diff --git a/.gitignore b/.gitignore index 2b880085b..606e522a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team +# SPDX-FileCopyrightText: (C) 2004-2022 Retroshare Team # SPDX-License-Identifier: CC0-1.0 *.o @@ -15,3 +15,23 @@ Thumbs.db *.pro.user .kdev4 *.kdev4 + +.qmake.stash + +!supportlibs/libsam3/Makefile + +# QtCreator cruft +*CMakeLists.txt.user* + +# Build artifacts +/jsonapi-generator/src/jsonapi-generator +/jsonapi-generator/src/jsonapi-generator-doxygen-final.conf +/jsonapi-generator/src/jsonapi-includes.inl +/jsonapi-generator/src/jsonapi-wrappers.inl +/jsonapi-generator/src/xml/ +/retroshare-friendserver/src/retroshare-friendserver +/retroshare-gui/src/include/ +/retroshare-gui/src/retroshare +/retroshare-gui/src/temp/ +/retroshare-service/src/retroshare-service +/*.tar.?z diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d620b3719..45fed1bb2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,32 +1,50 @@ -image: docker:stable +image: docker:latest services: - - docker:stable-dind + - docker:dind + +stages: + - build + - test workflow: rules: - if: $CI_MERGE_REQUEST_ID - if: $CI_COMMIT_BRANCH -build-and-test: +variables: + UBUNTU_TESTING_IMAGE_TAG: "$CI_REGISTRY_IMAGE/gitlabci_outputs/ubuntu_testing:$CI_COMMIT_SHA" + +build-ubuntu-test-image: + stage: build script: - - > - if [ -n "$CI_MERGE_REQUEST_ID" ]; then - REPO_ARGS="--build-arg REPO_URL=$CI_MERGE_REQUEST_SOURCE_PROJECT_URL" ; - REPO_ARGS="$REPO_ARGS --build-arg REPO_BRANCH=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" ; - else - REPO_ARGS="--build-arg REPO_URL=$CI_REPOSITORY_URL" ; - REPO_ARGS="$REPO_ARGS --build-arg REPO_BRANCH=$CI_COMMIT_BRANCH" ; - fi ; - export REPO_ARGS ; - echo REPO_ARGS=$REPO_ARGS ; + - docker --version + - > + docker login "$CI_REGISTRY" + --username "$CI_REGISTRY_USER" + --password "$CI_REGISTRY_PASSWORD" - mkdir Dockercontext - > - docker build -t retroshare:testing $REPO_ARGS + docker build + -t $UBUNTU_TESTING_IMAGE_TAG + $($CI_PROJECT_DIR/build_scripts/GitlabCI/getRepoArgs.sh) --file $CI_PROJECT_DIR/build_scripts/GitlabCI/gitlabCI.Dockerfile Dockercontext + - docker push $UBUNTU_TESTING_IMAGE_TAG + - echo UBUNTU_TESTING_IMAGE_TAG=$UBUNTU_TESTING_IMAGE_TAG + +test-ubuntu: + stage: test + script: + - docker --version + - > + docker login "$CI_REGISTRY" + --username "$CI_REGISTRY_USER" + --password "$CI_REGISTRY_PASSWORD" + - echo UBUNTU_TESTING_IMAGE_TAG=$UBUNTU_TESTING_IMAGE_TAG + - docker pull $UBUNTU_TESTING_IMAGE_TAG - > - docker run --name retroshare --detach --tty retroshare:testing + docker run --name retroshare --detach --tty $UBUNTU_TESTING_IMAGE_TAG retroshare-service --jsonApiPort 9092 - apk add jq - > diff --git a/.gitmodules b/.gitmodules index c35876fc6..273336f84 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,7 +10,34 @@ [submodule "supportlibs/udp-discovery-cpp"] path = supportlibs/udp-discovery-cpp url = https://github.com/truvorskameikin/udp-discovery-cpp.git - branch = develop + branch = master +# develop branch was removed we were using it at commit f3a3103a6c52e5707629e8d0a7e279a7758fe845 [submodule "supportlibs/rapidjson"] path = supportlibs/rapidjson url = https://github.com/Tencent/rapidjson.git +[submodule "supportlibs/libsam3"] + path = supportlibs/libsam3 + url = https://github.com/i2p/libsam3.git +[submodule "supportlibs/jni.hpp"] + path = supportlibs/jni.hpp + url = https://github.com/RetroShare/jni.hpp.git +[submodule "openpgpsdk"] + path = openpgpsdk + url = ../OpenPGP-SDK + branch = master +[submodule "libbitdht"] + path = libbitdht + url = ../BitDHT + branch = master +[submodule "libretroshare"] + path = libretroshare + url = https://github.com/RetroShare/libretroshare.git + branch = master +[submodule "retroshare-webui"] + path = retroshare-webui + url = https://github.com/RetroShare/RSNewWebUI.git + branch = master +[submodule "supportlibs/librnp"] + path = supportlibs/librnp + url = https://github.com/rnpgp/rnp.git + branch = main diff --git a/.travis.yml b/.travis.yml index cfe2eac21..ef38661ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,12 +8,12 @@ language: cpp matrix: include: - - os: linux - dist: bionic - sudo: required - compiler: gcc +# - os: linux +# dist: bionic +# sudo: required +# compiler: gcc - os: osx - osx_image: xcode10.1 + osx_image: xcode10.2 compiler: clang sudo: false @@ -68,11 +68,11 @@ before_script: fi script: - - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make -j4; fi + - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then travis_wait 30 make -j$(nproc); fi after_success: - if [ $TRAVIS_OS_NAME == osx ]; then build_scripts/OSX/travis_makeOSXPackage.sh ; fi - - if [ $TRAVIS_OS_NAME == linux ] && [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make -j2; fi +# - if [ $TRAVIS_OS_NAME == linux ] && [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make -j2; fi # branches: diff --git a/README.asciidoc b/README.asciidoc index 734c3d083..6e5c52ce9 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -7,13 +7,27 @@ RetroShare is a decentralized, private, secure, cross-platform, communication toolkit. RetroShare provides file sharing, chat, messages, forums, channels and more. +|=============================================================================== +| Developer Documentation | image:https://deepwiki.com/badge.svg[link="https://deepwiki.com/RetroShare/RetroShare",title="Ask DeepWiki"] +|=============================================================================== .Build Status |=============================================================================== |GNU/Linux (via Gitlab CI) | image:https://gitlab.com/RetroShare/RetroShare/badges/master/pipeline.svg[link="https://gitlab.com/RetroShare/RetroShare/-/commits/master",title="pipeline status"] -|GNU/Linux, macOS, (via Travis CI) | image:https://travis-ci.org/RetroShare/RetroShare.svg?branch=master[link="https://travis-ci.org/RetroShare/RetroShare"] |Windows (via AppVeyor) | image:https://ci.appveyor.com/api/projects/status/github/RetroShare/RetroShare?svg=true[link="https://ci.appveyor.com/project/RetroShare58622/retroshare"] +|macOS, (via Travis CI) | image:https://app.travis-ci.com/RetroShare/RetroShare.svg?branch=master[link="https://app.travis-ci.com/github/RetroShare/RetroShare"] +|libretroshare GNU/Linux, Android (via Gitlab CI) | image:https://gitlab.com/RetroShare/libretroshare/badges/master/pipeline.svg[link="https://gitlab.com/RetroShare/libretroshare/-/commits/master",title="pipeline status"] |=============================================================================== +== Get the source + +Clone this repository, enter the directory and then get the submodules with the +following command + +[source,bash] +-------- +git submodule update --init --remote --force libbitdht/ libretroshare/ openpgpsdk/ +-------- + == Compilation diff --git a/RetroShare.pro b/RetroShare.pro index dc590dd17..4972fe2ab 100644 --- a/RetroShare.pro +++ b/RetroShare.pro @@ -25,9 +25,6 @@ CONFIG += c++14 TEMPLATE = subdirs -SUBDIRS += openpgpsdk -openpgpsdk.file = openpgpsdk/src/openpgpsdk.pro - rs_jsonapi:isEmpty(JSONAPI_GENERATOR_EXE) { SUBDIRS += jsonapi-generator jsonapi-generator.file = jsonapi-generator/src/jsonapi-generator.pro @@ -36,7 +33,7 @@ rs_jsonapi:isEmpty(JSONAPI_GENERATOR_EXE) { SUBDIRS += libbitdht libbitdht.file = libbitdht/src/libbitdht.pro -libretroshare.depends += openpgpsdk libbitdht +libretroshare.depends += libbitdht SUBDIRS += libretroshare libretroshare.file = libretroshare/src/libretroshare.pro @@ -55,6 +52,12 @@ retroshare_service { retroshare_service.target = retroshare_service } +retroshare_friendserver { + SUBDIRS += retroshare_friendserver + retroshare_friendserver.file = retroshare-friendserver/src/retroshare-friendserver.pro + retroshare_friendserver.depends = libretroshare + retroshare_friendserver.target = retroshare_friendserver +} retroshare_plugins { SUBDIRS += plugins plugins.file = plugins/plugins.pro @@ -62,6 +65,13 @@ retroshare_plugins { plugins.target = plugins } +rs_webui { + SUBDIRS += retroshare-webui + retroshare-webui.file = retroshare-webui/webui.pro + retroshare-webui.target = rs_webui + retroshare-webui.depends = retroshare_gui +} + wikipoos { SUBDIRS += pegmarkdown pegmarkdown.file = supportlibs/pegmarkdown/pegmarkdown.pro diff --git a/appveyor.yml b/appveyor.yml index cd706d02c..5bc004fa1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -258,10 +258,10 @@ after_build: # artifacts configuration # #---------------------------------# -#artifacts: -# - path: '**\*.exe' -# - path: filelist.txt -# - path: $(RS_DEPLOY) +artifacts: + - path: '**\*.exe' + - path: filelist.txt + - path: $(RS_DEPLOY) # # # pushing a single file diff --git a/build_scripts/Android/README.asciidoc b/build_scripts/Android/README.asciidoc deleted file mode 100644 index 3f978cfd1..000000000 --- a/build_scripts/Android/README.asciidoc +++ /dev/null @@ -1,399 +0,0 @@ -= RetroShare development on Android - -// SPDX-FileCopyrightText: RetroShare Team -// SPDX-License-Identifier: CC-BY-SA-4.0 - - -Compiling an application for Android is not as easy as one would imagine, -expecially one like RetroShare that has a big codebase and is not well -documented. This document is aimed to empower the reader so she can hopefully -succed or at least have a significant help in compiling her own RetroShare APK -installable on Android. - - -== Preparing The Environement - -First of all setup your Qt for Android development environement following the -guide on the link:http://doc.qt.io/qt-5/androidgs.html[Qt for android web site]. -At this point you should have Android SDK, Android NDK, and Qt for Android -working fine, and you should be capable of executing on an Android emulator or -on your Android phone Qt for Android examples. - -But RetroShare is not as simple to compile as those examples. The good news is -that Android NDK ships all the necessary to build a custom toolchain that is -suitable to build RetroShare. -In order to build the toolchain with needed libraries RetroShare provides the -+android-prepare-toolchain.sh+ script; before you execute it you should define -some variables the script cannot determine in an easy and reliable manner by -itself in your terminal. - -[source,bash] -------------------------------------------------------------------------------- -## The path where Android NDK is installed in your system -export ANDROID_NDK_PATH="/opt/android-ndk/" - -## The path where your fresh compiled toolchain will be installed, make sure -## the parent exists -export NATIVE_LIBS_TOOLCHAIN_PATH="${HOME}/Builds/android-toolchains/retroshare-android/" - -## The CPU architecture of the Android device you want to target -export ANDROID_NDK_ARCH="arm" - -## The Android API level the Android device you want to target -export ANDROID_PLATFORM_VER="16" - -## The number of core that yout host CPU have (just to speed up compilation) set -## it to 1 if unsure -export HOST_NUM_CPU=1 - -./android-prepare-toolchain.sh -------------------------------------------------------------------------------- - - -== Preparing Qt Creator - -Now that your environement is set up you should configure Qt Creator for Android -following the -link:http://doc.qt.io/qtcreator/creator-developing-android.html[official guide]. -At the end of this step your Qt Creator should recognize the Android compiler -and the Qt for Android kit. - -Your Kit is now ready to use. Now you can open RetroShare as a Qt Creator -project and in the Projects left menu add the newly created kit if not already -present, so you can select it on the build type selection button down on the -left. - -Now you need to set properly a few options like `JSONAPI_GENERATOR_EXE` and -disable some of RetroShare modules like `retroshare-gui` that are not available -on Android so you will have to go to - -_Qt Creator left pane -> Projects -> Build and Run -> Android SOMESTUFF kit -> -Build Steps -> qmake -> Additional arguments_ + - -and add the following configurations (change `Your_Path` according to your -deployment) - -[source,makefile] -------------------------------------------------------------------------------- -CONFIG+=retroshare_service CONFIG+=rs_jsonapi CONFIG+=rs_deep_search -RS_UPNP_LIB=miniupnpc -JSONAPI_GENERATOR_EXE=Your_Path/jsonapi-generator/src/jsonapi-generator -NATIVE_LIBS_TOOLCHAIN_PATH=Your_Path/retroshare-android-16-arm/ -CONFIG+=no_retroshare_gui CONFIG+=no_rs_service_webui_terminal_password -CONFIG+=no_rs_service_terminal_login -------------------------------------------------------------------------------- - -TIP: Some versions of QtCreator try to find the Android SDK in -`/opt/android/sdk`. A workaround to this is to make a symbolic link there -pointing to your SDK installation path, like -+mkdir -p /opt/android/sdk && ln -s /home/user/android-sdk-linux -/opt/android/sdk+ - - -== Quircks - -=== Protected Apps - -On some Android devices like +Huawei ALE-L21+ background applications are -killed when screen is turned off unless they are in the _protected app_ list. -At moment seems apps developers don't have a way to have the application -_protected_ by default, unless the phone vendor decide the app is _popular_ so -the user have to enable _protection_ for RetroShare manually on those mobile -phones. + - -{empty} + -To enable enable _protection_: +Android menu -> Settings -> Privacy & security --> Protected apps -> RetroShare+ + -{empty} + - -Other devices may offer similar _features_ please report them. - - -=== APK signature mismatch - -If you try to install a RetroShare APK that comes from a different source -(eg: if you try to upgrade from F-Droid when you originally installed an APK -build by yourself) Android will prevent that from happening. In that case the -only solution is to uninstall the app and then install the new APK but if you do -it also the application data and your precious cryptographic keys, friend list -etc. will be lost forever. -To avoid that you can attempt to manually backup and then restore from the -command-line (`adb backup` seems not working either) to change the app source -without erasing the appliation data. - -CAUTION: Following steps require root access on your Android device - -.Backup RetroShare Android application data -[source,bash] --------------------------------------------------------------------------------- -export ORIG_DIR="/data/data/org.retroshare.android.qml_app" -export BACKUP_DIR="org.retroshare.android.qml_app.backup" - -adb root - -adb shell am force-stop org.retroshare.android.qml_app -sleep 1s - -mkdir ${BACKUP_DIR} - -# Avoid adb pull failing -adb shell rm ${ORIG_DIR}/files/.retroshare/libresapi.sock -adb pull ${ORIG_DIR}/files/ ${BACKUP_DIR}/files/ --------------------------------------------------------------------------------- - -After this you should be able to uninstall the old APK with your preferred -method, as example from the command-line. - -.Uninstall RetroShare Android from the command-line -[source,bash] --------------------------------------------------------------------------------- -adb uninstall org.retroshare.android.qml_app --------------------------------------------------------------------------------- - -Now you can install a different signature APK and then restore the application -data with the following commands. - -[source,bash] --------------------------------------------------------------------------------- -export ORIG_DIR="/data/data/org.retroshare.android.qml_app" -export BACKUP_DIR="org.retroshare.android.qml_app.backup" - -adb root - -## Launch the app to make sure the parent directory exists and has proper owner -adb shell monkey -p org.retroshare.android.qml_app -c android.intent.category.LAUNCHER 1 -sleep 1s - -adb shell am force-stop org.retroshare.android.qml_app -sleep 1s - - -APP_OWNER="$(adb shell busybox ls -lnd ${ORIG_DIR} | awk '{print $3":"$4}')" -adb shell rm -rf ${ORIG_DIR}/files -adb push ${BACKUP_DIR}/files/ ${ORIG_DIR}/files/ -adb shell busybox chown -R ${APP_OWNER} ${ORIG_DIR}/files/ --------------------------------------------------------------------------------- - -Opening RetroShare android app now should show your old profile. - - -== Debugging with GDB - -If building RetroShare Android package seems tricky, setting up a functional -debugging environement for it feels like black magic. This section is meant to -help you doing it with less headache and hopefully in a reproducible way. - -Unfortunately at the time of the last update to this guide, Qt build system -strips debugging symbols from the package and from the buildroot also if you -compile with debugging enabled. Fiddling with `qmake` configurations and -variables like `CONFIG+=debug`, `CONFIG+=force_debug_info` or `QMAKE_STRIP` -either as commandline arguments or inside retroshare `.pro` and `.pri` files is -uneffective. IMHO Qt should handle this on itself so it is probably worth -reporting a bug to them. So to workaround this problem you need to fiddle a bit -with the Android NDK. In my case I always keep +Debug+ or +Release+ suffix in -my build directory name depending on what kind of build it is, so I use this -information and modify `llvm-strip` in a way that it will strip only if stripped -file path doesn't contain +Debug+. - -.Modify llvm-strip inside Android NDK --------------------------------------------------------------------------------- -## Set ANDROID_NDK_PATH to your Android NDK installation path -export ANDROID_NDK_PATH="/opt/android-ndk/" - -## Define a convenience variable with llvm-strip path -export ANDROID_NDK_LLVM_STRIP="${ANDROID_NDK_PATH}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip" - -## If not existing yer create a backup of the original llvm-strip -[ -f "${ANDROID_NDK_LLVM_STRIP}.back" ] || - cp "${ANDROID_NDK_LLVM_STRIP}" "${ANDROID_NDK_LLVM_STRIP}.back" - -## Create a new llvm-strip that does nothing if the argument path contains Debug -cat > "${ANDROID_NDK_LLVM_STRIP}" << LLVMSTRIPTRICK -#!/bin/bash - -echo "\${2}" | grep -q Debug || - "${ANDROID_NDK_LLVM_STRIP}.back" --strip-all "\${2}" - -LLVMSTRIPTRICK - -## Eventually you can revert back simply by running -# `mv "${ANDROID_NDK_LLVM_STRIP}.back" "${ANDROID_NDK_LLVM_STRIP}"` --------------------------------------------------------------------------------- - - -To attach to the `retroshare-service` running on Android you need also to pull a -debugging sysroot out of your device first, RetroShare sources provides an -helper script to do that. - -.Prepare debugging sysroot with helper script -[source,bash] --------------------------------------------------------------------------------- -## Set RetroShare source path -export RS_SOURCE_DIR="${HOME}/Development/rs-develop" - -## Optionally set your device ID first available will be used, you can run -## `adb devices` to list available devices. -#export ANDROID_SERIAL="YT013PSPGK" - -## Optionally set a path where to save the debugging sysroot otherwise default -## is used. -#export DEBUG_SYSROOT="${HOME}/Builds/debug_sysroot/${ANDROID_SERIAL}/" - -## Run the helper script -${RS_SOURCE_DIR}/build_scripts/Android/pull_sysroot.sh --------------------------------------------------------------------------------- - -.Prepare Android NDK GDB configurations -[source,bash] --------------------------------------------------------------------------------- -## Optionally set Qt version variable consistently with your installation -export QT_VERSION="5.12.7" - -## Optionally set Qt architecture variable consistently with Android device -export QT_ARCH="arm64_v8a" - -## Optionally set Qt path variable consistently with your installation -export QT_DIR="/opt/Qt-${QT_VERSION}/${QT_VERSION}/" - -## Optionally set RetroShare buildroot path -export RS_BUILD_DIR="${HOME}/Builds/RetroShare-Android_for_${QT_ARCH}_Clang_Qt_${QT_VERSION//./_}_android_${QT_ARCH}-Debug/" - -## Optionally set gdb config file path -export GDB_CONFIGS_FILE="${HOME}/Builds/gdb_configs_${QT_ARCH}" - -## Generate Android NDK GDB configuration -${RS_SOURCE_DIR}/build_scripts/Android/generate_gdb_init_commands.sh --------------------------------------------------------------------------------- - - -You will need to run the following steps everytime you want to debug -`retroshare-service` on Android. - -Make sure `retroshare-service` is running on your connected Android device. - -.Run GDB server on your Android device from your host console -[source,bash] --------------------------------------------------------------------------------- -${RS_SOURCE_DIR}/build_scripts/Android/start_gdbserver.sh --------------------------------------------------------------------------------- - - -.Run Android NDK GDB on your workstation and attach -[source,bash] --------------------------------------------------------------------------------- -## Start NDK gdb -${ANDROID_NDK_PATH}/prebuilt/linux-x86_64/bin/gdb - -## Instruct GDB how and where to find debugging symbols -(gdb) source $GDB_CONFIGS_FILE - -## Connect to the gdbserver running on the phone -(gdb) target remote 127.0.01:5039 - -## Have fun debugging -(gdb) --------------------------------------------------------------------------------- - - -== Debugging with Qt Creator - -WARNING: As of the last update to this guide, debugging retroshare-service -running on Android via Qt creator doesn't wrok even with all the trickery -explained in this section, you better learn how to debug with GDB reading -carefully previous section. - -Qt Creator actually support debugging only for the foreground activity, so to -debug what's happening in the core extra trickery is needed. - -- Run the App in Debug mode from QtCreator "Start Debugging" button -- Enable QtCreator debugger console view Menu->Window->Debugger Log -- Run +show solib-search-path+ in the QtCreator GDB console -- Take note of the output you get in the right pane of the console -- Thanks https://stackoverflow.com/a/31164313 for the idea - -TIP: QtCreator GDB console seems a bit buggy and easly trigger timeout -message when a command is run, in that case attempt to run the command while the -debugging is paused or at breakpoint, or with other similar tricks. - -CAUTION: Following steps require root access on your Android device - -Now on your phone yuo need to authorize root access to applications, then once -you plug your sacrifical Android phone run this commands - -.Run gdbserver as root on Android phone -[source,bash] --------------------------------------------------------------------------------- -## Open a shell from your workstation on the connected Android phone -adb shell - -## take the note of the phone IP address -ip address show - -## Gain root permissions on the shell -su - -## Attach with gdbserver and listen on one TCP port -gdbserver :4567 --attach $(pgrep org.retroshare.android.qml_app:rs) --------------------------------------------------------------------------------- - - -.Prepare and run Android NDK GDB on your workstation -[source,bash] --------------------------------------------------------------------------------- -## Setup some convenience variables -NDK_GDB="${ANDROID_NDK_PATH}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdb" -RS_BUILD_PATH="${HOME}/Builds/RetroShare-Android_for_armeabi_v7a_GCC_4_9_Qt_5_9_2_android_armv7-Debug/" - -## Start Android NDK GDB of your phone architecture passing the executable -$NDK_GDB $RS_BUILD_PATH/retroshare-android-service/src/libretroshare-android-service.so - -## Instruct GDB how and where to find debugging symbols -(gdb) set auto-solib-add on -(gdb) set solib-search-path THE:BIG:LIST:OF:DIRECTORIES:YOU:TAKE:NOTE:BEFORE - -## Connect to the gdbserver running on the phone -(gdb) target remote $PHONE_IP:4567 - -## Have fun debugging -(gdb) --------------------------------------------------------------------------------- - -TIP: Some time WiFi power saving on Android mess with the GDB connection, -to prevent that from appening open another +adb shell+ and live +ping+ toward -your work-station running - -== Embedding into other Android packages - -As showed by https://elrepo.io/[elRepo.io] developers it is possible and quite -easy to embed `retroshare-service` into other Android packages see description - -https://gitlab.com/elRepo.io/elRepo.io-android/-/blob/master/README.adoc - -And implementation details - -https://gitlab.com/elRepo.io/elRepo.io-android/-/blob/master/android/app/build.gradle - - -== Furter Readings - -- link:http://doc.qt.io/qt-5/android-support.html[] -- link:https://developer.android.com/ndk/guides/libs.html[] -- link:retroshare://forum?name=Compiling%20nogui%20for%20android&id=8fd22bd8f99754461e7ba1ca8a727995&msgid=4e0f92330600bba9cf978f384f4b7b2f2ca64eff[] -- link:retroshare://file?name=Android%20Native%20Development%20Kit%20Cookbook.pdf&size=29214468&hash=0123361c1b14366ce36118e82b90faf7c7b1b136[] -- link:https://groups.google.com/forum/#!topic/android-developers/srATPaL0aRU[] -- link:https://stackoverflow.com/questions/31638986/protected-apps-setting-on-huawei-phones-and-how-to-handle-it[] -- link:https://tthtlc.wordpress.com/2012/09/19/how-to-do-remote-debugging-via-gdbserver-running-inside-the-android-phone/[] -- link:https://source.android.com/devices/tech/debug/[] -- link:https://source.android.com/devices/tech/debug/gdb[] -- link:https://fw4spl-org.github.io/fw4spl-blog/2015/07/27/Native-debugging-on-Android-with-QtCreator.html[] -- link:https://fragglet.livejournal.com/19646.html[] -- link:https://github.com/android-ndk/ndk/issues/773[How to build without using standalone toolchain?] - -== License - -Copyright (C) 2016-2020 Gioacchino Mazzurco + -Copyright (C) 2020 Asociación Civil Altermundi + - -This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License. - -image::https://i.creativecommons.org/l/by-sa/4.0/88x31.png[Creative Commons License, link=http://creativecommons.org/licenses/by-sa/4.0/] diff --git a/build_scripts/Android/generate_gdb_init_commands.sh b/build_scripts/Android/generate_gdb_init_commands.sh deleted file mode 100755 index 3a9883950..000000000 --- a/build_scripts/Android/generate_gdb_init_commands.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash - -# Script to prepare Android NDK GDB configurations to debug retroshare-service -# -# Copyright (C) 2020 Gioacchino Mazzurco -# Copyright (C) 2020 Asociación Civil Altermundi -# -# 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, version 3. -# -# 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 - - -## Define default value for variable, take two arguments, $1 variable name, -## $2 default variable value, if the variable is not already define define it -## with default value. -function define_default_value() -{ - VAR_NAME="${1}" - DEFAULT_VALUE="${2}" - - [ -z "${!VAR_NAME}" ] && export ${VAR_NAME}="${DEFAULT_VALUE}" -} - -define_default_value QT_VERSION "5.12.4" -define_default_value QT_ARCH "arm64_v8a" -define_default_value QT_DIR "/opt/Qt-${QT_VERSION}/${QT_VERSION}/" -define_default_value ANDROID_SERIAL "$(adb devices | head -n 2 | tail -n 1 | awk '{print $1}')" -define_default_value RS_BUILD_DIR "${HOME}/Builds/RetroShare-Android_for_${QT_ARCH}_Clang_Qt_${QT_VERSION//./_}_android_${QT_ARCH}-Debug/" -define_default_value RS_SOURCE_DIR "${HOME}/Development/rs-develop/" -define_default_value DEBUG_SYSROOT "${HOME}/Builds/debug_sysroot/${ANDROID_SERIAL}/" -define_default_value GDB_CONFIGS_FILE "${HOME}/Builds/gdb_configs_${QT_ARCH}" - -scanDir() -{ - find "$1" -type d -not -path '*/\.git/*' | tr '\n' ':' >> $GDB_CONFIGS_FILE -} - -putSeparator() -{ - echo >> $GDB_CONFIGS_FILE - echo >> $GDB_CONFIGS_FILE -} - -echo "set sysroot ${DEBUG_SYSROOT}" > $GDB_CONFIGS_FILE -putSeparator - -echo "set auto-solib-add on" >> $GDB_CONFIGS_FILE -echo -n "set solib-search-path " >> $GDB_CONFIGS_FILE -scanDir "${RS_BUILD_DIR}" -scanDir "${DEBUG_SYSROOT}" -scanDir "${QT_DIR}/android_${QT_ARCH}/lib/" -scanDir "${QT_DIR}/android_${QT_ARCH}/plugins/" -scanDir "${QT_DIR}/android_${QT_ARCH}/qml/" -putSeparator - -echo -n "directory " >> $GDB_CONFIGS_FILE -scanDir ${RS_SOURCE_DIR}/jsonapi-generator/src -scanDir ${RS_SOURCE_DIR}/libbitdht/src -scanDir ${RS_SOURCE_DIR}/openpgpsdk/src -scanDir ${RS_SOURCE_DIR}/libretroshare/src -scanDir ${RS_SOURCE_DIR}/retroshare-service/src -scanDir ${RS_SOURCE_DIR}/supportlibs/rapidjson/include/ -scanDir ${RS_SOURCE_DIR}/supportlibs/restbed/source/ -scanDir ${RS_SOURCE_DIR}/supportlibs/udp-discovery-cpp/ -scanDir ${RS_SOURCE_DIR}/supportlibs/restbed/dependency/asio/asio/include/ -scanDir ${RS_SOURCE_DIR}/supportlibs/restbed/dependency/catch/include/ -putSeparator - -## see https://stackoverflow.com/questions/28972367/gdb-backtrace-without-stopping -echo "catch signal SIGSEGV" >> $GDB_CONFIGS_FILE -echo "commands - bt - continue - end" >> $GDB_CONFIGS_FILE -putSeparator - -echo GDB_CONFIGS_FILE=$GDB_CONFIGS_FILE diff --git a/build_scripts/Android/prepare-toolchain-clang.sh b/build_scripts/Android/prepare-toolchain-clang.sh deleted file mode 100755 index 83c30721b..000000000 --- a/build_scripts/Android/prepare-toolchain-clang.sh +++ /dev/null @@ -1,549 +0,0 @@ -#!/bin/bash - -# Script to prepare RetroShare Android package building toolchain -# -# Copyright (C) 2016-2020 Gioacchino Mazzurco -# -# 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, version 3. -# -# 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 -# -# SPDX-FileCopyrightText: Retroshare Team -# SPDX-License-Identifier: AGPL-3.0-only - - -## Define default value for variable, take two arguments, $1 variable name, -## $2 default variable value, if the variable is not already define define it -## with default value. -function define_default_value() -{ - VAR_NAME="${1}" - DEFAULT_VALUE="${2}" - - [ -z "${!VAR_NAME}" ] && export ${VAR_NAME}="${DEFAULT_VALUE}" || true -} - -## You are supposed to provide the following variables according to your system setup -define_default_value ANDROID_NDK_PATH "/opt/android-ndk/" -define_default_value ANDROID_NDK_ARCH "arm" -define_default_value ANDROID_PLATFORM_VER "16" -define_default_value NATIVE_LIBS_TOOLCHAIN_PATH "${HOME}/Builds/android-toolchains/retroshare-android-${ANDROID_PLATFORM_VER}-${ANDROID_NDK_ARCH}/" -define_default_value HOST_NUM_CPU $(nproc) - -define_default_value BZIP2_SOURCE_VERSION "1.0.6" -define_default_value BZIP2_SOURCE_SHA256 a2848f34fcd5d6cf47def00461fcb528a0484d8edef8208d6d2e2909dc61d9cd - -define_default_value OPENSSL_SOURCE_VERSION "1.1.1c" -define_default_value OPENSSL_SOURCE_SHA256 f6fb3079ad15076154eda9413fed42877d668e7069d9b87396d0804fdb3f4c90 - -define_default_value SQLITE_SOURCE_YEAR "2018" -define_default_value SQLITE_SOURCE_VERSION "3250200" -define_default_value SQLITE_SOURCE_SHA256 da9a1484423d524d3ac793af518cdf870c8255d209e369bd6a193e9f9d0e3181 - -define_default_value SQLCIPHER_SOURCE_VERSION "4.2.0" -define_default_value SQLCIPHER_SOURCE_SHA256 105c1b813f848da038c03647a8bfc9d42fb46865e6aaf4edfd46ff3b18cdccfc - -define_default_value LIBUPNP_SOURCE_VERSION "1.8.4" -define_default_value LIBUPNP_SOURCE_SHA256 976c3e4555604cdd8391ed2f359c08c9dead3b6bf131c24ce78e64d6669af2ed - -define_default_value INSTALL_QT_ANDROID "false" -define_default_value QT_VERSION "5.12.0" -define_default_value QT_ANDROID_INSTALLER_SHA256 a214084e2295c9a9f8727e8a0131c37255bf724bfc69e80f7012ba3abeb1f763 - -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_VERSION "develop" - -define_default_value XAPIAN_SOURCE_VERSION "1.4.7" -define_default_value XAPIAN_SOURCE_SHA256 13f08a0b649c7afa804fa0e85678d693fd6069dd394c9b9e7d41973d74a3b5d3 - -define_default_value RAPIDJSON_SOURCE_VERSION "1.1.0" -define_default_value RAPIDJSON_SOURCE_SHA256 bf7ced29704a1e696fbccf2a2b4ea068e7774fa37f6d7dd4039d0787f8bed98e - -define_default_value MINIUPNPC_SOURCE_VERSION "2.1.20190625" -define_default_value MINIUPNPC_SOURCE_SHA256 8723f5d7fd7970de23635547700878cd29a5c2bb708b5e5475b2d1d2510317fb - - -## $1 filename, $2 sha256 hash -function check_sha256() -{ - echo ${2} "${1}" | sha256sum -c &> /dev/null -} - -## $1 filename, $2 sha256 hash, $3 url -function verified_download() -{ - FILENAME="$1" - SHA256="$2" - URL="$3" - - check_sha256 "${FILENAME}" "${SHA256}" || - { - rm -rf "${FILENAME}" - - wget -O "${FILENAME}" "$URL" || - { - echo "Failed downloading ${FILENAME} from $URL" - exit 1 - } - - check_sha256 "${FILENAME}" "${SHA256}" || - { - echo "SHA256 mismatch for ${FILENAME} from ${URL} expected sha256 ${SHA256} got $(sha256sum ${FILENAME} | awk '{print $1}')" - exit 1 - } - } -} - -cArch="" -eABI="" - -case "${ANDROID_NDK_ARCH}" in -"arm") - cArch="${ANDROID_NDK_ARCH}" - eABI="eabi" - ;; -"arm64") - cArch="aarch64" - eABI="" - ;; -"x86") - cArch="i686" - eABI="" - ;; -esac - -export SYSROOT="${NATIVE_LIBS_TOOLCHAIN_PATH}/sysroot/" -export PREFIX="${SYSROOT}/usr/" -export CC="${NATIVE_LIBS_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-clang" -export CXX="${NATIVE_LIBS_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-clang++" -export AR="${NATIVE_LIBS_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-ar" -export RANLIB="${NATIVE_LIBS_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-ranlib" - - -## More information available at https://android.googlesource.com/platform/ndk/+/ics-mr0/docs/STANDALONE-TOOLCHAIN.html -build_toolchain() -{ - echo "build_toolchain() -################################################################################ -################################################################################ -################################################################################ -" - - rm -rf ${NATIVE_LIBS_TOOLCHAIN_PATH} - ${ANDROID_NDK_PATH}/build/tools/make_standalone_toolchain.py --verbose \ - --arch ${ANDROID_NDK_ARCH} --install-dir ${NATIVE_LIBS_TOOLCHAIN_PATH} \ - --api ${ANDROID_PLATFORM_VER} - find "${PREFIX}/include/" -not -type d > "${NATIVE_LIBS_TOOLCHAIN_PATH}/deletefiles" -} - -## This avoid include errors due to -isystem and -I ordering issue -delete_copied_includes() -{ - echo "delete_copied_includes() -################################################################################ -################################################################################ -################################################################################ -" - cat "${NATIVE_LIBS_TOOLCHAIN_PATH}/deletefiles" | while read delFile ; do - rm "$delFile" - done -} - -## More information available at https://gitlab.com/relan/provisioners/merge_requests/1 and http://stackoverflow.com/a/34032216 -install_qt_android() -{ - echo "install_qt_android() -################################################################################ -################################################################################ -################################################################################ -" - - QT_VERSION_CODE=$(echo $QT_VERSION | tr -d .) - QT_INSTALL_PATH=${NATIVE_LIBS_TOOLCHAIN_PATH}/Qt - QT_INSTALLER="qt-unified-linux-x64-3.0.2-online.run" - - verified_download $QT_INSTALLER $QT_ANDROID_INSTALLER_SHA256 \ - http://master.qt.io/archive/online_installers/3.0/${QT_INSTALLER} - - chmod a+x ${QT_INSTALLER} - - QT_INSTALLER_SCRIPT="qt_installer_script.js" - cat << EOF > "${QT_INSTALLER_SCRIPT}" -function Controller() { - installer.autoRejectMessageBoxes(); - installer.installationFinished.connect(function() { - gui.clickButton(buttons.NextButton); - }); - - var welcomePage = gui.pageWidgetByObjectName("WelcomePage"); - welcomePage.completeChanged.connect(function() { - if (gui.currentPageWidget().objectName == welcomePage.objectName) - gui.clickButton(buttons.NextButton); - }); -} - -Controller.prototype.WelcomePageCallback = function() { - gui.clickButton(buttons.NextButton); -} - -Controller.prototype.CredentialsPageCallback = function() { - gui.clickButton(buttons.NextButton); -} - -Controller.prototype.IntroductionPageCallback = function() { - gui.clickButton(buttons.NextButton); -} - -Controller.prototype.TargetDirectoryPageCallback = function() { - gui.currentPageWidget().TargetDirectoryLineEdit.setText("$QT_INSTALL_PATH"); - gui.clickButton(buttons.NextButton); -} - -Controller.prototype.ComponentSelectionPageCallback = function() { - var widget = gui.currentPageWidget(); - - // You can get these component names by running the installer with the - // --verbose flag. It will then print out a resource tree. - - widget.deselectComponent("qt.tools.qtcreator"); - widget.deselectComponent("qt.tools.doc"); - widget.deselectComponent("qt.tools.examples"); - - widget.selectComponent("qt.$QT_VERSION_CODE.android_armv7"); - - gui.clickButton(buttons.NextButton); -} - -Controller.prototype.LicenseAgreementPageCallback = function() { - gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true); - gui.clickButton(buttons.NextButton); -} - -Controller.prototype.StartMenuDirectoryPageCallback = function() { - gui.clickButton(buttons.NextButton); -} - -Controller.prototype.ReadyForInstallationPageCallback = function() { - gui.clickButton(buttons.NextButton); -} - -Controller.prototype.FinishedPageCallback = function() { - var checkBoxForm = gui.currentPageWidget().LaunchQtCreatorCheckBoxForm; - if (checkBoxForm && checkBoxForm.launchQtCreatorCheckBox) - checkBoxForm.launchQtCreatorCheckBox.checked = false; - gui.clickButton(buttons.FinishButton); -} -EOF - -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 -build_bzlib() -{ - echo "build_bzlib() -################################################################################ -################################################################################ -################################################################################ -" - - B_dir="bzip2-${BZIP2_SOURCE_VERSION}" - rm -rf $B_dir - - verified_download $B_dir.tar.gz $BZIP2_SOURCE_SHA256 \ - http://distfiles.gentoo.org/distfiles/bzip2-${BZIP2_SOURCE_VERSION}.tar.gz - - tar -xf $B_dir.tar.gz - cd $B_dir - sed -i "/^CC=.*/d" Makefile - sed -i "/^AR=.*/d" Makefile - sed -i "/^RANLIB=.*/d" Makefile - sed -i "/^LDFLAGS=.*/d" Makefile - sed -i "s/^all: libbz2.a bzip2 bzip2recover test/all: libbz2.a bzip2 bzip2recover/" Makefile - make -j${HOST_NUM_CPU} - make install PREFIX=${PREFIX} -# sed -i "/^CC=.*/d" Makefile-libbz2_so -# make -f Makefile-libbz2_so -j${HOST_NUM_CPU} -# cp libbz2.so.1.0.6 ${SYSROOT}/usr/lib/libbz2.so - cd .. -} - -## More information available at http://doc.qt.io/qt-5/opensslsupport.html -build_openssl() -{ - echo "build_openssl() -################################################################################ -################################################################################ -################################################################################ -" - - B_dir="openssl-${OPENSSL_SOURCE_VERSION}" - rm -rf $B_dir - - verified_download $B_dir.tar.gz $OPENSSL_SOURCE_SHA256 \ - https://www.openssl.org/source/$B_dir.tar.gz - - tar -xf $B_dir.tar.gz - cd $B_dir -## We link openssl statically to avoid android silently sneaking in his own -## version of libssl.so (we noticed this because it had some missing symbol -## that made RS crash), the crash in some android version is only one of the -## possible problems the fact that android insert his own binary libssl.so pose -## non neglegible security concerns. - oBits="32" - [[ ${ANDROID_NDK_ARCH} =~ .*64.* ]] && oBits=64 - - ANDROID_NDK="${ANDROID_NDK_PATH}" PATH="${SYSROOT}/bin/:${PATH}" \ - ./Configure linux-generic${oBits} -fPIC --prefix="${PREFIX}" \ - --openssldir="${SYSROOT}/etc/ssl" -# sed -i 's/LIBNAME=$$i LIBVERSION=$(SHLIB_MAJOR).$(SHLIB_MINOR) \\/LIBNAME=$$i \\/g' Makefile -# sed -i '/LIBCOMPATVERSIONS=";$(SHLIB_VERSION_HISTORY)" \\/d' Makefile - make -j${HOST_NUM_CPU} - make install - rm -f ${PREFIX}/lib/libssl.so* - rm -f ${PREFIX}/lib/libcrypto.so* - cd .. -} - -build_sqlite() -{ - echo "build_sqlite() -################################################################################ -################################################################################ -################################################################################ -" - - B_dir="sqlite-autoconf-${SQLITE_SOURCE_VERSION}" - rm -rf $B_dir - - verified_download $B_dir.tar.gz $SQLITE_SOURCE_SHA256 \ - https://www.sqlite.org/${SQLITE_SOURCE_YEAR}/$B_dir.tar.gz - - tar -xf $B_dir.tar.gz - cd $B_dir - ./configure --with-pic --prefix="${PREFIX}" --host=${cArch}-linux - make -j${HOST_NUM_CPU} - make install - rm -f ${PREFIX}/lib/libsqlite3.so* -# ${CC} -shared -o libsqlite3.so -fPIC sqlite3.o -ldl -# cp libsqlite3.so "${SYSROOT}/usr/lib" - cd .. -} - -build_sqlcipher() -{ - echo "build_sqlcipher() -################################################################################ -################################################################################ -################################################################################ -" - - B_dir="sqlcipher-${SQLCIPHER_SOURCE_VERSION}" - rm -rf $B_dir - - T_file="${B_dir}.tar.gz" - - verified_download $T_file $SQLCIPHER_SOURCE_SHA256 \ - https://github.com/sqlcipher/sqlcipher/archive/v${SQLCIPHER_SOURCE_VERSION}.tar.gz - - tar -xf $T_file - cd $B_dir - case "${ANDROID_NDK_ARCH}" in - "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}" \ - --enable-tempstore=yes \ - --disable-tcl --disable-shared \ - CFLAGS="-DSQLITE_HAS_CODEC" LDFLAGS="${PREFIX}/lib/libcrypto.a" - make -j${HOST_NUM_CPU} - make install - cd .. -} - -build_libupnp() -{ - echo "build_libupnp() -################################################################################ -################################################################################ -################################################################################ -" - - B_dir="pupnp-release-${LIBUPNP_SOURCE_VERSION}" - B_ext=".tar.gz" - B_file="${B_dir}${B_ext}" - rm -rf $B_dir - - verified_download $B_file $LIBUPNP_SOURCE_SHA256 \ - https://github.com/mrjimenez/pupnp/archive/release-${LIBUPNP_SOURCE_VERSION}${B_ext} - - tar -xf $B_file - cd $B_dir - ./bootstrap -## liupnp must be configured as static library because if not the linker will -## 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 -## crash at startup. - ./configure --with-pic --enable-static --disable-shared --disable-samples \ - --disable-largefile \ - --prefix="${PREFIX}" --host=${cArch}-linux - make -j${HOST_NUM_CPU} - make install - cd .. -} - -build_rapidjson() -{ - echo "build_rapidjson() -################################################################################ -################################################################################ -################################################################################ -" - - B_dir="rapidjson-${RAPIDJSON_SOURCE_VERSION}" - D_file="${B_dir}.tar.gz" - verified_download $D_file $RAPIDJSON_SOURCE_SHA256 \ - https://github.com/Tencent/rapidjson/archive/v${RAPIDJSON_SOURCE_VERSION}.tar.gz - tar -xf $D_file - cp -r "${B_dir}/include/rapidjson/" "${PREFIX}/include/rapidjson" -} - -build_restbed() -{ - echo "build_restbed() -################################################################################ -################################################################################ -################################################################################ -" - - [ -d restbed ] || git clone --depth=2000 https://github.com/Corvusoft/restbed.git - cd restbed -# git fetch --tags -# git checkout tags/${RESTBED_SOURCE_VERSION} - git checkout ${RESTBED_SOURCE_VERSION} - git submodule update --init dependency/asio - git submodule update --init dependency/catch - git submodule update --init dependency/kashmir - cd .. - - rm -rf restbed-build; mkdir restbed-build ; cd restbed-build - cmake \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON BUILD_TESTS=OFF \ - -DBUILD_SSL=OFF -DCMAKE_INSTALL_PREFIX="${PREFIX}" -B. -H../restbed - make -j${HOST_NUM_CPU} - make install - cp "${PREFIX}/library/librestbed.a" "${PREFIX}/lib/" - cd .. -} - -build_udp-discovery-cpp() -{ - echo "build_udp-discovery-cpp() -################################################################################ -################################################################################ -################################################################################ -" - - S_dir="udp-discovery-cpp" - [ -d $S_dir ] || git clone $UDP_DISCOVERY_CPP_SOURCE $S_dir - cd $S_dir - git checkout $UDP_DISCOVERY_CPP_VERSION - cd .. - - B_dir="udp-discovery-cpp-build" - rm -rf ${B_dir}; mkdir ${B_dir}; cd ${B_dir} - cmake \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ - -DCMAKE_INSTALL_PREFIX="${PREFIX}" -B. -H../udp-discovery-cpp - make -j${HOST_NUM_CPU} - cp libudp-discovery.a "${PREFIX}/lib/" - cp ../$S_dir/*.hpp "${PREFIX}/include/" - cd .. -} - -build_xapian() -{ - echo "build_xapian() -################################################################################ -################################################################################ -################################################################################ -" - - B_dir="xapian-core-${XAPIAN_SOURCE_VERSION}" - D_file="$B_dir.tar.xz" - verified_download $D_file $XAPIAN_SOURCE_SHA256 \ - https://oligarchy.co.uk/xapian/${XAPIAN_SOURCE_VERSION}/$D_file - rm -rf $B_dir - tar -xf $D_file - cd $B_dir - B_endiannes_detection_failure_workaround="ac_cv_c_bigendian=no" - B_large_file="" - [ "${ANDROID_PLATFORM_VER}" -lt "24" ] && B_large_file="--disable-largefile" - ./configure ${B_endiannes_detection_failure_workaround} ${B_large_file} \ - --with-pic \ - --disable-backend-inmemory --disable-backend-remote \ - --disable--backend-chert --enable-backend-glass \ - --host=${cArch}-linux --enable-static --disable-shared \ - --prefix="${PREFIX}" --with-sysroot="${SYSROOT}" - make -j${HOST_NUM_CPU} - make install -} - -build_miniupnpc() -{ - echo "build_miniupnpc() -################################################################################ -################################################################################ -################################################################################ -" - S_dir="miniupnpc-${MINIUPNPC_SOURCE_VERSION}" - B_dir="miniupnpc-${MINIUPNPC_SOURCE_VERSION}-build" - D_file="$S_dir.tar.gz" - verified_download $D_file $MINIUPNPC_SOURCE_SHA256 \ - http://miniupnp.free.fr/files/${D_file} - rm -rf $S_dir $B_dir - tar -xf $D_file - mkdir $B_dir - cd $B_dir - cmake \ - -DUPNPC_BUILD_STATIC=TRUE \ - -DUPNPC_BUILD_SHARED=FALSE \ - -DUPNPC_BUILD_TESTS=FALSE \ - -DUPNPC_BUILD_SAMPLE=FALSE \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ - -DCMAKE_INSTALL_PREFIX="${PREFIX}" -B. -S../$S_dir - make -j${HOST_NUM_CPU} - make install -} - -build_toolchain -[ "${INSTALL_QT_ANDROID}X" != "trueX" ] || install_qt_android -build_bzlib -build_openssl -build_sqlite -build_sqlcipher -build_libupnp -build_rapidjson -build_restbed -build_udp-discovery-cpp -build_xapian -build_miniupnpc -delete_copied_includes - -echo NATIVE_LIBS_TOOLCHAIN_PATH=${NATIVE_LIBS_TOOLCHAIN_PATH} diff --git a/build_scripts/Android/pull_sysroot.sh b/build_scripts/Android/pull_sysroot.sh deleted file mode 100755 index d474610e4..000000000 --- a/build_scripts/Android/pull_sysroot.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/bash - -# Script to pull debugging sysroot from Android devices -# -# Copyright (C) 2020 Gioacchino Mazzurco -# Copyright (C) 2020 Asociación Civil Altermundi -# -# 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, version 3. -# -# 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 - -<<"ASCIIDOC" - -Pull files from Android device to prepare a debugging sysroot -Inspired by: -https://fw4spl-org.github.io/fw4spl-blog/2015/07/27/Native-debugging-on-Android-with-QtCreator.html - -The goal is to have a local copy of the sysroot of the connected device. -For that we use the command `adb pull ` - -We will get a copy of: - -- `/system/lib/` -- `/vendor/lib/` -- `libc.so` -- `libcutils.so` - -As well as the binaries `linker` and `app_process` - -IMPORTANT: -from one device to another, the remote file `app_process` can be a binary file -or a symlink to a binary file - which is NOT ok for us. -That's so we will try to pull every known possible variants of `app_process`, -e.g. `app_process32` or `app_process_init` - -ASCIIDOC - - -## Define default value for variable, take two arguments, $1 variable name, -## $2 default variable value, if the variable is not already define define it -## with default value. -function define_default_value() -{ - VAR_NAME="${1}" - DEFAULT_VALUE="${2}" - - [ -z "${!VAR_NAME}" ] && export ${VAR_NAME}="${DEFAULT_VALUE}" -} - -define_default_value ANDROID_SERIAL "$(adb devices | head -n 2 | tail -n 1 | awk '{print $1}')" -define_default_value DEBUG_SYSROOT "${HOME}/Builds/debug_sysroot/${ANDROID_SERIAL}/" - -rm -rf "${DEBUG_SYSROOT}" - -for mDir in "/system/lib/" "/vendor/lib/"; do - mkdir -p "${DEBUG_SYSROOT}/${mDir}" - # adb pull doesn't behave like rsync dirA/ dirB/ so avoid nesting the - # directory by deleting last one before copying - rmdir "${DEBUG_SYSROOT}/${mDir}" - adb pull "${mDir}" "${DEBUG_SYSROOT}/${mDir}" -done - -# Retrieve the specific binaries - some of these adb commands will fail, since -# some files may not exist, but that's ok. - -mkdir -p "${DEBUG_SYSROOT}/system/bin/" -for mBin in "/system/bin/linker" "/system/bin/app_process" \ - "/system/bin/app_process_init" "/system/bin/app_process32" \ - "/system/bin/app_process64" ; do - adb pull "${mBin}" "${DEBUG_SYSROOT}/${mBin}" -done - -# Verify which variants of the specific binaries could be pulled -echo -echo "Found the following specific binaries:" -echo -ls -1 "${DEBUG_SYSROOT}/system/bin/"* -ls -1 "${DEBUG_SYSROOT}/system/lib/libc.so"* -ls -1 "${DEBUG_SYSROOT}/system/lib/libcutils.so"* -echo - -echo DEBUG_SYSROOT="${DEBUG_SYSROOT}" diff --git a/build_scripts/Android/start_gdbserver.sh b/build_scripts/Android/start_gdbserver.sh deleted file mode 100755 index 1fd751e67..000000000 --- a/build_scripts/Android/start_gdbserver.sh +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/bash - -# Script to start gdbserver on Android device and attach to retroshare-service -# -# Copyright (C) 2020 Gioacchino Mazzurco -# Copyright (C) 2020 Asociación Civil Altermundi -# -# 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, version 3. -# -# 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 - -<<"ASCIIDOC" - -Start gdbserver on Android device and attach it to the retroshare service -process - -Inspired by: -https://fw4spl-org.github.io/fw4spl-blog/2015/07/27/Native-debugging-on-Android-with-QtCreator.html - -ASCIIDOC - - -## Define default value for variable, take two arguments, $1 variable name, -## $2 default variable value, if the variable is not already define define it -## with default value. -function define_default_value() -{ - VAR_NAME="${1}" - DEFAULT_VALUE="${2}" - - [ -z "${!VAR_NAME}" ] && export ${VAR_NAME}="${DEFAULT_VALUE}" || true -} - -define_default_value ANDROID_APK_PACKAGE "org.retroshare.service" -define_default_value ANDROID_PROCESS_NAME "org.retroshare.service:rs" -define_default_value ANDROID_INSTALL_PATH "" -define_default_value LIB_GDB_SERVER_PATH "" -define_default_value ANDROID_SERIAL "$(adb devices | head -n 2 | tail -n 1 | awk '{print $1}')" -define_default_value GDB_SERVER_PORT 5039 - -adb_ushell() -{ - adb shell run-as ${ANDROID_APK_PACKAGE} $@ -} - -[ -z "${ANDROID_INSTALL_PATH}" ] && -{ - ANDROID_INSTALL_PATH="$(adb_ushell pm path "${ANDROID_APK_PACKAGE}")" - ANDROID_INSTALL_PATH="$(dirname ${ANDROID_INSTALL_PATH#"package:"})" - [ -z "${ANDROID_INSTALL_PATH}" ] && - cat < New -> Import Project -> Git Clone -> Choose +Add Repository and Continoue -Install MacPort and XCode following this guide: [MacPort and XCode](http://guide.macports.org/#installing.xcode) + Repository: https://github.com/RetroShare/RetroShare.git -Start XCode to get it updated and to able C compiler to create executables. +via Terminal: -#### Install libraries + cd + git clone https://github.com/RetroShare/RetroShare.git retroshare - $sudo port -v selfupdate - $sudo port install openssl - $sudo port install miniupnpc - $sudo port install libmicrohttpd - -For VOIP Plugin: +via GitHub Desktop: [GitHub Desktop Download](https://central.github.com/deployments/desktop/desktop/latest/darwin) - $sudo port install speex-devel - $sudo port install opencv +In GitHub Desktop -> Clone Repository -> URL -Get Your OSX SDK if missing: [MacOSX-SDKs](https://github.com/phracker/MacOSX-SDKs) + Add Repository URL: https://github.com/RetroShare/RetroShare.git and Clone -### HOMEBREW Installation +## ***Get XCode & MacOSX SDK*** -Install HomeBrew following this guide: [HomeBrew](http://brew.sh/) +To identify the correct version of Xcode to install, you need to know which OS you are running. Go to the [x] menu -> "About This Mac" and read the macOS version number. + +If you are running macOS Ventura 13.5 or later, you can install Xcode directly from App Store using the instructions below. + +You can find older versions of Xcode at [Apple Developer Downloads](https://developer.apple.com/downloads/). Find the appropriate .xip file for your macOS version + +To install from App Store: + +Select [x] menu - > "App Store…". +Search for Xcode. Download and install. + +Once Xcode has installed, you must drag the XCode icon into your Applications folder. After you have done this, open Xcode from the Applications folder by double-clicking on the icon and then follow the remaining instructions below. Install XCode command line developer tools: @@ -44,11 +53,33 @@ Install XCode command line developer tools: Start XCode to get it updated and to able C compiler to create executables. +Older MacOSX SDK is available from here: [MacOSX-SDKs](https://github.com/phracker/MacOSX-SDKs) + +### MacPort Installation + +Install MacPort following this guide: [MacPort](http://guide.macports.org/#installing.xcode) + +### HOMEBREW Installation + +Install HomeBrew following this guide: [HomeBrew](http://brew.sh/) + #### Install libraries - $brew install openssl - $brew install miniupnpc - $brew install libmicrohttpd + $ brew install openssl + $ brew install miniupnpc + $ brew install rapidjson + $ brew install sqlcipher + +For RNP lib: + + $ brew install bzip2 + $ brew install zlib + $ brew install json-c + $ brew install botan@2 + +#### Install CMake + + $ brew install cmake If you have error in linking, run this: @@ -56,37 +87,130 @@ If you have error in linking, run this: For VOIP Plugin: - $brew install speex - $brew install speexdsp - $brew install homebrew/science/opencv - $brew install ffmpeg + $ brew install speex + $ brew install speexdsp + $ brew install opencv + $ brew install ffmpeg -Get Your OSX SDK if missing: [MacOSX-SDKs](https://github.com/phracker/MacOSX-SDKs) +For FeedReader Plugin: + + $ brew install libxslt + $ brew install libxml2 ## Last Settings -In QtCreator Option Git select "Pull" with "Rebase" +In QtCreator Projects -> Manage Kits > Version Control > Git: -## Compil missing libraries -### SQLCipher - - cd - git clone https://github.com/sqlcipher/sqlcipher.git - cd sqlcipher - ./configure --disable-shared --disable-tcl --enable-static --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC -I/opt/local/include" LDFLAGS="-lcrypto" - make - sudo make install + select "Pull with rebase" -NOTE, might be necessary to *chmod 000 /usr/local/ssl* temporarily during *./configure* if -homebrew uses newer, non-stock ssl dependencies found there. Configure might get confused. +In QtCreator Projects -> Build -> Build Settings -> Build Environment -> Add this path: -You can now compile RS into Qt Creator or with terminal + /usr/local/bin - cd - git clone https://github.com/RetroShare/RetroShare.git retroshare - cd retroshare - qmake; make +In QtCreator Projects -> Build -> Build Settings -> Build Steps -> Add Additional arguments: + + "CONFIG+=rs_autologin" "CONFIG+=rs_use_native_dialogs" + +## Set your Mac OS SDK version + + +Edit retroshare.pri and set your installed sdk version example for 11.1 -> rs_macos11.1 (line 135:) + + macx:CONFIG *= rs_macos11.1 + rs_macos10.8:CONFIG -= rs_macos11.1 + rs_macos10.9:CONFIG -= rs_macos11.1 + rs_macos10.10:CONFIG -= rs_macos11.1 + rs_macos10.12:CONFIG -= rs_macos11.1 + rs_macos10.13:CONFIG -= rs_macos11.1 + rs_macos10.14:CONFIG -= rs_macos11.1 + rs_macos10.15:CONFIG -= rs_macos11.1 + + +## Link Include & Libraries + +When required edit your retroshare.pri macx-* section, check if the Include and Lib path are correct (macx-* section) + + INCLUDEPATH += "/usr/local/opt/openssl/include" + QMAKE_LIBDIR += "/usr/local/opt/openssl/lib" + QMAKE_LIBDIR += "/usr/local/opt/sqlcipher/lib" + QMAKE_LIBDIR += "/usr/local/opt/miniupnpc/lib" + +alternative via Terminal + + $ qmake + INCLUDEPATH+="/usr/local/opt/openssl/include" \ + QMAKE_LIBDIR+="/usr/local/opt/openssl/lib" \ + QMAKE_LIBDIR+="/usr/local/opt/sqlcipher/lib" \ + QMAKE_LIBDIR+="/usr/local/opt/miniupnpc/lib" \ + CONFIG+=rs_autologin \ + CONFIG+=rs_use_native_dialogs \ + CONFIG+=release \ + .. + +For FeedReader Plugin: + + INCLUDEPATH += "/usr/local/opt/libxml2/include/libxml2" + +With plugins: + + $ qmake \ + INCLUDEPATH+="/usr/local/opt/openssl/include" QMAKE_LIBDIR+="/usr/local/opt/openssl/lib" \ + QMAKE_LIBDIR+="/usr/local/opt/sqlcipher/lib" \ + QMAKE_LIBDIR+="/usr/local/opt/miniupnpc/lib" \ + INCLUDEPATH+="/usr/local/opt/opencv/include/opencv4" QMAKE_LIBDIR+="/usr/local/opt/opencv/lib" \ + INCLUDEPATH+="/usr/local/opt/speex/include" QMAKE_LIBDIR+="/usr/local/opt/speex/lib/" \ + INCLUDEPATH+="/usr/local/opt/speexdsp/include" QMAKE_LIBDIR+="/usr/local/opt/speexdsp/lib/" \ + INCLUDEPATH+="/usr/local/opt/libxslt/include" QMAKE_LIBDIR+="/usr/local/opt/libxslt/lib" \ + QMAKE_LIBDIR+="/usr/local/opt/ffmpeg/lib" \ + LIBS+=-lopencv_videoio \ + CONFIG+=retroshare_plugins \ + CONFIG+=rs_autologin \ + CONFIG+=rs_use_native_dialogs \ + CONFIG+=release \ + .. + +## Compile RetroShare + +You can now compile RetroShare into Qt Creator or with Terminal + + $ cd /path/to/retroshare + $ qmake .. + $ make You can change Target and SDK in *./retroshare.pri:82* changing value of QMAKE_MACOSX_DEPLOYMENT_TARGET and QMAKE_MAC_SDK -You can find compiled application on *./retroshare/retroshare-gui/src/retroshare.app* +You can find the compiled application at *./retroshare/retroshare-gui/src/retroshare.app* + +## Issues + +If you have issues with openssl (Undefined symbols for architecture x86_64) try to add to *~/.profile* file this or via Terminal + + export PATH="/usr/local/opt/openssl/bin:$PATH" + export LDFLAGS="-L/usr/local/opt/openssl/lib" + export CPPFLAGS="-I/usr/local/opt/openssl/include" + export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig" + +For Qt Creator -> QtCreator Projects -> Build -> Build Settings -> Build Steps -> Add Additional arguments: + + LDFLAGS="-L/usr/local/opt/openssl/lib" + CPPFLAGS="-I/usr/local/opt/openssl/include" + + + +## Copy Plugins + + $ cp \ + ./plugins/FeedReader/lib/libFeedReader.dylib \ + ./plugins/VOIP/lib/libVOIP.dylib \ + ./plugins/RetroChess/lib/libRetroChess.dylib \ + ./retroshare-gui/src/RetroShare.app/Contents/Resources/ + +### Compile Retroshare-Service & Webui with CMake +before you can compile overwrite the file "asio/include/asio/detail/config.hpp" here is a fix for macos [ +asio fix](https://github.com/chriskohlhoff/asio/commit/68df16d560c68944809bb2947360fe8035e9ae0a) + + $ cd retroshare-service + $ mkdir build-dir + $ cd build-dir + $ cmake -DRS_WEBUI=ON -DCMAKE_BUILD_TYPE=Release .. + $ make diff --git a/build_scripts/OSX/OSX_RS_Compilation_Instructions.txt b/build_scripts/OSX/OSX_RS_Compilation_Instructions.txt deleted file mode 100644 index 684c45f3e..000000000 --- a/build_scripts/OSX/OSX_RS_Compilation_Instructions.txt +++ /dev/null @@ -1,66 +0,0 @@ - -Mac OSX Build Instructions. -------------------------------------------- - -There are several complications with building Retroshare under OSX. - 1) Support Libraries must be built and installed seperately. - 2) Universal and OSX 10.5 support is a little tricky, mainly due to the support libraries. - -Additional Libraries ---------------------- - - * GnuPG Package, that comes with Retroshare OSX install image. (GnuPG-1.4.9.dmg) - -GPG Development libraries - * libassuan (I'm using 2.0.1) - * libgpg-error (I'm using 1.9) - * libgpgme (I'm using 1.3.0) - -These libraries use standard UNIX installation systems: AUTOCONF/AUTOMAKE (configure, make, etc) -Unfortunately, this makes it difficult and a little manual to compile Universal and 10.5 libraries. - -UPNPC (for OSX and windows) - * miniupnpc (I'm using 1.0) - -You will also need to install - * XCode (available on the Apple Install CDs) - * Qt4 (from trolltech.com) - -First Compilation... --------------------- - -The First challenge is to build Retroshare on your Mac. For this first compilation, -we only build for your specific machine, and not attempt a Generic / 10.5 / Univeral build. - - -1) Install / Compile all the packages listed above. - be sure to use a configure command like this where applicable to only create a static library. - ./configure --enable-static=yes --enable-shared=no CFLAGS="-arch i386" CPPFLAGS="-arch i386" - -2) Check out the Retroshare SVN. - -3) compile libbitdht: - cd libbitdht/src - qmake - - This recreates a xcodeproj file for compilation using XCode. - Open with Xcode, and build. - -4) compile libretroshare: same way. -5) compile retroshare-gui: same way. - - -Creating Retroshare OSX Distribution Packages. ------------------------------------------------ - TODO, once I've got feedback on First Compilation! - - - - - - - - - - - diff --git a/build_scripts/OSX/makeOSXPackage.sh b/build_scripts/OSX/makeOSXPackage.sh new file mode 100644 index 000000000..8f9700ed0 --- /dev/null +++ b/build_scripts/OSX/makeOSXPackage.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +APP="RetroShare" +RSVERSION="0.6.7a" +QTVERSION="Qt-5.15.11" + +# Install the 7z to create dmg archives. +#brew list p7zip || brew install p7zip + +# Package your app +echo "Packaging retroshare..." +#cd ${project_dir}/build/macOS/clang/x86_64/release/ +cd retroshare-gui/src/ + +# Remove build directories that you don't want to deploy +rm -rf moc +rm -rf obj +rm -rf qrc + +# This sets the CFBundleVersion & CFBundleShortVersionString string +/usr/libexec/PlistBuddy -c "Delete :CFBundleGetInfoString" retroshare.app/Contents/Info.plist +/usr/libexec/PlistBuddy -c "Add :CFBundleVersion string $RSVERSION" retroshare.app/Contents/Info.plist +/usr/libexec/PlistBuddy -c "Add :CFBundleShortVersionString string $RSVERSION" retroshare.app/Contents/Info.plist +/usr/libexec/PlistBuddy -c "Delete :NSRequiresAquaSystemAppearance" retroshare.app/Contents/Info.plist + +# This automatically creates retroshare.dmg + +echo "Creating dmg archive..." +macdeployqt retroshare.app -dmg + +DATE=`date +"%m-%d-%Y"` +MACVERSION=`sw_vers -productVersion` +#RSVERSION=`git describe --abbrev=0 --tags` +GITHEAD=`git rev-parse --short HEAD` + +mv $APP.dmg "$APP-$RSVERSION-$GITHEAD-$DATE-MacOS-$MACVERSION-$QTVERSION.dmg" + +# You can use the appdmg command line app to create your dmg file if +# you want to use a custom background and icon arrangement. I'm still +# working on this for my apps, myself. If you want to do this, you'll +# remove the -dmg option above. +# appdmg json-path YourApp_${TRAVIS_TAG}.dmg + +# Copy other project files +cp "../../libbitdht/src/bitdht/bdboot.txt" "retroshare.app/Contents/Resources/" +cp "../../plugins/FeedReader/lib/libFeedReader.dylib" "retroshare.app/Contents/Resources/" +cp -R "sounds" "retroshare.app/Contents/Resources/sounds" + +# cp "${project_dir}/README.md" "README.md" +# cp "${project_dir}/LICENSE" "LICENSE" +# cp "${project_dir}/Qt License" "Qt License" diff --git a/build_scripts/OSX/retroshare-mac-build.patch b/build_scripts/OSX/retroshare-mac-build.patch deleted file mode 100644 index 7023ad7c2..000000000 --- a/build_scripts/OSX/retroshare-mac-build.patch +++ /dev/null @@ -1,94 +0,0 @@ -commit 51f554f909086f4baca7be215d5edacab744dea4 -Author: Kartikaya Gupta -Date: Wed Mar 7 23:30:48 2012 -0500 - - Modifications needed to get build working on Mac OS X 10.6 - -diff --git a/.gitignore b/.gitignore -new file mode 100644 -index 0000000..3e90033 ---- /dev/null -+++ b/.gitignore -@@ -0,0 +1,6 @@ -+*.o -+Makefile -+libbitdht/src/lib/ -+libretroshare/src/lib/ -+retroshare-gui/src/RetroShare.app/ -+retroshare-gui/src/temp/ -diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro -index 6f35e01..267cc91 100644 ---- a/libretroshare/src/libretroshare.pro -+++ b/libretroshare/src/libretroshare.pro -@@ -312,7 +312,7 @@ mac { - OBJECTS_DIR = temp/obj - MOC_DIR = temp/moc - #DEFINES = WINDOWS_SYS WIN32 STATICLIB MINGW -- #DEFINES *= MINIUPNPC_VERSION=13 -+ DEFINES *= MINIUPNPC_VERSION=13 - DESTDIR = lib - - #miniupnp implementation files -@@ -326,12 +326,11 @@ mac { - # Beautiful Hack to fix 64bit file access. - QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dfopen64=fopen -Dvstatfs64=vstatfs - -- UPNPC_DIR = ../../../miniupnpc-1.0 -- GPG_ERROR_DIR = ../../../../libgpg-error-1.7 -- GPGME_DIR = ../../../../gpgme-1.1.8 -+ UPNPC_DIR = ../../../miniupnpc-1.3 -+ GPG_ERROR_DIR = ../../../libgpg-error-1.10 -+ GPGME_DIR = ../../../gpgme-1.3.1 - -- INCLUDEPATH += . $${UPNPC_DIR} -- #INCLUDEPATH += . $${UPNPC_DIR} $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src -+ INCLUDEPATH += . $${UPNPC_DIR} $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src - } - - ################################# FreeBSD ########################################## -diff --git a/libretroshare/src/pqi/sslfns.cc b/libretroshare/src/pqi/sslfns.cc -index 2588cb8..305433f 100644 ---- a/libretroshare/src/pqi/sslfns.cc -+++ b/libretroshare/src/pqi/sslfns.cc -@@ -586,8 +586,8 @@ X509 *loadX509FromDER(const uint8_t *ptr, uint32_t len) - X509 *tmp = NULL; - #ifdef __APPLE__ - // This depends on which version you are compiling for... OSX10.5 doesn't have consts (old OpenSSL!) -- unsigned char **certptr = (unsigned char **) &ptr; -- //const unsigned char **certptr = (const unsigned char **) &ptr; -+ //unsigned char **certptr = (unsigned char **) &ptr; -+ const unsigned char **certptr = (const unsigned char **) &ptr; - #else - const unsigned char **certptr = (const unsigned char **) &ptr; - #endif -diff --git a/retroshare-gui/src/RetroShare.pro b/retroshare-gui/src/RetroShare.pro -index adcb5a0..ffbf669 100644 ---- a/retroshare-gui/src/RetroShare.pro -+++ b/retroshare-gui/src/RetroShare.pro -@@ -140,19 +140,21 @@ win32 { - - macx { - # ENABLE THIS OPTION FOR Univeral Binary BUILD. -- CONFIG += ppc x86 -- QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 -+ # CONFIG += ppc x86 -+ QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6 - - CONFIG += version_detail_bash_script - LIBS += ../../libretroshare/src/lib/libretroshare.a -- LIBS += -lssl -lcrypto -lz -lgpgme -lgpg-error -lassuan -- LIBS += ../../../miniupnpc-1.0/libminiupnpc.a -+ LIBS += ../../../libgpg-error-1.10/build/lib/libgpg-error.a -+ LIBS += ../../../gpgme-1.3.1/build/lib/libgpgme.a -+ LIBS += ../../../miniupnpc-1.3/libminiupnpc.a -+ LIBS += -lssl -lcrypto -lz -lassuan - LIBS += -framework CoreFoundation - LIBS += -framework Security - - # LIBS += -framework CoreServices - -- INCLUDEPATH += . -+ INCLUDEPATH += . ../../../gpgme-1.3.1/src - #DEFINES* = MAC_IDLE # for idle feature - CONFIG -= uitools - diff --git a/build_scripts/RedHat+Fedora/data/retroshare.desktop b/build_scripts/RedHat+Fedora/data/retroshare.desktop index 7b93b4fa5..95056d54a 100644 --- a/build_scripts/RedHat+Fedora/data/retroshare.desktop +++ b/build_scripts/RedHat+Fedora/data/retroshare.desktop @@ -1,10 +1,11 @@ [Desktop Entry] +Encoding=UTF-8 Version=1.0 Name=RetroShare -Comment=Securely share files with your friends +Comment=Securely communicate with your friends Exec=/usr/bin/retroshare %U Icon=/usr/share/pixmaps/retroshare.xpm Terminal=false Type=Application -Categories=Network;P2P; +Categories=Network;Email;InstantMessaging;Chat;Feed;FileTransfer;P2P MimeType=x-scheme-handler/retroshare; diff --git a/build_scripts/Windows-msys2/WindowsMSys2_InstallGuide.md b/build_scripts/Windows-msys2/WindowsMSys2_InstallGuide.md index 2105112f1..a0d1b67b6 100644 --- a/build_scripts/Windows-msys2/WindowsMSys2_InstallGuide.md +++ b/build_scripts/Windows-msys2/WindowsMSys2_InstallGuide.md @@ -18,8 +18,8 @@ At the end, you'll get at ..\\*-msys2\deploy\ the Portable 7zip file. ### MSYS2 INSTALLATION (for editing or debugging) -Download MSYS2 from [MSYS2](http://www.msys2.org/). Get the i686 version -if you run a 32-bit Windows or the x86_64 if you run a 64-bit Windows. +Download MSYS2 from [MSYS2](http://www.msys2.org/). Installing +MSYS2 requires 64 bit Windows 10 or newer. Run the installer and install MSYS2. @@ -40,26 +40,29 @@ Run MSYS2 MSYS again and finish updating with: Install the default programs needed to build: - pacman -S base-devel git wget p7zip gcc perl ruby python2 doxygen cmake + pacman -S base-devel git wget p7zip gcc perl ruby doxygen cmake -Install the 32-bit toolchain: +Install the 64-bit toolchain: - pacman -S mingw-w64-i686-toolchain + pacman -S mingw-w64-x86_64-toolchain Install all needed dependencies: - pacman -S mingw-w64-i686-miniupnpc - pacman -S mingw-w64-i686-libmicrohttpd - pacman -S mingw-w64-i686-libxslt - pacman -S mingw-w64-i686-xapian-core - pacman -S mingw-w64-i686-sqlcipher - pacman -S mingw-w64-i686-qt5 - pacman -S mingw32/mingw-w64-i686-cmake - pacman -S mingw-w64-i686-rapidjson + pacman -S mingw-w64-x86_64-miniupnpc + pacman -S mingw-w64-x86_64-libxslt + pacman -S mingw-w64-x86_64-xapian-core + pacman -S mingw-w64-x86_64-sqlcipher + pacman -S mingw-w64-x86_64-qt5-base + pacman -S mingw-w64-x86_64-qt5-multimedia + pacman -S mingw-w64-x86_64-ccmake + pacman -S mingw-w64-x86_64-rapidjson + pacman -S mingw-w64-x86_64-json-c + pacman -S mingw-w64-x86_64-libbotan + pacman -S mingw-w64-x86_64-asio If you want to use QtCreator as IDE, prefer using this one publish by MSYS2 as all build Kit are already setted. - pacman -S mingw-w64-i686-qt-creator + pacman -S mingw-w64-x86_64-qt-creator *You can start it from MSYS2 terminal.* @@ -67,7 +70,7 @@ We're done installing MSYS2, close the shell terminal. ### BUILDING RETROSHARE -Now run the MSYS2 MinGW 32-bit shell terminal (it's in the start menu). +Now run the MSYS2 MinGW 64-bit shell terminal (it's in the start menu). We will use it to checkout Retroshare and build it: git clone https://github.com/RetroShare/RetroShare.git diff --git a/build_scripts/Windows-msys2/build/build-installer.bat b/build_scripts/Windows-msys2/build/build-installer.bat index 192b2d025..da404f273 100644 --- a/build_scripts/Windows-msys2/build/build-installer.bat +++ b/build_scripts/Windows-msys2/build/build-installer.bat @@ -43,6 +43,7 @@ set NSIS_PARAM=%NSIS_PARAM% /DDEPLOYDIR="%RsDeployPath%" set NSIS_PARAM=%NSIS_PARAM% /DOUTDIR="%RsPackPath%" set NSIS_PARAM=%NSIS_PARAM% /DINSTALLERADD="%RsArchiveAdd%" set NSIS_PARAM=%NSIS_PARAM% /DARCHITECTURE="%RsArchitecture%" +set NSIS_PARAM=%NSIS_PARAM% /DTOOLCHAIN="%RsToolchain%" set NSIS_PARAM=%NSIS_PARAM% /DREVISION=%RsVersion.Extra% set QtMainVersion=%QtVersion:~0,1% diff --git a/build_scripts/Windows-msys2/build/build.bat b/build_scripts/Windows-msys2/build/build.bat index 4d366f28c..fc5632293 100644 --- a/build_scripts/Windows-msys2/build/build.bat +++ b/build_scripts/Windows-msys2/build/build.bat @@ -18,20 +18,32 @@ if errorlevel 1 goto error_env if not "%ParamNoupdate%"=="1" ( :: Install needed things %EnvMSYS2Cmd% "pacman --noconfirm --needed -S make git mingw-w64-%RsMSYS2Architecture%-toolchain mingw-w64-%RsMSYS2Architecture%-qt5 mingw-w64-%RsMSYS2Architecture%-miniupnpc mingw-w64-%RsMSYS2Architecture%-sqlcipher mingw-w64-%RsMSYS2Architecture%-cmake mingw-w64-%RsMSYS2Architecture%-rapidjson" + :: rnp + %EnvMSYS2Cmd% "pacman --noconfirm --needed -S mingw-w64-%RsMSYS2Architecture%-json-c mingw-w64-%RsMSYS2Architecture%-libbotan" :: Webui - if "%ParamWebui%"=="1" %EnvMSYS2Cmd% "pacman --noconfirm --needed -S mingw-w64-%RsMSYS2Architecture%-doxygen" + if "%ParamWebui%"=="1" %EnvMSYS2Cmd% "pacman --noconfirm --needed -S mingw-w64-%RsMSYS2Architecture%-doxygen mingw-w64-%RsMSYS2Architecture%-asio" :: Plugins if "%ParamPlugins%"=="1" %EnvMSYS2Cmd% "pacman --noconfirm --needed -S mingw-w64-%RsMSYS2Architecture%-speex mingw-w64-%RsMSYS2Architecture%-speexdsp mingw-w64-%RsMSYS2Architecture%-curl mingw-w64-%RsMSYS2Architecture%-libxslt mingw-w64-%RsMSYS2Architecture%-opencv mingw-w64-%RsMSYS2Architecture%-ffmpeg" :: Clang - if "%ParamClang%"=="1" %EnvMSYS2Cmd% "pacman --noconfirm --needed -S mingw-w64-%RsMSYS2Architecture%-clang" + if "%ClangCompiler%"=="1" %EnvMSYS2Cmd% "pacman --noconfirm --needed -S mingw-w64-%RsMSYS2Architecture%-clang" :: Indexing if "%ParamIndexing%"=="1" %EnvMSYS2Cmd% "pacman --noconfirm --needed -S mingw-w64-%RsMSYS2Architecture%-xapian-core mingw-w64-%RsMSYS2Architecture%-libvorbis mingw-w64-%RsMSYS2Architecture%-flac mingw-w64-%RsMSYS2Architecture%-taglib" ) +:: Fix webui compilation (TODO: remove when whole RS switched to cmake) +if "%ParamWebui%"=="1" ( + pushd "%SourcePath%" + copy "%SourcePath%\libretroshare\src\jsonapi\jsonapi-generator-doxygen.conf" "%SourcePath%\jsonapi-generator\src\jsonapi-generator-doxygen.conf" %Quite% + copy "%SourcePath%\libretroshare\src\jsonapi\async-method-wrapper-template.cpp.tmpl" "%SourcePath%\jsonapi-generator\src\async-method-wrapper-template.cpp.tmpl" %Quite% + copy "%SourcePath%\libretroshare\src\jsonapi\method-wrapper-template.cpp.tmpl" "%SourcePath%\jsonapi-generator\src\method-wrapper-template.cpp.tmpl" %Quite% + git update-index --assume-unchanged "jsonapi-generator\src\jsonapi-generator-doxygen.conf" "jsonapi-generator\src\async-method-wrapper-template.cpp.tmpl" "jsonapi-generator\src\method-wrapper-template.cpp.tmpl" + popd +) + :: Initialize environment call "%~dp0env.bat" %* if errorlevel 2 exit /B 2 @@ -66,11 +78,11 @@ echo %RS_QMAKE_CONFIG% > buildinfo.txt echo %RsBuildConfig% >> buildinfo.txt echo %RsArchitecture% >> buildinfo.txt echo Qt %QtVersion% >> buildinfo.txt -echo %RsCompiler% >> buildinfo.txt +echo %RsToolchain% >> buildinfo.txt call "%ToolsPath%\msys2-path.bat" "%SourcePath%" MSYS2SourcePath call "%ToolsPath%\msys2-path.bat" "%EnvMSYS2Path%" MSYS2EnvMSYS2Path -if "%ParamClang%"=="1" ( +if "%ClangCompiler%"=="1" ( %EnvMSYS2Cmd% "qmake "%MSYS2SourcePath%/RetroShare.pro" -r -spec win32-clang-g++ %RS_QMAKE_CONFIG%" ) else ( %EnvMSYS2Cmd% "qmake "%MSYS2SourcePath%/RetroShare.pro" -r -spec win32-g++ %RS_QMAKE_CONFIG%" @@ -86,11 +98,6 @@ title Build - %SourceName%-%RsBuildConfig% [make] %EnvMSYS2Cmd% "make -j %CoreCount%" if errorlevel 1 goto error -:: Webui -if "%ParamWebui%"=="1" ( - call "%~dp0..\tools\webui.bat" -) - :error popd diff --git a/build_scripts/Windows-msys2/build/env-base.bat b/build_scripts/Windows-msys2/build/env-base.bat index 9d9fa5379..6e5c8480f 100644 --- a/build_scripts/Windows-msys2/build/env-base.bat +++ b/build_scripts/Windows-msys2/build/env-base.bat @@ -1,25 +1,46 @@ :: Process commandline parameter -set Param32=0 -set Param64=0 set ParamRelease=0 set ParamDebug=0 set ParamAutologin=0 set ParamPlugins=0 set ParamTor=0 set ParamWebui=0 -set ParamClang=0 +set ClangCompiler=0 set ParamIndexing=0 +set ParamFriendserver=0 set ParamNoupdate=0 set CoreCount=%NUMBER_OF_PROCESSORS% set RS_QMAKE_CONFIG= +set RsToolchain= +set tcc=0 :parameter_loop if "%~1" NEQ "" ( for /f "tokens=1,2 delims==" %%a in ("%~1") do ( if "%%~a"=="32" ( - set Param32=1 + set RsToolchain=mingw32 + set /A tcc=tcc+1 ) else if "%%~a"=="64" ( - set Param64=1 + set RsToolchain=mingw64 + set /A tcc=tcc+1 + ) else if "%%~a"=="mingw32" ( + set RsToolchain=mingw32 + set /A tcc=tcc+1 + ) else if "%%~a"=="mingw64" ( + set RsToolchain=mingw64 + set /A tcc=tcc+1 + ) else if "%%~a"=="ucrt64" ( + set RsToolchain=ucrt64 + set /A tcc=tcc+1 + ) else if "%%~a"=="clang64" ( + set RsToolchain=clang64 + set /A tcc=tcc+1 + ) else if "%%~a"=="clang32" ( + set RsToolchain=clang32 + set /A tcc=tcc+1 + ) else if "%%~a"=="clangarm64" ( + set RsToolchain=clangarm64 + set /A tcc=tcc+1 ) else if "%%~a"=="release" ( set ParamRelease=1 ) else if "%%~a"=="debug" ( @@ -34,10 +55,10 @@ if "%~1" NEQ "" ( set ParamWebui=1 ) else if "%%~a"=="singlethread" ( set CoreCount=1 - ) else if "%%~a"=="clang" ( - set ParamClang=1 ) else if "%%~a"=="indexing" ( set ParamIndexing=1 + ) else if "%%~a"=="friendserver" ( + set ParamFriendserver=1 ) else if "%%~a"=="noupdate" ( set ParamNoupdate=1 ) else if "%%~a"=="CONFIG+" ( @@ -52,32 +73,39 @@ if "%~1" NEQ "" ( goto parameter_loop ) -if "%Param32%"=="1" ( - if "%Param64%"=="1" ( - echo. - echo 32-bit or 64-bit? - goto :usage - ) +if %tcc% NEQ 1 ( + echo Multiple or no toolchain specified + goto :usage +) - set RsBit=32 +if "%RsToolchain%"=="mingw32" ( set RsArchitecture=x86 set RsMSYS2Architecture=i686 -) - -if "%Param64%"=="1" ( - set RsBit=64 + set MSYSTEM=MINGW32 +) else if "%RsToolchain%"=="mingw64" ( set RsArchitecture=x64 set RsMSYS2Architecture=x86_64 + set MSYSTEM=MINGW64 +) else if "%RsToolchain%"=="ucrt64" ( + set RsArchitecture=x64 + set RsMSYS2Architecture=ucrt-x86_64 + set MSYSTEM=UCRT64 +) else if "%RsToolchain%"=="clang64" ( + set RsArchitecture=x64 + set RsMSYS2Architecture=clang-x86_64 + set MSYSTEM=CLANG64 + set ClangCompiler=1 +) else if "%RsToolchain%"=="clang32" ( + set RsArchitecture=x86 + set RsMSYS2Architecture=clang-i686 + set MSYSTEM=CLANG32 + set ClangCompiler=1 +) else if "%RsToolchain%"=="clangarm64" ( + set RsArchitecture=arm64 + set RsMSYS2Architecture=clang-aarch64 + set MSYSTEM=CLANGARM64 ) -if "%ParamClang%"=="1" ( - set RsCompiler=Clang -) else ( - set RsCompiler=GCC -) - -if "%RsBit%"=="" goto :usage - if "%ParamRelease%"=="1" ( if "%ParamDebug%"=="1" ( echo. @@ -104,14 +132,21 @@ if "%ParamIndexing%"=="1" ( set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% "CONFIG+=rs_deep_channels_index" "CONFIG+=rs_deep_files_index" "CONFIG+=rs_deep_files_index_ogg" "CONFIG+=rs_deep_files_index_flac" "CONFIG+=rs_deep_files_index_taglib" ) +if "%ParamFriendserver%"=="1" ( + set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% "CONFIG+=rs_efs" +) + exit /B 0 :usage echo. -echo Usage: 32^|64 release^|debug [autologin plugins webui singlethread clang indexing noupdate] ["CONFIG+=..."] +echo Usage: 32^|64^|other release^|debug [autologin plugins webui singlethread clang indexing friendserver noupdate] ["CONFIG+=..."] echo. echo Mandatory parameter -echo 32^|64 32-bit or 64-bit Version +echo 32^|64 32-bit or 64-bit version (same as mingw32 or mingw64) +echo Or you can specify any other toolchain supported by msys2: +echo mingw32^|mingw64^|clang32^|clang64^|ucrt64^|clangarm64 +echo More info: https://www.msys2.org/docs/environments echo release^|debug Build release or debug version echo. echo Optional parameter (need clean when changed) @@ -119,8 +154,8 @@ echo autologin Build with autologin echo plugins Build plugins echo webui Enable JsonAPI and pack webui files echo singlethread Use only 1 thread for building -echo clang Use clang compiler instead of GCC echo indexing Build with deep channel and file indexing support +echo friendserver Enable friendserver support echo noupdate Skip updating the libraries echo "CONFIG+=..." Enable some extra features, you can find the almost complete list in retroshare.pri echo. diff --git a/build_scripts/Windows-msys2/build/env.bat b/build_scripts/Windows-msys2/build/env.bat index bfe2afeba..38ceeaee3 100644 --- a/build_scripts/Windows-msys2/build/env.bat +++ b/build_scripts/Windows-msys2/build/env.bat @@ -2,8 +2,6 @@ call "%~dp0env-base.bat" %* if errorlevel 2 exit /B 2 if errorlevel 1 goto error_env -set MSYSTEM=MINGW%RsBit% - set BuildPath=%EnvRootPath%\builds set DeployPath=%EnvRootPath%\deploy @@ -14,13 +12,13 @@ if not exist "%DeployPath%" mkdir "%DeployPath%" call "%ToolsPath%\get-qt-version.bat" QtVersion if "%QtVersion%"=="" %cecho% error "Cannot get Qt version." & exit /B 1 -set RsMinGWPath=%EnvMSYS2BasePath%\mingw%RsBit% +set RsMinGWPath=%EnvMSYS2BasePath%\%RsToolchain% -set RsBuildPath=%BuildPath%\Qt-%QtVersion%-%RsArchitecture%-%RsCompiler%-%RsBuildConfig% -set RsDeployPath=%DeployPath%\Qt-%QtVersion%%RsType%-%RsArchitecture%-%RsCompiler%-%RsBuildConfig% +set RsBuildPath=%BuildPath%\Qt-%QtVersion%-%RsToolchain%-%RsBuildConfig% +set RsDeployPath=%DeployPath%\Qt-%QtVersion%-%RsToolchain%%RsType%-%RsBuildConfig% set RsPackPath=%DeployPath% set RsArchiveAdd= -set RsWebuiPath=%RootPath%\%SourceName%-webui +set RsWebuiBuildPath=%RsBuildPath%\retroshare-webui\webui if not exist "%~dp0env-mod.bat" goto no_mod call "%~dp0env-mod.bat" diff --git a/build_scripts/Windows-msys2/build/pack.bat b/build_scripts/Windows-msys2/build/pack.bat index 75a66af3c..3fa48c615 100644 --- a/build_scripts/Windows-msys2/build/pack.bat +++ b/build_scripts/Windows-msys2/build/pack.bat @@ -71,9 +71,9 @@ if "%QtMainVersion%"=="4" set QtMainVersion2=4 if "%QtMainVersion%"=="5" set QtMainVersion1=5 if "%RsBuildConfig%" NEQ "release" ( - set Archive=%RsPackPath%\RetroShare-%RsVersion%-Windows-Portable-%RsDate%-%RsVersion.Extra%-%RsArchitecture%-msys2%RsType%%RsArchiveAdd%-%RsBuildConfig%.7z + set Archive=%RsPackPath%\RetroShare-%RsVersion%-Windows-Portable-%RsDate%-%RsVersion.Extra%-%RsToolchain%-msys2%RsType%%RsArchiveAdd%-%RsBuildConfig%.7z ) else ( - set Archive=%RsPackPath%\RetroShare-%RsVersion%-Windows-Portable-%RsDate%-%RsVersion.Extra%-%RsArchitecture%-msys2%RsType%%RsArchiveAdd%.7z + set Archive=%RsPackPath%\RetroShare-%RsVersion%-Windows-Portable-%RsDate%-%RsVersion.Extra%-%RsToolchain%-msys2%RsType%%RsArchiveAdd%.7z ) if exist "%Archive%" del /Q "%Archive%" @@ -105,6 +105,10 @@ copy "%RsBuildPath%\retroshare-nogui\src\%RsBuildConfig%\retroshare*-nogui.exe" copy "%RsBuildPath%\retroshare-service\src\%RsBuildConfig%\retroshare*-service.exe" "%RsDeployPath%" %Quite% copy "%RsBuildPath%\supportlibs\cmark\build\src\libcmark.dll" "%RsDeployPath%" %Quite% if exist "%RsBuildPath%\libretroshare\src\lib\retroshare.dll" copy "%RsBuildPath%\libretroshare\src\lib\retroshare.dll" "%RsDeployPath%" %Quite% +if exist "%RsBuildPath%\supportlibs\librnp\Build\src\lib\librnp.dll" copy "%RsBuildPath%\supportlibs\librnp\Build\src\lib\librnp.dll" "%RsDeployPath%" %Quite% +if exist "%RsBuildPath%\retroshare-friendserver\src\%RsBuildConfig%\retroshare-friendserver.exe" ( + copy "%RsBuildPath%\retroshare-friendserver\src\%RsBuildConfig%\retroshare-friendserver.exe" "%RsDeployPath%" %Quite% +) echo copy extensions for /D %%D in ("%RsBuildPath%\plugins\*") do ( @@ -132,8 +136,14 @@ del /Q "%RsDeployPath%\imageformats\*d?.dll" %Quite% if "%ParamTor%"=="1" ( echo copy tor - copy "%RsMinGWPath%\bin\tor.exe" "%RsDeployPath%" %Quite% - copy "%RsMinGWPath%\bin\tor-gencert.exe" "%RsDeployPath%" %Quite% + if not exist "%RsDeployPath%\tor" mkdir "%RsDeployPath%\tor" + copy "%RsMinGWPath%\bin\tor.exe" "%RsDeployPath%\tor" %Quite% + copy "%RsMinGWPath%\bin\tor-gencert.exe" "%RsDeployPath%\tor" %Quite% + + echo copy tor dependencies + for /R "%RsDeployPath%\tor" %%D in (*.exe) do ( + call :copy_dependencies "%%D" "%RsDeployPath%\tor" + ) ) echo copy dependencies @@ -141,8 +151,10 @@ for /R "%RsDeployPath%" %%D in (*.dll, *.exe) do ( call :copy_dependencies "%%D" "%RsDeployPath%" ) -echo copy qss -xcopy /S "%SourcePath%\retroshare-gui\src\qss" "%RsDeployPath%\qss" %Quite% +if exist "%SourcePath%\retroshare-gui\src\qss" ( + echo copy qss + xcopy /S "%SourcePath%\retroshare-gui\src\qss" "%RsDeployPath%\qss" %Quite% +) echo copy stylesheets xcopy /S "%SourcePath%\retroshare-gui\src\gui\qss\chat" "%RsDeployPath%\stylesheets" %Quite% @@ -176,12 +188,12 @@ echo copy buildinfo.txt copy "%RsBuildPath%\buildinfo.txt" "%RsDeployPath%" %Quite% if "%ParamWebui%"=="1" ( - if exist "%RsWebuiPath%\webui" ( + if exist "%RsWebuiBuildPath%" ( echo copy webui mkdir "%RsDeployPath%\webui" - xcopy /S "%RsWebuiPath%\webui" "%RsDeployPath%\webui" %Quite% + xcopy /S "%RsWebuiBuildPath%" "%RsDeployPath%\webui" %Quite% ) else ( - %cecho% error "Webui is enabled, but no webui data found at %RsWebuiPath%\webui" + %cecho% error "Webui is enabled, but no webui data found at %RsWebuiBuildPath%" goto error ) ) diff --git a/build_scripts/Windows-msys2/env/tools/prepare-msys2.bat b/build_scripts/Windows-msys2/env/tools/prepare-msys2.bat index 2f85c42be..cea1df073 100644 --- a/build_scripts/Windows-msys2/env/tools/prepare-msys2.bat +++ b/build_scripts/Windows-msys2/env/tools/prepare-msys2.bat @@ -16,7 +16,13 @@ if "%~1"=="clean" ( goto exit ) -if exist "%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\pacman.exe" ( +set MSYS2Version=20241208 + +set MSYS2Install=msys2-base-x86_64-%MSYS2Version%.sfx.exe +set MSYS2Url=https://github.com/msys2/msys2-installer/releases/download/%MSYS2Version:~0,4%-%MSYS2Version:~4,2%-%MSYS2Version:~6,2%/%MSYS2Install% +set MSYS2UnpackPath=%EnvMSYS2Path%\msys64 + +if exist "%MSYS2UnpackPath%\usr\bin\pacman.exe" ( if "%~1"=="reinstall" ( choice /M "Found existing MSYS2 version. Do you want to proceed?" if !ERRORLEVEL!==2 goto exit @@ -25,28 +31,26 @@ if exist "%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\pacman.exe" ( ) ) -set MSYS2Install=msys2-base-%MSYS2Architecture%-20200720.tar.xz -set MSYS2Url=http://sourceforge.net/projects/msys2/files/Base/%MSYS2Architecture%/%MSYS2Install%/download +if exist "%MSYS2UnpackPath%" ( + %cecho% info "Remove previous MSYS2 version" + call "%ToolsPath%\remove-dir.bat" "%MSYS2UnpackPath%" +) -%cecho% info "Remove previous MSYS2 version" -call "%ToolsPath%\remove-dir.bat" "%EnvMSYS2Path%" - -%cecho% info "Download installation files" +%cecho% info "Download MSYS2 installation files" if not exist "%EnvDownloadPath%\%MSYS2Install%" call "%ToolsPath%\download-file.bat" "%MSYS2Url%" "%EnvDownloadPath%\%MSYS2Install%" if not exist "%EnvDownloadPath%\%MSYS2Install%" %cecho% error "Cannot download MSYS" & goto error %cecho% info "Unpack MSYS2" -"%EnvSevenZipExe%" x -so "%EnvDownloadPath%\%MSYS2Install%" | "%EnvSevenZipExe%" x -y -si -ttar -o"%EnvMSYS2Path%" +"%EnvDownloadPath%\%MSYS2Install%" -y -o"%EnvMSYS2Path%" -set MSYS2SH=%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\sh +set MSYS2SH=%MSYS2UnpackPath%\usr\bin\sh %cecho% info "Initialize MSYS2" -"%MSYS2SH%" -lc "pacman -Sy" -"%MSYS2SH%" -lc "pacman --noconfirm --needed -S bash pacman pacman-mirrors msys2-runtime" +"%MSYS2SH%" -lc "yes | pacman --noconfirm -Syuu msys2-keyring" +"%MSYS2SH%" -lc "pacman --noconfirm -Sy" +"%MSYS2SH%" -lc "pacman --noconfirm -Su" -call "%EnvMSYS2Path%\msys%MSYS2Base%\autorebase.bat" -call "%EnvRootPath%\update-msys2.bat" -call "%EnvRootPath%\update-msys2.bat" +call "%MSYS2UnpackPath%\autorebase.bat" :exit endlocal diff --git a/build_scripts/Windows-msys2/env/tools/prepare-tools.bat b/build_scripts/Windows-msys2/env/tools/prepare-tools.bat index c6b14a787..66f5f9120 100644 --- a/build_scripts/Windows-msys2/env/tools/prepare-tools.bat +++ b/build_scripts/Windows-msys2/env/tools/prepare-tools.bat @@ -34,7 +34,7 @@ if not exist "%EnvToolsPath%\cecho.exe" ( if not exist "%EnvDownloadPath%\%cCEhoInstall%" echo Cannot download cecho installation& goto error echo Unpack cecho - "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%CEchoInstall%" + "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%CEchoInstall%" -y -bso0 copy "%EnvTempPath%\cecho.exe" "%EnvToolsPath%" call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%" diff --git a/build_scripts/Windows-msys2/env/tools/root/update-msys2.bat b/build_scripts/Windows-msys2/env/tools/root/update-msys2.bat index 3075e392b..ddd5bdd0f 100644 --- a/build_scripts/Windows-msys2/env/tools/root/update-msys2.bat +++ b/build_scripts/Windows-msys2/env/tools/root/update-msys2.bat @@ -2,18 +2,13 @@ setlocal -if exist "%~dp0msys2\msys32" call :update 32 -if exist "%~dp0msys2\msys64" call :update 64 +if not exist "%~dp0msys2\msys64" goto :EOF -goto :EOF +set MSYS2SH=%~dp0msys2\msys64\usr\bin\sh -:update -set MSYSSH=%~dp0msys2\msys%~1\usr\bin\sh +echo Update MSYS2 +"%MSYS2SH%" -lc "yes | pacman --noconfirm -Syuu msys2-keyring" +"%MSYS2SH%" -lc "pacman --noconfirm -Su" -echo Update MSYS2 %~1 -"%MSYSSH%" -lc "pacman -Sy" -"%MSYSSH%" -lc "pacman --noconfirm -Su" - -:exit endlocal goto :EOF diff --git a/build_scripts/Windows-msys2/installer/retroshare-Qt5.nsi b/build_scripts/Windows-msys2/installer/retroshare-Qt5.nsi index b30300634..f37f33cf8 100644 --- a/build_scripts/Windows-msys2/installer/retroshare-Qt5.nsi +++ b/build_scripts/Windows-msys2/installer/retroshare-Qt5.nsi @@ -9,6 +9,7 @@ ;!define REVISION "" ;!define DEPLOYDIR "" ;!define ARCHITECTURE "" +;!define TOOLCHAIN "" # Optional defines ;!define OUTDIR "" @@ -21,6 +22,9 @@ !ifndef ARCHITECTURE !error "ARCHITECTURE is not defined" !endif +!ifndef TOOLCHAIN +!error "TOOLCHAIN is not defined" +!endif # Check optional defines !ifdef OUTDIR @@ -72,7 +76,7 @@ ${!defineifexist} TOR_EXISTS "${DEPLOYDIR}\tor.exe" # Main Install settings Name "${APPNAMEANDVERSION}" InstallDirRegKey HKLM "Software\${APPNAME}" "" -OutFile "${OUTDIR_}RetroShare-${VERSION}-${Date}-${REVISION}-${ARCHITECTURE}${RSTYPE}${INSTALLERADD}-setup.exe" +OutFile "${OUTDIR_}RetroShare-${VERSION}-${Date}-${REVISION}-${TOOLCHAIN}-msys2${RSTYPE}${INSTALLERADD}-setup.exe" BrandingText "${APPNAMEANDVERSION}" RequestExecutionlevel highest # Use compression @@ -218,7 +222,7 @@ Section $(Section_Data) Section_Data ; Stylesheets SetOutPath "$INSTDIR\qss" - File /r "${DEPLOYDIR}\qss\*.*" + File /nonfatal /r "${DEPLOYDIR}\qss\*.*" SectionEnd ;Section $(Section_Link) Section_Link diff --git a/build_scripts/Windows-msys2/readme.md b/build_scripts/Windows-msys2/readme.md index 5582ec451..f5e214ee7 100644 --- a/build_scripts/Windows-msys2/readme.md +++ b/build_scripts/Windows-msys2/readme.md @@ -55,7 +55,6 @@ Run the scripts in this order: * "CONFIG+=..." enable other extra compile time features, you can find the almost complete list in file *<sourcefolder>\retroshare.pri* * For fixing compile problems (optional) * singlethread: use only 1 thread for building, slow but useful if you don't find the error message in the console - * clang: use clang compiler instead of GCC * noupdate: skip the msys2 update step, sometimes some msys2 packages are broken, you can manually switch back to the older package, and this option will prevent updating to the broken version again Example: diff --git a/build_scripts/Windows-msys2/tools/webui.bat b/build_scripts/Windows-msys2/tools/webui.bat deleted file mode 100644 index b7af01e53..000000000 --- a/build_scripts/Windows-msys2/tools/webui.bat +++ /dev/null @@ -1,22 +0,0 @@ -setlocal - -echo. -echo === webui -echo. -title Build webui - -if not exist "%RsWebuiPath%" ( - echo Checking out webui source into %RsWebuiPath% - if not "%ParamNoupdate%"=="1" ( - %EnvMSYS2Cmd% "pacman --noconfirm --needed -S git" - ) - git clone https://github.com/RetroShare/RSNewWebUI.git "%RsWebuiPath%" -) else ( - echo Webui source found at %RsWebuiPath% -) - -pushd "%RsWebuiPath%\webui-src\make-src" -%EnvMSYS2Cmd% "sh build.sh" -popd - -endlocal \ No newline at end of file diff --git a/build_scripts/Windows/build-libs/Makefile b/build_scripts/Windows/build-libs/Makefile index e6927150f..b0c9ce137 100644 --- a/build_scripts/Windows/build-libs/Makefile +++ b/build_scripts/Windows/build-libs/Makefile @@ -1,25 +1,33 @@ -ZLIB_VERSION=1.2.3 -BZIP2_VERSION=1.0.6 -MINIUPNPC_VERSION=2.0 -OPENSSL_VERSION=1.1.1h -SPEEX_VERSION=1.2.0 -SPEEXDSP_VERSION=1.2rc3 -OPENCV_VERSION=4.5.0 -LIBXML2_VERSION=2.9.7 -LIBXSLT_VERSION=1.1.32 -CURL_VERSION=7.58.0 +ZLIB_VERSION=1.2.11 +BZIP2_VERSION=1.0.8 +MINIUPNPC_VERSION=2.2.3 +OPENSSL_VERSION=1.1.1w +SPEEX_VERSION=1.2.1 +SPEEXDSP_VERSION=1.2.1 +LIBXML2_MAIN_VERSION=2.14 +LIBXML2_VERSION=$(LIBXML2_MAIN_VERSION).5 +LIBXSLT_MAIN_VERSION=1.1 +LIBXSLT_VERSION=$(LIBXSLT_MAIN_VERSION).43 +CURL_VERSION=8.9.1 TCL_VERSION=8.6.10 -SQLCIPHER_VERSION=4.4.0 -LIBMICROHTTPD_VERSION=0.9.59 -FFMPEG_VERSION=3.4 +SQLCIPHER_VERSION=4.5.0 +LIBMICROHTTPD_VERSION=0.9.75 +FFMPEG_VERSION=4.4.6 RAPIDJSON_VERSION=1.1.0 -XAPIAN_VERSION=1.4.7 +XAPIAN_VERSION=1.4.29 +ASIO_VERSION=1-34-2 +#RNP_VERSION=0.17.1 + +# libaries for rnp +JSON_C_VERSION=0.18 +BOTAN_VERSION=2.19.5 DOWNLOAD_PATH?=download BUILD_PATH=build LIBS_PATH?=libs -all: dirs zlib bzip2 miniupnpc openssl speex speexdsp opencv libxml2 libxslt curl sqlcipher libmicrohttpd ffmpeg rapidjson xapian copylibs +all: dirs zlib bzip2 miniupnpc openssl speex speexdsp libxml curl sqlcipher libmicrohttpd ffmpeg rapidjson xapian jsonc botan asio copylibs +#rnp download: \ $(DOWNLOAD_PATH)/zlib-$(ZLIB_VERSION).tar.gz \ @@ -28,14 +36,13 @@ download: \ $(DOWNLOAD_PATH)/openssl-$(OPENSSL_VERSION).tar.gz \ $(DOWNLOAD_PATH)/speex-$(SPEEX_VERSION).tar.gz \ $(DOWNLOAD_PATH)/speexdsp-$(SPEEXDSP_VERSION).tar.gz \ - $(DOWNLOAD_PATH)/opencv-$(OPENCV_VERSION).tar.gz \ - $(DOWNLOAD_PATH)/libxml2-$(LIBXML2_VERSION).tar.gz \ - $(DOWNLOAD_PATH)/libxslt-$(LIBXSLT_VERSION).tar.gz \ + $(DOWNLOAD_PATH)/libxml2-$(LIBXML2_VERSION).tar.xz \ + $(DOWNLOAD_PATH)/libxslt-$(LIBXSLT_VERSION).tar.xz \ $(DOWNLOAD_PATH)/curl-$(CURL_VERSION).tar.gz \ $(DOWNLOAD_PATH)/tcl$(TCL_VERSION)-src.tar.gz \ $(DOWNLOAD_PATH)/sqlcipher-$(SQLCIPHER_VERSION).tar.gz \ $(DOWNLOAD_PATH)/libmicrohttpd-$(LIBMICROHTTPD_VERSION).tar.gz \ - $(DOWNLOAD_PATH)/ffmpeg-$(FFMPEG_VERSION).tar.gz \ + $(DOWNLOAD_PATH)/ffmpeg-$(FFMPEG_VERSION).tar.xz \ $(DOWNLOAD_PATH)/rapidjson-$(RAPIDJSON_VERSION).tar.gz \ $(DOWNLOAD_PATH)/xapian-core-$(XAPIAN_VERSION).tar.xz @@ -58,8 +65,7 @@ $(BUILD_PATH)/zlib-$(ZLIB_VERSION): $(DOWNLOAD_PATH)/zlib-$(ZLIB_VERSION).tar.gz rm -r -f $(BUILD_PATH)/zlib-* tar xvf $(DOWNLOAD_PATH)/zlib-$(ZLIB_VERSION).tar.gz # build - cd zlib-$(ZLIB_VERSION) && ./configure - #cd zlib-$(ZLIB_VERSION) && make install prefix="`pwd`/../$(BUILD_PATH)" + cd zlib-$(ZLIB_VERSION) && make -f win32/Makefile.gcc libz.a cd zlib-$(ZLIB_VERSION) && make # copy files mkdir -p $(BUILD_PATH)/zlib-$(ZLIB_VERSION).tmp/include @@ -74,7 +80,7 @@ $(BUILD_PATH)/zlib-$(ZLIB_VERSION): $(DOWNLOAD_PATH)/zlib-$(ZLIB_VERSION).tar.gz bzip2: $(BUILD_PATH)/bzip2-$(BZIP2_VERSION) $(DOWNLOAD_PATH)/bzip2-$(BZIP2_VERSION).tar.gz: - wget https://sourceforge.net/projects/bzip2/files/bzip2-$(BZIP2_VERSION).tar.gz/download -O $(DOWNLOAD_PATH)/bzip2-$(BZIP2_VERSION).tar.gz + wget https://www.sourceware.org/pub/bzip2/bzip2-$(BZIP2_VERSION).tar.gz -O $(DOWNLOAD_PATH)/bzip2-$(BZIP2_VERSION).tar.gz $(BUILD_PATH)/bzip2-$(BZIP2_VERSION): $(DOWNLOAD_PATH)/bzip2-$(BZIP2_VERSION).tar.gz # prepare @@ -102,10 +108,10 @@ $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION): $(DOWNLOAD_PATH)/miniupnpc-$(MINIU rm -r -f $(BUILD_PATH)/miniupnpc-* tar xvf $(DOWNLOAD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tar.gz # build - cd miniupnpc-$(MINIUPNPC_VERSION) && export CC=gcc && export PATH=.:$$PATH && make -f Makefile.mingw init libminiupnpc.a miniupnpc.dll + cd miniupnpc-$(MINIUPNPC_VERSION) && export CC=gcc && export PATH=.:$$PATH && make -f Makefile.mingw libminiupnpc.a miniupnpc.dll # copy files mkdir -p $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tmp/include/miniupnpc - cp miniupnpc-$(MINIUPNPC_VERSION)/*.h $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tmp/include/miniupnpc/ + cp miniupnpc-$(MINIUPNPC_VERSION)/include/*.h $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tmp/include/miniupnpc/ mkdir -p $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tmp/lib cp miniupnpc-$(MINIUPNPC_VERSION)/miniupnpc.lib $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tmp/lib/ mkdir -p $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tmp/bin @@ -187,75 +193,52 @@ $(BUILD_PATH)/speexdsp-$(SPEEXDSP_VERSION): $(DOWNLOAD_PATH)/speexdsp-$(SPEEXDSP rm -r -f speexdsp-$(SPEEXDSP_VERSION) mv $(BUILD_PATH)/speexdsp-$(SPEEXDSP_VERSION).tmp $(BUILD_PATH)/speexdsp-$(SPEEXDSP_VERSION) -opencv: $(BUILD_PATH)/opencv-$(OPENCV_VERSION) +libxml: \ + $(BUILD_PATH)/libxml2-$(LIBXML2_VERSION) \ + $(BUILD_PATH)/libxslt-$(LIBXSLT_VERSION) -$(DOWNLOAD_PATH)/opencv-$(OPENCV_VERSION).tar.gz: - wget --no-check-certificate https://github.com/opencv/opencv/archive/$(OPENCV_VERSION).tar.gz -O $(DOWNLOAD_PATH)/opencv-$(OPENCV_VERSION).tar.gz +$(DOWNLOAD_PATH)/libxml2-$(LIBXML2_VERSION).tar.xz: + wget --no-check-certificate https://download.gnome.org/sources/libxml2/$(LIBXML2_MAIN_VERSION)/libxml2-$(LIBXML2_VERSION).tar.xz -O $(DOWNLOAD_PATH)/libxml2-$(LIBXML2_VERSION).tar.xz -$(BUILD_PATH)/opencv-$(OPENCV_VERSION): $(DOWNLOAD_PATH)/opencv-$(OPENCV_VERSION).tar.gz - # prepare - rm -r -f $(BUILD_PATH)/opencv-* - tar xvf $(DOWNLOAD_PATH)/opencv-$(OPENCV_VERSION).tar.gz - # Remove version numbers from libraries. Is there a switch? - sed -i -e's/\(ocv_update(OPENCV_DLLVERSION \).*$$/\1"")/' opencv-$(OPENCV_VERSION)/CMakeLists.txt - # build - mkdir -p opencv-$(OPENCV_VERSION)/build - #cd opencv-$(OPENCV_VERSION)/build && cmake .. -G"MSYS Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX="`pwd`/../../build" - cd opencv-$(OPENCV_VERSION)/build && cmake .. -G"MSYS Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DBUILD_SHARED_LIBS=OFF -DENABLE_CXX11=ON -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -DSTRSAFE_NO_DEPRECATE" -DCMAKE_INSTALL_PREFIX="`pwd`/install" - cd opencv-$(OPENCV_VERSION)/build && make install - # copy files - mkdir -p $(BUILD_PATH)/opencv-$(OPENCV_VERSION).tmp/include - cp -r opencv-$(OPENCV_VERSION)/build/install/include/* $(BUILD_PATH)/opencv-$(OPENCV_VERSION).tmp/include/ - mkdir -p $(BUILD_PATH)/opencv-$(OPENCV_VERSION).tmp/lib/opencv - cp -r opencv-$(OPENCV_VERSION)/build/install/x64/mingw/staticlib/* $(BUILD_PATH)/opencv-$(OPENCV_VERSION).tmp/lib/opencv/ - # cleanup - rm -r -f opencv-$(OPENCV_VERSION) - mv $(BUILD_PATH)/opencv-$(OPENCV_VERSION).tmp $(BUILD_PATH)/opencv-$(OPENCV_VERSION) +$(DOWNLOAD_PATH)/libxslt-$(LIBXSLT_VERSION).tar.xz: + wget --no-check-certificate https://download.gnome.org/sources/libxslt/$(LIBXSLT_MAIN_VERSION)/libxslt-$(LIBXSLT_VERSION).tar.xz -O $(DOWNLOAD_PATH)/libxslt-$(LIBXSLT_VERSION).tar.xz -libxml2: $(BUILD_PATH)/libxml2-$(LIBXML2_VERSION) - -$(DOWNLOAD_PATH)/libxml2-$(LIBXML2_VERSION).tar.gz: - wget ftp://xmlsoft.org/libxml2/libxml2-$(LIBXML2_VERSION).tar.gz -O $(DOWNLOAD_PATH)/libxml2-$(LIBXML2_VERSION).tar.gz - -$(BUILD_PATH)/libxml2-$(LIBXML2_VERSION): $(DOWNLOAD_PATH)/libxml2-$(LIBXML2_VERSION).tar.gz - # prepare +$(BUILD_PATH)/libxml2-$(LIBXML2_VERSION) $(BUILD_PATH)/libxslt-$(LIBXSLT_VERSION): \ + $(DOWNLOAD_PATH)/libxml2-$(LIBXML2_VERSION).tar.xz \ + $(DOWNLOAD_PATH)/libxslt-$(LIBXSLT_VERSION).tar.xz + # libxml2: prepare + pacman --needed --noconfirm -S python3 pkg-config rm -r -f $(BUILD_PATH)/libxml2-* - tar xvf $(DOWNLOAD_PATH)/libxml2-$(LIBXML2_VERSION).tar.gz - # build + tar xvf $(DOWNLOAD_PATH)/libxml2-$(LIBXML2_VERSION).tar.xz + # libxslt: prepare + rm -r -f $(BUILD_PATH)/libxslt-* + tar xvf $(DOWNLOAD_PATH)/libxml2-$(LIBXML2_VERSION).tar.xz + tar xvf $(DOWNLOAD_PATH)/libxslt-$(LIBXSLT_VERSION).tar.xz + # libxml2: build cd libxml2-$(LIBXML2_VERSION) && ./configure --without-iconv -enable-shared=no #cd libxml2-$(LIBXML2_VERSION) && make install exec_prefix="`pwd`/../$(BUILD_PATH)" - cd libxml2-$(LIBXML2_VERSION) && make - # copy files + cd libxml2-$(LIBXML2_VERSION) && make libxml2.la + # libxslt: build + cd libxslt-$(LIBXSLT_VERSION) && ./configure --with-libxml-src=../libxml2-$(LIBXML2_VERSION) -enable-shared=no CFLAGS=-DLIBXML_STATIC + cd libxslt-$(LIBXSLT_VERSION)/libxslt && make + cd libxslt-$(LIBXSLT_VERSION)/libexslt && make + # libxml2: copy files mkdir -p $(BUILD_PATH)/libxml2-$(LIBXML2_VERSION).tmp/include/libxml cp libxml2-$(LIBXML2_VERSION)/include/libxml/*.h $(BUILD_PATH)/libxml2-$(LIBXML2_VERSION).tmp/include/libxml/ mkdir -p $(BUILD_PATH)/libxml2-$(LIBXML2_VERSION).tmp/lib cp libxml2-$(LIBXML2_VERSION)/.libs/libxml2.a $(BUILD_PATH)/libxml2-$(LIBXML2_VERSION).tmp/lib/ - # cleanup - #rm -r -f libxml2-$(LIBXML2_VERSION) # see libxslt - mv $(BUILD_PATH)/libxml2-$(LIBXML2_VERSION).tmp $(BUILD_PATH)/libxml2-$(LIBXML2_VERSION) - -libxslt: $(BUILD_PATH)/libxslt-$(LIBXSLT_VERSION) - -$(DOWNLOAD_PATH)/libxslt-$(LIBXSLT_VERSION).tar.gz: - wget ftp://xmlsoft.org/libxml2/libxslt-$(LIBXSLT_VERSION).tar.gz -O $(DOWNLOAD_PATH)/libxslt-$(LIBXSLT_VERSION).tar.gz - -$(BUILD_PATH)/libxslt-$(LIBXSLT_VERSION): $(DOWNLOAD_PATH)/libxml2-$(LIBXML2_VERSION).tar.gz $(DOWNLOAD_PATH)/libxslt-$(LIBXSLT_VERSION).tar.gz - # prepare - rm -r -f $(BUILD_PATH)/libxslt-* - tar xvf $(DOWNLOAD_PATH)/libxml2-$(LIBXML2_VERSION).tar.gz - tar xvf $(DOWNLOAD_PATH)/libxslt-$(LIBXSLT_VERSION).tar.gz - # build - cd libxslt-$(LIBXSLT_VERSION) && ./configure --with-libxml-src=../libxml2-$(LIBXML2_VERSION) -enable-shared=no CFLAGS=-DLIBXML_STATIC - cd libxslt-$(LIBXSLT_VERSION) && make - # copy files + # libxslt: copy files mkdir -p $(BUILD_PATH)/libxslt-$(LIBXSLT_VERSION).tmp/include/libxslt cp libxslt-$(LIBXSLT_VERSION)/libxslt/*.h $(BUILD_PATH)/libxslt-$(LIBXSLT_VERSION).tmp/include/libxslt/ mkdir -p $(BUILD_PATH)/libxslt-$(LIBXSLT_VERSION).tmp/lib cp libxslt-$(LIBXSLT_VERSION)/libxslt/.libs/libxslt.a $(BUILD_PATH)/libxslt-$(LIBXSLT_VERSION).tmp/lib/ cp libxslt-$(LIBXSLT_VERSION)/libexslt/.libs/libexslt.a $(BUILD_PATH)/libxslt-$(LIBXSLT_VERSION).tmp/lib/ - # cleanup + # libxml2: cleanup rm -r -f libxml2-$(LIBXML2_VERSION) + # libxslt: cleanup rm -r -f libxslt-$(LIBXSLT_VERSION) + # finish + mv $(BUILD_PATH)/libxml2-$(LIBXML2_VERSION).tmp $(BUILD_PATH)/libxml2-$(LIBXML2_VERSION) mv $(BUILD_PATH)/libxslt-$(LIBXSLT_VERSION).tmp $(BUILD_PATH)/libxslt-$(LIBXSLT_VERSION) curl: $(BUILD_PATH)/curl-$(CURL_VERSION) @@ -270,7 +253,7 @@ $(BUILD_PATH)/curl-$(CURL_VERSION): $(DOWNLOAD_PATH)/curl-$(CURL_VERSION).tar.gz # build cd curl-$(CURL_VERSION) && ./configure --disable-shared --with-ssl="`pwd`/../$(BUILD_PATH)/openssl-$(OPENSSL_VERSION)" #cd curl-$(CURL_VERSION) && make install exec_prefix="`pwd`/../$(BUILD_PATH)" - cd curl-$(CURL_VERSION) && make + cd curl-$(CURL_VERSION)/lib && make # copy files mkdir -p $(BUILD_PATH)/curl-$(CURL_VERSION).tmp/include/curl cp curl-$(CURL_VERSION)/include/curl/*.h $(BUILD_PATH)/curl-$(CURL_VERSION).tmp/include/curl/ @@ -333,15 +316,15 @@ $(BUILD_PATH)/libmicrohttpd-$(LIBMICROHTTPD_VERSION): $(DOWNLOAD_PATH)/libmicroh ffmpeg: $(BUILD_PATH)/ffmpeg-$(FFMPEG_VERSION) -$(DOWNLOAD_PATH)/ffmpeg-$(FFMPEG_VERSION).tar.gz: - wget --no-check-certificate https://ffmpeg.org/releases/ffmpeg-$(FFMPEG_VERSION).tar.gz -O $(DOWNLOAD_PATH)/ffmpeg-$(FFMPEG_VERSION).tar.gz +$(DOWNLOAD_PATH)/ffmpeg-$(FFMPEG_VERSION).tar.xz: + wget --no-check-certificate https://ffmpeg.org/releases/ffmpeg-$(FFMPEG_VERSION).tar.xz -O $(DOWNLOAD_PATH)/ffmpeg-$(FFMPEG_VERSION).tar.xz -$(BUILD_PATH)/ffmpeg-$(FFMPEG_VERSION): $(DOWNLOAD_PATH)/ffmpeg-$(FFMPEG_VERSION).tar.gz +$(BUILD_PATH)/ffmpeg-$(FFMPEG_VERSION): $(DOWNLOAD_PATH)/ffmpeg-$(FFMPEG_VERSION).tar.xz # prepare rm -r -f $(BUILD_PATH)/ffmpeg-* - tar xvf $(DOWNLOAD_PATH)/ffmpeg-$(FFMPEG_VERSION).tar.gz + tar xvf $(DOWNLOAD_PATH)/ffmpeg-$(FFMPEG_VERSION).tar.xz # build - cd ffmpeg-$(FFMPEG_VERSION) && ./configure --disable-shared --enable-static --disable-programs --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages --disable-yasm --disable-everything --enable-encoder=mpeg4 --enable-decoder=mpeg4 --prefix="`pwd`/../$(BUILD_PATH)/ffmpeg-$(FFMPEG_VERSION).tmp" + cd ffmpeg-$(FFMPEG_VERSION) && ./configure --disable-shared --enable-static --disable-programs --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages --disable-yasm --disable-everything --enable-encoder=mpeg4 --enable-decoder=mpeg4 --prefix="`pwd`/../$(BUILD_PATH)/ffmpeg-$(FFMPEG_VERSION).tmp" cd ffmpeg-$(FFMPEG_VERSION) && make install # cleanup rm -r -f ffmpeg-$(FFMPEG_VERSION) @@ -391,8 +374,73 @@ $(BUILD_PATH)/xapian-core-$(XAPIAN_VERSION): $(DOWNLOAD_PATH)/xapian-core-$(XAPI rm -r -f xapian-core-$(XAPIAN_VERSION) mv $(BUILD_PATH)/xapian-core-$(XAPIAN_VERSION).tmp $(BUILD_PATH)/xapian-core-$(XAPIAN_VERSION) +jsonc: $(BUILD_PATH)/json-c-$(JSON_C_VERSION) + +$(BUILD_PATH)/json-c-$(JSON_C_VERSION): + # prepare + rm -r -f $(BUILD_PATH)/json-c-* + [ -d "json-c-$(JSON_C_VERSION)" ] || git clone https://github.com/json-c/json-c.git --depth=1 --branch json-c-$(JSON_C_VERSION) "json-c-$(JSON_C_VERSION)" + # build + mkdir -p json-c-$(JSON_C_VERSION)/build + cd json-c-$(JSON_C_VERSION)/build && cmake .. -G"MSYS Makefiles" -Wno-dev -DCMAKE_BUILD_TYPE="release" -DBUILD_SHARED_LIBS=off -DBUILD_STATIC_LIBS=on -DBUILD_TESTING=off -DCMAKE_CXX_FLAGS="-D__MINGW_USE_VC2005_COMPAT" -DCMAKE_INSTALL_PREFIX="`pwd`/install" -DCMAKE_INSTALL_PREFIX="`pwd`/../../$(BUILD_PATH)/json-c-$(JSON_C_VERSION).tmp" + cd json-c-$(JSON_C_VERSION)/build && make install + # cleanup + rm -r -f json-c-$(JSON_C_VERSION) + mv $(BUILD_PATH)/json-c-$(JSON_C_VERSION).tmp $(BUILD_PATH)/json-c-$(JSON_C_VERSION) + +botan: $(BUILD_PATH)/botan-$(BOTAN_VERSION) + +$(BUILD_PATH)/botan-$(BOTAN_VERSION): + # prepare + pacman --needed --noconfirm -S python3 + rm -r -f $(BUILD_PATH)/botan-* + [ -d "botan-$(BOTAN_VERSION)" ] || git clone https://github.com/randombit/botan.git --depth=1 --branch $(BOTAN_VERSION) "botan-$(BOTAN_VERSION)" + # build + if [ $(MSYSTEM) = "MINGW32" ] ; then cd botan-$(BOTAN_VERSION) && ./configure.py --os=mingw --cpu=x86_32 --disable-shared-library --enable-static-library --extra-cxxflags="-D__MINGW_USE_VC2005_COMPAT" --prefix="`pwd`/../$(BUILD_PATH)/botan-$(BOTAN_VERSION).tmp" ; fi + if [ $(MSYSTEM) = "MINGW64" ] ; then cd botan-$(BOTAN_VERSION) && ./configure.py --os=mingw --cpu=x86_64 --disable-shared-library --enable-static-library --prefix="`pwd`/../$(BUILD_PATH)/botan-$(BOTAN_VERSION).tmp" ; fi + cd botan-$(BOTAN_VERSION) && make install + # cleanup + rm -r -f botan-$(BOTAN_VERSION) + mv $(BUILD_PATH)/botan-$(BOTAN_VERSION).tmp $(BUILD_PATH)/botan-$(BOTAN_VERSION) + +asio: $(BUILD_PATH)/asio-$(ASIO_VERSION) + +$(BUILD_PATH)/asio-$(ASIO_VERSION): + # prepare + rm -r -f $(BUILD_PATH)/asio-* + [ -d "asio-$(ASIO_VERSION)" ] || git clone https://github.com/chriskohlhoff/asio.git --depth=1 --branch asio-$(ASIO_VERSION) "asio-$(ASIO_VERSION)" + # copy files + mkdir -p $(BUILD_PATH)/asio-$(ASIO_VERSION).tmp/include/asio + cp asio-$(ASIO_VERSION)/asio/include/*.hpp $(BUILD_PATH)/asio-$(ASIO_VERSION).tmp/include/ + cp -r asio-$(ASIO_VERSION)/asio/include/asio/* $(BUILD_PATH)/asio-$(ASIO_VERSION).tmp/include/asio/ + # cleanup + rm -r -f asio-$(ASIO_VERSION) + mv $(BUILD_PATH)/asio-$(ASIO_VERSION).tmp $(BUILD_PATH)/asio-$(ASIO_VERSION) + +rnp: $(BUILD_PATH)/rnp-$(RNP_VERSION) + +$(BUILD_PATH)/rnp-$(RNP_VERSION): + # prepare + rm -r -f $(BUILD_PATH)/rnp-* + [ -d "rnp-$(RNP_VERSION)" ] || git clone https://github.com/rnpgp/rnp.git --depth=1 --branch v$(RNP_VERSION) --recurse-submodules --shallow-submodules "rnp-$(RNP_VERSION)" + # build + mkdir -p rnp-$(RNP_VERSION)/build + cd rnp-$(RNP_VERSION)/build && cmake .. -G"MSYS Makefiles" -Wno-dev -DCMAKE_INSTALL_PREFIX="`pwd`/install" -DBUILD_SHARED_LIBS=yes -DBUILD_TESTING=off -DCMAKE_CXX_FLAGS="-D__MINGW_USE_VC2005_COMPAT -D__STDC_FORMAT_MACROS" -DBZIP2_INCLUDE_DIR="`pwd`/../../$(BUILD_PATH)/bzip2-$(BZIP2_VERSION)/include" -DBZIP2_LIBRARY_RELEASE="`pwd`/../../$(BUILD_PATH)/bzip2-$(BZIP2_VERSION)/lib/libbz2.a" -DBZIP2_LIBRARIES="`pwd`/../../$(BUILD_PATH)/bzip2-$(BZIP2_VERSION)/lib/libbz2.a" -DZLIB_INCLUDE_DIR="`pwd`/../../$(BUILD_PATH)/zlib-$(ZLIB_VERSION)/include" -DZLIB_LIBRARY="`pwd`/../../$(BUILD_PATH)/zlib-$(ZLIB_VERSION)/lib/libz.a" -DJSON-C_INCLUDE_DIR="`pwd`/../../$(BUILD_PATH)/json-c-$(JSON_C_VERSION)/include/json-c" -DJSON-C_LIBRARY="`pwd`/../../$(BUILD_PATH)/json-c-$(JSON_C_VERSION)/lib/libjson-c.a" -DBOTAN_INCLUDE_DIR="`pwd`/../../$(BUILD_PATH)/botan-$(BOTAN_VERSION)/include/botan-`echo $(BOTAN_VERSION) | cut -c1-1`" -DBOTAN_LIBRARY="`pwd`/../../$(BUILD_PATH)/botan-$(BOTAN_VERSION)/lib/libbotan-`echo $(BOTAN_VERSION) | cut -c1-1`.a" + cmake --build rnp-$(RNP_VERSION)/build + # copy files + mkdir -p $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/include/rnp + cp -r rnp-$(RNP_VERSION)/include/rnp/* $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/include/rnp/ + cp -r rnp-$(RNP_VERSION)/build/src/lib/rnp/* $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/include/rnp/ + mkdir -p $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/lib + cp -r rnp-$(RNP_VERSION)/build/src/lib/librnp.dll.a $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/lib/ + mkdir -p $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/bin + cp -r rnp-$(RNP_VERSION)/build/src/lib/librnp.dll $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/bin/ + # cleanup + rm -r -f rnp-$(RNP_VERSION) + mv $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp $(BUILD_PATH)/rnp-$(RNP_VERSION) + copylibs: rm -r -f $(LIBS_PATH) ; \ mkdir -p $(LIBS_PATH) ; \ - cp $(BUILD_PATH)/gcc-version $(LIBS_PATH) ; \ - find $(BUILD_PATH) -mindepth 1 -maxdepth 1 -type d -not -name "*.tmp" -print -exec cp -r {}/. $(LIBS_PATH) \; ; \ + cp -p $(BUILD_PATH)/gcc-version $(LIBS_PATH) ; \ + find $(BUILD_PATH) -mindepth 1 -maxdepth 1 -type d -not -name "*.tmp" -print -exec cp -r -p {}/. $(LIBS_PATH) \; ; \ diff --git a/build_scripts/Windows/build.bat b/build_scripts/Windows/build.bat index 9dd51cc16..90bf2ae1c 100644 --- a/build_scripts/Windows/build.bat +++ b/build_scripts/Windows/build.bat @@ -13,11 +13,11 @@ call "%~dp0build-libs\build-libs.bat" if errorlevel 1 %cecho% error "Failed to build libraries." & exit /B %ERRORLEVEL% %cecho% info "Build %SourceName%" -call "%~dp0build\build.bat" release autologin jsonapi plugins nativedialogs +call "%~dp0build\build.bat" release autologin webui plugins nativedialogs service if errorlevel 1 %cecho% error "Failed to build %SourceName%." & exit /B %ERRORLEVEL% %cecho% info "Pack %SourceName%" -call "%~dp0build\pack.bat" release plugins +call "%~dp0build\pack.bat" release webui plugins service if errorlevel 1 %cecho% error "Failed to pack %SourceName%." & exit /B %ERRORLEVEL% %cecho% info "Build installer" diff --git a/build_scripts/Windows/build/build-installer.bat b/build_scripts/Windows/build/build-installer.bat index b34e76157..7209afb6e 100644 --- a/build_scripts/Windows/build/build-installer.bat +++ b/build_scripts/Windows/build/build-installer.bat @@ -9,7 +9,7 @@ call "%EnvPath%\env.bat" if errorlevel 1 goto error_env :: Initialize environment -call "%~dp0env.bat" release +call "%~dp0env.bat" installer release if errorlevel 2 exit /B 2 if errorlevel 1 goto error_env @@ -40,6 +40,7 @@ set NSIS_PARAM=%NSIS_PARAM% /DARCHITECTURE="%GCCArchitecture%" set NSIS_PARAM=%NSIS_PARAM% /DDATE="%RsDate%" if exist "%EnvTorPath%\Tor\tor.exe" set NSIS_PARAM=%NSIS_PARAM% /DTORDIR="%EnvTorPath%\Tor" +if exist "%RsWebuiBuildPath%" set NSIS_PARAM=%NSIS_PARAM% /DWEBUIDIR="%RsWebuiBuildPath%" :: Get compiled version call "%ToolsPath%\get-rs-version.bat" "%RsBuildPath%\retroshare-gui\src\%RsBuildConfig%\retroshare.exe" RsVersion diff --git a/build_scripts/Windows/build/build.bat b/build_scripts/Windows/build/build.bat index 095fc6081..91ff71382 100644 --- a/build_scripts/Windows/build/build.bat +++ b/build_scripts/Windows/build/build.bat @@ -9,7 +9,7 @@ call "%EnvPath%\env.bat" if errorlevel 1 goto error_env :: Initialize environment -call "%~dp0env.bat" %* +call "%~dp0env.bat" build %* if errorlevel 2 exit /B 2 if errorlevel 1 goto error_env @@ -49,11 +49,15 @@ echo. title Build - %SourceName%-%RsBuildConfig% [qmake] -set RS_QMAKE_CONFIG=%RsBuildConfig% no_rs_cppwarning +set RS_QMAKE_CONFIG=%RsBuildConfig% if "%ParamAutologin%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% rs_autologin if "%ParamJsonApi%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% rs_jsonapi +if "%ParamWebui%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% rs_webui if "%ParamPlugins%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% retroshare_plugins if "%ParamUseNativeDialogs%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% rs_use_native_dialogs +if "%ParamService%" NEQ "1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% no_retroshare_service +if "%ParamFriendServer%" NEQ "1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% no_retroshare_friendserver +if "%ParamEmbeddedFriendServer%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% rs_efs qmake "%SourcePath%\RetroShare.pro" -r -spec win32-g++ "CONFIG+=%RS_QMAKE_CONFIG%" "EXTERNAL_LIB_DIR=%BuildLibsPath%\libs" if errorlevel 1 goto error diff --git a/build_scripts/Windows/build/clean.bat b/build_scripts/Windows/build/clean.bat index e8d5aa7b8..4ab752d4d 100644 --- a/build_scripts/Windows/build/clean.bat +++ b/build_scripts/Windows/build/clean.bat @@ -8,7 +8,7 @@ if errorlevel 1 goto error_env call "%EnvPath%\env.bat" if errorlevel 1 goto error_env -call "%~dp0env.bat" %* +call "%~dp0env.bat" clean %* if errorlevel 2 exit /B 2 if errorlevel 1 goto error_env diff --git a/build_scripts/Windows/build/env.bat b/build_scripts/Windows/build/env.bat index 883077173..98f70c87f 100644 --- a/build_scripts/Windows/build/env.bat +++ b/build_scripts/Windows/build/env.bat @@ -4,11 +4,18 @@ set ParamDebug=0 set ParamAutologin=0 set ParamPlugins=0 set ParamJsonApi=0 +set ParamWebui=0 +set ParamService=0 +set ParamFriendServer=0 +set ParamEmbeddedFriendServer=0 set ParamUseNativeDialogs=0 set ParamTor=0 set NonInteractive=0 set CoreCount=%NUMBER_OF_PROCESSORS% +set Module=%~1 +shift /1 + :parameter_loop if "%~1" NEQ "" ( for /f "tokens=1,2 delims==" %%a in ("%~1") do ( @@ -20,6 +27,15 @@ if "%~1" NEQ "" ( set ParamAutologin=1 ) else if "%%~a"=="jsonapi" ( set ParamJsonApi=1 + ) else if "%%~a"=="webui" ( + set ParamJsonApi=1 + set ParamWebui=1 + ) else if "%%~a"=="service" ( + set ParamService=1 + ) else if "%%~a"=="friendserver" ( + set ParamFriendServer=1 + ) else if "%%~a"=="embedded-friendserver" ( + set ParamEmbeddedFriendServer=1 ) else if "%%~a"=="plugins" ( set ParamPlugins=1 ) else if "%%~a"=="tor" ( @@ -32,7 +48,7 @@ if "%~1" NEQ "" ( set ParamUseNativeDialogs=1 ) else ( echo. - echo Unknown parameter %1 + echo Unknown parameter %1 for %Module% goto :usage ) ) @@ -89,6 +105,7 @@ set RsBuildPath=%BuildPath%\Qt-%QtVersion%-%GCCArchitecture%-%RsBuildConfig% set RsDeployPath=%DeployPath%\Qt-%QtVersion%-%GCCArchitecture%%RsType%-%RsBuildConfig% set RsPackPath=%DeployPath% set RsArchiveAdd= +set RsWebuiBuildPath=%RsBuildPath%\retroshare-webui\webui if not exist "%~dp0env-mod.bat" goto no_mod call "%~dp0env-mod.bat" @@ -102,21 +119,33 @@ echo. echo Usage: release^|debug [^] echo. echo Mandatory parameter -echo release^|debug Build release or debug version +echo release^|debug Build release or debug version echo. -echo Optional parameter (need clean when changed) -echo autologin Build with autologin -echo jsonapi Build with jsonapi -echo plugins Build plugins -echo nativedialogs Build with native dialogs -echo. -echo Optional parameter -echo singlethread Use only 1 thread for building -echo. -echo Parameter for pack -echo tor Pack tor version -echo. -echo Parameter for git-log -echo non-interactive Non-interactive mode +if "%Module%"=="build" ( + echo Optional parameter ^(need clean when changed^) + echo autologin Build with autologin + echo jsonapi Build with jsonapi + echo webui Build with jsonapi and webui + echo service Build service + echo friendserver Build Friend Server + echo embedded-friendserver Build with embedded Friend Server + echo plugins Build plugins + echo nativedialogs Build with native dialogs + echo. + echo Optional parameter + echo singlethread Use only 1 thread for building +) +if "%Module%"=="pack" ( + echo Optional parameter + echo webui Pack webui + echo service Pack service + echo friendserver Pack Friend Server ^(needs Tor^) + echo tor Pack Tor version + echo plugins Pack plugins +) +if "%Module%"=="git-log" ( + echo Optional parameter + echo non-interactive Non-interactive mode +) echo. exit /B 2 diff --git a/build_scripts/Windows/build/git-log.bat b/build_scripts/Windows/build/git-log.bat index 4d479fc3f..b2328d853 100644 --- a/build_scripts/Windows/build/git-log.bat +++ b/build_scripts/Windows/build/git-log.bat @@ -8,7 +8,7 @@ if errorlevel 1 goto error_env call "%EnvPath%\env.bat" if errorlevel 1 goto error_env -call "%~dp0env.bat" %* +call "%~dp0env.bat" git-log %* if errorlevel 2 exit /B 2 if errorlevel 1 goto error_env @@ -88,6 +88,10 @@ echo %RsRef%>"%RsLastRefFile%" exit /B %ERRORLEVEL% +:error +%cecho% error "\n%~n0 failed\n" +exit /B 1 + :error_env echo Failed to initialize environment. endlocal diff --git a/build_scripts/Windows/build/pack.bat b/build_scripts/Windows/build/pack.bat index 8a82f35e3..ff347babf 100644 --- a/build_scripts/Windows/build/pack.bat +++ b/build_scripts/Windows/build/pack.bat @@ -11,7 +11,7 @@ call "%EnvPath%\env.bat" if errorlevel 1 goto error_env :: Initialize environment -call "%~dp0env.bat" %* +call "%~dp0env.bat" pack %* if errorlevel 2 exit /B 2 if errorlevel 1 goto error_env @@ -95,8 +95,23 @@ copy nul "%RsDeployPath%\portable" %Quite% echo copy binaries copy "%RsBuildPath%\retroshare-gui\src\%RsBuildConfig%\retroshare*.exe" "%RsDeployPath%" %Quite% -copy "%RsBuildPath%\retroshare-service\src\%RsBuildConfig%\retroshare*-service.exe" "%RsDeployPath%" %Quite% if exist "%RsBuildPath%\libretroshare\src\lib\retroshare.dll" copy "%RsBuildPath%\libretroshare\src\lib\retroshare.dll" "%RsDeployPath%" %Quite% +if exist "%RsBuildPath%\supportlibs\librnp\Build\src\lib\librnp.dll" copy "%RsBuildPath%\supportlibs\librnp\Build\src\lib\librnp.dll" "%RsDeployPath%" %Quite% + +if "%ParamService%"=="1" ( + copy "%RsBuildPath%\retroshare-service\src\%RsBuildConfig%\retroshare*-service.exe" "%RsDeployPath%" %Quite% + if errorlevel 1 %cecho% error "Service not found"& goto error +) + +if "%ParamFriendServer%"=="1" ( + if "%ParamTor%"=="1" ( + copy "%RsBuildPath%\retroshare-friendserver\src\%RsBuildConfig%\retroshare-friendserver.exe" "%RsDeployPath%" %Quite% + if errorlevel 1 %cecho% error "Friend Server not found"& goto error + ) else ( + %cecho% error "Friend Server needs Tor" + goto error + ) +) echo copy extensions if "%ParamPlugins%"=="1" ( @@ -132,8 +147,10 @@ if exist "%QtPath%\..\plugins\styles\qwindowsvistastyle.dll" ( copy "%QtPath%\..\plugins\imageformats\*.dll" "%RsDeployPath%\imageformats" %Quite% del /Q "%RsDeployPath%\imageformats\*d?.dll" %Quite% -echo copy qss -xcopy /S "%SourcePath%\retroshare-gui\src\qss" "%RsDeployPath%\qss" %Quite% +if exist "%SourcePath%\retroshare-gui\src\qss" ( + echo copy qss + xcopy /S "%SourcePath%\retroshare-gui\src\qss" "%RsDeployPath%\qss" %Quite% +) echo copy stylesheets xcopy /S "%SourcePath%\retroshare-gui\src\gui\qss\chat" "%RsDeployPath%\stylesheets" %Quite% @@ -165,15 +182,17 @@ copy "%SourcePath%\libbitdht\src\bitdht\bdboot.txt" "%RsDeployPath%" %Quite% echo copy changelog.txt copy "%RsBuildPath%\changelog.txt" "%RsDeployPath%" %Quite% -if exist "%SourcePath%\libresapi\src\webui" ( +if defined ParamWebui ( echo copy webui mkdir "%RsDeployPath%\webui" - xcopy /S "%SourcePath%\libresapi\src\webui" "%RsDeployPath%\webui" %Quite% + xcopy /S "%RsWebuiBuildPath%" "%RsDeployPath%\webui" %Quite% + if errorlevel 1 %cecho% error "WebUi not found"& goto error ) if "%ParamTor%"=="1" ( echo copy tor - echo n | copy /-y "%EnvTorPath%\Tor\*.*" "%RsDeployPath%" %Quite% + if not exist "%RsDeployPath%\tor" mkdir "%RsDeployPath%\tor" + echo n | copy /-y "%EnvTorPath%\Tor\*.*" "%RsDeployPath%\tor" %Quite% ) rem pack files diff --git a/build_scripts/Windows/env/env-msys2.bat b/build_scripts/Windows/env/env-msys2.bat index b99ede679..47dd8d96a 100644 --- a/build_scripts/Windows/env/env-msys2.bat +++ b/build_scripts/Windows/env/env-msys2.bat @@ -5,7 +5,6 @@ call "%~dp0env.bat" if errorlevel 1 goto error_env -rem openssl x86 doesn't compile with mingw64 x64 :: Get gcc versions call "%ToolsPath%\get-gcc-version.bat" GCCVersion GCCArchitecture if "%GCCVersion%"=="" %cecho% error "Cannot get gcc version." & exit /B 1 @@ -23,11 +22,12 @@ if "%GCCArchitecture%"=="x64" ( ) set EnvMSYS2Path=%EnvRootPath%\msys2 +set EnvMSYS2BasePath=%EnvMSYS2Path%\msys64 call "%~dp0tools\prepare-msys2.bat" %1 if errorlevel 1 exit /B %ERRORLEVEL% -set EnvMSYS2SH=%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\sh.exe +set EnvMSYS2SH=%EnvMSYS2BasePath%\usr\bin\sh.exe if not exist "%EnvMSYS2SH%" if errorlevel 1 goto error_env set EnvMSYS2Cmd="%EnvMSYS2SH%" -lc diff --git a/build_scripts/Windows/env/env.bat b/build_scripts/Windows/env/env.bat index bc95045b0..185a421a9 100644 --- a/build_scripts/Windows/env/env.bat +++ b/build_scripts/Windows/env/env.bat @@ -28,6 +28,9 @@ if errorlevel 1 exit /B %ERRORLEVEL% set PATH=%EnvToolsPath%\MinGit\cmd;%EnvToolsPath%\cmake\bin;%PATH% set HOME=%EnvToolsPath%\MinGit\home +:: Add Doxygen to PATH +set PATH=%EnvToolsPath%\doxygen;%PATH% + exit /B 0 :error_env diff --git a/build_scripts/Windows/env/tools/prepare-msys2.bat b/build_scripts/Windows/env/tools/prepare-msys2.bat index 0a649ae0e..ba2f12ce6 100644 --- a/build_scripts/Windows/env/tools/prepare-msys2.bat +++ b/build_scripts/Windows/env/tools/prepare-msys2.bat @@ -16,7 +16,15 @@ if "%~1"=="clean" ( goto exit ) -if exist "%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\pacman.exe" ( +set MSYS2Version=20241208 + +set MSYS2Install=msys2-base-x86_64-%MSYS2Version%.sfx.exe +set MSYS2Url=https://github.com/msys2/msys2-installer/releases/download/%MSYS2Version:~0,4%-%MSYS2Version:~4,2%-%MSYS2Version:~6,2%/%MSYS2Install% +set MSYS2UnpackPath=%EnvMSYS2Path%\msys64 +set CMakeInstall=cmake-3.31.3-windows-i386.zip +set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.31.3/%CMakeInstall% + +if exist "%MSYS2UnpackPath%\usr\bin\pacman.exe" ( if "%~1"=="reinstall" ( choice /M "Found existing MSYS2 version. Do you want to proceed?" if !ERRORLEVEL!==2 goto exit @@ -25,18 +33,12 @@ if exist "%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\pacman.exe" ( ) ) -set MSYS2Install=msys2-base-%MSYS2Architecture%-20190524.tar.xz -set MSYS2Url=http://sourceforge.net/projects/msys2/files/Base/%MSYS2Architecture%/%MSYS2Install%/download -set CMakeInstall=cmake-3.19.0-win32-x86.zip -set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.19.0/%CMakeInstall% -set CMakeUnpackPath=%EnvMSYS2Path%\msys%MSYS2Base% - -if exist "%EnvMSYS2Path%\msys%MSYS2Base%" ( +if exist "%MSYS2UnpackPath%" ( %cecho% info "Remove previous MSYS2 version" - call "%ToolsPath%\remove-dir.bat" "%EnvMSYS2Path%\msys%MSYS2Base%" + call "%ToolsPath%\remove-dir.bat" "%MSYS2UnpackPath%" ) -%cecho% info "Download installation files" +%cecho% info "Download MSYS2 installation files" if not exist "%EnvDownloadPath%\%MSYS2Install%" call "%ToolsPath%\download-file.bat" "%MSYS2Url%" "%EnvDownloadPath%\%MSYS2Install%" if not exist "%EnvDownloadPath%\%MSYS2Install%" %cecho% error "Cannot download MSYS" & goto error @@ -44,37 +46,32 @@ if not exist "%EnvDownloadPath%\%CMakeInstall%" call "%ToolsPath%\download-file. if not exist "%EnvDownloadPath%\%CMakeInstall%" %cecho% error "Cannot download CMake" & goto error %cecho% info "Unpack MSYS2" -"%EnvSevenZipExe%" x -so "%EnvDownloadPath%\%MSYS2Install%" | "%EnvSevenZipExe%" x -y -si -ttar -o"%EnvMSYS2Path%" +"%EnvDownloadPath%\%MSYS2Install%" -y -o"%EnvMSYS2Path%" %cecho% info "Unpack CMake" -"%EnvSevenZipExe%" x -o"%CMakeUnpackPath%" "%EnvDownloadPath%\%CMakeInstall%" +"%EnvSevenZipExe%" x -o"%MSYS2UnpackPath%" "%EnvDownloadPath%\%CMakeInstall%" -y -bso0 %cecho% info "Install CMake" set CMakeVersion= -for /D %%F in (%CMakeUnpackPath%\cmake*) do set CMakeVersion=%%~nxF +for /D %%F in (%MSYS2UnpackPath%\cmake*) do set CMakeVersion=%%~nxF if "%CMakeVersion%"=="" %cecho% error "CMake version not found." & goto :exit %cecho% info "Found CMake version %CMakeVersion%" set FoundProfile= -for /f "tokens=3" %%F in ('find /c /i "%CMakeVersion%" "%EnvMSYS2Path%\msys%MSYS2Base%\etc\profile"') do set FoundProfile=%%F +for /f "tokens=3" %%F in ('find /c /i "%CMakeVersion%" "%MSYS2UnpackPath%\etc\profile"') do set FoundProfile=%%F if "%FoundProfile%"=="0" ( - echo export PATH="${PATH}:/%CMakeVersion%/bin">>"%EnvMSYS2Path%\msys%MSYS2Base%\etc\profile" + echo export PATH="${PATH}:/%CMakeVersion%/bin">>"%MSYS2UnpackPath%\etc\profile" ) -set MSYS2SH=%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\sh - -%cecho% info "Update keyring" -"%MSYS2SH%" -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" -"%MSYS2SH%" -lc "pacman --noconfirm -U msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" +set MSYS2SH=%MSYS2UnpackPath%\usr\bin\sh %cecho% info "Initialize MSYS2" -"%MSYS2SH%" -lc "pacman -Sy" -"%MSYS2SH%" -lc "pacman --noconfirm --needed -S bash pacman pacman-mirrors msys2-runtime" +"%MSYS2SH%" -lc "yes | pacman --noconfirm -Syuu msys2-keyring" +"%MSYS2SH%" -lc "pacman --noconfirm -Sy" +"%MSYS2SH%" -lc "pacman --noconfirm -Su" -call "%EnvMSYS2Path%\msys%MSYS2Base%\autorebase.bat" -call "%EnvRootPath%\update-msys2.bat" -call "%EnvRootPath%\update-msys2.bat" +call "%MSYS2UnpackPath%\autorebase.bat" :exit endlocal diff --git a/build_scripts/Windows/env/tools/prepare-tools.bat b/build_scripts/Windows/env/tools/prepare-tools.bat index d53a70cf6..f088acfa8 100644 --- a/build_scripts/Windows/env/tools/prepare-tools.bat +++ b/build_scripts/Windows/env/tools/prepare-tools.bat @@ -16,9 +16,12 @@ set NSISInstallPath=%EnvToolsPath%\NSIS set MinGitInstall=MinGit-2.28.0-32-bit.zip set MinGitUrl=https://github.com/git-for-windows/git/releases/download/v2.28.0.windows.1/%MinGitInstall% set MinGitInstallPath=%EnvToolsPath%\MinGit -set CMakeVersion=cmake-3.19.0-win32-x86 +set DoxygenInstall=doxygen-1.9.6.windows.x64.bin.zip +set DoxygenUrl=https://github.com/doxygen/doxygen/releases/download/Release_1_9_6/%DoxygenInstall% +set DoxygenInstallPath=%EnvToolsPath%\doxygen +set CMakeVersion=cmake-3.31.3-windows-i386 set CMakeInstall=%CMakeVersion%.zip -set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.19.0/%CMakeInstall% +set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.31.3/%CMakeInstall% set CMakeInstallPath=%EnvToolsPath%\cmake set TorProjectUrl=https://www.torproject.org set TorDownloadIndexUrl=%TorProjectUrl%/download/tor @@ -50,7 +53,7 @@ if not exist "%EnvToolsPath%\cecho.exe" ( if not exist "%EnvDownloadPath%\%cCEhoInstall%" echo Cannot download cecho installation& goto error echo Unpack cecho - "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%CEchoInstall%" + "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%CEchoInstall%" -y -bso0 copy "%EnvTempPath%\cecho.exe" "%EnvToolsPath%" call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%" @@ -66,7 +69,7 @@ if not exist "%EnvToolsPath%\depends.exe" ( if not exist "%EnvDownloadPath%\%DependsInstall%" %cecho% error "Cannot download Dependendy Walker installation" & goto error %cecho% info "Unpack Dependency Walker" - "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%DependsInstall%" + "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%DependsInstall%" -y -bso0 copy "%EnvTempPath%\*" "%EnvToolsPath%" call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%" @@ -82,7 +85,7 @@ if not exist "%EnvToolsPath%\cut.exe" ( if not exist "%EnvDownloadPath%\%UnixToolsInstall%" %cecho% error "Cannot download Unix Tools installation" & goto error %cecho% info "Unpack Unix Tools" - "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%UnixToolsInstall%" + "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%UnixToolsInstall%" -y -bso0 copy "%EnvTempPath%\cut.exe" "%EnvToolsPath%" call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%" @@ -98,7 +101,7 @@ if not exist "%EnvToolsPath%\sed.exe" ( if not exist "%EnvDownloadPath%\%UnixToolsInstall%" %cecho% error "Cannot download Unix Tools installation" & goto error %cecho% info "Unpack Unix Tools" - "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%UnixToolsInstall%" + "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%UnixToolsInstall%" -y -bso0 copy "%EnvTempPath%\sed.exe" "%EnvToolsPath%" call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%" @@ -118,7 +121,7 @@ if not exist "%NSISInstallPath%\nsis.exe" ( if not exist "%EnvDownloadPath%\%NSISInstall%" %cecho% error "Cannot download NSIS installation" & goto error %cecho% info "Unpack NSIS" - "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%NSISInstall%" + "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%NSISInstall%" -y -bso0 if not exist "%NSISInstallPath%" mkdir "%NSISInstallPath%" xcopy /s "%EnvTempPath%" "%NSISInstallPath%" @@ -132,7 +135,20 @@ if not exist "%MinGitInstallPath%\cmd\git.exe" ( if not exist "%EnvDownloadPath%\%MinGitInstall%" %cecho% error "Cannot download MinGit installation" & goto error %cecho% info "Unpack MinGit" - "%EnvSevenZipExe%" x -o"%MinGitInstallPath%" "%EnvDownloadPath%\%MinGitInstall%" + "%EnvSevenZipExe%" x -o"%MinGitInstallPath%" "%EnvDownloadPath%\%MinGitInstall%" -y -bso0 +) + +if not exist "%EnvDownloadPath%\%DoxygenInstall%" call "%ToolsPath%\remove-dir.bat" "%DoxygenInstallPath%" +if not exist "%DoxygenInstallPath%\doxygen.exe" ( + if exist "%DoxygenInstallPath%" call "%ToolsPath%\remove-dir.bat" "%DoxygenInstallPath%" + + %cecho% info "Download Doxygen installation" + + if not exist "%EnvDownloadPath%\%DoxygenInstall%" call "%ToolsPath%\download-file.bat" "%DoxygenUrl%" "%EnvDownloadPath%\%DoxygenInstall%" + if not exist "%EnvDownloadPath%\%DoxygenInstall%" %cecho% error "Cannot download doxygen installation" & goto error + + %cecho% info "Unpack Doxygen" + "%EnvSevenZipExe%" x -o"%DoxygenInstallPath%" "%EnvDownloadPath%\%DoxygenInstall%" -y -bso0 ) if not exist "%EnvDownloadPath%\%CMakeInstall%" call "%ToolsPath%\remove-dir.bat" "%CMakeInstallPath%" @@ -147,7 +163,7 @@ if not exist "%CMakeInstallPath%\bin\cmake.exe" ( if not exist "%EnvDownloadPath%\%CMakeInstall%" %cecho% error "Cannot download CMake installation" & goto error %cecho% info "Unpack CMake" - "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%CMakeInstall%" + "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%CMakeInstall%" -y -bso0 move "%EnvTempPath%\%CMakeVersion%" "%CMakeInstallPath%" @@ -160,7 +176,7 @@ mkdir "%EnvTempPath%" call "%ToolsPath%\download-file.bat" "%TorDownloadIndexUrl%" "%EnvTempPath%\index.html" if not exist "%EnvTempPath%\index.html" %cecho% error "Cannot download Tor installation" & goto error -for /F "tokens=1,2 delims= " %%A in ('%EnvSedExe% -r -n -e"s/.*href=\"^(.*^)^(tor-win32.*\.zip^)\".*/\2 \1\2/p" "%EnvTempPath%\index.html"') do set TorInstall=%%A& set TorDownloadUrl=%TorProjectUrl%%%B +for /F "tokens=1,2 delims= " %%A in ('%EnvSedExe% -r -n -e"s/.*href=\"^(.*^)^(tor-.*windows-i686.*\.tar\.gz^)\".*/\2 \1\2/p" "%EnvTempPath%\index.html"') do set TorInstall=%%A& set TorDownloadUrl=%%B call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%" if "%TorInstall%"=="" %cecho% error "Cannot download Tor installation" & goto error if "%TorDownloadUrl%"=="" %cecho% error "Cannot download Tor installation" & goto error @@ -173,7 +189,7 @@ if not exist "%EnvTorPath%\Tor\tor.exe" ( if not exist "%EnvDownloadPath%\%TorInstall%" %cecho% error "Cannot download Tor installation" & goto error %cecho% info "Unpack Tor" - "%EnvSevenZipExe%" x -o"%EnvTorPath%" "%EnvDownloadPath%\%TorInstall%" + "%EnvSevenZipExe%" x -so "%EnvDownloadPath%\%TorInstall%" | "%EnvSevenZipExe%" x -si -ttar -o"%EnvTorPath%" -y -bso0 ) :exit diff --git a/build_scripts/Windows/env/tools/root/update-msys2.bat b/build_scripts/Windows/env/tools/root/update-msys2.bat index 3075e392b..ddd5bdd0f 100644 --- a/build_scripts/Windows/env/tools/root/update-msys2.bat +++ b/build_scripts/Windows/env/tools/root/update-msys2.bat @@ -2,18 +2,13 @@ setlocal -if exist "%~dp0msys2\msys32" call :update 32 -if exist "%~dp0msys2\msys64" call :update 64 +if not exist "%~dp0msys2\msys64" goto :EOF -goto :EOF +set MSYS2SH=%~dp0msys2\msys64\usr\bin\sh -:update -set MSYSSH=%~dp0msys2\msys%~1\usr\bin\sh +echo Update MSYS2 +"%MSYS2SH%" -lc "yes | pacman --noconfirm -Syuu msys2-keyring" +"%MSYS2SH%" -lc "pacman --noconfirm -Su" -echo Update MSYS2 %~1 -"%MSYSSH%" -lc "pacman -Sy" -"%MSYSSH%" -lc "pacman --noconfirm -Su" - -:exit endlocal goto :EOF diff --git a/build_scripts/Windows/installer/lang/ca_ES.nsh b/build_scripts/Windows/installer/lang/ca_ES.nsh index 74f92ffe5..4279f8174 100644 --- a/build_scripts/Windows/installer/lang/ca_ES.nsh +++ b/build_scripts/Windows/installer/lang/ca_ES.nsh @@ -2,6 +2,12 @@ !insertmacro LANG_STRING Section_Main_Desc "Instal·la ${APPNAME} i els components necessaris." !insertmacro LANG_STRING Section_Tor "Tor" !insertmacro LANG_STRING Section_Tor_Desc "Installs Tor." +!insertmacro LANG_STRING Section_WebUI "WebUI" +!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI." +!insertmacro LANG_STRING Section_Service "Service" +!insertmacro LANG_STRING Section_Service_Desc "Installs Service." +!insertmacro LANG_STRING Section_FriendServer "Friend Server" +!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server." !insertmacro LANG_STRING Section_Data "Pells" !insertmacro LANG_STRING Section_Data_Desc "Instal·la pells." !insertmacro LANG_STRING Section_Shortcuts "Icones d'accés directe" diff --git a/build_scripts/Windows/installer/lang/de.nsh b/build_scripts/Windows/installer/lang/de.nsh index 663e9e786..d67eb3e6f 100644 --- a/build_scripts/Windows/installer/lang/de.nsh +++ b/build_scripts/Windows/installer/lang/de.nsh @@ -2,6 +2,12 @@ !insertmacro LANG_STRING Section_Main_Desc "Installiert ${APPNAME} und die benötigten Komponenten." !insertmacro LANG_STRING Section_Tor "Tor" !insertmacro LANG_STRING Section_Tor_Desc "Installiert Tor." +!insertmacro LANG_STRING Section_WebUI "WebUI" +!insertmacro LANG_STRING Section_WebUI_Desc "Installiert WebUI." +!insertmacro LANG_STRING Section_Service "Service" +!insertmacro LANG_STRING Section_Service_Desc "Installiert Service." +!insertmacro LANG_STRING Section_FriendServer "Friend Server" +!insertmacro LANG_STRING Section_FriendServer_Desc "Installiert Friend Server." !insertmacro LANG_STRING Section_Data "Skins" !insertmacro LANG_STRING Section_Data_Desc "Skins installieren." !insertmacro LANG_STRING Section_Shortcuts "Verknüpfungssymbole" diff --git a/build_scripts/Windows/installer/lang/en.nsh b/build_scripts/Windows/installer/lang/en.nsh index a709eec24..7ecb92979 100644 --- a/build_scripts/Windows/installer/lang/en.nsh +++ b/build_scripts/Windows/installer/lang/en.nsh @@ -2,6 +2,12 @@ !insertmacro LANG_STRING Section_Main_Desc "Installs ${APPNAME} and required components." !insertmacro LANG_STRING Section_Tor "Tor" !insertmacro LANG_STRING Section_Tor_Desc "Installs Tor." +!insertmacro LANG_STRING Section_WebUI "WebUI" +!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI." +!insertmacro LANG_STRING Section_Service "Service" +!insertmacro LANG_STRING Section_Service_Desc "Installs Service." +!insertmacro LANG_STRING Section_FriendServer "Friend Server" +!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server." !insertmacro LANG_STRING Section_Data "Skins" !insertmacro LANG_STRING Section_Data_Desc "Installs skins." !insertmacro LANG_STRING Section_Shortcuts "Shortcut icons" diff --git a/build_scripts/Windows/installer/lang/es.nsh b/build_scripts/Windows/installer/lang/es.nsh index 66021c14e..5f0a8aeee 100644 --- a/build_scripts/Windows/installer/lang/es.nsh +++ b/build_scripts/Windows/installer/lang/es.nsh @@ -2,6 +2,12 @@ !insertmacro LANG_STRING Section_Main_Desc "Instala ${APPNAME} y los componentes requeridos." !insertmacro LANG_STRING Section_Tor "Tor" !insertmacro LANG_STRING Section_Tor_Desc "Installs Tor." +!insertmacro LANG_STRING Section_WebUI "WebUI" +!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI." +!insertmacro LANG_STRING Section_Service "Service" +!insertmacro LANG_STRING Section_Service_Desc "Installs Service." +!insertmacro LANG_STRING Section_FriendServer "Friend Server" +!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server." !insertmacro LANG_STRING Section_Data "Coberturas (skins)" !insertmacro LANG_STRING Section_Data_Desc "Instalar coberturas" !insertmacro LANG_STRING Section_Shortcuts "Iconos de accesos directos" diff --git a/build_scripts/Windows/installer/lang/fr.nsh b/build_scripts/Windows/installer/lang/fr.nsh index 680746da0..e55ca2466 100644 --- a/build_scripts/Windows/installer/lang/fr.nsh +++ b/build_scripts/Windows/installer/lang/fr.nsh @@ -2,6 +2,12 @@ !insertmacro LANG_STRING Section_Main_Desc "Installe ${APPNAME} et les composants requis." !insertmacro LANG_STRING Section_Tor "Tor" !insertmacro LANG_STRING Section_Tor_Desc "Installs Tor." +!insertmacro LANG_STRING Section_WebUI "WebUI" +!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI." +!insertmacro LANG_STRING Section_Service "Service" +!insertmacro LANG_STRING Section_Service_Desc "Installs Service." +!insertmacro LANG_STRING Section_FriendServer "Friend Server" +!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server." !insertmacro LANG_STRING Section_Data "Habillages" !insertmacro LANG_STRING Section_Data_Desc "Installe des habillages." !insertmacro LANG_STRING Section_Shortcuts "Icônes de raccourci" diff --git a/build_scripts/Windows/installer/lang/pl.nsh b/build_scripts/Windows/installer/lang/pl.nsh index 53fc42934..44b3b70a1 100644 --- a/build_scripts/Windows/installer/lang/pl.nsh +++ b/build_scripts/Windows/installer/lang/pl.nsh @@ -2,6 +2,12 @@ !insertmacro LANG_STRING Section_Main_Desc "Instaluje ${APPNAME} oraz wymagane komponenty." !insertmacro LANG_STRING Section_Tor "Tor" !insertmacro LANG_STRING Section_Tor_Desc "Installs Tor." +!insertmacro LANG_STRING Section_WebUI "WebUI" +!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI." +!insertmacro LANG_STRING Section_Service "Service" +!insertmacro LANG_STRING Section_Service_Desc "Installs Service." +!insertmacro LANG_STRING Section_FriendServer "Friend Server" +!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server." !insertmacro LANG_STRING Section_Data "Skórki" !insertmacro LANG_STRING Section_Data_Desc "Instaluje skórki." !insertmacro LANG_STRING Section_Shortcuts "Ikony skrótów" diff --git a/build_scripts/Windows/installer/lang/ru.nsh b/build_scripts/Windows/installer/lang/ru.nsh index b8ba2df89..969d58629 100644 --- a/build_scripts/Windows/installer/lang/ru.nsh +++ b/build_scripts/Windows/installer/lang/ru.nsh @@ -2,6 +2,12 @@ !insertmacro LANG_STRING Section_Main_Desc "Установка ${APPNAME} и необходимых компонентов." !insertmacro LANG_STRING Section_Tor "Tor" !insertmacro LANG_STRING Section_Tor_Desc "Installs Tor." +!insertmacro LANG_STRING Section_WebUI "WebUI" +!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI." +!insertmacro LANG_STRING Section_Service "Service" +!insertmacro LANG_STRING Section_Service_Desc "Installs Service." +!insertmacro LANG_STRING Section_FriendServer "Friend Server" +!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server." !insertmacro LANG_STRING Section_Data "Оболочки" !insertmacro LANG_STRING Section_Data_Desc "Установка оболочек." !insertmacro LANG_STRING Section_Shortcuts "Ярлыки" diff --git a/build_scripts/Windows/installer/lang/tr.nsh b/build_scripts/Windows/installer/lang/tr.nsh index 85abeaac2..70a475a86 100644 --- a/build_scripts/Windows/installer/lang/tr.nsh +++ b/build_scripts/Windows/installer/lang/tr.nsh @@ -2,6 +2,12 @@ !insertmacro LANG_STRING Section_Main_Desc "${APPNAME} ve gerekli bileşenleri kurar." !insertmacro LANG_STRING Section_Tor "Tor" !insertmacro LANG_STRING Section_Tor_Desc "Installs Tor." +!insertmacro LANG_STRING Section_WebUI "WebUI" +!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI." +!insertmacro LANG_STRING Section_Service "Service" +!insertmacro LANG_STRING Section_Service_Desc "Installs Service." +!insertmacro LANG_STRING Section_FriendServer "Friend Server" +!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server." !insertmacro LANG_STRING Section_Data "Temalar" !insertmacro LANG_STRING Section_Data_Desc "Tema yükleyin." !insertmacro LANG_STRING Section_Shortcuts "Kısayol simgeleri" diff --git a/build_scripts/Windows/installer/lang/ts/en.ts b/build_scripts/Windows/installer/lang/ts/en.ts index e95f6939f..cb38b6d94 100644 --- a/build_scripts/Windows/installer/lang/ts/en.ts +++ b/build_scripts/Windows/installer/lang/ts/en.ts @@ -22,6 +22,48 @@ + + Section_WebUI + + WebUI + + + + + Section_WebUI_Desc + + Installs WebUI. + + + + + Section_Service + + Service + + + + + Section_Service_Desc + + Installs Service. + + + + + Section_FriendServer + + Friend Server + + + + + Section_FriendServer_Desc + + Installs Friend Server. + + + Section_Data diff --git a/build_scripts/Windows/installer/lang/zh_CN.nsh b/build_scripts/Windows/installer/lang/zh_CN.nsh index 330de33ab..7d9a3cc02 100644 --- a/build_scripts/Windows/installer/lang/zh_CN.nsh +++ b/build_scripts/Windows/installer/lang/zh_CN.nsh @@ -2,6 +2,12 @@ !insertmacro LANG_STRING Section_Main_Desc "Installs ${APPNAME} and required components." !insertmacro LANG_STRING Section_Tor "Tor" !insertmacro LANG_STRING Section_Tor_Desc "Installs Tor." +!insertmacro LANG_STRING Section_WebUI "WebUI" +!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI." +!insertmacro LANG_STRING Section_Service "Service" +!insertmacro LANG_STRING Section_Service_Desc "Installs Service." +!insertmacro LANG_STRING Section_FriendServer "Friend Server" +!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server." !insertmacro LANG_STRING Section_Data "皮肤" !insertmacro LANG_STRING Section_Data_Desc "安装皮肤" !insertmacro LANG_STRING Section_Shortcuts "快捷方式图标" diff --git a/build_scripts/Windows/installer/retroshare-Qt5.nsi b/build_scripts/Windows/installer/retroshare-Qt5.nsi index a6ebbc81b..c7a5b9554 100644 --- a/build_scripts/Windows/installer/retroshare-Qt5.nsi +++ b/build_scripts/Windows/installer/retroshare-Qt5.nsi @@ -60,6 +60,9 @@ !define /date DATE "%Y%m%d" !endif +# Service +${!defineifexist} SERVICE_EXISTS "${RELEASEDIR}\retroshare-service\src\release\retroshare-service.exe" + # Tor !ifdef TORDIR ${!defineifexist} TOR_EXISTS "${TORDIR}\tor.exe" @@ -68,6 +71,20 @@ ${!defineifexist} TOR_EXISTS "${TORDIR}\tor.exe" !endif !endif +# WebUI +!ifdef WEBUIDIR +${!defineifexist} WEBUI_EXISTS "${WEBUIDIR}\index.html" +!ifndef WEBUI_EXISTS +!error "WebUI files not found" +!endif +!endif + +# Friend Server +!ifdef TOR_EXISTS +# Add Friend Server with Tor only +#${!defineifexist} FRIENDSERVER_EXISTS "${RELEASEDIR}\retroshare-friendserver\src\release\retroshare-friendserver.exe" +!endif + # Application name and version !define APPNAME "RetroShare" !define APPNAMEANDVERSION "${APPNAME} ${VERSION}" @@ -193,7 +210,6 @@ Section $(Section_Main) Section_Main ; Main binaries SetOutPath "$INSTDIR" File "${RELEASEDIR}\retroshare-gui\src\release\retroshare.exe" - File "${RELEASEDIR}\retroshare-service\src\release\retroshare-service.exe" File /nonfatal "${RELEASEDIR}\libretroshare\src\lib\retroshare.dll" ; Qt binaries @@ -231,6 +247,7 @@ Section $(Section_Main) Section_Main ; External binaries File "${EXTERNAL_LIB_DIR}\bin\miniupnpc.dll" + File "${RELEASEDIR}\supportlibs\librnp\Build\src\lib\librnp.dll" !if ${ARCHITECTURE} == "x86" File "${EXTERNAL_LIB_DIR}\bin\libcrypto-1_1.dll" File "${EXTERNAL_LIB_DIR}\bin\libssl-1_1.dll" @@ -282,11 +299,35 @@ Section $(Section_Main) Section_Main File /r "${SOURCEDIR}\retroshare-gui\src\license\*.*" SectionEnd +# Service +!ifdef SERVICE_EXISTS + Section /o $(Section_Service) Section_Service + SetOutPath "$INSTDIR" + File "${RELEASEDIR}\retroshare-service\src\release\retroshare-service.exe" + SectionEnd +!endif + +# Friend Server +!ifdef FRIENDSERVER_EXISTS + Section /o $(Section_FriendServer) Section_FriendServer + SetOutPath "$INSTDIR" + File "${RELEASEDIR}\retroshare-friendserver\src\release\retroshare-friendserver.exe" + SectionEnd +!endif + # Tor !ifdef TOR_EXISTS Section /o $(Section_Tor) Section_Tor - SetOutPath "$INSTDIR" - File /r "${TORDIR}\*" + SetOutPath "$INSTDIR\tor" + File "${TORDIR}\*" + SectionEnd +!endif + +# WebUI +!ifdef WEBUI_EXISTS + Section /o $(Section_WebUI) Section_WebUI + SetOutPath "$INSTDIR\webui" + File /r "${WEBUIDIR}\*" SectionEnd !endif @@ -334,7 +375,7 @@ Section $(Section_Data) Section_Data ; Stylesheets SetOutPath "$INSTDIR\qss" - File /r "${SOURCEDIR}\retroshare-gui\src\qss\*.*" + File /nonfatal /r "${SOURCEDIR}\retroshare-gui\src\qss\*.*" SectionEnd ;Section $(Section_Link) Section_Link @@ -355,6 +396,22 @@ Section $(Section_StartMenu) Section_StartMenu CreateDirectory "$SMPROGRAMS\${APPNAME}" CreateShortCut "$SMPROGRAMS\${APPNAME}\$(Link_Uninstall).lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\retroshare.exe" "" "$INSTDIR\retroshare.exe" 0 + +!ifdef SERVICE_EXISTS + SectionGetFlags ${Section_Service} $0 + IntOp $0 $0 & ${SF_SELECTED} + ${If} $0 == ${SF_SELECTED} + CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME} Service.lnk" "$INSTDIR\retroshare-service.exe" "" "$INSTDIR\retroshare-service.exe" 0 + ${EndIf} +!endif + +!ifdef FRIENDSERVER_EXISTS + SectionGetFlags ${Section_FriendServer} $0 + IntOp $0 $0 & ${SF_SELECTED} + ${If} $0 == ${SF_SELECTED} + CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME} Friend Server.lnk" "$INSTDIR\retroshare-friendserver.exe" "" "$INSTDIR\retroshare-friendserver.exe" 0 + ${EndIf} +!endif SectionEnd Section $(Section_Desktop) Section_Desktop @@ -407,6 +464,9 @@ SectionEnd ; !insertmacro MUI_DESCRIPTION_TEXT ${Section_Link} $(Section_Link_Desc) !insertmacro MUI_DESCRIPTION_TEXT ${Section_AutoStart} $(Section_AutoStart_Desc) !insertmacro MUI_DESCRIPTION_TEXT ${Section_Tor} $(Section_Tor_Desc) + !insertmacro MUI_DESCRIPTION_TEXT ${Section_WebUI} $(Section_WebUI_Desc) + !insertmacro MUI_DESCRIPTION_TEXT ${Section_Service} $(Section_Service_Desc) + !insertmacro MUI_DESCRIPTION_TEXT ${Section_FriendServer} $(Section_FriendServer_Desc) !insertmacro MUI_FUNCTION_DESCRIPTION_END # Uninstall @@ -461,6 +521,26 @@ Function .onInit !insertmacro MUI_LANGDLL_DISPLAY FunctionEnd +!ifdef FRIENDSERVER_EXISTS +Function .onSelChange + SectionGetFlags ${Section_FriendServer} $0 + IntOp $0 $0 & ${SF_SELECTED} + ${If} $0 == ${SF_SELECTED} + # Activate Tor and set readonly + SectionGetFlags ${Section_Tor} $1 + IntOp $1 $1 | ${SF_SELECTED} + IntOp $1 $1 | ${SF_RO} + SectionSetFlags ${Section_Tor} $1 + ${Else} + # Remove readonly from Tor + SectionGetFlags ${Section_Tor} $1 + IntOp $2 ${SF_RO} ~ + IntOp $1 $1 & $2 + SectionSetFlags ${Section_Tor} $1 + ${EndIf} +FunctionEnd +!endif + # Installation mode Function RequireAdmin diff --git a/build_scripts/Windows/tools/generate-changelog.bat b/build_scripts/Windows/tools/generate-changelog.bat index c38225045..2eb87ced6 100644 --- a/build_scripts/Windows/tools/generate-changelog.bat +++ b/build_scripts/Windows/tools/generate-changelog.bat @@ -18,6 +18,8 @@ copy nul %logfile% > nul pushd %~1 +set Percent=%% + set last=HEAD for /f %%t in ('git tag --sort=-taggerdate --merged ^| findstr v') do ( echo generating changelog for !last!..%%t @@ -30,7 +32,7 @@ for /f %%t in ('git tag --sort=-taggerdate --merged ^| findstr v') do ( rem echo !last! ---^> %%t >> %logfile% echo ----------------------------------------------- >> %logfile% echo. >> %logfile% - git log %%t..!last! --no-merges "--pretty=format:%%h %%ai %%<(10,trunc)%%an %%s" >> %logfile% + git log %%t..!last! --no-merges "--pretty=format:!Percent!h !Percent!ai !Percent!<(10,trunc)!Percent!an !Percent!s" >> %logfile% echo. >> %logfile% echo. >> %logfile% set last=%%t diff --git a/build_scripts/git_tag_cleaner.sh b/build_scripts/git_tag_cleaner.sh new file mode 100755 index 000000000..cf7a3ef0c --- /dev/null +++ b/build_scripts/git_tag_cleaner.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +function git_del_tag() +{ + mTag=$1 + + for mRemote in $(git remote); do + echo "Attempting tag $mTag removal from remote $mRemote" + GIT_TERMINAL_PROMPT=0 git push $mRemote :$mTag || true + done + git tag --delete $mTag +} + +for mModule in . build_scripts/OBS/ libbitdht/ libretroshare/ openpgpsdk/ retroshare-webui/ ; do + pushd $mModule + git_del_tag v0.6.7a + git tag --list | grep untagged | while read mTag; do git_del_tag $mTag ; done + popd +done + diff --git a/data/retroshare.desktop b/data/retroshare.desktop index efc73dd6b..95056d54a 100644 --- a/data/retroshare.desktop +++ b/data/retroshare.desktop @@ -7,5 +7,5 @@ Exec=/usr/bin/retroshare %U Icon=/usr/share/pixmaps/retroshare.xpm Terminal=false Type=Application -Categories=Application;Network;P2P;Feed;Chat;InstantMessaging +Categories=Network;Email;InstantMessaging;Chat;Feed;FileTransfer;P2P MimeType=x-scheme-handler/retroshare; diff --git a/jsonapi-generator/README.adoc b/jsonapi-generator/README.adoc index 64284b85c..cea59a117 100644 --- a/jsonapi-generator/README.adoc +++ b/jsonapi-generator/README.adoc @@ -1,447 +1,10 @@ -// SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team +// SPDX-FileCopyrightText: (C) 2021 Retroshare Team // SPDX-License-Identifier: CC0-1.0 -RetroShare JSON API -=================== += Moved -:Cxx: C++ +JSON API generator is now part of `libretroshare` look under `src/jsonapi/` +directory in `libretroshare` repository. -== How to use RetroShare JSON API - -Look for methods marked with +@jsonapi+ doxygen custom command into -+libretroshare/src/retroshare+. The method path is composed by service instance -pointer name like +rsGxsChannels+ for +RsGxsChannels+, and the method name like -+createGroup+ and pass the input paramethers as a JSON object. - -.Service instance pointer in rsgxschannels.h -[source,cpp] --------------------------------------------------------------------------------- -/** - * Pointer to global instance of RsGxsChannels service implementation - * @jsonapi{development} - */ -extern RsGxsChannels* rsGxsChannels; --------------------------------------------------------------------------------- - -.Method declaration in rsgxschannels.h -[source,cpp] --------------------------------------------------------------------------------- - /** - * @brief Request channel creation. - * The action is performed asyncronously, so it could fail in a subsequent - * phase even after returning true. - * @jsonapi{development} - * @param[out] token Storage for RsTokenService token to track request - * status. - * @param[in] group Channel data (name, description...) - * @return false on error, true otherwise - */ - virtual bool createGroup(uint32_t& token, RsGxsChannelGroup& group) = 0; --------------------------------------------------------------------------------- - -.paramethers.json -[source,json] --------------------------------------------------------------------------------- -{ - "group":{ - "mMeta":{ - "mGroupName":"JSON test group", - "mGroupFlags":4, - "mSignFlags":520 - }, - "mDescription":"JSON test group description" - }, - "caller_data":"Here can go any kind of JSON data (even objects) that the caller want to get back together with the response" -} --------------------------------------------------------------------------------- - -.Calling the JSON API with curl on the terminal -[source,bash] --------------------------------------------------------------------------------- -curl -u $API_USER --data @paramethers.json http://127.0.0.1:9092/rsGxsChannels/createGroup --------------------------------------------------------------------------------- - -.JSON API call result -[source,json] --------------------------------------------------------------------------------- -{ - "caller_data": "Here can go any kind of JSON data (even objects) that the caller want to get back together with the response", - "retval": true, - "token": 3 -} --------------------------------------------------------------------------------- - -Even if it is less efficient because of URL encoding HTTP +GET+ method is -supported too, so in cases where the client cannot use +POST+ she can still use -+GET+ taking care of encoding the JSON data. With +curl+ this can be done at -least in two different ways. - -.Calling the JSON API with GET method with curl on the terminal -[source,bash] --------------------------------------------------------------------------------- -curl -u $API_USER --get --data-urlencode jsonData@paramethers.json \ - http://127.0.0.1:9092/rsGxsChannels/createGroup --------------------------------------------------------------------------------- - -Letting +curl+ do the encoding is much more elegant but it is semantically -equivalent to the following. - -.Calling the JSON API with GET method and pre-encoded data with curl on the terminal --------------------------------------------------------------------------------- -curl -u $API_USER http://127.0.0.1:9092/rsGxsChannels/createGroup?jsonData=%7B%0A%20%20%20%20%22group%22%3A%7B%0A%20%20%20%20%20%20%20%20%22mMeta%22%3A%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mGroupName%22%3A%22JSON%20test%20group%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mGroupFlags%22%3A4%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mSignFlags%22%3A520%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22mDescription%22%3A%22JSON%20test%20group%20description%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22caller_data%22%3A%22Here%20can%20go%20any%20kind%20of%20JSON%20data%20%28even%20objects%29%20that%20the%20caller%20want%20to%20get%20back%20together%20with%20the%20response%22%0A%7D --------------------------------------------------------------------------------- - -Note that using +GET+ method +?jsonData=+ and then the JSON data URL encoded are -added after the path in the HTTP request. - - -== JSON API authentication - -Most of JSON API methods require authentication as they give access to -RetroShare user data, and we don't want any application running on the system -eventually by other users be able to access private data indiscriminately. -JSON API support HTTP Basic as authentication scheme, this is enough as JSON API -server is intented for usage on the same system (127.0.0.1) not over an -untrusted network. -If you need to use JSON API over an untrusted network consider using a reverse -proxy with HTTPS such as NGINX in front of JSON API server. -If RetroShare login has been effectuated through the JSON API you can use your -location SSLID as username and your PGP password as credential for the JSON API, -but we suggests you use specific meaningful and human readable credentials for -each JSON API client so the human user can have better control over which client -can access the JSON API. - -.NewToken.json -[source,json] --------------------------------------------------------------------------------- -{ - "token": "myNewUser:myNewPassword" -} --------------------------------------------------------------------------------- - -.An authenticated client can authorize new tokens like this --------------------------------------------------------------------------------- -curl -u $API_USER --data @NewToken.json http://127.0.0.1:9092/jsonApiServer/authorizeToken --------------------------------------------------------------------------------- - -.An unauthenticated JSON API client can request access with --------------------------------------------------------------------------------- -curl --data @NewToken.json http://127.0.0.1:9092/jsonApiServer/requestNewTokenAutorization --------------------------------------------------------------------------------- - -When an unauthenticated client request his token to be authorized, JSON API -server will try to ask confirmation to the human user if possible through -+mNewAccessRequestCallback+, if it is not possible or the user didn't authorized -the token +false+ is returned. - - -== Offer new RetroShare services through JSON API - -To offer a retroshare service through the JSON API, first of all one need find -the global pointer to the service instance and document it in doxygen syntax, -plus marking with the custom doxygen command +@jsonapi{RS_VERSION}+ where -+RS_VERSION+ is the retroshare version in which this service became available -with the current semantic (major changes to the service semantic, changes the -meaning of the service itself, so the version should be updated in the -documentation in that case). - -.Service instance pointer in rsgxschannels.h -[source,cpp] --------------------------------------------------------------------------------- -/** - * Pointer to global instance of RsGxsChannels service implementation - * @jsonapi{development} - */ -extern RsGxsChannels* rsGxsChannels; --------------------------------------------------------------------------------- - - -Once the service instance itself is known to the JSON API you need to document -in doxygen syntax and mark with the custom doxygen command -+@jsonapi{RS_VERSION}+ the methods of the service that you want to make -available through JSON API. - -.Offering RsGxsChannels::getChannelDownloadDirectory in rsgxschannels.h -[source,cpp] --------------------------------------------------------------------------------- - /** - * Get download directory for the given channel - * @jsonapi{development} - * @param[in] channelId id of the channel - * @param[out] directory reference to string where to store the path - * @return false on error, true otherwise - */ - virtual bool getChannelDownloadDirectory( const RsGxsGroupId& channelId, - std::string& directory ) = 0; --------------------------------------------------------------------------------- - -For each paramether you must specify if it is used as input +@param[in]+ as -output +@param[out]+ or both +@param[inout]+. Paramethers and return value -types must be of a type supported by +RsTypeSerializer+ which already support -most basic types (+bool+, +std::string+...), +RsSerializable+ and containers of -them like +std::vector+. Paramethers passed by value and by -reference of those types are both supported, while passing by pointer is not -supported. If your paramether or return +class+/+struct+ type is not supported -yet by +RsTypeSerializer+ most convenient approach is to make it derive from -+RsSerializable+ and implement +serial_process+ method like I did with -+RsGxsChannelGroup+. - -.Deriving RsGxsChannelGroup from RsSerializable in rsgxschannels.h -[source,cpp] --------------------------------------------------------------------------------- -struct RsGxsChannelGroup : RsSerializable -{ - RsGroupMetaData mMeta; - std::string mDescription; - RsGxsImage mImage; - - bool mAutoDownload; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mDescription); - RS_SERIAL_PROCESS(mImage); - RS_SERIAL_PROCESS(mAutoDownload); - } -}; --------------------------------------------------------------------------------- - -You can do the same recursively for any member of your +struct+ that is not yet -supported by +RsTypeSerializer+. - -Some Retroshare {Cxx} API functions are asyncronous, historically RetroShare -didn't follow a policy on how to expose asyncronous API so differents services -and some times even differents method of the same service follow differents -asyncronous patterns, thus making automatic generation of JSON API wrappers for -those methods impractical. Instead of dealing with all those differents patterns -I have chosed to support only one new pattern taking advantage of modern {Cxx}11 -and restbed features. On the {Cxx}11 side lambdas and +std::function+s are used, -on the restbed side Server Side Events are used to send asyncronous results. - -Lets see an example so it will be much esier to understand. - -.RsGxsChannels::turtleSearchRequest asyncronous API -[source,cpp] --------------------------------------------------------------------------------- - /** - * @brief Request remote channels search - * @jsonapi{development} - * @param[in] matchString string to look for in the search - * @param multiCallback function that will be called each time a search - * result is received - * @param[in] maxWait maximum wait time in seconds for search results - * @return false on error, true otherwise - */ - virtual bool turtleSearchRequest( - const std::string& matchString, - const std::function& multiCallback, - std::time_t maxWait = 300 ) = 0; --------------------------------------------------------------------------------- - -+RsGxsChannels::turtleSearchRequest(...)+ is an asyncronous method because it -send a channel search request on turtle network and then everytime a result is -received from the network +multiCallback+ is called and the result is passed as -parameter. To be supported by the automatic JSON API wrappers generator an -asyncronous method need a parameter of type +std::function+ called -+callback+ if the callback will be called only once or +multiCallback+ if the -callback is expected to be called more then once like in this case. -A second mandatory parameter is +maxWait+ of type +std::time_t+ it indicates the -maximum amount of time in seconds for which the caller is willing to wait for -results, in case the timeout is reached the callback will not be called anymore. - -[IMPORTANT] -================================================================================ -+callback+ and +multiCallback+ parameters documentation must *not* specify -+[in]+, +[out]+, +[inout]+, in Doxygen documentation as this would fool the -automatic wrapper generator, and ultimately break the compilation. -================================================================================ - -.RsFiles::turtleSearchRequest asyncronous JSON API usage example -[source,bash] --------------------------------------------------------------------------------- -$ cat turtle_search.json -{ - "matchString":"linux" -} -$ curl --data @turtle_search.json http://127.0.0.1:9092/rsFiles/turtleSearchRequest -data: {"retval":true} - -data: {"results":[{"size":157631,"hash":"69709b4d01025584a8def5cd78ebbd1a3cf3fd05","name":"kill_bill_linux_1024x768.jpg"},{"size":192560,"hash":"000000000000000000009a93e5be8486c496f46c","name":"coffee_box_linux2.jpg"},{"size":455087,"hash":"9a93e5be8486c496f46c00000000000000000000","name":"Linux.png"},{"size":182004,"hash":"e8845280912ebf3779e400000000000000000000","name":"Linux_2_6.png"}]} - -data: {"results":[{"size":668,"hash":"e8845280912ebf3779e400000000000000000000","name":"linux.png"},{"size":70,"hash":"e8845280912ebf3779e400000000000000000000","name":"kali-linux-2016.2-amd64.txt.sha1sum"},{"size":3076767744,"hash":"e8845280912ebf3779e400000000000000000000","name":"kali-linux-2016.2-amd64.iso"},{"size":2780872,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux.bin"},{"size":917504,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux.lzma"},{"size":2278404096,"hash":"e8845280912ebf3779e400000000000000000000","name":"gentoo-linux-livedvd-amd64-multilib-20160704.iso"},{"size":151770333,"hash":"e8845280912ebf3779e400000000000000000000","name":"flashtool-0.9.23.0-linux.tar.7z"},{"size":2847372,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux.elf"},{"size":1310720,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux.gz"},{"size":987809,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux-lzma.elf"}]} - --------------------------------------------------------------------------------- - -By default JSON API methods requires client authentication and their wrappers -are automatically generated by +json-api-generator+. -In some cases methods need do be accessible without authentication such as -+rsLoginHelper/getLocations+ so in the doxygen documentaion they have the custom -command +@jsonapi{RS_VERSION,unauthenticated}+. -Other methods such as +/rsControl/rsGlobalShutDown+ need special care so they -are marked with the custom doxygen command +@jsonapi{RS_VERSION,manualwrapper}+ -and their wrappers are not automatically generated but written manually into -+JsonApiServer::JsonApiServer(...)+. - -== Quirks - -=== 64 bits integers handling - -While JSON doesn't have problems representing 64 bits integers JavaScript, Dart -and other languages are not capable to handle those numbers natively. -To overcome this limitation JSON API output 64 bit integers as an object with -two keys, one as proper integer and one as string representation. - -.JSON API 64 bit integer output example -[source,json] --------------------------------------------------------------------------------- -"lobby_id": { "xint64": 6215642878098695544, "xstr64": "6215642878098695544" } --------------------------------------------------------------------------------- - -So from languages that have proper 64bit integers support like Python or C++ one -better read from `xint64` which is represented as a JSON integer, from languages -where there is no proper 64bit integers support like JavaScript one can read from -`xstr64` which is represented as JSON string (note that the first is not wrapped -in "" while the latter is). - -When one input a 64bit integer into the JSON API it first try to parse it as if -it was sent the old way for retrocompatibility. - -.JSON API 64 bit integer deprecated format input example -[source,json] --------------------------------------------------------------------------------- -"lobby_id":6215642878098695544 --------------------------------------------------------------------------------- - -This way is *DEPRECATED* and may disappear in the future, it is TEMPORALLY kept -only for retrocompatibiliy with old clients. - -If retrocompatible parsing attempt fail then it try to parse with the new way -with proper JSON integer format. - -.JSON API 64 bit integer new proper integer format input example -[source,json] --------------------------------------------------------------------------------- -lobby_id": { "xint64": 6215642878098695544 } --------------------------------------------------------------------------------- - -If this fails then it try to parse with the new way with JSON string format. - -.JSON API 64 bit integer new string format input example -[source,json] --------------------------------------------------------------------------------- -"lobby_id": { "xstr64": "6215642878098695544" } --------------------------------------------------------------------------------- - -[WARNING] -================================================================================ -Clients written in languages without proper 64bit integers support must -use *ONLY* the string format otherwise they will send approximated values and -get unexpected results from the JSON API, because parsing will success but the -value will not be exactly the one you believe you sent. -================================================================================ - - -== A bit of history - -=== First writings about this - -The previous attempt of exposing a RetroShare JSON API is called +libresapi+ and -unfortunatley it requires a bunch of boilerplate code when we want to expose -something present in the {Cxx} API in the JSON API. - -As an example here you can see the libresapi that exposes part of the retroshare -chat {Cxx} API and lot of boilerplate code just to convert {Cxx} objects to JSON - -https://github.com/RetroShare/RetroShare/blob/v0.6.4/libresapi/src/api/ChatHandler.cpp#L44 - -To avoid the {Cxx} to JSON and back conversion boilerplate code I have worked out -an extension to our {Cxx} serialization code so it is capable to serialize and -deserialize to JSON you can see it in this pull request - -https://github.com/RetroShare/RetroShare/pull/1155 - -So first step toward having a good API is to take advantage of the fact that RS -is now capable of converting C++ objects from and to JSON. - -The current API is accessible via HTTP and unix socket, there is no -authentication in both of them, so anyone having access to the HTTP server or to -the unix socket can access the API without extra restrictions. -Expecially for the HTTP API this is a big risk because also if the http server -listen on 127.0.0.1 every application on the machine (even rogue javascript -running on your web browser) can access that and for example on android it is -not safe at all (because of that I implemented the unix socket access so at -least in android API was reasonably safe) because of this. - -A second step to improve the API would be to implement some kind of API -authentication mechanism (it would be nice that the mechanism is handled at API -level and not at transport level so we can use it for any API trasport not just -HTTP for example) - -The HTTP server used by libresapi is libmicrohttpd server that is very minimal, -it doesn't provide HTTPS nor modern HTTP goodies, like server notifications, -websockets etc. because the lack of support we have a token polling mechanism in -libresapi to avoid polling for every thing but it is still ugly, so if we can -completely get rid of polling in the API that would be really nice. -I have done a crawl to look for a replacement and briefly looked at - -- https://www.gnu.org/software/libmicrohttpd/ -- http://wolkykim.github.io/libasyncd/ -- https://github.com/corvusoft/restbed -- https://code.facebook.com/posts/1503205539947302/introducing-proxygen-facebook-s-c-http-framework/ -- https://github.com/cmouse/yahttp - -taking in account a few metrics like modern HTTP goodies support, license, -platform support, external dependencies and documentation it seemed to me that -restbed is the more appropriate. - -Another source of boilerplate code into libresapi is the mapping between JSON -API requests and C++ API methods as an example you can look at this - -https://github.com/RetroShare/RetroShare/blob/v0.6.4/libresapi/src/api/ChatHandler.cpp#L158 - -and this - -https://github.com/RetroShare/RetroShare/blob/v0.6.4/libresapi/src/api/ApiServer.cpp#L253 - -The abstract logic of this thing is, when libreasapi get a request like -+/chat/initiate_distant_chat+ then call -+ChatHandler::handleInitiateDistantChatConnexion+ which in turn is just a -wrapper of +RsMsgs::initiateDistantChatConnexion+ all this process is basically -implemented as boilerplate code and would be unnecessary in a smarter design of -the API because almost all the information needed is already present in the -C++ API +libretroshare/src/retroshare+. - -So a third step to improve the JSON API would be to remove this source of -boilerplate code by automatizing the mapping between C++ and JSON API call. - -This may result a little tricky as language parsing or other adevanced things -may be required. - -Hope this dive is useful for you + -Cheers + -G10h4ck - -=== Second writings about this - -I have been investigating a bit more about: -[verse, G10h4ck] -________________________________________________________________________________ -So a third step to improve the JSON API would be to remove this source of -boilerplate code by automatizing the mapping between C++ and JSON API call -________________________________________________________________________________ - -After spending some hours investigating this topic the most reasonable approach -seems to: - -1. Properly document headers in +libretroshare/src/retroshare/+ in doxygen syntax -specifying wihich params are input and/or output (doxygen sysntax for this is -+@param[in/out/inout]+) this will be the API documentation too. - -2. At compile time use doxygen to generate XML description of the headers and use -the XML to generate the JSON api server stub. -http://www.stack.nl/~dimitri/doxygen/manual/customize.html#xmlgenerator - -3. Enjoy +This directory and all it's content is kept as is only for retro-compatibility +with the old, deprecated `qmake` build system. diff --git a/jsonapi-generator/src/async-method-wrapper-template.cpp.tmpl b/jsonapi-generator/src/async-method-wrapper-template.cpp.tmpl deleted file mode 100644 index 29f53ad48..000000000 --- a/jsonapi-generator/src/async-method-wrapper-template.cpp.tmpl +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * RetroShare JSON API * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero 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 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 . * - * * - *******************************************************************************/ - -registerHandler( "$%apiPath%$", - [this](const std::shared_ptr session) -{ - const std::multimap headers - { - { "Connection", "keep-alive" }, - { "Content-Type", "text/event-stream" } - }; - session->yield(rb::OK, headers); - - size_t reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( reqSize, [this]( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - if( !checkRsServicePtrReady( - $%instanceName%$, "$%instanceName%$", cAns, session ) ) - return; - -$%paramsDeclaration%$ - -$%inputParamsDeserialization%$ - - const std::weak_ptr weakService(mService); - const std::weak_ptr weakSession(session); - $%callbackName%$ = [weakService, weakSession]($%callbackParams%$) - { - auto session = weakSession.lock(); - if(!session || session->is_closed()) return; - - auto lService = weakService.lock(); - if(!lService || lService->is_down()) return; - -$%callbackParamsSerialization%$ - - std::stringstream sStream; - sStream << "data: " << compactJSON << ctx.mJson << "\n\n"; - const std::string message = sStream.str(); - - lService->schedule( [weakSession, message]() - { - auto session = weakSession.lock(); - if(!session || session->is_closed()) return; - session->yield(message); - $%sessionEarlyClose%$ - } ); - }; - -$%functionCall%$ - -$%outputParamsSerialization%$ - - // return them to the API caller - std::stringstream message; - message << "data: " << compactJSON << cAns.mJson << "\n\n"; - session->yield(message.str()); - $%sessionDelayedClose%$ - } ); -}, $%requiresAuth%$ ); diff --git a/jsonapi-generator/src/async-method-wrapper-template.cpp.tmpl b/jsonapi-generator/src/async-method-wrapper-template.cpp.tmpl new file mode 120000 index 000000000..1ae671997 --- /dev/null +++ b/jsonapi-generator/src/async-method-wrapper-template.cpp.tmpl @@ -0,0 +1 @@ +../../libretroshare/src/jsonapi/async-method-wrapper-template.cpp.tmpl \ No newline at end of file diff --git a/jsonapi-generator/src/jsonapi-generator-doxygen.conf b/jsonapi-generator/src/jsonapi-generator-doxygen.conf deleted file mode 100644 index 0edd1de3e..000000000 --- a/jsonapi-generator/src/jsonapi-generator-doxygen.conf +++ /dev/null @@ -1,230 +0,0 @@ -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "libretroshare" - -ALIASES += jsonapi{1}="\xmlonly\endxmlonly" -ALIASES += jsonapi{2}="\xmlonly\endxmlonly" - -# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the -# documentation from any documented member that it re-implements. -# The default value is: YES. - -INHERIT_DOCS = YES - -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments -# according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in -# case of backward compatibilities issues. -# The default value is: YES. - -MARKDOWN_SUPPORT = YES - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. -# The default value is: YES. - -AUTOLINK_SUPPORT = YES - - -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in -# documentation are documented, even if no documentation was available. Private -# class members and static file members will be hidden unless the -# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. -# Note: This will also disable the warnings about undocumented members that are -# normally produced when WARNINGS is set to YES. -# The default value is: NO. - -EXTRACT_ALL = YES - - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all -# undocumented members inside documented classes or files. If set to NO these -# members will be included in the various overviews, but no documentation -# section is generated. This option has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. If set -# to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_CLASSES = NO - - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like myfile.cpp or -# directories like /usr/src/myproject. Separate the files or directories with -# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING -# Note: If this tag is empty the current directory is searched. - -#INPUT = - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses -# libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: https://www.gnu.org/software/libiconv/) for the list of -# possible encodings. -# The default value is: UTF-8. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. -# -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, -# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. - -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.idl \ - *.ddl \ - *.odl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.cs \ - *.d \ - *.php \ - *.php4 \ - *.php5 \ - *.phtml \ - *.inc \ - *.m \ - *.markdown \ - *.md \ - *.mm \ - *.dox \ - *.py \ - *.pyw \ - *.f90 \ - *.f95 \ - *.f03 \ - *.f08 \ - *.f \ - *.for \ - *.tcl \ - *.vhd \ - *.vhdl \ - *.ucf \ - *.qsf - -# The RECURSIVE tag can be used to specify whether or not subdirectories should -# be searched for input files as well. -# The default value is: NO. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. -# The default value is: NO. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* - -EXCLUDE_SYMBOLS = - - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output -# The default value is: YES. - -GENERATE_HTML = NO - -# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. -# The default value is: YES. - -GENERATE_LATEX = NO - -# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that -# captures the structure of the code including all documentation. -# The default value is: NO. - -GENERATE_XML = YES - - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all -# C-preprocessor directives found in the sources and include files. -# The default value is: YES. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names -# in the source code. If set to NO, only conditional compilation will be -# performed. Macro expansion can be done in a controlled way by setting -# EXPAND_ONLY_PREDEF to YES. -# The default value is: NO. -# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then -# the macro expansion is limited to the macros specified with the PREDEFINED and -# EXPAND_AS_DEFINED tags. -# The default value is: NO. -# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. - -EXPAND_ONLY_PREDEF = NO - diff --git a/jsonapi-generator/src/jsonapi-generator-doxygen.conf b/jsonapi-generator/src/jsonapi-generator-doxygen.conf new file mode 120000 index 000000000..9aff33c39 --- /dev/null +++ b/jsonapi-generator/src/jsonapi-generator-doxygen.conf @@ -0,0 +1 @@ +../../libretroshare/src/jsonapi/jsonapi-generator-doxygen.conf \ No newline at end of file diff --git a/jsonapi-generator/src/method-wrapper-template.cpp.tmpl b/jsonapi-generator/src/method-wrapper-template.cpp.tmpl deleted file mode 100644 index a3927fba9..000000000 --- a/jsonapi-generator/src/method-wrapper-template.cpp.tmpl +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************* - * RetroShare JSON API * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * 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 . * - * * - *******************************************************************************/ - -registerHandler( "$%apiPath%$", - [](const std::shared_ptr session) -{ - size_t reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( reqSize, []( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - if( !checkRsServicePtrReady( - $%instanceName%$, "$%instanceName%$", cAns, session ) ) - return; - -$%paramsDeclaration%$ - - // deserialize input parameters from JSON -$%inputParamsDeserialization%$ - - // call retroshare C++ API -$%functionCall%$ - - // serialize out parameters and return value to JSON -$%outputParamsSerialization%$ - - // return them to the API caller - DEFAULT_API_CALL_JSON_RETURN(rb::OK); - } ); -}, $%requiresAuth%$ ); - diff --git a/jsonapi-generator/src/method-wrapper-template.cpp.tmpl b/jsonapi-generator/src/method-wrapper-template.cpp.tmpl new file mode 120000 index 000000000..717044ed2 --- /dev/null +++ b/jsonapi-generator/src/method-wrapper-template.cpp.tmpl @@ -0,0 +1 @@ +../../libretroshare/src/jsonapi/method-wrapper-template.cpp.tmpl \ No newline at end of file diff --git a/libbitdht b/libbitdht new file mode 160000 index 000000000..2ddc86fb5 --- /dev/null +++ b/libbitdht @@ -0,0 +1 @@ +Subproject commit 2ddc86fb575a61170f4c06a00152e3e7dc74c8f4 diff --git a/libbitdht/src/README.txt b/libbitdht/src/README.txt deleted file mode 100644 index a1dff67e4..000000000 --- a/libbitdht/src/README.txt +++ /dev/null @@ -1,25 +0,0 @@ -# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team -# SPDX-License-Identifier: CC0-1.0 - -What's in the Package ---------------------------------------------------------------- -bitdht - base BitDHT Code. -util - generic utils for networking and threading. -udp - UDP interfacing code. -lib - Where the library is created. -tests - basic unit tests. -example - example code of how to use libbitdht. -libbitdht.pro - build script for Qt's qmake. -README.txt - this file. - - -HOWTO libbitdht. ----------------------------------------------- -This version is build using Qt's qmake system. - -1) Install Qt's qmake system: libqt-dev -2) type ./qmake -3) type ./make -4) check out the example and tests to learn how to interface with libbitdht. - - diff --git a/libbitdht/src/bitdht/bdaccount.cc b/libbitdht/src/bitdht/bdaccount.cc deleted file mode 100644 index 57de177f7..000000000 --- a/libbitdht/src/bitdht/bdaccount.cc +++ /dev/null @@ -1,133 +0,0 @@ -/******************************************************************************* - * bitdht/bdaccount.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bitdht/bdaccount.h" - -#include -#include - -#include -#include - - -#define LPF_FACTOR (0.90) - -bdAccount::bdAccount() - :mNoStats(BDACCOUNT_NUM_ENTRIES), - mCountersOut(BDACCOUNT_NUM_ENTRIES), mCountersRecv(BDACCOUNT_NUM_ENTRIES), - mLpfOut(BDACCOUNT_NUM_ENTRIES), mLpfRecv(BDACCOUNT_NUM_ENTRIES), - mLabel(BDACCOUNT_NUM_ENTRIES) -{ - - mLabel[BDACCOUNT_MSG_OUTOFDATEPING] = "OUTOFDATEPING "; - mLabel[BDACCOUNT_MSG_PING] = "PING "; - mLabel[BDACCOUNT_MSG_PONG] = "PONG "; - mLabel[BDACCOUNT_MSG_QUERYNODE] = "QUERYNODE "; - mLabel[BDACCOUNT_MSG_QUERYHASH] = "QUERYHASH "; - mLabel[BDACCOUNT_MSG_REPLYFINDNODE] = "REPLYFINDNODE "; - mLabel[BDACCOUNT_MSG_REPLYQUERYHASH] = "REPLYQUERYHASH "; - - mLabel[BDACCOUNT_MSG_POSTHASH] = "POSTHASH "; - mLabel[BDACCOUNT_MSG_REPLYPOSTHASH] = "REPLYPOSTHASH "; - - mLabel[BDACCOUNT_MSG_CONNECTREQUEST] = "CONNECTREQUEST "; - mLabel[BDACCOUNT_MSG_CONNECTREPLY] = "CONNECTREPLY "; - mLabel[BDACCOUNT_MSG_CONNECTSTART] = "CONNECTSTART "; - mLabel[BDACCOUNT_MSG_CONNECTACK] = "CONNECTACK "; - - resetStats(); -} - - -void bdAccount::incCounter(uint32_t idx, bool out) -{ - if ((signed) idx > mNoStats-1) - { - std::cerr << "bdAccount::incCounter() Invalid Index"; - std::cerr << std::endl; - } - - if (out) - { - mCountersOut[idx]++; - } - else - { - mCountersRecv[idx]++; - } - return; -} - - -void bdAccount::doStats() -{ - int i; - for(i = 0; i < mNoStats; i++) - { - mLpfOut[i] *= (LPF_FACTOR) ; - mLpfOut[i] += (1.0 - LPF_FACTOR) * mCountersOut[i]; - - mLpfRecv[i] *= (LPF_FACTOR) ; - mLpfRecv[i] += (1.0 - LPF_FACTOR) * mCountersRecv[i]; - } - resetCounters(); -} - -void bdAccount::printStats(std::ostream &out) -{ - int i; - out << " Send Recv: "; - out << std::endl; - for(i = 0; i < mNoStats; i++) - { - - out << "Send" << mLabel[i] << " : " << std::setw(10) << mLpfOut[i]; - out << " "; - out << "Recv" << mLabel[i] << " : " << std::setw(10) << mLpfRecv[i]; - out << std::endl; - } -} - -void bdAccount::resetCounters() -{ - int i; - for(i = 0; i < mNoStats; i++) - { - mCountersOut[i] = 0; - mCountersRecv[i] = 0; - } -} - -void bdAccount::resetStats() -{ - int i; - for(i = 0; i < mNoStats; i++) - { - mLpfOut[i] = 0; - mLpfRecv[i] = 0; - } - resetCounters(); -} - - - - diff --git a/libbitdht/src/bitdht/bdaccount.h b/libbitdht/src/bitdht/bdaccount.h deleted file mode 100644 index 7116e3ced..000000000 --- a/libbitdht/src/bitdht/bdaccount.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef BITDHT_ACCOUNT_H -#define BITDHT_ACCOUNT_H - -/******************************************************************************* - * bitdht/bdaccount.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include -#include - -#define BDACCOUNT_MSG_OUTOFDATEPING 0 -#define BDACCOUNT_MSG_PING 1 -#define BDACCOUNT_MSG_PONG 2 -#define BDACCOUNT_MSG_QUERYNODE 3 -#define BDACCOUNT_MSG_QUERYHASH 4 -#define BDACCOUNT_MSG_REPLYFINDNODE 5 -#define BDACCOUNT_MSG_REPLYQUERYHASH 6 - -#define BDACCOUNT_MSG_POSTHASH 7 -#define BDACCOUNT_MSG_REPLYPOSTHASH 8 - -#define BDACCOUNT_MSG_CONNECTREQUEST 9 -#define BDACCOUNT_MSG_CONNECTREPLY 10 -#define BDACCOUNT_MSG_CONNECTSTART 11 -#define BDACCOUNT_MSG_CONNECTACK 12 - -#define BDACCOUNT_NUM_ENTRIES 13 - -class bdAccount -{ - public: - - bdAccount(); - - void incCounter(uint32_t idx, bool out); - void doStats(); - void printStats(std::ostream &out); - void resetCounters(); - void resetStats(); - - private: - - int mNoStats; - - std::vector mCountersOut; - std::vector mCountersRecv; - - std::vector mLpfOut; - std::vector mLpfRecv; - - std::vector mLabel; - // Statistics. -}; - - - -#endif // BITDHT_ACCOUNT_H diff --git a/libbitdht/src/bitdht/bdboot.txt b/libbitdht/src/bitdht/bdboot.txt deleted file mode 100644 index 273a35afc..000000000 --- a/libbitdht/src/bitdht/bdboot.txt +++ /dev/null @@ -1,267 +0,0 @@ -1.162.168.21 8956 -2.6.224.136 17320 -5.116.142.222 13755 -5.189.185.57 6968 -5.202.101.3 4000 -5.227.124.122 1024 -5.227.124.122 20600 -5.227.124.122 64196 -5.39.94.218 6991 -5.79.102.9 6881 -5.89.120.163 2457 -14.117.182.22 1091 -14.8.109.32 17160 -23.115.236.180 42375 -24.153.98.173 1024 -24.38.199.13 10583 -27.150.87.242 1123 -27.151.179.38 51413 -27.152.212.182 1424 -31.24.186.40 16143 -31.36.78.93 30020 -31.44.90.218 51413 -37.120.213.132 19525 -37.14.113.18 3815 -37.146.76.158 51413 -37.187.105.230 5169 -37.232.184.93 6881 -37.46.150.58 51413 -39.111.152.200 17527 -39.154.68.57 28007 -42.200.116.4 18578 -42.3.188.207 19771 -45.176.111.21 1434 -45.32.43.51 49091 -45.76.218.165 52911 -45.77.214.200 44350 -46.172.86.23 46039 -46.223.161.46 23693 -46.237.96.68 16536 -46.52.174.214 24012 -46.7.227.47 27644 -46.7.9.41 21374 -49.64.73.215 51413 -49.74.50.28 60893 -49.75.73.147 51413 -49.79.26.15 51413 -49.83.226.50 20864 -49.83.241.222 51413 -52.9.197.152 6881 -58.209.188.12 20994 -59.149.118.196 51413 -59.2.250.243 57099 -59.6.53.18 57437 -60.104.89.4 51413 -60.124.114.239 16925 -60.178.44.27 1050 -60.99.229.14 20617 -61.223.34.21 17881 -61.227.127.222 22223 -61.239.28.169 18873 -62.210.82.193 51413 -64.191.5.92 56891 -65.92.141.96 58361 -67.215.246.10 6881 -68.151.213.83 20047 -69.40.178.254 50793 -71.34.2.150 8053 -72.95.247.56 12956 -73.157.77.166 5477 -74.109.243.24 7250 -74.140.153.59 24757 -74.72.13.99 9613 -76.29.106.98 41447 -77.202.207.190 33034 -77.21.64.116 22222 -77.245.14.94 9910 -78.131.78.35 51238 -78.158.1.15 7433 -78.231.125.98 12162 -78.242.250.55 55946 -79.164.245.5 49001 -80.147.23.201 32746 -80.200.171.90 16294 -80.99.222.34 51414 -81.171.17.30 42254 -82.221.103.244 6881 -82.235.78.193 44097 -82.244.32.78 43518 -82.64.181.170 38240 -82.64.249.25 51413 -82.64.44.119 51413 -82.65.164.218 15726 -82.65.68.9 51413 -82.77.146.109 53713 -83.46.92.34 50000 -84.195.46.218 54600 -84.40.106.115 12046 -85.149.0.42 21045 -86.121.194.1 51413 -86.98.50.30 21455 -87.123.166.45 4145 -87.169.199.211 10496 -88.7.217.202 31348 -88.99.25.154 38051 -89.135.26.33 51413 -89.17.134.184 10327 -89.245.86.20 32417 -89.253.118.133 8621 -90.101.94.104 20780 -90.151.95.110 2199 -90.219.241.30 51413 -90.219.8.170 11916 -91.121.136.132 59001 -91.123.72.241 49001 -91.142.65.40 51413 -91.173.208.204 16300 -91.211.245.40 7369 -91.92.194.144 1031 -91.98.96.76 5385 -92.244.238.115 3115 -92.97.68.210 58000 -93.100.182.236 32249 -93.11.175.113 22948 -93.115.202.240 64493 -93.152.132.9 12332 -94.154.81.100 12345 -94.222.188.14 29299 -95.211.117.105 62086 -95.219.143.102 10360 -95.222.119.133 43087 -95.42.138.33 16550 -96.39.191.231 52000 -99.192.24.198 52552 -103.226.250.79 3521 -103.82.242.163 8083 -104.156.238.118 34731 -104.237.149.26 64879 -107.155.5.39 6881 -109.129.202.63 11076 -109.148.168.121 21651 -109.24.244.111 33334 -110.81.114.66 24732 -111.175.84.3 6881 -111.216.9.68 13493 -113.105.18.227 16001 -113.194.69.53 53858 -113.219.200.7 12935 -113.252.78.238 23474 -113.68.239.87 6396 -113.69.96.171 51443 -114.188.193.161 22555 -114.231.190.193 51413 -114.232.201.253 30350 -114.32.153.245 26233 -114.32.1.94 7788 -114.38.137.40 24062 -114.75.44.238 6881 -115.133.66.181 9460 -115.205.157.105 51413 -116.1.193.182 51413 -117.247.200.35 5353 -117.60.240.145 35709 -117.60.62.8 51413 -117.93.101.232 51413 -118.123.245.182 5060 -119.177.21.161 27048 -119.64.245.112 56265 -121.171.118.184 11566 -121.178.169.67 49259 -121.234.117.237 15398 -122.116.102.22 14054 -123.202.146.112 23118 -123.217.135.139 7830 -128.68.229.32 51413 -134.209.114.242 8000 -139.28.218.4 34826 -142.113.115.71 26453 -148.251.68.55 50000 -148.70.53.219 2551 -150.117.108.250 21902 -150.117.44.190 25052 -151.224.15.227 51413 -157.157.157.41 51413 -161.97.102.243 51902 -162.208.6.211 51413 -167.179.83.227 60220 -168.70.68.30 18325 -169.0.60.179 64494 -171.5.165.129 6881 -172.104.76.77 60542 -172.104.93.28 35617 -172.98.144.81 19186 -173.176.138.246 9545 -173.199.70.134 39045 -173.212.205.73 51432 -173.212.219.143 6881 -174.89.174.228 51413 -175.197.1.120 52574 -176.9.8.143 58250 -178.118.86.145 51413 -178.162.139.87 10029 -178.32.220.92 6881 -178.67.121.182 49001 -182.138.217.58 6881 -182.138.90.72 50288 -182.139.213.160 39587 -183.131.239.178 57835 -183.22.252.15 21568 -185.126.33.59 50024 -185.156.175.187 1025 -185.157.221.247 25401 -185.252.60.243 49001 -185.45.195.156 28074 -185.45.195.181 28185 -185.45.195.190 28136 -185.61.148.114 64879 -188.133.192.123 19967 -188.235.1.208 7890 -188.240.208.187 51413 -192.181.103.63 19627 -192.241.151.29 6881 -193.242.205.145 49001 -193.77.153.124 59835 -194.176.114.54 51413 -194.35.233.206 20124 -195.154.172.169 36097 -195.154.172.169 38340 -195.154.172.169 48043 -195.154.172.169 48799 -195.154.179.2 22794 -195.154.179.2 41210 -195.154.179.2 42687 -195.154.179.2 49156 -195.154.179.2 50385 -195.154.179.2 50944 -195.154.181.225 37558 -195.191.246.240 1026 -196.191.92.25 22937 -197.157.219.137 22629 -197.61.66.105 24612 -198.13.48.70 37360 -199.254.238.193 15374 -200.63.107.82 13323 -201.241.63.68 38705 -203.130.242.178 28280 -203.213.61.76 50559 -207.154.222.13 51111 -210.195.211.60 49771 -210.6.145.50 15207 -212.102.42.202 7611 -212.129.19.188 27096 -212.129.19.188 29812 -212.129.19.188 50117 -212.129.19.188 51965 -212.129.33.59 6881 -212.32.231.67 51413 -212.86.51.7 65148 -213.136.79.7 11910 -218.161.100.192 51413 -218.219.199.148 18753 -220.189.94.56 13279 -222.211.148.83 8080 -222.77.110.143 46016 -223.116.81.154 10655 -223.16.153.107 51413 -223.26.31.77 21440 -223.65.101.235 25159 diff --git a/libbitdht/src/bitdht/bdboot_generate.sh b/libbitdht/src/bitdht/bdboot_generate.sh deleted file mode 100755 index 97618f0df..000000000 --- a/libbitdht/src/bitdht/bdboot_generate.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -< - -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 . - -LICENSE - -< bdboot.txt --------------------------------- -README - -function check_dht_host() -{ - mHost="$1" - mPort="$2" - - sudo nmap -oG - -sU -p $mPort $mHost | grep open | \ - awk '{print $2" "$5}' | awk -F/ '{print $1}' -} - -cat | while read line; do - hostIP="$(echo $line | awk '{print $1}')" - hostPort="$(echo $line | awk '{print $2}')" - check_dht_host $hostIP $hostPort -done - -check_dht_host router.utorrent.com 6881 -check_dht_host router.bittorrent.com 6881 -check_dht_host dht.libtorrent.org 25401 -check_dht_host dht.transmissionbt.com 6881 - diff --git a/libbitdht/src/bitdht/bdconnection.cc b/libbitdht/src/bitdht/bdconnection.cc deleted file mode 100644 index 494e076f3..000000000 --- a/libbitdht/src/bitdht/bdconnection.cc +++ /dev/null @@ -1,3528 +0,0 @@ -/******************************************************************************* - * bitdht/bdconnection.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include "bitdht/bdiface.h" - -#include "bitdht/bdnode.h" -#include "bitdht/bdquerymgr.h" -#include "bitdht/bdconnection.h" -#include "bitdht/bdmsgs.h" -#include "bitdht/bdstddht.h" -#include "util/bdnet.h" -#include "util/bdrandom.h" -#include "util/bdstring.h" - -/* - * #define DEBUG_PROXY_CONNECTION 1 - * #define DEBUG_NODE_CONNECTION 1 - * #define DEBUG_NODE_CONNECTION_EXTRA 1 - * #define DEBUG_CONNECTION_DELAY 1 - */ - -//#define DEBUG_PROXY_CONNECTION 1 -//#define DEBUG_NODE_CONNECTION 1 -//#define DEBUG_CONNECTION_DELAY 1 - - -#define BITDHT_CR_PAUSE_SHORT_PERIOD 1 -#define BITDHT_CR_PAUSE_START_PERIOD 10 - -#define MAX_NUM_RETRIES 3 - -uint32_t createConnectionErrorCode(uint32_t userProvided, uint32_t fallback, uint32_t point); - -/************************************************************************************************************ -******************************************** Connection Config ********************************************** -************************************************************************************************************/ - -bdConnectManager::bdConnectManager(bdNodeId *ownId, bdSpace *space, bdQueryManager *qmgr, bdDhtFunctions *fns, bdNodePublisher *pub) - :mOwnId(*ownId), mNodeSpace(space), mQueryMgr(qmgr), mFns(fns), mPub(pub) -{ - defaultConnectionOptions(); -} - - - - -void bdConnectManager::defaultConnectionOptions() -{ - /* by default we want to help people proxy connections. - * As this involves no interaction at higher levels, - * we want ALL BitDHT clients to support - unless explicitly disabled. - */ - - setConnectionOptions(BITDHT_CONNECT_MODE_PROXY, - BITDHT_CONNECT_OPTION_AUTOPROXY); -} - -void bdConnectManager::setConnectionOptions(uint32_t allowedModes, uint32_t flags) -{ - mConfigAllowedModes = allowedModes; - mConfigAutoProxy = false; - - if (flags & BITDHT_CONNECT_OPTION_AUTOPROXY) - { - mConfigAutoProxy = true; - } - -} - -/* Setup Relay Mode */ -void bdConnectManager::setRelayMode(uint32_t mode) -{ - mRelayMode = mode; -} - - -void bdConnectManager::shutdownConnections() -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::shutdownConnections() Brutal Shutdown of the following connections: "; - std::cerr << std::endl; - - printConnections(); -#endif - - mConnectionRequests.clear(); - mConnections.clear(); - -} - -void bdConnectManager::printConnections() -{ - std::cerr << "bdConnectManager::printConnections()"; - std::cerr << std::endl; - - std::map::iterator it; - for(it = mConnectionRequests.begin(); it != mConnectionRequests.end(); it++) - { - std::cerr << "bdConnectManager::printConnections() Connect Request:"; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; - } - - std::map::iterator tit; - for(tit = mConnections.begin(); tit != mConnections.end(); tit++) - { - std::cerr << "bdConnectManager::printConnections() ConnectAttempt:"; - std::cerr << std::endl; - std::cerr << tit->second; - std::cerr << std::endl; - } -} - - - - - - -/************************************************************************************************************ -****************************************** Connection Initiation ******************************************** -************************************************************************************************************/ - - -/* This is called to initialise a connection. - * the callback could be with regard to: - * a Direct EndPoint. - * a Proxy Proxy, or an Proxy EndPoint. - * a Relay Proxy, or an Relay EndPoint. - * - * We have two alternatives: - * 1) Direct Endpoint. - * 2) Using a Proxy. - */ - -int bdConnectManager::requestConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start) -{ - /* check if connection obj already exists */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection() Mode: " << mode; - std::cerr << " Start: " << start; - std::cerr << " Target: "; - mFns->bdPrintNodeId(std::cerr, target); - std::cerr << " Local NetAddress: " << inet_ntoa(laddr->sin_addr); - std::cerr << ":" << ntohs(laddr->sin_port); - std::cerr << std::endl; -#endif - - if (!start) - { - return killConnectionRequest(laddr, target, mode); - } - - if (!(mConfigAllowedModes & mode)) - { - /* MODE not supported */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection() Mode Not Supported"; - std::cerr << std::endl; -#endif - return 0; - } - - // Seems like a dumb one, but the testing picked it up. - if (*target == mOwnId) - { - /* MODE not supported */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection() WARNING Not allowing connection to self"; - std::cerr << std::endl; -#endif - return 0; - } - - if (mode == BITDHT_CONNECT_MODE_DIRECT) - { - return requestConnection_direct(laddr, target); - } - else - { - return requestConnection_proxy(laddr, target, mode, delay); - } -} - -int bdConnectManager::checkExistingConnectionAttempt(bdNodeId *target) -{ - std::map::iterator it; - it = mConnectionRequests.find(*target); - if (it != mConnectionRequests.end()) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::checkExistingConnectAttempt() Found Existing Connection!"; - std::cerr << std::endl; -#endif - return 1; - } - return 0; -} - - -int bdConnectManager::killConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode) -{ - /* remove unused parameter warnings */ - (void) laddr; - (void) mode; - - /* check if connection obj already exists */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::killConnectionRequest() Mode: " << mode; - std::cerr << " Target: "; - mFns->bdPrintNodeId(std::cerr, target); - std::cerr << " Local NetAddress: " << inet_ntoa(laddr->sin_addr); - std::cerr << ":" << ntohs(laddr->sin_port); - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mConnectionRequests.find(*target); - if (it == mConnectionRequests.end()) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::killConnectionRequest() ERROR Request not there!"; - std::cerr << std::endl; -#endif - return 0; - } - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::killConnectionRequest() Flagging Connection Request as DONE"; - std::cerr << std::endl; -#endif - - time_t now = time(NULL); - it->second.mState = BITDHT_CONNREQUEST_DONE; - it->second.mStateTS = now; - it->second.mErrCode = BITDHT_CONNECT_ERROR_SOURCE_START | - BITDHT_CONNECT_ERROR_USER; - - -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::killConnectionRequest() Flagging Connection Request as DONE"; - std::cerr << std::endl; - // Print Connection Attempt. - std::cerr << it->second << std::endl; -#endif - - return 1; -} - - - - -#define MIN_START_DIRECT_COUNT 1 -#define MIN_START_PROXY_COUNT 3 -#define MED_START_PROXY_COUNT 5 -#define CONNECT_NUM_PROXY_ATTEMPTS 10 - - -int bdConnectManager::requestConnection_direct(struct sockaddr_in *laddr, bdNodeId *target) -{ - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection_direct()"; - std::cerr << std::endl; -#endif - /* create a bdConnect, and put into the queue */ - bdConnectionRequest connreq; - - if (checkExistingConnectionAttempt(target)) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection_direct() Existing ConnectionRequest... NOOP"; - std::cerr << std::endl; -#endif - return 0; - } - - connreq.setupDirectConnection(laddr, target); - - std::list goodProxies; - std::list::iterator pit; - mQueryMgr->result(target, goodProxies); - for(pit = goodProxies.begin(); pit != goodProxies.end(); pit++) - { - connreq.mGoodProxies.push_back(bdProxyId(*pit, BD_PI_SRC_QUERYRESULT, 0)); - } - - /* now look in the bdSpace as well */ - if (connreq.mGoodProxies.size() < MIN_START_DIRECT_COUNT) - { - int number = CONNECT_NUM_PROXY_ATTEMPTS; - int with_flag = BITDHT_PEER_STATUS_DHT_ENGINE_VERSION; - std::list matchIds; - std::list::iterator it; - std::list::iterator git; - - mNodeSpace->find_node(target, number, matchIds, with_flag); - - /* merge lists (costly should use sets or something) */ - for(it = matchIds.begin(); it != matchIds.end(); it++) - { - for(git = connreq.mGoodProxies.begin(); git != connreq.mGoodProxies.end(); git++) - { - if (git->id == *it) - break; - } - - if (git == connreq.mGoodProxies.end()) - { - connreq.mGoodProxies.push_back(bdProxyId(*it, BD_PI_SRC_NODESPACE_ENGINEVERSION, 0)); - } - } - } - - /* Actually if we lots of ids at this point... its likely that something is wrong - */ - - if (connreq.mGoodProxies.size() > 1) - { - std::cerr << "bdConnectManager::requestConnection_direct() ERROR Multiple Peers for DIRECT connection"; - std::cerr << std::endl; - } - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection_direct() CRINITSTATE Init Connection State"; - std::cerr << std::endl; - std::cerr << connreq; - std::cerr << std::endl; -#endif - - /* push connect onto queue, for later completion */ - - mConnectionRequests[*target] = connreq; - - /* connection continued via iterator */ - return 1; -} - - -int bdConnectManager::requestConnection_proxy(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay) -{ - -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy()"; - std::cerr << std::endl; -#endif - - - if (checkExistingConnectionAttempt(target)) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Existing ConnectionRequest... NOOP"; - std::cerr << std::endl; -#endif - return 0; - } - - /* create a bdConnect, and put into the queue */ - bdConnectionRequest connreq; - connreq.setupProxyConnection(laddr, target, mode, delay); - - /**** - * We want different behaviour here - depending on whether it is a proxy or a relay request - * furthermore if we are in relay server mode - we should only use those. - * - * Try to unify logic. - * - * Proxy - take potential proxies... - * - if RelayServerMode then relays. - * - take friends, friends of friends. - * - * Relay - - * - if RelayServerMode take relays. - * - take friends, friends of friends - * - take potential proxies. - */ - - - /* get the proxy lists from existing query */ - std::list::iterator pit; - std::list goodProxies; - std::list potentialProxies; - mQueryMgr->proxies(target, goodProxies); - mQueryMgr->potentialProxies(target, potentialProxies); - - /* check any potential proxies, must be same DHT Type */ - for(pit = potentialProxies.begin(); pit != potentialProxies.end(); ) - { - /* check the type in bdSpace */ - if (checkPeerForFlag(&(*pit), BITDHT_PEER_STATUS_DHT_ENGINE_VERSION)) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Shifting Pot -> Good: "; - mFns->bdPrintId(std::cerr, &(*pit)); - std::cerr << std::endl; -#endif - goodProxies.push_back(*pit); - pit = potentialProxies.erase(pit); - } - else - { - pit++; - } - } - - /* in proxy mode - put Good Proxies First */ - if (mode == BITDHT_CONNECT_MODE_PROXY) - { - for(pit = goodProxies.begin(); pit != goodProxies.end(); pit++) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Adding Good Proxy: "; - mFns->bdPrintId(std::cerr, &(*pit)); - std::cerr << std::endl; -#endif - connreq.mGoodProxies.push_back(bdProxyId(*pit, BD_PI_SRC_QUERYPROXY, 0)); - } - } - - - if (mRelayMode) - { - /* Add Relay Servers */ -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() In RelayMode... adding Relays"; -#endif - - std::list excluding; - std::multimap nearest; - - int number = CONNECT_NUM_PROXY_ATTEMPTS; - - mNodeSpace->find_nearest_nodes_with_flags(target, number, excluding, nearest, - BITDHT_PEER_STATUS_DHT_RELAY_SERVER); - - std::multimap::iterator it; - for(it = nearest.begin(); it != nearest.end(); it++) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Adding Relay Server: "; - mFns->bdPrintId(std::cerr, &(it->second)); - std::cerr << std::endl; -#endif - connreq.mGoodProxies.push_back(bdProxyId(it->second, BD_PI_SRC_NODESPACE_SERVER, 0)); - } - } - - { - std::list excluding; - std::multimap nearest; - - int number = CONNECT_NUM_PROXY_ATTEMPTS; - - mNodeSpace->find_nearest_nodes_with_flags(target, number, excluding, nearest, - BITDHT_PEER_STATUS_DHT_FRIEND); - - std::multimap::iterator it; - for(it = nearest.begin(); it != nearest.end(); it++) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Adding Friend: "; - mFns->bdPrintId(std::cerr, &(it->second)); - std::cerr << std::endl; -#endif - connreq.mGoodProxies.push_back(bdProxyId(it->second, BD_PI_SRC_NODESPACE_FRIEND, 0)); - } - } - - - /* in relay mode - Good Proxies are the BackUp */ - if (mode == BITDHT_CONNECT_MODE_RELAY) - { - for(pit = goodProxies.begin(); pit != goodProxies.end(); pit++) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Adding Good Proxy: "; - mFns->bdPrintId(std::cerr, &(*pit)); - std::cerr << std::endl; -#endif - connreq.mGoodProxies.push_back(bdProxyId(*pit, BD_PI_SRC_QUERYPROXY, 0)); - } - } - - // Final Desperate Measures! - if (connreq.mGoodProxies.size() < MED_START_PROXY_COUNT) - { - std::list excluding; - std::multimap nearest; - - int number = CONNECT_NUM_PROXY_ATTEMPTS; - - mNodeSpace->find_nearest_nodes_with_flags(target, number, excluding, nearest, - BITDHT_PEER_STATUS_DHT_FOF); - - std::multimap::iterator it; - for(it = nearest.begin(); it != nearest.end(); it++) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Querying FOF: "; - mFns->bdPrintId(std::cerr, &(it->second)); - std::cerr << std::endl; -#endif - //connreq.mGoodProxies.push_back(it->second); - mPub->send_query(&(it->second), target, true); - } - } - - - /* if we don't have enough proxies ... ping the potentials */ - if (connreq.mGoodProxies.size() < MED_START_PROXY_COUNT) - { - /* unknown, add to potential list, and ping! */ - for(pit = potentialProxies.begin(); pit != potentialProxies.end(); pit++) - { - - connreq.mPotentialProxies.push_back(*pit); - // If the pings come back will be handled by - // updatePotentialConnectionProxy() - - mPub->send_ping(&(*pit)); - -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Pinging Potential Proxy"; - mFns->bdPrintId(std::cerr, &(*pit)); - std::cerr << std::endl; -#endif - } - } - - /*** ORIGINAL CODE - TRIES TO PING/SEARCH PEERS - INSTEAD OF JUST TRYING THEM - * NOT SURE WHAT THE BEST PLAN IS..... - * LEAVE THIS CODE HERE FOR REFERENCE.... - ***/ - -#if 0 - // Final Desperate Measures! - if (connreq.mGoodProxies.size() < MED_START_PROXY_COUNT) - { - /* now find closest acceptable peers, - * and trigger a search for target... - * this will hopefully find more suitable proxies. - */ - - std::list excluding; - std::multimap nearest; - - - int number = CONNECT_NUM_PROXY_ATTEMPTS; - - mNodeSpace->find_nearest_nodes_with_flags(target, number, excluding, nearest, - BITDHT_PEER_STATUS_DHT_FOF | - BITDHT_PEER_STATUS_DHT_FRIEND); - - // just ask for the same number of closest (above doesn't return anything atm) - //int nFound = nearest.size(); - //number = CONNECT_NUM_PROXY_ATTEMPTS - nFound; - - mNodeSpace->find_nearest_nodes_with_flags(target, number, excluding, nearest, - BITDHT_PEER_STATUS_DHT_ENGINE_VERSION ); - - std::multimap::iterator it; - for(it = nearest.begin(); it != nearest.end(); it++) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() is Entry it connected to Friend? : "; - mFns->bdPrintId(std::cerr, &(it->second)); - std::cerr << std::endl; -#endif - - //bdNodeId midId; - //mFns->bdRandomMidId(target, &(it->second.id), &midId); - /* trigger search */ - //mPub->send_query(&(it->second), &midId); - mPub->send_query(&(it->second), target); - } - } -#endif - - - if (connreq.mGoodProxies.size() < 1) - { - std::cerr << "bdConnectManager::requestConnection_proxy() ERROR initial proxyList.size() == 0"; - std::cerr << std::endl; - } - - if (connreq.mGoodProxies.size() < MIN_START_PROXY_COUNT) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() WARNING initial proxyList.size() == SMALL PAUSING"; - std::cerr << std::endl; -#endif - - time_t now = time(NULL); - /* PAUSE the connection Attempt, so we can wait for responses */ - connreq.mState = BITDHT_CONNREQUEST_PAUSED; - connreq.mPauseTS = now + BITDHT_CR_PAUSE_START_PERIOD; - } - -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() CRINITSTATE Init Connection State"; - std::cerr << std::endl; - std::cerr << connreq; - std::cerr << std::endl; -#endif - - - /* push connect onto queue, for later completion */ - mConnectionRequests[*target] = connreq; - - return 1; -} - - - - -void bdConnectManager::addPotentialConnectionProxy(const bdId *srcId, const bdId *target) -{ -#ifdef DEBUG_NODE_CONNECTION_EXTRA - std::cerr << "bdConnectManager::addPotentialConnectionProxy() "; - std::cerr << " srcId: "; - bdStdPrintId(std::cerr, srcId); - std::cerr << " target: "; - bdStdPrintId(std::cerr, target); - std::cerr << std::endl; -#endif - - if (!srcId) - { - /* not one of our targets... drop it */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::addPotentialConnectionProxy() srcID = NULL, useless to us"; - std::cerr << std::endl; -#endif - return; - } - - std::map::iterator it; - it = mConnectionRequests.find(target->id); - if (it == mConnectionRequests.end()) - { - /* not one of our targets... drop it */ -#ifdef DEBUG_NODE_CONNECTION_EXTRA - std::cerr << "bdConnectManager::addPotentialConnectionProxy() Dropping Not one of Our Targets"; - std::cerr << std::endl; -#endif - return; - } - - if (it->second.mMode == BITDHT_CONNECT_MODE_DIRECT) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::addPotentialConnectionProxy() Dropping Target is DIRECT"; - std::cerr << std::endl; -#endif - return; - } - - /* This is one is strange elsewhere.... srcId = targetId. - * This means that peer is actually reachable! and we should be connecting directly. - * however there is not much we can do about it here. Really up to higher level logic. - */ - if (srcId->id == target->id) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::addPotentialConnectionProxy() ERROR srcId.id == target.id (more of a WARNING)"; - std::cerr << std::endl; - std::cerr << "bdConnectManager::addPotentialConnectionProxy() NB: This means peer is actually reachable...."; - std::cerr << std::endl; - std::cerr << "bdConnectManager::addPotentialConnectionProxy() and we should be connecting directly. Oh Well!"; - std::cerr << std::endl; -#endif - return; - } - - if (checkPeerForFlag(srcId, BITDHT_PEER_STATUS_DHT_ENGINE_VERSION)) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::addPotentialConnectionProxy() Src passes FLAG test"; - std::cerr << std::endl; -#endif - it->second.addGoodProxy(srcId); - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::addPotentialConnectionProxy() Dropping SrcId failed FLAG test"; - std::cerr << std::endl; -#endif - } -} - - -int bdConnectManager::checkPeerForFlag(const bdId *id, uint32_t with_flag) -{ - /* check the type in bdSpace */ - bdPeer peer; - if (mNodeSpace->find_exactnode(id, peer)) - { - if (peer.mPeerFlags & with_flag) - { - return 1; - } - } - /* XXX eventually we'll need to check against extra peer lists. - * with our friends, etc - * - * ideally we'll track this info in the query! - */ - - return 0; -} - - -void bdConnectManager::updatePotentialConnectionProxy(const bdId *id, uint32_t mode) -{ - if (mode & BITDHT_PEER_STATUS_DHT_ENGINE_VERSION) - { -#ifdef DEBUG_NODE_CONNECTION_EXTRA - std::cerr << "bdConnectManager::updatePotentialConnectionProxy() Peer is GOOD : "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; - std::cerr << "bdConnectManager::updatePotentialConnectionProxy() checking Connection Requests"; - std::cerr << std::endl; -#endif - /* good peer, see if any of our connectionrequests can use it */ - std::map::iterator it; - for(it = mConnectionRequests.begin(); it != mConnectionRequests.end(); it++) - { - it->second.checkGoodProxyPeer(id); - } - } -} - - -int bdConnectManager::tickConnections() -{ - iterateConnectionRequests(); - iterateConnections(); - - return 1; -} - - -void bdConnectManager::iterateConnectionRequests() -{ - time_t now = time(NULL); - - std::list eraseList; - std::list::iterator eit; - - std::map::iterator it; - for(it = mConnectionRequests.begin(); it != mConnectionRequests.end(); it++) - { - bool erase = false; - -#ifdef DEBUG_NODE_CONNECTION_EXTRA - std::cerr << "bdConnectManager::iterateConnectionAttempt() Request is:"; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; -#endif - - /* check status of connection */ - if (it->second.mState == BITDHT_CONNREQUEST_READY) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() Request is READY, starting"; - std::cerr << std::endl; -#endif - - /* kick off the connection if possible */ - // goes to BITDHT_CONNREQUEST_INPROGRESS; - if (!startConnectionAttempt(&(it->second))) - { -#ifdef DEBUG_NODE_CONNECTION - // FAILS if proxy is bad / nonexistent - std::cerr << "bdConnectManager::iterateConnectionAttempt() Failed startup => KILLED"; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; -#endif - - it->second.mErrCode = BITDHT_CONNECT_ERROR_SOURCE_START | - BITDHT_CONNECT_ERROR_OUTOFPROXY; - it->second.mState = BITDHT_CONNREQUEST_DONE; - it->second.mStateTS = now; - - } - } - else if (it->second.mState == BITDHT_CONNREQUEST_PAUSED) - { - /* forced pause, with period specified at PAUSE point */ - if (now > it->second.mPauseTS) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() PAUSED has reached timout -> READY"; - std::cerr << std::endl; -#endif - - /* if we have run out of proxies, or recycled too many times. kill it */ - if (it->second.mGoodProxies.size() == 0) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() no more proxies => DONE"; - std::cerr << std::endl; -#endif - - it->second.mErrCode = BITDHT_CONNECT_ERROR_SOURCE_START | - BITDHT_CONNECT_ERROR_OUTOFPROXY; - it->second.mState = BITDHT_CONNREQUEST_DONE; - it->second.mStateTS = now; - } - else if ((unsigned) it->second.mRecycled > it->second.mGoodProxies.size() * MAX_NUM_RETRIES) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() to many retries => DONE"; - std::cerr << std::endl; -#endif - - it->second.mErrCode = BITDHT_CONNECT_ERROR_SOURCE_START | - BITDHT_CONNECT_ERROR_TOOMANYRETRY; - it->second.mState = BITDHT_CONNREQUEST_DONE; - it->second.mStateTS = now; - } - else - { - /* timeout and restart */ - it->second.mState = BITDHT_CONNREQUEST_READY; - it->second.mStateTS = now; - } - } - } - else if (it->second.mState == BITDHT_CONNREQUEST_INPROGRESS) - { - /* single connection attempt */ - if (now - it->second.mStateTS > BITDHT_CONNREQUEST_TIMEOUT_INPROGRESS) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() INPROGRESS has reached timout -> READY"; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; -#endif - - /* timeout and restart */ - it->second.mState = BITDHT_CONNREQUEST_PAUSED; - it->second.mStateTS = now; - it->second.mPauseTS = now + BITDHT_CR_PAUSE_SHORT_PERIOD; - } - } - else if (it->second.mState == BITDHT_CONNREQUEST_EXTCONNECT) - { - /* connection completed, doing UDP connection */ - if (now - it->second.mStateTS > BITDHT_CONNREQUEST_TIMEOUT_CONNECT) - { - std::cerr << "bdConnectManager::iterateConnectionAttempt() ERROR EXTCONNECT has reached timout -> SHOULD NEVER HAPPEN... KILL this query:"; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; - - /* timeout and restart */ - it->second.mErrCode = BITDHT_CONNECT_ERROR_SOURCE_START | - BITDHT_CONNECT_ERROR_PROTOCOL; - it->second.mState = BITDHT_CONNREQUEST_DONE; - it->second.mStateTS = now; - } - } - else if (it->second.mState == BITDHT_CONNREQUEST_DONE) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() DONE -> erase"; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; -#endif - - erase = true; - - } - - // Cleanup - if (now - it->second.mStateTS > BITDHT_CONNREQUEST_MAX_AGE) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() Should clean Old ConnReq???: "; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; -#endif - } - - if (erase) - { - /* do callback */ - bdId srcId; - bdId proxyId; - bdId destId; - - destId.id = it->second.mTarget; - int param = 0; - callbackConnect(&srcId, &proxyId, &destId, it->second.mMode, - BD_PROXY_CONNECTION_START_POINT, param, - BITDHT_CONNECT_CB_REQUEST, it->second.mErrCode); - - /* cleanup */ - eraseList.push_back(it->first); - } - } - - for(eit = eraseList.begin(); eit != eraseList.end(); eit++) - { - it = mConnectionRequests.find(*eit); - if (it != mConnectionRequests.end()) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() Erasing Old Connection Request: "; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; -#endif - - mConnectionRequests.erase(it); - } - } -} - - - -int bdConnectManager::startConnectionAttempt(bdConnectionRequest *req) -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectionAttempt() ConnReq: "; - std::cerr << std::endl; - std::cerr << *req; - std::cerr << std::endl; -#endif - - if (req->mGoodProxies.size() < 1) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectionAttempt() No Potential Proxies... delaying attempt"; - std::cerr << std::endl; -#endif - return 0; - } - - bdId proxyId; - bdId srcConnAddr; - bdId destConnAddr; - - int mode = req->mMode; - - /* calculate the delay... accounting for the time since the request */ - time_t now = time(NULL); - int timeElapsed = (now - req->mRequestTS); - int delay = req->mDelay - timeElapsed; - int absDelay = 0; - if (delay > 0) - { - absDelay = delay; - } -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectionAttempt() TimeSinceReq: " << timeElapsed << " Original Delay: " << req->mDelay; - std::cerr << " AbsDelay: " << absDelay; - std::cerr << std::endl; -#endif - - destConnAddr.id = req->mTarget; - bdsockaddr_clear(&(destConnAddr.addr)); - - srcConnAddr.id = mOwnId; - srcConnAddr.addr = req->mLocalAddr; - - bdProxyId pidset = req->mGoodProxies.front(); - proxyId = pidset.id; - req->mGoodProxies.pop_front(); - - req->mCurrentAttempt = proxyId; - req->mCurrentSrcType = pidset.srcType; - - //req->mPeersTried.push_back(proxyId); - - req->mState = BITDHT_CONNREQUEST_INPROGRESS; - req->mStateTS = time(NULL); - - if (mode == BITDHT_CONNECT_MODE_DIRECT) - { - // ONE BUG I HAVE SEEN. - if (!(req->mTarget == proxyId.id)) - { - std::cerr << "bdConnectManager::startConnectionAttempt() ERROR Trying to use a Proxy for DIRECT"; - std::cerr << std::endl; - - return 0; - } - } - else - { - if (req->mTarget == proxyId.id) - { - std::cerr << "bdConnectManager::startConnectionAttempt() ERROR Trying connect direct for PROXY|RELAY"; - std::cerr << std::endl; - - return 0; - } - } - - - return startConnectionAttempt(&proxyId, &srcConnAddr, &destConnAddr, mode, absDelay); -} - - - -/************************************************************************************************************ -****************************************** Outgoing Triggers ************************************************ -************************************************************************************************************/ - -/************************************************************************************************************ -****************************************** Outgoing Triggers ************************************************ -************************************************************************************************************/ - -/************************************************************************************************************ -*************************************** Connection Requests Callback **************************************** -************************************************************************************************************/ - -/* Lots of Callbacks come through here... The Connection Request gets flagged, and the message - * get passed on up if necessary. - */ - -void bdConnectManager::callbackConnectRequest(bdId *srcId, bdId *proxyId, bdId *destId, - int mode, int point, int param, int cbtype, int errcode) -{ - /* Check if we are the originator of the Connect Request. If so, then we do stuff to the CR. - */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "mode: " << mode; - std::cerr << " point: " << point; - std::cerr << " param: " << param; - std::cerr << " cbtype: " << cbtype; - std::cerr << " errcode: " << errcode; - std::cerr << std::endl; - - std::cerr << "\tsrcId: "; - bdStdPrintId(std::cerr, srcId); - std::cerr << std::endl; - std::cerr << "\tproxyId: "; - bdStdPrintId(std::cerr, proxyId); - std::cerr << std::endl; - std::cerr << "\tdestId: "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; -#endif - - - if (point != BD_PROXY_CONNECTION_START_POINT) - { - /* ONLY ONE CASE THAT GOES HERE -> for sanity testing */ - if ((cbtype == BITDHT_CONNECT_CB_START) && (point == BD_PROXY_CONNECTION_END_POINT)) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() END & START checking ConnectRequest state"; - std::cerr << std::endl; -#endif - - // Reverse lookup (srcId). - std::map::iterator it = mConnectionRequests.find(srcId->id); - if (it != mConnectionRequests.end()) - { - if (it->second.mState == BITDHT_CONNREQUEST_INPROGRESS) - { - /* AT THIS POINT - WE SHOULD SWITCH IT INTO EXTCONNECT MODE????, - * which will timeout - if it fails... - * THIS is effectively the end of the connection attempt anyway. - * if UDP succeeds or fails, will Kill either way. - */ - std::cerr << "bdConnectManager::callbackConnectRequest() ERROR ALT CR also in progress!"; - std::cerr << std::endl; - - } - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() WARNING Switching ALT CR to EXTCONNECT Mode"; - std::cerr << std::endl; -#endif - - time_t now = time(NULL); - it->second.mState = BITDHT_CONNREQUEST_EXTCONNECT; - it->second.mStateTS = now; - - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() No ALT CR - Good"; - std::cerr << std::endl; -#endif - - } - callbackConnect(srcId, proxyId, destId, mode, point, param, cbtype, errcode); - return; - } - - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR point != START, should not be receiving this callback, ignoring"; - std::cerr << std::endl; - return; - } - - /* now find our peer in the map */ - std::map::iterator it = mConnectionRequests.find(destId->id); - if (it == mConnectionRequests.end()) - { - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR no associated Connection Request, ignoring"; - std::cerr << std::endl; - return; - } - bdConnectionRequest *cr = &(it->second); - time_t now = time(NULL); - - /* what types of cbtype can we get? - * BITDHT_CONNECT_CB_AUTH not as START - * BITDHT_CONNECT_CB_PENDING not as START - * BITDHT_CONNECT_CB_START YES important, change state to PAUSED and pass up - * BITDHT_CONNECT_CB_PROXY not as START - * BITDHT_CONNECT_CB_FAILED YES most important, trigger next one - */ - - switch(cbtype) - { - default: // all fallthrough. - case BITDHT_CONNECT_CB_AUTH: - case BITDHT_CONNECT_CB_PENDING: - case BITDHT_CONNECT_CB_PROXY: - { - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR unexpected CBTYPE: AUTH/PENDING/PROXY/other. ignoring"; - std::cerr << std::endl; - return; - } - - case BITDHT_CONNECT_CB_FAILED: - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "Connection FAILED.... determining if fatal/recycle/next"; - std::cerr << std::endl; -#endif - - // one more big switch statement, to decide: fatal/delay/or next - // default is move to next proxy/peer. - bool fatal = false; - bool recycle = false; - - int errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE; - int errsrc = errcode & BITDHT_CONNECT_ERROR_MASK_SOURCE; - - switch(errtype) - { - default: - // (These could be fatal or recycle cases... but really ERROR, try NEXT. - case BITDHT_CONNECT_ERROR_GENERIC: - case BITDHT_CONNECT_ERROR_PROTOCOL: - case BITDHT_CONNECT_ERROR_TIMEOUT: // SHould never receive. - { - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR unexpected errcode: " << errcode; - std::cerr << std::endl; - } - break; - - // FATAL ONES. - case BITDHT_CONNECT_ERROR_UNREACHABLE: // END has Unstable ExtAddr. ONLY(PROXYMODE,END) - { - if ((errsrc == BITDHT_CONNECT_ERROR_SOURCE_END) && - (mode == BITDHT_CONNECT_MODE_PROXY)) - { - // fatal. - fatal = true; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "END says UNREACHABLE. FATAL ;("; - std::cerr << std::endl; -#endif - } - else - { - // error. - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR, UNREACHABLE, but !END"; - std::cerr << std::endl; - } - } - break; - case BITDHT_CONNECT_ERROR_AUTH_DENIED: // END won't accept conn END|PROXY, RELAY|PROXY - { - if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_END) - { - // fatal. - fatal = true; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "END says AUTH_DENIED, fatal"; - std::cerr << std::endl; -#endif - } - else if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_MID) - { - // next. (unlikely). -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "WARNING MID says AUTH_DENIED"; - std::cerr << std::endl; -#endif - } - else - { - // error. - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR strange AUTH_DENIED"; - std::cerr << std::endl; - } - } - break; - case BITDHT_CONNECT_ERROR_UNSUPPORTED: // mode is unsupprted. fatal or next ANY/ANY - { - if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_END) - { - // fatal. - fatal = true; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "END says UNSUPPORTED, fatal"; - std::cerr << std::endl; -#endif - } - else if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_MID) - { - // next. -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "MID says UNSUPPORTED"; - std::cerr << std::endl; -#endif - - } - else - { - // error. - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR strange UNSUPPORTED"; - std::cerr << std::endl; - - } - } - break; - - // RECYCLE PROXY - case BITDHT_CONNECT_ERROR_TEMPUNAVAIL: // only END | PROXY, no extAddress - { - if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_END) - { - fatal = true; - //recycle = true; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "END says TEMPUNAVAIL, fatal (retried at higher level)"; - std::cerr << std::endl; -#endif - } - else - { - // next. - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR strange TEMPUNAVAIL"; - std::cerr << std::endl; - - } - } - break; - case BITDHT_CONNECT_ERROR_DUPLICATE: // similar attempt. delay/recycle (ANY/ANY) - { - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << " DUPLICATE, fatal"; - std::cerr << std::endl; -#endif - - fatal = true; - //recycle = true; - } - break; - case BITDHT_CONNECT_ERROR_OVERLOADED: // not more space. PROXY in RELAY mode. - { - if ((errsrc == BITDHT_CONNECT_ERROR_SOURCE_MID) && - (mode == BITDHT_CONNECT_MODE_RELAY)) - { - recycle = true; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "MID says OVERLOADED, recycle"; - std::cerr << std::endl; -#endif - - } - else - { - //ERROR. - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR strange OVERLOADED"; - std::cerr << std::endl; - } - } - break; - - // NEXT PROXY. - case BITDHT_CONNECT_ERROR_NOADDRESS: //Proxy doesn't know peer MID/(RELAY|PROXY) - { - if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_MID) - { - // could recycle? probably still won't work. -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "MID says NOADDRESS"; - std::cerr << std::endl; -#endif - } - else - { - //ERROR. - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR strange NOADDRESS"; - std::cerr << std::endl; - } - } - break; - } // end of error code switch. - - // Now act on the decision. - if (fatal) - { - /* kill connection request, do callback */ - /* setup for next one */ - cr->mState = BITDHT_CONNREQUEST_DONE; - } - else - { - if (recycle) - { - /* rotate around */ - cr->mGoodProxies.push_back(bdProxyId(cr->mCurrentAttempt, cr->mCurrentSrcType, errcode)); - cr->mRecycled++; - } - else - { - cr->mPeersTried.push_back(bdProxyId(cr->mCurrentAttempt, cr->mCurrentSrcType, errcode)); - } - - /* setup for next one */ - cr->mState = BITDHT_CONNREQUEST_PAUSED; - cr->mPauseTS = now + BITDHT_CR_PAUSE_SHORT_PERIOD; - } - - cr->mStateTS = now; - cr->mErrCode = errcode; - - /* just pass on the callbackConnect() */ - callbackConnect(srcId, proxyId, destId, mode, point, param, cbtype, errcode); - - return; // CALLBACK FINISHED for FAILURE CODES. - - } - break; - case BITDHT_CONNECT_CB_START: - { - - cr->mState = BITDHT_CONNREQUEST_EXTCONNECT; - cr->mStateTS = now; - - callbackConnect(srcId, proxyId, destId, mode, point, param, cbtype, errcode); - - } - break; - } -} - - - -/************************************************************************************************************ -************************************** END of Connection Requests ******************************************* -************************************************************************************************************/ - -/************************************************************************************************************ -****************************************** Outgoing Triggers ************************************************ -************************************************************************************************************/ - -/*** Called by iterator. - * initiates the connection startup - * - * srcConnAddr must contain Own ID + Connection Port (DHT or TOU depending on Mode). - * - * For a DIRECT Connection: proxyId == destination Id, and mode == DIRECT. - * - * For RELAY | PROXY Connection: - * - * In all cases, destConnAddr doesn't need to contain a valid address. - */ - -int bdConnectManager::startConnectionAttempt(bdId *proxyId, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay) -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectionAttempt()"; - std::cerr << std::endl; -#endif - - if (!(mConfigAllowedModes & mode)) - { - /* MODE not supported */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectionAttempt() ERROR Mode Not Supported"; - std::cerr << std::endl; -#endif - return 0; - } - - /* Check for existing Connection */ - bdConnection *conn = findExistingConnectionBySender(proxyId, srcConnAddr, destConnAddr); - if (conn) - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectAttempt() ERROR EXISTING CONNECTION"; - std::cerr << std::endl; -#endif - return 0; - } - - - /* Switch the order of peers around to test for "opposite connections" */ - if (NULL != findSimilarConnection(&(destConnAddr->id), &(srcConnAddr->id))) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectAttempt() WARNING Found Similar Connection. returning 0"; - std::cerr << std::endl; -#endif - - return 0; - } - - - { - // DO A CALLBACK to TELL higher levels, we are starting a connection attempt. - int point = BD_PROXY_CONNECTION_START_POINT; - int cbtype = BITDHT_CONNECT_CB_REQUEST; - int errcode = 0; - int param = 0; - callbackConnect(srcConnAddr, proxyId, destConnAddr, mode, point, param, cbtype, errcode); - } - - /* INSTALL a NEW CONNECTION */ - // not offically playing by the rules, but it should work. - conn = newConnectionBySender(proxyId, srcConnAddr, destConnAddr); - - if (mode == BITDHT_CONNECT_MODE_DIRECT) - { - /* proxy is the real peer address, destConnAddr has an invalid address */ - conn->ConnectionSetupDirect(proxyId, srcConnAddr); - } - else - { - conn->ConnectionSetup(proxyId, srcConnAddr, destConnAddr, mode, delay); - } - - - int msgtype = BITDHT_MSG_TYPE_CONNECT_REQUEST; - int status = BITDHT_CONNECT_ANSWER_OKAY; - mPub->send_connect_msg(&(conn->mProxyId), msgtype, - &(conn->mSrcConnAddr), &(conn->mDestConnAddr), conn->mMode, conn->mMaxDelay, status); - - return 1; -} - -/* This will be called in response to a callback. - * the callback could be with regard to: - * a Direct EndPoint. - * a Proxy Proxy, or an Proxy EndPoint. - * a Relay Proxy, or an Relay EndPoint. - * - * If we are going to store the minimal amount in the bdNode about connections, - * then the parameters must contain all the information: - * - * case 1: - * - */ - -void bdConnectManager::AuthConnectionOk(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int bandwidth, int delay) -{ - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk()"; - std::cerr << std::endl; -#endif - - /* Check for existing Connection */ - bdConnection *conn = findExistingConnection(&(srcId->id), &(proxyId->id), &(destId->id)); - if (!conn) - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() ERROR NO EXISTING CONNECTION"; - std::cerr << std::endl; -#endif - return; - } - - /* we need to continue the connection */ - if (mode == BITDHT_CONNECT_MODE_DIRECT) - { - if (conn->mState == BITDHT_CONNECTION_WAITING_AUTH) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() Direct Connection, in WAITING_AUTH state... Authorising Direct Connect"; - std::cerr << std::endl; -#endif - /* This pushes it into the START/ACK cycle, - * which handles messages elsewhere - */ - conn->AuthoriseDirectConnection(srcId, proxyId, destId, mode, loc); - } - else - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() ERROR Direct Connection, !WAITING_AUTH state... Ignoring"; - std::cerr << std::endl; -#endif - - } - return; - } - - if (loc == BD_PROXY_CONNECTION_END_POINT) - { - if (conn->mState == BITDHT_CONNECTION_WAITING_AUTH) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() Proxy End Connection, in WAITING_AUTH state... Authorising"; - std::cerr << std::endl; -#endif - /*** XXX MUST RECEIVE THE ADDRESS FROM DEST for connection */ - conn->AuthoriseEndConnection(srcId, proxyId, destId, mode, loc, delay); - - /* we respond to the proxy which will finalise connection */ - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - int status = BITDHT_CONNECT_ANSWER_OKAY; - mPub->send_connect_msg(&(conn->mProxyId), msgtype, - &(conn->mSrcConnAddr), &(conn->mDestConnAddr), conn->mMode, conn->mMaxDelay, status); - - return; - } - else - { - - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() ERROR Proxy End Connection, !WAITING_AUTH state... Ignoring"; - std::cerr << std::endl; -#endif - } - } - - if (conn->mState == BITDHT_CONNECTION_WAITING_AUTH) - { - /* otherwise we are the proxy (for either), pass on the request */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() Proxy Mid Connection, in WAITING_AUTH state... Authorising"; - std::cerr << std::endl; -#endif - - /* SEARCH for IP:Port of destination is done before AUTH */ - conn->AuthoriseProxyConnection(srcId, proxyId, destId, mode, loc, bandwidth); - - int msgtype = BITDHT_MSG_TYPE_CONNECT_REQUEST; - int status = BITDHT_CONNECT_ANSWER_OKAY; - int param = 0; - mPub->send_connect_msg(&(conn->mDestId), msgtype, - &(conn->mSrcConnAddr), &(conn->mDestConnAddr), conn->mMode, param, status); - } - else - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() ERROR Proxy Mid Connection, !WAITING_AUTH state... Ignoring"; - std::cerr << std::endl; -#endif - } - - return; -} - - - - -void bdConnectManager::AuthConnectionNo(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int errCode) -{ - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionNo()"; - std::cerr << std::endl; -#endif - - /* Check for existing Connection */ - bdConnection *conn = findExistingConnection(&(srcId->id), &(proxyId->id), &(destId->id)); - if (!conn) - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionNo() ERROR NO EXISTING CONNECTION"; - std::cerr << std::endl; -#endif - return; - } - - /* we need indicate failure of the connection */ - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - uint32_t status = createConnectionErrorCode(errCode, BITDHT_CONNECT_ERROR_AUTH_DENIED, conn->mPoint); - - if (mode == BITDHT_CONNECT_MODE_DIRECT) - { - /* we respond to the proxy which will finalise connection */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionNo() Direct End Connection Cleaning up"; - std::cerr << std::endl; -#endif - mPub->send_connect_msg(&(conn->mSrcId), msgtype, - &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, 0, status); - - cleanConnection(&(srcId->id), &(proxyId->id), &(destId->id)); - return; - } - - if (loc == BD_PROXY_CONNECTION_END_POINT) - { - /* we respond to the proxy which will finalise connection */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionNo() Proxy End Connection Cleaning up"; - std::cerr << std::endl; -#endif - mPub->send_connect_msg(&(conn->mProxyId), msgtype, - &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, 0, status); - - cleanConnection(&(srcId->id), &(proxyId->id), &(destId->id)); - - return; - } - - /* otherwise we are the proxy (for either), reply FAIL */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionNo() Proxy Mid Connection Cleaning up"; - std::cerr << std::endl; -#endif - mPub->send_connect_msg(&(conn->mSrcId), msgtype, - &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, 0, status); - - cleanConnection(&(srcId->id), &(proxyId->id), &(destId->id)); - - return; -} - - - - - -void bdConnectManager::iterateConnections() -{ - std::map::iterator it; - std::list eraseList; - time_t now = time(NULL); - - for(it = mConnections.begin(); it != mConnections.end(); it++) - { - if (now - it->second.mLastEvent > BD_CONNECTION_MAX_TIMEOUT) - { - /* cleanup event */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnections() Connection Timed Out: " << (it->first); - std::cerr << std::endl; -#endif - eraseList.push_back(it->first); - continue; - } - - /* Can I add a Quick Kill for connections that just haven't worked? TODO */ - - if ((it->second.mState == BITDHT_CONNECTION_WAITING_ACK) && - (now - it->second.mLastStart > BD_CONNECTION_START_RETRY_PERIOD)) - { - if (it->second.mRetryCount > BD_CONNECTION_START_MAX_RETRY) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnections() Start/ACK cycle, Too many iterations: " << it->first; - std::cerr << std::endl; -#endif - /* connection failed! cleanup */ - if ((it->second.mMode != BITDHT_CONNECT_MODE_PROXY) || (!mConfigAutoProxy)) - { - uint32_t errCode = createConnectionErrorCode(0, - BITDHT_CONNECT_ERROR_TIMEOUT,it->second.mPoint); - int param = 0; - callbackConnect(&(it->second.mSrcId),&(it->second.mProxyId), - &(it->second.mDestId), it->second.mMode, it->second.mPoint, param, - BITDHT_CONNECT_CB_FAILED, errCode); - } - - /* add to erase list */ - eraseList.push_back(it->first); - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnections() Start/ACK cycle, Retransmitting START: " << it->first; - std::cerr << std::endl; -#endif - it->second.mLastStart = now; - it->second.mRetryCount++; - - int bandwidth = it->second.mBandwidth; - int delay = it->second.mMaxDelay; - time_t elapsedTime = (time(NULL) - it->second.mConnectionStartTS); - int remainingDelay = delay - elapsedTime; - if (remainingDelay < 0) - { - remainingDelay = 0; - } - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnections() Start/ACK cycle: remaining Delay: " << remainingDelay; - std::cerr << std::endl; - std::cerr << "bdConnectManager::iterateConnections() Start/ACK cycle: Bandwidth: " << bandwidth; - std::cerr << std::endl; -#endif - - // Must calculate the correct delay's here!!!! - int delayOrBandwidth = remainingDelay; - if (it->second.mMode == BITDHT_CONNECT_MODE_RELAY) - { - delayOrBandwidth = bandwidth; - } - - if (!it->second.mSrcAck) - { - int msgtype = BITDHT_MSG_TYPE_CONNECT_START; - mPub->send_connect_msg(&(it->second.mSrcId), msgtype, - &(it->second.mSrcConnAddr), &(it->second.mDestConnAddr), - it->second.mMode, delayOrBandwidth, BITDHT_CONNECT_ANSWER_OKAY); - } - if (!it->second.mDestAck) - { - int msgtype = BITDHT_MSG_TYPE_CONNECT_START; - mPub->send_connect_msg(&(it->second.mDestId), msgtype, - &(it->second.mSrcConnAddr), &(it->second.mDestConnAddr), - it->second.mMode, delayOrBandwidth, BITDHT_CONNECT_ANSWER_OKAY); - } - } - } - } - - /* clean up */ - while(eraseList.size() > 0) - { - bdProxyTuple tuple = eraseList.front(); - eraseList.pop_front(); - - std::map::iterator eit = mConnections.find(tuple); - mConnections.erase(eit); - } -} - - - - -/************************************************************************************************************ -****************************************** Callback Functions ******************************************** -************************************************************************************************************/ - - -void bdConnectManager::callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, - int mode, int point, int param, int cbtype, int errcode) -{ - /* This is overloaded at a higher level */ - mPub->callbackConnect(srcId, proxyId, destId, mode, point, param, cbtype, errcode); -} - - -/************************************************************************************************************ -************************************** ProxyTuple + Connection State **************************************** -************************************************************************************************************/ - -int operator<(const bdProxyTuple &a, const bdProxyTuple &b) -{ - if (a.srcId < b.srcId) - { - return 1; - } - - if (a.srcId == b.srcId) - { - if (a.proxyId < b.proxyId) - { - return 1; - } - else if (a.proxyId == b.proxyId) - { - if (a.destId < b.destId) - { - return 1; - } - } - } - return 0; -} - -int operator==(const bdProxyTuple &a, const bdProxyTuple &b) -{ - if ((a.srcId == b.srcId) && (a.proxyId == b.proxyId) && (a.destId == b.destId)) - { - return 1; - } - return 0; -} - -std::ostream &operator<<(std::ostream &out, const bdProxyTuple &t) -{ - out << "[---"; - bdStdPrintNodeId(out, &(t.srcId)); - out << "---"; - bdStdPrintNodeId(out, &(t.proxyId)); - out << "---"; - bdStdPrintNodeId(out, &(t.destId)); - out << "---]"; - - return out; -} - -bdConnection::bdConnection() -{ - /* DUMMY INITIALISATION FOR ALL DATA - DON"T THINK IT MATTERS - * But keeps Valgrind happy - */ - - /* Connection State, and TimeStamp of Update */ - mState = 0; - mLastEvent = 0; - // - ///* Addresses of Start/Proxy/End Nodes */ - //bdId mSrcId; - //bdId mDestId; - //bdId mProxyId; - // - ///* Where we are in the connection, - //* and what connection mode. - //*/ - mPoint = 0; - mMode = 0; - // - ///* must have ip:ports of connection ends (if proxied) */ - //bdId mSrcConnAddr; - //bdId mDestConnAddr; - // - mBandwidth = 0; - mMaxDelay = 0; - mConnectionStartTS = 0; - - // - ///* START/ACK Finishing ****/ - mLastStart = 0; /* timer for retries */ - mRetryCount = 0; /* retry counter */ - // - mSrcAck = false; - mDestAck = false; - // - //// Completion TS. - mCompletedTS = 0; -} - - /* heavy check, used to check for alternative connections, coming from other direction - * Caller must switch src/dest to use it properly (otherwise it'll find your connection!) - */ -bdConnection *bdConnectManager::findSimilarConnection(bdNodeId *srcId, bdNodeId *destId) -{ - std::map::iterator it; - for(it = mConnections.begin(); it != mConnections.end(); it++) - { - if ((it->first.srcId == *srcId) && (it->first.destId == *destId)) - { - /* found similar connection */ - return &(it->second); - } - } - return NULL; -} - -bdConnection *bdConnectManager::findExistingConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId) -{ - bdProxyTuple tuple(srcId, proxyId, destId); - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::findExistingConnection() Looking For: " << tuple << std::endl; -#endif - - std::map::iterator it = mConnections.find(tuple); - if (it == mConnections.end()) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::findExistingConnection() Failed to Find: " << tuple << std::endl; -#endif - return NULL; - } - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::findExistingConnection() Found: " << tuple << std::endl; -#endif - return &(it->second); -} - -bdConnection *bdConnectManager::newConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId) -{ - bdProxyTuple tuple(srcId, proxyId, destId); - bdConnection conn; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::newConnection() Installing: " << tuple << std::endl; -#endif - - mConnections[tuple] = conn; - std::map::iterator it = mConnections.find(tuple); - if (it == mConnections.end()) - { - std::cerr << "bdConnectManager::newConnection() ERROR Installing: " << tuple << std::endl; - return NULL; - } - return &(it->second); -} - -int bdConnectManager::cleanConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId) -{ - bdProxyTuple tuple(srcId, proxyId, destId); - bdConnection conn; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::cleanConnection() Removing: " << tuple << std::endl; -#endif - - std::map::iterator it = mConnections.find(tuple); - if (it == mConnections.end()) - { - std::cerr << "bdConnectManager::cleanConnection() ERROR Removing: " << tuple << std::endl; - return 0; - } - mConnections.erase(it); - - return 1; -} - - -int bdConnectManager::determinePosition(bdNodeId */*sender*/, bdNodeId *src, bdNodeId *dest) -{ - int pos = BD_PROXY_CONNECTION_UNKNOWN_POINT; - if (mOwnId == *src) - { - pos = BD_PROXY_CONNECTION_START_POINT; - } - else if (mOwnId == *dest) - { - pos = BD_PROXY_CONNECTION_END_POINT; - } - else - { - pos = BD_PROXY_CONNECTION_MID_POINT; - } - return pos; -} - -int bdConnectManager::determineProxyId(bdNodeId *sender, bdNodeId *src, bdNodeId *dest, bdNodeId *proxyId) -{ - int pos = determinePosition(sender, src, dest); - switch(pos) - { - case BD_PROXY_CONNECTION_START_POINT: - case BD_PROXY_CONNECTION_END_POINT: - *proxyId = *sender; - return 1; - break; - default: - case BD_PROXY_CONNECTION_MID_POINT: - *proxyId = mOwnId; - return 1; - break; - } - return 0; -} - - - -bdConnection *bdConnectManager::findExistingConnectionBySender(bdId *sender, bdId *src, bdId *dest) -{ - bdNodeId proxyId; - bdNodeId *senderId = &(sender->id); - bdNodeId *srcId = &(src->id); - bdNodeId *destId = &(dest->id); - determineProxyId(senderId, srcId, destId, &proxyId); - - return findExistingConnection(srcId, &proxyId, destId); -} - -bdConnection *bdConnectManager::newConnectionBySender(bdId *sender, bdId *src, bdId *dest) -{ - bdNodeId proxyId; - bdNodeId *senderId = &(sender->id); - bdNodeId *srcId = &(src->id); - bdNodeId *destId = &(dest->id); - determineProxyId(senderId, srcId, destId, &proxyId); - - return newConnection(srcId, &proxyId, destId); -} - - -int bdConnectManager::cleanConnectionBySender(bdId *sender, bdId *src, bdId *dest) -{ - bdNodeId proxyId; - bdNodeId *senderId = &(sender->id); - bdNodeId *srcId = &(src->id); - bdNodeId *destId = &(dest->id); - determineProxyId(senderId, srcId, destId, &proxyId); - - return cleanConnection(srcId, &proxyId, destId); -} - - -/************************************************************************************************************ -****************************************** Received Connect Msgs ******************************************** -************************************************************************************************************/ - - -/* This function is triggered by a CONNECT_REQUEST message. - * it will occur on both the Proxy/Dest in the case of a Proxy (PROXY | RELAY) and on the Dest (DIRECT) nodes. - * - * In all cases, we store the request and ask for authentication. - * - */ - - - -int bdConnectManager::recvedConnectionRequest(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay) -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest()"; - std::cerr << std::endl; -#endif - - if (!(mConfigAllowedModes & mode)) - { - /* MODE not supported */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING Mode Not Supported"; - std::cerr << std::endl; -#endif - /* reply existing connection */ - int pos = determinePosition(&(id->id), &(srcConnAddr->id), &(destConnAddr->id)); - uint32_t status = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_UNSUPPORTED, pos); - - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - mPub->send_connect_msg(id, msgtype, srcConnAddr, destConnAddr, mode, 0, status); - - return 0; - } - - /* Check for existing Connection */ - bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); - if (conn) - { - /* Likely ERROR: Warning */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING Existing Connection: "; - std::cerr << std::endl; - std::cerr << std::endl; -#endif - /* reply existing connection */ - uint32_t status = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_DUPLICATE, conn->mPoint); - - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - int param = 0; - mPub->send_connect_msg(id, msgtype, srcConnAddr, destConnAddr, mode, param, status); - - return 0; - } - - - /* Switch the order of peers around to test for "opposite connections" */ - if (NULL != findSimilarConnection(&(destConnAddr->id), &(srcConnAddr->id))) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING Found Similar Connection. Replying NO"; - std::cerr << std::endl; -#endif - - /* reply existing connection */ - int pos = determinePosition(&(id->id), &(srcConnAddr->id), &(destConnAddr->id)); - uint32_t status = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_DUPLICATE, pos); - - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - int param = 0; - mPub->send_connect_msg(id, msgtype, srcConnAddr, destConnAddr, mode, param, status); - return 0; - } - - /* INSTALL a NEW CONNECTION */ - conn = bdConnectManager::newConnectionBySender(id, srcConnAddr, destConnAddr); - - int point = 0; - if (mode == BITDHT_CONNECT_MODE_DIRECT) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() Installing DIRECT CONNECTION"; - std::cerr << std::endl; -#endif - - /* we are actually the end node, store stuff, get auth and on with it! */ - point = BD_PROXY_CONNECTION_END_POINT; - - conn->ConnectionRequestDirect(id, srcConnAddr, destConnAddr); - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() Connection State:"; - std::cerr << std::endl; - std::cerr << *conn; - std::cerr << std::endl; -#endif - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_AUTH, - BITDHT_CONNECT_ERROR_NONE); - } - else - { - /* check if we are proxy, or end point */ - bool areProxy = (srcConnAddr->id == id->id); - if (areProxy) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() We are MID Point for Proxy / Relay Connection."; - std::cerr << std::endl; -#endif - - point = BD_PROXY_CONNECTION_MID_POINT; - - /* SEARCH for IP:Port of destination before AUTH */ - int numNodes = 10; - std::list matchingIds; - - std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING searching for \"VERSION\" flag... TO FIX LATER"; - std::cerr << std::endl; - - uint32_t with_flag = BITDHT_PEER_STATUS_DHT_ENGINE_VERSION; - //BITDHT_PEER_STATUS_DHT_APPL | BITDHT_PEER_STATUS_DHT_APPL_VERSION); - - bool proxyOk = false; - bdId destId; - - if (mNodeSpace->find_node(&(destConnAddr->id), numNodes, matchingIds, with_flag)) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() Found Suitable Destination Addr"; - std::cerr << std::endl; -#endif - - if (matchingIds.size() > 1) - { - /* WARNING multiple matches */ - std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING Found Multiple Matching Destination Addr"; - std::cerr << std::endl; - } - - proxyOk = true; - destId = matchingIds.front(); - } - - if (proxyOk) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() Proxy Addr Ok: "; - bdStdPrintId(std::cerr, destConnAddr); - std::cerr << "asking for AUTH to continue"; - std::cerr << std::endl; -#endif - - conn->ConnectionRequestProxy(id, srcConnAddr, &mOwnId, &destId, mode, delay); - - /* ALLOW AUTO AUTH for MID Proxy Connections. */ - if ((mConfigAutoProxy) && (mode == BITDHT_CONNECT_MODE_PROXY)) - { - AuthConnectionOk(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, 0, 0); - } - else - { - - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_AUTH, - BITDHT_CONNECT_ERROR_NONE); - } - } - else - { - /* clean up connection... its not going to work */ -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING No Proxy Addr, Shutting Connect Attempt"; - std::cerr << std::endl; -#endif - - - /* send FAIL message to SRC */ - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - uint32_t status = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_NOADDRESS, point); - int param = 0; - mPub->send_connect_msg(id, msgtype, srcConnAddr, destConnAddr, mode, param, status); - - - /* WILL NEED CALLBACK FOR FAILED PROXY ATTEMPT - TO SUPPORT RELAYS PROPERLY - * NODE needs to know PEERS to potentially WHITELIST! - */ - if (mRelayMode == BITDHT_RELAYS_SERVER) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() In RelayServer Mode, doing FAIL callbackConnect()"; - std::cerr << std::endl; -#endif - - bdId proxyId; - proxyId.id = mOwnId; - callbackConnect(srcConnAddr, &proxyId, destConnAddr, mode, point, param, BITDHT_CONNECT_CB_AUTH, - BITDHT_CONNECT_ERROR_NOADDRESS); - } - - /* remove connection */ - bdConnectManager::cleanConnectionBySender(id, srcConnAddr, destConnAddr); - } - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() END Proxy/Relay Connection, asking for AUTH to continue"; - std::cerr << std::endl; -#endif - - point = BD_PROXY_CONNECTION_END_POINT; - - conn->ConnectionRequestEnd(id, srcConnAddr, destConnAddr, mode); - - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_AUTH, - BITDHT_CONNECT_ERROR_NONE); - } - } - return 1; -} - - -/* This function is triggered by a CONNECT_REPLY message. - * it will occur on either the Proxy or Source. And indicates YES / NO to the connection, - * as well as supplying address info to the proxy. - * - */ - -int bdConnectManager::recvedConnectionReply(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay, int status) -{ - /* retrieve existing connection data */ - bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); - if (!conn) - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionReply() ERROR NO EXISTING CONNECTION"; - std::cerr << std::endl; -#endif - return 0; - } - - switch(conn->mPoint) - { - case BD_PROXY_CONNECTION_START_POINT: - case BD_PROXY_CONNECTION_END_POINT: /* NEVER EXPECT THIS */ - case BD_PROXY_CONNECTION_UNKNOWN_POINT: /* NEVER EXPECT THIS */ - default: /* NEVER EXPECT THIS */ - { - - - /* Only situation we expect this, is if the connection is not allowed. - * DEST has sent back an ERROR Message - */ - uint32_t errCode = BITDHT_CONNECT_ERROR_GENERIC; - if ((status != BITDHT_CONNECT_ANSWER_OKAY) && (conn->mPoint == BD_PROXY_CONNECTION_START_POINT)) - { - /* connection is killed */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionReply() WARNING Connection Rejected. Error: "; - std::cerr << decodeConnectionError(status); - std::cerr << ", Killing It: "; - std::cerr << std::endl; - std::cerr << *conn; - std::cerr << std::endl; -#endif - errCode = status; // Pass on the Error Message. - - } - else - { - /* ERROR in protocol */ - std::cerr << "bdConnectManager::recvedConnectionReply() ERROR Unexpected Message, Killing It: "; - std::cerr << std::endl; - std::cerr << *conn; - std::cerr << std::endl; - errCode = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_PROTOCOL, conn->mPoint ); - } - - /* do Callback for Failed Connection */ - if (conn->mPoint == BD_PROXY_CONNECTION_START_POINT) - { - /* As we started the connection, callback internally first! */ - int param = 0; - callbackConnectRequest(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_FAILED, errCode); - } - else - { - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_FAILED, errCode); - } - - /* Kill Connection always */ - cleanConnectionBySender(id, srcConnAddr, destConnAddr); - - return 0; - } - break; - - case BD_PROXY_CONNECTION_MID_POINT: - { - /* We are proxy. and OK / NOK for connection proceed. - */ - - if ((status == BITDHT_CONNECT_ANSWER_OKAY) && (conn->mState == BITDHT_CONNECTION_WAITING_REPLY)) - { - /* OK, continue connection! */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionReply() @MIDPOINT. Reply + State OK, continuing connection"; - std::cerr << std::endl; -#endif - - /* Upgrade Connection to Finishing Mode */ - conn->upgradeProxyConnectionToFinish(id, srcConnAddr, destConnAddr, mode, delay, status); - - /* do Callback for Pending Connection */ - /* DONT CALLBACK in AutoProxy Mode: (PROXY & mConfigAutoProxy) */ - if ((conn->mMode != BITDHT_CONNECT_MODE_PROXY) || (!mConfigAutoProxy)) - { - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_PENDING, - BITDHT_CONNECT_ERROR_NONE); - } - - return 1; - } - else - { - - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionReply() WARNING @MIDPOINT recved Error: "; - std::cerr << decodeConnectionError(status); - std::cerr << " Killing It: "; - std::cerr << std::endl; - std::cerr << *conn; - std::cerr << std::endl; -#endif - - uint32_t errCode = status; - if (errCode == BITDHT_CONNECT_ERROR_NONE) - { - errCode = createConnectionErrorCode(0, - BITDHT_CONNECT_ERROR_PROTOCOL, conn->mPoint ); - } - - /* do Callback for Failed Connection */ - /* DONT CALLBACK in AutoProxy Mode: (PROXY & mConfigAutoProxy) */ - if ((conn->mMode != BITDHT_CONNECT_MODE_PROXY) || (!mConfigAutoProxy)) - { - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_FAILED, errCode); - } - - - /* send on message to SRC */ - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - int param = 0; - mPub->send_connect_msg(&(conn->mSrcId), msgtype, &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, param, errCode); - - /* connection is killed */ - cleanConnectionBySender(id, srcConnAddr, destConnAddr); - } - return 0; - } - break; - } - return 0; -} - - -/* This function is triggered by a CONNECT_START message. - * it will occur on both the Src/Dest in the case of a Proxy (PROXY | RELAY) and on the Src (DIRECT) nodes. - * - * parameters are checked against pending connections. - * Acks are set, and connections completed if possible (including callback!). - */ - -int bdConnectManager::recvedConnectionStart(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delayOrBandwidth) -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionStart()"; - std::cerr << std::endl; -#endif - - /* retrieve existing connection data */ - bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); - if (!conn) - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionStart() ERROR NO EXISTING CONNECTION"; - std::cerr << std::endl; -#endif - return 0; - } - - - if (conn->mPoint == BD_PROXY_CONNECTION_MID_POINT) - { - std::cerr << "bdConnectManager::recvedConnectionStart() ERROR We Are Connection MID Point"; - std::cerr << std::endl; - /* ERROR */ - } - - /* check state */ - if ((conn->mState != BITDHT_CONNECTION_WAITING_START) && (conn->mState != BITDHT_CONNECTION_COMPLETED)) - { - /* ERROR */ - std::cerr << "bdConnectManager::recvedConnectionStart() ERROR State != WAITING_START && != COMPLETED"; - std::cerr << std::endl; - - return 0; - } - - /* ALL Okay, Send ACK */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionStart() Passed basic tests, Okay to send ACK"; - std::cerr << std::endl; -#endif - - int msgtype = BITDHT_MSG_TYPE_CONNECT_ACK; - int status = BITDHT_CONNECT_ANSWER_OKAY; - mPub->send_connect_msg(id, msgtype, &(conn->mSrcId), &(conn->mDestId), mode, 0, status); - - /* do complete Callback */ - - /* flag as completed */ - if (conn->mState != BITDHT_CONNECTION_COMPLETED) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionStart() Switching State to COMPLETED, doing callback"; - std::cerr << std::endl; -#endif - - int param = delayOrBandwidth; - int bandwidth = 0; - int delay = 0; - if (conn->mMode == BITDHT_CONNECT_MODE_RELAY) - { - bandwidth = param; - } - else - { - delay = param; - } - - conn->CompleteConnection(id, srcConnAddr, destConnAddr, bandwidth, delay); - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionStart() Connection State: "; - std::cerr << *conn; - std::cerr << std::endl; -#endif - - - if (conn->mPoint == BD_PROXY_CONNECTION_START_POINT) - { - /* internal callback first */ - callbackConnectRequest(&(conn->mSrcConnAddr),&(conn->mProxyId),&(conn->mDestConnAddr), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_START, - BITDHT_CONNECT_ERROR_NONE); - - } - else - { - /* internal callback first */ - callbackConnectRequest(&(conn->mSrcConnAddr),&(conn->mProxyId),&(conn->mDestConnAddr), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_START, - BITDHT_CONNECT_ERROR_NONE); - } - - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionStart() Just sent duplicate ACK"; - std::cerr << std::endl; -#endif - } - /* don't delete, if ACK is lost, we want to be able to re-respond */ - - return 1; -} - - -/* This function is triggered by a CONNECT_ACK message. - * it will occur on both the Proxy (PROXY | RELAY) and on the Dest (DIRECT) nodes. - * - * parameters are checked against pending connections. - * Acks are set, and connections completed if possible (including callback!). - */ - -int bdConnectManager::recvedConnectionAck(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int /*mode*/) -{ - /* retrieve existing connection data */ - bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); - if (!conn) - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionAck() ERROR NO EXISTING CONNECTION"; - std::cerr << std::endl; -#endif - return 0; - } - - if (conn->mPoint == BD_PROXY_CONNECTION_START_POINT) - { - /* ERROR */ - std::cerr << "bdConnectManager::recvedConnectionAck() ERROR ACK received at START POINT"; - std::cerr << std::endl; - - return 0; - } - - /* check state */ - if (conn->mState != BITDHT_CONNECTION_WAITING_ACK) - { - /* ERROR */ - std::cerr << "bdConnectManager::recvedConnectionAck() ERROR conn->mState != WAITING_ACK, actual State: " << conn->mState; - std::cerr << std::endl; - - return 0; - } - - if (id->id == srcConnAddr->id) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionAck() from Src, marking So"; - std::cerr << std::endl; -#endif - - /* recved Ack from source */ - conn->mSrcAck = true; - } - else if (id->id == destConnAddr->id) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionAck() from Dest, marking So"; - std::cerr << std::endl; -#endif - /* recved Ack from dest */ - conn->mDestAck = true; - } - - if (conn->mSrcAck && conn->mDestAck) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionAck() ACKs from Both Src & Dest, Connection Complete: callback & cleanup"; - std::cerr << std::endl; -#endif - - /* connection complete! cleanup */ - if (conn->mMode == BITDHT_CONNECT_MODE_DIRECT) - { -// int mode = conn->mMode | BITDHT_CONNECT_ANSWER_OKAY; - /* callback to connect to Src address! */ - // Slightly different callback, use ConnAddr for start message! - // Also callback to ConnectionRequest first. - // ACTUALLY we are END, so shouldn't (AT This Point do this). - // MUST callback via ConnectRequest - to prevent duplicate REQUESTS. - int param = 0; - callbackConnectRequest(&(conn->mSrcConnAddr),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_START, - BITDHT_CONNECT_ERROR_NONE); - - } - else - { - /* DONT CALLBACK in AutoProxy Mode: (PROXY & mConfigAutoProxy) */ - if ((conn->mMode != BITDHT_CONNECT_MODE_PROXY) || (!mConfigAutoProxy)) - { - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_PROXY, - BITDHT_CONNECT_ERROR_NONE); - } - - - } - - /* Finished Connection! */ - cleanConnectionBySender(id, srcConnAddr, destConnAddr); - } - return 1; -} - - - -/************************************************************************************************************ -********************************* Connection / ConnectionRequest Functions ********************************** -************************************************************************************************************/ - -// Initialise a new Connection (request by User) - -// Any Connection initialised at Source (START_POINT), prior to Auth. -int bdConnection::ConnectionSetup(bdId *proxyId, bdId *srcConnAddr, bdId *destId, int mode, int delay) -{ - mState = BITDHT_CONNECTION_WAITING_START; /* or REPLY, no AUTH required */ - mLastEvent = time(NULL); - mSrcId = *srcConnAddr; /* self, IP unknown */ - mDestId = *destId; /* dest, IP unknown */ - mProxyId = *proxyId; /* full proxy/dest address */ - - mPoint = BD_PROXY_CONNECTION_START_POINT; - mMode = mode; - - mSrcConnAddr = *srcConnAddr; /* self, full ID/IP */ - mDestConnAddr = *destId; /* IP unknown */ - - mBandwidth = 0; - mMaxDelay = delay; - mConnectionStartTS = time(NULL); - -#ifdef DEBUG_CONNECTION_DELAY - std::cerr << "bdConnection::ConnectionSetup(): delay: " << mMaxDelay; - std::cerr << std::endl; -#endif - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mSrcId.addr)); - bdsockaddr_clear(&(mDestId.addr)); - bdsockaddr_clear(&(mDestConnAddr.addr)); - - /* don't bother with START/ACK parameters */ - - return 1; -} - -int bdConnection::ConnectionSetupDirect(bdId *destId, bdId *srcConnAddr) -{ - mState = BITDHT_CONNECTION_WAITING_START; /* or REPLY, no AUTH required */ - mLastEvent = time(NULL); - mSrcId = *srcConnAddr; /* self, IP unknown */ - mDestId = *destId; /* full proxy/dest address */ - mProxyId = *destId; /* full proxy/dest address */ - - mPoint = BD_PROXY_CONNECTION_START_POINT; - mMode = BITDHT_CONNECT_MODE_DIRECT; - - mSrcConnAddr = *srcConnAddr; /* self, full ID/IP */ - mDestConnAddr = *destId; /* IP unknown */ - - mBandwidth = 0; - mMaxDelay = 0; - mConnectionStartTS = time(NULL); - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mSrcId.addr)); - bdsockaddr_clear(&(mDestConnAddr.addr)); - - /* don't bother with START/ACK parameters */ - - return 1; -} - - - -// Initialise a new Connection. (receiving a Connection Request) -// Direct Connection initialised at Destination (END_POINT), prior to Auth. -int bdConnection::ConnectionRequestDirect(bdId *id, bdId *srcConnAddr, bdId *destId) -{ - mState = BITDHT_CONNECTION_WAITING_AUTH; - mLastEvent = time(NULL); - mSrcId = *id; /* peer ID/IP known */ - mDestId = *destId; /* self, IP unknown */ - mProxyId = *id; /* src ID/IP known */ - - mPoint = BD_PROXY_CONNECTION_END_POINT; - mMode = BITDHT_CONNECT_MODE_DIRECT; - - mSrcConnAddr = *srcConnAddr; /* connect address ID/IP known */ - mDestConnAddr = *destId; /* self IP unknown */ - - mBandwidth = 0; - mMaxDelay = 0; - mConnectionStartTS = time(NULL); - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mDestId.addr)); - bdsockaddr_clear(&(mDestConnAddr.addr)); - - /* don't bother with START/ACK parameters */ - - return 1; -} - - -// Proxy Connection initialised at Proxy (MID_POINT), prior to Auth. -int bdConnection::ConnectionRequestProxy(bdId *id, bdId *srcConnAddr, bdNodeId *ownId, bdId *destId, int mode, int delay) -{ - mState = BITDHT_CONNECTION_WAITING_AUTH; - mLastEvent = time(NULL); - mSrcId = *id; /* ID/IP Known */ - mDestId = *destId; /* destination, ID/IP known */ - mProxyId.id = *ownId; /* own id, must be set for callback, IP Unknown */ - - mPoint = BD_PROXY_CONNECTION_MID_POINT; - mMode = mode; - - mSrcConnAddr = *srcConnAddr; - mDestConnAddr = *destId; /* other peer, IP unknown */ - - mBandwidth = 0; - mMaxDelay = delay; - mConnectionStartTS = time(NULL); - -#ifdef DEBUG_CONNECTION_DELAY - std::cerr << "bdConnection::ConnectionRequestProxy(): received Initial delay: " << mMaxDelay; - std::cerr << std::endl; -#endif - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mProxyId.addr)); - bdsockaddr_clear(&(mDestConnAddr.addr)); - - /* don't bother with START/ACK parameters */ - - return 1; -} - - -// Proxy Connection initialised at Destination (END_POINT), prior to Auth. -int bdConnection::ConnectionRequestEnd(bdId *id, bdId *srcId, bdId *destId, int mode) -{ - mState = BITDHT_CONNECTION_WAITING_AUTH; - mLastEvent = time(NULL); - mSrcId = *srcId; /* src IP unknown */ - mDestId = *destId; /* self, IP unknown */ - mProxyId = *id; /* src of message, full ID/IP of proxy */ - - mPoint = BD_PROXY_CONNECTION_END_POINT; - mMode = mode; - - mSrcConnAddr = *srcId; /* ID, not IP */ - mDestConnAddr = *destId; /* ID, not IP */ - - mBandwidth = 0; - mMaxDelay = 0; - mConnectionStartTS = time(NULL); - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mSrcId.addr)); - bdsockaddr_clear(&(mDestId.addr)); - bdsockaddr_clear(&(mSrcConnAddr.addr)); - bdsockaddr_clear(&(mDestConnAddr.addr)); - - /* don't bother with START/ACK parameters */ - - return 1; -} - -// Received AUTH, step up to next stage. -// Search for dest ID/IP is done before AUTH. so actually nothing to do here, except set the state -int bdConnection::AuthoriseProxyConnection(bdId */*srcId*/, bdId */*proxyId*/, bdId */*destId*/, int /*mode*/, int /*loc*/, int bandwidth) -{ - mState = BITDHT_CONNECTION_WAITING_REPLY; - mLastEvent = time(NULL); - - //mSrcId, (peer) (ID/IP known) - //mDestId (other peer) (ID/IP known) - //mProxyId (self) (IP unknown) - - // mPoint, mMode should be okay. - - mBandwidth = bandwidth; - //mMaxDelay Already set. - //mConnectionStartTS Already Set - -#ifdef DEBUG_CONNECTION_DELAY - std::cerr << "bdConnection::AuthoriseProxyConnection(): received Bandwidth Limitation: " << mBandwidth; - std::cerr << std::endl; -#endif - - // mSrcConnAddr (ID/IP known) - // mDestConnAddr is still pending. - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mProxyId.addr)); - bdsockaddr_clear(&(mDestConnAddr.addr)); - - /* don't bother with START/ACK parameters */ - - return 1; -} - - -/* we are end of a Proxy Connection */ -int bdConnection::AuthoriseEndConnection(bdId */*srcId*/, bdId */*proxyId*/, bdId *destConnAddr, int /*mode*/, int /*loc*/, int delay) -{ - mState = BITDHT_CONNECTION_WAITING_START; - mLastEvent = time(NULL); - - //mSrcId, (peer) should be okay. (IP unknown) - //mDestId (self) doesn't matter. (IP unknown) - //mProxyId (peer) should be okay. (ID/IP known) - - // mPoint, mMode should be okay. - - //mBandwidth not set by us. - time_t elapsedTime = (time(NULL) - mConnectionStartTS); - mMaxDelay = delay + elapsedTime; // relative to mConnectionStartTS. - //mConnectionStartTS // Already Set - -#ifdef DEBUG_CONNECTION_DELAY - std::cerr << "bdConnection::AuthoriseEndConnection(): adjusting delay: " << delay << " by elapsedTime: " << elapsedTime; - std::cerr << " for MaxDelay: " << mMaxDelay; - std::cerr << std::endl; -#endif - - // mSrcConnAddr should be okay. (IP unknown) - // Install the correct destConnAddr. (just received) - mDestConnAddr = *destConnAddr; - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mSrcId.addr)); - bdsockaddr_clear(&(mDestId.addr)); - bdsockaddr_clear(&(mSrcConnAddr.addr)); - - - // Initialise the START/ACK Parameters. - mRetryCount = 0; - mLastStart = 0; - mSrcAck = false; - mDestAck = true; // Automatic ACK, as it is from us. - mCompletedTS = 0; - - return 1; -} - - - - -// Auth of the Direct Connection, means we move straight to WAITING_ACK mode. -int bdConnection::AuthoriseDirectConnection(bdId */*srcId*/, bdId */*proxyId*/, bdId *destConnAddr, int /*mode*/, int /*loc*/) -{ - mState = BITDHT_CONNECTION_WAITING_ACK; - mLastEvent = time(NULL); - - //mSrcId, (peer) should be okay. (ID/IP known) - //mDestId (self) doesn't matter. (IP Unknown) - //mProxyId (peer) should be okay. (ID/IP known) - - // mPoint, mMode should be okay. - - //mBandwidth doesn't matter - //mMaxDelay doesn't matter - //mConnectionStartTS // Already Set - - // mSrcConnAddr should be okay. (ID/IP known) - // Install the correct destConnAddr. (just received) - mDestConnAddr = *destConnAddr; - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mDestId.addr)); - - // Should we check for these? This will not help for the Dest address, as we just blanked it above! */ - checkForDefaultConnectAddress(); - - // Initialise the START/ACK Parameters. - mRetryCount = 0; - mLastStart = 0; - mSrcAck = false; - mDestAck = true; // Automatic ACK, as it is from us. - mCompletedTS = 0; - - return 1; -} - -// Proxy Connection => at Proxy, Ready to send out Start and get back ACKs!! -int bdConnection::upgradeProxyConnectionToFinish(bdId */*id*/, bdId */*srcConnAddr*/, bdId *destConnAddr, int /*mode*/, int secondDelay, int /*status*/) -{ - mState = BITDHT_CONNECTION_WAITING_ACK; - mLastEvent = time(NULL); - - //mSrcId,mDestId should be okay. (ID/IP okay) - //mProxyId, not set, doesn't matter. (IP Unknown) - - // mPoint, mMode should be okay. - - //mBandwidth already set. - time_t elapsedTime = (time(NULL) - mConnectionStartTS); - int remainingDelayOne = mMaxDelay - elapsedTime; - if (secondDelay > remainingDelayOne) - { - /* maxDelay provided by Peer 2.... update calculations */ - mMaxDelay = secondDelay + elapsedTime; // relative to mConnectionStartTS. - } - //mConnectionStartTS // Already Set - -#ifdef DEBUG_CONNECTION_DELAY - std::cerr << "bdConnection::upgradeProxyConnectionToFinish(): elapsedTime: " << elapsedTime << " remainingDelayOne: "; - std::cerr << remainingDelayOne << " secondDelay: " << secondDelay << " => maxDelay: " << mMaxDelay; - std::cerr << std::endl; -#endif - - - if ((secondDelay > 100 || mMaxDelay > 100) || (mBandwidth > 1050)) - { - std::cerr << "bdConnection::upgradeProxyConnectionToFinish(): ERROR Bandwidth or Delay rather large"; - std::cerr << std::endl; - } -#ifdef DEBUG_CONNECTION_DELAY -#endif - - - // mSrcConnAddr should be okay. (ID/IP known) - // Install the correct destConnAddr. (just received) - mDestConnAddr = *destConnAddr; - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mProxyId.addr)); - - checkForDefaultConnectAddress(); - - // Initialise the START/ACK Parameters. - mRetryCount = 0; - mLastStart = 0; - mSrcAck = false; - mDestAck = false; - mCompletedTS = 0; - - return 1; -} - - -// Final Sorting out of Addresses. -// This is called at the Connection Ends, on receiving the START message. -// This will contain either Bandwidth or Delay. -int bdConnection::CompleteConnection(bdId */*id*/, bdId *srcConnAddr, bdId *destConnAddr, int bandwidth, int delay) -{ - /* Store Final Addresses */ - time_t now = time(NULL); - - mState = BITDHT_CONNECTION_COMPLETED; - mCompletedTS = now; - mLastEvent = now; - - mBandwidth = bandwidth; // Received from the Proxy (in the case of a Relay). - time_t elapsedTime = (time(NULL) - mConnectionStartTS); - int remainingOrigDelay = mMaxDelay - elapsedTime; - if (delay > remainingOrigDelay) - { - /* maxDelay provided by Peer 2.... update calculations */ - mMaxDelay = delay + elapsedTime; // relative to mConnectionStartTS. - } - - - if ((delay > 100 || mMaxDelay > 100) || (mBandwidth > 1050)) - { - std::cerr << "bdConnection::CompleteConnection(): ERROR Bandwidth or Delay rather large"; - std::cerr << std::endl; - } -#ifdef DEBUG_CONNECTION_DELAY -#endif - -#ifdef DEBUG_CONNECTION_DELAY - std::cerr << "bdConnection::CompleteConnection(): Bandwidth: " << mBandwidth; - std::cerr << std::endl; - std::cerr << "bdConnection::CompleteConnection(): elapsedTime: " << elapsedTime << " remainingOrigDelay: "; - std::cerr << remainingOrigDelay << " newDelay: " << delay << " => maxDelay: " << mMaxDelay; - std::cerr << std::endl; -#endif - - if (delay < remainingOrigDelay) - { - // ERROR - std::cerr << "bdConnection::CompleteConnection(): ERROR delay: " << delay << " is smaller than remainingOrigDelay: "; - std::cerr << remainingOrigDelay; - std::cerr << std::endl; - } - - // Received Definitive Final Addresses from Proxy. - // These have to be done by proxy, as its the only one who know both our addresses. - - mSrcConnAddr = *srcConnAddr; - mDestConnAddr = *destConnAddr; - - checkForDefaultConnectAddress(); - - return 1; -} - - - -int bdConnection::checkForDefaultConnectAddress() -{ - // We can check if the DestConnAddr / SrcConnAddr are real. - // If there is nothing there, we assume that that want to connect on the - // same IP:Port as the DHT Node. - - if (mSrcConnAddr.addr.sin_addr.s_addr == 0) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::checkForDefaultConnectAddress() SrcConnAddr.addr is BLANK, installing Dht Node Address"; - std::cerr << std::endl; -#endif - - mSrcConnAddr.addr = mSrcId.addr; - } - - if (mDestConnAddr.addr.sin_addr.s_addr == 0) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::checkForDefaultConnectAddress() DestConnAddr.addr is BLANK, installing Dht Node Address"; - std::cerr << std::endl; -#endif - - mDestConnAddr.addr = mDestId.addr; - } - - return 1; - -} - - -int bdConnectionRequest::setupDirectConnection(struct sockaddr_in *laddr, bdNodeId *target) -{ - mState = BITDHT_CONNREQUEST_READY; - mStateTS = time(NULL); - mPauseTS = 0; - mTarget = *target; - mLocalAddr = *laddr; - mMode = BITDHT_CONNECT_MODE_DIRECT; - mRecycled = 0; - mErrCode = 0; - - mDelay = 0; - mRequestTS = time(NULL); - - return 1; -} - -int bdConnectionRequest::setupProxyConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay) -{ - mState = BITDHT_CONNREQUEST_READY; - mStateTS = time(NULL); - mPauseTS = 0; - mTarget = *target; - mLocalAddr = *laddr; - mMode = mode; - mRecycled = 0; - mErrCode = 0; - - mDelay = delay; - mRequestTS = time(NULL); - - return 1; -} - -/* this is a good proxy peer (with flags already checked). - * if it is in the potential proxy list, then we can add it into the good proxy list. - */ - -int bdConnectionRequest::checkGoodProxyPeer(const bdId *id) -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::checkProxyPeer() "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - std::list::iterator it = std::find(mPotentialProxies.begin(), mPotentialProxies.end(), *id); - if (it != mPotentialProxies.end()) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::checkProxyPeer() Found in PotentialProxies List, adding in"; - std::cerr << std::endl; -#endif - - it = mPotentialProxies.erase(it); - - /* now add it in */ - addGoodProxy(id); - } - return 1; -} - - -int bdConnectionRequest::addGoodProxy(const bdId *srcId) -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::addGoodProxy() "; - bdStdPrintId(std::cerr, srcId); - std::cerr << std::endl; -#endif - - if (*srcId == mCurrentAttempt) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::addGoodProxy() Duplicate with CurrentAttempt"; - std::cerr << std::endl; -#endif - return 0; - } - - std::list::iterator it; - for(it = mPeersTried.begin(); it != mPeersTried.end(); it++) - { - if (*srcId == it->id) - break; - } - - if (it == mPeersTried.end()) - { - for(it = mGoodProxies.begin(); it != mGoodProxies.end(); it++) - { - if (*srcId == it->id) - break; - } - - if (it == mGoodProxies.end()) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::addGoodProxy() CRINITSTATE Found New Proxy: "; - bdStdPrintId(std::cerr, srcId); - std::cerr << std::endl; -#endif - - mGoodProxies.push_back(bdProxyId(*srcId, BD_PI_SRC_ADDGOODPROXY, 0)); - - /* if it is potentialProxies then remove */ - std::list::iterator pit; - pit = std::find(mPotentialProxies.begin(), mPotentialProxies.end(), *srcId); - if (pit != mPotentialProxies.end()) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::addGoodProxy() Removing from PotentialProxy List"; - std::cerr << std::endl; -#endif - - pit = mPotentialProxies.erase(pit); - } - return 1; - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::addGoodProxy() Duplicate in mPotentialProxies List"; - std::cerr << std::endl; -#endif - } - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::addGoodProxy() Already tried this peer"; - std::cerr << std::endl; -#endif - } - return 0; -} - - -std::ostream &operator<<(std::ostream &out, const bdConnectionRequest &req) -{ - time_t now = time(NULL); - out << "bdConnectionRequest: "; - out << "State: " << req.mState; - out << " StateTS: " << now - req.mStateTS; - out << " Recycled: " << req.mRecycled; - out << std::endl; - out << "\tTargetId: "; - bdStdPrintNodeId(out, &(req.mTarget)); - out << std::endl; - out << "\tMode: " << req.mMode; - out << std::endl; - out << "\tDelay: " << req.mDelay; - out << " RequestTS: " << now - req.mRequestTS; - out << std::endl; - - out << "CurrentAttempt:"; - bdStdPrintId(out, &(req.mCurrentAttempt)); - out << std::endl; - - out << "GoodProxies:"; - out << std::endl; - - std::list::const_iterator it; - std::list::const_iterator pit; - for(it = req.mGoodProxies.begin(); it != req.mGoodProxies.end(); it++) - { - out << "\t"; - bdStdPrintId(out, &(it->id)); - out << ", " << it->proxySrcType(); - out << ", " << decodeConnectionError(it->errcode); - out << std::endl; - } - - out << "PotentialProxies:"; - out << std::endl; - - for(pit = req.mPotentialProxies.begin(); pit != req.mPotentialProxies.end(); pit++) - { - out << "\t"; - bdStdPrintId(out, &(*pit)); - out << std::endl; - } - - out << "PeersTried:"; - out << std::endl; - - for(it = req.mPeersTried.begin(); it != req.mPeersTried.end(); it++) - { - out << "\t"; - bdStdPrintId(out, &(it->id)); - out << ", " << it->proxySrcType(); - out << ", " << decodeConnectionError(it->errcode); - out << std::endl; - } - return out; -} - -std::ostream &operator<<(std::ostream &out, const bdConnection &conn) -{ - time_t now = time(NULL); - out << "bdConnection: "; - out << "State: " << conn.mState; - out << " LastEvent: " << now - conn.mLastEvent; - out << " Point: " << conn.mPoint; - out << " Mode: " << conn.mMode; - out << std::endl; - - out << "\tsrcId: "; - bdStdPrintId(out, &(conn.mSrcId)); - out << std::endl; - out << "\tproxyId: "; - bdStdPrintId(out, &(conn.mProxyId)); - out << std::endl; - out << "\tdestId: "; - bdStdPrintId(out, &(conn.mDestId)); - out << std::endl; - - out << "\tsrcConnAddr: "; - bdStdPrintId(out, &(conn.mSrcConnAddr)); - out << std::endl; - - out << "\tdestConnAddr: "; - bdStdPrintId(out, &(conn.mDestConnAddr)); - out << std::endl; - - out << "\tretryCount: " << conn.mRetryCount; - out << " retryCount: " << conn.mLastStart; - out << " srcAck: " << conn.mSrcAck; - out << " destAck: " << conn.mDestAck; - out << " completedTS: " << now - conn.mCompletedTS; - - out << "\tBandwidth: " << conn.mBandwidth; - out << " maxDelay: " << conn.mMaxDelay; - out << " startTS: " << now - conn.mConnectionStartTS; - - out << std::endl; - - return out; - -} - - -uint32_t createConnectionErrorCode(uint32_t userProvided, uint32_t fallback, uint32_t point) -{ - int status = userProvided & BITDHT_CONNECT_ERROR_MASK_TYPE; - if (status == BITDHT_CONNECT_ERROR_NONE) - { - status = fallback; - } - /* backup, backup. */ - if (status == BITDHT_CONNECT_ERROR_NONE) - { - status = BITDHT_CONNECT_ERROR_GENERIC; /* FALLBACK ERROR CODE */ - } - - switch(point) - { - case BD_PROXY_CONNECTION_START_POINT: - status |= BITDHT_CONNECT_ERROR_SOURCE_START; - break; - case BD_PROXY_CONNECTION_MID_POINT: - status |= BITDHT_CONNECT_ERROR_SOURCE_MID; - break; - case BD_PROXY_CONNECTION_END_POINT: - status |= BITDHT_CONNECT_ERROR_SOURCE_END; - break; - } - - return status; -} - - - -std::string decodeConnectionErrorType(uint32_t errcode) -{ - uint32_t errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE; - std::string namedtype = "UNKNOWN"; - switch(errtype) - { - default: - bd_sprintf_append(namedtype, "(%lu)", errtype); - break; - case BITDHT_CONNECT_ERROR_GENERIC: - namedtype = "GENERIC"; - break; - case BITDHT_CONNECT_ERROR_PROTOCOL: - namedtype = "PROTOCOL"; - break; - case BITDHT_CONNECT_ERROR_TIMEOUT: - namedtype = "TIMEOUT"; - break; - case BITDHT_CONNECT_ERROR_TEMPUNAVAIL: - namedtype = "TEMPUNAVAIL"; - break; - case BITDHT_CONNECT_ERROR_NOADDRESS: - namedtype = "NOADDRESS"; - break; - case BITDHT_CONNECT_ERROR_UNREACHABLE: - namedtype = "UNREACHABLE"; - break; - case BITDHT_CONNECT_ERROR_UNSUPPORTED: - namedtype = "UNSUPPORTED"; - break; - case BITDHT_CONNECT_ERROR_OVERLOADED: - namedtype = "OVERLOADED"; - break; - case BITDHT_CONNECT_ERROR_AUTH_DENIED: - namedtype = "AUTH_DENIED"; - break; - case BITDHT_CONNECT_ERROR_DUPLICATE: - namedtype = "DUPLICATE"; - break; - case BITDHT_CONNECT_ERROR_TOOMANYRETRY: - namedtype = "TOOMANYRETRY"; - break; - case BITDHT_CONNECT_ERROR_OUTOFPROXY: - namedtype = "OUTOFPROXY"; - break; - case BITDHT_CONNECT_ERROR_USER: - namedtype = "USER DEFINED"; - break; - } - return namedtype; -} - - -std::string decodeConnectionErrorSource(uint32_t errcode) -{ - uint32_t errsrc = errcode & BITDHT_CONNECT_ERROR_MASK_SOURCE; - std::string namedtype = "ERROR SRC UNKNOWN"; - switch(errsrc) - { - default: - bd_sprintf_append(namedtype, "(%lu)", errsrc); - break; - case BITDHT_CONNECT_ERROR_SOURCE_START: - namedtype = "START"; - break; - case BITDHT_CONNECT_ERROR_SOURCE_MID: - namedtype = "MID"; - break; - case BITDHT_CONNECT_ERROR_SOURCE_END: - namedtype = "END"; - break; - case BITDHT_CONNECT_ERROR_SOURCE_OTHER: - namedtype = "OTHER"; - break; - } - return namedtype; -} - - -#if 0 -std::string decodeConnectionErrorCRMove(uint32_t errcode) -{ - uint32_t errcr = errcode & BITDHT_CONNECT_ERROR_MASK_CRMOVE; - std::string namedtype = "UNKNOWN"; - switch(errcr) - { - default: - break; - case 0: - namedtype = "REMOTE"; - break; - case BITDHT_CONNECT_ERROR_CRMOVE_FATAL: - namedtype = "FATAL"; - break; - case BITDHT_CONNECT_ERROR_SOURCE_NOMOREIDS: - namedtype = "NOMOREIDS"; - break; - case BITDHT_CONNECT_ERROR_SOURCE_NEXTID: - namedtype = "NEXTID"; - break; - case BITDHT_CONNECT_ERROR_CRMOVE_PAUSED: - namedtype = "PAUSED"; - break; - } - return namedtype; -} -#endif - - - -std::string decodeConnectionError(uint32_t errcode) -{ - std::string totalerror; - if (!errcode) - { - totalerror = "NoError"; - } - else - { - //totalerror = decodeConnectionErrorCRMove(errcode); - //totalerror += ":"; - totalerror = decodeConnectionErrorSource(errcode); - totalerror += ":"; - totalerror += decodeConnectionErrorType(errcode); - } - - return totalerror; -} - -std::string bdProxyId::proxySrcType() const -{ - std::string str("Unknown"); - - switch (srcType) { - case BD_PI_SRC_QUERYRESULT: - str = "QueryResult"; - break; - case BD_PI_SRC_QUERYPROXY: - str = "QueryProxy"; - break; - case BD_PI_SRC_NODESPACE_FRIEND: - str = "NodeSpaceFriend"; - break; - case BD_PI_SRC_NODESPACE_SERVER: - str = "NodeSpaceServer"; - break; - case BD_PI_SRC_NODESPACE_ENGINEVERSION: - str = "NodeSpaceEngineVersion"; - break; - case BD_PI_SRC_ADDGOODPROXY: - str = "AddGoodProxy"; - break; - case BD_PI_SRC_UNKNOWN: - default: - break; - } - return str; -} - diff --git a/libbitdht/src/bitdht/bdconnection.h b/libbitdht/src/bitdht/bdconnection.h deleted file mode 100644 index c55d95c09..000000000 --- a/libbitdht/src/bitdht/bdconnection.h +++ /dev/null @@ -1,314 +0,0 @@ -/******************************************************************************* - * bitdht/bdconnection.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef BITDHT_CONNECTION_H -#define BITDHT_CONNECTION_H - -#include "bitdht/bdiface.h" - -class bdQueryManager; -class bdNodePublisher; - -/************************************************************************************************************ -************************************** ProxyTuple + Connection State **************************************** -************************************************************************************************************/ - -#define BITDHT_CONNREQUEST_READY 1 -#define BITDHT_CONNREQUEST_PAUSED 2 -#define BITDHT_CONNREQUEST_INPROGRESS 3 -#define BITDHT_CONNREQUEST_EXTCONNECT 4 -#define BITDHT_CONNREQUEST_DONE 5 - -#define BITDHT_CONNREQUEST_TIMEOUT_CONNECT 300 // MAKE THIS LARGE - SHOULD NEVER HAPPEN. -#define BITDHT_CONNREQUEST_TIMEOUT_INPROGRESS 30 -#define BITDHT_CONNREQUEST_MAX_AGE 60 - - -#define BITDHT_CONNECTION_WAITING_AUTH 1 -#define BITDHT_CONNECTION_WAITING_REPLY 2 -#define BITDHT_CONNECTION_WAITING_START 3 -#define BITDHT_CONNECTION_WAITING_ACK 4 -#define BITDHT_CONNECTION_COMPLETED 5 - - -#define BD_CONNECTION_START_RETRY_PERIOD 3 // Should only take a couple of seconds to get reply. -#define BD_CONNECTION_START_MAX_RETRY 3 -#define BD_CONNECTION_MAX_TIMEOUT 20 /* should be quick */ - - - -class bdProxyTuple -{ - public: - bdProxyTuple() { return; } - bdProxyTuple(bdNodeId *s, bdNodeId *p, bdNodeId *d) - :srcId(*s), proxyId(*p), destId(*d) { return; } - - bdNodeId srcId; - bdNodeId proxyId; - bdNodeId destId; -}; - -std::ostream &operator<<(std::ostream &out, const bdProxyTuple &t); -int operator<(const bdProxyTuple &a, const bdProxyTuple &b); -int operator==(const bdProxyTuple &a, const bdProxyTuple &b); - - -class bdConnection -{ - public: - bdConnection(); - - /** Functions to tweak the connection status */ - - // User initialised Connection. - int ConnectionSetup(bdId *proxyId, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay); - int ConnectionSetupDirect(bdId *destId, bdId *srcConnAddr); - - // Initialise a new Connection. (receiving a Connection Request) - int ConnectionRequestDirect(bdId *id, bdId *srcConnAddr, bdId *destConnAddr); - int ConnectionRequestProxy(bdId *id, bdId *srcConnAddr, bdNodeId *ownId, bdId *destConnAddr, int mode, int delay); - int ConnectionRequestEnd(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode); - - // Setup Finishing Stage, (receiving a Connection Reply). - int upgradeProxyConnectionToFinish(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay, int status); - - int AuthoriseDirectConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc); - int AuthoriseProxyConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int bandwidth); - int AuthoriseEndConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int delay); - - int CompleteConnection(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int bandwidth, int delay); - - int checkForDefaultConnectAddress(); - - /* Connection State, and TimeStamp of Update */ - int mState; - time_t mLastEvent; - - /* Addresses of Start/Proxy/End Nodes */ - bdId mSrcId; - bdId mDestId; - bdId mProxyId; - - /* Where we are in the connection, - * and what connection mode. - */ - int mPoint; - int mMode; - - /* must have ip:ports of connection ends (if proxied) */ - bdId mSrcConnAddr; - bdId mDestConnAddr; - - int mBandwidth; - int mMaxDelay; - time_t mConnectionStartTS; - - /* START/ACK Finishing ****/ - time_t mLastStart; /* timer for retries */ - int mRetryCount; /* retry counter */ - - bool mSrcAck; - bool mDestAck; - - // Completion TS. - time_t mCompletedTS; - - -}; - -#define BD_PI_SRC_UNKNOWN 0 -#define BD_PI_SRC_QUERYRESULT 1 -#define BD_PI_SRC_QUERYPROXY 2 -#define BD_PI_SRC_NODESPACE_FRIEND 3 -#define BD_PI_SRC_NODESPACE_SERVER 4 -#define BD_PI_SRC_NODESPACE_ENGINEVERSION 5 -#define BD_PI_SRC_ADDGOODPROXY 6 - - -class bdProxyId -{ -public: - bdProxyId(const bdId &in_id, uint32_t in_srctype, uint32_t in_errcode) - :id(in_id), srcType(in_srctype), errcode(in_errcode) { return; } - - bdProxyId() :srcType(BD_PI_SRC_UNKNOWN), errcode(0) { return; } - - std::string proxySrcType() const; - - bdId id; - uint32_t srcType; - uint32_t errcode; -}; - - -class bdConnectionRequest -{ -public: - bdConnectionRequest() : mMode(0), mState(0), mStateTS(0), mPauseTS(0), mErrCode(0), mDelay(0), mRequestTS(0), mRecycled(0), mCurrentSrcType(0) - { - bdsockaddr_clear(&mLocalAddr); - } - -public: - int setupDirectConnection(struct sockaddr_in *laddr, bdNodeId *target); - int setupProxyConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay); - - int addGoodProxy(const bdId *srcId); - int checkGoodProxyPeer(const bdId *Id); - - bdNodeId mTarget; - struct sockaddr_in mLocalAddr; - int mMode; - - int mState; - time_t mStateTS; - - time_t mPauseTS; - uint32_t mErrCode; - - int mDelay; - time_t mRequestTS; // reference Time for mDelay. - - std::list mGoodProxies; - std::list mPotentialProxies; - //std::list mGoodProxies; - int mRecycled; - - bdId mCurrentAttempt; - uint32_t mCurrentSrcType; - - std::list mPeersTried; - //std::list mPeersTried; -}; - -std::ostream &operator<<(std::ostream &out, const bdConnectionRequest &req); -std::ostream &operator<<(std::ostream &out, const bdConnection &conn); - - -/********* - * The Connection Management Class. - * this encapsulates all of the functionality.. - * except for a couple of message in/outs + callback. - */ - -class bdConnectManager -{ - public: - - bdConnectManager(bdNodeId *ownid, bdSpace *space, bdQueryManager *qmgr, bdDhtFunctions *fns, bdNodePublisher *pub); - - - /* connection functions */ - void requestConnection(bdNodeId *id, uint32_t modes); - void allowConnection(bdNodeId *id, uint32_t modes); - - - /* high level */ - - void shutdownConnections(); - void printConnections(); - - /* Connections: Configuration */ - void defaultConnectionOptions(); - virtual void setConnectionOptions(uint32_t allowedModes, uint32_t flags); - - /* Connections: Initiation */ - - int requestConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start); - int requestConnection_direct(struct sockaddr_in *laddr, bdNodeId *target); - int requestConnection_proxy(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay); - - int killConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode); - - int checkExistingConnectionAttempt(bdNodeId *target); - void addPotentialConnectionProxy(const bdId *srcId, const bdId *target); - void updatePotentialConnectionProxy(const bdId *id, uint32_t mode); - - int checkPeerForFlag(const bdId *id, uint32_t with_flag); - - int tickConnections(); - void iterateConnectionRequests(); - int startConnectionAttempt(bdConnectionRequest *req); - - // internal Callback -> normally continues to callbackConnect(). - void callbackConnectRequest(bdId *srcId, bdId *proxyId, bdId *destId, - int mode, int point, int param, int cbtype, int errcode); - - /* Connections: Outgoing */ - - int startConnectionAttempt(bdId *proxyId, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay); - void AuthConnectionOk(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int bandwidth, int delay); - void AuthConnectionNo(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int errcode); - void iterateConnections(); - - - /* Connections: Utility State */ - - bdConnection *findExistingConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId); - bdConnection *newConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId); - int cleanConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId); - - int determinePosition(bdNodeId *sender, bdNodeId *src, bdNodeId *dest); - int determineProxyId(bdNodeId *sender, bdNodeId *src, bdNodeId *dest, bdNodeId *proxyId); - - bdConnection *findSimilarConnection(bdNodeId *srcId, bdNodeId *destId); - bdConnection *findExistingConnectionBySender(bdId *sender, bdId *src, bdId *dest); - bdConnection *newConnectionBySender(bdId *sender, bdId *src, bdId *dest); - int cleanConnectionBySender(bdId *sender, bdId *src, bdId *dest); - - // Overloaded Generalised Connection Callback. - virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, - int mode, int point, int param, int cbtype, int errcode); - - /* Connections: */ - int recvedConnectionRequest(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay); - int recvedConnectionReply(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay, int status); - int recvedConnectionStart(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delayOrBandwidth); - int recvedConnectionAck(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode); - - /* setup Relay Mode */ - void setRelayMode(uint32_t mode); - - private: - - std::map mConnections; - std::map mConnectionRequests; - - uint32_t mConfigAllowedModes; - bool mConfigAutoProxy; - - uint32_t mRelayMode; - - /****************************** Connection Code (in bdconnection.cc) ****************************/ - - private: - - bdNodeId mOwnId; - bdSpace *mNodeSpace; - bdQueryManager *mQueryMgr; - bdDhtFunctions *mFns; - bdNodePublisher *mPub; -}; - - -#endif // BITDHT_CONNECTION_H diff --git a/libbitdht/src/bitdht/bdfilter.cc b/libbitdht/src/bitdht/bdfilter.cc deleted file mode 100644 index 1ba7d3aca..000000000 --- a/libbitdht/src/bitdht/bdfilter.cc +++ /dev/null @@ -1,318 +0,0 @@ -/******************************************************************************* - * bitdht/bdfilter.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bitdht/bdfilter.h" -#include "bitdht/bdmanager.h" -#include "util/bdfile.h" - -#include -#include -#include -#include -#include - -/** - * #define DEBUG_FILTER 1 -**/ -#define BDFILTER_ENTRY_DROP_PERIOD (7 * 24 * 3600) - -bdFilter::bdFilter(const std::string &fname, const bdNodeId *ownid, uint32_t filterFlags, bdDhtFunctions *fns, bdNodeManager *manager) -{ - /* */ - mOwnId = *ownid; - mFns = fns; - mFilename = fname ; - - loadBannedIpFile() ; - - mFilterFlags = filterFlags; - mNodeManager = manager; -} - -void bdFilter::writeBannedIpFile() -{ - std::string filetmp = mFilename + ".tmp" ; - - FILE *fd = fopen(filetmp.c_str(), "w"); - - if (!fd) - { - std::cerr << "(EE) bdFilter::writeBannedIpFile() FAILED to Open File " << mFilename << std::endl; - return; - } - - for( std::map::iterator it=mFiltered.begin();it!=mFiltered.end();++it) - { - fprintf(fd, "%s %u %lu %lu\n", bdnet_inet_ntoa(it->second.mAddr.sin_addr).c_str(), it->second.mFilterFlags, it->second.mFilterTS, it->second.mLastSeen) ; -#ifdef DEBUG_FILTER - fprintf(stderr, "Storing Peer Address: %s \n", bdnet_inet_ntoa(it->second.mAddr.sin_addr).c_str()) ; -#endif - - } - fclose(fd); - - if(!bdFile::renameFile(filetmp,mFilename)) - std::cerr << "Could not rename file !!" << std::endl; -#ifdef DEBUG_FILTER - else - std::cerr << "Successfully renamed file " << filetmp << " to " << mFilename << std::endl; -#endif -} - -void bdFilter::loadBannedIpFile() -{ - char line[10240]; - char addr_str[10240]; - - struct sockaddr_in addr; - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = PF_INET; - - FILE *fd = fopen(mFilename.c_str(),"r") ; - - if(fd == NULL) - { - std::cerr << "(EE) Cannot load filter file " << mFilename << std::endl; - return ; - } - - while(line == fgets(line, 10240, fd)) - { - uint32_t filter_flags ; - unsigned long long int filter_ts ; - unsigned long long int last_seen ; - - if (4 == sscanf(line, "%s %u %llu %llu", addr_str, &filter_flags,&filter_ts,&last_seen)) - { - if (bdnet_inet_aton(addr_str, &(addr.sin_addr))) - { - addr.sin_port = 0; - - bdFilteredPeer peer; - - peer.mAddr = addr; - peer.mFilterTS = filter_ts; - peer.mLastSeen = last_seen; - peer.mFilterFlags = filter_flags; - - mFiltered[addr.sin_addr.s_addr] = peer ; - #ifdef DEBUG_FILTER - std::cerr << "Loaded filtered IP: " << std::string(addr_str) << " last seen: " << last_seen << ", TS=" << filter_ts << std::endl; - #endif - } - } - } - - fclose(fd); -} - -//bool bdFilter::filtered(std::list &answer) -//{ -// answer = mFiltered; -// return (answer.size() > 0); -//} - -bool bdFilter::filteredIPs(std::list &answer) -{ - std::map::iterator it; - for(it = mFiltered.begin(); it != mFiltered.end(); it++) - { - answer.push_back(it->second.mAddr); - } - return (answer.size() > 0); -} - -int bdFilter::checkPeer(const bdId *id, uint32_t mode) -{ - bool add = false; - uint32_t flags = 0; - if ((mFilterFlags & BITDHT_FILTER_REASON_OWNID) && - isOwnIdWithoutBitDhtFlags(id, mode)) - { - add = true; - flags |= BITDHT_FILTER_REASON_OWNID; - } - - if (add) - { - bool isNew = addPeerToFilter(id->addr, flags); - - if (isNew) - { - return 1; - } - } - - return 0; -} - -int bdFilter::addPeerToFilter(const struct sockaddr_in& addr, uint32_t flags) -{ - std::map::iterator it = mFiltered.find(addr.sin_addr.s_addr) ; - - if(it != mFiltered.end()) - { - it->second.mLastSeen = time(NULL); - it->second.mFilterFlags |= flags; - } - else - { - time_t now = time(NULL); - bdFilteredPeer fp; - - fp.mAddr = addr; - fp.mAddr.sin_port = 0; - fp.mFilterFlags = flags; - fp.mFilterTS = now; - fp.mLastSeen = now; - - uint32_t saddr = addr.sin_addr.s_addr; - - mFiltered[saddr] = fp; - - std::cerr << "Adding New Banned Ip Address: " << bdnet_inet_ntoa(addr.sin_addr); - std::cerr << std::endl; - } - writeBannedIpFile() ; - - return true; -} - -// void bdFilter::loadFilteredPeers(const std::list& peers) -// { -// for(std::list::iterator it = peers.begin(); it != peers.end();++it) -// { -// #ifdef DEBUG_FILTER -// std::cerr << "Loading filtered peer " << inet_ntoa(it->mAddr.sin_addr) << " Flags: " << it->mFilterFlags << " FilterTS: " -// << now - it->mFilterTS << " LastSeen: " << now - it->mLastSeen << std::endl; -// #endif -// uint32_t saddr = it->mAddr.sin_addr.s_addr; -// mFiltered[saddr] = *it ; -// } -// } -void bdFilter::getFilteredPeers(std::list& peers) -{ - for(std::map::iterator it = mFiltered.begin(); it != mFiltered.end();++it) - peers.push_back(it->second) ; -} -/* fast check if the addr is in the structure */ -int bdFilter::addrOkay(struct sockaddr_in *addr) -{ - // first check upper layer - bool isAvailable, isBanned; - mNodeManager->doIsBannedCallback(addr, &isAvailable, &isBanned); - - if(isAvailable) { -#ifdef DEBUG_FILTER - std::cerr << "bdFilter::addrOkay addr: " << inet_ntoa(addr->sin_addr) << " result from upper layer: " << (isBanned ? "banned" : "ok") << std::endl; -#endif - return !isBanned; - } else { - // fallback to own ban list - - std::map::const_iterator it = mFiltered.find(addr->sin_addr.s_addr); - if (it == mFiltered.end()) - return 1; // Address is Okay - } - -#ifdef DEBUG_FILTER - std::cerr << "Detected Packet From Banned Ip Address: " << inet_ntoa(addr->sin_addr); - std::cerr << std::endl; -#endif - return 0; -} - - -bool bdFilter::isOwnIdWithoutBitDhtFlags(const bdId *id, uint32_t peerFlags) -{ - if (peerFlags & BITDHT_PEER_STATUS_RECV_PONG) - { - if (peerFlags & BITDHT_PEER_STATUS_DHT_ENGINE) - { - /* okay! */ - return false; - } - - /* now check distance */ - bdMetric dist; - mFns->bdDistance(&mOwnId, &(id->id), &dist); - int bucket = mFns->bdBucketDistance(&dist); - - /* if they match us... kill it */ - if (bucket == 0) - { - return true; - } - } - return false; -} - - -/* periodically we want to cleanup the filter.... - * if we haven't had an IP address reported as filtered for several hours. - * remove it from the list. - */ - -bool bdFilter::cleanupFilter() -{ -#ifdef DEBUG_FILTER - std::cerr << "bdFilter: Checking current filter List:" << std::endl; -#endif - - time_t now = time(NULL); - time_t dropTime = now - BDFILTER_ENTRY_DROP_PERIOD; - - for(std::map::iterator it = mFiltered.begin(); it != mFiltered.end();) - { -#ifdef DEBUG_FILTER - std::cerr << "\t" << bdnet_inet_ntoa(it->second.mAddr.sin_addr); - std::cerr << " Flags: " << it->second.mFilterFlags; - std::cerr << " FilterTS: " << now - it->second.mFilterTS; - std::cerr << " LastSeen: " << now - it->second.mLastSeen; -#endif - - if (it->second.mLastSeen < dropTime) - { - /* remove from filter */ -#ifdef DEBUG_FILTER - std::cerr << " OLD DROPPING" << std::endl; -#endif - std::map::iterator tmp(it) ; - ++tmp ; - - mFiltered.erase(it); - it = tmp ; - } - else - { -#ifdef DEBUG_FILTER - std::cerr << " OK" << std::endl; -#endif - it++; - } - } - - return true; -} - - - diff --git a/libbitdht/src/bitdht/bdfilter.h b/libbitdht/src/bitdht/bdfilter.h deleted file mode 100644 index 27d32a7d4..000000000 --- a/libbitdht/src/bitdht/bdfilter.h +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * bitdht/bdfilter.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef BITDHT_FILTER_H -#define BITDHT_FILTER_H - -#include "bitdht/bdiface.h" -#include - -/* Query result flags are in bdiface.h */ - -#define BITDHT_FILTER_REASON_OWNID 0x0001 - -class bdFilteredPeer -{ - public: - struct sockaddr_in mAddr; - uint32_t mFilterFlags; /* reasons why we are filtering */ - time_t mFilterTS; - time_t mLastSeen; -}; - -class bdNodeManager; - -class bdFilter -{ - public: - bdFilter(const std::string& fname, const bdNodeId *ownid, uint32_t filterFlags, bdDhtFunctions *fns, bdNodeManager *manager); - - // get the answer. -//bool filtered(std::list &answer); -bool filteredIPs(std::list &answer); - -//void loadFilteredPeers(const std::list& peers) ; -void getFilteredPeers(std::list &peers); - -int checkPeer(const bdId *id, uint32_t peerFlags); - -int addrOkay(struct sockaddr_in *addr); -int addPeerToFilter(const struct sockaddr_in &addr, uint32_t flags); - -bool cleanupFilter(); - -void loadBannedIpFile() ; -void writeBannedIpFile() ; - -private: - -bool isOwnIdWithoutBitDhtFlags(const bdId *id, uint32_t peerFlags); - - // searching for - bdNodeId mOwnId; - uint32_t mFilterFlags; - - std::map mFiltered; - bdDhtFunctions *mFns; - std::string mFilename ; - - // have access to the manager for isBanned callback - bdNodeManager* mNodeManager; -}; - - -#endif - diff --git a/libbitdht/src/bitdht/bdfriendlist.cc b/libbitdht/src/bitdht/bdfriendlist.cc deleted file mode 100644 index 487f0a75c..000000000 --- a/libbitdht/src/bitdht/bdfriendlist.cc +++ /dev/null @@ -1,243 +0,0 @@ -/******************************************************************************* - * bitdht/bdfriendlist.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bitdht/bdfriendlist.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdpeer.h" - -#include - -/***** - * #define DEBUG_FRIENDLIST 1 - ****/ - -bdFriendEntry::bdFriendEntry() -{ - mFlags = 0; - mLastSeen = 0; -} - -bool bdFriendEntry::addrKnown(struct sockaddr_in *addr) -{ - if (mFlags & BD_FRIEND_ENTRY_ADDR_OK) - { - if (mFlags & BD_FRIEND_ENTRY_ONLINE) - { - *addr = mPeerId.addr; - return true; - } - - - if (time(NULL) - mLastSeen < BD_FRIEND_ENTRY_TIMEOUT) - { - *addr = mPeerId.addr; - return true; - } - } - return false; -} - -uint32_t bdFriendEntry::getPeerFlags() -{ - return mFlags & BD_FRIEND_ENTRY_MASK_KNOWN; -} - - -bdFriendList::bdFriendList(const bdNodeId *ownId) -{ - bdId tmpId; - tmpId.id = *ownId; - updatePeer(&tmpId, BD_FRIEND_ENTRY_SELF); -} - -/****** - * Simple logic: timestamp is set with address. - * if ONLINE, then address will be dropped as soon as OFFLINE. - * if ADDR_OK, then address will be dropped after XX seconds. - * - * ONLINE - will be used with friends. - * ADDR_OK - will potentially be used for friends of friends (but not for now). - *****/ - - /* catch-all interface function */ -bool bdFriendList::updatePeer(const bdId *id, uint32_t flags) -{ -#ifdef DEBUG_FRIENDLIST - std::cerr << "bdFriendList::updatePeer() Peer("; - bdStdPrintId(std::cerr, id); - std::cerr << ") Flags: " << flags; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mPeers.find(id->id); - if (it == mPeers.end()) - { - bdFriendEntry entry; - entry.mPeerId.id = id->id; - entry.mFlags = 0; - entry.mLastSeen = 0; - - mPeers[id->id] = entry; - it = mPeers.find(id->id); - } - - /* update all */ - it->second.mFlags = flags; - if (it->second.mFlags & (BD_FRIEND_ENTRY_ADDR_OK | BD_FRIEND_ENTRY_ONLINE)) - { - it->second.mFlags |= BD_FRIEND_ENTRY_ADDR_OK; - - it->second.mPeerId.addr = id->addr; - it->second.mLastSeen = time(NULL); - } - return true; -} - -bool bdFriendList::removePeer(const bdNodeId *id) -{ - /* see if it exists... */ - std::map::iterator it; - it = mPeers.find(*id); - if (it == mPeers.end()) - { -#ifdef DEBUG_FRIENDLIST - std::cerr << "bdFriendList::removeFriend() Peer("; - bdStdPrintNodeId(std::cerr, id); - std::cerr << ") is unknown!"; - std::cerr << std::endl; -#endif - - return false; - } - - mPeers.erase(*id); - - return true; -} - -bool bdFriendList::findPeerEntry(const bdNodeId *id, bdFriendEntry &entry) -{ - /* see if it exists... */ - std::map::iterator it; - it = mPeers.find(*id); - if (it == mPeers.end()) - { -#ifdef DEBUG_FRIENDLIST - std::cerr << "bdFriendList::getPeerEntry() Peer("; - bdStdPrintNodeId(std::cerr, id); - std::cerr << ") is unknown!"; - std::cerr << std::endl; -#endif - - return false; - } - - entry = it->second; - - - return true; -} - - -bool bdFriendList::findPeersWithFlags(uint32_t flags, std::list &peerList) -{ -#ifdef DEBUG_FRIENDLIST - std::cerr << "bdFriendList::findPeersWithFlags(" << flags << ")"; - std::cerr << std::endl; -#endif - - /* see if it exists... */ - std::map::iterator it; - for(it = mPeers.begin(); it != mPeers.end(); it++) - { - /* if they have ALL of the flags we specified */ - if ((it->second.getPeerFlags() & flags) == flags) - { -#ifdef DEBUG_FRIENDLIST - std::cerr << "bdFriendList::findPeersWithFlags() Found: "; - bdStdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - peerList.push_back(it->second.mPeerId.id); - } - } - return (peerList.size() > 0); -} - - - -bool bdFriendList::print(std::ostream &out) -{ - time_t now = time(NULL); - - out << "bdFriendList::print()"; - out << std::endl; - - std::map::iterator it; - for(it = mPeers.begin(); it != mPeers.end(); it++) - { - bdStdPrintId(out, &(it->second.mPeerId)); - out << " Flags: " << it->second.mFlags; - out << " Seen: " << now - it->second.mLastSeen; - out << std::endl; - } - - return true; -} - - - - -bdPeerQueue::bdPeerQueue() -{ - return; -} - -bool bdPeerQueue::queuePeer(const bdId *id, uint32_t flags) -{ - bdFriendEntry entry; - entry.mPeerId = *id; - entry.mFlags = flags; - entry.mLastSeen = time(NULL); - - mPeerQueue.push_back(entry); - return true; -} - -bool bdPeerQueue::popPeer(bdId *id, uint32_t &flags) -{ - if (mPeerQueue.size() > 0) - { - bdFriendEntry entry = mPeerQueue.front(); - mPeerQueue.pop_front(); - *id = entry.mPeerId; - flags = entry.mFlags; - - return true; - } - - return false; -} - - - diff --git a/libbitdht/src/bitdht/bdfriendlist.h b/libbitdht/src/bitdht/bdfriendlist.h deleted file mode 100644 index a58888ed8..000000000 --- a/libbitdht/src/bitdht/bdfriendlist.h +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * bitdht/bdfriendlist.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef BITDHT_FRIEND_LIST_H -#define BITDHT_FRIEND_LIST_H - -/* - * This class maintains a list of current friends and friends-of-friends. - * It should also be updated when a peer's address has been identified. - * - * It is used for selecting preferential peers for DHT Connections. - * and for detecting bad peers that are duplicating real RS peers. - * - */ - - -#include "bitdht/bdiface.h" -#include - -#define BD_FRIEND_ENTRY_TIMEOUT 10 - - -//#define BD_FRIEND_ENTRY_ONLINE 0x0001 -//#define BD_FRIEND_ENTRY_ADDR_OK 0x0002 - -//#define BD_FRIEND_ENTRY_WHITELIST BITDHT_PEER_STATUS_DHT_WHITELIST -//#define BD_FRIEND_ENTRY_FOF BITDHT_PEER_STATUS_DHT_FOF -//#define BD_FRIEND_ENTRY_FRIEND BITDHT_PEER_STATUS_DHT_FRIEND -//#define BD_FRIEND_ENTRY_RELAY_SERVER BITDHT_PEER_STATUS_DHT_RELAY_SERVER - -//#define BD_FRIEND_ENTRY_SELF BITDHT_PEER_STATUS_DHT_SELF - -//#define BD_FRIEND_ENTRY_MASK_KNOWN BITDHT_PEER_STATUS_MASK_KNOWN - -class bdFriendEntry -{ - public: - bdFriendEntry(); - -bool addrKnown(struct sockaddr_in *addr); -uint32_t getPeerFlags(); - - bdId mPeerId; - uint32_t mFlags; - time_t mLastSeen; -}; - -class bdFriendList -{ - - public: - bdFriendList(const bdNodeId *ownid); - -bool updatePeer(const bdId *id, uint32_t flags); -bool removePeer(const bdNodeId *id); - -bool findPeerEntry(const bdNodeId *id, bdFriendEntry &entry); -bool findPeersWithFlags(uint32_t flags, std::list &peerList); - -bool print(std::ostream &out); - private: - - std::map mPeers; -}; - -class bdPeerQueue -{ - - public: - bdPeerQueue(); - -bool queuePeer(const bdId *id, uint32_t flags); -bool popPeer(bdId *id, uint32_t &flags); - - private: - - std::list mPeerQueue; -}; - - -#endif - diff --git a/libbitdht/src/bitdht/bdhash.cc b/libbitdht/src/bitdht/bdhash.cc deleted file mode 100644 index 5eabd3d95..000000000 --- a/libbitdht/src/bitdht/bdhash.cc +++ /dev/null @@ -1,283 +0,0 @@ -/******************************************************************************* - * bitdht/bdhash.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bitdht/bdhash.h" -#include "bitdht/bdstddht.h" -#include - -bdHashEntry::bdHashEntry(std::string value, std::string secret, time_t lifetime, time_t store) - :mValue(value), mStoreTS(store), mSecret(secret), mLifetime(lifetime) -{ - return; -} - - -/**************************** class bdHashSet ********************************/ - -bdHashSet::bdHashSet(bdNodeId *id) - :mId(*id) -{ - return; -} - -int bdHashSet::search(std::string key, uint32_t maxAge, std::list &entries) -{ - std::multimap::iterator sit, eit, it; - sit = mEntries.lower_bound(key); - eit = mEntries.upper_bound(key); - - time_t now = time(NULL); - - for(it = sit; it != eit; it++) - { - time_t age = now - it->second.mStoreTS; - if (age < (int32_t) maxAge) - { - entries.push_back(it->second); - } - } - return (0 < entries.size()); -} - -/*** - * With modification. - * If there is no secret -> it cannot be deleted (must timeout), but can be extended. - * If there is a secret -> must include it to modify. - * - * Therefore if identical entry without secret comes along - what do I do? - * -> create duplicate? - */ - -int bdHashSet::modify(std::string key, bdHashEntry *entry, uint32_t modFlags) -{ - std::multimap::iterator sit, eit, it; - sit = mEntries.lower_bound(key); - eit = mEntries.upper_bound(key); - - time_t now = time(NULL); - - bool updated = false; - for(it = sit; it != eit; it++) - { - /* check it all */ - if (it->second.mValue == entry->mValue) - { - bool noSecret = (it->second.mSecret == ""); - bool sameSecret = (it->second.mSecret == entry->mSecret); - bool update = false; - - if (noSecret && sameSecret) - { - /* only allowed to increase lifetime */ - if (modFlags == BITDHT_HASH_ENTRY_ADD) - { - time_t existKillTime = it->second.mLifetime + it->second.mStoreTS; - time_t newKillTime = entry->mLifetime + now; - if (newKillTime > existKillTime) - { - update = true; - } - } - } - else if (sameSecret) - { - if (modFlags == BITDHT_HASH_ENTRY_ADD) - { - update = true; - } - else if (modFlags == BITDHT_HASH_ENTRY_DELETE) - { - /* do it here */ - mEntries.erase(it); - return 1; - } - } - - if (update) - { - it->second.mStoreTS = now; - it->second.mLifetime = entry->mLifetime; - updated = true; - } - } - } - - if ((!updated) && (modFlags == BITDHT_HASH_ENTRY_ADD)) - { - /* create a new entry */ - bdHashEntry newEntry(entry->mValue, entry->mSecret, entry->mLifetime, now); - mEntries.insert(std::pair(key, newEntry)); - updated = true; - } - return updated; -} - -int bdHashSet::printHashSet(std::ostream &out) -{ - time_t now = time(NULL); - std::multimap::iterator it; - out << "Hash: "; - bdStdPrintNodeId(out, &mId); // Allowing "Std" as we dont need dht functions everywhere. - out << std::endl; - - for(it = mEntries.begin(); it != mEntries.end();it++) - { - time_t age = now - it->second.mStoreTS; - out << "\tK:" << bdStdConvertToPrintable(it->first); - out << " V:" << bdStdConvertToPrintable(it->second.mValue); - out << " A:" << age << " L:" << it->second.mLifetime; - out << " S:" << bdStdConvertToPrintable(it->second.mSecret); - out << std::endl; - } - return 1; -} - - - - -int bdHashSet::cleanupHashSet(uint32_t maxAge) -{ - time_t now = time(NULL); - - /* this is nasty... but don't know how to effectively remove from multimaps - * * Must do full repeat for each removal. - */ - - std::multimap::iterator it; - for(it = mEntries.begin(); it != mEntries.end();) - { - time_t age = now - it->second.mStoreTS; - if ((age > (int32_t) maxAge) || (age > it->second.mLifetime)) - { - mEntries.erase(it); - it = mEntries.begin(); - } - else - { - it++; - } - } - return 1; -} - - - - - - -/******************************* class bdHashSpace ***************************/ - -bdHashSpace::bdHashSpace() -{ - return; -} - - /* accessors */ -int bdHashSpace::search(bdNodeId *id, std::string key, uint32_t maxAge, std::list &entries) -{ - std::map::iterator it; - it = mHashTable.find(*id); - if (it == mHashTable.end()) - { - /* no entry */ - return 1; - } - - return it->second.search(key, maxAge, entries); -} - -int bdHashSpace::modify(bdNodeId *id, std::string key, bdHashEntry *entry, uint32_t modFlags) -{ - std::map::iterator it; - it = mHashTable.find(*id); - if (it == mHashTable.end()) - { - if (modFlags == BITDHT_HASH_ENTRY_DELETE) - { - /* done already */ - return 1; - } - - //mHashTable[*id] = bdHashSet(id); - mHashTable.insert(std::pair(*id, bdHashSet(id))); - it = mHashTable.find(*id); - } - - return it->second.modify(key, entry, modFlags); -} - -int bdHashSpace::printHashSpace(std::ostream &out) -{ - std::map::iterator it; - out << "bdHashSpace::printHashSpace()" << std::endl; - out << "--------------------------------------------" << std::endl; - - for(it = mHashTable.begin(); it != mHashTable.end(); it++) - { - it->second.printHashSet(out); - } - out << "--------------------------------------------" << std::endl; - return 1; -} - -int bdHashSpace::cleanHashSpace(bdNodeId *min, bdNodeId *max, time_t maxAge) -{ - std::map::iterator it; - std::list eraseList; - std::list::iterator eit; - - for(it = mHashTable.begin(); it != mHashTable.end(); it++) - { - if ((it->first < *min) || - (*max < it->first)) - { - /* schedule for erasure */ - eraseList.push_back(it->first); - } - else - { - /* clean up Hash Set */ - it->second.cleanupHashSet(maxAge); - } - } - - /* cleanup */ - while(eraseList.size() > 0) - { - bdNodeId &eId = eraseList.front(); - it = mHashTable.find(eId); - if (it != mHashTable.end()) - { - mHashTable.erase(it); - } - } - return 1; -} - - -int bdHashSpace::clear() -{ - mHashTable.clear(); - return 1; -} - - diff --git a/libbitdht/src/bitdht/bdhash.h b/libbitdht/src/bitdht/bdhash.h deleted file mode 100644 index 680169665..000000000 --- a/libbitdht/src/bitdht/bdhash.h +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * bitdht/bdhash.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef BITDHT_HASH_SPACE_H -#define BITDHT_HASH_SPACE_H - -#include "bitdht/bdpeer.h" - -#include -#include -#include - -#define BITDHT_HASH_ENTRY_ADD 1 -#define BITDHT_HASH_ENTRY_DELETE 2 - -class bdHashEntry -{ - public: - - bdHashEntry(std::string value, std::string secret, time_t lifetime, time_t store); - std::string mValue; - time_t mStoreTS; - - /* These are nice features that OpenDHT had */ - std::string mSecret; - time_t mLifetime; -}; - - -class bdHashSet -{ - public: - - bdHashSet(bdNodeId *id); - -int search(std::string key, uint32_t maxAge, std::list &entries); -int modify(std::string key, bdHashEntry *entry, uint32_t modFlags); -int printHashSet(std::ostream &out); -int cleanupHashSet(uint32_t maxAge); - - bdNodeId mId; - std::multimap mEntries; -}; - -class bdHashSpace -{ - public: - - bdHashSpace(); - - /* accessors */ -int search(bdNodeId *id, std::string key, uint32_t maxAge, std::list &entries); -int modify(bdNodeId *id, std::string key, bdHashEntry *entry, uint32_t modFlags); - -int printHashSpace(std::ostream&); -int cleanHashSpace(bdNodeId *min, bdNodeId *max, time_t maxAge); -int clear(); - - private: - - std::map mHashTable; -}; - - -#endif - diff --git a/libbitdht/src/bitdht/bdhistory.cc b/libbitdht/src/bitdht/bdhistory.cc deleted file mode 100644 index 05bb73fa0..000000000 --- a/libbitdht/src/bitdht/bdhistory.cc +++ /dev/null @@ -1,647 +0,0 @@ -/******************************************************************************* - * bitdht/bdhistory.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - - -#include "bitdht/bdhistory.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdmsgs.h" -#include - -#define MIN_RESEND_PERIOD 60 - -bdMsgHistoryList::bdMsgHistoryList() -:mPeerVersion("Unknown") -{ - return; -} - - - -void bdMsgHistoryList::addMsg(time_t ts, uint32_t msgType, bool incoming, const bdNodeId *aboutId) -{ -// std::cerr << "bdMsgHistoryList::addMsg()"; -// std::cerr << std::endl; - - bdMsgHistoryItem msg(msgType, incoming, aboutId); - msgHistory.insert(std::make_pair(ts, msg)); -} - -void bdMsgHistoryList::setPeerType(time_t /* ts */, std::string version) -{ - mPeerVersion = version; -} - -int bdMsgHistoryList::msgCount(time_t start_ts, time_t end_ts) -{ - std::multimap::iterator sit, eit, it; - sit = msgHistory.lower_bound(start_ts); - eit = msgHistory.upper_bound(end_ts); - int count = 0; - for (it = sit; it != eit; it++, count++) ; // empty loop. - - return count; -} - -bool bdMsgHistoryList::msgClear(time_t before) -{ - if (before == 0) - { - msgHistory.clear(); - return true; - } - - // Delete the old stuff in the list. - while((msgHistory.begin() != msgHistory.end()) && (msgHistory.begin()->first < before)) - { - msgHistory.erase(msgHistory.begin()); - } - - // return true if empty. - if (msgHistory.begin() == msgHistory.end()) - { - return true; - } - return false; -} - -void bdMsgHistoryList::msgClear() -{ - msgHistory.clear(); -} - - -void bdMsgHistoryList::clearHistory() -{ - msgClear(); -} - -void bdMsgHistoryList::printHistory(std::ostream &out, int mode, time_t start_ts, time_t end_ts) -{ - //out << "AGE: MSGS => incoming, <= outgoing" << std::endl; - std::multimap::iterator sit, eit, it; - sit = msgHistory.lower_bound(start_ts); - eit = msgHistory.upper_bound(end_ts); - time_t curr_ts = 0; - bool time_changed = false; - bool first_line = true; - - for(it = sit; it != eit; it++) - { - time_changed = false; - if (curr_ts != it->first) - { - curr_ts = it->first; - time_changed = true; - } - switch(mode) - { - default: - { - /* print one line per ts */ - if (time_changed) - { - if (!first_line) - { - /* finish existing line */ - out << " " << std::endl; - } - else - { - first_line = false; - } - out << "\tTS: " << time(NULL) - curr_ts << " "; - } - - std::string name; - bitdht_msgtype(it->second.msgType, name); - - if (it->second.incoming) - { - out << "( =I> "; - } - else - { - out << "( second.aboutId.data[0] == 0) - && (it->second.aboutId.data[3] == 0) - && (it->second.aboutId.data[3] == 0) - && (it->second.aboutId.data[3] == 0)) - { - /* don't print anything */ - } - else - { - bdStdPrintNodeId(out, &(it->second.aboutId)); - } - out << " )"; - - } - break; - } // end of switch. - } - - /* finish up last line */ - if (!first_line) - { - out << " " << std::endl; - } -} - - -bool bdMsgHistoryList::canSend() -{ - std::cerr << "bdMsgHistoryList::canSend()"; - - std::multimap::reverse_iterator rit; - - rit = msgHistory.rbegin(); - if (rit != msgHistory.rend()) - { - time_t now = time(NULL); - if (now - rit->first > MIN_RESEND_PERIOD) - { - std::cerr << " OVER RESEND_PERIOD... true"; - std::cerr << std::endl; - - return true; - } - } - - if (msgHistory.size() % 2 == 0) - { - std::cerr << " SIZE: " << msgHistory.size() << " % 2 = 0 ... true"; - std::cerr << std::endl; - - return true; - } - - std::cerr << " false"; - std::cerr << std::endl; - - return false; -} - -bool bdMsgHistoryList::validPeer() -{ - std::cerr << "bdMsgHistoryList::validPeer()"; - - std::multimap::iterator it; - - for(it = msgHistory.begin(); it != msgHistory.end(); it++) - { - if (it->second.incoming) - { - std::cerr << " Incoming Msg... so validPeer"; - std::cerr << std::endl; - - return true; - } - } - - std::cerr << " false"; - std::cerr << std::endl; - - return false; -} - - -#define MAX_PING_PER_MINUTE 2 -#define MAX_QUERY_PER_MINUTE 2 - -bool bdMsgHistoryList::analysePeer() - -{ - /* analyse and print out details of the peers messages */ - bool flagged = false; - - //out << "AGE: MSGS => incoming, <= outgoing" << std::endl; - std::multimap::iterator sit, eit, it; - sit = msgHistory.begin(); - eit = msgHistory.end(); - if (sit == eit) - { - // nothing here. - return false; - } - - time_t start_ts = sit->first; - time_t end_ts = msgHistory.rbegin()->first; // must exist. - - - // don't divide by zero. - if (end_ts - start_ts < 60) - { - end_ts = start_ts + 60; - } - - - /* what do we want to analyse? */ - - /* if we have sent / recved too many queries or pings */ - - int in_ping = 0; - int out_ping = 0; - int in_query = 0; - int out_query = 0; - int in_other = 0; - int out_other = 0; - - for(it = sit; it != eit; it++) - { - if (it->second.incoming) - { - switch(it->second.msgType) - { - case BITDHT_MSG_TYPE_PING: - in_ping++; - break; - case BITDHT_MSG_TYPE_FIND_NODE: - in_query++; - break; - default: - in_other++; - break; - } - } - else - { - switch(it->second.msgType) - { - case BITDHT_MSG_TYPE_PING: - out_ping++; - break; - case BITDHT_MSG_TYPE_FIND_NODE: - out_query++; - break; - default: - out_other++; - break; - } - } - - } - - float in_ping_per_min = in_ping * 60.0 / (end_ts - start_ts); - float out_ping_per_min = out_ping * 60.0 / (end_ts - start_ts); - float in_query_per_min = in_query * 60.0 / (end_ts - start_ts); - float out_query_per_min = out_query * 60.0 / (end_ts - start_ts); - - if ((in_ping_per_min > MAX_PING_PER_MINUTE) || - (out_ping_per_min > MAX_PING_PER_MINUTE) || - (in_query_per_min > MAX_PING_PER_MINUTE) || - (out_query_per_min > MAX_PING_PER_MINUTE)) - { - flagged = true; - } - - if (flagged) - { - /* print header */ - std::ostream &out = std::cerr; - out << "BdHistoryAnalysis has flagged peer: "; - bdStdPrintId(out, &mId); - out << std::endl; - - out << "PeerType: " << mPeerVersion; - out << std::endl; - - out << "Ping In Per Min : " << in_ping_per_min << std::endl; - out << "Ping Out Per Min : " << out_ping_per_min << std::endl; - out << "Query In Per Min : " << in_query_per_min << std::endl; - out << "Query Out Per Min: " << out_query_per_min << std::endl; - - out << "Message History: "; - out << std::endl; - - printHistory(out, 0, 0, time(NULL)); - } - return true; -} - -bdHistory::bdHistory(time_t store_period) - :mStorePeriod(store_period) { return; } - -void bdHistory::addMsg(const bdId *id, bdToken * /*transId*/, uint32_t msgType, bool incoming, const bdNodeId *aboutId) -{ - //std::cerr << "bdHistory::addMsg() "; - //bdStdPrintId(std::cerr, id); - //std::cerr << std::endl; - - time_t now = time(NULL); - - std::map::iterator it; - bdMsgHistoryList &histRef = mHistory[*id]; /* will instaniate empty */ - histRef.mId = *id; - histRef.addMsg(now, msgType, incoming, aboutId); - - /* add to mMsgTimeline */ - mMsgTimeline.insert(std::make_pair(now, MsgRegister(id, msgType, incoming, aboutId))); -} - -void bdHistory::setPeerType(const bdId *id, std::string version) -{ - std::map::iterator it; - bdMsgHistoryList &histRef = mHistory[*id]; /* will instaniate empty */ - histRef.setPeerType(time(NULL), version); -} - -void bdHistory::printMsgs() -{ - /* print and clear msgs */ - std::ostream &out = std::cerr; - - std::cerr << "bdHistory::printMsgs()"; - std::cerr << std::endl; - - - std::map ::iterator it; - for(it = mHistory.begin(); it != mHistory.end(); it++) - { - if (it->second.msgCount(0, time(NULL))) // all msg count. - { - /* print header */ - out << "Msgs for "; - bdStdPrintId(out, &(it->first)); - out << " v:" << it->second.mPeerVersion; - out << std::endl; - - it->second.printHistory(out, 0, 0, time(NULL)); - } - } - - out << "Msg Timeline:"; - time_t now = time(NULL); - std::multimap::iterator hit; - for(hit = mMsgTimeline.begin(); hit != mMsgTimeline.end(); hit++) - { - out << now - hit->first << " "; - bdStdPrintId(out, &(hit->second.id)); - - if (hit->second.incoming) - { - out << " =I> "; - } - else - { - out << " second.msgType, name)) - { - out << name; - } - else - { - out << "UNKNOWN MSG"; - } - out << std::endl; - } -} - - -void bdHistory::cleanupOldMsgs() -{ - std::cerr << "bdHistory::cleanupOldMsgs()"; - std::cerr << std::endl; - - if (mStorePeriod == 0) - { - return; // no cleanup - } - - std::set to_cleanup; - std::set::iterator cit; - - time_t before = time(NULL) - mStorePeriod; - - // Delete the old stuff in the list. - while((mMsgTimeline.begin() != mMsgTimeline.end()) && (mMsgTimeline.begin()->first < before)) - { - std::multimap::iterator it = mMsgTimeline.begin(); - to_cleanup.insert(it->second.id); - mMsgTimeline.erase(it); - } - - // remove old msgs, delete entry if its empty. - std::map::iterator hit; - for(cit = to_cleanup.begin(); cit != to_cleanup.end(); cit++) - { - hit = mHistory.find(*cit); - if (hit != mHistory.end()) - { - if (hit->second.msgClear(before)) - { - // don't erase actual entry (so we remember peer type). - //mHistory.erase(hit); - } - } - } -} - - - -void bdHistory::clearHistory() -{ - // Switched to a alternative clear, so we don't drop peers, and remember their type. - //mHistory.clear(); - - - std::map ::iterator it; - for(it = mHistory.begin(); it != mHistory.end(); it++) - { - it->second.clearHistory(); - } -} - -bool bdHistory::canSend(const bdId *id) -{ - - std::map ::iterator it; - it = mHistory.find(*id); - if (it != mHistory.end()) - { - return (it->second.canSend()); - } - - /* if not found - then can send */ - return true; -} - - -bool bdHistory::validPeer(const bdId *id) -{ - std::map ::iterator it; - it = mHistory.find(*id); - if (it != mHistory.end()) - { - return (it->second.validPeer()); - } - - /* if not found - then can send */ - return false; -} - -bool bdHistory::analysePeers() -{ - std::map ::iterator it; - for(it = mHistory.begin(); it != mHistory.end(); it++) - { - it->second.analysePeer(); - } - return true; -} - - - -/* Temp data class. */ -class TypeStats -{ - public: - - TypeStats() :nodes(0) { return; } - - std::map incoming, outgoing; - int nodes; - - -void printStats(std::ostream &out, const TypeStats *refStats) -{ - std::map::iterator it; - std::map::const_iterator rit; - - out << " Nodes: " << nodes; - if (refStats) - { - out << " (" << 100.0 * nodes / (float) refStats->nodes << " %)"; - } - out << std::endl; - - out << " Incoming Msgs"; - out << std::endl; - for(it = incoming.begin(); it != incoming.end(); it++) - { - uint32_t count = 0; - if (refStats) - { - rit = refStats->incoming.find(it->first); - if (rit != refStats->incoming.end()) - { - count = rit->second; - } - } - printStatsLine(out, it->first, it->second, count); - } - - out << " Outgoing Msgs"; - out << std::endl; - for(it = outgoing.begin(); it != outgoing.end(); it++) - { - uint32_t count = 0; - if (refStats) - { - rit = refStats->outgoing.find(it->first); - if (rit != refStats->outgoing.end()) - { - count = rit->second; - } - } - printStatsLine(out, it->first, it->second, count); - } -} - - - -void printStatsLine(std::ostream &out, uint32_t msgType, uint32_t count, uint32_t global) -{ - std::string name; - bitdht_msgtype(msgType, name); - out << "\t" << name << " " << count; - if (global != 0) - { - out << " (" << 100.0 * count / (float) global << " %)"; - } - out << std::endl; -} - -}; /* end of TypeStats */ - -bool bdHistory::peerTypeAnalysis() -{ - - std::map mTypeStats; - TypeStats globalStats; - - std::map ::iterator it; - for(it = mHistory.begin(); it != mHistory.end(); it++) - { - if (it->second.msgHistory.empty()) - { - continue; - } - - std::string version = it->second.mPeerVersion; - // group be first two bytes. - version = it->second.mPeerVersion.substr(0,2); - TypeStats &stats = mTypeStats[version]; - - stats.nodes++; - globalStats.nodes++; - - std::multimap::iterator lit; - for (lit = it->second.msgHistory.begin(); lit != it->second.msgHistory.end(); lit++) - { - if (lit->second.incoming) - { - stats.incoming[lit->second.msgType]++; - globalStats.incoming[lit->second.msgType]++; - } - else - { - stats.outgoing[lit->second.msgType]++; - globalStats.outgoing[lit->second.msgType]++; - } - } - } - - - std::map::iterator tit; - for(tit = mTypeStats.begin(); tit != mTypeStats.end(); tit++) - { - std::cerr << "Stats for Peer Type: " << tit->first; - std::cerr << std::endl; - tit->second.printStats(std::cerr, &globalStats); - } - - std::cerr << "Global Stats: "; - std::cerr << std::endl; - - globalStats.printStats(std::cerr, NULL); - return true; - -} - - - diff --git a/libbitdht/src/bitdht/bdhistory.h b/libbitdht/src/bitdht/bdhistory.h deleted file mode 100644 index 79e420d92..000000000 --- a/libbitdht/src/bitdht/bdhistory.h +++ /dev/null @@ -1,147 +0,0 @@ -/******************************************************************************* - * bitdht/bdhistory.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef BITDHT_HISTORY_H -#define BITDHT_HISTORY_H - -#include "bitdht/bdpeer.h" -#include "bitdht/bdobj.h" -#include "bitdht/bdstddht.h" -#include - -#define MSG_TYPE_DIRECTION_MASK 0x000f0000 - -#define MSG_DIRECTION_INCOMING 0x00010000 -#define MSG_DIRECTION_OUTGOING 0x00020000 - -/**** DEBUGGING HISTORY ****/ - -class MsgRegister -{ - public: - MsgRegister() { return; } - MsgRegister(const bdId *inId, uint32_t inMsgType, bool inIncoming, const bdNodeId *inAboutId) - :id(*inId), msgType(inMsgType), incoming(inIncoming) - { - if (inAboutId) - { - aboutId = *inAboutId; - } - else - { - bdStdZeroNodeId(&aboutId); - } - - return; - } - - bdId id; - uint32_t msgType; - bool incoming; - bdNodeId aboutId; // filled in for queries. -}; - - -class bdMsgHistoryItem -{ - public: - bdMsgHistoryItem() - :msgType(0), incoming(false) - { - bdStdZeroNodeId(&aboutId); - return; - } - - bdMsgHistoryItem(uint32_t inMsgType, bool inIncoming, const bdNodeId *inAboutId) - :msgType(inMsgType), incoming(inIncoming) - { - if (inAboutId) - { - aboutId = *inAboutId; - } - else - { - bdStdZeroNodeId(&aboutId); - } - - return; - } - - uint32_t msgType; - bool incoming; - bdNodeId aboutId; // filled in for queries. -}; - - -class bdMsgHistoryList -{ - public: - bdMsgHistoryList(); -void addMsg(time_t ts, uint32_t msgType, bool incoming, const bdNodeId *aboutId); -void setPeerType(time_t ts, std::string version); -int msgCount(time_t start_ts, time_t end_ts); -bool msgClear(time_t before); // 0 => clear all. -void msgClear(); -void printHistory(std::ostream &out, int mode, time_t start_ts, time_t end_ts); -bool analysePeer(); -void clearHistory(); - -bool canSend(); -bool validPeer(); - - std::multimap msgHistory; - std::string mPeerVersion; - bdId mId; -}; - - - -class bdHistory -{ - public: - bdHistory(time_t store_period); - -void addMsg(const bdId *id, bdToken *transId, uint32_t msgType, bool incoming, const bdNodeId *aboutId); -void setPeerType(const bdId *id, std::string version); -void printMsgs(); - -void cleanupOldMsgs(); -void clearHistory(); -bool analysePeers(); -bool peerTypeAnalysis(); - -bool canSend(const bdId *id); -bool validPeer(const bdId *id); - - /* recent history */ - //std::list lastMsgs; - std::map mHistory; - std::multimap mMsgTimeline; - - int mStorePeriod; - -}; - - - -#endif - diff --git a/libbitdht/src/bitdht/bdiface.h b/libbitdht/src/bitdht/bdiface.h deleted file mode 100644 index 4e571ccdb..000000000 --- a/libbitdht/src/bitdht/bdiface.h +++ /dev/null @@ -1,413 +0,0 @@ -/******************************************************************************* - * bitdht/bdiface.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BIT_DHT_INTERFACE_H -#define BIT_DHT_INTERFACE_H - -#include -#include -#include -#include -#include - -#include "util/bdnet.h" - -/* - * Functions and Classes required for Interfacing with the BitDht. - * This should be the sole header file required to talk to Dht. - * ... though setting it up will require including udpbitdht.h as well. - * - */ - -#define BITDHT_KEY_LEN 20 -#define BITDHT_KEY_INTLEN 5 -#define BITDHT_KEY_BITLEN 160 - - - - -#define BITDHT_MAX_PKTSIZE 1024 - -#define BITDHT_TTL 64 - -#define BITDHT_SEARCH_ONE_SHOT 1 -#define BITDHT_SEARCH_REPEATING 2 - -class bdNodeId -{ - public: - unsigned char data[BITDHT_KEY_LEN]; -}; - -class bdMetric: public bdNodeId {}; - -class bdId -{ - public: - - bdId(); - bdId(bdNodeId in_id, struct sockaddr_in in_addr); - - struct sockaddr_in addr; - bdNodeId id; -}; - -#define BITDHT_LIKELY_SAME_NO 0x00000000 -#define BITDHT_LIKELY_SAME_YES 0x00000001 -#define BITDHT_LIKELY_SAME_PORT_CHANGED 0x00000002 -#define BITDHT_LIKELY_SAME_LOC_CHANGED 0x00000004 -#define BITDHT_LIKELY_SAME_IDENTICAL 0x00000008 - - -class bdDhtFunctions -{ - public: - -// bdDhtFunctions(); - /* setup variables */ -virtual uint16_t bdNumBuckets() = 0; -virtual uint16_t bdNodesPerBucket() = 0; /* used for bdspace */ -virtual uint16_t bdNumQueryNodes() = 0; /* used for queries */ -virtual uint16_t bdBucketBitSize() = 0; - -virtual int bdDistance(const bdNodeId *n1, const bdNodeId *n2, bdMetric *metric) = 0; -virtual int bdBucketDistance(const bdNodeId *n1, const bdNodeId *n2) = 0; -virtual int bdBucketDistance(const bdMetric *metric) = 0; - -virtual bool bdSimilarId(const bdId *id1, const bdId *id2) = 0; -virtual bool bdUpdateSimilarId(bdId *dest, const bdId *src) = 0; - -virtual void bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid) = 0; - -virtual void bdPrintId(std::ostream &out, const bdId *a) = 0; -virtual void bdPrintNodeId(std::ostream &out, const bdNodeId *a) = 0; - -}; - - - -// DHT MODES -#define BITDHT_MODE_TRAFFIC_MASK 0x00000f00 -#define BITDHT_MODE_RELAYSERVER_MASK 0x0000f000 - -// These are not ORd - only one can apply. -#define BITDHT_MODE_TRAFFIC_HIGH 0x00000100 -#define BITDHT_MODE_TRAFFIC_MED 0x00000200 -#define BITDHT_MODE_TRAFFIC_LOW 0x00000300 -#define BITDHT_MODE_TRAFFIC_TRICKLE 0x00000400 -#define BITDHT_MODE_TRAFFIC_DEFAULT BITDHT_MODE_TRAFFIC_LOW - -// These are not ORd - only one can apply. -#define BITDHT_MODE_RELAYSERVERS_IGNORED 0x00001000 -#define BITDHT_MODE_RELAYSERVERS_FLAGGED 0x00002000 -#define BITDHT_MODE_RELAYSERVERS_ONLY 0x00003000 -#define BITDHT_MODE_RELAYSERVERS_SERVER 0x00004000 - - -/* NODE OPTIONS */ -#define BITDHT_OPTIONS_MAINTAIN_UNSTABLE_PORT 0x00000001 -#define BITDHT_OPTIONS_ENABLE_RELAYS 0x00000002 - - -/* peer flags - * order is important! - * higher bits = more priority. - * BITDHT_PEER_STATUS_RECVPING - * BITDHT_PEER_STATUS_RECVPONG - * BITDHT_PEER_STATUS_RECVNODES - * BITDHT_PEER_STATUS_RECVHASHES - * BITDHT_PEER_STATUS_DHT_ENGINE (dbXXxx) - * BITDHT_PEER_STATUS_DHT_APPL (XXRSxx) - * BITDHT_PEER_STATUS_DHT_VERSION (XXxx50) - * - */ - -#define BITDHT_PEER_STATUS_MASK_RECVD 0x000000ff -#define BITDHT_PEER_STATUS_MASK_DHT 0x0000ff00 -#define BITDHT_PEER_STATUS_MASK_KNOWN 0x00ff0000 - -#define BITDHT_PEER_STATUS_RECV_PING 0x00000001 -#define BITDHT_PEER_STATUS_RECV_PONG 0x00000002 -#define BITDHT_PEER_STATUS_RECV_NODES 0x00000004 -#define BITDHT_PEER_STATUS_RECV_HASHES 0x00000008 -#define BITDHT_PEER_STATUS_RECV_CONNECT_MSG 0x00000010 - -#define BITDHT_PEER_STATUS_DHT_ENGINE 0x00000100 -#define BITDHT_PEER_STATUS_DHT_ENGINE_VERSION 0x00000200 -#define BITDHT_PEER_STATUS_DHT_APPL 0x00000400 -#define BITDHT_PEER_STATUS_DHT_APPL_VERSION 0x00000800 - -#define BITDHT_PEER_STATUS_DHT_WHITELIST 0x00010000 -#define BITDHT_PEER_STATUS_DHT_FOF 0x00020000 -#define BITDHT_PEER_STATUS_DHT_FRIEND 0x00040000 -#define BITDHT_PEER_STATUS_DHT_RELAY_SERVER 0x00080000 // (Flag must be enabled) -#define BITDHT_PEER_STATUS_DHT_SELF 0x00100000 - - -// EXTRA FLAGS are our internal thoughts about the peer. -#define BITDHT_PEER_EXFLAG_MASK_BASIC 0x000000ff -#define BITDHT_PEER_EXFLAG_UNSTABLE 0x00000001 // Port changes. -#define BITDHT_PEER_EXFLAG_ATTACHED 0x00000002 // We will ping in heavily. (if unstable) -#define BITDHT_PEER_EXFLAG_BADPEER 0x00000004 // For testing, we flag rather than discard. - - - - - -#define BITDHT_CONNECT_MODE_DIRECT 0x00000001 -#define BITDHT_CONNECT_MODE_PROXY 0x00000002 -#define BITDHT_CONNECT_MODE_RELAY 0x00000004 - -#define BITDHT_CONNECT_OPTION_AUTOPROXY 0x00000001 - -// STATUS CODES. == 0 is okay, != 0 is error. -#define BITDHT_CONNECT_ANSWER_OKAY 0x00000000 -#define BITDHT_CONNECT_ERROR_NONE (BITDHT_CONNECT_ANSWER_OKAY) - -#define BITDHT_CONNECT_ERROR_MASK_TYPE 0x0000ffff -#define BITDHT_CONNECT_ERROR_MASK_SOURCE 0x00ff0000 -#define BITDHT_CONNECT_ERROR_MASK_CRMOVE 0xff000000 - -#define BITDHT_CONNECT_ERROR_SOURCE_START 0x00010000 -#define BITDHT_CONNECT_ERROR_SOURCE_MID 0x00020000 -#define BITDHT_CONNECT_ERROR_SOURCE_END 0x00040000 -#define BITDHT_CONNECT_ERROR_SOURCE_OTHER 0x00080000 - -#define BITDHT_CONNECT_ERROR_CRMOVE_FATAL 0x01000000 -#define BITDHT_CONNECT_ERROR_CRMOVE_NOMOREIDS 0x02000000 -#define BITDHT_CONNECT_ERROR_CRMOVE_NEXTID 0x04000000 -#define BITDHT_CONNECT_ERROR_CRMOVE_PAUSED 0x08000000 - -// ERROR CODES. -#define BITDHT_CONNECT_ERROR_GENERIC 0x00000001 -#define BITDHT_CONNECT_ERROR_PROTOCOL 0x00000002 -#define BITDHT_CONNECT_ERROR_TIMEOUT 0x00000003 -#define BITDHT_CONNECT_ERROR_TEMPUNAVAIL 0x00000004 // Haven't got ext address yet. -#define BITDHT_CONNECT_ERROR_NOADDRESS 0x00000005 // Can't find the peer in tables. -#define BITDHT_CONNECT_ERROR_UNREACHABLE 0x00000006 // Symmetric NAT - -#define BITDHT_CONNECT_ERROR_UNSUPPORTED 0x00000007 -#define BITDHT_CONNECT_ERROR_OVERLOADED 0x00000008 -#define BITDHT_CONNECT_ERROR_AUTH_DENIED 0x00000009 -#define BITDHT_CONNECT_ERROR_DUPLICATE 0x0000000a - -// These are slightly special ones used for CB_REQUEST -#define BITDHT_CONNECT_ERROR_TOOMANYRETRY 0x0000000b -#define BITDHT_CONNECT_ERROR_OUTOFPROXY 0x0000000c -#define BITDHT_CONNECT_ERROR_USER 0x0000000d - - -/*************/ -// FRIEND_ENTRY_FLAGS... used by updateKnownPeers(). - -#define BD_FRIEND_ENTRY_ONLINE 0x0001 -#define BD_FRIEND_ENTRY_ADDR_OK 0x0002 - -#define BD_FRIEND_ENTRY_WHITELIST BITDHT_PEER_STATUS_DHT_WHITELIST -#define BD_FRIEND_ENTRY_FOF BITDHT_PEER_STATUS_DHT_FOF -#define BD_FRIEND_ENTRY_FRIEND BITDHT_PEER_STATUS_DHT_FRIEND -#define BD_FRIEND_ENTRY_RELAY_SERVER BITDHT_PEER_STATUS_DHT_RELAY_SERVER - -#define BD_FRIEND_ENTRY_SELF BITDHT_PEER_STATUS_DHT_SELF - -#define BD_FRIEND_ENTRY_MASK_KNOWN BITDHT_PEER_STATUS_MASK_KNOWN - - - - -/* Definitions of bdSpace Peer and Bucket are publically available, - * so we can expose the bucket entries for the gui. - */ - -class bdPeer -{ - public: - bdPeer():mPeerFlags(0), mLastSendTime(0), mLastRecvTime(0), mFoundTime(0), mExtraFlags(0) { return; } - - bdId mPeerId; - uint32_t mPeerFlags; - time_t mLastSendTime; - time_t mLastRecvTime; - time_t mFoundTime; /* time stamp that peer was found */ - - uint32_t mExtraFlags; -}; - -class bdBucket -{ - public: - - bdBucket(); - /* list so we can queue properly */ - std::list entries; -}; - -class bdQueryStatus -{ - public: - uint32_t mStatus; - uint32_t mQFlags; - std::list mResults; -}; - -class bdQuerySummary -{ - public: - - bdNodeId mId; - bdMetric mLimit; - uint32_t mState; - time_t mQueryTS; - uint32_t mQueryFlags; - int32_t mSearchTime; - - int32_t mQueryIdlePeerRetryPeriod; // seconds between retries. - - // closest peers - std::multimap mClosest; - std::multimap mPotentialPeers; - std::list mProxiesUnknown; - std::list mProxiesFlagged; -}; - - - - -/* Status options */ -#define BITDHT_QUERY_READY 1 -#define BITDHT_QUERY_QUERYING 2 -#define BITDHT_QUERY_FAILURE 3 -#define BITDHT_QUERY_FOUND_CLOSEST 4 -#define BITDHT_QUERY_PEER_UNREACHABLE 5 -#define BITDHT_QUERY_SUCCESS 6 - -/* Query Flags */ -#define BITDHT_QFLAGS_NONE 0x0000 -#define BITDHT_QFLAGS_DISGUISE 0x0001 // Don't search directly for target. -#define BITDHT_QFLAGS_DO_IDLE 0x0002 -#define BITDHT_QFLAGS_INTERNAL 0x0004 // runs through startup. (limited callback) -#define BITDHT_QFLAGS_UPDATES 0x0008 // Do regular updates. - -/* Connect Callback Flags */ -#define BITDHT_CONNECT_CB_AUTH 1 -#define BITDHT_CONNECT_CB_PENDING 2 -#define BITDHT_CONNECT_CB_START 3 -#define BITDHT_CONNECT_CB_PROXY 4 -#define BITDHT_CONNECT_CB_FAILED 5 -#define BITDHT_CONNECT_CB_REQUEST 6 - -#define BD_PROXY_CONNECTION_UNKNOWN_POINT 0 -#define BD_PROXY_CONNECTION_START_POINT 1 -#define BD_PROXY_CONNECTION_MID_POINT 2 -#define BD_PROXY_CONNECTION_END_POINT 3 - -#define BITDHT_INFO_CB_TYPE_BADPEER 1 - -/* Relay Modes */ -#define BITDHT_RELAYS_OFF 0 -#define BITDHT_RELAYS_ON 1 -#define BITDHT_RELAYS_ONLY 2 -#define BITDHT_RELAYS_SERVER 3 - - -class BitDhtCallback -{ - public: -// ~BitDhtCallback(); - - // dummy cos not needed for standard dht behaviour; - virtual int dhtNodeCallback(const bdId * /*id*/, uint32_t /*peerflags*/) { return 0; } - - // must be implemented. - virtual int dhtPeerCallback(const bdId *id, uint32_t status) = 0; - virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) = 0; - - // connection callback. Not required for basic behaviour, but forced for initial development. - virtual int dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t point, uint32_t param, uint32_t cbtype, uint32_t errcode) = 0; /* { return 0; } */ - - // Generic Info callback - initially will be used to provide bad peers. - virtual int dhtInfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info) = 0; - - // ask upper layer whether an IP is banned or not - // must not be implemented - // when set it will be used instead of the own ban list - // return code is used to express availability/absence - virtual int dhtIsBannedCallback(const sockaddr_in */*addr*/, bool */*isBanned*/) { return 0;} -}; - - -class BitDhtInterface -{ - public: - - /* bad peer notification */ -virtual void addBadPeer(const struct sockaddr_in &addr, uint32_t source, uint32_t reason, uint32_t age) = 0; - - /* Friend Tracking */ -virtual void updateKnownPeer(const bdId *id, uint32_t type, uint32_t flags) = 0; - - /***** Request Lookup (DHT Peer & Keyword) *****/ -virtual void addFindNode(bdNodeId *id, uint32_t mode) = 0; -virtual void removeFindNode(bdNodeId *id) = 0; -virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode) = 0; - - /***** Connections Requests *****/ -virtual bool ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start) = 0; -virtual void ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, - uint32_t bandwidth, uint32_t delay, uint32_t answer) = 0; -virtual void ConnectionOptions(uint32_t allowedModes, uint32_t flags) = 0; - -virtual bool setAttachMode(bool on) = 0; - - - /***** Add / Remove Callback Clients *****/ -virtual void addCallback(BitDhtCallback *cb) = 0; -virtual void removeCallback(BitDhtCallback *cb) = 0; - - /***** Get Results Details *****/ -virtual int getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from) = 0; -virtual int getDhtValue(const bdNodeId *id, std::string key, std::string &value) = 0; -virtual int getDhtBucket(const int idx, bdBucket &bucket) = 0; - -virtual int getDhtQueries(std::map &queries) = 0; -virtual int getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query) = 0; - - /* stats and Dht state */ -virtual int startDht() = 0; -virtual int stopDht() = 0; -virtual int stateDht() = 0; /* STOPPED, STARTING, ACTIVE, FAILED */ -virtual uint32_t statsNetworkSize() = 0; -virtual uint32_t statsBDVersionSize() = 0; /* same version as us! */ - -virtual uint32_t setDhtMode(uint32_t dhtFlags) = 0; -}; - - -// general helper functions for decoding error messages. -std::string decodeConnectionError(uint32_t errcode); -std::string decodeConnectionErrorCRMove(uint32_t errcode); -std::string decodeConnectionErrorSource(uint32_t errcode); -std::string decodeConnectionErrorType(uint32_t errcode); - - -#endif - diff --git a/libbitdht/src/bitdht/bdmanager.cc b/libbitdht/src/bitdht/bdmanager.cc deleted file mode 100644 index dadbfb264..000000000 --- a/libbitdht/src/bitdht/bdmanager.cc +++ /dev/null @@ -1,1485 +0,0 @@ -/******************************************************************************* - * bitdht/bdmanager.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -/******* - * Node Manager. - ******/ - -/****************************************** - * 1) Maintains a list of ids to search for. - * 2) Sets up initial search for own node. - * 3) Checks on status of queries. - * 4) Callback on successful searches. - * - * This is pretty specific to RS requirements. - ****/ - -#include "bitdht/bdiface.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdmanager.h" -#include "bitdht/bdmsgs.h" -#include "bitdht/bencode.h" -#include "bitdht/bdquerymgr.h" -#include "bitdht/bdfilter.h" - -#include -#include -#include - -#include "util/bdnet.h" -#include "util/bdrandom.h" -#include "util/bdstring.h" - -/*** - * #define DEBUG_MGR 1 - * #define DEBUG_MGR_PKT 1 - ***/ - -//#define DEBUG_MGR 1 - -//#define LOCAL_NET_FLAG (BITDHT_PEER_STATUS_DHT_APPL) -#define LOCAL_NET_FLAG (BITDHT_PEER_STATUS_DHT_ENGINE) -// This is eventually what we want. -//#define LOCAL_NET_FLAG (BITDHT_PEER_STATUS_DHT_ENGINE_VERSION) - -#define QUERY_UPDATE_PERIOD 8 // under refresh period - so it'll happen at the MAX_REFRESH_PERIOD - - -bdNodeManager::bdNodeManager(bdNodeId *id, std::string dhtVersion, std::string bootfile, std::string bootfilebak, const std::string& filterfile, bdDhtFunctions *fns) - :bdNode(id, dhtVersion, bootfile, bootfilebak,filterfile, fns, this) -{ - mMode = BITDHT_MGR_STATE_OFF; - mDhtFns = fns; - mModeTS = 0 ; - mStartTS = 0; - mSearchingDone = false; - mSearchTS = 0; - - mNetworkSize = 0; - mBdNetworkSize = 0; - - std::string bfilter = "edff727f3a49f55c0504ad99d4282f7a26b3f69b59ebc6ca496879c6805a0aa567dffb755f17fdfd44dd24180bf2b61ebfbe68e9a53e79d7893f002140882daf7efbfed66f36eb170064208286040001fbefbbbbef1fa7fdf4a21128d050a208cd3a529a7efdc672c8255130e022b134bc6c77dfbf455d054349c575774d427b"; - - mBloomFilter.setFilterBits(bfilter); - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::bdNodeManager() ID: "; - mDhtFns->bdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - - mLocalNetEnhancements = true; -} - -int bdNodeManager::stopDht() -{ - time_t now = time(NULL); - - /* clean up node */ - shutdownNode(); - - /* flag queries as inactive */ - /* check if exists already */ - std::map::iterator it; - for(it = mActivePeers.begin(); it != mActivePeers.end(); it++) - { - it->second.mStatus = BITDHT_QUERY_READY; - } - - /* set state flag */ - mMode = BITDHT_MGR_STATE_OFF; - mModeTS = now; - - return 1; -} - -int bdNodeManager::startDht() -{ - time_t now = time(NULL); - - /* set startup mode */ - restartNode(); - - mMode = BITDHT_MGR_STATE_STARTUP; - mModeTS = now; - - mStartTS = now; - mSearchingDone = false; - mSearchTS = now; - - return 1; -} - - /* STOPPED, STARTING, ACTIVE, FAILED */ -int bdNodeManager::stateDht() -{ - return mMode; -} - -uint32_t bdNodeManager::statsNetworkSize() -{ - return mNetworkSize; -} - -/* same version as us! */ -uint32_t bdNodeManager::statsBDVersionSize() -{ - return mBdNetworkSize; -} - -uint32_t bdNodeManager::setDhtMode(uint32_t dhtFlags) -{ - /* handle options here? */ - setNodeDhtMode(dhtFlags); - - return dhtFlags; -} - - -bool bdNodeManager::setAttachMode(bool on) -{ - if (on) - { - setNodeOptions(BITDHT_OPTIONS_MAINTAIN_UNSTABLE_PORT); - } - else - { - setNodeOptions(0); - } - return on; -} - - /* Friend Tracking */ -void bdNodeManager::addBadPeer(const struct sockaddr_in &/*addr*/, uint32_t /*source*/, uint32_t /*reason*/, uint32_t /*age*/) -{ - std::cerr << "bdNodeManager::addBadPeer() not implemented yet!"; - std::cerr << std::endl; -} - -void bdNodeManager::updateKnownPeer(const bdId *id, uint32_t /* type */, uint32_t flags) -{ - mFriendList.updatePeer(id, flags); -} - -void bdNodeManager::addFindNode(bdNodeId *id, uint32_t qflags) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::addFindNode() "; - mDhtFns->bdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - /* check if exists already */ - std::map::iterator it; - it = mActivePeers.find(*id); - if (it != mActivePeers.end()) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::addFindNode() Found existing...."; - std::cerr << std::endl; -#endif - return; - } - - /* add to map */ - bdQueryPeer peer; - peer.mId.id = (*id); - peer.mStatus = BITDHT_QUERY_READY; //QUERYING; - peer.mQFlags = qflags; - - peer.mDhtAddr.sin_addr.s_addr = 0; - peer.mDhtAddr.sin_port = 0; - - peer.mCallbackTS = 0; - - mActivePeers[*id] = peer; -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::addFindNode() Added QueryPeer as READY...."; - std::cerr << std::endl; -#endif - //addQuery(id, qflags | BITDHT_QFLAGS_DISGUISE); - return; -} - - /* finds a queued query, and starts it */ -void bdNodeManager::startQueries() -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::startQueries() "; - std::cerr << std::endl; -#endif - /* check if exists already */ - std::map::iterator it; - for(it = mActivePeers.begin(); it != mActivePeers.end(); it++) - { - if (it->second.mStatus == BITDHT_QUERY_READY) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::startQueries() Found READY Query."; - std::cerr << std::endl; -#endif - it->second.mStatus = BITDHT_QUERY_QUERYING; - - uint32_t qflags = it->second.mQFlags | BITDHT_QFLAGS_DISGUISE; - mQueryMgr->addQuery(&(it->first), qflags); - - // add all queries at the same time! - //return; - } - } - return; -} - - -void bdNodeManager::removeFindNode(bdNodeId *id) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::removeFindNode() "; - mDhtFns->bdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - std::map::iterator it; - it = mActivePeers.find(*id); - if (it == mActivePeers.end()) - { - return; - } - - /* cleanup any actions */ - mQueryMgr->clearQuery(&(it->first)); - //clearPing(&(it->first)); - - /* remove from map */ - mActivePeers.erase(it); - return; -} - -void bdNodeManager::iteration() -{ - - time_t now = time(NULL); - time_t modeAge = now - mModeTS; - switch(mMode) - { - case BITDHT_MGR_STATE_OFF: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): OFF"; - std::cerr << std::endl; -#endif - } - break; - - case BITDHT_MGR_STATE_STARTUP: - /* 10 seconds startup .... then switch to ACTIVE */ - - if (modeAge > MAX_STARTUP_TIME) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): STARTUP -> REFRESH"; - std::cerr << std::endl; -#endif - bdNodeId id; - getOwnId(&id); - mQueryMgr->addQuery(&id, BITDHT_QFLAGS_DO_IDLE | BITDHT_QFLAGS_DISGUISE); - - mMode = BITDHT_MGR_STATE_FINDSELF; - mModeTS = now; - } - break; - - case BITDHT_MGR_STATE_FINDSELF: - /* 60 seconds further startup .... then switch to ACTIVE - * if we reach TRANSITION_OP_SPACE_SIZE before this time, transition immediately... - * if, after 60 secs, we haven't reached MIN_OP_SPACE_SIZE, restart.... - */ - -#define TRANSITION_OP_SPACE_SIZE 50 /* 1 query / sec, should take 12-15 secs */ -#define MAX_FINDSELF_TIME 180 /* increased, as std rate has been dropped */ -#define MIN_OP_SPACE_SIZE 10 -// testing parameters. -//#define MAX_FINDSELF_TIME 10 -//#define MIN_OP_SPACE_SIZE 2 // for testing. self + oneother. - - { - uint32_t nodeSpaceSize = mNodeSpace.calcSpaceSize(); - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration() Finding Oneself: "; - std::cerr << "NodeSpace Size:" << nodeSpaceSize; - std::cerr << std::endl; -#endif - - if (nodeSpaceSize > TRANSITION_OP_SPACE_SIZE) - { - mMode = BITDHT_MGR_STATE_REFRESH; - mModeTS = now; - } - - if (modeAge > MAX_FINDSELF_TIME) - { - if (nodeSpaceSize >= MIN_OP_SPACE_SIZE) - { - mMode = BITDHT_MGR_STATE_REFRESH; - mModeTS = now; - } - else - { - mMode = BITDHT_MGR_STATE_FAILED; - mModeTS = now; - } - } - } - - break; - - case BITDHT_MGR_STATE_ACTIVE: - if (modeAge >= MAX_REFRESH_TIME) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): ACTIVE -> REFRESH"; - std::cerr << std::endl; -#endif - mMode = BITDHT_MGR_STATE_REFRESH; - mModeTS = now; - } - - break; - - case BITDHT_MGR_STATE_REFRESH: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): REFRESH -> ACTIVE"; - std::cerr << std::endl; -#endif - /* select random ids, and perform searchs to refresh space */ - mMode = BITDHT_MGR_STATE_ACTIVE; - mModeTS = now; - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): Starting Query"; - std::cerr << std::endl; -#endif - - startQueries(); - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): Updating Stores"; - std::cerr << std::endl; -#endif - - updateStore(); - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): Cleaning up Filter (should do less frequently)"; - std::cerr << std::endl; -#endif - - mFilterPeers.cleanupFilter(); - - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): Do App Search"; - std::cerr << std::endl; -#endif - - - /* This stuff is only important for "LocalNet based Features */ - if (mLocalNetEnhancements) - { - /* run a random search for ourselves, from own App DHT peer */ - QueryRandomLocalNet(); - -#define SEARCH_MAX_SIZE 10 - if (mBdNetworkSize < SEARCH_MAX_SIZE) - { -#ifdef DEBUG_MGR - std::cerr << "Local Netsize: " << mBdNetworkSize << " to small...searching"; - std::cerr << std::endl; -#endif - - /* if the network size is very small */ - SearchForLocalNet(); - mSearchingDone = false; - } - else - { - if (!mSearchingDone) - { - mSearchingDone = true; - mSearchTS = now; -#ifdef DEBUG_MGR - std::cerr << "Completed LocalNet Search in : " << mSearchTS-mStartTS; - std::cerr << std::endl; -#endif - } - } - } - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): REFRESH "; - std::cerr << std::endl; -#endif - - status(); /* calculates mNetworkSize */ - -#ifdef DEBUG_MGR - mAccount.printStats(std::cerr); -#endif - - /* Finally, Fail, and restart if we lose all peers */ - uint32_t nodeSpaceSize = mNodeSpace.calcSpaceSize(); - if (nodeSpaceSize < MIN_OP_SPACE_SIZE) - { - std::cerr << "bdNodeManager::iteration(): SpaceSize to Small: " << nodeSpaceSize; - std::cerr << std::endl; - std::cerr << "bdNodeManager::iteration(): REFRESH ==> FAILED"; - std::cerr << std::endl; - - mMode = BITDHT_MGR_STATE_FAILED; - mModeTS = now; - } - } - break; - - case BITDHT_MGR_STATE_QUIET: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): QUIET"; - std::cerr << std::endl; -#endif - - - } - break; - - default: - case BITDHT_MGR_STATE_FAILED: - { - std::cerr << "bdNodeManager::iteration(): FAILED ==> STARTUP"; - std::cerr << std::endl; -#ifdef DEBUG_MGR -#endif - stopDht(); - startDht(); - } - break; - } - - if (mMode == BITDHT_MGR_STATE_OFF) - { - bdNode::iterationOff(); - } - else - { - /* tick parent */ - bdNode::iteration(); - } -} - - /* NB: This is a bit of a hack, the code is duplicated from bdnode & bdquery. - * should use fn calls into their functions for good generality - */ - -#define RANDOM_SEARCH_FRAC (0.1) - -int bdNodeManager::QueryRandomLocalNet() -{ - bdId id; - bdNodeId targetNodeId; - - uint32_t withFlag = LOCAL_NET_FLAG; - if (mNodeSpace.findRandomPeerWithFlag(id, withFlag)) - { - /* if we've got a very small network size... then ask them about a random peer. - * (so we get there 159/158 boxes! - */ - bool isRandom = false; - if ((mBdNetworkSize < SEARCH_MAX_SIZE) || (RANDOM_SEARCH_FRAC > bdRandom::random_f32())) - { - bdStdRandomNodeId(&targetNodeId); - isRandom = true; - } - else - { - /* calculate mid point */ - mDhtFns->bdRandomMidId(&mOwnId, &(id.id), &targetNodeId); - } - - /* do standard find_peer message */ - mQueryMgr->addWorthyPeerSource(&id); /* Tell BitDHT that we really want to ping their peers */ - send_query(&id, &targetNodeId, true); - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::QueryRandomLocalNet() Querying : "; - mDhtFns->bdPrintId(std::cerr, &id); - std::cerr << " searching for : "; - mDhtFns->bdPrintNodeId(std::cerr, &targetNodeId); - - bdMetric dist; - mDhtFns->bdDistance(&targetNodeId, &(mOwnId), &dist); - int bucket = mDhtFns->bdBucketDistance(&dist); - std::cerr << " in Bucket: " << bucket; - std::cerr << std::endl; -#endif - - if (isRandom) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::QueryRandomLocalNet() Search is Random!"; - std::cerr << std::endl; -#endif - } - - return 1; - } - else - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::QueryRandomLocalNet() No LocalNet Peer Found"; - std::cerr << std::endl; -#endif - } - - return 0; -} - - - -void bdNodeManager::SearchForLocalNet() -{ - - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::SearchForLocalNet()"; - std::cerr << std::endl; -#endif - - /* Check how many "Search Queries" we've got going. */ - - /* check queries */ - std::map::iterator it; - std::map queryStatus; - - - mQueryMgr->QueryStatus(queryStatus); - - int numSearchQueries = 0; - for(it = queryStatus.begin(); it != queryStatus.end(); it++) - { - if (it->second.mQFlags & BITDHT_QFLAGS_INTERNAL) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::SearchForLocalNet() Existing Internal Search: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - - numSearchQueries++; - } - } - -#define MAX_SEARCH_QUERIES 5 - - for(;numSearchQueries < MAX_SEARCH_QUERIES; numSearchQueries++) - { - /* install a new query */ - bdNodeId targetNodeId; - - /* get something that filter approves of */ - bool filterOk = false; - int i; - -#define MAX_FILTER_ATTEMPTS 3000 - - for(i = 0; (!filterOk) && (i < MAX_FILTER_ATTEMPTS); i++) - { - bdStdRandomNodeId(&targetNodeId); - std::string tststr; - bdStdPrintNodeId(tststr, &targetNodeId, false); - - if (mBloomFilter.test(tststr)) - { - filterOk = true; - } - } - - if (filterOk) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::SearchForLocalNet() " << i << " Attempts to find OkNode: "; - mDhtFns->bdPrintNodeId(std::cerr, &targetNodeId); - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::SearchForLocalNet() Failed to Find FilterOk this time: "; - mDhtFns->bdPrintNodeId(std::cerr, &targetNodeId); - std::cerr << std::endl; -#endif - } - - - uint32_t qflags = BITDHT_QFLAGS_INTERNAL | BITDHT_QFLAGS_DISGUISE; - mQueryMgr->addQuery(&targetNodeId, qflags); - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::SearchForLocalNet() Adding New Internal Search: "; - mDhtFns->bdPrintNodeId(std::cerr, &(targetNodeId)); - std::cerr << std::endl; -#endif - } -} - - -int bdNodeManager::status() -{ - /* do status of bdNode */ -#ifdef DEBUG_MGR - printState(); -#endif - - checkStatus(); - checkBadPeerStatus(); - - /* update the network numbers */ - mNetworkSize = mNodeSpace.calcNetworkSize(); - mBdNetworkSize = mNodeSpace.calcNetworkSizeWithFlag( - LOCAL_NET_FLAG); - -#ifdef DEBUG_MGR - std::cerr << "BitDHT NetworkSize: " << mNetworkSize << std::endl; - std::cerr << "BitDHT App NetworkSize: " << mBdNetworkSize << std::endl; -#endif - - return 1; -} - - -int bdNodeManager::checkStatus() -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus()"; - std::cerr << std::endl; -#endif - - /* check queries */ - std::map::iterator it; - std::map queryStatus; - - - mQueryMgr->QueryStatus(queryStatus); - - for(it = queryStatus.begin(); it != queryStatus.end(); it++) - { - bool doPing = false; - bool doRemove = false; - bool doCallback = false; - bool doSaveAddress = false; - uint32_t callbackStatus = 0; - - switch(it->second.mStatus) - { - default: - case BITDHT_QUERY_QUERYING: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Query in Progress id: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - } - break; - - case BITDHT_QUERY_FAILURE: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Query Failed: id: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - // BAD. - doRemove = true; - doCallback = true; - callbackStatus = BITDHT_MGR_QUERY_FAILURE; - } - break; - - case BITDHT_QUERY_FOUND_CLOSEST: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Found Closest: id: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - - doRemove = true; - doCallback = true; - callbackStatus = BITDHT_MGR_QUERY_PEER_OFFLINE; - } - break; - - case BITDHT_QUERY_PEER_UNREACHABLE: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() the Peer Online but Unreachable: id: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - - doRemove = true; - doCallback = true; - callbackStatus = BITDHT_MGR_QUERY_PEER_UNREACHABLE; - } - break; - - case BITDHT_QUERY_SUCCESS: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Found Query: id: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - //foundId = - doRemove = true; - doCallback = true; - doSaveAddress = true; - callbackStatus = BITDHT_MGR_QUERY_PEER_ONLINE; - } - break; - } - - /* remove done queries */ - if (doRemove) - { - if (it->second.mQFlags & BITDHT_QFLAGS_DO_IDLE) - { - doRemove = false; - } - } - - if (doRemove) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Removing query: id: "; - mFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - mQueryMgr->clearQuery(&(it->first)); - } - - /* FIND in activePeers */ - std::map::iterator pit; - pit = mActivePeers.find(it->first); - - if (pit == mActivePeers.end()) - { - /* only internal! - disable Callback / Ping */ - doPing = false; - doCallback = false; -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Internal: no cb for id: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - } - else - { - if (pit->second.mStatus == it->second.mStatus) - { - /* status is unchanged */ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Status unchanged for : "; - mFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << " status: " << it->second.mStatus; - std::cerr << std::endl; -#endif - - - time_t now = time(NULL); - /* now we check if we've done a callback before... */ - if (it->second.mQFlags & BITDHT_QFLAGS_UPDATES) - { - if (now - pit->second.mCallbackTS > QUERY_UPDATE_PERIOD) - { - // keep flags. -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Doing Update Callback for"; - mFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << " status: " << it->second.mStatus; - std::cerr << std::endl; -#endif - } - else - { - /* no callback this time */ - doPing = false; - doCallback = false; - } - } - else - { - doPing = false; - doCallback = false; - } - } - else - { - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Updating External Status for : "; - mFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << " to: " << it->second.mStatus; - std::cerr << std::endl; -#endif - /* update status */ - pit->second.mStatus = it->second.mStatus; - } - - if (doSaveAddress) - { - if (it->second.mResults.size() > 0) - { - pit->second.mDhtAddr = it->second.mResults.front().addr; - } - else - { - pit->second.mDhtAddr.sin_addr.s_addr = 0; - pit->second.mDhtAddr.sin_port = 0; - } - } - - /* add successful queries to ping list */ - if (doPing) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Starting Ping (TODO): id: "; - mFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - /* add first matching peer */ - //addPeerPing(foundId); - } - - /* callback on new successful queries */ - if (doCallback) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Doing Callback: id: "; - mFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - - time_t now = time(NULL); - pit->second.mCallbackTS = now; - bdId id(it->first,pit->second.mDhtAddr); - doPeerCallback(&id, callbackStatus); - } - } - } - return 1; -} - -#if 0 -bdNodeManager::checkPingStatus() -{ - - /* check queries */ - std::map::iterator it; - std::map pingStatus; - - PingStatus(pingStatus); - - for(it = pingStatus.begin(); it != pingStatus.end(); it++) - { - switch(it->second.mStatus) - { - case BITDHT_QUERY_QUERYING: - { - - } - break; - - case BITDHT_QUERY_FAILURE: - { - // BAD. - doRemove = true; - } - break; - - case BITDHT_QUERY_FOUND_CLOSEST: - { - - doRemove = true; - } - break; - - case BITDHT_QUERY_SUCCESS: - { - foundId = - doRemove = true; - } - break; - } - - /* remove done queries */ - if (doRemove) - { - clearQuery(it->first); - } - - /* add successful queries to ping list */ - if (doPing) - { - /* add first matching peer */ - addPeerPing(foundId); - } - - /* callback on new successful queries */ - if (doCallback) - { - - } - } -} -#endif - -int bdNodeManager::checkBadPeerStatus() -{ - bdId id; - uint32_t flags; - std::string nullstr; - - while(mBadPeerQueue.popPeer(&id, flags)) - { - doInfoCallback(&id, BITDHT_INFO_CB_TYPE_BADPEER, flags, nullstr); - } - return 1; -} - -int bdNodeManager::SearchOutOfDate() -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::SearchOutOfDate()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - - /* search for out-of-date peers */ - for(it = mActivePeers.begin(); it != mActivePeers.end(); it++) - { -#if 0 - if (old) - { - addQuery(it->first); - } -#endif - } - - return 1; -} - - - - /***** Functions to Call down to bdNodeManager ****/ - /* Request DHT Peer Lookup */ - /* Request Keyword Lookup */ - -void bdNodeManager::findDhtValue(bdNodeId * /*id*/, std::string /*key*/, uint32_t /*mode*/) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::findDhtValue() TODO"; - std::cerr << std::endl; -#endif -} - - - /***** Get Results Details *****/ -int bdNodeManager::getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::getDhtPeerAddress() Id: "; - mDhtFns->bdPrintNodeId(std::cerr, id); - std::cerr << " ... ? TODO" << std::endl; -#else - (void) id; -#endif - - std::map::iterator pit; - pit = mActivePeers.find(*id); - - std::cerr << "bdNodeManager::getDhtPeerAddress() Id: "; - mDhtFns->bdPrintNodeId(std::cerr, id); - std::cerr << std::endl; - - if (pit != mActivePeers.end()) - { - std::cerr << "bdNodeManager::getDhtPeerAddress() Found ActiveQuery"; - std::cerr << std::endl; - - if (pit->second.mStatus == BITDHT_QUERY_SUCCESS) - { - from = pit->second.mDhtAddr; - - std::cerr << "bdNodeManager::getDhtPeerAddress() Found Peer Address:"; - std::cerr << bdnet_inet_ntoa(from.sin_addr) << ":" << htons(from.sin_port); - std::cerr << std::endl; - - return 1; - } - } - return 0; - -} - -int bdNodeManager::getDhtValue(const bdNodeId *id, std::string key, std::string & /*value*/) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::getDhtValue() Id: "; - mDhtFns->bdPrintNodeId(std::cerr, id); - std::cerr << " key: " << key; - std::cerr << " ... ? TODO" << std::endl; -#else - (void) id; - (void) key; -#endif - - return 1; -} - -int bdNodeManager::getDhtBucket(const int idx, bdBucket &bucket) -{ - return mNodeSpace.getDhtBucket(idx, bucket); -} - -int bdNodeManager::getDhtQueries(std::map &queries) -{ - mQueryMgr->QueryStatus(queries); - return 1; -} - -int bdNodeManager::getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query) -{ - return mQueryMgr->QuerySummary(id, query); -} - - - /***** Add / Remove Callback Clients *****/ -void bdNodeManager::addCallback(BitDhtCallback *cb) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::addCallback()"; - std::cerr << std::endl; -#endif - /* search list */ - std::list::iterator it; - it = std::find(mCallbacks.begin(), mCallbacks.end(), cb); - if (it == mCallbacks.end()) - { - /* add it */ - mCallbacks.push_back(cb); - } -} - -void bdNodeManager::removeCallback(BitDhtCallback *cb) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::removeCallback()"; - std::cerr << std::endl; -#endif - /* search list */ - std::list::iterator it; - it = std::find(mCallbacks.begin(), mCallbacks.end(), cb); - if (it == mCallbacks.end()) - { - /* not found! */ - return; - } - it = mCallbacks.erase(it); -} - - -void bdNodeManager::addPeer(const bdId *id, uint32_t peerflags) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::addPeer() Overloaded (doing Callback)"; - std::cerr << std::endl; -#endif - doNodeCallback(id, peerflags); - - // call parent. - bdNode::addPeer(id, peerflags); - - return; -} - - - -void bdNodeManager::doNodeCallback(const bdId *id, uint32_t peerflags) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::doNodeCallback() "; - mDhtFns->bdPrintId(std::cerr, id); - std::cerr << "peerflags: " << peerflags; - std::cerr << std::endl; -#endif - - /* search list */ - std::list::iterator it; - for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) - { - (*it)->dhtNodeCallback(id, peerflags); - } - return; -} - -void bdNodeManager::doPeerCallback(const bdId *id, uint32_t status) -{ - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::doPeerCallback()"; - mDhtFns->bdPrintId(std::cerr, id); - std::cerr << "status: " << status; - std::cerr << std::endl; -#endif - - /* search list */ - std::list::iterator it; - for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) - { - (*it)->dhtPeerCallback(id, status); - } - return; -} - -void bdNodeManager::doValueCallback(const bdNodeId *id, std::string key, uint32_t status) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::doValueCallback()"; - std::cerr << std::endl; -#endif - /* search list */ - std::list::iterator it; - for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) - { - (*it)->dhtValueCallback(id, key, status); - } - return; -} - - -void bdNodeManager::doInfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::doInfoCallback()"; - std::cerr << std::endl; -#endif - /* search list */ - std::list::iterator it; - for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) - { - (*it)->dhtInfoCallback(id, type, flags, info); - } - return; -} - -void bdNodeManager::doIsBannedCallback(const sockaddr_in *addr, bool *isAvailable, bool *isBanned) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::doIsBannedCallback()"; - std::cerr << std::endl; -#endif - /* search list */ - std::list::iterator it; - *isBanned = false; - *isAvailable = false; - for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) - { - // set isBanned to true as soon as one callback answers with true - bool banned; - if((*it)->dhtIsBannedCallback(addr, &banned)) - { - *isBanned = *isBanned || banned; - *isAvailable = true; - } - } -} - - -#define BITDHT_IDENTITY_STRING_V1 "d1:" -#define BITDHT_IDENTITY_SIZE_V1 3 -#define BITDHT_PACKET_MIN_SIZE 4 - - /******************* Internals *************************/ -int bdNodeManager::isBitDhtPacket(char *data, int size, struct sockaddr_in & from) - -{ - - /* use a very simple initial check */ - if (size < BITDHT_PACKET_MIN_SIZE) - return 0; - - return (0 == strncmp(data, BITDHT_IDENTITY_STRING_V1, BITDHT_IDENTITY_SIZE_V1)); - - /* Below is the old version! */ - - -#ifdef DEBUG_MGR_PKT - std::cerr << "bdNodeManager::isBitDhtPacket() *******************************"; - std::cerr << " from " << inet_ntoa(from.sin_addr); - std::cerr << ":" << ntohs(from.sin_port); - std::cerr << std::endl; - { - /* print the fucker... only way to catch bad ones */ - std::string out; - for(int i = 0; i < size; i++) - { - if (isascii(data[i])) - { - out += data[i]; - } - else - { - bd_sprintf_append(out, "[%02lx]", (uint32_t) data[i]); - } - if ((i % 16 == 0) && (i != 0)) - { - out += "\n"; - } - } - std::cerr << out; - } - std::cerr << "bdNodeManager::isBitDhtPacket() *******************************"; - std::cerr << std::endl; -#else - (void) from; -#endif - - /* try to parse it! */ - /* convert to a be_node */ - be_node *node = be_decoden(data, size); - if (!node) - { - /* invalid decode */ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::isBitDhtPacket() be_decode failed. dropping"; - std::cerr << std::endl; - std::cerr << "bdNodeManager::BadPacket ******************************"; - std::cerr << " from " << inet_ntoa(from.sin_addr); - std::cerr << ":" << ntohs(from.sin_port); - std::cerr << std::endl; - { - /* print the fucker... only way to catch bad ones */ - std::string out; - for(int i = 0; i < size; i++) - { - if (isascii(data[i])) - { - out += data[i]; - } - else - { - bd_sprintf_append(out, "[%02lx]", (uint32_t) data[i]); - } - if ((i % 16 == 0) && (i != 0)) - { - out += "\n"; - } - } - std::cerr << out; - } - std::cerr << "bdNodeManager::BadPacket ******************************"; - std::cerr << std::endl; -#endif - return 0; - } - - /* find message type */ - uint32_t beType = beMsgType(node); - int ans = (beType != BITDHT_MSG_TYPE_UNKNOWN); - be_free(node); - -#ifdef DEBUG_MGR_PKT - if (ans) - { - std::cerr << "bdNodeManager::isBitDhtPacket() YES"; - std::cerr << std::endl; - } - else - { - std::cerr << "bdNodeManager::isBitDhtPacket() NO: Unknown Type"; - std::cerr << std::endl; - } - -#endif - return ans; -} - - -bdDebugCallback::~bdDebugCallback() -{ -} - -int bdDebugCallback::dhtPeerCallback(const bdId *id, uint32_t status) -{ - /* remove unused parameter warnings */ - (void) status; - -#ifdef DEBUG_MGR - std::cerr << "bdDebugCallback::dhtPeerCallback() Id: "; -#endif - bdStdPrintId(std::cerr, id); -#ifdef DEBUG_MGR - std::cerr << " status: " << std::hex << status << std::dec << std::endl; -#endif - return 1; -} - -int bdDebugCallback::dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) -{ - /* remove unused parameter warnings */ - (void) key; - (void) status; - -#ifdef DEBUG_MGR - std::cerr << "bdDebugCallback::dhtValueCallback() Id: "; -#endif - bdStdPrintNodeId(std::cerr, id); -#ifdef DEBUG_MGR - std::cerr << " key: " << key; - std::cerr << " status: " << std::hex << status << std::dec << std::endl; -#endif - - return 1; -} - - - - - -/******************* Connection Stuff ********************/ - - - -bool bdNodeManager::ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start) -{ - std::cerr << "bdNodeManager::ConnectionRequest()"; - std::cerr << std::endl; - - return mConnMgr->requestConnection(laddr, target, mode, delay, start); -} - -void bdNodeManager::ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, uint32_t bandwidth, uint32_t delay, uint32_t answer) -{ - std::cerr << "bdNodeManager::ConnectionAuth()"; - std::cerr << std::endl; - - if (answer == BITDHT_CONNECT_ANSWER_OKAY) - { - mConnMgr->AuthConnectionOk(srcId, proxyId, destId, mode, loc, bandwidth, delay); - } - else - { - mConnMgr->AuthConnectionNo(srcId, proxyId, destId, mode, loc, answer); - } -} - -void bdNodeManager::ConnectionOptions(uint32_t allowedModes, uint32_t flags) -{ - mConnMgr->setConnectionOptions(allowedModes, flags); -} - - - /***** Connections Requests *****/ - - // Overloaded from bdnode for external node callback. -void bdNodeManager::callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int point, int param, int cbtype, int errcode) -{ - std::cerr << "bdNodeManager::callbackConnect()"; - std::cerr << std::endl; - -#ifdef DEBUG_MGR -#endif - /* search list */ - std::list::iterator it; - for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) - { - (*it)->dhtConnectCallback(srcId, proxyId, destId, mode, point, param, cbtype, errcode); - } - return; -} - -int bdDebugCallback::dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t point, uint32_t param, uint32_t cbtype, uint32_t errcode) -{ - /* remove unused parameter warnings */ - (void) srcId; - (void) proxyId; - (void) destId; - (void) mode; - (void) point; - (void) param; - (void) cbtype; - (void) errcode; - -#ifdef DEBUG_MGR - std::cerr << "bdDebugCallback::dhtConnectCallback() Type: " << cbtype; - std::cerr << " errCode: " << errcode; - std::cerr << " srcId: "; - bdStdPrintId(std::cerr, srcId); - std::cerr << " proxyId: "; - bdStdPrintId(std::cerr, proxyId); - std::cerr << " destId: "; - bdStdPrintId(std::cerr, destId); - std::cerr << " mode: " << mode; - std::cerr << " param: " << param; - std::cerr << " point: " << point << std::endl; -#endif - - return 1; -} - - -int bdDebugCallback::dhtInfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info) -{ - /* remove unused parameter warnings */ - (void) id; - (void) type; - (void) flags; - (void) info; - -#ifdef DEBUG_MGR - std::cerr << "bdDebugCallback::dhtInfoCallback() Type: " << type; - std::cerr << " Id: "; - bdStdPrintId(std::cerr, id); - std::cerr << " flags: " << flags; - std::cerr << " info: " << info; - std::cerr << std::endl; -#endif - - return 1; -} - - - diff --git a/libbitdht/src/bitdht/bdmanager.h b/libbitdht/src/bitdht/bdmanager.h deleted file mode 100644 index e1440c154..000000000 --- a/libbitdht/src/bitdht/bdmanager.h +++ /dev/null @@ -1,209 +0,0 @@ -/******************************************************************************* - * bitdht/bdmanager.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_MANAGER_H -#define BITDHT_MANAGER_H - -/******* - * Node Manager. - ******/ - -/****************************************** - * 1) Maintains a list of ids to search for. - * 2) Sets up initial search for own node. - * 3) Checks on status of queries. - * 4) Callback on successful searches. - * - * This is pretty specific to RS requirements. - ****/ - -#define BITDHT_PS_MASK_ACTIONS (0x000000ff) -#define BITDHT_PS_MASK_STATE (0x0000ff00) - -#define BITDHT_PS_ACTION_SEARCHING (0x00000001) -#define BITDHT_PS_ACTION_WAITING (0x00000002) -#define BITDHT_PS_ACTION_PINGING (0x00000004) - -#define BITDHT_PS_STATE_UNKNOWN (0x00000100) -#define BITDHT_PS_STATE_OFFLINE (0x00000200) -#define BITDHT_PS_STATE_ONLINE (0x00000400) -#define BITDHT_PS_STATE_CONNECTED (0x00000800) - -#include "bitdht/bdiface.h" -#include "bitdht/bdnode.h" -#include "util/bdbloom.h" - - - -class bdQueryPeer -{ - public: - bdId mId; - uint32_t mStatus; - uint32_t mQFlags; - //time_t mLastQuery; - //time_t mLastFound; - struct sockaddr_in mDhtAddr; - time_t mCallbackTS; // for UPDATES flag. -}; - - -#define BITDHT_MGR_STATE_OFF 0 -#define BITDHT_MGR_STATE_STARTUP 1 -#define BITDHT_MGR_STATE_FINDSELF 2 -#define BITDHT_MGR_STATE_ACTIVE 3 -#define BITDHT_MGR_STATE_REFRESH 4 -#define BITDHT_MGR_STATE_QUIET 5 -#define BITDHT_MGR_STATE_FAILED 6 - -#define MAX_STARTUP_TIME 10 -#define MAX_REFRESH_TIME 10 - -#define BITDHT_MGR_QUERY_FAILURE 1 -#define BITDHT_MGR_QUERY_PEER_OFFLINE 2 -#define BITDHT_MGR_QUERY_PEER_UNREACHABLE 3 -#define BITDHT_MGR_QUERY_PEER_ONLINE 4 - - -/*** NB: Nothing in here is protected by mutexes - * must be done at a higher level! - ***/ - -class bdNodeManager: public bdNode, public BitDhtInterface -{ - public: - bdNodeManager(bdNodeId *id, std::string dhtVersion, std::string bootfile, std::string bootfilebak, const std::string &filterfile, bdDhtFunctions *fns); - - -void iteration(); - - /***** Functions to Call down to bdNodeManager ****/ - - - /* Friend Tracking */ -virtual void addBadPeer(const struct sockaddr_in &addr, uint32_t source, uint32_t reason, uint32_t age); -virtual void updateKnownPeer(const bdId *id, uint32_t type, uint32_t flags); - - /* Request DHT Peer Lookup */ - /* Request Keyword Lookup */ -virtual void addFindNode(bdNodeId *id, uint32_t mode); -virtual void removeFindNode(bdNodeId *id); -virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode); - - /***** Add / Remove Callback Clients *****/ -virtual void addCallback(BitDhtCallback *cb); -virtual void removeCallback(BitDhtCallback *cb); - - /***** Get Results Details *****/ -virtual int getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from); -virtual int getDhtValue(const bdNodeId *id, std::string key, std::string &value); -virtual int getDhtBucket(const int idx, bdBucket &bucket); - -virtual int getDhtQueries(std::map &queries); -virtual int getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query); - - /***** Connection Interface ****/ -virtual bool ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start); -virtual void ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, - uint32_t mode, uint32_t loc, uint32_t bandwidth, uint32_t delay, uint32_t answer); -virtual void ConnectionOptions(uint32_t allowedModes, uint32_t flags); - -virtual bool setAttachMode(bool on); - - /* stats and Dht state */ -virtual int startDht(); -virtual int stopDht(); -virtual int stateDht(); /* STOPPED, STARTING, ACTIVE, FAILED */ -virtual uint32_t statsNetworkSize(); -virtual uint32_t statsBDVersionSize(); /* same version as us! */ - -virtual uint32_t setDhtMode(uint32_t dhtFlags); - - /******************* Internals *************************/ - - // Overloaded from bdnode for external node callback. -virtual void addPeer(const bdId *id, uint32_t peerflags); - // Overloaded from bdnode for external node callback. -virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, - int mode, int point, int param, int cbtype, int errcode); - -int isBitDhtPacket(char *data, int size, struct sockaddr_in &from); - - // this function is used by bdFilter (must be public!) -void doIsBannedCallback(const sockaddr_in *addr, bool *isAvailable, bool* isBanned); - -private: - - -void doNodeCallback(const bdId *id, uint32_t peerflags); -void doPeerCallback(const bdId *id, uint32_t status); -void doValueCallback(const bdNodeId *id, std::string key, uint32_t status); -void doInfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info); - -int status(); -int checkStatus(); -int checkPingStatus(); -int checkBadPeerStatus(); -int SearchOutOfDate(); -void startQueries(); - -int QueryRandomLocalNet(); -void SearchForLocalNet(); - - std::map mActivePeers; - std::list mCallbacks; - - uint32_t mMode; - time_t mModeTS; - - time_t mStartTS; - time_t mSearchTS; - bool mSearchingDone; - - bdDhtFunctions *mDhtFns; - - uint32_t mNetworkSize; - uint32_t mBdNetworkSize; - - bdBloom mBloomFilter; - - bool mLocalNetEnhancements; - - /* future node functions */ - //addPeerPing(foundId); - //clearPing(it->first); - //PingStatus(it->first); -}; - -class bdDebugCallback: public BitDhtCallback -{ - public: - ~bdDebugCallback(); -virtual int dhtPeerCallback(const bdId *id, uint32_t status); -virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status); -virtual int dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t point, uint32_t param, uint32_t cbtype, uint32_t errcode); -virtual int dhtInfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info); - -}; - - -#endif diff --git a/libbitdht/src/bitdht/bdmsgs.cc b/libbitdht/src/bitdht/bdmsgs.cc deleted file mode 100644 index 07114dbab..000000000 --- a/libbitdht/src/bitdht/bdmsgs.cc +++ /dev/null @@ -1,1087 +0,0 @@ -/******************************************************************************* - * bitdht/bdmsgs.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include -#include -#include "bitdht/bencode.h" -#include "bitdht/bdmsgs.h" - - -int create_ping_message(); -int response_ping_message(); - -int find_node_message(); -int response_node_message(); - -int get_peers_message(); -int response_peers_message(); -int response_closestnodes_message(); - - /* -ping Query = {"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}} -bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe - */ - -/**** - * #define DEBUG_MSG_DUMP 1 - * #define DEBUG_MSG_TYPE 1 - * #define DEBUG_MSGS 1 - ****/ - - -int bitdht_create_ping_msg(bdToken *tid, bdNodeId *id, bdToken *vid, char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_create_ping_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - be_node *iddict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - - be_add_keypair(iddict, "id", idnode); - - be_node *pingnode = be_create_str("ping"); - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *qynode = be_create_str("q"); - - be_add_keypair(dict, "a", iddict); - - be_add_keypair(dict, "q", pingnode); - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", qynode); - - if (vid) - { - be_node *vnode = be_create_str_wlen((char *) vid->data, vid->len); - be_add_keypair(dict, "v", vnode); - } - - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; - - -} - - - /* -Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}} -bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re - */ - -int bitdht_response_ping_msg(bdToken *tid, bdNodeId *id, bdToken *vid, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_response_ping_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *iddict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *yqrnode = be_create_str("r"); - - be_node *vnode = be_create_str_wlen((char *) vid->data, vid->len); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(dict, "r", iddict); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "v", vnode); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - - /* -find_node Query = {"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}} -bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe - */ - - -int bitdht_find_node_msg(bdToken *tid, bdNodeId *id, bdNodeId *target, bool localoption, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_find_node_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *iddict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - be_node *targetnode = be_create_str_wlen((char *) target->data, BITDHT_KEY_LEN); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *yqrnode = be_create_str("q"); - be_node *findnode = be_create_str("find_node"); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(iddict, "target", targetnode); - be_add_keypair(dict, "a", iddict); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "q", findnode); - - if (localoption) - { - be_node *optionnode = be_create_str("l"); - be_add_keypair(dict, "o", optionnode); - } - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - - - /* -Response = {"t":"aa", "y":"r", "r": {"id":"0123456789abcdefghij", "nodes": "def456..."}} -bencoded = d1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re - */ - -int bitdht_resp_node_msg(bdToken *tid, bdNodeId *id, std::list &nodes, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_resp_node_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *replydict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - - be_node *peersnode = makeCompactNodeIdString(nodes); - - be_node *yqrnode = be_create_str("r"); - - be_add_keypair(replydict, "id", idnode); - be_add_keypair(replydict, "nodes", peersnode); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "r", replydict); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - -#ifdef DEBUG_MSG_DUMP - fprintf(stderr, "bitdht_resp_node_msg() len = %d / %d\n", blen, avail); -#endif - - return blen; -} - - - /* -get_peers Query = {"t":"aa", "y":"q", "q":"get_peers", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456"}} -bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe - */ - -int bitdht_get_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_get_peers_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *iddict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - be_node *hashnode = be_create_str_wlen((char *) info_hash->data, BITDHT_KEY_LEN); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *yqrnode = be_create_str("q"); - be_node *findnode = be_create_str("get_peers"); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(iddict, "info_hash", hashnode); - be_add_keypair(dict, "a", iddict); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "q", findnode); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - - /* -Response with peers = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "values": ["axje.u", "idhtnm"]}} -bencoded = d1:rd2:id20:abcdefghij01234567895:token8:aoeusnth6:valuesl6:axje.u6:idhtnmee1:t2:aa1:y1:re - */ - -int bitdht_peers_reply_hash_msg(bdToken *tid, bdNodeId *id, - bdToken *token, std::list &values, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_peers_reply_hash_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *replydict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *tokennode = be_create_str_wlen((char *) token->data, token->len); - be_node *valuesnode = makeCompactPeerIds(values); - - be_node *yqrnode = be_create_str("r"); - - be_add_keypair(replydict, "id", idnode); - be_add_keypair(replydict, "token", tokennode); - be_add_keypair(replydict, "values", valuesnode); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "r", replydict); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - /** - -Response with closest nodes = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "nodes": "def456..."}} -bencoded = d1:rd2:id20:abcdefghij01234567895:nodes9:def456...5:token8:aoeusnthe1:t2:aa1:y1:re - - **/ - - -int bitdht_peers_reply_closest_msg(bdToken *tid, bdNodeId *id, - bdToken *token, std::list &nodes, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_peers_reply_closest_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *replydict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *tokennode = be_create_str_wlen((char *) token->data, token->len); - - be_node *peersnode = makeCompactNodeIdString(nodes); - - be_node *yqrnode = be_create_str("r"); - - be_add_keypair(replydict, "id", idnode); - be_add_keypair(replydict, "token", tokennode); - be_add_keypair(replydict, "nodes", peersnode); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "r", replydict); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - - -/**** FINAL TWO MESSAGES! ***/ - -/**** -announce_peers Query = {"t":"aa", "y":"q", "q":"announce_peer", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456", "port": 6881, "token": "aoeusnth"}} -bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe - -****/ - -int bitdht_announce_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash, uint32_t port, bdToken *token, char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_announce_peers_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - be_node *iddict = be_create_dict(); - - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - - be_node *hashnode = be_create_str_wlen((char *) info_hash->data, BITDHT_KEY_LEN); - be_node *portnode = be_create_int(port); - be_node *tokennode = be_create_str_wlen((char *) token->data, token->len); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(iddict, "info_hash", hashnode); - be_add_keypair(iddict, "port", portnode); - be_add_keypair(iddict, "token", tokennode); - - be_node *announcenode = be_create_str("announce_peer"); - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *qynode = be_create_str("q"); - - be_add_keypair(dict, "a", iddict); - - be_add_keypair(dict, "q", announcenode); - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", qynode); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; - -} - - -/***** -Response to Announce Peers = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}} -bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re -****/ - -/**** - * NB: This is the same as a PONG msg! - ***/ - -int bitdht_reply_announce_msg(bdToken *tid, bdNodeId *id, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_response_ping_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *iddict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *yqrnode = be_create_str("r"); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(dict, "r", iddict); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - - -/************************ Parsing Messages ********************* - * - */ - -be_node *beMsgGetDictNode(be_node *node, const char *key) -{ - /* make sure its a dictionary */ - if (node->type != BE_DICT) - { - return NULL; - } - - /* get dictionary entry 'y' */ - int i; - for(i = 0; node->val.d[i].val; i++) - { - if (0 == strcmp(key, node->val.d[i].key)) - { - return node->val.d[i].val; - } - } - return NULL; -} - - - -int beMsgMatchString(be_node *n, const char *str, int len) -{ - if (n->type != BE_STR) - { - return 0; - } - if (len != be_str_len(n)) - { - return 0; - } - - int i; - for(i = 0; i < len; i++) - { - if (n->val.s[i] != str[i]) - return 0; - } - return 1; -} - - -uint32_t beMsgGetY(be_node *n) -{ - be_node *val = beMsgGetDictNode(n, "y"); - - if(val == NULL) - return BE_Y_UNKNOWN ; - - if (val->type != BE_STR) - { - return BE_Y_UNKNOWN; - } - - if (val->val.s[0] == 'q') - { - return BE_Y_Q; - } - else if (val->val.s[0] == 'r') - { - return BE_Y_R; - } - - return BE_Y_UNKNOWN; -} - - - -uint32_t beMsgType(be_node *n) -{ - /* check for - * y: q or r - */ - uint32_t beY = beMsgGetY(n); - -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() beY: " << beY << std::endl; -#endif - - if (beY == BE_Y_UNKNOWN) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() UNKNOWN MSG TYPE" << std::endl; -#endif - - return BITDHT_MSG_TYPE_UNKNOWN; - } - - if (beY == BE_Y_Q) /* query */ - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY MSG TYPE" << std::endl; -#endif - be_node *query = beMsgGetDictNode(n, "q"); - - if(query == NULL) - return BITDHT_MSG_TYPE_UNKNOWN; - - if (beMsgMatchString(query, "ping", 4)) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY:ping MSG TYPE" << std::endl; -#endif - return BITDHT_MSG_TYPE_PING; - } - else if (beMsgMatchString(query, "find_node", 9)) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY:find_node MSG TYPE" << std::endl; -#endif - return BITDHT_MSG_TYPE_FIND_NODE; - } - else if (beMsgMatchString(query, "get_peers", 9)) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY:get_peers MSG TYPE" << std::endl; -#endif - return BITDHT_MSG_TYPE_GET_HASH; - } - else if (beMsgMatchString(query, "announce_peer", 13)) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY:announce_peer MSG TYPE" << std::endl; -#endif - return BITDHT_MSG_TYPE_POST_HASH; - } - else if (beMsgMatchString(query, "connect", 7)) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY:connect MSG TYPE" << std::endl; -#endif - return BITDHT_MSG_TYPE_CONNECT; - } -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY:UNKNOWN MSG TYPE, dumping dict" << std::endl; - /* dump answer */ - be_dump(n); -#endif - return BITDHT_MSG_TYPE_UNKNOWN; - } - - if (beY != BE_Y_R) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() UNKNOWN2 MSG TYPE" << std::endl; -#endif - return BITDHT_MSG_TYPE_UNKNOWN; - } - -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() REPLY MSG TYPE" << std::endl; -#endif - - /* otherwise a reply or - invalid - pong {"id":"mnopqrstuvwxyz123456"} - reply_neigh { "id":"0123456789abcdefghij", "nodes": "def456..."}} - reply_hash { "id":"abcdefghij0123456789", "token":"aoeusnth", "values": ["axje.u", "idhtnm"]}} - reply_near { "id":"abcdefghij0123456789", "token":"aoeusnth", "nodes": "def456..."} - */ - - be_node *reply = beMsgGetDictNode(n, "r"); - if (!reply) - { - return BITDHT_MSG_TYPE_UNKNOWN; - } - - be_node *id = beMsgGetDictNode(reply, "id"); - be_node *token = beMsgGetDictNode(reply, "token"); - be_node *values = beMsgGetDictNode(reply, "values"); - be_node *nodes = beMsgGetDictNode(reply, "nodes"); - - if (!id) - { - return BITDHT_MSG_TYPE_UNKNOWN; - } - - if (token && values) - { - /* reply hash */ - return BITDHT_MSG_TYPE_REPLY_HASH; - } - else if (token && nodes) - { - /* reply near */ - return BITDHT_MSG_TYPE_REPLY_NEAR; - } - else if (nodes) - { - /* reply neigh */ - return BITDHT_MSG_TYPE_REPLY_NODE; - } - else - { - /* pong */ - return BITDHT_MSG_TYPE_PONG; - } - /* TODO reply_post */ - //return BITDHT_MSG_TYPE_REPLY_POST; - /* can't get here! */ - return BITDHT_MSG_TYPE_UNKNOWN; -} - -/* extract specific types here */ - -int beMsgGetToken(be_node *n, bdToken &token) -{ - if (n->type != BE_STR) - { - return 0; - } - int len = be_str_len(n); - - if(len > BITDHT_TOKEN_MAX_LEN) - return 0 ; - - for(int i = 0; i < len; i++) - { - token.data[i] = n->val.s[i]; - } - token.len = len; - return 1; -} - -int beMsgGetNodeId(be_node *n, bdNodeId &nodeId) -{ - if (n->type != BE_STR) - { - return 0; - } - int len = be_str_len(n); - if (len != BITDHT_KEY_LEN) - { - return 0; - } - for(int i = 0; i < len; i++) - { - nodeId.data[i] = n->val.s[i]; - } - return 1; -} - -be_node *makeCompactNodeIdString(std::list &nodes) -{ - int len = BITDHT_COMPACTNODEID_LEN * nodes.size(); - std::string cni; - std::list::iterator it; - for(it = nodes.begin(); it != nodes.end(); it++) - { - cni += encodeCompactNodeId(&(*it)); - } - - - be_node *cninode = be_create_str_wlen((char *) cni.c_str(), len); - return cninode; -} - -be_node *makeCompactPeerIds(std::list &values) -{ - be_node *valuesnode = be_create_list(); - std::list::iterator it; - for(it = values.begin(); it != values.end(); it++) - { - be_node *val1 = be_create_str_wlen((char *) it->c_str(), it->length()); - be_add_list(valuesnode, val1); - } - return valuesnode; -} - - -int beMsgGetListBdIds(be_node *n, std::list &nodes) -{ - /* extract the string pointer, and size */ - /* split into parts */ - - if (n->type != BE_STR) - { - return 0; - } - - int len = be_str_len(n); - int count = len / BITDHT_COMPACTNODEID_LEN; - for(int i = 0; i < count; i++) - { - bdId id; - if (decodeCompactNodeId(&id, &(n->val.s[i*BITDHT_COMPACTNODEID_LEN]), BITDHT_COMPACTNODEID_LEN)) - { - nodes.push_back(id); - } - } - return 1; -} - -int beMsgGetBdId(be_node *n, bdId &id) -{ - /* extract the string pointer, and size */ - /* split into parts */ - - if (n->type != BE_STR) - { - return 0; - } - - int len = be_str_len(n); - if (len < BITDHT_COMPACTNODEID_LEN) - { - return 0; - } - if (decodeCompactNodeId(&id, n->val.s, BITDHT_COMPACTNODEID_LEN)) - { - return 1; - } - return 0; -} - -std::string encodeCompactNodeId(bdId *id) -{ - std::string enc; - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - enc += id->id.data[i]; - } - /* convert ip address (already in network order) */ - enc += encodeCompactPeerId(&(id->addr)); - return enc; -} - -int decodeCompactNodeId(bdId *id, char *enc, int len) -{ - if (len < BITDHT_COMPACTNODEID_LEN) - { - return 0; - } - - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - id->id.data[i] = enc[i]; - } - - char *ipenc = &(enc[BITDHT_COMPACTNODEID_LEN - BITDHT_COMPACTPEERID_LEN]); - if (!decodeCompactPeerId(&(id->addr), ipenc, BITDHT_COMPACTPEERID_LEN)) - { - return 0; - } - - return 1; -} - -std::string encodeCompactPeerId(struct sockaddr_in *addr) -{ - std::string encstr; - char enc[BITDHT_COMPACTPEERID_LEN]; - uint32_t *ip = (uint32_t *) (enc); - uint16_t *port = (uint16_t *) (&enc[4]); - (*ip) = addr->sin_addr.s_addr; - (*port) = addr->sin_port; - - encstr.append(enc, BITDHT_COMPACTPEERID_LEN); - return encstr; -} - -int decodeCompactPeerId(struct sockaddr_in *addr, char *enc, int len) -{ - if (len < BITDHT_COMPACTPEERID_LEN) - return 0; - - memset(addr, 0, sizeof(struct sockaddr_in)); - - //uint32_t *ip = (uint32_t *) (enc); - uint16_t *port = (uint16_t *) (&enc[4]); - - memcpy(& addr->sin_addr.s_addr, enc, sizeof(in_addr_t)); // aligned version of "addr->sin_addr.s_addr = (*ip); " - addr->sin_port = (*port); - addr->sin_family = AF_INET; - - return 1; -} - - -int beMsgGetListStrings(be_node *n, std::list &values) -{ - if (n->type != BE_LIST) - { - return 0; - } - for(int i = 0; n->val.l[i] != NULL; i++) - { - be_node *val = n->val.l[i]; - - if (val == NULL || val->type != BE_STR) - return 0; - - int len = be_str_len(val); - std::string str; - str.append(val->val.s, len); - values.push_back(str); - } - return 1; -} - - -int beMsgGetUInt32(be_node *n, uint32_t *port) -{ - if (n->type != BE_INT) - { - return 0; - } - *port = n->val.i; - return 1; -} - - - - - - - -/******************************************************************************************************************** - * CONNECTION EXTENSIONS - * - */ - - /* -ping Query = {"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}} -bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe - */ - - /* -Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}} -bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re - */ - - /* -find_node Query = {"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}} -bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe - */ - -#if 0 -int bitdht_find_node_msg(bdToken *tid, bdNodeId *id, bdNodeId *target, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_find_node_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *iddict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - be_node *targetnode = be_create_str_wlen((char *) target->data, BITDHT_KEY_LEN); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *yqrnode = be_create_str("q"); - be_node *findnode = be_create_str("find_node"); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(iddict, "target", targetnode); - be_add_keypair(dict, "a", iddict); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "q", findnode); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} -#endif - -/**** - * Thinking about the format of this message. - * id: ownId is stanard in all other messages, so should keep the same!. - * src: - * target: - * mode: d,p or r - * - * A -> B -> C - * direct: A ------> B - * ---> id:A src:A target:B mode:d - * <--- id:B src:A target:B mode:d a:OK - * - * proxy: A ------> B -------> C - * A->B id:A src:A target:C mode:p q - * - * a) - * B->A id:B src:A target:C mode:p r:NOK - * - * b) - * B->C id:B src:A target:C mode:p q - * C->B id:C src:A target:C mode:p r:NOK - * B->A id:B src:A target:C mode:p r:NOK - * - * c) - * B->C id:B src:A target:C mode:p q - * C->B id:C src:A target:C mode:p r:OK - * B->A id:B src:A target:C mode:p r:OK - * connect happens. - * Dropped packets will affect this! - * - * - * REQUIRED BITS FOR A MESSAGE - * 1) DIRECT - * -> REQUEST, ownId, targetId, transId, mode. - * -> RESPONSE, ownId, targetId, transId, mode, answer. - * - * 2) PROXY - */ - - -int bitdht_connect_genmsg(bdToken *tid, bdNodeId *id, int msgtype, bdId *src, bdId *dest, int mode, int param, int status, char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_connect_genmsg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *iddict = be_create_dict(); - - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - - std::string srcEnc = encodeCompactNodeId(src); - std::string destEnc = encodeCompactNodeId(dest); - - be_node *srcnode = be_create_str_wlen(srcEnc.c_str(), BITDHT_COMPACTNODEID_LEN); - be_node *destnode = be_create_str_wlen(destEnc.c_str(), BITDHT_COMPACTNODEID_LEN); - be_node *typenode = be_create_int(msgtype); - be_node *statusnode = be_create_int(status); - be_node *modenode = be_create_int(mode); - be_node *paramnode = be_create_int(param); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *yqrnode = be_create_str("q"); - be_node *cmdnode = be_create_str("connect"); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(iddict, "src", srcnode); - be_add_keypair(iddict, "dest", destnode); - be_add_keypair(iddict, "mode", modenode); - be_add_keypair(iddict, "param", paramnode); - be_add_keypair(iddict, "status", statusnode); - be_add_keypair(iddict, "type", typenode); - - be_add_keypair(dict, "a", iddict); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "q", cmdnode); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - - -bool bitdht_msgtype(uint32_t msg_type, std::string &name) -{ - switch(msg_type) - { - case BITDHT_MSG_TYPE_PING: - name = "PING"; - break; - case BITDHT_MSG_TYPE_PONG: - name = "PONG"; - break; - case BITDHT_MSG_TYPE_FIND_NODE: - name = "FIND_NODE"; - break; - case BITDHT_MSG_TYPE_REPLY_NODE: - name = "REPLY_NODE"; - break; - case BITDHT_MSG_TYPE_GET_HASH: - name = "GET_HASH"; - break; - case BITDHT_MSG_TYPE_REPLY_HASH: - name = "REPLY_HASH"; - break; - case BITDHT_MSG_TYPE_REPLY_NEAR: - name = "REPLY_NEAR"; - break; - case BITDHT_MSG_TYPE_POST_HASH: - name = "POST_HASH"; - break; - case BITDHT_MSG_TYPE_REPLY_POST: - name = "REPLY_POST"; - break; - - case BITDHT_MSG_TYPE_CONNECT: - name = "CONNECT"; - break; - case BITDHT_MSG_TYPE_CONNECT_REQUEST: - name = "CONNECT_REQUEST"; - break; - case BITDHT_MSG_TYPE_CONNECT_REPLY: - name = "CONNECT_REPLY"; - break; - case BITDHT_MSG_TYPE_CONNECT_START: - name = "CONNECT_START"; - break; - case BITDHT_MSG_TYPE_CONNECT_ACK: - name = "CONNECT_ACK"; - break; - default: - name = "UNKNOWN"; - return false; - break; - } - - return true; -} - - - diff --git a/libbitdht/src/bitdht/bdmsgs.h b/libbitdht/src/bitdht/bdmsgs.h deleted file mode 100644 index 99a26d76a..000000000 --- a/libbitdht/src/bitdht/bdmsgs.h +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************* - * bitdht/bdmsgs.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_MSGS_H -#define BITDHT_MSGS_H - -#include -#include -#include -#include "bitdht/bencode.h" -#include "bitdht/bdobj.h" -#include "bitdht/bdpeer.h" - -#define BITDHT_MSG_TYPE_UNKNOWN 0 -#define BITDHT_MSG_TYPE_PING 1 -#define BITDHT_MSG_TYPE_PONG 2 -#define BITDHT_MSG_TYPE_FIND_NODE 3 -#define BITDHT_MSG_TYPE_REPLY_NODE 4 -#define BITDHT_MSG_TYPE_GET_HASH 5 -#define BITDHT_MSG_TYPE_REPLY_HASH 6 -#define BITDHT_MSG_TYPE_REPLY_NEAR 7 -#define BITDHT_MSG_TYPE_POST_HASH 8 -#define BITDHT_MSG_TYPE_REPLY_POST 9 - - - -// THESE ARE EXTENSIONS -#define BITDHT_MSG_TYPE_CONNECT 20 - -// CONNECTIONS. -#define BITDHT_MSG_TYPE_CONNECT_REQUEST 101 -#define BITDHT_MSG_TYPE_CONNECT_REPLY 102 -#define BITDHT_MSG_TYPE_CONNECT_START 103 -#define BITDHT_MSG_TYPE_CONNECT_ACK 104 - -// FANCY HASHES. - - -#define BITDHT_COMPACTNODEID_LEN 26 -#define BITDHT_COMPACTPEERID_LEN 6 - -#define BE_Y_UNKNOWN 0 -#define BE_Y_R 1 -#define BE_Y_Q 2 - - -/****** Known BD Version Strings ******/ - -#define BITDHT_VID_RS1 1 -#define BITDHT_VID_UT 2 - - -int bitdht_create_ping_msg(bdToken *tid, bdNodeId *id, bdToken *vid, char *msg, int avail); -int bitdht_response_ping_msg(bdToken *tid, bdNodeId *id, bdToken *vid, char *msg, int avail); -int bitdht_find_node_msg(bdToken *tid, bdNodeId *id, bdNodeId *target, bool localnet, char *msg, int avail); -int bitdht_resp_node_msg(bdToken *tid, bdNodeId *id, std::list &nodes, - char *msg, int avail); -int bitdht_get_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash, - char *msg, int avail); -int bitdht_peers_reply_hash_msg(bdToken *tid, bdNodeId *id, - bdToken *token, std::list &values, - char *msg, int avail); -int bitdht_peers_reply_closest_msg(bdToken *tid, bdNodeId *id, - bdToken *token, std::list &nodes, - char *msg, int avail); -int bitdht_announce_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash, - uint32_t port, bdToken *token, char *msg, int avail); -int bitdht_reply_announce_msg(bdToken *tid, bdNodeId *id, - char *msg, int avail); - - -// Extensions. -int bitdht_connect_genmsg(bdToken *tid, bdNodeId *id, int msgtype, bdId *src, bdId *dest, int mode, int param, int status, char *msg, int avail); - - -//int response_peers_message() -//int response_closestnodes_message() - -be_node *beMsgGetDictNode(be_node *node, const char *key); -int beMsgMatchString(be_node *n, const char *str, int len); -uint32_t beMsgGetY(be_node *n); -uint32_t beMsgType(be_node *n); - -bool bitdht_msgtype(uint32_t msg_type, std::string &name); - - -uint32_t convertBdVersionToVID(bdVersion *version); - -be_node *makeCompactPeerIds(std::list &values); -be_node *makeCompactNodeIdString(std::list &nodes); - -int beMsgGetToken(be_node *n, bdToken &token); -int beMsgGetNodeId(be_node *n, bdNodeId &nodeId); -int beMsgGetBdId(be_node *n, bdId &id); -int beMsgGetListBdIds(be_node *n, std::list &nodes); - -int beMsgGetListStrings(be_node *n, std::list &values); -int beMsgGetUInt32(be_node *n, uint32_t *port); - -/* Low Level conversion functions */ -int decodeCompactPeerId(struct sockaddr_in *addr, char *enc, int len); -std::string encodeCompactPeerId(struct sockaddr_in *addr); - -int decodeCompactNodeId(bdId *id, char *enc, int len); -std::string encodeCompactNodeId(bdId *id); - - - -#endif diff --git a/libbitdht/src/bitdht/bdnode.cc b/libbitdht/src/bitdht/bdnode.cc deleted file mode 100644 index 5d3e4fd25..000000000 --- a/libbitdht/src/bitdht/bdnode.cc +++ /dev/null @@ -1,2478 +0,0 @@ -/******************************************************************************* - * bitdht/bdnode.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bitdht/bdnode.h" - -#include "bitdht/bencode.h" -#include "bitdht/bdmsgs.h" - -#include "bitdht/bdquerymgr.h" -#include "bitdht/bdfilter.h" - -#include "util/bdnet.h" -#include "util/bdrandom.h" -#include "util/bdstring.h" - -#include -#include - -#include -#include - - -#define BITDHT_QUERY_START_PEERS 10 -#define BITDHT_QUERY_NEIGHBOUR_PEERS 8 - -#define BITDHT_MAX_REMOTE_QUERY_AGE 3 // 3 seconds, keep it fresh. -#define MAX_REMOTE_PROCESS_PER_CYCLE 5 - -/**** - * #define USE_HISTORY 1 - * - * #define DEBUG_NODE_MULTIPEER 1 - * #define DEBUG_NODE_PARSE 1 - - * #define DEBUG_NODE_MSGS 1 - * #define DEBUG_NODE_ACTIONS 1 - - * #define DEBUG_NODE_MSGIN 1 - * #define DEBUG_NODE_MSGOUT 1 - * - * #define DISABLE_BAD_PEER_FILTER 1 - * - ***/ - -//#define DISABLE_BAD_PEER_FILTER 1 - -//#define USE_HISTORY 1 - -#define HISTORY_PERIOD 60 - -bdNode::bdNode(bdNodeId *ownId, std::string dhtVersion, const std::string& bootfile, const std::string &bootfilebak, const std::string& filterfile, bdDhtFunctions *fns, bdNodeManager *manager) - :mNodeSpace(ownId, fns), - mFilterPeers(filterfile,ownId, BITDHT_FILTER_REASON_OWNID, fns, manager), - mQueryMgr(NULL), - mConnMgr(NULL), - mOwnId(*ownId), mDhtVersion(dhtVersion), mStore(bootfile, bootfilebak, fns), mFns(fns), - mFriendList(ownId), mHistory(HISTORY_PERIOD) -{ - init(); /* (uses this pointers) stuff it - do it here! */ -} - -void bdNode::init() -{ - mQueryMgr = new bdQueryManager(&mNodeSpace, mFns, this); - mConnMgr = new bdConnectManager(&mOwnId, &mNodeSpace, mQueryMgr, mFns, this); - - //setNodeOptions(BITDHT_OPTIONS_MAINTAIN_UNSTABLE_PORT); - setNodeOptions(0); - - mNodeDhtMode = 0; - setNodeDhtMode(BITDHT_MODE_TRAFFIC_DEFAULT); - -} -bool bdNode::getFilteredPeers(std::list& peers) -{ - mFilterPeers.getFilteredPeers(peers) ; - return true ; -} -// -//void bdNode::loadFilteredPeers(const std::list& peers) -//{ -// mFilterPeers.loadFilteredPeers(peers) ; -//} -/* Unfortunately I've ended up with 2 calls down through the heirarchy... - * not ideal - must clean this up one day. - */ - -#define ATTACH_NUMBER 5 -void bdNode::setNodeOptions(uint32_t optFlags) -{ - mNodeOptionFlags = optFlags; - if (optFlags & BITDHT_OPTIONS_MAINTAIN_UNSTABLE_PORT) - { - mNodeSpace.setAttachedFlag(BITDHT_PEER_STATUS_DHT_ENGINE | BITDHT_PEER_STATUS_DHT_ENGINE_VERSION, ATTACH_NUMBER); - } - else - { - mNodeSpace.setAttachedFlag(BITDHT_PEER_STATUS_DHT_ENGINE | BITDHT_PEER_STATUS_DHT_ENGINE_VERSION, 0); - } -} - -#define BDNODE_HIGH_MSG_RATE 50 -#define BDNODE_MED_MSG_RATE 10 -#define BDNODE_LOW_MSG_RATE 5 -#define BDNODE_TRICKLE_MSG_RATE 3 - -/* So we are setting this up so you can independently update each parameter.... - * if the mask is empty - it'll use the previous parameter. - * - */ - - -uint32_t bdNode::setNodeDhtMode(uint32_t dhtFlags) -{ - std::cerr << "bdNode::setNodeDhtMode(" << dhtFlags << "), origFlags: " << mNodeDhtMode; - std::cerr << std::endl; - - uint32_t origFlags = mNodeDhtMode; - - - uint32_t traffic = dhtFlags & BITDHT_MODE_TRAFFIC_MASK; - if (traffic) - { - switch(traffic) - { - default: - case BITDHT_MODE_TRAFFIC_LOW: - mMaxAllowedMsgs = BDNODE_LOW_MSG_RATE; - break; - case BITDHT_MODE_TRAFFIC_MED: - mMaxAllowedMsgs = BDNODE_MED_MSG_RATE; - break; - case BITDHT_MODE_TRAFFIC_HIGH: - mMaxAllowedMsgs = BDNODE_HIGH_MSG_RATE; - break; - case BITDHT_MODE_TRAFFIC_TRICKLE: - mMaxAllowedMsgs = BDNODE_TRICKLE_MSG_RATE; - break; - } - } - else - { - dhtFlags |= (origFlags & BITDHT_MODE_TRAFFIC_MASK); - } - - uint32_t relay = dhtFlags & BITDHT_MODE_RELAYSERVER_MASK; - if ((relay) && (relay != (origFlags & BITDHT_MODE_RELAYSERVER_MASK))) - { - /* changed */ - switch(relay) - { - default: - case BITDHT_MODE_RELAYSERVERS_IGNORED: - mRelayMode = BITDHT_RELAYS_OFF; - dropRelayServers(); - break; - case BITDHT_MODE_RELAYSERVERS_FLAGGED: - mRelayMode = BITDHT_RELAYS_ON; - pingRelayServers(); - break; - case BITDHT_MODE_RELAYSERVERS_ONLY: - mRelayMode = BITDHT_RELAYS_ONLY; - pingRelayServers(); - break; - case BITDHT_MODE_RELAYSERVERS_SERVER: - mRelayMode = BITDHT_RELAYS_SERVER; - pingRelayServers(); - break; - } - mConnMgr->setRelayMode(mRelayMode); - } - else - { - dhtFlags |= (origFlags & BITDHT_MODE_RELAYSERVER_MASK); - } - - mNodeDhtMode = dhtFlags; - - std::cerr << "bdNode::setNodeDhtMode() newFlags: " << mNodeDhtMode; - std::cerr << std::endl; - - return dhtFlags; -} - - -void bdNode::getOwnId(bdNodeId *id) -{ - *id = mOwnId; -} - -/***** Startup / Shutdown ******/ -void bdNode::restartNode() -{ - mAccount.resetStats(); - - mStore.reloadFromStore(); - - /* setup */ - bdPeer peer; - while(mStore.getPeer(&peer)) - { - addPotentialPeer(&(peer.mPeerId), NULL); - } -} - - -void bdNode::shutdownNode() -{ - /* clear the queries */ - mQueryMgr->shutdownQueries(); - mConnMgr->shutdownConnections(); - - mRemoteQueries.clear(); - - /* clear the space */ - mNodeSpace.clear(); - mHashSpace.clear(); - - /* clear other stuff */ - mPotentialPeers.clear(); - mStore.clear(); - - /* clean up any outgoing messages */ - while(mOutgoingMsgs.size() > 0) - { - bdNodeNetMsg *msg = mOutgoingMsgs.front(); - mOutgoingMsgs.pop_front(); - - /* cleanup message */ - delete msg; - } -} - - -/* Crappy initial store... use bdspace as answer */ -void bdNode::updateStore() -{ - mStore.writeStore(); -} - -bool bdNode::addressBanned(const sockaddr_in& raddr) -{ - return !mFilterPeers.addrOkay(const_cast(&raddr)) ; -} - -void bdNode::printState() -{ - std::cerr << "bdNode::printState() for Peer: "; - mFns->bdPrintNodeId(std::cerr, &mOwnId); - std::cerr << std::endl; - - mNodeSpace.printDHT(); - - mQueryMgr->printQueries(); - mConnMgr->printConnections(); - - std::cerr << "Outstanding Potential Peers: " << mPotentialPeers.size(); - std::cerr << std::endl; - -#ifdef USE_HISTORY - mHistory.cleanupOldMsgs(); - mHistory.printMsgs(); - mHistory.analysePeers(); - mHistory.peerTypeAnalysis(); - - // Incoming Query Analysis. - std::cerr << "Outstanding Query Requests: " << mRemoteQueries.size(); - std::cerr << std::endl; - - mQueryHistory.printMsgs(); -#endif - - mAccount.printStats(std::cerr); -} - -void bdNode::iterationOff() -{ - /* clean up any incoming messages */ - while(mIncomingMsgs.size() > 0) - { - bdNodeNetMsg *msg = mIncomingMsgs.front(); - mIncomingMsgs.pop_front(); - - /* cleanup message */ - delete msg; - } -} - -void bdNode::iteration() -{ -#ifdef DEBUG_NODE_MULTIPEER - std::cerr << "bdNode::iteration() of Peer: "; - mFns->bdPrintNodeId(std::cerr, &mOwnId); - std::cerr << std::endl; -#endif - - /* process incoming msgs */ - while(mIncomingMsgs.size() > 0) - { - bdNodeNetMsg *msg = mIncomingMsgs.front(); - mIncomingMsgs.pop_front(); - - recvPkt(msg->data, msg->mSize, msg->addr); - - /* cleanup message */ - delete msg; - } - - - /* assume that this is called once per second... limit the messages - * in theory, a query can generate up to 10 peers (which will all require a ping!). - * we want to handle all the pings we can... so we don't hold up the process. - * but we also want enough queries to keep things moving. - * so allow up to 90% of messages to be pings. - * - * ignore responses to other peers... as the number is very small generally - * - * The Rate IS NOW DEFINED IN NodeDhtMode. - */ - - int allowedPings = 0.9 * mMaxAllowedMsgs; - int sentMsgs = 0; - int sentPings = 0; - -#define BDNODE_MAX_POTENTIAL_PEERS_MULTIPLIER 5 - - /* Disable Queries if our Ping Queue is too long */ - if (mPotentialPeers.size() > mMaxAllowedMsgs * BDNODE_MAX_POTENTIAL_PEERS_MULTIPLIER) - { -#ifdef DEBUG_NODE_MULTIPEER - std::cerr << "bdNode::iteration() Disabling Queries until PotentialPeer Queue reduced"; - std::cerr << std::endl; -#endif - allowedPings = mMaxAllowedMsgs; - } - - - while((mPotentialPeers.size() > 0) && (sentMsgs < allowedPings)) - { - /* check history ... is we have pinged them already... - * then simulate / pretend we have received a pong, - * and don't bother sending another ping. - */ - - bdId pid = mPotentialPeers.front(); - mPotentialPeers.pop_front(); - - - /* don't send too many queries ... check history first */ -#if 0 -#ifdef USE_HISTORY - if (mHistory.validPeer(&pid)) - { - /* just add as peer */ - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::iteration() Pinging Known Potential Peer : "; - mFns->bdPrintId(std::cerr, &pid); - std::cerr << std::endl; -#endif - - } -#endif -#endif - - /**** TEMP ****/ - - { - send_ping(&pid); - - sentMsgs++; - sentPings++; - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::iteration() Pinging Potential Peer : "; - mFns->bdPrintId(std::cerr, &pid); - std::cerr << std::endl; -#endif - - } - - } - - /* allow each query to send up to one query... until maxMsgs has been reached */ - int sentQueries = mQueryMgr->iterateQueries(mMaxAllowedMsgs-sentMsgs); - sentMsgs += sentQueries; - - -#ifdef DEBUG_NODE_ACTIONS - std::cerr << "bdNode::iteration() maxMsgs: " << maxMsgs << " sentPings: " << sentPings; - std::cerr << " / " << allowedPings; - std::cerr << " sentQueries: " << sentQueries; - std::cerr << std::endl; -#endif - - /* process remote query too */ - processRemoteQuery(); - - std::list peerIds; - std::list::iterator oit; - mNodeSpace.scanOutOfDatePeers(peerIds); - - for(oit = peerIds.begin(); oit != peerIds.end(); oit++) - { - send_ping(&(*oit)); - mAccount.incCounter(BDACCOUNT_MSG_OUTOFDATEPING, true); - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::iteration() Pinging Out-Of-Date Peer: "; - mFns->bdPrintId(std::cerr, &(*oit)); - std::cerr << std::endl; -#endif - } - - // Handle Connection loops. - mConnMgr->tickConnections(); - - mAccount.doStats(); -} - - - -/*************************************************************************************** - *************************************************************************************** - ***************************************************************************************/ - -void bdNode::send_ping(bdId *id) -{ - bdToken transId; - genNewTransId(&transId); - - msgout_ping(id, &transId); -} - - -void bdNode::send_query(bdId *id, bdNodeId *targetNodeId, bool localnet) -{ - /* push out query */ - bdToken transId; - genNewTransId(&transId); - - msgout_find_node(id, &transId, targetNodeId, localnet); - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::send_query() Find Node Req for : "; - mFns->bdPrintId(std::cerr, &id); - std::cerr << " searching for : "; - mFns->bdPrintNodeId(std::cerr, &targetNodeId); - std::cerr << std::endl; -#endif -} - - -void bdNode::send_connect_msg(bdId *id, int msgtype, bdId *srcAddr, bdId *destAddr, int mode, int param, int status) -{ - /* push out query */ - bdToken transId; - genNewTransId(&transId); - - msgout_connect_genmsg(id, &transId, msgtype, srcAddr, destAddr, mode, param, status); - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::send_connect_msg() to: "; - mFns->bdPrintId(std::cerr, &id); - std::cerr << std::endl; -#endif -} - - -void bdNode::checkPotentialPeer(bdId *id, bdId *src) -{ - /* Check BadPeer Filters for Potential Peers too */ - - /* first check the filters */ - if (!mFilterPeers.addrOkay(&(id->addr))) - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::checkPotentialPeer("; - mFns->bdPrintId(std::cerr, id); - std::cerr << ") BAD ADDRESS!!!! SHOULD DISCARD POTENTIAL PEER"; - std::cerr << std::endl; -#endif - - return; - } - - /* is it masquarading? */ - bdFriendEntry entry; - if (mFriendList.findPeerEntry(&(id->id), entry)) - { - struct sockaddr_in knownAddr; - if (entry.addrKnown(&knownAddr)) - { - if (knownAddr.sin_addr.s_addr != id->addr.sin_addr.s_addr) - { -#ifndef DISABLE_BAD_PEER_FILTER - std::cerr << "bdNode::checkPotentialPeer("; - mFns->bdPrintId(std::cerr, id); - std::cerr << ") MASQUERADING AS KNOWN PEER - FLAGGING AS BAD"; - std::cerr << std::endl; - - // Stores in queue for later callback and desemination around the network. - mBadPeerQueue.queuePeer(id, 0); - - mFilterPeers.addPeerToFilter(id->addr, 0); - - std::list filteredIPs; - mFilterPeers.filteredIPs(filteredIPs); - mStore.filterIpList(filteredIPs); - - return; -#endif - } - } - } - - bool isWorthyPeer = mQueryMgr->checkPotentialPeer(id, src); - - if (isWorthyPeer) - { - addPotentialPeer(id, src); - - } - - if (src) // src can be NULL! - { - mConnMgr->addPotentialConnectionProxy(src, id); // CAUTION: Order switched! - } - -} - - -void bdNode::addPotentialPeer(bdId *id, bdId * /*src*/) -{ - mPotentialPeers.push_back(*id); -} - - // virtual so manager can do callback. - // peer flags defined in bdiface.h -void bdNode::addPeer(const bdId *id, uint32_t peerflags) -{ - -#ifdef DEBUG_NODE_ACTIONS - fprintf(stderr, "bdNode::addPeer("); - mFns->bdPrintId(std::cerr, id); - fprintf(stderr, ")\n"); -#endif - - /* first check the filters */ - if (mFilterPeers.checkPeer(id, peerflags)) - { - std::cerr << "bdNode::addPeer("; - mFns->bdPrintId(std::cerr, id); - std::cerr << ", " << std::hex << peerflags << std::dec; - std::cerr << ") FAILED the BAD PEER FILTER!!!! DISCARDING MSG"; - std::cerr << std::endl; - - std::list filteredIPs; - mFilterPeers.filteredIPs(filteredIPs); - mStore.filterIpList(filteredIPs); - - mBadPeerQueue.queuePeer(id, peerflags); - - return; - } - - /* next we check if it is a friend, whitelist etc, and adjust flags */ - bdFriendEntry entry; - - if (mFriendList.findPeerEntry(&(id->id), entry)) - { - /* found! */ - peerflags |= entry.getPeerFlags(); // translates internal into general ones. - - struct sockaddr_in knownAddr; - if (entry.addrKnown(&knownAddr)) - { - if (knownAddr.sin_addr.s_addr != id->addr.sin_addr.s_addr) - { -#ifndef DISABLE_BAD_PEER_FILTER - std::cerr << "bdNode::addPeer("; - mFns->bdPrintId(std::cerr, id); - std::cerr << ", " << std::hex << peerflags << std::dec; - std::cerr << ") MASQUERADING AS KNOWN PEER - FLAGGING AS BAD"; - std::cerr << std::endl; - - - // Stores in queue for later callback and desemination around the network. - mBadPeerQueue.queuePeer(id, peerflags); - - mFilterPeers.addPeerToFilter(id->addr, peerflags); - - std::list filteredIPs; - mFilterPeers.filteredIPs(filteredIPs); - mStore.filterIpList(filteredIPs); - - // DO WE EXPLICITLY NEED TO DO THIS, OR WILL THEY JUST BE DROPPED? - //mNodeSpace.remove_badpeer(id); - //mQueryMgr->remove_badpeer(id); - - // FLAG in NodeSpace (Should be dropped very quickly anyway) - mNodeSpace.flagpeer(id, 0, BITDHT_PEER_EXFLAG_BADPEER); - - return; -#endif - } - } - } - - mQueryMgr->addPeer(id, peerflags); - mNodeSpace.add_peer(id, peerflags); - - bdPeer peer; - peer.mPeerId = *id; - peer.mPeerFlags = peerflags; - peer.mLastRecvTime = time(NULL); - mStore.addStore(&peer); - - // Finally we pass to connections for them to use. - mConnMgr->updatePotentialConnectionProxy(id, peerflags); - - -//#define DISPLAY_BITDHTNODES 1 -#ifdef DISPLAY_BITDHTNODES - /* TEMP to extract IDS for BloomFilter */ - if (peerflags & BITDHT_PEER_STATUS_DHT_ENGINE) - { - std::cerr << "bdNode::addPeer() FOUND BITDHT PEER"; - std::cerr << std::endl; - mFns->bdPrintNodeId(std::cerr, &(id->id)); - std::cerr << std::endl; - } -#endif -} - -/************************************ Process Remote Query *************************/ - -/* increased the allowed processing rate from 1/sec => 5/sec */ -void bdNode::processRemoteQuery() -{ - int nProcessed = 0; - time_t oldTS = time(NULL) - BITDHT_MAX_REMOTE_QUERY_AGE; - while(nProcessed < MAX_REMOTE_PROCESS_PER_CYCLE) - { - /* extra exit clause */ - if (mRemoteQueries.size() < 1) - { -#ifdef USE_HISTORY - if (nProcessed) - { - mQueryHistory.cleanupOldMsgs(); - } -#endif - return; - } - - bdRemoteQuery &query = mRemoteQueries.front(); - - // filtering. - bool badPeer = false; -#ifdef USE_HISTORY - // store result in badPeer to activate the filtering. - mQueryHistory.addIncomingQuery(query.mQueryTS, &(query.mId), &(query.mQuery)); -#endif - - /* discard older ones (stops queue getting overloaded) */ - if ((query.mQueryTS > oldTS) && (!badPeer)) - { - /* recent enough to process! */ - nProcessed++; - - switch(query.mQueryType) - { - case BD_QUERY_NEIGHBOURS: - case BD_QUERY_LOCALNET: - { - /* search bdSpace for neighbours */ - - std::list nearList; - std::multimap nearest; - std::multimap::iterator it; - - if (query.mQueryType == BD_QUERY_LOCALNET) - { - std::list excludeList; - mNodeSpace.find_nearest_nodes_with_flags(&(query.mQuery), - BITDHT_QUERY_NEIGHBOUR_PEERS, - excludeList, nearest, BITDHT_PEER_STATUS_DHT_APPL); - } - else - { - if (mRelayMode == BITDHT_RELAYS_SERVER) - { - std::list excludeList; - mNodeSpace.find_nearest_nodes_with_flags(&(query.mQuery), - BITDHT_QUERY_NEIGHBOUR_PEERS, - excludeList, nearest, BITDHT_PEER_STATUS_DHT_RELAY_SERVER); - } - else - { - mNodeSpace.find_nearest_nodes(&(query.mQuery), BITDHT_QUERY_NEIGHBOUR_PEERS, nearest); - } - } - - for(it = nearest.begin(); it != nearest.end(); it++) - { - nearList.push_back(it->second); - } - msgout_reply_find_node(&(query.mId), &(query.mTransId), nearList); -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::processRemoteQuery() Reply to Find Node: "; - mFns->bdPrintId(std::cerr, &(query.mId)); - std::cerr << " searching for : "; - mFns->bdPrintNodeId(std::cerr, &(query.mQuery)); - std::cerr << ", found " << nearest.size() << " nodes "; - std::cerr << std::endl; -#endif - - break; - } - case BD_QUERY_HASH: - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::processRemoteQuery() Reply to Query Node: "; - mFns->bdPrintId(std::cerr, &(query.mId)); - std::cerr << " TODO"; - std::cerr << std::endl; -#endif - - /* TODO */ - /* for now drop */ - /* unprocess! */ - nProcessed--; - break; - } - default: - { - /* drop */ - /* unprocess! */ - nProcessed--; - break; - } - } - - - - } - else - { - if (badPeer) - { - std::cerr << "bdNode::processRemoteQuery() Query from BadPeer: Discarding: "; - } -#ifdef DEBUG_NODE_MSGS - else - { - std::cerr << "bdNode::processRemoteQuery() Query Too Old: Discarding: "; - } -#endif -#ifdef DEBUG_NODE_MSGS - mFns->bdPrintId(std::cerr, &(query.mId)); - std::cerr << std::endl; -#endif - } - - mRemoteQueries.pop_front(); - - } - -#ifdef USE_HISTORY - mQueryHistory.cleanupOldMsgs(); -#endif -} - - - - - -/************************************ Message Buffering ****************************/ - - /* interaction with outside world */ -int bdNode::outgoingMsg(struct sockaddr_in *addr, char *msg, int *len) -{ - if (mOutgoingMsgs.size() > 0) - { - bdNodeNetMsg *bdmsg = mOutgoingMsgs.front(); - //bdmsg->print(std::cerr); - mOutgoingMsgs.pop_front(); - //bdmsg->print(std::cerr); - - /* truncate if necessary */ - if (bdmsg->mSize < *len) - { - //std::cerr << "bdNode::outgoingMsg space(" << *len << ") msgsize(" << bdmsg->mSize << ")"; - //std::cerr << std::endl; - *len = bdmsg->mSize; - } - else - { - //std::cerr << "bdNode::outgoingMsg space(" << *len << ") small - trunc from: " - //<< bdmsg->mSize; - //std::cerr << std::endl; - } - - - memcpy(msg, bdmsg->data, *len); - *addr = bdmsg->addr; - - //bdmsg->print(std::cerr); - - delete bdmsg; - return 1; - } - return 0; -} - -void bdNode::incomingMsg(struct sockaddr_in *addr, char *msg, int len) -{ - /* check against the filter */ - if (mFilterPeers.addrOkay(addr)) - { - bdNodeNetMsg *bdmsg = new bdNodeNetMsg(msg, len, addr); - mIncomingMsgs.push_back(bdmsg); - } -#ifdef DEBUG_NODE_MSGOUT - else - { - std::cerr << "bdNode::incomingMsg() Incoming Packet Filtered"; - std::cerr << std::endl; - } -#endif -} - -/************************************ Message Handling *****************************/ - -/* Outgoing Messages */ - -void bdNode::msgout_ping(bdId *id, bdToken *transId) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_ping() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - // THIS IS CRASHING HISTORY. - // LIKELY ID is not always valid! - // Either PotentialPeers or Out-Of-Date Peers. - //registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_PING); - - bdId dupId(*id); - registerOutgoingMsg(&dupId, transId, BITDHT_MSG_TYPE_PING, NULL); - - /* generate message, send to udp */ - bdToken vid; - uint32_t vlen = BITDHT_TOKEN_MAX_LEN; - if (mDhtVersion.size() < vlen) - { - vlen = mDhtVersion.size(); - } - memcpy(vid.data, mDhtVersion.c_str(), vlen); - vid.len = vlen; - - /* create string */ - char msg[10240]; - int avail = 10240; - - int blen = bitdht_create_ping_msg(transId, &(mOwnId), &vid, msg, avail-1); - sendPkt(msg, blen, id->addr); - - mAccount.incCounter(BDACCOUNT_MSG_PING, true); - -} - - -void bdNode::msgout_pong(bdId *id, bdToken *transId) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_pong() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " Version: " << version; - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_PONG, NULL); - - /* generate message, send to udp */ - bdToken vid; - uint32_t vlen = BITDHT_TOKEN_MAX_LEN; - if (mDhtVersion.size() < vlen) - { - vlen = mDhtVersion.size(); - } - memcpy(vid.data, mDhtVersion.c_str(), vlen); - vid.len = vlen; - - char msg[10240]; - int avail = 10240; - - int blen = bitdht_response_ping_msg(transId, &(mOwnId), &vid, msg, avail-1); - - sendPkt(msg, blen, id->addr); - - mAccount.incCounter(BDACCOUNT_MSG_PONG, true); - -} - - -void bdNode::msgout_find_node(bdId *id, bdToken *transId, bdNodeId *query, bool localnet) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_find_node() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Query: "; - mFns->bdPrintNodeId(std::cerr, query); - std::cerr << std::endl; -#endif - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_FIND_NODE, query); - - - - char msg[10240]; - int avail = 10240; - - int blen = bitdht_find_node_msg(transId, &(mOwnId), query, localnet, msg, avail-1); - - sendPkt(msg, blen, id->addr); - - mAccount.incCounter(BDACCOUNT_MSG_QUERYNODE, true); - -} - -void bdNode::msgout_reply_find_node(bdId *id, bdToken *transId, std::list &peers) -{ - char msg[10240]; - int avail = 10240; - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_REPLY_NODE, NULL); - - mAccount.incCounter(BDACCOUNT_MSG_REPLYFINDNODE, true); - - int blen = bitdht_resp_node_msg(transId, &(mOwnId), peers, msg, avail-1); - - sendPkt(msg, blen, id->addr); - -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_reply_find_node() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Peers:"; - std::list::iterator it; - for(it = peers.begin(); it != peers.end(); it++) - { - std::cerr << " "; - mFns->bdPrintId(std::cerr, &(*it)); - } - std::cerr << std::endl; -#endif -} - -/***************** - * SECOND HALF - * - *****/ - -void bdNode::msgout_get_hash(bdId *id, bdToken *transId, bdNodeId *info_hash) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_get_hash() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " InfoHash: "; - mFns->bdPrintNodeId(std::cerr, info_hash); - std::cerr << std::endl; -#endif - - char msg[10240]; - int avail = 10240; - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_GET_HASH, info_hash); - - - int blen = bitdht_get_peers_msg(transId, &(mOwnId), info_hash, msg, avail-1); - - sendPkt(msg, blen, id->addr); - - mAccount.incCounter(BDACCOUNT_MSG_QUERYHASH, true); - -} - -void bdNode::msgout_reply_hash(bdId *id, bdToken *transId, bdToken *token, std::list &values) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_reply_hash() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Token: "; - bdPrintToken(std::cerr, token); - - std::cerr << " Peers: "; - std::list::iterator it; - for(it = values.begin(); it != values.end(); it++) - { - std::cerr << " "; - bdPrintCompactPeerId(std::cerr, *it); - } - std::cerr << std::endl; -#endif - - char msg[10240]; - int avail = 10240; - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_REPLY_HASH, NULL); - - int blen = bitdht_peers_reply_hash_msg(transId, &(mOwnId), token, values, msg, avail-1); - - sendPkt(msg, blen, id->addr); - - mAccount.incCounter(BDACCOUNT_MSG_REPLYQUERYHASH, true); - -} - -void bdNode::msgout_reply_nearest(bdId *id, bdToken *transId, bdToken *token, std::list &nodes) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_reply_nearest() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Token: "; - bdPrintToken(std::cerr, token); - std::cerr << " Nodes:"; - - std::list::iterator it; - for(it = nodes.begin(); it != nodes.end(); it++) - { - std::cerr << " "; - mFns->bdPrintId(std::cerr, &(*it)); - } - std::cerr << std::endl; -#endif - - char msg[10240]; - int avail = 10240; - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_REPLY_NEAR, NULL); - - - - int blen = bitdht_peers_reply_closest_msg(transId, &(mOwnId), token, nodes, msg, avail-1); - - sendPkt(msg, blen, id->addr); - mAccount.incCounter(BDACCOUNT_MSG_REPLYQUERYHASH, true); - - -} - -void bdNode::msgout_post_hash(bdId *id, bdToken *transId, bdNodeId *info_hash, uint32_t port, bdToken *token) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_post_hash() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Info_Hash: "; - mFns->bdPrintNodeId(std::cerr, info_hash); - std::cerr << " Port: " << port; - std::cerr << " Token: "; - bdPrintToken(std::cerr, token); - std::cerr << std::endl; -#endif - - char msg[10240]; - int avail = 10240; - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_POST_HASH, info_hash); - - - int blen = bitdht_announce_peers_msg(transId,&(mOwnId),info_hash,port,token,msg,avail-1); - - sendPkt(msg, blen, id->addr); - mAccount.incCounter(BDACCOUNT_MSG_POSTHASH, true); - - -} - -void bdNode::msgout_reply_post(bdId *id, bdToken *transId) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_reply_post() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - /* generate message, send to udp */ - char msg[10240]; - int avail = 10240; - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_REPLY_POST, NULL); - - int blen = bitdht_reply_announce_msg(transId, &(mOwnId), msg, avail-1); - - sendPkt(msg, blen, id->addr); - mAccount.incCounter(BDACCOUNT_MSG_REPLYPOSTHASH, true); - -} - - -void bdNode::sendPkt(char *msg, int len, struct sockaddr_in addr) -{ - //fprintf(stderr, "bdNode::sendPkt(%d) to %s:%d\n", - // len, inet_ntoa(addr.sin_addr), htons(addr.sin_port)); - - /* filter outgoing packets */ - if (mFilterPeers.addrOkay(&addr)) - { - bdNodeNetMsg *bdmsg = new bdNodeNetMsg(msg, len, &addr); - //bdmsg->print(std::cerr); - mOutgoingMsgs.push_back(bdmsg); - //bdmsg->print(std::cerr); - } - else - { - std::cerr << "bdNode::sendPkt() Outgoing Packet Filtered"; - std::cerr << std::endl; - } - - return; -} - - -/********************* Incoming Messages *************************/ -/* - * These functions are holding up udp queue -> so quickly - * parse message, and get on with it! - */ - -void bdNode::recvPkt(char *msg, int len, struct sockaddr_in addr) -{ -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() msg[" << len << "] = "; - for(int i = 0; i < len; i++) - { - if ((msg[i] > 31) && (msg[i] < 127)) - { - std::cerr << msg[i]; - } - else - { - std::cerr << "[" << (int) msg[i] << "]"; - } - } - std::cerr << std::endl; -#endif - - /* convert to a be_node */ - be_node *node = be_decoden(msg, len); - if (!node) - { - /* invalid decode */ -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Failure to decode. Dropping Msg"; - std::cerr << std::endl; - std::cerr << "message length: " << len; - std::cerr << std::endl; - std::cerr << "msg[] = "; - for(int i = 0; i < len; i++) - { - if ((msg[i] > 31) && (msg[i] < 127)) - { - std::cerr << msg[i]; - } - else - { - std::cerr << "[" << (int) msg[i] << "]"; - } - } - std::cerr << std::endl; -#endif - return; - } - - /* find message type */ - uint32_t beType = beMsgType(node); - bool beQuery = (BE_Y_Q == beMsgGetY(node)); - - if (!beType) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Invalid Message Type. Dropping Msg"; - std::cerr << std::endl; -#endif - /* invalid message */ - be_free(node); - return; - } - - /************************* handle token (all) **************************/ - be_node *be_transId = beMsgGetDictNode(node, "t"); - bdToken transId; - if (be_transId) - { - beMsgGetToken(be_transId, transId); - } - else - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() TransId Failure. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /************************* handle data (all) **************************/ - - /* extract common features */ - char dictkey[2] = "r"; - if (beQuery) - { - dictkey[0] = 'a'; - } - - be_node *be_data = beMsgGetDictNode(node, dictkey); - if (!be_data) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Data Body. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /************************** handle id (all) ***************************/ - be_node *be_id = beMsgGetDictNode(be_data, "id"); - bdNodeId id; - if(!be_id || !beMsgGetNodeId(be_id, id)) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Peer Id. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /************************ handle version (optional:pong) **************/ - be_node *be_version = NULL; - bdToken versionId; - if ((beType == BITDHT_MSG_TYPE_PONG) || (beType == BITDHT_MSG_TYPE_PING)) - { - be_version = beMsgGetDictNode(node, "v"); - if (!be_version) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() NOTE: PONG missing Optional Version."; - std::cerr << std::endl; -#endif - } - } - - if (be_version) - { - beMsgGetToken(be_version, versionId); - } - - /************************ handle options (optional:bitdht extension) **************/ - be_node *be_options = beMsgGetDictNode(node, "o"); - bool localnet = false; - if (be_options) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Found Options Node, localnet"; - std::cerr << std::endl; -#endif - localnet = true; - } - - /*********** handle target (query) or info_hash (get_hash) ************/ - bdNodeId target_info_hash; - be_node *be_target = NULL; - if (beType == BITDHT_MSG_TYPE_FIND_NODE) - { - be_target = beMsgGetDictNode(be_data, "target"); - if (!be_target) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Target / Info_Hash. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - } - else if ((beType == BITDHT_MSG_TYPE_GET_HASH) || - (beType == BITDHT_MSG_TYPE_POST_HASH)) - { - be_target = beMsgGetDictNode(be_data, "info_hash"); - if (!be_target) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Target / Info_Hash. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - } - - if (be_target) - { - beMsgGetNodeId(be_target, target_info_hash); - } - - /*********** handle nodes (reply_query or reply_near) *****************/ - std::list nodes; - be_node *be_nodes = NULL; - if ((beType == BITDHT_MSG_TYPE_REPLY_NODE) || - (beType == BITDHT_MSG_TYPE_REPLY_NEAR)) - { - be_nodes = beMsgGetDictNode(be_data, "nodes"); - if (!be_nodes) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Nodes. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - } - - if (be_nodes) - { - beMsgGetListBdIds(be_nodes, nodes); - } - - /******************* handle values (reply_hash) ***********************/ - std::list values; - be_node *be_values = NULL; - if (beType == BITDHT_MSG_TYPE_REPLY_HASH) - { - be_values = beMsgGetDictNode(be_data, "values"); - if (!be_values) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Values. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - } - - if (be_values) - { - beMsgGetListStrings(be_values, values); - } - - /************ handle token (reply_hash, reply_near, post hash) ********/ - bdToken token; - be_node *be_token = NULL; - if ((beType == BITDHT_MSG_TYPE_REPLY_HASH) || - (beType == BITDHT_MSG_TYPE_REPLY_NEAR) || - (beType == BITDHT_MSG_TYPE_POST_HASH)) - { - be_token = beMsgGetDictNode(be_data, "token"); - if (!be_token) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Token. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - } - - if (be_token) - { - beMsgGetToken(be_transId, transId); - } - - /****************** handle port (post hash) ***************************/ - uint32_t port; - be_node *be_port = NULL; - if (beType == BITDHT_MSG_TYPE_POST_HASH) - { - be_port = beMsgGetDictNode(be_data, "port"); - if (!be_port) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() POST_HASH Missing Port. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - } - - if (be_port) - { - beMsgGetUInt32(be_port, &port); - } - - /****************** handle Connect (lots) ***************************/ - bdId connSrcAddr; - bdId connDestAddr; - uint32_t connMode; - uint32_t connParam = 0; - uint32_t connStatus; - uint32_t connType; - - be_node *be_ConnSrcAddr = NULL; - be_node *be_ConnDestAddr = NULL; - be_node *be_ConnMode = NULL; - be_node *be_ConnParam = NULL; - be_node *be_ConnStatus = NULL; - be_node *be_ConnType = NULL; - if (beType == BITDHT_MSG_TYPE_CONNECT) - { - /* SrcAddr */ - be_ConnSrcAddr = beMsgGetDictNode(be_data, "src"); - if (!be_ConnSrcAddr) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() CONNECT Missing SrcAddr. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /* DestAddr */ - be_ConnDestAddr = beMsgGetDictNode(be_data, "dest"); - if (!be_ConnDestAddr) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() CONNECT Missing DestAddr. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /* Mode */ - be_ConnMode = beMsgGetDictNode(be_data, "mode"); - if (!be_ConnMode) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() CONNECT Missing Mode. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /* Param */ - be_ConnParam = beMsgGetDictNode(be_data, "param"); - if (!be_ConnParam) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() CONNECT Missing Param. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /* Status */ - be_ConnStatus = beMsgGetDictNode(be_data, "status"); - if (!be_ConnStatus) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() CONNECT Missing Status. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /* Type */ - be_ConnType = beMsgGetDictNode(be_data, "type"); - if (!be_ConnType) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() CONNECT Missing Type. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - } - - if (be_ConnSrcAddr) - { - beMsgGetBdId(be_ConnSrcAddr, connSrcAddr); - } - - if (be_ConnDestAddr) - { - beMsgGetBdId(be_ConnDestAddr, connDestAddr); - } - - if (be_ConnMode) - { - beMsgGetUInt32(be_ConnMode, &connMode); - } - - if (be_ConnParam) - { - beMsgGetUInt32(be_ConnParam, &connParam); - } - - if (be_ConnStatus) - { - beMsgGetUInt32(be_ConnStatus, &connStatus); - } - - if (be_ConnType) - { - beMsgGetUInt32(be_ConnType, &connType); - } - - - - /****************** Bits Parsed Ok. Process Msg ***********************/ - /* Construct Source Id */ - bdId srcId(id, addr); - - if (be_target) - { - registerIncomingMsg(&srcId, &transId, beType, &target_info_hash); - } - else - { - registerIncomingMsg(&srcId, &transId, beType, NULL); - } - - switch(beType) - { - case BITDHT_MSG_TYPE_PING: /* a: id, transId */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Responding to Ping : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - if (be_version) - { - msgin_ping(&srcId, &transId, &versionId); - } - else - { - msgin_ping(&srcId, &transId, NULL); - } - break; - } - case BITDHT_MSG_TYPE_PONG: /* r: id, transId */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Received Pong from : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - if (be_version) - { - msgin_pong(&srcId, &transId, &versionId); - } - else - { - msgin_pong(&srcId, &transId, NULL); - } - - break; - } - case BITDHT_MSG_TYPE_FIND_NODE: /* a: id, transId, target */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Req Find Node from : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << " Looking for: "; - mFns->bdPrintNodeId(std::cerr, &target_info_hash); - std::cerr << std::endl; -#endif - msgin_find_node(&srcId, &transId, &target_info_hash, localnet); - break; - } - case BITDHT_MSG_TYPE_REPLY_NODE: /* r: id, transId, nodes */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Received Reply Node from : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - msgin_reply_find_node(&srcId, &transId, nodes); - break; - } - case BITDHT_MSG_TYPE_GET_HASH: /* a: id, transId, info_hash */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Received SearchHash : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << " for Hash: "; - mFns->bdPrintNodeId(std::cerr, &target_info_hash); - std::cerr << std::endl; -#endif - msgin_get_hash(&srcId, &transId, &target_info_hash); - break; - } - case BITDHT_MSG_TYPE_REPLY_HASH: /* r: id, transId, token, values */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Received Reply Hash : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - msgin_reply_hash(&srcId, &transId, &token, values); - break; - } - case BITDHT_MSG_TYPE_REPLY_NEAR: /* r: id, transId, token, nodes */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Received Reply Near : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - msgin_reply_nearest(&srcId, &transId, &token, nodes); - break; - } - case BITDHT_MSG_TYPE_POST_HASH: /* a: id, transId, info_hash, port, token */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Post Hash from : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << " to post: "; - mFns->bdPrintNodeId(std::cerr, &target_info_hash); - std::cerr << " with port: " << port; - std::cerr << std::endl; -#endif - msgin_post_hash(&srcId, &transId, &target_info_hash, port, &token); - break; - } - case BITDHT_MSG_TYPE_REPLY_POST: /* r: id, transId */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Reply Post from: "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - msgin_reply_post(&srcId, &transId); - break; - } - case BITDHT_MSG_TYPE_CONNECT: /* a: id, src, dest, mode, status, type */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() ConnectMsg from: "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - msgin_connect_genmsg(&srcId, &transId, connType, - &connSrcAddr, &connDestAddr, - connMode, connParam, connStatus); - break; - } - default: - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() ERROR"; - std::cerr << std::endl; -#endif - /* ERROR */ - break; - } - } - - be_free(node); - return; -} - -/* Input: id, token. - * Response: pong(id, token) - */ - -void bdNode::msgin_ping(bdId *id, bdToken *transId, bdToken *versionId) -{ -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_ping() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - mAccount.incCounter(BDACCOUNT_MSG_PING, false); - - /* peer is alive */ - uint32_t peerflags = BITDHT_PEER_STATUS_RECV_PING; /* no id typically, so cant get version */ - peerflags |= parseVersion(versionId); - addPeer(id, peerflags); - - /* reply */ - msgout_pong(id, transId); - -} - -/* Input: id, token, (+optional version) - * Response: store peer. - */ - -void bdNode::msgin_pong(bdId *id, bdToken *transId, bdToken *versionId) -{ -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_pong() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " Version: TODO!"; // << version; - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#else - (void) transId; -#endif - - uint32_t peerflags = BITDHT_PEER_STATUS_RECV_PONG; - peerflags |= parseVersion(versionId); - - mAccount.incCounter(BDACCOUNT_MSG_PONG, false); - addPeer(id, peerflags); -} - - -uint32_t bdNode::parseVersion(bdToken *versionId) -{ - /* recv pong, and peer is alive. add to DHT */ - //uint32_t vId = 0; // TODO XXX convertBdVersionToVID(versionId); - - /* calculate version match with peer */ - bool sameDhtEngine = false; - bool sameDhtVersion = false; - bool sameAppl = false; - bool sameApplVersion = false; - - if (versionId) - { - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::parseVersion() Peer Version: "; - for(int i = 0; i < versionId->len; i++) - { - std::cerr << versionId->data[i]; - } - std::cerr << std::endl; -#endif - -#ifdef USE_HISTORY - std::string version; - for(int i = 0; i < versionId->len; i++) - { - if (isalnum(versionId->data[i])) - { - version += versionId->data[i]; - } - else - { - version += 'X'; - } - } - mHistory.setPeerType(id, version); -#endif - - /* check two bytes */ - if ((versionId->len >= 2) && (mDhtVersion.size() >= 2) && - (versionId->data[0] == mDhtVersion[0]) && (versionId->data[1] == mDhtVersion[1])) - { - sameDhtEngine = true; - } - - /* check two bytes. - * Due to Old Versions not having this field, we need to check that they are numbers. - * We have a Major version, and minor version.... - * This flag is set if Major is same, and minor is greater or equal to our version. - */ - if ((versionId->len >= 4) && (mDhtVersion.size() >= 4)) - { - if ((isdigit(versionId->data[2]) && isdigit(versionId->data[3])) && - (versionId->data[2] == mDhtVersion[2]) && (versionId->data[3] >= mDhtVersion[3])) - { - sameDhtVersion = true; - } - } - - if ((sameDhtVersion) && (!sameDhtEngine)) - { - sameDhtVersion = false; -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::parseVersion() STRANGE Peer Version: "; - for(uint32_t i = 0; i < versionId->len; i++) - { - std::cerr << versionId->data[i]; - } - std::cerr << std::endl; -#endif - } - - /* check two bytes */ - if ((versionId->len >= 6) && (mDhtVersion.size() >= 6) && - (versionId->data[4] == mDhtVersion[4]) && (versionId->data[5] == mDhtVersion[5])) - { - sameAppl = true; - } - - - /* check two bytes */ - if ((versionId->len >= 8) && (mDhtVersion.size() >= 8)) - { - if ((isdigit(versionId->data[6]) && isdigit(versionId->data[7])) && - (versionId->data[6] == mDhtVersion[6]) && (versionId->data[7] >= mDhtVersion[7])) - { - sameApplVersion = true; - } - } - } - else - { - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::parseVersion() No Version"; - std::cerr << std::endl; -#endif - } - - uint32_t peerflags = BITDHT_PEER_STATUS_RECV_PONG; /* should have id too */ - if (sameDhtEngine) - { - peerflags |= BITDHT_PEER_STATUS_DHT_ENGINE; - } - if (sameDhtVersion) - { - peerflags |= BITDHT_PEER_STATUS_DHT_ENGINE_VERSION; - } - if (sameAppl) - { - peerflags |= BITDHT_PEER_STATUS_DHT_APPL; - } - if (sameApplVersion) - { - peerflags |= BITDHT_PEER_STATUS_DHT_APPL_VERSION; - } - return peerflags; -} - - - -/* Input: id, token, queryId */ - -void bdNode::msgin_find_node(bdId *id, bdToken *transId, bdNodeId *query, bool localnet) -{ -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_find_node() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Query: "; - mFns->bdPrintNodeId(std::cerr, query); - std::cerr << std::endl; -#endif - - mAccount.incCounter(BDACCOUNT_MSG_QUERYNODE, false); - - - /* store query... */ - uint32_t query_type = BD_QUERY_NEIGHBOURS; - if (localnet) - { - query_type = BD_QUERY_LOCALNET; - } - queueQuery(id, query, transId, query_type); - - - uint32_t peerflags = 0; /* no id, and no help! */ - addPeer(id, peerflags); -} - -void bdNode::msgin_reply_find_node(bdId *id, bdToken *transId, std::list &nodes) -{ - std::list::iterator it; - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::msgin_reply_find_node() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Peers:"; - for(it = nodes.begin(); it != nodes.end(); it++) - { - std::cerr << " "; - mFns->bdPrintId(std::cerr, &(*it)); - } - std::cerr << std::endl; -#else - (void) transId; -#endif - - mAccount.incCounter(BDACCOUNT_MSG_REPLYFINDNODE, false); - - /* add neighbours to the potential list */ - for(it = nodes.begin(); it != nodes.end(); it++) - { - checkPotentialPeer(&(*it), id); - } - - /* received reply - so peer must be good */ - uint32_t peerflags = BITDHT_PEER_STATUS_RECV_NODES; /* no id ;( */ - addPeer(id, peerflags); -} - -/********* THIS IS THE SECOND STAGE - * - */ - -void bdNode::msgin_get_hash(bdId *id, bdToken *transId, bdNodeId *info_hash) -{ - - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_get_hash() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " InfoHash: "; - mFns->bdPrintNodeId(std::cerr, info_hash); - std::cerr << std::endl; -#endif - - - mAccount.incCounter(BDACCOUNT_MSG_QUERYHASH, false); - - /* generate message, send to udp */ - queueQuery(id, info_hash, transId, BD_QUERY_HASH); - -} - -void bdNode::msgin_reply_hash(bdId *id, bdToken *transId, bdToken *token, std::list &values) -{ - mAccount.incCounter(BDACCOUNT_MSG_REPLYQUERYHASH, false); - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_reply_hash() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Token: "; - bdPrintToken(std::cerr, token); - - std::cerr << " Peers: "; - std::list::iterator it; - for(it = values.begin(); it != values.end(); it++) - { - std::cerr << " "; - bdPrintCompactPeerId(std::cerr, *it); - } - std::cerr << std::endl; -#else - (void) id; - (void) transId; - (void) token; - (void) values; -#endif -} - -void bdNode::msgin_reply_nearest(bdId *id, bdToken *transId, bdToken *token, std::list &nodes) -{ - mAccount.incCounter(BDACCOUNT_MSG_REPLYQUERYHASH, false); - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_reply_nearest() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Token: "; - bdPrintToken(std::cerr, token); - std::cerr << " Nodes:"; - - std::list::iterator it; - for(it = nodes.begin(); it != nodes.end(); it++) - { - std::cerr << " "; - mFns->bdPrintId(std::cerr, &(*it)); - } - std::cerr << std::endl; -#else - (void) id; - (void) transId; - (void) token; - (void) nodes; -#endif -} - - - -void bdNode::msgin_post_hash(bdId *id, bdToken *transId, bdNodeId *info_hash, uint32_t port, bdToken *token) -{ - - mAccount.incCounter(BDACCOUNT_MSG_POSTHASH, false); - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_post_hash() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Info_Hash: "; - mFns->bdPrintNodeId(std::cerr, info_hash); - std::cerr << " Port: " << port; - std::cerr << " Token: "; - bdPrintToken(std::cerr, token); - std::cerr << std::endl; -#else - (void) id; - (void) transId; - (void) info_hash; - (void) port; - (void) token; -#endif - -} - - -void bdNode::msgin_reply_post(bdId *id, bdToken *transId) -{ - /* generate message, send to udp */ - mAccount.incCounter(BDACCOUNT_MSG_REPLYPOSTHASH, false); - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_reply_post() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#else - (void) id; - (void) transId; -#endif -} - - - -/************************************************************************************************************ -******************************************** Message Interface ********************************************** -************************************************************************************************************/ - -/* Outgoing Messages */ -std::string getConnectMsgType(int msgtype) -{ - switch(msgtype) - { - case BITDHT_MSG_TYPE_CONNECT_REQUEST: - return "ConnectRequest"; - break; - case BITDHT_MSG_TYPE_CONNECT_REPLY: - return "ConnectReply"; - break; - case BITDHT_MSG_TYPE_CONNECT_START: - return "ConnectStart"; - break; - case BITDHT_MSG_TYPE_CONNECT_ACK: - return "ConnectAck"; - break; - default: - return "ConnectUnknown"; - break; - } -} - -void bdNode::msgout_connect_genmsg(bdId *id, bdToken *transId, int msgtype, bdId *srcAddr, bdId *destAddr, int mode, int param, int status) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdConnectManager::msgout_connect_genmsg() Type: " << getConnectMsgType(msgtype); - std::cerr << " TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " SrcAddr: "; - mFns->bdPrintId(std::cerr, srcAddr); - std::cerr << " DestAddr: "; - mFns->bdPrintId(std::cerr, destAddr); - std::cerr << " Mode: " << mode; - std::cerr << " Param: " << param; - std::cerr << " Status: " << status; - std::cerr << std::endl; -#endif - - switch(msgtype) - { - default: - case BITDHT_MSG_TYPE_CONNECT_REQUEST: - mAccount.incCounter(BDACCOUNT_MSG_CONNECTREQUEST, true); - break; - case BITDHT_MSG_TYPE_CONNECT_REPLY: - mAccount.incCounter(BDACCOUNT_MSG_CONNECTREPLY, true); - break; - case BITDHT_MSG_TYPE_CONNECT_START: - mAccount.incCounter(BDACCOUNT_MSG_CONNECTSTART, true); - break; - case BITDHT_MSG_TYPE_CONNECT_ACK: - mAccount.incCounter(BDACCOUNT_MSG_CONNECTACK, true); - break; - } - - registerOutgoingMsg(id, transId, msgtype, NULL); - - /* create string */ - char msg[10240]; - int avail = 10240; - - int blen = bitdht_connect_genmsg(transId, &(mOwnId), msgtype, srcAddr, destAddr, mode, param, status, msg, avail-1); - sendPkt(msg, blen, id->addr); -} - - -void bdNode::msgin_connect_genmsg(bdId *id, bdToken *transId, int msgtype, - bdId *srcAddr, bdId *destAddr, int mode, int param, int status) -{ - std::list::iterator it; - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdConnectManager::msgin_connect_genmsg() Type: " << getConnectMsgType(msgtype); - std::cerr << " TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " SrcAddr: "; - mFns->bdPrintId(std::cerr, srcAddr); - std::cerr << " DestAddr: "; - mFns->bdPrintId(std::cerr, destAddr); - std::cerr << " Mode: " << mode; - std::cerr << " Param: " << param; - std::cerr << " Status: " << status; - std::cerr << std::endl; -#else - (void) transId; -#endif - - /* switch to actual work functions */ - uint32_t peerflags = 0; - switch(msgtype) - { - case BITDHT_MSG_TYPE_CONNECT_REQUEST: - peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; - mAccount.incCounter(BDACCOUNT_MSG_CONNECTREQUEST, false); - - - mConnMgr->recvedConnectionRequest(id, srcAddr, destAddr, mode, param); - - break; - case BITDHT_MSG_TYPE_CONNECT_REPLY: - peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; - mAccount.incCounter(BDACCOUNT_MSG_CONNECTREPLY, false); - - mConnMgr->recvedConnectionReply(id, srcAddr, destAddr, mode, param, status); - - break; - case BITDHT_MSG_TYPE_CONNECT_START: - peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; - mAccount.incCounter(BDACCOUNT_MSG_CONNECTSTART, false); - - mConnMgr->recvedConnectionStart(id, srcAddr, destAddr, mode, param); - - break; - case BITDHT_MSG_TYPE_CONNECT_ACK: - peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; - mAccount.incCounter(BDACCOUNT_MSG_CONNECTACK, false); - - mConnMgr->recvedConnectionAck(id, srcAddr, destAddr, mode); - - break; - default: - break; - } - - /* received message - so peer must be good */ - addPeer(id, peerflags); - -} - - - - - - - - - - - -/****************** Other Functions ******************/ - -void bdNode::genNewToken(bdToken *token) -{ -#ifdef DEBUG_NODE_ACTIONS - fprintf(stderr, "bdNode::genNewToken()"); - fprintf(stderr, ")\n"); -#endif - - // XXX is this a good way to do it? - // Variable length, from 4 chars up to lots... 10? - // leave for the moment, but fix. - std::string num; - bd_sprintf(num, "%04lx", bdRandom::random_u32()); - int len = num.size(); - if (len > BITDHT_TOKEN_MAX_LEN) - len = BITDHT_TOKEN_MAX_LEN; - - for(int i = 0; i < len; i++) - { - token->data[i] = num[i]; - } - token->len = len; - -} - -uint32_t transIdCounter = 0; -void bdNode::genNewTransId(bdToken *token) -{ - /* generate message, send to udp */ -#ifdef DEBUG_NODE_ACTIONS - fprintf(stderr, "bdNode::genNewTransId()"); - fprintf(stderr, ")\n"); -#endif - - std::string num; - bd_sprintf(num, "%02lx", transIdCounter++); - int len = num.size(); - if (len > BITDHT_TOKEN_MAX_LEN) - len = BITDHT_TOKEN_MAX_LEN; - - for(int i = 0; i < len; i++) - { - token->data[i] = num[i]; - } - token->len = len; -} - - -/* Store Remote Query for processing */ -int bdNode::queueQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type) -{ -#ifdef DEBUG_NODE_ACTIONS - std::cerr << "bdnode::queueQuery()" << std::endl; -#endif - - mRemoteQueries.push_back(bdRemoteQuery(id, query, transId, query_type)); - - return 1; -} - -/*************** Register Transaction Ids *************/ - -void bdNode::registerOutgoingMsg(bdId *id, bdToken *transId, uint32_t msgType, bdNodeId *aboutId) -{ - -#ifdef DEBUG_MSG_CHECKS - std::cerr << "bdNode::registerOutgoingMsg("; - mFns->bdPrintId(std::cerr, id); - std::cerr << ", " << msgType << ")"; - std::cerr << std::endl; -#else - (void) id; - (void) msgType; -#endif - -#ifdef USE_HISTORY - - // splitting up - to see if we can isolate the crash causes. - switch(msgType) - { - // disabled types (which appear to crash it!) - case BITDHT_MSG_TYPE_PING: - if (!id) - { - return; - } - if ((id->id.data[0] == 0) - && (id->id.data[1] == 0) - && (id->id.data[2] == 0) - && (id->id.data[3] == 0)) - { - return; - } - break; - case BITDHT_MSG_TYPE_UNKNOWN: - case BITDHT_MSG_TYPE_PONG: - case BITDHT_MSG_TYPE_FIND_NODE: - case BITDHT_MSG_TYPE_REPLY_NODE: - case BITDHT_MSG_TYPE_GET_HASH: - case BITDHT_MSG_TYPE_REPLY_HASH: - case BITDHT_MSG_TYPE_REPLY_NEAR: - case BITDHT_MSG_TYPE_POST_HASH: - case BITDHT_MSG_TYPE_REPLY_POST: - break; - } - - // This line appears to cause crashes on OSX. - mHistory.addMsg(id, transId, msgType, false, aboutId); -#else - (void) transId; - (void) aboutId; -#endif - - - -/**** -#define BITDHT_MSG_TYPE_UNKNOWN 0 -#define BITDHT_MSG_TYPE_PING 1 -#define BITDHT_MSG_TYPE_PONG 2 -#define BITDHT_MSG_TYPE_FIND_NODE 3 -#define BITDHT_MSG_TYPE_REPLY_NODE 4 -#define BITDHT_MSG_TYPE_GET_HASH 5 -#define BITDHT_MSG_TYPE_REPLY_HASH 6 -#define BITDHT_MSG_TYPE_REPLY_NEAR 7 -#define BITDHT_MSG_TYPE_POST_HASH 8 -#define BITDHT_MSG_TYPE_REPLY_POST 9 -***/ - -} - - - -uint32_t bdNode::registerIncomingMsg(bdId *id, bdToken *transId, uint32_t msgType, bdNodeId *aboutId) -{ - -#ifdef DEBUG_MSG_CHECKS - std::cerr << "bdNode::registerIncomingMsg("; - mFns->bdPrintId(std::cerr, id); - std::cerr << ", " << msgType << ")"; - std::cerr << std::endl; -#else - (void) id; - (void) msgType; -#endif - -#ifdef USE_HISTORY - mHistory.addMsg(id, transId, msgType, true, aboutId); -#else - (void) transId; - (void) aboutId; -#endif - - return 0; -} - -void bdNode::cleanupTransIdRegister() -{ - return; -} - - - -/*************** Internal Msg Storage *****************/ - -bdNodeNetMsg::bdNodeNetMsg(char *msg, int len, struct sockaddr_in *in_addr) - :data(NULL), mSize(len), addr(*in_addr) -{ - data = (char *) malloc(len); - - if(data == NULL) - { - std::cerr << "(EE) " << __PRETTY_FUNCTION__ << ": ERROR. cannot allocate memory for " << len << " bytes." << std::endl; - return ; - } - - memcpy(data, msg, len); - //print(std::cerr); -} - -void bdNodeNetMsg::print(std::ostream &out) -{ - out << "bdNodeNetMsg::print(" << mSize << ") to " - << bdnet_inet_ntoa(addr.sin_addr) << ":" << htons(addr.sin_port); - out << std::endl; -} - - -bdNodeNetMsg::~bdNodeNetMsg() -{ - free(data); -} - - - -/**************** In/Out of Relay Mode ******************/ - -void bdNode::dropRelayServers() -{ - /* We leave them there... just drop the flags */ - uint32_t flags = BITDHT_PEER_STATUS_DHT_RELAY_SERVER; - std::list peerList; - std::list::iterator it; - - mFriendList.findPeersWithFlags(flags, peerList); - for(it = peerList.begin(); it != peerList.end(); it++) - { - mFriendList.removePeer(&(*it)); - } - - mNodeSpace.clean_node_flags(flags); -} - -void bdNode::pingRelayServers() -{ - /* if Relay's have been switched on, do search/ping to locate servers */ -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::pingRelayServers()"; - std::cerr << std::endl; -#endif - - bool doSearch = true; - - uint32_t flags = BITDHT_PEER_STATUS_DHT_RELAY_SERVER; - std::list peerList; - std::list::iterator it; - - mFriendList.findPeersWithFlags(flags, peerList); - for(it = peerList.begin(); it != peerList.end(); it++) - { - if (doSearch) - { - uint32_t qflags = BITDHT_QFLAGS_INTERNAL | BITDHT_QFLAGS_DISGUISE; - mQueryMgr->addQuery(&(*it), qflags); - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::pingRelayServers() Adding Internal Search for Relay Server: "; - mFns->bdPrintNodeId(std::cerr, &(*it)); - std::cerr << std::endl; -#endif - - } - else - { - /* try ping - if we have an address??? */ - - } - } -} - - diff --git a/libbitdht/src/bitdht/bdnode.h b/libbitdht/src/bitdht/bdnode.h deleted file mode 100644 index 39abbb435..000000000 --- a/libbitdht/src/bitdht/bdnode.h +++ /dev/null @@ -1,284 +0,0 @@ -/******************************************************************************* - * bitdht/bdnode.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_NODE_H -#define BITDHT_NODE_H - -#include "bitdht/bdpeer.h" -#include "bitdht/bdquery.h" -#include "bitdht/bdstore.h" -#include "bitdht/bdobj.h" -#include "bitdht/bdhash.h" -#include "bitdht/bdhistory.h" -#include "bitdht/bdfilter.h" - -#include "bitdht/bdconnection.h" -#include "bitdht/bdaccount.h" - -#include "bitdht/bdfriendlist.h" - -class bdFilter; - - -#define BD_QUERY_NEIGHBOURS 1 -#define BD_QUERY_LOCALNET 2 -#define BD_QUERY_HASH 3 - -/********************************** - * Running a node.... - * - * run(). - * loops through and checks out of date peers. - * handles searches. - * prints out dht Table. - * - -The node handles the i/o traffic from peers. -It - - - -ping, return -peers, return -hash store, return -hash get, return - - - -respond queue. - -query queue. - - - - - -input -> call into recvFunction() -output -> call back to Udp(). - - - - - *********/ - -class bdFilteredPeer ; -class bdNodeManager; - -class bdNodeNetMsg -{ - - public: - bdNodeNetMsg(char *data, int size, struct sockaddr_in *addr); - ~bdNodeNetMsg(); - - void print(std::ostream &out); - - char *data; - int mSize; - struct sockaddr_in addr; - -}; - -class bdNodePublisher -{ - public: - /* simplified outgoing msg functions (for the managers) */ - virtual void send_ping(bdId *id) = 0; /* message out */ - virtual void send_query(bdId *id, bdNodeId *targetNodeId, bool localnet) = 0; /* message out */ - virtual void send_connect_msg(bdId *id, int msgtype, - bdId *srcAddr, bdId *destAddr, int mode, int param, int status) = 0; - - // internal Callback -> normally continues to callbackConnect(). - virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, - int mode, int point, int param, int cbtype, int errcode) = 0; - -}; - - -class bdNode: public bdNodePublisher -{ - public: - - bdNode(bdNodeId *id, std::string dhtVersion, const std::string& bootfile, const std::string& bootfilebak, const std::string& filterfile, - bdDhtFunctions *fns, bdNodeManager* manager); - - void init(); /* sets up the self referential classes (mQueryMgr & mConnMgr) */ - - void setNodeOptions(uint32_t optFlags); - uint32_t setNodeDhtMode(uint32_t dhtFlags); - - /* startup / shutdown node */ - void restartNode(); - void shutdownNode(); - - void getOwnId(bdNodeId *id); - - // virtual so manager can do callback. - // peer flags defined in bdiface.h - virtual void addPeer(const bdId *id, uint32_t peerflags); - - void printState(); - void checkPotentialPeer(bdId *id, bdId *src); - void addPotentialPeer(bdId *id, bdId *src); - - void iterationOff(); - void iteration(); - void processRemoteQuery(); - void updateStore(); - - bool addressBanned(const sockaddr_in &raddr) ; - bool getFilteredPeers(std::list &peers); - //void loadFilteredPeers(const std::list &peers); - - /* simplified outgoing msg functions (for the managers) */ - virtual void send_ping(bdId *id); /* message out */ - virtual void send_query(bdId *id, bdNodeId *targetNodeId, bool localnet); /* message out */ - virtual void send_connect_msg(bdId *id, int msgtype, - bdId *srcAddr, bdId *destAddr, int mode, int param, int status); - -// This is implemented in bdManager. -// virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, -// int mode, int point, int param, int cbtype, int errcode); - - /* interaction with outside world (Accessed by controller to deliver us msgs) */ -int outgoingMsg(struct sockaddr_in *addr, char *msg, int *len); -void incomingMsg(struct sockaddr_in *addr, char *msg, int len); - - // For Relay Mode switching. -void dropRelayServers(); -void pingRelayServers(); - -// Below is internal Management of incoming / outgoing messages. - -private: - - /* internal interaction with network */ -void sendPkt(char *msg, int len, struct sockaddr_in addr); -void recvPkt(char *msg, int len, struct sockaddr_in addr); - - - /* output functions (send msg) */ - void msgout_ping(bdId *id, bdToken *transId); - void msgout_pong(bdId *id, bdToken *transId); - void msgout_find_node(bdId *id, bdToken *transId, bdNodeId *query, bool localnet); - void msgout_reply_find_node(bdId *id, bdToken *transId, - std::list &peers); - void msgout_get_hash(bdId *id, bdToken *transId, bdNodeId *info_hash); - void msgout_reply_hash(bdId *id, bdToken *transId, - bdToken *token, std::list &values); - void msgout_reply_nearest(bdId *id, bdToken *transId, - bdToken *token, std::list &peers); - - void msgout_post_hash(bdId *id, bdToken *transId, bdNodeId *info_hash, - uint32_t port, bdToken *token); - void msgout_reply_post(bdId *id, bdToken *transId); - - - /* input functions (once mesg is parsed) */ - uint32_t parseVersion(bdToken *versionId); - void msgin_ping(bdId *id, bdToken *token, bdToken *versionId); - void msgin_pong(bdId *id, bdToken *transId, bdToken *versionId); - - void msgin_find_node(bdId *id, bdToken *transId, bdNodeId *query, bool localnet); - void msgin_reply_find_node(bdId *id, bdToken *transId, - std::list &entries); - - void msgin_get_hash(bdId *id, bdToken *transId, bdNodeId *nodeid); - void msgin_reply_hash(bdId *id, bdToken *transId, - bdToken *token, std::list &values); - void msgin_reply_nearest(bdId *id, bdToken *transId, - bdToken *token, std::list &nodes); - - void msgin_post_hash(bdId *id, bdToken *transId, - bdNodeId *info_hash, uint32_t port, bdToken *token); - void msgin_reply_post(bdId *id, bdToken *transId); - - void msgout_connect_genmsg(bdId *id, bdToken *transId, int msgtype, - bdId *srcAddr, bdId *destAddr, int mode, int param, int status); - void msgin_connect_genmsg(bdId *id, bdToken *transId, int msgtype, - bdId *srcAddr, bdId *destAddr, int mode, int param, int status); - - - - /* token handling */ - void genNewToken(bdToken *token); - int queueQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type); - - /* transId handling */ - void genNewTransId(bdToken *token); - void registerOutgoingMsg(bdId *id, bdToken *transId, uint32_t msgType, bdNodeId *aboutId); - uint32_t registerIncomingMsg(bdId *id, bdToken *transId, uint32_t msgType, bdNodeId *aboutId); - - void cleanupTransIdRegister(); - - - void doStats(); - - /********** Variables **********/ - private: - - /**** Some Variables are Protected to allow inherited classes to use *****/ - protected: - - bdSpace mNodeSpace; - bdFilter mFilterPeers; - - bdQueryManager *mQueryMgr; - bdConnectManager *mConnMgr; - - bdNodeId mOwnId; - bdId mLikelyOwnId; // Try to workout own id address. - std::string mDhtVersion; - - bdAccount mAccount; - bdStore mStore; - - bdDhtFunctions *mFns; - bdHashSpace mHashSpace; - - bdFriendList mFriendList; - bdPeerQueue mBadPeerQueue; - - bdHistory mHistory; /* for understanding the DHT */ - - bdQueryHistory mQueryHistory; /* for determining old peers */ - - private: - - uint32_t mNodeOptionFlags; - uint32_t mNodeDhtMode; - - uint32_t mMaxAllowedMsgs; - uint32_t mRelayMode; - - - std::list mRemoteQueries; - - std::list mPotentialPeers; - - std::list mOutgoingMsgs; - std::list mIncomingMsgs; - -}; - - - -#endif // BITDHT_NODE_H diff --git a/libbitdht/src/bitdht/bdobj.cc b/libbitdht/src/bitdht/bdobj.cc deleted file mode 100644 index 9832796d2..000000000 --- a/libbitdht/src/bitdht/bdobj.cc +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************* - * bitdht/bdobj.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bitdht/bdobj.h" - - -void bdPrintTransId(std::ostream &out, bdToken *transId) -{ - //out << transId->data; - bdPrintToken(out, transId); - return; -} - - -void bdPrintToken(std::ostream &out, bdToken *token) -{ - for(unsigned int i = 0; i < token->len; i++) - { - out << std::hex << (uint32_t) token->data[i]; - } - out << std::dec; -} - -void bdPrintCompactPeerId(std::ostream &out, std::string /*cpi*/ ) -{ - out << "DummyCompactPeerId"; -} - - diff --git a/libbitdht/src/bitdht/bdobj.h b/libbitdht/src/bitdht/bdobj.h deleted file mode 100644 index d193c59a8..000000000 --- a/libbitdht/src/bitdht/bdobj.h +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * bitdht/bdobj.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_OBJECTS_H -#define BITDHT_OBJECTS_H - -#define BITDHT_TOKEN_MAX_LEN 20 - -#include -#include - -class bdToken -{ - public: - bdToken() :len(0) { return; } - uint32_t len; - unsigned char data[BITDHT_TOKEN_MAX_LEN]; -}; - -class bdCompactIds -{ - public: - bdCompactIds() :len(0) { return; } - uint32_t len; - unsigned char data[BITDHT_TOKEN_MAX_LEN]; -}; - -class bdVersion -{ - public: - bdVersion() :len(0) { return; } - uint32_t len; - unsigned char data[BITDHT_TOKEN_MAX_LEN]; -}; - -void bdPrintTransId(std::ostream &out, bdToken *transId); -void bdPrintToken(std::ostream &out, bdToken *transId); -void bdPrintCompactPeerId(std::ostream &out, std::string cpi); - -#endif - diff --git a/libbitdht/src/bitdht/bdpeer.cc b/libbitdht/src/bitdht/bdpeer.cc deleted file mode 100644 index 65cfb31b5..000000000 --- a/libbitdht/src/bitdht/bdpeer.cc +++ /dev/null @@ -1,1276 +0,0 @@ -/******************************************************************************* - * bitdht/bdpeer.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bitdht/bdpeer.h" -#include "util/bdnet.h" -#include "util/bdrandom.h" -#include "util/bdstring.h" -#include "bitdht/bdiface.h" - -#include -#include -#include - -#include -#include - -/** - * #define BITDHT_DEBUG 1 -**/ - -void bdSockAddrInit(struct sockaddr_in *addr) -{ - memset(addr, 0, sizeof(struct sockaddr_in)); - addr->sin_family = AF_INET; -} - -bdId::bdId() -{ - /* blank everything */ - bdSockAddrInit(&addr); - memset(&id.data, 0, BITDHT_KEY_LEN); -} - - -bdId::bdId(bdNodeId in_id, struct sockaddr_in in_addr) -{ - /* this bit is to ensure the address is valid for windows / osx */ - bdSockAddrInit(&addr); - addr.sin_addr.s_addr = in_addr.sin_addr.s_addr; - addr.sin_port = in_addr.sin_port; - - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - id.data[i] = in_id.data[i]; - } -}; - - -void bdZeroNodeId(bdNodeId *id) -{ - uint32_t *a_data = (uint32_t *) id->data; - for(int i = 0; i < BITDHT_KEY_INTLEN; i++) - { - a_data[i] = 0; - } - return; -} - - -int operator<(const bdNodeId &a, const bdNodeId &b) -{ -#if 0 - std::cerr << "operator<("); - bdPrintNodeId(std::cerr, &a); - std::cerr << ","; - bdPrintNodeId(std::cerr, &b); - std::cerr << ")" << std::endl; -#endif - - uint8_t *a_data = (uint8_t *) a.data; - uint8_t *b_data = (uint8_t *) b.data; - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - if (*a_data < *b_data) - { - //fprintf(stderr, "Return 1, at i = %d\n", i); - return 1; - } - else if (*a_data > *b_data) - { - //fprintf(stderr, "Return 0, at i = %d\n", i); - return 0; - } - a_data++; - b_data++; - } - //fprintf(stderr, "Return 0, at i = KEYLEN\n"); - return 0; -} - -#if 0 -int operator<(const struct sockaddr_in &a, const struct sockaddr_in &b) -{ - /* else NodeIds the same - check id addresses */ - if (a.sin_addr.s_addr < b.sin_addr.s_addr) - return 1; - if (b.sin_addr.s_addr > a.sin_addr.s_addr) - return 0; - - if (a.sin_port < b.sin_port) - return 1; - - return 0; -} -#endif - -int operator<(const bdId &a, const bdId &b) -{ - if (a.id < b.id) - return 1; - if (b.id < a.id) - return 0; - - /* else NodeIds the same - check id addresses */ - if (a.addr.sin_addr.s_addr < b.addr.sin_addr.s_addr) - return 1; - if (b.addr.sin_addr.s_addr > a.addr.sin_addr.s_addr) - return 0; - - if (a.addr.sin_port < b.addr.sin_port) - return 1; - - return 0; -} - - -int operator==(const bdNodeId &a, const bdNodeId &b) -{ - uint8_t *a_data = (uint8_t *) a.data; - uint8_t *b_data = (uint8_t *) b.data; - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - if (*a_data < *b_data) - { - return 0; - } - else if (*a_data > *b_data) - { - return 0; - } - a_data++; - b_data++; - } - return 1; -} - -int operator==(const bdId &a, const bdId &b) -{ - if (!(a.id == b.id)) - return 0; - - if ((a.addr.sin_addr.s_addr == b.addr.sin_addr.s_addr) && - (a.addr.sin_port == b.addr.sin_port)) - { - return 1; - } - return 0; -} - - - -bdBucket::bdBucket() -{ - return; -} - -bdSpace::bdSpace(bdNodeId *ownId, bdDhtFunctions *fns) - :mOwnId(*ownId), mFns(fns) -{ - /* make some space for data */ - buckets.resize(mFns->bdNumBuckets()); - - mAttachTS = 0; - mAttachedFlags = 0; - mAttachedCount = 0; - - return; -} - - /* empty the buckets */ -int bdSpace::clear() -{ - std::vector::iterator it; - /* iterate through the buckets, and sort by distance */ - for(it = buckets.begin(); it != buckets.end(); it++) - { - it->entries.clear(); - } - return 1; -} - -int bdSpace::setAttachedFlag(uint32_t withflags, int count) -{ - mAttachedFlags = withflags; - mAttachedCount = count; - mAttachTS = 0; - return 1; -} - -int bdSpace::find_nearest_nodes_with_flags(const bdNodeId *id, int number, - std::list /* excluding */, - std::multimap &nearest, uint32_t with_flags) -{ - std::multimap closest; - std::multimap::iterator mit; - - bdMetric dist; - mFns->bdDistance(id, &(mOwnId), &dist); - -#ifdef DEBUG_BD_SPACE - int bucket = mFns->bdBucketDistance(&dist); - - std::cerr << "bdSpace::find_nearest_nodes(NodeId:"; - mFns->bdPrintNodeId(std::cerr, id); - - std::cerr << " Number: " << number; - std::cerr << " Query Bucket #: " << bucket; - std::cerr << std::endl; -#endif - - std::vector::iterator it; - std::list::iterator eit; - /* iterate through the buckets, and sort by distance */ - for(it = buckets.begin(); it != buckets.end(); it++) - { - for(eit = it->entries.begin(); eit != it->entries.end(); eit++) - { - if ((!with_flags) || ((with_flags & eit->mPeerFlags) == with_flags)) - { - mFns->bdDistance(id, &(eit->mPeerId.id), &dist); - closest.insert(std::pair(dist, eit->mPeerId)); - -#if 0 - std::cerr << "Added NodeId: "; - bdPrintNodeId(std::cerr, &(eit->mPeerId.id)); - std::cerr << " Metric: "; - bdPrintNodeId(std::cerr, &(dist)); - std::cerr << std::endl; -#endif - } - } - } - - /* take the first number of nodes */ - int i = 0; - for(mit = closest.begin(); (mit != closest.end()) && (i < number); mit++, i++) - { - mFns->bdDistance(&(mOwnId), &(mit->second.id), &dist); - -#ifdef DEBUG_BD_SPACE - int iBucket = mFns->bdBucketDistance(&(mit->first)); - - std::cerr << "Closest " << i << ": "; - mFns->bdPrintNodeId(std::cerr, &(mit->second.id)); - std::cerr << " Bucket: " << iBucket; - std::cerr << std::endl; -#endif - - -#if 0 - std::cerr << "\tNodeId: "; - mFns->bdPrintNodeId(std::cerr, &(mit->second.id)); - std::cerr << std::endl; - - std::cerr << "\tOwn Id: "; - mFns->bdPrintNodeId(std::cerr, &(mOwnId)); - std::cerr << std::endl; - - std::cerr << " Us Metric: "; - mFns->bdPrintNodeId(std::cerr, &dist); - std::cerr << " Bucket: " << oBucket; - std::cerr << std::endl; - - std::cerr << "\tFindId: "; - mFns->bdPrintNodeId(std::cerr, id); - std::cerr << std::endl; - - std::cerr << " Id Metric: "; - mFns->bdPrintNodeId(std::cerr, &(mit->first)); - std::cerr << " Bucket: " << iBucket; - std::cerr << std::endl; -#endif - - nearest.insert(*mit); - } - -#ifdef DEBUG_BD_SPACE - std::cerr << "#Nearest: " << (int) nearest.size(); - std::cerr << " #Closest: " << (int) closest.size(); - std::cerr << " #Requested: " << number; - std::cerr << std::endl << std::endl; -#endif - - return 1; -} - -int bdSpace::find_nearest_nodes(const bdNodeId *id, int number, - std::multimap &nearest) -{ - std::list excluding; - uint32_t with_flag = 0; - - return find_nearest_nodes_with_flags(id, number, excluding, nearest, with_flag); -} - - -/* This is much cheaper than find nearest... we only look in the one bucket - */ - -int bdSpace::find_node(const bdNodeId *id, int number, std::list &matchIds, uint32_t with_flags) -{ - bdMetric dist; - mFns->bdDistance(id, &(mOwnId), &dist); - int buckno = mFns->bdBucketDistance(&dist); - -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_node(NodeId:"; - mFns->bdPrintNodeId(std::cerr, id); - std::cerr << ")"; - - std::cerr << " Number: " << number; - std::cerr << " Bucket #: " << buckno; - std::cerr << std::endl; -#else - (void)number; -#endif - - bdBucket &buck = buckets[buckno]; - - std::list::iterator eit; - int matchCount = 0; - for(eit = buck.entries.begin(); eit != buck.entries.end(); eit++) - { -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_node() Checking Against Peer: "; - mFns->bdPrintId(std::cerr, &(eit->mPeerId)); - std::cerr << " withFlags: " << eit->mPeerFlags; - std::cerr << std::endl; -#endif - - if ((!with_flags) || ((with_flags & eit->mPeerFlags) == with_flags)) - { - if (*id == eit->mPeerId.id) - { - matchIds.push_back(eit->mPeerId); - matchCount++; - -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_node() Found Matching Peer: "; - mFns->bdPrintId(std::cerr, &(eit->mPeerId)); - std::cerr << " withFlags: " << eit->mPeerFlags; - std::cerr << std::endl; -#endif - } - } - else - { - if (*id == eit->mPeerId.id) - { - //matchIds.push_back(eit->mPeerId); - //matchCount++; - -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_node() Found (WITHOUT FLAGS) Matching Peer: "; - mFns->bdPrintId(std::cerr, &(eit->mPeerId)); - std::cerr << " withFlags: " << eit->mPeerFlags; - std::cerr << std::endl; -#endif - } - } - } - -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_node() Found " << matchCount << " Matching Peers"; - std::cerr << std::endl << std::endl; -#endif - - return matchCount; -} - -/* even cheaper again... no big lists */ -int bdSpace::find_exactnode(const bdId *id, bdPeer &peer) -{ - bdMetric dist; - mFns->bdDistance(&(id->id), &(mOwnId), &dist); - int buckno = mFns->bdBucketDistance(&dist); - -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_exactnode(Id:"; - mFns->bdPrintId(std::cerr, id); - std::cerr << ")"; - - std::cerr << " Bucket #: " << buckno; - std::cerr << std::endl; -#endif - - bdBucket &buck = buckets[buckno]; - - std::list::iterator eit; - for(eit = buck.entries.begin(); eit != buck.entries.end(); eit++) - { - if (*id == eit->mPeerId) - { -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_exactnode() Found Matching Peer: "; - mFns->bdPrintId(std::cerr, &(eit->mPeerId)); - std::cerr << " withFlags: " << eit->mPeerFlags; - std::cerr << std::endl; -#endif - - peer = (*eit); - return 1; - } - } -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_exactnode() WARNING Failed to find Matching Peer: "; - std::cerr << std::endl; -#endif - - return 0; -} - - - -int bdSpace::clean_node_flags(uint32_t flags) -{ - std::cerr << "bdSpace::clean_node_flags(" << flags << ")"; - std::cerr << std::endl; - - int count = 0; - std::vector::iterator bit; - for(bit = buckets.begin(); bit != buckets.end(); bit++) - { - std::list::iterator eit; - for(eit = bit->entries.begin(); eit != bit->entries.end(); eit++) - { - if (flags & eit->mPeerFlags) - { -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::clean_node_flags() Found Match: "; - mFns->bdPrintId(std::cerr, &(eit->mPeerId)); - std::cerr << " withFlags: " << eit->mPeerFlags; - std::cerr << std::endl; -#endif - - count++; - eit->mPeerFlags &= ~flags; - } - } - } -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::clean_node_flags() Cleaned " << count << " Matching Peers"; - std::cerr << std::endl; -#endif - - return count; -} - - - -#define BITDHT_ATTACHED_SEND_PERIOD 17 - -int bdSpace::scanOutOfDatePeers(std::list &peerIds) -{ - /* - * - */ - bool doAttached = (mAttachedCount > 0); - uint32_t attachedCount = 0; - - std::map closest; - std::map::iterator mit; - - std::vector::iterator it; - std::list::iterator eit; - time_t ts = time(NULL); - - /* iterate through the buckets, and sort by distance */ - for(it = buckets.begin(); it != buckets.end(); it++) - { - for(eit = it->entries.begin(); eit != it->entries.end(); ) - { - bool added = false; - if (doAttached) - { - if (eit->mExtraFlags & BITDHT_PEER_EXFLAG_ATTACHED) - { - /* add to send list, if we haven't pinged recently */ - if ((ts - eit->mLastSendTime > BITDHT_ATTACHED_SEND_PERIOD ) && - (ts - eit->mLastRecvTime > BITDHT_ATTACHED_SEND_PERIOD )) - { - peerIds.push_back(eit->mPeerId); - eit->mLastSendTime = ts; - added = true; - } - attachedCount++; - } - } - - - /* timeout on last send time! */ - if ((!added) && (ts - eit->mLastSendTime > BITDHT_MAX_SEND_PERIOD )) - { - /* We want to ping a peer iff: - * 1) They are out-of-date: mLastRecvTime is too old. - * 2) They don't have 0x0001 flag (we haven't received a PONG) and never sent. - */ - if ((ts - eit->mLastRecvTime > BITDHT_MAX_SEND_PERIOD ) || - !(eit->mPeerFlags & BITDHT_PEER_STATUS_RECV_PONG)) - { - peerIds.push_back(eit->mPeerId); - eit->mLastSendTime = ts; - } - } - - - /* we also want to remove very old entries (should it happen here?) - * which are not pushed out by newer entries (will happen in for closer buckets) - */ - - bool discard = false; - /* discard very old entries */ - if (ts - eit->mLastRecvTime > BITDHT_DISCARD_PERIOD) - { - discard = true; - } - - /* discard peers which have not responded to anything (ie have no flags set) */ - /* changed into have not id'ed themselves, as we've added ping to list of flags. */ - if ((ts - eit->mFoundTime > BITDHT_MAX_RESPONSE_PERIOD ) && - !(eit->mPeerFlags & BITDHT_PEER_STATUS_RECV_PONG)) - { - discard = true; - } - - - /* INCREMENT */ - if (discard) - { - eit = it->entries.erase(eit); - } - else - { - eit++; - } - } - } - -#define ATTACH_UPDATE_PERIOD 600 - - if ((ts - mAttachTS > ATTACH_UPDATE_PERIOD) || (attachedCount != mAttachedCount)) - { - //std::cerr << "Updating ATTACH Stuff"; - //std::cerr << std::endl; - updateAttachedPeers(); /* XXX TEMP HACK to look at stability */ - mAttachTS = ts; - } - - return (peerIds.size()); -} - - -/* Attached should be changed to preferentially choose the ones we want - * If we have RELAYS enabled - then we want them to attach to the RELAYS - * Not sure about this yet! - * - * Have to think about it a bit more. (and redesign code to handle multiple passes) - */ - -int bdSpace::updateAttachedPeers() -{ - /* - * - */ - bool doAttached = (mAttachedCount > 0); - uint32_t attachedCount = 0; - - // Must scan through - otherwise we can never remove Attached state. - // It is only once every 10 minutes or so! -#if 0 - if (!doAttached) - { - return 0; - } -#endif - - std::map closest; - std::map::iterator mit; - - std::vector::iterator it; - std::list::reverse_iterator eit; - - - /* skip the first bucket, as we don't want to ping ourselves! */ - it = buckets.begin(); - if (it != buckets.end()) - { - it++; - } - - /* iterate through the buckets (sorted by distance) */ - for(; it != buckets.end(); it++) - { - /* start from the back, as these are the most recently seen (and more likely to be the old ATTACHED) */ - for(eit = it->entries.rbegin(); eit != it->entries.rend(); eit++) - { - if (doAttached) - { - if ((eit->mPeerFlags & mAttachedFlags) == mAttachedFlags) - { - /* flag as attached */ - eit->mExtraFlags |= BITDHT_PEER_EXFLAG_ATTACHED; - - /* inc count, and cancel search if we've found them */ - attachedCount++; - if (attachedCount >= mAttachedCount) - { - doAttached = false; - } - } - else - { - eit->mExtraFlags &= ~BITDHT_PEER_EXFLAG_ATTACHED; - } - } - else - { - eit->mExtraFlags &= ~BITDHT_PEER_EXFLAG_ATTACHED; - } - } - } - return 1; -} - - - - -/* Called to add or update peer. - * sorts bucket lists by lastRecvTime. - * updates requested node. - */ - -/* peer flags - * order is important! - * higher bits = more priority. - * BITDHT_PEER_STATUS_RECVPING - * BITDHT_PEER_STATUS_RECVPONG - * BITDHT_PEER_STATUS_RECVNODES - * BITDHT_PEER_STATUS_RECVHASHES - * BITDHT_PEER_STATUS_DHT_ENGINE (dbXXxx) - * BITDHT_PEER_STATUS_DHT_APPL (XXRSxx) - * BITDHT_PEER_STATUS_DHT_VERSION (XXxx50) - * - */ - -int bdSpace::add_peer(const bdId *id, uint32_t peerflags) -{ - /* find the peer */ - bool add = false; - time_t ts = time(NULL); - -#ifdef DEBUG_BD_SPACE - fprintf(stderr, "bdSpace::add_peer()\n"); -#endif - - /* calculate metric */ - bdMetric met; - mFns->bdDistance(&(mOwnId), &(id->id), &met); - int bucket = mFns->bdBucketDistance(&met); - -#ifdef DEBUG_BD_SPACE - fprintf(stderr, "peer:"); - mFns->bdPrintId(std::cerr, id); - fprintf(stderr, " bucket: %d", bucket); - fprintf(stderr, "\n"); -#endif - - /* select correct bucket */ - bdBucket &buck = buckets[bucket]; - - - std::list::iterator it; - - /* calculate the score for this new peer */ - uint32_t minScore = peerflags; - - /* loop through ids, to find it */ - for(it = buck.entries.begin(); it != buck.entries.end(); it++) - { - /* similar id check */ - if (mFns->bdSimilarId(id, &(it->mPeerId))) - { - bdPeer peer = *it; - it = buck.entries.erase(it); - - peer.mLastRecvTime = ts; - peer.mPeerFlags |= peerflags; /* must be cumulative ... so can do online, replynodes, etc */ - - /* also update port from incoming id, as we have definitely recved from it */ - if (mFns->bdUpdateSimilarId(&(peer.mPeerId), id)) - { - /* updated it... must be Unstable */ - peer.mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE; - } - - buck.entries.push_back(peer); - -#ifdef DEBUG_BD_SPACE - std::cerr << "Peer already in bucket: moving to back of the list" << std::endl; -#endif - - return 1; - } - - /* find lowest score */ - if (it->mPeerFlags < minScore) - { - minScore = it->mPeerFlags; - } - } - - /* not in the list! */ - - if (buck.entries.size() < mFns->bdNodesPerBucket()) - { -#ifdef DEBUG_BD_SPACE - std::cerr << "Bucket not full: allowing add" << std::endl; -#endif - add = true; - } - else - { - /* check head of list */ - bdPeer &peer = buck.entries.front(); - if (ts - peer.mLastRecvTime > BITDHT_MAX_RECV_PERIOD) - { -#ifdef DEBUG_BD_SPACE - std::cerr << "Dropping Out-of-Date peer in bucket" << std::endl; -#endif - buck.entries.pop_front(); - add = true; - } - else if (peerflags > minScore) - { - /* find one to drop */ - for(it = buck.entries.begin(); it != buck.entries.end(); it++) - { - if (it->mPeerFlags == minScore) - { - /* delete low priority peer */ - it = buck.entries.erase(it); - add = true; - break; - } - } - -#ifdef DEBUG_BD_SPACE - std::cerr << "Inserting due to Priority: minScore: " << minScore - << " new Peer Score: " << peerscore << << std::endl; -#endif - } - else - { -#ifdef DEBUG_BD_SPACE - std::cerr << "No Out-Of-Date peers in bucket... dropping new entry" << std::endl; -#endif - } - } - - if (add) - { - bdPeer newPeer; - - newPeer.mPeerId = *id; - newPeer.mLastRecvTime = ts; - newPeer.mLastSendTime = 0; // ts; //???? - newPeer.mFoundTime = ts; - newPeer.mPeerFlags = peerflags; - newPeer.mExtraFlags = 0; - - buck.entries.push_back(newPeer); - -#ifdef DEBUG_BD_SPACE - /* useful debug */ - std::cerr << "bdSpace::add_peer() Added Bucket["; - std::cerr << bucket << "] Entry: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - } - return add; -} - - /* flag peer */ -bool bdSpace::flagpeer(const bdId *id, uint32_t flags, uint32_t ex_flags) -{ -#ifdef DEBUG_BD_SPACE - fprintf(stderr, "bdSpace::flagpeer()\n"); -#endif - - /* calculate metric */ - bdMetric met; - mFns->bdDistance(&(mOwnId), &(id->id), &met); - int bucket = mFns->bdBucketDistance(&met); - - - /* select correct bucket */ - bdBucket &buck = buckets[bucket]; - - /* loop through ids, to find it */ - std::list::iterator it; - for(it = buck.entries.begin(); it != buck.entries.end(); it++) - { - /* similar id check */ - if (mFns->bdSimilarId(id, &(it->mPeerId))) - { -#ifdef DEBUG_BD_SPACE - fprintf(stderr, "peer:"); - mFns->bdPrintId(std::cerr, id); - fprintf(stderr, " bucket: %d", bucket); - fprintf(stderr, "\n"); - fprintf(stderr, "Original Flags: %x Extra: %x\n", - it->mPeerFlags, it->mExtraFlags); -#endif - it->mPeerFlags |= flags; - it->mExtraFlags |= ex_flags; - -#ifdef DEBUG_BD_SPACE - fprintf(stderr, "Updated Flags: %x Extra: %x\n", - it->mPeerFlags, it->mExtraFlags); -#endif - } - } - return true; -} - -/* print tables. - */ - -int bdSpace::printDHT() -{ - std::map closest; - std::map::iterator mit; - - std::vector::iterator it; - std::list::iterator eit; - - /* iterate through the buckets, and sort by distance */ - int i = 0; - -#ifdef BITDHT_DEBUG - fprintf(stderr, "bdSpace::printDHT()\n"); - for(it = buckets.begin(); it != buckets.end(); it++, i++) - { - if (it->entries.size() > 0) - { - fprintf(stderr, "Bucket %d ----------------------------\n", i); - } - - for(eit = it->entries.begin(); eit != it->entries.end(); eit++) - { - bdMetric dist; - mFns->bdDistance(&(mOwnId), &(eit->mPeerId.id), &dist); - - fprintf(stderr, " Metric: "); - mFns->bdPrintNodeId(std::cerr, &(dist)); - fprintf(stderr, " Id: "); - mFns->bdPrintId(std::cerr, &(eit->mPeerId)); - fprintf(stderr, " PeerFlags: %08x", eit->mPeerFlags); - fprintf(stderr, "\n"); - } - } -#endif - - fprintf(stderr, "--------------------------------------\n"); - fprintf(stderr, "DHT Table Summary --------------------\n"); - fprintf(stderr, "--------------------------------------\n"); - - /* little summary */ - unsigned long long sum = 0; - unsigned long long no_peers = 0; - uint32_t count = 0; - bool doPrint = false; - bool doAvg = false; - - i = 0; - for(it = buckets.begin(); it != buckets.end(); it++, i++) - { - int size = it->entries.size(); - int shift = BITDHT_KEY_BITLEN - i; - bool toBig = false; - - if (shift > BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1) - { - toBig = true; - shift = BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1; - } - unsigned long long no_nets = ((unsigned long long) 1 << shift); - - /* use doPrint so it acts as a single switch */ - if (size && !doAvg && !doPrint) - { - doAvg = true; - } - - if (size && !doPrint) - { - doPrint = true; - } - - if (size == 0) - { - /* reset counters - if empty slot - to discount outliers in average */ - sum = 0; - no_peers = 0; - count = 0; - } - - if (doPrint) - { - if (size) - fprintf(stderr, "Bucket %d: %d peers: ", i, size); -#ifdef BITDHT_DEBUG - else - fprintf(stderr, "Bucket %d: %d peers: ", i, size); -#endif - } - if (toBig) - { - if (size) - { - if (doPrint) - bd_fprintf(stderr, "Estimated NetSize >> %llu\n", no_nets); - } - else - { -#ifdef BITDHT_DEBUG - if (doPrint) - bd_fprintf(stderr, " Bucket = Net / >> %llu\n", no_nets); -#endif - } - } - else - { - no_peers = no_nets * size; - if (size) - { - if (doPrint) - bd_fprintf(stderr, "Estimated NetSize = %llu\n", no_peers); - } - else - { - -#ifdef BITDHT_DEBUG - if (doPrint) - bd_fprintf(stderr, " Bucket = Net / %llu\n", no_nets); -#endif - - } - } - if (doPrint && doAvg && !toBig) - { - if (size == mFns->bdNodesPerBucket()) - { - /* last average */ - doAvg = false; - } - if (no_peers != 0) - { - sum += no_peers; - count++; -#ifdef BITDHT_DEBUG - fprintf(stderr, "Est: %d: %llu => %llu / %d\n", - i, no_peers, sum, count); -#endif - } - } - - } - if (count == 0) - { - fprintf(stderr, "Zero Network Size (count = 0)\n"); - } - else - { - bd_fprintf(stderr, "Estimated Network Size = (%llu / %d) = %llu\n", sum, count, sum / count); - } - - return 1; -} - - -int bdSpace::getDhtBucket(const int idx, bdBucket &bucket) -{ - if ((idx < 0) || (idx > (int) buckets.size() - 1 )) - { - return 0; - } - bucket = buckets[idx]; - return 1; -} - -uint32_t bdSpace::calcNetworkSize() -{ - return calcNetworkSizeWithFlag(~0u) ; -} - -uint32_t bdSpace::calcNetworkSizeWithFlag(uint32_t withFlag) -{ - std::vector::iterator it; - - /* little summary */ - unsigned long long sum = 0; - unsigned long long no_peers = 0; - uint32_t count = 0; - -#ifdef BITDHT_DEBUG - std::cerr << "Estimating DHT network size. Flags=" << std::hex << withFlag << std::dec << std::endl; -#endif - - int i = 0; - for(it = buckets.begin(); it != buckets.end(); it++, i++) - { - int size = 0; - std::list::iterator lit; - for(lit = it->entries.begin(); lit != it->entries.end(); lit++) - if (withFlag & lit->mPeerFlags) - size++; - - int shift = BITDHT_KEY_BITLEN - i; - - if (shift > BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1) - continue ; - - unsigned long long no_nets = ((unsigned long long) 1 << shift); - - no_peers = no_nets * size; - - if(size < mFns->bdNodesPerBucket() && size > 0) - { - sum += no_peers; - count++; - } - -#ifdef BITDHT_DEBUG - if(size > 0) - std::cerr << " Bucket " << shift << ": " << size << " / " << mFns->bdNodesPerBucket() << " peers. no_nets=" << no_nets << ". no_peers=" << no_peers << "." << std::endl; -#endif - } - - - uint32_t NetSize = 0; - if (count != 0) - NetSize = sum / count; - -#ifdef BITDHT_DEBUG - std::cerr << "Estimated net size: " << NetSize << ". Old style estimate: " << calcNetworkSizeWithFlag_old(withFlag) << std::endl; -#endif - - return NetSize; -} - -/* (csoler) This is the old method for computing the DHT size estimate. The method is based on averaging the - * estimate given by each bucket: n 2^b where n is the bucket size and b is the number of similar bits - * in this bucket. The idea is that buckets that are not empty nor full give a estimate of the network - * size. - * - * The existing implementation of this method was not using all non empty/full buckets, in order to avoid - * outliers, but this method is also biased, and tends to give a lower value (because it skips the largest buckets) - * especially when the network is very sparse. - * - * The new implementation respects the original estimate without bias, but it still notoriously wrong. Only averaging - * the estimate over a large period of time would produce a reliable value. - */ -uint32_t bdSpace::calcNetworkSizeWithFlag_old(uint32_t withFlag) -{ - std::vector::iterator it; - - /* little summary */ - unsigned long long sum = 0; - unsigned long long no_peers = 0; - uint32_t count = 0; - uint32_t totalcount = 0; - bool doPrint = false; - bool doAvg = false; - - int i = 0; - for(it = buckets.begin(); it != buckets.end(); it++, i++) - { - int size = 0; - std::list::iterator lit; - for(lit = it->entries.begin(); lit != it->entries.end(); lit++) - { - if (withFlag & lit->mPeerFlags) - { - size++; - } - } - - totalcount += size; - - int shift = BITDHT_KEY_BITLEN - i; - bool toBig = false; - - if (shift > BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1) - { - toBig = true; - shift = BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1; - } - unsigned long long no_nets = ((unsigned long long) 1 << shift); - - - /* use doPrint so it acts as a single switch */ - if (size && !doAvg && !doPrint) - { - doAvg = true; - } - - if (size && !doPrint) - { - doPrint = true; - } - - if (size == 0) - { - /* reset counters - if empty slot - to discount outliers in average */ - sum = 0; - no_peers = 0; - count = 0; - } - - if (!toBig) - { - no_peers = no_nets * size; - } - - if (doPrint && doAvg && !toBig) - { - if (size == mFns->bdNodesPerBucket()) - { - /* last average */ - doAvg = false; - } - if (no_peers != 0) - { - sum += no_peers; - count++; - } - } - } - - - uint32_t NetSize = 0; - if (count != 0) - { - NetSize = sum / count; - } - - //std::cerr << "bdSpace::calcNetworkSize() : " << NetSize; - //std::cerr << std::endl; - - return NetSize; -} - -uint32_t bdSpace::calcSpaceSize() -{ - std::vector::iterator it; - - /* little summary */ - uint32_t totalcount = 0; - for(it = buckets.begin(); it != buckets.end(); it++) - { - totalcount += it->entries.size(); - } - return totalcount; -} - -uint32_t bdSpace::calcSpaceSizeWithFlag(uint32_t withFlag) -{ - std::vector::iterator it; - - /* little summary */ - uint32_t totalcount = 0; - - it = buckets.begin(); - if (it != buckets.end()) - { - it++; /* skip own bucket! */ - } - for(; it != buckets.end(); it++) - { - int size = 0; - std::list::iterator lit; - for(lit = it->entries.begin(); lit != it->entries.end(); lit++) - { - if (withFlag & lit->mPeerFlags) - { - size++; - } - } - totalcount += size; - } - return totalcount; -} - - /* special function to enable DHT localisation (i.e find peers from own network) */ -bool bdSpace::findRandomPeerWithFlag(bdId &id, uint32_t withFlag) -{ - std::vector::iterator it; - uint32_t totalcount = calcSpaceSizeWithFlag(withFlag); - - if(totalcount == 0) - return false ; - - uint32_t rnd = bdRandom::random_u32() % totalcount; - uint32_t i = 0; - uint32_t buck = 0; - - //std::cerr << "bdSpace::findRandomPeerWithFlag()"; - //std::cerr << std::endl; - - it = buckets.begin(); - if (it != buckets.end()) - { - it++; /* skip own bucket! */ - buck++; - } - for(; it != buckets.end(); it++, buck++) - { - std::list::iterator lit; - for(lit = it->entries.begin(); lit != it->entries.end(); lit++) - { - if (withFlag & lit->mPeerFlags) - { - if (i == rnd) - { -#ifdef BITDHT_DEBUG - std::cerr << "bdSpace::findRandomPeerWithFlag() found #" << i; - std::cerr << " in bucket #" << buck; - std::cerr << std::endl; -#endif - /* found */ - id = lit->mPeerId; - return true; - } - i++; - } - } - } - std::cerr << "bdSpace::findRandomPeerWithFlag() failed to find " << rnd << " / " << totalcount; - std::cerr << std::endl; -#ifdef BITDHT_DEBUG -#endif - - return false; -} - diff --git a/libbitdht/src/bitdht/bdpeer.h b/libbitdht/src/bitdht/bdpeer.h deleted file mode 100644 index d663a7ecd..000000000 --- a/libbitdht/src/bitdht/bdpeer.h +++ /dev/null @@ -1,212 +0,0 @@ -/******************************************************************************* - * bitdht/bdpeer.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_PEER_H -#define BITDHT_PEER_H - -#include "bitdht/bdiface.h" -#include - -/******* - * These type of parameters are now DHT Function dependent - * -#define BITDHT_BUCKET_SIZE 20 -#define BITDHT_BUCKET_SIZE_BITS 5 - -#define BITDHT_N_BUCKETS BITDHT_KEY_BITLEN - * - * - ***/ - -/*** - * DEFINED in bdiface.h - * #define BITDHT_KEY_LEN 20 - * #define BITDHT_KEY_INTLEN 5 - * #define BITDHT_KEY_BITLEN 160 - ***/ - -#define BITDHT_ULLONG_BITS 64 - -#define BITDHT_MAX_RESPONSE_PERIOD (15) -#define BITDHT_MAX_SEND_PERIOD 300 // 5 minutes. -#define BITDHT_MAX_RECV_PERIOD (BITDHT_MAX_SEND_PERIOD + BITDHT_MAX_RESPONSE_PERIOD) // didn't respond to a ping. - -// Properly out of date. -#define BITDHT_DISCARD_PERIOD (2 * BITDHT_MAX_SEND_PERIOD + BITDHT_MAX_RESPONSE_PERIOD) // didn't respond to two pings. - -// Must have a FLAG by this time. (Make it really quick - so we through away the rubbish). - - -#include -#include -#include -#include - -/**** - * DEFINED in bdiface.h - * - * class bdNodeId - * { - * public: - * unsigned char data[BITDHT_KEY_LEN]; - * }; - ****/ - - -/**** - * DEFINED in bdiface.h - * - -class bdMetric: public bdNodeId {}; - -class bdId -{ - public: - - bdId(); - bdId(bdNodeId in_id, struct sockaddr_in in_addr); - - struct sockaddr_in addr; - bdNodeId id; -}; - * - *********/ - - - -//void bdRandomNodeId(bdNodeId *id); - -// Only Functions that are common for all Dhts. -// zero, basic comparisons.. -void bdZeroNodeId(bdNodeId *id); - -//void bdRandomId(bdId *id); -//int bdDistance(const bdNodeId *a, const bdNodeId *b, bdMetric *r); -//int bdBucketDistance(const bdMetric *m); -//int bdBucketDistance(const bdNodeId *a, const bdNodeId *b); -//int operator<(const bdMetric &a, const bdMetric &b); - -//int operator<(const struct sockaddr_in &a, const struct sockaddr_in &b); - -int operator<(const bdNodeId &a, const bdNodeId &b); -int operator<(const bdId &a, const bdId &b); -int operator==(const bdNodeId &a, const bdNodeId &b); -int operator==(const bdId &a, const bdId &b); - -//void bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid); - -//void bdPrintId(std::ostream &out, const bdId *a); -//void bdPrintNodeId(std::ostream &out, const bdNodeId *a); - -//std::string bdConvertToPrintable(std::string input); - -/**** - * DEFINED in bdiface.h - * - -class bdPeer -{ - public: - - bdId mPeerId; - uint32_t mPeerFlags; - time_t mLastSendTime; - time_t mLastRecvTime; - time_t mFoundTime; // time stamp that peer was found -}; - - -class bdBucket -{ - public: - - bdBucket(); - - // list so we can queue properly - std::list entries; -}; - * - * - *****/ - -class bdSpace -{ - public: - - bdSpace(bdNodeId *ownId, bdDhtFunctions *fns); - -int clear(); - -int setAttachedFlag(uint32_t withflags, int count); - - /* accessors */ -int find_nearest_nodes(const bdNodeId *id, int number, - std::multimap &nearest); - -int find_nearest_nodes_with_flags(const bdNodeId *id, int number, - std::list excluding, - std::multimap &nearest, uint32_t with_flag); - -int find_node(const bdNodeId *id, int number, - std::list &matchIds, uint32_t with_flag); -int find_exactnode(const bdId *id, bdPeer &peer); - -// switched to more efficient single sweep. -//int out_of_date_peer(bdId &id); // side-effect updates, send flag on peer. -int scanOutOfDatePeers(std::list &peerIds); -int updateAttachedPeers(); - -int add_peer(const bdId *id, uint32_t mode); -int printDHT(); -int getDhtBucket(const int idx, bdBucket &bucket); - -uint32_t calcNetworkSize(); -uint32_t calcNetworkSizeWithFlag(uint32_t withFlag); -uint32_t calcNetworkSizeWithFlag_old(uint32_t withFlag); -uint32_t calcSpaceSize(); -uint32_t calcSpaceSizeWithFlag(uint32_t withFlag); - - /* special function to enable DHT localisation (i.e find peers from own network) */ -bool findRandomPeerWithFlag(bdId &id, uint32_t withFlag); - - /* strip out flags - to switch in/out of relay mode */ -int clean_node_flags(uint32_t flags); - - /* to add later */ -int updateOwnId(bdNodeId *newOwnId); - - /* flag peer */ -bool flagpeer(const bdId *id, uint32_t flags, uint32_t ex_flags); - - private: - - std::vector buckets; - bdNodeId mOwnId; - bdDhtFunctions *mFns; - - uint32_t mAttachedFlags; - uint32_t mAttachedCount; - time_t mAttachTS; -}; - - -#endif - diff --git a/libbitdht/src/bitdht/bdquery.cc b/libbitdht/src/bitdht/bdquery.cc deleted file mode 100644 index f9b77002d..000000000 --- a/libbitdht/src/bitdht/bdquery.cc +++ /dev/null @@ -1,1198 +0,0 @@ -/******************************************************************************* - * bitdht/bdquery.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bitdht/bdquery.h" -#include "bitdht/bdstddht.h" -#include "util/bdnet.h" - -#include -#include -#include - -/** - * #define DEBUG_QUERY 1 -**/ - -#define EXPECTED_REPLY 10 // Speed up queries -#define QUERY_IDLE_RETRY_PEER_PERIOD 600 // 10min = (mFns->bdNumQueryNodes() * 60) -#define MAX_QUERY_IDLE_PERIOD 1200 // 20min. - - -/************************************************************ - * bdQuery logic: - * 1) as replies come in ... maintain list of M closest peers to ID. - * 2) select non-queried peer from list, and query. - * 3) halt when we have asked all M closest peers about the ID. - * - * Flags can be set to disguise the target of the search. - * This involves - */ - -bdQuery::bdQuery(const bdNodeId *id, std::list &startList, uint32_t queryFlags, - bdDhtFunctions *fns) -{ - /* */ - mId = *id; - mFns = fns; - - time_t now = time(NULL); - std::list::iterator it; - for(it = startList.begin(); it != startList.end(); it++) - { - bdPeer peer; - peer.mLastSendTime = 0; - peer.mLastRecvTime = 0; - peer.mPeerFlags = 0; - peer.mFoundTime = now; - peer.mPeerId = *it; - - bdMetric dist; - - mFns->bdDistance(&mId, &(peer.mPeerId.id), &dist); - - mClosest.insert(std::pair(dist, peer)); - - - } - - mState = BITDHT_QUERY_QUERYING; - mQueryFlags = queryFlags; - mQueryTS = now; - mSearchTime = 0; - mClosestListSize = (int) (1.5 * mFns->bdNumQueryNodes()); - mPotPeerCleanTS = now; - - mQueryIdlePeerRetryPeriod = QUERY_IDLE_RETRY_PEER_PERIOD; - mRequiredPeerFlags = BITDHT_PEER_STATUS_DHT_ENGINE_VERSION; // XXX to update later. - - /* setup the limit of the search - * by default it is setup to 000000 = exact match - */ - bdZeroNodeId(&mLimit); -} - -bool bdQuery::result(std::list &answer) -{ - /* get all the matches to our query */ - std::multimap::iterator sit, eit; - sit = mClosest.begin(); - eit = mClosest.upper_bound(mLimit); - int i = 0; - for(; sit != eit; sit++) - { - if ((sit->second).mLastRecvTime != 0) - { - answer.push_back(sit->second.mPeerId); - i++; - } - } - return (i > 0); -} - - -int bdQuery::nextQuery(bdId &id, bdNodeId &targetNodeId) -{ - if ((mState != BITDHT_QUERY_QUERYING) && !(mQueryFlags & BITDHT_QFLAGS_DO_IDLE)) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() Query is done\n"); -#endif - return 0; - } - - /* search through through list, find closest not queried */ - time_t now = time(NULL); - - /* update IdlePeerRetry */ - if ((now - mQueryTS) / 2 > mQueryIdlePeerRetryPeriod) - { - mQueryIdlePeerRetryPeriod = (now-mQueryTS) / 2; - if (mQueryIdlePeerRetryPeriod > MAX_QUERY_IDLE_PERIOD) - { - mQueryIdlePeerRetryPeriod = MAX_QUERY_IDLE_PERIOD; - } - } - - bool notFinished = false; - std::multimap::iterator it; - int i = 0; - for(it = mClosest.begin(); it != mClosest.end(); it++, i++) - { - bool queryPeer = false; - - /* if never queried */ - if (it->second.mLastSendTime == 0) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() Found non-sent peer. queryPeer = true : "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - std::cerr << std::endl; -#endif - queryPeer = true; - } - - /* re-request every so often */ - if ((!queryPeer) && (mQueryFlags & BITDHT_QFLAGS_DO_IDLE) && - (now - it->second.mLastSendTime > mQueryIdlePeerRetryPeriod)) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() Found out-of-date. queryPeer = true : "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - std::cerr << std::endl; -#endif - queryPeer = true; - } - - /* expecting every peer to be up-to-date is too hard... - * enough just to have received lists from each - * - replacement policy will still work. - * - * Need to wait at least EXPECTED_REPLY, to make sure their answers are pinged - */ - - if (((it->second.mLastRecvTime == 0) || (now - it->second.mLastRecvTime < EXPECTED_REPLY)) && - (i < mFns->bdNumQueryNodes())) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() Never Received @Idx(%d) notFinished = true: ", i); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - std::cerr << std::endl; -#endif - notFinished = true; - } - - if (queryPeer) - { - id = it->second.mPeerId; - it->second.mLastSendTime = now; - - if (mQueryFlags & BITDHT_QFLAGS_DISGUISE) - { - /* calc Id mid point between Target and Peer */ - bdNodeId midRndId; - mFns->bdRandomMidId(&mId, &(id.id), &midRndId); - - targetNodeId = midRndId; - } - else - { - targetNodeId = mId; - } -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() Querying Peer: "); - mFns->bdPrintId(std::cerr, &id); - std::cerr << std::endl; -#endif - return 1; - } - } - - /* allow query to run for a minimal amount of time - * This is important as startup - when we might not have any peers. - * Probably should be handled elsewhere. - */ - time_t age = now - mQueryTS; - - if (age < BITDHT_MIN_QUERY_AGE) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() under Min Time: Query not finished / No Query\n"); -#endif - return 0; - } - - if (age > BITDHT_MAX_QUERY_AGE) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() over Max Time: Query force to Finish\n"); -#endif - /* fall through and stop */ - } - else if ((mClosest.size() < mFns->bdNumQueryNodes()) || (notFinished)) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() notFinished | !size(): Query not finished / No Query\n"); -#endif - /* not full yet... */ - return 0; - } - -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() Finished\n"); -#endif - - /* if we get here - query finished */ - if (mState == BITDHT_QUERY_QUERYING) - { - /* store query time */ - mSearchTime = now - mQueryTS; - } - - /* cleanup PotentialPeers before doing the final State */; - removeOldPotentialPeers(); - /* check if we found the node */ - if (mClosest.size() > 0) - { - if (((mClosest.begin()->second).mPeerId.id == mId) && - ((mClosest.begin()->second).mLastRecvTime != 0)) - { - mState = BITDHT_QUERY_SUCCESS; - } - else if ((mPotentialPeers.begin()->second).mPeerId.id == mId) - { - mState = BITDHT_QUERY_PEER_UNREACHABLE; - } - else - { - mState = BITDHT_QUERY_FOUND_CLOSEST; - } - } - else - { - mState = BITDHT_QUERY_FAILURE; - } - return 0; -} - -int bdQuery::addClosestPeer(const bdId *id, uint32_t mode) -{ - bdMetric dist; - time_t ts = time(NULL); - - mFns->bdDistance(&mId, &(id->id), &dist); - -#ifdef DEBUG_QUERY - fprintf(stderr, "bdQuery::addPeer("); - mFns->bdPrintId(std::cerr, id); - fprintf(stderr, ", %u)\n", mode); -#endif - - std::multimap::iterator it, sit, eit; - sit = mClosest.lower_bound(dist); - eit = mClosest.upper_bound(dist); - int i = 0; - int actualCloser = 0; - int toDrop = 0; - // switched end condition to upper_bound to provide stability for NATTED peers. - // we will favour the older entries! - for(it = mClosest.begin(); it != eit; it++, i++, actualCloser++) - { - time_t sendts = ts - it->second.mLastSendTime; - bool hasSent = (it->second.mLastSendTime != 0); - bool hasReply = (it->second.mLastRecvTime >= it->second.mLastSendTime); - if ((hasSent) && (!hasReply) && (sendts > EXPECTED_REPLY)) - { - i--; /* dont count this one */ - toDrop++; - } - } - // Counts where we are. -#ifdef DEBUG_QUERY - fprintf(stderr, "Searching.... %di = %d - %d peers closer than this one\n", i, actualCloser, toDrop); -#endif - - - if (i > mClosestListSize - 1) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Distance to far... dropping\n"); -#endif - /* drop it */ - return 0; - } - - for(it = sit; it != eit; it++, i++) - { - /* full id check */ - if (mFns->bdSimilarId(id, &(it->second.mPeerId))) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Peer Already here!\n"); -#endif - if (mode) - { - /* also update port from incoming id, as we have definitely recved from it */ - if (mFns->bdUpdateSimilarId(&(it->second.mPeerId), id)) - { - /* updated it... must be Unstable */ - it->second.mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE; - } - } - if (mode & BITDHT_PEER_STATUS_RECV_NODES) - { - /* only update recvTime if sendTime > checkTime.... (then its our query) */ -#ifdef DEBUG_QUERY - fprintf(stderr, "Updating LastRecvTime\n"); -#endif - it->second.mLastRecvTime = ts; - it->second.mPeerFlags |= mode; - } - return 1; - } - } - -#ifdef DEBUG_QUERY - fprintf(stderr, "Peer not in Query\n"); -#endif - /* firstly drop unresponded (bit ugly - but hard structure to extract from) */ - int j; - for(j = 0; j < toDrop; j++) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Dropping Peer that dont reply\n"); -#endif - for(it = mClosest.begin(); it != mClosest.end(); ++it) - { - time_t sendts = ts - it->second.mLastSendTime; - bool hasSent = (it->second.mLastSendTime != 0); - bool hasReply = (it->second.mLastRecvTime >= it->second.mLastSendTime); - - if ((hasSent) && (!hasReply) && (sendts > EXPECTED_REPLY)) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Dropped: "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, "\n"); -#endif - mClosest.erase(it); - break ; - } - } - } - - /* trim it back */ - while(mClosest.size() > (uint32_t) (mClosestListSize - 1)) - { - std::multimap::iterator it; - it = mClosest.end(); - if (!mClosest.empty()) - { - it--; -#ifdef DEBUG_QUERY - fprintf(stderr, "Removing Furthest Peer: "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, "\n"); -#endif - - mClosest.erase(it); - } - } - -#ifdef DEBUG_QUERY - fprintf(stderr, "bdQuery::addPeer(): Closer Peer!: "); - mFns->bdPrintId(std::cerr, id); - fprintf(stderr, "\n"); -#endif - - /* add it in */ - bdPeer peer; - peer.mPeerId = *id; - peer.mPeerFlags = mode; - peer.mLastSendTime = 0; - peer.mLastRecvTime = 0; - peer.mFoundTime = ts; - - if (mode & BITDHT_PEER_STATUS_RECV_NODES) - { - peer.mLastRecvTime = ts; - } - - mClosest.insert(std::pair(dist, peer)); - return 1; -} - - -/******************************************************************************************* - ********************************* Add Peer Interface ************************************* - *******************************************************************************************/ - -/**** These functions are called by bdNode to add peers to the query - * They add/update the three sets of lists. - * - * int bdQuery::addPeer(const bdId *id, uint32_t mode) - * Proper message from a peer. - * - * int bdQuery::addPotentialPeer(const bdId *id, const bdId *src, uint32_t srcmode) - * This returns 1 if worthy of pinging, 0 if to ignore. - */ - -#define PEER_MESSAGE 0 -#define FIND_NODE_RESPONSE 1 - -int bdQuery::addPeer(const bdId *id, uint32_t mode) -{ - addClosestPeer(id, mode); - updatePotentialPeer(id, mode, PEER_MESSAGE); - updateProxy(id, mode); - return 1; -} - -int bdQuery::addPotentialPeer(const bdId *id, const bdId *src, uint32_t srcmode) -{ - // is it a Potential Proxy? Always Check This. - addProxy(id, src, srcmode); - - int worthy = worthyPotentialPeer(id); - int shouldPing = 0; - if (worthy) - { - shouldPing = updatePotentialPeer(id, 0, FIND_NODE_RESPONSE); - } - return shouldPing; -} - - -/******************************************************************************************* - ********************************* Closest Peer ******************************************** - *******************************************************************************************/ - - -/******************************************************************************************* - ******************************** Potential Peer ******************************************* - *******************************************************************************************/ - - - - -/******* - * Potential Peers are a list of the closest answers to our queries. - * Lots of these peers will not be reachable.... so will only exist in this list. - * They will also never have there PeerFlags set ;( - * - */ - - -/*** utility functions ***/ - -int bdQuery::worthyPotentialPeer(const bdId *id) -{ - bdMetric dist; - mFns->bdDistance(&mId, &(id->id), &dist); - -#ifdef DEBUG_QUERY - std::cerr << "bdQuery::worthyPotentialPeer("; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - /* we check if this is a worthy potential peer.... - * if it is already in mClosest -> false. old peer. - * if it is > mClosest.rbegin() -> false. too far way. - */ - - std::multimap::iterator it, sit, eit; - sit = mClosest.lower_bound(dist); - eit = mClosest.upper_bound(dist); - - /* check if outside range, & bucket is full */ - if ((sit == mClosest.end()) && (mClosest.size() >= mFns->bdNumQueryNodes())) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Peer to far away for Potential\n"); -#endif - return 0; /* too far way */ - } - - - for(it = sit; it != eit; it++) - { - if (mFns->bdSimilarId(id, &(it->second.mPeerId))) - { - // Not updating Full Peer Id here... as inspection function. -#ifdef DEBUG_QUERY - fprintf(stderr, "Peer already in mClosest\n"); -#endif - return 0; - } - } - - return 1; /* either within mClosest Range (but not there!), or there aren't enough peers */ -} - - -/***** - * - * mLastSendTime ... is the last FIND_NODE_RESPONSE that we returned 1. (indicating to PING). - * mLastRecvTime ... is the last time we received an updatei about/from them - * - * The update is dependent on the flags passed in the function call. (saves duplicate code). - * - * - * XXX IMPORTANT TO DECIDE WHAT IS RETURNED HERE. - * original algorithm return 0 if exists in potential peers, 1 if unknown. - * This is used to limit the number of pings to non-responding potentials. - * - * MUST think about this. Need to install HISTORY tracking again. to look at the statistics. - * - * It is important that the potential Peers list extends all the way back to == mClosest().end(). - * Otherwise we end up with [TARGET] .... [ POTENTIAL ] ..... [ CLOSEST ] ...... - * and the gap between POT and CLOSEST will get hammered with pings. - * - */ - -#define MIN_PING_POTENTIAL_PERIOD 300 - -int bdQuery::updatePotentialPeer(const bdId *id, uint32_t mode, uint32_t addType) -{ - bdMetric dist; - time_t now = time(NULL); - - mFns->bdDistance(&mId, &(id->id), &dist); - - std::multimap::iterator it, sit, eit; - sit = mPotentialPeers.lower_bound(dist); - eit = mPotentialPeers.upper_bound(dist); - - for(it = sit; it != eit; it++) - { - if (mFns->bdSimilarId(id, &(it->second.mPeerId))) - { - - it->second.mPeerFlags |= mode; - it->second.mLastRecvTime = now; - if (addType == FIND_NODE_RESPONSE) - { - // We could lose peers here by not updating port... but should be okay. - if (now - it->second.mLastSendTime > MIN_PING_POTENTIAL_PERIOD) - { - it->second.mLastSendTime = now; - return 1; - } - } - else if (mode) - { - /* also update port from incoming id, as we have definitely recved from it */ - if (mFns->bdUpdateSimilarId(&(it->second.mPeerId), id)) - { - /* updated it... must be Unstable */ - it->second.mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE; - } - } - return 0; - } - } - -// Removing this check - so that we can have varying length PotentialPeers. -// Peer will always be added, then probably removed straight away. - -#if 0 - /* check if outside range, & bucket is full */ - if ((sit == mPotentialPeers.end()) && (mPotentialPeers.size() >= mFns->bdNumQueryNodes())) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Peer to far away for Potential\n"); -#endif - return 0; - } -#endif - - /* add it in */ - bdPeer peer; - peer.mPeerId = *id; - peer.mPeerFlags = mode; - peer.mFoundTime = now; - peer.mLastRecvTime = now; - peer.mLastSendTime = 0; - if (addType == FIND_NODE_RESPONSE) - { - peer.mLastSendTime = now; - } - - mPotentialPeers.insert(std::pair(dist, peer)); - -#ifdef DEBUG_QUERY - fprintf(stderr, "Flagging as Potential Peer!\n"); -#endif - - trimPotentialPeers_toClosest(); - - return 1; -} - - -int bdQuery::trimPotentialPeers_FixedLength() -{ - /* trim it back */ - while(mPotentialPeers.size() > (uint32_t) (mFns->bdNumQueryNodes())) - { - std::multimap::iterator it; - it = mPotentialPeers.end(); - it--; // must be more than 1 peer here? -#ifdef DEBUG_QUERY - fprintf(stderr, "Removing Furthest Peer: "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, "\n"); -#endif - mPotentialPeers.erase(it); - } - return 1; -} - - -int bdQuery::trimPotentialPeers_toClosest() -{ - if (mPotentialPeers.size() <= (uint32_t) (mFns->bdNumQueryNodes())) - return 1; - - std::multimap::reverse_iterator it; - it = mClosest.rbegin(); - bdMetric lastClosest = it->first; - - /* trim it back */ - while(mPotentialPeers.size() > (uint32_t) (mFns->bdNumQueryNodes())) - { - std::multimap::iterator it; - it = mPotentialPeers.end(); - it--; // must be more than 1 peer here? - if (lastClosest < it->first) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Removing Furthest Peer: "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, "\n"); -#endif - mPotentialPeers.erase(it); - } - else - { - return 1; - } - } - return 1; -} - - -/* as Potential Peeers are to determine if a peer is CLOSEST or UNREACHABLE - * we need to drop ones that we haven't heard about in ages. - * - * only do this in IDLE mode... - * The timeout period is dependent on our RetryPeriod. - */ - -#define POT_PEER_CLEAN_PERIOD 60 -#define POT_PEER_RECV_TIMEOUT_PERIOD (mQueryIdlePeerRetryPeriod + EXPECTED_REPLY) - -int bdQuery::removeOldPotentialPeers() -{ - if (!(mQueryFlags & BITDHT_QFLAGS_DO_IDLE)) - { - return 0; - } - - time_t now = time(NULL); - if (now - mPotPeerCleanTS < POT_PEER_CLEAN_PERIOD) - { - return 0; - } - - mPotPeerCleanTS = now; - - /* painful loop */ - std::multimap::iterator it; - for(it = mPotentialPeers.begin(); it != mPotentialPeers.end();) - { - /* which timestamp do we care about? */ - if (now - it->second.mLastRecvTime > POT_PEER_RECV_TIMEOUT_PERIOD) - { -#ifdef DEBUG_QUERY - std::cerr << "bdQuery::removeOldPotentialPeers() removing: "; - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, "\n"); -#endif - std::multimap::iterator it2 = it; - ++it2 ; - mPotentialPeers.erase(it); - it = it2 ; - - // Unfortunately have to start again... as pointers invalidated. - //it = mPotentialPeers.begin(); - } - else - { - ++it; - } - } - return 1 ; -} - - - -/******************************************************************************************* - ******************************** Potential Proxies **************************************** - *******************************************************************************************/ - -/******** - * Potential Proxies. a list of peers that have returned our target in response to a query. - * - * We are particularly interested in peers with specific flags... - * But all the peers have been pinged already by the time they reach this list. - * So there are two options: - * 1) Track everythings mode history - which is a waste of resources. - * 2) Store the list, and ping later. - * - * We will store these in two lists: Flags & Unknown. - * we keep the most recent of each, and move around as required. - * - * we could also check the Closest/PotentialPeer lists to grab the flags, - * for an unknown peer? - * - * All Functions manipulating PotentialProxies are here. - * We need several functions: - * - * For Extracting Proxies. -bool bdQuery::proxies(std::list &answer) -bool bdQuery::potentialProxies(std::list &answer) - * - * For Adding/Updating Proxies. -int bdQuery::addProxy(const bdId *id, const bdId *src, uint32_t srcmode) -int bdQuery::updateProxy(const bdId *id, uint32_t mode) - * - */ - -/*** Two Functions to extract Proxies... ***/ -bool bdQuery::proxies(std::list &answer) -{ - /* get all the matches to our query */ - std::list::iterator it; - int i = 0; - for(it = mProxiesFlagged.begin(); it != mProxiesFlagged.end(); it++, i++) - { - answer.push_back(it->mPeerId); - } - return (i > 0); -} - -bool bdQuery::potentialProxies(std::list &answer) -{ - /* get all the matches to our query */ - std::list::iterator it; - int i = 0; - for(it = mProxiesUnknown.begin(); it != mProxiesUnknown.end(); it++, i++) - { - answer.push_back(it->mPeerId); - } - return (i > 0); -} - - - -int bdQuery::addProxy(const bdId *id, const bdId *src, uint32_t srcmode) -{ - bdMetric dist; - time_t now = time(NULL); - - mFns->bdDistance(&mId, &(id->id), &dist); - - /* finally if it is an exact match, add as potential proxy */ - int bucket = mFns->bdBucketDistance(&dist); - if ((bucket != 0) || (src == NULL)) - { - /* not a potential proxy */ - return 0; - } - -#ifdef DEBUG_QUERY - fprintf(stderr, "Bucket = 0, Have Potential Proxy!\n"); -#endif - - bool found = false; - if (updateProxyList(src, srcmode, mProxiesUnknown)) - { - found = true; - } - - if (!found) - { - if (updateProxyList(src, srcmode, mProxiesFlagged)) - { - found = true; - } - } - - if (!found) - { - /* if we get here. its not in the list */ -#ifdef DEBUG_QUERY - fprintf(stderr, "Adding Source to Proxy List:\n"); -#endif - bdPeer peer; - peer.mPeerId = *src; - peer.mPeerFlags = srcmode; - peer.mLastSendTime = 0; - peer.mLastRecvTime = now; - peer.mFoundTime = now; - - /* add it in */ - if ((srcmode & mRequiredPeerFlags) == mRequiredPeerFlags) - { - mProxiesFlagged.push_front(peer); - } - else - { - mProxiesUnknown.push_front(peer); - } - } - - - trimProxies(); - - return 1; -} - - -int bdQuery::updateProxy(const bdId *id, uint32_t mode) -{ - if (!updateProxyList(id, mode, mProxiesUnknown)) - { - updateProxyList(id, mode, mProxiesFlagged); - } - - trimProxies(); - return 1; -} - - -/**** Utility functions that do all the work! ****/ - -int bdQuery::updateProxyList(const bdId *id, uint32_t mode, std::list &searchProxyList) -{ - std::list::iterator it; - for(it = searchProxyList.begin(); it != searchProxyList.end(); it++) - { - if (mFns->bdSimilarId(id, &(it->mPeerId))) - { - /* found it ;( */ -#ifdef DEBUG_QUERY - std::cerr << "bdQuery::updateProxyList() Found peer, updating"; - std::cerr << std::endl; -#endif - - time_t now = time(NULL); - if (mode) - { - /* also update port from incoming id, as we have definitely recved from it */ - if (mFns->bdUpdateSimilarId(&(it->mPeerId), id)) - { - /* updated it... must be Unstable */ - it->mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE; - } - } - it->mPeerFlags |= mode; - it->mLastRecvTime = now; - - /* now move it to the front of required list... - * note this could be exactly the same list as &searchProxyList, or a different one! - */ - - bdPeer peer = *it; - it = searchProxyList.erase(it); - - if ((peer.mPeerFlags & mRequiredPeerFlags) == mRequiredPeerFlags) - { - mProxiesFlagged.push_front(peer); - } - else - { - mProxiesUnknown.push_front(peer); - } - - return 1; - break; - } - } - - return 0; -} - -#define MAX_POTENTIAL_PROXIES 10 - -int bdQuery::trimProxies() -{ - - /* drop excess Potential Proxies */ - while(mProxiesUnknown.size() > MAX_POTENTIAL_PROXIES) - { - mProxiesUnknown.pop_back(); - } - - while(mProxiesFlagged.size() > MAX_POTENTIAL_PROXIES) - { - mProxiesFlagged.pop_back(); - } - return 1; -} - - -/******************************************************************************************* - ******************************** Potential Proxies **************************************** - *******************************************************************************************/ - - - -/* print query. - */ - -int bdQuery::printQuery() -{ -#ifdef DEBUG_QUERY - fprintf(stderr, "bdQuery::printQuery()\n"); -#endif - - time_t ts = time(NULL); - fprintf(stderr, "Query for: "); - mFns->bdPrintNodeId(std::cerr, &mId); - fprintf(stderr, " Query State: %d", mState); - fprintf(stderr, " Query Age %ld secs", ts-mQueryTS); - if (mState >= BITDHT_QUERY_FAILURE) - { - fprintf(stderr, " Search Time: %d secs", mSearchTime); - } - fprintf(stderr, "\n"); - -#ifdef DEBUG_QUERY - fprintf(stderr, "Closest Available Peers:\n"); - std::multimap::iterator it; - for(it = mClosest.begin(); it != mClosest.end(); it++) - { - fprintf(stderr, "Id: "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first))); - fprintf(stderr," Flags: %x", it->second.mPeerFlags); - fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime); - fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime); - fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); - fprintf(stderr, "\n"); - } - - fprintf(stderr, "\nClosest Potential Peers:\n"); - for(it = mPotentialPeers.begin(); it != mPotentialPeers.end(); it++) - { - fprintf(stderr, "Id: "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first))); - fprintf(stderr," Flags: %x", it->second.mPeerFlags); - fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime); - fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime); - fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); - fprintf(stderr, "\n"); - } -#else - // shortened version. - fprintf(stderr, "Closest Available Peer: "); - std::multimap::iterator it = mClosest.begin(); - if (it != mClosest.end()) - { - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first))); - fprintf(stderr," Flags: %x", it->second.mPeerFlags); - fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime); - fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime); - fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); - } - fprintf(stderr, "\n"); - - fprintf(stderr, "Closest Potential Peer: "); - it = mPotentialPeers.begin(); - if (it != mPotentialPeers.end()) - { - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first))); - fprintf(stderr," Flags: %x", it->second.mPeerFlags); - fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime); - fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime); - fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); - } - fprintf(stderr, "\n"); - -#endif - std::list::iterator lit; - fprintf(stderr, "Flagged Proxies:\n"); - for(lit = mProxiesFlagged.begin(); lit != mProxiesFlagged.end(); lit++) - { - fprintf(stderr, "ProxyId: "); - mFns->bdPrintId(std::cerr, &(lit->mPeerId)); - fprintf(stderr," Flags: %x", it->second.mPeerFlags); - fprintf(stderr," Found: %ld ago", ts-lit->mFoundTime); - fprintf(stderr," LastSent: %ld ago", ts-lit->mLastSendTime); - fprintf(stderr," LastRecv: %ld ago", ts-lit->mLastRecvTime); - fprintf(stderr, "\n"); - } - - fprintf(stderr, "Potential Proxies:\n"); - for(lit = mProxiesUnknown.begin(); lit != mProxiesUnknown.end(); lit++) - { - fprintf(stderr, "ProxyId: "); - mFns->bdPrintId(std::cerr, &(lit->mPeerId)); - fprintf(stderr," Flags: %x", it->second.mPeerFlags); - fprintf(stderr," Found: %ld ago", ts-lit->mFoundTime); - fprintf(stderr," LastSent: %ld ago", ts-lit->mLastSendTime); - fprintf(stderr," LastRecv: %ld ago", ts-lit->mLastRecvTime); - fprintf(stderr, "\n"); - } - - return 1; -} - - - - -/********************************* Remote Query **************************************/ - -#define QUERY_HISTORY_LIMIT 10 // Typically get max of 4-6 per 10minutes. -#define QUERY_HISTORY_PERIOD 600 - -bdRemoteQuery::bdRemoteQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type) - :mId(*id), mQuery(*query), mTransId(*transId), mQueryType(query_type) -{ - mQueryTS = time(NULL); -} - - - - -bdQueryHistoryList::bdQueryHistoryList() - :mBadPeer(false) -{ - -} - - -bool bdQueryHistoryList::addIncomingQuery(time_t recvd, const bdNodeId *aboutId) -{ - mList.insert(std::make_pair(recvd, *aboutId)); - mBadPeer = (mList.size() > QUERY_HISTORY_LIMIT); - return mBadPeer; -} - - -// returns true if empty. -bool bdQueryHistoryList::cleanupMsgs(time_t before) -{ - if (before == 0) - { - mList.clear(); - return true; - } - - // Delete the old stuff in the list. - while((mList.begin() != mList.end()) && (mList.begin()->first < before)) - { - mList.erase(mList.begin()); - } - - // return true if empty. - if (mList.begin() == mList.end()) - { - return true; - } - return false; -} - -bdQueryHistory::bdQueryHistory() - :mStorePeriod(QUERY_HISTORY_PERIOD) -{ - return; -} - -bool bdQueryHistory::addIncomingQuery(time_t recvd, const bdId *id, const bdNodeId *aboutId) -{ - std::map::iterator it; - - it = mHistory.find(*id); - if (it == mHistory.end()) - { - mHistory[*id] = bdQueryHistoryList(); - it = mHistory.find(*id); - } - - return (it->second).addIncomingQuery(recvd, aboutId); -} - -bool bdQueryHistory::isBadPeer(const bdId *id) -{ - std::map::iterator it; - - it = mHistory.find(*id); - if (it == mHistory.end()) - { - return false; - } - - return it->second.mBadPeer; -} - - -void bdQueryHistory::cleanupOldMsgs() -{ - if (mStorePeriod == 0) - { - return; // no cleanup. - } - - time_t before = time(NULL) - mStorePeriod; - std::map::iterator it; - for(it = mHistory.begin(); it != mHistory.end(); ) - { - if (it->second.cleanupMsgs(before)) - { - std::map::iterator tit(it); - ++tit; - mHistory.erase(it); - it = tit; - } - else - { - ++it; - } - } -} - - -void bdQueryHistory::printMsgs() -{ - std::ostream &out = std::cerr; - - out << "bdQueryHistory::printMsgs() IncomingQueries in last " << mStorePeriod; - out << " secs" << std::endl; - - std::map::iterator it; - for(it = mHistory.begin(); it != mHistory.end(); it++) - { - out << "\t"; - bdStdPrintId(out, &(it->first)); - out << " " << it->second.mList.size(); - if (it->second.mBadPeer) - { - out << " BadPeer"; - } - out << std::endl; - } -} - - - - - - - - - diff --git a/libbitdht/src/bitdht/bdquery.h b/libbitdht/src/bitdht/bdquery.h deleted file mode 100644 index 4cb08f165..000000000 --- a/libbitdht/src/bitdht/bdquery.h +++ /dev/null @@ -1,157 +0,0 @@ -/******************************************************************************* - * bitdht/bdquery.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_QUERY_H -#define BITDHT_QUERY_H - -#include "bitdht/bdiface.h" -#include "bitdht/bdpeer.h" -#include "bitdht/bdobj.h" - -/* Query result flags are in bdiface.h */ - -#define BITDHT_MIN_QUERY_AGE 10 -#define BITDHT_MAX_QUERY_AGE 300 /* Query Should take <1 minute, so 5 minutes sounds reasonable */ - -class bdQuery -{ - public: - bdQuery(const bdNodeId *id, std::list &startList, uint32_t queryFlags, - bdDhtFunctions *fns); - - // get the answer. -bool result(std::list &answer); -bool proxies(std::list &answer); -bool potentialProxies(std::list &answer); - - // returning results get passed to all queries. -//void addNode(const bdId *id, int mode); -int nextQuery(bdId &id, bdNodeId &targetId); -int addPeer(const bdId *id, uint32_t mode); -int addPotentialPeer(const bdId *id, const bdId *src, uint32_t srcmode); -int printQuery(); - - // searching for - bdNodeId mId; - bdMetric mLimit; - uint32_t mState; - time_t mQueryTS; - uint32_t mQueryFlags; - int32_t mSearchTime; - - int32_t mQueryIdlePeerRetryPeriod; // seconds between retries. - - //private: - - // Closest Handling Fns. -int addClosestPeer(const bdId *id, uint32_t mode); - - // Potential Handling Fns. -int worthyPotentialPeer(const bdId *id); -int updatePotentialPeer(const bdId *id, uint32_t mode, uint32_t addType); -int trimPotentialPeers_FixedLength(); -int trimPotentialPeers_toClosest(); -int removeOldPotentialPeers(); - - // Proxy Handling Fns. -int addProxy(const bdId *id, const bdId *src, uint32_t srcmode); -int updateProxy(const bdId *id, uint32_t mode); -int updateProxyList(const bdId *id, uint32_t mode, std::list &searchProxyList); -int trimProxies(); - - - // closest peers. - std::multimap mClosest; - std::multimap mPotentialPeers; - time_t mPotPeerCleanTS; // periodic cleanup of PotentialPeers. - - uint32_t mRequiredPeerFlags; - std::list mProxiesUnknown; - std::list mProxiesFlagged; - - int mClosestListSize; - bdDhtFunctions *mFns; - -}; - -#if 0 - -class bdQueryStatus -{ - public: - uint32_t mStatus; - uint32_t mQFlags; - std::list mResults; -}; - -#endif - - - -/* this is just a container class. - * we locally seach for this, once then discard. - */ -class bdRemoteQuery -{ - public: - bdRemoteQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type); - - bdId mId; - bdNodeId mQuery; - bdToken mTransId; - uint32_t mQueryType; - - time_t mQueryTS; -}; - - - -class bdQueryHistoryList -{ - public: - bdQueryHistoryList(); - -bool addIncomingQuery(time_t recvd, const bdNodeId *aboutId); // calcs and returns mBadPeer -bool cleanupMsgs(time_t before); // returns true if empty. - - bool mBadPeer; - std::multimap mList; -}; - -class bdQueryHistory -{ - public: - bdQueryHistory(); - -bool addIncomingQuery(time_t recvd, const bdId *id, const bdNodeId *aboutId); -void printMsgs(); - -void cleanupOldMsgs(); - -bool isBadPeer(const bdId *id); - - int mStorePeriod; - std::map mHistory; -}; - - -#endif - diff --git a/libbitdht/src/bitdht/bdquerymgr.cc b/libbitdht/src/bitdht/bdquerymgr.cc deleted file mode 100644 index 70f58ce90..000000000 --- a/libbitdht/src/bitdht/bdquerymgr.cc +++ /dev/null @@ -1,379 +0,0 @@ -/******************************************************************************* - * bitdht/bdquerymgr.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bitdht/bdquerymgr.h" -#include "bitdht/bdnode.h" - -#include -#include -#include -#include - -#include -#include - - -#define BITDHT_QUERY_START_PEERS 10 -#define BITDHT_QUERY_NEIGHBOUR_PEERS 8 -#define BITDHT_MAX_REMOTE_QUERY_AGE 10 - -/**** - * #define DEBUG_NODE_MULTIPEER 1 - * #define DEBUG_NODE_MSGS 1 - * #define DEBUG_NODE_ACTIONS 1 - - * #define DEBUG_NODE_MSGIN 1 - * #define DEBUG_NODE_MSGOUT 1 - ***/ - -//#define DEBUG_NODE_MSGS 1 - - -bdQueryManager::bdQueryManager(bdSpace *space, bdDhtFunctions *fns, bdNodePublisher *pub) - :mNodeSpace(space), mFns(fns), mPub(pub) -{ -} - -/***** Startup / Shutdown ******/ -void bdQueryManager::shutdownQueries() -{ - /* clear the queries */ - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end();it++) - { - delete (*it); - } - - mLocalQueries.clear(); -} - - -void bdQueryManager::printQueries() -{ - std::cerr << "bdQueryManager::printQueries()"; - std::cerr << std::endl; - - int i = 0; - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++, i++) - { - fprintf(stderr, "Query #%d:\n", i); - (*it)->printQuery(); - fprintf(stderr, "\n"); - } -} - - -int bdQueryManager::iterateQueries(int maxQueries) -{ -#ifdef DEBUG_NODE_MULTIPEER - std::cerr << "bdQueryManager::iterateQueries() of Peer: "; - mFns->bdPrintNodeId(std::cerr, &mOwnId); - std::cerr << std::endl; -#endif - - /* allow each query to send up to one query... until maxMsgs has been reached */ - int numQueries = mLocalQueries.size(); - int sentQueries = 0; - int i = 0; - - bdId id; - bdNodeId targetNodeId; - - while((i < numQueries) && (sentQueries < maxQueries)) - { - bdQuery *query = mLocalQueries.front(); - mLocalQueries.pop_front(); - mLocalQueries.push_back(query); - - /* go through the possible queries */ - if (query->nextQuery(id, targetNodeId)) - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdQueryManager::iteration() send_query("; - mFns->bdPrintId(std::cerr, &id); - std::cerr << ","; - mFns->bdPrintNodeId(std::cerr, &targetNodeId); - std::cerr << ")"; - std::cerr << std::endl; -#endif - mPub->send_query(&id, &targetNodeId, false); - sentQueries++; - } - i++; - } - -#ifdef DEBUG_NODE_ACTIONS - std::cerr << "bdQueryManager::iteration() maxMsgs: " << maxMsgs << " sentPings: " << sentPings; - std::cerr << " / " << allowedPings; - std::cerr << " sentQueries: " << sentQueries; - std::cerr << " / " << numQueries; - std::cerr << std::endl; -#endif - - //printQueries(); - - return sentQueries; -} - - -bool bdQueryManager::checkPotentialPeer(bdId *id, bdId *src) -{ - bool isWorthyPeer = false; - /* also push to queries */ - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++) - { - if ((*it)->addPotentialPeer(id, src, 0)) - { - isWorthyPeer = true; - } - } - - if (!isWorthyPeer) - { - isWorthyPeer = checkWorthyPeerSources(src); - } - - return isWorthyPeer; -} - - -void bdQueryManager::addPeer(const bdId *id, uint32_t peerflags) -{ - -#ifdef DEBUG_NODE_ACTIONS - fprintf(stderr, "bdQueryManager::addPeer("); - mFns->bdPrintId(std::cerr, id); - fprintf(stderr, ")\n"); -#endif - - /* iterate through queries */ - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++) - { - (*it)->addPeer(id, peerflags); - } -} - - -/************************************ Query Details *************************/ -void bdQueryManager::addQuery(const bdNodeId *id, uint32_t qflags) -{ - - std::list startList; - std::multimap nearest; - std::multimap::iterator it; - - mNodeSpace->find_nearest_nodes(id, BITDHT_QUERY_START_PEERS, nearest); - -#ifdef DEBUG_NODE_ACTIONS - fprintf(stderr, "bdQueryManager::addQuery("); - mFns->bdPrintNodeId(std::cerr, id); - fprintf(stderr, ")\n"); -#endif - - for(it = nearest.begin(); it != nearest.end(); it++) - { - startList.push_back(it->second); - } - - bdQuery *query = new bdQuery(id, startList, qflags, mFns); - mLocalQueries.push_back(query); -} - - -void bdQueryManager::clearQuery(const bdNodeId *rmId) -{ - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end();) - { - if ((*it)->mId == *rmId) - { - bdQuery *query = (*it); - it = mLocalQueries.erase(it); - delete query; - } - else - { - it++; - } - } -} - -void bdQueryManager::QueryStatus(std::map &statusMap) -{ - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++) - { - bdQueryStatus status; - status.mStatus = (*it)->mState; - status.mQFlags = (*it)->mQueryFlags; - (*it)->result(status.mResults); - statusMap[(*it)->mId] = status; - } -} - -int bdQueryManager::QuerySummary(const bdNodeId *id, bdQuerySummary &query) -{ - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++) - { - if ((*it)->mId == *id) - { - query.mId = (*it)->mId; - query.mLimit = (*it)->mLimit; - query.mState = (*it)->mState; - query.mQueryTS = (*it)->mQueryTS; - query.mQueryFlags = (*it)->mQueryFlags; - query.mSearchTime = (*it)->mSearchTime; - query.mClosest = (*it)->mClosest; - query.mPotentialPeers = (*it)->mPotentialPeers; - query.mProxiesUnknown = (*it)->mProxiesUnknown; - query.mProxiesFlagged = (*it)->mProxiesFlagged; - query.mQueryIdlePeerRetryPeriod = (*it)->mQueryIdlePeerRetryPeriod; - - return 1; - } - } - return 0; -} - -/* Extract Results from Peer Queries */ - -#define BDQRYMGR_RESULTS 1 -#define BDQRYMGR_PROXIES 2 -#define BDQRYMGR_POTPROXIES 3 - -int bdQueryManager::getResults(bdNodeId *target, std::list &answer, int querytype) -{ - - /* grab any peers from any existing query */ - int results = 0; - std::list::iterator qit; - for(qit = mLocalQueries.begin(); qit != mLocalQueries.end(); qit++) - { - if (!((*qit)->mId == (*target))) - { - continue; - } - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdQueryManager::getResults() Found Matching Query"; - std::cerr << std::endl; -#endif - switch(querytype) - { - default: - case BDQRYMGR_RESULTS: - results = (*qit)->result(answer); - break; - case BDQRYMGR_PROXIES: - results = (*qit)->proxies(answer); - break; - case BDQRYMGR_POTPROXIES: - results = (*qit)->potentialProxies(answer); - break; - } - /* will only be one matching query.. so end loop */ - return results; - } - return 0; -} - - -int bdQueryManager::result(bdNodeId *target, std::list &answer) -{ - return getResults(target, answer, BDQRYMGR_RESULTS); -} - -int bdQueryManager::proxies(bdNodeId *target, std::list &answer) -{ - return getResults(target, answer, BDQRYMGR_PROXIES); -} - -int bdQueryManager::potentialProxies(bdNodeId *target, std::list &answer) -{ - return getResults(target, answer, BDQRYMGR_POTPROXIES); -} - - -/************ WORTHY PEERS **********/ - -#define MAX_WORTHY_PEER_AGE 15 - -void bdQueryManager::addWorthyPeerSource(bdId *src) -{ - time_t now = time(NULL); - - bdPeer peer; - peer.mPeerId = *src; - peer.mFoundTime = now; - -#ifdef DEBUG_NODE_ACTIONS - std::cerr << "bdQueryManager::addWorthyPeerSource("; - mFns->bdPrintId(std::cerr, src); - std::cerr << ")" << std::endl; -#endif - - mWorthyPeerSources.push_back(peer); -} - -bool bdQueryManager::checkWorthyPeerSources(bdId *src) -{ - if (!src) - return false; - - time_t now = time(NULL); - std::list::iterator it; - for(it = mWorthyPeerSources.begin(); it != mWorthyPeerSources.end(); ) - { - if (now - it->mFoundTime > MAX_WORTHY_PEER_AGE) - { -#ifdef DEBUG_NODE_ACTIONS - std::cerr << "bdQueryManager::checkWorthyPeerSource() Discard old Source: "; - mFns->bdPrintId(std::cerr, &(it->mPeerId)); - std::cerr << std::endl; -#endif - - it = mWorthyPeerSources.erase(it); - } - else - { - if (it->mPeerId == *src) - { -#ifdef DEBUG_NODE_ACTIONS - std::cerr << "bdQueryManager::checkWorthyPeerSource("; - mFns->bdPrintId(std::cerr, src); - std::cerr << ") = true" << std::endl; -#endif - - return true; - } - it++; - } - } - return false; -} - - - diff --git a/libbitdht/src/bitdht/bdquerymgr.h b/libbitdht/src/bitdht/bdquerymgr.h deleted file mode 100644 index 355781244..000000000 --- a/libbitdht/src/bitdht/bdquerymgr.h +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * bitdht/bdquerymgr.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_QUERY_MANAGER_H -#define BITDHT_QUERY_MANAGER_H - -#include "bitdht/bdquery.h" -class bdNodePublisher; - - -class bdQueryManager -{ - public: - - bdQueryManager(bdSpace *space, bdDhtFunctions *fns, bdNodePublisher *pub); - - void shutdownQueries(); - void printQueries(); - - int iterateQueries(int maxqueries); - - bool checkPotentialPeer(bdId *id, bdId *src); - void addPeer(const bdId *id, uint32_t peerflags); - - void addQuery(const bdNodeId *id, uint32_t qflags); - void clearQuery(const bdNodeId *id); - void QueryStatus(std::map &statusMap); - int QuerySummary(const bdNodeId *id, bdQuerySummary &query); - - int result(bdNodeId *target, std::list &answer); - int proxies(bdNodeId *target, std::list &answer); - int potentialProxies(bdNodeId *target, std::list &answer); - - // extra "Worthy Peers" we will want to ping. - void addWorthyPeerSource(bdId *src); - bool checkWorthyPeerSources(bdId *src); - - private: - - int getResults(bdNodeId *target, std::list &answer, int querytype); - - /* NB: No Mutex Protection... Single threaded, Mutex at higher level! - */ - - bdSpace *mNodeSpace; - bdDhtFunctions *mFns; - bdNodePublisher *mPub; - - std::list mLocalQueries; - std::list mWorthyPeerSources; -}; - - - -#endif // BITDHT_QUERY_MANAGER_H diff --git a/libbitdht/src/bitdht/bdstddht.cc b/libbitdht/src/bitdht/bdstddht.cc deleted file mode 100644 index eac5c148e..000000000 --- a/libbitdht/src/bitdht/bdstddht.cc +++ /dev/null @@ -1,347 +0,0 @@ -/******************************************************************************* - * bitdht/bdstddht.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bitdht/bdstddht.h" -#include "bitdht/bdpeer.h" -#include "util/bdrandom.h" -#include "util/bdstring.h" - -#include -#include -#include -#include - -#include -#include - -/** - * #define BITDHT_DEBUG 1 -**/ - -void bdStdRandomId(bdId *id) -{ - bdStdRandomNodeId(&(id->id)); - id->addr.sin_addr.s_addr = bdRandom::random_u32(); - id->addr.sin_port = (bdRandom::random_u32() % USHRT_MAX); - - return; -} - -void bdStdRandomNodeId(bdNodeId *id) -{ - uint32_t *a_data = (uint32_t *) id->data; - for(int i = 0; i < BITDHT_KEY_INTLEN; i++) - { - a_data[i] = bdRandom::random_u32(); - } - return; -} - -void bdStdZeroNodeId(bdNodeId *id) -{ - uint32_t *a_data = (uint32_t *) id->data; - for(int i = 0; i < BITDHT_KEY_INTLEN; i++) - { - a_data[i] = 0; - } - return; -} - -// Ignore differences in port.... -// must be careful which one we accept after this. -// can could end-up with the wrong port. -// However this only matters with firewalled peers anyway. -// So not too serious. -bool bdStdSimilarId(const bdId *n1, const bdId *n2) -{ - if (n1->id == n2->id) - { - if (n1->addr.sin_addr.s_addr == n2->addr.sin_addr.s_addr) - { - return true; - } - } - return false; -} - -bool bdStdUpdateSimilarId(bdId *dest, const bdId *src) -{ - /* only difference that's currently allowed */ - if (dest->addr.sin_port == src->addr.sin_port) - { - /* no update required */ - return false; - } - - dest->addr.sin_port = src->addr.sin_port; - return true; -} - - -/* fills in bdNodeId r, with XOR of a and b */ -int bdStdDistance(const bdNodeId *a, const bdNodeId *b, bdMetric *r) -{ - uint8_t *a_data = (uint8_t *) a->data; - uint8_t *b_data = (uint8_t *) b->data; - uint8_t *ans = (uint8_t *) r->data; - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - *(ans++) = *(a_data++) ^ *(b_data++); - } - return 1; -} - -void bdStdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *midId) -{ - bdMetric dist; - - /* get distance between a & c */ - bdStdDistance(target, other, &dist); - - /* generate Random Id */ - bdStdRandomNodeId(midId); - - /* zero bits of Random Id until under 1/2 of distance - * done in bytes for ease... matches one extra byte than distance = 0 - * -> hence wierd order of operations - */ - //bool done = false; - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - midId->data[i] = target->data[i]; - - if (dist.data[i] != 0) - break; - } -} - -int bdStdLoadNodeId(bdNodeId *id, std::string input) -{ - uint8_t *a_data = (uint8_t *) id->data; - uint32_t reqlen = BITDHT_KEY_LEN * 2; - if (input.size() < reqlen) - { - return 0; - } - - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - char ch1 = input[2 * i]; - char ch2 = input[2 * i + 1]; - uint8_t value1 = 0; - uint8_t value2 = 0; - - /* do char1 */ - if (ch1 >= '0' && ch1 <= '9') - value1 = (ch1 - '0'); - else if (ch1 >= 'A' && ch1 <= 'F') - value1 = (ch1 - 'A' + 10); - else if (ch1 >= 'a' && ch1 <= 'f') - value1 = (ch1 - 'a' + 10); - - /* do char2 */ - if (ch2 >= '0' && ch2 <= '9') - value2 = (ch2 - '0'); - else if (ch2 >= 'A' && ch2 <= 'F') - value2 = (ch2 - 'A' + 10); - else if (ch2 >= 'a' && ch2 <= 'f') - value2 = (ch2 - 'a' + 10); - - a_data[i] = (value1 << 4) + value2; - } - return 1; -} - -std::string bdStdConvertToPrintable(std::string input) -{ - std::string out; - for(uint32_t i = 0; i < input.length(); i++) - { - /* sensible chars */ - if ((input[i] > 31) && (input[i] < 127)) - { - out += input[i]; - } - else - { - bd_sprintf_append(out, "[0x%x]", (uint32_t) input[i]); - } - } - return out; -} - -void bdStdPrintNodeId(std::ostream &out, const bdNodeId *a) -{ - std::string s; - bdStdPrintNodeId(s, a, true); - out << s; -} - -void bdStdPrintNodeId(std::string &out, const bdNodeId *a, bool append) -{ - if (!append) - { - out.clear(); - } - - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - bd_sprintf_append(out, "%02x", (uint32_t) (a->data)[i]); - } -} - -void bdStdPrintId(std::ostream &out, const bdId *a) -{ - std::string s; - bdStdPrintId(s, a, false); - out << s; -} - -void bdStdPrintId(std::string &out, const bdId *a, bool append) -{ - bdStdPrintNodeId(out, &(a->id), append); - bd_sprintf_append(out, " ip:%s:%u", bdnet_inet_ntoa(a->addr.sin_addr).c_str(), ntohs(a->addr.sin_port)); -} - -/* returns 0-160 depending on bucket */ -int bdStdBucketDistance(const bdNodeId *a, const bdNodeId *b) -{ - bdMetric m; - bdStdDistance(a, b, &m); - return bdStdBucketDistance(&m); -} - -/* returns 0-160 depending on bucket */ -int bdStdBucketDistance(const bdMetric *m) -{ - for(int i = 0; i < BITDHT_KEY_BITLEN; i++) - { - int bit = BITDHT_KEY_BITLEN - i - 1; - int byte = i / 8; - int bbit = 7 - (i % 8); - unsigned char comp = (1 << bbit); - -#ifdef BITDHT_DEBUG - fprintf(stderr, "bdStdBucketDistance: bit:%d byte:%d bbit:%d comp:%x, data:%x\n", bit, byte, bbit, comp, m->data[byte]); -#endif - - if (comp & m->data[byte]) - { - return bit; - } - } - return 0; -} - - -bdStdDht::bdStdDht() -{ - return; -} - /* setup variables */ -uint16_t bdStdDht::bdNumBuckets() -{ - - return BITDHT_STANDARD_N_BUCKETS; -} - -uint16_t bdStdDht::bdNodesPerBucket() /* used for bdspace */ -{ - return BITDHT_STANDARD_BUCKET_SIZE; -} - -uint16_t bdStdDht::bdNumQueryNodes() /* used for queries */ -{ - return BITDHT_STANDARD_BUCKET_SIZE; -} - -uint16_t bdStdDht::bdBucketBitSize() -{ - return BITDHT_STANDARD_BUCKET_SIZE_BITS; -} - -int bdStdDht::bdDistance(const bdNodeId *n1, const bdNodeId *n2, class bdMetric *metric) -{ - return bdStdDistance(n1, n2, metric); -} - -int bdStdDht::bdBucketDistance(const bdNodeId *n1, const bdNodeId *n2) -{ - return bdStdBucketDistance(n1, n2); -} - -int bdStdDht::bdBucketDistance(const bdMetric *metric) -{ - return bdStdBucketDistance(metric); -} - - -bool bdStdDht::bdSimilarId(const bdId *id1, const bdId *id2) -{ - return bdStdSimilarId(id1, id2); -} - - -bool bdStdDht::bdUpdateSimilarId(bdId *dest, const bdId *src) -{ - return bdStdUpdateSimilarId(dest, src); -} - - -void bdStdDht::bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid) -{ - return bdStdRandomMidId(target, other, mid); -} - - -void bdStdDht::bdPrintId(std::ostream &out, const bdId *a) -{ - return bdStdPrintId(out, a); -} - -void bdStdDht::bdPrintNodeId(std::ostream &out, const bdNodeId *a) -{ - return bdStdPrintNodeId(out, a); -} - - -/**************************/ - -bdModDht::bdModDht() - :mNodesPerBucket(BITDHT_STANDARD_BUCKET_SIZE) -{ - return; -} - -void bdModDht::setNodesPerBucket(uint16_t nodesPerBucket) -{ - mNodesPerBucket = nodesPerBucket; - return; -} - - -uint16_t bdModDht::bdNodesPerBucket() /* used for bdspace */ -{ - return mNodesPerBucket; -} - - diff --git a/libbitdht/src/bitdht/bdstddht.h b/libbitdht/src/bitdht/bdstddht.h deleted file mode 100644 index d38c19724..000000000 --- a/libbitdht/src/bitdht/bdstddht.h +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - * bitdht/bdstddht.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_STANDARD_DHT_H -#define BITDHT_STANDARD_DHT_H - -#include "bitdht/bdiface.h" - -#define BITDHT_STANDARD_BUCKET_SIZE 10 // 20 too many per query? -#define BITDHT_STANDARD_BUCKET_SIZE_BITS 5 - -#define BITDHT_STANDARD_N_BUCKETS BITDHT_KEY_BITLEN - -#include -#include -#include -#include - - - - -void bdStdRandomNodeId(bdNodeId *id); -void bdStdZeroNodeId(bdNodeId *id); - -void bdStdRandomId(bdId *id); -int bdStdDistance(const bdNodeId *a, const bdNodeId *b, bdMetric *r); -int bdStdBucketDistance(const bdMetric *m); -int bdStdBucketDistance(const bdNodeId *a, const bdNodeId *b); - -void bdStdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid); - -int bdStdLoadNodeId(bdNodeId *id, std::string input); - -void bdStdPrintId(std::ostream &out, const bdId *a); -void bdStdPrintId(std::string &out, const bdId *a, bool append); -void bdStdPrintNodeId(std::ostream &out, const bdNodeId *a); -void bdStdPrintNodeId(std::string &out, const bdNodeId *a, bool append); - -std::string bdStdConvertToPrintable(std::string input); - -//uint32_t bdStdSimilarNode(const bdId*, const bdId*); - - -class bdStdDht: public bdDhtFunctions -{ - public: - - bdStdDht(); - /* setup variables */ -virtual uint16_t bdNumBuckets(); -virtual uint16_t bdNodesPerBucket(); /* used for bdspace */ -virtual uint16_t bdNumQueryNodes(); /* used for queries */ -virtual uint16_t bdBucketBitSize(); - -virtual int bdDistance(const bdNodeId *n1, const bdNodeId *n2, bdMetric *metric); -virtual int bdBucketDistance(const bdNodeId *n1, const bdNodeId *n2); -virtual int bdBucketDistance(const bdMetric *metric); - -virtual bool bdSimilarId(const bdId *id1, const bdId *id2); -virtual bool bdUpdateSimilarId(bdId *dest, const bdId *src); /* returns true if update was necessary */ - -virtual void bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid); - -virtual void bdPrintId(std::ostream &out, const bdId *a); -virtual void bdPrintNodeId(std::ostream &out, const bdNodeId *a); - -}; - -class bdModDht: public bdStdDht -{ - public: - bdModDht(); -virtual void setNodesPerBucket(uint16_t nodesPerBucket); -virtual uint16_t bdNodesPerBucket(); /* used for bdspace */ - - private: - uint16_t mNodesPerBucket; -}; - - -#endif - diff --git a/libbitdht/src/bitdht/bdstore.cc b/libbitdht/src/bitdht/bdstore.cc deleted file mode 100644 index 2cce6840c..000000000 --- a/libbitdht/src/bitdht/bdstore.cc +++ /dev/null @@ -1,269 +0,0 @@ -/******************************************************************************* - * bitdht/bdstore.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bitdht/bdstore.h" -#include "util/bdnet.h" -#include "util/bdfile.h" - -#include -#include - -//#define DEBUG_STORE 1 - -bdStore::bdStore(std::string file, std::string backupfile, bdDhtFunctions *fns) - :mFns(fns) -{ -#ifdef DEBUG_STORE - std::cerr << "bdStore::bdStore(" << file << ")"; - std::cerr << std::endl; -#endif - - /* read data from file */ - mStoreFile = file; - mStoreFileBak = backupfile; - - reloadFromStore(); -} - -int bdStore::clear() -{ - mIndex = 0; - store.clear(); - return 1; -} - -int bdStore::reloadFromStore() -{ - int result = reloadFromStore(mStoreFile); - if( result != 0 && store.size() > 0){ - return result; - } else if(mStoreFileBak != "") { //Nothing loaded, try the backup file - return reloadFromStore(mStoreFileBak); - } else { - return 0; - } -} - -int bdStore::reloadFromStore(std::string file) -{ - clear(); - - FILE *fd = fopen(file.c_str(), "r"); - if (!fd) - { - fprintf(stderr, "Failed to Open File: %s ... No Peers\n", file.c_str()); - return 0; - } - - - char line[10240]; - char addr_str[10240]; - struct sockaddr_in addr; - addr.sin_family = PF_INET; - unsigned short port; - - while(line == fgets(line, 10240, fd)) - { - if (2 == sscanf(line, "%s %hd", addr_str, &port)) - { - if (bdnet_inet_aton(addr_str, &(addr.sin_addr))) - { - addr.sin_port = htons(port); - bdPeer peer; - bdZeroNodeId(&(peer.mPeerId.id)); - peer.mPeerId.addr = addr; - peer.mLastSendTime = 0; - peer.mLastRecvTime = 0; - store.push_back(peer); -#ifdef DEBUG_STORE - fprintf(stderr, "Read: %s %d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); -#endif - } - } - } - - fclose(fd); - -#ifdef DEBUG_STORE - fprintf(stderr, "Read %ld Peers\n", (long) store.size()); -#endif - - return 1; - -} - -// This is a very ugly function! -int bdStore::getPeer(bdPeer *peer) -{ -#ifdef DEBUG_STORE - fprintf(stderr, "bdStore::getPeer() %ld Peers left\n", (long) store.size()); -#endif - - std::list::iterator it; - int i = 0; - for(it = store.begin(); (it != store.end()) && (i < mIndex); it++, i++) ; /* empty loop */ - if (it != store.end()) - { - *peer = *it; - mIndex++; - return 1; - } - return 0; -} - -int bdStore::filterIpList(const std::list &filteredIPs) -{ - // Nasty O(n^2) iteration over 500 entries!!!. - // hope its not used to often. - - std::list::const_iterator it; - for(it = filteredIPs.begin(); it != filteredIPs.end(); it++) - { - std::list::iterator sit; - for(sit = store.begin(); sit != store.end();) - { - if (it->sin_addr.s_addr == sit->mPeerId.addr.sin_addr.s_addr) - { - std::cerr << "bdStore::filterIpList() Found Bad entry in Store. Erasing!"; - std::cerr << std::endl; - - sit = store.erase(sit); - } - else - { - sit++; - } - } - } - return 1; -} - - - -#define MAX_ENTRIES 500 - - /* maintain a sorted list */ -void bdStore::addStore(bdPeer *peer) -{ -#ifdef DEBUG_STORE - std::cerr << "bdStore::addStore() "; - mFns->bdPrintId(std::cerr, &(peer->mPeerId)); - std::cerr << std::endl; -#endif - - /* remove old entry */ - - std::list::iterator it; - for(it = store.begin(); it != store.end(); ) - { - if ((it->mPeerId.addr.sin_addr.s_addr == peer->mPeerId.addr.sin_addr.s_addr) && - (it->mPeerId.addr.sin_port == peer->mPeerId.addr.sin_port)) - { -#ifdef DEBUG_STORE - std::cerr << "bdStore::addStore() Removed Existing Entry: "; - mFns->bdPrintId(std::cerr, &(it->mPeerId)); - std::cerr << std::endl; -#endif - it = store.erase(it); - } - else - { - it++; - } - } - -#ifdef DEBUG_STORE - std::cerr << "bdStore::addStore() Push_back"; - std::cerr << std::endl; -#endif - store.push_back(*peer); - - while(store.size() > MAX_ENTRIES) - { -#ifdef DEBUG_STORE - std::cerr << "bdStore::addStore() pop_front()"; - std::cerr << std::endl; -#endif - store.pop_front(); - } -} - -void bdStore::writeStore(std::string file) -{ - /* write out store */ -#ifdef DEBUG_STORE - fprintf(stderr, "bdStore::writeStore(%s) = %d entries\n", file.c_str(), store.size()); -#endif - - if (store.size() < 0.9 * MAX_ENTRIES) - { - /* don't save yet! */ -#ifdef DEBUG_STORE - fprintf(stderr, "bdStore::writeStore() Delaying until more entries\n"); -#endif - return; - } - - std::string filetmp = file + ".tmp" ; - - FILE *fd = fopen(filetmp.c_str(), "w"); - - if (!fd) - { -#ifdef DEBUG_STORE -#endif - fprintf(stderr, "bdStore::writeStore() FAILED to Open File\n"); - return; - } - - std::list::iterator it; - for(it = store.begin(); it != store.end(); it++) - { - fprintf(fd, "%s %d\n", bdnet_inet_ntoa(it->mPeerId.addr.sin_addr).c_str(), ntohs(it->mPeerId.addr.sin_port)); -#ifdef DEBUG_STORE - fprintf(stderr, "Storing Peer Address: %s %d\n", inet_ntoa(it->mPeerId.addr.sin_addr), ntohs(it->mPeerId.addr.sin_port)); -#endif - - } - fclose(fd); - - if(!bdFile::renameFile(filetmp,file)) - std::cerr << "Could not rename file !!" << std::endl; -#ifdef DEBUG_STORE - else - std::cerr << "Successfully renamed file " << filetmp << " to " << file << std::endl; -#endif -} - -void bdStore::writeStore() -{ -#if 0 - if (mStoreFile == "") - { - return; - } -#endif - return writeStore(mStoreFile); -} - - - diff --git a/libbitdht/src/bitdht/bdstore.h b/libbitdht/src/bitdht/bdstore.h deleted file mode 100644 index 2202f0553..000000000 --- a/libbitdht/src/bitdht/bdstore.h +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * bitdht/bdstore.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_STORE_H -#define BITDHT_STORE_H - -#include -#include "bitdht/bdiface.h" -#include "bitdht/bdpeer.h" - -class bdStore -{ -public: - - bdStore(std::string file, std::string backupfile, bdDhtFunctions *fns); - - int reloadFromStore(); /* for restarts */ - int reloadFromStore(std::string file); - int filterIpList(const std::list &filteredIPs); - int clear(); - - int getPeer(bdPeer *peer); - void addStore(bdPeer *peer); - void writeStore(std::string file); - void writeStore(); - -protected: - std::string mStoreFile; - std::string mStoreFileBak; - std::list store; - int mIndex; - bdDhtFunctions *mFns; -}; - - -#endif diff --git a/libbitdht/src/bitdht/bencode.c b/libbitdht/src/bitdht/bencode.c deleted file mode 100644 index a496f5bc3..000000000 --- a/libbitdht/src/bitdht/bencode.c +++ /dev/null @@ -1,649 +0,0 @@ -/******************************************************************************* - * bitdht/bdencode.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * by Mike Frysinger * - * * - * 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 . * - * * - *******************************************************************************/ - -/* - * This implementation isn't optimized at all as I wrote it to support - * a bogus system. I have no real interest in this format. Feel free - * to send me patches (so long as you don't copyright them and you release - * your changes into the public domain as well). - */ - -#include -#include /* malloc() realloc() free() strtoll() */ -#include /* memset() */ -#include "util/bdstring.h" - -#include "bitdht/bencode.h" - -/*** - * #define BE_DEBUG_DECODE 1 - * #define BE_DEBUG 1 // controlled from Makefile too. - ***/ - -#ifdef BE_DEBUG_DECODE - #include /* debug */ -#endif - -static be_node *be_alloc(be_type type) -{ - be_node *ret = (be_node *) malloc(sizeof(*ret)); - if (ret) { - memset(ret, 0x00, sizeof(*ret)); - ret->type = type; - } - return ret; -} - -static long long _be_decode_int(const char **data, long long *data_len) -{ - char *endp; - long long ret = strtoll(*data, &endp, 10); - *data_len -= (endp - *data); - *data = endp; - -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_int(pnt: %p, rem: %lld) = %lld\n", *data, *data_len, ret); -#endif - return ret; -} - -long long be_str_len(be_node *node) -{ - long long ret = 0; - if (node->val.s) - memcpy(&ret, node->val.s - sizeof(ret), sizeof(ret)); - return ret; -} - -static char *_be_decode_str(const char **data, long long *data_len) -{ -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_str(pnt: %p, rem: %lld)\n", *data, *data_len); -#endif - long long sllen = _be_decode_int(data, data_len); - long slen = sllen; - unsigned long len; - char *ret = NULL; - - /* slen is signed, so negative values get rejected */ - if (sllen < 0) - { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_str() reject bad length\n"); -#endif - return ret; - } - - /* reject attempts to allocate large values that overflow the - * size_t type which is used with malloc() - */ - if (sizeof(long long) != sizeof(long)) - if (sllen != slen) - { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_str() reject large_values\n"); -#endif - return ret; - } - - /* make sure we have enough data left */ - if (sllen > *data_len - 1) - { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_str() reject large_values\n"); -#endif - return ret; - } - - /* switch from signed to unsigned so we don't overflow below */ - len = slen; - - if (**data == ':') { - char *_ret = (char *) malloc(sizeof(sllen) + len + 1); - - if(_ret == NULL) - { - fprintf(stderr, "(EE) bencode::_be_decode_str(): " - "ERROR. cannot allocate memory for %lu bytes.\n" - , len+1+sizeof(sllen) ); - return ret; - } - - memcpy(_ret, &sllen, sizeof(sllen)); - ret = _ret + sizeof(sllen); - memcpy(ret, *data + 1, len); - ret[len] = '\0'; - *data += len + 1; - *data_len -= len + 1; - -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_str() read %ld bytes\n", len+1); -#endif - } - else - { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_str() reject missing :\n"); -#endif - } - return ret; -} - -static be_node *_be_decode(const char **data, long long *data_len) -{ -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode(pnt: %p, rem: %lld)\n", *data, *data_len); -#endif - be_node *ret = NULL; - - if (!*data_len) - { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() reject invalid datalen\n"); -#endif - return ret; - } - - switch (**data) { - /* lists */ - case 'l': { - unsigned int i = 0; -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() found list\n"); -#endif - - ret = be_alloc(BE_LIST); - - --(*data_len); - ++(*data); - while (**data != 'e') { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() list get item (%d)\n", i); -#endif - ret->val.l = (be_node **) realloc(ret->val.l, (i + 2) * sizeof(*ret->val.l)); - ret->val.l[i] = _be_decode(data, data_len); - if (ret->val.l[i] == NULL) - { - /* failed decode - kill decode */ -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() failed list decode - kill\n"); -#endif - be_free(ret); - return NULL; - } - ++i; - } - --(*data_len); - ++(*data); - - /* empty list case. */ - if (i == 0) - { - ret->val.l = (be_node **) realloc(ret->val.l, 1 * sizeof(*ret->val.l)); - } - - ret->val.l[i] = NULL; - - return ret; - } - - /* dictionaries */ - case 'd': { - unsigned int i = 0; -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() found dictionary\n"); -#endif - - ret = be_alloc(BE_DICT); - - --(*data_len); - ++(*data); - while (**data != 'e') { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() dictionary get key (%d)\n", i); -#endif - ret->val.d = (be_dict *) realloc(ret->val.d, (i + 2) * sizeof(*ret->val.d)); - ret->val.d[i].key = _be_decode_str(data, data_len); -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() dictionary get val\n"); -#endif - ret->val.d[i ].val = _be_decode(data, data_len); - ret->val.d[i+1].val = NULL ; // ensures termination of loops based on 0x0 value, otherwise, uninitialized - // memory occurs if(ret->val.d[i].key == 0x0 && ret->val.d[i].val != NULL) - // when calling be_free 8 lines below this point... - - if ((ret->val.d[i].key == NULL) || (ret->val.d[i].val == NULL)) - { - /* failed decode - kill decode */ -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() failed dict decode - kill\n"); -#endif - be_free(ret); - return NULL; - } - ++i; - } - --(*data_len); - ++(*data); - - /* empty dictionary case. */ - if (i == 0) - { - ret->val.d = (be_dict *) realloc(ret->val.d, 1 * sizeof(*ret->val.d)); - } - - - ret->val.d[i].val = NULL; - return ret; - } - - /* integers */ - case 'i': { - ret = be_alloc(BE_INT); -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() found int\n"); -#endif - - --(*data_len); - ++(*data); - ret->val.i = _be_decode_int(data, data_len); - if (**data != 'e') - { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() reject data != e - kill\n"); -#endif - be_free(ret); - return NULL; - } - --(*data_len); - ++(*data); - - return ret; - } - - /* byte strings */ - case '0'...'9': { - ret = be_alloc(BE_STR); -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() found string\n"); -#endif - - ret->val.s = _be_decode_str(data, data_len); - - return ret; - } - - /* invalid */ - default: -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() found invalid - kill\n"); -#endif - return NULL; - break; - } - - return ret; -} - -be_node *be_decoden(const char *data, long long len) -{ - return _be_decode(&data, &len); -} - -be_node *be_decode(const char *data) -{ - return be_decoden(data, strlen(data)); -} - -static inline void _be_free_str(char *str) -{ - if (str) - free(str - sizeof(long long)); -} -void be_free(be_node *node) -{ - switch (node->type) { - case BE_STR: - _be_free_str(node->val.s); - break; - - case BE_INT: - break; - - case BE_LIST: { - unsigned int i; - for (i = 0; node->val.l[i]; ++i) - be_free(node->val.l[i]); - free(node->val.l); - break; - } - - case BE_DICT: { - unsigned int i; - for (i = 0; node->val.d[i].val; ++i) { - _be_free_str(node->val.d[i].key); - be_free(node->val.d[i].val); - } - free(node->val.d); - break; - } - } - free(node); -} - -#ifdef BE_DEBUG -#include -#include - -static void _be_dump_indent(ssize_t indent) -{ - while (indent-- > 0) - printf(" "); -} -static void _be_dump(be_node *node, ssize_t indent) -{ - size_t i; - - _be_dump_indent(indent); - indent = abs(indent); - - switch (node->type) { - case BE_STR: - be_dump_str(node); - //printf("str = %s (len = %lli)\n", node->val.s, be_str_len(node)); - break; - - case BE_INT: - printf("int = %lli\n", node->val.i); - break; - - case BE_LIST: - puts("list ["); - - for (i = 0; node->val.l[i]; ++i) - _be_dump(node->val.l[i], indent + 1); - - _be_dump_indent(indent); - puts("]"); - break; - - case BE_DICT: - puts("dict {"); - - for (i = 0; node->val.d[i].val; ++i) { - _be_dump_indent(indent + 1); - printf("%s => ", node->val.d[i].key); - _be_dump(node->val.d[i].val, -(indent + 1)); - } - - _be_dump_indent(indent); - puts("}"); - break; - } -} -void be_dump(be_node *node) -{ - _be_dump(node, 0); -} - -void be_dump_str(be_node *node) -{ - if (node->type != BE_STR) - { - printf("be_dump_str(): error not a string\n"); - return; - } - - int len = be_str_len(node); - int i = 0; - printf("str[%d] = ", len); - for(i = 0; i < len; i++) - { - /* sensible chars */ - if ((node->val.s[i] > 31) && (node->val.s[i] < 127)) - { - printf("%c", node->val.s[i]); - } - else - { - printf("[%d]", node->val.s[i]); - } - } - printf("\n"); -} - - -#endif - -/******************** New Functions added by drBob ************* - * Output bencode - * - */ - -int be_encode(be_node *node, char *str, int len) -{ - size_t i; - int loc = 0; - - switch (node->type) { - case BE_STR: - bd_snprintf(str, len, "%lli:", be_str_len(node)); - loc += strlen(&(str[loc])); - - memcpy(&(str[loc]), node->val.s, be_str_len(node)); - loc += be_str_len(node); - break; - - case BE_INT: - bd_snprintf(str, len, "i%llie", node->val.i); - loc += strlen(&(str[loc])); - break; - - case BE_LIST: - - snprintf(str, len, "l"); - loc += 1; - - for (i = 0; node->val.l[i]; ++i) - { - loc += be_encode(node->val.l[i], &(str[loc]), len-loc); - } - - snprintf(&(str[loc]), len - loc, "e"); - loc += 1; - - break; - - case BE_DICT: - snprintf(str, len, "d"); - loc += 1; - - for (i = 0; node->val.d[i].val; ++i) { - - /* assumption that key must be ascii! */ - snprintf(&(str[loc]), len-loc, "%i:%s", - (int) strlen(node->val.d[i].key), - node->val.d[i].key); - loc += strlen(&(str[loc])); - loc += be_encode(node->val.d[i].val, &(str[loc]), len-loc); - } - - snprintf(&(str[loc]), len - loc, "e"); - loc += 1; - - break; - } - return loc; -} - -/* hackish way to create nodes! */ -be_node *be_create_dict() -{ - be_node *n = be_decode("de"); - return n; -} - - -be_node *be_create_list() -{ - be_node *n = be_decode("le"); - return n; -} - -be_node *be_create_str(const char *str) -{ - - /* must */ - be_node *n = NULL; - int len = strlen(str); - long long int sllen = len; - char *_ret = (char *) malloc(sizeof(sllen) + len + 1); - if(_ret == NULL) - { - fprintf(stderr, "(EE) bencode::be_create_str(): " - "ERROR. cannot allocate memory for %lu bytes.\n" - , len+1+sizeof(sllen) ); - return n; - } - char *ret = NULL; - n = be_alloc(BE_STR); - - memcpy(_ret, &sllen, sizeof(sllen)); - ret = _ret + sizeof(sllen); - memcpy(ret, str, len); - ret[len] = '\0'; - - n->val.s = ret; - - return n; -} - -be_node *be_create_str_wlen(const char *str, int len) /* not including \0 */ -{ - - /* must */ - be_node *n = NULL; - long long int sllen = len; - char *_ret = (char *) malloc(sizeof(sllen) + len + 1); - if(_ret == NULL) - { - fprintf(stderr, "(EE) bencode::be_create_str_wlen(): " - "ERROR. cannot allocate memory for %lu bytes.\n" - , len+1+sizeof(sllen) ); - return n; - } - char *ret = NULL; - n = be_alloc(BE_STR); - - memcpy(_ret, &sllen, sizeof(sllen)); - ret = _ret + sizeof(sllen); - memcpy(ret, str, len); - ret[len] = '\0'; - - n->val.s = ret; - - return n; -} - -be_node *be_create_int(long long int num) -{ - /* must */ - be_node *n = be_alloc(BE_INT); - n->val.i = num; - return n; -} - -int be_add_keypair(be_node *dict, const char *str, be_node *node) -{ - int i = 0; - - /* only if dict type */ - if (dict->type != BE_DICT) - { - return 0; - } - - // get to end of dict. - for(i = 0; dict->val.d[i].val; i++) - ;//Silent empty body for loop for clang - - //fprintf(stderr, "be_add_keypair() i = %d\n",i); - - /* realloc space */ - dict->val.d = (be_dict *) realloc(dict->val.d, (i + 2) * sizeof(*dict->val.d)); - - /* stupid key storage system */ - int len = strlen(str); - long long int sllen = len; - char *_ret = (char *) malloc(sizeof(sllen) + len + 1); - if(_ret == NULL) - { - fprintf(stderr, "(EE) bencode::be_create_str_wlen(): " - "ERROR. cannot allocate memory for %lu bytes.\n" - , len+1+sizeof(sllen) ); - return 0; - } - char *ret = NULL; - - //fprintf(stderr, "be_add_keypair() key len = %d\n",len); - - memcpy(_ret, &sllen, sizeof(sllen)); - ret = _ret + sizeof(sllen); - memcpy(ret, str, len); - ret[len] = '\0'; - - dict->val.d[i].key = ret; - dict->val.d[i].val = node; - i++; - dict->val.d[i].val = NULL; - - return 1; -} - - -int be_add_list(be_node *list, be_node *node) -{ - int i = 0; - - /* only if dict type */ - if (list->type != BE_LIST) - { - return 0; - } - - // get to end of dict. - for(i = 0; list->val.l[i]; i++) - ;//Silent empty body for loop for clang - - /* realloc space */ - list->val.l = (be_node **) realloc(list->val.l, (i + 2) * sizeof(*list->val.l)); - list->val.l[i] = node; - ++i; - list->val.l[i] = NULL; - - return 1; -} - - - - diff --git a/libbitdht/src/bitdht/bencode.h b/libbitdht/src/bitdht/bencode.h deleted file mode 100644 index 4e733b66f..000000000 --- a/libbitdht/src/bitdht/bencode.h +++ /dev/null @@ -1,92 +0,0 @@ -/******************************************************************************* - * bitdht/bdencode.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * by Mike Frysinger * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef _BENCODE_H -#define _BENCODE_H - -/* USAGE: - * - pass the string full of the bencoded data to be_decode() - * - parse the resulting tree however you like - * - call be_free() on the tree to release resources - */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - BE_STR, - BE_INT, - BE_LIST, - BE_DICT, -} be_type; - -struct be_dict; -struct be_node; - -/* - * XXX: the "val" field of be_dict and be_node can be confusing ... - */ - -typedef struct be_dict { - char *key; - struct be_node *val; -} be_dict; - -typedef struct be_node { - be_type type; - union { - char *s; - long long i; - struct be_node **l; - struct be_dict *d; - } val; -} be_node; - -extern long long be_str_len(be_node *node); -// This function uses strlen, so is unreliable. -//extern be_node *be_decode(const char *bencode); -extern be_node *be_decoden(const char *bencode, long long bencode_len); -extern void be_free(be_node *node); -extern void be_dump(be_node *node); -extern void be_dump_str(be_node *node); - -// New Functions for the other half of the work - encoding */ - -extern int be_encode(be_node *node, char *str, int len); - - -// Creating the data structure. -extern int be_add_list(be_node *list, be_node *node); -extern int be_add_keypair(be_node *dict, const char *str, be_node *node); -extern be_node *be_create_int(long long int num); -extern be_node *be_create_list(); -extern be_node *be_create_str(const char *str); -extern be_node *be_create_str_wlen(const char *str, int len); /* not including \0 */ -extern be_node *be_create_dict(); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libbitdht/src/example/bdboot.txt b/libbitdht/src/example/bdboot.txt deleted file mode 100644 index 1d0d204af..000000000 --- a/libbitdht/src/example/bdboot.txt +++ /dev/null @@ -1,500 +0,0 @@ -77.196.18.56 22750 -77.84.97.16 31837 -213.174.60.46 17919 -50.113.92.209 6881 -184.89.243.73 43344 -210.195.47.196 19861 -83.49.197.212 61627 -184.145.109.37 31067 -180.18.98.235 29543 -186.254.61.185 40200 -78.213.113.102 9182 -89.92.251.113 16946 -195.240.45.224 6881 -188.142.164.252 43063 -41.45.41.123 18636 -219.84.184.204 61337 -95.26.91.94 6881 -79.114.193.207 17966 -83.213.185.157 43235 -37.110.127.110 6881 -178.35.204.111 6881 -174.48.201.143 41918 -109.214.57.82 1042 -121.214.57.226 51413 -90.184.93.164 22828 -98.214.166.21 38072 -50.0.146.178 51413 -81.13.253.217 46370 -81.249.29.121 7812 -92.80.201.189 20026 -95.37.18.51 59118 -50.53.143.88 57568 -180.183.213.112 11823 -112.206.13.117 41825 -79.169.77.54 63189 -76.174.205.156 8605 -2.1.187.15 50269 -175.151.131.80 16001 -82.7.124.219 12334 -217.209.125.15 26155 -93.181.201.89 54631 -197.87.68.102 25317 -183.109.112.49 58359 -203.198.141.201 7453 -82.192.32.151 58864 -184.146.76.179 13586 -37.107.121.203 18429 -186.54.1.246 38354 -184.18.8.33 8784 -77.101.130.178 61762 -109.8.154.28 19120 -74.96.156.188 31749 -94.96.167.130 64130 -93.81.126.53 6881 -79.136.243.46 46486 -78.29.75.248 6881 -114.42.47.178 9089 -31.147.61.11 23853 -193.253.220.184 6881 -80.57.45.239 28239 -72.192.215.39 30028 -91.74.119.134 49246 -85.250.43.217 41490 -188.176.218.22 35407 -98.119.4.86 1024 -89.143.138.33 64606 -46.138.37.148 59039 -178.120.85.170 24550 -67.185.95.9 32173 -98.197.42.116 19866 -114.38.21.113 7694 -77.46.26.128 38127 -93.80.96.134 23683 -60.241.209.107 57588 -171.97.173.243 9327 -50.43.117.21 42660 -87.244.169.128 55807 -94.190.105.157 6881 -178.122.199.251 16480 -76.88.254.191 27137 -112.120.144.128 60152 -77.249.124.77 49187 -165.132.236.14 25390 -87.16.197.67 20787 -80.103.109.43 55260 -195.234.21.119 6881 -176.212.60.108 60378 -178.185.98.43 12420 -124.149.151.181 33603 -85.220.66.170 35131 -109.130.31.27 11460 -72.223.102.189 11614 -111.15.147.164 16001 -83.202.163.16 6881 -92.246.22.40 33576 -94.41.249.131 10613 -95.24.101.211 6881 -98.232.199.100 29721 -174.101.153.252 38195 -91.157.230.16 1885 -109.211.143.205 13722 -84.123.4.247 29043 -112.209.16.158 19102 -114.34.46.63 6881 -85.138.230.74 56197 -62.169.127.9 26665 -211.217.2.251 41870 -81.221.84.77 20214 -109.197.191.45 19604 -46.118.116.209 20711 -46.42.23.240 53559 -199.127.250.15 29015 -78.220.115.99 49482 -71.232.195.149 56530 -84.123.59.159 13963 -213.251.184.146 64347 -67.164.23.233 7119 -86.194.215.166 14316 -89.224.149.142 25365 -94.23.49.143 8000 -78.119.193.151 55227 -78.222.160.139 37995 -89.209.82.248 12425 -178.137.112.35 14571 -94.23.0.84 51582 -78.247.176.4 18105 -90.41.206.239 30502 -78.241.70.65 22014 -98.194.6.21 51413 -174.119.150.115 17065 -189.5.22.202 52412 -93.124.97.171 49001 -186.4.42.27 20837 -24.144.184.102 14888 -78.173.175.56 53453 -79.114.14.206 4602 -109.184.163.146 11789 -98.200.252.137 18502 -79.82.130.49 20757 -5.165.66.132 63326 -46.29.147.201 20232 -114.32.184.15 25962 -94.21.70.206 50541 -92.98.171.108 51413 -188.49.25.79 46883 -90.149.227.168 49241 -92.99.221.105 51405 -123.139.45.71 16001 -68.98.108.234 24290 -88.169.60.195 17108 -114.37.154.22 16120 -121.219.232.47 65073 -46.119.196.109 19075 -123.110.104.200 29499 -77.73.46.124 28966 -87.253.26.85 45934 -176.108.146.88 6881 -188.187.45.126 43757 -92.2.212.97 15078 -178.140.169.137 22922 -114.38.14.84 16958 -80.98.106.227 9773 -86.169.117.185 51938 -201.53.229.60 1041 -65.95.191.51 51413 -24.78.8.98 6884 -90.204.42.12 48402 -76.7.214.210 35875 -88.155.36.246 15856 -78.227.88.161 23191 -62.83.111.85 36398 -130.43.29.146 52526 -88.170.61.126 32761 -85.246.109.226 6890 -82.237.40.39 39052 -95.239.56.106 62200 -71.187.209.2 22274 -178.148.68.18 53318 -78.163.220.242 31758 -188.235.149.202 63083 -119.201.103.241 62715 -83.87.5.5 43317 -201.83.71.123 50579 -83.6.22.221 52512 -95.54.76.150 56930 -207.255.112.154 6881 -188.121.244.133 10980 -41.212.221.164 33050 -178.168.58.44 23476 -142.161.41.171 41788 -211.133.168.214 44631 -220.18.72.3 64774 -70.114.155.3 34892 -97.85.86.199 6890 -119.74.54.94 6881 -114.34.239.242 22647 -67.128.168.196 11524 -86.145.211.200 49330 -72.230.75.87 21095 -31.35.57.129 13924 -190.60.48.165 41301 -213.245.41.143 40018 -95.104.80.193 6881 -120.208.30.229 16001 -93.105.81.215 21000 -93.96.13.136 12181 -190.88.179.253 20701 -58.7.210.130 51413 -195.222.95.57 51413 -121.223.47.224 41563 -85.219.118.111 27483 -78.43.137.174 10409 -77.71.220.234 62357 -85.107.182.248 19486 -37.235.207.247 30166 -176.97.212.163 22523 -88.230.184.110 25432 -94.44.164.74 60966 -95.188.23.129 42927 -78.242.168.94 34153 -62.93.99.6 28010 -78.105.105.87 42127 -208.101.109.128 53329 -164.215.87.224 57073 -87.106.187.29 20277 -91.121.114.171 58846 -80.42.246.251 20502 -188.72.98.36 15503 -176.31.248.87 6338 -118.160.199.38 63400 -174.71.20.57 52193 -113.161.204.192 6881 -2.94.72.90 27587 -89.204.110.192 6881 -76.121.38.23 58982 -93.95.160.156 13118 -122.174.156.164 15004 -94.155.59.112 57833 -176.49.172.107 49001 -23.16.200.217 51413 -60.241.87.17 24478 -108.242.252.38 39304 -201.252.144.11 15506 -92.125.17.239 25548 -114.79.138.158 60635 -76.103.79.28 36151 -77.71.69.65 12087 -138.199.66.212 26174 -119.131.41.152 1231 -119.202.178.119 45249 -78.141.127.164 55618 -88.245.188.55 28097 -217.165.53.221 24579 -46.22.234.12 14916 -98.199.98.228 32970 -203.213.94.200 14161 -66.197.135.74 9870 -213.167.206.125 38106 -80.83.245.36 6993 -112.203.171.200 25932 -105.236.34.74 43961 -92.49.5.186 38678 -46.61.12.234 49001 -91.148.14.62 11206 -95.37.162.145 14476 -68.192.162.202 31159 -68.209.239.148 50375 -75.185.11.189 23993 -178.72.159.43 47954 -118.160.199.38 61182 -75.142.21.2 56117 -46.187.88.219 48529 -98.127.163.114 53062 -94.245.153.136 23040 -109.174.3.81 51413 -77.232.162.51 14257 -94.96.112.204 35187 -118.160.199.38 51651 -5.13.18.103 24121 -79.226.190.78 18189 -95.90.236.216 41463 -83.134.60.207 10267 -118.160.199.38 51532 -176.31.109.159 24586 -99.242.88.203 21704 -88.174.176.173 56969 -84.151.248.98 61500 -123.195.214.39 20846 -94.62.25.152 39020 -89.33.72.233 1398 -92.37.27.83 37375 -83.110.225.79 17257 -178.36.198.215 22849 -112.234.202.158 16001 -188.231.143.20 6881 -5.12.126.206 34538 -62.65.216.158 13414 -92.43.189.45 3140 -79.9.144.222 29037 -93.77.32.187 57408 -91.247.142.205 58199 -85.114.60.149 17582 -119.196.44.47 51763 -178.88.3.227 33031 -76.30.131.83 49366 -86.168.167.166 55451 -212.45.81.173 16427 -188.224.10.109 46059 -82.178.114.74 50836 -78.55.114.191 42839 -85.54.211.184 17283 -95.135.101.164 55829 -209.195.77.83 34603 -79.153.101.234 11154 -71.63.225.31 21053 -184.147.116.143 49025 -88.186.230.88 12048 -89.132.181.63 61498 -95.84.208.14 9372 -79.93.218.69 28681 -64.113.125.178 61127 -174.100.51.253 44460 -88.3.236.194 10926 -109.194.234.36 14342 -68.106.225.140 47417 -78.24.231.166 6881 -84.40.80.3 6890 -177.5.36.152 12588 -68.82.32.238 18307 -64.121.118.201 61270 -75.40.21.238 51413 -99.59.129.46 26141 -79.95.171.102 11092 -67.71.140.245 15582 -95.32.187.214 14778 -213.112.177.129 43304 -81.51.97.133 40039 -89.133.89.51 55846 -79.18.246.192 20356 -109.124.197.42 31559 -182.53.45.3 14895 -74.219.135.69 30239 -95.111.0.20 34295 -84.154.235.198 59678 -93.58.14.83 51413 -213.114.48.42 38511 -46.48.90.11 55025 -5.2.58.49 49001 -92.139.252.16 36535 -94.68.144.118 10009 -75.187.202.104 44822 -84.52.169.26 10838 -114.32.211.85 30116 -75.69.72.31 51413 -118.160.199.38 63151 -142.59.218.136 11300 -118.160.199.38 63619 -118.160.199.38 59277 -82.47.63.231 26035 -67.8.141.69 63990 -223.18.249.29 7221 -82.136.113.22 6881 -86.100.227.142 50497 -188.186.13.95 21313 -24.128.39.166 5223 -31.8.136.66 11996 -82.137.118.90 26474 -84.217.43.156 45620 -217.29.187.23 62523 -108.254.5.66 58192 -182.177.228.43 31532 -118.160.199.38 60134 -67.167.180.162 11451 -188.164.212.104 28566 -95.196.203.111 59402 -213.27.20.223 53410 -178.44.187.32 52209 -70.83.35.78 31982 -1.172.161.190 17526 -78.237.111.89 45254 -188.25.246.130 16313 -67.173.33.90 33134 -212.49.47.32 19949 -176.214.214.73 64892 -173.73.46.92 52828 -71.237.6.246 41304 -70.113.2.167 45645 -88.84.191.25 30536 -87.2.74.180 6783 -96.63.15.208 34651 -76.181.135.146 17016 -79.168.31.62 2622 -95.153.169.40 19697 -88.217.36.182 2924 -119.96.130.9 12038 -90.225.103.241 40066 -78.106.178.64 46183 -220.136.37.144 27075 -92.87.167.73 55624 -188.232.61.83 6881 -183.89.3.101 10618 -111.242.54.149 15979 -120.146.228.149 6881 -67.242.169.143 6886 -31.8.71.71 10170 -78.236.77.65 32026 -91.137.168.238 27616 -93.109.84.235 21443 -77.34.44.71 35691 -109.209.40.17 55542 -83.157.77.228 7812 -88.233.167.39 20620 -69.176.171.40 11254 -93.11.175.201 41027 -50.71.135.98 20332 -69.181.169.181 7313 -46.8.136.196 57085 -180.64.39.48 14708 -46.211.113.5 49001 -142.163.53.182 58144 -90.38.76.72 4699 -83.252.23.84 10699 -78.163.181.120 16519 -221.118.191.176 17563 -184.41.75.34 57537 -99.192.77.139 33333 -88.174.167.76 30032 -46.116.177.103 22754 -94.103.196.139 54378 -188.77.246.133 35496 -217.76.184.18 51413 -108.160.185.132 31530 -50.83.34.19 23846 -193.77.159.24 43611 -80.14.161.164 51789 -114.185.184.10 23151 -82.235.101.26 7816 -92.83.188.95 10477 -46.180.245.79 53580 -46.37.83.122 37389 -86.29.220.199 28527 -92.137.208.191 29253 -85.167.249.218 55649 -221.127.216.99 21461 -130.89.165.24 10110 -99.60.78.40 18894 -49.145.59.194 38935 -92.247.248.50 23666 -5.149.211.210 22277 -176.226.153.243 61967 -174.117.49.59 13052 -121.141.14.57 30323 -83.155.218.188 51413 -129.21.122.81 32785 -46.118.83.183 12324 -92.255.208.221 34798 -212.21.13.209 56909 -220.120.236.151 11393 -37.218.190.131 35691 -46.41.109.26 39584 -2.51.116.185 63433 -67.86.174.199 33605 -212.74.222.13 38345 -115.240.98.113 51413 -37.59.55.58 51413 -109.72.144.240 41290 -207.224.196.66 10731 -78.128.52.177 24574 -79.138.67.151 47942 -50.201.138.122 10228 -176.9.113.77 61059 -94.21.30.143 63448 -178.89.100.227 6881 -91.67.129.216 1210 -82.232.212.66 55826 -78.228.230.130 12577 -79.175.106.234 12684 -213.231.145.208 12306 -97.106.156.54 63552 -79.176.173.50 33043 -75.70.84.67 52856 -31.220.168.41 35190 -1.161.107.196 31811 -80.98.158.177 29436 -88.148.233.194 38081 -184.166.72.229 63472 -93.186.192.165 39020 -151.25.110.226 49289 -178.45.159.135 31825 -98.225.11.98 51769 -109.28.82.4 33620 -90.16.53.195 31338 -223.219.73.227 17107 -92.96.51.71 56237 -112.173.11.227 63314 -37.229.60.103 6881 -90.29.226.250 14329 -182.210.49.84 11993 -177.32.251.226 27655 -189.54.195.49 50555 diff --git a/libbitdht/src/example/bdhandler.cc b/libbitdht/src/example/bdhandler.cc deleted file mode 100644 index 0b8766a5a..000000000 --- a/libbitdht/src/example/bdhandler.cc +++ /dev/null @@ -1,349 +0,0 @@ -/* - * libretroshare/src/dht: bdhandler.h - * - * BitDht example interface - * - * Copyright 2009-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include -#include -#include -#include - -#include - -#include "bdhandler.h" - - -/**** - * This example bitdht app is designed to perform a single shot DHT search. - * Ww want to minimise the dht work, and number of UDP packets sent. - * - * This means we need to add: - * - don't search for App network. (libbitdht option) - * - don't bother filling up Space. (libbitdht option) - * - Programmatically add bootstrap peers. (libbitdht option) - * - */ - - - -/* This is a conversion callback class - */ - -class BdCallback: public BitDhtCallback -{ - public: - - BdCallback(BitDhtHandler *parent) - :mParent(parent) { return; } - -virtual int dhtNodeCallback(const bdId *id, uint32_t peerflags) -{ - return mParent->NodeCallback(id, peerflags); -} - -virtual int dhtPeerCallback(const bdId *id, uint32_t status) -{ - return mParent->PeerCallback(id, status); -} - -virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) -{ - return mParent->ValueCallback(id, key, status); -} - -virtual int dhtConnectCallback(const bdId*, const bdId*, const bdId*, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t) -{ - return 1; -} - -virtual int dhtInfoCallback(const bdId*, uint32_t, uint32_t, std::string) -{ - return 1; -} - - private: - - BitDhtHandler *mParent; -}; - - -BitDhtHandler::BitDhtHandler(bdNodeId *ownId, uint16_t port, std::string appId, std::string bootstrapfile) -{ - std::cerr << "BitDhtHandler::BitDhtHandler()" << std::endl; - std::cerr << "Using Id: "; - bdStdPrintNodeId(std::cerr, ownId); - std::cerr << std::endl; - - std::cerr << "Using Bootstrap File: " << bootstrapfile; - std::cerr << std::endl; - std::cerr << "Converting OwnId to bdNodeId...."; - std::cerr << std::endl; - - /* standard dht behaviour */ - bdDhtFunctions *stdfns = new bdStdDht(); - - std::cerr << "BitDhtHandler() startup ... creating UdpBitDht"; - std::cerr << std::endl; - - /* create dht */ - struct sockaddr_in local; - memset(&local, 0, sizeof(local)); - local.sin_family = AF_INET; - local.sin_addr.s_addr = 0; - local.sin_port = htons(port); - - mStack = new UdpStack(local); - - mUdpBitDht = new UdpBitDht(mStack, ownId, appId, bootstrapfile, stdfns); - mStack->addReceiver(mUdpBitDht); - - /* setup callback to here */ - BdCallback *bdcb = new BdCallback(this); - mUdpBitDht->addCallback(bdcb); - - std::cerr << "BitDhtHandler() starting threads and dht"; - std::cerr << std::endl; - - mUdpBitDht->start(); /* starts up the bitdht thread */ - - /* setup best mode for quick search */ - uint32_t dhtFlags = BITDHT_MODE_TRAFFIC_MED | BITDHT_MODE_RELAYSERVERS_IGNORED; - mUdpBitDht->setDhtMode(dhtFlags); - mUdpBitDht->setAttachMode(false); - - /* switch on the dht too */ - mUdpBitDht->startDht(); -} - - /* pqiNetAssist - external interface functions */ -void BitDhtHandler::enable(bool on) -{ - std::cerr << "p3BitDht::enable(" << on << ")"; - std::cerr << std::endl; - if (on) - { - mUdpBitDht->startDht(); - } - else - { - mUdpBitDht->stopDht(); - } -} - -void BitDhtHandler::shutdown() /* blocking call */ -{ - mUdpBitDht->stopDht(); -} - - -void BitDhtHandler::restart() -{ - mUdpBitDht->stopDht(); - mUdpBitDht->startDht(); -} - -bool BitDhtHandler::getEnabled() -{ - return (mUdpBitDht->stateDht() != 0); -} - -bool BitDhtHandler::getActive() -{ - return (mUdpBitDht->stateDht() >= BITDHT_MGR_STATE_ACTIVE); -} - - - - - /* pqiNetAssistConnect - external interface functions */ - /* add / remove peers */ -bool BitDhtHandler::FindNode(bdNodeId *peerId) -{ - std::cerr << "BitDhtHandler::FindNode("; - bdStdPrintNodeId(std::cerr, peerId); - std::cerr << ")" << std::endl; - - - BssResult res; - res.id.id = *peerId; - res.mode = BSS_SINGLE_SHOT; - res.status = 0; - - { - bdStackMutex stack(resultsMtx); /********** MUTEX LOCKED *************/ - mSearchNodes[*peerId] = res; - } - - /* add in peer */ - mUdpBitDht->addFindNode(peerId, BITDHT_QFLAGS_DISGUISE); - - return true ; -} - -bool BitDhtHandler::DropNode(bdNodeId *peerId) -{ - std::cerr << "BitDhtHandler::DropNode("; - bdStdPrintNodeId(std::cerr, peerId); - std::cerr << ")" << std::endl; - std::cerr << std::endl; - - /* remove in peer */ - mUdpBitDht->removeFindNode(peerId); - - bdStackMutex stack(resultsMtx); /********** MUTEX LOCKED *************/ - - /* find the node from our list */ - std::map::iterator it; - it = mSearchNodes.find(*peerId); - if (it != mSearchNodes.end()) - { - std::cerr << "BitDhtHandler::DropNode() Found NodeId, removing"; - std::cerr << std::endl; - - mSearchNodes.erase(it); - } - return true ; -} - - -bool BitDhtHandler::SearchResult(bdId *id, uint32_t &status) -{ - bdStackMutex stack(resultsMtx); /********** MUTEX LOCKED *************/ - - /* find the node from our list */ - std::map::iterator it; - it = mSearchNodes.find(id->id); - if (it != mSearchNodes.end()) - { - if (it->second.status != 0) - { - std::cerr << "BitDhtHandler::SearchResults() Found Results"; - std::cerr << std::endl; - status = it->second.status; - *id = it->second.id; - return true; - } - - std::cerr << "BitDhtHandler::SearchResults() No Results Yet"; - std::cerr << std::endl; - return false; - } - - std::cerr << "BitDhtHandler::SearchResults() ERROR: No Search Entry"; - std::cerr << std::endl; - return false; -} - - -/********************** Callback Functions **************************/ - -int BitDhtHandler::NodeCallback(const bdId *id, uint32_t peerflags) -{ -#ifdef DEBUG_BITDHT - std::cerr << "BitDhtHandler::NodeCallback()"; - bdStdPrintNodeId(std::cerr, &(id->id)); - std::cerr << " flags: " << peerflags; - std::cerr << std::endl; -#endif - - return 0; -} - -int BitDhtHandler::PeerCallback(const bdId *id, uint32_t status) -{ - std::cerr << "BitDhtHandler::PeerCallback() NodeId: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; - - bdStackMutex stack(resultsMtx); /********** MUTEX LOCKED *************/ - - /* find the node from our list */ - std::map::iterator it; - it = mSearchNodes.find(id->id); - if (it == mSearchNodes.end()) - { - std::cerr << "BitDhtHandler::PeerCallback() Unknown NodeId !!! "; - std::cerr << std::endl; - - return 1; - } - it->second.status = status; - - bool connect = false; - switch(status) - { - case BITDHT_MGR_QUERY_FAILURE: - /* do nothing */ - std::cerr << "BitDhtHandler::PeerCallback() QUERY FAILURE ... do nothin "; - std::cerr << std::endl; - - - break; - - case BITDHT_MGR_QUERY_PEER_OFFLINE: - /* do nothing */ - - std::cerr << "BitDhtHandler::PeerCallback() QUERY PEER OFFLINE ... do nothin "; - std::cerr << std::endl; - - break; - - case BITDHT_MGR_QUERY_PEER_UNREACHABLE: - /* do nothing */ - - std::cerr << "BitDhtHandler::PeerCallback() QUERY PEER UNREACHABLE ... saving address "; - std::cerr << std::endl; - it->second.id = *id; - - break; - - case BITDHT_MGR_QUERY_PEER_ONLINE: - /* do something */ - - std::cerr << "BitDhtHandler::PeerCallback() QUERY PEER ONLINE ... saving address"; - std::cerr << std::endl; - - it->second.id = *id; - break; - } - return 1; -} - - - -int BitDhtHandler::ValueCallback(const bdNodeId *id, std::string key, uint32_t status) -{ - std::cerr << "BitDhtHandler::ValueCallback() NOOP for NOW"; - std::cerr << std::endl; - - std::cerr << "BitDhtHandler::ValueCallback()"; - bdStdPrintNodeId(std::cerr, id); - std::cerr << " key: " << key; - std::cerr << " status: " << status; - std::cerr << std::endl; - - /* ignore for now */ - return 0; -} - diff --git a/libbitdht/src/example/bdhandler.h b/libbitdht/src/example/bdhandler.h deleted file mode 100644 index c0c942db6..000000000 --- a/libbitdht/src/example/bdhandler.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * libbitdht/src/example/bdhandler.h - * - * BitDht interface example - * - * Copyright 2009-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#ifndef BITDHT_HANDLER_H -#define BITDHT_HANDLER_H - -#include -#include - -#include "udp/udpstack.h" -#include "udp/udpbitdht.h" -#include "bitdht/bdiface.h" - -/*** This class can be overloaded to use the XXXXCallback() Functions *****/ -class BitDhtIntCallback; - - -class BssResult -{ - public: - bdId id; - uint32_t mode; // single shot - uint32_t status; // SEARCHING, FAILURE, FOUND, MULTIPLE HITS. -}; - -#define BSS_SINGLE_SHOT 0x0001 - - -class BitDhtHandler -{ - - public: - - BitDhtHandler(bdNodeId *ownId, uint16_t port, std::string appId, std::string bootstrapfile); - -void enable(bool on); -void shutdown(); /* blocking call */ -void restart(); - -bool getEnabled(); -bool getActive(); - -bool FindNode(bdNodeId *peerId); -bool DropNode(bdNodeId *peerId); - -virtual int NodeCallback(const bdId *id, uint32_t peerflags); -virtual int PeerCallback(const bdId *id, uint32_t status); -virtual int ValueCallback(const bdNodeId *id, std::string key, uint32_t status); - -bool SearchResult(bdId *id, uint32_t &status); - - private: - - /* real DHT classes */ - UdpStack *mStack; - UdpBitDht *mUdpBitDht; - - bdMutex resultsMtx; /* for all class data (below) */ - - std::map mSearchNodes; -}; - - -#endif /* BITDHT_HANDLER_H */ - diff --git a/libbitdht/src/example/bootstrap_fn.cc b/libbitdht/src/example/bootstrap_fn.cc deleted file mode 100644 index 0288087f0..000000000 --- a/libbitdht/src/example/bootstrap_fn.cc +++ /dev/null @@ -1,84 +0,0 @@ - - -#include "bitdht/bdiface.h" -#include "bitdht/bdstddht.h" -#include "bdhandler.h" - -#include "bootstrap_fn.h" - -bool bdSingleShotFindPeer(const std::string bootstrapfile, const std::string peerId, std::string &peer_ip, uint16_t &peer_port) -{ - /* startup dht : with a random id! */ - bdNodeId ownId; - bdStdRandomNodeId(&ownId); - - uint16_t port = 6775; - std::string appId = "bsId"; - BitDhtHandler dht(&ownId, port, appId, bootstrapfile); - - /* install search node */ - bdNodeId searchId; - if (!bdStdLoadNodeId(&searchId, peerId)) - { - std::cerr << "bdSingleShotFindPeer(): Invalid Input Id: " << peerId; - return false; - } - - std::cerr << "bssdht: searching for Id: "; - bdStdPrintNodeId(std::cerr, &searchId); - std::cerr << std::endl; - - dht.FindNode(&searchId); - - /* run your program */ - bdId resultId; - uint32_t status; - - resultId.id = searchId; - - while(false == dht.SearchResult(&resultId, status)) - { - sleep(10); - } - - std::cerr << "bdSingleShotFindPeer(): Found Result:" << std::endl; - - std::cerr << "\tId: "; - bdStdPrintId(std::cerr, &resultId); - std::cerr << std::endl; - - std::cerr << "\tstatus: " << status; - std::cerr << std::endl; - - dht.shutdown(); - - if ((status == BITDHT_QUERY_PEER_UNREACHABLE) || - (status == BITDHT_QUERY_SUCCESS)) - { - - peer_ip = bdnet_inet_ntoa(resultId.addr.sin_addr); - peer_port = ntohs(resultId.addr.sin_port); - - std::cerr << "Answer: "; - std::cerr << std::endl; - std::cerr << "\tPeer IpAddress: " << peer_ip; - std::cerr << std::endl; - std::cerr << "\tPeer Port: " << peer_port; - std::cerr << std::endl; - } - else - { - std::cerr << "Sorry, Cant be found!"; - std::cerr << std::endl; - } - - return true; -} - - - - - - - - diff --git a/libbitdht/src/example/bootstrap_fn.h b/libbitdht/src/example/bootstrap_fn.h deleted file mode 100644 index 19ff6d714..000000000 --- a/libbitdht/src/example/bootstrap_fn.h +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - - -/* NOTE. At the moment only the bootstrapfile is actually used. - * peerId is ignored (a random peerId is searched for). ip & port are not filled in either. - * - * This is mainly to finish testing. - * - * Once the best form of the return functions is decided (ipv4 structure, or strings). - * this can be finished off. - * - */ - -bool bdSingleShotFindPeer(const std::string bootstrapfile, const std::string peerId, std::string &ip, uint16_t &port); - diff --git a/libbitdht/src/example/bssdht.cc b/libbitdht/src/example/bssdht.cc deleted file mode 100644 index 97f006260..000000000 --- a/libbitdht/src/example/bssdht.cc +++ /dev/null @@ -1,72 +0,0 @@ - -#include "bootstrap_fn.h" -#include -#include - -void args(char *name) -{ - std::cerr << std::endl; - std::cerr << "Dht Single Shot Searcher"; - std::cerr << std::endl; - std::cerr << "Usage:"; - std::cerr << std::endl; - std::cerr << "\t" << name << " -p "; - std::cerr << std::endl; - std::cerr << std::endl; - std::cerr << "NB: The PeerId is Required to Run"; - std::cerr << std::endl; - std::cerr << std::endl; -} - - -int main(int argc, char **argv) -{ - - std::string bootstrapfile = "bdboot.txt"; - std::string peerId; - std::string ip; - uint16_t port; - int c; - bool havePeerId = false; - - - while((c = getopt(argc, argv,"p:")) != -1) - { - switch (c) - { - case 'p': - peerId = optarg; - havePeerId = true; - break; - default: - args(argv[0]); - return 1; - break; - } - } - - if (!havePeerId) - { - args(argv[0]); - return 1; - } - - - std::cerr << "bssdht: starting up"; - std::cerr << std::endl; - - bdSingleShotFindPeer(bootstrapfile, peerId, ip, port); - - std::cerr << "bssdht: finished"; - std::cerr << std::endl; - - return 1; -} - - - - - - - - diff --git a/libbitdht/src/libbitdht.pro b/libbitdht/src/libbitdht.pro deleted file mode 100644 index ab53768a5..000000000 --- a/libbitdht/src/libbitdht.pro +++ /dev/null @@ -1,185 +0,0 @@ -# RetroShare main qmake build script -# -# Copyright (C) 2004-2019, Retroshare Team -# -# 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 . -# -# SPDX-FileCopyrightText: Retroshare Team -# SPDX-License-Identifier: LGPL-3.0-or-later - -!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri") - -TEMPLATE = lib -CONFIG += staticlib -CONFIG -= qt -TARGET = bitdht -DESTDIR = lib - -!include("use_libbitdht.pri"):error("Including") - -QMAKE_CXXFLAGS *= -Wall -DBE_DEBUG - -# treat warnings as error for better removing -#QMAKE_CFLAGS += -Werror -#QMAKE_CXXFLAGS += -Werror - -################################# Linux ########################################## -linux-* { - QMAKE_CC = $${QMAKE_CXX} -} - -linux-g++ { - OBJECTS_DIR = temp/linux-g++/obj -} - -linux-g++-64 { - OBJECTS_DIR = temp/linux-g++-64/obj -} - -unix { - data_files.path = "$${DATA_DIR}" - data_files.files = bitdht/bdboot.txt - INSTALLS += data_files -} - -android-* { - # see https://community.kde.org/Necessitas/Assets - bdboot.files=bitdht/bdboot.txt - bdboot.path=/assets/values - INSTALLS += bdboot -} - -#################### Cross compilation for windows under Linux #################### - -win32-x-g++ { - OBJECTS_DIR = temp/win32xgcc/obj - # These have been replaced by _WIN32 && __MINGW32__ - # DEFINES *= WINDOWS_SYS WIN32 WIN_CROSS_UBUNTU - QMAKE_CXXFLAGS *= -Wmissing-include-dirs - QMAKE_CC = i586-mingw32msvc-g++ - QMAKE_LIB = i586-mingw32msvc-ar - QMAKE_AR = i586-mingw32msvc-ar - DEFINES *= STATICLIB WIN32 - - INCLUDEPATH *= /usr/i586-mingw32msvc/include ${HOME}/.wine/drive_c/pthreads/include/ -} -################################# Windows ########################################## - -win32 { - QMAKE_CC = $${QMAKE_CXX} - OBJECTS_DIR = temp/obj - MOC_DIR = temp/moc - DEFINES *= STATICLIB WIN32_LEAN_AND_MEAN - # These have been replaced by _WIN32 && __MINGW32__ - #DEFINES *= WINDOWS_SYS WIN32 STATICLIB MINGW - - # Switch on extra warnings - QMAKE_CFLAGS += -Wextra - QMAKE_CXXFLAGS += -Wextra - - # Switch off optimization for release version - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -O0 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE += -O0 - - # Switch on optimization for debug version - #QMAKE_CXXFLAGS_DEBUG += -O2 - #QMAKE_CFLAGS_DEBUG += -O2 -} - -################################# MacOSX ########################################## - -mac { - QMAKE_CC = $${QMAKE_CXX} - OBJECTS_DIR = temp/obj - MOC_DIR = temp/moc -} - -################################# FreeBSD ########################################## - -freebsd-* { -} - -################################# OpenBSD ########################################## - -openbsd-* { -} - -################################# Haiku ########################################## - -haiku-* { - DESTDIR = lib -} - -################################### COMMON stuff ################################## -################################### COMMON stuff ################################## - -DEPENDPATH += . -INCLUDEPATH += . - -HEADERS += \ - bitdht/bdiface.h \ - bitdht/bencode.h \ - bitdht/bdobj.h \ - bitdht/bdmsgs.h \ - bitdht/bdpeer.h \ - bitdht/bdquery.h \ - bitdht/bdhash.h \ - bitdht/bdstore.h \ - bitdht/bdnode.h \ - bitdht/bdmanager.h \ - bitdht/bdstddht.h \ - bitdht/bdhistory.h \ - util/bdnet.h \ - util/bdthreads.h \ - util/bdrandom.h \ - util/bdfile.h \ - util/bdstring.h \ - udp/udplayer.h \ - udp/udpstack.h \ - udp/udpbitdht.h \ - bitdht/bdconnection.h \ - bitdht/bdfilter.h \ - bitdht/bdaccount.h \ - bitdht/bdquerymgr.h \ - util/bdbloom.h \ - bitdht/bdfriendlist.h \ - -SOURCES += \ - bitdht/bencode.c \ - bitdht/bdobj.cc \ - bitdht/bdmsgs.cc \ - bitdht/bdpeer.cc \ - bitdht/bdquery.cc \ - bitdht/bdhash.cc \ - bitdht/bdstore.cc \ - bitdht/bdnode.cc \ - bitdht/bdmanager.cc \ - bitdht/bdstddht.cc \ - bitdht/bdhistory.cc \ - util/bdnet.cc \ - util/bdthreads.cc \ - util/bdrandom.cc \ - util/bdfile.cc \ - util/bdstring.cc \ - udp/udplayer.cc \ - udp/udpstack.cc \ - udp/udpbitdht.cc \ - bitdht/bdconnection.cc \ - bitdht/bdfilter.cc \ - bitdht/bdaccount.cc \ - bitdht/bdquerymgr.cc \ - util/bdbloom.cc \ - bitdht/bdfriendlist.cc \ diff --git a/libbitdht/src/tests/bdbloom_makefilter.cc b/libbitdht/src/tests/bdbloom_makefilter.cc deleted file mode 100644 index ee3c6e4b8..000000000 --- a/libbitdht/src/tests/bdbloom_makefilter.cc +++ /dev/null @@ -1,90 +0,0 @@ -/* - * bitdht/bdbloom_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - -#include -#include "util/bdbloom.h" -#include "bitdht/bdstddht.h" -#include - -#define N_TESTS 100 - -int main(int argc, char **argv) -{ - /* read from the file */ - if (argc < 2) - { - std::cerr << "Missing Hash File"; - std::cerr << std::endl; - } - - FILE *fd = fopen(argv[1], "r"); - if (!fd) - { - std::cerr << "Failed to Open File: " << argv[1]; - std::cerr << std::endl; - return 1; - } - - char line[1000]; - - bdBloom filter; - - int nHashes = 0; - while(fgets(line, 1000-1, fd)) - { - std::string hash = line; - std::cerr << "Read Hash: " << hash; - std::cerr << std::endl; - - filter.add(hash); - nHashes++; - } - fclose(fd); - - filter.printFilter(std::cerr); - - int bits = filter.countBits(); - int filterBits = filter.filterBits(); - std::cerr << "Filter Bits Set: " << bits; - std::cerr << std::endl; - - double possible = ((double) bits) * bits; - double max = ((double) filterBits) * filterBits; - std::cerr << "Therefore Possible Finds: " << possible << "/" << max << " = %" << 100 * possible / max; - std::cerr << std::endl; - std::cerr << "With Insertions: " << nHashes; - std::cerr << std::endl; - - std::cerr << std::endl; - std::cerr << std::endl; - - std::cerr << "Filter String: " << filter.getFilter() << std::endl; - std::cerr << std::endl; - std::cerr << std::endl; - - return 1; -} - - diff --git a/libbitdht/src/tests/bdbloom_test.cc b/libbitdht/src/tests/bdbloom_test.cc deleted file mode 100644 index d0aefb947..000000000 --- a/libbitdht/src/tests/bdbloom_test.cc +++ /dev/null @@ -1,164 +0,0 @@ -/* - * bitdht/bdbloom_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - -#include -#include "util/bdbloom.h" -#include "bitdht/bdstddht.h" -#include - -#define N_TESTS 100 - -int main(int argc, char **argv) -{ - - /* Do this multiple times */ - int i; - - - bdBloom filter; - - std::list testIds; - std::list::iterator it; - - for(i = 0; i < N_TESTS; i++) - { - bdNodeId targetId; - bdStdRandomNodeId(&targetId); - testIds.push_back(targetId); - } - - std::cerr << "Test bdBloom Filter...." << std::endl; - for(it = testIds.begin(); it != testIds.end(); it++) - { - bdNodeId targetId = *it; - - std::cerr << "-------------------------------------------------" << std::endl; - std::cerr << "Inserting : "; - std::ostringstream str; - bdStdPrintNodeId(str, &targetId); - std::cerr << str.str(); - std::cerr << std::endl; - - filter.add(str.str()); - - filter.printFilter(std::cerr); - } - - std::string fs1 = filter.getFilter(); - /* now extract, and reinsert filter */ - bdBloom filter2; - filter2.setFilterBits(fs1); - - std::string fs2 = filter2.getFilter(); - filter2.printFilter(std::cerr); - - if (fs1 == fs2) - { - std::cerr << "SUCCESS: Filter Correctly Transferred!"; - std::cerr << std::endl; - } - else - { - std::cerr << "FAILURE: Filter Not Transferred!"; - std::cerr << std::endl; - } - - - for(it = testIds.begin(); it != testIds.end(); it++) - { - bdNodeId targetId = *it; - - std::cerr << "-------------------------------------------------" << std::endl; - std::cerr << "Testing : "; - std::cerr << std::endl; - - std::ostringstream str; - bdStdPrintNodeId(str, &targetId); - std::cerr << str.str() << std::endl; - - if (filter2.test(str.str())) - { - std::cerr << "SUCCESS: Filter Found Entry"; - std::cerr << std::endl; - } - else - { - std::cerr << "FAILURE: Filter Didn't Found Entry"; - std::cerr << std::endl; - } - } - - int bits = filter.countBits(); - int filterBits = filter.filterBits(); - std::cerr << "Filter Bits Set: " << bits; - std::cerr << std::endl; - - double possible = ((double) bits) * bits; - double max = ((double) filterBits) * filterBits; - std::cerr << "Therefore Possible Finds: " << possible << "/" << max << " = %" << 100 * possible / max; - std::cerr << std::endl; - std::cerr << "With Insertions: " << N_TESTS; - std::cerr << std::endl; - -#define FINAL_TESTS (1000000) - int found = 0; - int didnt = 0; - for(i = 0; i < FINAL_TESTS; i++) - { - if ((i != 0) && (i % 100000 == 0)) - { - std::cerr << "Run " << i << " Checks" << std::endl; - } - - bdNodeId targetId; - bdStdRandomNodeId(&targetId); - std::ostringstream str; - bdStdPrintNodeId(str, &targetId); - - if (filter2.test(str.str())) - { - found++; - } - else - { - didnt++; - } - } - - std::cerr << "Final Stats: " << FINAL_TESTS << " random checks done"; - std::cerr << std::endl; - std::cerr << "\t" << found << " " << 100.0 * ((double) found) / FINAL_TESTS << "% found"; - std::cerr << std::endl; - std::cerr << "\t" << didnt << " " << 100.0 * ((double) didnt) / FINAL_TESTS << "% didnt"; - std::cerr << std::endl; - - - - - - return 1; -} - - diff --git a/libbitdht/src/tests/bdboot.txt b/libbitdht/src/tests/bdboot.txt deleted file mode 100644 index 3a2f6b2b2..000000000 --- a/libbitdht/src/tests/bdboot.txt +++ /dev/null @@ -1,500 +0,0 @@ -50.193.28.158 36327 -88.181.96.123 11328 -99.37.188.41 29653 -88.72.55.221 12254 -76.103.79.28 36151 -78.219.65.122 18814 -50.80.44.10 60059 -82.66.32.246 39882 -89.88.138.23 50082 -93.9.151.183 41948 -60.35.23.158 12641 -93.181.45.102 62514 -41.249.53.96 52932 -82.227.12.97 46602 -89.156.177.7 29920 -178.236.129.166 56294 -46.173.64.63 44300 -86.73.179.122 59624 -209.195.101.75 44444 -76.114.41.44 13750 -188.103.108.41 1580 -74.192.244.156 23315 -91.217.90.22 58541 -27.32.169.219 57166 -175.196.134.95 6890 -99.229.202.165 36801 -119.14.195.27 60485 -112.206.13.117 41825 -87.89.253.70 52870 -203.186.173.169 22508 -122.168.241.122 16167 -113.250.99.211 3319 -87.106.249.208 4281 -97.90.151.69 54641 -81.249.29.121 7812 -24.122.0.38 5007 -79.119.57.255 48324 -84.237.250.67 60736 -72.208.178.104 46970 -93.7.211.121 35220 -82.126.138.5 31165 -98.21.67.18 56158 -174.101.153.252 38195 -70.184.208.133 1664 -173.12.200.5 5996 -5.39.78.183 7777 -212.178.8.49 61787 -81.38.140.98 37021 -189.4.28.74 28817 -90.55.204.2 38814 -183.89.101.187 63939 -175.208.45.169 32911 -124.86.6.169 14743 -58.168.9.105 36962 -89.178.158.14 54494 -86.23.51.76 44444 -111.119.227.15 26632 -68.82.46.243 31651 -91.20.211.178 57166 -89.85.171.145 32926 -75.126.109.30 15009 -88.170.61.126 32761 -82.237.40.39 39052 -80.101.24.220 17412 -95.84.208.14 9372 -109.212.31.106 4662 -80.98.106.227 9773 -67.197.115.77 33457 -212.43.36.251 20273 -129.21.122.81 32785 -109.187.235.96 49414 -93.66.62.37 59880 -81.169.151.138 42157 -67.252.30.196 41576 -77.176.247.93 7812 -178.65.138.159 52160 -178.17.18.206 8028 -96.53.93.210 56028 -80.236.120.181 14451 -37.24.108.103 2000 -95.171.138.138 42342 -88.72.55.221 37933 -89.133.71.20 14968 -96.250.108.15 45291 -86.74.221.169 36035 -111.50.223.158 16001 -46.33.251.143 11789 -159.224.9.168 57529 -74.4.200.21 45569 -77.224.214.10 7886 -91.237.165.36 55393 -71.65.115.24 60705 -180.245.74.54 10065 -89.229.5.2 1040 -178.129.19.231 53510 -76.23.105.94 47088 -76.121.226.114 47476 -108.77.112.69 51413 -24.246.67.233 55806 -95.25.123.108 17701 -142.161.104.76 16956 -90.56.162.201 53163 -62.99.25.102 22309 -116.14.209.177 59826 -213.87.123.121 20587 -83.165.11.132 9481 -122.150.77.71 6890 -77.236.180.89 24819 -84.24.96.215 6881 -98.176.147.218 62776 -79.82.130.49 20757 -78.43.137.174 10409 -74.136.3.207 43112 -95.133.243.200 7509 -71.232.162.47 10580 -209.195.104.126 6881 -178.82.162.111 36190 -175.173.87.138 16001 -72.218.218.39 6881 -84.252.26.117 10264 -46.166.104.222 50700 -86.52.88.196 52333 -188.186.142.97 22222 -63.227.112.135 40297 -110.171.80.30 50831 -62.16.187.208 60193 -41.221.124.3 12720 -122.86.88.153 5831 -46.29.209.84 6881 -83.165.111.199 63885 -80.98.162.185 51413 -176.73.16.252 34976 -24.188.113.226 42817 -88.207.42.112 51187 -85.230.147.123 58371 -50.92.78.248 41837 -94.212.214.204 52385 -86.52.180.140 6881 -94.23.198.174 51413 -212.198.182.174 18060 -78.234.129.171 33797 -125.186.188.58 6881 -94.210.26.194 16981 -109.64.246.237 23252 -86.201.102.163 51413 -75.82.14.204 37960 -172.1.72.173 31558 -86.71.169.12 32682 -37.110.130.32 61724 -61.64.143.4 59026 -202.79.36.129 58060 -88.254.55.5 53323 -84.39.4.247 6881 -31.151.104.160 51413 -201.87.14.68 50129 -24.246.26.61 51151 -101.103.182.123 36511 -95.111.64.209 10076 -89.224.149.142 25365 -46.21.211.0 18488 -49.49.27.110 13392 -60.185.230.42 64770 -188.27.125.50 51464 -212.21.6.250 64885 -114.243.240.207 53212 -89.40.161.33 29112 -14.145.16.208 18746 -186.204.50.237 17198 -124.115.12.153 2043 -47.54.129.97 47411 -109.200.116.239 17972 -213.16.182.12 25128 -217.20.73.188 35691 -182.177.193.44 10083 -80.222.111.127 35847 -79.94.175.146 41542 -74.141.87.159 55574 -95.37.172.1 11051 -77.100.104.142 54078 -80.184.19.34 35010 -94.180.203.42 6881 -37.201.168.34 48690 -95.28.111.83 11777 -84.208.143.35 50422 -188.186.45.35 17670 -90.146.80.87 26792 -122.121.191.214 47448 -31.181.0.236 6881 -99.242.88.203 21704 -176.31.109.159 32450 -62.93.99.6 28010 -95.90.236.216 41463 -95.132.145.53 17125 -222.216.168.211 50260 -182.96.166.223 4565 -111.92.19.48 46488 -88.170.61.126 7465 -216.49.152.239 59312 -108.46.182.176 23053 -59.19.172.14 58485 -159.224.26.228 13839 -184.147.15.149 64385 -41.98.81.187 10109 -90.5.180.162 18619 -81.198.134.16 6881 -66.229.51.242 51413 -82.11.60.187 55393 -62.194.99.138 18011 -178.151.1.128 20702 -84.98.19.169 36650 -84.224.105.232 13220 -68.115.149.90 49710 -37.205.70.166 35691 -85.232.130.42 62207 -83.158.230.144 55555 -83.246.216.234 49001 -92.233.249.147 55582 -41.108.95.129 12262 -83.152.236.89 58730 -115.220.147.35 7076 -78.106.26.128 26900 -84.101.22.120 55512 -89.142.253.198 10520 -151.64.241.149 51346 -95.168.12.60 63676 -213.46.147.163 38512 -85.130.52.88 25279 -90.193.28.149 22222 -79.132.25.126 59243 -111.250.206.117 25332 -99.230.144.57 34023 -112.192.66.172 1242 -58.170.183.148 16308 -110.76.72.49 13412 -80.9.174.99 58943 -84.98.243.248 13291 -91.148.138.106 17006 -173.193.242.231 25025 -173.193.242.231 37448 -84.244.2.193 27947 -78.45.13.229 19014 -173.193.242.231 22859 -119.154.190.187 43623 -213.65.128.142 55595 -78.234.140.58 8080 -92.142.60.155 6881 -189.59.195.217 64931 -122.169.6.171 35672 -178.47.227.162 33893 -46.246.67.243 64453 -46.119.144.241 49001 -174.36.55.75 18688 -94.243.89.164 57848 -209.140.255.87 20785 -62.77.128.245 51413 -91.211.177.3 20588 -81.84.65.143 12157 -68.228.230.85 20862 -108.90.48.119 51413 -24.212.131.70 48665 -85.23.70.134 53440 -217.55.204.253 12652 -31.180.94.141 35691 -109.152.61.125 57213 -92.136.246.118 13888 -178.34.229.72 30185 -94.24.202.64 30012 -123.202.103.167 33351 -109.71.206.215 6881 -89.70.19.188 26238 -59.180.22.196 20921 -189.73.206.149 55505 -46.130.66.188 60070 -183.10.152.135 47269 -41.233.124.184 13394 -112.139.59.213 12821 -89.2.143.130 18263 -217.210.76.120 30274 -178.149.61.10 19539 -96.233.255.79 50924 -124.121.88.187 63778 -119.204.207.162 30894 -103.14.61.48 53600 -46.63.62.162 10219 -77.41.141.187 6881 -83.110.90.167 42603 -61.78.82.158 29484 -85.0.20.26 6881 -94.236.128.96 50907 -99.230.119.14 1755 -108.13.168.252 62118 -84.125.19.21 42646 -74.141.87.159 55998 -86.125.209.88 62846 -37.43.117.187 40595 -95.104.110.103 47173 -76.78.36.229 36258 -97.94.141.117 63650 -49.49.90.217 14706 -94.6.23.192 39715 -46.232.228.161 5439 -186.133.30.205 15189 -46.186.48.179 61088 -31.134.17.73 32518 -98.229.16.76 13046 -89.211.153.176 63047 -95.16.10.140 12057 -46.149.41.106 49001 -178.204.78.171 28106 -94.51.214.102 6881 -178.127.223.150 23171 -203.141.138.201 42247 -95.53.43.124 19988 -66.11.189.123 16723 -178.46.157.54 54330 -85.87.178.219 23203 -83.114.210.35 51413 -178.78.33.173 49001 -95.191.57.183 28277 -111.241.72.105 63166 -190.213.94.37 13819 -114.34.93.16 6881 -80.201.144.250 16648 -217.148.57.194 52856 -46.180.187.212 20308 -59.143.213.135 36841 -115.241.104.112 54040 -58.182.18.125 11840 -202.160.16.7 58808 -78.230.94.4 63082 -188.254.157.48 40307 -78.162.174.165 24173 -88.196.203.160 47372 -182.164.124.199 48810 -121.102.203.62 20440 -219.246.57.153 16001 -2.61.38.78 25590 -99.98.96.67 13178 -125.114.50.210 1056 -90.193.128.203 61929 -94.14.5.83 58485 -37.193.160.216 57423 -58.115.35.67 11257 -182.235.129.91 16001 -186.36.145.147 42376 -128.68.147.228 6881 -200.119.228.231 17654 -88.89.110.64 26602 -115.79.234.94 36463 -80.193.158.59 49348 -78.73.114.77 11385 -90.54.174.104 20963 -218.151.52.146 16617 -46.161.143.220 49735 -188.18.80.97 6881 -37.212.44.31 10638 -89.223.99.150 49001 -65.4.130.12 50221 -186.74.22.89 45612 -95.58.93.119 28709 -209.6.69.225 56332 -85.103.248.197 27524 -174.45.1.123 6881 -118.171.185.18 19917 -87.90.247.194 39695 -213.222.142.58 28962 -69.253.233.190 44895 -88.172.121.96 30728 -222.226.45.246 26333 -82.245.33.128 25515 -178.44.235.211 19597 -121.168.129.77 60375 -121.45.206.235 23987 -217.162.186.254 39835 -83.222.112.119 58903 -178.74.53.50 22389 -61.70.254.221 62238 -119.56.48.165 16001 -93.148.114.59 12721 -88.251.154.23 17808 -188.79.87.245 15489 -46.119.165.133 58378 -76.94.95.223 25698 -88.188.193.27 26118 -123.211.1.4 27072 -101.68.107.193 25086 -95.147.47.122 26085 -123.243.64.132 35587 -186.89.157.161 15024 -174.106.96.168 56049 -109.148.234.144 60557 -89.178.224.73 28557 -85.104.92.129 10002 -99.228.252.24 37108 -61.62.254.10 32181 -2.50.255.118 36581 -176.49.163.194 23892 -90.23.214.138 63347 -119.36.38.104 62888 -109.122.3.81 6881 -86.99.199.68 25025 -84.120.63.7 11837 -188.60.197.229 16629 -89.110.207.136 13761 -213.57.37.242 44892 -75.90.96.145 31951 -99.247.185.46 36957 -76.227.224.238 24196 -217.27.215.96 6882 -213.33.236.230 65360 -77.5.35.67 43398 -83.108.63.210 61452 -24.12.46.116 23073 -173.193.242.231 36660 -71.94.186.218 10322 -109.228.185.71 6881 -175.205.72.185 59696 -200.120.153.187 57279 -1.64.32.1 11212 -89.233.243.128 33881 -89.3.35.16 8010 -219.99.6.250 54921 -79.95.171.102 11092 -126.13.14.150 17431 -58.208.74.237 6600 -114.245.149.20 9371 -78.233.157.35 40874 -84.226.253.50 6881 -69.14.60.243 61616 -50.33.142.137 52383 -188.242.78.174 33213 -71.237.6.246 41304 -41.107.85.131 10010 -89.222.164.45 39809 -88.186.107.212 42344 -195.132.158.234 22855 -82.122.102.50 25612 -76.255.133.138 31677 -24.130.61.50 28383 -98.165.83.165 3661 -99.55.140.166 50473 -75.109.50.114 25562 -87.106.187.29 20277 -24.247.183.167 2365 -82.228.100.167 42278 -109.214.57.82 1042 -77.196.18.56 22750 -66.177.205.21 8086 -82.231.237.146 9517 -176.31.248.87 6338 -2.6.66.21 45350 -79.153.101.234 11154 -24.247.179.164 8929 -71.63.225.31 21053 -83.157.77.228 7812 -108.59.72.193 2398 -88.127.44.139 15998 -64.121.118.201 61270 -90.38.76.72 4699 -67.173.33.90 33134 -88.217.36.182 2924 -2.236.14.214 55556 -109.194.233.11 6881 -178.187.47.44 53127 -126.29.214.91 42242 -41.178.247.176 24977 -37.59.34.186 41497 -82.225.11.196 38136 -195.132.158.49 61570 -78.105.105.87 42127 -94.23.204.135 30392 -178.63.84.76 51413 -78.237.111.89 45254 -76.189.121.236 31548 -24.85.183.150 9646 -88.181.149.119 5018 -126.130.125.117 24435 -65.15.247.19 51319 -176.31.109.159 24586 -176.31.127.140 44137 -89.93.149.195 57218 -88.165.34.61 51449 -188.242.97.188 35390 -107.15.22.183 10392 -24.211.20.89 62868 -74.108.4.175 17391 -80.185.95.18 18365 -146.247.80.210 38204 -27.4.216.128 57962 -88.238.170.69 26026 -74.215.38.97 50596 -87.89.75.85 42176 -115.188.217.116 62348 -98.250.89.141 13038 -93.11.175.201 41027 -174.109.14.220 51413 -114.79.170.114 27462 -84.22.157.13 28498 -180.183.210.31 21257 -42.113.246.104 10775 diff --git a/libbitdht/src/tests/bdmetric_test.cc b/libbitdht/src/tests/bdmetric_test.cc deleted file mode 100644 index d0865794e..000000000 --- a/libbitdht/src/tests/bdmetric_test.cc +++ /dev/null @@ -1,264 +0,0 @@ -/* - * bitdht/bdmetric_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" -#include -#include - - -#include "utest.h" - -bool test_metric_explicit(); -bool test_metric_random(); - -INITTEST(); - -int main(int argc, char **argv) -{ - std::cerr << "libbitdht: " << argv[0] << std::endl; - - test_metric_explicit(); - - FINALREPORT("libbitdht: Metric Tests"); - return TESTRESULT(); -} - -bool test_metric_explicit() -{ - std::cerr << "test_metric_explicit:" << std::endl; - -#define NUM_IDS 6 - - /* create some ids */ - bdId id[NUM_IDS]; - int i, j; - - /* create a set of known ids ... and - * check the metrics are what we expect. - */ - - for(i = 0; i < NUM_IDS; i++) - { - bdZeroNodeId(&(id[i].id)); - } - - /* test the zero node works */ - for(i = 0; i < NUM_IDS; i++) - { - for(j = 0; j < BITDHT_KEY_LEN; j++) - { - CHECK(id[i].id.data[j] == 0); - } - } - - for(i = 0; i < NUM_IDS; i++) - { - for(j = i; j < NUM_IDS; j++) - { - id[j].id.data[BITDHT_KEY_LEN - i - 1] = 1; - } - } - - for(i = 0; i < NUM_IDS; i++) - { - fprintf(stderr, "id[%d]:", i+1); - bdStdPrintId(std::cerr,&(id[i])); - fprintf(stderr, "\n"); - } - - /* now do the sums */ - bdMetric met; - bdMetric met2; - int bdist = 0; - - for(i = 0; i < 6; i++) - { - for(j = i+1; j < 6; j++) - { - bdStdDistance(&(id[i].id), &(id[j].id), &met); - - fprintf(stderr, "%d^%d:", i, j); - bdStdPrintNodeId(std::cerr,&met); - fprintf(stderr, "\n"); - - bdist = bdStdBucketDistance(&met); - fprintf(stderr, " bucket: %d\n", bdist); - } - } - -#if 0 - int c1 = met < met2; - int c2 = met2 < met; - - fprintf(stderr, "1^2<1^3? : %d 1^3<1^2?: %d\n", c1, c2); -#endif - - - REPORT("Test Byte Manipulation"); - //FAILED("Couldn't Bind to socket"); - - return 1; -} - - - -bool test_metric_random() -{ - std::cerr << "test_metric_random:" << std::endl; - - /* create some ids */ - bdId id1; - bdId id2; - bdId id3; - bdId id4; - bdId id5; - bdId id6; - - bdStdRandomId(&id1); - bdStdRandomId(&id2); - bdStdRandomId(&id3); - bdStdRandomId(&id4); - bdStdRandomId(&id5); - bdStdRandomId(&id6); - - fprintf(stderr, "id1:"); - bdStdPrintId(std::cerr,&id1); - fprintf(stderr, "\n"); - - fprintf(stderr, "id2:"); - bdStdPrintId(std::cerr,&id2); - fprintf(stderr, "\n"); - - fprintf(stderr, "id3:"); - bdStdPrintId(std::cerr,&id3); - fprintf(stderr, "\n"); - - fprintf(stderr, "id4:"); - bdStdPrintId(std::cerr,&id4); - fprintf(stderr, "\n"); - - fprintf(stderr, "id5:"); - bdStdPrintId(std::cerr,&id5); - fprintf(stderr, "\n"); - - fprintf(stderr, "id6:"); - bdStdPrintId(std::cerr,&id6); - fprintf(stderr, "\n"); - - /* now do the sums */ - bdMetric met; - bdMetric met2; - int bdist = 0; - bdStdDistance(&(id1.id), &(id2.id), &met); - - fprintf(stderr, "1^2:"); - bdStdPrintNodeId(std::cerr,&met); - fprintf(stderr, "\n"); - bdist = bdStdBucketDistance(&met); - fprintf(stderr, " bucket: %d\n", bdist); - - bdStdDistance(&(id1.id), &(id3.id), &met2); - bdist = bdStdBucketDistance(&met2); - - fprintf(stderr, "1^3:"); - bdStdPrintNodeId(std::cerr,&met2); - fprintf(stderr, "\n"); - fprintf(stderr, " bucket: %d\n", bdist); - - int c1 = met < met2; - int c2 = met2 < met; - - fprintf(stderr, "1^2<1^3? : %d 1^3<1^2?: %d\n", c1, c2); - - - bdStdDistance(&(id1.id), &(id4.id), &met2); - bdist = bdStdBucketDistance(&met2); - - fprintf(stderr, "1^4:"); - bdStdPrintNodeId(std::cerr,&met2); - fprintf(stderr, "\n"); - fprintf(stderr, " bucket: %d\n", bdist); - - c1 = met < met2; - c2 = met2 < met; - - fprintf(stderr, "1^2<1^4? : %d 1^4<1^2?: %d\n", c1, c2); - - bdStdDistance(&(id1.id), &(id5.id), &met); - bdist = bdStdBucketDistance(&met); - - fprintf(stderr, "1^5:"); - bdStdPrintNodeId(std::cerr,&met); - fprintf(stderr, "\n"); - fprintf(stderr, " bucket: %d\n", bdist); - - bdStdDistance(&(id1.id), &(id6.id), &met); - bdist = bdStdBucketDistance(&met); - - fprintf(stderr, "1^6:"); - bdStdPrintNodeId(std::cerr,&met); - fprintf(stderr, "\n"); - fprintf(stderr, " bucket: %d\n", bdist); - - bdStdDistance(&(id2.id), &(id3.id), &met); - bdist = bdStdBucketDistance(&met); - - fprintf(stderr, "2^3:"); - bdStdPrintNodeId(std::cerr,&met); - fprintf(stderr, "\n"); - fprintf(stderr, " bucket: %d\n", bdist); - - - fprintf(stderr, "id1:"); - bdStdPrintId(std::cerr,&id1); - fprintf(stderr, "\n"); - - fprintf(stderr, "id2:"); - bdStdPrintId(std::cerr,&id2); - fprintf(stderr, "\n"); - - fprintf(stderr, "id3:"); - bdStdPrintId(std::cerr,&id3); - fprintf(stderr, "\n"); - - fprintf(stderr, "id4:"); - bdStdPrintId(std::cerr,&id4); - fprintf(stderr, "\n"); - - fprintf(stderr, "id5:"); - bdStdPrintId(std::cerr,&id5); - fprintf(stderr, "\n"); - - fprintf(stderr, "id6:"); - bdStdPrintId(std::cerr,&id6); - fprintf(stderr, "\n"); - - - return 1; -} - - diff --git a/libbitdht/src/tests/bdmgr_multitest.cc b/libbitdht/src/tests/bdmgr_multitest.cc deleted file mode 100644 index cfed76862..000000000 --- a/libbitdht/src/tests/bdmgr_multitest.cc +++ /dev/null @@ -1,186 +0,0 @@ -/* - * bitdht/bdmgr_multitest.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdmanager.h" -#include "bitdht/bdstddht.h" -#include "udp/udplayer.h" -#include "util/bdrandom.h" - -#include - -/********************************************************************************** - * tests of multi bdnodes all connected together. - * in these cases, the networking step is shortcut and the ip addresses ignored. - * instead the port number is used as an index to peers. - * - * test1() - * Small cross seeding, and static list of peers. - * Set it going - and see what happens. - */ - -std::map nodes; -std::map addrIdx; - -int main(int argc, char **argv) -{ - time_t sim_time = 600; - time_t starttime = time(NULL); - int n_nodes = 1000; - std::map::iterator it; - std::map::iterator nit; - std::map::iterator ait; - - int i, j; - - bdDhtFunctions *fns = new bdStdDht(); - - std::cerr << "bdmgr_multitest() Setting up Nodes" << std::endl; - /* setup nodes */ - for(i = 0; i < n_nodes; i++) - { - bdId id; - - bdStdRandomId(&id); - - //id.addr.sin_port = htons(i); - //((uint32_t *) (id.id.data))[0] = i * 16 * 16; /* force this so the sort order is maintained! */ - std::cerr << "bdmgr_multitest() Id: "; - fns->bdPrintId(std::cerr, &id); - std::cerr << std::endl; - - bdNodeManager *mgr = new bdNodeManager(&(id.id), "bdTEST", "", fns); - - /* Store in nodes */ - nodes[id] = mgr; - /* Store in indices */ - addrIdx[id.addr] = id; - - } - - std::cerr << "bdmgr_multitest() Cross Seeding" << std::endl; - /* do a little cross seeding */ - for(nit = nodes.begin(); nit != nodes.end(); nit++) - { - for(j = 0; j < 2; j++) - { - int peeridx = bdRandom::random_u32() % n_nodes; - for(i = 0, it = nodes.begin(); - (i < peeridx) && (it != nodes.end()); i++, it++) - { - /* empty */ - } - if (it != nodes.end()) - { - nit->second->addPotentialPeer((bdId *) &(it->first), NULL); - } - } - } - - /* ready to run */ - - std::cerr << "bdmgr_multitest() Simulation Time....." << std::endl; - i = 0; - while(time(NULL) < starttime + sim_time) - { - i++; - std::cerr << "bdmgr_multitest() Iteration: " << i << std::endl; - - for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) - { - /* extract messages to go -> and deliver */ -#define MAX_MSG_SIZE 10240 - struct sockaddr_in addr; - char data[MAX_MSG_SIZE]; - int len = MAX_MSG_SIZE; - - while(it->second->outgoingMsg(&addr, data, &len)) - { - std::cerr << "bdmgr_multitest() Msg from Peer: " << j; - - /* find the peer */ - ait = addrIdx.find(addr); - nit = nodes.end(); - if (ait != addrIdx.end()) - { - nit = nodes.find(ait->second); - std::cerr << " For: "; - fns->bdPrintId(std::cerr, &(nit->first)); - std::cerr << std::endl; - } - else - { - std::cerr << " For Unknown Destination"; - std::cerr << std::endl; - - } - - if (nit != nodes.end()) - { - /* set from address */ - nit->second->incomingMsg( (sockaddr_in *) &(it->first.addr), data, len); - } - /* reset message size */ - len = MAX_MSG_SIZE; - } - } - - for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) - { - /* tick */ - std::cerr << "bdmgr_multitest() Ticking peer: " << j << std::endl; - it->second->iteration(); - } - - - /* have a rest */ - sleep(1); - } - - std::cerr << "bdmgr_multitest() Displying States"<< std::endl; - for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) - { - /* tick */ - std::cerr << "bdmgr_multitest() Peer State: " << j << std::endl; - it->second->printState(); - } - -} - - - - - - - - - - - - - - - - diff --git a/libbitdht/src/tests/bdmidids_test.cc b/libbitdht/src/tests/bdmidids_test.cc deleted file mode 100644 index de52975cb..000000000 --- a/libbitdht/src/tests/bdmidids_test.cc +++ /dev/null @@ -1,96 +0,0 @@ -/* - * bitdht/bdmidids_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" -#include - -int main(int argc, char **argv) -{ - - /* Do this multiple times */ - int i, j; - - std::cerr << "Test Mid Peer Intersection....." << std::endl; - for(i = 0; i < 10; i++) - { - bdNodeId targetId; - bdNodeId peerId; - - bdStdRandomNodeId(&targetId); - bdStdRandomNodeId(&peerId); - - std::cerr << "-------------------------------------------------" << std::endl; - - for(j = 0; j < 10; j++) - { - - bdNodeId midId; - - bdStdRandomMidId(&targetId, &peerId, &midId); - - bdMetric TPmetric; - bdMetric TMmetric; - bdMetric PMmetric; - - bdStdDistance(&targetId, &peerId, &TPmetric); - bdStdDistance(&targetId, &midId, &TMmetric); - bdStdDistance(&peerId, &midId, &PMmetric); - - int TPdist = bdStdBucketDistance(&TPmetric); - int TMdist = bdStdBucketDistance(&TMmetric); - int PMdist = bdStdBucketDistance(&PMmetric); - - std::cerr << "Target: "; - bdStdPrintNodeId(std::cerr,&targetId); - std::cerr << " Peer: "; - bdStdPrintNodeId(std::cerr,&peerId); - std::cerr << std::endl; - - std::cerr << "\tTarget ^ Peer: "; - bdStdPrintNodeId(std::cerr,&TPmetric); - std::cerr << " Bucket: " << TPdist; - std::cerr << std::endl; - - std::cerr << "\tTarget ^ Mid: "; - bdStdPrintNodeId(std::cerr,&TMmetric); - std::cerr << " Bucket: " << TMdist; - std::cerr << std::endl; - - std::cerr << "\tPeer ^ Mid: "; - bdStdPrintNodeId(std::cerr,&PMmetric); - std::cerr << " Bucket: " << PMdist; - std::cerr << std::endl; - - /* now save mid to peer... and repeat */ - peerId = midId; - } - } - - return 1; -} - - diff --git a/libbitdht/src/tests/bdmsgs_test.cc b/libbitdht/src/tests/bdmsgs_test.cc deleted file mode 100644 index cdfaed7d2..000000000 --- a/libbitdht/src/tests/bdmsgs_test.cc +++ /dev/null @@ -1,102 +0,0 @@ - -/* - * bitdht/bdmsgs_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdmsgs.h" -#include "bitdht/bdstddht.h" -#include - -/******************************************************************* - * Test of bencode message creation functions in bdmsgs.cc - * - * Create a couple of each type. - */ - -#define MAX_MESSAGE_LEN 10240 - -int main(int argc, char **argv) -{ - /***** create messages *****/ - char msg[MAX_MESSAGE_LEN]; - int avail = MAX_MESSAGE_LEN -1; - - bdToken tid; - bdToken vid; - bdToken token; - - - bdNodeId ownId; - bdNodeId peerId; - bdNodeId target; - bdNodeId info_hash; - - bdStdRandomNodeId(&ownId); - bdStdRandomNodeId(&peerId); - bdStdRandomNodeId(&target); - bdStdRandomNodeId(&info_hash); - - std::list nodes; - std::list values; - - /* setup tokens */ - strncpy((char*)tid.data, "tid", 4); - strncpy((char*)vid.data, "RS50", 5); - strncpy((char*)token.data, "ToKEn", 6); - - tid.len = 3; - vid.len = 4; - token.len = 5; - - /* setup lists */ - for(int i = 0; i < 8; i++) - { - bdId rndId; - bdStdRandomId(&rndId); - - nodes.push_back(rndId); - values.push_back("values"); - } - - uint32_t port = 1234; - - bitdht_create_ping_msg(&tid, &ownId, msg, avail); - bitdht_response_ping_msg(&tid, &ownId, &vid, msg, avail); - - bitdht_find_node_msg(&tid, &ownId, &target, msg, avail); - bitdht_resp_node_msg(&tid, &ownId, nodes, msg, avail); - - bitdht_get_peers_msg(&tid, &ownId, &info_hash, msg, avail); - bitdht_peers_reply_hash_msg(&tid, &ownId, &token, values, msg, avail); - bitdht_peers_reply_closest_msg(&tid, &ownId, &token, nodes, msg, avail); - - bitdht_announce_peers_msg(&tid, &ownId, &info_hash, port, &token, msg, avail); - bitdht_reply_announce_msg(&tid, &ownId, msg, avail); - - - return 1; -} - - diff --git a/libbitdht/src/tests/bdnode_multitest1.cc b/libbitdht/src/tests/bdnode_multitest1.cc deleted file mode 100644 index 5e1a6ebca..000000000 --- a/libbitdht/src/tests/bdnode_multitest1.cc +++ /dev/null @@ -1,185 +0,0 @@ -/* - * bitdht/bdnode_multitest1.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdnode.h" -#include "bitdht/bdstddht.h" -#include "util/bdrandom.h" - -#include - -/********************************************************************************** - * tests of multi bdnodes all connected together. - * in these cases, the networking step is shortcut and the ip addresses ignored. - * instead the port number is used as an index to peers. - * - * test1() - * Small cross seeding, and static list of peers. - * Set it going - and see what happens. - */ - -std::map nodes; -std::map portIdx; - -int main(int argc, char **argv) -{ - time_t sim_time = 60; - time_t starttime = time(NULL); - int n_nodes = 10; - std::map::iterator it; - std::map::iterator nit; - std::map::iterator pit; - - int i, j; - - bdDhtFunctions *fns = new bdStdDht(); - - std::cerr << "bdnode_multitest1() Setting up Nodes" << std::endl; - /* setup nodes */ - for(i = 0; i < n_nodes; i++) - { - bdId id; - - bdStdRandomId(&id); - - id.addr.sin_port = htons(i); - ((uint32_t *) (id.id.data))[0] = i * 16 * 16; /* force this so the sort order is maintained! */ - std::cerr << "bdnode_multitest1() Id: "; - fns->bdPrintId(std::cerr, &id); - std::cerr << std::endl; - - bdNode *node = new bdNode(&(id.id), "bdTEST", "", fns); - - /* Store in nodes */ - nodes[id] = node; - /* Store in indices */ - portIdx[i] = id; - - } - - std::cerr << "bdnode_multitest1() Cross Seeding" << std::endl; - /* do a little cross seeding */ - for(i = 0; i < n_nodes; i++) - { - bdId nid = portIdx[i]; - bdNode *node = nodes[nid]; - - for(j = 0; j < 5; j++) - { - int peeridx = bdRandom::random_u32() % n_nodes; - - bdId pid = portIdx[peeridx]; - node->addPotentialPeer(&pid, NULL); - } - } - - /* ready to run */ - - std::cerr << "bdnode_multitest1() Simulation Time....." << std::endl; - i = 0; - while(time(NULL) < starttime + sim_time) - { - i++; - std::cerr << "bdnode_multitest1() Iteration: " << i << std::endl; - - for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) - { - /* extract messages to go -> and deliver */ -#define MAX_MSG_SIZE 10240 - struct sockaddr_in addr; - char data[MAX_MSG_SIZE]; - int len = MAX_MSG_SIZE; - - while(it->second->outgoingMsg(&addr, data, &len)) - { - std::cerr << "bdnode_multitest1() Msg from Peer: " << j; - - /* find the peer */ - int peeridx = htons(addr.sin_port); - pit = portIdx.find(peeridx); - nit = nodes.end(); - if (pit != portIdx.end()) - { - nit = nodes.find(pit->second); - std::cerr << " For: "; - fns->bdPrintId(std::cerr, &(nit->first)); - std::cerr << std::endl; - } - else - { - std::cerr << " For Unknown Destination"; - std::cerr << std::endl; - - } - - if (nit != nodes.end()) - { - /* set from address */ - nit->second->incomingMsg( (sockaddr_in *) &(it->first.addr), data, len); - } - /* reset message size */ - len = MAX_MSG_SIZE; - } - } - - for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) - { - /* tick */ - std::cerr << "bdnode_multitest1() Ticking peer: " << j << std::endl; - it->second->iteration(); - } - - if (i % 5 == 0) - { - std::cerr << "bdnode_multitest1() Displying States"<< std::endl; - for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) - { - /* tick */ - std::cerr << "bdnode_multitest1() Peer State: " << j << std::endl; - it->second->printState(); - } - } - - - /* have a rest */ - sleep(1); - } -} - - - - - - - - - - - - - - - - diff --git a/libbitdht/src/tests/bdnode_test.cc b/libbitdht/src/tests/bdnode_test.cc deleted file mode 100644 index 848a27e7c..000000000 --- a/libbitdht/src/tests/bdnode_test.cc +++ /dev/null @@ -1,90 +0,0 @@ -/* - * bitdht/bdnode_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdquery.h" -#include "bitdht/bdnode.h" - -#define N_PEERS_TO_ADD_INIT 10 -#define N_PEERS_TO_ADD 11 -#define N_PEERS_TO_START 10 -#define N_PEERS_TO_PRINT 1 -#define N_QUERIES 2 - -int main(int argc, char **argv) -{ - - /* create some ids */ - bdDhtFunctions *fns = new bdStdDht(); - - bdNodeId ownId; - bdStdRandomNodeId(&ownId); - - bdNode node(&ownId, "bdTEST","./dht.log", fns); - - int i = 0; - for (i = 0; i < N_PEERS_TO_ADD_INIT; i++) - { - bdId tmpId; - bdStdRandomId(&tmpId); - - node.addPeer(&tmpId, 0); - } - - node.printState(); - -#if 0 - for(i = 0; i < N_QUERIES; i++) - { - /* create a query */ - bdNodeId queryId; - bdStdRandomNodeId(&queryId); - - node.addQuery(&queryId, 0); - } -#endif - - node.printState(); - - for (i = 0; i < N_PEERS_TO_ADD; i++) - { - bdId tmpId; - bdStdRandomId(&tmpId); - - node.addPeer(&tmpId, 0); - - if (i % N_PEERS_TO_PRINT == 0) - { - node.printState(); - node.iteration(); - sleep(5); - } - } - - return 1; -} - - diff --git a/libbitdht/src/tests/bdnode_test2.cc b/libbitdht/src/tests/bdnode_test2.cc deleted file mode 100644 index 1e4b16b68..000000000 --- a/libbitdht/src/tests/bdnode_test2.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* - * bitdht/bdnode_test2.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdquery.h" -#include "bitdht/bdnode.h" - -#define N_PEERS_TO_ADD_INIT 10 -#define N_PEERS_TO_ADD 11 -#define N_PEERS_TO_START 10 -#define N_PEERS_TO_PRINT 1 -#define N_QUERIES 2 - -int main(int argc, char **argv) -{ - - /* create some ids */ - bdNodeId ownId; - bdStdRandomNodeId(&ownId); - bdDhtFunctions *fns = new bdStdDht(); - - bdNode node(&ownId, "bdTEST", "./dht.log", fns); - - while(1) - { - node.iteration(); - sleep(1); - } - - return 1; -} - - diff --git a/libbitdht/src/tests/bdquery_test.cc b/libbitdht/src/tests/bdquery_test.cc deleted file mode 100644 index b4c8e980b..000000000 --- a/libbitdht/src/tests/bdquery_test.cc +++ /dev/null @@ -1,83 +0,0 @@ -/* - * bitdht/bdquery_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdquery.h" - -#define N_PEERS_TO_ADD 10000 -#define N_PEERS_TO_PRINT 1000 -#define N_PEERS_TO_START 10 - -int main(int argc, char **argv) -{ - - /* create some ids */ - bdNodeId ownId; - bdStdRandomNodeId(&ownId); - - bdDhtFunctions *fns = new bdStdDht(); - - bdSpace space(&ownId, fns); - int i = 0; - for (i = 0; i < N_PEERS_TO_ADD; i++) - { - bdId tmpId; - bdStdRandomId(&tmpId); - - space.add_peer(&tmpId, 0); - } - - space.printDHT(); - - /* create a query */ - bdId queryId; - bdStdRandomId(&queryId); - - - - std::list startList; - std::multimap nearest; - std::multimap::iterator it; - - space.find_nearest_nodes(&(queryId.id), N_PEERS_TO_START, nearest); - - for(it = nearest.begin(); it != nearest.end(); it++) - { - startList.push_back(it->second); - } - - bdQuery query(&(queryId.id), startList, BITDHT_QFLAGS_DISGUISE, fns); - - /* */ - - query.printQuery(); - - - return 1; -} - - diff --git a/libbitdht/src/tests/bdspace_test.cc b/libbitdht/src/tests/bdspace_test.cc deleted file mode 100644 index ead78c683..000000000 --- a/libbitdht/src/tests/bdspace_test.cc +++ /dev/null @@ -1,60 +0,0 @@ -/* - * bitdht/bdspace_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" - -#define N_PEERS_TO_ADD 10000 -#define N_PEERS_TO_PRINT 1000 - -int main(int argc, char **argv) -{ - - /* create some ids */ - bdNodeId ownId; - bdStdRandomNodeId(&ownId); - bdDhtFunctions *fns = new bdStdDht(); - - bdSpace space(&ownId, fns); - int i = 0; - for (i = 0; i < N_PEERS_TO_ADD; i++) - { - bdId tmpId; - bdStdRandomId(&tmpId); - - space.add_peer(&tmpId, 0); - - if (i % N_PEERS_TO_PRINT == 0) - { - space.printDHT(); - } - } - space.printDHT(); - - return 1; -} - - diff --git a/libbitdht/src/tests/bdspace_test2.cc b/libbitdht/src/tests/bdspace_test2.cc deleted file mode 100644 index ca9e7f024..000000000 --- a/libbitdht/src/tests/bdspace_test2.cc +++ /dev/null @@ -1,67 +0,0 @@ -/* - * bitdht/bdspace_test2.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" - -#define N_PEERS_TO_ADD 10000 -#define N_PEERS_TO_TEST 100 -#define N_PEERS_TO_FIND 10 - -int main(int argc, char **argv) -{ - - /* create some ids */ - bdNodeId ownId; - bdStdRandomNodeId(&ownId); - bdDhtFunctions *fns = new bdStdDht(); - - bdSpace space(&ownId, fns); - int i = 0; - for (i = 0; i < N_PEERS_TO_ADD; i++) - { - bdId tmpId; - bdStdRandomId(&tmpId); - space.add_peer(&tmpId, 0); - } - - space.printDHT(); - - - /* now generate random id's and test closeness */ - for(i = 0; i < N_PEERS_TO_TEST; i++) - { - bdId tmpId; - bdStdRandomId(&tmpId); - std::multimap list2; - - space.find_nearest_nodes(&(tmpId.id), N_PEERS_TO_FIND, list2); - } - - return 1; -} - - diff --git a/libbitdht/src/tests/bdstore_test.cc b/libbitdht/src/tests/bdstore_test.cc deleted file mode 100644 index c1207def5..000000000 --- a/libbitdht/src/tests/bdstore_test.cc +++ /dev/null @@ -1,47 +0,0 @@ -/* - * bitdht/bdstore_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdstore.h" -#include "bitdht/bdstddht.h" - -#include -#include - -int main(int argc, char **argv) -{ - /* load store */ - if (argc < 2) - { - fprintf(stderr, "Missing Store File\n"); - exit(1); - } - - bdDhtFunctions *fns = new bdStdDht(); - bdStore store(argv[1], fns); - return 1; -} - - diff --git a/libbitdht/src/tests/bdudp_test.cc b/libbitdht/src/tests/bdudp_test.cc deleted file mode 100644 index 4b9d581bd..000000000 --- a/libbitdht/src/tests/bdudp_test.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* - * bitdht/bdudp_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdpeer.h" -#include "bitdht/bdquery.h" -#include "udp/udpbitdht.h" - -#define N_PEERS_TO_ADD 10000 -#define N_PEERS_TO_PRINT 1000 -#define N_PEERS_TO_START 10 - -int main(int argc, char **argv) -{ - - /* create some ids */ - bdId ownId; - bdRandomId(&ownId); - - - struct sockaddr_in local; - local.sin_addr.s_addr = 0; - local.sin_port = htons(7812); - std::string bootstrapfile = "dht.log"; - - bdId bid; - - bid.addr = local; - bid.id = ownId.id; - - UdpBitDht ubd(local, 0, &bid, bootstrapfile); - - - - while(1) - { - ubd.tick(); - sleep(1); - } - - return 1; -} - - diff --git a/libbitdht/src/tests/bencode_test.cc b/libbitdht/src/tests/bencode_test.cc deleted file mode 100644 index 8d35c0678..000000000 --- a/libbitdht/src/tests/bencode_test.cc +++ /dev/null @@ -1,182 +0,0 @@ -/* - * bitdht/bencode_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bencode.h" -#include - -int main(int argc, char **argv) -{ - - char msg[100]; - - msg[0] = 'd'; - msg[1] = '1'; - msg[2] = ':'; - msg[3] = 't'; - msg[4] = 'L'; - msg[5] = 'b'; - msg[6] = 'U'; - msg[7] = 0xd9; - msg[8] = 0xfa; - msg[9] = 0xff; - msg[10] = 0xff; - msg[11] = 0xff; - msg[12] = 0xff; - msg[13] = '\n'; - msg[14] = 'H'; - msg[15] = '#'; - msg[16] = '#'; - msg[17] = '#'; - msg[18] = '#'; - msg[19] = '#'; - msg[20] = '#'; - msg[21] = '#'; - - be_node *n = be_decoden(msg, 16); - - if (n) - { - be_dump(n); - be_free(n); - } - else - { - fprintf(stderr, "didn't crash!\n"); - } - - msg[0] = 'd'; - msg[1] = '1'; - msg[2] = ':'; - msg[3] = 'a'; - msg[4] = 'L'; - msg[5] = 0x8d; - msg[6] = 0xd6; - msg[7] = '\r'; - msg[8] = 0x9d; - msg[9] = ';'; - msg[10] = 0xff; - msg[11] = 0xff; - msg[12] = 0xff; - msg[13] = 0xff; - msg[14] = 'H'; - msg[15] = '#'; - msg[16] = '#'; - msg[17] = '#'; - msg[18] = '#'; - msg[19] = '#'; - msg[20] = '#'; - msg[21] = '#'; - - n = be_decoden(msg, 14); - - if (n) - { - be_dump(n); - be_free(n); - } - else - { - fprintf(stderr, "didn't crash!\n"); - } - - msg[0] = 'd'; - msg[1] = '1'; - msg[2] = ':'; - msg[3] = 't'; - msg[4] = '4'; - msg[5] = ':'; - msg[6] = 'a'; - msg[7] = 'b'; - msg[8] = 'c'; - msg[9] = 'd'; - msg[10] = '1'; - msg[11] = ':'; - msg[12] = 'y'; - msg[13] = '1'; - msg[14] = ':'; - msg[15] = 'r'; - msg[16] = '1'; - msg[17] = ':'; - msg[18] = 'r'; - msg[19] = 'd'; - msg[20] = '2'; - msg[21] = ':'; - msg[22] = 'i'; - msg[23] = 'd'; - msg[24] = '2'; - msg[25] = '0'; - msg[26] = ':'; - msg[27] = '1'; - msg[28] = '2'; - msg[29] = '3'; - msg[30] = '4'; - msg[31] = '5'; - msg[32] = '6'; - msg[33] = '7'; - msg[34] = '8'; - msg[35] = '9'; - msg[36] = '0'; - msg[37] = 'a'; - msg[38] = 'b'; - msg[39] = 'c'; - msg[40] = 'd'; - msg[41] = 'e'; - msg[42] = 'f'; - msg[43] = 'g'; - msg[44] = 'h'; - msg[45] = 'i'; - msg[46] = '.'; - msg[47] = '5'; - msg[48] = ':'; - msg[49] = 'n'; - msg[50] = 'o'; - msg[51] = 'd'; - msg[52] = 'e'; - msg[53] = 's'; - msg[54] = '2'; - msg[55] = '0'; - msg[56] = '8'; - msg[57] = ':'; - msg[58] = '\0'; - msg[59] = '\0'; - msg[60] = '\0'; - - n = be_decoden(msg, 58); - - if (n) - { - be_dump(n); - be_free(n); - } - else - { - fprintf(stderr, "didn't crash!\n"); - } - - return 1; -} - - diff --git a/libbitdht/src/tests/scripts/checks.mk b/libbitdht/src/tests/scripts/checks.mk deleted file mode 100644 index dfccbdedf..000000000 --- a/libbitdht/src/tests/scripts/checks.mk +++ /dev/null @@ -1,19 +0,0 @@ -#Basic checks - -ifndef TEST_TOP_DIR -dummy: - echo "TEST_TOP_DIR is not defined in your makefile" -endif - -ifneq ($(OS),Linux) - ifneq ($(OS),MacOSX) - ifndef PTHREADS_DIR -dummy: - echo "you must define PTHREADS_DIR before you can compile" - - endif - endif -endif - - - diff --git a/libbitdht/src/tests/scripts/config-cygwin.mk b/libbitdht/src/tests/scripts/config-cygwin.mk deleted file mode 100644 index ec4518f68..000000000 --- a/libbitdht/src/tests/scripts/config-cygwin.mk +++ /dev/null @@ -1,118 +0,0 @@ -ifneq ($(OS),Cygwin) -dummy: - echo "ERROR Cygwin configuration file included, but (OS != Cygwin) - -endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -PQI_USE_XPGP = 1 -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -########################################################################### - -#### DrBobs Versions.... Please Don't Delete. -### Comment out if needed. -ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW -SRC_ROOT=../../../.. - -PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads/pthreads.2 - -################### - -#ALT_SRC_ROOT=/cygdrive/c/RetroShareBuild/src -#SRC_ROOT=/cygdrive/c/RetroShareBuild/src - -#PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads-w32-2-8-0-release - -################### - -ZLIB_DIR=$(ALT_SRC_ROOT)/zlib-1.2.3 - -SSL_DIR=$(SRC_ROOT)/openssl-0.9.7g-xpgp-0.1c -UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) - -ifdef PQI_DEBUG - CFLAGS = -Wall -g $(INCLUDE) -else - CFLAGS = -Wall -O2 $(INCLUDE) -endif - -ifdef PQI_USE_XPGP - INCLUDE += -I $(SSL_DIR)/include -endif - -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -RSCFLAGS = -Wall -g $(INCLUDE) - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# Cygwin - ?same? as Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM - -######################################################################### -# OS specific Linking. -######################################################################### - -# for static pthread libs.... -WININC += -DPTW32_STATIC_LIB -WININC += -mno-cygwin -mwindows -fno-exceptions -WININC += -DWINDOWS_SYS - -WINLIB = -lws2_32 -luuid -lole32 -liphlpapi -WINLIB += -lcrypt32 -lwinmm - -CFLAGS += -I$(PTHREADS_DIR) $(WININC) -CFLAGS += -I$(ZLIB_DIR) - -LIBS = -L$(LIBDIR) -lretroshare -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) -endif - -LIBS += -lssl -lcrypto -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += -L$(ZLIB_DIR) -lz -LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d -LIBS += $(WINLIB) - -RSCFLAGS += $(WININC) - - diff --git a/libbitdht/src/tests/scripts/config-linux.mk b/libbitdht/src/tests/scripts/config-linux.mk deleted file mode 100644 index 182f9c39a..000000000 --- a/libbitdht/src/tests/scripts/config-linux.mk +++ /dev/null @@ -1,41 +0,0 @@ - -ifneq ($(OS),Linux) -dummy: - echo "ERROR Linux configuration file included, but (OS != Linux) - -endif - -############ LINUX CONFIGURATION ######################## - -include $(TEST_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(LIB_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(LIB_TOP_DIR) -CFLAGS = -Wall -g $(INCLUDE) -CFLAGS += ${DEFINES} -D BE_DEBUG - -######################################################################### -# OS Compile Options -######################################################################### - -######################################################################### -# OS specific Linking. -######################################################################### - -LIBS = -L$(LIBDIR) -lbitdht -LIBS += -lpthread -#LIBS += $(XLIB) -ldl -lz -#LIBS += -lupnp -#LIBS += -lgpgme -# -#RSLIBS = $(LIBS) - - diff --git a/libbitdht/src/tests/scripts/config-macosx.mk b/libbitdht/src/tests/scripts/config-macosx.mk deleted file mode 100644 index ecf95733d..000000000 --- a/libbitdht/src/tests/scripts/config-macosx.mk +++ /dev/null @@ -1,81 +0,0 @@ - -ifneq ($(OS),MacOSX) -dummy: - echo "ERROR MacOSX configuration file included, but (OS != MacOSX) - -endif - -############ MACOSX CONFIGURATION ######################## - - -# FLAGS to decide if we want i386 Build or ppc Build -# -# - -# MAC_I386_BUILD = 1 -# MAC_PPC_BUILD = 1 - -MAC_I386_BUILD = 1 -#MAC_PPC_BUILD = 1 - -ifndef MAC_I386_BUILD - MAC_PPC_BUILD = 1 -endif - -include $(TEST_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm - -RANLIB = ranlib - -# Dummy ranlib -> can't do it until afterwards with universal binaries. -# RANLIB = ls -l - -LIBDIR = $(LIB_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -OPT_DIR = /opt/local -OPT_INCLUDE = $(OPT_DIR)/include -OPT_LIBS = $(OPT_DIR)/lib - -INCLUDE = -I $(LIB_TOP_DIR) -#-I $(OPT_INCLUDE) -#CFLAGS = -Wall -O3 -CFLAGS = -Wall -g - -# Flags for architecture builds. -ifdef MAC_I386_BUILD - CFLAGS += -arch i386 -endif - -ifdef MAC_PPC_BUILD - CFLAGS += -arch ppc -endif - -CFLAGS += $(INCLUDE) - -# This Line is for Universal BUILD for 10.4 + 10.5 -# (but unlikely to work unless Qt Libraries are build properly) -#CFLAGS += -isysroot /Developer/SDKs/MacOSX10.5.sdk - -######################################################################### -# OS Compile Options -######################################################################### - -######################################################################### -# OS specific Linking. -######################################################################### - -#LIBS = -Wl,-search_paths_first - -# for Univeral BUILD -# LIBS += -arch ppc -arch i386 -# LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386 - -#LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.5.sdk -LIBS += -L$(LIBDIR) -lbitdht - - diff --git a/libbitdht/src/tests/scripts/config-mingw.mk b/libbitdht/src/tests/scripts/config-mingw.mk deleted file mode 100644 index c0040ac4e..000000000 --- a/libbitdht/src/tests/scripts/config-mingw.mk +++ /dev/null @@ -1,138 +0,0 @@ -#ifneq ($(OS),"Win ") -#dummy: -# echo "ERROR OS = $(OS)" -# echo "ERROR MinGW configuration file included, but (OS != Win) -# -#endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -#PQI_USE_XPGP = 1 -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -########################################################################### - -#### DrBobs Versions.... Please Don't Delete. -### Comment out if needed. -SRC_ROOT_PKG=/home/Mark/prog/retroshare/package/rs-win-v0.5.0/src -SRC_ROOT_GPG=/local - -#ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW -#SRC_ROOT=../../../.. - -PTHREADS_DIR=$(SRC_ROOT_PKG)/pthreads-w32-2-8-0/Pre-built.2 -ZLIB_DIR=$(SRC_ROOT_PKG)/zlib-1.2.3 -SSL_DIR=$(SRC_ROOT_PKG)/openssl-tmp -UPNPC_DIR=$(SRC_ROOT_PKG)/miniupnpc-1.3 - -########################################################################### - -#### Enable this section for compiling with MSYS/MINGW compile -#SRC_ROOT=/home/linux - -#SSL_DIR=$(SRC_ROOT)/OpenSSL -#GPGME_DIR=$(SRC_ROOT)/gpgme-1.1.8 -#GPG_ERROR_DIR=$(SRC_ROOT)/libgpg-error-1.7 - -#ZLIB_DIR=$(SRC_ROOT)/zlib-1.2.3 -#UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 -#PTHREADS_DIR=$(SRC_ROOT)/pthreads-w32-2-8-0-release - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ####################################### - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) - -ifdef PQI_DEBUG - CFLAGS = -Wall -g $(INCLUDE) -else - CFLAGS = -Wall -O2 $(INCLUDE) -endif - -# These aren't used anymore.... really. -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -# SSL / pthreads / Zlib -# included by default for Windows compilation. -INCLUDE += -I $(SSL_DIR)/include -INCLUDE += -I$(PTHREADS_DIR) -INCLUDE += -I$(ZLIB_DIR) - - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# Cygwin - ?same? as Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM -BIOCFLAGS += -DWINDOWS_SYS - -######################################################################### -# OS specific Linking. -######################################################################### - -# for static pthread libs.... -#WININC += -DPTW32_STATIC_LIB -#WININC += -mno-cygwin -mwindows -fno-exceptions - -WININC += -DWINDOWS_SYS - -WINLIB = -lws2_32 -luuid -lole32 -liphlpapi -WINLIB += -lcrypt32 -lwinmm - -CFLAGS += -I$(SSL_DIR)/include -CFLAGS += -I$(PTHREADS_DIR)/include -CFLAGS += -I$(ZLIB_DIR) -CFLAGS += -I$(SRC_ROOT_GPG)/include - -### Enable this for GPGME and GPG ERROR dirs -#CFLAGS += -I$(GPGME_DIR)/src -#CFLAGS += -I$(GPG_ERROR_DIR)/src - -CFLAGS += $(WININC) - - - -LIBS = -L$(LIBDIR) -lretroshare - -LIBS += -L$(SSL_DIR) - -LIBS += -lssl -lcrypto -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += -L$(ZLIB_DIR) -lz -LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d -LIBS += $(WINLIB) - -#RSCFLAGS = -Wall -g $(INCLUDE) -#RSCFLAGS += $(WININC) - - diff --git a/libbitdht/src/tests/scripts/config.mk b/libbitdht/src/tests/scripts/config.mk deleted file mode 100644 index 0859a4799..000000000 --- a/libbitdht/src/tests/scripts/config.mk +++ /dev/null @@ -1,27 +0,0 @@ - -# determine which operating system -# -########################################################################### -#Define OS. -# -OS = Linux -#OS = MacOSX -#OS = Cygwin -#OS = Win # MinGw. -########################################################################### - -ifeq ($(OS),Linux) - include $(TEST_TOP_DIR)/scripts/config-linux.mk -else - ifeq ($(OS),MacOSX) - include $(TEST_TOP_DIR)/scripts/config-macosx.mk - else - ifeq ($(OS),Cygwin) - include $(TEST_TOP_DIR)/scripts/config-cygwin.mk - else - include $(TEST_TOP_DIR)/scripts/config-mingw.mk - endif - endif -endif - -########################################################################### diff --git a/libbitdht/src/tests/scripts/regress.mk b/libbitdht/src/tests/scripts/regress.mk deleted file mode 100644 index f80b48451..000000000 --- a/libbitdht/src/tests/scripts/regress.mk +++ /dev/null @@ -1,25 +0,0 @@ - -testoutputfiles = $(foreach tt,$(1),$(tt).tstout) - -%.tstout : %.sh - -sh ./$< > $@ 2>&1 - -%.tstout : % - -./$< > $@ 2>&1 - -TESTOUT = $(call testoutputfiles,$(TESTS)) - -.phony : tests regress retest clobber - -tests: $(TESTS) - -regress: $(TESTOUT) - @-echo "--------------- SUCCESS (count):" - @-grep -c SUCCESS $(TESTOUT) - @-echo "--------------- FAILURE REPORTS:" - @-grep FAILURE $(TESTOUT) || echo no failures - @-echo "--------------- end" - -retest: - -/bin/rm $(TESTOUT) - diff --git a/libbitdht/src/tests/scripts/rules.mk b/libbitdht/src/tests/scripts/rules.mk deleted file mode 100644 index 9166e80a4..000000000 --- a/libbitdht/src/tests/scripts/rules.mk +++ /dev/null @@ -1,19 +0,0 @@ - -# defines required / used. -# -# CFLAGS -# -# - -.cc.o: - $(CC) $(CFLAGS) -c $< - -clean: - -/bin/rm $(EXECOBJ) $(TESTOBJ) - -clobber: clean retest - -/bin/rm $(EXEC) $(TESTS) - - -include $(TEST_TOP_DIR)/scripts/regress.mk - diff --git a/libbitdht/src/tests/udpbitdht_nettest.cc b/libbitdht/src/tests/udpbitdht_nettest.cc deleted file mode 100644 index 0dbb634b2..000000000 --- a/libbitdht/src/tests/udpbitdht_nettest.cc +++ /dev/null @@ -1,278 +0,0 @@ -/* - * bitdht/udpbitdht_nettest.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "udp/udpbitdht.h" -#include "udp/udpstack.h" -#include "bitdht/bdstddht.h" - -#include -#include - -/******************************************************************* - * DHT test program. - * - * - * Create a couple of each type. - */ - -#define MAX_MESSAGE_LEN 10240 - -int args(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " -p "; - std::cerr << " -b "; - std::cerr << " -u "; - std::cerr << " -q "; - std::cerr << " -r (do dht restarts) "; - std::cerr << " -j (do join test) "; - std::cerr << std::endl; - return 1; -} - -#define DEF_PORT 7500 - -#define MIN_DEF_PORT 1001 -#define MAX_DEF_PORT 16000 - -#define DEF_BOOTFILE "bdboot.txt" - -int main(int argc, char **argv) -{ - int c; - int port = DEF_PORT; - std::string bootfile = DEF_BOOTFILE; - std::string uid; - bool setUid = false; - bool doRandomQueries = false; - bool doRestart = false; - bool doThreadJoin = false; - int noQueries = 0; - - while((c = getopt(argc, argv,"rjp:b:u:q:")) != -1) - { - switch (c) - { - case 'r': - doRestart = true; - break; - case 'j': - doThreadJoin = true; - break; - case 'p': - { - int tmp_port = atoi(optarg); - if ((tmp_port > MIN_DEF_PORT) && (tmp_port < MAX_DEF_PORT)) - { - port = tmp_port; - std::cerr << "Port: " << port; - std::cerr << std::endl; - } - else - { - std::cerr << "Invalid Port"; - std::cerr << std::endl; - args(argv[0]); - return 1; - } - - } - break; - case 'b': - { - bootfile = optarg; - std::cerr << "Bootfile: " << bootfile; - std::cerr << std::endl; - } - break; - case 'u': - { - setUid = true; - uid = optarg; - std::cerr << "UID: " << uid; - std::cerr << std::endl; - } - break; - case 'q': - { - doRandomQueries = true; - noQueries = atoi(optarg); - std::cerr << "Doing Random Queries"; - std::cerr << std::endl; - } - break; - - default: - { - args(argv[0]); - return 1; - } - break; - } - } - - - bdDhtFunctions *fns = new bdStdDht(); - - bdNodeId id; - - /* start off with a random id! */ - bdStdRandomNodeId(&id); - - if (setUid) - { - int len = uid.size(); - if (len > 20) - { - len = 20; - } - - for(int i = 0; i < len; i++) - { - id.data[i] = uid[i]; - } - } - - std::cerr << "Using NodeId: "; - fns->bdPrintNodeId(std::cerr, &id); - std::cerr << std::endl; - - /* setup the udp port */ - struct sockaddr_in local; - memset(&local, 0, sizeof(local)); - local.sin_family = AF_INET; - local.sin_addr.s_addr = 0; - local.sin_port = htons(port); - UdpStack *udpstack = new UdpStack(local); - - /* create bitdht component */ - std::string dhtVersion = "dbTEST"; - UdpBitDht *bitdht = new UdpBitDht(udpstack, &id, dhtVersion, bootfile, fns); - - /* add in the stack */ - udpstack->addReceiver(bitdht); - - /* register callback display */ - bdDebugCallback *cb = new bdDebugCallback(); - bitdht->addCallback(cb); - - /* startup threads */ - //udpstack->start(); - bitdht->start(); - - - - - /* do a couple of random continuous searchs. */ - - uint32_t mode = BITDHT_QFLAGS_DO_IDLE; - - int count = 0; - int running = 1; - - std::cerr << "Starting Dht: "; - std::cerr << std::endl; - bitdht->startDht(); - - - if (doRandomQueries) - { - for(int i = 0; i < noQueries; i++) - { - bdNodeId rndId; - bdStdRandomNodeId(&rndId); - - std::cerr << "BitDht Launching Random Search: "; - bdStdPrintNodeId(std::cerr, &rndId); - std::cerr << std::endl; - - bitdht->addFindNode(&rndId, mode); - - } - } - - while(1) - { - sleep(60); - - std::cerr << "BitDht State: "; - std::cerr << bitdht->stateDht(); - std::cerr << std::endl; - - std::cerr << "Dht Network Size: "; - std::cerr << bitdht->statsNetworkSize(); - std::cerr << std::endl; - - std::cerr << "BitDht Network Size: "; - std::cerr << bitdht->statsBDVersionSize(); - std::cerr << std::endl; - - if (++count == 2) - { - /* switch to one-shot searchs */ - mode = 0; - } - - if (doThreadJoin) - { - /* change address */ - if (count % 2 == 0) - { - - std::cerr << "Resetting UdpStack: "; - std::cerr << std::endl; - - udpstack->resetAddress(local); - } - } - if (doRestart) - { - if (count % 2 == 1) - { - if (running) - { - - std::cerr << "Stopping Dht: "; - std::cerr << std::endl; - - bitdht->stopDht(); - running = 0; - } - else - { - std::cerr << "Starting Dht: "; - std::cerr << std::endl; - - bitdht->startDht(); - running = 1; - } - } - } - } - return 1; -} - - diff --git a/libbitdht/src/tests/utest.h b/libbitdht/src/tests/utest.h deleted file mode 100644 index 1ebd9875a..000000000 --- a/libbitdht/src/tests/utest.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _UNIT_TEST_MACROS_H__ -#define _UNIT_TEST_MACROS_H__ - -#include - -#define TFAILURE( s ) printf( "FAILURE: " __FILE__ ":%-4d %s\n", __LINE__, s ) -#define TSUCCESS( s ) printf( "SUCCESS: " __FILE__ ":%-4d %s\n", __LINE__, s ) - -/* careful with this line (no protection) */ -#define INITTEST() int ok = 1; int gok = 1; - -/* declare the variables */ -extern int ok; -extern int gok; - -#define CHECK( b ) do { if ( ! (b) ) { ok = 0; TFAILURE( #b ); } } while(0) -#define FAILED( s ) do { ok = 0; TFAILURE( s ); } while(0) -#define REPORT( s ) do { if ( ! (ok) ) { ok = 0; TFAILURE( s ); } else { TSUCCESS( s );} gok &= ok; ok = 1; } while(0) -#define REPORT2( b, s ) do { if ( ! (b) ) { ok = 0; TFAILURE( s ); } else { TSUCCESS( s );} gok &= ok; ok = 1; } while(0) -#define FINALREPORT( s ) do { gok &= ok; ok = 1; if ( ! (gok) ) { TFAILURE( s ); } else { TSUCCESS( s );} } while(0) -#define TESTRESULT() (!gok) - -#endif diff --git a/libbitdht/src/udp/udpbitdht.cc b/libbitdht/src/udp/udpbitdht.cc deleted file mode 100644 index 066faf54d..000000000 --- a/libbitdht/src/udp/udpbitdht.cc +++ /dev/null @@ -1,373 +0,0 @@ -/******************************************************************************* - * bitdht/udpbitdht.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "udp/udpbitdht.h" -#include "bitdht/bdpeer.h" -#include "bitdht/bdstore.h" -#include "bitdht/bdmsgs.h" -#include "bitdht/bencode.h" - -#include -#include /* for usleep() */ -#include -#include - -#include - -#include "util/bdnet.h" - -/* - * #define DEBUG_UDP_BITDHT 1 - * - * #define BITDHT_VERSION_ANONYMOUS 1 - */ - -//#define DEBUG_UDP_BITDHT 1 - -#define BITDHT_VERSION_IDENTIFER 1 - -// Original RS 0.5.0/0.5.1 version, is un-numbered. -//#define BITDHT_VERSION "00" // First Release of BitDHT with Connections (Proxy Support + Dht Stun) -//#define BITDHT_VERSION "01" // Testing Connections (Proxy Only) -#define BITDHT_VERSION "02" // Completed Relay Connections from svn 4766 -//#define BITDHT_VERSION "04" // Full DHT implementation.? - -/*************************************/ - -UdpBitDht::UdpBitDht(UdpPublisher *pub, bdNodeId *id, std::string appVersion, std::string bootstrapfile, std::string bootstrapfilebak, const std::string& filteredipfile, bdDhtFunctions *fns) - :UdpSubReceiver(pub), dhtMtx(true)//, mFns(fns) -{ - std::string usedVersion; - -#ifdef BITDHT_VERSION_IDENTIFER - usedVersion = "BD"; - usedVersion += BITDHT_VERSION; -#endif - usedVersion += appVersion; - -#ifdef BITDHT_VERSION_ANONYMOUS - usedVersion = ""; /* blank it */ -#endif - - clearDataTransferred(); - - /* setup nodeManager */ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - mBitDhtManager = new bdNodeManager(id, usedVersion, bootstrapfile, bootstrapfilebak, filteredipfile, fns); -} - - -UdpBitDht::~UdpBitDht() -{ - return; -} - - - /*********** External Interface to the World ************/ - - /***** Functions to Call down to bdNodeManager ****/ - /* Friend Tracking */ -void UdpBitDht::addBadPeer(const struct sockaddr_in &addr, uint32_t source, uint32_t reason, uint32_t age) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->addBadPeer(addr, source, reason, age); -} - - -void UdpBitDht::updateKnownPeer(const bdId *id, uint32_t type, uint32_t flags) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->updateKnownPeer(id, type, flags); -} - - /* Request DHT Peer Lookup */ - /* Request Keyword Lookup */ -void UdpBitDht::addFindNode(bdNodeId *id, uint32_t mode) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->addFindNode(id, mode); -} - -void UdpBitDht::removeFindNode(bdNodeId *id) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->removeFindNode(id); -} - -void UdpBitDht::findDhtValue(bdNodeId *id, std::string key, uint32_t mode) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->findDhtValue(id, key, mode); -} - - /***** Add / Remove Callback Clients *****/ -void UdpBitDht::addCallback(BitDhtCallback *cb) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->addCallback(cb); -} - -void UdpBitDht::removeCallback(BitDhtCallback *cb) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->removeCallback(cb); -} - -bool UdpBitDht::ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->ConnectionRequest(laddr, target, mode, delay, start); -} - - - -void UdpBitDht::ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, - uint32_t bandwidth, uint32_t delay, uint32_t answer) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->ConnectionAuth(srcId, proxyId, destId, mode, loc, bandwidth, delay, answer); -} - -void UdpBitDht::ConnectionOptions(uint32_t allowedModes, uint32_t flags) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->ConnectionOptions(allowedModes, flags); -} - -bool UdpBitDht::setAttachMode(bool on) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->setAttachMode(on); -} - - -int UdpBitDht::getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->getDhtPeerAddress(id, from); -} - -int UdpBitDht::getDhtValue(const bdNodeId *id, std::string key, std::string &value) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->getDhtValue(id, key, value); -} - -int UdpBitDht::getDhtBucket(const int idx, bdBucket &bucket) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->getDhtBucket(idx, bucket); -} - - - -int UdpBitDht::getDhtQueries(std::map &queries) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->getDhtQueries(queries); -} - -int UdpBitDht::getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->getDhtQueryStatus(id, query); -} - -bool UdpBitDht::isAddressBanned(const sockaddr_in &raddr) -{ - return mBitDhtManager->addressBanned(raddr) ; -} - -bool UdpBitDht::getListOfBannedIps(std::list& ipl) -{ - return mBitDhtManager->getFilteredPeers(ipl) ; -} - - - - /* stats and Dht state */ -int UdpBitDht:: startDht() -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->startDht(); -} - -int UdpBitDht:: stopDht() -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->stopDht(); -} - -int UdpBitDht::stateDht() -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->stateDht(); -} - -uint32_t UdpBitDht::statsNetworkSize() -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->statsNetworkSize(); -} - -uint32_t UdpBitDht::statsBDVersionSize() -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->statsBDVersionSize(); -} - -uint32_t UdpBitDht::setDhtMode(uint32_t dhtFlags) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->setDhtMode(dhtFlags); -} - - - /******************* Internals *************************/ - - /***** Iteration / Loop Management *****/ - - /*** Overloaded from UdpSubReceiver ***/ -int UdpBitDht::recvPkt(void *data, int size, struct sockaddr_in &from) -{ - /* pass onto bitdht */ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - /* check packet suitability */ - if (mBitDhtManager->isBitDhtPacket((char *) data, size, from)) - { - - mReadBytes += size; - mBitDhtManager->incomingMsg(&from, (char *) data, size); - return 1; - } - return 0; -} - -int UdpBitDht::status(std::ostream &out) -{ - out << "UdpBitDht::status()" << std::endl; - - return 1; -} - -void UdpBitDht::clearDataTransferred() -{ - /* pass onto bitdht */ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mReadBytes = 0; - mWriteBytes = 0; -} - - -void UdpBitDht::getDataTransferred(uint32_t &read, uint32_t &write) -{ - { - /* pass onto bitdht */ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - read = mReadBytes; - write = mWriteBytes; - } - clearDataTransferred(); -} - - - /*** Overloaded from iThread ***/ -#define MAX_MSG_PER_TICK 100 -#define TICK_PAUSE_USEC 20000 /* 20ms secs .. max messages = 50 x 100 = 5000 */ - -void UdpBitDht::run() -{ - while(1) - { - while(tick()) - { - usleep(TICK_PAUSE_USEC); - } - - { - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - mBitDhtManager->iteration(); - } - sleep(1); - } -} - - -int UdpBitDht::tick() -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - /* pass on messages from the node */ - int i = 0; - char data[BITDHT_MAX_PKTSIZE]; - struct sockaddr_in toAddr; - int size = BITDHT_MAX_PKTSIZE; - - while((i < MAX_MSG_PER_TICK) && (mBitDhtManager->outgoingMsg(&toAddr, data, &size))) - { -#ifdef DEBUG_UDP_BITDHT - std::cerr << "UdpBitDht::tick() outgoing msg(" << size << ") to " << toAddr; - std::cerr << std::endl; -#endif - - mWriteBytes += size; - sendPkt(data, size, toAddr, BITDHT_TTL); - - // iterate - i++; - size = BITDHT_MAX_PKTSIZE; // reset msg size! - } - - if (i == MAX_MSG_PER_TICK) - { - return 1; /* keep on ticking */ - } - return 0; -} - - - diff --git a/libbitdht/src/udp/udpbitdht.h b/libbitdht/src/udp/udpbitdht.h deleted file mode 100644 index 38088edfb..000000000 --- a/libbitdht/src/udp/udpbitdht.h +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************* - * udp/udpbitdht.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef UDP_BIT_DHT_CLASS_H -#define UDP_BIT_DHT_CLASS_H - -#include -#include -#include - -#include "udp/udpstack.h" -#include "bitdht/bdiface.h" -#include "bitdht/bdmanager.h" - -/* - * This implements a UdpSubReceiver class to allow the DHT to talk to the network. - * The parser is very strict - and will try to not pick up anyone else's messages. - * - * Mutexes are implemented at this level protecting the whole of the DHT code. - * This class is also a thread - enabling it to do callback etc. - */ - -// class BitDhtCallback defined in bdiface.h - - -class UdpBitDht: public UdpSubReceiver, public bdThread, public BitDhtInterface -{ - public: - - UdpBitDht(UdpPublisher *pub, bdNodeId *id, std::string dhtVersion, std::string bootstrapfile, std::string bootstrapfilebak, const std::string& filteredipfile,bdDhtFunctions *fns); -virtual ~UdpBitDht(); - - - /*********** External Interface to the World (BitDhtInterface) ************/ - - /***** Functions to Call down to bdNodeManager ****/ - - /* Friend Tracking */ -virtual void addBadPeer(const struct sockaddr_in &addr, uint32_t source, uint32_t reason, uint32_t age); -virtual void updateKnownPeer(const bdId *id, uint32_t type, uint32_t flags); - - /* Request DHT Peer Lookup */ - /* Request Keyword Lookup */ -virtual void addFindNode(bdNodeId *id, uint32_t mode); -virtual void removeFindNode(bdNodeId *id); -virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode); - - /***** Add / Remove Callback Clients *****/ -virtual void addCallback(BitDhtCallback *cb); -virtual void removeCallback(BitDhtCallback *cb); - - /***** Connections Requests *****/ -virtual bool ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start); -virtual void ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, - uint32_t bandwidth, uint32_t delay, uint32_t answer); -virtual void ConnectionOptions(uint32_t allowedModes, uint32_t flags); -virtual bool setAttachMode(bool on); - - /***** Get Results Details *****/ -virtual int getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from); -virtual int getDhtValue(const bdNodeId *id, std::string key, std::string &value); -virtual int getDhtBucket(const int idx, bdBucket &bucket); - -virtual int getDhtQueries(std::map &queries); -virtual int getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query); - - virtual bool isAddressBanned(const sockaddr_in &raddr) ; - virtual bool getListOfBannedIps(std::list &ipl); - - /* stats and Dht state */ -virtual int startDht(); -virtual int stopDht(); -virtual int stateDht(); -virtual uint32_t statsNetworkSize(); -virtual uint32_t statsBDVersionSize(); -virtual uint32_t setDhtMode(uint32_t dhtFlags); - -void getDataTransferred(uint32_t &read, uint32_t &write); - - /******************* Internals *************************/ - /***** Iteration / Loop Management *****/ - - /*** Overloaded from UdpSubReceiver ***/ -virtual int recvPkt(void *data, int size, struct sockaddr_in &from); -virtual int status(std::ostream &out); - - - /*** Overloaded from iThread ***/ -virtual void run(); - - /**** do whats to be done ***/ -int tick(); -private: - -void clearDataTransferred(); - - bdMutex dhtMtx; /* for all class data (below) */ - bdNodeManager *mBitDhtManager; - //bdDhtFunctions *mFns; - - - uint32_t mReadBytes; - uint32_t mWriteBytes; - - -}; - - -#endif diff --git a/libbitdht/src/udp/udplayer.cc b/libbitdht/src/udp/udplayer.cc deleted file mode 100644 index 1a82c3d81..000000000 --- a/libbitdht/src/udp/udplayer.cc +++ /dev/null @@ -1,772 +0,0 @@ -/******************************************************************************* - * udp/udplayer.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2004-2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "udp/udplayer.h" -#include "util/bdrandom.h" -#include "util/bdstring.h" - -#include -#include -#include -#include -#include -#ifndef WIN32 -#include -#endif - -/*** - * #define UDP_ENABLE_BROADCAST 1 - * #define UDP_LOOPBACK_TESTING 1 - * #define DEBUG_UDP_LAYER 1 - ***/ - -//#define DEBUG_UDP_LAYER 1 - -static const int UDP_DEF_TTL = 64; - -/* NB: This #define makes the listener open 0.0.0.0:X port instead - * of a specific port - this helps library communicate on systems - * with multiple interfaces or unique network setups. - * - * - It should always be used! - * - * #define OPEN_UNIVERSAL_PORT 1 - * - */ - -#define OPEN_UNIVERSAL_PORT 1 - - -class udpPacket -{ - public: - udpPacket(struct sockaddr_in *addr, void *dta, int dlen) - :raddr(*addr), len(dlen) - { - data = malloc(len); - - if(data != NULL) - memcpy(data, dta, len); - else - std::cerr << "(EE) error in memory allocation in " << __PRETTY_FUNCTION__ << std::endl; - } - - ~udpPacket() - { - if (data) - { - free(data); - data = NULL; - len = 0; - } - } - - struct sockaddr_in raddr; - void *data; - int len; -}; - -//std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr) -std::ostream &operator<<(std::ostream &out, struct sockaddr_in &addr) -{ - out << "[" << bdnet_inet_ntoa(addr.sin_addr) << ":"; - out << htons(addr.sin_port) << "]"; - return out; -} - -bool operator==(const struct sockaddr_in &addr, const struct sockaddr_in &addr2) -{ - if (addr.sin_family != addr2.sin_family) - return false; - if (addr.sin_addr.s_addr != addr2.sin_addr.s_addr) - return false; - if (addr.sin_port != addr2.sin_port) - return false; - return true; -} - - -bool operator<(const struct sockaddr_in &addr, const struct sockaddr_in &addr2) -{ - if (addr.sin_family != addr2.sin_family) - return (addr.sin_family < addr2.sin_family); - if (addr.sin_addr.s_addr != addr2.sin_addr.s_addr) - return (addr.sin_addr.s_addr < addr2.sin_addr.s_addr); - if (addr.sin_port != addr2.sin_port) - return (addr.sin_port < addr2.sin_port); - return false; -} - -std::string printPkt(void *d, int size) -{ - std::string out = "Packet:**********************"; - for(int i = 0; i < size; i++) - { - if (i % 16 == 0) - out += "\n"; - bd_sprintf_append(out, "%2x ", (unsigned int) ((unsigned char *) d)[i]); - } - out += "\n**********************\n"; - return out; -} - - -std::string printPktOffset(unsigned int offset, void *d, unsigned int size) -{ - std::string out = "Packet:**********************\n"; - bd_sprintf_append(out, "Offset: %x -> %x\n", offset, offset + size); - out += "Packet:**********************"; - - unsigned int j = offset % 16; - if (j != 0) - { - out += "\n"; - bd_sprintf_append(out, "%6x: ", (unsigned int) offset - j); - for(unsigned int i = 0; i < j; i++) - { - out += "xx "; - } - } - for(unsigned int i = offset; i < offset + size; i++) - { - if (i % 16 == 0) - { - out += "\n"; - bd_sprintf_append(out, "%6x: ", (unsigned int) i); - } - bd_sprintf(out, "%2x ", (unsigned int) ((unsigned char *) d)[i-offset]); - } - out += "\n**********************\n"; - return out; -} - - - -UdpLayer::UdpLayer(UdpReceiver *udpr, struct sockaddr_in &local) - :recv(udpr), laddr(local), errorState(0), ttl(UDP_DEF_TTL) -{ - openSocket(); - return; -} - -int UdpLayer::status(std::ostream &out) -{ - out << "UdpLayer::status()" << std::endl; - out << "localaddr: " << laddr << std::endl; - out << "sockfd: " << sockfd << std::endl; - out << std::endl; - return 1; -} - -int UdpLayer::reset(struct sockaddr_in &local) -{ -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::reset()" << std::endl; -#endif - - /* stop the old thread */ - { - bdStackMutex stack(sockMtx); /********** LOCK MUTEX *********/ -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::reset() setting stopThread flag" << std::endl; -#endif - stopThread = true; - } -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::reset() joining" << std::endl; -#endif - - join(); - -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::reset() closing socket" << std::endl; -#endif - closeSocket(); - -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::reset() resetting variables" << std::endl; -#endif - laddr = local; - errorState = 0; - ttl = UDP_DEF_TTL; - -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::reset() opening socket" << std::endl; -#endif - openSocket(); - - return 1 ; -} - - -int UdpLayer::closeSocket() -{ - /* close socket if open */ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - if (sockfd > 0) - { - bdnet_close(sockfd); - } - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - return 1; -} - -void UdpLayer::run() -{ - return recv_loop(); -} - -/* higher level interface */ -void UdpLayer::recv_loop() -{ - size_t maxsize = 16000; - void *inbuf = malloc(maxsize); - - if(inbuf == NULL) - { - std::cerr << "(EE) Error in memory allocation of size " << maxsize - << " in " << __PRETTY_FUNCTION__ << std::endl; - return; - } - - int status; - struct timeval timeout; - - while(1) - { - for(;;) - { - /* check if we need to stop */ - bool toStop = false; - { - bdStackMutex stack(sockMtx); (void) stack; - toStop = stopThread; - } - - if (toStop) - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::recv_loop() stopping thread" << std::endl; -#endif - free(inbuf); - stop(); - return; // Avoid compiler warning about usage of inbuf after free - } - - fd_set rset; - FD_ZERO(&rset); - FD_SET(sockfd, &rset); - timeout.tv_sec = 0; - timeout.tv_usec = 500000; // 500 ms timeout - status = select(sockfd+1, &rset, NULL, NULL, &timeout); - if (status > 0) break; // data available, go read it -#ifdef DEBUG_UDP_LAYER - else if (status < 0) std::cerr << "UdpLayer::recv_loop() Error: " - << bdnet_errno() << std::endl; -#endif - }; - - int nsize = static_cast(maxsize); - struct sockaddr_in from; - if (0 < receiveUdpPacket(inbuf, &nsize, from)) - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::readPkt() from : " << from << std::endl - << printPkt(inbuf, nsize); -#endif - recv->recvPkt(inbuf, nsize, from); // pass to reciever. - } -#ifdef DEBUG_UDP_LAYER - else std::cerr << "UdpLayer::readPkt() not ready" << from << std::endl; -#endif - } -} - - -int UdpLayer::sendPkt(const void *data, int size, const sockaddr_in &to, int ttl) -{ - /* if ttl is different -> set it */ - if (ttl != getTTL()) - { - setTTL(ttl); - } - - /* and send! */ -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::sendPkt() to: " << to << std::endl; - std::cerr << printPkt((void *) data, size); -#endif - sendUdpPacket(data, size, to); - return size; -} - -/* setup connections */ -int UdpLayer::openSocket() -{ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - /* make a socket */ - sockfd = bdnet_socket(PF_INET, SOCK_DGRAM, 0); -#ifdef DEBUG_UDP_LAYER - std::cerr << "UpdStreamer::openSocket()" << std::endl; -#endif - /* bind to address */ - - -#ifdef UDP_LOOPBACK_TESTING - bdnet_inet_aton("127.0.0.1", &(laddr.sin_addr)); -#endif - -#ifdef OPEN_UNIVERSAL_PORT - struct sockaddr_in tmpaddr = laddr; - tmpaddr.sin_addr.s_addr = 0; - if (0 != bdnet_bind(sockfd, (struct sockaddr *) (&tmpaddr), sizeof(tmpaddr))) -#else - if (0 != bdnet_bind(sockfd, (struct sockaddr *) (&laddr), sizeof(laddr))) -#endif - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "Socket Failed to Bind to : " << laddr << std::endl; - std::cerr << "Error: " << bdnet_errno() << std::endl; -#endif - errorState = EADDRINUSE; - //exit(1); - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - return -1; - } - - if (-1 == bdnet_fcntl(sockfd, F_SETFL, O_NONBLOCK)) - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "Failed to Make Non-Blocking" << std::endl; -#endif - } - -#ifdef UDP_ENABLE_BROADCAST - /* Setup socket for broadcast. */ - int val = 1; - if (-1 == setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(int))) - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "Failed to Make Socket Broadcast" << std::endl; -#endif - } -#endif - - errorState = 0; - -#ifdef DEBUG_UDP_LAYER - std::cerr << "Socket Bound to : " << laddr << std::endl; -#endif - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - -#ifdef DEBUG_UDP_LAYER - std::cerr << "Setting TTL to " << UDP_DEF_TTL << std::endl; -#endif - setTTL(UDP_DEF_TTL); - clearDataTransferred(); // clear statistics. - - // start up our thread. - { - bdStackMutex stack(sockMtx); /********** LOCK MUTEX *********/ - stopThread = false; - } - start(); - - return 1; - -} - -int UdpLayer::setTTL(int t) -{ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - int err = bdnet_setsockopt(sockfd, IPPROTO_IP, IP_TTL, &t, sizeof(int)); - ttl = t; - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::setTTL(" << t << ") returned: " << err; - std::cerr << std::endl; -#endif - - return err; -} - -int UdpLayer::getTTL() -{ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - int t = ttl; - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return t; -} - -/* monitoring / updates */ -int UdpLayer::okay() -{ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - bool nonFatalError = ((errorState == 0) || - (errorState == EAGAIN) || - (errorState == EINPROGRESS)); - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - -#ifdef DEBUG_UDP_LAYER - if (!nonFatalError) - { - std::cerr << "UdpLayer::NOT okay(): Error: " << errorState << std::endl; - } - -#endif - - return nonFatalError; -} - -int UdpLayer::tick() -{ -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::tick()" << std::endl; -#endif - return 1; -} - -void UdpLayer::getDataTransferred(uint32_t &read, uint32_t &write) -{ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - read = readBytes; - write = writeBytes; - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - - clearDataTransferred(); -} - -void UdpLayer::clearDataTransferred() -{ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - readBytes = 0; - writeBytes = 0; - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ -} - -/******************* Internals *************************************/ - -int UdpLayer::receiveUdpPacket(void *data, int *size, struct sockaddr_in &from) -{ - struct sockaddr_in fromaddr; - socklen_t fromsize = sizeof(fromaddr); - int insize = *size; - - sockMtx.lock(); /********** LOCK MUTEX *********/ - - insize = bdnet_recvfrom(sockfd,data,insize,0, - (struct sockaddr*)&fromaddr,&fromsize); - - if (0 < insize) - { - readBytes += insize; - } - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - - if (0 < insize) - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "receiveUdpPacket() from: " << fromaddr; - std::cerr << " Size: " << insize; - std::cerr << std::endl; -#endif - *size = insize; - from = fromaddr; - return insize; - } - return -1; -} - -int UdpLayer::sendUdpPacket(const void *data, int size, const struct sockaddr_in &to) -{ - /* send out */ -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::sendUdpPacket(): size: " << size; - std::cerr << " To: " << to << std::endl; -#endif - struct sockaddr_in toaddr = to; - - sockMtx.lock(); /********** LOCK MUTEX *********/ - - bdnet_sendto(sockfd, data, size, 0, - (struct sockaddr *) &(toaddr), - sizeof(toaddr)); - - writeBytes += size; - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - return 1; -} - - -/**************************** LossyUdpLayer - for Testing **************/ - - -LossyUdpLayer::LossyUdpLayer(UdpReceiver *udpr, - struct sockaddr_in &local, double frac) - :UdpLayer(udpr, local), lossFraction(frac) -{ - return; -} -LossyUdpLayer::~LossyUdpLayer() { return; } - -int LossyUdpLayer::receiveUdpPacket(void *data, int *size, struct sockaddr_in &from) -{ - if (0 < UdpLayer::receiveUdpPacket(data, size, from)) - { - float prob = bdRandom::random_f32(); - if (prob < lossFraction) - { - /* discard */ - //std::cerr << "LossyUdpLayer::receiveUdpPacket() Dropping packet!"; - //std::cerr << std::endl; - //std::cerr << printPkt(data, *size); - //std::cerr << std::endl; - std::cerr << "LossyUdpLayer::receiveUdpPacket() Packet (" << *size << ") Dropped!"; - std::cerr << std::endl; - - *size = 0; - return -1; - } - - return *size; - } - return -1; -} - -int LossyUdpLayer::sendUdpPacket(const void *data, int size, const struct sockaddr_in &to) -{ - double prob = (1.0 * (rand() / (RAND_MAX + 1.0))); - - if (prob < lossFraction) - { - /* discard */ - - //std::cerr << "LossyUdpLayer::sendUdpPacket() Dropping packet!"; - //std::cerr << std::endl; - //std::cerr << printPkt((void *) data, size); - //std::cerr << std::endl; - std::cerr << "LossyUdpLayer::sendUdpPacket() Packet (" << size << ") Dropped!"; - std::cerr << std::endl; - - return size; - } - - // otherwise read normally; - return UdpLayer::sendUdpPacket(data, size, to); -} - -/**************************** LossyUdpLayer - for Testing **************/ - -PortRange::PortRange() :lport(0), uport(0) { return; } -PortRange::PortRange(uint16_t lp, uint16_t up) :lport(lp), uport(up) { return; } - -bool PortRange::inRange(uint16_t port) -{ - if (port < lport) - { - return false; - } - - if (port > uport) - { - return false; - } - return true; -} - - - -RestrictedUdpLayer::RestrictedUdpLayer(UdpReceiver *udpr, - struct sockaddr_in &local) - :UdpLayer(udpr, local) -{ - return; -} -RestrictedUdpLayer::~RestrictedUdpLayer() { return; } - -void RestrictedUdpLayer::addRestrictedPortRange(int lp, int up) -{ - PortRange pr(lp, up); - mLostPorts.push_back(pr); -} - -int RestrictedUdpLayer::receiveUdpPacket(void *data, int *size, struct sockaddr_in &from) -{ - if (0 < UdpLayer::receiveUdpPacket(data, size, from)) - { - /* check the port against list */ - uint16_t inPort = ntohs(from.sin_port); - - std::list::iterator it; - for(it = mLostPorts.begin(); it != mLostPorts.end(); it++) - { - if (it->inRange(inPort)) - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "RestrictedUdpLayer::receiveUdpPacket() Dropping packet"; - std::cerr << ", Port(" << inPort << ") in restricted range!"; - std::cerr << std::endl; - //std::cerr << printPkt(data, *size); - //std::cerr << std::endl; -#endif - - *size = 0; - return -1; - - } - - } - -#ifdef DEBUG_UDP_LAYER - std::cerr << "RestrictedUdpLayer::receiveUdpPacket() Accepting packet"; - std::cerr << ", Port(" << inPort << ") in Okay range!"; - std::cerr << std::endl; -#endif - /* acceptable port */ - return *size; - } - return -1; -} - -int RestrictedUdpLayer::sendUdpPacket(const void *data, int size, const struct sockaddr_in &to) -{ - /* check the port against list */ - uint16_t outPort = ntohs(to.sin_port); - - std::list::iterator it; - for(it = mLostPorts.begin(); it != mLostPorts.end(); it++) - { - if (it->inRange(outPort)) - { - /* drop */ -#ifdef DEBUG_UDP_LAYER - std::cerr << "RestrictedUdpLayer::sendUdpPacket() Dropping packet"; - std::cerr << ", Port(" << outPort << ") in restricted range!"; - std::cerr << std::endl; - //std::cerr << printPkt(data, *size); - //std::cerr << std::endl; -#endif - - return size; - } - - - } - -#ifdef DEBUG_UDP_LAYER - std::cerr << "RestrictedUdpLayer::sendUdpPacket() Sending packet"; - std::cerr << ", Port(" << outPort << ") in Okay range!"; - std::cerr << std::endl; -#endif - - // otherwise read normally; - return UdpLayer::sendUdpPacket(data, size, to); -} - - -#define STARTUP_PERIOD 60 - -TimedUdpLayer::TimedUdpLayer(UdpReceiver *udpr, - struct sockaddr_in &local) - :UdpLayer(udpr, local) -{ - mStartTime = time(NULL) + STARTUP_PERIOD; - mActive = false; - return; -} - -TimedUdpLayer::~TimedUdpLayer() { return; } - -int TimedUdpLayer::receiveUdpPacket(void *data, int *size, struct sockaddr_in &from) -{ - if (0 < UdpLayer::receiveUdpPacket(data, size, from)) - { - if (!mActive) - { - if (time(NULL) < mStartTime) - { -#ifdef DEBUG_UDP_LAYER -#endif - std::cerr << "TimedUdpLayer::receiveUdpPacket() Dropping packet (Too Early)"; - std::cerr << std::endl; - //std::cerr << printPkt(data, *size); - //std::cerr << std::endl; - - *size = 0; - return -1; - - } - - mActive = true; - - } - - /* acceptable port */ - return *size; - } - return -1; -} - -int TimedUdpLayer::sendUdpPacket(const void *data, int size, const struct sockaddr_in &to) -{ - if (!mActive) - { - if (time(NULL) < mStartTime) - { - /* drop */ -#ifdef DEBUG_UDP_LAYER -#endif - std::cerr << "TimedUdpLayer::sendUdpPacket() Dropping packet (Too Early)"; - std::cerr << std::endl; - return size; - } - - /* else activate */ - mActive = true; - } - - // otherwise read normally; - return UdpLayer::sendUdpPacket(data, size, to); -} - - - - diff --git a/libbitdht/src/udp/udplayer.h b/libbitdht/src/udp/udplayer.h deleted file mode 100644 index 06e76c647..000000000 --- a/libbitdht/src/udp/udplayer.h +++ /dev/null @@ -1,188 +0,0 @@ -/******************************************************************************* - * udp/udplayer.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2004-2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_UDP_LAYER_H -#define BITDHT_UDP_LAYER_H - -#include "util/bdthreads.h" -#include "util/bdnet.h" - -#include -#include -#include - -/* careful - duplicate definitions */ -//std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr); -std::ostream &operator<<(std::ostream &out, struct sockaddr_in &addr); - -bool operator==(const struct sockaddr_in &addr, const struct sockaddr_in &addr2); -bool operator<(const struct sockaddr_in &addr, const struct sockaddr_in &addr2); - -std::string printPkt(void *d, int size); -std::string printPktOffset(unsigned int offset, void *d, unsigned int size); - - -/* UdpLayer ..... is the bottom layer which - * just sends and receives Udp packets. - */ - -class UdpReceiver -{ - public: -virtual ~UdpReceiver() {} -virtual int recvPkt(void *data, int size, struct sockaddr_in &from) = 0; -virtual int status(std::ostream &out) = 0; -}; - -class UdpPublisher -{ - public: -virtual ~UdpPublisher() {} -virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl) = 0; -}; - - -class UdpLayer: public bdThread -{ - public: - - UdpLayer(UdpReceiver *recv, struct sockaddr_in &local); -virtual ~UdpLayer() { return; } - -int reset(struct sockaddr_in &local); /* calls join, close, openSocket */ -void getDataTransferred(uint32_t &read, uint32_t &write); - -int status(std::ostream &out); - - /* setup connections */ - int closeSocket(); - int openSocket(); - - /* RsThread functions */ -virtual void run(); /* called once the thread is started */ - -void recv_loop(); /* uses callback to UdpReceiver */ - - /* Higher Level Interface */ - //int readPkt(void *data, int *size, struct sockaddr_in &from); - int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); - - /* monitoring / updates */ - int okay(); - int tick(); - - - /* data */ - /* internals */ - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - int setTTL(int t); - int getTTL(); - - /* low level */ - private: - -void clearDataTransferred(); - - UdpReceiver *recv; - - struct sockaddr_in laddr; /* local addr */ - - uint32_t readBytes; - uint32_t writeBytes; - - int errorState; - int sockfd; - int ttl; - bool stopThread; - - bdMutex sockMtx; -}; - - -/* For Testing - drops packets */ -class LossyUdpLayer: public UdpLayer -{ - public: - LossyUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local, double frac); -virtual ~LossyUdpLayer(); - - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - double lossFraction; -}; - -class PortRange -{ - public: - PortRange(); - PortRange(uint16_t lp, uint16_t up); - - bool inRange(uint16_t port); - - uint16_t lport; - uint16_t uport; -}; - - -/* For Testing - drops packets */ -class RestrictedUdpLayer: public UdpLayer -{ - public: - RestrictedUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local); -virtual ~RestrictedUdpLayer(); - -void addRestrictedPortRange(int lp, int up); - - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - std::list mLostPorts; -}; - - -/* For Testing - drops packets all packets for initial minute (simulates TTL) */ -class TimedUdpLayer: public UdpLayer -{ - public: - TimedUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local); -virtual ~TimedUdpLayer(); - - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - time_t mStartTime; - bool mActive; - -}; - - -#endif diff --git a/libbitdht/src/udp/udpproxylayer.h b/libbitdht/src/udp/udpproxylayer.h deleted file mode 100644 index 939bdabf8..000000000 --- a/libbitdht/src/udp/udpproxylayer.h +++ /dev/null @@ -1,181 +0,0 @@ -/******************************************************************************* - * libbitdht/src/udp/udpproxylayer.h * - * * - * Copyright 2004 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef BITDHT_UDP_LAYER_H -#define BITDHT_UDP_LAYER_H - -#include "util/bdthreads.h" -#include "util/bdnet.h" - -#include -#include -#include - -/* careful - duplicate definitions */ -//std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr); -std::ostream &operator<<(std::ostream &out, struct sockaddr_in &addr); - -bool operator==(const struct sockaddr_in &addr, const struct sockaddr_in &addr2); -bool operator<(const struct sockaddr_in &addr, const struct sockaddr_in &addr2); - -std::string printPkt(void *d, int size); -std::string printPktOffset(unsigned int offset, void *d, unsigned int size); - - -/* UdpLayer ..... is the bottom layer which - * just sends and receives Udp packets. - */ - -class UdpReceiver -{ - public: -virtual ~UdpReceiver() {} -virtual int recvPkt(void *data, int size, struct sockaddr_in &from) = 0; -virtual int status(std::ostream &out) = 0; -}; - -class UdpPublisher -{ - public: -virtual ~UdpPublisher() {} -virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl) = 0; -}; - - -class UdpLayer: public bdThread -{ - public: - - UdpLayer(UdpReceiver *recv, struct sockaddr_in &local); -virtual ~UdpLayer() { return; } - -int reset(struct sockaddr_in &local); /* calls join, close, openSocket */ - -int status(std::ostream &out); - - /* setup connections */ - int closeSocket(); - int openSocket(); - - /* RsThread functions */ -virtual void run(); /* called once the thread is started */ - -void recv_loop(); /* uses callback to UdpReceiver */ - - /* Higher Level Interface */ - //int readPkt(void *data, int *size, struct sockaddr_in &from); - int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); - - /* monitoring / updates */ - int okay(); - int tick(); - - - /* data */ - /* internals */ - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - int setTTL(int t); - int getTTL(); - - /* low level */ - private: - - UdpReceiver *recv; - - struct sockaddr_in laddr; /* local addr */ - - int errorState; - int sockfd; - int ttl; - bool stopThread; - - bdMutex sockMtx; -}; - - -/* For Testing - drops packets */ -class LossyUdpLayer: public UdpLayer -{ - public: - LossyUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local, double frac); -virtual ~LossyUdpLayer(); - - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - double lossFraction; -}; - -class PortRange -{ - public: - PortRange(); - PortRange(uint16_t lp, uint16_t up); - - bool inRange(uint16_t port); - - uint16_t lport; - uint16_t uport; -}; - - -/* For Testing - drops packets */ -class RestrictedUdpLayer: public UdpLayer -{ - public: - RestrictedUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local); -virtual ~RestrictedUdpLayer(); - -void addRestrictedPortRange(int lp, int up); - - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - std::list mLostPorts; -}; - - -/* For Testing - drops packets all packets for initial minute (simulates TTL) */ -class TimedUdpLayer: public UdpLayer -{ - public: - TimedUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local); -virtual ~TimedUdpLayer(); - - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - time_t mStartTime; - bool mActive; - -}; - - -#endif diff --git a/libbitdht/src/udp/udpstack.cc b/libbitdht/src/udp/udpstack.cc deleted file mode 100644 index fdf8eb9cf..000000000 --- a/libbitdht/src/udp/udpstack.cc +++ /dev/null @@ -1,252 +0,0 @@ -/******************************************************************************* - * udp/udpstack.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "udp/udpstack.h" - -#include -#include -#include -#include - -#include - -/*** - * #define DEBUG_UDP_RECV 1 - ***/ - -//#define DEBUG_UDP_RECV 1 - - -UdpStack::UdpStack(struct sockaddr_in &local) - :udpLayer(NULL), laddr(local) -{ - openSocket(); - return; -} - -UdpStack::UdpStack(int testmode, struct sockaddr_in &local) - :udpLayer(NULL), laddr(local) -{ - std::cerr << "UdpStack::UdpStack() Evoked in TestMode" << std::endl; - if (testmode == UDP_TEST_LOSSY_LAYER) - { - std::cerr << "UdpStack::UdpStack() Installing LossyUdpLayer" << std::endl; - udpLayer = new LossyUdpLayer(this, laddr, UDP_TEST_LOSSY_FRAC); - } - else if (testmode == UDP_TEST_RESTRICTED_LAYER) - { - std::cerr << "UdpStack::UdpStack() Installing RestrictedUdpLayer" << std::endl; - udpLayer = new RestrictedUdpLayer(this, laddr); - } - else if (testmode == UDP_TEST_TIMED_LAYER) - { - std::cerr << "UdpStack::UdpStack() Installing TimedUdpLayer" << std::endl; - udpLayer = new TimedUdpLayer(this, laddr); - } - else - { - std::cerr << "UdpStack::UdpStack() Installing Standard UdpLayer" << std::endl; - // standard layer - openSocket(); - } - return; -} - -UdpLayer *UdpStack::getUdpLayer() /* for testing only */ -{ - return udpLayer; -} - -bool UdpStack::getLocalAddress(struct sockaddr_in &local) -{ - local = laddr; - return true; -} - -bool UdpStack::resetAddress(struct sockaddr_in &local) -{ -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpStack::resetAddress(" << local << ")"; - std::cerr << std::endl; -#endif - laddr = local; - - return udpLayer->reset(local); -} - - - -/* higher level interface */ -int UdpStack::recvPkt(void *data, int size, struct sockaddr_in &from) -{ - /* print packet information */ -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpStack::recvPkt(" << size << ") from: " << from; - std::cerr << std::endl; -#endif - - bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/ - - std::list::iterator it; - for(it = mReceivers.begin(); it != mReceivers.end(); it++) - { - // See if they want the packet. - if ((*it)->recvPkt(data, size, from)) - { -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpStack::recvPkt(" << size << ") from: " << from; - std::cerr << std::endl; -#endif - break; - } - } - return 1; -} - -int UdpStack::sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl) -{ - /* print packet information */ -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpStack::sendPkt(" << size << ") ttl: " << ttl; - std::cerr << " to: " << to; - std::cerr << std::endl; -#endif - - /* send to udpLayer */ - return udpLayer->sendPkt(data, size, to, ttl); -} - -int UdpStack::status(std::ostream &out) -{ - { - bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/ - - out << "UdpStack::status()" << std::endl; - out << "localaddr: " << laddr << std::endl; - out << "UdpStack::SubReceivers:" << std::endl; - std::list::iterator it; - int i = 0; - for(it = mReceivers.begin(); it != mReceivers.end(); it++, i++) - { - out << "\tReceiver " << i << " --------------------" << std::endl; - (*it)->status(out); - } - out << "--------------------" << std::endl; - out << std::endl; - } - - udpLayer->status(out); - - return 1; -} - -/* setup connections */ -int UdpStack::openSocket() -{ - udpLayer = new UdpLayer(this, laddr); - return 1; -} - -/* monitoring / updates */ -int UdpStack::okay() -{ - return udpLayer->okay(); -} - -int UdpStack::close() -{ - /* TODO */ - return 1; -} - - - /* add a TCPonUDP stream */ -int UdpStack::addReceiver(UdpReceiver *recv) -{ - bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/ - - /* check for duplicate */ - std::list::iterator it; - it = std::find(mReceivers.begin(), mReceivers.end(), recv); - if (it == mReceivers.end()) - { - mReceivers.push_back(recv); - return 1; - } - - /* otherwise its already there! */ - -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpStack::addReceiver() Recv already exists!" << std::endl; - std::cerr << "UdpStack::addReceiver() ERROR" << std::endl; -#endif - - return 0; -} - -int UdpStack::removeReceiver(UdpReceiver *recv) -{ - bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/ - - /* check for duplicate */ - std::list::iterator it; - it = std::find(mReceivers.begin(), mReceivers.end(), recv); - if (it != mReceivers.end()) - { - mReceivers.erase(it); - return 1; - } - - /* otherwise its not there! */ - -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpStack::removeReceiver() Recv dont exist!" << std::endl; - std::cerr << "UdpStack::removeReceiver() ERROR" << std::endl; -#endif - - return 0; -} - - - -/*****************************************************************************************/ - -UdpSubReceiver::UdpSubReceiver(UdpPublisher *pub) - :mPublisher(pub) -{ - return; -} - -int UdpSubReceiver::sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl) -{ - /* print packet information */ -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpSubReceiver::sendPkt(" << size << ") ttl: " << ttl; - std::cerr << " to: " << to; - std::cerr << std::endl; -#endif - - /* send to udpLayer */ - return mPublisher->sendPkt(data, size, to, ttl); -} - - diff --git a/libbitdht/src/udp/udpstack.h b/libbitdht/src/udp/udpstack.h deleted file mode 100644 index 31b8ec324..000000000 --- a/libbitdht/src/udp/udpstack.h +++ /dev/null @@ -1,114 +0,0 @@ -/******************************************************************************* - * udp/udpstack.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_UDP_STACK_RECEIVER_H -#define BITDHT_UDP_STACK_RECEIVER_H - -#include "util/bdthreads.h" -#include "util/bdnet.h" - -#include -#include -#include - -#include -#include - -#include "udp/udplayer.h" - -/* UdpStackReceiver is a Generic Receiver of info from a UdpLayer class. - * it provides a UdpReceiver class, and accepts a stack of UdpReceivers, - * which will be iterated through (in-order) until someone accepts the packet. - * - * It is important to order these Receivers correctly! - * - * This infact becomes the holder of the UdpLayer, and all controls - * go through the StackReceiver. - */ - -class UdpSubReceiver: public UdpReceiver -{ - public: - UdpSubReceiver(UdpPublisher *pub); - - /* calls mPublisher->sendPkt */ -virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); - /* callback for recved data (overloaded from UdpReceiver) */ -//virtual int recvPkt(void *data, int size, struct sockaddr_in &from) = 0; - - UdpPublisher *mPublisher; -}; - - -#define UDP_TEST_LOSSY_LAYER 1 -#define UDP_TEST_RESTRICTED_LAYER 2 -#define UDP_TEST_TIMED_LAYER 3 - -#define UDP_TEST_LOSSY_FRAC (0.10) - -class UdpStack: public UdpReceiver, public UdpPublisher -{ - public: - - UdpStack(struct sockaddr_in &local); - UdpStack(int testmode, struct sockaddr_in &local); -virtual ~UdpStack() { return; } - -UdpLayer *getUdpLayer(); /* for testing only */ - -bool getLocalAddress(struct sockaddr_in &local); -bool resetAddress(struct sockaddr_in &local); - - - /* add in a receiver */ -int addReceiver(UdpReceiver *recv); -int removeReceiver(UdpReceiver *recv); - - /* Packet IO */ - /* pass-through send packets */ -virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); - /* callback for recved data (overloaded from UdpReceiver) */ - -virtual int recvPkt(void *data, int size, struct sockaddr_in &from); - -int status(std::ostream &out); - - /* setup connections */ - int openSocket(); - - /* monitoring / updates */ - int okay(); -// int tick(); - - int close(); - - private: - - UdpLayer *udpLayer; - - bdMutex stackMtx; /* for all class data (below) */ - - struct sockaddr_in laddr; /* local addr */ - - std::list mReceivers; -}; - -#endif diff --git a/libbitdht/src/use_libbitdht.pri b/libbitdht/src/use_libbitdht.pri deleted file mode 100644 index 5758393af..000000000 --- a/libbitdht/src/use_libbitdht.pri +++ /dev/null @@ -1,25 +0,0 @@ -# RetroShare main qmake build script -# -# Copyright (C) 2004-2019, Retroshare Team -# -# 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 . -# -# SPDX-FileCopyrightText: Retroshare Team -# SPDX-License-Identifier: LGPL-3.0-or-later - -DEPENDPATH *= $$system_path($$clean_path($${PWD}/../../libbitdht/src)) -INCLUDEPATH *= $$system_path($$clean_path($${PWD}/../../libbitdht/src)) -LIBS *= -L$$system_path($$clean_path($${OUT_PWD}/../../libbitdht/src/lib/)) -lbitdht - -!equals(TARGET, bitdht):PRE_TARGETDEPS *= $$system_path($$clean_path($${OUT_PWD}/../../libbitdht/src/lib/libbitdht.a)) diff --git a/libbitdht/src/util/bdbloom.cc b/libbitdht/src/util/bdbloom.cc deleted file mode 100644 index 739e2c793..000000000 --- a/libbitdht/src/util/bdbloom.cc +++ /dev/null @@ -1,402 +0,0 @@ -/******************************************************************************* - * util/bdbloom.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "util/bdbloom.h" -#include "util/bdstring.h" - -#include -#include - -#if defined(_WIN32) || defined(__MINGW32__) -#include -#endif - -/* Bloom Filter implementation */ - - -bloomFilter::bloomFilter(int m, int k) -{ - mBits.resize(m); - mHashFns.resize(k); - - mFilterBits = m; - mNoHashs = k; - mNoElements = 0; - - int i; - for(i = 0; i < m; i++) - { - mBits[i] = 0; - } - - for(i = 0; i < k; i++) - { - mHashFns[i] = NULL; - } - -} - -uint8_t convertCharToUint8(char ch1, char ch2) -{ - uint8_t value1 = 0; - uint8_t value2 = 0; - - /* do char1 */ - if (ch1 >= '0' && ch1 <= '9') - value1 = (ch1 - '0'); - else if (ch1 >= 'A' && ch1 <= 'F') - value1 = (ch1 - 'A' + 10); - else if (ch1 >= 'a' && ch1 <= 'f') - value1 = (ch1 - 'a' + 10); - - /* do char2 */ - if (ch2 >= '0' && ch2 <= '9') - value2 = (ch2 - '0'); - else if (ch2 >= 'A' && ch2 <= 'F') - value2 = (ch2 - 'A' + 10); - else if (ch2 >= 'a' && ch2 <= 'f') - value2 = (ch2 - 'a' + 10); - - uint8_t output = (value1 << 4) + value2; - return output; -} - -#define BITS_PER_BYTE (8) - -int bloomFilter::setFilterBits(const std::string &hex) -{ - uint32_t bytes = (mFilterBits / BITS_PER_BYTE); - if (mFilterBits % BITS_PER_BYTE) - { - bytes++; - } - - if (hex.size() < bytes * 2) - { - return 0; - } - - // convert to binary array. - uint8_t *tmparray = (uint8_t *) malloc(bytes); - - if(tmparray == NULL) - { - std::cerr << "(EE) Error. Cannot allocate memory for " << bytes << " bytes in " << __PRETTY_FUNCTION__ << std::endl; - return 0; - } - - uint32_t i = 0; - - for(i = 0; i < bytes; i++) - { - tmparray[i] = convertCharToUint8(hex[2 * i], hex[2 * i + 1]); - } - - - for(i = 0; i < mFilterBits; i++) - { - int byte = i / BITS_PER_BYTE; - int bit = i % BITS_PER_BYTE; - uint8_t value = (tmparray[byte] & (1 << bit)); - - if (value) - { - mBits[i] = 1; - } - else - { - mBits[i] = 0; - } - } - - free(tmparray); - return 1; -} - -std::string bloomFilter::getFilter() -{ - /* extract filter as a hex string */ - int bytes = (mFilterBits / BITS_PER_BYTE); - if (mFilterBits % BITS_PER_BYTE) - { - bytes++; - } - - if (bytes==0) - { - std::cerr << "(EE) Error. Cannot allocate memory for 0 byte in " << __PRETTY_FUNCTION__ << std::endl; - return std::string(); - } - // convert to binary array. - uint8_t *tmparray = (uint8_t *) malloc(bytes); - - if(tmparray == NULL) - { - std::cerr << "(EE) Error. Cannot allocate memory for " << bytes << " bytes in " << __PRETTY_FUNCTION__ << std::endl; - return std::string(); - } - - int i,j; - - for(i = 0; i < bytes; i++) - { - tmparray[i] = 0; - for(j = 0; j < BITS_PER_BYTE; j++) - { - int bit = i * BITS_PER_BYTE + j; - if (mBits[bit]) - { - tmparray[i] |= (1 << j); - } - } - } - - std::string out; - for(int i = 0; i < bytes; i++) - { - bd_sprintf_append(out, "%02lx", (uint32_t) (tmparray)[i]); - } - - free(tmparray); - - return out; -} - -void bloomFilter::setBit(int bit) -{ - mBits[bit] = 1; - -} - - -bool bloomFilter::isBitSet(int bit) -{ - return (mBits[bit] == 1); -} - -uint32_t bloomFilter::filterBits() -{ - return mFilterBits; -} - -uint32_t bloomFilter::countBits() -{ - int count = 0; - uint32_t i; - for(i = 0; i < mFilterBits; i++) - { - if (mBits[i]) - { - count++; - } - } - return count; -} - - -void bloomFilter::printFilter(std::ostream &out) -{ - out << "bloomFilter: m = " << mFilterBits; - out << " k = " << mNoHashs; - out << " n = " << mNoElements; - out << std::endl; - - out << "BITS: "; - uint32_t i; - for(i = 0; i < mFilterBits; i++) - { - if ((i > 0) && (i % 32 == 0)) - { - out << std::endl; - out << "BITS: "; - } - if (mBits[i]) - { - out << "1"; - } - else - { - out << "0"; - } - } - out << std::endl; - out << "STR: " << getFilter(); - out << std::endl; -} - -void bloomFilter::setHashFunction(int idx, uint32_t (*hashfn)(const std::string &)) -{ - mHashFns[idx] = hashfn; -} - -void bloomFilter::add(const std::string &hex) -{ - uint32_t (*hashfn)(const std::string &); - uint32_t i; - for(i = 0; i < mNoHashs; i++) - { - hashfn = mHashFns[i]; - - int bit = hashfn(hex); - - setBit(bit); - } - - mNoElements++; - -} - -bool bloomFilter::test(const std::string &hex) -{ - uint32_t (*hashfn)(const std::string &); - uint32_t i; - for(i = 0; i < mNoHashs; i++) - { - hashfn = mHashFns[i]; - - int bit = hashfn(hex); - - if (!isBitSet(bit)) - { - return false; - } - } - return true; -} - -uint32_t getFirst10BitsAsNumber(const std::string &input) -{ - if (input.size() < 8) - { - std::cerr << "getFirst10BitsAsNumber() ERROR Size too small!"; - std::cerr << std::endl; - return 0; - } - - uint8_t data[4]; - - data[0] = convertCharToUint8(input[0], input[1]); - data[1] = convertCharToUint8(input[2], input[3]); - data[2] = convertCharToUint8(input[4], input[5]); - data[3] = convertCharToUint8(input[6], input[7]); - - uint32_t val = ((data[0] & 0xff) << 2) + ((data[1] & 0xc0) >> 6); - -#ifdef DEBUG_BLOOM - std::cerr << "getFirst10BitsAsNumber() input: " << input; - std::cerr << std::endl; - std::cerr << "getFirst10BitsAsNumber() "; - std::cerr << " data[0]: " << std::hex << (uint32_t) data[0]; - std::cerr << " data[1]: " << (uint32_t) data[1]; - std::cerr << " data[2]: " << (uint32_t) data[2]; - std::cerr << " data[3]: " << (uint32_t) data[3]; - std::cerr << " val: " << std::dec << (uint32_t) val; - std::cerr << std::endl; -#endif - - return val; -} - -uint32_t getSecond10BitsAsNumber(const std::string &input) -{ - if (input.size() < 8) - { - std::cerr << "getSecond10BitsAsNumber() ERROR Size too small!"; - std::cerr << std::endl; - return 0; - } - - uint8_t data[4]; - - data[0] = convertCharToUint8(input[0], input[1]); - data[1] = convertCharToUint8(input[2], input[3]); - data[2] = convertCharToUint8(input[4], input[5]); - data[3] = convertCharToUint8(input[6], input[7]); - - uint32_t val = ((data[1] & 0x3f) << 4) + ((data[2] & 0xf0) >> 4); - -#ifdef DEBUG_BLOOM - std::cerr << "getSecond10BitsAsNumber() input: " << input; - std::cerr << std::endl; - std::cerr << "getSecond10BitsAsNumber() "; - std::cerr << " data[0]: " << std::hex << (uint32_t) data[0]; - std::cerr << " data[1]: " << (uint32_t) data[1]; - std::cerr << " data[2]: " << (uint32_t) data[2]; - std::cerr << " data[3]: " << (uint32_t) data[3]; - std::cerr << " val: " << std::dec << (uint32_t) val; - std::cerr << std::endl; -#endif - - return val; -} - - -uint32_t getMid10BitsAsNumber(const std::string &input) -{ - if (input.size() < 8) - { - std::cerr << "getMid10BitsAsNumber() ERROR Size too small!"; - std::cerr << std::endl; - return 0; - } - - uint8_t data[4]; - - data[0] = convertCharToUint8(input[0], input[1]); - data[1] = convertCharToUint8(input[2], input[3]); - data[2] = convertCharToUint8(input[4], input[5]); - data[3] = convertCharToUint8(input[6], input[7]); - - uint32_t val = ((data[0] & 0x07) << 7) + ((data[1] & 0x7f) >> 1); - -#ifdef DEBUG_BLOOM - std::cerr << "getMid10BitsAsNumber() input: " << input; - std::cerr << std::endl; - std::cerr << "getMid10BitsAsNumber() "; - std::cerr << " data[0]: " << std::hex << (uint32_t) data[0]; - std::cerr << " data[1]: " << (uint32_t) data[1]; - std::cerr << " data[2]: " << (uint32_t) data[2]; - std::cerr << " data[3]: " << (uint32_t) data[3]; - std::cerr << " val: " << std::dec << (uint32_t) val; - std::cerr << std::endl; -#endif - - return val; -} - - -#define BDFILTER_M 1024 -#define BDFILTER_K 3 - -bdBloom::bdBloom() - :bloomFilter(BDFILTER_M, BDFILTER_K) -{ - /* set the fns. */ - setHashFunction(0, getFirst10BitsAsNumber); - setHashFunction(1, getSecond10BitsAsNumber); - setHashFunction(2, getMid10BitsAsNumber); -} - - - - - diff --git a/libbitdht/src/util/bdbloom.h b/libbitdht/src/util/bdbloom.h deleted file mode 100644 index 8ffd13f1e..000000000 --- a/libbitdht/src/util/bdbloom.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************* - * util/bdbloom.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_BLOOM_H -#define BITDHT_BLOOM_H - -#include -#include - -#include -#include - - -class bloomFilter -{ - public: - - bloomFilter(int m, int k); - -int setFilterBits(const std::string &hex); -std::string getFilter(); - -void printFilter(std::ostream &out); - -bool test(const std::string &hex); // takes first m bits. -void add(const std::string &hex); -uint32_t countBits(); -uint32_t filterBits(); - - protected: -void setHashFunction(int idx, uint32_t (*hashfn)(const std::string &)); - - private: -void setBit(int bit); -bool isBitSet(int bit); - - std::vector mBits; - std::vector mHashFns; - - uint32_t mFilterBits; - uint32_t mNoHashs; - uint32_t mNoElements; -}; - - -/* our specific implementation */ -class bdBloom: public bloomFilter -{ - public: - - bdBloom(); -}; - - -#endif - diff --git a/libbitdht/src/util/bdfile.cc b/libbitdht/src/util/bdfile.cc deleted file mode 100644 index bcd2eb64b..000000000 --- a/libbitdht/src/util/bdfile.cc +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * util/bdfile.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifdef WIN32 -#include -#endif - -#include -#include -#include -#include "bdfile.h" - -namespace librs { - namespace util { - bool ConvertUtf8ToUtf16(const std::string& source, std::wstring& dest) ; - } -} - -bool bdFile::renameFile(const std::string& from, const std::string& to) -{ - int loops = 0; - -#ifdef WIN32 - std::wstring f; - librs::util::ConvertUtf8ToUtf16(from, f); - std::wstring t; - librs::util::ConvertUtf8ToUtf16(to, t); - - while (!MoveFileEx(f.c_str(), t.c_str(), MOVEFILE_REPLACE_EXISTING)) -#else - std::string f(from),t(to) ; - - while (rename(from.c_str(), to.c_str()) < 0) -#endif - { -#ifdef WIN32 - if (GetLastError() != ERROR_ACCESS_DENIED) -#else - if (errno != EACCES) -#endif - /* set errno? */ - return false ; -#ifdef WIN32 - Sleep(100000); /* us */ -#else - usleep(100000); /* us */ -#endif - - if (loops >= 30) - return false ; - - loops++; - } - - return true ; -} - diff --git a/libbitdht/src/util/bdnet.cc b/libbitdht/src/util/bdnet.cc deleted file mode 100644 index ba8c33553..000000000 --- a/libbitdht/src/util/bdnet.cc +++ /dev/null @@ -1,363 +0,0 @@ -/******************************************************************************* - * util/bdnet.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bdnet.h" -#include "bdstring.h" - -#include -#include -#include - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#if defined(_WIN32) || defined(__MINGW32__) - -//#define BDNET_DEBUG - -/* error handling */ -int bdnet_int_errno; - -int bdnet_errno() -{ - return bdnet_int_errno; -} - -int bdnet_init() -{ - std::cerr << "bdnet_init()" << std::endl; - bdnet_int_errno = 0; - - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - - return 0; -} - -/* check if we can modify the TTL on a UDP packet */ -int bdnet_checkTTL(int fd) -{ - std::cerr << "bdnet_checkTTL()" << std::endl; - int optlen = 4; - char optval[optlen]; - - int ret = getsockopt(fd, IPPROTO_IP, IP_TTL, optval, &optlen); - //int ret = getsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, optval, &optlen); - if (ret == SOCKET_ERROR) - { - ret = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - std::cerr << "bdnet_checkTTL() Failed!"; - std::cerr << std::endl; - } - else - { - std::cerr << "bdnet_checkTTL() :"; - std::cerr << (int) optval[0] << ":"; - std::cerr << (int) optval[1] << ":"; - std::cerr << (int) optval[2] << ":"; - std::cerr << (int) optval[3] << ": RET: "; - std::cerr << ret << ":"; - std::cerr << std::endl; - } - return ret; -} - -int bdnet_close(int fd) -{ - std::cerr << "bdnet_close()" << std::endl; - return closesocket(fd); -} - -int bdnet_socket(int domain, int type, int protocol) -{ - int osock = socket(domain, type, protocol); - std::cerr << "bdnet_socket()" << std::endl; - - if ((unsigned) osock == INVALID_SOCKET) - { - // Invalidate socket Unix style. - osock = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - } - bdnet_checkTTL(osock); - return osock; -} - -int bdnet_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen) -{ - std::cerr << "bdnet_bind()" << std::endl; - int ret = bind(sockfd,my_addr,addrlen); - if (ret != 0) - { - /* store unix-style error - */ - - ret = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - } - return ret; -} - -int bdnet_fcntl(int fd, int cmd, long arg) -{ - int ret; - - unsigned long int on = 1; - std::cerr << "bdnet_fcntl()" << std::endl; - - /* can only do NONBLOCK at the moment */ - if ((cmd != F_SETFL) || (arg != O_NONBLOCK)) - { - std::cerr << "bdnet_fcntl() limited to fcntl(fd, F_SETFL, O_NONBLOCK)"; - std::cerr << std::endl; - bdnet_int_errno = EOPNOTSUPP; - return -1; - } - - ret = ioctlsocket(fd, FIONBIO, &on); - - if (ret != 0) - { - /* store unix-style error - */ - - ret = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - } - return ret; -} - -int bdnet_setsockopt(int s, int level, int optname, - const void *optval, socklen_t optlen) -{ - std::cerr << "bdnet_setsockopt() val:" << *((int *) optval) << std::endl; - std::cerr << "bdnet_setsockopt() len:" << optlen << std::endl; - if ((level != IPPROTO_IP) || (optname != IP_TTL)) - { - std::cerr << "bdnet_setsockopt() limited to "; - std::cerr << "setsockopt(fd, IPPROTO_IP, IP_TTL, ....)"; - std::cerr << std::endl; - bdnet_int_errno = EOPNOTSUPP; - return -1; - } - - int ret = setsockopt(s, level, optname, (const char *) optval, optlen); - //int ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (const char *) optval, optlen); - if (ret == SOCKET_ERROR) - { - ret = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - } - bdnet_checkTTL(s); - return ret; -} - -ssize_t bdnet_recvfrom(int s, void *buf, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) -{ -#ifdef BDNET_DEBUG - std::cerr << "bdnet_recvfrom()" << std::endl; -#endif - int ret = recvfrom(s, (char *) buf, len, flags, from, fromlen); - if (ret == SOCKET_ERROR) - { - ret = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - } - return ret; -} - -ssize_t bdnet_sendto(int s, const void *buf, size_t len, int flags, - const struct sockaddr *to, socklen_t tolen) -{ -#ifdef BDNET_DEBUG - std::cerr << "bdnet_sendto()" << std::endl; -#endif - int ret = sendto(s, (const char *) buf, len, flags, to, tolen); - if (ret == SOCKET_ERROR) - { - ret = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - } - return ret; -} - -int bdnet_w2u_errno(int err) -{ - /* switch */ - std::cerr << "tou_net_w2u_errno(" << err << ")" << std::endl; - switch(err) - { - case WSAEINPROGRESS: - return EINPROGRESS; - break; - case WSAEWOULDBLOCK: - return EINPROGRESS; - break; - case WSAENETUNREACH: - return ENETUNREACH; - break; - case WSAETIMEDOUT: - return ETIMEDOUT; - break; - case WSAEHOSTDOWN: - return EHOSTDOWN; - break; - case WSAECONNREFUSED: - return ECONNREFUSED; - break; - case WSAEADDRINUSE: - return EADDRINUSE; - break; - case WSAEUSERS: - return EUSERS; - break; - /* This one is returned for UDP recvfrom, when nothing there - * but not a real error... translate into EINPROGRESS - */ - case WSAECONNRESET: - std::cerr << "tou_net_w2u_errno(" << err << ")"; - std::cerr << " = WSAECONNRESET ---> EINPROGRESS"; - std::cerr << std::endl; - return EINPROGRESS; - break; - /*** - * - case WSAECONNRESET: - return ECONNRESET; - break; - * - ***/ - - case WSANOTINITIALISED: - std::cerr << "tou_net_w2u_errno(" << err << ") WSANOTINITIALISED. Fix Your Code!"; - std::cerr << std::endl; - break; - default: - std::cerr << "tou_net_w2u_errno(" << err << ") Unknown"; - std::cerr << std::endl; - break; - } - - return ECONNREFUSED; /* sensible default? */ -} - -int bdnet_inet_aton(const char *name, struct in_addr *addr) -{ - return (((*addr).s_addr = inet_addr(name)) != INADDR_NONE); -} - -#ifndef __MINGW64_VERSION_MAJOR -int sleep(unsigned int sec) -{ - Sleep(sec * 1000); - return 0; -} -#endif - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else // UNIX - -/* Unix Version is easy -> just call the unix fn - */ - -#include /* for close definition */ - -/* the universal interface */ -int bdnet_init() { return 0; } -int bdnet_errno() { return errno; } - - -/* check if we can modify the TTL on a UDP packet */ -int bdnet_checkTTL(int /*fd*/) { return 1;} - - -int bdnet_inet_aton(const char *name, struct in_addr *addr) -{ - return inet_aton(name, addr); -} - -int bdnet_close(int fd) { return close(fd); } - -int bdnet_socket(int domain, int type, int protocol) -{ - return socket(domain, type, protocol); -} - -int bdnet_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen) -{ - return bind(sockfd,my_addr,addrlen); -} - -int bdnet_fcntl(int fd, int cmd, long arg) -{ - return fcntl(fd, cmd, arg); -} - -int bdnet_setsockopt(int s, int level, int optname, - const void *optval, socklen_t optlen) -{ - return setsockopt(s, level, optname, optval, optlen); -} - -ssize_t bdnet_recvfrom(int s, void *buf, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) -{ - return recvfrom(s, buf, len, flags, from, fromlen); -} - -ssize_t bdnet_sendto(int s, const void *buf, size_t len, int flags, - const struct sockaddr *to, socklen_t tolen) -{ - return sendto(s, buf, len, flags, to, tolen); -} - - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - -void bdsockaddr_clear(struct sockaddr_in *addr) -{ - memset(addr, 0, sizeof(*addr)); -} - -/* thread-safe version of inet_ntoa */ - -std::string bdnet_inet_ntoa(struct in_addr in) -{ - std::string str; - uint8_t *bytes = (uint8_t *) &(in.s_addr); - bd_sprintf(str, "%u.%u.%u.%u", (int) bytes[0], (int) bytes[1], (int) bytes[2], (int) bytes[3]); - return str; -} diff --git a/libbitdht/src/util/bdnet.h b/libbitdht/src/util/bdnet.h deleted file mode 100644 index 89ecfa710..000000000 --- a/libbitdht/src/util/bdnet.h +++ /dev/null @@ -1,174 +0,0 @@ -/******************************************************************************* - * util/bdnet.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_UNIVERSAL_NETWORK_HEADER -#define BITDHT_UNIVERSAL_NETWORK_HEADER - -#include -#include - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#if defined(_WIN32) || defined(__MINGW32__) - -#include - -#include /* for ssize_t */ -typedef uint32_t in_addr_t; - -#else // UNIX - -#include -#include -#include -#include - -#include -#include - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - - -/* C Interface */ -#ifdef __cplusplus -extern "C" { -#endif - -/******* - * This defines a (unix-like) universal networking layer - * that should function on both windows and unix. (C - interface) - * - * This is of course only a subset of the full interface. - * functions required are: - * - * int bdnet_close(int fd); - * int bdnet_socket(int domain, int type, int protocol); - * int bdnet_bind(int sockfd, const struct sockaddr *my_addr, - * socklen_t addrlen); - * int bdnet_fcntl(int fd, int cmd, long arg); - * int bdnet_setsockopt(int s, int level, int optname, - * const void *optval, socklen_t optlen); - * ssize_t bdnet_recvfrom(int s, void *buf, size_t len, int flags, - * struct sockaddr *from, socklen_t *fromlen); - * ssize_t bdnet_sendto(int s, const void *buf, size_t len, int flags, - * const struct sockaddr *to, socklen_t tolen); - * - * There are some non-standard ones as well: - * int bdnet_errno(); for internal networking errors - * int bdnet_init(); required for windows - * int bdnet_checkTTL(); a check if we can modify the ttl - */ - - -/* the universal interface */ -int bdnet_errno(); /* for internal networking errors */ -int bdnet_init(); /* required for windows */ -int bdnet_close(int fd); -int bdnet_socket(int domain, int type, int protocol); -int bdnet_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen); -int bdnet_fcntl(int fd, int cmd, long arg); -int bdnet_setsockopt(int s, int level, int optname, - const void *optval, socklen_t optlen); -ssize_t bdnet_recvfrom(int s, void *buf, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen); -ssize_t bdnet_sendto(int s, const void *buf, size_t len, int flags, - const struct sockaddr *to, socklen_t tolen); - -/* address filling */ -int bdnet_inet_aton(const char *name, struct in_addr *addr); -/* check if we can modify the TTL on a UDP packet */ -int bdnet_checkTTL(int fd); - -void bdsockaddr_clear(struct sockaddr_in *addr); - -/* Extra stuff to declare for windows error handling (mimics unix errno) - */ - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#if defined(_WIN32) || defined(__MINGW32__) - -// Some Network functions that are missing from windows. -//in_addr_t inet_netof(struct in_addr addr); -//in_addr_t inet_network(char *inet_name); -//int inet_aton(const char *name, struct in_addr *addr); - - -// definitions for fcntl (NON_BLOCK) (random?) -#define F_SETFL 0x1010 -#define O_NONBLOCK 0x0100 - -// definitions for setsockopt (TTL) (random?) -//#define IPPROTO_IP 0x0011 -//#define IP_TTL 0x0110 - -/* define the Unix Error Codes that we use... - * NB. we should make the same, but not necessary - */ - -#define EAGAIN 11 -#define EUSERS 87 - -#define EHOSTDOWN 112 - -#ifndef __MINGW64_VERSION_MAJOR -#define EWOULDBLOCK EAGAIN - -#define ENOTSOCK 88 - -#define EOPNOTSUPP 95 - -#define EADDRINUSE 98 -#define EADDRNOTAVAIL 99 -#define ENETDOWN 100 -#define ENETUNREACH 101 - -#define ECONNRESET 104 - -#define ETIMEDOUT 10060 // value from pthread.h -#define ECONNREFUSED 111 -#define EHOSTUNREACH 113 -#define EALREADY 114 -#define EINPROGRESS 115 -#endif - -int bdnet_w2u_errno(int error); - -/* also put the sleep commands in here (where else to go) - * ms uses millisecs. - * void Sleep(int ms); - */ -#ifndef __MINGW64_VERSION_MAJOR -int sleep(unsigned int sec); -#endif - -#endif // END of WINDOWS defines. -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - -#ifdef __cplusplus -} /* C Interface */ -#endif - -/* thread-safe version of inet_ntoa */ -std::string bdnet_inet_ntoa(struct in_addr in); - -#endif /* BITDHT_UNIVERSAL_NETWORK_HEADER */ diff --git a/libbitdht/src/util/bdrandom.cc b/libbitdht/src/util/bdrandom.cc deleted file mode 100644 index 93a0352dd..000000000 --- a/libbitdht/src/util/bdrandom.cc +++ /dev/null @@ -1,120 +0,0 @@ -/******************************************************************************* - * util/bdrandom.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright (C) 2010 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include -#include -#include -#include "util/bdrandom.h" - -uint32_t bdRandom::index = 0 ; -std::vector bdRandom::MT(bdRandom::N,0u) ; -bdMutex bdRandom::rndMtx ; - -#if (defined(_WIN32) || defined(__MINGW32__)) && !defined(WIN_PTHREADS_H) -static bool auto_seed = bdRandom::seed( (time(NULL) + ((uint32_t) pthread_self().p)*0x1293fe)^0x18e34a12 ) ; -#else - #ifdef __APPLE__ - static bool auto_seed = bdRandom::seed( (time(NULL) + pthread_mach_thread_np(pthread_self())*0x1293fe + (getpid()^0x113ef76b))^0x18e34a12 ) ; - #elif defined(__FreeBSD__) || (__HAIKU__) - // since this is completely insecure anyway, just kludge for now - static bool auto_seed = bdRandom::seed(time(NULL)); - #elif defined(__OpenBSD__) - static bool auto_seed = bdRandom::seed(arc4random()); - #else - static bool auto_seed = bdRandom::seed( (time(NULL) + pthread_self()*0x1293fe + (getpid()^0x113ef76b))^0x18e34a12 ) ; - #endif -#endif -bool bdRandom::seed(uint32_t s) -{ - bdStackMutex mtx(rndMtx) ; - - MT.resize(N,0) ; // because MT might not be already resized - - uint32_t j ; - MT[0]= s & 0xffffffffUL; - for (j=1; j> 30)) + j) & 0xffffffffUL ; - - return true ; -} - -void bdRandom::locked_next_state() -{ - for(uint32_t i=0;i> 1) ; - - if((y & 1) == 1) - MT[i] = MT[i] ^ 0x9908b0df ; - } - index = 0 ; -} - -uint32_t bdRandom::random_u32() -{ - uint32_t y; - - { - bdStackMutex mtx(rndMtx) ; - - y = MT[index++] ; - - if(index == N) - locked_next_state(); - } - - // Tempering - y ^= (y >> 11); - y ^= (y << 7 ) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); - - return y; -} - -uint64_t bdRandom::random_u64() -{ - return ((uint64_t)random_u32() << 32ul) + random_u32() ; -} - -float bdRandom::random_f32() -{ - return random_u32() / (float)(~(uint32_t)0) ; -} - -double bdRandom::random_f64() -{ - return random_u64() / (double)(~(uint64_t)0) ; -} - -std::string bdRandom::random_alphaNumericString(uint32_t len) -{ - std::string s = "" ; - - for(uint32_t i=0;i * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_UTILS_BDRANDOM_H -#define BITDHT_UTILS_BDRANDOM_H - -/* This Source Code is basically a direct copy of libretroshare's RsRandom. - * the function names have just been renamed. drbob - */ - -// bdRandom contains a random number generator that is -// - thread safe -// - system independant -// - fast -// - NOT CRYPTOGRAPHICALLY SAFE -// - DO NOT USE FOR ANYTHING REQUIRING STRONG UNPREDICTABLE RANDOMNESS -// -// The implementation is adapted from the Mersenne Twister page of Wikipedia. -// -// http://en.wikipedia.org/wiki/Mersenne_twister - -// FIXME(ben): MT is not cryptographically safe. - -#include -#include "util/bdthreads.h" - -class bdRandom -{ - public: - static uint32_t random_u32() ; - static uint64_t random_u64() ; - static float random_f32() ; - static double random_f64() ; - - static bool seed(uint32_t s) ; - - static std::string random_alphaNumericString(uint32_t length) ; - - private: - static bdMutex rndMtx ; - - static const uint32_t N = 624; - static const uint32_t M = 397; - - static const uint32_t MATRIX_A = 0x9908b0dfUL; - static const uint32_t UMASK = 0x80000000UL; - static const uint32_t LMASK = 0x7fffffffUL; - - static void locked_next_state() ; - static uint32_t index ; - static std::vector MT ; -}; - -#endif diff --git a/libbitdht/src/util/bdstring.cc b/libbitdht/src/util/bdstring.cc deleted file mode 100644 index 3808e0c68..000000000 --- a/libbitdht/src/util/bdstring.cc +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * util/bdstring.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright (C) 2010 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bdstring.h" - -#ifdef _WIN32 -#include -#include -#else -#include -#include -#endif -#include - -#ifdef _WIN32 -// asprintf() and vasprintf() are missing in Win32 -static int vasprintf(char **sptr, const char *fmt, va_list argv) -{ - int wanted = __mingw_vsnprintf(*sptr = NULL, 0, fmt, argv); - if ((wanted > 0) && ((*sptr = (char*) malloc(wanted + 1)) != NULL)) { - return __mingw_vsprintf(*sptr, fmt, argv); - } - - return wanted; -} - -//static int asprintf(char **sptr, const char *fmt, ...) -//{ -// int retval; -// va_list argv; -// va_start( argv, fmt ); -// retval = vasprintf(sptr, fmt, argv); -// va_end(argv); -// return retval; -//} -#endif - -int bd_sprintf(std::string &str, const char *fmt, ...) -{ - char *buffer = NULL; - va_list ap; - - va_start(ap, fmt); - int retval = vasprintf(&buffer, fmt, ap); - va_end(ap); - - if (retval >= 0) { - if (buffer) { - str = buffer; - free(buffer); - } else { - str.clear(); - } - } else { - str.clear(); - } - - return retval; -} - -int bd_sprintf_append(std::string &str, const char *fmt, ...) -{ - va_list ap; - char *buffer = NULL; - - va_start(ap, fmt); - int retval = vasprintf(&buffer, fmt, ap); - va_end(ap); - - if (retval >= 0) { - if (buffer) { - str.append(buffer); - free(buffer); - } - } - - return retval; -} diff --git a/libbitdht/src/util/bdstring.h b/libbitdht/src/util/bdstring.h deleted file mode 100644 index e9160c663..000000000 --- a/libbitdht/src/util/bdstring.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * util/bdstring.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright (C) 2010 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_UTILS_BDSTRING_H -#define BITDHT_UTILS_BDSTRING_H - -#ifdef WIN32 -// for proper handling of %ll -#define bd_snprintf __mingw_snprintf -#define bd_fprintf __mingw_fprintf -#else -#define bd_snprintf snprintf -#define bd_fprintf fprintf -#endif - -#ifdef __cplusplus - // These definitions are only available for C++ Modules. - #include - - int bd_sprintf(std::string &str, const char *fmt, ...); - int bd_sprintf_append(std::string &str, const char *fmt, ...); -#endif - -#endif diff --git a/libbitdht/src/util/bdthreads.cc b/libbitdht/src/util/bdthreads.cc deleted file mode 100644 index 3fce7ff43..000000000 --- a/libbitdht/src/util/bdthreads.cc +++ /dev/null @@ -1,167 +0,0 @@ -/******************************************************************************* - * util/bdthread.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright (C) 2004-2010 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "bdthreads.h" -#include /* for usleep() */ - -/******* - * #define DEBUG_THREADS 1 - *******/ - -//#define DEBUG_THREADS 1 - -#ifdef DEBUG_THREADS - #include -#endif - -extern "C" void* bdthread_init(void* p) -{ -#ifdef DEBUG_THREADS - std::cerr << "bdthread_init()"; - std::cerr << std::endl; -#endif - - bdThread *thread = (bdThread *) p; - if (!thread) - { -#ifdef DEBUG_THREADS - std::cerr << "bdthread_init() Error Invalid thread pointer."; - std::cerr << std::endl; -#endif - return 0; - } - thread -> run(); - return 0; -} - - -pthread_t createThread(bdThread &thread) -{ - pthread_t tid; - void *data = (void *) (&thread); - -#ifdef DEBUG_THREADS - std::cerr << "createThread() creating a bdThread"; - std::cerr << std::endl; -#endif - - thread.mMutex.lock(); - { - pthread_create(&tid, 0, &bdthread_init, data); - thread.mTid = tid; - } - -#ifdef DEBUG_THREADS - std::cerr << "createThread() created Thread.mTid: "; - -#if defined(_WIN32) || defined(__MINGW32__) - std::cerr << "WIN32: Cannot print mTid "; -#else - std::cerr << thread.mTid; -#endif - std::cerr << std::endl; - -#endif - - thread.mMutex.unlock(); - - - - return tid; - -} - -bdThread::bdThread() -{ - -#ifdef DEBUG_THREADS - std::cerr << "bdThread::bdThread()"; - std::cerr << std::endl; -#endif - -#if defined(_WIN32) || defined(__MINGW32__) - memset (&mTid, 0, sizeof(mTid)); -#else - mTid = 0; -#endif -} - -void bdThread::join() /* waits for the the mTid thread to stop */ -{ -#ifdef DEBUG_THREADS - std::cerr << "bdThread::join() Called! Waiting for Thread.mTid: "; - -#if defined(_WIN32) || defined(__MINGW32__) - std::cerr << "WIN32: Cannot print mTid "; -#else - std::cerr << mTid; -#endif - - std::cerr << std::endl; -#endif - - mMutex.lock(); - { -#if defined(_WIN32) || defined(__MINGW32__) || defined(__APPLE__) - /* Its a struct in Windows compile and the member .p ist checked in the pthreads library */ -#else - if(mTid > 0) -#endif - pthread_join(mTid, NULL); - -#ifdef DEBUG_THREADS - std::cerr << "bdThread::join() Joined Thread.mTid: "; - -#if defined(_WIN32) || defined(__MINGW32__) - std::cerr << "WIN32: Cannot print mTid "; -#else - std::cerr << mTid; -#endif - - std::cerr << std::endl; - std::cerr << "bdThread::join() Setting mTid = 0"; - std::cerr << std::endl; -#endif - -#if defined(_WIN32) || defined(__MINGW32__) - memset (&mTid, 0, sizeof(mTid)); -#else - mTid = 0; -#endif - - } - mMutex.unlock(); - -} - -void bdThread::stop() -{ -#ifdef DEBUG_THREADS - std::cerr << "bdThread::stop() Called!"; - std::cerr << std::endl; -#endif - - pthread_exit(NULL); -} - - - diff --git a/libbitdht/src/util/bdthreads.h b/libbitdht/src/util/bdthreads.h deleted file mode 100644 index 34c48b1bc..000000000 --- a/libbitdht/src/util/bdthreads.h +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * util/bdthread.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright (C) 2004-2010 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef BITDHT_THREADS_H -#define BITDHT_THREADS_H - -#include -#include -#include - -/* Thread Wrappers */ - -class bdMutex -{ - public: - - bdMutex(bool recursive = false) - { - /* remove unused parameter warnings */ - (void) recursive; - -#if 0 // TESTING WITHOUT RECURSIVE - if(recursive) - { - pthread_mutexattr_t att ; - pthread_mutexattr_init(&att) ; - pthread_mutexattr_settype(&att,PTHREAD_MUTEX_RECURSIVE) ; - - if( pthread_mutex_init(&realMutex, &att)) - std::cerr << "ERROR: Could not initialize mutex !" << std::endl ; - } - else -#endif - if( pthread_mutex_init(&realMutex, NULL)) - std::cerr << "ERROR: Could not initialize mutex !" << std::endl ; - } - - ~bdMutex() { pthread_mutex_destroy(&realMutex); } - void lock() { pthread_mutex_lock(&realMutex); } - void unlock() { pthread_mutex_unlock(&realMutex); } - bool trylock() { return (0 == pthread_mutex_trylock(&realMutex)); } - - private: - pthread_mutex_t realMutex; -}; - -class bdStackMutex -{ - public: - - bdStackMutex(bdMutex &mtx): mMtx(mtx) { mMtx.lock(); } - ~bdStackMutex() { mMtx.unlock(); } - - private: - bdMutex &mMtx; -}; - -class bdThread; - -/* to create a thread! */ -pthread_t createThread(bdThread &thread); - -class bdThread -{ - public: - bdThread(); -virtual ~bdThread() { return; } - -virtual void start() { createThread(*this); } -virtual void run() = 0; /* called once the thread is started */ -virtual void join(); /* waits for the mTid thread to stop */ -virtual void stop(); /* calls pthread_exit() */ - - pthread_t mTid; - bdMutex mMutex; -}; - - -#endif diff --git a/libretroshare b/libretroshare new file mode 160000 index 000000000..ac83e00ea --- /dev/null +++ b/libretroshare @@ -0,0 +1 @@ +Subproject commit ac83e00ea7a26cd6cf57cefef745d6dcfd07e5da diff --git a/libretroshare/src/Doxyfile b/libretroshare/src/Doxyfile deleted file mode 100644 index 0f5cec54a..000000000 --- a/libretroshare/src/Doxyfile +++ /dev/null @@ -1,1633 +0,0 @@ -# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team -# SPDX-License-Identifier: CC0-1.0 - -# Doxyfile 1.7.1 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = "RetroShare libretroshare" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = /var/www/notdefine/retroshare/libretroshare - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = YES - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = YES - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. The create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the stylesheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. - -HTML_TIMESTAMP = YES - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = YES - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NONE - -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. - -FORMULA_TRANSPARENT = YES - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. - -SEARCHENGINE = YES - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvances is that it is more difficult to setup -# and does not have live searching capabilities. - -SERVER_BASED_SEARCH = NO - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. -# Note that when enabling USE_PDFLATEX this option is only used for -# generating bitmaps for formulas in the HTML output, but not in the -# Makefile that is written to the output directory. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include -# source code with syntax highlighting in the LaTeX output. -# Note that which sources are shown also depends on other settings -# such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = YES - -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is -# allowed to run in parallel. When set to 0 (the default) doxygen will -# base this on the number of processors available in the system. You can set it -# explicitly to a value larger than 0 to get control over the balance -# between CPU load and processing speed. - -DOT_NUM_THREADS = 0 - -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -DOT_FONTNAME = FreeSans - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = YES - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = YES - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = YES - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = YES - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES diff --git a/libretroshare/src/chat/distantchat.cc b/libretroshare/src/chat/distantchat.cc deleted file mode 100644 index 621e92229..000000000 --- a/libretroshare/src/chat/distantchat.cc +++ /dev/null @@ -1,389 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: distantchat.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include - -#include "openssl/rand.h" -#include "openssl/dh.h" -#include "openssl/err.h" - -#include "crypto/rsaes.h" -#include "util/rsmemory.h" -#include "util/rsprint.h" - -#include "rsitems/rsmsgitems.h" - -#include "retroshare/rsmsgs.h" -#include "retroshare/rsidentity.h" -#include "retroshare/rsiface.h" - -#include "rsserver/p3face.h" -#include "services/p3idservice.h" -#include "gxs/gxssecurity.h" -#include "turtle/p3turtle.h" -#include "retroshare/rsids.h" -#include "distantchat.h" - -//#define DEBUG_DISTANT_CHAT - -#ifdef DEBUG_DISTANT_CHAT - -#include - -uint32_t msecs_of_day() -{ - timeval tv ; - gettimeofday(&tv,NULL) ; - return tv.tv_usec / 1000 ; -} -#define DISTANT_CHAT_DEBUG() std::cerr << time(NULL) << "." << std::setfill('0') << std::setw(3) << msecs_of_day() << " : DISTANT_CHAT : " << __FUNCTION__ << " : " -#endif - -//static const uint32_t DISTANT_CHAT_KEEP_ALIVE_TIMEOUT = 6 ; // send keep alive packet so as to avoid tunnel breaks. - -//static const uint32_t RS_DISTANT_CHAT_DH_STATUS_UNINITIALIZED = 0x0000 ; -//static const uint32_t RS_DISTANT_CHAT_DH_STATUS_HALF_KEY_DONE = 0x0001 ; -//static const uint32_t RS_DISTANT_CHAT_DH_STATUS_KEY_AVAILABLE = 0x0002 ; - -static const uint32_t DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID = 0xa0001 ; - -DistantChatService::DistantChatService() : - // default: accept everyone - mDistantChatPermissions(RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_NONE), - mGxsTunnels(nullptr), mDistantChatMtx("distant chat") {} - -void DistantChatService::connectToGxsTunnelService(RsGxsTunnelService *tr) -{ - mGxsTunnels = tr ; - tr->registerClientService(DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID,this) ; -} - -bool DistantChatService::handleOutgoingItem(RsChatItem *item) -{ - RsGxsTunnelId tunnel_id ; - - { - RS_STACK_MUTEX(mDistantChatMtx) ; - - std::map::const_iterator it=mDistantChatContacts.find(DistantChatPeerId(item->PeerId())); - - if(it == mDistantChatContacts.end()) - return false ; - } - -#ifdef CHAT_DEBUG - DISTANT_CHAT_DEBUG() << "p3ChatService::handleOutgoingItem(): sending to " << item->PeerId() << ": interpreted as a distant chat virtual peer id." << std::endl; -#endif - - uint32_t size = RsChatSerialiser().size(item) ; - RsTemporaryMemory mem(size) ; - - if(!RsChatSerialiser().serialise(item,mem,&size)) - { - std::cerr << "(EE) serialisation error. Something's really wrong!" << std::endl; - return false; - } -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << " sending: " << RsUtil::BinToHex(mem,size,100) << std::endl; - DISTANT_CHAT_DEBUG() << " size: " << std::dec << size << std::endl; - DISTANT_CHAT_DEBUG() << " hash: " << RsDirUtil::sha1sum(mem,size) << std::endl; -#endif - - mGxsTunnels->sendData( RsGxsTunnelId(item->PeerId()),DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID,mem,size); - return true; -} - -void DistantChatService::handleRecvChatStatusItem(RsChatStatusItem *cs) -{ - if(cs->flags & RS_CHAT_FLAG_CONNEXION_REFUSED) - { -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << "(II) Distant chat: received notification that peer refuses conversation." << std::endl; -#endif - RsServer::notify()->notifyChatStatus(ChatId(DistantChatPeerId(cs->PeerId())),"Connexion refused by distant peer!") ; - } - - if(cs->flags & RS_CHAT_FLAG_CLOSING_DISTANT_CONNECTION) - markDistantChatAsClosed(DistantChatPeerId(cs->PeerId())) ; - - // nothing more to do, because the decryption routing will update the last_contact time when decrypting. - - if(cs->flags & RS_CHAT_FLAG_KEEP_ALIVE) - std::cerr << "DistantChatService::handleRecvChatStatusItem(): received keep alive packet for inactive chat! peerId=" << cs->PeerId() << std::endl; -} - -bool DistantChatService::acceptDataFromPeer(const RsGxsId& gxs_id,const RsGxsTunnelId& tunnel_id,bool am_I_client_side) -{ - if(am_I_client_side) // always accept distant chat when we're the client side. - return true ; - - bool res = true ; - - if(mDistantChatPermissions & RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS) - res = (rsIdentity!=NULL) && rsIdentity->isARegularContact(gxs_id) ; - - if(mDistantChatPermissions & RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY) - res = false ; - - if(!res) - { -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << "(II) refusing distant chat from peer " << gxs_id << ". Sending a notification back to tunnel " << tunnel_id << std::endl; -#endif - RsChatStatusItem *item = new RsChatStatusItem ; - item->flags = RS_CHAT_FLAG_CONNEXION_REFUSED ; - item->status_string.clear() ; // is not used yet! But could be set in GUI to some message (??). - item->PeerId(RsPeerId(tunnel_id)) ; - - // we do not use handleOutGoingItem() because there's no distant chat contact, as the chat is refused. - - uint32_t size = RsChatSerialiser().size(item) ; - RsTemporaryMemory mem(size) ; - - if(!RsChatSerialiser().serialise(item,mem,&size)) - { - std::cerr << "(EE) serialisation error. Something's really wrong!" << std::endl; - return false; - } - -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << " sending: " << RsUtil::BinToHex(mem,size,100) << std::endl; - DISTANT_CHAT_DEBUG() << " size: " << std::dec << std::endl; - DISTANT_CHAT_DEBUG() << " hash: " << RsDirUtil::sha1sum(mem,size) << std::endl; -#endif - - mGxsTunnels->sendData( RsGxsTunnelId(item->PeerId()),DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID,mem,size); - } - - return res ; -} - -void DistantChatService::notifyTunnelStatus( const RsGxsTunnelId& tunnel_id, uint32_t tunnel_status ) -{ -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << "DistantChatService::notifyTunnelStatus(): got notification " << std::hex << tunnel_status << std::dec << " for tunnel " << tunnel_id << std::endl; -#endif - - switch(tunnel_status) - { - default: - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_UNKNOWN: std::cerr << "(EE) don't know how to handle RS_GXS_TUNNEL_STATUS_UNKNOWN !" << std::endl; - break ; - - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_CAN_TALK: RsServer::notify()->notifyChatStatus(ChatId(DistantChatPeerId(tunnel_id)),"Tunnel is secured. You can talk!") ; - RsServer::notify()->notifyPeerStatusChanged(tunnel_id.toStdString(),RS_STATUS_ONLINE) ; - break ; - - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_TUNNEL_DN: RsServer::notify()->notifyChatStatus(ChatId(DistantChatPeerId(tunnel_id)),"Tunnel is down...") ; - RsServer::notify()->notifyPeerStatusChanged(tunnel_id.toStdString(),RS_STATUS_OFFLINE) ; - break ; - - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED: RsServer::notify()->notifyChatStatus(ChatId(DistantChatPeerId(tunnel_id)),"Tunnel is down...") ; - RsServer::notify()->notifyPeerStatusChanged(tunnel_id.toStdString(),RS_STATUS_OFFLINE) ; - break ; - } -} - -void DistantChatService::receiveData( const RsGxsTunnelId& tunnel_id, unsigned char* data, uint32_t data_size) -{ -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << "DistantChatService::receiveData(): got data of size " << std::dec << data_size << " for tunnel " << tunnel_id << std::endl; - DISTANT_CHAT_DEBUG() << " received: " << RsUtil::BinToHex(data,data_size,100) << std::endl; - DISTANT_CHAT_DEBUG() << " hash: " << RsDirUtil::sha1sum(data,data_size) << std::endl; - DISTANT_CHAT_DEBUG() << " deserialising..." << std::endl; -#endif - - // always make the contact up to date. This is useful for server side, which doesn't know about the chat until it - // receives the first item. - { - RS_STACK_MUTEX(mDistantChatMtx) ; - - RsGxsTunnelService::GxsTunnelInfo tinfo; - if(!mGxsTunnels->getTunnelInfo(tunnel_id,tinfo)) - return ; - - // Check if the data is accepted. We cannot prevent the creation of tunnels at the level of p3GxsTunnels, since tunnels are shared between services. - // however, - - DistantChatContact& contact(mDistantChatContacts[DistantChatPeerId(tunnel_id)]) ; - - contact.to_id = tinfo.destination_gxs_id ; - contact.from_id = tinfo.source_gxs_id ; - } - - RsItem *item = RsChatSerialiser().deserialise(data,&data_size) ; - - if(item != NULL) - { - item->PeerId(RsPeerId(tunnel_id)) ; // just in case, but normally this is already done. - - handleIncomingItem(item) ; - RsServer::notify()->notifyListChange(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD); - } - else - std::cerr << " (EE) item could not be deserialised!" << std::endl; -} - -void DistantChatService::markDistantChatAsClosed(const DistantChatPeerId& dcpid) -{ - mGxsTunnels->closeExistingTunnel( - RsGxsTunnelId(dcpid), DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID ); - - RS_STACK_MUTEX(mDistantChatMtx) ; - - std::map::iterator it = mDistantChatContacts.find(dcpid) ; - - if(it != mDistantChatContacts.end()) - mDistantChatContacts.erase(it) ; -} - -bool DistantChatService::initiateDistantChatConnexion( - const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, - DistantChatPeerId& dcpid, uint32_t& error_code, bool notify ) -{ - RsGxsTunnelId tunnel_id ; - - if(!mGxsTunnels->requestSecuredTunnel(to_gxs_id,from_gxs_id,tunnel_id,DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID,error_code)) - return false ; - - dcpid = DistantChatPeerId(tunnel_id) ; - - DistantChatContact& dc_contact(mDistantChatContacts[dcpid]) ; - - dc_contact.from_id = from_gxs_id ; - dc_contact.to_id = to_gxs_id ; - - error_code = RS_DISTANT_CHAT_ERROR_NO_ERROR ; - - if(notify) - { - // Make a self message to raise the chat window - RsChatMsgItem *item = new RsChatMsgItem; - item->message = "[Starting distant chat. Please wait for secure tunnel"; - item->message += " to be established]"; - item->chatFlags = RS_CHAT_FLAG_PRIVATE; - item->sendTime = time(NULL); - item->PeerId(RsPeerId(tunnel_id)); - handleRecvChatMsgItem(item); - delete item ; - } - - return true ; -} - -bool DistantChatService::getDistantChatStatus(const DistantChatPeerId& tunnel_id, DistantChatPeerInfo& cinfo) -{ - RS_STACK_MUTEX(mDistantChatMtx); - - RsGxsTunnelService::GxsTunnelInfo tinfo; - - if(!mGxsTunnels->getTunnelInfo(RsGxsTunnelId(tunnel_id),tinfo)) return false; - - cinfo.to_id = tinfo.destination_gxs_id; - cinfo.own_id = tinfo.source_gxs_id; - cinfo.pending_items = tinfo.pending_data_packets; - cinfo.peer_id = tunnel_id; - - switch(tinfo.tunnel_status) - { - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_CAN_TALK : cinfo.status = RS_DISTANT_CHAT_STATUS_CAN_TALK; break; - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_TUNNEL_DN: cinfo.status = RS_DISTANT_CHAT_STATUS_TUNNEL_DN; break; - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED: cinfo.status = RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED; break; - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_UNKNOWN: - default: - cinfo.status = RS_DISTANT_CHAT_STATUS_UNKNOWN; break; - } - - return true; -} - -bool DistantChatService::closeDistantChatConnexion(const DistantChatPeerId &tunnel_id) -{ - mGxsTunnels->closeExistingTunnel(RsGxsTunnelId(tunnel_id), DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID) ; - - // also remove contact. Or do we wait for the notification? - - return true ; -} - -uint32_t DistantChatService::getDistantChatPermissionFlags() -{ - return mDistantChatPermissions ; -} -bool DistantChatService::setDistantChatPermissionFlags(uint32_t flags) -{ - if(mDistantChatPermissions != flags) - { - mDistantChatPermissions = flags ; -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << "(II) Changing distant chat permissions to " << flags << ". Existing openned chats will however remain active until closed" << std::endl; -#endif - triggerConfigSave() ; - } - - return true ; -} - -void DistantChatService::addToSaveList(std::list& list) const -{ - /* Save permission flags */ - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - kv.key = "DISTANT_CHAT_PERMISSION_FLAGS" ; - kv.value = RsUtil::NumberToString(mDistantChatPermissions) ; - - vitem->tlvkvs.pairs.push_back(kv) ; - - list.push_back(vitem) ; -} -bool DistantChatService::processLoadListItem(const RsItem *item) -{ - const RsConfigKeyValueSet *vitem = NULL ; - - if(NULL != (vitem = dynamic_cast(item))) - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - if(kit->key == "DISTANT_CHAT_PERMISSION_FLAGS") - { -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << "Loaded distant chat permission flags: " << kit->value << std::endl ; -#endif - if (!kit->value.empty()) - { - std::istringstream is(kit->value) ; - - uint32_t tmp ; - is >> tmp ; - - if(tmp < 3) - mDistantChatPermissions = tmp ; - else - std::cerr << "(EE) Invalid value read for DistantChatPermission flags in config: " << tmp << std::endl; - } - - return true; - } - - return false ; -} - diff --git a/libretroshare/src/chat/distantchat.h b/libretroshare/src/chat/distantchat.h deleted file mode 100644 index eda55da49..000000000 --- a/libretroshare/src/chat/distantchat.h +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: distantchat.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -#pragma once - -#include -#include -#include - -class RsGixs ; - -static const uint32_t DISTANT_CHAT_AES_KEY_SIZE = 16 ; - -/** - * Public interface only uses DistandChatPeerId, but internally, this is - * converted into a RsGxsTunnelId - */ -class DistantChatService: public RsGxsTunnelService::RsGxsTunnelClientService -{ -public: - DistantChatService() ; - - virtual void triggerConfigSave()=0 ; - bool processLoadListItem(const RsItem *item) ; - void addToSaveList(std::list& list) const; - - /** - * Creates the invite if the public key of the distant peer is available. - * On success, stores the invite in the map above, so that we can respond - * to tunnel requests. */ - bool initiateDistantChatConnexion( const RsGxsId& to_gxs_id, - const RsGxsId &from_gxs_id, - DistantChatPeerId& dcpid, - uint32_t &error_code, - bool notify = true ); - bool closeDistantChatConnexion(const DistantChatPeerId &tunnel_id) ; - - // Sets flags to only allow connexion from some people. - - uint32_t getDistantChatPermissionFlags() ; - bool setDistantChatPermissionFlags(uint32_t flags) ; - - // Returns the status of a distant chat contact. The contact is defined by the tunnel id (turned into a DistantChatPeerId) because - // each pair of talking GXS id needs to be treated separately - - virtual bool getDistantChatStatus(const DistantChatPeerId &tunnel_id, DistantChatPeerInfo& cinfo) ; - - // derived in p3ChatService, so as to pass down some info - virtual void handleIncomingItem(RsItem *) = 0; - virtual bool handleRecvChatMsgItem(RsChatMsgItem *& ci)=0 ; - - bool handleOutgoingItem(RsChatItem *) ; - bool handleRecvItem(RsChatItem *) ; - void handleRecvChatStatusItem(RsChatStatusItem *cs) ; - -private: - struct DistantChatContact - { - RsGxsId from_id ; - RsGxsId to_id ; - }; - // This maps contains the current peers to talk to with distant chat. - // - std::map mDistantChatContacts ; // current peers we can talk to - - // Permission handling - - uint32_t mDistantChatPermissions ; - - // Overloaded from RsGxsTunnelClientService - -public: - virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) ; - -private: - virtual bool acceptDataFromPeer( - const RsGxsId& gxs_id, const RsGxsTunnelId& tunnel_id, - bool am_I_client_side); - virtual void notifyTunnelStatus( - const RsGxsTunnelId& tunnel_id, uint32_t tunnel_status); - virtual void receiveData( - const RsGxsTunnelId& id, unsigned char* data, uint32_t data_size ); - - // Utility functions. - - void markDistantChatAsClosed(const DistantChatPeerId& dcpid) ; - - RsGxsTunnelService *mGxsTunnels ; - RsMutex mDistantChatMtx ; -}; diff --git a/libretroshare/src/chat/distributedchat.cc b/libretroshare/src/chat/distributedchat.cc deleted file mode 100644 index 4112afd31..000000000 --- a/libretroshare/src/chat/distributedchat.cc +++ /dev/null @@ -1,2205 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: distributedchat.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include -#include -#include - -#include "util/rsprint.h" -#include "util/rsmemory.h" -#include "distributedchat.h" - -#include "pqi/p3historymgr.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsiface.h" -#include "retroshare/rsidentity.h" -#include "rsserver/p3face.h" -#include "gxs/rsgixs.h" -#include "services/p3idservice.h" - -//#define DEBUG_CHAT_LOBBIES 1 - -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 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 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_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 MIN_DELAY_BETWEEN_PUBLIC_LOBBY_REQ = 20 ; // don't ask for lobby list more than once every 30 secs. -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_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. - -#define IS_PUBLIC_LOBBY(flags) (flags & RS_CHAT_LOBBY_FLAGS_PUBLIC ) -#define IS_PGP_SIGNED_LOBBY(flags) (flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED) -#define IS_CONNEXION_CHALLENGE(flags) (flags & RS_CHAT_LOBBY_FLAGS_CHALLENGE ) - -#define EXTRACT_PRIVACY_FLAGS(flags) (ChatLobbyFlags(flags.toUInt32()) * (RS_CHAT_LOBBY_FLAGS_PUBLIC | RS_CHAT_LOBBY_FLAGS_PGP_SIGNED)) - -DistributedChatService::DistributedChatService(uint32_t serv_type,p3ServiceControl *sc,p3HistoryMgr *hm, RsGixs *is) - : mServType(serv_type),mDistributedChatMtx("Distributed Chat"), mServControl(sc), mHistMgr(hm),mGixs(is) -{ - _time_shift_average = 0.0f ; - _should_reset_lobby_counts = false ; - last_visible_lobby_info_request_time = 0 ; -} - -void DistributedChatService::flush() -{ - static rstime_t last_clean_time_lobby = 0 ; - static rstime_t last_req_chat_lobby_list = 0 ; - - rstime_t now = time(NULL) ; - - if(last_clean_time_lobby + LOBBY_CACHE_CLEANING_PERIOD < now) - { - cleanLobbyCaches() ; - last_clean_time_lobby = now ; - - // also make sure that the default identity is not null - - if(_default_identity.isNull()) - { - std::list ids ; - mGixs->getOwnIds(ids) ; - - if(!ids.empty()) - { - _default_identity = ids.front() ; - triggerConfigSave() ; - } - } - } - if(last_req_chat_lobby_list + LOBBY_LIST_AUTO_UPDATE_TIME < now) - { - std::vector visible_lobbies_tmp ; - getListOfNearbyChatLobbies(visible_lobbies_tmp) ; - - if (visible_lobbies_tmp.empty()){ - last_req_chat_lobby_list = now-LOBBY_LIST_AUTO_UPDATE_TIME+MIN_DELAY_BETWEEN_PUBLIC_LOBBY_REQ; - } else { - last_req_chat_lobby_list = now ; - } - } -} - -bool DistributedChatService::handleRecvChatLobbyMsgItem(RsChatMsgItem *ci) -{ - // check if it's a lobby msg, in which case we replace the peer id by the lobby's virtual peer id. - // - RsChatLobbyMsgItem *cli = dynamic_cast(ci) ; - - if(cli == NULL) - return true ; // the item is handled correctly if it's not a lobby item ;-) - - rstime_t now = time(NULL) ; - - if(now+100 > (rstime_t) cli->sendTime + MAX_KEEP_MSG_RECORD) // the message is older than the max cache keep plus 100 seconds ! It's too old, and is going to make an echo! - { - std::cerr << "Received severely outdated lobby event item (" << now - (rstime_t)cli->sendTime << " in the past)! Dropping it!" << std::endl; - std::cerr << "Message item is:" << std::endl; - cli->print(std::cerr) ; - std::cerr << std::endl; - return false ; - } - if(now+600 < (rstime_t) cli->sendTime) // the message is from the future. Drop it. more than 10 minutes - { - std::cerr << "Received event item from the future (" << (rstime_t)cli->sendTime - now << " seconds in the future)! Dropping it!" << std::endl; - std::cerr << "Message item is:" << std::endl; - cli->print(std::cerr) ; - std::cerr << std::endl; - return false ; - } - - if( rsReputations->overallReputationLevel(cli->signature.keyId) == - RsReputationLevel::LOCALLY_NEGATIVE ) - { - std::cerr << "(WW) Received lobby msg/item from banned identity " << cli->signature.keyId << ". Dropping it." << std::endl; - return false ; - } - if(!checkSignature(cli,cli->PeerId())) // check the object's signature and possibly request missing keys - { - std::cerr << "Signature mismatched for this lobby event item. Item will be dropped: " << std::endl; - cli->print(std::cerr) ; - std::cerr << std::endl; - return false; - } - - // add a routing clue for this peer/GXSid combination. This is quite reliable since the lobby transport is almost instantaneous - - rsGRouter->addRoutingClue(GRouterKeyId(cli->signature.keyId),cli->PeerId()) ; - - ChatLobbyFlags fl ; - - // delete items that are not for us, as early as possible. - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - // send upward for display - - std::map::const_iterator it = _chat_lobbys.find(cli->lobby_id) ; - - if(it == _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Chatlobby for id " << std::hex << cli->lobby_id << " has no record. Dropping the msg." << std::dec << std::endl; -#endif - return false; - } - fl = it->second.lobby_flags ; - } - if(IS_PGP_SIGNED_LOBBY(fl)) - { - RsIdentityDetails details; - - if(!rsIdentity->getIdDetails(cli->signature.keyId,details)) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "(WW) cannot get ID " << cli->signature.keyId << " for checking signature of lobby item." << std::endl; -#endif - return false; - } - - if(!(details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)) - { - std::cerr << "(WW) Received a lobby msg/item that is not PGP-authed (id=" << cli->signature.keyId << "), whereas the lobby flags require it. Rejecting!" << std::endl; - - return false ; - } - } - - if(!bounceLobbyObject(cli,cli->PeerId())) // forwards the message to friends, keeps track of subscribers, etc. - return false; - - // setup the peer id to the virtual peer id of the lobby. - // - RsPeerId virtual_peer_id ; - getVirtualPeerId(cli->lobby_id,virtual_peer_id) ; - cli->PeerId(virtual_peer_id) ; - - //name = cli->nick; - //popupChatFlag = RS_POPUP_CHATLOBBY; - - RsServer::notify()->AddPopupMessage(RS_POPUP_CHATLOBBY, ChatId(cli->lobby_id).toStdString(), cli->signature.keyId.toStdString(), cli->message); /* notify private chat message */ - - return true ; -} - -bool DistributedChatService::checkSignature(RsChatLobbyBouncingObject *obj,const RsPeerId& peer_id) -{ - // Always request the key. If not present, it will be asked to the peer id who sent this item. - - std::list peer_list ; - peer_list.push_back(peer_id) ; - - // network pre-request key to allow message authentication. - - mGixs->requestKey(obj->signature.keyId,peer_list,RsIdentityUsage(RsServiceType::CHAT, - RsIdentityUsage::CHAT_LOBBY_MSG_VALIDATION, - RsGxsGroupId(), - RsGxsMessageId(), - RsGxsMessageId(), - RsGxsMessageId(), - obj->lobby_id)); - - uint32_t size = RsChatSerialiser(RsSerializationFlags::SIGNATURE) - .size(dynamic_cast(obj)); - RsTemporaryMemory memory(size) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Checking object signature: " << std::endl; - std::cerr << " signature id: " << obj->signature.keyId << std::endl; -#endif - - if( !RsChatSerialiser(RsSerializationFlags::SIGNATURE) - .serialise(dynamic_cast(obj),memory,&size) ) - { - std::cerr << " (EE) Cannot serialise message item. " << std::endl; - return false ; - } - - uint32_t error_status ; - RsIdentityUsage use_info(RsServiceType::CHAT, - RsIdentityUsage::CHAT_LOBBY_MSG_VALIDATION, - RsGxsGroupId(), - RsGxsMessageId(), - RsGxsMessageId(), - RsGxsMessageId(), - obj->lobby_id) ; - - if(!mGixs->validateData(memory,size,obj->signature,false,use_info,error_status)) - { - bool res = false ; - - switch(error_status) - { - case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "(WW) Key is not is cache. Cannot verify." << std::endl; -#endif - res =true ; - break ; - case RsGixs::RS_GIXS_ERROR_SIGNATURE_MISMATCH: std::cerr << "(EE) Signature mismatch. Spoofing/MITM?." << std::endl; - res =false ; - break ; - default: break ; - } - return res; - } - - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " signature: CHECKS" << std::endl; -#endif - - return true ; -} - -bool DistributedChatService::getVirtualPeerId(const ChatLobbyId& id,ChatLobbyVirtualPeerId& vpid) -{ - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Was asked for virtual peer name of " << std::hex << id << std::dec<< std::endl; -#endif - std::map::const_iterator it(_chat_lobbys.find(id)) ; - - if(it == _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " not found!! " << std::endl; -#endif - return false ; - } - - vpid = it->second.virtual_peer_id ; -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " returning " << vpid << std::endl; -#endif - return true ; -} - -void DistributedChatService::locked_printDebugInfo() const -{ - std::cerr << "Recorded lobbies: " << std::endl; - rstime_t now = time(NULL) ; - - for( std::map::const_iterator it(_chat_lobbys.begin()) ;it!=_chat_lobbys.end();++it) - { - std::cerr << " Lobby id\t\t: " << std::hex << it->first << std::dec << std::endl; - std::cerr << " Lobby name\t\t: " << it->second.lobby_name << std::endl; - std::cerr << " Lobby topic\t\t: " << it->second.lobby_topic << std::endl; - std::cerr << " nick name\t\t: " << it->second.gxs_id << std::endl; - std::cerr << " Lobby type\t\t: " << ((IS_PUBLIC_LOBBY(it->second.lobby_flags))?"Public":"Private") << std::endl; - std::cerr << " Lobby security\t\t: " << ((IS_PGP_SIGNED_LOBBY(it->second.lobby_flags))?"PGP-signed IDs required":"Anon IDs accepted") << std::endl; - std::cerr << " Lobby peer id\t: " << it->second.virtual_peer_id << std::endl; - std::cerr << " Challenge count\t: " << it->second.connexion_challenge_count << std::endl; - std::cerr << " Last activity\t: " << now - it->second.last_activity << " seconds ago." << std::endl; - std::cerr << " Cached messages\t: " << it->second.msg_cache.size() << std::endl; - - for(std::map::const_iterator it2(it->second.msg_cache.begin());it2!=it->second.msg_cache.end();++it2) - std::cerr << " " << std::hex << it2->first << std::dec << " time=" << now - it2->second << " secs ago" << std::endl; - - std::cerr << " Participating friends: " << std::endl; - - for(std::set::const_iterator it2(it->second.participating_friends.begin());it2!=it->second.participating_friends.end();++it2) - std::cerr << " " << *it2 << std::endl; - - std::cerr << " Participating nick names: " << std::endl; - - for(std::map::const_iterator it2(it->second.gxs_ids.begin());it2!=it->second.gxs_ids.end();++it2) - std::cerr << " " << it2->first << ": " << now - it2->second << " secs ago" << std::endl; - - } - - std::cerr << "Visible public lobbies: " << std::endl; - - for( std::map::const_iterator it(_visible_lobbies.begin()) ;it!=_visible_lobbies.end();++it) - { - std::cerr << " " << std::hex << it->first << " name = " << std::dec << it->second.lobby_name << it->second.lobby_topic << std::endl; - for(std::set::const_iterator it2(it->second.participating_friends.begin());it2!=it->second.participating_friends.end();++it2) - std::cerr << " With friend: " << *it2 << std::endl; - } - - std::cerr << "Chat lobby flags: " << std::endl; - - for( std::map::const_iterator it(_known_lobbies_flags.begin()) ;it!=_known_lobbies_flags.end();++it) - std::cerr << " \"" << std::hex << it->first << "\" flags = " << it->second << std::dec << std::endl; -} - -bool DistributedChatService::locked_bouncingObjectCheck(RsChatLobbyBouncingObject *obj,const RsPeerId& peer_id,uint32_t lobby_count) -{ - static std::map > message_counts ; - - std::ostringstream os ; - os << obj->lobby_id ; - - std::string pid = peer_id.toStdString() + "_" + os.str() ; - - // Check for the number of peers in the lobby. First look into visible lobbies, because the number - // of peers there is more accurate. If non existant (because it's a private lobby), take the count from - // the current lobby list. - // - std::map::const_iterator it = _visible_lobbies.find(obj->lobby_id) ; - - if(it != _visible_lobbies.end()) - lobby_count = it->second.total_number_of_peers ; - else - { - std::map::const_iterator it = _chat_lobbys.find(obj->lobby_id) ; - - if(it != _chat_lobbys.end()) - lobby_count = it->second.gxs_ids.size() ; - else - { - std::cerr << "DistributedChatService::locked_bouncingObjectCheck(): weird situation: cannot find lobby in visible lobbies nor current lobbies. Dropping message. If you see this, contact the developers." << std::endl; - return false ; - } - } - - // max objects per second: lobby_count * 1/MAX_DELAY_BETWEEN_LOBBY_KEEP_ALIVE objects per second. - // So in cache, there is in average that number times MAX_MESSAGES_PER_SECONDS_PERIOD - // - float max_cnt = std::max(10.0f, 10*lobby_count / (float)MAX_DELAY_BETWEEN_LOBBY_KEEP_ALIVE * MAX_MESSAGES_PER_SECONDS_PERIOD) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "lobby_count=" << lobby_count << std::endl; - std::cerr << "Got msg for peer " << pid << std::dec << ". Limit is " << max_cnt << ". List is " ; - for(std::list::const_iterator it(message_counts[pid].begin());it!=message_counts[pid].end();++it) - std::cerr << *it << " " ; - std::cerr << std::endl; -#endif - - rstime_t now = time(NULL) ; - - std::list& lst = message_counts[pid] ; - - // Clean old messages time stamps from the list. - // - while(!lst.empty() && lst.front() + MAX_MESSAGES_PER_SECONDS_PERIOD < now) - lst.pop_front() ; - - if(lst.size() > max_cnt) - { - std::cerr << "(WW) more than " << max_cnt << " messages forwarded by peer " << pid << ". Message from \"" << obj->nick << "\" will not be forwarded." << std::endl; - return false; - } - else - lst.push_back(now) ; - - return true ; -} - -// This function should be used for all types of chat messages. But this requires a non backward compatible change in -// chat protocol. To be done for version 0.6 -// -void DistributedChatService::checkSizeAndSendLobbyMessage(RsChatItem *msg) -{ - // Multiple-parts messaging has been disabled in lobbies, because of the following issues: - // 1 - it breaks signatures because the subid of each sub-item is changed (can be fixed) - // 2 - it breaks (can be fixed as well) - // 3 - it is unreliable since items are not guarrantied to all arrive in the end (cannot be fixed) - // 4 - large objects can be used to corrupt end peers (cannot be fixed) - // - static const uint32_t MAX_ITEM_SIZE = 32000 ; - - if(RsChatSerialiser().size(msg) > MAX_ITEM_SIZE) - { - std::cerr << "(EE) Chat item exceeds maximum serial size. It will be dropped." << std::endl; - delete msg ; - return ; - } - sendChatItem(msg) ; -} - -bool DistributedChatService::handleRecvItem(RsChatItem *item) -{ - switch(item->PacketSubType()) - { - case RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_EVENT: handleRecvChatLobbyEventItem (dynamic_cast(item)) ; break ; - case RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_DEPRECATED: handleRecvLobbyInvite_Deprecated (dynamic_cast(item)) ; break ; // to be removed (deprecated since May 2017) - case RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE: handleRecvLobbyInvite (dynamic_cast(item)) ; break ; - case RS_PKT_SUBTYPE_CHAT_LOBBY_CHALLENGE: handleConnectionChallenge (dynamic_cast(item)) ; break ; - case RS_PKT_SUBTYPE_CHAT_LOBBY_UNSUBSCRIBE: handleFriendUnsubscribeLobby (dynamic_cast(item)) ; break ; - case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST: handleRecvChatLobbyListRequest (dynamic_cast(item)) ; break ; - case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST: handleRecvChatLobbyList (dynamic_cast(item)) ; break ; - default: return false ; - } - return true ; -} - -void DistributedChatService::handleRecvChatLobbyListRequest(RsChatLobbyListRequestItem *clr) -{ - // make a lobby list item - // - RsChatLobbyListItem *item = new RsChatLobbyListItem; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Peer " << clr->PeerId() << " requested the list of public chat lobbies." << std::endl; -#endif - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - for(std::map::const_iterator it(_chat_lobbys.begin());it!=_chat_lobbys.end();++it) - { - const ChatLobbyEntry& lobby(it->second) ; - - if(IS_PUBLIC_LOBBY(lobby.lobby_flags) || - (lobby.previously_known_peers.find(clr->PeerId()) != lobby.previously_known_peers.end() - ||lobby.participating_friends.find(clr->PeerId()) != lobby.participating_friends.end()) ) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Adding lobby " << std::hex << it->first << std::dec << " \"" - << it->second.lobby_name << it->second.lobby_topic << "\" count=" << it->second.gxs_ids.size() << std::endl; -#endif - - VisibleChatLobbyInfo info ; - - info.id = it->first ; - info.name = it->second.lobby_name ; - info.topic = it->second.lobby_topic ; - info.count = it->second.gxs_ids.size() ; - info.flags = ChatLobbyFlags(EXTRACT_PRIVACY_FLAGS(it->second.lobby_flags)) ; - - item->lobbies.push_back(info) ; - } -#ifdef DEBUG_CHAT_LOBBIES - else - std::cerr << " Not adding private lobby " << std::hex << it->first << std::dec << std::endl ; -#endif - } - } - - item->PeerId(clr->PeerId()) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Sending list to " << clr->PeerId() << std::endl; -#endif - sendChatItem(item); -} - -void DistributedChatService::handleRecvChatLobbyList(RsChatLobbyListItem *item) -{ - if(item->lobbies.size() > MAX_ALLOWED_LOBBIES_IN_LIST_WARNING) - std::cerr << "Warning: Peer " << item->PeerId() << "(" << rsPeers->getPeerName(item->PeerId()) << ") is sending a lobby list of " << item->lobbies.size() << " lobbies. This is unusual, and probably a attempt to crash you." << std::endl; - - std::list chatLobbyToSubscribe; - std::list invitationNeeded ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Received chat lobby list from friend " << item->PeerId() << ", " << item->lobbies.size() << " elements." << std::endl; -#endif - { - rstime_t now = time(NULL) ; - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - for(uint32_t i=0;ilobbies.size() && i < MAX_ALLOWED_LOBBIES_IN_LIST_WARNING;++i) - { - VisibleChatLobbyRecord& rec(_visible_lobbies[item->lobbies[i].id]) ; - - rec.lobby_id = item->lobbies[i].id ; - rec.lobby_name = item->lobbies[i].name ; - rec.lobby_topic = item->lobbies[i].topic ; - rec.participating_friends.insert(item->PeerId()) ; - - if(_should_reset_lobby_counts) - rec.total_number_of_peers = item->lobbies[i].count ; - else - rec.total_number_of_peers = std::max(rec.total_number_of_peers,item->lobbies[i].count) ; - - rec.last_report_time = now ; - rec.lobby_flags = EXTRACT_PRIVACY_FLAGS(item->lobbies[i].flags) ; - - std::map::const_iterator it(_known_lobbies_flags.find(item->lobbies[i].id)) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " lobby id " << std::hex << item->lobbies[i].id << std::dec << ", " << item->lobbies[i].name - << ", " << item->lobbies[i].count << " participants" << std::endl; -#endif - if(it != _known_lobbies_flags.end() && (it->second & RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE)) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " lobby is flagged as autosubscribed. Adding it to subscribe list." << std::endl; -#endif - ChatLobbyId clid = item->lobbies[i].id; - if(_chat_lobbys.find(clid) == _chat_lobbys.end()) - chatLobbyToSubscribe.push_back(clid); - } - - // for subscribed lobbies, check that item->PeerId() is among the participating friends. If not, add him! - - std::map::iterator it2 = _chat_lobbys.find(item->lobbies[i].id) ; - - if(it2 != _chat_lobbys.end() && it2->second.participating_friends.find(item->PeerId()) == it2->second.participating_friends.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " lobby is currently subscribed but friend is not participating already -> adding to partipating friends and sending invite." << std::endl; -#endif - it2->second.participating_friends.insert(item->PeerId()) ; - invitationNeeded.push_back(item->lobbies[i].id) ; - } - } - } - - std::list::iterator it; - for (it = chatLobbyToSubscribe.begin(); it != chatLobbyToSubscribe.end(); ++it) - { - RsGxsId gxsId = _lobby_default_identity[*it]; - if (gxsId.isNull()) - gxsId = _default_identity; - - //Check if gxsId can connect to this lobby - ChatLobbyFlags flags(0); - std::map::const_iterator vlIt = _visible_lobbies.find(*it) ; - if(vlIt != _visible_lobbies.end()) - flags = vlIt->second.lobby_flags; - else - { - std::map::const_iterator clIt = _chat_lobbys.find(*it) ; - - if(clIt != _chat_lobbys.end()) - flags = clIt->second.lobby_flags; - } - - RsIdentityDetails idd ; - if(!rsIdentity->getIdDetails(gxsId,idd)) - std::cerr << "(EE) Lobby auto-subscribe: Can't get Id detail for:" << gxsId.toStdString().c_str() << std::endl; - else - { - if(IS_PGP_SIGNED_LOBBY(flags) - && !(idd.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) ) - { - std::cerr << "(EE) Attempt to auto-subscribe to signed lobby with non signed Id. Remove it." << std::endl; - setLobbyAutoSubscribe(*it, false); - } else { - joinVisibleChatLobby(*it,gxsId); - } - } - } - - for(std::list::const_iterator it = invitationNeeded.begin();it!=invitationNeeded.end();++it) - invitePeerToLobby(*it,item->PeerId(),false) ; - - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD) ; - _should_reset_lobby_counts = false ; -} - -void DistributedChatService::addTimeShiftStatistics(int D) -{ - static const int S = 50 ; // accuracy up to 2^50 second. Quite conservative! - static int total = 0 ; - static std::vector log_delay_histogram(S,0) ; - - int delay = (D<0)?(-D):D ; - - if(delay < 0) - delay = -delay ; - - // compute log2. - int l = 0 ; - while(delay > 0) delay >>= 1, ++l ; - - int bin = std::min(S-1,l) ; - ++log_delay_histogram[bin] ; - ++total ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "New delay stat item. delay=" << D << ", log=" << bin << " total=" << total << ", histogram = " ; - - for(int i=0;i 30) - { - float t = 0.0f ; - int i=0 ; - for(;i0 so i is incremented - if(log_delay_histogram[i-1] == 0) return ; // cannot happen, either, but let's be cautious. - - float expected = ( i * (log_delay_histogram[i-1] - t + total*0.5) + (i-1) * (t - total*0.5) ) / (float)log_delay_histogram[i-1] - 1; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << ". Expected delay: " << expected << std::endl ; -#endif - - if(expected > 9) // if more than 20 samples - RsServer::notify()->notifyChatLobbyTimeShift( (int)pow(2.0f,expected)) ; - - total = 0.0f ; - log_delay_histogram.clear() ; - log_delay_histogram.resize(S,0) ; - } -#ifdef DEBUG_CHAT_LOBBIES - else - std::cerr << std::endl; -#endif -} - -void DistributedChatService::handleRecvChatLobbyEventItem(RsChatLobbyEventItem *item) -{ - ChatLobbyFlags fl ; - - // delete items that are not for us, as early as possible. - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - // send upward for display - - std::map::const_iterator it = _chat_lobbys.find(item->lobby_id) ; - - if(it == _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Chatlobby for id " << std::hex << item->lobby_id << " has no record. Dropping the msg." << std::dec << std::endl; -#endif - return ; - } - fl = it->second.lobby_flags ; - } - - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Received ChatLobbyEvent item of type " << (int)(item->event_type) << ", and string=" << item->string1 << std::endl; -#endif - rstime_t now = time(nullptr); - - if( rsReputations->overallReputationLevel(item->signature.keyId) == - RsReputationLevel::LOCALLY_NEGATIVE ) - { - std::cerr << "(WW) Received lobby msg/item from banned identity " << item->signature.keyId << ". Dropping it." << std::endl; - return ; - } - if(!checkSignature(item,item->PeerId())) // check the object's signature and possibly request missing keys - { - std::cerr << "Signature mismatched for this lobby event item: " << std::endl; - item->print(std::cerr) ; - std::cerr << std::endl; - return ; - } - - if(IS_PGP_SIGNED_LOBBY(fl)) - { - RsIdentityDetails details; - - if(!rsIdentity->getIdDetails(item->signature.keyId,details)) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "(WW) cannot get ID " << item->signature.keyId << " for checking signature of lobby item." << std::endl; -#endif - return ; - } - - if(!(details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)) - { - std::cerr << "(WW) Received a lobby msg/item that is not PGP-authed (ID=" << item->signature.keyId << "), whereas the lobby flags require it. Rejecting!" << std::endl; - return ; - } - } - addTimeShiftStatistics((int)now - (int)item->sendTime) ; - - if(now+100 > (rstime_t) item->sendTime + MAX_KEEP_MSG_RECORD) // the message is older than the max cache keep minus 100 seconds ! It's too old, and is going to make an echo! - { - std::cerr << "Received severely outdated lobby event item (" << now - (rstime_t)item->sendTime << " in the past)! Dropping it!" << std::endl; - std::cerr << "Message item is:" << std::endl; - item->print(std::cerr) ; - std::cerr << std::endl; - return ; - } - if(now+600 < (rstime_t) item->sendTime) // the message is from the future more than 10 minutes - { - std::cerr << "Received event item from the future (" << (rstime_t)item->sendTime - now << " seconds in the future)! Dropping it!" << std::endl; - std::cerr << "Message item is:" << std::endl; - item->print(std::cerr) ; - std::cerr << std::endl; - return ; - } - // add a routing clue for this peer/GXSid combination. This is quite reliable since the lobby transport is almost instantaneous - rsGRouter->addRoutingClue(GRouterKeyId(item->signature.keyId),item->PeerId()) ; - - if(! bounceLobbyObject(item,item->PeerId())) - return ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " doing specific job for this status item." << std::endl; -#endif - - if(item->event_type == RS_CHAT_LOBBY_EVENT_PEER_LEFT) // if a peer left. Remove its nickname from the list. - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " removing nickname " << item->nick << " from lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _chat_lobbys.find(item->lobby_id) ; - - if(it != _chat_lobbys.end()) - { - std::map::iterator it2(it->second.gxs_ids.find(item->signature.keyId)) ; - - if(it2 != it->second.gxs_ids.end()) - { - it->second.gxs_ids.erase(it2) ; -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " removed id " << item->signature.keyId << " from lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - } -#ifdef DEBUG_CHAT_LOBBIES - else - std::cerr << " (EE) nickname " << item->nick << " not in participant nicknames list!" << std::endl; -#endif - } - } - else if(item->event_type == RS_CHAT_LOBBY_EVENT_PEER_JOINED) // if a joined left. Add its nickname to the list. - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " adding nickname " << item->nick << " to lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _chat_lobbys.find(item->lobby_id) ; - - if(it != _chat_lobbys.end()) - { - it->second.gxs_ids[item->signature.keyId] = time(NULL) ; -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " added nickname " << item->nick << " from lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - // trigger a keep alive packets so as to inform the new participant of our presence in the chatroom - it->second.last_keep_alive_packet_time = 0 ; - } - } - else if(item->event_type == RS_CHAT_LOBBY_EVENT_KEEP_ALIVE) // keep alive packet. - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " adding nickname " << item->nick << " to lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _chat_lobbys.find(item->lobby_id) ; - - if(it != _chat_lobbys.end()) - { - it->second.gxs_ids[item->signature.keyId] = time(NULL) ; -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " added nickname " << item->nick << " from lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - } - } - - RsServer::notify()->notifyChatLobbyEvent(item->lobby_id,item->event_type,item->signature.keyId,item->string1); -} - -void DistributedChatService::getListOfNearbyChatLobbies(std::vector& visible_lobbies) -{ - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - visible_lobbies.clear() ; - - for(std::map::const_iterator it(_visible_lobbies.begin());it!=_visible_lobbies.end();++it) - visible_lobbies.push_back(it->second) ; - } - - rstime_t now = time(NULL) ; - - if(now > MIN_DELAY_BETWEEN_PUBLIC_LOBBY_REQ + last_visible_lobby_info_request_time) - { - std::set ids ; - mServControl->getPeersConnected(mServType, ids); - - for(std::set::const_iterator it(ids.begin());it!=ids.end();++it) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " asking list of public lobbies to " << *it << std::endl; -#endif - RsChatLobbyListRequestItem *item = new RsChatLobbyListRequestItem ; - item->PeerId(*it) ; - - sendChatItem(item); - } - last_visible_lobby_info_request_time = now ; - _should_reset_lobby_counts = true ; - } -} - -// returns: -// true: the object is not a duplicate and should be used -// false: the object is a duplicate or there is an error, and it should be destroyed. -// -bool DistributedChatService::bounceLobbyObject(RsChatLobbyBouncingObject *item,const RsPeerId& peer_id) -{ - rstime_t now = time(NULL) ; - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ -#ifdef DEBUG_CHAT_LOBBIES - locked_printDebugInfo() ; // debug - - std::cerr << "Handling ChatLobbyMsg " << std::hex << item->msg_id << ", lobby id " << item->lobby_id << ", from peer id " << peer_id << std::endl; -#endif - - // send upward for display - - std::map::iterator it(_chat_lobbys.find(item->lobby_id)) ; - - if(it == _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Chatlobby for id " << std::hex << item->lobby_id << " has no record. Dropping the msg." << std::dec << std::endl; -#endif - return false ; - } - - ChatLobbyEntry& lobby(it->second) ; - - // Adds the peer id to the list of friend participants, even if it's not original msg source - - if(peer_id != mServControl->getOwnId()) - lobby.participating_friends.insert(peer_id) ; - - lobby.gxs_ids[item->signature.keyId] = now ; - - // Checks wether the msg is already recorded or not - - std::map::iterator it2(lobby.msg_cache.find(item->msg_id)) ; - - if(it2 != lobby.msg_cache.end()) // found! - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Msg already received at time " << it2->second << ". Dropping!" << std::endl ; -#endif - it2->second = now ; // update last msg seen time, to prevent echos. - return false ; - } -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Msg not received already. Adding in cache, and forwarding!" << std::endl ; -#endif - - lobby.msg_cache[item->msg_id] = now ; - lobby.last_activity = now ; - - // Check that if we have a lobby bouncing object, it's not flooding the lobby - if(!locked_bouncingObjectCheck(item,peer_id,lobby.participating_friends.size())) - return false; - - // Forward to allparticipating friends, except this peer. - - for(std::set::const_iterator it(lobby.participating_friends.begin());it!=lobby.participating_friends.end();++it) - if((*it)!=peer_id && mServControl->isPeerConnected(mServType, *it)) - { - RsChatLobbyBouncingObject *obj2 = item->duplicate() ; // makes a copy - RsChatItem *item2 = dynamic_cast(obj2) ; - - assert(item2 != NULL) ; - - item2->PeerId(*it) ; // replaces the virtual peer id with the actual destination. - - checkSizeAndSendLobbyMessage(item2) ; - } - - ++lobby.connexion_challenge_count ; - - return true ; -} - -void DistributedChatService::sendLobbyStatusString(const ChatLobbyId& lobby_id,const std::string& status_string) -{ - sendLobbyStatusItem(lobby_id,RS_CHAT_LOBBY_EVENT_PEER_STATUS,status_string) ; -} - -/** - * Inform other Clients of a nickname change - * - * as example for updating their ChatLobby Blocklist for muted peers - * */ -void DistributedChatService::sendLobbyStatusPeerChangedNickname(const ChatLobbyId& lobby_id, const std::string& newnick) -{ - sendLobbyStatusItem(lobby_id,RS_CHAT_LOBBY_EVENT_PEER_CHANGE_NICKNAME, newnick) ; -} - - -void DistributedChatService::sendLobbyStatusPeerLeaving(const ChatLobbyId& lobby_id) -{ - sendLobbyStatusItem(lobby_id,RS_CHAT_LOBBY_EVENT_PEER_LEFT,std::string()) ; -} - -void DistributedChatService::sendLobbyStatusNewPeer(const ChatLobbyId& lobby_id) -{ - sendLobbyStatusItem(lobby_id,RS_CHAT_LOBBY_EVENT_PEER_JOINED,std::string()) ; -} - -void DistributedChatService::sendLobbyStatusKeepAlive(const ChatLobbyId& lobby_id) -{ - sendLobbyStatusItem(lobby_id,RS_CHAT_LOBBY_EVENT_KEEP_ALIVE,std::string()) ; -} - -void DistributedChatService::sendLobbyStatusItem(const ChatLobbyId& lobby_id,int type,const std::string& status_string) -{ - RsChatLobbyEventItem item ; - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - item.event_type = type ; - item.string1 = status_string ; - item.sendTime = time(NULL) ; - - if(! locked_initLobbyBouncableObject(lobby_id,item)) - return ; - } - RsPeerId ownId = mServControl->getOwnId(); - bounceLobbyObject(&item,ownId) ; -} - -bool DistributedChatService::locked_initLobbyBouncableObject(const ChatLobbyId& lobby_id,RsChatLobbyBouncingObject& item) -{ - // get a pointer to the info for that chat lobby. - // - std::map::iterator it(_chat_lobbys.find(lobby_id)) ; - - if(it == _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Chatlobby for id " << std::hex << lobby_id << " has no record. This is a serious error!!" << std::dec << std::endl; -#endif - return false; - } - ChatLobbyEntry& lobby(it->second) ; - - // chat lobby stuff - // - do - { - item.msg_id = RSRandom::random_u64(); - } - while( lobby.msg_cache.find(item.msg_id) != lobby.msg_cache.end() ) ; - - RsIdentityDetails 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; - return false ; - } - - item.lobby_id = lobby_id ; - item.nick = details.mNickname ; - item.signature.TlvClear() ; - item.signature.keyId = lobby.gxs_id ; - - // now sign the object, if the lobby expects it - - uint32_t size = RsChatSerialiser(RsSerializationFlags::SIGNATURE) - .size(dynamic_cast(&item)); - RsTemporaryMemory memory(size) ; - - if( !RsChatSerialiser(RsSerializationFlags::SIGNATURE) - .serialise(dynamic_cast(&item),memory,&size) ) - { - std::cerr << "(EE) Cannot sign message item. " << std::endl; - return false ; - } - - uint32_t error_status ; - - if(!mGixs->signData(memory,size,lobby.gxs_id,item.signature,error_status)) - { - switch(error_status) - { - case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: std::cerr << "(EE) Cannot sign item: key not available for ID " << lobby.gxs_id << std::endl; - break ; - default: std::cerr << "(EE) Cannot sign item: unknown error" << std::endl; - break ; - } - return false ; - } - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " signature done." << std::endl; - - // check signature - if(!mGixs->validateData(memory,item.signed_serial_size(),item.signature,true,error_status)) - { - std::cerr << "(EE) Cannot check message item. " << std::endl; - return false ; - } - std::cerr << " signature checks!" << std::endl; - std::cerr << " Item dump:" << std::endl; - item.print(std::cerr,2) ; -#endif - - return true ; -} - -bool DistributedChatService::sendLobbyChat(const ChatLobbyId& lobby_id, const std::string& msg) -{ -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Sending chat lobby message to lobby " << std::hex << lobby_id << std::dec << std::endl; - std::cerr << "msg:" << std::endl; - std::cerr << msg << std::endl; -#endif - - RsChatLobbyMsgItem item ; - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - // chat msg stuff - // - item.chatFlags = RS_CHAT_FLAG_LOBBY | RS_CHAT_FLAG_PRIVATE; - item.sendTime = time(NULL); - item.recvTime = item.sendTime; - item.message = msg; - item.parent_msg_id = 0; - - // gives a random msg id, setup the nickname, and signs the item. - - if(! locked_initLobbyBouncableObject(lobby_id,item)) - return false; - } - - RsPeerId ownId = rsPeers->getOwnId(); - - bounceLobbyObject(&item, ownId) ; - - ChatMessage message; - message.chatflags = 0; - message.chat_id = ChatId(lobby_id); - message.msg = msg; - message.lobby_peer_gxs_id = item.signature.keyId; - message.recvTime = item.recvTime; - message.sendTime = item.sendTime; - message.incoming = false; - message.online = true; - RsServer::notify()->notifyChatMessage(message); - mHistMgr->addMessage(message); - - return true ; -} - -void DistributedChatService::handleConnectionChallenge(RsChatLobbyConnectChallengeItem *item) -{ - // Look into message cache of all lobbys to handle the challenge. - // -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "DistributedChatService::handleConnectionChallenge(): received connection challenge:" << std::endl; - std::cerr << " Challenge code = 0x" << std::hex << item->challenge_code << std::dec << std::endl; - std::cerr << " Peer Id = " << item->PeerId() << std::endl; -#endif - - rstime_t now = time(NULL) ; - ChatLobbyId lobby_id ; - const RsPeerId& ownId = rsPeers->getOwnId(); - - bool found = false ; - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - for(std::map::iterator it(_chat_lobbys.begin());it!=_chat_lobbys.end() && !found;++it) - for(std::map::const_iterator it2(it->second.msg_cache.begin());it2!=it->second.msg_cache.end() && !found;++it2) - if(it2->second + CONNECTION_CHALLENGE_MAX_MSG_AGE + 5 > now) // any msg not older than 5 seconds plus max challenge count is fine. - { - uint64_t code = makeConnexionChallengeCode(ownId,it->first,it2->first) ; -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Lobby_id = 0x" << std::hex << it->first << ", msg_id = 0x" << it2->first << ": code = 0x" << code << std::dec << std::endl ; -#endif - if(code == item->challenge_code) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Challenge accepted for lobby " << std::hex << it->first << ", for chat msg " << it2->first << std::dec << std::endl ; - std::cerr << " Sending connection request to peer " << item->PeerId() << std::endl; -#endif - - lobby_id = it->first ; - found = true ; - - // also add the peer to the list of participating friends - it->second.participating_friends.insert(item->PeerId()) ; - } - } - } - - if(found) // send invitation. As the peer already has the lobby, the invitation will most likely be accepted. - invitePeerToLobby(lobby_id, item->PeerId(),true) ; -#ifdef DEBUG_CHAT_LOBBIES - else - std::cerr << " Challenge denied: no existing cached msg has matching Id." << std::endl; -#endif -} - -void DistributedChatService::sendConnectionChallenge(ChatLobbyId lobby_id) -{ - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Sending connection challenge to friends for lobby 0x" << std::hex << lobby_id << std::dec << std::endl ; -#endif - - // look for a msg in cache. Any recent msg is fine. - - std::map::const_iterator it = _chat_lobbys.find(lobby_id) ; - - if(it == _chat_lobbys.end()) - { - std::cerr << "ERROR: sendConnectionChallenge(): could not find lobby 0x" << std::hex << lobby_id << std::dec << std::endl; - return ; - } - - rstime_t now = time(NULL) ; - ChatLobbyMsgId msg_id = 0 ; - - for(std::map::const_iterator it2(it->second.msg_cache.begin());it2!=it->second.msg_cache.end();++it2) - if(it2->second + CONNECTION_CHALLENGE_MAX_MSG_AGE > now) // any msg not older than 20 seconds is fine. - { - msg_id = it2->first ; -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Using msg id 0x" << std::hex << it2->first << std::dec << std::endl; -#endif - break ; - } - - if(msg_id == 0) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " No suitable message found in cache. Probably not enough activity !!" << std::endl; -#endif - return ; - } - - // Broadcast to all direct friends - - std::set ids ; - mServControl->getPeersConnected(mServType, ids); - - for(std::set::const_iterator it(ids.begin());it!=ids.end();++it) - { - RsChatLobbyConnectChallengeItem *item = new RsChatLobbyConnectChallengeItem ; - - uint64_t code = makeConnexionChallengeCode(*it,lobby_id,msg_id) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Sending collexion challenge code 0x" << std::hex << code << std::dec << " to peer " << *it << std::endl; -#endif - item->PeerId(*it) ; - item->challenge_code = code ; - - sendChatItem(item); - } -} - -uint64_t DistributedChatService::makeConnexionChallengeCode(const RsPeerId& peer_id,ChatLobbyId lobby_id,ChatLobbyMsgId msg_id) -{ - uint64_t result = 0 ; - - for(uint32_t i=0;i> 35 ; - result += result << 6 ; - result ^= peer_id.toByteArray()[i] * lobby_id ; - result += result << 26 ; - result ^= result >> 13 ; - } - return result ; -} - -void DistributedChatService::getChatLobbyList(std::list& clids) -{ - // fill up a dummy list for now. - - clids.clear() ; - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - for(std::map::const_iterator it(_chat_lobbys.begin());it!=_chat_lobbys.end();++it) - clids.push_back(it->first) ; -} - -bool DistributedChatService::getChatLobbyInfo(const ChatLobbyId& id,ChatLobbyInfo& info) -{ - // fill up a dummy list for now. - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - - std::map::const_iterator it = _chat_lobbys.find(id) ; - - if(it != _chat_lobbys.end()) - { - info = it->second ; - return true ; - } - else - return false ; -} - -void DistributedChatService::invitePeerToLobby(const ChatLobbyId& lobby_id, const RsPeerId& peer_id,bool connexion_challenge) -{ -#ifdef DEBUG_CHAT_LOBBIES - if(connexion_challenge) - std::cerr << "Sending connection challenge accept to peer " << peer_id << " for lobby "<< std::hex << lobby_id << std::dec << std::endl; - else - std::cerr << "Sending invitation to peer " << peer_id << " to lobby "<< std::hex << lobby_id << std::dec << std::endl; -#endif - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _chat_lobbys.find(lobby_id) ; - - if(it == _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " invitation send: canceled. Lobby " << lobby_id << " not found!" << std::endl; -#endif - return ; - } - - RsChatLobbyInviteItem *item = new RsChatLobbyInviteItem ; - - item->lobby_id = lobby_id ; - item->lobby_name = it->second.lobby_name ; - item->lobby_topic = it->second.lobby_topic ; - item->lobby_flags = connexion_challenge?RS_CHAT_LOBBY_FLAGS_CHALLENGE:(it->second.lobby_flags) ; - item->PeerId(peer_id) ; - - sendChatItem(item) ; - - //FOR BACKWARD COMPATIBILITY - {// to be removed (deprecated since May 2017) - RsChatLobbyInviteItem_Deprecated *item = new RsChatLobbyInviteItem_Deprecated ; - - item->lobby_id = lobby_id ; - item->lobby_name = it->second.lobby_name ; - item->lobby_topic = it->second.lobby_topic ; - item->lobby_flags = connexion_challenge?RS_CHAT_LOBBY_FLAGS_CHALLENGE:(it->second.lobby_flags) ; - item->PeerId(peer_id) ; - - sendChatItem(item) ; - } -} - -// to be removed (deprecated since May 2017) -void DistributedChatService::handleRecvLobbyInvite_Deprecated(RsChatLobbyInviteItem_Deprecated *item) -{ -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Received deprecated invite to lobby from " << item->PeerId() << " to lobby " << std::hex << item->lobby_id << std::dec << ", named " << item->lobby_name << item->lobby_topic << std::endl; -#endif - RsChatLobbyInviteItem newItem ; - - newItem.lobby_id = item->lobby_id ; - newItem.lobby_name = item->lobby_name ; - newItem.lobby_topic = item->lobby_topic ; - newItem.lobby_flags = item->lobby_flags ; - newItem.PeerId( item->PeerId() ); - - handleRecvLobbyInvite(&newItem); // The item is not deleted inside this function. -} - -void DistributedChatService::handleRecvLobbyInvite(RsChatLobbyInviteItem *item) -{ -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Received invite to lobby from " << item->PeerId() << " to lobby " << std::hex << item->lobby_id << std::dec << ", named " << item->lobby_name << item->lobby_topic << std::endl; -#endif - - // 1 - store invite in a cache - // - // 1.1 - if the lobby is already setup, add the peer to the communicating peers. - // - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it = _chat_lobbys.find(item->lobby_id) ; - - if(it != _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Lobby already exists. " << std::endl; - std::cerr << " privacy levels: " << item->lobby_flags << " vs. " << it->second.lobby_flags ; -#endif - - if ((!IS_CONNEXION_CHALLENGE(item->lobby_flags)) && EXTRACT_PRIVACY_FLAGS(item->lobby_flags) != EXTRACT_PRIVACY_FLAGS(it->second.lobby_flags)) - { - std::cerr << " : Don't match. Cancelling." << std::endl; - return ; - } -#ifdef DEBUG_CHAT_LOBBIES - else - std::cerr << " : Match!" << std::endl; - - std::cerr << " Adding new friend " << item->PeerId() << " to lobby." << std::endl; -#endif - - // to be removed (deprecated since May 2017) - { //Update Topics if have received deprecated before (withou topic) - if(it->second.lobby_topic.empty() && !item->lobby_topic.empty()) - it->second.lobby_topic = item->lobby_topic; - } - - it->second.participating_friends.insert(item->PeerId()) ; - return ; - } - - // to be removed (deprecated since May 2017) - {//check if invitation is already received by deprecated version - std::map::const_iterator it(_lobby_invites_queue.find( item->lobby_id)) ; - if(it != _lobby_invites_queue.end()) - return ; - } - // Don't record the invitation if it's a challenge response item or a lobby we don't have. - // - if(IS_CONNEXION_CHALLENGE(item->lobby_flags)) - return ; - - // no, then create a new invitation entry in the cache. - - ChatLobbyInvite invite ; - invite.lobby_id = item->lobby_id ; - invite.peer_id = item->PeerId() ; - invite.lobby_name = item->lobby_name ; - invite.lobby_topic = item->lobby_topic ; - invite.lobby_flags = item->lobby_flags ; - - _lobby_invites_queue[item->lobby_id] = invite ; - } - // 2 - notify the gui to ask the user. - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_INVITATION, NOTIFY_TYPE_ADD); -} - -void DistributedChatService::getPendingChatLobbyInvites(std::list& invites) -{ - invites.clear() ; - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - for(std::map::const_iterator it(_lobby_invites_queue.begin());it!=_lobby_invites_queue.end();++it) - invites.push_back(it->second) ; -} - - -bool DistributedChatService::acceptLobbyInvite(const ChatLobbyId& lobby_id,const RsGxsId& identity) -{ - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Accepting chat lobby "<< lobby_id << std::endl; -#endif - - std::map::iterator it = _lobby_invites_queue.find(lobby_id) ; - - if(it == _lobby_invites_queue.end()) - { - std::cerr << " (EE) lobby invite not in cache!!" << std::endl; - return false; - } - - //std::map::const_iterator vid = _visible_lobbies.find(lobby_id) ; - - //When invited to new Lobby, it is not visible. - //if(_visible_lobbies.end() == vid) - //{ - // std::cerr << " (EE) Cannot subscribe a non visible chat lobby!!" << std::endl; - // return false ; - //} - - RsIdentityDetails det ; - if( (!rsIdentity->getIdDetails(identity,det)) || !(det.mFlags & RS_IDENTITY_FLAGS_IS_OWN_ID)) - { - std::cerr << " (EE) Cannot subscribe with identity " << identity << " because it is not ours! Something's wrong here." << std::endl; - return false ; - } - - if( (it->second.lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED ) && !(det.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)) - { - std::cerr << " (EE) Cannot subscribe with identity " << identity << " because it is unsigned and the lobby requires signed ids only." << std::endl; - return false ; - } - - if(_chat_lobbys.find(lobby_id) != _chat_lobbys.end()) - { - std::cerr << " (II) Lobby already exists. Weird." << std::endl; - return true ; - } - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Creating new Lobby entry." << std::endl; -#endif - rstime_t now = time(NULL) ; - - ChatLobbyEntry entry ; - entry.participating_friends.insert(it->second.peer_id) ; - entry.lobby_flags = it->second.lobby_flags ; - entry.gxs_id = identity ; - entry.lobby_id = lobby_id ; - entry.lobby_name = it->second.lobby_name ; - entry.lobby_topic = it->second.lobby_topic ; - entry.virtual_peer_id = makeVirtualPeerId(lobby_id) ; - entry.connexion_challenge_count = 0 ; - entry.last_activity = now ; - entry.last_connexion_challenge_time = now ; - entry.joined_lobby_packet_sent = false; - entry.last_keep_alive_packet_time = now ; - - _chat_lobbys[lobby_id] = entry ; - - _lobby_invites_queue.erase(it) ; // remove the invite from cache. - - // we should also send a message to the lobby to tell we're here. - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Pushing new msg item to incoming msgs." << std::endl; -#endif - RsChatLobbyMsgItem *item = new RsChatLobbyMsgItem; - item->lobby_id = entry.lobby_id ; - item->msg_id = 0 ; - item->parent_msg_id = 0 ; - item->nick = "Chat room management" ; - item->message = std::string("Welcome to chat lobby") ; - item->PeerId(entry.virtual_peer_id) ; - item->chatFlags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_LOBBY ; - - locked_storeIncomingMsg(item) ; - } -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Notifying of new recvd msg." << std::endl ; -#endif - - RsServer::notify()->notifyListChange(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD); - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD); - - // send AKN item - sendLobbyStatusNewPeer(lobby_id) ; - - return true ; -} - -ChatLobbyVirtualPeerId DistributedChatService::makeVirtualPeerId(ChatLobbyId lobby_id) -{ - uint8_t bytes[RsPeerId::SIZE_IN_BYTES] ; - memset(bytes,0,RsPeerId::SIZE_IN_BYTES) ; - memcpy(bytes,&lobby_id,sizeof(lobby_id)) ; - - return ChatLobbyVirtualPeerId(bytes) ; -} - - -void DistributedChatService::denyLobbyInvite(const ChatLobbyId& lobby_id) -{ - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Denying chat lobby invite to "<< lobby_id << std::endl; -#endif - std::map::iterator it = _lobby_invites_queue.find(lobby_id) ; - - if(it == _lobby_invites_queue.end()) - { - std::cerr << " (EE) lobby invite not in cache!!" << std::endl; - return ; - } - - _lobby_invites_queue.erase(it) ; -} - -bool DistributedChatService::joinVisibleChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& gxs_id) -{ - RsIdentityDetails det ; - if( (!rsIdentity->getIdDetails(gxs_id,det)) || !(det.mFlags & RS_IDENTITY_FLAGS_IS_OWN_ID)) - { - std::cerr << " (EE) Cannot subscribe with identity " << gxs_id << " because it is not ours! Something's wrong here." << std::endl; - return false ; - } - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Joining public chat lobby " << std::hex << lobby_id << std::dec << std::endl; -#endif - std::list invited_friends ; - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - // create a unique id. - // - std::map::const_iterator it(_visible_lobbies.find(lobby_id)) ; - - if(it == _visible_lobbies.end()) - { - std::cerr << " lobby is not a known public chat lobby. Sorry!" << std::endl; - return false ; - } - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " lobby found. Initiating join sequence..." << std::endl; -#endif - - if(_chat_lobbys.find(lobby_id) != _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " lobby already in participating list. Returning!" << std::endl; -#endif - return true ; - } - - if( (it->second.lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED ) && !(det.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)) - { - std::cerr << " (EE) Cannot subscribe with identity " << gxs_id << " because it is unsigned and the lobby requires signed ids only." << std::endl; - return false ; - } - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Creating new lobby entry." << std::endl; -#endif - rstime_t now = time(NULL) ; - - ChatLobbyEntry entry ; - - entry.lobby_flags = it->second.lobby_flags ;//RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC ; - entry.participating_friends.clear() ; - entry.gxs_id = gxs_id ; - entry.lobby_id = lobby_id ; - entry.lobby_name = it->second.lobby_name ; - entry.lobby_topic = it->second.lobby_topic ; - entry.virtual_peer_id = makeVirtualPeerId(lobby_id) ; - entry.connexion_challenge_count = 0 ; - entry.last_activity = now ; - entry.last_connexion_challenge_time = now ; - entry.joined_lobby_packet_sent = false; - entry.last_keep_alive_packet_time = now ; - - for(std::set::const_iterator it2(it->second.participating_friends.begin());it2!=it->second.participating_friends.end();++it2) - { - invited_friends.push_back(*it2) ; - entry.participating_friends.insert(*it2) ; - } - _chat_lobbys[lobby_id] = entry ; - } - - setLobbyAutoSubscribe(lobby_id,true); - - triggerConfigSave(); // so that we save the subscribed lobbies - - for(std::list::const_iterator it(invited_friends.begin());it!=invited_friends.end();++it) - invitePeerToLobby(lobby_id,*it) ; - - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD) ; - sendLobbyStatusNewPeer(lobby_id) ; - - return true ; -} - -ChatLobbyId DistributedChatService::createChatLobby(const std::string& lobby_name,const RsGxsId& lobby_identity,const std::string& lobby_topic,const std::set& invited_friends,ChatLobbyFlags lobby_flags) -{ -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Creating a new Chat lobby !!" << std::endl; -#endif - ChatLobbyId lobby_id ; - { - if (!rsIdentity->isOwnId(lobby_identity)) - { - RsErr() << __PRETTY_FUNCTION__ << " lobby_identity RsGxsId id must be own" << std::endl; - return 0; - } - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - // create a unique id. - // - do { lobby_id = RSRandom::random_u64() ; } while(_chat_lobbys.find(lobby_id) != _chat_lobbys.end()) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " New (unique) ID: " << std::hex << lobby_id << std::dec << std::endl; -#endif - rstime_t now = time(NULL) ; - - ChatLobbyEntry entry ; - entry.lobby_flags = lobby_flags ; - entry.participating_friends.clear() ; - entry.gxs_id = lobby_identity ; // to be changed. For debug only!! - entry.lobby_id = lobby_id ; - entry.lobby_name = lobby_name ; - entry.lobby_topic = lobby_topic ; - entry.virtual_peer_id = makeVirtualPeerId(lobby_id) ; - entry.connexion_challenge_count = 0 ; - entry.last_activity = now ; - entry.last_connexion_challenge_time = now ; - entry.joined_lobby_packet_sent = false; - entry.last_keep_alive_packet_time = now ; - - _chat_lobbys[lobby_id] = entry ; - } - - for(std::set::const_iterator it(invited_friends.begin());it!=invited_friends.end();++it) - invitePeerToLobby(lobby_id,*it) ; - - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD) ; - - triggerConfigSave(); - - return lobby_id ; -} - -void DistributedChatService::handleFriendUnsubscribeLobby(RsChatLobbyUnsubscribeItem *item) -{ - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it = _chat_lobbys.find(item->lobby_id) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Received unsubscribed to lobby " << std::hex << item->lobby_id << std::dec << ", from friend " << item->PeerId() << std::endl; -#endif - - if(it == _chat_lobbys.end()) - { - std::cerr << "Chat lobby " << std::hex << item->lobby_id << std::dec << " does not exist ! Can't unsubscribe friend!" << std::endl; - return ; - } - - for(std::set::iterator it2(it->second.participating_friends.begin());it2!=it->second.participating_friends.end();++it2) - if(*it2 == item->PeerId()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " removing peer id " << item->PeerId() << " from participant list of lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - it->second.previously_known_peers.insert(*it2) ; - it->second.participating_friends.erase(it2) ; - break ; - } - } - - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_MOD) ; -} - -void DistributedChatService::unsubscribeChatLobby(const ChatLobbyId& id) -{ - // send AKN item - sendLobbyStatusPeerLeaving(id) ; - setLobbyAutoSubscribe(id, false); - - { - RS_STACK_MUTEX(mDistributedChatMtx); - - std::map::iterator it = _chat_lobbys.find(id) ; - - if(it == _chat_lobbys.end()) - { - std::cerr << "Chat lobby " << id << " does not exist ! Can't unsubscribe!" << std::endl; - return ; - } - - // send a lobby leaving packet to all friends - - for(std::set::const_iterator it2(it->second.participating_friends.begin());it2!=it->second.participating_friends.end();++it2) - { - RsChatLobbyUnsubscribeItem *item = new RsChatLobbyUnsubscribeItem ; - - item->lobby_id = id ; - item->PeerId(*it2) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Sending unsubscribe item to friend " << *it2 << std::endl; -#endif - - sendChatItem(item) ; - } - - // remove history - - //mHistoryMgr->clear(it->second.virtual_peer_id); - - // remove lobby information - - _chat_lobbys.erase(it) ; - } - - triggerConfigSave(); // so that we save the subscribed lobbies - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_DEL) ; - - // done! -} -bool DistributedChatService::setDefaultIdentityForChatLobby(const RsGxsId& nick) -{ - if (nick.isNull()) - { - std::cerr << "Ignore empty nickname for chat lobby " << std::endl; - return false; - } - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - _default_identity = nick; - } - - triggerConfigSave() ; - return true ; -} - -void DistributedChatService::getDefaultIdentityForChatLobby(RsGxsId& nick) -{ - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - nick = locked_getDefaultIdentity() ; -} - -RsGxsId DistributedChatService::locked_getDefaultIdentity() -{ - if(_default_identity.isNull() && rsIdentity!=NULL) - { - std::list own_ids ; - rsIdentity->getOwnIds(own_ids) ; - - if(!own_ids.empty()) - { - _default_identity = own_ids.front() ; - triggerConfigSave(); - } - } - return _default_identity ; -} - -bool DistributedChatService::getIdentityForChatLobby(const ChatLobbyId& lobby_id,RsGxsId& nick) -{ - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "getting nickname for chat lobby "<< std::hex << lobby_id << std::dec << std::endl; -#endif - std::map::iterator it = _chat_lobbys.find(lobby_id) ; - - if(it == _chat_lobbys.end()) - { - std::cerr << " (EE) lobby does not exist!!" << std::endl; - return false ; - } - - nick = it->second.gxs_id ; - return true ; -} - -bool DistributedChatService::setIdentityForChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& nick) -{ - if (nick.isNull()) - { - std::cerr << "(EE) Ignore empty nickname for chat lobby " << nick << std::endl; - return false; - } - - // first check for change and send status peer changed nick name - bool changed = false; - std::map::iterator it; - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Changing nickname for chat lobby " << std::hex << lobby_id << std::dec << " to " << nick << std::endl; -#endif - it = _chat_lobbys.find(lobby_id) ; - - if(it == _chat_lobbys.end()) - { - std::cerr << " (EE) lobby does not exist!!" << std::endl; - return false; - } - - if (!it->second.gxs_id.isNull() && it->second.gxs_id != nick) - changed = true; - } - - if (changed) - { - // Inform other peers of change the Nickname - { - RsIdentityDetails det1,det2 ; - - // Only send a nickname change event if the two Identities are not anonymous - - if(rsIdentity->getIdDetails(nick,det1) && rsIdentity->getIdDetails(it->second.gxs_id,det2) && (det1.mFlags & det2.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)) - sendLobbyStatusPeerChangedNickname(lobby_id, nick.toStdString()) ; - } - - // set new nick name - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - it = _chat_lobbys.find(lobby_id) ; - - if(it == _chat_lobbys.end()) - { - std::cerr << " (EE) lobby does not exist!!" << std::endl; - return false; - } - - it->second.gxs_id = nick ; - } - - return true ; -} - -void DistributedChatService::setLobbyAutoSubscribe(const ChatLobbyId& lobby_id, const bool autoSubscribe) -{ - - if(autoSubscribe) - { - { - RS_STACK_MUTEX(mDistributedChatMtx); - _known_lobbies_flags[lobby_id] |= RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE; - } - 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) ; - triggerConfigSave(); -} - -bool DistributedChatService::getLobbyAutoSubscribe(const ChatLobbyId& lobby_id) -{ - if(_known_lobbies_flags.find(lobby_id) == _known_lobbies_flags.end()) // keep safe about default values form std::map - return false; - - return _known_lobbies_flags[lobby_id] & RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE ; -} - -void DistributedChatService::cleanLobbyCaches() -{ -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Cleaning chat lobby caches." << std::endl; -#endif - - std::list keep_alive_lobby_ids ; - std::list changed_lobbies ; - std::list send_challenge_lobbies ; - std::list joined_lobby_ids ; - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - rstime_t now = time(NULL) ; - - for(std::map::iterator it = _chat_lobbys.begin();it!=_chat_lobbys.end();++it) - { - // 1 - remove old messages - // - for(std::map::iterator it2(it->second.msg_cache.begin());it2!=it->second.msg_cache.end();) - if(it2->second + MAX_KEEP_MSG_RECORD < now) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " removing old msg 0x" << std::hex << it2->first << ", time=" << std::dec << now - it2->second << " secs ago" << std::endl; -#endif - - std::map::iterator tmp(it2) ; - ++tmp ; - it->second.msg_cache.erase(it2) ; - it2 = tmp ; - } - else - ++it2 ; - - bool changed = false ; - - // 2 - remove inactive nicknames - // - for(std::map::iterator it2(it->second.gxs_ids.begin());it2!=it->second.gxs_ids.end();) - if(it2->second + MAX_KEEP_INACTIVE_NICKNAME < now) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " removing inactive nickname 0x" << std::hex << it2->first << ", time=" << std::dec << now - it2->second << " secs ago" << std::endl; -#endif - - std::map::iterator tmp(it2) ; - ++tmp ; - it->second.gxs_ids.erase(it2) ; - it2 = tmp ; - changed = true ; - } - else - ++it2 ; - - if(changed) - changed_lobbies.push_back(it->first) ; - - // 3 - send a joined_lobby packet if a participating friend is connected, we do that only once - // - if (!it->second.joined_lobby_packet_sent) - { - bool oneParticipatingFriendIsConnected = false; - for(std::set::const_iterator fit(it->second.participating_friends.begin());fit!=it->second.participating_friends.end();++fit) - { - if(mServControl->isPeerConnected(mServType, *fit)) - { - oneParticipatingFriendIsConnected = true; - break; - } - } - if (oneParticipatingFriendIsConnected) - { - joined_lobby_ids.push_back(it->first) ; - it->second.joined_lobby_packet_sent = true; - } - } - - // 4 - send lobby keep-alive packet - // - if(it->second.last_keep_alive_packet_time + MAX_DELAY_BETWEEN_LOBBY_KEEP_ALIVE < now) - { - keep_alive_lobby_ids.push_back(it->first) ; - it->second.last_keep_alive_packet_time = now ; - } - - // 5 - look at lobby activity and possibly send connection challenge - // - if(++it->second.connexion_challenge_count > CONNECTION_CHALLENGE_MAX_COUNT && now > it->second.last_connexion_challenge_time + CONNECTION_CHALLENGE_MIN_DELAY) - { - it->second.connexion_challenge_count = 0 ; - it->second.last_connexion_challenge_time = now ; - send_challenge_lobbies.push_back(it->first); - } - } - - // 2 - clean deprecated public chat lobby records - // - - for(std::map::iterator it(_visible_lobbies.begin());it!=_visible_lobbies.end();) - { - if(it->second.last_report_time + MAX_KEEP_PUBLIC_LOBBY_RECORD < now && _chat_lobbys.find(it->first)==_chat_lobbys.end()) // this lobby record is too late. - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " removing old public lobby record 0x" << std::hex << it->first << ", time=" << std::dec << now - it->second.last_report_time << " secs ago" << std::endl; -#endif - std::map::iterator tmp(it) ; - ++tmp ; - _visible_lobbies.erase(it) ; - it = tmp ; - } - else - ++it ; - } - } - - // send keep alive - for(std::list::const_iterator it(keep_alive_lobby_ids.begin());it!=keep_alive_lobby_ids.end();++it) - sendLobbyStatusKeepAlive(*it) ; - - // update the gui - for(std::list::const_iterator it(changed_lobbies.begin());it!=changed_lobbies.end();++it) - RsServer::notify()->notifyChatLobbyEvent(*it,RS_CHAT_LOBBY_EVENT_KEEP_ALIVE,RsGxsId(),"") ; - - // send peer joined - for(std::list::const_iterator it(joined_lobby_ids.begin());it!=joined_lobby_ids.end();++it) - sendLobbyStatusNewPeer(*it) ; - - // send connection challenges - for(std::list::const_iterator it(send_challenge_lobbies.begin());it!=send_challenge_lobbies.end();++it) - sendConnectionChallenge(*it) ; -} - -void DistributedChatService::addToSaveList(std::list& list) const -{ - /* Save Lobby Auto Subscribe */ - for(std::map::const_iterator it=_known_lobbies_flags.begin(); it!=_known_lobbies_flags.end(); ++it) - { - RsChatLobbyConfigItem *clci = new RsChatLobbyConfigItem ; - clci->lobby_Id=it->first; - clci->flags=it->second.toUInt32(); - - 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 */ - { - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - kv.key = "DEFAULT_IDENTITY"; - kv.value = _default_identity.toStdString(); - vitem->tlvkvs.pairs.push_back(kv); - list.push_back(vitem); - } - - /* Save Default Nick Name by Lobby*/ - for(std::map::const_iterator it=_lobby_default_identity.begin(); it!=_lobby_default_identity.end(); ++it) - { - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - ChatLobbyId cli = it->first; - RsGxsId gxsId = it->second; - - std::stringstream stream; - stream << std::setfill ('0') << std::setw(sizeof(ChatLobbyId)*2) - << std::hex << cli; - std::string strCli( stream.str() ); - - RsTlvKeyValue kv; - kv.key = "LOBBY_DEFAULT_IDENTITY:"+strCli; - kv.value = gxsId.toStdString(); - vitem->tlvkvs.pairs.push_back(kv); - list.push_back(vitem); - } - -} - -bool DistributedChatService::processLoadListItem(const RsItem *item) -{ - const RsConfigKeyValueSet *vitem = NULL; - const std::string strldID = "LOBBY_DEFAULT_IDENTITY:"; - - if(NULL != (vitem = dynamic_cast(item))) - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if( kit->key == "DEFAULT_IDENTITY" ) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Loaded config default nick name for distributed chat: " << kit->value << std::endl ; -#endif - if (!kit->value.empty()) - { - _default_identity = RsGxsId(kit->value) ; - if(_default_identity.isNull()) - std::cerr << "ERROR: default identity is malformed." << std::endl; - } - - return true; - } - - if( kit->key.compare(0, strldID.length(), strldID) == 0) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Loaded config lobby default nick name: " << kit->key << " " << kit->value << std::endl ; -#endif - - std::string strCli = kit->key.substr(strldID.length()); - std::stringstream stream; - stream << std::hex << strCli; - ChatLobbyId cli = 0; - stream >> cli; - - if (!kit->value.empty() && (cli != 0)) - { - RsGxsId gxsId(kit->value); - if (gxsId.isNull()) - std::cerr << "ERROR: lobby default identity is malformed." << std::endl; - else - _lobby_default_identity[cli] = gxsId ; - } - - return true; - } - } - - const RsChatLobbyConfigItem *clci = NULL ; - - if(NULL != (clci = dynamic_cast(item))) - { - _known_lobbies_flags[clci->lobby_Id] = ChatLobbyFlags(clci->flags) ; - return true ; - } - - if(_default_identity.isNull() && rsIdentity!=NULL) - { - std::list own_ids ; - rsIdentity->getOwnIds(own_ids) ; - - if(!own_ids.empty()) - _default_identity = own_ids.front() ; - } - - const RsSubscribedChatLobbyConfigItem *scli = dynamic_cast(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.joined_lobby_packet_sent = false ; - 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 ; -} - diff --git a/libretroshare/src/chat/distributedchat.h b/libretroshare/src/chat/distributedchat.h deleted file mode 100644 index 96369511d..000000000 --- a/libretroshare/src/chat/distributedchat.h +++ /dev/null @@ -1,168 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: distributedchat.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -typedef RsPeerId ChatLobbyVirtualPeerId ; - -struct RsItem; -class p3HistoryMgr ; -class p3IdService ; -class p3ServiceControl; -class RsChatLobbyItem ; -class RsChatLobbyListRequestItem ; -class RsChatLobbyListItem ; -class RsChatLobbyEventItem ; -class RsChatLobbyBouncingObject ; -class RsChatLobbyInviteItem_Deprecated ; // to be removed (deprecated since May 2017) -class RsChatLobbyInviteItem ; -class RsChatLobbyMsgItem ; -class RsChatLobbyConnectChallengeItem ; -class RsChatLobbyUnsubscribeItem ; - -class RsChatItem ; -class RsChatMsgItem ; -class RsGixs ; - -class DistributedChatService -{ - public: - DistributedChatService(uint32_t service_type,p3ServiceControl *sc,p3HistoryMgr *hm,RsGixs *is) ; - - virtual ~DistributedChatService() {} - - void flush() ; - - // Interface part to communicate with - // - bool getVirtualPeerId(const ChatLobbyId& lobby_id, RsPeerId& virtual_peer_id) ; - void getChatLobbyList(std::list& clids) ; - bool getChatLobbyInfo(const ChatLobbyId& id,ChatLobbyInfo& clinfo) ; - bool acceptLobbyInvite(const ChatLobbyId& id,const RsGxsId& identity) ; - void denyLobbyInvite(const ChatLobbyId& id) ; - void getPendingChatLobbyInvites(std::list& invites) ; - void invitePeerToLobby(const ChatLobbyId&, const RsPeerId& peer_id,bool connexion_challenge = false) ; - void unsubscribeChatLobby(const ChatLobbyId& lobby_id) ; - bool setIdentityForChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& nick) ; - bool getIdentityForChatLobby(const ChatLobbyId& lobby_id,RsGxsId& nick) ; - bool setDefaultIdentityForChatLobby(const RsGxsId& nick) ; - void getDefaultIdentityForChatLobby(RsGxsId& nick) ; - void setLobbyAutoSubscribe(const ChatLobbyId& lobby_id, const bool autoSubscribe); - bool getLobbyAutoSubscribe(const ChatLobbyId& lobby_id); - 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& invited_friends,ChatLobbyFlags flags) ; - - void getListOfNearbyChatLobbies(std::vector& public_lobbies) ; - bool joinVisibleChatLobby(const ChatLobbyId& id, const RsGxsId &gxs_id) ; - - protected: - bool handleRecvItem(RsChatItem *) ; - - virtual void sendChatItem(RsChatItem *) =0 ; - virtual void locked_storeIncomingMsg(RsChatMsgItem *) =0 ; - virtual void triggerConfigSave() =0; - - void addToSaveList(std::list& list) const ; - bool processLoadListItem(const RsItem *item) ; - - void checkSizeAndSendLobbyMessage(RsChatItem *) ; - - bool sendLobbyChat(const ChatLobbyId &lobby_id, const std::string&) ; - bool handleRecvChatLobbyMsgItem(RsChatMsgItem *item) ; - - bool checkSignature(RsChatLobbyBouncingObject *obj,const RsPeerId& peer_id) ; - - private: - /// make some statistics about time shifts, to prevent various issues. - void addTimeShiftStatistics(int shift) ; - - void handleRecvChatLobbyListRequest(RsChatLobbyListRequestItem *item) ; - void handleRecvChatLobbyList(RsChatLobbyListItem *item) ; - void handleRecvChatLobbyEventItem(RsChatLobbyEventItem *item) ; - - - /// Checks that the lobby object is not flooding a lobby. - bool locked_bouncingObjectCheck(RsChatLobbyBouncingObject *obj,const RsPeerId& peer_id,uint32_t lobby_count) ; - - /// receive and handle chat lobby item - bool recvLobbyChat(RsChatLobbyMsgItem*,const RsPeerId& src_peer_id) ; - void handleRecvLobbyInvite_Deprecated(RsChatLobbyInviteItem_Deprecated*) ; // to be removed (deprecated since May 2017) - void handleRecvLobbyInvite(RsChatLobbyInviteItem*) ; - void checkAndRedirectMsgToLobby(RsChatMsgItem*) ; - void handleConnectionChallenge(RsChatLobbyConnectChallengeItem *item) ; - void sendConnectionChallenge(ChatLobbyId id) ; - void handleFriendUnsubscribeLobby(RsChatLobbyUnsubscribeItem*) ; - void cleanLobbyCaches() ; - bool bounceLobbyObject(RsChatLobbyBouncingObject *obj, const RsPeerId& peer_id) ; - - void sendLobbyStatusItem(const ChatLobbyId&, int type, const std::string& status_string) ; - void sendLobbyStatusPeerChangedNickname(const ChatLobbyId& lobby_id, const std::string& newnick) ; - - void sendLobbyStatusNewPeer(const ChatLobbyId& lobby_id) ; - void sendLobbyStatusKeepAlive(const ChatLobbyId&) ; - - bool locked_initLobbyBouncableObject(const ChatLobbyId& id,RsChatLobbyBouncingObject&) ; - void locked_printDebugInfo() const ; - RsGxsId locked_getDefaultIdentity(); - - static ChatLobbyVirtualPeerId makeVirtualPeerId(ChatLobbyId) ; - static uint64_t makeConnexionChallengeCode(const RsPeerId& peer_id,ChatLobbyId lobby_id,ChatLobbyMsgId msg_id) ; - - class ChatLobbyEntry: public ChatLobbyInfo - { - public: - std::map msg_cache ; - RsPeerId virtual_peer_id ; - int connexion_challenge_count ; - rstime_t last_connexion_challenge_time ; - bool joined_lobby_packet_sent; - rstime_t last_keep_alive_packet_time ; - std::set previously_known_peers ; - }; - - std::map _chat_lobbys ; - std::map _lobby_invites_queue ; - std::map _visible_lobbies ; - std::map _known_lobbies_flags ; // flags for all lobbies, including the ones that are not known. So we can't - std::map > _pendingPartialLobbyMessages ; // store them in _chat_lobbies (subscribed lobbies) nor _visible_lobbies. - // Known flags: - // RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE - - float _time_shift_average ; - rstime_t last_lobby_challenge_time ; // prevents bruteforce attack - rstime_t last_visible_lobby_info_request_time ; // allows to ask for updates - bool _should_reset_lobby_counts ; - RsGxsId _default_identity; - std::map _lobby_default_identity; - - uint32_t mServType ; - RsMutex mDistributedChatMtx ; - - p3ServiceControl *mServControl; - p3HistoryMgr *mHistMgr; - RsGixs *mGixs ; -}; diff --git a/libretroshare/src/chat/p3chatservice.cc b/libretroshare/src/chat/p3chatservice.cc deleted file mode 100644 index 3fbbdaf75..000000000 --- a/libretroshare/src/chat/p3chatservice.cc +++ /dev/null @@ -1,1485 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: chatservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include -#include - -#include "util/rsdir.h" -#include "util/radix64.h" -#include "crypto/rsaes.h" -#include "util/rsrandom.h" -#include "util/rsstring.h" -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsstatus.h" -#include "pqi/pqibin.h" -#include "pqi/pqistore.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3historymgr.h" -#include "rsserver/p3face.h" -#include "services/p3idservice.h" -#include "gxstrans/p3gxstrans.h" - -#include "chat/p3chatservice.h" -#include "rsitems/rsconfigitems.h" - -/**** - * #define CHAT_DEBUG 1 - ****/ - -static const uint32_t MAX_MESSAGE_SECURITY_SIZE = 31000 ; // Max message size to forward other friends -static const uint32_t MAX_AVATAR_JPEG_SIZE = 32767; // Maximum size in bytes for an avatar. Too large packets - // don't transfer correctly and can kill the system. - // Images are 96x96, which makes approx. 27000 bytes uncompressed. - -p3ChatService::p3ChatService( p3ServiceControl *sc, p3IdService *pids, - p3LinkMgr *lm, p3HistoryMgr *historyMgr, - p3GxsTrans& gxsTransService ) : - DistributedChatService(getServiceInfo().mServiceType, sc, historyMgr,pids), - mChatMtx("p3ChatService"), mServiceCtrl(sc), mLinkMgr(lm), - mHistoryMgr(historyMgr), _own_avatar(NULL), - _serializer(new RsChatSerialiser()), - mDGMutex("p3ChatService distant id - gxs id map mutex"), - mGxsTransport(gxsTransService) -{ - addSerialType(_serializer); - mGxsTransport.registerGxsTransClient( GxsTransSubServices::P3_CHAT_SERVICE, - this ); -} - -RsServiceInfo p3ChatService::getServiceInfo() -{ return RsServiceInfo(RS_SERVICE_TYPE_CHAT, "chat", 1, 0, 1, 0); } - -int p3ChatService::tick() -{ - if(receivedItems()) receiveChatQueue(); - - DistributedChatService::flush(); - - return 0; -} - -/***************** Chat Stuff **********************/ - -void p3ChatService::sendPublicChat(const std::string &msg) -{ - /* go through all the peers */ - - std::set ids; - std::set::iterator it; - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, ids); - - /* add in own id -> so get reflection */ - RsPeerId ownId = mServiceCtrl->getOwnId(); - ids.insert(ownId); - -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sendChat()"; - std::cerr << std::endl; -#endif - - for(it = ids.begin(); it != ids.end(); ++it) - { - RsChatMsgItem *ci = new RsChatMsgItem(); - - ci->PeerId(*it); - ci->chatFlags = RS_CHAT_FLAG_PUBLIC; - ci->sendTime = time(NULL); - ci->recvTime = ci->sendTime; - ci->message = msg; - -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sendChat() Item:"; - std::cerr << std::endl; - ci->print(std::cerr); - std::cerr << std::endl; -#endif - - if (*it == ownId) - { - //mHistoryMgr->addMessage(false, RsPeerId(), ownId, ci); - ChatMessage message; - initChatMessage(ci, message); - message.incoming = false; - message.online = true; - RsServer::notify()->notifyChatMessage(message); - mHistoryMgr->addMessage(message); - } - else - checkSizeAndSendMessage(ci); - } -} - - -class p3ChatService::AvatarInfo -{ - public: - AvatarInfo() - { - _image_size = 0 ; - _image_data = NULL ; - _peer_is_new = false ; // true when the peer has a new avatar - _own_is_new = false ; // true when I myself a new avatar to send to this peer. - } - - ~AvatarInfo() - { - free( _image_data ); - _image_data = NULL ; - _image_size = 0 ; - } - - AvatarInfo(const AvatarInfo& ai) - { - init(ai._image_data,ai._image_size) ; - } - - void init(const unsigned char *jpeg_data,int size) - { - if(size == 0) - { - _image_size = 0; - _image_data = nullptr; - } - else - { - _image_size = size ; - _image_data = (unsigned char*)rs_malloc(size) ; - memcpy(_image_data,jpeg_data,size) ; - } - } - AvatarInfo(const unsigned char *jpeg_data,int size) - { - init(jpeg_data,size) ; - } - - void toUnsignedChar(unsigned char *& data,uint32_t& size) const - { - if(_image_size == 0) - { - size = 0 ; - data = NULL ; - return ; - } - data = (unsigned char *)rs_malloc(_image_size) ; - size = _image_size ; - memcpy(data,_image_data,size*sizeof(unsigned char)) ; - } - - uint32_t _image_size ; - unsigned char *_image_data ; - int _peer_is_new ; // true when the peer has a new avatar - int _own_is_new ; // true when I myself a new avatar to send to this peer. -}; - -void p3ChatService::sendGroupChatStatusString(const std::string& status_string) -{ - std::set ids; - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, ids); - -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sendChat(): sending group chat status string: " << status_string << std::endl ; - std::cerr << std::endl; -#endif - - for(std::set::iterator it = ids.begin(); it != ids.end(); ++it) - { - RsChatStatusItem *cs = new RsChatStatusItem ; - - cs->status_string = status_string ; - cs->flags = RS_CHAT_FLAG_PUBLIC ; - - cs->PeerId(*it); - - sendItem(cs); - } -} - -void p3ChatService::sendStatusString( const ChatId& id, - const std::string& status_string ) -{ - if(id.isLobbyId()) sendLobbyStatusString(id.toLobbyId(),status_string); - else if(id.isBroadcast()) sendGroupChatStatusString(status_string); - else if(id.isPeerId() || id.isDistantChatId()) - { - RsPeerId vpid; - if(id.isDistantChatId()) vpid = RsPeerId(id.toDistantChatId()); - else vpid = id.toPeerId(); - - if(isOnline(vpid)) - { - RsChatStatusItem *cs = new RsChatStatusItem; - - cs->status_string = status_string; - cs->flags = RS_CHAT_FLAG_PRIVATE; - cs->PeerId(vpid); - -#ifdef CHAT_DEBUG - std::cerr << "sending chat status packet:" << std::endl; - cs->print(std::cerr); -#endif - sendChatItem(cs); - } - } - else - { - std::cerr << "p3ChatService::sendStatusString() Error: chat id of this " - << "type is not handled, is it empty?" << std::endl; - return; - } -} - -void p3ChatService::clearChatLobby(const ChatId& id) -{ - RsServer::notify()->notifyChatCleared(id); -} - -void p3ChatService::sendChatItem(RsChatItem *item) -{ - if(DistantChatService::handleOutgoingItem(item)) return; -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sendChatItem(): sending to " << item->PeerId() - << ": interpreted as friend peer id." << std::endl; -#endif - sendItem(item); -} - -void p3ChatService::checkSizeAndSendMessage(RsChatMsgItem *msg) -{ - // We check the message item, and possibly split it into multiple messages, if the message is too big. - - static const uint32_t MAX_STRING_SIZE = 15000 ; - -#ifdef CHAT_DEBUG - std::cerr << "Sending message: size=" << msg->message.size() << ", sha1sum=" << RsDirUtil::sha1sum((uint8_t*)msg->message.c_str(),msg->message.size()) << std::endl; -#endif - - while(msg->message.size() > MAX_STRING_SIZE) - { - // chop off the first 15000 wchars - - RsChatMsgItem *item = new RsChatMsgItem(*msg) ; - - item->message = item->message.substr(0,MAX_STRING_SIZE) ; - msg->message = msg->message.substr(MAX_STRING_SIZE,msg->message.size()-MAX_STRING_SIZE) ; - - // Clear out any one time flags that should not be copied into multiple objects. This is - // a precaution, in case the receivign peer does not yet handle split messages transparently. - // - item->chatFlags &= (RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_PUBLIC | RS_CHAT_FLAG_LOBBY) ; - -#ifdef CHAT_DEBUG - std::cerr << "Creating slice of size " << item->message.size() << std::endl; -#endif - // Indicate that the message is to be continued. - // - item->chatFlags |= RS_CHAT_FLAG_PARTIAL_MESSAGE ; - sendChatItem(item) ; - } -#ifdef CHAT_DEBUG - std::cerr << "Creating slice of size " << msg->message.size() << std::endl; -#endif - sendChatItem(msg) ; -} - - -bool p3ChatService::isOnline(const RsPeerId& pid) -{ - // check if the id is a tunnel id or a peer id. - DistantChatPeerInfo dcpinfo; - if(getDistantChatStatus(DistantChatPeerId(pid),dcpinfo)) - return dcpinfo.status == RS_DISTANT_CHAT_STATUS_CAN_TALK; - else return mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, pid); -} - -bool p3ChatService::sendChat(ChatId destination, std::string msg) -{ - if(destination.isLobbyId()) - return DistributedChatService::sendLobbyChat(destination.toLobbyId(), msg); - else if(destination.isBroadcast()) - { - sendPublicChat(msg); - return true; - } - else if(destination.isPeerId()==false && destination.isDistantChatId()==false) - { - std::cerr << "p3ChatService::sendChat() Error: chat id type not handled. Is it empty?" << std::endl; - return false; - } - // destination is peer or distant -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sendChat()" << std::endl; -#endif - - RsPeerId vpid; - if(destination.isDistantChatId()) - vpid = RsPeerId(destination.toDistantChatId()); // convert to virtual peer id - else - vpid = destination.toPeerId(); - - RsChatMsgItem *ci = new RsChatMsgItem(); - ci->PeerId(vpid); - ci->chatFlags = RS_CHAT_FLAG_PRIVATE; - ci->sendTime = time(NULL); - ci->recvTime = ci->sendTime; - ci->message = msg; - - ChatMessage message; - initChatMessage(ci, message); - message.incoming = false; - message.online = true; - - if(!isOnline(vpid) && !destination.isDistantChatId()) - { - message.online = false; - RsServer::notify()->notifyChatMessage(message); - - // use the history to load pending messages to the gui - // this is not very nice, because the user may think the message was send, while it is still in the queue - mHistoryMgr->addMessage(message); - - RsGxsTransId tId = RSRandom::random_u64(); - -#ifdef SUSPENDED_CODE - // this part of the code was formerly used to send the traffic over GxsTransport. The problem is that - // gxstunnel takes care of reaching the peer already, so GxsTransport would only be needed when the - // current peer is offline. So we need to fin a way to quickly push the items to friends when quitting RS. - - if(destination.isDistantChatId()) - { - RS_STACK_MUTEX(mDGMutex); - DIDEMap::const_iterator it = mDistantGxsMap.find(destination.toDistantChatId()); - if(it != mDistantGxsMap.end()) - { - const DistantEndpoints& de(it->second); - uint32_t sz = _serializer->size(ci); - std::vector data; data.resize(sz); - _serializer->serialise(ci, &data[0], &sz); - mGxsTransport.sendData(tId, GxsTransSubServices::P3_CHAT_SERVICE, - de.from, de.to, &data[0], sz); - } - else - std::cout << "p3ChatService::sendChat(...) can't find distant" - << "chat id in mDistantGxsMap this is unxpected!" - << std::endl; - } -#endif - - // peer is offline, add to outgoing list - { - RS_STACK_MUTEX(mChatMtx); - privateOutgoingMap.insert(outMP::value_type(tId, ci)); - } - - IndicateConfigChanged(); - return false; - } - - { - RS_STACK_MUTEX(mChatMtx); - std::map::iterator it = _avatars.find(vpid); - - if(it == _avatars.end()) - { - _avatars[vpid] = new AvatarInfo ; - it = _avatars.find(vpid) ; - } - if(it->second->_own_is_new) - { -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sendChat: new avatar never sent to peer " << vpid << ". Setting flag to packet." << std::endl; -#endif - - ci->chatFlags |= RS_CHAT_FLAG_AVATAR_AVAILABLE ; - it->second->_own_is_new = false ; - } - } - -#ifdef CHAT_DEBUG - std::cerr << "Sending msg to (maybe virtual) peer " << vpid << ", flags = " << ci->chatFlags << std::endl ; - std::cerr << "p3ChatService::sendChat() Item:"; - std::cerr << std::endl; - ci->print(std::cerr); - std::cerr << std::endl; -#endif - - RsServer::notify()->notifyChatMessage(message); - - // cyril: history is temporarily disabled for distant chat, since we need to store the full tunnel ID, but then - // at loading time, the ID is not known so that chat window shows 00000000 as a peer. - - //if(!message.chat_id.isDistantChatId()) - mHistoryMgr->addMessage(message); - - checkSizeAndSendMessage(ci); - - // Check if custom state string has changed, in which case it should be sent to the peer. - bool should_send_state_string = false ; - { - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _state_strings.find(vpid) ; - - if(it == _state_strings.end()) - { - _state_strings[vpid] = StateStringInfo() ; - it = _state_strings.find(vpid) ; - it->second._own_is_new = true ; - } - if(it->second._own_is_new) - { - should_send_state_string = true ; - it->second._own_is_new = false ; - } - } - - if(should_send_state_string) - { -#ifdef CHAT_DEBUG - std::cerr << "own status string is new for peer " << vpid << ": sending it." << std::endl ; -#endif - RsChatStatusItem *cs = makeOwnCustomStateStringItem() ; - cs->PeerId(vpid) ; - sendChatItem(cs) ; - } - - return true; -} - -// This method might take control over the memory, or modify it, possibly adding missing parts. -// This function looks weird because it cannot duplicate the message since it does not know -// what type of object it is and the duplicate method of lobby messages is reserved for -// ChatLobby bouncing objects. -// -// Returns false if the item shouldn't be used (and replaced to NULL) - -bool p3ChatService::locked_checkAndRebuildPartialMessage(RsChatMsgItem *& ci) -{ - // Check is the item is ending an incomplete item. - // - std::map::iterator it = _pendingPartialMessages.find(ci->PeerId()) ; - - bool ci_is_incomplete = ci->chatFlags & RS_CHAT_FLAG_PARTIAL_MESSAGE ; - - if(it != _pendingPartialMessages.end()) - { -#ifdef CHAT_DEBUG - std::cerr << "Pending message found. Appending it." << std::endl; -#endif - // Yes, there is. Append the item to ci. - - ci->message = it->second->message + ci->message ; - ci->chatFlags |= it->second->chatFlags ; - - // always remove existing partial. The compound message is in ci now. - - delete it->second ; - _pendingPartialMessages.erase(it) ; - } - - // now decide what to do: if ci is incomplete, store it and replace the pointer with NULL - // if complete, return it. - - if(ci_is_incomplete) - { -#ifdef CHAT_DEBUG - std::cerr << "Message is partial, storing for later." << std::endl; -#endif - // The item is a partial message. Push it, and wait for the rest. - // - _pendingPartialMessages[ci->PeerId()] = ci ; // cannot use duplicate() here - ci = NULL ; // takes memory ownership over ci - return false ; - } - else - { -#ifdef CHAT_DEBUG - std::cerr << "Message is complete, using it now. Size = " << ci->message.size() << ", hash=" << RsDirUtil::sha1sum((uint8_t*)ci->message.c_str(),ci->message.size()) << std::endl; -#endif - return true ; - } -} - - -void p3ChatService::receiveChatQueue() -{ - RsItem *item ; - - while(NULL != (item=recvItem())) - handleIncomingItem(item) ; -} - -class MsgCounter -{ - public: - MsgCounter() {} - - void clean(rstime_t max_time) - { - while(!recv_times.empty() && recv_times.front() < max_time) - recv_times.pop_front() ; - } - std::list recv_times ; -}; - -void p3ChatService::handleIncomingItem(RsItem *item) -{ -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::receiveChatQueue() Item:" << (void*)item - << std::endl ; -#endif - - // RsChatMsgItems needs dynamic_cast, since they have derived siblings. - RsChatMsgItem* ci = dynamic_cast(item); - if(ci) - { - handleRecvChatMsgItem(ci); - - /* +ci+ deletion is handled by handleRecvChatMsgItem ONLY in some - * specific cases, in case +ci+ has not been handled deleted it here */ - delete ci ; - - return; - } - - if(DistributedChatService::handleRecvItem(dynamic_cast(item))) - { - delete item; - return; - } - - switch(item->PacketSubType()) - { - case RS_PKT_SUBTYPE_CHAT_STATUS: - handleRecvChatStatusItem(dynamic_cast(item)); - break; - case RS_PKT_SUBTYPE_CHAT_AVATAR: - handleRecvChatAvatarItem(dynamic_cast(item)); - break; - default: - { - static int already = false; - if(!already) - { - std::cerr << "Unhandled item subtype " - << static_cast(item->PacketSubType()) - << " in p3ChatService: " << std::endl; - already = true; - } - } - } - delete item; -} - -void p3ChatService::handleRecvChatAvatarItem(RsChatAvatarItem *ca) -{ - receiveAvatarJpegData(ca) ; - -#ifdef CHAT_DEBUG - std::cerr << "Received avatar data for peer " << ca->PeerId() << ". Notifying." << std::endl ; -#endif - RsServer::notify()->notifyPeerHasNewAvatar(ca->PeerId().toStdString()) ; -} - -uint32_t p3ChatService::getMaxMessageSecuritySize(int type) -{ - switch (type) - { - case RS_CHAT_TYPE_LOBBY: - return MAX_MESSAGE_SECURITY_SIZE; - - case RS_CHAT_TYPE_PUBLIC: - case RS_CHAT_TYPE_PRIVATE: - case RS_CHAT_TYPE_DISTANT: - return 0; // unlimited - } - - std::cerr << "p3ChatService::getMaxMessageSecuritySize: Unknown chat type " << type << std::endl; - - return MAX_MESSAGE_SECURITY_SIZE; -} - -bool p3ChatService::checkForMessageSecurity(RsChatMsgItem *ci) -{ - // Remove too big messages - if (ci->chatFlags & RS_CHAT_FLAG_LOBBY) - { - uint32_t maxMessageSize = getMaxMessageSecuritySize(RS_CHAT_TYPE_LOBBY); - if (maxMessageSize > 0 && ci->message.length() > maxMessageSize) - { - std::ostringstream os; - os << getMaxMessageSecuritySize(RS_CHAT_TYPE_LOBBY); - - ci->message = "**** Security warning: Message bigger than "; - ci->message += os.str(); - ci->message += " characters, forwarded to you by "; - ci->message += rsPeers->getPeerName(ci->PeerId()); - ci->message += ", dropped. ****"; - return false; - } - } - - // The following code has been suggested, but is kept suspended since it is a bit too much restrictive. -#ifdef SUSPENDED - // Transform message to lowercase - std::wstring mes(ci->message); - std::transform( mes.begin(), mes.end(), mes.begin(), std::towlower); - - // Quick fix for svg attack and other nuisances (inline pictures) - if (mes.find(L"message = L"**** Security warning: Message contains an . ****"; - return false; - } - - // Remove messages with too many line breaks - size_t pos = 0; - int count_line_breaks = 0; - while ((pos = mes.find(L" 50) - { - ci->message = L"**** More than 50 line breaks, dropped. ****"; - return false; - } -#endif - - // https://en.wikipedia.org/wiki/Billion_laughs - // This should be done for all incoming HTML messages (also in forums - // etc.) so this should be a function in some other file. - - if (ci->message.find("message << std::endl; - std::cout << "**********" << std::endl; - std::cout << "********** entity attack by " << ci->PeerId().toStdString().c_str() << std::endl; - std::cout << "**********" << std::endl; - - ci->message = "**** This message (from peer id " + rsPeers->getPeerName(ci->PeerId()) + ") has been removed because it contains the string \" … - - // Also check flags. Lobby msgs should have proper flags, but they can be - // corrupted by a friend before sending them that can result in e.g. lobby - // messages ending up in the broadcast channel, etc. - - uint32_t fl = ci->chatFlags & (RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_PUBLIC | RS_CHAT_FLAG_LOBBY) ; - -#ifdef CHAT_DEBUG - std::cerr << "Checking msg flags: " << std::hex << fl << std::endl; -#endif - - if(dynamic_cast(ci) != NULL) - { - if(fl != (RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_LOBBY)) - std::cerr << "Warning: received chat lobby message with iconsistent flags " << std::hex << fl << std::dec << " from friend peer " << ci->PeerId() << std::endl; - - ci->chatFlags &= ~RS_CHAT_FLAG_PUBLIC ; - } - else if(fl!=0 && !(fl == RS_CHAT_FLAG_PRIVATE || fl == RS_CHAT_FLAG_PUBLIC)) // The !=0 is normally not needed, but we keep it for - { // a while, for backward compatibility. It's not harmful. - std::cerr << "Warning: received chat lobby message with iconsistent flags " << std::hex << fl << std::dec << " from friend peer " << ci->PeerId() << std::endl; - - std::cerr << "This message will be dropped."<< std::endl; - return false ; - } - - return true ; -} - -bool p3ChatService::initiateDistantChatConnexion( const RsGxsId& to_gxs_id, - const RsGxsId& from_gxs_id, - DistantChatPeerId& pid, - uint32_t& error_code, - bool notify ) -{ - - if(to_gxs_id.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " Destination RsGxsId is invalid" << std::endl; - return false; - } - if (from_gxs_id.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " Origin RsGxsId is invalid" << std::endl; - return false; - } - if (!rsIdentity->isOwnId(from_gxs_id)) - { - RsErr() << __PRETTY_FUNCTION__ << " Origin RsGxsId id must be own" << std::endl; - return false; - } - - if(DistantChatService::initiateDistantChatConnexion( to_gxs_id, - from_gxs_id, pid, - error_code, notify )) - { - RS_STACK_MUTEX(mDGMutex); - DistantEndpoints ep; ep.from = from_gxs_id; ep.to = to_gxs_id; - mDistantGxsMap.insert(DIDEMap::value_type(pid, ep)); - return true; - } - return false; -} - -bool p3ChatService::receiveGxsTransMail( const RsGxsId& authorId, - const RsGxsId& recipientId, - const uint8_t* data, - uint32_t dataSize ) -{ - DistantChatPeerId pid; - uint32_t error_code; - if(initiateDistantChatConnexion( - authorId, recipientId, pid, error_code, false )) - { - RsChatMsgItem* item = static_cast( - _serializer->deserialise( - const_cast(data), &dataSize )); - RsPeerId rd(p3GxsTunnelService::makeGxsTunnelId(authorId, recipientId)); - item->PeerId(rd); - handleRecvChatMsgItem(item); - delete item; - return true; - } - - std::cerr << __PRETTY_FUNCTION__ << " (EE) failed initiating" - << " distant chat connection error: "<< error_code - << std::endl; - return false; -} - -bool p3ChatService::notifyGxsTransSendStatus(RsGxsTransId mailId, - GxsTransSendStatus status ) -{ - if ( status != GxsTransSendStatus::RECEIPT_RECEIVED ) return true; - - bool changed = false; - - { - RS_STACK_MUTEX(mChatMtx); - auto it = privateOutgoingMap.find(mailId); - if( it != privateOutgoingMap.end() ) - { - privateOutgoingMap.erase(it); - changed = true; - } - } - - if(changed) - { - RsServer::notify()->notifyListChange( - NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_DEL ); - - IndicateConfigChanged(); - } - - return true; -} - -bool p3ChatService::handleRecvChatMsgItem(RsChatMsgItem *& ci) -{ - std::string name; - uint32_t popupChatFlag = RS_POPUP_CHAT; - - { - RS_STACK_MUTEX(mChatMtx); - - // we make sure this call does not take control over the memory - if(!locked_checkAndRebuildPartialMessage(ci)) return true; - /* message is a subpart of an existing message. - * So everything ok, but we need to return. */ - } - - // Check for security. This avoids bombing messages, and so on. - if(!checkForMessageSecurity(ci)) return false; - - /* If it's a lobby item, we need to bounce it and possibly check for timings - * etc. */ - if(!DistributedChatService::handleRecvChatLobbyMsgItem(ci)) return false; - -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::receiveChatQueue() Item:" << std::endl; - ci->print(std::cerr); - std::cerr << std::endl << "Got msg. Flags = " << ci->chatFlags << std::endl; -#endif - - // Now treat normal chat stuff such as avatar requests, except for chat lobbies. - - if( !(ci->chatFlags & RS_CHAT_FLAG_LOBBY)) - { - if(ci->chatFlags & RS_CHAT_FLAG_REQUESTS_AVATAR) // no msg here. Just an avatar request. - { - sendAvatarJpegData(ci->PeerId()) ; - return false ; - } - - // normal msg. Return it normally. - // Check if new avatar is available at peer's. If so, send a request to get the avatar. - - if((ci->chatFlags & RS_CHAT_FLAG_AVATAR_AVAILABLE) && !(ci->chatFlags & RS_CHAT_FLAG_LOBBY)) - { -#ifdef CHAT_DEBUG - std::cerr << "New avatar is available for peer " << ci->PeerId() << ", sending request" << std::endl ; -#endif - sendAvatarRequest(ci->PeerId()) ; - ci->chatFlags &= ~RS_CHAT_FLAG_AVATAR_AVAILABLE ; - } - - std::map::const_iterator it = _avatars.find(ci->PeerId()) ; - -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice:: avatar requested from above. " << std::endl ; -#endif - // has avatar. Return it strait away. - // - if(it!=_avatars.end() && it->second->_peer_is_new) - { -#ifdef CHAT_DEBUG - std::cerr << "Avatar is new for peer. ending info above" << std::endl ; -#endif - ci->chatFlags |= RS_CHAT_FLAG_AVATAR_AVAILABLE ; - } - } - - std::string message = ci->message; - - if(!(ci->chatFlags & RS_CHAT_FLAG_LOBBY)) - { - if(ci->chatFlags & RS_CHAT_FLAG_PRIVATE) - RsServer::notify()->AddPopupMessage(popupChatFlag, ci->PeerId().toStdString(), name, message); /* notify private chat message */ - else - { -#ifdef RS_DIRECT_CHAT - /* notify public chat message */ - RsServer::notify()->AddPopupMessage( RS_POPUP_GROUPCHAT, ci->PeerId().toStdString(), "", message ); - //RsServer::notify()->AddFeedItem( RS_FEED_ITEM_CHAT_NEW, ci->PeerId().toStdString(), message, "" ); -#else // def RS_DIRECT_CHAT - /* Ignore deprecated direct node broadcast chat messages */ - return false; -#endif - } - } - - ci->recvTime = time(NULL); - - ChatMessage cm; - initChatMessage(ci, cm); - cm.incoming = true; - cm.online = true; - RsServer::notify()->notifyChatMessage(cm); - - mHistoryMgr->addMessage(cm); - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mChatMessage = cm; - rsEvents->postEvent(ev); - } - - return true ; -} - -void p3ChatService::locked_storeIncomingMsg(RsChatMsgItem */*item*/) -{ -#ifdef REMOVE - privateIncomingList.push_back(item) ; -#endif -} - -void p3ChatService::handleRecvChatStatusItem(RsChatStatusItem *cs) -{ -#ifdef CHAT_DEBUG - std::cerr << "Received status string \"" << cs->status_string << "\"" << std::endl ; -#endif - - DistantChatPeerInfo dcpinfo; - - if(cs->flags & RS_CHAT_FLAG_REQUEST_CUSTOM_STATE) // no state here just a request. - sendCustomState(cs->PeerId()) ; - else if(cs->flags & RS_CHAT_FLAG_CUSTOM_STATE) // Check if new custom string is available at peer's. - { // If so, send a request to get the custom string. - receiveStateString(cs->PeerId(),cs->status_string) ; // store it - RsServer::notify()->notifyCustomState(cs->PeerId().toStdString(), cs->status_string) ; - } - else if(cs->flags & RS_CHAT_FLAG_CUSTOM_STATE_AVAILABLE) - { -#ifdef CHAT_DEBUG - std::cerr << "New custom state is available for peer " << cs->PeerId() << ", sending request" << std::endl ; -#endif - sendCustomStateRequest(cs->PeerId()) ; - } - else if(DistantChatService::getDistantChatStatus(DistantChatPeerId(cs->PeerId()), dcpinfo)) - { - RsServer::notify()->notifyChatStatus(ChatId(DistantChatPeerId(cs->PeerId())), cs->status_string) ; - } - else if(cs->flags & RS_CHAT_FLAG_PRIVATE) - { - RsServer::notify()->notifyChatStatus(ChatId(cs->PeerId()),cs->status_string) ; - } - else if(cs->flags & RS_CHAT_FLAG_PUBLIC) - { - ChatId id = ChatId::makeBroadcastId(); - id.broadcast_status_peer_id = cs->PeerId(); - RsServer::notify()->notifyChatStatus(id, cs->status_string) ; - } - - DistantChatService::handleRecvChatStatusItem(cs) ; -} - -void p3ChatService::initChatMessage(RsChatMsgItem *c, ChatMessage &m) -{ - m.chat_id = ChatId(c->PeerId()); - m.chatflags = 0; - m.sendTime = c->sendTime; - m.recvTime = c->recvTime; - m.msg = c->message; - - RsChatLobbyMsgItem *lobbyItem = dynamic_cast(c) ; - if(lobbyItem != NULL) - { - m.lobby_peer_gxs_id = lobbyItem->signature.keyId ; - m.chat_id = ChatId(lobbyItem->lobby_id); - return; - } - - DistantChatPeerInfo dcpinfo; - if(DistantChatService::getDistantChatStatus(DistantChatPeerId(c->PeerId()), dcpinfo)) - m.chat_id = ChatId(DistantChatPeerId(c->PeerId())); - - if (c -> chatFlags & RS_CHAT_FLAG_PRIVATE) - m.chatflags |= RS_CHAT_PRIVATE; - else - { - m.chat_id = ChatId::makeBroadcastId(); - m.broadcast_peer_id = c->PeerId(); - m.chatflags |= RS_CHAT_PUBLIC; - } -} - -void p3ChatService::setOwnCustomStateString(const std::string& s) -{ - std::set onlineList; - { - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice: Setting own state string to new value : " << s << std::endl ; -#endif - _custom_status_string = s ; - - for(std::map::iterator it(_state_strings.begin());it!=_state_strings.end();++it) - it->second._own_is_new = true ; - - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, onlineList); - } - - RsServer::notify()->notifyOwnStatusMessageChanged() ; - - // alert your online peers to your newly set status - std::set::iterator it(onlineList.begin()); - for(; it != onlineList.end(); ++it){ - - RsChatStatusItem *cs = new RsChatStatusItem(); - cs->flags = RS_CHAT_FLAG_CUSTOM_STATE_AVAILABLE; - cs->status_string = ""; - cs->PeerId(*it); - sendItem(cs); - } - - IndicateConfigChanged(); -} - -void p3ChatService::setOwnAvatarJpegData(const unsigned char *data,int size) -{ - { - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice: Setting own avatar to new image." << std::endl ; -#endif - - if((uint32_t)size > MAX_AVATAR_JPEG_SIZE) - { - std::cerr << "Supplied avatar image is too big. Maximum size is " << MAX_AVATAR_JPEG_SIZE << ", supplied image has size " << size << std::endl; - return ; - } - if(_own_avatar != NULL) - delete _own_avatar ; - - _own_avatar = new AvatarInfo(data,size) ; - - // set the info that our avatar is new, for all peers - for(std::map::iterator it(_avatars.begin());it!=_avatars.end();++it) - it->second->_own_is_new = true ; - } - IndicateConfigChanged(); - - RsServer::notify()->notifyOwnAvatarChanged() ; - -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice:setOwnAvatarJpegData() done." << std::endl ; -#endif - -} - -void p3ChatService::receiveStateString(const RsPeerId& id,const std::string& s) -{ - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice: received custom state string for peer " << id << ". Storing it." << std::endl ; -#endif - - bool new_peer = (_state_strings.find(id) == _state_strings.end()) ; - - _state_strings[id]._custom_status_string = s ; - _state_strings[id]._peer_is_new = true ; - _state_strings[id]._own_is_new = new_peer ; -} - -void p3ChatService::receiveAvatarJpegData(RsChatAvatarItem *ci) -{ - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice: received avatar jpeg data for peer " << ci->PeerId() << ". Storing it." << std::endl ; -#endif - - if(ci->image_size > MAX_AVATAR_JPEG_SIZE) - { - std::cerr << "Peer " << ci->PeerId()<< " is sending a jpeg image for avatar that exceeds the admitted size (size=" << ci->image_size << ", max=" << MAX_AVATAR_JPEG_SIZE << ")"<< std::endl; - return ; - } - bool new_peer = (_avatars.find(ci->PeerId()) == _avatars.end()) ; - - if (new_peer == false && _avatars[ci->PeerId()]) { - delete _avatars[ci->PeerId()]; - } - _avatars[ci->PeerId()] = new AvatarInfo(ci->image_data,ci->image_size) ; - _avatars[ci->PeerId()]->_peer_is_new = true ; - _avatars[ci->PeerId()]->_own_is_new = new_peer ; -} - -std::string p3ChatService::getOwnCustomStateString() -{ - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - return _custom_status_string ; -} -void p3ChatService::getOwnAvatarJpegData(unsigned char *& data,int& size) -{ - // should be a Mutex here. - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - - uint32_t s = 0 ; -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice:: own avatar requested from above. " << std::endl ; -#endif - // has avatar. Return it strait away. - // - if(_own_avatar != NULL) - { - _own_avatar->toUnsignedChar(data,s) ; - size = s ; - } - else - { - data=NULL ; - size=0 ; - } -} - -std::string p3ChatService::getCustomStateString(const RsPeerId& peer_id) -{ - { - // should be a Mutex here. - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _state_strings.find(peer_id) ; - - // has it. Return it strait away. - // - if(it!=_state_strings.end()) - { - it->second._peer_is_new = false ; - return it->second._custom_status_string ; - } - } - - sendCustomStateRequest(peer_id); - return std::string() ; -} - -void p3ChatService::getAvatarJpegData(const RsPeerId& peer_id,unsigned char *& data,int& size) -{ - { - // should be a Mutex here. - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::const_iterator it = _avatars.find(peer_id) ; - -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice:: avatar for peer " << peer_id << " requested from above. " << std::endl ; -#endif - // has avatar. Return it straight away. - // - if(it!=_avatars.end()) - { - uint32_t s=0 ; - it->second->toUnsignedChar(data,s) ; - size = s ; - it->second->_peer_is_new = false ; -#ifdef CHAT_DEBUG - std::cerr << "Already has avatar. Returning it" << std::endl ; -#endif - return ; - } else { -#ifdef CHAT_DEBUG - std::cerr << "No avatar for this peer. Requesting it by sending request packet." << std::endl ; -#endif - } - } - - sendAvatarRequest(peer_id); -} - -void p3ChatService::sendAvatarRequest(const RsPeerId& peer_id) -{ - if(!isOnline(peer_id)) - return ; - - // Doesn't have avatar. Request it. - // - RsChatMsgItem *ci = new RsChatMsgItem(); - - ci->PeerId(peer_id); - ci->chatFlags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_REQUESTS_AVATAR ; - ci->sendTime = time(NULL); - ci->message.erase(); - -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sending request for avatar, to peer " << peer_id << std::endl ; - std::cerr << std::endl; -#endif - - sendChatItem(ci); -} - -void p3ChatService::sendCustomStateRequest(const RsPeerId& peer_id){ - - if(!isOnline(peer_id)) - return ; - - RsChatStatusItem* cs = new RsChatStatusItem; - - cs->PeerId(peer_id); - cs->flags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_REQUEST_CUSTOM_STATE ; - cs->status_string.erase(); - -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sending request for status, to peer " << peer_id << std::endl ; - std::cerr << std::endl; -#endif - - sendChatItem(cs); -} - -RsChatStatusItem *p3ChatService::makeOwnCustomStateStringItem() -{ - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - RsChatStatusItem *ci = new RsChatStatusItem(); - - ci->flags = RS_CHAT_FLAG_CUSTOM_STATE ; - ci->status_string = _custom_status_string ; - - return ci ; -} - -RsChatAvatarItem *p3ChatService::makeOwnAvatarItem() -{ - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - RsChatAvatarItem *ci = new RsChatAvatarItem(); - - _own_avatar->toUnsignedChar(ci->image_data,ci->image_size) ; - - return ci ; -} - - -void p3ChatService::sendAvatarJpegData(const RsPeerId& peer_id) -{ -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice: sending requested for peer " << peer_id << ", data=" << (void*)_own_avatar << std::endl ; -#endif - - if(_own_avatar != NULL) - { - RsChatAvatarItem *ci = makeOwnAvatarItem(); - ci->PeerId(peer_id); - - // take avatar, and embed it into a std::string. - // -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sending avatar image to peer" << peer_id << ", image size = " << ci->image_size << std::endl ; - std::cerr << std::endl; -#endif - - sendChatItem(ci) ; - } - else { -#ifdef CHAT_DEBUG - std::cerr << "We have no avatar yet: Doing nothing" << std::endl ; -#endif - } -} - -void p3ChatService::sendCustomState(const RsPeerId& peer_id){ - -#ifdef CHAT_DEBUG -std::cerr << "p3chatservice: sending requested status string for peer " << peer_id << std::endl ; -#endif - - RsChatStatusItem *cs = makeOwnCustomStateStringItem(); - cs->PeerId(peer_id); - - sendChatItem(cs); -} - -bool p3ChatService::loadList(std::list& load) -{ - std::list ssl_peers; - mLinkMgr->getFriendList(ssl_peers); - - for(std::list::const_iterator it(load.begin());it!=load.end();++it) - { - if(PrivateOugoingMapItem* om=dynamic_cast(*it)) - { - RS_STACK_MUTEX(mChatMtx); - for( auto& pair : om->store ) - { - privateOutgoingMap.insert( - outMP::value_type(pair.first, - new RsChatMsgItem(pair.second)) ); - } - - delete om; continue; - } - - - RsChatAvatarItem *ai = NULL ; - - if(NULL != (ai = dynamic_cast(*it))) - { - RS_STACK_MUTEX(mChatMtx); - - if(ai->image_size <= MAX_AVATAR_JPEG_SIZE) - _own_avatar = new AvatarInfo(ai->image_data,ai->image_size) ; - else - std::cerr << "Dropping avatar image, because its size is " - << ai->image_size << ", and the maximum allowed size " - << "is " << MAX_AVATAR_JPEG_SIZE << std::endl; - - delete *it; - continue; - } - - RsChatStatusItem *mitem = NULL ; - - if(NULL != (mitem = dynamic_cast(*it))) - { - RS_STACK_MUTEX(mChatMtx); - - _custom_status_string = mitem->status_string ; - - delete *it; - continue; - } - - /* TODO: G10h4ck 2017/02/27 this block is kept for retrocompatibility, - * and will be used just first time, to load messages in the old format - * should be removed in the following RS version */ - if( RsPrivateChatMsgConfigItem *citem = - dynamic_cast(*it) ) - { - RS_STACK_MUTEX(mChatMtx); - - if ( citem->chatFlags & RS_CHAT_FLAG_PRIVATE ) - { - if ( std::find(ssl_peers.begin(), ssl_peers.end(), - citem->configPeerId) != ssl_peers.end() ) - { - RsChatMsgItem *ci = new RsChatMsgItem(); - citem->get(ci); - - if (citem->configFlags & RS_CHATMSG_CONFIGFLAG_INCOMING) - { - locked_storeIncomingMsg(ci); - } - else privateOutgoingMap.insert( - outMP::value_type(RSRandom::random_u64(), ci) ); - } - else { /* no friends */ } - } - else { /* ignore all other items */ } - - delete *it; - continue; - } - - DistributedChatService::processLoadListItem(*it) ; - DistantChatService::processLoadListItem(*it) ; - - // delete unknown items - delete *it; - } - - load.clear() ; - return true; -} - -bool p3ChatService::saveList(bool& cleanup, std::list& list) -{ - cleanup = true; - - /* now we create a pqistore, and stream all the msgs into it */ - - if(_own_avatar != NULL) - { - RsChatAvatarItem *ci = makeOwnAvatarItem() ; - ci->PeerId(mServiceCtrl->getOwnId()); - - list.push_back(ci) ; - } - - mChatMtx.lock(); /****** MUTEX LOCKED *******/ - - PrivateOugoingMapItem* om = new PrivateOugoingMapItem; - typedef std::map::value_type vT; - for( auto& pair : privateOutgoingMap ) - om->store.insert(vT(pair.first, *pair.second)); - list.push_back(om); - - - RsChatStatusItem *di = new RsChatStatusItem ; - di->status_string = _custom_status_string ; - di->flags = RS_CHAT_FLAG_CUSTOM_STATE ; - - list.push_back(di); - - DistributedChatService::addToSaveList(list) ; - DistantChatService::addToSaveList(list) ; - - return true; -} - -void p3ChatService::saveDone() -{ - /* unlock mutex */ - mChatMtx.unlock(); /****** MUTEX UNLOCKED *******/ -} - -RsSerialiser *p3ChatService::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsChatSerialiser) ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss ; -} - -/*************** pqiMonitor callback ***********************/ - -void p3ChatService::statusChange(const std::list &plist) -{ - for (auto it = plist.cbegin(); it != plist.cend(); ++it) - { - if (it->actions & RS_SERVICE_PEER_CONNECTED) - { - /* send the saved outgoing messages */ - bool changed = false; - - std::vector to_send; - - { - RS_STACK_MUTEX(mChatMtx); - - for( auto cit = privateOutgoingMap.begin(); - cit != privateOutgoingMap.end(); ) - { - RsChatMsgItem *c = cit->second; - if (c->PeerId() == it->id) - { - //mHistoryMgr->addMessage(false, c->PeerId(), ownId, c); - - to_send.push_back(c) ; - changed = true; - cit = privateOutgoingMap.erase(cit); - continue; - } - - ++cit; - } - } - - for(auto toIt = to_send.begin(); toIt != to_send.end(); ++toIt) - { - ChatMessage message; - initChatMessage(*toIt, message); - message.incoming = false; - message.online = true; - RsServer::notify()->notifyChatMessage(message); - - checkSizeAndSendMessage(*toIt); // delete item - } - - if (changed) - { - RsServer::notify()->notifyListChange( - NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_DEL); - - IndicateConfigChanged(); - } - } - else if (it->actions & RS_SERVICE_PEER_REMOVED) - { - /* now handle remove */ - mHistoryMgr->clear(ChatId(it->id)); - - RS_STACK_MUTEX(mChatMtx); - for ( auto cit = privateOutgoingMap.begin(); - cit != privateOutgoingMap.end(); ) - { - RsChatMsgItem *c = cit->second; - if (c->PeerId() == it->id) cit = privateOutgoingMap.erase(cit); - else ++cit; - } - IndicateConfigChanged(); - } - } -} diff --git a/libretroshare/src/chat/p3chatservice.h b/libretroshare/src/chat/p3chatservice.h deleted file mode 100644 index bc4dd56b9..000000000 --- a/libretroshare/src/chat/p3chatservice.h +++ /dev/null @@ -1,305 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: chatservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef SERVICE_CHAT_HEADER -#define SERVICE_CHAT_HEADER - -#include -#include -#include - -#include "rsitems/rsmsgitems.h" -#include "services/p3service.h" -#include "pqi/pqiservicemonitor.h" -#include "chat/distantchat.h" -#include "chat/distributedchat.h" -#include "retroshare/rsmsgs.h" -#include "gxstrans/p3gxstrans.h" -#include "util/rsdeprecate.h" - -class p3ServiceControl; -class p3LinkMgr; -class p3HistoryMgr; - -typedef RsPeerId ChatLobbyVirtualPeerId ; - -struct RsChatMessageEvent : RsEvent -{ - RsChatMessageEvent() : RsEvent(RsEventType::CHAT_MESSAGE) {} - ~RsChatMessageEvent() override = default; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - - RS_SERIAL_PROCESS(mChatMessage); - } - - ChatMessage mChatMessage; -}; - -//!The basic Chat service. - /** - * - * Can be used to send and receive chats, immediate status (using notify), avatars, and custom status - * This service uses rsnotify (callbacks librs clients (e.g. rs-gui)) - * @see NotifyBase - */ -class p3ChatService : - public p3Service, public DistantChatService, public DistributedChatService, public p3Config, - public pqiServiceMonitor, GxsTransClient -{ -public: - p3ChatService(p3ServiceControl *cs, p3IdService *pids, p3LinkMgr *cm, - p3HistoryMgr *historyMgr, p3GxsTrans& gxsTransService ); - - virtual RsServiceInfo getServiceInfo(); - - /***** overloaded from p3Service *****/ - /*! - * This retrieves all chat msg items and also (important!) - * processes chat-status items that are in service item queue. chat msg item requests are also processed and not returned - * (important! also) notifications sent to notify base on receipt avatar, immediate status and custom status - * : notifyCustomState, notifyChatStatus, notifyPeerHasNewAvatar - * @see NotifyBase - */ - virtual int tick(); - - /*************** pqiMonitor callback ***********************/ - virtual void statusChange(const std::list &plist); - - /*! - * public chat sent to all peers - */ - void sendPublicChat(const std::string &msg); - - /********* RsMsgs ***********/ - /*! - * Send a chat message. - * @param destination where to send the chat message - * @param msg the message - * @see ChatId - */ - bool sendChat(ChatId destination, std::string msg); - - /*! - * chat is sent to specifc peer - * @param id peer to send chat msg to - */ - bool sendPrivateChat(const RsPeerId &id, const std::string &msg); - - /** - * can be used to send 'immediate' status msgs, these status updates are - * meant for immediate use by peer (not saved by rs) e.g currently used to - * update user when a peer 'is typing' during a chat */ - void sendStatusString( const ChatId& id, const std::string& status_str ); - - /** - * @brief clearChatLobby: Signal chat was cleared by GUI. - * @param id: Chat id cleared. - */ - virtual void clearChatLobby(const ChatId& id); - - /*! - * send to all peers online - *@see sendStatusString() - */ - void sendGroupChatStatusString(const std::string& status_str) ; - - /*! - * this retrieves custom status for a peers, generate a requests to the peer - * @param peer_id the id of the peer you want status string for - */ - std::string getCustomStateString(const RsPeerId& peer_id) ; - - /*! - * sets the client's custom status, generates 'status available' item sent to all online peers - */ - void setOwnCustomStateString(const std::string&) ; - - /*! - * @return client's custom string - */ - std::string getOwnCustomStateString() ; - - /*! gets the peer's avatar in jpeg format, if available. Null otherwise. Also asks the peer to send - * its avatar, if not already available. Creates a new unsigned char array. It's the caller's - * responsibility to delete this ones used. - */ - void getAvatarJpegData(const RsPeerId& peer_id,unsigned char *& data,int& size) ; - - /*! - * Sets the avatar data and size for client's account - * @param data is copied, so should be destroyed by the caller - */ - void setOwnAvatarJpegData(const unsigned char *data,int size) ; - - /*! - * Gets the avatar data for clients account - * data is in jpeg format - */ - void getOwnAvatarJpegData(unsigned char *& data,int& size) ; - - /*! - * Return the max message size for security forwarding - * @param type RS_CHAT_TYPE_... - * return 0 unlimited - */ - static uint32_t getMaxMessageSecuritySize(int type); - - /*! - * Checks message security, especially remove billion laughs attacks - */ - - static bool checkForMessageSecurity(RsChatMsgItem *) ; - - /*! - * @param clear private chat queue - */ - bool clearPrivateChatQueue(bool incoming, const RsPeerId &id); - - virtual bool initiateDistantChatConnexion( const RsGxsId& to_gxs_id, - const RsGxsId& from_gxs_id, - DistantChatPeerId &pid, - uint32_t& error_code, - bool notify = true ); - - /// @see GxsTransClient::receiveGxsTransMail(...) - virtual bool receiveGxsTransMail( const RsGxsId& authorId, - const RsGxsId& recipientId, - const uint8_t* data, uint32_t dataSize ); - - /// @see GxsTransClient::notifySendMailStatus(...) - virtual bool notifyGxsTransSendStatus( RsGxsTransId mailId, - GxsTransSendStatus status ); - - -protected: - /************* from p3Config *******************/ - virtual RsSerialiser *setupSerialiser() ; - - /*! - * chat msg items and custom status are saved - */ - virtual bool saveList(bool& cleanup, std::list&) ; - virtual void saveDone(); - virtual bool loadList(std::list& load) ; - - // accepts virtual peer id - bool isOnline(const RsPeerId &pid) ; - - /// This is to be used by subclasses/parents to call IndicateConfigChanged() - virtual void triggerConfigSave() { IndicateConfigChanged() ; } - - /// Same, for storing messages in incoming list - RS_DEPRECATED virtual void locked_storeIncomingMsg(RsChatMsgItem *) ; - -private: - RsMutex mChatMtx; - - class AvatarInfo ; - class StateStringInfo ; - - // Receive chat queue - void receiveChatQueue(); - void handleIncomingItem(RsItem *); // called by the former, and turtle handler for incoming encrypted items - - virtual void sendChatItem(RsChatItem *) ; - - void initChatMessage(RsChatMsgItem *c, ChatMessage& msg); - - /// Send avatar info to peer in jpeg format. - void sendAvatarJpegData(const RsPeerId& peer_id) ; - - /// Send custom state info to peer - void sendCustomState(const RsPeerId& peer_id); - - /// Receive the avatar in a chat item, with RS_CHAT_RECEIVE_AVATAR flag. - void receiveAvatarJpegData(RsChatAvatarItem *ci) ; // new method - void receiveStateString(const RsPeerId& id,const std::string& s) ; - - /// methods for handling various Chat items. - virtual bool handleRecvChatMsgItem(RsChatMsgItem *&item) ; // NULL-ifies the item if memory ownership is taken - - void handleRecvChatStatusItem(RsChatStatusItem *item) ; - void handleRecvChatAvatarItem(RsChatAvatarItem *item) ; - - /// Sends a request for an avatar to the peer of given id - void sendAvatarRequest(const RsPeerId& peer_id) ; - - /// Send a request for custom status string - void sendCustomStateRequest(const RsPeerId& peer_id); - - /// called as a proxy to sendItem(). Possibly splits item into multiple items of size lower than the maximum item size. - //void checkSizeAndSendMessage(RsChatLobbyMsgItem *item) ; - void checkSizeAndSendMessage(RsChatMsgItem *item) ; // keep for compatibility for a few weeks. - - /// Called when a RsChatMsgItem is received. The item may be collapsed with any waiting partial chat item from the same peer. - /// if so, the chat item will be turned to NULL - bool locked_checkAndRebuildPartialMessage(RsChatMsgItem *&) ; - - RsChatAvatarItem *makeOwnAvatarItem() ; - RsChatStatusItem *makeOwnCustomStateStringItem() ; - - p3ServiceControl *mServiceCtrl; - p3LinkMgr *mLinkMgr; - p3HistoryMgr *mHistoryMgr; - - /// messages waiting to be send when peer comes online - typedef std::map outMP; - outMP privateOutgoingMap; - - AvatarInfo *_own_avatar ; - std::map _avatars ; - std::map _pendingPartialMessages; - - std::string _custom_status_string ; - std::map _state_strings ; - - RsChatSerialiser *_serializer; - - struct DistantEndpoints { RsGxsId from; RsGxsId to; }; - typedef std::map DIDEMap; - DIDEMap mDistantGxsMap; - RsMutex mDGMutex; - - p3GxsTrans& mGxsTransport; -}; - -class p3ChatService::StateStringInfo -{ - public: - StateStringInfo() - { - _custom_status_string = "" ; // the custom status string of the peer - _peer_is_new = false ; // true when the peer has a new avatar - _own_is_new = false ; // true when I myself a new avatar to send to this peer. - } - - std::string _custom_status_string ; - int _peer_is_new ; // true when the peer has a new avatar - int _own_is_new ; // true when I myself a new avatar to send to this peer. -}; - -#endif // SERVICE_CHAT_HEADER - diff --git a/libretroshare/src/chat/rschatitems.cc b/libretroshare/src/chat/rschatitems.cc deleted file mode 100644 index 13d272c4e..000000000 --- a/libretroshare/src/chat/rschatitems.cc +++ /dev/null @@ -1,206 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: rschatitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include "retroshare/rsmsgs.h" -#include "util/rstime.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" - -#include "serialiser/rstypeserializer.h" - -#include "chat/rschatitems.h" - -//#define CHAT_DEBUG 1 - -//static const uint32_t RS_CHAT_SERIALIZER_FLAGS_NO_SIGNATURE = 0x0001; - -RsItem *RsChatSerialiser::create_item(uint16_t service_id,uint8_t item_sub_id) const -{ - if(service_id != RS_SERVICE_TYPE_CHAT) return NULL; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_DEFAULT: return new RsChatMsgItem(); - case RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG: return new RsPrivateChatMsgConfigItem(); - case RS_PKT_SUBTYPE_CHAT_STATUS: return new RsChatStatusItem(); - case RS_PKT_SUBTYPE_CHAT_AVATAR: return new RsChatAvatarItem(); - case RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_MSG: return new RsChatLobbyMsgItem(); - case RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE: return new RsChatLobbyInviteItem(); - case RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_DEPRECATED: return new RsChatLobbyInviteItem_Deprecated(); // to be removed (deprecated since May 2017) - case RS_PKT_SUBTYPE_CHAT_LOBBY_CHALLENGE: return new RsChatLobbyConnectChallengeItem(); - case RS_PKT_SUBTYPE_CHAT_LOBBY_UNSUBSCRIBE: return new RsChatLobbyUnsubscribeItem(); - case RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_EVENT: return new RsChatLobbyEventItem(); - 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_CONFIG: return new RsChatLobbyConfigItem(); - case RS_PKT_SUBTYPE_SUBSCRIBED_CHAT_LOBBY_CONFIG: return new RsSubscribedChatLobbyConfigItem(); - case RS_PKT_SUBTYPE_OUTGOING_MAP: return new PrivateOugoingMapItem(); - default: - std::cerr << "Unknown packet type in chat!" << std::endl; - return NULL; - } -} - -void RsChatMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,chatFlags,"chatflags") ; - RsTypeSerializer::serial_process(j,ctx,sendTime,"sendTime") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,message,"message") ; -} - -/*************************************************************************/ - -void RsChatLobbyBouncingObject::serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,lobby_id,"lobby_id") ; - RsTypeSerializer::serial_process(j,ctx,msg_id ,"msg_id") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_NAME,nick,"nick") ; - - if(!(ctx.mFlags & RsSerializationFlags::SIGNATURE)) - RS_SERIAL_PROCESS(signature); -} - -void RsChatLobbyMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsChatMsgItem::serial_process(j,ctx) ; - RsTypeSerializer::serial_process(j,ctx,parent_msg_id,"parent_msg_id") ; - RsChatLobbyBouncingObject::serial_process(j,ctx) ; -} - -void RsChatLobbyListRequestItem::serial_process(RsGenericSerializer::SerializeJob /*j*/,RsGenericSerializer::SerializeContext& /*ctx*/) -{ - // nothing to do. This is an empty item. -} - -template<> void RsTypeSerializer::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,VisibleChatLobbyInfo& info,const std::string& /*name*/) -{ - RsTypeSerializer::serial_process(j,ctx,info.id,"info.id") ; - - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,info.name, "info.name") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,info.topic,"info.topic") ; - RsTypeSerializer::serial_process(j,ctx, info.count,"info.count") ; - RsTypeSerializer::serial_process (j,ctx, info.flags,"info.flags") ; -} - -void RsChatLobbyListItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,lobbies,"lobbies") ; -} - -void RsChatLobbyEventItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,event_type,"event_type") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,string1,"string1") ; - RsTypeSerializer::serial_process(j,ctx,sendTime ,"sendTime") ; - - RsChatLobbyBouncingObject::serial_process(j,ctx) ; -} -void RsChatLobbyUnsubscribeItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,lobby_id,"lobby_id") ; -} - -void RsChatLobbyConnectChallengeItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,challenge_code,"challenge_code") ; -} - -// to be removed (deprecated since May 2017) -void RsChatLobbyInviteItem_Deprecated::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx, lobby_id, "lobby_id") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,lobby_name, "lobby_name") ; - RsTypeSerializer::serial_process (j,ctx, lobby_flags,"lobby_flags") ; -} - -void RsChatLobbyInviteItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx, lobby_id, "lobby_id") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,lobby_name, "lobby_name") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,lobby_topic,"lobby_topic") ; - RsTypeSerializer::serial_process (j,ctx, lobby_flags,"lobby_flags") ; -} - -void RsPrivateChatMsgConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - uint32_t x=0 ; - - RsTypeSerializer::serial_process(j,ctx, x, "place holder value") ; - RsTypeSerializer::serial_process (j,ctx, configPeerId,"configPeerId") ; - RsTypeSerializer::serial_process(j,ctx, chatFlags, "chatFlags") ; - RsTypeSerializer::serial_process(j,ctx, sendTime, "sendTime") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_MSG,message, "message") ; - RsTypeSerializer::serial_process(j,ctx, recvTime, "recvTime") ; -} - -void RsChatStatusItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,flags,"flags") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,status_string,"status_string") ; -} - -void RsChatAvatarItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::TlvMemBlock_proxy b(image_data,image_size) ; - 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) -{ - RsTypeSerializer::serial_process(j,ctx,lobby_Id,"lobby_Id") ; - RsTypeSerializer::serial_process(j,ctx,flags,"flags") ; -} - -/* set data from RsChatMsgItem to RsPrivateChatMsgConfigItem */ -void RsPrivateChatMsgConfigItem::set(RsChatMsgItem *ci, const RsPeerId& /*peerId*/, uint32_t confFlags) -{ - PeerId(ci->PeerId()); - configPeerId = ci->PeerId(); - chatFlags = ci->chatFlags; - configFlags = confFlags; - sendTime = ci->sendTime; - message = ci->message; - recvTime = ci->recvTime; -} - -/* get data from RsPrivateChatMsgConfigItem to RsChatMsgItem */ -void RsPrivateChatMsgConfigItem::get(RsChatMsgItem *ci) -{ - ci->PeerId(configPeerId); - ci->chatFlags = chatFlags; - //configFlags not used - ci->sendTime = sendTime; - ci->message = message; - ci->recvTime = recvTime; -} - - -void PrivateOugoingMapItem::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ RS_SERIAL_PROCESS(store); } diff --git a/libretroshare/src/chat/rschatitems.h b/libretroshare/src/chat/rschatitems.h deleted file mode 100644 index aca3a411a..000000000 --- a/libretroshare/src/chat/rschatitems.h +++ /dev/null @@ -1,383 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: rschatitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ - -#pragma once - -#include "openssl/bn.h" -#include "retroshare/rstypes.h" -#include "serialiser/rsserializer.h" -#include "serialiser/rstlvkeys.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" -#include "rsitems/rsitem.h" -#include "serialiser/rsserial.h" -#include "util/rsdeprecate.h" - -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvfileitem.h" -#include "retroshare/rsmsgs.h" - -/* chat Flags */ -const uint32_t RS_CHAT_FLAG_PRIVATE = 0x0001; -const uint32_t RS_CHAT_FLAG_REQUESTS_AVATAR = 0x0002; -const uint32_t RS_CHAT_FLAG_CONTAINS_AVATAR = 0x0004; -const uint32_t RS_CHAT_FLAG_AVATAR_AVAILABLE = 0x0008; -const uint32_t RS_CHAT_FLAG_CUSTOM_STATE = 0x0010; // used for transmitting peer status string -const uint32_t RS_CHAT_FLAG_PUBLIC = 0x0020; -const uint32_t RS_CHAT_FLAG_REQUEST_CUSTOM_STATE = 0x0040; -const uint32_t RS_CHAT_FLAG_CUSTOM_STATE_AVAILABLE = 0x0080; -const uint32_t RS_CHAT_FLAG_PARTIAL_MESSAGE = 0x0100; -const uint32_t RS_CHAT_FLAG_LOBBY = 0x0200; -const uint32_t RS_CHAT_FLAG_CLOSING_DISTANT_CONNECTION = 0x0400; -const uint32_t RS_CHAT_FLAG_ACK_DISTANT_CONNECTION = 0x0800; -const uint32_t RS_CHAT_FLAG_KEEP_ALIVE = 0x1000; -const uint32_t RS_CHAT_FLAG_CONNEXION_REFUSED = 0x2000; - -const uint32_t RS_CHATMSG_CONFIGFLAG_INCOMING = 0x0001; - -const uint8_t RS_PKT_SUBTYPE_CHAT_AVATAR = 0x03 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_STATUS = 0x04 ; -const uint8_t RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG = 0x05 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_MSG_DEPRECATED = 0x06 ; // don't use ! Deprecated -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_DEPREC = 0x07 ; // don't use ! Deprecated -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_ACCEPT = 0x08 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_CHALLENGE = 0x09 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_UNSUBSCRIBE = 0x0A ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_EVENT_DEPREC = 0x0B ; // don't use ! Deprecated -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_MSG = 0x0C ; // will be deprecated when only signed messages are accepted (02/2015) -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST = 0x0D ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated = 0x0E ; // to be removed -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_deprecated = 0x0F ; // to be removed -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_EVENT = 0x10 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated2 = 0x11 ; // to be removed (deprecated since 02 Dec. 2012) -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated3 = 0x12 ; -const uint8_t RS_PKT_SUBTYPE_DISTANT_INVITE_CONFIG = 0x13 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_CONFIG = 0x15 ; -const uint8_t RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY = 0x16 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_MSG = 0x17 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_EVENT = 0x18 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST = 0x19 ; - -RS_DEPRECATED_FOR(RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE) \ -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_DEPRECATED = 0x1A ; // to be removed (deprecated since May 2017) - -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_SUBSCRIBED_CHAT_LOBBY_CONFIG = 0x1D ; - -typedef uint64_t ChatLobbyId ; -typedef uint64_t ChatLobbyMsgId ; -typedef std::string ChatLobbyNickName ; -typedef uint64_t DistantChatDHSessionId ; - -class RsChatItem: public RsItem -{ - public: - RsChatItem(uint8_t chat_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_CHAT,chat_subtype) - { - setPriorityLevel(QOS_PRIORITY_RS_CHAT_ITEM) ; - } - - virtual ~RsChatItem() {} - virtual void clear() {} -}; - -/*! - * For sending chat msgs - * @see p3ChatService - */ -class RsChatMsgItem: public RsChatItem -{ -public: - RsChatMsgItem() :RsChatItem(RS_PKT_SUBTYPE_DEFAULT) {} - RsChatMsgItem(uint8_t subtype) :RsChatItem(subtype) {} - - //RsChatMsgItem() {} - - virtual ~RsChatMsgItem() {} - - // derived from RsItem - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - virtual void clear() {} - - uint32_t chatFlags; - uint32_t sendTime; - std::string message; - - /* not serialised */ - uint32_t recvTime; -}; - -// This class contains the info to bounce an object throughout a lobby, while -// maintaining cache info to avoid duplicates. -// -class RsChatLobbyBouncingObject -{ -public: - ChatLobbyId lobby_id ; - ChatLobbyMsgId msg_id ; - ChatLobbyNickName nick ; // Nickname of sender - - RsTlvKeySignature signature ; - - virtual RsChatLobbyBouncingObject *duplicate() const = 0 ; - -protected: - // The functions below handle the serialisation of data that is specific to the bouncing object level. - // They are called by serial_size() and serialise() from children, but should not overload the serial_size() and - // serialise() methods, otherwise the wrong method will be called when serialising from this top level class. - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - virtual uint32_t PacketId() const= 0; -}; - -class RsChatLobbyMsgItem: public RsChatMsgItem, public RsChatLobbyBouncingObject -{ -public: - RsChatLobbyMsgItem() :RsChatMsgItem(RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_MSG) {} - - virtual ~RsChatLobbyMsgItem() {} - virtual RsChatLobbyBouncingObject *duplicate() const { return new RsChatLobbyMsgItem(*this) ; } - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - ChatLobbyMsgId parent_msg_id ; // Used for threaded chat. - -protected: - virtual uint32_t PacketId() const { return RsChatMsgItem::PacketId() ; } -}; - -class RsChatLobbyEventItem: public RsChatItem, public RsChatLobbyBouncingObject -{ -public: - RsChatLobbyEventItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_EVENT) {} - - virtual ~RsChatLobbyEventItem() {} - virtual RsChatLobbyBouncingObject *duplicate() const { return new RsChatLobbyEventItem(*this) ; } - // - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // members. - // - uint8_t event_type ; // used for defining the type of event. - std::string string1; // used for any string - uint32_t sendTime; // used to check for old looping messages - -protected: - virtual uint32_t PacketId() const { return RsChatItem::PacketId() ; } -}; - -class RsChatLobbyListRequestItem: public RsChatItem -{ - public: - RsChatLobbyListRequestItem() : RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST) {} - virtual ~RsChatLobbyListRequestItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -struct VisibleChatLobbyInfo -{ - ChatLobbyId id ; - std::string name ; - std::string topic ; - uint32_t count ; - ChatLobbyFlags flags ; -}; - -class RsChatLobbyListItem: public RsChatItem -{ - public: - RsChatLobbyListItem() : RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_LIST) {} - virtual ~RsChatLobbyListItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - std::vector lobbies ; -}; - -class RsChatLobbyUnsubscribeItem: public RsChatItem -{ - public: - RsChatLobbyUnsubscribeItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_UNSUBSCRIBE) {} - - virtual ~RsChatLobbyUnsubscribeItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint64_t lobby_id ; -}; - -class RsChatLobbyConnectChallengeItem: public RsChatItem -{ - public: - RsChatLobbyConnectChallengeItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_CHALLENGE) {} - - virtual ~RsChatLobbyConnectChallengeItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint64_t challenge_code ; -}; - -/// @deprecated since May 2017, to be removed -class RsChatLobbyInviteItem_Deprecated : public RsChatItem -{ - public: - RsChatLobbyInviteItem_Deprecated() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_DEPRECATED) {} - virtual ~RsChatLobbyInviteItem_Deprecated() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - ChatLobbyId lobby_id ; - std::string lobby_name ; - std::string lobby_topic ; - ChatLobbyFlags lobby_flags ; -}; - -class RsChatLobbyInviteItem: public RsChatItem -{ - public: - RsChatLobbyInviteItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE) {} - virtual ~RsChatLobbyInviteItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - ChatLobbyId lobby_id ; - std::string lobby_name ; - std::string lobby_topic ; - ChatLobbyFlags lobby_flags ; -}; - -/*! - * For saving incoming and outgoing chat msgs - * @see p3ChatService - */ -struct RsPrivateChatMsgConfigItem : RsChatItem -{ - RsPrivateChatMsgConfigItem() : - RsChatItem(RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG) {} - - virtual ~RsPrivateChatMsgConfigItem() {} - virtual void clear() {} - - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - - /** set data from RsChatMsgItem to RsPrivateChatMsgConfigItem */ - void set(RsChatMsgItem *ci, const RsPeerId &peerId, uint32_t confFlags); - /** get data from RsPrivateChatMsgConfigItem to RsChatMsgItem */ - void get(RsChatMsgItem *ci); - - RsPeerId configPeerId; - uint32_t chatFlags; - uint32_t configFlags; - uint32_t sendTime; - std::string message; - 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 -{ -public: - RsChatLobbyConfigItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_CONFIG) { lobby_Id = 0; } - - virtual ~RsChatLobbyConfigItem() {} - - virtual void clear() { lobby_Id = 0; } - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint64_t lobby_Id; - uint32_t flags ; -}; - -// This class contains activity info for the sending peer: active, idle, typing, etc. -// -class RsChatStatusItem: public RsChatItem -{ - public: - RsChatStatusItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_STATUS) {} - - virtual ~RsChatStatusItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t flags ; - std::string status_string; -}; - -// This class contains avatar images in Qt format. -// -class RsChatAvatarItem: public RsChatItem -{ -public: - RsChatAvatarItem(): - RsChatItem(RS_PKT_SUBTYPE_CHAT_AVATAR), - image_size(0), image_data(nullptr) - { setPriorityLevel(QOS_PRIORITY_RS_CHAT_AVATAR_ITEM); } - - ~RsChatAvatarItem() override { free(image_data); } - - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override; - - uint32_t image_size; /// size of data in bytes - unsigned char* image_data ; /// image data -}; - - -struct PrivateOugoingMapItem : RsChatItem -{ - PrivateOugoingMapItem() : RsChatItem(RS_PKT_SUBTYPE_OUTGOING_MAP) {} - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - - std::map store; -}; - -struct RsChatSerialiser : RsServiceSerializer -{ - RsChatSerialiser(RsSerializationFlags flags = RsSerializationFlags::NONE): - RsServiceSerializer(RS_SERVICE_TYPE_CHAT, flags) {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_sub_id) const; -}; - diff --git a/libretroshare/src/crypto/chacha20.cpp b/libretroshare/src/crypto/chacha20.cpp deleted file mode 100644 index ebda0ee3c..000000000 --- a/libretroshare/src/crypto/chacha20.cpp +++ /dev/null @@ -1,1421 +0,0 @@ -/******************************************************************************* - * libretroshare/src/crypto: chacha20.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "crypto/chacha20.h" -#include "util/rsprint.h" -#include "util/rsrandom.h" -#include "util/rstime.h" - -#define rotl(x,n) { x = (x << n) | (x >> (-n & 31)) ;} - -//#define DEBUG_CHACHA20 - -#if OPENSSL_VERSION_NUMBER >= 0x010100000L && !defined(LIBRESSL_VERSION_NUMBER) - #define AEAD_chacha20_poly1305_openssl AEAD_chacha20_poly1305 -#else - #define AEAD_chacha20_poly1305_rs AEAD_chacha20_poly1305 -#endif - -namespace librs { -namespace crypto { - -/*! - * \brief The uint256_32 struct - * This structure represents 256bits integers, to be used for computing poly1305 authentication tags. - */ -struct uint256_32 -{ - uint32_t b[8] ; - - uint256_32() { memset(&b[0],0,8*sizeof(uint32_t)) ; } - - uint256_32(uint32_t b7,uint32_t b6,uint32_t b5,uint32_t b4,uint32_t b3,uint32_t b2,uint32_t b1,uint32_t b0) - { - b[0]=b0; b[1]=b1; b[2]=b2; b[3]=b3; - b[4]=b4; b[5]=b5; b[6]=b6; b[7]=b7; - } - - static uint256_32 random() - { - uint256_32 r ; - for(uint32_t i=0;i<8;++i) - r.b[i] = RSRandom::random_u32(); - - return r; - } - - // constant cost == - bool operator==(const uint256_32& u) - { - bool res = true ; - - if(b[0] != u.b[0]) res = false ; - if(b[1] != u.b[1]) res = false ; - if(b[2] != u.b[2]) res = false ; - if(b[3] != u.b[3]) res = false ; - if(b[4] != u.b[4]) res = false ; - if(b[5] != u.b[5]) res = false ; - if(b[6] != u.b[6]) res = false ; - if(b[7] != u.b[7]) res = false ; - - return res ; - } - - // Constant cost sum. - // - void operator +=(const uint256_32& u) - { - uint64_t v(0) ; - - v += (uint64_t)b[0] + (uint64_t)u.b[0] ; b[0] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[1] + (uint64_t)u.b[1] ; b[1] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[2] + (uint64_t)u.b[2] ; b[2] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[3] + (uint64_t)u.b[3] ; b[3] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[4] + (uint64_t)u.b[4] ; b[4] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[5] + (uint64_t)u.b[5] ; b[5] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[6] + (uint64_t)u.b[6] ; b[6] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[7] + (uint64_t)u.b[7] ; b[7] = (uint32_t)v ; - } - void operator -=(const uint256_32& u) - { - *this += ~u ; - ++*this ; - } - void operator++() - { - for(int i=0;i<8;++i) - if( ++b[i] ) - break ; - } - - bool operator<(const uint256_32& u) const - { - for(int i=7;i>=0;--i) - if(b[i] < u.b[i]) - return true ; - else - if(b[i] > u.b[i]) - return false ; - - return false ; - } - uint256_32 operator~() const - { - uint256_32 r(*this) ; - - r.b[0] = ~b[0] ; - r.b[1] = ~b[1] ; - r.b[2] = ~b[2] ; - r.b[3] = ~b[3] ; - r.b[4] = ~b[4] ; - r.b[5] = ~b[5] ; - r.b[6] = ~b[6] ; - r.b[7] = ~b[7] ; - - return r ; - } - - void poly1305clamp() - { - b[0] &= 0x0fffffff; - b[1] &= 0x0ffffffc; - b[2] &= 0x0ffffffc; - b[3] &= 0x0ffffffc; - } - // Constant cost product. - // - void operator *=(const uint256_32& u) - { - uint256_32 r ; - - for(int i=0;i<8;++i) - for(int j=0;j<8;++j) - if(i+j < 8) - { - uint64_t s = (uint64_t)u.b[j]*(uint64_t)b[i] ; - - uint256_32 partial ; - partial.b[i+j] = (s & 0xffffffff) ; - - if(i+j+1 < 8) - partial.b[i+j+1] = (s >> 32) ; - - r += partial; - } - *this = r; - } - - static void print(const uint256_32& s) - { - fprintf(stdout,"%08x %08x %08x %08x %08x %08x %08x %08x",(uint32_t)s.b[7],(uint32_t)s.b[6],(uint32_t)s.b[5],(uint32_t)s.b[4], - (uint32_t)s.b[3],(uint32_t)s.b[2],(uint32_t)s.b[1],(uint32_t)s.b[0]) ; - } - static int max_non_zero_of_height_bits(uint8_t s) - { - for(int i=7;i>=0;--i) - if((s & (1<=0;--c) - if(b[c] != 0) - { - if( (b[c] & 0xff000000) != 0) return (c<<5) + 3*8 + max_non_zero_of_height_bits(b[c] >> 24) ; - if( (b[c] & 0x00ff0000) != 0) return (c<<5) + 2*8 + max_non_zero_of_height_bits(b[c] >> 16) ; - if( (b[c] & 0x0000ff00) != 0) return (c<<5) + 1*8 + max_non_zero_of_height_bits(b[c] >> 8) ; - - return c*32 + 0*8 + max_non_zero_of_height_bits(b[c]) ; - } - return -1; - } - void lshift(uint32_t n) - { - uint32_t p = n >> 5; // n/32 - uint32_t u = n & 0x1f ; // n%32 - - if(p > 0) - for(int i=7;i>=0;--i) - b[i] = (i>=(int)p)?b[i-p]:0 ; - - uint32_t r = 0 ; - - if(u>0) - for(int i=0;i<8;++i) - { - uint32_t r1 = (b[i] >> (31-u+1)) ; - b[i] = (b[i] << u) & 0xffffffff; - b[i] += r ; - r = r1 ; - } - } - void lshift() - { - uint32_t r ; - uint32_t r1 ; - - r1 = (b[0] >> 31) ; b[0] <<= 1; r = r1 ; - r1 = (b[1] >> 31) ; b[1] <<= 1; b[1] += r ; r = r1 ; - r1 = (b[2] >> 31) ; b[2] <<= 1; b[2] += r ; r = r1 ; - r1 = (b[3] >> 31) ; b[3] <<= 1; b[3] += r ; r = r1 ; - r1 = (b[4] >> 31) ; b[4] <<= 1; b[4] += r ; r = r1 ; - r1 = (b[5] >> 31) ; b[5] <<= 1; b[5] += r ; r = r1 ; - r1 = (b[6] >> 31) ; b[6] <<= 1; b[6] += r ; r = r1 ; - b[7] <<= 1; b[7] += r ; - } - void rshift() - { - uint32_t r ; - uint32_t r1 ; - - r1 = b[7] & 0x1; b[7] >>= 1 ; r = r1 ; - r1 = b[6] & 0x1; b[6] >>= 1 ; if(r) b[6] += 0x80000000 ; r = r1 ; - r1 = b[5] & 0x1; b[5] >>= 1 ; if(r) b[5] += 0x80000000 ; r = r1 ; - r1 = b[4] & 0x1; b[4] >>= 1 ; if(r) b[4] += 0x80000000 ; r = r1 ; - r1 = b[3] & 0x1; b[3] >>= 1 ; if(r) b[3] += 0x80000000 ; r = r1 ; - r1 = b[2] & 0x1; b[2] >>= 1 ; if(r) b[2] += 0x80000000 ; r = r1 ; - r1 = b[1] & 0x1; b[1] >>= 1 ; if(r) b[1] += 0x80000000 ; r = r1 ; - b[0] >>= 1 ; if(r) b[0] += 0x80000000 ; - } -}; - -// Compute quotient and modulo of n by p where both n and p are 256bits integers. -// -static void quotient(const uint256_32& n,const uint256_32& p,uint256_32& q,uint256_32& r) -{ - // simple algorithm: add up multiples of u while keeping below *this. Once done, substract. - - r = n ; - q = uint256_32(0,0,0,0,0,0,0,0) ; - - int bmax = n.max_non_zero_bit() - p.max_non_zero_bit(); - - uint256_32 m(0,0,0,0,0,0,0,0) ; - uint256_32 d = p ; - - m.b[bmax/32] = (1u << (bmax%32)) ; // set m to be 2^bmax - - d.lshift(bmax); - - for(int b=bmax;b>=0;--b,d.rshift(),m.rshift()) - if(! (r < d)) - { - r -= d ; - q += m ; - } -} - -static void remainder(const uint256_32& n,const uint256_32& p,uint256_32& r) -{ - // simple algorithm: add up multiples of u while keeping below *this. Once done, substract. - - r = n ; - int bmax = n.max_non_zero_bit() - p.max_non_zero_bit(); - - uint256_32 d = p ; - d.lshift(bmax); - - for(int b=bmax;b>=0;--b,d.rshift()) - if(! (r < d)) - r -= d ; -} - -class chacha20_state -{ -public: - uint32_t c[16] ; - - chacha20_state(uint8_t key[32],uint32_t block_counter,uint8_t nounce[12]) - { - c[0] = 0x61707865 ; - c[1] = 0x3320646e ; - c[2] = 0x79622d32 ; - c[3] = 0x6b206574 ; - - c[ 4] = (uint32_t)key[0 ] + (((uint32_t)key[1 ])<<8) + (((uint32_t)key[2 ])<<16) + (((uint32_t)key[3 ])<<24); - c[ 5] = (uint32_t)key[4 ] + (((uint32_t)key[5 ])<<8) + (((uint32_t)key[6 ])<<16) + (((uint32_t)key[7 ])<<24); - c[ 6] = (uint32_t)key[8 ] + (((uint32_t)key[9 ])<<8) + (((uint32_t)key[10])<<16) + (((uint32_t)key[11])<<24); - c[ 7] = (uint32_t)key[12] + (((uint32_t)key[13])<<8) + (((uint32_t)key[14])<<16) + (((uint32_t)key[15])<<24); - c[ 8] = (uint32_t)key[16] + (((uint32_t)key[17])<<8) + (((uint32_t)key[18])<<16) + (((uint32_t)key[19])<<24); - c[ 9] = (uint32_t)key[20] + (((uint32_t)key[21])<<8) + (((uint32_t)key[22])<<16) + (((uint32_t)key[23])<<24); - c[10] = (uint32_t)key[24] + (((uint32_t)key[25])<<8) + (((uint32_t)key[26])<<16) + (((uint32_t)key[27])<<24); - c[11] = (uint32_t)key[28] + (((uint32_t)key[29])<<8) + (((uint32_t)key[30])<<16) + (((uint32_t)key[31])<<24); - - c[12] = block_counter ; - - c[13] = (uint32_t)nounce[0 ] + (((uint32_t)nounce[1 ])<<8) + (((uint32_t)nounce[2 ])<<16) + (((uint32_t)nounce[3 ])<<24); - c[14] = (uint32_t)nounce[4 ] + (((uint32_t)nounce[5 ])<<8) + (((uint32_t)nounce[6 ])<<16) + (((uint32_t)nounce[7 ])<<24); - c[15] = (uint32_t)nounce[8 ] + (((uint32_t)nounce[9 ])<<8) + (((uint32_t)nounce[10])<<16) + (((uint32_t)nounce[11])<<24); - } -}; - -static void quarter_round(uint32_t& a,uint32_t& b,uint32_t& c,uint32_t& d) -{ - a += b ; d ^= a; rotl(d,16) ; //d <<<=16 ; - c += d ; b ^= c; rotl(b,12) ; //b <<<=12 ; - a += b ; d ^= a; rotl(d,8) ; //d <<<=8 ; - c += d ; b ^= c; rotl(b,7) ; //b <<<=7 ; -} - -static void add(chacha20_state& s,const chacha20_state& t) { for(uint32_t i=0;i<16;++i) s.c[i] += t.c[i] ; } - -static void apply_20_rounds(chacha20_state& s) -{ - chacha20_state t(s) ; - - for(uint32_t i=0;i<10;++i) - { - quarter_round(s.c[ 0],s.c[ 4],s.c[ 8],s.c[12]) ; - quarter_round(s.c[ 1],s.c[ 5],s.c[ 9],s.c[13]) ; - quarter_round(s.c[ 2],s.c[ 6],s.c[10],s.c[14]) ; - quarter_round(s.c[ 3],s.c[ 7],s.c[11],s.c[15]) ; - quarter_round(s.c[ 0],s.c[ 5],s.c[10],s.c[15]) ; - quarter_round(s.c[ 1],s.c[ 6],s.c[11],s.c[12]) ; - quarter_round(s.c[ 2],s.c[ 7],s.c[ 8],s.c[13]) ; - quarter_round(s.c[ 3],s.c[ 4],s.c[ 9],s.c[14]) ; - } - - add(s,t) ; -} - -#ifdef DEBUG_CHACHA20 -static void print(const chacha20_state& s) -{ - fprintf(stdout,"%08x %08x %08x %08x\n",s.c[0 ],s.c[1 ],s.c[2 ],s.c[3 ]) ; - fprintf(stdout,"%08x %08x %08x %08x\n",s.c[4 ],s.c[5 ],s.c[6 ],s.c[7 ]) ; - fprintf(stdout,"%08x %08x %08x %08x\n",s.c[8 ],s.c[9 ],s.c[10],s.c[11]) ; - fprintf(stdout,"%08x %08x %08x %08x\n",s.c[12],s.c[13],s.c[14],s.c[15]) ; -} -#endif - -void chacha20_encrypt_rs(uint8_t key[32], uint32_t block_counter, uint8_t nonce[12], uint8_t *data, uint32_t size) -{ - for(uint32_t i=0;i> (8*(k%4))) & 0xff) ; - } -} - -#if OPENSSL_VERSION_NUMBER >= 0x010100000L && !defined(LIBRESSL_VERSION_NUMBER) -void chacha20_encrypt_openssl(uint8_t key[32], uint32_t block_counter, uint8_t nonce[12], uint8_t *data, uint32_t size) -{ - EVP_CIPHER_CTX *ctx; - - int len; - int tmp_len; - uint8_t tmp[size]; - uint8_t iv[16]; - - // create iv with nonce and block counter - memcpy(iv, &block_counter, 4); - memcpy(iv + 4, nonce, 12); - - /* Create and initialise the context */ - if(!(ctx = EVP_CIPHER_CTX_new())) return; - - /* Initialise the encryption operation. IMPORTANT - ensure you use a key - * and IV size appropriate for your cipher - * In this example we are using 256 bit AES (i.e. a 256 bit key). The - * IV size for *most* modes is the same as the block size. For AES this - * is 128 bits */ - if(1 != EVP_EncryptInit_ex(ctx, EVP_chacha20(), NULL, key, iv)) goto out; - - /* Provide the message to be encrypted, and obtain the encrypted output. - * EVP_EncryptUpdate can be called multiple times if necessary - */ - if(1 != EVP_EncryptUpdate(ctx, tmp, &len, data, size)) goto out; - tmp_len = len; - - /* Finalise the encryption. Further ciphertext bytes may be written at - * this stage. - */ - if(1 != EVP_EncryptFinal_ex(ctx, tmp + len, &len)) goto out; - tmp_len += len; - - memcpy(data, tmp, tmp_len); - -out: - /* Clean up */ - EVP_CIPHER_CTX_free(ctx); -} -#endif - -struct poly1305_state -{ - uint256_32 r ; - uint256_32 s ; - uint256_32 p ; - uint256_32 a ; -}; - -static void poly1305_init(poly1305_state& s,uint8_t key[32]) -{ - s.r = uint256_32( 0,0,0,0, - ((uint32_t)key[12] << 0) + ((uint32_t)key[13] << 8) + ((uint32_t)key[14] << 16) + ((uint32_t)key[15] << 24), - ((uint32_t)key[ 8] << 0) + ((uint32_t)key[ 9] << 8) + ((uint32_t)key[10] << 16) + ((uint32_t)key[11] << 24), - ((uint32_t)key[ 4] << 0) + ((uint32_t)key[ 5] << 8) + ((uint32_t)key[ 6] << 16) + ((uint32_t)key[ 7] << 24), - ((uint32_t)key[ 0] << 0) + ((uint32_t)key[ 1] << 8) + ((uint32_t)key[ 2] << 16) + ((uint32_t)key[ 3] << 24) - ); - - s.r.poly1305clamp(); - - s.s = uint256_32( 0,0,0,0, - ((uint32_t)key[28] << 0) + ((uint32_t)key[29] << 8) + ((uint32_t)key[30] << 16) + ((uint32_t)key[31] << 24), - ((uint32_t)key[24] << 0) + ((uint32_t)key[25] << 8) + ((uint32_t)key[26] << 16) + ((uint32_t)key[27] << 24), - ((uint32_t)key[20] << 0) + ((uint32_t)key[21] << 8) + ((uint32_t)key[22] << 16) + ((uint32_t)key[23] << 24), - ((uint32_t)key[16] << 0) + ((uint32_t)key[17] << 8) + ((uint32_t)key[18] << 16) + ((uint32_t)key[19] << 24) - ); - - s.p = uint256_32(0,0,0,0x3,0xffffffff,0xffffffff,0xffffffff,0xfffffffb) ; - s.a = uint256_32(0,0,0, 0, 0, 0, 0, 0) ; -} - -// Warning: each call will automatically *pad* the data to a multiple of 16 bytes. -// -static void poly1305_add(poly1305_state& s,uint8_t *message,uint32_t size,bool pad_to_16_bytes=false) -{ -#ifdef DEBUG_CHACHA20 - std::cerr << "Poly1305: digesting " << RsUtil::BinToHex(message,size) << std::endl; -#endif - - for(uint32_t i=0;i<(size+15)/16;++i) - { - uint256_32 block ; - uint32_t j; - - for(j=0;j<16 && i*16+j < size;++j) - block.b[j/4] += ((uint64_t)message[i*16+j]) << (8*(j & 0x3)) ; - - if(pad_to_16_bytes) - block.b[4] += 0x01 ; - else - block.b[j/4] += 0x01 << (8*(j& 0x3)); - - s.a += block ; - s.a *= s.r ; - - uint256_32 q,rst; - remainder(s.a,s.p,rst) ; - s.a = rst ; - } -} - -static void poly1305_finish(poly1305_state& s,uint8_t tag[16]) -{ - s.a += s.s ; - - tag[ 0] = (s.a.b[0] >> 0) & 0xff ; tag[ 1] = (s.a.b[0] >> 8) & 0xff ; tag[ 2] = (s.a.b[0] >>16) & 0xff ; tag[ 3] = (s.a.b[0] >>24) & 0xff ; - tag[ 4] = (s.a.b[1] >> 0) & 0xff ; tag[ 5] = (s.a.b[1] >> 8) & 0xff ; tag[ 6] = (s.a.b[1] >>16) & 0xff ; tag[ 7] = (s.a.b[1] >>24) & 0xff ; - tag[ 8] = (s.a.b[2] >> 0) & 0xff ; tag[ 9] = (s.a.b[2] >> 8) & 0xff ; tag[10] = (s.a.b[2] >>16) & 0xff ; tag[11] = (s.a.b[2] >>24) & 0xff ; - tag[12] = (s.a.b[3] >> 0) & 0xff ; tag[13] = (s.a.b[3] >> 8) & 0xff ; tag[14] = (s.a.b[3] >>16) & 0xff ; tag[15] = (s.a.b[3] >>24) & 0xff ; -} - -void poly1305_tag(uint8_t key[32],uint8_t *message,uint32_t size,uint8_t tag[16]) -{ - poly1305_state s; - - poly1305_init (s,key); - poly1305_add(s,message,size) ; - poly1305_finish(s,tag); -} - -static void poly1305_key_gen(uint8_t key[32], uint8_t nonce[12], uint8_t generated_key[32]) -{ - uint32_t counter = 0 ; - - chacha20_state s(key,counter,nonce); - apply_20_rounds(s) ; - - for(uint32_t k=0;k<8;++k) - for(uint32_t i=0;i<4;++i) - generated_key[k*4 + i] = (s.c[k] >> 8*i) & 0xff ; -} - -bool constant_time_memory_compare(const uint8_t *m1,const uint8_t *m2,uint32_t size) -{ - return !CRYPTO_memcmp(m1,m2,size) ; -} - -bool AEAD_chacha20_poly1305_rs(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint32_t data_size,uint8_t *aad,uint32_t aad_size,uint8_t tag[16],bool encrypt) -{ - // encrypt + tag. See RFC7539-2.8 - - uint8_t session_key[32]; - poly1305_key_gen(key,nonce,session_key); - - uint8_t lengths_vector[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } ; - - for(uint32_t i=0;i<4;++i) - { - lengths_vector[0+i] = ( aad_size >> (8*i)) & 0xff ; - lengths_vector[8+i] = (data_size >> (8*i)) & 0xff ; - } - - if(encrypt) - { - chacha20_encrypt_rs(key,1,nonce,data,data_size); - - poly1305_state pls ; - - poly1305_init(pls,session_key); - - poly1305_add(pls,aad,aad_size,true); // add and pad the aad - poly1305_add(pls,data,data_size,true); // add and pad the cipher text - poly1305_add(pls,lengths_vector,16,true); // add the lengths - - poly1305_finish(pls,tag); - return true ; - } - else - { - poly1305_state pls ; - uint8_t computed_tag[16]; - - poly1305_init(pls,session_key); - - poly1305_add(pls,aad,aad_size,true); // add and pad the aad - poly1305_add(pls,data,data_size,true); // add and pad the cipher text - poly1305_add(pls,lengths_vector,16,true); // add the lengths - - poly1305_finish(pls,computed_tag); - - // decrypt - - chacha20_encrypt_rs(key,1,nonce,data,data_size); - - return constant_time_memory_compare(tag,computed_tag,16) ; - } -} - -#if OPENSSL_VERSION_NUMBER >= 0x010100000L && !defined(LIBRESSL_VERSION_NUMBER) -#define errorOut {ret = false; goto out;} - -bool AEAD_chacha20_poly1305_openssl(uint8_t key[32], uint8_t nonce[12], uint8_t *data, uint32_t data_size, uint8_t *aad, uint32_t aad_size, uint8_t tag[16], bool encrypt_or_decrypt) -{ - EVP_CIPHER_CTX *ctx; - - bool ret = true; - int len; - const uint8_t tag_len = 16; - int tmp_len; - uint8_t tmp[data_size]; - - /* Create and initialise the context */ - if(!(ctx = EVP_CIPHER_CTX_new())) return false; - - if (encrypt_or_decrypt) { - /* Initialise the encryption operation. */ - if(1 != EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), NULL, NULL, NULL)) errorOut - - /* Initialise key and IV */ - if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce)) errorOut - - /* Provide any AAD data. This can be called zero or more times as - * required - */ - if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_size)) errorOut - - /* Provide the message to be encrypted, and obtain the encrypted output. - * EVP_EncryptUpdate can be called multiple times if necessary - */ - if(1 != EVP_EncryptUpdate(ctx, tmp, &len, data, data_size)) errorOut - tmp_len = len; - - /* Finalise the encryption. Normally ciphertext bytes may be written at - * this stage, but this does not occur in GCM mode - */ - if(1 != EVP_EncryptFinal_ex(ctx, data + len, &len)) errorOut - tmp_len += len; - - /* Get the tag */ - if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag_len, tag)) errorOut - } else { - /* Initialise the decryption operation. */ - if(!EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), NULL, key, nonce)) errorOut - - /* Provide any AAD data. This can be called zero or more times as - * required - */ - if(!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_size)) errorOut - - /* Provide the message to be decrypted, and obtain the plaintext output. - * EVP_DecryptUpdate can be called multiple times if necessary - */ - if(!EVP_DecryptUpdate(ctx, tmp, &len, data, data_size)) errorOut - tmp_len = len; - - /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ - if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, tag)) errorOut - - /* Finalise the decryption. A positive return value indicates success, - * anything else is a failure - the plaintext is not trustworthy. - */ - if(EVP_DecryptFinal_ex(ctx, tmp + len, &len) > 0) { - /* Success */ - tmp_len += len; - ret = true; - } else { - /* Verify failed */ - errorOut - } - } - - memcpy(data, tmp, tmp_len); - -out: - /* Clean up */ - EVP_CIPHER_CTX_free(ctx); - return !!ret; -} - -#undef errorOut -#endif - -bool AEAD_chacha20_sha256(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint32_t data_size,uint8_t *aad,uint32_t aad_size,uint8_t tag[16],bool encrypt) -{ - // encrypt + tag. See RFC7539-2.8 - - if(encrypt) - { -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - chacha20_encrypt_rs(key,1,nonce,data,data_size); -#else - chacha20_encrypt_openssl(key, 1, nonce, data, data_size); -#endif - - uint8_t computed_tag[EVP_MAX_MD_SIZE]; - unsigned int md_size ; - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - HMAC_CTX hmac_ctx ; - HMAC_CTX_init(&hmac_ctx) ; - - HMAC_Init(&hmac_ctx,key,32,EVP_sha256()) ; - HMAC_Update(&hmac_ctx,aad,aad_size) ; - HMAC_Update(&hmac_ctx,data,data_size) ; - HMAC_Final(&hmac_ctx,computed_tag,&md_size) ; - - HMAC_CTX_cleanup(&hmac_ctx) ; -#else - HMAC_CTX *hmac_ctx = HMAC_CTX_new(); - - HMAC_Init_ex(hmac_ctx,key,32,EVP_sha256(),NULL) ; - HMAC_Update(hmac_ctx,aad,aad_size) ; - HMAC_Update(hmac_ctx,data,data_size) ; - HMAC_Final(hmac_ctx,computed_tag,&md_size) ; - - HMAC_CTX_free(hmac_ctx) ; - hmac_ctx=NULL; -#endif - - assert(md_size >= 16); - - memcpy(tag,computed_tag,16) ; - - return true ; - } - else - { - uint8_t computed_tag[EVP_MAX_MD_SIZE]; - unsigned int md_size ; - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - HMAC_CTX hmac_ctx ; - HMAC_CTX_init(&hmac_ctx) ; - - HMAC_Init(&hmac_ctx,key,32,EVP_sha256()) ; - HMAC_Update(&hmac_ctx,aad,aad_size) ; - HMAC_Update(&hmac_ctx,data,data_size) ; - HMAC_Final(&hmac_ctx,computed_tag,&md_size) ; - - HMAC_CTX_cleanup(&hmac_ctx) ; -#else - HMAC_CTX *hmac_ctx = HMAC_CTX_new(); - - HMAC_Init_ex(hmac_ctx,key,32,EVP_sha256(),NULL) ; - HMAC_Update(hmac_ctx,aad,aad_size) ; - HMAC_Update(hmac_ctx,data,data_size) ; - HMAC_Final(hmac_ctx,computed_tag,&md_size) ; - - HMAC_CTX_free(hmac_ctx) ; - hmac_ctx=NULL; -#endif - - // decrypt - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - chacha20_encrypt_rs(key,1,nonce,data,data_size); -#else - chacha20_encrypt_openssl(key, 1, nonce, data, data_size); -#endif - - return constant_time_memory_compare(tag,computed_tag,16) ; - } -} - - -bool perform_tests() -{ - // RFC7539 - 2.1.1 - - std::cerr << " quarter round " ; - - uint32_t a = 0x11111111 ; - uint32_t b = 0x01020304 ; - uint32_t c = 0x9b8d6f43 ; - uint32_t d = 0x01234567 ; - - quarter_round(a,b,c,d) ; - - if(!(a == 0xea2a92f4)) return false ; - if(!(b == 0xcb1cf8ce)) return false ; - if(!(c == 0x4581472e)) return false ; - if(!(d == 0x5881c4bb)) return false ; - - std::cerr << " OK" << std::endl; - - // RFC7539 - 2.3.2 - - std::cerr << " RFC7539 - 2.3.2 " ; - - uint8_t key[32] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b, \ - 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, \ - 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f } ; - uint8_t nounce[12] = { 0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x00 } ; - - chacha20_state s(key,1,nounce) ; - -#ifdef DEBUG_CHACHA20 - print(s) ; -#endif - - apply_20_rounds(s) ; - -#ifdef DEBUG_CHACHA20 - fprintf(stdout,"\n") ; - - print(s) ; -#endif - - uint32_t check_vals[16] = { - 0xe4e7f110, 0x15593bd1, 0x1fdd0f50, 0xc47120a3, - 0xc7f4d1c7, 0x0368c033, 0x9aaa2204, 0x4e6cd4c3, - 0x466482d2, 0x09aa9f07, 0x05d7c214, 0xa2028bd9, - 0xd19c12b5, 0xb94e16de, 0xe883d0cb, 0x4e3c50a2 - }; - - for(uint32_t i=0;i<16;++i) - if(s.c[i] != check_vals[i]) - return false ; - - std::cerr << " OK" << std::endl; - - // RFC7539 - 2.4.2 - - std::cerr << " RFC7539 - 2.4.2 " ; - - uint8_t nounce2[12] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x00 } ; - - uint8_t plaintext[7*16+2] = { - 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, - 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, - 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, - 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, - 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, - 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, - 0x74, 0x2e - }; - - chacha20_encrypt_rs(key,1,nounce2,plaintext,7*16+2) ; - -#ifdef DEBUG_CHACHA20 - fprintf(stdout,"CipherText: \n") ; - - for(uint32_t k=0;k<7*16+2;++k) - { - fprintf(stdout,"%02x ",plaintext[k]) ; - - if( (k % 16) == 15) - fprintf(stdout,"\n") ; - } - fprintf(stdout,"\n") ; -#endif - - uint8_t check_cipher_text[7*16+2] = { - 0x6e, 0x2e, 0x35, 0x9a, 0x25, 0x68, 0xf9, 0x80, 0x41, 0xba, 0x07, 0x28, 0xdd, 0x0d, 0x69, 0x81, - 0xe9, 0x7e, 0x7a, 0xec, 0x1d, 0x43, 0x60, 0xc2, 0x0a, 0x27, 0xaf, 0xcc, 0xfd, 0x9f, 0xae, 0x0b, - 0xf9, 0x1b, 0x65, 0xc5, 0x52, 0x47, 0x33, 0xab, 0x8f, 0x59, 0x3d, 0xab, 0xcd, 0x62, 0xb3, 0x57, - 0x16, 0x39, 0xd6, 0x24, 0xe6, 0x51, 0x52, 0xab, 0x8f, 0x53, 0x0c, 0x35, 0x9f, 0x08, 0x61, 0xd8, - 0x07, 0xca, 0x0d, 0xbf, 0x50, 0x0d, 0x6a, 0x61, 0x56, 0xa3, 0x8e, 0x08, 0x8a, 0x22, 0xb6, 0x5e, - 0x52, 0xbc, 0x51, 0x4d, 0x16, 0xcc, 0xf8, 0x06, 0x81, 0x8c, 0xe9, 0x1a, 0xb7, 0x79, 0x37, 0x36, - 0x5a, 0xf9, 0x0b, 0xbf, 0x74, 0xa3, 0x5b, 0xe6, 0xb4, 0x0b, 0x8e, 0xed, 0xf2, 0x78, 0x5e, 0x42, - 0x87, 0x4d - }; - - for(uint32_t i=0;i<7*16+2;++i) - if(!(check_cipher_text[i] == plaintext[i] )) - return false; - - std::cerr << " OK" << std::endl; - - // operators - - { uint256_32 uu(0,0,0,0,0,0,0,0 ) ; ++uu ; if(!(uu == uint256_32(0,0,0,0,0,0,0,1))) return false ; } - { uint256_32 uu(0,0,0,0,0,0,0,0xffffffff) ; ++uu ; if(!(uu == uint256_32(0,0,0,0,0,0,1,0))) return false ; } - { uint256_32 uu(0,0,0,0,0,0,0,0) ; uu = ~uu;++uu ; if(!(uu == uint256_32(0,0,0,0,0,0,0,0))) return false ; } - - std::cerr << " operator++ on 256bits numbers OK" << std::endl; - - // sums/diffs of numbers - - for(uint32_t i=0;i<100;++i) - { - uint256_32 a = uint256_32::random() ; - uint256_32 b = uint256_32::random() ; -#ifdef DEBUG_CHACHA20 - fprintf(stdout,"Adding ") ; - uint256_32::print(a) ; - fprintf(stdout,"\n to ") ; - uint256_32::print(b) ; -#endif - - uint256_32 c(a) ; - if(!(c == a) ) - return false; - - c += b ; - -#ifdef DEBUG_CHACHA20 - fprintf(stdout,"\n found ") ; - uint256_32::print(c) ; -#endif - - c -= b ; - -#ifdef DEBUG_CHACHA20 - fprintf(stdout,"\n subst ") ; - uint256_32::print(c) ; - fprintf(stdout,"\n") ; -#endif - - if(!(a == a)) return false ; - if(!(c == a)) return false ; - - uint256_32 vv(0,0,0,0,0,0,0,1) ; - vv -= a ; - vv += a ; - - if(!(vv == uint256_32(0,0,0,0,0,0,0,1))) return false ; - - } - uint256_32 vv(0,0,0,0,0,0,0,0) ; - uint256_32 ww(0,0,0,0,0,0,0,1) ; - vv -= ww ; - if(!(vv == ~uint256_32(0,0,0,0,0,0,0,0))) return false; - - std::cerr << " Sums / diffs of 256bits numbers OK" << std::endl; - - // check that (a-b)*(c-d) = ac - bc - ad + bd - - for(uint32_t i=0;i<100;++i) - { - uint256_32 a = uint256_32::random(); - uint256_32 b = uint256_32::random(); - uint256_32 c = uint256_32::random(); - uint256_32 d = uint256_32::random(); - - uint256_32 amb(a) ; - amb -= b; - uint256_32 cmd(c) ; - cmd -= d; - uint256_32 ambtcmd(amb); - ambtcmd *= cmd ; - - uint256_32 atc(a) ; atc *= c ; - uint256_32 btc(b) ; btc *= c ; - uint256_32 atd(a) ; atd *= d ; - uint256_32 btd(b) ; btd *= d ; - - uint256_32 atcmbtcmatdpbtd(atc) ; - atcmbtcmatdpbtd -= btc ; - atcmbtcmatdpbtd -= atd ; - atcmbtcmatdpbtd += btd ; - - if(!(atcmbtcmatdpbtd == ambtcmd)) return false ; - } - std::cerr << " (a-b)*(c-d) == ac-bc-ad+bd on random OK" << std::endl; - - // shifts - - for(uint32_t i=0;i<100;++i) - { - uint256_32 x = uint256_32::random(); - uint256_32 y(x) ; - - uint32_t r = x.b[0] & 0x1 ; - x.rshift() ; - x.lshift() ; - - x.b[0] += r ; - - if(!(x == y) ) return false ; - } - std::cerr << " left/right shifting OK" << std::endl; - - // test modulo by computing modulo and recomputing the product. - - for(uint32_t i=0;i<100;++i) - { - uint256_32 q1(0,0,0,0,0,0,0,0),r1(0,0,0,0,0,0,0,0) ; - - uint256_32 n1 = uint256_32::random(); - uint256_32 p1 = uint256_32::random(); - - if(RSRandom::random_f32() < 0.2) - { - p1.b[7] = 0 ; - - if(RSRandom::random_f32() < 0.1) - p1.b[6] = 0 ; - } - - quotient(n1,p1,q1,r1) ; -#ifdef DEBUG_CHACHA20 - fprintf(stdout,"result: q=") ; uint256_32::print(q1) ; fprintf(stdout," r=") ; uint256_32::print(r1) ; fprintf(stdout,"\n") ; -#endif - - //uint256_32 res(q1) ; - q1 *= p1 ; - q1 += r1 ; - - if(!(q1 == n1)) return false ; - } - std::cerr << " Quotient/modulo on random numbers OK" << std::endl; - - // RFC7539 - 2.5 - // - { - uint8_t key[32] = { 0x85,0xd6,0xbe,0x78,0x57,0x55,0x6d,0x33,0x7f,0x44,0x52,0xfe,0x42,0xd5,0x06,0xa8,0x01,0x03,0x80,0x8a,0xfb,0x0d,0xb2,0xfd,0x4a,0xbf,0xf6,0xaf,0x41,0x49,0xf5,0x1b } ; - uint8_t tag[16] ; - std::string msg("Cryptographic Forum Research Group") ; - - poly1305_tag(key,(uint8_t*)msg.c_str(),msg.length(),tag) ; - - uint8_t test_tag[16] = { 0xa8,0x06,0x1d,0xc1,0x30,0x51,0x36,0xc6,0xc2,0x2b,0x8b,0xaf,0x0c,0x01,0x27,0xa9 }; - - if(!(constant_time_memory_compare(tag,test_tag,16))) return false ; - } - std::cerr << " RFC7539 - 2.5 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #1 - // - { - uint8_t key[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - uint8_t tag[16] ; - uint8_t text[64] ; - memset(text,0,64) ; - - poly1305_tag(key,text,64,tag) ; - - uint8_t test_tag[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #001 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #2 - // - { - uint8_t key[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x36,0xe5,0xf6,0xb5,0xc5,0xe0,0x60,0x70,0xf0,0xef,0xca,0x96,0x22,0x7a,0x86,0x3e } ; - uint8_t tag[16] ; - - std::string msg("Any submission to the IETF intended by the Contributor for publication as all or part of an IETF Internet-Draft or RFC and any statement made within the context of an IETF activity is considered an \"IETF Contribution\". Such statements include oral statements in IETF sessions, as well as written and electronic communications made at any time or place, which are addressed to") ; - - poly1305_tag(key,(uint8_t*)msg.c_str(),msg.length(),tag) ; - - uint8_t test_tag[16] = { 0x36,0xe5,0xf6,0xb5,0xc5,0xe0,0x60,0x70,0xf0,0xef,0xca,0x96,0x22,0x7a,0x86,0x3e }; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #002 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #3 - // - { - uint8_t key[32] = { 0x36,0xe5,0xf6,0xb5,0xc5,0xe0,0x60,0x70,0xf0,0xef,0xca,0x96,0x22,0x7a,0x86,0x3e, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - uint8_t tag[16] ; - - std::string msg("Any submission to the IETF intended by the Contributor for publication as all or part of an IETF Internet-Draft or RFC and any statement made within the context of an IETF activity is considered an \"IETF Contribution\". Such statements include oral statements in IETF sessions, as well as written and electronic communications made at any time or place, which are addressed to") ; - - poly1305_tag(key,(uint8_t*)msg.c_str(),msg.length(),tag) ; - - uint8_t test_tag[16] = { 0xf3,0x47,0x7e,0x7c,0xd9,0x54,0x17,0xaf,0x89,0xa6,0xb8,0x79,0x4c,0x31,0x0c,0xf0 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #003 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #4 - // - { - uint8_t key[32] = { 0x1c ,0x92 ,0x40 ,0xa5 ,0xeb ,0x55 ,0xd3 ,0x8a ,0xf3 ,0x33 ,0x88 ,0x86 ,0x04 ,0xf6 ,0xb5 ,0xf0, - 0x47 ,0x39 ,0x17 ,0xc1 ,0x40 ,0x2b ,0x80 ,0x09 ,0x9d ,0xca ,0x5c ,0xbc ,0x20 ,0x70 ,0x75 ,0xc0 }; - uint8_t tag[16] ; - - std::string msg("'Twas brillig, and the slithy toves\nDid gyre and gimble in the wabe:\nAll mimsy were the borogoves,\nAnd the mome raths outgrabe.") ; - - poly1305_tag(key,(uint8_t*)msg.c_str(),msg.length(),tag) ; - - uint8_t test_tag[16] = { 0x45,0x41,0x66,0x9a,0x7e,0xaa,0xee,0x61,0xe7,0x08,0xdc,0x7c,0xbc,0xc5,0xeb,0x62 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #004 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #5 - // - { - uint8_t key[32] = { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t tag[16] ; - - uint8_t msg[] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; - - poly1305_tag(key,msg,16,tag) ; - - uint8_t test_tag[16] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #005 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #6 - // - { - uint8_t key[32] = { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; - uint8_t tag[16] ; - - uint8_t msg[16] = { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - - poly1305_tag(key,msg,16,tag) ; - - uint8_t test_tag[16] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #006 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #7 - // - { - uint8_t key[32] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t tag[16] ; - - uint8_t msg[48] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - poly1305_tag(key,msg,48,tag) ; - - uint8_t test_tag[16] = { 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #007 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #8 - // - { - uint8_t key[32] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t tag[16] ; - - uint8_t msg[48] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xfb,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe, - 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 } ; - - poly1305_tag(key,msg,48,tag) ; - - uint8_t test_tag[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #008 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #9 - // - { - uint8_t key[32] = { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t tag[16] ; - - uint8_t msg[16] = { 0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff } ; - - poly1305_tag(key,msg,16,tag) ; - - uint8_t test_tag[16] = { 0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #009 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #10 - // - { - uint8_t key[32] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t tag[16] ; - - uint8_t msg[64] = { - 0xE3 ,0x35 ,0x94 ,0xD7 ,0x50 ,0x5E ,0x43 ,0xB9 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, - 0x33 ,0x94 ,0xD7 ,0x50 ,0x5E ,0x43 ,0x79 ,0xCD ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, - 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, - 0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 }; - - poly1305_tag(key,msg,64,tag) ; - - uint8_t test_tag[16] = { 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #010 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #11 - // - { - uint8_t key[32] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t tag[16] ; - - uint8_t msg[48] = { - 0xE3 ,0x35 ,0x94 ,0xD7 ,0x50 ,0x5E ,0x43 ,0xB9 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, - 0x33 ,0x94 ,0xD7 ,0x50 ,0x5E ,0x43 ,0x79 ,0xCD ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, - 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 } ; - - poly1305_tag(key,msg,48,tag) ; - - uint8_t test_tag[16] = { 0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - if(!constant_time_memory_compare(tag,test_tag,16)) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #011 OK" << std::endl; - - // RFC7539 - 2.6.2 - // - { - uint8_t key[32] = { 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f }; - - uint8_t session_key[32] ; - uint8_t test_session_key[32] = { 0x8a,0xd5,0xa0,0x8b,0x90,0x5f,0x81,0xcc,0x81,0x50,0x40,0x27,0x4a,0xb2,0x94,0x71, - 0xa8,0x33,0xb6,0x37,0xe3,0xfd,0x0d,0xa5,0x08,0xdb,0xb8,0xe2,0xfd,0xd1,0xa6,0x46 }; - - uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }; - - poly1305_key_gen(key,nonce,session_key) ; - - if(!constant_time_memory_compare(session_key,test_session_key,32)) return false ; - } - std::cerr << " RFC7539 - 2.6.2 OK" << std::endl; - - // RFC7539 - Poly1305 key generation. Test vector #1 - // - { - uint8_t key[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - - uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t session_key[32] ; - uint8_t test_session_key[32] = { 0x76,0xb8,0xe0,0xad,0xa0,0xf1,0x3d,0x90,0x40,0x5d,0x6a,0xe5,0x53,0x86,0xbd,0x28, - 0xbd,0xd2,0x19,0xb8,0xa0,0x8d,0xed,0x1a,0xa8,0x36,0xef,0xcc,0x8b,0x77,0x0d,0xc7 }; - - poly1305_key_gen(key,nonce,session_key) ; - - if(!constant_time_memory_compare(session_key,test_session_key,32)) return false ; - } - std::cerr << " RFC7539 poly1305 key gen. TVec #1 OK" << std::endl; - - // RFC7539 - Poly1305 key generation. Test vector #2 - // - { - uint8_t key[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 }; - - uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 }; - uint8_t session_key[32] ; - uint8_t test_session_key[32] = { 0xec,0xfa,0x25,0x4f,0x84,0x5f,0x64,0x74,0x73,0xd3,0xcb,0x14,0x0d,0xa9,0xe8,0x76, - 0x06,0xcb,0x33,0x06,0x6c,0x44,0x7b,0x87,0xbc,0x26,0x66,0xdd,0xe3,0xfb,0xb7,0x39 }; - - - - poly1305_key_gen(key,nonce,session_key) ; - - if(!constant_time_memory_compare(session_key,test_session_key,32)) return false ; - } - std::cerr << " RFC7539 poly1305 key gen. TVec #2 OK" << std::endl; - - // RFC7539 - Poly1305 key generation. Test vector #3 - // - { - uint8_t key[32] = { 0x1c,0x92,0x40,0xa5,0xeb,0x55,0xd3,0x8a,0xf3,0x33,0x88,0x86,0x04,0xf6,0xb5,0xf0, - 0x47,0x39,0x17,0xc1,0x40,0x2b,0x80,0x09,0x9d,0xca,0x5c,0xbc,0x20,0x70,0x75,0xc0 }; - - uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 }; - uint8_t session_key[32] ; - uint8_t test_session_key[32] = { 0x96,0x5e,0x3b,0xc6,0xf9,0xec,0x7e,0xd9,0x56,0x08,0x08,0xf4,0xd2,0x29,0xf9,0x4b, - 0x13,0x7f,0xf2,0x75,0xca,0x9b,0x3f,0xcb,0xdd,0x59,0xde,0xaa,0xd2,0x33,0x10,0xae }; - - poly1305_key_gen(key,nonce,session_key) ; - - if(!constant_time_memory_compare(session_key,test_session_key,32)) return false ; - } - std::cerr << " RFC7539 poly1305 key gen. TVec #3 OK" << std::endl; - - // RFC7539 - 2.8.2 - // - { - uint8_t msg[7*16+2] = { - 0x4c,0x61,0x64,0x69,0x65,0x73,0x20,0x61,0x6e,0x64,0x20,0x47,0x65,0x6e,0x74,0x6c, - 0x65,0x6d,0x65,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x6c,0x61,0x73, - 0x73,0x20,0x6f,0x66,0x20,0x27,0x39,0x39,0x3a,0x20,0x49,0x66,0x20,0x49,0x20,0x63, - 0x6f,0x75,0x6c,0x64,0x20,0x6f,0x66,0x66,0x65,0x72,0x20,0x79,0x6f,0x75,0x20,0x6f, - 0x6e,0x6c,0x79,0x20,0x6f,0x6e,0x65,0x20,0x74,0x69,0x70,0x20,0x66,0x6f,0x72,0x20, - 0x74,0x68,0x65,0x20,0x66,0x75,0x74,0x75,0x72,0x65,0x2c,0x20,0x73,0x75,0x6e,0x73, - 0x63,0x72,0x65,0x65,0x6e,0x20,0x77,0x6f,0x75,0x6c,0x64,0x20,0x62,0x65,0x20,0x69, - 0x74,0x2e } ; - - uint8_t test_msg[7*16+2] = { - 0xd3,0x1a,0x8d,0x34,0x64,0x8e,0x60,0xdb,0x7b,0x86,0xaf,0xbc,0x53,0xef,0x7e,0xc2, - 0xa4,0xad,0xed,0x51,0x29,0x6e,0x08,0xfe,0xa9,0xe2,0xb5,0xa7,0x36,0xee,0x62,0xd6, - 0x3d,0xbe,0xa4,0x5e,0x8c,0xa9,0x67,0x12,0x82,0xfa,0xfb,0x69,0xda,0x92,0x72,0x8b, - 0x1a,0x71,0xde,0x0a,0x9e,0x06,0x0b,0x29,0x05,0xd6,0xa5,0xb6,0x7e,0xcd,0x3b,0x36, - 0x92,0xdd,0xbd,0x7f,0x2d,0x77,0x8b,0x8c,0x98,0x03,0xae,0xe3,0x28,0x09,0x1b,0x58, - 0xfa,0xb3,0x24,0xe4,0xfa,0xd6,0x75,0x94,0x55,0x85,0x80,0x8b,0x48,0x31,0xd7,0xbc, - 0x3f,0xf4,0xde,0xf0,0x8e,0x4b,0x7a,0x9d,0xe5,0x76,0xd2,0x65,0x86,0xce,0xc6,0x4b, - 0x61,0x16 }; - - uint8_t aad[12] = { 0x50,0x51,0x52,0x53,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7 }; - uint8_t nonce[12] = { 0x07,0x00,0x00,0x00,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47 }; - - uint8_t key[32] = { 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f }; - uint8_t tag[16] ; - uint8_t test_tag[16] = { 0x1a,0xe1,0x0b,0x59,0x4f,0x09,0xe2,0x6a,0x7e,0x90,0x2e,0xcb,0xd0,0x60,0x06,0x91 }; - - AEAD_chacha20_poly1305_rs(key,nonce,msg,7*16+2,aad,12,tag,true) ; - - if(!constant_time_memory_compare(msg,test_msg,7*16+2)) return false ; - if(!constant_time_memory_compare(tag,test_tag,16)) return false ; - - bool res = AEAD_chacha20_poly1305_rs(key,nonce,msg,7*16+2,aad,12,tag,false) ; - - if(!res) return false ; - } - std::cerr << " RFC7539 - 2.8.2 OK" << std::endl; - - - // RFC7539 - AEAD checking and decryption - // - { - uint8_t key[32] = { 0x1c,0x92,0x40,0xa5,0xeb,0x55,0xd3,0x8a,0xf3,0x33,0x88,0x86,0x04,0xf6,0xb5,0xf0, - 0x47,0x39,0x17,0xc1,0x40,0x2b,0x80,0x09,0x9d,0xca,0x5c,0xbc,0x20,0x70,0x75,0xc0 }; - - uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 }; - - uint8_t ciphertext[16*16 + 9] = { - 0x64,0xa0,0x86,0x15,0x75,0x86,0x1a,0xf4,0x60,0xf0,0x62,0xc7,0x9b,0xe6,0x43,0xbd, - 0x5e,0x80,0x5c,0xfd,0x34,0x5c,0xf3,0x89,0xf1,0x08,0x67,0x0a,0xc7,0x6c,0x8c,0xb2, - 0x4c,0x6c,0xfc,0x18,0x75,0x5d,0x43,0xee,0xa0,0x9e,0xe9,0x4e,0x38,0x2d,0x26,0xb0, - 0xbd,0xb7,0xb7,0x3c,0x32,0x1b,0x01,0x00,0xd4,0xf0,0x3b,0x7f,0x35,0x58,0x94,0xcf, - 0x33,0x2f,0x83,0x0e,0x71,0x0b,0x97,0xce,0x98,0xc8,0xa8,0x4a,0xbd,0x0b,0x94,0x81, - 0x14,0xad,0x17,0x6e,0x00,0x8d,0x33,0xbd,0x60,0xf9,0x82,0xb1,0xff,0x37,0xc8,0x55, - 0x97,0x97,0xa0,0x6e,0xf4,0xf0,0xef,0x61,0xc1,0x86,0x32,0x4e,0x2b,0x35,0x06,0x38, - 0x36,0x06,0x90,0x7b,0x6a,0x7c,0x02,0xb0,0xf9,0xf6,0x15,0x7b,0x53,0xc8,0x67,0xe4, - 0xb9,0x16,0x6c,0x76,0x7b,0x80,0x4d,0x46,0xa5,0x9b,0x52,0x16,0xcd,0xe7,0xa4,0xe9, - 0x90,0x40,0xc5,0xa4,0x04,0x33,0x22,0x5e,0xe2,0x82,0xa1,0xb0,0xa0,0x6c,0x52,0x3e, - 0xaf,0x45,0x34,0xd7,0xf8,0x3f,0xa1,0x15,0x5b,0x00,0x47,0x71,0x8c,0xbc,0x54,0x6a, - 0x0d,0x07,0x2b,0x04,0xb3,0x56,0x4e,0xea,0x1b,0x42,0x22,0x73,0xf5,0x48,0x27,0x1a, - 0x0b,0xb2,0x31,0x60,0x53,0xfa,0x76,0x99,0x19,0x55,0xeb,0xd6,0x31,0x59,0x43,0x4e, - 0xce,0xbb,0x4e,0x46,0x6d,0xae,0x5a,0x10,0x73,0xa6,0x72,0x76,0x27,0x09,0x7a,0x10, - 0x49,0xe6,0x17,0xd9,0x1d,0x36,0x10,0x94,0xfa,0x68,0xf0,0xff,0x77,0x98,0x71,0x30, - 0x30,0x5b,0xea,0xba,0x2e,0xda,0x04,0xdf,0x99,0x7b,0x71,0x4d,0x6c,0x6f,0x2c,0x29, - 0xa6,0xad,0x5c,0xb4,0x02,0x2b,0x02,0x70,0x9b }; - - uint8_t aad[12] = { 0xf3,0x33,0x88,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x4e,0x91 }; - - uint8_t received_tag[16] = { 0xee,0xad,0x9d,0x67,0x89,0x0c,0xbb,0x22,0x39,0x23,0x36,0xfe,0xa1,0x85,0x1f,0x38 }; - - if(!AEAD_chacha20_poly1305_rs(key,nonce,ciphertext,16*16+9,aad,12,received_tag,false)) - return false ; - - uint8_t cleartext[16*16+9] = { - 0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x2d,0x44,0x72,0x61,0x66,0x74,0x73,0x20, - 0x61,0x72,0x65,0x20,0x64,0x72,0x61,0x66,0x74,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65, - 0x6e,0x74,0x73,0x20,0x76,0x61,0x6c,0x69,0x64,0x20,0x66,0x6f,0x72,0x20,0x61,0x20, - 0x6d,0x61,0x78,0x69,0x6d,0x75,0x6d,0x20,0x6f,0x66,0x20,0x73,0x69,0x78,0x20,0x6d, - 0x6f,0x6e,0x74,0x68,0x73,0x20,0x61,0x6e,0x64,0x20,0x6d,0x61,0x79,0x20,0x62,0x65, - 0x20,0x75,0x70,0x64,0x61,0x74,0x65,0x64,0x2c,0x20,0x72,0x65,0x70,0x6c,0x61,0x63, - 0x65,0x64,0x2c,0x20,0x6f,0x72,0x20,0x6f,0x62,0x73,0x6f,0x6c,0x65,0x74,0x65,0x64, - 0x20,0x62,0x79,0x20,0x6f,0x74,0x68,0x65,0x72,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65, - 0x6e,0x74,0x73,0x20,0x61,0x74,0x20,0x61,0x6e,0x79,0x20,0x74,0x69,0x6d,0x65,0x2e, - 0x20,0x49,0x74,0x20,0x69,0x73,0x20,0x69,0x6e,0x61,0x70,0x70,0x72,0x6f,0x70,0x72, - 0x69,0x61,0x74,0x65,0x20,0x74,0x6f,0x20,0x75,0x73,0x65,0x20,0x49,0x6e,0x74,0x65, - 0x72,0x6e,0x65,0x74,0x2d,0x44,0x72,0x61,0x66,0x74,0x73,0x20,0x61,0x73,0x20,0x72, - 0x65,0x66,0x65,0x72,0x65,0x6e,0x63,0x65,0x20,0x6d,0x61,0x74,0x65,0x72,0x69,0x61, - 0x6c,0x20,0x6f,0x72,0x20,0x74,0x6f,0x20,0x63,0x69,0x74,0x65,0x20,0x74,0x68,0x65, - 0x6d,0x20,0x6f,0x74,0x68,0x65,0x72,0x20,0x74,0x68,0x61,0x6e,0x20,0x61,0x73,0x20, - 0x2f,0xe2,0x80,0x9c,0x77,0x6f,0x72,0x6b,0x20,0x69,0x6e,0x20,0x70,0x72,0x6f,0x67, - 0x72,0x65,0x73,0x73,0x2e,0x2f,0xe2,0x80,0x9d } ; - - if(!constant_time_memory_compare(cleartext,ciphertext,16*16+9)) - return false ; - } - std::cerr << " RFC7539 AEAD test vector #1 OK" << std::endl; - - // bandwidth test - // - - { - uint32_t SIZE = 1*1024*1024 ; - uint8_t *ten_megabyte_data = (uint8_t*)malloc(SIZE) ; - - memset(ten_megabyte_data,0x37,SIZE) ; // put something. We dont really care here. - - uint8_t key[32] = { 0x1c,0x92,0x40,0xa5,0xeb,0x55,0xd3,0x8a,0xf3,0x33,0x88,0x86,0x04,0xf6,0xb5,0xf0, - 0x47,0x39,0x17,0xc1,0x40,0x2b,0x80,0x09,0x9d,0xca,0x5c,0xbc,0x20,0x70,0x75,0xc0 }; - - uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 }; - uint8_t aad[12] = { 0xf3,0x33,0x88,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x4e,0x91 }; - - uint8_t received_tag[16] ; - - { - rstime::RsScopeTimer s("AEAD1") ; - chacha20_encrypt_rs(key, 1, nonce, ten_megabyte_data,SIZE) ; - - std::cerr << " Chacha20 encryption speed : " << SIZE / (1024.0*1024.0) / s.duration() << " MB/s" << std::endl; - } - { - rstime::RsScopeTimer s("AEAD2") ; - AEAD_chacha20_poly1305_rs(key,nonce,ten_megabyte_data,SIZE,aad,12,received_tag,true) ; - - std::cerr << " AEAD/poly1305 own encryption speed : " << SIZE / (1024.0*1024.0) / s.duration() << " MB/s" << std::endl; - } -#if OPENSSL_VERSION_NUMBER >= 0x010100000L && !defined(LIBRESSL_VERSION_NUMBER) - { - rstime::RsScopeTimer s("AEAD3") ; - AEAD_chacha20_poly1305_openssl(key,nonce,ten_megabyte_data,SIZE,aad,12,received_tag,true) ; - - std::cerr << " AEAD/poly1305 openssl encryption speed: " << SIZE / (1024.0*1024.0) / s.duration() << " MB/s" << std::endl; - } -#endif - { - rstime::RsScopeTimer s("AEAD4") ; - AEAD_chacha20_sha256(key,nonce,ten_megabyte_data,SIZE,aad,12,received_tag,true) ; - - std::cerr << " AEAD/sha256 encryption speed : " << SIZE / (1024.0*1024.0) / s.duration() << " MB/s" << std::endl; - } - - free(ten_megabyte_data) ; - } - - return true; -} - -} -} - - diff --git a/libretroshare/src/crypto/chacha20.h b/libretroshare/src/crypto/chacha20.h deleted file mode 100644 index 1b19a1402..000000000 --- a/libretroshare/src/crypto/chacha20.h +++ /dev/null @@ -1,113 +0,0 @@ -/******************************************************************************* - * libretroshare/src/crypto: chacha20.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * 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 . * - * * - *******************************************************************************/ - -#include - -namespace librs -{ - namespace crypto - { - /*! - * \brief chacha20_encrypt - * Performs in place encryption/decryption of the supplied data, using chacha20, using the supplied key and nonce. - * - * \param key secret encryption key. *Should never* be re-used. - * \param block_counter any integer. 0 is fine. - * \param nonce acts as an initialzation vector. /!\ it is extremely important to make sure that this nounce *is* everytime different. Using a purely random value is fine. - * \param data data that gets encrypted/decrypted in place - * \param size size of the data. - */ - void chacha20_encrypt(uint8_t key[32], uint32_t block_counter, uint8_t nonce[12], uint8_t *data, uint32_t size) ; - - /*! - * \brief poly1305_tag - * Computes an authentication tag for the supplied data, using the given secret key. - * \param key secret key. *Should not* be used multiple times. - * \param message message to generate a tag for - * \param size size of the message - * \param tag place where the tag is stored. - */ - - void poly1305_tag(uint8_t key[32],uint8_t *message,uint32_t size,uint8_t tag[16]); - - /*! - * \brief AEAD_chacha20_poly1305 - * Provides in-place authenticated encryption using the AEAD construction as described in RFC7539. - * The data is first encrypted in place then 16-padded and concatenated to its size, than concatenated to the - * 16-padded AAD (additional authenticated data) and its size, authenticated using poly1305. - * - * \param key key that is used to derive a one time secret key for poly1305 and that is also used to encrypt the data - * \param nonce nonce. *Should be unique* in order to make the chacha20 stream cipher unique. - * \param data data that is encrypted/decrypted in place. - * \param size size of the data - * \param aad additional authenticated data. Can be used to authenticate the nonce. - * \param aad_size - * \param tag generated poly1305 tag. - * \param encrypt true to encrypt, false to decrypt and check the tag. - * \return - * always true for encryption. - * authentication result for decryption. data is *always* xored to the cipher stream whatever the authentication result is. - */ - bool AEAD_chacha20_poly1305(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint32_t data_size,uint8_t *aad,uint32_t aad_size,uint8_t tag[16],bool encrypt_or_decrypt) ; - - /*! - * \brief AEAD_chacha20_sha256 - * Provides authenticated encryption using a simple construction that associates chacha20 encryption with HMAC authentication using - * the same 32 bytes key. The authenticated tag is the 16 first bytes of the sha256 HMAC. - * - * \param key encryption/authentication key - * \param nonce nonce. *Should be unique* in order to make chacha20 stream cipher unique. - * \param data data that is encrypted/decrypted in place - * \param data_size size of data to encrypt/authenticate - * \param aad additional authenticated data. Can be used to authenticate the nonce. - * \param aad_size - * \param tag 16 bytes authentication tag result - * \param encrypt true to encrypt, false to decrypt and check the tag. - * \return - * always true for encryption. - * authentication result for decryption. data is *always* xored to the cipher stream whatever the authentication result is. - */ - bool AEAD_chacha20_sha256(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint32_t data_size,uint8_t *aad,uint32_t aad_size,uint8_t tag[16],bool encrypt_or_decrypt) ; - - /*! - * \brief constant_time_memcmp - * Provides a constant time comparison of two memory chunks. Calls CRYPTO_memcmp. - * - * \param m1 memory block 1 - * \param m2 memory block 2 - * \param size common size of m1 and m2 - * \return - * false if the two chunks are different - * true if the two chunks are identical - */ - bool constant_time_memory_compare(const uint8_t *m1,const uint8_t *m2,uint32_t size) ; - - /*! - * \brief perform_tests - * Tests all methods in this class, using the tests supplied in RFC7539 - * \return - * true is all tests pass - */ - - bool perform_tests() ; - } -} diff --git a/libretroshare/src/crypto/hashstream.cc b/libretroshare/src/crypto/hashstream.cc deleted file mode 100644 index 1d3c46b75..000000000 --- a/libretroshare/src/crypto/hashstream.cc +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - * libretroshare/src/crypto: hashstream.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#include "hashstream.h" - -#include -#include -#include -#include - -namespace librs -{ - namespace crypto - { - HashStream::HashStream(HashType t) - { - assert(t == SHA1) ; - - mdctx = EVP_MD_CTX_create(); - EVP_DigestInit_ex(mdctx,EVP_sha1(),NULL); - } - HashStream::~HashStream() - { - if(mdctx) - EVP_MD_CTX_destroy(mdctx) ; - } - - Sha1CheckSum HashStream::hash() - { - uint8_t h[EVP_MAX_MD_SIZE] ; - unsigned int len; - EVP_DigestFinal_ex(mdctx,h,&len) ; - - EVP_MD_CTX_destroy(mdctx) ; - mdctx=NULL ; - - return Sha1CheckSum(h); - } - - template<> - HashStream& operator<<(HashStream& u,const std::string& s) - { - EVP_DigestUpdate(u.mdctx,s.c_str(),s.length()) ; - return u; - } - template<> - HashStream& operator<<(HashStream& u,const uint64_t& n) - { - unsigned char mem[8] ; - uint64_t s(n); - for(int i=0;i<8;++i) - { - mem[i] = (uint8_t)s; - s <<= 8 ; - } - - EVP_DigestUpdate(u.mdctx,mem,8); - return u; - } - template<> - HashStream& operator<<(HashStream& u,const uint32_t& n) - { - unsigned char mem[4] ; - uint64_t s(n); - for(int i=0;i<4;++i) - { - mem[i] = (uint8_t)s; - s <<= 8 ; - } - - EVP_DigestUpdate(u.mdctx,mem,4); - return u; - } - template<> - HashStream& operator<<(HashStream& u,const uint8_t& n) - { - EVP_DigestUpdate(u.mdctx,&n,1); - return u; - } - - } -} diff --git a/libretroshare/src/crypto/hashstream.h b/libretroshare/src/crypto/hashstream.h deleted file mode 100644 index b303b6509..000000000 --- a/libretroshare/src/crypto/hashstream.h +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * libretroshare/src/crypto: hashstream.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -namespace librs -{ - namespace crypto - { - // Forward declare the class - class HashStream; - // Forward declare the template operator - template HashStream& operator<<(HashStream& u, const T&); - - class HashStream - { - public: - enum HashType { UNKNOWN = 0x00, - SHA1 = 0x01 - }; - - HashStream(HashType t); - ~HashStream(); - - Sha1CheckSum hash() ; - - template friend HashStream& operator<<(HashStream& u, const T&) ; - - template - friend HashStream& operator<<(HashStream& u, const t_RsGenericIdType& r) - { - EVP_DigestUpdate(u.mdctx, r.toByteArray(), ID_SIZE_IN_BYTES); - return u; - } - private: - EVP_MD_CTX *mdctx ; - }; - } -} diff --git a/libretroshare/src/crypto/rsaes.cc b/libretroshare/src/crypto/rsaes.cc deleted file mode 100644 index d5ad2c7a0..000000000 --- a/libretroshare/src/crypto/rsaes.cc +++ /dev/null @@ -1,144 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsaes.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2013 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include -#include - -#include "rsaes.h" - -uint32_t RsAES::get_buffer_size(uint32_t n) -{ - return n + AES_BLOCK_SIZE ; -} - -bool RsAES::aes_crypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key_data[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) -{ - int nrounds = 5; - uint8_t key[32], iv[32]; - - /* - * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material. - * nrounds is the number of times the we hash the material. More rounds are more secure but - * slower. - */ - int i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, 16, nrounds, key, iv); - - if (i != 32) - { - printf("Key size is %d bits - should be 256 bits\n", i); - return false ; - } - - EVP_CIPHER_CTX *e_ctx = EVP_CIPHER_CTX_new(); - EVP_EncryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv); - - /* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes */ - int c_len = input_data_length + AES_BLOCK_SIZE ; - int f_len = 0; - - if(output_data_length < (uint32_t)c_len) - { - EVP_CIPHER_CTX_free(e_ctx) ; - return false ; - } - - /* update ciphertext, c_len is filled with the length of ciphertext generated, - *len is the size of plaintext in bytes */ - - if(!EVP_EncryptUpdate(e_ctx, output_data, &c_len, input_data, input_data_length)) - { - std::cerr << "RsAES: decryption failed at end. Check padding." << std::endl; - EVP_CIPHER_CTX_free(e_ctx) ; - return false ; - } - - /* update ciphertext with the final remaining bytes */ - if(!EVP_EncryptFinal_ex(e_ctx, output_data+c_len, &f_len)) - { - std::cerr << "RsAES: decryption failed at end. Check padding." << std::endl; - EVP_CIPHER_CTX_free(e_ctx) ; - return false ; - } - - output_data_length = c_len + f_len; - - EVP_CIPHER_CTX_free(e_ctx) ; - return true; -} - -bool RsAES::aes_decrypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key_data[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) -{ - int nrounds = 5; - uint8_t key[32], iv[32]; - - /* - * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material. - * nrounds is the number of times the we hash the material. More rounds are more secure but - * slower. - */ - int i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, 16, nrounds, key, iv); - - if (i != 32) - { - printf("Key size is %d bits - should be 256 bits\n", i); - return false ; - } - - EVP_CIPHER_CTX *e_ctx = EVP_CIPHER_CTX_new(); - EVP_DecryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv); - - /* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes */ - int c_len = input_data_length + AES_BLOCK_SIZE ; - int f_len = 0; - - if(output_data_length < (uint32_t)c_len) - { - EVP_CIPHER_CTX_free(e_ctx) ; - return false ; - } - - output_data_length = c_len ; - - /* update ciphertext, c_len is filled with the length of ciphertext generated, - *len is the size of plaintext in bytes */ - - if(! EVP_DecryptUpdate(e_ctx, output_data, &c_len, input_data, input_data_length)) - { - std::cerr << "RsAES: decryption failed." << std::endl; - EVP_CIPHER_CTX_free(e_ctx) ; - return false ; - } - - /* update ciphertext with the final remaining bytes */ - if(!EVP_DecryptFinal_ex(e_ctx, output_data+c_len, &f_len)) - { - std::cerr << "RsAES: decryption failed at end. Check padding." << std::endl; - EVP_CIPHER_CTX_free(e_ctx) ; - return false ; - } - - output_data_length = c_len + f_len; - - EVP_CIPHER_CTX_free(e_ctx) ; - return true; -} - diff --git a/libretroshare/src/crypto/rsaes.h b/libretroshare/src/crypto/rsaes.h deleted file mode 100644 index d4592793d..000000000 --- a/libretroshare/src/crypto/rsaes.h +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsaes.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2013 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include - -class RsAES -{ - public: - // Crypt/decrypt data using a 16 bytes key and a 8 bytes salt. - // - // output_data allocation is left to the client. The size should be at least RsAES::get_buffer_size(input_data_length) - // - // Return value: - // true: encryption/decryption ok - // - // false: encryption/decryption went bad. Check buffer size. - // - static bool aes_crypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) ; - static bool aes_decrypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) ; - - // computes the safe buffer size to store encrypted/decrypted data for the given input stream size - // - static uint32_t get_buffer_size(uint32_t size) ; -}; - diff --git a/libretroshare/src/crypto/rscrypto.cpp b/libretroshare/src/crypto/rscrypto.cpp deleted file mode 100644 index 0a296673e..000000000 --- a/libretroshare/src/crypto/rscrypto.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/******************************************************************************* - * libretroshare/src/crypto: crypto.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include -#include - -#include "rscrypto.h" -#include "util/rsrandom.h" - -//#define CRYPTO_DEBUG 1 - -namespace librs { -namespace crypto { - -#define RSCRYPTO_DEBUG() std::cerr << time(NULL) << " : RSCRYPTO : " << __FUNCTION__ << " : " -#define RSCRYPTO_ERROR() std::cerr << "(EE) RSCRYPTO ERROR : " - -static const uint32_t ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE = 12 ; -static const uint32_t ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE = 16 ; -static const uint32_t ENCRYPTED_MEMORY_HEADER_SIZE = 4 ; -static const uint32_t ENCRYPTED_MEMORY_EDATA_SIZE = 4 ; - -static const uint8_t ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_POLY1305 = 0x01 ; -static const uint8_t ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_SHA256 = 0x02 ; - -bool encryptAuthenticateData(const unsigned char *clear_data,uint32_t clear_data_size,uint8_t *encryption_master_key,unsigned char *& encrypted_data,uint32_t& encrypted_data_len) -{ - uint8_t initialization_vector[ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE] ; - - RSRandom::random_bytes(initialization_vector,ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE) ; - -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << "ftServer::Encrypting ft item." << std::endl; - RSCRYPTO_DEBUG() << " random nonce : " << RsUtil::BinToHex(initialization_vector,ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE) << std::endl; -#endif - - uint32_t item_serialized_size = clear_data_size;//RsGenericSerializer().size(clear_item) ; - uint32_t total_data_size = ENCRYPTED_MEMORY_HEADER_SIZE + ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_MEMORY_EDATA_SIZE + item_serialized_size + ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE ; - -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << " clear part size : " << size(clear_item) << std::endl; - RSCRYPTO_DEBUG() << " total item size : " << total_data_size << std::endl; -#endif - - encrypted_data = (unsigned char*)rs_malloc( total_data_size ) ; - encrypted_data_len = total_data_size ; - - if(encrypted_data == NULL) - return false ; - - uint8_t *edata = (uint8_t*)encrypted_data; - uint32_t edata_size = item_serialized_size; - uint32_t offset = 0; - - edata[0] = 0xae ; - edata[1] = 0xad ; - edata[2] = ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_SHA256 ; // means AEAD_chacha20_sha256 - edata[3] = 0x01 ; - - offset += ENCRYPTED_MEMORY_HEADER_SIZE; - uint32_t aad_offset = offset ; - uint32_t aad_size = ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_MEMORY_EDATA_SIZE ; - - memcpy(&edata[offset], initialization_vector, ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE) ; - offset += ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE ; - - edata[offset+0] = (edata_size >> 0) & 0xff ; - edata[offset+1] = (edata_size >> 8) & 0xff ; - edata[offset+2] = (edata_size >> 16) & 0xff ; - edata[offset+3] = (edata_size >> 24) & 0xff ; - - offset += ENCRYPTED_MEMORY_EDATA_SIZE ; - - memcpy(&edata[offset],clear_data,clear_data_size); - -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << " clear item : " << RsUtil::BinToHex(&edata[offset],std::min(50,(int)total_data_size-(int)offset)) << "(...)" << std::endl; -#endif - - uint32_t clear_item_offset = offset ; - offset += edata_size ; - - uint32_t authentication_tag_offset = offset ; - assert(ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE + offset == total_data_size) ; - - //uint8_t encryption_key[32] ; - //deriveEncryptionKey(hash,encryption_key) ; - - if(edata[2] == ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_POLY1305) - librs::crypto::AEAD_chacha20_poly1305(encryption_master_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],true) ; - else if(edata[2] == ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_SHA256) - librs::crypto::AEAD_chacha20_sha256 (encryption_master_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],true) ; - else - return false ; - -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << " encryption key : " << RsUtil::BinToHex(encryption_key,32) << std::endl; - RSCRYPTO_DEBUG() << " authen. tag : " << RsUtil::BinToHex(&edata[authentication_tag_offset],ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE) << std::endl; - RSCRYPTO_DEBUG() << " final item : " << RsUtil::BinToHex(&edata[0],std::min(50u,total_data_size)) << "(...)" << std::endl; -#endif - - return true ; -} - -// Decrypts the given item using aead-chacha20-poly1305 -bool decryptAuthenticateData(const unsigned char *encrypted_data,uint32_t encrypted_data_len,uint8_t *encryption_master_key, unsigned char *& decrypted_data, uint32_t& decrypted_data_size) -{ - //uint8_t encryption_key[32] ; - //deriveEncryptionKey(hash,encryption_key) ; - - uint8_t *edata = (uint8_t*)encrypted_data; - uint32_t offset = 0; - - if(encrypted_data_len < ENCRYPTED_MEMORY_HEADER_SIZE + ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_MEMORY_EDATA_SIZE) return false ; - - if(edata[0] != 0xae) return false ; - if(edata[1] != 0xad) return false ; - if(edata[2] != ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_POLY1305 && edata[2] != ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_SHA256) return false ; - if(edata[3] != 0x01) return false ; - - offset += ENCRYPTED_MEMORY_HEADER_SIZE ; - uint32_t aad_offset = offset ; - uint32_t aad_size = ENCRYPTED_MEMORY_EDATA_SIZE + ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE ; - - uint8_t *initialization_vector = &edata[offset] ; - -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << "ftServer::decrypting ft item." << std::endl; - RSCRYPTO_DEBUG() << " item data : " << RsUtil::BinToHex(edata,std::min(50u,encrypted_data_len) << "(...)" << std::endl; - RSCRYPTO_DEBUG() << " hash : " << hash << std::endl; - RSCRYPTO_DEBUG() << " encryption key : " << RsUtil::BinToHex(encryption_key,32) << std::endl; - RSCRYPTO_DEBUG() << " random nonce : " << RsUtil::BinToHex(initialization_vector,ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE) << std::endl; -#endif - - offset += ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE ; - - uint32_t edata_size = 0 ; - edata_size += ((uint32_t)edata[offset+0]) << 0 ; - edata_size += ((uint32_t)edata[offset+1]) << 8 ; - edata_size += ((uint32_t)edata[offset+2]) << 16 ; - edata_size += ((uint32_t)edata[offset+3]) << 24 ; - - if(edata_size + ENCRYPTED_MEMORY_EDATA_SIZE + ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE + ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_MEMORY_HEADER_SIZE != encrypted_data_len) - { - RSCRYPTO_ERROR() << " ERROR: encrypted data size is " << edata_size << ", should be " << encrypted_data_len - (ENCRYPTED_MEMORY_EDATA_SIZE + ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE + ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_MEMORY_HEADER_SIZE ) << std::endl; - return false ; - } - - offset += ENCRYPTED_MEMORY_EDATA_SIZE ; - uint32_t clear_item_offset = offset ; - - uint32_t authentication_tag_offset = offset + edata_size ; -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << " authen. tag : " << RsUtil::BinToHex(&edata[authentication_tag_offset],ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE) << std::endl; -#endif - - bool result ; - - if(edata[2] == ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_POLY1305) - result = librs::crypto::AEAD_chacha20_poly1305(encryption_master_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],false) ; - else if(edata[2] == ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_SHA256) - result = librs::crypto::AEAD_chacha20_sha256 (encryption_master_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],false) ; - else - return false ; - -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << " authen. result : " << result << std::endl; - RSCRYPTO_DEBUG() << " decrypted daya : " << RsUtil::BinToHex(&edata[clear_item_offset],std::min(50u,edata_size)) << "(...)" << std::endl; -#endif - - if(!result) - { - RSCRYPTO_ERROR() << "(EE) decryption/authentication went wrong." << std::endl; - return false ; - } - - decrypted_data_size = edata_size ; - decrypted_data = (unsigned char*)rs_malloc(edata_size) ; - - if(decrypted_data == NULL) - { - std::cerr << "Failed to allocate memory for decrypted data chunk of size " << edata_size << std::endl; - return false ; - } - memcpy(decrypted_data,&edata[clear_item_offset],edata_size) ; - - return true ; -} - -} -} - diff --git a/libretroshare/src/crypto/rscrypto.h b/libretroshare/src/crypto/rscrypto.h deleted file mode 100644 index 9666aed28..000000000 --- a/libretroshare/src/crypto/rscrypto.h +++ /dev/null @@ -1,59 +0,0 @@ - -/******************************************************************************* - * libretroshare/src/crypto: crypto.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "crypto/chacha20.h" - -namespace librs -{ -namespace crypto -{ -/*! - * \brief encryptAuthenticateData - Encrypts/decrypts data, using a autenticated construction + chacha20, based on a given 32 bytes master key. The actual encryption using a randomized key - based on a 96 bits IV. Input values are not touched (memory is not released). Memory ownership of outputs is left to the client. - * \param clear_data input data to encrypt - * \param clear_data_size length of input data - * \param encryption_master_key encryption master key of length 32 bytes. - * \param encrypted_data encrypted data, allocated using malloc - * \param encrypted_data_len length of encrypted data - * \return - * true if everything went well. - */ -bool encryptAuthenticateData(const unsigned char *clear_data,uint32_t clear_data_size,uint8_t *encryption_master_key,unsigned char *& encrypted_data,uint32_t& encrypted_data_size); - -/*! - * \brief decryptAuthenticateData - Encrypts/decrypts data, using a autenticated construction + chacha20, based on a given 32 bytes master key. The actual encryption using a randomized key - based on a 96 bits IV. Input values are not touched (memory is not released). Memory ownership of outputs is left to the client. - * \param encrypted_data input encrypted data - * \param encrypted_data_size input encrypted data length - * \param encryption_master_key encryption master key of length 32 bytes. - * \param decrypted_data decrypted data, allocated using malloc. - * \param decrypted_data_size length of allocated decrypted data. - * \return - * true if decryption + authentication are ok. - */ -bool decryptAuthenticateData(const unsigned char *encrypted_data,uint32_t encrypted_data_size, uint8_t* encryption_master_key, unsigned char *& decrypted_data,uint32_t& decrypted_data_size); -} -} - diff --git a/libretroshare/src/deep_search/channelsindex.cpp b/libretroshare/src/deep_search/channelsindex.cpp deleted file mode 100644 index cd1c374fc..000000000 --- a/libretroshare/src/deep_search/channelsindex.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 Asociación Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero 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 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 . * - * * - *******************************************************************************/ - -#include "deep_search/channelsindex.hpp" -#include "deep_search/commonutils.hpp" - -uint32_t DeepChannelsIndex::search( - const std::string& queryStr, - std::vector& results, uint32_t maxResults ) -{ - results.clear(); - - std::unique_ptr dbPtr( - DeepSearch::openReadOnlyDatabase(dbPath()) ); - if(!dbPtr) return 0; - - Xapian::Database& db(*dbPtr); - - // Set up a QueryParser with a stemmer and suitable prefixes. - Xapian::QueryParser queryparser; - //queryparser.set_stemmer(Xapian::Stem("en")); - queryparser.set_stemming_strategy(queryparser.STEM_SOME); - // Start of prefix configuration. - //queryparser.add_prefix("title", "S"); - //queryparser.add_prefix("description", "XD"); - // End of prefix configuration. - - // And parse the query. - Xapian::Query query = queryparser.parse_query(queryStr); - - // Use an Enquire object on the database to run the query. - Xapian::Enquire enquire(db); - enquire.set_query(query); - - Xapian::MSet mset = enquire.get_mset( - 0, maxResults ? maxResults : db.get_doccount() ); - - for ( Xapian::MSetIterator m = mset.begin(); m != mset.end(); ++m ) - { - const Xapian::Document& doc = m.get_document(); - DeepChannelsSearchResult s; - s.mUrl = doc.get_value(URL_VALUENO); -#if XAPIAN_AT_LEAST(1,3,5) - s.mSnippet = mset.snippet(doc.get_data()); -#endif // XAPIAN_AT_LEAST(1,3,5) - results.push_back(s); - } - - return static_cast(results.size()); -} - -void DeepChannelsIndex::indexChannelGroup(const RsGxsChannelGroup& chan) -{ - std::unique_ptr dbPtr( - DeepSearch::openWritableDatabase( - dbPath(), Xapian::DB_CREATE_OR_OPEN ) ); - if(!dbPtr) return; - - Xapian::WritableDatabase& db(*dbPtr); - - // Set up a TermGenerator that we'll use in indexing. - Xapian::TermGenerator termgenerator; - //termgenerator.set_stemmer(Xapian::Stem("en")); - - // We make a document and tell the term generator to use this. - Xapian::Document doc; - termgenerator.set_document(doc); - - // Index each field with a suitable prefix. - termgenerator.index_text(chan.mMeta.mGroupName, 1, "G"); - termgenerator.index_text( - DeepSearch::timetToXapianDate(chan.mMeta.mPublishTs), 1, "D" ); - termgenerator.index_text(chan.mDescription, 1, "XD"); - - // Index fields without prefixes for general search. - termgenerator.index_text(chan.mMeta.mGroupName); - termgenerator.increase_termpos(); - termgenerator.index_text(chan.mDescription); - - RsUrl chanUrl; chanUrl - .setScheme("retroshare").setPath("/channel") - .setQueryKV("id", chan.mMeta.mGroupId.toStdString()); - const std::string idTerm("Q" + chanUrl.toString()); - - chanUrl.setQueryKV("publishTs", std::to_string(chan.mMeta.mPublishTs)); - chanUrl.setQueryKV("name", chan.mMeta.mGroupName); - if(!chan.mMeta.mAuthorId.isNull()) - chanUrl.setQueryKV("authorId", chan.mMeta.mAuthorId.toStdString()); - if(chan.mMeta.mSignFlags) - chanUrl.setQueryKV( "signFlags", - std::to_string(chan.mMeta.mSignFlags) ); - std::string rsLink(chanUrl.toString()); - - // store the RS link so we are able to retrive it on matching search - doc.add_value(URL_VALUENO, rsLink); - - // Store some fields for display purposes. - doc.set_data(chan.mMeta.mGroupName + "\n" + chan.mDescription); - - // We use the identifier to ensure each object ends up in the - // database only once no matter how many times we run the - // indexer. "Q" prefix is a Xapian convention for unique id term. - doc.add_boolean_term(idTerm); - db.replace_document(idTerm, doc); -} - -void DeepChannelsIndex::removeChannelFromIndex(RsGxsGroupId grpId) -{ - // "Q" prefix is a Xapian convention for unique id term. - RsUrl chanUrl; chanUrl - .setScheme("retroshare").setPath("/channel") - .setQueryKV("id", grpId.toStdString()); - std::string idTerm("Q" + chanUrl.toString()); - - std::unique_ptr dbPtr( - DeepSearch::openWritableDatabase( - dbPath(), Xapian::DB_CREATE_OR_OPEN ) ); - if(!dbPtr) return; - - Xapian::WritableDatabase& db(*dbPtr); - db.delete_document(idTerm); -} - -void DeepChannelsIndex::indexChannelPost(const RsGxsChannelPost& post) -{ - std::unique_ptr dbPtr( - DeepSearch::openWritableDatabase( - dbPath(), Xapian::DB_CREATE_OR_OPEN ) ); - if(!dbPtr) return; - - Xapian::WritableDatabase& db(*dbPtr); - - // Set up a TermGenerator that we'll use in indexing. - Xapian::TermGenerator termgenerator; - //termgenerator.set_stemmer(Xapian::Stem("en")); - - // We make a document and tell the term generator to use this. - Xapian::Document doc; - termgenerator.set_document(doc); - - // Index each field with a suitable prefix. - termgenerator.index_text(post.mMeta.mMsgName, 1, "S"); - termgenerator.index_text( - DeepSearch::timetToXapianDate(post.mMeta.mPublishTs), 1, "D" ); - - // TODO: we should strip out HTML tags instead of skipping indexing - // Avoid indexing HTML - bool isPlainMsg = - post.mMsg[0] != '<' || post.mMsg[post.mMsg.size() - 1] != '>'; - - if(isPlainMsg) - termgenerator.index_text(post.mMsg, 1, "XD"); - - // Index fields without prefixes for general search. - termgenerator.index_text(post.mMeta.mMsgName); - if(isPlainMsg) - { - termgenerator.increase_termpos(); - termgenerator.index_text(post.mMsg); - } - - for(const RsGxsFile& attachment : post.mFiles) - { - termgenerator.index_text(attachment.mName, 1, "F"); - - termgenerator.increase_termpos(); - termgenerator.index_text(attachment.mName); - } - - // We use the identifier to ensure each object ends up in the - // database only once no matter how many times we run the - // indexer. - RsUrl postUrl; postUrl - .setScheme("retroshare").setPath("/channel") - .setQueryKV("id", post.mMeta.mGroupId.toStdString()) - .setQueryKV("msgid", post.mMeta.mMsgId.toStdString()); - std::string idTerm("Q" + postUrl.toString()); - - postUrl.setQueryKV("publishTs", std::to_string(post.mMeta.mPublishTs)); - postUrl.setQueryKV("name", post.mMeta.mMsgName); - postUrl.setQueryKV("authorId", post.mMeta.mAuthorId.toStdString()); - std::string rsLink(postUrl.toString()); - - // store the RS link so we are able to retrive it on matching search - doc.add_value(URL_VALUENO, rsLink); - - // Store some fields for display purposes. - if(isPlainMsg) - doc.set_data(post.mMeta.mMsgName + "\n" + post.mMsg); - else doc.set_data(post.mMeta.mMsgName); - - doc.add_boolean_term(idTerm); - db.replace_document(idTerm, doc); -} - -void DeepChannelsIndex::removeChannelPostFromIndex( - RsGxsGroupId grpId, RsGxsMessageId msgId ) -{ - RsUrl postUrl; postUrl - .setScheme("retroshare").setPath("/channel") - .setQueryKV("id", grpId.toStdString()) - .setQueryKV("msgid", msgId.toStdString()); - // "Q" prefix is a Xapian convention for unique id term. - std::string idTerm("Q" + postUrl.toString()); - - std::unique_ptr dbPtr( - DeepSearch::openWritableDatabase( - dbPath(), Xapian::DB_CREATE_OR_OPEN ) ); - if(!dbPtr) return; - - Xapian::WritableDatabase& db(*dbPtr); - db.delete_document(idTerm); -} diff --git a/libretroshare/src/deep_search/channelsindex.hpp b/libretroshare/src/deep_search/channelsindex.hpp deleted file mode 100644 index 0a49629d9..000000000 --- a/libretroshare/src/deep_search/channelsindex.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 Asociación Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero 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 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "util/rstime.h" -#include "retroshare/rsgxschannels.h" -#include "retroshare/rsinit.h" -#include "util/rsurl.h" - -struct DeepChannelsSearchResult -{ - std::string mUrl; - double mWeight; - std::string mSnippet; -}; - -struct DeepChannelsIndex -{ - /** - * @brief Search indexed GXS groups and messages - * @param[in] maxResults maximum number of acceptable search results, 0 for - * no limits - * @return search results count - */ - static uint32_t search( const std::string& queryStr, - std::vector& results, - uint32_t maxResults = 100 ); - - static void indexChannelGroup(const RsGxsChannelGroup& chan); - - static void removeChannelFromIndex(RsGxsGroupId grpId); - - static void indexChannelPost(const RsGxsChannelPost& post); - - static void removeChannelPostFromIndex( - RsGxsGroupId grpId, RsGxsMessageId msgId ); - - static uint32_t indexFile(const std::string& path); - -private: - - enum : Xapian::valueno - { - /// Used to store retroshare url of indexed documents - URL_VALUENO, - - /// @see Xapian::BAD_VALUENO - BAD_VALUENO = Xapian::BAD_VALUENO - }; - - static const std::string& dbPath() - { - static const std::string dbDir = - RsAccounts::AccountDirectory() + "/deep_channels_xapian_db"; - return dbDir; - } -}; diff --git a/libretroshare/src/deep_search/commonutils.cpp b/libretroshare/src/deep_search/commonutils.cpp deleted file mode 100644 index eecbd4ec6..000000000 --- a/libretroshare/src/deep_search/commonutils.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 Asociación Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero 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 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 . * - * * - *******************************************************************************/ - -#include "deep_search/commonutils.hpp" -#include "util/stacktrace.h" -#include "util/rsdebug.h" - -namespace DeepSearch -{ - -std::unique_ptr openWritableDatabase( - const std::string& path, int flags, int blockSize ) -{ - try - { - std::unique_ptr dbPtr( - new Xapian::WritableDatabase(path, flags, blockSize) ); - return dbPtr; - } - catch(Xapian::DatabaseLockError) - { - RsErr() << __PRETTY_FUNCTION__ << " Failed aquiring Xapian DB lock " - << path << std::endl; - print_stacktrace(); - } - catch(...) - { - RsErr() << __PRETTY_FUNCTION__ << " Xapian DB is apparently corrupted " - << "deleting it might help without causing any harm: " - << path << std::endl; - print_stacktrace(); - } - - return nullptr; -} - -std::unique_ptr openReadOnlyDatabase( - const std::string& path, int flags ) -{ - try - { - std::unique_ptr dbPtr( - new Xapian::Database(path, flags) ); - return dbPtr; - } - catch(Xapian::DatabaseOpeningError e) - { - RsWarn() << __PRETTY_FUNCTION__ << " " << e.get_msg() - << ", probably nothing has been indexed yet." << std::endl; - } - catch(Xapian::DatabaseLockError) - { - RsErr() << __PRETTY_FUNCTION__ << " Failed aquiring Xapian DB lock " - << path << std::endl; - print_stacktrace(); - } - catch(...) - { - RsErr() << __PRETTY_FUNCTION__ << " Xapian DB is apparently corrupted " - << "deleting it might help without causing any harm: " - << path << std::endl; - print_stacktrace(); - } - - return nullptr; -} - -std::string timetToXapianDate(const rstime_t& time) -{ - char date[] = "YYYYMMDD\0"; - time_t tTime = static_cast(time); - std::strftime(date, 9, "%Y%m%d", std::gmtime(&tTime)); - return date; -} - -} diff --git a/libretroshare/src/deep_search/commonutils.hpp b/libretroshare/src/deep_search/commonutils.hpp deleted file mode 100644 index 28961bc09..000000000 --- a/libretroshare/src/deep_search/commonutils.hpp +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 Asociación Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero 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 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "util/rstime.h" - -#ifndef XAPIAN_AT_LEAST -#define XAPIAN_AT_LEAST(A,B,C) (XAPIAN_MAJOR_VERSION > (A) || \ - (XAPIAN_MAJOR_VERSION == (A) && \ - (XAPIAN_MINOR_VERSION > (B) || \ - (XAPIAN_MINOR_VERSION == (B) && XAPIAN_REVISION >= (C))))) -#endif // ndef XAPIAN_AT_LEAST - -namespace DeepSearch -{ - -std::unique_ptr openWritableDatabase( - const std::string& path, int flags = 0, int blockSize = 0 ); - -std::unique_ptr openReadOnlyDatabase( - const std::string& path, int flags = 0 ); - -std::string timetToXapianDate(const rstime_t& time); - -} diff --git a/libretroshare/src/deep_search/filesflacindexer.hpp b/libretroshare/src/deep_search/filesflacindexer.hpp deleted file mode 100644 index dbdc62b99..000000000 --- a/libretroshare/src/deep_search/filesflacindexer.hpp +++ /dev/null @@ -1,156 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 Asociación Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero 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 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 . * - * * - *******************************************************************************/ - -#include "deep_search/filesindex.hpp" -#include "util/rsdebug.h" - -#include -#include -#include -#include -#include - -struct RsDeepFlacFileIndexer -{ - RsDeepFlacFileIndexer() - { - DeepFilesIndex::registerIndexer(31, indexFlacFile); - } - - static uint32_t indexFlacFile( - const std::string& path, const std::string& /*name*/, - Xapian::TermGenerator& xTG, Xapian::Document& xDoc ) - { - Dbg3() << __PRETTY_FUNCTION__ << " " << path << std::endl; - - using FlacChain = FLAC::Metadata::Chain; - std::unique_ptr flacChain(new FlacChain); - - if(!flacChain->is_valid()) - { - RsErr() << __PRETTY_FUNCTION__ << " Failed creating FLAC Chain 1" - << std::endl; - return 1; - } - - if(!flacChain->read(path.c_str(), false)) - { - Dbg3() << __PRETTY_FUNCTION__ << " Failed to open the file as FLAC" - << std::endl; - - flacChain.reset(new FlacChain); - if(!flacChain->is_valid()) - { - RsErr() << __PRETTY_FUNCTION__ - << " Failed creating FLAC Chain 2" << std::endl; - return 1; - } - if(!flacChain->read(path.c_str(), true)) - { - Dbg3() << __PRETTY_FUNCTION__ - << " Failed to open the file as OggFLAC" - << std::endl; - return 0; - } - } - - unsigned validCommentsCnt = 0; - std::string docData = xDoc.get_data(); - - FLAC::Metadata::Iterator mdit; - mdit.init(*flacChain); - if(!mdit.is_valid()) return 1; - - do - { - ::FLAC__MetadataType mdt = mdit.get_block_type(); - if (mdt != FLAC__METADATA_TYPE_VORBIS_COMMENT) continue; - - Dbg2() << __PRETTY_FUNCTION__ << " Found Vorbis Comment Block" - << std::endl; - - std::unique_ptr proto(mdit.get_block()); - if(!proto) continue; - - const FLAC::Metadata::VorbisComment* vc = - dynamic_cast(proto.get()); - if(!vc || !vc->is_valid()) continue; - - unsigned numComments = vc->get_num_comments(); - for(unsigned i = 0; i < numComments; ++i) - { - FLAC::Metadata::VorbisComment::Entry entry = - vc->get_comment(i); - if(!entry.is_valid()) continue; - - std::string tagName( entry.get_field_name(), - entry.get_field_name_length() ); - - /* Vorbis tags should be uppercases but not all the softwares - * enforce it */ - for (auto& c: tagName) c = static_cast(toupper(c)); - - std::string tagValue( entry.get_field_value(), - entry.get_field_value_length() ); - - if(tagValue.empty()) continue; - - if(tagName == "ARTIST") - xTG.index_text(tagValue, 1, "A"); - else if (tagName == "DESCRIPTION") - xTG.index_text(tagValue, 1, "XD"); - else if (tagName == "TITLE") - xTG.index_text(tagValue, 1, "S"); - else if(tagName.find("COVERART") != tagName.npos) - continue; // Avoid polluting the index with binary data - else if (tagName.find("METADATA_BLOCK_PICTURE") != tagName.npos) - continue; // Avoid polluting the index with binary data - - // Index fields without prefixes for general search. - xTG.increase_termpos(); - std::string fullComment(tagName + "=" + tagValue); - xTG.index_text(fullComment); - docData += fullComment + "\n"; - - Dbg2() << __PRETTY_FUNCTION__ << " Indexed " << fullComment - << std::endl; - - ++validCommentsCnt; - } - } - while(mdit.next()); - - if(validCommentsCnt > 0) - { - Dbg1() << __PRETTY_FUNCTION__ << " Successfully indexed: " << path - << std::endl; - - xDoc.set_data(docData); - return 99; - } - - /* Altought the file appears to be a valid FLAC, no vorbis comment has - * been found so return less then 50 maybe it has tagged only with ID3 - * tags ? */ - return 30; - } - - RS_SET_CONTEXT_DEBUG_LEVEL(3) -}; diff --git a/libretroshare/src/deep_search/filesindex.cpp b/libretroshare/src/deep_search/filesindex.cpp deleted file mode 100644 index 3edcf9a97..000000000 --- a/libretroshare/src/deep_search/filesindex.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 Asociación Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero 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 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 . * - * * - *******************************************************************************/ - -#include "deep_search/filesindex.hpp" -#include "deep_search/commonutils.hpp" -#include "util/rsdebug.h" -#include "retroshare/rsinit.h" -#include "retroshare/rsversion.h" - -#include - -/*static*/ std::multimap -DeepFilesIndex::indexersRegister = {}; - -bool DeepFilesIndex::indexFile( - const std::string& path, const std::string& name, - const RsFileHash& hash ) -{ - auto dbPtr = DeepSearch::openWritableDatabase( - mDbPath, Xapian::DB_CREATE_OR_OPEN ); - if(!dbPtr) return false; - Xapian::WritableDatabase& db(*dbPtr); - - const std::string hashString = hash.toStdString(); - const std::string idTerm("Q" + hashString); - - Xapian::Document oldDoc; - Xapian::PostingIterator pIt = db.postlist_begin(idTerm); - if( pIt != db.postlist_end(idTerm) ) - { - oldDoc = db.get_document(*pIt); - if( oldDoc.get_value(INDEXER_VERSION_VALUENO) == - RS_HUMAN_READABLE_VERSION && - std::stoull(oldDoc.get_value(INDEXERS_COUNT_VALUENO)) == - indexersRegister.size() ) - { - /* Looks like this file has already been indexed by this RetroShare - * exact version, so we can skip it. If the version was different it - * made sense to reindex it as better indexers might be available - * since last time it was indexed */ - Dbg3() << __PRETTY_FUNCTION__ << " skipping laready indexed file: " - << hash << " " << name << std::endl; - return true; - } - } - - Xapian::Document doc; - - // Set up a TermGenerator that we'll use in indexing. - Xapian::TermGenerator termgenerator; - //termgenerator.set_stemmer(Xapian::Stem("en")); - termgenerator.set_document(doc); - - for(auto& indexerPair : indexersRegister) - if(indexerPair.second(path, name, termgenerator, doc) > 50) - break; - - doc.add_boolean_term(idTerm); - termgenerator.index_text(name, 1, "N"); - termgenerator.index_text(name); - doc.add_value(FILE_HASH_VALUENO, hashString); - doc.add_value(INDEXER_VERSION_VALUENO, RS_HUMAN_READABLE_VERSION); - doc.add_value( - INDEXERS_COUNT_VALUENO, - std::to_string(indexersRegister.size()) ); - db.replace_document(idTerm, doc); - - return true; -} - -bool DeepFilesIndex::removeFileFromIndex(const RsFileHash& hash) -{ - Dbg3() << __PRETTY_FUNCTION__ << " removing file from index: " - << hash << std::endl; - - std::unique_ptr db = - DeepSearch::openWritableDatabase(mDbPath, Xapian::DB_CREATE_OR_OPEN); - if(!db) return false; - - db->delete_document("Q" + hash.toStdString()); - return true; -} - -/*static*/ std::string DeepFilesIndex::dbDefaultPath() -{ return RsAccounts::AccountDirectory() + "/deep_files_index_xapian_db"; } - -/*static*/ bool DeepFilesIndex::registerIndexer( - int order, const DeepFilesIndex::IndexerFunType& indexerFun ) -{ - Dbg1() << __PRETTY_FUNCTION__ << " " << order << std::endl; - - indexersRegister.insert(std::make_pair(order, indexerFun)); - return true; -} - -uint32_t DeepFilesIndex::search( - const std::string& queryStr, - std::vector& results, uint32_t maxResults ) -{ - results.clear(); - - auto dbPtr = DeepSearch::openReadOnlyDatabase(mDbPath); - if(!dbPtr) return 0; - Xapian::Database& db(*dbPtr); - - // Set up a QueryParser with a stemmer and suitable prefixes. - Xapian::QueryParser queryparser; - //queryparser.set_stemmer(Xapian::Stem("en")); - queryparser.set_stemming_strategy(queryparser.STEM_SOME); - // Start of prefix configuration. - //queryparser.add_prefix("title", "S"); - //queryparser.add_prefix("description", "XD"); - // End of prefix configuration. - - // And parse the query. - Xapian::Query query = queryparser.parse_query(queryStr); - - // Use an Enquire object on the database to run the query. - Xapian::Enquire enquire(db); - enquire.set_query(query); - - Xapian::MSet mset = enquire.get_mset( - 0, maxResults ? maxResults : db.get_doccount() ); - - for ( Xapian::MSetIterator m = mset.begin(); m != mset.end(); ++m ) - { - const Xapian::Document& doc = m.get_document(); - DeepFilesSearchResult s; - s.mFileHash = RsFileHash(doc.get_value(FILE_HASH_VALUENO)); - s.mWeight = m.get_weight(); -#if XAPIAN_AT_LEAST(1,3,5) - s.mSnippet = mset.snippet(doc.get_data()); -#endif // XAPIAN_AT_LEAST(1,3,5) - results.push_back(s); - } - - return static_cast(results.size()); -} - - -#ifdef RS_DEEP_FILES_INDEX_OGG -# include "deep_search/filesoggindexer.hpp" -static RsDeepOggFileIndexer oggFileIndexer; -#endif // def RS_DEEP_FILES_INDEX_OGG - -#ifdef RS_DEEP_FILES_INDEX_FLAC -# include "deep_search/filesflacindexer.hpp" -static RsDeepFlacFileIndexer flacFileIndexer; -#endif // def RS_DEEP_FILES_INDEX_FLAC - -#ifdef RS_DEEP_FILES_INDEX_TAGLIB -# include "deep_search/filestaglibindexer.hpp" -static RsDeepTaglibFileIndexer taglibFileIndexer; -#endif // def RS_DEEP_FILES_INDEX_TAGLIB diff --git a/libretroshare/src/deep_search/filesindex.hpp b/libretroshare/src/deep_search/filesindex.hpp deleted file mode 100644 index f811e5e9c..000000000 --- a/libretroshare/src/deep_search/filesindex.hpp +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 Asociación Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero 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 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rstypes.h" -#include "util/rsdebug.h" - -#include -#include -#include -#include -#include -#include - -struct DeepFilesSearchResult -{ - DeepFilesSearchResult() : mWeight(0) {} - - RsFileHash mFileHash; - double mWeight; - std::string mSnippet; -}; - -class DeepFilesIndex -{ -public: - DeepFilesIndex(const std::string& dbPath) : mDbPath(dbPath) {} - - /** - * @brief Search indexed files - * @param[in] maxResults maximum number of acceptable search results, 0 for - * no limits - * @return search results count - */ - uint32_t search( const std::string& queryStr, - std::vector& results, - uint32_t maxResults = 100 ); - - /** - * @return false if file could not be indexed because of error or - * unsupported type, true otherwise. - */ - bool indexFile( - const std::string& path, const std::string& name, - const RsFileHash& hash ); - - /** - * @brief Remove file entry from database - * @return false on error, true otherwise. - */ - bool removeFileFromIndex(const RsFileHash& hash); - - static std::string dbDefaultPath(); - - using IndexerFunType = std::function< - uint32_t( const std::string& path, const std::string& name, - Xapian::TermGenerator& xTG, Xapian::Document& xDoc ) >; - - static bool registerIndexer( - int order, const IndexerFunType& indexerFun ); - -private: - enum : Xapian::valueno - { - /// Used to store RsFileHash of indexed documents - FILE_HASH_VALUENO, - - /** Used to check if some file need reindex because was indexed with an - * older version of the indexer */ - INDEXER_VERSION_VALUENO, - - /** Used to check if some file need reindex because was indexed with an - * older version of the indexer */ - INDEXERS_COUNT_VALUENO, - - /// @see Xapian::BAD_VALUENO - BAD_VALUENO = Xapian::BAD_VALUENO - }; - - const std::string mDbPath; - - /** Storage for indexers function by order */ - static std::multimap indexersRegister; - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; diff --git a/libretroshare/src/deep_search/filesoggindexer.hpp b/libretroshare/src/deep_search/filesoggindexer.hpp deleted file mode 100644 index 00c22ae66..000000000 --- a/libretroshare/src/deep_search/filesoggindexer.hpp +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 Asociación Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero 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 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 . * - * * - *******************************************************************************/ - -#include "deep_search/filesindex.hpp" -#include "util/rsdebug.h" - -#include -#include -#include -#include - -struct RsDeepOggFileIndexer -{ - RsDeepOggFileIndexer() - { - DeepFilesIndex::registerIndexer(30, indexOggFile); - } - - static uint32_t indexOggFile( - const std::string& path, const std::string& /*name*/, - Xapian::TermGenerator& xTG, Xapian::Document& xDoc ) - { - Dbg3() << __PRETTY_FUNCTION__ << " " << path << std::endl; - - OggVorbis_File vf; - int ret = ov_fopen(path.c_str(), &vf); - - if(ret == 0 && vf.vc) - { - vorbis_comment& vc = *vf.vc; - std::string docData = xDoc.get_data(); - for (int i = 0; i < vc.comments; ++i) - { - using szt = std::string::size_type; - std::string userComment( - vc.user_comments[i], - static_cast(vc.comment_lengths[i]) ); - - if(userComment.empty()) continue; - - szt equalPos = userComment.find('='); - if(equalPos == std::string::npos) continue; - - std::string tagName = userComment.substr(0, equalPos); - if(tagName.empty()) continue; - - std::string tagValue = userComment.substr(equalPos + 1); - if(tagValue.empty()) continue; - - /* Ogg tags should be uppercases but not all the softwares - * enforce it */ - for (auto& c: tagName) c = static_cast(toupper(c)); - - if(tagName == "ARTIST") - xTG.index_text(tagValue, 1, "A"); - else if (tagName == "DESCRIPTION") - xTG.index_text(tagValue, 1, "XD"); - else if (tagName == "TITLE") - xTG.index_text(tagValue, 1, "S"); - else if(tagName.find("COVERART") != tagName.npos) - continue; // Avoid polluting the index with binary data - else if (tagName.find("METADATA_BLOCK_PICTURE") != tagName.npos) - continue; // Avoid polluting the index with binary data - - // Index fields without prefixes for general search. - xTG.increase_termpos(); - xTG.index_text(userComment); - docData += userComment + "\n"; - } - xDoc.set_data(docData); - - ov_clear(&vf); - return 99; - } - - return 0; - } - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; diff --git a/libretroshare/src/deep_search/filestaglibindexer.hpp b/libretroshare/src/deep_search/filestaglibindexer.hpp deleted file mode 100644 index 341e9af38..000000000 --- a/libretroshare/src/deep_search/filestaglibindexer.hpp +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 Asociación Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero 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 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 . * - * * - *******************************************************************************/ - -#include "deep_search/filesindex.hpp" -#include "util/rsdebug.h" - -#include -#include -#include -#include -#include -#include - -struct RsDeepTaglibFileIndexer -{ - RsDeepTaglibFileIndexer() - { - DeepFilesIndex::registerIndexer(40, indexFile); - } - - static uint32_t indexFile( - const std::string& path, const std::string& /*name*/, - Xapian::TermGenerator& xTG, Xapian::Document& xDoc ) - { - Dbg4() << __PRETTY_FUNCTION__ << " " << path << std::endl; - - TagLib::FileRef tFile(path.c_str()); - if(tFile.isNull()) return 0; - - const TagLib::Tag* tag = tFile.tag(); - if(!tag) return 0; - - TagLib::PropertyMap tMap = tag->properties(); - - unsigned validCommentsCnt = 0; - std::string docData = xDoc.get_data(); - for( TagLib::PropertyMap::ConstIterator mIt = tMap.begin(); - mIt != tMap.end(); ++mIt ) - { - if(mIt->first.isNull() || mIt->first.isEmpty()) continue; - std::string tagName(mIt->first.upper().to8Bit()); - - if(mIt->second.isEmpty()) continue; - std::string tagValue(mIt->second.toString(", ").to8Bit(true)); - if(tagValue.empty()) continue; - - if(tagName == "ARTIST") - xTG.index_text(tagValue, 1, "A"); - else if (tagName == "DESCRIPTION") - xTG.index_text(tagValue, 1, "XD"); - else if (tagName == "TITLE") - xTG.index_text(tagValue, 1, "S"); - else if(tagName.find("COVERART") != tagName.npos) - continue; // Avoid polluting the index with binary data - else if (tagName.find("METADATA_BLOCK_PICTURE") != tagName.npos) - continue; // Avoid polluting the index with binary data - - // Index fields without prefixes for general search. - xTG.increase_termpos(); - std::string fullComment(tagName + "=" + tagValue); - xTG.index_text(fullComment); - docData += fullComment + "\n"; - - Dbg2() << __PRETTY_FUNCTION__ << " Indexed " << tagName << "=\"" - << tagValue << '"' << std::endl; - - ++validCommentsCnt; - } - - if(validCommentsCnt > 0) - { - Dbg1() << __PRETTY_FUNCTION__ << " Successfully indexed: " << path - << std::endl; - - xDoc.set_data(docData); - return 99; - } - - /* Altought the file appears to be supported by taglib, no comments has - * been found so return less then 50 maybe another indexer is capable of - * extracting information */ - return 30; - } - - RS_SET_CONTEXT_DEBUG_LEVEL(3) -}; diff --git a/libretroshare/src/dht/connectstatebox.cc b/libretroshare/src/dht/connectstatebox.cc deleted file mode 100644 index c1a0c4ff2..000000000 --- a/libretroshare/src/dht/connectstatebox.cc +++ /dev/null @@ -1,1049 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: connectstatebox.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "dht/connectstatebox.h" - -#include "util/rsrandom.h" -#include "util/rsstring.h" - -#include - -/** - * - * #define TESTING_PERIODS 1 - * #define DEBUG_CONNECTBOX 1 - * - **/ - - -/* Have made the PROXY Attempts + MAX_TIME much larger, - * have have potential for this to take a while. - */ - -#ifdef TESTING_PERIODS - #define FAILED_WAIT_TIME (1800) // 5 minutes. - #define TCP_WAIT_TIME (10) // 1/6 minutes. - #define DIRECT_MAX_WAIT_TIME (30) // 1/6 minutes. - #define PROXY_BASE_WAIT_TIME (10) // 30 // 1/6 minutes. - #define PROXY_MAX_WAIT_TIME (30) // 120 // 1/6 minutes. - #define RELAY_MAX_WAIT_TIME (30) // 1/6 minutes. - #define REVERSE_WAIT_TIME (30) // 1/2 minutes. - - #define MAX_DIRECT_ATTEMPTS (3) - #define MAX_PROXY_ATTEMPTS (3) - #define MAX_RELAY_ATTEMPTS (3) - - #define MAX_DIRECT_FAILED_ATTEMPTS (1) - #define MAX_PROXY_FAILED_ATTEMPTS (2) - #define MAX_RELAY_FAILED_ATTEMPTS (2) -#else - #define FAILED_WAIT_TIME (1800) // 30 minutes. - #define TCP_WAIT_TIME (60) // 1 minutes. - #define DIRECT_MAX_WAIT_TIME (60) // 1 minutes. - - #define PROXY_BASE_WAIT_TIME (30) // 1/2 minutes. - #define PROXY_MAX_WAIT_TIME (120) // 1 minutes. - - #define RELAY_MAX_WAIT_TIME (60) // 1 minutes. - #define REVERSE_WAIT_TIME (300) // 5 minutes. - - #define MAX_DIRECT_ATTEMPTS (5) - #define MAX_PROXY_ATTEMPTS (10) - #define MAX_RELAY_ATTEMPTS (5) - - #define MAX_DIRECT_FAILED_ATTEMPTS (3) - #define MAX_PROXY_FAILED_ATTEMPTS (3) - #define MAX_RELAY_FAILED_ATTEMPTS (3) - -#endif - -PeerConnectStateBox::PeerConnectStateBox() -{ - //mPeerId = id; - rstime_t now = time(NULL); - mState = CSB_START; - mNetState = CSB_NETSTATE_UNKNOWN; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - mNextAttemptTS = now; - mAttemptLength = 0; - mProxyPortFlags = 0; - mProxyPortChoice = false; - mProxyPortTS = 0; - - -} - - -std::string NetStateAsString(uint32_t netstate) -{ - std::string str; - switch(netstate) - { - case CSB_NETSTATE_FORWARD: - str = "Forwarded"; - break; - - case CSB_NETSTATE_STABLENAT: - str = "StableNat"; - break; - - case CSB_NETSTATE_EXCLUSIVENAT: - str = "ExclusiveNat"; - break; - - case CSB_NETSTATE_FIREWALLED: - str = "Firewalled"; - break; - default: - str = "Unknown NetState"; - break; - } - return str; -} - -std::string StateAsString(uint32_t state) -{ - std::string str; - switch(state) - { - case CSB_START: - str = "Start:"; - break; - - case CSB_TCP_WAIT: - str = "TCP Wait:"; - break; - - case CSB_DIRECT_ATTEMPT: - str = "Direct Attempt:"; - break; - - case CSB_DIRECT_WAIT: - str = "Direct Wait:"; - break; - - case CSB_PROXY_ATTEMPT: - str = "Proxy Attempt:"; - break; - - case CSB_PROXY_WAIT: - str = "Proxy Wait:"; - break; - - case CSB_RELAY_ATTEMPT: - str = "Relay Attempt:"; - break; - - case CSB_RELAY_WAIT: - str = "Relay Wait:"; - break; - - case CSB_REVERSE_WAIT: - str = "Reverse Wait:"; - break; - - case CSB_FAILED_WAIT: - str = "Failed Wait:"; - break; - - case CSB_CONNECTED: - str = "Connected:"; - break; - - default: - str = "Unknown State:"; - break; - } - - return str; -} - - -std::string UpdateAsString(uint32_t update) -{ - std::string str; - switch(update) - { - case CSB_UPDATE_NONE: - str = "none"; - break; - - case CSB_UPDATE_CONNECTED: - str = "Connected"; - break; - - case CSB_UPDATE_DISCONNECTED: - str = "Disconnected"; - break; - - case CSB_UPDATE_AUTH_DENIED: - str = "Auth Denied"; - break; - - case CSB_UPDATE_FAILED_ATTEMPT: - str = "Failed Attempt:"; - break; - - case CSB_UPDATE_MODE_UNAVAILABLE: - str = "Mode Unavailable:"; - break; - - default: - str = "Unknown Update"; - break; - } - return str; -} - -void PeerConnectStateBox::errorMsg(std::ostream &out, std::string msg, uint32_t updateParam) -{ - out << "PeerConnectStateBox::ERROR " << msg; - out << " NetState: " << NetStateAsString(mNetState); - out << " State: " << StateAsString(mState); - out << " Update: " << UpdateAsString(updateParam); - out << " for peer: " << mPeerId; - out << std::endl; -} - - -void PeerConnectStateBox::stateMsg(std::ostream &out, std::string msg, uint32_t updateParam) -{ - out << "PeerConnectStateBox::MSG " << msg; - out << " NetState: " << NetStateAsString(mNetState); - out << " State: " << StateAsString(mState); - out << " Update: " << UpdateAsString(updateParam); - out << " for peer: " << mPeerId; - out << std::endl; -} - -std::string PeerConnectStateBox::connectState() const -{ - std::string str = StateAsString(mState); - rstime_t now = time(NULL); - std::string out; - rs_sprintf(out, "%s(%lu/%lu) for %ld secs", str.c_str(), mNoAttempts, mNoFailedAttempts, now - mStateTS); - if ( (mState == CSB_CONNECTED) || (mState == CSB_DIRECT_ATTEMPT) || - (mState == CSB_PROXY_ATTEMPT) || (mState == CSB_RELAY_ATTEMPT) || - (mState == CSB_FAILED_WAIT) ) - { - rs_sprintf_append(out, " Last Attempt: %ld", mAttemptLength); - } - else - { - rs_sprintf_append(out, " LA: %ld", mAttemptLength); - rs_sprintf_append(out, " NextAttempt: %ld", mNextAttemptTS - now); - } - - return out; -} - - -uint32_t convertNetStateToInternal(RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype) -{ - uint32_t connNet = CSB_NETSTATE_UNKNOWN; - - if (netmode == RsNetworkMode::EXTERNALIP) - { - connNet = CSB_NETSTATE_FORWARD; - } - else if ((nathole != RsNatHoleMode::UNKNOWN) && (nathole != RsNatHoleMode::NONE)) - { - connNet = CSB_NETSTATE_FORWARD; - } - else if (netmode == RsNetworkMode::BEHINDNAT) - { - if ((nattype == RsNatTypeMode::RESTRICTED_CONE) || - (nattype == RsNatTypeMode::FULL_CONE)) - { - connNet = CSB_NETSTATE_STABLENAT; - } - else if (nattype == RsNatTypeMode::DETERM_SYM) - { - connNet = CSB_NETSTATE_EXCLUSIVENAT; - } - else - { - connNet = CSB_NETSTATE_FIREWALLED; - } - } - return connNet; -} - -bool shouldUseProxyPortInternal(uint32_t netstate) -{ - if (netstate == CSB_NETSTATE_FORWARD) - { - return false; - } - return true; -} - -bool PeerConnectStateBox::shouldUseProxyPort(RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype) -{ - uint32_t netstate = convertNetStateToInternal(netmode, nathole, nattype); - return shouldUseProxyPortInternal(netstate); -} - -uint32_t PeerConnectStateBox::calcNetState(RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype) -{ - uint32_t netstate = convertNetStateToInternal(netmode, nathole, nattype); - return netstate; -} - - -uint32_t PeerConnectStateBox::connectCb(uint32_t cbtype, RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype) -{ - uint32_t netstate = convertNetStateToInternal(netmode, nathole, nattype); - -#ifdef DEBUG_CONNECTBOX - std::cerr << "PeerConnectStateBox::connectCb("; - if (cbtype == CSB_CONNECT_DIRECT) - { - std::cerr << "DIRECT"; - } - else - { - std::cerr << "UNREACHABLE"; - } - std::cerr << "," << NetStateAsString(netstate) << ")"; - std::cerr << std::endl; -#endif - - if (netstate != mNetState) - { -#ifdef DEBUG_CONNECTBOX - std::cerr << "PeerConnectStateBox::connectCb() WARNING Changing NetState from: "; - std::cerr << " from: " << NetStateAsString(mNetState); - std::cerr << " to: " << NetStateAsString(netstate); - std::cerr << " for peer: " << mPeerId; - std::cerr << std::endl; -#endif - - mNetState = netstate; - } - - if (cbtype == CSB_CONNECT_DIRECT) - { - return connectCb_direct(); - } - else - { - return connectCb_unreachable(); - } -} - - -uint32_t PeerConnectStateBox::connectCb_direct() -{ - uint32_t retval = 0; - rstime_t now = time(NULL); - - switch(mState) - { - - case CSB_DIRECT_ATTEMPT: - { - errorMsg(std::cerr, "mState == DIRECT_ATTEMPT", 0); - retval = CSB_ACTION_WAIT; - } - break; - - case CSB_PROXY_ATTEMPT: - { - errorMsg(std::cerr, "mState == PROXY_ATTEMPT", 0); - retval = CSB_ACTION_WAIT; - } - break; - - case CSB_RELAY_ATTEMPT: - { - errorMsg(std::cerr, "mState == RELAY_ATTEMPT", 0); - retval = CSB_ACTION_WAIT; - } - break; - - case CSB_FAILED_WAIT: - { - /* if too soon */ - //if (now - mStateTS < FAILED_WAIT_TIME) - if (mNextAttemptTS > now) - { - /* same state */ - retval = CSB_ACTION_WAIT; - break; - } - } /* FALLTHROUGH TO START CASE */ - /* fallthrough */ - default: - case CSB_REVERSE_WAIT: - case CSB_PROXY_WAIT: - case CSB_RELAY_WAIT: - { - if (mState != CSB_FAILED_WAIT) - { - /* ERROR */ - errorMsg(std::cerr, "mState != FAILED_WAIT", 0); - - } - - } /* FALLTHROUGH TO START CASE */ - /* fallthrough */ - case CSB_START: - { - /* starting up the connection */ - mState = CSB_TCP_WAIT; - retval = CSB_ACTION_TCP_CONN; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - mNextAttemptTS = now + TCP_WAIT_TIME; - - } - break; - case CSB_TCP_WAIT: - { - /* if too soon */ - //if (now - mStateTS < TCP_WAIT_TIME) - if (mNextAttemptTS > now) - { - /* same state */ - retval = CSB_ACTION_WAIT; - } - else - { - /* try again */ - mState = CSB_DIRECT_ATTEMPT; - retval = CSB_ACTION_DIRECT_CONN | CSB_ACTION_DHT_PORT; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - } - } - break; - - case CSB_DIRECT_WAIT: - { - /* if too soon */ - //if (now - mStateTS < DIRECT_WAIT_TIME) - if (mNextAttemptTS > now) - { - /* same state */ - retval = CSB_ACTION_WAIT; - } - else if ((mNoAttempts >= MAX_DIRECT_ATTEMPTS) || - (mNoFailedAttempts >= MAX_DIRECT_FAILED_ATTEMPTS)) - { - /* if too many attempts */ - /* no RELAY attempt => FAILED_WAIT */ - mState = CSB_FAILED_WAIT; - retval = CSB_ACTION_WAIT; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - mNextAttemptTS = now + FAILED_WAIT_TIME; - } - else - { - /* try again */ - mState = CSB_DIRECT_ATTEMPT; - retval = CSB_ACTION_DIRECT_CONN | CSB_ACTION_DHT_PORT; - mStateTS = now; - mNoAttempts++; - } - } - break; - - case CSB_CONNECTED: - { - retval = CSB_ACTION_WAIT; - } - break; - } - - return retval; - -} - - -uint32_t PeerConnectStateBox::connectCb_unreachable() -{ - uint32_t retval = 0; - - uint32_t proxyPortMode = CSB_ACTION_PROXY_PORT; - if (!shouldUseProxyPortInternal(mNetState)) - { - proxyPortMode = CSB_ACTION_DHT_PORT; - } - - rstime_t now = time(NULL); - - switch(mState) - { - case CSB_DIRECT_ATTEMPT: - { - errorMsg(std::cerr, "mState == DIRECT_ATTEMPT", 0); - retval = CSB_ACTION_WAIT; - } - break; - - case CSB_PROXY_ATTEMPT: - { - errorMsg(std::cerr, "mState == PROXY_ATTEMPT", 0); - retval = CSB_ACTION_WAIT; - } - break; - - case CSB_RELAY_ATTEMPT: - { - errorMsg(std::cerr, "mState == RELAY_ATTEMPT", 0); - retval = CSB_ACTION_WAIT; - } - break; - - case CSB_FAILED_WAIT: - { - /* if too soon */ - //if (now - mStateTS < FAILED_WAIT_TIME) - if (mNextAttemptTS > now) - { - /* same state */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "too soon, no action", 0); -#endif - retval = CSB_ACTION_WAIT; - break; - } - } /* FALLTHROUGH TO START CASE */ - /* fallthrough */ - default: - case CSB_DIRECT_WAIT: - { - if (mState != CSB_FAILED_WAIT) - { - /* ERROR */ - errorMsg(std::cerr, "mState != FAILED_WAIT", 0); - - } - - } /* FALLTHROUGH TO START CASE */ - /* fallthrough */ - case CSB_START: - { - /* starting up the connection */ - mState = CSB_TCP_WAIT; - retval = CSB_ACTION_WAIT; /* NO POINT TRYING A TCP_CONN */ - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - mNextAttemptTS = now + TCP_WAIT_TIME; - - } - break; - case CSB_TCP_WAIT: - { - /* if too soon */ - if (mNextAttemptTS > now) - { - /* same state */ - retval = CSB_ACTION_WAIT; - } - else - { - /* starting up the connection */ - if (mState != CSB_NETSTATE_FIREWALLED) - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "not Firewalled => PROXY_ATTEMPT", 0); -#endif - mState = CSB_PROXY_ATTEMPT; - retval = CSB_ACTION_PROXY_CONN | proxyPortMode; - } - else - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "Firewalled => RELAY_ATTEMPT", 0); -#endif - mState = CSB_RELAY_ATTEMPT; - retval = CSB_ACTION_RELAY_CONN | CSB_ACTION_DHT_PORT; - - } - - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - } - - } - break; - case CSB_PROXY_WAIT: - { - /* if too soon */ - if (mNextAttemptTS > now) - { - /* same state */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "too soon, no action", 0); -#endif - retval = CSB_ACTION_WAIT; - } - else if ((mNoAttempts >= MAX_PROXY_ATTEMPTS) || - (mNoFailedAttempts >= MAX_PROXY_FAILED_ATTEMPTS)) - { - /* if too many attempts */ - /* switch to RELAY attempt */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "too many PROXY => RELAY_ATTEMPT", 0); -#endif - mState = CSB_RELAY_ATTEMPT; - retval = CSB_ACTION_RELAY_CONN | CSB_ACTION_DHT_PORT; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - } - else - { - /* try again */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "PROXY_ATTEMPT try again", 0); -#endif - mState = CSB_PROXY_ATTEMPT; - retval = CSB_ACTION_PROXY_CONN | proxyPortMode; - mStateTS = now; - mNoAttempts++; - } - } - break; - - case CSB_REVERSE_WAIT: - { - /* if too soon */ - //if (now - mStateTS < REVERSE_WAIT_TIME) - if (mNextAttemptTS > now) - { - /* same state */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "too soon, no action", 0); -#endif - retval = CSB_ACTION_WAIT; - } - else - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "timeout => RELAY_ATTEMPT", 0); -#endif - /* switch to RELAY attempt */ - mState = CSB_RELAY_ATTEMPT; - retval = CSB_ACTION_RELAY_CONN | CSB_ACTION_DHT_PORT; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - } - } - break; - - case CSB_RELAY_WAIT: - { - /* if too soon */ - if (mNextAttemptTS > now) - { - /* same state */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "too soon, no action", 0); -#endif - retval = CSB_ACTION_WAIT; - } - else if ((mNoAttempts >= MAX_RELAY_ATTEMPTS) || - (mNoFailedAttempts >= MAX_RELAY_FAILED_ATTEMPTS)) - { - /* if too many attempts */ - /* switch to RELAY attempt */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "too many RELAY => FAILED_WAIT", 0); -#endif - mState = CSB_FAILED_WAIT; - retval = CSB_ACTION_WAIT; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - mNextAttemptTS = now + FAILED_WAIT_TIME; - } - else - { - /* try again */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "RELAY_ATTEMPT try again", 0); -#endif - mState = CSB_RELAY_ATTEMPT; - retval = CSB_ACTION_RELAY_CONN | CSB_ACTION_DHT_PORT; - mStateTS = now; - mNoAttempts++; - } - } - break; - - case CSB_CONNECTED: - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "connected => no action", 0); -#endif - retval = CSB_ACTION_WAIT; - } - break; - } - - return retval; -} - - - -uint32_t PeerConnectStateBox::updateCb(uint32_t update) -{ - /* The Error Callback doesn't trigger another connection. - * but can change the connection state - * - * Possible Errors: - * 1) AUTH DENIED. (fatal) - * 2) MODE UNAVILABLE - * 3) RETRY ATTEMPT - * 4) FAILED ATTEMPT - * 5) CONNECTION - * 6) DISCONNECTED. - * - * Fitting these into the states: - case CSB_START: - CONNECTION => CSB_CONNECTED - error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT, DISCONNECTED - case CSB_CONNECTED: - CONNECTION => CSB_CONNECTED - DISCONNECTED => CSB_START - error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT - - case CSB_FAILED_WAIT: - CONNECTION => CSB_CONNECTED - error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT, DISCONNECTED - case CSB_REVERSE_WAIT: - CONNECTION => CSB_CONNECTED - error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT, DISCONNECTED - case CSB_DIRECT_ATTEMPT: - CONNECTION => CSB_CONNECTED - AUTH DENIED => CSB_FAILED_WAIT - FAILED ATTEMPT => stay here. - RETRY ATTEMPT => stay here - MODE UNAVAILABLE - probably error => CSB_FAILED_WAIT - error if: MODE UNAVAILABLE, DISCONNECTED - - case CSB_PROXY_ATTEMPT: - CONNECTION => CSB_CONNECTED - AUTH DENIED => CSB_FAILED_WAIT - FAILED ATTEMPT => stay here. - RETRY ATTEMPT => stay here - MODE_UNAVAILABLE => CSB_REVERSE_WAIT | CSB_RELAY_ATTEMPT - error if: DISCONNECTED - - case CSB_RELAY_ATTEMPT: - CONNECTION => CSB_CONNECTED - AUTH DENIED => CSB_FAILED_WAIT - FAILED ATTEMPT => stay here. - RETRY ATTEMPT => stay here - MODE_UNAVAILABLE => CSB_FAILED_WAIT - error if: DISCONNECTED - - case CSB_DIRECT_WAIT: - CONNECTION => CSB_CONNECTED - error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT, DISCONNECTED - case CSB_PROXY_WAIT: - CONNECTION => CSB_CONNECTED - error if: AUTH_DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT, DISCONNECTED - case CSB_RELAY_ATTEMPT: - CONNECTION => CSB_CONNECTED - error if: AUTH_DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT, DISCONNECTED - */ - - /* DO Connect / Disconnect Updates ... very specific! */ - rstime_t now = time(NULL); - switch(update) - { - case CSB_UPDATE_CONNECTED: - { - if ((mState == CSB_DIRECT_ATTEMPT) || (mState == CSB_PROXY_ATTEMPT) || (mState == CSB_RELAY_ATTEMPT)) - { - mAttemptLength = now - mStateTS; - } - else - { - mAttemptLength = 0; - } - -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "=> CONNECTED", update); -#endif - mState = CSB_CONNECTED; - mStateTS = now; - - return 0; - } - break; - case CSB_UPDATE_DISCONNECTED: - { - if (mState != CSB_CONNECTED) - { - /* ERROR, ignore (as already in disconnected state) */ - errorMsg(std::cerr, "mState != CSB_CONNECTED", update); - - } - else - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "=> START", update); -#endif - /* move to START state */ - mState = CSB_START; - mStateTS = now; - return 1; - } - - return 0; - } - break; - } - - - /* Now catch errors for feedback when we should be WAITING */ - switch(mState) - { - default: - case CSB_DIRECT_WAIT: - case CSB_PROXY_WAIT: - case CSB_RELAY_WAIT: - case CSB_REVERSE_WAIT: - case CSB_FAILED_WAIT: - case CSB_START: - case CSB_CONNECTED: /* impossible */ - { - /* ERROR */ - /* shouldn't receive anything here! */ - errorMsg(std::cerr, "shouldnt get anything", update); - - return 0; - } - break; - - case CSB_DIRECT_ATTEMPT: - case CSB_PROXY_ATTEMPT: - case CSB_RELAY_ATTEMPT: - { - /* OKAY */ - - } - break; - } - - - switch(update) - { - /* if AUTH_DENIED ... => FAILED_WAIT */ - case CSB_UPDATE_AUTH_DENIED: - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "=> FAILED WAIT", update); -#endif - mState = CSB_FAILED_WAIT; - mStateTS = now; - mAttemptLength = now - mStateTS; - mNextAttemptTS = now + FAILED_WAIT_TIME; - - return 1; - } - break; - /* if standard FAIL => stay where we are */ - case CSB_UPDATE_RETRY_ATTEMPT: - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "RETRY FAIL => switch to wait state", update); -#endif - mAttemptLength = now - mStateTS; - switch(mState) - { - case CSB_DIRECT_ATTEMPT: - mState = CSB_DIRECT_WAIT; - mStateTS = now; - mNextAttemptTS = now + RSRandom::random_u32() % DIRECT_MAX_WAIT_TIME; - break; - case CSB_PROXY_ATTEMPT: - mState = CSB_PROXY_WAIT; - mStateTS = now; - mNextAttemptTS = now + PROXY_BASE_WAIT_TIME + (RSRandom::random_u32() % (PROXY_MAX_WAIT_TIME - PROXY_BASE_WAIT_TIME)); - break; - case CSB_RELAY_ATTEMPT: - mState = CSB_RELAY_WAIT; - mStateTS = now; - mNextAttemptTS = now + RSRandom::random_u32() % RELAY_MAX_WAIT_TIME; - break; - default: -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "RETRY FAIL, but unusual state", update); -#endif - break; - } - - return 1; - } - /* if standard FAIL => stay where we are */ - case CSB_UPDATE_FAILED_ATTEMPT: - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "STANDARD FAIL => switch to wait state", update); -#endif - mNoFailedAttempts++; - mAttemptLength = now - mStateTS; - switch(mState) - { - case CSB_DIRECT_ATTEMPT: - mState = CSB_DIRECT_WAIT; - mStateTS = now; - mNextAttemptTS = now + RSRandom::random_u32() % DIRECT_MAX_WAIT_TIME; - break; - case CSB_PROXY_ATTEMPT: - mState = CSB_PROXY_WAIT; - mStateTS = now; - mNextAttemptTS = now + PROXY_BASE_WAIT_TIME + (RSRandom::random_u32() % (PROXY_MAX_WAIT_TIME - PROXY_BASE_WAIT_TIME)); - break; - case CSB_RELAY_ATTEMPT: - mState = CSB_RELAY_WAIT; - mStateTS = now; - mNextAttemptTS = now + RSRandom::random_u32() % RELAY_MAX_WAIT_TIME; - break; - default: -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "STANDARD FAIL, but unusual state", update); -#endif - break; - } - - return 1; - } - break; - - /* finally MODE_UNAVAILABLE */ - case CSB_UPDATE_MODE_UNAVAILABLE: - { - mAttemptLength = now - mStateTS; - if (mState == CSB_PROXY_ATTEMPT) - { - if (mNetState == CSB_NETSTATE_FORWARD) - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "as FORWARDED => REVERSE_WAIT", update); -#endif - mState = CSB_REVERSE_WAIT; - mStateTS = now; - mNextAttemptTS = now + REVERSE_WAIT_TIME; - } - else - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "as !FORWARDED => RELAY_ATTEMPT", update); -#endif - mState = CSB_RELAY_WAIT; - mNoAttempts = 0; - mStateTS = now; - mNextAttemptTS = now + RSRandom::random_u32() % RELAY_MAX_WAIT_TIME; - } - return 1; - } - else - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "MODE UNAVAIL => FAILED_WAIT", update); -#endif - mState = CSB_FAILED_WAIT; - mStateTS = now; - mNextAttemptTS = now + FAILED_WAIT_TIME; - - if ((mState == CSB_DIRECT_ATTEMPT) - || (mState == CSB_PROXY_ATTEMPT)) - { - /* OKAY */ - return 1; - } - else - { - /* ERROR */ - errorMsg(std::cerr, "strange MODE", update); - - return 0; - } - } - } - break; - - default: - { - /* ERROR */ - errorMsg(std::cerr, "impossible default", update); - } - break; - } - - /* if we get here... ERROR */ - errorMsg(std::cerr, "if we get here => ERROR", update); - - - return 0; -} - - - - - - - - - - -bool PeerConnectStateBox::storeProxyPortChoice(uint32_t flags, bool useProxyPort) -{ - mProxyPortFlags = flags; - mProxyPortChoice = useProxyPort; - mProxyPortTS = time(NULL); - - return useProxyPort; -} - -bool PeerConnectStateBox::getProxyPortChoice() -{ -#ifdef DEBUG_CONNECTBOX - rstime_t now = time(NULL); - - std::cerr << "PeerConnectStateBox::getProxyPortChoice() Using ConnectLogic Info from: "; - std::cerr << now-mProxyPortTS << " ago. Flags: " << mProxyPortFlags; - std::cerr << " UseProxyPort? " << mProxyPortChoice; - std::cerr << std::endl; -#endif - - return mProxyPortChoice; -} - - - diff --git a/libretroshare/src/dht/connectstatebox.h b/libretroshare/src/dht/connectstatebox.h deleted file mode 100644 index 20c6fdb20..000000000 --- a/libretroshare/src/dht/connectstatebox.h +++ /dev/null @@ -1,122 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: connectstatebox.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef CONNECT_STATUS_BOX_H -#define CONNECT_STATUS_BOX_H - -/* a connect state box */ - -#define CSB_START 1 -#define CSB_TCP_WAIT 2 -#define CSB_DIRECT_ATTEMPT 3 -#define CSB_DIRECT_WAIT 4 -#define CSB_PROXY_ATTEMPT 5 -#define CSB_PROXY_WAIT 6 -#define CSB_RELAY_ATTEMPT 7 -#define CSB_RELAY_WAIT 8 -#define CSB_REVERSE_WAIT 9 -#define CSB_FAILED_WAIT 10 -#define CSB_CONNECTED 11 - - -#define CSB_NETSTATE_UNKNOWN 0 -#define CSB_NETSTATE_FORWARD 1 -#define CSB_NETSTATE_STABLENAT 2 -#define CSB_NETSTATE_EXCLUSIVENAT 3 -#define CSB_NETSTATE_FIREWALLED 4 - -#define CSB_CONNECT_DIRECT 1 -#define CSB_CONNECT_UNREACHABLE 2 - -/* return values */ -#define CSB_ACTION_MASK_MODE 0x00ff -#define CSB_ACTION_MASK_PORT 0xff00 - -#define CSB_ACTION_WAIT 0x0001 -#define CSB_ACTION_TCP_CONN 0x0002 -#define CSB_ACTION_DIRECT_CONN 0x0004 -#define CSB_ACTION_PROXY_CONN 0x0008 -#define CSB_ACTION_RELAY_CONN 0x0010 - -#define CSB_ACTION_DHT_PORT 0x0100 -#define CSB_ACTION_PROXY_PORT 0x0200 - -/* update input */ -#define CSB_UPDATE_NONE 0x0000 -#define CSB_UPDATE_CONNECTED 0x0001 -#define CSB_UPDATE_DISCONNECTED 0x0002 -#define CSB_UPDATE_AUTH_DENIED 0x0003 -#define CSB_UPDATE_RETRY_ATTEMPT 0x0004 -#define CSB_UPDATE_FAILED_ATTEMPT 0x0005 -#define CSB_UPDATE_MODE_UNAVAILABLE 0x0006 - -#include -#include - -#include -#include "util/rstime.h" -#include - -#include - -class PeerConnectStateBox -{ - public: - PeerConnectStateBox(); - - uint32_t connectCb(uint32_t cbtype, RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype); - uint32_t updateCb(uint32_t updateType); - - bool shouldUseProxyPort(RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype); - - uint32_t calcNetState(RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype); - std::string connectState() const; - - std::string mPeerId; - - bool storeProxyPortChoice(uint32_t flags, bool useProxyPort); - bool getProxyPortChoice(); - - private: - - uint32_t connectCb_direct(); - uint32_t connectCb_unreachable(); - - void errorMsg(std::ostream &out, std::string msg, uint32_t updateParam); - void stateMsg(std::ostream &out, std::string msg, uint32_t updateParam); - - - uint32_t mState; - uint32_t mNetState; - rstime_t mStateTS; - uint32_t mNoAttempts; - uint32_t mNoFailedAttempts; - rstime_t mNextAttemptTS; - rstime_t mAttemptLength; - - // ProxyPort Storage. - uint32_t mProxyPortFlags; - bool mProxyPortChoice; - rstime_t mProxyPortTS; -}; - - -#endif diff --git a/libretroshare/src/dht/p3bitdht.cc b/libretroshare/src/dht/p3bitdht.cc deleted file mode 100644 index 9e4798066..000000000 --- a/libretroshare/src/dht/p3bitdht.cc +++ /dev/null @@ -1,460 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: p3bitdht.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include - -#include "dht/p3bitdht.h" - -#include "bitdht/bdstddht.h" - -#include "tcponudp/udprelay.h" -#ifdef RS_USE_DHT_STUNNER -#include "tcponudp/udpstunner.h" -#endif // RS_USE_DHT_STUNNER - -#include "retroshare/rsbanlist.h" - -#include - - -/* This is a conversion callback class between pqi interface - * and the BitDht Interface. - * - */ - -/**** EXTERNAL INTERFACE DHT POINTER *****/ -RsDht *rsDht = NULL; - -class p3BdCallback: public BitDhtCallback -{ - public: - - p3BdCallback(p3BitDht *parent) - :mParent(parent) { return; } - -virtual int dhtNodeCallback(const bdId *id, uint32_t peerflags) -{ - return mParent->NodeCallback(id, peerflags); -} - -virtual int dhtPeerCallback(const bdId *id, uint32_t status) -{ - return mParent->PeerCallback(id, status); -} - -virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) -{ - return mParent->ValueCallback(id, key, status); -} - -virtual int dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t point, uint32_t param, uint32_t cbtype, uint32_t errcode) -{ - return mParent->ConnectCallback(srcId, proxyId, destId, mode, point, param, cbtype, errcode); -} - -virtual int dhtInfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info) -{ - return mParent->InfoCallback(id, type, flags, info); -} - - virtual int dhtIsBannedCallback(const sockaddr_in *addr, bool *isBanned) - { - if(!rsBanList) - { - *isBanned = true; // rsBanList is not enabled yet. For security, default to banned. - return 0; - } - - // check whether ip filtering is enabled - // if not return 0 to signal that no filter is available - if(!rsBanList->ipFilteringEnabled()) - return 0; - - // now check the filter - if(rsBanList->isAddressAccepted( - *reinterpret_cast(addr), - RSBANLIST_CHECKING_FLAGS_BLACKLIST )) - { - *isBanned = false; - } else { -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht dhtIsBannedCallback: peer is banned " << sockaddr_storage_tostring(*(const sockaddr_storage*)addr) << std::endl; -#endif - *isBanned = true; - } - - // return 1 to signal that a filter is available - return 1; - } - - private: - - p3BitDht *mParent; -}; - - -p3BitDht::p3BitDht(const RsPeerId& id, pqiConnectCb *cb, p3NetMgr *nm, - UdpStack *udpstack, std::string bootstrapfile, std::string bootstrapfilebak, const std::string& filteredipfile) - :p3Config(), pqiNetAssistConnect(id, cb), mNetMgr(nm), dhtMtx("p3BitDht") -{ -#ifdef RS_USE_DHT_STUNNER - mDhtStunner = NULL; - mProxyStunner = NULL; -#endif - mRelay = NULL; - - mPeerSharer = NULL; - - mRelayHandler = NULL; - - std::string dhtVersion = "RS51"; // should come from elsewhere! - mOwnRsId = id; - - mMinuteTS = 0; - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::p3BitDht()" << std::endl; - std::cerr << "Using Id: " << id; - std::cerr << std::endl; - std::cerr << "Using Bootstrap File: " << bootstrapfile; - std::cerr << std::endl; - std::cerr << "Converting OwnId to bdNodeId...."; - std::cerr << std::endl; -#endif - - /* setup ownId */ - storeTranslation_locked(id); - lookupNodeId_locked(id, &mOwnDhtId); - - -#ifdef DEBUG_BITDHT - std::cerr << "Own NodeId: "; - bdStdPrintNodeId(std::cerr, &mOwnDhtId); - std::cerr << std::endl; -#endif - - /* standard dht behaviour */ - //bdDhtFunctions *stdfns = new bdStdDht(); - mDhtFns = new bdModDht(); - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht() startup ... creating UdpBitDht"; - std::cerr << std::endl; -#endif - - /* create dht */ - mUdpBitDht = new UdpBitDht(udpstack, &mOwnDhtId, dhtVersion, bootstrapfile, bootstrapfilebak, filteredipfile,mDhtFns); - udpstack->addReceiver(mUdpBitDht); - - /* setup callback to here */ - p3BdCallback *bdcb = new p3BdCallback(this); - mUdpBitDht->addCallback(bdcb); - -#if 0 - /* enable all modes */ - /* Switched to only Proxy Mode - as Direct Connections can be unreliable - as they share the UDP with the DHT.... - * We'll get these working properly and then if necessary get Direct further tested. - */ - mUdpBitDht->ConnectionOptions( - // BITDHT_CONNECT_MODE_DIRECT | BITDHT_CONNECT_MODE_PROXY | BITDHT_CONNECT_MODE_RELAY, - //BITDHT_CONNECT_MODE_DIRECT | BITDHT_CONNECT_MODE_PROXY, - BITDHT_CONNECT_MODE_PROXY, - BITDHT_CONNECT_OPTION_AUTOPROXY); - -#endif - - setupRelayDefaults(); - - clearDataRates(); -} - -p3BitDht::~p3BitDht() -{ - //udpstack->removeReceiver(mUdpBitDht); - delete mUdpBitDht; -} - - -bool p3BitDht::getOwnDhtId(std::string &ownDhtId) -{ - bdStdPrintNodeId(ownDhtId, &(mOwnDhtId), false); - return true; -} - -#ifdef RS_USE_DHT_STUNNER -void p3BitDht::setupConnectBits(UdpStunner *dhtStunner, UdpStunner *proxyStunner, UdpRelayReceiver *relay) -{ - mDhtStunner = dhtStunner; - mProxyStunner = proxyStunner; - mRelay = relay; -} -#else // RS_USE_DHT_STUNNER -void p3BitDht::setupConnectBits(UdpRelayReceiver *relay) -{ - mRelay = relay; -} -#endif //RS_USE_DHT_STUNNER - -void p3BitDht::setupPeerSharer(pqiNetAssistPeerShare *sharer) -{ - mPeerSharer = sharer; -} - - /* Tweak the DHT Parameters */ -void p3BitDht::modifyNodesPerBucket(uint16_t count) -{ - bdModDht *modFns = (bdModDht *) mDhtFns; - modFns->setNodesPerBucket(count); -} - -/* Support for Outsourced Relay Handling */ - -void p3BitDht::installRelayHandler(p3BitDhtRelayHandler *handler) -{ - /* The Handler is mutex protected, as its installation can occur when the dht is already running */ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - mRelayHandler = handler; -} - -UdpRelayReceiver *p3BitDht::getRelayReceiver() -{ - return mRelay; -} - - -void p3BitDht::start() -{ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::start()"; - std::cerr << std::endl; -#endif - - mUdpBitDht->start(); /* starts up the bitdht thread */ - - /* dht switched on by config later. */ -} - - /* pqiNetAssist - external interface functions */ -void p3BitDht::enable(bool on) -{ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::enable(" << on << ")"; - std::cerr << std::endl; -#endif - - if (on) - { - mUdpBitDht->startDht(); - } - else - { - mUdpBitDht->stopDht(); - } -} - -void p3BitDht::shutdown() /* blocking call */ -{ - mUdpBitDht->stopDht(); -} - - -void p3BitDht::restart() -{ - mUdpBitDht->stopDht(); - mUdpBitDht->startDht(); -} - -bool p3BitDht::getEnabled() -{ - return (mUdpBitDht->stateDht() != 0); -} - -bool p3BitDht::getActive() -{ - return (mUdpBitDht->stateDht() >= BITDHT_MGR_STATE_ACTIVE); -} - -bool p3BitDht::getNetworkStats(uint32_t &netsize, uint32_t &localnetsize) -{ - netsize = mUdpBitDht->statsNetworkSize(); - localnetsize = mUdpBitDht->statsBDVersionSize(); - return true; -} - -#if 0 - /* pqiNetAssistConnect - external interface functions */ - /* add / remove peers */ -bool p3BitDht::findPeer(std::string pid) -{ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer(" << pid << ")"; - std::cerr << std::endl; -#endif - - /* convert id -> NodeId */ - if (!storeTranslation(pid)) - { - std::cerr << "p3BitDht::findPeer() Failed to storeTranslation"; - std::cerr << std::endl; - - /* error */ - return false; - } - - bdNodeId nid; - if (!lookupNodeId(pid, &nid)) - { - std::cerr << "p3BitDht::findPeer() Failed to lookupNodeId"; - std::cerr << std::endl; - - /* error */ - return false; - } - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() calling AddFindNode() with pid => NodeId: "; - bdStdPrintNodeId(std::cerr, &nid); - std::cerr << std::endl; -#endif - - /* add in peer */ - mUdpBitDht->addFindNode(&nid, BITDHT_QFLAGS_DO_IDLE); - - return true ; -} - -bool p3BitDht::dropPeer(std::string pid) -{ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::dropPeer(" << pid << ")"; - std::cerr << std::endl; -#endif - - /* convert id -> NodeId */ - bdNodeId nid; - if (!lookupNodeId(pid, &nid)) - { - std::cerr << "p3BitDht::dropPeer() Failed to lookup NodeId"; - std::cerr << std::endl; - - /* error */ - return false; - } - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::dropPeer() Translated to NodeId: "; - bdStdPrintNodeId(std::cerr, &nid); - std::cerr << std::endl; -#endif - - /* remove in peer */ - mUdpBitDht->removeFindNode(&nid); - - /* remove from translation */ - if (!removeTranslation(pid)) - { - std::cerr << "p3BitDht::dropPeer() Failed to removeTranslation"; - std::cerr << std::endl; - - /* error */ - return false; - } - - return true ; -} - -#endif - - - /* extract current peer status */ -bool p3BitDht::getPeerStatus(const RsPeerId& id, - struct sockaddr_storage &/*laddr*/, struct sockaddr_storage &/*raddr*/, - uint32_t &/*type*/, uint32_t &/*mode*/) -{ - /* remove unused parameter warnings */ - (void) id; - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::getPeerStatus(" << id << ")"; - std::cerr << std::endl; -#endif - - return false; -} - -bool p3BitDht::getExternalInterface(struct sockaddr_storage &/*raddr*/, - uint32_t &/*mode*/) -{ - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::getExternalInterface()"; - std::cerr << std::endl; -#endif - - - return false; -} - -bool p3BitDht::isAddressBanned(const sockaddr_storage &raddr) -{ - if(raddr.ss_family == AF_INET6) // the DHT does not handle INET6 addresses yet. - return false ; - - if(raddr.ss_family == AF_INET) - return mUdpBitDht->isAddressBanned((sockaddr_in&)raddr) ; - - return false ; -} - -void p3BitDht::getListOfBannedIps(std::list& ips) -{ - std::list lst ; - - mUdpBitDht->getListOfBannedIps(lst) ; - - for(std::list::const_iterator it(lst.begin());it!=lst.end();++it) - { - RsDhtFilteredPeer fp ; - fp.mAddr = (*it).mAddr ; - fp.mFilterFlags = (*it).mFilterFlags ; - fp.mFilterTS = (*it).mFilterTS ; - fp.mLastSeen = (*it).mLastSeen ; - ips.push_back(fp) ; - } -} - -bool p3BitDht::setAttachMode(bool on) -{ - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::setAttachMode(" << on << ")"; - std::cerr << std::endl; -#endif - - return mUdpBitDht->setAttachMode(on); -} - - - - diff --git a/libretroshare/src/dht/p3bitdht.h b/libretroshare/src/dht/p3bitdht.h deleted file mode 100644 index 26cb43847..000000000 --- a/libretroshare/src/dht/p3bitdht.h +++ /dev/null @@ -1,398 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: p3bitdht.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef MRK_P3_BITDHT_H -#define MRK_P3_BITDHT_H - -#include "pqi/pqiassist.h" -#include "pqi/p3cfgmgr.h" -#include "retroshare/rsdht.h" - -#include -#include -#include "pqi/pqinetwork.h" -#include "pqi/pqimonitor.h" -#include "util/rsthreads.h" - -#include "udp/udpstack.h" -#include "udp/udpbitdht.h" -#include "bitdht/bdiface.h" - -#include "dht/connectstatebox.h" - -class DhtPeerDetails -{ - public: - - DhtPeerDetails(); - - RsDhtPeerType mPeerType; - - bdId mDhtId; - RsPeerId mRsId; - - /* direct from the DHT! */ - RsDhtPeerDht mDhtState; - rstime_t mDhtUpdateTS; - - /* internal state */ - PeerConnectStateBox mConnectLogic; - - /* Actual Connection Status */ - RsDhtPeerConnectState mPeerConnectState; - std::string mPeerConnectMsg; - uint32_t mPeerConnectMode; - bdId mPeerConnectPeerId; - bdId mPeerConnectProxyId; - struct sockaddr_in mPeerConnectAddr; - uint32_t mPeerConnectPoint; - - rstime_t mPeerConnectUdpTS; - rstime_t mPeerConnectTS; - rstime_t mPeerConnectClosedTS; - - bool mExclusiveProxyLock; - - /* keeping the PeerCbMsg, as we will need it for debugging */ - /* don't think this data is ever used for decisions??? */ - - /* Connection Request Status */ - std::string mPeerReqStatusMsg; - RsDhtPeerRequest mPeerReqState; - uint32_t mPeerReqMode; - bdId mPeerReqProxyId; - rstime_t mPeerReqTS; - - /* Callback Info */ - std::string mPeerCbMsg; - uint32_t mPeerCbMode; - uint32_t mPeerCbPoint; - bdId mPeerCbProxyId; - bdId mPeerCbDestId; - rstime_t mPeerCbTS; - -}; - -#define PEERNET_ACTION_TYPE_CONNECT 1 -#define PEERNET_ACTION_TYPE_AUTHORISE 2 -#define PEERNET_ACTION_TYPE_START 3 -#define PEERNET_ACTION_TYPE_RESTARTREQ 4 -#define PEERNET_ACTION_TYPE_KILLREQ 5 -#define PEERNET_ACTION_TYPE_TCPATTEMPT 6 - -class PeerAction -{ - public: - - uint32_t mType; - bdId mSrcId; - bdId mProxyId; - bdId mDestId; - uint32_t mMode; - uint32_t mPoint; - uint32_t mAnswer; - uint32_t mDelayOrBandwidth; -}; - - - -/****** - * Adding the ability to install alternative Handler - * for monitoring/controlling Relay Connections outside of p3bitdht. - ***/ - -class p3BitDhtRelayHandler -{ - public: - - int (*mInstallRelay)(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t &bandwidth); - int (*mLogFailedConnection)(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t errcode); -}; - - - - -class UdpRelayReceiver; -#ifdef RS_USE_DHT_STUNNER -class UdpStunner; -#endif // RS_USE_DHT_STUNNER -class p3NetMgr; - -class p3BitDht: public p3Config, public pqiNetAssistConnect, public RsDht -{ -public: - p3BitDht(const RsPeerId& id, pqiConnectCb *cb, p3NetMgr *nm, - UdpStack *udpstack, std::string bootstrapfile, std::string bootstrapfilebak, const std::string &filteredipfile); - - - virtual ~p3BitDht(); - - - /*********************************************************************************************** - ********** External RsDHT Interface (defined in libretroshare/src/retroshare/rsdht.h) ********* -************************************************************************************************/ - - virtual uint32_t getNetState(uint32_t type); - virtual int getDhtPeers(int lvl, std::list &peers); - virtual int getNetPeerList(std::list &peerIds); - virtual int getNetPeerStatus(const RsPeerId& peerId, RsDhtNetPeer &status); - - virtual int getRelayEnds(std::list &relayEnds); - virtual int getRelayProxies(std::list &relayProxies); - - //virtual int getNetFailedPeer(std::string peerId, PeerStatus &status); - - virtual std::string getUdpAddressString(); - - virtual void getDhtRates(float &read, float &write); - virtual void getRelayRates(float &read, float &write, float &relay); - - virtual bool getOwnDhtId(std::string &ownDhtId); - - /*********************************************************************************************** - ********** External RsDHT Interface (defined in libretroshare/src/retroshare/rsdht.h) ********* -************************************************************************************************/ - -#ifdef RS_USE_DHT_STUNNER - void setupConnectBits(UdpStunner *dhtStunner, UdpStunner *proxyStunner, UdpRelayReceiver *relay); -#else // RS_USE_DHT_STUNNER - void setupConnectBits(UdpRelayReceiver *relay); -#endif // RS_USE_DHT_STUNNER - void setupPeerSharer(pqiNetAssistPeerShare *sharer); - void modifyNodesPerBucket(uint16_t count); - - void start(); /* starts up the bitdht thread */ - - /* pqiNetAssist - external interface functions */ - virtual int tick(); - virtual void enable(bool on); - virtual void shutdown(); /* blocking call */ - virtual void restart(); - - virtual bool getEnabled(); - virtual bool getActive(); - virtual bool getNetworkStats(uint32_t &netsize, uint32_t &localnetsize); - - /* pqiNetAssistConnect - external interface functions */ - - /* add / remove peers */ - virtual bool findPeer(const RsPeerId& id); - virtual bool dropPeer(const RsPeerId& id); - - virtual int addBadPeer(const struct sockaddr_storage &addr, uint32_t reason, uint32_t flags, uint32_t age); - virtual int addKnownPeer(const RsPeerId &pid, const struct sockaddr_storage &addr, uint32_t flags); - //virtual int addFriend(const std::string pid); - //virtual int addFriendOfFriend(const std::string pid); - //virtual int addOther(const std::string pid); - - /* feedback on success failure of Connections */ - virtual void ConnectionFeedback(const RsPeerId& pid, int state); - - /* extract current peer status */ - virtual bool getPeerStatus(const RsPeerId& id, - struct sockaddr_storage &laddr, struct sockaddr_storage &raddr, - uint32_t &type, uint32_t &mode); - - virtual bool getExternalInterface(struct sockaddr_storage &raddr, - uint32_t &mode); - - virtual bool isAddressBanned(const struct sockaddr_storage& raddr) ; - virtual void getListOfBannedIps(std::list &lst) ; - - virtual bool setAttachMode(bool on); - - - - /* notifyPeer/setExtInterface/Bootstrap/Stun - * hould all be removed from NetAssist? - */ - - - - /* pqiNetAssistConnect - external interface functions */ - - - /*********************************************************************************************** - ****************************** Connections (p3bitdht_peernet.cc) ****************************** -************************************************************************************************/ - /* Feedback from RS Upper Layers */ - //virtual void ConnectionFeedback(std::string pid, int state); - - /* Callback functions - from bitdht */ - int NodeCallback(const bdId *id, uint32_t peerflags); - int PeerCallback(const bdId *id, uint32_t status); - int ValueCallback(const bdNodeId *id, std::string key, uint32_t status); - int ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t point, uint32_t param, uint32_t cbtype, uint32_t errcode); - int InfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info); - - - int OnlinePeerCallback_locked(const bdId *id, uint32_t status, DhtPeerDetails *dpd); - int UnreachablePeerCallback_locked(const bdId *id, uint32_t status, DhtPeerDetails *dpd); - //int tick(); - int minuteTick(); - int doActions(); - int checkProxyAllowed(const bdId *srcId, const bdId *destId, int mode, uint32_t &bandwidth); - int checkConnectionAllowed(const bdId *peerId, int mode); - void initiateConnection(const bdId *srcId, const bdId *proxyId, const bdId *destId, uint32_t mode, uint32_t loc, uint32_t delayOrBandwidth); - int installRelayConnection(const bdId *srcId, const bdId *destId, uint32_t &bandwidth); - int removeRelayConnection(const bdId *srcId, const bdId *destId); - void monitorConnections(); - - void ConnectCallout(const RsPeerId &peerId, struct sockaddr_in addr, uint32_t connectMode); - - void ConnectCalloutTCPAttempt(const RsPeerId &peerId, struct sockaddr_in addr); - void ConnectCalloutDirectOrProxy(const RsPeerId &peerId, struct sockaddr_in raddr, uint32_t connectFlags, uint32_t delay); - void ConnectCalloutRelay(const RsPeerId &peerId, struct sockaddr_in srcaddr, - struct sockaddr_in proxyaddr, struct sockaddr_in destaddr, - uint32_t connectMode, uint32_t bandwidth); - - - void Feedback_Connected(const RsPeerId& pid); - void Feedback_ConnectionFailed(const RsPeerId& pid); - void Feedback_ConnectionClosed(const RsPeerId& pid); - - void UdpConnectionFailed_locked(DhtPeerDetails *dpd); - void ReleaseProxyExclusiveMode_locked(DhtPeerDetails *dpd, bool addrChgLikely); - - - /*** RELAY HANDLER CODE ***/ - void installRelayHandler(p3BitDhtRelayHandler *); - UdpRelayReceiver *getRelayReceiver(); - - int RelayHandler_InstallRelayConnection(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t &bandwidth); - int RelayHandler_LogFailedProxyAttempt(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t errcode); - - - - /*********************************************************************************************** - ******************** Relay Config Stuff (TEMP - MOSTLY, in p3bitdht_relay.cc) ***************** - ********** External RsDHT Interface (defined in libretroshare/src/retroshare/rsdht.h) ********* -************************************************************************************************/ - - // Interface for controlling Relays & DHT Relay Mode - virtual int getRelayServerList(std::list &ids); - virtual int addRelayServer(std::string ids); - virtual int removeRelayServer(std::string ids); - - virtual RsDhtRelayMode getRelayMode(); - virtual int setRelayMode(RsDhtRelayMode mode); - - virtual int getRelayAllowance(RsDhtRelayClass classIdx, uint32_t &count, uint32_t &bandwidth); - virtual int setRelayAllowance(RsDhtRelayClass classIdx, uint32_t count, uint32_t bandwidth); - -private: - - // Relay Handling Code / Variables (Mutex Protected). - int setupRelayDefaults(); - int pushRelayServers(); - - std::list mRelayServerList; - RsDhtRelayMode mRelayMode; - -protected: - /*****************************************************************/ - /*********************** p3config ******************************/ - /* Key Functions to be overloaded for Full Configuration */ - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool &cleanup, std::list&); - virtual void saveDone(); - virtual bool loadList(std::list& load); - /*****************************************************************/ - - // DATA RATES: Variables (Mutex Protected). -private: - - void updateDataRates(); - void clearDataRates(); - - float mRelayReadRate; - float mRelayWriteRate; - float mRelayRelayRate; - float mDhtReadRate; - float mDhtWriteRate; - - rstime_t mLastDataRateUpdate; - - - /*********************************************************************************************** - ************************** Internal Accounting (p3bitdht_peers.cc) **************************** -************************************************************************************************/ - -public: - - int removePeer(const RsPeerId& pid); - - // Can be used externally too. - int calculateNodeId(const RsPeerId& pid, bdNodeId *id); - int addKnownNode(const bdId *id, uint32_t flags); - -private: - - DhtPeerDetails *addInternalPeer_locked(const RsPeerId& pid, RsDhtPeerType type); - int removeInternalPeer_locked(const RsPeerId& pid); - DhtPeerDetails *findInternalDhtPeer_locked(const bdNodeId *id, RsDhtPeerType type); - DhtPeerDetails *findInternalRsPeer_locked(const RsPeerId &pid); - - bool havePeerTranslation_locked(const RsPeerId &pid); - int lookupNodeId_locked(const RsPeerId& pid, bdNodeId *id); - int lookupRsId_locked(const bdNodeId *id, RsPeerId &pid); - int storeTranslation_locked(const RsPeerId& pid); - int removeTranslation_locked(const RsPeerId& pid); - - UdpBitDht *mUdpBitDht; /* has own mutex, is static except for creation/destruction */ -#ifdef RS_USE_DHT_STUNNER - UdpStunner *mDhtStunner; - UdpStunner *mProxyStunner; -#endif // RS_USE_DHT_STUNNER - UdpRelayReceiver *mRelay; - - p3NetMgr *mNetMgr; - - pqiNetAssistPeerShare *mPeerSharer; - - bdDhtFunctions *mDhtFns; - - RsMutex dhtMtx; - - - p3BitDhtRelayHandler *mRelayHandler; - - RsPeerId mOwnRsId; - bdNodeId mOwnDhtId; - - rstime_t mMinuteTS; - - /* translation maps */ - std::map mTransToNodeId; - std::map mTransToRsId; - - std::map mPeers; - std::map mFailedPeers; - - /* Connection Action Queue */ - std::list mActions; - -}; - -#endif /* MRK_P3_BITDHT_H */ - diff --git a/libretroshare/src/dht/p3bitdht_interface.cc b/libretroshare/src/dht/p3bitdht_interface.cc deleted file mode 100644 index b31bbd03c..000000000 --- a/libretroshare/src/dht/p3bitdht_interface.cc +++ /dev/null @@ -1,387 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: p3bitdht_interface.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "util/rsnet.h" -#include "dht/p3bitdht.h" - -#include "tcponudp/udprelay.h" -#include "tcponudp/udpstunner.h" -#include "bitdht/bdstddht.h" - - -void convertBdPeerToRsDhtPeer(RsDhtPeer &peer, const bdPeer &int_peer); -void convertDhtPeerDetailsToRsDhtNetPeer(RsDhtNetPeer &status, const DhtPeerDetails &details); -void convertUdpRelayEndtoRsDhtRelayEnd(RsDhtRelayEnd &end, const UdpRelayEnd &int_end); -void convertUdpRelayProxytoRsDhtRelayProxy(RsDhtRelayProxy &proxy, const UdpRelayProxy &int_proxy); - - -/*********************************************************************************************** - ********** External RsDHT Interface (defined in libretroshare/src/retroshare/rsdht.h) ********* -************************************************************************************************/ - -uint32_t p3BitDht::getNetState(uint32_t /*type*/) -{ - - return 1; -} - -int p3BitDht::getDhtPeers(int lvl, std::list &peers) -{ - /* this function we can actually implement! */ - bdBucket int_peers; - std::list::iterator it; - mUdpBitDht->getDhtBucket(lvl, int_peers); - - for(it = int_peers.entries.begin(); it != int_peers.entries.end(); ++it) - { - RsDhtPeer peer; - - convertBdPeerToRsDhtPeer(peer, *it); - peer.mBucket = lvl; - - peers.push_back(peer); - } - return (int_peers.entries.size() > 0); -} - -int p3BitDht::getNetPeerList(std::list &peerIds) -{ - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - std::map::iterator it; - for(it = mPeers.begin(); it != mPeers.end(); ++it) - { - peerIds.push_back(it->second.mRsId); - } - - return 1; -} - -int p3BitDht::getNetPeerStatus(const RsPeerId& peerId, RsDhtNetPeer &status) -{ - - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - - DhtPeerDetails *dpd = findInternalRsPeer_locked(peerId); - if (!dpd) - { - return 0; - } - - convertDhtPeerDetailsToRsDhtNetPeer(status, *dpd); - return 1; -} - - -int p3BitDht::getRelayEnds(std::list &relayEnds) -{ - /* no need for mutex as mRelayReceiver is protected */ - if (!mRelay) - { - return 0; - } - - std::list int_relayEnds; - std::list::iterator it; - mRelay->getRelayEnds(int_relayEnds); - - for(it = int_relayEnds.begin(); it != int_relayEnds.end(); ++it) - { - RsDhtRelayEnd end; - convertUdpRelayEndtoRsDhtRelayEnd(end, *it); - - relayEnds.push_back(end); - } - return 1; -} - - -int p3BitDht::getRelayProxies(std::list &relayProxies) -{ - /* no need for mutex as mRelayReceiver is protected */ - if (!mRelay) - { - return 0; - } - - std::list int_relayProxies; - std::list::iterator it; - mRelay->getRelayProxies(int_relayProxies); - - for(it = int_relayProxies.begin(); it != int_relayProxies.end(); ++it) - { - RsDhtRelayProxy proxy; - convertUdpRelayProxytoRsDhtRelayProxy(proxy, *it); - relayProxies.push_back(proxy); - } - return 1; -} - - -#if 0 -int p3BitDht::getNetFailedPeer(std::string peerId, PeerStatus &status) -{ - return 1; -} -#endif - -std::string p3BitDht::getUdpAddressString() -{ - std::string out; -#ifdef RS_USE_DHT_STUNNER - struct sockaddr_in extAddr; - uint8_t extStable; - - if (mDhtStunner->externalAddr(extAddr, extStable)) - { - rs_sprintf_append(out, " DhtExtAddr: %s:%u", rs_inet_ntoa(extAddr.sin_addr).c_str(), ntohs(extAddr.sin_port)); - - if (extStable) - { - out += " (Stable) "; - } - else - { - out += " (Unstable) "; - } - } - else - { - out += " DhtExtAddr: Unknown "; - } - if (mProxyStunner->externalAddr(extAddr, extStable)) - { - rs_sprintf_append(out, " ProxyExtAddr: %s:%u", rs_inet_ntoa(extAddr.sin_addr).c_str(), ntohs(extAddr.sin_port)); - - if (extStable) - { - out += " (Stable) "; - } - else - { - out += " (Unstable) "; - } - } - else - { - out += " ProxyExtAddr: Unknown "; - } -#else // RS_USE_DHT_STUNNER - // whitespaces taken from above - out = " DhtExtAddr: Unknown ProxyExtAddr: Unknown "; -#endif // RS_USE_DHT_STUNNER - return out; -} - -void p3BitDht::updateDataRates() -{ - uint32_t relayRead = 0; - uint32_t relayWrite = 0; - uint32_t relayRelay = 0; - uint32_t dhtRead = 0; - uint32_t dhtWrite = 0; - - mRelay->getDataTransferred(relayRead, relayWrite, relayRelay); - mUdpBitDht->getDataTransferred(dhtRead, dhtWrite); - - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - rstime_t now = time(NULL); - float period = now - mLastDataRateUpdate; - -#define RATE_FACTOR (0.75) - - mRelayReadRate *= RATE_FACTOR; - mRelayReadRate += (1.0 - RATE_FACTOR) * (relayRead / period); - - mRelayWriteRate *= RATE_FACTOR; - mRelayWriteRate += (1.0 - RATE_FACTOR) * (relayWrite / period); - - mRelayRelayRate *= RATE_FACTOR; - mRelayRelayRate += (1.0 - RATE_FACTOR) * (relayRelay / period); - - mDhtReadRate *= RATE_FACTOR; - mDhtReadRate += (1.0 - RATE_FACTOR) * (dhtRead / period); - - mDhtWriteRate *= RATE_FACTOR; - mDhtWriteRate += (1.0 - RATE_FACTOR) * (dhtWrite / period); - - mLastDataRateUpdate = now; - -} - -void p3BitDht::clearDataRates() -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - mRelayReadRate = 0; - mRelayWriteRate = 0; - mRelayRelayRate = 0; - mDhtReadRate = 0; - mDhtWriteRate = 0; - - mLastDataRateUpdate = time(NULL); -} - - -/* in kB/s */ -void p3BitDht::getDhtRates(float &read, float &write) -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - read = mDhtReadRate / 1024.0; - write = mDhtWriteRate / 1024.0; -} - -void p3BitDht::getRelayRates(float &read, float &write, float &relay) -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - read = mRelayReadRate / 1024.0; - write = mRelayWriteRate / 1024.0; - relay = mRelayRelayRate / 1024.0; -} - - - -/*********************************************************************************************** - ********** External RsDHT Interface (defined in libretroshare/src/retroshare/rsdht.h) ********* -************************************************************************************************/ - -void convertBdPeerToRsDhtPeer(RsDhtPeer &peer, const bdPeer &int_peer) -{ - bdStdPrintNodeId(peer.mDhtId, &(int_peer.mPeerId.id), false); - - rs_sprintf(peer.mAddr, "%s:%u", rs_inet_ntoa(int_peer.mPeerId.addr.sin_addr).c_str(), ntohs(int_peer.mPeerId.addr.sin_port)); - - peer.mLastSendTime = int_peer.mLastSendTime; - peer.mLastRecvTime = int_peer.mLastRecvTime; - peer.mFoundTime = int_peer.mFoundTime; - peer.mPeerFlags = int_peer.mPeerFlags; - peer.mExtraFlags = int_peer.mExtraFlags; -} - - - -void convertDhtPeerDetailsToRsDhtNetPeer(RsDhtNetPeer &status, const DhtPeerDetails &details) -{ - bdStdPrintId(status.mDhtId, &(details.mDhtId), false); - - status.mRsId = details.mRsId; - - status.mPeerType = details.mPeerType; - - status.mDhtState = details.mDhtState; - - status.mConnectState = details.mConnectLogic.connectState(); - - status.mPeerReqState = details.mPeerReqState; - - status.mExclusiveProxyLock = details.mExclusiveProxyLock; - - status.mPeerConnectState = details.mPeerConnectState; - - switch(details.mPeerConnectMode) - { - default: - status.mPeerConnectMode = RsDhtTouMode::NONE; - break; - case BITDHT_CONNECT_MODE_DIRECT: - status.mPeerConnectMode = RsDhtTouMode::DIRECT; - break; - case BITDHT_CONNECT_MODE_PROXY: - status.mPeerConnectMode = RsDhtTouMode::PROXY; - break; - case BITDHT_CONNECT_MODE_RELAY: - status.mPeerConnectMode = RsDhtTouMode::RELAY; - break; - } - - //status.mPeerConnectProxyId = details.mPeerConnectProxyId; - bdStdPrintId(status.mPeerConnectProxyId, &(details.mPeerConnectProxyId), false); - - status.mCbPeerMsg = details.mPeerCbMsg; - - return; -} - -void convertUdpRelayEndtoRsDhtRelayEnd(RsDhtRelayEnd &end, const UdpRelayEnd &int_end) -{ - rs_sprintf(end.mLocalAddr, "%s:%u", rs_inet_ntoa(int_end.mLocalAddr.sin_addr).c_str(), ntohs(int_end.mLocalAddr.sin_port)); - rs_sprintf(end.mProxyAddr, "%s:%u", rs_inet_ntoa(int_end.mProxyAddr.sin_addr).c_str(), ntohs(int_end.mProxyAddr.sin_port)); - rs_sprintf(end.mRemoteAddr, "%s:%u", rs_inet_ntoa(int_end.mRemoteAddr.sin_addr).c_str(), ntohs(int_end.mRemoteAddr.sin_port)); - - end.mCreateTS = 0; - return; -} - -void convertUdpRelayProxytoRsDhtRelayProxy(RsDhtRelayProxy &proxy, const UdpRelayProxy &int_proxy) -{ - rs_sprintf(proxy.mSrcAddr, "%s:%u", rs_inet_ntoa(int_proxy.mAddrs.mSrcAddr.sin_addr).c_str(), ntohs(int_proxy.mAddrs.mSrcAddr.sin_port)); - rs_sprintf(proxy.mDestAddr, "%s:%u", rs_inet_ntoa(int_proxy.mAddrs.mDestAddr.sin_addr).c_str(), ntohs(int_proxy.mAddrs.mDestAddr.sin_port)); - - proxy.mBandwidth = int_proxy.mBandwidth; - proxy.mRelayClass = int_proxy.mRelayClass; - proxy.mLastTS = int_proxy.mLastTS; - proxy.mCreateTS = 0; - - //proxy.mDataSize = int_proxy.mDataSize; - //proxy.mLastBandwidthTS = int_proxy.mLastBandwidthTS; -} - -RsDhtPeer::RsDhtPeer() -{ - mBucket = 0; - - //std::string mDhtId; - mLastSendTime = 0; - mLastRecvTime = 0; - mFoundTime = 0; - mPeerFlags = 0; - mExtraFlags = 0; -} - - -RsDhtNetPeer::RsDhtNetPeer() -{ - return; -} - - -RsDhtRelayEnd::RsDhtRelayEnd() -{ - mCreateTS = 0; -} - - -RsDhtRelayProxy::RsDhtRelayProxy() -{ - mBandwidth = 0; - mRelayClass = 0; - mLastTS = 0; - mCreateTS = 0; - - //uint32_t mDataSize; - //rstime_t mLastBandwidthTS; - -} - - diff --git a/libretroshare/src/dht/p3bitdht_peernet.cc b/libretroshare/src/dht/p3bitdht_peernet.cc deleted file mode 100644 index a37678728..000000000 --- a/libretroshare/src/dht/p3bitdht_peernet.cc +++ /dev/null @@ -1,2533 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: p3bitdht_peernet.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "dht/p3bitdht.h" - -#include -#include - - -#include "bitdht/bdiface.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdmanager.h" - -//#include "udp/udplayer.h" - -#include "util/rsnet.h" -#include "tcponudp/tou.h" -#include "tcponudp/udpstunner.h" -#include "tcponudp/udprelay.h" - -#include "pqi/p3netmgr.h" -#include "pqi/pqimonitor.h" - -#define PEERNET_CONNECT_TIMEOUT 180 // Should be BIGGER than Higher level (but okay if not!) - -#define MIN_DETERMINISTIC_SWITCH_PERIOD 60 - -/*** - * - * #define DEBUG_BITDHT_COMMON 1 // These are the things that are called regularly (annoying for debugging specifics) - * #define DEBUG_PEERNET 1 - * - **/ - - -/****************************************************************************************** - ************************************* Dht Callback *************************************** - ******************************************************************************************/ - -/**** dht NodeCallback **** - * - * - * In the old version, we used this to callback mConnCb->peerStatus() - * We might want to drop this, and concentrate on the connection stuff. - * - * -> if an new dht peer, then pass to Stunners. - * -> do we care if we know them? not really! - */ - -int p3BitDht::InfoCallback(const bdId *id, uint32_t /*type*/, uint32_t /*flags*/, std::string /*info*/) -{ - /* translate info */ - RsPeerId rsid; - struct sockaddr_in addr = id->addr; - int outtype = PNASS_TYPE_BADPEER; - int outreason = PNASS_REASON_UNKNOWN; - int outage = 0; - -#ifdef DEBUG_BITDHT_COMMON - std::cerr << "p3BitDht::InfoCallback() likely BAD_PEER: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(id->id), RsDhtPeerType::ANY); - - if (dpd) - { - rsid = dpd->mRsId; - } - } - - if (mPeerSharer) - { - struct sockaddr_storage tmpaddr; - struct sockaddr_in *ap = (struct sockaddr_in *) &tmpaddr; - ap->sin_family = AF_INET; - ap->sin_addr = addr.sin_addr; - ap->sin_port = addr.sin_port; - - mPeerSharer->updatePeer(rsid, tmpaddr, outtype, outreason, outage); - } - -#ifdef RS_USE_DHT_STUNNER - /* call to the Stunners to drop the address as well */ - /* IDEALLY these addresses should all be filtered at UdpLayer level instead! */ - if (mDhtStunner) - { - mDhtStunner->dropStunPeer(addr); - } - if (mProxyStunner) - { - mProxyStunner->dropStunPeer(addr); - } -#endif // RS_USE_DHT_STUNNER - - return 1; -} - - - -/**** dht NodeCallback **** - * - * - * In the old version, we used this to callback mConnCb->peerStatus() - * We might want to drop this, and concentrate on the connection stuff. - * - * -> if an new dht peer, then pass to Stunners. - * -> do we care if we know them? not really! - */ - -int p3BitDht::NodeCallback(const bdId *id, uint32_t peerflags) -{ - // No need for Mutex, and Stunners are self protected. - - // These are the flags that will be returned by p3BitDht & RS peers with the new DHT. - // if (peerflags & BITDHT_PEER_STATUS_DHT_ENGINE_VERSION) // Change to this later... - if ((peerflags & BITDHT_PEER_STATUS_DHT_ENGINE) && - (peerflags & BITDHT_PEER_STATUS_DHT_APPL)) - { - - /* pass off to the Stunners - * but only if they need them. - * ideally don't pass to both peers... (XXX do later) - */ - - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - if (id->id == mOwnDhtId) - { -#ifdef DEBUG_BITDHT_COMMON - std::cerr << "p3BitDht::NodeCallback() Skipping own id"; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - return 1; - } - } - -#ifdef RS_USE_DHT_STUNNER - if ((mProxyStunner) && (mProxyStunner->needStunPeers())) - { -#ifdef DEBUG_BITDHT_COMMON - std::cerr << "p3BitDht::NodeCallback() Passing BitDHT Peer to DhtStunner: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - mProxyStunner->addStunPeer(id->addr, NULL); - } - /* else */ // removed else until we have lots of peers. - - if ((mDhtStunner) && (mDhtStunner->needStunPeers())) - { -#ifdef DEBUG_BITDHT_COMMON - std::cerr << "p3BitDht::NodeCallback() Passing BitDHT Peer to DhtStunner: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - mDhtStunner->addStunPeer(id->addr, NULL); - } -#endif // RS_USE_DHT_STUNNER - } - return 1; -} - -/**** dht PeerCallback **** - * - * - * In the old version, we used this to callback mConnCb->peerConnectRequest() - * we need to continue doing this, to maintain compatibility. - * - * -> update Dht Status, and trigger connect if ONLINE or UNREACHABLE - */ - - -int p3BitDht::PeerCallback(const bdId *id, uint32_t status) -{ - //std::string str; - //bdStdPrintNodeId(str, &(id->id)); - - //std::cerr << "p3BitDht::dhtPeerCallback()"; - //std::cerr << std::endl; - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(id->id), RsDhtPeerType::FRIEND); - - if (!dpd) - { - /* ERROR */ - std::cerr << "p3BitDht::PeerCallback() ERROR Unknown Peer: "; - bdStdPrintId(std::cerr, id); - std::cerr << " status: " << status; - std::cerr << std::endl; - - return 0; - } - - sockaddr_clear(&(dpd->mDhtId.addr)); - - switch(status) - { - default: - dpd->mDhtState = RsDhtPeerDht::NOT_ACTIVE; - break; - - case BITDHT_MGR_QUERY_FAILURE: - dpd->mDhtState = RsDhtPeerDht::FAILURE; - break; - - case BITDHT_MGR_QUERY_PEER_OFFLINE: - dpd->mDhtState = RsDhtPeerDht::OFFLINE; - break; - - case BITDHT_MGR_QUERY_PEER_UNREACHABLE: - dpd->mDhtState = RsDhtPeerDht::UNREACHABLE; - dpd->mDhtId = *id; // set the IP:Port of the unreachable peer. - UnreachablePeerCallback_locked(id, status, dpd); - - break; - - case BITDHT_MGR_QUERY_PEER_ONLINE: - dpd->mDhtState = RsDhtPeerDht::ONLINE; - dpd->mDhtId = *id; // set the IP:Port of the Online peer. - OnlinePeerCallback_locked(id, status, dpd); - - break; - - } - - rstime_t now = time(NULL); - dpd->mDhtUpdateTS = now; - - return 1; -} - - - -int p3BitDht::OnlinePeerCallback_locked(const bdId *id, uint32_t /*status*/, DhtPeerDetails *dpd) -{ - /* remove unused parameter warnings */ - (void) id; - - if ((dpd->mPeerConnectState != RsDhtPeerConnectState::DISCONNECTED) || - (dpd->mPeerReqState == RsDhtPeerRequest::RUNNING)) - { - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::OnlinePeerCallback_locked() WARNING Ignoring Callback: connection already underway: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - return 1; - } - - bool connectOk = true; - bool doTCPCallback = false; - - /* work out network state */ - uint32_t connectFlags = dpd->mConnectLogic.connectCb(CSB_CONNECT_DIRECT, - mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()); -// bool useProxyPort = (connectFlags & CSB_ACTION_PROXY_PORT); - - switch(connectFlags & CSB_ACTION_MASK_MODE) - { - default: - case CSB_ACTION_WAIT: - { - connectOk = false; - } - break; - case CSB_ACTION_TCP_CONN: - { - connectOk = false; - doTCPCallback = true; - } - break; - case CSB_ACTION_DIRECT_CONN: - { - - connectOk = true; - } - break; - case CSB_ACTION_PROXY_CONN: - { - /* ERROR */ - std::cerr << "dhtPeerCallback: ERROR ConnectLogic returned PROXY"; - std::cerr << std::endl; - connectOk = false; - } - break; - case CSB_ACTION_RELAY_CONN: - { - /* ERROR */ - std::cerr << "dhtPeerCallback: ERROR ConnectLogic returned RELAY"; - std::cerr << std::endl; - connectOk = false; - } - break; - } - - if (connectOk) - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Peer Online, triggering Direct Connection for: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_CONNECT; - ca.mMode = BITDHT_CONNECT_MODE_DIRECT; - ca.mDestId = *id; - ca.mAnswer = BITDHT_CONNECT_ERROR_NONE; - - mActions.push_back(ca); - } - - /* might need to make this an ACTION - leave for now */ - if (doTCPCallback) - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Peer Online, triggering TCP Connection for: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_TCPATTEMPT; - ca.mMode = BITDHT_CONNECT_MODE_DIRECT; - ca.mDestId = *id; - ca.mAnswer = BITDHT_CONNECT_ERROR_NONE; - - mActions.push_back(ca); - //ConnectCalloutTCPAttempt(dpd->mRsId, id->addr); - } - - return 1; -} - - - -int p3BitDht::UnreachablePeerCallback_locked(const bdId *id, uint32_t /*status*/, DhtPeerDetails *dpd) -{ - - if ((dpd->mPeerConnectState != RsDhtPeerConnectState::DISCONNECTED) || - (dpd->mPeerReqState == RsDhtPeerRequest::RUNNING)) - { - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::UnreachablePeerCallback_locked() WARNING Ignoring Callback: connection already underway: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - return 1; - } - -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Peer Unreachable, triggering Proxy | Relay Connection for: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - bool proxyOk = false; - bool connectOk = true; - - /* work out network state */ - uint32_t connectFlags = dpd->mConnectLogic.connectCb(CSB_CONNECT_UNREACHABLE, - mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()); - bool useProxyPort = (connectFlags & CSB_ACTION_PROXY_PORT); - - switch(connectFlags & CSB_ACTION_MASK_MODE) - { - default: - case CSB_ACTION_WAIT: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Request to Wait ... so no Connection Attempt for "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - connectOk = false; - } - break; - case CSB_ACTION_DIRECT_CONN: - { - /* ERROR */ - std::cerr << "dhtPeerCallback: ERROR ConnectLogic returned DIRECT"; - std::cerr << std::endl; - - connectOk = false; - } - break; - case CSB_ACTION_PROXY_CONN: - { - proxyOk = true; - connectOk = true; - } - break; - case CSB_ACTION_RELAY_CONN: - { - proxyOk = false; - connectOk = true; - } - break; - } - - if (connectOk) - { - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_CONNECT; - ca.mDestId = *id; - - dpd->mConnectLogic.storeProxyPortChoice(connectFlags, useProxyPort); - - if (proxyOk) - { - ca.mMode = BITDHT_CONNECT_MODE_PROXY; -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Trying Proxy Connection."; - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Trying Relay Connection."; - std::cerr << std::endl; -#endif - ca.mMode = BITDHT_CONNECT_MODE_RELAY; - } - - ca.mAnswer = BITDHT_CONNECT_ERROR_NONE; - mActions.push_back(ca); - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Cancelled Connection Attempt for "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - } - - return 1; -} - - - -int p3BitDht::ValueCallback(const bdNodeId */*id*/, std::string /*key*/, uint32_t /*status*/) -{ - std::cerr << "p3BitDht::ValueCallback() ERROR Does nothing!"; - std::cerr << std::endl; - - return 1; -} - -int p3BitDht::ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t point, uint32_t param, uint32_t cbtype, uint32_t errcode) -{ -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::ConnectCallback()"; - std::cerr << std::endl; - std::cerr << "srcId: "; - bdStdPrintId(std::cerr, srcId); - std::cerr << std::endl; - std::cerr << "proxyId: "; - bdStdPrintId(std::cerr, proxyId); - std::cerr << std::endl; - std::cerr << "destId: "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; - - std::cerr << " mode: " << mode; - std::cerr << " param: " << param; - std::cerr << " point: " << point; - std::cerr << " cbtype: " << cbtype; - std::cerr << std::endl; -#endif - - - /* we handle MID and START/END points differently... this is biggest difference. - * so handle first. - */ - - bdId peerId; - rstime_t now = time(NULL); - - switch(point) - { - default: - case BD_PROXY_CONNECTION_UNKNOWN_POINT: - { - std::cerr << "p3BitDht::dhtConnectCallback() ERROR UNKNOWN point, ignoring Callback"; - std::cerr << std::endl; - return 0; - } - case BD_PROXY_CONNECTION_START_POINT: - peerId = *destId; - break; - case BD_PROXY_CONNECTION_END_POINT: - peerId = *srcId; - break; - case BD_PROXY_CONNECTION_MID_POINT: - { - /* AS a mid point, we can receive.... AUTH,PENDING,PROXY,FAILED */ - - switch(cbtype) - { - case BITDHT_CONNECT_CB_AUTH: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection Requested Between:"; - std::cerr << std::endl; - bdStdPrintId(std::cerr, srcId); - std::cerr << " and "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; -#endif - /* if there is an error code - then it is just to inform us of a failed attempt */ - if (errcode) - { - RelayHandler_LogFailedProxyAttempt(srcId, destId, mode, errcode); - /* END MID FAILED ATTEMPT */ - return 1; - } - - uint32_t bandwidth = 0; - - int connectionAllowed = BITDHT_CONNECT_ERROR_GENERIC; - if (checkProxyAllowed(srcId, destId, mode, bandwidth)) - { - connectionAllowed = BITDHT_CONNECT_ANSWER_OKAY; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Allowed"; - std::cerr << std::endl; -#endif - } - else - { - connectionAllowed = BITDHT_CONNECT_ERROR_AUTH_DENIED; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Denied"; - std::cerr << std::endl; -#endif - } - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_AUTHORISE; - ca.mMode = mode; - ca.mProxyId = *proxyId; - ca.mSrcId = *srcId; - ca.mDestId = *destId; - ca.mPoint = point; - ca.mAnswer = connectionAllowed; - ca.mDelayOrBandwidth = bandwidth; - - mActions.push_back(ca); - } - break; - case BITDHT_CONNECT_CB_PENDING: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection Pending:"; - std::cerr << std::endl; - bdStdPrintId(std::cerr, srcId); - std::cerr << " and "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; -#endif - } - break; - case BITDHT_CONNECT_CB_PROXY: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection Starting:"; - std::cerr << std::endl; - bdStdPrintId(std::cerr, srcId); - std::cerr << " and "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; -#endif - } - break; - case BITDHT_CONNECT_CB_FAILED: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection Failed:"; - std::cerr << std::endl; - bdStdPrintId(std::cerr, srcId); - std::cerr << " and "; - bdStdPrintId(std::cerr, destId); - - std::cerr << " ErrorCode: " << errcode; - int errsrc = errcode & BITDHT_CONNECT_ERROR_MASK_SOURCE; - int errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE; - - std::cerr << " ErrorSrc: " << errsrc; - std::cerr << " ErrorType: " << errtype; - - std::cerr << std::endl; -#endif - - if (mode == BITDHT_CONNECT_MODE_RELAY) - { - removeRelayConnection(srcId, destId); - } - } - break; - default: - case BITDHT_CONNECT_CB_START: - { - std::cerr << "dhtConnectionCallback() ERROR unexpected Proxy ConnectionCallback:"; - std::cerr << std::endl; - bdStdPrintId(std::cerr, srcId); - std::cerr << " and "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; - } - break; - } - /* End the MID Point stuff */ - return 1; - } - } - - /* if we get here, we are an endpoint (peer specified in peerId) */ - - /* translate id into string for exclusive mode */ - std::string pid; - bdStdPrintNodeId(pid, &(peerId.id), false); - - switch(cbtype) - { - case BITDHT_CONNECT_CB_AUTH: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Requested By: "; - bdStdPrintId(std::cerr, &(peerId)); - std::cerr << std::endl; -#endif - - int connectionAllowed = BITDHT_CONNECT_ERROR_GENERIC; - if (checkConnectionAllowed(&(peerId), mode)) - { - connectionAllowed = BITDHT_CONNECT_ANSWER_OKAY; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Allowed"; - std::cerr << std::endl; -#endif - } - else - { - connectionAllowed = BITDHT_CONNECT_ERROR_AUTH_DENIED; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Denied"; - std::cerr << std::endl; -#endif - } - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_AUTHORISE; - ca.mProxyId = *proxyId; - ca.mSrcId = *srcId; - ca.mDestId = *destId; - ca.mDelayOrBandwidth = 0; - - /* Check Proxy ExtAddress Status (but only if connection is Allowed) */ - if ((connectionAllowed == BITDHT_CONNECT_ANSWER_OKAY) && - (mode == BITDHT_CONNECT_MODE_PROXY)) - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Checking Address for Proxy"; - std::cerr << std::endl; -#endif - - struct sockaddr_in extaddr; - sockaddr_clear(&extaddr); - - bool connectOk = false; - bool proxyPort = false; - bool exclusivePort = false; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback(): Proxy... deciding which port to use."; - std::cerr << std::endl; -#endif - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - proxyPort = dpd->mConnectLogic.shouldUseProxyPort( - mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()); - - dpd->mConnectLogic.storeProxyPortChoice(0, proxyPort); - -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback: Setting ProxyPort: "; - std::cerr << " UseProxyPort? " << proxyPort; - std::cerr << std::endl; - - std::cerr << "dhtConnectionCallback: Checking ConnectLogic.NetState: "; - std::cerr << dpd->mConnectLogic.calcNetState(mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()); - std::cerr << std::endl; -#endif - - if (proxyPort) - { - exclusivePort = (CSB_NETSTATE_EXCLUSIVENAT == dpd->mConnectLogic.calcNetState( - mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode())); - } - -#ifdef DEBUG_PEERNET - if (exclusivePort) std::cerr << "dhtConnectionCallback: we Require Exclusive Proxy Port for connection" << std::endl; - else std::cerr << "dhtConnectionCallback: Dont need Exclusive Proxy Port for connection" << std::endl; -#endif - - connectOk = true; - } - else - { - std::cerr << "PeerAction: Connect Proxy: ERROR Cannot find PeerStatus"; - std::cerr << std::endl; - } - -#ifdef RS_USE_DHT_STUNNER - uint8_t extStable = 0; - - UdpStunner *stunner = mProxyStunner; - if (!proxyPort) - { - stunner = mDhtStunner; - } - - if ((connectOk) && (stunner) && (stunner->externalAddr(extaddr, extStable))) - { - if (extStable) - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection Attempt to: "; - bdStdPrintId(std::cerr, &(peerId)); - std::cerr << " is Ok as we have Stable Own External Proxy Address"; - std::cerr << std::endl; -#endif - - if (point == BD_PROXY_CONNECTION_END_POINT) - { - ca.mDestId.addr = extaddr; - } - else - { - ca.mSrcId.addr = extaddr; - std::cerr << "dhtConnectionCallback() ERROR Proxy Auth as SrcId"; - std::cerr << std::endl; - } - - /* check if we require exclusive use of the proxy port */ - if (exclusivePort) - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback: Attempting to Grab ExclusiveLock of UdpStunner"; - std::cerr << std::endl; -#endif - - int stun_age = mProxyStunner->grabExclusiveMode(pid); - if (stun_age > 0) - { - int delay = 0; - if (stun_age < MIN_DETERMINISTIC_SWITCH_PERIOD) - { - delay = MIN_DETERMINISTIC_SWITCH_PERIOD - stun_age; - } - - /* great we got it! */ - ca.mDelayOrBandwidth = delay; - -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback: GotExclusiveLock With Delay: " << delay; - std::cerr << " for stable port"; - std::cerr << std::endl; -#endif - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - dpd->mExclusiveProxyLock = true; - -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback: Success at grabbing ExclusiveLock of UdpStunner"; - std::cerr << std::endl; -#endif - - } - else - { - std::cerr << "PeerAction: Connect Proxy: ERROR Cannot find PeerStatus"; - std::cerr << std::endl; - connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL; - mProxyStunner->releaseExclusiveMode(pid,false); - } - } - else - { - /* failed to get exclusive mode - must wait */ - connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL; - -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback: Failed to Grab ExclusiveLock, Returning TEMPUNAVAIL"; - std::cerr << std::endl; -#endif - } - } - - - } - else - { - if (exclusivePort) - { - connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection"; - std::cerr << " is Discarded, as External Proxy Address is Not Stable! (EXCLUSIVE MODE)"; - std::cerr << std::endl; -#endif - } - else - { - connectionAllowed = BITDHT_CONNECT_ERROR_UNREACHABLE; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection"; - std::cerr << " is Discarded, as Own External Proxy Address is Not Stable!"; - std::cerr << std::endl; -#endif - } - } - } - else - { - connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() ERROR Proxy Connection "; - std::cerr << " is Discarded, as Failed to get Own External Proxy Address."; - std::cerr << std::endl; -#endif - } -#else // RS_USE_DHT_STUNNER - connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL; - (void) connectOk; - (void) exclusivePort; -#endif // RS_USE_DHT_STUNNER - } - - ca.mMode = mode; - ca.mPoint = point; - ca.mAnswer = connectionAllowed; - - mActions.push_back(ca); - } - break; - - case BITDHT_CONNECT_CB_START: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Starting with: "; - bdStdPrintId(std::cerr, &(peerId)); - std::cerr << std::endl; -#endif - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_START; - ca.mMode = mode; - ca.mProxyId = *proxyId; - ca.mSrcId = *srcId; - ca.mDestId = *destId; - ca.mPoint = point; - ca.mDelayOrBandwidth = param; - ca.mAnswer = BITDHT_CONNECT_ERROR_NONE; - - mActions.push_back(ca); - - } - break; - - case BITDHT_CONNECT_CB_FAILED: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Attempt Failed with:"; - bdStdPrintId(std::cerr, &(peerId)); - std::cerr << std::endl; - - std::cerr << "dhtConnectionCallback() Proxy:"; - bdStdPrintId(std::cerr, proxyId); - std::cerr << std::endl; - - std::cerr << "dhtConnectionCallback() "; - std::cerr << " ErrorCode: " << errcode; - int errsrc = errcode & BITDHT_CONNECT_ERROR_MASK_SOURCE; - int errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE; - - std::cerr << " ErrorSrc: " << errsrc; - std::cerr << " ErrorType: " << errtype; - std::cerr << std::endl; -#endif - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - dpd->mPeerCbMsg = "ERROR : "; - dpd->mPeerCbMsg += decodeConnectionError(errcode); - dpd->mPeerCbMode = mode; - dpd->mPeerCbPoint = point; - dpd->mPeerCbProxyId = *proxyId; - dpd->mPeerCbDestId = peerId; - dpd->mPeerCbTS = now; - } - else - { - std::cerr << "dhtConnectionCallback() "; - std::cerr << "ERROR Unknown Peer"; - std::cerr << std::endl; - } - } - break; - - case BITDHT_CONNECT_CB_REQUEST: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Local Connection Request Feedback:"; - bdStdPrintId(std::cerr, &(peerId)); - std::cerr << std::endl; - - std::cerr << "dhtConnectionCallback() Proxy:"; - bdStdPrintId(std::cerr, proxyId); - std::cerr << std::endl; -#endif - - if (point != BD_PROXY_CONNECTION_START_POINT) - { - std::cerr << "dhtConnectionCallback() ERROR not START_POINT"; - std::cerr << std::endl; - return 0; - } - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - if (errcode) - { - ReleaseProxyExclusiveMode_locked(dpd, false); - - dpd->mPeerReqStatusMsg = "STOPPED: "; - dpd->mPeerReqStatusMsg += decodeConnectionError(errcode); - dpd->mPeerReqState = RsDhtPeerRequest::STOPPED; - dpd->mPeerReqTS = now; - - int updatecode = CSB_UPDATE_FAILED_ATTEMPT; - int errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE; - switch(errtype) - { - /* fatal errors */ - case BITDHT_CONNECT_ERROR_AUTH_DENIED: - { - updatecode = CSB_UPDATE_AUTH_DENIED; - } - break; - - /* move on errors */ - case BITDHT_CONNECT_ERROR_UNREACHABLE: // sym NAT. - case BITDHT_CONNECT_ERROR_UNSUPPORTED: // mode unavailable. - { - updatecode = CSB_UPDATE_MODE_UNAVAILABLE; - } - break; - - - /* retry attempts */ - case BITDHT_CONNECT_ERROR_TEMPUNAVAIL: - case BITDHT_CONNECT_ERROR_DUPLICATE: - { - updatecode = CSB_UPDATE_RETRY_ATTEMPT; - } - break; - /* standard failed attempts */ - case BITDHT_CONNECT_ERROR_GENERIC: - case BITDHT_CONNECT_ERROR_PROTOCOL: - case BITDHT_CONNECT_ERROR_TIMEOUT: - case BITDHT_CONNECT_ERROR_NOADDRESS: - case BITDHT_CONNECT_ERROR_OVERLOADED: - /* CB_REQUEST errors */ - case BITDHT_CONNECT_ERROR_TOOMANYRETRY: - case BITDHT_CONNECT_ERROR_OUTOFPROXY: - { - updatecode = CSB_UPDATE_FAILED_ATTEMPT; - } - break; - - /* user cancelled ... no update */ - case BITDHT_CONNECT_ERROR_USER: - { - updatecode = CSB_UPDATE_NONE; - } - break; - } - if (updatecode) - { - dpd->mConnectLogic.updateCb(updatecode); - } - } - else // a new connection attempt. - { - dpd->mPeerReqStatusMsg = "Connect Attempt"; - dpd->mPeerReqState = RsDhtPeerRequest::RUNNING; - dpd->mPeerReqMode = mode; - dpd->mPeerReqProxyId = *proxyId; - dpd->mPeerReqTS = now; - - // This also is flagged into the instant Cb info. - dpd->mPeerCbMsg = "Local Connect Attempt"; - dpd->mPeerCbMode = mode; - dpd->mPeerCbPoint = point; - dpd->mPeerCbProxyId = *proxyId; - dpd->mPeerCbDestId = peerId; - dpd->mPeerCbTS = now; - } - } - else - { - std::cerr << "dhtConnectionCallback() ERROR Cannot find PeerStatus"; - std::cerr << std::endl; - } - } - break; - - default: - case BITDHT_CONNECT_CB_PENDING: - case BITDHT_CONNECT_CB_PROXY: - { - std::cerr << "dhtConnectionCallback() ERROR unexpected ConnectionCallback:"; - std::cerr << std::endl; - bdStdPrintId(std::cerr, srcId); - std::cerr << " and "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; - } - break; - } - return 1; -} - -/****************************************************************************************** - ******************************** Dht Actions / Monitoring ******************************** - ******************************************************************************************/ - - -/* tick stuff that isn't in its own thread */ - -int p3BitDht::tick() -{ - doActions(); - monitorConnections(); - - minuteTick(); - -#ifdef DEBUG_PEERNET_COMMON - time_t now = time(NULL); // Don't use rstime_t here or ctime break on windows - std::cerr << "p3BitDht::tick() TIME: " << ctime(&now) << std::endl; - std::cerr.flush(); -#endif - - return 1; -} - -#define MINUTE_IN_SECS 60 -#define TEN_IN_SECS 10 - -int p3BitDht::minuteTick() -{ - rstime_t now = time(NULL); - int deltaT = 0; - - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - deltaT = now-mMinuteTS; - } - - //if (deltaT > MINUTE_IN_SECS) - if (deltaT > TEN_IN_SECS) - { - mRelay->checkRelays(); - - updateDataRates(); - - /* temp - testing - print dht & relay traffic */ - float dhtRead, dhtWrite; - float relayRead, relayWrite, relayRelayed; - - getRelayRates(relayRead, relayWrite, relayRelayed); - getDhtRates(dhtRead, dhtWrite); - -#ifdef DEBUG_PEERNET_COMMON - double denom = deltaT; - - std::cerr << "p3BitDht::minuteTick() "; - std::cerr << "DhtRead: " << dhtRead / denom << " kB/s "; - std::cerr << "DhtWrite: " << dhtWrite / denom << " kB/s "; - std::cerr << std::endl; - - std::cerr << "p3BitDht::minuteTick() "; - std::cerr << "RelayRead: " << relayRead / denom << " kB/s "; - std::cerr << "RelayWrite: " << relayWrite / denom << " kB/s "; - std::cerr << "RelayRelayed: " << relayRelayed / denom << " kB/s "; - std::cerr << std::endl; -#endif - - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - mMinuteTS = now; - } - return 1; -} - -int p3BitDht::doActions() -{ -#ifdef DEBUG_PEERNET_COMMON - std::cerr << "p3BitDht::doActions()" << std::endl; -#endif - - rstime_t now = time(NULL); - - while(mActions.size() > 0) - { - PeerAction action; - - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - if (mActions.size() < 1) - { - break; - } - - action = mActions.front(); - mActions.pop_front(); - } - - switch(action.mType) - { - case PEERNET_ACTION_TYPE_CONNECT: - { - /* connect attempt */ -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " mode: " << action.mMode; - std::cerr << std::endl; -#endif - - bool doConnectionRequest = false; - bool connectionReqFailed = false; - bool grabbedExclusivePort = false; - - /* translate id into string for exclusive mode */ - std::string pid; - bdStdPrintNodeId(pid, &(action.mDestId.id), false); - - - // Parameters that will be used for the Connect Request. - struct sockaddr_in connAddr; // We zero this address. (DHT Layer handles most cases) - sockaddr_clear(&connAddr); - uint32_t connStart = 1; /* > 0 indicates GO (number indicates required startup delay) */ - uint32_t connDelay = 0; - - uint32_t failReason = CSB_UPDATE_MODE_UNAVAILABLE; - - if ((action.mMode == BITDHT_CONNECT_MODE_DIRECT) || - (action.mMode == BITDHT_CONNECT_MODE_RELAY)) - { - doConnectionRequest = true; - } - else if (action.mMode == BITDHT_CONNECT_MODE_PROXY) - { - struct sockaddr_in extaddr; - sockaddr_clear(&extaddr); - bool proxyPort = true; - bool exclusivePort = false; - bool connectOk = false; - -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Proxy... deciding which port to use."; - std::cerr << std::endl; -#endif - - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - connectOk = true; - proxyPort = dpd->mConnectLogic.getProxyPortChoice(); - if (proxyPort) - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Using ProxyPort. Checking ConnectLogic.NetState: "; - std::cerr << dpd->mConnectLogic.calcNetState(mNetMgr->getNetworkMode(), - mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()); - std::cerr << std::endl; -#endif - - exclusivePort = (CSB_NETSTATE_EXCLUSIVENAT == dpd->mConnectLogic.calcNetState( - mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode())); - - if (exclusivePort) - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: NetState indicates Exclusive Mode"; - std::cerr << std::endl; -#endif - } - } - } - else - { - std::cerr << "PeerAction: Connect Proxy: ERROR Cannot find PeerStatus"; - std::cerr << std::endl; - } - } -#ifdef RS_USE_DHT_STUNNER - uint8_t extStable = 0; - - UdpStunner *stunner = mProxyStunner; - if (!proxyPort) - { - stunner = mDhtStunner; - } - - - - if ((connectOk) && (stunner) && (stunner->externalAddr(extaddr, extStable))) - { - if (extStable) - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Proxy Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " is OkGo as we have Stable Own External Proxy Address"; - std::cerr << std::endl; -#endif - - /* check if we require exclusive use of the proxy port */ - if (exclusivePort) - { - int stun_age = mProxyStunner->grabExclusiveMode(pid); - if (stun_age > 0) - { - int delay = 0; - if (stun_age < MIN_DETERMINISTIC_SWITCH_PERIOD) - { - delay = MIN_DETERMINISTIC_SWITCH_PERIOD - stun_age; - } - -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Stunner has indicated a Delay of " << delay; - std::cerr << " to ensure a stable Port!"; - std::cerr << std::endl; -#endif - - /* great we got it! */ - connAddr = extaddr; - connDelay = delay; - doConnectionRequest = true; - grabbedExclusivePort = true; - } - else - { - /* failed to get exclusive mode - must wait */ - connectionReqFailed = true; - failReason = CSB_UPDATE_RETRY_ATTEMPT; - } - } - else - { - /* stable and non-exclusive - go for it */ - connAddr = extaddr; - connStart = 1; - doConnectionRequest = true; - } - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: WARNING Proxy Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " is Discarded, as Own External Proxy Address is Not Stable!"; - std::cerr << std::endl; -#endif - - connectionReqFailed = true; - if (exclusivePort) - { - failReason = CSB_UPDATE_RETRY_ATTEMPT; -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: As Exclusive Mode, Port Will stabilise => RETRY"; - std::cerr << std::endl; -#endif - - } - else - { - failReason = CSB_UPDATE_MODE_UNAVAILABLE; -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Not Exclusive Mode, => MODE UNAVAILABLE"; - std::cerr << std::endl; -#endif - } - } - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: ERROR Proxy Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " is Discarded, as Failed to get Own External Proxy Address."; - std::cerr << std::endl; -#endif - - connectionReqFailed = true; - failReason = CSB_UPDATE_RETRY_ATTEMPT; - } -#else // RS_USE_DHT_STUNNER - connectionReqFailed = true; - failReason = CSB_UPDATE_RETRY_ATTEMPT; - (void) connectOk; -#endif //RS_USE_DHT_STUNNER - } - - if (doConnectionRequest) - { - if (mUdpBitDht->ConnectionRequest(&connAddr, &(action.mDestId.id), action.mMode, connDelay, connStart)) - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " has gone ahead"; - std::cerr << std::endl; -#endif - - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - dpd->mPeerReqStatusMsg = "Connect Request"; - dpd->mPeerReqState = RsDhtPeerRequest::RUNNING; - dpd->mPeerReqMode = action.mMode; - dpd->mPeerReqTS = now; - - if (grabbedExclusivePort) - { - dpd->mExclusiveProxyLock = true; - } - } - else - { - std::cerr << "PeerAction: Connect ERROR Cannot find PeerStatus"; - std::cerr << std::endl; - } - } - else - { - connectionReqFailed = true; - failReason = CSB_UPDATE_MODE_UNAVAILABLE; - } - } - - if (connectionReqFailed) - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " is Discarded, as Mode is Unavailable"; - std::cerr << std::endl; -#endif - - //if (grabbedExclusivePort) - //{ - // mProxyStunner->releaseExclusiveMode(pid,false); - //} - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - dpd->mConnectLogic.updateCb(failReason); - - dpd->mPeerReqStatusMsg = "Req Mode Unavailable"; - dpd->mPeerReqState = RsDhtPeerRequest::STOPPED; - dpd->mPeerReqMode = action.mMode; - dpd->mPeerReqTS = now; - - if (grabbedExclusivePort) - { - ReleaseProxyExclusiveMode_locked(dpd, false); - } - } - else - { - std::cerr << "PeerAction: ERROR Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " has no Internal Dht Peer!"; - std::cerr << std::endl; - - if (grabbedExclusivePort) - { - std::cerr << "PeerAction: ERROR ERROR, we grabd Exclusive Port to do this, trying emergency release"; - std::cerr << std::endl; -#ifdef RS_USE_DHT_STUNNER - mProxyStunner->releaseExclusiveMode(pid,false); -#endif // RS_USE_DHT_STUNNER - } - } - } - - } - break; - - case PEERNET_ACTION_TYPE_AUTHORISE: - { - /* connect attempt */ -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. Authorise Connection between: "; - bdStdPrintId(std::cerr, &(action.mSrcId)); - std::cerr << " and "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " mode: " << action.mMode; - std::cerr << " delay/bandwidth: " << action.mDelayOrBandwidth; - std::cerr << std::endl; -#endif - - int delay = 0; - int bandwidth = 0; - if (action.mMode == BITDHT_CONNECT_MODE_RELAY) - { - bandwidth = action.mDelayOrBandwidth; - } - else - { - delay = action.mDelayOrBandwidth; - } - - mUdpBitDht->ConnectionAuth(&(action.mSrcId), &(action.mProxyId), &(action.mDestId), - action.mMode, action.mPoint, bandwidth, delay, action.mAnswer); - - // Only feedback to the gui if we are at END. - if (action.mPoint == BD_PROXY_CONNECTION_END_POINT) - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mSrcId.id), RsDhtPeerType::ANY); - if (dpd) - { - if (action.mAnswer) - { - dpd->mPeerCbMsg = "WE DENIED AUTH: ERROR : "; - dpd->mPeerCbMsg += decodeConnectionError(action.mAnswer); - } - else - { - dpd->mPeerCbMsg = "We AUTHED"; - } - dpd->mPeerCbMode = action.mMode; - dpd->mPeerCbPoint = action.mPoint; - dpd->mPeerCbProxyId = action.mProxyId; - dpd->mPeerCbDestId = action.mSrcId; - dpd->mPeerCbTS = now; - } - // Not an error if AUTH_DENIED - cos we don't know them! (so won't be in peerList). - else if (action.mAnswer | BITDHT_CONNECT_ERROR_AUTH_DENIED) - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction Authorise Connection "; - std::cerr << "Denied Unknown Peer"; - std::cerr << std::endl; -#endif - } - else - { - std::cerr << "PeerAction Authorise Connection "; - std::cerr << "ERROR Unknown Peer & !DENIED ???"; - std::cerr << std::endl; - } - } - } - break; - - case PEERNET_ACTION_TYPE_START: - { - /* connect attempt */ -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. Start Connection between: "; - bdStdPrintId(std::cerr, &(action.mSrcId)); - std::cerr << " and "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " mode: " << action.mMode; - std::cerr << " delay/bandwidth: " << action.mDelayOrBandwidth; - std::cerr << std::endl; -#endif - - initiateConnection(&(action.mSrcId), &(action.mProxyId), &(action.mDestId), - action.mMode, action.mPoint, action.mDelayOrBandwidth); - } - break; - - case PEERNET_ACTION_TYPE_RESTARTREQ: - { - /* connect attempt */ -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. Restart Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " mode: " << action.mMode; - std::cerr << std::endl; -#endif - - struct sockaddr_in laddr; - sockaddr_clear(&laddr); - uint32_t start = 1; - uint32_t delay = 0; - - mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode, delay, start); - } - break; - - case PEERNET_ACTION_TYPE_KILLREQ: - { - /* connect attempt */ -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. Kill Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " mode: " << action.mMode; - std::cerr << std::endl; -#endif - - struct sockaddr_in laddr; - sockaddr_clear(&laddr); - uint32_t start = 0; - uint32_t delay = 0; - - mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode, delay, start); - } - break; - - case PEERNET_ACTION_TYPE_TCPATTEMPT: - { - /* connect attempt */ -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. TCP Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " mode: " << action.mMode; - std::cerr << std::endl; -#endif - - RsPeerId peerRsId; - bool foundPeerId = false; - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RsDhtPeerType::ANY); - if (dpd) - { - peerRsId = dpd->mRsId; - foundPeerId = true; -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. TCP Connection Attempt. DoingCallback for RsID: "; - std::cerr << peerRsId; - std::cerr << std::endl; -#endif - } - else - { - std::cerr << "PeerAction. TCP Connection Attempt. ERROR unknown peer"; - std::cerr << std::endl; - } - } - - if (foundPeerId) - { - ConnectCalloutTCPAttempt(peerRsId, action.mDestId.addr); - } - } - break; - } - } - return 1; -} - - - - - -/****************************** Connection Logic ***************************/ - -/* Proxies!. - * - * We can allow all PROXY connections, as it is just a couple of messages, - * however, we should be smart about how many RELAY connections are allowed. - * - * e.g. Allow 20 Relay connections. - * 15 for friends, 5 for randoms. - * - * Can also validate addresses with own secure connections. - */ - -int p3BitDht::checkProxyAllowed(const bdId *srcId, const bdId *destId, int mode, uint32_t &bandwidth) -{ -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkProxyAllowed()"; - std::cerr << std::endl; -#endif - - // Dont think that a mutex is required here! But might be so just lock to ensure that it is possible. - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - } - - if (mode == BITDHT_CONNECT_MODE_PROXY) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkProxyAllowed() Allowing all PROXY connections, OKAY"; - std::cerr << std::endl; -#endif - - bandwidth = 0; // unlimited as p2p. - return 1; - //return CONNECTION_OKAY; - } - - if (mode != BITDHT_CONNECT_MODE_RELAY) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkProxyAllowed() unknown Connect Mode DENIED"; - std::cerr << std::endl; -#endif - return 0; - } - - /* will install the Relay Here... so that we reserve the Relay Space for later. - * decide on relay bandwidth limitation as well - */ - if (RelayHandler_InstallRelayConnection(srcId, destId, mode, bandwidth)) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkProxyAllowed() Successfully added Relay, Connection OKAY"; - std::cerr << std::endl; -#endif - - return 1; - // CONNECT_OKAY. - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkProxyAllowed() Failed to install Relay, Connection DENIED"; - std::cerr << std::endl; -#endif - - return 0; - //return CONNECT_MODE_OVERLOADED; - } - - return 0; - //return CONNECT_MODE_NOTAVAILABLE; - //return CONNECT_MODE_OVERLOADED; -} - - -int p3BitDht::checkConnectionAllowed(const bdId *peerId, int mode) -{ - (void) mode; - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkConnectionAllowed() to: "; - bdStdPrintId(std::cerr,peerId); - std::cerr << " mode: " << mode; - std::cerr << std::endl; -#endif - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - rstime_t now = time(NULL); - - /* check if they are in our friend list */ - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId->id), RsDhtPeerType::FRIEND); - if (!dpd) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkConnectionAllowed() Peer Not Friend, DENIED"; - std::cerr << std::endl; -#endif - - /* store as failed connection attempt */ - std::map::iterator it; - it = mFailedPeers.find(peerId->id); - if (it == mFailedPeers.end()) - { - mFailedPeers[peerId->id] = DhtPeerDetails(); - it = mFailedPeers.find(peerId->id); - } - - /* flag as failed */ - it->second.mDhtId = *peerId; - it->second.mDhtState = RsDhtPeerDht::NOT_ACTIVE; - it->second.mDhtUpdateTS = now; - - it->second.mPeerType = RsDhtPeerType::OTHER; - it->second.mPeerCbMsg = "Denied Non-Friend"; - - it->second.mPeerReqStatusMsg = "Denied Non-Friend"; - it->second.mPeerReqState = RsDhtPeerRequest::STOPPED; - it->second.mPeerReqTS = now; - it->second.mPeerReqMode = 0; - //it->second.mPeerProxyId; - it->second.mPeerReqTS = now; - - it->second.mPeerCbMsg = "Denied Non-Friend"; - - it->second.mPeerConnectMsg = "Denied Non-Friend"; - it->second.mPeerConnectState = RsDhtPeerConnectState::DISCONNECTED; - - - return 0; - //return NOT_FRIEND; - } - - /* are a friend */ - - if (dpd->mPeerConnectState == RsDhtPeerConnectState::CONNECTED) - { - std::cerr << "p3BitDht::checkConnectionAllowed() ERROR Peer Already Connected, DENIED"; - std::cerr << std::endl; - - // STATUS UPDATE DONE IN ACTION. - //it->second.mPeerStatusMsg = "2nd Connection Attempt!"; - //it->second.mPeerUpdateTS = now; - return 0; - //return ALREADY_CONNECTED; - } - - return 1; - //return CONNECTION_OKAY; -} - - - - - -/* So initiateConnection has to call out to other bits of RS. - * critical information is: - * Peer RsId, Peer Address, Connect Mode (includes Proxy/OrNot). - - * - * What do we need: ACTIVE / PASSIVE / UNSPEC - * + Min Delay Time, - */ - - -void p3BitDht::ConnectCalloutTCPAttempt(const RsPeerId &peerId, struct sockaddr_in raddrv4) -{ - struct sockaddr_storage raddr; - struct sockaddr_storage proxyaddr; - struct sockaddr_storage srcaddr; - - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(srcaddr); - - struct sockaddr_in *rap = (struct sockaddr_in *) &raddr; - //struct sockaddr_in *pap = (struct sockaddr_in *) &proxyaddr; - //struct sockaddr_in *sap = (struct sockaddr_in *) &srcaddr; - - // only one to translate - rap->sin_family = AF_INET; - rap->sin_addr = raddrv4.sin_addr; - rap->sin_port = raddrv4.sin_port; - - uint32_t source = RS_CB_DHT; - uint32_t connectFlags = RS_CB_FLAG_ORDER_UNSPEC | RS_CB_FLAG_MODE_TCP; - uint32_t delay = 0; - uint32_t bandwidth = 0; - - mConnCb->peerConnectRequest(peerId, raddr, proxyaddr, srcaddr, source, connectFlags, delay, bandwidth); -} - - -void p3BitDht::ConnectCalloutDirectOrProxy(const RsPeerId &peerId, struct sockaddr_in raddrv4, uint32_t connectFlags, uint32_t delay) -{ - struct sockaddr_storage raddr; - struct sockaddr_storage proxyaddr; - struct sockaddr_storage srcaddr; - - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(srcaddr); - - struct sockaddr_in *rap = (struct sockaddr_in *) &raddr; -// struct sockaddr_in *pap = (struct sockaddr_in *) &proxyaddr; -// struct sockaddr_in *sap = (struct sockaddr_in *) &srcaddr; - - // only one to translate - rap->sin_family = AF_INET; - rap->sin_addr = raddrv4.sin_addr; - rap->sin_port = raddrv4.sin_port; - - uint32_t source = RS_CB_DHT; - uint32_t bandwidth = 0; - - mConnCb->peerConnectRequest(peerId, raddr, proxyaddr, srcaddr, source, connectFlags, delay, bandwidth); -} - -void p3BitDht::ConnectCalloutRelay(const RsPeerId &peerId, - struct sockaddr_in srcaddrv4, struct sockaddr_in proxyaddrv4, struct sockaddr_in destaddrv4, - uint32_t connectFlags, uint32_t bandwidth) -{ - struct sockaddr_storage destaddr; - struct sockaddr_storage proxyaddr; - struct sockaddr_storage srcaddr; - - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(srcaddr); - - struct sockaddr_in *dap = (struct sockaddr_in *) &destaddr; - struct sockaddr_in *pap = (struct sockaddr_in *) &proxyaddr; - struct sockaddr_in *sap = (struct sockaddr_in *) &srcaddr; - - dap->sin_family = AF_INET; - dap->sin_addr = destaddrv4.sin_addr; - dap->sin_port = destaddrv4.sin_port; - - pap->sin_family = AF_INET; - pap->sin_addr = proxyaddrv4.sin_addr; - pap->sin_port = proxyaddrv4.sin_port; - - sap->sin_family = AF_INET; - sap->sin_addr = srcaddrv4.sin_addr; - sap->sin_port = srcaddrv4.sin_port; - - uint32_t source = RS_CB_DHT; - uint32_t delay = 0; - - mConnCb->peerConnectRequest(peerId, destaddr, proxyaddr, srcaddr, source, connectFlags, delay, bandwidth); -} - - - - -//virtual void peerConnectRequest(std::string id, struct sockaddr_in raddr, -// struct sockaddr_in proxyaddr, struct sockaddr_in srcaddr, -// uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth) = 0; - - -void p3BitDht::initiateConnection(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t loc, uint32_t delayOrBandwidth) -{ -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::initiateConnection()"; - std::cerr << std::endl; - std::cerr << "\t srcId: "; - bdStdPrintId(std::cerr, srcId); - std::cerr << std::endl; - - std::cerr << "\t proxyId: "; - bdStdPrintId(std::cerr, proxyId); - std::cerr << std::endl; - - std::cerr << "\t destId: "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; - - std::cerr << "\t Mode: " << mode << " loc: " << loc; - std::cerr << std::endl; - std::cerr << "\t DelayOrBandwidth: " << delayOrBandwidth; - std::cerr << std::endl; -#endif - - bdId peerConnectId; - - uint32_t connectFlags = 0; - - uint32_t delay = 0; - uint32_t bandwidth = 0; - - /* determine who the actual destination is. - * as we always specify the remote address, this is all we need. - */ - if (loc == BD_PROXY_CONNECTION_START_POINT) - { - peerConnectId = *destId; - /* lowest is active */ - if (srcId < destId) - { - connectFlags |= RS_CB_FLAG_ORDER_ACTIVE; - } - else - { - connectFlags |= RS_CB_FLAG_ORDER_PASSIVE; - } - } - else if (loc == BD_PROXY_CONNECTION_END_POINT) - { - peerConnectId = *srcId; - /* lowest is active (we are now dest - in this case) */ - if (destId < srcId) - { - connectFlags |= RS_CB_FLAG_ORDER_ACTIVE; - } - else - { - connectFlags |= RS_CB_FLAG_ORDER_PASSIVE; - } - } - else - { - std::cerr << "p3BitDht::initiateConnection() ERROR, NOT either START or END"; - std::cerr << std::endl; - /* ERROR */ - return; - } - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::initiateConnection() Connecting to "; - bdStdPrintId(std::cerr, &peerConnectId); - std::cerr << std::endl; -#endif - -// uint32_t touConnectMode = 0; - RsPeerId rsId; - - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerConnectId.id), RsDhtPeerType::FRIEND); - /* grab a socket */ - if (!dpd) - { - std::cerr << "p3BitDht::initiateConnection() ERROR Peer not found"; - std::cerr << std::endl; - return; - } - - if (dpd->mPeerConnectState != RsDhtPeerConnectState::DISCONNECTED) - { - std::cerr << "p3BitDht::initiateConnection() ERROR Peer is not Disconnected"; - std::cerr << std::endl; - return; - } - - rsId = dpd->mRsId; - - /* start the connection */ - /* These Socket Modes must match the TOU Stack - or it breaks. */ - switch(mode) - { - default: - case BITDHT_CONNECT_MODE_DIRECT: -// touConnectMode = RsDhtTouMode::DIRECT; - connectFlags |= RS_CB_FLAG_MODE_UDP_DIRECT; - delay = delayOrBandwidth; - break; - - case BITDHT_CONNECT_MODE_PROXY: - { - bool useProxyPort = dpd->mConnectLogic.getProxyPortChoice(); - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::initiateConnection() Peer Mode Proxy... deciding which port to use."; - std::cerr << " UseProxyPort? " << useProxyPort; - std::cerr << std::endl; -#endif - - delay = delayOrBandwidth; - if (useProxyPort) - { -// touConnectMode = RsDhtTouMode::PROXY; - connectFlags |= RS_CB_FLAG_MODE_UDP_PROXY; - } - else - { -// touConnectMode = RsDhtTouMode::DIRECT; - connectFlags |= RS_CB_FLAG_MODE_UDP_DIRECT; - } - - } - break; - - case BITDHT_CONNECT_MODE_RELAY: -// touConnectMode = RsDhtTouMode::RELAY; - connectFlags |= RS_CB_FLAG_MODE_UDP_RELAY; - bandwidth = delayOrBandwidth; - break; - } - - - dpd->mPeerConnectProxyId = *proxyId; - dpd->mPeerConnectPeerId = peerConnectId; - - - /* store results in Status */ - dpd->mPeerConnectMsg = "UDP started"; - dpd->mPeerConnectState = RsDhtPeerConnectState::UDP_STARTED; - dpd->mPeerConnectUdpTS = time(NULL); - dpd->mPeerConnectMode = mode; - dpd->mPeerConnectPoint = loc; - } - - /* finally we call out to start the connection (Outside of Mutex) */ - - if ((mode == BITDHT_CONNECT_MODE_DIRECT) || (mode == BITDHT_CONNECT_MODE_PROXY)) - { - ConnectCalloutDirectOrProxy(rsId, peerConnectId.addr, connectFlags, delay); - } - else if (mode == BITDHT_CONNECT_MODE_RELAY) - { - if (loc == BD_PROXY_CONNECTION_START_POINT) - { - ConnectCalloutRelay(rsId, srcId->addr, proxyId->addr, destId->addr, connectFlags, bandwidth); - } - else // END_POINT - { - /* reverse order connection call */ - ConnectCalloutRelay(rsId, destId->addr, proxyId->addr, srcId->addr, connectFlags, bandwidth); - } - } - - -} - - -int p3BitDht::installRelayConnection(const bdId *srcId, const bdId *destId, uint32_t &bandwidth) -{ - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - /* work out if either srcId or DestId is a friend */ - int relayClass = UDP_RELAY_CLASS_GENERAL; - -#ifdef DEBUG_PEERNET - RsPeerId strId1; - bdStdPrintNodeId(strId1, &(srcId->id), false); - - RsPeerId strId2; - bdStdPrintNodeId(strId2, &(destId->id), false); -#endif - - /* grab a socket */ - DhtPeerDetails *dpd_src = findInternalDhtPeer_locked(&(srcId->id), RsDhtPeerType::ANY); - DhtPeerDetails *dpd_dest = findInternalDhtPeer_locked(&(destId->id), RsDhtPeerType::ANY); - - if ((dpd_src) && (dpd_src->mPeerType == RsDhtPeerType::FRIEND)) - { - relayClass = UDP_RELAY_CLASS_FRIENDS; - } - else if ((dpd_dest) && (dpd_dest->mPeerType == RsDhtPeerType::FRIEND)) - { - relayClass = UDP_RELAY_CLASS_FRIENDS; - } - else if ((dpd_src) && (dpd_src->mPeerType == RsDhtPeerType::FOF)) - { - relayClass = UDP_RELAY_CLASS_FOF; - } - else if ((dpd_dest) && (dpd_dest->mPeerType == RsDhtPeerType::FOF)) - { - relayClass = UDP_RELAY_CLASS_FOF; - } - else - { - relayClass = UDP_RELAY_CLASS_GENERAL; - } - - /* will install the Relay Here... so that we reserve the Relay Space for later. */ - UdpRelayAddrSet relayAddrs(&(srcId->addr), &(destId->addr)); - if (mRelay->addUdpRelay(&relayAddrs, relayClass, bandwidth)) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::installRelayConnection() Successfully added Relay, Connection OKAY"; - std::cerr << std::endl; -#endif - - return 1; - // CONNECT_OKAY. - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::installRelayConnection() Failed to install Relay, Connection DENIED"; - std::cerr << std::endl; -#endif - - return 0; - //return CONNECT_MODE_OVERLOADED; - } - return 0; -} - - -int p3BitDht::removeRelayConnection(const bdId *srcId, const bdId *destId) -{ - //RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - UdpRelayAddrSet relayAddrs(&(srcId->addr), &(destId->addr)); - if (mRelay->removeUdpRelay(&relayAddrs)) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::removeRelayConnection() Successfully removed Relay"; - std::cerr << std::endl; -#endif - - return 1; - } - else - { - std::cerr << "p3BitDht::removeRelayConnection() ERROR Failed to remove Relay"; - std::cerr << std::endl; - - return 0; - } -} - -/***************************************************** UDP Connections *****************************/ - - -void p3BitDht::monitorConnections() -{ - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - rstime_t now = time(NULL); - - std::map::iterator it; - - for(it = mPeers.begin(); it != mPeers.end(); ++it) - { - /* ignore ones which aren't friends */ - if (it->second.mPeerType != RsDhtPeerType::FRIEND) - { - continue; - } - - if (it->second.mPeerConnectState == RsDhtPeerConnectState::UDP_STARTED) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::monitorConnections() Connection in progress to: "; - - bdStdPrintNodeId(std::cerr, &(it->second.mDhtId.id)); - std::cerr << std::endl; -#endif - - if (now - it->second.mPeerConnectUdpTS > PEERNET_CONNECT_TIMEOUT) - { - /* This CAN happen ;( */ -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::monitorConnections() WARNING InProgress Connection Failed: "; - bdStdPrintNodeId(std::cerr, &(it->second.mDhtId.id)); - std::cerr << std::endl; -#endif - - UdpConnectionFailed_locked(&(it->second)); - } - } - } -} - - - - -void p3BitDht::Feedback_Connected(const RsPeerId& pid) -{ - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - DhtPeerDetails *dpd = findInternalRsPeer_locked(pid); - - if (!dpd) - { - /* ERROR */ - std::cerr << "p3BitDht::Feedback_Connected() ERROR peer not found: " << pid; - std::cerr << std::endl; - - return; - } - - /* sanity checking */ - if (dpd->mPeerConnectState != RsDhtPeerConnectState::UDP_STARTED) - { - /* ERROR */ - std::cerr << "p3BitDht::Feedback_Connected() ERROR not in UDP_STARTED mode for: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; - - return; - } - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::monitorConnections() InProgress Connection Now Active: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - /* switch state! */ - dpd->mPeerConnectState = RsDhtPeerConnectState::CONNECTED; - dpd->mPeerConnectTS = time(NULL); - - dpd->mConnectLogic.updateCb(CSB_UPDATE_CONNECTED); - - rs_sprintf(dpd->mPeerConnectMsg, "Connected in %ld secs", dpd->mPeerConnectTS - dpd->mPeerConnectUdpTS); - - // Remove the Connection Request. - if (dpd->mPeerReqState == RsDhtPeerRequest::RUNNING) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::monitorConnections() Request Active, Stopping Request"; - std::cerr << std::endl; -#endif - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_KILLREQ; - ca.mMode = dpd->mPeerConnectMode; - //ca.mProxyId = *proxyId; - //ca.mSrcId = *srcId; - ca.mDestId = dpd->mPeerConnectPeerId; - //ca.mPoint = point; - ca.mAnswer = BITDHT_CONNECT_ERROR_NONE; - - mActions.push_back(ca); - - // What the Action should do... - //struct sockaddr_in tmpaddr; - //bdsockaddr_clear(&tmpaddr); - //int start = 0; - //mUdpBitDht->ConnectionRequest(&tmpaddr, &(it->second.mPeerConnectPeerId.id), it->second.mPeerConnectMode, start); - } - // only an error if we initiated the connection. - else if (dpd->mPeerConnectPoint == BD_PROXY_CONNECTION_START_POINT) - { - std::cerr << "p3BitDht::monitorConnections() ERROR Request not active, can't stop"; - std::cerr << std::endl; - } - - ReleaseProxyExclusiveMode_locked(dpd, true); -} - -void p3BitDht::Feedback_ConnectionFailed(const RsPeerId& pid) -{ - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - DhtPeerDetails *dpd = findInternalRsPeer_locked(pid); - - if (!dpd) - { - /* ERROR */ - std::cerr << "p3BitDht::Feedback_Connected() ERROR peer not found: " << pid; - std::cerr << std::endl; - - return; - } - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::Feedback_ConnectionFailed() UDP Connection Failed: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - return UdpConnectionFailed_locked(dpd); -} - -void p3BitDht::Feedback_ConnectionClosed(const RsPeerId& pid) -{ - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - DhtPeerDetails *dpd = findInternalRsPeer_locked(pid); - - if (!dpd) - { - /* ERROR */ - std::cerr << "p3BitDht::Feedback_Connected() ERROR peer not found: " << pid; - std::cerr << std::endl; - - return; - } - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::Feedback_ConnectionClosed() Active Connection Closed: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - return UdpConnectionFailed_locked(dpd); -} - - -void p3BitDht::UdpConnectionFailed_locked(DhtPeerDetails *dpd) -{ - if (dpd->mPeerConnectState == RsDhtPeerConnectState::UDP_STARTED) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::UdpConnectionFailed_locked() UDP Connection Failed: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - /* shut it down */ - - /* ONLY need to update ConnectLogic - if it was our Attempt Running */ - if (dpd->mPeerReqState == RsDhtPeerRequest::RUNNING) - { - dpd->mConnectLogic.updateCb(CSB_UPDATE_FAILED_ATTEMPT); - } - dpd->mPeerConnectState = RsDhtPeerConnectState::DISCONNECTED; - dpd->mPeerConnectMsg = "UDP Failed"; - - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::UdpConnectionFailed_locked() Active Connection Closed: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - dpd->mConnectLogic.updateCb(CSB_UPDATE_DISCONNECTED); - - dpd->mPeerConnectState = RsDhtPeerConnectState::DISCONNECTED; - dpd->mPeerConnectClosedTS = time(NULL); - rs_sprintf(dpd->mPeerConnectMsg, "Closed, Alive for: %ld secs", dpd->mPeerConnectClosedTS - dpd->mPeerConnectTS); - } - - - - if (dpd->mPeerReqState == RsDhtPeerRequest::RUNNING) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::UdpConnectionFailed_locked() "; - std::cerr << "Request Active (Paused)... Killing for next Attempt"; - std::cerr << std::endl; -#endif - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_KILLREQ; - ca.mMode = dpd->mPeerConnectMode; - //ca.mProxyId = *proxyId; - //ca.mSrcId = *srcId; - ca.mDestId = dpd->mPeerConnectPeerId; - //ca.mPoint = point; - ca.mAnswer = BITDHT_CONNECT_ERROR_NONE; - - mActions.push_back(ca); - } - // only an error if we initiated the connection. - else if (dpd->mPeerConnectPoint == BD_PROXY_CONNECTION_START_POINT) - { - std::cerr << "p3BitDht::UdpConnectionFailed_locked() "; - std::cerr << "ERROR Request not active, can't stop"; - std::cerr << std::endl; - } - - ReleaseProxyExclusiveMode_locked(dpd, true); -} - - - -void p3BitDht::ReleaseProxyExclusiveMode_locked(DhtPeerDetails *dpd, bool addrChgLikely) -{ -#ifdef DEBUG_BITDHT_COMMON - std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked()"; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - /* translate id into string for exclusive mode */ - std::string pid; - bdStdPrintNodeId(pid, &(dpd->mDhtId.id), false); - - - if (dpd->mExclusiveProxyLock) - { -#ifdef RS_USE_DHT_STUNNER - if (mProxyStunner->releaseExclusiveMode(pid, addrChgLikely)) - { - dpd->mExclusiveProxyLock = false; - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked() Lock released by Connection to peer: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - } - else -#else // RS_USE_DHT_STUNNER - (void)addrChgLikely; -#endif // RS_USE_DHT_STUNNER - { - dpd->mExclusiveProxyLock = false; - - std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked() ERROR ProxyStunner is not Locked"; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; - } - - } - else - { -#ifdef DEBUG_BITDHT_COMMON - std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked() Don't Have a Lock"; - std::cerr << std::endl; -#endif - } - -} - - -void p3BitDht::ConnectionFeedback(const RsPeerId& pid, int mode) -{ -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::ConnectionFeedback() peer: " << pid; - std::cerr << " mode: " << mode; - std::cerr << std::endl; -#endif - - switch(mode) - { - case NETMGR_DHT_FEEDBACK_CONNECTED: -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::ConnectionFeedback() HAVE CONNECTED (tcp?/udp) to peer: " << pid; - std::cerr << std::endl; -#endif - - Feedback_Connected(pid); - break; - - case NETMGR_DHT_FEEDBACK_CONN_FAILED: -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::ConnectionFeedback() UDP CONNECTION FAILED to peer: " << pid; - std::cerr << std::endl; -#endif - Feedback_ConnectionFailed(pid); - break; - - case NETMGR_DHT_FEEDBACK_CONN_CLOSED: -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::ConnectionFeedback() CONNECTION (tcp?/udp) CLOSED to peer: " << pid; - std::cerr << std::endl; -#endif - Feedback_ConnectionClosed(pid); - break; - } -} - - -/***** Check for a RelayHandler... and call its functions preferentially */ - -int p3BitDht::RelayHandler_LogFailedProxyAttempt(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t errcode) -{ - - { - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - if ((mRelayHandler) && (mRelayHandler->mLogFailedConnection)) - { - return mRelayHandler->mLogFailedConnection(srcId, destId, mode, errcode); - } - } - - /* NO standard handler */ - return 0; -} - - -int p3BitDht::RelayHandler_InstallRelayConnection(const bdId *srcId, const bdId *destId, - uint32_t mode, uint32_t &bandwidth) -{ - - { - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - if ((mRelayHandler) && (mRelayHandler->mInstallRelay)) - { - return mRelayHandler->mInstallRelay(srcId, destId, mode, bandwidth); - } - } - - /* standard handler */ - return installRelayConnection(srcId, destId, bandwidth); -} - - - - - diff --git a/libretroshare/src/dht/p3bitdht_peers.cc b/libretroshare/src/dht/p3bitdht_peers.cc deleted file mode 100644 index 013a9b47c..000000000 --- a/libretroshare/src/dht/p3bitdht_peers.cc +++ /dev/null @@ -1,752 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: p3bitdht_peernet.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2010 by Robert Fernie. * - * Copyright (C) 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#include "dht/p3bitdht.h" - -#include "bitdht/bdstddht.h" - -#include "tcponudp/udprelay.h" -#include "tcponudp/udpstunner.h" - -#include - -/*** - * - * #define DEBUG_BITDHT 1 - * #define DEBUG_BITDHT_TRANSLATE 1 - * - **/ - -/****************************************************************************************** - ********************************* Existing Interface ************************************* - ******************************************************************************************/ - /* pqiNetAssistConnect - external interface functions */ - /* add / remove peers */ -/***** - * At the moment, findPeer, dropPeer are the only way that peer info enters the dht. - * This will obviously change, and we will have a list of Friends and FoF, - * but for now we need to expect that this function will add unknown pids. - * - */ -#define USE_OLD_DHT_INTERFACE 1 - - -bool p3BitDht::findPeer(const RsPeerId& pid) -{ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer(" << pid << ")"; - std::cerr << std::endl; -#endif - bdNodeId nid; - - { - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - DhtPeerDetails *dpd = findInternalRsPeer_locked(pid); - if (!dpd) - { - dpd = addInternalPeer_locked(pid, RsDhtPeerType::FRIEND); - if (!dpd) - { - /* ERROR */ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() ERROR installing InternalPeer"; - std::cerr << std::endl; -#endif - return false; - } - - /* new entry... what do we need to set? */ - dpd->mDhtState = RsDhtPeerDht::SEARCHING; - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() Installed new DhtPeer with pid => NodeId: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - } - else - { - /* old entry */ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() Reactivating DhtPeer with pid => NodeId: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - if (dpd->mDhtState != RsDhtPeerDht::NOT_ACTIVE) - { -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() WARNING DhtState is Already Active!"; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - } - else - { - /* flag as searching */ - dpd->mDhtState = RsDhtPeerDht::SEARCHING; -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() Marking Old Peer as SEARCHING"; - std::cerr << std::endl; -#endif - } - - } - - nid = dpd->mDhtId.id; - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() calling AddFindNode() with pid => NodeId: "; - bdStdPrintNodeId(std::cerr, &nid); - std::cerr << std::endl; -#endif - - } - - /* add in peer */ - mUdpBitDht->addFindNode(&nid, BITDHT_QFLAGS_DO_IDLE | BITDHT_QFLAGS_UPDATES); - - return true ; -} - -bool p3BitDht::dropPeer(const RsPeerId& pid) -{ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::dropPeer(" << pid << ")"; - std::cerr << std::endl; -#endif - - bdNodeId nid; - - { - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - DhtPeerDetails *dpd = findInternalRsPeer_locked(pid); - if (!dpd) - { -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::dropPeer(" << pid << ") HACK TO INCLUDE FRIEND AS NON-ACTIVE PEER"; - std::cerr << std::endl; -#endif - - //addFriend(pid); - dpd = addInternalPeer_locked(pid, RsDhtPeerType::FOF); - - return false; - } - - /* flag as searching */ - dpd->mDhtState = RsDhtPeerDht::NOT_ACTIVE; - - nid = dpd->mDhtId.id; - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::dropPeer() calling removeFindNode() with pid => NodeId: "; - bdStdPrintNodeId(std::cerr, &nid); - std::cerr << std::endl; -#endif - } - - /* remove in peer */ - mUdpBitDht->removeFindNode(&nid); - - /* not removing from translation */ - - return true ; -} - - -/****************************************************************************************** - ********************************* Basic Peer Details ************************************* - ******************************************************************************************/ - -int p3BitDht::addBadPeer( const sockaddr_storage &addr, uint32_t /*reason*/, - uint32_t /*flags*/, uint32_t /*age*/ ) -{ - //mUdpBitDht->updateKnownPeer(&id, 0, bdflags); - - sockaddr_in addrv4; - sockaddr_storage tmpaddr; - sockaddr_storage_copy(addr, tmpaddr); - if(!sockaddr_storage_ipv6_to_ipv4(tmpaddr)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error: got non IPv4 address!" - << std::endl; - sockaddr_storage_dump(addr); - print_stacktrace(); - return -EINVAL; - } - - struct sockaddr_in *ap = (struct sockaddr_in *) &tmpaddr; - - // convert. - addrv4.sin_family = ap->sin_family; - addrv4.sin_addr = ap->sin_addr; - addrv4.sin_port = ap->sin_port; - -#ifdef RS_USE_DHT_STUNNER - if (mDhtStunner) - { - mDhtStunner->dropStunPeer(addrv4); - } - if (mProxyStunner) - { - mProxyStunner->dropStunPeer(addrv4); - } -#endif // RS_USE_DHT_STUNNER - return 1; -} - - -int p3BitDht::addKnownPeer( const RsPeerId &pid, - const sockaddr_storage &addr, uint32_t flags ) -{ - sockaddr_in addrv4; - sockaddr_clear(&addrv4); - - sockaddr_storage tmpaddr; - sockaddr_storage_copy(addr, tmpaddr); - if( !sockaddr_storage_isnull(addr) && - !sockaddr_storage_ipv6_to_ipv4(tmpaddr) ) - { - std::cerr << __PRETTY_FUNCTION__ << " Error: got non IPv4 address!" - << std::endl; - sockaddr_storage_dump(addr); - print_stacktrace(); - return -EINVAL; - } - - // convert. - struct sockaddr_in *ap = (struct sockaddr_in *) &tmpaddr; - addrv4.sin_family = ap->sin_family; - addrv4.sin_addr = ap->sin_addr; - addrv4.sin_port = ap->sin_port; - - RsDhtPeerType p3type = RsDhtPeerType::ANY; - int bdflags = 0; - bdId id; - bool isOwnId = false; - - switch(flags & NETASSIST_KNOWN_PEER_TYPE_MASK) - { - default: - return 0; - break; - case NETASSIST_KNOWN_PEER_WHITELIST: - p3type = RsDhtPeerType::OTHER; - bdflags = BITDHT_PEER_STATUS_DHT_WHITELIST; - - break; - case NETASSIST_KNOWN_PEER_FOF: - p3type = RsDhtPeerType::FOF; - bdflags = BITDHT_PEER_STATUS_DHT_FOF; - - break; - case NETASSIST_KNOWN_PEER_FRIEND: - p3type = RsDhtPeerType::FRIEND; - bdflags = BITDHT_PEER_STATUS_DHT_FRIEND; - - break; - case NETASSIST_KNOWN_PEER_RELAY: - p3type = RsDhtPeerType::OTHER; - bdflags = BITDHT_PEER_STATUS_DHT_RELAY_SERVER; - - break; - case NETASSIST_KNOWN_PEER_SELF: - p3type = RsDhtPeerType::OTHER; - bdflags = BITDHT_PEER_STATUS_DHT_SELF; - isOwnId = true; - - - break; - } - - if (flags & NETASSIST_KNOWN_PEER_ONLINE) - { - bdflags |= BD_FRIEND_ENTRY_ONLINE; - } - - if (!isOwnId) - { - RS_STACK_MUTEX(dhtMtx); - DhtPeerDetails *dpd = addInternalPeer_locked(pid, p3type); - - - if (bdflags & BD_FRIEND_ENTRY_ONLINE) - { - /* can we update the address? */ - //dpd->mDhtId.addr = addr; - } - - - id.id = dpd->mDhtId.id; - id.addr = addrv4; - } - else - { - // shouldn't use own id without mutex - but it is static! - id.id = mOwnDhtId; - id.addr = addrv4; - } - - mUdpBitDht->updateKnownPeer(&id, 0, bdflags); - - return 1; -} - - -/* Total duplicate of above function - can't be helped, should merge somehow */ -int p3BitDht::addKnownNode(const bdId *id, uint32_t flags) -{ - int bdflags = 0; - - switch(flags & NETASSIST_KNOWN_PEER_TYPE_MASK) - { - default: - return 0; - break; - case NETASSIST_KNOWN_PEER_WHITELIST: - bdflags = BITDHT_PEER_STATUS_DHT_WHITELIST; - - break; - case NETASSIST_KNOWN_PEER_FOF: - bdflags = BITDHT_PEER_STATUS_DHT_FOF; - - break; - case NETASSIST_KNOWN_PEER_FRIEND: - bdflags = BITDHT_PEER_STATUS_DHT_FRIEND; - - break; - case NETASSIST_KNOWN_PEER_RELAY: - bdflags = BITDHT_PEER_STATUS_DHT_RELAY_SERVER; - - break; - case NETASSIST_KNOWN_PEER_SELF: - bdflags = BITDHT_PEER_STATUS_DHT_SELF; - - break; - } - - if (flags & NETASSIST_KNOWN_PEER_ONLINE) - { - bdflags |= BD_FRIEND_ENTRY_ONLINE; - } - - mUdpBitDht->updateKnownPeer(id, 0, bdflags); - - return 1; -} - - - -#if 0 -int p3BitDht::addFriend(const std::string pid) -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - return (NULL != addInternalPeer_locked(pid, RsDhtPeerType::FRIEND)); -} - - -int p3BitDht::addFriendOfFriend(const std::string pid) -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - return (NULL != addInternalPeer_locked(pid, RsDhtPeerType::FOF)); -} - - -int p3BitDht::addOther(const std::string pid) -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - return (NULL != addInternalPeer_locked(pid, RsDhtPeerType::OTHER)); -} -#endif - - -int p3BitDht::removePeer(const RsPeerId& pid) -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - return removeInternalPeer_locked(pid); -} - - -/****************************************************************************************** - ********************************* Basic Peer Details ************************************* - ******************************************************************************************/ - -DhtPeerDetails *p3BitDht::addInternalPeer_locked(const RsPeerId& pid, RsDhtPeerType type) -{ - /* create the data structure */ - if (!havePeerTranslation_locked(pid)) - { - storeTranslation_locked(pid); - } - - bdNodeId id; - if (!lookupNodeId_locked(pid, &id)) - { - return 0; - } - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&id, RsDhtPeerType::ANY); - if (!dpd) - { - DhtPeerDetails newdpd; - - newdpd.mDhtId.id = id; - newdpd.mRsId = pid; - newdpd.mDhtState = RsDhtPeerDht::NOT_ACTIVE; - newdpd.mPeerType = RsDhtPeerType::ANY; - - mPeers[id] = newdpd; - dpd = findInternalDhtPeer_locked(&id, RsDhtPeerType::ANY); - - if(dpd == NULL) - { - std::cerr << "(EE) inconsistency error in p3BitDht::addInternalPeer_locked() Cannot find peer that was just added." << std::endl; - return NULL; - } - } - - /* what do we need to reset? */ - dpd->mPeerType = type; - - return dpd; -} - - -int p3BitDht::removeInternalPeer_locked(const RsPeerId& pid) -{ - bdNodeId id; - if (!lookupNodeId_locked(pid, &id)) - { - return 0; - } - - std::map::iterator it = mPeers.find(id); - if (it == mPeers.end()) - { - return 0; - } - - mPeers.erase(it); - - // remove the translation? - removeTranslation_locked(pid); - - return 1; -} - - -/* indexed by bdNodeId, as this is the more used call interface */ -DhtPeerDetails *p3BitDht::findInternalDhtPeer_locked(const bdNodeId *id, RsDhtPeerType type) -{ - std::map::iterator it = mPeers.find(*id); - if (it == mPeers.end()) - { - return NULL; - } - if (type != RsDhtPeerType::ANY) - { - if (it->second.mPeerType != type) - { - return NULL; - } - } - return &(it->second); -} - - -/* interface to get with alt id */ -DhtPeerDetails *p3BitDht::findInternalRsPeer_locked(const RsPeerId &pid) -{ - /* create the data structure */ - if (!havePeerTranslation_locked(pid)) - { - return NULL; - } - - bdNodeId id; - if (!lookupNodeId_locked(pid, &id)) - { - return NULL; - } - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&id,RsDhtPeerType::ANY); - - return dpd; -} - - -/****************************************************************************************** - *************************** Fundamental Node Translation ********************************* - ******************************************************************************************/ - -bool p3BitDht::havePeerTranslation_locked(const RsPeerId &pid) -{ -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::havePeerTranslation_locked() for : " << pid; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mTransToNodeId.find(pid); - if (it == mTransToNodeId.end()) - { -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::havePeerTranslation_locked() failed Missing translation"; - std::cerr << std::endl; -#endif - - return false; - } - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::havePeerTranslation_locked() Found NodeId: "; - bdStdPrintNodeId(std::cerr, &(it->second)); - std::cerr << std::endl; -#endif - - return true; -} - - -int p3BitDht::lookupNodeId_locked(const RsPeerId& pid, bdNodeId *id) -{ -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::lookupNodeId_locked() for : " << pid; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mTransToNodeId.find(pid); - if (it == mTransToNodeId.end()) - { -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::lookupNodeId_locked() failed"; - std::cerr << std::endl; -#endif - - return 0; - } - *id = it->second; - - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::lookupNodeId_locked() Found NodeId: "; - bdStdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - - return 1; -} - - -int p3BitDht::lookupRsId_locked(const bdNodeId *id, RsPeerId&pid) -{ -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::lookupRsId_locked() for : "; - bdStdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - - std::map::iterator nit; - nit = mTransToRsId.find(*id); - if (nit == mTransToRsId.end()) - { -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::lookupRsId_locked() failed"; - std::cerr << std::endl; -#endif - - return 0; - } - pid = nit->second; - - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::lookupRsId_locked() Found Matching RsId: " << pid; - std::cerr << std::endl; -#endif - - return 1; -} - -int p3BitDht::storeTranslation_locked(const RsPeerId& pid) -{ -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::storeTranslation_locked(" << pid << ")"; - std::cerr << std::endl; -#endif - - bdNodeId nid; - calculateNodeId(pid, &nid); - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::storeTranslation_locked() Converts to NodeId: "; - bdStdPrintNodeId(std::cerr, &(nid)); - std::cerr << std::endl; -#endif - - mTransToNodeId[pid] = nid; - mTransToRsId[nid] = pid; - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::storeTranslation_locked() Success"; - std::cerr << std::endl; -#endif - - return 1; -} - -int p3BitDht::removeTranslation_locked(const RsPeerId& pid) -{ - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::removeTranslation_locked(" << pid << ")"; - std::cerr << std::endl; -#endif - - std::map::iterator it = mTransToNodeId.find(pid); - it = mTransToNodeId.find(pid); - if (it == mTransToNodeId.end()) - { - std::cerr << "p3BitDht::removeTranslation_locked() ERROR MISSING TransToNodeId"; - std::cerr << std::endl; - /* missing */ - return 0; - } - - bdNodeId nid = it->second; - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::removeTranslation_locked() Found Translation: NodeId: "; - bdStdPrintNodeId(std::cerr, &(nid)); - std::cerr << std::endl; -#endif - - - std::map::iterator nit; - nit = mTransToRsId.find(nid); - if (nit == mTransToRsId.end()) - { - std::cerr << "p3BitDht::removeTranslation_locked() ERROR MISSING TransToRsId"; - std::cerr << std::endl; - /* inconsistent!!! */ - return 0; - } - - mTransToNodeId.erase(it); - mTransToRsId.erase(nit); - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::removeTranslation_locked() SUCCESS"; - std::cerr << std::endl; -#endif - - return 1; -} - - -/* Adding a little bit of fixed text... - * This allows us to ensure that only compatible peers will find each other - */ - -const uint8_t RS_DHT_VERSION_LEN = 17; -const uint8_t rs_dht_version_data[RS_DHT_VERSION_LEN] = "RS_VERSION_0.5.1"; - -/******************** Conversion Functions **************************/ -int p3BitDht::calculateNodeId(const RsPeerId& pid, bdNodeId *id) -{ - /* generate node id from pid */ -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::calculateNodeId() " << pid; -#endif - - /* use a hash to make it impossible to reverse */ - - uint8_t sha_hash[SHA_DIGEST_LENGTH]; - memset(sha_hash,0,SHA_DIGEST_LENGTH*sizeof(uint8_t)) ; - SHA_CTX *sha_ctx = new SHA_CTX; - SHA1_Init(sha_ctx); - - SHA1_Update(sha_ctx, rs_dht_version_data, RS_DHT_VERSION_LEN); - SHA1_Update(sha_ctx, pid.toByteArray(), RsPeerId::SIZE_IN_BYTES); - SHA1_Final(sha_hash, sha_ctx); - - for(int i = 0; i < SHA_DIGEST_LENGTH && (i < BITDHT_KEY_LEN); i++) - { - id->data[i] = sha_hash[i]; - } - delete sha_ctx; - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << " => "; - bdStdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - - return 1; -} - - -/******************** Conversion Functions **************************/ - -DhtPeerDetails::DhtPeerDetails() -{ - mDhtState = RsDhtPeerDht::NOT_ACTIVE; - - mDhtState = RsDhtPeerDht::SEARCHING; - mDhtUpdateTS = time(NULL); - - mPeerReqStatusMsg = "Just Added"; - mPeerReqState = RsDhtPeerRequest::STOPPED; - mPeerReqMode = 0; - //mPeerReqProxyId; - mPeerReqTS = time(NULL); - - mExclusiveProxyLock = false; - - mPeerCbMsg = "No CB Yet"; - mPeerCbMode = 0; - mPeerCbPoint = 0; - //mPeerCbProxyId = 0; - //mPeerCbDestId = 0; - mPeerCbTS = 0; - - mPeerConnectState = RsDhtPeerConnectState::DISCONNECTED; - mPeerConnectMsg = "Disconnected"; - mPeerConnectMode = 0; - //dpd->mPeerConnectProxyId; - mPeerConnectPoint = 0; - - mPeerConnectUdpTS = 0; - mPeerConnectTS = 0; - mPeerConnectClosedTS = 0; - - bdsockaddr_clear(&(mPeerConnectAddr)); -} - diff --git a/libretroshare/src/dht/p3bitdht_relay.cc b/libretroshare/src/dht/p3bitdht_relay.cc deleted file mode 100644 index 2d2845c83..000000000 --- a/libretroshare/src/dht/p3bitdht_relay.cc +++ /dev/null @@ -1,404 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: p3bitdht_relay.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2011 by Robert Fernie. * - * * - * 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 . * - * * - ******************************************************************************/ - -#include "util/rsnet.h" -#include "dht/p3bitdht.h" - -#include "tcponudp/udprelay.h" -#include "bitdht/bdstddht.h" - -#include "rsitems/rsconfigitems.h" - - -/*********************************************************************************************** - ********** External RsDHT Interface for Dht-Relay Control ************************************* -************************************************************************************************/ - -int p3BitDht::setupRelayDefaults() -{ - RsDhtRelayMode mode = RsDhtRelayMode::ENABLED | RsDhtRelayMode::OFF; - setRelayMode(mode); - - return 1; -} - - -/**** THIS IS A TEMPORARY HACK INTERFACE - UNTIL WE HAVE MORE SOFISTICATED SYSTEM - * NB: using bdNodeIds here, rather than SSL IDS. - *****/ - -int p3BitDht::getRelayServerList(std::list &ids) -{ - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - - ids = mRelayServerList; - - return 1; -} - -int p3BitDht::addRelayServer(std::string id) -{ - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - - std::list::iterator it; - it = std::find(mRelayServerList.begin(), mRelayServerList.end(), id); - if (it == mRelayServerList.end()) - { - mRelayServerList.push_back(id); - } - - IndicateConfigChanged(); - return 1; -} - -int p3BitDht::removeRelayServer(std::string id) -{ - - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - - std::list::iterator it; - it = std::find(mRelayServerList.begin(), mRelayServerList.end(), id); - if (it != mRelayServerList.end()) - { - mRelayServerList.erase(it); - } - - IndicateConfigChanged(); - return 1; -} - -int p3BitDht::pushRelayServers() -{ - std::list servers; - - { - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - - servers = mRelayServerList; - } - - std::list::iterator it; - for(it = servers.begin(); it != servers.end(); ++it) - { - /* push it to dht */ - uint32_t bdflags = BITDHT_PEER_STATUS_DHT_RELAY_SERVER; - bdId id; - bdStdLoadNodeId(&(id.id), *it); - - mUdpBitDht->updateKnownPeer(&id, 0, bdflags); - - } - return 1; -} - - -RsDhtRelayMode p3BitDht::getRelayMode() -{ - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - - return mRelayMode; -} - -int p3BitDht::setRelayMode(RsDhtRelayMode mode) -{ - std::cerr << "p3BitDht::setRelayMode(" << mode << ")"; - std::cerr << std::endl; - - if (!!(mode & RsDhtRelayMode::ENABLED)) - { - mUdpBitDht->ConnectionOptions( - BITDHT_CONNECT_MODE_DIRECT | BITDHT_CONNECT_MODE_PROXY | BITDHT_CONNECT_MODE_RELAY, - BITDHT_CONNECT_OPTION_AUTOPROXY); - } - else - { - mUdpBitDht->ConnectionOptions( - BITDHT_CONNECT_MODE_DIRECT | BITDHT_CONNECT_MODE_PROXY, - BITDHT_CONNECT_OPTION_AUTOPROXY); - } - - RsDhtRelayMode relaymode = mode & RsDhtRelayMode::MASK; - - switch(relaymode) - { - case RsDhtRelayMode::OFF: - mUdpBitDht->setDhtMode(BITDHT_MODE_RELAYSERVERS_IGNORED); - break; - case RsDhtRelayMode::ON: - pushRelayServers(); - mUdpBitDht->setDhtMode(BITDHT_MODE_RELAYSERVERS_FLAGGED); - break; - case RsDhtRelayMode::SERVER: - pushRelayServers(); - mUdpBitDht->setDhtMode(BITDHT_MODE_RELAYSERVERS_SERVER); - break; - } - - { - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - mRelayMode = mode; - } - - IndicateConfigChanged(); - - return 1; -} - -int p3BitDht::getRelayAllowance(RsDhtRelayClass classIdx, uint32_t &count, uint32_t &bandwidth) -{ - std::cerr << "p3BitDht::getRelayAllowance(" << static_cast::type>(classIdx) << "): "; - if ((classIdx >= RsDhtRelayClass::ALL) && (classIdx < RsDhtRelayClass::NUM_CLASS)) - { - count = mRelay->getRelayClassMax(static_cast::type>(classIdx)); - bandwidth = mRelay->getRelayClassBandwidth(static_cast::type>(classIdx)); - - std::cerr << " count: " << count << " bandwidth: " << bandwidth; - std::cerr << std::endl; - return 1; - } - std::cerr << " Invalid classIdx"; - std::cerr << std::endl; - - return 0; -} - -int p3BitDht::setRelayAllowance(RsDhtRelayClass classIdx, uint32_t count, uint32_t bandwidth) -{ - std::cerr << "p3BitDht::getRelayAllowance(" << static_cast::type>(classIdx) << ", "; - std::cerr << ", " << count << ", " << bandwidth << ")"; - std::cerr << std::endl; - - int retval = mRelay->setRelayClassMax(static_cast::type>(classIdx), count, bandwidth); - IndicateConfigChanged(); - - return retval; -} - - -/*********************************************************************************************** - ********** External RsDHT Interface for Dht-Relay Control ************************************* -************************************************************************************************/ - -/*****************************************************************/ -/*********************** p3config ******************************/ - /* Key Functions to be overloaded for Full Configuration */ -RsSerialiser *p3BitDht::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - return rss ; -} - - -bool p3BitDht::saveList(bool &cleanup, std::list &saveList) -{ - cleanup = true; - - std::cerr << "p3BitDht::saveList()"; - std::cerr << std::endl; - - - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - RsConfigKeyValueSet *config = new RsConfigKeyValueSet(); - - RsTlvKeyValue kv; - - /* Push Relay Class Stuff */ - int i; - for(i = 0; i < static_cast::type>(RsDhtRelayClass::NUM_CLASS); ++i) - { - rs_sprintf(kv.key, "RELAY_CLASS%d_COUNT", i); - rs_sprintf(kv.value, "%d", mRelay->getRelayClassMax(i)); - config->tlvkvs.pairs.push_back(kv); - - rs_sprintf(kv.key, "RELAY_CLASS%d_BANDWIDTH", i); - rs_sprintf(kv.value, "%d", mRelay->getRelayClassBandwidth(i)); - config->tlvkvs.pairs.push_back(kv); - } - - /* add RelayMode */ - { - kv.key = "RELAY_MODE"; - rs_sprintf(kv.value, "%lu", mRelayMode); - config->tlvkvs.pairs.push_back(kv); - } - - /* add Servers */ - std::list::iterator it; - for(i = 0, it = mRelayServerList.begin(); it != mRelayServerList.end(); ++it, ++i) - { - rs_sprintf(kv.key, "RELAY_SERVER%d", i); - kv.value = *it; - config->tlvkvs.pairs.push_back(kv); - } - - std::cerr << "BITDHT Save Item:"; - std::cerr << std::endl; - - config->print(std::cerr, 0); - - saveList.push_back(config); - - return true; -} - -void p3BitDht::saveDone() -{ - return; -} - -bool p3BitDht::loadList(std::list& load) -{ - std::cerr << "p3BitDht::loadList()"; - std::cerr << std::endl; - - if (load.empty() || (load.size() > 1)) - { - /* error */ - std::cerr << "p3BitDht::loadList() Error only expecting 1 item"; - std::cerr << std::endl; - - for(std::list::iterator it=load.begin();it!=load.end();++it) - delete *it ; - - load.clear() ; - return false; - } - RsItem *item = load.front(); - - RsConfigKeyValueSet *config = dynamic_cast(item); - - if (!config) - { - /* error */ - std::cerr << "p3BitDht::loadList() Error expecting item = config"; - std::cerr << std::endl; - delete item ; - return false; - } - - //std::cerr << "BITDHT Load Item:"; - //std::cerr << std::endl; - - //config->print(std::cerr, 0); - - std::list servers; - int peers[static_cast::type>(RsDhtRelayClass::NUM_CLASS)] = {0}; - int bandwidth[static_cast::type>(RsDhtRelayClass::NUM_CLASS)] = {0}; - - bool haveMode = false; - RsDhtRelayMode mode = RsDhtRelayMode::DISABLED; - - std::list::iterator it; - for(it = config->tlvkvs.pairs.begin(); it != config->tlvkvs.pairs.end(); ++it) - { - std::string key = it->key; - std::string value = it->value; - if (0 == strncmp(key.c_str(), "RELAY_SERVER", 12)) - { - /* add to RELAY_SERVER List */ - servers.push_back(value); - //std::cerr << "p3BitDht::loadList() Found Server: " << value; - //std::cerr << std::endl; - } - else if (0 == strncmp(key.c_str(), "RELAY_MODE", 10)) - { - mode = static_cast(atoi(value.c_str())); - haveMode = true; - - //std::cerr << "p3BitDht::loadList() Found Mode: " << mode; - //std::cerr << std::endl; - } - else if (0 == strncmp(key.c_str(), "RELAY_CLASS", 11)) - { - /* len check */ - if (key.length() < 14) - continue; - - int idx = 0; - uint32_t val = atoi(value.c_str()); - switch(key[11]) - { - default: - case '0': - idx = 0; - break; - case '1': - idx = 1; - break; - case '2': - idx = 2; - break; - case '3': - idx = 3; - break; - } - - if (key[13] == 'C') - { - //std::cerr << "p3BitDht::loadList() Found Count(" << idx << "): "; - //std::cerr << val; - //std::cerr << std::endl; - peers[idx] = val; - } - else - { - //std::cerr << "p3BitDht::loadList() Found Bandwidth(" << idx << "): "; - //std::cerr << val; - //std::cerr << std::endl; - bandwidth[idx] = val; - } - } - else - { - //std::cerr << "p3BitDht::loadList() Unknown Key:value: " << key; - //std::cerr << ":" << value; - //std::cerr << std::endl; - } - } - - - // Cleanup config. - delete config; - - { - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - mRelayServerList = servers; - } - - int i; - for(i = 0; i < static_cast::type>(RsDhtRelayClass::NUM_CLASS); ++i) - { - mRelay->setRelayClassMax(i, peers[i], bandwidth[i]); - } - - if (haveMode) - { - setRelayMode(mode); - } - - load.clear() ; - return true; -} - -/*****************************************************************/ - diff --git a/libretroshare/src/dht/stunaddrassist.h b/libretroshare/src/dht/stunaddrassist.h deleted file mode 100644 index 195337b1a..000000000 --- a/libretroshare/src/dht/stunaddrassist.h +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: stunaddrassist.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie. * - * * - * 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 . * - * * - ******************************************************************************/ - -#ifndef STUN_ADDR_ASSIST_H -#define STUN_ADDR_ASSIST_H - -#include "pqi/pqiassist.h" -#include "tcponudp/udpstunner.h" - -class stunAddrAssist: public pqiAddrAssist -{ - public: - - stunAddrAssist(UdpStunner *stunner) - { - mStunner = stunner; - } - -virtual bool getExternalAddr(struct sockaddr_storage &remote, uint8_t &stable) - { - // IPV4 ONLY. - struct sockaddr_in remotev4; - if (mStunner->externalAddr(remotev4, stable)) - { - sockaddr_storage_clear(remote); - struct sockaddr_in *addr = (struct sockaddr_in *) &remote; - addr->sin_family = AF_INET; - addr->sin_addr = remotev4.sin_addr; - addr->sin_port = remotev4.sin_port; - - return true; - } - return false; - } - -virtual int tick() - { - return mStunner->tick(); - } - -virtual void setRefreshPeriod(int32_t period) - { - return mStunner->setTargetStunPeriod(period); - } - - private: - - UdpStunner *mStunner; -}; - -#endif - diff --git a/libretroshare/src/file_sharing/README.txt b/libretroshare/src/file_sharing/README.txt deleted file mode 100644 index 947cf64be..000000000 --- a/libretroshare/src/file_sharing/README.txt +++ /dev/null @@ -1,215 +0,0 @@ -Design document for the new file list sharing system. -==================================================== - -Big picture ------------ - - p3SharesManager - Functionalities - * contains the list of shared files - - responds to search, requests for FileInfo - * responsible for sync-ing file lists between peers - - Level 3: interface with GUI - - regularly issue syncing requests in background - - automatically issue syncing requests as files are browsed - - Level 2: internal stuff - - examine syncing requests. Only get data - - Level 1: syncing system - - list of pending requests with priorities, sort them and handle response from friends - - Level 0: interface with friends - - serialisation/deserialisation of file list items - - FileIndex should support: - - O(log(n)) search for hash - - O(n) search for regular exp - - O(1) remove of file and directory - - Members - - list of file indexes - => map of - - - - Parent classes - - p3Service (sends and receives information about shared files) - - Notes: - - the same file should be able to be held by two different directories. Hash search will return a single hit. - - the previously existing PersonEntry had no field and was overloading DirEntry, with overwritten file names, hashes etc. Super bad! - -Directory storage file format ------------------------------ - * should be extensible (xml or binary format? Binary, because it's going to be encrypted anyway) - => works with binary fields - => - - [= version =] - [= peer id =] - [= num entries =] - [= some information =] - - [entry tag] [entry size] [Field ID 01] [field size v 01] [Field data 01] [Field ID 02] [field size v 02] [Field data 02] ... - [entry tag] [entry size] [Field ID 01] [field size v 01] [Field data 01] [Field ID 02] [field size v 02] [Field data 02] ... - [entry tag] [entry size] [Field ID 01] [field size v 01] [Field data 01] [Field ID 02] [field size v 02] [Field data 02] ... - ... - 2 1-5 v 2 1-5 v - * entry content - Tag | Content | Size - ----------------+--------------------------------------+------ - 01 | sha1 hash | 20 - 01 | sha1^2 hash | 20 - 02 | file name | < 512 - 03 | file size | 8 - 04 | dir name | < 512 - 05 | last modif time local | 4 - 06 | last modif time including sub-dirs | 4 - -Classes -------- - - p3ShareManager - - tick() - * handle pending syncing requests => sends items - * watch shared directories - => hash new files - => updates shared files - * - - - list of shared parent directories, with share flags - - FileIndex // should support hierarchical navigation, load/save - - - - LocalFileIndex: public FileIndex - - std::map // used for search - - FileInfo - - std::string name - - RsFileHash hash - - uint64_t size - - rstime_t Last modification time - - LocalFileInfo: public FileInfo - - rstime_t Last data access time - - uint64_t Total data uploaded - - uint32_t ShareFlags - - SharedDirectory - - parent groups - - group flags - -Best data structure for file index ----------------------------------- - - | Hash map map list - ----------------+-----------------+------------+-------------- - Adding | Constant | log(n) | O(n) - Hash search | Constant | log(n) | O(n) - Name/exp search | O(n) | O(n) | O(n) - Recursive browse| Constant | log(n) | O(n) - - Should we use the same struct for files and directories? - - Sol 1: - DirClass + PersonClass + FileEntry class - - each has pointers to elements list of the same type - - lists are handled for Files (all file entries), - - Directories are represented by the hash of the full path - - Sol 2: - Same class for all elements, in a single hash map. Each element is - defined by its type (Dir, Person, File) which all have a hash. - -Syncing between peers ---------------------- - -Generating sync events - * Client side - - for each directory, in breadth first order - - if directory has changed, or last update is old - => push a sync request - - store the peer's last up time. Compare with peer uptimes recursively. - - * Server side - - after a change, broadcast a "directory changed" packet to all connected friends - - * directoy updater - - crawl through directories - - compare TS of files, missing files, new files - - feed a queue of files to hash - - directory whatcher gets notified when files are hashed - - - a separate component hashes files (FileHashingProcess) - - DirectoryWatcher (watches a hierarchy) File List (stores a directory hierarchy) - | | - | | - | | - +-----------------------+------------------+ - | | - Shared File Service | - | | - | | - +----------- own file list -------+---------- Encrypted/compressed save to disk - | | | - +----------- friend file lists ---+ -Roadmap -------- - -[X] complete this file until a proper description of the whole thing is achieved. -[X] create a new directory and implement the .h for the basic functionality -[ ] look into existing code in ftServer for the integration, but don't change anything yet -[X] setup class hierarchy -[ ] merge hash cache into file lists. -[ ] new format for saving of FileIndex to make it locally encrypted, compact and extensible -[ ] create basic directory functionality with own files: re-hash, and store -[ ] display own files in GUI, with proper update and working sort - -TODO -==== - - [ ] directory handler - [ ] abstract functions to keep a directory and get updates to it. - [ ] hierarchical storage representation. - [ ] allow add/delete entries - [ ] auto-cleanup - - [ ] directory updater - [ ] abstract layer - [ ] crawls the directory and ask updates - - [ ] derive local directory updater - [ ] crawl local files, and asks updates to storage class - [ ] derive remote directory updater - [ ] crawl stored files, and request updates to storage class - - [ ] load/save of directory content. Should be extensible - [ ] p3FileLists with minimal functonality: no exchange. Only storage of own file lists - [ ] service (items) for p3FileLists - [ ] connect RemoteDirModel to new system - [ ] test GUI functions - [ ] test update between peers - - - - - - - - - - - - - - - - - - - - diff --git a/libretroshare/src/file_sharing/dir_hierarchy.cc b/libretroshare/src/file_sharing/dir_hierarchy.cc deleted file mode 100644 index d93df1d1b..000000000 --- a/libretroshare/src/file_sharing/dir_hierarchy.cc +++ /dev/null @@ -1,1235 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: dir_hierarchy.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ -#include -#include - -#include "util/rstime.h" -#include "util/rsdir.h" -#include "util/rsprint.h" -#include "retroshare/rsexpr.h" -#include "dir_hierarchy.h" -#include "filelist_io.h" -#include "file_sharing_defaults.h" - -#ifdef RS_DEEP_FILES_INDEX -# include "deep_search/filesindex.hpp" -#endif // def RS_DEEP_FILES_INDEX - -//#define DEBUG_DIRECTORY_STORAGE 1 - -typedef FileListIO::read_error read_error; - -/******************************************************************************************************************/ -/* Internal File Hierarchy Storage */ -/******************************************************************************************************************/ - -template typename std::set::iterator erase_from_set(typename std::set& s,const typename std::set::iterator& it) -{ - typename std::set::iterator tmp(it); - ++tmp; - s.erase(it) ; - return tmp; -} - -// This class handles the file hierarchy -// A Mutex is used to ensure total coherence at this level. So only abstracted operations are allowed, -// so that the hierarchy stays completely coherent between calls. - -InternalFileHierarchyStorage::InternalFileHierarchyStorage() : mRoot(0) -{ - DirEntry *de = new DirEntry("") ; - - de->row=0; - de->parent_index=0; - de->dir_modtime=0; - de->dir_hash=RsFileHash() ; // null hash is root by convention. - - mNodes.push_back(de) ; - mDirHashes[de->dir_hash] = 0 ; - - mTotalSize = 0 ; - mTotalFiles = 0 ; -} - -bool InternalFileHierarchyStorage::getDirHashFromIndex(const DirectoryStorage::EntryIndex& index,RsFileHash& hash) const -{ - if(!checkIndex(index,FileStorageNode::TYPE_DIR)) - return false ; - - hash = static_cast(mNodes[index])->dir_hash ; - - return true; -} -bool InternalFileHierarchyStorage::getIndexFromDirHash(const RsFileHash& hash,DirectoryStorage::EntryIndex& index) -{ - std::map::iterator it = mDirHashes.find(hash) ; - - if(it == mDirHashes.end()) - return false; - - index = it->second; - - // make sure the hash actually points to some existing file. If not, remove it. This is a lazy update of dir hashes: when we need them, we check them. - if(!checkIndex(index, FileStorageNode::TYPE_DIR) || static_cast(mNodes[index])->dir_hash != hash) - { - std::cerr << "(II) removing non existing hash from dir hash list: " << hash << std::endl; - - mDirHashes.erase(it) ; - return false ; - } - return true; -} -bool InternalFileHierarchyStorage::getIndexFromFileHash(const RsFileHash& hash,DirectoryStorage::EntryIndex& index) -{ - std::map::iterator it = mFileHashes.find(hash) ; - - if(it == mFileHashes.end()) - return false; - - index = it->second; - - // make sure the hash actually points to some existing file. If not, remove it. This is a lazy update of file hashes: when we need them, we check them. - if(!checkIndex(it->second, FileStorageNode::TYPE_FILE) || static_cast(mNodes[index])->file_hash != hash) - { - std::cerr << "(II) removing non existing hash from file hash list: " << hash << std::endl; - - mFileHashes.erase(it) ; - return false ; - } - - return true; -} - -bool InternalFileHierarchyStorage::getChildIndex(DirectoryStorage::EntryIndex e,int row,DirectoryStorage::EntryIndex& c) const -{ - if(!checkIndex(e,FileStorageNode::TYPE_DIR)) - return false ; - - const DirEntry& d = *static_cast(mNodes[e]) ; - - if((uint32_t)row < d.subdirs.size()) - { - c = d.subdirs[row] ; - return true ; - } - - if((uint32_t)row < d.subdirs.size() + d.subfiles.size()) - { - c = d.subfiles[row - (int)d.subdirs.size()] ; - return true ; - } - return false; -} - -int InternalFileHierarchyStorage::parentRow(DirectoryStorage::EntryIndex e) -{ - if(!checkIndex(e,FileStorageNode::TYPE_DIR | FileStorageNode::TYPE_FILE) || e==0) - return -1 ; - - return mNodes[mNodes[e]->parent_index]->row; -} - -// high level modification routines - -bool InternalFileHierarchyStorage::isIndexValid(DirectoryStorage::EntryIndex e) const -{ - return e < mNodes.size() && mNodes[e] != NULL ; -} - -bool InternalFileHierarchyStorage::updateSubDirectoryList(const DirectoryStorage::EntryIndex& indx, const std::set& subdirs, const RsFileHash& random_hash_seed) -{ - if(!checkIndex(indx,FileStorageNode::TYPE_DIR)) - return false; - - DirEntry& d(*static_cast(mNodes[indx])) ; - - std::set should_create(subdirs); - - for(uint32_t i=0;i(mNodes[d.subdirs[i]])->dir_name) == subdirs.end()) - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] Removing subdirectory " << static_cast(mNodes[d.subdirs[i]])->dir_name << " with index " << d.subdirs[i] << std::endl; -#endif - - if( !removeDirectory(d.subdirs[i])) - i++ ; - } - else - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] Keeping existing subdirectory " << static_cast(mNodes[d.subdirs[i]])->dir_name << " with index " << d.subdirs[i] << std::endl; -#endif - - should_create.erase(static_cast(mNodes[d.subdirs[i]])->dir_name) ; - ++i; - } - - for(std::set::const_iterator it(should_create.begin());it!=should_create.end();++it) - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] adding new subdirectory " << it->first << " at index " << mNodes.size() << std::endl; -#endif - - DirEntry *de = new DirEntry(*it) ; - - de->row = mNodes.size(); - de->parent_index = indx; - de->dir_modtime = 0;// forces parsing.it->second; - de->dir_parent_path = RsDirUtil::makePath(d.dir_parent_path, d.dir_name) ; - de->dir_hash = createDirHash(de->dir_name,d.dir_hash,random_hash_seed) ; - - mDirHashes[de->dir_hash] = mNodes.size() ; - - d.subdirs.push_back(mNodes.size()) ; - mNodes.push_back(de) ; - } - - return true; -} - -RsFileHash InternalFileHierarchyStorage::createDirHash(const std::string& dir_name, const RsFileHash& dir_parent_hash, const RsFileHash& random_hash_salt) -{ - // What we need here: a unique identifier - // - that cannot be bruteforced to find the real directory name and path - // - that is used by friends to refer to a specific directory. - - // Option 1: compute H(some_secret_salt + dir_name + dir_parent_path) - // and keep the same salt so that we can re-create the hash - // - // Option 2: compute H(virtual_path). That only works at the level of LocalDirectoryStorage - // - // Option 3: just compute something random, but then we need to store it so as to not - // confuse friends when restarting. - - RsTemporaryMemory mem(dir_name.size() + 2*RsFileHash::SIZE_IN_BYTES) ; - - memcpy( mem, random_hash_salt.toByteArray(),RsFileHash::SIZE_IN_BYTES) ; - memcpy(&mem[ RsFileHash::SIZE_IN_BYTES], dir_parent_hash.toByteArray(),RsFileHash::SIZE_IN_BYTES) ; - memcpy(&mem[2*RsFileHash::SIZE_IN_BYTES],dir_name.c_str(), dir_name.size()) ; - - RsFileHash res = RsDirUtil::sha1sum( mem,mem.size() ) ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "Creating new dir hash for dir " << dir_name << ", parent dir hash=" << dir_parent_hash << " seed=[hidden]" << " result is " << res << std::endl; -#endif - - return res ; -} - -bool InternalFileHierarchyStorage::removeDirectory(DirectoryStorage::EntryIndex indx) // no reference here! Very important. Otherwise, the messign we do inside can change the value of indx!! -{ - // check that it's a directory - - if(!checkIndex(indx,FileStorageNode::TYPE_DIR)) - return false; - - if(indx == 0) - return nodeAccessError("checkIndex(): Cannot remove top level directory") ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "(--) Removing directory " << indx << std::endl; - print(); -#endif - // remove from parent - - DirEntry& d(*static_cast(mNodes[indx])) ; - DirEntry& parent_dir(*static_cast(mNodes[d.parent_index])); - - for(uint32_t i=0;i= mNodes.size() || mNodes[indx] == NULL) - return nodeAccessError("checkIndex(): Node does not exist") ; - - if(! (mNodes[indx]->type() & type)) - return nodeAccessError("checkIndex(): Node is of wrong type") ; - - return true; -} - -bool InternalFileHierarchyStorage::updateSubFilesList(const DirectoryStorage::EntryIndex& indx,const std::map& subfiles,std::map& new_files) -{ - if(!checkIndex(indx,FileStorageNode::TYPE_DIR)) - return false; - - DirEntry& d(*static_cast(mNodes[indx])) ; - new_files = subfiles ; - - // remove from new_files the ones that already exist and have a modf time that is not older. - - for(uint32_t i=0;i(mNodes[d.subfiles[i]])) ; - std::map::const_iterator it = subfiles.find(f.file_name) ; - - if(it == subfiles.end()) // file does not exist anymore => delete - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] removing non existing file " << f.file_name << " at index " << d.subfiles[i] << std::endl; -#endif - - deleteFileNode(d.subfiles[i]) ; - - d.subfiles[i] = d.subfiles[d.subfiles.size()-1] ; - d.subfiles.pop_back(); - continue; - } - - if(it->second.modtime != f.file_modtime || it->second.size != f.file_size) // file is newer and/or has different size - { - f.file_hash.clear(); // hash needs recomputing - f.file_modtime = it->second.modtime; - f.file_size = it->second.size; - - mTotalSize -= f.file_size ; - mTotalSize += it->second.size ; - } - new_files.erase(f.file_name) ; - - ++i; - } - - for(std::map::const_iterator it(new_files.begin());it!=new_files.end();++it) - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] adding new file " << it->first << " at index " << mNodes.size() << std::endl; -#endif - - d.subfiles.push_back(mNodes.size()) ; - mNodes.push_back(new FileEntry(it->first,it->second.size,it->second.modtime)); - mNodes.back()->row = mNodes.size()-1; - mNodes.back()->parent_index = indx; - - mTotalSize += it->second.size; - mTotalFiles += 1; - } - return true; -} -bool InternalFileHierarchyStorage::updateHash(const DirectoryStorage::EntryIndex& file_index,const RsFileHash& hash) -{ - if(!checkIndex(file_index,FileStorageNode::TYPE_FILE)) - { - std::cerr << "[directory storage] (EE) cannot update file at index " << file_index << ". Not a valid index, or not a file." << std::endl; - return false; - } -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] updating hash at index " << file_index << ", hash=" << hash << std::endl; -#endif - - RsFileHash& old_hash (static_cast(mNodes[file_index])->file_hash) ; - mFileHashes[hash] = file_index ; - - old_hash = hash ; - - return true; -} -bool InternalFileHierarchyStorage::updateFile(const DirectoryStorage::EntryIndex& file_index,const RsFileHash& hash, const std::string& fname,uint64_t size, const rstime_t modf_time) -{ - if(!checkIndex(file_index,FileStorageNode::TYPE_FILE)) - { - std::cerr << "[directory storage] (EE) cannot update file at index " << file_index << ". Not a valid index, or not a file." << std::endl; - return false; - } - - FileEntry& fe(*static_cast(mNodes[file_index])) ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] updating file entry at index " << file_index << ", name=" << fe.file_name << " size=" << fe.file_size << ", hash=" << fe.file_hash << std::endl; -#endif - if(mTotalSize >= fe.file_size) - mTotalSize -= fe.file_size; - - mTotalSize += size ; - - fe.file_hash = hash; - fe.file_size = size; - fe.file_modtime = modf_time; - fe.file_name = fname; - - if(!hash.isNull()) - mFileHashes[hash] = file_index ; - - return true; -} - -void InternalFileHierarchyStorage::deleteFileNode(uint32_t index) -{ - if(mNodes[index] != NULL) - { - FileEntry& fe(*static_cast(mNodes[index])) ; - -#ifdef RS_DEEP_FILES_INDEX - DeepFilesIndex tfi(DeepFilesIndex::dbDefaultPath()); - tfi.removeFileFromIndex(fe.file_hash); -#endif - - if(mTotalSize >= fe.file_size) - mTotalSize -= fe.file_size ; - - if(mTotalFiles > 0) - mTotalFiles -= 1; - - delete mNodes[index] ; - mFreeNodes.push_back(index) ; - mNodes[index] = NULL ; - } -} -void InternalFileHierarchyStorage::deleteNode(uint32_t index) -{ - if(mNodes[index] != NULL) - { - delete mNodes[index] ; - mFreeNodes.push_back(index) ; - mNodes[index] = NULL ; - } -} - -DirectoryStorage::EntryIndex InternalFileHierarchyStorage::allocateNewIndex() -{ - while(!mFreeNodes.empty()) - { - uint32_t index = mFreeNodes.front(); - mFreeNodes.pop_front(); - - if(mNodes[index] == NULL) - return DirectoryStorage::EntryIndex(index) ; - } - - mNodes.push_back(NULL) ; - return mNodes.size()-1 ; -} - -bool InternalFileHierarchyStorage::updateDirEntry(const DirectoryStorage::EntryIndex& indx,const std::string& dir_name,rstime_t most_recent_time,rstime_t dir_modtime,const std::vector& subdirs_hash,const std::vector& subfiles_array) -{ - if(!checkIndex(indx,FileStorageNode::TYPE_DIR)) - { - std::cerr << "[directory storage] (EE) cannot update dir at index " << indx << ". Not a valid index, or not an existing dir." << std::endl; - return false; - } - DirEntry& d(*static_cast(mNodes[indx])) ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "Updating dir entry: name=\"" << dir_name << "\", most_recent_time=" << most_recent_time << ", modtime=" << dir_modtime << std::endl; -#endif - - d.dir_most_recent_time = most_recent_time; - d.dir_modtime = dir_modtime; - d.dir_update_time = time(NULL); - d.dir_name = dir_name; - - std::map existing_subdirs ; - - for(uint32_t i=0;i(mNodes[d.subdirs[i]])->dir_hash] = d.subdirs[i] ; - - d.subdirs.clear(); - - // check that all subdirs already exist. If not, create. - for(uint32_t i=0;i::iterator it = existing_subdirs.find(subdirs_hash[i]) ; - DirectoryStorage::EntryIndex dir_index = 0; - - if(it != existing_subdirs.end() && mNodes[it->second] != NULL && mNodes[it->second]->type() == FileStorageNode::TYPE_DIR) - { - dir_index = it->second ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " already exists, at index " << dir_index << std::endl; -#endif - - existing_subdirs.erase(it) ; - } - else - { - dir_index = allocateNewIndex() ; - - DirEntry *de = new DirEntry("") ; - - mNodes[dir_index] = de ; - - de->dir_parent_path = RsDirUtil::makePath(d.dir_parent_path, dir_name) ; - de->dir_hash = subdirs_hash[i]; - - mDirHashes[subdirs_hash[i]] = dir_index ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " created, at new index " << dir_index << std::endl; -#endif - } - - d.subdirs.push_back(dir_index) ; - mDirHashes[subdirs_hash[i]] = dir_index ; - } - // remove subdirs that do not exist anymore - - for(std::map::const_iterator it = existing_subdirs.begin();it!=existing_subdirs.end();++it) - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " removing existing subfile that is not in the dirctory anymore: name=" << it->first << " index=" << it->second << std::endl; -#endif - - if(!checkIndex(it->second,FileStorageNode::TYPE_DIR)) - { - std::cerr << "(EE) Cannot delete node of index " << it->second << " because it is not a file. Inconsistency error!" << std::endl; - continue ; - } - recursRemoveDirectory(it->second) ; - } - - // now update subfiles. This is more stricky because we need to not suppress hash duplicates - - std::map existing_subfiles ; - - for(uint32_t i=0;i(mNodes[d.subfiles[i]])->file_name] = d.subfiles[i] ; - - d.subfiles.clear(); - - for(uint32_t i=0;i::iterator it = existing_subfiles.find(subfiles_array[i].file_name) ; - const FileEntry& f(subfiles_array[i]) ; - DirectoryStorage::EntryIndex file_index ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " subfile name = " << subfiles_array[i].file_name << ": " ; -#endif - - if(it != existing_subfiles.end() && mNodes[it->second] != NULL && mNodes[it->second]->type() == FileStorageNode::TYPE_FILE) - { - file_index = it->second ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " already exists, at index " << file_index << std::endl; -#endif - - if(!updateFile(file_index,f.file_hash,f.file_name,f.file_size,f.file_modtime)) - std::cerr << "(EE) Cannot update file with index " << it->second <<" and hash " << f.file_hash << ". This is very weird. Entry should have just been created and therefore should exist. Skipping." << std::endl; - - existing_subfiles.erase(it) ; - } - else - { - file_index = allocateNewIndex() ; - - mNodes[file_index] = new FileEntry(f.file_name,f.file_size,f.file_modtime,f.file_hash) ; - mFileHashes[f.file_hash] = file_index ; - mTotalSize += f.file_size ; - mTotalFiles++; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " created, at new index " << file_index << std::endl; -#endif - } - - d.subfiles.push_back(file_index) ; - } - // remove subfiles that do not exist anymore - - for(std::map::const_iterator it = existing_subfiles.begin();it!=existing_subfiles.end();++it) - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " removing existing subfile that is not in the dirctory anymore: name=" << it->first << " index=" << it->second << std::endl; -#endif - - if(!checkIndex(it->second,FileStorageNode::TYPE_FILE)) - { - std::cerr << "(EE) Cannot delete node of index " << it->second << " because it is not a file. Inconsistency error!" << std::endl; - continue ; - } - deleteFileNode(it->second) ; - } - - // now update row and parent index for all subnodes - - uint32_t n=0; - for(uint32_t i=0;i(mNodes[d.subdirs[i]])->dir_update_time = 0 ; // force the update of the subdir. - - mNodes[d.subdirs[i]]->parent_index = indx ; - mNodes[d.subdirs[i]]->row = n++ ; - } - for(uint32_t i=0;iparent_index = indx ; - mNodes[d.subfiles[i]]->row = n++ ; - } - - - return true; -} - -void InternalFileHierarchyStorage::getStatistics(SharedDirStats& stats) const -{ - stats.total_number_of_files = mTotalFiles ; - stats.total_shared_size = mTotalSize ; -} - -bool InternalFileHierarchyStorage::getTS(const DirectoryStorage::EntryIndex& index,rstime_t& TS,rstime_t DirEntry::* m) const -{ - if(!checkIndex(index,FileStorageNode::TYPE_DIR)) - { - std::cerr << "[directory storage] (EE) cannot get TS for index " << index << ". Not a valid index or not a directory." << std::endl; - return false; - } - - DirEntry& d(*static_cast(mNodes[index])) ; - - TS = d.*m ; - - return true; -} - -bool InternalFileHierarchyStorage::setTS(const DirectoryStorage::EntryIndex& index,rstime_t& TS,rstime_t DirEntry::* m) -{ - if(!checkIndex(index,FileStorageNode::TYPE_DIR)) - { - std::cerr << "[directory storage] (EE) cannot get TS for index " << index << ". Not a valid index or not a directory." << std::endl; - return false; - } - - DirEntry& d(*static_cast(mNodes[index])) ; - - d.*m = TS; - - return true; -} - -// Do a complete recursive sweep of directory hierarchy and update cumulative size of directories - -uint64_t InternalFileHierarchyStorage::recursUpdateCumulatedSize(const DirectoryStorage::EntryIndex& dir_index) -{ - DirEntry& d(*static_cast(mNodes[dir_index])) ; - - uint64_t local_cumulative_size = 0; - - for(uint32_t i=0;i(mNodes[d.subfiles[i]])->file_size; - - for(uint32_t i=0;i(mNodes[dir_index])) ; - - rstime_t largest_modf_time = d.dir_modtime ; - unfinished_files_present = false ; - - for(uint32_t i=0;i(mNodes[d.subfiles[i]]) ; - - if(!f->file_hash.isNull()) - largest_modf_time = std::max(largest_modf_time, f->file_modtime) ; // only account for hashed files, since we never send unhashed files to friends. - else - unfinished_files_present = true ; - } - - for(uint32_t i=0;i 0) - largest_modf_time-- ; - - d.dir_most_recent_time = largest_modf_time ; - - return largest_modf_time ; -} - -// Low level stuff. Should normally not be used externally. - -const InternalFileHierarchyStorage::FileStorageNode *InternalFileHierarchyStorage::getNode(DirectoryStorage::EntryIndex indx) const -{ - if(checkIndex(indx,FileStorageNode::TYPE_FILE | FileStorageNode::TYPE_DIR)) - return mNodes[indx] ; - else - return NULL ; -} - -const InternalFileHierarchyStorage::DirEntry *InternalFileHierarchyStorage::getDirEntry(DirectoryStorage::EntryIndex indx) const -{ - if(!checkIndex(indx,FileStorageNode::TYPE_DIR)) - return NULL ; - - return static_cast(mNodes[indx]) ; -} -const InternalFileHierarchyStorage::FileEntry *InternalFileHierarchyStorage::getFileEntry(DirectoryStorage::EntryIndex indx) const -{ - if(!checkIndex(indx,FileStorageNode::TYPE_FILE)) - return NULL ; - - return static_cast(mNodes[indx]) ; -} -uint32_t InternalFileHierarchyStorage::getType(DirectoryStorage::EntryIndex indx) const -{ - if(checkIndex(indx,FileStorageNode::TYPE_FILE | FileStorageNode::TYPE_DIR)) - return mNodes[indx]->type() ; - else - return FileStorageNode::TYPE_UNKNOWN; -} - -DirectoryStorage::EntryIndex InternalFileHierarchyStorage::getSubFileIndex(DirectoryStorage::EntryIndex parent_index,uint32_t file_tab_index) -{ - if(!checkIndex(parent_index,FileStorageNode::TYPE_DIR)) - return DirectoryStorage::NO_INDEX; - - if(static_cast(mNodes[parent_index])->subfiles.size() <= file_tab_index) - return DirectoryStorage::NO_INDEX; - - return static_cast(mNodes[parent_index])->subfiles[file_tab_index]; -} -DirectoryStorage::EntryIndex InternalFileHierarchyStorage::getSubDirIndex(DirectoryStorage::EntryIndex parent_index,uint32_t dir_tab_index) -{ - if(!checkIndex(parent_index,FileStorageNode::TYPE_DIR)) - return DirectoryStorage::NO_INDEX; - - if(static_cast(mNodes[parent_index])->subdirs.size() <= dir_tab_index) - return DirectoryStorage::NO_INDEX; - - return static_cast(mNodes[parent_index])->subdirs[dir_tab_index]; -} - -bool InternalFileHierarchyStorage::searchHash(const RsFileHash& hash,DirectoryStorage::EntryIndex& result) -{ - return getIndexFromFileHash(hash,result); -} - -class DirectoryStorageExprFileEntry: public RsRegularExpression::ExpFileEntry -{ -public: - DirectoryStorageExprFileEntry(const InternalFileHierarchyStorage::FileEntry& fe,const InternalFileHierarchyStorage::DirEntry& parent) : mFe(fe),mDe(parent) {} - - inline virtual const std::string& file_name() const { return mFe.file_name ; } - inline virtual uint64_t file_size() const { return mFe.file_size ; } - inline virtual const RsFileHash& file_hash() const { return mFe.file_hash ; } - inline virtual rstime_t file_modtime() const { return mFe.file_modtime ; } - inline virtual std::string file_parent_path()const { return RsDirUtil::makePath(mDe.dir_parent_path, mDe.dir_name) ; } - inline virtual uint32_t file_popularity() const { NOT_IMPLEMENTED() ; return 0; } - -private: - const InternalFileHierarchyStorage::FileEntry& mFe ; - const InternalFileHierarchyStorage::DirEntry& mDe ; -}; - -int InternalFileHierarchyStorage::searchBoolExp(RsRegularExpression::Expression * exp, std::list &results) const -{ - for(std::map::const_iterator it(mFileHashes.begin());it!=mFileHashes.end();++it) - if(mNodes[it->second] != NULL && exp->eval( - DirectoryStorageExprFileEntry(*static_cast(mNodes[it->second]), - *static_cast(mNodes[mNodes[it->second]->parent_index]) - ))) - results.push_back(it->second); - - return 0; -} - -int InternalFileHierarchyStorage::searchTerms( - const std::list& terms, - std::list& results ) const -{ - // most entries are likely to be files, so we could do a linear search over the entries tab. - // instead we go through the table of hashes. - - for(std::map::const_iterator it(mFileHashes.begin());it!=mFileHashes.end();++it) - if(mNodes[it->second] != NULL) - { - const std::string &str1 = static_cast(mNodes[it->second])->file_name; - - for(std::list::const_iterator iter(terms.begin()); iter != terms.end(); ++iter) - { - /* always ignore case */ - const std::string &str2 = (*iter); - - if(str1.end() != std::search( str1.begin(), str1.end(), str2.begin(), str2.end(), RsRegularExpression::CompareCharIC() )) - { - results.push_back(it->second); - break; - } - } - } - return 0 ; -} - -bool InternalFileHierarchyStorage::check(std::string& error_string) // checks consistency of storage. -{ - // recurs go through all entries, check that all - - error_string = ""; - bool bDirOut = false; - bool bDirDouble = false; - bool bFileOut = false; - bool bFileDouble = false; - bool bOrphean = false; - - std::vector hits(mNodes.size(),0) ; // count hits of children. Should be 1 for all in the end. Otherwise there's an error. - hits[0] = 1 ; // because 0 is never the child of anyone - - mFreeNodes.clear(); - - for(uint32_t i=0;itype() == FileStorageNode::TYPE_DIR) - { - // stamp the kids - DirEntry& de = *static_cast(mNodes[i]) ; - - for(uint32_t j=0;j= mNodes.size()) - { - if(!bDirOut){ error_string += " - Node child dir out of tab!"; bDirOut = true;} - de.subdirs[j] = de.subdirs.back() ; - de.subdirs.pop_back(); - } - else if(hits[de.subdirs[j]] != 0) - { - if(!bDirDouble){ error_string += " - Double hit on a single node dir."; bDirDouble = true;} - de.subdirs[j] = de.subdirs.back() ; - de.subdirs.pop_back(); - } - else - { - hits[de.subdirs[j]] = 1; - ++j ; - } - } - for(uint32_t j=0;j= mNodes.size()) - { - if(!bFileOut){ error_string += " - Node child file out of tab!"; bFileOut = true;} - de.subfiles[j] = de.subfiles.back() ; - de.subfiles.pop_back(); - } - else if(hits[de.subfiles[j]] != 0) - { - if(!bFileDouble){ error_string += " - Double hit on a single node file."; bFileDouble = true;} - de.subfiles[j] = de.subfiles.back() ; - de.subfiles.pop_back(); - } - else - { - hits[de.subfiles[j]] = 1; - ++j ; - } - } - } - else if( mNodes[i] == NULL ) - mFreeNodes.push_back(i) ; - - for(uint32_t i=0;itype() == FileStorageNode::TYPE_DIR) - { - std::cerr << " Node " << i << ": type=" << mNodes[i]->type() << std::endl; - ++ndirs; - } - else if(mNodes[i]->type() == FileStorageNode::TYPE_FILE) - { - std::cerr << " Node " << i << ": type=" << mNodes[i]->type() << std::endl; - ++nfiles; - } - else - { - ++nunknown; - std::cerr << "(EE) Error: unknown type node found!" << std::endl; - } - - std::cerr << "Total nodes: " << mNodes.size() << " (" << nfiles << " files, " << ndirs << " dirs, " << nempty << " empty slots"; - if (nunknown > 0) std::cerr << ", " << nunknown << " unknown"; - std::cerr << ")" << std::endl; - - - recursPrint(0,DirectoryStorage::EntryIndex(0)); - - std::cerr << "Known dir hashes: " << std::endl; - for(std::map::const_iterator it(mDirHashes.begin());it!=mDirHashes.end();++it) - std::cerr << " " << it->first << " at index " << it->second << std::endl; - - std::cerr << "Known file hashes: " << std::endl; - for(std::map::const_iterator it(mFileHashes.begin());it!=mFileHashes.end();++it) - std::cerr << " " << it->first << " at index " << it->second << std::endl; -} -void InternalFileHierarchyStorage::recursPrint(int depth,DirectoryStorage::EntryIndex node) const -{ - std::string indent(2*depth,' '); - - if(mNodes[node] == NULL) - { - std::cerr << "EMPTY NODE !!" << std::endl; - return ; - } - DirEntry& d(*static_cast(mNodes[node])); - - std::cerr << indent << "dir hash=" << d.dir_hash << ". name:" << d.dir_name << ", parent_path:" << d.dir_parent_path << ", modf time: " << d.dir_modtime << ", recurs_last_modf_time: " << d.dir_most_recent_time << ", parent: " << d.parent_index << ", row: " << d.row << ", subdirs: " ; - - for(uint32_t i=0;i(mNodes[d.subfiles[i]])); - std::cerr << indent << " hash:" << f.file_hash << " ts:" << (uint64_t)f.file_modtime << " " << f.file_size << " " << f.file_name << ", parent: " << f.parent_index << ", row: " << f.row << std::endl; - } -} - -bool InternalFileHierarchyStorage::nodeAccessError(const std::string& s) -{ - std::cerr << "(EE) InternalDirectoryStructure: ERROR: " << s << std::endl; - return false ; -} - -// Removes the given subdirectory from the parent node and all its pendign subdirs and files. - -bool InternalFileHierarchyStorage::recursRemoveDirectory(DirectoryStorage::EntryIndex dir) -{ - DirEntry& d(*static_cast(mNodes[dir])) ; - - RsFileHash hash = d.dir_hash ; - - for(uint32_t i=0;itype() == FileStorageNode::TYPE_FILE) - { - const FileEntry& fe(*static_cast(mNodes[i])) ; - - uint32_t file_section_offset = 0 ; - - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_PARENT_INDEX ,(uint32_t)fe.parent_index)) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_ROW ,(uint32_t)fe.row )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_ENTRY_INDEX ,(uint32_t)i )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,fe.file_name )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,fe.file_size )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,fe.file_hash )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_MODIF_TS ,(uint32_t)fe.file_modtime)) throw std::runtime_error("Write error") ; - - if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_FILE_ENTRY,tmp_section_data,file_section_offset)) throw std::runtime_error("Write error") ; - } - else if(mNodes[i] != NULL && mNodes[i]->type() == FileStorageNode::TYPE_DIR) - { - const DirEntry& de(*static_cast(mNodes[i])) ; - - uint32_t dir_section_offset = 0 ; - - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_PARENT_INDEX ,(uint32_t)de.parent_index )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_ROW ,(uint32_t)de.row )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_ENTRY_INDEX ,(uint32_t)i )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,de.dir_name )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_DIR_HASH ,de.dir_hash )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,de.dir_parent_path )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_MODIF_TS ,(uint32_t)de.dir_modtime )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_UPDATE_TS ,(uint32_t)de.dir_update_time )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_RECURS_MODIF_TS,(uint32_t)de.dir_most_recent_time )) throw std::runtime_error("Write error") ; - - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)de.subdirs.size())) throw std::runtime_error("Write error") ; - - for(uint32_t j=0;j= mNodes.size()) - mNodes.resize(node_index+1,NULL) ; - - FileEntry *fe = new FileEntry(file_name,file_size,file_modtime,file_hash); - - fe->parent_index = parent_index ; - fe->row = row ; - - mNodes[node_index] = fe ; - mFileHashes[fe->file_hash] = node_index ; - - mTotalFiles++ ; - mTotalSize += file_size ; - } - else if(FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIR_ENTRY,node_section_data,node_section_size)) - { - uint32_t node_index ; - std::string dir_name ; - std::string dir_parent_path ; - RsFileHash dir_hash ; - uint32_t dir_modtime ; - uint32_t dir_update_time ; - uint32_t dir_most_recent_time ; - uint32_t row ; - uint32_t parent_index ; - - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_PARENT_INDEX ,parent_index )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_PARENT_INDEX ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_ROW ,row )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_ROW ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_ENTRY_INDEX ,node_index )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_ENTRY_INDEX ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,dir_name )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_NAME ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_DIR_HASH ,dir_hash )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_DIR_HASH ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,dir_parent_path )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_MODIF_TS ,dir_modtime )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_MODIF_TS ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_UPDATE_TS ,dir_update_time )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_UPDATE_TS ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RECURS_MODIF_TS,dir_most_recent_time )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RECURS_MODIF_TS) ; - - if(node_index >= mNodes.size()) - mNodes.resize(node_index+1,NULL) ; - - DirEntry *de = new DirEntry(dir_name) ; - de->dir_name = dir_name ; - de->dir_parent_path = dir_parent_path ; - de->dir_hash = dir_hash ; - de->dir_modtime = dir_modtime ; - de->dir_update_time = dir_update_time ; - de->dir_most_recent_time = dir_most_recent_time ; - - de->parent_index = parent_index ; - de->row = row ; - - uint32_t n_subdirs = 0 ; - uint32_t n_subfiles = 0 ; - - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subdirs)) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ; - - for(uint32_t j=0;jsubdirs.push_back(di) ; - } - - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subfiles)) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ; - - for(uint32_t j=0;jsubfiles.push_back(fi) ; - } - mNodes[node_index] = de ; - mDirHashes[de->dir_hash] = node_index ; - } - else - throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_FILE_ENTRY) ; - - free(node_section_data) ; - } - free(buffer) ; - - std::string err_str ; - - if(!check(err_str)) - std::cerr << "(EE) Error while loading file hierarchy " << fname << std::endl; - - recursUpdateCumulatedSize(mRoot); - - return true ; - } - catch(read_error& e) - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "Error while reading: " << e.what() << std::endl; -#endif - - if(buffer != NULL) - free(buffer) ; - return false; - } -} - diff --git a/libretroshare/src/file_sharing/dir_hierarchy.h b/libretroshare/src/file_sharing/dir_hierarchy.h deleted file mode 100644 index c6a28650b..000000000 --- a/libretroshare/src/file_sharing/dir_hierarchy.h +++ /dev/null @@ -1,199 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: dir_hierarchy.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "directory_storage.h" - -class InternalFileHierarchyStorage -{ -public: - class FileStorageNode - { - public: - static const uint32_t TYPE_UNKNOWN = 0x0000 ; - static const uint32_t TYPE_FILE = 0x0001 ; - static const uint32_t TYPE_DIR = 0x0002 ; - - virtual ~FileStorageNode() {} - virtual uint32_t type() const =0; - - DirectoryStorage::EntryIndex parent_index; - uint32_t row ; - }; - class FileEntry: public FileStorageNode - { - public: - FileEntry() : file_size(0), file_modtime(0) {} - FileEntry(const std::string& name,uint64_t size,rstime_t modtime) : file_name(name),file_size(size),file_modtime(modtime) {} - FileEntry(const std::string& name,uint64_t size,rstime_t modtime,const RsFileHash& hash) : file_name(name),file_size(size),file_modtime(modtime),file_hash(hash) {} - - virtual uint32_t type() const { return FileStorageNode::TYPE_FILE ; } - virtual ~FileEntry() {} - - // local stuff - std::string file_name ; - uint64_t file_size ; - rstime_t file_modtime; - RsFileHash file_hash ; - }; - - class DirEntry: public FileStorageNode - { - public: - explicit DirEntry(const std::string& name) : dir_name(name), dir_cumulated_size(0), dir_modtime(0),dir_most_recent_time(0),dir_update_time(0) {} - virtual ~DirEntry() {} - - virtual uint32_t type() const { return FileStorageNode::TYPE_DIR ; } - - // local stuff - std::string dir_name ; - std::string dir_parent_path ; - RsFileHash dir_hash ; - uint64_t dir_cumulated_size; - - std::vector subdirs ; - std::vector subfiles ; - - rstime_t dir_modtime; - rstime_t dir_most_recent_time;// recursive most recent modification time, including files and subdirs in the entire hierarchy below. - rstime_t dir_update_time; // last time the information was updated for that directory. Includes subdirs indexes and subfile info. - }; - - // class stuff - InternalFileHierarchyStorage() ; - - bool load(const std::string& fname) ; - bool save(const std::string& fname) ; - - int parentRow(DirectoryStorage::EntryIndex e); - bool isIndexValid(DirectoryStorage::EntryIndex e) const; - bool getChildIndex(DirectoryStorage::EntryIndex e,int row,DirectoryStorage::EntryIndex& c) const; - bool updateSubDirectoryList(const DirectoryStorage::EntryIndex& indx, const std::set& subdirs, const RsFileHash &random_hash_seed); - bool removeDirectory(DirectoryStorage::EntryIndex indx) ; - bool checkIndex(DirectoryStorage::EntryIndex indx,uint8_t type) const; - bool updateSubFilesList(const DirectoryStorage::EntryIndex& indx,const std::map& subfiles,std::map& new_files); - bool updateHash(const DirectoryStorage::EntryIndex& file_index,const RsFileHash& hash); - bool updateFile(const DirectoryStorage::EntryIndex& file_index,const RsFileHash& hash, const std::string& fname,uint64_t size, const rstime_t modf_time); - bool updateDirEntry(const DirectoryStorage::EntryIndex& indx, const std::string& dir_name, rstime_t most_recent_time, rstime_t dir_modtime, const std::vector &subdirs_hash, const std::vector &subfiles_array); - - // TS get/set functions. Take one of the class members as argument. - - bool getTS(const DirectoryStorage::EntryIndex& index,rstime_t& TS,rstime_t DirEntry::* ) const; - bool setTS(const DirectoryStorage::EntryIndex& index,rstime_t& TS,rstime_t DirEntry::* ) ; - - // Do a complete recursive sweep over sub-directories and files, and update the lst modf TS. This could be also performed by a cleanup method. - // Also keeps the high level statistics up to date. - - rstime_t recursUpdateLastModfTime(const DirectoryStorage::EntryIndex& dir_index, bool &unfinished_files_present); - - // Do a complete recursive sweep over sub-directories and files, and update the cumulative size. - - uint64_t recursUpdateCumulatedSize(const DirectoryStorage::EntryIndex& dir_index); - - // hash stuff - - bool getDirHashFromIndex(const DirectoryStorage::EntryIndex& index,RsFileHash& hash) const ; - bool getIndexFromDirHash(const RsFileHash& hash,DirectoryStorage::EntryIndex& index) ; - bool getIndexFromFileHash(const RsFileHash& hash,DirectoryStorage::EntryIndex& index) ; - - // file/dir access and modification - bool findSubDirectory(DirectoryStorage::EntryIndex e,const std::string& s) const ; // returns true when s is the name of a sub-directory in the given entry e - - uint32_t mRoot ; - std::list mFreeNodes ; // keeps a list of free nodes in order to make insert effcieint - std::vector mNodes;// uses pointers to keep information about valid/invalid objects. - - void compress() ; // use empty space in the vector, mostly due to deleted entries. This is a complicated operation, mostly due to - // all the indirections used. Nodes need to be moved, renamed, etc. The operation discards all file entries that - // are not referenced. - - friend class DirectoryStorage ; // only class that can use this. - friend class LocalDirectoryStorage ; // only class that can use this. - - // Low level stuff. Should normally not be used externally. - - const FileStorageNode *getNode(DirectoryStorage::EntryIndex indx) const; - const DirEntry *getDirEntry(DirectoryStorage::EntryIndex indx) const; - const FileEntry *getFileEntry(DirectoryStorage::EntryIndex indx) const; - uint32_t getType(DirectoryStorage::EntryIndex indx) const; - DirectoryStorage::EntryIndex getSubFileIndex(DirectoryStorage::EntryIndex parent_index,uint32_t file_tab_index); - DirectoryStorage::EntryIndex getSubDirIndex(DirectoryStorage::EntryIndex parent_index,uint32_t dir_tab_index); - - // search. SearchHash is logarithmic. The other two are linear. - - bool searchHash(const RsFileHash& hash, DirectoryStorage::EntryIndex &result); - int searchBoolExp(RsRegularExpression::Expression * exp, std::list &results) const ; - int searchTerms(const std::list& terms, std::list &results) const ; // does a logical OR between items of the list of terms - - bool check(std::string& error_string) ;// checks consistency of storage. - - void print() const; - - // gets statistics about share files - - void getStatistics(SharedDirStats& stats) const ; - -private: - void recursPrint(int depth,DirectoryStorage::EntryIndex node) const; - static bool nodeAccessError(const std::string& s); - static RsFileHash createDirHash(const std::string& dir_name, const RsFileHash &dir_parent_hash, const RsFileHash &random_hash_salt) ; - - // Allocates a new entry in mNodes, possible re-using an empty slot and returns its index. - - DirectoryStorage::EntryIndex allocateNewIndex(); - - // Deletes an existing entry in mNodes, and keeps record of the indices that get freed. - - void deleteNode(DirectoryStorage::EntryIndex); - void deleteFileNode(DirectoryStorage::EntryIndex); - - // Removes the given subdirectory from the parent node and all its pendign subdirs. Files are kept, and will go during the cleaning - // phase. That allows to keep file information when moving them around. - - bool recursRemoveDirectory(DirectoryStorage::EntryIndex dir); - - // Map of the hash of all files. The file hashes are the sha1sum of the file data. - // is used for fast search access for FT. - // Note: We should try something faster than std::map. hash_map?? - // Unlike directories, multiple files may have the same hash. So this cannot be used for anything else than FT. - - std::map mFileHashes ; - - // The directory hashes are the sha1sum of the - // full public path to the directory. - // The later is used by synchronisation items in order - // to avoid sending explicit EntryIndex values. - // This is kept separate from mFileHashes because the two are used - // in very different ways. - // - std::map mDirHashes ; - - // high level statistics on the full hierarchy. Should be kept up to date. - - uint32_t mTotalFiles ; - uint64_t mTotalSize ; -}; - diff --git a/libretroshare/src/file_sharing/directory_list.h b/libretroshare/src/file_sharing/directory_list.h deleted file mode 100644 index c643b6153..000000000 --- a/libretroshare/src/file_sharing/directory_list.h +++ /dev/null @@ -1,13 +0,0 @@ -// This class keeps a shared directory. It's quite the equivalent of the old "FileIndex" class -// The main difference is that it is -// - extensible -// - fast to search (at least for hashes). Should provide possibly multiple search handles for -// the same file, e.g. if connexion is encrypted. -// - abstracts the browsing in a same manner. -// -class SharedDirectoryList -{ - public: - - DirEntry mRoot ; -}; diff --git a/libretroshare/src/file_sharing/directory_storage.cc b/libretroshare/src/file_sharing/directory_storage.cc deleted file mode 100644 index c4a46f4fb..000000000 --- a/libretroshare/src/file_sharing/directory_storage.cc +++ /dev/null @@ -1,961 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: directory_storage.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ -#include - -#include "util/rstime.h" -#include "serialiser/rstlvbinary.h" -#include "retroshare/rspeers.h" -#include "util/rsdir.h" -#include "util/rsstring.h" -#include "file_sharing_defaults.h" -#include "directory_storage.h" -#include "dir_hierarchy.h" -#include "filelist_io.h" - -#ifdef RS_DEEP_FILES_INDEX -# include "deep_search/filesindex.hpp" -#endif // def RS_DEEP_FILES_INDEX - -//#define DEBUG_REMOTE_DIRECTORY_STORAGE 1 - -/******************************************************************************************************************/ -/* Iterators */ -/******************************************************************************************************************/ - -DirectoryStorage::DirIterator::DirIterator(DirectoryStorage *s,DirectoryStorage::EntryIndex i) -{ - mStorage = s->mFileHierarchy ; - mParentIndex = i; - mDirTabIndex = 0; -} - -DirectoryStorage::FileIterator::FileIterator(DirectoryStorage *s,DirectoryStorage::EntryIndex i) -{ - mStorage = s->mFileHierarchy ; - mParentIndex = i; - mFileTabIndex = 0; -} - -DirectoryStorage::DirIterator& DirectoryStorage::DirIterator::operator++() -{ - ++mDirTabIndex ; - - return *this; -} -DirectoryStorage::FileIterator& DirectoryStorage::FileIterator::operator++() -{ - ++mFileTabIndex ; - - return *this; -} -DirectoryStorage::EntryIndex DirectoryStorage::FileIterator::operator*() const { return mStorage->getSubFileIndex(mParentIndex,mFileTabIndex) ; } -DirectoryStorage::EntryIndex DirectoryStorage::DirIterator ::operator*() const { return mStorage->getSubDirIndex(mParentIndex,mDirTabIndex) ; } - -DirectoryStorage::FileIterator::operator bool() const { return **this != DirectoryStorage::NO_INDEX; } -DirectoryStorage::DirIterator ::operator bool() const { return **this != DirectoryStorage::NO_INDEX; } - -RsFileHash DirectoryStorage::FileIterator::hash() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_hash):RsFileHash(); } -uint64_t DirectoryStorage::FileIterator::size() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_size):0; } -std::string DirectoryStorage::FileIterator::name() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_name):std::string(); } -rstime_t DirectoryStorage::FileIterator::modtime() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_modtime):0; } - -std::string DirectoryStorage::DirIterator::name() const { const InternalFileHierarchyStorage::DirEntry *d = mStorage->getDirEntry(**this) ; return d?(d->dir_name):std::string(); } - -/******************************************************************************************************************/ -/* Directory Storage */ -/******************************************************************************************************************/ - -DirectoryStorage::DirectoryStorage(const RsPeerId &pid,const std::string& fname) - : mPeerId(pid), mDirStorageMtx("Directory storage "+pid.toStdString()),mLastSavedTime(0),mChanged(false),mFileName(fname) -{ - { - RS_STACK_MUTEX(mDirStorageMtx) ; - mFileHierarchy = new InternalFileHierarchyStorage(); - } - load(fname) ; -} - -DirectoryStorage::EntryIndex DirectoryStorage::root() const -{ - return EntryIndex(0) ; -} -int DirectoryStorage::parentRow(EntryIndex e) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - return mFileHierarchy->parentRow(e) ; -} -bool DirectoryStorage::getChildIndex(EntryIndex e,int row,EntryIndex& c) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - return mFileHierarchy->getChildIndex(e,row,c) ; -} - -uint32_t DirectoryStorage::getEntryType(const EntryIndex& indx) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - switch(mFileHierarchy->getType(indx)) - { - case InternalFileHierarchyStorage::FileStorageNode::TYPE_DIR: return DIR_TYPE_DIR ; - case InternalFileHierarchyStorage::FileStorageNode::TYPE_FILE: return DIR_TYPE_FILE ; - default: - return DIR_TYPE_UNKNOWN; - } -} - -bool DirectoryStorage::getDirectoryUpdateTime (EntryIndex index,rstime_t& update_TS) const { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->getTS(index,update_TS,&InternalFileHierarchyStorage::DirEntry::dir_update_time ); } -bool DirectoryStorage::getDirectoryRecursModTime(EntryIndex index,rstime_t& rec_md_TS) const { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->getTS(index,rec_md_TS,&InternalFileHierarchyStorage::DirEntry::dir_most_recent_time); } -bool DirectoryStorage::getDirectoryLocalModTime (EntryIndex index,rstime_t& loc_md_TS) const { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->getTS(index,loc_md_TS,&InternalFileHierarchyStorage::DirEntry::dir_modtime ); } - -bool DirectoryStorage::setDirectoryUpdateTime (EntryIndex index,rstime_t update_TS) { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->setTS(index,update_TS,&InternalFileHierarchyStorage::DirEntry::dir_update_time ); } -bool DirectoryStorage::setDirectoryRecursModTime(EntryIndex index,rstime_t rec_md_TS) { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->setTS(index,rec_md_TS,&InternalFileHierarchyStorage::DirEntry::dir_most_recent_time); } -bool DirectoryStorage::setDirectoryLocalModTime (EntryIndex index,rstime_t loc_md_TS) { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->setTS(index,loc_md_TS,&InternalFileHierarchyStorage::DirEntry::dir_modtime ); } - -bool DirectoryStorage::updateSubDirectoryList(const EntryIndex& indx, const std::set &subdirs, const RsFileHash& hash_salt) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - bool res = mFileHierarchy->updateSubDirectoryList(indx,subdirs,hash_salt) ; - mChanged = true ; - return res ; -} -bool DirectoryStorage::updateSubFilesList(const EntryIndex& indx,const std::map& subfiles,std::map& new_files) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - bool res = mFileHierarchy->updateSubFilesList(indx,subfiles,new_files) ; - mChanged = true ; - return res ; -} -bool DirectoryStorage::removeDirectory(const EntryIndex& indx) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - bool res = mFileHierarchy->removeDirectory(indx); - mChanged = true ; - - return res ; -} - -void DirectoryStorage::locked_check() -{ - std::string error ; - if(!mFileHierarchy->check(error)) - std::cerr << "Check error: " << error << std::endl; -} - -void DirectoryStorage::getStatistics(SharedDirStats& stats) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - mFileHierarchy->getStatistics(stats); -} - -bool DirectoryStorage::load(const std::string& local_file_name) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - mChanged = false ; - return mFileHierarchy->load(local_file_name); -} -void DirectoryStorage::save(const std::string& local_file_name) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - mFileHierarchy->save(local_file_name); -} -void DirectoryStorage::print() -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - mFileHierarchy->print(); -} - -int DirectoryStorage::searchTerms( - const std::list& terms, - std::list& results ) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - return mFileHierarchy->searchTerms(terms,results); -} -int DirectoryStorage::searchBoolExp(RsRegularExpression::Expression * exp, std::list &results) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - return mFileHierarchy->searchBoolExp(exp,results); -} - -bool DirectoryStorage::extractData(const EntryIndex& indx,DirDetails& d) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - d.children.clear() ; - uint32_t type = mFileHierarchy->getType(indx) ; - - d.ref = (void*)(intptr_t)indx ; - - if (type == InternalFileHierarchyStorage::FileStorageNode::TYPE_DIR) /* has children --- fill */ - { - const InternalFileHierarchyStorage::DirEntry *dir_entry = mFileHierarchy->getDirEntry(indx) ; - - /* extract all the entries */ - - for(DirectoryStorage::DirIterator it(this,indx);it;++it) - { - DirStub stub; - stub.type = DIR_TYPE_DIR; - stub.name = it.name(); - stub.ref = (void*)(intptr_t)*it; // this is updated by the caller, who knows which friend we're dealing with - - d.children.push_back(stub); - } - - for(DirectoryStorage::FileIterator it(this,indx);it;++it) - { - DirStub stub; - stub.type = DIR_TYPE_FILE; - stub.name = it.name(); - stub.ref = (void*)(intptr_t)*it; - - d.children.push_back(stub); - } - - d.type = DIR_TYPE_DIR; - d.hash.clear() ; - d.size = dir_entry->dir_cumulated_size;//dir_entry->subdirs.size() + dir_entry->subfiles.size(); - d.max_mtime = dir_entry->dir_most_recent_time ; - d.mtime = dir_entry->dir_modtime ; - d.name = dir_entry->dir_name; - d.path = RsDirUtil::makePath(dir_entry->dir_parent_path, dir_entry->dir_name) ; - d.parent = (void*)(intptr_t)dir_entry->parent_index ; - - if(indx == 0) - { - d.type = DIR_TYPE_PERSON ; - d.name = mPeerId.toStdString(); - } - } - else if(type == InternalFileHierarchyStorage::FileStorageNode::TYPE_FILE) - { - const InternalFileHierarchyStorage::FileEntry *file_entry = mFileHierarchy->getFileEntry(indx) ; - - d.type = DIR_TYPE_FILE; - d.size = file_entry->file_size; - d.max_mtime = file_entry->file_modtime ; - d.name = file_entry->file_name; - d.hash = file_entry->file_hash; - d.mtime = file_entry->file_modtime; - d.parent = (void*)(intptr_t)file_entry->parent_index ; - - const InternalFileHierarchyStorage::DirEntry *parent_dir_entry = mFileHierarchy->getDirEntry(file_entry->parent_index); - - if(parent_dir_entry != NULL) - d.path = RsDirUtil::makePath(parent_dir_entry->dir_parent_path, parent_dir_entry->dir_name) ; - else - d.path = "" ; - } - else - return false; - - d.flags.clear() ; - - return true; -} - -bool DirectoryStorage::getDirHashFromIndex(const EntryIndex& index,RsFileHash& hash) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - return mFileHierarchy->getDirHashFromIndex(index,hash) ; -} -bool DirectoryStorage::getIndexFromDirHash(const RsFileHash& hash,EntryIndex& index) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - return mFileHierarchy->getIndexFromDirHash(hash,index) ; -} - -void DirectoryStorage::checkSave() -{ - rstime_t now = time(NULL); - - if(mChanged && mLastSavedTime + MIN_INTERVAL_BETWEEN_REMOTE_DIRECTORY_SAVE < now) - { - mFileHierarchy->recursUpdateCumulatedSize(mFileHierarchy->mRoot); - - { - RS_STACK_MUTEX(mDirStorageMtx) ; - locked_check(); - } - - save(mFileName); - - { - RS_STACK_MUTEX(mDirStorageMtx) ; - mLastSavedTime = now ; - mChanged = false ; - } - } -} -/******************************************************************************************************************/ -/* Local Directory Storage */ -/******************************************************************************************************************/ - -LocalDirectoryStorage::LocalDirectoryStorage(const std::string& fname,const RsPeerId& own_id) - : DirectoryStorage(own_id,fname) -{ - mTSChanged = false ; -} - -RsFileHash LocalDirectoryStorage::makeEncryptedHash(const RsFileHash& hash) -{ - return RsDirUtil::sha1sum(hash.toByteArray(),hash.SIZE_IN_BYTES); -} -bool LocalDirectoryStorage::locked_findRealHash(const RsFileHash& hash, RsFileHash& real_hash) const -{ - std::map::const_iterator it = mEncryptedHashes.find(hash) ; - - if(it == mEncryptedHashes.end()) - return false ; - - real_hash = it->second ; - return true ; -} - -int LocalDirectoryStorage::searchHash(const RsFileHash& hash, RsFileHash& real_hash, EntryIndex& result) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - if(locked_findRealHash(hash,real_hash) && mFileHierarchy->searchHash(real_hash,result)) - return true ; - - if(mFileHierarchy->searchHash(hash,result)) - { - real_hash.clear(); - return true ; - } - return false ; -} - -void LocalDirectoryStorage::setSharedDirectoryList(const std::list& lst) -{ - std::set dirs_with_new_virtualname ; - bool dirs_with_changed_flags = false ; - - { - RS_STACK_MUTEX(mDirStorageMtx) ; - - // Chose virtual name if not supplied, and remove duplicates. - - std::set virtual_names ; // maps virtual to real name - std::list processed_list ; - - for(std::list::const_iterator it(lst.begin());it!= lst.end();++it) - { - int i=0; - std::string candidate_virtual_name = it->virtualname ; - - if(candidate_virtual_name.empty()) - candidate_virtual_name = RsDirUtil::getTopDir(it->filename); - - while(virtual_names.find(candidate_virtual_name) != virtual_names.end()) - rs_sprintf_append(candidate_virtual_name, "-%d", ++i); - - SharedDirInfo d(*it); - d.virtualname = candidate_virtual_name ; - processed_list.push_back(d) ; - - virtual_names.insert(candidate_virtual_name) ; - } - - // now for each member of the processed list, check if it is an existing shared directory that has been changed. If so, we need to update the dir TS of that directory - - std::map new_dirs ; - - for(std::list::const_iterator it(processed_list.begin());it!=processed_list.end();++it) - { - std::map::iterator it2 = mLocalDirs.find(it->filename) ; - - if(it2 != mLocalDirs.end()) - { - if(it2->second.virtualname != it->virtualname) - dirs_with_new_virtualname.insert(it->filename) ; - - if(!SharedDirInfo::sameLists((*it).parent_groups,it2->second.parent_groups) || (*it).shareflags != it2->second.shareflags) - dirs_with_changed_flags = true ; - } - - new_dirs[it->filename] = *it; - } - - mLocalDirs = new_dirs ; - mTSChanged = true ; - } - - // now update the TS off-mutex. - - for(DirIterator dirit(this,root());dirit;++dirit) - if(dirs_with_new_virtualname.find(dirit.name()) != dirs_with_new_virtualname.end()) - { - std::cerr << "Updating TS of local dir \"" << dirit.name() << "\" with changed virtual name" << std::endl; - setDirectoryLocalModTime(*dirit,time(NULL)); - } - - if(dirs_with_changed_flags) - setDirectoryLocalModTime(0,time(NULL)) ; -} - -void LocalDirectoryStorage::getSharedDirectoryList(std::list& lst) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - lst.clear(); - - for(std::map::iterator it(mLocalDirs.begin());it!=mLocalDirs.end();++it) - lst.push_back(it->second) ; -} -void LocalDirectoryStorage::updateShareFlags(const SharedDirInfo& info) -{ - bool changed = false ; - - { - RS_STACK_MUTEX(mDirStorageMtx) ; - - std::map::iterator it = mLocalDirs.find(info.filename) ; - - if(it == mLocalDirs.end()) - { - std::cerr << "(EE) LocalDirectoryStorage::updateShareFlags: directory \"" << info.filename << "\" not found" << std::endl; - return ; - } - - // we compare the new info with the old one. If the two group lists have a different order, they will be seen as different. Not a big deal. We just - // want to make sure that if they are different, flags get updated. - - if(!SharedDirInfo::sameLists(it->second.parent_groups,info.parent_groups) || it->second.filename != info.filename || it->second.shareflags != info.shareflags || it->second.virtualname != info.virtualname) - { - it->second = info; - -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << "Updating dir mod time because flags at level 0 have changed." << std::endl; -#endif - changed = true ; - } - } - - if(changed) - { - setDirectoryLocalModTime(0,time(NULL)) ; - mTSChanged = true ; - } -} - -bool LocalDirectoryStorage::convertSharedFilePath(const std::string& path, std::string& fullpath) -{ - std::string shpath = RsDirUtil::removeRootDir(path); - std::string basedir = RsDirUtil::getRootDir(path); - std::string realroot ; - { - RS_STACK_MUTEX(mDirStorageMtx) ; - realroot = locked_findRealRootFromVirtualFilename(basedir); - } - - if (realroot.empty()) - return false; - - /* construct full name */ - fullpath = realroot + "/"; - fullpath += shpath; - - return true; -} - -void LocalDirectoryStorage::notifyTSChanged() -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - mTSChanged = true ; -} -void LocalDirectoryStorage::updateTimeStamps() -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - if(mTSChanged) - { -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << "Updating recursive TS for local shared dirs..." << std::endl; -#endif - - bool unfinished_files_below ; - - rstime_t last_modf_time = mFileHierarchy->recursUpdateLastModfTime(EntryIndex(0),unfinished_files_below) ; - mTSChanged = false ; - -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << "LocalDirectoryStorage: global last modf time is " << last_modf_time << " (which is " << time(NULL) - last_modf_time << " secs ago), unfinished files below=" << unfinished_files_below << std::endl; -#else - // remove unused variable warning - // variable is only used for debugging - (void)last_modf_time; -#endif - } -} - -bool LocalDirectoryStorage::updateHash( - const EntryIndex& index, const RsFileHash& hash, - bool update_internal_hierarchy ) -{ - bool ret = false; - - { - RS_STACK_MUTEX(mDirStorageMtx); - - mEncryptedHashes[makeEncryptedHash(hash)] = hash ; - mChanged = true ; - -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << "Updating index of hash " << hash << " update_internal=" - << update_internal_hierarchy << std::endl; -#endif - - ret = (!update_internal_hierarchy) || - mFileHierarchy->updateHash(index,hash); - } // RS_STACK_MUTEX(mDirStorageMtx); - -#ifdef RS_DEEP_FILES_INDEX - FileInfo fInfo; - if( ret && getFileInfo(index, fInfo) && - fInfo.storage_permission_flags & DIR_FLAGS_ANONYMOUS_SEARCH ) - { - DeepFilesIndex dfi(DeepFilesIndex::dbDefaultPath()); - ret &= dfi.indexFile(fInfo.path, fInfo.fname, hash); - } -#endif // def RS_DEEP_FILES_INDEX - - return ret; -} -std::string LocalDirectoryStorage::locked_findRealRootFromVirtualFilename(const std::string& virtual_rootdir) const -{ - /**** MUST ALREADY BE LOCKED ****/ - - std::map::const_iterator cit = mLocalDirs.find(virtual_rootdir) ; - - if (cit == mLocalDirs.end()) - { - std::cerr << "(EE) locked_findRealRootFromVirtualFilename() Invalid RootDir: " << virtual_rootdir << std::endl; - return std::string(); - } - return cit->second.filename; -} - -bool LocalDirectoryStorage::extractData(const EntryIndex& indx,DirDetails& d) -{ - bool res = DirectoryStorage::extractData(indx,d) ; - - if(!res) - return false; - - // here we should update the file sharing flags - - return getFileSharingPermissions(indx,d.flags,d.parent_groups) ; -} - -bool LocalDirectoryStorage::getFileInfo(DirectoryStorage::EntryIndex i,FileInfo& info) -{ - DirDetails d; - extractData(i,d) ; - - if(d.type != DIR_TYPE_FILE) - { - std::cerr << "(EE) LocalDirectoryStorage: asked for file info for index " << i << " which is not a file." << std::endl; - return false; - } - - info.storage_permission_flags = d.flags; // Combination of the four RS_DIR_FLAGS_*. Updated when the file is a local stored file. - info.parent_groups = d.parent_groups; - info.transfer_info_flags = TransferRequestFlags(); // various flags from RS_FILE_HINTS_* - info.path = d.path + "/" + d.name; - info.fname = d.name; - info.hash = d.hash; - info.size = d.size; - - // all this stuff below is not useful in this case. - - info.mId = 0; /* (GUI) Model Id -> unique number */ - info.ext.clear(); - info.avail = 0; /* how much we have */ - info.rank = 0; - info.age = 0; - info.queue_position =0; - info.searchId = 0; /* 0 if none */ - - /* Transfer Stuff */ - info.transfered = 0; - info.tfRate = 0; /* in kbytes */ - info.downloadStatus = FT_STATE_COMPLETE ; - //std::list peers; - - info.priority = SPEED_NORMAL; - info.lastTS = 0; - - return true; -} - -bool LocalDirectoryStorage::getFileSharingPermissions(const EntryIndex& indx,FileStorageFlags& flags,std::list& parent_groups) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - return locked_getFileSharingPermissions(indx,flags,parent_groups) ; -} - -bool LocalDirectoryStorage::locked_getFileSharingPermissions(const EntryIndex& indx, FileStorageFlags& flags, std::list &parent_groups) -{ - flags.clear() ; - parent_groups.clear(); - - std::string base_dir; - - const InternalFileHierarchyStorage::FileStorageNode *n = mFileHierarchy->getNode(indx) ; - - if(n == NULL) - return false ; - - for(DirectoryStorage::EntryIndex i=((n->type()==InternalFileHierarchyStorage::FileStorageNode::TYPE_FILE)?((intptr_t)n->parent_index):indx);;) - { - const InternalFileHierarchyStorage::DirEntry *e = mFileHierarchy->getDirEntry(i) ; - - if(e == NULL) - break ; - - if(e->parent_index == 0) - { - base_dir = e->dir_name ; - break ; - } - i = e->parent_index ; - } - - if(!base_dir.empty()) - { - std::map::const_iterator it = mLocalDirs.find(base_dir) ; - - if(it == mLocalDirs.end()) - { - std::cerr << "(II) base directory \"" << base_dir << "\" not found in shared dir list." << std::endl; - return false ; - } - - flags = it->second.shareflags; - parent_groups = it->second.parent_groups; - } - - return true; -} - -std::string LocalDirectoryStorage::locked_getVirtualDirName(EntryIndex indx) const -{ - if(indx == 0) - return std::string() ; - - const InternalFileHierarchyStorage::DirEntry *dir = mFileHierarchy->getDirEntry(indx); - - if(dir->parent_index != 0) - return dir->dir_name ; - - std::map::const_iterator it = mLocalDirs.find(dir->dir_name) ; - - if(it == mLocalDirs.end()) - { - std::cerr << "(EE) Cannot find real name " << dir->dir_name << " at level 1 among shared dirs. Bug?" << std::endl; - return std::string() ; - } - - return it->second.virtualname ; -} -std::string LocalDirectoryStorage::locked_getVirtualPath(EntryIndex indx) const -{ - if(indx == 0) - return std::string() ; - - std::string res ; - const InternalFileHierarchyStorage::DirEntry *dir = mFileHierarchy->getDirEntry(indx); - - while(dir->parent_index != 0) - { - dir = mFileHierarchy->getDirEntry(dir->parent_index) ; - res += dir->dir_name + "/"+ res ; - } - - std::map::const_iterator it = mLocalDirs.find(dir->dir_name) ; - - if(it == mLocalDirs.end()) - { - std::cerr << "(EE) Cannot find real name " << dir->dir_name << " at level 1 among shared dirs. Bug?" << std::endl; - return std::string() ; - } - return it->second.virtualname + "/" + res; -} - -bool LocalDirectoryStorage::serialiseDirEntry(const EntryIndex& indx,RsTlvBinaryData& bindata,const RsPeerId& client_id) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - const InternalFileHierarchyStorage::DirEntry *dir = mFileHierarchy->getDirEntry(indx); - -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << "Serialising Dir entry " << std::hex << indx << " for client id " << client_id << std::endl; -#endif - if(dir == NULL) - { - std::cerr << "(EE) serialiseDirEntry: ERROR. Cannot find entry " << (void*)(intptr_t)indx << std::endl; - return false; - } - - // compute list of allowed subdirs - std::vector allowed_subdirs ; - FileStorageFlags node_flags ; - std::list node_groups ; - - // for each subdir, compute the node flags and groups, then ask rsPeers to compute the mask that result from these flags for the particular peer supplied in parameter - - for(uint32_t i=0;isubdirs.size();++i) - if(indx != 0 || (locked_getFileSharingPermissions(dir->subdirs[i],node_flags,node_groups) && (rsPeers->computePeerPermissionFlags(client_id,node_flags,node_groups) & RS_FILE_HINTS_BROWSABLE))) - { - RsFileHash hash ; - if(!mFileHierarchy->getDirHashFromIndex(dir->subdirs[i],hash)) - { - std::cerr << "(EE) Cannot get hash from subdir index " << dir->subdirs[i] << ". Weird bug." << std::endl ; - return false; - } - allowed_subdirs.push_back(hash) ; -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << " pushing subdir " << hash << ", array position=" << i << " indx=" << dir->subdirs[i] << std::endl; -#endif - } -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - else - std::cerr << " not pushing subdir " << hash << ", array position=" << i << " indx=" << dir->subdirs[i] << ": permission denied for this peer." << std::endl; -#endif - - // now count the files that do not have a null hash (meaning the hash has indeed been computed) - - uint32_t allowed_subfiles = 0 ; - - for(uint32_t i=0;isubfiles.size();++i) - { - const InternalFileHierarchyStorage::FileEntry *file = mFileHierarchy->getFileEntry(dir->subfiles[i]) ; - if(file != NULL && !file->file_hash.isNull()) - allowed_subfiles++ ; - } - - unsigned char *section_data = (unsigned char *)rs_malloc(FL_BASE_TMP_SECTION_SIZE) ; - - if(!section_data) - return false ; - - uint32_t section_size = FL_BASE_TMP_SECTION_SIZE; - uint32_t section_offset = 0; - - // we need to send: - // - the name of the directory, its TS - // - the index entry for each subdir (the updte TS are exchanged at a higher level) - // - the file info for each subfile - // - std::string virtual_dir_name = locked_getVirtualDirName(indx) ; - - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_DIR_NAME ,virtual_dir_name )) { free(section_data); return false ;} - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RECURS_MODIF_TS,(uint32_t)dir->dir_most_recent_time)) { free(section_data); return false ;} - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_MODIF_TS ,(uint32_t)dir->dir_modtime )) { free(section_data); return false ;} - - // serialise number of subdirs and number of subfiles - - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)allowed_subdirs.size() )) { free(section_data); return false ;} - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)allowed_subfiles )) { free(section_data); return false ;} - - // serialise subdirs entry indexes - - for(uint32_t i=0;isubfiles.size();++i) - { - uint32_t file_section_offset = 0 ; - - const InternalFileHierarchyStorage::FileEntry *file = mFileHierarchy->getFileEntry(dir->subfiles[i]) ; - - if(file == NULL || file->file_hash.isNull()) - { - std::cerr << "(II) skipping unhashed or Null file entry " << dir->subfiles[i] << " to get/send file info." << std::endl; - continue ; - } - - if(!FileListIO::writeField(file_section_data,file_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,file->file_name )) { free(section_data);free(file_section_data);return false ;} - if(!FileListIO::writeField(file_section_data,file_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,file->file_size )) { free(section_data);free(file_section_data);return false ;} - if(!FileListIO::writeField(file_section_data,file_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,file->file_hash )) { free(section_data);free(file_section_data);return false ;} - if(!FileListIO::writeField(file_section_data,file_section_size,file_section_offset,FILE_LIST_IO_TAG_MODIF_TS ,(uint32_t)file->file_modtime)) { free(section_data);free(file_section_data);return false ;} - - // now write the whole string into a single section in the file - - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_REMOTE_FILE_ENTRY,file_section_data,file_section_offset)) { free(section_data); free(file_section_data);return false ;} - -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << " pushing subfile " << file->hash << ", array position=" << i << " indx=" << dir->subfiles[i] << std::endl; -#endif - } - free(file_section_data) ; - -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << "Serialised dir entry to send for entry index " << (void*)(intptr_t)indx << ". Data size is " << section_size << " bytes" << std::endl; -#endif - - bindata.bin_data = realloc(section_data,section_offset) ; // This discards the possibly unused trailing bytes in the end of section_data - bindata.bin_len = section_offset ; - - return true ; -} - - -/******************************************************************************************************************/ -/* Remote Directory Storage */ -/******************************************************************************************************************/ - -RemoteDirectoryStorage::RemoteDirectoryStorage(const RsPeerId& pid,const std::string& fname) - : DirectoryStorage(pid,fname) -{ - mLastSweepTime = time(NULL) - (RSRandom::random_u32() % DELAY_BETWEEN_REMOTE_DIRECTORIES_SWEEP) ; - - std::cerr << "Loaded remote directory for peer " << pid << ", inited last sweep time to " << time(NULL) - mLastSweepTime << " secs ago." << std::endl; -#ifdef DEBUG_REMOTE_DIRECTORY_STORAGE - mFileHierarchy->print(); -#endif -} - -bool RemoteDirectoryStorage::deserialiseUpdateDirEntry(const EntryIndex& indx,const RsTlvBinaryData& bindata) -{ - const unsigned char *section_data = (unsigned char*)bindata.bin_data ; - uint32_t section_size = bindata.bin_len ; - uint32_t section_offset=0 ; - -#ifdef DEBUG_REMOTE_DIRECTORY_STORAGE - std::cerr << "RemoteDirectoryStorage::deserialiseDirEntry(): deserialising directory content for friend " << peerId() << ", and directory " << indx << std::endl; -#endif - - std::string dir_name ; - uint32_t most_recent_time ,dir_modtime ; - - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_DIR_NAME ,dir_name )) return false ; - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RECURS_MODIF_TS,most_recent_time)) return false ; - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_MODIF_TS ,dir_modtime )) return false ; - -#ifdef DEBUG_REMOTE_DIRECTORY_STORAGE - std::cerr << " dir name : \"" << dir_name << "\"" << std::endl; - std::cerr << " most recent time : " << most_recent_time << std::endl; - std::cerr << " modification time : " << dir_modtime << std::endl; -#endif - - // serialise number of subdirs and number of subfiles - - uint32_t n_subdirs,n_subfiles ; - - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subdirs )) return false ; - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subfiles )) return false ; - -#ifdef DEBUG_REMOTE_DIRECTORY_STORAGE - std::cerr << " number of subdirs : " << n_subdirs << std::endl; - std::cerr << " number of files : " << n_subfiles << std::endl; -#endif - - // serialise subdirs entry indexes - - std::vector subdirs_hashes ; - RsFileHash subdir_hash ; - - for(uint32_t i=0;i subfiles_array ; - - // Pre-allocate file_section_data, so that read_field does not need to do it many times. - - unsigned char *file_section_data = (unsigned char *)rs_malloc(FL_BASE_TMP_SECTION_SIZE) ; - - if(!file_section_data) - return false ; - - uint32_t file_section_size = FL_BASE_TMP_SECTION_SIZE ; - - for(uint32_t i=0;iupdateDirEntry(indx,dir_name,most_recent_time,dir_modtime,subdirs_hashes,subfiles_array)) - { - std::cerr << "(EE) Cannot update dir entry with index " << indx << ": entry does not exist." << std::endl; - return false ; - } - - mChanged = true ; - - return true ; -} - -int RemoteDirectoryStorage::searchHash(const RsFileHash& hash, EntryIndex& result) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - return mFileHierarchy->searchHash(hash,result); -} - - - diff --git a/libretroshare/src/file_sharing/directory_storage.h b/libretroshare/src/file_sharing/directory_storage.h deleted file mode 100644 index 670682be3..000000000 --- a/libretroshare/src/file_sharing/directory_storage.h +++ /dev/null @@ -1,318 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: directory_storage.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "retroshare/rsids.h" -#include "retroshare/rsfiles.h" -#include "util/rstime.h" - -#define NOT_IMPLEMENTED() { std::cerr << __PRETTY_FUNCTION__ << ": not yet implemented." << std::endl; } - -class RsTlvBinaryData ; -class InternalFileHierarchyStorage ; -class RsTlvBinaryData ; - -class DirectoryStorage -{ - public: - DirectoryStorage(const RsPeerId& pid, const std::string& fname) ; - virtual ~DirectoryStorage() {} - - typedef uint32_t EntryIndex ; - static const EntryIndex NO_INDEX = 0xffffffff; - - void save() const ; - - // These functions are to be used by file transfer and file search. - - virtual int searchTerms(const std::list& terms, std::list &results) const ; - virtual int searchBoolExp(RsRegularExpression::Expression * exp, std::list &results) const ; - - // gets/sets the various time stamps: - // - bool getDirectoryRecursModTime(EntryIndex index,rstime_t& recurs_max_modf_TS) const ; // last modification time, computed recursively over all subfiles and directories - bool getDirectoryLocalModTime (EntryIndex index,rstime_t& motime_TS) const ; // last modification time for that index only - bool getDirectoryUpdateTime (EntryIndex index,rstime_t& update_TS) const ; // last time the entry was updated. This is only used on the RemoteDirectoryStorage side. - - bool setDirectoryRecursModTime(EntryIndex index,rstime_t recurs_max_modf_TS) ; - bool setDirectoryLocalModTime (EntryIndex index,rstime_t modtime_TS) ; - bool setDirectoryUpdateTime (EntryIndex index,rstime_t update_TS) ; - - uint32_t getEntryType(const EntryIndex& indx) ; // WARNING: returns DIR_TYPE_*, not the internal directory storage stuff. - virtual bool extractData(const EntryIndex& indx,DirDetails& d); - - // This class allows to abstractly browse the stored directory hierarchy in a depth-first manner. - // It gives access to sub-files and sub-directories below. When using it, the client should make sure - // that the DirectoryStorage is properly locked, since the iterator cannot lock it. - // - class DirIterator - { - public: - DirIterator(const DirIterator& d) ; - DirIterator(DirectoryStorage *d,EntryIndex i) ; - - DirIterator& operator++() ; - EntryIndex operator*() const ; - - operator bool() const ; // used in for loops. Returns true when the iterator is valid. - - // info about the directory that is pointed by the iterator - - std::string name() const ; - rstime_t last_modif_time() const ; // last time a file in this directory or in the directories below has been modified. - rstime_t last_update_time() const ; // last time this directory was updated - private: - EntryIndex mParentIndex ; // index of the parent dir. - uint32_t mDirTabIndex ; // index in the vector of subdirs. - InternalFileHierarchyStorage *mStorage ; - - friend class DirectoryStorage ; - }; - class FileIterator - { - public: - explicit FileIterator(DirIterator& d); // crawls all files in specified directory - FileIterator(DirectoryStorage *d,EntryIndex e); // crawls all files in specified directory - - FileIterator& operator++() ; - EntryIndex operator*() const ; // current file entry - - operator bool() const ; // used in for loops. Returns true when the iterator is valid. - - // info about the file that is pointed by the iterator - - std::string name() const ; - uint64_t size() const ; - RsFileHash hash() const ; - rstime_t modtime() const ; - - private: - EntryIndex mParentIndex ; // index of the parent dir. - uint32_t mFileTabIndex ; // index in the vector of subdirs. - InternalFileHierarchyStorage *mStorage ; - }; - - struct FileTS - { - uint64_t size ; - rstime_t modtime; - }; - - EntryIndex root() const ; // returns the index of the root directory entry. This is generally 0. - const RsPeerId& peerId() const { return mPeerId ; } // peer ID of who owns that file list. - int parentRow(EntryIndex e) const ; // position of the current node, in the array of children at its parent node. Used by GUI for display. - bool getChildIndex(EntryIndex e,int row,EntryIndex& c) const; // returns the index of the children node at position "row" in the children nodes. Used by GUI for display. - - // Sets the subdirectory/subfiles list of entry indx the supplied one, possible adding and removing directories (resp.files). New directories are set empty with - // just a name and need to be updated later on. New files are returned in a list so that they can be sent to hash cache. - // - bool updateSubDirectoryList(const EntryIndex& indx, const std::set& subdirs, const RsFileHash &random_hash_salt) ; - bool updateSubFilesList(const EntryIndex& indx, const std::map &subfiles, std::map &new_files) ; - bool removeDirectory(const EntryIndex& indx) ; - - // Returns the hash of the directory at the given index and reverse. This hash is set as random the first time it is used (when updating directories). It will be - // used by the sync system to designate the directory without referring to index (index could be used to figure out the existance of hidden directories) - - bool getDirHashFromIndex(const EntryIndex& index,RsFileHash& hash) const ; // constant cost - bool getIndexFromDirHash(const RsFileHash& hash,EntryIndex& index) const ; // log cost. - - // gathers statistics from the internal directory structure - - void getStatistics(SharedDirStats& stats) ; - - void print(); - void cleanup(); - - /*! - * \brief checkSave - * Checks the time of last saving, last modification time, and saves if needed. - */ - void checkSave() ; - - const std::string& filename() const { return mFileName ; } - - protected: - bool load(const std::string& local_file_name) ; - void save(const std::string& local_file_name) ; - - private: - - // debug - void locked_check(); - - // storage of internal structure. Totally hidden from the outside. EntryIndex is simply the index of the entry in the vector. - - RsPeerId mPeerId; - - protected: - mutable RsMutex mDirStorageMtx ; - - InternalFileHierarchyStorage *mFileHierarchy ; - - rstime_t mLastSavedTime ; - bool mChanged ; - std::string mFileName; -}; - -class RemoteDirectoryStorage: public DirectoryStorage -{ -public: - RemoteDirectoryStorage(const RsPeerId& pid,const std::string& fname) ; - virtual ~RemoteDirectoryStorage() {} - - /*! - * \brief deserialiseDirEntry - * Loads a serialised directory content coming from a friend. The directory entry needs to exist already, - * as it is created when updating the parent. - * - * \param indx index of the directory to update - * \param bindata binary data to deserialise from - * \return false when the directory cannot be found. - */ - bool deserialiseUpdateDirEntry(const EntryIndex& indx,const RsTlvBinaryData& data) ; - - /*! - * \brief lastSweepTime - * returns the last time a sweep has been done over the directory in order to check update TS. - * \return - */ - rstime_t& lastSweepTime() { return mLastSweepTime ; } - - /*! - * \brief searchHash - * Looks into local database of shared files for the given hash. - * \param hash hash to look for - * \param results Entry index of the file that is found - * \return - * true is a file is found - * false otherwise. - */ - virtual int searchHash(const RsFileHash& hash, EntryIndex& results) const ; - -private: - rstime_t mLastSweepTime ; -}; - -class LocalDirectoryStorage: public DirectoryStorage -{ -public: - LocalDirectoryStorage(const std::string& fname,const RsPeerId& own_id); - virtual ~LocalDirectoryStorage() {} - - /*! - * \brief [gs]etSharedDirectoryList - * Gets/sets the list of shared directories. Each directory is supplied with a virtual name (the name the friends will see), and sharing flags/groups. - * \param lst - */ - void setSharedDirectoryList(const std::list& lst) ; - void getSharedDirectoryList(std::list& lst) ; - - void updateShareFlags(const SharedDirInfo& info) ; - bool convertSharedFilePath(const std::string& path_with_virtual_name,std::string& fullpath) ; - - virtual bool updateHash(const EntryIndex& index, const RsFileHash& hash, bool update_internal_hierarchy); - /*! - * \brief searchHash - * Looks into local database of shared files for the given hash. Also looks for files such that the hash of the hash - * matches the given hash, and returns the real hash. - * \param hash hash to look for - * \param real_hash hash such that H(real_hash) = hash, or null hash if not found. - * \param results Entry index of the file that is found - * \return - * true is a file is found - * false otherwise. - */ - virtual int searchHash(const RsFileHash& hash, RsFileHash &real_hash, EntryIndex &results) const ; - - /*! - * \brief updateTimeStamps - * Checks recursive TS and update the if needed. - */ - void updateTimeStamps(); - - /*! - * \brief notifyTSChanged - * Use this to force an update of the recursive TS, when calling updateTimeStamps(); - */ - void notifyTSChanged(); - /*! - * \brief getFileInfo Converts an index info a full file info structure. - * \param i index in the directory structure - * \param info structure to be filled in - * \return false if the file does not exist, or is a directory,... - */ - bool getFileInfo(DirectoryStorage::EntryIndex i,FileInfo& info) ; - - /*! - * \brief getFileSharingPermissions - * Computes the flags and parent groups for any index. - * \param indx index of the entry to compute the flags for - * \param flags computed flags - * \param parent_groups computed parent groups - * \return - * false if the index is not valid - * false otherwise - */ - bool getFileSharingPermissions(const EntryIndex& indx, FileStorageFlags &flags, std::list &parent_groups); - - virtual bool extractData(const EntryIndex& indx,DirDetails& d) ; - - /*! - * \brief serialiseDirEntry - * Produced a serialised directory content listing suitable for export to friends. - * - * \param indx index of the directory to serialise - * \param bindata binary data created by serialisation - * \param client_id Peer id to be serialised to. Depending on permissions, some subdirs can be removed. - * \return false when the directory cannot be found. - */ - bool serialiseDirEntry(const EntryIndex& indx, RsTlvBinaryData& bindata, const RsPeerId &client_id) ; - -private: - static RsFileHash makeEncryptedHash(const RsFileHash& hash); - bool locked_findRealHash(const RsFileHash& hash, RsFileHash& real_hash) const; - std::string locked_getVirtualPath(EntryIndex indx) const ; - std::string locked_getVirtualDirName(EntryIndex indx) const ; - - bool locked_getFileSharingPermissions(const EntryIndex& indx, FileStorageFlags &flags, std::list& parent_groups); - std::string locked_findRealRootFromVirtualFilename(const std::string& virtual_rootdir) const; - - std::map mLocalDirs ; // map is better for search. it->first=it->second.filename - std::map mEncryptedHashes; // map such that hash(it->second) = it->first - - bool mTSChanged ; -}; - - - - - - - - - - - diff --git a/libretroshare/src/file_sharing/directory_updater.cc b/libretroshare/src/file_sharing/directory_updater.cc deleted file mode 100644 index 828d1ee2c..000000000 --- a/libretroshare/src/file_sharing/directory_updater.cc +++ /dev/null @@ -1,416 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: directory_updater.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ -#include "util/folderiterator.h" -#include "util/rstime.h" -#include "rsserver/p3face.h" - -#include "directory_storage.h" -#include "directory_updater.h" -#include "file_sharing_defaults.h" - -//#define DEBUG_LOCAL_DIR_UPDATER 1 - -//=============================================================================================================// -// Local Directory Updater // -//=============================================================================================================// - -LocalDirectoryUpdater::LocalDirectoryUpdater(HashStorage *hc,LocalDirectoryStorage *lds) - : mHashCache(hc), mSharedDirectories(lds) - , mLastSweepTime(0), mLastTSUpdateTime(0) - , mDelayBetweenDirectoryUpdates(DELAY_BETWEEN_DIRECTORY_UPDATES) - , mIsEnabled(false), mFollowSymLinks(FOLLOW_SYMLINKS_DEFAULT) - , mIgnoreDuplicates(true) - /* Can be left to false, but setting it to true will force to re-hash any file that has been left unhashed in the last session.*/ - , mNeedsFullRecheck(true) - , mIsChecking(false), mForceUpdate(false), mIgnoreFlags (0), mMaxShareDepth(0) -{ -} - -bool LocalDirectoryUpdater::isEnabled() const -{ - return mIsEnabled ; -} -void LocalDirectoryUpdater::setEnabled(bool b) -{ - if(mIsEnabled == b) return; - if(!b) RsThread::askForStop(); - else if(!RsThread::isRunning()) start("fs dir updater"); - mIsEnabled = b ; -} - -void LocalDirectoryUpdater::threadTick() -{ - rstime_t now = time(NULL) ; - - if (mIsEnabled || mForceUpdate) - { - if(now > mDelayBetweenDirectoryUpdates + mLastSweepTime) - { - bool some_files_not_ready = false ; - - if(sweepSharedDirectories(some_files_not_ready)) - { - if(some_files_not_ready) - { - mNeedsFullRecheck = true ; - mLastSweepTime = now - mDelayBetweenDirectoryUpdates + 60 ; // retry 20 secs from now - - std::cerr << "(II) some files being modified. Will re-scan in 60 secs." << std::endl; - } - else - { - mNeedsFullRecheck = false ; - mLastSweepTime = now ; - } - - mSharedDirectories->notifyTSChanged(); - mForceUpdate = false ; - } - else - std::cerr << "(WW) sweepSharedDirectories() failed. Will do it again in a short time." << std::endl; - } - - if(now > DELAY_BETWEEN_LOCAL_DIRECTORIES_TS_UPDATE + mLastTSUpdateTime) - { - mSharedDirectories->updateTimeStamps() ; - mLastTSUpdateTime = now ; - } - } - - for(uint32_t i=0;i<10;++i) - { - rstime::rs_usleep(1*1000*1000); - - { - if(mForceUpdate) - break ; - } - } -} - -void LocalDirectoryUpdater::forceUpdate(bool add_safe_delay) -{ - mForceUpdate = true ; - mLastSweepTime = rstime_t(time(NULL)) - rstime_t(mDelayBetweenDirectoryUpdates) ; - - if(add_safe_delay) - mLastSweepTime += rstime_t(MIN_TIME_AFTER_LAST_MODIFICATION); - - if(mHashCache != NULL && mHashCache->hashingProcessPaused()) - mHashCache->togglePauseHashingProcess(); -} - -bool LocalDirectoryUpdater::sweepSharedDirectories(bool& some_files_not_ready) -{ - if(mHashSalt.isNull()) - { - std::cerr << "(EE) no salt value in LocalDirectoryUpdater. Is that a bug?" << std::endl; - return false; - } - - mIsChecking = true ; - - RsServer::notify()->notifyListPreChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); -#ifdef DEBUG_LOCAL_DIR_UPDATER - std::cerr << "[directory storage] LocalDirectoryUpdater::sweep()" << std::endl; -#endif - - // recursive update algorithm works that way: - // - the external loop starts on the shared directory list and goes through sub-directories - // - at the same time, it updates the local list of shared directories. A single sweep is performed over the whole directory structure. - // - the information that is costly to compute (the hash) is store externally into a separate structure. - // - doing so, changing directory names or moving files between directories does not cause a re-hash of the content. - // - std::list shared_directory_list ; - mSharedDirectories->getSharedDirectoryList(shared_directory_list); - - std::set sub_dir_list ; - - // We re-check that each dir actually exists. It might have been removed from the disk. - - for(std::list::const_iterator real_dir_it(shared_directory_list.begin());real_dir_it!=shared_directory_list.end();++real_dir_it) - if(RsDirUtil::checkDirectory( (*real_dir_it).filename ) ) - sub_dir_list.insert( (*real_dir_it).filename ) ; - - // make sure that entries in stored_dir_it are the same than paths in real_dir_it, and in the same order. - - mSharedDirectories->updateSubDirectoryList(mSharedDirectories->root(),sub_dir_list,mHashSalt) ; - - // now for each of them, go recursively and match both files and dirs - - std::set existing_dirs ; - - for(DirectoryStorage::DirIterator stored_dir_it(mSharedDirectories,mSharedDirectories->root()) ; stored_dir_it;++stored_dir_it) - { -#ifdef DEBUG_LOCAL_DIR_UPDATER - std::cerr << "[directory storage] recursing into " << stored_dir_it.name() << std::endl; -#endif - existing_dirs.insert(RsDirUtil::removeSymLinks(stored_dir_it.name())); - - recursUpdateSharedDir(stored_dir_it.name(), *stored_dir_it,existing_dirs,1,some_files_not_ready) ; // here we need to use the list that was stored, instead of the shared dir list, because the two - // are not necessarily in the same order. - } - - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); - mIsChecking = false ; - - return true ; -} - -void LocalDirectoryUpdater::recursUpdateSharedDir(const std::string& cumulated_path, DirectoryStorage::EntryIndex indx,std::set& existing_directories,uint32_t current_depth,bool& some_files_not_ready) -{ -#ifdef DEBUG_LOCAL_DIR_UPDATER - std::cerr << "[directory storage] parsing directory " << cumulated_path << ", index=" << indx << std::endl; -#endif - - // make sure list of subdirs is the same - // make sure list of subfiles is the same - // request all hashes to the hashcache - - librs::util::FolderIterator dirIt(cumulated_path,mFollowSymLinks,false); // disallow symbolic links and files from the future. - - rstime_t dir_local_mod_time ; - if(!mSharedDirectories->getDirectoryLocalModTime(indx,dir_local_mod_time)) - { - std::cerr << "(EE) Cannot get local mod time for dir index " << indx << std::endl; - return; - } - - rstime_t now = time(NULL) ; - - if(mNeedsFullRecheck || dirIt.dir_modtime() > dir_local_mod_time) // the > is because we may have changed the virtual name, and therefore the TS wont match. - // we only want to detect when the directory has changed on the disk - { - // collect subdirs and subfiles - - std::map subfiles ; - std::set subdirs ; - - for(;dirIt.isValid();dirIt.next()) - if(filterFile(dirIt.file_name())) - { - switch(dirIt.file_type()) - { - case librs::util::FolderIterator::TYPE_FILE: - - if(dirIt.file_modtime() + MIN_TIME_AFTER_LAST_MODIFICATION < now) - { - subfiles[dirIt.file_name()].modtime = dirIt.file_modtime() ; - subfiles[dirIt.file_name()].size = dirIt.file_size(); -#ifdef DEBUG_LOCAL_DIR_UPDATER - std::cerr << " adding sub-file \"" << dirIt.file_name() << "\"" << std::endl; -#endif - } - else - { - some_files_not_ready = true ; - - std::cerr << "(WW) file " << dirIt.file_fullpath() << " is probably being written to. Keeping it for later." << std::endl; - } - - break; - - case librs::util::FolderIterator::TYPE_DIR: - { - bool dir_is_accepted = true ; - - if( (mMaxShareDepth > 0u && current_depth > mMaxShareDepth) || (mMaxShareDepth==0 && current_depth >= 64)) // 64 is here as a safe limit, to make loops impossible. - dir_is_accepted = false ; - - if(dir_is_accepted && mFollowSymLinks && mIgnoreDuplicates) - { - std::string real_path = RsDirUtil::removeSymLinks(cumulated_path + "/" + dirIt.file_name()) ; - - if(existing_directories.end() != existing_directories.find(real_path)) - { - std::cerr << "(WW) Directory " << cumulated_path << " has real path " << real_path << " which already belongs to another shared directory. Ignoring" << std::endl; - dir_is_accepted = false ; - } - else - existing_directories.insert(real_path) ; - } - - if(dir_is_accepted) - subdirs.insert(dirIt.file_name()); - -#ifdef DEBUG_LOCAL_DIR_UPDATER - std::cerr << " adding sub-dir \"" << dirIt.file_name() << "\"" << std::endl; -#endif - } - break; - default: - std::cerr << "(EE) Dir entry of unknown type with path \"" << cumulated_path << "/" << dirIt.file_name() << "\"" << std::endl; - } - } - // update folder modificatoin time, which is the only way to detect e.g. removed or renamed files. - - mSharedDirectories->setDirectoryLocalModTime(indx,dirIt.dir_modtime()) ; - - // update file and dir lists for current directory. - - mSharedDirectories->updateSubDirectoryList(indx,subdirs,mHashSalt) ; - - std::map new_files ; - mSharedDirectories->updateSubFilesList(indx,subfiles,new_files) ; - - // now go through list of subfiles and request the hash to hashcache - - for(DirectoryStorage::FileIterator dit(mSharedDirectories,indx);dit;++dit) - { - // ask about the hash. If not present, ask HashCache. If not present, or different, the callback will update it. - - RsFileHash hash ; - - // mSharedDirectories does two things: store H(F), and compute H(H(F)), which is used in FT. The later is always needed. - - if(mHashCache->requestHash(cumulated_path + "/" + dit.name(),dit.size(),dit.modtime(),hash,this,*dit)) - mSharedDirectories->updateHash(*dit,hash,hash != dit.hash()); - } - } -#ifdef DEBUG_LOCAL_DIR_UPDATER - else - std::cerr << " directory is unchanged. Keeping existing files and subdirs list." << std::endl; -#endif - - // go through the list of sub-dirs and recursively update - - for(DirectoryStorage::DirIterator stored_dir_it(mSharedDirectories,indx) ; stored_dir_it; ++stored_dir_it) - { -#ifdef DEBUG_LOCAL_DIR_UPDATER - std::cerr << " recursing into " << stored_dir_it.name() << std::endl; -#endif - recursUpdateSharedDir(cumulated_path + "/" + stored_dir_it.name(), *stored_dir_it,existing_directories,current_depth+1,some_files_not_ready) ; - } -} - -bool LocalDirectoryUpdater::filterFile(const std::string& fname) const -{ - if(mIgnoreFlags & RS_FILE_SHARE_FLAGS_IGNORE_SUFFIXES) - for(auto it(mIgnoredSuffixes.begin());it!=mIgnoredSuffixes.end();++it) - if(fname.size() >= (*it).size() && fname.substr( fname.size() - (*it).size()) == *it) - { - std::cerr << "(II) ignoring file " << fname << ", because it matches suffix \"" << *it << "\"" << std::endl; - return false ; - } - - if(mIgnoreFlags & RS_FILE_SHARE_FLAGS_IGNORE_PREFIXES) - for(auto it(mIgnoredPrefixes.begin());it!=mIgnoredPrefixes.end();++it) - if(fname.size() >= (*it).size() && fname.substr( 0,(*it).size()) == *it) - { - std::cerr << "(II) ignoring file " << fname << ", because it matches prefix \"" << *it << "\"" << std::endl; - return false ; - } - - return true ; -} - -void LocalDirectoryUpdater::togglePauseHashingProcess() -{ - mHashCache->togglePauseHashingProcess() ; -} -bool LocalDirectoryUpdater::hashingProcessPaused() -{ - return mHashCache->hashingProcessPaused(); -} - -bool LocalDirectoryUpdater::inDirectoryCheck() const -{ - return mHashCache->isRunning(); -} - -void LocalDirectoryUpdater::hash_callback(uint32_t client_param, const std::string &/*name*/, const RsFileHash &hash, uint64_t /*size*/) -{ - if(!mSharedDirectories->updateHash(DirectoryStorage::EntryIndex(client_param),hash,true)) - std::cerr << "(EE) Cannot update file. Something's wrong." << std::endl; - - mSharedDirectories->notifyTSChanged() ; -} - -bool LocalDirectoryUpdater::hash_confirm(uint32_t client_param) -{ - return mSharedDirectories->getEntryType(DirectoryStorage::EntryIndex(client_param)) == DIR_TYPE_FILE ; -} - -void LocalDirectoryUpdater::setFileWatchPeriod(int seconds) -{ - mDelayBetweenDirectoryUpdates = seconds ; -} -uint32_t LocalDirectoryUpdater::fileWatchPeriod() const -{ - return mDelayBetweenDirectoryUpdates ; -} - -void LocalDirectoryUpdater::setFollowSymLinks(bool b) -{ - if(b != mFollowSymLinks) - mNeedsFullRecheck = true ; - - mFollowSymLinks = b ; - - forceUpdate(false); -} - -bool LocalDirectoryUpdater::followSymLinks() const -{ - return mFollowSymLinks ; -} - -void LocalDirectoryUpdater::setIgnoreLists(const std::list& ignored_prefixes,const std::list& ignored_suffixes,uint32_t ignore_flags) -{ - mIgnoredPrefixes = ignored_prefixes ; - mIgnoredSuffixes = ignored_suffixes ; - mIgnoreFlags = ignore_flags; -} -bool LocalDirectoryUpdater::getIgnoreLists(std::list& ignored_prefixes,std::list& ignored_suffixes,uint32_t& ignore_flags) const -{ - ignored_prefixes = mIgnoredPrefixes; - ignored_suffixes = mIgnoredSuffixes; - ignore_flags = mIgnoreFlags ; - - return true; -} - -int LocalDirectoryUpdater::maxShareDepth() const -{ - return mMaxShareDepth ; -} - -void LocalDirectoryUpdater::setMaxShareDepth(uint32_t d) -{ - if(d != mMaxShareDepth) - mNeedsFullRecheck = true ; - - mMaxShareDepth = d ; -} - -bool LocalDirectoryUpdater::ignoreDuplicates() const -{ - return mIgnoreDuplicates; -} - -void LocalDirectoryUpdater::setIgnoreDuplicates(bool b) -{ - if(b != mIgnoreDuplicates) - mNeedsFullRecheck = true ; - - mIgnoreDuplicates = b ; -} diff --git a/libretroshare/src/file_sharing/directory_updater.h b/libretroshare/src/file_sharing/directory_updater.h deleted file mode 100644 index b7d72b3a9..000000000 --- a/libretroshare/src/file_sharing/directory_updater.h +++ /dev/null @@ -1,98 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: directory_updater.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ - -// This class crawls the given directry hierarchy and updates it. It does so by calling the -// shared file list source. This source may be of two types: -// - local: directories are crawled n disk and files are hashed / requested from a cache -// - remote: directories are requested remotely to a providing client -// -#include "file_sharing/hash_cache.h" -#include "file_sharing/directory_storage.h" -#include "util/rstime.h" - -class LocalDirectoryUpdater: public HashStorageClient, public RsTickingThread -{ -public: - LocalDirectoryUpdater(HashStorage *hash_cache,LocalDirectoryStorage *lds) ; - virtual ~LocalDirectoryUpdater() {} - - void forceUpdate(bool add_safe_delay); - bool inDirectoryCheck() const ; - void togglePauseHashingProcess(); - bool hashingProcessPaused(); - - void setHashSalt(const RsFileHash& hash) { mHashSalt = hash; } - const RsFileHash& hashSalt() const { return mHashSalt; } - - void setFileWatchPeriod(int seconds) ; - uint32_t fileWatchPeriod() const ; - - void setFollowSymLinks(bool b) ; - bool followSymLinks() const ; - - void setEnabled(bool b) ; - bool isEnabled() const ; - - void setIgnoreLists(const std::list& ignored_prefixes,const std::list& ignored_suffixes,uint32_t ignore_flags) ; - bool getIgnoreLists(std::list& ignored_prefixes,std::list& ignored_suffixes,uint32_t& ignore_flags) const ; - - void setMaxShareDepth(uint32_t i) ; - int maxShareDepth() const; - - void setIgnoreDuplicates(bool b) ; - bool ignoreDuplicates() const; - -protected: - void threadTick() override; /// @see RsTickingThread - - virtual void hash_callback(uint32_t client_param, const std::string& name, const RsFileHash& hash, uint64_t size); - virtual bool hash_confirm(uint32_t client_param) ; - - void recursUpdateSharedDir(const std::string& cumulated_path, DirectoryStorage::EntryIndex indx, std::set& existing_directories, uint32_t current_depth,bool& files_not_ready); - bool sweepSharedDirectories(bool &some_files_not_ready); - -private: - bool filterFile(const std::string& fname) const ; // reponds true if the file passes the ignore lists test. - - HashStorage *mHashCache ; - LocalDirectoryStorage *mSharedDirectories ; - - RsFileHash mHashSalt ; - - rstime_t mLastSweepTime; - rstime_t mLastTSUpdateTime; - - uint32_t mDelayBetweenDirectoryUpdates; - bool mIsEnabled ; - bool mFollowSymLinks; - bool mIgnoreDuplicates; - bool mNeedsFullRecheck ; - bool mIsChecking ; - bool mForceUpdate ; - - uint32_t mIgnoreFlags ; - uint32_t mMaxShareDepth ; - - std::list mIgnoredPrefixes ; - std::list mIgnoredSuffixes ; -}; - diff --git a/libretroshare/src/file_sharing/file_sharing_defaults.h b/libretroshare/src/file_sharing/file_sharing_defaults.h deleted file mode 100644 index 92ff43947..000000000 --- a/libretroshare/src/file_sharing/file_sharing_defaults.h +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: file_sharing_defaults.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ -#pragma once - -static const uint32_t DELAY_BETWEEN_DIRECTORY_UPDATES = 600 ; // 10 minutes -static const uint32_t DELAY_BETWEEN_REMOTE_DIRECTORY_SYNC_REQ = 120 ; // 2 minutes -static const uint32_t DELAY_BETWEEN_LOCAL_DIRECTORIES_TS_UPDATE = 20 ; // 20 sec. But we only update for real if something has changed. -static const uint32_t DELAY_BETWEEN_REMOTE_DIRECTORIES_SWEEP = 60 ; // 60 sec. -static const uint32_t DELAY_BETWEEN_EXTRA_FILES_CACHE_UPDATES = 2 ; // 2 sec. - -static const uint32_t DELAY_BEFORE_DELETE_NON_EMPTY_REMOTE_DIR = 60*24*86400 ; // delete non empty remoe directories after 60 days of inactivity -static const uint32_t DELAY_BEFORE_DELETE_EMPTY_REMOTE_DIR = 5*24*86400 ; // delete empty remote directories after 5 days of inactivity - -static const std::string HASH_CACHE_DURATION_SS = "HASH_CACHE_DURATION" ; // key string to store hash remembering time -static const std::string WATCH_FILE_DURATION_SS = "WATCH_FILES_DELAY" ; // key to store delay before re-checking for new files -static const std::string WATCH_FILE_ENABLED_SS = "WATCH_FILES_ENABLED"; // key to store ON/OFF flags for file whatch -static const std::string TRUST_FRIEND_NODES_FOR_BANNED_FILES_SS = "TRUST_FRIEND_NODES_FOR_BANNED_FILES"; // should we trust friends for banned files or not -static const std::string FOLLOW_SYMLINKS_SS = "FOLLOW_SYMLINKS"; // dereference symbolic links, or just ignore them. -static const std::string IGNORE_DUPLICATES = "IGNORE_DUPLICATES"; // do not index files that are referenced multiple times because of links -static const std::string WATCH_HASH_SALT_SS = "WATCH_HASH_SALT"; // Salt that is used to hash directory names -static const std::string IGNORED_PREFIXES_SS = "IGNORED_PREFIXES"; // ignore file prefixes -static const std::string IGNORED_SUFFIXES_SS = "IGNORED_SUFFIXES"; // ignore file suffixes -static const std::string IGNORE_LIST_FLAGS_SS = "IGNORED_FLAGS"; // ignore file flags -static const std::string MAX_SHARE_DEPTH = "MAX_SHARE_DEPTH"; // maximum depth of shared directories - -static const std::string FILE_SHARING_DIR_NAME = "file_sharing" ; // hard-coded directory name to store friend file lists, hash cache, etc. -static const std::string HASH_CACHE_FILE_NAME = "hash_cache.bin" ; // hard-coded directory name to store encrypted hash cache. -static const std::string LOCAL_SHARED_DIRS_FILE_NAME = "local_dir_hierarchy.bin" ; // hard-coded directory name to store encrypted local dir hierarchy. - -static const uint32_t MIN_INTERVAL_BETWEEN_HASH_CACHE_SAVE = 20 ; // never save hash cache more often than every 20 secs. -static const uint32_t MIN_INTERVAL_BETWEEN_REMOTE_DIRECTORY_SAVE = 23 ; // never save remote directories more often than this -static const uint32_t MIN_TIME_AFTER_LAST_MODIFICATION = 10 ; // never hash a file that is just being modified, otherwise we end up with a corrupted hash - -static const uint32_t MAX_DIR_SYNC_RESPONSE_DATA_SIZE = 20000 ; // Maximum RsItem data size in bytes for serialised directory transmission -static const uint32_t DEFAULT_HASH_STORAGE_DURATION_DAYS = 30 ; // remember deleted/inaccessible files for 30 days - -static const uint32_t NB_FRIEND_INDEX_BITS_32BITS = 10 ; // Do not change this! -static const uint32_t NB_ENTRY_INDEX_BITS_32BITS = 22 ; // Do not change this! -static const uint32_t ENTRY_INDEX_BIT_MASK_32BITS = 0x003fffff ; // used for storing (EntryIndex,Friend) couples into a 32bits pointer. Depends on the two values just before. Dont change! - -static const uint64_t NB_FRIEND_INDEX_BITS_64BITS = 24 ; // Do not change this! -static const uint64_t NB_ENTRY_INDEX_BITS_64BITS = 40 ; // Do not change this! -static const uint64_t ENTRY_INDEX_BIT_MASK_64BITS = 0x0000000fffffffff ; // used for storing (EntryIndex,Friend) couples into a 32bits pointer. Depends on the two values just before. Dont change! - -static const uint32_t DELAY_BEFORE_DROP_REQUEST = 600; // every 10 min - -static const bool FOLLOW_SYMLINKS_DEFAULT = true; -static const bool TRUST_FRIEND_NODES_FOR_BANNED_FILES_DEFAULT = true; - -static const uint32_t FL_BASE_TMP_SECTION_SIZE = 4096 ; diff --git a/libretroshare/src/file_sharing/file_tree.cc b/libretroshare/src/file_sharing/file_tree.cc deleted file mode 100644 index d34dc166b..000000000 --- a/libretroshare/src/file_sharing/file_tree.cc +++ /dev/null @@ -1,378 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: file_tree.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2018 Retroshare Team * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - ******************************************************************************/ -#include - -#include "util/radix64.h" -#include "util/rsbase64.h" -#include "util/rsdir.h" -#include "retroshare/rsfiles.h" -#include "file_sharing_defaults.h" -#include "filelist_io.h" -#include "serialiser/rstypeserializer.h" - -void RsFileTree::DirData::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(name); - RS_SERIAL_PROCESS(subdirs); - RS_SERIAL_PROCESS(subfiles); -} - -void RsFileTree::FileData::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(name); - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(hash); -} - -/*static*/ std::tuple, std::error_condition> -RsFileTree::fromBase64(const std::string& base64) -{ - const auto failure = [](std::error_condition ec) - { return std::make_tuple(nullptr, ec); }; - - if(base64.empty()) return failure(std::errc::invalid_argument); - - std::error_condition ec; - std::vector mem; - if( (ec = RsBase64::decode(base64, mem)) ) return failure(ec); - - RsGenericSerializer::SerializeContext ctx( - mem.data(), static_cast(mem.size()), - RsSerializationFlags::INTEGER_VLQ ); - std::unique_ptr ft(new RsFileTree); - ft->serial_process( - RsGenericSerializer::SerializeJob::DESERIALIZE, ctx); - if(ctx.mOk) return std::make_tuple(std::move(ft), std::error_condition()); - - return failure(std::errc::invalid_argument); -} - -std::string RsFileTree::toBase64() const -{ - RsGenericSerializer::SerializeContext ctx; - ctx.mFlags = RsSerializationFlags::INTEGER_VLQ; - RsFileTree* ncThis = const_cast(this); - ncThis->serial_process( - RsGenericSerializer::SerializeJob::SIZE_ESTIMATE, ctx ); - - std::vector buf(ctx.mOffset); - ctx.mSize = ctx.mOffset; ctx.mOffset = 0; ctx.mData = buf.data(); - - ncThis->serial_process( - RsGenericSerializer::SerializeJob::SERIALIZE, ctx ); - std::string result; - RsBase64::encode(ctx.mData, ctx.mSize, result, false, true); - return result; -} - -std::string RsFileTree::toRadix64() const -{ - unsigned char* buff = nullptr; - uint32_t size = 0; - serialise(buff, size); - std::string res; - Radix64::encode(buff,size,res); - free(buff); - return res; -} - -std::unique_ptr RsFileTree::fromRadix64( - const std::string& radix64_string ) -{ - std::unique_ptr ft(new RsFileTree); - std::vector mem = Radix64::decode(radix64_string); - if(ft->deserialise(mem.data(), static_cast(mem.size()))) - return ft; - return nullptr; -} - -void RsFileTree::recurs_buildFileTree( - RsFileTree& ft, uint32_t index, const DirDetails& dd, bool remote, - bool remove_top_dirs ) -{ - RsDbg() << __PRETTY_FUNCTION__ << " index: " << index << std::endl; - if(ft.mDirs.size() <= index) - ft.mDirs.resize(index+1) ; - - if(remove_top_dirs) - ft.mDirs[index].name = RsDirUtil::getTopDir(dd.name) ; - else - ft.mDirs[index].name = dd.name ; - - ft.mDirs[index].subfiles.clear(); - ft.mDirs[index].subdirs.clear(); - - DirDetails dd2 ; - - FileSearchFlags flags = remote ? RS_FILE_HINTS_REMOTE : RS_FILE_HINTS_LOCAL; - - for(uint32_t i=0;iRequestDirDetails(dd.children[i].ref,dd2,flags)) - { - if(dd.children[i].type == DIR_TYPE_FILE) - { - FileData f ; - f.name = dd2.name ; - f.size = dd2.size ; - f.hash = dd2.hash ; - - ft.mDirs[index].subfiles.push_back(ft.mFiles.size()) ; - ft.mFiles.push_back(f) ; - - ft.mTotalFiles++ ; - ft.mTotalSize += f.size ; - } - else if(dd.children[i].type == DIR_TYPE_DIR) - { - ft.mDirs[index].subdirs.push_back(ft.mDirs.size()); - recurs_buildFileTree(ft,ft.mDirs.size(),dd2,remote,remove_top_dirs) ; - } - else - std::cerr << "(EE) Unsupported DirDetails type." << std::endl; - } - else - std::cerr << "(EE) Cannot request dir details for pointer " << dd.children[i].ref << std::endl; -} - -bool RsFileTree::getDirectoryContent( - std::string& name, std::vector& subdirs, - std::vector& subfiles, uint64_t index_p ) const -{ - // Avoid warnings on Android armv7 - using sz_t = std::vector::size_type; - sz_t index = static_cast(index_p); - - if(index >= mDirs.size()) return false; - - name = mDirs[index].name; - subdirs = mDirs[index].subdirs ; - - subfiles.clear() ; - for(sz_t i=0; i < mDirs[index].subfiles.size(); ++i) - subfiles.push_back(mFiles[static_cast(mDirs[index].subfiles[i])]); - - return true; -} - -std::unique_ptr RsFileTree::fromDirDetails( - const DirDetails& dd, bool remote ,bool remove_top_dirs ) -{ - std::unique_ptrft(new RsFileTree); - if(dd.type == DIR_TYPE_FILE) - { - FileData fd; - fd.name = dd.name; fd.hash = dd.hash; fd.size = dd.size; - ft->mFiles.push_back(fd); - ft->mTotalFiles = 1; - ft->mTotalSize = fd.size; - - DirData dd; - dd.name = "/"; - dd.subfiles.push_back(0); - ft->mDirs.push_back(dd); - } - else recurs_buildFileTree(*ft, 0, dd, remote, remove_top_dirs ); - return ft; -} - -typedef FileListIO::read_error read_error ; - -bool RsFileTree::deserialise(unsigned char *buffer,uint32_t buffer_size) -{ - uint32_t buffer_offset = 0 ; - - mTotalFiles = 0; - mTotalSize = 0; - - try - { - // Read some header - - uint32_t version,n_dirs,n_files ; - - if(!FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION,version)) throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION) ; - if(version != (uint32_t) FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001) throw std::runtime_error("Wrong version number") ; - - if(!FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_files)) throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ; - if(!FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_dirs)) throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ; - - // Write all file/dir entries - - mFiles.resize(n_files) ; - mDirs.resize(n_dirs) ; - - unsigned char *node_section_data = NULL ; - uint32_t node_section_size = 0 ; - - for(uint32_t i=0;i * - * * - * 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 . * - * * - ******************************************************************************/ -#include -#include "retroshare/rsids.h" -#include "pqi/authssl.h" -#include "util/rsdir.h" -#include "util/rsprint.h" -#include "serialiser/rsbaseserial.h" -#include "filelist_io.h" - -FileListIO::read_error::read_error(unsigned char *sec,uint32_t size,uint32_t offset,uint8_t expected_tag) -{ - std::ostringstream s ; - s << "At offset " << offset << "/" << size << ": expected section tag " << std::hex << (int)expected_tag << std::dec << " but got " << RsUtil::BinToHex(&sec[offset],std::min((int)size-(int)offset, 15)) << "..." << std::endl; - err_string = s.str(); -} - -template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const uint32_t & val) { return setRawUInt32(buff,size,&offset,val) ; } -template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const uint64_t & val) { return setRawUInt64(buff,size,&offset,val) ; } -template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const std::string & val) { return setRawString(buff,size,&offset,val) ; } -template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const Sha1CheckSum & val) { return val.serialise(buff,size,offset) ; } - -template<> bool FileListIO::deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,uint32_t & val) { return getRawUInt32(const_cast(buff),size,&offset,&val) ; } -template<> bool FileListIO::deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,uint64_t & val) { return getRawUInt64(const_cast(buff),size,&offset,&val) ; } -template<> bool FileListIO::deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,std::string & val) { return getRawString(const_cast(buff),size,&offset,val) ; } -template<> bool FileListIO::deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,Sha1CheckSum & val) { return val.deserialise(const_cast(buff),size,offset) ; } - -template<> uint32_t FileListIO::serial_size(const uint32_t & ) { return 4 ; } -template<> uint32_t FileListIO::serial_size(const uint64_t & ) { return 8 ; } -template<> uint32_t FileListIO::serial_size(const std::string & val) { return getRawStringSize(val) ; } -template<> uint32_t FileListIO::serial_size(const Sha1CheckSum & ) { return Sha1CheckSum::serial_size(); } - -bool FileListIO::writeField( unsigned char*&buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,const unsigned char * val,uint32_t size) -{ - if(!checkSectionSize(buff,buff_size,offset,size)) - return false; - - if(!writeSectionHeader(buff,buff_size,offset,section_tag,size)) - return false; - - memcpy(&buff[offset],val,size) ; - offset += size ; - - return true; -} - -bool FileListIO::readField (const unsigned char *buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag, unsigned char *& val,uint32_t& size) -{ - uint32_t local_size ; - - if(!readSectionHeader(buff,buff_size,offset,check_section_tag,local_size)) - return false; - - if(!checkSectionSize(val,size,0,local_size)) // allocate val if needed to handle local_size bytes. - return false; - - memcpy(val,&buff[offset],local_size); - offset += local_size ; - - return true ; -} - -bool FileListIO::write125Size(unsigned char *data,uint32_t data_size,uint32_t& offset,uint32_t S) -{ - if(S < 192) - { - if(offset+1 > data_size) - return false; - - data[offset++] = (uint8_t)S ; - return true; - } - else if(S < 8384) - { - if(offset+2 > data_size) - return false; - - data[offset+1] = (S - 192) & 0xff ; - data[offset ] = ((S - 192 - data[offset+1]) >> 8) + 192; - - offset += 2 ; - - return true; - } - else - { - if(offset+5 > data_size) - return false; - - data[offset++] = 0xff ; - data[offset++] = (uint8_t)((S >> 24) & 255) ; - data[offset++] = (uint8_t)((S >> 16) & 255) ; - data[offset++] = (uint8_t)((S >> 8) & 255) ; - data[offset++] = (uint8_t)((S ) & 255) ; - - return true ; - } -} - -bool FileListIO::read125Size(const unsigned char *data,uint32_t data_size,uint32_t& offset,uint32_t& S) -{ - if(offset + 1 >= data_size) return false; - - uint8_t b1 = data[offset++] ; - - if(b1 < 192) - { - S = b1; - return true ; - } - if(offset + 1 >= data_size) return false; - - uint8_t b2 = data[offset++] ; - - if(b1 < 224) - { - S = ((b1-192) << 8) + b2 + 192 ; - return true; - } - - if(b1 != 0xff) - return false; - - if(offset + 3 >= data_size) return false; - - uint8_t b3 = data[offset++]; - uint8_t b4 = data[offset++]; - uint8_t b5 = data[offset++]; - - S = (b2 << 24) | (b3 << 16) | (b4 << 8) | b5 ; - return true; -} - -bool FileListIO::saveEncryptedDataToFile(const std::string& fname,const unsigned char *data,uint32_t total_size) -{ - void *encryptedData = NULL ; - int encDataLen = 0 ; - - if(!AuthSSL::getAuthSSL()->encrypt( encryptedData, encDataLen, data,total_size, AuthSSL::getAuthSSL()->OwnId())) - { - std::cerr << "Cannot encrypt encrypted file. Something's wrong." << std::endl; - return false; - } - - FILE *F = fopen( (fname+".tmp").c_str(),"wb" ) ; - - if(!F) - { - std::cerr << "Cannot open encrypted file for writing: " << fname+".tmp" << std::endl; - - free(encryptedData); - return false; - } - if(fwrite(encryptedData,1,encDataLen,F) != (uint32_t)encDataLen) - { - std::cerr << "Could not write entire encrypted file. Out of disc space??" << std::endl; - fclose(F) ; - - free(encryptedData); - return false; - } - - fclose(F) ; - - RsDirUtil::renameFile(fname+".tmp",fname) ; -#ifdef FIM_DEBUG - std::cerr << "done." << std::endl ; -#endif - - free(encryptedData); - return true; -} - -bool FileListIO::loadEncryptedDataFromFile(const std::string& fname,unsigned char *& data,uint32_t& total_size) -{ - uint64_t file_size ; - - if(!RsDirUtil::checkFile( fname,file_size,true ) ) - { -#ifdef FIM_DEBUG - std::cerr << "Encrypted file " << fname << " not available or empty." << std::endl; -#endif - return false; - } - - // read the binary stream into memory. - // - RsTemporaryMemory buffer(file_size) ; - - if(buffer == NULL) - return false; - - FILE *F = fopen( fname.c_str(),"rb") ; - if (!F) - { - std::cerr << "Cannot open encrypted file, filename " << fname << std::endl; - return false; - } - if(fread(buffer,1,file_size,F) != file_size) - { - std::cerr << "Cannot read from file " + fname << ": something's wrong." << std::endl; - fclose(F) ; - return false; - } - fclose(F) ; - - // now decrypt - void *decrypted_data =NULL; - int decrypted_data_size =0; - - if(!AuthSSL::getAuthSSL()->decrypt(decrypted_data, decrypted_data_size, buffer, file_size)) - { - std::cerr << "Cannot decrypt encrypted file. Something's wrong." << std::endl; - return false; - } - - data = (unsigned char*)decrypted_data ; - total_size = decrypted_data_size ; - - return true; -} diff --git a/libretroshare/src/file_sharing/filelist_io.h b/libretroshare/src/file_sharing/filelist_io.h deleted file mode 100644 index 65863ffd0..000000000 --- a/libretroshare/src/file_sharing/filelist_io.h +++ /dev/null @@ -1,167 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: filelist_io.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "util/rsmemory.h" - -// This file implements load/save of various fields used for file lists and directory content. -// WARNING: the encoding is system-dependent, so this should *not* be used to exchange data between computers. - -static const uint32_t FILE_LIST_IO_LOCAL_DIRECTORY_STORAGE_VERSION_0001 = 0x00000001 ; -static const uint32_t FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001 = 0x00010001 ; - -static const uint8_t FILE_LIST_IO_TAG_UNKNOWN = 0x00 ; -static const uint8_t FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION = 0x01 ; - -static const uint8_t FILE_LIST_IO_TAG_HASH_STORAGE_ENTRY = 0x10 ; -static const uint8_t FILE_LIST_IO_TAG_LOCAL_FILE_ENTRY = 0x11 ; -static const uint8_t FILE_LIST_IO_TAG_LOCAL_DIR_ENTRY = 0x12 ; -static const uint8_t FILE_LIST_IO_TAG_REMOTE_FILE_ENTRY = 0x13 ; - -static const uint8_t FILE_LIST_IO_TAG_FILE_SHA1_HASH = 0x20 ; -static const uint8_t FILE_LIST_IO_TAG_FILE_NAME = 0x21 ; -static const uint8_t FILE_LIST_IO_TAG_FILE_SIZE = 0x22 ; - -static const uint8_t FILE_LIST_IO_TAG_MODIF_TS = 0x30 ; -static const uint8_t FILE_LIST_IO_TAG_RECURS_MODIF_TS = 0x31 ; -static const uint8_t FILE_LIST_IO_TAG_UPDATE_TS = 0x32 ; - -static const uint8_t FILE_LIST_IO_TAG_ENTRY_INDEX = 0x40 ; -static const uint8_t FILE_LIST_IO_TAG_PARENT_INDEX = 0x41 ; - -static const uint8_t FILE_LIST_IO_TAG_DIR_HASH = 0x50 ; -static const uint8_t FILE_LIST_IO_TAG_DIR_NAME = 0x51 ; - -static const uint8_t FILE_LIST_IO_TAG_ROW = 0x60 ; -static const uint8_t FILE_LIST_IO_TAG_BINARY_DATA = 0x61 ; -static const uint8_t FILE_LIST_IO_TAG_RAW_NUMBER = 0x62 ; - -static const uint32_t SECTION_HEADER_MAX_SIZE = 6 ; // section tag (1 byte) + size (max = 5 bytes) - - -class FileListIO -{ -public: - template - static bool writeField(unsigned char *& buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,const T& val) - { - uint32_t s = serial_size(val) ; - - if(!checkSectionSize(buff,buff_size,offset,s)) - return false; - - if(!writeSectionHeader(buff,buff_size,offset,section_tag,s)) - return false; - - return serialise(buff,buff_size,offset,val) ; - } - - template - static bool readField(const unsigned char *buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag,T& val) - { - uint32_t section_size ; - - if(!readSectionHeader(buff,buff_size,offset,check_section_tag,section_size)) - return false; - - return deserialise(buff,buff_size,offset,val); - } - - class read_error - { - public: - read_error(unsigned char *sec,uint32_t size,uint32_t offset,uint8_t expected_tag); - read_error(const std::string& s) : err_string(s) {} - - const std::string& what() const { return err_string ; } - private: - std::string err_string ; - }; - - - static bool writeField( unsigned char*&buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,const unsigned char * val,uint32_t size) ; - static bool readField (const unsigned char *buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag, unsigned char *& val,uint32_t& size) ; - - template static bool serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const T& val) ; - template static bool deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,T& val) ; - template static uint32_t serial_size(const T& val) ; - - static bool saveEncryptedDataToFile(const std::string& fname,const unsigned char *data,uint32_t total_size); - static bool loadEncryptedDataFromFile(const std::string& fname,unsigned char *& data,uint32_t& total_size); - -private: - static bool write125Size(unsigned char *data,uint32_t total_size,uint32_t& offset,uint32_t size) ; - static bool read125Size (const unsigned char *data,uint32_t total_size,uint32_t& offset,uint32_t& size) ; - - static bool checkSectionSize(unsigned char *& buff,uint32_t& buff_size,uint32_t offset,uint32_t S) - { - // This tests avoids an infinite loop when growing new size - - if(offset + S + SECTION_HEADER_MAX_SIZE > 0x8fffffff) - return false ; - - if(offset + S + SECTION_HEADER_MAX_SIZE > buff_size) - { - uint32_t new_size = (buff_size == 0)?512:buff_size ; - - while(new_size < offset + S + SECTION_HEADER_MAX_SIZE) - new_size <<= 1 ; - - buff = (unsigned char *)realloc(buff,new_size) ; - - if(!buff) - { - buff_size = 0 ; - return false ; - } - buff_size = new_size ; - } - return true ; - } - - static bool writeSectionHeader(unsigned char *& buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,uint32_t S) - { - buff[offset++] = section_tag ; - if(!write125Size(buff,buff_size,offset,S)) return false ; - - return true; - } - - static bool readSectionHeader(const unsigned char *& buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag,uint32_t& S) - { - if(offset + 1 > buff_size) - return false ; - - uint8_t section_tag = buff[offset] ; // we do the offset++ after, only if the header can be read. Doing so, we can make multiple read attempts. - - if(section_tag != check_section_tag) - return false; - - offset++ ; - - return read125Size(buff,buff_size,offset,S) ; - } -}; diff --git a/libretroshare/src/file_sharing/hash_cache.cc b/libretroshare/src/file_sharing/hash_cache.cc deleted file mode 100644 index 331f1a481..000000000 --- a/libretroshare/src/file_sharing/hash_cache.cc +++ /dev/null @@ -1,606 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: hash_cache.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ -#include "util/rsdir.h" -#include "util/rsprint.h" -#include "util/rstime.h" -#include "rsserver/p3face.h" -#include "pqi/authssl.h" -#include "hash_cache.h" -#include "filelist_io.h" -#include "file_sharing_defaults.h" -#include "retroshare/rsinit.h" - -//#define HASHSTORAGE_DEBUG 1 - -static const uint32_t DEFAULT_INACTIVITY_SLEEP_TIME = 50*1000; -static const uint32_t MAX_INACTIVITY_SLEEP_TIME = 2*1000*1000; - -HashStorage::HashStorage(const std::string& save_file_name) - : mFilePath(save_file_name), mHashMtx("Hash Storage mutex") -{ - mInactivitySleepTime = DEFAULT_INACTIVITY_SLEEP_TIME; - mRunning = false ; - mLastSaveTime = 0 ; - mTotalSizeToHash = 0; - mTotalFilesToHash = 0; - mCurrentHashingSpeed = 0 ; - mMaxStorageDurationDays = DEFAULT_HASH_STORAGE_DURATION_DAYS ; - mHashingProcessPaused = false; - mHashedBytes = 0 ; - mHashingTime = 0 ; - - { - RS_STACK_MUTEX(mHashMtx) ; - - if(!locked_load()) - try_load_import_old_hash_cache(); - } -} - -void HashStorage::togglePauseHashingProcess() -{ - RS_STACK_MUTEX(mHashMtx) ; - mHashingProcessPaused = !mHashingProcessPaused ; -} -bool HashStorage::hashingProcessPaused() -{ - RS_STACK_MUTEX(mHashMtx) ; - return mHashingProcessPaused; -} - -static std::string friendlyUnit(uint64_t val) -{ - const std::string units[6] = {"B","KB","MB","GB","TB","PB"}; - char buf[50] ; - - double fact = 1.0 ; - - for(unsigned int i=0; i<6; ++i) - if(double(val)/fact < 1024.0) - { - sprintf(buf,"%2.2f",double(val)/fact) ; - return std::string(buf) + " " + units[i]; - } - else - fact *= 1024.0f ; - - sprintf(buf,"%2.2f",double(val)/fact*1024.0f) ; - return std::string(buf) + " TB"; -} - -void HashStorage::threadTick() -{ - FileHashJob job; - RsFileHash hash; - uint64_t size = 0; - - - { - bool empty ; - uint32_t st ; - - { - RS_STACK_MUTEX(mHashMtx) ; - - if(mChanged && mLastSaveTime + MIN_INTERVAL_BETWEEN_HASH_CACHE_SAVE < time(NULL)) - { - locked_save(); - mLastSaveTime = time(NULL) ; - mChanged = false ; - } - } - - { - RS_STACK_MUTEX(mHashMtx) ; - - empty = mFilesToHash.empty(); - st = mInactivitySleepTime ; - } - - // sleep off mutex! - if(empty) - { -#ifdef HASHSTORAGE_DEBUG - std::cerr << "nothing to hash. Sleeping for " << st << " us" << std::endl; -#endif - - rstime::rs_usleep(st); // when no files to hash, just wait for 2 secs. This avoids a dramatic loop. - - if(st > MAX_INACTIVITY_SLEEP_TIME) - { - RS_STACK_MUTEX(mHashMtx) ; - - mInactivitySleepTime = MAX_INACTIVITY_SLEEP_TIME; - - if(!mChanged) // otherwise it might prevent from saving the hash cache - { - stopHashThread(); - } - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mEventCode = RsSharedDirectoriesEventCode::DIRECTORY_SWEEP_ENDED; - rsEvents->postEvent(ev); - } - //RsServer::notify()->notifyHashingInfo(NOTIFY_HASHTYPE_FINISH, "") ; - } - else - { - RS_STACK_MUTEX(mHashMtx) ; - mInactivitySleepTime = 2*st ; - } - - return ; - } - mInactivitySleepTime = DEFAULT_INACTIVITY_SLEEP_TIME; - - bool paused = false ; - { - RS_STACK_MUTEX(mHashMtx) ; - paused = mHashingProcessPaused ; - } - - if(paused) // we need to wait off mutex!! - { - rstime::rs_usleep(MAX_INACTIVITY_SLEEP_TIME) ; - std::cerr << "Hashing process currently paused." << std::endl; - return; - } - else - { - RS_STACK_MUTEX(mHashMtx) ; - - job = mFilesToHash.begin()->second ; - mFilesToHash.erase(mFilesToHash.begin()) ; - } - - if(job.client->hash_confirm(job.client_param)) - { -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Hashing file " << job.full_path << "..." ; std::cerr.flush(); -#endif - - std::string tmpout; - - if(mCurrentHashingSpeed > 0) - rs_sprintf(tmpout, "%lu/%lu (%s - %d%%, %d MB/s) : %s", (unsigned long int)mHashCounter+1, (unsigned long int)mTotalFilesToHash, friendlyUnit(mTotalHashedSize).c_str(), int(mTotalHashedSize/double(mTotalSizeToHash)*100.0), mCurrentHashingSpeed,job.full_path.c_str()) ; - else - rs_sprintf(tmpout, "%lu/%lu (%s - %d%%) : %s", (unsigned long int)mHashCounter+1, (unsigned long int)mTotalFilesToHash, friendlyUnit(mTotalHashedSize).c_str(), int(mTotalHashedSize/double(mTotalSizeToHash)*100.0), job.full_path.c_str()) ; - - //RsServer::notify()->notifyHashingInfo(NOTIFY_HASHTYPE_HASH_FILE, tmpout) ; - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mEventCode = RsSharedDirectoriesEventCode::HASHING_FILE; - ev->mMessage = tmpout; - rsEvents->postEvent(ev); - } - - double seconds_origin = rstime::RsScopeTimer::currentTime() ; - - if(RsDirUtil::getFileHash(job.full_path, hash,size, this)) - { - // store the result - -#ifdef HASHSTORAGE_DEBUG - std::cerr << "done."<< std::endl; -#endif - - RS_STACK_MUTEX(mHashMtx) ; - HashStorageInfo& info(mFiles[job.real_path]); - - info.filename = job.real_path ; - info.size = size ; - info.modf_stamp = job.ts ; - info.time_stamp = time(NULL); - info.hash = hash; - - mChanged = true ; - mTotalHashedSize += size ; - } - else - std::cerr << "ERROR: cannot hash file " << job.full_path << std::endl; - - mHashingTime += rstime::RsScopeTimer::currentTime() - seconds_origin ; - mHashedBytes += size ; - - if(mHashingTime > 3) - { - mCurrentHashingSpeed = (int)(mHashedBytes / mHashingTime ) / (1024*1024) ; - mHashingTime = 0 ; - mHashedBytes = 0 ; - } - - ++mHashCounter ; - } - } - // call the client - - if(!hash.isNull()) - job.client->hash_callback(job.client_param, job.full_path, hash, size); -} - -bool HashStorage::requestHash(const std::string& full_path,uint64_t size,rstime_t mod_time,RsFileHash& known_hash,HashStorageClient *c,uint32_t client_param) -{ - // check if the hash is up to date w.r.t. cache. - -#ifdef HASHSTORAGE_DEBUG - std::cerr << "HASH Requested for file " << full_path << ": mod_time: " << mod_time << ", size: " << size << " :" ; -#endif - RS_STACK_MUTEX(mHashMtx) ; - - std::string real_path = RsDirUtil::removeSymLinks(full_path) ; - - rstime_t now = time(NULL) ; - std::map::iterator it = mFiles.find(real_path) ; - - // On windows we compare the time up to +/- 3600 seconds. This avoids re-hashing files in case of daylight saving change. - // - // See: - // https://support.microsoft.com/en-us/kb/190315 - // - if(it != mFiles.end() -#ifdef WINDOWS_SYS - && ( (uint64_t)mod_time == it->second.modf_stamp || (uint64_t)mod_time+3600 == it->second.modf_stamp ||(uint64_t)mod_time == it->second.modf_stamp+3600) -#else - && (uint64_t)mod_time == it->second.modf_stamp -#endif - && size == it->second.size) - { - it->second.time_stamp = now ; - -#ifdef WINDOWS_SYS - if(it->second.modf_stamp != (uint64_t)mod_time) - { - std::cerr << "(WW) detected a 1 hour shift in file modification time. This normally happens to many files at once, when daylight saving time shifts (file=\"" << full_path << "\")." << std::endl; - it->second.modf_stamp = (uint64_t)mod_time; - mChanged = true; - startHashThread(); - } -#endif - - known_hash = it->second.hash; -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Found in cache." << std::endl ; -#endif - return true ; - } -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Not in cache. Scheduling for re-hash." << std::endl ; -#endif - - // we need to schedule a re-hashing - - if(mFilesToHash.find(real_path) != mFilesToHash.end()) - return false ; - - FileHashJob job ; - - job.client = c ; - job.size = size ; - job.client_param = client_param ; - job.full_path = full_path ; - job.real_path = real_path ; - job.ts = mod_time ; - - // We store the files indexed by their real path, so that we allow to not re-hash files that are pointed multiple times through the directory links - // The client will be notified with the full path instead of the real path. - - mFilesToHash[real_path] = job; - - mTotalSizeToHash += size ; - ++mTotalFilesToHash; - - startHashThread(); - - return false; -} - -void HashStorage::startHashThread() -{ - if(!mRunning) - { - mRunning = true ; - std::cerr << "Starting hashing thread." << std::endl; - mHashCounter = 0; - mTotalHashedSize = 0; - - start("fs hash cache") ; - } -} - -void HashStorage::stopHashThread() -{ - if(mRunning) - { - RsInfo() << __PRETTY_FUNCTION__ << "Stopping hashing thread." - << std::endl; - - RsThread::askForStop(); - mRunning = false ; - mTotalSizeToHash = 0; - mTotalFilesToHash = 0; - } -} - -void HashStorage::clean() -{ - RS_STACK_MUTEX(mHashMtx) ; - - rstime_t now = time(NULL) ; - rstime_t duration = mMaxStorageDurationDays * 24 * 3600 ; // seconds - -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Cleaning hash cache." << std::endl ; -#endif - - for(std::map::iterator it(mFiles.begin());it!=mFiles.end();) - if((uint64_t)(it->second.time_stamp + duration) < (uint64_t)now) - { -#ifdef HASHSTORAGE_DEBUG - std::cerr << " Entry too old: " << it->first << ", ts=" << it->second.time_stamp << std::endl ; -#endif - std::map::iterator tmp(it) ; - ++tmp ; - mFiles.erase(it) ; - it=tmp ; - mChanged = true ; - } - else - ++it ; - -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Done." << std::endl; -#endif -} - -bool HashStorage::locked_load() -{ - unsigned char *data = NULL ; - uint32_t data_size=0; - - if(!FileListIO::loadEncryptedDataFromFile(mFilePath,data,data_size)) - { - std::cerr << "(EE) Cannot read hash cache." << std::endl; - return false; - } - uint32_t offset = 0 ; - HashStorageInfo info ; -#ifdef HASHSTORAGE_DEBUG - uint32_t n=0; -#endif - - while(offset < data_size) - if(readHashStorageInfo(data,data_size,offset,info)) - { -#ifdef HASHSTORAGE_DEBUG - std::cerr << info << std::endl; - ++n ; -#endif - mFiles[info.filename] = info ; - } - - free(data) ; -#ifdef HASHSTORAGE_DEBUG - std::cerr << n << " entries loaded." << std::endl ; -#endif - return true ; -} - -void HashStorage::locked_save() -{ -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Saving Hash Cache to file " << mFilePath << "..." << std::endl ; -#endif - - unsigned char *data = NULL ; - uint32_t offset = 0 ; - uint32_t total_size = 0; - - for(std::map::const_iterator it(mFiles.begin());it!=mFiles.end();++it) - writeHashStorageInfo(data,total_size,offset,it->second) ; - - if(!FileListIO::saveEncryptedDataToFile(mFilePath,data,offset)) - { - std::cerr << "(EE) Cannot save hash cache data." << std::endl; - free(data) ; - return ; - } - - std::cerr << mFiles.size() << " entries saved in hash cache." << std::endl; - - free(data) ; -} - -bool HashStorage::readHashStorageInfo(const unsigned char *data,uint32_t total_size,uint32_t& offset,HashStorageInfo& info) const -{ - unsigned char *section_data = (unsigned char *)rs_malloc(FL_BASE_TMP_SECTION_SIZE) ; - - if(!section_data) - return false ; - - uint32_t section_size = FL_BASE_TMP_SECTION_SIZE; - uint32_t section_offset = 0; - - // This way, the entire section is either read or skipped. That avoids the risk of being stuck somewhere in the middle - // of a section because of some unknown field, etc. - - if(!FileListIO::readField(data,total_size,offset,FILE_LIST_IO_TAG_HASH_STORAGE_ENTRY,section_data,section_size)) - { - free(section_data); - return false; - } - - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_NAME ,info.filename )) { free(section_data); return false ; } - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,info.size )) { free(section_data); return false ; } - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_UPDATE_TS ,info.time_stamp)) { free(section_data); return false ; } - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_MODIF_TS ,info.modf_stamp)) { free(section_data); return false ; } - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,info.hash )) { free(section_data); return false ; } - - free(section_data); - return true; -} - -bool HashStorage::writeHashStorageInfo(unsigned char *& data,uint32_t& total_size,uint32_t& offset,const HashStorageInfo& info) const -{ - unsigned char *section_data = (unsigned char *)rs_malloc(FL_BASE_TMP_SECTION_SIZE) ; - - if(!section_data) - return false ; - - uint32_t section_offset = 0 ; - uint32_t section_size = FL_BASE_TMP_SECTION_SIZE; - - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_NAME ,info.filename )) { free(section_data); return false ; } - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,info.size )) { free(section_data); return false ; } - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_UPDATE_TS ,info.time_stamp)) { free(section_data); return false ; } - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_MODIF_TS ,info.modf_stamp)) { free(section_data); return false ; } - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,info.hash )) { free(section_data); return false ; } - - // now write the whole string into a single section in the file - - if(!FileListIO::writeField(data,total_size,offset,FILE_LIST_IO_TAG_HASH_STORAGE_ENTRY,section_data,section_offset)) return false ; -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Writing hash storage section " << RsUtil::BinToHex(section_data,section_offset) << std::endl; - std::cerr << "Info.filename = " << info.filename << std::endl; -#endif - free(section_data) ; - - return true; -} - -std::ostream& operator<<(std::ostream& o,const HashStorage::HashStorageInfo& info) -{ - return o << info.hash << " " << info.modf_stamp << " " << info.size << " " << info.filename ; -} - -/********************************************************************************************************************************/ -/* 09/26/2016 */ -/* This method should be removed in a few months. It only helps importing the old hash cache in order to */ -/* spare the re-hashing of everything. If successful, it also renames the old hash cache into a new name so that */ -/* the file is not found at the next attempt. */ -/********************************************************************************************************************************/ -// -#include "rsserver/rsaccounts.h" -#include - -bool HashStorage::try_load_import_old_hash_cache() -{ - // compute file name - - std::string base_dir = RsAccounts::AccountDirectory(); - std::string old_cache_filename = base_dir + "/" + "file_cache.bin" ; - - // check for unencrypted - - std::istream *f = NULL ; - uint64_t file_size ; - - if(RsDirUtil::checkFile( old_cache_filename,file_size,false ) ) - { - std::cerr << "Encrypted hash cache file present. Reading it." << std::endl; - - // read the binary stream into memory. - // - RsTemporaryMemory buffer(file_size) ; - - if(buffer == NULL) - return false; - - FILE *F = fopen( old_cache_filename.c_str(),"rb") ; - if (!F) - { - std::cerr << "Cannot open file for reading encrypted file cache, filename " << old_cache_filename << std::endl; - return false; - } - if(fread(buffer,1,file_size,F) != file_size) - { - std::cerr << "Cannot read from file " << old_cache_filename << ": something's wrong." << std::endl; - fclose(F) ; - return false; - } - fclose(F) ; - - void *decrypted_data =NULL; - int decrypted_data_size =0; - - if(!AuthSSL::getAuthSSL()->decrypt(decrypted_data, decrypted_data_size, buffer, file_size)) - { - std::cerr << "Cannot decrypt encrypted file cache. Something's wrong." << std::endl; - return false; - } - std::string s((char *)decrypted_data,decrypted_data_size) ; - f = new std::istringstream(s) ; - - free(decrypted_data) ; - } - else - return false; - - std::streamsize max_line_size = 2000 ; // should be enough. Anyway, if we - // miss one entry, we just lose some - // cache itemsn but this is not too - // much of a problem. - char *buff = new char[max_line_size] ; - - std::cerr << "Importing hashCache from file " << old_cache_filename << std::endl ; - int n=0 ; - - std::map tmp_files ; // stored as (full_path, hash_info) - - while(!f->eof()) - { - HashStorageInfo info ; - - f->getline(buff,max_line_size,'\n') ; - info.filename = std::string(buff) ; - - f->getline(buff,max_line_size,'\n') ; //if(sscanf(buff,"%llu",&info.size) != 1) break ; - - info.size = 0 ; - sscanf(buff, RsDirUtil::scanf_string_for_uint(sizeof(info.size)), &info.size); - - f->getline(buff,max_line_size,'\n') ; if(sscanf(buff,RsDirUtil::scanf_string_for_uint(sizeof(info.time_stamp)),&info.time_stamp) != 1) { std::cerr << "Could not read one entry! Giving up." << std::endl; break ; } - f->getline(buff,max_line_size,'\n') ; if(sscanf(buff,RsDirUtil::scanf_string_for_uint(sizeof(info.modf_stamp)),&info.modf_stamp) != 1) { std::cerr << "Could not read one entry! Giving up." << std::endl; break ; } - f->getline(buff,max_line_size,'\n') ; info.hash = RsFileHash(std::string(buff)) ; - - std::cerr << " (" << info.filename << ", " << info.size << ", " << info.time_stamp << ", " << info.modf_stamp << ", " << info.hash << std::endl ; - ++n ; - - tmp_files[info.filename] = info ; - } - - delete[] buff ; - delete f ; - - std::cerr << "(II) Successfully imported hash cache from file " << old_cache_filename << " for a total of " << n << " entries." << std::endl; - std::cerr << "(II) This file is now obsolete, and will be renamed " << old_cache_filename + ".bak" << " in case you needed it. But you can safely remove it." << std::endl; - - RsDirUtil::renameFile(old_cache_filename,old_cache_filename+".bak") ; - - mFiles = tmp_files ; - locked_save() ; // this is called explicitly here because the ticking thread is not active. - - return true; -} -/********************************************************************************************************************************/ diff --git a/libretroshare/src/file_sharing/hash_cache.h b/libretroshare/src/file_sharing/hash_cache.h deleted file mode 100644 index 6fbb9ae5c..000000000 --- a/libretroshare/src/file_sharing/hash_cache.h +++ /dev/null @@ -1,149 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: hash_cache.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ - - -#pragma once - -#include -#include "util/rsthreads.h" -#include "retroshare/rsfiles.h" -#include "util/rstime.h" - -/*! - * \brief The HashStorageClient class - * Used by clients of the hash cache for receiving hash results when done. This is asynchrone of course since hashing - * might be quite costly. - */ -class HashStorageClient -{ -public: - HashStorageClient() {} - virtual ~HashStorageClient() {} - - // the result of the hashing info is sent to this method - - virtual void hash_callback(uint32_t client_param, const std::string& name, const RsFileHash& hash, uint64_t size)=0; - - // this method is used to check that the client param is still valid just before hashing. This avoids hashing files - // that are still in queue while removed from shared lists. - - virtual bool hash_confirm(uint32_t client_param)=0 ; -}; - -class HashStorage: public RsTickingThread -{ -public: - explicit HashStorage(const std::string& save_file_name) ; - - /*! - * \brief requestHash Requests the hash for the given file, assuming size and mod_time are the same. - * - * \param full_path Full path to reach the file - * \param size Actual file size - * \param mod_time Actual file modification time - * \param known_hash Returned hash for the file. - * \param c Hash cache client to which the hash should be sent once calculated - * \param client_param Param to be passed to the client callback. Useful if the client needs a file ID. - * - * \return true if the supplied hash info is up to date. - */ - bool requestHash(const std::string& full_path, uint64_t size, rstime_t mod_time, RsFileHash& known_hash, HashStorageClient *c, uint32_t client_param) ; - - struct HashStorageInfo - { - std::string filename ; // full path of the file - uint64_t size ; - uint32_t time_stamp ; // last time the hash was tested/requested - uint32_t modf_stamp ; - RsFileHash hash ; - } ; - - // interaction with GUI, called from p3FileLists - void setRememberHashFilesDuration(uint32_t days) { mMaxStorageDurationDays = days ; } // duration for which the hash is kept even if the file is not shared anymore - uint32_t rememberHashFilesDuration() const { return mMaxStorageDurationDays ; } - void clear() { mFiles.clear(); mChanged=true; } // drop all known hashes. Not something to do, except if you want to rehash the entire database - bool empty() const { return mFiles.empty() ; } - void togglePauseHashingProcess() ; - bool hashingProcessPaused(); - - void threadTick() override; /// @see RsTickingThread - - friend std::ostream& operator<<(std::ostream& o,const HashStorageInfo& info) ; -private: - /*! - * \brief clean - * This function is responsible for removing old hashes, etc - */ - void clean() ; - - void startHashThread(); - void stopHashThread(); - - // loading/saving the entire hash database to a file - - void locked_save() ; - bool locked_load() ; - bool try_load_import_old_hash_cache(); - - bool readHashStorageInfo(const unsigned char *data,uint32_t total_size,uint32_t& offset,HashStorageInfo& info) const; - bool writeHashStorageInfo(unsigned char *& data,uint32_t& total_size,uint32_t& offset,const HashStorageInfo& info) const; - - // Local configuration and storage - - uint32_t mMaxStorageDurationDays ; // maximum duration of un-requested cache entries - std::map mFiles ; // stored as (full_path, hash_info) - std::string mFilePath ; // file where the hash database is stored - bool mChanged ; - bool mHashingProcessPaused ; - - struct FileHashJob - { - std::string full_path; // canonicalized file name (means: symlinks removed, loops removed, etc) - std::string real_path; // path supplied by the client. - uint64_t size ; - HashStorageClient *client; - uint32_t client_param ; - rstime_t ts; - }; - - // current work - - std::map mFilesToHash ; - - // thread/mutex stuff - - RsMutex mHashMtx ; - bool mRunning; - uint64_t mHashCounter; - uint32_t mInactivitySleepTime ; - uint64_t mTotalSizeToHash ; - uint64_t mTotalHashedSize ; - uint64_t mTotalFilesToHash ; - rstime_t mLastSaveTime ; - - // The following is used to estimate hashing speed. - - double mHashingTime ; - uint64_t mHashedBytes ; - uint32_t mCurrentHashingSpeed ; // in MB/s -}; - diff --git a/libretroshare/src/file_sharing/p3filelists.cc b/libretroshare/src/file_sharing/p3filelists.cc deleted file mode 100644 index 6eb3899e2..000000000 --- a/libretroshare/src/file_sharing/p3filelists.cc +++ /dev/null @@ -1,2285 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: p3filelists.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ -#include "rsitems/rsserviceids.h" - -#include "file_sharing/p3filelists.h" -#include "file_sharing/directory_storage.h" -#include "file_sharing/directory_updater.h" -#include "file_sharing/rsfilelistitems.h" -#include "file_sharing/file_sharing_defaults.h" - -#include "retroshare/rsids.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsinit.h" - -#include "rsserver/p3face.h" - -#define P3FILELISTS_DEBUG() std::cerr << time(NULL) << " : FILE_LISTS : " << __FUNCTION__ << " : " -#define P3FILELISTS_ERROR() std::cerr << "***ERROR***" << " : FILE_LISTS : " << __FUNCTION__ << " : " - -//#define DEBUG_P3FILELISTS 1 -//#define DEBUG_CONTENT_FILTERING 1 -//#define DEBUG_FILE_HIERARCHY 1 - -static const uint32_t P3FILELISTS_UPDATE_FLAG_NOTHING_CHANGED = 0x0000 ; -static const uint32_t P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED = 0x0001 ; -static const uint32_t P3FILELISTS_UPDATE_FLAG_LOCAL_DIRS_CHANGED = 0x0002 ; -static const uint32_t P3FILELISTS_UPDATE_FLAG_REMOTE_DIRS_CHANGED = 0x0004 ; - -p3FileDatabase::p3FileDatabase(p3ServiceControl *mpeers) - : mServCtrl(mpeers), mFLSMtx("p3FileLists") -{ - // make sure the base directory exists - - std::string base_dir = RsAccounts::AccountDirectory(); - - if(base_dir.empty()) - throw std::runtime_error("Cannot create base directory to store/access file sharing files.") ; - - mFileSharingDir = base_dir + "/" + FILE_SHARING_DIR_NAME ; - - if(!RsDirUtil::checkCreateDirectory(mFileSharingDir)) - throw std::runtime_error("Cannot create base directory to store/access file sharing files.") ; - - // loads existing indexes for friends. Some might be already present here. - // - mRemoteDirectories.clear() ; // we should load them! - mOwnId = mpeers->getOwnId() ; - - mBannedFileListNeedsUpdate = false; - mLocalSharedDirs = new LocalDirectoryStorage(mFileSharingDir + "/" + LOCAL_SHARED_DIRS_FILE_NAME,mOwnId); - mHashCache = new HashStorage(mFileSharingDir + "/" + HASH_CACHE_FILE_NAME) ; - - mLocalDirWatcher = new LocalDirectoryUpdater(mHashCache,mLocalSharedDirs) ; - - mUpdateFlags = P3FILELISTS_UPDATE_FLAG_NOTHING_CHANGED ; - mLastRemoteDirSweepTS = 0 ; - mLastExtraFilesCacheUpdate = 0; - mLastCleanupTime = 0 ; - mLastDataRecvTS = 0 ; - mTrustFriendNodesForBannedFiles = TRUST_FRIEND_NODES_FOR_BANNED_FILES_DEFAULT; - mLastPrimaryBanListChangeTimeStamp = 0; - - // This is for the transmission of data - - addSerialType(new RsFileListsSerialiser()) ; -} - -void p3FileDatabase::setIgnoreLists(const std::list& ignored_prefixes,const std::list& ignored_suffixes, uint32_t ignore_flags) -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalDirWatcher->setIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ; - - IndicateConfigChanged(); -} -bool p3FileDatabase::getIgnoreLists(std::list& ignored_prefixes,std::list& ignored_suffixes, uint32_t& ignore_flags) -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->getIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ; -} - -RsSerialiser *p3FileDatabase::setupSerialiser() -{ - // This one is for saveList/loadList - - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsFileListsSerialiser()) ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - rss->addSerialType(new RsFileConfigSerialiser()); - - return rss ; -} -void p3FileDatabase::setSharedDirectories(const std::list& shared_dirs) -{ - { - RS_STACK_MUTEX(mFLSMtx) ; - - mLocalSharedDirs->setSharedDirectoryList(shared_dirs) ; - mLocalDirWatcher->forceUpdate(false); - - } - - IndicateConfigChanged(); -} -void p3FileDatabase::getSharedDirectories(std::list& shared_dirs) -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalSharedDirs->getSharedDirectoryList(shared_dirs) ; -} -void p3FileDatabase::updateShareFlags(const SharedDirInfo& info) -{ - { - RS_STACK_MUTEX(mFLSMtx) ; - mLocalSharedDirs->updateShareFlags(info) ; - } - - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); - IndicateConfigChanged(); -} - -p3FileDatabase::~p3FileDatabase() -{ - RS_STACK_MUTEX(mFLSMtx) ; - - for(uint32_t i=0;iprint(); -#endif - last_print_time = now ; - } - -#warning mr-alice 2016-08-19: "This should be removed, but it's necessary atm for updating the GUI" - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); - - checkSendBannedFilesInfo(); - } - - if(mUpdateFlags) - { - IndicateConfigChanged(); - - if(mUpdateFlags & P3FILELISTS_UPDATE_FLAG_LOCAL_DIRS_CHANGED) - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); - - if(mUpdateFlags & P3FILELISTS_UPDATE_FLAG_REMOTE_DIRS_CHANGED) - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_FRIENDS, 0); - - mUpdateFlags = P3FILELISTS_UPDATE_FLAG_NOTHING_CHANGED ; - } - - if(mLastRemoteDirSweepTS + 5 < now) - { - RS_STACK_MUTEX(mFLSMtx) ; - - std::set online_peers ; - mServCtrl->getPeersConnected(getServiceInfo().mServiceType, online_peers) ; - - for(uint32_t i=0;ipeerId()) != online_peers.end() && mRemoteDirectories[i]->lastSweepTime() + DELAY_BETWEEN_REMOTE_DIRECTORIES_SWEEP < now) - { -#ifdef DEBUG_FILE_HIERARCHY - P3FILELISTS_DEBUG() << "Launching recurs sweep of friend directory " << mRemoteDirectories[i]->peerId() << ". Content currently is:" << std::endl; - mRemoteDirectories[i]->print(); -#endif - - locked_recursSweepRemoteDirectory(mRemoteDirectories[i],mRemoteDirectories[i]->root(),0) ; - mRemoteDirectories[i]->lastSweepTime() = now ; - } - - mRemoteDirectories[i]->checkSave() ; - } - - mLastRemoteDirSweepTS = now; - mLocalSharedDirs->checkSave() ; - - // This is a hack to make loaded directories show up in the GUI, because the GUI generally isn't ready at the time they are actually loaded up, - // so the first notify is ignored, and no other notify will happen next. We only do it if no data was received in the last 5 secs, in order to - // avoid syncing the GUI at every dir sync which kills performance. - - if(mLastDataRecvTS + 5 < now && mLastDataRecvTS + 20 > now) - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_FRIENDS, 0); // notify the GUI if the hierarchy has changed - } - - return 0; -} - -void p3FileDatabase::startThreads() -{ - RS_STACK_MUTEX(mFLSMtx) ; -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Starting directory watcher thread..." ; -#endif - mLocalDirWatcher->start("fs dir watcher"); -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Done." << std::endl; -#endif -} -void p3FileDatabase::stopThreads() -{ - RS_STACK_MUTEX(mFLSMtx) ; -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Stopping hash cache thread..." ; std::cerr.flush() ; -#endif - mHashCache->fullstop(); -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Done." << std::endl; - P3FILELISTS_DEBUG() << "Stopping directory watcher thread..." ; std::cerr.flush() ; -#endif - mLocalDirWatcher->fullstop(); -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Done." << std::endl; -#endif -} - -bool p3FileDatabase::saveList(bool &cleanup, std::list& sList) -{ -cleanup = true; - -#ifdef DEBUG_FILE_HIERARCHY - P3FILELISTS_DEBUG() << "Save list" << std::endl; -#endif - - /* get list of directories */ - std::list dirList; - { - RS_STACK_MUTEX(mFLSMtx) ; - mLocalSharedDirs->getSharedDirectoryList(dirList); - } - - { - RS_STACK_MUTEX(mFLSMtx) ; - for(std::list::iterator it = dirList.begin(); it != dirList.end(); ++it) - { - RsFileConfigItem *fi = new RsFileConfigItem(); - - fi->file.path = (*it).filename ; - fi->file.name = (*it).virtualname ; - fi->flags = (*it).shareflags.toUInt32() ; - - for(std::list::const_iterator it2( (*it).parent_groups.begin());it2!=(*it).parent_groups.end();++it2) - fi->parent_groups.ids.insert(*it2) ; - - sList.push_back(fi); - } - } - - { - RS_STACK_MUTEX(mFLSMtx) ; - - RsFileListsBannedHashesConfigItem *item = new RsFileListsBannedHashesConfigItem ; - - item->primary_banned_files_list = mPrimaryBanList; - sList.push_back(item) ; - } - - RsConfigKeyValueSet *rskv = new RsConfigKeyValueSet(); - - /* basic control parameters */ - { - RS_STACK_MUTEX(mFLSMtx) ; - std::string s ; - rs_sprintf(s, "%lu", mHashCache->rememberHashFilesDuration()) ; - - RsTlvKeyValue kv; - - kv.key = HASH_CACHE_DURATION_SS; - kv.value = s ; - - rskv->tlvkvs.pairs.push_back(kv); - } - - { - std::string s ; - rs_sprintf(s, "%d", watchPeriod()) ; - - RsTlvKeyValue kv; - - kv.key = WATCH_FILE_DURATION_SS; - kv.value = s ; - - rskv->tlvkvs.pairs.push_back(kv); - } - { - std::string s ; - rs_sprintf(s, "%d", maxShareDepth()) ; - - RsTlvKeyValue kv; - - kv.key = MAX_SHARE_DEPTH; - kv.value = s ; - - rskv->tlvkvs.pairs.push_back(kv); - } - { - RsTlvKeyValue kv; - - kv.key = FOLLOW_SYMLINKS_SS; - kv.value = followSymLinks()?"YES":"NO" ; - - rskv->tlvkvs.pairs.push_back(kv); - } - { - RsTlvKeyValue kv; - - kv.key = IGNORE_DUPLICATES; - kv.value = ignoreDuplicates()?"YES":"NO" ; - - rskv->tlvkvs.pairs.push_back(kv); - } - { - RsTlvKeyValue kv; - - kv.key = WATCH_FILE_ENABLED_SS; - kv.value = watchEnabled()?"YES":"NO" ; - - rskv->tlvkvs.pairs.push_back(kv); - } - { - RsTlvKeyValue kv; - - kv.key = TRUST_FRIEND_NODES_FOR_BANNED_FILES_SS; - kv.value = trustFriendNodesForBannedFiles()?"YES":"NO" ; - - rskv->tlvkvs.pairs.push_back(kv); - } - { - RsTlvKeyValue kv; - - kv.key = WATCH_HASH_SALT_SS; - kv.value = mLocalDirWatcher->hashSalt().toStdString(); - - rskv->tlvkvs.pairs.push_back(kv); - } - { - std::list prefix_list,suffix_list; - uint32_t flags ; - - mLocalDirWatcher->getIgnoreLists(prefix_list,suffix_list,flags) ; - - std::string prefix_string, suffix_string ; - - for(auto it(prefix_list.begin());it!=prefix_list.end();++it) prefix_string += *it + ";" ; - for(auto it(suffix_list.begin());it!=suffix_list.end();++it) suffix_string += *it + ";" ; - - RsTlvKeyValue kv; - - kv.key = IGNORED_PREFIXES_SS; kv.value = prefix_string; rskv->tlvkvs.pairs.push_back(kv); - kv.key = IGNORED_SUFFIXES_SS; kv.value = suffix_string; rskv->tlvkvs.pairs.push_back(kv); - - std::string s ; - rs_sprintf(s, "%lu", flags) ; - - kv.key = IGNORE_LIST_FLAGS_SS; kv.value = s; rskv->tlvkvs.pairs.push_back(kv); - } - - /* Add KeyValue to saveList */ - sList.push_back(rskv); - - return true; -} - -bool p3FileDatabase::loadList(std::list& load) -{ - /* for each item, check it exists .... - * - remove any that are dead (or flag?) - */ - static const FileStorageFlags PERMISSION_MASK = DIR_FLAGS_PERMISSIONS_MASK; - -#ifdef DEBUG_FILE_HIERARCHY - P3FILELISTS_DEBUG() << "Load list" << std::endl; -#endif - - std::list dirList; - std::list ignored_prefixes,ignored_suffixes ; - uint32_t ignore_flags = RS_FILE_SHARE_FLAGS_IGNORE_PREFIXES | RS_FILE_SHARE_FLAGS_IGNORE_SUFFIXES ; - uint32_t max_share_depth = 0; - - // OS-dependent default ignore lists -#ifdef WINDOWS_SYS - ignored_suffixes.push_back( ".bak" ); -#else - ignored_prefixes.push_back( "." ); - ignored_suffixes.push_back( "~" ); - ignored_suffixes.push_back( ".part" ); -#endif - - for(std::list::iterator it = load.begin(); it != load.end(); ++it) - { - RsConfigKeyValueSet *rskv ; - - if (NULL != (rskv = dynamic_cast(*it))) - { - /* make into map */ - //std::map configMap; - //std::map::const_iterator mit ; - - for(std::list::const_iterator kit = rskv->tlvkvs.pairs.begin(); kit != rskv->tlvkvs.pairs.end(); ++kit) - if (kit->key == HASH_CACHE_DURATION_SS) - { - uint32_t t=0 ; - if(sscanf(kit->value.c_str(),"%u",&t) == 1) - mHashCache->setRememberHashFilesDuration(t); - } - else if(kit->key == WATCH_FILE_DURATION_SS) - { - int t=0 ; - if(sscanf(kit->value.c_str(),"%d",&t) == 1) - setWatchPeriod(t); - } - else if(kit->key == FOLLOW_SYMLINKS_SS) - { - setFollowSymLinks(kit->value == "YES") ; - } - else if(kit->key == IGNORE_DUPLICATES) - { - setIgnoreDuplicates(kit->value == "YES") ; - } - else if(kit->key == WATCH_FILE_ENABLED_SS) - { - setWatchEnabled(kit->value == "YES") ; - } - else if(kit->key == TRUST_FRIEND_NODES_FOR_BANNED_FILES_SS) - { - setTrustFriendNodesForBannedFiles(kit->value == "YES") ; - } - else if(kit->key == WATCH_HASH_SALT_SS) - { - std::cerr << "Initing directory watcher with saved secret salt..." << std::endl; - mLocalDirWatcher->setHashSalt(RsFileHash(kit->value)) ; - } - else if(kit->key == IGNORED_PREFIXES_SS) - { - ignored_prefixes.clear(); - - std::string b ; - for(uint32_t i=0;ivalue.size();++i) - if(kit->value[i] == ';') - { - if(!b.empty()) // security! - ignored_prefixes.push_back(b) ; - - b.clear(); - } - else - b.push_back(kit->value[i]) ; - } - else if(kit->key == IGNORED_SUFFIXES_SS) - { - ignored_suffixes.clear(); - - std::string b ; - for(uint32_t i=0;ivalue.size();++i) - if(kit->value[i] == ';') - { - if(!b.empty()) // security! - ignored_suffixes.push_back(b) ; - b.clear(); - } - else - b.push_back(kit->value[i]) ; - } - else if(kit->key == IGNORE_LIST_FLAGS_SS) - { - int t=0 ; - if(sscanf(kit->value.c_str(),"%d",&t) == 1) - ignore_flags = (uint32_t)t ; - } - else if(kit->key == MAX_SHARE_DEPTH) - { - int t=0 ; - if(sscanf(kit->value.c_str(),"%d",&t) == 1) - max_share_depth = (uint32_t)t ; - } - - delete *it ; - continue ; - } - - RsFileConfigItem *fi = dynamic_cast(*it); - - if (fi) - { - /* ensure that it exists? */ - - SharedDirInfo info ; - info.filename = RsDirUtil::convertPathToUnix(fi->file.path); - info.virtualname = fi->file.name; - info.shareflags = FileStorageFlags(fi->flags) ; - info.shareflags &= PERMISSION_MASK ; - - for(std::set::const_iterator itt(fi->parent_groups.ids.begin());itt!=fi->parent_groups.ids.end();++itt) - info.parent_groups.push_back(*itt) ; - - dirList.push_back(info) ; - } - - RsFileListsBannedHashesConfigItem *fb = dynamic_cast(*it) ; - - if(fb) - { - mPrimaryBanList = fb->primary_banned_files_list ; - mBannedFileListNeedsUpdate = true; - mLastPrimaryBanListChangeTimeStamp = time(NULL); - } - - delete *it ; - } - - /* set directories */ - mLocalSharedDirs->setSharedDirectoryList(dirList); - mLocalDirWatcher->setIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ; - mLocalDirWatcher->setMaxShareDepth(max_share_depth); - - load.clear() ; - - return true; -} - -void p3FileDatabase::cleanup() -{ - { - RS_STACK_MUTEX(mFLSMtx) ; -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "p3FileDatabase::cleanup()" << std::endl; -#endif - - // look through the list of friend directories. Remove those who are not our friends anymore. - // - std::set friend_set ; - { - std::list friend_lst ; - - rsPeers->getFriendList(friend_lst); - - for(std::list::const_iterator it(friend_lst.begin());it!=friend_lst.end();++it) - friend_set.insert(*it) ; - } - rstime_t now = time(NULL); - - for(uint32_t i=0;igetDirectoryRecursModTime(0,recurs_mod_time) ; - - rstime_t last_contact = 0 ; - RsPeerDetails pd ; - if(rsPeers->getPeerDetails(mRemoteDirectories[i]->peerId(),pd)) - last_contact = pd.lastConnect ; - - // We remove directories in the following situations: - // - the peer is not a friend - // - the dir list is non empty but the peer is offline since more than 60 days - // - the dir list is empty and the peer is ffline since more than 5 days - - bool should_remove = friend_set.find(mRemoteDirectories[i]->peerId()) == friend_set.end() - || (recurs_mod_time == 0 && last_contact + DELAY_BEFORE_DELETE_EMPTY_REMOTE_DIR < now ) - || (recurs_mod_time != 0 && last_contact + DELAY_BEFORE_DELETE_NON_EMPTY_REMOTE_DIR < now ); - - if(!should_remove) - continue ; - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " removing file list of non friend " << mRemoteDirectories[i]->peerId() << std::endl; -#endif - - mUpdateFlags |= P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED ; - - friend_set.erase(mRemoteDirectories[i]->peerId()); - - mFriendIndexMap.erase(mRemoteDirectories[i]->peerId()); - - // also remove the existing file - - remove(mRemoteDirectories[i]->filename().c_str()) ; - - delete mRemoteDirectories[i]; - mRemoteDirectories[i] = NULL ; - - // now, in order to avoid empty seats, just move the last one here, and update indexes - - while(i < mRemoteDirectories.size() && mRemoteDirectories[i] == NULL) - { - mRemoteDirectories[i] = mRemoteDirectories.back(); - mRemoteDirectories.pop_back(); - } - - if(i < mRemoteDirectories.size() && mRemoteDirectories[i] != NULL) // this test is needed in the case we have deleted the last element - mFriendIndexMap[mRemoteDirectories[i]->peerId()] = i; - - mUpdateFlags |= P3FILELISTS_UPDATE_FLAG_REMOTE_DIRS_CHANGED ; - } - - // look through the remaining list of friends, which are the ones for which no remoteDirectoryStorage class has been allocated. - // - for(std::set::const_iterator it(friend_set.begin());it!=friend_set.end();++it) - { - // Check if a remote directory exists for that friend, possibly creating the index if the file does not but the friend is online. - - if(rsPeers->isOnline(*it) || RsDirUtil::fileExists(makeRemoteFileName(*it))) - locked_getFriendIndex(*it) ; - } - - // cancel existing requests for which the peer is offline - - std::set online_peers ; - mServCtrl->getPeersConnected(getServiceInfo().mServiceType, online_peers) ; - - for(std::map::iterator it = mPendingSyncRequests.begin();it!=mPendingSyncRequests.end();) - if(online_peers.find(it->second.peer_id) == online_peers.end() || it->second.request_TS + DELAY_BEFORE_DROP_REQUEST < now) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " removing pending request " << std::hex << it->first << std::dec << " for peer " << it->second.peer_id << ", because peer is offline or request is too old." << std::endl; -#endif - std::map::iterator tmp(it); - ++tmp; - mPendingSyncRequests.erase(it) ; - it = tmp; - } - else - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " keeping request " << std::hex << it->first << std::dec << " for peer " << it->second.peer_id << std::endl; -#endif - ++it ; - } - - // This is needed at least here, because loadList() might never have been called, if there is no config file present. - - if(mLocalDirWatcher->hashSalt().isNull()) - { - std::cerr << "(WW) Initialising directory watcher salt to some random value " << std::endl; - mLocalDirWatcher->setHashSalt(RsFileHash::random()) ; - - IndicateConfigChanged(); - } - } -} - -std::string p3FileDatabase::makeRemoteFileName(const RsPeerId& pid) const -{ - return mFileSharingDir + "/" + "dirlist_"+pid.toStdString()+".bin" ; -} - -uint32_t p3FileDatabase::locked_getFriendIndex(const RsPeerId& pid) -{ - std::map::const_iterator it = mFriendIndexMap.find(pid) ; - - if(it == mFriendIndexMap.end()) - { - // allocate a new index for that friend, and tell that we should save. - uint32_t found = 0 ; - for(uint32_t i=0;isecond << std::endl; -#endif - } - - if(sizeof(void*)==4 && mRemoteDirectories.size() >= (1u << NB_FRIEND_INDEX_BITS_32BITS) ) - { - std::cerr << "(EE) FriendIndexTab is full. This is weird. Do you really have more than " << (1<= (1ull << NB_FRIEND_INDEX_BITS_64BITS) ) - { - std::cerr << "(EE) FriendIndexTab is full. This is weird. Do you really have more than " << (1<second) - { - mRemoteDirectories.resize(it->second+1,NULL) ; - mRemoteDirectories[it->second] = new RemoteDirectoryStorage(pid,makeRemoteFileName(pid)); - - mUpdateFlags |= P3FILELISTS_UPDATE_FLAG_REMOTE_DIRS_CHANGED ; - mUpdateFlags |= P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED ; - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " adding missing remote dir entry for friend " << pid << ", with index " << it->second << std::endl; -#endif - } - - return it->second; - } -} - -template<> bool p3FileDatabase::convertPointerToEntryIndex<4>(const void *p, EntryIndex& e, uint32_t& friend_index) -{ - // trust me, I can do this ;-) - -#if defined(__GNUC__) && !defined(__clang__) -# pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif // defined(__GNUC__) && !defined(__clang__) - e = EntryIndex( *reinterpret_cast(&p) & ENTRY_INDEX_BIT_MASK_32BITS ) ; - friend_index = (*reinterpret_cast(&p)) >> NB_ENTRY_INDEX_BITS_32BITS ; -#if defined(__GNUC__) && !defined(__clang__) -# pragma GCC diagnostic pop -#endif // defined(__GNUC__) && !defined(__clang__) - - if(friend_index == 0) - { - std::cerr << "(EE) Cannot find friend index in pointer. Encoded value is zero!" << std::endl; - return false; - } - friend_index--; - - return true; -} -template<> bool p3FileDatabase::convertEntryIndexToPointer<4>(const EntryIndex& e, uint32_t fi, void *& p) -{ - // the pointer is formed the following way: - // - // [ 10 bits | 22 bits ] - // - // This means that the whoel software has the following build-in limitation: - // * 1023 friends - // * 4M shared files. - - uint32_t fe = (uint32_t)e ; - - if(fi+1 >= (1u<= (1u<< NB_ENTRY_INDEX_BITS_32BITS)) - { - P3FILELISTS_ERROR() << "(EE) cannot convert entry index " << e << " of friend with index " << fi << " to pointer." << std::endl; - return false ; - } - - p = reinterpret_cast( ( (1u+fi) << NB_ENTRY_INDEX_BITS_32BITS ) + (fe & ENTRY_INDEX_BIT_MASK_32BITS)) ; - - return true; -} -template<> bool p3FileDatabase::convertPointerToEntryIndex<8>(const void *p, EntryIndex& e, uint32_t& friend_index) -{ - // trust me, I can do this ;-) - -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif // defined(__GNUC__) && !defined(__clang__) - e = EntryIndex( *reinterpret_cast(&p) & ENTRY_INDEX_BIT_MASK_64BITS ) ; - friend_index = (*reinterpret_cast(&p)) >> NB_ENTRY_INDEX_BITS_64BITS ; -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif // defined(__GNUC__) && !defined(__clang__) - - if(friend_index == 0) - { - std::cerr << "(EE) Cannot find friend index in pointer. Encoded value is zero!" << std::endl; - return false; - } - friend_index--; - -#ifdef DEBUG_P3FILELISTS - std::cerr << "Generated index " << e <<" friend " << friend_index << " from pointer " << p << std::endl; -#endif - return true; -} -template<> bool p3FileDatabase::convertEntryIndexToPointer<8>(const EntryIndex& e, uint32_t fi, void *& p) -{ - // the pointer is formed the following way: - // - // [ 24 bits | 40 bits ] - // - // This means that the whoel software has the following build-in limitation: - // * 1.6M friends - // * 1T shared files. - - uint64_t fe = (uint64_t)e ; - - if(fi+1 >= (1ull<= (1ull<< NB_ENTRY_INDEX_BITS_64BITS)) - { - P3FILELISTS_ERROR() << "(EE) cannot convert entry index " << e << " of friend with index " << fi << " to pointer." << std::endl; - return false ; - } - - p = reinterpret_cast( ( (1ull+fi) << NB_ENTRY_INDEX_BITS_64BITS ) + (fe & ENTRY_INDEX_BIT_MASK_64BITS)) ; - -#ifdef DEBUG_P3FILELISTS - std::cerr << "Generated pointer " << p << " from friend " << fi << " and index " << e << std::endl; -#endif - - return true; -} -void p3FileDatabase::requestDirUpdate(void *ref) -{ - uint32_t fi; - DirectoryStorage::EntryIndex e ; - - convertPointerToEntryIndex(ref,e,fi); - - if(fi == 0) - return ; // not updating current directory (should we?) - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Trying to force sync of entry ndex " << e << " to friend " << mRemoteDirectories[fi-1]->peerId() << std::endl; -#endif - - RS_STACK_MUTEX(mFLSMtx) ; - - if(locked_generateAndSendSyncRequest(mRemoteDirectories[fi-1],e)) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Succeed." << std::endl; -#endif - } -} - -// Finds the pointer to the sub-element #row under element ref. - -bool p3FileDatabase::findChildPointer( void *ref, int row, void *& result, - FileSearchFlags flags ) const -{ - if (ref == NULL) - { - if(flags & RS_FILE_HINTS_LOCAL) - { - if(row != 0 && row != 1) - return false ; - - convertEntryIndexToPointer(0,row,result); - - return true ; - } - else if((uint32_t)row < mRemoteDirectories.size()) - { - convertEntryIndexToPointer(mRemoteDirectories[row]->root(),row+1,result); - return true; - } - else - return false; - } - - uint32_t fi; - DirectoryStorage::EntryIndex e ; - - convertPointerToEntryIndex(ref,e,fi); - - // check consistency - if( (fi == 0 && !(flags & RS_FILE_HINTS_LOCAL)) || (fi > 1 && (flags & RS_FILE_HINTS_LOCAL))) - { - P3FILELISTS_ERROR() << "(EE) remote request on local index or local request on remote index. This should not happen." << std::endl; - return false ; - } - - if(fi==1 && (flags & RS_FILE_HINTS_LOCAL)) // extra list - { - convertEntryIndexToPointer(row+1,1,result); - return true; - } - DirectoryStorage *storage = (flags & RS_FILE_HINTS_LOCAL)? ((DirectoryStorage*)mLocalSharedDirs) : ((DirectoryStorage*)mRemoteDirectories[fi-1]); - - // Case where the index is the top of a single person. Can be us, or a friend. - - EntryIndex c = 0; - bool res = storage->getChildIndex(e,row,c); - - convertEntryIndexToPointer(c,fi,result) ; - - return res; -} - -// This function returns statistics about the entire directory - -int p3FileDatabase::getSharedDirStatistics(const RsPeerId& pid,SharedDirStats& stats) -{ - RS_STACK_MUTEX(mFLSMtx) ; - - if(pid == mOwnId) - { - mLocalSharedDirs->getStatistics(stats) ; - return true ; - } - else - { - uint32_t fi = locked_getFriendIndex(pid); - mRemoteDirectories[fi]->getStatistics(stats) ; - - return true ; - } -} - -bool p3FileDatabase::removeExtraFile(const RsFileHash& hash) -{ - bool ret = false; - { - RS_STACK_MUTEX(mFLSMtx) ; - - ret = mExtraFiles->removeExtraFile(hash); - mLastExtraFilesCacheUpdate = 0 ; // forced cache reload - } - - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); - return ret; -} - -void p3FileDatabase::getExtraFilesDirDetails(void *ref,DirectoryStorage::EntryIndex e,DirDetails& d) const -{ - // update the cache of extra files if last requested too long ago - - rstime_t now = time(NULL); - - if(mLastExtraFilesCacheUpdate + DELAY_BETWEEN_EXTRA_FILES_CACHE_UPDATES <= now) - { - mExtraFiles->getExtraFileList(mExtraFilesCache); - mLastExtraFilesCacheUpdate = now; - } - - // - - if(e == 0) // "virtual extra files directory" => create a dir with as many child as they are extra files - { - d.parent = NULL ; - - d.prow = 0;//fi-1 ; - d.type = DIR_TYPE_PERSON; - d.hash.clear() ; - d.size = mExtraFilesCache.size(); - d.max_mtime = time(NULL); - d.mtime = time(NULL); - d.name = "[Extra List]"; - d.path = "/"; - d.ref = ref ; - - for(uint32_t i=0;i(i+1,1,stub.ref); // local shared files from extra list - - d.children.push_back(stub); - } - } - else // extra file. Just query the corresponding data from ftExtra - { - d.prow = 1;//fi-1 ; - d.type = DIR_TYPE_EXTRA_FILE; - - FileInfo& f(mExtraFilesCache[(int)e-1]) ; - - d.hash = f.hash; - d.size = f.size; - d.max_mtime = 0; // this is irrelevant - d.mtime = 0; // this is irrelevant - d.name = f.path; // so that the UI shows the complete path, since the parent directory is not really a directory. - d.path = f.path; - d.ref = ref ; - - convertEntryIndexToPointer(0,1,d.parent) ; - } - - d.flags = DIR_FLAGS_ANONYMOUS_DOWNLOAD ; - d.id = RsPeerId(); -} - -// This function converts a pointer into directory details, to be used by the AbstractItemModel for browsing the files. -int p3FileDatabase::RequestDirDetails(void *ref, DirDetails& d, FileSearchFlags flags) const -{ - RS_STACK_MUTEX(mFLSMtx) ; - - d.children.clear(); - - // Case where the pointer is NULL, which means we're at the top of the list of shared directories for all friends (including us) - // or at the top of our own list of shared directories, depending on the flags. - - // Friend index is used as follows: - // 0 : own id - // 1...n : other friends - // - // entry_index: starts at 0. - // - // The point is: we cannot use (0,0) because it encodes to NULL. No existing combination should encode to NULL. - // So we need to properly convert the friend index into 0 or into a friend tab index in mRemoteDirectories. - // - // We should also check the consistency between flags and the content of ref. - - if (ref == NULL) - { - d.ref = NULL ; - d.type = DIR_TYPE_ROOT; - d.parent = NULL; - d.prow = -1; - d.name = "root"; - d.hash.clear() ; - d.path = ""; - d.mtime = 0; - d.flags.clear() ; - d.max_mtime = 0 ; - - if(flags & RS_FILE_HINTS_LOCAL) - { - void *p; - - { - convertEntryIndexToPointer(0,0,p); // root of own directories - DirStub stub; - stub.type = DIR_TYPE_PERSON; - stub.name = mServCtrl->getOwnId().toStdString(); - stub.ref = p; - d.children.push_back(stub); - } - - if(mExtraFiles->size() > 0) - { - convertEntryIndexToPointer(0,1,p); // local shared files from extra list - DirStub stub; - stub.type = DIR_TYPE_PERSON; // not totally exact, but used as a trick. - stub.name = "[Extra List]"; - stub.ref = p; - - d.children.push_back(stub); - } - - - } - else for(uint32_t i=0;i(mRemoteDirectories[i]->root(),i+1,p); - - DirStub stub; - stub.type = DIR_TYPE_PERSON; - stub.name = mRemoteDirectories[i]->peerId().toStdString(); - stub.ref = p; - d.children.push_back(stub); - } - - d.size = 0; // non documented - -#ifdef DEBUG_FILE_HIERARCHY - P3FILELISTS_DEBUG() << "ExtractData: ref=" << ref << ", flags=" << flags << " : returning this: " << std::endl; - P3FILELISTS_DEBUG() << d << std::endl; -#endif - - return true ; - } - - uint32_t fi; - DirectoryStorage::EntryIndex e ; - - convertPointerToEntryIndex(ref,e,fi); - - // check consistency - if( (fi == 0 && !(flags & RS_FILE_HINTS_LOCAL)) || (fi > 1 && (flags & RS_FILE_HINTS_LOCAL))) - { - P3FILELISTS_ERROR() << "(EE) remote request on local index or local request on remote index. This should not happen." << std::endl; - return false ; - } - - if((flags & RS_FILE_HINTS_LOCAL) && fi == 1) // extra list - { - getExtraFilesDirDetails(ref,e,d); - -#ifdef DEBUG_FILE_HIERARCHY - P3FILELISTS_DEBUG() << "ExtractData: ref=" << ref << ", flags=" << flags << " : returning this: " << std::endl; - P3FILELISTS_DEBUG() << d << std::endl; -#endif - return true; - } - - - DirectoryStorage *storage = (flags & RS_FILE_HINTS_LOCAL)? ((DirectoryStorage*)mLocalSharedDirs) : ((DirectoryStorage*)mRemoteDirectories[fi-1]); - - // Case where the index is the top of a single person. Can be us, or a friend. - - if(storage==NULL || !storage->extractData(e,d)) - { -#ifdef DEBUG_FILE_HIERARCHY - P3FILELISTS_DEBUG() << "(WW) request on index " << e << ", for directory ID=" << ((storage==NULL)?("[NULL]"):(storage->peerId().toStdString())) << " failed. This should not happen." << std::endl; -#endif - return false ; - } - - // update indexes. This is a bit hacky, but does the job. The cast to intptr_t is the proper way to convert - // a pointer into an int. - - convertEntryIndexToPointer((intptr_t)d.ref,fi,d.ref) ; - - for(uint32_t i=0;i((intptr_t)d.children[i].ref,fi,d.children[i].ref); - - if(e == 0) // root - { - d.prow = 0;//fi-1 ; - d.parent = NULL ; - } - else - { - if(d.parent == 0) // child of root node - d.prow = (flags & RS_FILE_HINTS_LOCAL)?0:(fi-1); - else - d.prow = storage->parentRow(e) ; - - convertEntryIndexToPointer((intptr_t)d.parent,fi,d.parent) ; - } - - d.id = storage->peerId(); - -#ifdef DEBUG_FILE_HIERARCHY - P3FILELISTS_DEBUG() << "ExtractData: ref=" << ref << ", flags=" << flags << " : returning this: " << std::endl; - P3FILELISTS_DEBUG() << d << std::endl; -#endif - - return true; -} - -uint32_t p3FileDatabase::getType(void *ref,FileSearchFlags flags) const -{ - RS_STACK_MUTEX(mFLSMtx) ; - - EntryIndex e ; - uint32_t fi; - - if(ref == NULL) - return DIR_TYPE_ROOT ; - - convertPointerToEntryIndex(ref,e,fi); - - if(e == 0) - return DIR_TYPE_PERSON ; - - if(flags & RS_FILE_HINTS_LOCAL) - { - if(fi == 0 && mLocalSharedDirs != NULL) - return mLocalSharedDirs->getEntryType(e) ; - - if(fi == 1) - return DIR_TYPE_EXTRA_FILE; - - P3FILELISTS_ERROR() << " Cannot determine type of entry " << ref << std::endl; - return DIR_TYPE_ROOT ;// some failure case. Should not happen - } - else - { - if(fi-1 < mRemoteDirectories.size() && mRemoteDirectories[fi-1]!=NULL) - return mRemoteDirectories[fi-1]->getEntryType(e) ; - - P3FILELISTS_ERROR() << " Cannot determine type of entry " << ref << std::endl; - return DIR_TYPE_ROOT ;// some failure case. Should not happen - } -} - -void p3FileDatabase::forceDirectoryCheck(bool add_safe_delay) // Force re-sweep the directories and see what's changed -{ - mLocalDirWatcher->forceUpdate(add_safe_delay); -} -void p3FileDatabase::togglePauseHashingProcess() -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalDirWatcher->togglePauseHashingProcess(); -} -bool p3FileDatabase::hashingProcessPaused() -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->hashingProcessPaused(); -} -bool p3FileDatabase::inDirectoryCheck() -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->inDirectoryCheck(); -} -void p3FileDatabase::setFollowSymLinks(bool b) -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalDirWatcher->setFollowSymLinks(b) ; - IndicateConfigChanged(); -} -bool p3FileDatabase::followSymLinks() const -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->followSymLinks() ; -} -void p3FileDatabase::setIgnoreDuplicates(bool i) -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalDirWatcher->setIgnoreDuplicates(i) ; - IndicateConfigChanged(); -} -bool p3FileDatabase::ignoreDuplicates() const -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->ignoreDuplicates() ; -} -void p3FileDatabase::setMaxShareDepth(int i) -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalDirWatcher->setMaxShareDepth(i) ; - IndicateConfigChanged(); -} -int p3FileDatabase::maxShareDepth() const -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->maxShareDepth() ; -} -void p3FileDatabase::setWatchEnabled(bool b) -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalDirWatcher->setEnabled(b) ; - IndicateConfigChanged(); -} -bool p3FileDatabase::watchEnabled() -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->isEnabled() ; -} -void p3FileDatabase::setWatchPeriod(uint32_t seconds) -{ - RS_STACK_MUTEX(mFLSMtx) ; - - mLocalDirWatcher->setFileWatchPeriod(seconds); - IndicateConfigChanged(); -} -uint32_t p3FileDatabase::watchPeriod() -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->fileWatchPeriod(); -} - -int p3FileDatabase::SearchKeywords(const std::list& keywords, std::list& results,FileSearchFlags flags,const RsPeerId& client_peer_id) -{ - if(flags & RS_FILE_HINTS_LOCAL) - { - std::list firesults; - std::list pointers; - - { - RS_STACK_MUTEX(mFLSMtx) ; - - mLocalSharedDirs->searchTerms(keywords,firesults) ; - - for(std::list::iterator it(firesults.begin());it!=firesults.end();++it) - { - void *p=NULL; - convertEntryIndexToPointer(*it,0,p); - pointers.push_back(p) ; - } - } - - filterResults(pointers,results,flags,client_peer_id) ; - } - - if(flags & RS_FILE_HINTS_REMOTE) - { - std::list pointers ; - - { - RS_STACK_MUTEX(mFLSMtx) ; - - for(uint32_t i=0;i local_results; - mRemoteDirectories[i]->searchTerms(keywords,local_results) ; - - for(std::list::iterator it(local_results.begin());it!=local_results.end();++it) - { - void *p=NULL; - convertEntryIndexToPointer(*it,i+1,p); - - pointers.push_back(p) ; - } - } - } - - for(auto it(pointers.begin());it!=pointers.end();++it) - { - DirDetails dd; - - if(!RequestDirDetails (*it,dd,RS_FILE_HINTS_REMOTE)) - continue ; - - results.push_back(dd); - } - } - - return !results.empty() ; -} - -int p3FileDatabase::SearchBoolExp(RsRegularExpression::Expression *exp, std::list& results,FileSearchFlags flags,const RsPeerId& client_peer_id) const -{ - if(flags & RS_FILE_HINTS_LOCAL) - { - std::list firesults; - std::list pointers; - { - RS_STACK_MUTEX(mFLSMtx) ; - - mLocalSharedDirs->searchBoolExp(exp,firesults) ; - - for(std::list::iterator it(firesults.begin());it!=firesults.end();++it) - { - void *p=NULL; - convertEntryIndexToPointer(*it,0,p); - pointers.push_back(p); - } - } - - filterResults(pointers,results,flags,client_peer_id) ; - } - - if(flags & RS_FILE_HINTS_REMOTE) - { - std::list pointers ; - { - RS_STACK_MUTEX(mFLSMtx) ; - - for(uint32_t i=0;i local_results; - mRemoteDirectories[i]->searchBoolExp(exp,local_results) ; - - for(std::list::iterator it(local_results.begin());it!=local_results.end();++it) - { - void *p=NULL; - convertEntryIndexToPointer(*it,i+1,p); - pointers.push_back(p) ; - } - } - } - - for(auto it(pointers.begin());it!=pointers.end();++it) - { - DirDetails dd; - - if(!RequestDirDetails (*it,dd,RS_FILE_HINTS_REMOTE)) - continue ; - - results.push_back(dd); - } - } - - return !results.empty() ; - -} - -bool p3FileDatabase::search( - const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const -{ - RS_STACK_MUTEX(mFLSMtx); - - if( (hintflags & RS_FILE_HINTS_EXTRA) && - mExtraFiles->search(hash, hintflags, info) ) - return true; - - if(hintflags & RS_FILE_HINTS_LOCAL) - { - RsFileHash real_hash ; - EntryIndex indx; - - if(mLocalSharedDirs->searchHash(hash,real_hash,indx)) - { - mLocalSharedDirs->getFileInfo(indx,info) ; - - if(!real_hash.isNull()) - { - info.hash = real_hash ; - info.transfer_info_flags |= RS_FILE_REQ_ENCRYPTED ; - } - - return true; - } - } - - if(hintflags & RS_FILE_HINTS_REMOTE) - { - EntryIndex indx; - bool found = false ; - - for(uint32_t i=0;isearchHash(hash,indx)) - { - TransferInfo ti ; - ti.peerId = mRemoteDirectories[i]->peerId(); - - info.hash = hash ; - info.peers.push_back(ti) ; - - found = true ; - } - - if(found) - return true; - } - return false; -} - -int p3FileDatabase::filterResults(const std::list& firesults,std::list& results,FileSearchFlags flags,const RsPeerId& peer_id) const -{ - results.clear(); - - flags &= RS_FILE_HINTS_PERMISSION_MASK; // remove other flags. - - /* translate/filter results */ - - for(std::list::const_iterator rit(firesults.begin()); rit != firesults.end(); ++rit) - { - DirDetails cdetails ; - - if(!RequestDirDetails (*rit,cdetails,RS_FILE_HINTS_LOCAL)) - { - P3FILELISTS_ERROR() << "(EE) Cannot get dir details for entry " << *rit << std::endl; - continue ; - } -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Filtering candidate " << *rit << ", flags=" << cdetails.flags << ", peer=" << peer_id ; -#endif - - if(!peer_id.isNull()) - { - FileSearchFlags permission_flags = rsPeers->computePeerPermissionFlags(peer_id,cdetails.flags,cdetails.parent_groups) ; - - if (cdetails.type == DIR_TYPE_FILE && ( permission_flags & flags )) - { - cdetails.id.clear() ; - results.push_back(cdetails); -#ifdef DEBUG_P3FILELISTS - std::cerr << ": kept" << std::endl ; -#endif - } -#ifdef DEBUG_P3FILELISTS - else - std::cerr << ": discarded" << std::endl ; -#endif - } - else - results.push_back(cdetails); - } - - return !results.empty() ; -} - -bool p3FileDatabase::convertSharedFilePath(const std::string& path,std::string& fullpath) -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalSharedDirs->convertSharedFilePath(path,fullpath) ; -} - -//==============================================================================================================================// -// Update of remote directories // -//==============================================================================================================================// - -// Algorithm: -// -// Local dirs store the last modif time of the file, in local time -// - the max time is computed upward until the root of the hierarchy -// - because the hash is performed late, the last modf time upward is updated only when the hash is obtained. -// -// Remote dirs store -// 1 - recursive max modif time of the files/dir in the friend's time -// 2 - modif time of the files/dir in the friend's time -// 3 - update TS in the local time -// -// The update algorithm is the following: -// -// [Client side] -// - every 30 sec, send a sync packet for the root of the hierarchy containing the remote known max recurs TS. -// - crawl through all directories and if the update TS is 0, ask for sync too. -// - when a sync respnse is received: -// - if response is ACK, set the update time to now. Nothing changed. -// - if response is an update -// * locally update the subfiles -// * for all subdirs, set the local update time to 0 (so as to force a sync) -// -// [Server side] -// - when sync req is received, compare to local recurs TS, and send ACK or full update accordingly -// -// Directories are designated by their hash, instead of their index. This allows to hide the non shared directories -// behind a layer of abstraction, at the cost of a logarithmic search, which is acceptable as far as dir sync-ing between -// friends is concerned (We obviously could not do that for GUI display, which has a small and constant cost). - -void p3FileDatabase::tickRecv() -{ - RsItem *item ; - - while( NULL != (item = recvItem()) ) - { - switch(item->PacketSubType()) - { - case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM: handleDirSyncRequest( dynamic_cast(item) ) ; break ; - case RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_ITEM : handleBannedFilesInfo( dynamic_cast(item) ) ; break ; - case RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM: - { - RsFileListsSyncResponseItem *sitem = dynamic_cast(item); - handleDirSyncResponse(sitem) ; - item = sitem ; - } - break ; - default: - P3FILELISTS_ERROR() << "(EE) unhandled packet subtype " << item->PacketSubType() << " in " << __PRETTY_FUNCTION__ << std::endl; - } - - delete item ; - } -} - -void p3FileDatabase::tickSend() -{ - // go through the list of out requests and send them to the corresponding friends, if they are online. -} - -void p3FileDatabase::handleDirSyncRequest(RsFileListsSyncRequestItem *item) -{ - RsFileListsSyncResponseItem *ritem = new RsFileListsSyncResponseItem; - - // look at item TS. If local is newer, send the full directory content. - { - RS_STACK_MUTEX(mFLSMtx) ; - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Received directory sync request from peer " << item->PeerId() << ". hash=" << item->entry_hash << ", flags=" << (void*)(intptr_t)item->flags << ", request id: " << std::hex << item->request_id << std::dec << ", last known TS: " << item->last_known_recurs_modf_TS << std::endl; -#endif - - EntryIndex entry_index = DirectoryStorage::NO_INDEX; - - if(!mLocalSharedDirs->getIndexFromDirHash(item->entry_hash,entry_index)) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " (EE) Cannot find entry index for hash " << item->entry_hash << ": cannot respond to sync request." << std::endl; -#endif - return; - } - - uint32_t entry_type = mLocalSharedDirs->getEntryType(entry_index) ; - ritem->PeerId(item->PeerId()) ; - ritem->request_id = item->request_id; - ritem->entry_hash = item->entry_hash ; - - std::list node_groups; - FileStorageFlags node_flags; - - if(entry_type != DIR_TYPE_DIR) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Directory does not exist anymore, or is not a directory, or permission denied. Answering with proper flags." << std::endl; -#endif - ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | RsFileListsItem::FLAGS_ENTRY_WAS_REMOVED ; - } - else if(entry_index != 0 && (!mLocalSharedDirs->getFileSharingPermissions(entry_index,node_flags,node_groups) || !(rsPeers->computePeerPermissionFlags(item->PeerId(),node_flags,node_groups) & RS_FILE_HINTS_BROWSABLE))) - { - P3FILELISTS_ERROR() << "(EE) cannot get file permissions for entry index " << (void*)(intptr_t)entry_index << ", or permission denied." << std::endl; - ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | RsFileListsItem::FLAGS_ENTRY_WAS_REMOVED ; - } - else - { - rstime_t local_recurs_max_time ; - mLocalSharedDirs->getDirectoryRecursModTime(entry_index,local_recurs_max_time) ; - - if(item->last_known_recurs_modf_TS != local_recurs_max_time) // normally, should be "<", but since we provided the TS it should be equal, so != is more robust. - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Directory is more recent than what the friend knows. Sending full dir content as response." << std::endl; -#endif - - ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | RsFileListsItem::FLAGS_SYNC_DIR_CONTENT; - ritem->last_known_recurs_modf_TS = local_recurs_max_time; - - // We supply the peer id, in order to possibly remove some subdirs, if entries are not allowed to be seen by this peer. - mLocalSharedDirs->serialiseDirEntry(entry_index,ritem->directory_content_data,item->PeerId()) ; - } - else - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Directory is up to date w.r.t. what the friend knows. Sending ACK." << std::endl; -#endif - - ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | RsFileListsItem::FLAGS_ENTRY_UP_TO_DATE ; - ritem->last_known_recurs_modf_TS = local_recurs_max_time ; - } - } - } - - // sends the response. - - splitAndSendItem(ritem) ; -} - -void p3FileDatabase::splitAndSendItem(RsFileListsSyncResponseItem *ritem) -{ - ritem->checksum = RsDirUtil::sha1sum((uint8_t*)ritem->directory_content_data.bin_data,ritem->directory_content_data.bin_len); - - while(ritem->directory_content_data.bin_len > MAX_DIR_SYNC_RESPONSE_DATA_SIZE) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Chopping off partial chunk of size " << MAX_DIR_SYNC_RESPONSE_DATA_SIZE << " from item data of size " << ritem->directory_content_data.bin_len << std::endl; -#endif - - ritem->flags |= RsFileListsItem::FLAGS_SYNC_PARTIAL ; - - RsFileListsSyncResponseItem *subitem = new RsFileListsSyncResponseItem() ; - - subitem->entry_hash = ritem->entry_hash; - subitem->flags = ritem->flags ; - subitem->last_known_recurs_modf_TS = ritem->last_known_recurs_modf_TS; - subitem->request_id = ritem->request_id; - subitem->checksum = ritem->checksum ; - - // copy a subpart of the data - subitem->directory_content_data.tlvtype = ritem->directory_content_data.tlvtype ; - subitem->directory_content_data.setBinData(ritem->directory_content_data.bin_data, MAX_DIR_SYNC_RESPONSE_DATA_SIZE) ; - - // update ritem to chop off the data that was sent. - memmove(ritem->directory_content_data.bin_data, &((unsigned char*)ritem->directory_content_data.bin_data)[MAX_DIR_SYNC_RESPONSE_DATA_SIZE], ritem->directory_content_data.bin_len - MAX_DIR_SYNC_RESPONSE_DATA_SIZE) ; - ritem->directory_content_data.bin_len -= MAX_DIR_SYNC_RESPONSE_DATA_SIZE ; - - // send - subitem->PeerId(ritem->PeerId()) ; - - sendItem(subitem) ; - - // fix up last chunk - if(ritem->directory_content_data.bin_len <= MAX_DIR_SYNC_RESPONSE_DATA_SIZE) - ritem->flags |= RsFileListsItem::FLAGS_SYNC_PARTIAL_END ; - } - - sendItem(ritem) ; -} - -// This function should not take memory ownership of ritem, so it makes copies. -// The item that is returned is either created (if different from ritem) or equal to ritem. - -RsFileListsSyncResponseItem *p3FileDatabase::recvAndRebuildItem(RsFileListsSyncResponseItem *ritem) -{ - if(!(ritem->flags & RsFileListsItem::FLAGS_SYNC_PARTIAL )) - return ritem ; - - // item is a partial item. Look first for a starting entry - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Item from peer " << ritem->PeerId() << " is partial. Size = " << ritem->directory_content_data.bin_len << std::endl; -#endif - - RS_STACK_MUTEX(mFLSMtx) ; - - bool is_ending = (ritem->flags & RsFileListsItem::FLAGS_SYNC_PARTIAL_END); - std::map::iterator it = mPartialResponseItems.find(ritem->request_id) ; - - if(it == mPartialResponseItems.end()) - { - if(is_ending) - { - P3FILELISTS_ERROR() << "Impossible situation: partial item ended right away. Dropping..." << std::endl; - return NULL; - } -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Creating new item buffer" << std::endl; -#endif - - mPartialResponseItems[ritem->request_id] = new RsFileListsSyncResponseItem(*ritem) ; - return NULL ; - } - else if(it->second->checksum != ritem->checksum) - { - P3FILELISTS_ERROR() << "Impossible situation: partial items with different checksums. Dropping..." << std::endl; - mPartialResponseItems.erase(it); - return NULL; - } - - // collapse the item at the end of the existing partial item. Dont delete ritem as it will be by the caller. - - uint32_t old_len = it->second->directory_content_data.bin_len ; - uint32_t added = ritem->directory_content_data.bin_len; - - it->second->directory_content_data.bin_data = realloc(it->second->directory_content_data.bin_data,old_len + added) ; - memcpy(&((unsigned char*)it->second->directory_content_data.bin_data)[old_len],ritem->directory_content_data.bin_data,added); - it->second->directory_content_data.bin_len = old_len + added ; - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Added new chunk of length " << added << ". New size is " << old_len + added << std::endl; -#endif - - // if finished, return the item - - if(is_ending) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Item is complete. Returning it" << std::endl; -#endif - - RsFileListsSyncResponseItem *ret = it->second ; - mPartialResponseItems.erase(it) ; - - ret->flags &= ~RsFileListsItem::FLAGS_SYNC_PARTIAL_END ; - ret->flags &= ~RsFileListsItem::FLAGS_SYNC_PARTIAL ; - - return ret ; - } - else - return NULL ; -} - -// We employ a trick in this function: -// - if recvAndRebuildItem(item) returns the same item, it has not created memory, so the incoming item should be the one to -// delete, which is done by the caller in every case. -// - if it returns a different item, it means that the item has been created below when collapsing items, so we should delete both. -// to do so, we first delete the incoming item, and replace the pointer by the new created one. - -void p3FileDatabase::handleDirSyncResponse(RsFileListsSyncResponseItem*& sitem) -{ - RsFileListsSyncResponseItem *item = recvAndRebuildItem(sitem) ; - - if(!item) - return ; - - if(item != sitem) - { - delete sitem ; - sitem = item ; - } - - rstime_t now = time(NULL); - - // check the hash. If anything goes wrong (in the chunking for instance) the hash will not match - - if(RsDirUtil::sha1sum((uint8_t*)item->directory_content_data.bin_data,item->directory_content_data.bin_len) != item->checksum) - { - P3FILELISTS_ERROR() << "Checksum error in response item " << std::hex << item->request_id << std::dec << " . This is unexpected, and might be due to connection problems." << std::endl; - return ; - } - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Handling sync response for directory with hash " << item->entry_hash << std::endl; -#endif - - EntryIndex entry_index = DirectoryStorage::NO_INDEX; - - // find the correct friend entry - - uint32_t fi = 0 ; - - { - RS_STACK_MUTEX(mFLSMtx) ; - fi = locked_getFriendIndex(item->PeerId()); - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " friend index is " << fi ; -#endif - - // make sure we have a remote directory for that friend. - - if(!mRemoteDirectories[fi]->getIndexFromDirHash(item->entry_hash,entry_index)) - { - std::cerr << std::endl; - P3FILELISTS_ERROR() << " (EE) cannot find index from hash " << item->entry_hash << ". Dropping the response." << std::endl; - return ; - } -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " entry index is " << entry_index << " " ; -#endif - } - - if(item->flags & RsFileListsItem::FLAGS_ENTRY_WAS_REMOVED) - { - RS_STACK_MUTEX(mFLSMtx) ; -#ifdef DEBUG_P3FILELISTS - std::cerr << " removing directory with index " << entry_index << " because it does not exist." << std::endl; -#endif - mRemoteDirectories[fi]->removeDirectory(entry_index); - - mRemoteDirectories[fi]->print(); - } - else if(item->flags & RsFileListsItem::FLAGS_ENTRY_UP_TO_DATE) - { - RS_STACK_MUTEX(mFLSMtx) ; -#ifdef DEBUG_P3FILELISTS - std::cerr << " Directory is up to date. Setting local TS." << std::endl; -#endif - - mRemoteDirectories[fi]->setDirectoryUpdateTime(entry_index,now) ; - } - else if(item->flags & RsFileListsItem::FLAGS_SYNC_DIR_CONTENT) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Item contains directory data. Deserialising/Updating." << std::endl; -#endif - RS_STACK_MUTEX(mFLSMtx) ; - - if(mLastDataRecvTS + 1 < now) // avoid notifying the GUI too often as it kills performance. - { - RsServer::notify()->notifyListPreChange(NOTIFY_LIST_DIRLIST_FRIENDS, 0); // notify the GUI if the hierarchy has changed - mLastDataRecvTS = now; - } -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Performing update of directory index " << std::hex << entry_index << std::dec << " from friend " << item->PeerId() << std::endl; -#endif - - if(mRemoteDirectories[fi]->deserialiseUpdateDirEntry(entry_index,item->directory_content_data)) - mRemoteDirectories[fi]->lastSweepTime() = now - DELAY_BETWEEN_REMOTE_DIRECTORIES_SWEEP + 10 ; // force re-sweep in 10 secs, so as to fasten updated - else - P3FILELISTS_ERROR() << "(EE) Cannot deserialise dir entry. ERROR. "<< std::endl; - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " new content after update: " << std::endl; - mRemoteDirectories[fi]->print(); -#endif - } - - // remove the original request from pending list in the end. doing this here avoids that a new request is added while the previous response is not treated. - - { - RS_STACK_MUTEX(mFLSMtx) ; - - std::map::iterator it = mPendingSyncRequests.find(item->request_id) ; - - if(it == mPendingSyncRequests.end()) - { - P3FILELISTS_ERROR() << " request " << std::hex << item->request_id << std::dec << " cannot be found. ERROR!" << std::endl; - return ; - } - mPendingSyncRequests.erase(it) ; - } - - -} - -void p3FileDatabase::locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *rds,DirectoryStorage::EntryIndex e,int depth) -{ - rstime_t now = time(NULL) ; - - //std::string indent(2*depth,' ') ; - - // if not up to date, request update, and return (content is not certified, so no need to recurs yet). - // if up to date, return, because TS is about the last modif TS below, so no need to recurs either. - - // get the info for this entry - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "currently at entry index " << e << std::endl; -#endif - - rstime_t local_update_TS; - - if(!rds->getDirectoryUpdateTime(e,local_update_TS)) - { - P3FILELISTS_ERROR() << " (EE) lockec_recursSweepRemoteDirectory(): cannot get update TS for directory with index " << e << ". This is a consistency bug." << std::endl; - return; - } - - // compare TS - - if((e == 0 && now > local_update_TS + DELAY_BETWEEN_REMOTE_DIRECTORY_SYNC_REQ) || local_update_TS == 0) // we need to compare local times only. We cannot compare local (now) with remote time. - if(locked_generateAndSendSyncRequest(rds,e)) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Asking for sync of directory " << e << " to peer " << rds->peerId() << " because it's " << (now - local_update_TS) << " secs old since last check." << std::endl; -#endif - } - - for(DirectoryStorage::DirIterator it(rds,e);it;++it) - locked_recursSweepRemoteDirectory(rds,*it,depth+1); -} - -p3FileDatabase::DirSyncRequestId p3FileDatabase::makeDirSyncReqId(const RsPeerId& peer_id,const RsFileHash& hash) -{ - static uint64_t random_bias = RSRandom::random_u64(); - - uint8_t mem[RsPeerId::SIZE_IN_BYTES + RsFileHash::SIZE_IN_BYTES]; - memcpy(mem,peer_id.toByteArray(),RsPeerId::SIZE_IN_BYTES) ; - memcpy(&mem[RsPeerId::SIZE_IN_BYTES],hash.toByteArray(),RsFileHash::SIZE_IN_BYTES) ; - - RsFileHash tmp = RsDirUtil::sha1sum(mem,RsPeerId::SIZE_IN_BYTES + RsFileHash::SIZE_IN_BYTES) ; - - // This is kind of arbitrary. The important thing is that the same ID needs to be generated every time for a given (peer_id,entry index) pair, in a way - // that cannot be brute-forced or reverse-engineered, which explains the random bias and the usage of the hash, that is itself random. - - uint64_t tmp2 ; - memcpy(&tmp2,tmp.toByteArray(),sizeof(uint64_t)); - - uint64_t r = random_bias ^ tmp2; - -#ifdef DEBUG_P3FILELISTS - std::cerr << "Creating ID " << std::hex << r << std::dec << " from peer id " << peer_id << " and hash " << hash << std::endl; -#endif - - return r ; -} - -bool p3FileDatabase::locked_generateAndSendSyncRequest(RemoteDirectoryStorage *rds,const DirectoryStorage::EntryIndex& e) -{ - RsFileHash entry_hash ; - rstime_t now = time(NULL) ; - - rstime_t max_known_recurs_modf_time ; - - if(!rds->getDirectoryRecursModTime(e,max_known_recurs_modf_time)) - { - P3FILELISTS_ERROR() << " (EE) cannot find recurs mod time for entry index " << e << ". This is very unexpected." << std::endl; - return false; - } - if(!rds->getDirHashFromIndex(e,entry_hash) ) - { - P3FILELISTS_ERROR() << " (EE) cannot find hash for entry index " << e << ". This is very unexpected." << std::endl; - return false; - } - - // check if a request already exists and is not too old either: no need to re-ask. - - DirSyncRequestId sync_req_id = makeDirSyncReqId(rds->peerId(),entry_hash) ; - - std::map::iterator it = mPendingSyncRequests.find(sync_req_id) ; - - if(it != mPendingSyncRequests.end()) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Not asking for sync of directory " << e << " to friend " << rds->peerId() << " because a recent pending request still exists." << std::endl; -#endif - return false ; - } - - RsFileListsSyncRequestItem *item = new RsFileListsSyncRequestItem ; - - item->entry_hash = entry_hash ; - item->flags = RsFileListsItem::FLAGS_SYNC_REQUEST ; - item->request_id = sync_req_id ; - item->last_known_recurs_modf_TS = max_known_recurs_modf_time ; - item->PeerId(rds->peerId()) ; - - DirSyncRequestData data ; - - data.request_TS = now ; - data.peer_id = item->PeerId(); - data.flags = item->flags; - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Pushing req " << std::hex << sync_req_id << std::dec << " in pending list with peer id " << data.peer_id << std::endl; -#endif - - mPendingSyncRequests[sync_req_id] = data ; - - sendItem(item) ; // at end! Because item is destroyed by the process. - - return true; -} - - -//=========================================================================================================================// -// Unwanted content filtering system // -//=========================================================================================================================// - -bool p3FileDatabase::banFile(const RsFileHash& real_file_hash, const std::string& filename, uint64_t file_size) -{ -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " setting file \"" << filename << "\" size=" << file_size << " hash=" << real_file_hash << " as banned." << std::endl; -#endif - { - RS_STACK_MUTEX(mFLSMtx) ; - BannedFileEntry& entry(mPrimaryBanList[real_file_hash]) ; // primary list (user controlled) of files banned from FT search and forwarding. map - - if(entry.mBanTimeStamp == 0) - { - entry.mFilename = filename ; - entry.mSize = file_size ; - entry.mBanTimeStamp = time(NULL); - - RsFileHash hash_of_hash ; - ftServer::encryptHash(real_file_hash,hash_of_hash) ; - - mBannedFileList.insert(real_file_hash) ; - mBannedFileList.insert(hash_of_hash) ; - - mLastPrimaryBanListChangeTimeStamp = time(NULL); - mBannedFileListNeedsUpdate = true ; - } - } - - IndicateConfigChanged(); - return true; -} -bool p3FileDatabase::unbanFile(const RsFileHash& real_file_hash) -{ -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " unbanning file with hash " << real_file_hash << std::endl; -#endif - { - RS_STACK_MUTEX(mFLSMtx) ; - mPrimaryBanList.erase(real_file_hash) ; - mLastPrimaryBanListChangeTimeStamp = time(NULL); - mBannedFileListNeedsUpdate = true ; - } - - IndicateConfigChanged(); - return true; -} - -bool p3FileDatabase::isFileBanned(const RsFileHash& hash) -{ - RS_STACK_MUTEX(mFLSMtx) ; - - if(mBannedFileList.empty()) // quick exit - return false ; - - RsFileHash hash_of_hash ; - ftServer::encryptHash(hash,hash_of_hash) ; - - bool res = mBannedFileList.find(hash) != mBannedFileList.end() || mBannedFileList.find(hash_of_hash) != mBannedFileList.end() ; - -#ifdef DEBUG_CONTENT_FILTERING - if(res) - P3FILELISTS_DEBUG() << " is file banned(" << hash << "): " << (res?"YES":"NO") << std::endl; -#endif - return res ; -} - -bool p3FileDatabase::getPrimaryBannedFilesList(std::map& banned_files) -{ - RS_STACK_MUTEX(mFLSMtx) ; - banned_files = mPrimaryBanList; - - return true ; -} - -bool p3FileDatabase::trustFriendNodesForBannedFiles() const -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mTrustFriendNodesForBannedFiles; -} - -void p3FileDatabase::setTrustFriendNodesForBannedFiles(bool b) -{ - if(b != mTrustFriendNodesForBannedFiles) - { - IndicateConfigChanged(); - mBannedFileListNeedsUpdate = true; - } - - RS_STACK_MUTEX(mFLSMtx) ; - mTrustFriendNodesForBannedFiles = b; -} - -void p3FileDatabase::checkSendBannedFilesInfo() -{ - RS_STACK_MUTEX(mFLSMtx) ; - - // 1 - compare records to list of online friends, send own info of not already - -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " Checking banned files information: " << std::endl; -#endif - - rstime_t now = time(NULL); - std::list online_friends ; - rsPeers->getOnlineList(online_friends); - - std::set peers ; - for(auto it(online_friends.begin());it!=online_friends.end();++it) // convert to std::set for efficient search - peers.insert(*it) ; - - for(auto it(mPeerBannedFiles.begin());it!=mPeerBannedFiles.end();) - { - if(peers.find(it->first) == peers.end()) // friend not online, remove his record - { - it = mPeerBannedFiles.erase(it) ; -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " Peer " << it->first << " is offline: removign record." << std::endl; -#endif - continue; - } - - if(it->second.mLastSent < mLastPrimaryBanListChangeTimeStamp) // has ban info already been sent? If not do it. - { -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " Peer " << it->first << " is online and hasn't been sent since last change: sending..." << std::endl; -#endif - locked_sendBanInfo(it->first); - it->second.mLastSent = now; - } - - peers.erase(it->first); // friend has been handled -> remove from list - ++it; - } - - // 2 - add a new record for friends not already in the record map - - for(auto it(peers.begin());it!=peers.end();++it) - { - locked_sendBanInfo(*it); - mPeerBannedFiles[*it].mLastSent = now; -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " Peer " << *it << " is online and hasn't been sent info at all: sending..." << std::endl; -#endif - } - - // 3 - update list of banned hashes if it has changed somehow - - if(mBannedFileListNeedsUpdate) - { - mBannedFileList.clear(); - -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " Creating local banned file list: " << std::endl; -#endif - // Add all H(H(f)) from friends - - if(mTrustFriendNodesForBannedFiles) - for(auto it(mPeerBannedFiles.begin());it!=mPeerBannedFiles.end();++it) - for(auto it2(it->second.mBannedHashOfHash.begin());it2!=it->second.mBannedHashOfHash.end();++it2) - { - mBannedFileList.insert(*it2); - -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " from " << it->first << ": H(H(f)) = " << *it2 << std::endl; -#endif - } - - // Add H(f) and H(H(f)) from our primary list - - for(auto it(mPrimaryBanList.begin());it!=mPrimaryBanList.end();++it) - { - mBannedFileList.insert(it->first) ; - - RsFileHash hash_of_hash ; - ftServer::encryptHash(it->first,hash_of_hash) ; - - mBannedFileList.insert(hash_of_hash) ; - -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " primary: H(f) = " << it->first << ": H(H(f)) = " << hash_of_hash << std::endl; -#endif - } - - mBannedFileListNeedsUpdate = false ; - } - -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " Final list of locally banned hashes contains: " << mBannedFileList.size() << " elements." << std::endl; -#endif -} - -void p3FileDatabase::locked_sendBanInfo(const RsPeerId& peer) -{ - RsFileListsBannedHashesItem *item = new RsFileListsBannedHashesItem ; - uint32_t session_id = RSRandom::random_u32(); - - item->session_id = session_id ; - item->PeerId(peer); - - for(auto it(mPrimaryBanList.begin());it!=mPrimaryBanList.end();++it) - { - RsFileHash hash_of_hash ; - - ftServer::encryptHash(it->first,hash_of_hash) ; - - if(!item) - { - item = new RsFileListsBannedHashesItem ; - - item->PeerId(peer); - item->session_id = session_id ; - } - - item->encrypted_hashes.insert(hash_of_hash) ; - - if(item->encrypted_hashes.size() >= 200) - { - sendItem(item); - item = NULL ; - } - } - - if(item) - sendItem(item); -} - -void p3FileDatabase::handleBannedFilesInfo(RsFileListsBannedHashesItem *item) -{ - RS_STACK_MUTEX(mFLSMtx) ; - -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " received banned files info from peer " << item->PeerId() << ", session id = " << std::hex << item->session_id << std::dec << ": " << item->encrypted_hashes.size() << " files:" << std::endl; -#endif - // 1 - localize the friend in the banned file map - - PeerBannedFilesEntry& pbfe(mPeerBannedFiles[item->PeerId()]) ; - - if(pbfe.mSessionId != item->session_id) - pbfe.mBannedHashOfHash.clear(); - - pbfe.mSessionId = item->session_id ; - - // 2 - replace/update the list, depending on the session_id - - for(auto it(item->encrypted_hashes.begin());it!=item->encrypted_hashes.end();++it) - { - pbfe.mBannedHashOfHash.insert(*it); -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " added H(H(f)) = " << *it << std::endl; -#endif - } - - // 3 - tell the updater that the banned file list has changed - - mBannedFileListNeedsUpdate = true ; -} - diff --git a/libretroshare/src/file_sharing/p3filelists.h b/libretroshare/src/file_sharing/p3filelists.h deleted file mode 100644 index f9a97e47b..000000000 --- a/libretroshare/src/file_sharing/p3filelists.h +++ /dev/null @@ -1,301 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: p3filelists.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ - -// -// This class is responsible for -// - maintaining a list of shared file hierarchies for each known friends -// - talking to the GUI -// - providing handles for the directory tree listing GUI -// - providing search handles for FT -// - keeping these lists up to date -// - sending our own file list to friends depending on the defined access rights -// - serving file search requests from other services such as file transfer -// -// p3FileList does the following micro-tasks: -// - tick the watchers -// - get incoming info from the service layer, which can be: -// - directory content request => the directory content is shared to the friend -// - directory content => the directory watcher is notified -// - keep two queues of update requests: -// - fast queue that is handled in highest priority. This one is used for e.g. updating while browsing. -// - slow queue that is handled slowly. Used in background update of shared directories. -// -// The list of local shared files is maintained by FileListWatcher. -// -// p3FileLists is organised as follows: -// -// p3FileDatabase -// | -// +---- HashStorage // Handles known hashes. Serves as a reference when new files are hashed. -// | -// +---- RemoteDirectoryStorage // Stores the list of shared files at friends -// | | -// | +---- InternalFileHierarchyStorage -// | -// +---- LocalDirectoryStorage // Stores the list of locally shared files -// | | -// | +---- InternalFileHierarchyStorage -// | -// +---- LocalDirectoryUpdater // Keeps the local lists up to date, by regularly crawling directories -// -#pragma once - -#include "ft/ftsearch.h" -#include "ft/ftextralist.h" -#include "retroshare/rsfiles.h" -#include "services/p3service.h" -#include "util/rstime.h" -#include "file_sharing/hash_cache.h" -#include "file_sharing/directory_storage.h" - -#include "pqi/p3cfgmgr.h" -#include "pqi/p3linkmgr.h" - -class RemoteDirectoryUpdater ; -class LocalDirectoryUpdater ; - -class RemoteDirectoryStorage ; -class LocalDirectoryStorage ; - -class RsFileListsSyncRequestItem ; -class RsFileListsSyncResponseItem ; -class RsFileListsBannedHashesItem ; - -class HashStorage ; - -struct PeerBannedFilesEntry -{ - std::set mBannedHashOfHash; - uint32_t mSessionId ; // used for when a friend sends multiple packets in separate items. - rstime_t mLastSent; -}; - -class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, public RsSharedFileService -{ - public: - typedef DirectoryStorage::EntryIndex EntryIndex; // this should probably be defined elsewhere - - virtual RsServiceInfo getServiceInfo(); - - struct RsFileListSyncRequest - { - RsPeerId peerId ; - EntryIndex index ; - // [...] more to add here - }; - - explicit p3FileDatabase(p3ServiceControl *mpeers); - ~p3FileDatabase(); - - void setExtraList(ftExtraList *f) { mExtraFiles = f ; } - /*! - * \brief forceSyncWithPeers - * - * Forces the synchronisation of the database with connected peers. This is triggered when e.g. a new group of friend is created, or when - * a friend was added/removed from a group. - */ - void forceSyncWithPeers() { NOT_IMPLEMENTED() ; } - - // derived from p3Service - // - virtual int tick() ; - - // ftSearch - virtual bool search(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const; - virtual int SearchKeywords(const std::list& keywords, std::list& results,FileSearchFlags flags,const RsPeerId& peer_id) ; - virtual int SearchBoolExp(RsRegularExpression::Expression *exp, std::list& results,FileSearchFlags flags,const RsPeerId& peer_id) const ; - - // Extra file list - virtual bool removeExtraFile(const RsFileHash& hash); - - // Interface for browsing dir hierarchy - // - - void stopThreads() ; - void startThreads() ; - - bool findChildPointer(void *ref, int row, void *& result, FileSearchFlags flags) const; - - // void * here is the type expected by the abstract model index from Qt. It gets turned into a DirectoryStorage::EntryIndex internally. - - void requestDirUpdate(void *ref) ; // triggers an update. Used when browsing. - int RequestDirDetails(void *, DirDetails&, FileSearchFlags) const ; - uint32_t getType(void *, FileSearchFlags flags) const ; - - // proxy method used by the web UI. Dont't delete! - int RequestDirDetails(const RsPeerId& uid, const std::string& path, DirDetails &details)const; - - // set/update shared directories - - void setSharedDirectories(const std::list& dirs); - void getSharedDirectories(std::list& dirs); - void updateShareFlags(const SharedDirInfo& info) ; - bool convertSharedFilePath(const std::string& path,std::string& fullpath); - - void setIgnoreLists(const std::list& ignored_prefixes,const std::list& ignored_suffixes, uint32_t ignore_flags) ; - bool getIgnoreLists(std::list& ignored_prefixes,std::list& ignored_suffixes, uint32_t& ignore_flags) ; - - void setIgnoreDuplicates(bool i) ; - bool ignoreDuplicates() const ; - - void setMaxShareDepth(int i) ; - int maxShareDepth() const ; - - bool banFile(const RsFileHash& real_file_hash, const std::string& filename, uint64_t file_size) ; - bool unbanFile(const RsFileHash& real_file_hash); - bool isFileBanned(const RsFileHash& hash) ; - bool getPrimaryBannedFilesList(std::map& banned_files) ; - bool trustFriendNodesForBannedFiles() const ; - void setTrustFriendNodesForBannedFiles(bool b) ; - - // computes/gathers statistics about shared directories - - int getSharedDirStatistics(const RsPeerId& pid,SharedDirStats& stats); - - // interface for hash caching - - void setWatchPeriod(uint32_t seconds); - uint32_t watchPeriod() ; - void setWatchEnabled(bool b) ; - bool watchEnabled() ; - - bool followSymLinks() const; - void setFollowSymLinks(bool b) ; - - // interfact for directory parsing - - void forceDirectoryCheck(bool add_safe_delay); // Force re-sweep the directories and see what's changed - bool inDirectoryCheck(); - void togglePauseHashingProcess(); - bool hashingProcessPaused(); - - protected: - void getExtraFilesDirDetails(void *ref,DirectoryStorage::EntryIndex e,DirDetails& d) const; - - int filterResults(const std::list& firesults,std::list& results,FileSearchFlags flags,const RsPeerId& peer_id) const; - std::string makeRemoteFileName(const RsPeerId& pid) const; - - // Derived from p3Config - // - virtual bool loadList(std::list& items); - virtual bool saveList(bool &cleanup, std::list&); - virtual RsSerialiser *setupSerialiser() ; - - void cleanup(); - void tickRecv(); - void tickSend(); - - void checkSendBannedFilesInfo(); - - private: - p3ServiceControl *mServCtrl ; - RsPeerId mOwnId ; - - typedef uint64_t DirSyncRequestId ; - - static DirSyncRequestId makeDirSyncReqId(const RsPeerId& peer_id, const RsFileHash &hash) ; - - // utility functions to send items with some maximum size. - - void splitAndSendItem(RsFileListsSyncResponseItem *ritem); - RsFileListsSyncResponseItem *recvAndRebuildItem(RsFileListsSyncResponseItem *ritem); - - /*! - * \brief generateAndSendSyncRequest - * \param rds Remote directory storage for the request - * \param e Entry index to update - * \return true if the request is correctly sent. - */ - bool locked_generateAndSendSyncRequest(RemoteDirectoryStorage *rds,const DirectoryStorage::EntryIndex& e); - - // File sync request queues. The fast one is used for online browsing when friends are connected. - // The slow one is used for background update of file lists. - // - std::map mFastRequestQueue ; - std::map mSlowRequestQueue ; - - // Directory storage hierarchies - // - // The remote one is the reference for the PeerId index below: - // RemoteDirectories[ getFriendIndex(pid) - 1] = RemoteDirectoryStorage(pid) - - std::vector mRemoteDirectories ; - LocalDirectoryStorage *mLocalSharedDirs ; - LocalDirectoryUpdater *mLocalDirWatcher ; - ftExtraList *mExtraFiles; - - // utility functions to make/get a pointer out of an (EntryIndex,PeerId) pair. This is further documented in the .cc - - template static bool convertEntryIndexToPointer(const EntryIndex &e, uint32_t friend_index, void *& p); - template static bool convertPointerToEntryIndex(const void *p, EntryIndex& e, uint32_t& friend_index) ; - - uint32_t locked_getFriendIndex(const RsPeerId& pid); - - void handleDirSyncRequest (RsFileListsSyncRequestItem *) ; - void handleDirSyncResponse (RsFileListsSyncResponseItem *&) ; - - std::map mFriendIndexMap ; - std::vector mFriendIndexTab; - - // Directory synchronization - // - struct DirSyncRequestData - { - RsPeerId peer_id ; - rstime_t request_TS ; - uint32_t flags ; - }; - - rstime_t mLastRemoteDirSweepTS ; // TS for friend list update - std::map mPendingSyncRequests ; // pending requests, waiting for an answer - std::map mPartialResponseItems; - - void locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *rds, DirectoryStorage::EntryIndex e, int depth); - - // We use a shared file cache as well, to avoid re-hashing files with known modification TS and equal name. - // - HashStorage *mHashCache ; - - // Local flags and mutexes - - mutable RsMutex mFLSMtx ; - uint32_t mUpdateFlags ; - std::string mFileSharingDir ; - rstime_t mLastCleanupTime; - rstime_t mLastDataRecvTS ; - - // File filtering. Not explicitly related to shared files, but has its place here - // - - std::map mPrimaryBanList ; // primary list (user controlled) of files banned from FT search and forwarding. map - std::map mPeerBannedFiles ; // records of which files other peers ban, stored as H(H(f)) - std::set mBannedFileList ; // list of banned hashes. This include original hashs and H(H(f)) when coming from friends. - mutable std::vector mExtraFilesCache; // cache for extra files, to avoid requesting them too often. - mutable rstime_t mLastExtraFilesCacheUpdate ; - bool mTrustFriendNodesForBannedFiles ; - bool mBannedFileListNeedsUpdate; - rstime_t mLastPrimaryBanListChangeTimeStamp; - - void locked_sendBanInfo(const RsPeerId& pid); - void handleBannedFilesInfo(RsFileListsBannedHashesItem *item); -}; - diff --git a/libretroshare/src/file_sharing/rsfilelistitems.cc b/libretroshare/src/file_sharing/rsfilelistitems.cc deleted file mode 100644 index 4ac90af10..000000000 --- a/libretroshare/src/file_sharing/rsfilelistitems.cc +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: rsfilelistsitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ -#include "serialiser/rsbaseserial.h" - -#include "serialiser/rstypeserializer.h" - -#include "file_sharing/rsfilelistitems.h" - -void RsFileListsSyncRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,entry_hash,"entry_hash") ; - RsTypeSerializer::serial_process(j,ctx,flags ,"flags") ; - RsTypeSerializer::serial_process(j,ctx,last_known_recurs_modf_TS,"last_known_recurs_modf_TS") ; - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; -} -void RsFileListsSyncResponseItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,entry_hash, "entry_hash") ; - RsTypeSerializer::serial_process (j,ctx,checksum, "checksum") ; - RsTypeSerializer::serial_process (j,ctx,flags, "flags") ; - RsTypeSerializer::serial_process (j,ctx,last_known_recurs_modf_TS,"last_known_recurs_modf_TS") ; - RsTypeSerializer::serial_process (j,ctx,request_id, "request_id") ; - RsTypeSerializer::serial_process(j,ctx,directory_content_data, "directory_content_data") ; -} -void RsFileListsBannedHashesItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,session_id ,"session_id") ; - RsTypeSerializer::serial_process(j,ctx,encrypted_hashes,"encrypted_hashes") ; -} -void RsFileListsBannedHashesConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,primary_banned_files_list,"primary_banned_files_list") ; -} - -RsItem *RsFileListsSerialiser::create_item(uint16_t service,uint8_t type) const -{ - if(service != RS_SERVICE_TYPE_FILE_DATABASE) - return NULL ; - - switch(type) - { - case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM: return new RsFileListsSyncRequestItem(); - case RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM: return new RsFileListsSyncResponseItem(); - case RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_ITEM: return new RsFileListsBannedHashesItem(); - case RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_CONFIG_ITEM: return new RsFileListsBannedHashesConfigItem(); - default: - return NULL ; - } -} -void RsFileListsSyncResponseItem::clear() -{ - directory_content_data.TlvClear(); -} diff --git a/libretroshare/src/file_sharing/rsfilelistitems.h b/libretroshare/src/file_sharing/rsfilelistitems.h deleted file mode 100644 index a8c84e18b..000000000 --- a/libretroshare/src/file_sharing/rsfilelistitems.h +++ /dev/null @@ -1,141 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: rsfilelistsitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Mr.Alice * - * * - * 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 . * - * * - ******************************************************************************/ -#pragma once - -#include -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvkeys.h" -#include "gxs/rsgxsdata.h" - -#include "serialiser/rsserializer.h" -#include "retroshare/rsfiles.h" - -const uint8_t RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM = 0x01; -const uint8_t RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_FILELISTS_CONFIG_ITEM = 0x03; -const uint8_t RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_ITEM = 0x04; -const uint8_t RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_CONFIG_ITEM = 0x05; - -/*! - * Base class for filelist sync items - */ -class RsFileListsItem : public RsItem -{ -public: - explicit RsFileListsItem(uint8_t subtype) - : RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_FILE_DATABASE, subtype) - { - setPriorityLevel(QOS_PRIORITY_RS_SLOW_SYNC_REQUEST); // this is the default. Someitems may be faster, on demand. - return; - } - virtual ~RsFileListsItem(){} - - virtual void clear() = 0; - - static const uint32_t FLAGS_SYNC_REQUEST = 0x0001 ; - static const uint32_t FLAGS_SYNC_RESPONSE = 0x0002 ; - static const uint32_t FLAGS_SYNC_DIR_CONTENT = 0x0004 ; - static const uint32_t FLAGS_ENTRY_UP_TO_DATE = 0x0008 ; - static const uint32_t FLAGS_ENTRY_WAS_REMOVED = 0x0010 ; - static const uint32_t FLAGS_SYNC_PARTIAL = 0x0020 ; - static const uint32_t FLAGS_SYNC_PARTIAL_END = 0x0040 ; -}; - -/*! - * Use to request synchronization on a specific directory. Also used to respond that the directory is up to date. - */ -class RsFileListsSyncRequestItem : public RsFileListsItem -{ -public: - - RsFileListsSyncRequestItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM), flags(0), last_known_recurs_modf_TS(0), request_id(0) {} - - virtual void clear(){} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsFileHash entry_hash ; // hash of the directory to sync - uint32_t flags; // used to say that it's a request or a response, say that the directory has been removed, ask for further update, etc. - uint32_t last_known_recurs_modf_TS; // time of last modification, computed over all files+directories below. - uint64_t request_id; // use to determine if changes that have occured since last hash -}; - -class RsFileListsSyncResponseItem : public RsFileListsItem -{ -public: - - RsFileListsSyncResponseItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM), flags(0), last_known_recurs_modf_TS(0), request_id(0) {} - - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsFileHash entry_hash ; // hash of the directory to sync - RsFileHash checksum ; // checksum of the bindary data, for checking - uint32_t flags; // is it a partial/final item (used for large items only) - uint32_t last_known_recurs_modf_TS; // time of last modification, computed over all files+directories below. - uint64_t request_id; // use to determine if changes that have occured since last hash - - RsTlvBinaryData directory_content_data ; // encoded binary data. This allows to vary the encoding format, in a way that is transparent to the serialiser. -}; - -class RsFileListsBannedHashesItem: public RsFileListsItem -{ -public: - RsFileListsBannedHashesItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_ITEM){} - - virtual void clear() { encrypted_hashes.clear(); } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t session_id ; // used to allow to send in multiple parts. - std::set encrypted_hashes ;// hash of hash for each banned file. -}; - -class RsFileListsBannedHashesConfigItem: public RsFileListsItem -{ -public: - RsFileListsBannedHashesConfigItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_CONFIG_ITEM){} - - virtual void clear() { primary_banned_files_list.clear(); } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - std::map primary_banned_files_list ; -}; - -class RsFileListsSerialiser : public RsServiceSerializer -{ -public: - - RsFileListsSerialiser() : RsServiceSerializer(RS_SERVICE_TYPE_FILE_DATABASE) {} - - virtual ~RsFileListsSerialiser() {} - - virtual RsItem *create_item(uint16_t service,uint8_t type) const ; -}; - - diff --git a/libretroshare/src/ft/ftchunkmap.cc b/libretroshare/src/ft/ftchunkmap.cc deleted file mode 100644 index 8b0c60007..000000000 --- a/libretroshare/src/ft/ftchunkmap.cc +++ /dev/null @@ -1,708 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftchunkmap.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010 by Cyril Soler * - * * - * 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 . * - * * - ******************************************************************************/ - -/******** - * #define DEBUG_FTCHUNK 1 - *********/ - -#ifdef DEBUG_FTCHUNK -#include -#endif -#include -#include -#include "retroshare/rspeers.h" -#include "ftchunkmap.h" -#include "util/rstime.h" - -static const uint32_t SOURCE_CHUNK_MAP_UPDATE_PERIOD = 60 ; //! TTL for chunkmap info -static const uint32_t INACTIVE_CHUNK_TIME_LAPSE = 3600 ; //! TTL for an inactive chunk -static const uint32_t FT_CHUNKMAP_MAX_CHUNK_JUMP = 50 ; //! Maximum chunk jump in progressive DL mode -static const uint32_t FT_CHUNKMAP_MAX_SLICE_REASK_DELAY = 10 ; //! Maximum time to re-ask a slice to another peer at end of transfer - -std::ostream& operator<<(std::ostream& o,const ftChunk& c) -{ - return o << "\tChunk [" << c.offset << "] size: " << c.size << " ChunkId: " << c.id << " Age: " << time(NULL) - c.ts << ", owner: " << c.peer_id ; -} - -// Chunk: very bold implementation for now. We should compress the bits to have -// 32 of them per uint32_t value, of course! -// -Chunk::Chunk(uint64_t start,uint32_t size) - : _start(start),_offset(start),_end( (uint64_t)size + start ) -{ -} - -void Chunk::getSlice(uint32_t size_hint,ftChunk& chunk) -{ - // Take the current offset - chunk.offset = _offset ; - chunk.size = std::min(size_hint,(uint32_t)(_end-_offset)) ; - chunk.id = _offset ; - chunk.ts = time(NULL) ; - - // push the slice marker into currently handled slices. - _offset += chunk.size ; -} - -ChunkMap::ChunkMap(uint64_t s,bool availability) - : _file_size(s), - _chunk_size(CHUNKMAP_FIXED_CHUNK_SIZE), // 1MB chunks - _assume_availability(availability) -{ - uint64_t n = s/(uint64_t)_chunk_size ; - if(s% (uint64_t)_chunk_size != 0) - ++n ; - - _map.resize(n,FileChunksInfo::CHUNK_OUTSTANDING) ; - _strategy = FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE ; - _total_downloaded = 0 ; - _file_is_complete = false ; -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::ChunkMap: starting new chunkmap:" << std::endl ; - std::cerr << " File size: " << s << std::endl ; - std::cerr << " Strategy: " << _strategy << std::endl ; - std::cerr << " ChunkSize: " << _chunk_size << std::endl ; - std::cerr << " Number of Chunks: " << n << std::endl ; - std::cerr << " Data: " ; - for(uint32_t i=0;i<_map.size();++i) - std::cerr << _map[i] ; - std::cerr << std::endl ; -#endif -} - -void ChunkMap::setAvailabilityMap(const CompressedChunkMap& map) -{ - // do some sanity check - // - - if( (((int)_map.size()-1)>>5) >= (int)map._map.size() ) - { - std::cerr << "ChunkMap::setPeerAvailabilityMap: Compressed chunkmap received is too small or corrupted." << std::endl; - return ; - } - - // copy the map - // - _file_is_complete = true ; - _total_downloaded = 0 ; - - for(uint32_t i=0;i<_map.size();++i) - if(map[i] > 0) - { - _map[i] = FileChunksInfo::CHUNK_DONE ; - _total_downloaded += sizeOfChunk(i) ; - } - else - { - _map[i] = FileChunksInfo::CHUNK_OUTSTANDING ; - _file_is_complete = false ; - } -} - -void ChunkMap::dataReceived(const ftChunk::OffsetInFile& cid) -{ - // 1 - find which chunk contains the received data. - // - - // trick: cid is the chunk offset. So we use it to get the chunk number. - int n = (uint64_t)cid/_chunk_size ; - - std::map::iterator itc(_slices_to_download.find(n)) ; - - if(itc == _slices_to_download.end()) - { - std::cerr << "!!! ChunkMap::dataReceived: error: ChunkId " << cid << " corresponds to chunk number " << n << ", which is not being downloaded!" << std::endl ; -#ifdef DEBUG_FTCHUNK - assert(false) ; -#endif - return ; - } - - std::map::iterator it(itc->second._slices.find(cid)) ; - - if(it == itc->second._slices.end()) - { - std::cerr << "!!! ChunkMap::dataReceived: chunk " << cid << " is not found in slice lst of chunk number " << n << std::endl ; -#ifdef DEBUG_FTCHUNK - assert(false) ; -#endif - return ; - } - - _total_downloaded += it->second.size ; - itc->second._remains -= it->second.size ; - itc->second._slices.erase(it) ; - itc->second._last_data_received = time(NULL) ; // update time stamp - -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::dataReceived: received data chunk " << cid << " for chunk number " << n << ", local remains=" << itc->second._remains << ", total downloaded=" << _total_downloaded << ", remains=" << _file_size - _total_downloaded << std::endl ; -#endif - if(itc->second._remains == 0) // the chunk was completely downloaded - { -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::dataReceived: Chunk is complete. Removing it." << std::endl ; -#endif - - _map[n] = FileChunksInfo::CHUNK_CHECKING ; - - if(n > 0 || _file_size > CHUNKMAP_FIXED_CHUNK_SIZE) // dont' put <1MB files into checking mode. This is useless. - _chunks_checking_queue.push_back(n) ; - else - _map[n] = FileChunksInfo::CHUNK_DONE ; - - _slices_to_download.erase(itc) ; - - updateTotalDownloaded() ; - } -} - -void ChunkMap::updateTotalDownloaded() -{ - _total_downloaded = 0 ; - _file_is_complete = true ; - - // First, round over chunk map to get the raw info. - // - for(uint32_t i=0;i<_map.size();++i) - switch(_map[i]) - { - case FileChunksInfo::CHUNK_CHECKING: _file_is_complete = false ; - /* fallthrough */ - case FileChunksInfo::CHUNK_DONE: _total_downloaded += sizeOfChunk(i) ; - break ; - default: - _file_is_complete = false ; - } - - // Then go through active chunks. - // - for(std::map::const_iterator itc(_slices_to_download.begin());itc!=_slices_to_download.end();++itc) - { - if(_map[itc->first] == FileChunksInfo::CHUNK_CHECKING) - _total_downloaded -= sizeOfChunk(itc->first) ; - - _total_downloaded += sizeOfChunk(itc->first) - itc->second._remains ; - - if(_file_is_complete) - std::cerr << "ChunkMap::updateTotalDownloaded(): ERROR: file still has pending slices but all chunks are marked as DONE !!" << std::endl; - } -} - -void ChunkMap::getChunksToCheck(std::vector& chunks_crc_to_ask) -{ - chunks_crc_to_ask.clear() ; - - for(uint32_t i=0;i<_chunks_checking_queue.size();) - { - chunks_crc_to_ask.push_back(_chunks_checking_queue[i]) ; - - // remove that chunk from the queue - - _chunks_checking_queue[i] = _chunks_checking_queue.back() ; - _chunks_checking_queue.pop_back() ; - } -} - -void ChunkMap::setChunkCheckingResult(uint32_t chunk_number,bool check_succeeded) -{ - // Find the chunk is the waiting queue. Remove it, and mark it as done. - // - if(_map[chunk_number] != FileChunksInfo::CHUNK_CHECKING) - { - std::cerr << "(EE) ChunkMap: asked to set checking result of chunk " << chunk_number<< " that is not marked as being checked!!" << std::endl; - return ; - } - - if(check_succeeded) - { - _map[chunk_number] = FileChunksInfo::CHUNK_DONE ; - - // We also check whether the file is complete or not. - - _file_is_complete = true ; - - for(uint32_t i=0;i<_map.size();++i) - if(_map[i] != FileChunksInfo::CHUNK_DONE) - { - _file_is_complete = false ; - break ; - } - } - else - { - _total_downloaded -= sizeOfChunk(chunk_number) ; // restore completion. - _map[chunk_number] = FileChunksInfo::CHUNK_OUTSTANDING ; - } -} - -bool ChunkMap::reAskPendingChunk( const RsPeerId& peer_id, - uint32_t /*size_hint*/, - uint64_t& offset, uint32_t& size) -{ - // make sure that we're at the end of the file. No need to be too greedy in the middle of it. - - for(uint32_t i=0;i<_map.size();++i) - if(_map[i] == FileChunksInfo::CHUNK_OUTSTANDING) - return false ; - - rstime_t now = time(NULL); - - for(std::map::iterator it(_slices_to_download.begin());it!=_slices_to_download.end();++it) - for(std::map::iterator it2(it->second._slices.begin());it2!=it->second._slices.end();++it2) - if(it2->second.request_time + FT_CHUNKMAP_MAX_SLICE_REASK_DELAY < now && it2->second.peers.end()==it2->second.peers.find(peer_id)) - { - offset = it2->first; - size = it2->second.size ; - -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::reAskPendingChunk: re-asking slice (" << offset << ", " << size << ") to peer " << peer_id << std::endl; -#endif - - it2->second.request_time = now ; - it2->second.peers.insert(peer_id) ; - - return true ; - } - - return false ; -} - -// Warning: a chunk may be empty, but still being downloaded, so asking new slices from it -// will produce slices of size 0. This happens at the end of each chunk. -// --> I need to get slices from the next chunk, in such a case. -// --> solution: -// - have too chunks maps: -// 1 indexed by peer id to feed the getChunk method -// - chunks pushed when new chunks are needed -// - chunks removed when empty -// 1 indexed by chunk id to account for chunks being downloaded -// - chunks pushed when new chunks are needed -// - chunks removed when completely downloaded -// -bool ChunkMap::getDataChunk(const RsPeerId& peer_id,uint32_t size_hint,ftChunk& chunk,bool& source_chunk_map_needed) -{ -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::getDataChunk: size_hint = " << size_hint << std::endl ; -#endif - // 1 - find if this peer already has an active chunk. - // - std::map::iterator it = _active_chunks_feed.find(peer_id) ; - std::map::iterator falsafe_it = _active_chunks_feed.end() ; - - if(it == _active_chunks_feed.end()) - { - SourceChunksInfo *sci = getSourceChunksInfo(peer_id) ; - - // 0 - Look into other pending chunks and slice from here. We only consider chunks with size smaller than - // the requested size, - // - for(std::map::iterator pit(_active_chunks_feed.begin());pit!=_active_chunks_feed.end();++pit) - { - uint32_t c = pit->second._start / _chunk_size ; - - if(!(sci->is_full || sci->cmap[c])) // check that the chunk is available for requested peer. - continue ; - - ChunkDownloadInfo& cdi(_slices_to_download[c]) ; - falsafe_it = pit ; // let's keep this one just in case. - - if(cdi._slices.rbegin() != cdi._slices.rend() && cdi._slices.rbegin()->second.size*0.7 <= (float)size_hint) - { - it = pit ; -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::getDataChunk: Sharing slice " << pit->second._start << " of peer " << pit->first << " for peer " << peer_id << std::endl; -#endif - break ; - } -#ifdef DEBUG_FTCHUNK - else - std::cerr << "*** ChunkMap::getDataChunk: Not Sharing slice " << pit->second._start << " of peer " << pit->first << " for peer " << peer_id << ", because current peer is too slow" << std::endl; -#endif - } - - if(it == _active_chunks_feed.end()) // not found. Find a new chunk. - { - // 1 - select an available chunk id for this peer. - // - uint32_t c = getAvailableChunk(peer_id,source_chunk_map_needed) ; - - if(c >= _map.size()) - if(falsafe_it != _active_chunks_feed.end()) // no chunk available. Let's see if we can still take an active--faster--chunk. - { - it = falsafe_it ; -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::getDataChunk: Using falsafe chunk " << it->second._start << " of peer " << it->first << " for peer " << peer_id << std::endl; -#endif - } - else - return false ; // no more availabel chunks, no falsafe case. - else - { - // 2 - add the chunk in the list of active chunks, and mark it as being downloaded - // - uint32_t soc = sizeOfChunk(c) ; - _active_chunks_feed[peer_id] = Chunk( c*(uint64_t)_chunk_size, soc ) ; - _map[c] = FileChunksInfo::CHUNK_ACTIVE ; - _slices_to_download[c]._remains = soc ; // init the list of slices to download - it = _active_chunks_feed.find(peer_id) ; -#ifdef DEBUG_FTCHUNK - std::cout << "*** ChunkMap::getDataChunk: Allocating new chunk " << c << " for peer " << peer_id << std::endl ; -#endif - } - } - } -#ifdef DEBUG_FTCHUNK - else - std::cout << "*** ChunkMap::getDataChunk: Re-using chunk " << it->second._start/_chunk_size << " for peer " << peer_id << std::endl ; -#endif - - // Get the first slice of the chunk, that is at most of length size - // - it->second.getSlice(size_hint,chunk) ; - _slices_to_download[chunk.offset/_chunk_size]._last_data_received = time(NULL) ; - - ChunkDownloadInfo::SliceRequestInfo& r(_slices_to_download[chunk.offset/_chunk_size]._slices[chunk.id]); - - r.size = chunk.size ; - r.request_time = time(NULL); - r.peers.insert(peer_id); - - chunk.peer_id = peer_id ; - -#ifdef DEBUG_FTCHUNK - std::cout << "*** ChunkMap::getDataChunk: returning slice " << chunk << " for peer " << it->first << std::endl ; -#endif - if(it->second.empty()) - _active_chunks_feed.erase(it) ; - - return true ; -} - -void ChunkMap::removeInactiveChunks(std::vector& to_remove) -{ - to_remove.clear() ; - rstime_t now = time(NULL) ; - - for(std::map::iterator it(_slices_to_download.begin());it!=_slices_to_download.end();) - if(now - it->second._last_data_received > (int)INACTIVE_CHUNK_TIME_LAPSE) - { -#ifdef DEBUG_FTCHUNK - std::cerr << "ChunkMap::removeInactiveChunks(): removing inactive chunk " << it->first << ", time lapse=" << now - it->second._last_data_received << std::endl ; -#endif - // First, remove all slices from this chunk - // - std::map::iterator tmp(it) ; - - for(std::map::const_iterator it2(it->second._slices.begin());it2!=it->second._slices.end();++it2) - to_remove.push_back(it2->first) ; - - _map[it->first] = FileChunksInfo::CHUNK_OUTSTANDING ; // reset the chunk - - _total_downloaded -= (sizeOfChunk(it->first) - it->second._remains) ; // restore completion. - - // Also remove the chunk from the chunk feed, to free the associated peer. - // - for(std::map::iterator it3=_active_chunks_feed.begin();it3!=_active_chunks_feed.end();) - if(it3->second._start == _chunk_size*uint64_t(it->first)) - { - std::map::iterator tmp3 = it3 ; - ++it3 ; - _active_chunks_feed.erase(tmp3) ; - } - else - ++it3 ; - - ++it ; - _slices_to_download.erase(tmp) ; - } - else - ++it ; -} - -bool ChunkMap::isChunkAvailable(uint64_t offset, uint32_t chunk_size) const -{ - return hasChunkState(offset, chunk_size, FileChunksInfo::CHUNK_DONE); -} - -bool ChunkMap::isChunkOutstanding(uint64_t offset, uint32_t chunk_size) const -{ - return hasChunkState(offset, chunk_size, FileChunksInfo::CHUNK_OUTSTANDING); -} - -bool ChunkMap::hasChunkState(uint64_t offset, uint32_t chunk_size, FileChunksInfo::ChunkState state) const -{ - uint32_t chunk_number_start = offset/(uint64_t)_chunk_size ; - uint32_t chunk_number_end = (offset+(uint64_t)chunk_size)/(uint64_t)_chunk_size ; - - if((offset+(uint64_t)chunk_size) % (uint64_t)_chunk_size != 0) - ++chunk_number_end ; - - // It's possible that chunk_number_start==chunk_number_end+1, but for this we need to have - // chunk_size=0, and offset%_chunk_size=0, so the response "true" is still valid. - // - for(uint32_t i=chunk_number_start;i::iterator it(_peers_chunks_availability.find(peer_id)) ; - - // Do we have a chunk map for this file source ? - // - if yes, we use it - // - if no, - // - if availability is assumed, let's build a plain chunkmap for it - // - otherwise, refuse the transfer, but still ask for the chunkmap - // - // We first test whether the source has a record of not. If not, we fill a new record. - // For availability sources we fill it plain, otherwise, we fill it blank. - // - if(it == _peers_chunks_availability.end()) - { - SourceChunksInfo& pchunks(_peers_chunks_availability[peer_id]) ; - - // Ok, we don't have the info, so two cases: - // - peer_id is a not a turtle peer, so he is considered having the full file source, so we init with a plain chunkmap - // - otherwise, a source map needs to be obtained, so we init with a blank chunkmap - // - if(_assume_availability) - { - pchunks.cmap._map.resize( CompressedChunkMap::getCompressedSize(_map.size()),~(uint32_t)0 ) ; - pchunks.TS = 0 ; - pchunks.is_full = true ; - } - else - { - pchunks.cmap._map.resize( CompressedChunkMap::getCompressedSize(_map.size()),0 ) ; - pchunks.TS = 0 ; - pchunks.is_full = false ; - } - - it = _peers_chunks_availability.find(peer_id) ; - } - return &(it->second) ; -} - -void ChunkMap::getSourcesList(uint32_t chunk_number,std::vector& sources) -{ - sources.clear() ; - - for(std::map::const_iterator it(_peers_chunks_availability.begin());it!=_peers_chunks_availability.end();++it) - if(it->second.cmap[chunk_number]) - sources.push_back(it->first) ; -} - -uint32_t ChunkMap::getAvailableChunk(const RsPeerId& peer_id,bool& map_is_too_old) -{ - // Quite simple strategy: Check for 1st availabe chunk for this peer starting from the given start location. - // - SourceChunksInfo *peer_chunks = getSourceChunksInfo(peer_id) ; - - // If the info is too old, we ask for a new one. When the map is full, we ask 10 times less, as it's probably not - // useful to get a new map that will also be full, but because we need to be careful not to mislead information, - // we still keep asking. - // - rstime_t now = time(NULL) ; - - if((!peer_chunks->is_full) && ((int)now - (int)peer_chunks->TS > (int)SOURCE_CHUNK_MAP_UPDATE_PERIOD)) - { - map_is_too_old = true ;// We will re-ask but not before some seconds. - peer_chunks->TS = now ; - } - else - map_is_too_old = false ;// the map is not too old - - uint32_t available_chunks = 0 ; - uint32_t available_chunks_before_max_dist = 0 ; - - for(unsigned int i=0;i<_map.size();++i) - if(_map[i] == FileChunksInfo::CHUNK_OUTSTANDING) - { - if(peer_chunks->is_full || peer_chunks->cmap[i]) - ++available_chunks ; - } - else - available_chunks_before_max_dist = available_chunks ; - - if(available_chunks > 0) - { - uint32_t chosen_chunk_number ; - - switch(_strategy) - { - case FileChunksInfo::CHUNK_STRATEGY_STREAMING: chosen_chunk_number = 0 ; - break ; - case FileChunksInfo::CHUNK_STRATEGY_RANDOM: chosen_chunk_number = rand() % available_chunks ; - break ; - case FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE: chosen_chunk_number = rand() % std::min(available_chunks, available_chunks_before_max_dist+FT_CHUNKMAP_MAX_CHUNK_JUMP) ; - break ; - default: - chosen_chunk_number = 0 ; - } - uint32_t j=0 ; - - for(uint32_t i=0;i<_map.size();++i) - if(_map[i] == FileChunksInfo::CHUNK_OUTSTANDING && (peer_chunks->is_full || peer_chunks->cmap[i])) - { - if(j == chosen_chunk_number) - { -#ifdef DEBUG_FTCHUNK - std::cerr << "ChunkMap::getAvailableChunk: returning chunk " << i << " for peer " << peer_id << std::endl; -#endif - return i ; - } - else - ++j ; - } - } - -#ifdef DEBUG_FTCHUNK - std::cout << "!!! ChunkMap::getAvailableChunk: No available chunk from peer " << peer_id << ": returning false" << std::endl ; -#endif - return _map.size() ; -} - -void ChunkMap::getChunksInfo(FileChunksInfo& info) const -{ - info.file_size = _file_size ; - info.chunk_size = _chunk_size ; - info.chunks = _map ; - info.strategy = _strategy ; - - info.active_chunks.clear() ; - - for(std::map::const_iterator it(_slices_to_download.begin());it!=_slices_to_download.end();++it) - info.active_chunks.push_back(std::pair(it->first,it->second._remains)) ; - - info.compressed_peer_availability_maps.clear() ; - - for(std::map::const_iterator it(_peers_chunks_availability.begin());it!=_peers_chunks_availability.end();++it) - info.compressed_peer_availability_maps[it->first] = it->second.cmap ; -} - -void ChunkMap::removeFileSource(const RsPeerId& peer_id) -{ - std::map::iterator it(_peers_chunks_availability.find(peer_id)) ; - - if(it == _peers_chunks_availability.end()) - return ; - - _peers_chunks_availability.erase(it) ; -} - -void ChunkMap::getAvailabilityMap(CompressedChunkMap& compressed_map) const -{ - compressed_map = CompressedChunkMap(_map) ; - -#ifdef DEBUG_FTCHUNK - std::cerr << "ChunkMap:: retrieved availability map of size " << _map.size() << ", chunk_size=" << _chunk_size << std::endl ; -#endif -} - -void ChunkMap::forceCheck() -{ - for(uint32_t i=0;i<_map.size();++i) - { - _map[i] = FileChunksInfo::CHUNK_CHECKING ; - _chunks_checking_queue.push_back(i) ; - } - - updateTotalDownloaded() ; -} - -uint32_t ChunkMap::getNumberOfChunks(uint64_t size) -{ - uint64_t n = size/(uint64_t)CHUNKMAP_FIXED_CHUNK_SIZE ; - - if(size % (uint64_t)CHUNKMAP_FIXED_CHUNK_SIZE != 0) - ++n ; - - uint32_t value = n & 0xffffffffull ; - - if((uint64_t)value != n) - { - std::cerr << "ERROR: number of chunks is a totally absurd value. File size is " << size << ", chunks are " << n << "!!" << std::endl ; - return 0 ; - } - return value ; -} - -void ChunkMap::buildPlainMap(uint64_t size, CompressedChunkMap& map) -{ - uint32_t n = getNumberOfChunks(size) ; - - map = CompressedChunkMap(n,~uint32_t(0)) ; -} - - diff --git a/libretroshare/src/ft/ftchunkmap.h b/libretroshare/src/ft/ftchunkmap.h deleted file mode 100644 index a9e7eb900..000000000 --- a/libretroshare/src/ft/ftchunkmap.h +++ /dev/null @@ -1,260 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftchunkmap.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010 by Cyril Soler * - * * - * 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 . * - * * - ******************************************************************************/ - -#pragma once - -#include -#include "retroshare/rstypes.h" - -// ftChunkMap: -// - handles chunk map over a complete file -// - mark down which chunk is being downloaded by which peer -// - allocate data ranges of any requested size for a given peer -// - continuing an existing chunk -// - allocating a new chunk -// -// Download mecanism: -// - ftFileCreator handles a list of active slices, and periodically resends requests every 20 sec. -// Slices have arbitrary size (less than a chunk), depending on the transfer rate. -// When receiving data, ftFileCreator shrinks its slices until they get complete. When a slice is finished, it -// notifies ftChunkMap that this slice is done. -// -// - ftChunkMap maintains two levels: -// - the chunk level (Chunks a 1MB long) with a map of who has which chunk and what locally is the state of -// each chunk -// - the slice level: each active chunk is cut into slices (basically a list of intervalls) being downloaded, and -// a remaining slice to cut off new candidates. When notified for a complete slice, ftChunkMap removed the -// corresponding acive slice. When asked a slice, ftChunkMap cuts out a slice from the remaining part of the chunk -// to download, sends the slice's coordinates and gives a unique slice id (such as the slice offset). - - -// This class handles a slice of a chunk of arbitrary uint32_t size, at the level of ftFileCreator - -class ftController ; - -class ftChunk -{ - public: - typedef uint64_t OffsetInFile ; - - ftChunk():offset(0), size(0), id(0), ts(0),ref_cnt(NULL) {} - - friend std::ostream& operator<<(std::ostream& o,const ftChunk& f) ; - - uint64_t offset; // current offset of the slice - uint64_t size; // size remaining to download - OffsetInFile id ; // id of the chunk. Equal to the starting offset of the chunk - rstime_t ts; // time of last data received - int *ref_cnt; // shared counter of number of sub-blocks. Used when a slice gets split. - RsPeerId peer_id ; -}; - -// This class handles a single fixed-sized chunk. Although each chunk is requested at once, -// it may be sent back into sub-chunks because of file transfer rate constraints. -// So the dataReceived function should be called to progressively complete the chunk, -// and the getChunk method should ask for a sub-chunk of a given size. -// -class Chunk -{ - public: - Chunk(): _start(0),_offset(0),_end(0) {} // only used in default std::map fillers - - Chunk(uint64_t start,uint32_t size) ; - - void getSlice(uint32_t size_hint,ftChunk& chunk) ; - - // Returns true when the chunk is complete - bool empty() const { return _offset == _end ; } - - // Array of intervalls of bytes to download. - // - uint64_t _start ; // const - uint64_t _offset ; // not const: handles the current offset within the chunk. - uint64_t _end ; // const -}; - -struct ChunkDownloadInfo -{ - public: - struct SliceRequestInfo - { - uint32_t size ; // size of the slice - rstime_t request_time ; // last request time - std::set peers ; // peers the slice was requested to. Normally only one, except at the end of the file. - }; - - std::map _slices ; - uint32_t _remains ; - rstime_t _last_data_received ; -}; - -class SourceChunksInfo -{ - public: - CompressedChunkMap cmap ; //! map of what the peer has/doens't have - rstime_t TS ; //! last update time for this info - bool is_full ; //! is the map full ? In such a case, re-asking for it is unnecessary. - - // Returns true if the offset is starting in a mapped chunk. - // - bool hasData(uint64_t offset,uint32_t fixed_chunk_size) const - { - if(is_full) - return true ; - - return cmap[offset / (uint64_t)fixed_chunk_size ] ; - } -}; - -class ChunkMap -{ - public: - static const uint32_t CHUNKMAP_FIXED_CHUNK_SIZE = 1024*1024 ; // 1 MB chunk - typedef uint32_t ChunkNumber ; - - /// Constructor. Decides what will be the size of chunks and how many there will be. - - ChunkMap(uint64_t file_size,bool assume_availability) ; - - /// destructor - virtual ~ChunkMap() {} - - /// Returns an slice of data to be asked to the peer within a chunk. - /// If a chunk is already been downloaded by this peer, take a slice at - /// the beginning of this chunk, or at least where it starts. - /// If not, randomly/streamly select a new chunk depending on the strategy. - /// adds an entry in the chunk_ids map, and sets up 1 interval for it. - /// the chunk should be available from the designated peer. - /// On return: - /// - source_chunk_map_needed = true if the source map should be asked - - virtual bool getDataChunk(const RsPeerId& peer_id,uint32_t size_hint,ftChunk& chunk,bool& source_chunk_map_needed) ; - - /// Returns an already pending slice that was being downloaded but hasn't arrived yet. This is mostly used at the end of the file - /// in order to re-ask pendign slices to active peers while slow peers take a lot of time to send their remaining slices. - /// - bool reAskPendingChunk(const RsPeerId& peer_id,uint32_t size_hint,uint64_t& offset,uint32_t& size); - - /// Notify received a slice of data. This needs to - /// - carve in the map of chunks what is received, what is not. - /// - tell which chunks are finished. For this, each interval must know what chunk number it has been attributed - /// when the interval is split in the middle, the number of intervals for the chunk is increased. If the interval is - /// completely covered by the data, the interval number is decreased. - - virtual void dataReceived(const ftChunk::OffsetInFile& c_id) ; - - /// Decides how chunks are selected. - /// STREAMING: the 1st chunk is always returned - /// RANDOM: a uniformly random chunk is selected among available chunks for the current source. - /// - - void setStrategy(FileChunksInfo::ChunkStrategy s) { _strategy = s ; } - FileChunksInfo::ChunkStrategy getStrategy() const { return _strategy ; } - - /// Properly fills an vector of fixed size chunks with availability or download state. - /// chunks is given with the proper number of chunks and we have to adapt to it. This can be used - /// to display square chunks in the gui or display a blue bar of availability by collapsing info from all peers. - /// The set method is not virtual because it has no reason to exist in the parent ftFileProvider - - virtual void getAvailabilityMap(CompressedChunkMap& cmap) const ; - void setAvailabilityMap(const CompressedChunkMap& cmap) ; - - /// Removes the source availability map. The map - void removeFileSource(const RsPeerId& peer_id) ; - - /// This function fills in a plain map for a file of the given size. This - /// is used to ensure that the chunk size will be consistent with the rest - /// of the code. - // - static void buildPlainMap(uint64_t size,CompressedChunkMap& map) ; - - /// Computes the number of chunks for the given file size. - static uint32_t getNumberOfChunks(uint64_t size) ; - - /// This function is used by the parent ftFileProvider to know whether the chunk can be sent or not. - bool isChunkAvailable(uint64_t offset, uint32_t chunk_size) const ; - - bool isChunkOutstanding(uint64_t offset, uint32_t chunk_size) const ; - - /// Remove active chunks that have not received any data for the last 60 seconds, and return - /// the list of slice numbers that should be canceled. - void removeInactiveChunks(std::vector& to_remove) ; - - /// Updates the peer's availablility map - // - void setPeerAvailabilityMap(const RsPeerId& peer_id,const CompressedChunkMap& peer_map) ; - - /// Returns a pointer to the availability chunk map of the given source, and possibly - /// allocates it if necessary. - // - SourceChunksInfo *getSourceChunksInfo(const RsPeerId& peer_id) ; - - /// Returns the total size of downloaded data in the file. - uint64_t getTotalReceived() const { return _total_downloaded ; } - - /// returns true is the file is complete - bool isComplete() const { return _file_is_complete ; } - - /// returns info about currently downloaded chunks - void getChunksInfo(FileChunksInfo& info) const ; - - /// input the result of the chunk hash checking - void setChunkCheckingResult(uint32_t chunk_number, bool succeed) ; - - /// returns the current list of chunks to ask for a CRC, and a proposed source for each - void getChunksToCheck(std::vector& chunks_to_ask) ; - - /// Get all available sources for this chunk - void getSourcesList(uint32_t chunk_number,std::vector& sources) ; - - /// sets all chunks to checking state - void forceCheck() ; - - /// Goes through all structures and computes the actual file completion. The true completion - /// gets lost when force checking the file. - void updateTotalDownloaded() ; - - protected: - /// handles what size the last chunk has. - uint32_t sizeOfChunk(uint32_t chunk_number) const ; - - /// Returns a chunk available for this peer_id, depending on the chunk strategy. - // - uint32_t getAvailableChunk(const RsPeerId& peer_id,bool& chunk_map_too_old) ; - - private: - bool hasChunkState(uint64_t offset, uint32_t chunk_size, FileChunksInfo::ChunkState state) const; - - uint64_t _file_size ; //! total size of the file in bytes. - uint32_t _chunk_size ; //! Size of chunks. Common to all chunks. - FileChunksInfo::ChunkStrategy _strategy ; //! how do we allocate new chunks - std::map _active_chunks_feed ; //! vector of chunks being downloaded. Exactly 1 chunk per peer. - std::map _slices_to_download ; //! list of (slice offset,slice size) currently being downloaded - std::vector _map ; //! vector of chunk state over the whole file - std::map _peers_chunks_availability ; //! what does each source peer have - uint64_t _total_downloaded ; //! completion for the file - bool _file_is_complete ; //! set to true when the file is complete. - bool _assume_availability ; //! true if all sources always have the complete file. - std::vector _chunks_checking_queue ; //! Queue of downloaded chunks to be checked. -}; - - diff --git a/libretroshare/src/ft/ftcontroller.cc b/libretroshare/src/ft/ftcontroller.cc deleted file mode 100644 index 29494f189..000000000 --- a/libretroshare/src/ft/ftcontroller.cc +++ /dev/null @@ -1,2273 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftcontroller.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -/* - * ftController - * - * Top level download controller. - * - * inherits configuration (save downloading files) - * inherits pqiMonitor (knows which peers are online). - * inherits CacheTransfer (transfers cache files too) - * inherits RsThread (to control transfers) - * - */ - -#ifdef WINDOWS_SYS -#include "util/rsstring.h" -#endif -#include "util/rsdiscspace.h" -#include "util/rsmemory.h" -#include "util/rstime.h" -#include "util/cxx17retrocompat.h" -#include "ft/ftcontroller.h" - -#include "ft/ftfilecreator.h" -#include "ft/fttransfermodule.h" -#include "ft/ftsearch.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftextralist.h" -#include "ft/ftserver.h" - -#include "turtle/p3turtle.h" - -#include "util/rsdir.h" -#include "rsserver/p3face.h" - -#include "pqi/p3linkmgr.h" - -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" - -#include "rsitems/rsconfigitems.h" -#include -#include /* for (u)sleep() */ -#include "util/rstime.h" - -/****** - * #define CONTROL_DEBUG 1 - * #define DEBUG_DWLQUEUE 1 - *****/ - -static const int32_t SAVE_TRANSFERS_DELAY = 301 ; // save transfer progress every 301 seconds. -static const int32_t INACTIVE_CHUNKS_CHECK_DELAY = 240 ; // time after which an inactive chunk is released -static const int32_t MAX_TIME_INACTIVE_REQUEUED = 120 ; // time after which an inactive ftFileControl is bt-queued - -static const int32_t FT_FILECONTROL_QUEUE_ADD_END = 0 ; -static const int32_t FT_FILECONTROL_MAX_UPLOAD_SLOTS_DEFAULT= 0 ; - -const uint32_t FT_CNTRL_STANDARD_RATE = 10 * 1024 * 1024; -const uint32_t FT_CNTRL_SLOW_RATE = 100 * 1024; - -ftFileControl::ftFileControl() - :mTransfer(NULL), mCreator(NULL), - mState(DOWNLOADING), mSize(0), mFlags(0), mCreateTime(0), mQueuePriority(0), mQueuePosition(0) -{ - return; -} - -ftFileControl::ftFileControl(const std::string& fname, const std::string& tmppath, const std::string& dest - , uint64_t size, const RsFileHash &hash, TransferRequestFlags flags - , ftFileCreator *fc, ftTransferModule *tm) - : mName(fname), mCurrentPath(tmppath), mDestination(dest) - , mTransfer(tm), mCreator(fc), mState(DOWNLOADING), mHash(hash) - , mSize(size), mFlags(flags), mCreateTime(0), mQueuePriority(0), mQueuePosition(0) -{} - -ftController::ftController(ftDataMultiplex *dm, p3ServiceControl *sc, uint32_t ftServiceId) - : p3Config(), - last_save_time(0), - last_clean_time(0), - mSearch(NULL), - mDataplex(dm), - mExtraList(NULL), - mTurtle(NULL), - mFtServer(NULL), - mServiceCtrl(sc), - mFtServiceType(ftServiceId), - mDefaultEncryptionPolicy(RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE), - mFilePermDirectDLPolicy(RS_FILE_PERM_DIRECT_DL_PER_USER), - cnt(0), - ctrlMutex("ftController"), - doneMutex("ftController"), - mFtActive(false), - mFtPendingDone(false), - mDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE), - _max_active_downloads(5), // default queue size - _max_uploads_per_friend(FT_FILECONTROL_MAX_UPLOAD_SLOTS_DEFAULT) -{ -} - -void ftController::setTurtleRouter(p3turtle *pt) { mTurtle = pt ; } -void ftController::setFtServer(ftServer *ft) { mFtServer = ft ; } - -void ftController::setFtSearchNExtra(ftSearch *search, ftExtraList *list) -{ - mSearch = search; - mExtraList = list; -} - -bool ftController::getFileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo& info) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it = mDownloads.find(hash) ; - - if(it != mDownloads.end()) - { - it->second->mCreator->getChunkMap(info) ; - //info.flags = it->second->mFlags ; - - return true ; - } - - it = mCompleted.find(hash) ; - - if(it != mCompleted.end()) - { - // This should rather be done as a static method of ChunkMap. - // - // We do this manually, because the file creator has already been destroyed. - // - info.file_size = it->second->mSize ; - info.strategy = mDefaultChunkStrategy ; - info.chunk_size = ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE ; - //info.flags = it->second->mFlags ; - uint32_t nb_chunks = it->second->mSize/ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE ; - if(it->second->mSize % ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE != 0) - ++nb_chunks ; - info.chunks.resize(nb_chunks,FileChunksInfo::CHUNK_DONE) ; - - return true ; - } - - return false ; -} - -void ftController::addFileSource(const RsFileHash& hash,const RsPeerId& peer_id) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it = mDownloads.find(hash); - -#ifdef CONTROL_DEBUG - std::cerr << "ftController: Adding source " << peer_id << " to current download hash=" << hash ; -#endif - if(it != mDownloads.end()) - { - it->second->mTransfer->addFileSource(peer_id); - setPeerState(it->second->mTransfer, peer_id, FT_CNTRL_STANDARD_RATE, mServiceCtrl->isPeerConnected(mFtServiceType, peer_id )); - -#ifdef CONTROL_DEBUG - std::cerr << "... added." << std::endl ; -#endif - return ; - } -#ifdef CONTROL_DEBUG - std::cerr << "... not added: hash not found." << std::endl ; -#endif -} -void ftController::removeFileSource(const RsFileHash& hash,const RsPeerId& peer_id) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it = mDownloads.find(hash); - -#ifdef CONTROL_DEBUG - std::cerr << "ftController: Adding source " << peer_id << " to current download hash=" << hash ; -#endif - if(it != mDownloads.end()) - { - it->second->mTransfer->removeFileSource(peer_id); - it->second->mCreator->removeFileSource(peer_id); - -#ifdef CONTROL_DEBUG - std::cerr << "... added." << std::endl ; -#endif - return ; - } -#ifdef CONTROL_DEBUG - std::cerr << "... not added: hash not found." << std::endl ; -#endif -} -void ftController::threadTick() -{ - /* check the queues */ - - //Waiting 1 sec before start - rstime::rs_usleep(1*1000*1000); // 1 sec - -#ifdef CONTROL_DEBUG - //std::cerr << "ftController::run()"; - //std::cerr << std::endl; -#endif - bool doPending = false; - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - doPending = (mFtActive) && (!mFtPendingDone); - } - - rstime_t now = time(NULL) ; - if(now > last_save_time + SAVE_TRANSFERS_DELAY) - { - IndicateConfigChanged() ; - last_save_time = now ; - } - - if(now > last_clean_time + INACTIVE_CHUNKS_CHECK_DELAY) - { - searchForDirectSources() ; - - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - for(std::map::iterator it(mDownloads.begin());it!=mDownloads.end();++it) - it->second->mCreator->removeInactiveChunks() ; - - last_clean_time = now ; - } - - if (doPending) - { - if (!handleAPendingRequest()) - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - mFtPendingDone = true; - } - } - - tickTransfers() ; - - { - std::list files_to_complete ; - - { - RsStackMutex stack2(doneMutex); - files_to_complete = mDone ; - mDone.clear(); - } - - for(std::list::iterator it(files_to_complete.begin()); it != files_to_complete.end(); ++it) - completeFile(*it); - } - - if(cnt++ % 10 == 0) - checkDownloadQueue() ; -} - -void ftController::searchForDirectSources() -{ -#ifdef CONTROL_DEBUG - std::cerr << "ftController::searchForDirectSources()" << std::endl; -#endif - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - if (!mSearch) - { -#ifdef CONTROL_DEBUG - std::cerr << " search module not available!" << std::endl; -#endif - return; - } - - for(std::map::iterator it(mDownloads.begin()); it != mDownloads.end(); ++it ) - if(it->second->mState != ftFileControl::QUEUED && it->second->mState != ftFileControl::PAUSED ) - { -#ifdef CONTROL_DEBUG - std::cerr << " file " << it->first << ":" << std::endl; -#endif - FileInfo info ; // Info needs to be re-allocated each time, to start with a clear list of peers (it's not cleared down there) - - if( mSearch->search(it->first, RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY, info) ) - for( std::vector::const_iterator pit = info.peers.begin(); pit != info.peers.end(); ++pit ) - { - bool bAllowDirectDL = false; - switch (mFilePermDirectDLPolicy) { - case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break; - case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break; - default:bAllowDirectDL = (rsPeers->servicePermissionFlags(pit->peerId) & RS_NODE_PERM_DIRECT_DL); break; - } - if( bAllowDirectDL ) - if( it->second->mTransfer->addFileSource(pit->peerId) ) /* if the sources don't exist already - add in */ - setPeerState( it->second->mTransfer, pit->peerId, FT_CNTRL_STANDARD_RATE, mServiceCtrl->isPeerConnected(mFtServiceType, pit->peerId) ); -#ifdef CONTROL_DEBUG - std::cerr << " found source " << pit->peerId << ", allowDirectDL=" << bAllowDirectDL << ". " << (bAllowDirectDL?"adding":"not adding") << std::endl; -#endif - } -#ifdef CONTROL_DEBUG - else - std::cerr << " search returned empty.: " << std::endl; -#endif - } -#ifdef CONTROL_DEBUG - else - std::cerr << " file " << it->first << ": state is " << it->second->mState << ": ignored." << std::endl; -#endif -} - -void ftController::tickTransfers() -{ - // 1 - sort modules into arrays according to priority - - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - -#ifdef CONTROL_DEBUG - // std::cerr << "ticking transfers." << std::endl ; -#endif - // Collect all non queued files. - // - for(std::map::iterator it(mDownloads.begin()); it != mDownloads.end(); ++it) - if(it->second->mState != ftFileControl::QUEUED && it->second->mState != ftFileControl::PAUSED) - it->second->mTransfer->tick() ; -} - -bool ftController::getPriority(const RsFileHash& hash,DwlSpeed& p) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it(mDownloads.find(hash)) ; - - if(it != mDownloads.end()) - { - p = it->second->mTransfer->downloadPriority() ; - return true ; - } - else - return false ; -} - -void ftController::setPriority(const RsFileHash& hash,DwlSpeed p) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it(mDownloads.find(hash)) ; - - if(it != mDownloads.end()) - it->second->mTransfer->setDownloadPriority(p) ; -} - -/* Called every 10 seconds or so */ -void ftController::checkDownloadQueue() -{ - // We do multiple things here: - // - // 0 - make sure all transfers have a consistent value for mDownloadQueue - // - // 1 - are there queued files ? - // - // YES - // 1.1 - check for inactive files (see below). - // - select one inactive file - // - close it temporarily - // - remove it from turtle handling - // - move the ftFileControl to queued list - // - set the queue priority to 1+largest in the queue. - // 1.2 - pop from the queue the 1st file to come (according to availability of sources, then priority) - // - enable turtle router handling for this hash - // - reset counters - // - set the file as waiting - // NO - // Do nothing, because no files are waiting. - // - // 2 - in FileRequest, if the max number of downloaded files is exceeded, put the - // file in the queue list, and don't enable the turtle router handling. - // - // Implementation: - // - locate a hash in the queue - // - move hashes in the queue up/down/top/bottom - // - now the place of each ftFileControl element in the queue to activate/desactive them - // - // So: - // - change mDownloads to be a std::map - // - sort the ftFileControl* into a std::vector - // - store the queue position of each ftFileControl* into its own structure (mQueuePosition member) - // - // We don't want the turtle router to keep openning tunnels for queued files, so we only base - // the notion of inactive on the fact that no traffic happens for the file within 5 mins. - // - // How do we detect inactive files? - // For a downld file: - no traffic for 5 min. - - RsStackMutex mtx(ctrlMutex) ; - -#ifdef DEBUG_DWLQUEUE - std::cerr << "Checking download queue." << std::endl ; -#endif - if(mDownloads.size() <= _max_active_downloads) - return ; - - std::vector inactive_transfers ; - std::vector transfers_with_online_sources ; - - std::set online_peers ; - mServiceCtrl->getPeersConnected(mFtServiceType,online_peers) ; - - // Check for inactive transfers, and queued transfers with online sources. - // - rstime_t now = time(NULL) ; - - for(std::map::const_iterator it(mDownloads.begin());it!=mDownloads.end() ;++it) - if( it->second->mState != ftFileControl::QUEUED && (it->second->mState == ftFileControl::PAUSED - || now > it->second->mTransfer->lastActvTimeStamp() + (rstime_t)MAX_TIME_INACTIVE_REQUEUED)) - { - inactive_transfers.push_back(it->second) ; - } - else if(it->second->mState == ftFileControl::QUEUED) - { - std::list srcs ; - it->second->mTransfer->getFileSources(srcs) ; - - for(std::list::const_iterator it2(srcs.begin());it2!=srcs.end();++it2) - if(online_peers.find(*it2) != online_peers.end()) - { - transfers_with_online_sources.push_back(it->second) ; - break ; - } - } - -#ifdef DEBUG_DWLQUEUE - std::cerr << "Identified " << inactive_transfers.size() << " inactive transfer, and " << transfers_with_online_sources.size() << " queued transfers with online sources." << std::endl; -#endif - - // first swap as many queued transfers with online sources with inactive transfers - uint32_t i=0; - - for(;imName << " at position " << inactive_transfers[i]->mQueuePosition << " with transfer at position " << transfers_with_online_sources[i]->mQueuePosition << " which has available sources." << std::endl; -#endif - inactive_transfers[i]->mTransfer->resetActvTimeStamp() ; // very important! - transfers_with_online_sources[i]->mTransfer->resetActvTimeStamp() ; // very important! - - locked_swapQueue(inactive_transfers[i]->mQueuePosition,transfers_with_online_sources[i]->mQueuePosition); - } - - // now if some inactive transfers remain, put them at the end of the queue. - - for(;imName << " at position " << inactive_transfers[i]->mQueuePosition << " moved to end of the queue. mState=" << inactive_transfers[i]->mState << ", time lapse=" << now - it->second->mCreator->lastActvTimeStamp() << std::endl ; -#endif - locked_bottomQueue(inactive_transfers[i]->mQueuePosition) ; -#ifdef DEBUG_DWLQUEUE - std::cerr << " new position: " << inactive_transfers[i]->mQueuePosition << std::endl ; - std::cerr << " new state: " << inactive_transfers[i]->mState << std::endl ; -#endif - inactive_transfers[i]->mTransfer->resetActvTimeStamp() ; // very important! - } - - // finally, do a full swab over the queue to make sure that the expected number of downloads is met. - - for(uint32_t i=0;i::iterator it(mDownloads.find(hash)) ; - - if(it == mDownloads.end()) - { - std::cerr << "ftController::moveInQueue: can't find hash " << hash << " in the download list." << std::endl ; - return ; - } - uint32_t pos = it->second->mQueuePosition ; - -#ifdef DEBUG_DWLQUEUE - std::cerr << "Moving file " << hash << ", pos=" << pos << " to new pos." << std::endl ; -#endif - switch(mv) - { - case QUEUE_TOP: locked_topQueue(pos) ; - break ; - - case QUEUE_BOTTOM: locked_bottomQueue(pos) ; - break ; - - case QUEUE_UP: if(pos > 0) - locked_swapQueue(pos,pos-1) ; - break ; - - case QUEUE_DOWN: if(pos < mDownloadQueue.size()-1) - locked_swapQueue(pos,pos+1) ; - break ; - default: - std::cerr << "ftController::moveInQueue: unknown move " << mv << std::endl ; - } -} - -void ftController::locked_topQueue(uint32_t pos) -{ - ftFileControl *tmp=mDownloadQueue[pos] ; - - for(int p=pos;p>0;--p) - { - mDownloadQueue[p]=mDownloadQueue[p-1] ; - locked_checkQueueElement(p) ; - } - mDownloadQueue[0]=tmp ; - - locked_checkQueueElement(0) ; -} -void ftController::locked_bottomQueue(uint32_t pos) -{ - ftFileControl *tmp=mDownloadQueue[pos] ; - - for(uint32_t p=pos;pmQueuePosition = pos ; - - if(pos < _max_active_downloads && mDownloadQueue[pos]->mState != ftFileControl::PAUSED) - { - if(mDownloadQueue[pos]->mState == ftFileControl::QUEUED) - mDownloadQueue[pos]->mTransfer->resetActvTimeStamp() ; - - mDownloadQueue[pos]->mState = ftFileControl::DOWNLOADING ; - - if(mDownloadQueue[pos]->mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mFtServer->activateTunnels(mDownloadQueue[pos]->mHash,mDefaultEncryptionPolicy,mDownloadQueue[pos]->mFlags,true); - } - - if(pos >= _max_active_downloads && mDownloadQueue[pos]->mState != ftFileControl::QUEUED && mDownloadQueue[pos]->mState != ftFileControl::PAUSED) - { - mDownloadQueue[pos]->mState = ftFileControl::QUEUED ; - mDownloadQueue[pos]->mCreator->closeFile() ; - - if(mDownloadQueue[pos]->mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mFtServer->activateTunnels(mDownloadQueue[pos]->mHash,mDefaultEncryptionPolicy,mDownloadQueue[pos]->mFlags,false); - } -} - -bool ftController::FlagFileComplete(const RsFileHash& hash) -{ - RsStackMutex stack2(doneMutex); - mDone.push_back(hash); - -#ifdef CONTROL_DEBUG - std::cerr << "ftController:FlagFileComplete(" << hash << ")"; - std::cerr << std::endl; -#endif - - return true; -} - -bool ftController::completeFile(const RsFileHash& hash) -{ - /* variables... so we can drop mutex later */ - std::string path; - std::string name; - uint64_t size = 0; - uint32_t period = 0; - TransferRequestFlags flags ; - TransferRequestFlags extraflags ; - uint32_t completeCount = 0; - - { - RS_STACK_MUTEX(ctrlMutex); - -#ifdef CONTROL_DEBUG - std::cerr << "ftController:completeFile(" << hash << ")"; - std::cerr << std::endl; -#endif - std::map::iterator it(mDownloads.find(hash)); - - if (it == mDownloads.end()) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController:completeFile(" << hash << ")"; - std::cerr << " Not Found!"; - std::cerr << std::endl; -#endif - return false; - } - - /* check if finished */ - if (!(it->second)->mCreator->finished()) - { - /* not done! */ -#ifdef CONTROL_DEBUG - std::cerr << "ftController:completeFile(" << hash << ")"; - std::cerr << " Transfer Not Done"; - std::cerr << std::endl; - - std::cerr << "FileSize: "; - std::cerr << (it->second)->mCreator->getFileSize(); - std::cerr << " and Recvd: "; - std::cerr << (it->second)->mCreator->getRecvd(); -#endif - return false; - } - - - ftFileControl *fc = it->second; - - // (csoler) I've postponed this to the end of the block because deleting the - // element from the map calls the destructor of fc->mTransfer, which - // makes fc to point to nothing and causes random behavior/crashes. - // - // mDataplex->removeTransferModule(fc->mTransfer->hash()); - // - /* done - cleanup */ - - // (csoler) I'm copying this because "delete fc->mTransfer" deletes the hash string! - RsFileHash hash_to_suppress(fc->mTransfer->hash()); - - // This should be done that early, because once the file creator is - // deleted, it should not be accessed by the data multiplex anymore! - // - mDataplex->removeTransferModule(hash_to_suppress) ; - - if (fc->mTransfer) - { - delete fc->mTransfer; - fc->mTransfer = NULL; - } - - if (fc->mCreator) - { - fc->mCreator->closeFile() ; - delete fc->mCreator; - fc->mCreator = NULL; - } - - fc->mState = ftFileControl::COMPLETED; - - std::string dst_dir,src_dir,src_file,dst_file ; - - RsDirUtil::splitDirFromFile(fc->mCurrentPath,src_dir,src_file) ; - RsDirUtil::splitDirFromFile(fc->mDestination,dst_dir,dst_file) ; - - // We use this intermediate file in case the destination directory is not available, so as to not keep the partial file name. - - std::string intermediate_file_name = src_dir+'/'+dst_file ; - - // I don't know how the size can be zero, but believe me, this happens, - // and it causes an error on linux because then the file may not even exist. - // - if( fc->mSize == 0) - fc->mState = ftFileControl::ERROR_COMPLETION; - else - { - std::cerr << "CompleteFile(): renaming " << fc->mCurrentPath << " into " << fc->mDestination << std::endl; - std::cerr << "CompleteFile(): 1 - renaming " << fc->mCurrentPath << " info " << intermediate_file_name << std::endl; - - if(RsDirUtil::moveFile(fc->mCurrentPath,intermediate_file_name) ) - { - fc->mCurrentPath = intermediate_file_name ; - - std::cerr << "CompleteFile(): 2 - renaming/copying " << intermediate_file_name << " into " << fc->mDestination << std::endl; - - if(RsDirUtil::moveFile(intermediate_file_name,fc->mDestination) ) - fc->mCurrentPath = fc->mDestination; - else - fc->mState = ftFileControl::ERROR_COMPLETION; - } - else - fc->mState = ftFileControl::ERROR_COMPLETION; - } - - /* for extralist additions */ - path = fc->mDestination; - name = fc->mName; - //hash = fc->mHash; - size = fc->mSize; - period = 30 * 24 * 3600; /* 30 days */ - extraflags.clear() ; - -#ifdef CONTROL_DEBUG - std::cerr << "CompleteFile(): size = " << size << std::endl ; -#endif - - flags = fc->mFlags ; - - locked_queueRemove(it->second->mQueuePosition) ; - - /* switch map */ - mCompleted[fc->mHash] = fc; - completeCount = mCompleted.size(); - - mDownloads.erase(it); - - if(flags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mFtServer->activateTunnels(hash_to_suppress,mDefaultEncryptionPolicy,flags,false); - - } // UNLOCK: RS_STACK_MUTEX(ctrlMutex); - - - /******************** NO Mutex from Now ******************** - * cos Callback can end up back in this class. - ***********************************************************/ - - /* If it has a callback - do it now */ - - if(flags & RS_FILE_REQ_EXTRA)// | RS_FILE_HINTS_MEDIA)) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::completeFile() adding to ExtraList"; - std::cerr << std::endl; -#endif - - if(mExtraList) - mExtraList->addExtraFile(path, hash, size, period, extraflags); - } - else - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::completeFile() No callback"; - std::cerr << std::endl; -#endif - } - - /* Notify GUI */ - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mHash = hash; - ev->mFileTransferEventCode = RsFileTransferEventCode::DOWNLOAD_COMPLETE; - rsEvents->postEvent(ev); - } - - rsFiles->ForceDirectoryCheck(true) ; - - IndicateConfigChanged(); /* completed transfer -> save */ - return true; -} - - /***************************************************************/ - /********************** Controller Access **********************/ - /***************************************************************/ - -bool ftController::activate() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - mFtActive = true; - mFtPendingDone = false; - return true; -} - -bool ftController::isActiveAndNoPending() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - return (mFtActive && mFtPendingDone); -} - -bool ftController::handleAPendingRequest() -{ - uint32_t nb_requests_handled = 0 ; - static const uint32_t MAX_SIMULTANEOUS_PENDING_REQUESTS = 100 ; - - while(!mPendingRequests.empty() && nb_requests_handled++ < MAX_SIMULTANEOUS_PENDING_REQUESTS) - { - ftPendingRequest req; - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - req = mPendingRequests.front(); - mPendingRequests.pop_front(); - } -#ifdef CONTROL_DEBUG - std::cerr << "Requesting pending hash " << req.mHash << std::endl ; -#endif - - FileRequest(req.mName, req.mHash, req.mSize, req.mDest, TransferRequestFlags(req.mFlags), req.mSrcIds, req.mState); - - { - // See whether there is a pendign chunk map recorded for this hash. - // - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it(mPendingChunkMaps.find(req.mHash)) ; - - if(it != mPendingChunkMaps.end()) - { - RsFileTransfer *rsft = it->second ; - std::map::iterator fit = mDownloads.find(rsft->file.hash); - - if((fit==mDownloads.end() || (fit->second)->mCreator == NULL)) - { - // This should never happen, because the last call to FileRequest must have created the fileCreator!! - // - std::cerr << "ftController::loadList(): Error: could not find hash " << rsft->file.hash << " in mDownloads list !" << std::endl ; - } - else - { -#ifdef CONTROL_DEBUG - std::cerr << "Hash " << req.mHash << " is in downloads" << std::endl ; - std::cerr << " setting chunk strategy to " << rsft->chunk_strategy << std::endl; -#endif - (fit->second)->mCreator->setAvailabilityMap(rsft->compressed_chunk_map) ; - (fit->second)->mCreator->setChunkStrategy((FileChunksInfo::ChunkStrategy)(rsft->chunk_strategy)) ; - (fit->second)->mState=rsft->state; - } - - delete rsft ; - mPendingChunkMaps.erase(it) ; - } -#ifdef CONTROL_DEBUG - else - std::cerr << "No pending chunkmap for hash " << req.mHash << std::endl ; -#endif - } - } - return !mPendingRequests.empty(); -} - -bool ftController::alreadyHaveFile(const RsFileHash& hash, FileInfo &info) -{ - // check for downloads - if (FileDetails(hash, info) && (info.downloadStatus == FT_STATE_COMPLETE)) - return true ; - - // check for file lists - if (!mSearch) return false; - if (mSearch->search(hash, RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY, info)) - return true ; - - return false ; -} - -bool ftController::FileRequest( - const std::string& fname, const RsFileHash& hash, uint64_t size, - const std::string& dest, TransferRequestFlags flags, - const std::list &_srcIds, uint16_t state ) -{ - /* TODO: To support collections faithfully we need to be able to save - * the same file to multiple locations, both if already downloaded or - * incomplete */ - - std::list srcIds(_srcIds) ; - - /* check if we have the file */ - - FileInfo info; - if(alreadyHaveFile(hash, info)) - return false ; - - // the strategy for requesting encryption is the following: - // - // if policy is STRICT - // - disable clear, enforce encryption - // else - // - if not specified, use both - // - if(mDefaultEncryptionPolicy == RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT) - { - flags |= RS_FILE_REQ_ENCRYPTED ; - flags &= ~RS_FILE_REQ_UNENCRYPTED ; - } - else if(!(flags & ( RS_FILE_REQ_ENCRYPTED | RS_FILE_REQ_UNENCRYPTED ))) - { - flags |= RS_FILE_REQ_ENCRYPTED ; - flags |= RS_FILE_REQ_UNENCRYPTED ; - } - - if(size == 0) // we treat this special case because - { - /* if no destpath - send to download directory */ - std::string destination ; - - if (dest == "") - destination = mDownloadPath + "/" + fname; - else - destination = dest + "/" + fname; - - // create void file with the target name. - FILE *f = RsDirUtil::rs_fopen(destination.c_str(),"w") ; - if(!f) - RsErr() << __PRETTY_FUNCTION__ << " Could not write file " - << destination << std::endl; - else - fclose(f) ; - - return true ; - } - - // Bugs in the cache system can cause files with arbitrary size to be - // requested, causing a division by zero in ftChunkMap when size > 1MB * - // (2^32-1). I thus conservatively check for large size values. - // - if(size >= 1024ull*1024ull*((1ull << 32) - 1)) - { - RsErr() << __PRETTY_FUNCTION__ - << " unexpected size. This is probably a bug." - << " name = " << fname - << " flags = " << flags - << " dest = " << dest - << " size = " << size << std::endl; - return false; - } - - /* If file transfer is not enabled .... - * save request for later. This will also - * mean that we will have to copy local files, - * or have a callback which says: local file. - */ - - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - if (!mFtActive) - { - /* store in pending queue */ - ftPendingRequest req(fname, hash, size, dest, flags, srcIds,state); - mPendingRequests.push_back(req); - return true; - } - } - - /* remove the sources from the list, if they don't have clearance for direct - * transfer. This happens only for non cache files. */ - for(std::list::iterator it = srcIds.begin(); it != srcIds.end(); ) - { - bool bAllowDirectDL = false; - switch (mFilePermDirectDLPolicy) { - case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break; - case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break; - default:bAllowDirectDL = (rsPeers->servicePermissionFlags(*it) & RS_NODE_PERM_DIRECT_DL); break; - } - - if(!bAllowDirectDL) - { - std::list::iterator tmp(it); - ++tmp; - srcIds.erase(it); - it = tmp; - } - else - ++it; - } - - std::list::const_iterator it; - std::vector::const_iterator pit; - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest(" << fname << ","; - std::cerr << hash << "," << size << "," << dest << ","; - std::cerr << flags << ",<"; - - for(it = srcIds.begin(); it != srcIds.end(); ++it) - { - std::cerr << *it << ","; - } - std::cerr << ">)"; - std::cerr << std::endl; -#endif - - uint32_t rate = 0; - if (flags & RS_FILE_REQ_BACKGROUND) - rate = FT_CNTRL_SLOW_RATE; - else - rate = FT_CNTRL_STANDARD_RATE; - - /* First check if the file is already being downloaded.... - * This is important as some guis request duplicate files regularly. - */ - - { - RS_STACK_MUTEX(ctrlMutex); - - auto dit = std::as_const(mDownloads).find(hash); - if (dit != mDownloads.end()) - { - /* we already have it! */ - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() Already Downloading File"; - std::cerr << std::endl; - std::cerr << "\tNo need to download"; - std::cerr << std::endl; -#endif - /* but we should add this peer - if they don't exist! - * (needed for channels). - */ - - for(it = srcIds.begin(); it != srcIds.end(); ++it) - { - bool bAllowDirectDL = false; - switch (mFilePermDirectDLPolicy) { - case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break; - case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break; - default:bAllowDirectDL = (rsPeers->servicePermissionFlags(*it) & RS_NODE_PERM_DIRECT_DL); break; - } - if(bAllowDirectDL) - { - uint32_t i, j; - if ((dit->second)->mTransfer->getPeerState(*it, i, j)) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() Peer Existing"; - std::cerr << std::endl; -#endif - continue; /* already added peer */ - } - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() Adding Peer: " << *it; - std::cerr << std::endl; -#endif - (dit->second)->mTransfer->addFileSource(*it); - setPeerState(dit->second->mTransfer, *it, rate, mServiceCtrl->isPeerConnected(mFtServiceType, *it)); - } - } - - if (srcIds.empty()) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() WARNING: No Src Peers"; - std::cerr << std::endl; -#endif - } - - return true; - } - } // RS_STACK_MUTEX(ctrlMutex); unlocked - - - if(mSearch && !(flags & RS_FILE_REQ_NO_SEARCH)) - { - /* do a source search - for any extra sources */ - // add sources only in direct mode - // - if(/* (flags & RS_FILE_HINTS_BROWSABLE) && */ mSearch->search(hash, RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY, info)) - { - /* do something with results */ -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() Found Other Sources"; - std::cerr << std::endl; -#endif - - /* if the sources don't exist already - add in */ - for(pit = info.peers.begin(); pit != info.peers.end(); ++pit) - { -#ifdef CONTROL_DEBUG - std::cerr << "\tSource: " << pit->peerId; - std::cerr << std::endl; -#endif - // Because this is auto-add, we only add sources that we allow to DL from using direct transfers. - - bool bAllowDirectDL = false; - switch (mFilePermDirectDLPolicy) { - case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break; - case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break; - default:bAllowDirectDL = (rsPeers->servicePermissionFlags(pit->peerId) & RS_NODE_PERM_DIRECT_DL); break; - } - - if ((srcIds.end() == std::find( srcIds.begin(), srcIds.end(), pit->peerId)) && bAllowDirectDL) - { - srcIds.push_back(pit->peerId); - -#ifdef CONTROL_DEBUG - std::cerr << "\tAdding in: " << pit->peerId; - std::cerr << std::endl; -#endif - } - } - } - } - - /* add in new item for download */ - std::string savepath; - std::string destination; - - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - savepath = mPartialsPath + "/" + hash.toStdString(); - destination = dest + "/" + fname; - - /* if no destpath - send to download directory */ - if (dest == "") - destination = mDownloadPath + "/" + fname; - } /******* UNLOCKED ********/ - - // We check that flags are consistent. - - if(flags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mFtServer->activateTunnels(hash,mDefaultEncryptionPolicy,flags,true); - - bool assume_availability = false; - - ftFileCreator *fc = new ftFileCreator(savepath, size, hash,assume_availability); - ftTransferModule *tm = new ftTransferModule(fc, mDataplex,this); - -#ifdef CONTROL_DEBUG - std::cerr << "Note: setting chunk strategy to " << mDefaultChunkStrategy <setChunkStrategy(mDefaultChunkStrategy) ; - - /* add into maps */ - ftFileControl *ftfc = new ftFileControl(fname, savepath, destination, size, hash, flags, fc, tm); - ftfc->mCreateTime = time(NULL); - - /* now add source peers (and their current state) */ - tm->setFileSources(srcIds); - - /* get current state for transfer module */ - for(it = srcIds.begin(); it != srcIds.end(); ++it) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() adding peer: " << *it; - std::cerr << std::endl; -#endif - setPeerState(tm, *it, rate, mServiceCtrl->isPeerConnected(mFtServiceType, *it)); - } - - /* add structures into the accessible data. Needs to be locked */ - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - locked_addToQueue(ftfc, FT_FILECONTROL_QUEUE_ADD_END ) ; - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() Created ftFileCreator @: " << fc; - std::cerr << std::endl; - std::cerr << "ftController::FileRequest() Created ftTransModule @: " << tm; - std::cerr << std::endl; - std::cerr << "ftController::FileRequest() Created ftFileControl." ; - std::cerr << std::endl; -#endif - - /* add to ClientModule */ - mDataplex->addTransferModule(tm, fc); - mDownloads[hash] = ftfc; - } - - IndicateConfigChanged(); /* completed transfer -> save */ - return true; -} - -bool ftController::setPeerState(ftTransferModule *tm, const RsPeerId& id, uint32_t maxrate, bool online) -{ - if (id == mServiceCtrl->getOwnId()) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::setPeerState() is Self"; - std::cerr << std::endl; -#endif - tm->setPeerState(id, PQIPEER_IDLE, maxrate); - } - else if (online || mTurtle->isOnline(id)) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::setPeerState()"; - std::cerr << " Peer is Online"; - std::cerr << std::endl; -#endif - tm->setPeerState(id, PQIPEER_IDLE, maxrate); - } - else - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::setPeerState()"; - std::cerr << " Peer is Offline"; - std::cerr << std::endl; -#endif - tm->setPeerState(id, PQIPEER_NOT_ONLINE, maxrate); - } - return true; -} - - -bool ftController::setChunkStrategy(const RsFileHash& hash,FileChunksInfo::ChunkStrategy s) -{ - std::map::iterator mit=mDownloads.find(hash); - if (mit==mDownloads.end()) - { -#ifdef CONTROL_DEBUG - std::cerr<<"ftController::setChunkStrategy file is not found in mDownloads"<second->mCreator->setChunkStrategy(s) ; - return true ; -} - -bool ftController::FileCancel(const RsFileHash& hash) -{ - mFtServer->activateTunnels(hash,mDefaultEncryptionPolicy,TransferRequestFlags(0),false); - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileCancel" << std::endl; -#endif - /*check if the file in the download map*/ - - { - RsStackMutex mtx(ctrlMutex) ; - - std::map::iterator mit=mDownloads.find(hash); - if (mit==mDownloads.end()) - { -#ifdef CONTROL_DEBUG - std::cerr<<"ftController::FileCancel file is not found in mDownloads"<second)->mCreator->finished()) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController:FileCancel(" << hash << ")"; - std::cerr << " Transfer Already finished"; - std::cerr << std::endl; - - std::cerr << "FileSize: "; - std::cerr << (mit->second)->mCreator->getFileSize(); - std::cerr << " and Recvd: "; - std::cerr << (mit->second)->mCreator->getRecvd(); -#endif - return false; - } - - /*find the point to transfer module*/ - ftTransferModule* ft=(mit->second)->mTransfer; - ft->cancelTransfer(); - - ftFileControl *fc = mit->second; - mDataplex->removeTransferModule(fc->mTransfer->hash()); - - if (fc->mTransfer) - { - delete fc->mTransfer; - fc->mTransfer = NULL; - } - - if (fc->mCreator) - { - delete fc->mCreator; - fc->mCreator = NULL; - } - - /* delete the temporary file */ - if (0 == remove(fc->mCurrentPath.c_str())) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileCancel() remove temporary file "; - std::cerr << fc->mCurrentPath; - std::cerr << std::endl; -#endif - } - else - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileCancel() fail to remove file "; - std::cerr << fc->mCurrentPath; - std::cerr << std::endl; -#endif - } - - locked_queueRemove(fc->mQueuePosition) ; - delete fc ; - mDownloads.erase(mit); - } - - IndicateConfigChanged(); /* completed transfer -> save */ - return true; -} - -bool ftController::FileControl(const RsFileHash& hash, uint32_t flags) -{ -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileControl(" << hash << ","; - std::cerr << flags << ")"<::iterator mit=mDownloads.find(hash); - if (mit==mDownloads.end()) - { -#ifdef CONTROL_DEBUG - std::cerr<<"ftController::FileControl file is not found in mDownloads"<second->mState = ftFileControl::PAUSED ; - std::cerr << "setting state to " << ftFileControl::PAUSED << std::endl ; - break; - - case RS_FILE_CTRL_START: - mit->second->mState = ftFileControl::DOWNLOADING ; - std::cerr << "setting state to " << ftFileControl::DOWNLOADING << std::endl ; - break; - - case RS_FILE_CTRL_FORCE_CHECK: - mit->second->mTransfer->forceCheck(); - std::cerr << "setting state to " << ftFileControl::CHECKING_HASH << std::endl ; - break; - - default: - return false; - } - IndicateConfigChanged() ; - - return true; -} - -bool ftController::FileClearCompleted() -{ -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileClearCompleted()" <second; - - mCompleted.clear(); - - IndicateConfigChanged(); - } - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mFileTransferEventCode = RsFileTransferEventCode::COMPLETED_FILES_REMOVED; - rsEvents->postEvent(ev); - } - - return true; -} - - /* get Details of File Transfers */ -void ftController::FileDownloads(std::list &hashs) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it; - for(it = mDownloads.begin(); it != mDownloads.end(); ++it) - { - hashs.push_back(it->second->mHash); - } - for(it = mCompleted.begin(); it != mCompleted.end(); ++it) - { - hashs.push_back(it->second->mHash); - } -} - - - /* Directory Handling */ -bool ftController::setDownloadDirectory(std::string path) -{ -#ifdef CONTROL_DEBUG - std::cerr << "ftController::setDownloadDirectory(" << path << ")"; - std::cerr << std::endl; -#endif - /* check if it exists */ - if (RsDirUtil::checkCreateDirectory(path)) - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - mDownloadPath = RsDirUtil::convertPathToUnix(path); - - RsDiscSpace::setDownloadPath(mDownloadPath) ; -#ifdef CONTROL_DEBUG - std::cerr << "ftController::setDownloadDirectory() Okay!"; - std::cerr << std::endl; -#endif - IndicateConfigChanged(); - return true; - } - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::setDownloadDirectory() Failed"; - std::cerr << std::endl; -#endif - return false; -} - -bool ftController::setPartialsDirectory(std::string path) -{ - - /* check it is not a subdir of download / shared directories (BAD) - TODO */ - { - RsStackMutex stack(ctrlMutex); - - path = RsDirUtil::convertPathToUnix(path); - - if (path.find(mDownloadPath) != std::string::npos) { - return false; - } - - if (rsFiles) { - std::list::iterator it; - std::list dirs; - rsFiles->getSharedDirectories(dirs); - for (it = dirs.begin(); it != dirs.end(); ++it) { - if (path.find((*it).filename) != std::string::npos) { - return false; - } - } - } - } - - /* check if it exists */ - - if (RsDirUtil::checkCreateDirectory(path)) - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - mPartialsPath = path; - - RsDiscSpace::setPartialsPath(path) ; - -#if 0 /*** FIX ME !!!**************/ - /* move all existing files! */ - std::map::iterator it; - for(it = mDownloads.begin(); it != mDownloads.end(); ++it) - { - (it->second).mCreator->changePartialDirectory(mPartialPath); - } -#endif - IndicateConfigChanged(); - return true; - } - - return false; -} - -std::string ftController::getDownloadDirectory() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - return mDownloadPath; -} - -std::string ftController::getPartialsDirectory() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - return mPartialsPath; -} - -bool ftController::setDestinationDirectory(const RsFileHash& hash,const std::string& dest_dir) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - std::map::iterator it = mDownloads.find(hash); - - if (it == mDownloads.end()) - return false; - - std::cerr << "(II) Changing destination of file " << it->second->mDestination << std::endl; - - it->second->mDestination = dest_dir + '/' + it->second->mName ; - - std::cerr << "(II) ...to " << it->second->mDestination << std::endl; - - return true ; -} -bool ftController::setDestinationName(const RsFileHash& hash,const std::string& dest_name) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - std::map::iterator it = mDownloads.find(hash); - - if (it == mDownloads.end()) - return false; - - std::cerr << "(II) Changing destination of file " << it->second->mDestination << std::endl; - - std::string dest_path ; - RsDirUtil::removeTopDir(it->second->mDestination, dest_path); /* remove fname */ - - it->second->mDestination = dest_path + '/' + dest_name ; - it->second->mName = dest_name ; - - std::cerr << "(II) ...to " << it->second->mDestination << std::endl; - - return true ; -} - -bool ftController::FileDetails(const RsFileHash &hash, FileInfo &info) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - bool completed = false; - std::map::iterator it = mDownloads.find(hash); - if (it == mDownloads.end()) - { - /* search completed files too */ - it = mCompleted.find(hash); - if (it == mCompleted.end()) - { - /* Note: mTransfer & mCreator - * are both NULL - */ - return false; - } - completed = true; - } - - /* extract details */ - info.hash = hash; - info.fname = it->second->mName; - info.storage_permission_flags.clear() ; - info.transfer_info_flags = it->second->mFlags ; - info.priority = SPEED_NORMAL ; - RsDirUtil::removeTopDir(it->second->mDestination, info.path); /* remove fname */ - info.queue_position = it->second->mQueuePosition ; - - if(it->second->mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING) - info.storage_permission_flags |= DIR_FLAGS_ANONYMOUS_DOWNLOAD ; // file being downloaded anonymously are always anonymously available. - - /* get list of sources from transferModule */ - std::list peerIds; - std::list::iterator pit; - - if (!completed) - { - it->second->mTransfer->getFileSources(peerIds); - info.priority = it->second->mTransfer->downloadPriority() ; - info.lastTS = it->second->mCreator->lastRecvTimeStamp(); // last time the file was actually written - } - else - info.lastTS = 0; - - double totalRate = 0; - uint32_t tfRate = 0; - uint32_t state = 0; - - bool isDownloading = false; - bool isSuspended = false; - - info.peers.clear(); - - for(pit = peerIds.begin(); pit != peerIds.end(); ++pit) - { - if (it->second->mTransfer->getPeerState(*pit, state, tfRate)) - { - TransferInfo ti; - switch(state) - { - case PQIPEER_INIT: - ti.status = FT_STATE_OKAY; - break; - case PQIPEER_NOT_ONLINE: - ti.status = FT_STATE_WAITING; - break; - case PQIPEER_DOWNLOADING: - isDownloading = true; - ti.status = FT_STATE_DOWNLOADING; - break; - case PQIPEER_IDLE: - ti.status = FT_STATE_OKAY; - break; - default: - case PQIPEER_SUSPEND: - isSuspended = true; - ti.status = FT_STATE_FAILED; - break; - } - - ti.tfRate = tfRate / 1024.0; - ti.peerId = *pit; - info.peers.push_back(ti); - totalRate += tfRate / 1024.0; - } - } - - if ((completed) || ((it->second)->mCreator->finished())) - { - info.downloadStatus = FT_STATE_COMPLETE; - } - else if (isDownloading) - { - info.downloadStatus = FT_STATE_DOWNLOADING; - } - else if (isSuspended) - { - info.downloadStatus = FT_STATE_FAILED; - } - else - { - info.downloadStatus = FT_STATE_WAITING; - } - - if(it->second->mState == ftFileControl::QUEUED) - info.downloadStatus = FT_STATE_QUEUED ; - - if(it->second->mState == ftFileControl::PAUSED) - info.downloadStatus = FT_STATE_PAUSED ; - - if((!completed) && it->second->mTransfer->isCheckingHash()) - info.downloadStatus = FT_STATE_CHECKING_HASH ; - - info.tfRate = totalRate; - info.size = (it->second)->mSize; - - if (completed) - { - info.transfered = info.size; - info.avail = info.transfered; - } - else - { - info.transfered = (it->second)->mCreator->getRecvd(); - info.avail = info.transfered; - } - - return true; - - - -} - - - /***************************************************************/ - /********************** Controller Access **********************/ - /***************************************************************/ - - /* pqiMonitor callback: - * Used to tell TransferModules new available peers - */ -void ftController::statusChange(const std::list &plist) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - uint32_t rate = FT_CNTRL_STANDARD_RATE; - - /* add online to all downloads */ - std::map::iterator it; - std::list::const_iterator pit; - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::statusChange()"; - std::cerr << std::endl; -#endif - - for(it = mDownloads.begin(); it != mDownloads.end(); ++it) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::statusChange() Updating Hash:"; - std::cerr << it->first; - std::cerr << std::endl; -#endif - for(pit = plist.begin(); pit != plist.end(); ++pit) - { -#ifdef CONTROL_DEBUG - std::cerr << "Peer: " << pit->id; -#endif - if (pit->actions & RS_SERVICE_PEER_CONNECTED) - { -#ifdef CONTROL_DEBUG - std::cerr << " is Newly Connected!"; - std::cerr << std::endl; -#endif - setPeerState(it->second->mTransfer, pit->id, rate, true); - } - else if (pit->actions & RS_SERVICE_PEER_DISCONNECTED) - { -#ifdef CONTROL_DEBUG - std::cerr << " is Just disconnected!"; - std::cerr << std::endl; -#endif - setPeerState(it->second->mTransfer, pit->id, rate, false); - } - else // Added or Removed. - { -#ifdef CONTROL_DEBUG - std::cerr << " had something happen to it: "; - std::cerr << pit-> actions; - std::cerr << std::endl; -#endif - setPeerState(it->second->mTransfer, pit->id, rate, false); - } - } - - // Now also look at turtle virtual peers, for ongoing downloads only. - // - if(it->second->mState != ftFileControl::DOWNLOADING) - continue ; - - std::list vlist ; - std::list::const_iterator vit; - mTurtle->getSourceVirtualPeersList(it->first,vlist) ; - -#ifdef CONTROL_DEBUG - std::cerr << "vlist.size() = " << vlist.size() << std::endl; -#endif - - for(vit = vlist.begin(); vit != vlist.end(); ++vit) - { -#ifdef CONTROL_DEBUG - std::cerr << "Peer: " << vit->id; -#endif - if (vit->actions & RS_PEER_CONNECTED) - { -#ifdef CONTROL_DEBUG - std::cerr << " is Newly Connected!"; - std::cerr << std::endl; -#endif - setPeerState(it->second->mTransfer, vit->id, rate, true); - } - else if (vit->actions & RS_PEER_DISCONNECTED) - { -#ifdef CONTROL_DEBUG - std::cerr << " is Just disconnected!"; - std::cerr << std::endl; -#endif - setPeerState(it->second->mTransfer, vit->id, rate, false); - } - else - { -#ifdef CONTROL_DEBUG - std::cerr << " had something happen to it: "; - std::cerr << vit-> actions; - std::cerr << std::endl; -#endif - setPeerState(it->second->mTransfer, vit->id, rate, false); - } - } - } -} - -const std::string active_downloads_size_ss("MAX_ACTIVE_DOWNLOADS"); -const std::string download_dir_ss("DOWN_DIR"); -const std::string partial_dir_ss("PART_DIR"); -const std::string max_uploads_per_friend_ss("MAX_UPLOADS_PER_FRIEND"); -const std::string default_chunk_strategy_ss("DEFAULT_CHUNK_STRATEGY"); -const std::string free_space_limit_ss("FREE_SPACE_LIMIT"); -const std::string default_encryption_policy_ss("DEFAULT_ENCRYPTION_POLICY"); -const std::string file_perm_direct_dl_ss("FILE_PERM_DIRECT_DL"); - - - /* p3Config Interface */ -RsSerialiser *ftController::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser(); - - /* add in the types we need! */ - rss->addSerialType(new RsFileConfigSerialiser()); - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss; -} - -bool ftController::saveList(bool &cleanup, std::list& saveData) -{ - - - /* it can delete them! */ - cleanup = true; - - /* create a key/value set for most of the parameters */ - std::map configMap; - std::map::iterator mit; - std::list::iterator it; - - /* basic control parameters */ - std::string s ; - rs_sprintf(s, "%lu", getQueueSize()) ; - configMap[active_downloads_size_ss] = s ; - configMap[download_dir_ss] = getDownloadDirectory(); - configMap[partial_dir_ss] = getPartialsDirectory(); - - switch(mDefaultChunkStrategy) - { - case FileChunksInfo::CHUNK_STRATEGY_STREAMING: configMap[default_chunk_strategy_ss] = "STREAMING" ; - break ; - case FileChunksInfo::CHUNK_STRATEGY_RANDOM: configMap[default_chunk_strategy_ss] = "RANDOM" ; - break ; - - default: - case FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE:configMap[default_chunk_strategy_ss] = "PROGRESSIVE" ; - break ; - } - - rs_sprintf(s,"%lu",_max_uploads_per_friend) ; - configMap[max_uploads_per_friend_ss] = s ; - - configMap[default_encryption_policy_ss] = (mDefaultEncryptionPolicy==RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE)?"PERMISSIVE":"STRICT" ; - - switch (mFilePermDirectDLPolicy) { - case RS_FILE_PERM_DIRECT_DL_YES: configMap[file_perm_direct_dl_ss] = "YES" ; - break; - case RS_FILE_PERM_DIRECT_DL_NO: configMap[file_perm_direct_dl_ss] = "NO" ; - break; - default: configMap[file_perm_direct_dl_ss] = "PER_USER" ; - break; - } - - rs_sprintf(s, "%lu", RsDiscSpace::freeSpaceLimit()); - configMap[free_space_limit_ss] = s ; - - RsConfigKeyValueSet *rskv = new RsConfigKeyValueSet(); - - /* Convert to TLV */ - for(mit = configMap.begin(); mit != configMap.end(); ++mit) - { - RsTlvKeyValue kv; - kv.key = mit->first; - kv.value = mit->second; - - rskv->tlvkvs.pairs.push_back(kv); - } - - /* Add KeyValue to saveList */ - saveData.push_back(rskv); - - /* get list of Downloads .... - * strip out Caches / ExtraList / Channels???? - * (anything with a callback?) - * - most systems will restart missing files. - */ - - - /* get Details of File Transfers */ - std::list hashs; - FileDownloads(hashs); - - for(it = hashs.begin(); it != hashs.end(); ++it) - { - /* stack mutex released each loop */ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator fit = mDownloads.find(*it); - if (fit == mDownloads.end()) - continue; - - /* ignore cache files. As this is small files, better download them again from scratch at restart.*/ - - // Node: We still save finished transfers. This keeps transfers that are - // in checking mode. Finished or checked transfers will restart and - // immediately terminate/recheck at next startup. - // - // if ((fit->second)->mCreator->finished()) - // continue; - - /* make RsFileTransfer item for save list */ - RsFileTransfer *rft = new RsFileTransfer(); - - /* what data is important? */ - - rft->file.name = fit->second->mName; - rft->file.hash = fit->second->mHash; - rft->file.filesize = fit->second->mSize; - RsDirUtil::removeTopDir(fit->second->mDestination, rft->file.path); /* remove fname */ - rft->flags = fit->second->mFlags.toUInt32(); - rft->state = fit->second->mState; - - std::list lst ; - fit->second->mTransfer->getFileSources(lst); - - // Remove turtle peers from sources, as they are not supposed to survive a reboot of RS, since they are dynamic sources. - // Otherwize, such sources are unknown from the turtle router, at restart, and never get removed. - // - for(std::list::const_iterator it(lst.begin());it!=lst.end();++it) - if(!mTurtle->isTurtlePeer(*it)) - rft->allPeerIds.ids.insert(*it) ; - - rft->transferred = fit->second->mCreator->getRecvd(); - fit->second->mCreator->getAvailabilityMap(rft->compressed_chunk_map) ; - rft->chunk_strategy = fit->second->mCreator->getChunkStrategy() ; - - saveData.push_back(rft); - } - - { - /* Save pending list of downloads */ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::list::iterator pit; - for (pit = mPendingRequests.begin(); pit != mPendingRequests.end(); ++pit) - { - /* make RsFileTransfer item for save list */ - RsFileTransfer *rft = NULL; - - std::map::iterator rit = mPendingChunkMaps.find(pit->mHash); - if (rit != mPendingChunkMaps.end()) { - /* use item from the not loaded pending list */ - rft = new RsFileTransfer(*(rit->second)); - } else { - rft = new RsFileTransfer(); - - /* what data is important? */ - - rft->file.name = pit->mName; - rft->file.hash = pit->mHash; - rft->file.filesize = pit->mSize; - RsDirUtil::removeTopDir(pit->mDest, rft->file.path); /* remove fname */ - rft->flags = pit->mFlags.toUInt32(); - rft->state = pit->mState; - - rft->allPeerIds.ids.clear() ; - for(std::list::const_iterator it(pit->mSrcIds.begin());it!=pit->mSrcIds.end();++it) - rft->allPeerIds.ids.insert( *it ) ; - } - - // Remove turtle peers from sources, as they are not supposed to survive a reboot of RS, since they are dynamic sources. - // Otherwize, such sources are unknown from the turtle router, at restart, and never get removed. We do that in post - // process since the rft object may have been created from mPendingChunkMaps - // - for(std::set::iterator sit(rft->allPeerIds.ids.begin());sit!=rft->allPeerIds.ids.end();) - if(mTurtle->isTurtlePeer(RsPeerId(*sit))) - { - std::set::iterator sittmp(sit) ; - ++sittmp ; - rft->allPeerIds.ids.erase(sit) ; - sit = sittmp ; - } - else - ++sit ; - - saveData.push_back(rft); - } - } - - /* list completed! */ - return true; -} - - -bool ftController::loadList(std::list& load) -{ - std::list::iterator it; - std::list::iterator kit; - RsConfigKeyValueSet *rskv; - RsFileTransfer *rsft; - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::loadList() Item Count: " << load.size(); - std::cerr << std::endl; -#endif - - for(it = load.begin(); it != load.end(); ++it) - { - /* switch on type */ - if (NULL != (rskv = dynamic_cast(*it))) - { - /* make into map */ - std::map configMap; - for(kit = rskv->tlvkvs.pairs.begin(); - kit != rskv->tlvkvs.pairs.end(); ++kit) - { - configMap[kit->key] = kit->value; - } - - loadConfigMap(configMap); - - } - else if (NULL != (rsft = dynamic_cast(*it))) - { - /* This will get stored on a waiting list - until the - * config files are fully loaded - */ -#ifdef TO_REMOVE - (csoler) I removed this because RS_FILE_HINTS_NETWORK_WIDE is actually equal to RS_FILE_REQ_ENCRYPTED, so this test removed the encrypted flag when loading!! - // Compatibility with previous versions. - if(rsft->flags & RS_FILE_HINTS_NETWORK_WIDE.toUInt32()) - { - std::cerr << "Ensuring compatibility, replacing RS_FILE_HINTS_NETWORK_WIDE with RS_FILE_REQ_ANONYMOUS_ROUTING" << std::endl; - rsft->flags &= ~RS_FILE_HINTS_NETWORK_WIDE.toUInt32() ; - rsft->flags |= RS_FILE_REQ_ANONYMOUS_ROUTING.toUInt32() ; - } -#endif - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::loadList(): requesting " << rsft->file.name << ", " << rsft->file.hash << ", " << rsft->file.filesize << std::endl ; -#endif - std::list src_lst ; - for(std::set::const_iterator it(rsft->allPeerIds.ids.begin());it!=rsft->allPeerIds.ids.end();++it) - src_lst.push_back(*it) ; - - FileRequest(rsft->file.name, rsft->file.hash, rsft->file.filesize, rsft->file.path, TransferRequestFlags(rsft->flags), src_lst, rsft->state); - - { - RsStackMutex mtx(ctrlMutex) ; - - std::map::iterator fit = mDownloads.find(rsft->file.hash); - - if((fit==mDownloads.end() || (fit->second)->mCreator == NULL)) - { - std::cerr << "ftController::loadList(): Error: could not find hash " << rsft->file.hash << " in mDownloads list !" << std::endl ; - std::cerr << "Storing the map in a wait list." << std::endl ; - - mPendingChunkMaps[rsft->file.hash] = rsft ; - - continue ; // i.e. don't delete the item! - } - else - { - (fit->second)->mCreator->setAvailabilityMap(rsft->compressed_chunk_map) ; - (fit->second)->mCreator->setChunkStrategy((FileChunksInfo::ChunkStrategy)(rsft->chunk_strategy)) ; - } - } - } - - /* cleanup */ - delete (*it); - } - load.clear() ; - return true; - -} - -bool ftController::loadConfigMap(std::map &configMap) -{ - std::map::iterator mit; - - //std::string str_true("true"); - //std::string empty(""); - //std::string dir = "notempty"; - - if (configMap.end() != (mit = configMap.find(download_dir_ss))) - setDownloadDirectory(mit->second); - - if (configMap.end() != (mit = configMap.find(active_downloads_size_ss))) - { - int n=5 ; - sscanf(mit->second.c_str(), "%d", &n); - std::cerr << "Note: loading active max downloads: " << n << std::endl; - setQueueSize(n); - } - if (configMap.end() != (mit = configMap.find(partial_dir_ss))) - { - setPartialsDirectory(mit->second); - } - - if (configMap.end() != (mit = configMap.find(default_encryption_policy_ss))) - { - if(mit->second == "STRICT") - { - mDefaultEncryptionPolicy = RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT ; - std::cerr << "Note: loading default value for encryption policy: STRICT" << std::endl; - } - else if(mit->second == "PERMISSIVE") - { - mDefaultEncryptionPolicy = RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE ; - std::cerr << "Note: loading default value for encryption policy: PERMISSIVE" << std::endl; - } - else - { - std::cerr << "(EE) encryption policy not recognized: \"" << mit->second << "\"" << std::endl; - mDefaultEncryptionPolicy = RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE ; - } - } - - if (configMap.end() != (mit = configMap.find(default_chunk_strategy_ss))) - { - if(mit->second == "STREAMING") - { - setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_STREAMING) ; - std::cerr << "Note: loading default value for chunk strategy: streaming" << std::endl; - } - else if(mit->second == "RANDOM") - { - setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; - std::cerr << "Note: loading default value for chunk strategy: random" << std::endl; - } - else if(mit->second == "PROGRESSIVE") - { - setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) ; - std::cerr << "Note: loading default value for chunk strategy: progressive" << std::endl; - } - else - std::cerr << "**** ERROR ***: Unknown value for default chunk strategy in keymap." << std::endl ; - } - - if (configMap.end() != (mit = configMap.find(free_space_limit_ss))) - { - uint32_t size ; - if (sscanf(mit->second.c_str(), "%u", &size) == 1) { - std::cerr << "have read a size limit of " << size <<" MB" << std::endl ; - - RsDiscSpace::setFreeSpaceLimit(size) ; - } - } - if(configMap.end() != (mit = configMap.find(max_uploads_per_friend_ss))) - { - uint32_t n ; - if (sscanf(mit->second.c_str(), "%u", &n) == 1) { - std::cerr << "have read a max upload slots limit of " << n << std::endl ; - - _max_uploads_per_friend = n ; - } - } - - if(configMap.end() != (mit = configMap.find(file_perm_direct_dl_ss))) - { - if(mit->second == "YES") - { - mFilePermDirectDLPolicy = RS_FILE_PERM_DIRECT_DL_YES ; - std::cerr << "Note: loading default value for file permission direct download: YES" << std::endl; - } - else if(mit->second == "NO") - { - mFilePermDirectDLPolicy = RS_FILE_PERM_DIRECT_DL_NO ; - std::cerr << "Note: loading default value for file permission direct download: NO" << std::endl; - } - else if(mit->second == "PER_USER") - { - mFilePermDirectDLPolicy = RS_FILE_PERM_DIRECT_DL_PER_USER ; - std::cerr << "Note: loading default value for file permission direct download: PER_USER" << std::endl; - } - } - - return true; -} - -void ftController::setMaxUploadsPerFriend(uint32_t m) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - _max_uploads_per_friend = m ; - IndicateConfigChanged(); -} -uint32_t ftController::getMaxUploadsPerFriend() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - return _max_uploads_per_friend ; -} -void ftController::setDefaultEncryptionPolicy(uint32_t p) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - mDefaultEncryptionPolicy = p ; - IndicateConfigChanged(); -} -uint32_t ftController::defaultEncryptionPolicy() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - return mDefaultEncryptionPolicy ; -} - -void ftController::setFilePermDirectDL(uint32_t perm) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - if (mFilePermDirectDLPolicy != perm) - { - mFilePermDirectDLPolicy = perm; - IndicateConfigChanged(); - } -} -uint32_t ftController::filePermDirectDL() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - return mFilePermDirectDLPolicy; -} - -void ftController::setFreeDiskSpaceLimit(uint32_t size_in_mb) -{ - RsDiscSpace::setFreeSpaceLimit(size_in_mb) ; - - IndicateConfigChanged() ; -} - - -uint32_t ftController::freeDiskSpaceLimit() const -{ - return RsDiscSpace::freeSpaceLimit() ; -} - -FileChunksInfo::ChunkStrategy ftController::defaultChunkStrategy() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - return mDefaultChunkStrategy ; -} -void ftController::setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy S) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ -#ifdef CONTROL_DEBUG - std::cerr << "Note: in frController: setting chunk strategy to " << S << std::endl ; -#endif - mDefaultChunkStrategy = S ; - IndicateConfigChanged() ; -} diff --git a/libretroshare/src/ft/ftcontroller.h b/libretroshare/src/ft/ftcontroller.h deleted file mode 100644 index e890a83d6..000000000 --- a/libretroshare/src/ft/ftcontroller.h +++ /dev/null @@ -1,273 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftcontroller.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef FT_CONTROLLER_HEADER -#define FT_CONTROLLER_HEADER - -/* - * ftController - * - * Top level download controller. - * - * inherits configuration (save downloading files) - * inherits pqiMonitor (knows which peers are online). - * inherits CacheTransfer (transfers cache files too) - * inherits RsThread (to control transfers) - * - */ - -class ftFileCreator; -class ftTransferModule; -class ftFileProvider; -class ftSearch; -class ftServer; -class ftExtraList; -class ftDataMultiplex; -class p3turtle ; -class p3ServiceControl; - -#include "util/rsthreads.h" -#include "pqi/pqiservicemonitor.h" -#include "pqi/p3cfgmgr.h" - -#include "retroshare/rsfiles.h" -#include "rsitems/rsconfigitems.h" - -#include - - -const uint32_t FC_TRANSFER_COMPLETE = 0x0001; - -class ftFileControl -{ - public: - - enum { DOWNLOADING = 0, - COMPLETED = 1, - ERROR_COMPLETION = 2, - QUEUED = 3, - PAUSED = 4, - CHECKING_HASH = 5 - }; - - ftFileControl(); - ftFileControl( const std::string& fname, const std::string& tmppath, const std::string& dest - , uint64_t size, const RsFileHash& hash, TransferRequestFlags flags - , ftFileCreator *fc, ftTransferModule *tm); - - std::string mName; - std::string mCurrentPath; /* current full path (including name) */ - std::string mDestination; /* final full path (including name) */ - ftTransferModule * mTransfer; - ftFileCreator * mCreator; - uint32_t mState; - RsFileHash mHash; - uint64_t mSize; - TransferRequestFlags mFlags; - rstime_t mCreateTime; - uint32_t mQueuePriority ; - uint32_t mQueuePosition ; -}; - -class ftPendingRequest -{ - public: - ftPendingRequest(const std::string& fname, const RsFileHash& hash, - uint64_t size, const std::string& dest, TransferRequestFlags flags, - const std::list &srcIds, uint16_t state) - : mName(fname), mHash(hash), mSize(size), - mDest(dest), mFlags(flags), mSrcIds(srcIds), mState(state) { return; } - - ftPendingRequest() : mSize(0), mFlags(0), mState(0) { return; } - - std::string mName; - RsFileHash mHash; - uint64_t mSize; - std::string mDest; - TransferRequestFlags mFlags; - std::list mSrcIds; - uint16_t mState; -}; - - -class ftController: - public RsTickingThread, public pqiServiceMonitor, public p3Config -{ -public: - - /* Setup */ - ftController(ftDataMultiplex *dm, p3ServiceControl *sc, uint32_t ftServiceId); - - void setFtSearchNExtra(ftSearch *, ftExtraList *); - void setTurtleRouter(p3turtle *) ; - void setFtServer(ftServer *) ; - bool activate(); - bool isActiveAndNoPending(); - - void threadTick() override; /// @see RsTickingThread - - /***************************************************************/ - /********************** Controller Access **********************/ - /***************************************************************/ - - bool FileRequest(const std::string& fname, const RsFileHash& hash, - uint64_t size, const std::string& dest, TransferRequestFlags flags, - const std::list &sourceIds, uint16_t state = ftFileControl::DOWNLOADING); - - /// Do we already have this file, either in download or in file lists ? - bool alreadyHaveFile(const RsFileHash& hash, FileInfo &info); - - bool setChunkStrategy(const RsFileHash& hash,FileChunksInfo::ChunkStrategy s); - void setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy s); - void setDefaultEncryptionPolicy(uint32_t s); - FileChunksInfo::ChunkStrategy defaultChunkStrategy(); - uint32_t freeDiskSpaceLimit() const ; - void setFreeDiskSpaceLimit(uint32_t size_in_mb) ; - uint32_t defaultEncryptionPolicy(); - - void setMaxUploadsPerFriend(uint32_t m) ; - uint32_t getMaxUploadsPerFriend() ; - - void setFilePermDirectDL(uint32_t perm) ; - uint32_t filePermDirectDL() ; - - bool FileCancel(const RsFileHash& hash); - bool FileControl(const RsFileHash& hash, uint32_t flags); - bool FileClearCompleted(); - bool FlagFileComplete(const RsFileHash& hash); - bool getFileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo& info); - bool setDestinationName(const RsFileHash& hash,const std::string& dest_name) ; - bool setDestinationDirectory(const RsFileHash& hash,const std::string& dest_name) ; - - // Download speed - bool getPriority(const RsFileHash& hash,DwlSpeed& p); - void setPriority(const RsFileHash& hash,DwlSpeed p); - - // Action on queue position - // - void moveInQueue(const RsFileHash& hash,QueueMove mv) ; - void clearQueue() ; - void setQueueSize(uint32_t size) ; - uint32_t getQueueSize() ; - - /* get Details of File Transfers */ - void FileDownloads(std::list &hashs); - - /* Directory Handling */ - bool setDownloadDirectory(std::string path); - bool setPartialsDirectory(std::string path); - std::string getDownloadDirectory(); - std::string getPartialsDirectory(); - bool FileDetails(const RsFileHash &hash, FileInfo &info); - - /***************************************************************/ - /********************** Cache Transfer *************************/ - /***************************************************************/ - - /// Returns true is full source availability can be assumed for this peer. - /// - bool assumeAvailability(const RsPeerId& peer_id) const ; - - /* pqiMonitor callback (also provided mConnMgr pointer!) */ - virtual void statusChange(const std::list &plist); - - void addFileSource(const RsFileHash& hash,const RsPeerId& peer_id) ; - void removeFileSource(const RsFileHash& hash,const RsPeerId& peer_id) ; - - protected: - - void searchForDirectSources() ; - void tickTransfers() ; - - /***************************************************************/ - /********************** Controller Access **********************/ - /***************************************************************/ - - - /* p3Config Interface */ - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool &cleanup, std::list&); - virtual bool loadList(std::list& load); - bool loadConfigMap(std::map &configMap); - - private: - - /* RunTime Functions */ - void checkDownloadQueue(); // check the whole queue for inactive files - - void locked_addToQueue(ftFileControl*,int strategy) ;// insert this one into the queue - void locked_bottomQueue(uint32_t pos) ; // bottom queue file which is at this position - void locked_topQueue(uint32_t pos) ; // top queue file which is at this position - void locked_checkQueueElement(uint32_t pos) ; // check the state of this element in the queue - void locked_queueRemove(uint32_t pos) ; // delete this element from the queue - void locked_swapQueue(uint32_t pos1,uint32_t pos2) ; // swap position of the two elements - - bool completeFile(const RsFileHash& hash); - bool handleAPendingRequest(); - - bool setPeerState(ftTransferModule *tm, const RsPeerId& id, - uint32_t maxrate, bool online); - - rstime_t last_save_time ; - rstime_t last_clean_time ; - /* pointers to other components */ - - ftSearch *mSearch; - ftDataMultiplex *mDataplex; - ftExtraList *mExtraList; - p3turtle *mTurtle ; - ftServer *mFtServer ; - p3ServiceControl *mServiceCtrl; - uint32_t mFtServiceType; - uint32_t mDefaultEncryptionPolicy; - uint32_t mFilePermDirectDLPolicy; - - uint32_t cnt ; - RsMutex ctrlMutex; - - std::map mCompleted; - std::map mDownloads; - std::vector mDownloadQueue ; - - std::string mConfigPath; - std::string mDownloadPath; - std::string mPartialsPath; - - /**** SPEED QUEUES ****/ - - /* callback list (for File Completion) */ - RsMutex doneMutex; - std::list mDone; - - /* List to Pause File transfers until Caches are properly loaded */ - bool mFtActive; - bool mFtPendingDone; - std::list mPendingRequests; - std::map mPendingChunkMaps ; - - FileChunksInfo::ChunkStrategy mDefaultChunkStrategy ; - - uint32_t _max_active_downloads ; // maximum number of simultaneous downloads - uint32_t _max_uploads_per_friend ; // maximum number of uploads per friend. 0 means unlimited. -}; - -#endif diff --git a/libretroshare/src/ft/ftdata.h b/libretroshare/src/ft/ftdata.h deleted file mode 100644 index 349dae521..000000000 --- a/libretroshare/src/ft/ftdata.h +++ /dev/null @@ -1,94 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftdata.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef FT_DATA_INTERFACE_HEADER -#define FT_DATA_INTERFACE_HEADER - -/* - * ftData. - * - * Internal Interfaces for sending and receiving data. - * Most likely to be implemented by ftServer. - * Provided as an independent interface for testing purposes. - * - */ - -#include -#include - -#include - - /*************** SEND INTERFACE *******************/ - -class CompressedChunkMap ; - -class ftDataSend -{ - public: - virtual ~ftDataSend() { return; } - - /* Client Send */ - virtual bool sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize) = 0; - - /* Server Send */ - virtual bool sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data) = 0; - - /// Send a chunkmap[request]. Because requests/chunkmaps can go both - //directions, but for different usages, we have this "is_client" flags, - //that gives the ultimate goal of the data. "is_client==true" means that - //the message is for a client (download) instead of a server. - // - virtual bool sendChunkMapRequest(const RsPeerId& peer_id,const RsFileHash& hash,bool is_client) = 0; - virtual bool sendChunkMap(const RsPeerId& peer_id,const RsFileHash& hash,const CompressedChunkMap& cmap,bool is_client) = 0; - - /// Send a request for a chunk crc map - virtual bool sendSingleChunkCRCRequest(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_number) = 0; - /// Send a chunk crc map - virtual bool sendSingleChunkCRC(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_number,const Sha1CheckSum& crc) = 0; -}; - - - - /*************** RECV INTERFACE *******************/ - -class ftDataRecv -{ - public: - virtual ~ftDataRecv() { return; } - - /* Client Recv */ - virtual bool recvData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data) = 0; - - /* Server Recv */ - virtual bool recvDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize) = 0; - - /// Send a request for a chunk map - virtual bool recvChunkMapRequest(const RsPeerId& peer_id,const RsFileHash& hash,bool is_client) = 0; - - /// Send a chunk map - virtual bool recvChunkMap(const RsPeerId& peer_id,const RsFileHash& hash,const CompressedChunkMap& cmap,bool is_client) = 0; - - virtual bool recvSingleChunkCRCRequest(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_id) = 0; - virtual bool recvSingleChunkCRC(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_id,const Sha1CheckSum& sum) = 0; - -}; - -#endif diff --git a/libretroshare/src/ft/ftdatamultiplex.cc b/libretroshare/src/ft/ftdatamultiplex.cc deleted file mode 100644 index de8f1261c..000000000 --- a/libretroshare/src/ft/ftdatamultiplex.cc +++ /dev/null @@ -1,1164 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftdatamultiplex.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -/* - * ftDataMultiplexModule. - * - * This multiplexes the data from PQInterface to the ftTransferModules. - */ - -#include "ft/ftdatamultiplex.h" -#include "ft/fttransfermodule.h" -#include "ft/ftfilecreator.h" -#include "ft/ftfileprovider.h" -#include "ft/ftsearch.h" -#include "util/rsdir.h" -#include "util/rsmemory.h" -#include -#include "util/rstime.h" - -/* For Thread Behaviour */ -const uint32_t DMULTIPLEX_MIN = 10; /* 10 msec sleep */ -const uint32_t DMULTIPLEX_MAX = 1000; /* 1 sec sleep */ -const double DMULTIPLEX_RELAX = 0.5; /* relax factor to calculate sleep time if not working in /libretroshare/src/util/rsthreads.cc */ - -static const uint32_t MAX_CHECKING_CHUNK_WAIT_DELAY = 120 ; //! TTL for an inactive chunk -const uint32_t MAX_SIMULTANEOUS_CRC_REQUESTS = 20 ; - -/****** - * #define MPLEX_DEBUG 1 - *****/ - -ftClient::ftClient(ftTransferModule *module, ftFileCreator *creator) - :mModule(module), mCreator(creator) -{ - return; -} - -const uint32_t FT_DATA = 0x0001; // data cuhnk to be stored -const uint32_t FT_DATA_REQ = 0x0002; // data request to be treated -const uint32_t FT_CLIENT_CHUNK_MAP_REQ = 0x0003; // chunk map request to be treated by client -const uint32_t FT_SERVER_CHUNK_MAP_REQ = 0x0004; // chunk map request to be treated by server -//const uint32_t FT_CRC32MAP_REQ = 0x0005; // crc32 map request to be treated by server -const uint32_t FT_CLIENT_CHUNK_CRC_REQ = 0x0006; // chunk sha1 crc request to be treated - -ftRequest::ftRequest(uint32_t type, const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunk, void *data) - :mType(type), mPeerId(peerId), mHash(hash), mSize(size), - mOffset(offset), mChunk(chunk), mData(data) -{ - return; -} - -ftDataMultiplex::ftDataMultiplex(const RsPeerId& ownId, ftDataSend *server, ftSearch *search) - :RsQueueThread(DMULTIPLEX_MIN, DMULTIPLEX_MAX, DMULTIPLEX_RELAX), dataMtx("ftDataMultiplex"), - mDataSend(server), mSearch(search), mOwnId(ownId) -{ - return; -} - -bool ftDataMultiplex::getFileData(const RsFileHash& hash, uint64_t offset, uint32_t& requested_size, uint8_t *data) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - ftFileProvider* provider = 0; - - std::map::iterator cit; - std::map::iterator sit; - - // check if file is currently downloading - if (mClients.end() != (cit = mClients.find(hash))) - provider = (cit->second).mCreator; - - // else check if its already uploading - else if (mServers.end() != (sit = mServers.find(hash))) - provider = sit->second; - - // else create a new provider - else - { - FileInfo info; - FileSearchFlags hintflags = RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_SPEC_ONLY | RS_FILE_HINTS_NETWORK_WIDE; - if(mSearch->search(hash, hintflags, info)) - { - provider = new ftFileProvider(info.path, info.size, hash); - mServers[hash] = provider; - } - } - - if(!provider || ! provider->getFileData(mOwnId, offset, requested_size, data, true)) - { - requested_size = 0 ; - return false ; - } - return true ; -} - -bool ftDataMultiplex::addTransferModule(ftTransferModule *mod, ftFileCreator *f) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - std::map::iterator it; - if (mClients.end() != (it = mClients.find(mod->hash()))) - { - /* error */ - return false; - } - mClients[mod->hash()] = ftClient(mod, f); - - return true; -} - -bool ftDataMultiplex::removeTransferModule(const RsFileHash& hash) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - std::map::iterator it; - if (mClients.end() == (it = mClients.find(hash))) - { - /* error */ - return false; - } - mClients.erase(it); - - // This is very important to delete the hash from servers as well, because - // after removing the transfer module, ftController will delete the fileCreator. - // If the file creator is also a server in use, then it will cause a crash - // at the next server request. - // - // With the current action, the next server request will re-create the server as - // a ftFileProvider. - // - std::map::iterator sit = mServers.find(hash) ; - - if(sit != mServers.end()) - mServers.erase(sit); - - return true; -} - - -bool ftDataMultiplex::FileUploads(std::list &hashs) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - std::map::iterator sit; - for(sit = mServers.begin(); sit != mServers.end(); ++sit) - { - hashs.push_back(sit->first); - } - return true; -} - -bool ftDataMultiplex::FileDownloads(std::list &hashs) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - std::map::iterator cit; - for(cit = mClients.begin(); cit != mClients.end(); ++cit) - { - hashs.push_back(cit->first); - } - return true; -} - - -bool ftDataMultiplex::FileDetails(const RsFileHash &hash, FileSearchFlags hintsflag, FileInfo &info) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::FileDetails("; - std::cerr << hash << ", " << hintsflag << ")"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - if(hintsflag & RS_FILE_HINTS_DOWNLOAD) - { - std::map::iterator cit; - if (mClients.end() != (cit = mClients.find(hash))) - { - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::FileDetails()"; - std::cerr << " Found ftFileCreator!"; - std::cerr << std::endl; -#endif - - //(cit->second).mModule->FileDetails(info); - (cit->second).mCreator->FileDetails(info); - return true; - } - } - - if(hintsflag & RS_FILE_HINTS_UPLOAD) - { - std::map::iterator sit; - sit = mServers.find(hash); - if (sit != mServers.end()) - { - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::FileDetails()"; - std::cerr << " Found ftFileProvider!"; - std::cerr << std::endl; -#endif - - (sit->second)->FileDetails(info); - return true; - } - } - - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::FileDetails()"; - std::cerr << " Found nothing"; - std::cerr << std::endl; -#endif - - return false; -} - - /* data interface */ - - /*************** SEND INTERFACE (calls ftDataSend) *******************/ - - /* Client Send */ -bool ftDataMultiplex::sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::sendDataRequest() Client Send"; - std::cerr << std::endl; -#endif - return mDataSend->sendDataRequest(peerId,hash,size,offset,chunksize); -} - - /* Server Send */ -bool ftDataMultiplex::sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::sendData() Server Send"; - std::cerr << std::endl; -#endif - return mDataSend->sendData(peerId,hash,size,offset,chunksize,data); -} - - - /*************** RECV INTERFACE (provides ftDataRecv) ****************/ - - /* Client Recv */ -bool ftDataMultiplex::recvData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvData() Client Recv"; - std::cerr << std::endl; -#endif - /* Store in Queue */ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - mRequestQueue.push_back(ftRequest(FT_DATA,peerId,hash,size,offset,chunksize,data)); - - return true; -} - - - /* Server Recv */ -bool ftDataMultiplex::recvDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvDataRequest() Server Recv"; - std::cerr << std::endl; -#endif - /* Store in Queue */ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - mRequestQueue.push_back( - ftRequest(FT_DATA_REQ,peerId,hash,size,offset,chunksize,NULL)); - - return true; -} - -bool ftDataMultiplex::recvChunkMapRequest(const RsPeerId& peerId, const RsFileHash& hash,bool is_client) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvChunkMapRequest() Server Recv"; - std::cerr << std::endl; -#endif - /* Store in Queue */ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - if(is_client) - mRequestQueue.push_back(ftRequest(FT_CLIENT_CHUNK_MAP_REQ,peerId,hash,0,0,0,NULL)); - else - mRequestQueue.push_back(ftRequest(FT_SERVER_CHUNK_MAP_REQ,peerId,hash,0,0,0,NULL)); - - return true; -} - -bool ftDataMultiplex::recvSingleChunkCRCRequest(const RsPeerId& peerId, const RsFileHash& hash,uint32_t chunk_number) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvChunkMapRequest() Server Recv"; - std::cerr << std::endl; -#endif - /* Store in Queue */ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - mRequestQueue.push_back(ftRequest(FT_CLIENT_CHUNK_CRC_REQ,peerId,hash,0,0,chunk_number,NULL)); - - return true; -} - -/*********** BACKGROUND THREAD OPERATIONS ***********/ -bool ftDataMultiplex::workQueued() -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - if (mRequestQueue.size() > 0) - { - return true; - } - - if (mSearchQueue.size() > 0) - { - return true; - } - - return false; -} - -bool ftDataMultiplex::doWork() -{ - bool doRequests = true; - - /* Handle All the current Requests */ - while(doRequests) - { - ftRequest req; - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - if (mRequestQueue.empty()) - { - doRequests = false; - continue; - } - - req = mRequestQueue.front(); - mRequestQueue.pop_front(); - } - - /* MUTEX FREE */ - - switch(req.mType) - { - case FT_DATA: -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Handling FT_DATA"; - std::cerr << std::endl; -#endif - handleRecvData(req.mPeerId, req.mHash, req.mSize, req.mOffset, req.mChunk, req.mData); - break; - - case FT_DATA_REQ: -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Handling FT_DATA_REQ"; - std::cerr << std::endl; -#endif - handleRecvDataRequest(req.mPeerId, req.mHash, req.mSize, req.mOffset, req.mChunk); - break; - - case FT_CLIENT_CHUNK_MAP_REQ: -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Handling FT_CLIENT_CHUNK_MAP_REQ"; - std::cerr << std::endl; -#endif - handleRecvClientChunkMapRequest(req.mPeerId,req.mHash) ; - break ; - - case FT_SERVER_CHUNK_MAP_REQ: -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Handling FT_CLIENT_CHUNK_MAP_REQ"; - std::cerr << std::endl; -#endif - handleRecvServerChunkMapRequest(req.mPeerId,req.mHash) ; - break ; - - case FT_CLIENT_CHUNK_CRC_REQ: -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Handling FT_CLIENT_CHUNK_CRC_REQ"; - std::cerr << std::endl; -#endif - handleRecvChunkCrcRequest(req.mPeerId,req.mHash,req.mChunk) ; - break ; - - default: -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Ignoring UNKNOWN"; - std::cerr << std::endl; -#endif - break; - } - } - - /* Only Handle One Search Per Period.... - * Lower Priority - */ - ftRequest req; - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - if (mSearchQueue.empty()) - { - /* Finished */ - return true; - } - - req = mSearchQueue.front(); - mSearchQueue.pop_front(); - } - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Handling Search Request"; - std::cerr << std::endl; -#endif - if(handleSearchRequest(req.mPeerId, req.mHash)) - handleRecvDataRequest(req.mPeerId, req.mHash, req.mSize, req.mOffset, req.mChunk) ; - - - return true; -} - -bool ftDataMultiplex::recvSingleChunkCRC(const RsPeerId& peerId, const RsFileHash& hash,uint32_t chunk_number,const Sha1CheckSum& crc) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvSingleChunkCrc() Received crc of file " << hash << ", from peer id " << peerId << ", chunk " << chunk_number << ", crc=" << crc.toStdString() << std::endl; -#else - (void) peerId; -#endif - // remove this chunk from the request list as well. - - Sha1CacheEntry& sha1cache(_cached_sha1maps[hash]) ; - std::map >::iterator it2(sha1cache._to_ask.find(chunk_number)) ; - - if(it2 != sha1cache._to_ask.end()) - sha1cache._to_ask.erase(it2) ; - - // update the cache: get size from the client. - - std::map::iterator it = mClients.find(hash); - - if(it == mClients.end()) - { - std::cerr << "ftDataMultiplex::recvSingleChunkCrc() ERROR: No matching Client for CRC. This is an error. " << hash << " !" << std::endl; - /* error */ - return false; - } - - // store in the cache as well - - if(sha1cache._map.size() == 0) - sha1cache._map = Sha1Map(it->second.mCreator->fileSize(),ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE) ; - - sha1cache._map.set(chunk_number,crc) ; - - sha1cache._received.push_back(chunk_number) ; - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvSingleChunkCrc() stored in cache. " << std::endl; -#endif - - return true ; -} - -bool ftDataMultiplex::dispatchReceivedChunkCheckSum() -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - uint32_t MAX_CHECKSUM_CHECK_PER_FILE = 25 ; - - for(std::map::iterator it(_cached_sha1maps.begin());it!=_cached_sha1maps.end();) - { - std::map::iterator itc = mClients.find(it->first); - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::dispatchReceivedChunkCheckSum(): treating hash " << it->first << std::endl; -#endif - - if(itc == mClients.end()) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::dispatchReceivedChunkCheckSum() ERROR: No matching Client for hash. This is probably a late answer. Dropping the hash. Hash=" << it->first << std::endl; -#endif - - std::map::iterator tmp(it) ; - ++tmp ; - _cached_sha1maps.erase(it) ; - it = tmp ; - /* error */ - continue ; - } - ftFileCreator *client = itc->second.mCreator ; - - for(uint32_t n=0;nsecond._received.empty();++n) - { - int chunk_number = it->second._received.back() ; - - if(!it->second._map.isSet(chunk_number)) - std::cerr << "ftDataMultiplex::dispatchReceivedChunkCheckSum() ERROR: chunk " << chunk_number << " is supposed to be initialized but it was not received !!" << std::endl; - else - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::dispatchReceivedChunkCheckSum(): checking chunk " << chunk_number << " with hash " << it->second._map[chunk_number].toStdString() << std::endl; -#endif - client->verifyChunk(chunk_number,it->second._map[chunk_number]) ; - } - it->second._received.pop_back() ; - } - ++it ; - } - return true ; -} - -// A chunk map has arrived. It can be two different situations: -// - an uploader has sent his chunk map, so we need to store it in the corresponding ftFileProvider -// - a source for a download has sent his chunk map, so we need to send it to the corresponding ftFileCreator. -// -bool ftDataMultiplex::recvChunkMap(const RsPeerId& peerId, const RsFileHash& hash,const CompressedChunkMap& compressed_map,bool client) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - if(client) // is the chunk map for a client, or for a server ? - { - std::map::iterator it = mClients.find(hash); - - if(it == mClients.end()) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvChunkMap() ERROR: No matching Client for hash " << hash << " !"; - std::cerr << std::endl; -#endif - /* error */ - return false; - } - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvChunkMap() Passing map of file " << hash << ", to FT Module"; - std::cerr << std::endl; -#endif - - (it->second).mCreator->setSourceMap(peerId, compressed_map); - return true ; - } - else - { - std::map::iterator it = mServers.find(hash) ; - - if(it == mServers.end()) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMap() ERROR: No matching file Provider for hash " << hash ; - std::cerr << std::endl; -#endif - return false; - } - - it->second->setClientMap(peerId, compressed_map); - return true ; - } - - return false; -} - -bool ftDataMultiplex::handleRecvClientChunkMapRequest(const RsPeerId& peerId, const RsFileHash& hash) -{ - CompressedChunkMap cmap ; - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - std::map::iterator it = mClients.find(hash); - - if(it == mClients.end()) - { - // If we can't find the client, it's not a problem. Chunk maps from - // clients are not essential, as they are only used for display. -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvClientChunkMapRequest() ERROR: No matching Client for hash " << hash ; - std::cerr << ". Performing local search." << std::endl; -#endif - return false; - } - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvClientChunkMapRequest() Sending map of file " << hash << ", to peer " << peerId << std::endl; -#endif - - (it->second).mCreator->getAvailabilityMap(cmap); - } - - mDataSend->sendChunkMap(peerId,hash,cmap,false); - - return true ; -} - -bool ftDataMultiplex::handleRecvChunkCrcRequest(const RsPeerId& peerId, const RsFileHash& hash, uint32_t chunk_number) -{ - // look into the sha1sum cache - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() looking for chunk " << chunk_number << " for hash " << hash << std::endl; -#endif - - Sha1CheckSum crc ; - bool found = false ; - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - Sha1CacheEntry& sha1cache(_cached_sha1maps[hash]) ; - sha1cache.last_activity = time(NULL) ; // update time_stamp - - if(sha1cache._map.size() > 0 && sha1cache._map.isSet(chunk_number)) - { - crc = sha1cache._map[chunk_number] ; - found = true ; - } - } - - if(found) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() found in cache ! Sending " << crc.toStdString() << std::endl; -#endif - mDataSend->sendSingleChunkCRC(peerId,hash,chunk_number,crc); - return true ; - } - - std::map::iterator it ; - std::string filename ; - uint64_t filesize =0; - found = true ; - - // 1 - look into the list of servers.Not clients ! Clients dont' have verified data. - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - it = mServers.find(hash) ; - - if(it == mServers.end()) - found = false ; - } - - // 2 - if not found, create a server. - // - if(!found) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() ERROR: No matching file Provider for hash " << hash ; - std::cerr << std::endl; -#endif - if(!handleSearchRequest(peerId,hash)) - return false ; - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() A new file Provider has been made up for hash " << hash ; - std::cerr << std::endl; -#endif - } - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - it = mServers.find(hash) ; - - if(it == mServers.end()) // handleSearchRequest should have filled mServers[hash], but we have been off-mutex since, - { - std::cerr << "Could definitely not find a provider for file " << hash << ". Maybe the file does not exist?" << std::endl; - return false ; // so it's safer to check again. - } - else - { - filesize = it->second->fileSize() ; - filename = it->second->fileName() ; - } - } - -#ifdef MPLEX_DEBUG - std::cerr << "Computing Sha1 for chunk " << chunk_number<< " of file " << filename << ", hash=" << hash << ", size=" << filesize << std::endl; -#endif - - unsigned char *buf = new unsigned char[ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE] ; - FILE *fd = RsDirUtil::rs_fopen(filename.c_str(),"rb") ; - - if(fd == NULL) - { - std::cerr << "Cannot read file " << filename << ". Something's wrong!" << std::endl; - delete[] buf ; - return false ; - } - uint32_t len ; - if(fseeko64(fd,(uint64_t)chunk_number * (uint64_t)ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE,SEEK_SET)!=0 || 0==(len = fread(buf,1,ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE,fd))) - { - std::cerr << "Cannot fseek/read from file " << filename << " at position " << (uint64_t)chunk_number * (uint64_t)ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE << std::endl; - fclose(fd) ; - - delete[] buf ; - return false ; - } - fclose(fd) ; - - crc = RsDirUtil::sha1sum(buf,len) ; - delete[] buf ; - - // update cache - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - Sha1CacheEntry& sha1cache(_cached_sha1maps[hash]) ; - - if(sha1cache._map.size() == 0) - sha1cache._map = Sha1Map(filesize,ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE) ; - - sha1cache._map.set(chunk_number,crc) ; - } -#ifdef MPLEX_DEBUG - std::cerr << "Sending CRC of chunk " << chunk_number<< " of file " << filename << ", hash=" << hash << ", size=" << filesize << ", crc=" << crc.toStdString() << std::endl; -#endif - - mDataSend->sendSingleChunkCRC(peerId,hash,chunk_number,crc); - return true ; -} - -bool ftDataMultiplex::handleRecvServerChunkMapRequest(const RsPeerId& peerId, const RsFileHash& hash) -{ - CompressedChunkMap cmap ; - std::map::iterator it ; - bool found = true ; - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - it = mServers.find(hash) ; - - if(it == mServers.end()) - found = false ; - } - - if(!found) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() ERROR: No matching file Provider for hash " << hash ; - std::cerr << std::endl; -#endif - if(!handleSearchRequest(peerId,hash)) - return false ; - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() A new file Provider has been made up for hash " << hash ; - std::cerr << std::endl; -#endif - } - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - it = mServers.find(hash) ; - - if(it == mServers.end()) // handleSearchRequest should have filled mServers[hash], but we have been off-mutex since, - { - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() : weird state: search request succeeded, but no server available!" << std::endl; - return false ; // so it's safer to check again. - } - else - it->second->getAvailabilityMap(cmap); - } - - mDataSend->sendChunkMap(peerId,hash,cmap,true); - - return true; -} - -bool ftDataMultiplex::handleRecvData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t /*size*/, uint64_t offset, uint32_t chunksize, void *data) -{ - ftTransferModule *transfer_module = NULL ; - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - std::map::iterator it; - if (mClients.end() == (it = mClients.find(hash))) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvData() ERROR: No matching Client!"; - std::cerr << std::endl; -#endif - /* error */ - return false; - } - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvData() Passing to Module"; - std::cerr << std::endl; -#endif - - transfer_module = (it->second).mModule ; - } - transfer_module->recvFileData(peerId, offset, chunksize, data); - - return true; -} - - - /* called by ftTransferModule */ -bool ftDataMultiplex::handleRecvDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize) -{ - /**** Find Files *****/ - - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - std::map::iterator cit; - if (mOwnId == peerId) - { - /* own requests must be passed to Servers */ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvData() OwnId, so skip Clients..."; - std::cerr << std::endl; -#endif - } - else if (mClients.end() != (cit = mClients.find(hash))) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvData() Matched to a Client."; - std::cerr << std::endl; -#endif - locked_handleServerRequest((cit->second).mCreator, peerId, hash, size, offset, chunksize); - return true; - } - - std::map::iterator sit; - if (mServers.end() != (sit = mServers.find(hash))) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvData() Matched to a Provider."; - std::cerr << std::endl; -#endif - locked_handleServerRequest(sit->second, peerId, hash, size, offset, chunksize); - return true; - } - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvData() No Match... adding to Search Queue."; - std::cerr << std::endl; -#endif - - /* Add to Search Queue */ - mSearchQueue.push_back( ftRequest(FT_DATA_REQ, peerId, hash, size, offset, chunksize, NULL)); - - return true; -} - -bool ftDataMultiplex::locked_handleServerRequest(ftFileProvider *provider, const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, - uint64_t offset, uint32_t chunksize) -{ - if(chunksize > uint32_t(10*1024*1024)) - { - std::cerr << "Warning: peer " << peerId << " is asking a large chunk (s=" << chunksize << ") for hash " << hash << ", filesize=" << size << ". This is unexpected." << std::endl ; - return false ; - } - void *data = rs_malloc(chunksize); - - if(data == NULL) - return false ; - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::locked_handleServerRequest()"; - std::cerr << "\t peer: " << peerId << " hash: " << hash; - std::cerr << " size: " << size; - std::cerr << std::endl; - std::cerr << "\t offset: " << offset; - std::cerr << " chunksize: " << chunksize << " data: " << data; - std::cerr << std::endl; -#endif - - if (provider->getFileData(peerId,offset, chunksize, data)) - { - /* send data out */ - sendData(peerId, hash, size, offset, chunksize, data); - return true; - } -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::locked_handleServerRequest()"; - std::cerr << " FAILED"; - std::cerr << std::endl; -#endif - free(data); - - return false; -} - -bool ftDataMultiplex::getClientChunkMap(const RsFileHash& upload_hash,const RsPeerId& peerId,CompressedChunkMap& cmap) -{ - bool too_old = false; - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - std::map::iterator sit = mServers.find(upload_hash); - - if(mServers.end() == sit) - return false ; - - sit->second->getClientMap(peerId,cmap,too_old) ; - } - - // If the map is too old then we should ask an other map to the peer. - // - if(too_old) - sendChunkMapRequest(peerId,upload_hash,true); - - return true ; -} - -bool ftDataMultiplex::sendChunkMapRequest(const RsPeerId& peer_id,const RsFileHash& hash,bool is_client) -{ - return mDataSend->sendChunkMapRequest(peer_id,hash,is_client); -} -bool ftDataMultiplex::sendSingleChunkCRCRequests(const RsFileHash& hash, const std::vector& to_ask) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - // Put all requested chunks in the request queue. - - Sha1CacheEntry& ce(_cached_sha1maps[hash]) ; - - for(uint32_t i=0;i& list(ce._to_ask[to_ask[i]]) ; - list.first = 0 ; // set last request time to 0 - } - return true ; -} - -void ftDataMultiplex::handlePendingCrcRequests() -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - rstime_t now = time(NULL) ; - uint32_t n=0 ; - - // Go through the list of currently handled hashes. For each of them, - // look for pending chunk crc requests. - // - if the last request is too old, re-ask: - // - ask the file creator about the possible sources for this chunk => returns a list of active sources - // - among active sources, pick the one that has the smallest request time stamp, in the request list. - // - // With this, only active sources are querried. - // - - for(std::map::iterator it(_cached_sha1maps.begin());it!=_cached_sha1maps.end();++it) - for(std::map >::iterator it2(it->second._to_ask.begin());it2!=it->second._to_ask.end();++it2) - if(it2->second.first + MAX_CHECKING_CHUNK_WAIT_DELAY < now) // is the last request old enough? - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handlePendingCrcRequests(): Requesting sources for chunk " << it2->first << ", hash " << it->first << std::endl; -#endif - // 0 - ask which sources can be used for this chunk - // - std::map::const_iterator it4(mClients.find(it->first)) ; - - if(it4 == mClients.end()) - continue ; - - std::vector sources ; - it4->second.mCreator->getSourcesList(it2->first,sources) ; - - // 1 - go through all sources. Take the oldest one. - // - - RsPeerId best_source ; - rstime_t oldest_timestamp = now ; - - for(uint32_t i=0;i::const_iterator it3(it2->second.second.find(sources[i])) ; - - if(it3 == it2->second.second.end()) // source not found. So this one is surely the oldest one to have been requested. - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handlePendingCrcRequests(): not found! So using it directly." << std::endl; -#endif - best_source = sources[i] ; - break ; - } - else if(it3->second <= oldest_timestamp) // do nothing, otherwise, ask again - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handlePendingCrcRequests(): not found! So using it directly." << std::endl; -#endif - best_source = sources[i] ; - oldest_timestamp = it3->second ; - } -#ifdef MPLEX_DEBUG - else - std::cerr << "ftDataMultiplex::handlePendingCrcRequests(): Source too recently used! So using it directly." << std::endl; -#endif - } - if(!best_source.isNull()) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handlePendingCrcRequests(): Asking crc of chunk " << it2->first << " to peer " << best_source << " for hash " << it->first << std::endl; -#endif - // Use the source to ask the CRC. - // - // sendSingleChunkCRCRequest(peer_id, hash, chunk_id) - // - mDataSend->sendSingleChunkCRCRequest(best_source,it->first,it2->first); - it2->second.second[best_source] = now ; - it2->second.first = now ; - - if(++n > MAX_SIMULTANEOUS_CRC_REQUESTS) - return ; - } -#ifdef MPLEX_DEBUG - else - std::cerr << "ftDataMultiplex::handlePendingCrcRequests(): no source for chunk " << it2->first << std::endl; -#endif - } -} - -void ftDataMultiplex::deleteUnusedServers() -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - //scan the uploads list in ftdatamultiplex and delete the items which time out - rstime_t now = time(NULL); - - for(std::map::iterator sit(mServers.begin());sit != mServers.end();) - if(sit->second->purgeOldPeers(now,10)) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::deleteUnusedServers(): provider " << (void*)sit->second << " has no active peers. Removing. Now=" << now << std::endl ; -#endif - // We don't delete servers that are clients at the same time ! - if(dynamic_cast(sit->second) == NULL) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::deleteUnusedServers(): deleting file provider " << (void*)sit->second << std::endl ; -#endif - delete sit->second; - } -#ifdef MPLEX_DEBUG - else - std::cerr << "ftDataMultiplex::deleteUnusedServers(): " << (void*)sit->second << " was not deleted because it's also a file creator." << std::endl ; -#endif - - std::map::iterator tmp(sit); - ++tmp ; - - mServers.erase(sit); - - sit = tmp ; - } - else - ++sit ; -} - -bool ftDataMultiplex::handleSearchRequest(const RsPeerId& peerId, const RsFileHash& hash) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleSearchRequest("; - std::cerr << peerId << ", " << hash << "...)"; - std::cerr << std::endl; -#endif - - /* - * Do Actual search - * Could be Cache File, Local or Extra - * (anywhere but remote really) - * - * the network wide and browsable flags are needed, otherwise results get filtered. - * For tunnel creation, the check of browsable/network wide flag is already done, so - * if we get a file download packet here, the source is already allowed to download it. - * That is why we don't call the search function with a peer id. - * - */ - - FileInfo info; - FileSearchFlags hintflags = RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_SPEC_ONLY ; - - if(rsTurtle->isTurtlePeer(peerId)) - hintflags |= RS_FILE_HINTS_NETWORK_WIDE ; - - if(mSearch->search(hash, hintflags, info)) - { - - /* setup a new provider */ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - // We might already have a file provider, if two requests have got stacked in the request queue. So let's - // check that before. - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleSearchRequest("; - std::cerr << " Found Local File, sharing..."; -#endif - std::map::const_iterator it = mServers.find(hash) ; - ftFileProvider *provider ; - - if(it == mServers.end()) - { - provider = new ftFileProvider(info.path, info.size, hash); - mServers[hash] = provider; -#ifdef MPLEX_DEBUG - std::cerr << " created new file provider " << (void*)provider << std::endl; -#endif - } - else - { -#ifdef MPLEX_DEBUG - std::cerr << " re-using existing file provider " << (void*)it->second << std::endl; -#endif - } - - return true; - } - // Now check wether the required file is actually being downloaded. In such a case, - // setup the file provider to be the file creator itself. Warning: this server should not - // be deleted when not used anymore. We need to restrict this to client peers that are - // not ourself, since the file transfer also handles the local cache traffic (this - // is something to be changed soon!!) - // - - if(peerId != mOwnId) - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - std::map::const_iterator it(mClients.find(hash)) ; - - if(it != mClients.end()) - { - mServers[hash] = it->second.mCreator ; - return true; - } - } - - return false; -} - - - - - diff --git a/libretroshare/src/ft/ftdatamultiplex.h b/libretroshare/src/ft/ftdatamultiplex.h deleted file mode 100644 index 019940b63..000000000 --- a/libretroshare/src/ft/ftdatamultiplex.h +++ /dev/null @@ -1,192 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftdatamultiplex.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef FT_DATA_MULTIPLEX_HEADER -#define FT_DATA_MULTIPLEX_HEADER - -/* - * ftDataMultiplexModule. - * - * This multiplexes the data from PQInterface to the ftTransferModules. - */ - -class ftTransferModule; -class ftFileProvider; -class ftFileCreator; -class ftSearch; - -#include -#include -#include -#include - -#include "util/rsthreads.h" - -#include "ft/ftdata.h" -#include "retroshare/rsfiles.h" - - -class ftClient -{ - public: - - ftClient() :mModule(NULL), mCreator(NULL) { return; } - ftClient(ftTransferModule *module, ftFileCreator *creator); - - ftTransferModule *mModule; - ftFileCreator *mCreator; -}; - -class ftRequest -{ - public: - - ftRequest(uint32_t type, const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunk, void *data); - - ftRequest() - :mType(0), mSize(0), mOffset(0), mChunk(0), mData(NULL) { return; } - - uint32_t mType; - RsPeerId mPeerId; - RsFileHash mHash; - uint64_t mSize; - uint64_t mOffset; - uint32_t mChunk; - void *mData; -}; - -typedef std::map ChunkCheckSumSourceList ; - -class Sha1CacheEntry -{ - public: - Sha1Map _map ; // Map of available sha1 sums for every chunk. - rstime_t last_activity ; // This is used for removing unused entries. - std::vector _received ; // received chunk ids. To bedispatched. - std::map > _to_ask ; // Chunks to ask to sources. -}; - -class ftDataMultiplex: public ftDataRecv, public RsQueueThread -{ - - public: - - ftDataMultiplex(const RsPeerId& ownId, ftDataSend *server, ftSearch *search); - - /** - * @see RsFiles::getFileData - * - * data should be pre-allocated by the client with size sufficient gfor requested_size bytes. - * requested_size will be changed so as to contain the actual number of bytes copied from the file, - * in case where the full size wasn't available. - * False is returned if no data can be obtained from that file. - */ - bool getFileData(const RsFileHash& hash, uint64_t offset,uint32_t& requested_size, uint8_t *data); - - /* ftController Interface */ - bool addTransferModule(ftTransferModule *mod, ftFileCreator *f); - bool removeTransferModule(const RsFileHash& hash); - - /* data interface */ - /* get Details of File Transfers */ - bool FileUploads(std::list &hashs); - bool FileDownloads(std::list &hashs); - bool FileDetails(const RsFileHash &hash, FileSearchFlags hintsflag, FileInfo &info); - - void deleteUnusedServers() ; - void handlePendingCrcRequests() ; - - - /*************** SEND INTERFACE (calls ftDataSend) *******************/ - - /* Client Send */ - bool sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize); - - /* Server Send */ - bool sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); - - /* Server/client Send */ - bool sendChunkMapRequest(const RsPeerId& peerId, const RsFileHash& hash,bool is_client) ; - - - /* called from a separate thread */ - bool sendSingleChunkCRCRequests(const RsFileHash& hash, const std::vector& to_ask) ; - - bool dispatchReceivedChunkCheckSum() ; - - /*************** RECV INTERFACE (provides ftDataRecv) ****************/ - - /* Client Recv */ - virtual bool recvData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); - /* Server Recv */ - virtual bool recvDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize); - - /// Receive a request for a chunk map - virtual bool recvChunkMapRequest(const RsPeerId& peer_id,const RsFileHash& hash,bool is_client) ; - /// Receive a chunk map - virtual bool recvChunkMap(const RsPeerId& peer_id,const RsFileHash& hash,const CompressedChunkMap& cmap,bool is_client) ; - - virtual bool recvSingleChunkCRCRequest(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_id) ; - virtual bool recvSingleChunkCRC(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_id,const Sha1CheckSum& sum) ; - - // Returns the chunk map from the file uploading client. Also initiates a chunk map request if this - // map is too old. This supposes that the caller will ask again in a few seconds. - // - bool getClientChunkMap(const RsFileHash& upload_hash,const RsPeerId& peer_id,CompressedChunkMap& map) ; - - protected: - - /* Overloaded from RsQueueThread */ - virtual bool workQueued(); - virtual bool doWork(); - - private: - - /* Handling Job Queues */ - bool handleRecvData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); - bool handleRecvDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize); - bool handleSearchRequest(const RsPeerId& peerId, const RsFileHash& hash); - bool handleRecvClientChunkMapRequest(const RsPeerId& peerId, const RsFileHash& hash) ; - bool handleRecvServerChunkMapRequest(const RsPeerId& peerId, const RsFileHash& hash) ; - bool handleRecvChunkCrcRequest(const RsPeerId& peerId, const RsFileHash& hash,uint32_t chunk_id) ; - - /* We end up doing the actual server job here */ - bool locked_handleServerRequest(ftFileProvider *provider, const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize); - - RsMutex dataMtx; - - std::map mClients; - std::map mServers; - - std::list mRequestQueue; - std::list mSearchQueue; - - std::map _cached_sha1maps ; // one cache entry per file hash. Handled dynamically. - - ftDataSend *mDataSend; - ftSearch *mSearch; - RsPeerId mOwnId; - - friend class ftServer; -}; - -#endif diff --git a/libretroshare/src/ft/ftextralist.cc b/libretroshare/src/ft/ftextralist.cc deleted file mode 100644 index 3912cc1b3..000000000 --- a/libretroshare/src/ft/ftextralist.cc +++ /dev/null @@ -1,538 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftextralist.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2008 Robert Fernie * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#include -#include - -#ifdef WINDOWS_SYS -#include "util/rswin.h" -#endif - -#include -#include -#include "ft/ftextralist.h" -#include "rsitems/rsconfigitems.h" -#include "util/rsdir.h" -#include "util/rstime.h" -#include -#include /* for (u)sleep() */ -#include "util/rstime.h" - -/****** - * #define DEBUG_ELIST 1 - *****/ - -ftExtraList::ftExtraList() - :p3Config(), extMutex("p3Config") -{ - cleanup = 0; - return; -} - - -void ftExtraList::threadTick() -{ - bool todo = false; - rstime_t now = time(NULL); - - { - RsStackMutex stack(extMutex); - - todo = (mToHash.size() > 0); - } - - if (todo) - { - /* Hash a file */ - hashAFile(); - - /* microsleep */ - rstime::rs_usleep(10); - } - else - { - /* cleanup */ - if (cleanup < now) - { - cleanupOldFiles(); - cleanup = now + CLEANUP_PERIOD; - } - - /* sleep */ -#ifdef WIN32 - Sleep(1000); -#else - sleep(1); -#endif - } -} - - - -void ftExtraList::hashAFile() -{ -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::hashAFile()"; - std::cerr << std::endl; -#endif - - /* extract entry from the queue */ - FileDetails details; - - { - RS_STACK_MUTEX(extMutex); - - if (mToHash.empty()) - return; - - details = mToHash.front(); - mToHash.pop_front(); - } - -#ifdef DEBUG_ELIST - std::cerr << "Hashing: " << details.info.path; - std::cerr << std::endl; -#endif - - /* hash it! */ - std::string name, hash; - //uint64_t size; - if (RsDirUtil::hashFile(details.info.path, details.info.fname, details.info.hash, details.info.size)) - { - RS_STACK_MUTEX(extMutex); - - /* stick it in the available queue */ - mFiles[details.info.hash] = details; - mHashOfHash[makeEncryptedHash(details.info.hash)] = details.info.hash ; - - /* add to the path->hash map */ - mHashedList[details.info.path] = details.info.hash; - - IndicateConfigChanged(); - - auto ev = std::make_shared(); - ev->mEventCode = RsSharedDirectoriesEventCode::EXTRA_LIST_FILE_ADDED; - if(rsEvents) - rsEvents->postEvent(ev); - } -} - - /*** - * If the File is alreay Hashed, then just add it in. - **/ - -bool ftExtraList::addExtraFile(std::string path, const RsFileHash& hash, - uint64_t size, uint32_t period, TransferRequestFlags flags) -{ -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::addExtraFile() path: " << path; - std::cerr << " hash: " << hash; - std::cerr << " size: " << size; - std::cerr << " period: " << period; - std::cerr << " flags: " << flags; - - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(extMutex); - - FileDetails details; - - details.info.path = path; - details.info.fname = RsDirUtil::getTopDir(path); - details.info.hash = hash; - details.info.size = size; - details.info.age = time(NULL) + period; /* if time > this... cleanup */ - details.info.transfer_info_flags = flags ; - - /* stick it in the available queue */ - mFiles[details.info.hash] = details; - mHashOfHash[makeEncryptedHash(details.info.hash)] = details.info.hash ; - - IndicateConfigChanged(); - - return true; -} - -bool ftExtraList::removeExtraFile(const RsFileHash& hash) -{ - /* remove unused parameter warnings */ -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::removeExtraFile()"; - std::cerr << " hash: " << hash; - std::cerr << " flags: " << flags; - - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(extMutex); - - mHashOfHash.erase(makeEncryptedHash(hash)) ; - - std::map::iterator it; - it = mFiles.find(hash); - if (it == mFiles.end()) - { - return false; - } - - mFiles.erase(it); - - IndicateConfigChanged(); - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mEventCode = RsSharedDirectoriesEventCode::EXTRA_LIST_FILE_REMOVED; - rsEvents->postEvent(ev); - } - return true; -} - -bool ftExtraList::moveExtraFile(std::string fname, const RsFileHash &hash, uint64_t /*size*/, - std::string destpath) -{ - RsStackMutex stack(extMutex); - - std::map::iterator it; - it = mFiles.find(hash); - if (it == mFiles.end()) - { - return false; - } - - std::string path = destpath + '/' + fname; - if (RsDirUtil::renameFile(it->second.info.path, path)) - { - /* rename */ - it->second.info.path = path; - it->second.info.fname = fname; - IndicateConfigChanged(); - } - - return true; -} - - - -bool ftExtraList::cleanupOldFiles() -{ -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::cleanupOldFiles()"; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(extMutex); - - rstime_t now = time(NULL); - - std::list toRemove; - - for( std::map::iterator it = mFiles.begin(); it != mFiles.end(); ++it) /* check timestamps */ - if ((rstime_t)it->second.info.age < now) - toRemove.push_back(it->first); - - if (toRemove.size() > 0) - { - std::map::iterator it; - - /* remove items */ - for(std::list::iterator rit = toRemove.begin(); rit != toRemove.end(); ++rit) - { - if (mFiles.end() != (it = mFiles.find(*rit))) mFiles.erase(it); - mHashOfHash.erase(makeEncryptedHash(*rit)); - } - - IndicateConfigChanged(); - } - return true; -} - -bool ftExtraList::hashExtraFile( - std::string path, uint32_t period, TransferRequestFlags flags ) -{ - constexpr rstime_t max_int = std::numeric_limits::max(); - const rstime_t now = time(nullptr); - const rstime_t timeOut = now + period; - - if(timeOut > max_int) - { - /* Under the hood period is stored as int FileInfo::age so we do this - * check here to detect 2038 year problem - * https://en.wikipedia.org/wiki/Year_2038_problem */ - RsErr() << __PRETTY_FUNCTION__ << " period: " << period << " > " - << max_int - now << std::errc::value_too_large << std::endl; - return false; - } - - if(!RsDirUtil::fileExists(path)) - { - RsErr() << __PRETTY_FUNCTION__ << " path: " << path - << std::errc::no_such_file_or_directory << std::endl; - return false; - } - - if(RsDirUtil::checkDirectory(path)) - { - RsErr() << __PRETTY_FUNCTION__ << " path: " << path - << std::errc::is_a_directory << std::endl; - return false; - } - - FileDetails details(path, period, flags); - details.info.age = static_cast(timeOut); - - { - RS_STACK_MUTEX(extMutex); - mToHash.push_back(details); /* add into queue */ - } - - return true; -} - -bool ftExtraList::hashExtraFileDone(std::string path, FileInfo &info) -{ -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::hashExtraFileDone()"; - std::cerr << std::endl; -#endif - - RsFileHash hash; - { - /* Find in the path->hash map */ - RS_STACK_MUTEX(extMutex); - - std::map::iterator it; - if (mHashedList.end() == (it = mHashedList.find(path))) - { - return false; - } - hash = it->second; - } - return search(hash, FileSearchFlags(0), info); -} - - /*** - * Search Function - used by File Transfer - * - **/ -bool ftExtraList::search(const RsFileHash &hash, FileSearchFlags /*hintflags*/, FileInfo &info) const -{ -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::search() hash=" << hash ; -#endif - - /* find hash */ - std::map::const_iterator fit; - if (mFiles.end() == (fit = mFiles.find(hash))) - { -#ifdef DEBUG_ELIST - std::cerr << " not found in mFiles. Trying encrypted... " ; -#endif - // File not found. We try to look for encrypted hash. - - std::map::const_iterator hit = mHashOfHash.find(hash) ; - - if(hit == mHashOfHash.end()) - { -#ifdef DEBUG_ELIST - std::cerr << " not found." << std::endl; -#endif - return false; - } -#ifdef DEBUG_ELIST - std::cerr << " found! Reaching data..." ; -#endif - - fit = mFiles.find(hit->second) ; - - if(fit == mFiles.end()) // not found. This is an error. - { -#ifdef DEBUG_ELIST - std::cerr << " no data. Returning false." << std::endl; -#endif - return false ; - } - -#ifdef DEBUG_ELIST - std::cerr << " ok! Accepting encrypted transfer." << std::endl; -#endif - info = fit->second.info; - info.storage_permission_flags = FileStorageFlags(DIR_FLAGS_ANONYMOUS_DOWNLOAD) ; - info.transfer_info_flags |= RS_FILE_REQ_ENCRYPTED ; - } - else - { -#ifdef DEBUG_ELIST - std::cerr << " found! Accepting direct transfer" << std::endl; -#endif - info = fit->second.info; - - // Unencrypted file transfer: We only allow direct transfers. This is not exactly secure since another friend can - // swarm the file. But the hash being kept secret, there's no risk here. - // - info.storage_permission_flags = FileStorageFlags(DIR_FLAGS_BROWSABLE) ; - } - - if(info.transfer_info_flags & RS_FILE_REQ_ANONYMOUS_ROUTING) info.storage_permission_flags |= DIR_FLAGS_ANONYMOUS_DOWNLOAD ; - - return true; -} - -RsFileHash ftExtraList::makeEncryptedHash(const RsFileHash& hash) -{ - return RsDirUtil::sha1sum(hash.toByteArray(),hash.SIZE_IN_BYTES); -} - - /*** - * Configuration - store extra files. - * - **/ - -RsSerialiser *ftExtraList::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser(); - - /* add in the types we need! */ - rss->addSerialType(new RsFileConfigSerialiser()); - return rss; -} - -bool ftExtraList::saveList(bool &cleanup, std::list& sList) -{ - - - cleanup = true; - - /* called after each item is added */ - - /* create a list of fileitems with - * age used to specify its timeout. - */ - -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::saveList()"; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(extMutex); - - - std::map::const_iterator it; - for(it = mFiles.begin(); it != mFiles.end(); ++it) - { - RsFileConfigItem *fi = new RsFileConfigItem(); - - fi->file.path = (it->second).info.path; - fi->file.name = (it->second).info.fname; - fi->file.hash = (it->second).info.hash; - fi->file.filesize = (it->second).info.size; - fi->file.age = (it->second).info.age; - fi->flags = (it->second).info.transfer_info_flags.toUInt32(); - - sList.push_back(fi); - } - - return true; -} - - -bool ftExtraList::loadList(std::list& load) -{ - /* for each item, check it exists .... - * - remove any that are dead (or flag?) - */ - -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::loadList()"; - std::cerr << std::endl; -#endif - - rstime_t ts = time(NULL); - - - std::list::iterator it; - for(it = load.begin(); it != load.end(); ++it) - { - - RsFileConfigItem *fi = dynamic_cast(*it); - if (!fi) - { - delete (*it); - continue; - } - - /* open file */ - FILE *fd = RsDirUtil::rs_fopen(fi->file.path.c_str(), "rb"); - if (fd == NULL) - { - delete (*it); - continue; - } - - fclose(fd); - fd = NULL ; - - if (ts > (rstime_t)fi->file.age) - { - /* too old */ - delete (*it); - continue ; - } - - /* add into system */ - FileDetails file; - - RS_STACK_MUTEX(extMutex); - - FileDetails details; - - details.info.path = fi->file.path; - details.info.fname = fi->file.name; - details.info.hash = fi->file.hash; - details.info.size = fi->file.filesize; - details.info.age = fi->file.age; /* time that we remove it. */ - details.info.transfer_info_flags = TransferRequestFlags(fi->flags); - - /* stick it in the available queue */ - mFiles[details.info.hash] = details; - mHashOfHash[makeEncryptedHash(details.info.hash)] = details.info.hash ; - - delete (*it); - - /* short sleep */ - rstime::rs_usleep(1000) ; - } - load.clear() ; - return true; -} - -void ftExtraList::getExtraFileList(std::vector& files) const -{ - RS_STACK_MUTEX(extMutex); - - files.clear(); - - for(auto it(mFiles.begin());it!=mFiles.end();++it) - files.push_back(it->second.info); -} diff --git a/libretroshare/src/ft/ftextralist.h b/libretroshare/src/ft/ftextralist.h deleted file mode 100644 index 229c0fe3c..000000000 --- a/libretroshare/src/ft/ftextralist.h +++ /dev/null @@ -1,187 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftextralist.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef FT_FILE_EXTRA_LIST_HEADER -#define FT_FILE_EXTRA_LIST_HEADER - -/* - * ftFileExtraList - * - * This maintains a list of 'Extra Files' to share with peers. - * - * Files are added via: - * 1) For Files which have been hashed already: - * addExtraFile(std::string path, std::string hash, uint64_t size, uint32_t period, uint32_t flags); - * - * 2) For Files to be hashed: - * hashExtraFile(std::string path, uint32_t period, uint32_t flags); - * - * Results of Hashing can be retrieved via: - * hashExtraFileDone(std::string path, std::string &hash, uint64_t &size); - * - * Files can be searched for via: - * searchExtraFiles(std::string hash, ftFileDetail file); - * - * This Class is Mutexed protected, and has a thread in it which checks the files periodically. - * If a file is found to have changed... It is discarded from the list - and not updated. - * - * this thread is also used to hash added files. - * - * The list of extra files is stored using the configuration system. - * - */ - -#include -#include -#include - -#include "ft/ftsearch.h" -#include "util/rsthreads.h" -#include "retroshare/rsfiles.h" -#include "pqi/p3cfgmgr.h" -#include "util/rstime.h" - -class RS_DEPRECATED_FOR(FileInfo) FileDetails -{ - public: - FileDetails() - { - return; - } - - FileDetails(std::string path, uint32_t /*p*/, TransferRequestFlags f) - { - info.path = path; -// period = p; - info.transfer_info_flags = f; - } - - FileDetails(FileInfo &i, uint32_t /*p*/, TransferRequestFlags f) - { - info = i; - // period = p; - info.transfer_info_flags = f; - } - - FileInfo info; - -#if 0 /*** WHAT IS NEEDED ***/ - std::list sources; - std::string path; - std::string fname; - RsFileHash hash; - uint64_t size; -#endif - - //uint32_t start; - //uint32_t period; - //TransferRequestFlags flags; -}; - -const uint32_t FT_DETAILS_CLEANUP = 0x0100; /* remove when it expires */ -const uint32_t FT_DETAILS_LOCAL = 0x0001; -const uint32_t FT_DETAILS_REMOTE = 0x0002; - -const uint32_t CLEANUP_PERIOD = 600; /* 10 minutes */ - - -class ftExtraList: public RsTickingThread, public p3Config, public ftSearch -{ - -public: - - ftExtraList(); - - /*** - * If the File is alreay Hashed, then just add it in. - **/ - - bool addExtraFile(std::string path, const RsFileHash &hash, - uint64_t size, uint32_t period, TransferRequestFlags flags); - - bool removeExtraFile(const RsFileHash& hash); - bool moveExtraFile(std::string fname, const RsFileHash& hash, uint64_t size, - std::string destpath); - - - uint32_t size() const { return mFiles.size() ; } - - /*** - * Hash file, and add to the files, - * file is removed after period. - **/ - - /** - * Hash file, and add to the files, file is removed after period. - */ - bool hashExtraFile( - std::string path, uint32_t period, TransferRequestFlags flags ); - bool hashExtraFileDone(std::string path, FileInfo &info); - - /*** - * Search Function - used by File Transfer - * implementation of ftSearch. - * - **/ - virtual bool search(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const; - - /*! - * \brief getExtraFileList - * Retrieves the list for display purposes - */ - void getExtraFileList(std::vector& files) const ; - - void threadTick() override; /// @see RsTickingThread - - /*** - * Configuration - store extra files. - * - **/ - -protected: - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool &cleanup, std::list&); - virtual bool loadList(std::list& load); - - static RsFileHash makeEncryptedHash(const RsFileHash& hash); - -private: - - /* Worker Functions */ - void hashAFile(); - bool cleanupOldFiles(); - - mutable RsMutex extMutex; - - std::list mToHash; - - std::map mHashedList; /* path -> hash ( not saved ) */ - std::map mFiles; - std::map mHashOfHash; /* sha1(hash) map so as to answer requests to encrypted transfers */ - - rstime_t cleanup ; -}; - - - - -#endif diff --git a/libretroshare/src/ft/ftfilecreator.cc b/libretroshare/src/ft/ftfilecreator.cc deleted file mode 100644 index a5c354092..000000000 --- a/libretroshare/src/ft/ftfilecreator.cc +++ /dev/null @@ -1,762 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftfilecreator.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#ifdef WINDOWS_SYS -#include "util/rsstring.h" -#include "util/rswin.h" -#endif - -#include "ftfilecreator.h" -#include -#include -#include "util/rstime.h" -#include -#include -#include - -/******* - * #define FILE_DEBUG 1 - ******/ - -#define CHUNK_MAX_AGE 120 -#define MAX_FTCHUNKS_PER_PEER 20 - -/*********************************************************** -* -* ftFileCreator methods -* -***********************************************************/ - -ftFileCreator::ftFileCreator(const std::string& path, uint64_t size, const RsFileHash& hash,bool assume_availability) - : ftFileProvider(path,size,hash), chunkMap(size,assume_availability) -{ - /* - * FIXME any inits to do? - */ - -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator()"; - std::cerr << std::endl; - std::cerr << "\tpath: " << path; - std::cerr << std::endl; - std::cerr << "\tsize: " << size; - std::cerr << std::endl; - std::cerr << "\thash: " << hash; - std::cerr << std::endl; -#endif - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - rstime_t now = time(NULL) ; - _creation_time = now ; - - struct stat64 buf; - - // Initialise last recv time stamp to last modification time for the partial file. - // -#ifdef WINDOWS_SYS - std::wstring wfullname; - librs::util::ConvertUtf8ToUtf16(file_name, wfullname); - if ( 0 == _wstati64(wfullname.c_str(), &buf)) -#else - if ( 0 == stat64(file_name.c_str(), &buf)) -#endif - _last_recv_time_t = buf.st_mtime ; - else - _last_recv_time_t = now ; - -#ifdef FILE_DEBUG - std::cerr << "Inited last modification time for hash " << hash << " to " << _last_recv_time_t << std::endl; -#endif -} - -bool ftFileCreator::getFileData(const RsPeerId& peer_id,uint64_t offset, uint32_t &chunk_size, void *data, bool allow_unverified) -{ - // Only send the data if we actually have it. - // -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::getFileData(). Asked for offset=" << offset << ", size=" << chunk_size << std::endl ; -#endif - bool have_it = false ; - { - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - have_it = chunkMap.isChunkAvailable(offset, chunk_size) ; - -#define ENABLE_SLICES -#ifdef ENABLE_SLICES - // try if we have data from an incomplete or not veryfied chunk - if(!have_it && allow_unverified) - { - //std::map::iterator it; - have_it = true; - // this map contains chunks which are currently being downloaded - for(std::map::iterator it=mChunks.begin(); it!=mChunks.end(); ++it) - { - ftChunk chunk = it->second; - // begin of slice is in requested range - if(chunk.offset >= offset && chunk.offset < (offset+chunk_size)) - { - // reduce the requested size - chunk_size = chunk.offset - offset; - } - // end of slice is in requested range - if((chunk.offset+chunk.size) >= offset && (chunk.offset+chunk.size) < (offset+chunk_size)) - { - // can do nothing about this - have_it = false; - } - } - // check if the chunk was already started to download - // if not, we don't have it - if(chunkMap.isChunkOutstanding(offset, chunk_size)) - have_it = false; - } -#endif - } -#ifdef FILE_DEBUG - if(have_it) - std::cerr << "ftFileCreator::getFileData(). Have it" << std::endl ; - else - std::cerr << "ftFileCreator::getFileData(). Don't have it" << std::endl ; -#endif - - if(have_it) - return ftFileProvider::getFileData(peer_id,offset, chunk_size, data); - else - return false ; -} - -rstime_t ftFileCreator::creationTimeStamp() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - return _creation_time ; -} -rstime_t ftFileCreator::lastRecvTimeStamp() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - return _last_recv_time_t ; -} - -void ftFileCreator::closeFile() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - if(fd != NULL) - { -#ifdef FILE_DEBUG - std::cerr << "CLOSED FILE " << (void*)fd << " (" << file_name << ")." << std::endl ; -#endif - fclose(fd) ; - } - - fd = NULL ; -} - -uint64_t ftFileCreator::getRecvd() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - return chunkMap.getTotalReceived() ; -} - -bool ftFileCreator::addFileData(uint64_t offset, uint32_t chunk_size, void *data) -{ -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::addFileData("; - std::cerr << offset; - std::cerr << ", " << chunk_size; - std::cerr << ", " << data << ")"; - std::cerr << " this: " << this; - std::cerr << std::endl; -#endif - /* dodgey checking outside of mutex... much check again inside FileAttrs(). */ - /* Check File is open */ - - if(!RsDiscSpace::checkForDiscSpace(RS_PARTIALS_DIRECTORY)) - return false ; - - bool complete = false ; - { - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - if (fd == NULL) - if (!locked_initializeFileAttrs()) - return false; - - /* - * check its at the correct location - */ - if (offset + chunk_size > mSize) - { - chunk_size = mSize - offset; - std::cerr <<"Chunk Size greater than total file size, adjusting chunk size " << chunk_size << std::endl; - - } - - /* - * go to the offset of the file - */ - if (0 != fseeko64(this->fd, offset, SEEK_SET)) - { - std::cerr << "ftFileCreator::addFileData() Bad fseek at offset " << offset << ", fd=" << (void*)(this->fd) << ", size=" << mSize << ", errno=" << errno << std::endl; - return 0; - } - - if (1 != fwrite(data, chunk_size, 1, this->fd)) - { - std::cerr << "ftFileCreator::addFileData() Bad fwrite." << std::endl; - std::cerr << "ERRNO: " << errno << std::endl; - - return 0; - } - -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::addFileData() added Data..."; - std::cerr << std::endl; - std::cerr << " pos: " << offset; - std::cerr << std::endl; -#endif - /* - * Notify ftFileChunker about chunks received - */ - locked_notifyReceived(offset,chunk_size); - - complete = chunkMap.isComplete(); - } - if(complete) - { -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::addFileData() File is complete: closing" << std::endl ; -#endif - closeFile(); - } - - /* - * FIXME HANDLE COMPLETION HERE - Any better way? - */ - - return 1; -} - -void ftFileCreator::removeInactiveChunks() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::removeInactiveChunks(): looking for old chunks." << std::endl ; -#endif - std::vector to_remove ; - - chunkMap.removeInactiveChunks(to_remove) ; - -#ifdef FILE_DEBUG - if(!to_remove.empty()) - std::cerr << "ftFileCreator::removeInactiveChunks(): removing slice ids: " ; -#endif - // This double loop looks costly, but it's called on very few chunks, and not often, so it's ok. - // - for(uint32_t i=0;i::iterator it(mChunks.begin());it!=mChunks.end();) - if(it->second.id == to_remove[i]) - { - std::map::iterator tmp(it) ; - ++it ; - if(--*tmp->second.ref_cnt == 0) - delete tmp->second.ref_cnt; - --mChunksPerPeer[tmp->second.peer_id].cnt ; - mChunks.erase(tmp) ; - } - else - ++it ; - } -#ifdef FILE_DEBUG - if(!to_remove.empty()) - std::cerr << std::endl ; -#endif -} - -void ftFileCreator::removeFileSource(const RsPeerId& peer_id) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator:: removign file source " << peer_id << " from chunkmap." << std::endl ; -#endif - chunkMap.removeFileSource(peer_id) ; -} - -int ftFileCreator::locked_initializeFileAttrs() -{ -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::initializeFileAttrs() Filename: " << file_name << " this: " << this << std::endl; -#endif - - /* - * check if the file exists - * cant use FileProviders verion because that opens readonly. - */ - - if (fd) - return 1; - - /* - * check if the file exists - */ - - { -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::initializeFileAttrs() trying (r+b) " << file_name << " this: " << this << std::endl; -#endif - } - - /* - * attempt to open file - */ - - fd = RsDirUtil::rs_fopen(file_name.c_str(), "r+b"); - - if (!fd) - { -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::initializeFileAttrs() Failed to open (r+b): "; - std::cerr << file_name << ", errno = " << errno << std::endl; - - std::cerr << "ftFileCreator::initializeFileAttrs() opening w+b"; - std::cerr << std::endl; -#endif - - /* try opening for write */ - fd = RsDirUtil::rs_fopen(file_name.c_str(), "w+b"); - if (!fd) - { - std::cerr << "ftFileCreator::initializeFileAttrs()"; - std::cerr << " Failed to open (w+b): "<< file_name << ", errno = " << errno << std::endl; - return 0; - } - } -#ifdef FILE_DEBUG - std::cerr << "OPENNED FILE " << (void*)fd << " (" << file_name << "), for r/w." << std::endl ; -#endif - - return 1; -} -ftFileCreator::~ftFileCreator() -{ -#ifdef FILE_DEBUG - std::cerr << "Deleting file creator for " << file_name << std::endl; -#endif - - // Note: The file is actually closed in the parent, that is always a ftFileProvider. - // - /* - * FIXME Any cleanups specific to filecreator? - */ -} - - -int ftFileCreator::locked_notifyReceived(uint64_t offset, uint32_t chunk_size) -{ - /* ALREADY LOCKED */ -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::locked_notifyReceived( " << offset; - std::cerr << ", " << chunk_size << " )"; - std::cerr << " this: " << this; - std::cerr << std::endl; -#endif - - /* find the chunk */ - std::map::iterator it = mChunks.find(offset); - ftChunk chunk ; - - if(it == mChunks.end()) - { - // Chunk is not found. Maybe that is because the packet is in the middle - // of an existing chunk. This case occurs whenever a packet is lost due - // to temporarily interrupted connection. In such a case we split the - // chunk. Any pending block will be re-asked to the source after 40 secs. - // -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::locked_notifyReceived(): Failed to match to existing chunk. A packet was probably dropped. Strategy is:" << std::endl; - std::cerr << " - find corresponding chunk, split it in two pieces and ask again the first part." << std::endl; - - locked_printChunkMap(); -#endif - bool found = false ; - - for(std::map::iterator it2=mChunks.begin();it2!=mChunks.end();++it2) - if( it2->second.offset < offset && it2->second.size+it2->second.offset >= chunk_size+offset) // found it if it started strictly after the beginning of the chunk and ends before its end. - { - it = it2 ; -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::locked_notifyReceived(): Chunk found: " << it->second.offset << " to " << it->second.offset + it->second.size << std::endl; -#endif - - // 1 - split the chunk into two parts. Re-ask the first part, and keep the second part - // as ongoing. - - ftChunk part1( it->second ); - part1.size = offset - it->second.offset ; // always > 0 - - chunk = it->second ; // saves the data, as it will be erased by next line - mChunks[part1.offset] = part1; - - chunk.offset = offset ; - chunk.size -= part1.size ; - - // 2 - we need to be extra careful: - // - the chunks will have the same id. That's potentially a problem for completing the slice - // we should keep a list of pending chunkIds, so as to only call chunkMap.dataReceived() when - // all parts are obtained. - // - new parts arriving in the second part cannot interfere since they should come in order. - - ++(*chunk.ref_cnt) ; - -#ifdef FILE_DEBUG - std::cerr << "Created two sub chunks. Ref_cnt = " << *chunk.ref_cnt << std::endl; - std::cerr << " chunk1: " << part1 << std::endl; - std::cerr << " chunk2: " << chunk << std::endl; -#endif - - found = true ; - break ; - } - - if(!found) - { -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::locked_notifyReceived(): failed to find an active slice for " << offset << "+" << chunk_size << ", hash = " << hash << ": dropping data." << std::endl; -#endif - return 0; /* ignoring */ - } - } - else - { - chunk = it->second; - mChunks.erase(it); - } - - if (chunk.size != chunk_size) - { - /* partial : shrink chunk */ - chunk.size -= chunk_size; - chunk.offset += chunk_size; - mChunks[chunk.offset] = chunk; - } - else if( --*chunk.ref_cnt == 0) // notify the chunkmap that the slice is finished, and decrement the number of chunks for this peer. - { -#ifdef FILE_DEBUG - std::cerr << "Chunk finished and ref cnt = " << *chunk.ref_cnt << ": deleting." << std::endl; -#endif - chunkMap.dataReceived(chunk.id) ; - --mChunksPerPeer[chunk.peer_id].cnt ; - delete chunk.ref_cnt ; // delete the counter - } -#ifdef FILE_DEBUG - else - std::cerr << "Chunk finished but ref cnt = " << *chunk.ref_cnt << ": not deleting." << std::endl; -#endif - - _last_recv_time_t = time(NULL) ; - - /* otherwise there is another earlier block to go - */ - - return 1; -} - -FileChunksInfo::ChunkStrategy ftFileCreator::getChunkStrategy() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - return chunkMap.getStrategy() ; -} -void ftFileCreator::setChunkStrategy(FileChunksInfo::ChunkStrategy s) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - // Let's check, for safety. - if(s != FileChunksInfo::CHUNK_STRATEGY_STREAMING && s != FileChunksInfo::CHUNK_STRATEGY_RANDOM && s != FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) - { - std::cerr << "ftFileCreator::ERROR: invalid chunk strategy " << s << "!" << " setting default value " << FileChunksInfo::CHUNK_STRATEGY_STREAMING << std::endl ; - s = FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE ; - } - -#ifdef FILE_DEBUG - std::cerr << "ftFileCtreator: setting chunk strategy to " << s << std::endl ; -#endif - chunkMap.setStrategy(s) ; -} - -/* Returns true if more to get - * But can return size = 0, if we are still waiting for the data. - */ - -bool ftFileCreator::getMissingChunk(const RsPeerId& peer_id,uint32_t size_hint,uint64_t &offset, uint32_t& size,bool& source_chunk_map_needed) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ -#ifdef FILE_DEBUG - std::cerr << "ffc::getMissingChunk(...,"<< size_hint << ")"; - std::cerr << " this: " << this; - std::cerr << std::endl; - locked_printChunkMap(); -#endif - source_chunk_map_needed = false ; - rstime_t now = time(NULL) ; - - // 0 - is there a faulting chunk that would need to be asked again ? - - for(std::map::iterator it(mChunks.begin());it!=mChunks.end();++it) - if(it->second.ts + CHUNK_MAX_AGE < now && chunkMap.getSourceChunksInfo(peer_id)->hasData(it->second.offset,ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE)) - { - offset = it->second.offset ; - size = it->second.size ; - it->second.ts = now ; - -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::getMissingChunk(): re-asking for chunk that wasn't received: " << offset << " + " << size << std::endl; -#endif - return true ; - } - - // 1 - is there an ongoing 1MB chunk for which we need to take a new slice? - // - uint32_t& chunks_for_this_peer(mChunksPerPeer[peer_id].cnt) ; - - if(chunks_for_this_peer >= MAX_FTCHUNKS_PER_PEER) - { -#ifdef FILE_DEBUG - std::cerr << "ffc::getMissingChunk() too many chunks for peer " << peer_id << " for hash " << hash << ". Count = " << chunks_for_this_peer << std::endl ; -#endif - return false ; - } - - /* else allocate a new chunk */ - - ftChunk chunk ; - - if(!chunkMap.getDataChunk(peer_id,size_hint,chunk,source_chunk_map_needed)) - { - // No chunks are available. We brutally re-ask an ongoing chunk to another peer. - - if(chunkMap.reAskPendingChunk(peer_id,size_hint,offset,size)) - return true ; - - return false ; - } - -#ifdef FILE_DEBUG - std::cerr << "ffc::getMissingChunk() Retrieved new chunk: " << chunk << std::endl ; -#endif - - chunk.ref_cnt = new int ; - *chunk.ref_cnt = 1 ; - mChunks[chunk.offset] = chunk ; - - offset = chunk.offset ; - // cppcheck-suppress unreadVariable - size = chunk.size ; - - ++chunks_for_this_peer ; // increase number of chunks for this peer. - - return true; /* cos more data to get */ -} - -void ftFileCreator::getChunkMap(FileChunksInfo& info) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - chunkMap.getChunksInfo(info) ; - - // add info pending requests, handled by ftFileCreator - // - info.pending_slices.clear(); - - for(std::map::iterator it = mChunks.begin();it!=mChunks.end();++it) - { - int n = it->second.id / info.chunk_size ; - - FileChunksInfo::SliceInfo si ; - si.start = it->second.offset - n*info.chunk_size ; - si.size = it->second.size ; - si.peer_id = it->second.peer_id ; - - info.pending_slices[n].push_back(si) ; - } -} - -bool ftFileCreator::locked_printChunkMap() -{ -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::locked_printChunkMap()"; - std::cerr << " this: " << this; - std::cerr << std::endl; -#endif - - /* check start point */ - std::cerr << "\tOutstanding Chunks:"; - std::cerr << std::endl; - - std::map::iterator it; - - for(it = mChunks.begin(); it != mChunks.end(); ++it) - std::cerr << " " << it->second << std::endl ; - - std::cerr << "Active chunks per peer:" << std::endl ; - for(std::map::const_iterator it(mChunksPerPeer.begin());it!=mChunksPerPeer.end();++it) - std::cerr << " " << it->first << "\t: " << it->second.cnt << std::endl; - - return true; -} - -void ftFileCreator::setAvailabilityMap(const CompressedChunkMap& cmap) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - chunkMap.setAvailabilityMap(cmap) ; -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator: setting chunkmap for hash " << hash << ": " ; - - for(uint32_t i=0;iis_full ; -} - -void ftFileCreator::setSourceMap(const RsPeerId& peer_id,const CompressedChunkMap& compressed_map) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator:: Received source map for hash " << hash << " for source peer " << peer_id << std::endl; -#endif - // At this point, we should cancel all file chunks that are asked to the - // peer and which this peer actually doesn't possesses. Otherwise, the transfer may get stuck. - // This should be done by: - // - first setting the peer availability map - // - then asking the chunkmap which chunks are being downloaded, but actually shouldn't - // - cancelling them in the ftFileCreator, so that they can be re-asked later to another peer. - // - chunkMap.setPeerAvailabilityMap(peer_id,compressed_map) ; -} - -bool ftFileCreator::finished() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - return chunkMap.isComplete() ; -} - -bool ftFileCreator::hashReceivedData(RsFileHash& hash) -{ -#ifdef FILE_DEBUG - std::cerr << "file creator asked for hashing received data " << file_name << std::endl; -#endif - - // csoler: No mutex here please ! - // - // This is a bit dangerous, but otherwise we might stuck the GUI for a - // long time. Therefore, we must pay attention not to call this function - // at a time file_name nor hash can be modified, which is easy. - // - if(!finished()) - { - std::cerr << "Transfer not finished !! This should not happen" << std::endl; - return false ; - } - - uint64_t tmpsize ; - return RsDirUtil::getFileHash(file_name,hash,tmpsize) ; -} - -void ftFileCreator::forceCheck() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - chunkMap.forceCheck(); -} - -void ftFileCreator::getSourcesList(uint32_t chunk_num,std::vector& sources) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - chunkMap.getSourcesList(chunk_num,sources) ; -} - -void ftFileCreator::getChunksToCheck(std::vector& chunks_to_ask) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - chunkMap.getChunksToCheck(chunks_to_ask) ; -} - -bool ftFileCreator::verifyChunk(uint32_t chunk_number,const Sha1CheckSum& sum) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - if(!locked_initializeFileAttrs() ) - return false ; - - static const uint32_t chunk_size = ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE ; - unsigned char *buff = new unsigned char[chunk_size] ; - uint32_t len ; - - if(fseeko64(fd,(uint64_t)chunk_number * (uint64_t)chunk_size,SEEK_SET)==0 && (len = fread(buff,1,chunk_size,fd)) > 0) - { - Sha1CheckSum comp = RsDirUtil::sha1sum(buff,len) ; - - if(sum == comp) - chunkMap.setChunkCheckingResult(chunk_number,true) ; - else - { - std::cerr << "Sum mismatch for chunk " << chunk_number << std::endl; - std::cerr << " Computed hash = " << comp.toStdString() << std::endl; - std::cerr << " Reference hash = " << sum.toStdString() << std::endl; - - chunkMap.setChunkCheckingResult(chunk_number,false) ; - } - } - else - { - printf("Chunk verification: cannot fseek!\n") ; - chunkMap.setChunkCheckingResult(chunk_number,false) ; - } - - delete[] buff ; - return true ; -} - - - diff --git a/libretroshare/src/ft/ftfilecreator.h b/libretroshare/src/ft/ftfilecreator.h deleted file mode 100644 index 01a990414..000000000 --- a/libretroshare/src/ft/ftfilecreator.h +++ /dev/null @@ -1,151 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftfilecreator.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef FT_FILE_CREATOR_HEADER -#define FT_FILE_CREATOR_HEADER - -/* - * ftFileCreator - * - * TODO: Serialiser Load / Save. - * - */ -#include "ftfileprovider.h" -#include "ftchunkmap.h" -#include - -class ZeroInitCounter -{ - public: - ZeroInitCounter(): cnt(0) {} - uint32_t cnt ; -}; - -class ftFileCreator: public ftFileProvider -{ - public: - - ftFileCreator(const std::string& savepath, uint64_t size, const RsFileHash& hash,bool assume_availability); - - ~ftFileCreator(); - - /* overloaded from FileProvider */ - virtual bool getFileData(const RsPeerId& peer_id,uint64_t offset, uint32_t &chunk_size, void *data, bool allow_unverified = false); - bool finished() ; - uint64_t getRecvd(); - - /// (temporarily) close the file, to save file descriptors. - void closeFile() ; - - void getChunkMap(FileChunksInfo& info) ; - - void setChunkStrategy(FileChunksInfo::ChunkStrategy s) ; - FileChunksInfo::ChunkStrategy getChunkStrategy() ; - - // Computes a sha1sum of the partial file, to check that the data is overall consistent. - // This function is not mutexed. This is a bit dangerous, but otherwise we might stuck the GUI for a - // long time. Therefore, we must pay attention not to call this function - // at a time file_name nor hash can be modified, which is quite easy. - - bool hashReceivedData(RsFileHash& hash) ; - - // Sets all chunks to checking state - // - void forceCheck() ; - - bool verifyChunk(uint32_t, const Sha1CheckSum&) ; - - // Looks into the chunkmap for downloaded chunks that have not yet been certified. - // For each of them, returns the chunk number and a source peer to ask the CRC to. - // - void getChunksToCheck(std::vector& chunks_to_ask) ; - - /* - * creation functions for FileCreator - */ - - // Gets a new variable-sized chunk of size "size_hint" from the given peer id. The returned size, "size" is - // at most equal to size_hint. chunk_map_needed is set if - // - no chunkmap info is available. In such a case, the chunk info is irrelevant and false is returned. - // - the chunk info is too old. In tis case, true is returned, and the chunks info can be used. - // - bool getMissingChunk(const RsPeerId& peer_id,uint32_t size_hint,uint64_t& offset, uint32_t& size,bool& is_chunk_map_too_old); - - // Takes care of purging any inactive chunks. This should be called regularly, because some peers may disconnect - // and let inactive chunks not finished. - // - void removeInactiveChunks() ; - - // removes the designated file source from the chunkmap. - void removeFileSource(const RsPeerId& peer_id) ; - - // Get all available sources for this chunk - // - void getSourcesList(uint32_t chunk_number,std::vector& sources) ; - - // Returns resets the time stamp of the last data receive. - rstime_t lastRecvTimeStamp() ; - rstime_t creationTimeStamp() ; - - // actually store data in the file, and update chunks info - // - bool addFileData(uint64_t offset, uint32_t chunk_size, void *data); - - // Load/save the availability map for the file being downloaded, in a compact/compressed form. - // This is used for - // - loading and saving info about the current transfers - // - getting info about current chunks for the GUI - // - sending availability info to the peers for which we also are a source - // - virtual void getAvailabilityMap(CompressedChunkMap& cmap) ; - void setAvailabilityMap(const CompressedChunkMap& cmap) ; - - // This is called when receiving the availability map from a source peer, for the file being handled. - // - void setSourceMap(const RsPeerId& peer_id,const CompressedChunkMap& map) ; - - // Returns true id the given file source is complete. - // - bool sourceIsComplete(const RsPeerId& peer_id) ; - - protected: - - virtual int locked_initializeFileAttrs(); - - private: - - bool locked_printChunkMap(); - int locked_notifyReceived(uint64_t offset, uint32_t chunk_size); - /* - * structure to track missing chunks - */ - - std::map mChunks; - std::map mChunksPerPeer ; - - ChunkMap chunkMap ; - - rstime_t _last_recv_time_t ; /// last time stamp when data was received. Used for queue control. - rstime_t _creation_time ; /// time at which the file creator was created. Used to spot long-inactive transfers. -}; - -#endif // FT_FILE_CREATOR_HEADER diff --git a/libretroshare/src/ft/ftfileprovider.cc b/libretroshare/src/ft/ftfileprovider.cc deleted file mode 100644 index 0660a9bca..000000000 --- a/libretroshare/src/ft/ftfileprovider.cc +++ /dev/null @@ -1,357 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftfileprovider.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifdef WINDOWS_SYS -#include "util/rswin.h" -#endif // WINDOWS_SYS - -#include "ftfileprovider.h" -#include "ftchunkmap.h" - -#include "util/rsdir.h" -#include -#include -#include "util/rstime.h" - -/******** -* #define DEBUG_FT_FILE_PROVIDER 1 -* #define DEBUG_TRANSFERS 1 // TO GET TIMESTAMPS of DATA READING -********/ - -#ifdef DEBUG_TRANSFERS - #include "util/rsprint.h" - #include -#endif - -static const rstime_t UPLOAD_CHUNK_MAPS_TIME = 20 ; // time to ask for a new chunkmap from uploaders in seconds. - -ftFileProvider::ftFileProvider(const std::string& path, uint64_t size, const RsFileHash& hash) - : mSize(size), hash(hash), file_name(path), fd(NULL), ftcMutex("ftFileProvider") -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_FT_FILE_PROVIDER - std::cout << "Creating file provider for " << hash << std::endl ; -#endif -} - -ftFileProvider::~ftFileProvider() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ -#ifdef DEBUG_FT_FILE_PROVIDER - std::cout << "ftFileProvider::~ftFileProvider(): Destroying file provider for " << hash << std::endl ; -#endif - if (fd!=NULL) { - fclose(fd); - fd = NULL ; -#ifdef DEBUG_FT_FILE_PROVIDER - std::cout << "ftFileProvider::~ftFileProvider(): closed file: " << hash << std::endl ; -#endif - } -} - -bool ftFileProvider::fileOk() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - return (fd != NULL); -} - -RsFileHash ftFileProvider::getHash() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - return hash; -} - -uint64_t ftFileProvider::getFileSize() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - return mSize; -} - -bool ftFileProvider::FileDetails(FileInfo &info) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - info.hash = hash; - info.size = mSize; - info.path = file_name; - info.fname = RsDirUtil::getTopDir(file_name); - - info.transfered = 0 ; // unused - info.lastTS = 0; - info.downloadStatus = FT_STATE_DOWNLOADING ; - - info.peers.clear() ; - float total_transfer_rate = 0.0f ; - - for(std::map::const_iterator it(uploading_peers.begin());it!=uploading_peers.end();++it) - { - TransferInfo inf ; - inf.peerId = it->first ; - inf.status = FT_STATE_DOWNLOADING ; - inf.name = info.fname ; - inf.transfered = it->second.req_loc ; - - inf.tfRate = it->second.transfer_rate/1024.0 ; - total_transfer_rate += it->second.transfer_rate ; - info.lastTS = std::max(info.lastTS,it->second.lastTS); - - info.peers.push_back(inf) ; - } - info.tfRate = total_transfer_rate/1024.0 ; - - /* Use req_loc / req_size to estimate data rate */ - - return true; -} - -bool ftFileProvider::purgeOldPeers(rstime_t now,uint32_t max_duration) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::purgeOldPeers(): " << (void*)this << ": examining peers." << std::endl ; -#endif - bool ret = true ; - for(std::map::iterator it(uploading_peers.begin());it!=uploading_peers.end();) - if( (*it).second.lastTS+max_duration < (uint32_t)now) - { -#ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::purgeOldPeers(): " << (void*)this << ": peer " << it->first << " is too old. Removing." << std::endl ; -#endif - std::map::iterator tmp = it ; - ++tmp ; - uploading_peers.erase(it) ; - it=tmp ; - } - else - { -#ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::purgeOldPeers(): " << (void*)this << ": peer " << it->first << " will be kept." << std::endl ; -#endif - ret = false ; - ++it ; - } - return ret ; -} - -void ftFileProvider::getAvailabilityMap(CompressedChunkMap& cmap) -{ - // We are here because the file we deal with is complete. So we return a plain map. - // - ChunkMap::buildPlainMap(mSize,cmap) ; -} - - -bool ftFileProvider::getFileData(const RsPeerId& peer_id,uint64_t offset, uint32_t &chunk_size, void *data, bool /*allow_unverified*/) -{ - /* dodgey checking outside of mutex... - * much check again inside FileAttrs(). - */ - if (fd == NULL) - if (!initializeFileAttrs()) - return false; - - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - /* - * FIXME: Warning of comparison between unsigned and signed int? - */ - - if(offset >= mSize) - { - std::cerr << "ftFileProvider::getFileData(): request (" << offset << ") exceeds file size (" << mSize << "! " << std::endl; - return false ; - } - - uint32_t data_size = chunk_size; - uint64_t base_loc = offset; - - if (base_loc + data_size > mSize) - { - data_size = mSize - base_loc; - chunk_size = mSize - base_loc; - std::cerr <<"Chunk Size greater than total file size, adjusting chunk size " << data_size << std::endl; - } - - if(data_size > 0 && data != NULL) - { - /* - * seek for base_loc - */ - if(fseeko64(fd, base_loc, SEEK_SET) == -1) - { - #ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::getFileData() Failed to seek. Data_size=" << data_size << ", base_loc=" << base_loc << " !" << std::endl; - #endif - //free(data); No!! It's already freed upwards in ftDataMultiplex::locked_handleServerRequest() - return 0; - } - - // Data space allocated by caller. - //void *data = malloc(chunk_size); - - /* - * read the data - */ - - if (1 != fread(data, data_size, 1, fd)) - { - #ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::getFileData() Failed to get data. Data_size=" << data_size << ", base_loc=" << base_loc << " !" << std::endl; - #endif - //free(data); No!! It's already freed upwards in ftDataMultiplex::locked_handleServerRequest() - return 0; - } - - /* - * Update status of ftFileStatus to reflect last usage (for GUI display) - * We need to store. - * (a) Id, - * (b) Offset, - * (c) Size, - * (d) timestamp - */ - - // This creates the peer info, and updates it. - // - rstime_t now = time(NULL) ; - uploading_peers[peer_id].updateStatus(offset,data_size,now) ; - -#ifdef DEBUG_TRANSFERS - std::cerr << "ftFileProvider::getFileData() "; - std::cerr << " at " << RsUtil::AccurateTimeString(); - std::cerr << " hash: " << hash; - std::cerr << " for peerId: " << peer_id; - std::cerr << " offset: " << offset; - std::cerr << " chunkSize: " << chunk_size; - std::cerr << std::endl; -#endif - - } - else - { - std::cerr << "No data to read, or NULL buffer used" << std::endl; - return 0; - } - return 1; -} - -void ftFileProvider::PeerUploadInfo::updateStatus(uint64_t offset,uint32_t data_size,rstime_t now) -{ - lastTS = now ; - long int diff = (long int)now - (long int)lastTS_t ; // in bytes/s. Average over multiple samples - -#ifdef DEBUG_FT_FILE_PROVIDER - std::cout << "diff = " << diff << std::endl ; -#endif - - if(diff > 3) - { - transfer_rate = total_size / (float)diff ; -#ifdef DEBUG_FT_FILE_PROVIDER - std::cout << "updated TR = " << transfer_rate << ", total_size=" << total_size << std::endl ; -#endif - lastTS_t = now ; - total_size = 0 ; - } - - req_loc = offset; - req_size = data_size; - total_size += req_size ; -} - -void ftFileProvider::setClientMap(const RsPeerId& peer_id,const CompressedChunkMap& cmap) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - // Create by default. - uploading_peers[peer_id].client_chunk_map = cmap ; - uploading_peers[peer_id].client_chunk_map_stamp = time(NULL) ; -} - -void ftFileProvider::getClientMap(const RsPeerId& peer_id,CompressedChunkMap& cmap,bool& map_is_too_old) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - PeerUploadInfo& pui(uploading_peers[peer_id]) ; - - rstime_t now = time(NULL) ; - - if(now - pui.client_chunk_map_stamp > UPLOAD_CHUNK_MAPS_TIME) - { - map_is_too_old = true ; - pui.client_chunk_map_stamp = now ; // to avoid re-asking before the TTL - } - else - map_is_too_old = false ; - - cmap = pui.client_chunk_map; -} - -int ftFileProvider::initializeFileAttrs() -{ -#ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::initializeFileAttrs() Filename: " << file_name << std::endl; -#endif - - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - if (fd) - return 1; - - /* - * check if the file exists - */ - - { -#ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::initializeFileAttrs() trying (r+b) " << std::endl; -#endif - } - - /* - * attempt to open file - */ - - fd = RsDirUtil::rs_fopen(file_name.c_str(), "r+b"); - if (!fd) - { - std::cerr << "ftFileProvider::initializeFileAttrs() Failed to open (r+b): "; - std::cerr << file_name << std::endl; - - /* try opening read only */ - fd = RsDirUtil::rs_fopen(file_name.c_str(), "rb"); - if (!fd) - { - std::cerr << "ftFileProvider::initializeFileAttrs() Failed to open (rb): "; - std::cerr << file_name << std::endl; - - /* try opening read only */ - return 0; - } - } -#ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider:: openned file " << file_name << std::endl ; -#endif - - return 1; -} - - diff --git a/libretroshare/src/ft/ftfileprovider.h b/libretroshare/src/ft/ftfileprovider.h deleted file mode 100644 index 4ed0dbec9..000000000 --- a/libretroshare/src/ft/ftfileprovider.h +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftfileprovider.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef FT_FILE_PROVIDER_HEADER -#define FT_FILE_PROVIDER_HEADER - -/* - * ftFileProvider. - * - */ -#include -#include -#include "util/rsthreads.h" -#include "retroshare/rsfiles.h" - -class ftFileProvider -{ - public: - ftFileProvider(const std::string& path, uint64_t size, const RsFileHash& hash); - virtual ~ftFileProvider(); - - /** - * read a block of data from the file - * @param peer_id for the uploading stats: to which peer the data will be send - * @param offset begin of the requested data range - * @param chunk_size how many bytes to read. Will be set to the number of valid bytes in data on return. - * @param data pointer to a buffer of size chunk_size. Contains the data on success. - * @param allow_unverified for ftFileCreator: set to true to return data from unverified chunks. Use it if you want data asap. - * @return true if data was read - */ - virtual bool getFileData(const RsPeerId& peer_id,uint64_t offset, uint32_t &chunk_size, void *data, bool allow_unverified = false); - virtual bool FileDetails(FileInfo &info); - RsFileHash getHash(); - uint64_t getFileSize(); - bool fileOk(); - - // Provides a client for the map of chunks actually present in the file. If the provider is also - // a file creator, because the file is actually being downloaded, then the map may be partially complete. - // Otherwize, a plain map is returned. - // - virtual void getAvailabilityMap(CompressedChunkMap& cmap) ; - - // a ftFileProvider feeds a distant peer. To display what the peers already has, we need to store/read this info. - void getClientMap(const RsPeerId& peer_id,CompressedChunkMap& cmap,bool& map_is_too_old) ; - void setClientMap(const RsPeerId& peer_id,const CompressedChunkMap& cmap) ; - - // Removes inactive peers from the client list. Returns true if all peers have been removed. - // - bool purgeOldPeers(rstime_t now,uint32_t max_duration) ; - - const RsFileHash& fileHash() const { return hash ; } - const std::string& fileName() const { return file_name ; } - uint64_t fileSize() const { return mSize ; } - protected: - virtual int initializeFileAttrs(); /* does for both */ - - uint64_t mSize; - RsFileHash hash; - std::string file_name; - FILE *fd; - - /* - * Structure to gather statistics FIXME: lastRequestor - figure out a - * way to get last requestor (peerID) - */ - class PeerUploadInfo - { - public: - PeerUploadInfo() - : req_loc(0),req_size(1), lastTS_t(0), lastTS(0),transfer_rate(0), total_size(0), client_chunk_map_stamp(0) {} - - void updateStatus(uint64_t offset,uint32_t data_size,rstime_t now) ; - - uint64_t req_loc; - uint32_t req_size; - rstime_t lastTS_t; // used for estimating transfer rate. - rstime_t lastTS; // last update time (for purging) - - // these two are used for speed estimation - float transfer_rate ; - uint32_t total_size ; - - // Info about what the downloading peer already has - CompressedChunkMap client_chunk_map ; - rstime_t client_chunk_map_stamp ; - }; - - // Contains statistics (speed, peer name, etc.) of all uploading peers for that file. - // - std::map uploading_peers ; - - /* - * Mutex Required for stuff below - */ - RsMutex ftcMutex; -}; - - -#endif // FT_FILE_PROVIDER_HEADER diff --git a/libretroshare/src/ft/ftfilesearch.cc b/libretroshare/src/ft/ftfilesearch.cc deleted file mode 100644 index c9571f9a8..000000000 --- a/libretroshare/src/ft/ftfilesearch.cc +++ /dev/null @@ -1,177 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftfilesearch.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "ft/ftfilesearch.h" - -const uint32_t MAX_SEARCHS = 24; /* lower 24 bits of hint */ - -//#define DEBUG_SEARCH 1 - -ftFileSearch::ftFileSearch() - :mSearchs(MAX_SEARCHS) -{ - uint32_t i; - for(i = 0; i < MAX_SEARCHS; i++) - { - mSearchs[i] = NULL; - } -} - -bool ftFileSearch::addSearchMode(ftSearch *search, FileSearchFlags hintflags) -{ - hintflags &= FileSearchFlags(0x000000ff); - -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::addSearchMode() : " << hintflags; - std::cerr << std::endl; -#endif - - uint32_t i; - for (i = 0; i < MAX_SEARCHS; i++) - { - uint32_t hints = hintflags.toUInt32() >> i; - if (hints & 0x0001) - { - /* has the flag */ - mSearchs[i] = search; - -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::addSearchMode() to slot "; - std::cerr << i; - std::cerr << std::endl; -#endif - - return true; - } - } - -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::addSearchMode() Failed"; - std::cerr << std::endl; -#endif - - return false; -} - -bool ftFileSearch::search(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const -{ - uint32_t hints, i; - -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search(" << hash ; - std::cerr << ", " << hintflags << ");"; - std::cerr << std::endl; -#endif - - for (i = 0; i < MAX_SEARCHS; i++) - { - hints = hintflags.toUInt32() >> i; - if (hints & 0x0001) - { - /* has the flag */ - ftSearch *search = mSearchs[i]; - if (search) - { -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SLOT: "; - std::cerr << i; - std::cerr << std::endl; -#endif - if (search->search(hash, hintflags, info)) - { -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SLOT: "; - std::cerr << i << " success!"; - std::cerr << std::endl; -#endif - return true; - } - else - { -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SLOT: "; - std::cerr << i << " no luck"; - std::cerr << std::endl; -#endif - } - } - } - } - - /* if we haven't found it by now! - check if SPEC_ONLY flag is set */ - if (hintflags & RS_FILE_HINTS_SPEC_ONLY) - { -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SPEC_ONLY: Failed"; - std::cerr << std::endl; -#endif - return false; - } - -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() Searching Others (no SPEC ONLY):"; - std::cerr << std::endl; -#endif - - /* if we don't have the SPEC_ONLY flag, - * we check through all the others - */ - for (i = 0; i < MAX_SEARCHS; i++) - { - hints = hintflags.toUInt32() >> i; - if (hints & 0x0001) - { - continue; - } - - /* has the flag */ - ftSearch *search = mSearchs[i]; - if (search) - { - -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SLOT: " << i; - std::cerr << std::endl; -#endif - if (search->search(hash, hintflags, info)) - { -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SLOT: "; - std::cerr << i << " success!"; - std::cerr << std::endl; -#endif - return true; - } - else - { -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SLOT: "; - std::cerr << i << " no luck"; - std::cerr << std::endl; -#endif - } - - } - } - /* found nothing */ - return false; -} - diff --git a/libretroshare/src/ft/ftfilesearch.h b/libretroshare/src/ft/ftfilesearch.h deleted file mode 100644 index 46c11d33c..000000000 --- a/libretroshare/src/ft/ftfilesearch.h +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftfilesearch.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef FT_FILE_SEARCH_HEADER -#define FT_FILE_SEARCH_HEADER - -/* - * ftFileSearch - * - * This is implements an array of ftSearch Interfaces. - * - */ - -#include - -#include "ft/ftsearch.h" - -class ftFileSearch: public ftSearch -{ - - public: - - ftFileSearch(); - -bool addSearchMode(ftSearch *search, FileSearchFlags hintflags); -virtual bool search(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const; - - private: - - // should have a mutex to protect vector.... - // but not really necessary as it is const most of the time. - - std::vector mSearchs; -}; - - -#endif diff --git a/libretroshare/src/ft/ftsearch.h b/libretroshare/src/ft/ftsearch.h deleted file mode 100644 index 7906d275f..000000000 --- a/libretroshare/src/ft/ftsearch.h +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftsearch.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef FT_SEARCH_HEADER -#define FT_SEARCH_HEADER - -/* - * ftSearch - * - * This is a generic search interface - used by ft* to find files. - * The derived class will search for Caches/Local/ExtraList/Remote entries. - * - */ - -#include "retroshare/rsfiles.h" // includes retroshare/rstypes.h too! - -class ftSearch -{ - - public: - ftSearch() { return; } - virtual ~ftSearch() { return; } - virtual bool search(const RsFileHash & /*hash*/, FileSearchFlags /*hintflags*/,const RsPeerId& /*peer_id*/, FileInfo & /*info*/) const - { - std::cerr << "Non overloaded search method called!!!" << std::endl; - return false; - } - virtual bool search(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const = 0; - -}; - -#endif diff --git a/libretroshare/src/ft/ftserver.cc b/libretroshare/src/ft/ftserver.cc deleted file mode 100644 index 07a400acf..000000000 --- a/libretroshare/src/ft/ftserver.cc +++ /dev/null @@ -1,2360 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftserver.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include -#include -#include - -#include "crypto/chacha20.h" -//const int ftserverzone = 29539; - -#include "file_sharing/p3filelists.h" -#include "ft/ftcontroller.h" -#include "ft/ftdatamultiplex.h" -//#include "ft/ftdwlqueue.h" -#include "ft/ftextralist.h" -#include "ft/ftfileprovider.h" -#include "ft/ftfilesearch.h" -#include "ft/ftserver.h" -#include "ft/ftturtlefiletransferitem.h" - -#include "pqi/p3linkmgr.h" -#include "pqi/p3notify.h" -#include "pqi/pqi.h" - -#include "retroshare/rstypes.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsinit.h" -#include "util/cxx17retrocompat.h" -#include "rsitems/rsfiletransferitems.h" -#include "rsitems/rsserviceids.h" -#include "util/rsmemory.h" -#include "rsserver/p3face.h" -#include "turtle/p3turtle.h" -#include "util/rsurl.h" -#include "util/rsdebug.h" -#include "util/rsdir.h" -#include "util/rsprint.h" -#include "util/rstime.h" - -#ifdef RS_DEEP_FILES_INDEX -# include "deep_search/filesindex.hpp" -#endif // def RS_DEEP_FILES_INDEX - -/*** - * #define SERVER_DEBUG 1 - * #define SERVER_DEBUG_CACHE 1 - ***/ - -#define FTSERVER_DEBUG() std::cerr << time(NULL) << " : FILE_SERVER : " << __FUNCTION__ << " : " -#define FTSERVER_ERROR() std::cerr << "(EE) FILE_SERVER ERROR : " - -/*static*/ const RsFilesErrorCategory RsFilesErrorCategory::instance; - -/*static*/ const std::string RsFiles::DEFAULT_FILES_BASE_URL = - "retroshare:///files"; -/*static*/ const std::string RsFiles::FILES_URL_COUNT_FIELD = "filesCount"; -/*static*/ const std::string RsFiles::FILES_URL_DATA_FIELD = "filesData"; -// Use a 5 character word so there is no mistake it isn't base64 as 5%4=1 -/*static*/ const std::string RsFiles::FILES_URL_FAGMENT_FORWARD = "fragm"; -/*static*/ const std::string RsFiles::FILES_URL_NAME_FIELD = "filesName"; -/*static*/ const std::string RsFiles::FILES_URL_SIZE_FIELD = "filesSize"; - - -static const rstime_t FILE_TRANSFER_LOW_PRIORITY_TASKS_PERIOD = 5 ; // low priority tasks handling every 5 seconds -static const rstime_t FILE_TRANSFER_MAX_DELAY_BEFORE_DROP_USAGE_RECORD = 10 ; // keep usage records for 10 secs at most. - -#ifdef RS_DEEP_FILES_INDEX -TurtleFileInfoV2::TurtleFileInfoV2(const DeepFilesSearchResult& dRes) : - fHash(dRes.mFileHash), fWeight(static_cast(dRes.mWeight)), - fSnippet(dRes.mSnippet) -{ - FileInfo fInfo; - rsFiles->FileDetails(fHash, RS_FILE_HINTS_LOCAL, fInfo); - - fSize = fInfo.size; - fName = fInfo.fname; -} -#endif // def RS_DEEP_FILES_INDEX - -TurtleFileInfoV2::~TurtleFileInfoV2() = default; - -/* Setup */ -ftServer::ftServer(p3PeerMgr *pm, p3ServiceControl *sc): - p3Service(), - // should be FT, but this is for backward compatibility - RsServiceSerializer(RS_SERVICE_TYPE_TURTLE), - mPeerMgr(pm), mServiceCtrl(sc), - mFileDatabase(NULL), - mFtController(NULL), mFtExtra(NULL), - mFtDataplex(NULL), mFtSearch(NULL), srvMutex("ftServer"), - mSearchCallbacksMapMutex("ftServer callbacks map") -{ - addSerialType(new RsFileTransferSerialiser()) ; -} - -const std::string FILE_TRANSFER_APP_NAME = "ft"; -const uint16_t FILE_TRANSFER_APP_MAJOR_VERSION = 1; -const uint16_t FILE_TRANSFER_APP_MINOR_VERSION = 0; -const uint16_t FILE_TRANSFER_MIN_MAJOR_VERSION = 1; -const uint16_t FILE_TRANSFER_MIN_MINOR_VERSION = 0; - -RsServiceInfo ftServer::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_FILE_TRANSFER, - FILE_TRANSFER_APP_NAME, - FILE_TRANSFER_APP_MAJOR_VERSION, - FILE_TRANSFER_APP_MINOR_VERSION, - FILE_TRANSFER_MIN_MAJOR_VERSION, - FILE_TRANSFER_MIN_MINOR_VERSION); -} - - -void ftServer::setConfigDirectory(std::string path) -{ - mConfigPath = path; - - /* Must update the sub classes ... if they exist - * TODO. - */ - - std::string basecachedir = mConfigPath + "/cache"; - std::string localcachedir = mConfigPath + "/cache/local"; - std::string remotecachedir = mConfigPath + "/cache/remote"; - - RsDirUtil::checkCreateDirectory(basecachedir) ; - RsDirUtil::checkCreateDirectory(localcachedir) ; - RsDirUtil::checkCreateDirectory(remotecachedir) ; -} - -/* Control Interface */ - -/* add Config Items (Extra, Controller) */ -void ftServer::addConfigComponents(p3ConfigMgr */*mgr*/) -{ - /* NOT SURE ABOUT THIS ONE */ -} - -const RsPeerId& ftServer::OwnId() -{ - static RsPeerId null_id ; - - if (mServiceCtrl) - return mServiceCtrl->getOwnId(); - else - return null_id ; -} - -/* Final Setup (once everything is assigned) */ -void ftServer::SetupFtServer() -{ - - /* setup FiStore/Monitor */ - //std::string localcachedir = mConfigPath + "/cache/local"; - //std::string remotecachedir = mConfigPath + "/cache/remote"; - RsPeerId ownId = mServiceCtrl->getOwnId(); - - /* search/extras List */ - mFtExtra = new ftExtraList(); - mFtSearch = new ftFileSearch(); - - /* Transport */ - mFtDataplex = new ftDataMultiplex(ownId, this, mFtSearch); - - /* make Controller */ - mFtController = new ftController(mFtDataplex, mServiceCtrl, getServiceInfo().mServiceType); - mFtController -> setFtSearchNExtra(mFtSearch, mFtExtra); - - std::string emergencySaveDir = RsAccounts::AccountDirectory(); - std::string emergencyPartialsDir = RsAccounts::AccountDirectory(); - - if (emergencySaveDir != "") - { - emergencySaveDir += "/"; - emergencyPartialsDir += "/"; - } - emergencySaveDir += "Downloads"; - emergencyPartialsDir += "Partials"; - - mFtController->setDownloadDirectory(emergencySaveDir); - mFtController->setPartialsDirectory(emergencyPartialsDir); - - /* complete search setup */ - mFtSearch->addSearchMode(mFtExtra, RS_FILE_HINTS_EXTRA); - - mServiceCtrl->registerServiceMonitor(mFtController, getServiceInfo().mServiceType); - - return; -} - -void ftServer::connectToFileDatabase(p3FileDatabase *fdb) -{ - mFileDatabase = fdb ; - - mFtSearch->addSearchMode(fdb, RS_FILE_HINTS_LOCAL); // due to a bug in addSearchModule, modules can only be added one by one. Using | between flags wont work. - mFtSearch->addSearchMode(fdb, RS_FILE_HINTS_REMOTE); - - mFileDatabase->setExtraList(mFtExtra); -} -void ftServer::connectToTurtleRouter(p3turtle *fts) -{ - mTurtleRouter = fts ; - - mFtController->setTurtleRouter(fts) ; - mFtController->setFtServer(this) ; - - mTurtleRouter->registerTunnelService(this) ; -} - -void ftServer::StartupThreads() -{ - /* start up order - important for dependencies */ - - /* self contained threads */ - /* startup ExtraList Thread */ - mFtExtra->start("ft extra lst"); - - /* startup Monitor Thread */ - /* startup the FileMonitor (after cache load) */ - /* start it up */ - mFileDatabase->startThreads(); - - /* Controller thread */ - mFtController->start("ft ctrl"); - - /* Dataplex */ - mFtDataplex->start("ft dataplex"); -} - -void ftServer::StopThreads() -{ - /* stop Dataplex */ - mFtDataplex->fullstop(); - - /* stop Controller thread */ - mFtController->fullstop(); - - /* self contained threads */ - /* stop ExtraList Thread */ - mFtExtra->fullstop(); - - delete (mFtDataplex); - mFtDataplex = nullptr; - - delete (mFtController); - mFtController = nullptr; - - delete (mFtExtra); - mFtExtra = nullptr; - - /* stop Monitor Thread */ - mFileDatabase->stopThreads(); - delete mFileDatabase; - mFileDatabase = nullptr; -} - -/***************************************************************/ -/********************** RsFiles Interface **********************/ -/***************************************************************/ - -/***************************************************************/ -/********************** Controller Access **********************/ -/***************************************************************/ - -bool ftServer::ResumeTransfers() -{ - mFtController->activate(); - - return true; -} - -bool ftServer::getFileData(const RsFileHash& hash, uint64_t offset, uint32_t& requested_size,uint8_t *data) -{ - return mFtDataplex->getFileData(hash, offset, requested_size,data); -} - -bool ftServer::alreadyHaveFile(const RsFileHash& hash, FileInfo &info) -{ - return mFileDatabase->search( - hash, RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL, info ); -} - -bool ftServer::FileRequest( - const std::string& fname, const RsFileHash& hash, uint64_t size, - const std::string& dest, TransferRequestFlags flags, - const std::list& srcIds ) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "Requesting " << fname << std::endl ; -#endif - - if(!mFtController->FileRequest(fname, hash, size, dest, flags, srcIds)) - return false ; - - return true ; -} - -std::error_condition ftServer::requestFiles( - const RsFileTree& collection, const std::string& destPath, - const std::vector& srcIds, FileRequestFlags flags ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto dirsCount = collection.mDirs.size(); - const auto filesCount = collection.mFiles.size(); - - Dbg2() << fname << " dirsCount: " << dirsCount - << " filesCount: " << filesCount << std::endl; - - if(!dirsCount) - { - RsErr() << fname << " Directories list empty in collection " - << std::endl; - return std::errc::not_a_directory; - } - - if(!filesCount) - { - RsErr() << fname << " Files list empty in collection " << std::endl; - return std::errc::invalid_argument; - } - - if(filesCount != collection.mTotalFiles) - { - RsErr() << fname << " Files count mismatch" << std::endl; - return std::errc::invalid_argument; - } - - std::string basePath = destPath.empty() ? getDownloadDirectory() : destPath; - // Track how many time a directory have been explored - std::vector dirsSeenCnt(dirsCount, 0); - // - using StackEntry = std::tuple; - std::deque dStack = { std::make_tuple(0, basePath) }; - - const auto exploreDir = [&](const StackEntry& se)-> std::error_condition - { - uint64_t dirHandle; std::string parentPath; - std::tie(dirHandle, parentPath) = se; - - const auto& dirData = collection.mDirs[dirHandle]; - auto& seenTimes = dirsSeenCnt[dirHandle]; - std::string dirPath = RsDirUtil::makePath(parentPath, dirData.name); - - /* This check is not perfect but is cheap and interrupt loop exploration - * before it becomes pathological */ - if(seenTimes++ > dirsCount) - { - RsErr() << fname << " loop detected! dir: " - << dirHandle << " \"" << dirPath - << "\" explored too many times" << std::endl; - return std::errc::too_many_symbolic_link_levels; - } - - for(auto fHandle: dirData.subfiles) - { - if(fHandle >= filesCount) return std::errc::argument_out_of_domain; - - const RsFileTree::FileData& fData = collection.mFiles[fHandle]; - - bool fr = - FileRequest( fData.name, fData.hash, fData.size, - dirPath, - TransferRequestFlags::fromEFT(flags), - std::list(srcIds.begin(), srcIds.end()) ); - - Dbg2() << fname << " requested: " << fr << " " - << fData.hash << " -> " << dirPath << std::endl; - } - - for(auto dHandle: dirData.subdirs) - dStack.push_back(std::make_tuple(dHandle, dirPath)); - - return std::error_condition(); - }; - - while(!dStack.empty()) - { - if(std::error_condition ec = exploreDir(dStack.front())) return ec; - dStack.pop_front(); - } - - return std::error_condition(); -} - -bool ftServer::activateTunnels(const RsFileHash& hash,uint32_t encryption_policy,TransferRequestFlags flags,bool onoff) -{ - RsFileHash hash_of_hash ; - - encryptHash(hash,hash_of_hash) ; - mEncryptedHashes.insert(std::make_pair(hash_of_hash,hash)) ; - - if(onoff) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "Activating tunnels for hash " << hash << std::endl; -#endif - if(flags & RS_FILE_REQ_ENCRYPTED) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " flags require end-to-end encryption. Requesting hash of hash " << hash_of_hash << std::endl; -#endif - mTurtleRouter->monitorTunnels(hash_of_hash,this,true) ; - } - if((flags & RS_FILE_REQ_UNENCRYPTED) && (encryption_policy != RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT)) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " flags require no end-to-end encryption. Requesting hash " << hash << std::endl; -#endif - mTurtleRouter->monitorTunnels(hash,this,true) ; - } - } - else - { - mTurtleRouter->stopMonitoringTunnels(hash_of_hash); - mTurtleRouter->stopMonitoringTunnels(hash); - } - return true ; -} - -bool ftServer::setDestinationDirectory(const RsFileHash& hash,const std::string& directory) -{ - return mFtController->setDestinationDirectory(hash,directory); -} -bool ftServer::setDestinationName(const RsFileHash& hash,const std::string& name) -{ - return mFtController->setDestinationName(hash,name); -} - -bool ftServer::setChunkStrategy(const RsFileHash& hash,FileChunksInfo::ChunkStrategy s) -{ - return mFtController->setChunkStrategy(hash,s); -} -void ftServer::setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy s) -{ - mFtController->setDefaultChunkStrategy(s) ; -} -FileChunksInfo::ChunkStrategy ftServer::defaultChunkStrategy() -{ - return mFtController->defaultChunkStrategy() ; -} - -uint32_t ftServer::freeDiskSpaceLimit()const -{ - return mFtController->freeDiskSpaceLimit() ; -} -void ftServer::setFreeDiskSpaceLimit(uint32_t s) -{ - mFtController->setFreeDiskSpaceLimit(s) ; -} - -void ftServer::setDefaultEncryptionPolicy(uint32_t s) -{ - mFtController->setDefaultEncryptionPolicy(s) ; -} -uint32_t ftServer::defaultEncryptionPolicy() -{ - return mFtController->defaultEncryptionPolicy() ; -} - -void ftServer::setMaxUploadSlotsPerFriend(uint32_t n) -{ - mFtController->setMaxUploadsPerFriend(n) ; -} -uint32_t ftServer::getMaxUploadSlotsPerFriend() -{ - return mFtController->getMaxUploadsPerFriend() ; -} - -void ftServer::setFilePermDirectDL(uint32_t perm) -{ - mFtController->setFilePermDirectDL(perm); -} -uint32_t ftServer::filePermDirectDL() -{ - return mFtController->filePermDirectDL() ; -} - -bool ftServer::FileCancel(const RsFileHash& hash) -{ - // Remove from both queue and ftController, by default. - // - mFtController->FileCancel(hash); - - return true ; -} - -bool ftServer::FileControl(const RsFileHash& hash, uint32_t flags) -{ - return mFtController->FileControl(hash, flags); -} - -bool ftServer::FileClearCompleted() -{ - return mFtController->FileClearCompleted(); -} -void ftServer::setQueueSize(uint32_t s) -{ - mFtController->setQueueSize(s) ; -} -uint32_t ftServer::getQueueSize() -{ - return mFtController->getQueueSize() ; -} -/* Control of Downloads Priority. */ -bool ftServer::changeQueuePosition(const RsFileHash& hash, QueueMove mv) -{ - mFtController->moveInQueue(hash,mv) ; - return true ; -} -bool ftServer::changeDownloadSpeed(const RsFileHash& hash, int speed) -{ - mFtController->setPriority(hash, (DwlSpeed)speed); - return true ; -} -bool ftServer::getDownloadSpeed(const RsFileHash& hash, int & speed) -{ - DwlSpeed _speed; - int ret = mFtController->getPriority(hash, _speed); - if (ret) - speed = _speed; - - return ret; -} -bool ftServer::clearDownload(const RsFileHash& /*hash*/) -{ - return true ; -} - -bool ftServer::FileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo& info) -{ - return mFtController->getFileDownloadChunksDetails(hash,info); -} - -void ftServer::requestDirUpdate(void *ref) -{ - mFileDatabase->requestDirUpdate(ref) ; -} - -/* Directory Handling */ -bool ftServer::setDownloadDirectory(const std::string& path) -{ - return mFtController->setDownloadDirectory(path); -} - -std::string ftServer::getDownloadDirectory() -{ - return mFtController->getDownloadDirectory(); -} - -bool ftServer::setPartialsDirectory(const std::string& path) -{ - return mFtController->setPartialsDirectory(path); -} - -std::string ftServer::getPartialsDirectory() -{ - return mFtController->getPartialsDirectory(); -} - -/***************************************************************/ -/************************* Other Access ************************/ -/***************************************************************/ - -bool ftServer::copyFile(const std::string& source, const std::string& dest) -{ - return RsDirUtil::copyFile(source, dest); -} - -void ftServer::FileDownloads(std::list &hashs) -{ - mFtController->FileDownloads(hashs); -} - -bool ftServer::FileUploadChunksDetails(const RsFileHash& hash,const RsPeerId& peer_id,CompressedChunkMap& cmap) -{ - return mFtDataplex->getClientChunkMap(hash,peer_id,cmap); -} - -bool ftServer::FileUploads(std::list &hashs) -{ - return mFtDataplex->FileUploads(hashs); -} - -bool ftServer::FileDetails(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) -{ - if (hintflags & RS_FILE_HINTS_DOWNLOAD) - if(mFtController->FileDetails(hash, info)) - return true ; - - if(hintflags & RS_FILE_HINTS_UPLOAD) - if(mFtDataplex->FileDetails(hash, hintflags, info)) - { - // We also check if the file is a DL as well. In such a case we use - // the DL as the file name, to replace the hash. If the file is a cache - // file, we skip the call to fileDetails() for efficiency reasons. - // - FileInfo info2 ; - if(mFtController->FileDetails(hash, info2)) - info.fname = info2.fname ; - - return true ; - } - - if(hintflags & ~(RS_FILE_HINTS_UPLOAD | RS_FILE_HINTS_DOWNLOAD)) - if(mFtSearch->search(hash, hintflags, info)) - return true ; - - return false; -} - -RsItem *ftServer::create_item(uint16_t service, uint8_t item_type) const -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "p3turtle: deserialising packet: " << std::endl ; -#endif - - RsServiceType serviceType = static_cast(service); - switch (serviceType) - { - /* This one is here for retro-compatibility as turtle routing and file - * trasfer services were just one service before turle service was - * generalized */ - case RsServiceType::TURTLE: break; - case RsServiceType::FILE_TRANSFER: break; - default: - RsErr() << __PRETTY_FUNCTION__ << " Wrong service type: " << service - << std::endl; - return nullptr; - } - - try - { - switch(item_type) - { - case RS_TURTLE_SUBTYPE_FILE_REQUEST : return new RsTurtleFileRequestItem(); - case RS_TURTLE_SUBTYPE_FILE_DATA : return new RsTurtleFileDataItem(); - case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST : return new RsTurtleFileMapRequestItem(); - case RS_TURTLE_SUBTYPE_FILE_MAP : return new RsTurtleFileMapItem(); - case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST : return new RsTurtleChunkCrcRequestItem(); - case RS_TURTLE_SUBTYPE_CHUNK_CRC : return new RsTurtleChunkCrcItem(); - case static_cast(RsFileItemType::FILE_SEARCH_REQUEST): - return new RsFileSearchRequestItem(); - case static_cast(RsFileItemType::FILE_SEARCH_RESULT): - return new RsFileSearchResultItem(); - default: - return nullptr; - } - } - catch(std::exception& e) - { - FTSERVER_ERROR() << "(EE) deserialisation error in " << __PRETTY_FUNCTION__ << ": " << e.what() << std::endl; - - return nullptr; - } -} - -bool ftServer::isEncryptedSource(const RsPeerId& virtual_peer_id) -{ - RS_STACK_MUTEX(srvMutex) ; - - return mEncryptedPeerIds.find(virtual_peer_id) != mEncryptedPeerIds.end(); -} - -void ftServer::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "adding virtual peer. Direction=" << dir << ", hash=" << hash << ", vpid=" << virtual_peer_id << std::endl; -#endif - RsFileHash real_hash ; - - { - if(findRealHash(hash,real_hash)) - { - RS_STACK_MUTEX(srvMutex) ; - mEncryptedPeerIds[virtual_peer_id] = hash ; - } - else - real_hash = hash; - } - - if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " direction is SERVER. Adding file source for end-to-end encrypted tunnel for real hash " << real_hash << ", virtual peer id = " << virtual_peer_id << std::endl; -#endif - mFtController->addFileSource(real_hash,virtual_peer_id) ; - } -} - -void ftServer::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) -{ - RsFileHash real_hash ; - if(findRealHash(hash,real_hash)) - mFtController->removeFileSource(real_hash,virtual_peer_id) ; - else - mFtController->removeFileSource(hash,virtual_peer_id) ; - - RS_STACK_MUTEX(srvMutex) ; - mEncryptedPeerIds.erase(virtual_peer_id) ; -} - -bool ftServer::handleTunnelRequest(const RsFileHash& hash,const RsPeerId& peer_id) -{ - FileInfo info ; - RsFileHash real_hash ; - bool found = false ; - - if(FileDetails(hash, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY, info)) - { - if(info.transfer_info_flags & RS_FILE_REQ_ENCRYPTED) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "handleTunnelRequest: openning encrypted FT tunnel for H(H(F))=" << hash << " and H(F)=" << info.hash << std::endl; -#endif - - RS_STACK_MUTEX(srvMutex) ; - mEncryptedHashes[hash] = info.hash; - - real_hash = info.hash ; - } - else - real_hash = hash ; - - found = true ; - } - else // try to see if we're already swarming the file - { - { - RS_STACK_MUTEX(srvMutex) ; - std::map::const_iterator it = mEncryptedHashes.find(hash) ; - - if(it != mEncryptedHashes.end()) - real_hash = it->second ; - else - real_hash = hash ; - } - - if(FileDetails(real_hash,RS_FILE_HINTS_DOWNLOAD,info)) - { - // This file is currently being downloaded. Let's look if we already have a chunk or not. If not, no need to - // share the file! - - FileChunksInfo info2 ; - if(rsFiles->FileDownloadChunksDetails(real_hash, info2)) - for(uint32_t i=0;idefaultEncryptionPolicy() == RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT && hash == real_hash) - { -#ifdef SERVER_DEBUG - std::cerr << "(WW) rejecting file transfer for hash " << hash << " because the hash is not encrypted and encryption policy requires it." << std::endl; -#endif - return false ; - } - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer: performing local hash search for hash " << hash << std::endl; - - if(found) - { - FTSERVER_DEBUG() << "Found hash: " << std::endl; - FTSERVER_DEBUG() << " hash = " << real_hash << std::endl; - FTSERVER_DEBUG() << " peer = " << peer_id << std::endl; - FTSERVER_DEBUG() << " flags = " << info.storage_permission_flags << std::endl; - FTSERVER_DEBUG() << " groups= " ; - for(std::list::const_iterator it(info.parent_groups.begin());it!=info.parent_groups.end();++it) - FTSERVER_DEBUG() << (*it) << ", " ; - FTSERVER_DEBUG() << std::endl; - FTSERVER_DEBUG() << " clear = " << rsPeers->computePeerPermissionFlags(peer_id,info.storage_permission_flags,info.parent_groups) << std::endl; - } -#endif - - // The call to computeHashPeerClearance() return a combination of RS_FILE_HINTS_NETWORK_WIDE and RS_FILE_HINTS_BROWSABLE - // This is an additional computation cost, but the way it's written here, it's only called when res is true. - // - found = found && (RS_FILE_HINTS_NETWORK_WIDE & rsPeers->computePeerPermissionFlags(peer_id,info.storage_permission_flags,info.parent_groups)) ; - - return found ; -} - -/***************************************************************/ -/******************* ExtraFileList Access **********************/ -/***************************************************************/ - -bool ftServer::ExtraFileAdd(std::string fname, const RsFileHash& hash, uint64_t size, uint32_t period, TransferRequestFlags flags) -{ - return mFtExtra->addExtraFile(fname, hash, size, period, flags); -} - -bool ftServer::ExtraFileRemove(const RsFileHash& hash) -{ return mFileDatabase->removeExtraFile(hash); } - -bool ftServer::ExtraFileHash( std::string localpath, rstime_t period, TransferRequestFlags flags ) -{ - constexpr rstime_t uintmax = std::numeric_limits::max(); - if(period > uintmax) - { - RsErr() << __PRETTY_FUNCTION__ << " period: " << period << " > " - << uintmax << std::errc::value_too_large << std::endl; - return false; - } - - return mFtExtra->hashExtraFile( - localpath, static_cast(period), flags ); -} - -bool ftServer::ExtraFileStatus(std::string localpath, FileInfo &info) -{ - return mFtExtra->hashExtraFileDone(localpath, info); -} - -bool ftServer::ExtraFileMove(std::string fname, const RsFileHash& hash, uint64_t size, std::string destpath) -{ - return mFtExtra->moveExtraFile(fname, hash, size, destpath); -} - -/***************************************************************/ -/******************** Directory Listing ************************/ -/***************************************************************/ - -bool ftServer::findChildPointer(void *ref, int row, void *& result, FileSearchFlags flags) -{ - return mFileDatabase->findChildPointer(ref,row,result,flags) ; -} - -bool ftServer::requestDirDetails( - DirDetails &details, uint64_t handle, FileSearchFlags flags ) -{ return RequestDirDetails(reinterpret_cast(handle), details, flags); } - -int ftServer::RequestDirDetails(void *ref, DirDetails &details, FileSearchFlags flags) -{ - return mFileDatabase->RequestDirDetails(ref,details,flags) ; -} - -uint32_t ftServer::getType(void *ref, FileSearchFlags flags) -{ - return mFileDatabase->getType(ref,flags) ; -} -/***************************************************************/ -/******************** Search Interface *************************/ -/***************************************************************/ - -int ftServer::SearchKeywords(std::list keywords, std::list &results,FileSearchFlags flags) -{ - return mFileDatabase->SearchKeywords(keywords, results,flags,RsPeerId()); -} -int ftServer::SearchKeywords(std::list keywords, std::list &results,FileSearchFlags flags,const RsPeerId& peer_id) -{ - return mFileDatabase->SearchKeywords(keywords, results,flags,peer_id); -} - -int ftServer::SearchBoolExp(RsRegularExpression::Expression * exp, std::list &results,FileSearchFlags flags) -{ - return mFileDatabase->SearchBoolExp(exp, results,flags,RsPeerId()); -} -int ftServer::SearchBoolExp(RsRegularExpression::Expression * exp, std::list &results,FileSearchFlags flags,const RsPeerId& peer_id) -{ - return mFileDatabase->SearchBoolExp(exp,results,flags,peer_id) ; -} -int ftServer::getSharedDirStatistics(const RsPeerId& pid, SharedDirStats& stats) -{ - return mFileDatabase->getSharedDirStatistics(pid,stats) ; -} - -/***************************************************************/ -/*************** Local Shared Dir Interface ********************/ -/***************************************************************/ - -bool ftServer::ConvertSharedFilePath(std::string path, std::string &fullpath) -{ - return mFileDatabase->convertSharedFilePath(path, fullpath); -} - -void ftServer::updateSinceGroupPermissionsChanged() -{ - mFileDatabase->forceSyncWithPeers(); -} -void ftServer::ForceDirectoryCheck(bool add_safe_delay) -{ - mFileDatabase->forceDirectoryCheck(add_safe_delay); - return; -} - -bool ftServer::InDirectoryCheck() -{ - return mFileDatabase->inDirectoryCheck(); -} - -bool ftServer::getSharedDirectories(std::list &dirs) -{ - mFileDatabase->getSharedDirectories(dirs); - return true; -} - -bool ftServer::setSharedDirectories(const std::list& dirs) -{ - mFileDatabase->setSharedDirectories(dirs); - return true; -} - -bool ftServer::addSharedDirectory(const SharedDirInfo& dir) -{ - SharedDirInfo _dir = dir; - _dir.filename = RsDirUtil::convertPathToUnix(_dir.filename); - - std::list dirList; - mFileDatabase->getSharedDirectories(dirList); - - // check that the directory is not already in the list. - for(std::list::const_iterator it(dirList.begin());it!=dirList.end();++it) - if((*it).filename == _dir.filename) - return false ; - - // ok then, add the shared directory. - dirList.push_back(_dir); - - mFileDatabase->setSharedDirectories(dirList); - return true; -} - -bool ftServer::updateShareFlags(const SharedDirInfo& info) -{ - mFileDatabase->updateShareFlags(info); - - return true ; -} - -bool ftServer::removeSharedDirectory(std::string dir) -{ - dir = RsDirUtil::convertPathToUnix(dir); - - std::list dirList; - std::list::iterator it; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::removeSharedDirectory(" << dir << ")" << std::endl; -#endif - - mFileDatabase->getSharedDirectories(dirList); - -#ifdef SERVER_DEBUG - for(it = dirList.begin(); it != dirList.end(); ++it) - FTSERVER_DEBUG() << " existing: " << (*it).filename << std::endl; -#endif - - for(it = dirList.begin();it!=dirList.end() && (*it).filename != dir;++it) ; - - if(it == dirList.end()) - { - FTSERVER_ERROR() << "(EE) ftServer::removeSharedDirectory(): Cannot Find Directory... Fail" << std::endl; - return false; - } - - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " Updating Directories" << std::endl; -#endif - - dirList.erase(it); - mFileDatabase->setSharedDirectories(dirList); - - return true; -} - -bool ftServer::getIgnoreLists(std::list& ignored_prefixes, std::list& ignored_suffixes,uint32_t& ignore_flags) -{ - return mFileDatabase->getIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ; -} -void ftServer::setIgnoreLists(const std::list& ignored_prefixes, const std::list& ignored_suffixes, uint32_t ignore_flags) -{ - mFileDatabase->setIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ; -} - -bool ftServer::watchEnabled() { return mFileDatabase->watchEnabled() ; } -int ftServer::watchPeriod() const { return mFileDatabase->watchPeriod()/60 ; } -bool ftServer::followSymLinks() const { return mFileDatabase->followSymLinks() ; } -bool ftServer::ignoreDuplicates() { return mFileDatabase->ignoreDuplicates() ; } -int ftServer::maxShareDepth() const { return mFileDatabase->maxShareDepth() ; } - -void ftServer::setWatchEnabled(bool b) { mFileDatabase->setWatchEnabled(b) ; } -void ftServer::setWatchPeriod(int minutes) { mFileDatabase->setWatchPeriod(minutes*60) ; } -void ftServer::setFollowSymLinks(bool b) { mFileDatabase->setFollowSymLinks(b) ; } -void ftServer::setIgnoreDuplicates(bool ignore) { mFileDatabase->setIgnoreDuplicates(ignore); } -void ftServer::setMaxShareDepth(int depth) { mFileDatabase->setMaxShareDepth(depth) ; } - -void ftServer::togglePauseHashingProcess() { mFileDatabase->togglePauseHashingProcess() ; } -bool ftServer::hashingProcessPaused() { return mFileDatabase->hashingProcessPaused() ; } - -bool ftServer::getShareDownloadDirectory() -{ - std::list dirList; - mFileDatabase->getSharedDirectories(dirList); - - std::string dir = mFtController->getDownloadDirectory(); - - // check if the download directory is in the list. - for (std::list::const_iterator it(dirList.begin()); it != dirList.end(); ++it) - if ((*it).filename == dir) - return true; - - return false; -} - -bool ftServer::shareDownloadDirectory(bool share) -{ - if (share) - { - /* Share */ - SharedDirInfo inf ; - inf.filename = mFtController->getDownloadDirectory(); - inf.shareflags = DIR_FLAGS_ANONYMOUS_DOWNLOAD ; - - return addSharedDirectory(inf); - } - else - { - /* Unshare */ - std::string dir = mFtController->getDownloadDirectory(); - return removeSharedDirectory(dir); - } -} - -/***************************************************************/ -/****************** End of RsFiles Interface *******************/ -/***************************************************************/ - -//bool ftServer::loadConfigMap(std::map &/*configMap*/) -//{ -// return true; -//} - -/***************************************************************/ -/********************** Data Flow **********************/ -/***************************************************************/ - -bool ftServer::sendTurtleItem(const RsPeerId& peerId,const RsFileHash& hash,RsTurtleGenericTunnelItem *item) -{ - // we cannot look in the encrypted hash map, since the same hash--on this side of the FT--can be used with both - // encrypted and unencrypted peers ids. So the information comes from the virtual peer Id. - - RsFileHash encrypted_hash; - - if(findEncryptedHash(peerId,encrypted_hash)) - { - // we encrypt the item - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "Sending turtle item to peer ID " << peerId << " using encrypted tunnel." << std::endl; -#endif - - RsTurtleGenericDataItem *encrypted_item ; - - if(!encryptItem(item, hash, encrypted_item)) - return false ; - - encrypted_item->setPriorityLevel(item->priority_level()); - - delete item ; - - mTurtleRouter->sendTurtleData(peerId,encrypted_item) ; - } - else - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "Sending turtle item to peer ID " << peerId << " using non uncrypted tunnel." << std::endl; -#endif - mTurtleRouter->sendTurtleData(peerId,item) ; - } - - return true ; -} - -/* Client Send */ -bool ftServer::sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendDataRequest() to peer " << peerId << " for hash " << hash << ", offset=" << offset << ", chunk size="<< chunksize << std::endl; -#endif - if(mTurtleRouter->isTurtlePeer(peerId)) - { - RsTurtleFileRequestItem *item = new RsTurtleFileRequestItem ; - - item->chunk_offset = offset ; - item->chunk_size = chunksize ; - - sendTurtleItem(peerId,hash,item) ; - } - else - { - /* create a packet */ - /* push to networking part */ - RsFileTransferDataRequestItem *rfi = new RsFileTransferDataRequestItem(); - - /* id */ - rfi->PeerId(peerId); - - /* file info */ - rfi->file.filesize = size; - rfi->file.hash = hash; /* ftr->hash; */ - - /* offsets */ - rfi->fileoffset = offset; /* ftr->offset; */ - rfi->chunksize = chunksize; /* ftr->chunk; */ - - sendItem(rfi); - } - - return true; -} - -bool ftServer::sendChunkMapRequest(const RsPeerId& peerId,const RsFileHash& hash,bool is_client) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendChunkMapRequest() to peer " << peerId << " for hash " << hash << std::endl; -#endif - if(mTurtleRouter->isTurtlePeer(peerId)) - { - RsTurtleFileMapRequestItem *item = new RsTurtleFileMapRequestItem ; - sendTurtleItem(peerId,hash,item) ; - } - else - { - /* create a packet */ - /* push to networking part */ - RsFileTransferChunkMapRequestItem *rfi = new RsFileTransferChunkMapRequestItem(); - - /* id */ - rfi->PeerId(peerId); - - /* file info */ - rfi->hash = hash; /* ftr->hash; */ - rfi->is_client = is_client ; - - sendItem(rfi); - } - - return true ; -} - -bool ftServer::sendChunkMap(const RsPeerId& peerId,const RsFileHash& hash,const CompressedChunkMap& map,bool is_client) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendChunkMap() to peer " << peerId << " for hash " << hash << std::endl; -#endif - if(mTurtleRouter->isTurtlePeer(peerId)) - { - RsTurtleFileMapItem *item = new RsTurtleFileMapItem ; - item->compressed_map = map ; - sendTurtleItem(peerId,hash,item) ; - } - else - { - /* create a packet */ - /* push to networking part */ - RsFileTransferChunkMapItem *rfi = new RsFileTransferChunkMapItem(); - - /* id */ - rfi->PeerId(peerId); - - /* file info */ - rfi->hash = hash; /* ftr->hash; */ - rfi->is_client = is_client; /* ftr->hash; */ - rfi->compressed_map = map; /* ftr->hash; */ - - sendItem(rfi); - } - - return true ; -} - -bool ftServer::sendSingleChunkCRCRequest(const RsPeerId& peerId,const RsFileHash& hash,uint32_t chunk_number) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendSingleCRCRequest() to peer " << peerId << " for hash " << hash << ", chunk number=" << chunk_number << std::endl; -#endif - if(mTurtleRouter->isTurtlePeer(peerId)) - { - RsTurtleChunkCrcRequestItem *item = new RsTurtleChunkCrcRequestItem; - item->chunk_number = chunk_number ; - - sendTurtleItem(peerId,hash,item) ; - } - else - { - /* create a packet */ - /* push to networking part */ - RsFileTransferSingleChunkCrcRequestItem *rfi = new RsFileTransferSingleChunkCrcRequestItem(); - - /* id */ - rfi->PeerId(peerId); - - /* file info */ - rfi->hash = hash; /* ftr->hash; */ - rfi->chunk_number = chunk_number ; - - sendItem(rfi); - } - - return true ; -} - -bool ftServer::sendSingleChunkCRC(const RsPeerId& peerId,const RsFileHash& hash,uint32_t chunk_number,const Sha1CheckSum& crc) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendSingleCRC() to peer " << peerId << " for hash " << hash << ", chunk number=" << chunk_number << std::endl; -#endif - if(mTurtleRouter->isTurtlePeer(peerId)) - { - RsTurtleChunkCrcItem *item = new RsTurtleChunkCrcItem; - item->chunk_number = chunk_number ; - item->check_sum = crc ; - - sendTurtleItem(peerId,hash,item) ; - } - else - { - /* create a packet */ - /* push to networking part */ - RsFileTransferSingleChunkCrcItem *rfi = new RsFileTransferSingleChunkCrcItem(); - - /* id */ - rfi->PeerId(peerId); - - /* file info */ - rfi->hash = hash; /* ftr->hash; */ - rfi->check_sum = crc; - rfi->chunk_number = chunk_number; - - sendItem(rfi); - } - - return true ; -} - -/* Server Send */ -bool ftServer::sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t baseoffset, uint32_t chunksize, void *data) -{ - /* create a packet */ - /* push to networking part */ - uint32_t tosend = chunksize; - uint64_t offset = 0; - uint32_t chunk; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendData() to " << peerId << ", hash: " << hash << " offset: " << baseoffset << " chunk: " << chunksize << " data: " << data << std::endl; -#endif - - while(tosend > 0) - { - //static const uint32_t MAX_FT_CHUNK = 32 * 1024; /* 32K */ - //static const uint32_t MAX_FT_CHUNK = 16 * 1024; /* 16K */ - // - static const uint32_t MAX_FT_CHUNK = 8 * 1024; /* 16K */ - - /* workout size */ - chunk = MAX_FT_CHUNK; - if (chunk > tosend) - { - chunk = tosend; - } - - /******** New Serialiser Type *******/ - - if(mTurtleRouter->isTurtlePeer(peerId)) - { - RsTurtleFileDataItem *item = new RsTurtleFileDataItem ; - - item->chunk_offset = offset+baseoffset ; - item->chunk_size = chunk; - item->chunk_data = rs_malloc(chunk) ; - - if(item->chunk_data == NULL) - { - delete item; - return false; - } - memcpy(item->chunk_data,&(((uint8_t *) data)[offset]),chunk) ; - - sendTurtleItem(peerId,hash,item) ; - } - else - { - RsFileTransferDataItem *rfd = new RsFileTransferDataItem(); - - /* set id */ - rfd->PeerId(peerId); - - /* file info */ - rfd->fd.file.filesize = size; - rfd->fd.file.hash = hash; - rfd->fd.file.name = ""; /* blank other data */ - rfd->fd.file.path = ""; - rfd->fd.file.pop = 0; - rfd->fd.file.age = 0; - - rfd->fd.file_offset = baseoffset + offset; - - /* file data */ - rfd->fd.binData.setBinData( &(((uint8_t *) data)[offset]), chunk); - - sendItem(rfd); - - /* print the data pointer */ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendData() Packet: " << " offset: " << rfd->fd.file_offset << " chunk: " << chunk << " len: " << rfd->fd.binData.bin_len << " data: " << rfd->fd.binData.bin_data << std::endl; -#endif - } - - offset += chunk; - tosend -= chunk; - } - - /* clean up data */ - free(data); - - return true; -} - -// Encrypts the given item using aead-chacha20-poly1305 -// -// The format is the following -// -// [encryption format] [random initialization vector] [encrypted data size] [encrypted data] [authentication tag] -// 4 bytes 12 bytes 4 bytes variable 16 bytes -// -// +-------------------- authenticated data part ----------------------+ -// -// -// Encryption format: -// ae ad 01 01 : encryption using AEAD, format 01 (authed with Poly1305 ), version 01 -// ae ad 02 01 : encryption using AEAD, format 02 (authed with HMAC Sha256), version 01 -// -// - -void ftServer::deriveEncryptionKey(const RsFileHash& hash, uint8_t *key) -{ - // The encryption key is simply the 256 hash of the - SHA256_CTX sha_ctx ; - - if(SHA256_DIGEST_LENGTH != 32) - throw std::runtime_error("Warning: can't compute Sha1Sum with sum size != 32") ; - - SHA256_Init(&sha_ctx); - SHA256_Update(&sha_ctx, hash.toByteArray(), hash.SIZE_IN_BYTES); - SHA256_Final (key, &sha_ctx); -} - -#ifdef USE_NEW_METHOD -static const uint32_t ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE = 12 ; -static const uint32_t ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE = 16 ; -static const uint32_t ENCRYPTED_FT_HEADER_SIZE = 4 ; -static const uint32_t ENCRYPTED_FT_EDATA_SIZE = 4 ; - -static const uint8_t ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_POLY1305 = 0x01 ; -static const uint8_t ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256 = 0x02 ; -#endif //USE_NEW_METHOD - -bool ftServer::encryptItem(RsTurtleGenericTunnelItem *clear_item,const RsFileHash& hash,RsTurtleGenericDataItem *& encrypted_item) -{ -#ifndef USE_NEW_METHOD - uint32_t item_serialized_size = size(clear_item) ; - - RsTemporaryMemory data(item_serialized_size) ; - - if(data == NULL) - return false ; - - serialise(clear_item, data, &item_serialized_size); - - uint8_t encryption_key[32] ; - deriveEncryptionKey(hash,encryption_key) ; - - return p3turtle::encryptData(data,item_serialized_size,encryption_key,encrypted_item) ; -#else - uint8_t initialization_vector[ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE] ; - - RSRandom::random_bytes(initialization_vector,ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) ; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::Encrypting ft item." << std::endl; - FTSERVER_DEBUG() << " random nonce : " << RsUtil::BinToHex(initialization_vector,ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) << std::endl; -#endif - - uint32_t item_serialized_size = size(clear_item) ; - uint32_t total_data_size = ENCRYPTED_FT_HEADER_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_EDATA_SIZE + item_serialized_size + ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE ; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " clear part size : " << size(clear_item) << std::endl; - FTSERVER_DEBUG() << " total item size : " << total_data_size << std::endl; -#endif - - encrypted_item = new RsTurtleGenericDataItem ; - encrypted_item->data_bytes = rs_malloc( total_data_size ) ; - encrypted_item->data_size = total_data_size ; - - if(encrypted_item->data_bytes == NULL) - return false ; - - uint8_t *edata = (uint8_t*)encrypted_item->data_bytes ; - uint32_t edata_size = item_serialized_size; - uint32_t offset = 0; - - edata[0] = 0xae ; - edata[1] = 0xad ; - edata[2] = ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256 ; // means AEAD_chacha20_sha256 - edata[3] = 0x01 ; - - offset += ENCRYPTED_FT_HEADER_SIZE; - uint32_t aad_offset = offset ; - uint32_t aad_size = ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_EDATA_SIZE ; - - memcpy(&edata[offset], initialization_vector, ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) ; - offset += ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE ; - - edata[offset+0] = (edata_size >> 0) & 0xff ; - edata[offset+1] = (edata_size >> 8) & 0xff ; - edata[offset+2] = (edata_size >> 16) & 0xff ; - edata[offset+3] = (edata_size >> 24) & 0xff ; - - offset += ENCRYPTED_FT_EDATA_SIZE ; - - uint32_t ser_size = (uint32_t)((int)total_data_size - (int)offset); - - serialise(clear_item,&edata[offset], &ser_size); - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " clear item : " << RsUtil::BinToHex(&edata[offset],std::min(50,(int)total_data_size-(int)offset)) << "(...)" << std::endl; -#endif - - uint32_t clear_item_offset = offset ; - offset += edata_size ; - - uint32_t authentication_tag_offset = offset ; - assert(ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE + offset == total_data_size) ; - - uint8_t encryption_key[32] ; - deriveEncryptionKey(hash,encryption_key) ; - - if(edata[2] == ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_POLY1305) - librs::crypto::AEAD_chacha20_poly1305(encryption_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],true) ; - else if(edata[2] == ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256) - librs::crypto::AEAD_chacha20_sha256 (encryption_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],true) ; - else - return false ; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " encryption key : " << RsUtil::BinToHex(encryption_key,32) << std::endl; - FTSERVER_DEBUG() << " authen. tag : " << RsUtil::BinToHex(&edata[authentication_tag_offset],ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE) << std::endl; - FTSERVER_DEBUG() << " final item : " << RsUtil::BinToHex(&edata[0],std::min(50u,total_data_size)) << "(...)" << std::endl; -#endif - - return true ; -#endif -} - -// Decrypts the given item using aead-chacha20-poly1305 - -bool ftServer::decryptItem(const RsTurtleGenericDataItem *encrypted_item,const RsFileHash& hash,RsTurtleGenericTunnelItem *& decrypted_item) -{ -#ifndef USE_NEW_METHOD - unsigned char *data = NULL ; - uint32_t data_size = 0 ; - - uint8_t encryption_key[32] ; - deriveEncryptionKey(hash,encryption_key) ; - - if(!p3turtle::decryptItem(encrypted_item,encryption_key,data,data_size)) - { - FTSERVER_ERROR() << "Cannot decrypt data!" << std::endl; - - if(data) - free(data) ; - return false ; - } - decrypted_item = dynamic_cast(deserialise(data,&data_size)) ; - free(data); - - return (decrypted_item != NULL); - -#else - uint8_t encryption_key[32] ; - deriveEncryptionKey(hash,encryption_key) ; - - uint8_t *edata = (uint8_t*)encrypted_item->data_bytes ; - uint32_t offset = 0; - - if(encrypted_item->data_size < ENCRYPTED_FT_HEADER_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_EDATA_SIZE) return false ; - - if(edata[0] != 0xae) return false ; - if(edata[1] != 0xad) return false ; - if(edata[2] != ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_POLY1305 && edata[2] != ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256) return false ; - if(edata[3] != 0x01) return false ; - - offset += ENCRYPTED_FT_HEADER_SIZE ; - uint32_t aad_offset = offset ; - uint32_t aad_size = ENCRYPTED_FT_EDATA_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE ; - - uint8_t *initialization_vector = &edata[offset] ; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::decrypting ft item." << std::endl; - FTSERVER_DEBUG() << " item data : " << RsUtil::BinToHex(edata,std::min(50u,encrypted_item->data_size)) << "(...)" << std::endl; - FTSERVER_DEBUG() << " hash : " << hash << std::endl; - FTSERVER_DEBUG() << " encryption key : " << RsUtil::BinToHex(encryption_key,32) << std::endl; - FTSERVER_DEBUG() << " random nonce : " << RsUtil::BinToHex(initialization_vector,ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) << std::endl; -#endif - - offset += ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE ; - - uint32_t edata_size = 0 ; - edata_size += ((uint32_t)edata[offset+0]) << 0 ; - edata_size += ((uint32_t)edata[offset+1]) << 8 ; - edata_size += ((uint32_t)edata[offset+2]) << 16 ; - edata_size += ((uint32_t)edata[offset+3]) << 24 ; - - if(edata_size + ENCRYPTED_FT_EDATA_SIZE + ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_HEADER_SIZE != encrypted_item->data_size) - { - FTSERVER_ERROR() << " ERROR: encrypted data size is " << edata_size << ", should be " << encrypted_item->data_size - (ENCRYPTED_FT_EDATA_SIZE + ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_HEADER_SIZE ) << std::endl; - return false ; - } - - offset += ENCRYPTED_FT_EDATA_SIZE ; - uint32_t clear_item_offset = offset ; - - uint32_t authentication_tag_offset = offset + edata_size ; -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " authen. tag : " << RsUtil::BinToHex(&edata[authentication_tag_offset],ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE) << std::endl; -#endif - - bool result ; - - if(edata[2] == ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_POLY1305) - result = librs::crypto::AEAD_chacha20_poly1305(encryption_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],false) ; - else if(edata[2] == ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256) - result = librs::crypto::AEAD_chacha20_sha256 (encryption_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],false) ; - else - return false ; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " authen. result : " << result << std::endl; - FTSERVER_DEBUG() << " decrypted daya : " << RsUtil::BinToHex(&edata[clear_item_offset],std::min(50u,edata_size)) << "(...)" << std::endl; -#endif - - if(!result) - { - FTSERVER_ERROR() << "(EE) decryption/authentication went wrong." << std::endl; - return false ; - } - - decrypted_item = dynamic_cast(deserialise(&edata[clear_item_offset],&edata_size)) ; - - if(decrypted_item == NULL) - return false ; - - return true ; -#endif -} - -bool ftServer::encryptHash(const RsFileHash& hash, RsFileHash& hash_of_hash) -{ - hash_of_hash = RsDirUtil::sha1sum(hash.toByteArray(),hash.SIZE_IN_BYTES); - return true ; -} - -bool ftServer::findEncryptedHash(const RsPeerId& virtual_peer_id, RsFileHash& encrypted_hash) -{ - RS_STACK_MUTEX(srvMutex); - - std::map::const_iterator it = mEncryptedPeerIds.find(virtual_peer_id) ; - - if(it != mEncryptedPeerIds.end()) - { - encrypted_hash = it->second ; - return true ; - } - else - return false ; -} - -bool ftServer::findRealHash(const RsFileHash& hash, RsFileHash& real_hash) -{ - RS_STACK_MUTEX(srvMutex); - std::map::const_iterator it = mEncryptedHashes.find(hash) ; - - if(it != mEncryptedHashes.end()) - { - real_hash = it->second ; - return true ; - } - else - return false ; -} - -TurtleSearchRequestId ftServer::turtleSearch(const std::string& string_to_match) -{ - return mTurtleRouter->turtleSearch(string_to_match) ; -} -TurtleSearchRequestId ftServer::turtleSearch(const RsRegularExpression::LinearizedExpression& expr) -{ - return mTurtleRouter->turtleSearch(expr) ; -} - -#warning we should do this here, but for now it is done by turtle router. -// // Dont delete the item. The client (p3turtle) is doing it after calling this. -// // -// void ftServer::receiveSearchResult(RsTurtleSearchResultItem *item) -// { -// RsTurtleFTSearchResultItem *ft_sr = dynamic_cast(item) ; -// -// if(ft_sr == NULL) -// { -// FTSERVER_ERROR() << "(EE) ftServer::receiveSearchResult(): item cannot be cast to a RsTurtleFTSearchResultItem" << std::endl; -// return ; -// } -// -// RsServer::notify()->notifyTurtleSearchResult(ft_sr->request_id,ft_sr->result) ; -// } - -// Dont delete the item. The client (p3turtle) is doing it after calling this. -// -void ftServer::receiveTurtleData(const RsTurtleGenericTunnelItem *i, - const RsFileHash& hash, - const RsPeerId& virtual_peer_id, - RsTurtleGenericTunnelItem::Direction direction) -{ - if(i->PacketSubType() == RS_TURTLE_SUBTYPE_GENERIC_DATA) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "Received encrypted data item. Trying to decrypt" << std::endl; -#endif - - RsFileHash real_hash ; - - if(!findRealHash(hash,real_hash)) - { - FTSERVER_ERROR() << "(EE) Cannot find real hash for encrypted data item with H(H(F))=" << hash << ". This is unexpected." << std::endl; - return ; - } - - RsTurtleGenericTunnelItem *decrypted_item ; - if(!decryptItem(dynamic_cast(i),real_hash,decrypted_item)) - { - FTSERVER_ERROR() << "(EE) decryption error." << std::endl; - return ; - } - - receiveTurtleData(decrypted_item, real_hash, virtual_peer_id,direction) ; - - delete decrypted_item ; - return ; - } - - switch(i->PacketSubType()) - { - case RS_TURTLE_SUBTYPE_FILE_REQUEST: - { - const RsTurtleFileRequestItem *item = dynamic_cast(i) ; - if (item) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received file data request for " << hash << " from peer " << virtual_peer_id << std::endl; -#endif - getMultiplexer()->recvDataRequest(virtual_peer_id,hash,0,item->chunk_offset,item->chunk_size) ; - } - } - break ; - - case RS_TURTLE_SUBTYPE_FILE_DATA : - { - const RsTurtleFileDataItem *item = dynamic_cast(i) ; - if (item) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received file data for " << hash << " from peer " << virtual_peer_id << std::endl; -#endif - getMultiplexer()->recvData(virtual_peer_id,hash,0,item->chunk_offset,item->chunk_size,item->chunk_data) ; - - const_cast(item)->chunk_data = NULL ; // this prevents deletion in the destructor of RsFileDataItem, because data will be deleted - // down _ft_server->getMultiplexer()->recvData()...in ftTransferModule::recvFileData - } - } - break ; - - case RS_TURTLE_SUBTYPE_FILE_MAP : - { - const RsTurtleFileMapItem *item = dynamic_cast(i) ; - if (item) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received chunk map for hash " << hash << " from peer " << virtual_peer_id << std::endl; -#endif - getMultiplexer()->recvChunkMap(virtual_peer_id,hash,item->compressed_map,direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; - } - } - break ; - - case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST: - { - //RsTurtleFileMapRequestItem *item = dynamic_cast(i) ; -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received chunkmap request for hash " << hash << " from peer " << virtual_peer_id << std::endl; -#endif - getMultiplexer()->recvChunkMapRequest(virtual_peer_id,hash,direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; - } - break ; - - case RS_TURTLE_SUBTYPE_CHUNK_CRC : - { - const RsTurtleChunkCrcItem *item = dynamic_cast(i) ; - if (item) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received single chunk CRC for hash " << hash << " from peer " << virtual_peer_id << std::endl; -#endif - getMultiplexer()->recvSingleChunkCRC(virtual_peer_id,hash,item->chunk_number,item->check_sum) ; - } - } - break ; - - case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST: - { - const RsTurtleChunkCrcRequestItem *item = dynamic_cast(i) ; - if (item) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received single chunk CRC request for hash " << hash << " from peer " << virtual_peer_id << std::endl; -#endif - getMultiplexer()->recvSingleChunkCRCRequest(virtual_peer_id,hash,item->chunk_number) ; - } - } - break ; - default: - FTSERVER_ERROR() << "WARNING: Unknown packet type received: sub_id=" << reinterpret_cast(i->PacketSubType()) << ". Is somebody trying to poison you ?" << std::endl ; - } -} - -/* NB: The rsCore lock must be activated before calling this. - * This Lock should be moved lower into the system... - * most likely destination is in ftServer. - */ -int ftServer::tick() -{ - bool moreToTick = false ; - - if(handleIncoming()) - moreToTick = true; - - static rstime_t last_law_priority_tasks_handling_time = 0 ; - rstime_t now = time(NULL) ; - - if(last_law_priority_tasks_handling_time + FILE_TRANSFER_LOW_PRIORITY_TASKS_PERIOD < now) - { - last_law_priority_tasks_handling_time = now ; - - mFtDataplex->deleteUnusedServers() ; - mFtDataplex->handlePendingCrcRequests() ; - mFtDataplex->dispatchReceivedChunkCheckSum() ; - cleanTimedOutSearches(); - } - - return moreToTick; -} - -bool ftServer::checkUploadLimit(const RsPeerId& pid,const RsFileHash& hash) -{ - // No need for this extra cost if the value means "unlimited" - -#ifdef SERVER_DEBUG - std::cerr << "Checking upload limit for friend " << pid << " and hash " << hash << ": " ; -#endif - - uint32_t max_ups = mFtController->getMaxUploadsPerFriend() ; - - RS_STACK_MUTEX(srvMutex) ; - - if(max_ups == 0) - { -#ifdef SERVER_DEBUG - std::cerr << " no limit! returning true." << std::endl; -#endif - return true ; - } -#ifdef SERVER_DEBUG - std::cerr << " max=" << max_ups ; -#endif - - // Find the latest records for this pid. - - std::map& tmap(mUploadLimitMap[pid]) ; - std::map::iterator it ; - - rstime_t now = time(NULL) ; - - // If the limit has been decresed, we arbitrarily drop some ongoing slots. - - while(tmap.size() > max_ups) - tmap.erase(tmap.begin()) ; - - // Look in the upload record map. If it's not full, directly allocate a slot. If full, re-use an existing slot if a file is already cited. - - if(tmap.size() < max_ups || (tmap.size()==max_ups && tmap.end() != (it = tmap.find(hash)))) - { -#ifdef SERVER_DEBUG - std::cerr << " allocated slot for this hash => true" << std::endl; -#endif - - tmap[hash] = now ; - return true ; - } - - // There's no room in the used slots, but maybe some of them are not used anymore, in which case we remove them, which freeze a slot. - uint32_t cleaned = 0 ; - - for(it = tmap.begin();it!=tmap.end() && cleaned<2;) - if(it->second + FILE_TRANSFER_MAX_DELAY_BEFORE_DROP_USAGE_RECORD < now) - { - std::map::iterator tmp(it) ; - ++tmp; - tmap.erase(it) ; - it = tmp; - ++cleaned ; - } - else - ++it ; - - if(cleaned > 0) - { -#ifdef SERVER_DEBUG - std::cerr << " cleaned up " << cleaned << " old hashes => true" << std::endl; -#endif - tmap[hash] = now ; - return true ; - } - -#ifdef SERVER_DEBUG - std::cerr << " no slot for this hash => false" << std::endl; -#endif - return false ; -} - -int ftServer::handleIncoming() -{ - // now File Input. - int nhandled = 0 ; - - RsItem *item = NULL ; - - while(NULL != (item = recvItem())) - { - nhandled++ ; - - switch(item->PacketSubType()) - { - case RS_PKT_SUBTYPE_FT_DATA_REQUEST: - { - RsFileTransferDataRequestItem *f = dynamic_cast(item) ; - - if (f && checkUploadLimit(f->PeerId(),f->file.hash)) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::handleIncoming: received data request for hash " << f->file.hash << ", offset=" << f->fileoffset << ", chunk size=" << f->chunksize << std::endl; -#endif - mFtDataplex->recvDataRequest(f->PeerId(), f->file.hash, f->file.filesize, f->fileoffset, f->chunksize); - } - } - break ; - - case RS_PKT_SUBTYPE_FT_DATA: - { - RsFileTransferDataItem *f = dynamic_cast(item) ; - if (f) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::handleIncoming: received data for hash " << f->fd.file.hash << ", offset=" << f->fd.file_offset << ", chunk size=" << f->fd.binData.bin_len << std::endl; -#endif - mFtDataplex->recvData(f->PeerId(), f->fd.file.hash, f->fd.file.filesize, f->fd.file_offset, f->fd.binData.bin_len, f->fd.binData.bin_data); - - /* we've stolen the data part -> so blank before delete - */ - f->fd.binData.TlvShallowClear(); - } - } - break ; - - case RS_PKT_SUBTYPE_FT_CHUNK_MAP_REQUEST: - { - RsFileTransferChunkMapRequestItem *f = dynamic_cast(item) ; - if (f) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::handleIncoming: received chunkmap request for hash " << f->hash << ", client=" << f->is_client << std::endl; -#endif - mFtDataplex->recvChunkMapRequest(f->PeerId(), f->hash,f->is_client) ; - } - } - break ; - - case RS_PKT_SUBTYPE_FT_CHUNK_MAP: - { - RsFileTransferChunkMapItem *f = dynamic_cast(item) ; - if (f) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::handleIncoming: received chunkmap for hash " << f->hash << ", client=" << f->is_client << /*", map=" << f->compressed_map <<*/ std::endl; -#endif - mFtDataplex->recvChunkMap(f->PeerId(), f->hash,f->compressed_map,f->is_client) ; - } - } - break ; - - case RS_PKT_SUBTYPE_FT_CHUNK_CRC_REQUEST: - { - RsFileTransferSingleChunkCrcRequestItem *f = dynamic_cast(item) ; - if (f) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::handleIncoming: received single chunk crc req for hash " << f->hash << ", chunk number=" << f->chunk_number << std::endl; -#endif - mFtDataplex->recvSingleChunkCRCRequest(f->PeerId(), f->hash,f->chunk_number) ; - } - } - break ; - - case RS_PKT_SUBTYPE_FT_CHUNK_CRC: - { - RsFileTransferSingleChunkCrcItem *f = dynamic_cast(item) ; - if (f) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::handleIncoming: received single chunk crc req for hash " << f->hash << ", chunk number=" << f->chunk_number << ", checksum = " << f->check_sum << std::endl; -#endif - mFtDataplex->recvSingleChunkCRC(f->PeerId(), f->hash,f->chunk_number,f->check_sum); - } - } - break ; - } - - delete item ; - } - - return nhandled; -} - -/********************************** - ********************************** - ********************************** - *********************************/ - -void ftServer::ftReceiveSearchResult(RsTurtleFTSearchResultItem *item) -{ - bool hasCallback = false; - - { - RS_STACK_MUTEX(mSearchCallbacksMapMutex); - auto cbpt = mSearchCallbacksMap.find(item->request_id); - if(cbpt != mSearchCallbacksMap.end()) - { - hasCallback = true; - - std::vector cRes; - for(auto& res: std::as_const(item->result)) - cRes.push_back(TurtleFileInfoV2(res)); - - cbpt->second.first(cRes); - } - } // end RS_STACK_MUTEX(mSearchCallbacksMapMutex); - - if(!hasCallback) - RsServer::notify()->notifyTurtleSearchResult( - item->PeerId(), item->request_id, item->result ); -} - -bool ftServer::receiveSearchRequest( - unsigned char* searchRequestData, uint32_t searchRequestDataLen, - unsigned char*& searchResultData, uint32_t& searchResultDataLen, - uint32_t& maxAllowsHits ) -{ -#ifdef RS_DEEP_FILES_INDEX - std::unique_ptr recvItem( - RsServiceSerializer::deserialise( - searchRequestData, &searchRequestDataLen ) ); - - if(!recvItem) - { - RsWarn() << __PRETTY_FUNCTION__ << " Search request deserialization " - << "failed" << std::endl; - return false; - } - - std::unique_ptr sReqItPtr( - dynamic_cast(recvItem.get()) ); - if(!sReqItPtr) - { - RsWarn() << __PRETTY_FUNCTION__ << " Received an invalid search request" - << " " << *recvItem << std::endl; - return false; - } - recvItem.release(); - - RsFileSearchRequestItem& searchReq(*sReqItPtr); - - std::vector dRes; - DeepFilesIndex dfi(DeepFilesIndex::dbDefaultPath()); - if(dfi.search(searchReq.queryString, dRes, maxAllowsHits) > 0) - { - RsFileSearchResultItem resIt; - - for(const auto& dMatch : dRes) - resIt.mResults.push_back(TurtleFileInfoV2(dMatch)); - - searchResultDataLen = RsServiceSerializer::size(&resIt); - searchResultData = static_cast(malloc(searchResultDataLen)); - return RsServiceSerializer::serialise( - &resIt, searchResultData, &searchResultDataLen ); - } -#endif // def RS_DEEP_FILES_INDEX - - searchResultData = nullptr; - searchResultDataLen = 0; - return false; -} - -void ftServer::receiveSearchResult( - TurtleSearchRequestId requestId, unsigned char* searchResultData, - uint32_t searchResultDataLen ) -{ - if(!searchResultData || !searchResultDataLen) - { - RsWarn() << __PRETTY_FUNCTION__ << " got null paramethers " - << "searchResultData: " << static_cast(searchResultData) - << " searchResultDataLen: " << searchResultDataLen - << " seems someone else in the network have a buggy RetroShare" - << " implementation" << std::endl; - return; - } - - RS_STACK_MUTEX(mSearchCallbacksMapMutex); - auto cbpt = mSearchCallbacksMap.find(requestId); - if(cbpt != mSearchCallbacksMap.end()) - { - RsItem* recvItem = RsServiceSerializer::deserialise( - searchResultData, &searchResultDataLen ); - - if(!recvItem) - { - RsWarn() << __PRETTY_FUNCTION__ << " Search result deserialization " - << "failed" << std::endl; - return; - } - - std::unique_ptr resItPtr( - dynamic_cast(recvItem) ); - - if(!resItPtr) - { - RsWarn() << __PRETTY_FUNCTION__ << " Received invalid search result" - << std::endl; - delete recvItem; - return; - } - - cbpt->second.first(resItPtr->mResults); - } -} - -/***************************** CONFIG ****************************/ - -bool ftServer::addConfiguration(p3ConfigMgr *cfgmgr) -{ - /* add all the subbits to config mgr */ - cfgmgr->addConfiguration("ft_database.cfg" , mFileDatabase); - cfgmgr->addConfiguration("ft_extra.cfg" , mFtExtra ); - cfgmgr->addConfiguration("ft_transfers.cfg", mFtController); - - return true; -} - -#ifdef RS_DEEP_FILES_INDEX -static std::vector xapianQueryKeywords = -{ - " AND ", " OR ", " NOT ", " XOR ", " +", " -", " ( ", " ) ", " NEAR ", - " ADJ ", " \"", "\" " -}; -#endif - -bool ftServer::turtleSearchRequest( - const std::string& matchString, - const std::function& results)>& multiCallback, - rstime_t maxWait ) -{ - if(matchString.empty()) - { - RsWarn() << __PRETTY_FUNCTION__ << " match string can't be empty!" - << std::endl; - return false; - } - -#ifdef RS_DEEP_FILES_INDEX - RsFileSearchRequestItem sItem; - sItem.queryString = matchString; - - uint32_t iSize = RsServiceSerializer::size(&sItem); - uint8_t* iBuf = static_cast(malloc(iSize)); - RsServiceSerializer::serialise(&sItem, iBuf, &iSize); - - Dbg3() << __PRETTY_FUNCTION__ << " sending search request:" << sItem - << std::endl; - - TurtleRequestId xsId = mTurtleRouter->turtleSearch(iBuf, iSize, this); - - { RS_STACK_MUTEX(mSearchCallbacksMapMutex); - mSearchCallbacksMap.emplace( - xsId, - std::make_pair( - multiCallback, - std::chrono::system_clock::now() + - std::chrono::seconds(maxWait) ) ); - } // RS_STACK_MUTEX(mSearchCallbacksMapMutex); - - /* Trick to keep receiving more or less usable results from old peers */ - std::string strippedQuery = matchString; - for(const std::string& xKeyword : xapianQueryKeywords) - { - std::string::size_type pos = std::string::npos; - while( (pos = strippedQuery.find(xKeyword)) != std::string::npos ) - strippedQuery.replace(pos, xKeyword.length(), " "); - } - - Dbg3() << __PRETTY_FUNCTION__ << " sending stripped query for " - << "retro-compatibility: " << strippedQuery << std::endl; - - TurtleRequestId sId = mTurtleRouter->turtleSearch(strippedQuery); -#else // def RS_DEEP_FILES_INDEX - TurtleRequestId sId = mTurtleRouter->turtleSearch(matchString); -#endif // def RS_DEEP_FILES_INDEX - - { - RS_STACK_MUTEX(mSearchCallbacksMapMutex); - mSearchCallbacksMap.emplace( - sId, - std::make_pair( - multiCallback, - std::chrono::system_clock::now() + - std::chrono::seconds(maxWait) ) ); - } - - return true; -} - -void ftServer::cleanTimedOutSearches() -{ - RS_STACK_MUTEX(mSearchCallbacksMapMutex); - auto now = std::chrono::system_clock::now(); - for( auto cbpt = mSearchCallbacksMap.begin(); - cbpt != mSearchCallbacksMap.end(); ) - if(cbpt->second.second <= now) - cbpt = mSearchCallbacksMap.erase(cbpt); - else ++cbpt; -} - -// Offensive content file filtering - -int ftServer::banFile(const RsFileHash& real_file_hash, const std::string& filename, uint64_t file_size) -{ - return mFileDatabase->banFile(real_file_hash,filename,file_size) ; -} -int ftServer::unbanFile(const RsFileHash& real_file_hash) -{ - return mFileDatabase->unbanFile(real_file_hash) ; -} -bool ftServer::getPrimaryBannedFilesList(std::map& banned_files) -{ - return mFileDatabase->getPrimaryBannedFilesList(banned_files) ; -} - -bool ftServer::isHashBanned(const RsFileHash& hash) -{ - return mFileDatabase->isFileBanned(hash); -} - -RsFileItem::~RsFileItem() = default; - -RsFileItem::RsFileItem(RsFileItemType subtype) : - RsItem( RS_PKT_VERSION_SERVICE, - static_cast(RsServiceType::FILE_TRANSFER), - static_cast(subtype) ) {} - -void RsFileSearchRequestItem::clear() { queryString.clear(); } - -void RsFileSearchResultItem::clear() { mResults.clear(); } - - -std::error_condition RsFilesErrorCategory::default_error_condition(int ev) -const noexcept -{ - switch(static_cast(ev)) - { - case RsFilesErrorNum::FILES_HANDLE_NOT_FOUND: - return std::errc::invalid_argument; - default: - return std::error_condition(ev, *this); - } -} - -std::error_condition ftServer::dirDetailsToLink( - std::string& link, - const DirDetails& dirDetails, bool fragSneak, const std::string& baseUrl ) -{ - std::unique_ptr tFileTree = - RsFileTree::fromDirDetails(dirDetails, false); - if(!tFileTree) return std::errc::invalid_argument; - - link = tFileTree->toBase64(); - - if(!baseUrl.empty()) - { - RsUrl tUrl(baseUrl); - tUrl.setQueryKV(FILES_URL_COUNT_FIELD, - std::to_string(tFileTree->mTotalFiles) ) - .setQueryKV(FILES_URL_NAME_FIELD, dirDetails.name) - .setQueryKV( FILES_URL_SIZE_FIELD, - std::to_string(tFileTree->mTotalSize) ); - if(fragSneak) - tUrl.setQueryKV(FILES_URL_DATA_FIELD, FILES_URL_FAGMENT_FORWARD) - .setFragment(link); - else tUrl.setQueryKV(FILES_URL_DATA_FIELD, link); - link = tUrl.toString(); - } - - return std::error_condition(); -} - -std::error_condition ftServer::exportCollectionLink( - std::string& link, uint64_t handle, bool fragSneak, - const std::string& baseUrl ) -{ - DirDetails tDirDet; - if(!requestDirDetails(tDirDet, handle)) - return RsFilesErrorNum::FILES_HANDLE_NOT_FOUND; - - return dirDetailsToLink(link, tDirDet, fragSneak, baseUrl); -} - -/// @see RsFiles -std::error_condition ftServer::exportFileLink( - std::string& link, const RsFileHash& fileHash, uint64_t fileSize, - const std::string& fileName, bool fragSneak, const std::string& baseUrl ) -{ - if(fileHash.isNull() || !fileSize || fileName.empty()) - return std::errc::invalid_argument; - - DirDetails tDirDet; - tDirDet.type = DIR_TYPE_FILE; - tDirDet.name = fileName; - tDirDet.hash = fileHash; - tDirDet.size = fileSize; - - return dirDetailsToLink(link, tDirDet, fragSneak, baseUrl); -} - -std::error_condition ftServer::parseFilesLink( - const std::string& link, RsFileTree& collection ) -{ - RsUrl tUrl(link); - - { - /* Handle retrocompatibility with old stile single file links - * retroshare://file?name=$FILE_NAME&size=$FILE_SIZE&hash=$FILE_HASH - */ - if( tUrl.scheme() == "retroshare" && tUrl.host() == "file" - && tUrl.hasQueryK("name") && !tUrl.getQueryV("name")->empty() - && tUrl.hasQueryK("size") && !tUrl.getQueryV("size")->empty() - && tUrl.hasQueryK("hash") && !tUrl.getQueryV("hash")->empty() ) - { - DirDetails dt; - dt.type = DIR_TYPE_FILE; - dt.hash = RsFileHash(*tUrl.getQueryV("hash")); - dt.name = *tUrl.getQueryV("name"); - try - { - dt.size = std::stoull(*tUrl.getQueryV("size")); - std::unique_ptr ft; - if( !dt.hash.isNull() && - (ft = RsFileTree::fromDirDetails(dt, true)) ) - { - collection = *ft; - return std::error_condition(); - } - } - catch (...) {} - } - } - - { - /* Handle retrocompatibility with old stile collection links - * retroshare://collection?name=$NAME&size=$SIZE&radix=$RADIX&files=$COUNT - */ - if( tUrl.scheme() == "retroshare" && tUrl.host() == "collection" - && tUrl.hasQueryK("name") && !tUrl.getQueryV("name")->empty() - && tUrl.hasQueryK("size") && !tUrl.getQueryV("size")->empty() - && tUrl.hasQueryK("radix") && !tUrl.getQueryV("radix")->empty() - && tUrl.hasQueryK("files") && !tUrl.getQueryV("files")->empty() ) - { - try - { - // Don't need the values just check they are valid numbers - std::stoull(*tUrl.getQueryV("size")); - std::stoull(*tUrl.getQueryV("files")); - - auto ft = RsFileTree::fromRadix64(*tUrl.getQueryV("radix")); - if(ft) - { - collection = *ft; - return std::error_condition(); - } - } - catch (...) {} - } - } - - // Finaly handle the new files link format - rs_view_ptr radixPtr = - tUrl.getQueryV(FILES_URL_DATA_FIELD); - if(!radixPtr) radixPtr = &link; - else if(*radixPtr == FILES_URL_FAGMENT_FORWARD) radixPtr = &tUrl.fragment(); - - std::unique_ptr tft; std::error_condition ec; - std::tie(tft, ec) = RsFileTree::fromBase64(*radixPtr); - if(tft) collection = *tft; - return ec; -} diff --git a/libretroshare/src/ft/ftserver.h b/libretroshare/src/ft/ftserver.h deleted file mode 100644 index f6cc4b44c..000000000 --- a/libretroshare/src/ft/ftserver.h +++ /dev/null @@ -1,439 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftserver.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef FT_SERVER_HEADER -#define FT_SERVER_HEADER - -/* - * ftServer. - * - * Top level File Transfer interface. - * (replaces old filedexserver) - * - * sets up the whole File Transfer class structure. - * sets up the File Indexing side of cache system too. - * - * provides rsFiles interface for external control. - * - */ - -#include -#include -#include -#include -#include - -#include "ft/ftdata.h" -#include "turtle/turtleclientservice.h" -#include "services/p3service.h" -#include "retroshare/rsfiles.h" -#include "rsitems/rsitem.h" -#include "serialiser/rsserial.h" -#include "pqi/pqi.h" -#include "pqi/p3cfgmgr.h" - -class p3ConnectMgr; -class p3FileDatabase; - -class ftFiStore; -class ftFiMonitor; - -class ftController; -class ftExtraList; -class ftFileSearch; - -class ftDataMultiplex; -class p3turtle; - -class p3PeerMgr; -class p3ServiceControl; -class p3FileDatabase; - -enum class RsFileItemType : uint8_t -{ - NONE = 0x00, /// Only to detect ununitialized - FILE_SEARCH_REQUEST = 0x57, - FILE_SEARCH_RESULT = 0x58 -}; - -struct RsFileItem : RsItem -{ - ~RsFileItem() override; - -protected: - RsFileItem(RsFileItemType subtype); -}; - -struct RsFileSearchRequestItem : RsFileItem -{ - RsFileSearchRequestItem() : RsFileItem(RsFileItemType::FILE_SEARCH_REQUEST) - { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_SEARCH_REQUEST); } - - std::string queryString; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { RS_SERIAL_PROCESS(queryString); } - - void clear() override; -}; - -struct RsFileSearchResultItem : RsFileItem -{ - RsFileSearchResultItem() : RsFileItem(RsFileItemType::FILE_SEARCH_RESULT) - { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_SEARCH_RESULT); } - - std::vector mResults; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { RS_SERIAL_PROCESS(mResults); } - - void clear() override; -}; - - -class ftServer : - public p3Service, public RsFiles, public ftDataSend, - public RsTurtleClientService, public RsServiceSerializer -{ - -public: - - /***************************************************************/ - /******************** Setup ************************************/ - /***************************************************************/ - - ftServer(p3PeerMgr *peerMgr, p3ServiceControl *serviceCtrl); - virtual RsServiceInfo getServiceInfo(); - - /* Assign important variables */ - void setConfigDirectory(std::string path); - - /* add Config Items (Extra, Controller) */ - void addConfigComponents(p3ConfigMgr *mgr); - - const RsPeerId& OwnId(); - - /* Final Setup (once everything is assigned) */ - void SetupFtServer() ; - virtual void connectToTurtleRouter(p3turtle *p) ; - virtual void connectToFileDatabase(p3FileDatabase *b); - - // Implements RsTurtleClientService - // - - uint16_t serviceId() const { return RS_SERVICE_TYPE_FILE_TRANSFER ; } - virtual bool handleTunnelRequest(const RsFileHash& hash,const RsPeerId& peer_id) ; - virtual void receiveTurtleData(const RsTurtleGenericTunnelItem *item,const RsFileHash& hash,const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ; - - /// We keep this for retro-compatibility @see RsTurtleClientService - virtual void ftReceiveSearchResult(RsTurtleFTSearchResultItem *item); - - /// @see RsTurtleClientService - bool receiveSearchRequest( - unsigned char* searchRequestData, uint32_t searchRequestDataLen, - unsigned char*& search_result_data, uint32_t& searchResultDataLen, - uint32_t& maxAllowsHits ) override; - - /// @see RsTurtleClientService - void receiveSearchResult( - TurtleSearchRequestId requestId, unsigned char* searchResultData, - uint32_t searchResultDataLen ) override; - - virtual RsItem *create_item(uint16_t service,uint8_t item_type) const ; - virtual RsServiceSerializer *serializer() { return this ; } - - void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ; - void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ; - - /***************************************************************/ - /*************** Control Interface *****************************/ - /************** (Implements RsFiles) ***************************/ - /***************************************************************/ - - void StartupThreads(); - void StopThreads(); - - // member access - - ftDataMultiplex *getMultiplexer() const { return mFtDataplex ; } - ftController *getController() const { return mFtController ; } - - /** - * @see RsFiles::getFileData - */ - bool getFileData(const RsFileHash& hash, uint64_t offset, uint32_t& requested_size,uint8_t *data); - - /*** - * Control of Downloads - ***/ - virtual bool alreadyHaveFile(const RsFileHash& hash, FileInfo &info); - virtual bool FileRequest(const std::string& fname, const RsFileHash& hash, uint64_t size, const std::string& dest, TransferRequestFlags flags, const std::list& srcIds); - virtual bool FileCancel(const RsFileHash& hash); - virtual bool FileControl(const RsFileHash& hash, uint32_t flags); - virtual bool FileClearCompleted(); - virtual bool setDestinationDirectory(const RsFileHash& hash,const std::string& new_path) ; - virtual bool setDestinationName(const RsFileHash& hash,const std::string& new_name) ; - virtual bool setChunkStrategy(const RsFileHash& hash,FileChunksInfo::ChunkStrategy s) ; - virtual void setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy) ; - virtual FileChunksInfo::ChunkStrategy defaultChunkStrategy() ; - virtual uint32_t freeDiskSpaceLimit() const ; - virtual void setFreeDiskSpaceLimit(uint32_t size_in_mb) ; - virtual void setDefaultEncryptionPolicy(uint32_t policy) ; // RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT/PERMISSIVE - virtual uint32_t defaultEncryptionPolicy() ; - virtual void setMaxUploadSlotsPerFriend(uint32_t n) ; - virtual uint32_t getMaxUploadSlotsPerFriend() ; - virtual void setFilePermDirectDL(uint32_t perm) ; - virtual uint32_t filePermDirectDL() ; - - /// @see RsFiles - std::error_condition requestFiles( - const RsFileTree& collection, - const std::string& destPath = "", - const std::vector& srcIds = std::vector(), - FileRequestFlags flags = FileRequestFlags::ANONYMOUS_ROUTING - ) override; - - /// @see RsFiles - bool turtleSearchRequest( - const std::string& matchString, - const std::function& results)>& multiCallback, - rstime_t maxWait = 300 ) override; - - virtual TurtleSearchRequestId turtleSearch(const std::string& string_to_match) ; - virtual TurtleSearchRequestId turtleSearch(const RsRegularExpression::LinearizedExpression& expr) ; - - /// @see RsFiles - std::error_condition exportCollectionLink( - std::string& link, uint64_t handle, bool fragSneak = false, - const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL - ) override; - - /// @see RsFiles - std::error_condition exportFileLink( - std::string& link, const RsFileHash& fileHash, uint64_t fileSize, - const std::string& fileName, bool fragSneak = false, - const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL - ) override; - - /// @see RsFiles - std::error_condition parseFilesLink( - const std::string& link, RsFileTree& collection ) override; - - /*** - * Control of Downloads Priority. - ***/ - virtual uint32_t getQueueSize() ; - virtual void setQueueSize(uint32_t s) ; - virtual bool changeQueuePosition(const RsFileHash& hash, QueueMove queue_mv); - virtual bool changeDownloadSpeed(const RsFileHash& hash, int speed); - virtual bool getDownloadSpeed(const RsFileHash& hash, int & speed); - virtual bool clearDownload(const RsFileHash& hash); - //virtual void getDwlDetails(std::list & details); - - /*** - * Download/Upload Details - ***/ - virtual void FileDownloads(std::list &hashs); - virtual bool FileUploads(std::list &hashs); - virtual bool FileDetails(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info); - virtual bool FileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo& info) ; - virtual bool FileUploadChunksDetails(const RsFileHash& hash,const RsPeerId& peer_id,CompressedChunkMap& map) ; - virtual bool isEncryptedSource(const RsPeerId& virtual_peer_id) ; - - - /*** - * Extra List Access - ***/ - 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 ExtraFileHash(std::string localpath, rstime_t period, TransferRequestFlags flags); - virtual bool ExtraFileStatus(std::string localpath, FileInfo &info); - virtual bool ExtraFileMove(std::string fname, const RsFileHash& hash, uint64_t size, std::string destpath); - - - /*** - * Directory Listing / Search Interface - ***/ - virtual int RequestDirDetails(void *ref, DirDetails &details, FileSearchFlags flags); - - /// @see RsFiles::RequestDirDetails - virtual bool requestDirDetails( - DirDetails &details, uint64_t handle = 0, - FileSearchFlags flags = RS_FILE_HINTS_LOCAL ); - - virtual bool findChildPointer(void *ref, int row, void *& result, FileSearchFlags flags) ; - virtual uint32_t getType(void *ref,FileSearchFlags flags) ; - - virtual int SearchKeywords(std::list keywords, std::list &results,FileSearchFlags flags); - virtual int SearchKeywords(std::list keywords, std::list &results,FileSearchFlags flags,const RsPeerId& peer_id); - virtual int SearchBoolExp(RsRegularExpression::Expression * exp, std::list &results,FileSearchFlags flags); - virtual int SearchBoolExp(RsRegularExpression::Expression * exp, std::list &results,FileSearchFlags flags,const RsPeerId& peer_id); - virtual int getSharedDirStatistics(const RsPeerId& pid, SharedDirStats& stats) ; - - virtual int banFile(const RsFileHash& real_file_hash, const std::string& filename, uint64_t file_size) ; - virtual int unbanFile(const RsFileHash& real_file_hash); - virtual bool getPrimaryBannedFilesList(std::map& banned_files) ; - virtual bool isHashBanned(const RsFileHash& hash); - - /*** - * Utility Functions - ***/ - virtual bool ConvertSharedFilePath(std::string path, std::string &fullpath); - virtual void ForceDirectoryCheck(bool add_safe_delay); - virtual void updateSinceGroupPermissionsChanged() ; - virtual bool InDirectoryCheck(); - virtual bool copyFile(const std::string& source, const std::string& dest); - - /*** - * Directory Handling - ***/ - virtual void requestDirUpdate(void *ref) ; // triggers the update of the given reference. Used when browsing. - virtual bool setDownloadDirectory(const std::string& path); - virtual bool setPartialsDirectory(const std::string& path); - virtual std::string getDownloadDirectory(); - virtual std::string getPartialsDirectory(); - - virtual bool getSharedDirectories(std::list &dirs); - virtual bool setSharedDirectories(const std::list &dirs); - virtual bool addSharedDirectory(const SharedDirInfo& dir); - virtual bool updateShareFlags(const SharedDirInfo& dir); // updates the flags. The directory should already exist ! - virtual bool removeSharedDirectory(std::string dir); - - virtual bool getIgnoreLists(std::list& ignored_prefixes, std::list& ignored_suffixes, uint32_t& ignore_flags) ; - virtual void setIgnoreLists(const std::list& ignored_prefixes, const std::list& ignored_suffixes,uint32_t ignore_flags) ; - - virtual bool getShareDownloadDirectory(); - virtual bool shareDownloadDirectory(bool share); - - virtual void setWatchPeriod(int minutes) ; - virtual int watchPeriod() const ; - virtual void setWatchEnabled(bool b) ; - virtual bool watchEnabled() ; - virtual bool followSymLinks() const; - virtual void setFollowSymLinks(bool b); - virtual void togglePauseHashingProcess(); - virtual bool hashingProcessPaused(); - - virtual void setMaxShareDepth(int depth) ; - virtual int maxShareDepth() const; - - virtual bool ignoreDuplicates() ; - virtual void setIgnoreDuplicates(bool ignore) ; - - static bool encryptHash(const RsFileHash& hash, RsFileHash& hash_of_hash); - - /***************************************************************/ - /*************** Data Transfer Interface ***********************/ - /***************************************************************/ -public: - virtual bool activateTunnels(const RsFileHash& hash,uint32_t default_encryption_policy,TransferRequestFlags flags,bool onoff); - - virtual bool sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); - virtual bool sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize); - virtual bool sendChunkMapRequest(const RsPeerId& peer_id,const RsFileHash& hash,bool is_client) ; - virtual bool sendChunkMap(const RsPeerId& peer_id,const RsFileHash& hash,const CompressedChunkMap& cmap,bool is_client) ; - virtual bool sendSingleChunkCRCRequest(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_number) ; - virtual bool sendSingleChunkCRC(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_number,const Sha1CheckSum& crc) ; - - static void deriveEncryptionKey(const RsFileHash& hash, uint8_t *key); - - bool encryptItem(RsTurtleGenericTunnelItem *clear_item,const RsFileHash& hash,RsTurtleGenericDataItem *& encrypted_item); - bool decryptItem(const RsTurtleGenericDataItem *encrypted_item, const RsFileHash& hash, RsTurtleGenericTunnelItem *&decrypted_item); - - /*************** Internal Transfer Fns *************************/ - virtual int tick(); - - /* Configuration */ - bool addConfiguration(p3ConfigMgr *cfgmgr); - bool ResumeTransfers(); - - /*************************** p3 Config Overload ********************/ - -protected: - int handleIncoming() ; - bool handleCacheData() ; - - /*! - * \brief sendTurtleItem - * Sends the given item into a turtle tunnel, possibly encrypting it if the type of tunnel requires it, which is known from the hash itself. - * \param peerId Peer id to send to (this is a virtual peer id from turtle service) - * \param hash hash of the file. If the item needs to be encrypted - * \param item item to send. - * \return - * true if everything goes right - */ - bool sendTurtleItem(const RsPeerId& peerId,const RsFileHash& hash,RsTurtleGenericTunnelItem *item); - - // fnds out what is the real hash of encrypted hash hash - bool findRealHash(const RsFileHash& hash, RsFileHash& real_hash); - bool findEncryptedHash(const RsPeerId& virtual_peer_id, RsFileHash& encrypted_hash); - - bool checkUploadLimit(const RsPeerId& pid,const RsFileHash& hash); - - std::error_condition dirDetailsToLink( - std::string& link, - const DirDetails& dirDetails, bool fragSneak, - const std::string& baseUrl ); - -private: - - /* no need for Mutex protection - - * as each component is protected independently. - */ - p3PeerMgr *mPeerMgr; - p3ServiceControl *mServiceCtrl; - p3FileDatabase *mFileDatabase ; - ftController *mFtController; - ftExtraList *mFtExtra; - ftDataMultiplex *mFtDataplex; - p3turtle *mTurtleRouter ; - ftFileSearch *mFtSearch; - - RsMutex srvMutex; - std::string mConfigPath; - std::string mDownloadPath; - std::string mPartialsPath; - - std::map mEncryptedHashes ; // This map is such that sha1(it->second) = it->first - std::map mEncryptedPeerIds ; // This map holds the hash to be used with each peer id - std::map > mUploadLimitMap ; - - /** Store search callbacks with timeout*/ - std::map< - TurtleRequestId, - std::pair< - std::function& results)>, - std::chrono::system_clock::time_point > - > mSearchCallbacksMap; - RsMutex mSearchCallbacksMapMutex; - - /// Cleanup mSearchCallbacksMap - void cleanTimedOutSearches(); - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; - - - -#endif diff --git a/libretroshare/src/ft/fttransfermodule.cc b/libretroshare/src/ft/fttransfermodule.cc deleted file mode 100644 index 8c6ae1f08..000000000 --- a/libretroshare/src/ft/fttransfermodule.cc +++ /dev/null @@ -1,923 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: fttransfermodule.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -/****** - * #define FT_DEBUG 1 - *****/ - -#include "util/rstime.h" - -#include "retroshare/rsturtle.h" -#include "fttransfermodule.h" - -/************************************************************************* - * Notes on file transfer strategy. - * Care must be taken not to overload pipe. best way is to time requests. - * and according adjust data rate. - * - * each peer gets a 'max_rate' which is decided on the type of transfer. - * - trickle ... - * - stream ... - * - max ... - * - * Each peer is independently managed. - * - * via the functions: - * - */ - -const double FT_TM_MAX_PEER_RATE = 100 * 1024 * 1024; /* 100MB/s */ -const uint32_t FT_TM_MAX_RESETS = 5; -const uint32_t FT_TM_MINIMUM_CHUNK = 1024; /* ie 1Kb / sec */ -const uint32_t FT_TM_DEFAULT_TRANSFER_RATE = 20*1024; /* ie 20 Kb/sec */ -const uint32_t FT_TM_RESTART_DOWNLOAD = 20; /* 20 seconds */ -const uint32_t FT_TM_DOWNLOAD_TIMEOUT = 10; /* 10 seconds */ - -const double FT_TM_RATE_INCREASE_SLOWER = 0.05 ; -const double FT_TM_RATE_INCREASE_AVERAGE = 0.3 ; -const double FT_TM_RATE_INCREASE_FASTER = 1.0 ; - -#define FT_TM_FLAG_DOWNLOADING 0 -#define FT_TM_FLAG_CANCELED 1 -#define FT_TM_FLAG_COMPLETE 2 -#define FT_TM_FLAG_CHECKING 3 -#define FT_TM_FLAG_CHUNK_CRC 4 - -peerInfo::peerInfo(const RsPeerId& peerId_in) - :peerId(peerId_in),state(PQIPEER_NOT_ONLINE),desiredRate(FT_TM_DEFAULT_TRANSFER_RATE),actualRate(FT_TM_DEFAULT_TRANSFER_RATE), - lastTS(0), - recvTS(0), lastTransfers(0), nResets(0), - rtt(0), rttActive(false), rttStart(0), rttOffset(0), - mRateIncrease(1) - { - } -// peerInfo(const RsPeerId& peerId_in,uint32_t state_in,uint32_t maxRate_in): -// peerId(peerId_in),state(state_in),desiredRate(maxRate_in),actualRate(0), -// lastTS(0), -// recvTS(0), lastTransfers(0), nResets(0), -// rtt(0), rttActive(false), rttStart(0), rttOffset(0), -// mRateIncrease(1) -// { -// return; -// } -ftTransferModule::ftTransferModule(ftFileCreator *fc, ftDataMultiplex *dm, ftController *c) - :mFileCreator(fc), mMultiplexor(dm), mFtController(c), tfMtx("ftTransferModule"), mFlag(FT_TM_FLAG_DOWNLOADING),mPriority(SPEED_NORMAL) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - - mHash = mFileCreator->getHash(); - mSize = mFileCreator->getFileSize(); - mFileStatus.hash = mHash; - - _hash_thread = NULL ; - - // Dummy for Testing (should be handled independantly for - // each peer. - //mChunkSize = 10000; - desiredRate = FT_TM_MAX_PEER_RATE; /* 1MB/s ??? */ - actualRate = 0; - - _last_activity_time_stamp = time(NULL) ; -} - -ftTransferModule::~ftTransferModule() -{ - // Prevents deletion while called from another thread. - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ -} - - -bool ftTransferModule::setFileSources(const std::list& peerIds) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - - mFileSources.clear(); - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::setFileSources()"; - std::cerr << " List of peers: " ; -#endif - - std::list::const_iterator it; - for(it = peerIds.begin(); it != peerIds.end(); ++it) - { - -#ifdef FT_DEBUG - std::cerr << " \t" << *it; -#endif - - peerInfo pInfo(*it); - mFileSources.insert(std::pair(*it,pInfo)); - } - -#ifdef FT_DEBUG - std::cerr << std::endl; -#endif - - return true; -} - -bool ftTransferModule::getFileSources(std::list &peerIds) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - std::map::iterator it; - for(it = mFileSources.begin(); it != mFileSources.end(); ++it) - { - peerIds.push_back(it->first); - } - return true; -} - -bool ftTransferModule::addFileSource(const RsPeerId& peerId) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - std::map::iterator mit; - mit = mFileSources.find(peerId); - - if (mit == mFileSources.end()) - { - /* add in new source */ - peerInfo pInfo(peerId); - mFileSources.insert(std::pair(peerId,pInfo)); - //mit = mFileSources.find(peerId); - - mMultiplexor->sendChunkMapRequest(peerId, mHash,false) ; -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::addFileSource()"; - std::cerr << " adding peer: " << peerId << " to sourceList"; - std::cerr << std::endl; -#endif - return true ; - - } - else - { -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::addFileSource()"; - std::cerr << " peer: " << peerId << " already there"; - std::cerr << std::endl; -#endif - return false; - } -} - -bool ftTransferModule::removeFileSource(const RsPeerId& peerId) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - std::map::iterator mit; - mit = mFileSources.find(peerId); - - if (mit != mFileSources.end()) - { - /* add in new source */ - mFileSources.erase(mit) ; -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::addFileSource(): removing peer: " << peerId << " from sourceList" << std::endl; -#endif - } -#ifdef FT_DEBUG - else - std::cerr << "ftTransferModule::addFileSource(): Should remove peer: " << peerId << ", but it's not in the source list. " << std::endl; -#endif - - return true; -} - -bool ftTransferModule::setPeerState(const RsPeerId& peerId,uint32_t state,uint32_t maxRate) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::setPeerState()"; - std::cerr << " peerId: " << peerId; - std::cerr << " state: " << state; - std::cerr << " maxRate: " << maxRate << std::endl; -#endif - - std::map::iterator mit; - mit = mFileSources.find(peerId); - - if (mit == mFileSources.end()) - { - /* add in new source */ - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::setPeerState()"; - std::cerr << " adding new peer to sourceList"; - std::cerr << std::endl; -#endif - return false; - } - - (mit->second).state=state; - (mit->second).desiredRate=maxRate; - // Start it off at zero.... - // (mit->second).actualRate=maxRate; /* should give big kick in right direction */ - - std::list::iterator it; - it = std::find(mOnlinePeers.begin(), mOnlinePeers.end(), peerId); - - if (state!=PQIPEER_NOT_ONLINE) - { - //change to online, add peerId in online peer list - if (it==mOnlinePeers.end()) mOnlinePeers.push_back(peerId); - } - else - { - //change to offline, remove peerId in online peer list - if (it!=mOnlinePeers.end()) mOnlinePeers.erase(it); - } - - return true; -} - - -bool ftTransferModule::getPeerState(const RsPeerId& peerId,uint32_t &state,uint32_t &tfRate) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - std::map::iterator mit; - mit = mFileSources.find(peerId); - - if (mit == mFileSources.end()) return false; - - state = (mit->second).state; - tfRate = (uint32_t) (mit->second).actualRate; - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::getPeerState()"; - std::cerr << " peerId: " << peerId; - std::cerr << " state: " << state; - std::cerr << " tfRate: " << tfRate << std::endl; -#endif - return true; -} - -uint32_t ftTransferModule::getDataRate(const RsPeerId& peerId) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - std::map::iterator mit; - mit = mFileSources.find(peerId); - if (mit == mFileSources.end()) - { -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::getDataRate()"; - std::cerr << " peerId: " << peerId; - std::cerr << " peer not exist in file sources " << std::endl; -#endif - return 0; - } - else - return (uint32_t) (mit->second).actualRate; -} -void ftTransferModule::resetActvTimeStamp() -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - _last_activity_time_stamp = time(NULL); -} -rstime_t ftTransferModule::lastActvTimeStamp() -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - return _last_activity_time_stamp ; -} - - //interface to client module -bool ftTransferModule::recvFileData(const RsPeerId& peerId, uint64_t offset, uint32_t chunk_size, void *data) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::recvFileData()"; - std::cerr << " peerId: " << peerId; - std::cerr << " offset: " << offset; - std::cerr << " chunksize: " << chunk_size; - std::cerr << " data: " << data; - std::cerr << std::endl; -#endif - - bool ok = false; - - std::map::iterator mit; - mit = mFileSources.find(peerId); - - if (mit == mFileSources.end()) - { -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::recvFileData()"; - std::cerr << " peer not found in sources"; - std::cerr << std::endl; -#endif - return false; - } - ok = locked_recvPeerData(mit->second, offset, chunk_size, data); - - locked_storeData(offset, chunk_size, data); - - _last_activity_time_stamp = time(NULL) ; - - free(data) ; - return ok; -} - -void ftTransferModule::locked_requestData(const RsPeerId& peerId, uint64_t offset, uint32_t chunk_size) -{ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::requestData()"; - std::cerr << " peerId: " << peerId; - std::cerr << " hash: " << mHash; - std::cerr << " size: " << mSize; - std::cerr << " offset: " << offset; - std::cerr << " chunk_size: " << chunk_size; - std::cerr << std::endl; -#endif - - mMultiplexor->sendDataRequest(peerId, mHash, mSize, offset,chunk_size); -} - -bool ftTransferModule::locked_getChunk(const RsPeerId& peer_id,uint32_t size_hint,uint64_t &offset, uint32_t &chunk_size) -{ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::locked_getChunk()"; - std::cerr << " hash: " << mHash; - std::cerr << " size: " << mSize; - std::cerr << " offset: " << offset; - std::cerr << " size_hint: " << size_hint; - std::cerr << " chunk_size: " << chunk_size; - std::cerr << std::endl; -#endif - - bool source_peer_map_needed ; - - bool val = mFileCreator->getMissingChunk(peer_id,size_hint,offset, chunk_size,source_peer_map_needed); - - if(source_peer_map_needed) - mMultiplexor->sendChunkMapRequest(peer_id, mHash,false) ; - -#ifdef FT_DEBUG - if (val) - { - std::cerr << "ftTransferModule::locked_getChunk()"; - std::cerr << " Answer: Chunk Available"; - std::cerr << " hash: " << mHash; - std::cerr << " size: " << mSize; - std::cerr << " offset: " << offset; - std::cerr << " chunk_size: " << chunk_size; - std::cerr << " peer map needed = " << source_peer_map_needed << std::endl ; - std::cerr << std::endl; - } - else - { - std::cerr << "ftTransferModule::locked_getChunk()"; - std::cerr << " Answer: No Chunk Available"; - std::cerr << " peer map needed = " << source_peer_map_needed << std::endl ; - std::cerr << std::endl; - } -#endif - - return val; -} - -bool ftTransferModule::locked_storeData(uint64_t offset, uint32_t chunk_size,void *data) -{ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::storeData()"; - std::cerr << " hash: " << mHash; - std::cerr << " size: " << mSize; - std::cerr << " offset: " << offset; - std::cerr << " chunk_size: " << chunk_size; - std::cerr << std::endl; -#endif - - return mFileCreator -> addFileData(offset, chunk_size, data); -} - -bool ftTransferModule::queryInactive() -{ - /* NB: Not sure about this lock... might cause deadlock. - */ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::queryInactive()" << std::endl; -#endif - - if (mFileStatus.stat == ftFileStatus::PQIFILE_INIT) - mFileStatus.stat = ftFileStatus::PQIFILE_DOWNLOADING; - - if (mFileStatus.stat != ftFileStatus::PQIFILE_DOWNLOADING) - { - if (mFileStatus.stat == ftFileStatus::PQIFILE_FAIL_CANCEL) - mFlag = FT_TM_FLAG_COMPLETE; //file canceled by user - return false; - } - - if (mFileStatus.stat == ftFileStatus::PQIFILE_CHECKING) - return false ; - - std::map::iterator mit; - for(mit = mFileSources.begin(); mit != mFileSources.end(); ++mit) - { - locked_tickPeerTransfer(mit->second); - } - if(mFileCreator->finished()) // transfer is complete - { - mFileStatus.stat = ftFileStatus::PQIFILE_CHECKING ; - mFlag = FT_TM_FLAG_CHECKING; - } - else - { - // request for CRCs to ask - std::vector chunks_to_ask ; - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::queryInactive() : getting chunks to check." << std::endl; -#endif - - mFileCreator->getChunksToCheck(chunks_to_ask) ; -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::queryInactive() : got " << chunks_to_ask.size() << " chunks." << std::endl; -#endif - - mMultiplexor->sendSingleChunkCRCRequests(mHash,chunks_to_ask); - } - - return true; -} - -bool ftTransferModule::cancelTransfer() -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - mFileStatus.stat=ftFileStatus::PQIFILE_FAIL_CANCEL; - - return 1; -} - -bool ftTransferModule::cancelFileTransferUpward() -{ - if (mFtController) - mFtController->FileCancel(mHash); - return true; -} -bool ftTransferModule::completeFileTransfer() -{ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::completeFileTransfer()"; - std::cerr << std::endl; -#endif - if (mFtController) - mFtController->FlagFileComplete(mHash); - return true; -} - -int ftTransferModule::tick() -{ - queryInactive(); -#ifdef FT_DEBUG - { - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - - std::cerr << "ftTransferModule::tick()"; - std::cerr << " mFlag: " << mFlag; - std::cerr << " mHash: " << mHash; - std::cerr << " mSize: " << mSize; - std::cerr << std::endl; - - std::cerr << "Peers: "; - std::map::iterator it; - for(it = mFileSources.begin(); it != mFileSources.end(); ++it) - { - std::cerr << " " << it->first; - } - std::cerr << std::endl; - - - } -#endif - - uint32_t flags = 0; - { - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - flags = mFlag; - } - - switch (flags) - { - case FT_TM_FLAG_DOWNLOADING: //file transfer not complete - adjustSpeed(); - break; - case FT_TM_FLAG_COMPLETE: //file transfer complete - completeFileTransfer(); - break; - case FT_TM_FLAG_CANCELED: //file transfer canceled - break; - case FT_TM_FLAG_CHECKING: // Check if file hash matches the hashed data - checkFile() ; - break ; - default: - break; - } - - return 0; -} - -bool ftTransferModule::isCheckingHash() -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ -#ifdef FT_DEBUG - std::cerr << "isCheckingHash(): mFlag=" << mFlag << std::endl; -#endif - return mFlag == FT_TM_FLAG_CHECKING || mFlag == FT_TM_FLAG_CHUNK_CRC; -} - -class HashThread: public RsThread -{ - public: - explicit HashThread(ftFileCreator *m) - : _hashThreadMtx("HashThread"), _m(m),_finished(false),_hash("") {} - - virtual void run() - { -#ifdef FT_DEBUG - std::cerr << "hash thread is running for file " << std::endl; -#endif - RsFileHash tmphash ; - _m->hashReceivedData(tmphash) ; - - RsStackMutex stack(_hashThreadMtx) ; - _hash = tmphash ; - _finished = true ; - } - RsFileHash hash() - { - RsStackMutex stack(_hashThreadMtx) ; - return _hash ; - } - bool finished() - { - RsStackMutex stack(_hashThreadMtx) ; - return _finished ; - } - private: - RsMutex _hashThreadMtx ; - ftFileCreator *_m ; - bool _finished ; - RsFileHash _hash ; -}; - -bool ftTransferModule::checkFile() -{ - { - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::checkFile(): checking File " << mHash << std::endl ; -#endif - - // if we don't have a hashing thread, create one. - - if(_hash_thread == NULL) - { - // Note: using new is really important to avoid copy and write errors in the thread. - // - _hash_thread = new HashThread(mFileCreator) ; - _hash_thread->start("ft hash") ; -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::checkFile(): launched hashing thread for file " << mHash << std::endl ; -#endif - return false ; - } - - if(!_hash_thread->finished()) - { -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::checkFile(): file " << mHash << " is being hashed.?" << std::endl ; -#endif - return false ; - } - - RsFileHash check_hash( _hash_thread->hash() ) ; - - delete _hash_thread ; - _hash_thread = NULL ; - - if(check_hash == mHash) - { - mFlag = FT_TM_FLAG_COMPLETE ; // Transfer is complete. -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::checkFile(): hash finished. File verification complete ! Setting mFlag to 1" << std::endl ; -#endif - return true ; - } - } - - - forceCheck() ; - return false ; -} - -void ftTransferModule::forceCheck() -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::forceCheck(): setting flags to force check." << std::endl ; -#endif - - mFileCreator->forceCheck() ; - mFlag = FT_TM_FLAG_DOWNLOADING ; // Ask for CRC map. - mFileStatus.stat = ftFileStatus::PQIFILE_DOWNLOADING; -} - -void ftTransferModule::adjustSpeed() -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - - std::map::iterator mit; - - - actualRate = 0; - for(mit = mFileSources.begin(); mit != mFileSources.end(); ++mit) - { -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::adjustSpeed()"; - std::cerr << "Peer: " << mit->first; - std::cerr << " Desired Rate: " << (mit->second).desiredRate; - std::cerr << " Actual Rate: " << (mit->second).actualRate; - std::cerr << std::endl; -#endif - actualRate += mit->second.actualRate; - } - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::adjustSpeed() Totals:"; - std::cerr << "Desired Rate: " << desiredRate << " Actual Rate: " << actualRate; - std::cerr << std::endl; -#endif - - return; -} - - -/******************************************************************************* - * Actual Peer Transfer Management Code. - * - * request very tick, at rate - * - * - **/ - - -/* NOTEs on this function... - * 1) This is the critical function for deciding the rate at which ft takes place. - * 2) Some of the peers might not have the file... care must be taken avoid deadlock. - * - * Eg. A edge case which fails badly. - * Small 1K file (one chunk), with 3 sources (A,B,C). A doesn't have file. - * (a) request data from A. B & C pause cos no more data needed. - * (b) all timeout, chunk reset... then back to request again (a) and repeat. - * (c) all timeout x 5 and are disabled.... no transfer, while B&C had it all the time. - * - * To solve this we might need random waiting periods, so each peer can - * be tried. - * - * - */ - -bool ftTransferModule::locked_tickPeerTransfer(peerInfo &info) -{ - /* how long has it been? */ - rstime_t ts = time(NULL); - - int ageRecv = ts - info.recvTS; - int ageReq = ts - info.lastTS; - - /* if offline - ignore */ - if(info.state == PQIPEER_SUSPEND) - return false; - - if (ageReq > (int) (FT_TM_RESTART_DOWNLOAD * (info.nResets + 1))) - { - // The succession of ifs, makes the process continue every 6 * FT_TM_RESTART_DOWNLOAD * FT_TM_MAX_RESETS seconds - // on average, which is one attempt every 600 seconds in the least, which corresponds to once every 10 minutes in - // average. - // - if (info.nResets > 1) /* 3rd timeout */ - { - /* 90% chance of return false... - * will mean variations in which peer - * starts first. hopefully stop deadlocks. - */ - if (rand() % 12 != 0) - return false; - } - - info.state = PQIPEER_DOWNLOADING; - info.recvTS = ts; /* reset to activate */ - info.nResets = std::min(FT_TM_MAX_RESETS,info.nResets + 1); - ageRecv = 0; - } - - if (ageRecv > (int) FT_TM_DOWNLOAD_TIMEOUT) - { - info.state = PQIPEER_IDLE; - return false; - } -#ifdef FT_DEBUG - std::cerr << "locked_tickPeerTransfer() actual rate (before): " << info.actualRate << ", lastTransfers=" << info.lastTransfers << std::endl ; - std::cerr << mHash<< " - actual rate: " << info.actualRate << " lastTransfers=" << info.lastTransfers << ". AgeReq = " << ageReq << std::endl; -#endif - /* update rate */ - - if( (info.lastTransfers > 0 && ageReq > 0) || ageReq > 2) - { - info.actualRate = info.actualRate * 0.75 + 0.25 * info.lastTransfers / (float)ageReq; - info.lastTransfers = 0; - info.lastTS = ts; - } - - /**************** - * NOTE: If we continually increase the request rate thus: ... - * uint32_t next_req = info.actualRate * 1.25; - * - * then we will achieve max data rate, but we will fill up - * peers out queue and/or network buffers..... - * - * we must therefore monitor the RTT to tell us if this is happening. - */ - - /* emergency shutdown if we are stuck in x 1.25 mode - * probably not needed - */ - -// csoler: I commented this out because that tends to make some sources -// get stuck into minimal 128 B/s rate, when multiple sources are competiting into the -// same limited bandwidth. I don't think this emergency shutdown is necessary anyway. -// -// if ((info.rttActive) && (ts - info.rttStart > FT_TM_SLOW_RTT)) -// { -// if (info.mRateIncrease > 0) -// { -//#ifdef FT_DEBUG -// std::cerr << "!!! - Emergency shutdown because rttActive is true, and age is " << ts - info.rttStart << std::endl ; -//#endif -// info.mRateIncrease = 0; -// info.rttActive = false ; // I've added this to avoid being stuck when rttActive is true -// } -// } - - /* request at more than current rate */ - uint32_t next_req = info.actualRate * (1.0 + info.mRateIncrease); -#ifdef FT_DEBUG - std::cerr << "locked_tickPeerTransfer() actual rate (after): " << actualRate - << " info.desiredRate=" << info.desiredRate - << " info.actualRate=" << info.actualRate - << ", next_req=" << next_req ; - - std::cerr << std::endl; -#endif - - if (next_req > info.desiredRate * 1.1) - { - next_req = info.desiredRate * 1.1; -#ifdef FT_DEBUG - std::cerr << "locked_tickPeerTransfer() Reached MaxRate: next_req: " << next_req; - std::cerr << std::endl; -#endif - } - - - if (next_req > FT_TM_MAX_PEER_RATE) - { - next_req = FT_TM_MAX_PEER_RATE; -#ifdef FT_DEBUG - std::cerr << "locked_tickPeerTransfer() Reached AbsMaxRate: next_req: " << next_req; - std::cerr << std::endl; -#endif - } - - - if (next_req < FT_TM_MINIMUM_CHUNK) - { - next_req = FT_TM_MINIMUM_CHUNK; -#ifdef FT_DEBUG - std::cerr << "locked_tickPeerTransfer() small chunk: next_req: " << next_req; - std::cerr << std::endl; -#endif - } - -#ifdef FT_DEBUG - std::cerr << "locked_tickPeerTransfer() desired next_req: " << next_req; - std::cerr << std::endl; -#endif - - /* do request */ - uint64_t req_offset = 0; - uint32_t req_size =0 ; - - // Loop over multiple calls to the file creator: for some reasons the file creator might not be able to - // give a plain chunk of the requested size (size hint larger than the fixed chunk size, priority given to - // an old pending chunk, etc). - // - while(next_req > 0 && locked_getChunk(info.peerId,next_req,req_offset,req_size)) - if(req_size > 0) - { - info.state = PQIPEER_DOWNLOADING; - locked_requestData(info.peerId,req_offset,req_size); - - /* start next rtt measurement */ - if (!info.rttActive) - { - info.rttStart = ts; - info.rttActive = true; - info.rttOffset = req_offset + req_size; - } - next_req -= std::min(req_size,next_req) ; - } - else - { - std::cerr << "transfermodule::Waiting for available data"; - std::cerr << std::endl; - break ; - } - - return true; -} - - - - //interface to client module -bool ftTransferModule::locked_recvPeerData(peerInfo &info, uint64_t offset, uint32_t chunk_size, void *) -{ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::locked_recvPeerData()"; - std::cerr << " peerId: " << info.peerId; - std::cerr << " rttOffset: " << info.rttOffset; - std::cerr << " lastTransfers: " << info.lastTransfers; - std::cerr << " offset: " << offset; - std::cerr << " chunksize: " << chunk_size; - std::cerr << std::endl; -#endif - - rstime_t ts = time(NULL); - info.recvTS = ts; - info.nResets = 0; - info.state = PQIPEER_DOWNLOADING; - info.lastTransfers += chunk_size; - - if ((info.rttActive) && (info.rttOffset == offset + chunk_size)) - { - /* update tip */ - int32_t rtt = time(NULL) - info.rttStart; - - /* - * FT_TM_FAST_RTT = 1 sec. mRateIncrease = 1.00 - * FT_TM_SLOW_RTT =20 sec. mRateIncrease = 0 - * 11 sec. mRateIncrease = -0.25 - * if it is slower than this allow fast data increase. - * initial guess - linear with rtt. - * change if this leads to wild oscillations - * - */ - -// info.mRateIncrease = (FT_TM_SLOW_RTT - rtt) * -// (FT_TM_MAX_INCREASE / (FT_TM_SLOW_RTT - FT_TM_FAST_RTT)); -// -// if (info.mRateIncrease > FT_TM_MAX_INCREASE) -// info.mRateIncrease = FT_TM_MAX_INCREASE; -// -// if (info.mRateIncrease < FT_TM_MIN_INCREASE) -// info.mRateIncrease = FT_TM_MIN_INCREASE; - - switch(mPriority) - { - case SPEED_LOW : info.mRateIncrease = FT_TM_RATE_INCREASE_SLOWER ; break ; - case SPEED_NORMAL : info.mRateIncrease = FT_TM_RATE_INCREASE_AVERAGE; break ; - case SPEED_HIGH : info.mRateIncrease = FT_TM_RATE_INCREASE_FASTER ; break ; - } - info.rtt = rtt; - info.rttActive = false; - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::locked_recvPeerData()"; - std::cerr << "Updated Rate based on RTT: " << rtt; - std::cerr << " Rate increase: " << 1.0+info.mRateIncrease; - std::cerr << std::endl; -#endif - - } - return true; -} - diff --git a/libretroshare/src/ft/fttransfermodule.h b/libretroshare/src/ft/fttransfermodule.h deleted file mode 100644 index 29766dbad..000000000 --- a/libretroshare/src/ft/fttransfermodule.h +++ /dev/null @@ -1,189 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: fttransfermodule.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef FT_TRANSFER_MODULE_HEADER -#define FT_TRANSFER_MODULE_HEADER - -/* - * FUNCTION DESCRIPTION - * - * Each Transfer Module is paired up with a single File Creator, and responsible for the transfer of one file. - * The Transfer Module is responsible for sending requests to peers at the correct data rates, and storing the returned data - * in a FileCreator. - * There are multiple Transfer Modules in the File Transfer system. Their requests are multiplexed through the Client Module. * The Transfer Module contains all the algorithms for sensible Data Requests. - * It must be able to cope with varying data rates and dropped peers without flooding the system with too many requests. - * - */ - -#include -#include -#include - -#include "ft/ftfilecreator.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftcontroller.h" - -#include "util/rsthreads.h" - -const uint32_t PQIPEER_INIT = 0x0000; -const uint32_t PQIPEER_NOT_ONLINE = 0x0001; -const uint32_t PQIPEER_DOWNLOADING = 0x0002; -const uint32_t PQIPEER_IDLE = 0x0004; -const uint32_t PQIPEER_SUSPEND = 0x0010; - -class HashThread ; - -class peerInfo -{ -public: - explicit peerInfo(const RsPeerId& peerId_in); - -// peerInfo(const RsPeerId& peerId_in,uint32_t state_in,uint32_t maxRate_in): -// peerId(peerId_in),state(state_in),desiredRate(maxRate_in),actualRate(0), -// lastTS(0), -// recvTS(0), lastTransfers(0), nResets(0), -// rtt(0), rttActive(false), rttStart(0), rttOffset(0), -// mRateIncrease(1) -// { -// return; -// } - RsPeerId peerId; - uint32_t state; - double desiredRate; /* speed at which the data should be requested */ - double actualRate; /* actual speed at which the data is received */ - - rstime_t lastTS; /* last Request */ - rstime_t recvTS; /* last Recv */ - uint32_t lastTransfers; /* data recvd in last second */ - uint32_t nResets; /* count to disable non-existant files */ - - uint32_t rtt; /* last rtt */ - bool rttActive; /* have we initialised an rtt measurement */ - rstime_t rttStart; /* ts of request */ - uint64_t rttOffset; /* end of request */ - float mRateIncrease; /* current rate increase factor */ -}; - -class ftFileStatus -{ -public: - enum Status { - PQIFILE_INIT, - PQIFILE_NOT_ONLINE, - PQIFILE_DOWNLOADING, - PQIFILE_COMPLETE, - PQIFILE_CHECKING, - PQIFILE_FAIL, - PQIFILE_FAIL_CANCEL, - PQIFILE_FAIL_NOT_AVAIL, - PQIFILE_FAIL_NOT_OPEN, - PQIFILE_FAIL_NOT_SEEK, - PQIFILE_FAIL_NOT_WRITE, - PQIFILE_FAIL_NOT_READ, - PQIFILE_FAIL_BAD_PATH - }; - - ftFileStatus():hash(""),stat(PQIFILE_INIT) {} - explicit ftFileStatus(const RsFileHash& hash_in):hash(hash_in),stat(PQIFILE_INIT) {} - - RsFileHash hash; - Status stat; -}; - -class ftTransferModule -{ -public: - ftTransferModule(ftFileCreator *fc, ftDataMultiplex *dm, ftController *c); - ~ftTransferModule(); - - //interface to download controller - bool setFileSources(const std::list& peerIds); - bool addFileSource(const RsPeerId& peerId); - bool removeFileSource(const RsPeerId& peerId); - bool setPeerState(const RsPeerId& peerId,uint32_t state,uint32_t maxRate); //state = ONLINE/OFFLINE - bool getFileSources(std::list &peerIds); - bool getPeerState(const RsPeerId& peerId,uint32_t &state,uint32_t &tfRate); - uint32_t getDataRate(const RsPeerId& peerId); - bool cancelTransfer(); - bool cancelFileTransferUpward(); - bool completeFileTransfer(); - bool isCheckingHash() ; - void forceCheck() ; - - //interface to multiplex module - bool recvFileData(const RsPeerId& peerId, uint64_t offset, uint32_t chunk_size, void *data); - void locked_requestData(const RsPeerId& peerId, uint64_t offset, uint32_t chunk_size); - - //interface to file creator - bool locked_getChunk(const RsPeerId& peer_id,uint32_t size_hint,uint64_t &offset, uint32_t &chunk_size); - bool locked_storeData(uint64_t offset, uint32_t chunk_size, void *data); - - int tick(); - - const RsFileHash& hash() const { return mHash; } - uint64_t size() const { return mSize; } - - //internal used functions - bool queryInactive(); - void adjustSpeed(); - - DwlSpeed downloadPriority() const { return mPriority ; } - void setDownloadPriority(DwlSpeed p) { mPriority =p ; } - - // read/reset the last time the transfer module was active (either wrote data, or was solicitaded by clients) - rstime_t lastActvTimeStamp() ; - void resetActvTimeStamp() ; - -private: - - bool locked_tickPeerTransfer(peerInfo &info); - bool locked_recvPeerData(peerInfo &info, uint64_t offset, - uint32_t chunk_size, void *data); - - bool checkFile() ; - bool checkCRC() ; - - /* These have independent Mutexes / are const locally (no Mutex protection)*/ - ftFileCreator *mFileCreator; - ftDataMultiplex *mMultiplexor; - ftController *mFtController; - - RsFileHash mHash; - uint64_t mSize; - - RsMutex tfMtx; /* below is mutex protected */ - - std::list mOnlinePeers; - std::map mFileSources; - - uint16_t mFlag; //2:file canceled, 1:transfer complete, 0: not complete, 3: checking hash, 4: checking chunks - double desiredRate; - double actualRate; - - rstime_t _last_activity_time_stamp ; - - ftFileStatus mFileStatus; //used for pause/resume file transfer - - HashThread *_hash_thread ; - DwlSpeed mPriority ; // transfer speed priority -}; - -#endif //FT_TRANSFER_MODULE_HEADER diff --git a/libretroshare/src/ft/ftturtlefiletransferitem.cc b/libretroshare/src/ft/ftturtlefiletransferitem.cc deleted file mode 100644 index 14150e42d..000000000 --- a/libretroshare/src/ft/ftturtlefiletransferitem.cc +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftturtlefiletransferitem.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include - -#include -#include -#include - -#include - -void RsTurtleFileMapRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,direction,"direction") ; -} - -void RsTurtleFileMapItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,direction,"direction") ; - RsTypeSerializer::serial_process (j,ctx,compressed_map._map,"map") ; -} -void RsTurtleChunkCrcRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,chunk_number,"chunk_number") ; -} -void RsTurtleChunkCrcItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,chunk_number,"chunk_number") ; - RsTypeSerializer::serial_process (j,ctx,check_sum,"check_sum") ; -} - -void RsTurtleFileRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,chunk_offset,"chunk_offset") ; - RsTypeSerializer::serial_process(j,ctx,chunk_size,"chunk_size") ; -} -void RsTurtleFileDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,chunk_offset,"chunk_offset") ; - - RsTypeSerializer::TlvMemBlock_proxy prox(chunk_data,chunk_size) ; - - RsTypeSerializer::serial_process(j,ctx,prox,"chunk_data") ; -} - diff --git a/libretroshare/src/ft/ftturtlefiletransferitem.h b/libretroshare/src/ft/ftturtlefiletransferitem.h deleted file mode 100644 index 6bbc24aef..000000000 --- a/libretroshare/src/ft/ftturtlefiletransferitem.h +++ /dev/null @@ -1,122 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftturtlefiletransferitem.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include - -/***********************************************************************************/ -/* Turtle File Transfer item classes */ -/***********************************************************************************/ - -class RsTurtleFileRequestItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleFileRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_REQUEST), chunk_offset(0), chunk_size(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_REQUEST);} - - virtual bool shouldStampTunnel() const { return false ; } - virtual Direction travelingDirection() const { return DIRECTION_SERVER ; } - - uint64_t chunk_offset ; - uint32_t chunk_size ; - - void clear() {} - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleFileDataItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleFileDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_DATA), chunk_offset(0), chunk_size(0), chunk_data(NULL) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_DATA) ;} - ~RsTurtleFileDataItem() { clear() ; } - - virtual bool shouldStampTunnel() const { return true ; } - virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; } - - void clear() - { - free(chunk_data); - chunk_data = NULL ; - chunk_size = 0 ; - chunk_offset = 0 ; - } - - uint64_t chunk_offset ; // offset in the file - uint32_t chunk_size ; // size of the file chunk - void *chunk_data ; // actual data. - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleFileMapRequestItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleFileMapRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP_REQUEST) ;} - - virtual bool shouldStampTunnel() const { return false ; } - - void clear() {} - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleFileMapItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleFileMapItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP) ;} - - virtual bool shouldStampTunnel() const { return false ; } - - CompressedChunkMap compressed_map ; // Map info for the file in compressed format. Each *bit* in the array uint's says "I have" or "I don't have" - // by default, we suppose the peer has all the chunks. This info will thus be and-ed - // with the default file map for this source. - - void clear() { compressed_map._map.clear() ;} - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleChunkCrcRequestItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleChunkCrcRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST), chunk_number(0) { setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC_REQUEST);} - - virtual bool shouldStampTunnel() const { return false ; } - virtual Direction travelingDirection() const { return DIRECTION_SERVER ; } - - uint32_t chunk_number ; // id of the chunk to CRC. - - void clear() {} - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleChunkCrcItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleChunkCrcItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC), chunk_number(0) { setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC);} - - virtual bool shouldStampTunnel() const { return true ; } - virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; } - - uint32_t chunk_number ; - Sha1CheckSum check_sum ; - - void clear() { check_sum.clear() ;} - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; diff --git a/libretroshare/src/gossipdiscovery/gossipdiscoveryitems.cc b/libretroshare/src/gossipdiscovery/gossipdiscoveryitems.cc deleted file mode 100644 index 6f66684c9..000000000 --- a/libretroshare/src/gossipdiscovery/gossipdiscoveryitems.cc +++ /dev/null @@ -1,155 +0,0 @@ -/******************************************************************************* - * Gossip discovery service items * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2008 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#include "gossipdiscovery/gossipdiscoveryitems.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstypeserializer.h" -#include "serialiser/rsserializable.h" - -#include - -RsItem *RsDiscSerialiser::create_item( - uint16_t service, uint8_t item_subtype ) const -{ - if(service != RS_SERVICE_TYPE_DISC) return nullptr; - - switch(static_cast(item_subtype)) - { - case RsGossipDiscoveryItemType::PGP_LIST: return new RsDiscPgpListItem(); - case RsGossipDiscoveryItemType::PGP_CERT_BINARY: return new RsDiscPgpKeyItem(); - case RsGossipDiscoveryItemType::PGP_CERT: return new RsDiscPgpCertItem(); // deprecated, hanlde to suppress "unkown item" warning - case RsGossipDiscoveryItemType::CONTACT: return new RsDiscContactItem(); - case RsGossipDiscoveryItemType::IDENTITY_LIST: return new RsDiscIdentityListItem(); - default: - return nullptr; - } - - return nullptr; -} - -/*************************************************************************/ - -void RsDiscPgpListItem::clear() -{ - mode = RsGossipDiscoveryPgpListMode::NONE; - pgpIdSet.TlvClear(); -} - -void RsDiscPgpListItem::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(mode); - RS_SERIAL_PROCESS(pgpIdSet); -} - -void RsDiscPgpKeyItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,pgpKeyId,"pgpKeyId") ; - - RsTypeSerializer::TlvMemBlock_proxy prox(bin_data,bin_len) ; - RsTypeSerializer::serial_process(j,ctx,prox,"keyData") ; -} - -void RsDiscPgpKeyItem::clear() -{ - pgpKeyId.clear(); - free(bin_data); - bin_data = nullptr; - bin_len = 0; -} - -void RsDiscContactItem::clear() -{ - pgpId.clear(); - sslId.clear(); - - location.clear(); - version.clear(); - - netMode = 0; - vs_disc = 0; - vs_dht = 0; - lastContact = 0; - - isHidden = false; - hiddenAddr.clear(); - hiddenPort = 0; - - localAddrV4.TlvClear(); - extAddrV4.TlvClear(); - localAddrV6.TlvClear(); - extAddrV6.TlvClear(); - - - dyndns.clear(); - - localAddrList.TlvClear(); - extAddrList.TlvClear(); -} - -void RsDiscContactItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,pgpId,"pgpId"); - RsTypeSerializer::serial_process (j,ctx,sslId,"sslId"); - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_LOCATION,location,"location"); - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_VERSION,version,"version"); - RsTypeSerializer::serial_process(j,ctx,netMode,"netMode"); - RsTypeSerializer::serial_process(j,ctx,vs_disc,"vs_disc"); - RsTypeSerializer::serial_process(j,ctx,vs_dht,"vs_dht"); - RsTypeSerializer::serial_process(j,ctx,lastContact,"lastContact"); - - // This is a hack. Normally we should have to different item types, in order to avoid this nonesense. - - if(j == RsGenericSerializer::DESERIALIZE) - isHidden = ( GetTlvType( &(((uint8_t *) ctx.mData)[ctx.mOffset]) )==TLV_TYPE_STR_DOMADDR); - - if(isHidden) - { - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_DOMADDR,hiddenAddr,"hiddenAddr"); - RsTypeSerializer::serial_process(j,ctx,hiddenPort,"hiddenPort"); - } - else - { - RsTypeSerializer::serial_process(j,ctx,localAddrV4,"localAddrV4"); - RsTypeSerializer::serial_process(j,ctx, extAddrV4,"extAddrV4"); - RsTypeSerializer::serial_process(j,ctx,localAddrV6,"localAddrV6"); - RsTypeSerializer::serial_process(j,ctx, extAddrV6,"extAddrV6"); - RsTypeSerializer::serial_process(j,ctx,currentConnectAddress,"currentConnectAddress"); - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_DYNDNS,dyndns,"dyndns"); - RsTypeSerializer::serial_process (j,ctx,localAddrList,"localAddrList"); - RsTypeSerializer::serial_process (j,ctx, extAddrList,"extAddrList"); - } -} - -void RsDiscIdentityListItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RS_SERIAL_PROCESS(ownIdentityList); -} - -RsDiscItem::RsDiscItem(RsGossipDiscoveryItemType subtype) - : RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DISC, static_cast(subtype) ) -{ -} - -RsDiscItem::~RsDiscItem() {} diff --git a/libretroshare/src/gossipdiscovery/gossipdiscoveryitems.h b/libretroshare/src/gossipdiscovery/gossipdiscoveryitems.h deleted file mode 100644 index b77074e37..000000000 --- a/libretroshare/src/gossipdiscovery/gossipdiscoveryitems.h +++ /dev/null @@ -1,196 +0,0 @@ -/******************************************************************************* - * Gossip discovery service items * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "serialiser/rsserial.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvaddrs.h" -#include "serialiser/rstlvbinary.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rsserializer.h" - -enum class RsGossipDiscoveryItemType : uint8_t -{ - PGP_LIST = 0x1, - PGP_CERT = 0x2, // deprecated - CONTACT = 0x5, - IDENTITY_LIST = 0x6, - PGP_CERT_BINARY = 0x9, -}; - -class RsDiscItem: public RsItem -{ -protected: - RsDiscItem(RsGossipDiscoveryItemType subtype); - -public: - RsDiscItem() = delete; - virtual ~RsDiscItem(); -}; - -/** - * This enum is underlined by uint32_t for historical reasons. - * We are conscious that uint32_t is an overkill for so few possible values but, - * changing here it at this point would break binary serialized item - * retro-compatibility. - */ -enum class RsGossipDiscoveryPgpListMode : uint32_t -{ - NONE = 0x0, - FRIENDS = 0x1, - GETCERT = 0x2 -}; - -class RsDiscPgpListItem: public RsDiscItem -{ -public: - - RsDiscPgpListItem() : RsDiscItem(RsGossipDiscoveryItemType::PGP_LIST) - { setPriorityLevel(QOS_PRIORITY_RS_DISC_PGP_LIST); } - - void clear() override; - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - RsGossipDiscoveryPgpListMode mode; - RsTlvPgpIdSet pgpIdSet; -}; - -class RsDiscPgpKeyItem: public RsDiscItem -{ -public: - - RsDiscPgpKeyItem() : - RsDiscItem(RsGossipDiscoveryItemType::PGP_CERT_BINARY), - bin_data(nullptr), bin_len(0) - { setPriorityLevel(QOS_PRIORITY_RS_DISC_PGP_CERT); } - - ~RsDiscPgpKeyItem() override { free(bin_data); } - void clear() override; - - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - /// duplicate information for practical reasons - RsPgpId pgpKeyId; - - unsigned char* bin_data; - uint32_t bin_len; -}; - -class RS_DEPRECATED_FOR(RsDiscPgpKeyItem) RsDiscPgpCertItem: public RsDiscItem -{ -public: - RsDiscPgpCertItem() : RsDiscItem(RsGossipDiscoveryItemType::PGP_CERT) - { setPriorityLevel(QOS_PRIORITY_RS_DISC_PGP_CERT); } - - void clear() override - { - pgpId.clear(); - pgpCert.clear(); - } - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) override - { - RsTypeSerializer::serial_process(j,ctx,pgpId,"pgpId") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_PGPCERT,pgpCert,"pgpCert") ; - } - - RsPgpId pgpId; - std::string pgpCert; -}; - -class RsDiscContactItem: public RsDiscItem -{ -public: - - RsDiscContactItem() : RsDiscItem(RsGossipDiscoveryItemType::CONTACT) - { setPriorityLevel(QOS_PRIORITY_RS_DISC_CONTACT); } - - void clear() override; - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - RsPgpId pgpId; - RsPeerId sslId; - - // COMMON - std::string location; - std::string version; - - uint32_t netMode; /* Mandatory */ - uint16_t vs_disc; /* Mandatory */ - uint16_t vs_dht; /* Mandatory */ - uint32_t lastContact; - - bool isHidden; /* not serialised */ - - // HIDDEN. - std::string hiddenAddr; - uint16_t hiddenPort; - - // STANDARD. - - RsTlvIpAddress currentConnectAddress ; // used to check! - - RsTlvIpAddress localAddrV4; /* Mandatory */ - RsTlvIpAddress extAddrV4; /* Mandatory */ - - RsTlvIpAddress localAddrV6; /* Mandatory */ - RsTlvIpAddress extAddrV6; /* Mandatory */ - - std::string dyndns; - - RsTlvIpAddrSet localAddrList; - RsTlvIpAddrSet extAddrList; -}; - -class RsDiscIdentityListItem: public RsDiscItem -{ -public: - - RsDiscIdentityListItem() : - RsDiscItem(RsGossipDiscoveryItemType::IDENTITY_LIST) - { setPriorityLevel(QOS_PRIORITY_RS_DISC_CONTACT); } - - void clear() override { ownIdentityList.clear(); } - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override; - - std::list ownIdentityList; -}; - -class RsDiscSerialiser: public RsServiceSerializer -{ -public: - RsDiscSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_DISC) {} - virtual ~RsDiscSerialiser() {} - - RsItem* create_item(uint16_t service, uint8_t item_subtype) const; -}; diff --git a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc b/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc deleted file mode 100644 index 732967f44..000000000 --- a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc +++ /dev/null @@ -1,1366 +0,0 @@ -/******************************************************************************* - * RetroShare gossip discovery service implementation * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2013 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#include "gossipdiscovery/p3gossipdiscovery.h" -#include "pqi/p3peermgr.h" -#include "retroshare/rsversion.h" -#include "retroshare/rsiface.h" -#include "rsserver/p3face.h" -#include "util/rsdebug.h" -#include "retroshare/rspeers.h" - -/**** - * #define P3DISC_DEBUG 1 - ****/ - -/*extern*/ std::shared_ptr rsGossipDiscovery(nullptr); - -static bool populateContactInfo( const peerState &detail, - RsDiscContactItem *pkt, - bool include_ip_information ) -{ - pkt->clear(); - - pkt->pgpId = detail.gpg_id; - pkt->sslId = detail.id; - pkt->location = detail.location; - pkt->version = ""; - pkt->netMode = detail.netMode; - pkt->vs_disc = detail.vs_disc; - pkt->vs_dht = detail.vs_dht; - - pkt->lastContact = time(nullptr); - - if (detail.hiddenNode) - { - pkt->isHidden = true; - pkt->hiddenAddr = detail.hiddenDomain; - pkt->hiddenPort = detail.hiddenPort; - } - else - { - pkt->isHidden = false; - - if(include_ip_information) - { - pkt->localAddrV4.addr = detail.localaddr; - pkt->extAddrV4.addr = detail.serveraddr; - sockaddr_storage_clear(pkt->localAddrV6.addr); - sockaddr_storage_clear(pkt->extAddrV6.addr); - - pkt->dyndns = detail.dyndns; - detail.ipAddrs.mLocal.loadTlv(pkt->localAddrList); - detail.ipAddrs.mExt.loadTlv(pkt->extAddrList); - } - else - { - sockaddr_storage_clear(pkt->localAddrV6.addr); - sockaddr_storage_clear(pkt->extAddrV6.addr); - sockaddr_storage_clear(pkt->localAddrV4.addr); - sockaddr_storage_clear(pkt->extAddrV4.addr); - } - } - - return true; -} - -void DiscPgpInfo::mergeFriendList(const std::set &friends) -{ - std::set::const_iterator it; - for(it = friends.begin(); it != friends.end(); ++it) - { - mFriendSet.insert(*it); - } -} - - -p3discovery2::p3discovery2( - p3PeerMgr* peerMgr, p3LinkMgr* linkMgr, p3NetMgr* netMgr, - p3ServiceControl* sc, RsGixs* gixs ) : - p3Service(), mRsEventsHandle(0), mPeerMgr(peerMgr), mLinkMgr(linkMgr), - mNetMgr(netMgr), mServiceCtrl(sc), mGixs(gixs), mDiscMtx("p3discovery2"), - mLastPgpUpdate(0) -{ - Dbg3() << __PRETTY_FUNCTION__ << std::endl; - - RS_STACK_MUTEX(mDiscMtx); - addSerialType(new RsDiscSerialiser()); - - // Add self into PGP FriendList. - mFriendList[AuthGPG::getAuthGPG()->getGPGOwnId()] = DiscPgpInfo(); -} - - -const std::string DISCOVERY_APP_NAME = "disc"; -const uint16_t DISCOVERY_APP_MAJOR_VERSION = 1; -const uint16_t DISCOVERY_APP_MINOR_VERSION = 0; -const uint16_t DISCOVERY_MIN_MAJOR_VERSION = 1; -const uint16_t DISCOVERY_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3discovery2::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_DISC, - DISCOVERY_APP_NAME, - DISCOVERY_APP_MAJOR_VERSION, - DISCOVERY_APP_MINOR_VERSION, - DISCOVERY_MIN_MAJOR_VERSION, - DISCOVERY_MIN_MINOR_VERSION); -} - -p3discovery2::~p3discovery2() -{ rsEvents->unregisterEventsHandler(mRsEventsHandle); } - -void p3discovery2::addFriend(const RsPeerId &sslId) -{ - RsPgpId pgpId = getPGPId(sslId); - - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it; - it = mFriendList.find(pgpId); - if (it == mFriendList.end()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::addFriend() adding pgp entry: " << pgpId; - std::cerr << std::endl; -#endif - - mFriendList[pgpId] = DiscPgpInfo(); - - it = mFriendList.find(pgpId); - } - - - /* now add RsPeerId */ - - std::map::iterator sit; - sit = it->second.mSslIds.find(sslId); - if (sit == it->second.mSslIds.end()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::addFriend() adding ssl entry: " << sslId; - std::cerr << std::endl; -#endif - - it->second.mSslIds[sslId] = DiscSslInfo(); - sit = it->second.mSslIds.find(sslId); - } - - /* update Settings from peerMgr */ - peerState detail; - if (mPeerMgr->getFriendNetStatus(sit->first, detail)) - { - sit->second.mDiscStatus = detail.vs_disc; - } - else - { - sit->second.mDiscStatus = RS_VS_DISC_OFF; - } -} - -void p3discovery2::removeFriend(const RsPeerId &sslId) -{ - RsPgpId pgpId = getPGPId(sslId); - - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it; - it = mFriendList.find(pgpId); - if (it == mFriendList.end()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::removeFriend() missing pgp entry: " << pgpId; - std::cerr << std::endl; -#endif - return; - } - - std::map::iterator sit; - sit = it->second.mSslIds.find(sslId); - if (sit == it->second.mSslIds.end()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::addFriend() missing ssl entry: " << sslId; - std::cerr << std::endl; -#endif - return; - } - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::addFriend() removing ssl entry: " << sslId; - std::cerr << std::endl; -#endif - it->second.mSslIds.erase(sit); - - if (it->second.mSslIds.empty()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::addFriend() pgpId now has no sslIds"; - std::cerr << std::endl; -#endif - /* pgp peer without any ssl entries -> check if they are still a real friend */ - if (!(AuthGPG::getAuthGPG()->isGPGAccepted(pgpId))) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::addFriend() pgpId is no longer a friend, removing"; - std::cerr << std::endl; -#endif - mFriendList.erase(it); - } - } -} - -RsPgpId p3discovery2::getPGPId(const RsPeerId &id) -{ - RsPgpId pgpId; - mPeerMgr->getGpgId(id, pgpId); - return pgpId; -} - -int p3discovery2::tick() -{ - return handleIncoming(); -} - -int p3discovery2::handleIncoming() -{ - RsItem* item = nullptr; - - int nhandled = 0; - // While messages read - while(nullptr != (item = recvItem())) - { - RsDiscPgpListItem* pgplist = nullptr; - RsDiscPgpKeyItem* pgpkey = nullptr; - RsDiscPgpCertItem* pgpcert = nullptr; // deprecated, hanlde for retro compability - RsDiscContactItem* contact = nullptr; - RsDiscIdentityListItem* gxsidlst = nullptr; - - ++nhandled; - - Dbg4() << __PRETTY_FUNCTION__ << " Received item: " << *item << std::endl; - - if((contact = dynamic_cast(item)) != nullptr) - { - if (item->PeerId() == contact->sslId) - recvOwnContactInfo(item->PeerId(), contact); - else - processContactInfo(item->PeerId(), contact); - } - else if( (gxsidlst = dynamic_cast(item)) != nullptr ) - recvIdentityList(item->PeerId(),gxsidlst->ownIdentityList); - else if((pgpkey = dynamic_cast(item)) != nullptr) - recvPGPCertificate(item->PeerId(), pgpkey); - else if((pgpcert = dynamic_cast(item)) != nullptr) - RsWarn() << "Received a deprecated RsDiscPgpCertItem. Will not be handled." << std::endl; // nothing to do. - else if((pgplist = dynamic_cast(item)) != nullptr) - { - if (pgplist->mode == RsGossipDiscoveryPgpListMode::FRIENDS) - processPGPList(pgplist->PeerId(), pgplist); - else if (pgplist->mode == RsGossipDiscoveryPgpListMode::GETCERT) - recvPGPCertificateRequest(pgplist->PeerId(), pgplist); - } - else - { - RsWarn() << __PRETTY_FUNCTION__ << " Received unknown item type " << (int)item->PacketSubType() << "! " << std::endl ; - RsWarn() << item << std::endl; - } - - delete item; - } - - return nhandled; -} - -void p3discovery2::sendOwnContactInfo(const RsPeerId &sslid) -{ - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendOwnContactInfo()"; - std::cerr << std::endl; -#endif - peerState detail; - if (mPeerMgr->getOwnNetStatus(detail)) - { - RsDiscContactItem *pkt = new RsDiscContactItem(); - - /* Cyril: we dont send our own IP to an hidden node. It will not use it - * anyway. Furthermore, a Tor node is not supposed to have any mean to send the IPs of his friend nodes - * to other nodes. This would be a very serious security risk. */ - - populateContactInfo(detail, pkt, !rsPeers->isHiddenNode(sslid)); - - /* G10h4ck: sending IP information also to hidden nodes has proven very - * helpful in the usecase of non hidden nodes, that share a common - * hidden trusted node, to discover each other IP. - * Advanced/corner case non hidden node users that want to hide their - * IP to a specific hidden ~trusted~ node can do it through the - * permission matrix. Disabling this instead will make life more - * difficult for average user, that moreover whould have no way to - * revert an hardcoded policy. */ - - pkt->version = RS_HUMAN_READABLE_VERSION; - pkt->PeerId(sslid); - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendOwnContactInfo() sending:" << std::endl; - pkt -> print(std::cerr); - std::cerr << std::endl; -#endif - sendItem(pkt); - - RsDiscIdentityListItem *pkt2 = new RsDiscIdentityListItem(); - - rsIdentity->getOwnIds(pkt2->ownIdentityList,true); - pkt2->PeerId(sslid) ; - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendOwnContactInfo() sending own signed identity list:" << std::endl; - for(auto it(pkt2->ownIdentityList.begin());it!=pkt2->ownIdentityList.end();++it) - std::cerr << " identity: " << (*it).toStdString() << std::endl; -#endif - sendItem(pkt2); - } -} - -void p3discovery2::recvOwnContactInfo(const RsPeerId &fromId, const RsDiscContactItem *item) -{ -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::recvOwnContactInfo()"; - std::cerr << std::endl; - - std::cerr << "Info sent by the peer itself -> updating self info:" << std::endl; - std::cerr << " -> vs_disc : " << item->vs_disc << std::endl; - std::cerr << " -> vs_dht : " << item->vs_dht << std::endl; - std::cerr << " -> network mode : " << item->netMode << std::endl; - std::cerr << " -> location : " << item->location << std::endl; - std::cerr << std::endl; -#endif - // Check that the "own" ID sent corresponds to the one we think it should be. - // Some of these checks may look superfluous but it's better to risk to check twice than not check at all. - - // was obtained using a short invite. , and that the friend is marked as "ignore PGP validation" because it - RsPeerDetails det ; - if(!rsPeers->getPeerDetails(fromId,det)) - { - RsErr() << "(EE) Cannot obtain details from " << fromId << " who is supposed to be a friend! Dropping the info." << std::endl; - return; - } - if(det.gpg_id != item->pgpId) - { - RsErr() << "(EE) peer " << fromId << " sent own details with PGP key ID " << item->pgpId << " which does not match the known key id " << det.gpg_id << ". Dropping the info." << std::endl; - return; - } - - // Peer Own Info replaces the existing info, because the - // peer is the primary source of his own IPs, except for hidden nodes - // that normally send nothing. We still ignore it as a double security. - - mPeerMgr->setNetworkMode(fromId, item->netMode); - mPeerMgr->setLocation(fromId, item->location); - mPeerMgr->setVisState(fromId, item->vs_disc, item->vs_dht); - - if(!mPeerMgr->isHiddenNode(fromId)) - { - if(!det.localAddr.empty()) - { - if(sockaddr_storage_isValidNet(item->localAddrV4.addr)) - mPeerMgr->setLocalAddress(fromId,item->localAddrV4.addr); - else if(sockaddr_storage_isValidNet(item->localAddrV6.addr)) - mPeerMgr->setLocalAddress(fromId,item->localAddrV6.addr); - } - - if(!det.extAddr.empty()) - { - if(sockaddr_storage_isValidNet(item->extAddrV4.addr)) - mPeerMgr->setExtAddress(fromId,item->extAddrV4.addr); - else if(sockaddr_storage_isValidNet(item->extAddrV6.addr)) - mPeerMgr->setExtAddress(fromId,item->extAddrV6.addr); - } - } - - setPeerVersion(fromId, item->version); - - // Hidden nodes do not need IP information. So that information is dropped. - // However, that doesn't mean hidden nodes do not know that information. Normally - // normal nodes should not send it, but old nodes still do. - - if(!mPeerMgr->isHiddenNode(rsPeers->getOwnId())) - updatePeerAddresses(item); - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mGossipDiscoveryEventType = RsGossipDiscoveryEventType::FRIEND_PEER_INFO_RECEIVED; - ev->mFromId = fromId; - ev->mAboutId = item->sslId; - rsEvents->postEvent(ev); - } - - // if the peer is not validated, we stop the exchange here - - if(det.skip_pgp_signature_validation) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::recvOwnContactInfo() missing PGP key " << item->pgpId << " from short invite friend " << fromId << ". Requesting it." << std::endl; -#endif - requestPGPCertificate(det.gpg_id, fromId); - return; - } - - // This information will be sent out to online peers, at the receipt of their PGPList. - // It is important that PGPList is received after the OwnContactItem. - // This should happen, but is not enforced by the protocol. - - // Start peer list exchange, if discovery is enabled - - peerState ps; - mPeerMgr->getOwnNetStatus(ps); - - if(ps.vs_disc != RS_VS_DISC_OFF) - sendPGPList(fromId); - - // Update mDiscStatus. - RS_STACK_MUTEX(mDiscMtx); - - RsPgpId pgpId = getPGPId(fromId); - std::map::iterator it = mFriendList.find(pgpId); - if (it != mFriendList.end()) - { - std::map::iterator sit = it->second.mSslIds.find(fromId); - if (sit != it->second.mSslIds.end()) - { - sit->second.mDiscStatus = item->vs_disc; -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::recvOwnContactInfo()"; - std::cerr << "updating mDiscStatus to: " << sit->second.mDiscStatus; - std::cerr << std::endl; -#endif - } - else - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::recvOwnContactInfo()"; - std::cerr << " ERROR missing SSL Entry: " << fromId; - std::cerr << std::endl; -#endif - } - } -} - -void p3discovery2::recvIdentityList(const RsPeerId& pid,const std::list& ids) -{ - std::list peers; - peers.push_back(pid); - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::recvIdentityList(): from peer " << pid << ": " << ids.size() << " identities" << std::endl; -#endif - - RsIdentityUsage use_info(RsServiceType::GOSSIP_DISCOVERY,RsIdentityUsage::IDENTITY_NEW_FROM_DISCOVERY); - - for(auto it(ids.begin());it!=ids.end();++it) - { -#ifdef P3DISC_DEBUG - std::cerr << " identity: " << (*it).toStdString() << std::endl; -#endif - mGixs->requestKey(*it,peers,use_info) ; - } -} - -void p3discovery2::updatePeerAddresses(const RsDiscContactItem *item) -{ - if (item->isHidden) - mPeerMgr->setHiddenDomainPort(item->sslId, item->hiddenAddr, - item->hiddenPort); - else - { - mPeerMgr->setDynDNS(item->sslId, item->dyndns); - updatePeerAddressList(item); - } -} - -void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item) -{ - if (item->isHidden) - { - } - else if(!mPeerMgr->isHiddenNode(rsPeers->getOwnId())) - { - /* Cyril: we don't store IP addresses if we're a hidden node. - * Normally they should not be sent to us, except for old peers. */ - /* G10h4ck: sending IP information also to hidden nodes has proven very - * helpful in the usecase of non hidden nodes, that share a common - * hidden trusted node, to discover each other IP. - * Advanced/corner case non hidden node users that want to hide their - * IP to a specific hidden ~trusted~ node can do it through the - * permission matrix. Disabling this instead will make life more - * difficult for average user, that moreover whould have no way to - * revert an hardcoded policy. */ - pqiIpAddrSet addrsFromPeer; - addrsFromPeer.mLocal.extractFromTlv(item->localAddrList); - addrsFromPeer.mExt.extractFromTlv(item->extAddrList); - -#ifdef P3DISC_DEBUG - std::cerr << "Setting address list to peer " << item->sslId - << ", to be:" << std::endl ; - - std::string addrstr; - addrsFromPeer.printAddrs(addrstr); - std::cerr << addrstr; - std::cerr << std::endl; -#endif - mPeerMgr->updateAddressList(item->sslId, addrsFromPeer); - } -} - -// Starts the Discovery process. -// should only be called it DISC2_STATUS_NOT_HIDDEN(OwnInfo.status). -void p3discovery2::sendPGPList(const RsPeerId &toId) -{ - updatePgpFriendList(); - - RS_STACK_MUTEX(mDiscMtx); - - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendPGPList() to " << toId << std::endl; -#endif - - RsDiscPgpListItem *pkt = new RsDiscPgpListItem(); - - pkt->mode = RsGossipDiscoveryPgpListMode::FRIENDS; - - for(auto it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - // Check every friend, and only send his PGP key if the friend tells that he wants discovery. Because this action over profiles depends on a node information, - // we check each node of a given progile and only send the profile key if at least one node allows it. - - for(auto it2(it->second.mSslIds.begin());it2!=it->second.mSslIds.end();++it2) - if(it2->second.mDiscStatus != RS_VS_DISC_OFF) - { - pkt->pgpIdSet.ids.insert(it->first); - break; - } - } - - pkt->PeerId(toId); - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendPGPList() sending:" << std::endl; - pkt->print(std::cerr); - std::cerr << std::endl; -#endif - - sendItem(pkt); -} - -void p3discovery2::updatePgpFriendList() -{ -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePgpFriendList()"; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(mDiscMtx); - -#define PGP_MAX_UPDATE_PERIOD 300 - - if (time(NULL) < mLastPgpUpdate + PGP_MAX_UPDATE_PERIOD ) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePgpFriendList() Already uptodate"; - std::cerr << std::endl; -#endif - return; - } - - mLastPgpUpdate = time(NULL); - - std::list pgpList; - std::set pgpSet; - - std::set::iterator sit; - std::list::iterator lit; - std::map::iterator it; - - RsPgpId ownPgpId = AuthGPG::getAuthGPG()->getGPGOwnId(); - AuthGPG::getAuthGPG()->getGPGAcceptedList(pgpList); - pgpList.push_back(ownPgpId); - - // convert to set for ordering. - for(lit = pgpList.begin(); lit != pgpList.end(); ++lit) - { - pgpSet.insert(*lit); - } - - std::list pgpToAdd; - std::list pgpToRemove; - - - sit = pgpSet.begin(); - it = mFriendList.begin(); - while (sit != pgpSet.end() && it != mFriendList.end()) - { - if (*sit < it->first) - { - /* to add */ - pgpToAdd.push_back(*sit); - ++sit; - } - else if (it->first < *sit) - { - /* to remove */ - pgpToRemove.push_back(it->first); - ++it; - } - else - { - /* same - okay */ - ++sit; - ++it; - } - } - - /* more to add? */ - for(; sit != pgpSet.end(); ++sit) - { - pgpToAdd.push_back(*sit); - } - - for(; it != mFriendList.end(); ++it) - { - /* more to remove */ - pgpToRemove.push_back(it->first); - } - - for(lit = pgpToRemove.begin(); lit != pgpToRemove.end(); ++lit) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePgpFriendList() Removing pgpId: " << *lit; - std::cerr << std::endl; -#endif - - it = mFriendList.find(*lit); - mFriendList.erase(it); - } - - for(lit = pgpToAdd.begin(); lit != pgpToAdd.end(); ++lit) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePgpFriendList() Adding pgpId: " << *lit; - std::cerr << std::endl; -#endif - - mFriendList[*lit] = DiscPgpInfo(); - } - - /* finally install the pgpList on our own entry */ - DiscPgpInfo &ownInfo = mFriendList[ownPgpId]; - ownInfo.mergeFriendList(pgpSet); - -} - -void p3discovery2::processPGPList(const RsPeerId &fromId, const RsDiscPgpListItem *item) -{ - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::processPGPList() from " << fromId; - std::cerr << std::endl; -#endif - - RsPgpId fromPgpId = getPGPId(fromId); - auto it = mFriendList.find(fromPgpId); - if (it == mFriendList.end()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::processPGPList() is not friend: " << fromId; - std::cerr << std::endl; -#endif - - // cleanup. - return; - } - - bool requestUnknownPgpCerts = true; - peerState pstate; - mPeerMgr->getOwnNetStatus(pstate); - if (pstate.vs_disc != RS_VS_DISC_FULL) - requestUnknownPgpCerts = false; - - uint32_t linkType = mLinkMgr->getLinkType(fromId); - if ((linkType & RS_NET_CONN_SPEED_TRICKLE) || - (linkType & RS_NET_CONN_SPEED_LOW)) - { - std::cerr << "p3discovery2::processPGPList() Not requesting Certificates from: " << fromId; - std::cerr << " (low bandwidth)" << std::endl; - requestUnknownPgpCerts = false; - } - - if (requestUnknownPgpCerts) - { - std::set::const_iterator fit; - for(fit = item->pgpIdSet.ids.begin(); fit != item->pgpIdSet.ids.end(); ++fit) - { - if (!AuthGPG::getAuthGPG()->isGPGId(*fit)) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::processPGPList() requesting certificate for PgpId: " << *fit; - std::cerr << " from SslId: " << fromId; - std::cerr << std::endl; -#endif - requestPGPCertificate(*fit, fromId); - } - } - } - - it->second.mergeFriendList(item->pgpIdSet.ids); - updatePeers_locked(fromId); -} - - -/* - * -> Update Other Peers about B. - * -> Update B about Other Peers. - */ -void p3discovery2::updatePeers_locked(const RsPeerId &aboutId) -{ - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeers_locked() about " << aboutId; - std::cerr << std::endl; -#endif - - RsPgpId aboutPgpId = getPGPId(aboutId); - - auto ait = mFriendList.find(aboutPgpId); - if (ait == mFriendList.end()) - { - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeers_locked() PgpId is not a friend: " << aboutPgpId; - std::cerr << std::endl; -#endif - return; - } - - std::set mutualFriends; - std::set onlineFriends; - - const std::set &friendSet = ait->second.mFriendSet; - - for(auto fit = friendSet.begin(); fit != friendSet.end(); ++fit) - { - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeer_locked() checking their friend: " << *fit; - std::cerr << std::endl; -#endif - - auto ffit = mFriendList.find(*fit); - - if (ffit == mFriendList.end()) - { - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeer_locked() Ignoring not our friend"; - std::cerr << std::endl; -#endif - // Not our friend, or we have no Locations (SSL) for this RsPgpId (same difference) - continue; - } - - if (ffit->second.mFriendSet.find(aboutPgpId) != ffit->second.mFriendSet.end()) - { - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeer_locked() Adding as Mutual Friend"; - std::cerr << std::endl; -#endif - mutualFriends.insert(*fit); - - for(auto mit = ffit->second.mSslIds.begin(); mit != ffit->second.mSslIds.end(); ++mit) - { - RsPeerId sslid = mit->first; - if (mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, sslid)) - { - // TODO IGNORE if sslid == aboutId, or sslid == ownId. -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeer_locked() Adding Online RsPeerId: " << sslid; - std::cerr << std::endl; -#endif - onlineFriends.insert(sslid); - } - } - } - } - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeer_locked() Updating " << aboutId << " about Mutual Friends"; - std::cerr << std::endl; -#endif - // update aboutId about Other Peers. - for(auto fit = mutualFriends.begin(); fit != mutualFriends.end(); ++fit) - sendContactInfo_locked(*fit, aboutId); - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeer_locked() Updating Online Peers about " << aboutId; - std::cerr << std::endl; -#endif - // update Other Peers about aboutPgpId. - for(auto sit = onlineFriends.begin(); sit != onlineFriends.end(); ++sit) - { - // This could be more efficient, and only be specific about aboutId. - // but we'll leave it like this for the moment. - sendContactInfo_locked(aboutPgpId, *sit); - } -} - -void p3discovery2::sendContactInfo_locked(const RsPgpId &aboutId, const RsPeerId &toId) -{ -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendContactInfo_locked() aboutPGPId: " << aboutId << " toId: " << toId; - std::cerr << std::endl; -#endif - std::map::const_iterator it; - it = mFriendList.find(aboutId); - if (it == mFriendList.end()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendContactInfo_locked() ERROR aboutId is not a friend"; - std::cerr << std::endl; -#endif - return; - } - - std::map::const_iterator sit; - for(sit = it->second.mSslIds.begin(); sit != it->second.mSslIds.end(); ++sit) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendContactInfo_locked() related sslId: " << sit->first; - std::cerr << std::endl; -#endif - - if (sit->first == rsPeers->getOwnId()) - { - // sending info of toId to himself will be used by toId to check that the IP it is connected as is the same - // as its external IP. -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::processContactInfo() not sending info on self"; - std::cerr << std::endl; -#endif - continue; - } - - if (sit->second.mDiscStatus != RS_VS_DISC_OFF) - { - peerState detail; - peerConnectState detail2; - - if (mPeerMgr->getFriendNetStatus(sit->first, detail)) - { - RsDiscContactItem *pkt = new RsDiscContactItem(); - populateContactInfo(detail, pkt,!mPeerMgr->isHiddenNode(toId));// never send IPs to an hidden node. The node will not use them anyway. - pkt->PeerId(toId); - - // send to each peer its own connection address. - - if(sit->first == toId && mLinkMgr->getFriendNetStatus(sit->first,detail2)) - pkt->currentConnectAddress.addr = detail2.connectaddr; - else - sockaddr_storage_clear(pkt->currentConnectAddress.addr) ; - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendContactInfo_locked() Sending"; - std::cerr << std::endl; - pkt->print(std::cerr); - std::cerr << std::endl; -#endif - sendItem(pkt); - } - else - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendContactInfo_locked() No Net Status"; - std::cerr << std::endl; -#endif - } - } - else - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendContactInfo_locked() RsPeerId Hidden"; - std::cerr << std::endl; -#endif - } - } -} - -void p3discovery2::processContactInfo(const RsPeerId &fromId, const RsDiscContactItem *item) -{ - (void) fromId; // remove unused parameter warnings, debug only - - RS_STACK_MUTEX(mDiscMtx); - - // This case is the node fromId sending information about ourselves to us. There's one good use of this: - // read the IP information the friend knows about us, and use it to extimate our external address. - - if (item->sslId == rsPeers->getOwnId()) - { - if(sockaddr_storage_isExternalNet(item->currentConnectAddress.addr)) - mPeerMgr->addCandidateForOwnExternalAddress(item->PeerId(), item->currentConnectAddress.addr); - - return; - } - - auto it = mFriendList.find(item->pgpId); // is this the PGP id one of our friends? - - if (it == mFriendList.end()) // no it's not. - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::processContactInfo(" << fromId << ") RsPgpId: "; - std::cerr << item->pgpId << " Not Friend."; - std::cerr << std::endl; - std::cerr << "p3discovery2::processContactInfo(" << fromId << ") THIS SHOULD NEVER HAPPEN!"; - std::cerr << std::endl; -#endif - - /* THESE ARE OUR FRIEND OF FRIENDS ... pass this information along to - * NetMgr & DHT... - * as we can track FOF and use them as potential Proxies / Relays - */ - - if (!item->isHidden) - { - /* add into NetMgr and non-search, so we can detect connect attempts */ - mNetMgr->netAssistFriend(item->sslId,false); - - /* inform NetMgr that we know this peer */ - mNetMgr->netAssistKnownPeer(item->sslId, item->extAddrV4.addr, NETASSIST_KNOWN_PEER_FOF | NETASSIST_KNOWN_PEER_OFFLINE); - } - return; - } - - // The peer the discovery info is about is a friend. We gather the nodes for that profile into the local structure and notify p3peerMgr. - - if(!rsPeers->isGPGAccepted(item->pgpId)) // this is an additional check, because the friendship previously depends on the local cache. We need - return ; // fresh information here. - - bool should_notify_discovery = false; - - DiscSslInfo& sslInfo(it->second.mSslIds[item->sslId]); // This line inserts the entry while not removing already existing data - // do not remove it! - if (!mPeerMgr->isFriend(item->sslId)) - { - should_notify_discovery = true; - - // Add with no disc by default. If friend already exists, it will do nothing - // NO DISC is important - otherwise, we'll just enter a nasty loop, - // where every addition triggers requests, then they are cleaned up, and readded... - - // This way we get their addresses, but don't advertise them until we get a - // connection. -#ifdef P3DISC_DEBUG - std::cerr << "--> Adding to friends list " << item->sslId << " - " << item->pgpId << std::endl; -#endif - // We pass RS_NODE_PERM_ALL because the PGP id is already a friend, so we should keep the existing - // permission flags. Therefore the mask needs to be 0xffff. - - // set last seen to RS_PEER_OFFLINE_NO_DISC minus 1 so that it won't be shared with other friends - // until a first connection is established - - // This code is a bit dangerous: we add a friend without the insurance that the PGP key that will validate this friend actually has - // the supplied PGP id. Of course, because it comes from a friend, we should trust that friend. Anyway, it is important that - // when connecting the handshake is always doen w.r.t. the known PGP key, and not the one that is indicated in the certificate issuer field. - - mPeerMgr->addFriend( item->sslId, item->pgpId, item->netMode, - RS_VS_DISC_OFF, RS_VS_DHT_FULL, - time(NULL) - RS_PEER_OFFLINE_NO_DISC - 1, - RS_NODE_PERM_ALL ); - - updatePeerAddresses(item); - } - updatePeerAddressList(item); - - RsServer::notify()->notifyListChange(NOTIFY_LIST_NEIGHBOURS, NOTIFY_TYPE_MOD); - - if(should_notify_discovery) - { - RsServer::notify()->notifyDiscInfoChanged(); - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mGossipDiscoveryEventType = RsGossipDiscoveryEventType::FRIEND_PEER_INFO_RECEIVED; - ev->mFromId = fromId; - ev->mAboutId = item->sslId; - rsEvents->postEvent(ev); - } - } -} - -/* we explictly request certificates, instead of getting them all the time - */ -void p3discovery2::requestPGPCertificate(const RsPgpId &aboutId, const RsPeerId &toId) -{ -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::requestPGPCertificate() aboutId: " << aboutId << " to: " << toId; - std::cerr << std::endl; -#endif - - RsDiscPgpListItem *pkt = new RsDiscPgpListItem(); - - pkt->mode = RsGossipDiscoveryPgpListMode::GETCERT; - pkt->pgpIdSet.ids.insert(aboutId); - pkt->PeerId(toId); - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::requestPGPCertificate() sending:" << std::endl; - pkt->print(std::cerr); - std::cerr << std::endl; -#endif - - sendItem(pkt); -} - -void p3discovery2::recvPGPCertificateRequest( const RsPeerId& fromId, const RsDiscPgpListItem* item ) -{ -#ifdef P3DISC_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " from " << fromId << std::endl; -#endif - peerState ps; - mPeerMgr->getOwnNetStatus(ps); - - if(ps.vs_disc == RS_VS_DISC_OFF) - { - std::cerr << "(WW) refusing PGP certificate request from " << fromId << " because discovery is OFF" << std::endl; - return; - } - - RsPgpId ownPgpId = AuthGPG::getAuthGPG()->getGPGOwnId(); - for(const RsPgpId& pgpId : item->pgpIdSet.ids) - if (pgpId == ownPgpId) - sendPGPCertificate(pgpId, fromId); - else if(ps.vs_disc != RS_VS_DISC_OFF && AuthGPG::getAuthGPG()->isGPGAccepted(pgpId)) - sendPGPCertificate(pgpId, fromId); - else - std::cerr << "(WW) not sending certificate " << pgpId << " asked by friend " << fromId << " because this either this cert is not a friend, or discovery is off" << std::endl; -} - - -void p3discovery2::sendPGPCertificate(const RsPgpId &aboutId, const RsPeerId &toId) -{ - RsDiscPgpKeyItem *pgp_key_item = new RsDiscPgpKeyItem; - - pgp_key_item->PeerId(toId); - pgp_key_item->pgpKeyId = aboutId; - unsigned char *bin_data; - size_t bin_len; - - if(!AuthGPG::getAuthGPG()->exportPublicKey(aboutId,bin_data,bin_len,false,true)) - { - std::cerr << "(EE) cannot export public key " << aboutId << " requested by peer " << toId << std::endl; - return ; - } - - pgp_key_item->bin_data = bin_data; - pgp_key_item->bin_len = bin_len; - - sendItem(pgp_key_item); -} - -void p3discovery2::recvPGPCertificate(const RsPeerId& fromId, RsDiscPgpKeyItem* item ) -{ - // 1 - check that the cert structure is valid. - - RsPgpId cert_pgp_id; - std::string cert_name; - std::list cert_signers; - - if(!AuthGPG::getAuthGPG()->getGPGDetailsFromBinaryBlock( (unsigned char*)item->bin_data,item->bin_len, cert_pgp_id, cert_name, cert_signers )) - { - std::cerr << "(EE) cannot parse own PGP key sent by " << fromId << std::endl; - return; - } - - if(cert_pgp_id != item->pgpKeyId) - { - std::cerr << "(EE) received a PGP key from " << fromId << " which ID (" << cert_pgp_id << ") is different from the one anounced in the packet (" << item->pgpKeyId << ")!" << std::endl; - return; - } - - // 2 - check if the peer who is sending us a cert is already validated - - RsPeerDetails det; - if(!rsPeers->getPeerDetails(fromId,det)) - { - std::cerr << "(EE) cannot get peer details from friend " << fromId << ": this is very wrong!"<< std::endl; - return; - } - - // We treat own pgp keys right away when they are sent by a friend for which we dont have it. This way we can keep the skip_pgg_signature_validation consistent - - if(det.skip_pgp_signature_validation) - { -#ifdef P3DISC_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " Received own full certificate from short-invite friend " << fromId << std::endl; -#endif - // do some extra checks. Dont remove them. They cost nothing as compared to what they could avoid. - - if(item->pgpKeyId != det.gpg_id) - { - std::cerr << "(EE) received a PGP key with ID " << item->pgpKeyId << " from non validated peer " << fromId << ", which should only be allowed to send his own key " << det.gpg_id << std::endl; - return; - } - } - RsPgpId tmp_pgp_id; - std::string error_string; - -#ifdef P3DISC_DEBUG - std::cerr << __PRETTY_FUNCTION__ << "Received PGP key " << cert_pgp_id << " from from friend " << fromId << ". Adding to keyring." << std::endl; -#endif - // now that will add the key *and* set the skip_signature_validation flag at once - rsPeers->loadPgpKeyFromBinaryData((unsigned char*)item->bin_data,item->bin_len, tmp_pgp_id,error_string); // no error should occur at this point because we called loadDetailsFromStringCert() already - - // Make sure we allow connections after the key is added. This is not the case otherwise. We only do that if the peer is non validated peer, since - // otherwise the connection should already be accepted. This only happens when the short invite peer sends its own PGP key. - - if(det.skip_pgp_signature_validation) - AuthGPG::getAuthGPG()->AllowConnection(det.gpg_id,true); -} - - /************* from pqiServiceMonitor *******************/ -void p3discovery2::statusChange(const std::list &plist) -{ -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange()" << std::endl; -#endif - - std::list::const_iterator pit; - for(pit = plist.begin(); pit != plist.end(); ++pit) - { - if (pit->actions & RS_SERVICE_PEER_CONNECTED) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange() Starting Disc with: " << pit->id << std::endl; -#endif - sendOwnContactInfo(pit->id); - } - else if (pit->actions & RS_SERVICE_PEER_DISCONNECTED) - { - std::cerr << "p3discovery2::statusChange() Disconnected: " << pit->id << std::endl; - } - - if (pit->actions & RS_SERVICE_PEER_NEW) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange() Adding Friend: " << pit->id << std::endl; -#endif - addFriend(pit->id); - } - else if (pit->actions & RS_SERVICE_PEER_REMOVED) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange() Removing Friend: " << pit->id << std::endl; -#endif - removeFriend(pit->id); - } - } -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange() finished." << std::endl; -#endif - return; -} - - - /*************************************************************************************/ - /* Extracting Network Graph Details */ - /*************************************************************************************/ -bool p3discovery2::getDiscFriends(const RsPeerId& id, std::list &proxyIds) -{ - // This is treated appart, because otherwise we don't receive any disc info about us - if(id == rsPeers->getOwnId()) // SSL id - return rsPeers->getFriendList(proxyIds) ; - - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - - std::map::const_iterator it; - RsPgpId pgp_id = getPGPId(id); - - it = mFriendList.find(pgp_id); - if (it == mFriendList.end()) - { - // ERROR. - return false; - } - - // For each of their friends that we know, grab that set of RsPeerId. - const std::set &friendSet = it->second.mFriendSet; - std::set::const_iterator fit; - for(fit = friendSet.begin(); fit != friendSet.end(); ++fit) - { - it = mFriendList.find(*fit); - if (it == mFriendList.end()) - { - continue; - } - - std::map::const_iterator sit; - for(sit = it->second.mSslIds.begin(); - sit != it->second.mSslIds.end(); ++sit) - { - proxyIds.push_back(sit->first); - } - } - return true; - -} - -bool p3discovery2::getWaitingDiscCount(size_t &sendCount, size_t &recvCount) -{ - RS_STACK_MUTEX(mDiscMtx); - sendCount = 0;//mPendingDiscPgpCertOutList.size(); - recvCount = 0;//mPendingDiscPgpCertInList.size(); - - return true; -} - -bool p3discovery2::getDiscPgpFriends(const RsPgpId &pgp_id, std::list &proxyPgpIds) -{ - /* find id -> and extract the neighbour_of ids */ - - if(pgp_id == rsPeers->getGPGOwnId()) // SSL id // This is treated appart, because otherwise we don't receive any disc info about us - return rsPeers->getGPGAcceptedList(proxyPgpIds) ; - - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - - std::map::const_iterator it; - it = mFriendList.find(pgp_id); - if (it == mFriendList.end()) - { - // ERROR. - return false; - } - - std::set::const_iterator fit; - for(fit = it->second.mFriendSet.begin(); fit != it->second.mFriendSet.end(); ++fit) - { - proxyPgpIds.push_back(*fit); - } - return true; -} - -bool p3discovery2::getPeerVersion(const RsPeerId &peerId, std::string &version) -{ - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - - std::map::const_iterator it; - it = mLocationMap.find(peerId); - if (it == mLocationMap.end()) - { - // MISSING. - return false; - } - - version = it->second.mVersion; - return true; -} - -bool p3discovery2::setPeerVersion(const RsPeerId &peerId, const std::string &version) -{ - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it; - it = mLocationMap.find(peerId); - if (it == mLocationMap.end()) - { - mLocationMap[peerId] = DiscPeerInfo(); - it = mLocationMap.find(peerId); - } - - it->second.mVersion = version; - return true; -} - - -/*************************************************************************************/ -/* AuthGPGService */ -/*************************************************************************************/ -// AuthGPGOperation *p3discovery2::getGPGOperation() -// { -// { -// RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ -// -// /* process disc reply in list */ -// if (!mPendingDiscPgpCertInList.empty()) { -// RsDiscPgpCertItem *item = mPendingDiscPgpCertInList.front(); -// mPendingDiscPgpCertInList.pop_front(); -// -// return new AuthGPGOperationLoadOrSave(true, item->pgpId, item->pgpCert, item); -// } -// } -// -// return NULL; -// } - -// void p3discovery2::setGPGOperation(AuthGPGOperation *operation) -// { -// AuthGPGOperationLoadOrSave *loadOrSave = dynamic_cast(operation); -// if (loadOrSave) -// { -// RsDiscPgpCertItem *item = (RsDiscPgpCertItem *) loadOrSave->m_userdata; -// if (!item) -// { -// return; -// } -// -// if (loadOrSave->m_load) -// { -// -// #ifdef P3DISC_DEBUG -// std::cerr << "p3discovery2::setGPGOperation() Loaded Cert" << std::endl; -// item->print(std::cerr, 5); -// std::cerr << std::endl; -// #endif -// // It has already been processed by PGP. -// delete item; -// } -// else -// { -// // Attaching Certificate. -// item->pgpCert = loadOrSave->m_certGpg; -// -// #ifdef P3DISC_DEBUG -// std::cerr << "p3discovery2::setGPGOperation() Sending Message:" << std::endl; -// item->print(std::cerr, 5); -// #endif -// -// // Send off message -// sendItem(item); -// } -// return; -// } -// -// /* ignore other operations */ -// } diff --git a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.h b/libretroshare/src/gossipdiscovery/p3gossipdiscovery.h deleted file mode 100644 index 95773df69..000000000 --- a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.h +++ /dev/null @@ -1,222 +0,0 @@ -/******************************************************************************* - * RetroShare gossip discovery service implementation * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2013 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -// -// p3GossipDiscovery is reponsible for facilitating the circulation of public keys between friend nodes. -// -// The service locally holds a cache that stores: -// * the list of friend profiles, in each of which the list of locations with their own discovery flag (which means whether they allow discovery or not) -// * the list of friend nodes, with their version number -// -// Data flow -// ========= -// -// statusChange(std::list&) // called by pqiMonitor when peers are added,removed, or recently connected -// | -// +---- sendOwnContactInfo(RsPeerId) // [On connection] sends own PgpId, discovery flag, list of own signed GxsIds -// | | -// | +---->[to friend] -// | -// +---- locally add/remove cache info // [New/Removed friend] updates the list of friends, along with their own discovery flag -// -// tick() -// | -// +------ handleIncoming() -// | -// +-- recvOwnContactInfo(RsPeerId) // update location, IP addresses of a peer. -// | | -// | +------(if the peer has short_invite flag) -// | | | -// | | +---------requestPGPKey()->[to friend] // requests the full PGP public key, so as to be -// | | // able to validate connections. -// | | -// | +------(if disc != RS_VS_DISC_OFF) -// | | -// | +---------sendPgpList()->[to friend] // sends own list of friend profiles for which at least one location -// | // accepts discovery -// +-- processContactInfo(item->PeerId(), contact); -// | | -// | +------ addFriend() // called on nodes signed by the PGP key mentionned in the disc info -// | | -// | +------ update local discovery info -// | -// +-- recvIdentityList(Gxs Identity List) -// | | -// | +------ mGixs->requestKey(*it,peers,use_info) ; // requestKey() takes care of requesting the GxsIds that are missing -// | -// +-- recvPGPCertificate(item->PeerId(), pgpkey); -// | | -// | +------(if peer has short invite flag) -// | | -// | +--------- add key to keyring, accept connections and notify peerMgr -// | -// +-- processPGPList(pgplist->PeerId(), pgplist); // list of PGP keys of a friend, received from himself -// | | -// | +------ requestPgpCertificate() // request missing keys only -// | | -// | +------ updatePeers_locked(fromId) -// | | -// | +--------- sendContactInfo_locked(from,to) // sends IP information about mutual friends to the origin of the info -// | | -// | +--------- sendContactInfo_locked(to,from) // sends IP information origin to online mutual friends -// | -// +-- recvPGPCertificateRequest(pgplist->PeerId(), pgplist); -// | -// +------ sendPGPCertificate() // only sends the ones we are friend with, and only send own cert -// // if discovery is off -// -// Notes: -// * Tor nodes never send their own IP, and normal nodes never send their IP to Tor nodes either. -// A Tor node may accidentally know the IP of a normal node when it adds its certificate. However, the IP is dropped and not saved in this case. -// Generally speaking, no IP information should leave or transit through a Tor node. -// -// * the decision to call recvOwnContactInfo() or processContactInfo() depends on whether the item's peer id is the one the info is about. This is -// a bit unsafe. We should probably have to different items here especially if the information is not exactly the same. -// -#include - -#include "retroshare/rsgossipdiscovery.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" -#include "pqi/pqiservicemonitor.h" -#include "gossipdiscovery/gossipdiscoveryitems.h" -#include "services/p3service.h" -#include "pqi/authgpg.h" -#include "gxs/rsgixs.h" - -class p3ServiceControl; - -struct DiscSslInfo -{ - DiscSslInfo() : mDiscStatus(RS_VS_DISC_OFF) {} // default is to not allow discovery, until the peer tells about it - uint16_t mDiscStatus; -}; - -struct DiscPeerInfo -{ - DiscPeerInfo() {} - - std::string mVersion; -}; - -struct DiscPgpInfo -{ - DiscPgpInfo() {} - - void mergeFriendList(const std::set &friends); - - std::set mFriendSet; - std::map mSslIds; -}; - - -class p3discovery2 : - public RsGossipDiscovery, public p3Service, public pqiServiceMonitor - //public AuthGPGService -{ -public: - - p3discovery2( p3PeerMgr* peerMgr, p3LinkMgr* linkMgr, p3NetMgr* netMgr, - p3ServiceControl* sc, RsGixs* gixs ); - virtual ~p3discovery2(); - -virtual RsServiceInfo getServiceInfo(); - - /************* from pqiServiceMonitor *******************/ - virtual void statusChange(const std::list &plist); - /************* from pqiServiceMonitor *******************/ - - int tick(); - - /* external interface */ - bool getDiscFriends(const RsPeerId &id, std::list &friends); - bool getDiscPgpFriends(const RsPgpId &pgpid, std::list &gpg_friends); - bool getPeerVersion(const RsPeerId &id, std::string &version); - bool getWaitingDiscCount(size_t &sendCount, size_t &recvCount); - - /************* from AuthGPService ****************/ - // virtual AuthGPGOperation *getGPGOperation(); - // virtual void setGPGOperation(AuthGPGOperation *operation); - - -private: - - RsPgpId getPGPId(const RsPeerId &id); - - int handleIncoming(); - void updatePgpFriendList(); - - void addFriend(const RsPeerId &sslId); - void removeFriend(const RsPeerId &sslId); - - void updatePeerAddresses(const RsDiscContactItem *item); - void updatePeerAddressList(const RsDiscContactItem *item); - - void sendOwnContactInfo(const RsPeerId &sslid); - void recvOwnContactInfo(const RsPeerId &fromId, const RsDiscContactItem *item); - - void sendPGPList(const RsPeerId &toId); - void processPGPList(const RsPeerId &fromId, const RsDiscPgpListItem *item); - - void processContactInfo(const RsPeerId &fromId, const RsDiscContactItem *info); - - // send/recv information - - void requestPGPCertificate(const RsPgpId &aboutId, const RsPeerId &toId); - void recvPGPCertificateRequest(const RsPeerId& fromId, const RsDiscPgpListItem* item ); - void sendPGPCertificate(const RsPgpId &aboutId, const RsPeerId &toId); - void recvPGPCertificate(const RsPeerId &fromId, RsDiscPgpKeyItem *item); - void recvIdentityList(const RsPeerId& pid,const std::list& ids); - - bool setPeerVersion(const RsPeerId &peerId, const std::string &version); - - void rsEventsHandler(const RsEvent& event); - RsEventsHandlerId_t mRsEventsHandle; - - p3PeerMgr *mPeerMgr; - p3LinkMgr *mLinkMgr; - p3NetMgr *mNetMgr; - p3ServiceControl *mServiceCtrl; - RsGixs* mGixs; - - /* data */ - RsMutex mDiscMtx; - - void updatePeers_locked(const RsPeerId &aboutId); - void sendContactInfo_locked(const RsPgpId &aboutId, const RsPeerId &toId); - - rstime_t mLastPgpUpdate; - - std::map mFriendList; - std::map mLocationMap; - -// This was used to async the receiving of PGP keys, mainly because PGPHandler cross-checks all signatures, so receiving these keys in large loads can be costly -// Because discovery is not running in the main thread, there's no reason to re-async this into another process (e.g. AuthGPG) -// -// std::list mPendingDiscPgpCertInList; - -protected: - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; diff --git a/libretroshare/src/grouter/groutercache.h b/libretroshare/src/grouter/groutercache.h deleted file mode 100644 index cfaa847b8..000000000 --- a/libretroshare/src/grouter/groutercache.h +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: groutercache.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsflags.h" -#include "rsgrouter.h" - -#define FLAGS_TAG_GROUTER_CACHE 0x22948eb1 - -typedef t_RsFlags32 GRouterCacheInfoFlags ; -typedef uint64_t GRouterMessageId ; - -const uint32_t GROUTER_CACHE_INFO_FLAGS_WAITING_ACK = 0x0001 ; - -class GRouterMessageDataItem -{ - public: - uint8_t *data_bytes ; // data to be sent - uint32_t data_size ; // size of the data - GRouterMessageId message_id ; - GRouterKeyId destination ; - - private: - // Make this class non copiable to avoid memory issues - // - GRouterMessageDataItem& operator=(const GRouterMessageDataItem&) ; - GRouterMessageDataItem(const GRouterMessageDataItem&) ; -}; - -class GRouterCacheInfo -{ - public: - GRouterCacheInfoFlags flags ; - rstime_t last_activity ; -}; - -class GRouterCache -{ - public: - // Stored transitting messages - // - std::list _pending_messages ; - - // Cache of which message is pending, waiting for an ACK, etc. - // - std::map _cache_info ; - - // debug stuff - // - void debugDump() ; -}; - diff --git a/libretroshare/src/grouter/grouterclientservice.h b/libretroshare/src/grouter/grouterclientservice.h deleted file mode 100644 index 394f8421a..000000000 --- a/libretroshare/src/grouter/grouterclientservice.h +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: grouterclientservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -// This class is the parent class for any service that will use the global router to distribute its packets. -// Typical representative clients include: -// -// p3msgservice: sends distant messages and advertise messaging keys -// -#pragma once - -#include -#include -#include - -struct RsItem; - -static const uint32_t GROUTER_CLIENT_SERVICE_DATA_STATUS_UNKNOWN = 0x0000 ; // unused. -static const uint32_t GROUTER_CLIENT_SERVICE_DATA_STATUS_RECEIVED = 0x0001 ; // sent when data has been received and a receipt is available. -static const uint32_t GROUTER_CLIENT_SERVICE_DATA_STATUS_FAILED = 0x0002 ; // sent if the global router cannot send after a while - -class GRouterClientService -{ -public: - // This method is called by the turtle router to send data that comes out of a turtle tunnel. - // The turtle router stays responsible for the memory management of data. Most of the time the - // data chunk is a serialized item to be de-serialized by the client service. - // - // Parameters: - // item : global router item. Handled by the client service. - // destination_key : key that is associated with this item. Can be useful for the client. - // - // GRouter stays owner of the item, so the client should not delete it! - // - virtual void receiveGRouterData(const RsGxsId& destination_key,const RsGxsId& /*signing_key*/, GRouterServiceId &/*client_id*/, uint8_t */*data*/, uint32_t /*data_size*/) - { - std::cerr << "!!!!!! Received Data from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ; - std::cerr << " destination key_id = " << destination_key.toStdString() << std::endl; - } - - // This method is called by the global router when a message has been received, or cannot be sent, etc. - // - virtual void notifyDataStatus(const GRouterMsgPropagationId& received_id,const RsGxsId& signer_id,uint32_t data_status) - { - std::cerr << "!!!!!! Received Data status from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ; - std::cerr << " message ID = " << received_id << std::endl; - std::cerr << " data status = " << data_status << std::endl; - std::cerr << " signer ID = " << signer_id << std::endl; - } - - // This function is mandatory. It should do two things: - // 1 - keep a pointer to the global router, so as to be able to send data (e.g. copy pt into a local variable) - // 2 - call pt->registerTunnelService(this), so that the TR knows that service and can send back information to it. - // - virtual void connectToGlobalRouter(p3GRouter *pt) = 0 ; - - // should be derived to determine wether the client accepts data from this peer or not. If not, the data is dropped. - - virtual bool acceptDataFromPeer(const RsGxsId& gxs_id) =0; -}; - - diff --git a/libretroshare/src/grouter/grouteritems.cc b/libretroshare/src/grouter/grouteritems.cc deleted file mode 100644 index 10c91b222..000000000 --- a/libretroshare/src/grouter/grouteritems.cc +++ /dev/null @@ -1,269 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: grouteritems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include "util/rsprint.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" -#include "grouteritems.h" - -#include "serialiser/rstypeserializer.h" - -/**********************************************************************************************/ -/* SERIALISER STUFF */ -/**********************************************************************************************/ - -RsItem *RsGRouterSerialiser::create_item(uint16_t service_id,uint8_t subtype) const -{ - if(RS_SERVICE_TYPE_GROUTER != service_id) - return NULL; /* wrong type */ - - switch(subtype) - { - case RS_PKT_SUBTYPE_GROUTER_DATA: return new RsGRouterGenericDataItem (); - case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK: return new RsGRouterTransactionChunkItem(); - case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN: return new RsGRouterTransactionAcknItem (); - case RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT: return new RsGRouterSignedReceiptItem (); - case RS_PKT_SUBTYPE_GROUTER_MATRIX_CLUES: return new RsGRouterMatrixCluesItem (); - case RS_PKT_SUBTYPE_GROUTER_MATRIX_TRACK: return new RsGRouterMatrixTrackItem (); - case RS_PKT_SUBTYPE_GROUTER_FRIENDS_LIST: return new RsGRouterMatrixFriendListItem(); - case RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO: return new RsGRouterRoutingInfoItem (); - - default: - return NULL; - } -} - -void RsGRouterTransactionChunkItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,propagation_id,"propagation_id") ; - RsTypeSerializer::serial_process(j,ctx,chunk_start ,"chunk_start") ; - RsTypeSerializer::serial_process(j,ctx,chunk_size ,"chunk_size") ; - RsTypeSerializer::serial_process(j,ctx,total_size ,"total_size") ; - - // Hack for backward compatibility (the chunk size is not directly next to the chunk data) - - if(j == RsGenericSerializer::DESERIALIZE) - { - if(chunk_size > ctx.mSize || ctx.mOffset > ctx.mSize - chunk_size) // better than if(chunk_size + offset > size) - { - std::cerr << __PRETTY_FUNCTION__ << ": Cannot read beyond item size. Serialisation error!" << std::endl; - ctx.mOk = false ; - return ; - } - if( NULL == (chunk_data = (uint8_t*)rs_malloc(chunk_size))) - { - ctx.mOk = false ; - return ; - } - - memcpy(chunk_data,&((uint8_t*)ctx.mData)[ctx.mOffset],chunk_size) ; - ctx.mOffset += chunk_size ; - } - else if(j== RsGenericSerializer::SERIALIZE) - { - memcpy(&((uint8_t*)ctx.mData)[ctx.mOffset],chunk_data,chunk_size) ; - ctx.mOffset += chunk_size ; - } - else if(j== RsGenericSerializer::SIZE_ESTIMATE) - ctx.mOffset += chunk_size ; - else - std::cerr << " [Binary data] " << ", length=" << chunk_size << " data=" << RsUtil::BinToHex((uint8_t*)chunk_data,std::min(50u,chunk_size)) << ((chunk_size>50)?"...":"") << std::endl; - -} -void RsGRouterTransactionAcknItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,propagation_id,"propagation_id") ; -} - -void RsGRouterGenericDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,routing_id,"routing_id") ; - RsTypeSerializer::serial_process (j,ctx,destination_key,"destination_key") ; - RsTypeSerializer::serial_process(j,ctx,service_id,"service_id") ; - - RsTypeSerializer::RawMemoryWrapper prox(data_bytes, data_size); - RsTypeSerializer::serial_process(j, ctx, prox, "data"); - - if(!!(ctx.mFlags & RsSerializationFlags::SIGNATURE)) return; - - RsTypeSerializer::serial_process(j,ctx,signature,"signature") ; - RsTypeSerializer::serial_process(j,ctx,duplication_factor,"duplication_factor") ; - RS_SERIAL_PROCESS(flags); - - if(j == RsGenericSerializer::DESERIALIZE) // make sure the duplication factor is not altered by friends. In the worst case, the item will duplicate a bit more. - { - if(duplication_factor < 1) - { - duplication_factor = 1 ; - std::cerr << "(II) correcting GRouter item duplication factor from 0 to 1, to ensure backward compat." << std::endl; - } - if(duplication_factor > GROUTER_MAX_DUPLICATION_FACTOR) - { - std::cerr << "(WW) correcting GRouter item duplication factor of " << duplication_factor << ". This is very unexpected." << std::endl; - duplication_factor = GROUTER_MAX_DUPLICATION_FACTOR ; - } - } -} - -void RsGRouterSignedReceiptItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,routing_id,"routing_id") ; - RS_SERIAL_PROCESS(flags); - RsTypeSerializer::serial_process (j,ctx,destination_key,"destination_key") ; - RsTypeSerializer::serial_process (j,ctx,service_id,"service_id") ; - RsTypeSerializer::serial_process (j,ctx,data_hash,"data_hash") ; - - if(!!(ctx.mFlags & RsSerializationFlags::SIGNATURE)) return; - - RsTypeSerializer::serial_process(j,ctx,signature,"signature") ; -} - -void RsGRouterRoutingInfoItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,peerId,"peerId") ; - RsTypeSerializer::serial_process(j,ctx,data_status,"data_status") ; - RsTypeSerializer::serial_process(j,ctx,tunnel_status,"tunnel_status") ; - RsTypeSerializer::serial_process (j,ctx,received_time_TS,"received_time_TS") ; - RsTypeSerializer::serial_process (j,ctx,last_sent_TS,"last_sent_TS") ; - - RsTypeSerializer::serial_process (j,ctx,last_tunnel_request_TS,"last_tunnel_request_TS") ; - RsTypeSerializer::serial_process(j,ctx,sending_attempts,"sending_attempts") ; - - RsTypeSerializer::serial_process(j,ctx,client_id,"client_id") ; - RsTypeSerializer::serial_process (j,ctx,item_hash,"item_hash") ; - RsTypeSerializer::serial_process (j,ctx,tunnel_hash,"tunnel_hash") ; - RsTypeSerializer::serial_process(j,ctx,routing_flags,"routing_flags") ; - - RsTypeSerializer::serial_process(j,ctx,incoming_routes,"incoming_routes") ; - - // Hack for backward compatibility. Normally we should need a single commandline to serialise/deserialise a single item here. - // But the full item is serialised, so we need the header. - - if(j == RsGenericSerializer::DESERIALIZE) - { - data_item = new RsGRouterGenericDataItem() ; - - ctx.mOffset += 8 ; - data_item->serial_process(j,ctx) ; - - if(ctx.mOffset < ctx.mSize) - { - receipt_item = new RsGRouterSignedReceiptItem(); - - ctx.mOffset += 8 ; - receipt_item->serial_process(j,ctx) ; - } - else - receipt_item = NULL ; - } - else if(j == RsGenericSerializer::SERIALIZE) - { - uint32_t remaining_size = ctx.mSize - ctx.mOffset; - ctx.mOk = ctx.mOk && RsGRouterSerialiser().serialise(data_item,ctx.mData,&remaining_size) ; - ctx.mOffset += RsGRouterSerialiser().size(data_item) ; - - if(receipt_item != NULL) - { - remaining_size = ctx.mSize - ctx.mOffset; - ctx.mOk = ctx.mOk && RsGRouterSerialiser().serialise(receipt_item,ctx.mData,&remaining_size); - ctx.mOffset += RsGRouterSerialiser().size(receipt_item) ; - } - } - else if(j == RsGenericSerializer::PRINT) - { - std::cerr << " [Serialized data] " << std::endl; - - if(receipt_item != NULL) - std::cerr << " [Receipt item ]" << std::endl; - } - else if(j == RsGenericSerializer::SIZE_ESTIMATE) - { - ctx.mOffset += RsGRouterSerialiser().size(data_item) ; - - if(receipt_item != NULL) - ctx.mOffset += RsGRouterSerialiser().size(receipt_item) ; - } -} - -void RsGRouterMatrixFriendListItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,reverse_friend_indices,"reverse_friend_indices") ; -} - -void RsGRouterMatrixTrackItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,provider_id,"provider_id") ; - RsTypeSerializer::serial_process(j,ctx,message_id,"message_id") ; - RsTypeSerializer::serial_process(j,ctx,time_stamp,"time_stamp") ; -} - -void RsGRouterMatrixCluesItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,destination_key,"destination_key") ; - RsTypeSerializer::serial_process(j,ctx,clues,"clues") ; -} - -template<> void RsTypeSerializer::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,RoutingMatrixHitEntry& s,const std::string& name) -{ - RsTypeSerializer::serial_process(j,ctx,s.friend_id,name+":friend_id") ; - RsTypeSerializer::serial_process (j,ctx,s.weight,name+":weight") ; - RsTypeSerializer::serial_process (j,ctx,s.time_stamp,name+":time_stamp") ; -} - -RsGRouterGenericDataItem *RsGRouterGenericDataItem::duplicate() const -{ - RsGRouterGenericDataItem *item = new RsGRouterGenericDataItem ; - - // copy all members - - *item = *this ; - - // then duplicate the memory chunk - - if(data_size > 0) - { - item->data_bytes = (uint8_t*)rs_malloc(data_size) ; - - if(item->data_bytes == NULL) - { - delete item ; - return NULL ; - } - memcpy(item->data_bytes,data_bytes,data_size) ; - } - else - item->data_bytes = NULL ; - - return item ; -} - -RsGRouterSignedReceiptItem *RsGRouterSignedReceiptItem::duplicate() const -{ - RsGRouterSignedReceiptItem *item = new RsGRouterSignedReceiptItem ; - - // copy all members - - *item = *this ; - - return item ; -} - -RsGRouterAbstractMsgItem::~RsGRouterAbstractMsgItem() = default; diff --git a/libretroshare/src/grouter/grouteritems.h b/libretroshare/src/grouter/grouteritems.h deleted file mode 100644 index 0a12cb3f0..000000000 --- a/libretroshare/src/grouter/grouteritems.h +++ /dev/null @@ -1,296 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: grouteritems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "util/rsmemory.h" - -#include "serialiser/rsserial.h" -#include "serialiser/rstlvkeys.h" -#include "rsitems/rsserviceids.h" -#include "retroshare/rstypes.h" -#include "retroshare/rsflags.h" -#include "retroshare/rsgrouter.h" -#include "groutermatrix.h" - -const uint8_t RS_PKT_SUBTYPE_GROUTER_PUBLISH_KEY = 0x01 ; // used to publish a key -const uint8_t RS_PKT_SUBTYPE_GROUTER_ACK_deprecated = 0x03 ; // don't use! -const uint8_t RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT_deprecated = 0x04 ; // don't use! -const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA_deprecated = 0x05 ; // don't use! -const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA_deprecated2 = 0x06 ; // don't use! -const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA = 0x07 ; // used to send data to a destination (Signed by source) -const uint8_t RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT = 0x08 ; // long-distance acknowledgement of data received -const uint8_t RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK = 0x10 ; // chunk of data. Used internally. -const uint8_t RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN = 0x11 ; // acknowledge for finished transaction. Not necessary, but increases fiability. -const uint8_t RS_PKT_SUBTYPE_GROUTER_MATRIX_CLUES = 0x80 ; // item to save matrix clues -const uint8_t RS_PKT_SUBTYPE_GROUTER_FRIENDS_LIST = 0x82 ; // item to save friend lists -const uint8_t RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO = 0x93 ; // -const uint8_t RS_PKT_SUBTYPE_GROUTER_MATRIX_TRACK = 0x94 ; // item to save matrix track info - -const uint8_t QOS_PRIORITY_RS_GROUTER = 4 ; // relevant for items that travel through friends - - -/***********************************************************************************/ -/* Basic GRouter Item Class */ -/***********************************************************************************/ - -class RsGRouterItem: public RsItem -{ - public: - explicit RsGRouterItem(uint8_t grouter_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_GROUTER,grouter_subtype) {} - - virtual ~RsGRouterItem() {} - - virtual void clear() = 0 ; -}; - -/***********************************************************************************/ -/* Helper base classes */ -/***********************************************************************************/ - -class RsGRouterNonCopyableObject -{ - public: - RsGRouterNonCopyableObject() {} - protected: - RsGRouterNonCopyableObject(const RsGRouterNonCopyableObject&) {} - RsGRouterNonCopyableObject operator=(const RsGRouterNonCopyableObject&) { return *this ;} -}; - -/***********************************************************************************/ -/* Specific packets */ -/***********************************************************************************/ - -// This abstract item class encapsulates 2 types of signed items. All have signature, destination key -// and routing ID. Sub-items are responsible for providing the serialised data to be signed for -// both signing and checking. - -enum class RsGRouterItemFlags : uint32_t -{ - NONE = 0x0, - ENCRYPTED = 0x1, - SERVICE_UNKNOWN = 0x2 -}; -RS_REGISTER_ENUM_FLAGS_TYPE(RsGRouterItemFlags) - -struct RsGRouterAbstractMsgItem: RsGRouterItem -{ - explicit RsGRouterAbstractMsgItem(uint8_t pkt_subtype): - RsGRouterItem(pkt_subtype), flags(RsGRouterItemFlags::NONE) {} - - GRouterMsgPropagationId routing_id ; - GRouterKeyId destination_key ; - GRouterServiceId service_id ; - RsTlvKeySignature signature ; // signs mid+destination_key+state - - /// packet was delivered, not delivered, bounced, etc - RsGRouterItemFlags flags; - - ~RsGRouterAbstractMsgItem(); -}; - -class RsGRouterGenericDataItem: - public RsGRouterAbstractMsgItem, public RsGRouterNonCopyableObject -{ -public: - RsGRouterGenericDataItem(): - RsGRouterAbstractMsgItem(RS_PKT_SUBTYPE_GROUTER_DATA), - data_size(0), data_bytes(nullptr), duplication_factor(0) - { setPriorityLevel(QOS_PRIORITY_RS_GROUTER); } - - virtual ~RsGRouterGenericDataItem() { clear(); } - virtual void clear() - { - free(data_bytes); - data_bytes = nullptr; - } - - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - - RsGRouterGenericDataItem *duplicate() const; - - /// packet data - uint32_t data_size; - uint8_t* data_bytes; - - /** number of duplicates allowed. Should be capped at each de-serialise - * operation! */ - uint32_t duplication_factor; -}; - -class RsGRouterSignedReceiptItem: public RsGRouterAbstractMsgItem -{ - public: - RsGRouterSignedReceiptItem() : RsGRouterAbstractMsgItem(RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; } - virtual ~RsGRouterSignedReceiptItem() {} - - virtual void clear() {} - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsGRouterSignedReceiptItem *duplicate() const ; - - // packet data - // - Sha1CheckSum data_hash ; // avoids an attacker to re-use a given signed receipt. This is the hash of the enceypted data. -}; - -// Low-level data items - -class RsGRouterTransactionItem: public RsGRouterItem -{ - public: - explicit RsGRouterTransactionItem(uint8_t pkt_subtype) : RsGRouterItem(pkt_subtype) {} - - virtual ~RsGRouterTransactionItem() {} - - virtual void clear() =0; - - virtual RsGRouterTransactionItem *duplicate() const = 0 ; -}; - -class RsGRouterTransactionChunkItem: public RsGRouterTransactionItem, public RsGRouterNonCopyableObject -{ -public: - RsGRouterTransactionChunkItem() : RsGRouterTransactionItem(RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK), chunk_start(0), chunk_size(0), total_size(0), chunk_data(NULL) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; } - - virtual ~RsGRouterTransactionChunkItem() { free(chunk_data) ; } - - virtual void clear() {} - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - virtual RsGRouterTransactionItem *duplicate() const - { - RsGRouterTransactionChunkItem *item = new RsGRouterTransactionChunkItem ; - *item = *this ; // copy all fields - item->chunk_data = (uint8_t*)rs_malloc(chunk_size) ; // deep copy memory chunk - - if(item->chunk_data == NULL) - return NULL ; - - memcpy(item->chunk_data,chunk_data,chunk_size) ; - return item ; - } - - GRouterMsgPropagationId propagation_id ; - uint32_t chunk_start ; - uint32_t chunk_size ; - uint32_t total_size ; - uint8_t *chunk_data ; -}; -class RsGRouterTransactionAcknItem: public RsGRouterTransactionItem -{ -public: - RsGRouterTransactionAcknItem() : RsGRouterTransactionItem(RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; } - virtual ~RsGRouterTransactionAcknItem() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - virtual void clear() {} - - virtual RsGRouterTransactionItem *duplicate() const { return new RsGRouterTransactionAcknItem(*this) ; } - - GRouterMsgPropagationId propagation_id ; -}; - -// Items for saving the routing matrix information. - -class RsGRouterMatrixCluesItem: public RsGRouterItem -{ - public: - RsGRouterMatrixCluesItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_MATRIX_CLUES) - { setPriorityLevel(0) ; } // this item is never sent through the network - - virtual void clear() {} - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // packet data - // - GRouterKeyId destination_key ; - std::list clues ; -}; - -class RsGRouterMatrixTrackItem: public RsGRouterItem -{ - public: - RsGRouterMatrixTrackItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_MATRIX_TRACK), time_stamp(0) - { setPriorityLevel(0) ; } // this item is never sent through the network - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - virtual void clear() {} - - // packet data - // - RsGxsMessageId message_id ; - RsPeerId provider_id ; - rstime_t time_stamp ; -}; -class RsGRouterMatrixFriendListItem: public RsGRouterItem -{ - public: - RsGRouterMatrixFriendListItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_FRIENDS_LIST) - { setPriorityLevel(0) ; } // this item is never sent through the network - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - virtual void clear() {} - - // packet data - // - std::vector reverse_friend_indices ; -}; - -class RsGRouterRoutingInfoItem: public RsGRouterItem, public GRouterRoutingInfo, public RsGRouterNonCopyableObject -{ - public: - RsGRouterRoutingInfoItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO) - { setPriorityLevel(0) ; } // this item is never sent through the network - - virtual ~RsGRouterRoutingInfoItem() { clear() ; } - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - virtual void clear() - { - if(data_item != NULL) delete data_item ; - if(receipt_item != NULL) delete receipt_item ; - - data_item = NULL ; - receipt_item = NULL ; - } -}; - -/***********************************************************************************/ -/* Serialisation */ -/***********************************************************************************/ - -class RsGRouterSerialiser: public RsServiceSerializer -{ -public: - explicit RsGRouterSerialiser( - RsSerializationFlags flags = RsSerializationFlags::NONE ): - RsServiceSerializer(RS_SERVICE_TYPE_GROUTER, flags) {} - - virtual RsItem *create_item(uint16_t service,uint8_t subtype) const ; -}; - - diff --git a/libretroshare/src/grouter/groutermatrix.cc b/libretroshare/src/grouter/groutermatrix.cc deleted file mode 100644 index b210f619e..000000000 --- a/libretroshare/src/grouter/groutermatrix.cc +++ /dev/null @@ -1,379 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: groutermatrix.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "groutertypes.h" -#include "groutermatrix.h" -#include "grouteritems.h" - -//#define ROUTING_MATRIX_DEBUG - -GRouterMatrix::GRouterMatrix() -{ - _proba_need_updating = true ; -} - -bool GRouterMatrix::addTrackingInfo(const RsGxsMessageId& mid,const RsPeerId& source_friend) -{ - rstime_t now = time(NULL) ; - - RoutingTrackEntry rte ; - - rte.friend_id = source_friend ; - rte.time_stamp = now ; - - _tracking_clues[mid] = rte ; -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << "GRouterMatrix::addTrackingInfo(): Added clue mid=" << mid << ", from " << source_friend << " ID=" << source_friend << std::endl; -#endif - return true ; -} - -bool GRouterMatrix::cleanUp() -{ - // remove all tracking entries that have become too old. - -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << "GRouterMatrix::cleanup()" << std::endl; -#endif - rstime_t now = time(NULL) ; - - for(std::map::iterator it(_tracking_clues.begin());it!=_tracking_clues.end();) - if(it->second.time_stamp + RS_GROUTER_MAX_KEEP_TRACKING_CLUES < now) - { -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " removing old entry msgId=" << it->first << ", from id " << it->second.friend_id << ", obtained " << (now - it->second.time_stamp) << " secs ago." << std::endl; -#endif - std::map::iterator tmp(it) ; - ++tmp ; - _tracking_clues.erase(it) ; - it=tmp ; - } - else - ++it ; - - return true ; -} - -bool GRouterMatrix::addRoutingClue(const GRouterKeyId& key_id,const RsPeerId& source_friend,float weight) -{ - // 1 - get the friend index. - // - uint32_t fid = getFriendId(source_friend) ; - - // 2 - get the Key map, and add the routing clue. - // - rstime_t now = time(NULL) ; - - RoutingMatrixHitEntry rc ; - rc.weight = weight ; - rc.time_stamp = now ; - rc.friend_id = fid ; - - std::list& lst( _routing_clues[key_id] ) ; - - // Prevent flooding. Happens in two scenarii: - // 1 - a user restarts RS very often => keys get republished for some reason - // 2 - a user intentionnaly floods a key - // - // Solution is to look for all recorded events, and not add any new event if an event came from the same friend - // too close in the past. Going through the list is not costly since it is bounded to RS_GROUTER_MATRIX_MAX_HIT_ENTRIES elemts. - - for(std::list::const_iterator mit(lst.begin());mit!=lst.end();++mit) - if((*mit).friend_id == fid && (*mit).time_stamp + RS_GROUTER_MATRIX_MIN_TIME_BETWEEN_HITS > now) - { -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << "GRouterMatrix::addRoutingClue(): too many clues for key " << key_id.toStdString() << " from friend " << source_friend << " in a small interval of " << now - lst.front().time_stamp << " seconds. Flooding?" << std::endl; -#endif - return false ; - } - - lst.push_front(rc) ; // create it if necessary - - // Remove older elements - // - uint32_t sz = lst.size() ; // O(n)! - - for(uint32_t i=RS_GROUTER_MATRIX_MAX_HIT_ENTRIES;i::const_iterator it = _friend_indices.find(source_friend) ; - - if(it == _friend_indices.end()) - return _reverse_friend_indices.size() ; - else - return it->second ; -} -uint32_t GRouterMatrix::getFriendId(const RsPeerId& source_friend) -{ - std::map::const_iterator it = _friend_indices.find(source_friend) ; - - if(it == _friend_indices.end()) - { - // add a new friend - - uint32_t new_id = _reverse_friend_indices.size() ; - _reverse_friend_indices.push_back(source_friend) ; - _friend_indices[source_friend] = new_id ; - - return new_id ; - } - else - return it->second ; -} - -void GRouterMatrix::getListOfKnownKeys(std::vector& key_ids) const -{ - key_ids.clear() ; - - for(std::map >::const_iterator it(_time_combined_hits.begin());it!=_time_combined_hits.end();++it) - key_ids.push_back(it->first) ; -} - -bool GRouterMatrix::getTrackingInfo(const RsGxsMessageId& mid, RsPeerId &source_friend) -{ - std::map::const_iterator it = _tracking_clues.find(mid) ; - - if(it == _tracking_clues.end()) - return false ; - - source_friend = it->second.friend_id; - - return true ; -} - -void GRouterMatrix::debugDump() const -{ - std::cerr << " Proba needs up: " << _proba_need_updating << std::endl; - std::cerr << " Known keys: " << _time_combined_hits.size() << std::endl; - std::cerr << " Routing events: " << std::endl; - rstime_t now = time(NULL) ; - - for(std::map >::const_iterator it(_routing_clues.begin());it!=_routing_clues.end();++it) - { - std::cerr << " " << it->first.toStdString() << " : " ; - for(std::list::const_iterator it2(it->second.begin());it2!=it->second.end();++it2) - std::cerr << now - (*it2).time_stamp << " (" << (*it2).friend_id << "," << (*it2).weight << ") " ; - - std::cerr << std::endl; - } - std::cerr << " Routing values: " << std::endl; - - for(std::map >::const_iterator it(_time_combined_hits.begin());it!=_time_combined_hits.end();++it) - { - std::cerr << " " << it->first.toStdString() << " : " ; - - for(uint32_t i=0;isecond.size();++i) - std::cerr << it->second[i] << " " ; - std::cerr << std::endl; - } - std::cerr << " Tracking clues: " << std::endl; - - for(std::map::const_iterator it(_tracking_clues.begin());it!=_tracking_clues.end();++it) - std::cerr << " " << it->first << ": from " << it->second.friend_id << " " << now - it->second.time_stamp << " secs ago." << std::endl; -} - -bool GRouterMatrix::computeRoutingProbabilities(const GRouterKeyId& key_id, const std::vector& friends, std::vector& probas, float& maximum) const -{ - // Routing probabilities are computed according to routing clues - // - // For a given key, each friend has a known set of routing clues (rstime_t, weight) - // We combine these to compute a static weight for each friend/key pair. - // This is performed in updateRoutingProbabilities() - // - // Then for a given list of online friends, the weights are computed into probabilities, - // that always sum up to 1. - // -#ifdef ROUTING_MATRIX_DEBUG - if(_proba_need_updating) - std::cerr << "GRouterMatrix::computeRoutingProbabilities(): matrix is not up to date. Not a real problem, but still..." << std::endl; -#endif - - probas.resize(friends.size(),0.0f) ; - float total = 0.0f ; - - std::map >::const_iterator it2 = _time_combined_hits.find(key_id) ; - - if(it2 == _time_combined_hits.end()) - { - // The key is not known. In this case, we return a zero probability for all peers. - // - float p = 0.0f;//1.0f / friends.size() ; - - probas.clear() ; - probas.resize(friends.size(),p) ; - -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << "GRouterMatrix::computeRoutingProbabilities(): key id " << key_id.toStdString() << " does not exist! Returning uniform probabilities." << std::endl; -#endif - return false ; - } - const std::vector& w(it2->second) ; - maximum = 0.0f ; - - for(uint32_t i=0;i= w.size()) - probas[i] = 0.0f ; - else - { - probas[i] = w[findex] ; - total += w[findex] ; - - if(maximum < w[findex]) - maximum = w[findex] ; - } - } - - if(total > 0.0f) - for(uint32_t i=0;i >::const_iterator it(_routing_clues.begin());it!=_routing_clues.end();++it) - { -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " " << it->first.toStdString() << " : " ; -#endif - - std::vector& v(_time_combined_hits[it->first]) ; - v.clear() ; - v.resize(_friend_indices.size(),0.0f) ; - - for(std::list::const_iterator it2(it->second.begin());it2!=it->second.end();++it2) - { - // Half life period is 7 days. - - float time_difference_in_days = 1 + (now - (*it2).time_stamp ) / (7*86400.0f) ; - v[(*it2).friend_id] += (*it2).weight / (time_difference_in_days*time_difference_in_days) ; - } - } -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " done." << std::endl; -#endif - - _proba_need_updating = false ; - return true ; -} - -bool GRouterMatrix::saveList(std::list& items) -{ -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " GRoutingMatrix::saveList()" << std::endl; -#endif - - RsGRouterMatrixFriendListItem *item = new RsGRouterMatrixFriendListItem ; - - item->reverse_friend_indices = _reverse_friend_indices ; - items.push_back(item) ; - - for(std::map >::const_iterator it(_routing_clues.begin());it!=_routing_clues.end();++it) - { - RsGRouterMatrixCluesItem *item = new RsGRouterMatrixCluesItem ; - - item->destination_key = it->first ; - item->clues = it->second ; - - items.push_back(item) ; - } - - for(std::map::const_iterator it(_tracking_clues.begin());it!=_tracking_clues.end();++it) - { - RsGRouterMatrixTrackItem *item = new RsGRouterMatrixTrackItem ; - - item->provider_id = it->second.friend_id ; - item->time_stamp = it->second.time_stamp ; - item->message_id = it->first ; - - items.push_back(item) ; - } - - return true ; -} -bool GRouterMatrix::loadList(std::list& items) -{ - RsGRouterMatrixFriendListItem *itm1 = NULL ; - RsGRouterMatrixCluesItem *itm2 = NULL ; - RsGRouterMatrixTrackItem *itm3 = NULL ; - -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " GRoutingMatrix::loadList()" << std::endl; -#endif - - for(std::list::const_iterator it(items.begin());it!=items.end();++it) - { - if(NULL != (itm3 = dynamic_cast(*it))) - { -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " initing tracking clues." << std::endl; -#endif - RoutingTrackEntry rte ; - rte.friend_id = itm3->provider_id ; - rte.time_stamp = itm3->time_stamp ; - - _tracking_clues[itm3->message_id] = rte; - } - if(NULL != (itm2 = dynamic_cast(*it))) - { -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " initing routing clues." << std::endl; -#endif - - _routing_clues[itm2->destination_key] = itm2->clues ; - _proba_need_updating = true ; // notifies to re-compute all the info. - } - if(NULL != (itm1 = dynamic_cast(*it))) - { - _reverse_friend_indices = itm1->reverse_friend_indices ; - _friend_indices.clear() ; - - for(uint32_t i=0;i<_reverse_friend_indices.size();++i) - _friend_indices[_reverse_friend_indices[i]] = i ; - - _proba_need_updating = true ; // notifies to re-compute all the info. - } - } - - return true ; -} - diff --git a/libretroshare/src/grouter/groutermatrix.h b/libretroshare/src/grouter/groutermatrix.h deleted file mode 100644 index 7630b798d..000000000 --- a/libretroshare/src/grouter/groutermatrix.h +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: groutermatrix.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -#pragma once - -#include - -#include "pgp/rscertificate.h" -#include "retroshare/rsgrouter.h" -#include "groutertypes.h" - -struct RsItem; - -// The routing matrix records the event clues received from each friend -// -struct RoutingMatrixHitEntry -{ - uint32_t friend_id ; // not the full key. Gets too big otherwise! - float weight ; - rstime_t time_stamp ; -}; - -struct RoutingTrackEntry -{ - RsPeerId friend_id ; // not the full key. Gets too big otherwise! - rstime_t time_stamp ; -}; - -class GRouterMatrix -{ - public: - GRouterMatrix() ; - - // Computes the routing probabilities for this id for the given list of friends. - // the computation accounts for the time at which the info was received and the - // weight of each routing hit record. - // - bool computeRoutingProbabilities(const GRouterKeyId& id, const std::vector& friends, std::vector& probas, float &maximum) const ; - - // Update routing probabilities for each key, accounting for all received events, but without - // activity information - // - bool updateRoutingProbabilities() ; - - // Record one routing clue. The events can possibly be merged in time buckets. - // - bool addRoutingClue(const GRouterKeyId& id,const RsPeerId& source_friend,float weight) ; - bool addTrackingInfo(const RsGxsMessageId& id,const RsPeerId& source_friend) ; - - bool saveList(std::list& items) ; - bool loadList(std::list& items) ; - - bool cleanUp() ; - - // Dump info in terminal. - // - void debugDump() const ; - void getListOfKnownKeys(std::vector& key_ids) const ; - - bool getTrackingInfo(const RsGxsMessageId& id,RsPeerId& source_friend); - private: - // returns the friend id, possibly creating a new id. - // - uint32_t getFriendId(const RsPeerId& id) ; - - // returns the friend id. If not exist, returns _reverse_friend_indices.size() - // - uint32_t getFriendId_const(const RsPeerId& id) const; - - // List of events received and computed routing probabilities - // - std::map > _routing_clues ; // received routing clues. Should be saved. - std::map > _time_combined_hits ; // hit matrix after time-convolution filter - std::map _tracking_clues ; // who provided the most recent messages - - // This is used to avoid re-computing probas when new events have been received. - // - bool _proba_need_updating ; - - // Routing weights. These are the result of a time convolution of the routing clues and weights - // recorded in _routing_clues. - // - std::map _friend_indices ; // index for each friend to lookup in the routing matrix Not saved. - std::vector _reverse_friend_indices ;// SSLid corresponding to each friend index. Saved. -}; - diff --git a/libretroshare/src/grouter/groutertypes.h b/libretroshare/src/grouter/groutertypes.h deleted file mode 100644 index 23efdbed6..000000000 --- a/libretroshare/src/grouter/groutertypes.h +++ /dev/null @@ -1,135 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: groutertypes.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include "util/rstime.h" -#include -#include "pgp/rscertificate.h" -#include "turtle/p3turtle.h" -#include "retroshare/rsgrouter.h" - -class RsGRouterGenericDataItem ; -class RsGRouterSignedReceiptItem ; - -static const uint16_t GROUTER_CLIENT_ID_MESSAGES = 0x1001 ; - -static const uint32_t RS_GROUTER_MATRIX_MAX_HIT_ENTRIES = 10 ; // max number of clues to store -static const uint32_t RS_GROUTER_MATRIX_MIN_TIME_BETWEEN_HITS = 60 ; // can be set to up to half the publish time interval. Prevents flooding routes. -static const uint32_t RS_GROUTER_MIN_CONFIG_SAVE_PERIOD = 61 ; // at most save config every 10 seconds -static const uint32_t RS_GROUTER_MAX_KEEP_TRACKING_CLUES = 86400*10 ; // max time for which we keep record of tracking info: 10 days. - -static const float RS_GROUTER_BASE_WEIGHT_ROUTED_MSG = 1.0f ; // base contribution of routed message clue to routing matrix -static const float RS_GROUTER_BASE_WEIGHT_GXS_PACKET = 0.1f ; // base contribution of GXS message to routing matrix -static const float RS_GROUTER_PROBABILITY_THRESHOLD_FOR_RANDOM_ROUTING = 0.01f ; // routing probability under which the routage is performed randomly -static const float RS_GROUTER_PROBABILITY_THRESHOLD_BEST_PEERS_SELECT = 0.5f ; // min ratio of forward proba with respect to best peer. - -static const uint32_t MAX_TUNNEL_WAIT_TIME = 60 ; // wait for 60 seconds at most for a tunnel response. -static const uint32_t MAX_TUNNEL_UNMANAGED_TIME = 600 ; // min time before retry tunnels for that msg. -static const uint32_t MAX_DELAY_FOR_RESEND = 2*86400+300 ; // re-send if held for more than 2 days (cache store period) plus security delay. -static const uint32_t MAX_DESTINATION_KEEP_TIME = 20*86400 ; // keep for 20 days in destination cache to avoid re- -static const uint32_t MAX_RECEIPT_KEEP_TIME = 20*86400 ; // keep for 20 days in destination cache to avoid re- -static const uint32_t TUNNEL_OK_WAIT_TIME = 2 ; // wait for 2 seconds after last tunnel ok, so that we have a complete set of tunnels. -static const uint32_t MAX_GROUTER_DATA_SIZE = 2*1024*1024 ; // 2MB size limit. This is of course arbitrary. -static const uint32_t MAX_TRANSACTION_ACK_WAITING_TIME = 60 ; // wait for at most 60 secs for a ACK. If not restart the transaction. -static const uint32_t DIRECT_FRIEND_TRY_DELAY = 20 ; // wait for 20 secs if no friends available, then try tunnels. -static const uint32_t MAX_INACTIVE_DATA_PIPE_DELAY = 300 ; // clean inactive data pipes for more than 5 mins -static const uint32_t GROUTER_MAX_DUPLICATION_FACTOR = 10 ; // max number of duplicates for a given message to keep in the network -static const uint32_t GROUTER_MAX_BRANCHING_FACTOR = 3 ; // max number of branches, for locally forwarding items - -static const rstime_t RS_GROUTER_DEBUG_OUTPUT_PERIOD = 10 ; // Output everything -static const rstime_t RS_GROUTER_AUTOWASH_PERIOD = 10 ; // Autowash every minute. Not a costly operation. -static const rstime_t RS_GROUTER_MATRIX_UPDATE_PERIOD = 60*10 ; // Check for key advertising every 10 minutes -static const uint32_t GROUTER_ITEM_MAX_CACHE_KEEP_TIME = 2*86400 ; // Cached items are kept for 48 hours at most. - -static const uint32_t RS_GROUTER_DATA_STATUS_UNKNOWN = 0x0000 ; // unknown. Unused. -static const uint32_t RS_GROUTER_DATA_STATUS_PENDING = 0x0001 ; // item is pending. Should be sent asap. -static const uint32_t RS_GROUTER_DATA_STATUS_SENT = 0x0002 ; // item is sent to tunnel or friend. No need to keep sending. -static const uint32_t RS_GROUTER_DATA_STATUS_RECEIPT_OK = 0x0003 ; // item is at destination. -static const uint32_t RS_GROUTER_DATA_STATUS_ONGOING = 0x0004 ; // transaction is ongoing. -static const uint32_t RS_GROUTER_DATA_STATUS_DONE = 0x0005 ; // receipt item has been forward to all routes. We can remove the item. - -static const uint32_t RS_GROUTER_SENDING_STATUS_TUNNEL = 0x0001 ; // item was sent in a tunnel -static const uint32_t RS_GROUTER_SENDING_STATUS_FRIEND = 0x0002 ; // item was sent to a friend - -static const uint32_t RS_GROUTER_TUNNEL_STATUS_UNMANAGED = 0x0000 ; // no tunnel requested atm -static const uint32_t RS_GROUTER_TUNNEL_STATUS_PENDING = 0x0001 ; // tunnel requested to turtle -static const uint32_t RS_GROUTER_TUNNEL_STATUS_READY = 0x0002 ; // tunnel is ready but we're still waiting for various confirmations - -class FriendTrialRecord -{ - public: - RsPeerId friend_id ; // id of the friend - rstime_t time_stamp ; // time of the last tried - float probability ; // probability at which the item was selected - uint32_t nb_friends ; // number of friends at the time of sending the item - - bool serialise(void *data,uint32_t& offset,uint32_t size) const ; - bool deserialise(void *data,uint32_t& offset,uint32_t size) ; -}; - -class GRouterRoutingInfo -{ - // There's no destructor to this class, because the memory is managed elsewhere, which - // ovoids lots of duplications if the class is copied. -public: - GRouterRoutingInfo() - : data_status(0) - , tunnel_status(0) - , received_time_TS(0) - , last_sent_TS(0) - , last_tunnel_request_TS(0) - , sending_attempts(0) - , routing_flags(0) - , data_item(NULL) - , receipt_item(NULL) - , data_transaction_TS(0) // this is not serialised. - {} - - uint32_t data_status ; // pending, waiting, etc. - uint32_t tunnel_status ; // status of tunnel handling. - - rstime_t received_time_TS ; // time at which the item was originally received - rstime_t last_sent_TS ; // last time the item was sent - rstime_t last_tunnel_request_TS ; // last time tunnels have been asked for this item. - uint32_t sending_attempts ; // number of times tunnels have been asked for this peer without success - - GRouterServiceId client_id ; // service ID of the client. Only valid when origin==OwnId - TurtleFileHash tunnel_hash ; // tunnel hash to be used for this item - uint32_t routing_flags ; - - RsGRouterGenericDataItem *data_item ; - RsGRouterSignedReceiptItem *receipt_item ; - - RsTlvPeerIdSet incoming_routes ; - Sha1CheckSum item_hash ; // used to check re-existance, consistency, etc. - - // non serialised data - - rstime_t data_transaction_TS ; - - static const uint32_t ROUTING_FLAGS_ALLOW_TUNNELS = 0x0001; - static const uint32_t ROUTING_FLAGS_ALLOW_FRIENDS = 0x0002; - static const uint32_t ROUTING_FLAGS_IS_ORIGIN = 0x0004; - static const uint32_t ROUTING_FLAGS_IS_DESTINATION = 0x0008; -}; - diff --git a/libretroshare/src/grouter/p3grouter.cc b/libretroshare/src/grouter/p3grouter.cc deleted file mode 100644 index 16148d508..000000000 --- a/libretroshare/src/grouter/p3grouter.cc +++ /dev/null @@ -1,2519 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: p3grouter.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Decentralized routing -// ===================== -// -// Main idea: Each peer holds a local routing table, a matrix with probabilities that each friend -// is a correct path for a given key ID. -// -// The routing tables are updated as messages go back and forth. Successful -// interactions feed the routing table with information of where to route the -// packets. -// -// The routing is kept probabilistic, meaning that the optimal route is not -// always chosen, but the randomness helps updating the routing probabilities. -// -// Services that might use the router (All services really...) -// - Messenger -// - sends/receives messages to distant peers -// - Channels, forums, posted, etc. -// - send messages to the origin of the channel/forum/posted -// -// Decentralized routing algorithm: -// - message passing -// - upward: -// * Forward msg to friends according to probabilities. -// * If all equal, send to all friends (or a rando subset of them). -// * keep the local routing info in a cache that is saved (Which peer issued the msg) -// - which probability was used to chose this friend (will be useful -// to compute the routing contribution if the msg is ACK-ed) -// -// Two probabilities are computed: -// - routing probabilities among connected friends -// * this is computed by the routing matrix -// - branching factor N -// * depends on the depth of the items. Currently branching is 3 at origin and 1 elsewhere. -// * depends on the distribution of probabilities (min and max) -// -// Once computed, -// - the item is forwarded randomly to N peers drawn from the list of connected peers with the given probabilities. -// - the depth of the item is incremented randomly -// -// - downward: look into routing cache. If info not present, drop the item. -// Forward item into stored direction. -// -// - routing probability computation: count number of times a reliable info is obtained from -// which direction for which identity -// * the count is a floating point number, since weights can be assigned to each info -// (especially for importance sampling) -// * init: all friends have equal count of 0 (or 1, well, we'll have to make this right). -// * We use importance sampling, meaning that when peer relays a msg from ID: -// count[ID, peer] += 1.0 / importance -// -// ... where importance was the probability of chosing peer for the -// route upward. -// -// * probability of forward is proportional to count. -// -// - routing cache -// * this cache stores messages IDs (like turtle router) but is saved on disk -// * it is used to remember where to send back responses to messages, and -// with what probability the route was chosen. -// * cache items have a TTL and the cache is cleaned regularly. -// -// - routing matrix -// * the structure is fed by other services, when they receive key IDs. -// * stores for each identity the count of how many times each peer gave reliable info for that ID. -// That information should be enough to route packets in the correct direction. -// * saved to disk. -// * all contributions should have a time stamp. Regularly, the oldest contributions are removed. -// -// - Routed packets: we use a common packet type for all services: -// -// We need two abstract item types: -// -// * Data packet -// - packet unique ID (sha1, or uint64_t) -// - destination ID (for Dn packets, the destination is the source!) -// - packet type: Id request, Message, etc. -// - packet service ID (Can be messenging, channels, etc). -// - packet data (void* + size_t) -// - flags (such as ACK or response required, and packet direction) -// - routed directions and probabilities -// * ACK packet. -// - packet unique ID (the id of the corresponding data) -// - flags (reason for ACK. Could be data delivered, or error, too far, etc) -// -// - Data storage packets -// * We need storage packets for the matrix states. -// * General routing options info? -// -// - Main difficulties: -// * have a good re-try strategy if a msg does not arrive. -// * handle peer availability. In forward mode: easy. In backward mode: -// difficult. We should wait, and send back the packet if possible. -// * robustness -// * security: avoid flooding, and message alteration. -// -// Data pipeline -// ============= -// -// sendData() -// | -// +--> encrypt/sign ---> store in _pending_messages -// -// receiveTurtleData() -// | -// +-------------------------------------------------+ -// tick() | -// | | -// +--> HandleLowLevelServiceItems() | -// | | | -// | +--> handleLowLevelServiceItem(item) <------------+ -// | | -// | +--> handleIncomingTransactionAckItem() -// | | -// | +--> handleIncomingTransactionChunkItem() -// | | -// | +---> addDataChunk() -// | | -// | +---> push item to _incoming_items list -// | -// +--> handleIncoming() -// | | -// | +---> handleIncomingReceiptItem(GRouterSignedReceiptItem*) -// | | | -// | +---> handleIncomingDataItem(GRouterDataItem*) | -// | | | -// | +----------------------------+ -// | | -// | | -// | [for US?] --------------------+-----> verifySignedData() -// | | | -// | +-----> notifyClient() -// | | | -// | | +-----> send Receipt item ---+ -// | | | -// | +----> Store In _pending_messages | -// | | -// +--> routePendingObjects() | -// | | | -// | +--> locked_collectAvailablePeers()/locked_collectAvailableTunnels() | -// | | | -// | +--> sliceDataItem() | -// | | | -// | +--> locked_sendTransactionData() <-----------------------------------------------+ -// | | -// | +--> mTurtle->sendTurtleData(virtual_pid,turtle_item) / sendItem() -// | -// +--> handleTunnels() -// | | -// | +---> mTurtle->stopMonitoringTunnels(hash) ; -// | +---> mTurtle->monitoringTunnels(hash) ; -// | -// +--> autoWash() -// -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include -#include - -#include "util/rsrandom.h" -#include "util/rsprint.h" -#include "util/rsmemory.h" -#include "rsitems/rsconfigitems.h" -#include "services/p3idservice.h" -#include "turtle/p3turtle.h" -#include "gxs/rsgixs.h" -#include "retroshare/rspeers.h" -#include "util/cxx17retrocompat.h" -#include "p3grouter.h" -#include "grouteritems.h" -#include "groutertypes.h" -#include "grouterclientservice.h" - -/**********************/ -//#define GROUTER_DEBUG -/**********************/ - -const std::string p3GRouter::SERVICE_INFO_APP_NAME = "Global Router" ; - -p3GRouter::p3GRouter(p3ServiceControl *sc, RsGixs *is) : - p3Service(), p3Config(), mServiceControl(sc), mTurtle(nullptr), mGixs(is), - grMtx("GRouter"), _changed(false), _debug_enabled(true), - _last_autowash_time(0), _last_matrix_update_time(0), - _last_debug_output_time(0), _last_config_changed(0), - _random_salt(RsRandom::random_u64()), - mMissingKeyQueueMtx("GRouterMissingKeyQueue") -{ addSerialType(new RsGRouterSerialiser()); } - -int p3GRouter::tick() -{ - rstime_t now = time(nullptr); - - // Sort incoming service data - // - handleLowLevelServiceItems() ; - - // Handle high level global router data - // - handleIncoming() ; - - // Take each item in the list of pending messages and receipts. If the destination peer is available - // or if the tunnel is available, the item will be sent there. - // - routePendingObjects() ; - - // clean things up. Remove unused requests, old stuff etc. - - autoWash() ; - - // Go through the list of active tunnel requests and pending objects to ask for new tunnels - // or close existing tunnel requests. - // - handleTunnels() ; - - /* Handle items in mMissingKeyQueue */ - if(now > mMissingKeyQueueCheckLastCheck + mMissingKeyQueueCheckEvery) - { - mMissingKeyQueueCheckLastCheck = now; - - RS_STACK_MUTEX(mMissingKeyQueueMtx); - for(auto it = mMissingKeyQueue.begin(); it != mMissingKeyQueue.end();) - { - const RsGxsId& senderId = it->first->signature.keyId; - if(rsIdentity->isKnownId(senderId)) - { - Dbg2() << __PRETTY_FUNCTION__ << " got key: " << senderId - << " for item pending validation, calling item handler" - << std::endl; - - handleIncomingItem(it->first.get()); - it = mMissingKeyQueue.erase(it); - } - else - { - Dbg3() << __PRETTY_FUNCTION__ << " requesting missing key: " - << senderId << " to validate pending item" << std::endl; - - /* At this point the network status may have varied a lot since - * we received the item, so we don't even know if the peer who - * forwarded the item is still online, moreover the fact that - * after specific request we haven't got the key yet suggests it - * is not a good route toward the key, so request it to all - * available peers */ - rsIdentity->requestIdentity(senderId); - ++it; - } - } - } - - // Update routing matrix - // - if(now > _last_matrix_update_time + RS_GROUTER_MATRIX_UPDATE_PERIOD) - { - RsStackMutex mtx(grMtx) ; - - _last_matrix_update_time = now ; - _routing_matrix.updateRoutingProbabilities() ; // This should be locked. - _routing_matrix.cleanUp() ; // This should be locked. - } - -#ifdef GROUTER_DEBUG - // Debug dump everything - // - if(now > _last_debug_output_time + RS_GROUTER_DEBUG_OUTPUT_PERIOD) - { - _last_debug_output_time = now ; - if(_debug_enabled) - debugDump() ; - } -#endif - - // If content has changed, save config, at most every RS_GROUTER_MIN_CONFIG_SAVE_PERIOD seconds appart - // Otherwise, always save at least every RS_GROUTER_MAX_CONFIG_SAVE_PERIOD seconds - // - if(_changed && now > _last_config_changed + RS_GROUTER_MIN_CONFIG_SAVE_PERIOD) - { -#ifdef GROUTER_DEBUG - grouter_debug() << "p3GRouter::tick(): triggering config save." << std::endl; -#endif - - _changed = false ; - _last_config_changed = now ; - IndicateConfigChanged() ; - } - - return 0 ; -} - -RsSerialiser *p3GRouter::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - - rss->addSerialType(new RsGRouterSerialiser) ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss ; -} - -bool p3GRouter::registerKey(const RsGxsId& authentication_key,const GRouterServiceId& client_id,const std::string& description) -{ - RS_STACK_MUTEX(grMtx) ; - - if(_registered_services.find(client_id) == _registered_services.end()) - { - std::cerr << __PRETTY_FUNCTION__ << ": unable to register key " << authentication_key << " for client id " << client_id << ": client id is not known." << std::endl; - return false ; - } - - GRouterPublishedKeyInfo info ; - info.service_id = client_id ; - info.authentication_key = authentication_key ; - info.description_string = description.substr(0,20); - - Sha1CheckSum hash = makeTunnelHash(authentication_key,client_id) ; - - _owned_key_ids[hash] = info ; -#ifdef GROUTER_DEBUG - grouter_debug() << "Registered the following key: " << std::endl; - grouter_debug() << " Auth GXS Id : " << authentication_key << std::endl; - grouter_debug() << " Client id : " << std::hex << client_id << std::dec << std::endl; - grouter_debug() << " Description : " << info.description_string << std::endl; - grouter_debug() << " Hash : " << hash << std::endl; -#endif - - return true ; -} -bool p3GRouter::unregisterKey(const RsGxsId& key_id,const GRouterServiceId& sid) -{ - RS_STACK_MUTEX(grMtx) ; - - Sha1CheckSum hash = makeTunnelHash(key_id,sid) ; - - const auto it = _owned_key_ids.find(hash); - if(it == _owned_key_ids.end()) - { - RsErr() << __PRETTY_FUNCTION__ << " key " << key_id << " not found." - << std::endl; - return false; - } - -#ifdef GROUTER_DEBUG - grouter_debug() << "p3GRouter::unregistered the following key: " << std::endl; - grouter_debug() << " Key id : " << key_id.toStdString() << std::endl; - grouter_debug() << " Client id : " << std::hex << it->second.service_id << std::dec << std::endl; - grouter_debug() << " Description : " << it->second.description_string << std::endl; -#endif - - _owned_key_ids.erase(it) ; - - return true ; -} -//===========================================================================================================================// -// Service data handling // -//===========================================================================================================================// - -void p3GRouter::handleLowLevelServiceItems() -{ - // While messages read - // - RsItem *item = NULL; - - while(NULL != (item = recvItem())) - { - RsGRouterTransactionItem *gtitem = dynamic_cast(item); - if (gtitem) - { - handleLowLevelServiceItem(gtitem) ; - } - else - { - delete(item); - } - } -} - -void p3GRouter::handleLowLevelServiceItem(RsGRouterTransactionItem *item) -{ - switch(item->PacketSubType()) - { - case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN: - { - RsGRouterTransactionAcknItem *trans_ack_item = dynamic_cast(item); - if (trans_ack_item) - { - handleLowLevelTransactionAckItem(trans_ack_item) ; - } - break ; - } - case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK: - { - RsGRouterTransactionChunkItem *chunk_item = dynamic_cast(item); - if (chunk_item) - { - handleLowLevelTransactionChunkItem(chunk_item) ; - } - break ; - } - default: - std::cerr << "p3GRouter::handleIncoming: Unknown packet subtype " << item->PacketSubType() << std::endl ; - } - delete item; -} - -//===========================================================================================================================// -// Turtle management // -//===========================================================================================================================// - -bool p3GRouter::handleTunnelRequest(const RsFileHash& hash,const RsPeerId& /*peer_id*/) -{ - // tunnel request is answered according to the following rules: - // - we are the destination => always accept - // - we know the destination and have RCPT items to send back => always accept - // - we know the destination and have a route (according to matrix) => accept with high probability - // - we don't know the destination => accept with very low probability - - if(_owned_key_ids.find(hash) == _owned_key_ids.end()) - return false ; - -#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::handleTunnelRequest(). Got req for hash " << hash << ", responding OK" << std::endl; -#endif - return true ; -} - -void p3GRouter::handleLowLevelTransactionChunkItem(RsGRouterTransactionChunkItem *chunk_item) -{ -#ifdef GROUTER_DEBUG - std::cerr << " item is a transaction item." << std::endl; -#endif - - RsPeerId pid = chunk_item->PeerId() ; - - RsGRouterAbstractMsgItem *generic_item = NULL; - { - RS_STACK_MUTEX(grMtx) ; - - generic_item = _incoming_data_pipes[pid].addDataChunk(dynamic_cast(chunk_item->duplicate())) ;// addDataChunk takes ownership over chunk_item - } - - // send to client off-mutex - - if(generic_item == NULL) - return ; - - generic_item->PeerId(pid) ; - -#ifdef GROUTER_DEBUG - std::cerr << " transaction is finished. Passing newly created item to client." << std::endl; - std::cerr << " sending a ACK item" << std::endl; -#endif - - RsGRouterTransactionAcknItem ackn_item ; - ackn_item.propagation_id = generic_item->routing_id ; - locked_sendTransactionData(pid,ackn_item) ; - - { - RS_STACK_MUTEX(grMtx) ; - _incoming_items.push_back(generic_item) ; - } -} - -void p3GRouter::handleLowLevelTransactionAckItem(RsGRouterTransactionAcknItem *trans_ack_item) -{ -#ifdef GROUTER_DEBUG - std::cerr << " item is a transaction ACK." << std::endl; -#endif - RS_STACK_MUTEX(grMtx) ; - - std::map::iterator it=_pending_messages.find(trans_ack_item->propagation_id) ; - - if(it != _pending_messages.end() && it->second.data_status == RS_GROUTER_DATA_STATUS_ONGOING) - { - it->second.data_status = RS_GROUTER_DATA_STATUS_SENT; - it->second.last_sent_TS = time(NULL) ; -#ifdef GROUTER_DEBUG - std::cerr << " setting new status as sent/awaiting receipt." << std::endl; -#endif - } -#ifdef GROUTER_DEBUG - else - std::cerr << " Note: no routing ID corresponds to this ACK item. This probably corresponds to a signed receipt" << std::endl; -#endif -} - -void p3GRouter::receiveTurtleData(const RsTurtleGenericTunnelItem *gitem, const RsFileHash & hash, const RsPeerId &virtual_peer_id, RsTurtleGenericTunnelItem::Direction direction) -{ -#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::receiveTurtleData() " << std::endl; - std::cerr << " Received data for hash : " << hash << std::endl; - std::cerr << " Virtual peer id : " << virtual_peer_id << std::endl; - std::cerr << " Direction : " << direction << std::endl; -#endif - - // turtle data is received. - // This function - // - possibly packs multi-item blocks back together - // - converts it into a grouter generic item (by deserialising it) - - const RsTurtleGenericDataItem *item = dynamic_cast(gitem) ; - - if(item == NULL) - { - std::cerr << " ERROR: item is not a data item. That is an error." << std::endl; - return ; - } -#ifdef GROUTER_DEBUG - std::cerr << " data size : " << item->data_size << std::endl; - std::cerr << " data bytes : " << RsDirUtil::sha1sum((unsigned char*)item->data_bytes,item->data_size) << std::endl; -#endif - - // Items come out of the pipe in order. We need to recover all chunks before we de-serialise the content and have it handled by handleIncoming() - - uint32_t size = item->data_size ; - RsItem *itm = RsGRouterSerialiser().deserialise(item->data_bytes,&size); - -if(itm == NULL) -{ - std::cerr << "(EE) p3GRouter::receiveTurtleData(): cannot de-serialise data. Somthing wrong in the format. Item data (size="<< item->data_size << "): " << RsUtil::BinToHex((char*)item->data_bytes,item->data_size) << std::endl; - return ; -} - - itm->PeerId(virtual_peer_id) ; - - // At this point we can have either a transaction chunk, or a transaction ACK. - // We handle them both here - - RsGRouterTransactionChunkItem *chunk_item = dynamic_cast(itm) ; - RsGRouterTransactionAcknItem *trans_ack_item = NULL; - - if(chunk_item != NULL) - handleLowLevelTransactionChunkItem(chunk_item) ; - else if(NULL != (trans_ack_item = dynamic_cast(itm))) - handleLowLevelTransactionAckItem(trans_ack_item) ; - else - { - std::cerr << " ERROR: cannot deserialise turtle item." << std::endl; - if(itm) - delete itm ; - } -} - -void GRouterTunnelInfo::removeVirtualPeer(const TurtleVirtualPeerId& vpid) -{ - std::set::iterator it = virtual_peers.find(vpid) ; - - if(it == virtual_peers.end()) - { - std::cerr << " ERROR: removing a virtual peer that does not exist. This is an error!" << std::endl; - return ; - } - - virtual_peers.erase(it) ; -} -void GRouterTunnelInfo::addVirtualPeer(const TurtleVirtualPeerId& vpid) -{ - if(virtual_peers.find(vpid) != virtual_peers.end()) - std::cerr << " ERROR: adding a virtual peer that already exist. This is an error!" << std::endl; - - virtual_peers.insert(vpid) ; - - rstime_t now = time(NULL) ; - - if(first_tunnel_ok_TS == 0) first_tunnel_ok_TS = now ; - last_tunnel_ok_TS = now ; -} - -RsGRouterAbstractMsgItem *GRouterDataInfo::addDataChunk(RsGRouterTransactionChunkItem *chunk) -{ - last_activity_TS = time(NULL) ; - - // perform some checking - - if(chunk->total_size > MAX_GROUTER_DATA_SIZE + 10000 || chunk->chunk_size > chunk->total_size || chunk->chunk_start >= chunk->total_size) - { - std::cerr << " ERROR: chunk size is unconsistent, or too large: size=" << chunk->chunk_size << ", start=" << chunk->chunk_start << ", total size=" << chunk->total_size << ". Chunk will be dropped. Data pipe will be reset." << std::endl; - clear() ; - delete chunk ; - return NULL ; - } - - // now add that chunk. - - if(incoming_data_buffer == NULL) - { - if(chunk->chunk_start != 0) - { - std::cerr << " ERROR: chunk numbering is wrong. First chunk is not starting at 0. Dropping." << std::endl; - delete chunk; - return NULL; - } - incoming_data_buffer = chunk ; - } - else - { - if(incoming_data_buffer->chunk_size != chunk->chunk_start || incoming_data_buffer->total_size != chunk->total_size) - { - std::cerr << " ERROR: chunk numbering is wrong. Dropping." << std::endl; - delete chunk ; - delete incoming_data_buffer ; - incoming_data_buffer = NULL ; - return NULL; - } - incoming_data_buffer->chunk_data = (uint8_t*)realloc((uint8_t*)incoming_data_buffer->chunk_data,incoming_data_buffer->chunk_size + chunk->chunk_size) ; - memcpy(&incoming_data_buffer->chunk_data[incoming_data_buffer->chunk_size],chunk->chunk_data,chunk->chunk_size) ; - incoming_data_buffer->chunk_size += chunk->chunk_size ; - - delete chunk ; - } - - // if finished, return it. - - if(incoming_data_buffer->total_size == incoming_data_buffer->chunk_size) - { - RsItem *data_item = RsGRouterSerialiser().deserialise(incoming_data_buffer->chunk_data,&incoming_data_buffer->chunk_size) ; - - delete incoming_data_buffer; - incoming_data_buffer = NULL ; - - return dynamic_cast(data_item) ; - } - else - return NULL ; -} - -void p3GRouter::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) -{ - RS_STACK_MUTEX(grMtx) ; - - // Server side tunnels. This is incoming data. Nothing to do. - -#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::addVirtualPeer(). Received vpid " << virtual_peer_id << " for hash " << hash << ", direction=" << dir << std::endl; - std::cerr << " direction = " << dir << std::endl; -#endif - - // client side. We set the tunnel flags to READY. - - if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER) - { - bool found = false ; - - // linear search. Bad, but not really a problem. New virtual peers come quite rarely. - for(std::map::iterator it(_pending_messages.begin());it!=_pending_messages.end();++it) - if(it->second.tunnel_hash == hash) - { -#ifdef GROUTER_DEBUG - std::cerr << " setting tunnel state to READY." << std::endl; -#endif - it->second.tunnel_status = RS_GROUTER_TUNNEL_STATUS_READY ; - found = true ; - - // don't break here, because we might send multiple items though the same tunnel. - } - - if(!found) - { - std::cerr << " ERROR: cannot find corresponding pending message." << std::endl; - return ; - } - } - if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) - { - } - -#ifdef GROUTER_DEBUG - std::cerr << " adding VPID." << std::endl; -#endif - - _tunnels[hash].addVirtualPeer(virtual_peer_id) ; - -} - -void p3GRouter::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) -{ - RS_STACK_MUTEX(grMtx) ; - -#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::removeVirtualPeer(). Removing vpid " << virtual_peer_id << " for hash " << hash << std::endl; - std::cerr << " removing VPID." << std::endl; -#endif - - // make sure the VPID exists. - - std::map::iterator it = _tunnels.find(hash) ; - - if(it == _tunnels.end()) - { - std::cerr << " no virtual peers at all for this hash: " << hash << "! This is a consistency error." << std::endl; - return ; - } - it->second.removeVirtualPeer(virtual_peer_id) ; - -#ifdef GROUTER_DEBUG - std::cerr << " setting tunnel status in pending message." << std::endl; -#endif - - for(std::map::iterator it2(_pending_messages.begin());it2!=_pending_messages.end();++it2) - if(it2->second.tunnel_hash == hash && it->second.virtual_peers.empty()) - it2->second.tunnel_status = RS_GROUTER_TUNNEL_STATUS_PENDING ; - - if(it->second.virtual_peers.empty()) - { -#ifdef GROUTER_DEBUG - std::cerr << " last virtual peer removed. Also deleting hash entry." << std::endl; -#endif - _tunnels.erase(it) ; - } - -} - -void p3GRouter::connectToTurtleRouter(p3turtle *pt) -{ - mTurtle = pt ; - pt->registerTunnelService(this) ; -} - -//===========================================================================================================================// -// Tunnel management // -//===========================================================================================================================// - -class item_comparator_001 -{ -public: - template - bool operator()(const std::pair& p1,const std::pair& p2) const - { - return p1.first < p2.first ; - } -}; - -void p3GRouter::handleTunnels() -{ - // This function is responsible for asking for tunnels, and removing requests from the turtle router. - // To remove the unnecessary TR activity generated by multiple peers trying to send the same message, - // only peers which haven't passed on any data to direct friends, or for which the best friends are not online - // will be allowed to monitor tunnels. - - // Go through the list of pending messages - // - if tunnels are pending for too long => remove from turtle - // - if item is waiting for too long => tunnels are waitin - - // We need a priority queue of items to handle, starting from the most ancient items, with a delay that varies with - // how much time they have been waiting. When a turtle slot it freed, we take the next item in the queue and - // activate tunnel handling for it. - - // possible pending message status: - // - RS_GROUTER_PENDING_MSG_STATUS_TUNNEL_READY : tunnel is ready. Waiting a few seconds to be used (this is to allow multiple tunnels to come). - // - RS_GROUTER_PENDING_MSG_STATUS_TUNNEL_PENDING : tunnel was asked. - // - RS_GROUTER_PENDING_MSG_STATUS_TUNNEL_UNMANAGED: not tunnel managed at the moment. - - // 1 - make a priority list of messages to ask tunnels for - - // Compute the priority of pending messages, according to the number of attempts and how far in the past they have been tried for the last time. - // Delay after which a message is re-sent, depending on the number of attempts already made. - - RS_STACK_MUTEX(grMtx) ; - -#ifdef GROUTER_DEBUG - if(!_pending_messages.empty()) - { - grouter_debug() << "p3GRouter::handleTunnels()" << std::endl; - grouter_debug() << " building priority list of items to send..." << std::endl; - } -#endif - - rstime_t now = time(NULL) ; - std::vector > priority_list ; - - for(std::map::iterator it=_pending_messages.begin();it!=_pending_messages.end();++it) - { -#ifdef GROUTER_DEBUG - grouter_debug() << " " << std::hex << it->first << std::dec - << ", data_status=" << it->second.data_status << ", tunnel_status=" << it->second.tunnel_status - << ", last received: "<< now - it->second.received_time_TS << " (secs ago)" - << ", last TR: "<< now - it->second.last_tunnel_request_TS << " (secs ago)" - << ", last sent: " << now - it->second.last_sent_TS << " (secs ago) "<< std::endl; -#endif - - if(it->second.data_status == RS_GROUTER_DATA_STATUS_PENDING && (it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS)) - { - if(it->second.tunnel_status == RS_GROUTER_TUNNEL_STATUS_UNMANAGED && it->second.last_tunnel_request_TS + MAX_TUNNEL_UNMANAGED_TIME < now) - { - uint32_t item_delay = now - it->second.last_tunnel_request_TS ; - int item_priority = item_delay ; - -#ifdef GROUTER_DEBUG - grouter_debug() << " delay=" << item_delay << " attempts=" << it->second.sending_attempts << ", priority=" << item_priority << std::endl; -#endif - - if(item_priority > 0) - priority_list.push_back(std::make_pair(item_priority,&it->second)) ; - } - else if(it->second.tunnel_status == RS_GROUTER_TUNNEL_STATUS_PENDING && it->second.last_tunnel_request_TS + MAX_TUNNEL_WAIT_TIME < now) - { - mTurtle->stopMonitoringTunnels(it->second.tunnel_hash) ; - - it->second.tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ; - -#ifdef GROUTER_DEBUG - grouter_debug() << " stopping tunnels for this message." << std::endl; ; -#endif - } -#ifdef GROUTER_DEBUG - else if(it->second.tunnel_status == RS_GROUTER_TUNNEL_STATUS_READY) - grouter_debug() << " tunnel is available. " << std::endl; - else - grouter_debug() << " doing nothing." << std::endl; - - grouter_debug() << std::endl; -#endif - } - else - { -#ifdef GROUTER_DEBUG - std::cerr << " closing pending tunnels." << std::endl; -#endif - mTurtle->stopMonitoringTunnels(it->second.tunnel_hash) ; - - it->second.tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ; - } - - // also check that all tunnels are actually active, to remove any old dead tunnels - // - // if(it->second.tunnel_status == RS_GROUTER_TUNNEL_STATUS_READY) - // { - // std::map::iterator it2 = _tunnels.find(it->second.tunnel_hash) ; - // - // if(it2 == _tunnels.end() || it2->second.virtual_peers.empty()) ; - // { - // std::cerr << " re-setting tunnel status to PENDING, as no tunnels are actually present." << std::endl; - // it->second.tunnel_status = RS_GROUTER_TUNNEL_STATUS_PENDING ; - // } - // } - } -#ifdef GROUTER_DEBUG - if(!priority_list.empty()) - grouter_debug() << " sorting..." << std::endl; -#endif - - - std::sort(priority_list.begin(),priority_list.end(),item_comparator_001()) ; - - // take tunnels from item priority list, and enable tunnel handling, while respecting max number of active tunnels limit - - for(uint32_t i=0;ifirst << " with duplication factor = " << itpid->second << std::endl; -#endif - // delete temporary items - - for(std::list::const_iterator cit=chunks.begin();cit!=chunks.end();++cit) - delete *cit; - } - - data_item->duplication_factor = saved_duplication_factor ; -} - -void p3GRouter::routePendingObjects() -{ - // Go throught he list of pending messages. For those with a peer ready, send the message to that peer. - // The peer might be: - // - a virtual peer id that actually is a tunnel - // - a real friend node - // Tunnels and friends will used whenever available. Of course this might cause a message to arrive multiple times, but we - // don't really care since the GR takes care of duplicates already. - // - // Which tunnels are available is handled by handleTunnels() - // - - rstime_t now = time(NULL) ; - - RS_STACK_MUTEX(grMtx) ; -#ifdef GROUTER_DEBUG - if(!_pending_messages.empty()) - std::cerr << "p3GRouter::routePendingObjects()" << std::endl; -#endif - bool pending_messages_changed = false ; - - for(std::map::iterator it=_pending_messages.begin();it!=_pending_messages.end();++it) - { -#ifdef GROUTER_DEBUG - std::cerr << " message " << std::hex << it->first << std::dec << std::endl; -#endif - if(it->second.data_status == RS_GROUTER_DATA_STATUS_PENDING) - { - // Look for tunnels and friends where to send the data. Send to both. - - std::map peers_and_duplication_factors ; - - if(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS) - locked_collectAvailableTunnels(it->second.tunnel_hash,it->second.data_item->duplication_factor,peers_and_duplication_factors); - - if(!peers_and_duplication_factors.empty()) - { -#ifdef GROUTER_DEBUG - std::cerr << " tunnels available! sending!" << std::endl; -#endif - locked_sendToPeers(it->second.data_item,peers_and_duplication_factors) ; - - // change item state in waiting list - - it->second.data_status = RS_GROUTER_DATA_STATUS_ONGOING ; - it->second.data_transaction_TS = now ; - - pending_messages_changed = true ; - continue ; // no need to seek for friend asynced routes since tunnels directly go to the final destination! - } - - if(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_FRIENDS) - locked_collectAvailableFriends(it->second.data_item->destination_key,it->second.incoming_routes.ids,it->second.data_item->duplication_factor,peers_and_duplication_factors); - - if(!peers_and_duplication_factors.empty()) - { -#ifdef GROUTER_DEBUG - std::cerr << " friends available! sending!" << std::endl; -#endif - locked_sendToPeers(it->second.data_item,peers_and_duplication_factors) ; - - // change item state in waiting list - - it->second.data_status = RS_GROUTER_DATA_STATUS_ONGOING ; - it->second.data_transaction_TS = now ; - - pending_messages_changed = true ; - } - else - { -#ifdef GROUTER_DEBUG - std::cerr << " no direct friends available" << std::endl; -#endif - - if(it->second.received_time_TS + DIRECT_FRIEND_TRY_DELAY < now && !(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS)) - { -#ifdef GROUTER_DEBUG - std::cerr << " enabling tunnels for this message." << std::endl; -#endif - it->second.routing_flags |= GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS ; - } - } - - } - else if(it->second.data_status == RS_GROUTER_DATA_STATUS_ONGOING && now > MAX_TRANSACTION_ACK_WAITING_TIME + it->second.data_transaction_TS) - { -#ifdef GROUTER_DEBUG - std::cerr << " waited too long for this transation. Switching back to PENDING." << std::endl; -#endif - - it->second.data_status = RS_GROUTER_DATA_STATUS_PENDING ; - } - else if(it->second.data_status == RS_GROUTER_DATA_STATUS_SENT) - { - if( (it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_IS_ORIGIN) && it->second.last_sent_TS + MAX_DELAY_FOR_RESEND < now) - { -#ifdef GROUTER_DEBUG - std::cerr << " item was not received. Re-setting status to PENDING" << std::endl; -#endif - it->second.data_status = RS_GROUTER_DATA_STATUS_PENDING ; - } - else - { -#ifdef GROUTER_DEBUG - std::cerr << " item was sent. Desactivating tunnels." << std::endl; -#endif - it->second.routing_flags &= ~GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS ; - } - } - - // We treat this case apart, so as to make sure that receipt items are always forwarded wen possible even if the data_status - // is not set correctly. - - if(it->second.receipt_item != NULL && !it->second.incoming_routes.ids.empty()) - { - // send the receipt through all incoming routes, as soon as it gets delivered. - -#ifdef GROUTER_DEBUG - std::cerr << " receipt should be sent back. Trying all incoming routes..." << std::endl; -#endif - - std::list chunks ; - - for(std::set::iterator it2=it->second.incoming_routes.ids.begin();it2!=it->second.incoming_routes.ids.end();) - if(mServiceControl->isPeerConnected(getServiceInfo().mServiceType,*it2) || mTurtle->isTurtlePeer(*it2)) - { -#ifdef GROUTER_DEBUG - std::cerr << " sending receipt back to " << *it2 << " which is online." << std::endl; -#endif - if(chunks.empty()) - sliceDataItem(it->second.receipt_item,chunks) ; - - for(std::list::const_iterator it3(chunks.begin());it3!=chunks.end();++it3) - locked_sendTransactionData(*it2,*(*it3) ) ; - - // then remove from the set. - std::set::iterator it2tmp = it2 ; - ++it2tmp ; - it->second.incoming_routes.ids.erase(it2) ; - it2 = it2tmp ; - - pending_messages_changed = true ; - } - else - ++it2 ; - - for(std::list::const_iterator cit=chunks.begin();cit!=chunks.end();++cit) - delete *cit; - - // Because signed receipts are small items, we take the bet that if the item could be sent, then it was received. - // otherwise, we should mark that incomng route as being handled, wait for the ACK and deal with it by updating - // it->second.data_status at that time. - - if(it->second.incoming_routes.ids.empty()) - it->second.data_status = RS_GROUTER_DATA_STATUS_DONE ; - } - } - - if(pending_messages_changed) - IndicateConfigChanged() ; -} - -void p3GRouter::locked_collectAvailableFriends(const GRouterKeyId& gxs_id,const std::set& incoming_routes,uint32_t duplication_factor, std::map& friend_peers_and_duplication_factors) -{ - // Old strategy was the following: - // if origin - // send to multiple neighbors : best and random - // else - // send to a single "best" neighbor (determined by threshold over routing probability), - - // New strategy is: - // - // Characteristics of the distribution to look at: - // * who's online, who's not - // * all values quite equal - // * single value well above others - // * largest value is small - // Algorithm: - // - // 0 - encode duplicate factor in routed item and allow at most N duplicates - // - when forwarding to N peers, split the duplication factor into N bins, each being proportional to the forwarding probability. - // Example for N=3 and D=10: - // - // p Calculation Final bin - // - // +-0.21--> 0.21*10=2.1 --> 2 0.1 below - // | - // 10 ----+-0.45--> 0.45*10=4.5 --> 4.6-> 5 0.4 above - // | - // +-0.34--> 0.34*10=3.4 --> 3.0-> 3 0 - // - // - // 1 - get routing probabilities p_i for all peers as well as the maximum proba p before normalization. - // - // Set N = min(3,item->duplication_factor) // max number of friends to route to - // - // if p < threshold // That means the routage info is too old => Fallback to random routing. - // Select N random online friends and forward to them. - // else - // Let p_i be the probabilities of all peers - // Select all online peers for which p_i >= 0.5*p. - // if !empty - // Update duplication factors according to probabilities and number of peers - // Route to these peers - // else - // Keep the item - // - -#ifdef GROUTER_DEBUG - std::cerr << "locked_getAvailableFriends()" << std::endl; - std::cerr << " looking for friends for item to ID " << gxs_id << " duplication factor = " << duplication_factor << std::endl; - std::cerr << " retrieving online friends and all friends lists." << std::endl; -#endif - std::set online_ids ; - std::list all_ids ; - - rsPeers->getFriendList(all_ids) ; - mServiceControl->getPeersConnected(getServiceInfo().mServiceType,online_ids) ; - - std::vector tmp_peers; - - for(std::list::const_iterator it(all_ids.begin());it!=all_ids.end();++it) - tmp_peers.push_back(*it) ; - - std::vector probas; - float maximum = 1.0; - float max_probability = 0.0; - - _routing_matrix.computeRoutingProbabilities(gxs_id, tmp_peers, probas, maximum) ; - -#ifdef GROUTER_DEBUG - std::cerr << " initial routing probabilities (maximum=" << maximum << ")" << std::endl; - for(uint32_t i=0;i using uniform random routing." << std::endl; -#endif - } - else - { - for(uint32_t i=0;i giving up." << std::endl; -#endif - return ; - } - - // now select the N best peers -#ifdef GROUTER_DEBUG - std::cerr << " Remaining peers and routing probabilities:" << std::endl; - for(uint32_t i=0;i > mypairs ; - - for(uint32_t i=0;i 0 && max_count > 0) - { - for(int i=mypairs.size()-1,n=0;i>=0 && n=0 && n=0 && nsecond.last_tunnel_ok_TS + TUNNEL_OK_WAIT_TIME > now) - { -#ifdef GROUTER_DEBUG - std::cerr << ". Still waiting delay (stabilisation)." << std::endl; -#endif - return ; - } - - // for now, just take one. But in the future, we will need some policy to temporarily store objects at proxy peers, etc. - -#ifdef GROUTER_DEBUG - std::cerr << " " << vpit->second.virtual_peers.size() << " virtual peers available. " << std::endl; -#endif - TurtleVirtualPeerId vpid = *(vpit->second.virtual_peers.begin()) ; - - tunnel_peers_and_duplication_factors[vpid] = total_duplication ; -} - -bool p3GRouter::locked_sendTransactionData(const RsPeerId& pid,const RsGRouterTransactionItem& trans_item) -{ - if(mTurtle->isTurtlePeer(pid)) - { -#ifdef GROUTER_DEBUG - std::cerr << " sending to tunnel vpid " << pid << std::endl; -#endif - uint32_t turtle_data_size = RsGRouterSerialiser().size(const_cast(&trans_item)) ; - uint8_t *turtle_data = (uint8_t*)rs_malloc(turtle_data_size) ; - - if(turtle_data == NULL) - return false ; - - if(!RsGRouterSerialiser().serialise(const_cast(&trans_item),turtle_data,&turtle_data_size)) - { - std::cerr << " ERROR: cannot serialise RsGRouterTransactionChunkItem." << std::endl; - - free(turtle_data) ; - return false ; - } - - RsTurtleGenericDataItem *turtle_item = new RsTurtleGenericDataItem ; - - turtle_item->data_size = turtle_data_size ; - turtle_item->data_bytes = turtle_data ; - -#ifdef GROUTER_DEBUG - std::cerr << " sending to vpid " << pid << std::endl; -#endif - mTurtle->sendTurtleData(pid,turtle_item) ; - - return true ; - } - else - { -#ifdef GROUTER_DEBUG - std::cerr << " sending to pid " << pid << std::endl; -#endif - RsGRouterTransactionItem *item_copy = trans_item.duplicate() ; - item_copy->PeerId(pid) ; - - sendItem(item_copy) ; - - return true ; - } -} - -void p3GRouter::autoWash() -{ - bool items_deleted = false ; - rstime_t now = time(nullptr); - - std::map > failed_msgs ; - - { - RS_STACK_MUTEX(grMtx) ; - - for(std::map::iterator it=_pending_messages.begin();it!=_pending_messages.end();) - { - bool delete_entry = false ; - - if(it->second.data_status == RS_GROUTER_DATA_STATUS_DONE ) - { - if(!(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_IS_DESTINATION) || it->second.received_time_TS + MAX_DESTINATION_KEEP_TIME < now) // is the item too old for cache - delete_entry = true ; - } - else if(it->second.data_status == RS_GROUTER_DATA_STATUS_RECEIPT_OK ) - { - if(it->second.received_time_TS + MAX_RECEIPT_KEEP_TIME < now) // is the item too old for cache - delete_entry = true ; - } - else - if(it->second.received_time_TS + GROUTER_ITEM_MAX_CACHE_KEEP_TIME < now) - delete_entry = true ; - - if(delete_entry) - { -#ifdef GROUTER_DEBUG - grouter_debug() << " Removing cached item " << std::hex << it->first << std::dec << std::endl; -#endif - //GRouterClientService *client = NULL ; - //GRouterServiceId service_id = 0; - - if( it->second.data_status != RS_GROUTER_DATA_STATUS_DONE ) - { - GRouterClientService *client = NULL; - - if(locked_getLocallyRegisteredClientFromServiceId(it->second.client_id,client)) - failed_msgs[it->first] = std::make_pair(client,it->second.data_item->signature.keyId) ; - else - std::cerr << " ERROR: client id " << it->second.client_id << " not registered. Consistency error." << std::endl; - } - - delete it->second.data_item ; - - if(it->second.receipt_item != NULL) - delete it->second.receipt_item ; - - std::map::iterator tmp(it) ; - ++tmp ; - _pending_messages.erase(it) ; - it = tmp ; - - items_deleted = true ; - } - else - ++it ; - } - - // also check all existing tunnels - - for(std::map::iterator it = _tunnels.begin();it!=_tunnels.end();++it) - { - std::list vpids_to_remove ; - for(std::set::iterator it2 = it->second.virtual_peers.begin();it2!=it->second.virtual_peers.end();++it2) - if(!mTurtle->isTurtlePeer(*it2)) - { - vpids_to_remove.push_back(*it2) ; -#ifdef GROUTER_DEBUG - std::cerr << " " << *it2 << " is not an active tunnel for hash " << it->first << ". Removing virtual peer id." << std::endl; -#endif - } - - for(std::list::const_iterator it2=vpids_to_remove.begin();it2!=vpids_to_remove.end();++it2) - it->second.removeVirtualPeer(*it2) ; - } - - - // Also clean incoming data pipes - - for(std::map::iterator it(_incoming_data_pipes.begin());it!=_incoming_data_pipes.end();) - if(it->second.last_activity_TS + MAX_INACTIVE_DATA_PIPE_DELAY < now) - { -#ifdef GROUTER_DEBUG - std::cerr << " removing data pipe for peer " << it->first << " which is too old." << std::endl; -#endif - std::map::iterator ittmp = it ; - ++ittmp ; - it->second.clear() ; - _incoming_data_pipes.erase(it) ; - it = ittmp ; - } - else - ++it ; - - /* Cleanup timed out items in mMissingKeyQueue */ - mMissingKeyQueueMtx.lock(); - while( mMissingKeyQueue.begin() != mMissingKeyQueue.end() && - mMissingKeyQueue.front().second <= now ) - { - RsWarn() << __PRETTY_FUNCTION__ << " Deleting timed out item from " - << "unknown RsGxsId: " - << mMissingKeyQueue.front().first->signature.keyId - << std::endl; - mMissingKeyQueue.pop_front(); - } - mMissingKeyQueueMtx.unlock(); - } - // Look into pending items. - - for(std::map >::const_iterator it(failed_msgs.begin());it!=failed_msgs.end();++it) - { -#ifdef GROUTER_DEBUG - std::cerr << " notifying client for message id " << std::hex << it->first << " state = FAILED" << std::endl; -#endif - it->second.first->notifyDataStatus(it->first,it->second.second ,GROUTER_CLIENT_SERVICE_DATA_STATUS_FAILED) ; - } - - if(items_deleted) - _changed = true ; -} - -bool p3GRouter::sliceDataItem(RsGRouterAbstractMsgItem *item,std::list& chunks) -{ - try - { - // Split the item into chunks. This function ensures that chunks in the list are valid. Memory ownership is left to the - // calling client. In case of error, all allocated memory is deleted. - -#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::sliceDataItem()" << std::endl; - std::cerr << "item dump before send:" << std::endl; - item->print(std::cerr, 2) ; -#endif - - uint32_t size = RsGRouterSerialiser().size(item); - - RsTemporaryMemory data(size) ; // data will be freed on return, whatever the route taken. - - if(data == NULL) - { - std::cerr << " ERROR: cannot allocate memory. Size=" << size << std::endl; - throw ; - } - - if(!RsGRouterSerialiser().serialise(item,data,&size)) - { - std::cerr << " ERROR: cannot serialise." << std::endl; - throw ; - } - - uint32_t offset = 0 ; - static const uint32_t CHUNK_SIZE = 15000 ; - - while(offset < size) - { - uint32_t chunk_size = std::min(size - offset, CHUNK_SIZE) ; - - RsGRouterTransactionChunkItem *chunk_item = new RsGRouterTransactionChunkItem ; - - chunk_item->propagation_id = item->routing_id ; - chunk_item->total_size = size; - chunk_item->chunk_start= offset; - chunk_item->chunk_size = chunk_size ; - chunk_item->chunk_data = (uint8_t*)rs_malloc(chunk_size) ; -#ifdef GROUTER_DEBUG - std::cerr << " preparing to send a chunk [" << offset << " -> " << offset + chunk_size << " / " << size << "]" << std::endl; -#endif - - if(chunk_item->chunk_data == NULL) - { - delete chunk_item; - throw ; - } - memcpy(chunk_item->chunk_data,&data[offset],chunk_size) ; - - offset += chunk_size ; - - chunks.push_back(chunk_item) ; - } - - return true ; - } - catch(...) - { - for(std::list::const_iterator it(chunks.begin());it!=chunks.end();++it) - delete *it ; - - chunks.clear() ; - - return false ; - } -} - -void p3GRouter::handleIncoming() -{ - while(!_incoming_items.empty()) - { - RsGRouterAbstractMsgItem *item = _incoming_items.front() ; - _incoming_items.pop_front() ; - - handleIncomingItem(item); - delete item ; - } -} - -void p3GRouter::handleIncomingItem(const RsGRouterAbstractMsgItem *item) -{ - const RsGRouterGenericDataItem *generic_data_item ; - const RsGRouterSignedReceiptItem *receipt_item ; - - if(NULL != (generic_data_item = dynamic_cast(item))) - handleIncomingDataItem(generic_data_item) ; - else if(NULL != (receipt_item = dynamic_cast(item))) - handleIncomingReceiptItem(receipt_item) ; - else - std::cerr << "Item has unknown type (not data nor signed receipt). Dropping!" << std::endl; -} - -void p3GRouter::handleIncomingReceiptItem(const RsGRouterSignedReceiptItem *receipt_item) -{ - bool changed = false ; -#ifdef GROUTER_DEBUG - std::cerr << "Handling incoming signed receipt item." << std::endl; - std::cerr << "Item content:" << std::endl; - const_cast(receipt_item)->print(std::cerr,2) ; -#endif - RsGxsId signer_id ; - - // Because we don't do proxy-transmission yet, the client needs to be notified. Otherwise, we will need to - // first check if we're a proxy or not. We also remove the message from the global router sending list. - // in the proxy case, we should only store the receipt. - - GRouterClientService *client_service = NULL; - GRouterMsgPropagationId mid = 0 ; - - { - RS_STACK_MUTEX (grMtx) ; - - std::map::iterator it=_pending_messages.find(receipt_item->routing_id) ; - if(it == _pending_messages.end()) - { - std::cerr << " ERROR: no routing ID corresponds to this message. Inconsistency!" << std::endl; - return ; - } - signer_id = it->second.data_item->signature.keyId ; - - // check hash. - - if(receipt_item->data_hash != it->second.item_hash) - { - std::cerr << " checking receipt hash : FAILED. Receipt is dropped." << std::endl; - return ; - } -#ifdef GROUTER_DEBUG - else - std::cerr << " checking receipt hash : OK" << std::endl; -#endif - // check signature. The policy if the following: - // if we're the destination: - // signature should check and signing key should be available // always ensures the receipt is valid - // else - // if key is available, signature should check // early protects against frodulent receipts that we can check - - uint32_t error_status ; - - if(! verifySignedDataItem(receipt_item,RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CHECK,error_status)) - if( (it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_IS_ORIGIN) || (error_status != RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE)) - { - std::cerr << " checking receipt signature : FAILED. Receipt is dropped. Error status=" << error_status << std::endl; - return ; - } -#ifdef GROUTER_DEBUG - std::cerr << " checking receipt signature : OK. " << std::endl; - std::cerr << " removing messsage from cache." << std::endl; -#endif - - if(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_IS_ORIGIN) - { -#ifdef GROUTER_DEBUG - std::cerr << " message is at origin. Setting message transmission to DONE" << std::endl; -#endif - it->second.data_status = RS_GROUTER_DATA_STATUS_DONE; - - if(locked_getLocallyRegisteredClientFromServiceId(it->second.client_id,client_service)) - mid = it->first ; - else - { - mid = 0 ; - std::cerr << " ERROR: cannot retrieve service ID for message " << std::hex << it->first << std::dec << std::endl; - } - } - else - { -#ifdef GROUTER_DEBUG - std::cerr << " message is not at origin. Setting message transmission to RECEIPT_OK" << std::endl; -#endif - it->second.data_status = RS_GROUTER_DATA_STATUS_RECEIPT_OK; - it->second.receipt_item = receipt_item->duplicate() ; - } - - changed = true ; - } - - if(mid != 0) - { -#ifdef GROUTER_DEBUG - std::cerr << " notifying client " << (void*)client_service << " that msg " << std::hex << mid << std::dec << " was received." << std::endl; -#endif - client_service->notifyDataStatus(mid, signer_id, GROUTER_CLIENT_SERVICE_DATA_STATUS_RECEIVED) ; - } - - // also note the incoming route in the routing matrix - - if(!mTurtle->isTurtlePeer(receipt_item->PeerId())) - { -#ifdef GROUTER_DEBUG - std::cerr << " receipt item comes from a direct friend. Marking route in routing matrix." << std::endl; -#endif - addRoutingClue(receipt_item->signature.keyId,receipt_item->PeerId()) ; - } - - if(changed) - IndicateConfigChanged() ; -} - -Sha1CheckSum p3GRouter::computeDataItemHash(const RsGRouterGenericDataItem *data_item) -{ - RsGRouterSerialiser signature_serializer( - RsSerializationFlags::SIGNATURE | - RsSerializationFlags::SKIP_HEADER ); - - uint32_t signed_data_size = signature_serializer.size(const_cast(data_item)); - uint32_t total_size = signed_data_size + data_item->signature.TlvSize() ; - RsTemporaryMemory mem(total_size) ; - - uint32_t offset = 0 ; - uint32_t tmp_size = total_size ; - signature_serializer.serialise(const_cast(data_item),mem,&tmp_size) ; - if(tmp_size != signed_data_size) - std::cerr << "(EE) Some error occured in p3GRouter::computeDataItemHash(). Mismatched offset/data size" << std::endl; - - offset += tmp_size ; - - data_item->signature.SetTlv(mem, total_size,&offset) ; - - if(offset != total_size) - std::cerr << "(EE) Some error occured in p3GRouter::computeDataItemHash(). Mismatched offset/data size" << std::endl; - - return RsDirUtil::sha1sum(mem,total_size) ; -} - -void p3GRouter::handleIncomingDataItem(const RsGRouterGenericDataItem *data_item) -{ -#ifdef GROUTER_DEBUG - std::cerr << "Handling incoming data item. " << std::endl; - std::cerr << "Item content:" << std::endl; - const_cast(data_item)->print(std::cerr,2) ; -#endif - - // we find 3 things: - // A - is the item for us ? - // B - signature and hash check ? - // C - item is already known ? - - // Store the item? if !C - // Send a receipt? if A && B - // Notify client? if A && !C - // - GRouterClientService *clientService = NULL ; - GRouterServiceId service_id = data_item->service_id ; - RsGRouterSignedReceiptItem *receipt_item = NULL ; - - Sha1CheckSum item_hash = computeDataItemHash(data_item) ; - - bool item_is_already_known = false ; - bool cache_has_changed = false ; - bool item_is_for_us = _owned_key_ids.find( makeTunnelHash(data_item->destination_key,service_id) ) != _owned_key_ids.end() ; - - // A - Find client and service ID from destination key. -#ifdef GROUTER_DEBUG - std::cerr << " step A: find if the item is for us or not, and whether it's aready in cache or not." << std::endl; -#endif - { - RS_STACK_MUTEX(grMtx) ; - - // also check wether this item is for us or not - -#ifdef GROUTER_DEBUG - std::cerr << " item is " << (item_is_for_us?"":"not") << " for us." << std::endl; -#endif - auto it = _pending_messages.find(data_item->routing_id) ; - - if(it != _pending_messages.end()) - { - if(it->second.item_hash != item_hash) - { -#ifdef GROUTER_DEBUG - std::cerr << " ERROR: item is already known but data hash does not match. Dropping that item." << std::endl; -#endif - return ; - } - item_is_already_known = true ; - receipt_item = it->second.receipt_item ; -#ifdef GROUTER_DEBUG - std::cerr << " item is already in cache." << std::endl; -#endif - } -#ifdef GROUTER_DEBUG - else - std::cerr << " item is new." << std::endl; -#endif - } - - if(!item_is_already_known) - { - uint32_t error_status ; - - if(!verifySignedDataItem(data_item,RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CHECK,error_status)) // we should get proper flags out of this - { - switch(error_status) - { - case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: - { - RS_STACK_MUTEX(mMissingKeyQueueMtx); - - rstime_t timeout = time(nullptr) + mMissingKeyQueueEntryTimeout; - RsGxsId authorId = data_item->signature.keyId; - mMissingKeyQueue.push_back( std::make_pair(std::unique_ptr(data_item->duplicate()), timeout) ); - - /* Do not request the missing key here to the peer which forwarded the item as verifySignedDataItem(...) does it already */ - - RsInfo() << __PRETTY_FUNCTION__ << " Received a message from unknown RsGxsId: " << authorId <<". Cannot verify signature yet, storing in mMissingKeyQueue for later processing. Timeout: " << timeout << std::endl; - return; - } - default: - RsWarn() << __PRETTY_FUNCTION__ << " item signature verification FAILED with: " << error_status << ", Dropping!" << std::endl; - return; - } - } -#ifdef GROUTER_DEBUG - else - std::cerr << " verifying item signature: CHECKED!" ; -#endif - } - - // At this point, if item is already known, it is guarrantied to be identical to the stored item. - // If the item is for us, and not already known, check the signature and hash, and generate a signed receipt - - if(item_is_for_us && !item_is_already_known) - { - // Check that we actually have a registered service ready to accept this item. If not, drop it. - - { - RS_STACK_MUTEX(grMtx) ; - auto its = _registered_services.find(service_id) ; - - if(its != _registered_services.end()) - clientService = its->second ; - } - -#ifdef GROUTER_DEBUG - std::cerr << " step B: item is for us and is new, so make sure it's authentic and create a receipt" << std::endl; -#endif - // No we need to send a signed receipt to the sender. - - receipt_item = new RsGRouterSignedReceiptItem; - receipt_item->data_hash = item_hash ; - receipt_item->service_id = data_item->service_id ; - receipt_item->routing_id = data_item->routing_id ; - receipt_item->destination_key = data_item->signature.keyId ; - receipt_item->flags = RsGRouterItemFlags::NONE ; - - if(!clientService) - { - receipt_item->flags = RsGRouterItemFlags::SERVICE_UNKNOWN; - RsWarn() << __PRETTY_FUNCTION__ << " got a message from: " << data_item->signature.keyId << " for an unkown service: " << data_item->service_id << " is your RetroShare version updated?" << std::endl; - } - -#ifdef GROUTER_DEBUG - std::cerr << " preparing signed receipt." << std::endl; -#endif - - if(!signDataItem(receipt_item,data_item->destination_key)) - { - std::cerr << " signing: FAILED. Receipt dropped. ERROR. Packet dropped as well." << std::endl; - return ; - } -#ifdef GROUTER_DEBUG - std::cerr << " signing: OK." << std::endl; -#endif - } -#ifdef GROUTER_DEBUG - else - std::cerr << " step B: skipped, since item is not for us, or already known." << std::endl; -#endif - - // now store the item in _pending_messages whether it is for us or not (if the item is for us, this prevents receiving multiple - // copies of the message) -#ifdef GROUTER_DEBUG - std::cerr << " step C: store the item is cache." << std::endl; -#endif - { - RS_STACK_MUTEX(grMtx) ; - - GRouterRoutingInfo& info(_pending_messages[data_item->routing_id]) ; - - if(info.data_item == NULL) // item is not for us - { -#ifdef GROUTER_DEBUG - std::cerr << " item is new. Storing it." << std::endl; -#endif - - info.data_item = data_item->duplicate() ; - info.receipt_item = receipt_item ; // inited before, or NULL. - info.tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ; - info.last_sent_TS = 0 ; - info.client_id = data_item->service_id ; - info.item_hash = item_hash ; - info.last_tunnel_request_TS = 0 ; - info.sending_attempts = 0 ; - info.received_time_TS = time(NULL) ; - info.tunnel_hash = makeTunnelHash(data_item->destination_key,data_item->service_id) ; - - if(item_is_for_us) - { - // don't store if item is for us. No need to take that much memory. - - free(info.data_item->data_bytes) ; - info.data_item->data_size = 0 ; - info.data_item->data_bytes = NULL ; - - info.routing_flags = GRouterRoutingInfo::ROUTING_FLAGS_IS_DESTINATION | GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_FRIENDS ; - info.data_status = RS_GROUTER_DATA_STATUS_RECEIPT_OK ; - } - else - { - info.routing_flags = GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_FRIENDS ; // don't allow tunnels just yet - info.data_status = RS_GROUTER_DATA_STATUS_PENDING ; - } - } -#ifdef GROUTER_DEBUG - else - std::cerr << " item is already in cache." << std::endl; - - std::cerr << " storing incoming route from " << data_item->PeerId() << std::endl; -#endif - info.incoming_routes.ids.insert(data_item->PeerId()) ; - cache_has_changed = true ; - } - - // if the item is for us and is not already known, notify the client. - - if(clientService && !item_is_already_known) - { - // compute the hash before decryption. - -#ifdef GROUTER_DEBUG - std::cerr << " step D: item is for us and is new: decrypting and notifying client." << std::endl; -#endif - RsGRouterGenericDataItem *decrypted_item = data_item->duplicate() ; - - if(!decryptDataItem(decrypted_item)) - { - std::cerr << " decrypting item : FAILED! Item cannot be passed to the client." << std::endl; - delete decrypted_item ; - - return ; - } -#ifdef GROUTER_DEBUG - else - std::cerr << " decrypting item : OK!" << std::endl; - - std::cerr << " notyfying client." << std::endl; -#endif - if(clientService->acceptDataFromPeer(decrypted_item->signature.keyId)) - { - clientService->receiveGRouterData(decrypted_item->destination_key,decrypted_item->signature.keyId,service_id,decrypted_item->data_bytes,decrypted_item->data_size); - - decrypted_item->data_bytes = NULL ; - decrypted_item->data_size = 0 ; - } - - delete decrypted_item ; - } -#ifdef GROUTER_DEBUG - else - std::cerr << " step D: item is not for us or not new: skipping this step." << std::endl; -#endif - - if(cache_has_changed) - IndicateConfigChanged() ; -} - -bool p3GRouter::locked_getLocallyRegisteredClientFromServiceId(const GRouterServiceId& service_id,GRouterClientService *& client) -{ - client = NULL ; - - std::map::const_iterator its = _registered_services.find(service_id) ; - - if(its == _registered_services.end()) - { - std::cerr << " ERROR: client id " << service_id << " not registered. Consistency error." << std::endl; - return false; - } - - client = its->second ; - - return true ; -} - -void p3GRouter::addRoutingClue(const RsGxsId& id, const RsPeerId& peer_id) -{ - RS_STACK_MUTEX(grMtx) ; -#ifdef GROUTER_DEBUG - grouter_debug() << "Received new routing clue for key " << id << " from peer " << peer_id << std::endl; -#endif - _routing_matrix.addRoutingClue(id,peer_id,RS_GROUTER_BASE_WEIGHT_GXS_PACKET) ; - _changed = true ; -} - -bool p3GRouter::registerClientService(const GRouterServiceId& id,GRouterClientService *service) -{ - RS_STACK_MUTEX(grMtx) ; - _registered_services[id] = service ; - return true ; -} - -bool p3GRouter::encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& destination_key) -{ - assert(!(item->flags & RsGRouterItemFlags::ENCRYPTED)); - -#ifdef GROUTER_DEBUG - std::cerr << " Encrypting data for key " << destination_key << std::endl; - std::cerr << " Decrypted size = " << item->data_size << std::endl; -#endif - - uint8_t *encrypted_data =NULL; - uint32_t encrypted_size =0; - uint32_t error_status ; - - if(!mGixs->encryptData( item->data_bytes, item->data_size, encrypted_data, - encrypted_size, destination_key, error_status, - true )) - { - std::cerr << "(EE) Cannot encrypt: " ; - if(error_status == RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE) std::cerr << " key not available for ID = " << destination_key << std::endl; - if(error_status == RsGixs::RS_GIXS_ERROR_UNKNOWN ) std::cerr << " unknown error for ID = " << destination_key << std::endl; - - return false ; - } - - free(item->data_bytes) ; - item->data_bytes = encrypted_data ; - item->data_size = encrypted_size ; - item->flags |= RsGRouterItemFlags::ENCRYPTED; - -#ifdef GROUTER_DEBUG - std::cerr << " Encrypted size = " << encrypted_size << std::endl; - std::cerr << " First bytes of encrypted data: " << RsUtil::BinToHex((const char *)encrypted_data,std::min(encrypted_size,30u)) << "..."<< std::endl; - std::cerr << " Encrypted data hash = " << RsDirUtil::sha1sum((const uint8_t *)encrypted_data,encrypted_size) << std::endl; -#endif -return true ; -} -bool p3GRouter::decryptDataItem(RsGRouterGenericDataItem *item) -{ - assert(!!(item->flags & RsGRouterItemFlags::ENCRYPTED)); - -#ifdef GROUTER_DEBUG - std::cerr << " decrypting data for key " << item->destination_key << std::endl; - std::cerr << " encrypted size = " << item->data_size << std::endl; -#endif - - uint8_t *decrypted_data =NULL; - uint32_t decrypted_size =0; - uint32_t error_status ; - - if(!mGixs->decryptData( item->data_bytes, item->data_size, decrypted_data, - decrypted_size, item->destination_key, error_status, - true )) - { - if(error_status == RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE) - std::cerr << "(EE) Cannot decrypt incoming message. Key " << item->destination_key << " unknown." << std::endl; - else - std::cerr << "(EE) Cannot decrypt incoming message. Unknown error. " << std::endl; - - return false ; - } - - free(item->data_bytes) ; - item->data_bytes = decrypted_data ; - item->data_size = decrypted_size ; - item->flags &= ~RsGRouterItemFlags::ENCRYPTED; - - return true ; -} - -bool p3GRouter::signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& signing_id) -{ - try - { -//#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::signDataItem()" << std::endl; - std::cerr << " Key ID = " << signing_id << std::endl; - std::cerr << " Getting key material..." << std::endl; -//#endif - RsGRouterSerialiser signature_serializer( - RsSerializationFlags::SIGNATURE | - RsSerializationFlags::SKIP_HEADER ); - uint32_t data_size = signature_serializer.size(item) ; - RsTemporaryMemory data(data_size) ; - - if(data == NULL) - throw std::runtime_error("Cannot allocate memory for signing data.") ; - - if(!signature_serializer.serialise(item,data,&data_size)) - throw std::runtime_error("Cannot serialise signed data.") ; - - uint32_t error_status ; - - std::cerr << "GRouter::signing data" << std::endl; - std::cerr << " size: " << data_size << std::endl; - std::cerr << " data: " << RsUtil::BinToHex(data,data_size) << std::endl; - - if(!mGixs->signData(data,data_size,signing_id,item->signature,error_status)) - throw std::runtime_error("Cannot sign for id " + signing_id.toStdString() + ". Signature call failed.") ; - -//#ifdef GROUTER_DEBUG - std::cerr << "Created signature for data hash: " << RsDirUtil::sha1sum(data,data_size) << " and key id=" << signing_id << std::endl; -//#endif - // Check signature - RsIdentityUsage::UsageCode info = RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CREATION; - uint32_t error; - - if(verifySignedDataItem(item,info,error)) - std::cerr << "Signature checks." << std::endl; - else - { - std::cerr << "(EE) Cannot verify own signed item. Something's wrong." << std::endl; - return false ; - } - - return true ; - } - catch(std::exception& e) - { - std::cerr << " signing failed. Error: " << e.what() << std::endl; - - item->signature.TlvClear() ; - return false ; - } -} -bool p3GRouter::verifySignedDataItem(const RsGRouterAbstractMsgItem *item,const RsIdentityUsage::UsageCode& info,uint32_t& error_status) -{ - try - { - if( rsReputations->overallReputationLevel(item->signature.keyId) == - RsReputationLevel::LOCALLY_NEGATIVE ) - { - RsWarn() << __PRETTY_FUNCTION__ << " received global router " - << "message from banned identity " << item->signature.keyId - << ". Rejecting the message." << std::endl; - return false; - } - - RsGRouterSerialiser signature_serializer( - RsSerializationFlags::SIGNATURE | - RsSerializationFlags::SKIP_HEADER ); - - uint32_t data_size = signature_serializer.size(const_cast(item)); // the const cast shouldn't be necessary if size() took a const. - RsTemporaryMemory data(data_size); - - if(data == NULL) - throw std::runtime_error("Cannot allocate data.") ; - - if(!signature_serializer.serialise(const_cast(item),data,&data_size)) - throw std::runtime_error("Cannot serialise signed data."); - - RsIdentityUsage use(RsServiceType::GROUTER,info); - - if(!mGixs->validateData( data, data_size, item->signature, true, use, error_status )) - { - switch(error_status) - { - case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: - { - std::list peer_ids; - peer_ids.push_back(item->PeerId()); - - RsWarn() << __PRETTY_FUNCTION__ << " Key for GXS Id " << item->signature.keyId << " is not available. Cannot verify. Asking key to peer " << item->PeerId() << std::endl; - mGixs->requestKey(item->signature.keyId,peer_ids,use); - } - break; - case RsGixs::RS_GIXS_ERROR_SIGNATURE_MISMATCH: - RsWarn() << __PRETTY_FUNCTION__ << " Signature mismatch. " << "Spoofing/Corrupted/MITM?." << std::endl; - break; - default: - RsErr() << __PRETTY_FUNCTION__ << " Signature verification failed on GRouter message. Unknown error status: " << error_status << std::endl; - break; - } - return false; - } - - return true; - } - catch(std::exception& e) - { - RsErr() << __PRETTY_FUNCTION__ << " Failed. Error: " << e.what() << std::endl; - return false ; - } -} - -bool p3GRouter::cancel(GRouterMsgPropagationId mid) -{ - { - RS_STACK_MUTEX(grMtx) ; - -#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::cancel(). Canceling message ID " << mid << std::endl; -#endif - - std::map::iterator it = _pending_messages.find(mid) ; - - if(it == _pending_messages.end()) - { - std::cerr << " ERROR: message ID is unknown." << std::endl; - return false ; - } - - delete it->second.data_item ; - if(it->second.receipt_item) - delete it->second.receipt_item; - - _pending_messages.erase(it) ; - } - - IndicateConfigChanged() ; - - return true ; -} - -bool p3GRouter::sendData( const RsGxsId& destination, const GRouterServiceId& client_id, const uint8_t* data, uint32_t data_size, const RsGxsId& signing_id, GRouterMsgPropagationId&propagation_id ) -{ -// std::cerr << "GRouter currently disabled." << std::endl; -// return false; - - if(data_size > MAX_GROUTER_DATA_SIZE) - { - std::cerr << "GRouter max size limit exceeded (size=" << data_size << ", max=" << MAX_GROUTER_DATA_SIZE << "). Please send a smaller object!" << std::endl; - return false ; - } - - // Make sure we have a unique id (at least locally). There's little chances that an id of the same value is out there anyway. - // - { - RsStackMutex mtx(grMtx) ; - do { propagation_id = RSRandom::random_u64(); } while(_pending_messages.find(propagation_id) != _pending_messages.end()) ; - } - - // create the signed data item - - RsGRouterGenericDataItem *data_item = new RsGRouterGenericDataItem ; - - data_item->data_bytes = (uint8_t*)rs_malloc(data_size) ; - - if(data_item->data_bytes == NULL) - return false ; - - memcpy(data_item->data_bytes,data,data_size) ; - - data_item->data_size = data_size ; - data_item->routing_id = propagation_id ; - data_item->duplication_factor = GROUTER_MAX_DUPLICATION_FACTOR ; - data_item->service_id = client_id ; - data_item->destination_key = destination ; - data_item->flags = RsGRouterItemFlags::NONE ; // this is unused for now. - - // First, encrypt. - - if(!encryptDataItem(data_item,destination)) - { - std::cerr << "Cannot encrypt data item. Some error occured!" << std::endl; - delete data_item; - return false; - } - - // Then, sign the encrypted data, so that the signature can be checked by non priviledged users. - - if(!signDataItem(data_item,signing_id)) - { - std::cerr << "Cannot sign data item. Some error occured!" << std::endl; - delete data_item; - return false; - } - - // Verify the signature. If that fails, there's a bug somewhere!! - uint32_t error_status; - - if(!verifySignedDataItem(data_item,RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CREATION,error_status)) - { - std::cerr << "Cannot verify data item that was just signed. Some error occured!" << std::endl; - delete data_item; - return false; - } - // push the item into pending messages. - // - GRouterRoutingInfo info ; - - rstime_t now = time(NULL) ; - - info.data_item = data_item ; - info.receipt_item = NULL ; - info.data_status = RS_GROUTER_DATA_STATUS_PENDING ; - info.tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ; - info.last_sent_TS = 0 ; - info.client_id = client_id ; - info.last_tunnel_request_TS = 0 ; - info.item_hash = computeDataItemHash(data_item) ; - info.sending_attempts = 0 ; - info.routing_flags = GRouterRoutingInfo::ROUTING_FLAGS_IS_ORIGIN | GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_FRIENDS ;// don't allow tunnels just yet - info.received_time_TS = now ; - info.tunnel_hash = makeTunnelHash(destination,client_id) ; - -#ifdef GROUTER_DEBUG - grouter_debug() << "p3GRouter::sendGRouterData(): pushing the following item in the msg pending list:" << std::endl; - grouter_debug() << " routing id = " << std::hex << propagation_id << std::dec << std::endl; - grouter_debug() << " data_item.size = " << info.data_item->data_size << std::endl; - grouter_debug() << " data_item.byte = " << RsDirUtil::sha1sum(info.data_item->data_bytes,info.data_item->data_size) << std::endl; - grouter_debug() << " destination = " << data_item->destination_key << std::endl; - grouter_debug() << " signed by key = " << data_item->signature.keyId << std::endl; - grouter_debug() << " data status = " << info.data_status << std::endl; - grouter_debug() << " tunnel status = " << info.tunnel_status << std::endl; - grouter_debug() << " sending attempt= " << info.sending_attempts << std::endl; - grouter_debug() << " duplicate fact = " << info.data_item->duplication_factor << std::endl; - grouter_debug() << " recv time = " << info.received_time_TS << std::endl; - grouter_debug() << " client id = " << std::hex << data_item->service_id << std::dec << std::endl; - grouter_debug() << " tunnel hash = " << info.tunnel_hash << std::endl; - grouter_debug() << " item hash = " << info.item_hash << std::endl; - grouter_debug() << " routing flags = " << info.routing_flags << std::endl; -#endif - - { - RS_STACK_MUTEX(grMtx) ; - _pending_messages[propagation_id] = info ; - } - IndicateConfigChanged() ; - -return true ; -} - -Sha1CheckSum p3GRouter::makeTunnelHash(const RsGxsId& destination,const GRouterServiceId& client) -{ - static_assert( RsGxsId::SIZE_IN_BYTES == 16, - "This function breaks if RsGxsId size changes" ); - static_assert( Sha1CheckSum::SIZE_IN_BYTES == 20, - "This function breaks if Sha1CheckSum size changes" ); - static_assert( sizeof(client) == 4, - "This function breaks if client service id size changes" ); - - uint8_t bytes[20] ; - memcpy(bytes,destination.toByteArray(),16) ; - bytes[16] = 0 ; - bytes[17] = 0 ; - bytes[18] = (client >> 8) & 0xff ; - bytes[19] = client & 0xff ; - - return RsDirUtil::sha1sum(bytes,20) ; -} -bool p3GRouter::loadList(std::list& items) -{ - { - RS_STACK_MUTEX(grMtx) ; - -#ifdef GROUTER_DEBUG - grouter_debug() << "p3GRouter::loadList() : " << std::endl; -#endif - - _routing_matrix.loadList(items) ; - -#ifdef GROUTER_DEBUG - // remove all existing objects. - // - grouter_debug() << " removing all existing items (" << _pending_messages.size() << " items to delete)." << std::endl; -#endif - - if(!_pending_messages.empty()) - std::cerr << " WARNING: pending msg list is not empty. List will be cleared." << std::endl; - - // clear the existing list. - // - for(std::map::iterator it(_pending_messages.begin());it!=_pending_messages.end();++it) - delete it->second.data_item ; - - _pending_messages.clear() ; - - for(std::list::const_iterator it(items.begin());it!=items.end();++it) - { - RsGRouterRoutingInfoItem *itm1 = NULL ; - - if(NULL != (itm1 = dynamic_cast(*it))) - { - // clean data state - itm1->tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ; - - _pending_messages[itm1->data_item->routing_id] = *itm1 ; - - itm1->data_item = NULL ; // prevents deletion. - itm1->receipt_item = NULL ; // prevents deletion. - } - - delete *it ; - } - } -#ifdef GROUTER_DEBUG - debugDump(); -#endif - items.clear() ; - return true ; -} -bool p3GRouter::saveList(bool& cleanup,std::list& items) -{ - // We save - // - the routing clues - // - the pending items - - cleanup = true ; // the client should delete the items. - -#ifdef GROUTER_DEBUG - grouter_debug() << "p3GRouter::saveList()..." << std::endl; - grouter_debug() << " saving routing clues." << std::endl; -#endif - - RS_STACK_MUTEX(grMtx) ; - - _routing_matrix.saveList(items) ; - -#ifdef GROUTER_DEBUG - grouter_debug() << " saving pending items." << std::endl; -#endif - - for(std::map::const_iterator it(_pending_messages.begin());it!=_pending_messages.end();++it) - { - RsGRouterRoutingInfoItem *item = new RsGRouterRoutingInfoItem ; - -#warning: Cppcheck(cstyleCast): C-style pointer casting - // cppcheck-suppress cstyleCast - *(GRouterRoutingInfo*)item = it->second ; // copy all members - - item->data_item = it->second.data_item->duplicate() ; // deep copy, because we call delete on the object, and the item might be removed before we handle it in the client. - if(it->second.receipt_item != NULL) - item->receipt_item = it->second.receipt_item->duplicate() ; - - items.push_back(item) ; - } - - return true ; -} - -bool p3GRouter::getRoutingMatrixInfo(RsGRouter::GRouterRoutingMatrixInfo& info) -{ - RS_STACK_MUTEX(grMtx) ; - - info.per_friend_probabilities.clear() ; - info.friend_ids.clear() ; - info.published_keys.clear() ; - - std::list ids ; - //mServiceControl->getPeersConnected(getServiceInfo().mServiceType,ids) ; - rsPeers->getFriendList(ids) ; - - info.published_keys = _owned_key_ids ; - - for(std::list::const_iterator it(ids.begin());it!=ids.end();++it) - info.friend_ids.push_back(*it) ; - - std::vector known_keys ; - std::vector probas ; - float maximum= 0.0f; - _routing_matrix.getListOfKnownKeys(known_keys) ; - - for(uint32_t i=0;i& infos) -{ - RS_STACK_MUTEX(grMtx) ; - - infos.clear() ; - - for(std::map::const_iterator it(_pending_messages.begin());it!=_pending_messages.end();++it) - { - GRouterRoutingCacheInfo cinfo ; - - cinfo.mid = it->first ; - cinfo.local_origin = it->second.incoming_routes.ids ; - cinfo.destination = it->second.data_item->destination_key ; - cinfo.duplication_factor = it->second.data_item->duplication_factor ; - cinfo.routing_time = it->second.received_time_TS ; - cinfo.last_tunnel_attempt_time = it->second.last_tunnel_request_TS ; - cinfo.last_sent_time = it->second.last_sent_TS ; - cinfo.receipt_available = (it->second.receipt_item != NULL); - cinfo.data_status = it->second.data_status ; - cinfo.tunnel_status = it->second.tunnel_status ; - cinfo.data_size = it->second.data_item->data_size ; - cinfo.item_hash = it->second.item_hash; - - infos.push_back(cinfo) ; - } - return true ; -} - -// Dump everything -// -void p3GRouter::debugDump() -{ - RS_STACK_MUTEX(grMtx) ; - - rstime_t now = time(NULL) ; - - grouter_debug() << "Full dump of Global Router state: " << std::endl; - grouter_debug() << " Owned keys : " << std::endl; - - for(std::map::const_iterator it(_owned_key_ids.begin());it!=_owned_key_ids.end();++it) - { - grouter_debug() << " Hash : " << it->first << std::endl; - grouter_debug() << " Key : " << it->second.authentication_key << std::endl; - grouter_debug() << " Service id : " << std::hex << it->second.service_id << std::dec << std::endl; - grouter_debug() << " Description : " << it->second.description_string << std::endl; - } - - grouter_debug() << " Registered services: " << std::endl; - - for(std::map::const_iterator it(_registered_services.begin() );it!=_registered_services.end();++it) - grouter_debug() << " " << std::hex << it->first << " " << std::dec << (void*)it->second << std::endl; - - grouter_debug() << " Data items: " << std::endl; - - static const std::string statusString[6] = { "Unkn","Pend","Sent","Receipt OK","Ongoing","Done" }; - - for(std::map::iterator it(_pending_messages.begin());it!=_pending_messages.end();++it) - { - grouter_debug() << " Msg id: " << std::hex << it->first << std::dec ; - grouter_debug() << " data hash: " << it->second.item_hash ; - grouter_debug() << " client: " << std::hex << it->second.client_id << std::dec; - grouter_debug() << " Flags: " << std::hex << it->second.routing_flags << std::dec; - grouter_debug() << " Dest: " << it->second.data_item->destination_key ; - grouter_debug() << " Recd: " << now - it->second.received_time_TS << " secs ago."; - grouter_debug() << " Sent: " << now - it->second.last_sent_TS << " secs ago."; - grouter_debug() << " Trans. TS: " << now - it->second.data_transaction_TS << " secs ago." ; - grouter_debug() << " Data Status: " << statusString[it->second.data_status] ; - grouter_debug() << " Tunl Status: " << statusString[it->second.tunnel_status] ; - grouter_debug() << " Receipt ok: " << (it->second.receipt_item != NULL) ; - grouter_debug() << " Dup: " << it->second.data_item->duplication_factor << std::endl; - } - - grouter_debug() << " Tunnels: " << std::endl; - - for(std::map::const_iterator it(_tunnels.begin());it!=_tunnels.end();++it) - { - grouter_debug() << " hash: " << it->first << ", first received: " << now - it->second.last_tunnel_ok_TS << " (secs ago), last received: " << now - it->second.last_tunnel_ok_TS << std::endl; - - for(std::set::const_iterator it2 = it->second.virtual_peers.begin();it2!=it->second.virtual_peers.end();++it2) - grouter_debug() << " " << (*it2) << std::endl; - } - - grouter_debug() << " Incoming data pipes: " << std::endl; - - for(std::map::const_iterator it(_incoming_data_pipes.begin());it!=_incoming_data_pipes.end();++it) - if(it->second.incoming_data_buffer != NULL) - grouter_debug() << " " << it->first << ": offset=" << it->second.incoming_data_buffer->chunk_start << " size=" << it->second.incoming_data_buffer->chunk_size << " over " << it->second.incoming_data_buffer->total_size << std::endl; - else - grouter_debug() << " " << it->first << " empty." << std::endl; - - grouter_debug() << " Routing matrix: " << std::endl; - - // if(_debug_enabled) - // _routing_matrix.debugDump() ; -} - - - - diff --git a/libretroshare/src/grouter/p3grouter.h b/libretroshare/src/grouter/p3grouter.h deleted file mode 100644 index 236c8b7a5..000000000 --- a/libretroshare/src/grouter/p3grouter.h +++ /dev/null @@ -1,374 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: p3grouter.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "retroshare/rsgrouter.h" -#include "retroshare/rstypes.h" -#include "retroshare/rstypes.h" -#include "retroshare/rsidentity.h" - -#include "turtle/turtleclientservice.h" -#include "services/p3service.h" -#include "pqi/p3cfgmgr.h" -#include "util/rsdebug.h" -#include "groutertypes.h" -#include "groutermatrix.h" -#include "grouteritems.h" - -// To be put in pqi/p3cfgmgr.h -static const uint32_t CONFIG_TYPE_GROUTER = 0x0016 ; - -class p3LinkMgr ; -class p3turtle ; -class RsGixs ; -class RsGRouterItem ; -class RsGRouterGenericDataItem ; -class RsGRouterSignedReceiptItem ; -class RsGRouterAbstractMsgItem ; -class RsGRouterTransactionItem ; -class RsGRouterTransactionAcknItem ; - -// This class is responsible for accepting data chunks and merging them into a final object. When the object is -// complete, it is de-serialised and returned as a RsGRouterGenericDataItem*. - -class GRouterTunnelInfo -{ -public: - GRouterTunnelInfo() :first_tunnel_ok_TS(0), last_tunnel_ok_TS(0) {} - - // These two methods handle the memory management of buffers for each virtual peers. - - void addVirtualPeer(const TurtleVirtualPeerId& vpid) ; - void removeVirtualPeer(const TurtleVirtualPeerId& vpid) ; - - std::set virtual_peers ; - - rstime_t first_tunnel_ok_TS ; // timestamp when 1st tunnel was received. - rstime_t last_tunnel_ok_TS ; // timestamp when last tunnel was received. -}; -class GRouterDataInfo -{ - // ! This class does not have a copy constructor that duplicates the incoming data buffer. This is on purpose! -public: - GRouterDataInfo() : last_activity_TS(0) - { - incoming_data_buffer = NULL ; - } - - void clear() { if(incoming_data_buffer!=NULL) delete incoming_data_buffer ; incoming_data_buffer = NULL ;} - - // These two methods handle the memory management of buffers for each virtual peers. - - RsGRouterAbstractMsgItem *addDataChunk(RsGRouterTransactionChunkItem *chunk_item) ; - RsGRouterTransactionChunkItem *incoming_data_buffer ; - - rstime_t last_activity_TS ; -}; - -class p3GRouter: public RsGRouter, public RsTurtleClientService, public p3Service, public p3Config -{ -public: - p3GRouter(p3ServiceControl *sc,RsGixs *is) ; - - //===================================================// - // Router clients business // - //===================================================// - - // This method allows to associate client ids (that are saved to disk) to client objects deriving - // from GRouterClientService. The various services are responsible for regstering themselves to the - // global router, with consistent ids. The services are stored in a map, and arriving objects are - // passed on the correct service depending on the client id of the key they are reaching. - // - virtual bool registerClientService(const GRouterServiceId& id,GRouterClientService *service) ; - - // Use this method to register/unregister a key that the global router will - // forward in the network, so that is can be a possible destination for - // global messages. - // - // auth_id : The GXS key that will be used to sign the data Receipts. - // contact_key : The key that is used to open tunnels - // desc_str : Any fixed length string (< 20 characters) to descript the address in words. - // client_id : Id of the client service to send the traffic to. - // The client ID should match the ID that has been registered using the previous method. - // - // Unregistering a key might not have an instantaneous effect, so the client is responsible for - // discarding traffic that might later come for this key. - // - virtual bool registerKey(const RsGxsId& authentication_id, const GRouterServiceId& client_id,const std::string& description_string) ; - virtual bool unregisterKey(const RsGxsId &key_id, const GRouterServiceId &sid) ; - - //===================================================// - // Routing clue collection methods // - //===================================================// - - virtual void addRoutingClue( - const RsGxsId& id, const RsPeerId& peer_id) override; - - //===================================================// - // Client/server request services // - //===================================================// - - // Sends an item to the given destination. The router takes ownership of - // the memory. That means item_data will be erase on return. The returned id should be - // remembered by the client, so that he knows when the data has been received. - // The client id is supplied so that the client can be notified when the data has been received. - // Data is not modified by the global router. - // - virtual bool sendData(const RsGxsId& destination, const GRouterServiceId& client_id, const uint8_t *data, uint32_t data_size, const RsGxsId& signing_id, GRouterMsgPropagationId& id) ; - - // Cancels a given sending order. If called too late, the message might already have left. But this will remove the item from the - // re-try list. - virtual bool cancel(GRouterMsgPropagationId mid) ; - - //===================================================// - // Interface with RsGRouter // - //===================================================// - - // debug info from routing matrix - // - list of known key ids - // - list of clues/time_stamp for each key. - // - real time routing probabilities - // - virtual bool getRoutingMatrixInfo(GRouterRoutingMatrixInfo& info) ; - - // debug info from routing cache - // - Cache Items - // * which message ids - // * directions - // * timestamp - // * message type - // - Cache state (memory size, etc) - // - virtual bool getRoutingCacheInfo(std::vector& info) ; - - //===================================================// - // Derived from p3Service // - //===================================================// - - virtual RsServiceInfo getServiceInfo() - { - return RsServiceInfo(RS_SERVICE_TYPE_GROUTER, - SERVICE_INFO_APP_NAME, - SERVICE_INFO_APP_MAJOR_VERSION, - SERVICE_INFO_APP_MINOR_VERSION, - SERVICE_INFO_MIN_MAJOR_VERSION, - SERVICE_INFO_MIN_MINOR_VERSION) ; - } - - virtual void setDebugEnabled(bool b) { _debug_enabled = b ; } - - virtual void connectToTurtleRouter(p3turtle *pt) ; - -protected: - //===================================================// - // Routing method handling // - //===================================================// - - // Calls - // - packet handling methods - // - matrix updates - // - virtual int tick() ; - - static const std::string SERVICE_INFO_APP_NAME ; - static const uint16_t SERVICE_INFO_APP_MAJOR_VERSION = 1; - static const uint16_t SERVICE_INFO_APP_MINOR_VERSION = 0; - static const uint16_t SERVICE_INFO_MIN_MAJOR_VERSION = 1; - static const uint16_t SERVICE_INFO_MIN_MINOR_VERSION = 0; - - //===================================================// - // Interaction with turtle router // - //===================================================// - - uint16_t serviceId() const { return RS_SERVICE_TYPE_GROUTER; } - virtual bool handleTunnelRequest(const RsFileHash& /*hash*/,const RsPeerId& /*peer_id*/) ; - virtual void receiveTurtleData(const RsTurtleGenericTunnelItem */*item*/,const RsFileHash& /*hash*/,const RsPeerId& /*virtual_peer_id*/,RsTurtleGenericTunnelItem::Direction /*direction*/); - virtual void addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) ; - virtual void removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) ; - -private: - //===================================================// - // Low level item sorting // - //===================================================// - - void handleLowLevelServiceItems() ; - void handleLowLevelServiceItem(RsGRouterTransactionItem*) ; - void handleLowLevelTransactionChunkItem(RsGRouterTransactionChunkItem *chunk_item); - void handleLowLevelTransactionAckItem(RsGRouterTransactionAcknItem*) ; - - static Sha1CheckSum computeDataItemHash(const RsGRouterGenericDataItem *data_item); - - std::ostream& grouter_debug() const - { - static std::ostream null(0); - return _debug_enabled?(std::cerr):null; - } - - void routePendingObjects() ; - void handleTunnels() ; - void autoWash() ; - - //===================================================// - // High level item sorting // - //===================================================// - - void handleIncoming() ; - - void handleIncomingItem(const RsGRouterAbstractMsgItem *item); - void handleIncomingReceiptItem(const RsGRouterSignedReceiptItem *receipt_item) ; - void handleIncomingDataItem(const RsGRouterGenericDataItem *data_item) ; - - bool locked_getLocallyRegisteredClientFromServiceId(const GRouterServiceId& service_id,GRouterClientService *& client); - - // utility functions - // - static float computeMatrixContribution(float base,uint32_t time_shift,float probability) ; - static bool sliceDataItem(RsGRouterAbstractMsgItem *,std::list& chunks) ; - - uint32_t computeRandomDistanceIncrement(const RsPeerId& pid,const GRouterKeyId& destination_id) ; - - // signs an item with the given key. - bool signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& id) ; - bool verifySignedDataItem(const RsGRouterAbstractMsgItem *item, const RsIdentityUsage::UsageCode &info, uint32_t &error_status) ; - bool encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& destination_key) ; - bool decryptDataItem(RsGRouterGenericDataItem *item) ; - - static Sha1CheckSum makeTunnelHash(const RsGxsId& destination,const GRouterServiceId& client); - - //bool locked_getGxsIdAndClientId(const TurtleFileHash &sum,RsGxsId& gxs_id,GRouterServiceId& client_id); - bool locked_sendTransactionData(const RsPeerId& pid,const RsGRouterTransactionItem& item); - - void locked_collectAvailableFriends(const GRouterKeyId &gxs_id, const std::set& incoming_routes,uint32_t duplication_factor, std::map &friend_peers_and_duplication_factors); - void locked_collectAvailableTunnels(const TurtleFileHash& hash, uint32_t total_duplication, std::map &tunnel_peers_and_duplication_factors); - void locked_sendToPeers(RsGRouterGenericDataItem *data_item, const std::map &peers_and_duplication_factors); - - //===================================================// - // p3Config methods // - //===================================================// - - // Load/save the routing info, the pending items in transit, and the config variables. - // - virtual bool loadList(std::list& items) ; - virtual bool saveList(bool& cleanup,std::list& items) ; - - virtual RsSerialiser *setupSerialiser() ; - - //===================================================// - // Debug methods // - //===================================================// - - // Prints the internal state of the router, for debug purpose. - // - void debugDump() ; - - //===================================================// - // Internal queues/variables // - //===================================================// - - // Stores the routing info - // - list of known key ids - // - list of clues/time_stamp for each key. - // - real time routing probabilities - // - GRouterMatrix _routing_matrix ; - - // Stores the keys which identify the router's node. For each key, a structure holds: - // - the client service - // - flags - // - usage time stamps - // - std::map _owned_key_ids ; - - // Registered services. These are known to the different peers with a common id, - // so it's important to keep consistency here. This map is volatile, and re-created at each startup of - // the software, when newly created services register themselves. - - std::map _registered_services ; - - // Stores the routing events. - // - ongoing requests, waiting for return ACK - // - pending items - // Both a stored in 2 different lists, to allow a more efficient handling. - // - std::map _pending_messages;// pending messages - - // Stores virtual peers that appear/disappear as the result of the turtle router client - // - std::map _tunnels ; - - // Stores incoming data from any peers (virtual and real) into chunks that get aggregated until finished. - // - std::map _incoming_data_pipes ; - - // Queue of incoming items. Might be receipts or data. Should always be empty (not a storage place) - std::list _incoming_items ; - - // Data handling methods - // - //void handleRecvDataItem(RsGRouterGenericDataItem *item); - //void handleRecvReceiptItem(RsGRouterReceiptItem *item); - - // Pointers to other RS objects - // - p3ServiceControl *mServiceControl ; - p3turtle *mTurtle ; - RsGixs *mGixs ; - //p3LinkMgr *mLinkMgr ; - - // Multi-thread protection mutex. - // - RsMutex grMtx ; - - // config update/save variables - bool _changed ; - bool _debug_enabled ; - - rstime_t _last_autowash_time ; - rstime_t _last_matrix_update_time ; - rstime_t _last_debug_output_time ; - rstime_t _last_config_changed ; - - uint64_t _random_salt ; - - /** Temporarly store items that could not have been verified yet due to - * missing author key, attempt to handle them once in a while. - * The items are discarded if after mMissingKeyQueueEntryTimeout the key - * hasn't been received yet, and are not saved on RetroShare stopping. */ - std::list< std::pair< - std::unique_ptr, rstime_t > > mMissingKeyQueue; - RsMutex mMissingKeyQueueMtx; /// protect mMissingKeyQueue - - /// @see mMissingKeyQueue - static constexpr rstime_t mMissingKeyQueueEntryTimeout = 600; - - /// @see mMissingKeyQueue - static constexpr rstime_t mMissingKeyQueueCheckEvery = 30; - - /// @see mMissingKeyQueue - rstime_t mMissingKeyQueueCheckLastCheck = 0; - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; diff --git a/libretroshare/src/gxs/UseCases.txt b/libretroshare/src/gxs/UseCases.txt deleted file mode 100644 index 4ca721633..000000000 --- a/libretroshare/src/gxs/UseCases.txt +++ /dev/null @@ -1,341 +0,0 @@ - -These are some example usages of the GxsService... -All of these must be provided by the basic system. - -chris: -Please not all request* functions have a receive pair if not noted below - - -1) Forums ------------------------------------- -1.1) Display of subscribed forums. Service must provide: - 1.1.1) list of subscribed Groups. - ---------------- - int requestSubscribedGrps(); - - Component: - RsGnp::requestGroups() - - - ---------------- - 1.1.2) list of messages for each Group. - ---------------- - int requestGrpMsgs(std::list&); - ---------------- - - 1.1.3) details of group by group Id. - ---------------- - int requestGrp(std::list& grpIds); - ---------------- - - 1.1.4) details of messages by message Id. - ---------------- - int requestMsgs(std::list& msgs); - ---------------- - - 1.1.5) newest version of each message - - ---------------- - 1.1.4 : not intitialising RsGxsMsgId::version default to returning - newest version of message - ---------------- - - 1.1.6) status of message (read / unread). - - ---------------- - returned with msg data - int flagMsgRead(const RsGxsMsgId& msgId, bool read) - - ---------------- - - 1.1.7) access to Identity associated with Group and Messages - - ---------------- - returned with message - ---------------- - - 1.1.8) updates when new groups arrive. - - ---------------- - virtual void notifyGroupChanged(std::list grpId) = 0 - ---------------- - - 1.1.9) updates when new messages arrive. - ---------------- - virtual void notifyMsgChanged(std::list msgId) = 0 - ---------------- - - 1.1.10) updates when groups / messages change. - - ---------------- - 1.1.8 and 1.1.9 - ---------------- - - 1.1.11) Search forums for Keywords. - - ---------------- - int requestLocalSearch(RsGxsSearch* term); - ---------------- - - 1.1.12) Access new (time restricted) messages. - ---------------- - ? explain - ---------------- - -1.2) Creation of new material. - 1.2.1) ability to create Groups. - - ---------------- - int pushGrp(std::set& grp, std::string& profileName); - int pushGrp(std::set& grp, RsIdentityExchangeService::IdentityType type, const std::set& peers, - const std::string& pseudonymName = ""); - - ---------------- - - 1.2.2) ability to create Messages. - - void pushMsg(std::set& msg); - -1.3) Deletion of forums and posts. - 1.3.1) discard forum (can't do this currently). - ---------------- - done automatically by GDService based on cutoff - ---------------- - - 1.3.2) delete post. - ---------------- - // post is removed from system and note made in db not to syn it - // this is cleaned from db post expires - // very likely to also propagate to friends - int requestDeleteMsg(const RsGxsMsgId& msgId); - int requestDeleteGrp(const RsGxsGrpId& grpId); - ---------------- - - 1.3.3) discard old posts. - ---------------- - done automatically by GDService based on cutoff - ---------------- - -1.4) Control of Forums - - 1.4.1) Storage Period of subscribed forums - - ---------------- - void setSubscribedGroupDiscardAge(uint32_t length); - ---------------- - - 1.4.2) Storage Period of unsubscribed forums. - - ---------------- - void setUnsubscribedGrpDiscardAge(uint32_t length); - ---------------- - - 1.4.3) transfer unsubscribed forums and posts (yes/no) - - ---------------- - don't think I want this, definitely default false - int GXService::allUnsubscribedTransfer(bool) - ---------------- - - 1.4.4) modify forums we own. - - ---------------- - int GXService::updateGroup(multimap) - ---------------- - - ---------------- - int GXService::updateMsg(multimap) - ---------------- - - 1.4.5) modify read status. - - ---------------- - int flagMsgRead(const RsGxsMsgId& msgId, bool read) ; - ---------------- - 1.4.6) Subscribe to forums - - ---------------- - int requestSubscribeToGrp(const RsGxsGrpId& grpId, bool subscribe); - ---------------- - -1.5) Finding other forums. - 1.5.1) Listing of other forums. - int GXService::requestGroupList(); - void receiveGroupList(token, list); //call back - 1.5.2) ability to temporarily get forum messages. - ? Explain - 1.5.3) search remote forums for keywords. - ---------------- - // service will have to provide own search module (can RsGDService can - // service remote search requests concurrent with GXS) - // module return message and groups (msgs can be marked compile time as not // searchable - int requestRemoteSearch(RsGxsSearch* term, uint32_t hops); - - ---------------- - 1.5.4) optional download of friends forums. - ---------------- - int requestPeersGrps(const std::string& sslId); - ---------------- - - -2) Channels ------------------------------------- -2.1) Mostly like Forums, additional functionality. - 2.1.1) Download files associated with Post. - - ---------------- - ? Explain, This should not be part of interface, this is feature specific - ---------------- - -2.2) Comments - 2.2.1) Write a comment. - ---------------- - see 1.2.2. RsGxsMsg with required indirection data members - to associate with message the comment is being made on - ---------------- - - 2.2.2) Reject (downgrade) bad comment. - ---------------- - user needs to verify publisher sent downgrage message - bool RsGxis::bool verify(const KeyRef& keyref, unsigned char* data, uint32_t dataLen, std::string& signature); - - ---------------- - - 2.2.3) Control Comments: Allow / Disallow, Pseudo / Authed Comments. - ---------------- - bool RsGxis::bool sign(const KeyRef& keyref, unsigned char* data, uint32_t dataLen, std::string& signature); - - ---------------- - - -3) Wiki ------------------------------------- -3.1) Editing functionality - 3.1.1) Access to Latest Version. - - ---------------- - Pls see 1.1.7 - ---------------- - - 3.1.2) Access to Version History. (including who edited). - - ---------------- - // need to include std::map as top level RsGxsMsg - ---------------- - - 3.2) Controlling Editing Rights. - - ---------------- - Pls see 1.1.7 - ---------------- - - - 3.2.1) Rejecting an Edit. - - ---------------- - using 1.2.2 publisher can send messages with private key signature that he does not accept edit 'x' - bool GXIService verify(Identity, data, dataLen, signature) - ---------------- - - 3.2.2) Changing Edit Rights. -using 1.2.2, publisher sends new publish key under old private key signature, and user uses - -3.3) Searching for Wikis. - 3.3.1) Search for keyword. - ---------------- - see 1.5.3 - ---------------- - - 3.3.2) Search for hashtag. - ---------------- - ? Explain, anything different from keyword - see 1.5.3 - ---------------- - - - 3.3.3) Search for pattern? - ---------------- - Bit more detail on search type - RsGxsSearch{ int searchType; const int PATTERN_TYPE, TERM_TYPE; ....} - - ---------------- - - -4) Wire (Twitter) ------------------------------------- -4.1) Following Friends. - 4.1.1) Adding Person. - - ---------------- - See 1.4.6 - ---------------- - - -4.2) Search The Wire. - 4.2.1) Search for friends. - 4.2.2) Search for hash tags. - 4.2.3) Search for keywords. - 4.2.4) Search for Retweets. - 4.2.5) Search for replies. - ---------------- - for 4.2.* see 3.3.1 - ---------------- - -5) PhotoShare. ------------------------------------- -5.1) Controlling Access. - 5.1.1) Friends Only. - - ---------------- - GXService::setShareGroup(grpId, group=RsGroups::GROUP_FRIENDS) - ---------------- - - 5.1.2) Groups Only. - - ---------------- - 5.1.1 - ---------------- - - 5.1.3) Everyone. - ---------------- - 5.1.1 GXService::setShareGroup(grpId, group=RsGroups::GROUP_ALL) - ---------------- - - 5.1.4) Deleting Photographs. - - ---------------- - 1.3.2 - ---------------- - - 5.1.4) Deleting Album. - ---------------- - 1.3.2 - ---------------- - -6) Acadeeb ------------------------------------- -6.1) Review Article. - 6.1.1) Write Review/Rate. - ---------------- - see 1.2.2 for sending message - ---------------- - - 6.1.2) Recommend Article. - ---------------- - see 1.2.2 for sending message - ---------------- - 6.1.3) Get Rating of Article. - ---------------- - See 3.2.1 and 2.2.2 - ---------------- - - -6.2) Submit Review of Article - 6.2.1) stuff. - 6.2.2) stuff. - - -7) Tracker. ------------------------------------- -7.1) Tracker Stuff. - diff --git a/libretroshare/src/gxs/gxssecurity.cc b/libretroshare/src/gxs/gxssecurity.cc deleted file mode 100644 index 6798ee29c..000000000 --- a/libretroshare/src/gxs/gxssecurity.cc +++ /dev/null @@ -1,1191 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxssecurity.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2010 by Robert Fernie * - * 2011-2012 Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#include "gxssecurity.h" -#include "pqi/authgpg.h" -#include "util/rsdir.h" -#include "util/rsmemory.h" -//#include "retroshare/rspeers.h" - -/**** - * #define GXS_SECURITY_DEBUG 1 - ***/ - -static const uint32_t MULTI_ENCRYPTION_FORMAT_v001_HEADER = 0xFACE; -static const uint32_t MULTI_ENCRYPTION_FORMAT_v001_HEADER_SIZE = 2 ; -static const uint32_t MULTI_ENCRYPTION_FORMAT_v001_NUMBER_OF_KEYS_SIZE = 2 ; -static const uint32_t MULTI_ENCRYPTION_FORMAT_v001_ENCRYPTED_KEY_SIZE = 256 ; - -static RsGxsId getRsaKeyFingerprint_old_insecure_method(RSA *pubkey) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - int lenn = BN_num_bytes(pubkey -> n); - - RsTemporaryMemory tmp(lenn) ; - BN_bn2bin(pubkey -> n, tmp); -#else - const BIGNUM *nn=NULL,*ee=NULL ; - RSA_get0_key(pubkey,&nn,&ee,NULL) ; - - int lenn = BN_num_bytes(nn); - - RsTemporaryMemory tmp(lenn) ; - BN_bn2bin(nn, tmp); -#endif - - // Copy first CERTSIGNLEN bytes from the hash of the public modulus and exponent - // We should not be using strings here, but a real ID. To be done later. - - assert(lenn >= CERTSIGNLEN) ; - - return RsGxsId((unsigned char*)tmp) ; -} -static RsGxsId getRsaKeyFingerprint(RSA *pubkey) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - int lenn = BN_num_bytes(pubkey -> n); - int lene = BN_num_bytes(pubkey -> e); - - RsTemporaryMemory tmp(lenn+lene) ; - - BN_bn2bin(pubkey -> n, tmp); - BN_bn2bin(pubkey -> e, &tmp[lenn]); -#else - const BIGNUM *nn=NULL,*ee=NULL ; - RSA_get0_key(pubkey,&nn,&ee,NULL) ; - - int lenn = BN_num_bytes(nn); - int lene = BN_num_bytes(ee); - - RsTemporaryMemory tmp(lenn+lene) ; - - BN_bn2bin(nn, tmp); - BN_bn2bin(ee, &tmp[lenn]); -#endif - - Sha1CheckSum s = RsDirUtil::sha1sum(tmp,lenn+lene) ; - - // Copy first CERTSIGNLEN bytes from the hash of the public modulus and exponent - // We should not be using strings here, but a real ID. To be done later. - - assert(Sha1CheckSum::SIZE_IN_BYTES >= CERTSIGNLEN) ; - - return RsGxsId(s.toStdString().substr(0,2*CERTSIGNLEN)); -} - -static RSA *extractPrivateKey(const RsTlvPrivateRSAKey& key) -{ - assert(key.keyFlags & RSTLV_KEY_TYPE_FULL) ; - - const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; - long keylen = key.keyData.bin_len; - - /* extract admin key */ - RSA *rsakey = d2i_RSAPrivateKey(NULL, &(keyptr), keylen); - - return rsakey; -} - -static RSA *extractPublicKey(const RsTlvPublicRSAKey& key) -{ - assert(!(key.keyFlags & RSTLV_KEY_TYPE_FULL)) ; - - const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; - long keylen = key.keyData.bin_len; - - /* extract admin key */ - RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen); - - return rsakey; -} -static void setRSAPublicKeyData(RsTlvPublicRSAKey& key, RSA *rsa_pub) -{ - assert(!(key.keyFlags & RSTLV_KEY_TYPE_FULL)) ; - unsigned char *data = NULL ; // this works for OpenSSL > 0.9.7 - int reqspace = i2d_RSAPublicKey(rsa_pub, &data); - - key.keyData.setBinData(data, reqspace); - key.keyId = getRsaKeyFingerprint(rsa_pub); - - free(data) ; -} - -static void setRSAPrivateKeyData(RsTlvPrivateRSAKey& key, RSA *rsa_priv) -{ - assert(key.keyFlags & RSTLV_KEY_TYPE_FULL) ; - - unsigned char *data = NULL ; // this works for OpenSSL > 0.9.7 - int reqspace = i2d_RSAPrivateKey(rsa_priv, &data); - - key.keyData.setBinData(data, reqspace); - key.keyId = getRsaKeyFingerprint(rsa_priv); - - free(data) ; -} -bool GxsSecurity::checkFingerprint(const RsTlvPublicRSAKey& key) -{ - RSA *rsa_pub = ::extractPublicKey(key) ; - bool res = (key.keyId == getRsaKeyFingerprint(rsa_pub)) ; - RSA_free(rsa_pub) ; - return res ; -} - -bool GxsSecurity::checkPrivateKey(const RsTlvPrivateRSAKey& key) -{ -#ifdef GXS_SECURITY_DEBUG - std::cerr << "Checking private key " << key.keyId << " ..." << std::endl; -#endif - - if( (key.keyFlags & RSTLV_KEY_TYPE_MASK) != RSTLV_KEY_TYPE_FULL) - { - std::cerr << "(WW) GxsSecurity::checkPrivateKey(): private key has wrong flags " << std::hex << (key.keyFlags & RSTLV_KEY_TYPE_MASK) << std::dec << ". This is unexpected." << std::endl; - return false ; - } - RSA *rsa_prv = ::extractPrivateKey(key) ; - - if(rsa_prv == NULL) - { - std::cerr << "(WW) GxsSecurity::checkPrivateKey(): no private key can be extracted from key ID " << key.keyId << ". Key is corrupted?" << std::endl; - return false ; - } - RSA *rsa_pub = RSAPublicKey_dup(rsa_prv); - RSA_free(rsa_prv) ; - - if(rsa_pub == NULL) - { - std::cerr << "(WW) GxsSecurity::checkPrivateKey(): no public key can be extracted from key ID " << key.keyId << ". Key is corrupted?" << std::endl; - return false ; - } - RsGxsId recomputed_key_id = getRsaKeyFingerprint(rsa_pub) ; - - if(recomputed_key_id != key.keyId) - { - if(key.keyId == getRsaKeyFingerprint_old_insecure_method(rsa_pub)) - { -#ifdef GXS_SECURITY_DEBUG - std::cerr << "(WW) fingerprint of key " << key.keyId << " was derived using old---insecure---format. It can be faked easily. You should get rid of this key!" << std::endl; -#endif - RSA_free(rsa_pub) ; - - // The policy is to *accept* these private keys, but the public key that corresponds will be rejected anyway, as it can easily be faked. - return true ; - } - else - { - std::cerr << "(WW) GxsSecurity::checkPrivateKey(): key " << key.keyId << " has wrong fingerprint " << recomputed_key_id << std::endl; - - RSA_free(rsa_pub) ; - return false ; - } - } - - RSA_free(rsa_pub) ; - return true ; -} - -bool GxsSecurity::checkPublicKey(const RsTlvPublicRSAKey &key) -{ -#ifdef GXS_SECURITY_DEBUG - std::cerr << "Checking public key " << key.keyId << " ..." << std::endl; -#endif - - if( (key.keyFlags & RSTLV_KEY_TYPE_MASK) != RSTLV_KEY_TYPE_PUBLIC_ONLY) - { - std::cerr << "(WW) GxsSecurity::checkPublicKey(): public key has wrong flags " << std::hex << (key.keyFlags & RSTLV_KEY_TYPE_MASK) << std::dec << ". This is unexpected." << std::endl; - return false ; - } - - // try to extract private key - const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; - long keylen = key.keyData.bin_len; - RSA *rsa_prv = d2i_RSAPrivateKey(NULL, &(keyptr), keylen); - - if(rsa_prv != NULL) - { - std::cerr << "(SS) GxsSecurity::checkPublicKey(): public key with ID " << key.keyId << " actually is a Private key!!!" << std::endl; - RSA_free(rsa_prv) ; - return false ; - } - - RSA *rsa_pub = ::extractPublicKey(key) ; - - if(rsa_pub == NULL) - { - std::cerr << "(WW) GxsSecurity::checkPublicKey(): no public key can be extracted from key ID " << key.keyId << ". Key is corrupted?" << std::endl; - return false ; - } - RsGxsId recomputed_key_id = getRsaKeyFingerprint(rsa_pub) ; - - if(recomputed_key_id != key.keyId) - { - if(key.keyId == getRsaKeyFingerprint_old_insecure_method(rsa_pub)) - { -#ifdef GXS_SECURITY_DEBUG - std::cerr << "(WW) fingerprint was derived using old---insecure---format. It can be faked easily." << std::endl; -#endif - RSA_free(rsa_pub) ; - - // The policy is to accept these public keys, but warn the owner, since they might be fake keys. They will be soon rejected here, by replacing - // the return value by false. - return true ; - } - else - std::cerr << "(WW) GxsSecurity::checkPublicKey(): key " << key.keyId << " has wrong fingerprint " << recomputed_key_id << "! Key will be discarded." << std::endl; - - RSA_free(rsa_pub) ; - return false ; - } - - RSA_free(rsa_pub) ; - return true ; -} - -bool GxsSecurity::generateKeyPair(RsTlvPublicRSAKey& public_key,RsTlvPrivateRSAKey& private_key) -{ - // admin keys - BIGNUM *ebn = BN_new(); - BN_set_word(ebn, 65537); - RSA *rsa = RSA_new(); - RSA_generate_key_ex(rsa, 2048, ebn, NULL); - RSA *rsa_pub = RSAPublicKey_dup(rsa); - - BN_clear_free(ebn) ; - - public_key.keyFlags = RSTLV_KEY_TYPE_PUBLIC_ONLY ; - private_key.keyFlags = RSTLV_KEY_TYPE_FULL ; - - setRSAPublicKeyData(public_key, rsa_pub); - setRSAPrivateKeyData(private_key, rsa); - - public_key.startTS = time(NULL); - public_key.endTS = public_key.startTS + 60 * 60 * 24 * 365 * 5; /* approx 5 years */ - - private_key.startTS = public_key.startTS; - private_key.endTS = 0; /* no end */ - - // clean up - RSA_free(rsa); - RSA_free(rsa_pub); - - if(!(private_key.checkKey() && public_key.checkKey())) - { - std::cerr << "(EE) ERROR while generating keys. Something inconsistent in flags. This is probably a bad sign!" << std::endl; - return false ; - } - - return true ; -} - -bool GxsSecurity::extractPublicKey(const RsTlvPrivateRSAKey &private_key, RsTlvPublicRSAKey &public_key) -{ - public_key.TlvClear() ; - - if(!(private_key.keyFlags & RSTLV_KEY_TYPE_FULL)) - return false ; - - RSA *rsaPrivKey = extractPrivateKey(private_key); - - if(!rsaPrivKey) - return false ; - - RSA *rsaPubKey = RSAPublicKey_dup(rsaPrivKey); - RSA_free(rsaPrivKey); - - if(!rsaPubKey) - return false ; - - setRSAPublicKeyData(public_key, rsaPubKey); - RSA_free(rsaPubKey); - - public_key.keyFlags = private_key.keyFlags & (RSTLV_KEY_DISTRIB_MASK) ; // keep the distrib flags - public_key.keyFlags |= RSTLV_KEY_TYPE_PUBLIC_ONLY; - public_key.startTS = private_key.startTS ; - public_key.endTS = public_key.startTS + 60 * 60 * 24 * 365 * 5; /* approx 5 years */ - - // This code fixes a problem of old RSA keys where the fingerprint wasn't computed using SHA1(n,e) but - // using the first bytes of n (ouuuuch!). Still, these keys are valid and should produce a correct - // fingerprint. So we replace the public key fingerprint (that is normally recomputed) with the FP of - // the private key. - - if(public_key.keyId != private_key.keyId) - { - std::cerr << std::endl; - std::cerr << "WARNING: GXS ID key pair " << private_key.keyId << " has inconsistent fingerprint. This is an old key " << std::endl; - std::cerr << " that is unsecure (can be faked easily). You should delete it!" << std::endl; - std::cerr << std::endl; - - public_key.keyId = private_key.keyId ; - } - - return true ; -} - -bool GxsSecurity::getSignature(const char *data, uint32_t data_len, const RsTlvPrivateRSAKey &privKey, RsTlvKeySignature& sign) -{ - RSA* rsa_priv = extractPrivateKey(privKey); - - if(!rsa_priv) - { - std::cerr << "GxsSecurity::getSignature(): Cannot create signature. Keydata is incomplete." << std::endl; - return false ; - } - EVP_PKEY *key_priv = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(key_priv, rsa_priv); - - /* calc and check signature */ - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - bool ok = EVP_SignInit(mdctx, EVP_sha1()) == 1; - ok &= EVP_SignUpdate(mdctx, data, data_len) == 1; - - unsigned int siglen = EVP_PKEY_size(key_priv); - unsigned char sigbuf[siglen] ; - memset(sigbuf,0,siglen) ; - ok &= EVP_SignFinal(mdctx, sigbuf, &siglen, key_priv) == 1; - - // clean up - EVP_MD_CTX_destroy(mdctx); - EVP_PKEY_free(key_priv); - - sign.signData.setBinData(sigbuf, siglen); - sign.keyId = RsGxsId(privKey.keyId); - - return ok; -} - -bool GxsSecurity::validateSignature(const char *data, uint32_t data_len, const RsTlvPublicRSAKey &key, const RsTlvKeySignature& signature) -{ - assert(!(key.keyFlags & RSTLV_KEY_TYPE_FULL)) ; - - RSA *rsakey = ::extractPublicKey(key) ; - - if(!rsakey) - { - std::cerr << "GxsSecurity::validateSignature(): Cannot validate signature. Keydata is incomplete." << std::endl; - key.print(std::cerr,0) ; - return false ; - } - EVP_PKEY *signKey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(signKey, rsakey); - - /* calc and check signature */ - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - EVP_VerifyInit(mdctx, EVP_sha1()); - EVP_VerifyUpdate(mdctx, data, data_len); - - int signOk = EVP_VerifyFinal(mdctx, (unsigned char*)signature.signData.bin_data, signature.signData.bin_len, signKey); - - /* clean up */ - EVP_PKEY_free(signKey); - EVP_MD_CTX_destroy(mdctx); - - return signOk; -} - -bool GxsSecurity::validateNxsMsg(const RsNxsMsg& msg, const RsTlvKeySignature& sign, const RsTlvPublicRSAKey& key) -{ - #ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsMsg()"; - std::cerr << std::endl; - std::cerr << "RsNxsMsg :"; - std::cerr << std::endl; - const_cast(&msg)->print(std::cerr, 10); - std::cerr << std::endl; - #endif - - RsGxsMsgMetaData& msgMeta = *(msg.metaData); - - // /********************* check signature *******************/ - - /* check signature timeperiod */ - if(msgMeta.mPublishTs < key.startTS) - { - RsWarn() << __PRETTY_FUNCTION__ << " GxsSecurity::validateNxsMsg() TS out of range for key " << msgMeta.mAuthorId - << " The signed message has an inconsistent msg publish time of " << msgMeta.mPublishTs - << " whereas the signing key was created later at TS " << key.startTS - << ". Validation rejected for security. If you see this, something irregular is going on." << std::endl; - return false; - } - - if(key.endTS != 0 && msgMeta.mPublishTs > key.endTS) - { - RsWarn() << __PRETTY_FUNCTION__ << " GxsSecurity::validateNxsMsg() TS out of range for key " << msgMeta.mAuthorId - << " usage is limited to TS=[" << key.startTS << "," << key.endTS << "] and msg publish time is " << msgMeta.mPublishTs - << " The validation still passes, but that key should be renewed." << std::endl; - - // no return here. We still proceed checking the signature. - } - - /* decode key */ - const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; - long keylen = key.keyData.bin_len; - unsigned int siglen = sign.signData.bin_len; - unsigned char *sigbuf = (unsigned char *) sign.signData.bin_data; - - #ifdef DISTRIB_DEBUG - std::cerr << "GxsSecurity::validateNxsMsg() Decode Key"; - std::cerr << " keylen: " << keylen << " siglen: " << siglen; - std::cerr << std::endl; - #endif - - /* extract admin key */ - - RSA *rsakey = (key.keyFlags & RSTLV_KEY_TYPE_FULL)? (d2i_RSAPrivateKey(NULL, &(keyptr), keylen)) : (d2i_RSAPublicKey(NULL, &(keyptr), keylen)); - - if (!rsakey) - { - #ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsMsg()"; - std::cerr << " Invalid RSA Key"; - std::cerr << std::endl; - - key.print(std::cerr, 10); - #endif - } - - - RsTlvKeySignatureSet signSet = msgMeta.signSet; - msgMeta.signSet.TlvClear(); - - RsGxsMessageId msgId = msgMeta.mMsgId, origMsgId = msgMeta.mOrigMsgId; - - if(msgMeta.mOrigMsgId == msgMeta.mMsgId) // message is not versionned, then the signature was made with mOrigMsgId==NULL - msgMeta.mOrigMsgId.clear(); - - msgMeta.mMsgId.clear(); - - int signOk = 0 ; - - { - EVP_PKEY *signKey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(signKey, rsakey); - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - uint32_t metaDataLen = msgMeta.serial_size(); - uint32_t allMsgDataLen = metaDataLen + msg.msg.bin_len; - - RsTemporaryMemory metaData(metaDataLen) ; - RsTemporaryMemory allMsgData(allMsgDataLen) ; - - if(!metaData || !allMsgData) - return false ; - - msgMeta.serialise(metaData, &metaDataLen); - - // copy msg data and meta in allmsgData buffer - memcpy(allMsgData, msg.msg.bin_data, msg.msg.bin_len); - memcpy(allMsgData+(msg.msg.bin_len), metaData, metaDataLen); - - /* calc and check signature */ - - EVP_VerifyInit(mdctx, EVP_sha1()); - EVP_VerifyUpdate(mdctx, allMsgData, allMsgDataLen); - - signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey); - - /* clean up */ - EVP_PKEY_free(signKey); - EVP_MD_CTX_destroy(mdctx); - } - - msgMeta.mOrigMsgId = origMsgId; - msgMeta.mMsgId = msgId; - msgMeta.signSet = signSet; - - if (signOk == 1) - { - #ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsMsg() Signature OK"; - std::cerr << std::endl; - #endif - return true; - } - - #ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsMsg() Signature invalid"; - std::cerr << std::endl; - #endif - - return false; -} - -bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvPublicRSAKey& key) -{ -#ifdef DISTRIB_DEBUG - std::cerr << "GxsSecurity::encrypt() " << std::endl; -#endif - // Encrypts (in,inlen) into (out,outlen) using the given RSA public key. - // The format of the encrypted data is: - // - // [--- Encrypted session key length ---|--- Encrypted session key ---|--- IV ---|---- Encrypted data ---] - // - - out = NULL ; - - RSA *tmpkey = ::extractPublicKey(key) ; - RSA *rsa_publish_pub = RSAPublicKey_dup(tmpkey) ; - RSA_free(tmpkey) ; - - EVP_PKEY *public_key = NULL; - - //RSA* rsa_publish = EVP_PKEY_get1_RSA(privateKey); - //rsa_publish_pub = RSAPublicKey_dup(rsa_publish); - - - if(rsa_publish_pub != NULL) - { - public_key = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(public_key, rsa_publish_pub); - } - else - { -#ifdef DISTRIB_DEBUG - std::cerr << "GxsSecurity(): Could not generate publish key " << grpId - << std::endl; -#endif - return false; - } - - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - int eklen, net_ekl; - unsigned char *ek; - unsigned char iv[EVP_MAX_IV_LENGTH]; - int out_currOffset = 0; - int out_offset = 0; - - int max_evp_key_size = EVP_PKEY_size(public_key); - ek = (unsigned char*)rs_malloc(max_evp_key_size); - - if(ek == NULL) - return false ; - - const EVP_CIPHER *cipher = EVP_aes_128_cbc(); - int cipher_block_size = EVP_CIPHER_block_size(cipher); - int size_net_ekl = sizeof(net_ekl); - - int max_outlen = inlen + cipher_block_size + EVP_MAX_IV_LENGTH + max_evp_key_size + size_net_ekl; - - // intialize context and send store encrypted cipher in ek - if(!EVP_SealInit(ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &public_key, 1)) return false; - - EVP_PKEY_free(public_key) ; - - // now assign memory to out accounting for data, and cipher block size, key length, and key length val - out = (uint8_t*)rs_malloc(inlen + cipher_block_size + size_net_ekl + eklen + EVP_MAX_IV_LENGTH) ; - - if (out == NULL) - return false; - - net_ekl = htonl(eklen); - memcpy((unsigned char*)out + out_offset, &net_ekl, size_net_ekl); - out_offset += size_net_ekl; - - memcpy((unsigned char*)out + out_offset, ek, eklen); - out_offset += eklen; - - memcpy((unsigned char*)out + out_offset, iv, EVP_MAX_IV_LENGTH); - out_offset += EVP_MAX_IV_LENGTH; - - // now encrypt actual data - if(!EVP_SealUpdate(ctx, (unsigned char*) out + out_offset, &out_currOffset, (unsigned char*) in, inlen)) - { - free(out) ; - out = NULL ; - return false; - } - - // move along to partial block space - out_offset += out_currOffset; - - // add padding - if(!EVP_SealFinal(ctx, (unsigned char*) out + out_offset, &out_currOffset)) - { - free(out) ; - out = NULL ; - return false; - } - - // move to end - out_offset += out_currOffset; - - // make sure offset has not gone passed valid memory bounds - if(out_offset > max_outlen) - { - free(out) ; - out = NULL ; - return false; - } - - // free encrypted key data - free(ek); - - EVP_CIPHER_CTX_free(ctx); - - outlen = out_offset; - return true; -} - -bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const std::vector &keys) -{ -#ifdef DISTRIB_DEBUG - std::cerr << "GxsSecurity::encrypt() " << std::endl; -#endif - // Encrypts (in,inlen) into (out,outlen) using the given RSA public key. - // The format of the encrypted data is: - // - // [--- ID ---|--- number of encrypted keys---| n * (--- Encrypted session keys ---) |--- IV ---|---- Encrypted data ---] - // 2 bytes 2 byte = n 256 bytes EVP_MAX_IV_LENGTH Rest of packet - // - - out = NULL ; - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - std::vector public_keys(keys.size(),NULL); - - try - { - if(keys.empty()) - throw std::runtime_error("EVP_SealInit will not be called with 0 keys. GxsSecurity::encrypt() was called with an empty set of destination keys!") ; - - for(uint32_t i=0;i ek(keys.size(),NULL) ; - std::vector eklen(keys.size(),0) ; - - for(uint32_t i=0;i> 8) & 0xff ; - - // number of keys - - out[out_offset++] = keys.size() & 0xff ; - out[out_offset++] = (keys.size() >> 8) & 0xff ; - - // encrypted keys, each preceeded with its length - - for(uint32_t i=0;i max_outlen) - throw std::runtime_error("Memory used by encryption exceeds allocated memory block") ; - - // free encrypted key data - - for(uint32_t i=0;i 512 || eklen+in_offset > (int)inlen) - { - std::cerr << "Error while deserialising encryption key length: eklen = " << std::dec << eklen << ". Giving up decryption." << std::endl; - free(ek); - return false; - } - - memcpy(ek, (unsigned char*)in + in_offset, eklen); - in_offset += eklen; - - memcpy(iv, (unsigned char*)in + in_offset, EVP_MAX_IV_LENGTH); - in_offset += EVP_MAX_IV_LENGTH; - - const EVP_CIPHER* cipher = EVP_aes_128_cbc(); - - if(!EVP_OpenInit(ctx, cipher, ek, eklen, iv, privateKey)) - { - std::cerr << "(EE) Cannot decrypt data. Most likely reason: private GXS key is missing." << std::endl; - return false; - } - EVP_PKEY_free(privateKey) ; - - if(inlen < (uint32_t)in_offset) - { - std::cerr << "Severe error in " << __PRETTY_FUNCTION__ << ": cannot encrypt. " << std::endl; - return false ; - } - out = (uint8_t*)rs_malloc(inlen - in_offset); - - if(out == NULL) - return false; - - if(!EVP_OpenUpdate(ctx, (unsigned char*) out, &out_currOffset, (unsigned char*)in + in_offset, inlen - in_offset)) - { - free(out) ; - out = NULL ; - return false; - } - - outlen = out_currOffset; - - if(!EVP_OpenFinal(ctx, (unsigned char*)out + out_currOffset, &out_currOffset)) - { - free(out) ; - out = NULL ; - return false; - } - - outlen += out_currOffset; - free(ek); - - EVP_CIPHER_CTX_free(ctx); - return true; -} - -bool GxsSecurity::decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in, uint32_t inlen, const std::vector &keys) -{ - // Decrypts (in,inlen) into (out,outlen) using one of the given RSA public keys, trying them all in a row. - // The format of the encrypted data is: - // - // [--- ID ---|--- number of encrypted keys---| n * (--- Encrypted session keys ---) |--- IV ---|---- Encrypted data ---] - // 2 bytes 2 byte = n 256 bytes EVP_MAX_IV_LENGTH Rest of packet - // - // This method can be used to decrypt multi-encrypted data, if passing he correct encrypted key block (corresponding to the given key) - -#ifdef DISTRIB_DEBUG - std::cerr << "GxsSecurity::decrypt() " << std::endl; -#endif - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - - try - { - out = NULL ; - - // check that the input block has a valid format. - - uint32_t offset = 0 ; - uint16_t format_id = in[offset] + (in[offset+1] << 8) ; - - if(format_id != MULTI_ENCRYPTION_FORMAT_v001_HEADER) - { - std::cerr << "Unrecognised format in encrypted block. Header id = " << std::hex << format_id << std::dec << std::endl; - throw std::runtime_error("Unrecognised format in encrypted block.") ; - } - offset += MULTI_ENCRYPTION_FORMAT_v001_HEADER_SIZE; - - // read number of encrypted keys - - uint32_t number_of_keys = in[offset] + (in[offset+1] << 8) ; - offset += MULTI_ENCRYPTION_FORMAT_v001_NUMBER_OF_KEYS_SIZE; - - // reach the actual data offset - - uint32_t encrypted_keys_offset = offset ; - uint32_t encrypted_block_size = 0 ; - - uint32_t IV_offset = offset + number_of_keys * MULTI_ENCRYPTION_FORMAT_v001_ENCRYPTED_KEY_SIZE ; - uint32_t encrypted_block_offset = IV_offset + EVP_MAX_IV_LENGTH ; - - // read IV offset - - if(encrypted_block_offset >= inlen) - throw std::runtime_error("Offset error") ; - - encrypted_block_size = inlen - encrypted_block_offset ; -#ifdef GXS_SECURITY_DEBUG - std::cerr << " number of keys in envelop: " << number_of_keys << std::endl; - std::cerr << " IV offset : " << IV_offset << std::endl; - std::cerr << " encrypted block offset : " << encrypted_block_offset << std::endl; - std::cerr << " encrypted block size : " << encrypted_block_size << std::endl; -#endif - - // decrypt - - bool succeed = false; - - for(uint32_t j=0;j(&grp)->print(std::cerr, 10); - std::cerr << std::endl; -#endif - - RsGxsGrpMetaData& grpMeta = *(grp.metaData); - - /********************* check signature *******************/ - - /* check signature timeperiod */ - if (grpMeta.mPublishTs < key.startTS) - { - RsWarn() << __PRETTY_FUNCTION__ << " GxsSecurity::validateNxsGrp() TS out of range for admin/publish key of group " << grpMeta.mGroupId - << " The signed group has an inconsistent creation/modification time of " << grpMeta.mPublishTs - << " whereas the key was created later at TS " << key.startTS - << ". Validation rejected for security. If you see this, something irregular is going on." << std::endl; - return false; - } - if (key.endTS != 0 && grpMeta.mPublishTs > key.endTS) - { - RsWarn() << __PRETTY_FUNCTION__ << " GxsSecurity::validateNxsMsg() TS out of range for admin/publish key for group " << grpMeta.mGroupId - << " usage is limited to TS=[" << key.startTS << "," << key.endTS << "] and msg publish time is " << grpMeta.mPublishTs - << " The validation still passes, but that key should be renewed." << std::endl; - - // no return. Still proceed checking signature. - } - - /* decode key */ - const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; - long keylen = key.keyData.bin_len; - unsigned int siglen = sign.signData.bin_len; - unsigned char *sigbuf = (unsigned char *) sign.signData.bin_data; - -#ifdef DISTRIB_DEBUG - std::cerr << "GxsSecurity::validateNxsMsg() Decode Key"; - std::cerr << " keylen: " << keylen << " siglen: " << siglen; - std::cerr << std::endl; -#endif - - /* extract admin key */ - RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen); - - if (!rsakey) - { -#ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsGrp()"; - std::cerr << " Invalid RSA Key"; - std::cerr << std::endl; - - key.print(std::cerr, 10); -#endif - } - - std::vector api_versions_to_check ; - api_versions_to_check.push_back(RS_GXS_GRP_META_DATA_VERSION_ID_0002) ; // put newest first, for debug info purpose - api_versions_to_check.push_back(RS_GXS_GRP_META_DATA_VERSION_ID_0001) ; - - RsTlvKeySignatureSet signSet = grpMeta.signSet; - grpMeta.signSet.TlvClear(); - - int signOk =0; - EVP_PKEY *signKey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(signKey, rsakey); - - - for(uint32_t i=0;i0) - std::cerr << "(WW) Checking group signature with old api version " << i+1 << " : tag " << std::hex << api_versions_to_check[i] << std::dec << " result: " << signOk << std::endl; -#endif - } - - /* clean up */ - EVP_PKEY_free(signKey); - - // restore data - - grpMeta.signSet = signSet; - - if (signOk == 1) - { -#ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsGrp() Signature OK"; - std::cerr << std::endl; -#endif - return true; - } - -#ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsGrp() Signature invalid"; - std::cerr << std::endl; -#endif - - return false; -} - -void GxsSecurity::createPublicKeysFromPrivateKeys(RsTlvSecurityKeySet& keyset) -{ - for( std::map::const_iterator it = keyset.private_keys.begin(); it != keyset.private_keys.end() ; ++it) - if(keyset.public_keys.find(it->second.keyId) == keyset.public_keys.end()) - { - RsTlvPublicRSAKey pub_key ; - - if(!extractPublicKey(it->second,pub_key)) - { - std::cerr << "(EE) ERROR when trying to generate public key from private key for ID " << it->second.keyId << ". This is probably a bug with security implications." << std::endl; - continue ; - } - - keyset.public_keys[it->second.keyId] = pub_key ; - - std::cerr << "(II) Generated missing public key for ID " << it->second.keyId << " from private key." << std::endl; - } -} diff --git a/libretroshare/src/gxs/gxssecurity.h b/libretroshare/src/gxs/gxssecurity.h deleted file mode 100644 index 7b607c916..000000000 --- a/libretroshare/src/gxs/gxssecurity.h +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxssecurity.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2010 by Robert Fernie * - * 2011-2012 Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef GXSSECURITY_H -#define GXSSECURITY_H - -#include "serialiser/rstlvkeys.h" - -#include "rsitems/rsnxsitems.h" - -#include -#include - - -/*! - * This contains functionality for performing basic security operations needed - * in RsGenExchange operations. - * Also has routine for creating security objects around msgs and groups - * TODO: Those functions doesn't do param checking! - */ -class GxsSecurity -{ - public: - /*! - * Extracts a public key from a private key. - */ - static bool extractPublicKey(const RsTlvPrivateRSAKey& private_key,RsTlvPublicRSAKey& public_key) ; - - /*! - * Generates a public/private RSA keypair. To be used for all GXS purposes. - * @param RsTlvSecurityKey public RSA key - * @param RsTlvSecurityKey private RSA key - * @return true if the generate was successful, false otherwise. - */ - static bool generateKeyPair(RsTlvPublicRSAKey &public_key, RsTlvPrivateRSAKey &private_key) ; - - /*! - * Encrypts data using envelope encryption (taken from open ssl's evp_sealinit ) - * only full publish key holders can encrypt data for given group - *@param out - *@param outlen - *@param in - *@param inlen - */ - static bool encrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvPublicRSAKey& key) ; - static bool encrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const std::vector& keys) ; - - /** - * Decrypts data using evelope decryption (taken from open ssl's evp_sealinit ) - * only full publish key holders can decrypt data for a group - * @param out where decrypted data is written to - * @param outlen - * @param in - * @param inlen - * @return false if encryption failed - */ - static bool decrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvPrivateRSAKey& key) ; - static bool decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in, uint32_t inlen, const std::vector& keys); - - /*! - * uses grp signature to check if group has been - * tampered with - * @param newGrp the Nxs group to be validated - * @param sign the signature to validdate against - * @param key the public key to use to check signature - * @return true if group valid false otherwise - */ - static bool validateNxsGrp(const RsNxsGrp& grp, const RsTlvKeySignature& sign, const RsTlvPublicRSAKey& key); - - /*! - * Validate a msg's signature using the given public key - * @param msg the Nxs message to be validated - * @param sign the signature to validdate against - * @param key the public key to use to check signature - * @return false if verfication of signature is not passed - */ - static bool validateNxsMsg(const RsNxsMsg& msg, const RsTlvKeySignature& sign, const RsTlvPublicRSAKey &key); - - - /*! - * @param data data to be signed - * @param data_len length of data to be signed - * @param privKey private key to used to make signature - * @param sign the signature is stored here - * @return false if signature creation failed, true is signature created - */ - static bool getSignature(const char *data, uint32_t data_len, const RsTlvPrivateRSAKey& privKey, RsTlvKeySignature& sign); - - /*! - * @param data data that has been signed - * @param data_len length of signed data - * @param privKey public key to used to check signature - * @param sign Signature for the data - * @return true if signature checks - */ - static bool validateSignature(const char *data, uint32_t data_len, const RsTlvPublicRSAKey& pubKey, const RsTlvKeySignature& sign); - - /*! - * Checks that the public key has correct fingerprint and correct flags. - * @brief checkPublicKey - * @param key - * @return false if the key is invalid. - */ - - static bool checkPublicKey(const RsTlvPublicRSAKey &key); - static bool checkPrivateKey(const RsTlvPrivateRSAKey &key); - static bool checkFingerprint(const RsTlvPublicRSAKey& key); // helper function to only check the fingerprint - - /*! - * Adds possibly missing public keys when private keys are present. - * - * \brief createPublicKeysForPrivateKeys - * \param set set of keys to consider - * \return - */ - static void createPublicKeysFromPrivateKeys(RsTlvSecurityKeySet& set) ; -}; - -#endif // GXSSECURITY_H diff --git a/libretroshare/src/gxs/gxstokenqueue.cc b/libretroshare/src/gxs/gxstokenqueue.cc deleted file mode 100644 index 227ea33fc..000000000 --- a/libretroshare/src/gxs/gxstokenqueue.cc +++ /dev/null @@ -1,95 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxstokenqueue.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "gxs/gxstokenqueue.h" - -/******* - * #define GXS_DEBUG 1 - ******/ - -bool GxsTokenQueue::queueRequest(uint32_t token, uint32_t req_type) -{ - RS_STACK_MUTEX(mQueueMtx); - mQueue.push_back(GxsTokenQueueItem(token, req_type)); - return true; -} - - -void GxsTokenQueue::checkRequests() -{ - { - RS_STACK_MUTEX(mQueueMtx); - if (mQueue.empty()) return; - } - - // Must check all, and move to a different list - for reentrant / good mutex behaviour. - std::list toload; - std::list::iterator it; - bool stuffToLoad = false; - - { - RS_STACK_MUTEX(mQueueMtx); - for(it = mQueue.begin(); it != mQueue.end();) - { - uint32_t token = it->mToken; - it->mStatus = mGenExchange->getTokenService()->requestStatus(token); - - if ( it->mStatus == RsTokenService::COMPLETE - || it->mStatus == RsTokenService::CANCELLED ) - { - toload.push_back(*it); - it = mQueue.erase(it); - stuffToLoad = true; - -#ifdef GXS_DEBUG - std::cerr << "GxsTokenQueue::checkRequests() token: " << token - << " Complete" << std::endl; -#endif - ++it; - } - else if (it->mStatus == RsTokenService::FAILED) - { - // maybe we should do alternative callback? - std::cerr << __PRETTY_FUNCTION__ << " ERROR Request Failed! " - << " token: " << token << std::endl; - - it = mQueue.erase(it); - } - else - { -#ifdef GXS_DEBUG - std::cerr << "GxsTokenQueue::checkRequests() token: " << token - << " is unfinished, status: " << status << std::endl; -#endif - ++it; - } - } - } // RS_STACK_MUTEX(mQueueMtx) END - - if (stuffToLoad) - { - for(it = toload.begin(); it != toload.end(); ++it) - { - handleResponse(it->mToken, it->mReqType, it->mStatus); - } - } -} - diff --git a/libretroshare/src/gxs/gxstokenqueue.h b/libretroshare/src/gxs/gxstokenqueue.h deleted file mode 100644 index e4445c44a..000000000 --- a/libretroshare/src/gxs/gxstokenqueue.h +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxstokenqueue.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef R_GXS_TOKEN_QUEUE_H -#define R_GXS_TOKEN_QUEUE_H - -#include "gxs/rsgenexchange.h" -#include "retroshare/rsservicecontrol.h" -#include "util/rsthreads.h" - - -struct GxsTokenQueueItem -{ -public: - - GxsTokenQueueItem(const uint32_t token, const uint32_t req_type) : - mToken(token), mReqType(req_type), mStatus(RsTokenService::PENDING) {} - - GxsTokenQueueItem(): mToken(0), mReqType(0), mStatus(RsTokenService::PENDING) {} - - uint32_t mToken; - uint32_t mReqType; - RsTokenService::GxsRequestStatus mStatus; -}; - - -/** - * A little helper class, to manage callbacks from requests - */ -class GxsTokenQueue -{ -public: - explicit GxsTokenQueue(RsGenExchange *gxs) : - mGenExchange(gxs), mQueueMtx("GxsTokenQueueMtx") {} - - bool queueRequest(uint32_t token, uint32_t req_type); - void checkRequests(); /// must be called by - -protected: - - /// This must be overloaded to complete the functionality. - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) = 0; - -private: - RsGenExchange *mGenExchange; - RsMutex mQueueMtx; - std::list mQueue; -}; - - -#endif //R_GXS_TOKEN_QUEUE_H diff --git a/libretroshare/src/gxs/rsdataservice.cc b/libretroshare/src/gxs/rsdataservice.cc deleted file mode 100644 index b0415a9f6..000000000 --- a/libretroshare/src/gxs/rsdataservice.cc +++ /dev/null @@ -1,1780 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxsdataservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Evi-Parker Christopher * - * * - * 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 . * - * * - *******************************************************************************/ - -/***** - * #define RS_DATA_SERVICE_DEBUG 1 - * #define RS_DATA_SERVICE_DEBUG_TIME 1 - * #define RS_DATA_SERVICE_DEBUG_CACHE 1 - ****/ - -#include -#include -#include - -#ifdef RS_DATA_SERVICE_DEBUG_TIME -#include -#endif - -#include "rsdataservice.h" -#include "retroshare/rsgxsflags.h" -#include "util/rsstring.h" - -#define MSG_TABLE_NAME std::string("MESSAGES") -#define GRP_TABLE_NAME std::string("GROUPS") -#define DATABASE_RELEASE_TABLE_NAME std::string("DATABASE_RELEASE") - -#define GRP_LAST_POST_UPDATE_TRIGGER std::string("LAST_POST_UPDATE") - -#define MSG_INDEX_GRPID std::string("INDEX_MESSAGES_GRPID") - -// generic -#define KEY_NXS_DATA std::string("nxsData") -#define KEY_NXS_DATA_LEN std::string("nxsDataLen") -#define KEY_NXS_IDENTITY std::string("identity") -#define KEY_GRP_ID std::string("grpId") -#define KEY_ORIG_GRP_ID std::string("origGrpId") -#define KEY_PARENT_GRP_ID std::string("parentGrpId") -#define KEY_SIGN_SET std::string("signSet") -#define KEY_TIME_STAMP std::string("timeStamp") -#define KEY_NXS_FLAGS std::string("flags") -#define KEY_NXS_META std::string("meta") -#define KEY_NXS_SERV_STRING std::string("serv_str") -#define KEY_NXS_HASH std::string("hash") -#define KEY_RECV_TS std::string("recv_time_stamp") - -// remove later -#define KEY_NXS_FILE_OLD std::string("nxsFile") -#define KEY_NXS_FILE_OFFSET_OLD std::string("fileOffset") -#define KEY_NXS_FILE_LEN_OLD std::string("nxsFileLen") - -// grp table columns -#define KEY_KEY_SET std::string("keySet") -#define KEY_GRP_NAME std::string("grpName") -#define KEY_GRP_SIGN_FLAGS std::string("signFlags") -#define KEY_GRP_CIRCLE_ID std::string("circleId") -#define KEY_GRP_CIRCLE_TYPE std::string("circleType") -#define KEY_GRP_INTERNAL_CIRCLE std::string("internalCircle") -#define KEY_GRP_ORIGINATOR std::string("originator") -#define KEY_GRP_AUTHEN_FLAGS std::string("authenFlags") - -// grp local -#define KEY_GRP_SUBCR_FLAG std::string("subscribeFlag") -#define KEY_GRP_POP std::string("popularity") -#define KEY_MSG_COUNT std::string("msgCount") -#define KEY_GRP_STATUS std::string("grpStatus") -#define KEY_GRP_LAST_POST std::string("lastPost") -#define KEY_GRP_REP_CUTOFF std::string("rep_cutoff") - -// msg table columns -#define KEY_MSG_ID std::string("msgId") -#define KEY_ORIG_MSG_ID std::string("origMsgId") -#define KEY_MSG_PARENT_ID std::string("parentId") -#define KEY_MSG_THREAD_ID std::string("threadId") -#define KEY_MSG_NAME std::string("msgName") - -// msg local -#define KEY_MSG_STATUS std::string("msgStatus") -#define KEY_CHILD_TS std::string("childTs") - -// database release columns -#define KEY_DATABASE_RELEASE_ID std::string("id") -#define KEY_DATABASE_RELEASE_ID_VALUE 1 -#define KEY_DATABASE_RELEASE std::string("release") - -const std::string RsGeneralDataService::GRP_META_SERV_STRING = KEY_NXS_SERV_STRING; -const std::string RsGeneralDataService::GRP_META_STATUS = KEY_GRP_STATUS; -const std::string RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG = KEY_GRP_SUBCR_FLAG; -const std::string RsGeneralDataService::GRP_META_CUTOFF_LEVEL = KEY_GRP_REP_CUTOFF; - -const std::string RsGeneralDataService::MSG_META_SERV_STRING = KEY_NXS_SERV_STRING; -const std::string RsGeneralDataService::MSG_META_STATUS = KEY_MSG_STATUS; - -const uint32_t RsGeneralDataService::GXS_MAX_ITEM_SIZE = 1572864; // 1.5 Mbytes - -static int addColumn(std::list &list, const std::string &attribute) -{ - list.push_back(attribute); - return list.size() - 1; -} - -RsDataService::RsDataService(const std::string &serviceDir, const std::string &dbName, uint16_t serviceType, - RsGxsSearchModule * /* mod */, const std::string& key) - : RsGeneralDataService(), mDbMutex("RsDataService"), mServiceDir(serviceDir), mDbName(dbName), mDbPath(mServiceDir + "/" + dbName), mServType(serviceType), mDb(NULL) -{ - bool isNewDatabase = !RsDirUtil::fileExists(mDbPath); - - mDb = new RetroDb(mDbPath, RetroDb::OPEN_READWRITE_CREATE, key); - mUseCache = true; - - initialise(isNewDatabase); - - // for retrieving msg meta - mColMsgMeta_GrpId = addColumn(mMsgMetaColumns, KEY_GRP_ID); - mColMsgMeta_TimeStamp = addColumn(mMsgMetaColumns, KEY_TIME_STAMP); - mColMsgMeta_NxsFlags = addColumn(mMsgMetaColumns, KEY_NXS_FLAGS); - mColMsgMeta_SignSet = addColumn(mMsgMetaColumns, KEY_SIGN_SET); - mColMsgMeta_NxsIdentity = addColumn(mMsgMetaColumns, KEY_NXS_IDENTITY); - mColMsgMeta_NxsHash = addColumn(mMsgMetaColumns, KEY_NXS_HASH); - mColMsgMeta_MsgId = addColumn(mMsgMetaColumns, KEY_MSG_ID); - mColMsgMeta_OrigMsgId = addColumn(mMsgMetaColumns, KEY_ORIG_MSG_ID); - mColMsgMeta_MsgStatus = addColumn(mMsgMetaColumns, KEY_MSG_STATUS); - mColMsgMeta_ChildTs = addColumn(mMsgMetaColumns, KEY_CHILD_TS); - mColMsgMeta_MsgParentId = addColumn(mMsgMetaColumns, KEY_MSG_PARENT_ID); - mColMsgMeta_MsgThreadId = addColumn(mMsgMetaColumns, KEY_MSG_THREAD_ID); - mColMsgMeta_Name = addColumn(mMsgMetaColumns, KEY_MSG_NAME); - mColMsgMeta_NxsServString = addColumn(mMsgMetaColumns, KEY_NXS_SERV_STRING); - mColMsgMeta_RecvTs = addColumn(mMsgMetaColumns, KEY_RECV_TS); - mColMsgMeta_NxsDataLen = addColumn(mMsgMetaColumns, KEY_NXS_DATA_LEN); - - // for retrieving actual data - mColMsg_GrpId = addColumn(mMsgColumns, KEY_GRP_ID); - mColMsg_NxsData = addColumn(mMsgColumns, KEY_NXS_DATA); - mColMsg_MetaData = addColumn(mMsgColumns, KEY_NXS_META); - mColMsg_MsgId = addColumn(mMsgColumns, KEY_MSG_ID); - - // for retrieving msg data with meta - mMsgColumnsWithMeta = mMsgColumns; - mColMsg_WithMetaOffset = mMsgColumnsWithMeta.size(); - mMsgColumnsWithMeta.insert(mMsgColumnsWithMeta.end(), mMsgMetaColumns.begin(), mMsgMetaColumns.end()); - - // for retrieving grp meta data - mColGrpMeta_GrpId = addColumn(mGrpMetaColumns, KEY_GRP_ID); - mColGrpMeta_TimeStamp = addColumn(mGrpMetaColumns, KEY_TIME_STAMP); - mColGrpMeta_NxsFlags = addColumn(mGrpMetaColumns, KEY_NXS_FLAGS); -// mColGrpMeta_SignSet = addColumn(mGrpMetaColumns, KEY_SIGN_SET); - mColGrpMeta_NxsIdentity = addColumn(mGrpMetaColumns, KEY_NXS_IDENTITY); - mColGrpMeta_NxsHash = addColumn(mGrpMetaColumns, KEY_NXS_HASH); - mColGrpMeta_KeySet = addColumn(mGrpMetaColumns, KEY_KEY_SET); - mColGrpMeta_SubscrFlag = addColumn(mGrpMetaColumns, KEY_GRP_SUBCR_FLAG); - mColGrpMeta_Pop = addColumn(mGrpMetaColumns, KEY_GRP_POP); - mColGrpMeta_MsgCount = addColumn(mGrpMetaColumns, KEY_MSG_COUNT); - mColGrpMeta_Status = addColumn(mGrpMetaColumns, KEY_GRP_STATUS); - mColGrpMeta_Name = addColumn(mGrpMetaColumns, KEY_GRP_NAME); - mColGrpMeta_LastPost = addColumn(mGrpMetaColumns, KEY_GRP_LAST_POST); - mColGrpMeta_OrigGrpId = addColumn(mGrpMetaColumns, KEY_ORIG_GRP_ID); - mColGrpMeta_ServString = addColumn(mGrpMetaColumns, KEY_NXS_SERV_STRING); - mColGrpMeta_SignFlags = addColumn(mGrpMetaColumns, KEY_GRP_SIGN_FLAGS); - mColGrpMeta_CircleId = addColumn(mGrpMetaColumns, KEY_GRP_CIRCLE_ID); - mColGrpMeta_CircleType = addColumn(mGrpMetaColumns, KEY_GRP_CIRCLE_TYPE); - mColGrpMeta_InternCircle = addColumn(mGrpMetaColumns, KEY_GRP_INTERNAL_CIRCLE); - mColGrpMeta_Originator = addColumn(mGrpMetaColumns, KEY_GRP_ORIGINATOR); - mColGrpMeta_AuthenFlags = addColumn(mGrpMetaColumns, KEY_GRP_AUTHEN_FLAGS); - mColGrpMeta_ParentGrpId = addColumn(mGrpMetaColumns, KEY_PARENT_GRP_ID); - mColGrpMeta_RecvTs = addColumn(mGrpMetaColumns, KEY_RECV_TS); - mColGrpMeta_RepCutoff = addColumn(mGrpMetaColumns, KEY_GRP_REP_CUTOFF); - mColGrpMeta_NxsDataLen = addColumn(mGrpMetaColumns, KEY_NXS_DATA_LEN); - - // for retrieving actual grp data - mColGrp_GrpId = addColumn(mGrpColumns, KEY_GRP_ID); - mColGrp_NxsData = addColumn(mGrpColumns, KEY_NXS_DATA); - mColGrp_MetaData = addColumn(mGrpColumns, KEY_NXS_META); - - // for retrieving grp data with meta - mGrpColumnsWithMeta = mGrpColumns; - mColGrp_WithMetaOffset = mGrpColumnsWithMeta.size(); - mGrpColumnsWithMeta.insert(mGrpColumnsWithMeta.end(), mGrpMetaColumns.begin(), mGrpMetaColumns.end()); - - // Group id columns - mColGrpId_GrpId = addColumn(mGrpIdColumn, KEY_GRP_ID); - - // Msg id columns - mColMsgId_MsgId = addColumn(mMsgIdColumn, KEY_MSG_ID); -} - -RsDataService::~RsDataService(){ - -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "RsDataService::~RsDataService()"; - std::cerr << std::endl; -#endif - - mDb->closeDb(); - delete mDb; -} - -static bool moveDataFromFileToDatabase(RetroDb *db, const std::string serviceDir, const std::string &tableName, const std::string &keyId, std::list &files) -{ - bool ok = true; - - // Move message data - std::list columns; - columns.push_back(keyId); - columns.push_back(KEY_NXS_FILE_OLD); - columns.push_back(KEY_NXS_FILE_OFFSET_OLD); - columns.push_back(KEY_NXS_FILE_LEN_OLD); - - RetroCursor* c = db->sqlQuery(tableName, columns, "", ""); - - if (c) - { - bool valid = c->moveToFirst(); - - while (ok && valid){ - std::string dataFile; - c->getString(1, dataFile); - - if (!dataFile.empty()) { - bool fileOk = true; - - // first try to find the file in the service dir - if (RsDirUtil::fileExists(serviceDir + "/" + dataFile)) { - dataFile.insert(0, serviceDir + "/"); - } else if (RsDirUtil::fileExists(dataFile)) { - // use old way for backward compatibility - //TODO: can be removed later - } else { - fileOk = false; - - std::cerr << "moveDataFromFileToDatabase() cannot find file " << dataFile; - std::cerr << std::endl; - } - - if (fileOk) { - std::string id; - c->getString(0, id); - - uint32_t offset = c->getInt32(2); - uint32_t data_len = c->getInt32(3); - - char* data = new char[data_len]; - std::ifstream istrm(dataFile.c_str(), std::ios::binary); - istrm.seekg(offset, std::ios::beg); - istrm.read(data, data_len); - istrm.close(); - - ContentValue cv; - // insert new columns - cv.put(KEY_NXS_DATA, data_len, data); - cv.put(KEY_NXS_DATA_LEN, (int32_t) data_len); - // clear old columns - cv.put(KEY_NXS_FILE_OLD, ""); - cv.put(KEY_NXS_FILE_OFFSET_OLD, 0); - cv.put(KEY_NXS_FILE_LEN_OLD, 0); - - ok = db->sqlUpdate(tableName, keyId + "='" + id + "'", cv); - delete[] data; - - if (std::find(files.begin(), files.end(), dataFile) == files.end()) { - files.push_back(dataFile); - } - } - } - - valid = c->moveToNext(); - } - - delete c; - } - - return ok; -} - -void RsDataService::initialise(bool isNewDatabase) -{ - const int databaseRelease = 1; - int currentDatabaseRelease = 0; - bool ok = true; - - RsStackMutex stack(mDbMutex); - - // initialise database - - if (isNewDatabase || !mDb->tableExists(DATABASE_RELEASE_TABLE_NAME)) { - // create table for database release - mDb->execSQL("CREATE TABLE " + DATABASE_RELEASE_TABLE_NAME + "(" + - KEY_DATABASE_RELEASE_ID + " INT PRIMARY KEY," + - KEY_DATABASE_RELEASE + " INT);"); - } - - if (isNewDatabase) { - // create table for msg data - mDb->execSQL("CREATE TABLE " + MSG_TABLE_NAME + "(" + - KEY_MSG_ID + " TEXT PRIMARY KEY," + - KEY_GRP_ID + " TEXT," + - KEY_NXS_FLAGS + " INT," + - KEY_ORIG_MSG_ID + " TEXT," + - KEY_TIME_STAMP + " INT," + - KEY_NXS_IDENTITY + " TEXT," + - KEY_SIGN_SET + " BLOB," + - KEY_NXS_DATA + " BLOB,"+ - KEY_NXS_DATA_LEN + " INT," + - KEY_MSG_STATUS + " INT," + - KEY_CHILD_TS + " INT," + - KEY_NXS_META + " BLOB," + - KEY_MSG_THREAD_ID + " TEXT," + - KEY_MSG_PARENT_ID + " TEXT,"+ - KEY_MSG_NAME + " TEXT," + - KEY_NXS_SERV_STRING + " TEXT," + - KEY_NXS_HASH + " TEXT," + - KEY_RECV_TS + " INT);"); - - // create table for grp data - mDb->execSQL("CREATE TABLE " + GRP_TABLE_NAME + "(" + - KEY_GRP_ID + " TEXT PRIMARY KEY," + - KEY_TIME_STAMP + " INT," + - KEY_NXS_DATA + " BLOB," + - KEY_NXS_DATA_LEN + " INT," + - KEY_KEY_SET + " BLOB," + - KEY_NXS_META + " BLOB," + - KEY_GRP_NAME + " TEXT," + - KEY_GRP_LAST_POST + " INT," + - KEY_GRP_POP + " INT," + - KEY_MSG_COUNT + " INT," + - KEY_GRP_SUBCR_FLAG + " INT," + - KEY_GRP_STATUS + " INT," + - KEY_NXS_IDENTITY + " TEXT," + - KEY_ORIG_GRP_ID + " TEXT," + - KEY_NXS_SERV_STRING + " TEXT," + - KEY_NXS_FLAGS + " INT," + - KEY_GRP_AUTHEN_FLAGS + " INT," + - KEY_GRP_SIGN_FLAGS + " INT," + - KEY_GRP_CIRCLE_ID + " TEXT," + - KEY_GRP_CIRCLE_TYPE + " INT," + - KEY_GRP_INTERNAL_CIRCLE + " TEXT," + - KEY_GRP_ORIGINATOR + " TEXT," + - KEY_NXS_HASH + " TEXT," + - KEY_RECV_TS + " INT," + - KEY_PARENT_GRP_ID + " TEXT," + - KEY_GRP_REP_CUTOFF + " INT," + - KEY_SIGN_SET + " BLOB);"); - - mDb->execSQL("CREATE TRIGGER " + GRP_LAST_POST_UPDATE_TRIGGER + - " INSERT ON " + MSG_TABLE_NAME + - std::string(" BEGIN ") + - " UPDATE " + GRP_TABLE_NAME + " SET " + KEY_GRP_LAST_POST + "= new." - + KEY_RECV_TS + " WHERE " + KEY_GRP_ID + "=new." + KEY_GRP_ID + ";" - + std::string("END;")); - - mDb->execSQL("CREATE INDEX " + MSG_INDEX_GRPID + " ON " + MSG_TABLE_NAME + "(" + KEY_GRP_ID + ");"); - - // Insert release, no need to upgrade - ContentValue cv; - cv.put(KEY_DATABASE_RELEASE_ID, KEY_DATABASE_RELEASE_ID_VALUE); - cv.put(KEY_DATABASE_RELEASE, databaseRelease); - mDb->sqlInsert(DATABASE_RELEASE_TABLE_NAME, "", cv); - - currentDatabaseRelease = databaseRelease; - } else { - // check release - - { - // try to select the release - std::list columns; - columns.push_back(KEY_DATABASE_RELEASE); - - std::string where; - rs_sprintf(where, "%s=%d", KEY_DATABASE_RELEASE_ID.c_str(), KEY_DATABASE_RELEASE_ID_VALUE); - - RetroCursor* c = mDb->sqlQuery(DATABASE_RELEASE_TABLE_NAME, columns, where, ""); - if (c) { - ok = c->moveToFirst(); - - if (ok) { - currentDatabaseRelease = c->getInt32(0); - } - delete c; - - if (!ok) { - // No record found ... insert the record - ContentValue cv; - cv.put(KEY_DATABASE_RELEASE_ID, KEY_DATABASE_RELEASE_ID_VALUE); - cv.put(KEY_DATABASE_RELEASE, currentDatabaseRelease); - ok = mDb->sqlInsert(DATABASE_RELEASE_TABLE_NAME, "", cv); - } - } else { - ok = false; - } - } - - // Release 1 - int newRelease = 1; - if (ok && currentDatabaseRelease < newRelease) { - // Update database - std::list files; - - ok = startReleaseUpdate(newRelease); - - // Move data in files into database - ok = ok && mDb->execSQL("ALTER TABLE " + GRP_TABLE_NAME + " ADD COLUMN " + KEY_NXS_DATA + " BLOB;"); - ok = ok && mDb->execSQL("ALTER TABLE " + GRP_TABLE_NAME + " ADD COLUMN " + KEY_NXS_DATA_LEN + " INT;"); - ok = ok && mDb->execSQL("ALTER TABLE " + MSG_TABLE_NAME + " ADD COLUMN " + KEY_NXS_DATA + " BLOB;"); - ok = ok && mDb->execSQL("ALTER TABLE " + MSG_TABLE_NAME + " ADD COLUMN " + KEY_NXS_DATA_LEN + " INT;"); - - ok = ok && moveDataFromFileToDatabase(mDb, mServiceDir, GRP_TABLE_NAME, KEY_GRP_ID, files); - ok = ok && moveDataFromFileToDatabase(mDb, mServiceDir, MSG_TABLE_NAME, KEY_MSG_ID, files); - -// SQLite doesn't support DROP COLUMN -// ok = ok && mDb->execSQL("ALTER TABLE " + GRP_TABLE_NAME + " DROP COLUMN " + KEY_NXS_FILE_OLD + ";"); -// ok = ok && mDb->execSQL("ALTER TABLE " + GRP_TABLE_NAME + " DROP COLUMN " + KEY_NXS_FILE_OFFSET_OLD + ";"); -// ok = ok && mDb->execSQL("ALTER TABLE " + GRP_TABLE_NAME + " DROP COLUMN " + KEY_NXS_FILE_LEN_OLD + ";"); -// ok = ok && mDb->execSQL("ALTER TABLE " + MSG_TABLE_NAME + " DROP COLUMN " + KEY_NXS_FILE_OLD + ";"); -// ok = ok && mDb->execSQL("ALTER TABLE " + MSG_TABLE_NAME + " DROP COLUMN " + KEY_NXS_FILE_OFFSET_OLD + ";"); -// ok = ok && mDb->execSQL("ALTER TABLE " + MSG_TABLE_NAME + " DROP COLUMN " + KEY_NXS_FILE_LEN_OLD + ";"); - - ok = finishReleaseUpdate(newRelease, ok); - if (ok) { - // Remove transfered files - std::list::const_iterator file; - for (file = files.begin(); file != files.end(); ++file) { - remove(file->c_str()); - } - currentDatabaseRelease = newRelease; - } - } - } - - if (ok) { - std::cerr << "Database " << mDbName << " release " << currentDatabaseRelease << " successfully initialised." << std::endl; - } else { - std::cerr << "Database " << mDbName << " initialisation failed." << std::endl; - } -} - -bool RsDataService::startReleaseUpdate(int release) -{ - // Update database - std::cerr << "Database " << mDbName << " update to release " << release << "." << std::endl; - - return mDb->beginTransaction(); -} - -bool RsDataService::finishReleaseUpdate(int release, bool result) -{ - if (result) { - std::string where; - rs_sprintf(where, "%s=%d", KEY_DATABASE_RELEASE_ID.c_str(), KEY_DATABASE_RELEASE_ID_VALUE); - - ContentValue cv; - cv.put(KEY_DATABASE_RELEASE, release); - result = mDb->sqlUpdate(DATABASE_RELEASE_TABLE_NAME, where, cv); - } - - if (result) { - result = mDb->commitTransaction(); - } else { - result = mDb->rollbackTransaction(); - } - - if (result) { - std::cerr << "Database " << mDbName << " successfully updated to release " << release << "." << std::endl; - } else { - std::cerr << "Database " << mDbName << " update to release " << release << "failed." << std::endl; - } - - return result; -} - -std::shared_ptr RsDataService::locked_getGrpMeta(RetroCursor& c, int colOffset) -{ -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "RsDataService::locked_getGrpMeta()" << std::endl; -#endif - - bool ok = true; - - // for extracting raw data - uint32_t offset = 0; - char* data = NULL; - uint32_t data_len = 0; - - // grpId - std::string tempId; - c.getString(mColGrpMeta_GrpId + colOffset, tempId); - - std::shared_ptr grpMeta ; - RsGxsGroupId grpId(tempId) ; - - if(grpId.isNull()) // not in the DB! - return nullptr; - - if(mUseCache) - grpMeta = mGrpMetaDataCache.getOrCreateMeta(grpId); - else - grpMeta = std::make_shared(); - - if(!grpMeta->mGroupId.isNull()) // the grpMeta is already initialized because it comes from the cache - return grpMeta; - - grpMeta->mGroupId = RsGxsGroupId(tempId); - c.getString(mColGrpMeta_NxsIdentity + colOffset, tempId); - grpMeta->mAuthorId = RsGxsId(tempId); - - c.getString(mColGrpMeta_Name + colOffset, grpMeta->mGroupName); - c.getString(mColGrpMeta_OrigGrpId + colOffset, tempId); - grpMeta->mOrigGrpId = RsGxsGroupId(tempId); - c.getString(mColGrpMeta_ServString + colOffset, grpMeta->mServiceString); - std::string temp; - c.getString(mColGrpMeta_NxsHash + colOffset, temp); - grpMeta->mHash = RsFileHash(temp); - grpMeta->mReputationCutOff = c.getInt32(mColGrpMeta_RepCutoff + colOffset); - grpMeta->mSignFlags = c.getInt32(mColGrpMeta_SignFlags + colOffset); - - grpMeta->mPublishTs = c.getInt32(mColGrpMeta_TimeStamp + colOffset); - grpMeta->mGroupFlags = c.getInt32(mColGrpMeta_NxsFlags + colOffset); - grpMeta->mGrpSize = c.getInt32(mColGrpMeta_NxsDataLen + colOffset); - - offset = 0; data = NULL; data_len = 0; - data = (char*)c.getData(mColGrpMeta_KeySet + colOffset, data_len); - - if(data) - ok &= grpMeta->keys.GetTlv(data, data_len, &offset); - else - grpMeta->keys.TlvClear() ; - - // local meta - grpMeta->mSubscribeFlags = c.getInt32(mColGrpMeta_SubscrFlag + colOffset); - grpMeta->mPop = c.getInt32(mColGrpMeta_Pop + colOffset); - grpMeta->mVisibleMsgCount = c.getInt32(mColGrpMeta_MsgCount + colOffset); - grpMeta->mLastPost = c.getInt32(mColGrpMeta_LastPost + colOffset); - grpMeta->mGroupStatus = c.getInt32(mColGrpMeta_Status + colOffset); - - c.getString(mColGrpMeta_CircleId + colOffset, tempId); - grpMeta->mCircleId = RsGxsCircleId(tempId); - grpMeta->mCircleType = c.getInt32(mColGrpMeta_CircleType + colOffset); - c.getString(mColGrpMeta_InternCircle + colOffset, tempId); - grpMeta->mInternalCircle = RsGxsCircleId(tempId); - - std::string s ; c.getString(mColGrpMeta_Originator + colOffset, s) ; - grpMeta->mOriginator = RsPeerId(s); - grpMeta->mAuthenFlags = c.getInt32(mColGrpMeta_AuthenFlags + colOffset); - grpMeta->mRecvTS = c.getInt32(mColGrpMeta_RecvTs + colOffset); - - - c.getString(mColGrpMeta_ParentGrpId, tempId); - grpMeta->mParentGrpId = RsGxsGroupId(tempId); - - // make sure that flags and keys are actually consistent - - bool have_private_admin_key = false ; - bool have_private_publish_key = false ; - - for(auto mit = grpMeta->keys.private_keys.begin(); mit != grpMeta->keys.private_keys.end();++mit) - { - if(mit->second.keyFlags == (RSTLV_KEY_DISTRIB_PUBLISH | RSTLV_KEY_TYPE_FULL)) have_private_publish_key = true ; - if(mit->second.keyFlags == (RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL)) have_private_admin_key = true ; - } - - if(have_private_admin_key && !(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) - { - std::cerr << "(WW) inconsistency in group " << grpMeta->mGroupId << ": group does not have flag ADMIN but an admin key was found. Updating the flags." << std::endl; - grpMeta->mSubscribeFlags |= GXS_SERV::GROUP_SUBSCRIBE_ADMIN; - } - if(!have_private_admin_key && (grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) - { - std::cerr << "(WW) inconsistency in group " << grpMeta->mGroupId << ": group has flag ADMIN but no admin key found. Updating the flags." << std::endl; - grpMeta->mSubscribeFlags &= ~GXS_SERV::GROUP_SUBSCRIBE_ADMIN; - } - if(have_private_publish_key && !(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH)) - { - std::cerr << "(WW) inconsistency in group " << grpMeta->mGroupId << ": group does not have flag PUBLISH but an admin key was found. Updating the flags." << std::endl; - grpMeta->mSubscribeFlags |= GXS_SERV::GROUP_SUBSCRIBE_PUBLISH; - } - if(!have_private_publish_key && (grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH)) - { - std::cerr << "(WW) inconsistency in group " << grpMeta->mGroupId << ": group has flag PUBLISH but no admin key found. Updating the flags." << std::endl; - grpMeta->mSubscribeFlags &= ~GXS_SERV::GROUP_SUBSCRIBE_PUBLISH; - } - - if(ok) - return grpMeta; - else - return NULL; -} - -RsNxsGrp* RsDataService::locked_getGroup(RetroCursor &c) -{ - /*! - * grpId, pub admin and pub publish key - * necessary for successful group - */ - RsNxsGrp* grp = new RsNxsGrp(mServType); - bool ok = true; - - // for manipulating raw data - uint32_t offset = 0; - char* data = NULL; - uint32_t data_len = 0; - - // grpId - c.getStringT(mColGrp_GrpId, grp->grpId); - ok &= !grp->grpId.isNull(); - - offset = 0; data_len = 0; - if(ok){ - - data = (char*)c.getData(mColGrp_MetaData, data_len); - if(data) - grp->meta.GetTlv(data, data_len, &offset); - } - - /* now retrieve grp data */ - offset = 0; data_len = 0; - if(ok){ - data = (char*)c.getData(mColGrp_NxsData, data_len); - if(data) - ok &= grp->grp.GetTlv(data, data_len, &offset); - } - - if(ok) - return grp; - else - delete grp; - - return NULL; -} - -std::shared_ptr RsDataService::locked_getMsgMeta(RetroCursor &c, int colOffset) -{ - bool ok = true; - uint32_t data_len = 0, - offset = 0; - char* data = NULL; - - RsGxsGroupId group_id; - RsGxsMessageId msg_id; - - std::string gId; - c.getString(mColMsgMeta_GrpId + colOffset, gId); - group_id = RsGxsGroupId(gId); - std::string temp; - c.getString(mColMsgMeta_MsgId + colOffset, temp); - msg_id = RsGxsMessageId(temp); - - // without these, a msg is meaningless - if(group_id.isNull() || msg_id.isNull()) - return nullptr; - - std::shared_ptr msgMeta; - - if(mUseCache) - msgMeta = mMsgMetaDataCache[group_id].getOrCreateMeta(msg_id); - else - msgMeta = std::make_shared(); - - if(!msgMeta->mGroupId.isNull()) // we cannot do that because the cursor needs to advance. Is there a method to skip some data in the db? - return msgMeta; - - msgMeta->mGroupId = group_id; - msgMeta->mMsgId = msg_id; - - c.getString(mColMsgMeta_OrigMsgId + colOffset, temp); - msgMeta->mOrigMsgId = RsGxsMessageId(temp); - c.getString(mColMsgMeta_NxsIdentity + colOffset, temp); - msgMeta->mAuthorId = RsGxsId(temp); - c.getString(mColMsgMeta_Name + colOffset, msgMeta->mMsgName); - c.getString(mColMsgMeta_NxsServString + colOffset, msgMeta->mServiceString); - - c.getString(mColMsgMeta_NxsHash + colOffset, temp); - msgMeta->mHash = RsFileHash(temp); - msgMeta->recvTS = c.getInt32(mColMsgMeta_RecvTs + colOffset); - offset = 0; - data = (char*)c.getData(mColMsgMeta_SignSet + colOffset, data_len); - msgMeta->signSet.GetTlv(data, data_len, &offset); - msgMeta->mMsgSize = c.getInt32(mColMsgMeta_NxsDataLen + colOffset); - - msgMeta->mMsgFlags = c.getInt32(mColMsgMeta_NxsFlags + colOffset); - msgMeta->mPublishTs = c.getInt32(mColMsgMeta_TimeStamp + colOffset); - - offset = 0; data_len = 0; - - // thread and parent id - c.getString(mColMsgMeta_MsgThreadId + colOffset, temp); - msgMeta->mThreadId = RsGxsMessageId(temp); - c.getString(mColMsgMeta_MsgParentId + colOffset, temp); - msgMeta->mParentId = RsGxsMessageId(temp); - - // local meta - msgMeta->mMsgStatus = c.getInt32(mColMsgMeta_MsgStatus + colOffset); - msgMeta->mChildTs = c.getInt32(mColMsgMeta_ChildTs + colOffset); - - if(ok) - return msgMeta; - - return nullptr; -} - - - -RsNxsMsg* RsDataService::locked_getMessage(RetroCursor &c) -{ - - RsNxsMsg* msg = new RsNxsMsg(mServType); - - bool ok = true; - uint32_t data_len = 0, - offset = 0; - char* data = NULL; - c.getStringT(mColMsg_GrpId, msg->grpId); - std::string temp; - c.getString(mColMsg_MsgId, temp); - msg->msgId = RsGxsMessageId(temp); - - ok &= (!msg->grpId.isNull()) && (!msg->msgId.isNull()); - - offset = 0; data_len = 0; - if(ok){ - - data = (char*)c.getData(mColMsg_MetaData, data_len); - if(data) - msg->meta.GetTlv(data, data_len, &offset); - } - - /* now retrieve msg data */ - offset = 0; data_len = 0; - if(ok){ - data = (char*)c.getData(mColMsg_NxsData, data_len); - if(data) - ok &= msg->msg.GetTlv(data, data_len, &offset); - } - - if(ok) - return msg; - - delete msg; - return nullptr; -} - -int RsDataService::storeMessage(const std::list& msg) -{ - - RsStackMutex stack(mDbMutex); - - // start a transaction - mDb->beginTransaction(); - - for(std::list::const_iterator mit = msg.begin(); mit != msg.end(); ++mit) - { - RsNxsMsg* msgPtr = *mit; - RsGxsMsgMetaData* msgMetaPtr = msgPtr->metaData; - - assert(msgMetaPtr != NULL); - -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "RsDataService::storeMessage() "; - std::cerr << " GroupId: " << msgMetaPtr->mGroupId.toStdString(); - std::cerr << " MessageId: " << msgMetaPtr->mMsgId.toStdString(); - std::cerr << std::endl; -#endif - - // skip msg item if size if greater than - if(!validSize(msgPtr)) - { - std::cerr << "RsDataService::storeMessage() ERROR invalid size"; - std::cerr << std::endl; - continue; - } - - ContentValue cv; - - uint32_t dataLen = msgPtr->msg.TlvSize(); - char msgData[dataLen]; - uint32_t offset = 0; - msgPtr->msg.SetTlv(msgData, dataLen, &offset); - cv.put(KEY_NXS_DATA, dataLen, msgData); - - cv.put(KEY_NXS_DATA_LEN, (int32_t)dataLen); - cv.put(KEY_MSG_ID, msgMetaPtr->mMsgId.toStdString()); - cv.put(KEY_GRP_ID, msgMetaPtr->mGroupId.toStdString()); - cv.put(KEY_NXS_SERV_STRING, msgMetaPtr->mServiceString); - cv.put(KEY_NXS_HASH, msgMetaPtr->mHash.toStdString()); - cv.put(KEY_RECV_TS, (int32_t)msgMetaPtr->recvTS); - - - char signSetData[msgMetaPtr->signSet.TlvSize()]; - offset = 0; - msgMetaPtr->signSet.SetTlv(signSetData, msgMetaPtr->signSet.TlvSize(), &offset); - cv.put(KEY_SIGN_SET, msgMetaPtr->signSet.TlvSize(), signSetData); - cv.put(KEY_NXS_IDENTITY, msgMetaPtr->mAuthorId.toStdString()); - - - cv.put(KEY_NXS_FLAGS, (int32_t) msgMetaPtr->mMsgFlags); - cv.put(KEY_TIME_STAMP, (int32_t) msgMetaPtr->mPublishTs); - - offset = 0; - char metaData[msgPtr->meta.TlvSize()]; - msgPtr->meta.SetTlv(metaData, msgPtr->meta.TlvSize(), &offset); - cv.put(KEY_NXS_META, msgPtr->meta.TlvSize(), metaData); - - cv.put(KEY_MSG_PARENT_ID, msgMetaPtr->mParentId.toStdString()); - cv.put(KEY_MSG_THREAD_ID, msgMetaPtr->mThreadId.toStdString()); - cv.put(KEY_ORIG_MSG_ID, msgMetaPtr->mOrigMsgId.toStdString()); - cv.put(KEY_MSG_NAME, msgMetaPtr->mMsgName); - - // now local meta - cv.put(KEY_MSG_STATUS, (int32_t)msgMetaPtr->mMsgStatus); - cv.put(KEY_CHILD_TS, (int32_t)msgMetaPtr->mChildTs); - - if (!mDb->sqlInsert(MSG_TABLE_NAME, "", cv)) - { - std::cerr << "RsDataService::storeMessage() sqlInsert Failed"; - std::cerr << std::endl; - std::cerr << "\t For GroupId: " << msgMetaPtr->mGroupId.toStdString(); - std::cerr << std::endl; - std::cerr << "\t & MessageId: " << msgMetaPtr->mMsgId.toStdString(); - std::cerr << std::endl; - } - - // This is needed so that mLastPost is correctly updated in the group meta when it is re-loaded. - - if(mUseCache) - mMsgMetaDataCache[msgMetaPtr->mGroupId].updateMeta(msgMetaPtr->mMsgId,*msgMetaPtr); - - delete *mit; - } - - // finish transaction - bool ret = mDb->commitTransaction(); - - return ret; -} - -bool RsDataService::validSize(RsNxsMsg* msg) const -{ - if((msg->msg.TlvSize() + msg->meta.TlvSize()) <= GXS_MAX_ITEM_SIZE) return true; - - return false; -} - - -int RsDataService::storeGroup(const std::list& grp) -{ - - RsStackMutex stack(mDbMutex); - - // begin transaction - mDb->beginTransaction(); - - for(std::list::const_iterator sit = grp.begin();sit != grp.end(); ++sit) - { - RsNxsGrp* grpPtr = *sit; - RsGxsGrpMetaData* grpMetaPtr = grpPtr->metaData; - - assert(grpMetaPtr != NULL); - - // if data is larger than max item size do not add - if(!validSize(grpPtr)) continue; - -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "RsDataService::storeGroup() GrpId: " << grpPtr->grpId.toStdString(); - std::cerr << " CircleType: " << (uint32_t) grpMetaPtr->mCircleType; - std::cerr << " CircleId: " << grpMetaPtr->mCircleId.toStdString(); - std::cerr << std::endl; -#endif - - /*! - * STORE data, data len, - * grpId, flags, publish time stamp, identity, - * id signature, admin signatue, key set, last posting ts - * and meta data - **/ - ContentValue cv; - - uint32_t dataLen = grpPtr->grp.TlvSize(); - char grpData[dataLen]; - uint32_t offset = 0; - grpPtr->grp.SetTlv(grpData, dataLen, &offset); - cv.put(KEY_NXS_DATA, dataLen, grpData); - - cv.put(KEY_NXS_DATA_LEN, (int32_t) dataLen); - cv.put(KEY_GRP_ID, grpPtr->grpId.toStdString()); - cv.put(KEY_GRP_NAME, grpMetaPtr->mGroupName); - cv.put(KEY_ORIG_GRP_ID, grpMetaPtr->mOrigGrpId.toStdString()); - cv.put(KEY_NXS_SERV_STRING, grpMetaPtr->mServiceString); - cv.put(KEY_NXS_FLAGS, (int32_t)grpMetaPtr->mGroupFlags); - cv.put(KEY_TIME_STAMP, (int32_t)grpMetaPtr->mPublishTs); - cv.put(KEY_GRP_SIGN_FLAGS, (int32_t)grpMetaPtr->mSignFlags); - cv.put(KEY_GRP_CIRCLE_ID, grpMetaPtr->mCircleId.toStdString()); - cv.put(KEY_GRP_CIRCLE_TYPE, (int32_t)grpMetaPtr->mCircleType); - cv.put(KEY_GRP_INTERNAL_CIRCLE, grpMetaPtr->mInternalCircle.toStdString()); - cv.put(KEY_GRP_ORIGINATOR, grpMetaPtr->mOriginator.toStdString()); - cv.put(KEY_GRP_AUTHEN_FLAGS, (int32_t)grpMetaPtr->mAuthenFlags); - cv.put(KEY_PARENT_GRP_ID, grpMetaPtr->mParentGrpId.toStdString()); - cv.put(KEY_NXS_HASH, grpMetaPtr->mHash.toStdString()); - cv.put(KEY_RECV_TS, (int32_t)grpMetaPtr->mRecvTS); - cv.put(KEY_GRP_REP_CUTOFF, (int32_t)grpMetaPtr->mReputationCutOff); - cv.put(KEY_NXS_IDENTITY, grpMetaPtr->mAuthorId.toStdString()); - - offset = 0; - char keySetData[grpMetaPtr->keys.TlvSize()]; - grpMetaPtr->keys.SetTlv(keySetData, grpMetaPtr->keys.TlvSize(), &offset); - cv.put(KEY_KEY_SET, grpMetaPtr->keys.TlvSize(), keySetData); - - offset = 0; - char metaData[grpPtr->meta.TlvSize()]; - grpPtr->meta.SetTlv(metaData, grpPtr->meta.TlvSize(), &offset); - cv.put(KEY_NXS_META, grpPtr->meta.TlvSize(), metaData); - - // local meta data - cv.put(KEY_GRP_SUBCR_FLAG, (int32_t)grpMetaPtr->mSubscribeFlags); - cv.put(KEY_GRP_POP, (int32_t)grpMetaPtr->mPop); - cv.put(KEY_MSG_COUNT, (int32_t)grpMetaPtr->mVisibleMsgCount); - cv.put(KEY_GRP_STATUS, (int32_t)grpMetaPtr->mGroupStatus); - cv.put(KEY_GRP_LAST_POST, (int32_t)grpMetaPtr->mLastPost); - - mGrpMetaDataCache.updateMeta(grpMetaPtr->mGroupId,*grpMetaPtr); - - if (!mDb->sqlInsert(GRP_TABLE_NAME, "", cv)) - { - std::cerr << "RsDataService::storeGroup() sqlInsert Failed"; - std::cerr << std::endl; - std::cerr << "\t For GroupId: " << grpMetaPtr->mGroupId.toStdString(); - std::cerr << std::endl; - } - - delete *sit; - } - // finish transaction - bool ret = mDb->commitTransaction(); - - return ret; -} - -int RsDataService::updateGroup(const std::list &grp) -{ - - RsStackMutex stack(mDbMutex); - - // begin transaction - mDb->beginTransaction(); - - for( std::list::const_iterator sit = grp.begin(); sit != grp.end(); ++sit) - { - - RsNxsGrp* grpPtr = *sit; - RsGxsGrpMetaData* grpMetaPtr = grpPtr->metaData; - - assert(grpMetaPtr != NULL); - - // if data is larger than max item size do not add - if(!validSize(grpPtr)) continue; - - /*! - * STORE data, data len, - * grpId, flags, publish time stamp, identity, - * id signature, admin signatue, key set, last posting ts - * and meta data - **/ - ContentValue cv; - uint32_t dataLen = grpPtr->grp.TlvSize(); - char grpData[dataLen]; - uint32_t offset = 0; - grpPtr->grp.SetTlv(grpData, dataLen, &offset); - cv.put(KEY_NXS_DATA, dataLen, grpData); - - cv.put(KEY_NXS_DATA_LEN, (int32_t) dataLen); - cv.put(KEY_GRP_ID, grpPtr->grpId.toStdString()); - cv.put(KEY_GRP_NAME, grpMetaPtr->mGroupName); - cv.put(KEY_ORIG_GRP_ID, grpMetaPtr->mOrigGrpId.toStdString()); - cv.put(KEY_NXS_SERV_STRING, grpMetaPtr->mServiceString); - cv.put(KEY_NXS_FLAGS, (int32_t)grpMetaPtr->mGroupFlags); - cv.put(KEY_TIME_STAMP, (int32_t)grpMetaPtr->mPublishTs); - cv.put(KEY_GRP_SIGN_FLAGS, (int32_t)grpMetaPtr->mSignFlags); - cv.put(KEY_GRP_CIRCLE_ID, grpMetaPtr->mCircleId.toStdString()); - cv.put(KEY_GRP_CIRCLE_TYPE, (int32_t)grpMetaPtr->mCircleType); - cv.put(KEY_GRP_INTERNAL_CIRCLE, grpMetaPtr->mInternalCircle.toStdString()); - cv.put(KEY_GRP_ORIGINATOR, grpMetaPtr->mOriginator.toStdString()); - cv.put(KEY_GRP_AUTHEN_FLAGS, (int32_t)grpMetaPtr->mAuthenFlags); - cv.put(KEY_NXS_HASH, grpMetaPtr->mHash.toStdString()); - cv.put(KEY_RECV_TS, (int32_t)grpMetaPtr->mRecvTS); - cv.put(KEY_NXS_IDENTITY, grpMetaPtr->mAuthorId.toStdString()); - - offset = 0; - char keySetData[grpMetaPtr->keys.TlvSize()]; - grpMetaPtr->keys.SetTlv(keySetData, grpMetaPtr->keys.TlvSize(), &offset); - cv.put(KEY_KEY_SET, grpMetaPtr->keys.TlvSize(), keySetData); - - offset = 0; - char metaData[grpPtr->meta.TlvSize()]; - grpPtr->meta.SetTlv(metaData, grpPtr->meta.TlvSize(), &offset); - cv.put(KEY_NXS_META, grpPtr->meta.TlvSize(), metaData); - - // local meta data - cv.put(KEY_GRP_SUBCR_FLAG, (int32_t)grpMetaPtr->mSubscribeFlags); - cv.put(KEY_GRP_POP, (int32_t)grpMetaPtr->mPop); - cv.put(KEY_MSG_COUNT, (int32_t)grpMetaPtr->mVisibleMsgCount); - cv.put(KEY_GRP_STATUS, (int32_t)grpMetaPtr->mGroupStatus); - cv.put(KEY_GRP_LAST_POST, (int32_t)grpMetaPtr->mLastPost); - - mDb->sqlUpdate(GRP_TABLE_NAME, "grpId='" + grpPtr->grpId.toStdString() + "'", cv); - - mGrpMetaDataCache.updateMeta(grpMetaPtr->mGroupId,*grpMetaPtr); - - delete *sit; - } - // finish transaction - bool ret = mDb->commitTransaction(); - - return ret; -} - -int RsDataService::updateGroupKeys(const RsGxsGroupId& grpId,const RsTlvSecurityKeySet& keys,uint32_t subscribe_flags) -{ - RsStackMutex stack(mDbMutex); - - // begin transaction - mDb->beginTransaction(); - - /*! - * STORE key set - **/ - - ContentValue cv; - //cv.put(KEY_NXS_FLAGS, (int32_t)grpMetaPtr->mGroupFlags); ? - - uint32_t offset = 0; - char keySetData[keys.TlvSize()]; - keys.SetTlv(keySetData, keys.TlvSize(), &offset); - cv.put(KEY_KEY_SET, keys.TlvSize(), keySetData); - cv.put(KEY_GRP_SUBCR_FLAG, (int32_t)subscribe_flags); - - mDb->sqlUpdate(GRP_TABLE_NAME, "grpId='" + grpId.toStdString() + "'", cv); - - // finish transaction - bool res = mDb->commitTransaction(); - - mGrpMetaDataCache.clear(grpId); - mGrpMetaDataCache.setCacheUpToDate(false); // this is needed because clear() doesn't do it (on purpose) - - return res; -} - -bool RsDataService::validSize(RsNxsGrp* grp) const -{ - if((grp->grp.TlvSize() + grp->meta.TlvSize()) <= GXS_MAX_ITEM_SIZE) return true; - return false; -} - -int RsDataService::retrieveNxsGrps(std::map &grp, bool withMeta) -{ -#ifdef RS_DATA_SERVICE_DEBUG_TIME - rstime::RsScopeTimer timer(""); - int resultCount = 0; - int requestedGroups = grp.size(); -#endif - - if(grp.empty()) - { - RsStackMutex stack(mDbMutex); - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, withMeta ? mGrpColumnsWithMeta : mGrpColumns, "", ""); - - if(c) - { - std::vector grps; - - locked_retrieveGroups(c, grps, withMeta ? mColGrp_WithMetaOffset : 0); - std::vector::iterator vit = grps.begin(); - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - resultCount = grps.size(); -#endif - - for(; vit != grps.end(); ++vit) - { - grp[(*vit)->grpId] = *vit; - } - - delete c; - } - - } - else - { - RsStackMutex stack(mDbMutex); - std::map::iterator mit = grp.begin(); - - std::list toRemove; - - for(; mit != grp.end(); ++mit) - { - const RsGxsGroupId& grpId = mit->first; - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, withMeta ? mGrpColumnsWithMeta : mGrpColumns, "grpId='" + grpId.toStdString() + "'", ""); - - if(c) - { - std::vector grps; - locked_retrieveGroups(c, grps, withMeta ? mColGrp_WithMetaOffset : 0); - - if(!grps.empty()) - { - RsNxsGrp* ng = grps.front(); - grp[ng->grpId] = ng; - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - ++resultCount; -#endif - }else{ - toRemove.push_back(grpId); - } - - delete c; - } - } - - std::list::iterator grpIdIt; - for (grpIdIt = toRemove.begin(); grpIdIt != toRemove.end(); ++grpIdIt) - { - grp.erase(*grpIdIt); - } - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - std::cerr << "RsDataService::retrieveNxsGrps() " << mDbName << ", Requests: " << requestedGroups << ", Results: " << resultCount << ", Time: " << timer.duration() << std::endl; -#endif - - return 1; -} - -void RsDataService::locked_retrieveGroups(RetroCursor* c, std::vector& grps, int metaOffset) -{ - if(c){ - bool valid = c->moveToFirst(); - - while(valid){ - RsNxsGrp* g = locked_getGroup(*c); - - // only add the latest grp info - if(g) - { - if (metaOffset) - g->metaData = new RsGxsGrpMetaData(*locked_getGrpMeta(*c, metaOffset)); - else - g->metaData = nullptr; - - grps.push_back(g); - } - valid = c->moveToNext(); - } - } -} - -int RsDataService::retrieveNxsMsgs(const GxsMsgReq &reqIds, GxsMsgResult &msg, bool withMeta) -{ -#ifdef RS_DATA_SERVICE_DEBUG_TIME - rstime::RsScopeTimer timer(""); - int resultCount = 0; -#endif - - for(auto mit = reqIds.begin(); mit != reqIds.end(); ++mit) - { - - const RsGxsGroupId& grpId = mit->first; - - // if vector empty then request all messages - const std::set& msgIdV = mit->second; - std::vector msgSet; - - if(msgIdV.empty()) - { - RS_STACK_MUTEX(mDbMutex); - - RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, withMeta ? mMsgColumnsWithMeta : mMsgColumns, KEY_GRP_ID+ "='" + grpId.toStdString() + "'", ""); - - if(c) - locked_retrieveMessages(c, msgSet, withMeta ? mColMsg_WithMetaOffset : 0); - - delete c; - } - else - { - RS_STACK_MUTEX(mDbMutex); - - // request each grp - for( std::set::const_iterator sit = msgIdV.begin(); - sit!=msgIdV.end();++sit ) - { - const RsGxsMessageId& msgId = *sit; - - RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, withMeta ? mMsgColumnsWithMeta : mMsgColumns, KEY_GRP_ID+ "='" + grpId.toStdString() - + "' AND " + KEY_MSG_ID + "='" + msgId.toStdString() + "'", ""); - - if(c) - { - locked_retrieveMessages(c, msgSet, withMeta ? mColMsg_WithMetaOffset : 0); - } - - delete c; - } - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - resultCount += msgSet.size(); -#endif - - msg[grpId] = msgSet; - - msgSet.clear(); - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - std::cerr << "RsDataService::retrieveNxsMsgs() " << mDbName << ", Requests: " << reqIds.size() << ", Results: " << resultCount << ", Time: " << timer.duration() << std::endl; -#endif - - return 1; -} - -void RsDataService::locked_retrieveMessages(RetroCursor *c, std::vector &msgs, int metaOffset) -{ - bool valid = c->moveToFirst(); - while(valid){ - RsNxsMsg* m = locked_getMessage(*c); - - if(m){ - if (metaOffset) - m->metaData = new RsGxsMsgMetaData(*locked_getMsgMeta(*c, metaOffset)); - else - m->metaData = nullptr; - - msgs.push_back(m); - } - - valid = c->moveToNext(); - } - return; -} - -int RsDataService::retrieveGxsMsgMetaData(const GxsMsgReq& reqIds, GxsMsgMetaResult& msgMeta) -{ - RsStackMutex stack(mDbMutex); - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - rstime::RsScopeTimer timer(""); - int resultCount = 0; -#endif - - for(auto mit(reqIds.begin()); mit != reqIds.end(); ++mit) - { - - const RsGxsGroupId& grpId = mit->first; - const std::set& msgIdV = mit->second; - - // if vector empty then request all messages - - // The pointer here is a trick to not initialize a new cache entry when cache is disabled, while keeping the unique variable all along. - t_MetaDataCache *cache(mUseCache? (&mMsgMetaDataCache[grpId]) : nullptr); - - if(msgIdV.empty()) - { - if(mUseCache && cache->isCacheUpToDate()) - cache->getFullMetaList(msgMeta[grpId]); - else - { - RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, mMsgMetaColumns, KEY_GRP_ID+ "='" + grpId.toStdString() + "'", ""); - - if (c) - { - locked_retrieveMsgMetaList(c, msgMeta[grpId]); - - if(mUseCache) - cache->setCacheUpToDate(true); - } - delete c; - } -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << mDbName << ": Retrieving (all) Msg metadata grpId=" << grpId << ", " << std::dec << metaSet.size() << " messages" << std::endl; -#endif - } - else - { - // request each msg meta - auto& metaSet(msgMeta[grpId]); - - for(auto sit(msgIdV.begin()); sit!=msgIdV.end(); ++sit) - { - const RsGxsMessageId& msgId = *sit; - - auto meta = mUseCache?cache->getMeta(msgId): (std::shared_ptr()); - - if(meta) - metaSet.push_back(meta); - else - { - RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, mMsgMetaColumns, KEY_GRP_ID+ "='" + grpId.toStdString() + "' AND " + KEY_MSG_ID + "='" + msgId.toStdString() + "'", ""); - - c->moveToFirst(); - auto meta = locked_getMsgMeta(*c, 0); - - if(meta) - { - metaSet.push_back(meta); - - if(mUseCache) - mMsgMetaDataCache[grpId].updateMeta(msgId,meta); - } - - delete c; - } - } -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << mDbName << ": Retrieving Msg metadata grpId=" << grpId << ", " << std::dec << metaSet.size() << " messages" << std::endl; -#endif - } - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - if(mDbName==std::string("gxsforums_db")) - std::cerr << "RsDataService::retrieveGxsMsgMetaData() " << mDbName << ", Requests: " << reqIds.size() << ", Results: " << resultCount << ", Time: " << timer.duration() << std::endl; -#endif - - return 1; -} - -void RsDataService::locked_retrieveGrpMetaList(RetroCursor *c, std::map >& grpMeta) -{ - if(!c) - { - RsErr() << __PRETTY_FUNCTION__ << ": attempt to retrieve Group Meta data from the DB with null cursor!" << std::endl; - return; - } - - bool valid = c->moveToFirst(); - - while(valid) - { - auto m = locked_getGrpMeta(*c, 0); - - if(m != nullptr) - grpMeta[m->mGroupId] = m; - - valid = c->moveToNext(); - } -} - -void RsDataService::locked_retrieveMsgMetaList(RetroCursor *c, std::vector >& msgMeta) -{ - if(!c) - { - RsErr() << __PRETTY_FUNCTION__ << ": attempt to retrieve Msg Meta data from the DB with null cursor!" << std::endl; - return; - } - - bool valid = c->moveToFirst(); - while(valid) - { - auto m = locked_getMsgMeta(*c, 0); - - if(m != nullptr) - msgMeta.push_back(m); - - valid = c->moveToNext(); - } -} - -int RsDataService::retrieveGxsGrpMetaData(std::map >& grp) -{ -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "RsDataService::retrieveGxsGrpMetaData()"; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(mDbMutex); - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - rstime::RsScopeTimer timer(""); - int resultCount = 0; - int requestedGroups = grp.size(); -#endif - - if(grp.empty()) - { - if(mUseCache && mGrpMetaDataCache.isCacheUpToDate()) // grab all the stash from the cache, so as to avoid decryption costs. - { -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << (void*)this << ": RsDataService::retrieveGxsGrpMetaData() retrieving all from cache!" << std::endl; -#endif - - mGrpMetaDataCache.getFullMetaList(grp) ; - } - else - { -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "RsDataService::retrieveGxsGrpMetaData() retrieving all" << std::endl; -#endif - // clear the cache - - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, mGrpMetaColumns, "", ""); - - if(c) - { - locked_retrieveGrpMetaList(c,grp); - - if(mUseCache) - mGrpMetaDataCache.setCacheUpToDate(true); - } - delete c; -#ifdef RS_DATA_SERVICE_DEBUG_TIME - resultCount += grp.size(); -#endif - - } - } - else - { - for(auto mit(grp.begin()); mit != grp.end(); ++mit) - { - auto meta = mUseCache?mGrpMetaDataCache.getMeta(mit->first): (std::shared_ptr()) ; - - if(meta) - mit->second = meta; - else - { -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << mDbName << ": Retrieving Grp metadata grpId=" << mit->first ; -#endif - - const RsGxsGroupId& grpId = mit->first; - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, mGrpMetaColumns, "grpId='" + grpId.toStdString() + "'", ""); - - c->moveToFirst(); - - auto meta = locked_getGrpMeta(*c, 0); - - if(meta) - { - mit->second = meta; - - if(mUseCache) - mGrpMetaDataCache.updateMeta(grpId,meta); - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - ++resultCount; -#endif - - delete c; - -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - else - std::cerr << ". not found!" << std::endl; -#endif - } - } - - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - std::cerr << "RsDataService::retrieveGxsGrpMetaData() " << mDbName << ", Requests: " << requestedGroups << ", Results: " << resultCount << ", Time: " << timer.duration() << std::endl; -#endif - - /* Remove not found entries as stated in the documentation */ - for(auto i = grp.begin(); i != grp.end();) - if(!i->second) i = grp.erase(i); - else ++i; - - return 1; -} - -int RsDataService::resetDataStore() -{ - -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "resetDataStore() " << std::endl; -#endif - - { - RsStackMutex stack(mDbMutex); - - mDb->execSQL("DROP INDEX " + MSG_INDEX_GRPID); - mDb->execSQL("DROP TABLE " + DATABASE_RELEASE_TABLE_NAME); - mDb->execSQL("DROP TABLE " + MSG_TABLE_NAME); - mDb->execSQL("DROP TABLE " + GRP_TABLE_NAME); - mDb->execSQL("DROP TRIGGER " + GRP_LAST_POST_UPDATE_TRIGGER); - } - - // recreate database - initialise(true); - - return 1; -} - -int RsDataService::updateGroupMetaData(const GrpLocMetaData& meta) -{ -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << (void*)this << ": Updating Grp Meta data: grpId = " << meta.grpId << std::endl; -#endif - - RsStackMutex stack(mDbMutex); - const RsGxsGroupId& grpId = meta.grpId; - -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << (void*)this << ": erasing old entry from cache." << std::endl; -#endif - - if( mDb->sqlUpdate(GRP_TABLE_NAME, KEY_GRP_ID+ "='" + grpId.toStdString() + "'", meta.val)) - { - // If we use the cache, update the meta data immediately. - - if(mUseCache) - { - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, mGrpMetaColumns, "grpId='" + grpId.toStdString() + "'", ""); - - c->moveToFirst(); - - // temporarily disable the cache so that we get the value from the DB itself. - mUseCache=false; - auto meta = locked_getGrpMeta(*c, 0); - mUseCache=true; - - if(meta) - mGrpMetaDataCache.updateMeta(grpId,meta); - - delete c; - } - - return 1; - } - return 0; -} - -int RsDataService::updateMessageMetaData(const MsgLocMetaData& metaData) -{ -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << (void*)this << ": Updating Msg Meta data: grpId = " << metaData.msgId.first << " msgId = " << metaData.msgId.second << std::endl; -#endif - - RsStackMutex stack(mDbMutex); - const RsGxsGroupId& grpId = metaData.msgId.first; - const RsGxsMessageId& msgId = metaData.msgId.second; - - if(mDb->sqlUpdate(MSG_TABLE_NAME, KEY_GRP_ID+ "='" + grpId.toStdString() + "' AND " + KEY_MSG_ID + "='" + msgId.toStdString() + "'", metaData.val) ) - { - // If we use the cache, update the meta data immediately. - - if(mUseCache) - { - RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, mMsgMetaColumns, KEY_GRP_ID+ "='" + grpId.toStdString() + "' AND " + KEY_MSG_ID + "='" + msgId.toStdString() + "'", ""); - - c->moveToFirst(); - - // temporarily disable the cache so that we get the value from the DB itself. - mUseCache=false; - auto meta = locked_getMsgMeta(*c, 0); - mUseCache=true; - - if(meta) - mMsgMetaDataCache[grpId].updateMeta(msgId,meta); - - delete c; - } - - return 1; - } - return 0; -} - -int RsDataService::removeMsgs(const GxsMsgReq& msgIds) -{ - RsStackMutex stack(mDbMutex); - - GxsMsgReq::const_iterator mit = msgIds.begin(); - - for(; mit != msgIds.end(); ++mit) - { - const std::set& msgIdV = mit->second; - const RsGxsGroupId& grpId = mit->first; - - // delete messages - GxsMsgReq msgsToDelete; - msgsToDelete[grpId] = msgIdV; - locked_removeMessageEntries(msgsToDelete); - } - - return 1; -} - -int RsDataService::removeGroups(const std::vector &grpIds) -{ - - RsStackMutex stack(mDbMutex); - - locked_removeGroupEntries(grpIds); - - return 1; -} - -int RsDataService::retrieveGroupIds(std::vector &grpIds) -{ - RsStackMutex stack(mDbMutex); - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - rstime::RsScopeTimer timer(""); - int resultCount = 0; -#endif - - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, mGrpIdColumn, "", ""); - - if(c) - { - bool valid = c->moveToFirst(); - - while(valid) - { - std::string grpId; - c->getString(mColGrpId_GrpId, grpId); - grpIds.push_back(RsGxsGroupId(grpId)); - valid = c->moveToNext(); - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - ++resultCount; -#endif - } - delete c; - }else - { - return 0; - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - std::cerr << "RsDataService::retrieveGroupIds() " << mDbName << ", Results: " << resultCount << ", Time: " << timer.duration() << std::endl; -#endif - - return 1; -} - -int RsDataService::retrieveMsgIds(const RsGxsGroupId& grpId, RsGxsMessageId::std_set& msgIds) -{ -#ifdef RS_DATA_SERVICE_DEBUG_TIME - rstime::RsScopeTimer timer(""); - int resultCount = 0; -#endif - - RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, mMsgIdColumn, KEY_GRP_ID+ "='" + grpId.toStdString() + "'", ""); - - if(c) - { - bool valid = c->moveToFirst(); - - while(valid) - { - std::string msgId; - c->getString(mColMsgId_MsgId, msgId); - - if(c->columnCount() != 1) - std::cerr << "(EE) ********* not retrieving all columns!!" << std::endl; - - msgIds.insert(RsGxsMessageId(msgId)); - valid = c->moveToNext(); - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - ++resultCount; -#endif - } - delete c; - }else - { - return 0; - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - std::cerr << "RsDataService::retrieveNxsGrps() " << mDbName << ", Results: " << resultCount << ", Time: " << timer.duration() << std::endl; -#endif - - return 1; - -} - -bool RsDataService::locked_removeMessageEntries(const GxsMsgReq& msgIds) -{ - // start a transaction - bool ret = mDb->beginTransaction(); - - GxsMsgReq::const_iterator mit = msgIds.begin(); - - for(; mit != msgIds.end(); ++mit) - { - const RsGxsGroupId& grpId = mit->first; - const std::set& msgsV = mit->second; - auto& cache(mMsgMetaDataCache[grpId]); - - for(auto& msgId:msgsV) - { - mDb->sqlDelete(MSG_TABLE_NAME, KEY_GRP_ID+ "='" + grpId.toStdString() + "' AND " + KEY_MSG_ID + "='" + msgId.toStdString() + "'", ""); - - cache.clear(msgId); - } - } - - ret &= mDb->commitTransaction(); - - return ret; -} - -bool RsDataService::locked_removeGroupEntries(const std::vector& grpIds) -{ - // start a transaction - bool ret = mDb->beginTransaction(); - - for(auto grpId:grpIds) - { - mDb->sqlDelete(GRP_TABLE_NAME, KEY_GRP_ID+ "='" + grpId.toStdString() + "'", ""); - - // also remove the group meta from cache. - mGrpMetaDataCache.clear(grpId) ; - } - - ret &= mDb->commitTransaction(); - return ret; -} - -uint32_t RsDataService::cacheSize() const { - return 0; -} - -int RsDataService::setCacheSize(uint32_t /* size */) -{ - return 0; -} - -void RsDataService::debug_printCacheSize() -{ - RS_STACK_MUTEX(mDbMutex); - - uint32_t nb_items; - uint64_t total_size; - - mGrpMetaDataCache.debug_computeSize(nb_items, total_size); - - RsDbg() << "[CACHE] Cache size: " << std::endl; - RsDbg() << "[CACHE] Groups: " << " total: " << nb_items << ", size: " << total_size << std::endl; - - nb_items = 0; - total_size = 0; - - for(auto& it:mMsgMetaDataCache) - { - uint32_t tmp_nb_items; - uint64_t tmp_total_size; - - it.second.debug_computeSize(tmp_nb_items, tmp_total_size); - - nb_items += tmp_nb_items; - total_size += tmp_total_size; - } - RsDbg() << "[CACHE] Msgs: " << " total: " << nb_items << ", size: " << total_size << std::endl; -} - - - - - - - - diff --git a/libretroshare/src/gxs/rsdataservice.h b/libretroshare/src/gxs/rsdataservice.h deleted file mode 100644 index e9554f04f..000000000 --- a/libretroshare/src/gxs/rsdataservice.h +++ /dev/null @@ -1,459 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxsdataservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2012 by Evi-Parker Christopher * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSDATASERVICE_H -#define RSDATASERVICE_H - -#include "gxs/rsgds.h" -#include "util/retrodb.h" - -class MsgUpdate -{ -public: - - //MsgUpdate(){} - //MsgUpdate(const MsgUpdate& ){}//hier müsste ein echter constructor sein - RsGxsMessageId msgId; - ContentValue cv; -}; - -template class t_MetaDataCache -{ -public: - t_MetaDataCache() - : mCache_ContainsAllMetas(false) - {} - virtual ~t_MetaDataCache() = default; - - bool isCacheUpToDate() const { return mCache_ContainsAllMetas ; } - void setCacheUpToDate(bool b) { mCache_ContainsAllMetas = b; } - - void getFullMetaList(std::map >& mp) const { mp = mMetas ; } - void getFullMetaList(std::vector >& mp) const { for(auto& m:mMetas) mp.push_back(m.second) ; } - - std::shared_ptr getMeta(const ID& id) - { - auto itt = mMetas.find(id); - - if(itt != mMetas.end()) - return itt->second ; - else - return nullptr; - } - - std::shared_ptr getOrCreateMeta(const ID& id) - { - auto it = mMetas.find(id) ; - - if(it != mMetas.end()) - { -#ifdef RS_DATA_SERVICE_DEBUG - RsDbg() << __PRETTY_FUNCTION__ << ": getting group meta " << grpId << " from cache." << std::endl; -#endif - return it->second ; - } - else - { -#ifdef RS_DATA_SERVICE_DEBUG - RsDbg() << __PRETTY_FUNCTION__ << ": group meta " << grpId << " not in cache. Loading it from DB..." << std::endl; -#endif - return (mMetas[id] = std::make_shared()); - } - } - - void updateMeta(const ID& id,const MetaDataClass& meta) - { - mMetas[id] = std::make_shared(meta); // create a new shared_ptr to possibly replace the previous one - } - - void updateMeta(const ID& id,const std::shared_ptr& meta) - { - mMetas[id] = meta; // create a new shared_ptr to possibly replace the previous one - } - - void clear(const ID& id) - { - auto it = mMetas.find(id) ; - - // We dont actually delete the item, because it might be used by a calling client. - // In this case, the memory will not be used for long, so we keep it into a list for a safe amount - // of time and delete it later. Using smart pointers here would be more elegant, but that would need - // to be implemented thread safe, which is difficult in this case. - - if(it != mMetas.end()) - { -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "(II) moving database cache entry " << (void*)(*it).second << " to dead list." << std::endl; -#endif - - mMetas.erase(it) ; - - // No need to modify mCache_ContainsAllMetas since, assuming that the cache always contains - // all possible elements from the DB, clearing one from the cache means that it is also deleted from the db, so - // the property is preserved. - } - } - - void debug_computeSize(uint32_t& nb_items, uint64_t& total_size) const - { - nb_items = mMetas.size(); - total_size = 0; - - for(auto it:mMetas) total_size += it.second->serial_size(); - } -private: - std::map > mMetas; - - static const uint32_t CACHE_ENTRY_GRACE_PERIOD = 600 ; // Unused items are deleted 10 minutes after last usage. - - bool mCache_ContainsAllMetas ; -}; - -class RsDataService : public RsGeneralDataService -{ -public: - - RsDataService(const std::string& serviceDir, const std::string& dbName, uint16_t serviceType, - RsGxsSearchModule* mod = NULL, const std::string& key = ""); - virtual ~RsDataService(); - - /*! - * Retrieves all msgs - * @param reqIds requested msg ids (grpId,msgId), leave msg list empty to get all msgs for the grp - * @param msg result of msg retrieval - * @param withMeta true will also retrieve metadata - * @return error code - */ - int retrieveNxsMsgs(const GxsMsgReq& reqIds, GxsMsgResult& msg, bool withMeta = false) override; - - /*! - * Retrieves groups, if empty, retrieves all grps, if map is not empty - * only retrieve entries, if entry cannot be found, it is removed from map - * @param grp retrieved groups - * @param withMeta this initialise the metaData member of the nxsgroups retrieved - * @return error code - */ - int retrieveNxsGrps(std::map& grp, bool withMeta) override; - - /*! - * Retrieves meta data of all groups stored (most current versions only) - * @param grp output group meta data - * @return error code - */ - int retrieveGxsGrpMetaData(std::map > &grp) override; - - /*! - * Retrieves meta data of all groups stored (most current versions only) - * @param grpIds grpIds for which to retrieve meta data - * @param msgMeta meta data result as map of grpIds to array of metadata for that grpId - * @return error code - */ - int retrieveGxsMsgMetaData(const GxsMsgReq& reqIds, GxsMsgMetaResult& msgMeta) override; - - /*! - * remove msgs in data store - * @param grpId group Id of message to be removed - * @param msgIds ids of messages to be removed - * @return error code - */ - int removeMsgs(const GxsMsgReq& msgIds) override; - - /*! - * remove groups in data store listed in grpIds param - * @param grpIds ids of groups to be removed - * @return error code - */ - int removeGroups(const std::vector& grpIds) override; - - /*! - * Retrieves all group ids in store - * @param grpIds all grpids in store is inserted into this vector - * @return error code - */ - int retrieveGroupIds(std::vector &grpIds) override; - - /*! - * Retrives all msg ids in store - * @param grpId groupId of message ids to retrieve - * @param msgId msgsids retrieved - * @return error code - */ - int retrieveMsgIds(const RsGxsGroupId& grpId, RsGxsMessageId::std_set& msgId) override; - - /*! - * @return the cache size set for this RsGeneralDataService in bytes - */ - uint32_t cacheSize() const override; - - /*! - * \brief serviceType - * \return - * The service type for the current data service. - */ - virtual uint16_t serviceType() const override { return mServType; } - - /*! - * @param size size of cache to set in bytes - */ - int setCacheSize(uint32_t size) override; - - /*! - * Stores a list of signed messages into data store - * @param msg map of message and decoded meta data information - * @return error code - */ - int storeMessage(const std::list& msg) override; - - /*! - * Stores a list of groups in data store - * @param grp map of group and decoded meta data - * @return error code - */ - int storeGroup(const std::list& grp) override; - - /*! - * Updates group entries in Db - * @param grp map of group and decoded meta data - * @return error code - */ - int updateGroup(const std::list& grsp) override; - - /*! - * @param metaData The meta data item to update - * @return error code - */ - int updateMessageMetaData(const MsgLocMetaData& metaData) override; - - /*! - * @param metaData The meta data item to update - * @return error code - */ - int updateGroupMetaData(const GrpLocMetaData &meta) override; - - /*! - * Completely clear out data stored in - * and returns this to a state - * as it was when first constructed - * @return error code - */ - int resetDataStore() override; - - bool validSize(RsNxsMsg* msg) const override; - bool validSize(RsNxsGrp* grp) const override; - - /*! - * Convenience function used to only update group keys. This is used when sending - * publish keys between peers. - * @return SQL error code - */ - - int updateGroupKeys(const RsGxsGroupId& grpId,const RsTlvSecurityKeySet& keys, uint32_t subscribe_flags) override; - - void debug_printCacheSize() ; - -private: - - /*! - * Retrieves all the msg results from a cursor - * @param c cursor to result set - * @param msgs messages retrieved from cursor are stored here - */ - void locked_retrieveMessages(RetroCursor* c, std::vector& msgs, int metaOffset); - - /*! - * Retrieves all the grp results from a cursor - * @param c cursor to result set - * @param grps groups retrieved from cursor are stored here - * @param withMeta this initialise the metaData member of the nxsgroups retrieved - */ - void locked_retrieveGroups(RetroCursor* c, std::vector& grps, int metaOffset); - - /*! - * Retrieves all the msg meta results from a cursor - * @param c cursor to result set - * @param msgMeta message metadata retrieved from cursor are stored here - */ - void locked_retrieveMsgMetaList(RetroCursor* c, std::vector > &msgMeta); - - /*! - * Retrieves all the grp meta results from a cursor - * @param c cursor to result set - * @param grpMeta group metadata retrieved from cursor are stored here - */ - void locked_retrieveGrpMetaList(RetroCursor *c, std::map > &grpMeta); - - /*! - * extracts a msg meta item from a cursor at its - * current position - */ - std::shared_ptr locked_getMsgMeta(RetroCursor& c, int colOffset); - - /*! - * extracts a grp meta item from a cursor at its - * current position - */ - std::shared_ptr locked_getGrpMeta(RetroCursor& c, int colOffset); - - /*! - * extracts a msg item from a cursor at its - * current position - */ - RsNxsMsg* locked_getMessage(RetroCursor& c); - - /*! - * extracts a grp item from a cursor at its - * current position - */ - RsNxsGrp* locked_getGroup(RetroCursor& c); - - /*! - * Creates an sql database and its associated file - * also creates the message and groups table - * @param isNewDatabase is new database - */ - void initialise(bool isNewDatabase); - - /*! - * Remove entries for data base - * @param msgIds - */ - bool locked_removeMessageEntries(const GxsMsgReq& msgIds); - bool locked_removeGroupEntries(const std::vector& grpIds); - -private: - /*! - * Start release update - * @param release - * @return true/false - */ - bool startReleaseUpdate(int release); - - /*! - * Finish release update - * @param release - * @param result - * @return true/false - */ - bool finishReleaseUpdate(int release, bool result); - -private: - - RsMutex mDbMutex; - - std::list mMsgColumns; - std::list mMsgMetaColumns; - std::list mMsgColumnsWithMeta; - std::list mMsgIdColumn; - - std::list mGrpColumns; - std::list mGrpMetaColumns; - std::list mGrpColumnsWithMeta; - std::list mGrpIdColumn; - - // Message meta column - int mColMsgMeta_GrpId; - int mColMsgMeta_TimeStamp; - int mColMsgMeta_NxsFlags; - int mColMsgMeta_SignSet; - int mColMsgMeta_NxsIdentity; - int mColMsgMeta_NxsHash; - int mColMsgMeta_MsgId; - int mColMsgMeta_OrigMsgId; - int mColMsgMeta_MsgStatus; - int mColMsgMeta_ChildTs; - int mColMsgMeta_MsgParentId; - int mColMsgMeta_MsgThreadId; - int mColMsgMeta_Name; - int mColMsgMeta_NxsServString; - int mColMsgMeta_RecvTs; - int mColMsgMeta_NxsDataLen; - - // Message columns - int mColMsg_GrpId; - int mColMsg_NxsData; - int mColMsg_MetaData; - int mColMsg_MsgId; - - // Message columns with meta - int mColMsg_WithMetaOffset; - - // Group meta columns - int mColGrpMeta_GrpId; - int mColGrpMeta_TimeStamp; - int mColGrpMeta_NxsFlags; -// int mColGrpMeta_SignSet; - int mColGrpMeta_NxsIdentity; - int mColGrpMeta_NxsHash; - int mColGrpMeta_KeySet; - int mColGrpMeta_SubscrFlag; - int mColGrpMeta_Pop; - int mColGrpMeta_MsgCount; - int mColGrpMeta_Status; - int mColGrpMeta_Name; - int mColGrpMeta_LastPost; - int mColGrpMeta_OrigGrpId; - int mColGrpMeta_ServString; - int mColGrpMeta_SignFlags; - int mColGrpMeta_CircleId; - int mColGrpMeta_CircleType; - int mColGrpMeta_InternCircle; - int mColGrpMeta_Originator; - int mColGrpMeta_AuthenFlags; - int mColGrpMeta_ParentGrpId; - int mColGrpMeta_RecvTs; - int mColGrpMeta_RepCutoff; - int mColGrpMeta_NxsDataLen; - - // Group columns - int mColGrp_GrpId; - int mColGrp_NxsData; - int mColGrp_MetaData; - - // Group columns with meta - int mColGrp_WithMetaOffset; - - // Group id columns - int mColGrpId_GrpId; - - // Msg id columns - int mColMsgId_MsgId; - - std::string mServiceDir; - std::string mDbName; - std::string mDbPath; - uint16_t mServType; - - RetroDb* mDb; - - // used to store metadata instead of reading it from the database. - // The boolean variable below is also used to force re-reading when - // the entre list of grp metadata is requested (which happens quite often) - - void locked_clearGrpMetaCache(const RsGxsGroupId& gid); - void locked_updateGrpMetaCache(const RsGxsGrpMetaData& meta); - - t_MetaDataCache mGrpMetaDataCache; - std::map > mMsgMetaDataCache; - - bool mUseCache; -}; - -#endif // RSDATASERVICE_H diff --git a/libretroshare/src/gxs/rsgds.h b/libretroshare/src/gxs/rsgds.h deleted file mode 100644 index f4a3b0229..000000000 --- a/libretroshare/src/gxs/rsgds.h +++ /dev/null @@ -1,278 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgds.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie, Evi-Parker Christopher * - * * - * 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 . * - * * - *******************************************************************************/ - -#pragma once - -#include -#include -#include - -#include "inttypes.h" - -#include "rsitems/rsgxsitems.h" -#include "rsitems/rsnxsitems.h" -#include "gxs/rsgxsdata.h" -#include "rsgxs.h" -#include "rsgxsutil.h" -#include "util/contentvalue.h" - -class RsGxsSearchModule { - -public: - - virtual ~RsGxsSearchModule(); - - -}; - -/*! - * This allows modification of local - * meta data items of a message - */ -struct MsgLocMetaData { - MsgLocMetaData() = default; - MsgLocMetaData(const MsgLocMetaData& meta): msgId(meta.msgId), val(meta.val) {} - - RsGxsGrpMsgIdPair msgId; - ContentValue val; -}; - -/*! - * This allows modification of local - * meta data items of a group - */ -struct GrpLocMetaData { - GrpLocMetaData() = default; - GrpLocMetaData(const GrpLocMetaData& meta): grpId(meta.grpId), val(meta.val) {} - - RsGxsGroupId grpId; - ContentValue val; -}; - -/*! - * This is used to query network statistics for a given group. This is useful - * to e.g. show group popularity, or number of visible messages for unsubscribed - * group. - */ -struct RsGroupNetworkStats -{ - RsGroupNetworkStats() : - mSuppliers(0), mMaxVisibleCount(0), mGrpAutoSync(false), - mAllowMsgSync(false), mLastGroupModificationTS(0) {} - - uint32_t mSuppliers; - uint32_t mMaxVisibleCount; - bool mGrpAutoSync; - bool mAllowMsgSync; - rstime_t mLastGroupModificationTS; -}; - -typedef std::map > NxsMsgDataResult; -typedef std::map > NxsMsgRelatedDataResult; -typedef std::map > GxsMsgResult; // - -/*! - * The main role of GDS is the preparation and handing out of messages requested from - * RsGeneralExchangeService and RsGeneralExchangeService - * It is important to note that no actual messages are passed by this interface as its is expected - * architecturally to pass messages to the service via a call back - * - * It also acts as a layer between RsGeneralStorageService and its parent RsGeneralExchangeService - * thus allowing for non-blocking requests, etc. - * It also provides caching ability - * - * - * Caching feature: - * - A cache index should be maintained which is faster than normal message request - * - This should allow fast retrieval of message based on grp id or msg id - * - * Identity Exchange Service: - * - As this is the point where data is accessed by both the GNP and GXS the identities - * used to decrypt, encrypt and verify is handle here. - * - * Please note all function are blocking. - */ -class RsGeneralDataService -{ - -public: - - static const uint32_t GXS_MAX_ITEM_SIZE; - - static const std::string MSG_META_SERV_STRING; - static const std::string MSG_META_STATUS; - - static const std::string GRP_META_SUBSCRIBE_FLAG; - static const std::string GRP_META_STATUS; - static const std::string GRP_META_SERV_STRING; - static const std::string GRP_META_CUTOFF_LEVEL; - -public: - - typedef std::map GrpStoreMap; - typedef std::map MsgStoreMap; - - RsGeneralDataService(){} - virtual ~RsGeneralDataService(){} - - /*! - * Retrieves all msgs - * @param reqIds requested msg ids (grpId,msgId), leave msg list empty to get all msgs for the grp - * @param msg result of msg retrieval - * @param cache whether to store results of this retrieval in memory for faster later retrieval - * @param strictFilter if true do not request any message if reqIds is empty - * @return error code - */ - virtual int retrieveNxsMsgs( const GxsMsgReq& reqIds, GxsMsgResult& msg, bool withMeta = false ) = 0; - - /*! - * Retrieves all groups stored. Caller owns the memory and is supposed to delete the RsNxsGrp pointers after use. - * @param grp retrieved groups - * @param withMeta if true the meta handle of nxs grps is intitialised - * @param cache whether to store retrieval in mem for faster later retrieval - * @return error code - */ - virtual int retrieveNxsGrps(std::map& grp, bool withMeta) = 0; - - /*! - * Retrieves meta data of all groups stored (most current versions only) - * Memory is owned by the service, not the caller. Therefore the pointers in the temporary map - * shouldn't be destroyed. - * - * @param grp if null grpIds entries are made, only meta for those grpId are retrieved \n - * , if grpId is failed to be retrieved it will be erased from map - * @return error code - */ - virtual int retrieveGxsGrpMetaData(std::map >& grp) = 0; - - /*! - * Retrieves meta data of all groups stored (most current versions only) - * @param grpIds grpIds for which to retrieve meta data - * @param msgMeta meta data result as map of grpIds to array of metadata for that grpId - * @return error code - */ - virtual int retrieveGxsMsgMetaData(const GxsMsgReq& msgIds, GxsMsgMetaResult& msgMeta) = 0; - - /*! - * remove msgs in data store listed in msgIds param - * @param msgIds ids of messages to be removed - * @return error code - */ - virtual int removeMsgs(const GxsMsgReq& msgIds) = 0; - - /*! - * remove groups in data store listed in grpIds param - * @param grpIds ids of groups to be removed - * @return error code - */ - virtual int removeGroups(const std::vector& grpIds) = 0; - - /*! - * Retrieves all group ids in store - * @param grpIds all grpids in store is inserted into this vector - * @return error code - */ - virtual int retrieveGroupIds(std::vector& grpIds) = 0; - - /*! - * Retrives all msg ids in store - * @param grpId groupId of message ids to retrieve - * @param msgId msgsids retrieved - * @return error code - */ - virtual int retrieveMsgIds(const RsGxsGroupId& grpId, RsGxsMessageId::std_set& msgId) = 0; - - /*! - * @return the cache size set for this RsGeneralDataService in bytes - */ - virtual uint32_t cacheSize() const = 0; - - /*! - * \brief serviceType - * \return - * The service type for the current data service. - */ - virtual uint16_t serviceType() const = 0 ; - - /*! - * @param size size of cache to set in bytes - */ - virtual int setCacheSize(uint32_t size) = 0; - - /*! - * Stores a list of signed messages into data store - * @param msg map of message and decoded meta data information - * @return error code - */ - virtual int storeMessage(const std::list& msgs) = 0; - - /*! - * Stores a list of groups in data store - * @param grp map of group and decoded meta data - * @return error code - */ - virtual int storeGroup(const std::list& grsp) = 0; - - - /*! - * Updates group entries in Db - * @param grp map of group and decoded meta data - * @return error code - */ - virtual int updateGroup(const std::list& grsp) = 0; - - /*! - * @param metaData - */ - virtual int updateMessageMetaData(const MsgLocMetaData& metaData) = 0; - - /*! - * @param metaData - */ - virtual int updateGroupMetaData(const GrpLocMetaData& meta) = 0; - - virtual int updateGroupKeys(const RsGxsGroupId& grpId,const RsTlvSecurityKeySet& keys,uint32_t subscribed_flags) = 0 ; - - /*! - * Completely clear out data stored in - * and returns this to a state - * as it was when first constructed - */ - virtual int resetDataStore() = 0; - - /*! - * Use to determine if message isn't over the storage - * limit for a single message item - * @param msg the message to check size validity - * @return whether the size of of msg is valid - */ - virtual bool validSize(RsNxsMsg* msg) const = 0 ; - - /*! - * Use to determine if group isn't over the storage limit - * for a single group item - * @param grp the group to check size validity - * @return whether the size of grp is valid for storage - */ - virtual bool validSize(RsNxsGrp* grp) const = 0 ; - -}; diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc deleted file mode 100644 index 5ddb0be26..000000000 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ /dev/null @@ -1,3739 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgenexchange.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Christopher Evi-Parker * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#include -#include - -#include "pqi/pqihash.h" -#include "rsgenexchange.h" -#include "gxssecurity.h" -#include "util/contentvalue.h" -#include "util/rsprint.h" -#include "util/rstime.h" -#include "retroshare/rsgxsflags.h" -#include "retroshare/rsgxscircles.h" -#include "retroshare/rsgrouter.h" -#include "retroshare/rsidentity.h" -#include "retroshare/rspeers.h" -#include "rsitems/rsnxsitems.h" -#include "rsgixs.h" -#include "rsgxsutil.h" -#include "rsserver/p3face.h" -#include "retroshare/rsevents.h" -#include "util/radix64.h" - -#define PUB_GRP_MASK 0x000f -#define RESTR_GRP_MASK 0x00f0 -#define PRIV_GRP_MASK 0x0f00 -#define GRP_OPTIONS_MASK 0xf000 - -#define PUB_GRP_OFFSET 0 -#define RESTR_GRP_OFFSET 8 -#define PRIV_GRP_OFFSET 16 -#define GRP_OPTIONS_OFFSET 24 - -// Authentication key indices. Used to store them in a map -// these where originally flags, but used as indexes. Still, we need -// to keep their old values to ensure backward compatibility. - -static const uint32_t INDEX_AUTHEN_IDENTITY = 0x00000010; // identity -static const uint32_t INDEX_AUTHEN_PUBLISH = 0x00000020; // publish key -static const uint32_t INDEX_AUTHEN_ADMIN = 0x00000040; // admin key - -static const uint32_t MSG_CLEANUP_PERIOD = 60*59; // 59 minutes -static const uint32_t INTEGRITY_CHECK_PERIOD = 60*31; // 31 minutes - -#define GXS_MASK "GXS_MASK_HACK" - -/* - * #define GEN_EXCH_DEBUG 1 - */ - -#if defined(GEN_EXCH_DEBUG) -static const uint32_t service_to_print = RS_SERVICE_GXS_TYPE_FORUMS;// use this to allow to this service id only, or 0 for all services - // warning. Numbers should be SERVICE IDS (see serialiser/rsserviceids.h. E.g. 0x0215 for forums) -class nullstream: public std::ostream {}; - -// static std::string nice_time_stamp(rstime_t now,rstime_t TS) -// { -// if(TS == 0) -// return "Never" ; -// else -// { -// std::ostringstream s; -// s << now - TS << " secs ago" ; -// return s.str() ; -// } -// } - -static std::ostream& gxsgenexchangedebug(uint32_t service_type) -{ - static nullstream null ; - - if (service_to_print==0 || service_type == 0 || (service_type == service_to_print)) - return std::cerr << time(NULL) << ":RSGENEXCHANGE service " << std::hex << service_type << std::dec << ": " ; - else - return null ; -} - -#define GXSGENEXCHANGEDEBUG gxsgenexchangedebug(serviceType()) - -#endif - -// Data flow in RsGenExchange -// -// publishGroup() -// | -// +--- stores in mGrpsToPublish -// -// updateGroup() -// | -// +--- stores in mGroupUpdatePublish -// -// tick() -// | -// +--- processRecvdData(); -// | | -// | +-- processRecvdGroups(); -// | | | -// | | +---- mGroupPendingValidate -// | | | -// | | +---- acceptance => validateGrp() => check existance => store in mGroupUpdates -// | | | -// | | +--- validateNxsGrp() -// | | -// | +-- processRecvdMessages(); -// | | -// | +-- performUpdateValidation(); // validates group updates in mGroupUpdates received from friends -// | | -// | +---- mGroupUpdates => updateValid() => store new groups -// | | | -// | | +--- stamp keys, check admin keys are the same, validateNxsGrp() -// | | | -// | +---- stores RsGxsGroupChange in mNotifications +--- data signature check -// | -// +--- publishGrps(); // creates signatures and data for locally created groups -// | | -// | +-- reads mGrpsToPublish, creates the group, clears mGrpsToPublish -// | | -// | +--- generateGroupKeys() -// | | -// | +--- serviceCreateGroup() -// | | -// | +--- createGroup() -// | | -// | +--- createGroupSignatures() -// | -// +--- processGroupUpdatePublish(); // goes through list of group updates to perform locally -// | | -// | +-- reads/deletes mGroupUpdatePublish, stores in mGrpsToPublish -// | -// +--- processGrpMetaChanges(); -// | | -// | +-- updates mNotifications, calls mDataAccess -// | -// +--- processGroupDelete(); -// | -// +--- publishMsgs(); -// | -// +--- processMsgMetaChanges(); -// | | -// | +-- updates mNotifications, calls mDataAccess -// | -// +--- processMessageDelete(); -// | -// +--- mDataAccess->processRequests(); -// | -// +--- processRoutingClues() ; -// - -RsGenExchange::RsGenExchange( - RsGeneralDataService* gds, RsNetworkExchangeService* ns, - RsSerialType* serviceSerialiser, uint16_t servType, RsGixs* gixs, - uint32_t authenPolicy ) : - mGenMtx("GenExchange"), - mDataStore(gds), - mNetService(ns), - mSerialiser(serviceSerialiser), - mServType(servType), - mGixs(gixs), - mAuthenPolicy(authenPolicy), - mCleaning(false), - mLastClean((int)time(NULL) - (int)(RSRandom::random_u32() % MSG_CLEANUP_PERIOD)), // this helps unsynchronising the checks for the different services - mChecking(false), - mCheckStarted(false), - mLastCheck((int)time(NULL) - (int)(RSRandom::random_u32() % INTEGRITY_CHECK_PERIOD) + 120), // this helps unsynchronising the checks for the different services, with 2 min security to avoid checking right away before statistics come up. - mIntegrityCheck(NULL), - SIGN_MAX_WAITING_TIME(60), - SIGN_FAIL(0), - SIGN_SUCCESS(1), - SIGN_FAIL_TRY_LATER(2), - VALIDATE_FAIL(0), - VALIDATE_SUCCESS(1), - VALIDATE_FAIL_TRY_LATER(2), - VALIDATE_MAX_WAITING_TIME(60) -{ - mDataAccess = new RsGxsDataAccess(gds); - - // Perform an early checking/cleaning of the db. Will eliminate groups and messages that do not match their hash - -#ifdef RS_DEEP_CHANNEL_INDEX - // This code is only called because it of deep indexing in channels. But loading - // the entire set of messages in order to provide indexing is pretty bad (very costly and slowly - // eats memory, as many tests have shown. Not because of leaks, but because new threads are - // apparently attributed large stacks and pages of memory are not regained by the system maybe because it thinks - // that RS will use them again. - // - // * the deep check should be implemented differently, in an incremental way. For instance in notifyChanges() of each - // service (e.g. channels here) should update the index when a new message is received. The question to how old messages - // are processed is open. I believe that they shouldn't. New users will progressively process them. - // - // * integrity check (re-hashing of message data) is not needed. Message signature already ensures that all messages received are - // unalterated. The only problem (possibly very rare) is that a message is locally corrupted and not deleted (because of no check). - // It will therefore never be replaced by the correct one from friends. The cost of re-hashing the whole db data regularly - // doesn't counterbalance such a low risk. - // - if(mServType == RS_SERVICE_GXS_TYPE_CHANNELS) - { - std::vector grpsToDel; - GxsMsgReq msgsToDel; - - RsGxsSinglePassIntegrityCheck::check(mServType,mGixs,mDataStore, - this, *mSerialiser, - grpsToDel,msgsToDel); - - for(auto& grpId: grpsToDel) - { - uint32_t token2=0; - deleteGroup(token2,grpId); - } - - if(!msgsToDel.empty()) - { - uint32_t token1=0; - deleteMsgs(token1,msgsToDel); - } - } -#endif -} - -void RsGenExchange::setNetworkExchangeService(RsNetworkExchangeService *ns) -{ - if(mNetService != NULL) - std::cerr << "(EE) Cannot override existing network exchange service. Make sure it has been deleted otherwise." << std::endl; - else - mNetService = ns ; -} - -RsGenExchange::~RsGenExchange() -{ - // need to destruct in a certain order (bad thing, TODO: put down instance ownership rules!) - delete mNetService; - - delete mDataAccess; - mDataAccess = NULL; - - delete mDataStore; - mDataStore = NULL; - - for(uint32_t i=0;igetGroupServerUpdateTS(gid,grp_server_update_TS,msg_server_update_TS) ; -} - -void RsGenExchange::threadTick() -{ - static const double timeDelta = 0.1; // slow tick in sec - - tick(); - rstime::rs_usleep((int) (timeDelta * 1000 *1000)); // timeDelta sec -} - -void RsGenExchange::tick() -{ - // Meta Changes should happen first. - // This is important, as services want to change Meta, then get results. - // Services shouldn't rely on this ordering - but some do. - processGrpMetaChanges(); - processMsgMetaChanges(); - - mDataAccess->processRequests(); - - publishGrps(); - - publishMsgs(); - - processGroupUpdatePublish(); - - processGroupDelete(); - processMessageDelete(); - - processRecvdData(); - - processRoutingClues() ; - - { - std::vector mNotifications_copy; - - // make a non-deep copy of mNotifications so that it can be passed off-mutex to notifyChanged() - // that will delete it. The potential high cost of notifyChanges() makes it preferable to call off-mutex. - { - RS_STACK_MUTEX(mGenMtx); - if(!mNotifications.empty()) - { - mNotifications_copy = mNotifications; - mNotifications.clear(); - } - } - - // Calling notifyChanges() calls back RsGxsIfaceHelper::receiveChanges() that deletes the pointers in the array - // and the array itself. This is pretty bad and we should normally delete the changes here. - - if(!mNotifications_copy.empty()) - notifyChanges(mNotifications_copy); - } - - // implemented service tick function - service_tick(); - - rstime_t now = time(NULL); - - // Cleanup unused data. This is only needed when auto-synchronization is needed, which is not the case - // of identities. This is why idendities do their own cleaning. - now = time(NULL); - - if( (mNetService && (mNetService->msgAutoSync() || mNetService->grpAutoSync())) && (mLastClean + MSG_CLEANUP_PERIOD < now) ) - { - GxsMsgReq msgs_to_delete; - std::vector grps_to_delete; - - RsGxsCleanUp(mDataStore,this,1).clean(mNextGroupToCheck,grps_to_delete,msgs_to_delete); // no need to lock here, because all access below (RsGenExchange, RsDataStore) are properly mutexed - - uint32_t token1=0; - deleteMsgs(token1,msgs_to_delete); - - for(auto& grpId: grps_to_delete) - { - uint32_t token2=0; - deleteGroup(token2,grpId); - } - - RS_STACK_MUTEX(mGenMtx) ; - mLastClean = now; - } - - if(mChecking || (mLastCheck + INTEGRITY_CHECK_PERIOD < now)) - { - mLastCheck = time(NULL); - - { - RS_STACK_MUTEX(mGenMtx) ; - - if(!mIntegrityCheck) - { - mIntegrityCheck = new RsGxsIntegrityCheck( mDataStore, this, - *mSerialiser, mGixs); - mIntegrityCheck->start("gxs integrity"); - mChecking = true; - } - } - - if(mIntegrityCheck->isDone()) - { - std::vector grpIds; - GxsMsgReq msgIds; - - { - RS_STACK_MUTEX(mGenMtx) ; - mIntegrityCheck->getDeletedIds(grpIds, msgIds); - } - - if(!msgIds.empty()) - { - uint32_t token1=0; - deleteMsgs(token1,msgIds); - } - - if(!grpIds.empty()) - for(auto& grpId: grpIds) - { - uint32_t token2=0; - deleteGroup(token2,grpId); - } - - { - RS_STACK_MUTEX(mGenMtx) ; - delete mIntegrityCheck; - mIntegrityCheck = NULL; - mChecking = false; - } - } - } -} - -bool RsGenExchange::messagePublicationTest(const RsGxsMsgMetaData& meta) -{ - if(!mNetService) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "(EE) No network service in service " << std::hex << serviceType() << std::dec << ": cannot read message storage time." << std::endl; -#endif - return false ; - } - - uint32_t st = mNetService->getKeepAge(meta.mGroupId); - - rstime_t storageTimeLimit = meta.mPublishTs + st; - - return meta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_KEEP_FOREVER || st == 0 || storageTimeLimit >= time(NULL); -} - -bool RsGenExchange::acknowledgeTokenMsg(const uint32_t& token, RsGxsGrpMsgIdPair& msgId) -{ - RS_STACK_MUTEX(mGenMtx) ; - -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "RsGenExchange::acknowledgeTokenMsg(). token=" << token << std::endl; -#endif - std::map::iterator mit = mMsgNotify.find(token); - - if(mit == mMsgNotify.end()) - { -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << " no notification found for this token." << std::endl; -#endif - return false; - } - - - msgId = mit->second; - - // no dump token as client has ackowledged its completion - mDataAccess->disposeOfPublicToken(token); - mMsgNotify.erase(mit); - -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << " found grpId=" << msgId.first <<", msgId=" << msgId.second << " disposing token from mDataAccess" << std::endl; -#endif - return true; -} - - - -bool RsGenExchange::acknowledgeTokenGrp(const uint32_t& token, RsGxsGroupId& grpId) -{ - RS_STACK_MUTEX(mGenMtx) ; - -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "RsGenExchange::acknowledgeTokenGrp(). token=" << token << std::endl; -#endif - std::map::iterator mit = mGrpNotify.find(token); - - if(mit == mGrpNotify.end()) - { -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << " no notification found for this token." << std::endl; -#endif - return false; - } - - grpId = mit->second; - - // no dump token as client has ackowledged its completion - mDataAccess->disposeOfPublicToken(token); - mGrpNotify.erase(mit); - -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << " found grpId=" << grpId << ". Disposing token from mDataAccess" << std::endl; -#endif - return true; -} - -void RsGenExchange::generateGroupKeys(RsTlvSecurityKeySet& keySet, bool genPublishKeys) -{ - /* create Keys */ - RsTlvPublicRSAKey pubAdminKey ; - RsTlvPrivateRSAKey privAdminKey; - - GxsSecurity::generateKeyPair(pubAdminKey,privAdminKey) ; - - // for now all public - pubAdminKey.keyFlags |= RSTLV_KEY_DISTRIB_ADMIN ; - privAdminKey.keyFlags |= RSTLV_KEY_DISTRIB_ADMIN ; - - keySet.public_keys[pubAdminKey.keyId] = pubAdminKey; - keySet.private_keys[privAdminKey.keyId] = privAdminKey; - - if(genPublishKeys) - { - /* set publish keys */ - RsTlvPublicRSAKey pubPublishKey ; - RsTlvPrivateRSAKey privPublishKey; - - GxsSecurity::generateKeyPair(pubPublishKey,privPublishKey) ; - - // for now all public - pubPublishKey.keyFlags |= RSTLV_KEY_DISTRIB_PUBLISH ; - privPublishKey.keyFlags |= RSTLV_KEY_DISTRIB_PUBLISH ; - - keySet.public_keys[pubPublishKey.keyId] = pubPublishKey; - keySet.private_keys[privPublishKey.keyId] = privPublishKey; - } -} - -uint8_t RsGenExchange::createGroup(RsNxsGrp *grp, RsTlvSecurityKeySet& keySet) -{ -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "RsGenExchange::createGroup()"<< std::endl; -#endif - - RsGxsGrpMetaData* meta = grp->metaData; - - /* add public admin and publish keys to grp */ - - // find private admin key - RsTlvPrivateRSAKey privAdminKey; - bool privKeyFound = false; // private admin key - - for( std::map::iterator mit = keySet.private_keys.begin(); mit != keySet.private_keys.end(); ++mit) - { - RsTlvPrivateRSAKey& key = mit->second; - - if((key.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) && (key.keyFlags & RSTLV_KEY_TYPE_FULL)) - { - privAdminKey = key; - privKeyFound = true; - break ; - } - } - - if(!privKeyFound) - { - std::cerr << "RsGenExchange::createGroup() Missing private ADMIN Key" << std::endl; - - return false; - } - - // only public keys are included to be transported. The 2nd line below is very important. - - meta->keys = keySet; - meta->keys.private_keys.clear() ; - - // group is self signing - // for the creation of group signature - // only public admin and publish keys are present in meta - uint32_t metaDataLen = meta->serial_size(RS_GXS_GRP_META_DATA_CURRENT_API_VERSION); - uint32_t allGrpDataLen = metaDataLen + grp->grp.bin_len; - - char* metaData = new char[metaDataLen]; - char* allGrpData = new char[allGrpDataLen]; // msgData + metaData - - meta->serialise(metaData, metaDataLen,RS_GXS_GRP_META_DATA_CURRENT_API_VERSION); - - // copy msg data and meta in allMsgData buffer - memcpy(allGrpData, grp->grp.bin_data, grp->grp.bin_len); - memcpy(allGrpData+(grp->grp.bin_len), metaData, metaDataLen); - - RsTlvKeySignature adminSign; - bool ok = GxsSecurity::getSignature(allGrpData, allGrpDataLen, privAdminKey, adminSign); - - // add admin sign to grpMeta - meta->signSet.keySignSet[INDEX_AUTHEN_ADMIN] = adminSign; - - RsTlvBinaryData grpData(mServType); - grpData.setBinData(allGrpData, allGrpDataLen); - - uint8_t ret = createGroupSignatures(meta->signSet, grpData, *(grp->metaData)); - - // clean up - delete[] allGrpData; - delete[] metaData; - - if (!ok) - { - std::cerr << "RsGenExchange::createGroup() ERROR !okay (getSignature error)" << std::endl; - return CREATE_FAIL; - } - - if(ret == SIGN_FAIL) - { - return CREATE_FAIL; - }else if(ret == SIGN_FAIL_TRY_LATER) - { - return CREATE_FAIL_TRY_LATER; - }else if(ret == SIGN_SUCCESS) - { - return CREATE_SUCCESS; - }else{ - return CREATE_FAIL; - } -} - -int RsGenExchange::createGroupSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinaryData& grpData, - RsGxsGrpMetaData& grpMeta) -{ - bool needIdentitySign = false; - int id_ret; - - uint8_t author_flag = GXS_SERV::GRP_OPTION_AUTHEN_AUTHOR_SIGN; - - PrivacyBitPos pos = GRP_OPTION_BITS; - - // Check required permissions, and allow them to sign it - if they want too - as well! - if ((!grpMeta.mAuthorId.isNull()) || checkAuthenFlag(pos, author_flag)) - { - needIdentitySign = true; -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "Needs Identity sign! (Service Flags)"<< std::endl; -#endif - } - - if (needIdentitySign) - { - if(grpMeta.mAuthorId.isNull()) - { - std::cerr << "RsGenExchange::createGroupSignatures() "; - std::cerr << "Group signature is required by service, but the author id is null." << std::endl; - id_ret = SIGN_FAIL; - } - else if(mGixs) - { - bool haveKey = mGixs->havePrivateKey(grpMeta.mAuthorId); - - if(haveKey) - { - RsTlvPrivateRSAKey authorKey; - mGixs->getPrivateKey(grpMeta.mAuthorId, authorKey); - RsTlvKeySignature sign; - - if(GxsSecurity::getSignature((char*)grpData.bin_data, grpData.bin_len, authorKey, sign)) - { - id_ret = SIGN_SUCCESS; - mGixs->timeStampKey(grpMeta.mAuthorId,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_CREATION,grpMeta.mGroupId)) ; - signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign; - } - else - id_ret = SIGN_FAIL; - } - else - { - mGixs->requestPrivateKey(grpMeta.mAuthorId); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::createGroupSignatures(): "; - std::cerr << " ERROR AUTHOR KEY: " << grpMeta.mAuthorId - << " is not Cached / available for Message Signing\n"; - std::cerr << "RsGenExchange::createGroupSignatures(): Requestiong AUTHOR KEY"; - std::cerr << std::endl; -#endif - - id_ret = SIGN_FAIL_TRY_LATER; - } - } - else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::createGroupSignatures()"; - std::cerr << "Gixs not enabled while request identity signature validation!" << std::endl; -#endif - id_ret = SIGN_FAIL; - } - } - else - { - id_ret = SIGN_SUCCESS; - } - - return id_ret; -} - -int RsGenExchange::createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinaryData& msgData, - const RsGxsMsgMetaData& msgMeta, const RsGxsGrpMetaData& grpMeta) -{ - bool needPublishSign = false, needIdentitySign = false; - uint32_t grpFlag = grpMeta.mGroupFlags; - - bool publishSignSuccess = false; - -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "RsGenExchange::createMsgSignatures() for Msg.mMsgName: " << msgMeta.mMsgName<< std::endl; -#endif - - - // publish signature is determined by whether group is public or not - // for private group signature is not needed as it needs decrypting with - // the private publish key anyways - - // restricted is a special case which heeds whether publish sign needs to be checked or not - // one may or may not want - - uint8_t author_flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN; - uint8_t publish_flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN; - - if(!msgMeta.mParentId.isNull()) - { - // Child Message. - author_flag = GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - publish_flag = GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - } - - PrivacyBitPos pos = PUBLIC_GRP_BITS; - if (grpFlag & GXS_SERV::FLAG_PRIVACY_RESTRICTED) - { - pos = RESTRICTED_GRP_BITS; - } - else if (grpFlag & GXS_SERV::FLAG_PRIVACY_PRIVATE) - { - pos = PRIVATE_GRP_BITS; - } - - needIdentitySign = false; - needPublishSign = false; - if (checkAuthenFlag(pos, publish_flag)) - { - needPublishSign = true; -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "Needs Publish sign! (Service Flags)"<< std::endl; -#endif - } - - // Check required permissions, and allow them to sign it - if they want too - as well! - if (checkAuthenFlag(pos, author_flag)) - { - needIdentitySign = true; -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "Needs Identity sign! (Service Flags)"<< std::endl; -#endif - } - - if (!msgMeta.mAuthorId.isNull()) - { - needIdentitySign = true; -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "Needs Identity sign! (AuthorId Exists)"<< std::endl; -#endif - } - - if(needPublishSign) - { - // public and shared is publish key - const RsTlvSecurityKeySet& keys = grpMeta.keys; - const RsTlvPrivateRSAKey *publishKey; - - std::map::const_iterator mit = keys.private_keys.begin(), mit_end = keys.private_keys.end(); - bool publish_key_found = false; - - for(; mit != mit_end; ++mit) - { - - publish_key_found = mit->second.keyFlags == (RSTLV_KEY_DISTRIB_PUBLISH | RSTLV_KEY_TYPE_FULL); - if(publish_key_found) - break; - } - - if (publish_key_found) - { - // private publish key - publishKey = &(mit->second); - - RsTlvKeySignature publishSign = signSet.keySignSet[INDEX_AUTHEN_PUBLISH]; - - publishSignSuccess = GxsSecurity::getSignature((char*)msgData.bin_data, msgData.bin_len, *publishKey, publishSign); - - //place signature in msg meta - signSet.keySignSet[INDEX_AUTHEN_PUBLISH] = publishSign; - }else - { - std::cerr << "RsGenExchange::createMsgSignatures()"; - std::cerr << " ERROR Cannot find PUBLISH KEY for Message Signing!"; - std::cerr << " ERROR Publish Sign failed!"; - std::cerr << std::endl; - } - - } - else // publish sign not needed so set as successful - { - publishSignSuccess = true; - } - - int id_ret; - - if (needIdentitySign) - { - if(mGixs) - { - bool haveKey = mGixs->havePrivateKey(msgMeta.mAuthorId); - - if(haveKey) - { - RsTlvPrivateRSAKey authorKey; - mGixs->getPrivateKey(msgMeta.mAuthorId, authorKey); - RsTlvKeySignature sign; - - if(GxsSecurity::getSignature((char*)msgData.bin_data, msgData.bin_len, authorKey, sign)) - { - id_ret = SIGN_SUCCESS; - mGixs->timeStampKey(msgMeta.mAuthorId,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_CREATION,msgMeta.mGroupId,msgMeta.mMsgId,msgMeta.mParentId,msgMeta.mThreadId)) ; - signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign; - } - else - id_ret = SIGN_FAIL; - } - else - { - mGixs->requestPrivateKey(msgMeta.mAuthorId); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::createMsgSignatures(): "; - std::cerr << " ERROR AUTHOR KEY: " << msgMeta.mAuthorId - << " is not Cached / available for Message Signing\n"; - std::cerr << "RsGenExchange::createMsgSignatures(): Requestiong AUTHOR KEY"; - std::cerr << std::endl; -#endif - - id_ret = SIGN_FAIL_TRY_LATER; - } - } - else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::createMsgSignatures()"; - std::cerr << "Gixs not enabled while request identity signature validation!" << std::endl; -#endif - id_ret = SIGN_FAIL; - } - } - else - { - id_ret = SIGN_SUCCESS; - } - - if(publishSignSuccess) - { - return id_ret; - } - else - { - return SIGN_FAIL; - } -} - -int RsGenExchange::createMessage(RsNxsMsg* msg) -{ - const RsGxsGroupId& id = msg->grpId; - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::createMessage() " << std::endl; -#endif - RsGxsGrpMetaTemporaryMap metaMap ; - metaMap[id] = std::make_shared(); - mDataStore->retrieveGxsGrpMetaData(metaMap); - - RsGxsMsgMetaData &meta = *(msg->metaData); - - int ret_val; - - if(!metaMap[id]) - { - return CREATE_FAIL; - } - else - { - // get publish key - const auto& grpMeta = metaMap[id]; - - uint32_t metaDataLen = meta.serial_size(); - uint32_t allMsgDataLen = metaDataLen + msg->msg.bin_len; - - RsTemporaryMemory metaData(metaDataLen); - RsTemporaryMemory allMsgData(allMsgDataLen); - - meta.serialise(metaData, &metaDataLen); - - // copy msg data and meta in allmsgData buffer - memcpy(allMsgData, msg->msg.bin_data, msg->msg.bin_len); - memcpy(allMsgData+(msg->msg.bin_len), metaData, metaDataLen); - - RsTlvBinaryData msgData(0); - - msgData.setBinData(allMsgData, allMsgDataLen); - - // create signatures - ret_val = createMsgSignatures(meta.signSet, msgData, meta, *grpMeta); - - - // get hash of msg data to create msg id - pqihash hash; - hash.addData(allMsgData, allMsgDataLen); - RsFileHash hashId; - hash.Complete(hashId); - msg->msgId = RsGxsMessageId(hashId); - - // assign msg id to msg meta - msg->metaData->mMsgId = msg->msgId; - } - - if(ret_val == SIGN_FAIL) - return CREATE_FAIL; - else if(ret_val == SIGN_FAIL_TRY_LATER) - return CREATE_FAIL_TRY_LATER; - else if(ret_val == SIGN_SUCCESS) - return CREATE_SUCCESS; - else - { - std::cerr << "Unknown return value from signature attempt!"; - return CREATE_FAIL; - } -} - -int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, const uint32_t& /*signFlag*/, RsTlvSecurityKeySet& grpKeySet) -{ - bool needIdentitySign = false; - bool needPublishSign = false; - bool publishValidate = true, idValidate = true; - - uint8_t author_flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN; - uint8_t publish_flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN; - - if(!msg->metaData->mParentId.isNull()) - { - // Child Message. - author_flag = GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - publish_flag = GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - } - - PrivacyBitPos pos = PUBLIC_GRP_BITS; - if (grpFlag & GXS_SERV::FLAG_PRIVACY_RESTRICTED) - { - pos = RESTRICTED_GRP_BITS; - } - else if (grpFlag & GXS_SERV::FLAG_PRIVACY_PRIVATE) - { - pos = PRIVATE_GRP_BITS; - } - - if (checkAuthenFlag(pos, publish_flag)) - needPublishSign = true; - - // Check required permissions, if they have signed it anyway - we need to validate it. - if ((checkAuthenFlag(pos, author_flag)) || (!msg->metaData->mAuthorId.isNull())) - needIdentitySign = true; - -#ifdef GEN_EXCH_DEBUG - std::cerr << "Validate message: msgId=" << msg->msgId << ", grpId=" << msg->grpId << " grpFlags=" << std::hex << grpFlag << std::dec - << ". Need publish=" << needPublishSign << ", needIdentitySign=" << needIdentitySign ; -#endif - - RsGxsMsgMetaData& metaData = *(msg->metaData); - - if(needPublishSign) - { - RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_PUBLISH]; - - std::map& keys = grpKeySet.public_keys; - std::map::iterator mit = keys.begin(); - - RsGxsId keyId; - for(; mit != keys.end() ; ++mit) - { - RsTlvPublicRSAKey& key = mit->second; - - if(key.keyFlags & RSTLV_KEY_DISTRIB_PUBLIC_deprecated) - { - keyId = key.keyId; - std::cerr << "WARNING: old style publish key with flags " << key.keyFlags << std::endl; - std::cerr << " this cannot be fixed, but RS will deal with it." << std::endl; - break ; - } - if(key.keyFlags & RSTLV_KEY_DISTRIB_PUBLISH) // we might have the private key, but we still should be able to check the signature - { - keyId = key.keyId; - break; - } - } - - if(!keyId.isNull()) - { - RsTlvPublicRSAKey& key = keys[keyId]; - publishValidate &= GxsSecurity::validateNxsMsg(*msg, sign, key); - } - else - { - std::cerr << "(EE) public publish key not found in group that require publish key validation. This should not happen! msgId=" << metaData.mMsgId << ", grpId=" << metaData.mGroupId << std::endl; - std::cerr << "(EE) public keys available for this group are: " << std::endl; - - for(std::map::const_iterator it(grpKeySet.public_keys.begin());it!=grpKeySet.public_keys.end();++it) - std::cerr << "(EE) " << it->first << std::endl; - - std::cerr << "(EE) private keys available for this group are: " << std::endl; - - for(std::map::const_iterator it(grpKeySet.private_keys.begin());it!=grpKeySet.private_keys.end();++it) - std::cerr << "(EE) " << it->first << std::endl; - - publishValidate = false; - } - } - else - { - publishValidate = true; - } - - - - if(needIdentitySign) - { - if(mGixs) - { - bool haveKey = mGixs->haveKey(metaData.mAuthorId); - - if(haveKey) - { - - RsTlvPublicRSAKey authorKey; - bool auth_key_fetched = mGixs->getKey(metaData.mAuthorId, authorKey) ; - - if (auth_key_fetched) - { - RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_IDENTITY]; - idValidate &= GxsSecurity::validateNxsMsg(*msg, sign, authorKey); - mGixs->timeStampKey(metaData.mAuthorId,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_VALIDATION, - metaData.mGroupId, - metaData.mMsgId, - metaData.mParentId, - metaData.mThreadId)) ; - } - else - { - std::cerr << "RsGenExchange::validateMsg()"; - std::cerr << " ERROR Cannot Retrieve AUTHOR KEY for Message Validation"; - std::cerr << std::endl; - idValidate = false; - } - - if(idValidate) - { - // get key data and check that the key is actually PGP-linked. If not, reject the post. - - RsIdentityDetails details ; - - if(!mGixs->getIdDetails(metaData.mAuthorId,details)) - { - // the key cannot ke reached, although it's in cache. Weird situation. - std::cerr << "RsGenExchange::validateMsg(): cannot get key data for ID=" << metaData.mAuthorId << ", although it's supposed to be already in cache. Cannot validate." << std::endl; - idValidate = false ; - } - else - { - - // now check reputation of the message author. The reputation will need to be at least as high as this value for the msg to validate. - // At validation step, we accept all messages, except the ones signed by locally rejected identities. - - if( details.mReputation.mOverallReputationLevel == - RsReputationLevel::LOCALLY_NEGATIVE ) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::validateMsg(): message from " << metaData.mAuthorId << ", rejected because reputation level (" << static_cast(details.mReputation.mOverallReputationLevel) <<") indicate that you banned this ID." << std::endl; -#endif - idValidate = false ; - } - } - - } - } - else - { - std::list peers; - peers.push_back(msg->PeerId()); - mGixs->requestKey(metaData.mAuthorId, peers, RsIdentityUsage((RsServiceType)serviceType(), - RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_VALIDATION, - metaData.mGroupId, - metaData.mMsgId, - metaData.mParentId, - metaData.mThreadId)); - -#ifdef GEN_EXCH_DEBUG - std::cerr << ", Key missing. Retry later." << std::endl; -#endif - return VALIDATE_FAIL_TRY_LATER; - } - } - else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "Gixs not enabled while request identity signature validation!" << std::endl; -#endif - idValidate = false; - } - } - else - { - idValidate = true; - } - -#ifdef GEN_EXCH_DEBUG - std::cerr << ", publish val=" << publishValidate << ", idValidate=" << idValidate << ". Result=" << (publishValidate && idValidate) << std::endl; -#endif - - if(publishValidate && idValidate) - return VALIDATE_SUCCESS; - else - return VALIDATE_FAIL; - -} - -int RsGenExchange::validateGrp(RsNxsGrp* grp) -{ - bool needIdentitySign = false, idValidate = false; - RsGxsGrpMetaData& metaData = *(grp->metaData); - - uint8_t author_flag = GXS_SERV::GRP_OPTION_AUTHEN_AUTHOR_SIGN; - - PrivacyBitPos pos = GRP_OPTION_BITS; - -#ifdef GEN_EXCH_DEBUG - std::cerr << "Validating group " << grp->grpId << ", authorId = " << metaData.mAuthorId << std::endl; -#endif - // Check required permissions, and allow them to sign it - if they want too - as well! - if ((!metaData.mAuthorId.isNull()) || checkAuthenFlag(pos, author_flag)) - { - needIdentitySign = true; -#ifdef GEN_EXCH_DEBUG - std::cerr << " Needs Identity sign! (Service Flags). Identity signing key is " << metaData.mAuthorId << std::endl; -#endif - } - - if(needIdentitySign) - { - if(mGixs) - { - bool haveKey = mGixs->haveKey(metaData.mAuthorId); - - if(haveKey) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " have ID key in cache: yes" << std::endl; -#endif - - RsTlvPublicRSAKey authorKey; - bool auth_key_fetched = mGixs->getKey(metaData.mAuthorId, authorKey) ; - - if (auth_key_fetched) - { - - RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_IDENTITY]; - idValidate = GxsSecurity::validateNxsGrp(*grp, sign, authorKey); - -#ifdef GEN_EXCH_DEBUG - std::cerr << " key ID validation result: " << idValidate << std::endl; -#endif - mGixs->timeStampKey(metaData.mAuthorId,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_VALIDATION,metaData.mGroupId)); - } - else - { - std::cerr << "RsGenExchange::validateGrp()"; - std::cerr << " ERROR Cannot Retrieve AUTHOR KEY for Group Sign Validation"; - std::cerr << std::endl; - idValidate = false; - } - - }else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " have key in cache: no. Return VALIDATE_LATER" << std::endl; - std::cerr << " requesting key " << metaData.mAuthorId << " to origin peer " << grp->PeerId() << std::endl; -#endif - std::list peers; - peers.push_back(grp->PeerId()); - mGixs->requestKey(metaData.mAuthorId, peers,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_VALIDATION,metaData.mGroupId)); - return VALIDATE_FAIL_TRY_LATER; - } - } - else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " (EE) Gixs not enabled while request identity signature validation!" << std::endl; -#endif - idValidate = false; - } - } - else - { - idValidate = true; - } - - if(idValidate) - return VALIDATE_SUCCESS; - else - return VALIDATE_FAIL; - -} - -bool RsGenExchange::checkAuthenFlag(const PrivacyBitPos& pos, const uint8_t& flag) const -{ -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::checkMsgAuthenFlag(pos: " << pos << " flag: "; - std::cerr << (int) flag << " mAuthenPolicy: " << mAuthenPolicy << ")"; - std::cerr << std::endl; -#endif - - switch(pos) - { - case PUBLIC_GRP_BITS: - return mAuthenPolicy & flag; - break; - case RESTRICTED_GRP_BITS: - return flag & (mAuthenPolicy >> RESTR_GRP_OFFSET); - break; - case PRIVATE_GRP_BITS: - return flag & (mAuthenPolicy >> PRIV_GRP_OFFSET); - break; - case GRP_OPTION_BITS: - return flag & (mAuthenPolicy >> GRP_OPTIONS_OFFSET); - break; - default: - std::cerr << "pos option not recognised"; - return false; - } -} - -static void addMessageChanged(std::map > &msgs, const std::map > &msgChanged) -{ - if (msgs.empty()) { - msgs = msgChanged; - } else { - for (auto mapIt = msgChanged.begin(); mapIt != msgChanged.end(); ++mapIt) - { - const RsGxsGroupId &grpId = mapIt->first; - const std::set &srcMsgIds = mapIt->second; - std::set &destMsgIds = msgs[grpId]; - - for (auto msgIt = srcMsgIds.begin(); msgIt != srcMsgIds.end(); ++msgIt) - destMsgIds.insert(*msgIt) ; - } - } -} - -#ifdef TO_REMOVE -void RsGenExchange::receiveChanges(std::vector& changes) -{ - std::cerr << "*********************************** RsGenExchange::receiveChanges()" << std::endl; -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::receiveChanges()" << std::endl; -#endif - std::unique_ptr evt(new RsGxsChanges); - evt->mServiceType = static_cast(mServType); - - RsGxsChanges& out = *evt; - out.mService = getTokenService(); - - // collect all changes in one GxsChanges object - std::vector::iterator vit = changes.begin(); - for(; vit != changes.end(); ++vit) - { - RsGxsNotify* n = *vit; - RsGxsGroupChange* gc; - RsGxsMsgChange* mc; - RsGxsDistantSearchResultChange *gt; - - if((mc = dynamic_cast(n)) != nullptr) - { - if (mc->metaChange()) - addMessageChanged(out.mMsgsMeta, mc->msgChangeMap); - else - addMessageChanged(out.mMsgs, mc->msgChangeMap); - } - else if((gc = dynamic_cast(n)) != nullptr) - { - if(gc->metaChange()) - out.mGrpsMeta.splice(out.mGrpsMeta.end(), gc->mGrpIdList); - else - out.mGrps.splice(out.mGrps.end(), gc->mGrpIdList); - } - else if(( gt = dynamic_cast(n) ) != nullptr) - out.mDistantSearchReqs.push_back(gt->mRequestId); - else - RsErr() << __PRETTY_FUNCTION__ << " Unknown changes type!" << std::endl; - delete n; - } - changes.clear() ; - - if(rsEvents) rsEvents->postEvent(std::move(evt)); -} -#endif - -bool RsGenExchange::subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) -{ - if(subscribe) - setGroupSubscribeFlags(token, grpId, GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED, - (GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED | GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED)); - else - setGroupSubscribeFlags(token, grpId, GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED, - (GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED | GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED)); - - if(mNetService) mNetService->subscribeStatusChanged(grpId,subscribe); -#ifdef GEN_EXCH_DEBUG - else - std::cerr << "(EE) No mNetService in RsGenExchange for service 0x" << std::hex << mServType << std::dec << std::endl; -#endif - - return true; -} - -bool RsGenExchange::getGroupStatistic(const uint32_t& token, GxsGroupStatistic& stats) -{ - return mDataAccess->getGroupStatistic(token, stats); -} - -bool RsGenExchange::getServiceStatistic(const uint32_t& token, GxsServiceStatistic& stats) -{ - return mDataAccess->getServiceStatistic(token, stats); -} - -bool RsGenExchange::getGroupList(const uint32_t &token, std::list &groupIds) -{ - return mDataAccess->getGroupList(token, groupIds); - -} - -bool RsGenExchange::getMsgList(const uint32_t &token, - GxsMsgIdResult &msgIds) -{ - return mDataAccess->getMsgIdList(token, msgIds); -} - -bool RsGenExchange::getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult &msgIds) -{ - return mDataAccess->getMsgRelatedList(token, msgIds); -} -bool RsGenExchange::getPublishedMsgMeta(const uint32_t& token,RsMsgMetaData& meta) -{ - auto it = mPublishedMsgs.find(token); - - if(it == mPublishedMsgs.end()) - return false ; - - meta = it->second; - return true; -} -bool RsGenExchange::getPublishedGroupMeta(const uint32_t& token,RsGroupMetaData& meta) -{ - auto it = mPublishedGrps.find(token); - - if(it == mPublishedGrps.end()) - return false ; - - meta = it->second; - return true; -} - -bool RsGenExchange::getGroupMeta(const uint32_t &token, std::list &groupInfo) -{ - std::list > metaL; - bool ok = mDataAccess->getGroupSummary(token, metaL); - - for( auto lit = metaL.begin(); lit != metaL.end(); ++lit) - { - const RsGxsGrpMetaData& gMeta = *(*lit); - - RsGroupMetaData m(gMeta); - RsGroupNetworkStats sts ; - - if(mNetService != NULL && mNetService->getGroupNetworkStats(gMeta.mGroupId,sts)) - { - m.mPop = sts.mSuppliers ; - m.mVisibleMsgCount = sts.mMaxVisibleCount ; - - if((!(IS_GROUP_SUBSCRIBED(gMeta.mSubscribeFlags))) || gMeta.mLastPost == 0) - m.mLastPost = sts.mLastGroupModificationTS ; - } - else - { - m.mPop= 0 ; - m.mVisibleMsgCount = 0 ; - } - - // We could save this in the net service, but it's a bit more than that since some services have - // specific usage footprints for their groups. - - m.mLastSeen = (IS_GROUP_SUBSCRIBED(gMeta.mSubscribeFlags)) ? time(nullptr) : service_getLastGroupSeenTs(gMeta.mGroupId); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "Group: " << gMeta.mGroupId << " name \"" << gMeta.mGroupName << "\" last seen=" << m.mLastSeen << " now=" << time(nullptr) << std::endl; -#endif - - groupInfo.push_back(m); - } - - return ok; -} - -bool RsGenExchange::getMsgMeta(const uint32_t &token, - GxsMsgMetaMap &msgInfo) -{ -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::getMsgMeta(): retrieving meta data for token " << token << std::endl; -#endif - //std::list metaL; - GxsMsgMetaResult result; - bool ok = mDataAccess->getMsgSummary(token, result); - - for(auto mit=result.begin(); mit != result.end(); ++mit) - { - auto& metaV = mit->second; - - std::vector& msgInfoV = msgInfo[mit->first]; - - RsMsgMetaData meta; - for(auto vit=metaV.begin(); vit != metaV.end(); ++vit) - msgInfoV.push_back(RsMsgMetaData(*(*vit))); - } - - return ok; -} - -bool RsGenExchange::getMsgRelatedMeta(const uint32_t &token, GxsMsgRelatedMetaMap &msgMeta) -{ - MsgRelatedMetaResult result; - bool ok = mDataAccess->getMsgRelatedSummary(token, result); - - MsgRelatedMetaResult::iterator mit = result.begin(); - - for(; mit != result.end(); ++mit) - { - auto& metaV = mit->second; - - std::vector& msgInfoV = msgMeta[mit->first]; - - for(auto vit=metaV.begin(); vit != metaV.end(); ++vit) - msgInfoV.push_back(RsMsgMetaData(*(*vit))); - } - - return ok; -} - -bool RsGenExchange::getSerializedGroupData(uint32_t token, RsGxsGroupId& id, - unsigned char *& data, - uint32_t& size) -{ - RS_STACK_MUTEX(mGenMtx) ; - - std::list nxsGrps; - - if(!mDataAccess->getGroupData(token, nxsGrps)) - return false ; - - if(nxsGrps.size() != 1) - { - std::cerr << "(EE) getSerializedGroupData() got multiple groups in single request. This is unexpected." << std::endl; - - for(std::list::const_iterator it(nxsGrps.begin());it!=nxsGrps.end();++it) - delete *it ; - - return false ; - } - RsNxsGrp *nxs_grp = *(nxsGrps.begin()); - - size = RsNxsSerialiser(mServType).size(nxs_grp); - id = nxs_grp->metaData->mGroupId ; - - if(size > 1024*1024 || NULL==(data = (unsigned char *)rs_malloc(size))) - { - std::cerr << "(EE) getSerializedGroupData() cannot allocate mem chunk of size " << size << ". Too big, or no room." << std::endl; - delete nxs_grp ; - return false ; - } - - return RsNxsSerialiser(mServType).serialise(nxs_grp,data,&size) ; -} - -bool RsGenExchange::retrieveNxsIdentity(const RsGxsGroupId& group_id,RsNxsGrp *& identity_grp) -{ - RS_STACK_MUTEX(mGenMtx) ; - - std::map grp; - grp[group_id]=nullptr; - std::map::const_iterator grp_it; - - if(! mDataStore->retrieveNxsGrps(grp, true) || grp.end()==(grp_it=grp.find(group_id)) || !grp_it->second) - { - std::cerr << "(EE) Cannot retrieve group data for group " << group_id << " in service " << mServType << std::endl; - return false; - } - - identity_grp = grp_it->second; - return true; -} - -bool RsGenExchange::deserializeGroupData(unsigned char *data, uint32_t size, - RsGxsGroupId* gId /*= nullptr*/) -{ - RS_STACK_MUTEX(mGenMtx) ; - - RsItem *item = RsNxsSerialiser(mServType).deserialise(data, &size); - - RsNxsGrp *nxs_grp = dynamic_cast(item); - - if(item == NULL) - { - std::cerr << "(EE) RsGenExchange::deserializeGroupData(): cannot " - << "deserialise this data. Something's wrong." << std::endl; - delete item; - return false; - } - - if(mGrpPendingValidate.find(nxs_grp->grpId) != mGrpPendingValidate.end()) - { - std::cerr << "(WW) Group " << nxs_grp->grpId << " is already pending validation. Not adding again." << std::endl; - return true; - } - - if(gId) - *gId = nxs_grp->grpId; - - mGrpPendingValidate.insert(std::make_pair(nxs_grp->grpId, GxsPendingItem(nxs_grp, nxs_grp->grpId,time(NULL)))); - - return true; -} - -bool RsGenExchange::getGroupData(const uint32_t &token, std::vector& grpItem) -{ - std::list nxsGrps; - bool ok = mDataAccess->getGroupData(token, nxsGrps); - - std::list::iterator lit = nxsGrps.begin(); -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::getGroupData() RsNxsGrp::len: " << nxsGrps.size(); - std::cerr << std::endl; -#endif - - if(ok) - { - for(; lit != nxsGrps.end(); ++lit) - { - RsTlvBinaryData& data = (*lit)->grp; - RsItem* item = NULL; - - if(data.bin_len != 0) - item = mSerialiser->deserialise(data.bin_data, &data.bin_len); - - if(item) - { - RsGxsGrpItem* gItem = dynamic_cast(item); - if (gItem) - { - gItem->meta = *((*lit)->metaData); - - RsGroupNetworkStats sts ; - if(mNetService && mNetService->getGroupNetworkStats(gItem->meta.mGroupId,sts)) - { - gItem->meta.mPop = sts.mSuppliers; - gItem->meta.mVisibleMsgCount = sts.mMaxVisibleCount; - - // When the group is not subscribed, the last post value is not updated, because there's no message stored. As a consequence, - // we rely on network statistics to give this value, but it is not as accurate as if it was locally computed, because of blocked - // posts, friends not available, sync delays, etc. Similarly if the group has just been subscribed, the last post info is probably - // uninitialised, so we will it too. - - if((!(IS_GROUP_SUBSCRIBED(gItem->meta.mSubscribeFlags))) || gItem->meta.mLastPost == 0) - gItem->meta.mLastPost = sts.mLastGroupModificationTS ; - - } - else - { - gItem->meta.mPop = 0; - gItem->meta.mVisibleMsgCount = 0; - } - - // We could save this in the net service, but it's a bit more than that since some services have - // specific usage footprints for their groups. - - gItem->meta.mLastSeen = (IS_GROUP_SUBSCRIBED(gItem->meta.mSubscribeFlags)) ? time(nullptr) : service_getLastGroupSeenTs(gItem->meta.mGroupId); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "Group: " << gItem->meta.mGroupId << " name \"" << gItem->meta.mGroupName << "\" last seen=" << gItem->meta.mLastSeen << " now=" << time(nullptr) << std::endl; -#endif - - // Also check the group privacy flags. A while ago, it as possible to publish a group without privacy flags. Now it is not possible anymore. - // As a consequence, it's important to supply a correct value in this flag before the data can be edited/updated. - - if((gItem->meta.mGroupFlags & GXS_SERV::FLAG_PRIVACY_MASK) == 0) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "(WW) getGroupData(): mGroupFlags for group " << gItem->meta.mGroupId << " has incorrect value " << std::hex << gItem->meta.mGroupFlags << std::dec << ". Setting value to GXS_SERV::FLAG_PRIVACY_PUBLIC." << std::endl; -#endif - gItem->meta.mGroupFlags |= GXS_SERV::FLAG_PRIVACY_PUBLIC; - } - - grpItem.push_back(gItem); - } - else - { - std::cerr << "RsGenExchange::getGroupData() deserialisation/dynamic_cast ERROR"; - std::cerr << std::endl; - delete item; - } - } - else if(data.bin_len > 0) - //std::cerr << "(EE) RsGenExchange::getGroupData() Item type is probably not handled. Data is: " << RsUtil::BinToHex((unsigned char*)data.bin_data,std::min(50u,data.bin_len)) << ((data.bin_len>50)?"...":"") << std::endl; - std::cerr << "(EE) RsGenExchange::getGroupData() Item type is probably not handled. Data is: " << RsUtil::BinToHex((unsigned char*)data.bin_data,data.bin_len) << std::endl; - - delete *lit; - } - } - return ok; -} - -bool RsGenExchange::getMsgData(uint32_t token, GxsMsgDataMap &msgItems) -{ - RS_STACK_MUTEX(mGenMtx) ; - NxsMsgDataResult msgResult; - bool ok = mDataAccess->getMsgData(token, msgResult); - - if(ok) - { - NxsMsgDataResult::iterator mit = msgResult.begin(); - for(; mit != msgResult.end(); ++mit) - { - const RsGxsGroupId& grpId = mit->first; - std::vector& gxsMsgItems = msgItems[grpId]; - std::vector& nxsMsgsV = mit->second; - std::vector::iterator vit = nxsMsgsV.begin(); - for(; vit != nxsMsgsV.end(); ++vit) - { - RsNxsMsg*& msg = *vit; - RsItem* item = NULL; - - if(msg->msg.bin_len != 0) - item = mSerialiser->deserialise(msg->msg.bin_data, &msg->msg.bin_len); - - if (item) - { - RsGxsMsgItem* mItem = dynamic_cast(item); - if (mItem) - { - mItem->meta = *((*vit)->metaData); // get meta info from nxs msg - gxsMsgItems.push_back(mItem); - } - else - { - std::cerr << "RsGenExchange::getMsgData() deserialisation/dynamic_cast ERROR"; - std::cerr << std::endl; - delete item; - } - } - else - { - std::cerr << "RsGenExchange::getMsgData() deserialisation ERROR"; - std::cerr << std::endl; - } - delete msg; - } - } - } - return ok; -} - -bool RsGenExchange::getMsgRelatedData( uint32_t token, - GxsMsgRelatedDataMap &msgItems ) -{ - RS_STACK_MUTEX(mGenMtx) ; - NxsMsgRelatedDataResult msgResult; - bool ok = mDataAccess->getMsgRelatedData(token, msgResult); - - if(ok) - { - NxsMsgRelatedDataResult::iterator mit = msgResult.begin(); - for(; mit != msgResult.end(); ++mit) - { - const RsGxsGrpMsgIdPair& msgId = mit->first; - std::vector &gxsMsgItems = msgItems[msgId]; - std::vector& nxsMsgsV = mit->second; - - for(auto vit=nxsMsgsV.begin(); vit != nxsMsgsV.end(); ++vit) - { - RsNxsMsg*& msg = *vit; - RsItem* item = NULL; - - if(msg->msg.bin_len != 0) - item = mSerialiser->deserialise(msg->msg.bin_data, - &msg->msg.bin_len); - if (item) - { - RsGxsMsgItem* mItem = dynamic_cast(item); - - if (mItem) - { - mItem->meta = *((*vit)->metaData); // get meta info from nxs msg - gxsMsgItems.push_back(mItem); - } - else - { - std::cerr << "RsGenExchange::getMsgRelatedData() deserialisation/dynamic_cast ERROR"; - std::cerr << std::endl; - delete item; - } - } - else - { - std::cerr << "RsGenExchange::getMsgRelatedData() deserialisation ERROR"; - std::cerr << std::endl; - } - - delete msg; - } - } - } - return ok; -} - -RsTokenService* RsGenExchange::getTokenService() -{ - return mDataAccess; -} - - -bool RsGenExchange::setAuthenPolicyFlag(const uint8_t &msgFlag, uint32_t& authenFlag, const PrivacyBitPos &pos) -{ - uint32_t temp = 0; - temp = msgFlag; - - switch(pos) - { - case PUBLIC_GRP_BITS: - authenFlag &= ~PUB_GRP_MASK; - authenFlag |= temp; - break; - case RESTRICTED_GRP_BITS: - authenFlag &= ~RESTR_GRP_MASK; - authenFlag |= (temp << RESTR_GRP_OFFSET); - break; - case PRIVATE_GRP_BITS: - authenFlag &= ~PRIV_GRP_MASK; - authenFlag |= (temp << PRIV_GRP_OFFSET); - break; - case GRP_OPTION_BITS: - authenFlag &= ~GRP_OPTIONS_MASK; - authenFlag |= (temp << GRP_OPTIONS_OFFSET); - break; - default: - std::cerr << "pos option not recognised"; - return false; - } - return true; -} - -void RsGenExchange::receiveNewGroups(const std::vector &groups) -{ - RS_STACK_MUTEX(mGenMtx) ; - - auto vit = groups.begin(); - - // store these for tick() to pick them up - for(; vit != groups.end(); ++vit) - { - RsNxsGrp* grp = *vit; - NxsGrpPendValidVect::iterator received = mGrpPendingValidate.find(grp->grpId); - - // drop group if you already have them - // TODO: move this to nxs layer to save bandwidth - if(received == mGrpPendingValidate.end()) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::notifyNewGroups() Received GrpId: " << grp->grpId; - std::cerr << std::endl; -#endif - - mGrpPendingValidate.insert(std::make_pair(grp->grpId, GxsPendingItem(grp, grp->grpId,time(NULL)))); - } - else - { - delete grp; - } - } - -} - - -void RsGenExchange::receiveNewMessages(const std::vector& messages) -{ - RS_STACK_MUTEX(mGenMtx) ; - - // store these for tick() to pick them up - - for(uint32_t i=0;imsgId) ; - - // if we have msg already just delete it - if(it == mMsgPendingValidate.end()) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::notifyNewMessages() Received Msg: "; - std::cerr << " GrpId: " << msg->grpId; - std::cerr << " MsgId: " << msg->msgId; - std::cerr << std::endl; -#endif - RsGxsGrpMsgIdPair id; - id.first = msg->grpId; - id.second = msg->msgId; - - mMsgPendingValidate.insert(std::make_pair(msg->msgId,GxsPendingItem(msg, id,time(NULL)))); - } - else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " message is already in pending validation list. dropping." << std::endl; -#endif - delete msg; - } - } -} - -void RsGenExchange::receiveDistantSearchResults(TurtleRequestId id,const RsGxsGroupId &grpId) -{ - std::cerr << __PRETTY_FUNCTION__ << " received result for request " << std::hex << id << std::dec << ": this method should be overloaded in the client service, but it is not. This is a bug!" << std::endl; -} - -void RsGenExchange::notifyReceivePublishKey(const RsGxsGroupId &grpId) -{ - RS_STACK_MUTEX(mGenMtx); - - RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_RECEIVED_PUBLISHKEY,grpId, true); - mNotifications.push_back(gc); -} - -void RsGenExchange::notifyChangedGroupSyncParams(const RsGxsGroupId &grpId) -{ - RS_STACK_MUTEX(mGenMtx); - - RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_GROUP_SYNC_PARAMETERS_UPDATED,grpId, false); - - mNotifications.push_back(gc); -} -void RsGenExchange::notifyChangedGroupStats(const RsGxsGroupId &grpId) -{ - RS_STACK_MUTEX(mGenMtx); - - RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_STATISTICS_CHANGED,grpId, false); - - mNotifications.push_back(gc); -} - -bool RsGenExchange::checkGroupMetaConsistency(const RsGroupMetaData& meta) -{ - std::cerr << "Checking group consistency:" << std::endl; - - if(meta.mGroupName.empty()) - { - std::cerr << "(EE) cannot create a group with no name." << std::endl; - return false; - } - - uint32_t gf = meta.mGroupFlags & GXS_SERV::FLAG_PRIVACY_MASK ; - - if(gf != GXS_SERV::FLAG_PRIVACY_PUBLIC && gf != GXS_SERV::FLAG_PRIVACY_RESTRICTED && gf != GXS_SERV::FLAG_PRIVACY_PRIVATE) - { - std::cerr << "(EE) mGroupFlags has incorrect value " << std::hex << meta.mGroupFlags << std::dec << ". A value among GXS_SERV::FLAG_PRIVACY_{PUBLIC,RESTRICTED,PRIVATE} is expected." << std::endl; - return false ; - } - - if(meta.mCircleType < GXS_CIRCLE_TYPE_PUBLIC || meta.mCircleType > GXS_CIRCLE_TYPE_YOUR_EYES_ONLY) - { - std::cerr << "(EE) mCircleType has incorrect value " << std::hex << meta.mCircleType << std::dec << ". A single value among GXS_CIRCLE_TYPE_{PUBLIC,EXTERNAL,YOUR_FRIENDS_ONLY,LOCAL,EXT_SELF,YOUR_EYES_ONLY} is expected." << std::endl; - return false ; - } - - if(meta.mCircleType == GXS_CIRCLE_TYPE_EXTERNAL) - { - if(!meta.mInternalCircle.isNull()) - { - std::cerr << "(EE) Group circle type is EXTERNAL, but an internal circle ID " << meta.mInternalCircle << " was supplied. This is an error." << std::endl; - return false ; - } - if(meta.mCircleId.isNull()) - { - std::cerr << "(EE) Group circle type is EXTERNAL, but no external circle ID was supplied. meta.mCircleId is indeed empty. This is an error." << std::endl; - return false ; - } - } - - if(meta.mCircleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) - { - if(!meta.mCircleId.isNull()) - { - std::cerr << "(EE) Group circle type is YOUR_FRIENDS_ONLY, but an external circle ID " << meta.mCircleId << " was supplied. This is an error." << std::endl; - return false ; - } - if(meta.mInternalCircle.isNull()) - { - std::cerr << "(EE) Group circle type is YOUR_FRIENDS_ONLY, but no internal circle ID was supplied. meta.mInternalCircle is indeed empty. This is an error." << std::endl; - return false ; - } - } - - if(meta.mCircleType == GXS_CIRCLE_TYPE_EXT_SELF) - { - if(!meta.mCircleId.isNull()) - { - std::cerr << "(EE) Group circle type is EXT_SELF, but an external circle ID " << meta.mCircleId << " was supplied. This is an error." << std::endl; - return false ; - } - if(!meta.mInternalCircle.isNull()) - { - std::cerr << "(EE) Group circle type is EXT_SELF, but an internal circle ID " << meta.mInternalCircle << " was supplied. This is an error." << std::endl; - return false ; - } - } - - std::cerr << "Group is clean." << std::endl; - return true ; -} - -void RsGenExchange::publishGroup(uint32_t& token, RsGxsGrpItem *grpItem) -{ - if(!checkGroupMetaConsistency(grpItem->meta)) - { - std::cerr << "(EE) Cannot publish group. Some information was not supplied." << std::endl; - return ; - } - - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - GxsGrpPendingSign ggps(grpItem, token); - mGrpsToPublish.push_back(ggps); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishGroup() token: " << token; - std::cerr << std::endl; -#endif - -} - - -void RsGenExchange::updateGroup(uint32_t& token, RsGxsGrpItem* grpItem) -{ - if(!checkGroupMetaConsistency(grpItem->meta)) - { - std::cerr << "(EE) Cannot update group. Some information was not supplied." << std::endl; - delete grpItem; - return ; - } - - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - mGroupUpdatePublish.push_back(GroupUpdatePublish(grpItem, token)); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::updateGroup() token: " << token; - std::cerr << std::endl; -#endif -} - -void RsGenExchange::deleteGroup(uint32_t& token, const RsGxsGroupId& grpId) -{ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - mGroupDeletePublish.push_back(GroupDeletePublish(grpId, token)); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::deleteGroup() token: " << token; - std::cerr << std::endl; -#endif -} -void RsGenExchange::deleteMsgs(uint32_t& token, const GxsMsgReq& msgs) -{ - RS_STACK_MUTEX(mGenMtx) ; - - token = mDataAccess->generatePublicToken(); - mMsgDeletePublish.push_back(MsgDeletePublish(msgs, token)); - - // This code below will suspend any requests of the deleted messages for 24 hrs. This of course only works - // if all friend nodes consistently delete the messages in the mean time. - - if(mNetService != NULL) - for(GxsMsgReq::const_iterator it(msgs.begin());it!=msgs.end();++it) - for(auto it2(it->second.begin());it2!=it->second.end();++it2) - mNetService->rejectMessage(*it2); -} - -void RsGenExchange::publishMsg(uint32_t& token, RsGxsMsgItem *msgItem) -{ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - mMsgsToPublish.insert(std::make_pair(token, msgItem)); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishMsg() token: " << token; - std::cerr << std::endl; -#endif - -} - -uint32_t RsGenExchange::getDefaultSyncPeriod() -{ - RS_STACK_MUTEX(mGenMtx) ; - - if(mNetService != NULL) - return mNetService->getDefaultSyncAge(); - else - { - std::cerr << "(EE) No network service available. Cannot get default sync period. " << std::endl; - return 0; - } -} - -RsReputationLevel RsGenExchange::minReputationForForwardingMessages( - uint32_t group_sign_flags, uint32_t identity_sign_flags ) -{ - return RsNetworkExchangeService::minReputationForForwardingMessages(group_sign_flags,identity_sign_flags); -} -uint32_t RsGenExchange::getSyncPeriod(const RsGxsGroupId& grpId) -{ - RS_STACK_MUTEX(mGenMtx) ; - - if(mNetService != NULL) - return mNetService->getSyncAge(grpId); - else - return RS_GXS_DEFAULT_MSG_REQ_PERIOD; -} - -bool RsGenExchange::getGroupNetworkStats(const RsGxsGroupId& grpId,RsGroupNetworkStats& stats) -{ - return (!mNetService) || mNetService->getGroupNetworkStats(grpId,stats) ; -} - -void RsGenExchange::setSyncPeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) -{ - if(mNetService != NULL) - return mNetService->setSyncAge(grpId,age_in_secs) ; - else - std::cerr << "(EE) No network service available. Cannot set storage period. " << std::endl; -} - -uint32_t RsGenExchange::getStoragePeriod(const RsGxsGroupId& grpId) -{ - RS_STACK_MUTEX(mGenMtx) ; - - if(!mNetService) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "(EE) No network service in service " << std::hex << serviceType() << std::dec << ": cannot read message storage time. Returning infinity." << std::endl; -#endif - return false ; - } - return mNetService->getKeepAge(grpId) ; -} -void RsGenExchange::setStoragePeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) -{ - if(mNetService != NULL) - return mNetService->setKeepAge(grpId,age_in_secs) ; - else - std::cerr << "(EE) No network service available. Cannot set storage period. " << std::endl; -} - -void RsGenExchange::setGroupSubscribeFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& flag, const uint32_t& mask) -{ - /* TODO APPLY MASK TO FLAGS */ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - - GrpLocMetaData g; - g.grpId = grpId; - g.val.put(RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG, (int32_t)flag); - g.val.put(RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG+GXS_MASK, (int32_t)mask); // HACK, need to perform mask operation in a non-blocking location - mGrpLocMetaMap.insert(std::make_pair(token, g)); -} - -void RsGenExchange::setGroupStatusFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask) -{ - /* TODO APPLY MASK TO FLAGS */ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - - GrpLocMetaData g; - g.grpId = grpId; - g.val.put(RsGeneralDataService::GRP_META_STATUS, (int32_t)status); - g.val.put(RsGeneralDataService::GRP_META_STATUS+GXS_MASK, (int32_t)mask); // HACK, need to perform mask operation in a non-blocking location - mGrpLocMetaMap.insert(std::make_pair(token, g)); -} - - -void RsGenExchange::setGroupServiceString(uint32_t& token, const RsGxsGroupId& grpId, const std::string& servString) -{ - RS_STACK_MUTEX(mGenMtx); - token = mDataAccess->generatePublicToken(); - - GrpLocMetaData g; - g.grpId = grpId; - g.val.put(RsGeneralDataService::GRP_META_SERV_STRING, servString); - mGrpLocMetaMap.insert(std::make_pair(token, g)); -} - -void RsGenExchange::setMsgStatusFlags(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const uint32_t& status, const uint32_t& mask) -{ - /* TODO APPLY MASK TO FLAGS */ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - - MsgLocMetaData m; - m.val.put(RsGeneralDataService::MSG_META_STATUS, (int32_t)status); - m.val.put(RsGeneralDataService::MSG_META_STATUS+GXS_MASK, (int32_t)mask); // HACK, need to perform mask operation in a non-blocking location - m.msgId = msgId; - mMsgLocMetaMap.insert(std::make_pair(token, m)); -} - -void RsGenExchange::setMsgServiceString(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const std::string& servString ) -{ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - - MsgLocMetaData m; - m.val.put(RsGeneralDataService::MSG_META_SERV_STRING, servString); - m.msgId = msgId; - mMsgLocMetaMap.insert(std::make_pair(token, m)); -} - -void RsGenExchange::processMsgMetaChanges() -{ - std::map metaMap; - - { - RS_STACK_MUTEX(mGenMtx); - if (mMsgLocMetaMap.empty()) - { - return; - } - metaMap = mMsgLocMetaMap; - mMsgLocMetaMap.clear(); - } - - GxsMsgReq msgIds; - - std::map::iterator mit; - for (mit = metaMap.begin(); mit != metaMap.end(); ++mit) - { - MsgLocMetaData& m = mit->second; - - int32_t value, mask; - bool ok = true; - bool changed = false; - - // for meta flag changes get flag to apply mask - if(m.val.getAsInt32(RsGeneralDataService::MSG_META_STATUS, value)) - { - ok = false; - if(m.val.getAsInt32(RsGeneralDataService::MSG_META_STATUS+GXS_MASK, mask)) - { - GxsMsgReq req; - std::set msgIdV; - msgIdV.insert(m.msgId.second); - req.insert(std::make_pair(m.msgId.first, msgIdV)); - GxsMsgMetaResult result; - mDataStore->retrieveGxsMsgMetaData(req, result); - GxsMsgMetaResult::iterator mit = result.find(m.msgId.first); - - if(mit != result.end()) - { - const auto& msgMetaV = mit->second; - - if(!msgMetaV.empty()) - { - const auto& meta = *(msgMetaV.begin()); - value = (meta->mMsgStatus & ~mask) | (mask & value); - changed = (static_cast(meta->mMsgStatus) != value); - m.val.put(RsGeneralDataService::MSG_META_STATUS, value); - ok = true; - } - } - m.val.removeKeyValue(RsGeneralDataService::MSG_META_STATUS+GXS_MASK); - } - } - - ok &= mDataStore->updateMessageMetaData(m) == 1; - uint32_t token = mit->first; - - if(ok) - { - mDataAccess->updatePublicRequestStatus(token, RsTokenService::COMPLETE); - if (changed) - { - msgIds[m.msgId.first].insert(m.msgId.second); - } - } - else - { - mDataAccess->updatePublicRequestStatus(token, RsTokenService::FAILED); - } - - { - RS_STACK_MUTEX(mGenMtx); - mMsgNotify.insert(std::make_pair(token, m.msgId)); - } - } - - if (!msgIds.empty()) - { - RS_STACK_MUTEX(mGenMtx); - - for(auto it(msgIds.begin());it!=msgIds.end();++it) - for(auto& msg_id:it->second) - mNotifications.push_back(new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED, it->first, msg_id, false)); - } -} - -void RsGenExchange::processGrpMetaChanges() -{ - std::map metaMap; - - { - RS_STACK_MUTEX(mGenMtx); - if (mGrpLocMetaMap.empty()) - { - return; - } - metaMap = mGrpLocMetaMap; - mGrpLocMetaMap.clear(); - } - - std::list grpChanged; - - std::map::iterator mit; - for (mit = metaMap.begin(); mit != metaMap.end(); ++mit) - { - GrpLocMetaData& g = mit->second; - uint32_t token = mit->first; - -#ifdef GEN_EXCH_DEBUG - RsDbg() << " Processing GrpMetaChange for token " << token << std::endl; -#endif - // process mask - bool ok = processGrpMask(g.grpId, g.val); - - ok = ok && (mDataStore->updateGroupMetaData(g) == 1); - - if(ok) - { - mDataAccess->updatePublicRequestStatus(token, RsTokenService::COMPLETE); - grpChanged.push_back(g.grpId); - } - else - { - mDataAccess->updatePublicRequestStatus(token, RsTokenService::FAILED); - } - - { - RS_STACK_MUTEX(mGenMtx); - mGrpNotify.insert(std::make_pair(token, g.grpId)); -#ifdef GEN_EXCH_DEBUG - RsDbg() << " Processing GrpMetaChange Adding token " << token << " to mGrpNotify" << std::endl; -#endif - } - } - - for(auto& groupId:grpChanged) - { - RS_STACK_MUTEX(mGenMtx); - - mNotifications.push_back(new RsGxsGroupChange(RsGxsNotify::TYPE_PROCESSED,groupId, true)); - } -} - -bool RsGenExchange::processGrpMask(const RsGxsGroupId& grpId, ContentValue &grpCv) -{ - // first find out which mask is involved - int32_t value, mask, currValue; - std::string key; - std::shared_ptr grpMeta; - bool ok = false; - - RsGxsGrpMetaTemporaryMap grpMetaMap; - grpMetaMap[grpId] = std::make_shared(); - - mDataStore->retrieveGxsGrpMetaData(grpMetaMap); - auto mit = grpMetaMap.find(grpId); - - if(mit != grpMetaMap.end()) - { - grpMeta = mit->second; - - if (!grpMeta) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::processGrpMask() Ignore update for not existing grp id " << grpId.toStdString(); - std::cerr << std::endl; -#endif - return false; - } - ok = true; - } - - if(grpCv.getAsInt32(RsGeneralDataService::GRP_META_STATUS, value) && grpMeta) - { - key = RsGeneralDataService::GRP_META_STATUS; - currValue = grpMeta->mGroupStatus; - } - else if(grpCv.getAsInt32(RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG, value) && grpMeta) - { - key = RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG; - currValue = grpMeta->mSubscribeFlags; - } - else - return !(grpCv.empty()); - - ok &= grpCv.getAsInt32(key+GXS_MASK, mask); - - // remove mask entry so it doesn't affect actual entry - grpCv.removeKeyValue(key+GXS_MASK); - - // apply mask to current value - value = (currValue & ~mask) | (value & mask); - - grpCv.put(key, value); - - return ok; -} - -void RsGenExchange::publishMsgs() -{ - - RS_STACK_MUTEX(mGenMtx) ; - - rstime_t now = time(NULL); - - // stick back msgs pending signature - typedef std::map > PendSignMap; - - PendSignMap::iterator sign_it = mMsgPendingSign.begin(); - - for(; sign_it != mMsgPendingSign.end(); ++sign_it) - { - GxsPendingItem& item = sign_it->second; - mMsgsToPublish.insert(std::make_pair(sign_it->first, item.mItem)); - } - - std::map > msgChangeMap; - std::map::iterator mit = mMsgsToPublish.begin(); - - for(; mit != mMsgsToPublish.end(); ++mit) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishMsgs() Publishing a Message"; - std::cerr << std::endl; -#endif - - RsGxsMsgItem* msgItem = mit->second; - uint32_t token = mit->first; - - uint32_t size = mSerialiser->size(msgItem); - - if(size > RsSerialiser::MAX_SERIAL_SIZE) - { - std::cerr << "Trying to publish a GXS message larger than the accepted maximal size of " << RsSerialiser::MAX_SERIAL_SIZE << " bytes. This is a bug." << std::endl; - mDataAccess->updatePublicRequestStatus(token, RsTokenService::FAILED); - delete msgItem; - - continue; - } - RsTemporaryMemory mData(size); - - // for fatal sign creation - bool createOk = false; - - // if sign requests to try later - bool tryLater = false; - - bool serialOk = mSerialiser->serialise(msgItem, mData, &size); - - if(serialOk) - { - RsNxsMsg* msg = new RsNxsMsg(mServType); - msg->grpId = msgItem->meta.mGroupId; - - msg->msg.setBinData(mData, size); - - // now create meta - msg->metaData = new RsGxsMsgMetaData(); - *(msg->metaData) = msgItem->meta; - - // assign time stamp - msg->metaData->mPublishTs = time(NULL); - - // now intialise msg (sign it) - uint8_t createReturn = createMessage(msg); - - if(createReturn == CREATE_FAIL) - { - createOk = false; - } - else if(createReturn == CREATE_FAIL_TRY_LATER) - { - PendSignMap::iterator pit = mMsgPendingSign.find(token); - tryLater = true; - - // add to queue of messages waiting for a successful - // sign attempt - if(pit == mMsgPendingSign.end()) - { - GxsPendingItem gsi(msgItem, token,time(NULL)); - mMsgPendingSign.insert(std::make_pair(token, gsi)); - } - else - { - // remove from attempts queue if over sign - // attempts limit - if(pit->second.mFirstTryTS + SIGN_MAX_WAITING_TIME < now) - { - std::cerr << "Pending signature grp=" << pit->second.mItem->meta.mGroupId << ", msg=" << pit->second.mItem->meta.mMsgId << ", has exceeded validation time limit. The author's key can probably not be obtained. This is unexpected." << std::endl; - - mMsgPendingSign.erase(token); - tryLater = false; - } - } - - createOk = false; - } - else if(createReturn == CREATE_SUCCESS) - { - createOk = true; - - // erase from queue if it exists - mMsgPendingSign.erase(token); - } - else // unknown return, just fail - createOk = false; - - - - RsGxsMessageId msgId; - RsGxsGroupId grpId = msgItem->meta.mGroupId; - - bool validSize = false; - - // check message not over single msg storage limit - if(createOk) - validSize = mDataStore->validSize(msg); - - if(createOk && validSize) - { - // empty orig msg id means this is the original - // msg. - // (csoler) Why are we doing this??? - - if(msg->metaData->mOrigMsgId.isNull()) - { - msg->metaData->mOrigMsgId = msg->metaData->mMsgId; - } - - // now serialise meta data - size = msg->metaData->serial_size(); - - { - RsTemporaryMemory metaDataBuff(size); - - bool s = msg->metaData->serialise(metaDataBuff, &size); - s &= msg->meta.setBinData(metaDataBuff, size); - if (!s) - std::cerr << "(WW) Can't serialise or set bin data" << std::endl; - } - - msg->metaData->mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - msgId = msg->msgId; - grpId = msg->grpId; - msg->metaData->recvTS = time(NULL); - - // FIXTESTS global variable rsPeers not available in unittests! - - if(rsPeers) - mRoutingClues[msg->metaData->mAuthorId].insert(rsPeers->getOwnId()) ; - - computeHash(msg->msg, msg->metaData->mHash); // (csoler) weird choice: hash should also depend on metadata. Fortunately, msg signature - // signs the holw thing (msg + meta) - - mPublishedMsgs[token] = *msg->metaData; - - RsGxsMsgItem *msg_item = dynamic_cast(mSerialiser->deserialise(msg->msg.bin_data,&msg->msg.bin_len)) ; - - if(!msg_item) - { - delete msg; - mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::FAILED); - - std::cerr << "RsGenExchange::publishMsgs() failed to publish msg, probably because of data size limits. bin_len=" << msg->msg.bin_len << std::endl; - continue; // next mit - } - msg_item->meta = *msg->metaData; - - mDataAccess->addMsgData(msg); // msg is deleted by addMsgData() - - msgChangeMap[grpId].push_back(msg_item); - - if(mNetService != NULL) - mNetService->stampMsgServerUpdateTS(grpId) ; - - // add to published to allow acknowledgement - mMsgNotify.insert(std::make_pair(mit->first, std::make_pair(grpId, msgId))); - mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::COMPLETE); - } - else - { - // delete msg if create msg not ok - delete msg; - - if(!tryLater) - mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::FAILED); - - std::cerr << "RsGenExchange::publishMsgs() failed to publish msg " << std::endl; - } - } - else - { - std::cerr << "RsGenExchange::publishMsgs() failed to serialise msg " << std::endl; - } - - if(!tryLater) - delete msgItem; - } - - // clear msg item map as we're done publishing them and all - // entries are invalid - mMsgsToPublish.clear(); - - for(auto it(msgChangeMap.begin());it!=msgChangeMap.end();++it) - for(auto& msg_item: it->second) - { - RsGxsMsgChange* ch = new RsGxsMsgChange(RsGxsNotify::TYPE_PUBLISHED,msg_item->meta.mGroupId, msg_item->meta.mMsgId, false); - ch->mNewMsgItem = msg_item; - - mNotifications.push_back(ch); - } -} - -RsGenExchange::ServiceCreate_Return RsGenExchange::service_CreateGroup(RsGxsGrpItem* /* grpItem */, - RsTlvSecurityKeySet& /* keySet */) -{ -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::service_CreateGroup(): Does nothing" - << std::endl; -#endif - return SERVICE_CREATE_SUCCESS; -} - - -#define PENDING_SIGN_TIMEOUT 10 // 5 seconds - - -void RsGenExchange::processGroupUpdatePublish() -{ - RS_STACK_MUTEX(mGenMtx) ; - - // get keys for group update publish - - // first build meta request map for groups to be updated - RsGxsGrpMetaTemporaryMap grpMeta; - - for(auto vit = mGroupUpdatePublish.begin(); vit != mGroupUpdatePublish.end(); ++vit) - { - GroupUpdatePublish& gup = *vit; - const RsGxsGroupId& groupId = gup.grpItem->meta.mGroupId; - grpMeta.insert(std::make_pair(groupId, std::make_shared())); - } - - if(grpMeta.empty()) - return; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - // now - for(auto vit = mGroupUpdatePublish.begin(); vit != mGroupUpdatePublish.end(); ++vit) - { - GroupUpdatePublish& gup = *vit; - const RsGxsGroupId& groupId = gup.grpItem->meta.mGroupId; - auto mit = grpMeta.find(groupId); - - std::shared_ptr meta; - - if(mit == grpMeta.end() || mit->second == nullptr) - { - std::cerr << "Error! could not find meta of old group to update!" << std::endl; - mDataAccess->updatePublicRequestStatus(gup.mToken, RsTokenService::FAILED); - delete gup.grpItem; - continue; - } - else - meta = mit->second; - - //gup.grpItem->meta = *meta; - GxsGrpPendingSign ggps(gup.grpItem, gup.mToken); - - if(checkKeys(meta->keys)) - { - ggps.mKeys = meta->keys; - - GxsSecurity::createPublicKeysFromPrivateKeys(ggps.mKeys) ; - - ggps.mHaveKeys = true; - ggps.mStartTS = time(NULL); - ggps.mLastAttemptTS = 0; - ggps.mIsUpdate = true; - ggps.mToken = gup.mToken; - mGrpsToPublish.push_back(ggps); - } - else - { - std::cerr << "(EE) publish group fails because RS cannot find the private publish and author keys" << std::endl; - - delete gup.grpItem; - mDataAccess->updatePublicRequestStatus(gup.mToken, RsTokenService::FAILED); - } - } - - mGroupUpdatePublish.clear(); -} - - -void RsGenExchange::processRoutingClues() -{ - RS_STACK_MUTEX(mGenMtx) ; - - for(std::map >::const_iterator it = mRoutingClues.begin();it!=mRoutingClues.end();++it) - for(std::set::const_iterator it2(it->second.begin());it2!=it->second.end();++it2) - rsGRouter->addRoutingClue(GRouterKeyId(it->first),(*it2) ) ; - - mRoutingClues.clear() ; -} - -void RsGenExchange::processGroupDelete() -{ - RS_STACK_MUTEX(mGenMtx); - - // get keys for group delete publish - typedef std::pair GrpNote; - std::map toNotify; - - for( auto vit = mGroupDeletePublish.begin();vit != mGroupDeletePublish.end(); ++vit) - { - std::vector gprIds; - gprIds.push_back(vit->mGroupId); - mDataStore->removeGroups(gprIds); - toNotify.insert(std::make_pair( vit->mToken, GrpNote(true, vit->mGroupId))); - } - - std::list grpDeleted; - for(auto mit=toNotify.begin(); mit != toNotify.end(); ++mit) - { - GrpNote& note = mit->second; - RsTokenService::GxsRequestStatus status = - note.first ? RsTokenService::COMPLETE - : RsTokenService::FAILED; - - mDataAccess->updatePublicRequestStatus(mit->first, status); - mDataAccess->disposeOfPublicToken(mit->first); - - if(note.first) - grpDeleted.push_back(note.second); - } - - for(auto& groupId:grpDeleted) - { - RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_GROUP_DELETED, groupId,false); - mNotifications.push_back(gc); - } - - mGroupDeletePublish.clear(); -} - -void RsGenExchange::processMessageDelete() -{ - RS_STACK_MUTEX(mGenMtx) ; - - struct MsgNote { - MsgNote(bool s,const GxsMsgReq& mid) : state(s),msgIds(mid){} - - bool state; - GxsMsgReq msgIds; - }; - std::map toNotify; - - for( auto vit = mMsgDeletePublish.begin(); vit != mMsgDeletePublish.end(); ++vit) - { - uint32_t token = (*vit).mToken; - bool res = mDataStore->removeMsgs( (*vit).mMsgs ); - -#ifdef GEN_EXCH_DEBUG - for(auto mit: (*vit).mMsgs) - { - std::cerr << "Attempt to delete messages: token=" << token << std::endl; - for(const auto& msg:mit.second) - std::cerr << " grpId=" << mit.first << ", msgId=" << msg << std::endl; - std::cerr << " Result: " << res << std::endl; - } -#endif - toNotify.insert(std::make_pair(token, MsgNote(res,(*vit).mMsgs))); - } - - std::list msgDeleted; - - for(auto mit = toNotify.begin(); mit != toNotify.end(); ++mit) - { - MsgNote& note = mit->second; - RsTokenService::GxsRequestStatus status = - note.state ? RsTokenService::COMPLETE - : RsTokenService::FAILED; - - mDataAccess->updatePublicRequestStatus(mit->first, status); - mDataAccess->disposeOfPublicToken(mit->first); - - if(note.state) - msgDeleted.push_back(note.msgIds); - } - - for(const auto& msgreq:msgDeleted) - for(const auto& msgit:msgreq) - for(const auto& msg:msgit.second) - mNotifications.push_back(new RsGxsMsgChange(RsGxsNotify::TYPE_MESSAGE_DELETED,msgit.first,msg, false)); - - mMsgDeletePublish.clear(); -} - -bool RsGenExchange::checkKeys(const RsTlvSecurityKeySet& keySet) -{ - - typedef std::map keyMap; - const keyMap& allKeys = keySet.private_keys; - keyMap::const_iterator cit = allKeys.begin(); - - bool adminFound = false, publishFound = false; - for(; cit != allKeys.end(); ++cit) - { - const RsTlvPrivateRSAKey& key = cit->second; - if(key.keyFlags & RSTLV_KEY_TYPE_FULL) // this one is not useful. Just a security. - { - if(key.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) - adminFound = true; - - if(key.keyFlags & RSTLV_KEY_DISTRIB_PUBLISH) - publishFound = true; - - } - else if(key.keyFlags & RSTLV_KEY_TYPE_PUBLIC_ONLY) // this one is not useful. Just a security. - { - std::cerr << "(EE) found a public only key in the private key list" << std::endl; - return false ; - } - } - - // user must have both private and public parts of publish and admin keys - return adminFound && publishFound; -} - -void RsGenExchange::publishGrps() -{ - std::list groups_to_subscribe ; - - { - RS_STACK_MUTEX(mGenMtx) ; - NxsGrpSignPendVect::iterator vit = mGrpsToPublish.begin(); - - typedef struct _GrpNote { - - _GrpNote(bool success,bool is_update,const RsGxsGroupId& gid) : mSuccess(success),mIsUpdate(is_update),mGroupId(gid){} - - bool mSuccess; - bool mIsUpdate; - RsGxsGroupId mGroupId; - - } GrpNote; - - std::map toNotify; // used to notify about token processing if success or fails because of timeout - - while( vit != mGrpsToPublish.end() ) - { - GxsGrpPendingSign& ggps = *vit; - - /* do intial checks to see if this entry has expired */ - rstime_t now = time(NULL) ; - uint32_t token = ggps.mToken; - - - if(now > (ggps.mStartTS + PENDING_SIGN_TIMEOUT) ) - { - // timed out - toNotify.insert(std::make_pair( token, GrpNote(false,ggps.mIsUpdate, RsGxsGroupId()))); - delete ggps.mItem; - vit = mGrpsToPublish.erase(vit); - - continue; - } - - RsGxsGroupId grpId; - RsNxsGrp* grp = new RsNxsGrp(mServType); - RsGxsGrpItem* grpItem = ggps.mItem; - - RsTlvSecurityKeySet fullKeySet; - - if(!(ggps.mHaveKeys)) - { - generateGroupKeys(fullKeySet, true); - ggps.mHaveKeys = true; - ggps.mKeys = fullKeySet; - } - else - { - // We should just merge the keys instead of overwriting them, because the update may not contain private parts. - - fullKeySet = ggps.mKeys; - } - - // find private admin key - RsTlvPrivateRSAKey privAdminKey; - bool privKeyFound = false; - for(std::map::iterator mit_keys = fullKeySet.private_keys.begin(); mit_keys != fullKeySet.private_keys.end(); ++mit_keys) - { - RsTlvPrivateRSAKey& key = mit_keys->second; - - if(key.keyFlags == (RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL)) - { - privAdminKey = key; - privKeyFound = true; - } - } - - uint8_t create = CREATE_FAIL; - - if(privKeyFound) - { - // get group id from private admin key id - grpItem->meta.mGroupId = grp->grpId = RsGxsGroupId(privAdminKey.keyId); - - ServiceCreate_Return ret = service_CreateGroup(grpItem, fullKeySet); - - bool serialOk = false, servCreateOk; - - if(ret == SERVICE_CREATE_SUCCESS) - { - uint32_t size = mSerialiser->size(grpItem); - char *gData = new char[size]; - serialOk = mSerialiser->serialise(grpItem, gData, &size); - grp->grp.setBinData(gData, size); - delete[] gData; - servCreateOk = true; - - }else - { - servCreateOk = false; - } - - if(serialOk && servCreateOk) - { - grp->metaData = new RsGxsGrpMetaData(); - grpItem->meta.mPublishTs = time(NULL); - *(grp->metaData) = grpItem->meta; - - // TODO: change when publish key optimisation added (public groups don't have publish key - grp->metaData->mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN | GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED - | GXS_SERV::GROUP_SUBSCRIBE_PUBLISH; - - create = createGroup(grp, fullKeySet); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishGrps() "; - std::cerr << " GrpId: " << grp->grpId; - std::cerr << " CircleType: " << (uint32_t) grp->metaData->mCircleType; - std::cerr << " CircleId: " << grp->metaData->mCircleId.toStdString(); - std::cerr << std::endl; -#endif - - if(create == CREATE_SUCCESS) - { - // Here we need to make sure that no private keys are included. This is very important since private keys - // can be used to modify the group. Normally the private key set is whiped out by createGroup, but - - grp->metaData->keys.private_keys.clear() ; - - uint32_t mdSize = grp->metaData->serial_size(RS_GXS_GRP_META_DATA_CURRENT_API_VERSION); - - { - RsTemporaryMemory metaData(mdSize); - serialOk = grp->metaData->serialise(metaData, mdSize,RS_GXS_GRP_META_DATA_CURRENT_API_VERSION); -#warning csoler: TODO: grp->meta should be renamed grp->public_meta ! - grp->meta.setBinData(metaData, mdSize); - } - mPublishedGrps[ggps.mToken] = *grp->metaData ; // save the connexion between the token and the created metadata, without private keys - - // Place back private keys for publisher and database storage - grp->metaData->keys.private_keys = fullKeySet.private_keys; - - if(mDataStore->validSize(grp) && serialOk) - { - grpId = grp->grpId; - computeHash(grp->grp, grp->metaData->mHash); - grp->metaData->mRecvTS = time(NULL); - - // Also push in notifications. We do it here when we still have pointers on the old and new groups - - RsGxsGroupChange *c = new RsGxsGroupChange(ggps.mIsUpdate?RsGxsNotify::TYPE_UPDATED:RsGxsNotify::TYPE_PUBLISHED, grpId,false); - - c->mNewGroupItem = dynamic_cast(mSerialiser->deserialise(grp->grp.bin_data,&grp->grp.bin_len)); - c->mNewGroupItem->meta = *grp->metaData; // grp will be deleted because mDataStore will destroy it on update - - if(ggps.mIsUpdate) - { - RsNxsGrpDataTemporaryMap oldGrpDatas; - oldGrpDatas.insert(std::make_pair(grpId, (RsNxsGrp*)NULL)); - - if(mDataStore->retrieveNxsGrps(oldGrpDatas,true) && oldGrpDatas.size() == 1) - { - auto oldGrp = oldGrpDatas[grpId]; - c->mOldGroupItem = dynamic_cast(mSerialiser->deserialise(oldGrp->grp.bin_data,&oldGrp->grp.bin_len)); - c->mOldGroupItem->meta = *oldGrp->metaData; - } - } - - mNotifications.push_back(c); - - // now store (and incidently delete grp) - - if(ggps.mIsUpdate) - mDataAccess->updateGroupData(grp); - else - mDataAccess->addGroupData(grp); - - groups_to_subscribe.push_back(grpId) ; - } - else - { - create = CREATE_FAIL; - } - } - } - else if(ret == SERVICE_CREATE_FAIL_TRY_LATER) - { - // if the service is not ready yet, reset the start timestamp to give the service more time - // the service should have it's own timeout mechanism - // services should return SERVICE_CREATE_FAIL if the action timed out - // at the moment this is only important for the idservice: - // the idservice may ask the user for a password, and the user needs time - ggps.mStartTS = now; - create = CREATE_FAIL_TRY_LATER; - } - else if(ret == SERVICE_CREATE_FAIL) - create = CREATE_FAIL; - } - else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishGrps() Could not find private publish keys " << std::endl; -#endif - create = CREATE_FAIL; - } - - if(create == CREATE_FAIL) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishGrps() failed to publish grp " << std::endl; -#endif - delete grp; - delete grpItem; - vit = mGrpsToPublish.erase(vit); - toNotify.insert(std::make_pair(token, GrpNote(false, ggps.mIsUpdate,grpId))); - - } - else if(create == CREATE_FAIL_TRY_LATER) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishGrps() failed grp, trying again " << std::endl; -#endif - delete grp; - ggps.mLastAttemptTS = time(NULL); - ++vit; - } - else if(create == CREATE_SUCCESS) - { - delete grpItem; - vit = mGrpsToPublish.erase(vit); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishGrps() ok -> pushing to notifies" - << std::endl; -#endif - - // add to published to allow acknowledgement - toNotify.insert(std::make_pair(token, GrpNote(true,ggps.mIsUpdate,grpId))); - } - } - - // toNotify contains the token and the group update/creation info. We parse it to - // - notify that group creation/update for a specific token was - - for(auto mit=toNotify.begin(); mit != toNotify.end(); ++mit) - { - GrpNote& note = mit->second; - RsTokenService::GxsRequestStatus status = note.mSuccess ? RsTokenService::COMPLETE : RsTokenService::FAILED; - - mGrpNotify.insert(std::make_pair(mit->first, note.mGroupId)); // always notify - mDataAccess->updatePublicRequestStatus(mit->first, status); // update the token request with the given status - } - } - - // This is done off-mutex to avoid possible cross deadlocks with the net service. - - if(mNetService!=NULL) - for(std::list::const_iterator it(groups_to_subscribe.begin());it!=groups_to_subscribe.end();++it) - mNetService->subscribeStatusChanged((*it),true) ; -} - -uint32_t RsGenExchange::generatePublicToken() -{ - uint32_t token = mDataAccess->generatePublicToken(); -#ifdef GEN_EXCH_DEBUG - std::cerr << "New token generated: " << token << " in RsGenExchange::generatePublicToken()" << std::endl; -#endif - return token; -} - -bool RsGenExchange::updatePublicRequestStatus( - uint32_t token, RsTokenService::GxsRequestStatus status ) -{ - return mDataAccess->updatePublicRequestStatus(token, status); -} - -bool RsGenExchange::disposeOfPublicToken(const uint32_t &token) -{ - return mDataAccess->disposeOfPublicToken(token); -} - -RsGeneralDataService* RsGenExchange::getDataStore() -{ - return mDataStore; -} - -bool RsGenExchange::getGroupKeys(const RsGxsGroupId &grpId, RsTlvSecurityKeySet &keySet) -{ - if(grpId.isNull()) - return false; - - RS_STACK_MUTEX(mGenMtx) ; - - RsGxsGrpMetaTemporaryMap grpMeta; - grpMeta[grpId] = std::make_shared(); - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - if(grpMeta.empty()) - return false; - - const auto& meta = grpMeta[grpId]; - - if(meta == NULL) - return false; - - keySet = meta->keys; - GxsSecurity::createPublicKeysFromPrivateKeys(keySet) ; - - return true; -} - -void RsGenExchange::shareGroupPublishKey(const RsGxsGroupId& grpId,const std::set& peers) -{ - if(grpId.isNull()) - return ; - - mNetService->sharePublishKey(grpId,peers) ; -} - -void RsGenExchange::processRecvdData() -{ - processRecvdGroups(); - - processRecvdMessages(); - - performUpdateValidation(); - -} - - -void RsGenExchange::computeHash(const RsTlvBinaryData& data, RsFileHash& hash) -{ - pqihash pHash; - pHash.addData(data.bin_data, data.bin_len); - pHash.Complete(hash); -} - -void RsGenExchange::processRecvdMessages() -{ - std::list messages_to_reject ; - - { - RS_STACK_MUTEX(mGenMtx) ; - - rstime_t now = time(NULL); - - if(mMsgPendingValidate.empty()) - return ; -#ifdef GEN_EXCH_DEBUG - else - std::cerr << "processing received messages" << std::endl; -#endif - // 1 - First, make sure items metadata is deserialised, clean old failed items, and collect the groups Ids we have to check - - RsGxsGrpMetaTemporaryMap grpMetas; - - for(NxsMsgPendingVect::iterator pend_it = mMsgPendingValidate.begin();pend_it != mMsgPendingValidate.end();) - { - GxsPendingItem& gpsi = pend_it->second; - RsNxsMsg *msg = gpsi.mItem ; - - if(msg->metaData == NULL) - { - RsGxsMsgMetaData* meta = new RsGxsMsgMetaData(); - - if(msg->meta.bin_len != 0 && meta->deserialise(msg->meta.bin_data, &(msg->meta.bin_len))) - msg->metaData = meta; - else - delete meta; - } - - bool accept_new_msg = msg->metaData != NULL && acceptNewMessage(msg->metaData,msg->msg.bin_len); - - if(!accept_new_msg) - messages_to_reject.push_back(msg->metaData->mMsgId); // This prevents reloading the message again at next sync. - - if(!accept_new_msg || gpsi.mFirstTryTS + VALIDATE_MAX_WAITING_TIME < now) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "Pending validation grp=" << gpsi.mId.first << ", msg=" << gpsi.mId.second << ", has exceeded validation time limit. The author's key can probably not be obtained. This is unexpected." << std::endl; -#endif - - delete gpsi.mItem; - pend_it = mMsgPendingValidate.erase(pend_it); - } - else - { - grpMetas.insert(std::make_pair(pend_it->second.mItem->grpId, std::make_shared())); - ++pend_it; - } - } - - // 2 - Retrieve the metadata for the associated groups. The test is here to avoid the default behavior to - // retrieve all groups when the list is empty - - if(!grpMetas.empty()) - mDataStore->retrieveGxsGrpMetaData(grpMetas); - - GxsMsgReq msgIds; - std::list msgs_to_store; - -#ifdef GEN_EXCH_DEBUG - std::cerr << " updating received messages:" << std::endl; -#endif - - // 3 - Validate each message - - for(NxsMsgPendingVect::iterator pend_it = mMsgPendingValidate.begin();pend_it != mMsgPendingValidate.end();) - { - RsNxsMsg* msg = pend_it->second.mItem; - - // (cyril) Normally we should discard posts that are older than the sync request. But that causes a problem because - // RsGxsNetService requests posts to sync by chunks of 20. So if the 20 are discarded, they will be re-synced next time, and the sync process - // will indefinitly loop on the same 20 posts. Since the posts are there already, keeping them is the least problematique way to fix this problem. - // - // uint32_t max_sync_age = ( mNetService != NULL)?( mNetService->getSyncAge(msg->metaData->mGroupId)):RS_GXS_DEFAULT_MSG_REQ_PERIOD; - // - // if(max_sync_age != 0 && msg->metaData->mPublishTs + max_sync_age < time(NULL)) - // { - // std::cerr << "(WW) not validating message " << msg->metaData->mMsgId << " in group " << msg->metaData->mGroupId << " because it is older than synchronisation limit. This message was probably sent by a friend node that does not accept sync limits already." << std::endl; - // ok = false ; - // } - -#ifdef GEN_EXCH_DEBUG - std::cerr << " deserialised info: grp id=" << msg->grpId << ", msg id=" << msg->msgId ; -#endif - auto mit = grpMetas.find(msg->grpId); - -#ifdef GEN_EXCH_DEBUG - std::cerr << " msg info : grp id=" << msg->grpId << ", msg id=" << msg->msgId << std::endl; -#endif - // validate msg - - if(mit == grpMetas.end()) - { - std::cerr << "RsGenExchange::processRecvdMessages(): impossible situation: grp meta " << msg->grpId << " not available." << std::endl; - ++pend_it ; - continue ; - } - - const auto& grpMeta = mit->second; - RsTlvSecurityKeySet keys = grpMeta->keys ; - - GxsSecurity::createPublicKeysFromPrivateKeys(keys); // make sure we have the public keys that correspond to the private ones, as it happens. Most of the time this call does nothing. - - int validateReturn = validateMsg(msg, grpMeta->mGroupFlags, grpMeta->mSignFlags, keys); - -#ifdef GEN_EXCH_DEBUG - std::cerr << " grpMeta.mSignFlags: " << std::hex << grpMeta->mSignFlags << std::dec << std::endl; - std::cerr << " grpMeta.mAuthFlags: " << std::hex << grpMeta->mAuthenFlags << std::dec << std::endl; - std::cerr << " message validation result: " << (int)validateReturn << std::endl; -#endif - - if(validateReturn == VALIDATE_SUCCESS) - { - msg->metaData->mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - msgs_to_store.push_back(msg); - - msgIds[msg->grpId].insert(msg->msgId); - // std::vector &msgv = msgIds[msg->grpId]; - // if (std::find(msgv.begin(), msgv.end(), msg->msgId) == msgv.end()) - // msgv.push_back(msg->msgId); - - computeHash(msg->msg, msg->metaData->mHash); - msg->metaData->recvTS = time(NULL); - -#ifdef GEN_EXCH_DEBUG - std::cerr << " new status flags: " << msg->metaData->mMsgStatus << std::endl; - std::cerr << " computed hash: " << msg->metaData->mHash << std::endl; - std::cerr << "Message received. Identity=" << msg->metaData->mAuthorId << ", from peer " << msg->PeerId() << std::endl; -#endif - - if(!msg->metaData->mAuthorId.isNull()) - mRoutingClues[msg->metaData->mAuthorId].insert(msg->PeerId()) ; - } - else if(validateReturn == VALIDATE_FAIL) - { - // In this case, we notify the network exchange service not to DL the message again, at least not yet. - -#ifdef GEN_EXCH_DEBUG - std::cerr << "Validation failed for message id " - << "msg->grpId: " << msg->grpId << ", msgId: " << msg->msgId << std::endl; -#endif - messages_to_reject.push_back(msg->msgId) ; - delete msg ; - } - else if(validateReturn == VALIDATE_FAIL_TRY_LATER) - { - ++pend_it ; - continue; - } - - // Remove the entry from mMsgPendingValidate, but do not delete msg since it's either pushed into msg_to_store or deleted in the FAIL case! - - NxsMsgPendingVect::iterator tmp = pend_it ; - ++tmp ; - mMsgPendingValidate.erase(pend_it) ; - pend_it = tmp ; - } - - if(!msgIds.empty()) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " removing existing and old messages from incoming list." << std::endl; -#endif - removeDeleteExistingMessages(msgs_to_store, msgIds); - -#ifdef GEN_EXCH_DEBUG - std::cerr << " storing remaining messages" << std::endl; -#endif - - for(auto& nxs_msg: msgs_to_store) - { - RsGxsMsgItem *item = dynamic_cast(mSerialiser->deserialise(nxs_msg->msg.bin_data,&nxs_msg->msg.bin_len)); - - if(!item) - continue; - - item->meta = *nxs_msg->metaData; - - RsGxsMsgChange* c = new RsGxsMsgChange(RsGxsNotify::TYPE_RECEIVED_NEW, item->meta.mGroupId, item->meta.mMsgId,false); - c->mNewMsgItem = item; - - mNotifications.push_back(c); - } - - mDataStore->storeMessage(msgs_to_store); // All items will be destroyed later on, since msgs_to_store is a temporary map - } - } - - // Done off-mutex to avoid cross deadlocks in the netservice that might call the RsGenExchange as an observer.. - - if(mNetService != NULL) - for(std::list::const_iterator it(messages_to_reject.begin());it!=messages_to_reject.end();++it) - mNetService->rejectMessage(*it) ; -} - -bool RsGenExchange::acceptNewGroup(const RsGxsGrpMetaData* /*grpMeta*/ ) { return true; } -bool RsGenExchange::acceptNewMessage(const RsGxsMsgMetaData* /*grpMeta*/,uint32_t /*size*/ ) { return true; } - -void RsGenExchange::processRecvdGroups() -{ - RS_STACK_MUTEX(mGenMtx) ; - - if(mGrpPendingValidate.empty()) - return; - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::Processing received groups" << std::endl; -#endif - std::list grpIds; - std::list grps_to_store; - - // 1 - retrieve the existing groups so as to check what's not new - std::vector existingGrpIds; - mDataStore->retrieveGroupIds(existingGrpIds); - - // 2 - go through each and every new group data and validate the signatures. - - for(NxsGrpPendValidVect::iterator vit = mGrpPendingValidate.begin(); vit != mGrpPendingValidate.end();) - { - GxsPendingItem& gpsi = vit->second; - RsNxsGrp* grp = gpsi.mItem; - - if(grp->metaData == NULL) - { - RsGxsGrpMetaData* meta = new RsGxsGrpMetaData(); - - if(grp->meta.bin_len != 0 && meta->deserialise(grp->meta.bin_data, grp->meta.bin_len)) - grp->metaData = meta ; - else - delete meta ; - } -#ifdef GEN_EXCH_DEBUG - std::cerr << " processing validation for group " << grp->metaData->mGroupId << ", original attempt time: " << time(NULL) - gpsi.mFirstTryTS << " seconds ago" << std::endl; -#endif - - // early deletion of group from the pending list if it's malformed, not accepted, or has been tried unsuccessfully for too long - - if(grp->metaData == NULL || !acceptNewGroup(grp->metaData) || gpsi.mFirstTryTS + VALIDATE_MAX_WAITING_TIME < time(NULL)) - { - NxsGrpPendValidVect::iterator tmp(vit) ; - ++tmp ; - delete grp ; - mGrpPendingValidate.erase(vit) ; - vit = tmp ; - continue; - } - - // group signature validation - - uint8_t ret = validateGrp(grp); - - if(ret == VALIDATE_SUCCESS) - { - grp->metaData->mGroupStatus = GXS_SERV::GXS_GRP_STATUS_UNPROCESSED | GXS_SERV::GXS_GRP_STATUS_UNREAD; - - computeHash(grp->grp, grp->metaData->mHash); - - // group has been validated. Let's notify the global router for the clue - - if(!grp->metaData->mAuthorId.isNull()) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "Group routage info: Identity=" << grp->metaData->mAuthorId << " from " << grp->PeerId() << std::endl; -#endif - mRoutingClues[grp->metaData->mAuthorId].insert(grp->PeerId()) ; - } - - // This has been moved here (as opposed to inside part for new groups below) because it is used to update the server TS when updates - // of grp metadata arrive. - - grp->metaData->mRecvTS = time(NULL); - - // now check if group already exists - - if(std::find(existingGrpIds.begin(), existingGrpIds.end(), grp->grpId) == existingGrpIds.end()) - { - grp->metaData->mOriginator = grp->PeerId(); - grp->metaData->mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED; - - grps_to_store.push_back(grp); - grpIds.push_back(grp->grpId); - } - else - { - GroupUpdate update; - update.newGrp = grp; - mGroupUpdates.push_back(update); - } - } - else if(ret == VALIDATE_FAIL) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " failed to validate incoming meta, grpId: " << grp->grpId << ": wrong signature" << std::endl; -#endif - delete grp; - } - else if(ret == VALIDATE_FAIL_TRY_LATER) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " failed to validate incoming grp, trying again later. grpId: " << grp->grpId << std::endl; -#endif - ++vit ; - continue; - } - - // Erase entry from the list - - NxsGrpPendValidVect::iterator tmp(vit) ; - ++tmp ; - mGrpPendingValidate.erase(vit) ; - vit = tmp ; - } - - if(!grps_to_store.empty()) - { - for(auto Grp:grps_to_store) - { - RsGxsGroupChange* c = new RsGxsGroupChange(RsGxsNotify::TYPE_RECEIVED_NEW, Grp->grpId, false); - - c->mNewGroupItem = dynamic_cast(mSerialiser->deserialise(Grp->grp.bin_data,&Grp->grp.bin_len)); - - mNotifications.push_back(c); - } - - mDataStore->storeGroup(grps_to_store); // deletes the data after storing it. -#ifdef GEN_EXCH_DEBUG - std::cerr << " adding the following grp ids to notification: " << std::endl; - for(std::list::const_iterator it(grpIds.begin());it!=grpIds.end();++it) - std::cerr << " " << *it << std::endl; -#endif - } -} - -void RsGenExchange::performUpdateValidation() -{ - RS_STACK_MUTEX(mGenMtx) ; - - if(mGroupUpdates.empty()) - return; - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::performUpdateValidation() " << std::endl; -#endif - - RsNxsGrpDataTemporaryMap grpDatas; - - for(auto vit(mGroupUpdates.begin()); vit != mGroupUpdates.end(); ++vit) - grpDatas.insert(std::make_pair(vit->newGrp->grpId, (RsNxsGrp*)NULL)); - - if(grpDatas.empty() || !mDataStore->retrieveNxsGrps(grpDatas,true)) - { - if(grpDatas.empty()) - RsErr() << __PRETTY_FUNCTION__ << " Validation of multiple group updates failed: no group in list!" << std::endl; - else - RsErr() << __PRETTY_FUNCTION__ << " Validation of multiple group updates failed: cannot retrieve froup data for these groups!" << std::endl; - - return; - } - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::performUpdateValidation() " << std::endl; -#endif - std::list grps; // dont use RsNxsGrpDataTemporaryList because updateGrps will delete the groups - - for(auto vit(mGroupUpdates.begin()); vit != mGroupUpdates.end(); ++vit) - { - GroupUpdate& gu = *vit; - - auto mit = grpDatas.find(gu.newGrp->grpId); - - if(mit == grpDatas.end()) - { - RsErr() << __PRETTY_FUNCTION__ << " Validation of group update failed for group " << gu.newGrp->grpId << " because previous grp version cannot be found." << std::endl; - continue; - } - RsGxsGrpMetaData *oldGrpMeta(mit->second->metaData); - RsNxsGrp *oldGrp(mit->second); - - if(updateValid(*oldGrpMeta, *gu.newGrp)) - { - if(gu.newGrp->metaData->mCircleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) - gu.newGrp->metaData->mOriginator = gu.newGrp->PeerId(); - - // Keep subscriptionflag to what it was. This avoids clearing off the flag when updates to group meta information - // is received. - - gu.newGrp->metaData->mSubscribeFlags = oldGrpMeta->mSubscribeFlags ; - - // Also keep private keys if present - - if(!gu.newGrp->metaData->keys.private_keys.empty()) - std::cerr << "(EE) performUpdateValidation() group " <metaData->mGroupId << " has been received with private keys. This is very unexpected!" << std::endl; - else - gu.newGrp->metaData->keys.private_keys = oldGrpMeta->keys.private_keys ; - - // Now prepare notification of the client - - RsGxsGroupChange *c = new RsGxsGroupChange(RsGxsNotify::TYPE_UPDATED,gu.newGrp->metaData->mGroupId,false); - - c->mNewGroupItem = dynamic_cast(mSerialiser->deserialise(gu.newGrp->grp.bin_data,&gu.newGrp->grp.bin_len)); - c->mNewGroupItem->meta = *gu.newGrp->metaData; // gu.newGrp will be deleted because mDataStore will destroy it on update - - c->mOldGroupItem = dynamic_cast(mSerialiser->deserialise(oldGrp->grp.bin_data,&oldGrp->grp.bin_len)); - c->mOldGroupItem->meta = *oldGrpMeta; // no need to delete mit->second, as it will be deleted automatically in the temporary map - - mNotifications.push_back(c); - - // finally, add the group to the list to send to mDataStore - - grps.push_back(gu.newGrp); - } - else - { - delete gu.newGrp; // delete here because mDataStore will not take care of this one. no need to delete mit->second, as it will be deleted automatically in the temporary map - gu.newGrp = NULL ; - } - } - - mDataStore->updateGroup(grps); - -#ifdef GEN_EXCH_DEBUG - std::cerr << " adding the following grp ids to notification: " << std::endl; -#endif - - // cleanup - - mGroupUpdates.clear(); -} - -bool RsGenExchange::updateValid(const RsGxsGrpMetaData& oldGrpMeta, const RsNxsGrp& newGrp) const -{ - std::map& signSet = newGrp.metaData->signSet.keySignSet; - std::map::iterator mit = signSet.find(INDEX_AUTHEN_ADMIN); - - if(mit == signSet.end()) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::updateValid() new admin sign not found! " << std::endl; - std::cerr << "RsGenExchange::updateValid() grpId: " << oldGrpMeta.mGroupId << std::endl; -#endif - - return false; - } - - RsTlvKeySignature adminSign = mit->second; - RsTlvSecurityKeySet old_keys = oldGrpMeta.keys ; - - GxsSecurity::createPublicKeysFromPrivateKeys(old_keys); // make sure we have the public keys that correspond to the private ones, as it happens. Most of the time this call does nothing. - - std::map& keys = old_keys.public_keys; - std::map::iterator keyMit = keys.find(RsGxsId(oldGrpMeta.mGroupId)); - - if(keyMit == keys.end()) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::updateValid() admin key not found! " << std::endl; -#endif - return false; - } - - // also check this is the latest published group - bool latest = newGrp.metaData->mPublishTs > oldGrpMeta.mPublishTs; - - mGixs->timeStampKey(newGrp.metaData->mAuthorId, RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::GROUP_ADMIN_SIGNATURE_CREATION, oldGrpMeta.mGroupId)) ; - - return GxsSecurity::validateNxsGrp(newGrp, adminSign, keyMit->second) && latest; -} - -void RsGenExchange::setGroupReputationCutOff(uint32_t& token, const RsGxsGroupId& grpId, int CutOff) -{ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - - GrpLocMetaData g; - g.grpId = grpId; - g.val.put(RsGeneralDataService::GRP_META_CUTOFF_LEVEL, (int32_t)CutOff); - mGrpLocMetaMap.insert(std::make_pair(token, g)); -} - -void RsGenExchange::removeDeleteExistingMessages( std::list& msgs, GxsMsgReq& msgIdsNotify) -{ - // first get grp ids of messages to be stored - - RsGxsGroupId::std_set mGrpIdsUnique; - - for(std::list::const_iterator cit = msgs.begin(); cit != msgs.end(); ++cit) - mGrpIdsUnique.insert((*cit)->metaData->mGroupId); - - //RsGxsGroupId::std_list grpIds(mGrpIdsUnique.begin(), mGrpIdsUnique.end()); - //RsGxsGroupId::std_list::const_iterator it = grpIds.begin(); - typedef std::map MsgIdReq; - MsgIdReq msgIdReq; - - // now get a list of all msgs ids for each group - for(RsGxsGroupId::std_set::const_iterator it(mGrpIdsUnique.begin()); it != mGrpIdsUnique.end(); ++it) - { - mDataStore->retrieveMsgIds(*it, msgIdReq[*it]); - -#ifdef GEN_EXCH_DEBUG - const std::set& vec(msgIdReq[*it]) ; - std::cerr << " retrieved " << vec.size() << " message ids for group " << *it << std::endl; - - for(auto it2(vec.begin());it2!=vec.end();++it2) - std::cerr << " " << *it2 << std::endl; -#endif - } - - // now for each msg to be stored that exist in the retrieved msg/grp "index" delete and erase from map - for(std::list::iterator cit2 = msgs.begin(); cit2 != msgs.end();) - { - const RsGxsMessageId::std_set& msgIds = msgIdReq[(*cit2)->metaData->mGroupId]; - -#ifdef GEN_EXCH_DEBUG - std::cerr << " grpid=" << (*cit2)->grpId << ", msgid=" << (*cit2)->msgId ; -#endif - - // Avoid storing messages that are already in the database, as well as messages that are too old (or generally do not pass the database storage test) - // - if(msgIds.find((*cit2)->metaData->mMsgId) != msgIds.end() || !messagePublicationTest( *(*cit2)->metaData)) - { - // msg exist in retrieved index. We should use a std::set here instead of a vector. - - RsGxsMessageId::std_set& notifyIds = msgIdsNotify[ (*cit2)->metaData->mGroupId]; - RsGxsMessageId::std_set::iterator it2 = notifyIds.find((*cit2)->metaData->mMsgId); - - if(it2 != notifyIds.end()) - { - notifyIds.erase(it2); - if (notifyIds.empty()) - { - msgIdsNotify.erase( (*cit2)->metaData->mGroupId); - } - } -#ifdef GEN_EXCH_DEBUG - std::cerr << " discarding " << (*cit2)->msgId << std::endl; -#endif - - delete *cit2; - cit2 = msgs.erase(cit2); - } - else - ++cit2; - } -} - -DistantSearchGroupStatus RsGenExchange::getDistantSearchStatus(const RsGxsGroupId& group_id) -{ - return mNetService->getDistantSearchStatus(group_id) ; -} -void RsGenExchange::turtleGroupRequest(const RsGxsGroupId& group_id) -{ - mNetService->turtleGroupRequest(group_id) ; -} -void RsGenExchange::turtleSearchRequest(const std::string& match_string) -{ - mNetService->turtleSearchRequest(match_string) ; -} - -bool RsGenExchange::localSearch( const std::string& matchString, - std::list& results ) -{ - return mNetService->search(matchString, results); -} - -bool RsGenExchange::exportGroupBase64( - std::string& radix, const RsGxsGroupId& groupId, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(groupId.isNull()) return failure("groupId cannot be null"); - - // We have no blocking API here, so we need to make a blocking request manually. - const std::list groupIds({groupId}); - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - uint32_t token; - mDataAccess->requestGroupInfo( token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds); - - // provide a sync response: actually wait for the token. - std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000); - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100); - - auto timeout = std::chrono::steady_clock::now() + maxWait; // wait for 10 secs at most - auto st = mDataAccess->requestStatus(token); - - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = mDataAccess->requestStatus(token); - } - if(st != RsTokenService::COMPLETE) - return failure( "waitToken(...) failed with: " + std::to_string(st) ); - - uint8_t* buf = nullptr; - uint32_t size; - RsGxsGroupId grpId; - - if(!getSerializedGroupData(token, grpId, buf, size)) - return failure("failed retrieving GXS data"); - - Radix64::encode(buf, static_cast(size), radix); - free(buf); - - return true; -} - -bool RsGenExchange::importGroupBase64( - const std::string& radix, RsGxsGroupId& groupId, - std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(radix.empty()) return failure("radix is empty"); - - std::vector mem = Radix64::decode(radix); - if(mem.empty()) return failure("radix seems corrupted"); - - // On success this also import the group as pending validation - if(!deserializeGroupData( - mem.data(), static_cast(mem.size()), - reinterpret_cast(&groupId) )) - return failure("failed deserializing group"); - - return true; -} - -RsGxsChanges::RsGxsChanges() : - RsEvent(RsEventType::GXS_CHANGES), mServiceType(RsServiceType::NONE), - mService(nullptr) {} - -RsGxsIface::~RsGxsIface() = default; -RsGxsGroupSummary::~RsGxsGroupSummary() = default; diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h deleted file mode 100644 index 1bb8bbde6..000000000 --- a/libretroshare/src/gxs/rsgenexchange.h +++ /dev/null @@ -1,1015 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgenexchange.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie, Evi-Parker Christopher * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSGENEXCHANGE_H -#define RSGENEXCHANGE_H - -#include -#include "util/rstime.h" - -#include "rsgxs.h" -#include "rsgds.h" -#include "rsnxs.h" -#include "retroshare/rsgxsiface.h" -#include "rsgxsdataaccess.h" -#include "rsnxsobserver.h" -#include "retroshare/rsgxsservice.h" -#include "rsitems/rsnxsitems.h" -#include "gxs/rsgxsnotify.h" -#include "rsgxsutil.h" - -template -class GxsPendingItem -{ -public: - GxsPendingItem(GxsItem item, Identity id,rstime_t ts) : - mItem(item), mId(id), mFirstTryTS(ts) - {} - - bool operator==(const Identity& id) - { - return this->mId == id; - } - - GxsItem mItem; - Identity mId; - rstime_t mFirstTryTS; -}; - -class GxsGrpPendingSign -{ -public: - - GxsGrpPendingSign(RsGxsGrpItem* item, uint32_t token): mLastAttemptTS(0), mStartTS(time(NULL)), mToken(token), - mItem(item), mHaveKeys(false), mIsUpdate(false) - {} - - rstime_t mLastAttemptTS, mStartTS; - uint32_t mToken; - RsGxsGrpItem* mItem; - bool mHaveKeys; // mKeys->first == true if key present - bool mIsUpdate; - RsTlvSecurityKeySet mKeys; -}; - -typedef std::map > GxsMsgDataMap; -typedef std::map GxsGroupDataMap; -typedef std::map > GxsMsgRelatedDataMap; - -/*! - * This should form the parent class to \n - * all gxs services. This provides access to service's msg/grp data \n - * management/publishing/sync features - * - * Features: \n - * a. Data Access: \n - * Provided by handle to RsTokenService. This ensure consistency \n - * of requests and hiearchy of groups -> then messages which are \n - * sectioned by group ids. \n - * The one caveat is that redemption of tokens are done through \n - * the backend of this class \n - * b. Publishing: \n - * Methods are provided to publish msg and group items and also make \n - * changes to meta information of both item types \n - * c. Sync/Notification: \n - * Also notifications are made here on receipt of new data from \n - * connected peers - */ - -class RsGixs; - -class RsGenExchange : public RsNxsObserver, public RsTickingThread, - public RsGxsIface -{ -public: - - /// used by class derived for RsGenExchange to indicate if service create passed or not - enum ServiceCreate_Return { SERVICE_CREATE_SUCCESS, SERVICE_CREATE_FAIL, SERVICE_CREATE_FAIL_TRY_LATER } ; - - /*! - * Constructs a RsGenExchange object, the owner ship of gds, ns, and serviceserialiser passes \n - * onto the constructed object - * @param gds Data service needed to act as store of message - * @param ns Network service needed to synchronise data with rs peers - * @param serviceSerialiser The users service needs this \n - * in order for gen exchange to deal with its data types - * @param mServType This should be service type used by the serialiser - * @param gixs This is used for verification of msgs and groups received by Gen Exchange using identities. - * @param authenPolicy This determines the authentication used for verfying authorship of msgs and groups - */ - RsGenExchange( - RsGeneralDataService* gds, RsNetworkExchangeService* ns, - RsSerialType* serviceSerialiser, uint16_t mServType, RsGixs* gixs, - uint32_t authenPolicy ); - - virtual ~RsGenExchange(); - - // Convention that this is implemented here. - // and passes to network service. - virtual RsServiceInfo getServiceInfo() = 0; - - void setNetworkExchangeService(RsNetworkExchangeService *ns) ; - - /** S: Observer implementation **/ - - /*! - * @param messages messages are deleted after function returns - */ - virtual void receiveNewMessages(const std::vector &messages) override; - - /*! - * @param groups groups are deleted after function returns - */ - virtual void receiveNewGroups(const std::vector &groups) override; - - /*! - * @param grpId group id - */ - virtual void notifyReceivePublishKey(const RsGxsGroupId &grpId) override; - - virtual void notifyChangedGroupSyncParams(const RsGxsGroupId &grpId) override; - /*! - * \brief notifyReceiveDistantSearchResults - * Should be called when new search results arrive. - * \param grpId - */ - virtual void receiveDistantSearchResults(TurtleRequestId id,const RsGxsGroupId &grpId) override; - /*! - * @param grpId group id - */ - virtual void notifyChangedGroupStats(const RsGxsGroupId &grpId) override; - - /** E: Observer implementation **/ - - /*! - * This is called by Gxs service runner - * periodically, use to implement non - * blocking calls - */ - void tick(); - - /*! - * Any backgroup processing needed by - */ - virtual void service_tick() = 0; - - /*! - * - * @return handle to token service handle for making - * request to this gxs service - */ - RsTokenService* getTokenService(); - - void threadTick() override; /// @see RsTickingThread - - /*! - * Policy bit pattern portion - */ - enum PrivacyBitPos { PUBLIC_GRP_BITS, RESTRICTED_GRP_BITS, PRIVATE_GRP_BITS, GRP_OPTION_BITS } ; - - /*! - * Convenience function for setting bit patterns of the individual privacy level authentication - * policy and group options - * @param flag the bit pattern (and policy) set for the privacy policy - * @param authenFlag Only the policy portion chosen will be modified with 'flag', - * the origianl flags in the indicated bit position (pos) are over-written - * @param pos The policy bit portion to modify - * @see PrivacyBitPos - */ - static bool setAuthenPolicyFlag(const uint8_t& flag, uint32_t& authenFlag, const PrivacyBitPos& pos); - -public: - - /** data access functions **/ - - /*! - * Retrieve group list for a given token - * @param token - * @param groupIds - * @return false if token cannot be redeemed, if false you may have tried to redeem when not ready - */ - bool getGroupList(const uint32_t &token, std::list &groupIds); - - /*! - * Retrieve msg list for a given token sectioned by group Ids - * @param token token to be redeemed - * @param msgIds a map of grpId -> msgList (vector) - * @return false if could not redeem token - */ - bool getMsgList(const uint32_t &token, GxsMsgIdResult &msgIds); - - /*! - * Retrieve msg list for a given token for message related info - * @param token token to be redeemed - * @param msgIds a map of RsGxsGrpMsgIdPair -> msgList (vector) - * @return false if could not redeem token - */ - bool getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult& msgIds)override; - - - /*! - * retrieve group meta data associated to a request token - * @param token - * @param groupInfo - * @return false if could not redeem token - */ - bool getGroupMeta(const uint32_t &token, std::list& groupInfo)override; - - /*! - * retrieves message meta data associated to a request token - * @param token token to be redeemed - * @param msgInfo the meta data to be retrieved for token store here - */ - bool getMsgMeta(const uint32_t &token, GxsMsgMetaMap &msgInfo)override; - - /*! - * Retrieve msg meta for a given token for message related info - * @param token token to be redeemed - * @param msgIds a map of RsGxsGrpMsgIdPair -> msgList (vector) - * @return false if could not redeem token - */ - bool getMsgRelatedMeta(const uint32_t &token, GxsMsgRelatedMetaMap& msgMeta)override; - - /*! - * Retrieves the meta data of a newly created group. The meta is kept in cache for the current session. - * \param token token that was used to create the group - * \param meta meta data for this group - * \return false if the group is not yet created. - */ - bool getPublishedGroupMeta(const uint32_t& token,RsGroupMetaData& meta); - - /*! - * Retrieves the meta data of a newly created post. The meta is kept in cache for the current session. - * \param token token that was used to create the post - * \param meta meta data for this post - * \return false if the group is not yet created. - */ - bool getPublishedMsgMeta(const uint32_t& token,RsMsgMetaData& meta); - -#ifdef TO_REMOVE - /*! - * Gxs services should call this for automatic handling of - * changes, send - * @param changes - */ - virtual void receiveChanges(std::vector& changes); -#endif - - /*! - * \brief acceptNewGroup - * Early checks if the group can be accepted. This is mainly used to check wether the group is banned for some reasons. - * Returns true unless derived in GXS services. - * - * \param grpMeta Group metadata to check - * \return - */ - virtual bool acceptNewGroup(const RsGxsGrpMetaData *grpMeta) ; - - /*! - * \brief acceptNewMessage - * Early checks if the message can be accepted. This is mainly used to check wether the group is for instance overloaded and the service wants - * to put limitations to it. - * Returns true unless derived in GXS services. - * - * \param grpMeta Group metadata to check - * \return - */ - virtual bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta, uint32_t size) ; - - bool subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) override; - - /*! - * Gets service statistic for a given services - * @param token value to to retrieve requested stats - * @param stats the status - * @return true if token exists false otherwise - */ - bool getServiceStatistic(const uint32_t& token, GxsServiceStatistic& stats) override; - - /*! - * Get group statistic - * @param token to be redeemed - * @param stats the stats associated to token requ - * @return true if token is false otherwise - */ - bool getGroupStatistic(const uint32_t& token, GxsGroupStatistic& stats) override; - - /*! - * \brief turtleGroupRequest - * Issues a browadcast group request using the turtle router generic search system. The request is obviously asynchroneous and will be - * handled in RsGenExchange when received. - * \param group_id - */ - void turtleGroupRequest(const RsGxsGroupId& group_id); - void turtleSearchRequest(const std::string& match_string); - - /*! - * \brief getDistantSearchStatus - * Returns the status of ongoing search: unknown (probably not even searched), known as a search result, - * data request ongoing and data available - */ - DistantSearchGroupStatus getDistantSearchStatus(const RsGxsGroupId& group_id) ; - - /** - * @brief Search local groups. Blocking API. - * @param matchString string to look for in the search - * @param results storage for results - * @return false on error, true otherwise - */ - bool localSearch( const std::string& matchString, - std::list& results ); - - /// @see RsGxsIface - bool exportGroupBase64( - std::string& radix, const RsGxsGroupId& groupId, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsGxsIface - bool importGroupBase64( - const std::string& radix, - RsGxsGroupId& groupId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - -protected: - - bool messagePublicationTest(const RsGxsMsgMetaData&) ; - /*! - * retrieves group data associated to a request token - * @param token token to be redeemed for grpitem retrieval - * @param grpItem the items to be retrieved for token are stored here - */ - bool getGroupData(const uint32_t &token, std::vector& grpItem); - - /*! - * \brief getSerializedGroupData - * Retrieves the complete group data serialized into a chunk of memory. This can be useful to - * transfer a full group from one machine to another. - * - * \param token token previously obtained from cache request - * \param data memory chunk allocated (using malloc) - * \param size size of the memory chunk. - * \return - */ - - bool getSerializedGroupData(uint32_t token, RsGxsGroupId &id, - unsigned char *& data, uint32_t& size); - bool deserializeGroupData(unsigned char *data, uint32_t size, - RsGxsGroupId* gId = nullptr); - - /*! - * \brief retrieveNxsIdentity - * Sync version of the previous method. Might take some time, so should be used carefully. - */ - bool retrieveNxsIdentity(const RsGxsGroupId& group_id,RsNxsGrp *& identity_grp); - - template - bool getGroupDataT(const uint32_t &token, std::vector& grpItem) - { - std::vector items; - bool ok = getGroupData(token, items); - std::vector::iterator vit = items.begin(); - - for(; vit != items.end(); ++vit) - { - RsGxsGrpItem* gi = *vit; - - GrpType* item = dynamic_cast(gi); - - if(item) - { - grpItem.push_back(item); - } - else - { -#ifdef GXS_DEBUG - std::cerr << "\nRsGenExchange::getGroupDataT(): Wrong type!\n"; -#endif - delete gi; - } - } - - return ok; - } - -public: - - /*! - * retrieves message data associated to a request token - * @param token token to be redeemed for message item retrieval - * @param msgItems - */ - bool getMsgData(uint32_t token, GxsMsgDataMap& msgItems); - - template - bool getMsgDataT( uint32_t token, std::map >& msgItems) - { - GxsMsgDataMap msgData; - bool ok = getMsgData(token, msgData); - - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - const RsGxsGroupId& grpId = mit->first; - std::vector& mv = mit->second; - std::vector::iterator vit = mv.begin(); - for(; vit != mv.end(); ++vit) - { - RsGxsMsgItem* mi = *vit; - MsgType* mt = dynamic_cast(mi); - - if(mt != NULL) - { - msgItems[grpId].push_back(mt); - } - else - { - std::cerr << "RsGenExchange::getMsgDataT(): bad cast to msg type" << std::endl; - delete mi; - } - } - } - - return ok; - } - - /*! - * retrieves message related data associated to a request token - * @param token token to be redeemed for message item retrieval - * @param msgItems - */ - bool getMsgRelatedData(uint32_t token, GxsMsgRelatedDataMap& msgItems); - -protected: - - /*! - * Convenience template function for retrieve - * msg related data from - * @param GxsMsgType This represent derived msg class type of the service (i.e. msg type that derives from RsGxsMsgItem - * @param MsgType Represents the final type the core data is converted to - * @param token token to be redeemed - */ - template - bool getMsgRelatedDataT(const uint32_t &token, std::map > &msgItems) - { - - RsStackMutex stack(mGenMtx); - NxsMsgRelatedDataResult msgResult; - bool ok = mDataAccess->getMsgRelatedData(token, msgResult); - NxsMsgRelatedDataResult::iterator mit = msgResult.begin(); - - if(ok) - { - for(; mit != msgResult.end(); ++mit) - { - std::vector gxsMsgItems; - const RsGxsGrpMsgIdPair& msgId = mit->first; - std::vector& nxsMsgsV = mit->second; - std::vector::iterator vit - = nxsMsgsV.begin(); - for(; vit != nxsMsgsV.end(); ++vit) - { - RsNxsMsg*& msg = *vit; - RsItem* item = NULL; - - if(msg->msg.bin_len != 0) - item = mSerialiser->deserialise(msg->msg.bin_data, - &msg->msg.bin_len); - - GxsMsgType* mItem = NULL; - - if(item) - mItem = dynamic_cast(item); - - if(mItem == NULL) - { - delete msg; - continue; - } - - mItem->meta = *((*vit)->metaData); // get meta info from nxs msg - // GxsMsgType m = (*mItem); // doesn't work! don't know why, even with overloading done. - MsgType theServMsg = (MsgType)*mItem; - gxsMsgItems.push_back(theServMsg); - delete msg; - } - msgItems[msgId] = gxsMsgItems; - } - } - return ok; - } - -public: - /*! - * Generate a new token, the status of the token can be queried from request - * status feature. - * @attention the token space is shared with RsGenExchange backend. - * @return Generated token - */ - uint32_t generatePublicToken(); - - /*! - * Updates the status of associate token - * @warning the token space is shared with RsGenExchange backend, so do not - * modify tokens except does you have created by calling generatePublicToken() - * @param token - * @param status - * @return false if token could not be found, true if token disposed of - */ - bool updatePublicRequestStatus( - uint32_t token, RsTokenService::GxsRequestStatus status); - - /*! - * This gets rid of a publicly issued token - * @param token - * @return false if token could not found, true if token is disposed of - */ - bool disposeOfPublicToken(const uint32_t &token); - -protected: - /*! - * This gives access to the data store which hold msgs and groups - * for the service - * @return Data store for retrieving msgs and groups - */ - RsGeneralDataService* getDataStore(); - - /*! - * Retrieve keys for a given group, \n - * call is blocking retrieval from underlying db - * @warning under normal circumstance a service should not need this - * @param grpId the id of the group to retrieve keys for - * @param keys set to the retrieved keys - * @return false if group does not exist or grpId is empty - */ - bool getGroupKeys(const RsGxsGroupId& grpId, RsTlvSecurityKeySet& keySet); - -public: - - /*! - * This allows the client service to acknowledge that their msgs has \n - * been created/modified and retrieve the create/modified msg ids - * @param token the token related to modification/create request - * @param msgIds map of grpid->msgIds of message created/modified - * @return true if token exists false otherwise - */ - bool acknowledgeTokenMsg(const uint32_t& token, RsGxsGrpMsgIdPair& msgId); - - /*! - * This allows the client service to acknowledge that their grps has \n - * been created/modified and retrieve the create/modified grp ids - * @param token the token related to modification/create request - * @param grpId ids of created/modified group - * @return true if token exists false otherwise - */ - bool acknowledgeTokenGrp(const uint32_t& token, RsGxsGroupId& grpId); - -protected: - - /** Modifications **/ - - /*! - * Enables publication of a group item \n - * This will induce a related change message \n - * Ownership of item passes to this rsgenexchange \n - * @param token - * @param grpItem - */ - void publishGroup(uint32_t& token, RsGxsGrpItem* grpItem); - - /*! - * Updates an existing group item \n - * This will induce a related change message \n - * Ownership of item passes to this rsgenexchange \n - * @param token - * @param grpItem - */ - void updateGroup(uint32_t& token, RsGxsGrpItem* grpItem); - - /*! - * Deletes an existing group item \n - * This will induce a related change message \n - * Ownership of item passes to this rsgenexchange \n - * @param token - * @param grpItem - */ - void deleteGroup(uint32_t& token, const RsGxsGroupId &grpId); - -public: - /*! - * Enables publication of a message item \n - * Setting mOrigMsgId meta member to blank \n - * leads to this msg being an original msg \n - * if mOrigMsgId is not blank the msgId then this msg is \n - * considered a versioned msg \n - * Ownership of item passes to this rsgenexchange - * @param token - * @param msgItem - */ - void publishMsg(uint32_t& token, RsGxsMsgItem* msgItem); - - /*! - * Deletes the messages \n - * This will induce a related change message \n - * @param token - * @param msgs - */ - void deleteMsgs(uint32_t& token, const GxsMsgReq& msgs); - -protected: - /*! - * This represents the group before its signature is calculated - * Reimplement this function if you need to access keys to further extend - * security of your group items using keyset properties - * Derived service should return one of three ServiceCreate_Return enum values below - * @warning do not modify keySet! - * @param grp The group which is stored by GXS prior - * service can make specific modifications need - * in particular access to its keys and meta - * @param keySet this is the key set used to define the group - * contains private and public admin and publish keys - * (use key flags to distinguish) - * @return SERVICE_CREATE_SUCCESS, SERVICE_CREATE_FAIL, SERVICE_FAIL_TRY_LATER - */ - virtual ServiceCreate_Return service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet); - - /*! - * \brief service_checkIfGroupIsStillUsed - * Re-implement this function to help GXS cleaning, by telling that some particular group - * is not used anymore. This usually depends on subscription, the fact that friend nodes send - * some info or not, and particular cleaning strategy of each service. - * Besides, groups in some services are used by other services (e.g. identities, circles, are used in - * forums and so on), so deciding on a group usage can only be left to the specific service it is used in. - * \return - * true if the group is still used, false otherwise, meaning that the group can be deleted. Default is - * that the group is always in use. - */ - virtual bool service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& /* meta */) { return true; } // see RsGenExchange - - /*! - * \brief service_getLastGroupSeenTs - * \return - * returns the last time a friend sent information (statistics) about this group. That practically means when the - * group was still being subscribed by at least one friend. This is used by service_checkIfGroupIsStillUsed() to - * help getting rid of dead groups. - */ - virtual rstime_t service_getLastGroupSeenTs(const RsGxsGroupId&) { return 0; } -public: - - /*! - * sets the group subscribe flag - * @param token this is set to token value associated to this request - * @param grpId Id of group whose subscribe file will be changed - * @param status - * @param mask - */ - void setGroupSubscribeFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask); - - /*! - * sets the group subscribe flag - * @param token this is set to token value associated to this request - * @param grpId Id of group whose subscribe file will be changed - * @param status - * @param mask - */ - void setGroupStatusFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask); - - /*! - * sets the group service string - * @param token this is set to token value associated to this request - * @param grpId Id of group whose subscribe file will be changed - * @param servString - */ - void setGroupServiceString(uint32_t& token, const RsGxsGroupId& grpId, const std::string& servString); - - /*! - * - * @param token value set to be redeemed with acknowledgement - * @param grpId group id for cutoff value to be set - * @param CutOff The cut off value to set - */ - void setGroupReputationCutOff(uint32_t& token, const RsGxsGroupId& grpId, int CutOff); - - /*! - * - * @param token value set to be redeemed with acknowledgement - * @param grpId group id of the group to update - * @param CutOff The cut off value to set - */ - void updateGroupLastMsgTimeStamp(uint32_t& token, const RsGxsGroupId& grpId); - - /*! - * sets the msg status flag - * @param token this is set to token value associated to this request - * @param grpId Id of group whose subscribe file will be changed - * @param status - * @param mask Mask to apply to status flag - */ - void setMsgStatusFlags(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const uint32_t& status, const uint32_t& mask); - - /*! - * sets the message service string - * @param token this is set to token value associated to this request - * @param msgId Id of message whose service string will be changed - * @param servString The service string to set msg to - */ - void setMsgServiceString(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const std::string& servString ); - - /*! - * sets the message service string - */ - - void shareGroupPublishKey(const RsGxsGroupId& grpId,const std::set& peers) ; - - /*! - * Returns the local TS of the group as known by the network service. - * This is useful to allow various network services to sync their update TS - * when needed. Typical use case is forums and circles. - * @param gid GroupId the TS is which is requested - */ - bool getGroupServerUpdateTS(const RsGxsGroupId& gid,rstime_t& grp_server_update_TS,rstime_t& msg_server_update_TS) ; - - /*! - * \brief getDefaultStoragePeriod. All times in seconds. - * \return - */ - virtual uint32_t getDefaultStoragePeriod() override{ return mNetService->getDefaultKeepAge() ; } - - virtual uint32_t getStoragePeriod(const RsGxsGroupId& grpId) override; - virtual void setStoragePeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) override; - - virtual uint32_t getDefaultSyncPeriod()override; - virtual uint32_t getSyncPeriod(const RsGxsGroupId& grpId) override; - virtual void setSyncPeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) override; - virtual bool getGroupNetworkStats(const RsGxsGroupId& grpId,RsGroupNetworkStats& stats); - - uint16_t serviceType() const override { return mServType ; } - uint32_t serviceFullType() const { return RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(mServType); } - - virtual RsReputationLevel minReputationForForwardingMessages( - uint32_t group_sign_flags, uint32_t identity_flags )override; -protected: - - /** Notifications **/ - - /*! - * This confirms this class as an abstract one that \n - * should not be instantiated \n - * The deriving class should implement this function \n - * as it is called by the backend GXS system to \n - * update client of changes which should \n - * instigate client to retrieve new content from the system - * Note! For newly received message and groups, bit 0xf00 is set to - * GXS_SERV::GXS_MSG_STATUS_UNPROCESSED and GXS_SERV::GXS_MSG_STATUS_UNREAD - * @param changes the changes that have occured to data held by this service - */ - virtual void notifyChanges(std::vector& changes) = 0; - -private: - - void processRecvdData(); - - void processRecvdMessages(); - - void processRecvdGroups(); - - void publishGrps(); - - void processGroupUpdatePublish(); - - void processGroupDelete(); - void processMessageDelete(); - void processRoutingClues(); - - void publishMsgs(); - - bool checkGroupMetaConsistency(const RsGroupMetaData& meta); - - /*! - * processes msg local meta changes - */ - void processMsgMetaChanges(); - - /*! - * Processes group local meta changes - */ - void processGrpMetaChanges(); - - /*! - * Convenience function for properly applying masks for status and subscribe flag - * of a group. - * @warning mask entry is removed from grpCv - */ - bool processGrpMask(const RsGxsGroupId& grpId, ContentValue& grpCv); - - /*! - * This completes the creation of an instance on RsNxsGrp - * by assigning it a groupId and signature via SHA1 and EVP_sign respectively \n - * @param grp Nxs group to create - * @return CREATE_SUCCESS for success, CREATE_FAIL for fail, - * CREATE_FAIL_TRY_LATER for Id sign key not avail (but requested) - */ - uint8_t createGroup(RsNxsGrp* grp, RsTlvSecurityKeySet& keySet); - -protected: - /*! - * This completes the creation of an instance on RsNxsMsg - * by assigning it a groupId and signature via SHA1 and EVP_sign respectively - * What signatures are calculated are based on the authentication policy - * of the service - * @param msg the Nxs message to create - * @return CREATE_SUCCESS for success, CREATE_FAIL for fail, - * CREATE_FAIL_TRY_LATER for Id sign key not avail (but requested) - */ - int createMessage(RsNxsMsg* msg); - - RsNetworkExchangeService *netService() const { return mNetService ; } - -private: - /*! - * convenience function to create sign - * @param signSet signatures are stored here - * @param msgData message data to be signed - * @param grpMeta the meta data for group the message belongs to - * @return SIGN_SUCCESS for success, SIGN_FAIL for fail, - * SIGN_FAIL_TRY_LATER for Id sign key not avail (but requested), try later - */ - int createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinaryData& msgData, - const RsGxsMsgMetaData& msgMeta, const RsGxsGrpMetaData& grpMeta); - - /*! - * convenience function to create sign for groups - * @param signSet signatures are stored here - * @param grpData group data to be signed - * @param grpMeta the meta data for group to be signed - * @return SIGN_SUCCESS for success, SIGN_FAIL for fail, - * SIGN_FAIL_TRY_LATER for Id sign key not avail (but requested), try later - */ - int createGroupSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinaryData& grpData, - RsGxsGrpMetaData& grpMeta); - - /*! - * check meta change is legal - * @return false if meta change is not legal - */ - bool locked_validateGrpMetaChange(GrpLocMetaData&); - - /*! - * Generate a set of keys that can define a GXS group - * @param privatekeySet contains private generated keys - * @param publickeySet contains public generated keys (counterpart of private) - * @param genPublicKeys should publish key pair also be generated - */ - void generateGroupKeys(RsTlvSecurityKeySet& keySet, bool genPublishKeys); - - /*! - * Attempts to validate msg signatures - * @param msg message to be validated - * @param grpFlag the distribution flag for the group the message belongs to - * @param grpFlag the signature flag for the group the message belongs to - * @param grpKeySet the key set user has for the message's group - * @return VALIDATE_SUCCESS for success, VALIDATE_FAIL for fail, - * VALIDATE_ID_SIGN_NOT_AVAIL for Id sign key not avail (but requested) - */ - int validateMsg(RsNxsMsg* msg, const uint32_t& grpFlag, const uint32_t &signFlag, RsTlvSecurityKeySet& grpKeySet); - - /*! - * Attempts to validate group signatures - * @param grp group to be validated - * @return VALIDATE_SUCCESS for success, VALIDATE_FAIL for fail, - * VALIDATE_ID_SIGN_NOT_AVAIL for Id sign key not avail (but requested) - */ - int validateGrp(RsNxsGrp* grp); - - /*! - * Checks flag against a given privacy bit block - * @param pos Determines 8 bit wide privacy block to check - * @param flag the flag to and(&) against - * @param the result of the (bit-block & flag) - */ - bool checkAuthenFlag(const PrivacyBitPos& pos, const uint8_t& flag) const; - - void groupShareKeys(std::list peers); - - static void computeHash(const RsTlvBinaryData& data, RsFileHash& hash); - - /*! - * Checks validation of recently received groups to be - * updated (and updates them, a bit of a misnomer) - */ - void performUpdateValidation(); - - /*! - * Checks if the update is valid (i.e. the new admin signature is by the old admin key) - * @param oldGrp the old group to be updated (must have meta data member initialised) - * @param newGrp the new group that updates the old group (must have meta data member initialised) - * @return - */ - bool updateValid(const RsGxsGrpMetaData& oldGrp, const RsNxsGrp& newGrp) const; - - /*! - * convenience function for checking private publish and admin keys are present - * @param keySet The keys set to split into a private and public set - * @return false, if private admin and publish keys cannot be found, true otherwise - */ - bool checkKeys(const RsTlvSecurityKeySet& keySet); - - /*! - * Message and notification map passed to method - * are cleansed of msgs and ids that already exist in database - * @param msgs messages to be filtered - * @param msgIdsNotify message notification map to be filtered - */ - void removeDeleteExistingMessages(std::list& msgs, GxsMsgReq& msgIdsNotify); - - RsMutex mGenMtx; - RsGxsDataAccess* mDataAccess; - RsGeneralDataService* mDataStore; - RsNetworkExchangeService *mNetService; - RsSerialType *mSerialiser; - /// service type - uint16_t mServType; - RsGixs* mGixs; - - std::vector mReceivedMsgs; - - typedef std::map > NxsGrpPendValidVect; - NxsGrpPendValidVect mGrpPendingValidate; - - std::vector mGrpsToPublish; - typedef std::vector NxsGrpSignPendVect; - - std::map mPublishedGrps ; // keeps track of which group was created using which token - std::map mPublishedMsgs ; // keeps track of which message was created using which token - - std::map mMsgsToPublish; - - std::map mMsgNotify; - std::map mGrpNotify; - - // for loc meta changes - std::map mGrpLocMetaMap; - std::map mMsgLocMetaMap; - - std::vector mNotifications; - - - - /// authentication policy - uint32_t mAuthenPolicy; - - std::map > mMsgPendingSign; - - typedef std::map > NxsMsgPendingVect; - NxsMsgPendingVect mMsgPendingValidate; - - bool mCleaning; - rstime_t mLastClean; - - bool mChecking, mCheckStarted; - rstime_t mLastCheck; - RsGxsIntegrityCheck* mIntegrityCheck; - RsGxsGroupId mNextGroupToCheck ; - -protected: - enum CreateStatus { CREATE_FAIL, CREATE_SUCCESS, CREATE_FAIL_TRY_LATER }; - const uint8_t SIGN_MAX_WAITING_TIME; - // TODO: cleanup this should be an enum! - const uint8_t SIGN_FAIL, SIGN_SUCCESS, SIGN_FAIL_TRY_LATER; - const uint8_t VALIDATE_FAIL, VALIDATE_SUCCESS, VALIDATE_FAIL_TRY_LATER, VALIDATE_MAX_WAITING_TIME; - -private: - - std::vector mGroupUpdates, mPeersGroupUpdate; - - std::vector mGroupUpdatePublish; - std::vector mGroupDeletePublish; - std::vector mMsgDeletePublish; - - std::map > mRoutingClues ; - - friend class RsGxsCleanUp; -}; - -#endif // RSGENEXCHANGE_H diff --git a/libretroshare/src/gxs/rsgixs.h b/libretroshare/src/gxs/rsgixs.h deleted file mode 100644 index 955aea673..000000000 --- a/libretroshare/src/gxs/rsgixs.h +++ /dev/null @@ -1,248 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgixs.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie, Evi-Parker Christopher * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSGIXS_H -#define RSGIXS_H - -#include "gxs/rsgxs.h" -#include "gxs/rsgenexchange.h" - -#include "retroshare/rsgxscircles.h" - -#include "serialiser/rstlvkeys.h" -#include "retroshare/rsids.h" -/*! - * GIXP: General Identity Exchange Service. - * - * As we're always running into troubles with GPG signatures... we are going to - * create a layer of RSA Keys for the following properties: - * - * 1) RSA Keys can be Anonymous, Self-Signed with Pseudonym, Signed by GPG Key. - * To clarify: - * a. This forms a layer of keys stay between GPG and pub/priv publish key ? - * b. Difference between anonymous and pseudonym keys? - * - Anonymous cannot be signed? - * - - * c. To some extent this determines security model of RsGeneralExchangeService - - * - Anonymous & Pseudonym Keys will be shared network-wide (Hop by Hop). - - GPG signed Keys will only be shared if we can validate the signature - (providing similar behaviour to existing GPG Keys). - - GPG signed Keys can optionally be marked for Network-wide sharing. - * 2) These keys can be used anywhere, specifically in the protocols described below. - * 3) These keys can be used to sign, encrypt, verify & decrypt - * 4) Keys will never need to be directly accessed - stored in this class. - * a. I guess can work solely through Id - * b. Use Case: Receivve a message, has a key id, request - * 5) They will be cached locally and exchanged p2p, by pull request. - * 6) This class will use the generalised packet storage for efficient caching & loading. - * 7) Data will be stored encrypted. - */ - - -/****** - * More notes. The ideas above have been crystalised somewhat. - * - * The Identity service will now serve two roles: - * 1) validating msgs. - * 2) reputation of identity. - * - * The identity will be equivalent to a Group Definition. - * and the reputation contained in the group's messages. - * - * - * Group - * MetaData: - * Public Key - * Signatures. (Admin & optional GPG). - * RealData: - * Nickname. - * GPGHash - * - * The GPGHash will allow people to identify the real gpg user behind the identity. - * We must make sure that the Hash input has enough entropy that it cannot be brute-forced (e.g. like password hashes). - * - * The Identity service only has to provide hooks to access the Keys for each group. - * All the key definitions are exactly the same as for GroupMetaData. - * - * The Interface is split into three parts. - * 1) Internal interface used by GXS to verify signatures. - * 2) Internal interface used by GXS to help decide if we get a message or not. - * 3) External interface to access nicknames, generate new identities etc. - * - * The actual implementation will cache frequently used keys and nicknames, - * as these will be used very frequently. - *****/ - -/* Identity Interface for GXS Message Verification. - */ -class RsGixs -{ -public: - // TODO: cleanup this should be an enum! - static const uint32_t RS_GIXS_ERROR_NO_ERROR = 0x0000 ; - static const uint32_t RS_GIXS_ERROR_UNKNOWN = 0x0001 ; - static const uint32_t RS_GIXS_ERROR_KEY_NOT_AVAILABLE = 0x0002 ; - static const uint32_t RS_GIXS_ERROR_SIGNATURE_MISMATCH = 0x0003 ; - - /* Performs/validate a signature with the given key ID. The key must be available, otherwise the signature error - * will report it. Each time a key is used to validate a signature, its usage timestamp is updated. - * - * If force_load is true, the key will be forced loaded from the cache. If not, uncached keys will return - * with error_status=RS_GIXS_SIGNATURE_ERROR_KEY_NOT_AVAILABLE, but will likely be cached on the next call. - */ - - virtual bool signData(const uint8_t *data,uint32_t data_size,const RsGxsId& signer_id,RsTlvKeySignature& signature,uint32_t& signing_error) = 0 ; - virtual bool validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,const RsIdentityUsage& info,uint32_t& signing_error) = 0 ; - - virtual bool encryptData( const uint8_t *clear_data, - uint32_t clear_data_size, - uint8_t *& encrypted_data, - uint32_t& encrypted_data_size, - const RsGxsId& encryption_key_id, - uint32_t& encryption_error, bool force_load) = 0 ; - virtual bool decryptData( const uint8_t *encrypted_data, - uint32_t encrypted_data_size, - uint8_t *& clear_data, uint32_t& clear_data_size, - const RsGxsId& encryption_key_id, - uint32_t& encryption_error, bool force_load) = 0 ; - - virtual bool getOwnIds(std::list &ownIds, bool signed_only = false)=0; - virtual bool isOwnId(const RsGxsId& key_id) = 0 ; - - virtual void timeStampKey(const RsGxsId& key_id,const RsIdentityUsage& reason) = 0 ; - - // Key related interface - used for validating msgs and groups. - /*! - * Use to query a whether given key is available by its key reference - * @param keyref the keyref of key that is being checked for - * @return true if available, false otherwise - */ - virtual bool haveKey(const RsGxsId &id) = 0; - - /*! - * Use to query whether private key member of the given key reference is available - * @param keyref the KeyRef of the key being checked for - * @return true if private key is held here, false otherwise - */ - virtual bool havePrivateKey(const RsGxsId &id) = 0; - - // The fetchKey has an optional peerList.. this is people that had the msg with the signature. - // These same people should have the identity - so we ask them first. - /*! - * Use to request a given key reference - * @param keyref the KeyRef of the key being requested - * @return will - */ - virtual bool requestKey(const RsGxsId &id, const std::list &peers,const RsIdentityUsage& info) = 0; - virtual bool requestPrivateKey(const RsGxsId &id) = 0; - - /*! - * \brief receiveNewIdentity - * Receives a new identity. This is a facility offerred to RsGxsNetService when identities are sent/received by turtle tunnels - */ - virtual bool receiveNewIdentity(RsNxsGrp *identity_grp)=0; - virtual bool retrieveNxsIdentity(const RsGxsId& group_id,RsNxsGrp *& identity_grp)=0; - - /*! - * Retrieves a key identity - * @param keyref - * @return a pointer to a valid profile if successful, otherwise NULL - * - */ - virtual bool getKey(const RsGxsId &id, RsTlvPublicRSAKey& key) = 0; - virtual bool getPrivateKey(const RsGxsId &id, RsTlvPrivateRSAKey& key) = 0; // For signing outgoing messages. - virtual bool getIdDetails(const RsGxsId& id, RsIdentityDetails& details) = 0 ; // Proxy function so that we get p3Identity info from Gxs - - virtual ~RsGixs(); -}; - -class GixsReputation -{ -public: - GixsReputation() :reputation_level(0) {} - - RsGxsId id; - uint32_t reputation_level ; -}; - -struct RsGixsReputation -{ - virtual RsReputationLevel overallReputationLevel( - const RsGxsId& id, uint32_t* identity_flags = nullptr ) = 0; - virtual ~RsGixsReputation(){} -}; - -/*** This Class pulls all the GXS Interfaces together ****/ - -struct RsGxsIdExchange : RsGenExchange, RsGixs -{ - RsGxsIdExchange( - RsGeneralDataService* gds, RsNetworkExchangeService* ns, - RsSerialType* serviceSerialiser, uint16_t mServType, - uint32_t authenPolicy ) - : RsGenExchange( - gds, ns, serviceSerialiser, mServType, this, authenPolicy ) {} -}; - - - - -/* For Circles Too */ - -class RsGcxs -{ - public: - virtual ~RsGcxs(){} - - /* GXS Interface - for working out who can receive */ - virtual bool isLoaded(const RsGxsCircleId &circleId) = 0; - virtual bool loadCircle(const RsGxsCircleId &circleId) = 0; - - virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id,bool& should_encrypt) = 0; - virtual int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id) = 0; - - virtual bool recipients(const RsGxsCircleId &circleId, std::list& friendlist) = 0; - virtual bool recipients(const RsGxsCircleId &circleId, const RsGxsGroupId& destination_group, std::list& idlist) = 0; - - virtual bool isRecipient(const RsGxsCircleId &circleId, const RsGxsGroupId& destination_group, const RsGxsId& id) = 0; - - virtual bool getLocalCircleServerUpdateTS(const RsGxsCircleId& gid,rstime_t& grp_server_update_TS,rstime_t& msg_server_update_TS) =0; -}; - - - -class RsGxsCircleExchange: public RsGenExchange, public RsGcxs -{ -public: - RsGxsCircleExchange(RsGeneralDataService* gds, RsNetworkExchangeService* ns, RsSerialType* serviceSerialiser, - uint16_t mServType, RsGixs* gixs, uint32_t authenPolicy) - :RsGenExchange(gds,ns,serviceSerialiser,mServType, gixs, authenPolicy) { return; } - virtual ~RsGxsCircleExchange() { return; } - - virtual bool getLocalCircleServerUpdateTS(const RsGxsCircleId& gid,rstime_t& grp_server_update_TS,rstime_t& msg_server_update_TS) - { - return RsGenExchange::getGroupServerUpdateTS(RsGxsGroupId(gid),grp_server_update_TS,msg_server_update_TS) ; - } -}; - - -#endif // RSGIXS_H diff --git a/libretroshare/src/gxs/rsgroups.h b/libretroshare/src/gxs/rsgroups.h deleted file mode 100644 index 5a24ac826..000000000 --- a/libretroshare/src/gxs/rsgroups.h +++ /dev/null @@ -1,151 +0,0 @@ -// -// This is a first attempt at managing groups and group permissions -// in libretroshare. -// -// Rules: -// 1 - Groups are handled GPG-wise, and not SSLId wise, but we need to provide functions -// for SSLIds since that's what peers are represented by. -// -// 2 - A peer can be in different groups. That will be useful for e.g. file sharing. -// -// 3 - Global permissions always prevail over permissions given at the group level. For -// instance for discovery between two peers that belong to groups G1 and G2: -// -// | Global discovery flag ON | Global disc flag OFF | -// --------------------+--------------------------+----------------------+ -// Group disc(G1,G2)=1 | Allow | Don't allow | -// Group disc(G1,G2)=0 | Don't allow | Don't allow | -// -// 4 - Binary group permissions are OR-ed between pairs of groups. If peers (A,B) can be matched to -// two different pairs of groups, the flags are combined with an OR. -// -// libretroshare side -// ================== -// We need a matrix for binary group flags, i.e. flags for pair of groups, for: -// -// Turtle traffic: -// * does the turtle traffic can go from peers of a group to another -// * default: yes -// -// Discovery: -// * does the turtle traffic can go from peers of a group to another -// * default: yes. Overriden by discovery status in config. -// -// Public chat lobby advertisement: -// * public lobby coming from peers of a group go to peers of another group -// * default: yes -// -// Relay connexions: -// * allow relay connexions between people of group A and group B. -// -// General Exchange Services: -// * Allow data exchanged from one peers of one group to peers of another group -// -// We need per-group permission flags for: -// -// File download permission: -// * each shared directory belongs to a list of groups -// * each shared directory has a set of DL flags (browsable B,network wide N) for groups and for global. -// * files are listed with unix-like permissions style: -// ---- : file can't be transfered at all. -// bn-- : file is browsable and turtle-able by friends of its groups only. -// b-b- : file is browsable by everybody -// --b- : file is browsable by everybody that does not belong to its groups (can be useful to isolate people in a group) -// -n-- : file is turtle-able by people that belong to its groups only. -// bnbn : file is always accessible in any ways. That's what file sharing is about. Should be the default ;-) -// -// We need to propose some pre-initialized settings to the user, so that he won't have to bother with flags, but we -// need to allow precisely tweaking them as well: -// Directory is -// - Accessible for this group only (allow select a group) -// - Fully shared anonymously -// - [...] -// -// If the shared directory has no groups, than the first two flags are meaningless. -// -// GUI side -// ======== -// - we need a tab in config to manage groups and group flag permission matrix -// - when sharing a directory, the user can act on permissions: setting which groups a -// directory belongs to. -// -// Classes for groups. To be displatched in rstypes.h ? -// - -#pragma once - -typedef RsPeerId SSLId ; -typedef RsPgpId GPGId ; -typedef uint64_t RsGroupId ; - -class RsPeerGroupInfo -{ - public: - RsGroupId group_id ; // Id of the group, should be random and unique in the RS session. - std::string group_name ; // user-defined name of the group ("parents", "friends", etc) - std::set elements ; // people in the group. GPG-wise. -}; - -class GroupFlagsMatrix -{ - public: - // flags - - static const uint32_t GROUP_MATRIX_FLAG_DISCOVERY = 0x1 ; - static const uint32_t GROUP_MATRIX_FLAG_TURTLE = 0x2 ; - static const uint32_t GROUP_MATRIX_FLAG_PUBLIC_LOBBY = 0x4 ; - static const uint32_t GROUP_MATRIX_FLAG_RELAY = 0x8 ; - - // returns/set all flags for a given pair of groups. Used by the - // GUI to draw/modify group flags. - // - uint32_t getGroupFlags(RsGroupId grp1,RsGroupId grp2) const ; - void setGroupFlags(uint32_t flags,RsGroupId grp1,RsGroupId grp2) const ; - - // Returns a given flag for two people in particular. Used by services to - // know what to do or not do. - // - bool groupPermission(uint32_t group_flag,GPGId peer_1,GPGId peer2) const ; - - private: - std::vector _flags ; // vector of size number_of_groups^2 - std::map _group_entries ; // index to read the flags vector. -}; - -// Interface class for Groups. Should go in libretroshare/stc/retroshare/rsgroups.h -// - -class RsGroupManagement -{ - public: - // Group handling - - // Returns false is the group does not exist. Otherwise, fills the GroupInfo struct. - // - virtual bool getGroupInfo(const RsGroupId& id,RsPeerGroupInfo& info) = 0 ; - - // Adds a friend to a group. - virtual bool getGroupInfo(const RsGroupId& id,RsPeerGroupInfo& info) = 0 ; - - // Group permission handling - // - virtual bool allow_TwoPeers_TurtleTraffic (const SSLId& p1,const SSLId& p2) = 0 ; - virtual bool allow_TwoPeers_Discovery (const SSLId& p1,const SSLId& p2) = 0 ; - virtual bool allow_TwoPeers_LobbyAdvertisement(const SSLId& p1,const SSLId& p2) = 0 ; - virtual bool allow_TwoPeers_GeneralExchangeService(const SSLId& p1,const SSLId& p2) = 0 ; - // [...] -}; - -class p3GroupManagement: public RsGroupManagement, public p3Config -{ - public: - // [...] - - private: - std::map _groups ; -}; - -// This is the entry point for external interface. -// -extern RsGroupManagement *rsGroups ; - diff --git a/libretroshare/src/gxs/rsgxs.h b/libretroshare/src/gxs/rsgxs.h deleted file mode 100644 index 696f317ae..000000000 --- a/libretroshare/src/gxs/rsgxs.h +++ /dev/null @@ -1,41 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxs.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSGXS_H -#define RSGXS_H - -#include "gxs/rsgxsdata.h" - -#include -#include - -/* data types used throughout Gxs from netservice to genexchange */ - -typedef std::map > > GxsMsgMetaResult; -typedef std::map > > MsgRelatedMetaResult; - -// Default values that are used throughout GXS code - -static const uint32_t RS_GXS_DEFAULT_MSG_STORE_PERIOD = 86400 * 372 ; // 1 year. Default time for which messages are keps in the database. -static const uint32_t RS_GXS_DEFAULT_MSG_SEND_PERIOD = 86400 * 30 * 1 ; // one month. Default delay after which we don't send messages -static const uint32_t RS_GXS_DEFAULT_MSG_REQ_PERIOD = 86400 * 30 * 1 ; // one month. Default Delay after which we don't request messages - -#endif // RSGXS_H diff --git a/libretroshare/src/gxs/rsgxsdata.cc b/libretroshare/src/gxs/rsgxsdata.cc deleted file mode 100644 index b83096575..000000000 --- a/libretroshare/src/gxs/rsgxsdata.cc +++ /dev/null @@ -1,360 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsdata.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Christopher Evi-Parker, Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "rsgxsdata.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" - -RsGxsGrpMetaData::RsGxsGrpMetaData() -{ - clear(); -} - -uint32_t RsGxsGrpMetaData::serial_size(uint32_t api_version) const -{ - uint32_t s = 8; // header size - - s += mGroupId.serial_size(); - s += mOrigGrpId.serial_size(); - s += mParentGrpId.serial_size(); - s += GetTlvStringSize(mGroupName); - s += 4; // mGroupFlags - s += 4; // mPublishTs - s += 4; // mCircleType - s += 4; // mAuthenFlag - s += mAuthorId.serial_size(); - s += GetTlvStringSize(mServiceString); - s += mCircleId.serial_size(); - s += signSet.TlvSize(); - s += keys.TlvSize(); - - if(api_version == RS_GXS_GRP_META_DATA_VERSION_ID_0002) - s += 4; // mSignFlag - else if(api_version != RS_GXS_GRP_META_DATA_VERSION_ID_0001) - std::cerr << "(EE) wrong/unknown API version " << api_version << " requested in RsGxsGrpMetaData::serial_size()" << std::endl; - - return s; -} - -void RsGxsGrpMetaData::clear(){ - - mGroupId.clear(); - mOrigGrpId.clear(); - mGroupName.clear(); - mGroupFlags = 0; - mPublishTs = 0; - mSignFlags = 0; - mAuthorId.clear(); - - mCircleId.clear(); - mCircleType = 0; - - signSet.TlvClear(); - keys.TlvClear(); - - mServiceString.clear(); - mAuthenFlags = 0; - mParentGrpId.clear(); - - mSubscribeFlags = 0; - - mPop = 0; - mVisibleMsgCount = 0; - mGroupStatus = 0; - mLastPost = 0; - mReputationCutOff = 0; - mGrpSize = 0 ; - - mGroupStatus = 0 ; - mRecvTS = 0; - - mOriginator.clear(); - mInternalCircle.clear(); - mHash.clear() ; -} - -bool RsGxsGrpMetaData::serialise(void *data, uint32_t &pktsize,uint32_t api_version) -{ - uint32_t tlvsize = serial_size(api_version) ; - uint32_t offset = 0; - - if (pktsize < tlvsize) - return false; /* not enough space */ - - pktsize = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, api_version, tlvsize); - -#ifdef GXS_DEBUG - std::cerr << "RsGxsGrpMetaData serialise()" << std::endl; - std::cerr << "RsGxsGrpMetaData serialise(): Header: " << ok << std::endl; - std::cerr << "RsGxsGrpMetaData serialise(): Size: " << tlvsize << std::endl; -#endif - - /* skip header */ - offset += 8; - - ok &= mGroupId.serialise(data, tlvsize, offset); - ok &= mOrigGrpId.serialise(data, tlvsize, offset); - ok &= mParentGrpId.serialise(data, tlvsize, offset); - ok &= SetTlvString(data, tlvsize, &offset, 0, mGroupName); - ok &= setRawUInt32(data, tlvsize, &offset, mGroupFlags); - ok &= setRawUInt32(data, tlvsize, &offset, mPublishTs); - ok &= setRawUInt32(data, tlvsize, &offset, mCircleType); - ok &= setRawUInt32(data, tlvsize, &offset, mAuthenFlags); - ok &= mAuthorId.serialise(data, tlvsize, offset); - ok &= SetTlvString(data, tlvsize, &offset, 0, mServiceString); - ok &= mCircleId.serialise(data, tlvsize, offset); - - ok &= signSet.SetTlv(data, tlvsize, &offset); - ok &= keys.SetTlv(data, tlvsize, &offset); - - if(api_version == RS_GXS_GRP_META_DATA_VERSION_ID_0002) - ok &= setRawUInt32(data, tlvsize, &offset, mSignFlags); // new in API v2. Was previously missing. Kept in the end for backward compatibility - - return ok; -} - -bool RsGxsGrpMetaData::deserialise(void *data, uint32_t &pktsize) -{ - - uint32_t offset = 8; // skip the header - uint32_t rssize = getRsItemSize(data); - - bool ok = true ; - - ok &= rssize == pktsize; - - if(!ok) return false; - - ok &= mGroupId.deserialise(data, pktsize, offset); - ok &= mOrigGrpId.deserialise(data, pktsize, offset); - ok &= mParentGrpId.deserialise(data, pktsize, offset); - ok &= GetTlvString(data, pktsize, &offset, 0, mGroupName); - ok &= getRawUInt32(data, pktsize, &offset, &mGroupFlags); - ok &= getRawUInt32(data, pktsize, &offset, &mPublishTs); - ok &= getRawUInt32(data, pktsize, &offset, &mCircleType); - ok &= getRawUInt32(data, pktsize, &offset, &mAuthenFlags); - - - ok &= mAuthorId.deserialise(data, pktsize, offset); - ok &= GetTlvString(data, pktsize, &offset, 0, mServiceString); - ok &= mCircleId.deserialise(data, pktsize, offset); - ok &= signSet.GetTlv(data, pktsize, &offset); - ok &= keys.GetTlv(data, pktsize, &offset); - - switch(getRsItemId(data)) - { - case RS_GXS_GRP_META_DATA_VERSION_ID_0002: ok &= getRawUInt32(data, pktsize, &offset, &mSignFlags); // current API - break ; - - case RS_GXS_GRP_META_DATA_VERSION_ID_0001: mSignFlags = 0; // old API. Do not leave this uninitialised! - break ; - - default: - std::cerr << "(EE) RsGxsGrpMetaData::deserialise(): ERROR: unknown API version " << std::hex << getRsItemId(data) << std::dec << std::endl; - } - - if(offset != pktsize) - { - std::cerr << "(EE) RsGxsGrpMetaData::deserialise(): ERROR: unmatched size " << offset << ", expected: " << pktsize << std::dec << std::endl; - return false ; - } -#ifdef DROP_NON_CANONICAL_ITEMS - if(mGroupName.length() > RsGxsGrpMetaData::MAX_ALLOWED_STRING_SIZE) - { - std::cerr << "WARNING: Deserialised group with mGroupName.length() = " << mGroupName.length() << ". This is not allowed. This item will be dropped." << std::endl; - return false ; - } - if(mServiceString.length() > RsGxsGrpMetaData::MAX_ALLOWED_STRING_SIZE) - { - std::cerr << "WARNING: Deserialised group with mServiceString.length() = " << mGroupName.length() << ". This is not allowed. This item will be dropped." << std::endl; - return false ; - } -#endif - - return ok; -} - -RsGxsMsgMetaData::RsGxsMsgMetaData(){ - clear(); - //std::cout << "\nrefcount++ : " << ++refcount << std::endl; - return; -} - -RsGxsMsgMetaData::~RsGxsMsgMetaData(){ - //std::cout << "\nrefcount-- : " << --refcount << std::endl; - return; -} - -uint32_t RsGxsMsgMetaData::serial_size() const -{ - - uint32_t s = 8; // header size - - s += mGroupId.serial_size(); - s += mMsgId.serial_size(); - s += mThreadId.serial_size(); - s += mParentId.serial_size(); - s += mOrigMsgId.serial_size(); - s += mAuthorId.serial_size(); - - s += signSet.TlvSize(); - s += GetTlvStringSize(mMsgName); - s += 4; // mPublishTS - s += 4; // mMsgFlags - - return s; -} - -void RsGxsMsgMetaData::clear() -{ - mGroupId.clear(); - mMsgId.clear(); - mThreadId.clear(); - mParentId.clear(); - mOrigMsgId.clear(); - mAuthorId.clear(); - - signSet.TlvClear(); - mMsgName.clear(); - mPublishTs = 0; - mMsgFlags = 0; - - mServiceString.clear(); - mMsgStatus = 0; - mMsgSize = 0; - mChildTs = 0; - recvTS = 0; - mHash.clear(); - validated = false; -} - -bool RsGxsMsgMetaData::serialise(void *data, uint32_t *size) -{ - uint32_t tlvsize = serial_size() ; - uint32_t offset = 0; - - if (*size < tlvsize) - return false; /* not enough space */ - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, RS_GXS_MSG_META_DATA_VERSION_ID_0002, tlvsize); - -#ifdef GXS_DEBUG - std::cerr << "RsGxsGrpMetaData serialise()" << std::endl; - std::cerr << "RsGxsGrpMetaData serialise(): Header: " << ok << std::endl; - std::cerr << "RsGxsGrpMetaData serialise(): Size: " << tlvsize << std::endl; -#endif - - /* skip header */ - offset += 8; - - ok &= mGroupId.serialise(data, *size, offset); - ok &= mMsgId.serialise(data, *size, offset); - ok &= mThreadId.serialise(data, *size, offset); - ok &= mParentId.serialise(data, *size, offset); - ok &= mOrigMsgId.serialise(data, *size, offset); - ok &= mAuthorId.serialise(data, *size, offset); - - ok &= signSet.SetTlv(data, *size, &offset); - ok &= SetTlvString(data, *size, &offset, 0, mMsgName); - ok &= setRawUInt32(data, *size, &offset, mPublishTs); - ok &= setRawUInt32(data, *size, &offset, mMsgFlags); - - return ok; -} - - -bool RsGxsMsgMetaData::deserialise(void *data, uint32_t *size) -{ - uint32_t offset = 8; // skip the header - uint32_t rssize = getRsItemSize(data); - - bool ok = true ; - - ok &= rssize == *size; - - if(!ok) return false; - - ok &= mGroupId.deserialise(data, *size, offset); - ok &= mMsgId.deserialise(data, *size, offset); - ok &= mThreadId.deserialise(data, *size, offset); - ok &= mParentId.deserialise(data, *size, offset); - ok &= mOrigMsgId.deserialise(data, *size, offset); - ok &= mAuthorId.deserialise(data, *size, offset); - - ok &= signSet.GetTlv(data, *size, &offset); - ok &= GetTlvString(data, *size, &offset, 0, mMsgName); - uint32_t t=0; - ok &= getRawUInt32(data, *size, &offset, &t); - mPublishTs = t; - ok &= getRawUInt32(data, *size, &offset, &mMsgFlags); - - return ok; -} - -void RsGxsGrpMetaData::operator =(const RsGroupMetaData& rMeta) -{ - this->mAuthorId = rMeta.mAuthorId; - this->mGroupFlags = rMeta.mGroupFlags; - this->mGroupId = rMeta.mGroupId; - this->mGroupStatus = rMeta.mGroupStatus ; - this->mLastPost = rMeta.mLastPost; - this->mVisibleMsgCount = rMeta.mVisibleMsgCount ; - this->mPop = rMeta.mPop; - this->mPublishTs = rMeta.mPublishTs; - this->mSubscribeFlags = rMeta.mSubscribeFlags; - this->mGroupName = rMeta.mGroupName; - this->mServiceString = rMeta.mServiceString; - this->mSignFlags = rMeta.mSignFlags; - this->mCircleId = rMeta.mCircleId; - this->mCircleType = rMeta.mCircleType; - this->mInternalCircle = rMeta.mInternalCircle; - this->mOriginator = rMeta.mOriginator; - this->mAuthenFlags = rMeta.mAuthenFlags; - //std::cout << "rMeta.mParentGrpId= " <mParentGrpId = rMeta.mParentGrpId; -} - -void RsGxsMsgMetaData::operator =(const RsMsgMetaData& rMeta) -{ - this->mAuthorId = rMeta.mAuthorId; - this->mChildTs = rMeta.mChildTs ; - this->mGroupId = rMeta.mGroupId; - this->mMsgFlags = rMeta.mMsgFlags ; - this->mMsgId = rMeta.mMsgId ; - this->mMsgName = rMeta.mMsgName; - this->mMsgStatus = rMeta.mMsgStatus; - this->mOrigMsgId = rMeta.mOrigMsgId; - this->mParentId = rMeta.mParentId ; - this->mPublishTs = rMeta.mPublishTs ; - this->mThreadId = rMeta.mThreadId; - this->mServiceString = rMeta.mServiceString; -} - - diff --git a/libretroshare/src/gxs/rsgxsdata.h b/libretroshare/src/gxs/rsgxsdata.h deleted file mode 100644 index acc0c71d8..000000000 --- a/libretroshare/src/gxs/rsgxsdata.h +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsdata.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Christopher Evi-Parker, Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSGXSMETA_H -#define RSGXSMETA_H - -#include - -#include "retroshare/rstypes.h" -#include "serialiser/rstlvkeys.h" -#include "util/rstime.h" -#include "rsitems/rsgxsitems.h" - -struct RsGroupMetaData; -struct RsMsgMetaData; - -static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0001 = 0x0000 ; // change this, and keep old values if the content changes -static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0002 = 0xaf01 ; // current API - -static const uint32_t RS_GXS_MSG_META_DATA_VERSION_ID_0002 = 0x0000 ; // current API - -static const uint32_t RS_GXS_GRP_META_DATA_CURRENT_API_VERSION = RS_GXS_GRP_META_DATA_VERSION_ID_0002; - -class RsGxsGrpMetaData -{ -public: - static const int MAX_ALLOWED_STRING_SIZE = 50 ; - - RsGxsGrpMetaData(); - bool deserialise(void *data, uint32_t &pktsize); - bool serialise(void* data, uint32_t &pktsize, uint32_t api_version); - uint32_t serial_size(uint32_t api_version) const; - uint32_t serial_size() const { return serial_size(RS_GXS_GRP_META_DATA_CURRENT_API_VERSION); } - void clear(); - void operator =(const RsGroupMetaData& rMeta); - - //Sort data in same order than serialiser and deserializer - RsGxsGroupId mGroupId; - RsGxsGroupId mOrigGrpId; - RsGxsGroupId mParentGrpId; - std::string mGroupName; - uint32_t mGroupFlags; // GXS_SERV::FLAG_PRIVACY_RESTRICTED | GXS_SERV::FLAG_PRIVACY_PRIVATE | GXS_SERV::FLAG_PRIVACY_PUBLIC - uint32_t mPublishTs; - uint32_t mCircleType; - uint32_t mAuthenFlags; - RsGxsId mAuthorId; - std::string mServiceString; - RsGxsCircleId mCircleId; - RsTlvKeySignatureSet signSet; - RsTlvSecurityKeySet keys; - - uint32_t mSignFlags; - - // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. - - uint32_t mSubscribeFlags; - - uint32_t mPop; // Number of friends who subscribed - uint32_t mVisibleMsgCount; // Max number of messages reported by a single friend (used for unsubscribed groups) - uint32_t mLastPost; // Time stamp of last post (not yet filled) - uint32_t mReputationCutOff; - uint32_t mGrpSize; - - uint32_t mGroupStatus; - uint32_t mRecvTS; - RsPeerId mOriginator; - RsGxsCircleId mInternalCircle; - RsFileHash mHash; -}; - - -class RsGxsMsgMetaData -{ -public: - - explicit RsGxsMsgMetaData(); - ~RsGxsMsgMetaData(); - bool deserialise(void *data, uint32_t *size); - bool serialise(void* data, uint32_t *size); - uint32_t serial_size() const; - void clear(); - void operator =(const RsMsgMetaData& rMeta); - - //Sort data in same order than serialiser and deserializer - RsGxsGroupId mGroupId; - RsGxsMessageId mMsgId; - RsGxsMessageId mThreadId; - RsGxsMessageId mParentId; - RsGxsMessageId mOrigMsgId; - RsGxsId mAuthorId; - - RsTlvKeySignatureSet signSet; - std::string mMsgName; - rstime_t mPublishTs; - uint32_t mMsgFlags; // used by some services (e.g. by forums to store message moderation flags) - - // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. - // normally READ / UNREAD flags. LOCAL Data. - - std::string mServiceString; - uint32_t mMsgStatus; - uint32_t mMsgSize; - rstime_t mChildTs; - uint32_t recvTS; - RsFileHash mHash; - bool validated; -}; - - - - -#endif // RSGXSMETA_H diff --git a/libretroshare/src/gxs/rsgxsdataaccess.cc b/libretroshare/src/gxs/rsgxsdataaccess.cc deleted file mode 100644 index a14248d4f..000000000 --- a/libretroshare/src/gxs/rsgxsdataaccess.cc +++ /dev/null @@ -1,1973 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsdataaccess.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 by Christopher Evi-Parker, Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "util/rstime.h" - -#include "rsgxsutil.h" -#include "rsgxsdataaccess.h" -#include "retroshare/rsgxsflags.h" - -/*********** - * #define DATA_DEBUG 1 - **********/ - -// Debug system to allow to print only for some services (group, Peer, etc) - -#if defined(DATA_DEBUG) -static const uint32_t service_to_print = RS_SERVICE_GXS_TYPE_FORUMS;// use this to allow to this service id only, or 0 for all services - // warning. Numbers should be SERVICE IDS (see serialiser/rsserviceids.h. E.g. 0x0215 for forums) - -class nullstream: public std::ostream {}; - -static std::string nice_time_stamp(rstime_t now,rstime_t TS) -{ - if(TS == 0) - return "Never" ; - else - { - std::ostringstream s; - s << now - TS << " secs ago" ; - return s.str() ; - } -} - -static std::ostream& gxsdatadebug(uint32_t service_type) -{ - static nullstream null ; - - if (service_to_print==0 || service_type == 0 || (service_type == service_to_print)) - return std::cerr << time(NULL) << ":GXSDATASERVICE: " ; - else - return null ; -} - -#define GXSDATADEBUG gxsdatadebug(mDataStore->serviceType()) - -static const std::vector tokenStatusString( { - std::string("FAILED"), - std::string("PENDING"), - std::string("PARTIAL"), - std::string("COMPLETE"), - std::string("DONE"), - std::string("CANCELLED"), - }); - -#endif - -bool operator<(const std::pair& p1,const std::pair& p2) -{ - return p1.second->Options.mPriority <= p2.second->Options.mPriority ; // <= so that new elements with same priority are inserted before -} - -RsGxsDataAccess::RsGxsDataAccess(RsGeneralDataService* ds) : - mDataStore(ds), mDataMutex("RsGxsDataAccess"), mNextToken(0) {} - - -RsGxsDataAccess::~RsGxsDataAccess() -{ - for(auto& it:mRequestQueue) - delete it.second; -} -bool RsGxsDataAccess::requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds ) -{ - if(groupIds.empty()) - { - std::cerr << __PRETTY_FUNCTION__ << " (WW) Group Id list is empty!" << std::endl; - return false; - } - - GxsRequest* req = nullptr; - uint32_t reqType = opts.mReqType; - - if(reqType & GXS_REQUEST_TYPE_GROUP_META) - { - GroupMetaReq* gmr = new GroupMetaReq(); - gmr->mGroupIds = groupIds; - req = gmr; - } - else if(reqType & GXS_REQUEST_TYPE_GROUP_DATA) - { - GroupDataReq* gdr = new GroupDataReq(); - gdr->mGroupIds = groupIds; - req = gdr; - } - else if(reqType & GXS_REQUEST_TYPE_GROUP_IDS) - { - GroupIdReq* gir = new GroupIdReq(); - gir->mGroupIds = groupIds; - req = gir; - } - else if(reqType & GXS_REQUEST_TYPE_GROUP_SERIALIZED_DATA) - { - GroupSerializedDataReq* gir = new GroupSerializedDataReq(); - gir->mGroupIds = groupIds; - req = gir; - } - - if(!req) - { - RsErr() << __PRETTY_FUNCTION__ << " request type not recognised, " << "reqType: " << reqType << std::endl; - return false; - } - - generateToken(token); - -#ifdef DATA_DEBUG - GXSDATADEBUG << "RsGxsDataAccess::requestGroupInfo() gets token: " << token << std::endl; -#endif - - setReq(req, token, ansType, opts); - storeRequest(req); - - return true; -} - -bool RsGxsDataAccess::requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts) -{ - - GxsRequest* req = nullptr; - uint32_t reqType = opts.mReqType; - - if(reqType & GXS_REQUEST_TYPE_GROUP_META) - req = new GroupMetaReq(); - else if(reqType & GXS_REQUEST_TYPE_GROUP_DATA) - req = new GroupDataReq(); - else if(reqType & GXS_REQUEST_TYPE_GROUP_IDS) - req = new GroupIdReq(); - else if(reqType & GXS_REQUEST_TYPE_GROUP_SERIALIZED_DATA) - req = new GroupSerializedDataReq(); - else - { - RsErr() << "RsGxsDataAccess::requestGroupInfo() request type not recognised, type " << reqType << std::endl; - return false; - } - - generateToken(token); -#ifdef DATA_DEBUG - GXSDATADEBUG << "RsGxsDataAccess::requestGroupInfo() gets Token: " << token << std::endl; -#endif - - setReq(req, token, ansType, opts); - storeRequest(req); - - return true; -} - -void RsGxsDataAccess::generateToken(uint32_t &token) -{ - RS_STACK_MUTEX(mDataMutex); - token = mNextToken++; -} - - -bool RsGxsDataAccess::requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const GxsMsgReq &msgIds) -{ - - GxsRequest* req = nullptr; - uint32_t reqType = opts.mReqType; - - // remove all empty grpId entries - GxsMsgReq::const_iterator mit = msgIds.begin(); - std::vector toRemove; - - for(; mit != msgIds.end(); ++mit) - { - if(mit->second.empty()) - toRemove.push_back(mit->first); - } - - std::vector::const_iterator vit = toRemove.begin(); - - GxsMsgReq filteredMsgIds = msgIds; - - for(; vit != toRemove.end(); ++vit) - filteredMsgIds.erase(*vit); - - if(reqType & GXS_REQUEST_TYPE_MSG_META) - { - MsgMetaReq* mmr = new MsgMetaReq(); - mmr->mMsgIds = filteredMsgIds; - req = mmr; - - }else if(reqType & GXS_REQUEST_TYPE_MSG_DATA) - { - MsgDataReq* mdr = new MsgDataReq(); - mdr->mMsgIds = filteredMsgIds; - req = mdr; - - }else if(reqType & GXS_REQUEST_TYPE_MSG_IDS) - { - MsgIdReq* mir = new MsgIdReq(); - mir->mMsgIds = filteredMsgIds; - req = mir; - - } - - if(req == nullptr) - { - RsErr() << "RsGxsDataAccess::requestMsgInfo() request type not recognised, type " << reqType << std::endl; - return false; - }else - { - generateToken(token); -#ifdef DATA_DEBUG - GXSDATADEBUG << "RsGxsDataAccess::requestMsgInfo() gets Token: " << token << std::endl; -#endif - } - - setReq(req, token, ansType, opts); - storeRequest(req); - return true; -} - -bool RsGxsDataAccess::requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list& grpIds) -{ - GxsRequest* req = nullptr; - uint32_t reqType = opts.mReqType; - - std::list::const_iterator lit = grpIds.begin(); - - if(reqType & GXS_REQUEST_TYPE_MSG_META) - { - MsgMetaReq* mmr = new MsgMetaReq(); - - for(; lit != grpIds.end(); ++lit) - mmr->mMsgIds[*lit] = std::set(); - - req = mmr; - } - else if(reqType & GXS_REQUEST_TYPE_MSG_DATA) - { - MsgDataReq* mdr = new MsgDataReq(); - - for(; lit != grpIds.end(); ++lit) - mdr->mMsgIds[*lit] = std::set(); - - req = mdr; - } - else if(reqType & GXS_REQUEST_TYPE_MSG_IDS) - { - MsgIdReq* mir = new MsgIdReq(); - - for(; lit != grpIds.end(); ++lit) - mir->mMsgIds[*lit] = std::set(); - - req = mir; - } - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " request type not recognised, type " << reqType << std::endl; - return false; - }else - { - generateToken(token); -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ << " gets Token: " << token << std::endl; -#endif - } - - setReq(req, token, ansType, opts); - storeRequest(req); - return true; -} - - -void RsGxsDataAccess::requestServiceStatistic(uint32_t& token,const RsTokReqOptions& opts) -{ - ServiceStatisticRequest* req = new ServiceStatisticRequest(); - - generateToken(token); - - if(opts.mReqType != GXS_REQUEST_TYPE_SERVICE_STATS) - { - RsErr() << "Expected opts.mReqType to be GXS_REQUEST_TYPE_SERVICE_STATS requestServiceStatistic()" << std::endl; - return; - } - - setReq(req, token, 0, opts); - storeRequest(req); -} - -void RsGxsDataAccess::requestGroupStatistic(uint32_t& token, const RsGxsGroupId& grpId,const RsTokReqOptions& opts) -{ - GroupStatisticRequest* req = new GroupStatisticRequest(); - req->mGrpId = grpId; - - if(opts.mReqType != GXS_REQUEST_TYPE_GROUP_STATS) - { - RsErr() << "Expected opts.mReqType to be GXS_REQUEST_TYPE_SERVICE_STATS requestServiceStatistic()" << std::endl; - return; - } - - generateToken(token); - - setReq(req, token,0, opts); - storeRequest(req); -} - -bool RsGxsDataAccess::requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::vector &msgIds) -{ - - MsgRelatedInfoReq* req = new MsgRelatedInfoReq(); - req->mMsgIds = msgIds; - - generateToken(token); - - setReq(req, token, ansType, opts); - storeRequest(req); - - return true; -} - - -void RsGxsDataAccess::setReq(GxsRequest* req, uint32_t token, uint32_t ansType, const RsTokReqOptions& opts) const -{ - req->token = token; - req->clientAnswerType = ansType; - req->Options = opts; - return; -} -void RsGxsDataAccess::storeRequest(GxsRequest* req) -{ - RS_STACK_MUTEX(mDataMutex); - req->status = PENDING; - req->reqTime = time(nullptr); - - mRequestQueue.insert(std::make_pair(req->token,req)); - mPublicToken[req->token] = PENDING; - -#ifdef DATA_DEBUG - GXSDATADEBUG << "Stored request token=" << req->token << " priority = " << static_cast(req->Options.mPriority) << " Current request Queue is:" ; - for(auto it(mRequestQueue.begin());it!=mRequestQueue.end();++it) - GXSDATADEBUG << it->first << " (p=" << static_cast(req->Options.mPriority) << ") "; - GXSDATADEBUG << std::endl; - GXSDATADEBUG << "PublicToken size: " << mPublicToken.size() << " Completed requests waiting for client: " << mCompletedRequests.size() << std::endl; -#endif -} - -RsTokenService::GxsRequestStatus RsGxsDataAccess::requestStatus(uint32_t token) -{ - RsTokenService::GxsRequestStatus status; - uint32_t reqtype; - uint32_t anstype; - rstime_t ts; - - if (!checkRequestStatus(token, status, reqtype, anstype, ts)) - return RsTokenService::FAILED; - - return status; -} - -bool RsGxsDataAccess::cancelRequest(const uint32_t& token) -{ - RsStackMutex stack(mDataMutex); /****** LOCKED *****/ - - GxsRequest* req = locked_retrieveCompletedRequest(token); - if (!req) - { - return false; - } - - req->status = CANCELLED; - - return true; -} - -bool RsGxsDataAccess::clearRequest(const uint32_t& token) -{ - RS_STACK_MUTEX(mDataMutex); - return locked_clearRequest(token); -} - -bool RsGxsDataAccess::locked_clearRequest(const uint32_t& token) -{ - auto it = mCompletedRequests.find(token); - - if(it == mCompletedRequests.end()) - return false; - - delete it->second; - mCompletedRequests.erase(it); - - auto it2 = mPublicToken.find(token); - if(it2 != mPublicToken.end()) - mPublicToken.erase(it2); - -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": Removing public token " << token << ". Completed tokens: " << mCompletedRequests.size() << " Size of mPublicToken: " << mPublicToken.size() << std::endl; -#endif - return true; -} - -bool RsGxsDataAccess::getGroupSummary(const uint32_t& token, std::list >& groupInfo) -{ - RS_STACK_MUTEX(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve group summary" << std::endl; - return false; - } - - GroupMetaReq* gmreq = dynamic_cast(req); - - if(gmreq) - { - groupInfo = gmreq->mGroupMetaData; - gmreq->mGroupMetaData.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed cast" << std::endl; - return false; - } - locked_clearRequest(token); - - return true; -} - -bool RsGxsDataAccess::getGroupData(const uint32_t& token, std::list& grpData) -{ - RS_STACK_MUTEX(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << "RsGxsDataAccess::getGroupData() Unable to retrieve group data" << std::endl; - return false; - } - - GroupDataReq* gmreq = dynamic_cast(req); - GroupSerializedDataReq* gsreq = dynamic_cast(req); - - if(gsreq) - { - grpData.swap(gsreq->mGroupData); - gsreq->mGroupData.clear(); - } - else if(gmreq) - { - grpData.swap(gmreq->mGroupData); - gmreq->mGroupData.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed cast req->reqType: " << req->reqType << std::endl; - return false; - } - locked_clearRequest(token); - - return true; -} - -bool RsGxsDataAccess::getMsgData(const uint32_t& token, NxsMsgDataResult& msgData) -{ - - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve group data" << std::endl; - return false; - } - - MsgDataReq* mdreq = dynamic_cast(req); - - if(mdreq) - { - msgData.swap(mdreq->mMsgData); - mdreq->mMsgData.clear(); - } - else - { - RsErr() << "RsGxsDataAccess::getMsgData() Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - - return true; -} - -bool RsGxsDataAccess::getMsgRelatedData(const uint32_t& token, NxsMsgRelatedDataResult& msgData) -{ - - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve group data" << std::endl; - return false; - } - MsgRelatedInfoReq* mrireq = dynamic_cast(req); - - if(req->Options.mReqType != GXS_REQUEST_TYPE_MSG_RELATED_DATA) - return false; - - if(mrireq) - { - msgData.swap(mrireq->mMsgDataResult); - mrireq->mMsgDataResult.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed caste" << std::endl; - return false; - } - - locked_clearRequest(token); - - return true; -} - -bool RsGxsDataAccess::getMsgSummary(const uint32_t& token, GxsMsgMetaResult& msgInfo) -{ - - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve group data" << std::endl; - return false; - } - MsgMetaReq* mmreq = dynamic_cast(req); - - if(mmreq) - { - msgInfo.swap(mmreq->mMsgMetaData); - mmreq->mMsgMetaData.clear(); - } - else - { - RsErr() << " Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} - -bool RsGxsDataAccess::getMsgRelatedSummary(const uint32_t &token, MsgRelatedMetaResult &msgMeta) -{ - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve message summary" << std::endl; - return false; - } - if(req->Options.mReqType != GXS_REQUEST_TYPE_MSG_RELATED_META) - return false; - - MsgRelatedInfoReq* mrireq = dynamic_cast(req); - - if(mrireq) - { - msgMeta.swap(mrireq->mMsgMetaResult); - mrireq->mMsgMetaResult.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} - - -bool RsGxsDataAccess::getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult &msgIds) -{ - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve message data" << std::endl; - return false; - } - if(req->Options.mReqType != GXS_REQUEST_TYPE_MSG_RELATED_IDS) - return false; - - MsgRelatedInfoReq* mrireq = dynamic_cast(req); - - if(mrireq) - { - msgIds.swap(mrireq->mMsgIdResult); - mrireq->mMsgIdResult.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} - -bool RsGxsDataAccess::getMsgIdList(const uint32_t& token, GxsMsgIdResult& msgIds) -{ - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve msg Ids" << std::endl; - return false; - } - MsgIdReq* mireq = dynamic_cast(req); - - if(mireq) - { - msgIds.swap(mireq->mMsgIdResult); - mireq->mMsgIdResult.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed cast" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} - -bool RsGxsDataAccess::getGroupList(const uint32_t& token, std::list& groupIds) -{ - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve group Ids, Request does not exist" << std::endl; - return false; - } - GroupIdReq* gireq = dynamic_cast(req); - - if(gireq) - { - groupIds.swap(gireq->mGroupIdResult); - gireq->mGroupIdResult.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} - -bool RsGxsDataAccess::getGroupStatistic(const uint32_t &token, GxsGroupStatistic &grpStatistic) -{ - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << "RsGxsDataAccess::getGroupStatistic() Unable to retrieve grp stats" << std::endl; - return false; - } - GroupStatisticRequest* gsreq = dynamic_cast(req); - - if(gsreq) - grpStatistic = gsreq->mGroupStatistic; - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} - -bool RsGxsDataAccess::getServiceStatistic(const uint32_t &token, GxsServiceStatistic &servStatistic) -{ - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve service stats" << std::endl; - return false; - } - ServiceStatisticRequest* ssreq = dynamic_cast(req); - - if(ssreq) - servStatistic = ssreq->mServiceStatistic; - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} -GxsRequest* RsGxsDataAccess::locked_retrieveCompletedRequest(const uint32_t& token) -{ - auto it = mCompletedRequests.find(token) ; - - if(it == mCompletedRequests.end()) - return nullptr; - - return it->second; -} - -#define MAX_REQUEST_AGE 120 // 2 minutes - -void RsGxsDataAccess::processRequests() -{ - // process requests - - while (!mRequestQueue.empty()) - { -#ifdef DATA_DEBUG - dumpTokenQueues(); -#endif - // Extract the first elements from the request queue. cleanup all other elements marked at terminated. - - GxsRequest* req = nullptr; - { - RsStackMutex stack(mDataMutex); /******* LOCKED *******/ - rstime_t now = time(nullptr); // this is ok while in the loop below - - while(!mRequestQueue.empty() && req == nullptr) - { - if(now > mRequestQueue.begin()->second->reqTime + MAX_REQUEST_AGE) - { - mPublicToken[mRequestQueue.begin()->second->token] = CANCELLED; - delete mRequestQueue.begin()->second; - mRequestQueue.erase(mRequestQueue.begin()); - continue; - } - - switch( mRequestQueue.begin()->second->status ) - { - case PARTIAL: - RsErr() << "Found partial request in mRequestQueue. This is a bug." << std::endl; // fallthrough - case COMPLETE: - case DONE: - case FAILED: - case CANCELLED: -#ifdef DATA_DEBUG - GXSDATADEBUG << " Service " << std::hex << mDataStore->serviceType() << std::dec << ": request " << mRequestQueue.begin()->second->token << ": status = " << mRequestQueue.begin()->second->status << ": removing from the RequestQueue" << std::endl; -#endif - delete mRequestQueue.begin()->second; - mRequestQueue.erase(mRequestQueue.begin()); - continue; - break; - case PENDING: - req = mRequestQueue.begin()->second; - req->status = PARTIAL; - mRequestQueue.erase(mRequestQueue.begin()); // remove it right away from the waiting queue. - break; - } - - } - } // END OF MUTEX. - - if (!req) - break; - - GroupMetaReq* gmr; - GroupDataReq* gdr; - GroupIdReq* gir; - - MsgMetaReq* mmr; - MsgDataReq* mdr; - MsgIdReq* mir; - MsgRelatedInfoReq* mri; - GroupStatisticRequest* gsr; - GroupSerializedDataReq* grr; - ServiceStatisticRequest* ssr; - -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": Processing request: " << req->token << " Status: " << req->status << " ReqType: " << req->reqType << " Age: " << time(nullptr) - req->reqTime << std::endl; -#endif - - /* PROCESS REQUEST! */ - bool ok = false; - - if((gmr = dynamic_cast(req)) != nullptr) - { - ok = getGroupSummary(gmr); - } - else if((gdr = dynamic_cast(req)) != nullptr) - { - ok = getGroupData(gdr); - } - else if((gir = dynamic_cast(req)) != nullptr) - { - ok = getGroupList(gir); - } - else if((mmr = dynamic_cast(req)) != nullptr) - { - ok = getMsgSummary(mmr); - } - else if((mdr = dynamic_cast(req)) != nullptr) - { - ok = getMsgData(mdr); - } - else if((mir = dynamic_cast(req)) != nullptr) - { - ok = getMsgIdList(mir); - } - else if((mri = dynamic_cast(req)) != nullptr) - { - ok = getMsgRelatedInfo(mri); - } - else if((gsr = dynamic_cast(req)) != nullptr) - { - ok = getGroupStatistic(gsr); - } - else if((ssr = dynamic_cast(req)) != nullptr) - { - ok = getServiceStatistic(ssr); - } - else if((grr = dynamic_cast(req)) != nullptr) - { - ok = getGroupSerializedData(grr); - } - else - RsErr() << __PRETTY_FUNCTION__ << " Failed to process request, token: " << req->token << std::endl; - - // We cannot easily remove the request here because the queue may have more elements now and mRequestQueue.begin() is not necessarily the same element. - // but we mark it as COMPLETE/FAILED so that it will be removed in the next loop. - { - RsStackMutex stack(mDataMutex); /******* LOCKED *******/ - - if(ok) - { - // When the request is complete, we move it to the complete list, so that the caller can easily retrieve the request data - -#ifdef DATA_DEBUG - GXSDATADEBUG << " Service " << std::hex << mDataStore->serviceType() << std::dec << ": Request completed successfully. Marking as COMPLETE." << std::endl; -#endif - req->status = COMPLETE ; - mCompletedRequests[req->token] = req; - mPublicToken[req->token] = COMPLETE; - } - else - { - mPublicToken[req->token] = FAILED; - delete req;//req belongs to no one now -#ifdef DATA_DEBUG - GXSDATADEBUG << " Service " << std::hex << mDataStore->serviceType() << std::dec << ": Request failed. Marking as FAILED." << std::endl; -#endif - } - } // END OF MUTEX. - - } -} - - - -bool RsGxsDataAccess::getGroupSerializedData(GroupSerializedDataReq* req) -{ - std::map grpData; - std::list grpIdsOut; - - getGroupList(req->mGroupIds, req->Options, grpIdsOut); - - if(grpIdsOut.empty()) - return true; - - - for(std::list::iterator lit = grpIdsOut.begin();lit != grpIdsOut.end();++lit) - grpData[*lit] = nullptr; - - bool ok = mDataStore->retrieveNxsGrps(grpData, true); - req->mGroupData.clear(); - - std::map::iterator mit = grpData.begin(); - - for(; mit != grpData.end(); ++mit) - req->mGroupData.push_back(mit->second) ; - - return ok; -} -bool RsGxsDataAccess::getGroupData(GroupDataReq* req) -{ - std::map grpData; - std::list grpIdsOut; - - getGroupList(req->mGroupIds, req->Options, grpIdsOut); - - if(grpIdsOut.empty()) - return true; - - std::list::iterator lit = grpIdsOut.begin(), - lit_end = grpIdsOut.end(); - - for(; lit != lit_end; ++lit) - { - grpData[*lit] = nullptr; - } - - bool ok = mDataStore->retrieveNxsGrps(grpData, true); - - std::map::iterator mit = grpData.begin(); - for(; mit != grpData.end(); ++mit) - req->mGroupData.push_back(mit->second); - - return ok; -} - -bool RsGxsDataAccess::getGroupSummary(GroupMetaReq* req) -{ - - RsGxsGrpMetaTemporaryMap grpMeta; - std::list grpIdsOut; - - getGroupList(req->mGroupIds, req->Options, grpIdsOut); - - if(grpIdsOut.empty()) - return true; - - for(auto lit = grpIdsOut.begin();lit != grpIdsOut.end(); ++lit) - grpMeta[*lit] = nullptr; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - for(auto mit = grpMeta.begin(); mit != grpMeta.end(); ++mit) - req->mGroupMetaData.push_back(mit->second); - - return true; -} - -bool RsGxsDataAccess::getGroupList(GroupIdReq* req) -{ - return getGroupList(req->mGroupIds, req->Options, req->mGroupIdResult); -} - -bool RsGxsDataAccess::getGroupList(const std::list& grpIdsIn, const RsTokReqOptions& opts, std::list& grpIdsOut) -{ - RsGxsGrpMetaTemporaryMap grpMeta; - - for(auto lit = grpIdsIn.begin(); lit != grpIdsIn.end(); ++lit) - grpMeta[*lit] = nullptr; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - for(auto mit = grpMeta.begin() ; mit != grpMeta.end(); ++mit) - grpIdsOut.push_back(mit->first); - - filterGrpList(grpIdsOut, opts, grpMeta); - - return true; -} - -bool RsGxsDataAccess::getMsgData(MsgDataReq* req) -{ - GxsMsgReq msgIdOut; - - const RsTokReqOptions& opts(req->Options); - - // filter based on options - getMsgIdList(req->mMsgIds, opts, msgIdOut); - - // If the list is empty because of filtering do not retrieve from DB - if((opts.mMsgFlagMask || opts.mStatusMask) && msgIdOut.empty()) - return true; - - mDataStore->retrieveNxsMsgs(msgIdOut, req->mMsgData, true); - return true; -} - - -bool RsGxsDataAccess::getMsgSummary(MsgMetaReq* req) -{ - GxsMsgReq msgIdOut; - - const RsTokReqOptions& opts(req->Options); - - // filter based on options - getMsgMetaDataList(req->mMsgIds, opts, req->mMsgMetaData); - -// // If the list is empty because of filtering do not retrieve from DB -// if((opts.mMsgFlagMask || opts.mStatusMask) && msgIdOut.empty()) -// return true; -// -// mDataStore->retrieveGxsMsgMetaData(msgIdOut, req->mMsgMetaData); - - return true; -} - -bool RsGxsDataAccess::getMsgMetaDataList( const GxsMsgReq& msgIds, const RsTokReqOptions& opts, GxsMsgMetaResult& result ) -{ - // First get all message metas, then filter out the ones we want to keep. - result.clear(); - mDataStore->retrieveGxsMsgMetaData(msgIds, result); - - /* CASEs this handles. - * Input is groupList + Flags. - * 1) No Flags => All Messages in those Groups. - * - */ -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgList()" << std::endl; -#endif - - bool onlyOrigMsgs = false; - bool onlyLatestMsgs = false; - bool onlyThreadHeadMsgs = false; - - // Can only choose one of these two. - if (opts.mOptions & RS_TOKREQOPT_MSG_ORIGMSG) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgList() MSG_ORIGMSG" << std::endl; -#endif - onlyOrigMsgs = true; - } - else if (opts.mOptions & RS_TOKREQOPT_MSG_LATEST) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgList() MSG_LATEST" << std::endl; -#endif - onlyLatestMsgs = true; - } - - if (opts.mOptions & RS_TOKREQOPT_MSG_THREAD) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgList() MSG_THREAD" << std::endl; -#endif - onlyThreadHeadMsgs = true; - } - - GxsMsgMetaResult::iterator meta_it; - - for(meta_it = result.begin(); meta_it != result.end(); ++meta_it) - { - //const RsGxsGroupId& grpId = meta_it->first; - - //auto& filter( metaFilter[grpId] ); // does the initialization of metaFilter[grpId] and avoids further O(log(n)) calls - - auto& metaV = meta_it->second; - - if (onlyLatestMsgs) // if we only consider latest messages, we need to first filter out messages with "children" - { - // The strategy is the following: for each msg we only know its direct ancestor. So we build a map to be able to find for a given message - // which messages derive from it. - // Then when this map is fuly build, we follow this map and every message that has no direct follow up will be kept. - // Because msgs are stored in a std::vector we build a map to convert each vector to its position in metaV. - - std::vector keep(metaV.size(),true); // this vector will tell wether we keep or not a given Meta - std::map index_in_metaV; // holds the index of each group Id in metaV - - for(uint32_t i=0;imMsgId] = i; - - // Now loop once over message Metas and see if they have a parent. If yes, then mark the parent to be discarded. - - for(uint32_t i=0;imOrigMsgId.isNull() && metaV[i]->mOrigMsgId != metaV[i]->mMsgId) // this one is a follow up - { - auto it = index_in_metaV.find(metaV[i]->mOrigMsgId); - - if(it != index_in_metaV.end()) - keep[it->second] = false; - else - std::cerr << "Found a msg that has a parent that is not locally known. Not an error anyway." << std::endl; - - } - - // Finally we just discard the messages for which the keep flag has been set to false. - - for(uint32_t i=0;i TS. - std::map > origMsgTs; - - for(uint32_t i=0;imParentId.isNull())) - { - delete msgMeta; - metaV[i] = nullptr; - continue; - } - - auto oit = origMsgTs.find(msgMeta->mOrigMsgId); - - bool addMsg = false; - if (oit != origMsgTs.end()) - { - if(oit->second.second > msgMeta->mPublishTs) - { -#ifdef DATA_DEBUG - std::cerr << "RsGxsDataAccess::getMsgList() Found New OrigMsgId: "; - std::cerr << msgMeta->mOrigMsgId; - std::cerr << " MsgId: " << msgMeta->mMsgId; - std::cerr << " TS: " << msgMeta->mPublishTs; - std::cerr << std::endl; -#endif - origMsgTs[msgMeta->mOrigMsgId] = std::make_pair(msgMeta->mMsgId, msgMeta->mPublishTs); // add as latest. (overwriting if necessary) - } - } - else - { - delete msgMeta; - metaV[i] = nullptr; - continue; - } - - - } - - // Add the discovered Latest Msgs. - for(auto oit = origMsgTs.begin(); oit != origMsgTs.end(); ++oit) - { - msgIdsOut[grpId].insert(oit->second.first); - } -#endif - - for(uint32_t i=0;imParentId.isNull()) - { - //delete msgMeta; - metaV[i] = nullptr; - continue; - } - - if (onlyOrigMsgs && !msgMeta->mOrigMsgId.isNull() && msgMeta->mMsgId != msgMeta->mOrigMsgId) - { - //delete msgMeta; - metaV[i] = nullptr; - continue; - } - } - } - - // collapse results while keeping the order, eliminating empty slots - - for(auto it(result.begin());it!=result.end();++it) - { - uint32_t j=0; // j is the end of the cleaned-up tab, at the first available place - - for(uint32_t i=0;isecond.size();++i) // i is the index in the tab possibly containing nullptr's - if(it->second[i] != nullptr) - { - it->second[j] = it->second[i]; // move the pointer to the first available place - ++j; - } - - it->second.resize(j); // normally all pointers have been moved forward so there is nothing to delete here. - } - - // filterMsgIdList(msgIdsOut, opts, metaFilter); // this call is absurd: we already have in metaFilter the content we want. - - //metaFilter.clear(); - - // delete meta data - //cleanseMsgMetaMap(result); - - return true; -} - -bool RsGxsDataAccess::getMsgIdList( const GxsMsgReq& msgIds, const RsTokReqOptions& opts, GxsMsgReq& msgIdsOut ) -{ - GxsMsgMetaResult result; - - getMsgMetaDataList( msgIds, opts, result ); - - // extract MessageIds - - msgIdsOut.clear(); - - for(auto it(result.begin());it!=result.end();++it) - { - auto& id_set(msgIdsOut[it->first]); - - for(uint32_t i=0;isecond.size();++i) - id_set.insert(it->second[i]->mMsgId); - } - - // delete meta data - //cleanseMsgMetaMap(result); - - return true; -} - -bool RsGxsDataAccess::getMsgRelatedInfo(MsgRelatedInfoReq *req) -{ - /* CASEs this handles. - * Input is msgList + Flags. - * 1) No Flags => return nothing - */ -#ifdef DATA_DEBUG - GXSDATADEBUG << "RsGxsDataAccess::getMsgRelatedList()" << std::endl; -#endif - - const RsTokReqOptions& opts = req->Options; - - bool onlyLatestMsgs = false; - bool onlyAllVersions = false; - bool onlyChildMsgs = false; - bool onlyThreadMsgs = false; - - if (opts.mOptions & RS_TOKREQOPT_MSG_LATEST) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgRelatedList() MSG_LATEST" << std::endl; -#endif - onlyLatestMsgs = true; - } - else if (opts.mOptions & RS_TOKREQOPT_MSG_VERSIONS) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgRelatedList() MSG_VERSIONS" << std::endl; -#endif - onlyAllVersions = true; - } - - if (opts.mOptions & RS_TOKREQOPT_MSG_PARENT) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgRelatedList() MSG_PARENTS" << std::endl; -#endif - onlyChildMsgs = true; - } - - if (opts.mOptions & RS_TOKREQOPT_MSG_THREAD) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgRelatedList() MSG_THREAD" << std::endl; -#endif - onlyThreadMsgs = true; - } - - if(onlyAllVersions && onlyChildMsgs) - { - RS_ERR("Incompatible FLAGS (VERSIONS & PARENT)"); - return false; - } - - if(onlyAllVersions && onlyThreadMsgs) - { - RS_ERR("Incompatible FLAGS (VERSIONS & THREAD)"); - return false; - } - - if((!onlyLatestMsgs) && onlyChildMsgs) - { - RS_ERR("Incompatible FLAGS (!LATEST & PARENT)"); - return false; - } - - if((!onlyLatestMsgs) && onlyThreadMsgs) - { - RS_ERR("Incompatible FLAGS (!LATEST & THREAD)"); - return false; - } - - if(onlyChildMsgs && onlyThreadMsgs) - { - RS_ERR("Incompatible FLAGS (PARENT & THREAD)"); - return false; - } - - if( (!onlyLatestMsgs) && (!onlyAllVersions) && (!onlyChildMsgs) && - (!onlyThreadMsgs) ) - { - RS_WARN("NO FLAGS -> SIMPLY RETURN nothing"); - return true; - } - - for(auto vit_msgIds(req->mMsgIds.begin()); vit_msgIds != req->mMsgIds.end(); ++vit_msgIds) - { - MsgMetaFilter filterMap; - - - const RsGxsGrpMsgIdPair& grpMsgIdPair = *vit_msgIds; - - // get meta data for all in group - GxsMsgMetaResult result; - GxsMsgReq msgIds; - msgIds.insert(std::make_pair(grpMsgIdPair.first, std::set())); - mDataStore->retrieveGxsMsgMetaData(msgIds, result); - auto& metaV = result[grpMsgIdPair.first]; - - // msg id to relate to - const RsGxsMessageId& msgId = grpMsgIdPair.second; - const RsGxsGroupId& grpId = grpMsgIdPair.first; - - std::set outMsgIds; - - std::shared_ptr origMeta; - - for(auto vit_meta = metaV.begin(); vit_meta != metaV.end(); ++vit_meta) - if(msgId == (*vit_meta)->mMsgId) - { - origMeta = *vit_meta; - break; - } - - if(!origMeta) - { - RS_ERR("Cannot find meta of msgId: ", msgId, " to relate to"); - return false; - } - - const RsGxsMessageId& origMsgId = origMeta->mOrigMsgId; - auto& metaMap = filterMap[grpId]; - - if (onlyLatestMsgs) - { - if (onlyChildMsgs || onlyThreadMsgs) - { - // RUN THROUGH ALL MSGS... in map origId -> TS. - std::map > origMsgTs; - std::map >::iterator oit; - - for(auto vit_meta = metaV.begin(); vit_meta != metaV.end(); ++vit_meta) - { - auto meta = *vit_meta; - - // skip msgs that aren't children. - if (onlyChildMsgs) - { - if (meta->mParentId != origMsgId) - { - continue; - } - } - else /* onlyThreadMsgs */ - { - if (meta->mThreadId != msgId) - { - continue; - } - } - - - oit = origMsgTs.find(meta->mOrigMsgId); - - bool addMsg = false; - if (oit == origMsgTs.end()) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "RsGxsDataAccess::getMsgRelatedList() Found New OrigMsgId: " - << meta->mOrigMsgId - << " MsgId: " << meta->mMsgId - << " TS: " << meta->mPublishTs - << std::endl; -#endif - - addMsg = true; - } - // check timestamps. - else if (oit->second.second < meta->mPublishTs) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgRelatedList() Found Later Msg. OrigMsgId: " - << meta->mOrigMsgId - << " MsgId: " << meta->mMsgId - << " TS: " << meta->mPublishTs - << std::endl; -#endif - - addMsg = true; - } - - if (addMsg) - { - // add as latest. (overwriting if necessary) - origMsgTs[meta->mOrigMsgId] = std::make_pair(meta->mMsgId, meta->mPublishTs); - metaMap.insert(std::make_pair(meta->mMsgId, meta)); - } - } - - // Add the discovered Latest Msgs. - for(oit = origMsgTs.begin(); oit != origMsgTs.end(); ++oit) - { - outMsgIds.insert(oit->second.first); - } - } - else - { - - /* first guess is potentially better than Orig (can't be worse!) */ - rstime_t latestTs = 0; - RsGxsMessageId latestMsgId; - std::shared_ptr latestMeta; - - for(auto vit_meta = metaV.begin(); vit_meta != metaV.end(); ++vit_meta) - if ((*vit_meta)->mOrigMsgId == origMsgId) - { - if ((*vit_meta)->mPublishTs > latestTs) - { - latestTs = (*vit_meta)->mPublishTs; - latestMsgId = (*vit_meta)->mMsgId; - latestMeta = (*vit_meta); - } - } - - outMsgIds.insert(latestMsgId); - metaMap.insert(std::make_pair(latestMsgId, latestMeta)); - } - } - else if (onlyAllVersions) - { - for(auto vit_meta = metaV.begin(); vit_meta != metaV.end(); ++vit_meta) - if ((*vit_meta)->mOrigMsgId == origMsgId) - { - outMsgIds.insert((*vit_meta)->mMsgId); - metaMap.insert(std::make_pair((*vit_meta)->mMsgId, (*vit_meta))); - } - } - - GxsMsgIdResult filteredOutMsgIds; - filteredOutMsgIds[grpId] = outMsgIds; - filterMsgIdList(filteredOutMsgIds, opts, filterMap); - - if(!filteredOutMsgIds[grpId].empty()) - { - if(req->Options.mReqType == GXS_REQUEST_TYPE_MSG_RELATED_IDS) - { - req->mMsgIdResult[grpMsgIdPair] = filteredOutMsgIds[grpId]; - } - else if(req->Options.mReqType == GXS_REQUEST_TYPE_MSG_RELATED_META) - { - GxsMsgMetaResult metaResult; - mDataStore->retrieveGxsMsgMetaData(filteredOutMsgIds, metaResult); - req->mMsgMetaResult[grpMsgIdPair] = metaResult[grpId]; - } - else if(req->Options.mReqType == GXS_REQUEST_TYPE_MSG_RELATED_DATA) - { - GxsMsgResult msgResult; - mDataStore->retrieveNxsMsgs(filteredOutMsgIds, msgResult, true); - req->mMsgDataResult[grpMsgIdPair] = msgResult[grpId]; - } - } - - outMsgIds.clear(); - filteredOutMsgIds.clear(); - } - return true; -} - -bool RsGxsDataAccess::getGroupStatistic(GroupStatisticRequest *req) -{ - // filter based on options - GxsMsgIdResult metaReq; - metaReq[req->mGrpId] = std::set(); - GxsMsgMetaResult metaResult; - mDataStore->retrieveGxsMsgMetaData(metaReq, metaResult); - - const auto& msgMetaV_it = metaResult.find(req->mGrpId); - - if(msgMetaV_it == metaResult.end()) - return false; - - const auto& msgMetaV(msgMetaV_it->second); - - req->mGroupStatistic.mGrpId = req->mGrpId; - req->mGroupStatistic.mNumMsgs = msgMetaV.size(); - req->mGroupStatistic.mTotalSizeOfMsgs = 0; - req->mGroupStatistic.mNumThreadMsgsNew = 0; - req->mGroupStatistic.mNumThreadMsgsUnread = 0; - req->mGroupStatistic.mNumChildMsgsNew = 0; - req->mGroupStatistic.mNumChildMsgsUnread = 0; - - std::set obsolete_msgs ; // stored message ids that are referred to as older versions of an existing message - - for(uint32_t i = 0; i < msgMetaV.size(); ++i) - if(!msgMetaV[i]->mOrigMsgId.isNull() && msgMetaV[i]->mOrigMsgId!=msgMetaV[i]->mMsgId) - obsolete_msgs.insert(msgMetaV[i]->mOrigMsgId); - - for(uint32_t i = 0; i < msgMetaV.size(); ++i) - { - const auto& m = msgMetaV[i]; - req->mGroupStatistic.mTotalSizeOfMsgs += m->mMsgSize + m->serial_size(); - - if(obsolete_msgs.find(m->mMsgId) != obsolete_msgs.end()) // skip obsolete messages. - continue; - - if (IS_MSG_NEW(m->mMsgStatus)) - { - if (m->mParentId.isNull()) - ++req->mGroupStatistic.mNumThreadMsgsNew; - else - ++req->mGroupStatistic.mNumChildMsgsNew; - } - if (IS_MSG_UNREAD(m->mMsgStatus)) - { - if (m->mParentId.isNull()) - ++req->mGroupStatistic.mNumThreadMsgsUnread; - else - ++req->mGroupStatistic.mNumChildMsgsUnread; - } - } - - return true; -} - -// potentially very expensive! -bool RsGxsDataAccess::getServiceStatistic(ServiceStatisticRequest *req) -{ - RsGxsGrpMetaTemporaryMap grpMeta ; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - req->mServiceStatistic.mNumGrps = grpMeta.size(); - req->mServiceStatistic.mNumMsgs = 0; - req->mServiceStatistic.mSizeOfGrps = 0; - req->mServiceStatistic.mSizeOfMsgs = 0; - req->mServiceStatistic.mNumGrpsSubscribed = 0; - req->mServiceStatistic.mNumThreadMsgsNew = 0; - req->mServiceStatistic.mNumThreadMsgsUnread = 0; - req->mServiceStatistic.mNumChildMsgsNew = 0; - req->mServiceStatistic.mNumChildMsgsUnread = 0; - - for(auto mit = grpMeta.begin(); mit != grpMeta.end(); ++mit) - { - const auto& m = mit->second; - req->mServiceStatistic.mSizeOfGrps += m->mGrpSize + m->serial_size(RS_GXS_GRP_META_DATA_CURRENT_API_VERSION); - - if (IS_GROUP_SUBSCRIBED(m->mSubscribeFlags)) - { - ++req->mServiceStatistic.mNumGrpsSubscribed; - - GroupStatisticRequest gr; - gr.mGrpId = m->mGroupId; - getGroupStatistic(&gr); - - req->mServiceStatistic.mNumMsgs += gr.mGroupStatistic.mNumMsgs; - req->mServiceStatistic.mSizeOfMsgs += gr.mGroupStatistic.mTotalSizeOfMsgs; - req->mServiceStatistic.mNumThreadMsgsNew += gr.mGroupStatistic.mNumThreadMsgsNew; - req->mServiceStatistic.mNumThreadMsgsUnread += gr.mGroupStatistic.mNumThreadMsgsUnread; - req->mServiceStatistic.mNumChildMsgsNew += gr.mGroupStatistic.mNumChildMsgsNew; - req->mServiceStatistic.mNumChildMsgsUnread += gr.mGroupStatistic.mNumChildMsgsUnread; - } - } - - req->mServiceStatistic.mSizeStore = req->mServiceStatistic.mSizeOfGrps + req->mServiceStatistic.mSizeOfMsgs; - - return true; -} - -bool RsGxsDataAccess::getMsgIdList(MsgIdReq* req) -{ - - GxsMsgMetaResult result; - mDataStore->retrieveGxsMsgMetaData(req->mMsgIds, result); - - for(auto mit = result.begin(); mit != result.end(); ++mit) - { - const RsGxsGroupId grpId = mit->first; - auto& metaV = mit->second; - - for(auto vit=metaV.begin(); vit != metaV.end(); ++vit) - req->mMsgIdResult[grpId].insert((*vit)->mMsgId); - } - - GxsMsgReq msgIdOut; - - // filter based on options - getMsgIdList(req->mMsgIdResult, req->Options, msgIdOut); - req->mMsgIdResult = msgIdOut; - - return true; -} - -void RsGxsDataAccess::filterMsgIdList( GxsMsgIdResult& resultsMap, const RsTokReqOptions& opts, const MsgMetaFilter& msgMetas ) const -{ - for( GxsMsgIdResult::iterator grpIt = resultsMap.begin(); grpIt != resultsMap.end(); ++grpIt ) - { - const RsGxsGroupId& groupId(grpIt->first); - std::set& msgsIdSet(grpIt->second); - - MsgMetaFilter::const_iterator cit = msgMetas.find(groupId); - if(cit == msgMetas.end()) continue; -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ << " " << msgsIdSet.size() - << " for group: " << groupId << " before filtering" - << std::endl; -#endif - - for( std::set::iterator msgIdIt = msgsIdSet.begin(); msgIdIt != msgsIdSet.end(); ) - { - const RsGxsMessageId& msgId(*msgIdIt); - const auto& msgsMetaMap = cit->second; - - bool keep = false; - auto msgsMetaMapIt = msgsMetaMap.find(msgId); - - if( msgsMetaMapIt != msgsMetaMap.end() ) - keep = checkMsgFilter(opts, msgsMetaMapIt->second); - - if(keep) - ++msgIdIt; - else - msgIdIt = msgsIdSet.erase(msgIdIt); - } - -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ << " " << msgsIdSet.size() - << " for group: " << groupId << " after filtering" - << std::endl; -#endif - } -} - -void RsGxsDataAccess::filterGrpList(std::list &grpIds, const RsTokReqOptions &opts, const GrpMetaFilter& meta) const -{ - for(auto lit = grpIds.begin(); lit != grpIds.end(); ) - { - auto cit = meta.find(*lit); - - bool keep = false; - - if(cit != meta.end()) - keep = checkGrpFilter(opts, cit->second); - - if(keep) - ++lit; - else - lit = grpIds.erase(lit); - } -} - - -bool RsGxsDataAccess::checkRequestStatus( uint32_t token, GxsRequestStatus& status, uint32_t& reqtype, uint32_t& anstype, rstime_t& ts ) -{ - RS_STACK_MUTEX(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - -#ifdef DATA_DEBUG - GXSDATADEBUG << "CheckRequestStatus: token=" << token << std::endl ; -#endif - - if(req != nullptr) - { - anstype = req->clientAnswerType; - reqtype = req->reqType; - status = COMPLETE; - ts = req->reqTime; -#ifdef DATA_DEBUG - GXSDATADEBUG << " Returning status = COMPLETE" << std::endl; -#endif - return true; - } - - auto it = mPublicToken.find(token); - - if(it != mPublicToken.end()) - { - status = it->second; -#ifdef DATA_DEBUG - GXSDATADEBUG << " Returning status = " << status << std::endl; -#endif - return true; - } - - status = FAILED; -#ifdef DATA_DEBUG - GXSDATADEBUG << " Token not found. Returning FAILED" << std::endl; -#endif - return false; -} - -bool RsGxsDataAccess::addGroupData(RsNxsGrp* grp) { - - RsStackMutex stack(mDataMutex); - - std::list grpM; - grpM.push_back(grp); - return mDataStore->storeGroup(grpM); -} - -bool RsGxsDataAccess::updateGroupData(RsNxsGrp* grp) { - - RsStackMutex stack(mDataMutex); - - std::list grpM; - grpM.push_back(grp); - return mDataStore->updateGroup(grpM); -} - -bool RsGxsDataAccess::getGroupData(const RsGxsGroupId& grpId, RsNxsGrp *& grp_data) -{ - RsStackMutex stack(mDataMutex); - - std::map grps ; - - grps[grpId] = nullptr ; - - if(mDataStore->retrieveNxsGrps(grps, false)) // the false here is very important: it removes the private key parts. - { - grp_data = grps.begin()->second; - return true; - } - else - return false ; -} - -bool RsGxsDataAccess::addMsgData(RsNxsMsg* msg) { - - RsStackMutex stack(mDataMutex); - - std::list msgM; - msgM.push_back(msg); - return mDataStore->storeMessage(msgM); -} - - - -void RsGxsDataAccess::tokenList(std::list& tokens) -{ - - RsStackMutex stack(mDataMutex); - - for(auto& it:mRequestQueue) - tokens.push_back(it.second->token); - - for(auto& it:mCompletedRequests) - tokens.push_back(it.first); -} - -bool RsGxsDataAccess::locked_updateRequestStatus( uint32_t token, RsTokenService::GxsRequestStatus status ) -{ - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req) req->status = status; - else return false; - - return true; -} - -uint32_t RsGxsDataAccess::generatePublicToken() -{ - uint32_t token; - generateToken(token); - - { - RS_STACK_MUTEX(mDataMutex); - mPublicToken[token] = PENDING ; -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": Adding new public token " << token << " in PENDING state. Completed tokens: " << mCompletedRequests.size() << " Size of mPublicToken: " << mPublicToken.size() << std::endl; - if(mDataStore->serviceType() == 0x218 && token==19) - print_stacktrace(); -#endif - } - - return token; -} - - - -bool RsGxsDataAccess::updatePublicRequestStatus( uint32_t token, RsTokenService::GxsRequestStatus status ) -{ - RS_STACK_MUTEX(mDataMutex); - - auto mit = mPublicToken.find(token); - - if(mit != mPublicToken.end()) - { - mit->second = status; -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": updating public token " << token << " to state " << tokenStatusString[status] << std::endl; -#endif - return true; - } - else - return false; -} - - - -bool RsGxsDataAccess::disposeOfPublicToken(uint32_t token) -{ - RS_STACK_MUTEX(mDataMutex); - auto mit = mPublicToken.find(token); - if(mit != mPublicToken.end()) - { - mPublicToken.erase(mit); -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": Deleting public token " << token << ". Completed tokens: " << mCompletedRequests.size() << " Size of mPublicToken: " << mPublicToken.size() << std::endl; -#endif - return true; - } - else - return false; -} - -#ifdef DATA_DEBUG -void RsGxsDataAccess::dumpTokenQueues() -{ - RS_STACK_MUTEX(mDataMutex); - - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": dumping token list."<< std::endl; - - for(auto tokenpair:mPublicToken) - GXSDATADEBUG << " Public Token " << tokenpair.first << " : " << tokenStatusString[tokenpair.second] << std::endl; - - for(auto tokenpair:mCompletedRequests) - GXSDATADEBUG << " Completed Tokens: " << tokenpair.first << std::endl; - - for(auto tokenpair:mRequestQueue) - GXSDATADEBUG << " RequestQueue: " << tokenpair.first << " status " << tokenStatusString[tokenpair.second->status] << std::endl; - - GXSDATADEBUG << std::endl; -} -#endif - -bool RsGxsDataAccess::checkGrpFilter(const RsTokReqOptions &opts, const std::shared_ptr& meta) const -{ - - bool subscribeMatch = false; - - if(opts.mSubscribeMask) - { - // Exact Flags match required. - if ((opts.mSubscribeMask & opts.mSubscribeFilter) == (opts.mSubscribeMask & meta->mSubscribeFlags)) - { - subscribeMatch = true; - } - } - else - { - subscribeMatch = true; - } - - return subscribeMatch; -} -bool RsGxsDataAccess::checkMsgFilter(const RsTokReqOptions& opts, const std::shared_ptr &meta ) const -{ - if (opts.mStatusMask) - { - // Exact Flags match required. - if ( (opts.mStatusMask & opts.mStatusFilter) == - (opts.mStatusMask & meta->mMsgStatus) ) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ - << " Continue checking Msg as StatusMatches: " - << " Mask: " << opts.mStatusMask - << " StatusFilter: " << opts.mStatusFilter - << " MsgStatus: " << meta->mMsgStatus - << " MsgId: " << meta->mMsgId << std::endl; -#endif - } - else - { -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ - << " Dropping Msg due to !StatusMatch " - << " Mask: " << opts.mStatusMask - << " StatusFilter: " << opts.mStatusFilter - << " MsgStatus: " << meta->mMsgStatus - << " MsgId: " << meta->mMsgId << std::endl; -#endif - - return false; - } - } - else - { -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ - << " Status check not requested" - << " mStatusMask: " << opts.mStatusMask - << " MsgId: " << meta->mMsgId << std::endl; -#endif - } - - if(opts.mMsgFlagMask) - { - // Exact Flags match required. - if ( (opts.mMsgFlagMask & opts.mMsgFlagFilter) == - (opts.mMsgFlagMask & meta->mMsgFlags) ) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ - << " Accepting Msg as FlagMatches: " - << " Mask: " << opts.mMsgFlagMask - << " FlagFilter: " << opts.mMsgFlagFilter - << " MsgFlag: " << meta->mMsgFlags - << " MsgId: " << meta->mMsgId << std::endl; -#endif - } - else - { -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ - << " Dropping Msg due to !FlagMatch " - << " Mask: " << opts.mMsgFlagMask - << " FlagFilter: " << opts.mMsgFlagFilter - << " MsgFlag: " << meta->mMsgFlags - << " MsgId: " << meta->mMsgId << std::endl; -#endif - - return false; - } - } - else - { -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ - << " Flags check not requested" - << " mMsgFlagMask: " << opts.mMsgFlagMask - << " MsgId: " << meta->mMsgId << std::endl; -#endif - } - - return true; -} - -GxsGroupStatistic::~GxsGroupStatistic() = default; -GxsServiceStatistic::~GxsServiceStatistic() = default; diff --git a/libretroshare/src/gxs/rsgxsdataaccess.h b/libretroshare/src/gxs/rsgxsdataaccess.h deleted file mode 100644 index cf5c729bd..000000000 --- a/libretroshare/src/gxs/rsgxsdataaccess.h +++ /dev/null @@ -1,519 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsdataaccess.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Christopher Evi-Parker, Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSGXSDATAACCESS_H -#define RSGXSDATAACCESS_H - -#include -#include "retroshare/rstokenservice.h" -#include "rsgxsrequesttypes.h" -#include "rsgds.h" - - -typedef std::map< RsGxsGroupId, std::map > > MsgMetaFilter; -typedef std::map< RsGxsGroupId, std::shared_ptr > GrpMetaFilter; - -bool operator<(const std::pair& p1,const std::pair& p2); - -class RsGxsDataAccess : public RsTokenService -{ -public: - explicit RsGxsDataAccess(RsGeneralDataService* ds); - virtual ~RsGxsDataAccess() ; - -public: - - /** S: RsTokenService - * TODO: cleanup - * In the following methods @param uint32_t ansType is of no use, it is - * deprecated and should be removed as soon as possible as it is cause of - * many confusions, instead use const RsTokReqOptions::mReqType &opts to - * specify the kind of data you are interested in. - * Most of the methods use const uint32_t &token as param type change it to - * uint32_t - */ - - /*! - * Use this to request group related information - * @param token The token returned for the request, store this value to pool for request completion - * @param ansType @deprecated unused @see S: RsTokenService notice - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds group id to request info for - * @return - */ - bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) override; - - /*! - * Use this to request all group related info - * @param token The token returned for the request, store this value to pool for request completion - * @param ansType @deprecated unused @see S: RsTokenService notice - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @return - */ - bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts) override; - - /*! - * Use this to get msg information (id, meta, or data), store token value to poll for request completion - * @param token The token returned for the request - * @param ansType @deprecated unused @see S: RsTokenService notice - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs - * @return true if request successful false otherwise - */ - bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const GxsMsgReq& msgIds) override; - - /*! - * Use this to get message information (id, meta, or data), store token value to poll for request completion - * @param token The token returned for the request - * @param ansType @deprecated unused @see S: RsTokenService notice - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds The ids of the groups to get, this retrieve all the msgs info for each grpId in list, if group Id list is empty \n - * all messages for all groups are retrieved - * @return true if request successful false otherwise - */ - bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list& grpIds) override; - - /*! - * For requesting msgs related to a given msg id within a group - * @param token The token returned for the request - * @param ansType @deprecated unused @see S: RsTokenService notice - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs - * @return true if request successful false otherwise - */ - bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::vector &msgIds) override; - - /*! - * This request statistics on amount of data held - * number of groups - * number of groups subscribed - * number of messages - * size of db store - * total size of messages - * total size of groups - * @param token - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - */ - void requestServiceStatistic(uint32_t& token, const RsTokReqOptions &opts) override; - - /*! - * To request statistic on a group - * @param token set to value to be redeemed to get statistic - * @param grpId the id of the group - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - */ - void requestGroupStatistic(uint32_t& token, const RsGxsGroupId& grpId, const RsTokReqOptions &opts) override; - - /* Poll */ - GxsRequestStatus requestStatus(uint32_t token); - - /* Cancel Request */ - bool cancelRequest(const uint32_t &token); - - - /** E: RsTokenService **/ - -public: - - /*! - * This adds a groups to the gxs data base, this is a blocking call \n - * If function returns successfully DataAccess can be queried for grp - * @param grp the group to add, responsibility grp passed lies with callee - * @return false if group cound not be added - */ - bool addGroupData(RsNxsGrp* grp); - - /*! - * This updates a groups in the gxs data base, this is a blocking call \n - * If function returns successfully DataAccess can be queried for grp - * @param grp the group to add, responsibility grp passed lies with callee - * @return false if group cound not be added - */ - bool updateGroupData(RsNxsGrp* grp); - - /*! - * This adds a group to the gxs data base, this is a blocking call \n - * Responsibility for msg still lies with callee \n - * If function returns successfully DataAccess can be queried for msg - * @param msg the msg to add - * @return false if msg could not be added, true otherwise - */ - bool addMsgData(RsNxsMsg* msg); - - /*! - * This retrieves a group from the gxs data base, this is a blocking call \n - * @param grp the group to add, memory ownership passed to the callee - * @return false if group cound not be retrieved - */ - bool getGroupData(const RsGxsGroupId& grpId,RsNxsGrp *& grp_data); - - -public: - - - - /*! - * This must be called periodically to progress requests - */ - void processRequests(); - - /*! - * @param token - * @param grpStatistic - * @return false if token cannot be redeemed - */ - bool getGroupStatistic(const uint32_t &token, GxsGroupStatistic& grpStatistic); - - /*! - * @param token - * @param servStatistic - * @return false if token cannot be redeemed - */ - bool getServiceStatistic(const uint32_t &token, GxsServiceStatistic& servStatistic); - - - /*! - * Retrieve group list for a given token - * @param token request token to be redeemed - * @param groupIds - * @param msgIds - * @return false if token cannot be redeemed, if false you may have tried to redeem when not ready - */ - bool getGroupList(const uint32_t &token, std::list &groupIds); - - /*! - * - * @param token request token to be redeemed - * @param msgIds - */ - bool getMsgIdList(const uint32_t &token, GxsMsgIdResult &msgIds); - - - /*! - * Retrieve msg list for a given token for message related info - * @param token token to be redeemed - * @param msgIds a map of RsGxsGrpMsgIdPair -> msgList (vector) - * @return false if could not redeem token - */ - bool getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult& msgIds); - - - /*! - * @param token request token to be redeemed - * @param groupInfo - */ - bool getGroupSummary(const uint32_t &token, std::list > &groupInfo); - - /*! - * - * @param token request token to be redeemed - * @param msgInfo - */ - bool getMsgSummary(const uint32_t &token, GxsMsgMetaResult &msgInfo); - - - /*! - * Retrieve msg meta for a given token for message related info - * @param token token to be redeemed - * @param msgIds a map of RsGxsGrpMsgIdPair -> msgList (vector) - * @return false if could not redeem token - */ - bool getMsgRelatedSummary(const uint32_t &token, MsgRelatedMetaResult& msgMeta); - - /*! - * - * @param token request token to be redeemed - * @param grpData - */ - bool getGroupData(const uint32_t &token, std::list& grpData); - - /*! - * - * @param token request token to be redeemed - * @param msgData - * @return false if data cannot be found for token - */ - bool getMsgData(const uint32_t &token, NxsMsgDataResult& msgData); - - /*! - * - * @param token request token to be redeemed - * @param msgData - * @return false if data cannot be found for token - */ - bool getMsgRelatedData(const uint32_t &token, NxsMsgRelatedDataResult& msgData); - -private: - - /** helper functions to implement token service **/ - - /*! - * Assigns a token value to passed integer - * @param token is assigned a unique token value - */ - void generateToken(uint32_t &token); - - /*! - * - * @param token the value of the token for the request object handle wanted - * @return the request associated to this token - */ - GxsRequest* locked_retrieveCompletedRequest(const uint32_t& token); - - /*! - * Add a gxs request to queue - * @param req gxs request to add - */ - void storeRequest(GxsRequest* req); - - /*! - * convenience function to setting members of request - * @param req - * @param token - * @param ansType - * @param opts - */ - void setReq(GxsRequest* req, uint32_t token, uint32_t ansType, const RsTokReqOptions& opts) const; - - /*! - * Remove request for request queue - * Request is deleted - * @param token the token associated to the request - * @return true if token successfully cleared, false if token does not exist - */ - bool clearRequest(const uint32_t &token); - - /*! - * Updates the status flag of a request - * @param token the token value of the request to set - * @param status the status to set - * @return - */ - bool locked_updateRequestStatus(uint32_t token, GxsRequestStatus status); - - /*! - * Use to query the status and other values of a given token - * @param token the toke of the request to check for - * @param status set to current status of request - * @param reqtype set to request type of request - * @param anstype set to to anstype of request - * @param ts time stamp - * @return false if token does not exist, true otherwise - */ - bool checkRequestStatus( uint32_t token, GxsRequestStatus &status, - uint32_t &reqtype, uint32_t &anstype, rstime_t &ts); - - // special ones for testing (not in final design) - /*! - * Get list of active tokens of this token service - * @param tokens sets to list of token contained in this tokenservice - */ - void tokenList(std::list &tokens); - - // /*! - // * Convenience function to delete the ids - // * @param filter the meta filter to clean - // */ - // void cleanseMsgMetaMap(GxsMsgMetaResult& result); - -public: - - /*! - * Assigns a token value to passed integer - * The status of the token can still be queried from request status feature - * @param token is assigned a unique token value - */ - uint32_t generatePublicToken(); - - /*! - * Updates the status of associate token - * @param token - * @param status - * @return false if token could not be found, true if token disposed of - */ - bool updatePublicRequestStatus(uint32_t token, GxsRequestStatus status); - - /*! - * This gets rid of a publicly issued token - * @param token - * @return false if token could not found, true if token disposed of - */ - bool disposeOfPublicToken(uint32_t token); - -private: - - /* These perform the actual blocking retrieval of data */ - - /*! - * Attempts to retrieve group id list from data store - * @param req - * @return false if unsuccessful, true otherwise - */ - bool getGroupList(GroupIdReq* req); - - /*! - * convenience function for filtering grpIds - * @param grpIdsIn The ids to filter with opts - * @param opts the filter options - * @param grpIdsOut grpIdsIn filtered with opts - */ - bool getGroupList(const std::list& grpIdsIn, const RsTokReqOptions& opts, std::list& grpIdsOut); - - /*! - * Attempts to retrieve msg id list from data store - * Computationally/CPU-Bandwidth expensive - * @param req - * @return false if unsuccessful, true otherwise - */ - bool getMsgIdList(MsgIdReq* req); - - /*! - * Attempts to retrieve msg Meta list from data store - * Computationally/CPU-Bandwidth expensive - * - * @param msgIds List of message Ids for the Message Metas to retrieve - * @param opts GxsRequest options - * @param result Map of Meta information for messages - * - */ - bool getMsgMetaDataList( const GxsMsgReq& msgIds, const RsTokReqOptions& opts, GxsMsgMetaResult& result ); - - /*! - * Attempts to retrieve group meta data from data store - * @param req - * @return false if unsuccessful, true otherwise - */ - bool getGroupSummary(GroupMetaReq* req); - - /*! - * Attempts to retrieve msg meta data from data store - * @param req - * @return false if unsuccessful, true otherwise - */ - bool getMsgSummary(MsgMetaReq* req); - - /*! - * Attempts to retrieve group data from data store - * @param req The request specifying data to retrieve - * @return false if unsuccessful, true otherwise - */ - bool getGroupData(GroupDataReq* req); - - /*! - * Attempts to retrieve message data from data store - * @param req The request specifying data to retrieve - * @return false if unsuccessful, true otherwise - */ - bool getMsgData(MsgDataReq* req); - - - /*! - * Attempts to retrieve messages related to msgIds of associated equest - * @param req Request object to satisfy - * @return false if data cannot be found for token - */ - bool getMsgRelatedInfo(MsgRelatedInfoReq* req); - - - /*! - * - * Attempts to retrieve group statistic - * @param req Request object to satisfy - */ - bool getGroupStatistic(GroupStatisticRequest* req); - - /*! - * - * Attempts to retrieve group data in serialized format - * @param req Request object to satisfy - */ - bool getGroupSerializedData(GroupSerializedDataReq* req); - - /*! - * - * Attempts to service statistic - * @param req request object to satisfy - */ - bool getServiceStatistic(ServiceStatisticRequest* req); - - /*! - * This filter msgs based of options supplied (at the moment just status masks) - * @param msgIds The msgsIds to filter - * @param opts the request options set by user - * @param meta The accompanying meta information for msg, ids - */ - void filterMsgIdList(GxsMsgIdResult& msgIds, const RsTokReqOptions& opts, const MsgMetaFilter& meta) const; - - /*! - * This filter msgs based of options supplied (at the moment just status masks) - * @param grpIds The group ids to filter - * @param opts the request options containing mask set by user - * @param meta The accompanying meta information for group ids - */ - void filterGrpList(std::list& msgIds, const RsTokReqOptions& opts, const GrpMetaFilter& meta) const; - - - /*! - * This applies the options to the meta to find out if the given message satisfies - * them - * @param opts options containing filters to check - * @param meta meta containing currently defined options for msg - * @return true if msg meta passes all options - */ - bool checkMsgFilter(const RsTokReqOptions& opts, const std::shared_ptr& meta) const; - - /*! - * This applies the options to the meta to find out if the given group satisfies - * them - * @param opts options containing filters to check - * @param meta meta containing currently defined options for group - * @return true if group meta passes all options - */ - bool checkGrpFilter(const RsTokReqOptions& opts, const std::shared_ptr &meta) const; - - - /*! - * This is a filter method which applies the request options to the list of ids - * requested - * @param msgIds the msg ids for filter to be applied to - * @param opts the options used to parameterise the id filter - * @param msgIdsOut the left overs ids after filter is applied to msgIds - */ - bool getMsgIdList(const GxsMsgReq& msgIds, const RsTokReqOptions& opts, GxsMsgReq& msgIdsOut); - - void dumpTokenQueues(); -private: - bool locked_clearRequest(const uint32_t &token); - - RsGeneralDataService* mDataStore; - - RsMutex mDataMutex; /* protecting below */ - - uint32_t mNextToken; - std::map mPublicToken; - - std::set > mRequestQueue; - std::map mCompletedRequests; - - bool mUseMetaCache; -}; - -#endif // RSGXSDATAACCESS_H diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc deleted file mode 100644 index e1b70a670..000000000 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ /dev/null @@ -1,5612 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsnetservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ - -// -// RsNxsItem -// | -// +-- RsNxsSyncGrp send req for group list, with time stamp of what we have -// +-- RsNxsSyncMsg -// +-- RsNxsGroupPublishKeyItem -// +-- RsNxsSyncGrpItem send individual grp info with time stamps, authors, etc. -// -// -// tick() -// | -// +----------- sharePublishKeys() -// | -// +----------- syncWithPeers() -// | | -// | +--if AutoSync--- send global UpdateTS of each peer to itself => the peer knows the last -// | | time current peer has received an updated from himself -// | | type=RsNxsSyncGrp -// | | role: advise to request grp list for mServType -// | | -// | +--Retrive all grp Id + meta -// | -// | For each peer -// | For each grp to request -// | send RsNxsSyncMsg(ServiceType, grpId, updateTS) -// | | -// | (Only send if rand() < sendingProb()) +---comes from mClientMsgUpdateMap -// | -// +----------- recvNxsItemQueue() -// | -// +------ handleRecvPublishKeys(auto*) -// | -// | -// | -// +------ handleRecvSyncGroup( RsNxsSyncGrp*) -// | - parse all subscribed groups. For each, send a RsNxsSyncGrpItem with publish TS -// | - pack into a single RsNxsTransac item -// | | -// | +---- canSendGrpId(peer, grpMeta, toVet) // determines if put in vetting list -// | | | // or sent right away -// | | +--CIRCLES_TYPE_LOCAL------- false -// | | +--CIRCLES_TYPE_PUBLIC------ true -// | | +--CIRCLES_TYPE_EXTERNAL---- mCircles->canSend(circleId, getPgpId(peerId)) -// | | +--CIRCLES_TYPE_YOUR_EYES--- internal circle stuff -// | | -// | +---- store in mPendingCircleVet ou directement locked_pushGrpRespFromList() -// | -// +------ handleRecvSyncMessage( RsNxsSyncMsg*) -// - parse msgs from group -// - send all msg IDs for this group -// | -// +---- canSendMsgIds(msgMeta, grpMeta, peer) -// | | -// | +--CIRCLES_TYPE_LOCAL------- false -// | +--CIRCLES_TYPE_PUBLIC------ true -// | +--CIRCLES_TYPE_EXTERNAL---- mCircles->canSend(circleId, getPgpId(peerId)) -// | +--CIRCLES_TYPE_YOUR_EYES--- internal circle stuff -// | -// +---- store in mPendingCircleVet ou directement locked_pushGrpRespFromList() -// data_tick() -// | -// +----------- updateServerSyncTS() -// | - retrieve all group meta data -// | - updates mServerMsgUpdateMap[grpId]=grp->mLastPostTS for all grps -// | - updates mGrpServerUpdateItem to max of all received TS -// | -// +----------- processTransactions() -// | -// +----------- processCompletedTransactions() -// | | -// | +------ locked_processCompletedIncomingTrans() -// | | | -// | | +-------- locked_genReqMsgTransaction() // request messages based on list -// | | | -// | | +-------- locked_genReqGrpTransaction() // request groups based on list -// | | | -// | | +-------- locked_genSendMsgsTransaction() // send msg list -// | | | -// | | +-------- locked_genSendGrpsTransaction() // send group list -// | | -// | +------ locked_processCompletedOutgoingTrans() -// | -// +----------- processExplicitGroupRequests() -// | - parse mExplicitRequest and for each element (containing a grpId list), -// | send the group ID (?!?!) -// | -// +----------- runVetting() -// | -// +--------- sort items from mPendingResp -// | | -// | +------ locked_createTransactionFromPending(GrpRespPending / MsgRespPending) -// | | // takes accepted transaction and adds them to the list of active trans -// | -// +--------- sort items from mPendingCircleVetting -// | -// +------ locked_createTransactionFromPending(GrpCircleIdsRequestVetting / MsgCircleIdsRequestVetting) -// // takes accepted transaction and adds them to the list of active trans -// -// Objects for time stamps -// ======================= -// -// mClientGrpUpdateMap: map< RsPeerId, TimeStamp > Time stamp of last modification of group data for that peer (in peer's clock time!) -// (Set at server side to be mGrpServerUpdateItem->grpUpdateTS) -// -// Only updated in processCompletedIncomingTransaction() from Grp list transaction. -// Used in syncWithPeers() sending in RsNxsSyncGrp once to all peers: peer will send data if -// has something new. All time comparisons are in the friends' clock time. -// -// mClientMsgUpdateMap: map< RsPeerId, map > -// -// Last msg list modification time sent by that peer Id -// Updated in processCompletedIncomingTransaction() from Grp list trans. -// Used in syncWithPeers() sending in RsNxsSyncGrp once to all peers. -// Set at server to be mServerMsgUpdateMap[grpId]->msgUpdateTS -// -// mGrpServerUpdateItem: TimeStamp Last group local modification timestamp over all groups -// -// mServerMsgUpdateMap: map< GrpId, TimeStamp > Timestamp local modification for each group (i.e. time of most recent msg / metadata update) -// -// -// Group update algorithm -// ====================== -// -// CLient Server -// ====== ====== -// -// tick() tick() -// | | -// +---- SyncWithPeers +-- recvNxsItemQueue() -// | | -// +---------------- Send global UpdateTS of each peer to itself => the peer knows +---------> +------ handleRecvSyncGroup( RsNxsSyncGrp*) -// | the last msg sent (stored in mClientGrpUpdateMap[peer_id]), | | - parse all subscribed groups. For each, send a RsNxsSyncGrpItem with publish TS -// | type=RsNxsSyncGrp | | - pack into a single RsNxsTransac item -// | role: advise to request grp list for mServType -------------------+ | -// | +--> +------ handleRecvSyncMessage( RsNxsSyncMsg*) -// +---------------- Retrieve all grp Id + meta | - parse msgs from group -// | | - send all msg IDs for this group -// +-- For each peer | -// For each grp to request | -// send RsNxsSyncMsg(ServiceType, grpId, updateTS) | -// | | -// (Only send if rand() < sendingProb()) +---comes from mClientMsgUpdateMap -----+ -// -// Suggestions -// =========== -// * handleRecvSyncGroup should use mit->second.mLastPost to limit the sending of already known data -// X * apparently mServerMsgUpdateMap is initially empty -> by default clients will always want to receive the data. -// => new peers will always send data for each group until they get an update for that group. -// X * check that there is a timestamp for unsubscribed items, otherwise we always send TS=0 and we always get them!! (in 346) -// -// -> there is not. mClientMsgUpdateMap is updated when msgs are received. -// -> 1842: leaves before asking for msg content. -// -// Proposed changes: -// - for unsubsribed groups, mClientMsgUpdateMap[peerid][grpId]=now when the group list is received => wont be asked again -// - when we subscribe, we reset the time stamp. -// -// Better change: -// - each peer sends last -// -// * the last TS method is not perfect: do new peers always receive old messages? -// -// * there's double information between mServerMsgUpdateMap first element (groupId) and second->grpId -// * processExplicitGroupRequests() seems to send the group list that it was asked for without further information. How is that useful??? -// -// * grps without messages will never be stamped because stamp happens in genReqMsgTransaction, after checking msgListL.empty() -// Problem: without msg, we cannot know the grpId!! -// -// * mClientMsgUpdateMap[peerid][grpId] is only updated when new msgs are received. Up to date groups will keep asking for lists! -// -// Distant sync -// ============ -// -// Distant sync uses tunnels to sync subscribed GXS groups that are not supplied by friends. Peers can subscribe to a GXS group using a RS link -// which GXS uses to request updates through tunnels. -// * The whole exchange should be kept private and anonymous between the two distant peers, so we use the same trick than for FT: encrypt the data using the group ID. -// * The same node shouldn't be known as a common server for different GXS groups -// -// GXS net service: -// * talks to virtual peers, treated like normal peers -// * virtual peers only depend on the server ID, not on tunnel ID, and be kept constant accross time so that ClientGroupUpdateMap is kept consistent -// * does not use tunnels if friends can already supply the data (??) This causes issues with "islands". -// -// Tunnels: -// * a specific service named GxsSyncTunnelService handles the creation/management of sync tunnels: -// * tunnel data need to be encrypted. -// -// bool manageTunnels(const RsGxsGroupId&) ; // start managing tunnels for this group -// bool releaseTunnels(const RsGxsGroupId&) ; // stop managing tunnels for this group -// bool sendData(const unsigned char *data,uint32_t size,const RsPeerId& virtual_peer) ; // send data to this virtual peer -// bool getVirtualPeers(const RsGxsGroupId&, std::list& peers) ; // returns the virtual peers for this group -// -// Proposed protocol: -// * request tunnels based on H(GroupId) -// * encrypt tunnel data using chacha20+HMAC-SHA256 using AEAD( GroupId, 96bits IV, tunnel ID ) (similar to what FT does) -// * when tunnel is established, exchange virtual peer names: vpid = H( GroupID | Random bias ) -// * when vpid is known, notify the client (GXS net service) which can use the virtual peer to sync -// -// * only use a single tunnel per virtual peer ID -// -// Client ------------------ TR(H(GroupId)) --------------> Server -// -// Client <-------------------- T OK ---------------------- Server -// -// [Encrypted traffic using H(GroupId, 96bits IV, tunnel ID)] -// -// Client <--------- VPID = H( Random IV | GroupId ) ------ Server -// | | -// +--------------> Mark the virtual peer active <-----------+ -// -// Unsolved problems: -// * if we want to preserve anonymity, we cannot prevent GXS from duplicating the data from virtual/real peers that actually are the same peers. -// * ultimately we should only use tunnels to sync GXS. The mix between tunnels and real peers is not a problem but will cause unnecessary traffic. -// -// Notes: -// * given that GXS only talks to peers once every 2 mins, it's likely that keep-alive packets will be needed - - -#include -#include -#include -#include -#include - -#include "rsgxsnetservice.h" -#include "gxssecurity.h" -#include "retroshare/rsconfig.h" -#include "retroshare/rsgxsflags.h" -#include "retroshare/rsgxscircles.h" -#include "retroshare/rspeers.h" -#include "pgp/pgpauxutils.h" -#include "crypto/rscrypto.h" -#include "util/rsdir.h" -#include "util/rstime.h" -#include "util/rsmemory.h" -#include "util/stacktrace.h" -#include "util/rsdebug.h" -#include "util/cxx17retrocompat.h" - -/*** - * Use the following defines to debug: - NXS_NET_DEBUG_0 shows group update high level information - NXS_NET_DEBUG_1 shows group update low level info (including transaction details) - NXS_NET_DEBUG_2 bandwidth information - NXS_NET_DEBUG_3 publish key exchange - NXS_NET_DEBUG_4 vetting - NXS_NET_DEBUG_5 summary of transactions (useful to just know what comes in/out) - NXS_NET_DEBUG_6 group sync statistics (e.g. number of posts at nighbour nodes, etc) - NXS_NET_DEBUG_7 encryption/decryption of transactions - NXS_NET_DEBUG_8 gxs distant sync - NXS_NET_DEBUG_9 gxs distant search - - ***/ -//#define NXS_NET_DEBUG_0 1 -//#define NXS_NET_DEBUG_1 1 -//#define NXS_NET_DEBUG_2 1 -//#define NXS_NET_DEBUG_3 1 -//#define NXS_NET_DEBUG_4 1 -//#define NXS_NET_DEBUG_5 1 -//#define NXS_NET_DEBUG_6 1 -//#define NXS_NET_DEBUG_7 1 -//#define NXS_NET_DEBUG_8 1 -//#define NXS_NET_DEBUG_9 1 - -//#define NXS_FRAG - -// The constant below have a direct influence on how fast forums/channels/posted/identity groups propagate and on the overloading of queues: -// -// Channels/forums will update at a rate of SYNC_PERIOD*MAX_REQLIST_SIZE/60 messages per minute. -// A large TRANSAC_TIMEOUT helps large transactions to finish before anything happens (e.g. disconnexion) or when the server has low upload bandwidth, -// but also uses more memory. -// A small value for MAX_REQLIST_SIZE is likely to help messages to propagate in a chaotic network, but will also slow them down. -// A small SYNC_PERIOD fasten message propagation, but is likely to overload the server side of transactions (e.g. overload outqueues). -// -//static const uint32_t GIXS_CUT_OFF = 0; -static const uint32_t SYNC_PERIOD = 60; -static const uint32_t MAX_REQLIST_SIZE = 20; // No more than 20 items per msg request list => creates smaller transactions that are less likely to be cancelled. -static const uint32_t TRANSAC_TIMEOUT = 2000; // In seconds. Has been increased to avoid epidemic transaction cancelling due to overloaded outqueues. -#ifdef TO_REMOVE -static const uint32_t SECURITY_DELAY_TO_FORCE_CLIENT_REUPDATE = 3600; // force re-update if there happens to be a large delay between our server side TS and the client side TS of friends -#endif -static const uint32_t REJECTED_MESSAGE_RETRY_DELAY = 24*3600; // re-try rejected messages every 24hrs. Most of the time this is because the peer's reputation has changed. -static const uint32_t GROUP_STATS_UPDATE_DELAY = 240; // update unsubscribed group statistics every 3 mins -static const uint32_t GROUP_STATS_UPDATE_NB_PEERS = 2; // number of peers to which the group stats are asked -static const uint32_t MAX_ALLOWED_GXS_MESSAGE_SIZE = 199000; // 200,000 bytes including signature and headers -static const uint32_t MIN_DELAY_BETWEEN_GROUP_SEARCH = 40; // dont search same group more than every 40 secs. -static const uint32_t SAFETY_DELAY_FOR_UNSUCCESSFUL_UPDATE = 0; // avoid re-sending the same msg list to a peer who asks twice for the same update in less than this time - -static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN = 0x00 ; -static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_NO_ERROR = 0x01 ; -static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR = 0x02 ; -static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_ENCRYPTION_ERROR = 0x03 ; -static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_SERIALISATION_ERROR = 0x04 ; -static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING = 0x05 ; - -// Debug system to allow to print only for some IDs (group, Peer, etc) - -#if defined(NXS_NET_DEBUG_0) || defined(NXS_NET_DEBUG_1) || defined(NXS_NET_DEBUG_2) || defined(NXS_NET_DEBUG_3) \ - || defined(NXS_NET_DEBUG_4) || defined(NXS_NET_DEBUG_5) || defined(NXS_NET_DEBUG_6) || defined(NXS_NET_DEBUG_7) \ - || defined(NXS_NET_DEBUG_8) || defined(NXS_NET_DEBUG_9) - -static const RsPeerId peer_to_print = RsPeerId();//std::string("a97fef0e2dc82ddb19200fb30f9ac575")) ; -static const RsGxsGroupId group_id_to_print = RsGxsGroupId();//std::string("66052380f5d1d0c5992e2b55dc402ce6")) ; // use this to allow to this group id only, or "" for all IDs -static const uint32_t service_to_print = RS_SERVICE_GXS_TYPE_CHANNELS; // use this to allow to this service id only, or 0 for all services - // warning. Numbers should be SERVICE IDS (see serialiser/rsserviceids.h. E.g. 0x0215 for forums) - -class nullstream: public std::ostream {}; - -static std::string nice_time_stamp(rstime_t now,rstime_t TS) -{ - if(TS == 0) - return "Never" ; - else - { - std::ostringstream s; - s << now - TS << " secs ago" ; - return s.str() ; - } -} - -static std::ostream& gxsnetdebug(const RsPeerId& peer_id,const RsGxsGroupId& grp_id,uint32_t service_type) -{ - static nullstream null ; - - if((peer_to_print.isNull() || peer_id.isNull() || peer_id == peer_to_print) - && (group_id_to_print.isNull() || grp_id.isNull() || grp_id == group_id_to_print) - && (service_to_print==0 || service_type == 0 || ((service_type >> 8)&0xffff) == service_to_print)) - return std::cerr << time(NULL) << ":GXSNETSERVICE: " ; - else - return null ; -} - -#define GXSNETDEBUG___ gxsnetdebug(RsPeerId(),RsGxsGroupId(),mServiceInfo.mServiceType) -#define GXSNETDEBUG_P_(peer_id ) gxsnetdebug(peer_id ,RsGxsGroupId(),mServiceInfo.mServiceType) -#define GXSNETDEBUG__G( group_id) gxsnetdebug(RsPeerId(),group_id ,mServiceInfo.mServiceType) -#define GXSNETDEBUG_PG(peer_id,group_id) gxsnetdebug(peer_id ,group_id ,mServiceInfo.mServiceType) - -#endif - -const uint32_t RsGxsNetService::FRAGMENT_SIZE = 150000; - -RsGxsNetService::RsGxsNetService(uint16_t servType, RsGeneralDataService *gds, - RsNxsNetMgr *netMgr, RsNxsObserver *nxsObs, - const RsServiceInfo serviceInfo, - RsGixsReputation* reputations, RsGcxs* circles, RsGixs *gixs, - PgpAuxUtils *pgpUtils, RsGxsNetTunnelService *mGxsNT, - bool grpAutoSync, bool msgAutoSync, bool distSync, uint32_t default_store_period, uint32_t default_sync_period) - : p3ThreadedService(), p3Config(), mTransactionN(0), - mObserver(nxsObs), mDataStore(gds), - mServType(servType), mTransactionTimeOut(TRANSAC_TIMEOUT), - mNetMgr(netMgr), mNxsMutex("RsGxsNetService"), - mSyncTs(0), mLastKeyPublishTs(0), - mLastCleanRejectedMessages(0), mSYNC_PERIOD(SYNC_PERIOD), - mCircles(circles), mGixs(gixs), - mReputations(reputations), mPgpUtils(pgpUtils), mGxsNetTunnel(mGxsNT), - mGrpAutoSync(grpAutoSync), mAllowMsgSync(msgAutoSync),mAllowDistSync(distSync), - mServiceInfo(serviceInfo), mDefaultMsgStorePeriod(default_store_period), - mDefaultMsgSyncPeriod(default_sync_period) -{ - addSerialType(new RsNxsSerialiser(mServType)); - mOwnId = mNetMgr->getOwnId(); - mUpdateCounter = 0; - - mLastCacheReloadTS = 0; - - // check the consistency - - if(mDefaultMsgStorePeriod > 0 && mDefaultMsgSyncPeriod > mDefaultMsgStorePeriod) - { - std::cerr << "(WW) in GXS service \"" << getServiceInfo().mServiceName << "\": too large message sync period will be set to message store period." << std::endl; - mDefaultMsgSyncPeriod = mDefaultMsgStorePeriod ; - } -} - -void RsGxsNetService::getItemNames(std::map& names) const -{ - names.clear(); - - names[RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM ] = "Group Sync Request" ; - names[RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM ] = "Group Sync" ; - names[RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM ] = "Group Stats" ; - names[RS_PKT_SUBTYPE_NXS_GRP_ITEM ] = "Group Data" ; - names[RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM ] = "Encrypted data" ; - names[RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM ] = "Session Key" ; - names[RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM ] = "Message Sync" ; - names[RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM ] = "Message Sync Request" ; - names[RS_PKT_SUBTYPE_NXS_MSG_ITEM ] = "Message Data" ; - names[RS_PKT_SUBTYPE_NXS_TRANSAC_ITEM ] = "Transaction" ; - names[RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM ] = "Publish key" ; -} - -RsGxsNetService::~RsGxsNetService() -{ - RS_STACK_MUTEX(mNxsMutex) ; - - for(TransactionsPeerMap::iterator it = mTransactions.begin();it!=mTransactions.end();++it) - { - for(TransactionIdMap::iterator it2 = it->second.begin();it2!=it->second.end();++it2) - delete it2->second ; - - it->second.clear() ; - } - mTransactions.clear() ; - - mClientGrpUpdateMap.clear() ; - mServerMsgUpdateMap.clear() ; -} - - -int RsGxsNetService::tick() -{ - // always check for new items arriving - // from peers - recvNxsItemQueue(); - - bool should_notify = false; - - { - RS_STACK_MUTEX(mNxsMutex) ; - - should_notify = should_notify || !mNewGroupsToNotify.empty() ; - should_notify = should_notify || !mNewMessagesToNotify.empty() ; - should_notify = should_notify || !mNewPublishKeysToNotify.empty() ; - should_notify = should_notify || !mNewStatsToNotify.empty() ; - should_notify = should_notify || !mNewGrpSyncParamsToNotify.empty() ; - } - - if(should_notify) - processObserverNotifications() ; - - rstime_t now = time(NULL); - rstime_t elapsed = mSYNC_PERIOD + mSyncTs; - - if((elapsed) < now) - { - syncWithPeers(); - syncGrpStatistics(); - checkDistantSyncState(); - - mSyncTs = now; - } - - if(now > 10 + mLastKeyPublishTs) - { - sharePublishKeysPending() ; - - mLastKeyPublishTs = now ; - } - - if(now > 3600 + mLastCleanRejectedMessages) - { - mLastCleanRejectedMessages = now ; - cleanRejectedMessages() ; - } - return 1; -} - -void RsGxsNetService::processObserverNotifications() -{ -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << "Processing observer notification." << std::endl; -#endif - - // Observer notifycation should never be done explicitly within a Mutex-protected region, because of the risk - // of causing a cross-deadlock between the observer (RsGxsGenExchange) and the network layer (RsGxsNetService). - - std::vector grps_copy ; - std::vector msgs_copy ; - std::set stat_copy ; - std::set keys_copy,grpss_copy ; - - { - RS_STACK_MUTEX(mNxsMutex) ; - - grps_copy = mNewGroupsToNotify ; - msgs_copy = mNewMessagesToNotify ; - stat_copy = mNewStatsToNotify ; - keys_copy = mNewPublishKeysToNotify ; - grpss_copy = mNewGrpSyncParamsToNotify ; - - mNewGroupsToNotify.clear() ; - mNewMessagesToNotify.clear() ; - mNewStatsToNotify.clear() ; - mNewPublishKeysToNotify.clear() ; - mNewGrpSyncParamsToNotify.clear() ; - } - - if(!grps_copy.empty()) mObserver->receiveNewGroups (grps_copy); - if(!msgs_copy.empty()) mObserver->receiveNewMessages(msgs_copy); - - for(std::set::const_iterator it(keys_copy.begin());it!=keys_copy.end();++it) - mObserver->notifyReceivePublishKey(*it); - - for(std::set::const_iterator it(stat_copy.begin());it!=stat_copy.end();++it) - mObserver->notifyChangedGroupStats(*it); - - for(std::set::const_iterator it(grpss_copy.begin());it!=grpss_copy.end();++it) - mObserver->notifyChangedGroupSyncParams(*it); -} - -void RsGxsNetService::rejectMessage(const RsGxsMessageId& msg_id) -{ - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << "adding message " << msg_id << " to rejection list for 24hrs." << std::endl; -#endif - mRejectedMessages[msg_id] = time(NULL) ; -} -void RsGxsNetService::cleanRejectedMessages() -{ - RS_STACK_MUTEX(mNxsMutex) ; - rstime_t now = time(NULL) ; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << "Cleaning rejected messages." << std::endl; -#endif - - for(std::map::iterator it(mRejectedMessages.begin());it!=mRejectedMessages.end();) - if(it->second + REJECTED_MESSAGE_RETRY_DELAY < now) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << " message id " << it->first << " should be re-tried. removing from list..." << std::endl; -#endif - - std::map::iterator tmp = it ; - ++tmp ; - mRejectedMessages.erase(it) ; - it=tmp ; - } - else - ++it ; -} - -RsGxsGroupId RsGxsNetService::hashGrpId(const RsGxsGroupId& gid,const RsPeerId& pid) -{ - static const uint32_t SIZE = RsGxsGroupId::SIZE_IN_BYTES + RsPeerId::SIZE_IN_BYTES ; - unsigned char tmpmem[SIZE]; - uint32_t offset = 0 ; - - pid.serialise(tmpmem,SIZE,offset) ; - gid.serialise(tmpmem,SIZE,offset) ; - - assert(RsGxsGroupId::SIZE_IN_BYTES <= Sha1CheckSum::SIZE_IN_BYTES) ; - - return RsGxsGroupId( RsDirUtil::sha1sum(tmpmem,SIZE).toByteArray() ); -} - -void RsGxsNetService::syncWithPeers() -{ -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << "RsGxsNetService::syncWithPeers() this=" << (void*)this << ". serviceInfo=" << mServiceInfo << std::endl; -#endif - - static RsNxsSerialiser ser(mServType) ; // this is used to estimate bandwidth. - - RS_STACK_MUTEX(mNxsMutex) ; - - std::set peers; - mNetMgr->getOnlineList(mServiceInfo.mServiceType, peers); - - if(mAllowDistSync && mGxsNetTunnel != NULL) - { - // Grab all online virtual peers of distant tunnels for the current service. - - std::list vpids ; - mGxsNetTunnel->getVirtualPeers(vpids); - - for(auto it(vpids.begin());it!=vpids.end();++it) - peers.insert(RsPeerId(*it)) ; - } - - if (peers.empty()) { - // nothing to do - return; - } - - // for now just grps - for(auto sit = peers.begin(); sit != peers.end(); ++sit) - { - - const RsPeerId peerId = *sit; - - ClientGrpMap::const_iterator cit = mClientGrpUpdateMap.find(peerId); - uint32_t updateTS = 0; - - if(cit != mClientGrpUpdateMap.end()) - { - const RsGxsGrpUpdate *gui = &cit->second; - updateTS = gui->grpUpdateTS; - } - RsNxsSyncGrpReqItem *grp = new RsNxsSyncGrpReqItem(mServType); - grp->clear(); - grp->PeerId(*sit); - grp->updateTS = updateTS; - -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_(*sit) << "Service "<< std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending global group TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) to himself" << std::endl; -#endif - generic_sendItem(grp); - } - - if(!mAllowMsgSync) - return ; - -#ifndef GXS_DISABLE_SYNC_MSGS - - RsGxsGrpMetaTemporaryMap grpMeta; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - RsGxsGrpMetaTemporaryMap toRequest; - - for(RsGxsGrpMetaTemporaryMap::iterator mit = grpMeta.begin(); mit != grpMeta.end(); ++mit) - { - const auto& meta = mit->second; - - // This was commented out because we want to know how many messages are available for unsubscribed groups. - - if(meta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED ) - { - toRequest.insert(std::make_pair(mit->first, meta)); - mit->second = NULL ; // avoids destruction ;-) - } - } - - // Synchronise group msg for groups which we're subscribed to - // For each peer and each group, we send to the peer the time stamp of the most - // recent modification the peer has sent. If the peer has more recent messages he will send them, because its latest - // modifications will be more recent. This ensures that we always compare timestamps all taken in the same - // computer (the peer's computer in this case) - - for(auto sit = peers.begin(); sit != peers.end(); ++sit) - { - const RsPeerId& peerId = *sit; - - // now see if you have an updateTS so optimise whether you need - // to get a new list of peer data - const RsGxsMsgUpdate *mui = NULL; - - ClientMsgMap::const_iterator cit = mClientMsgUpdateMap.find(peerId); - - if(cit != mClientMsgUpdateMap.end()) - mui = &cit->second; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peerId) << " syncing messages with peer " << peerId << std::endl; -#endif - - RsGxsGrpMetaTemporaryMap::const_iterator mmit = toRequest.begin(); - for(; mmit != toRequest.end(); ++mmit) - { - const auto& meta = mmit->second; - const RsGxsGroupId& grpId = mmit->first; - RsGxsCircleId encrypt_to_this_circle_id ; - - if(!checkCanRecvMsgFromPeer(peerId, *meta,encrypt_to_this_circle_id)) - continue; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(peerId,grpId) << " peer can send messages for group " << grpId ; - if(!encrypt_to_this_circle_id.isNull()) - GXSNETDEBUG_PG(peerId,grpId) << " request should be encrypted for circle ID " << encrypt_to_this_circle_id << std::endl; - else - GXSNETDEBUG_PG(peerId,grpId) << " request should be sent in clear." << std::endl; - -#endif - // On default, the info has never been received so the TS is 0, meaning the peer has sent that it had no information. - - uint32_t updateTS = 0; - - if(mui) - { - std::map::const_iterator cit2 = mui->msgUpdateInfos.find(grpId); - - if(cit2 != mui->msgUpdateInfos.end()) - updateTS = cit2->second.time_stamp; - } - - // get sync params for this group - - RsNxsSyncMsgReqItem* msg = new RsNxsSyncMsgReqItem(mServType); - - msg->clear(); - msg->PeerId(peerId); - msg->updateTS = updateTS; - - int req_delay = (int)locked_getGrpConfig(grpId).msg_req_delay ; - int keep_delay = (int)locked_getGrpConfig(grpId).msg_keep_delay ; - - // If we store for less than we request, we request less, otherwise the posts will be deleted after being obtained. - - if(keep_delay > 0 && req_delay > 0 && keep_delay < req_delay) - req_delay = keep_delay ; - - // The last post will be set to TS 0 if the req delay is 0, which means "Indefinitly" - - if(req_delay > 0) - msg->createdSinceTS = std::max(0,(int)time(NULL) - req_delay); - else - msg->createdSinceTS = 0 ; - - if(encrypt_to_this_circle_id.isNull()) - msg->grpId = grpId; - else - { - msg->grpId = hashGrpId(grpId,mNetMgr->getOwnId()) ; - msg->flag |= RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID ; - } - -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(*sit,grpId) << " Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending message TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) for group " << grpId << " to himself - in clear " << std::endl; -#endif - generic_sendItem(msg); - -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_PG(*sit,grpId) << "Service "<< std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending global message TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) for group " << grpId << " to himself" << std::endl; -#endif - } - } - -#endif -} - -void RsGxsNetService::generic_sendItem(RsNxsItem *si) -{ - // check if the item is to be sent to a distant peer or not - - RsGxsGroupId tmp_grpId; - - if(mAllowDistSync && mGxsNetTunnel != NULL && mGxsNetTunnel->isDistantPeer( static_cast(si->PeerId()),tmp_grpId)) - { - RsNxsSerialiser ser(mServType); - - uint32_t size = ser.size(si); - unsigned char *mem = (unsigned char *)rs_malloc(size) ; - - if(!mem) - return ; - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG_P_(si->PeerId()) << "Sending RsGxsNetTunnelService Item:" << (void*)si << " of type: " << std::hex << si->PacketId() << std::dec - << " transaction " << si->transactionNumber << " to virtual peer " << si->PeerId() << std::endl ; -#endif - ser.serialise(si,mem,&size) ; - - mGxsNetTunnel->sendTunnelData(mServType,mem,size,static_cast(si->PeerId())); - delete si; - } - else - sendItem(si) ; -} - -void RsGxsNetService::checkDistantSyncState() -{ - if(!mAllowDistSync || mGxsNetTunnel==NULL || !mGrpAutoSync) - return ; - - RsGxsGrpMetaTemporaryMap grpMeta; - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - // Go through group statistics and groups without information are re-requested to random peers selected - // among the ones who provided the group info. - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___<< "Checking distant sync for all groups." << std::endl; -#endif - // get the list of online peers - - std::set online_peers; - mNetMgr->getOnlineList(mServiceInfo.mServiceType , online_peers); - - RS_STACK_MUTEX(mNxsMutex) ; - - for(auto it(grpMeta.begin());it!=grpMeta.end();++it) - if(it->second->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) // we only consider subscribed groups here. - { -#warning (cyril) We might need to also remove peers for recently unsubscribed groups - const RsGxsGroupId& grpId(it->first); - const RsGxsGrpConfig& rec = locked_getGrpConfig(grpId) ; - -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG__G(it->first) << " group " << grpId; -#endif - bool at_least_one_friend_is_supplier = false ; - - for(auto it2(rec.suppliers.ids.begin());it2!=rec.suppliers.ids.end() && !at_least_one_friend_is_supplier;++it2) - if(online_peers.find(*it2) != online_peers.end()) // check that the peer is online - at_least_one_friend_is_supplier = true ; - - // That strategy is likely to create islands of friends connected to each other. There's no real way - // to decide what to do here, except maybe checking the last message TS remotely vs. locally. - - if(at_least_one_friend_is_supplier) - { - mGxsNetTunnel->releaseDistantPeers(mServType,grpId); -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___<< " Group " << grpId << ": suppliers among friends. Releasing peers." << std::endl; -#endif - } - else - { - mGxsNetTunnel->requestDistantPeers(mServType,grpId); -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___<< " Group " << grpId << ": no suppliers among friends. Requesting peers." << std::endl; -#endif - } - } -} - -void RsGxsNetService::syncGrpStatistics() -{ - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG___<< "Sync-ing group statistics." << std::endl; -#endif - RsGxsGrpMetaTemporaryMap grpMeta; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - std::set online_peers; - mNetMgr->getOnlineList(mServiceInfo.mServiceType, online_peers); - - if(mAllowDistSync && mGxsNetTunnel != NULL) - { - // Grab all online virtual peers of distant tunnels for the current service. - - std::list vpids ; - mGxsNetTunnel->getVirtualPeers(vpids); - - for(auto it(vpids.begin());it!=vpids.end();++it) - online_peers.insert(RsPeerId(*it)) ; - } - - // Go through group statistics and groups without information are re-requested to random peers selected - // among the ones who provided the group info. - - rstime_t now = time(NULL) ; - - for(auto it(grpMeta.begin());it!=grpMeta.end();++it) - { - const RsGxsGrpConfig& rec = locked_getGrpConfig(it->first) ; - -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG__G(it->first) << " group " << it->first ; -#endif - - if(rec.statistics_update_TS + GROUP_STATS_UPDATE_DELAY < now && rec.suppliers.ids.size() > 0) - { -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG__G(it->first) << " needs update. Randomly asking to some friends" << std::endl; -#endif - // randomly select GROUP_STATS_UPDATE_NB_PEERS friends among the suppliers of this group - - uint32_t n = RSRandom::random_u32() % rec.suppliers.ids.size() ; - - std::set::const_iterator rit = rec.suppliers.ids.begin(); - for(uint32_t i=0;ifirst) << " asking friend " << peer_id << " for an update of stats for group " << it->first << std::endl; -#endif - - RsNxsSyncGrpStatsItem *grs = new RsNxsSyncGrpStatsItem(mServType) ; - - grs->request_type = RsNxsSyncGrpStatsItem::GROUP_INFO_TYPE_REQUEST ; - - grs->grpId = it->first ; - grs->PeerId(peer_id) ; - - generic_sendItem(grs) ; - } - } - } -#ifdef NXS_NET_DEBUG_6 - else - GXSNETDEBUG__G(it->first) << " up to date." << std::endl; -#endif - } -} - -void RsGxsNetService::handleRecvSyncGrpStatistics(RsNxsSyncGrpStatsItem *grs) -{ - if(grs->request_type == RsNxsSyncGrpStatsItem::GROUP_INFO_TYPE_REQUEST) - { -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << "Received Grp update stats Request for group " << grs->grpId << " from friend " << grs->PeerId() << std::endl; -#endif - RsGxsGrpMetaTemporaryMap grpMetas; - grpMetas[grs->grpId] = NULL; - - mDataStore->retrieveGxsGrpMetaData(grpMetas); - - const auto& grpMeta = grpMetas[grs->grpId]; - - if(grpMeta == NULL) - { -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << " Group is unknown. Not reponding." << std::endl; -#endif - return ; - } - - // check if we're subscribed or not - - if(! (grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED )) - { -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << " Group is not subscribed. Not reponding." << std::endl; -#endif - return ; - } - - // now count available messages - - GxsMsgReq reqIds; - reqIds[grs->grpId] = std::set(); - GxsMsgMetaResult result; - -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << " retrieving message information." << std::endl; -#endif - mDataStore->retrieveGxsMsgMetaData(reqIds, result); - - const auto& vec(result[grs->grpId]) ; - - if(vec.empty()) // that means we don't have any, or there isn't any, but since the default is always 0, no need to send. - return ; - - RsNxsSyncGrpStatsItem *grs_resp = new RsNxsSyncGrpStatsItem(mServType) ; - grs_resp->request_type = RsNxsSyncGrpStatsItem::GROUP_INFO_TYPE_RESPONSE ; - grs_resp->number_of_posts = vec.size(); - grs_resp->grpId = grs->grpId; - grs_resp->PeerId(grs->PeerId()) ; - - grs_resp->last_post_TS = grpMeta->mPublishTs ; // This is not zero, and necessarily older than any message in the group up to clock precision. - // This allows us to use 0 as "uninitialized" proof. If the group meta has been changed, this time - // will be more recent than some messages. This shouldn't be a problem, since this value can only - // be used to discard groups that are not used. - - for(uint32_t i=0;ilast_post_TS < vec[i]->mPublishTs) - grs_resp->last_post_TS = vec[i]->mPublishTs; - -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << " sending back statistics item with " << vec.size() << " elements." << std::endl; -#endif - - generic_sendItem(grs_resp) ; - } - else if(grs->request_type == RsNxsSyncGrpStatsItem::GROUP_INFO_TYPE_RESPONSE) - { -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << "Received Grp update stats item from peer " << grs->PeerId() << " for group " << grs->grpId << ", reporting " << grs->number_of_posts << " posts." << std::endl; -#endif - RS_STACK_MUTEX(mNxsMutex) ; - - RsGxsGrpConfig& rec(locked_getGrpConfig(grs->grpId)) ; - - uint32_t old_count = rec.max_visible_count ; - uint32_t old_suppliers_count = rec.suppliers.ids.size() ; - - rec.suppliers.ids.insert(grs->PeerId()) ; - rec.max_visible_count = std::max(rec.max_visible_count,grs->number_of_posts) ; - rec.statistics_update_TS = time(NULL) ; - rec.last_group_modification_TS = grs->last_post_TS; - - if (old_count != rec.max_visible_count || old_suppliers_count != rec.suppliers.ids.size()) - mNewStatsToNotify.insert(grs->grpId) ; - } - else - std::cerr << "(EE) RsGxsNetService::handleRecvSyncGrpStatistics(): unknown item type " << grs->request_type << " found. This is a bug." << std::endl; -} - -// This function is useful when we need to force a new sync of messages from all friends when e.g. the delay for sync gets changed. -// Normally, when subscribing to a group (not needed when unsubscribing), we should also call this method. - -void RsGxsNetService::locked_resetClientTS(const RsGxsGroupId& grpId) -{ -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(grpId) << "Resetting client TS for grp " << grpId << std::endl; -#endif - - for(ClientMsgMap::iterator it(mClientMsgUpdateMap.begin());it!=mClientMsgUpdateMap.end();++it) - it->second.msgUpdateInfos.erase(grpId) ; -} - -void RsGxsNetService::subscribeStatusChanged(const RsGxsGroupId& grpId,bool subscribed) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - if(!subscribed) - return ; - - // When we subscribe, we reset the time stamps, so that the entire group list - // gets requested once again, for a proper update. - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(grpId) << "Changing subscribe status for grp " << grpId << " to " << subscribed << ": reseting all server msg time stamps for this group, and server global TS." << std::endl; - std::map::iterator it = mServerMsgUpdateMap.find(grpId) ; -#endif - - RsGxsServerMsgUpdate& item(mServerMsgUpdateMap[grpId]) ; - - item.msgUpdateTS = time(NULL) ; - - // We also update mGrpServerUpdateItem so as to trigger a new grp list exchange with friends (friends will send their known ClientTS which - // will be lower than our own grpUpdateTS, triggering our sending of the new subscribed grp list. - - mGrpServerUpdate.grpUpdateTS = time(NULL) ; - - if(subscribed) - locked_resetClientTS(grpId) ; -} - -bool RsGxsNetService::fragmentMsg(RsNxsMsg& msg, MsgFragments& msgFragments) const -{ - // first determine how many fragments - uint32_t msgSize = msg.msg.TlvSize(); - uint32_t dataLeft = msgSize; - uint8_t nFragments = ceil(float(msgSize)/FRAGMENT_SIZE); - - RsTemporaryMemory buffer(FRAGMENT_SIZE); - int currPos = 0; - - - for(uint8_t i=0; i < nFragments; ++i) - { - RsNxsMsg* msgFrag = new RsNxsMsg(mServType); - msgFrag->grpId = msg.grpId; - msgFrag->msgId = msg.msgId; - msgFrag->meta = msg.meta; - msgFrag->transactionNumber = msg.transactionNumber; - msgFrag->pos = i; - msgFrag->PeerId(msg.PeerId()); - msgFrag->count = nFragments; - uint32_t fragSize = std::min(dataLeft, FRAGMENT_SIZE); - - memcpy(buffer, ((char*)msg.msg.bin_data) + currPos, fragSize); - msgFrag->msg.setBinData(buffer, fragSize); - - currPos += fragSize; - dataLeft -= fragSize; - msgFragments.push_back(msgFrag); - } - - return true; -} - -bool RsGxsNetService::fragmentGrp(RsNxsGrp& grp, GrpFragments& grpFragments) const -{ - // first determine how many fragments - uint32_t grpSize = grp.grp.TlvSize(); - uint32_t dataLeft = grpSize; - uint8_t nFragments = ceil(float(grpSize)/FRAGMENT_SIZE); - char buffer[FRAGMENT_SIZE]; - int currPos = 0; - - - for(uint8_t i=0; i < nFragments; ++i) - { - RsNxsGrp* grpFrag = new RsNxsGrp(mServType); - grpFrag->grpId = grp.grpId; - grpFrag->meta = grp.meta; - grpFrag->pos = i; - grpFrag->count = nFragments; - uint32_t fragSize = std::min(dataLeft, FRAGMENT_SIZE); - - memcpy(buffer, ((char*)grp.grp.bin_data) + currPos, fragSize); - grpFrag->grp.setBinData(buffer, fragSize); - - currPos += fragSize; - dataLeft -= fragSize; - grpFragments.push_back(grpFrag); - } - - return true; -} - -RsNxsMsg* RsGxsNetService::deFragmentMsg(MsgFragments& msgFragments) const -{ - if(msgFragments.empty()) return NULL; - - // if there is only one fragment with a count 1 or less then - // the fragment is the msg - if(msgFragments.size() == 1) - { - RsNxsMsg* m = msgFragments.front(); - - if(m->count > 1) // normally mcount should be exactly 1, but if not initialised (old versions) it's going to be 0 - { - // delete everything - std::cerr << "(WW) Cannot deFragment message set. m->count=" << m->count << ", but msgFragments.size()=" << msgFragments.size() << ". Incomplete? Dropping all." << std::endl; - - for(uint32_t i=0;imsg.bin_len; - - RsTemporaryMemory data(datSize) ; - - if(!data) - { - for(uint32_t i=0;imsg.bin_data, msg->msg.bin_len); - currPos += msg->msg.bin_len; - } - - RsNxsMsg* msg = new RsNxsMsg(mServType); - const RsNxsMsg& m = *(*(msgFragments.begin())); - msg->msg.setBinData(data, datSize); - msg->msgId = m.msgId; - msg->grpId = m.grpId; - msg->transactionNumber = m.transactionNumber; - msg->meta = m.meta; - - // now clean! - for(uint32_t i=0;igrp.bin_len; - - char* data = new char[datSize]; - uint32_t currPos = 0; - - for(mit = grpFragments.begin(); mit != grpFragments.end(); ++mit) - { - RsNxsGrp* grp = *mit; - memcpy(data + (currPos), grp->grp.bin_data, grp->grp.bin_len); - currPos += grp->grp.bin_len; - } - - RsNxsGrp* grp = new RsNxsGrp(mServType); - const RsNxsGrp& g = *(*(grpFragments.begin())); - grp->grp.setBinData(data, datSize); - grp->grpId = g.grpId; - grp->transactionNumber = g.transactionNumber; - grp->meta = g.meta; - - delete[] data; - - return grp; -} - -struct GrpFragCollate -{ - RsGxsGroupId mGrpId; - GrpFragCollate(const RsGxsGroupId& grpId) : mGrpId(grpId){ } - bool operator()(RsNxsGrp* grp) { return grp->grpId == mGrpId;} -}; - -void RsGxsNetService::locked_createTransactionFromPending( MsgRespPending* msgPend) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(msgPend->mPeerId) << "locked_createTransactionFromPending()" << std::endl; -#endif - MsgAuthorV::const_iterator cit = msgPend->mMsgAuthV.begin(); - std::list reqList; - uint32_t transN = locked_getTransactionId(); - for(; cit != msgPend->mMsgAuthV.end(); ++cit) - { - const MsgAuthEntry& entry = *cit; - - if(entry.mPassedVetting) - { - RsNxsSyncMsgItem* msgItem = new RsNxsSyncMsgItem(mServType); - msgItem->grpId = entry.mGrpId; - msgItem->msgId = entry.mMsgId; - msgItem->authorId = entry.mAuthorId; - msgItem->flag = RsNxsSyncMsgItem::FLAG_REQUEST; - msgItem->transactionNumber = transN; - msgItem->PeerId(msgPend->mPeerId); - reqList.push_back(msgItem); - } -#ifdef NXS_NET_DEBUG_1 - else - GXSNETDEBUG_PG(msgPend->mPeerId,entry.mGrpId) << " entry failed vetting: grpId=" << entry.mGrpId << ", msgId=" << entry.mMsgId << ", peerId=" << msgPend->mPeerId << std::endl; -#endif - } - - if(!reqList.empty()) - locked_pushMsgTransactionFromList(reqList, msgPend->mPeerId, transN) ; -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(msgPend->mPeerId) << " added " << reqList.size() << " items to transaction." << std::endl; -#endif -} - -void RsGxsNetService::locked_createTransactionFromPending(GrpRespPending* grpPend) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(grpPend->mPeerId) << "locked_createTransactionFromPending() from peer " << grpPend->mPeerId << std::endl; -#endif - GrpAuthorV::const_iterator cit = grpPend->mGrpAuthV.begin(); - std::list reqList; - uint32_t transN = locked_getTransactionId(); - for(; cit != grpPend->mGrpAuthV.end(); ++cit) - { - const GrpAuthEntry& entry = *cit; - - if(entry.mPassedVetting) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGrpId) << " entry Group Id: " << entry.mGrpId << " PASSED" << std::endl; -#endif - RsNxsSyncGrpItem* msgItem = new RsNxsSyncGrpItem(mServType); - msgItem->grpId = entry.mGrpId; - msgItem->authorId = entry.mAuthorId; - msgItem->flag = RsNxsSyncMsgItem::FLAG_REQUEST; - msgItem->transactionNumber = transN; - msgItem->PeerId(grpPend->mPeerId); - reqList.push_back(msgItem); - } -#ifdef NXS_NET_DEBUG_1 - else - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGrpId) << " entry failed vetting: grpId=" << entry.mGrpId << ", peerId=" << grpPend->mPeerId << std::endl; -#endif - } - - if(!reqList.empty()) - locked_pushGrpTransactionFromList(reqList, grpPend->mPeerId, transN); -} - - -bool RsGxsNetService::locked_createTransactionFromPending(GrpCircleIdRequestVetting* grpPend) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(grpPend->mPeerId) << "locked_createTransactionFromPending(GrpCircleIdReq)" << std::endl; -#endif - std::vector::iterator cit = grpPend->mGrpCircleV.begin(); - uint32_t transN = locked_getTransactionId(); - std::list itemL; - for(; cit != grpPend->mGrpCircleV.end(); ++cit) - { - const GrpIdCircleVet& entry = *cit; - - if(entry.mCleared) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " Group Id: " << entry.mGroupId << " PASSED" << std::endl; -#endif - RsNxsSyncGrpItem* gItem = new RsNxsSyncGrpItem(mServType); - gItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - gItem->grpId = entry.mGroupId; - gItem->publishTs = 0; - gItem->PeerId(grpPend->mPeerId); - gItem->transactionNumber = transN; - gItem->authorId = entry.mAuthorId; - // why it authorId not set here??? - - if(entry.mShouldEncrypt) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " item for this grpId should be encrypted." << std::endl; -#endif - RsNxsItem *encrypted_item = NULL ; - uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; - - if(encryptSingleNxsItem(gItem, entry.mCircleId, entry.mGroupId,encrypted_item,status)) - { - itemL.push_back(encrypted_item) ; - delete gItem ; - } -#ifdef NXS_NET_DEBUG_7 - else - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " Could not encrypt item for grpId " << entry.mGroupId << " for circle " << entry.mCircleId << ". Will try later. Adding to vetting list." << std::endl; -#endif - } - else - itemL.push_back(gItem); - } -#ifdef NXS_NET_DEBUG_1 - else - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " Group Id: " << entry.mGroupId << " FAILED" << std::endl; -#endif - } - - if(!itemL.empty()) - locked_pushGrpRespFromList(itemL, grpPend->mPeerId, transN); - - return true ; -} - -bool RsGxsNetService::locked_createTransactionFromPending(MsgCircleIdsRequestVetting* msgPend) -{ - std::vector::iterator vit = msgPend->mMsgs.begin(); - std::list itemL; - - uint32_t transN = locked_getTransactionId(); - RsGxsGroupId grp_id ; - - for(; vit != msgPend->mMsgs.end(); ++vit) - { - MsgIdCircleVet& mic = *vit; - RsNxsSyncMsgItem* mItem = new RsNxsSyncMsgItem(mServType); - mItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - mItem->grpId = msgPend->mGrpId; - mItem->msgId = mic.mMsgId; - mItem->authorId = mic.mAuthorId; - mItem->PeerId(msgPend->mPeerId); - mItem->transactionNumber = transN; - - grp_id = msgPend->mGrpId ; - - if(msgPend->mShouldEncrypt) - { - RsNxsItem *encrypted_item = NULL ; - uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; - - if(encryptSingleNxsItem(mItem,msgPend->mCircleId,msgPend->mGrpId,encrypted_item,status)) - { - itemL.push_back(encrypted_item) ; - delete mItem ; - } - else - { - std::cerr << "(EE) cannot encrypt Msg ids in circle-restriced response to grp " << msgPend->mGrpId << " for circle " << msgPend->mCircleId << std::endl; - return false ; - } - } - else - itemL.push_back(mItem); - } - - if(!itemL.empty()) - locked_pushMsgRespFromList(itemL, msgPend->mPeerId,grp_id, transN); - - return true ; -} - -/*bool RsGxsNetService::locked_canReceive(const RsGxsGrpMetaData * const grpMeta - , const RsPeerId& peerId ) -{ - - double timeDelta = 0.2; - - if(grpMeta->mCircleType == GXS_CIRCLE_TYPE_EXTERNAL) { - int i=0; - mCircles->loadCircle(grpMeta->mCircleId); - - // check 5 times at most - // spin for 1 second at most - while(i < 5) { - - if(mCircles->isLoaded(grpMeta->mCircleId)) { - const RsPgpId& pgpId = mPgpUtils->getPGPId(peerId); - return mCircles->canSend(grpMeta->mCircleId, pgpId); - }//if(mCircles->isLoaded(grpMeta->mCircleId)) - - usleep((int) (timeDelta * 1000 * 1000));// timeDelta sec - i++; - }//while(i < 5) - - } else {//if(grpMeta->mCircleType == GXS_CIRCLE_TYPE_EXTERNAL) - return true; - }//else (grpMeta->mCircleType == GXS_CIRCLE_TYPE_EXTERNAL) - - return false; -}*/ - -void RsGxsNetService::collateGrpFragments(GrpFragments fragments, - std::map& partFragments) const -{ - // get all unique grpIds; - GrpFragments::iterator vit = fragments.begin(); - std::set grpIds; - - for(; vit != fragments.end(); ++vit) - grpIds.insert( (*vit)->grpId ); - - std::set::iterator sit = grpIds.begin(); - - for(; sit != grpIds.end(); ++sit) - { - const RsGxsGroupId& grpId = *sit; - GrpFragments::iterator bound = std::partition( - fragments.begin(), fragments.end(), - GrpFragCollate(grpId)); - - // something will always be found for a group id - for(vit = fragments.begin(); vit != bound; ) - { - partFragments[grpId].push_back(*vit); - vit = fragments.erase(vit); - } - - GrpFragments& f = partFragments[grpId]; - RsNxsGrp* grp = *(f.begin()); - - // if counts of fragments is incorrect remove - // from coalescion - if(grp->count != f.size()) - { - GrpFragments::iterator vit2 = f.begin(); - - for(; vit2 != f.end(); ++vit2) - delete *vit2; - - partFragments.erase(grpId); - } - } - - fragments.clear(); -} - -struct MsgFragCollate -{ - RsGxsMessageId mMsgId; - MsgFragCollate(const RsGxsMessageId& msgId) : mMsgId(msgId){ } - bool operator()(RsNxsMsg* msg) { return msg->msgId == mMsgId;} -}; - -void RsGxsNetService::collateMsgFragments(MsgFragments& fragments, std::map& partFragments) const -{ - // get all unique message Ids; - MsgFragments::iterator vit = fragments.begin(); - std::set msgIds; - - for(; vit != fragments.end(); ++vit) - msgIds.insert( (*vit)->msgId ); - - - std::set::iterator sit = msgIds.begin(); - - for(; sit != msgIds.end(); ++sit) - { - const RsGxsMessageId& msgId = *sit; - MsgFragments::iterator bound = std::partition( - fragments.begin(), fragments.end(), - MsgFragCollate(msgId)); - - // something will always be found for a group id - for(vit = fragments.begin(); vit != bound; ++vit ) - { - partFragments[msgId].push_back(*vit); - } - - fragments.erase(fragments.begin(), bound); - MsgFragments& f = partFragments[msgId]; - RsNxsMsg* msg = *(f.begin()); - - // if counts of fragments is incorrect remove - // from coalescion - if(msg->count != f.size()) - { - MsgFragments::iterator vit2 = f.begin(); - - for(; vit2 != f.end(); ++vit2) - delete *vit2; - - partFragments.erase(msgId); - } - } - - fragments.clear(); -} - -class StoreHere -{ -public: - - StoreHere(RsGxsNetService::ClientGrpMap& cgm, RsGxsNetService::ClientMsgMap& cmm, RsGxsNetService::ServerMsgMap& smm,RsGxsNetService::GrpConfigMap& gcm, RsGxsServerGrpUpdate& sgm) - : mClientGrpMap(cgm), mClientMsgMap(cmm), mServerMsgMap(smm), mGrpConfigMap(gcm), mServerGrpUpdate(sgm) - {} - - template void check_store(ID_type id,UpdateMap& map,ItemClass& item) - { - if(!id.isNull()) - map.insert(std::make_pair(id,item)) ; - else - std::cerr << "(EE) loaded a null ID for class type " << typeid(map).name() << std::endl; - } - - void operator() (RsItem* item) - { - RsGxsMsgUpdateItem *mui; - RsGxsGrpUpdateItem *gui; - RsGxsServerGrpUpdateItem *gsui; - RsGxsServerMsgUpdateItem *msui; - RsGxsGrpConfigItem *mgci; - - if((mui = dynamic_cast(item)) != NULL) - check_store(mui->peerID,mClientMsgMap,*mui); - else if((mgci = dynamic_cast(item)) != NULL) - check_store(mgci->grpId,mGrpConfigMap, *mgci); - else if((gui = dynamic_cast(item)) != NULL) - check_store(gui->peerID,mClientGrpMap, *gui); - else if((msui = dynamic_cast(item)) != NULL) - check_store(msui->grpId,mServerMsgMap, *msui); - else if((gsui = dynamic_cast(item)) != NULL) - mServerGrpUpdate = *gsui; - else - std::cerr << "Type not expected!" << std::endl; - - delete item ; - } - -private: - - RsGxsNetService::ClientGrpMap& mClientGrpMap; - RsGxsNetService::ClientMsgMap& mClientMsgMap; - RsGxsNetService::ServerMsgMap& mServerMsgMap; - RsGxsNetService::GrpConfigMap& mGrpConfigMap; - - RsGxsServerGrpUpdate& mServerGrpUpdate; -}; - -bool RsGxsNetService::loadList(std::list &load) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - // The delete is done in StoreHere, if necessary - - std::for_each(load.begin(), load.end(), StoreHere(mClientGrpUpdateMap, mClientMsgUpdateMap, mServerMsgUpdateMap, mServerGrpConfigMap, mGrpServerUpdate)); - rstime_t now = time(NULL); - - // We reset group statistics here. This is the best place since we know at this point which are all unsubscribed groups. - - for(GrpConfigMap::iterator it(mServerGrpConfigMap.begin());it!=mServerGrpConfigMap.end();++it) - { - // At each reload, we reset the count of visible messages. It will be rapidely restored to its real value from friends. - - it->second.max_visible_count = 0; // std::max(it2->second.message_count,gnsr.max_visible_count) ; - - // the update time stamp is randomised so as not to ask all friends at once about group statistics. - - it->second.statistics_update_TS = now - GROUP_STATS_UPDATE_DELAY + (RSRandom::random_u32()%(GROUP_STATS_UPDATE_DELAY/10)) ; - - // Similarly, we remove all suppliers. - // Actual suppliers will come back automatically. - - it->second.suppliers.ids.clear() ; - - // also make sure that values stored for keep and req delays correspond to the canonical values - - locked_checkDelay(it->second.msg_req_delay); - locked_checkDelay(it->second.msg_keep_delay); - } - - return true; -} - -void RsGxsNetService::locked_checkDelay(uint32_t& time_in_secs) -{ - if(time_in_secs < 1 * 86400) { time_in_secs = 0 ; return ; } - if(time_in_secs <= 10 * 86400) { time_in_secs = 5 * 86400; return ; } - if(time_in_secs <= 20 * 86400) { time_in_secs = 15 * 86400; return ; } - if(time_in_secs <= 60 * 86400) { time_in_secs = 30 * 86400; return ; } - if(time_in_secs <= 120 * 86400) { time_in_secs = 90 * 86400; return ; } - if(time_in_secs <= 250 * 86400) { time_in_secs = 180 * 86400; return ; } - time_in_secs = 365 * 86400; -} - -#include - -template -struct get_second : public std::unary_function -{ - get_second(uint16_t serv_type,typename UpdateMap::key_type ItemClass::*member): mServType(serv_type),ID_member(member) {} - - RsItem* operator()(const typename UpdateMap::value_type& value) const - { - ItemClass *item = new ItemClass(value.second,mServType); - (*item).*ID_member = value.first ; - return item ; - } - - uint16_t mServType ; - typename UpdateMap::key_type ItemClass::*ID_member ; -}; - - -bool RsGxsNetService::saveList(bool& cleanup, std::list& save) -{ - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef NXS_NET_DEBUG_0 - std::cerr << "RsGxsNetService::saveList()..." << std::endl; -#endif - - // hardcore templates - std::transform(mClientGrpUpdateMap.begin(), mClientGrpUpdateMap.end(), std::back_inserter(save), get_second(mServType,&RsGxsGrpUpdateItem::peerID)); - std::transform(mClientMsgUpdateMap.begin(), mClientMsgUpdateMap.end(), std::back_inserter(save), get_second(mServType,&RsGxsMsgUpdateItem::peerID)); - std::transform(mServerMsgUpdateMap.begin(), mServerMsgUpdateMap.end(), std::back_inserter(save), get_second(mServType,&RsGxsServerMsgUpdateItem::grpId)); - std::transform(mServerGrpConfigMap.begin(), mServerGrpConfigMap.end(), std::back_inserter(save), get_second(mServType,&RsGxsGrpConfigItem::grpId)); - - RsGxsServerGrpUpdateItem *it = new RsGxsServerGrpUpdateItem(mGrpServerUpdate,mServType) ; - - save.push_back(it); - - cleanup = true; - return true; -} - -RsSerialiser *RsGxsNetService::setupSerialiser() -{ - - RsSerialiser *rss = new RsSerialiser; - rss->addSerialType(new RsGxsUpdateSerialiser(mServType)); - - return rss; -} - -RsItem *RsGxsNetService::generic_recvItem() -{ - { - RsItem *item ; - - if(NULL != (item=recvItem())) - return item ; - } - - unsigned char *data = NULL ; - uint32_t size = 0 ; - RsGxsNetTunnelVirtualPeerId virtual_peer_id ; - - while(mAllowDistSync && mGxsNetTunnel!=NULL && mGxsNetTunnel->receiveTunnelData(mServType,data,size,virtual_peer_id)) - { - RsNxsItem *item = dynamic_cast(RsNxsSerialiser(mServType).deserialise(data,&size)) ; - item->PeerId(virtual_peer_id) ; - - free(data) ; - - if(!item) - continue ; - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG_P_(item->PeerId()) << "Received RsGxsNetTunnelService Item:" << (void*)item << " of type: " << std::hex << item->PacketId() << std::dec - << " transaction " << item->transactionNumber << " from virtual peer " << item->PeerId() << std::endl ; -#endif - return item ; - } - - return NULL ; -} - -void RsGxsNetService::recvNxsItemQueue() -{ - RsItem *item ; - - while(NULL != (item=generic_recvItem())) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(item->PeerId()) << "Received RsGxsNetService Item:" << (void*)item << " type=" << std::hex << item->PacketId() << std::dec << std::endl ; -#endif - // RsNxsItem needs dynamic_cast, since they have derived siblings. - // - RsNxsItem *ni = dynamic_cast(item) ; - if(ni != NULL) - { - // a live transaction has a non zero value - if(ni->transactionNumber != 0) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(item->PeerId()) << " recvNxsItemQueue() handlingTransaction, transN " << ni->transactionNumber << std::endl; -#endif - - if(!handleTransaction(ni)) - delete ni; - - continue; - } - - // Check whether the item is encrypted. If so, try to decrypt it, and replace ni with the decrypted item.. - - bool item_was_encrypted = false ; - - if(ni->PacketSubType() == RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM) - { - RsNxsItem *decrypted_item ; - - if(decryptSingleNxsItem(dynamic_cast(ni),decrypted_item)) - { - item = ni = decrypted_item ; - item_was_encrypted = true ; -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(item->PeerId()) << " decrypted item " << std::endl; -#endif - } -#ifdef NXS_NET_DEBUG_7 - else - GXSNETDEBUG_P_(item->PeerId()) << " (EE) Could not decrypt incoming encrypted NXS item. Probably a friend subscribed to a circle-restricted group." << std::endl; -#endif - } - - switch(ni->PacketSubType()) - { - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM: handleRecvSyncGrpStatistics (dynamic_cast(ni)) ; break ; - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM: handleRecvSyncGroup (dynamic_cast(ni)) ; break ; - case RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM: handleRecvSyncMessage (dynamic_cast(ni),item_was_encrypted) ; break ; - case RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM:handleRecvPublishKeys (dynamic_cast(ni)) ; break ; - - default: - if(ni->PacketSubType() != RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM) - { - std::cerr << "Unhandled item subtype " << (uint32_t) ni->PacketSubType() << " in RsGxsNetService: " << std::endl ; break ; - } - } - delete item ; - } - else - { - std::cerr << "Not a RsNxsItem, deleting!" << std::endl; - delete(item); - } - } -} - - -bool RsGxsNetService::handleTransaction(RsNxsItem* item) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(item->PeerId()) << "handleTransaction(RsNxsItem) number=" << item->transactionNumber << std::endl; -#endif - - /*! - * This attempts to handle a transaction - * It first checks if this transaction id already exists - * If it does then check this not a initiating transactions - */ - - RS_STACK_MUTEX(mNxsMutex) ; - - const RsPeerId& peer = item->PeerId(); - - RsNxsTransacItem* transItem = dynamic_cast(item); - - // if this is a RsNxsTransac item process - if(transItem) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(item->PeerId()) << " this is a RsNxsTransac item. callign process." << std::endl; -#endif - return locked_processTransac(transItem); - } - - - // then this must be transaction content to be consumed - // first check peer exist for transaction - bool peerTransExists = mTransactions.find(peer) != mTransactions.end(); - - // then check transaction exists - - NxsTransaction* tr = NULL; - uint32_t transN = item->transactionNumber; - - if(peerTransExists) - { - TransactionIdMap& transMap = mTransactions[peer]; - - if(transMap.find(transN) != transMap.end()) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(item->PeerId()) << " Consuming Transaction content, transN: " << item->transactionNumber << std::endl; - GXSNETDEBUG_P_(item->PeerId()) << " Consuming Transaction content, from Peer: " << item->PeerId() << std::endl; -#endif - - tr = transMap[transN]; - tr->mItems.push_back(item); - - return true; - } - } - - return false; -} - -bool RsGxsNetService::locked_processTransac(RsNxsTransacItem *item) -{ - - /*! - * To process the transaction item - * It can either be initiating a transaction - * or ending one that already exists - * - * For initiating an incoming transaction the peer - * and transaction item need not exists - * as the peer will be added and transaction number - * added thereafter - * - * For commencing/starting an outgoing transaction - * the transaction must exist already - * - * For ending a transaction the - */ - - RsPeerId peer; - - // for outgoing transaction use own id - if(item->transactFlag & (RsNxsTransacItem::FLAG_BEGIN_P2 | RsNxsTransacItem::FLAG_END_SUCCESS)) - peer = mOwnId; - else - peer = item->PeerId(); - - uint32_t transN = item->transactionNumber; - item->timestamp = time(NULL); // register time received - NxsTransaction* tr = NULL; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << "locked_processTransac() " << std::endl; - GXSNETDEBUG_P_(peer) << " Received transaction item: " << transN << std::endl; - GXSNETDEBUG_P_(peer) << " With peer: " << item->PeerId() << std::endl; - GXSNETDEBUG_P_(peer) << " trans type: " << item->transactFlag << std::endl; -#endif - - bool peerTrExists = mTransactions.find(peer) != mTransactions.end(); - bool transExists = false; - - if(peerTrExists) - { - TransactionIdMap& transMap = mTransactions[peer]; - // record whether transaction exists already - transExists = transMap.find(transN) != transMap.end(); - } - - // initiating an incoming transaction - if(item->transactFlag & RsNxsTransacItem::FLAG_BEGIN_P1) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " initiating Incoming transaction." << std::endl; -#endif - - if(transExists) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " transaction already exist! ERROR" << std::endl; -#endif - return false; // should not happen! - } - - // create a transaction if the peer does not exist - if(!peerTrExists) - mTransactions[peer] = TransactionIdMap(); - - TransactionIdMap& transMap = mTransactions[peer]; - - - // create new transaction - tr = new NxsTransaction(); - transMap[transN] = tr; - tr->mTransaction = item; - tr->mTimeOut = item->timestamp + mTransactionTimeOut; -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " Setting timeout of " << mTransactionTimeOut << " secs, which is " << tr->mTimeOut - time(NULL) << " secs from now." << std::endl; -#endif - - // note state as receiving, commencement item - // is sent on next run() loop - tr->mFlag = NxsTransaction::FLAG_STATE_STARTING; - return true; - // commencement item for outgoing transaction - } - else if(item->transactFlag & RsNxsTransacItem::FLAG_BEGIN_P2) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " initiating outgoign transaction." << std::endl; -#endif - // transaction must exist - if(!peerTrExists || !transExists) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " transaction does not exist. Cancelling!" << std::endl; -#endif - - return false; - } - - - // alter state so transaction content is sent on - // next run() loop - TransactionIdMap& transMap = mTransactions[mOwnId]; - NxsTransaction* tr = transMap[transN]; - tr->mFlag = NxsTransaction::FLAG_STATE_SENDING; - delete item; - return true; - // end transac item for outgoing transaction - } - else if(item->transactFlag & RsNxsTransacItem::FLAG_END_SUCCESS) - { - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " marking this transaction succeed" << std::endl; -#endif - // transaction does not exist - if(!peerTrExists || !transExists) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " transaction does not exist. Cancelling!" << std::endl; -#endif - return false; - } - - // alter state so that transaction is removed - // on next run() loop - TransactionIdMap& transMap = mTransactions[mOwnId]; - NxsTransaction* tr = transMap[transN]; - tr->mFlag = NxsTransaction::FLAG_STATE_COMPLETED; - delete item; - return true; - } - else - return false; -} - -void RsGxsNetService::threadTick() -{ - static const double timeDelta = 0.5; - - //Start waiting as nothing to do in runup - rstime::rs_usleep((int) (timeDelta * 1000 * 1000)); // timeDelta sec - - if(mUpdateCounter >= 120) // 60 seconds - { - updateServerSyncTS(); -#ifdef TO_REMOVE - updateClientSyncTS(); -#endif - mUpdateCounter = 1; - } - else - mUpdateCounter++; - - if(mUpdateCounter % 20 == 0) // dump the full shit every 20 secs - debugDump() ; - - // process active transactions - processTransactions(); - - // process completed transactions - processCompletedTransactions(); - - // vetting of id and circle info - runVetting(); - - processExplicitGroupRequests(); -} - -void RsGxsNetService::debugDump() -{ -#ifdef NXS_NET_DEBUG_0 - RS_STACK_MUTEX(mNxsMutex) ; - //rstime_t now = time(NULL) ; - - GXSNETDEBUG___<< "RsGxsNetService::debugDump():" << std::endl; - - RsGxsGrpMetaTemporaryMap grpMetas; - - if(!group_id_to_print.isNull()) - grpMetas[group_id_to_print] = NULL ; - - mDataStore->retrieveGxsGrpMetaData(grpMetas); - - GXSNETDEBUG___<< " mGrpServerUpdateItem time stamp: " << nice_time_stamp(time(NULL) , mGrpServerUpdate.grpUpdateTS) << " (is the last local modification time over all groups of this service)" << std::endl; - - GXSNETDEBUG___<< " mServerMsgUpdateMap: (is for each subscribed group, the last local modification time)" << std::endl; - - for(ServerMsgMap::const_iterator it(mServerMsgUpdateMap.begin());it!=mServerMsgUpdateMap.end();++it) - { - RsGxsGrpMetaTemporaryMap::const_iterator it2 = grpMetas.find(it->first) ; - auto grpMeta = (it2 != grpMetas.end())? it2->second : (std::shared_ptr()) ; - std::string subscribe_string = (grpMeta==NULL)?"Unknown" : ((grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED)?" Subscribed":" NOT Subscribed") ; - - GXSNETDEBUG__G(it->first) << " Grp:" << it->first << " last local modification (secs ago): " << nice_time_stamp(time(NULL),it->second.msgUpdateTS) << ", " << subscribe_string << std::endl; - } - - GXSNETDEBUG___<< " mClientGrpUpdateMap: (is for each friend, last modif time of group meta data at that friend, all groups included, sent by the friend himself)" << std::endl; - - for(std::map::const_iterator it(mClientGrpUpdateMap.begin());it!=mClientGrpUpdateMap.end();++it) - GXSNETDEBUG_P_(it->first) << " From peer: " << it->first << " - last updated at peer (secs ago): " << nice_time_stamp(time(NULL),it->second.grpUpdateTS) << std::endl; - - GXSNETDEBUG___<< " mClientMsgUpdateMap: (is for each friend, the modif time for each group (e.g. last message received), sent by the friend himself)" << std::endl; - - for(std::map::const_iterator it(mClientMsgUpdateMap.begin());it!=mClientMsgUpdateMap.end();++it) - { - GXSNETDEBUG_P_(it->first) << " From peer: " << it->first << std::endl; - - for(std::map::const_iterator it2(it->second.msgUpdateInfos.begin());it2!=it->second.msgUpdateInfos.end();++it2) - GXSNETDEBUG_PG(it->first,it2->first) << " group " << it2->first << " - last updated at peer (secs ago): " << nice_time_stamp(time(NULL),it2->second.time_stamp) << ". Message count=" << it2->second.message_count << std::endl; - } - - GXSNETDEBUG___<< " List of rejected message ids: " << std::dec << mRejectedMessages.size() << std::endl; -#endif -} - -#ifdef TO_REMOVE -// This method is normally not needed, but we use it to correct possible inconsistencies in the updte time stamps -// on the client side. - -void RsGxsNetService::updateClientSyncTS() -{ - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___<< "updateClientSyncTS(): checking last modification time stamps of local data w.r.t. client's modification times" << std::endl; -#endif - - if(mGrpServerUpdateItem == NULL) - mGrpServerUpdateItem = new RsGxsServerGrpUpdateItem(mServType); - - for(ClientGrpMap::iterator it = mClientGrpUpdateMap.begin();it!=mClientGrpUpdateMap.end();++it) - if(it->second->grpUpdateTS > SECURITY_DELAY_TO_FORCE_CLIENT_REUPDATE + mGrpServerUpdateItem->grpUpdateTS) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(it->first) << " last global client GRP modification time known for peer (" << nice_time_stamp(time(NULL),it->second->grpUpdateTS) << " is quite more recent than our own server modification time (" << nice_time_stamp(time(NULL),mGrpServerUpdateItem->grpUpdateTS) << ". Forcing update! " << std::endl; -#endif - it->second->grpUpdateTS = 0 ; - } - - for(ClientMsgMap::iterator it = mClientMsgUpdateMap.begin();it!=mClientMsgUpdateMap.end();++it) - for(std::map::iterator it2 = it->second->msgUpdateInfos.begin();it2!=it->second->msgUpdateInfos.end();++it2) - { - std::map::const_iterator mmit = mServerMsgUpdateMap.find(it2->first) ; - - if(mmit != mServerMsgUpdateMap.end() && it2->second.time_stamp > SECURITY_DELAY_TO_FORCE_CLIENT_REUPDATE + mmit->second->msgUpdateTS) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(it->first,it2->first) << " last group msg modification time known for peer (" << nice_time_stamp(time(NULL),it2->second.time_stamp) << " and group " << it2->first << " is quite more recent than our own server modification time (" << nice_time_stamp(time(NULL),mmit->second->msgUpdateTS) << ". Forcing update! " << std::endl; -#endif - it2->second.time_stamp = 0 ; - } - } -} -#endif - -void RsGxsNetService::updateServerSyncTS() -{ - RsGxsGrpMetaTemporaryMap gxsMap; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___<< "updateServerSyncTS(): updating last modification time stamp of local data." << std::endl; -#endif - - { - RS_STACK_MUTEX(mNxsMutex) ; - // retrieve all grps and update TS - mDataStore->retrieveGxsGrpMetaData(gxsMap); - - // (cyril) This code was previously removed because it sounded inconsistent: the list of grps normally does not need to be updated when - // new posts arrive. The two (grp list and msg list) are handled independently. Still, when group meta data updates are received, - // the server TS needs to be updated, because it is the only way to propagate the changes. So we update it to the publish time stamp, - // if needed. - - // as a grp list server also note this is the latest item you have - // then remove from mServerMsgUpdateMap, all items that are not in the group list! - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << " cleaning server map of groups with no data:" << std::endl; -#endif - - for(ServerMsgMap::iterator it(mServerMsgUpdateMap.begin());it!=mServerMsgUpdateMap.end();) - if(gxsMap.find(it->first) == gxsMap.end()) - { - // not found! Removing server update info for this group - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(it->first) << " removing server update info for group " << it->first << std::endl; -#endif - ServerMsgMap::iterator tmp(it) ; - ++tmp ; - mServerMsgUpdateMap.erase(it) ; - it = tmp ; - } - else - ++it; - } - -#ifdef NXS_NET_DEBUG_0 - if(gxsMap.empty()) - GXSNETDEBUG___<< " database seems to be empty. The modification timestamp will be reset." << std::endl; -#endif - // finally, update timestamps. - bool change = false; - - for(auto mit = gxsMap.begin();mit != gxsMap.end(); ++mit) - { - // Check if the group is subscribed and restricted to a circle. If the circle has changed, update the - // global TS to reflect that change to clients who may be able to see/subscribe to that particular group. - - if( (mit->second->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) && !mit->second->mCircleId.isNull()) - { - // ask to the GxsNetService of circles what the server TS is for that circle. If more recent, we update the serverTS of the - // local group - - rstime_t circle_group_server_ts ; - rstime_t circle_msg_server_ts ; - - // This call needs to be off-mutex, because of self-restricted circles. - // Normally we should update as a function of MsgServerUpdateTS and the mRecvTS of the circle, not the global grpServerTS. - // But grpServerTS is easier to get since it does not require a db access. So we trade the real call for this cheap and conservative call. - - if(mCircles->getLocalCircleServerUpdateTS(mit->second->mCircleId,circle_group_server_ts,circle_msg_server_ts)) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(mit->first) << " Group " << mit->first << " is conditionned to circle " << mit->second->mCircleId << ". local Grp TS=" << time(NULL) - mGrpServerUpdate.grpUpdateTS << " secs ago, circle grp server update TS=" << time(NULL) - circle_group_server_ts << " secs ago"; -#endif - // We use a max here between grp and msg TS because membership is driven by invite list (grp data) crossed with - // membership requests messages (msg data). - - auto circle_membership_ts = std::max(circle_group_server_ts,circle_msg_server_ts); - - if(circle_membership_ts > mGrpServerUpdate.grpUpdateTS) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(mit->first) << " - Updating local Grp Server update TS to follow changes in circles." << std::endl; -#endif - - RS_STACK_MUTEX(mNxsMutex) ; - mGrpServerUpdate.grpUpdateTS = circle_membership_ts ; - } -#ifdef NXS_NET_DEBUG_0 - else - GXSNETDEBUG__G(mit->first) << " - Nothing to do." << std::endl; -#endif - } - else - std::cerr << "(EE) Cannot retrieve attached circle TS" << std::endl; - } - - RS_STACK_MUTEX(mNxsMutex) ; - - const auto& grpMeta = mit->second; -#ifdef TO_REMOVE - // That accounts for modification of the meta data. - - if(mGrpServerUpdateItem->grpUpdateTS < grpMeta->mPublishTs) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(grpId) << " publish time stamp of group " << grpId << " has changed to " << time(NULL)-grpMeta->mPublishTs << " secs ago. updating!" << std::endl; -#endif - mGrpServerUpdateItem->grpUpdateTS = grpMeta->mPublishTs; - } -#endif - - // I keep the creation, but the data is not used yet. -#warning csoler 2016-12-12: Disabled this, but do we need it? - // RsGxsServerMsgUpdate& msui(mServerMsgUpdateMap[grpId]) ; - - // (cyril) I'm removing this, because the msgUpdateTS is updated when new messages are received by calling locked_stampMsgServerUpdateTS(). - // mLastPost is actually updated somewhere when loading group meta data. It's not clear yet whether it is set to the latest publish time (wrong) - // or the latest receive time (right). The former would cause problems because it would need to compare times coming from different (potentially async-ed) - // machines. - // - // if(grpMeta->mLastPost > msui->msgUpdateTS ) - // { - // change = true; - // msui->msgUpdateTS = grpMeta->mLastPost; -#ifdef NXS_NET_DEBUG_0 - // GXSNETDEBUG__G(grpId) << " updated msgUpdateTS to last post = " << time(NULL) - grpMeta->mLastPost << " secs ago for group "<< grpId << std::endl; -#endif - // } - - // This is needed for group metadata updates to actually propagate: only a new grpUpdateTS will trigger the exchange of groups mPublishTs which - // will then be compared and pssibly trigger a MetaData transmission. mRecvTS is upated when creating, receiving for the first time, or receiving - // an update, all in rsgenexchange.cc, after group/update validation. It is therefore a local TS, that can be compared to grpUpdateTS (same machine). - - if(mGrpServerUpdate.grpUpdateTS < grpMeta->mRecvTS) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(grpMeta->mGroupId) << " updated msgUpdateTS to last RecvTS = " << time(NULL) - grpMeta->mRecvTS << " secs ago for group "<< grpMeta->mGroupId << ". This is probably because an update has been received." << std::endl; -#endif - mGrpServerUpdate.grpUpdateTS = grpMeta->mRecvTS; - change = true; - } - } - - // actual change in config settings, then save configuration - if(change) - IndicateConfigChanged(); -} - -bool RsGxsNetService::locked_checkTransacTimedOut(NxsTransaction* tr) -{ - return tr->mTimeOut < ((uint32_t) time(NULL)); -} - -void RsGxsNetService::processTransactions() -{ - RS_STACK_MUTEX(mNxsMutex) ; - - for(TransactionsPeerMap::iterator mit = mTransactions.begin();mit != mTransactions.end(); ++mit) - { -#ifdef NXS_NET_DEBUG_1 - if(!mit->second.empty()) - GXSNETDEBUG_P_(mit->first) << "processTransactions from/to peer " << mit->first << std::endl; -#endif - - TransactionIdMap& transMap = mit->second; - TransactionIdMap::iterator mmit = transMap.begin(), mmit_end = transMap.end(); - - if(mmit == mmit_end) // no waiting transactions for this peer - continue ; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " peerId=" << mit->first << std::endl; -#endif - // transaction to be removed - std::list toRemove; - - /*! - * Transactions owned by peer - */ - if(mit->first == mOwnId) - { - for(; mmit != mmit_end; ++mmit) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " type: outgoing " << std::endl; - GXSNETDEBUG_P_(mit->first) << " transN = " << mmit->second->mTransaction->transactionNumber << std::endl; -#endif - NxsTransaction* tr = mmit->second; - uint16_t flag = tr->mFlag; - std::list::iterator lit, lit_end; - uint32_t transN = tr->mTransaction->transactionNumber; - - // first check transaction has not expired - if(locked_checkTransacTimedOut(tr)) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " timeout! " << std::endl; - GXSNETDEBUG_P_(mit->first) << std::dec ; - int total_transaction_time = (int)time(NULL) - (tr->mTimeOut - mTransactionTimeOut) ; - GXSNETDEBUG_P_(mit->first) << " Outgoing Transaction has failed, tranN: " << transN << ", Peer: " << mit->first ; - GXSNETDEBUG_P_(mit->first) << ", age: " << total_transaction_time << ", nItems=" << tr->mTransaction->nItems << ". tr->mTimeOut = " << tr->mTimeOut << ", now = " << (uint32_t) time(NULL) << std::endl; -#endif - - tr->mFlag = NxsTransaction::FLAG_STATE_FAILED; - toRemove.push_back(transN); - mComplTransactions.push_back(tr); - continue; - } -#ifdef NXS_NET_DEBUG_1 - else - GXSNETDEBUG_P_(mit->first) << " still on time." << std::endl; -#endif - - // send items requested - if(flag & NxsTransaction::FLAG_STATE_SENDING) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first)<< " Sending Transaction content, transN: " << transN << " with peer: " << tr->mTransaction->PeerId() << std::endl; -#endif - lit = tr->mItems.begin(); - lit_end = tr->mItems.end(); - - for(; lit != lit_end; ++lit){ - generic_sendItem(*lit); - } - - tr->mItems.clear(); // clear so they don't get deleted in trans cleaning - tr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - - } - else if(flag & NxsTransaction::FLAG_STATE_WAITING_CONFIRM) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first)<< " Waiting confirm! returning." << std::endl; -#endif - continue; - - } - else if(flag & NxsTransaction::FLAG_STATE_COMPLETED) - { - -#ifdef NXS_NET_DEBUG_1 - int total_transaction_time = (int)time(NULL) - (tr->mTimeOut - mTransactionTimeOut) ; - - GXSNETDEBUG_P_(mit->first)<< " Outgoing completed " << tr->mTransaction->nItems << " items transaction in " << total_transaction_time << " seconds." << std::endl; -#endif - // move to completed transactions - toRemove.push_back(transN); - mComplTransactions.push_back(tr); - }else{ - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first)<< " Unknown flag for active transaction, transN: " << transN << ", Peer: " << mit->first<< std::endl; -#endif - - toRemove.push_back(transN); - tr->mFlag = NxsTransaction::FLAG_STATE_FAILED; - mComplTransactions.push_back(tr); - } - } - - }else{ - - /*! - * Essentially these are incoming transactions - * Several states are dealth with - * Receiving: waiting to receive items from peer's transaction - * and checking if all have been received - * Completed: remove transaction from active and tell peer - * involved in transaction - * Starting: this is a new transaction and need to teell peer - * involved in transaction - */ - - for(; mmit != mmit_end; ++mmit){ - - NxsTransaction* tr = mmit->second; - uint16_t flag = tr->mFlag; - uint32_t transN = tr->mTransaction->transactionNumber; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " type: incoming " << std::endl; - GXSNETDEBUG_P_(mit->first) << " transN = " << mmit->second->mTransaction->transactionNumber << std::endl; -#endif - // first check transaction has not expired - if(locked_checkTransacTimedOut(tr)) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " timeout!" << std::endl; - GXSNETDEBUG_P_(mit->first) << std::dec ; - int total_transaction_time = (int)time(NULL) - (tr->mTimeOut - mTransactionTimeOut) ; - GXSNETDEBUG_P_(mit->first) << " Incoming Transaction has failed, tranN: " << transN << ", Peer: " << mit->first ; - GXSNETDEBUG_P_(mit->first) << ", age: " << total_transaction_time << ", nItems=" << tr->mTransaction->nItems << ". tr->mTimeOut = " << tr->mTimeOut << ", now = " << (uint32_t) time(NULL) << std::endl; -#endif - - tr->mFlag = NxsTransaction::FLAG_STATE_FAILED; - toRemove.push_back(transN); - mComplTransactions.push_back(tr); - continue; - } - - if(flag & NxsTransaction::FLAG_STATE_RECEIVING) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " received " << tr->mItems.size() << " item over a total of " << tr->mTransaction->nItems << std::endl; -#endif - - // if the number it item received equal that indicated - // then transaction is marked as completed - // to be moved to complete transations - // check if done - if(tr->mItems.size() == tr->mTransaction->nItems) - { - tr->mFlag = NxsTransaction::FLAG_STATE_COMPLETED; -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " completed!" << std::endl; -#endif - } - - }else if(flag & NxsTransaction::FLAG_STATE_COMPLETED) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " transaction is completed!" << std::endl; - GXSNETDEBUG_P_(mit->first) << " sending success!" << std::endl; -#endif - - // send completion msg - RsNxsTransacItem* trans = new RsNxsTransacItem(mServType); - trans->clear(); - trans->transactFlag = RsNxsTransacItem::FLAG_END_SUCCESS; - trans->transactionNumber = transN; - trans->PeerId(tr->mTransaction->PeerId()); - generic_sendItem(trans); - - // move to completed transactions - - // Try to decrypt the items that need to be decrypted. This function returns true if the transaction is not encrypted. - - if(processTransactionForDecryption(tr)) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " successfully decrypted/processed transaction " << transN << ". Adding to completed list." << std::endl; -#endif - mComplTransactions.push_back(tr); - - // transaction processing done - // for this id, add to removal list - toRemove.push_back(mmit->first); -#ifdef NXS_NET_DEBUG_1 - int total_transaction_time = (int)time(NULL) - (tr->mTimeOut - mTransactionTimeOut) ; - GXSNETDEBUG_P_(mit->first) << " incoming completed " << tr->mTransaction->nItems << " items transaction in " << total_transaction_time << " seconds." << std::endl; -#endif - } - else - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " no decryption occurred because of unloaded keys. Will retry later. TransN=" << transN << std::endl; -#endif - } - - - } - else if(flag & NxsTransaction::FLAG_STATE_STARTING) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " transaction is starting!" << std::endl; - GXSNETDEBUG_P_(mit->first) << " setting state to Receiving" << std::endl; -#endif - // send item to tell peer your are ready to start - RsNxsTransacItem* trans = new RsNxsTransacItem(mServType); - trans->clear(); - trans->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P2 | - (tr->mTransaction->transactFlag & RsNxsTransacItem::FLAG_TYPE_MASK); - trans->transactionNumber = transN; - trans->PeerId(tr->mTransaction->PeerId()); - generic_sendItem(trans); - tr->mFlag = NxsTransaction::FLAG_STATE_RECEIVING; - - } - else{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " transaction is in unknown state. ERROR!" << std::endl; - GXSNETDEBUG_P_(mit->first) << " transaction FAILS!" << std::endl; -#endif - - std::cerr << " Unknown flag for active transaction, transN: " << transN << ", Peer: " << mit->first << std::endl; - toRemove.push_back(mmit->first); - mComplTransactions.push_back(tr); - tr->mFlag = NxsTransaction::FLAG_STATE_FAILED; // flag as a failed transaction - } - } - } - - std::list::iterator lit = toRemove.begin(); - - for(; lit != toRemove.end(); ++lit) - { - transMap.erase(*lit); - } - - } -} - -bool RsGxsNetService::getGroupNetworkStats(const RsGxsGroupId& gid,RsGroupNetworkStats& stats) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - GrpConfigMap::const_iterator it ( mServerGrpConfigMap.find(gid) ); - - if(it == mServerGrpConfigMap.end()) - return false ; - - stats.mSuppliers = it->second.suppliers.ids.size(); - stats.mMaxVisibleCount = it->second.max_visible_count ; - stats.mAllowMsgSync = mAllowMsgSync ; - stats.mGrpAutoSync = mGrpAutoSync ; - stats.mLastGroupModificationTS = it->second.last_group_modification_TS ; - - return true ; -} - -void RsGxsNetService::processCompletedTransactions() -{ - RS_STACK_MUTEX(mNxsMutex) ; - /*! - * Depending on transaction we may have to respond to peer - * responsible for transaction - */ - while(mComplTransactions.size()>0) - { - - NxsTransaction* tr = mComplTransactions.front(); - - bool outgoing = tr->mTransaction->PeerId() == mOwnId; - - if(outgoing){ - locked_processCompletedOutgoingTrans(tr); - }else{ - locked_processCompletedIncomingTrans(tr); - } - - - delete tr; - mComplTransactions.pop_front(); - } -} - -void RsGxsNetService::locked_processCompletedIncomingTrans(NxsTransaction* tr) -{ - uint16_t flag = tr->mTransaction->transactFlag; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << "Processing complete Incoming transaction with " << tr->mTransaction->nItems << " items." << std::endl; - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " flags = " << flag << std::endl; - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " peerId= " << tr->mTransaction->PeerId() << std::endl; -#endif - if(tr->mFlag & NxsTransaction::FLAG_STATE_COMPLETED) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " transaction has completed." << std::endl; -#endif - // for a completed list response transaction - // one needs generate requests from this - if(flag & RsNxsTransacItem::FLAG_TYPE_MSG_LIST_RESP) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = msg list response." << std::endl; - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " => generate msg request based on it." << std::endl; -#endif - // generate request based on a peers response - locked_genReqMsgTransaction(tr); - - }else if(flag & RsNxsTransacItem::FLAG_TYPE_GRP_LIST_RESP) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = grp list response." << std::endl; - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " => generate group transaction request based on it." << std::endl; -#endif - locked_genReqGrpTransaction(tr); - } - // you've finished receiving request information now gen - else if(flag & RsNxsTransacItem::FLAG_TYPE_MSG_LIST_REQ) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = msg list request." << std::endl; - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " => generate msg list based on it." << std::endl; -#endif - locked_genSendMsgsTransaction(tr); - } - else if(flag & RsNxsTransacItem::FLAG_TYPE_GRP_LIST_REQ) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = grp list request." << std::endl; - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " => generate grp list based on it." << std::endl; -#endif - locked_genSendGrpsTransaction(tr); - } - else if(flag & RsNxsTransacItem::FLAG_TYPE_GRPS) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = groups." << std::endl; -#endif - std::vector grps; - - while(tr->mItems.size() != 0) - { - RsNxsGrp* grp = dynamic_cast(tr->mItems.front()); - - if(grp) - { - tr->mItems.pop_front(); - grps.push_back(grp); -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grp->grpId) << " adding new group " << grp->grpId << " to incoming list!" << std::endl; -#endif - } - else - std::cerr << " /!\\ item did not caste to grp" << std::endl; - } - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " ...and notifying observer " << std::endl; -#endif -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_ (tr->mTransaction->PeerId()) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - Received new groups meta data from peer " << tr->mTransaction->PeerId() << std::endl; - for(uint32_t i=0;imTransaction->PeerId(),grps[i]->grpId) ; -#endif - // notify listener of grps - for(uint32_t i=0;imTransaction->PeerId(); - uint32_t updateTS = tr->mTransaction->updateTS; - -#ifdef NXS_NET_DEBUG_0 - ClientGrpMap::iterator it = mClientGrpUpdateMap.find(peerFrom); -#endif - - RsGxsGrpUpdate& item(mClientGrpUpdateMap[peerFrom]) ; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " and updating mClientGrpUpdateMap for peer " << peerFrom << " of new time stamp " << nice_time_stamp(time(NULL),updateTS) << std::endl; -#endif - - item.grpUpdateTS = updateTS; - - IndicateConfigChanged(); - } - else if(flag & RsNxsTransacItem::FLAG_TYPE_MSGS) - { - - std::vector msgs; -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = msgs." << std::endl; -#endif - RsGxsGroupId grpId; - //rstime_t now = time(NULL) ; - - while(tr->mItems.size() > 0) - { - RsNxsMsg* msg = dynamic_cast(tr->mItems.front()); - if(msg) - { - if(grpId.isNull()) - grpId = msg->grpId; - - tr->mItems.pop_front(); - - msgs.push_back(msg); -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),msg->grpId) << " pushing grpId="<< msg->grpId << ", msgsId=" << msg->msgId << " to list of incoming messages" << std::endl; -#endif - } - else - std::cerr << "RsGxsNetService::processCompletedTransactions(): item did not caste to msg" << std::endl; - } - -//#warning We need here to queue all incoming items into a list where the vetting will be checked -//#warning in order to avoid someone without the proper rights to post in a group protected with an external circle - -#ifdef NXS_FRAG - // (cyril) This code does not work. Since we do not really need message fragmenting, I won't fix it. - - std::map collatedMsgs; - collateMsgFragments(msgs, collatedMsgs); // this destroys msgs whatsoever and recovers memory when needed - - msgs.clear(); - - std::map::iterator mit = collatedMsgs.begin(); - for(; mit != collatedMsgs.end(); ++mit) - { - MsgFragments& f = mit->second; - RsNxsMsg* msg = deFragmentMsg(f); - - if(msg) - msgs.push_back(msg); - } - collatedMsgs.clear(); -#endif -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " ...and notifying observer of " << msgs.size() << " new messages." << std::endl; -#endif -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_PG (tr->mTransaction->PeerId(),grpId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - Received new messages from peer " << tr->mTransaction->PeerId() << " for group " << grpId << std::endl; - for(uint32_t i=0;imTransaction->PeerId(),grpId) << " " << msgs[i]->msgId << std::endl ; -#endif - // notify listener of msgs - for(uint32_t i=0;imTransaction, grpId); - - // also update server sync TS, since we need to send the new message list to friends for comparison - locked_stampMsgServerUpdateTS(grpId); - } - } - else if(tr->mFlag == NxsTransaction::FLAG_STATE_FAILED) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " transaction has failed. Wasting it." << std::endl; -#endif - // don't do anything transaction will simply be cleaned - } - return; -} - -void RsGxsNetService::locked_doMsgUpdateWork(const RsNxsTransacItem *nxsTrans, const RsGxsGroupId &grpId) -{ -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(nxsTrans->PeerId(),grpId) << "updating MsgUpdate time stamps for peerId=" << nxsTrans->PeerId() << ", grpId=" << grpId << std::endl; -#endif - // firts check if peer exists - const RsPeerId& peerFrom = nxsTrans->PeerId(); - - if(peerFrom.isNull()) - { - std::cerr << "(EE) update from null peer!" << std::endl; - print_stacktrace() ; - } - - RsGxsMsgUpdate& mui(mClientMsgUpdateMap[peerFrom]) ; - - // now update the peer's entry for this grp id - - if(mPartialMsgUpdates[peerFrom].find(grpId) != mPartialMsgUpdates[peerFrom].end()) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(nxsTrans->PeerId(),grpId) << " this is a partial update. Not using new time stamp." << std::endl; -#endif - } - else - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(nxsTrans->PeerId(),grpId) << " this is a full update. Updating time stamp." << std::endl; -#endif - mui.msgUpdateInfos[grpId].time_stamp = nxsTrans->updateTS; - IndicateConfigChanged(); - } -} - -void RsGxsNetService::locked_processCompletedOutgoingTrans(NxsTransaction* tr) -{ - uint16_t flag = tr->mTransaction->transactFlag; - -#ifdef NXS_NET_DEBUG_0 - RsNxsTransacItem *nxsTrans = tr->mTransaction; - GXSNETDEBUG_P_(nxsTrans->PeerId()) << "locked_processCompletedOutgoingTrans(): tr->flags = " << flag << std::endl; -#endif - - if(tr->mFlag & NxsTransaction::FLAG_STATE_COMPLETED) - { - // for a completed list response transaction - // one needs generate requests from this - if(flag & RsNxsTransacItem::FLAG_TYPE_MSG_LIST_RESP) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Msg List Response, transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - }else if(flag & RsNxsTransacItem::FLAG_TYPE_GRP_LIST_RESP) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Grp Response, transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - } - // you've finished sending a request so don't do anything - else if( (flag & RsNxsTransacItem::FLAG_TYPE_MSG_LIST_REQ) || - (flag & RsNxsTransacItem::FLAG_TYPE_GRP_LIST_REQ) ) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Msg/Grp Request, transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - - }else if(flag & RsNxsTransacItem::FLAG_TYPE_GRPS) - { - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Grp Data, transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - - }else if(flag & RsNxsTransacItem::FLAG_TYPE_MSGS) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Msg Data, transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - } - }else if(tr->mFlag == NxsTransaction::FLAG_STATE_FAILED){ -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " Failed transaction! transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - }else{ - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " Serious error unrecognised trans Flag! transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - } -} - - -void RsGxsNetService::locked_pushMsgTransactionFromList(std::list& reqList, const RsPeerId& peerId, const uint32_t& transN) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peerId) << "locked_pushMsgTransactionFromList()" << std::endl; - GXSNETDEBUG_P_(peerId) << " nelems = " << reqList.size() << std::endl; - GXSNETDEBUG_P_(peerId) << " peerId = " << peerId << std::endl; - GXSNETDEBUG_P_(peerId) << " transN = " << transN << std::endl; -#endif -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_ (peerId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending message request to peer " - << peerId << " for " << reqList.size() << " messages" << std::endl; -#endif - RsNxsTransacItem* transac = new RsNxsTransacItem(mServType); - transac->transactFlag = RsNxsTransacItem::FLAG_TYPE_MSG_LIST_REQ - | RsNxsTransacItem::FLAG_BEGIN_P1; - transac->timestamp = 0; - transac->nItems = reqList.size(); - transac->PeerId(peerId); - transac->transactionNumber = transN; - NxsTransaction* newTrans = new NxsTransaction(); - newTrans->mItems = reqList; - newTrans->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - newTrans->mTimeOut = time(NULL) + mTransactionTimeOut; - // create transaction copy with your id to indicate - // its an outgoing transaction - newTrans->mTransaction = new RsNxsTransacItem(*transac); - newTrans->mTransaction->PeerId(mOwnId); - - if (locked_addTransaction(newTrans)) - generic_sendItem(transac); - else - { - delete newTrans; - delete transac; - } - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peerId) << " Requested new transaction for " << reqList.size() << " items." << std::endl; -#endif -} - -void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr) -{ - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG___ << "RsGxsNetService::genReqMsgTransaction()" << std::endl; -#endif - - // to create a transaction you need to know who you are transacting with - // then what msgs to request - // then add an active Transaction for request - - std::list msgItemL; - std::list::iterator lit = tr->mItems.begin(); - - // first get item list sent from transaction - for(; lit != tr->mItems.end(); ++lit) - { - RsNxsSyncMsgItem* item = dynamic_cast(*lit); - if(item) - { - msgItemL.push_back(item); - }else - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(item->PeerId()) << "RsGxsNetService::genReqMsgTransaction(): item failed cast to RsNxsSyncMsgItem* " << std::endl; -#endif - } - } -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " found " << msgItemL.size()<< " messages in this transaction." << std::endl; -#endif - - if(msgItemL.empty()) - return; - - // get grp id for this transaction - RsNxsSyncMsgItem* item = msgItemL.front(); - const RsGxsGroupId& grpId = item->grpId; - - // store the count for the peer who sent the message list - uint32_t mcount = msgItemL.size() ; - RsPeerId pid = msgItemL.front()->PeerId() ; - - RsGxsGrpConfig& gnsr(locked_getGrpConfig(grpId)); - - std::set::size_type oldSuppliersCount = gnsr.suppliers.ids.size(); - uint32_t oldVisibleCount = gnsr.max_visible_count; - - gnsr.suppliers.ids.insert(pid) ; - gnsr.max_visible_count = std::max(gnsr.max_visible_count, mcount) ; - - if (oldVisibleCount != gnsr.max_visible_count || oldSuppliersCount != gnsr.suppliers.ids.size()) - mNewStatsToNotify.insert(grpId) ; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " grpId = " << grpId << std::endl; - GXSNETDEBUG_PG(item->PeerId(),grpId) << " retrieving grp mesta data..." << std::endl; -#endif - RsGxsGrpMetaTemporaryMap grpMetaMap; - grpMetaMap[grpId] = NULL; - - mDataStore->retrieveGxsGrpMetaData(grpMetaMap); - const auto& grpMeta = grpMetaMap[grpId]; - - if(grpMeta == NULL) // this should not happen, but just in case... - { - std::cerr << "(EE) grpMeta is NULL in " << __PRETTY_FUNCTION__ << " line " << __LINE__ << ". This is very unexpected." << std::endl; - return ; - } - - if(! (grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED )) - { - // For unsubscribed groups, we update the timestamp something more recent, so that the group content will not be asked to the same - // peer again, unless the peer has new info about it. It's important to use the same clock (this is peer's clock) so that - // we never compare times from different (and potentially badly sync-ed clocks) - - std::cerr << "(EE) stepping in part of the code (" << __PRETTY_FUNCTION__ << ") where we shouldn't. This is a bug." << std::endl; - -#ifdef TO_REMOVE - locked_stampPeerGroupUpdateTime(pid,grpId,tr->mTransaction->updateTS,msgItemL.size()) ; -#endif - return ; - } - -#ifdef TO_REMOVE - int cutoff = 0; - if(grpMeta != NULL) - cutoff = grpMeta->mReputationCutOff; -#endif - - GxsMsgReq reqIds; - reqIds[grpId] = std::set(); - GxsMsgMetaResult result; - mDataStore->retrieveGxsMsgMetaData(reqIds, result); - auto& msgMetaV = result[grpId]; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " retrieving grp message list..." << std::endl; - GXSNETDEBUG_PG(item->PeerId(),grpId) << " grp locally contains " << msgMetaV.size() << " messsages." << std::endl; -#endif - std::set msgIdSet; - - // put ids in set for each searching - for(auto vit=msgMetaV.begin(); vit != msgMetaV.end(); ++vit) - msgIdSet.insert((*vit)->mMsgId); - - msgMetaV.clear(); - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " grp locally contains " << msgIdSet.size() << " unique messsages." << std::endl; -#endif - // get unique id for this transaction - uint32_t transN = locked_getTransactionId(); - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " new transaction ID: " << transN << std::endl; -#endif - // add msgs that you don't have to request list - std::list::iterator llit = msgItemL.begin(); - std::list reqList; - int reqListSize = 0 ; - - const RsPeerId peerFrom = tr->mTransaction->PeerId(); - - std::list peers; - peers.push_back(tr->mTransaction->PeerId()); - bool reqListSizeExceeded = false ; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " sorting items..." << std::endl; -#endif - for(; llit != msgItemL.end(); ++llit) - { - RsNxsSyncMsgItem*& syncItem = *llit; - const RsGxsMessageId& msgId = syncItem->msgId; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " msg ID = " << msgId ; -#endif - if(reqListSize >= (int)MAX_REQLIST_SIZE) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << ". reqlist too big. Pruning out this item for now." << std::endl; -#endif - reqListSizeExceeded = true ; - continue ; // we should actually break, but we need to print some debug info. - } - - if(reqListSize < (int)MAX_REQLIST_SIZE && msgIdSet.find(msgId) == msgIdSet.end()) - { - - bool noAuthor = syncItem->authorId.isNull(); - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << ", reqlist size=" << reqListSize << ", message not present." ; -#endif - // grp meta must be present if author present - - if(!noAuthor && grpMeta == NULL) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << ", no group meta found. Givign up." << std::endl; -#endif - continue; - } - - // The algorithm on request of message is: - // - // - always re-check for author ban level - // - if author is locally banned, do not download. - // - if author is not locally banned, download, whatever friends' opinion might be. - - if( mReputations->overallReputationLevel(syncItem->authorId) == - RsReputationLevel::LOCALLY_NEGATIVE ) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << ", Identity " << syncItem->authorId << " is banned. Not requesting message!" << std::endl; -#endif - continue ; - } - - if(mRejectedMessages.find(msgId) != mRejectedMessages.end()) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << ", message has been recently rejected. Not requesting message!" << std::endl; -#endif - continue ; - } - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << ", passed! Adding message to req list." << std::endl; -#endif - RsNxsSyncMsgItem* msgItem = new RsNxsSyncMsgItem(mServType); - msgItem->grpId = grpId; - msgItem->msgId = msgId; - msgItem->flag = RsNxsSyncMsgItem::FLAG_REQUEST; - msgItem->transactionNumber = transN; - msgItem->PeerId(peerFrom); - reqList.push_back(msgItem); - ++reqListSize ; - } -#ifdef NXS_NET_DEBUG_1 - else - GXSNETDEBUG_PG(item->PeerId(),grpId) << ". already here." << std::endl; -#endif - } - - if(!reqList.empty()) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " Request list: " << reqList.size() << " elements." << std::endl; -#endif - locked_pushMsgTransactionFromList(reqList, tr->mTransaction->PeerId(), transN); - - if(reqListSizeExceeded) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " Marking update operation as unfinished." << std::endl; -#endif - mPartialMsgUpdates[tr->mTransaction->PeerId()].insert(item->grpId) ; - } - else - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " Marking update operation as terminal." << std::endl; -#endif - mPartialMsgUpdates[tr->mTransaction->PeerId()].erase(item->grpId) ; - } - } - else - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " Request list is empty. Not doing anything. " << std::endl; -#endif - // The list to req is empty. That means we already have all messages that this peer can - // provide. So we can stamp the group from this peer to be up to date. - - // Part of this is already achieved in two other places: - // - the GroupStats exchange system, which counts the messages at each peer. It could also supply TS for the messages, but it does not for the time being - // - client TS are updated when receiving messages - - locked_stampPeerGroupUpdateTime(pid,grpId,tr->mTransaction->updateTS,msgItemL.size()) ; - } -} - -void RsGxsNetService::locked_stampPeerGroupUpdateTime(const RsPeerId& pid,const RsGxsGroupId& grpId,rstime_t tm,uint32_t n_messages) -{ - RsGxsMsgUpdate& up(mClientMsgUpdateMap[pid]); - - up.msgUpdateInfos[grpId].time_stamp = tm; - up.msgUpdateInfos[grpId].message_count = std::max(n_messages, up.msgUpdateInfos[grpId].message_count) ; - - IndicateConfigChanged(); -} - -void RsGxsNetService::locked_pushGrpTransactionFromList( std::list& reqList, const RsPeerId& peerId, const uint32_t& transN) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peerId) << "locked_pushGrpTransactionFromList()" << std::endl; - GXSNETDEBUG_P_(peerId) << " nelems = " << reqList.size() << std::endl; - GXSNETDEBUG_P_(peerId) << " peerId = " << peerId << std::endl; - GXSNETDEBUG_P_(peerId) << " transN = " << transN << std::endl; -#endif -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_ (peerId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending group request to peer " - << peerId << " for " << reqList.size() << " groups" << std::endl; -#endif - RsNxsTransacItem* transac = new RsNxsTransacItem(mServType); - transac->transactFlag = RsNxsTransacItem::FLAG_TYPE_GRP_LIST_REQ - | RsNxsTransacItem::FLAG_BEGIN_P1; - transac->timestamp = 0; - transac->nItems = reqList.size(); - transac->PeerId(peerId); - transac->transactionNumber = transN; - NxsTransaction* newTrans = new NxsTransaction(); - newTrans->mItems = reqList; - newTrans->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - newTrans->mTimeOut = time(NULL) + mTransactionTimeOut; - newTrans->mTransaction = new RsNxsTransacItem(*transac); - newTrans->mTransaction->PeerId(mOwnId); - - if (locked_addTransaction(newTrans)) - generic_sendItem(transac); - else - { - delete newTrans; - delete transac; - } -} -void RsGxsNetService::addGroupItemToList(NxsTransaction*& tr, const RsGxsGroupId& grpId, uint32_t& transN, std::list& reqList) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << "RsGxsNetService::addGroupItemToList() Added GroupID: << grpId" << std::endl; -#endif - - RsNxsSyncGrpItem* grpItem = new RsNxsSyncGrpItem(mServType); - grpItem->PeerId(tr->mTransaction->PeerId()); - grpItem->grpId = grpId; - grpItem->flag = RsNxsSyncMsgItem::FLAG_REQUEST; - grpItem->transactionNumber = transN; - reqList.push_back(grpItem); -} - -void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr) -{ - // to create a transaction you need to know who you are transacting with - // then what grps to request - // then add an active Transaction for request - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << "locked_genReqGrpTransaction(): " << std::endl; -#endif - - std::list grpItemL; - RsGxsGrpMetaTemporaryMap grpMetaMap; - - for(std::list::iterator lit = tr->mItems.begin(); lit != tr->mItems.end(); ++lit) - { - RsNxsSyncGrpItem* item = dynamic_cast(*lit); - if(item) - { - grpItemL.push_back(item); - grpMetaMap[item->grpId] = NULL; - } - else - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),item->grpId) << "RsGxsNetService::genReqGrpTransaction(): item failed to caste to RsNxsSyncMsgItem* " << std::endl; -#endif - } - } - - if (grpItemL.empty()) - { - // Normally the client grp updateTS is set after the transaction, but if no transaction is to happen, we have to set it here. - // Possible change: always do the update of the grpClientTS here. Needs to be tested... - - RsGxsGrpUpdate& item (mClientGrpUpdateMap[tr->mTransaction->PeerId()]); - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " reqList is empty, updating anyway ClientGrpUpdate TS for peer " << tr->mTransaction->PeerId() << " to: " << tr->mTransaction->updateTS << std::endl; -#endif - - if(item.grpUpdateTS != tr->mTransaction->updateTS) - { - item.grpUpdateTS = tr->mTransaction->updateTS; - IndicateConfigChanged(); - } - return; - } - - mDataStore->retrieveGxsGrpMetaData(grpMetaMap); - - // now do compare and add loop - std::list::iterator llit = grpItemL.begin(); - std::list reqList; - - uint32_t transN = locked_getTransactionId(); - - std::list peers; - peers.push_back(tr->mTransaction->PeerId()); - - for(; llit != grpItemL.end(); ++llit) - { - RsNxsSyncGrpItem*& grpSyncItem = *llit; - const RsGxsGroupId& grpId = grpSyncItem->grpId; - - auto metaIter = grpMetaMap.find(grpId); - bool haveItem = false; - bool latestVersion = false; - - if (metaIter != grpMetaMap.end() && metaIter->second) - { - haveItem = true; - latestVersion = grpSyncItem->publishTs > metaIter->second->mPublishTs; - } - // FIXTESTS global variable rsReputations not available in unittests! - - if( mReputations->overallReputationLevel(RsGxsId(grpSyncItem->grpId)) == RsReputationLevel::LOCALLY_NEGATIVE ) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Identity " << grpSyncItem->grpId << " is banned. Not GXS-syncing group." << std::endl; -#endif - continue ; - } - - if( (mGrpAutoSync && !haveItem) || latestVersion) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Identity " << grpId << " will be sync-ed using GXS. mGrpAutoSync:" << mGrpAutoSync << " haveItem:" << haveItem << " latest_version: " << latestVersion << std::endl; -#endif - addGroupItemToList(tr, grpId, transN, reqList); - } - } - - if(!reqList.empty()) - locked_pushGrpTransactionFromList(reqList, tr->mTransaction->PeerId(), transN); - else - { - // Normally the client grp updateTS is set after the transaction, but if no transaction is to happen, we have to set it here. - // Possible change: always do the update of the grpClientTS here. Needs to be tested... - - RsGxsGrpUpdate& item (mClientGrpUpdateMap[tr->mTransaction->PeerId()]); - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " reqList is empty, updating anyway ClientGrpUpdate TS for peer " << tr->mTransaction->PeerId() << " to: " << tr->mTransaction->updateTS << std::endl; -#endif - - if(item.grpUpdateTS != tr->mTransaction->updateTS) - { - item.grpUpdateTS = tr->mTransaction->updateTS; - IndicateConfigChanged(); - } - } - -} - -void RsGxsNetService::locked_genSendGrpsTransaction(NxsTransaction* tr) -{ - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << "locked_genSendGrpsTransaction() Generating Grp data send from TransN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - - // go groups requested in transaction tr - - std::list::iterator lit = tr->mItems.begin(); - - t_RsGxsGenericDataTemporaryMap grps ; - - for(;lit != tr->mItems.end(); ++lit) - { - RsNxsSyncGrpItem* item = dynamic_cast(*lit); - if (item) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),item->grpId) << "locked_genSendGrpsTransaction() retrieving data for group \"" << item->grpId << "\"" << std::endl; -#endif - grps[item->grpId] = NULL; - } - else - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),item->grpId) << "RsGxsNetService::locked_genSendGrpsTransaction(): item failed to caste to RsNxsSyncGrpItem* " << std::endl; -#endif - } - } - - if(!grps.empty()) - mDataStore->retrieveNxsGrps(grps, false); - else - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << "RsGxsNetService::locked_genSendGrpsTransaction(): no group to request! This is unexpected" << std::endl; -#endif - return; - } - - NxsTransaction* newTr = new NxsTransaction(); - newTr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - - uint32_t transN = locked_getTransactionId(); - - // store grp items to send in transaction - std::map::iterator mit = grps.begin(); - RsPeerId peerId = tr->mTransaction->PeerId(); - for(;mit != grps.end(); ++mit) - { -#warning csoler: Should make sure that no private key information is sneaked in here for the grp - mit->second->PeerId(peerId); // set so it gets sent to right peer - mit->second->transactionNumber = transN; - newTr->mItems.push_back(mit->second); - mit->second = NULL ; // avoids deletion -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),mit->first) << "RsGxsNetService::locked_genSendGrpsTransaction(): adding grp data of group \"" << mit->first << "\" to transaction" << std::endl; -#endif - } - - if(newTr->mItems.empty()){ - delete newTr; - return; - } - - uint32_t updateTS = 0; - updateTS = mGrpServerUpdate.grpUpdateTS; - -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_ (tr->mTransaction->PeerId()) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending global group TS " - << updateTS << " to peer " << tr->mTransaction->PeerId() << std::endl; -#endif - RsNxsTransacItem* ntr = new RsNxsTransacItem(mServType); - ntr->transactionNumber = transN; - ntr->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P1 | RsNxsTransacItem::FLAG_TYPE_GRPS; - ntr->updateTS = updateTS; - ntr->nItems = grps.size(); - ntr->PeerId(tr->mTransaction->PeerId()); - - newTr->mTransaction = new RsNxsTransacItem(*ntr); - newTr->mTransaction->PeerId(mOwnId); - newTr->mTimeOut = time(NULL) + mTransactionTimeOut; - - ntr->PeerId(tr->mTransaction->PeerId()); - - if(locked_addTransaction(newTr)) - generic_sendItem(ntr); - else - { - delete ntr ; - delete newTr; - } - - return; -} - -void RsGxsNetService::runVetting() -{ - // The vetting operation consists in transforming pending group/msg Id requests and grp/msg content requests - // into real transactions, based on the authorisations of the Peer Id these transactions are targeted to using the - // reputation system. - // - - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef TO_BE_REMOVED - // Author response vetting is disabled since not used, as the reputations are currently not async-ed anymore. - - std::vector::iterator vit = mPendingResp.begin(); - - for(; vit != mPendingResp.end(); ) - { - AuthorPending* ap = *vit; - - if(ap->accepted() || ap->expired()) - { - // add to transactions - if(AuthorPending::MSG_PEND == ap->getType()) - { - MsgRespPending* mrp = static_cast(ap); - locked_createTransactionFromPending(mrp); - } - else if(AuthorPending::GRP_PEND == ap->getType()) - { - GrpRespPending* grp = static_cast(ap); - locked_createTransactionFromPending(grp); - }else - std::cerr << "RsGxsNetService::runVetting(): Unknown pending type! Type: " << ap->getType() << std::endl; - - delete ap; - vit = mPendingResp.erase(vit); - } - else - { - ++vit; - } - - } -#endif - - - // now lets do circle vetting - std::vector::iterator vit2 = mPendingCircleVets.begin(); - for(; vit2 != mPendingCircleVets.end(); ) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG___ << " Examining/clearing pending vetting of type " << (*vit2)->getType() << std::endl; -#endif - GrpCircleVetting*& gcv = *vit2; - if(gcv->cleared() || gcv->expired()) - { - if(gcv->getType() == GrpCircleVetting::GRP_ID_PEND) - { - GrpCircleIdRequestVetting* gcirv = static_cast(gcv); -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_P_(gcirv->mPeerId) << " vetting is a GRP ID PENDING Response" << std::endl; -#endif - - if(!locked_createTransactionFromPending(gcirv)) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_P_(gcirv->mPeerId) << " Response sent!" << std::endl; -#endif - ++vit2 ; - continue ; - } - } - else if(gcv->getType() == GrpCircleVetting::MSG_ID_SEND_PEND) - { - MsgCircleIdsRequestVetting* mcirv = static_cast(gcv); - -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_P_(mcirv->mPeerId) << " vetting is a MSG ID PENDING Response" << std::endl; -#endif - if(mcirv->cleared()) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_P_(mcirv->mPeerId) << " vetting cleared! Sending..." << std::endl; -#endif - if(!locked_createTransactionFromPending(mcirv)) - continue ; // keep it in the list for retry - } - } - else - { -#ifdef NXS_NET_DEBUG_4 - std::cerr << "RsGxsNetService::runVetting(): Unknown Circle pending type! Type: " << gcv->getType() << std::endl; -#endif - } - - delete gcv; - vit2 = mPendingCircleVets.erase(vit2); - } - else - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG___ << " ... not cleared yet." << std::endl; -#endif - ++vit2; - } - } -} - -void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr) -{ -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << "locked_genSendMsgsTransaction() Generating Msg data send fron TransN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - - // go groups requested in transaction tr - - std::list::iterator lit = tr->mItems.begin(); - - GxsMsgReq msgIds; - GxsMsgResult msgs; - - if(tr->mItems.empty()){ - return; - } - - // hacky assumes a transaction only consist of a single grpId - RsGxsGroupId grpId; - - for(;lit != tr->mItems.end(); ++lit) - { - RsNxsSyncMsgItem* item = dynamic_cast(*lit); - if (item) - { - msgIds[item->grpId].insert(item->msgId); - - if(grpId.isNull()) - grpId = item->grpId; - else if(grpId != item->grpId) - { - std::cerr << "RsGxsNetService::locked_genSendMsgsTransaction(): transaction on two different groups! ERROR!" << std::endl; - return ; - } - } - else - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << "RsGxsNetService::locked_genSendMsgsTransaction(): item failed to caste to RsNxsSyncMsgItem* " << std::endl; -#endif - } - } - -#ifdef CODE_TO_ENCRYPT_MESSAGE_DATA - // now if transaction is limited to an external group, encrypt it for members of the group. - - RsGxsCircleId encryption_circle ; - std::map grp; - grp[grpId] = NULL ; - - mDataStore->retrieveGxsGrpMetaData(grp); - - RsGxsGrpMetaData *grpMeta = grp[grpId] ; - - if(grpMeta == NULL) - { - std::cerr << "(EE) cannot retrieve group meta data for message transaction " << tr->mTransaction->transactionNumber << std::endl; - return ; - } - - encryption_circle = grpMeta->mCircleId ; - delete grpMeta ; - grp.clear() ; -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Msg transaction items will be encrypted for circle " << std::endl; -#endif -#endif - - mDataStore->retrieveNxsMsgs(msgIds, msgs, false); - - NxsTransaction* newTr = new NxsTransaction(); - newTr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - - uint32_t transN = locked_getTransactionId(); - - // store msg items to send in transaction - GxsMsgResult::iterator mit = msgs.begin(); - RsPeerId peerId = tr->mTransaction->PeerId(); - uint32_t msgSize = 0; - - for(;mit != msgs.end(); ++mit) - { - std::vector& msgV = mit->second; - std::vector::iterator vit = msgV.begin(); - - for(; vit != msgV.end(); ++vit) - { - RsNxsMsg* msg = *vit; - msg->PeerId(peerId); - msg->transactionNumber = transN; - - // Quick trick to clamp messages with an exceptionnally large size. Signature will fail on client side, and the message - // will be rejected. - - if(msg->msg.bin_len > MAX_ALLOWED_GXS_MESSAGE_SIZE) - { - std::cerr << "(WW) message with ID " << msg->msgId << " in group " << msg->grpId << " exceeds size limit of " << MAX_ALLOWED_GXS_MESSAGE_SIZE << " bytes. Actual size is " << msg->msg.bin_len << " bytes. Message will be truncated and rejected at client." << std::endl; - msg->msg.bin_len = 1 ; // arbitrary small size, but not 0. No need to send the data since it's going to be rejected. - } - -#ifdef NXS_FRAG - MsgFragments fragments; - fragmentMsg(*msg, fragments); - - delete msg ; - - MsgFragments::iterator mit = fragments.begin(); - - for(; mit != fragments.end(); ++mit) - { - newTr->mItems.push_back(*mit); - msgSize++; - } -#else - - msg->count = 1; // only one piece. This is to keep compatibility if we ever implement fragmenting in the future. - msg->pos = 0; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),msg->grpId) << " sending msg Id " << msg->msgId << " in Group " << msg->grpId << std::endl; -#endif - - newTr->mItems.push_back(msg); - msgSize++; -#endif - -#ifdef CODE_TO_ENCRYPT_MESSAGE_DATA - // encrypt - - if(!encryption_circle.isNull()) - { - uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; - - RsNxsEncryptedDataItem encrypted_msg_item = NULL ; - - if(encryptSingleNxsItem(msg,encryption_circle,encrypted_msg_item,status)) - { - newTr->mItems.push_back(msg); - delete msg ; - } - else - { - } - } - else - { - newTr->mItems.push_back(msg); - - msgSize++; - } -#endif - } - } - - if(newTr->mItems.empty()){ - delete newTr; - return; - } - - // now send a transaction item and store the transaction data - - uint32_t updateTS = mServerMsgUpdateMap[grpId].msgUpdateTS; - - RsNxsTransacItem* ntr = new RsNxsTransacItem(mServType); - ntr->transactionNumber = transN; - ntr->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P1 | - RsNxsTransacItem::FLAG_TYPE_MSGS; - ntr->updateTS = updateTS; - ntr->nItems = msgSize; - ntr->PeerId(peerId); - - newTr->mTransaction = new RsNxsTransacItem(*ntr); - newTr->mTransaction->PeerId(mOwnId); - newTr->mTimeOut = time(NULL) + mTransactionTimeOut; - -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_PG (peerId,grpId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending message update to peer " << peerId << " for group " << grpId << " with TS=" << nice_time_stamp(time(NULL),updateTS) <<" (secs ago)" << std::endl; - -#endif - ntr->PeerId(tr->mTransaction->PeerId()); - - if(locked_addTransaction(newTr)) - generic_sendItem(ntr); - else - { - delete ntr ; - delete newTr; - } - - return; -} -uint32_t RsGxsNetService::locked_getTransactionId() -{ - return ++mTransactionN; -} -bool RsGxsNetService::locked_addTransaction(NxsTransaction* tr) -{ - const RsPeerId& peer = tr->mTransaction->PeerId(); -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << "locked_addTransaction() " << std::endl; -#endif - uint32_t transN = tr->mTransaction->transactionNumber; - TransactionIdMap& transMap = mTransactions[peer]; - bool transNumExist = transMap.find(transN) != transMap.end(); - - if(transNumExist) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " Transaction number exist already, transN: " << transN << std::endl; -#endif - return false; - } - - transMap[transN] = tr; - - return true; -} - -// Turns a single RsNxsItem into an encrypted one, suitable for the supplied destination circle. -// Returns false when the keys are not loaded. Question to solve: what do we do if we miss some keys?? -// We should probably send anyway. - -bool RsGxsNetService::encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, const RsGxsGroupId& destination_group, RsNxsItem *&encrypted_item, uint32_t& status) -{ - encrypted_item = NULL ; - status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_ (item->PeerId()) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - Encrypting single item for peer " << item->PeerId() << ", for circle ID " << destination_circle << std::endl; -#endif - // 1 - Find out the list of GXS ids to encrypt for - // We could do smarter things (like see if the peer_id owns one of the circle's identities - // but for now we aim at the simplest solution: encrypt for all identities in the circle. - - std::list recipients ; - - if(!mCircles->recipients(destination_circle,destination_group,recipients)) - { - std::cerr << " (EE) Cannot encrypt transaction: recipients list not available. Should re-try later." << std::endl; - status = RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR ; - return false ; - } - - if(recipients.empty()) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(item->PeerId()) << " (EE) No recipients found for circle " << destination_circle << ". Circle not in cache, or empty circle?" << std::endl; -#endif - return false ; - } - -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_ (item->PeerId()) << " Dest Ids: " << std::endl; -#endif - std::vector recipient_keys ; - - for(std::list::const_iterator it(recipients.begin());it!=recipients.end();++it) - { - RsTlvPublicRSAKey pkey ; - - if(!mGixs->getKey(*it,pkey)) - { - std::cerr << " (EE) Cannot retrieve public key " << *it << " for circle encryption. Should retry later?" << std::endl; - - // we should probably request the key? - status = RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING ; - continue ; - } -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_ (item->PeerId()) << " added key " << *it << std::endl; -#endif - recipient_keys.push_back(pkey) ; - } - - // 2 - call GXSSecurity to make a header item that encrypts for the given list of peers. - -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_ (item->PeerId()) << " Encrypting..." << std::endl; -#endif - uint32_t size = RsNxsSerialiser(mServType).size(item) ; - RsTemporaryMemory tempmem( size ) ; - - if(!RsNxsSerialiser(mServType).serialise(item,tempmem,&size)) - { - std::cerr << " (EE) Cannot serialise item. Something went wrong." << std::endl; - status = RS_NXS_ITEM_ENCRYPTION_STATUS_SERIALISATION_ERROR ; - return false ; - } - - unsigned char *encrypted_data = NULL ; - uint32_t encrypted_len = 0 ; - - if(!GxsSecurity::encrypt(encrypted_data, encrypted_len,tempmem,size,recipient_keys)) - { - std::cerr << " (EE) Cannot multi-encrypt item. Something went wrong." << std::endl; - status = RS_NXS_ITEM_ENCRYPTION_STATUS_ENCRYPTION_ERROR ; - return false ; - } - - RsNxsEncryptedDataItem *enc_item = new RsNxsEncryptedDataItem(mServType) ; - - enc_item->encrypted_data.bin_len = encrypted_len ; - enc_item->encrypted_data.bin_data = encrypted_data ; - - // also copy all the important data. - - enc_item->transactionNumber = item->transactionNumber ; - enc_item->PeerId(item->PeerId()) ; - - encrypted_item = enc_item ; -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(item->PeerId()) << " encrypted item of size " << encrypted_len << std::endl; -#endif - status = RS_NXS_ITEM_ENCRYPTION_STATUS_NO_ERROR ; - - return true ; -} - -// Tries to decrypt the transaction. First load the keys and process all items. -// If keys are loaded, encrypted items that cannot be decrypted are discarded. -// Otherwise the transaction is untouched for retry later. - -bool RsGxsNetService::processTransactionForDecryption(NxsTransaction *tr) -{ -#ifdef NXS_NET_DEBUG_7 - RsPeerId peerId = tr->mTransaction->PeerId() ; - GXSNETDEBUG_P_(peerId) << "RsGxsNetService::decryptTransaction()" << std::endl; -#endif - - std::list decrypted_items ; - std::vector private_keys ; - - // get all private keys. Normally we should look into the circle name and only supply the keys that we have - - for(std::list::iterator it(tr->mItems.begin());it!=tr->mItems.end();) - { - RsNxsEncryptedDataItem *encrypted_item = dynamic_cast(*it) ; - - if(encrypted_item == NULL) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(peerId) << " skipping unencrypted item..." << std::endl; -#endif - ++it ; - continue ; - } - - // remove the encrypted item. After that it points to the next item to handle - it = tr->mItems.erase(it) ; - - RsNxsItem *nxsitem = NULL ; - - if(decryptSingleNxsItem(encrypted_item,nxsitem,&private_keys)) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(peerId) << " Replacing the encrypted item with the clear one." << std::endl; -#endif - tr->mItems.insert(it,nxsitem) ; // inserts before it, so no need to ++it - } - - delete encrypted_item ; - } - - return true ; -} - -bool RsGxsNetService::decryptSingleNxsItem(const RsNxsEncryptedDataItem *encrypted_item, RsNxsItem *& nxsitem,std::vector *pprivate_keys) -{ - // if private_keys storage is supplied use/update them, otherwise, find which key should be used, and store them in a local std::vector. - - nxsitem = NULL ; - std::vector local_keys ; - std::vector& private_keys = pprivate_keys?(*pprivate_keys):local_keys ; - - // we need the private keys to decrypt the item. First load them in! - bool key_loading_failed = false ; - - if(private_keys.empty()) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(encrypted_item->PeerId()) << " need to retrieve private keys..." << std::endl; -#endif - - std::list own_keys ; - mGixs->getOwnIds(own_keys) ; - - for(std::list::const_iterator it(own_keys.begin());it!=own_keys.end();++it) - { - RsTlvPrivateRSAKey private_key ; - - if(mGixs->getPrivateKey(*it,private_key)) - { - private_keys.push_back(private_key) ; -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(encrypted_item->PeerId())<< " retrieved private key " << *it << std::endl; -#endif - } - else - { - std::cerr << " (EE) Cannot retrieve private key for ID " << *it << std::endl; - key_loading_failed = true ; - break ; - } - } - } - if(key_loading_failed) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(encrypted_item->PeerId()) << " Some keys not loaded.Returning false to retry later." << std::endl; -#endif - return false ; - } - - // we do this only when something actually needs to be decrypted. - - unsigned char *decrypted_mem = NULL; - uint32_t decrypted_len =0; - -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(encrypted_item->PeerId())<< " Trying to decrypt item..." ; -#endif - - if(!GxsSecurity::decrypt(decrypted_mem,decrypted_len, (uint8_t*)encrypted_item->encrypted_data.bin_data,encrypted_item->encrypted_data.bin_len,private_keys)) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(encrypted_item->PeerId()) << " Failed! Cannot decrypt this item." << std::endl; -#endif - decrypted_mem = NULL ; // for safety - return false ; - } -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(encrypted_item->PeerId())<< " Succeeded! deserialising..." << std::endl; -#endif - - // deserialise the item - - RsItem *ditem = NULL ; - - if(decrypted_mem!=NULL) - { - ditem = RsNxsSerialiser(mServType).deserialise(decrypted_mem,&decrypted_len) ; - free(decrypted_mem) ; - - if(ditem != NULL) - { - ditem->PeerId(encrypted_item->PeerId()) ; // This is needed because the deserialised item has no peer id - nxsitem = dynamic_cast(ditem) ; - } - else - std::cerr << " Cannot deserialise. Item encoding error!" << std::endl; - - return (nxsitem != NULL) ; - } - return false ; -} - -void RsGxsNetService::cleanTransactionItems(NxsTransaction* tr) const -{ - std::list::iterator lit = tr->mItems.begin(); - - for(; lit != tr->mItems.end(); ++lit) - { - delete *lit; - } - - tr->mItems.clear(); -} - -void RsGxsNetService::locked_pushGrpRespFromList(std::list& respList, const RsPeerId& peer, const uint32_t& transN) -{ -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << "locked_pushGrpResponseFromList()" << std::endl; - GXSNETDEBUG_P_(peer) << " nelems = " << respList.size() << std::endl; - GXSNETDEBUG_P_(peer) << " peerId = " << peer << std::endl; - GXSNETDEBUG_P_(peer) << " transN = " << transN << std::endl; -#endif - NxsTransaction* tr = new NxsTransaction(); - tr->mItems = respList; - - tr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - RsNxsTransacItem* trItem = new RsNxsTransacItem(mServType); - trItem->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P1 - | RsNxsTransacItem::FLAG_TYPE_GRP_LIST_RESP; - trItem->nItems = respList.size(); - trItem->timestamp = 0; - trItem->PeerId(peer); - trItem->transactionNumber = transN; -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_ (peer) << "Setting tr->mTransaction->updateTS to " << mGrpServerUpdate.grpUpdateTS << std::endl; -#endif - trItem->updateTS = mGrpServerUpdate.grpUpdateTS; - - // also make a copy for the resident transaction - tr->mTransaction = new RsNxsTransacItem(*trItem); - tr->mTransaction->PeerId(mOwnId); - tr->mTimeOut = time(NULL) + mTransactionTimeOut; - // signal peer to prepare for transaction -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_ (peer) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending group response to peer " - << peer << " with " << respList.size() << " groups " << std::endl; -#endif - if(locked_addTransaction(tr)) - generic_sendItem(trItem); - else - { - delete tr ; - delete trItem ; - } -} - -bool RsGxsNetService::locked_CanReceiveUpdate(const RsNxsSyncGrpReqItem *item) -{ - // Do we have new updates for this peer? - // The received TS is in our own clock, but send to us by the friend. - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(item->PeerId()) << " local modification time stamp: " << std::dec<< time(NULL) - mGrpServerUpdate.grpUpdateTS << " secs ago. Update sent: " << - ((item->updateTS < mGrpServerUpdate.grpUpdateTS)?"YES":"NO") << std::endl; -#endif - return item->updateTS < mGrpServerUpdate.grpUpdateTS && locked_checkResendingOfUpdates(item->PeerId(),RsGxsGroupId(),item->updateTS,mGrpServerUpdate.grpUpdateTsRecords[item->PeerId()]) ; -} - -void RsGxsNetService::handleRecvSyncGroup(RsNxsSyncGrpReqItem *item) -{ - if (!item) - return; - - RS_STACK_MUTEX(mNxsMutex) ; - - RsPeerId peer = item->PeerId(); -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << "HandleRecvSyncGroup(): Service: " << mServType << " from " << peer << ", Last update TS (from myself) sent from peer is T = " << std::dec<< time(NULL) - item->updateTS << " secs ago" << std::endl; -#endif - - if(!locked_CanReceiveUpdate(item)) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " RsGxsNetService::handleRecvSyncGroup() update will not be sent." << std::endl; -#endif - return; - } - - RsGxsGrpMetaTemporaryMap grp; - mDataStore->retrieveGxsGrpMetaData(grp); - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " RsGxsNetService::handleRecvSyncGroup() retrieving local list of groups..." << std::endl; -#endif - if(grp.empty()) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " RsGxsNetService::handleRecvSyncGroup() Grp Empty" << std::endl; -#endif - return; - } - - std::list itemL; - - uint32_t transN = locked_getTransactionId(); - - std::vector toVet; -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " Group list beings being sent: " << std::endl; -#endif - - for(auto mit = grp.begin(); mit != grp.end(); ++mit) - { - const auto& grpMeta = mit->second; - - // Only send info about subscribed groups. - - if(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) - { - - // check if you can send this id to peer - // or if you need to add to the holding - // pen for peer to be vetted - - bool should_encrypt = false ; - - if(canSendGrpId(peer, *grpMeta, toVet,should_encrypt)) - { - RsNxsSyncGrpItem* gItem = new RsNxsSyncGrpItem(mServType); - gItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - gItem->grpId = mit->first; - gItem->publishTs = mit->second->mPublishTs; - gItem->authorId = grpMeta->mAuthorId; - gItem->PeerId(peer); - gItem->transactionNumber = transN; - - if(should_encrypt) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(peer,mit->first) << " item for this grpId should be encrypted." << std::endl; -#endif - RsNxsItem *encrypted_item = NULL ; - uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; - - if(encryptSingleNxsItem(gItem, grpMeta->mCircleId,mit->first, encrypted_item,status)) - itemL.push_back(encrypted_item) ; - else - { - switch(status) - { - case RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR: - case RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING: toVet.push_back(GrpIdCircleVet(grpMeta->mGroupId, grpMeta->mCircleId, grpMeta->mAuthorId)); -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(peer,mit->first) << " Could not encrypt item for grpId " << grpMeta->mGroupId << " for circle " << grpMeta->mCircleId << ". Will try later. Adding to vetting list." << std::endl; -#endif - break ; - default: - std::cerr << " Could not encrypt item for grpId " << grpMeta->mGroupId << " for circle " << grpMeta->mCircleId << ". Not sending it." << std::endl; - } - } - delete gItem ; - } - else - itemL.push_back(gItem); - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(peer,mit->first) << " sending item for Grp " << mit->first << " name=" << grpMeta->mGroupName << ", publishTS=" << std::dec<< time(NULL) - mit->second->mPublishTs << " secs ago to peer ID " << peer << std::endl; -#endif - } - } - } - - if(!toVet.empty()) - mPendingCircleVets.push_back(new GrpCircleIdRequestVetting(mCircles, mPgpUtils, toVet, peer)); - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " final list sent (after vetting): " << itemL.size() << " elements." << std::endl; -#endif - locked_pushGrpRespFromList(itemL, peer, transN); - - return; -} - - - -bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, const RsGxsGrpMetaData& grpMeta, std::vector& /* toVet */, bool& should_encrypt) -{ -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendGrpId()"<< std::endl; -#endif - // check if that peer is a virtual peer id, in which case we only send/recv data to/from it items for the group it's requested for - - RsGxsGroupId peer_grp ; - if(mAllowDistSync && mGxsNetTunnel != NULL && mGxsNetTunnel->isDistantPeer(RsGxsNetTunnelVirtualPeerId(sslId),peer_grp) && peer_grp != grpMeta.mGroupId) - { -#warning (cyril) make sure that this is not a problem for cross-service sending of items -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Distant peer designed for group " << peer_grp << ": cannot request sync for different group." << std::endl; -#endif - return false ; - } - - // first do the simple checks - uint8_t circleType = grpMeta.mCircleType; - - if(circleType == GXS_CIRCLE_TYPE_LOCAL) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " LOCAL_CIRCLE, cannot send"<< std::endl; -#endif - return false; - } - else if(circleType == GXS_CIRCLE_TYPE_PUBLIC || circleType == GXS_CIRCLE_TYPE_UNKNOWN) // this complies with the fact that p3IdService does not initialise the circle type. - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " PUBLIC_CIRCLE, can send"<< std::endl; -#endif - return true; - } - else if(circleType == GXS_CIRCLE_TYPE_EXTERNAL) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " EXTERNAL_CIRCLE, will be sent encrypted."<< std::endl; -#endif - should_encrypt = true ; - return true ; - } - else if(circleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " YOUREYESONLY, checking further" << std::endl; -#endif - bool res = checkPermissionsForFriendGroup(sslId,grpMeta) ; -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Final answer: " << res << std::endl; -#endif - return res ; -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " YOUREYESONLY, checking further"<< std::endl; -#endif - } - else - { - std::cerr << "(EE) unknown value found in circle type for group " << grpMeta.mGroupId << ": " << (int)circleType << ": this is probably a bug in the design of the group creation." << std::endl; - return false; - } -} - -bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxsGrpMetaData& grpMeta, RsGxsCircleId& should_encrypt_id) -{ - -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::checkCanRecvMsgFromPeer()"; - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " peer Id = " << sslId << ", grpId=" << grpMeta.mGroupId <isDistantPeer(RsGxsNetTunnelVirtualPeerId(sslId),peer_grp) && peer_grp != grpMeta.mGroupId) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Distant peer designed for group " << peer_grp << ": cannot request sync for different group." << std::endl; -#endif - return false ; - } - - // first do the simple checks - uint8_t circleType = grpMeta.mCircleType; - should_encrypt_id.clear() ; - - if(circleType == GXS_CIRCLE_TYPE_LOCAL) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " LOCAL_CIRCLE, cannot request sync from peer" << std::endl; -#endif - return false; - } - - if(circleType == GXS_CIRCLE_TYPE_PUBLIC) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " PUBLIC_CIRCLE, can request msg sync" << std::endl; -#endif - return true; - } - - if(circleType == GXS_CIRCLE_TYPE_EXTERNAL) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: EXTERNAL => returning true. Msgs will be encrypted." << std::endl; -#endif - should_encrypt_id = grpMeta.mCircleId ; - return true ; - } - - if(circleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) // do not attempt to sync msg unless to originator or those permitted - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " YOUREYESONLY, checking further" << std::endl; -#endif - bool res = checkPermissionsForFriendGroup(sslId,grpMeta) ; -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Final answer: " << res << std::endl; -#endif - return res ; - } - - return true; -} - -bool RsGxsNetService::locked_checkResendingOfUpdates(const RsPeerId& pid,const RsGxsGroupId& grpId,rstime_t incoming_ts,RsPeerUpdateTsRecord& rec) -{ - rstime_t now = time(NULL); - - // Now we check if the peer is sending the same outdated TS for the same time in a short while. This would mean the peer - // hasn't finished processing the updates we're sending and we shouldn't send new data anymore. Of course the peer might - // have disconnected or so, which means that we need to be careful about not sending. As a compromise we still send, but - // after waiting for a while (See - - if(rec.mLastTsReceived == incoming_ts && rec.mTs + SAFETY_DELAY_FOR_UNSUCCESSFUL_UPDATE > now) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(pid,grpId) << "(II) peer " << pid << " already sent the same TS " << (long int)now-(long int)rec.mTs << " secs ago for that group ID. Will not send msg list again for a while to prevent clogging..." << std::endl; -#endif - return false; - } - - rec.mLastTsReceived = incoming_ts; - rec.mTs = now; - - return true; -} - -bool RsGxsNetService::locked_CanReceiveUpdate(RsNxsSyncMsgReqItem *item,bool& grp_is_known) -{ - // Do we have new updates for this peer? - // Here we compare times in the same clock: our own clock, so it should be fine. - - grp_is_known = false ; - - if(item->flag & RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID) - { - // Item contains the hashed group ID in order to protect is from friends who don't know it. So we de-hash it using bruteforce over known group IDs for this peer. - // We could save the de-hash result. But the cost is quite light, since the number of encrypted groups per service is usually low. - - for(ServerMsgMap::iterator it(mServerMsgUpdateMap.begin());it!=mServerMsgUpdateMap.end();++it) - if(item->grpId == hashGrpId(it->first,item->PeerId())) - { - item->grpId = it->first ; - item->flag &= ~RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID; -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << "(II) de-hashed group ID " << it->first << " from hash " << item->grpId << " and peer id " << item->PeerId() << std::endl; -#endif - grp_is_known = true ; - - // The order of tests below is important because we want to only modify the map of requests records if the request actually is a valid requests instead of - // a simple check that nothing's changed. - - return item->updateTS < it->second.msgUpdateTS && locked_checkResendingOfUpdates(item->PeerId(),item->grpId,item->updateTS,it->second.msgUpdateTsRecords[item->PeerId()]) ; - } - - return false ; - } - - ServerMsgMap::iterator cit = mServerMsgUpdateMap.find(item->grpId); - - if(cit != mServerMsgUpdateMap.end()) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " local time stamp: " << std::dec<< time(NULL) - cit->second.msgUpdateTS << " secs ago. Update sent: " << (item->updateTS < cit->second.msgUpdateTS) << std::endl; -#endif - grp_is_known = true ; - - return item->updateTS < cit->second.msgUpdateTS && locked_checkResendingOfUpdates(item->PeerId(),item->grpId,item->updateTS,cit->second.msgUpdateTsRecords[item->PeerId()]) ; - } - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " no local time stamp for this grp. "<< std::endl; -#endif - - return false; -} - -void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_was_encrypted) -{ - if (!item) - return; - - RS_STACK_MUTEX(mNxsMutex) ; - - const RsPeerId& peer = item->PeerId(); - bool grp_is_known = false; - bool was_circle_protected = item_was_encrypted || bool(item->flag & RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID); - - // This call determines if the peer can receive updates from us, meaning that our last TS is larger than what the peer sent. - // It also changes the items' group id into the un-hashed group ID if the group is a distant group. - - bool peer_can_receive_update = locked_CanReceiveUpdate(item, grp_is_known); - - if(item_was_encrypted) - std::cerr << "(WW) got an encrypted msg sync req. from " << item->PeerId() << ". This will not send messages updates for group " << item->grpId << std::endl; - - // Insert the PeerId in suppliers list for this grpId -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << "RsGxsNetService::handleRecvSyncMessage(): Inserting PeerId " << item->PeerId() << " in suppliers list for group " << item->grpId << std::endl; -#endif -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << "handleRecvSyncMsg(): Received last update TS of group " << item->grpId << ", for peer " << peer << ", TS = " << time(NULL) - item->updateTS << " secs ago." ; -#endif - - // We update suppliers in two cases: - // Case 1: the grp is known because it is the hash of an existing group, but it's not yet in the server config map - // Case 2: the grp is not known, possibly because it was deleted, but there's an entry in mServerGrpConfigMap due to statistics gathering. Still, statistics are only - // gathered from known suppliers. So statistics never add new suppliers. These are only added here. - - if(grp_is_known || mServerGrpConfigMap.find(item->grpId)!=mServerGrpConfigMap.end()) - { - RsGxsGrpConfig& rec(locked_getGrpConfig(item->grpId)); // this creates it if needed. When the grp is unknown (and hashed) this will would create a unused entry - rec.suppliers.ids.insert(peer) ; - } - if(!peer_can_receive_update) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " no update will be sent." << std::endl; -#endif - return; - } - - RsGxsGrpMetaTemporaryMap grpMetas; - grpMetas[item->grpId] = NULL; - - mDataStore->retrieveGxsGrpMetaData(grpMetas); - const auto& grpMeta = grpMetas[item->grpId]; - - if(grpMeta == NULL) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " Grp is unknown." << std::endl; -#endif - return; - } - if(!(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED )) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " Grp is not subscribed." << std::endl; -#endif - return ; - } - - if( (grpMeta->mCircleType == GXS_CIRCLE_TYPE_EXTERNAL) != was_circle_protected ) - { - std::cerr << "(EE) received a sync Msg request for group " << item->grpId << " from peer " << item->PeerId() ; - if(!was_circle_protected) - std::cerr << ". The group is tied to an external circle (ID=" << grpMeta->mCircleId << ") but the request wasn't encrypted." << std::endl; - else - std::cerr << ". The group is not tied to an external circle (ID=" << grpMeta->mCircleId << ") but the request was encrypted." << std::endl; - - return ; - } - - GxsMsgReq req; - req[item->grpId] = std::set(); - - GxsMsgMetaResult metaResult; - mDataStore->retrieveGxsMsgMetaData(req, metaResult); - auto& msgMetas = metaResult[item->grpId]; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " retrieving message meta data." << std::endl; -#endif - if(req.empty()) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " No msg meta data.." << std::endl; -#endif - } -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " Sending MSG meta data created since TS=" << item->createdSinceTS << std::endl; -#endif - - std::list itemL; - - uint32_t transN = locked_getTransactionId(); - RsGxsCircleId should_encrypt_to_this_circle_id ; - - rstime_t now = time(NULL) ; - -#ifndef RS_GXS_SEND_ALL - uint32_t max_send_delay = locked_getGrpConfig(item->grpId).msg_req_delay; // we should use "sync" but there's only one variable used in the GUI: the req one. -#endif - - if(canSendMsgIds(msgMetas, *grpMeta, peer, should_encrypt_to_this_circle_id)) - { - for(auto vit = msgMetas.begin();vit != msgMetas.end(); ++vit) - { - const auto& m = *vit; - - // Check reputation - - if(!m->mAuthorId.isNull()) - { - RsIdentityDetails details ; - - if(!rsIdentity->getIdDetails(m->mAuthorId,details)) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " not sending grp message ID " << (*vit)->mMsgId << ", because the identity of the author (" << m->mAuthorId << ") is not accessible (unknown/not cached)" << std::endl; -#endif - continue ; - } - - if(details.mReputation.mOverallReputationLevel < minReputationForForwardingMessages(grpMeta->mSignFlags, details.mFlags)) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " not sending item ID " << (*vit)->mMsgId << ", because the author is flags " << std::hex << details.mFlags << std::dec << " and reputation level " << (int) details.mReputation.mOverallReputationLevel << std::endl; -#endif - continue ; - } - } - // Check publish TS -#ifndef RS_GXS_SEND_ALL - if(item->createdSinceTS > (*vit)->mPublishTs || ((max_send_delay > 0) && (*vit)->mPublishTs + max_send_delay < now)) -#else - if(item->createdSinceTS > (*vit)->mPublishTs) -#endif - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " not sending item ID " << (*vit)->mMsgId << ", because it is too old (publishTS = " << (time(NULL)-(*vit)->mPublishTs)/86400 << " days ago" << std::endl; -#endif - continue ; - } - - RsNxsSyncMsgItem* mItem = new RsNxsSyncMsgItem(mServType); - mItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - mItem->grpId = m->mGroupId; - mItem->msgId = m->mMsgId; - mItem->authorId = m->mAuthorId; - mItem->PeerId(peer); - mItem->transactionNumber = transN; - - if(!should_encrypt_to_this_circle_id.isNull()) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId << ". Transaction will be encrypted for group " << should_encrypt_to_this_circle_id << std::endl; -#endif - RsNxsItem *encrypted_item = NULL ; - uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; - - if(encryptSingleNxsItem(mItem, grpMeta->mCircleId,m->mGroupId, encrypted_item,status)) - { - itemL.push_back(encrypted_item) ; - delete mItem ; - } - else - { - // Something's not ready (probably the circle content. We could put on a vetting list, but actually the client will re-ask the list asap. - - std::cerr << " (EE) Cannot encrypt msg meta data. MsgId=" << mItem->msgId << ", grpId=" << mItem->grpId << ", circleId=" << should_encrypt_to_this_circle_id << ". Dropping the whole list." << std::endl; - - for(std::list::const_iterator it(itemL.begin());it!=itemL.end();++it) - delete *it ; - - itemL.clear() ; - delete mItem ; - break ; - } - } - else - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId << " in clear." << std::endl; -#endif - itemL.push_back(mItem); - } - } - } -#ifdef NXS_NET_DEBUG_0 - else - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " vetting forbids sending. Nothing will be sent." << itemL.size() << " items." << std::endl; -#endif - - if(!itemL.empty()) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending final msg info list of " << itemL.size() << " items." << std::endl; -#endif - locked_pushMsgRespFromList(itemL, peer, item->grpId,transN); - } -#ifdef NXS_NET_DEBUG_0 - else - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " list is empty! Not sending anything." << std::endl; -#endif - - - // release meta resource - // for(std::vector::iterator vit = msgMetas.begin(); vit != msgMetas.end(); ++vit) - // delete *vit; -} - -void RsGxsNetService::locked_pushMsgRespFromList(std::list& itemL, const RsPeerId& sslId, const RsGxsGroupId& grp_id,const uint32_t& transN) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(sslId,grp_id) << "locked_pushMsgResponseFromList()" << std::endl; - GXSNETDEBUG_PG(sslId,grp_id) << " nelems = " << itemL.size() << std::endl; - GXSNETDEBUG_PG(sslId,grp_id) << " peerId = " << sslId << std::endl; - GXSNETDEBUG_PG(sslId,grp_id) << " transN = " << transN << std::endl; -#endif - NxsTransaction* tr = new NxsTransaction(); - tr->mItems = itemL; - tr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - - RsNxsTransacItem* trItem = new RsNxsTransacItem(mServType); - trItem->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P1 | RsNxsTransacItem::FLAG_TYPE_MSG_LIST_RESP; - trItem->nItems = itemL.size(); - trItem->timestamp = 0; - trItem->PeerId(sslId); - trItem->transactionNumber = transN; - - // also make a copy for the resident transaction - tr->mTransaction = new RsNxsTransacItem(*trItem); - tr->mTransaction->PeerId(mOwnId); - tr->mTimeOut = time(NULL) + mTransactionTimeOut; - - // This time stamp is not supposed to be used on the other side. We just set it to avoid sending an uninitialiszed value. - trItem->updateTS = mServerMsgUpdateMap[grp_id].msgUpdateTS; - -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_ (sslId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending messages response to peer " - << sslId << " with " << itemL.size() << " messages " << std::endl; -#endif - // signal peer to prepare for transaction - if(locked_addTransaction(tr)) - generic_sendItem(trItem); - else - { - delete tr ; - delete trItem ; - } -} - -bool RsGxsNetService::canSendMsgIds(std::vector >& msgMetas, const RsGxsGrpMetaData& grpMeta, const RsPeerId& sslId,RsGxsCircleId& should_encrypt_id) -{ -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendMsgIds() CIRCLE VETTING" << std::endl; -#endif - // check if that peer is a virtual peer id, in which case we only send/recv data to/from it items for the group it's requested for - - RsGxsGroupId peer_grp ; - if(mAllowDistSync && mGxsNetTunnel != NULL && mGxsNetTunnel->isDistantPeer(RsGxsNetTunnelVirtualPeerId(sslId),peer_grp) && peer_grp != grpMeta.mGroupId) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Distant peer designed for group " << peer_grp << ": cannot request sync for different group." << std::endl; -#endif - return false ; - } - - // first do the simple checks - uint8_t circleType = grpMeta.mCircleType; - - if(circleType == GXS_CIRCLE_TYPE_LOCAL) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: LOCAL => returning false" << std::endl; -#endif - return false; - } - else if(circleType == GXS_CIRCLE_TYPE_PUBLIC || circleType == GXS_CIRCLE_TYPE_UNKNOWN) // this complies with the fact that p3IdService does not initialise the circle type. - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: PUBLIC => returning true" << std::endl; -#endif - return true; - } - else if(circleType == GXS_CIRCLE_TYPE_EXTERNAL) - { - const RsGxsCircleId& circleId = grpMeta.mCircleId; -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: EXTERNAL => returning true. Msgs ids list will be encrypted." << std::endl; -#endif - should_encrypt_id = circleId ; - - // For each message ID, check that the author is in the circle. If not, do not send the message, which means, remove it from the list. - // Unsigned messages are still transmitted. This is because in some groups (channels) the posts are not signed. Whether an unsigned post - // is allowed at this point is anyway already vetted by the RsGxsGenExchange service. - - // Messages that stay in the list will be sent. As a consequence true is always returned. - // Messages put in vetting list will be dealt with later - - std::vector toVet; - - for(uint32_t i=0;imAuthorId.isNull() ) // keep the message in this case - ++i ; - else - { - if(mCircles->isLoaded(circleId) && mCircles->isRecipient(circleId, grpMeta.mGroupId, msgMetas[i]->mAuthorId)) - { - ++i ; - continue ; - } - - MsgIdCircleVet mic(msgMetas[i]->mMsgId, msgMetas[i]->mAuthorId); - toVet.push_back(mic); -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " deleting MsgMeta entry for msg ID " << msgMetas[i]->mMsgId << " signed by " << msgMetas[i]->mAuthorId << " who is not in group circle " << circleId << std::endl; -#endif - - //delete msgMetas[i] ; - msgMetas[i] = msgMetas[msgMetas.size()-1] ; - msgMetas.pop_back() ; - } - -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle info not loaded. Putting in vetting list and returning false." << std::endl; -#endif - if(!toVet.empty()) - mPendingCircleVets.push_back(new MsgCircleIdsRequestVetting(mCircles, mPgpUtils, toVet, grpMeta.mGroupId, sslId, grpMeta.mCircleId)); - - return true ; - } - else if(circleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " YOUREYESONLY, checking further" << std::endl; -#endif - bool res = checkPermissionsForFriendGroup(sslId,grpMeta) ; -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Final answer: " << res << std::endl; -#endif - return res ; - } - else - { - std::cerr << "(EE) unknown value found in circle type for group " << grpMeta.mGroupId << ": " << (int)circleType << ": this is probably a bug in the design of the group creation." << std::endl; - return false; - } -} - -/** inherited methods **/ - -bool RsGxsNetService::checkPermissionsForFriendGroup(const RsPeerId& sslId,const RsGxsGrpMetaData& grpMeta) -{ -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: YOUR EYES ONLY - ID = " << grpMeta.mInternalCircle << std::endl; -#endif - // a non empty internal circle id means this - // is the personal circle owner - if(!grpMeta.mInternalCircle.isNull()) - { - RsGroupInfo ginfo ; - RsPgpId pgpId = mPgpUtils->getPGPId(sslId) ; - -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Group internal circle: " << grpMeta.mInternalCircle << ", We're owner. Sending to everyone in the group." << std::endl; - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Current destination is PGP Id: " << pgpId << std::endl; -#endif - if(!rsPeers->getGroupInfo(RsNodeGroupId(grpMeta.mInternalCircle),ginfo)) - { - std::cerr << "(EE) Cannot get information for internal circle (group node) ID " << grpMeta.mInternalCircle << " which conditions dissemination of GXS group " << grpMeta.mGroupId << std::endl; - return false ; - } - - bool res = (ginfo.peerIds.find(pgpId) != ginfo.peerIds.end()); - -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Final Answer is: " << res << std::endl; -#endif - return res ; - } - else - { - // An empty internal circle id means this peer can only - // send circle related info from peer he received it from. - // Normally this should be a pgp-based decision, but if we do that, - // A ---> B ----> A' ---...--->B' , then A' will also send to B' since B is the - // originator for A'. So A will lose control of who can see the data. This should - // be discussed further... - -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Empty internal circle: cannot only send/recv info to/from Peer we received it from (grpMeta.mOriginator=" << grpMeta.mOriginator << ")" << std::endl; - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Final answer is: " << (grpMeta.mOriginator == sslId) << std::endl; -#endif - if(grpMeta.mOriginator == sslId) - return true; - else - return false; - } -} - -void RsGxsNetService::pauseSynchronisation(bool /* enabled */) -{ - std::cerr << "(EE) RsGxsNetService::pauseSynchronisation() called, but not implemented." << std::endl; -} - -void RsGxsNetService::setSyncAge(const RsGxsGroupId &grpId, uint32_t age_in_secs) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - locked_checkDelay(age_in_secs) ; - - RsGxsGrpConfig& conf(locked_getGrpConfig(grpId)); - - if(conf.msg_req_delay != age_in_secs) - { - conf.msg_req_delay = age_in_secs; - - // we also need to zero the client TS, in order to trigger a new sync - locked_resetClientTS(grpId); - - IndicateConfigChanged(); - - // also send an event so that UI is updated - - mNewGrpSyncParamsToNotify.insert(grpId); - } -} -void RsGxsNetService::setKeepAge(const RsGxsGroupId &grpId, uint32_t age_in_secs) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - locked_checkDelay(age_in_secs) ; - - RsGxsGrpConfig& conf(locked_getGrpConfig(grpId)); - - if(conf.msg_keep_delay != age_in_secs) - { - conf.msg_keep_delay = age_in_secs; - IndicateConfigChanged(); - } -} - -RsGxsGrpConfig& RsGxsNetService::locked_getGrpConfig(const RsGxsGroupId& grp_id) -{ - GrpConfigMap::iterator it = mServerGrpConfigMap.find(grp_id); - - if(it == mServerGrpConfigMap.end()) - { - RsGxsGrpConfig& conf(mServerGrpConfigMap[grp_id]) ; - - conf.msg_keep_delay = mDefaultMsgStorePeriod; - conf.msg_send_delay = mDefaultMsgSyncPeriod; - conf.msg_req_delay = mDefaultMsgSyncPeriod; - - conf.max_visible_count = 0 ; - conf.statistics_update_TS = 0 ; - conf.last_group_modification_TS = 0 ; - - return conf ; - } - else - return it->second; -} - -uint32_t RsGxsNetService::getSyncAge(const RsGxsGroupId& grpId) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - return locked_getGrpConfig(grpId).msg_req_delay ; -} -uint32_t RsGxsNetService::getKeepAge(const RsGxsGroupId& grpId) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - return locked_getGrpConfig(grpId).msg_keep_delay ; -} - -int RsGxsNetService::requestGrp( - const std::list& grpIds, const RsPeerId& peerId ) -{ -#ifdef NXS_NET_DEBUG_0 - RS_DBG("Adding explicit groups requests to peer: ", peerId); - for(auto& grpId: std::as_const(grpIds)) RS_DBG("\t Group ID: ", grpId); -#endif - - RS_STACK_MUTEX(mNxsMutex); - mExplicitRequest[peerId].insert(grpIds.begin(), grpIds.end()); - return 1; -} - -void RsGxsNetService::processExplicitGroupRequests() -{ - RS_STACK_MUTEX(mNxsMutex); - - for(auto& cit: std::as_const(mExplicitRequest)) - { -#ifdef NXS_NET_DEBUG_0 - RS_DBG("sending pending explicit group requests to peer ", cit.first); -#endif - const RsPeerId& peerId = cit.first; - const std::set& groupIdList = cit.second; - - std::list grpSyncItems; - uint32_t transN = locked_getTransactionId(); - for(auto& grpId: std::as_const(groupIdList)) - { -#ifdef NXS_NET_DEBUG_0 - RS_DBG("\t group request for group ID: ", grpId); -#endif - RsNxsSyncGrpItem* item = new RsNxsSyncGrpItem(mServType); - item->grpId = grpId; - item->PeerId(peerId); - item->flag = RsNxsSyncGrpItem::FLAG_REQUEST; - item->transactionNumber = transN; - grpSyncItems.push_back(item); - } - - if(!grpSyncItems.empty()) - locked_pushGrpTransactionFromList(grpSyncItems, peerId, transN); - } - - mExplicitRequest.clear(); -} - -int RsGxsNetService::sharePublishKey(const RsGxsGroupId& grpId,const std::set& peers) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - mPendingPublishKeyRecipients[grpId] = peers ; -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG__G(grpId) << "RsGxsNetService::sharePublishKeys() " << (void*)this << " adding publish keys for grp " << grpId << " to sending list" << std::endl; -#endif - - return true ; -} - -void RsGxsNetService::sharePublishKeysPending() -{ - RS_STACK_MUTEX(mNxsMutex) ; - - if(mPendingPublishKeyRecipients.empty()) - return ; - -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG___ << "RsGxsNetService::sharePublishKeys() " << (void*)this << std::endl; -#endif - // get list of peers that are online - - std::set peersOnline; - std::list toDelete; - std::map >::iterator mit ; - - mNetMgr->getOnlineList(mServiceInfo.mServiceType, peersOnline); - -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG___ << " " << peersOnline.size() << " peers online." << std::endl; -#endif - /* send public key to peers online */ - - for(mit = mPendingPublishKeyRecipients.begin(); mit != mPendingPublishKeyRecipients.end(); ++mit) - { - // Compute the set of peers to send to. We start with this, to avoid retrieving the data for nothing. - - std::list recipients ; - std::set offline_recipients ; - - for(std::set::const_iterator it(mit->second.begin());it!=mit->second.end();++it) - if(peersOnline.find(*it) != peersOnline.end()) - { -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_P_(*it) << " " << *it << ": online. Adding." << std::endl; -#endif - recipients.push_back(*it) ; - } - else - { -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_P_(*it) << " " << *it << ": offline. Keeping for next try." << std::endl; -#endif - offline_recipients.insert(*it) ; - } - - // If empty, skip - - if(recipients.empty()) - { -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG___ << " No recipients online. Skipping." << std::endl; -#endif - continue ; - } - - // Get the meta data for this group Id - // - RsGxsGrpMetaTemporaryMap grpMetaMap; - grpMetaMap[mit->first] = NULL; - mDataStore->retrieveGxsGrpMetaData(grpMetaMap); - - // Find the publish keys in the retrieved info - - const auto& grpMeta = grpMetaMap[mit->first] ; - - if(grpMeta == NULL) - { - std::cerr << "(EE) RsGxsNetService::sharePublishKeys() Publish keys cannot be found for group " << mit->first << std::endl; - continue ; - } - - const RsTlvSecurityKeySet& keys = grpMeta->keys; - - std::map::const_iterator kit = keys.private_keys.begin(), kit_end = keys.private_keys.end(); - bool publish_key_found = false; - RsTlvPrivateRSAKey publishKey ; - - for(; kit != kit_end && !publish_key_found; ++kit) - { - publish_key_found = (kit->second.keyFlags == (RSTLV_KEY_DISTRIB_PUBLISH | RSTLV_KEY_TYPE_FULL)); - publishKey = kit->second ; - } - - if(!publish_key_found) - { - std::cerr << "(EE) no publish key in group " << mit->first << ". Cannot share!" << std::endl; - continue ; - } - - -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG__G(grpMeta->mGroupId) << " using publish key ID=" << publishKey.keyId << ", flags=" << publishKey.keyFlags << std::endl; -#endif - for(std::list::const_iterator it(recipients.begin());it!=recipients.end();++it) - { - /* Create publish key sharing item */ - RsNxsGroupPublishKeyItem *publishKeyItem = new RsNxsGroupPublishKeyItem(mServType); - - publishKeyItem->clear(); - publishKeyItem->grpId = mit->first; - - publishKeyItem->private_key = publishKey ; - publishKeyItem->PeerId(*it); - - generic_sendItem(publishKeyItem); -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(*it,grpMeta->mGroupId) << " sent key item to " << *it << std::endl; -#endif - } - - mit->second = offline_recipients ; - - // If given peers have all received key(s) then stop sending for group - if(offline_recipients.empty()) - toDelete.push_back(mit->first); - } - - // delete pending peer list which are done with - for(std::list::const_iterator lit = toDelete.begin(); lit != toDelete.end(); ++lit) - mPendingPublishKeyRecipients.erase(*lit); -} - -void RsGxsNetService::handleRecvPublishKeys(RsNxsGroupPublishKeyItem *item) -{ -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << "RsGxsNetService::sharePublishKeys() " << std::endl; -#endif - - if (!item) - return; - - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " PeerId : " << item->PeerId() << std::endl; - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " GrpId: " << item->grpId << std::endl; - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " Got key Item: " << item->private_key.keyId << std::endl; -#endif - - // Get the meta data for this group Id - // - RsGxsGrpMetaTemporaryMap grpMetaMap; - grpMetaMap[item->grpId] = NULL; - - mDataStore->retrieveGxsGrpMetaData(grpMetaMap); - - // update the publish keys in this group meta info - - const auto& grpMeta = grpMetaMap[item->grpId] ; - if (!grpMeta) { - std::cerr << "(EE) RsGxsNetService::handleRecvPublishKeys() grpMeta not found." << std::endl; - return ; - } - - // Check that the keys correspond, and that FULL keys are supplied, etc. - -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(item->PeerId(),item->grpId)<< " Key received: " << std::endl; -#endif - - bool admin = (item->private_key.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) && (item->private_key.keyFlags & RSTLV_KEY_TYPE_FULL) ; - bool publi = (item->private_key.keyFlags & RSTLV_KEY_DISTRIB_PUBLISH) && (item->private_key.keyFlags & RSTLV_KEY_TYPE_FULL) ; - -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(item->PeerId(),item->grpId)<< " Key id = " << item->private_key.keyId << " admin=" << admin << ", publish=" << publi << " ts=" << item->private_key.endTS << std::endl; -#endif - - if(!(!admin && publi)) - { - std::cerr << " Key is not a publish private key. Discarding!" << std::endl; - return ; - } - // Also check that we don't already have full keys for that group. - - if(grpMeta->keys.public_keys.find(item->private_key.keyId) == grpMeta->keys.public_keys.end()) - { - std::cerr << " (EE) Key not found in known group keys. This is an inconsistency." << std::endl; - return ; - } - - if(grpMeta->keys.private_keys.find(item->private_key.keyId) != grpMeta->keys.private_keys.end()) - { -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(item->PeerId(),item->grpId)<< " (EE) Publish key already present in database. Discarding message." << std::endl; -#endif - mNewPublishKeysToNotify.insert(item->grpId) ; - return ; - } - - // Store/update the info. - - RsTlvSecurityKeySet keys = grpMeta->keys ; - keys.private_keys[item->private_key.keyId] = item->private_key ; - - bool ret = mDataStore->updateGroupKeys(item->grpId,keys, grpMeta->mSubscribeFlags | GXS_SERV::GROUP_SUBSCRIBE_PUBLISH) ; - - if(ret) - { -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(item->PeerId(),item->grpId)<< " updated database with new publish keys." << std::endl; -#endif - mNewPublishKeysToNotify.insert(item->grpId) ; - } - else - { - std::cerr << "(EE) could not update database. Something went wrong." << std::endl; - } -} - -bool RsGxsNetService::getGroupServerUpdateTS(const RsGxsGroupId& gid,rstime_t& group_server_update_TS, rstime_t& msg_server_update_TS) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - group_server_update_TS = mGrpServerUpdate.grpUpdateTS ; - - ServerMsgMap::iterator it = mServerMsgUpdateMap.find(gid) ; - - if(mServerMsgUpdateMap.end() == it) - msg_server_update_TS = 0 ; - else - msg_server_update_TS = it->second.msgUpdateTS ; - - return true ; -} - -bool RsGxsNetService::removeGroups(const std::list& groups) -{ - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << "Removing group information from deleted groups:" << std::endl; -#endif - - for(std::list::const_iterator git(groups.begin());git!=groups.end();++git) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(*git) << " deleting info for group " << *git << std::endl; -#endif - - // Here we do not use locked_getGrpConfig() because we dont want the entry to be created if it doesnot already exist. - - GrpConfigMap::iterator it = mServerGrpConfigMap.find(*git) ; - - if(it != mServerGrpConfigMap.end()) - { - it->second.suppliers.TlvClear(); // we dont erase the entry, because we want to keep the user-defined sync parameters. - it->second.max_visible_count = 0; - } - - mServerMsgUpdateMap.erase(*git) ; - - for(ClientMsgMap::iterator it(mClientMsgUpdateMap.begin());it!=mClientMsgUpdateMap.end();++it) - it->second.msgUpdateInfos.erase(*git) ; - - // This last step is very important: it makes RS re-sync all groups after deleting, with every new peer. If may happen indeed that groups - // are deleted because there's no suppliers since the actual supplier friend is offline for too long. In this case, the group needs - // to re-appear when the friend who is a subscriber comes online again. - - mClientGrpUpdateMap.clear(); - } - - IndicateConfigChanged(); - return true ; -} - -bool RsGxsNetService::isDistantPeer(const RsPeerId& pid) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - if(!mAllowDistSync || mGxsNetTunnel == NULL) - return false ; - - RsGxsGroupId group_id ; - - return mGxsNetTunnel->isDistantPeer(RsGxsNetTunnelVirtualPeerId(pid),group_id); -} - -bool RsGxsNetService::stampMsgServerUpdateTS(const RsGxsGroupId& gid) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - return locked_stampMsgServerUpdateTS(gid) ; -} - -bool RsGxsNetService::locked_stampMsgServerUpdateTS(const RsGxsGroupId& gid) -{ - RsGxsServerMsgUpdate& m(mServerMsgUpdateMap[gid]); - - m.msgUpdateTS = time(NULL) ; - - return true; -} - -DistantSearchGroupStatus RsGxsNetService::getDistantSearchStatus(const RsGxsGroupId& group_id) -{ - auto it = mSearchedGroups.find(group_id); - - if(it != mSearchedGroups.end()) - return it->second.status; - - for(auto it2:mDistantSearchResults) - if(it2.second.find(group_id) != it2.second.end()) - return DistantSearchGroupStatus::CAN_BE_REQUESTED; - - return DistantSearchGroupStatus::UNKNOWN; -} - -TurtleRequestId RsGxsNetService::turtleGroupRequest(const RsGxsGroupId& group_id) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - rstime_t now = time(NULL); - auto it = mSearchedGroups.find(group_id) ; - - if(mSearchedGroups.end() != it && (it->second.ts + MIN_DELAY_BETWEEN_GROUP_SEARCH > now)) - { - std::cerr << "(WW) Last turtle request was " << now - it->second.ts << " secs ago. Not searching again." << std::endl; - return it->second.request_id; - } - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG__G(group_id) << " requesting group id " << group_id << " using turtle" << std::endl; -#endif - TurtleRequestId req = mGxsNetTunnel->turtleGroupRequest(group_id,this) ; - - GroupRequestRecord& rec(mSearchedGroups[group_id]) ; - - rec.request_id = req; - rec.ts = now; - rec.status = DistantSearchGroupStatus::ONGOING_REQUEST; - - mSearchRequests[req] = group_id; - - return req; -} -TurtleRequestId RsGxsNetService::turtleSearchRequest(const std::string& match_string) -{ - return mGxsNetTunnel->turtleSearchRequest(match_string,this) ; -} - -#ifndef RS_DEEP_CHANNEL_INDEX -static bool termSearch(const std::string& src, const std::string& substring) -{ - /* always ignore case */ - return src.end() != std::search( src.begin(), src.end(), substring.begin(), substring.end(), RsRegularExpression::CompareCharIC() ); -} -#endif // ndef RS_DEEP_CHANNEL_INDEX - -bool RsGxsNetService::retrieveDistantSearchResults(TurtleRequestId req,std::map& group_infos) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - auto it = mDistantSearchResults.find(req) ; - - if(it == mDistantSearchResults.end()) - return false ; - - group_infos = it->second; - return true ; -} -bool RsGxsNetService::retrieveDistantGroupSummary(const RsGxsGroupId& group_id,RsGxsGroupSearchResults& gs) -{ - RS_STACK_MUTEX(mNxsMutex) ; - for(auto it(mDistantSearchResults.begin());it!=mDistantSearchResults.end();++it) - { - auto it2 = it->second.find(group_id) ; - - if(it2 != it->second.end()) - { - gs = it2->second; - return true ; - } - } - return false ; -} -bool RsGxsNetService::clearDistantSearchResults(const TurtleRequestId& id) -{ - RS_STACK_MUTEX(mNxsMutex) ; - mDistantSearchResults.erase(id); - return true ; -} - -void RsGxsNetService::receiveTurtleSearchResults( TurtleRequestId req, const std::list& group_infos ) -{ - std::set groupsToNotifyResults; - - { - RS_STACK_MUTEX(mNxsMutex); - - RsGxsGrpMetaTemporaryMap grpMeta; - std::map& search_results_map(mDistantSearchResults[req]); - -#ifdef NXS_NET_DEBUG_9 - std::cerr << "Received group summary through turtle search for the following groups:" << std::endl; -#endif - - for(const RsGxsGroupSummary& gps : group_infos) - { - std::cerr <<" " << gps.mGroupId << " \"" << gps.mGroupName << "\"" << std::endl; - grpMeta[gps.mGroupId] = nullptr; - } - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - -#ifdef NXS_NET_DEBUG_9 - std::cerr << "Retrieved data store group data for the following groups:" <mGroupName << std::endl; -#endif - - for (const RsGxsGroupSummary& gps : group_infos) - { -#ifndef RS_DEEP_CHANNEL_INDEX - /* Only keep groups that are not locally known, and groups that are - * not already in the mDistantSearchResults structure. - * mDataStore may in some situations allocate an empty group meta data, so it's important - * to test that the group meta is both non null and actually corresponds to the group id we seek. */ - - auto& meta(grpMeta[gps.mGroupId]); - - if(meta != nullptr && meta->mGroupId == gps.mGroupId) - continue; - -#ifdef NXS_NET_DEBUG_9 - std::cerr << " group " << gps.mGroupId << " is not known. Adding it to search results..." << std::endl; -#endif - -#else // ndef RS_DEEP_CHANNEL_INDEX - /* When deep search is enabled search results may bring more info - * then we already have also about post that are indexed by xapian, - * so we don't apply this filter in this case. */ -#endif - const RsGxsGroupId& grpId(gps.mGroupId); - - groupsToNotifyResults.insert(grpId); - - // Find search results place for this particular group - -#ifdef NXS_NET_DEBUG_9 - std::cerr << " Adding gps=" << gps.mGroupId << " name=\"" << gps.mGroupName << "\" gps.mSearchContext=\"" << gps.mSearchContext << "\"" << std::endl; -#endif - RsGxsGroupSearchResults& eGpS(search_results_map[grpId]); - - if(eGpS.mGroupId != grpId) // not initialized yet. So we do it now. - { - eGpS.mGroupId = gps.mGroupId; - eGpS.mGroupName = gps.mGroupName; - eGpS.mAuthorId = gps.mAuthorId; - eGpS.mPublishTs = gps.mPublishTs; - eGpS.mSignFlags = gps.mSignFlags; - } - // We should check that the above values are always the same for all info that is received. In the end, we'll - // request the group meta and check the signature, but it may be misleading to receive a forged information - // that is not the real one. - - ++eGpS.mPopularity; // increase popularity. This is not a real counting, but therefore some heuristic estimate. - eGpS.mNumberOfMessages = std::max( eGpS.mNumberOfMessages, gps.mNumberOfMessages ); - eGpS.mLastMessageTs = std::max( eGpS.mLastMessageTs, gps.mLastMessageTs ); - - if(gps.mSearchContext != gps.mGroupName) // this is a bit of a hack. We should have flags to tell where the search hit happens - eGpS.mSearchContexts.insert(gps.mSearchContext); - } - } // end RS_STACK_MUTEX(mNxsMutex); - - for(const RsGxsGroupId& grpId : groupsToNotifyResults) - mObserver->receiveDistantSearchResults(req, grpId); -} - -void RsGxsNetService::receiveTurtleSearchResults(TurtleRequestId req,const unsigned char *encrypted_group_data,uint32_t encrypted_group_data_len) -{ -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " received encrypted group data for turtle search request " << std::hex << req << std::dec << ": " << RsUtil::BinToHex(encrypted_group_data,encrypted_group_data_len,50) << std::endl; -#endif - auto it = mSearchRequests.find(req); - - if(mSearchRequests.end() == it) - { - std::cerr << "(EE) received search results for unknown request " << std::hex << req << std::dec ; - return; - } - RsGxsGroupId grpId = it->second; - - uint8_t encryption_master_key[32]; - Sha256CheckSum s = RsDirUtil::sha256sum(grpId.toByteArray(),grpId.SIZE_IN_BYTES); - memcpy(encryption_master_key,s.toByteArray(),32); - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " attempting data decryption with master key " << RsUtil::BinToHex(encryption_master_key,32) << std::endl; -#endif - unsigned char *clear_group_data = NULL; - uint32_t clear_group_data_len ; - - if(!librs::crypto::decryptAuthenticateData(encrypted_group_data,encrypted_group_data_len,encryption_master_key,clear_group_data,clear_group_data_len)) - { - std::cerr << "(EE) Could not decrypt data. Something went wrong. Wrong key??" << std::endl; - return ; - } - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " successfuly decrypted data : " << RsUtil::BinToHex(clear_group_data,clear_group_data_len,50) << std::endl; -#endif - uint32_t used_size = clear_group_data_len; - RsItem *item = RsNxsSerialiser(mServType).deserialise(clear_group_data,&used_size) ; - RsNxsGrp *nxs_identity_grp=nullptr; - - if(used_size < clear_group_data_len) - { - uint32_t remaining_size = clear_group_data_len-used_size ; - RsItem *item2 = RsNxsSerialiser(RS_SERVICE_GXS_TYPE_GXSID).deserialise(clear_group_data+used_size,&remaining_size) ; - - nxs_identity_grp = dynamic_cast(item2); - - if(!nxs_identity_grp) - std::cerr << "(EE) decrypted item contains more data that cannot be deserialized as a GxsId. Unexpected!" << std::endl; - - // We should probably check that the identity that is sent corresponds to the group author and don't add - // it otherwise. But in any case, this won't harm to add a new public identity. If that identity is banned, - // the group will be discarded in RsGenExchange anyway. - - if(nxs_identity_grp) - mGixs->receiveNewIdentity(nxs_identity_grp); - } - - free(clear_group_data); - clear_group_data = NULL ; - - RsNxsGrp *nxs_grp = dynamic_cast(item) ; - - if(nxs_grp == NULL) - { - std::cerr << "(EE) decrypted item is not a RsNxsGrp. Weird!" << std::endl; - return ; - } - -#ifdef NXS_NET_DEBUG_8 - if(nxs_identity_grp) - GXSNETDEBUG___ << " Serialized clear data contains a group " << nxs_grp->grpId << " in service " << std::hex << mServType << std::dec << " and a second identity item for an identity." << nxs_identity_grp->grpId << std::endl; - else - GXSNETDEBUG___ << " Serialized clear data contains a single GXS group for Grp Id " << nxs_grp->grpId << " in service " << std::hex << mServType << std::dec << std::endl; -#endif - - std::vector new_grps(1,nxs_grp); - - GroupRequestRecord& rec(mSearchedGroups[nxs_grp->grpId]) ; - rec.status = DistantSearchGroupStatus::HAVE_GROUP_DATA; - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " passing the grp data to observer." << std::endl; -#endif - mObserver->receiveNewGroups(new_grps); - mObserver->receiveDistantSearchResults(req, grpId); -} - -bool RsGxsNetService::search( const std::string& substring, - std::list& group_infos ) -{ - group_infos.clear(); - -#ifdef RS_DEEP_CHANNEL_INDEX - -#warning TODO: filter deep index search result to non circle-restricted groups. -// /!\ -// /!\ These results should be filtered to only return results coming from a non restricted group! -// /!\ - - std::vector results; - DeepChannelsIndex::search(substring, results); - - for(auto dsr : results) - { - RsUrl rUrl(dsr.mUrl); - const auto& uQ(rUrl.query()); - auto rit = uQ.find("id"); - if(rit != rUrl.query().end()) - { - RsGroupNetworkStats stats; - RsGxsGroupId grpId(rit->second); - if( !grpId.isNull() && getGroupNetworkStats(grpId, stats) ) - { - RsGxsGroupSummary s; - - s.mGroupId = grpId; - - if((rit = uQ.find("name")) != uQ.end()) - s.mGroupName = rit->second; - if((rit = uQ.find("signFlags")) != uQ.end()) - s.mSignFlags = static_cast(std::stoul(rit->second)); - if((rit = uQ.find("publishTs")) != uQ.end()) - s.mPublishTs = static_cast(std::stoll(rit->second)); - if((rit = uQ.find("authorId")) != uQ.end()) - s.mAuthorId = RsGxsId(rit->second); - - s.mSearchContext = dsr.mSnippet; - - s.mNumberOfMessages = stats.mMaxVisibleCount; - s.mLastMessageTs = stats.mLastGroupModificationTS; - s.mPopularity = stats.mSuppliers; - - group_infos.push_back(s); - } - } - } -#else // RS_DEEP_CHANNEL_INDEX - RsGxsGrpMetaTemporaryMap grpMetaMap; - { - RS_STACK_MUTEX(mNxsMutex) ; - mDataStore->retrieveGxsGrpMetaData(grpMetaMap); - } - - RsGroupNetworkStats stats; - for(auto it(grpMetaMap.begin());it!=grpMetaMap.end();++it) - if(it->second->mCircleType==GXS_CIRCLE_TYPE_PUBLIC && termSearch(it->second->mGroupName,substring)) - { - getGroupNetworkStats(it->first,stats); - - RsGxsGroupSummary s; - s.mGroupId = it->first; - s.mGroupName = it->second->mGroupName; - s.mSearchContext = it->second->mGroupName; - s.mSignFlags = it->second->mSignFlags; - s.mPublishTs = it->second->mPublishTs; - s.mAuthorId = it->second->mAuthorId; - s.mNumberOfMessages = stats.mMaxVisibleCount; - s.mLastMessageTs = stats.mLastGroupModificationTS; - s.mPopularity = it->second->mPop; - - group_infos.push_back(s); - } -#endif // RS_DEEP_CHANNEL_INDEX - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " performing local substring search in response to distant request. Found " << group_infos.size() << " responses." << std::endl; -#endif - return !group_infos.empty(); -} - -bool RsGxsNetService::search(const Sha1CheckSum& hashed_group_id,unsigned char *& encrypted_group_data,uint32_t& encrypted_group_data_len) -{ - // First look into the grp hash cache - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " Received group data request for hash " << hashed_group_id << std::endl; -#endif - auto it = mGroupHashCache.find(hashed_group_id) ; - RsNxsGrp *grp_data = NULL ; - - if(mGroupHashCache.end() != it) - { - grp_data = it->second; - } - else - { - // Now check if the last request was too close in time, in which case, we dont retrieve data. - - if(mLastCacheReloadTS + 60 > time(NULL)) - { - std::cerr << "(WW) Not found in cache, and last cache reload less than 60 secs ago. Returning false. " << std::endl; - return false ; - } - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " reloading group cache information" << std::endl; -#endif - RsNxsGrpDataTemporaryMap grpDataMap; - { - RS_STACK_MUTEX(mNxsMutex) ; - mDataStore->retrieveNxsGrps(grpDataMap, true); - mLastCacheReloadTS = time(NULL); - } - - for(auto it(grpDataMap.begin());it!=grpDataMap.end();++it) - if(it->second->metaData->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED ) // only cache subscribed groups - { - RsNxsGrp *grp = it->second ; - grp->metaData->keys.TlvClear() ;// clean private keys. This technically not needed, since metaData is not serialized, but I still prefer. - - Sha1CheckSum hash(RsDirUtil::sha1sum(it->first.toByteArray(),it->first.SIZE_IN_BYTES)); - - mGroupHashCache[hash] = grp ; - it->second = NULL ; // prevents deletion - - if(hash == hashed_group_id) - grp_data = grp ; - } - } - - if(!grp_data) - { -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " no group found for hash " << hashed_group_id << ": returning false." << std::endl; -#endif - return false ; - } - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " found corresponding group data group id in cache group_id=" << grp_data->grpId << std::endl; -#endif - // Finally, serialize and encrypt the grp data - - uint32_t size = RsNxsSerialiser(mServType).size(grp_data); - RsNxsGrp *author_group=nullptr; - - if(!grp_data->metaData->mAuthorId.isNull()) - { -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " this group has an author identity " << grp_data->metaData->mAuthorId << " that we need to send at the same time." << std::endl; -#endif - mGixs->retrieveNxsIdentity(grp_data->metaData->mAuthorId,author_group); // whatever gets the data - - if(!author_group) - { - std::cerr << "(EE) Cannot retrieve author group data " << grp_data->metaData->mAuthorId << " for GXS group " << grp_data->grpId << std::endl; - return false; - } - - delete author_group->metaData; // delete private information, just in case, but normally it is not serialized. - author_group->metaData = NULL ; - - size += RsNxsSerialiser(RS_SERVICE_GXS_TYPE_GXSID).size(author_group); - } - - RsTemporaryMemory mem(size) ; - uint32_t used_size=size; - - RsNxsSerialiser(mServType).serialise(grp_data,mem,&used_size) ; - - uint32_t remaining_size=size-used_size; - - if(author_group) - { -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " Serializing author group data..." << std::endl; -#endif - RsNxsSerialiser(RS_SERVICE_GXS_TYPE_GXSID).serialise(author_group,mem+used_size,&remaining_size); - } - - uint8_t encryption_master_key[32]; - Sha256CheckSum s = RsDirUtil::sha256sum(grp_data->grpId.toByteArray(),grp_data->grpId.SIZE_IN_BYTES); - memcpy(encryption_master_key,s.toByteArray(),32); - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " sending data encrypted with master key " << RsUtil::BinToHex(encryption_master_key,32) << std::endl; -#endif - return librs::crypto::encryptAuthenticateData(mem,size,encryption_master_key,encrypted_group_data,encrypted_group_data_len); -} - diff --git a/libretroshare/src/gxs/rsgxsnetservice.h b/libretroshare/src/gxs/rsgxsnetservice.h deleted file mode 100644 index 295b8232a..000000000 --- a/libretroshare/src/gxs/rsgxsnetservice.h +++ /dev/null @@ -1,633 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsnetservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSGXSNETSERVICE_H -#define RSGXSNETSERVICE_H - -#include -#include - -#include "rsnxs.h" -#include "rsgds.h" -#include "rsnxsobserver.h" -#include "pqi/p3linkmgr.h" -#include "rsitems/rsnxsitems.h" -#include "rsitems/rsgxsupdateitems.h" -#include "rsgxsnettunnel.h" -#include "rsgxsnetutils.h" -#include "pqi/p3cfgmgr.h" -#include "rsgixs.h" -#include "util/rssharedptr.h" - -/// keep track of transaction number -typedef std::map TransactionIdMap; - -/// to keep track of peers active transactions -typedef std::map TransactionsPeerMap; - -class PgpAuxUtils; - -class RsGroupNetworkStatsRecord -{ - public: - RsGroupNetworkStatsRecord() { max_visible_count= 0 ; update_TS=0; } - - std::set suppliers ; - uint32_t max_visible_count ; - rstime_t update_TS ; -}; - -struct GroupRequestRecord -{ - GroupRequestRecord(): ts(0),request_id(0),status(DistantSearchGroupStatus::UNKNOWN) {} - - rstime_t ts ; - TurtleRequestId request_id; - DistantSearchGroupStatus status; -}; - -/*! - * This class implements the RsNetWorkExchangeService - * using transactions to handle synchrnisation of Nxs items between - * peers in a network - * Transactions requires the maintenance of several states between peers - * - * Thus a data structure maintains: peers, and their active transactions - * Then for each transaction it needs to be noted if this is an outgoing or incoming transaction - * Outgoing transaction are in 3 different states: - * 1. START 2. INITIATED 3. SENDING 4. END - * Incoming transaction are in 3 different states - * 1. START 2. RECEIVING 3. END - */ -class RsGxsNetService : - public RsNetworkExchangeService, public p3ThreadedService, public p3Config -{ -public: - - static const uint32_t FRAGMENT_SIZE; - /*! - * only one observer is allowed - * @param servType service type - * @param gds The data service which allows read access to a service/store - * @param nxsObs observer will be notified whenever new messages/grps - * @param nxsObs observer will be notified whenever new messages/grps - * arrive - */ - RsGxsNetService(uint16_t servType, RsGeneralDataService *gds, - RsNxsNetMgr *netMgr, - RsNxsObserver *nxsObs, // used to be = NULL. - const RsServiceInfo serviceInfo, - RsGixsReputation* reputations = NULL, RsGcxs* circles = NULL, RsGixs *gixs=NULL, - PgpAuxUtils *pgpUtils = NULL, RsGxsNetTunnelService *mGxsNT = NULL, - bool grpAutoSync = true, bool msgAutoSync = true,bool distSync=false, - uint32_t default_store_period = RS_GXS_DEFAULT_MSG_STORE_PERIOD, - uint32_t default_sync_period = RS_GXS_DEFAULT_MSG_REQ_PERIOD); - - virtual ~RsGxsNetService(); - - virtual RsServiceInfo getServiceInfo() override { return mServiceInfo; } - - virtual void getItemNames(std::map& names) const override ; - -public: - - - virtual uint16_t serviceType() const override { return mServType ; } - - /*! - * Use this to set how far back synchronisation and storage of messages should take place - * @param age the max age a sync/storage item can to be allowed in a synchronisation - */ - virtual void setSyncAge(const RsGxsGroupId& grpId,uint32_t age_in_secs)override ; - virtual void setKeepAge(const RsGxsGroupId& grpId,uint32_t age_in_secs)override ; - - virtual uint32_t getSyncAge(const RsGxsGroupId& id)override ; - virtual uint32_t getKeepAge(const RsGxsGroupId& id)override ; - - virtual uint32_t getDefaultSyncAge() override { return mDefaultMsgSyncPeriod ; } - virtual uint32_t getDefaultKeepAge() override { return mDefaultMsgStorePeriod ; } - - virtual void setDefaultKeepAge(uint32_t t) override { mDefaultMsgStorePeriod = t ; } - virtual void setDefaultSyncAge(uint32_t t) override { mDefaultMsgSyncPeriod = t ; } - - virtual bool msgAutoSync() const override { return mAllowMsgSync; } - virtual bool grpAutoSync() const override { return mGrpAutoSync; } - /*! - * \brief Search methods. - * These four methods are used to request distant search and receive the results. - * \param group_id - */ - virtual TurtleRequestId turtleGroupRequest(const RsGxsGroupId& group_id)override ; - virtual TurtleRequestId turtleSearchRequest(const std::string& match_string)override ; - - virtual bool search(const std::string& substring,std::list& group_infos) override ; - virtual bool search(const Sha1CheckSum& hashed_group_id,unsigned char *& encrypted_group_data,uint32_t& encrypted_group_data_len)override ; - virtual void receiveTurtleSearchResults(TurtleRequestId req,const std::list& group_infos)override ; - virtual void receiveTurtleSearchResults(TurtleRequestId req,const unsigned char *encrypted_group_data,uint32_t encrypted_group_data_len)override ; - - virtual bool retrieveDistantSearchResults(TurtleRequestId req, std::map &group_infos)override ; - virtual bool clearDistantSearchResults(const TurtleRequestId& id)override ; - virtual bool retrieveDistantGroupSummary(const RsGxsGroupId&, RsGxsGroupSearchResults &)override ; - virtual DistantSearchGroupStatus getDistantSearchStatus(const RsGxsGroupId&) override ; - - /*! - * pauses synchronisation of subscribed groups and request for group id - * from peers - * @param enabled set to false to disable pause, and true otherwise - */ - // NOT IMPLEMENTED - virtual void pauseSynchronisation(bool enabled)override ; - - - /*! - * Request for this message is sent through to peers on your network - * and how many hops from them you've indicated - * @param msgId the messages to retrieve - * @return request token to be redeemed - */ - virtual int requestMsg(const RsGxsGrpMsgIdPair& /* msgId */)override { return 0;} - - /*! - * Request for this group is sent through to peers on your network - * and how many hops from them you've indicated - * @param enabled set to false to disable pause, and true otherwise - * @return request token to be redeemed - */ - virtual int requestGrp(const std::list& grpId, const RsPeerId& peerId)override ; - - /*! - * share publish keys for the specified group with the peers in the specified list. - */ - - virtual int sharePublishKey(const RsGxsGroupId& grpId,const std::set& peers) override ; - - /*! - * Returns statistics for the group networking activity: popularity (number of friends subscribers) and max_visible_msg_count, - * that is the max nnumber of messages reported by a friend. - */ - virtual bool getGroupNetworkStats(const RsGxsGroupId& id,RsGroupNetworkStats& stats) override ; - - /*! - * Used to inform the net service that we changed subscription status. That helps - * optimising data transfer when e.g. unsubsribed groups are updated less often, etc - */ - virtual void subscribeStatusChanged(const RsGxsGroupId& id,bool subscribed) override ; - - virtual void rejectMessage(const RsGxsMessageId& msg_id) override ; - - virtual bool getGroupServerUpdateTS(const RsGxsGroupId& gid,rstime_t& grp_server_update_TS,rstime_t& msg_server_update_TS) override ; - virtual bool stampMsgServerUpdateTS(const RsGxsGroupId& gid) override ; - virtual bool removeGroups(const std::list& groups)override ; - virtual bool isDistantPeer(const RsPeerId& pid)override ; - - /* p3Config methods */ -public: - - bool loadList(std::list& load)override ; - bool saveList(bool &cleanup, std::list&)override ; - RsSerialiser *setupSerialiser()override ; - -public: - - /*! - * initiates synchronisation - */ - int tick()override ; - - void threadTick() override; /// @see RsTickingThread - -private: - - /*! - * called when - * items are deemed to be waiting in p3Service item queue - */ - void recvNxsItemQueue(); - - - /** S: Transaction processing **/ - - /*! - * These process transactions which are in a wait state - * Also moves transaction which have been completed to - * the completed transactions list - */ - void processTransactions(); - - /*! - * Process completed transaction, which either simply - * retires a transaction or additionally generates a response - * to the completed transaction - */ - void processCompletedTransactions(); - - /*! - * Process transaction owned/started by user - * @param tr transaction to process, ownership stays with callee - */ - void locked_processCompletedOutgoingTrans(NxsTransaction* tr); - - /*! - * Process transactions started/owned by other peers - * @param tr transaction to process, ownership stays with callee - */ - void locked_processCompletedIncomingTrans(NxsTransaction* tr); - - - /*! - * Process a transaction item, assumes a general lock - * @param item the transaction item to process - * @return false ownership of item left with callee - */ - bool locked_processTransac(RsNxsTransacItem* item); - - /*! - * This adds a transaction - * completeted transaction list - * If this is an outgoing transaction, transaction id is - * decrement - * @param trans transaction to add - */ - void locked_completeTransaction(NxsTransaction* trans); - - /*! - * \brief locked_stampMsgServerUpdateTS - * updates the server msg time stamp. This function is the locked method for the one above with similar name - * \param gid group id to stamp. - * \return - */ - bool locked_stampMsgServerUpdateTS(const RsGxsGroupId& gid); - /*! - * This retrieves a unique transaction id that - * can be used in an outgoing transaction - */ - uint32_t locked_getTransactionId(); - - /*! - * This attempts to push the transaction id counter back if you have - * active outgoing transactions in play - */ - bool attemptRecoverIds(); - - /*! - * The cb listener is the owner of the grps - * @param grps - */ - //void notifyListenerGrps(std::list& grps); - - /*! - * The cb listener is the owner of the msgs - * @param msgs - */ - //void notifyListenerMsgs(std::list& msgs); - - /*! - * Generates new transaction to send msg requests based on list - * of msgs received from peer stored in passed transaction - * @param tr transaction responsible for generating msg request - */ - void locked_genReqMsgTransaction(NxsTransaction* tr); - - /*! - * Generates new transaction to send grp requests based on list - * of grps received from peer stored in passed transaction - * @param tr transaction responsible for generating grp request - */ - void locked_genReqGrpTransaction(NxsTransaction* tr); - - /*! - * This first checks if one can send a grpId based circles - * If it can send, then it call locked_genSendMsgsTransaction - * @param tr transaction responsible for generating grp request - * @see locked_genSendMsgsTransaction - */ - void locked_checkSendMsgsTransaction(NxsTransaction* tr); - - /*! - * Generates new transaction to send msg data based on list - * of grpids received from peer stored in passed transaction - * @param tr transaction responsible for generating grp request - */ - void locked_genSendMsgsTransaction(NxsTransaction* tr); - - /*! - * Generates new transaction to send grp data based on list - * of grps received from peer stored in passed transaction - * @param tr transaction responsible for generating grp request - */ - void locked_genSendGrpsTransaction(NxsTransaction* tr); - - /*! - * convenience function to add a transaction to list - * @param tr transaction to add - */ - bool locked_addTransaction(NxsTransaction* tr); - - void cleanTransactionItems(NxsTransaction* tr) const; - - /*! - * @param tr the transaction to check for timeout - * @return false if transaction has timed out, true otherwise - */ - bool locked_checkTransacTimedOut(NxsTransaction* tr); - - /** E: Transaction processing **/ - - /** S: item handlers **/ - - /*! - * This attempts handles transaction items - * ownership of item is left with callee if this method returns false - * @param item transaction item to handle - * @return false if transaction could not be handled, ownership of item is left with callee - */ - bool handleTransaction(RsNxsItem* item); - - /*! - * Handles an nxs item for group synchronisation - * by startin a transaction and sending a list - * of groups held by user - * @param item contains grp sync info - */ - void handleRecvSyncGroup(RsNxsSyncGrpReqItem* item); - - /*! - * Handles an nxs item for group statistics - * @param item contaims update time stamp and number of messages - */ - void handleRecvSyncGrpStatistics(RsNxsSyncGrpStatsItem *grs); - - /*! - * Handles an nxs item for msgs synchronisation - * @param item contaims msg sync info - */ - void handleRecvSyncMessage(RsNxsSyncMsgReqItem* item,bool item_was_encrypted); - - /*! - * Handles an nxs item for group publish key - * @param item contaims keys/grp info - */ - void handleRecvPublishKeys(RsNxsGroupPublishKeyItem*) ; - - /** E: item handlers **/ - - - void runVetting(); - - /*! - * @param peerId The peer to vet to see if they can receive this groupid - * @param grpMeta this is the meta item to determine if it can be sent to given peer - * @param toVet groupid/peer to vet are stored here if their circle id is not cached - * @return false, if you cannot send to this peer, true otherwise - */ - bool canSendGrpId(const RsPeerId& sslId, const RsGxsGrpMetaData& grpMeta, std::vector& toVet, bool &should_encrypt); - bool canSendMsgIds(std::vector > &msgMetas, const RsGxsGrpMetaData&, const RsPeerId& sslId, RsGxsCircleId &should_encrypt_id); - - /*! - * \brief checkPermissionsForFriendGroup - * Checks that we can send/recv from that node, given that the grpMeta has a distribution limited to a local circle. - * \param sslId Candidate peer to send to or to receive from. - * \param grpMeta Contains info about the group id, internal circle id, etc. - * \return true only when the internal exists and validates as a friend node group, and contains the owner of sslId. - */ - bool checkPermissionsForFriendGroup(const RsPeerId& sslId,const RsGxsGrpMetaData& grpMeta) ; - - bool checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxsGrpMetaData& meta, RsGxsCircleId& should_encrypt_id); - - void locked_createTransactionFromPending(MsgRespPending* grpPend); - void locked_createTransactionFromPending(GrpRespPending* msgPend); - bool locked_createTransactionFromPending(GrpCircleIdRequestVetting* grpPend) ; - bool locked_createTransactionFromPending(MsgCircleIdsRequestVetting* grpPend) ; - - void locked_pushGrpTransactionFromList(std::list& reqList, const RsPeerId& peerId, const uint32_t& transN); // forms a grp list request - void locked_pushMsgTransactionFromList(std::list& reqList, const RsPeerId& peerId, const uint32_t& transN); // forms a msg list request - void locked_pushGrpRespFromList(std::list& respList, const RsPeerId& peer, const uint32_t& transN); - void locked_pushMsgRespFromList(std::list& itemL, const RsPeerId& sslId, const RsGxsGroupId &grp_id, const uint32_t& transN); - - void checkDistantSyncState(); - void syncWithPeers(); - void syncGrpStatistics(); - void addGroupItemToList(NxsTransaction*& tr, - const RsGxsGroupId& grpId, uint32_t& transN, - std::list& reqList); - - //bool locked_canReceive(const RsGxsGrpMetaData * const grpMeta, const RsPeerId& peerId); - - void processExplicitGroupRequests(); - - void locked_doMsgUpdateWork(const RsNxsTransacItem* nxsTrans, const RsGxsGroupId& grpId); - - void updateServerSyncTS(); -#ifdef TO_REMOVE - void updateClientSyncTS(); -#endif - - bool locked_CanReceiveUpdate(const RsNxsSyncGrpReqItem *item); - bool locked_CanReceiveUpdate(RsNxsSyncMsgReqItem *item, bool &grp_is_known); - void locked_resetClientTS(const RsGxsGroupId& grpId); - bool locked_checkResendingOfUpdates(const RsPeerId& pid, const RsGxsGroupId &grpId, rstime_t incoming_ts, RsPeerUpdateTsRecord& rec); - - static RsGxsGroupId hashGrpId(const RsGxsGroupId& gid,const RsPeerId& pid) ; - - RsGxsGrpConfig& locked_getGrpConfig(const RsGxsGroupId& grp_id); -private: - - typedef std::vector GrpFragments; - typedef std::vector MsgFragments; - - /*! - * Loops over pending publish key orders. - */ - void sharePublishKeysPending() ; - - /*! - * Fragment a message into individual fragments which are at most 150kb - * @param msg message to fragment - * @param msgFragments fragmented message - * @return false if fragmentation fails true otherwise - */ - bool fragmentMsg(RsNxsMsg& msg, MsgFragments& msgFragments) const; - - /*! - * Fragment a group into individual fragments which are at most 150kb - * @param grp group to fragment - * @param grpFragments fragmented group - * @return false if fragmentation fails true other wise - */ - bool fragmentGrp(RsNxsGrp& grp, GrpFragments& grpFragments) const; - - /*! - * Fragment a message into individual fragments which are at most 150kb - * @param msg message to fragment - * @param msgFragments fragmented message - * @return NULL if not possible to reconstruct message from fragment, - * pointer to defragments nxs message is possible - */ - RsNxsMsg* deFragmentMsg(MsgFragments& msgFragments) const; - - /*! - * Fragment a group into individual fragments which are at most 150kb - * @param grp group to fragment - * @param grpFragments fragmented group - * @return NULL if not possible to reconstruct group from fragment, - * pointer to defragments nxs group is possible - */ - RsNxsGrp* deFragmentGrp(GrpFragments& grpFragments) const; - - - /*! - * Note that if all fragments for a message are not found then its fragments are dropped - * @param fragments message fragments which are not necessarily from the same message - * @param partFragments the partitioned fragments (into message ids) - */ - void collateMsgFragments(MsgFragments &fragments, std::map& partFragments) const; - - /*! - * Note that if all fragments for a group are not found then its fragments are dropped - * @param fragments group fragments which are not necessarily from the same group - * @param partFragments the partitioned fragments (into message ids) - */ - void collateGrpFragments(GrpFragments fragments, std::map& partFragments) const; - - /*! - * stamp the group info from that particular peer at the given time. - */ - - void locked_stampPeerGroupUpdateTime(const RsPeerId& pid,const RsGxsGroupId& grpId,rstime_t tm,uint32_t n_messages) ; - - /*! - * encrypts/decrypts the transaction for the destination circle id. - */ - bool encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, const RsGxsGroupId &destination_group, RsNxsItem *& encrypted_item, uint32_t &status) ; - bool decryptSingleNxsItem(const RsNxsEncryptedDataItem *encrypted_item, RsNxsItem *&nxsitem, std::vector *private_keys=NULL); - bool processTransactionForDecryption(NxsTransaction *tr); // return false when the keys are not loaded => need retry later - - void cleanRejectedMessages(); - void processObserverNotifications(); - - void generic_sendItem(RsNxsItem *si); - RsItem *generic_recvItem(); - -private: - - static void locked_checkDelay(uint32_t& time_in_secs); - - /*** transactions ***/ - - /// active transactions - TransactionsPeerMap mTransactions; - - /// completed transactions - std::list mComplTransactions; - - /// transaction id counter - uint32_t mTransactionN; - - /*** transactions ***/ - - /*** synchronisation ***/ - std::list mSyncGrp; - std::list mSyncMsg; - /*** synchronisation ***/ - - RsNxsObserver* mObserver; - RsGeneralDataService* mDataStore; - uint16_t mServType; - - // how much time must elapse before a timeout failure - // for an active transaction - uint32_t mTransactionTimeOut; - - RsPeerId mOwnId; - - RsNxsNetMgr* mNetMgr; - - /// for other members save transactions - RsMutex mNxsMutex; - - uint32_t mSyncTs; - uint32_t mLastKeyPublishTs; - uint32_t mLastCleanRejectedMessages; - - const uint32_t mSYNC_PERIOD; - int mUpdateCounter ; - - RsGcxs* mCircles; - RsGixs *mGixs; - RsGixsReputation* mReputations; - PgpAuxUtils *mPgpUtils; - RsGxsNetTunnelService *mGxsNetTunnel; - - bool mGrpAutoSync; - bool mAllowMsgSync; - bool mAllowDistSync; - - // need to be verfied - std::vector mPendingResp; - std::vector mPendingCircleVets; - std::map > mPendingPublishKeyRecipients ; - std::map > mExplicitRequest; - std::map > mPartialMsgUpdates ; - - // nxs sync optimisation - // can pull dynamically the latest timestamp for each message - -public: - - typedef std::map ClientMsgMap; - typedef std::map ServerMsgMap; - typedef std::map ClientGrpMap; - typedef std::map GrpConfigMap; -private: - - ClientMsgMap mClientMsgUpdateMap; - ServerMsgMap mServerMsgUpdateMap; - ClientGrpMap mClientGrpUpdateMap; - GrpConfigMap mServerGrpConfigMap; - - RsGxsServerGrpUpdate mGrpServerUpdate; - RsServiceInfo mServiceInfo; - - std::map mRejectedMessages; - - std::vector mNewGroupsToNotify ; - std::vector mNewMessagesToNotify ; - std::set mNewStatsToNotify ; - std::set mNewPublishKeysToNotify ; - std::set mNewGrpSyncParamsToNotify ; - - // Distant search result map - std::map > mDistantSearchResults ; - - void debugDump(); - - uint32_t mDefaultMsgStorePeriod ; - uint32_t mDefaultMsgSyncPeriod ; - - std::map mGroupHashCache; - std::map mSearchRequests; - std::map mSearchedGroups ; - rstime_t mLastCacheReloadTS ; - - bool mUseMetaCache; -}; - -#endif // RSGXSNETSERVICE_H diff --git a/libretroshare/src/gxs/rsgxsnettunnel.cc b/libretroshare/src/gxs/rsgxsnettunnel.cc deleted file mode 100644 index 380491c5d..000000000 --- a/libretroshare/src/gxs/rsgxsnettunnel.cc +++ /dev/null @@ -1,1180 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxsnettunnel.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "util/rsdir.h" -#include "util/rstime.h" -#include "retroshare/rspeers.h" -#include "serialiser/rstypeserializer.h" -#include "gxs/rsnxs.h" -#include "rsgxsnettunnel.h" - -//#define DEBUG_RSGXSNETTUNNEL 1 - -#define GXS_NET_TUNNEL_NOT_IMPLEMENTED() { std::cerr << __PRETTY_FUNCTION__ << ": not yet implemented." << std::endl; } -#define GXS_NET_TUNNEL_DEBUG() std::cerr << time(NULL) << " : GXS_NET_TUNNEL: " << __FUNCTION__ << " : " -#define GXS_NET_TUNNEL_ERROR() std::cerr << "(EE) GXS_NET_TUNNEL ERROR : " - -static const uint32_t RS_GXS_NET_TUNNEL_MAX_ALLOWED_HITS_GROUP_DATA = 1; -static const uint32_t RS_GXS_NET_TUNNEL_MAX_ALLOWED_HITS_GROUP_SEARCH = 100; - -RsGxsDistSync *rsGxsDistSync = NULL; - -RsGxsNetTunnelService::RsGxsNetTunnelService(): mGxsNetTunnelMtx("GxsNetTunnel") -{ - mRandomBias.clear(); - - mLastKeepAlive = time(NULL) + (RSRandom::random_u32()%20); // adds some variance in order to avoid doing all this tasks at once across services - mLastAutoWash = time(NULL) + (RSRandom::random_u32()%20); - mLastDump = time(NULL) + (RSRandom::random_u32()%20); -} - -//===========================================================================================================================================// -// Transport Items // -//===========================================================================================================================================// - -const uint16_t RS_SERVICE_TYPE_GXS_NET_TUNNEL = 0x2233 ; - -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_VIRTUAL_PEER = 0x01 ; -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_KEEP_ALIVE = 0x02 ; -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_RANDOM_BIAS = 0x03 ; -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_SUBSTRING = 0x04 ; -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_REQUEST = 0x05 ; -// const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_SUMMARY = 0x06; // DEPRECATED -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_DATA = 0x07 ; -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_SUMMARY = 0x08; - -class RsGxsNetTunnelItem: public RsItem -{ -public: - explicit RsGxsNetTunnelItem(uint8_t item_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_GXS_NET_TUNNEL,item_subtype) - { - // no priority. All items are encapsulated into generic Turtle items anyway. - } - - virtual ~RsGxsNetTunnelItem() {} - virtual void clear() {} -}; - -class RsGxsNetTunnelVirtualPeerItem: public RsGxsNetTunnelItem -{ -public: - RsGxsNetTunnelVirtualPeerItem() :RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_VIRTUAL_PEER) {} - - virtual ~RsGxsNetTunnelVirtualPeerItem() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,virtual_peer_id,"virtual_peer_id") ; - } - - RsPeerId virtual_peer_id ; -}; - -class RsGxsNetTunnelKeepAliveItem: public RsGxsNetTunnelItem -{ -public: - RsGxsNetTunnelKeepAliveItem() :RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_KEEP_ALIVE) {} - - virtual ~RsGxsNetTunnelKeepAliveItem() {} - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) {} -}; - -class RsGxsNetTunnelRandomBiasItem: public RsGxsNetTunnelItem -{ -public: - explicit RsGxsNetTunnelRandomBiasItem() : RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_RANDOM_BIAS) { clear();} - virtual ~RsGxsNetTunnelRandomBiasItem() {} - - virtual void clear() { mRandomBias.clear() ; } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,mRandomBias,"random bias") ; - } - - Bias20Bytes mRandomBias; // Cannot be a simple char[] because of serialization. -}; - -class RsGxsNetTunnelTurtleSearchSubstringItem: public RsGxsNetTunnelItem -{ -public: - explicit RsGxsNetTunnelTurtleSearchSubstringItem(): RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_SUBSTRING) {} - virtual ~RsGxsNetTunnelTurtleSearchSubstringItem() {} - - uint16_t service ; - std::string substring_match ; - - virtual void clear() { substring_match.clear() ; } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,service,"service") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_KEY,substring_match,"substring_match") ; - } -}; - -class RsGxsNetTunnelTurtleSearchGroupRequestItem: public RsGxsNetTunnelItem -{ -public: - explicit RsGxsNetTunnelTurtleSearchGroupRequestItem(): RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_REQUEST) {} - virtual ~RsGxsNetTunnelTurtleSearchGroupRequestItem() {} - - uint16_t service ; - Sha1CheckSum hashed_group_id ; - - virtual void clear() { hashed_group_id.clear() ; } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,service,"service") ; - RsTypeSerializer::serial_process(j,ctx,hashed_group_id,"hashed_group_id") ; - } -}; - -class RsGxsNetTunnelTurtleSearchGroupSummaryItem: public RsGxsNetTunnelItem -{ -public: - explicit RsGxsNetTunnelTurtleSearchGroupSummaryItem(): RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_SUMMARY) {} - virtual ~RsGxsNetTunnelTurtleSearchGroupSummaryItem() {} - - uint16_t service ; - std::list group_infos; - - virtual void clear() { group_infos.clear() ; } - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,service,"service") ; - RsTypeSerializer::serial_process(j,ctx,group_infos,"group_infos") ; - } -}; -class RsGxsNetTunnelTurtleSearchGroupDataItem: public RsGxsNetTunnelItem -{ -public: - explicit RsGxsNetTunnelTurtleSearchGroupDataItem() - : RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_DATA), - encrypted_group_data(NULL), - encrypted_group_data_len(0) - {} - - virtual ~RsGxsNetTunnelTurtleSearchGroupDataItem() {} - - uint16_t service ; - unsigned char *encrypted_group_data ; - uint32_t encrypted_group_data_len ; - - virtual void clear() { free(encrypted_group_data);encrypted_group_data=NULL;encrypted_group_data_len=0; } - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,service,"service") ; - - RsTypeSerializer::TlvMemBlock_proxy prox(encrypted_group_data,encrypted_group_data_len) ; - RsTypeSerializer::serial_process(j,ctx,prox,"encrypted_group_data") ; - } -}; - -class RsGxsNetTunnelSerializer: public RsServiceSerializer -{ -public: - RsGxsNetTunnelSerializer() :RsServiceSerializer(RS_SERVICE_TYPE_GXS_NET_TUNNEL) {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const - { - if(service != RS_SERVICE_TYPE_GXS_NET_TUNNEL) - { - GXS_NET_TUNNEL_ERROR() << "received item with wrong service ID " << std::hex << service << std::dec << std::endl; - return NULL ; - } - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_GXS_NET_TUNNEL_VIRTUAL_PEER : return new RsGxsNetTunnelVirtualPeerItem ; - case RS_PKT_SUBTYPE_GXS_NET_TUNNEL_KEEP_ALIVE : return new RsGxsNetTunnelKeepAliveItem ; - case RS_PKT_SUBTYPE_GXS_NET_TUNNEL_RANDOM_BIAS : return new RsGxsNetTunnelRandomBiasItem ; - case RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_SUBSTRING : return new RsGxsNetTunnelTurtleSearchSubstringItem; - case RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_REQUEST : return new RsGxsNetTunnelTurtleSearchGroupRequestItem; - case RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_SUMMARY : return new RsGxsNetTunnelTurtleSearchGroupSummaryItem; - case RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_DATA : return new RsGxsNetTunnelTurtleSearchGroupDataItem; - default: - GXS_NET_TUNNEL_ERROR() << "type ID " << std::hex << (int)item_subtype << std::dec << " is not handled!" << std::endl; - return NULL ; - } - } -}; - -//===========================================================================================================================================// -// Interface with rest of the software // -//===========================================================================================================================================// - -uint16_t RsGxsNetTunnelService::serviceId() const -{ - return RS_SERVICE_TYPE_GXS_NET_TUNNEL; -} - -bool RsGxsNetTunnelService::registerSearchableService(RsNetworkExchangeService *gxs_service) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - mSearchableServices[gxs_service->serviceType()] = gxs_service ; - - return true; -} - -class DataAutoDelete -{ -public: - DataAutoDelete(unsigned char *& data) : mData(data) {} - ~DataAutoDelete() { free(mData); mData=NULL ; } - unsigned char *& mData; -}; - -RsGxsNetTunnelService::~RsGxsNetTunnelService() -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - // This is needed because we need to clear these structure in a mutex protected environment - // Also this calls the destructor of the objects which calls the freeing of memory e.g. allocated in the incoming data list. - - mGroups.clear(); - mHandledHashes.clear(); - mVirtualPeers.clear(); - - for(auto it(mIncomingData.begin());it!=mIncomingData.end();++it) - for(auto it2(it->second.begin());it2!=it->second.end();++it2) - delete it2->second; - - mIncomingData.clear(); -} - -bool RsGxsNetTunnelService::isDistantPeer(const RsGxsNetTunnelVirtualPeerId& virtual_peer, RsGxsGroupId& group_id) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - auto it = mVirtualPeers.find(virtual_peer) ; - - if(it != mVirtualPeers.end()) - { - group_id = it->second.group_id ; - return true ; - } - else - return false ; -} - -bool RsGxsNetTunnelService::receiveTunnelData(uint16_t service_id, unsigned char *& data, uint32_t& data_len, RsGxsNetTunnelVirtualPeerId& virtual_peer) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - std::list >& lst(mIncomingData[service_id]); - - if(lst.empty()) - { - data = NULL; - data_len = 0; - return false ; - } - - data = (unsigned char*)lst.front().second->bin_data ; - data_len = lst.front().second->bin_len ; - virtual_peer = lst.front().first; - - lst.front().second->bin_data = NULL ; // avoids deletion - lst.front().second->bin_len = 0 ; // avoids deletion - - delete lst.front().second; - lst.pop_front(); - - return true; -} - -bool RsGxsNetTunnelService::sendTunnelData(uint16_t /* service_id */,unsigned char *& data,uint32_t data_len,const RsGxsNetTunnelVirtualPeerId& virtual_peer) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - // The item is serialized and encrypted using chacha20+SHA256, using the generic turtle encryption, and then sent to the turtle router. - - DataAutoDelete iad(data) ; // This ensures the item is deleted whatsoever when leaving - - // 1 - find the virtual peer and the proper master key to encrypt with, and check that all the info is known - - auto it = mVirtualPeers.find(virtual_peer) ; - - if(it == mVirtualPeers.end()) - { - GXS_NET_TUNNEL_ERROR() << "cannot find virtual peer " << virtual_peer << ". Data is dropped." << std::endl; - return false ; - } - - if(it->second.vpid_status != RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE) - { - GXS_NET_TUNNEL_ERROR() << "virtual peer " << virtual_peer << " is not active. Data is dropped." << std::endl; - return false ; - } - - // 2 - encrypt and send the item. - - RsTurtleGenericDataItem *encrypted_turtle_item = NULL ; - - if(!p3turtle::encryptData(data,data_len,it->second.encryption_master_key,encrypted_turtle_item)) - { - GXS_NET_TUNNEL_ERROR() << "cannot encrypt. Something's wrong. Data is dropped." << std::endl; - return false ; - } - - mTurtle->sendTurtleData(it->second.turtle_virtual_peer_id,encrypted_turtle_item) ; - - return true ; -} - -bool RsGxsNetTunnelService::getVirtualPeers(std::list& peers) -{ - // This function has two effects: - // - return the virtual peers for this group - // - passively set the group as "managed", so that it we answer tunnel requests. - - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - // update the hash entry if needed - - for(auto it(mVirtualPeers.begin());it!=mVirtualPeers.end();++it) - peers.push_back(it->first) ; - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " returning " << peers.size() << " peers." << std::endl; -#endif - - return true ; -} - -bool RsGxsNetTunnelService::requestDistantPeers(uint16_t service_id, const RsGxsGroupId& group_id) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - // Now ask the turtle router to manage a tunnel for that hash. - - RsGxsNetTunnelGroupInfo& ginfo( mGroups[group_id] ) ; - - if(ginfo.group_policy < RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE) - ginfo.group_policy = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE; - - ginfo.hash = calculateGroupHash(group_id) ; - ginfo.service_id = service_id; - - mHandledHashes[ginfo.hash] = group_id ; - - // we dont set the group policy here. It will only be set if no peers, or too few peers are available. -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " requesting peers for group " << group_id << std::endl; -#endif - - return true; -} - -bool RsGxsNetTunnelService::releaseDistantPeers(uint16_t /* service_id */,const RsGxsGroupId& group_id) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - // Ask turtle router to stop requesting tunnels for that hash. - - RsGxsNetTunnelGroupInfo& ginfo( mGroups[group_id] ) ; - - ginfo.group_policy = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE; - ginfo.hash = calculateGroupHash(group_id) ; - - mHandledHashes[ginfo.hash] = group_id ; // yes, we do not remove, because we're supposed to answer tunnel requests from other peers. - - mTurtle->stopMonitoringTunnels(ginfo.hash) ; - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " releasing peers for group " << group_id << std::endl; -#endif - return true; -} - -void RsGxsNetTunnelService::dump() const -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - static std::string group_status_str[4] = { - std::string("[UNKNOWN ]"), - std::string("[IDLE ]"), - std::string("[TUNNELS_REQUESTED]"), - std::string("[VPIDS_AVAILABLE ]") - }; - - static std::string group_policy_str[4] = { - std::string("[UNKNOWN ]"), - std::string("[PASSIVE ]"), - std::string("[ACTIVE ]"), - std::string("[REQUESTING]"), - }; - static std::string vpid_status_str[3] = { - std::string("[UNKNOWN ]"), - std::string("[TUNNEL_OK]"), - std::string("[ACTIVE ]") - }; - - std::cerr << "GxsNetTunnelService dump (this=" << (void*)this << ": " << std::endl; - std::cerr << " Managed GXS groups: " << std::endl; - - for(auto it(mGroups.begin());it!=mGroups.end();++it) - { - std::cerr << " " << it->first << " hash: " << it->second.hash << " policy: " << group_policy_str[it->second.group_policy] << " status: " << group_status_str[it->second.group_status] << " Last contact: " << time(NULL) - it->second.last_contact << " secs ago" << std::endl; - - if(!it->second.virtual_peers.empty()) - std::cerr << " virtual peers:" << std::endl; - for(auto it2(it->second.virtual_peers.begin());it2!=it->second.virtual_peers.end();++it2) - std::cerr << " " << *it2 << std::endl; - } - - std::cerr << " Virtual peers: " << std::endl; - for(auto it(mVirtualPeers.begin());it!=mVirtualPeers.end();++it) - std::cerr << " GXS Peer:" << it->first << " Turtle:" << it->second.turtle_virtual_peer_id - << " status: " << vpid_status_str[it->second.vpid_status] - << " group_id: " << it->second.group_id - << " direction: " << (int)it->second.side - << " last seen " << time(NULL)-it->second.last_contact << " secs ago" - << " ekey: " << RsUtil::BinToHex(it->second.encryption_master_key,RS_GXS_TUNNEL_CONST_EKEY_SIZE,10) << std::endl; - - std::cerr << " Virtual peer turtle => GXS conversion table: " << std::endl; - for(auto it(mTurtle2GxsPeer.begin());it!=mTurtle2GxsPeer.end();++it) - std::cerr << " " << it->first << " => " << it->second << std::endl; - - std::cerr << " Hashes: " << std::endl; - for(auto it(mHandledHashes.begin());it!=mHandledHashes.end();++it) - std::cerr << " hash: " << it->first << " GroupId: " << it->second << std::endl; - - std::cerr << " Incoming data: " << std::endl; - for(auto it(mIncomingData.begin());it!=mIncomingData.end();++it) - { - std::cerr << " service " << std::hex << it->first << std::dec << std::endl; - - for(auto it2(it->second.begin());it2!=it->second.end();++it2) - std::cerr << " peer id " << it2->first << " " << (void*)it2->second << std::endl; - } -} - -//===========================================================================================================================================// -// Interaction with Turtle Router // -//===========================================================================================================================================// - -void RsGxsNetTunnelService::connectToTurtleRouter(p3turtle *tr) -{ - mTurtle = tr ; - mTurtle->registerTunnelService(this) ; -} - -bool RsGxsNetTunnelService::handleTunnelRequest(const RsFileHash &hash,const RsPeerId& /* peer_id */) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - // We simply check for wether a managed group has a hash that corresponds to the given hash. - - return mHandledHashes.find(hash) != mHandledHashes.end(); -} - -void RsGxsNetTunnelService::receiveTurtleData(const RsTurtleGenericTunnelItem *item, const RsFileHash& hash, const RsPeerId& turtle_virtual_peer_id, RsTurtleGenericTunnelItem::Direction direction) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " received turtle data for vpid " << turtle_virtual_peer_id << " for hash " << hash << " in direction " << (int)direction << std::endl; -#endif - - if(item->PacketSubType() != RS_TURTLE_SUBTYPE_GENERIC_DATA) - { - GXS_NET_TUNNEL_ERROR() << "item with type " << std::hex << item->PacketSubType() << std::dec << " received by GxsNetTunnel, but is not handled!" << std::endl; - return; - } - // find the group id - - auto it4 = mHandledHashes.find(hash) ; - - if(it4 == mHandledHashes.end()) - { - GXS_NET_TUNNEL_ERROR() << "Cannot find hash " << hash << " to be handled by GxsNetTunnel" << std::endl; - return; - } - RsGxsGroupId group_id = it4->second; - - // Now check if we got an item to advertise a virtual peer - - unsigned char *data = NULL ; - uint32_t data_size = 0 ; - - // generate the decryption key based on virtual peer id and group id - - uint8_t encryption_master_key[RS_GXS_TUNNEL_CONST_EKEY_SIZE] ; - - generateEncryptionKey(group_id,turtle_virtual_peer_id,encryption_master_key); - - if(!p3turtle::decryptItem(static_cast(item),encryption_master_key,data,data_size)) - { - GXS_NET_TUNNEL_ERROR() << "Cannot decrypt data!" << std::endl; - - if(data) - free(data) ; - - return ; - } - - uint16_t service_id = getRsItemService(getRsItemId(data)); - - if(service_id == RS_SERVICE_TYPE_GXS_NET_TUNNEL) - { - RsItem *decrypted_item = RsGxsNetTunnelSerializer().deserialise(data,&data_size); - RsGxsNetTunnelVirtualPeerItem *pid_item = dynamic_cast(decrypted_item) ; - - if(!pid_item) // this handles the case of a KeepAlive packet. - { - delete decrypted_item ; - free(data); - return ; - } - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " item is a virtual peer id item with vpid = "<< pid_item->virtual_peer_id - << " for group " << group_id << ". Setting virtual peer." << std::endl; -#endif - // we receive a virtual peer id, so we need to update the local information for this peer id - - mTurtle2GxsPeer[turtle_virtual_peer_id] = pid_item->virtual_peer_id ; - - RsGxsNetTunnelVirtualPeerInfo& vp_info(mVirtualPeers[pid_item->virtual_peer_id]) ; - delete pid_item; - - vp_info.vpid_status = RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE ; // status of the peer - vp_info.side = direction; // client/server - vp_info.last_contact = time(NULL); // last time some data was sent/recvd - vp_info.group_id = group_id; - vp_info.service_id = mGroups[group_id].service_id ; - - memcpy(vp_info.encryption_master_key,encryption_master_key,RS_GXS_TUNNEL_CONST_EKEY_SIZE); - - vp_info.turtle_virtual_peer_id = turtle_virtual_peer_id; // turtle peer to use when sending data to this vpid. - - free(data); - - return ; - } - - - // item is a generic data item for the client. Let's store the data in the appropriate incoming data queue. - - auto it = mTurtle2GxsPeer.find(turtle_virtual_peer_id) ; - - if(it == mTurtle2GxsPeer.end()) - { - GXS_NET_TUNNEL_ERROR() << "item received by GxsNetTunnel for vpid " << turtle_virtual_peer_id << " but this vpid is unknown! Removing this vpid from group " << group_id << std::endl; - - // this situation is inconsistent: the first item that should go through the tunnel is a virtual peer info, so if we don't have one, it means that - // this virtual peer is dead. We should therefore remove it from the list of vpids for this group. - - mGroups[group_id].virtual_peers.erase(turtle_virtual_peer_id) ; - - free(data); - return; - } - - RsGxsNetTunnelVirtualPeerId gxs_vpid = it->second ; - - auto it2 = mVirtualPeers.find(gxs_vpid) ; - - if(it2 == mVirtualPeers.end()) - { - GXS_NET_TUNNEL_ERROR() << "item received by GxsNetTunnel for GXS vpid " << gxs_vpid << " but the virtual peer id is missing!" << std::endl; - free(data); - return; - } - - if(service_id != it2->second.service_id && service_id != RS_SERVICE_GXS_TYPE_GXSID) - { - GXS_NET_TUNNEL_ERROR() << " received an item for VPID " << gxs_vpid << " openned for service " << it2->second.service_id << " that is not for that service nor for GXS Id service (service=" << std::hex << service_id << std::dec << ". Rejecting!" << std::endl; - free(data); - return ; - } - it2->second.vpid_status = RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE ; // status of the peer - it2->second.last_contact = time(NULL); // last time some data was sent/recvd from this peer - - mGroups[group_id].last_contact = time(NULL); // last time some data as received for this group - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << "item contains generic data for VPID " << gxs_vpid << ". service_id = " << std::hex << service_id << std::dec << ". Storing in incoming list" << std::endl; -#endif - - // push the data into the incoming data list - - RsTlvBinaryData *bind = new RsTlvBinaryData; - bind->tlvtype = 0; - bind->bin_len = data_size; - bind->bin_data = data; - - mIncomingData[service_id].push_back(std::make_pair(gxs_vpid,bind)) ; -} - -void RsGxsNetTunnelService::addVirtualPeer(const TurtleFileHash& hash, const TurtleVirtualPeerId& vpid,RsTurtleGenericTunnelItem::Direction dir) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - auto it = mHandledHashes.find(hash) ; - - if(it == mHandledHashes.end()) - { - std::cerr << "RsGxsNetTunnelService::addVirtualPeer(): error! hash " << hash << " is not handled. Cannot add vpid " << vpid << " in direction " << dir << std::endl; - return ; - } - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " adding virtual peer " << vpid << " for hash " << hash << " in direction " << dir << std::endl; -#endif - const RsGxsGroupId group_id(it->second) ; - - RsGxsNetTunnelGroupInfo& ginfo( mGroups[group_id] ) ; - ginfo.group_status = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_VPIDS_AVAILABLE ; - ginfo.virtual_peers.insert(vpid); - - uint8_t encryption_master_key[RS_GXS_TUNNEL_CONST_EKEY_SIZE]; - - generateEncryptionKey(group_id,vpid,encryption_master_key ); - - // We need to send our own virtual peer id to the other end of the tunnel - - RsGxsNetTunnelVirtualPeerId net_service_virtual_peer = locked_makeVirtualPeerId(group_id); - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " sending back virtual peer name " << net_service_virtual_peer << " to end of tunnel" << std::endl; -#endif - RsGxsNetTunnelVirtualPeerItem pitem ; - pitem.virtual_peer_id = net_service_virtual_peer ; - - RsTemporaryMemory tmpmem( RsGxsNetTunnelSerializer().size(&pitem) ) ; - uint32_t len = tmpmem.size(); - - RsGxsNetTunnelSerializer().serialise(&pitem,tmpmem,&len); - - RsTurtleGenericDataItem *encrypted_turtle_item = NULL ; - - if(p3turtle::encryptData(tmpmem,len,encryption_master_key,encrypted_turtle_item)) - mPendingTurtleItems.push_back(std::make_pair(vpid,encrypted_turtle_item)) ; // we cannot send directly because of turtle mutex locked before calling addVirtualPeer. - else - GXS_NET_TUNNEL_ERROR() << "cannot encrypt. Something's wrong. Data is dropped." << std::endl; -} - -void RsGxsNetTunnelService::removeVirtualPeer(const TurtleFileHash& hash, const TurtleVirtualPeerId& vpid) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " removing virtual peer " << vpid << " for hash " << hash << std::endl; -#endif - mTurtle2GxsPeer.erase(vpid); - - auto it = mHandledHashes.find(hash) ; - - if(it == mHandledHashes.end()) - { - std::cerr << "RsGxsNetTunnelService::removeVirtualPeer(): error! hash " << hash << " is not handled. Cannot remove vpid " << vpid << std::endl; - return ; - } - - const RsGxsGroupId group_id(it->second) ; - - RsGxsNetTunnelGroupInfo& ginfo( mGroups[group_id] ) ; - - ginfo.virtual_peers.erase(vpid); - - if(ginfo.virtual_peers.empty()) - { - ginfo.group_status = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE ; - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " no more virtual peers for group " << group_id << ": setting status to TUNNELS_REQUESTED" << std::endl; -#endif - } -} - -RsFileHash RsGxsNetTunnelService::calculateGroupHash(const RsGxsGroupId& group_id) const -{ - return RsDirUtil::sha1sum(group_id.toByteArray(),RsGxsGroupId::SIZE_IN_BYTES) ; -} - -void RsGxsNetTunnelService::generateEncryptionKey(const RsGxsGroupId& group_id,const TurtleVirtualPeerId& vpid,unsigned char key[RS_GXS_TUNNEL_CONST_EKEY_SIZE]) -{ - // The key is generated as H(group_id | vpid) - // Because group_id is not known it shouldn't be possible to recover the key by observing the traffic. - - assert(Sha256CheckSum::SIZE_IN_BYTES == 32) ; - - unsigned char mem[RsGxsGroupId::SIZE_IN_BYTES + TurtleVirtualPeerId::SIZE_IN_BYTES] ; - - memcpy(mem ,group_id.toByteArray(),RsGxsGroupId::SIZE_IN_BYTES) ; - memcpy(mem+RsGxsGroupId::SIZE_IN_BYTES,vpid.toByteArray() ,TurtleVirtualPeerId::SIZE_IN_BYTES) ; - - memcpy( key, RsDirUtil::sha256sum(mem,RsGxsGroupId::SIZE_IN_BYTES+TurtleVirtualPeerId::SIZE_IN_BYTES).toByteArray(), RS_GXS_TUNNEL_CONST_EKEY_SIZE ) ; -} - -//===========================================================================================================================================// -// Service parts // -//===========================================================================================================================================// - -void RsGxsNetTunnelService::threadTick() -{ - while(!mPendingTurtleItems.empty()) - { - auto& it(mPendingTurtleItems.front()); - - mTurtle->sendTurtleData(it.first,it.second) ; - mPendingTurtleItems.pop_front(); - } - - rstime_t now = time(NULL); - - // cleanup - - if(mLastAutoWash + 5 < now) - { - autowash(); - mLastAutoWash = now; - } - - if(mLastKeepAlive + 20 < now) - { - mLastKeepAlive = now ; - sendKeepAlivePackets() ; - } - -#ifdef DEBUG_RSGXSNETTUNNEL - if(mLastDump + 10 < now) - { - mLastDump = now; - dump(); - } -#endif - - for(uint32_t i=0;i<2;++i) - { - if(shouldStop()) - return; - rstime::rs_usleep(500*1000) ; // 1 sec - } -} - -const Bias20Bytes& RsGxsNetTunnelService::locked_randomBias() -{ - if(mRandomBias.isNull()) - { - mRandomBias = Bias20Bytes::random(); - IndicateConfigChanged(); - - std::cerr << "Initialized RsGxsNetTunnel random bias to " << RsUtil::BinToHex(mRandomBias.toByteArray(),mRandomBias.SIZE_IN_BYTES) << std::endl; - } - - return mRandomBias ; -} - -RsGxsNetTunnelVirtualPeerId RsGxsNetTunnelService::locked_makeVirtualPeerId(const RsGxsGroupId& group_id) -{ - assert(RsPeerId::SIZE_IN_BYTES <= Sha1CheckSum::SIZE_IN_BYTES) ;// so that we can build the virtual PeerId from a SHA1 sum. - - // We compute sha1( GroupId | mRandomBias ) and trunk it to 16 bytes in order to compute a RsPeerId - - Bias20Bytes rb(locked_randomBias()); - - unsigned char mem[group_id.SIZE_IN_BYTES + rb.SIZE_IN_BYTES]; - - memcpy(mem ,group_id.toByteArray(),group_id.SIZE_IN_BYTES) ; - memcpy(mem+group_id.SIZE_IN_BYTES,rb.toByteArray(),rb.SIZE_IN_BYTES) ; - - return RsGxsNetTunnelVirtualPeerId(RsDirUtil::sha1sum(mem,group_id.SIZE_IN_BYTES+rb.SIZE_IN_BYTES).toByteArray()); -} - - -void RsGxsNetTunnelService::sendKeepAlivePackets() -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " sending keep-alive packets. " << std::endl; -#endif - - // We send KA packets for each GXS virtual peer. The advantage is that unused tunnels will automatically die which eliminates duplicate tunnels - // automatically. We only send from the client side. - - for(auto it(mVirtualPeers.begin());it!=mVirtualPeers.end();++it) - { - RsGxsNetTunnelVirtualPeerId own_gxs_vpid = locked_makeVirtualPeerId(it->second.group_id) ; - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " virtual peer " << it->first << " through tunnel " << it->second.turtle_virtual_peer_id << " for group " << it->second.group_id ; -#endif - - if(own_gxs_vpid < it->first) - { -#ifdef DEBUG_RSGXSNETTUNNEL - std::cerr << ": sent!" << std::endl; -#endif - RsGxsNetTunnelKeepAliveItem pitem ; - RsTemporaryMemory tmpmem( RsGxsNetTunnelSerializer().size(&pitem) ) ; - uint32_t len = tmpmem.size(); - - RsGxsNetTunnelSerializer().serialise(&pitem,tmpmem,&len); - - RsTurtleGenericDataItem *encrypted_turtle_item = NULL ; - - if(p3turtle::encryptData(tmpmem,len,it->second.encryption_master_key,encrypted_turtle_item)) - mPendingTurtleItems.push_back(std::make_pair(it->second.turtle_virtual_peer_id,encrypted_turtle_item)) ; - - it->second.last_contact = time(NULL) ; - } -#ifdef DEBUG_RSGXSNETTUNNEL - else - std::cerr << ": ignored!" << std::endl; -#endif - } -} - -void RsGxsNetTunnelService::autowash() -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " performing per-group consistency test." << std::endl; -#endif - for(auto it(mGroups.begin());it!=mGroups.end();++it) - { - RsGxsNetTunnelVirtualPeerId own_gxs_vpid = locked_makeVirtualPeerId(it->first) ; - RsGxsNetTunnelGroupInfo& ginfo(it->second) ; - bool should_monitor_tunnels = false ; - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " group " << it->first << ": " ; -#endif - // check whether the group already has GXS virtual peers with suppliers. If so, we can set the GRP policy as passive. - - if(ginfo.group_policy >= RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE) - { - bool found = false ; - - // check wether one virtual peer provided by GXS has ID > own ID. In this case we leave the priority to it. - - for(auto it2(ginfo.virtual_peers.begin());!found && it2!=ginfo.virtual_peers.end();++it2) - { - auto it3 = mTurtle2GxsPeer.find(*it2) ; - - if( it3 != mTurtle2GxsPeer.end() && it3->second < own_gxs_vpid) - found = true ; - } - - if(found) - { -#ifdef DEBUG_RSGXSNETTUNNEL - std::cerr << " active, with client-side peers : "; -#endif - should_monitor_tunnels = false ; - ginfo.group_policy = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE ; - } - else - { - should_monitor_tunnels = true ; - ginfo.group_policy = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_REQUESTING ; -#ifdef DEBUG_RSGXSNETTUNNEL - std::cerr << " active, and no client-side peers available : " ; -#endif - } - } -#ifdef DEBUG_RSGXSNETTUNNEL - else - std::cerr << " passive : "; -#endif - - // We should also check whether the group is supplied using another tunnel. If so, no need to request tunnels. - // Otherwise the engine will keep requesting tunnels for all groups. -#warning CODE MISSING HERE - - if(should_monitor_tunnels) - { -#ifdef DEBUG_RSGXSNETTUNNEL - std::cerr << " requesting tunnels" << std::endl; -#endif - mTurtle->monitorTunnels(ginfo.hash,this,false) ; - } - else - { -#ifdef DEBUG_RSGXSNETTUNNEL - std::cerr << " dropping tunnels" << std::endl; -#endif - mTurtle->stopMonitoringTunnels(ginfo.hash); - } - } -} - -bool RsGxsNetTunnelService::saveList(bool& cleanup, std::list& save) -{ - RsGxsNetTunnelRandomBiasItem *it2 = new RsGxsNetTunnelRandomBiasItem() ; - - { - RS_STACK_MUTEX(mGxsNetTunnelMtx); - it2->mRandomBias = mRandomBias; - std::cerr << "Saving RsGxsNetTunnel random bias to disc" << std::endl; - } - - save.push_back(it2) ; - cleanup = true ; - - return true; -} - -bool RsGxsNetTunnelService::loadList(std::list &load) -{ - RsGxsNetTunnelRandomBiasItem *rbsi ; - - for(auto it(load.begin());it!=load.end();++it) - { - if((rbsi = dynamic_cast(*it))!=NULL) - { - RS_STACK_MUTEX(mGxsNetTunnelMtx); - mRandomBias = rbsi->mRandomBias; - - std::cerr << "Loaded RsGxsNetTunnel random bias from disc: " << RsUtil::BinToHex(mRandomBias.toByteArray(),mRandomBias.SIZE_IN_BYTES) << std::endl; - } - else - GXS_NET_TUNNEL_ERROR() << " unknown item in config file: type=" << std::hex << (*it)->PacketId() << std::dec << std::endl; - - delete *it; - } - - return true; -} - -RsSerialiser *RsGxsNetTunnelService::setupSerialiser() -{ - RsSerialiser *ser = new RsSerialiser ; - ser->addSerialType(new RsGxsNetTunnelSerializer) ; - - return ser ; -} - -//===========================================================================================================================================// -// Turtle Search system // -//===========================================================================================================================================// - -TurtleRequestId RsGxsNetTunnelService::turtleGroupRequest(const RsGxsGroupId& group_id,RsNetworkExchangeService *client_service) -{ - Sha1CheckSum hashed_group_id = RsDirUtil::sha1sum(group_id.toByteArray(),group_id.SIZE_IN_BYTES) ; - - GXS_NET_TUNNEL_DEBUG() << ": starting a turtle group request for grp \"" << group_id << "\" hashed to \"" << hashed_group_id << "\"" << std::endl; - - RsGxsNetTunnelTurtleSearchGroupRequestItem search_item ; - search_item.hashed_group_id = hashed_group_id ; - search_item.service = client_service->serviceType() ; - - uint32_t size = RsGxsNetTunnelSerializer().size(&search_item) ; - unsigned char *mem = (unsigned char*)rs_malloc(size) ; - - if(mem == NULL) - return 0 ; - - RsGxsNetTunnelSerializer().serialise(&search_item,mem,&size); - - return mTurtle->turtleSearch(mem,size,this) ; -} - -TurtleRequestId RsGxsNetTunnelService::turtleSearchRequest(const std::string& match_string,RsNetworkExchangeService *client_service) -{ - GXS_NET_TUNNEL_DEBUG() << ": starting a turtle search request for string \"" << match_string << "\"" << std::endl; - - RsGxsNetTunnelTurtleSearchSubstringItem search_item ; - search_item.substring_match = match_string ; - search_item.service = client_service->serviceType() ; - - uint32_t size = RsGxsNetTunnelSerializer().size(&search_item) ; - unsigned char *mem = (unsigned char*)rs_malloc(size) ; - - if(mem == NULL) - return 0 ; - - RsGxsNetTunnelSerializer().serialise(&search_item,mem,&size); - - RS_STACK_MUTEX(mGxsNetTunnelMtx); - return mTurtle->turtleSearch(mem,size,this) ; -} - -bool RsGxsNetTunnelService::receiveSearchRequest(unsigned char *search_request_data,uint32_t search_request_data_len,unsigned char *& search_result_data,uint32_t& search_result_data_size,uint32_t& max_allowed_hits) -{ - GXS_NET_TUNNEL_DEBUG() << ": received a request." << std::endl; - - RsItem *item = RsGxsNetTunnelSerializer().deserialise(search_request_data,&search_request_data_len) ; - - RsGxsNetTunnelTurtleSearchSubstringItem *substring_sr = dynamic_cast(item) ; - - if(substring_sr != NULL) - { - GXS_NET_TUNNEL_DEBUG() << " : type is substring for service " << std::hex << (int)substring_sr->service << std::dec << std::endl; - - max_allowed_hits = RS_GXS_NET_TUNNEL_MAX_ALLOWED_HITS_GROUP_SEARCH ; - - std::list results ; - - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - auto it = mSearchableServices.find(substring_sr->service) ; - - if(it != mSearchableServices.end() && it->second->search(substring_sr->substring_match,results)) - { - RsGxsNetTunnelTurtleSearchGroupSummaryItem search_result_item ; - - GXS_NET_TUNNEL_DEBUG() << " : " << results.size() << " result found. Sending back." << std::endl; - - search_result_item.service = substring_sr->service ; - search_result_item.group_infos = results ; - - search_result_data_size = RsGxsNetTunnelSerializer().size(&search_result_item) ; - search_result_data = (unsigned char*)rs_malloc(search_result_data_size) ; - - delete item; - - if(search_result_data == NULL) - return false ; - - RsGxsNetTunnelSerializer().serialise(&search_result_item,search_result_data,&search_result_data_size); - - return true ; - } - } - - RsGxsNetTunnelTurtleSearchGroupRequestItem *substring_gr = dynamic_cast(item) ; - - if(substring_gr != NULL) - { - RS_STACK_MUTEX(mGxsNetTunnelMtx); - auto it = mSearchableServices.find(substring_gr->service) ; - - max_allowed_hits = RS_GXS_NET_TUNNEL_MAX_ALLOWED_HITS_GROUP_DATA ; - - unsigned char *encrypted_group_data = NULL ; - uint32_t encrypted_group_data_len = 0 ; - - if(it != mSearchableServices.end() && it->second->search(substring_gr->hashed_group_id,encrypted_group_data,encrypted_group_data_len)) - { - RsGxsNetTunnelTurtleSearchGroupDataItem search_result_item ; - - search_result_item.service = substring_gr->service ; - search_result_item.encrypted_group_data = encrypted_group_data ; - search_result_item.encrypted_group_data_len = encrypted_group_data_len; - - search_result_data_size = RsGxsNetTunnelSerializer().size(&search_result_item) ; - search_result_data = (unsigned char*)rs_malloc(search_result_data_size) ; - - if(search_result_data == NULL) - return false ; - - RsGxsNetTunnelSerializer().serialise(&search_result_item,search_result_data,&search_result_data_size); - - delete item; - return true ; - } - } - - delete item; - return false ; -} - -void RsGxsNetTunnelService::receiveSearchResult(TurtleSearchRequestId request_id,unsigned char *search_result_data,uint32_t search_result_data_len) -{ - RsItem *item = RsGxsNetTunnelSerializer().deserialise(search_result_data,&search_result_data_len); - - GXS_NET_TUNNEL_DEBUG() << " : received search result for search request " << std::hex << request_id << "" << std::endl; - - RsGxsNetTunnelTurtleSearchGroupSummaryItem *result_gs = dynamic_cast(item) ; - - if(result_gs != NULL) - { - GXS_NET_TUNNEL_DEBUG() << " : result is of type group summary result for service " << result_gs->service << std::dec << ": " << std::endl; - -#ifdef DEBUG_RSGXSNETTUNNEL - for(auto it(result_gs->group_infos.begin());it!=result_gs->group_infos.end();++it) - std::cerr << " group " << (*it).mGroupId << ": " << (*it).mGroupName << ", " << (*it).mNumberOfMessages << " messages, last is " << time(NULL)-(*it).mLastMessageTs << " secs ago." << std::endl; -#endif - - auto it = mSearchableServices.find(result_gs->service) ; - - if(it == mSearchableServices.end()) - { - GXS_NET_TUNNEL_ERROR() << ": deserialized item is for service " << std::hex << result_gs->service << std::dec << " that is not in the searchable services list." << std::endl; - delete item; - return ; - } - - it->second->receiveTurtleSearchResults(request_id,result_gs->group_infos) ; - - delete item; - return ; - } - - RsGxsNetTunnelTurtleSearchGroupDataItem *result_gd = dynamic_cast(item) ; - - if(result_gd != NULL) - { - GXS_NET_TUNNEL_DEBUG() << " : result is of type group data for service " << result_gd->service << std::dec << ": " << std::endl; - - auto it = mSearchableServices.find(result_gd->service) ; - - if(it == mSearchableServices.end()) - { - GXS_NET_TUNNEL_ERROR() << ": deserialized item is for service " << std::hex << result_gd->service << std::dec << " that is not in the searchable services list." << std::endl; - delete item; - return ; - } - - it->second->receiveTurtleSearchResults(request_id,result_gd->encrypted_group_data,result_gd->encrypted_group_data_len) ; - - result_gd->encrypted_group_data = NULL ; // prevents deletion - delete item; - - return ; - } - - GXS_NET_TUNNEL_ERROR() << ": deserialized item is of unknown type. Dropping!" << std::endl; -} - -void RsGxsNetTunnelService::getStatistics(std::map& groups, std::map& virtual_peers, std::map &turtle_vpid_to_net_tunnel_vpid, Bias20Bytes& bias ) const -{ - groups = mGroups ; - virtual_peers = mVirtualPeers ; - turtle_vpid_to_net_tunnel_vpid = mTurtle2GxsPeer; - bias = mRandomBias ; -} - - - - - - - - - - - - - - - - - - - - diff --git a/libretroshare/src/gxs/rsgxsnettunnel.h b/libretroshare/src/gxs/rsgxsnettunnel.h deleted file mode 100644 index 7c18ab54c..000000000 --- a/libretroshare/src/gxs/rsgxsnettunnel.h +++ /dev/null @@ -1,274 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxsnettunnel.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -#pragma once - -#include - -#include "turtle/p3turtle.h" -#include "retroshare/rsgxsdistsync.h" - -/*! - * \brief The RsGxsNetTunnelService class takes care of requesting tunnels to the turtle router, through which it is possible to sync - * a particular GXS group. For each group, a set of virtual peers, corresponding to active tunnels will be made available - * to RsGxsNetService. - * - * It is the responsibility of RsGxsNetService to activate/desactivate tunnels for each particular group, depending on wether the group - * is already available at regular friends or not. - * - * Tunnel management is done at the level of groups rather than services, because we would like to keep the possibility to not - * request tunnels for some groups which do not need it, and only request tunnels for specific groups that cannot be provided - * by direct connections. - */ - -// Protocol: -// * request tunnels based on H(GroupId) -// * encrypt tunnel data using chacha20+HMAC-SHA256 using AEAD( GroupId, 96bits IV, tunnel ID ) (similar to what FT does) -// * when tunnel is established, exchange virtual peer names: vpid = H( GroupID | Random bias ) -// * when vpid is known, notify the client (GXS net service) which can use the virtual peer to sync -// * only use a single tunnel per virtual peer ID -// - -// Client ------------------ TR(H(GroupId)) --------------> Server | -// | Turtle -// Client <-------------------- T OK ---------------------- Server | -// - -// Here, a turtle vpid is known | [ addVirtualPeer() called by turtle ] -// - -// [Encrypted traffic using H(GroupId | Tunnel ID, 96bits IV)] | -// | -// Client <--------- VPID = H( Random IV | GroupId ) ------ Server | -// | | | -// +--------------> Mark the virtual peer active <-----------+ | Encrypted traffic decoded locally and sorted -// | -// Here, a consistent virtual peer ID is known | -// | -// Client <------------------- GXS Data ------------------> Server | -// - -// Notes: -// * tunnels are established symmetrically. If a distant peers wants to sync the same group, they'll have to open a single tunnel, with a different ID. -// Groups therefore have two states: -// - managed : the group can be used to answer tunnel requests. If server tunnels are established, the group will be synced with these peers -// - tunneled: the group will actively request tunnels. If tunnels are established both ways, the same virtual peers will be used so the tunnels are "merged". -// * In practice, that means one of the two tunnels will not be used and therefore die. -// * If a tunneled group already has enough virtual peers, it will not request for tunnels itself. -// -// Group policy | Request tunnels | SyncWithPeers | Item receipt -// --------------------+-------------------+-----------------------+---------------- -// Passive | no | If peers present | If peers present -// Active | yes, if no peers | If peers present | If peers present -// | | | -// -// * when a service has the DistSync flag set, groups to sync are communicated passively to the GxsNetTunnel service when requesting distant peers. -// However, a call should be made to set a particular group policy to "ACTIVE" for group that do not have peers and need some. -// -// * services also need to retrieve GXS data items that come out of tunnels. These will be available as (data,len) type, since they are not de-serialized. -// -// * GxsNetService stores data information (such as update maps) per peerId, so it makes sense to use the same PeerId for all groups of a given service -// Therefore, virtual peers are stored separately from groups, because each one can sync multiple groups. -// -// * virtual peers are also shared among services. This reduces the required amount of tunnels and tunnel requests to send. -// -// * tunnels for a given service may also be used by the net service of p3IdService in order to explicitely request missing GxsIds. -// So GxsNetTunnel somehow allows different services to use the same tunnel. However we make sure that this traffic is limited to only p3IdService. -// -// How do we know that a group needs distant sync? -// * look into GrpConfigMap for suppliers. Suppliers is cleared at load. -// * last_update_TS in GrpConfigMap is randomised so it cannot be used -// * we need a way to know that there's no suppliers for good reasons (not that we just started) -// -// Security -// * the question of sync-ing with distant anonymous peers is a bit tricky because these peers can try to generate fake requests or change which messages are available -// and there is no way to prevent it. We therefore rely on GXS data integrity system to prevent this to happen. -// - -class RsGxsNetTunnelItem ; -class RsNetworkExchangeService ; - -class RsGxsNetTunnelService: - public RsTurtleClientService, public RsTickingThread, public p3Config, - public RsGxsDistSync -{ -public: - RsGxsNetTunnelService() ; - virtual ~RsGxsNetTunnelService() ; - - /*! - * \brief registerSearchableService - * Adds the network exchange service as a possible search source. This is used to allow distant search on the corresponding - * GXS service. - * \return - * always returns true. - */ - bool registerSearchableService(RsNetworkExchangeService *) ; - - /*! - * \brief Manage tunnels for this group - * @param group_id group for which tunnels should be released - */ - bool requestDistantPeers(uint16_t service_id,const RsGxsGroupId&group_id) ; - - /*! - * \brief Stop managing tunnels for this group - * @param group_id group for which tunnels should be released - */ - bool releaseDistantPeers(uint16_t service_id, const RsGxsGroupId&group_id) ; - - /*! - * \brief Get the list of active virtual peers for a given group. This implies that a tunnel is up and - * alive. This function also "registers" the group which allows to handle tunnel requests in the server side. - */ - bool getVirtualPeers(std::list& peers) ; // returns the virtual peers for this service - - /*! - * \brief serviceId - * Overloads the method in RsTurtleClientService. - * \return - * The service id for RsGxsNetTunnel. - */ - uint16_t serviceId() const ; - - /*! - * \brief sendData - * send data to this virtual peer, and takes memory ownership (deletes the item) - * \param item item to send - * \param virtual_peer destination virtual peer - * \return - * true if succeeded. - */ - bool sendTunnelData(uint16_t service_id,unsigned char *& data, uint32_t data_len, const RsGxsNetTunnelVirtualPeerId& virtual_peer) ; - - /*! - * \brief receiveData - * returns the next piece of data received, and the virtual GXS peer that sended it. - * \param data memory check containing the data. Memory ownership belongs to the client. - * \param data_len length of memory chunk - * \param virtual_peer peer who sent the data - * \return - * true if something is returned. If not, data is set to NULL, data_len to 0. - */ - bool receiveTunnelData(uint16_t service_id, unsigned char *& data, uint32_t& data_len, RsGxsNetTunnelVirtualPeerId& virtual_peer) ; - - /*! - * \brief isDistantPeer - * returns wether the peer is in the list of available distant peers or not - * \param group_id returned by the service to indicate which group this peer id is designed for. - * \return true if the peer is a distant GXS peer. - */ - - bool isDistantPeer(const RsGxsNetTunnelVirtualPeerId& virtual_peer,RsGxsGroupId& group_id) ; - - /*! - * \brief dumps all information about monitored groups. - */ - void dump() const; - - /*! - * \brief connectToTurtleRouter - * Should be called after allocating a RsGxsNetTunnelService - * \param tr turtle router object - */ - virtual void connectToTurtleRouter(p3turtle *tr) ; - - TurtleRequestId turtleGroupRequest(const RsGxsGroupId& group_id, RsNetworkExchangeService *client_service) ; - TurtleRequestId turtleSearchRequest(const std::string& match_string,RsNetworkExchangeService *client_service) ; - - /*! - * \brief receiveSearchRequest - * See RsTurtleClientService::@ - */ - virtual bool receiveSearchRequest(unsigned char *search_request_data, uint32_t search_request_data_len, unsigned char *& search_result_data, uint32_t& search_result_data_len, uint32_t &max_allowed_hits); - virtual void receiveSearchResult(TurtleSearchRequestId request_id,unsigned char *search_result_data,uint32_t search_result_data_len); - - void threadTick() override; /// @see RsTickingThread - - // Overloads p3Config - - RsSerialiser *setupSerialiser(); - bool saveList(bool& cleanup, std::list& save); - bool loadList(std::list &load); - - // Overloads RsGxsDistSync - - void getStatistics(std::map& groups, // groups on the client and server side - std::map& virtual_peers, // current virtual peers, which group they provide, and how to talk to them through turtle - std::map& turtle_vpid_to_net_tunnel_vpid, - Bias20Bytes& bias) const; - -protected: - // interaction with turtle router - - virtual bool handleTunnelRequest(const RsFileHash &hash,const RsPeerId& peer_id) ; - virtual void receiveTurtleData(const RsTurtleGenericTunnelItem *item,const RsFileHash& hash,const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ; - void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ; - void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ; - const Bias20Bytes& locked_randomBias() ; - - p3turtle *mTurtle ; - - static const uint32_t RS_GXS_TUNNEL_CONST_RANDOM_BIAS_SIZE = 20 ; - static const uint32_t RS_GXS_TUNNEL_CONST_EKEY_SIZE = 32 ; - - mutable Bias20Bytes mRandomBias ; // constant accross reboots. Allows to disguise the real SSL id while providing a consistent value accross time. -private: - void autowash() ; - void sendKeepAlivePackets() ; - void handleIncoming(RsGxsNetTunnelItem *item) ; - void flush_pending_items(); - - std::map mGroups ; // groups on the client and server side - - std::map mVirtualPeers ; // current virtual peers, which group they provide, and how to talk to them through turtle - std::map mHandledHashes ; // hashes asked to turtle. Used to answer tunnel requests - std::map mTurtle2GxsPeer ; // convertion table to find GXS peer id from turtle - - std::list > mPendingTurtleItems ; // items that need to be sent off-turtle Mutex. - - std::map > > mIncomingData; // list of incoming data items - - std::map mSearchableServices ; - - /*! - * \brief Generates the hash to request tunnels for this group. This hash is only used by turtle, and is used to - * hide the real group id. - */ - - RsFileHash calculateGroupHash(const RsGxsGroupId&group_id) const ; - - /*! - * \brief makeVirtualPeerIdForGroup creates a virtual peer id that can be used and that will be constant accross time, whatever the - * tunnel ID and turtle virtual peer id. This allows RsGxsNetService to keep sync-ing the data consistently. - */ - - RsGxsNetTunnelVirtualPeerId locked_makeVirtualPeerId(const RsGxsGroupId& group_id) ; - - static void generateEncryptionKey(const RsGxsGroupId& group_id,const TurtleVirtualPeerId& vpid,unsigned char key[RS_GXS_TUNNEL_CONST_EKEY_SIZE]) ; - - mutable RsMutex mGxsNetTunnelMtx; - - friend class RsGxsTunnelRandomBiasItem ; - friend class StoreHere ; - - rstime_t mLastKeepAlive ; - rstime_t mLastAutoWash ; - rstime_t mLastDump ; -}; - diff --git a/libretroshare/src/gxs/rsgxsnetutils.cc b/libretroshare/src/gxs/rsgxsnetutils.cc deleted file mode 100644 index b74abcb0f..000000000 --- a/libretroshare/src/gxs/rsgxsnetutils.cc +++ /dev/null @@ -1,319 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsnetutils.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 by Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "rsgxsnetutils.h" -#include "pqi/p3servicecontrol.h" -#include "pgp/pgpauxutils.h" - - const rstime_t AuthorPending::EXPIRY_PERIOD_OFFSET = 30; // 30 seconds - const int AuthorPending::MSG_PEND = 1; - const int AuthorPending::GRP_PEND = 2; - -AuthorPending::AuthorPending(RsGixsReputation* rep, rstime_t timeStamp) : mRep(rep), mTimeStamp(timeStamp) {} - -AuthorPending::~AuthorPending() {} - -bool AuthorPending::expired() const -{ - return time(NULL) > (mTimeStamp + EXPIRY_PERIOD_OFFSET); -} - -bool AuthorPending::getAuthorRep(GixsReputation& rep, const RsGxsId& authorId, const RsPeerId& /*peerId*/) -{ - rep.id = authorId ; - rep.reputation_level = - static_cast(mRep->overallReputationLevel(authorId)); - -#warning csoler 2017-01-10: Can it happen that reputations do not have the info yet? - return true ; -#ifdef TO_BE_REMOVED - { - return mRep->getReputation(authorId, rep); - } - - std::list peers; - peers.push_back(peerId); - mRep->loadReputation(authorId, peers); - return false; -#endif -} - -MsgAuthEntry::MsgAuthEntry() - : mPassedVetting(false) {} - - -GrpAuthEntry::GrpAuthEntry() - : mPassedVetting(false) {} - - - -MsgRespPending::MsgRespPending(RsGixsReputation* rep, const RsPeerId& peerId, const MsgAuthorV& msgAuthV, int cutOff) - : AuthorPending(rep, time(NULL)), mPeerId(peerId), mMsgAuthV(msgAuthV), mCutOff(cutOff) -{ -} - -GrpRespPending::GrpRespPending(RsGixsReputation* rep, const RsPeerId& peerId, const GrpAuthorV& grpAuthV, int cutOff) - : AuthorPending(rep, time(NULL)), mPeerId(peerId), mGrpAuthV(grpAuthV), mCutOff(cutOff) -{ -} - -int MsgRespPending::getType() const -{ - return MSG_PEND; -} - -bool MsgRespPending::accepted() -{ - MsgAuthorV::iterator cit = mMsgAuthV.begin(); - MsgAuthorV::size_type count = 0; - for(; cit != mMsgAuthV.end(); ++cit) - { - MsgAuthEntry& entry = *cit; - - if(!entry.mPassedVetting) - { - GixsReputation rep; - if(getAuthorRep(rep, entry.mAuthorId, mPeerId)) - { - if(rep.reputation_level >= (uint32_t)mCutOff) - { - entry.mPassedVetting = true; - count++; - } - } - - }else - { - count++; - } - } - - return count == mMsgAuthV.size(); -} - -int GrpRespPending::getType() const -{ - return GRP_PEND; -} - -bool GrpRespPending::accepted() -{ - GrpAuthorV::iterator cit = mGrpAuthV.begin(); - GrpAuthorV::size_type count = 0; - for(; cit != mGrpAuthV.end(); ++cit) - { - GrpAuthEntry& entry = *cit; - - if(!entry.mPassedVetting) - { - GixsReputation rep; - - if(getAuthorRep(rep, entry.mAuthorId, mPeerId)) - { - if(rep.reputation_level >= (uint32_t)mCutOff) - { - entry.mPassedVetting = true; - count++; - } - } - - }else - { - count++; - } - } - - return count == mGrpAuthV.size(); -} - - - -/** NxsTransaction definition **/ - -const uint8_t NxsTransaction::FLAG_STATE_STARTING = 0x0001; // when -const uint8_t NxsTransaction::FLAG_STATE_RECEIVING = 0x0002; // begin receiving items for incoming trans -const uint8_t NxsTransaction::FLAG_STATE_SENDING = 0x0004; // begin sending items for outgoing trans -const uint8_t NxsTransaction::FLAG_STATE_FAILED = 0x0010; -const uint8_t NxsTransaction::FLAG_STATE_WAITING_CONFIRM = 0x0020; -const uint8_t NxsTransaction::FLAG_STATE_COMPLETED = 0x0080; // originaly 0x008, but probably a typo, but we cannot change it since it would break backward compatibility. - - -NxsTransaction::NxsTransaction() - : mFlag(0), mTimeOut(0), mTransaction(NULL) { - -} - -NxsTransaction::~NxsTransaction(){ - - std::list::iterator lit = mItems.begin(); - - for(; lit != mItems.end(); ++lit) - { - delete *lit; - *lit = NULL; - } - - if(mTransaction) - delete mTransaction; - - mTransaction = NULL; -} - - -/* Net Manager */ - -RsNxsNetMgrImpl::RsNxsNetMgrImpl(p3ServiceControl *sc) - : mServiceCtrl(sc) -{ - -} - - -const RsPeerId& RsNxsNetMgrImpl::getOwnId() -{ - return mServiceCtrl->getOwnId(); -} - -void RsNxsNetMgrImpl::getOnlineList(const uint32_t serviceId, std::set &ssl_peers) -{ - mServiceCtrl->getPeersConnected(serviceId, ssl_peers); -} - -const rstime_t GrpCircleVetting::EXPIRY_PERIOD_OFFSET = 5; // 10 seconds -const int GrpCircleVetting::GRP_ID_PEND = 1; -const int GrpCircleVetting::GRP_ITEM_PEND = 2; -const int GrpCircleVetting::MSG_ID_SEND_PEND = 3; -const int GrpCircleVetting::MSG_ID_RECV_PEND = 3; - - -GrpIdCircleVet::GrpIdCircleVet(const RsGxsGroupId& grpId, const RsGxsCircleId& circleId, const RsGxsId& authId) - : mGroupId(grpId), mCircleId(circleId), mAuthorId(authId), mCleared(false) {} - -GrpCircleVetting::GrpCircleVetting(RsGcxs* const circles, PgpAuxUtils *pgpUtils) - : mCircles(circles), mPgpUtils(pgpUtils), mTimeStamp(time(NULL)) {} - -GrpCircleVetting::~GrpCircleVetting() {} - -bool GrpCircleVetting::expired() -{ - return time(NULL) > (mTimeStamp + EXPIRY_PERIOD_OFFSET); -} -bool GrpCircleVetting::canSend( - const RsPeerId& peerId, const RsGxsCircleId& circleId, - bool& should_encrypt ) -{ - if(mCircles->isLoaded(circleId)) - { - const RsPgpId& pgpId = mPgpUtils->getPGPId(peerId); - return mCircles->canSend(circleId, pgpId,should_encrypt); - } - - mCircles->loadCircle(circleId); - - return false; -} - -GrpCircleIdRequestVetting::GrpCircleIdRequestVetting( - RsGcxs* const circles, - PgpAuxUtils *pgpUtils, - std::vector grpCircleV, const RsPeerId& peerId) - : GrpCircleVetting(circles, pgpUtils), mGrpCircleV(grpCircleV), mPeerId(peerId) {} - -bool GrpCircleIdRequestVetting::cleared() -{ - std::vector::size_type i, count=0; - for(i = 0; i < mGrpCircleV.size(); ++i) - { - GrpIdCircleVet& gic = mGrpCircleV[i]; - - if(!gic.mCleared) - { - if(canSend(mPeerId, gic.mCircleId,gic.mShouldEncrypt)) - { - gic.mCleared = true; - count++; - } - } - else - { - count++; - } - - } - - return count == mGrpCircleV.size(); -} - -int GrpCircleIdRequestVetting::getType() const -{ - return GRP_ID_PEND; -} - -MsgIdCircleVet::MsgIdCircleVet(const RsGxsMessageId& msgId, - const RsGxsId& authorId) - : mMsgId(msgId), mAuthorId(authorId) { -} - -MsgCircleIdsRequestVetting::MsgCircleIdsRequestVetting(RsGcxs* const circles, - PgpAuxUtils *pgpUtils, - std::vector msgs, const RsGxsGroupId& grpId, - const RsPeerId& peerId, const RsGxsCircleId& circleId) -: GrpCircleVetting(circles, pgpUtils), mMsgs(msgs), mGrpId(grpId), mPeerId(peerId), mCircleId(circleId) {} - -bool MsgCircleIdsRequestVetting::cleared() -{ - if(!mCircles->isLoaded(mCircleId)) - { - mCircles->loadCircle(mCircleId); - return false ; - } - - uint32_t filtered_out_msgs=0; - - for(uint32_t i=0;iisRecipient(mCircleId,mGrpId,mMsgs[i].mAuthorId)) - { - ++filtered_out_msgs; - mMsgs[i] = mMsgs[mMsgs.size()-1] ; - mMsgs.pop_back(); - } - else - ++i ; - - if(filtered_out_msgs>0) - std::cerr << "(WW) " << filtered_out_msgs << " messages not sent because they are signed by author(s) not member of that circle " << mCircleId << std::endl; - - RsPgpId pgpId = mPgpUtils->getPGPId(mPeerId); - bool can_send_res = mCircles->canSend(mCircleId, pgpId,mShouldEncrypt); - - if(mShouldEncrypt) // that means the circle is external - return true ; - else - return can_send_res ; -} - -int MsgCircleIdsRequestVetting::getType() const -{ - return MSG_ID_SEND_PEND; -} - - diff --git a/libretroshare/src/gxs/rsgxsnetutils.h b/libretroshare/src/gxs/rsgxsnetutils.h deleted file mode 100644 index 2ed229de0..000000000 --- a/libretroshare/src/gxs/rsgxsnetutils.h +++ /dev/null @@ -1,290 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsnetutils.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 by Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef RSGXSNETUTILS_H_ -#define RSGXSNETUTILS_H_ - -#include -#include "retroshare/rsgxsifacetypes.h" -#include "rsitems/rsnxsitems.h" -#include "rsgixs.h" - -class p3ServiceControl; -class PgpAuxUtils; - -/*! - * This represents a transaction made - * with the NxsNetService in all states - * of operation until completion - * - */ -class NxsTransaction -{ - -public: - - static const uint8_t FLAG_STATE_STARTING; // when - static const uint8_t FLAG_STATE_RECEIVING; // begin receiving items for incoming trans - static const uint8_t FLAG_STATE_SENDING; // begin sending items for outgoing trans - static const uint8_t FLAG_STATE_COMPLETED; - static const uint8_t FLAG_STATE_FAILED; - static const uint8_t FLAG_STATE_WAITING_CONFIRM; - - NxsTransaction(); - ~NxsTransaction(); - - uint32_t mFlag; // current state of transaction - uint32_t mTimeOut; - - /*! - * this contains who we - * c what peer this transaction involves. - * c The type of transaction - * c transaction id - * c timeout set for this transaction - * c and itemCount - */ - RsNxsTransacItem* mTransaction; - std::list mItems; // items received or sent -}; - -/*! - * An abstraction of the net manager - * for retrieving Rs peers whom you will be synchronising - * and also you own Id - * Useful for testing also (abstracts away Rs's p3NetMgr) - */ -class RsNxsNetMgr -{ - -public: - - virtual ~RsNxsNetMgr(){}; - virtual const RsPeerId& getOwnId() = 0; - virtual void getOnlineList(const uint32_t serviceId, std::set& ssl_peers) = 0; - -}; - -class RsNxsNetMgrImpl : public RsNxsNetMgr -{ - -public: - - RsNxsNetMgrImpl(p3ServiceControl* sc); - virtual ~RsNxsNetMgrImpl(){}; - - virtual const RsPeerId& getOwnId(); - virtual void getOnlineList(const uint32_t serviceId, std::set& ssl_peers); - -private: - - // No need for mutex as this is constant in the class. - p3ServiceControl* mServiceCtrl; - -}; - -/*! - * Partial abstract class - * which represents - * items waiting to be vetted - * on account of their author Id - */ -class AuthorPending -{ -public: - - static const int MSG_PEND; - static const int GRP_PEND; - static const rstime_t EXPIRY_PERIOD_OFFSET; - - AuthorPending(RsGixsReputation* rep, rstime_t timeStamp); - virtual ~AuthorPending(); - virtual int getType() const = 0 ; - - /*! - * @return true if all authors pass vetting and their messages - * should be requested - */ - virtual bool accepted() = 0; - - /*! - * @return true if message is past set expiry date - */ - bool expired() const; - -protected: - - /*! - * Convenience function to get author reputation - * @param rep reputation of author - * @param authorId reputation to get - * @return true if successfully retrieve repution - */ - bool getAuthorRep(GixsReputation& rep, const RsGxsId& authorId, const RsPeerId& peerId); - -private: - - RsGixsReputation* mRep; - rstime_t mTimeStamp; -}; - -class MsgAuthEntry -{ - -public: - - MsgAuthEntry(); - - RsGxsMessageId mMsgId; - RsGxsGroupId mGrpId; - RsGxsId mAuthorId; - bool mPassedVetting; - -}; - -class GrpAuthEntry -{ - -public: - - GrpAuthEntry(); - - RsGxsGroupId mGrpId; - RsGxsId mAuthorId; - bool mPassedVetting; -}; - -typedef std::vector MsgAuthorV; -typedef std::vector GrpAuthorV; - -class MsgRespPending : public AuthorPending -{ -public: - - MsgRespPending(RsGixsReputation* rep, const RsPeerId& peerId, const MsgAuthorV& msgAuthV, int cutOff = 0); - - int getType() const; - bool accepted(); - RsPeerId mPeerId; - MsgAuthorV mMsgAuthV; - int mCutOff; -}; - -class GrpRespPending : public AuthorPending -{ -public: - - GrpRespPending(RsGixsReputation* rep, const RsPeerId& peerId, const GrpAuthorV& grpAuthV, int cutOff = 0); - int getType() const; - bool accepted(); - RsPeerId mPeerId; - GrpAuthorV mGrpAuthV; - int mCutOff; -}; - - -/////////////// - -class GrpIdCircleVet -{ -public: - GrpIdCircleVet(const RsGxsGroupId& grpId, const RsGxsCircleId& circleId, const RsGxsId& authId); - RsGxsGroupId mGroupId; - RsGxsCircleId mCircleId; - RsGxsId mAuthorId; - - bool mCleared; - bool mShouldEncrypt; -}; - -class MsgIdCircleVet -{ -public: - MsgIdCircleVet(const RsGxsMessageId& grpId, const RsGxsId& authorId); - - RsGxsMessageId mMsgId; - RsGxsId mAuthorId; -}; - -class GrpItemCircleVet -{ -public: - RsNxsGrp* grpItem; - RsGxsCircleId mCircleId; - bool mCleared; -}; - -class GrpCircleVetting -{ -public: - - static const rstime_t EXPIRY_PERIOD_OFFSET; - static const int GRP_ID_PEND; - static const int GRP_ITEM_PEND; - static const int MSG_ID_SEND_PEND; - static const int MSG_ID_RECV_PEND; - - - GrpCircleVetting(RsGcxs* const circles, PgpAuxUtils *pgpUtils); - virtual ~GrpCircleVetting(); - bool expired(); - virtual int getType() const = 0; - virtual bool cleared() = 0; - -protected: - bool canSend(const RsPeerId& peerId, const RsGxsCircleId& circleId, bool& should_encrypt); - - RsGcxs* const mCircles; - PgpAuxUtils *mPgpUtils; - rstime_t mTimeStamp; -}; - -class GrpCircleIdRequestVetting : public GrpCircleVetting -{ -public: - GrpCircleIdRequestVetting(RsGcxs* const circles, - PgpAuxUtils *pgpUtils, - std::vector mGrpCircleV, const RsPeerId& peerId); - bool cleared(); - int getType() const; - std::vector mGrpCircleV; - RsPeerId mPeerId; -}; - -class MsgCircleIdsRequestVetting : public GrpCircleVetting -{ -public: - MsgCircleIdsRequestVetting(RsGcxs* const circles, - PgpAuxUtils *auxUtils, - std::vector msgs, const RsGxsGroupId& grpId, - const RsPeerId& peerId, const RsGxsCircleId& circleId); - bool cleared(); - int getType() const; - std::vector mMsgs; - RsGxsGroupId mGrpId; - RsPeerId mPeerId; - RsGxsCircleId mCircleId; - bool mShouldEncrypt; -}; - - -#endif /* RSGXSNETUTILS_H_ */ diff --git a/libretroshare/src/gxs/rsgxsnotify.h b/libretroshare/src/gxs/rsgxsnotify.h deleted file mode 100644 index 990acfe84..000000000 --- a/libretroshare/src/gxs/rsgxsnotify.h +++ /dev/null @@ -1,99 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs/: rsgxsnotify.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ - -#pragma once - -/*! - * The aim of this class is to implement notifications internally to GXS, which are - * mostly used by RsGenExchange to send information to specific services. These services - * then interpret these changes and turn them into human-readable/processed service-specific changes. - */ - -#include "retroshare/rsids.h" - -class RsGxsNotify -{ -public: - RsGxsNotify(const RsGxsGroupId& gid): mGroupId(gid){} - virtual ~RsGxsNotify()=default; - - enum NotifyType - { - TYPE_UNKNOWN = 0x00, - TYPE_PUBLISHED = 0x01, - TYPE_RECEIVED_NEW = 0x02, - TYPE_PROCESSED = 0x03, - TYPE_RECEIVED_PUBLISHKEY = 0x04, - TYPE_RECEIVED_DISTANT_SEARCH_RESULTS = 0x05, - TYPE_STATISTICS_CHANGED = 0x06, - TYPE_UPDATED = 0x07, - TYPE_MESSAGE_DELETED = 0x08, - TYPE_GROUP_DELETED = 0x09, - TYPE_GROUP_SYNC_PARAMETERS_UPDATED = 0x0a, - }; - - virtual NotifyType getType() = 0; - - RsGxsGroupId mGroupId; // Group id of the group we're talking about. When the group is deleted, it's useful to know which group - // that was although there is no pointers to the actual group data anymore. -}; - -/*! - * Relevant to group changes - */ -class RsGxsGroupChange : public RsGxsNotify -{ -public: - RsGxsGroupChange(NotifyType type, const RsGxsGroupId& gid,bool metaChange) : RsGxsNotify(gid),mNewGroupItem(nullptr),mOldGroupItem(nullptr), mNotifyType(type), mMetaChange(metaChange) {} - virtual ~RsGxsGroupChange() override { delete mOldGroupItem; delete mNewGroupItem ; } - - NotifyType getType() override { return mNotifyType;} - bool metaChange() { return mMetaChange; } - - RsGxsGrpItem *mNewGroupItem; // Valid when a group has changed, or a new group is received. - RsGxsGrpItem *mOldGroupItem; // only valid when mNotifyType is TYPE_UPDATED - -protected: - NotifyType mNotifyType; - bool mMetaChange; -}; - -/*! - * Relevant to message changes - */ -class RsGxsMsgChange : public RsGxsNotify -{ -public: - RsGxsMsgChange(NotifyType type, const RsGxsGroupId& gid, const RsGxsMessageId& msg_id,bool metaChange) - : RsGxsNotify(gid), mMsgId(msg_id), mNewMsgItem(nullptr),NOTIFY_TYPE(type), mMetaChange(metaChange) {} - virtual ~RsGxsMsgChange() override { delete mNewMsgItem ; } - - RsGxsMessageId mMsgId; - RsGxsMsgItem *mNewMsgItem; - - NotifyType getType(){ return NOTIFY_TYPE;} - bool metaChange() { return mMetaChange; } -private: - const NotifyType NOTIFY_TYPE; - bool mMetaChange; -}; - diff --git a/libretroshare/src/gxs/rsgxsrequesttypes.cc b/libretroshare/src/gxs/rsgxsrequesttypes.cc deleted file mode 100644 index e10a4efc3..000000000 --- a/libretroshare/src/gxs/rsgxsrequesttypes.cc +++ /dev/null @@ -1,175 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsrequesttypes.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "rsgxsrequesttypes.h" -#include "util/rsstd.h" - -std::ostream& operator<<(std::ostream& o,const GxsRequest& g) -{ - return g.print(o); -} - - -std::ostream& GroupMetaReq::print(std::ostream& o) const -{ - o << "[Request type=GroupMeta groupIds (size=" << mGroupIds.size() << "): " ; - - if(!mGroupIds.empty()) - { - o << *mGroupIds.begin() ; - - if(mGroupIds.size() > 1) - o << " ..." ; - } - - o << "]" ; - - return o; -} -std::ostream& GroupIdReq::print(std::ostream& o) const -{ - return o << "[Request type=GroupIdReq" << "]" ; -} - -std::ostream& GroupSerializedDataReq::print(std::ostream& o) const -{ - return o << "[Request type=GroupSerializedData" << "]" ; -} - -std::ostream& GroupDataReq::print(std::ostream& o) const -{ - o << "[Request type=GroupDataReq groupIds (size=" << mGroupIds.size() << "): " ; - - if(!mGroupIds.empty()) - { - o << *mGroupIds.begin() ; - - if(mGroupIds.size() > 1) - o << " ..." ; - } - - o << "]" ; - - return o; -} - -std::ostream& MsgIdReq::print(std::ostream& o) const -{ - return o << "[Request type=MsgId" << "]" ; -} - -std::ostream& MsgMetaReq::print(std::ostream& o) const -{ - o << "[Request type=MsgMetaReq groups (size=" << mMsgIds.size() << "): " ; - - if(!mMsgIds.empty()) - { - o << mMsgIds.begin()->first << " (" << mMsgIds.begin()->second.size() << " messages)"; - - if(mMsgIds.size() > 1) - o << " ..." ; - } - - o << "]" ; - - return o; -} - -std::ostream& MsgDataReq::print(std::ostream& o) const -{ - o << "[Request type=MsgDataReq groups (size=" << mMsgIds.size() << "): " ; - - if(!mMsgIds.empty()) - { - o << mMsgIds.begin()->first << " (" << mMsgIds.begin()->second.size() << " messages)"; - - if(mMsgIds.size() > 1) - o << " ..." ; - } - - o << "]" ; - - return o; -} - -std::ostream& MsgRelatedInfoReq::print(std::ostream& o) const -{ - o << "[Request type=MsgRelatedInfo msgIds (size=" << mMsgIds.size() << "): " ; - - if(!mMsgIds.empty()) - { - o << mMsgIds.begin()->first ; - - if(mMsgIds.size() > 1) - o << " ..." ; - } - - o << "]" ; - - return o; -} - -std::ostream& GroupSetFlagReq::print(std::ostream& o) const -{ - return o << "[Request type=GroupFlagSet grpId=" << grpId << "]" ; -} - - - -std::ostream& ServiceStatisticRequest::print(std::ostream& o) const -{ - return o << "[Request type=ServiceStatistics" << "]" ; -} - -std::ostream& GroupStatisticRequest::print(std::ostream& o) const -{ - return o << "[Request type=GroupStatistics grpId=" << mGrpId << "]" ; -} - -GroupMetaReq::~GroupMetaReq() -{ - //rsstd::delete_all(mGroupMetaData.begin(), mGroupMetaData.end()); // now memory ownership is kept by the cache. - mGroupMetaData.clear(); -} - -GroupDataReq::~GroupDataReq() -{ - rsstd::delete_all(mGroupData.begin(), mGroupData.end()); -} - -MsgDataReq::~MsgDataReq() -{ - for (NxsMsgDataResult::iterator it = mMsgData.begin(); it != mMsgData.end(); ++it) { - rsstd::delete_all(it->second.begin(), it->second.end()); - } -} - -MsgRelatedInfoReq::~MsgRelatedInfoReq() -{ - for (NxsMsgRelatedDataResult::iterator dataIt = mMsgDataResult.begin(); dataIt != mMsgDataResult.end(); ++dataIt) - rsstd::delete_all(dataIt->second.begin(), dataIt->second.end()); -} -std::ostream& MessageSetFlagReq::print(std::ostream& o) const -{ - return o << "[Request type=MsgFlagSet" << "]" ; -} - diff --git a/libretroshare/src/gxs/rsgxsrequesttypes.h b/libretroshare/src/gxs/rsgxsrequesttypes.h deleted file mode 100644 index dd9ddb7cd..000000000 --- a/libretroshare/src/gxs/rsgxsrequesttypes.h +++ /dev/null @@ -1,176 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsrequesttypes.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSGXSREQUESTTYPES_H_ -#define RSGXSREQUESTTYPES_H_ - -#include "retroshare/rstokenservice.h" -#include "gxs/rsgds.h" -#include "util/rsdeprecate.h" - -struct GxsRequest -{ - GxsRequest() : - token(0), reqTime(0), clientAnswerType(0), reqType(0), - status(RsTokenService::FAILED) {} - virtual ~GxsRequest() {} - - uint32_t token; - uint32_t reqTime; - - uint32_t clientAnswerType; /// This is made available to the clients in order to keep track of why specific requests where sent.. - uint32_t reqType; - RsTokReqOptions Options; - - RsTokenService::GxsRequestStatus status; - - virtual std::ostream& print(std::ostream& o) const = 0; -}; - -std::ostream& operator<<(std::ostream& o,const GxsRequest& g); - -class GroupMetaReq : public GxsRequest -{ -public: - virtual ~GroupMetaReq(); - - virtual std::ostream& print(std::ostream& o) const override; -public: - std::list mGroupIds; - std::list > mGroupMetaData; -}; - -class GroupIdReq : public GxsRequest -{ -public: - virtual std::ostream& print(std::ostream& o) const override ; - - std::list mGroupIds; - std::list mGroupIdResult; -}; -class GroupSerializedDataReq : public GxsRequest -{ -public: - virtual std::ostream& print(std::ostream& o) const override ; - - std::list mGroupIds; - std::list mGroupData; -}; - -class GroupDataReq : public GxsRequest -{ -public: - virtual ~GroupDataReq(); - - virtual std::ostream& print(std::ostream& o) const override; -public: - std::list mGroupIds; - std::list mGroupData; -}; - -class MsgIdReq : public GxsRequest -{ -public: - virtual std::ostream& print(std::ostream& o) const override ; - - GxsMsgReq mMsgIds; - GxsMsgIdResult mMsgIdResult; -}; - -class MsgMetaReq : public GxsRequest -{ -public: - virtual ~MsgMetaReq() = default; - - virtual std::ostream& print(std::ostream& o) const override; - -public: - GxsMsgReq mMsgIds; - GxsMsgMetaResult mMsgMetaData; -}; - -class MsgDataReq : public GxsRequest -{ -public: - virtual ~MsgDataReq(); - - virtual std::ostream& print(std::ostream& o) const override; -public: - GxsMsgReq mMsgIds; - NxsMsgDataResult mMsgData; -}; - -class ServiceStatisticRequest: public GxsRequest -{ -public: - virtual std::ostream& print(std::ostream& o) const override ; - GxsServiceStatistic mServiceStatistic; -}; - -struct GroupStatisticRequest: public GxsRequest -{ -public: - virtual std::ostream& print(std::ostream& o) const override ; - - RsGxsGroupId mGrpId; - GxsGroupStatistic mGroupStatistic; -}; - -class MsgRelatedInfoReq : public GxsRequest -{ -public: - virtual ~MsgRelatedInfoReq(); - - std::ostream& print(std::ostream& o) const override; -public: - std::vector mMsgIds; - MsgRelatedIdResult mMsgIdResult; - MsgRelatedMetaResult mMsgMetaResult; - NxsMsgRelatedDataResult mMsgDataResult; -}; - -class GroupSetFlagReq : public GxsRequest -{ -public: - virtual std::ostream& print(std::ostream& o) const override ; - - const static uint32_t FLAG_SUBSCRIBE; - const static uint32_t FLAG_STATUS; - - uint8_t type; - uint32_t flag; - uint32_t flagMask; - RsGxsGroupId grpId; -}; - -class MessageSetFlagReq : public GxsRequest -{ -public: - const static uint32_t FLAG_STATUS; - - virtual std::ostream& print(std::ostream& o) const override ; - uint8_t type; - uint32_t flag; - uint32_t flagMask; - RsGxsGrpMsgIdPair msgId; -}; - -#endif /* RSGXSREQUESTTYPES_H_ */ diff --git a/libretroshare/src/gxs/rsgxsutil.cc b/libretroshare/src/gxs/rsgxsutil.cc deleted file mode 100644 index f64fd236f..000000000 --- a/libretroshare/src/gxs/rsgxsutil.cc +++ /dev/null @@ -1,566 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsutil.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2013 by Christopher Evi-Parker * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#include "util/rstime.h" - -#include "rsgxsutil.h" -#include "retroshare/rsgxsflags.h" -#include "retroshare/rspeers.h" -#include "pqi/pqihash.h" -#include "gxs/rsgixs.h" - -#ifdef RS_DEEP_CHANNEL_INDEX -# include "deep_search/channelsindex.hpp" -# include "services/p3gxschannels.h" -# include "rsitems/rsgxschannelitems.h" -#endif - -// The goals of this set of methods is to check GXS messages and groups for consistency, mostly -// re-ferifying signatures and hashes, to make sure that the data hasn't been tempered. This shouldn't -// happen anyway, but we still conduct these test as an extra safety measure. - -static const uint32_t MAX_GXS_IDS_REQUESTS_NET = 10 ; // max number of requests from cache/net (avoids killing the system!) - -// #define DEBUG_GXSUTIL 1 - -#ifdef DEBUG_GXSUTIL -#define GXSUTIL_DEBUG() std::cerr << "[" << time(NULL) << "] : GXS_UTIL : " << __FUNCTION__ << " : " -#endif - -RsGxsCleanUp::RsGxsCleanUp(RsGeneralDataService* const dataService, RsGenExchange *genex, uint32_t chunkSize) -: mDs(dataService), mGenExchangeClient(genex), CHUNK_SIZE(chunkSize) -{ -} - -bool RsGxsCleanUp::clean(RsGxsGroupId& next_group_to_check,std::vector& grps_to_delete,GxsMsgReq& messages_to_delete) -{ - RsGxsGrpMetaTemporaryMap grpMetaMap; - mDs->retrieveGxsGrpMetaData(grpMetaMap); - - rstime_t now = time(NULL); - -#ifdef DEBUG_GXSUTIL - uint16_t service_type = mGenExchangeClient->serviceType() ; - GXSUTIL_DEBUG() << " Cleaning up groups in service " << std::hex << service_type << std::dec << " starting at group " << next_group_to_check << std::endl; -#endif - // This method stores/takes the next group to check. This allows to limit group checking to a small part of the total groups - // in the situation where it takes too much time. So when arriving here, we must start again from where we left last time. - - if(grpMetaMap.empty()) // nothing to do. - { - next_group_to_check.clear(); - return true; - } - - auto it = next_group_to_check.isNull()?grpMetaMap.begin() : grpMetaMap.find(next_group_to_check); - - if(it == grpMetaMap.end()) // group wasn't found - it = grpMetaMap.begin(); - - bool full_round = false; // did we have the time to test all groups? - next_group_to_check = it->first; // covers the case where next_group_to_check is null or not found - - while(true) // check all groups, starting from the one indicated as parameter - { - const RsGxsGrpMetaData& grpMeta = *(it->second); - - // first check if we keep the group or not - - if(!mGenExchangeClient->service_checkIfGroupIsStillUsed(grpMeta)) - { -#ifdef DEBUG_GXSUTIL - std::cerr << " Scheduling group " << grpMeta.mGroupId << " for removal." << std::endl; -#endif - grps_to_delete.push_back(grpMeta.mGroupId); - } - else - { - const RsGxsGroupId& grpId = grpMeta.mGroupId; - GxsMsgReq req; - GxsMsgMetaResult result; - - req[grpId] = std::set(); - mDs->retrieveGxsMsgMetaData(req, result); - - GxsMsgMetaResult::iterator mit = result.begin(); - -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " Cleaning up group message for group ID " << grpId << std::endl; -#endif - uint32_t store_period = mGenExchangeClient->getStoragePeriod(grpId) ; - - for(; mit != result.end(); ++mit) - { - auto& metaV = mit->second; - - // First, make a map of which message have a child message. This allows to only delete messages that dont have child messages. - // A more accurate way to go would be to compute the time of the oldest message and possibly delete all the branch, but in the - // end the message tree will be deleted slice after slice, which should still be reasonnably fast. - // - std::set messages_with_kids ; - - for( uint32_t i=0;imParentId.isNull()) - messages_with_kids.insert(metaV[i]->mParentId) ; - - for( uint32_t i=0;imMsgId)!=messages_with_kids.end()); - - // check if expired - bool remove = store_period > 0 && ((meta->mPublishTs + store_period) < now) && !have_kids; - - // check client does not want the message kept regardless of age - remove &= !(meta->mMsgStatus & GXS_SERV::GXS_MSG_STATUS_KEEP_FOREVER); - - // if not subscribed remove messages (can optimise this really) - remove = remove || (grpMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED); - remove = remove || !(grpMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED); - -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " msg id " << meta->mMsgId << " in grp " << grpId << ": keep_flag=" << bool(meta->mMsgStatus & GXS_SERV::GXS_MSG_STATUS_KEEP_FOREVER) - << " subscribed: " << bool(grpMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) << " store_period: " << store_period - << " kids: " << have_kids << " now - meta->mPublishTs: " << now - meta->mPublishTs ; -#endif - - if( remove ) - { - messages_to_delete[grpId].insert(meta->mMsgId); -#ifdef DEBUG_GXSUTIL - std::cerr << " Scheduling for removal." << std::endl; -#endif - } -#ifdef DEBUG_GXSUTIL - else - std::cerr << std::endl; -#endif - //delete meta; - } - } - } - - ++it; - - if(it == grpMetaMap.end()) - it = grpMetaMap.begin(); - - // check if we looped already - - if(it->first == next_group_to_check) - { -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "Had the time to test all groups. Will start again at " << it->first << std::endl; -#endif - full_round = true; - break; - } - - // now check if we spent too much time on this already - - rstime_t tm = time(nullptr); - - //if(tm > now + 1) // we spent more than 1 sec on the job already - if(tm > now) // we spent more than 1 sec on the job already - { -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "Aborting cleanup because it took too much time already. Next group left to be " << it->first << std::endl; -#endif - next_group_to_check = it->first; - full_round = false; - break; - } - } - - return full_round; -} - -RsGxsIntegrityCheck::RsGxsIntegrityCheck( - RsGeneralDataService* const dataService, RsGenExchange* genex, - RsSerialType& - , RsGixs* gixs ) - : mDs(dataService), mGenExchangeClient(genex), - mDone(false), mIntegrityMutex("integrity"), mGixs(gixs) {} - -void RsGxsIntegrityCheck::run() -{ - std::vector grps_to_delete; - GxsMsgReq msgs_to_delete; - - check(mGenExchangeClient->serviceType(), mGixs, mDs); - - RS_STACK_MUTEX(mIntegrityMutex); - mDone = true; -} - -bool RsGxsIntegrityCheck::check(uint16_t service_type, RsGixs *mgixs, RsGeneralDataService *mds) -{ -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "Parsing all groups and messages MetaData in service " << std::hex << mds->serviceType() << std::endl; -#endif - // first take out all the groups - std::map > grp; - - mds->retrieveGxsGrpMetaData(grp); - - GxsMsgReq msgIds; - - std::map used_gxs_ids ; - std::set subscribed_groups ; - - // Check that message ids... - - for( auto git = grp.begin(); git != grp.end(); ++git ) - { - const auto& grpMeta = git->second; - - if (mds->retrieveMsgIds(grpMeta->mGroupId, msgIds[grpMeta->mGroupId]) == 1) - { - if(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) - { - subscribed_groups.insert(git->first); - - if(!grpMeta->mAuthorId.isNull()) - { -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "TimeStamping group authors' key ID " << grpMeta->mAuthorId << " in group ID " << grpMeta->mGroupId << std::endl; -#endif - if( rsReputations && rsReputations->overallReputationLevel( grpMeta->mAuthorId ) > RsReputationLevel::LOCALLY_NEGATIVE ) - used_gxs_ids.insert(std::make_pair(grpMeta->mAuthorId, RsIdentityUsage(RsServiceType(service_type), RsIdentityUsage::GROUP_AUTHOR_KEEP_ALIVE,grpMeta->mGroupId))); - } - } - } - else - msgIds.erase(msgIds.find(grpMeta->mGroupId)); // could not get them, so group is removed from list. - } - - // now messages - GxsMsgMetaResult msgMetas; - - mds->retrieveGxsMsgMetaData(msgIds, msgMetas); - - for(auto mit=msgMetas.begin(); mit != msgMetas.end(); ++mit) - { - const auto& msgM = mit->second; - - for(auto vit=msgM.begin(); vit != msgM.end(); ++vit) - { - const auto& meta = *vit; - - if (subscribed_groups.count(meta->mGroupId)) - if(!meta->mAuthorId.isNull()) - { -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "TimeStamping message authors' key ID " << meta->mAuthorId << " in message " << meta->mMsgId << ", group ID " << meta->mGroupId<< std::endl; -#endif - if( rsReputations && rsReputations->overallReputationLevel( meta->mAuthorId ) > RsReputationLevel::LOCALLY_NEGATIVE ) - used_gxs_ids.insert(std::make_pair(meta->mAuthorId,RsIdentityUsage(RsServiceType(service_type), - RsIdentityUsage::MESSAGE_AUTHOR_KEEP_ALIVE, - meta->mGroupId, - meta->mMsgId, - meta->mParentId, - meta->mThreadId))) ; - } - } - } - - { -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "At end of pass, this is the list used GXS ids: " << std::endl; - GXSUTIL_DEBUG() << " requesting them to GXS identity service to enforce loading." << std::endl; -#endif - - std::list connected_friends ; - rsPeers->getOnlineList(connected_friends) ; - - std::vector > gxs_ids ; - - for(std::map::const_iterator it(used_gxs_ids.begin());it!=used_gxs_ids.end();++it) - { - gxs_ids.push_back(*it) ; -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " " << it->first << std::endl; -#endif - } - uint32_t nb_requested_not_in_cache = 0; - -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " issuing random get on friends for non existing IDs" << std::endl; -#endif - - // now request a cache update for them, which triggers downloading from friends, if missing. - - for(;nb_requested_not_in_cachehaveKey(gxs_ids[n].first)) // checks if we have it already in the cache (conservative way to ensure that we atually have it) - { - mgixs->requestKey(gxs_ids[n].first,connected_friends,gxs_ids[n].second); - - ++nb_requested_not_in_cache ; -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " ... from cache/net" << std::endl; -#endif - } - else - { -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " ... already in cache" << std::endl; -#endif - } - mgixs->timeStampKey(gxs_ids[n].first,gxs_ids[n].second); - - gxs_ids[n] = gxs_ids[gxs_ids.size()-1] ; - gxs_ids.pop_back() ; - } -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " total actual cache requests: "<< nb_requested_not_in_cache << std::endl; -#endif - } - - return true; -} - -bool RsGxsSinglePassIntegrityCheck::check(uint16_t service_type, RsGixs *mgixs, RsGeneralDataService *mds -#ifdef RS_DEEP_CHANNEL_INDEX - , RsGenExchange* mGenExchangeClient, RsSerialType& mSerializer -#endif - , std::vector& grpsToDel, GxsMsgReq& msgsToDel) -{ -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "Parsing all groups and messages data in service " << std::hex << mds->serviceType() << " for integrity check. Could take a while..." << std::endl; -#endif -#ifdef RS_DEEP_CHANNEL_INDEX - bool isGxsChannels = mGenExchangeClient->serviceType() == RS_SERVICE_GXS_TYPE_CHANNELS; - std::set indexedGroups; -#endif - - // first take out all the groups - std::map grp; - mds->retrieveNxsGrps(grp, true); - GxsMsgReq msgIds; - GxsMsgReq grps; - - std::map used_gxs_ids ; - std::set subscribed_groups ; - - // compute hash and compare to stored value, if it fails then simply add it - // to list - for( std::map::iterator git = grp.begin(); git != grp.end(); ++git ) - { - RsNxsGrp* grp = git->second; - RsFileHash currHash; - pqihash pHash; - pHash.addData(grp->grp.bin_data, grp->grp.bin_len); - pHash.Complete(currHash); - - if(currHash == grp->metaData->mHash) - { - // Get all message ids of group, store them in msgIds, creating the grp entry at the same time. - - if (mds->retrieveMsgIds(grp->grpId, msgIds[grp->grpId]) == 1) - { - // store the group for retrieveNxsMsgs - grps[grp->grpId]; - - if(grp->metaData->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) - subscribed_groups.insert(git->first); - } - else - msgIds.erase(msgIds.find(grp->grpId)); // could not get them, so group is removed from list. - -#ifdef RS_DEEP_CHANNEL_INDEX - // This should be moved to p3gxschannels. It is really not the place for this here! - - if( isGxsChannels - && grp->metaData->mCircleType == GXS_CIRCLE_TYPE_PUBLIC - && grp->metaData->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED ) - { - RsGxsGrpMetaData meta; - meta.deserialise(grp->meta.bin_data, grp->meta.bin_len); - - uint32_t blz = grp->grp.bin_len; - RsItem* rIt = mSerializer.deserialise(grp->grp.bin_data, - &blz); - - if( RsGxsChannelGroupItem* cgIt = - dynamic_cast(rIt) ) - { - RsGxsChannelGroup cg; - cgIt->toChannelGroup(cg, false); - cg.mMeta = meta; - - indexedGroups.insert(grp->grpId); - DeepChannelsIndex::indexChannelGroup(cg); - } - else - { - std::cerr << __PRETTY_FUNCTION__ << " Group: " - << meta.mGroupId.toStdString() << " " - << meta.mGroupName - << " doesn't seems a channel, please " - << "report to developers" - << std::endl; - print_stacktrace(); - } - - delete rIt; - } -#endif // def RS_DEEP_CHANNEL_INDEX - } - else - { - std::cerr << __PRETTY_FUNCTION__ <<" (EE) deleting group " << grp->grpId << " with wrong hash or null/corrupted meta data. meta=" << grp->metaData << std::endl; - grpsToDel.push_back(grp->grpId); -#ifdef RS_DEEP_CHANNEL_INDEX - if(isGxsChannels) - DeepChannelsIndex::removeChannelFromIndex(grp->grpId); -#endif // def RS_DEEP_CHANNEL_INDEX - } - - delete grp; - } - - // now messages - GxsMsgResult msgs; - - mds->retrieveNxsMsgs(grps, msgs, true); - - // Check msg ids and messages. Go through all message IDs referred to by the db call - // and verify that the message belongs to the nxs msg data that was just retrieved. - - for(auto& msgIdsIt:msgIds) - { - const RsGxsGroupId& grpId = msgIdsIt.first; - std::set& msgIdV = msgIdsIt.second; - - std::set nxsMsgS; - std::vector& nxsMsgV = msgs[grpId]; - - // To make the search efficient, we first build a set of msgIds to search in. - // Set build and search are both O(n log(n)). - - for(auto& nxsMsg:nxsMsgV) - if(nxsMsg) - nxsMsgS.insert(nxsMsg->msgId); - - for (auto& msgId:msgIdV) - if(nxsMsgS.find(msgId) == nxsMsgS.end()) - { - msgsToDel[grpId].insert(msgId); -#ifdef RS_DEEP_CHANNEL_INDEX - if(isGxsChannels) - DeepChannelsIndex::removeChannelPostFromIndex(grpId, msgId); -#endif // def RS_DEEP_CHANNEL_INDEX - } - } - - for(auto mit = msgs.begin(); mit != msgs.end(); ++mit) - { - std::vector& msgV = mit->second; - std::vector::iterator vit = msgV.begin(); - - for(; vit != msgV.end(); ++vit) - { - RsNxsMsg* msg = *vit; - RsFileHash currHash; - pqihash pHash; - pHash.addData(msg->msg.bin_data, msg->msg.bin_len); - pHash.Complete(currHash); - - if(msg->metaData == NULL || currHash != msg->metaData->mHash) - { - std::cerr << __PRETTY_FUNCTION__ <<" (EE) deleting message " << msg->msgId << " in group " << msg->grpId << " with wrong hash or null/corrupted meta data. meta=" << (void*)msg->metaData << std::endl; - msgsToDel[msg->grpId].insert(msg->msgId); -#ifdef RS_DEEP_CHANNEL_INDEX - if(isGxsChannels) - DeepChannelsIndex::removeChannelPostFromIndex( - msg->grpId, msg->msgId ); -#endif // def RS_DEEP_CHANNEL_INDEX - } - else if (subscribed_groups.count(msg->metaData->mGroupId)) - { -#ifdef RS_DEEP_CHANNEL_INDEX - // This should be moved to p3gxschannels. It is really not the place for this here! - - if( isGxsChannels && indexedGroups.count(msg->metaData->mGroupId) ) - { - RsGxsMsgMetaData meta; - meta.deserialise(msg->meta.bin_data, &msg->meta.bin_len); - - uint32_t blz = msg->msg.bin_len; - RsItem* rIt = mSerializer.deserialise(msg->msg.bin_data, - &blz); - - if( RsGxsChannelPostItem* cgIt = - dynamic_cast(rIt) ) - { - RsGxsChannelPost cg; - cgIt->toChannelPost(cg, false); - cg.mMeta = meta; - - DeepChannelsIndex::indexChannelPost(cg); - } - else if(dynamic_cast(rIt)) {} - else if(dynamic_cast(rIt)) {} - else - { - std::cerr << __PRETTY_FUNCTION__ << " Message: " - << meta.mMsgId.toStdString() - << " in group: " - << meta.mGroupId.toStdString() << " " - << " doesn't seems a channel post, please " - << "report to developers" - << std::endl; - print_stacktrace(); - } - - delete rIt; - } -#endif // def RS_DEEP_CHANNEL_INDEX - } - - delete msg; - } - } - - return true; -} -bool RsGxsIntegrityCheck::isDone() -{ - RS_STACK_MUTEX(mIntegrityMutex); - return mDone; -} - -void RsGxsIntegrityCheck::getDeletedIds(std::vector& grpIds, GxsMsgReq& msgIds) -{ - RS_STACK_MUTEX(mIntegrityMutex); - grpIds = mDeletedGrps; - msgIds = mDeletedMsgs; -} - diff --git a/libretroshare/src/gxs/rsgxsutil.h b/libretroshare/src/gxs/rsgxsutil.h deleted file mode 100644 index 34f1b2baa..000000000 --- a/libretroshare/src/gxs/rsgxsutil.h +++ /dev/null @@ -1,256 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsutil.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2013 by Christopher Evi-Parker * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#pragma once - -#include -#include "rsitems/rsnxsitems.h" -#include "rsgds.h" - -class RsGixs ; -class RsGenExchange ; -class RsGeneralDataService ; - -// temporary holds a map of pointers to class T, and destroys all pointers on delete. - -class non_copiable -{ -public: - non_copiable() {} -private: - non_copiable& operator=(const non_copiable&) { return *this ;} - non_copiable(const non_copiable&) {} -}; - -template -class t_RsGxsGenericDataTemporaryMap: public std::map, public non_copiable -{ -public: - virtual ~t_RsGxsGenericDataTemporaryMap() - { - clear() ; - } - - virtual void clear() - { - for(typename t_RsGxsGenericDataTemporaryMap::iterator it = this->begin();it!=this->end();++it) - if(it->second != NULL) - delete it->second ; - - std::map::clear() ; - } -}; - -template -class t_RsGxsGenericDataTemporaryMapVector: public std::map >, public non_copiable -{ -public: - virtual ~t_RsGxsGenericDataTemporaryMapVector() - { - clear() ; - } - - virtual void clear() - { - for(typename t_RsGxsGenericDataTemporaryMapVector::iterator it = this->begin();it!=this->end();++it) - { - for(uint32_t i=0;isecond.size();++i) - delete it->second[i] ; - - it->second.clear(); - } - - std::map >::clear() ; - } -}; - -template -class t_RsGxsGenericDataTemporaryList: public std::list, public non_copiable -{ -public: - virtual ~t_RsGxsGenericDataTemporaryList() - { - clear() ; - } - - virtual void clear() - { - for(typename t_RsGxsGenericDataTemporaryList::iterator it = this->begin();it!=this->end();++it) - delete *it; - - std::list::clear() ; - } -}; - -typedef std::map > RsGxsGrpMetaTemporaryMap; // This map doesn't need to delete elements since it holds -typedef std::map > > RsGxsMsgMetaTemporaryMap; // shared_ptr's. - -typedef t_RsGxsGenericDataTemporaryMap RsNxsGrpDataTemporaryMap; -typedef t_RsGxsGenericDataTemporaryMapVector RsNxsMsgDataTemporaryMap ; - -typedef t_RsGxsGenericDataTemporaryList RsNxsGrpDataTemporaryList ; -typedef t_RsGxsGenericDataTemporaryList RsNxsMsgDataTemporaryList ; - -inline RsGxsGrpMsgIdPair getMsgIdPair(RsNxsMsg& msg) -{ - return RsGxsGrpMsgIdPair(std::make_pair(msg.grpId, msg.msgId)); -} - -inline RsGxsGrpMsgIdPair getMsgIdPair(RsGxsMsgItem& msg) -{ - return RsGxsGrpMsgIdPair(std::make_pair(msg.meta.mGroupId, msg.meta.mMsgId)); -} - -/*! - * Does message clean up based on individual group expirations first - * if avialable. If not then deletion s - */ -class RsGxsCleanUp -{ -public: - - /*! - * - * @param dataService - * @param mGroupTS - * @param chunkSize - * @param sleepPeriod - */ - RsGxsCleanUp(RsGeneralDataService* const dataService, RsGenExchange *genex, uint32_t chunkSize); - - /*! - * On construction this should be called to progress deletions - * Deletion will process by chunk size - * @return true if no more messages to delete, false otherwise - */ - bool clean(RsGxsGroupId& next_group_to_check,std::vector& grps_to_delete,GxsMsgReq& messages_to_delete); - -private: - - RsGeneralDataService* const mDs; - RsGenExchange *mGenExchangeClient; - uint32_t CHUNK_SIZE; -}; - -/*! - * Checks the integrity message and groups - * in rsDataService using computed hash - */ -class RsGxsIntegrityCheck : public RsThread -{ - - enum CheckState { CheckStart, CheckChecking }; - -public: - - - /*! - * - * @param dataService - * @param mGroupTS - * @param chunkSize - * @param sleepPeriod - */ - RsGxsIntegrityCheck(RsGeneralDataService* const dataService, - RsGenExchange *genex, RsSerialType&, - RsGixs *gixs); - - static bool check(uint16_t service_type, RsGixs *mgixs, RsGeneralDataService *mds); - bool isDone(); - - void run(); - - void getDeletedIds(std::vector &grpIds, GxsMsgReq &msgIds); - -private: - - RsGeneralDataService* const mDs; - RsGenExchange *mGenExchangeClient; - bool mDone; - RsMutex mIntegrityMutex; - std::vector mDeletedGrps; - GxsMsgReq mDeletedMsgs; - - RsGixs* mGixs; -}; - -/*! - * Checks the integrity message and groups - * in rsDataService using computed hash - */ -class RsGxsSinglePassIntegrityCheck -{ -public: - - /*! - * - * @param dataService - * @param mGroupTS - * @param chunkSize - * @param sleepPeriod - */ - static bool check(uint16_t service_type, RsGixs *mgixs, RsGeneralDataService *mds -#ifdef RS_DEEP_CHANNEL_INDEX - , RsGenExchange* mGenExchangeClient, RsSerialType& mSerializer -#endif - , std::vector& grpsToDel, GxsMsgReq& msgsToDel); -}; - -class GroupUpdate -{ -public: - GroupUpdate() : oldGrpMeta(NULL), newGrp(NULL), validUpdate(false) - {} - const RsGxsGrpMetaData* oldGrpMeta; - RsNxsGrp* newGrp; - bool validUpdate; -}; - -class GroupUpdatePublish -{ -public: - GroupUpdatePublish(RsGxsGrpItem* item, uint32_t token) - : grpItem(item), mToken(token) {} - RsGxsGrpItem* grpItem; - uint32_t mToken; -}; - -class GroupDeletePublish -{ -public: - GroupDeletePublish(const RsGxsGroupId& grpId, uint32_t token) - : mGroupId(grpId), mToken(token) {} - RsGxsGroupId mGroupId; - uint32_t mToken; -}; - - -class MsgDeletePublish -{ -public: - MsgDeletePublish(const GxsMsgReq& msgs, uint32_t token) - : mMsgs(msgs), mToken(token) {} - - GxsMsgReq mMsgs ; - uint32_t mToken; -}; diff --git a/libretroshare/src/gxs/rsnxs.h b/libretroshare/src/gxs/rsnxs.h deleted file mode 100644 index fb6238f92..000000000 --- a/libretroshare/src/gxs/rsnxs.h +++ /dev/null @@ -1,310 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsnxs.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * Copyright 2011-2011 by Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef RSGNP_H -#define RSGNP_H - -#include -#include -#include "util/rstime.h" -#include -#include -#include - -#include "services/p3service.h" -#include "retroshare/rsreputations.h" -#include "retroshare/rsidentity.h" -#include "retroshare/rsturtle.h" -#include "rsgds.h" - -/*! - * Retroshare General Network Exchange Service: \n - * Interface: - * - This provides a module to service peer's requests for GXS messages \n - * and also request GXS messages from other peers. \n - * - The general mode of operation is to sychronise all messages/grps between - * peers - * - * The interface is sparse as this service is mostly making the requests to other GXS components - * - * Groups: - * - As this is where exchanges occur between peers, this is also where group's relationships - * should get resolved as far as - * - Per implemented GXS there are a set of rules which will determine whether data is transferred - * between any set of groups - * - * 1 allow transfers to any group - * 2 transfers only between group - * - the also group matrix settings which is by default everyone can transfer to each other - */ - -class RsNetworkExchangeService -{ -public: - - RsNetworkExchangeService(){ return;} - virtual ~RsNetworkExchangeService() {} - - virtual uint16_t serviceType() const =0; - /*! - * Use this to set how far back synchronisation of messages should take place - * @param age in seconds the max age a sync/store item can to be allowed in a synchronisation - */ - virtual void setSyncAge(const RsGxsGroupId& id,uint32_t age_in_secs) =0; - virtual void setKeepAge(const RsGxsGroupId& id,uint32_t age_in_secs) =0; - - virtual uint32_t getSyncAge(const RsGxsGroupId& id) =0; - virtual uint32_t getKeepAge(const RsGxsGroupId& id) =0; - - virtual void setDefaultKeepAge(uint32_t t) =0; - virtual void setDefaultSyncAge(uint32_t t) =0; - - virtual uint32_t getDefaultSyncAge() =0; - virtual uint32_t getDefaultKeepAge() =0; - - virtual bool msgAutoSync() const =0; - virtual bool grpAutoSync() const =0; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// DISTANT SEARCH FUNCTIONS /// - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - /*! - * \brief turtleGroupRequest - * Requests a particular group meta data. The request protects the group ID. - * \param group_id - * \return - * returns the turtle request ID that might be associated to some results. - */ - virtual TurtleRequestId turtleGroupRequest(const RsGxsGroupId& group_id)=0; - - /*! - * \brief turtleSearchRequest - * Uses distant search to match the substring to the group meta data. - * \param match_string - * \return - * returns the turtle request ID that might be associated to some results. - */ - virtual TurtleRequestId turtleSearchRequest(const std::string& match_string)=0; - - /*! - * \brief receiveTurtleSearchResults - * Called by turtle (through RsGxsNetTunnel) when new results are received - * \param req Turtle search request ID associated with this result - * \param group_infos Group summary information for the groups returned by the search - */ - virtual void receiveTurtleSearchResults(TurtleRequestId req,const std::list& group_infos)=0; - - /*! - * \brief receiveTurtleSearchResults - * Called by turtle (through RsGxsNetTunnel) when new data is received - * \param req Turtle search request ID associated with this result - * \param encrypted_group_data Group data - */ - virtual void receiveTurtleSearchResults(TurtleRequestId req,const unsigned char *encrypted_group_data,uint32_t encrypted_group_data_len)=0; - - /*! - * \brief retrieveTurtleSearchResults - * To be used to retrieve the search results that have been notified (or not) - * \param req request that match the results to retrieve - * \param group_infos results to retrieve. - * \return - * false when the request is unknown. - */ - virtual bool retrieveDistantSearchResults(TurtleRequestId req, std::map &group_infos)=0; - /*! - * \brief getDistantSearchResults - * \param id - * \param group_infos - * \return - */ - virtual bool clearDistantSearchResults(const TurtleRequestId& id)=0; - virtual bool retrieveDistantGroupSummary(const RsGxsGroupId&,RsGxsGroupSearchResults&)=0; - - virtual bool search(const std::string& substring,std::list& group_infos) =0; - virtual bool search(const Sha1CheckSum& hashed_group_id,unsigned char *& encrypted_group_data,uint32_t& encrypted_group_data_len)=0; - - /*! - * \brief getDistantSearchStatus - * Request status of a possibly ongoing/finished search. If UNKNOWN is returned, it means that no - * such group is under request - * \return - */ - virtual DistantSearchGroupStatus getDistantSearchStatus(const RsGxsGroupId&) =0; - - /*! - * Initiates a search through the network - * This returns messages which contains the search terms set in RsGxsSearch - * @param search contains search terms of requested from service - * @param hops how far into friend tree for search - * @return search token that can be redeemed later, implementation should indicate how this should be used - */ - //virtual int searchMsgs(RsGxsSearch* search, uint8_t hops = 1, bool retrieve = 0) = 0; - - /*! - * Initiates a search of groups through the network which goes - * a given number of hops deep into your friend network - * @param search contains search term requested from service - * @param hops number of hops deep into peer network - * @return search token that can be redeemed later - */ - //virtual int searchGrps(RsGxsSearch* search, uint8_t hops = 1, bool retrieve = 0) = 0; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// DATA ACCESS FUNCTIONS /// - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - /*! - * pauses synchronisation of subscribed groups and request for group id - * from peers - * @param enabled set to false to disable pause, and true otherwise - */ - virtual void pauseSynchronisation(bool enabled) = 0; - - - /*! - * Request for this message is sent through to peers on your network - * and how many hops from them you've indicated - * @param msgId the messages to retrieve - * @return request token to be redeemed - */ - virtual int requestMsg(const RsGxsGrpMsgIdPair& msgId) = 0; - - /*! - * Request for this group is sent through to peers on your network - * and how many hops from them you've indicated - * @param enabled set to false to disable pause, and true otherwise - * @return request token to be redeemed - */ - virtual int requestGrp(const std::list& grpId, const RsPeerId& peerId) = 0; - - /*! - * returns some stats about this group related to the network visibility. - * For now, only one statistics: - * max_known_messages: max number of messages reported by a friend. This is used to display unsubscribed group content. - */ - virtual bool getGroupNetworkStats(const RsGxsGroupId& grpId,RsGroupNetworkStats& stats)=0; - - virtual void subscribeStatusChanged(const RsGxsGroupId& id,bool subscribed) =0; - - /*! - * Request for this group is sent through to peers on your network - * and how many hops from them you've indicated - */ - virtual int sharePublishKey(const RsGxsGroupId& grpId,const std::set& peers)=0 ; - - /*! - * \brief rejectMessage - * Tells the network exchange service to not download this message again, at least for some time (maybe 24h or more) - * in order to avoid cluttering the network pipe with copied of this rejected message. - * \param msgId - */ - virtual void rejectMessage(const RsGxsMessageId& msgId) =0; - - /*! - * \brief getGroupServerUpdateTS - * Returns the server update time stamp for that group. This is used for synchronisation of TS between - * various network exchange services, suhc as channels/circles or forums/circles - * \param gid group for that request - * \param tm time stamp computed - * \return false if the group is not found, true otherwise - */ - virtual bool getGroupServerUpdateTS(const RsGxsGroupId& gid,rstime_t& grp_server_update_TS,rstime_t& msg_server_update_TS) =0; - - /*! - * \brief stampMsgServerUpdateTS - * Updates the msgServerUpdateMap structure to time(NULL), so as to trigger sending msg lists to friends. - * This is needed when e.g. posting a new message to a group. - * \param gid the group to stamp in msgServerUpdateMap - * \return - */ - virtual bool stampMsgServerUpdateTS(const RsGxsGroupId& gid) =0; - - /*! - * \brief isDistantPeer - * \param pid peer that is a virtual peer provided by GxsNetTunnel - * \return - * true if the peer exists (adn therefore is online) - */ - virtual bool isDistantPeer(const RsPeerId& pid)=0; - - /*! - * \brief removeGroups - * Removes time stamp information from the list of groups. This allows to re-sync them if suppliers are present. - * \param groups list of groups to remove from the update maps - * \return true if nothing bad happens. - */ - virtual bool removeGroups(const std::list& groups)=0; - - /*! - * \brief minReputationForForwardingMessages - * Encodes the policy for sending/requesting messages depending on anti-spam settings. - * - * \param group_sign_flags Sign flags from the group meta data - * \param identity_flags Flags of the identity - * \return - */ - static RsReputationLevel minReputationForRequestingMessages( - uint32_t /* group_sign_flags */, uint32_t /* identity_flags */ ) - { - // We always request messages, except if the author identity is locally banned. - return RsReputationLevel::REMOTELY_NEGATIVE; - } - static RsReputationLevel minReputationForForwardingMessages( - uint32_t group_sign_flags, uint32_t identity_flags ) - { - // If anti-spam is enabled, do not send messages from authors with bad reputation. The policy is to only forward messages if the reputation of the author is at least - // equal to the minimal reputation in the table below (R=remotely, L=locally, P=positive, N=negative, O=neutral) : - // - // - // +----------------------------------------------------+ - // | Identity flags | - // +----------------------------------------------------+ - // | Anonymous Signed Signed+Known | - // +-------------+-----------+----------------------------------------------------+ - // | |NONE | O O O | - // | Forum flags |GPG_AUTHED | RP O O | - // | |GPG_KNOWN | RP RP O | - // +-------------+-----------+----------------------------------------------------+ - // - - if(identity_flags & RS_IDENTITY_FLAGS_PGP_KNOWN) - return RsReputationLevel::NEUTRAL; - else if(identity_flags & RS_IDENTITY_FLAGS_PGP_LINKED) - { - if(group_sign_flags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN) - return RsReputationLevel::REMOTELY_POSITIVE; - else - return RsReputationLevel::NEUTRAL; - } - else - { - if( (group_sign_flags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN) || (group_sign_flags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG)) - return RsReputationLevel::REMOTELY_POSITIVE; - else - return RsReputationLevel::NEUTRAL; - } - } -}; - -#endif // RSGNP_H diff --git a/libretroshare/src/gxs/rsnxsobserver.h b/libretroshare/src/gxs/rsnxsobserver.h deleted file mode 100644 index 2da5067a4..000000000 --- a/libretroshare/src/gxs/rsnxsobserver.h +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsobserver.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2012 by Robert Fernie, Evi-Parker Christopher * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSNXSOBSERVER_H -#define RSNXSOBSERVER_H - -#include -#include "rsitems/rsnxsitems.h" - -typedef uint32_t TurtleRequestId ; - -class RsNxsObserver -{ -public: - - RsNxsObserver() {} - - -public: - - /*! - * @param messages messages are deleted after function returns - */ - virtual void receiveNewMessages(const std::vector& messages) = 0; - - /*! - * @param groups groups are deleted after function returns - */ - virtual void receiveNewGroups(const std::vector& groups) = 0; - - /*! - * \brief receiveDistantSearchResults - * Called when new distant search result arrive. - * \param grpId - */ - virtual void receiveDistantSearchResults(TurtleRequestId /*id*/,const RsGxsGroupId& /*grpId*/) - { - std::cerr << __PRETTY_FUNCTION__ << ": not overloaded but still called. Nothing will happen." << std::endl; - } - - /*! - * @param grpId group id - */ - virtual void notifyReceivePublishKey(const RsGxsGroupId &grpId) = 0; - - /*! - * \brief notifyChangedGroupSyncParams - * \param caled when a group sync parameter is updated - */ - virtual void notifyChangedGroupSyncParams(const RsGxsGroupId &grpId) = 0; - /*! - * @param grpId group id - */ - virtual void notifyChangedGroupStats(const RsGxsGroupId &grpId) = 0; -}; - -#endif // RSNXSOBSERVER_H diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc deleted file mode 100644 index 354cf812f..000000000 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ /dev/null @@ -1,1405 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxstrans: p3gxstrans.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#include "util/rsdir.h" -#include "gxstrans/p3gxstrans.h" -#include "util/stacktrace.h" -#include "util/rsdebug.h" - -//#define DEBUG_GXSTRANS 1 - -typedef unsigned int uint; - -/*extern*/ RsGxsTrans* rsGxsTrans = nullptr; - -const uint32_t p3GxsTrans::MAX_DELAY_BETWEEN_CLEANUPS = 900; // every 15 mins. Could be less. - -p3GxsTrans::~p3GxsTrans() -{ - // (cyril) this cannot be called here! There's chances the thread that saves configs will be dead already! - //p3Config::saveConfiguration(); - - { - RS_STACK_MUTEX(mIngoingMutex); - for ( auto& kv : mIncomingQueue) delete kv.second; - } -} - -bool p3GxsTrans::getDataStatistics(GxsTransStatistics& stats) -{ - { - RS_STACK_MUTEX(mDataMutex); - stats.prefered_group_id = mPreferredGroupId; - } - stats.outgoing_records.clear(); - - { - RS_STACK_MUTEX(mOutgoingMutex); - - for ( auto it = mOutgoingQueue.begin(); it != mOutgoingQueue.end(); ++it) - { - const OutgoingRecord& pr(it->second); - - RsGxsTransOutgoingRecord rec ; - rec.status = pr.status ; - rec.send_TS = pr.sent_ts ; - rec.group_id = pr.group_id ; - rec.trans_id = pr.mailItem.mailId ; - rec.recipient = pr.recipient ; - rec.data_size = pr.mailData.size(); - rec.data_hash = RsDirUtil::sha1sum(pr.mailData.data(),pr.mailData.size()); - rec.client_service = pr.clientService ; - - stats.outgoing_records.push_back(rec) ; - } - } - - return true; -} - -bool p3GxsTrans::sendData( RsGxsTransId& mailId, - GxsTransSubServices service, - const RsGxsId& own_gxsid, const RsGxsId& recipient, - const uint8_t* data, uint32_t size, - RsGxsTransEncryptionMode cm ) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::sendEmail(...)" << std::endl; -#endif - - if(!mIdService.isOwnId(own_gxsid)) - { - std::cerr << "p3GxsTrans::sendEmail(...) isOwnId(own_gxsid) false!" - << std::endl; - return false; - } - - if(recipient.isNull()) - { - std::cerr << "p3GxsTrans::sendEmail(...) got invalid recipient" - << std::endl; - print_stacktrace(); - return false; - } - - OutgoingRecord pr( recipient, service, data, size ); - - pr.mailItem.clear(); - pr.author = own_gxsid; //pr.mailItem.meta.mAuthorId = own_gxsid; - pr.mailItem.cryptoType = cm; - pr.mailItem.mailId = RSRandom::random_u64(); - - { - RS_STACK_MUTEX(mOutgoingMutex); - mOutgoingQueue.insert(prMap::value_type(pr.mailItem.mailId, pr)); - } - - mailId = pr.mailItem.mailId; - - IndicateConfigChanged(); // This causes the saving of the message after all data has been filled in. - return true; -} - -bool p3GxsTrans::querySendStatus(RsGxsTransId mailId, GxsTransSendStatus& st) -{ - RS_STACK_MUTEX(mOutgoingMutex); - auto it = mOutgoingQueue.find(mailId); - if( it != mOutgoingQueue.end() ) - { - st = it->second.status; - return true; - } - return false; -} - -void p3GxsTrans::registerGxsTransClient( - GxsTransSubServices serviceType, GxsTransClient* service) -{ - RS_STACK_MUTEX(mServClientsMutex); - mServClients[serviceType] = service; -} - -void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::handleResponse(" << token << ", " << req_type << ", " << status << ")" << std::endl; -#endif - if (status != RsTokenService::COMPLETE) - return; //For now, only manage Complete request - - bool changed = false ; - - switch (req_type) - { - case GROUPS_LIST: - { -#ifdef DEBUG_GXSTRANS - std::cerr << " Reviewing available groups. " << std::endl; -#endif - std::vector groups; - getGroupData(token, groups); - - // First recompute the prefered group Id. - - { - RS_STACK_MUTEX(mDataMutex); - - for( auto grp : groups ) - { - locked_supersedePreferredGroup(grp->meta.mGroupId); - - if(RsGenExchange::getStoragePeriod(grp->meta.mGroupId) != GXS_STORAGE_PERIOD) - { - std::cerr << "(WW) forcing storage period in GxsTrans group " << grp->meta.mGroupId << " to " << GXS_STORAGE_PERIOD << " seconds. Value was " << RsGenExchange::getStoragePeriod(grp->meta.mGroupId) << std::endl; - - RsGenExchange::setStoragePeriod(grp->meta.mGroupId,GXS_STORAGE_PERIOD) ; - } - } - } - -#ifdef DEBUG_GXSTRANS - std::cerr << " computed preferred group id: " << mPreferredGroupId << std::endl; -#endif - for( auto grp : groups ) - { - /* For each group check if it is better candidate then - * preferredGroupId, if it is supplant it and subscribe if it is not - * subscribed yet. - * Otherwise if it has recent messages subscribe. - * If the group was already subscribed has no recent messages - * unsubscribe. - */ - - const RsGroupMetaData& meta = grp->meta; - bool subscribed = IS_GROUP_SUBSCRIBED(meta.mSubscribeFlags); - - // if mLastPost is 0, then the group is not subscribed, so it only has impact on shouldSubscribe. In any case, a group - // with no information shouldn't be subscribed, so the olderThen() test is still valid in the case mLastPost=0. - - bool old = olderThen( meta.mLastPost, UNUSED_GROUP_UNSUBSCRIBE_INTERVAL ); - uint32_t token; - - bool shouldSubscribe = false ; - bool shouldUnSubscribe = false ; - { - RS_STACK_MUTEX(mDataMutex); - - shouldSubscribe = (!subscribed) && ((!old)|| meta.mGroupId == mPreferredGroupId ); - shouldUnSubscribe = ( subscribed) && old && meta.mGroupId != mPreferredGroupId; - } - -#ifdef DEBUG_GXSTRANS - std::cout << " group " << grp->meta.mGroupId << ", subscribed: " << subscribed << " last post: " << meta.mLastPost << " should subscribe: "<< shouldSubscribe - << ", should unsubscribe: " << shouldUnSubscribe << std::endl; -#endif - if(shouldSubscribe) - RsGenExchange::subscribeToGroup(token, meta.mGroupId, true); - else if(shouldUnSubscribe) - RsGenExchange::subscribeToGroup(token, meta.mGroupId, false); - -#ifdef GXS_MAIL_GRP_DEBUG - char buff[30]; - struct tm* timeinfo; - timeinfo = localtime(&meta.mLastPost); - strftime(buff, sizeof(buff), "%Y %b %d %H:%M", timeinfo); - - std::cout << "p3GxsTrans::handleResponse(...) GROUPS_LIST " - << "meta.mGroupId: " << meta.mGroupId - << " meta.mLastPost: " << buff - << " subscribed: " << subscribed - << " old: " << old - << " shoudlSubscribe: " << shoudlSubscribe - << " shoudlUnSubscribe: " << shoudlUnSubscribe - << std::endl; -#endif // GXS_MAIL_GRP_DEBUG - - delete grp; - } - - bool have_preferred_group = false ; - - { - RS_STACK_MUTEX(mDataMutex); - have_preferred_group = !mPreferredGroupId.isNull(); - } - - if(!have_preferred_group) - { - /* This is true only at first run when we haven't received mail - * distribuition groups from friends */ - -#ifdef DEBUG_GXSTRANS - std::cerr << "p3GxsTrans::handleResponse(...) preferredGroupId.isNu" - << "ll() let's create a new group." << std::endl; -#endif - uint32_t token; - publishGroup(token, new RsGxsTransGroupItem()); - queueRequest(token, GROUP_CREATE); - } - - break; - } - case GROUP_CREATE: - { -#ifdef DEBUG_GXSTRANS - std::cerr << "p3GxsTrans::handleResponse(...) GROUP_CREATE" << std::endl; -#endif - RsGxsGroupId grpId; - acknowledgeTokenGrp(token, grpId); - - RS_STACK_MUTEX(mDataMutex); - locked_supersedePreferredGroup(grpId); - break; - } - case MAILS_UPDATE: - { -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::handleResponse(...) MAILS_UPDATE" << std::endl; -#endif - typedef std::map > GxsMsgDataMap; - GxsMsgDataMap gpMsgMap; - getMsgData(token, gpMsgMap); - for ( GxsMsgDataMap::iterator gIt = gpMsgMap.begin(); - gIt != gpMsgMap.end(); ++gIt ) - { - typedef std::vector vT; - vT& mv(gIt->second); - for( vT::const_iterator mIt = mv.begin(); mIt != mv.end(); ++mIt ) - { - RsGxsMsgItem* gIt = *mIt; - switch(static_cast(gIt->PacketSubType())) - { - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: - { - RsGxsTransBaseMsgItem* mb = dynamic_cast(*mIt); - - if(mb) - { - RS_STACK_MUTEX(mIngoingMutex); - mIncomingQueue.insert(inMap::value_type(mb->mailId,mb)); - - changed = true ; - } - else - std::cerr << "p3GxsTrans::handleResponse(...) " - << "GXS_MAIL_SUBTYPE_MAIL cast error, " - << "something really wrong is happening" - << std::endl; - break; - } - default: - std::cerr << "p3GxsTrans::handleResponse(...) MAILS_UPDATE " - << "Unknown mail subtype : " - << static_cast(gIt->PacketSubType()) - << std::endl; - delete gIt; - break; - } - } - } - break; - } - default: - std::cerr << "p3GxsTrans::handleResponse(...) Unknown req_type: " - << req_type << std::endl; - break; - } - - if(changed) - IndicateConfigChanged(); -} -void p3GxsTrans::GxsTransIntegrityCleanupThread::getPerUserStatistics(std::map& m) -{ - RS_STACK_MUTEX(mMtx) ; - - m = total_message_size_and_count ; -} - -void p3GxsTrans::GxsTransIntegrityCleanupThread::getMessagesToDelete(GxsMsgReq& m) -{ - RS_STACK_MUTEX(mMtx) ; - - m = mMsgToDel ; - mMsgToDel.clear(); -} - -// This method does two things: -// 1 - cleaning up old messages and messages for which an ACK has been received. -// 2 - building per user statistics across groups. This is important because it allows to mitigate the excess of -// messages, which might be due to spam. -// -// Note: the anti-spam system is disabled the level of GXS, because we want to allow to send anonymous messages -// between identities that might not have a reputation yet. Still, messages from identities with a bad reputation -// are still deleted by GXS. -// -// The group limits are enforced according to the following rules: -// * a temporal sliding window is computed for each identity and the number of messages signed by this identity is counted -// * -// -// -// Deleted messages are notified to the RsGxsNetService part which keeps a list of delete messages so as not to request them again -// during the same session. This allows to safely delete messages while avoiding re-synchronisation from friend nodes. - -void p3GxsTrans::GxsTransIntegrityCleanupThread::run() -{ - // first take out all the groups - - std::map grp; - mDs->retrieveNxsGrps(grp, true); - -#ifdef DEBUG_GXSTRANS - std::cerr << "GxsTransIntegrityCleanupThread::run()" << std::endl; -#endif - - // compute hash and compare to stored value, if it fails then simply add it - // to list - - GxsMsgReq grps; - for(std::map::iterator git = grp.begin(); git != grp.end(); ++git) - { - RsNxsGrp* grp = git->second; - - // store the group for retrieveNxsMsgs - grps[grp->grpId]; - - delete grp; - } - - // now messages - - std::map totalMessageSizeAndCount; - - std::map > stored_msgs ; - std::list received_msgs ; - - GxsMsgResult msgs; - mDs->retrieveNxsMsgs(grps, msgs, true); - - for(GxsMsgResult::iterator mit = msgs.begin();mit != msgs.end(); ++mit) - { - std::vector& msgV = mit->second; - std::vector::iterator vit = msgV.begin(); -#ifdef DEBUG_GXSTRANS - std::cerr << "Group " << mit->first << ": " << std::endl; -#endif - - for(; vit != msgV.end(); ++vit) - { - RsNxsMsg* msg = *vit; - - RsGxsTransSerializer s ; - uint32_t size = msg->msg.bin_len; - RsItem *item = s.deserialise(msg->msg.bin_data,&size); - RsGxsTransMailItem *mitem ; - RsGxsTransPresignedReceipt *pitem ; - - if(item == NULL) - std::cerr << " Unrecocognised item type!" << std::endl; - else if(NULL != (mitem = dynamic_cast(item))) - { -#ifdef DEBUG_GXSTRANS - std::cerr << " " << msg->metaData->mMsgId << ": Mail data with ID " << std::hex << std::setfill('0') << std::setw(16) << mitem->mailId << std::dec << " from " << msg->metaData->mAuthorId << " size: " << msg->msg.bin_len << std::endl; -#endif - - stored_msgs[mitem->mailId] = std::make_pair(msg->metaData->mGroupId,msg->metaData->mMsgId) ; - } - else if(NULL != (pitem = dynamic_cast(item))) - { -#ifdef DEBUG_GXSTRANS - std::cerr << " " << msg->metaData->mMsgId << ": Signed rcpt of ID " << std::hex << pitem->mailId << std::dec << " from " << msg->metaData->mAuthorId << " size: " << msg->msg.bin_len << std::endl; -#endif - - received_msgs.push_back(pitem->mailId) ; - } - else - std::cerr << " Unknown item type!" << std::endl; - - totalMessageSizeAndCount[msg->metaData->mAuthorId].size += msg->msg.bin_len ; - totalMessageSizeAndCount[msg->metaData->mAuthorId].count++; - delete msg; - - delete item; - } - } - - // From the collected information, build a list of group messages to delete. - - GxsMsgReq msgsToDel ; - -#ifdef DEBUG_GXSTRANS - std::cerr << "Msg removal report:" << std::endl; - - std::cerr << " Per user size and count: " << std::endl; - for(std::map::const_iterator it(totalMessageSizeAndCount.begin());it!=totalMessageSizeAndCount.end();++it) - std::cerr << " " << it->first << ": " << it->second.count << " messages, for a total size of " << it->second.size << " bytes." << std::endl; -#endif - - for(std::list::const_iterator it(received_msgs.begin());it!=received_msgs.end();++it) - { - std::map >::const_iterator it2 = stored_msgs.find(*it) ; - - if(stored_msgs.end() != it2) - { - msgsToDel[it2->second.first].insert(it2->second.second); - -#ifdef DEBUG_GXSTRANS - std::cerr << " scheduling msg " << std::hex << it2->second.first << "," << it2->second.second << " for deletion." << std::endl; -#endif - } - } - - RS_STACK_MUTEX(mMtx) ; - mMsgToDel = msgsToDel ; - total_message_size_and_count = totalMessageSizeAndCount; - mDone = true; -} - -bool p3GxsTrans::GxsTransIntegrityCleanupThread::isDone() -{ - RS_STACK_MUTEX(mMtx) ; - return mDone ; -} -void p3GxsTrans::service_tick() -{ - GxsTokenQueue::checkRequests(); - - rstime_t now = time(NULL); - bool changed = false ; - - if(mLastMsgCleanup + MAX_DELAY_BETWEEN_CLEANUPS < now) - { - RS_STACK_MUTEX(mPerUserStatsMutex); - if(!mCleanupThread) - mCleanupThread = new GxsTransIntegrityCleanupThread(getDataStore()); - - if(mCleanupThread->isRunning()) - std::cerr << "Cleanup thread is already running. Not running it again!" << std::endl; - else - { -#ifdef DEBUG_GXSTRANS - std::cerr << "Starting GxsIntegrity cleanup thread." << std::endl; -#endif - - mCleanupThread->start() ; - mLastMsgCleanup = now ; - } - - // This forces to review all groups, and decide to subscribe or not to each of them. - - requestGroupsData(); - } - - // now grab collected messages to delete - - if(mCleanupThread != NULL && mCleanupThread->isDone()) - { - RS_STACK_MUTEX(mPerUserStatsMutex); - GxsMsgReq msgToDel ; - - mCleanupThread->getMessagesToDelete(msgToDel) ; - - if(!msgToDel.empty()) - { -#ifdef DEBUG_GXSTRANS - std::cerr << "p3GxsTrans::service_tick(): deleting messages." << std::endl; -#endif - uint32_t token ; - deleteMsgs(token,msgToDel); - } - - mCleanupThread->getPerUserStatistics(per_user_statistics) ; - -#ifdef DEBUG_GXSTRANS - std::cerr << "p3GxsTrans: Got new set of per user statistics:"<< std::endl; - for(std::map::const_iterator it(per_user_statistics.begin());it!=per_user_statistics.end();++it) - std::cerr << " " << it->first << ": " << it->second.count << " " << it->second.size << std::endl; -#endif - // Waiting here is very important because the thread may still be updating its semaphores after setting isDone() to true - // If we delete it during this operation it will corrupt the stack and cause unpredictable errors. - - while(mCleanupThread->isRunning()) - { - std::cerr << "Waiting for mCleanupThread to terminate..." << std::endl; - rstime::rs_usleep(500*1000); - } - - delete mCleanupThread; - mCleanupThread=NULL ; - } - - { - RS_STACK_MUTEX(mOutgoingMutex); - for ( auto it = mOutgoingQueue.begin(); it != mOutgoingQueue.end(); ) - { - OutgoingRecord& pr(it->second); - GxsTransSendStatus oldStatus = pr.status; - - locked_processOutgoingRecord(pr); - - if (oldStatus != pr.status) notifyClientService(pr); - if( pr.status >= GxsTransSendStatus::RECEIPT_RECEIVED ) - { - it = mOutgoingQueue.erase(it); - changed = true ; - } - else ++it; - } - } - - - { - RS_STACK_MUTEX(mIngoingMutex); - for( auto it = mIncomingQueue.begin(); it != mIncomingQueue.end(); ) - { - switch(static_cast( it->second->PacketSubType())) - { - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: - { - RsGxsTransMailItem* msg = dynamic_cast(it->second); - - if(!msg) - { - std::cerr << "p3GxsTrans::service_tick() (EE) " - << "GXS_MAIL_SUBTYPE_MAIL dynamic_cast failed, " - << "something really wrong is happening!" - << std::endl; - } - else - { -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::service_tick() " - << "GXS_MAIL_SUBTYPE_MAIL handling: " - << msg->meta.mMsgId - << " with cryptoType: " - << static_cast(msg->cryptoType) - << " recipientHint: " << msg->recipientHint - << " mailId: "<< msg->mailId - << " payload.size(): " << msg->payload.size() - << std::endl; -#endif - handleEncryptedMail(msg); - } - break; - } - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: - { - RsGxsTransPresignedReceipt* rcpt = dynamic_cast(it->second); - - if(!rcpt) - { - std::cerr << "p3GxsTrans::service_tick() (EE) " - << "GXS_MAIL_SUBTYPE_RECEIPT dynamic_cast failed," - << " something really wrong is happening!" - << std::endl; - } - else if(mIdService.isOwnId(rcpt->meta.mAuthorId)) - { - /* It is a receipt for a mail sent by this node live it in - * ingoingQueue so processOutgoingRecord(...) will take care - * of it at next tick */ - ++it; - continue; - } - else - { - /* It is a receipt for a message sent by someone else - * we can delete original mail from our GXS DB without - * waiting for GXS_STORAGE_PERIOD, this has been implemented - * already by Cyril into GxsTransIntegrityCleanupThread */ - } - break; - } - default: - std::cerr << "p3GxsTrans::service_tick() (EE) got something " - << "really unknown into ingoingQueue!!" << std::endl; - break; - } - - delete it->second ; - it = mIncomingQueue.erase(it); - changed = true ; - } - } - - if(changed) - IndicateConfigChanged(); -} - -RsGenExchange::ServiceCreate_Return p3GxsTrans::service_CreateGroup( - RsGxsGrpItem* /*grpItem*/, RsTlvSecurityKeySet& /*keySet*/ ) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::service_CreateGroup(...) " - << grpItem->meta.mGroupId << std::endl; -#endif - return SERVICE_CREATE_SUCCESS; -} - -void p3GxsTrans::notifyChanges(std::vector& changes) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::notifyChanges(...)" << std::endl; -#endif - std::list grps_to_request; - GxsMsgReq msgs_to_request; - - for( auto it = changes.begin(); it != changes.end(); ++it ) - { - RsGxsGroupChange* grpChange = dynamic_cast(*it); - RsGxsMsgChange* msgChange = dynamic_cast(*it); - - if (grpChange) - { -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::notifyChanges(...) grpChange" << std::endl; -#endif - grps_to_request.push_back(grpChange->mGroupId); - } - else if(msgChange) - { -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::notifyChanges(...) msgChange" << std::endl; -#endif - - msgs_to_request[msgChange->mGroupId].insert(msgChange->mMsgId); - -#ifdef DEBUG_GXSTRANS - for( GxsMsgReq::const_iterator it = msgChange->msgChangeMap.begin(); - it != msgChange->msgChangeMap.end(); ++it ) - { - const RsGxsGroupId& grpId = it->first; - const std::vector& msgsIds = it->second; - typedef std::vector::const_iterator itT; - for(itT vit = msgsIds.begin(); vit != msgsIds.end(); ++vit) - { - const RsGxsMessageId& msgId = *vit; - std::cout << "p3GxsTrans::notifyChanges(...) got " - << "notification for message " << msgId - << " in group " << grpId << std::endl; - } - } -#endif - } - delete *it; - } - - if(!msgs_to_request.empty()) - { - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - RsGenExchange::getTokenService()->requestMsgInfo( token, 0xcaca, opts, msgs_to_request); - - GxsTokenQueue::queueRequest(token, MAILS_UPDATE); - } - - - if(!grps_to_request.empty()) - requestGroupsData(&grps_to_request); -} - -uint32_t p3GxsTrans::AuthenPolicy() -{ - uint32_t policy = 0; - uint32_t flag = 0; - - // This ensure propagated message have valid author signature - flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN | - GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag( flag, policy, - RsGenExchange::PUBLIC_GRP_BITS ); - - /* This ensure that in for restricted and private groups only authorized - * authors get the messages. Really not used ATM but don't hurts. */ - flag |= GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | - GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag( flag, policy, - RsGenExchange::RESTRICTED_GRP_BITS ); - RsGenExchange::setAuthenPolicyFlag( flag, policy, - RsGenExchange::PRIVATE_GRP_BITS ); - - /* This seems never used RetroShare wide but we should investigate it - * more before considering this conclusive */ - flag = 0; - RsGenExchange::setAuthenPolicyFlag( flag, policy, - RsGenExchange::GRP_OPTION_BITS ); - - return policy; -} - -bool p3GxsTrans::requestGroupsData(const std::list* groupIds) -{ - // std::cout << "p3GxsTrans::requestGroupsList()" << std::endl; - uint32_t token=0; - RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - if(!groupIds) - RsGenExchange::getTokenService()->requestGroupInfo(token, 0xcaca, opts); - else - RsGenExchange::getTokenService()->requestGroupInfo(token, 0xcaca, opts, *groupIds); - - GxsTokenQueue::queueRequest(token, GROUPS_LIST); - return true; -} - -bool p3GxsTrans::handleEncryptedMail(const RsGxsTransMailItem* mail) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::handleEcryptedMail(...)" << std::endl; -#endif - - std::set decryptIds; - std::list ownIds; - mIdService.getOwnIds(ownIds); - for(auto it = ownIds.begin(); it != ownIds.end(); ++it) - if(mail->maybeRecipient(*it)) decryptIds.insert(*it); - - // Hint match none of our own ids - if(decryptIds.empty()) - { -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::handleEcryptedMail(...) hint doesn't match" << std::endl; -#endif - return true; - } - - switch (mail->cryptoType) - { - case RsGxsTransEncryptionMode::CLEAR_TEXT: - { - uint16_t csri = 0; - uint32_t off = 0; - getRawUInt16(&mail->payload[0], mail->payload.size(), &off, &csri); - -#ifdef DEBUG_GXSTRANS - std::cerr << "service: " << csri << " got CLEAR_TEXT mail!" - << std::endl; -#endif - /* As we cannot verify recipient without encryption, just pass the hint - * as recipient */ - return dispatchDecryptedMail( mail->meta.mAuthorId, mail->recipientHint, - &mail->payload[0], mail->payload.size() ); - } - case RsGxsTransEncryptionMode::RSA: - { - bool ok = true; - for( std::set::const_iterator it = decryptIds.begin(); - it != decryptIds.end(); ++it ) - { - const RsGxsId& decryptId(*it); - uint8_t* decrypted_data = NULL; - uint32_t decrypted_data_size = 0; - uint32_t decryption_error; - if( mIdService.decryptData( &mail->payload[0], - mail->payload.size(), decrypted_data, - decrypted_data_size, decryptId, - decryption_error ) ) - ok = ok && dispatchDecryptedMail( mail->meta.mAuthorId, - decryptId, decrypted_data, - decrypted_data_size ); - free(decrypted_data); - } - return ok; - } - default: - std::cout << "Unknown encryption type:" - << static_cast(mail->cryptoType) << std::endl; - return false; - } -} - -bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId, - const RsGxsId& decryptId, - const uint8_t* decrypted_data, - uint32_t decrypted_data_size ) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::dispatchDecryptedMail(, , " << decrypted_data_size - << ")" << std::endl; -#endif - - uint16_t csri = 0; - uint32_t offset = 0; - if(!getRawUInt16( decrypted_data, decrypted_data_size, &offset, &csri)) - { - std::cerr << "p3GxsTrans::dispatchDecryptedMail(...) (EE) fatal error " - << "deserializing service type, something really wrong is " - << "happening!" << std::endl; - return false; - } - GxsTransSubServices rsrvc = static_cast(csri); - - uint32_t rcptsize = decrypted_data_size - offset; - RsNxsTransPresignedReceipt* receipt = - static_cast( - RsNxsSerialiser(RS_SERVICE_TYPE_GXS_TRANS).deserialise( - const_cast(&decrypted_data[offset]), &rcptsize )); - offset += rcptsize; - if(!receipt) - { - std::cerr << "p3GxsTrans::dispatchDecryptedMail(...) (EE) fatal error " - << "deserializing presigned return receipt , something really" - << " wrong is happening!" << std::endl; - return false; - } -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::dispatchDecryptedMail(...) dispatching receipt " - << "with: msgId: " << receipt->msgId << std::endl; -#endif - - std::vector rcct; rcct.push_back(receipt); - RsGenExchange::receiveNewMessages(rcct); - - GxsTransClient* recipientService = NULL; - { - RS_STACK_MUTEX(mServClientsMutex); - recipientService = mServClients[rsrvc]; - } - - if(recipientService) - return recipientService->receiveGxsTransMail( - authorId, decryptId, &decrypted_data[offset], - decrypted_data_size-offset ); - else - { - std::cerr << "p3GxsTrans::dispatchReceivedMail(...) " - << "got message for unknown service: " - << csri << std::endl; - return false; - } -} - -void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr) -{ - //std::cout << "p3GxsTrans::processRecord(...)" << std::endl; - - switch (pr.status) - { - case GxsTransSendStatus::PENDING_PROCESSING: - { - pr.mailItem.saltRecipientHint(pr.recipient); - pr.mailItem.saltRecipientHint(RsGxsId::random()); - pr.sent_ts = time(NULL) ; //pr.mailItem.meta.mPublishTs = time(NULL); - } - /* fallthrough */ - case GxsTransSendStatus::PENDING_PREFERRED_GROUP: - { - RS_STACK_MUTEX(mDataMutex); - - if(mPreferredGroupId.isNull()) - { - requestGroupsData(); - pr.status = GxsTransSendStatus::PENDING_PREFERRED_GROUP; - break; - } - - pr.group_id = mPreferredGroupId ; //pr.mailItem.meta.mGroupId = mPreferredGroupId; - } - /* fallthrough */ - case GxsTransSendStatus::PENDING_RECEIPT_CREATE: - { - RsGxsTransPresignedReceipt grcpt; - grcpt.meta.mAuthorId = pr.author ; //grcpt.meta = pr.mailItem.meta; - grcpt.meta.mGroupId = pr.group_id ; //grcpt.meta = pr.mailItem.meta; - grcpt.meta.mMsgId.clear() ; - grcpt.meta.mParentId.clear() ; - grcpt.meta.mOrigMsgId.clear() ; - grcpt.meta.mPublishTs = time(NULL); - grcpt.mailId = pr.mailItem.mailId; - uint32_t grsz = RsGxsTransSerializer().size(&grcpt); - std::vector grsrz; - grsrz.resize(grsz); - RsGxsTransSerializer().serialise(&grcpt, &grsrz[0], &grsz); - - { - RS_STACK_MUTEX(mDataMutex); - pr.presignedReceipt.grpId = mPreferredGroupId; - } - pr.presignedReceipt.metaData = new RsGxsMsgMetaData(); - *pr.presignedReceipt.metaData = grcpt.meta; - pr.presignedReceipt.msg.setBinData(&grsrz[0], grsz); - } - /* fallthrough */ - case GxsTransSendStatus::PENDING_RECEIPT_SIGNATURE: // (cyril) This step is never actually used. - { - switch (RsGenExchange::createMessage(&pr.presignedReceipt)) - { - case CREATE_SUCCESS: break; - case CREATE_FAIL_TRY_LATER: - pr.status = GxsTransSendStatus::PENDING_RECEIPT_CREATE; - return; - default: - pr.status = GxsTransSendStatus::FAILED_RECEIPT_SIGNATURE; - goto processingFailed; - } - - uint32_t metaSize = pr.presignedReceipt.metaData->serial_size(); - std::vector srx; srx.resize(metaSize); - pr.presignedReceipt.metaData->serialise(&srx[0], &metaSize); - pr.presignedReceipt.meta.setBinData(&srx[0], metaSize); - } - /* fallthrough */ - case GxsTransSendStatus::PENDING_PAYLOAD_CREATE: - { - uint16_t serv = static_cast(pr.clientService); - uint32_t rcptsize = RsGxsTransSerializer().size(&pr.presignedReceipt); - uint32_t datasize = pr.mailData.size(); - pr.mailItem.payload.resize(2 + rcptsize + datasize); - uint32_t offset = 0; - setRawUInt16(&pr.mailItem.payload[0], 2, &offset, serv); - RsGxsTransSerializer().serialise(&pr.presignedReceipt, - &pr.mailItem.payload[offset], - &rcptsize); - offset += rcptsize; - memcpy(&pr.mailItem.payload[offset], &pr.mailData[0], datasize); - } - /* fallthrough */ - case GxsTransSendStatus::PENDING_PAYLOAD_ENCRYPT: - { - switch (pr.mailItem.cryptoType) - { - case RsGxsTransEncryptionMode::CLEAR_TEXT: - { - RsWarn() << __PRETTY_FUNCTION__ << " you are sending a mail " - << "without encryption, everyone can read it!" - << std::endl; - break; - } - case RsGxsTransEncryptionMode::RSA: - { - uint8_t* encryptedData = NULL; - uint32_t encryptedSize = 0; - uint32_t encryptError = 0; - if( mIdService.encryptData( &pr.mailItem.payload[0], - pr.mailItem.payload.size(), - encryptedData, encryptedSize, - pr.recipient, encryptError, true ) ) - { - pr.mailItem.payload.resize(encryptedSize); - memcpy( &pr.mailItem.payload[0], encryptedData, encryptedSize ); - free(encryptedData); - break; - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " RSA encryption failed! " - << "error_status: " << encryptError << std::endl; - pr.status = GxsTransSendStatus::FAILED_ENCRYPTION; - goto processingFailed; - } - } - case RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION: - default: - RsErr() << __PRETTY_FUNCTION__ << " attempt to send mail with " - << "wrong EncryptionMode: " - << static_cast(pr.mailItem.cryptoType) - << " dropping mail!" << std::endl; - pr.status = GxsTransSendStatus::FAILED_ENCRYPTION; - goto processingFailed; - } - } - /* fallthrough */ - case GxsTransSendStatus::PENDING_PUBLISH: - { -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::sendEmail(...) sending mail to: " - << pr.recipient - << " with cryptoType: " - << static_cast(pr.mailItem.cryptoType) - << " recipientHint: " << pr.mailItem.recipientHint - << " receiptId: " << pr.mailItem.mailId - << " payload size: " << pr.mailItem.payload.size() - << std::endl; -#endif - - RsGxsTransMailItem *mail_item = new RsGxsTransMailItem(pr.mailItem); - - // pr.mailItem.meta is *not* serialised. So it is important to not rely on what's in it! - - mail_item->meta.mGroupId = pr.group_id ; - mail_item->meta.mAuthorId = pr.author ; - - mail_item->meta.mMsgId.clear(); - mail_item->meta.mParentId.clear(); - mail_item->meta.mOrigMsgId.clear(); - - uint32_t token; - publishMsg(token, mail_item) ; - - pr.status = GxsTransSendStatus::PENDING_RECEIPT_RECEIVE; - - IndicateConfigChanged(); // This causes the saving of the message after pr.status has changed. - break; - } - //case GxsTransSendStatus::PENDING_TRANSFER: - case GxsTransSendStatus::PENDING_RECEIPT_RECEIVE: - { - RS_STACK_MUTEX(mIngoingMutex); - auto range = mIncomingQueue.equal_range(pr.mailItem.mailId); - bool changed = false; - bool received = false; - - for( auto it = range.first; it != range.second; ++it) - { - RsGxsTransPresignedReceipt* rt = dynamic_cast(it->second); - - if(rt && mIdService.isOwnId(rt->meta.mAuthorId)) - { - mIncomingQueue.erase(it); delete rt; - pr.status = GxsTransSendStatus::RECEIPT_RECEIVED; - - changed = true; - received = true; - break; - } - } - - if(!received && time(nullptr) - pr.sent_ts > GXS_STORAGE_PERIOD) - { - changed = true; - pr.status = GxsTransSendStatus::FAILED_TIMED_OUT; - } - - if(changed) - IndicateConfigChanged(); - - break; - } - case GxsTransSendStatus::RECEIPT_RECEIVED: - break; - -processingFailed: - case GxsTransSendStatus::FAILED_RECEIPT_SIGNATURE: - case GxsTransSendStatus::FAILED_ENCRYPTION: - case GxsTransSendStatus::FAILED_TIMED_OUT: - default: - RsErr() << __PRETTY_FUNCTION__ << " processing:" << pr.mailItem.mailId - << " failed with: " << static_cast(pr.status) - << std::endl; - break; - } -} - -void p3GxsTrans::notifyClientService(const OutgoingRecord& pr) -{ - RS_STACK_MUTEX(mServClientsMutex); - auto it = mServClients.find(pr.clientService); - if( it != mServClients.end()) - { - GxsTransClient* serv(it->second); - if(serv) - { - serv->notifyGxsTransSendStatus(pr.mailItem.mailId, pr.status); - return; - } - } - - std::cerr << "p3GxsTrans::processRecord(...) (EE) processed" - << " mail for unkown service: " - << static_cast(pr.clientService) - << " fatally failed with: " - << static_cast(pr.status) << std::endl; - print_stacktrace(); -} - -RsSerialiser* p3GxsTrans::setupSerialiser() -{ - RsSerialiser* rss = new RsSerialiser; - rss->addSerialType(new RsGxsTransSerializer); - return rss; -} - -bool p3GxsTrans::saveList(bool &cleanup, std::list& saveList) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl; -#endif - - mOutgoingMutex.lock(); - mIngoingMutex.lock(); - - for ( auto& kv : mOutgoingQueue ) - { -#ifdef DEBUG_GXSTRANS - std::cerr << "Saving outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::dec << "Group id: " << kv.second.group_id << ", TS=" << kv.second.sent_ts << std::endl; -#endif - saveList.push_back(&kv.second); - } - for ( auto& kv : mIncomingQueue ) - { -#ifdef DEBUG_GXSTRANS - std::cerr << "Saving incoming item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::endl; -#endif - saveList.push_back(kv.second); - } - -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl; -#endif - - cleanup = false; - return true; -} - -void p3GxsTrans::saveDone() -{ - mOutgoingMutex.unlock(); - mIngoingMutex.unlock(); -} - -bool p3GxsTrans::loadList(std::list&loadList) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::loadList(...) " << loadList.size() << " " - << mIncomingQueue.size() << " " << mOutgoingQueue.size() - << std::endl; -#endif - - for(auto& v : loadList) - switch(static_cast(v->PacketSubType())) - { - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: - { - RsGxsTransBaseMsgItem* mi = dynamic_cast(v); - if(mi) - { - RS_STACK_MUTEX(mIngoingMutex); - mIncomingQueue.insert(inMap::value_type(mi->mailId, mi)); - } - break; - } - case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated: - { - OutgoingRecord_deprecated* dot = dynamic_cast(v); - - if(dot) - { - std::cerr << "(EE) Read a deprecated GxsTrans outgoing item. Converting to new format..." << std::endl; - - OutgoingRecord ot(dot->recipient,dot->clientService,&dot->mailData[0],dot->mailData.size()) ; - - ot.status = dot->status ; - - ot.author.clear(); // These 3 fields cannot be stored in mailItem.meta, which is not serialised, so they are lost. - ot.group_id.clear() ; - ot.sent_ts = 0; - - ot.mailItem = dot->mailItem ; - ot.presignedReceipt = dot->presignedReceipt; - - RS_STACK_MUTEX(mOutgoingMutex); - mOutgoingQueue.insert(prMap::value_type(ot.mailItem.mailId, ot)); - -#ifdef DEBUG_GXSTRANS - std::cerr << "Loaded outgoing item (converted), ID " << std::hex << std::setfill('0') << std::setw(16) << ot.mailItem.mailId<< std::dec << ", Group id: " << ot.group_id << ", TS=" << ot.sent_ts << std::endl; -#endif - } - delete v; - break; - } - - case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM: - { - OutgoingRecord* ot = dynamic_cast(v); - if(ot) - { - RS_STACK_MUTEX(mOutgoingMutex); - mOutgoingQueue.insert( - prMap::value_type(ot->mailItem.mailId, *ot)); - -#ifdef DEBUG_GXSTRANS - std::cerr << "Loading outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << ot->mailItem.mailId<< std::dec << "Group id: " << ot->group_id << ", TS=" << ot->sent_ts << std::endl; -#endif - } - delete v; - break; - } - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_GROUP: - default: - std::cerr << "p3GxsTrans::loadList(...) (EE) got item with " - << "unhandled type: " - << static_cast(v->PacketSubType()) - << std::endl; - delete v; - break; - } - -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::loadList(...) " << loadList.size() << " " - << mIncomingQueue.size() << " " << mOutgoingQueue.size() - << std::endl; -#endif - - return true; -} - -bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta,uint32_t msg_size) -{ - // 1 - check the total size of the msgs for the author of this particular msg. - - // 2 - Reject depending on embedded limits. - - // Depending on reputation, the messages will be rejected: - // - // Reputation | Maximum msg count | Maximum msg size - // ------------+----------------------+------------------ - // Negative | 0 | 0 // This is already handled by the anti-spam - // R-Negative | 10 | 10k - // Neutral | 100 | 20k - // R-Positive | 400 | 1M - // Positive | 1000 | 2M - - // Ideally these values should be left as user-defined parameters, with the - // default values below used as backup. - - static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT = 10 ; - static const uint32_t GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT = 40 ; - static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_POSITIVE_DEFAULT = 400 ; - static const uint32_t GXSTRANS_MAX_COUNT_LOCALLY_POSITIVE_DEFAULT = 1000 ; - - static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_NEGATIVE_DEFAULT = 10 * 1024 ; - static const uint32_t GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT = 200 * 1024 ; - static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_POSITIVE_DEFAULT = 1024 * 1024 ; - static const uint32_t GXSTRANS_MAX_SIZE_LOCALLY_POSITIVE_DEFAULT = 2 * 1024 * 1024 ; - - uint32_t max_count = 0 ; - uint32_t max_size = 0 ; - uint32_t identity_flags = 0 ; - - RsReputationLevel rep_lev = - rsReputations->overallReputationLevel( - msgMeta->mAuthorId, &identity_flags ); - - switch(rep_lev) - { - case RsReputationLevel::REMOTELY_NEGATIVE: - max_count = GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT; - max_size = GXSTRANS_MAX_SIZE_REMOTELY_NEGATIVE_DEFAULT; - break ; - case RsReputationLevel::NEUTRAL: - max_count = GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT; - max_size = GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT; - break; - case RsReputationLevel::REMOTELY_POSITIVE: - max_count = GXSTRANS_MAX_COUNT_REMOTELY_POSITIVE_DEFAULT; - max_size = GXSTRANS_MAX_SIZE_REMOTELY_POSITIVE_DEFAULT; - break; - case RsReputationLevel::LOCALLY_POSITIVE: - max_count = GXSTRANS_MAX_COUNT_LOCALLY_POSITIVE_DEFAULT; - max_size = GXSTRANS_MAX_SIZE_LOCALLY_POSITIVE_DEFAULT; - break; - case RsReputationLevel::LOCALLY_NEGATIVE: // fallthrough - default: - max_count = 0; - max_size = 0; - break; - } - - bool pgp_linked = identity_flags & RS_IDENTITY_FLAGS_PGP_LINKED; - - if(rep_lev <= RsReputationLevel::NEUTRAL && !pgp_linked) - { - max_count /= 10 ; - max_size /= 10 ; - } - - RS_STACK_MUTEX(mPerUserStatsMutex); - - MsgSizeCount& s(per_user_statistics[msgMeta->mAuthorId]); - -#ifdef DEBUG_GXSTRANS - std::cerr << "GxsTrans::acceptMessage(): size=" << msg_size << ", grp=" << msgMeta->mGroupId << ", gxs_id=" << msgMeta->mAuthorId << ", pgp_linked=" << pgp_linked << ", current (size,cnt)=(" - << s.size << "," << s.count << ") reputation=" << rep_lev << ", limits=(" << max_size << "," << max_count << ") " ; -#endif - - if(s.size + msg_size > max_size || 1+s.count > max_count) - { -#ifdef DEBUG_GXSTRANS - std::cerr << "=> rejected." << std::endl; -#endif - return false ; - } - else - { -#ifdef DEBUG_GXSTRANS - std::cerr << "=> accepted." << std::endl; -#endif - - s.count++ ; - s.size += msg_size ; // update the statistics, so that it's not possible to pass a bunch of msgs at once below the limits. - - return true ; - } -} - - -bool p3GxsTrans::getGroupStatistics(std::map& stats) -{ - uint32_t token1; - - RsTokReqOptions opts1; - opts1.mReqType = GXS_REQUEST_TYPE_GROUP_META; - if( !requestGroupInfo(token1, opts1) || waitToken(token1) != RsTokenService::COMPLETE ) - return false; - - std::list group_metas; - getGroupSummary(token1,group_metas); - - for(auto& group_meta:group_metas) - { - RsGxsTransGroupStatistics& stat(stats[group_meta.mGroupId]); - - uint32_t token2; - if(!RsGxsIfaceHelper::requestGroupStatistic(token2,group_meta.mGroupId) || waitToken(token2) != RsTokenService::COMPLETE) - continue; - - RsGenExchange::getGroupStatistic(token2,stat); - - stat.popularity = group_meta.mPop ; - stat.subscribed = IS_GROUP_SUBSCRIBED(group_meta.mSubscribeFlags) ; - stat.mGrpId = group_meta.mGroupId ; - - std::vector metas; - - uint32_t token3; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - - std::list groupIds; - groupIds.push_back(group_meta.mGroupId); - - if( !requestMsgInfo(token3, opts, groupIds) || waitToken(token3, std::chrono::seconds(5)) != RsTokenService::COMPLETE ) - continue; - - GxsMsgMetaMap metaMap; - if(!RsGenExchange::getMsgMeta(token3, metaMap) || metaMap.size() != 1) - continue; - - for(auto& meta: metaMap.begin()->second) - stat.addMessageMeta(group_meta.mGroupId,meta) ; - } - - return true; -} - - diff --git a/libretroshare/src/gxstrans/p3gxstrans.h b/libretroshare/src/gxstrans/p3gxstrans.h deleted file mode 100644 index aff7b9eda..000000000 --- a/libretroshare/src/gxstrans/p3gxstrans.h +++ /dev/null @@ -1,342 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxstrans: p3gxstrans.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "retroshare/rsgxsifacetypes.h" // For RsGxsId, RsGxsCircleId -#include "gxs/gxstokenqueue.h" // For GxsTokenQueue -#include "gxstrans/p3gxstransitems.h" -#include "services/p3idservice.h" // For p3IdService -#include "util/rsthreads.h" -#include "retroshare/rsgxstrans.h" - -class p3GxsTrans; - -/// Services who want to make use of p3GxsTrans should inherit this struct -struct GxsTransClient -{ - /** - * This will be called by p3GxsTrans to dispatch mails to the subservice - * @param authorId message sender - * @param decryptId recipient id - * @param data buffer containing the decrypted data - * @param dataSize size of the buffer - * @return true if dispatching goes fine, false otherwise - */ - virtual bool receiveGxsTransMail( const RsGxsId& authorId, - const RsGxsId& recipientId, - const uint8_t* data, uint32_t dataSize - ) = 0; - - /** - * This will be called by p3GxsTrans to notify the subservice about the - * status of a sent email. - * @param originalMessage message for with the notification is made - * @param status the new status of the message - * @return true if notification goes fine, false otherwise (ignored ATM) - */ - virtual bool notifyGxsTransSendStatus( RsGxsTransId mailId, - GxsTransSendStatus status ) = 0; -}; - -struct MsgSizeCount -{ - MsgSizeCount() : size(0),count(0) {} - - uint32_t size ; - uint32_t count ; -}; - -/** - * @brief p3GxsTrans asyncronous redundant small mail trasport on top of GXS. - * p3GxsTrans is capable of asynchronous mail delivery and acknowledgement. - * p3GxsTrans is meant to be capable of multiple encryption options, - * @see RsGxsTransEncryptionMode at moment messages are encrypted using RSA - * unless the user ask for them being sent in clear text ( this is not supposed - * to happen in non testing environment so warnings and stack traces are printed - * in the log if an attempt to send something in clear text is made ). - * p3GxsTrans try to hide metadata so the travelling message signed by the author - * but the recipient is not disclosed, instead to avoid everyone trying to - * decrypt every message a hint has been introduced, the hint is calculated in a - * way that one can easily prove that a message is not destined to someone, but - * cannot prove the message is destined to someone - * @see RsGxsTransMailItem::recipientHint for more details. - * p3GxsTrans expose a simple API to send and receive mails, the API also - * provide notification for the sending mail status @see sendMail(...), - * @see querySendStatus(...), @see registerGxsTransClient(...), - * @see GxsTransClient::receiveGxsTransMail(...), - * @see GxsTransClient::notifyGxsTransSendStatus(...). - */ -class p3GxsTrans : public RsGenExchange, public GxsTokenQueue, public p3Config, public RsGxsTrans -{ -public: - p3GxsTrans( RsGeneralDataService* gds, RsNetworkExchangeService* nes, - p3IdService& identities ) : - RsGenExchange( gds, nes, new RsGxsTransSerializer(), - RS_SERVICE_TYPE_GXS_TRANS, &identities, - AuthenPolicy()), - GxsTokenQueue(this), - RsGxsTrans(static_cast(*this)), - // always check 30 secs after start) - mLastMsgCleanup(time(NULL) - MAX_DELAY_BETWEEN_CLEANUPS + 30), - mIdService(identities), - mServClientsMutex("p3GxsTrans client services map mutex"), - mOutgoingMutex("p3GxsTrans outgoing queue map mutex"), - mIngoingMutex("p3GxsTrans ingoing queue map mutex"), - mCleanupThread(nullptr), - mPerUserStatsMutex("p3GxsTrans user stats mutex"), - mDataMutex("p3GxsTrans data mutex") {} - - virtual ~p3GxsTrans(); - - /*! - * \brief getStatistics - * Gathers all sorts of statistics about the data transported by p3GxsTrans, in order to display info about the running status, - * message transport, etc. This is a blocking call. Use it in a thread. - * \param stats This structure contains all statistics information. - * \return true is the call succeeds. - */ - - virtual bool getDataStatistics(GxsTransStatistics& stats) override; - - /*! - * \brief getGroupStatistics - * Gathers statistics about GXS groups and messages used by GxsTrans to transport data. This is a blocking call. Use it in a thread. - * \param stats - * \return true if the data collection succeeds. - */ - virtual bool getGroupStatistics(std::map& stats) override; - - /** - * Send an email to recipient, in the process author of the email is - * disclosed to the network (because the sent GXS item is signed), while - * recipient is not @see RsGxsTransMailItem::recipientHint for details on - * recipient protection. - * This method is part of the public interface of this service. - * @return true if the mail will be sent, false if not - */ - bool sendData( RsGxsTransId& mailId, - GxsTransSubServices service, - const RsGxsId& own_gxsid, const RsGxsId& recipient, - const uint8_t* data, uint32_t size, - RsGxsTransEncryptionMode cm = RsGxsTransEncryptionMode::RSA - ); - - /** - * This method is part of the public interface of this service. - * @return false if mail is not found in outgoing queue, true otherwise - */ - bool querySendStatus( RsGxsTransId mailId, GxsTransSendStatus& st ); - - /** - * Register a client service to p3GxsTrans to receive mails via - * GxsTransClient::receiveGxsTransMail(...) callback - * This method is part of the public interface of this service. - */ - void registerGxsTransClient( GxsTransSubServices serviceType, - GxsTransClient* service ); - - /// @see RsGenExchange::getServiceInfo() - virtual RsServiceInfo getServiceInfo() override { return RsServiceInfo( RS_SERVICE_TYPE_GXS_TRANS, "GXS Mails", 0, 1, 0, 1 ); } - - static const uint32_t GXS_STORAGE_PERIOD = 15*86400; // 15 days. - static const uint32_t GXS_SYNC_PERIOD = 15*86400; -private: - /** Time interval of inactivity before a distribution group is unsubscribed. - * Approximatively 3 months seems ok ATM. */ - const static int32_t UNUSED_GROUP_UNSUBSCRIBE_INTERVAL = 16*86400; // 16 days - - /** - * This should be as little as possible as the size of the database can grow - * very fast taking in account we are handling mails for the whole network. - * We do prefer to resend a not acknowledged yet mail after - * GXS_STORAGE_PERIOD has passed and keep it little. - * Tought it can't be too little as this may cause signed receipts to - * get lost thus causing resend and fastly grow perceived async latency, in - * case two sporadically connected users sends mails each other. - * While it is ok for signed acknowledged to stays in the DB for a - * full GXS_STORAGE_PERIOD, mails should be removed as soon as a valid - * signed acknowledged is received for each of them. - * Two weeks seems fair ATM. - */ - static const uint32_t MAX_DELAY_BETWEEN_CLEANUPS ; // every 20 mins. Could be less. - - rstime_t mLastMsgCleanup ; - - /// Define how the backend should handle authentication based on signatures - static uint32_t AuthenPolicy(); - - /// Types to mark queries in tokens queue - enum GxsReqResTypes - { - GROUPS_LIST = 1, - GROUP_CREATE = 2, - MAILS_UPDATE = 3 - }; - - /// Store the id of the preferred GXS group to send emails - RsGxsGroupId mPreferredGroupId; - - /// Used for items {de,en}cryption - p3IdService& mIdService; - - /// Stores pointers to client services to notify them about new mails - std::map mServClients; - RsMutex mServClientsMutex; - - /** - * @brief Keep track of outgoing mails. - * Records enter the queue when a mail is sent, and are removed when a - * receipt has been received or sending is considered definetly failed. - * Items are saved in config for consistence accross RetroShare shutdowns. - */ - typedef std::map prMap; - prMap mOutgoingQueue; - RsMutex mOutgoingMutex; - void locked_processOutgoingRecord(OutgoingRecord& r); - - /** - * @brief Ingoing mail and receipt processing queue. - * At shutdown remaining items are saved in config and then deleted in - * destructor for consistence accross RetroShare instances. - * In order to avoid malicious messages ( non malicious collision has 1/2^64 - * probablity ) to smash items in the queue thus causing previous incoming - * item to not being processed and memleaked multimap is used instead of map - * for incoming queue. - */ - typedef std::unordered_multimap inMap; - inMap mIncomingQueue; - RsMutex mIngoingMutex; - - /// @see GxsTokenQueue::handleResponse(uint32_t token, uint32_t req_type - /// , RsTokenService::GxsRequestStatus status) - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) override; - - /// @see RsGenExchange::service_tick() - virtual void service_tick() override; - - /// @see RsGenExchange::service_CreateGroup(...) - RsGenExchange::ServiceCreate_Return service_CreateGroup( - RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& ) override; - - /// @see RsGenExchange::notifyChanges(std::vector &changes) - void notifyChanges(std::vector &changes) override; - - /// @see p3Config::setupSerialiser() - virtual RsSerialiser* setupSerialiser() override; - - /// @see p3Config::saveList(bool &cleanup, std::list&) - virtual bool saveList(bool &cleanup, std::list&saveList) override; - - /// @see p3Config::saveDone() - void saveDone() override; - - /// @see p3Config::loadList(std::list&) - virtual bool loadList(std::list& loadList) override; - - /// Request groups list to GXS backend. Async method. - bool requestGroupsData(const std::list* groupIds = NULL); - - /** - * Check if current preferredGroupId is the best against potentialGrId, if - * the passed one is better update it. - * Useful when GXS backend notifies groups changes, or when a reponse to an - * async grop request (@see GXS_REQUEST_TYPE_GROUP_*) is received. - * @return true if preferredGroupId has been supeseded by potentialGrId - * false otherwise. - */ - bool inline locked_supersedePreferredGroup(const RsGxsGroupId& potentialGrId) - { - if(mPreferredGroupId < potentialGrId) - { - // std::cerr << "supersedePreferredGroup(...) " << potentialGrId << " supersed " << mPreferredGroupId << std::endl; - mPreferredGroupId = potentialGrId; - return true; - } - return false; - } - - /** @return true if has passed more then interval seconds between timeStamp - * and ref. @param ref by default now is taked as reference. */ - bool static inline olderThen(rstime_t timeStamp, int32_t interval, - rstime_t ref = time(NULL)) - { return (timeStamp + interval) < ref; } - - - /// Decrypt email content and pass it to dispatchDecryptedMail(...) - bool handleEncryptedMail(const RsGxsTransMailItem* mail); - - /// Dispatch the message to the recipient service - bool dispatchDecryptedMail( const RsGxsId& authorId, - const RsGxsId& decryptId, - const uint8_t* decrypted_data, - uint32_t decrypted_data_size ); - - void notifyClientService(const OutgoingRecord& pr); - - /// Checks the integrity message and groups - class GxsTransIntegrityCleanupThread : public RsThread - { - enum CheckState { CheckStart, CheckChecking }; - - public: - explicit GxsTransIntegrityCleanupThread( - RsGeneralDataService* const dataService ): - mDs(dataService), mMtx("GxsTransIntegrityCheck"), mDone(false) {} - - bool isDone(); - void run(); - - void getDeletedIds(std::list& grpIds, std::map >& msgIds); - - void getMessagesToDelete(GxsMsgReq& req) ; - void getPerUserStatistics(std::map& m) ; - - private: - RsGeneralDataService* const mDs; - RsMutex mMtx ; - - GxsMsgReq mMsgToDel ; - std::map total_message_size_and_count; - bool mDone; - }; - - // Overloaded from RsGenExchange. - - bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta, uint32_t size) override; - - GxsTransIntegrityCleanupThread *mCleanupThread ; - - // statistics of the load across all groups, per user. - - RsMutex mPerUserStatsMutex; - std::map per_user_statistics ; - - // Mutex to protect local data - - RsMutex mDataMutex; -}; - diff --git a/libretroshare/src/gxstrans/p3gxstransitems.cc b/libretroshare/src/gxstrans/p3gxstransitems.cc deleted file mode 100644 index 733d40bec..000000000 --- a/libretroshare/src/gxstrans/p3gxstransitems.cc +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxstrans: p3gxstrans.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#include "gxstrans/p3gxstransitems.h" -#include "serialiser/rstypeserializer.h" - -const RsGxsId RsGxsTransMailItem::allRecipientsHint("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); - -OutgoingRecord_deprecated::OutgoingRecord_deprecated() - : RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, static_cast(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated) ) { clear();} - -OutgoingRecord::OutgoingRecord() - : RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, static_cast(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM) ) { clear();} - -OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs, - const uint8_t* data, uint32_t size ) : - RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, - static_cast(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM) ), - status(GxsTransSendStatus::PENDING_PROCESSING), recipient(rec), - clientService(cs) -{ - mailData.resize(size); - memcpy(&mailData[0], data, size); -} - -void OutgoingRecord_deprecated::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(status); - RS_SERIAL_PROCESS(recipient); - RS_SERIAL_PROCESS(mailItem); - RS_SERIAL_PROCESS(mailData); - RS_SERIAL_PROCESS(clientService); - RS_SERIAL_PROCESS(presignedReceipt); -} - -void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) -{ - RS_SERIAL_PROCESS(status); - RS_SERIAL_PROCESS(recipient); - RS_SERIAL_PROCESS(author); - RS_SERIAL_PROCESS(group_id); - RS_SERIAL_PROCESS(sent_ts); - RS_SERIAL_PROCESS(mailItem); - RS_SERIAL_PROCESS(mailData); - RS_SERIAL_PROCESS(clientService); - RS_SERIAL_PROCESS(presignedReceipt); -} diff --git a/libretroshare/src/gxstrans/p3gxstransitems.h b/libretroshare/src/gxstrans/p3gxstransitems.h deleted file mode 100644 index f2cab3cfe..000000000 --- a/libretroshare/src/gxstrans/p3gxstransitems.h +++ /dev/null @@ -1,270 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxstrans: p3gxstrans.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2017 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include "rsitems/rsgxsitems.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvidset.h" -#include "retroshare/rsgxsflags.h" -#include "retroshare/rsgxstrans.h" -#include "retroshare/rsgxscircles.h" // For: GXS_CIRCLE_TYPE_PUBLIC -#include "services/p3idservice.h" -#include "serialiser/rstypeserializer.h" - -class RsNxsTransPresignedReceipt : public RsNxsMsg -{ -public: - RsNxsTransPresignedReceipt() : RsNxsMsg(RS_SERVICE_TYPE_GXS_TRANS) {} - - virtual ~RsNxsTransPresignedReceipt() {} -}; - -class RsGxsTransBaseMsgItem : public RsGxsMsgItem -{ -public: - explicit RsGxsTransBaseMsgItem(GxsTransItemsSubtypes subtype) : - RsGxsMsgItem( RS_SERVICE_TYPE_GXS_TRANS, - static_cast(subtype) ), mailId(0) {} - - virtual ~RsGxsTransBaseMsgItem() {} - - RsGxsTransId mailId; - - void inline clear() - { - mailId = 0; - meta = RsMsgMetaData(); - } - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { RS_SERIAL_PROCESS(mailId); } -}; - -class RsGxsTransPresignedReceipt : public RsGxsTransBaseMsgItem -{ -public: - RsGxsTransPresignedReceipt() : RsGxsTransBaseMsgItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT) {} - virtual ~RsGxsTransPresignedReceipt() {} -}; - -enum class RsGxsTransEncryptionMode : uint8_t -{ - CLEAR_TEXT = 1, - RSA = 2, - UNDEFINED_ENCRYPTION = 250 -}; - -class RsGxsTransMailItem : public RsGxsTransBaseMsgItem -{ -public: - RsGxsTransMailItem() : - RsGxsTransBaseMsgItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL), - cryptoType(RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION) {} - - virtual ~RsGxsTransMailItem() {} - - RsGxsTransEncryptionMode cryptoType; - - /** - * @brief recipientHint used instead of plain recipient id, so sender can - * decide the equilibrium between exposing the recipient and the cost of - * completely anonymize it. So a bunch of luky non recipient can conclude - * rapidly that they are not the recipient without trying to decrypt the - * message. - * - * To be able to decide how much metadata we disclose sending a message we - * send an hint instead of the recipient id in clear, the hint cannot be - * false (the recipient would discard the mail) but may be arbitrarly - * obscure like 0xFF...FF so potentially everyone could be the recipient, or - * may expose the complete recipient id or be a middle ground. - * To calculate arbitrary precise hint one do a bitwise OR of the recipients - * keys and an arbitrary salt, the more recipients has the mail and the more - * 1 bits has the salt the less accurate is the hint. - * This way the sender is able to adjust the metadata privacy needed for the - * message, in the more private case (recipientHint == 0xFFF...FFF) no one - * has a clue about who is the actual recipient, while this imply the cost - * that every potencial recipient has to try to decrypt it to know if it is - * for herself. This way a bunch of non recipients can rapidly discover that - * the message is not directed to them without attempting it's decryption. - * - * To check if one id may be the recipient of the mail or not one need to - * bitwise compare the hint with the id, if at least one bit of the hint is - * 0 while the corresponding bit in the id is 1 then the id cannot be the - * recipient of the mail. - * - * Note that by design one can prove that an id is not recipient of the mail - * but cannot prove it is. - * Also in the extreme case of using 0x00...00 as salt that is equivalent - * to not salting at all (aka the plain recipient id is used as hint) a - * malicious observer could not demostrate in a conclusive manner that the - * mail is directed to the actual recipient as the "apparently" - * corresponding hint may be fruit of a "luky" salting of another id. - */ - RsGxsId recipientHint; - void inline saltRecipientHint(const RsGxsId& salt) - { recipientHint = recipientHint | salt; } - - /** - * @brief maybeRecipient given an id and an hint check if they match - * @see recipientHint - * @return true if the id may be recipient of the hint, false otherwise - */ - bool inline maybeRecipient(const RsGxsId& id) const - { return (~id|recipientHint) == allRecipientsHint; } - - const static RsGxsId allRecipientsHint; - - /** This should travel encrypted, unless EncryptionMode::CLEAR_TEXT - * is specified */ - std::vector payload; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RsGxsTransBaseMsgItem::serial_process(j, ctx); - RS_SERIAL_PROCESS(cryptoType); - RS_SERIAL_PROCESS(recipientHint); - RS_SERIAL_PROCESS(payload); - } - - void clear() - { - RsGxsTransBaseMsgItem::clear(); - cryptoType = RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION; - recipientHint.clear(); - payload.clear(); - } - - /// Maximum mail size in bytes 10 MiB is more than anything sane can need - const static uint32_t MAX_SIZE = 10*8*1024*1024; -}; - -class RsGxsTransGroupItem : public RsGxsGrpItem -{ -public: - RsGxsTransGroupItem() : - RsGxsGrpItem( RS_SERVICE_TYPE_GXS_TRANS, - static_cast( - GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_GROUP) ) - { - meta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; - meta.mGroupName = "Mail"; - meta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC; - } - virtual ~RsGxsTransGroupItem() {} - - // TODO: Talk with Cyril why there is no RsGxsGrpItem::serial_process - virtual void serial_process(RsGenericSerializer::SerializeJob /*j*/, - RsGenericSerializer::SerializeContext& /*ctx*/) - {} - - void clear() {} -}; - -class RsGxsTransSerializer; - -class OutgoingRecord_deprecated : public RsItem -{ -public: - OutgoingRecord_deprecated( RsGxsId rec, GxsTransSubServices cs, const uint8_t* data, uint32_t size ); - - virtual ~OutgoingRecord_deprecated() {} - - GxsTransSendStatus status; - RsGxsId recipient; - /// Don't use a pointer would be invalid after publish - RsGxsTransMailItem mailItem; - - std::vector mailData; - GxsTransSubServices clientService; - - RsNxsTransPresignedReceipt presignedReceipt; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - - void clear() {} - -private: - friend class RsGxsTransSerializer; - OutgoingRecord_deprecated(); -}; - -class OutgoingRecord : public RsItem -{ -public: - OutgoingRecord( RsGxsId rec, GxsTransSubServices cs, - const uint8_t* data, uint32_t size ); - - virtual ~OutgoingRecord() {} - - GxsTransSendStatus status; - RsGxsId recipient; - - RsGxsId author; // These 3 fields cannot be stored in mailItem.meta, which is not serialised. - RsGxsGroupId group_id ; - uint32_t sent_ts ; - - /// Don't use a pointer would be invalid after publish - RsGxsTransMailItem mailItem; - - std::vector mailData; - GxsTransSubServices clientService; - - RsNxsTransPresignedReceipt presignedReceipt; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - - void clear() {} - -private: - friend class RsGxsTransSerializer; - OutgoingRecord(); -}; - - -class RsGxsTransSerializer : public RsServiceSerializer -{ -public: - RsGxsTransSerializer() : RsServiceSerializer(RS_SERVICE_TYPE_GXS_TRANS) {} - virtual ~RsGxsTransSerializer() {} - - RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const - { - if(service_id != RS_SERVICE_TYPE_GXS_TRANS) return NULL; - - switch(static_cast(item_sub_id)) - { - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: return new RsGxsTransMailItem(); - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: return new RsGxsTransPresignedReceipt(); - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_GROUP: return new RsGxsTransGroupItem(); - case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated: return new OutgoingRecord_deprecated(); - case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM: return new OutgoingRecord(); - default: return NULL; - } - } -}; - diff --git a/libretroshare/src/gxstunnel/p3gxstunnel.cc b/libretroshare/src/gxstunnel/p3gxstunnel.cc deleted file mode 100644 index e500f82b0..000000000 --- a/libretroshare/src/gxstunnel/p3gxstunnel.cc +++ /dev/null @@ -1,1774 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: distantchat.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2015 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include - -#include "openssl/rand.h" -#include "openssl/dh.h" -#include "openssl/err.h" - -#include "crypto/rsaes.h" -#include "util/rsprint.h" -#include "util/rsmemory.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include "p3gxstunnel.h" - -//#define DEBUG_GXS_TUNNEL - -static const uint32_t GXS_TUNNEL_KEEP_ALIVE_TIMEOUT = 6 ; // send keep alive packet so as to avoid tunnel breaks. - -static const uint32_t RS_GXS_TUNNEL_DH_STATUS_UNINITIALIZED = 0x0000 ; -static const uint32_t RS_GXS_TUNNEL_DH_STATUS_HALF_KEY_DONE = 0x0001 ; -static const uint32_t RS_GXS_TUNNEL_DH_STATUS_KEY_AVAILABLE = 0x0002 ; - -static const uint32_t RS_GXS_TUNNEL_DELAY_BETWEEN_RESEND = 10 ; // re-send every 10 secs. -static const uint32_t RS_GXS_TUNNEL_DATA_PRINT_STORAGE_DELAY = 600 ; // store old message ids for 10 minutes. - -static const uint32_t GXS_TUNNEL_ENCRYPTION_HMAC_SIZE = SHA_DIGEST_LENGTH ; -static const uint32_t GXS_TUNNEL_ENCRYPTION_IV_SIZE = 8 ; - -#ifdef DEBUG_GXS_TUNNEL -static const uint32_t INTERVAL_BETWEEN_DEBUG_DUMP = 10 ; -#endif - -static std::string GXS_TUNNEL_APP_NAME = "GxsTunnels" ; - -static const uint8_t GXS_TUNNEL_APP_MAJOR_VERSION = 0x01 ; -static const uint8_t GXS_TUNNEL_APP_MINOR_VERSION = 0x00 ; -static const uint8_t GXS_TUNNEL_MIN_MAJOR_VERSION = 0x01 ; -static const uint8_t GXS_TUNNEL_MIN_MINOR_VERSION = 0x00 ; - -RsGxsTunnelService *rsGxsTunnel = NULL ; - -p3GxsTunnelService::p3GxsTunnelService(RsGixs *pids) - : mGixs(pids), mGxsTunnelMtx("GXS tunnel") -{ - mTurtle = NULL ; - mCurrentPacketCounter = 0 ; -} - -void p3GxsTunnelService::connectToTurtleRouter(p3turtle *tr) -{ - mTurtle = tr ; - tr->registerTunnelService(this) ; -} - -bool p3GxsTunnelService::registerClientService(uint32_t service_id,RsGxsTunnelService::RsGxsTunnelClientService *service) -{ - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - if(mRegisteredServices.find(service_id) != mRegisteredServices.end()) - { - std::cerr << "(EE) p3GxsTunnelService::registerClientService(): trying to register client " << std::hex << service_id << std::dec << ", which is already registered!" << std::endl; - return false; - } -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::registerClientService(): registering client service " << std::hex << service_id << std::dec << std::endl; -#endif - - mRegisteredServices[service_id] = service ; - return true ; -} - -int p3GxsTunnelService::tick() -{ - -#ifdef DEBUG_GXS_TUNNEL - rstime_t now = time(NULL); - static rstime_t last_dump = 0; - - if(now > last_dump + INTERVAL_BETWEEN_DEBUG_DUMP ) - { - last_dump = now ; - debug_dump() ; - } -#endif - - flush() ; - - return 0 ; -} - -RsServiceInfo p3GxsTunnelService::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_GXS_TUNNEL, - GXS_TUNNEL_APP_NAME, - GXS_TUNNEL_APP_MAJOR_VERSION, - GXS_TUNNEL_APP_MINOR_VERSION, - GXS_TUNNEL_MIN_MAJOR_VERSION, - GXS_TUNNEL_MIN_MINOR_VERSION); -} - -void p3GxsTunnelService::flush() -{ - // Flush pending DH items. This is a higher priority, so we deal with them first. - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::flush() flushing pending items." << std::endl; -#endif - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - for(std::list::iterator it=pendingDHItems.begin();it!=pendingDHItems.end();) - if(locked_sendClearTunnelData(*it) ) - { - delete *it ; - it = pendingDHItems.erase(it) ; - } - else - ++it ; - } - - // Flush items that could not be sent, probably because of a Mutex protected zone. - // - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - for(std::list::iterator it=pendingGxsTunnelItems.begin();it!=pendingGxsTunnelItems.end();) - if(locked_sendEncryptedTunnelData(*it) ) - { - delete *it ; - it = pendingGxsTunnelItems.erase(it) ; - } - else - { - ++it ; -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "Cannot send encrypted data item to tunnel " << (*it)->PeerId() << std::endl; -#endif - } - } - - // Look at pending data item, and re-send them if necessary. - - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - rstime_t now = time(NULL) ; - - for(std::map::iterator it = pendingGxsTunnelDataItems.begin();it != pendingGxsTunnelDataItems.end();++it) - if(now > RS_GXS_TUNNEL_DELAY_BETWEEN_RESEND + it->second.last_sending_attempt) - { - if(locked_sendEncryptedTunnelData(it->second.data_item)) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " sending data item #" << std::hex << it->first << std::dec << std::endl; -#endif - it->second.last_sending_attempt = now ; - } -#ifdef DEBUG_GXS_TUNNEL - else - std::cerr << " Cannot send item " << std::hex << it->first << std::dec << std::endl; -#endif - } - } - - // TODO: also sweep GXS id map and disable any ID with no virtual peer id in the list. - - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - rstime_t now = time(NULL) ; - - for(std::map::iterator it(_gxs_tunnel_contacts.begin());it!=_gxs_tunnel_contacts.end();) - { - // All sorts of cleaning. We start with the ones that may remove stuff, for efficiency reasons. - - // 1 - Remove any tunnel that was remotely closed, since we cannot use it anymore. - - if(it->second.status == RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED && it->second.last_contact + 20 < now) - { - std::map::iterator tmp = it ; - ++tmp ; - _gxs_tunnel_contacts.erase(it) ; - it=tmp ; - continue ; - } - - // 2 - re-digg tunnels that have died out of inaction - - if(it->second.last_contact+20+GXS_TUNNEL_KEEP_ALIVE_TIMEOUT < now && it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(II) GxsTunnelService:: connection interrupted with peer." << std::endl; -#endif - - it->second.status = RS_GXS_TUNNEL_STATUS_TUNNEL_DN ; - it->second.virtual_peer_id.clear() ; - - // Also reset turtle router monitoring so as to make the tunnel handling more responsive. If we don't do that, - // the TR will wait 60 secs for the tunnel to die, which causes a significant waiting time in the chat window. - - if(it->second.direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(II) GxsTunnelService:: forcing new tunnel campain." << std::endl; -#endif - - mTurtle->forceReDiggTunnels( randomHashFromDestinationGxsId(it->second.to_gxs_id) ); - } - } - - // send keep alive packets to active tunnels. - - if(it->second.last_keep_alive_sent + GXS_TUNNEL_KEEP_ALIVE_TIMEOUT < now && it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK) - { - RsGxsTunnelStatusItem *cs = new RsGxsTunnelStatusItem ; - - cs->status = RS_GXS_TUNNEL_FLAG_KEEP_ALIVE; - cs->PeerId(RsPeerId(it->first)) ; - - // we send off-mutex to avoid deadlock. - - pendingGxsTunnelItems.push_back(cs) ; - - it->second.last_keep_alive_sent = now ; -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(II) GxsTunnelService:: Sending keep alive packet to gxs id " << it->first << std::endl; -#endif - } - - // clean old received data prints. - - for(std::map::iterator it2=it->second.received_data_prints.begin();it2!=it->second.received_data_prints.end();) - if(now > it2->second + RS_GXS_TUNNEL_DATA_PRINT_STORAGE_DELAY) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(II) erasing old data print for message #" << it2->first << " in tunnel " << it->first << std::endl; -#endif - std::map::iterator tmp(it2) ; - ++tmp ; - it->second.received_data_prints.erase(it2) ; - it2 = tmp ; - } - else - ++it2 ; - - ++it ; - } -} - -// In this function the PeerId is the GXS tunnel ID. - -void p3GxsTunnelService::handleIncomingItem(const RsGxsTunnelId& tunnel_id,RsGxsTunnelItem *item) -{ - if(item == NULL) - return ; - - // We have 3 things to do: - // - // 1 - if it's a data item, send an ACK - // 2 - if it's an ack item, mark the item as properly received, and remove it from the queue - // 3 - if it's a status item, act accordingly. - - switch(item->PacketSubType()) - { - - case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA: handleRecvTunnelDataItem(tunnel_id,dynamic_cast(item)) ; - break ; - - case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK: handleRecvTunnelDataAckItem(tunnel_id,dynamic_cast(item)) ; - break ; - - case RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS: handleRecvStatusItem(tunnel_id,dynamic_cast(item)) ; - break ; - - default: - std::cerr << "(EE) impossible situation. DH items should be handled at the service level" << std::endl; - } - - delete item ; -} - -void p3GxsTunnelService::handleRecvTunnelDataAckItem(const RsGxsTunnelId &/*id*/,RsGxsTunnelDataAckItem *item) -{ - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::handling RecvTunnelDataAckItem()" << std::endl; - std::cerr << " item counter = " << std::hex << item->unique_item_counter << std::dec << std::endl; -#endif - - // remove it from the queue. - - std::map::iterator it = pendingGxsTunnelDataItems.find(item->unique_item_counter) ; - - if(it == pendingGxsTunnelDataItems.end()) - { - std::cerr << " (EE) item number " << std::hex << item->unique_item_counter << std::dec << " is unknown. This is unexpected." << std::endl; - return ; - } - - delete it->second.data_item ; - pendingGxsTunnelDataItems.erase(it) ; -} - -void p3GxsTunnelService::handleRecvTunnelDataItem(const RsGxsTunnelId& tunnel_id,RsGxsTunnelDataItem *item) -{ - // imediately send an ACK for this item - - RsGxsTunnelDataAckItem *ackitem = new RsGxsTunnelDataAckItem ; - - ackitem->unique_item_counter = item->unique_item_counter ; - ackitem->PeerId(RsPeerId(tunnel_id)) ; - - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - pendingGxsTunnelItems.push_back(ackitem) ; // we use the queue that does not need an ACK, in order to avoid an infinite loop ;-) - } - - // notify the client for the received data - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::handleRecvTunnelDataItem()" << std::endl; - std::cerr << " data size = " << item->data_size << std::endl; - std::cerr << " service id = " << std::hex << item->service_id << std::dec << std::endl; - std::cerr << " counter id = " << std::hex << item->unique_item_counter << std::dec << std::endl; -#endif - - RsGxsTunnelClientService *service = NULL ; - RsGxsId peer_from ; - bool is_client_side = false ; - - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - std::map::const_iterator it = mRegisteredServices.find(item->service_id) ; - - if(it == mRegisteredServices.end()) - { - std::cerr << " (EE) no registered service with ID " << std::hex << item->service_id << std::dec << ". Rejecting item." << std::endl; - return ; - } - service = it->second ; - - std::map::iterator it2 = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it2 != _gxs_tunnel_contacts.end()) - { - it2->second.client_services.insert(item->service_id) ; - peer_from = it2->second.to_gxs_id ; - is_client_side = (it2->second.direction == RsTurtleGenericDataItem::DIRECTION_SERVER); - } - - // Check if the item has already been received. This is necessary because we actually re-send items until an ACK is received. If the ACK gets lost (connection interrupted) the - // item may be received twice. This is conservative and ensure that no item is lost nor received twice. - - if(it2->second.received_data_prints.find(item->unique_item_counter) != it2->second.received_data_prints.end()) - { - std::cerr << "(WW) received the same data item #" << std::hex << item->unique_item_counter << std::dec << " twice in last 20 mins. Tunnel id=" << tunnel_id << ". Probably a replay. Item will be dropped." << std::endl; - return ; - } - it2->second.received_data_prints[item->unique_item_counter] = time(NULL) ; - } - - if(service->acceptDataFromPeer(peer_from,tunnel_id,is_client_side)) - service->receiveData(tunnel_id,item->data,item->data_size) ; - - item->data = NULL ; // avoids deletion, since the client has the memory now - item->data_size = 0 ; -} - -void p3GxsTunnelService::handleRecvStatusItem(const RsGxsTunnelId& tunnel_id, RsGxsTunnelStatusItem *cs) -{ - std::vector notifications ; - std::set clients ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::handleRecvStatusItem(): tunnel_id=" << tunnel_id << " status=" << cs->status << std::endl; -#endif - - switch(cs->status) - { - case RS_GXS_TUNNEL_FLAG_CLOSING_DISTANT_CONNECTION: - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it == _gxs_tunnel_contacts.end()) - { - std::cerr << "(EE) Cannot mark tunnel connection as closed. No connection openned for tunnel id " << tunnel_id << ". Unexpected situation." << std::endl; - return ; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Marking distant chat as remotely closed for tunnel id " << tunnel_id << std::endl; -#endif - if(it->second.direction == RsTurtleGenericDataItem::DIRECTION_CLIENT) - { - it->second.status = RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED ; -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " This is server side. The tunnel cannot be re-openned, so we give it up." << std::endl; -#endif - } - else - { - it->second.status = RS_GXS_TUNNEL_STATUS_TUNNEL_DN ; -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " This is client side. The tunnel will be re-openned automatically." << std::endl; -#endif - } - - notifications.push_back(RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED) ; - } // nothing more to do, because the decryption routing will update the last_contact time when decrypting. - break ; - - case RS_GXS_TUNNEL_FLAG_KEEP_ALIVE: -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService::handleRecvGxsTunnelStatusItem(): received keep alive packet for inactive tunnel! peerId=" << cs->PeerId() << " tunnel=" << tunnel_id << std::endl; -#endif - break ; - - case RS_GXS_TUNNEL_FLAG_ACK_DISTANT_CONNECTION: - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "Received ACK item from the distant peer!" << std::endl; -#endif - - // in this case we notify the clients using this tunnel. - - notifications.push_back(RS_GXS_TUNNEL_STATUS_CAN_TALK) ; - } - break ; - - default: - std::cerr << "(EE) unhandled tunnel status " << std::hex << cs->status << std::dec << std::endl; - break ; - } - - // notify all clients - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " notifying clients. Prending notifications: " << notifications.size() << std::endl; -#endif - - if(notifications.size() > 0) - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " " << it->second.client_services.size() << " client services for tunnel id " << tunnel_id << std::endl; -#endif - - for(std::set::const_iterator it2(it->second.client_services.begin());it2!=it->second.client_services.end();++it2) - { - std::map::const_iterator it3=mRegisteredServices.find(*it2) ; - - if(it3 != mRegisteredServices.end()) - clients.insert(it3->second) ; - } - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " notifying " << clients.size() << " clients." << std::endl; -#endif - - for(std::set::const_iterator it(clients.begin());it!=clients.end();++it) - for(uint32_t i=0;inotifyTunnelStatus(tunnel_id,notifications[i]) ; -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " notifying client " << (void*)(*it) << " of status " << notifications[i] << std::endl; -#endif - } -} - -bool p3GxsTunnelService::handleTunnelRequest(const RsFileHash& hash,const RsPeerId& /*peer_id*/) -{ - RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - // look into owned GXS ids, and see if the hash corresponds to the expected hash - // - std::list own_id_list ; - rsIdentity->getOwnIds(own_id_list) ; - - // extract the GXS id from the hash - - RsGxsId destination_id = destinationGxsIdFromHash(hash) ; - - // linear search. Not costly because we have typically a low number of IDs. Otherwise, this really should be avoided! - - for(std::list::const_iterator it(own_id_list.begin());it!=own_id_list.end();++it) - if(*it == destination_id) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService::handleTunnelRequest: received tunnel request for hash " << hash << std::endl; - std::cerr << " answering true!" << std::endl; -#endif - return true ; - } - - return false ; -} - -void p3GxsTunnelService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) -{ -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService:: received new virtual peer " << virtual_peer_id << " for hash " << hash << ", dir=" << dir << std::endl; -#endif - RsGxsId own_gxs_id ; - - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - GxsTunnelDHInfo& dhinfo( _gxs_tunnel_virtual_peer_ids[virtual_peer_id] ) ; - dhinfo.gxs_id.clear() ; - - if(dhinfo.dh != NULL) - DH_free(dhinfo.dh) ; - - dhinfo.dh = NULL ; - dhinfo.direction = dir ; - dhinfo.hash = hash ; - dhinfo.status = RS_GXS_TUNNEL_DH_STATUS_UNINITIALIZED ; - dhinfo.tunnel_id.clear(); - - if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) // server side - { - // check that a tunnel is not already working for this hash. If so, give up. - - own_gxs_id = destinationGxsIdFromHash(hash) ; - } - else // client side - { - std::map::const_iterator it = _gxs_tunnel_contacts.begin(); - - while(it != _gxs_tunnel_contacts.end() && it->second.hash != hash) ++it ; - - if(it == _gxs_tunnel_contacts.end()) - { - std::cerr << "(EE) no pre-registered peer for hash " << hash << " on client side. This is a bug." << std::endl; - return ; - } - - if(it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " virtual peer is for a distant chat session that is already openned and alive. Giving it up." << std::endl; -#endif - return ; - } - - own_gxs_id = it->second.own_gxs_id ; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Creating new virtual peer ID entry and empty DH session key." << std::endl; -#endif - - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Adding virtual peer " << virtual_peer_id << " for chat hash " << hash << std::endl; -#endif - - // Start a new DH session for this tunnel - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - locked_restartDHSession(virtual_peer_id,own_gxs_id) ; -} - -void p3GxsTunnelService::locked_restartDHSession(const RsPeerId& virtual_peer_id,const RsGxsId& own_gxs_id) -{ -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "Starting new DH session." << std::endl; -#endif - GxsTunnelDHInfo& dhinfo = _gxs_tunnel_virtual_peer_ids[virtual_peer_id] ; // creates it, if necessary - - dhinfo.status = RS_GXS_TUNNEL_DH_STATUS_UNINITIALIZED ; - dhinfo.own_gxs_id = own_gxs_id ; - - if(!locked_initDHSessionKey(dhinfo.dh)) - { - std::cerr << " (EE) Cannot start DH session. Something went wrong." << std::endl; - return ; - } - dhinfo.status = RS_GXS_TUNNEL_DH_STATUS_HALF_KEY_DONE ; - - if(!locked_sendDHPublicKey(dhinfo.dh,own_gxs_id,virtual_peer_id)) - std::cerr << " (EE) Cannot send DH public key. Something went wrong." << std::endl; -} - -void p3GxsTunnelService::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) -{ - bool tunnel_dn = false ; - std::set client_services ; - RsGxsTunnelId tunnel_id ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService: Removing virtual peer " << virtual_peer_id << " for hash " << hash << std::endl; -#else - /* remove unused parameter warnings */ - (void) hash; -#endif - { - RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - RsGxsId gxs_id ; - std::map::iterator it = _gxs_tunnel_virtual_peer_ids.find(virtual_peer_id) ; - - if(it == _gxs_tunnel_virtual_peer_ids.end()) - { - std::cerr << "(EE) Cannot remove virtual peer " << virtual_peer_id << ": not found in tunnel list!!" << std::endl; - return ; - } - - tunnel_id = it->second.tunnel_id ; - - if(it->second.dh != NULL) - DH_free(it->second.dh) ; - - _gxs_tunnel_virtual_peer_ids.erase(it) ; - - std::map::iterator it2 = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it2 == _gxs_tunnel_contacts.end()) - { - std::cerr << "(EE) Cannot find tunnel id " << tunnel_id << " in contact list. Weird." << std::endl; - return ; - } - if(it2->second.virtual_peer_id == virtual_peer_id) - { - it2->second.status = RS_GXS_TUNNEL_STATUS_TUNNEL_DN ; - it2->second.virtual_peer_id.clear() ; - tunnel_dn = true ; - } - - for(std::set::const_iterator it(it2->second.client_services.begin());it!=it2->second.client_services.end();++it) - { - std::map::const_iterator it2 = mRegisteredServices.find(*it) ; - - if(it2 != mRegisteredServices.end()) - client_services.insert(it2->second) ; - } - } - - if(tunnel_dn) - { - // notify all client services that this tunnel is down - - for(std::set::const_iterator it(client_services.begin());it!=client_services.end();++it) - (*it)->notifyTunnelStatus(tunnel_id,RS_GXS_TUNNEL_STATUS_TUNNEL_DN) ; - } -} - -void p3GxsTunnelService::receiveTurtleData(const RsTurtleGenericTunnelItem *gitem, const RsFileHash& hash, const RsPeerId& virtual_peer_id, RsTurtleGenericTunnelItem::Direction direction) -{ -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService::receiveTurtleData(): Received turtle data. " << std::endl; - std::cerr << " hash = " << hash << std::endl; - std::cerr << " vpid = " << virtual_peer_id << std::endl; - std::cerr << " acting as = " << direction << std::endl; -#else - /* remove unused parameter warnings */ - (void) direction; -#endif - - void *data_bytes; - uint32_t data_size ; - bool accept_fast_items = false; - - const RsTurtleGenericFastDataItem *fitem = dynamic_cast(gitem) ; - - if(fitem != NULL) - { - data_bytes = fitem->data_bytes ; - data_size = fitem->data_size ; - accept_fast_items = true; - } - else - { - const RsTurtleGenericDataItem *item = dynamic_cast(gitem) ; - - if(item == NULL) - { - std::cerr << "(EE) item is not a data item. That is an error." << std::endl; - return ; - } - data_bytes = item->data_bytes ; - data_size = item->data_size ; - } - - // Call the AES crypto module - // - the IV is the first 8 bytes of item->data_bytes - - if(data_size < 8) - { - std::cerr << "(EE) item encrypted data stream is too small: size = " << data_size << std::endl; - return ; - } - if(*((uint64_t*)data_bytes) != 0) // WTF?? we should use flags - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Item is encrypted." << std::endl; -#endif - - // if cannot decrypt, it means the key is wrong. We need to re-negociate a new key. - - handleEncryptedData((uint8_t*)data_bytes,data_size,hash,virtual_peer_id,accept_fast_items) ; - } - else - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Item is not encrypted." << std::endl; -#endif - - // Now try deserialise the decrypted data to make an RsItem out of it. - // - uint32_t pktsize = data_size-8; - RsItem *citem = RsGxsTunnelSerialiser().deserialise(&((uint8_t*)data_bytes)[8],&pktsize) ; - - if(citem == NULL) - { - std::cerr << "(EE) item could not be de-serialized. That is an error." << std::endl; - return ; - } - - // DH key items are sent even before we know who we speak to, so the virtual peer id is used in this - // case only. - RsGxsTunnelDHPublicKeyItem *dhitem = dynamic_cast(citem) ; - - if(dhitem != NULL) - { - dhitem->PeerId(virtual_peer_id) ; - handleRecvDHPublicKey(dhitem) ; - } - else - std::cerr << "(EE) Deserialiased item has unexpected type." << std::endl; - - delete citem ; - } -} - -// This function encrypts the given data and adds a MAC and an IV into a serialised memory chunk that is then sent through the tunnel. - -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 -bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id,bool accepts_fast_items) -#else -bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id) -#endif -{ -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::handleEncryptedDataItem()" << std::endl; - std::cerr << " size = " << data_size << std::endl; - std::cerr << " data = " << (void*)data_bytes << std::endl; - std::cerr << " IV = " << std::hex << *(uint64_t*)data_bytes << std::dec << std::endl; - std::cerr << " data = " << RsUtil::BinToHex((unsigned char*)data_bytes,data_size,100) ; - std::cerr << std::endl; -#endif - - RsGxsTunnelItem *citem = NULL; - RsGxsTunnelId tunnel_id; - - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - uint32_t encrypted_size = data_size - GXS_TUNNEL_ENCRYPTION_IV_SIZE - GXS_TUNNEL_ENCRYPTION_HMAC_SIZE; - uint32_t decrypted_size = RsAES::get_buffer_size(encrypted_size); - uint8_t *encrypted_data = (uint8_t*)data_bytes+GXS_TUNNEL_ENCRYPTION_IV_SIZE+GXS_TUNNEL_ENCRYPTION_HMAC_SIZE; - - RsTemporaryMemory decrypted_data(decrypted_size); - uint8_t aes_key[GXS_TUNNEL_AES_KEY_SIZE] ; - - if(!decrypted_data) - return false ; - - std::map::iterator it = _gxs_tunnel_virtual_peer_ids.find(virtual_peer_id) ; - - if(it == _gxs_tunnel_virtual_peer_ids.end()) - { - std::cerr << "(EE) item is not coming out of a registered tunnel. Weird. hash=" << hash << ", peer id = " << virtual_peer_id << std::endl; - return false ; - } - - tunnel_id = it->second.tunnel_id ; - std::map::iterator it2 = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it2 == _gxs_tunnel_contacts.end()) - { - std::cerr << "(EE) no tunnel data for tunnel ID=" << tunnel_id << ". This is a bug." << std::endl; - return false ; - } -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 - if(accepts_fast_items) - { - if(!it2->second.accepts_fast_turtle_items) - std::cerr << "(II) received probe for Fast track turtle items for tunnel VPID " << it2->second.virtual_peer_id << ": switching to Fast items mode." << std::endl; - - it2->second.accepts_fast_turtle_items = true; - } -#endif - - memcpy(aes_key,it2->second.aes_key,GXS_TUNNEL_AES_KEY_SIZE) ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Using IV: " << std::hex << *(uint64_t*)data_bytes << std::dec << std::endl; - std::cerr << " Decrypted buffer size: " << decrypted_size << std::endl; - std::cerr << " key : " << RsUtil::BinToHex((unsigned char*)aes_key,GXS_TUNNEL_AES_KEY_SIZE) << std::endl; - std::cerr << " hmac : " << RsUtil::BinToHex((unsigned char*)data_bytes+GXS_TUNNEL_ENCRYPTION_IV_SIZE,GXS_TUNNEL_ENCRYPTION_HMAC_SIZE) << std::endl; - std::cerr << " data : " << RsUtil::BinToHex((unsigned char*)data_bytes,data_size,100) << std::endl; -#endif - // first, check the HMAC - - unsigned char *hm = HMAC(EVP_sha1(),aes_key,GXS_TUNNEL_AES_KEY_SIZE,encrypted_data,encrypted_size,NULL,NULL) ; - - if(memcmp(hm,&data_bytes[GXS_TUNNEL_ENCRYPTION_IV_SIZE],GXS_TUNNEL_ENCRYPTION_HMAC_SIZE)) - { - std::cerr << "(EE) packet HMAC does not match. Computed HMAC=" << RsUtil::BinToHex((char*)hm,GXS_TUNNEL_ENCRYPTION_HMAC_SIZE) << std::endl; - std::cerr << "(EE) resetting new DH session." << std::endl; - - locked_restartDHSession(virtual_peer_id,it2->second.own_gxs_id) ; - - return false ; - } - - if(!RsAES::aes_decrypt_8_16(encrypted_data,encrypted_size, aes_key,(uint8_t*)data_bytes,decrypted_data,decrypted_size)) - { - std::cerr << "(EE) packet decryption failed." << std::endl; - std::cerr << "(EE) resetting new DH session." << std::endl; - - locked_restartDHSession(virtual_peer_id,it2->second.own_gxs_id) ; - - return false ; - } - it2->second.status = RS_GXS_TUNNEL_STATUS_CAN_TALK ; - it2->second.last_contact = time(NULL) ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(II) Decrypted data: size=" << decrypted_size << std::endl; -#endif - - // Now try deserialise the decrypted data to make an RsItem out of it. - // - citem = dynamic_cast(RsGxsTunnelSerialiser().deserialise(decrypted_data,&decrypted_size)) ; - - if(citem == NULL) - { - std::cerr << "(EE) item could not be de-serialized. That is an error." << std::endl; - return true; - } - - it2->second.total_received += decrypted_size ; - - // DH key items are sent even before we know who we speak to, so the virtual peer id is used in this - // case only. - - citem->PeerId(virtual_peer_id) ; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(II) Setting peer id to " << citem->PeerId() << std::endl; -#endif - handleIncomingItem(tunnel_id,citem) ; // Treats the item, and deletes it - - return true ; -} - -void p3GxsTunnelService::handleRecvDHPublicKey(RsGxsTunnelDHPublicKeyItem *item) -{ - if (!item) - { - std::cerr << "p3GxsTunnelService: Received null DH public key item. This should not happen." << std::endl; - return; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService: Received DH public key." << std::endl; - item->print(std::cerr, 0) ; -#endif - - // Look for the current state of the key agreement. - - TurtleVirtualPeerId vpid = item->PeerId() ; - - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _gxs_tunnel_virtual_peer_ids.find(vpid) ; - - if(it == _gxs_tunnel_virtual_peer_ids.end()) - { - std::cerr << " (EE) Cannot find hash in gxs_tunnel peer list!!" << std::endl; - return ; - } - - // Now check the signature of the DH public key item. - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Checking signature. " << std::endl; -#endif - - uint32_t pubkey_size = BN_num_bytes(item->public_key) ; - RsTemporaryMemory data(pubkey_size) ; - BN_bn2bin(item->public_key, data) ; - - RsTlvPublicRSAKey signature_key ; - - // We need to get the key of the sender, but if the key is not cached, we - // need to get it first. So we let the system work for 2-3 seconds before - // giving up. Normally this would only cause a delay for uncached keys, - // which is rare. To force the system to cache the key, we first call for - // getIdDetails(). - // - RsIdentityDetails details ; - RsGxsId senders_id( item->signature.keyId ) ; - - for(int i=0;i<6;++i) - if(!mGixs->getKey(senders_id,signature_key) || signature_key.keyData.bin_data == NULL) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl; -#endif - usleep(500 * 1000) ; // sleep for 500 msec. - } - else - break ; - - if(signature_key.keyData.bin_data == NULL) - { - std::cerr << " (EE) Key unknown for checking signature from " << senders_id << ", can't verify signature. Using key provided in DH packet (without adding to the keyring)." << std::endl; - - // check GXS key for defects. - - if(!GxsSecurity::checkPublicKey(item->gxs_key)) - { - std::cerr << "(SS) Security error in distant chat DH handshake: supplied key " << item->gxs_key.keyId << " is inconsistent. Refusing chat!" << std::endl; - return ; - } - if(item->gxs_key.keyId != item->signature.keyId) - { - std::cerr << "(SS) Security error in distant chat DH handshake: supplied key " << item->gxs_key.keyId << " is not the same than the item's signature key " << item->signature.keyId << ". Refusing chat!" << std::endl; - return ; - } - - signature_key = item->gxs_key ; - } - - if(!GxsSecurity::validateSignature((char*)(unsigned char*)data,pubkey_size,signature_key,item->signature)) - { - std::cerr << "(SS) Signature was verified and it doesn't check! This is a security issue!" << std::endl; - return ; - } - mGixs->timeStampKey(item->signature.keyId,RsIdentityUsage(RsServiceType::GXS_TUNNEL,RsIdentityUsage::GXS_TUNNEL_DH_SIGNATURE_CHECK)); - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Signature checks! Sender's ID = " << senders_id << std::endl; - std::cerr << " Computing AES key" << std::endl; -#endif - - if(it->second.dh == NULL) - { - std::cerr << " (EE) no DH information for that peer. This is an error." << std::endl; - return ; - } - if(it->second.status == RS_GXS_TUNNEL_DH_STATUS_KEY_AVAILABLE) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " DH Session already set for this tunnel. Re-initing a new session!" << std::endl; -#endif - - locked_restartDHSession(vpid,it->second.own_gxs_id) ; - } - - // gets current key params. By default, should contain all null pointers. - // - RsGxsId own_id = it->second.own_gxs_id ; - - RsGxsTunnelId tunnel_id = makeGxsTunnelId(own_id,senders_id) ; - - it->second.tunnel_id = tunnel_id ; - it->second.gxs_id = senders_id ; - - // Looks for the DH params. If not there yet, create them. - // - int size = DH_size(it->second.dh) ; - RsTemporaryMemory key_buff(size) ; - - if(size != DH_compute_key(key_buff,item->public_key,it->second.dh)) - { - std::cerr << " (EE) DH computation failed. Probably a bug. Error code=" << ERR_get_error() << std::endl; - return ; - } - it->second.status = RS_GXS_TUNNEL_DH_STATUS_KEY_AVAILABLE ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " DH key computation successed. New key in place." << std::endl; -#endif - // make a hash of destination and source GXS ids in order to create the tunnel name - - GxsTunnelPeerInfo& pinfo(_gxs_tunnel_contacts[tunnel_id]) ; - - // Now hash the key buffer into a 16 bytes key. - - assert(GXS_TUNNEL_AES_KEY_SIZE <= Sha1CheckSum::SIZE_IN_BYTES) ; - memcpy(pinfo.aes_key, RsDirUtil::sha1sum(key_buff,size).toByteArray(),GXS_TUNNEL_AES_KEY_SIZE) ; - - pinfo.last_contact = time(NULL) ; - pinfo.last_keep_alive_sent = time(NULL) ; - pinfo.status = RS_GXS_TUNNEL_STATUS_CAN_TALK ; - pinfo.virtual_peer_id = vpid ; - pinfo.direction = it->second.direction ; - pinfo.own_gxs_id = own_id ; - pinfo.to_gxs_id = item->signature.keyId; // this is already set for client side but not for server side. - - // note: the hash might still be nn initialised on server side. - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " DH key computed. Tunnel is now secured!" << std::endl; - std::cerr << " Key computed: " << RsUtil::BinToHex((char*)pinfo.aes_key,16) << std::endl; - std::cerr << " Sending a ACK packet." << std::endl; -#endif - - // then we send an ACK packet to notify that the tunnel works. That's useful - // because it makes the peer at the other end of the tunnel know that all - // intermediate peer in the tunnel are able to transmit the data. - // However, it is not possible here to call sendTurtleData(), without dead-locking - // the turtle router, so we store the item is a list of items to be sent. - - RsGxsTunnelStatusItem *cs = new RsGxsTunnelStatusItem ; - - cs->status = RS_GXS_TUNNEL_FLAG_ACK_DISTANT_CONNECTION; - cs->PeerId(RsPeerId(tunnel_id)) ; - - pendingGxsTunnelItems.push_back(cs) ; -} - -// Note: for some obscure reason, the typedef does not work here. Looks like a compiler error. So I use the primary type. - -/*static*/ RsGxsTunnelId p3GxsTunnelService::makeGxsTunnelId( - const RsGxsId &own_id, const RsGxsId &distant_id ) -{ - unsigned char mem[RsGxsId::SIZE_IN_BYTES * 2] ; - - // Always sort the ids, as a matter to avoid confusion between the two. Also that generates the same tunnel ID on both sides - // which helps debugging. If the code is right this is not needed anyway. - - if(own_id < distant_id) - { - memcpy(mem, own_id.toByteArray(), RsGxsId::SIZE_IN_BYTES) ; - memcpy(mem+RsGxsId::SIZE_IN_BYTES, distant_id.toByteArray(), RsGxsId::SIZE_IN_BYTES) ; - } - else - { - memcpy(mem, distant_id.toByteArray(), RsGxsId::SIZE_IN_BYTES) ; - memcpy(mem+RsGxsId::SIZE_IN_BYTES, own_id.toByteArray(), RsGxsId::SIZE_IN_BYTES) ; - } - - assert( RsGxsTunnelId::SIZE_IN_BYTES <= Sha1CheckSum::SIZE_IN_BYTES ) ; - - return RsGxsTunnelId( RsDirUtil::sha1sum(mem, 2*RsGxsId::SIZE_IN_BYTES).toByteArray() ) ; -} - -bool p3GxsTunnelService::locked_sendDHPublicKey(const DH *dh,const RsGxsId& own_gxs_id,const RsPeerId& virtual_peer_id) -{ - if(dh == NULL) - { - std::cerr << " (EE) DH struct is not initialised! Error." << std::endl; - return false ; - } - - RsGxsTunnelDHPublicKeyItem *dhitem = new RsGxsTunnelDHPublicKeyItem ; -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - dhitem->public_key = BN_dup(dh->pub_key) ; -#else - const BIGNUM *pub_key=NULL ; - DH_get0_key(dh,&pub_key,NULL) ; - dhitem->public_key = BN_dup(pub_key) ; -#endif - - // we should also sign the data and check the signature on the other end. - // - RsTlvKeySignature signature ; - RsTlvPrivateRSAKey signature_key ; - RsTlvPublicRSAKey signature_key_public ; - - uint32_t error_status ; - - uint32_t size = BN_num_bytes(dhitem->public_key) ; - - RsTemporaryMemory data(size) ; - - if(data == NULL) - { - delete(dhitem); - return false ; - } - - BN_bn2bin(dhitem->public_key, data) ; - - if(!mGixs->signData((unsigned char*)data,size,own_gxs_id,signature,error_status)) - { - switch(error_status) - { - case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: std::cerr << "(EE) Key is not available. Cannot sign." << std::endl; - break ; - default: std::cerr << "(EE) Unknown error when signing" << std::endl; - break ; - } - delete(dhitem); - return false; - } - - if(!mGixs->getKey(own_gxs_id,signature_key_public)) - { - std::cerr << " (EE) Could not retrieve own public key for ID = " << own_gxs_id << ". Giging up sending DH session params." << std::endl; - return false ; - } - - - assert(!(signature_key_public.keyFlags & RSTLV_KEY_TYPE_FULL)) ; - - dhitem->signature = signature ; - dhitem->gxs_key = signature_key_public ; - dhitem->PeerId(virtual_peer_id) ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Pushing DH session key item to pending distant messages..." << std::endl; - dhitem->print(std::cerr, 2) ; - std::cerr << std::endl; -#endif - pendingDHItems.push_back(dhitem) ; // sent off-mutex to avoid deadlocking. - - return true ; -} - -bool p3GxsTunnelService::locked_initDHSessionKey(DH *& dh) -{ - // We use our own DH group prime. This has been generated with command-line openssl and checked. - - static const std::string dh_prime_2048_hex = "B3B86A844550486C7EA459FA468D3A8EFD71139593FE1C658BBEFA9B2FC0AD2628242C2CDC2F91F5B220ED29AAC271192A7374DFA28CDDCA70252F342D0821273940344A7A6A3CB70C7897A39864309F6CAC5C7EA18020EF882693CA2C12BB211B7BA8367D5A7C7252A5B5E840C9E8F081469EBA0B98BCC3F593A4D9C4D5DF539362084F1B9581316C1F80FDAD452FD56DBC6B8ED0775F596F7BB22A3FE2B4753764221528D33DB4140DE58083DB660E3E105123FC963BFF108AC3A268B7380FFA72005A1515C371287C5706FFA6062C9AC73A9B1A6AC842C2764CDACFC85556607E86611FDF486C222E4896CDF6908F239E177ACC641FCBFF72A758D1C10CBB" ; - - if(dh != NULL) - { - DH_free(dh) ; - dh = NULL ; - } - - dh = DH_new() ; - - if(!dh) - { - std::cerr << " (EE) DH_new() failed." << std::endl; - return false ; - } - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - BN_hex2bn(&dh->p,dh_prime_2048_hex.c_str()) ; - BN_hex2bn(&dh->g,"5") ; -#else - BIGNUM *pp=NULL ; - BIGNUM *gg=NULL ; - - BN_hex2bn(&pp,dh_prime_2048_hex.c_str()) ; - BN_hex2bn(&gg,"5") ; - - DH_set0_pqg(dh,pp,NULL,gg) ; -#endif - - int codes = 0 ; - - if(!DH_check(dh, &codes) || codes != 0) - { - std::cerr << " (EE) DH check failed!" << std::endl; - return false ; - } - - if(!DH_generate_key(dh)) - { - std::cerr << " (EE) DH generate_key() failed! Error code = " << ERR_get_error() << std::endl; - return false ; - } -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " (II) DH Session key inited." << std::endl; -#endif - return true ; -} - -// Sends the item in clear. This is only used for DH key exchange. -// in this case only, the item's PeerId is equal to the virtual peer Id for the tunnel, -// since we ight not now the tunnel id yet. - -bool p3GxsTunnelService::locked_sendClearTunnelData(RsGxsTunnelDHPublicKeyItem *item) -{ -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService::sendClearTunnelData(): try sending item " << (void*)item << " to peer " << item->PeerId() << std::endl; -#endif - - // make a RsTurtleGenericData item out of it, and send it in clear. - // this is compatible with nodes older than 0.6.6 - RsTurtleGenericDataItem *gitem = new RsTurtleGenericDataItem ; - // force item priority to QOS_PRIORITY_RS_TURTLE_GENERIC_FAST_DATA to make the DH exchange faster on 0.6.6+ nodes - // this will not affect old nodes - gitem->setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_FAST_DATA); - - RsGxsTunnelSerialiser ser ; - - uint32_t rssize = ser.size(item); - - gitem->data_size = rssize + 8 ; - gitem->data_bytes = rs_malloc(rssize+8) ; - - if(gitem->data_bytes == NULL) - { - delete gitem ; - return false ; - } - // by convention, we use a IV of 0 for unencrypted data. - memset(gitem->data_bytes,0,8) ; - - if(!ser.serialise(item,&((uint8_t*)gitem->data_bytes)[8],&rssize)) - { - std::cerr << "(EE) Could not serialise item!!!" << std::endl; - delete gitem ; - return false; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " GxsTunnelService::sendClearTunnelData(): Sending clear data to virtual peer: " << item->PeerId() << std::endl; - std::cerr << " gitem->data_size = " << gitem->data_size << std::endl; - std::cerr << " data = " << RsUtil::BinToHex((unsigned char*)gitem->data_bytes,gitem->data_size,100) ; - std::cerr << std::endl; -#endif - mTurtle->sendTurtleData(item->PeerId(),gitem) ; - - return true ; -} - -// Sends this item using secured/authenticated method, thx to the establshed cryptographic channel. - -bool p3GxsTunnelService::locked_sendEncryptedTunnelData(RsGxsTunnelItem *item) -{ - RsGxsTunnelSerialiser ser; - - uint32_t rssize = ser.size(item); - RsTemporaryMemory buff(rssize) ; - - if(!ser.serialise(item,buff,&rssize)) - { - std::cerr << "(EE) GxsTunnelService::sendEncryptedTunnelData(): Could not serialise item!" << std::endl; - return false; - } - - uint8_t aes_key[GXS_TUNNEL_AES_KEY_SIZE] ; - uint64_t IV = 0; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "Sending encrypted data to tunnel with vpid " << item->PeerId() << std::endl; -#endif - - RsGxsTunnelId tunnel_id ( item->PeerId() ); - - std::map::iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it == _gxs_tunnel_contacts.end()) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Cannot find contact key info for tunnel id " - << tunnel_id << ". Cannot send message!" << std::endl; -#endif - return false; - } - if(it->second.status != RS_GXS_TUNNEL_STATUS_CAN_TALK) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(EE) Cannot talk to tunnel id " << tunnel_id << ". Tunnel status is: " << it->second.status << std::endl; -#endif - return false; - } - - it->second.total_sent += rssize ; // counts the size of clear data that is sent - - memcpy(aes_key,it->second.aes_key,GXS_TUNNEL_AES_KEY_SIZE) ; - RsPeerId virtual_peer_id = it->second.virtual_peer_id ; - - while(IV == 0) IV = RSRandom::random_u64() ; // make a random 8 bytes IV, that is not 0 - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService::sendEncryptedTunnelData(): tunnel found. Encrypting data." << std::endl; -#endif - - // Now encrypt this data using AES. - // - uint32_t encrypted_size = RsAES::get_buffer_size(rssize); - RsTemporaryMemory encrypted_data(encrypted_size) ; - - if(!RsAES::aes_crypt_8_16(buff,rssize,aes_key,(uint8_t*)&IV,encrypted_data,encrypted_size)) - { - std::cerr << "(EE) packet encryption failed." << std::endl; - return false; - } - - // make a TurtleGenericData item out of it: - // - - uint32_t data_size = encrypted_size + GXS_TUNNEL_ENCRYPTION_IV_SIZE + GXS_TUNNEL_ENCRYPTION_HMAC_SIZE ; - void *data_bytes = rs_malloc(data_size) ; - - if(data_bytes == NULL) - return false ; - - memcpy(& ((uint8_t*)data_bytes)[0] ,&IV,8) ; - - unsigned int md_len = GXS_TUNNEL_ENCRYPTION_HMAC_SIZE ; - HMAC(EVP_sha1(),aes_key,GXS_TUNNEL_AES_KEY_SIZE,encrypted_data,encrypted_size,&(((uint8_t*)data_bytes)[GXS_TUNNEL_ENCRYPTION_IV_SIZE]),&md_len) ; - - memcpy(& (((uint8_t*)data_bytes)[GXS_TUNNEL_ENCRYPTION_HMAC_SIZE+GXS_TUNNEL_ENCRYPTION_IV_SIZE]),encrypted_data,encrypted_size) ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Using IV: " << std::hex << IV << std::dec << std::endl; - std::cerr << " Using Key: " << RsUtil::BinToHex((char*)aes_key,GXS_TUNNEL_AES_KEY_SIZE) ; std::cerr << std::endl; - std::cerr << " hmac: " << RsUtil::BinToHex((char*)data_bytes,GXS_TUNNEL_ENCRYPTION_HMAC_SIZE) << std::endl; -#endif -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService::sendEncryptedTunnelData(): Sending encrypted data to virtual peer: " << virtual_peer_id << std::endl; - std::cerr << " data_size = " << data_size << std::endl; - std::cerr << " serialised data = " << RsUtil::BinToHex((unsigned char*)data_bytes,data_size,100) ; - std::cerr << std::endl; -#endif - - // We send the item through the turtle tunnel. We do that using the new 'fast' item type if the tunnel accepts it, and using the old slow one otherwise. - // Still if the tunnel hasn't been probed, we duplicate the packet using the new fast item format. The packet being received twice on the other side will - // be discarded with a warning. - // Note that because the data is deleted by sendTurtleData(), we need to send all packets at the end, and properly duplicate the data when needed. - -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 - RsTurtleGenericFastDataItem *gitem = new RsTurtleGenericFastDataItem; - gitem->data_bytes = data_bytes; - gitem->data_size = data_size ; -#else - RsTurtleGenericDataItem *gitem = NULL; - RsTurtleGenericFastDataItem *gitem2 = NULL; - - if(!it->second.accepts_fast_turtle_items) - { - std::cerr << "Sending old format (slow) item for packet IV=" << std::hex << IV << std::dec << " in tunnel VPID=" << it->second.virtual_peer_id << std::endl; - gitem = new RsTurtleGenericDataItem ; - - gitem->data_bytes = data_bytes; - gitem->data_size = data_size ; - } - - if(it->second.accepts_fast_turtle_items || !it->second.already_probed_for_fast_items) - { - std::cerr << "Sending new format (fast) item for packet IV=" << std::hex << IV << std::dec << " in tunnel VPID=" << it->second.virtual_peer_id << std::endl; - gitem2 = new RsTurtleGenericFastDataItem ; - - if(gitem != NULL) // duplicate the data because it was already sent in gitem. - { - gitem2->data_bytes = rs_malloc(data_size); - gitem2->data_size = data_size ; - memcpy(gitem2->data_bytes,data_bytes,data_size); - } - else - { - gitem2->data_bytes = data_bytes; - gitem2->data_size = data_size ; - } - - it->second.already_probed_for_fast_items = true; - - } - if(gitem2) mTurtle->sendTurtleData(virtual_peer_id,gitem2) ; -#endif - if(gitem) mTurtle->sendTurtleData(virtual_peer_id,gitem) ; - - return true ; -} - -bool p3GxsTunnelService::requestSecuredTunnel(const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, RsGxsTunnelId &tunnel_id, uint32_t service_id, uint32_t& error_code) -{ - // should be a parameter. - - std::list lst ; - mGixs->getOwnIds(lst) ; - - bool found = false ; - for(std::list::const_iterator it = lst.begin();it!=lst.end();++it) - if(*it == from_gxs_id) - { - found=true; - break ; - } - - if(!found) - { - std::cerr << " (EE) Cannot start distant chat, since GXS id " << from_gxs_id << " is not available." << std::endl; - error_code = RS_GXS_TUNNEL_ERROR_UNKNOWN_GXS_ID ; - return false ; - } - RsGxsId own_gxs_id = from_gxs_id ; - - startClientGxsTunnelConnection(to_gxs_id,own_gxs_id,service_id,tunnel_id) ; - - error_code = RS_GXS_TUNNEL_ERROR_NO_ERROR ; - - return true ; -} - -// This method generates an ID that should be unique for each packet sent to a same peer. Rather than a random value, -// we use this counter because outgoing items are sorted in a map by their counter value. Using an increasing value -// ensures that the packets are sent in the same order than received from the service. This can be useful in some cases, -// for instance when services split their items while expecting them to arrive in the same order. - -uint64_t p3GxsTunnelService::locked_getPacketCounter() -{ - return mCurrentPacketCounter++ ; -} - -bool p3GxsTunnelService::sendData(const RsGxsTunnelId &tunnel_id, uint32_t service_id, const uint8_t *data, uint32_t size) -{ - // make sure that the tunnel ID is registered. - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::sendData()" << std::endl; - std::cerr << " tunnel id : " << tunnel_id << std::endl; - std::cerr << " data size : " << size << std::endl; - std::cerr << " service id: " << std::hex << service_id << std::dec << std::endl; -#endif - - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - std::map::const_iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it == _gxs_tunnel_contacts.end()) - { - std::cerr << " (EE) no tunnel known with this ID. Sorry!" << std::endl; - return false ; - } - - // make sure the service is registered. - - if(mRegisteredServices.find(service_id) == mRegisteredServices.end()) - { - std::cerr << " (EE) no service registered with this ID. Please call rsGxsTunnel->registerClientService() at some point." << std::endl; - return false ; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " verifications fine! Storing in out queue with:" << std::endl; -#endif - - RsGxsTunnelDataItem *item = new RsGxsTunnelDataItem ; - - item->unique_item_counter = locked_getPacketCounter() ;// this allows to make the item unique, while respecting the packet order! - item->flags = 0; // not used yet. - item->service_id = service_id; - item->data_size = size; // encrypted data size - item->data = (uint8_t*)rs_malloc(size); // encrypted data - - if(item->data == NULL) - delete item ; - - item->PeerId(RsPeerId(tunnel_id)) ; - memcpy(item->data,data,size) ; - - GxsTunnelData& tdata( pendingGxsTunnelDataItems[item->unique_item_counter] ) ; - - tdata.data_item = item ; - tdata.last_sending_attempt = 0 ; // never sent until now - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " counter id : " << std::hex << item->unique_item_counter << std::dec << std::endl; -#endif - - return true ; -} - - -void p3GxsTunnelService::startClientGxsTunnelConnection(const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id,uint32_t service_id,RsGxsTunnelId& tunnel_id) -{ - // compute a random hash for that pair, and init the DH session for it so that we can recognise it when we get the virtual peer for it. - - RsFileHash hash = randomHashFromDestinationGxsId(to_gxs_id) ; - - tunnel_id = makeGxsTunnelId(from_gxs_id,to_gxs_id) ; - - { - RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - if(_gxs_tunnel_contacts.find(tunnel_id) != _gxs_tunnel_contacts.end()) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService:: asking GXS tunnel for a configuration that already exits.Ignoring." << std::endl; -#endif - return ; - } - } - - GxsTunnelPeerInfo info ; - - rstime_t now = time(NULL) ; - - info.last_contact = now ; - info.last_keep_alive_sent = now ; - info.status = RS_GXS_TUNNEL_STATUS_TUNNEL_DN ; - info.own_gxs_id = from_gxs_id ; - info.to_gxs_id = to_gxs_id ; - info.hash = hash ; - info.direction = RsTurtleGenericTunnelItem::DIRECTION_SERVER ; - info.virtual_peer_id.clear(); - info.client_services.insert(service_id) ; - - memset(info.aes_key,0,GXS_TUNNEL_AES_KEY_SIZE) ; - - { - RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - _gxs_tunnel_contacts[tunnel_id] = info ; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "Starting distant chat to " << to_gxs_id << ", hash = " << hash << ", from " << from_gxs_id << std::endl; - std::cerr << "Asking turtle router to monitor tunnels for hash " << hash << std::endl; -#endif - - // Now ask the turtle router to manage a tunnel for that hash. - - mTurtle->monitorTunnels(hash,this,false) ; -} - -TurtleFileHash p3GxsTunnelService::randomHashFromDestinationGxsId(const RsGxsId& destination) -{ - // This is in prevision for the "secured GXS tunnel" service, which will need a service ID to register, - // just like GRouter does. - - assert( destination.SIZE_IN_BYTES == 16) ; - assert(Sha1CheckSum::SIZE_IN_BYTES == 20) ; - - uint8_t bytes[20] ; - memcpy(&bytes[4],destination.toByteArray(),16) ; - - RAND_bytes(&bytes[0],4) ; // fill the 4 first bytes with random crap. Very important to allow tunnels from different sources and statistically avoid collisions. - - // We could rehash this, with a secret key to get a HMAC. That would allow to publish secret distant chat - // passphrases. I'll do this later if needed. - - return Sha1CheckSum(bytes) ; // this does not compute a hash, and that is on purpose. -} - -RsGxsId p3GxsTunnelService::destinationGxsIdFromHash(const TurtleFileHash& sum) -{ - assert( RsGxsId::SIZE_IN_BYTES == 16) ; - assert(Sha1CheckSum::SIZE_IN_BYTES == 20) ; - - return RsGxsId(&sum.toByteArray()[4]);// takes the last 16 bytes -} - -bool p3GxsTunnelService::getTunnelInfo(const RsGxsTunnelId& tunnel_id,GxsTunnelInfo& info) -{ - RS_STACK_MUTEX(mGxsTunnelMtx); - - std::map::const_iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it == _gxs_tunnel_contacts.end()) - return false ; - - info.destination_gxs_id = it->second.to_gxs_id; - info.source_gxs_id = it->second.own_gxs_id; - info.tunnel_status = it->second.status; - info.total_size_sent = it->second.total_sent; - info.total_size_received= it->second.total_received; - info.is_client_side = (it->second.direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT); - - // Data packets - - info.pending_data_packets = 0; - RsPeerId p(tunnel_id); - - for(auto it(pendingGxsTunnelDataItems.begin());it!=pendingGxsTunnelDataItems.end();++it) - if(it->second.data_item->PeerId() == p) - ++info.pending_data_packets ; - - info.total_data_packets_sent=0 ; - info.total_data_packets_received=0 ; - - return true ; -} - -bool p3GxsTunnelService::closeExistingTunnel(const RsGxsTunnelId& tunnel_id, uint32_t service_id) -{ - // two cases: - // - client needs to stop asking for tunnels => remove the hash from the list of tunnelled files - // - server needs to only close the window and let the tunnel die. But the window should only open - // if a message arrives. - - TurtleFileHash hash ; - TurtleVirtualPeerId vpid ; - bool close_tunnel = false ; - int direction ; - { - RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it == _gxs_tunnel_contacts.end()) - { - std::cerr << "(EE) Cannot close distant tunnel connection. No connection openned for tunnel id " << tunnel_id << std::endl; - - // We cannot stop tunnels, since their peer id is lost. Anyway, they'll die of starving. - - return false ; - } - vpid = it->second.virtual_peer_id ; - - std::map::const_iterator it2 = _gxs_tunnel_virtual_peer_ids.find(vpid) ; - - if(it2 != _gxs_tunnel_virtual_peer_ids.end()) - hash = it2->second.hash ; - else - hash = it->second.hash ; - - // check how many clients are used. If empty, close the tunnel - - std::set::iterator it3 = it->second.client_services.find(service_id) ; - - if(it3 == it->second.client_services.end()) - { - std::cerr << "(EE) service id not currently using that tunnel. This is an error." << std::endl; - return false; - } - - it->second.client_services.erase(it3) ; - direction = it->second.direction ; - - if(it->second.client_services.empty()) - close_tunnel = true ; - } - - if(close_tunnel) - { - // send a status item saying that we're closing the connection -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Sending a ACK to close the tunnel since we're managing it and it's not used by any service. tunnel id=." << tunnel_id << std::endl; -#endif - - RsGxsTunnelStatusItem *cs = new RsGxsTunnelStatusItem ; - - cs->status = RS_GXS_TUNNEL_FLAG_CLOSING_DISTANT_CONNECTION; - cs->PeerId(RsPeerId(tunnel_id)) ; - - locked_sendEncryptedTunnelData(cs) ; // that needs to be done off-mutex and before we close the tunnel also ignoring failure. - - if(direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER) // nothing more to do for server side. - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " This is client side. Stopping tunnel manageement for tunnel_id " << tunnel_id << std::endl; -#endif - mTurtle->stopMonitoringTunnels( hash ) ; // still valid if the hash is null - } - - RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it == _gxs_tunnel_contacts.end()) // server side. Nothing to do. - { - std::cerr << "(EE) Cannot close chat associated to tunnel id " << tunnel_id << ": not found." << std::endl; - return false ; - } - - _gxs_tunnel_contacts.erase(it) ; - - // GxsTunnelService::removeVirtualPeerId() will be called by the turtle service. - } - return true ; -} - -bool p3GxsTunnelService::getTunnelsInfo(std::vector &infos) -{ - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - for(std::map::const_iterator it(_gxs_tunnel_contacts.begin());it!=_gxs_tunnel_contacts.end();++it) - { - GxsTunnelInfo ti ; - - ti.tunnel_id = it->first ; - ti.destination_gxs_id = it->second.to_gxs_id ; - ti.source_gxs_id = it->second.own_gxs_id ; - ti.tunnel_status = it->second.status ; - ti.total_size_sent = it->second.total_sent ; - ti.total_size_received = it->second.total_received ; - - ti.pending_data_packets = 0; - RsPeerId p(it->first); - for(auto it(pendingGxsTunnelDataItems.begin());it!=pendingGxsTunnelDataItems.end();++it) - if(it->second.data_item->PeerId() == p) - ++ti.pending_data_packets ; - - ti.total_data_packets_sent =0; // not accounted for yet. - ti.total_data_packets_received=0 ; // not accounted for yet. - - infos.push_back(ti) ; - } - - return true ; -} - -void p3GxsTunnelService::debug_dump() -{ - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - rstime_t now = time(NULL) ; - - std::cerr << "p3GxsTunnelService::debug_dump()" << std::endl; - std::cerr << " Registered client services: " << std::endl; - - for(std::map::const_iterator it=mRegisteredServices.begin();it!=mRegisteredServices.end();++it) - std::cerr << std::hex << " " << it->first << " - " << (void*)it->second << std::dec << std::endl; - - std::cerr << " Active tunnels" << std::endl; - - for(std::map::const_iterator it=_gxs_tunnel_contacts.begin();it!=_gxs_tunnel_contacts.end();++it) - std::cerr << " tunnel_id=" << it->first << " vpid=" << it->second.virtual_peer_id << " status=" << it->second.status << " direction=" << it->second.direction << " last_contact=" << (now-it->second.last_contact) <<" secs ago. Last_keep_alive_sent:" << (now - it->second.last_keep_alive_sent) << " secs ago." << std::endl; - - std::cerr << " Virtual peers:" << std::endl; - - for(std::map::const_iterator it=_gxs_tunnel_virtual_peer_ids.begin();it!=_gxs_tunnel_virtual_peer_ids.end();++it) - std::cerr << " vpid=" << it->first << " to=" << it->second.gxs_id << " from=" << it->second.own_gxs_id << " tunnel_id=" << it->second.tunnel_id << " status=" << it->second.status << " direction=" << it->second.direction << " hash=" << it->second.hash << std::endl; - - std::cerr << " Pending items: " << std::endl; - std::cerr << " DH : " << pendingDHItems.size() << std::endl; - std::cerr << " Tunnel Management: " << pendingGxsTunnelItems.size() << std::endl; - std::cerr << " Data (client) : " << pendingGxsTunnelDataItems.size() << std::endl; -} - - - - - - - - - - - - - - - - diff --git a/libretroshare/src/gxstunnel/p3gxstunnel.h b/libretroshare/src/gxstunnel/p3gxstunnel.h deleted file mode 100644 index d6e200678..000000000 --- a/libretroshare/src/gxstunnel/p3gxstunnel.h +++ /dev/null @@ -1,274 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: distantchat.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2015 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -// Generic tunnel service -// -// Preconditions: -// * the secured tunnel service takes care of: -// - tunnel health: tunnels are kept alive using special items, re-openned when necessary, etc. -// - transport: items are ACK-ed and re-sent if never received -// - encryption: items are all encrypted and authenticated using PFS(DH)+HMAC(sha1)+AES(128) -// * each tunnel is associated to a specific GXS id on both sides. Consequently, services that request tunnels from different IDs to a -// server for the same GXS id need to be handled correctly. -// * client services must register to the secured tunnel service if they want to use it. -// * multiple services can use the same tunnel. Items contain a service Id that is obtained when registering to the secured tunnel service. -// -// GUI -// * the GUI should show for each tunnel: -// - starting and ending GXS ids -// - tunnel status (DH ok, closed from distant peer, locally closed, etc) -// - amount of data that is transferred in the tunnel -// - number of pending items (and total size) -// - number ACKed items both ways. -// -// We can use an additional tab "Authenticated tunnels" in the statistics->turtle window for that purpose. -// -// Interaction with services: -// -// Services request tunnels from a given GXS id and to a given GXS id. When ready, they get a handle (type = RsGxsTunnelId) -// -// Services send data in the tunnel using the virtual peer id -// -// Data is send to a service ID (could be any existing service ID). The endpoint of the tunnel must register each service, in order to -// allow the data to be transmitted/sent from/to that service. Otherwise an error is issued. -// -// Encryption -// * the whole tunnel traffic is encrypted using AES-128 with random IV -// * a random key is established using DH key exchange for each connection (establishment of a new virtual peer) -// * encrypted items are authenticated with HMAC(sha1). -// * DH public keys are the only chunks of data that travel un-encrypted along the tunnel. They are -// signed to avoid any MITM interactions. No time-stamp is used in DH exchange since a replay attack would not work. -// -// Algorithms -// -// * we need two layers: the turtle layer, and the GXS id layer. -// - for each pair of GXS ids talking, a single turtle tunnel is used -// - that tunnel can be shared by multiple services using it. -// - services are responsoble for asking tunnels and also droppping them when unused. -// - at the turtle layer, the tunnel will be effectively closed only when no service uses it. -// * IDs -// TurtleVirtualPeerId: -// - Used by tunnel service for each turtle tunnel -// - one virtual peer ID per GXS tunnel -// -// GxsTunnelId: -// - one GxsTunnelId per couple of GXS ids. But we also need to allow multiple services to use the tunnel. -// -// * at the turtle layer: -// - accept virtual peers from turtle tunnel service. The hash for that VP only depends on the server GXS id at server side, which is our -// own ID at server side, and destination ID at client side. What happens if two different clients request to talk to the same GXS id? (same hash) -// They should use different virtual peers, so it should be ok. -// -// Turtle hash: [ 0 ---------------15 16---19 ] -// Destination Random -// -// We Use 16 bytes to target the exact destination of the hash. The source part is just 4 arbitrary bytes that need to be different for all source -// IDs that come from the same peer, which is quite likely to be sufficient. The real source of the tunnel will make itself known when sending the -// DH key. -// -// * at the GXS layer -// - we should be able to have as many tunnels as they are different couples of GXS ids to interact. That means the tunnel should be determined -// by a mix between our own GXS id and the GXS id we're talking to. That is what the TunnelVirtualPeer is. -// -// -// RequestTunnel(source_own_id,destination_id) - -// | | -// +---------------------------> p3Turtle::monitorTunnels( hash(destination_id) ) | -// | | -// [Turtle async work] -------------------+ | Turtle layer: one virtual peer id -// | | | -// handleTunnelRequest() <-----------------------------------------------+ | | -// | | | -// +---------------- keep record in _gxs_tunnel_virtual_peer_id, initiate DH exchange | - -// | | -// handleDHPublicKey() <-----------------------------------------------------------------------------+ | -// | | -// +---------------- update _gxs_tunnel_contacts[ tunnel_hash = hash(own_id, destination_id) ] | GxsTunnelId level -// | | -// +---------------- notify client service that Peer(destination_id, tunnel_hash) is ready to talk to | -// - - -#include -#include -#include -#include - -class RsGixs ; - -static const uint32_t GXS_TUNNEL_AES_KEY_SIZE = 16 ; - -class p3GxsTunnelService: public RsGxsTunnelService, public RsTurtleClientService, public p3Service -{ -public: - explicit p3GxsTunnelService(RsGixs *pids) ; - virtual void connectToTurtleRouter(p3turtle *) override; - - uint16_t serviceId() const override { return RS_SERVICE_TYPE_GXS_TUNNEL ; } - - // Creates the invite if the public key of the distant peer is available. - // Om success, stores the invite in the map above, so that we can respond to tunnel requests. - // - virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,RsGxsTunnelId& tunnel_id,uint32_t service_id,uint32_t& error_code) override ; - virtual bool closeExistingTunnel(const RsGxsTunnelId &tunnel_id,uint32_t service_id) override ; - virtual bool getTunnelsInfo(std::vector& infos) override ; - virtual bool getTunnelInfo(const RsGxsTunnelId& tunnel_id,GxsTunnelInfo& info) override ; - virtual bool sendData(const RsGxsTunnelId& tunnel_id,uint32_t service_id,const uint8_t *data,uint32_t size) override ; - virtual bool registerClientService(uint32_t service_id,RsGxsTunnelClientService *service) override ; - - // derived from p3service - - virtual int tick() override; - virtual RsServiceInfo getServiceInfo() override; - -private: - void flush() ; - virtual void handleIncomingItem(const RsGxsTunnelId &tunnel_id, RsGxsTunnelItem *) ; - - class GxsTunnelPeerInfo - { - public: - GxsTunnelPeerInfo() - : last_contact(0), last_keep_alive_sent(0), status(0), direction(0) - , total_sent(0), total_received(0) - #ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 - , accepts_fast_turtle_items(false) - , already_probed_for_fast_items(false) - #endif - { - memset(aes_key, 0, GXS_TUNNEL_AES_KEY_SIZE); - } - - rstime_t last_contact ; // used to keep track of working connexion - rstime_t last_keep_alive_sent ; // last time we sent a keep alive packet. - - unsigned char aes_key[GXS_TUNNEL_AES_KEY_SIZE] ; - - uint32_t status ; // info: do we have a tunnel ? - RsPeerId virtual_peer_id; // given by the turtle router. Identifies the tunnel. - RsGxsId to_gxs_id; // gxs id we're talking to - RsGxsId own_gxs_id ; // gxs id we're using to talk. - RsTurtleGenericTunnelItem::Direction direction ; // specifiec wether we are client(managing the tunnel) or server. - TurtleFileHash hash ; // hash that is last used. This is necessary for handling tunnel establishment - std::set client_services ; // services that used this tunnel - std::map received_data_prints ; // list of recently received messages, to avoid duplicates. Kept for 20 mins at most. - uint32_t total_sent ; // total data sent to this peer - uint32_t total_received ; // total data received by this peer -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 - bool accepts_fast_turtle_items; // does the tunnel accept RsTurtleGenericFastDataItem type? - bool already_probed_for_fast_items; // has the tunnel been probed already? If not, a fast item will be sent -#endif - }; - - class GxsTunnelDHInfo - { - public: - GxsTunnelDHInfo() : dh(0), direction(0), status(0) {} - - DH *dh ; - RsGxsId gxs_id ; - RsGxsId own_gxs_id ; - RsGxsTunnelId tunnel_id ; // this is a proxy, since we cna always recompute that from the two previous values. - RsTurtleGenericTunnelItem::Direction direction ; - uint32_t status ; - TurtleFileHash hash ; - }; - - struct GxsTunnelData - { - RsGxsTunnelDataItem *data_item ; - rstime_t last_sending_attempt ; - }; - - // This maps contains the current peers to talk to with distant chat. - // - std::map _gxs_tunnel_contacts ; // current peers we can talk to - std::map _gxs_tunnel_virtual_peer_ids ; // current virtual peers. Used to figure out tunnels, etc. - - // List of items to be sent asap. Used to store items that we cannot pass directly to - // sendTurtleData(), because of Mutex protection. - - std::map pendingGxsTunnelDataItems ; // items that need provable transport and encryption - std::list pendingGxsTunnelItems ; // items that do not need provable transport, yet need encryption - std::list pendingDHItems ; - - // Overloaded from RsTurtleClientService - - virtual bool handleTunnelRequest(const RsFileHash &hash,const RsPeerId& peer_id) override; - virtual void receiveTurtleData(const RsTurtleGenericTunnelItem *item,const RsFileHash& hash,const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) override; - void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) override; - void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) override; - - // session handling handles - - void startClientGxsTunnelConnection(const RsGxsId &to_gxs_id, const RsGxsId& from_gxs_id, uint32_t service_id, RsGxsTunnelId &tunnel_id) ; - void locked_restartDHSession(const RsPeerId &virtual_peer_id, const RsGxsId &own_gxs_id) ; - - // utility functions - - static TurtleFileHash randomHashFromDestinationGxsId(const RsGxsId& destination) ; - static RsGxsId destinationGxsIdFromHash(const TurtleFileHash& sum) ; - - // Cryptography management - - void handleRecvDHPublicKey(RsGxsTunnelDHPublicKeyItem *item) ; - bool locked_sendDHPublicKey(const DH *dh, const RsGxsId& own_gxs_id, const RsPeerId& virtual_peer_id) ; - bool locked_initDHSessionKey(DH *&dh); - uint64_t locked_getPacketCounter(); - - TurtleVirtualPeerId virtualPeerIdFromHash(const TurtleFileHash& hash) ; // ... and to a hash for p3turtle - - // item handling - - void handleRecvStatusItem(const RsGxsTunnelId& id,RsGxsTunnelStatusItem *item) ; - void handleRecvTunnelDataItem(const RsGxsTunnelId& id,RsGxsTunnelDataItem *item) ; - void handleRecvTunnelDataAckItem(const RsGxsTunnelId &id, RsGxsTunnelDataAckItem *item); - - // Comunication with Turtle service - - bool locked_sendEncryptedTunnelData(RsGxsTunnelItem *item) ; - bool locked_sendClearTunnelData(RsGxsTunnelDHPublicKeyItem *item); // this limits the usage to DH items. Others should be encrypted! - -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 - bool handleEncryptedData(const uint8_t *data_bytes, uint32_t data_size, const TurtleFileHash& hash, const RsPeerId& virtual_peer_id, bool accepts_fast_items) ; -#else - bool handleEncryptedData(const uint8_t *data_bytes, uint32_t data_size, const TurtleFileHash& hash, const RsPeerId& virtual_peer_id) ; -#endif - - // local data - - p3turtle *mTurtle ; - RsGixs *mGixs ; - RsMutex mGxsTunnelMtx ; - - uint64_t mCurrentPacketCounter ; - - std::map mRegisteredServices ; - - void debug_dump(); - -public: - /// creates a unique tunnel ID from two GXS ids. - static RsGxsTunnelId makeGxsTunnelId( const RsGxsId &own_id, - const RsGxsId &distant_id ); -}; - diff --git a/libretroshare/src/gxstunnel/rsgxstunnelitems.cc b/libretroshare/src/gxstunnel/rsgxstunnelitems.cc deleted file mode 100644 index f86529c3b..000000000 --- a/libretroshare/src/gxstunnel/rsgxstunnelitems.cc +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxstunnel: rsgxstunnelitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2015 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include "util/rstime.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstypeserializer.h" -#include "util/rsprint.h" -#include "util/rsmemory.h" - -#include "gxstunnel/rsgxstunnelitems.h" - -//#define GXS_TUNNEL_ITEM_DEBUG 1 - -RsItem *RsGxsTunnelSerialiser::create_item(uint16_t service,uint8_t item_subtype) const -{ - if(service != RS_SERVICE_TYPE_GXS_TUNNEL) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA: return new RsGxsTunnelDataItem(); - case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK: return new RsGxsTunnelDataAckItem(); - case RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY: return new RsGxsTunnelDHPublicKeyItem(); - case RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS: return new RsGxsTunnelStatusItem(); - default: - return NULL ; - } -} - -RsGxsTunnelDHPublicKeyItem::~RsGxsTunnelDHPublicKeyItem() -{ - BN_free(public_key) ; -} - -void RsGxsTunnelDHPublicKeyItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,public_key,"public_key") ; - RsTypeSerializer::serial_process(j,ctx,signature,"signature") ; - RsTypeSerializer::serial_process(j,ctx,gxs_key,"gxs_key") ; -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, BIGNUM * const & member) -{ - uint32_t s = BN_num_bytes(member) ; - - if(size < offset + 4 + s) - return false ; - - bool ok = true ; - ok &= setRawUInt32(data, size, &offset, s); - - BN_bn2bin(member,&((unsigned char *)data)[offset]) ; - offset += s ; - - return ok; -} -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, BIGNUM *& member) -{ - uint32_t s=0 ; - bool ok = true ; - ok &= getRawUInt32(data, size, &offset, &s); - - if(s > size || size - s < offset) - return false ; - - member = BN_bin2bn(&((unsigned char *)data)[offset],s,NULL) ; - offset += s ; - - return ok; -} -template<> uint32_t RsTypeSerializer::serial_size(BIGNUM * const & member) -{ - return 4 + BN_num_bytes(member) ; -} -template<> void RsTypeSerializer::print_data(const std::string& name,BIGNUM * const & /* member */) -{ - std::cerr << "[BIGNUM] : " << name << std::endl; -} - -RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(BIGNUM*) -RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(BIGNUM*) - -void RsGxsTunnelStatusItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,status,"status") ; -} - -void RsGxsTunnelDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,unique_item_counter,"unique_item_counter") ; - RsTypeSerializer::serial_process(j,ctx,flags ,"flags") ; - RsTypeSerializer::serial_process(j,ctx,service_id ,"service_id") ; - - RsTypeSerializer::TlvMemBlock_proxy mem(data,data_size) ; - RsTypeSerializer::serial_process(j,ctx,mem,"data") ; -} -void RsGxsTunnelDataAckItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,unique_item_counter,"unique_item_counter") ; -} - - - - - - - - - - - - - - - - - diff --git a/libretroshare/src/gxstunnel/rsgxstunnelitems.h b/libretroshare/src/gxstunnel/rsgxstunnelitems.h deleted file mode 100644 index a098c8c05..000000000 --- a/libretroshare/src/gxstunnel/rsgxstunnelitems.h +++ /dev/null @@ -1,151 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: rsgxstunnelitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2015 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" -#include "rsitems/rsitem.h" - -#include "retroshare/rstypes.h" -#include "serialiser/rstlvkeys.h" -#include "serialiser/rsserial.h" - -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvfileitem.h" - -/* chat Flags */ -const uint32_t RS_GXS_TUNNEL_FLAG_CLOSING_DISTANT_CONNECTION = 0x0400; -const uint32_t RS_GXS_TUNNEL_FLAG_ACK_DISTANT_CONNECTION = 0x0800; -const uint32_t RS_GXS_TUNNEL_FLAG_KEEP_ALIVE = 0x1000; - -const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_DATA = 0x01 ; -const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY = 0x02 ; -const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS = 0x03 ; -const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK = 0x04 ; - -typedef uint64_t GxsTunnelDHSessionId ; - -class RsGxsTunnelItem: public RsItem -{ - public: - explicit RsGxsTunnelItem(uint8_t item_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_GXS_TUNNEL,item_subtype) - { - setPriorityLevel(QOS_PRIORITY_RS_CHAT_ITEM) ; - } - - virtual ~RsGxsTunnelItem() {} - virtual void clear() {} -}; - -/*! - * For sending distant communication data. The item is not encrypted after being serialised, but the data it. - * The MAC is computed over encrypted data using the PFS key. All other items (except DH keys) are serialised, encrypted, and - * sent as data in a RsGxsTunnelDataItem. - * - * @see p3GxsTunnelService - */ -class RsGxsTunnelDataItem: public RsGxsTunnelItem -{ -public: - RsGxsTunnelDataItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DATA), unique_item_counter(0), flags(0), service_id(0), data_size(0), data(NULL) {} - explicit RsGxsTunnelDataItem(uint8_t subtype) :RsGxsTunnelItem(subtype) , unique_item_counter(0), flags(0), service_id(0), data_size(0), data(NULL) {} - - virtual ~RsGxsTunnelDataItem() {} - virtual void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint64_t unique_item_counter; // this allows to make the item unique - uint32_t flags; // mainly NEEDS_HACK? - uint32_t service_id ; - uint32_t data_size ; // encrypted data size - unsigned char *data ; // encrypted data -}; - -// Used to send status of connection. This can be closing orders, flushing orders, etc. -// These items are always sent encrypted. - -class RsGxsTunnelStatusItem: public RsGxsTunnelItem -{ - public: - RsGxsTunnelStatusItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS) , status(0) {} - RsGxsTunnelStatusItem(void *data,uint32_t size) ; // deserialization - - virtual ~RsGxsTunnelStatusItem() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t status ; -}; - -// Used to confirm reception of an encrypted item. - -class RsGxsTunnelDataAckItem: public RsGxsTunnelItem -{ - public: - RsGxsTunnelDataAckItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK), unique_item_counter(0) {} - RsGxsTunnelDataAckItem(void *data,uint32_t size) ; // deserialization - - virtual ~RsGxsTunnelDataAckItem() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint64_t unique_item_counter ; // unique identifier for that item -}; - - -// This class contains the public Diffie-Hellman parameters to be sent -// when performing a DH agreement over a distant chat tunnel. -// -class RsGxsTunnelDHPublicKeyItem: public RsGxsTunnelItem -{ - public: - RsGxsTunnelDHPublicKeyItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY), public_key(NULL) {} - RsGxsTunnelDHPublicKeyItem(void *data,uint32_t size) ; // deserialization - - virtual ~RsGxsTunnelDHPublicKeyItem() ; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // Private data to DH public key item - // - BIGNUM *public_key ; - - RsTlvKeySignature signature ; // signs the public key in a row. - RsTlvPublicRSAKey gxs_key ; // public key of the signer - - private: - // make the object non copy-able - RsGxsTunnelDHPublicKeyItem(const RsGxsTunnelDHPublicKeyItem&) : RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY), public_key(NULL) {} - const RsGxsTunnelDHPublicKeyItem& operator=(const RsGxsTunnelDHPublicKeyItem&) { public_key = NULL; return *this ;} -}; - -class RsGxsTunnelSerialiser: public RsServiceSerializer -{ -public: - RsGxsTunnelSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_GXS_TUNNEL) {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const ; -}; - diff --git a/libretroshare/src/jsonapi/jsonapi.cpp b/libretroshare/src/jsonapi/jsonapi.cpp deleted file mode 100644 index 3fc54f6b0..000000000 --- a/libretroshare/src/jsonapi/jsonapi.cpp +++ /dev/null @@ -1,835 +0,0 @@ -/* - * RetroShare JSON API - * - * Copyright (C) 2018-2020 Gioacchino Mazzurco - * Copyright (C) 2019-2020 Asociación Civil Altermundi - * - * 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, version 3. - * - * 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 - * - * SPDX-FileCopyrightText: 2004-2020 RetroShare Team - * SPDX-License-Identifier: AGPL-3.0-only - */ - -#include -#include -#include -#include -#include -#include - - -#include "jsonapi.h" - -#include "util/rsjson.h" -#include "retroshare/rsfiles.h" -#include "util/radix64.h" -#include "retroshare/rsinit.h" -#include "util/rsnet.h" -#include "retroshare/rsiface.h" -#include "retroshare/rsinit.h" -#include "util/rsurl.h" -#include "util/rstime.h" -#include "retroshare/rsevents.h" -#include "retroshare/rsversion.h" - -// Generated at compile time -#include "jsonapi-includes.inl" - -/*extern*/ RsJsonApi* rsJsonApi = nullptr; - -const std::string RsJsonApi::DEFAULT_BINDING_ADDRESS = "127.0.0.1"; - -/*static*/ const std::multimap -JsonApiServer::corsHeaders = -{ - { "Access-Control-Allow-Origin", "*" }, - { "Access-Control-Allow-Methods", "GET, POST, OPTIONS"}, - { "Access-Control-Allow-Headers", "Authorization,DNT,User-Agent," - "X-Requested-With,If-Modified-Since," - "Cache-Control,Content-Type,Range" }, - { "Access-Control-Expose-Headers", "Content-Length,Content-Range" } -}; - -/*static*/ const std::multimap -JsonApiServer::corsOptionsHeaders = -{ - { "Access-Control-Allow-Origin", "*" }, - { "Access-Control-Allow-Methods", "GET, POST, OPTIONS"}, - { "Access-Control-Allow-Headers", "Authorization,DNT,User-Agent," - "X-Requested-With,If-Modified-Since," - "Cache-Control,Content-Type,Range" }, - { "Access-Control-Max-Age", "1728000" }, // 20 days - { "Content-Type", "text/plain; charset=utf-8" }, - { "Content-Length", "0" } -}; - -/* static */ const RsJsonApiErrorCategory RsJsonApiErrorCategory::instance; - -#define INITIALIZE_API_CALL_JSON_CONTEXT \ - RsGenericSerializer::SerializeContext cReq( \ - nullptr, 0, \ - RsSerializationFlags::YIELDING ); \ - RsJson& jReq(cReq.mJson); \ - if(session->get_request()->get_method() == "GET") \ - { \ - const std::string jrqp(session->get_request()->get_query_parameter("jsonData")); \ - jReq.Parse(jrqp.c_str(), jrqp.size()); \ - } \ - else \ - jReq.Parse(reinterpret_cast(body.data()), body.size()); \ -\ - RsGenericSerializer::SerializeContext cAns; \ - RsJson& jAns(cAns.mJson); \ -\ - /* if caller specified caller_data put it back in the answhere */ \ - const char kcd[] = "caller_data"; \ - if(jReq.HasMember(kcd)) \ - jAns.AddMember(kcd, jReq[kcd], jAns.GetAllocator()) - -#define DEFAULT_API_CALL_JSON_RETURN(RET_CODE) \ - std::stringstream ss; \ - ss << jAns; \ - std::string&& ans(ss.str()); \ - auto headers = corsHeaders; \ - headers.insert({ "Content-Type", "application/json" }); \ - headers.insert({ "Content-Length", std::to_string(ans.length()) }); \ - session->close(RET_CODE, ans, headers) - - -/*static*/ bool JsonApiServer::checkRsServicePtrReady( - const void* serviceInstance, const std::string& serviceName, - RsGenericSerializer::SerializeContext& ctx, - const std::shared_ptr session ) -{ - if(serviceInstance) return true; - - std::string jsonApiError = __PRETTY_FUNCTION__; - jsonApiError += "Service: "; - jsonApiError += serviceName; - jsonApiError += " not initialized!"; - - RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON); - RS_SERIAL_PROCESS(jsonApiError); - - RsJson& jAns(ctx.mJson); - DEFAULT_API_CALL_JSON_RETURN(rb::CONFLICT); - return false; -} - -void JsonApiServer::unProtectedRestart() -{ - /* Extremely sensitive stuff! - * Make sure you read documentation in header before changing or use!! */ - - fullstop(); - RsThread::start("JSON API Server"); -} - -bool RsJsonApi::parseToken( - const std::string& clear_token, std::string& user,std::string& passwd ) -{ - auto colonIndex = std::string::npos; - const auto tkLen = clear_token.length(); - - for(uint32_t i=0; i < tkLen; ++i) - if(clear_token[i] == ':') { colonIndex = i; break; } - - user = clear_token.substr(0, colonIndex); - - if(colonIndex < tkLen) - passwd = clear_token.substr(colonIndex + 1); - - return true; -} - -JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"), - mService(nullptr), - mListeningPort(RsJsonApi::DEFAULT_PORT), - mBindingAddress(RsJsonApi::DEFAULT_BINDING_ADDRESS), - mRestartReqTS(0) -{ -#if defined(RS_THREAD_FORCE_STOP) && defined(RS_JSONAPI_DEBUG_SERVICE_STOP) - /* When called in bursts it seems that Restbed::Service::stop() doesn't - * always does the job, to debug those cases it has been useful to ask - * RsThread to force it to stop for us. */ - RsThread::setStopTimeout(10); -#endif - -#if !RS_VERSION_AT_LEAST(0,6,6) - registerHandler("/rsLoginHelper/createLocation", - [this](const std::shared_ptr session) - { - auto reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( static_cast(reqSize), [this]( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - RsLoginHelper::Location location; - std::string password; - std::string errorMessage; - bool makeHidden = false; - bool makeAutoTor = false; - std::string createToken; - - // deserialize input parameters from JSON - { - RsGenericSerializer::SerializeContext& ctx(cReq); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON); - RS_SERIAL_PROCESS(location); - RS_SERIAL_PROCESS(password); - RS_SERIAL_PROCESS(makeHidden); - RS_SERIAL_PROCESS(makeAutoTor); - RS_SERIAL_PROCESS(createToken); - } - - // call retroshare C++ API - bool retval = rsLoginHelper->createLocation( - location, password, errorMessage, makeHidden, - makeAutoTor ); - - std::string tokenUser, tokenPw; - if(retval && parseToken(createToken, tokenUser, tokenPw)) - authorizeUser(tokenUser,tokenPw); - - // serialize out parameters and return value to JSON - { - RsGenericSerializer::SerializeContext& ctx(cAns); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON); - RS_SERIAL_PROCESS(location); - RS_SERIAL_PROCESS(errorMessage); - RS_SERIAL_PROCESS(retval); - } - - // return them to the API caller - DEFAULT_API_CALL_JSON_RETURN(rb::OK); - } ); - }, false); -#endif // !RS_VERSION_AT_LEAST(0,6,6) - - registerHandler("/rsLoginHelper/createLocationV2", - [this](const std::shared_ptr session) - { - auto reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( static_cast(reqSize), [this]( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - RsPeerId locationId; - RsPgpId pgpId; - std::string locationName; - std::string pgpName; - std::string password; - - // JSON API only - std::string apiUser; - std::string apiPass; - - // deserialize input parameters from JSON - { - RsGenericSerializer::SerializeContext& ctx(cReq); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON); - RS_SERIAL_PROCESS(locationId); - RS_SERIAL_PROCESS(pgpId); - RS_SERIAL_PROCESS(locationName); - RS_SERIAL_PROCESS(pgpName); - RS_SERIAL_PROCESS(password); - - // JSON API only - RS_SERIAL_PROCESS(apiUser); - RS_SERIAL_PROCESS(apiPass); - } - - std::error_condition retval; - - if(apiUser.empty()) - retval = RsJsonApiErrorNum::TOKEN_FORMAT_INVALID; - - if(!retval) - retval = badApiCredientalsFormat(apiUser, apiPass); - - if(!retval) // call retroshare C++ API - retval = rsLoginHelper->createLocationV2( - locationId, pgpId, locationName, pgpName, password ); - - if(!retval) retval = authorizeUser(apiUser, apiPass); - - // serialize out parameters and return value to JSON - { - RsGenericSerializer::SerializeContext& ctx(cAns); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON); - RS_SERIAL_PROCESS(locationId); - RS_SERIAL_PROCESS(pgpId); - RS_SERIAL_PROCESS(retval); - } - - // return them to the API caller - DEFAULT_API_CALL_JSON_RETURN(rb::OK); - } ); - }, false); - - registerHandler("/rsControl/rsGlobalShutDown", - [](const std::shared_ptr session) - { - auto reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( static_cast(reqSize), []( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - DEFAULT_API_CALL_JSON_RETURN(rb::OK); - - /* Wrap inside RsThread::async because this call - * RsThread::fullstop() also on JSON API server thread. - * Calling RsThread::fullstop() from it's own thread should never - * happen and if it happens an error message is printed - * accordingly by RsThread::fullstop() */ - RsThread::async([](){ rsControl->rsGlobalShutDown(); }); - } ); - }, true); - - registerHandler("/rsFiles/getFileData", - [](const std::shared_ptr session) - { - auto reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( static_cast(reqSize), []( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - if(!checkRsServicePtrReady(rsFiles, "rsFiles", cAns, session)) - return; - - RsFileHash hash; - uint64_t offset; - uint32_t requested_size; - bool retval = false; - std::string errorMessage; - std::string base64data; - - // deserialize input parameters from JSON - { - RsGenericSerializer::SerializeContext& ctx(cReq); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON); - RS_SERIAL_PROCESS(hash); - RS_SERIAL_PROCESS(offset); - RS_SERIAL_PROCESS(requested_size); - } - - if(requested_size > 10485760) - errorMessage = "requested_size is too big! Better less then 1M"; - else - { - std::vector buffer(requested_size); - - // call retroshare C++ API - retval = rsFiles->getFileData( - hash, offset, requested_size, buffer.data()); - - Radix64::encode(buffer.data(), requested_size, base64data); - } - - // serialize out parameters and return value to JSON - { - RsGenericSerializer::SerializeContext& ctx(cAns); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON); - RS_SERIAL_PROCESS(retval); - RS_SERIAL_PROCESS(requested_size); - RS_SERIAL_PROCESS(base64data); - if(!errorMessage.empty()) RS_SERIAL_PROCESS(errorMessage); - } - - DEFAULT_API_CALL_JSON_RETURN(rb::OK); - } ); - }, true); - - registerHandler("/rsEvents/registerEventsHandler", - [this](const std::shared_ptr session) - { - const std::weak_ptr weakService(mService); - const std::multimap headers - { - { "Connection", "keep-alive" }, - { "Content-Type", "text/event-stream" } - }; - session->yield(rb::OK, headers); - - size_t reqSize = static_cast( - session->get_request()->get_header("Content-Length", 0) ); - session->fetch( reqSize, [weakService]( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - if( !checkRsServicePtrReady( - rsEvents, "rsEvents", cAns, session ) ) - return; - - RsEventType eventType = RsEventType::__NONE; - - // deserialize input parameters from JSON - { - RsGenericSerializer::SerializeContext& ctx(cReq); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON); - RS_SERIAL_PROCESS(eventType); - } - - const std::weak_ptr weakSession(session); - RsEventsHandlerId_t hId = rsEvents->generateUniqueHandlerId(); - std::function)> multiCallback = - [weakSession, weakService, hId]( - std::shared_ptr event ) - { - auto lService = weakService.lock(); - if(!lService || lService->is_down()) - { - if(rsEvents) rsEvents->unregisterEventsHandler(hId); - return; - } - - lService->schedule( [weakSession, hId, event]() - { - auto session = weakSession.lock(); - if(!session || session->is_closed()) - { - if(rsEvents) rsEvents->unregisterEventsHandler(hId); - return; - } - - RsGenericSerializer::SerializeContext ctx; - RsTypeSerializer::serial_process( - RsGenericSerializer::TO_JSON, ctx, - *const_cast(event.get()), "event" ); - - std::stringstream message; - message << "data: " << compactJSON << ctx.mJson << "\n\n"; - - session->yield(message.str()); - } ); - }; - - std::error_condition retval = rsEvents->registerEventsHandler( - multiCallback, hId, eventType ); - - { - RsGenericSerializer::SerializeContext& ctx(cAns); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON); - RS_SERIAL_PROCESS(retval); - } - - // return them to the API caller - std::stringstream message; - message << "data: " << compactJSON << cAns.mJson << "\n\n"; - session->yield(message.str()); - } ); - }, true); - - registerHandler("/rsJsonApi/restart", - [this](const std::shared_ptr session) - { - auto reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( static_cast(reqSize), [this]( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - std::error_condition retval; - - const auto now = time(nullptr); - if(mRestartReqTS.exchange(now) + RESTART_BURST_PROTECTION > now) - retval = RsJsonApiErrorNum::NOT_A_MACHINE_GUN; - - // serialize out parameters and return value to JSON - { - RsGenericSerializer::SerializeContext& ctx(cAns); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON); - RS_SERIAL_PROCESS(retval); - } - - DEFAULT_API_CALL_JSON_RETURN(rb::OK); - - /* Wrap inside RsThread::async because this call fullstop() on - * JSON API server thread. - * Calling RsThread::fullstop() from it's own thread should never - * happen and if it happens an error message is printed - * accordingly by RsThread::fullstop() */ - if(!retval) RsThread::async([this](){ unProtectedRestart(); }); - } ); - }, true); - -// Generated at compile time -#include "jsonapi-wrappers.inl" -} - -void JsonApiServer::registerHandler( - const std::string& path, - const std::function)>& handler, - bool requiresAutentication ) -{ - std::shared_ptr resource(new rb::Resource); - resource->set_path(path); - resource->set_method_handler("GET", handler); - resource->set_method_handler("POST", handler); - resource->set_method_handler("OPTIONS", handleCorsOptions); - - if(requiresAutentication) - resource->set_authentication_handler( - [this, path]( - const std::shared_ptr session, - const std::function)>& callback ) - { - /* Declare outside the lambda to avoid returning a dangling - * reference */ - RsWarn tWarn; - const auto authFail = - [&](int status) -> std::ostream& - { - /* Capture session by reference as it is cheaper then copying - * shared_ptr by value which is not needed in this case */ - - session->close(status, corsOptionsHeaders); - return tWarn << "JsonApiServer authentication handler " - "blocked an attempt to call JSON API " - "authenticated method: " << path; - }; - - if(session->get_request()->get_method() == "OPTIONS") - { - callback(session); - return; - } - - if(!rsLoginHelper->isLoggedIn()) - { - authFail(rb::CONFLICT) << " before RetroShare login" - << std::endl; - return; - } - - std::istringstream authHeader; - authHeader.str(session->get_request()->get_header("Authorization")); - - std::string authToken; - std::getline(authHeader, authToken, ' '); - - if(authToken != "Basic") - { - authFail(rb::UNAUTHORIZED) - << " with wrong Authorization header: " - << authHeader.str() << std::endl; - return; - } - - std::getline(authHeader, authToken, ' '); - authToken = decodeToken(authToken); - - std::error_condition ec; - if(isAuthTokenValid(authToken, ec)) callback(session); - else - { - std::string tUser; - parseToken(authToken, tUser, RS_DEFAULT_STORAGE_PARAM(std::string)); - authFail(rb::UNAUTHORIZED) - << " user: " << tUser << ec << std::endl; - } - } ); - - mResources.push_back(resource); -} - -void JsonApiServer::setNewAccessRequestCallback( - const std::function& callback ) -{ mNewAccessRequestCallback = callback; } - -/*static*/ std::error_condition JsonApiServer::badApiCredientalsFormat( - const std::string& user, const std::string& passwd ) -{ - if(user.find(':') < std::string::npos) - return RsJsonApiErrorNum::API_USER_CONTAIN_COLON; - - if(user.empty()) - RsWarn() << __PRETTY_FUNCTION__ << " User is empty, are you sure " - << "this what you wanted?" << std::endl; - - if(passwd.empty()) - RsWarn() << __PRETTY_FUNCTION__ << " Password is empty, are you sure " - << "this what you wanted?" << std::endl; - - return std::error_condition(); -} - -std::error_condition JsonApiServer::requestNewTokenAutorization( - const std::string& user, const std::string& passwd ) -{ - auto ec = badApiCredientalsFormat(user, passwd); - if(ec) return ec; - - if(!rsLoginHelper->isLoggedIn()) - return RsJsonApiErrorNum::CANNOT_EXECUTE_BEFORE_RS_LOGIN; - - if(mNewAccessRequestCallback(user, passwd)) - return authorizeUser(user, passwd); - - return RsJsonApiErrorNum::AUTHORIZATION_REQUEST_DENIED; -} - -bool JsonApiServer::isAuthTokenValid( - const std::string& token, std::error_condition& error ) -{ - RS_STACK_MUTEX(configMutex); - - const auto failure = [&error](RsJsonApiErrorNum e) -> bool - { - error = e; - return false; - }; - - const auto success = [&error]() - { - error.clear(); - return true; - }; - - std::string user,passwd; - if(!parseToken(token, user, passwd)) - return failure(RsJsonApiErrorNum::TOKEN_FORMAT_INVALID); - - auto it = mAuthTokenStorage.mAuthorizedTokens.find(user); - if(it == mAuthTokenStorage.mAuthorizedTokens.end()) - return failure(RsJsonApiErrorNum::UNKNOWN_API_USER); - - // attempt avoiding +else CRYPTO_memcmp+ being optimized away - int noOptimiz = 1; - - /* Do not use mAuthTokenStorage.mAuthorizedTokens.count(token), because - * std::string comparison is usually not constant time on content to be - * faster, so an attacker may use timings to guess authorized tokens */ - - if( passwd.size() == it->second.size() && - ( noOptimiz = CRYPTO_memcmp( - passwd.data(), it->second.data(), it->second.size() ) ) == 0 ) - return success(); - // Make token size guessing harder - else noOptimiz = CRYPTO_memcmp(passwd.data(), passwd.data(), passwd.size()); - - /* At this point we are sure password is wrong, and one could think to - * plainly `return false` still this ugly and apparently unuseful extra - * calculation is here to avoid `else CRYPTO_memcmp` being optimized away, - * so a pontential attacker cannot guess password size based on timing */ - return static_cast(noOptimiz) + 1 == 0 ? - success() : failure(RsJsonApiErrorNum::WRONG_API_PASSWORD); -} - -std::map JsonApiServer::getAuthorizedTokens() -{ - RS_STACK_MUTEX(configMutex); - return mAuthTokenStorage.mAuthorizedTokens; -} - -bool JsonApiServer::revokeAuthToken(const std::string& token) -{ - RS_STACK_MUTEX(configMutex); - if(mAuthTokenStorage.mAuthorizedTokens.erase(token)) - { - IndicateConfigChanged(); - return true; - } - return false; -} - -void JsonApiServer::connectToConfigManager(p3ConfigMgr& cfgmgr) -{ - cfgmgr.addConfiguration("jsonapi.cfg",this); - - RsFileHash hash; - loadConfiguration(hash); -} - -std::error_condition JsonApiServer::authorizeUser( - const std::string& user, const std::string& passwd ) -{ - auto ec = badApiCredientalsFormat(user, passwd); - if(ec) return ec; - - RS_STACK_MUTEX(configMutex); - - std::string& p(mAuthTokenStorage.mAuthorizedTokens[user]); - if(p != passwd) - { - p = passwd; - IndicateConfigChanged(); - } - return ec; -} - -/*static*/ std::string JsonApiServer::decodeToken(const std::string& radix64_token) -{ - std::vector decodedVect(Radix64::decode(radix64_token)); - std::string decodedToken( - reinterpret_cast(&decodedVect[0]), - decodedVect.size() ); - return decodedToken; -} - -RsSerialiser* JsonApiServer::setupSerialiser() -{ - RsSerialiser* rss = new RsSerialiser; - rss->addSerialType(new JsonApiConfigSerializer); - return rss; -} - -bool JsonApiServer::saveList(bool& cleanup, std::list& saveItems) -{ - cleanup = false; - configMutex.lock(); - saveItems.push_back(&mAuthTokenStorage); - return true; -} - -bool JsonApiServer::loadList(std::list& loadList) -{ - for(RsItem* it : loadList) - switch (static_cast(it->PacketSubType())) - { - case JsonApiItemsType::AuthTokenItem: - mAuthTokenStorage = *static_cast(it); - delete it; - break; - default: - delete it; - break; - } - return true; -} - -void JsonApiServer::saveDone() { configMutex.unlock(); } - -void JsonApiServer::handleCorsOptions( - const std::shared_ptr session ) -{ session->close(rb::NO_CONTENT, corsOptionsHeaders); } - -void JsonApiServer::registerResourceProvider(const JsonApiResourceProvider& rp) -{ mResourceProviders.insert(rp); } -void JsonApiServer::unregisterResourceProvider(const JsonApiResourceProvider& rp) -{ mResourceProviders.erase(rp); } -bool JsonApiServer::hasResourceProvider(const JsonApiResourceProvider& rp) -{ return mResourceProviders.find(rp) != mResourceProviders.end(); } - -std::vector > JsonApiServer::getResources() const -{ - auto tab = mResources; - - for(auto& rp: mResourceProviders) - for(auto r: rp.get().getResources()) tab.push_back(r); - - return tab; -} - -std::error_condition JsonApiServer::restart() -{ - const auto now = time(nullptr); - if(mRestartReqTS.exchange(now) + RESTART_BURST_PROTECTION > now) - return RsJsonApiErrorNum::NOT_A_MACHINE_GUN; - - unProtectedRestart(); - return std::error_condition(); -} - -void JsonApiServer::onStopRequested() -{ - auto tService = std::atomic_exchange( - &mService, std::shared_ptr(nullptr) ); - if(tService) tService->stop(); -} - -uint16_t JsonApiServer::listeningPort() const { return mListeningPort; } -void JsonApiServer::setListeningPort(uint16_t p) { mListeningPort = p; } -void JsonApiServer::setBindingAddress(const std::string& bindAddress) -{ mBindingAddress = bindAddress; } -std::string JsonApiServer::getBindingAddress() const { return mBindingAddress; } - -void JsonApiServer::run() -{ - auto settings = std::make_shared(); - settings->set_port(mListeningPort); - settings->set_bind_address(mBindingAddress); - settings->set_default_header("Connection", "close"); - - auto tService = std::make_shared(); - - for(auto& r: getResources()) tService->publish(r); - - try - { - RsUrl apiUrl; apiUrl.setScheme("http").setHost(mBindingAddress) - .setPort(mListeningPort); - RsInfo() << __PRETTY_FUNCTION__ << " JSON API server listening on " - << apiUrl.toString() << std::endl; - - /* re-allocating mService is important because it deletes the existing - * service and therefore leaves the listening port open */ - auto tExpected = std::shared_ptr(nullptr); - if(atomic_compare_exchange_strong(&mService, &tExpected, tService)) - tService->start(settings); - else - { - RsErr() << __PRETTY_FUNCTION__ << " mService was expected to be " - << " null, instead we got: " << tExpected - << " something wrong happened JsonApiServer won't start" - << std::endl; - print_stacktrace(); - } - } - catch(std::exception& e) - { - RsErr() << __PRETTY_FUNCTION__ << " Failure starting JSON API server: " - << e.what() << std::endl; - print_stacktrace(); - return; - } - - RsDbg() << __PRETTY_FUNCTION__ << " finished!" << std::endl; -} - -/*static*/ void RsJsonApi::version( - uint32_t& major, uint32_t& minor, uint32_t& mini, std::string& extra, - std::string& human ) -{ - major = RS_MAJOR_VERSION; - minor = RS_MINOR_VERSION; - mini = RS_MINI_VERSION; - extra = RS_EXTRA_VERSION; - human = RS_HUMAN_READABLE_VERSION; -} - -std::error_condition RsJsonApiErrorCategory::default_error_condition(int ev) const noexcept -{ - switch(static_cast(ev)) - { - case RsJsonApiErrorNum::TOKEN_FORMAT_INVALID: // fallthrough - case RsJsonApiErrorNum::UNKNOWN_API_USER: // fallthrough - case RsJsonApiErrorNum::WRONG_API_PASSWORD: // fallthrough - case RsJsonApiErrorNum::AUTHORIZATION_REQUEST_DENIED: - return std::errc::permission_denied; - case RsJsonApiErrorNum::API_USER_CONTAIN_COLON: - return std::errc::invalid_argument; - default: - return std::error_condition(ev, *this); - } -} diff --git a/libretroshare/src/jsonapi/jsonapi.h b/libretroshare/src/jsonapi/jsonapi.h deleted file mode 100644 index 317d4066f..000000000 --- a/libretroshare/src/jsonapi/jsonapi.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * RetroShare JSON API - * - * Copyright (C) 2018-2020 Gioacchino Mazzurco - * Copyright (C) 2019-2020 Asociación Civil Altermundi - * - * 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, version 3. - * - * 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 - * - * SPDX-FileCopyrightText: 2004-2019 RetroShare Team - * SPDX-License-Identifier: AGPL-3.0-only - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util/rsthreads.h" -#include "pqi/p3cfgmgr.h" -#include "rsitems/rsitem.h" -#include "jsonapi/jsonapiitems.h" -#include "retroshare/rsjsonapi.h" -#include "util/rsthreads.h" - -namespace rb = restbed; - -/** Interface to provide addotional resources to JsonApiServer */ -class JsonApiResourceProvider -{ -public: - virtual ~JsonApiResourceProvider() = default; - - virtual std::vector> getResources() const = 0; - - inline bool operator< (const JsonApiResourceProvider& rp) const - { return this < &rp; } -}; - -/** - * Uses p3Config to securely store persistent JSON API authorization tokens - */ -class JsonApiServer : public p3Config, public RsThread, public RsJsonApi -{ -public: - JsonApiServer(); - ~JsonApiServer() override = default; - - std::vector> getResources() const; - - /// @see RsJsonApi - void fullstop() override { RsThread::fullstop(); } - - /// @see RsJsonApi - std::error_condition restart() override; - - /// @see RsJsonApi - void askForStop() override { RsThread::askForStop(); } - - /// @see RsJsonApi - inline bool isRunning() override { return RsThread::isRunning(); } - - /// @see RsJsonApi - void setListeningPort(uint16_t port) override; - - /// @see RsJsonApi - void setBindingAddress(const std::string& bindAddress) override; - - /// @see RsJsonApi - std::string getBindingAddress() const override; - - /// @see RsJsonApi - uint16_t listeningPort() const override; - - /// @see RsJsonApi - void connectToConfigManager(p3ConfigMgr& cfgmgr) override; - - /// @see RsJsonApi - virtual std::error_condition authorizeUser( - const std::string& user, const std::string& passwd ) override; - - /// @see RsJsonApi - std::map getAuthorizedTokens() override; - - /// @see RsJsonApi - bool revokeAuthToken(const std::string& user) override; - - /// @see RsJsonApi - bool isAuthTokenValid( - const std::string& token, - std::error_condition& error = RS_DEFAULT_STORAGE_PARAM(std::error_condition) - ) override; - - /// @see RsJsonAPI - std::error_condition requestNewTokenAutorization( - const std::string& user, const std::string& password ) override; - - /// @see RsJsonApi - void registerResourceProvider(const JsonApiResourceProvider&) override; - - /// @see RsJsonApi - void unregisterResourceProvider(const JsonApiResourceProvider&) override; - - /// @see RsJsonApi - bool hasResourceProvider(const JsonApiResourceProvider&) override; - - /** - * @brief Get decoded version of the given encoded token - * @param[in] radix64_token encoded - * @return token decoded - */ - static std::string decodeToken(const std::string& radix64_token); - - /** - * Register an unique handler for a resource path - * @param[in] path Path into which publish the API call - * @param[in] handler function which will be called to handle the requested - * @param[in] requiresAutentication specify if the API call must be - * autenticated or not. - */ - void registerHandler( - const std::string& path, - const std::function)>& handler, - bool requiresAutentication = true ); - - /** - * @brief Set new access request callback - * @param callback function to call when a new JSON API access is requested - */ - void setNewAccessRequestCallback( - const std::function& - callback ); - -protected: - /// @see RsThread - void onStopRequested() override; - - static std::error_condition badApiCredientalsFormat( - const std::string& user, const std::string& passwd ); - -private: - /// @see RsThread - void run() override; - - /// @see p3Config::setupSerialiser - RsSerialiser* setupSerialiser() override; - - /// @see p3Config::saveList - bool saveList(bool &cleanup, std::list& saveItems) override; - - /// @see p3Config::loadList - bool loadList(std::list& loadList) override; - - /// @see p3Config::saveDone - void saveDone() override; - - /// Called when new JSON API auth token is requested to be authorized - std::function - mNewAccessRequestCallback; - - /// Encrypted persistent storage for authorized JSON API tokens - JsonApiServerAuthTokenStorage mAuthTokenStorage; - RsMutex configMutex; - - static const std::multimap corsHeaders; - static const std::multimap corsOptionsHeaders; - static void handleCorsOptions(const std::shared_ptr session); - - static bool checkRsServicePtrReady( - const void* serviceInstance, const std::string& serviceName, - RsGenericSerializer::SerializeContext& ctx, - const std::shared_ptr session ); - - static inline bool checkRsServicePtrReady( - const std::shared_ptr serviceInstance, - const std::string& serviceName, - RsGenericSerializer::SerializeContext& ctx, - const std::shared_ptr session ) - { - return checkRsServicePtrReady( - serviceInstance.get(), serviceName, ctx, session ); - } - - std::vector> mResources; - std::set< - std::reference_wrapper, - std::less > mResourceProviders; - - /** - * This pointer should be accessed via std::atomic_* operations, up until - * now only very critical operations like reallocation, are done that way, - * but this is not still 100% thread safe, but seems to handle all of the - * test cases (no crash, no deadlock), once we switch to C++20 we shoud - * change this into std::atomic> which - * will automatically handle atomic access properly all the times - */ - std::shared_ptr mService; - - uint16_t mListeningPort; - std::string mBindingAddress; - - /// @see unProtectedRestart() - std::atomic mRestartReqTS; - - /// @see unProtectedRestart() - constexpr static rstime_t RESTART_BURST_PROTECTION = 7; - - /** It is very important to protect this method from being called in bursts, - * because Restbed::Service::stop() together with - * Restbed::Service::start(...), which are called internally, silently fails - * if combined in bursts, probably because they have to deal with - * listening/releasing TCP port. - * @see JsonApiServer::restart() and @see JsonApiServer::JsonApiServer() - * implementation to understand how correctly use this. - */ - void unProtectedRestart(); -}; - diff --git a/libretroshare/src/jsonapi/jsonapiitems.h b/libretroshare/src/jsonapi/jsonapiitems.h deleted file mode 100644 index eba871e98..000000000 --- a/libretroshare/src/jsonapi/jsonapiitems.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * RetroShare JSON API - * - * Copyright (C) 2018-2019 Gioacchino Mazzurco - * - * 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, version 3. - * - * 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 - * - * SPDX-FileCopyrightText: 2004-2019 RetroShare Team - * SPDX-License-Identifier: AGPL-3.0-only - */ - -#pragma once - -#include -#include "util/rstime.h" -#include -#include - -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserializer.h" -#include "serialiser/rsserializable.h" - -enum class JsonApiItemsType : uint8_t { AuthTokenItem_deprecated = 0, AuthTokenItem = 1 }; - -struct JsonApiServerAuthTokenStorage : RsItem -{ - JsonApiServerAuthTokenStorage() : - RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_JSONAPI, - static_cast(JsonApiItemsType::AuthTokenItem) ) {} - - /// @see RsSerializable - virtual void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(mAuthorizedTokens); - } - - /// @see RsItem - virtual void clear() { mAuthorizedTokens.clear(); } - - std::map mAuthorizedTokens; -}; - - -struct JsonApiConfigSerializer : RsServiceSerializer -{ - JsonApiConfigSerializer() : RsServiceSerializer(RS_SERVICE_TYPE_JSONAPI) {} - virtual ~JsonApiConfigSerializer() {} - - RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const - { - if(service_id != RS_SERVICE_TYPE_JSONAPI) return nullptr; - - switch(static_cast(item_sub_id)) - { - case JsonApiItemsType::AuthTokenItem: return new JsonApiServerAuthTokenStorage(); - default: return nullptr; - } - } -}; - - diff --git a/libretroshare/src/jsonapi/p3webui.cc b/libretroshare/src/jsonapi/p3webui.cc deleted file mode 100644 index 60fc63ea9..000000000 --- a/libretroshare/src/jsonapi/p3webui.cc +++ /dev/null @@ -1,196 +0,0 @@ -/* - * RetroShare Web User Interface - * - * Copyright (C) 2019 Cyril Soler - * - * 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, version 3. - * - * 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 - * - * SPDX-FileCopyrightText: 2004-2019 RetroShare Team - * SPDX-License-Identifier: AGPL-3.0-only - */ - -#include "p3webui.h" - -#include -#include -#include -#include -#include -#include - -#include "util/rsthreads.h" -#include "util/rsdebug.h" -#include "retroshare/rswebui.h" -#include "rsserver/rsaccounts.h" -#include "retroshare/rsjsonapi.h" - -#define DEBUG_RS_WEBUI 1 - -/*extern*/ RsWebUi* rsWebUi = new p3WebUI; - -enum MimeTypeIndex -{ - TEXT_HTML, - TEXT_CSS, - TEXT_SVG, - TEXT_TTF, - TEXT_WOFF, - APPLICATION_OCTET_STREAM, -}; - -static const constexpr char* const mime_types[] = -{ - "text/html", - "text/css", - "image/svg+xml", - "font/ttf", - "font/woff", - "application/octet-stream", -}; - -const std::string RsWebUi::DEFAULT_BASE_DIRECTORY = - RsAccountsDetail::PathDataDirectory(false) + "/webui/"; - -static std::string _base_directory = RsWebUi::DEFAULT_BASE_DIRECTORY; - -template class handler -{ -public: - static void get_handler( const std::shared_ptr< restbed::Session > session ) - { - const auto request = session->get_request( ); - const std::string filename = request->get_path_parameter( "filename" ); - std::string directory = request->get_path_parameter( "dir" ); - - if(!directory.empty()) directory += "/"; - - std::string resource_filename = _base_directory + "/" + directory + filename; - RsDbg() << "Reading file: \"" << resource_filename << "\"" << std::endl; - std::ifstream stream( resource_filename, std::ifstream::in ); - - if(stream.is_open()) - { - const std::string body = std::string( - std::istreambuf_iterator(stream), - std::istreambuf_iterator() ); - - RsDbg() << __PRETTY_FUNCTION__ - << " body length=" << body.length() << std::endl; - - const std::multimap headers - { - { "Content-Type", mime_types[MIME_TYPE_INDEX] }, - { "Content-Length", std::to_string(body.length()) } - }; - - session->close(restbed::OK, body, headers); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << "Could not open file: " - << resource_filename << std::endl; - session->close(restbed::NOT_FOUND); - } - } -}; - -std::vector< std::shared_ptr > p3WebUI::getResources() const -{ - static std::vector< std::shared_ptr > rtab; - - if(rtab.empty()) - { - auto resource1 = std::make_shared< restbed::Resource >(); - resource1->set_paths( { - "/{filename: index.html}", - "/{filename: app.js}", - } - ); - resource1->set_method_handler( "GET", handler::get_handler ); - - auto resource2 = std::make_shared< restbed::Resource >(); - resource2->set_paths( { - "/{dir: css}/{filename: fontawesome.css}", - "/{dir: css}/{filename: solid.css}", - "/{filename: app.css}", - } ); - resource2->set_method_handler( "GET", handler::get_handler ); - - auto resource3 = std::make_shared< restbed::Resource >(); - resource3->set_paths( { - "/{dir: data}/{filename: retroshare.svg}", - "/{dir: webfonts}/{filename: fa-solid-900.svg}", - } ); - resource3->set_method_handler( "GET", handler::get_handler ); - - auto resource4 = std::make_shared< restbed::Resource >(); - resource4->set_paths( { - "/{dir: webfonts}/{filename: fa-solid-900.ttf}", - } ); - resource4->set_method_handler( "GET", handler::get_handler ); - - auto resource5 = std::make_shared< restbed::Resource >(); - resource5->set_paths( { - "/{dir: webfonts}/{filename: fa-solid-900.woff}", - "/{dir: webfonts}/{filename: fa-solid-900.woff2}", - } ); - resource5->set_method_handler( "GET", handler::get_handler ); - - auto resource6 = std::make_shared< restbed::Resource >(); - resource6->set_paths( { - "/{dir: webfonts}/{filename: fa-solid-900.eot}", - } ); - resource6->set_method_handler( "GET", handler::get_handler ); - - rtab.push_back(resource1); - rtab.push_back(resource2); - rtab.push_back(resource3); - rtab.push_back(resource4); - rtab.push_back(resource5); - rtab.push_back(resource6); - } - - return rtab; -} - - -void p3WebUI::setHtmlFilesDirectory(const std::string& html_dir) -{ - _base_directory = html_dir; -} - -bool p3WebUI::isRunning() const -{ return rsJsonApi->isRunning() && rsJsonApi->hasResourceProvider(*this); } - -void p3WebUI::setUserPassword(const std::string& passwd) -{ - RsDbg() << __PRETTY_FUNCTION__ << " Updating webui token with new passwd \"" - << passwd << "\"" << std::endl; - - if(!rsJsonApi->authorizeUser("webui",passwd)) - std::cerr << "(EE) Cannot register webui token. Some error occurred when calling authorizeUser()" << std::endl; -} - -bool p3WebUI::restart() -{ - rsJsonApi->registerResourceProvider(*this); - rsJsonApi->restart(); - return true; -} - -bool p3WebUI::stop() -{ - rsJsonApi->unregisterResourceProvider(*this); - rsJsonApi->restart(); - return true; -} diff --git a/libretroshare/src/jsonapi/p3webui.h b/libretroshare/src/jsonapi/p3webui.h deleted file mode 100644 index b67927ab7..000000000 --- a/libretroshare/src/jsonapi/p3webui.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * RetroShare Web User Interface - * - * Copyright (C) 2019 Cyril Soler - * - * 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, version 3. - * - * 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 - * - * SPDX-FileCopyrightText: 2004-2019 RetroShare Team - * SPDX-License-Identifier: AGPL-3.0-only - */ - -#pragma once - -#include -#include -#include - -#include "retroshare/rswebui.h" -#include "jsonapi/jsonapi.h" - -class p3WebUI: public RsWebUi, public JsonApiResourceProvider -{ -public: - ~p3WebUI() override = default; - - // implements RsWebUI - - virtual void setHtmlFilesDirectory(const std::string& html_dir) override; - virtual void setUserPassword(const std::string& passwd) override; - - virtual bool restart() override ; - virtual bool stop() override ; - bool isRunning() const override; - // implements JsonApiResourceProvider - - virtual std::vector > getResources() const override; -}; diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro deleted file mode 100644 index 84d18944e..000000000 --- a/libretroshare/src/libretroshare.pro +++ /dev/null @@ -1,1069 +0,0 @@ -# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team -# SPDX-License-Identifier: CC0-1.0 - -!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri") - -TEMPLATE = lib -libretroshare_shared { - CONFIG += shared -} else { - CONFIG += staticlib -} -CONFIG -= qt -TARGET = retroshare -TARGET_PRL = libretroshare -DESTDIR = lib - -!include("use_libretroshare.pri"):error("Including") - -# treat warnings as error for better removing -#QMAKE_CFLAGS += -Werror -#QMAKE_CXXFLAGS += -Werror - -## Uncomment to enable Unfinished Services. -#CONFIG += wikipoos -#CONFIG += gxsthewire -#CONFIG += gxsphotoshare - -debug { -# DEFINES *= DEBUG -# DEFINES *= OPENDHT_DEBUG DHT_DEBUG CONN_DEBUG DEBUG_UDP_SORTER P3DISC_DEBUG DEBUG_UDP_LAYER FT_DEBUG EXTADDRSEARCH_DEBUG -# DEFINES *= CONTROL_DEBUG FT_DEBUG DEBUG_FTCHUNK P3TURTLE_DEBUG -# DEFINES *= P3TURTLE_DEBUG -# DEFINES *= NET_DEBUG -# DEFINES *= DISTRIB_DEBUG -# DEFINES *= P3TURTLE_DEBUG FT_DEBUG DEBUG_FTCHUNK MPLEX_DEBUG -# DEFINES *= STATUS_DEBUG SERV_DEBUG RSSERIAL_DEBUG #CONN_DEBUG - - QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer - QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer -} - -CONFIG += file_lists - -file_lists { - HEADERS *= file_sharing/p3filelists.h \ - file_sharing/hash_cache.h \ - file_sharing/filelist_io.h \ - file_sharing/directory_storage.h \ - file_sharing/directory_updater.h \ - file_sharing/rsfilelistitems.h \ - file_sharing/dir_hierarchy.h \ - file_sharing/file_sharing_defaults.h - - SOURCES *= file_sharing/p3filelists.cc \ - file_sharing/hash_cache.cc \ - file_sharing/filelist_io.cc \ - file_sharing/directory_storage.cc \ - file_sharing/directory_updater.cc \ - file_sharing/dir_hierarchy.cc \ - file_sharing/file_tree.cc \ - file_sharing/rsfilelistitems.cc -} - - -dsdv { -DEFINES *= SERVICES_DSDV -HEADERS += unused/p3dsdv.h \ - unused/rstlvdsdv.h \ - unused/rsdsdvitems.h \ - unused/rsdsdv.h - -SOURCES *= unused/rstlvdsdv.cc \ - unused/rsdsdvitems.cc \ - unused/p3dsdv.cc -} -bitdht { - -HEADERS += dht/p3bitdht.h \ - dht/connectstatebox.h - -SOURCES += dht/p3bitdht.cc \ - dht/p3bitdht_interface.cc \ - dht/p3bitdht_peers.cc \ - dht/p3bitdht_peernet.cc \ - dht/p3bitdht_relay.cc \ - dht/connectstatebox.cc - -HEADERS += tcponudp/udppeer.h \ - tcponudp/bio_tou.h \ - tcponudp/tcppacket.h \ - tcponudp/tcpstream.h \ - tcponudp/tou.h \ - tcponudp/udprelay.h \ - tcponudp/rsudpstack.h \ - pqi/pqissludp.h \ - -SOURCES += tcponudp/udppeer.cc \ - tcponudp/tcppacket.cc \ - tcponudp/tcpstream.cc \ - tcponudp/tou.cc \ - tcponudp/bss_tou.cc \ - tcponudp/udprelay.cc \ - pqi/pqissludp.cc \ - - useDhtStunner { - HEADERS += dht/stunaddrassist.h \ - tcponudp/udpstunner.h - - SOURCES += tcponudp/udpstunner.cc - - DEFINES += RS_USE_DHT_STUNNER - } - - DEFINES *= RS_USE_BITDHT - - BITDHT_DIR = ../../libbitdht/src - DEPENDPATH += . $${BITDHT_DIR} - INCLUDEPATH += . $${BITDHT_DIR} - PRE_TARGETDEPS *= $${BITDHT_DIR}/lib/libbitdht.a - LIBS *= $${BITDHT_DIR}/lib/libbitdht.a -} - - - - -PUBLIC_HEADERS = retroshare/rsdisc.h \ - retroshare/rsgossipdiscovery \ - retroshare/rsevents.h \ - retroshare/rsexpr.h \ - retroshare/rsfiles.h \ - retroshare/rshistory.h \ - retroshare/rsids.h \ - retroshare/rsiface.h \ - retroshare/rsinit.h \ - retroshare/rsplugin.h \ - retroshare/rsloginhandler.h \ - retroshare/rsmsgs.h \ - retroshare/rsnotify.h \ - retroshare/rspeers.h \ - retroshare/rsrank.h \ - retroshare/rsstatus.h \ - retroshare/rsturtle.h \ - retroshare/rsbanlist.h \ - retroshare/rstypes.h \ - retroshare/rsdht.h \ - retroshare/rsrtt.h \ - retroshare/rsconfig.h \ - retroshare/rsversion.h \ - retroshare/rsservicecontrol.h \ - retroshare/rsgxsdistsync.h - -rs_webui { - PUBLIC_HEADERS += retroshare/rswebui.h - SOURCES += jsonapi/p3webui.cc - HEADERS += jsonapi/p3webui.h -} - -HEADERS += plugins/pluginmanager.h \ - plugins/dlfcn_win32.h \ - rsitems/rspluginitems.h \ - util/i2pcommon.h \ - util/rsinitedptr.h - -HEADERS += $$PUBLIC_HEADERS - -################################# Linux ########################################## -linux-* { - CONFIG += link_pkgconfig - - QMAKE_CXXFLAGS *= -Wall -D_FILE_OFFSET_BITS=64 - QMAKE_CC = $${QMAKE_CXX} - - no_sqlcipher { - PKGCONFIG *= sqlite3 - } else { - SQLCIPHER_OK = $$system(pkg-config --exists sqlcipher && echo yes) - isEmpty(SQLCIPHER_OK) { - # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. - exists(../../../lib/sqlcipher/.libs/libsqlcipher.a) { - LIBS += ../../../lib/sqlcipher/.libs/libsqlcipher.a - DEPENDPATH += ../../../lib/ - INCLUDEPATH += ../../../lib/ - } else { - error("libsqlcipher is not installed and libsqlcipher.a not found. SQLCIPHER is necessary for encrypted database, to build with unencrypted database, run: qmake CONFIG+=no_sqlcipher") - } - } else { - # Workaround for broken sqlcipher packages, e.g. Ubuntu 14.04 - # https://bugs.launchpad.net/ubuntu/+source/sqlcipher/+bug/1493928 - # PKGCONFIG *= sqlcipher - LIBS *= -lsqlcipher - } - } - - contains(RS_UPNP_LIB, threadutil) { # ensure we don't break libpnp-1.8.x - # Check if the systems libupnp-1.6.x has been Debian-patched - !system(grep -E 'char[[:space:]]+PublisherUrl' /usr/include/upnp/upnp.h >/dev/null 2>&1) { - # Patched libupnp or new unreleased version - DEFINES *= PATCHED_LIBUPNP - } - } - - PKGCONFIG *= libssl - equals(RS_UPNP_LIB, "upnp ixml threadutil"):PKGCONFIG *= libupnp - PKGCONFIG *= libcrypto zlib - no_sqlcipher:PKGCONFIG *= sqlite3 - LIBS *= -ldl - - DEFINES *= PLUGIN_DIR=\"\\\"$${PLUGIN_DIR}\\\"\" - DEFINES *= DATA_DIR=\"\\\"$${DATA_DIR}\\\"\" -} - -linux-g++ { - OBJECTS_DIR = temp/linux-g++/obj -} - -linux-g++-64 { - OBJECTS_DIR = temp/linux-g++-64/obj -} - -version_detail_bash_script { - warning("Version detail script is deprecated.") - warning("Remove references to version_detail_bash_script from all of your build scripts!") -} - -#################### Cross compilation for windows under Linux #################### - -win32-x-g++ { - OBJECTS_DIR = temp/win32xgcc/obj - DEFINES *= WINDOWS_SYS WIN32 WIN_CROSS_UBUNTU - QMAKE_CXXFLAGS *= -Wmissing-include-dirs - QMAKE_CC = i586-mingw32msvc-g++ - QMAKE_LIB = i586-mingw32msvc-ar - QMAKE_AR = i586-mingw32msvc-ar - DEFINES *= STATICLIB WIN32 - - SSL_DIR=../../../../openssl - UPNPC_DIR = ../../../../miniupnpc-1.3 - GPG_ERROR_DIR = ../../../../libgpg-error-1.7 - GPGME_DIR = ../../../../gpgme-1.1.8 - - INCLUDEPATH *= /usr/i586-mingw32msvc/include ${HOME}/.wine/drive_c/pthreads/include/ -} -################################# Windows ########################################## - -win32-g++|win32-clang-g++ { - QMAKE_CC = $${QMAKE_CXX} - OBJECTS_DIR = temp/obj - MOC_DIR = temp/moc - !libretroshare_shared:DEFINES *= STATICLIB - - # Switch on extra warnings - QMAKE_CFLAGS += -Wextra - QMAKE_CXXFLAGS += -Wextra - - # Switch off optimization for release version - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -O0 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE += -O0 - - # Switch on optimization for debug version - #QMAKE_CXXFLAGS_DEBUG += -O2 - #QMAKE_CFLAGS_DEBUG += -O2 - - DEFINES += USE_CMD_ARGS - - wLibs = ws2_32 gdi32 uuid iphlpapi crypt32 ole32 winmm - LIBS += $$linkDynamicLibs(wLibs) -} - -################################# MacOSX ########################################## - -mac { - QMAKE_CC = $${QMAKE_CXX} - OBJECTS_DIR = temp/obj - MOC_DIR = temp/moc - - # Beautiful Hack to fix 64bit file access. - QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dfopen64=fopen -Dvstatfs64=vstatfs - - for(lib, LIB_DIR):LIBS += -L"$$lib" - for(bin, BIN_DIR):LIBS += -L"$$bin" - - DEPENDPATH += . $$INC_DIR - INCLUDEPATH += . $$INC_DIR - INCLUDEPATH += ../../../. - - # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. - LIBS += /usr/local/lib/libsqlcipher.a - #LIBS += -lsqlite3 - - DEFINES *= PLUGIN_DIR=\"\\\"$${PLUGIN_DIR}\\\"\" - DEFINES *= DATA_DIR=\"\\\"$${DATA_DIR}\\\"\" -} - -################################# FreeBSD ########################################## - -freebsd-* { - INCLUDEPATH *= /usr/local/include/gpgme - INCLUDEPATH *= /usr/local/include/glib-2.0 - - QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dstat64=stat -Dstatvfs64=statvfs -Dfopen64=fopen -} - -################################# OpenBSD ########################################## - -openbsd-* { - INCLUDEPATH *= /usr/local/include - INCLUDEPATH += $$system(pkg-config --cflags glib-2.0 | sed -e "s/-I//g") - - QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dstat64=stat -Dstatvfs64=statvfs -Dfopen64=fopen -} - -################################# Haiku ########################################## - -haiku-* { - - QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dstat64=stat -Dstatvfs64=statvfs -Dfopen64=fopen - OPENPGPSDK_DIR = ../../openpgpsdk/src - INCLUDEPATH *= $${OPENPGPSDK_DIR} ../openpgpsdk - DEFINES *= NO_SQLCIPHER - CONFIG += release - DESTDIR = lib -} - -################################### COMMON stuff ################################## - -# openpgpsdk -OPENPGPSDK_DIR = ../../openpgpsdk/src -DEPENDPATH *= $${OPENPGPSDK_DIR} -INCLUDEPATH *= $${OPENPGPSDK_DIR} -PRE_TARGETDEPS *= $${OPENPGPSDK_DIR}/lib/libops.a -LIBS *= $${OPENPGPSDK_DIR}/lib/libops.a -lbz2 - -################################### HEADERS & SOURCES ############################# - -HEADERS += ft/ftchunkmap.h \ - ft/ftcontroller.h \ - ft/ftdata.h \ - ft/ftdatamultiplex.h \ - ft/ftextralist.h \ - ft/ftfilecreator.h \ - ft/ftfileprovider.h \ - ft/ftfilesearch.h \ - ft/ftsearch.h \ - ft/ftserver.h \ - ft/fttransfermodule.h \ - ft/ftturtlefiletransferitem.h - -HEADERS += crypto/chacha20.h \ - crypto/rsaes.h \ - crypto/hashstream.h \ - crypto/rscrypto.h - -HEADERS += directory_updater.h \ - directory_list.h \ - p3filelists.h - -HEADERS += chat/distantchat.h \ - chat/p3chatservice.h \ - chat/distributedchat.h \ - chat/rschatitems.h - -HEADERS += pqi/authssl.h \ - pqi/authgpg.h \ - pgp/pgphandler.h \ - pgp/pgpkeyutil.h \ - pgp/rscertificate.h \ - pgp/pgpauxutils.h \ - pqi/p3cfgmgr.h \ - pqi/p3peermgr.h \ - pqi/p3linkmgr.h \ - pqi/p3netmgr.h \ - pqi/p3notify.h \ - pqi/p3upnpmgr.h \ - pqi/pqiqos.h \ - pqi/pqi.h \ - pqi/pqi_base.h \ - pqi/pqiassist.h \ - pqi/pqibin.h \ - pqi/pqihandler.h \ - pqi/pqihash.h \ - pqi/p3historymgr.h \ - pqi/pqiindic.h \ - pqi/pqiipset.h \ - pqi/pqilistener.h \ - pqi/pqiloopback.h \ - pqi/pqimonitor.h \ - pqi/pqinetwork.h \ - pqi/pqiperson.h \ - pqi/pqipersongrp.h \ - pqi/pqiservice.h \ - pqi/pqiservicemonitor.h \ - pqi/pqissl.h \ - pqi/pqissllistener.h \ - pqi/pqisslpersongrp.h \ - pqi/pqissli2pbob.h \ - pqi/pqisslproxy.h \ - pqi/pqistore.h \ - pqi/pqistreamer.h \ - pqi/pqithreadstreamer.h \ - pqi/pqiqosstreamer.h \ - pqi/sslfns.h \ - pqi/pqinetstatebox.h \ - pqi/p3servicecontrol.h - -HEADERS += rsserver/p3face.h \ - rsserver/p3history.h \ - rsserver/p3msgs.h \ - rsserver/p3peers.h \ - rsserver/p3status.h \ - rsserver/rsaccounts.h \ - rsserver/p3serverconfig.h - -HEADERS += grouter/groutercache.h \ - retroshare/rsgrouter.h \ - grouter/grouteritems.h \ - grouter/p3grouter.h \ - grouter/rsgroutermatrix.h \ - grouter/groutertypes.h \ - grouter/grouterclientservice.h - -HEADERS += rsitems/rsitem.h \ - rsitems/itempriorities.h \ - serialiser/rsbaseserial.h \ - rsitems/rsfiletransferitems.h \ - rsitems/rsconfigitems.h \ - rsitems/rshistoryitems.h \ - rsitems/rsmsgitems.h \ - serialiser/rsserial.h \ - rsitems/rsserviceids.h \ - serialiser/rsserviceitems.h \ - rsitems/rsstatusitems.h \ - serialiser/rstlvaddrs.h \ - serialiser/rstlvbase.h \ - serialiser/rstlvitem.h \ - serialiser/rstlvidset.h \ - serialiser/rstlvfileitem.h \ - serialiser/rstlvimage.h \ - serialiser/rstlvstring.h \ - serialiser/rstlvbinary.h \ - serialiser/rstlvkeys.h \ - serialiser/rstlvkeyvalue.h \ - serialiser/rstlvgenericparam.h \ - serialiser/rstlvgenericmap.h \ - serialiser/rstlvgenericmap.inl \ - serialiser/rstlvlist.h \ - serialiser/rstlvmaps.h \ - serialiser/rstlvbanlist.h \ - rsitems/rsbanlistitems.h \ - rsitems/rsbwctrlitems.h \ - gossipdiscovery/gossipdiscoveryitems.h \ - rsitems/rsheartbeatitems.h \ - rsitems/rsrttitems.h \ - rsitems/rsgxsrecognitems.h \ - rsitems/rsgxsupdateitems.h \ - rsitems/rsserviceinfoitems.h \ - -HEADERS += services/autoproxy/p3i2pbob.h \ - services/rseventsservice.h \ - services/autoproxy/rsautoproxymonitor.h \ - services/p3msgservice.h \ - services/p3service.h \ - services/p3statusservice.h \ - services/p3banlist.h \ - services/p3bwctrl.h \ - gossipdiscovery/p3gossipdiscovery.h \ - services/p3heartbeat.h \ - services/p3rtt.h \ - services/p3serviceinfo.h \ - -HEADERS += turtle/p3turtle.h \ - turtle/rsturtleitem.h \ - turtle/turtletypes.h \ - turtle/turtleclientservice.h - -HEADERS += util/folderiterator.h \ - util/rsdebug.h \ - util/rsdebuglevel0.h \ - util/rsdebuglevel1.h \ - util/rsdebuglevel2.h \ - util/rsdebuglevel3.h \ - util/rsdebuglevel4.h \ - util/rskbdinput.h \ - util/rsmemory.h \ - util/smallobject.h \ - util/rsdir.h \ - util/argstream.h \ - util/rsdiscspace.h \ - util/rsnet.h \ - util/extaddrfinder.h \ - util/dnsresolver.h \ - util/radix32.h \ - util/radix64.h \ - util/rsbase64.h \ - util/rsendian.h \ - util/rsinitedptr.h \ - util/rsprint.h \ - util/rsstring.h \ - util/rsstd.h \ - util/rsthreads.h \ - util/rswin.h \ - util/rsrandom.h \ - util/rsmemcache.h \ - util/rstickevent.h \ - util/rsrecogn.h \ - util/rstime.h \ - util/stacktrace.h \ - util/rsdeprecate.h \ - util/cxx11retrocompat.h \ - util/cxx14retrocompat.h \ - util/cxx17retrocompat.h \ - util/rsurl.h \ - util/rserrno.h - -SOURCES += ft/ftchunkmap.cc \ - ft/ftcontroller.cc \ - ft/ftdatamultiplex.cc \ - ft/ftextralist.cc \ - ft/ftfilecreator.cc \ - ft/ftfileprovider.cc \ - ft/ftfilesearch.cc \ - ft/ftserver.cc \ - ft/fttransfermodule.cc \ - ft/ftturtlefiletransferitem.cc \ - util/i2pcommon.cpp - -SOURCES += crypto/chacha20.cpp \ - crypto/hashstream.cc\ - crypto/rsaes.cc \ - crypto/rscrypto.cpp - -SOURCES += chat/distantchat.cc \ - chat/p3chatservice.cc \ - chat/distributedchat.cc \ - chat/rschatitems.cc - -SOURCES += pqi/authgpg.cc \ - pqi/authssl.cc \ - pgp/pgphandler.cc \ - pgp/pgpkeyutil.cc \ - pgp/rscertificate.cc \ - pgp/pgpauxutils.cc \ - pqi/p3cfgmgr.cc \ - pqi/p3peermgr.cc \ - pqi/p3linkmgr.cc \ - pqi/p3netmgr.cc \ - pqi/p3notify.cc \ - pqi/pqiqos.cc \ - pqi/pqibin.cc \ - pqi/pqihandler.cc \ - pqi/p3historymgr.cc \ - pqi/pqiipset.cc \ - pqi/pqiloopback.cc \ - pqi/pqimonitor.cc \ - pqi/pqinetwork.cc \ - pqi/pqiperson.cc \ - pqi/pqipersongrp.cc \ - pqi/pqiservice.cc \ - pqi/pqissl.cc \ - pqi/pqissllistener.cc \ - pqi/pqisslpersongrp.cc \ - pqi/pqissli2pbob.cpp \ - pqi/pqisslproxy.cc \ - pqi/pqistore.cc \ - pqi/pqistreamer.cc \ - pqi/pqithreadstreamer.cc \ - pqi/pqiqosstreamer.cc \ - pqi/sslfns.cc \ - pqi/pqinetstatebox.cc \ - pqi/p3servicecontrol.cc - -SOURCES += rsserver/p3face-config.cc \ - rsserver/p3face-server.cc \ - rsserver/p3face-info.cc \ - rsserver/p3history.cc \ - rsserver/p3msgs.cc \ - rsserver/p3peers.cc \ - rsserver/p3status.cc \ - rsserver/rsinit.cc \ - rsserver/rsaccounts.cc \ - rsserver/rsloginhandler.cc \ - rsserver/p3serverconfig.cc - -SOURCES += grouter/p3grouter.cc \ - grouter/grouteritems.cc \ - grouter/groutermatrix.cc - -SOURCES += plugins/pluginmanager.cc \ - plugins/dlfcn_win32.cc - -SOURCES += serialiser/rsbaseserial.cc \ - rsitems/rsfiletransferitems.cc \ - rsitems/rsconfigitems.cc \ - rsitems/rshistoryitems.cc \ - rsitems/rsmsgitems.cc \ - serialiser/rsserial.cc \ - serialiser/rstlvaddrs.cc \ - serialiser/rstlvbase.cc \ - serialiser/rstlvitem.cc \ - serialiser/rstlvidset.cc \ - serialiser/rstlvfileitem.cc \ - serialiser/rstlvimage.cc \ - serialiser/rstlvstring.cc \ - serialiser/rstlvbinary.cc \ - serialiser/rstlvkeys.cc \ - serialiser/rstlvkeyvalue.cc \ - serialiser/rstlvgenericparam.cc \ - serialiser/rstlvbanlist.cc \ - rsitems/rsbanlistitems.cc \ - rsitems/rsbwctrlitems.cc \ - gossipdiscovery/gossipdiscoveryitems.cc \ - rsitems/rsrttitems.cc \ - rsitems/rsgxsrecognitems.cc \ - rsitems/rsgxsupdateitems.cc \ - rsitems/rsserviceinfoitems.cc \ - - -SOURCES += services/autoproxy/rsautoproxymonitor.cc \ - services/rseventsservice.cc \ - services/autoproxy/p3i2pbob.cc \ - services/p3msgservice.cc \ - services/p3service.cc \ - services/p3statusservice.cc \ - services/p3banlist.cc \ - services/p3bwctrl.cc \ - gossipdiscovery/p3gossipdiscovery.cc \ - services/p3heartbeat.cc \ - services/p3rtt.cc \ - services/p3serviceinfo.cc \ - -SOURCES += turtle/p3turtle.cc \ - turtle/rsturtleitem.cc - -SOURCES += util/folderiterator.cc \ - util/rsdebug.cc \ - util/rskbdinput.cc \ - util/rsexpr.cc \ - util/smallobject.cc \ - util/rsdir.cc \ - util/rsmemory.cc \ - util/rsdiscspace.cc \ - util/rsnet.cc \ - util/rsnet_ss.cc \ - util/extaddrfinder.cc \ - util/dnsresolver.cc \ - util/rsprint.cc \ - util/rsstring.cc \ - util/rsthreads.cc \ - util/rsrandom.cc \ - util/rstickevent.cc \ - util/rsrecogn.cc \ - util/rstime.cc \ - util/rsurl.cc \ - util/rsbase64.cc \ - util/rserrno.cc - -equals(RS_UPNP_LIB, miniupnpc) { - HEADERS += rs_upnp/upnputil.h rs_upnp/upnphandler_miniupnp.h - SOURCES += rs_upnp/upnputil.cc rs_upnp/upnphandler_miniupnp.cc -} - -contains(RS_UPNP_LIB, upnp) { - HEADERS += rs_upnp/upnp18_retrocompat.h - HEADERS += rs_upnp/UPnPBase.h rs_upnp/upnphandler_libupnp.h - SOURCES += rs_upnp/UPnPBase.cpp rs_upnp/upnphandler_libupnp.cc -} - -# new gxs cache system -# this should be disabled for releases until further notice. - -DEFINES *= SQLITE_HAS_CODEC -DEFINES *= GXS_ENABLE_SYNC_MSGS - -HEADERS += rsitems/rsnxsitems.h \ - rsitems/rsgxsitems.h \ - retroshare/rstokenservice.h \ - retroshare/rsgxsservice.h \ - retroshare/rsgxsflags.h \ - retroshare/rsgxsifacetypes.h \ - retroshare/rsgxsiface.h \ - retroshare/rsgxscommon.h \ - retroshare/rsgxsifacehelper.h \ - util/retrodb.h \ - util/rsdbbind.h \ - util/contentvalue.h \ - gxs/rsgxsutil.h \ - gxs/rsgxsnotify.h \ - gxs/gxssecurity.h \ - gxs/rsgds.h \ - gxs/rsgxs.h \ - gxs/rsdataservice.h \ - gxs/rsgxsnetservice.h \ - gxs/rsgxsnettunnel.h \ - gxs/rsgenexchange.h \ - gxs/rsnxs.h \ - gxs/rsnxsobserver.h \ - gxs/rsgxsdata.h \ - gxs/rsgxsdataaccess.h \ - gxs/gxstokenqueue.h \ - gxs/rsgxsnetutils.h \ - gxs/rsgxsrequesttypes.h - - -SOURCES += rsitems/rsnxsitems.cc \ - rsitems/rsgxsitems.cc \ - util/retrodb.cc \ - util/contentvalue.cc \ - util/rsdbbind.cc \ - gxs/gxssecurity.cc \ - gxs/rsgxsdataaccess.cc \ - gxs/rsdataservice.cc \ - gxs/rsgenexchange.cc \ - gxs/rsgxsnetservice.cc \ - gxs/rsgxsnettunnel.cc \ - gxs/rsgxsdata.cc \ - gxs/gxstokenqueue.cc \ - gxs/rsgxsnetutils.cc \ - gxs/rsgxsutil.cc \ - gxs/rsgxsrequesttypes.cc - -# gxs tunnels -HEADERS += gxstunnel/p3gxstunnel.h \ - gxstunnel/rsgxstunnelitems.h \ - retroshare/rsgxstunnel.h - -SOURCES += gxstunnel/p3gxstunnel.cc \ - gxstunnel/rsgxstunnelitems.cc - -# new serialization code -HEADERS += serialiser/rsserializable.h \ - serialiser/rsserializer.h \ - serialiser/rstypeserializer.h \ - util/rsjson.h - -SOURCES += serialiser/rsserializable.cc \ - serialiser/rsserializer.cc \ - serialiser/rstypeserializer.cc \ - util/rsjson.cc - -# Identity Service -HEADERS += retroshare/rsidentity.h \ - retroshare/rsreputations.h \ - gxs/rsgixs.h \ - services/p3idservice.h \ - rsitems/rsgxsiditems.h \ - services/p3gxsreputation.h \ - rsitems/rsgxsreputationitems.h \ - -SOURCES += services/p3idservice.cc \ - rsitems/rsgxsiditems.cc \ - services/p3gxsreputation.cc \ - rsitems/rsgxsreputationitems.cc \ - -# GxsCircles Service -HEADERS += services/p3gxscircles.h \ - rsitems/rsgxscircleitems.h \ - retroshare/rsgxscircles.h \ - -SOURCES += services/p3gxscircles.cc \ - rsitems/rsgxscircleitems.cc \ - -# GxsForums Service -HEADERS += retroshare/rsgxsforums.h \ - services/p3gxsforums.h \ - rsitems/rsgxsforumitems.h - -SOURCES += services/p3gxsforums.cc \ - rsitems/rsgxsforumitems.cc \ - -# GxsChannels Service -HEADERS += retroshare/rsgxschannels.h \ - services/p3gxschannels.h \ - services/p3gxscommon.h \ - rsitems/rsgxscommentitems.h \ - rsitems/rsgxschannelitems.h \ - -SOURCES += services/p3gxschannels.cc \ - services/p3gxscommon.cc \ - rsitems/rsgxscommentitems.cc \ - rsitems/rsgxschannelitems.cc \ - -wikipoos { - DEFINES *= RS_USE_WIKI - - # Wiki Service - HEADERS += retroshare/rswiki.h \ - services/p3wiki.h \ - rsitems/rswikiitems.h - - SOURCES += services/p3wiki.cc \ - rsitems/rswikiitems.cc \ -} - -gxsthewire { - DEFINES *= RS_USE_WIRE - - # Wire Service - HEADERS += retroshare/rswire.h \ - services/p3wire.h \ - rsitems/rswireitems.h - - SOURCES += services/p3wire.cc \ - rsitems/rswireitems.cc \ -} - -# Posted Service -HEADERS += services/p3postbase.h \ - services/p3posted.h \ - retroshare/rsposted.h \ - rsitems/rsposteditems.h - -SOURCES += services/p3postbase.cc \ - services/p3posted.cc \ - rsitems/rsposteditems.cc - -gxsphotoshare { - DEFINES *= RS_USE_PHOTO - - #Photo Service - HEADERS += services/p3photoservice.h \ - retroshare/rsphoto.h \ - rsitems/rsphotoitems.h \ - - SOURCES += services/p3photoservice.cc \ - rsitems/rsphotoitems.cc \ -} - -rs_gxs_trans { - HEADERS += gxstrans/p3gxstransitems.h gxstrans/p3gxstrans.h - SOURCES += gxstrans/p3gxstransitems.cc gxstrans/p3gxstrans.cc -} - -rs_jsonapi { - JSONAPI_GENERATOR_SRC=$$clean_path($${RS_SRC_PATH}/jsonapi-generator/src/) - JSONAPI_GENERATOR_OUT=$$clean_path($${RS_BUILD_PATH}/jsonapi-generator/src/) - isEmpty(JSONAPI_GENERATOR_EXE) { - win32 { - CONFIG(release, debug|release) { - JSONAPI_GENERATOR_EXE=$$clean_path($${JSONAPI_GENERATOR_OUT}/release/jsonapi-generator.exe) - } - CONFIG(debug, debug|release) { - JSONAPI_GENERATOR_EXE=$$clean_path($${JSONAPI_GENERATOR_OUT}/debug/jsonapi-generator.exe) - } - } else { - JSONAPI_GENERATOR_EXE=$$clean_path($${JSONAPI_GENERATOR_OUT}/jsonapi-generator) - } - } - - DOXIGEN_INPUT_DIRECTORY=$$clean_path($${PWD}) - DOXIGEN_CONFIG_SRC=$$clean_path($${RS_SRC_PATH}/jsonapi-generator/src/jsonapi-generator-doxygen.conf) - DOXIGEN_CONFIG_OUT=$$clean_path($${JSONAPI_GENERATOR_OUT}/jsonapi-generator-doxygen-final.conf) - WRAPPERS_INCL_FILE=$$clean_path($${JSONAPI_GENERATOR_OUT}/jsonapi-includes.inl) - WRAPPERS_REG_FILE=$$clean_path($${JSONAPI_GENERATOR_OUT}/jsonapi-wrappers.inl) - - no_rs_cross_compiling { - DUMMYRESTBEDINPUT = FORCE - CMAKE_GENERATOR_OVERRIDE="" - win32-g++|win32-clang-g++ { - isEmpty(QMAKE_SH) { - CMAKE_GENERATOR_OVERRIDE="-G \"MinGW Makefiles\"" - } else { - CMAKE_GENERATOR_OVERRIDE="-G \"MSYS Makefiles\"" - } - } - genrestbedlib.name = Generating librestbed. - genrestbedlib.input = DUMMYRESTBEDINPUT - genrestbedlib.output = $$clean_path($${RESTBED_BUILD_PATH}/librestbed.a) - genrestbedlib.CONFIG += target_predeps combine - genrestbedlib.variable_out = PRE_TARGETDEPS - win32-g++:isEmpty(QMAKE_SH) { - genrestbedlib.commands = \ - cd /D $$shell_path($${RS_SRC_PATH}) && git submodule update --init supportlibs/restbed || cd . $$escape_expand(\\n\\t) \ - cd /D $$shell_path($${RESTBED_SRC_PATH}) && git submodule update --init dependency/asio || cd . $$escape_expand(\\n\\t) \ - cd /D $$shell_path($${RESTBED_SRC_PATH}) && git submodule update --init dependency/catch || cd . $$escape_expand(\\n\\t )\ - cd /D $$shell_path($${RESTBED_SRC_PATH}) && git submodule update --init dependency/kashmir || cd . $$escape_expand(\\n\\t) \ - $(CHK_DIR_EXISTS) $$shell_path($$UDP_DISCOVERY_BUILD_PATH) $(MKDIR) $$shell_path($${UDP_DISCOVERY_BUILD_PATH}) $$escape_expand(\\n\\t) - } else { - genrestbedlib.commands = \ - cd $${RS_SRC_PATH} && ( \ - git submodule update --init supportlibs/restbed ; \ - cd $${RESTBED_SRC_PATH} ; \ - git submodule update --init dependency/asio ; \ - git submodule update --init dependency/catch ; \ - git submodule update --init dependency/kashmir ; \ - true ) && \ - mkdir -p $${RESTBED_BUILD_PATH} && - } - genrestbedlib.commands += \ - cd $$shell_path($${RESTBED_BUILD_PATH}) && \ - cmake \ - -DCMAKE_CXX_COMPILER=$$QMAKE_CXX \ - \"-DCMAKE_CXX_FLAGS=$${QMAKE_CXXFLAGS}\" \ - $${CMAKE_GENERATOR_OVERRIDE} -DBUILD_SSL=OFF \ - -DCMAKE_INSTALL_PREFIX=. -B. \ - -H$$shell_path($${RESTBED_SRC_PATH}) && \ - $(MAKE) - QMAKE_EXTRA_COMPILERS += genrestbedlib - - RESTBED_HEADER_FILE=$$clean_path($${RESTBED_BUILD_PATH}/include/restbed) - genrestbedheader.name = Generating restbed header. - genrestbedheader.input = genrestbedlib.output - genrestbedheader.output = $${RESTBED_HEADER_FILE} - genrestbedheader.CONFIG += target_predeps no_link - genrestbedheader.variable_out = HEADERS - genrestbedheader.commands = cd $$shell_path($${RESTBED_BUILD_PATH}) && $(MAKE) install - QMAKE_EXTRA_COMPILERS += genrestbedheader - } - - INCLUDEPATH *= $${JSONAPI_GENERATOR_OUT} - DEPENDPATH *= $${JSONAPI_GENERATOR_OUT} - APIHEADERS = $$files($${RS_SRC_PATH}/libretroshare/src/retroshare/*.h) - #Make sure that the jsonapigenerator executable are ready - APIHEADERS += $${JSONAPI_GENERATOR_EXE} - - genjsonapi.name = Generating jsonapi headers. - genjsonapi.input = APIHEADERS - genjsonapi.output = $${WRAPPERS_INCL_FILE} $${WRAPPERS_REG_FILE} - genjsonapi.clean = $${WRAPPERS_INCL_FILE} $${WRAPPERS_REG_FILE} - genjsonapi.CONFIG += target_predeps combine no_link - genjsonapi.variable_out = HEADERS - win32-g++:isEmpty(QMAKE_SH) { - genjsonapi.commands = \ - $(CHK_DIR_EXISTS) $$shell_path($$JSONAPI_GENERATOR_OUT) $(MKDIR) $$shell_path($${JSONAPI_GENERATOR_OUT}) $$escape_expand(\\n\\t) - } else { - genjsonapi.commands = \ - mkdir -p $${JSONAPI_GENERATOR_OUT} && \ - cp $${DOXIGEN_CONFIG_SRC} $${DOXIGEN_CONFIG_OUT} && \ - echo OUTPUT_DIRECTORY=$${JSONAPI_GENERATOR_OUT} >> $${DOXIGEN_CONFIG_OUT} && \ - echo INPUT=$${DOXIGEN_INPUT_DIRECTORY} >> $${DOXIGEN_CONFIG_OUT} && \ - doxygen $${DOXIGEN_CONFIG_OUT} && - } - genjsonapi.commands += \ - $${JSONAPI_GENERATOR_EXE} $${JSONAPI_GENERATOR_SRC} $${JSONAPI_GENERATOR_OUT} - QMAKE_EXTRA_COMPILERS += genjsonapi - - # Force recalculation of libretroshare dependencies see https://stackoverflow.com/a/47884045 - QMAKE_EXTRA_TARGETS += libretroshare - - HEADERS += jsonapi/jsonapi.h jsonapi/jsonapiitems.h retroshare/rsjsonapi.h - SOURCES += jsonapi/jsonapi.cpp -} - -rs_deep_channels_index { - HEADERS *= deep_search/commonutils.hpp - SOURCES *= deep_search/commonutils.cpp - - HEADERS += deep_search/channelsindex.hpp - SOURCES += deep_search/channelsindex.cpp -} - -rs_deep_files_index { - HEADERS *= deep_search/commonutils.hpp - SOURCES *= deep_search/commonutils.cpp - - HEADERS += deep_search/filesindex.hpp - SOURCES += deep_search/filesindex.cpp -} - -rs_deep_files_index_ogg { - HEADERS += deep_search/filesoggindexer.hpp -} - -rs_deep_files_index_flac { - HEADERS += deep_search/filesflacindexer.hpp -} - -rs_deep_files_index_taglib { - HEADERS += deep_search/filestaglibindexer.hpp -} - -rs_broadcast_discovery { - HEADERS += retroshare/rsbroadcastdiscovery.h \ - services/broadcastdiscoveryservice.h - SOURCES += services/broadcastdiscoveryservice.cc - - no_rs_cross_compiling { - DUMMYQMAKECOMPILERINPUT = FORCE - CMAKE_GENERATOR_OVERRIDE="" - win32-g++|win32-clang-g++ { - isEmpty(QMAKE_SH) { - CMAKE_GENERATOR_OVERRIDE="-G \"MinGW Makefiles\"" - } else { - CMAKE_GENERATOR_OVERRIDE="-G \"MSYS Makefiles\"" - } - } - udpdiscoverycpplib.name = Generating libudp-discovery.a. - udpdiscoverycpplib.input = DUMMYQMAKECOMPILERINPUT - udpdiscoverycpplib.output = $$clean_path($${UDP_DISCOVERY_BUILD_PATH}/libudp-discovery.a) - udpdiscoverycpplib.CONFIG += target_predeps combine - udpdiscoverycpplib.variable_out = PRE_TARGETDEPS - win32-g++:isEmpty(QMAKE_SH) { - udpdiscoverycpplib.commands = \ - cd /D $$shell_path($${RS_SRC_PATH}) && git submodule update --init supportlibs/udp-discovery-cpp || cd . $$escape_expand(\\n\\t) \ - $(CHK_DIR_EXISTS) $$shell_path($$UDP_DISCOVERY_BUILD_PATH) $(MKDIR) $$shell_path($${UDP_DISCOVERY_BUILD_PATH}) $$escape_expand(\\n\\t) - } else { - udpdiscoverycpplib.commands = \ - cd $${RS_SRC_PATH} && ( \ - git submodule update --init supportlibs/udp-discovery-cpp || \ - true ) && \ - mkdir -p $${UDP_DISCOVERY_BUILD_PATH} && - } - udpdiscoverycpplib.commands += \ - cd $$shell_path($${UDP_DISCOVERY_BUILD_PATH}) && \ - cmake -DCMAKE_C_COMPILER=$$fixQmakeCC($$QMAKE_CC) \ - -DCMAKE_CXX_COMPILER=$$QMAKE_CXX \ - \"-DCMAKE_CXX_FLAGS=$${QMAKE_CXXFLAGS}\" \ - $${CMAKE_GENERATOR_OVERRIDE} \ - -DBUILD_EXAMPLE=OFF -DBUILD_TOOL=OFF \ - -DCMAKE_INSTALL_PREFIX=. -B. \ - -H$$shell_path($${UDP_DISCOVERY_SRC_PATH}) && \ - $(MAKE) - QMAKE_EXTRA_COMPILERS += udpdiscoverycpplib - } -} - -########################################################################################################### -# OLD CONFIG OPTIONS. -# Not used much - but might be useful one day. -# - -testnetwork { - # used in rsserver/rsinit.cc Enabled Port Restrictions, and makes Proxy Port next to Dht Port. - DEFINES *= LOCALNET_TESTING - - # used in tcponudp/udprelay.cc Debugging Info for Relays. - DEFINES *= DEBUG_UDP_RELAY - - # used in tcponudp/udpstunner.[h | cc] enables local stun (careful - modifies class variables). - DEFINES *= UDPSTUN_ALLOW_LOCALNET - - # used in pqi/p3linkmgr.cc prints out extra debug. - DEFINES *= LINKMGR_DEBUG_LINKTYPE - - # used in dht/connectstatebox to reduce connection times and display debug. - # DEFINES *= TESTING_PERIODS - # DEFINES *= DEBUG_CONNECTBOX -} - - -test_bitdht { - # DISABLE TCP CONNECTIONS... - DEFINES *= P3CONNMGR_NO_TCP_CONNECTIONS - - # NO AUTO CONNECTIONS??? FOR TESTING DHT STATUS. - DEFINES *= P3CONNMGR_NO_AUTO_CONNECTION - - # ENABLED UDP NOW. -} - -################################# Android ##################################### - -android-* { -## TODO: This probably disable largefile support and maybe is not necessary with -## __ANDROID_API__ >= 24 hence should be made conditional or moved to a -## compatibility header - DEFINES *= "fopen64=fopen" - DEFINES *= "fseeko64=fseeko" - DEFINES *= "ftello64=ftello" - -## Static library are very susceptible to order in command line - sLibs = bz2 $$RS_UPNP_LIB $$RS_SQL_LIB ssl crypto - - LIBS += $$linkStaticLibs(sLibs) - PRE_TARGETDEPS += $$pretargetStaticLibs(sLibs) - - HEADERS += util/androiddebug.h -} - diff --git a/libretroshare/src/pgp/pgpauxutils.cc b/libretroshare/src/pgp/pgpauxutils.cc deleted file mode 100644 index d7229e848..000000000 --- a/libretroshare/src/pgp/pgpauxutils.cc +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: pgpauxutils.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pgp/pgpauxutils.h" - -#include "pqi/authgpg.h" -#include "rsserver/p3face.h" -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" - -PgpAuxUtilsImpl::PgpAuxUtilsImpl() -{ - return; -} - - -const RsPgpId& PgpAuxUtilsImpl::getPGPOwnId() -{ - return AuthGPG::getAuthGPG()->getGPGOwnId(); -} - -RsPgpId PgpAuxUtilsImpl::getPGPId(const RsPeerId& sslid) -{ - return rsPeers->getGPGId(sslid); -} - -bool PgpAuxUtilsImpl::getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) const -{ - return AuthGPG::getAuthGPG()->getKeyFingerprint(id, fp); -} - -bool PgpAuxUtilsImpl::VerifySignBin(const void *data, - uint32_t len, - unsigned char *sign, - unsigned int signlen, - const PGPFingerprintType& withfingerprint) - -{ - return AuthGPG::getAuthGPG()->VerifySignBin(data, len, sign, signlen, withfingerprint); -} - -bool PgpAuxUtilsImpl::getGPGAllList(std::list &ids) -{ - return AuthGPG::getAuthGPG()->getGPGAllList(ids); -} - -bool PgpAuxUtilsImpl::parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const -{ - return AuthGPG::getAuthGPG()->parseSignature(sign,signlen,issuer); -} - - - - diff --git a/libretroshare/src/pgp/pgpauxutils.h b/libretroshare/src/pgp/pgpauxutils.h deleted file mode 100644 index 4b188e3ae..000000000 --- a/libretroshare/src/pgp/pgpauxutils.h +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: pgpauxutils.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsids.h" -#include "retroshare/rstypes.h" -#include "util/rsdeprecate.h" - -/* 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. - */ - -class PgpAuxUtils -{ - public: - virtual ~PgpAuxUtils(){} - - virtual const RsPgpId &getPGPOwnId() = 0; - virtual RsPgpId getPGPId(const RsPeerId& sslid) = 0; - virtual bool getGPGAllList(std::list &ids) = 0; - virtual bool getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) 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; -}; - -class PgpAuxUtilsImpl: public PgpAuxUtils -{ -public: - PgpAuxUtilsImpl(); - - virtual const RsPgpId &getPGPOwnId(); - virtual RsPgpId getPGPId(const RsPeerId& sslid); - - virtual bool parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const ; - virtual bool getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) const; - virtual bool VerifySignBin(const void *data, uint32_t len, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint); - virtual bool getGPGAllList(std::list &ids); -}; - - diff --git a/libretroshare/src/pgp/pgphandler.cc b/libretroshare/src/pgp/pgphandler.cc deleted file mode 100644 index b1e96b00b..000000000 --- a/libretroshare/src/pgp/pgphandler.cc +++ /dev/null @@ -1,2133 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: pgphandler.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include - -#ifdef WINDOWS_SYS -#include -#include "util/rsstring.h" -#include "util/rswin.h" -#endif - -extern "C" { -#include -#include -#include -#include -#include -#include -#include -} -#include "pgphandler.h" -#include "retroshare/rsiface.h" // For rsicontrol. -#include "retroshare/rspeers.h" // For rsicontrol. -#include "util/rsdir.h" -#include "util/rsdiscspace.h" -#include "util/rsmemory.h" -#include "pgp/pgpkeyutil.h" - -static const uint32_t PGP_CERTIFICATE_LIMIT_MAX_NAME_SIZE = 64 ; -static const uint32_t PGP_CERTIFICATE_LIMIT_MAX_EMAIL_SIZE = 64 ; -static const uint32_t PGP_CERTIFICATE_LIMIT_MAX_PASSWD_SIZE = 1024 ; - -//#define DEBUG_PGPHANDLER 1 -//#define PGPHANDLER_DSA_SUPPORT - -PassphraseCallback PGPHandler::_passphrase_callback = NULL ; - -ops_keyring_t *PGPHandler::allocateOPSKeyring() -{ - ops_keyring_t *kr = (ops_keyring_t*)rs_malloc(sizeof(ops_keyring_t)) ; - - if(kr == NULL) - return NULL ; - - kr->nkeys = 0 ; - kr->nkeys_allocated = 0 ; - kr->keys = 0 ; - - return kr ; -} - -ops_parse_cb_return_t cb_get_passphrase(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)// __attribute__((unused))) -{ - const ops_parser_content_union_t *content=&content_->content; - bool prev_was_bad = false ; - - switch(content_->tag) - { - case OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD: prev_was_bad = true ; - /* fallthrough */ - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - { - std::string passwd; - std::string uid_hint ; - - if(cbinfo->cryptinfo.keydata->nuids > 0) - uid_hint = std::string((const char *)cbinfo->cryptinfo.keydata->uids[0].user_id) ; - uid_hint += "(" + RsPgpId(cbinfo->cryptinfo.keydata->key_id).toStdString()+")" ; - - bool cancelled = false ; - passwd = PGPHandler::passphraseCallback()(NULL,"",uid_hint.c_str(),NULL,prev_was_bad,&cancelled) ; - - if(cancelled) - *(unsigned char *)cbinfo->arg = 1; - - *(content->secret_key_passphrase.passphrase)= (char *)ops_mallocz(passwd.length()+1) ; - memcpy(*(content->secret_key_passphrase.passphrase),passwd.c_str(),passwd.length()) ; - return OPS_KEEP_MEMORY; - } - break; - - default: - break; - } - - return OPS_RELEASE_MEMORY; -} -void PGPHandler::setPassphraseCallback(PassphraseCallback cb) -{ - _passphrase_callback = cb ; -} - -PGPHandler::PGPHandler(const std::string& pubring, const std::string& secring,const std::string& trustdb,const std::string& pgp_lock_filename) - : pgphandlerMtx(std::string("PGPHandler")), _pubring_path(pubring),_secring_path(secring),_trustdb_path(trustdb),_pgp_lock_filename(pgp_lock_filename) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - _pubring_changed = false ; - _trustdb_changed = false ; - - RsStackFileLock flck(_pgp_lock_filename) ; // lock access to PGP directory. - - if(_passphrase_callback == NULL) - std::cerr << "WARNING: before created a PGPHandler, you need to init the passphrase callback using PGPHandler::setPassphraseCallback()" << std::endl; - - // Allocate public and secret keyrings. - // - _pubring = allocateOPSKeyring() ; - _secring = allocateOPSKeyring() ; - - // Check that the file exists. If not, create a void keyring. - - FILE *ftest ; - ftest = RsDirUtil::rs_fopen(pubring.c_str(),"rb") ; - bool pubring_exist = (ftest != NULL) ; - if(ftest != NULL) - fclose(ftest) ; - ftest = RsDirUtil::rs_fopen(secring.c_str(),"rb") ; - bool secring_exist = (ftest != NULL) ; - if(ftest != NULL) - fclose(ftest) ; - - // Read public and secret keyrings from supplied files. - // - if(pubring_exist) - { - if(ops_false == ops_keyring_read_from_file(_pubring, false, pubring.c_str())) - throw std::runtime_error("PGPHandler::readKeyRing(): cannot read pubring. File corrupted.") ; - } - else - std::cerr << "pubring file \"" << pubring << "\" not found. Creating a void keyring." << std::endl; - - const ops_keydata_t *keydata ; - int i=0 ; - while( (keydata = ops_keyring_get_key_by_index(_pubring,i)) != NULL ) - { - PGPCertificateInfo& cert(_public_keyring_map[ RsPgpId(keydata->key_id) ]) ; - - // Init all certificates. - - initCertificateInfo(cert,keydata,i) ; - - // Validate signatures. - - validateAndUpdateSignatures(cert,keydata) ; - - ++i ; - } - _pubring_last_update_time = time(NULL) ; - std::cerr << "Pubring read successfully." << std::endl; - - if(secring_exist) - { - if(ops_false == ops_keyring_read_from_file(_secring, false, secring.c_str())) - throw std::runtime_error("PGPHandler::readKeyRing(): cannot read secring. File corrupted.") ; - } - else - std::cerr << "secring file \"" << secring << "\" not found. Creating a void keyring." << std::endl; - - i=0 ; - while( (keydata = ops_keyring_get_key_by_index(_secring,i)) != NULL ) - { - initCertificateInfo(_secret_keyring_map[ RsPgpId(keydata->key_id) ],keydata,i) ; - ++i ; - } - _secring_last_update_time = time(NULL) ; - - std::cerr << "Secring read successfully." << std::endl; - - locked_readPrivateTrustDatabase() ; - _trustdb_last_update_time = time(NULL) ; -} - -void PGPHandler::initCertificateInfo(PGPCertificateInfo& cert,const ops_keydata_t *keydata,uint32_t index) -{ - // Parse certificate name - // - - if(keydata->uids != NULL) - { - std::string namestring( (char *)keydata->uids[0].user_id ) ; - - cert._name = "" ; - uint32_t i=0; - while(i < namestring.length() && namestring[i] != '(' && namestring[i] != '<') { cert._name += namestring[i] ; ++i ;} - - // trim right spaces - std::string::size_type found = cert._name.find_last_not_of(' '); - if (found != std::string::npos) - cert._name.erase(found + 1); - else - cert._name.clear(); // all whitespace - - std::string& next = (namestring[i] == '(')?cert._comment:cert._email ; - ++i ; - next = "" ; - while(i < namestring.length() && namestring[i] != ')' && namestring[i] != '>') { next += namestring[i] ; ++i ;} - - while(i < namestring.length() && namestring[i] != '(' && namestring[i] != '<') { next += namestring[i] ; ++i ;} - - if(i< namestring.length()) - { - std::string& next2 = (namestring[i] == '(')?cert._comment:cert._email ; - ++i ; - next2 = "" ; - while(i < namestring.length() && namestring[i] != ')' && namestring[i] != '>') { next2 += namestring[i] ; ++i ;} - } - } - - cert._trustLvl = 1 ; // to be setup accordingly - cert._validLvl = 1 ; // to be setup accordingly - cert._key_index = index ; - cert._flags = 0 ; - cert._time_stamp = 0 ;// "never" by default. Will be updated by trust database, and effective key usage. - - switch(keydata->key.pkey.algorithm) - { - case OPS_PKA_RSA: cert._type = PGPCertificateInfo::PGP_CERTIFICATE_TYPE_RSA ; - break ; - case OPS_PKA_DSA: cert._type = PGPCertificateInfo::PGP_CERTIFICATE_TYPE_DSA ; - cert._flags |= PGPCertificateInfo::PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM ; - break ; - default: cert._type = PGPCertificateInfo::PGP_CERTIFICATE_TYPE_UNKNOWN ; - cert._flags |= PGPCertificateInfo::PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM ; - break ; - } - - ops_fingerprint_t f ; - ops_fingerprint(&f,&keydata->key.pkey) ; - - cert._fpr = PGPFingerprintType(f.fingerprint) ; -} - -bool PGPHandler::validateAndUpdateSignatures(PGPCertificateInfo& cert,const ops_keydata_t *keydata) -{ - ops_validate_result_t* result=(ops_validate_result_t*)ops_mallocz(sizeof *result); - ops_boolean_t res = ops_validate_key_signatures(result,keydata,_pubring,cb_get_passphrase) ; - - if(res == ops_false) - { - static ops_boolean_t already = 0 ; - if(!already) - { - std::cerr << "(WW) Error in PGPHandler::validateAndUpdateSignatures(). Validation failed for at least some signatures." << std::endl; - already = 1 ; - } - } - - bool ret = false ; - - // Parse signers. - // - - if(result != NULL) - for(size_t i=0;ivalid_count;++i) - { - RsPgpId signer_id(result->valid_sigs[i].signer_id); - - if(cert.signers.find(signer_id) == cert.signers.end()) - { - cert.signers.insert(signer_id) ; - ret = true ; - } - } - - ops_validate_result_free(result) ; - - return ret ; -} - -PGPHandler::~PGPHandler() -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. -#ifdef DEBUG_PGPHANDLER - std::cerr << "Freeing PGPHandler. Deleting keyrings." << std::endl; -#endif - - // no need to free the the _map_ elements. They will be freed by the following calls: - // - ops_keyring_free(_pubring) ; - ops_keyring_free(_secring) ; - - free(_pubring) ; - free(_secring) ; -} - -bool PGPHandler::printKeys() const -{ -#ifdef DEBUG_PGPHANDLER - std::cerr << "Printing details of all " << std::dec << _public_keyring_map.size() << " keys: " << std::endl; -#endif - - for(std::map::const_iterator it(_public_keyring_map.begin()); it != _public_keyring_map.end(); ++it) - { - std::cerr << "PGP Key: " << it->first.toStdString() << std::endl; - - std::cerr << "\tName : " << it->second._name << std::endl; - std::cerr << "\tEmail : " << it->second._email << std::endl; - std::cerr << "\tOwnSign : " << (it->second._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE) << std::endl; - std::cerr << "\tAccept Connect: " << (it->second._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION) << std::endl; - std::cerr << "\ttrustLvl : " << it->second._trustLvl << std::endl; - std::cerr << "\tvalidLvl : " << it->second._validLvl << std::endl; - std::cerr << "\tUse time stamp: " << it->second._time_stamp << std::endl; - std::cerr << "\tfingerprint : " << it->second._fpr.toStdString() << std::endl; - std::cerr << "\tSigners : " << it->second.signers.size() << std::endl; - - std::set::const_iterator sit; - for(sit = it->second.signers.begin(); sit != it->second.signers.end(); ++sit) - { - std::cerr << "\t\tSigner ID:" << (*sit).toStdString() << ", Name: " ; - const PGPCertificateInfo *info = PGPHandler::getCertificateInfo(*sit) ; - - if(info != NULL) - std::cerr << info->_name ; - - std::cerr << std::endl ; - } - } - std::cerr << "Public keyring list from OPS:" << std::endl; - ops_keyring_list(_pubring) ; - - return true ; -} - -bool PGPHandler::haveSecretKey(const RsPgpId& id) const -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - return locked_getSecretKey(id) != NULL ; -} - -const PGPCertificateInfo *PGPHandler::getCertificateInfo(const RsPgpId& id) const -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - std::map::const_iterator it( _public_keyring_map.find(id) ) ; - - if(it != _public_keyring_map.end()) - return &it->second; - else - return NULL ; -} - -bool PGPHandler::availableGPGCertificatesWithPrivateKeys(std::list& ids) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - // go through secret keyring, and check that we have the pubkey as well. - // - - const ops_keydata_t *keydata = NULL ; - int i=0 ; - - while( (keydata = ops_keyring_get_key_by_index(_secring,i++)) != NULL ) - if(ops_keyring_find_key_by_id(_pubring,keydata->key_id) != NULL) // check that the key is in the pubring as well - { -#ifdef PGPHANDLER_DSA_SUPPORT - if(keydata->key.pkey.algorithm == OPS_PKA_RSA || keydata->key.pkey.algorithm == OPS_PKA_DSA) -#else - if(keydata->key.pkey.algorithm == OPS_PKA_RSA) -#endif - ids.push_back(RsPgpId(keydata->key_id)) ; -#ifdef DEBUG_PGPHANDLER - else - std::cerr << "Skipping keypair " << RsPgpId(keydata->key_id).toStdString() << ", unsupported algorithm: " << keydata->key.pkey.algorithm << std::endl; -#endif - } - - return true ; -} - -bool PGPHandler::GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passphrase, RsPgpId& pgpId, const int keynumbits, std::string& errString) -{ - // Some basic checks - - if(!RsDiscSpace::checkForDiscSpace(RS_PGP_DIRECTORY)) - { - errString = std::string("(EE) low disc space in pgp directory. Can't write safely to keyring.") ; - return false ; - } - if(name.length() > PGP_CERTIFICATE_LIMIT_MAX_NAME_SIZE) - { - errString = std::string("(EE) name in certificate exceeds the maximum allowed name size") ; - return false ; - } - if(email.length() > PGP_CERTIFICATE_LIMIT_MAX_EMAIL_SIZE) - { - errString = std::string("(EE) email in certificate exceeds the maximum allowed email size") ; - return false ; - } - if(passphrase.length() > PGP_CERTIFICATE_LIMIT_MAX_PASSWD_SIZE) - { - errString = std::string("(EE) passphrase in certificate exceeds the maximum allowed passphrase size") ; - return false ; - } - if(keynumbits % 1024 != 0) - { - errString = std::string("(EE) RSA key length is not a multiple of 1024") ; - return false ; - } - - // Now the real thing - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - RsStackFileLock flck(_pgp_lock_filename) ; // lock access to PGP directory. - - // 1 - generate keypair - RSA-2048 - // - ops_user_id_t uid ; - char *s = strdup((name + " (Generated by RetroShare) <" + email + ">" ).c_str()) ; - uid.user_id = (unsigned char *)s ; - unsigned long int e = 65537 ; // some prime number - - ops_keydata_t *key = ops_rsa_create_selfsigned_keypair(keynumbits, e, &uid) ; - - free(s) ; - - if(!key) - return false ; - - // 2 - save the private key encrypted to a temporary memory buffer, so as to read an encrypted key to memory - - ops_create_info_t *cinfo = NULL ; - ops_memory_t *buf = NULL ; - ops_setup_memory_write(&cinfo, &buf, 0); - - if(!ops_write_transferable_secret_key(key,(unsigned char *)passphrase.c_str(),passphrase.length(),ops_false,cinfo)) - { - errString = std::string("(EE) Cannot encode secret key to memory!!") ; - return false ; - } - - // 3 - read the memory chunk into an encrypted keyring - - ops_keyring_t *tmp_secring = allocateOPSKeyring() ; - - if(! ops_keyring_read_from_mem(tmp_secring, ops_false, buf)) - { - errString = std::string("(EE) Cannot re-read key from memory!!") ; - return false ; - } - ops_teardown_memory_write(cinfo,buf); // cleanup memory - - // 4 - copy the encrypted private key to the private keyring - - pgpId = RsPgpId(tmp_secring->keys[0].key_id) ; - addNewKeyToOPSKeyring(_secring,tmp_secring->keys[0]) ; - initCertificateInfo(_secret_keyring_map[ pgpId ],&tmp_secring->keys[0],_secring->nkeys-1) ; - -#ifdef DEBUG_PGPHANDLER - std::cerr << "Added new secret key with id " << pgpId.toStdString() << " to secret keyring." << std::endl; -#endif - ops_keyring_free(tmp_secring) ; - free(tmp_secring) ; - - // 5 - add key to secret keyring on disk. - - cinfo = NULL ; - std::string secring_path_tmp = _secring_path + ".tmp" ; - - if(RsDirUtil::fileExists(_secring_path) && !RsDirUtil::copyFile(_secring_path,secring_path_tmp)) - { - errString= std::string("Cannot copy secret keyring !! Disk full? Out of disk quota?") ; - return false ; - } - int fd=ops_setup_file_append(&cinfo, secring_path_tmp.c_str()); - - if(!ops_write_transferable_secret_key(key,(unsigned char *)passphrase.c_str(),passphrase.length(),ops_false,cinfo)) - { - errString= std::string("Cannot encode secret key to disk!! Disk full? Out of disk quota?") ; - return false ; - } - ops_teardown_file_write(cinfo,fd) ; - - if(!RsDirUtil::renameFile(secring_path_tmp,_secring_path)) - { - errString= std::string("Cannot rename tmp secret key file ") + secring_path_tmp + " into " + _secring_path +". Disk error?" ; - return false ; - } - - // 6 - copy the public key to the public keyring on disk - - cinfo = NULL ; - std::string pubring_path_tmp = _pubring_path + ".tmp" ; - - if(RsDirUtil::fileExists(_pubring_path) && !RsDirUtil::copyFile(_pubring_path,pubring_path_tmp)) - { - errString= std::string("Cannot encode secret key to disk!! Disk full? Out of disk quota?") ; - return false ; - } - fd=ops_setup_file_append(&cinfo, pubring_path_tmp.c_str()); - - if(!ops_write_transferable_public_key(key, ops_false, cinfo)) - { - errString=std::string("Cannot encode secret key to memory!!") ; - return false ; - } - ops_teardown_file_write(cinfo,fd) ; - - if(!RsDirUtil::renameFile(pubring_path_tmp,_pubring_path)) - { - errString= std::string("Cannot rename tmp public key file ") + pubring_path_tmp + " into " + _pubring_path +". Disk error?" ; - return false ; - } - // 7 - clean - ops_keydata_free(key) ; - - // 8 - re-read the key from the public keyring, and add it to memory. - - _pubring_last_update_time = 0 ; // force update pubring from disk. - locked_syncPublicKeyring() ; - -#ifdef DEBUG_PGPHANDLER - std::cerr << "Added new public key with id " << pgpId.toStdString() << " to public keyring." << std::endl; -#endif - - // 9 - Update some flags. - - privateTrustCertificate(pgpId,PGPCertificateInfo::PGP_CERTIFICATE_TRUST_ULTIMATE) ; - - return true ; -} - -std::string PGPHandler::makeRadixEncodedPGPKey(const ops_keydata_t *key,bool include_signatures) -{ - ops_create_info_t* cinfo; - ops_memory_t *buf = NULL ; - ops_setup_memory_write(&cinfo, &buf, 0); - ops_boolean_t armoured = ops_true ; - - if(key->type == OPS_PTAG_CT_PUBLIC_KEY) - { - if(ops_write_transferable_public_key_from_packet_data(key,armoured,cinfo) != ops_true) - return "ERROR: This key cannot be processed by RetroShare because\nDSA certificates are not yet handled." ; - } - else if(key->type == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) - { - if(ops_write_transferable_secret_key_from_packet_data(key,armoured,cinfo) != ops_true) - return "ERROR: This key cannot be processed by RetroShare because\nDSA certificates are not yet handled." ; - } - else - { - ops_create_info_delete(cinfo); - std::cerr << "Unhandled key type " << key->type << std::endl; - return "ERROR: Cannot write key. Unhandled key type. " ; - } - - ops_writer_close(cinfo) ; - - std::string res((char *)ops_memory_get_data(buf),ops_memory_get_length(buf)) ; - ops_teardown_memory_write(cinfo,buf); - - if(!include_signatures) - { - std::string tmp ; - if(PGPKeyManagement::createMinimalKey(res,tmp) ) - res = tmp ; - } - - return res ; -} - -const ops_keydata_t *PGPHandler::locked_getSecretKey(const RsPgpId& id) const -{ - std::map::const_iterator res = _secret_keyring_map.find(id) ; - - if(res == _secret_keyring_map.end()) - return NULL ; - else - return ops_keyring_get_key_by_index(_secring,res->second._key_index) ; -} -const ops_keydata_t *PGPHandler::locked_getPublicKey(const RsPgpId& id,bool stamp_the_key) const -{ - std::map::const_iterator res = _public_keyring_map.find(id) ; - - if(res == _public_keyring_map.end()) - return NULL ; - else - { - if(stamp_the_key) // Should we stamp the key as used? - { - static rstime_t last_update_db_because_of_stamp = 0 ; - rstime_t now = time(NULL) ; - - res->second._time_stamp = now ; - - if(now > last_update_db_because_of_stamp + 3600) // only update database once every hour. No need to do it more often. - { - _trustdb_changed = true ; - last_update_db_because_of_stamp = now ; - } - } - return ops_keyring_get_key_by_index(_pubring,res->second._key_index) ; - } -} - -std::string PGPHandler::SaveCertificateToString(const RsPgpId& id,bool include_signatures) const -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - const ops_keydata_t *key = locked_getPublicKey(id,false) ; - - if(key == NULL) - { - std::cerr << "Cannot output key " << id.toStdString() << ": not found in keyring." << std::endl; - return "" ; - } - - return makeRadixEncodedPGPKey(key,include_signatures) ; -} - -bool PGPHandler::exportPublicKey( - const RsPgpId& id, - unsigned char*& mem_block, size_t& mem_size, - bool armoured, bool include_signatures ) const -{ - mem_block = nullptr; mem_size = 0; // clear just in case - - if(armoured) - { - RsErr() << __PRETTY_FUNCTION__ << " should not be used with " - << "armoured=true, because there's a bug in the armoured export" - << " of OPS" << std::endl; - print_stacktrace(); - return false; - } - - RS_STACK_MUTEX(pgphandlerMtx); - const ops_keydata_t* key = locked_getPublicKey(id,false); - - if(!key) - { - RsErr() << __PRETTY_FUNCTION__ << " key id: " << id - << " not found in keyring." << std::endl; - return false; - } - - ops_create_info_t* cinfo; - ops_memory_t *buf = nullptr; - ops_setup_memory_write(&cinfo, &buf, 0); - - if(ops_write_transferable_public_key_from_packet_data( - key, armoured, cinfo ) != ops_true) - { - RsErr() << __PRETTY_FUNCTION__ << " This key id " << id - << " cannot be processed by RetroShare because DSA certificates" - << " support is not implemented yet." << std::endl; - return false; - } - - ops_writer_close(cinfo); - - mem_size = ops_memory_get_length(buf); - mem_block = reinterpret_cast(malloc(mem_size)); - memcpy(mem_block,ops_memory_get_data(buf),mem_size); - - ops_teardown_memory_write(cinfo,buf); - - if(!include_signatures) - { - size_t new_size; - PGPKeyManagement::findLengthOfMinimalKey(mem_block, mem_size, new_size); - mem_size = new_size; - } - - return true; -} - -bool PGPHandler::exportGPGKeyPair(const std::string& filename,const RsPgpId& exported_key_id) const -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - const ops_keydata_t *pubkey = locked_getPublicKey(exported_key_id,false) ; - - if(pubkey == NULL) - { - std::cerr << "Cannot output key " << exported_key_id.toStdString() << ": not found in public keyring." << std::endl; - return false ; - } - const ops_keydata_t *seckey = locked_getSecretKey(exported_key_id) ; - - if(seckey == NULL) - { - std::cerr << "Cannot output key " << exported_key_id.toStdString() << ": not found in secret keyring." << std::endl; - return false ; - } - - FILE *f = RsDirUtil::rs_fopen(filename.c_str(),"w") ; - if(f == NULL) - { - std::cerr << "Cannot output key " << exported_key_id.toStdString() << ": file " << filename << " cannot be written. Please check for permissions, quotas, disk space." << std::endl; - return false ; - } - - fprintf(f,"%s\n", makeRadixEncodedPGPKey(pubkey,true).c_str()) ; - fprintf(f,"%s\n", makeRadixEncodedPGPKey(seckey,true).c_str()) ; - - fclose(f) ; - return true ; -} - -bool PGPHandler::exportGPGKeyPairToString( - std::string& data, const RsPgpId& exportedKeyId, - bool includeSignatures, std::string& errorMsg ) const -{ - RS_STACK_MUTEX(pgphandlerMtx); - - const ops_keydata_t *pubkey = locked_getPublicKey(exportedKeyId,false); - - if(!pubkey) - { - errorMsg = "Cannot output key " + exportedKeyId.toStdString() + - ": not found in public keyring."; - return false; - } - const ops_keydata_t *seckey = locked_getSecretKey(exportedKeyId); - - if(!seckey) - { - errorMsg = "Cannot output key " + exportedKeyId.toStdString() + - ": not found in secret keyring."; - return false; - } - - data = makeRadixEncodedPGPKey(pubkey, includeSignatures); - data += "\n"; - data += makeRadixEncodedPGPKey(seckey, includeSignatures); - data += "\n"; - return true; -} - -bool PGPHandler::getGPGDetailsFromBinaryBlock(const unsigned char *mem_block,size_t mem_size,RsPgpId& key_id, std::string& name, std::list& signers) const -{ - ops_keyring_t *tmp_keyring = allocateOPSKeyring(); - ops_memory_t *mem = ops_memory_new() ; - ops_memory_add(mem,mem_block,mem_size); - - if(!ops_keyring_read_from_mem(tmp_keyring,ops_false,mem)) - { - ops_keyring_free(tmp_keyring) ; - free(tmp_keyring) ; - ops_memory_release(mem) ; - free(mem) ; - - std::cerr << "Could not read key. Format error?" << std::endl; - //error_string = std::string("Could not read key. Format error?") ; - return false ; - } - ops_memory_release(mem) ; - free(mem) ; - //error_string.clear() ; - - if(tmp_keyring->nkeys != 1) - { - std::cerr << "No or incomplete/invalid key in supplied pgp block." << std::endl; - return false ; - } - if(tmp_keyring->keys[0].uids == NULL) - { - std::cerr << "No uid in supplied key." << std::endl; - return false ; - } - - key_id = RsPgpId(tmp_keyring->keys[0].key_id) ; - name = std::string((char *)tmp_keyring->keys[0].uids[0].user_id) ; - - // now parse signatures. - // - ops_validate_result_t* result=(ops_validate_result_t*)ops_mallocz(sizeof *result); - ops_boolean_t res ; - - { - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - res = ops_validate_key_signatures(result,&tmp_keyring->keys[0],_pubring,cb_get_passphrase) ; - } - - if(res == ops_false) - std::cerr << "(WW) Error in PGPHandler::validateAndUpdateSignatures(). Validation failed for at least some signatures." << std::endl; - - // also add self-signature if any (there should be!). - // - res = ops_validate_key_signatures(result,&tmp_keyring->keys[0],tmp_keyring,cb_get_passphrase) ; - - if(res == ops_false) - std::cerr << "(WW) Error in PGPHandler::validateAndUpdateSignatures(). Validation failed for at least some signatures." << std::endl; - - // Parse signers. - // - - std::set signers_set ; // Use a set to remove duplicates. - - if(result != NULL) - for(size_t i=0;ivalid_count;++i) - signers_set.insert(RsPgpId(result->valid_sigs[i].signer_id)) ; - - ops_validate_result_free(result) ; - - ops_keyring_free(tmp_keyring) ; - free(tmp_keyring) ; - - // write to the output variable - - signers.clear() ; - - for(std::set::const_iterator it(signers_set.begin());it!=signers_set.end();++it) - signers.push_back(*it) ; - - return true ; -} - -bool PGPHandler::importGPGKeyPair(const std::string& filename,RsPgpId& imported_key_id,std::string& import_error) -{ - import_error = "" ; - - // 1 - Test for file existance - // - FILE *ftest = RsDirUtil::rs_fopen(filename.c_str(),"r") ; - - if(ftest == NULL) - { - import_error = "Cannot open file " + filename + " for read. Please check access permissions." ; - return false ; - } - - fclose(ftest) ; - - // 2 - Read keyring from supplied file. - // - ops_keyring_t *tmp_keyring = allocateOPSKeyring(); - - if(ops_false == ops_keyring_read_from_file(tmp_keyring, ops_true, filename.c_str())) - { - import_error = "PGPHandler::readKeyRing(): cannot read key file. File corrupted?" ; - free(tmp_keyring); - return false ; - } - - return checkAndImportKeyPair(tmp_keyring, imported_key_id, import_error); -} - -bool PGPHandler::importGPGKeyPairFromString(const std::string &data, RsPgpId &imported_key_id, std::string &import_error) -{ - import_error = "" ; - - ops_memory_t* mem = ops_memory_new(); - ops_memory_add(mem, (unsigned char*)data.data(), data.length()); - - ops_keyring_t *tmp_keyring = allocateOPSKeyring(); - - if(ops_false == ops_keyring_read_from_mem(tmp_keyring, ops_true, mem)) - { - import_error = "PGPHandler::importGPGKeyPairFromString(): cannot parse key data" ; - free(tmp_keyring); - return false ; - } - return checkAndImportKeyPair(tmp_keyring, imported_key_id, import_error); -} - -bool PGPHandler::checkAndImportKeyPair(ops_keyring_t *tmp_keyring, RsPgpId &imported_key_id, std::string &import_error) -{ - if(tmp_keyring == 0) - { - import_error = "PGPHandler::checkAndImportKey(): keyring is null" ; - return false; - } - - if(tmp_keyring->nkeys != 2) - { - import_error = "PGPHandler::importKeyPair(): file does not contain a valid keypair." ; - if(tmp_keyring->nkeys > 2) - import_error += "\nMake sure that your key is a RSA key (DSA is not yet supported) and does not contain subkeys (not supported yet)."; - return false ; - } - - // 3 - Test that keyring contains a valid keypair. - // - const ops_keydata_t *pubkey = NULL ; - const ops_keydata_t *seckey = NULL ; - - if(tmp_keyring->keys[0].type == OPS_PTAG_CT_PUBLIC_KEY) - pubkey = &tmp_keyring->keys[0] ; - else if(tmp_keyring->keys[0].type == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) - seckey = &tmp_keyring->keys[0] ; - else - { - import_error = "Unrecognised key type in key file for key #0. Giving up." ; - std::cerr << "Unrecognised key type " << tmp_keyring->keys[0].type << " in key file for key #0. Giving up." << std::endl; - return false ; - } - if(tmp_keyring->keys[1].type == OPS_PTAG_CT_PUBLIC_KEY) - pubkey = &tmp_keyring->keys[1] ; - else if(tmp_keyring->keys[1].type == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) - seckey = &tmp_keyring->keys[1] ; - else - { - import_error = "Unrecognised key type in key file for key #1. Giving up." ; - std::cerr << "Unrecognised key type " << tmp_keyring->keys[1].type << " in key file for key #1. Giving up." << std::endl; - return false ; - } - - if(pubkey == nullptr || seckey == nullptr || pubkey == seckey) - { - import_error = "File does not contain a public and a private key. Sorry." ; - return false ; - } - if(memcmp( pubkey->fingerprint.fingerprint, - seckey->fingerprint.fingerprint, - RsPgpFingerprint::SIZE_IN_BYTES ) != 0) - { - import_error = "Public and private keys do nt have the same fingerprint. Sorry!" ; - return false ; - } - if(pubkey->key.pkey.version != 4) - { - import_error = "Public key is not version 4. Rejected!" ; - return false ; - } - - // 4 - now check self-signature for this keypair. For this we build a dummy keyring containing only the key. - // - ops_validate_result_t *result=(ops_validate_result_t*)ops_mallocz(sizeof *result); - - ops_keyring_t dummy_keyring ; - dummy_keyring.nkeys=1 ; - dummy_keyring.nkeys_allocated=1 ; - dummy_keyring.keys=const_cast(pubkey) ; - - ops_validate_key_signatures(result, const_cast(pubkey), &dummy_keyring, cb_get_passphrase) ; - - // Check that signatures contain at least one certification from the user id. - // - bool found = false ; - - for(uint32_t i=0;ivalid_count;++i) - if(!memcmp( - static_cast(result->valid_sigs[i].signer_id), - pubkey->key_id, - RsPgpId::SIZE_IN_BYTES )) - { - found = true ; - break ; - } - - if(!found) - { - import_error = "Cannot validate self signature for the imported key. Sorry." ; - return false ; - } - ops_validate_result_free(result); - - if(!RsDiscSpace::checkForDiscSpace(RS_PGP_DIRECTORY)) - { - import_error = std::string("(EE) low disc space in pgp directory. Can't write safely to keyring.") ; - return false ; - } - // 5 - All test passed. Adding key to keyring. - // - { - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - imported_key_id = RsPgpId(pubkey->key_id) ; - - if(locked_getSecretKey(imported_key_id) == NULL) - { - RsStackFileLock flck(_pgp_lock_filename) ; // lock access to PGP directory. - - ops_create_info_t *cinfo = NULL ; - - // Make a copy of the secret keyring - // - std::string secring_path_tmp = _secring_path + ".tmp" ; - if(RsDirUtil::fileExists(_secring_path) && !RsDirUtil::copyFile(_secring_path,secring_path_tmp)) - { - import_error = "(EE) Cannot write secret key to disk!! Disk full? Out of disk quota. Keyring will be left untouched." ; - return false ; - } - - // Append the new key - - int fd=ops_setup_file_append(&cinfo, secring_path_tmp.c_str()); - - if(!ops_write_transferable_secret_key_from_packet_data(seckey,ops_false,cinfo)) - { - import_error = "(EE) Cannot encode secret key to disk!! Disk full? Out of disk quota?" ; - return false ; - } - ops_teardown_file_write(cinfo,fd) ; - - // Rename the new keyring to overwrite the old one. - // - if(!RsDirUtil::renameFile(secring_path_tmp,_secring_path)) - { - import_error = " (EE) Cannot move temp file " + secring_path_tmp + ". Bad write permissions?" ; - return false ; - } - - addNewKeyToOPSKeyring(_secring,*seckey) ; - initCertificateInfo(_secret_keyring_map[ imported_key_id ],seckey,_secring->nkeys-1) ; - } - else - import_error = "Private key already exists! Not importing it again." ; - - if(locked_addOrMergeKey(_pubring,_public_keyring_map,pubkey)) - _pubring_changed = true ; - } - - // 6 - clean - // - ops_keyring_free(tmp_keyring) ; - free(tmp_keyring); - - // write public key to disk - syncDatabase(); - - return true ; -} - -void PGPHandler::addNewKeyToOPSKeyring(ops_keyring_t *kr,const ops_keydata_t& key) -{ - if(kr->nkeys >= kr->nkeys_allocated) - { - kr->keys = (ops_keydata_t *)realloc(kr->keys,(kr->nkeys+1)*sizeof(ops_keydata_t)) ; - kr->nkeys_allocated = kr->nkeys+1; - } - memset(&kr->keys[kr->nkeys],0,sizeof(ops_keydata_t)) ; - ops_keydata_copy(&kr->keys[kr->nkeys],&key) ; - kr->nkeys++ ; -} - -bool PGPHandler::LoadCertificateFromBinaryData(const unsigned char *data,uint32_t data_len,RsPgpId& id,std::string& error_string) -{ - return LoadCertificate(data,data_len,ops_false,id,error_string); -} - -bool PGPHandler::LoadCertificateFromString(const std::string& pgp_cert,RsPgpId& id,std::string& error_string) -{ - return LoadCertificate((unsigned char*)(pgp_cert.c_str()),pgp_cert.length(),ops_true,id,error_string); -} - -bool PGPHandler::LoadCertificate(const unsigned char *data,uint32_t data_len,bool armoured,RsPgpId& id,std::string& error_string) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. -#ifdef DEBUG_PGPHANDLER - std::cerr << "Reading new key from string: " << std::endl; -#endif - - ops_keyring_t *tmp_keyring = allocateOPSKeyring(); - ops_memory_t *mem = ops_memory_new() ; - ops_memory_add(mem,data,data_len) ; - - if(!ops_keyring_read_from_mem(tmp_keyring,armoured,mem)) - { - ops_keyring_free(tmp_keyring) ; - free(tmp_keyring) ; - ops_memory_release(mem) ; - free(mem) ; - - std::cerr << "Could not read key. Format error?" << std::endl; - error_string = std::string("Could not read key. Format error?") ; - return false ; - } - ops_memory_release(mem) ; - free(mem) ; - error_string.clear() ; - - // Check that there is exactly one key in this data packet. - // - if(tmp_keyring->nkeys != 1) - { - std::cerr << "Loaded certificate contains more than one PGP key. This is not allowed." << std::endl; - error_string = "Loaded certificate contains more than one PGP key. This is not allowed." ; - return false ; - } - - const ops_keydata_t *keydata = ops_keyring_get_key_by_index(tmp_keyring,0); - - // Check that the key is a version 4 key - // - if(keydata->key.pkey.version != 4) - { - error_string = "Public key is not version 4. Rejected!" ; - std::cerr << "Received a key with unhandled version number (" << keydata->key.pkey.version << ")" << std::endl; - return false ; - } - - // Check that the key is correctly self-signed. - // - ops_validate_result_t* result=(ops_validate_result_t*)ops_mallocz(sizeof *result); - - ops_validate_key_signatures(result,keydata,tmp_keyring,cb_get_passphrase) ; - - bool found = false ; - - for(uint32_t i=0;ivalid_count;++i) - if(!memcmp( - static_cast(result->valid_sigs[i].signer_id), - keydata->key_id, - RsPgpId::SIZE_IN_BYTES )) - { - found = true ; - break ; - } - - if(!found) - { - error_string = "This key is not self-signed. This is required by Retroshare." ; - std::cerr << "This key is not self-signed. This is required by Retroshare." << std::endl; - ops_validate_result_free(result); - return false ; - } - ops_validate_result_free(result); - -#ifdef DEBUG_PGPHANDLER - std::cerr << " Key read correctly: " << std::endl; - ops_keyring_list(tmp_keyring) ; -#endif - - int i=0 ; - - while( (keydata = ops_keyring_get_key_by_index(tmp_keyring,i++)) != NULL ) - if(locked_addOrMergeKey(_pubring,_public_keyring_map,keydata)) - { - _pubring_changed = true ; -#ifdef DEBUG_PGPHANDLER - std::cerr << " Added the key in the main public keyring." << std::endl; -#endif - } - else - std::cerr << "Key already in public keyring." << std::endl; - - if(tmp_keyring->nkeys > 0) - id = RsPgpId(tmp_keyring->keys[0].key_id) ; - else - return false ; - - ops_keyring_free(tmp_keyring) ; - free(tmp_keyring) ; - - _pubring_changed = true ; - - return true ; -} - -bool PGPHandler::locked_addOrMergeKey(ops_keyring_t *keyring,std::map& kmap,const ops_keydata_t *keydata) -{ - bool ret = false ; - RsPgpId id(keydata->key_id) ; - -#ifdef DEBUG_PGPHANDLER - std::cerr << "AddOrMergeKey():" << std::endl; - std::cerr << " id: " << id.toStdString() << std::endl; -#endif - - // See if the key is already in the keyring - const ops_keydata_t *existing_key = NULL; - std::map::const_iterator res = kmap.find(id) ; - - // Checks that - // - the key is referenced by keyid - // - the map is initialized - // - the fingerprint matches! - // - if(res == kmap.end() || (existing_key = ops_keyring_get_key_by_index(keyring,res->second._key_index)) == NULL) - { -#ifdef DEBUG_PGPHANDLER - std::cerr << " Key is new. Adding it to keyring" << std::endl; -#endif - addNewKeyToOPSKeyring(keyring,*keydata) ; // the key is new. - initCertificateInfo(kmap[id],keydata,keyring->nkeys-1) ; - existing_key = &(keyring->keys[keyring->nkeys-1]) ; - ret = true ; - } - else - { - if(memcmp( existing_key->fingerprint.fingerprint, - keydata->fingerprint.fingerprint, - RsPgpFingerprint::SIZE_IN_BYTES )) - { - std::cerr << "(EE) attempt to merge key with identical id, but different fingerprint!" << std::endl; - return false ; - } - -#ifdef DEBUG_PGPHANDLER - std::cerr << " Key exists. Merging signatures." << std::endl; -#endif - ret = mergeKeySignatures(const_cast(existing_key),keydata) ; - - if(ret) - initCertificateInfo(kmap[id],existing_key,res->second._key_index) ; - } - - if(ret) - { - validateAndUpdateSignatures(kmap[id],existing_key) ; - kmap[id]._time_stamp = time(NULL) ; - } - - return ret ; -} - -bool PGPHandler::encryptTextToFile(const RsPgpId& key_id,const std::string& text,const std::string& outfile) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - const ops_keydata_t *public_key = locked_getPublicKey(key_id,true) ; - - if(public_key == NULL) - { - std::cerr << "Cannot get public key of id " << key_id.toStdString() << std::endl; - return false ; - } - - if(public_key->type != OPS_PTAG_CT_PUBLIC_KEY) - { - std::cerr << "PGPHandler::encryptTextToFile(): ERROR: supplied id did not return a public key!" << std::endl; - return false ; - } - - std::string outfile_tmp = outfile + ".tmp" ; - - ops_create_info_t *info; - int fd = ops_setup_file_write(&info, outfile_tmp.c_str(), ops_true); - - if (fd < 0) - { - std::cerr << "PGPHandler::encryptTextToFile(): ERROR: Cannot write to " << outfile_tmp << std::endl; - return false ; - } - - if(!ops_encrypt_stream(info, public_key, NULL, ops_false, ops_true)) - { - std::cerr << "PGPHandler::encryptTextToFile(): ERROR: encryption failed." << std::endl; - return false ; - } - - ops_write(text.c_str(), text.length(), info); - ops_teardown_file_write(info, fd); - - if(!RsDirUtil::renameFile(outfile_tmp,outfile)) - { - std::cerr << "PGPHandler::encryptTextToFile(): ERROR: Cannot rename " + outfile_tmp + " to " + outfile + ". Disk error?" << std::endl; - return false ; - } - - return true ; -} - -bool PGPHandler::encryptDataBin(const RsPgpId& key_id,const void *data, const uint32_t len, unsigned char *encrypted_data, unsigned int *encrypted_data_len) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - const ops_keydata_t *public_key = locked_getPublicKey(key_id,true) ; - - if(public_key == NULL) - { - std::cerr << "Cannot get public key of id " << key_id.toStdString() << std::endl; - return false ; - } - - if(public_key->type != OPS_PTAG_CT_PUBLIC_KEY) - { - std::cerr << "PGPHandler::encryptTextToFile(): ERROR: supplied id did not return a public key!" << std::endl; - return false ; - } - if(public_key->key.pkey.algorithm != OPS_PKA_RSA) - { - std::cerr << "PGPHandler::encryptTextToFile(): ERROR: supplied key id " << key_id.toStdString() << " is not an RSA key (DSA for instance, is not supported)!" << std::endl; - return false ; - } - ops_create_info_t *info; - ops_memory_t *buf = NULL ; - ops_setup_memory_write(&info, &buf, 0); - bool res = true; - - if(!ops_encrypt_stream(info, public_key, NULL, ops_false, ops_false)) - { - std::cerr << "Encryption failed." << std::endl; - res = false ; - } - - ops_write(data,len,info); - ops_writer_close(info); - ops_create_info_delete(info); - - int tlen = ops_memory_get_length(buf) ; - - if( (int)*encrypted_data_len >= tlen) - { - if(res) - { - memcpy(encrypted_data,ops_memory_get_data(buf),tlen) ; - *encrypted_data_len = tlen ; - res = true ; - } - } - else - { - std::cerr << "Not enough room to fit encrypted data. Size given=" << *encrypted_data_len << ", required=" << tlen << std::endl; - res = false ; - } - - ops_memory_release(buf) ; - free(buf) ; - - return res ; -} - -bool PGPHandler::decryptDataBin(const RsPgpId& /*key_id*/,const void *encrypted_data, const uint32_t encrypted_len, unsigned char *data, unsigned int *data_len) -{ - int out_length ; - unsigned char *out ; - ops_boolean_t res = ops_decrypt_memory((const unsigned char *)encrypted_data,encrypted_len,&out,&out_length,_secring,ops_false,cb_get_passphrase) ; - - if(*data_len < (unsigned int)out_length) - { - std::cerr << "Not enough room to store decrypted data! Please give more."<< std::endl; - return false ; - } - - *data_len = (unsigned int)out_length ; - memcpy(data,out,out_length) ; - free(out) ; - - return (bool)res ; -} - -bool PGPHandler::decryptTextFromFile(const RsPgpId&,std::string& text,const std::string& inputfile) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - unsigned char *out_buf = NULL ; - std::string buf ; - - FILE *f = RsDirUtil::rs_fopen(inputfile.c_str(),"rb") ; - - if (f == NULL) - { - std::cerr << "Cannot open file " << inputfile << " for read." << std::endl; - return false; - } - - int c ; - while( (c = fgetc(f))!= EOF) - buf += (unsigned char)c; - - fclose(f) ; - -#ifdef DEBUG_PGPHANDLER - std::cerr << "PGPHandler::decryptTextFromFile: read a file of length " << std::dec << buf.length() << std::endl; - std::cerr << "buf=\"" << buf << "\"" << std::endl; -#endif - - int out_length ; - ops_boolean_t res = ops_decrypt_memory((const unsigned char *)buf.c_str(),buf.length(),&out_buf,&out_length,_secring,ops_true,cb_get_passphrase) ; - - text = std::string((char *)out_buf,out_length) ; - free (out_buf); - return (bool)res ; -} - -bool PGPHandler::SignDataBin(const RsPgpId& id,const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,bool use_raw_signature, std::string reason /* = "" */) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - // need to find the key and to decrypt it. - - const ops_keydata_t *key = locked_getSecretKey(id) ; - - if(!key) - { - std::cerr << "Cannot sign: no secret key with id " << id.toStdString() << std::endl; - return false ; - } - - std::string uid_hint ; - if(key->nuids > 0) - uid_hint = std::string((const char *)key->uids[0].user_id) ; - uid_hint += "(" + RsPgpId(key->key_id).toStdString()+")" ; - -#ifdef DEBUG_PGPHANDLER - ops_fingerprint_t f ; - ops_fingerprint(&f,&key->key.pkey) ; - - PGPFingerprintType fp(f.fingerprint) ; -#endif - - bool last_passwd_was_wrong = false ; -ops_secret_key_t *secret_key = NULL ; - - for(int i=0;i<3;++i) - { - bool cancelled =false; - std::string passphrase = _passphrase_callback(NULL,reason.c_str(),uid_hint.c_str(),"Please enter passwd for encrypting your key : ",last_passwd_was_wrong,&cancelled) ;//TODO reason - - secret_key = ops_decrypt_secret_key_from_data(key,passphrase.c_str()) ; - - if(cancelled) - { - std::cerr << "Key entering cancelled" << std::endl; - return false ; - } - if(secret_key) - break ; - - std::cerr << "Key decryption went wrong. Wrong passwd?" << std::endl; - last_passwd_was_wrong = true ; - } - if(!secret_key) - { - std::cerr << "Could not obtain secret key. Signature cancelled." << std::endl; - return false ; - } - - // then do the signature. - - ops_boolean_t not_raw = !use_raw_signature ; -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_002 - ops_memory_t *memres = ops_sign_buf(data,len,OPS_SIG_BINARY,OPS_HASH_SHA256,secret_key,ops_false,ops_false,not_raw,not_raw) ; -#else - ops_memory_t *memres = ops_sign_buf(data,len,OPS_SIG_BINARY,OPS_HASH_SHA1,secret_key,ops_false,ops_false,not_raw,not_raw) ; -#endif - - if(!memres) - return false ; - - bool res ; - uint32_t slen = (uint32_t)ops_memory_get_length(memres); - - if(*signlen >= slen) - { - *signlen = slen ; - - memcpy(sign,ops_memory_get_data(memres),*signlen) ; - res = true ; - } - else - { - std::cerr << "(EE) memory chunk is not large enough for signature packet. Requred size: " << slen << " bytes." << std::endl; - res = false ; - } - - ops_memory_release(memres) ; - free(memres) ; - ops_secret_key_free(secret_key) ; - free(secret_key) ; - -#ifdef DEBUG_PGPHANDLER - std::cerr << "Signed with fingerprint " << fp.toStdString() << ", length " << std::dec << *signlen << ", literal data length = " << len << std::endl; - std::cerr << "Signature body: " << std::endl; - hexdump( (unsigned char *)data, len) ; - std::cerr << std::endl; - std::cerr << "Data: " << std::endl; - hexdump( (unsigned char *)sign,*signlen) ; - std::cerr << std::endl; -#endif - return res ; -} - -bool PGPHandler::privateSignCertificate(const RsPgpId& ownId,const RsPgpId& id_of_key_to_sign) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - ops_keydata_t *key_to_sign = const_cast(locked_getPublicKey(id_of_key_to_sign,true)) ; - - if(key_to_sign == NULL) - { - std::cerr << "Cannot sign: no public key with id " << id_of_key_to_sign.toStdString() << std::endl; - return false ; - } - - // 1 - get decrypted secret key - // - const ops_keydata_t *skey = locked_getSecretKey(ownId) ; - - if(!skey) - { - std::cerr << "Cannot sign: no secret key with id " << ownId.toStdString() << std::endl; - return false ; - } - const ops_keydata_t *pkey = locked_getPublicKey(ownId,true) ; - - if(!pkey) - { - std::cerr << "Cannot sign: no public key with id " << ownId.toStdString() << std::endl; - return false ; - } - - bool cancelled = false; - std::string passphrase = _passphrase_callback(NULL,"",RsPgpId(skey->key_id).toStdString().c_str(),"Please enter passwd for encrypting your key : ",false,&cancelled) ; - - ops_secret_key_t *secret_key = ops_decrypt_secret_key_from_data(skey,passphrase.c_str()) ; - - if(cancelled) - { - std::cerr << "Key cancelled by used." << std::endl; - return false ; - } - if(!secret_key) - { - std::cerr << "Key decryption went wrong. Wrong passwd?" << std::endl; - return false ; - } - - // 2 - then do the signature. - - if(!ops_sign_key(key_to_sign,pkey->key_id,secret_key)) - { - std::cerr << "Key signature went wrong. Wrong passwd?" << std::endl; - return false ; - } - - // 3 - free memory - // - ops_secret_key_free(secret_key) ; - free(secret_key) ; - - _pubring_changed = true ; - - // 4 - update signatures. - // - PGPCertificateInfo& cert(_public_keyring_map[ id_of_key_to_sign ]) ; - validateAndUpdateSignatures(cert,key_to_sign) ; - cert._flags |= PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ; - - return true ; -} - -void PGPHandler::updateOwnSignatureFlag(const RsPgpId& own_id) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - if(_public_keyring_map.find(own_id)==_public_keyring_map.end()) - { - std::cerr << __func__ << ": key with id=" << own_id.toStdString() << " not in keyring." << std::endl; - // return now, because the following operation would add an entry to _public_keyring_map - return; - } - - PGPCertificateInfo& own_cert(_public_keyring_map[ own_id ]) ; - - for(std::map::iterator it=_public_keyring_map.begin();it!=_public_keyring_map.end();++it) - locked_updateOwnSignatureFlag(it->second,it->first,own_cert,own_id) ; -} -void PGPHandler::updateOwnSignatureFlag(const RsPgpId& cert_id,const RsPgpId& own_id) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - std::map::iterator it( _public_keyring_map.find(cert_id) ) ; - - if(it == _public_keyring_map.end()) - { - std::cerr << "updateOwnSignatureFlag: Cannot get certificate for string " << cert_id.toStdString() << ". This is probably a bug." << std::endl; - return ; - } - - PGPCertificateInfo& cert( it->second ); - - PGPCertificateInfo& own_cert(_public_keyring_map[ own_id ]) ; - - locked_updateOwnSignatureFlag(cert,cert_id,own_cert,own_id) ; -} -void PGPHandler::locked_updateOwnSignatureFlag(PGPCertificateInfo& cert,const RsPgpId& cert_id,PGPCertificateInfo& own_cert,const RsPgpId& own_id_str) -{ - if(cert.signers.find(own_id_str) != cert.signers.end()) - cert._flags |= PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ; - else - cert._flags &= ~PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ; - - if(own_cert.signers.find( cert_id ) != own_cert.signers.end()) - cert._flags |= PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME ; - else - cert._flags &= ~PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME ; -} - -/*static*/ RsPgpId PGPHandler::pgpIdFromFingerprint(const RsPgpFingerprint& f) -{ - return RsPgpId::fromBufferUnsafe( - f.toByteArray() + - RsPgpFingerprint::SIZE_IN_BYTES - RsPgpId::SIZE_IN_BYTES ); -} - -bool PGPHandler::getKeyFingerprint(const RsPgpId& id, RsPgpFingerprint& fp) const -{ - RS_STACK_MUTEX(pgphandlerMtx); - - const ops_keydata_t *key = locked_getPublicKey(id,false) ; - - if(!key) return false; - - ops_fingerprint_t f ; - ops_fingerprint(&f,&key->key.pkey) ; - - fp = RsPgpFingerprint::fromBufferUnsafe(f.fingerprint); - - return true ; -} - -bool PGPHandler::VerifySignBin(const void *literal_data, uint32_t literal_data_length, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& key_fingerprint) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - RsPgpId id = RsPgpId(key_fingerprint.toByteArray() + PGPFingerprintType::SIZE_IN_BYTES - RsPgpId::SIZE_IN_BYTES) ; - const ops_keydata_t *key = locked_getPublicKey(id,true) ; - - if(key == NULL) - { - std::cerr << "No key returned by fingerprint " << key_fingerprint.toStdString() << ", and ID " << id.toStdString() << ", signature verification failed!" << std::endl; - return false ; - } - - // Check that fingerprint is the same. - const ops_public_key_t *pkey = &key->key.pkey ; - ops_fingerprint_t fp ; - ops_fingerprint(&fp,pkey) ; - - if(key_fingerprint != PGPFingerprintType(fp.fingerprint)) - { - std::cerr << "Key fingerprint does not match " << key_fingerprint.toStdString() << ", for ID " << id.toStdString() << ", signature verification failed!" << std::endl; - return false ; - } - -#ifdef DEBUG_PGPHANDLER - std::cerr << "Verifying signature from fingerprint " << key_fingerprint.toStdString() << ", length " << std::dec << sign_len << ", literal data length = " << literal_data_length << std::endl; - std::cerr << "Signature body: " << std::endl; - hexdump( (unsigned char *)sign,sign_len) ; - std::cerr << std::endl; - std::cerr << "Signed data: " << std::endl; - hexdump( (unsigned char *)literal_data, literal_data_length) ; - std::cerr << std::endl; -#endif - - return ops_validate_detached_signature(literal_data,literal_data_length,sign,sign_len,key) ; -} - -void PGPHandler::setAcceptConnexion(const RsPgpId& id,bool b) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - std::map::iterator res = _public_keyring_map.find(id) ; - - if(res != _public_keyring_map.end()) - { - if(b) - res->second._flags |= PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ; - else - res->second._flags &= ~PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ; - } -} - -bool PGPHandler::getGPGFilteredList(std::list& list,bool (*filter)(const PGPCertificateInfo&)) const -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP directory. - list.clear() ; - - for(std::map::const_iterator it(_public_keyring_map.begin());it!=_public_keyring_map.end();++it) - if( filter == NULL || (*filter)(it->second) ) - list.push_back(RsPgpId(it->first)) ; - - return true ; -} - -bool PGPHandler::isPgpPubKeyAvailable(const RsPgpId &id) -{ return _public_keyring_map.find(id) != _public_keyring_map.end(); } - -bool PGPHandler::isGPGId(const RsPgpId &id) -{ - return _public_keyring_map.find(id) != _public_keyring_map.end() ; -} - -bool PGPHandler::isGPGSigned(const RsPgpId &id) -{ - std::map::const_iterator res = _public_keyring_map.find(id) ; - return res != _public_keyring_map.end() && (res->second._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE) ; -} - -bool PGPHandler::isGPGAccepted(const RsPgpId &id) -{ - std::map::const_iterator res = _public_keyring_map.find(id) ; - return (res != _public_keyring_map.end()) && (res->second._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION) ; -} - -// Lexicographic order on signature packets -// -bool operator<(const ops_packet_t& p1,const ops_packet_t& p2) -{ - if(p1.length < p2.length) - return true ; - if(p1.length > p2.length) - return false ; - - for(uint32_t i=0;i p2.raw[i]) - return false ; - } - return false ; -} - -bool PGPHandler::mergeKeySignatures(ops_keydata_t *dst,const ops_keydata_t *src) -{ - // First sort all signatures into lists to see which is new, which is not new - -#ifdef DEBUG_PGPHANDLER - std::cerr << "Merging signatures for key " << RsPgpId(dst->key_id).toStdString() << std::endl; -#endif - std::set dst_packets ; - - for(uint32_t i=0;inpackets;++i) dst_packets.insert(dst->packets[i]) ; - - std::set to_add ; - - for(uint32_t i=0;inpackets;++i) - if(dst_packets.find(src->packets[i]) == dst_packets.end()) - { - uint8_t tag ; - uint32_t length ; - unsigned char *tmp_data = src->packets[i].raw ; // put it in a tmp variable because read_packetHeader() will modify it!! - - PGPKeyParser::read_packetHeader(tmp_data,tag,length) ; - - if(tag == PGPKeyParser::PGP_PACKET_TAG_SIGNATURE) - to_add.insert(src->packets[i]) ; -#ifdef DEBUG_PGPHANDLER - else - std::cerr << " Packet with tag 0x" << std::hex << (int)(src->packets[i].raw[0]) << std::dec << " not merged, because it is not a signature." << std::endl; -#endif - } - - for(std::set::const_iterator it(to_add.begin());it!=to_add.end();++it) - { -#ifdef DEBUG_PGPHANDLER - std::cerr << " Adding packet with tag 0x" << std::hex << (int)(*it).raw[0] << std::dec << std::endl; -#endif - ops_add_packet_to_keydata(dst,&*it) ; - } - return to_add.size() > 0 ; -} - -bool PGPHandler::parseSignature(unsigned char *sign, unsigned int signlen,RsPgpId& issuer_id) -{ - PGPSignatureInfo info ; - - if(!PGPKeyManagement::parseSignature(sign,signlen,info)) - return false ; - - unsigned char bytes[8] ; - for(int i=0;i<8;++i) - { - bytes[7-i] = info.issuer & 0xff ; - info.issuer >>= 8 ; - } - issuer_id = RsPgpId(bytes) ; - - return true ; -} - -bool PGPHandler::privateTrustCertificate(const RsPgpId& id,int trustlvl) -{ - if(trustlvl < 0 || trustlvl >= 6 || trustlvl == 1) - { - std::cerr << "Invalid trust level " << trustlvl << " passed to privateTrustCertificate." << std::endl; - return false ; - } - - std::map::iterator it = _public_keyring_map.find(id); - - if(it == _public_keyring_map.end()) - { - std::cerr << "(EE) Key id " << id.toStdString() << " not in the keyring. Can't setup trust level." << std::endl; - return false ; - } - - if( (int)it->second._trustLvl != trustlvl ) - _trustdb_changed = true ; - - it->second._trustLvl = trustlvl ; - - return true ; -} - -struct PrivateTrustPacket -{ - /// pgp id in unsigned char format. - unsigned char user_id[RsPgpId::SIZE_IN_BYTES]; - uint8_t trust_level ; // trust level. From 0 to 6. - uint32_t time_stamp ; // last time the cert was ever used, in seconds since the epoch. 0 means not initialized. -}; - -void PGPHandler::locked_readPrivateTrustDatabase() -{ - FILE *fdb = RsDirUtil::rs_fopen(_trustdb_path.c_str(),"rb") ; -#ifdef DEBUG_PGPHANDLER - std::cerr << "PGPHandler: Reading private trust database." << std::endl; -#endif - - if(fdb == NULL) - { - std::cerr << " private trust database not found. No trust info loaded." << std::endl ; - return ; - } - std::map::iterator it ; - PrivateTrustPacket trustpacket; - int n_packets = 0 ; - - while(fread((void*)&trustpacket,sizeof(PrivateTrustPacket),1,fdb) == 1) - { - it = _public_keyring_map.find(RsPgpId(trustpacket.user_id)) ; - - if(it == _public_keyring_map.end()) - { - std::cerr << " (WW) Trust packet found for unknown key id " << RsPgpId(trustpacket.user_id).toStdString() << std::endl; - continue ; - } - if(trustpacket.trust_level > 6) - { - std::cerr << " (WW) Trust packet found with unexpected trust level " << trustpacket.trust_level << std::endl; - continue ; - } - - ++n_packets ; - it->second._trustLvl = trustpacket.trust_level ; - - if(trustpacket.time_stamp > it->second._time_stamp) // only update time stamp if the loaded time stamp is newer - it->second._time_stamp = trustpacket.time_stamp ; - } - - fclose(fdb) ; - - std::cerr << "PGPHandler: Successfully read " << std::hex << n_packets << std::dec << " trust packets." << std::endl; -} - -bool PGPHandler::locked_writePrivateTrustDatabase() -{ - FILE *fdb = RsDirUtil::rs_fopen((_trustdb_path+".tmp").c_str(),"wb") ; -#ifdef DEBUG_PGPHANDLER - std::cerr << "PGPHandler: Reading private trust database." << std::endl; -#endif - - if(fdb == NULL) - { - std::cerr << " (EE) Can't open private trust database file " << _trustdb_path << " for write. Giving up!" << std::endl ; - return false; - } - PrivateTrustPacket trustpacket ; - /* Clear PrivateTrustPacket struct to suppress valgrind warnings due to the compiler extra padding*/ - memset(&trustpacket, 0, sizeof(PrivateTrustPacket)); - - for( std::map::iterator it = - _public_keyring_map.begin(); it!=_public_keyring_map.end(); ++it ) - { - memcpy( trustpacket.user_id, - it->first.toByteArray(), - RsPgpId::SIZE_IN_BYTES ); - trustpacket.trust_level = it->second._trustLvl ; - trustpacket.time_stamp = it->second._time_stamp ; - - if(fwrite((void*)&trustpacket,sizeof(PrivateTrustPacket),1,fdb) != 1) - { - std::cerr << " (EE) Cannot write to trust database " << _trustdb_path << ". Disc full, or quota exceeded ? Leaving database untouched." << std::endl; - fclose(fdb) ; - return false; - } - } - - fclose(fdb) ; - - if(!RsDirUtil::renameFile(_trustdb_path+".tmp",_trustdb_path)) - { - std::cerr << " (EE) Cannot move temp file " << _trustdb_path+".tmp" << ". Bad write permissions?" << std::endl; - return false ; - } - else - return true ; -} - -bool PGPHandler::syncDatabase() -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - RsStackFileLock flck(_pgp_lock_filename) ; // lock access to PGP directory. - -#ifdef DEBUG_PGPHANDLER - std::cerr << "Sync-ing keyrings." << std::endl; -#endif - locked_syncPublicKeyring() ; - //locked_syncSecretKeyring() ; - - // Now sync the trust database as well. - // - locked_syncTrustDatabase() ; - -#ifdef DEBUG_PGPHANDLER - std::cerr << "Done. " << std::endl; -#endif - return true ; -} - -bool PGPHandler::locked_syncPublicKeyring() -{ - struct stat64 buf ; -#ifdef WINDOWS_SYS - std::wstring wfullname; - librs::util::ConvertUtf8ToUtf16(_pubring_path, wfullname); - if(-1 == _wstati64(wfullname.c_str(), &buf)) -#else - if(-1 == stat64(_pubring_path.c_str(), &buf)) -#endif - std::cerr << "PGPHandler::syncDatabase(): can't stat file " << _pubring_path << ". Can't sync public keyring." << std::endl; - - if(_pubring_last_update_time < buf.st_mtime) - { - std::cerr << "Detected change on disk of public keyring. Merging!" << std::endl ; - - locked_mergeKeyringFromDisk(_pubring,_public_keyring_map,_pubring_path) ; - _pubring_last_update_time = buf.st_mtime ; - } - - // Now check if the pubring was locally modified, which needs saving it again - if(_pubring_changed && RsDiscSpace::checkForDiscSpace(RS_PGP_DIRECTORY)) - { - std::string tmp_keyring_file = _pubring_path + ".tmp" ; - - std::cerr << "Local changes in public keyring. Writing to disk..." << std::endl; - if(!ops_write_keyring_to_file(_pubring,ops_false,tmp_keyring_file.c_str(),ops_true)) - { - std::cerr << "Cannot write public keyring tmp file. Disk full? Disk quota exceeded?" << std::endl; - return false ; - } - if(!RsDirUtil::renameFile(tmp_keyring_file,_pubring_path)) - { - std::cerr << "Cannot rename tmp pubring file " << tmp_keyring_file << " into actual pubring file " << _pubring_path << ". Check writing permissions?!?" << std::endl; - return false ; - } - - std::cerr << "Done." << std::endl; - _pubring_last_update_time = time(NULL) ; // should we get this value from the disk instead?? - _pubring_changed = false ; - } - return true ; -} - -bool PGPHandler::locked_syncTrustDatabase() -{ - struct stat64 buf ; -#ifdef WINDOWS_SYS - std::wstring wfullname; - librs::util::ConvertUtf8ToUtf16(_trustdb_path, wfullname); - if(-1 == _wstati64(wfullname.c_str(), &buf)) -#else - if(-1 == stat64(_trustdb_path.c_str(), &buf)) -#endif - { - std::cerr << "PGPHandler::syncDatabase(): can't stat file " << _trustdb_path << ". Will force write it." << std::endl; - _trustdb_changed = true ; // we force write of trust database if it does not exist. - } - - if(_trustdb_last_update_time < buf.st_mtime) - { - std::cerr << "Detected change on disk of trust database. " << std::endl ; - - locked_readPrivateTrustDatabase(); - _trustdb_last_update_time = time(NULL) ; - } - - if(_trustdb_changed) - { - std::cerr << "Local changes in trust database. Writing to disk..." << std::endl; - if(!locked_writePrivateTrustDatabase()) - std::cerr << "Cannot write trust database. Disk full? Disk quota exceeded?" << std::endl; - else - { - std::cerr << "Done." << std::endl; - _trustdb_last_update_time = time(NULL) ; - _trustdb_changed = false ; - } - } - return true ; -} -void PGPHandler::locked_mergeKeyringFromDisk( ops_keyring_t *keyring, - std::map& kmap, - const std::string& keyring_file) -{ -#ifdef DEBUG_PGPHANDLER - std::cerr << "Merging keyring " << keyring_file << " from disk to memory." << std::endl; -#endif - - // 1 - load keyring into a temporary keyring list. - ops_keyring_t *tmp_keyring = PGPHandler::allocateOPSKeyring() ; - - if(ops_false == ops_keyring_read_from_file(tmp_keyring, false, keyring_file.c_str())) - { - std::cerr << "PGPHandler::locked_mergeKeyringFromDisk(): cannot read keyring. File corrupted?" ; - ops_keyring_free(tmp_keyring) ; - return ; - } - - // 2 - load new keys and merge existing key signatures - - for(int i=0;inkeys;++i) - locked_addOrMergeKey(keyring,kmap,&tmp_keyring->keys[i]) ;// we dont' account for the return value. This is disk merging, not local changes. - - // 4 - clean - ops_keyring_free(tmp_keyring) ; -} - -bool PGPHandler::removeKeysFromPGPKeyring(const std::set& keys_to_remove,std::string& backup_file,uint32_t& error_code) -{ - // 1 - lock everything. - // - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - RsStackFileLock flck(_pgp_lock_filename) ; // lock access to PGP directory. - - error_code = PGP_KEYRING_REMOVAL_ERROR_NO_ERROR ; - - for(std::set::const_iterator it(keys_to_remove.begin());it!=keys_to_remove.end();++it) - if(locked_getSecretKey(*it) != NULL) - { - std::cerr << "(EE) PGPHandler:: can't remove key " << (*it).toStdString() << " since its shared by a secret key! Operation cancelled." << std::endl; - error_code = PGP_KEYRING_REMOVAL_ERROR_CANT_REMOVE_SECRET_KEYS ; - return false ; - } - - // 2 - sync everything. - // - locked_syncPublicKeyring() ; - - // 3 - make a backup of the public keyring - // - char template_name[_pubring_path.length()+8] ; - sprintf(template_name,"%s.XXXXXX",_pubring_path.c_str()) ; - -#if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8 - int fd_keyring_backup(mkstemp(template_name)); - if (fd_keyring_backup == -1) -#else - if(mktemp(template_name) == NULL) -#endif - { - std::cerr << "PGPHandler::removeKeysFromPGPKeyring(): cannot create keyring backup file. Giving up." << std::endl; - error_code = PGP_KEYRING_REMOVAL_ERROR_CANNOT_CREATE_BACKUP ; - return false ; - } -#if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8 - close(fd_keyring_backup); // TODO: keep the file open and use the fd -#endif - - if(!ops_write_keyring_to_file(_pubring,ops_false,template_name,ops_true)) - { - std::cerr << "PGPHandler::removeKeysFromPGPKeyring(): cannot write keyring backup file. Giving up." << std::endl; - error_code = PGP_KEYRING_REMOVAL_ERROR_CANNOT_WRITE_BACKUP ; - return false ; - } - backup_file = std::string(template_name,_pubring_path.length()+7) ; - - std::cerr << "Keyring was backed up to file " << backup_file << std::endl; - - // Remove keys from the keyring, and update the keyring map. - // - for(std::set::const_iterator it(keys_to_remove.begin());it!=keys_to_remove.end();++it) - { - if(locked_getSecretKey(*it) != NULL) - { - std::cerr << "(EE) PGPHandler:: can't remove key " << (*it).toStdString() << " since its shared by a secret key!" << std::endl; - continue ; - } - - std::map::iterator res = _public_keyring_map.find(*it) ; - - if(res == _public_keyring_map.end()) - { - std::cerr << "(EE) PGPHandler:: can't remove key " << (*it).toStdString() << " from keyring: key not found." << std::endl; - continue ; - } - - if(res->second._key_index >= (unsigned int)_pubring->nkeys || RsPgpId(_pubring->keys[res->second._key_index].key_id) != *it) - { - std::cerr << "(EE) PGPHandler:: can't remove key " << (*it).toStdString() << ". Inconsistency found." << std::endl; - error_code = PGP_KEYRING_REMOVAL_ERROR_DATA_INCONSISTENCY ; - return false ; - } - - // Move the last key to the freed place. This deletes the key in place. - // - ops_keyring_remove_key(_pubring,res->second._key_index) ; - - // Erase the info from the keyring map. - // - _public_keyring_map.erase(res) ; - - // now update all indices back. This internal look is very costly, but it avoids deleting the wrong keys, since the keyring structure is - // changed by ops_keyring_remove_key and therefore indices don't point to the correct location anymore. - - int i=0 ; - const ops_keydata_t *keydata ; - while( (keydata = ops_keyring_get_key_by_index(_pubring,i)) != NULL ) - { - PGPCertificateInfo& cert(_public_keyring_map[ RsPgpId(keydata->key_id) ]) ; - cert._key_index = i ; - ++i ; - } - } - - // Everything went well, sync back the keyring on disk - - _pubring_changed = true ; - _trustdb_changed = true ; - - locked_syncPublicKeyring() ; - locked_syncTrustDatabase() ; - - return true ; -} diff --git a/libretroshare/src/pgp/pgphandler.h b/libretroshare/src/pgp/pgphandler.h deleted file mode 100644 index 5d7eb82f8..000000000 --- a/libretroshare/src/pgp/pgphandler.h +++ /dev/null @@ -1,259 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: pgphandler.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -extern "C" { -#include -#include -#include -} - -typedef std::string (*PassphraseCallback)(void *data, const char *uid_title, const char *uid_hint, const char *passphrase_info, int prev_was_bad,bool *cancelled) ; - -class PGPCertificateInfo -{ - public: - PGPCertificateInfo() : _trustLvl(0), _validLvl(0), _flags(0), _type(0), _time_stamp(0), _key_index(0) {} - - std::string _name; - std::string _email; - std::string _comment; - - std::set signers; - - uint32_t _trustLvl; - uint32_t _validLvl; - uint32_t _flags ; - uint32_t _type ; - - mutable rstime_t _time_stamp ; // last time the key was used (received, used for signature verification, etc) - - PGPFingerprintType _fpr; /* fingerprint */ - // RsPgpId _key_id ; - - uint32_t _key_index ; // index to array of keys in the public keyring - - static const uint32_t PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION = 0x0001 ; - static const uint32_t PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE = 0x0002 ; - static const uint32_t PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME = 0x0004 ; - static const uint32_t PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM = 0x0008 ; // set when the key is not RSA, so that RS avoids to use it. - - static const uint8_t PGP_CERTIFICATE_TRUST_UNDEFINED = 0x00 ; - static const uint8_t PGP_CERTIFICATE_TRUST_NEVER = 0x02 ; - static const uint8_t PGP_CERTIFICATE_TRUST_MARGINALLY = 0x03 ; - static const uint8_t PGP_CERTIFICATE_TRUST_FULLY = 0x04 ; - static const uint8_t PGP_CERTIFICATE_TRUST_ULTIMATE = 0x05 ; - - static const uint8_t PGP_CERTIFICATE_TYPE_UNKNOWN = 0x00 ; - static const uint8_t PGP_CERTIFICATE_TYPE_DSA = 0x01 ; - static const uint8_t PGP_CERTIFICATE_TYPE_RSA = 0x02 ; -}; - -/// This class offer an abstract pgp handler to be used in RetroShare. -class PGPHandler -{ -public: - PGPHandler( const std::string& path_to_public_keyring, - const std::string& path_to_secret_keyring, - const std::string& path_to_trust_database, - const std::string& pgp_lock_file) ; - - virtual ~PGPHandler() ; - - /** - * @param ids list of gpg certificate ids (note, not the actual certificates) - */ - bool getGPGFilteredList(std::list& list,bool (*filter)(const PGPCertificateInfo&) = NULL) const ; - bool haveSecretKey(const RsPgpId& id) const ; - - bool importGPGKeyPair(const std::string& filename,RsPgpId& imported_id,std::string& import_error) ; - bool importGPGKeyPairFromString(const std::string& data,RsPgpId& imported_id,std::string& import_error) ; - bool exportGPGKeyPair(const std::string& filename,const RsPgpId& exported_id) const ; - bool exportGPGKeyPairToString( - std::string& data, const RsPgpId& exportedKeyId, - bool includeSignatures, std::string& errorMsg ) const; - - bool availableGPGCertificatesWithPrivateKeys(std::list& ids); - bool GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId& pgpId, const int keynumbits, std::string& errString) ; - - bool LoadCertificateFromString(const std::string& pem, RsPgpId& gpg_id, std::string& error_string); - bool LoadCertificateFromBinaryData(const unsigned char *bin_data,uint32_t bin_data_len, RsPgpId& gpg_id, std::string& error_string); - - std::string SaveCertificateToString(const RsPgpId& id,bool include_signatures) const ; - - /** The caller is in charge of freeing `mem` once finished */ - bool exportPublicKey( const RsPgpId& id, - unsigned char*& mem, size_t& mem_size, - bool armoured, bool include_signatures) const; - - bool parseSignature(unsigned char *sign, unsigned int signlen,RsPgpId& issuer_id) ; - bool SignDataBin(const RsPgpId& id, const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, bool make_raw_signature=false, std::string reason = "") ; - bool VerifySignBin(const void *data, uint32_t data_len, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& withfingerprint) ; - bool privateSignCertificate(const RsPgpId& own_id,const RsPgpId& id_of_key_to_sign) ; - - // The client should supply a memory chunk to store the data. The length will be updated to the real length of the data. - // - bool encryptDataBin(const RsPgpId& key_id,const void *data, const uint32_t len - , unsigned char *encrypted_data, unsigned int *encrypted_data_len) ; - bool decryptDataBin(const RsPgpId& key_id,const void *encrypted_data, const uint32_t encrypted_len - , unsigned char *data, unsigned int *data_len) ; - - bool encryptTextToFile(const RsPgpId& key_id,const std::string& text,const std::string& outfile) ; - bool decryptTextFromFile(const RsPgpId& key_id,std::string& text,const std::string& encrypted_inputfile) ; - - void setAcceptConnexion(const RsPgpId&,bool) ; - - void updateOwnSignatureFlag(const RsPgpId& ownId) ; - void updateOwnSignatureFlag(const RsPgpId& pgp_id,const RsPgpId& ownId) ; - - void locked_updateOwnSignatureFlag(PGPCertificateInfo&, const RsPgpId&, PGPCertificateInfo&, const RsPgpId&) ; - - // Removes the given keys from the keyring. Also backup the keyring to a file which name is automatically generated - // and given pack for proper display. - // - bool removeKeysFromPGPKeyring(const std::set& key_ids,std::string& backup_file,uint32_t& error_code) ; - - //bool isKeySupported(const RsPgpId& id) const ; - - bool privateTrustCertificate(const RsPgpId& id,int valid_level) ; - - // Write keyring - - //bool writeSecretKeyring() ; - //bool writePublicKeyring() ; - - const PGPCertificateInfo *getCertificateInfo(const RsPgpId& id) const ; - - RS_DEPRECATED_FOR(isPgpPubKeyAvailable) - bool isGPGId(const RsPgpId &id); - bool isGPGSigned(const RsPgpId &id); - bool isGPGAccepted(const RsPgpId &id); - - static void setPassphraseCallback(PassphraseCallback cb) ; - static PassphraseCallback passphraseCallback() { return _passphrase_callback ; } - - /** - * @brief Check if a PGP publick key is available - * @param id id of the key to check - * @return true if the public key for the given id is available, - * false otherwise - */ - bool isPgpPubKeyAvailable(const RsPgpId& id); - - /** - * @brief Convert PGP fingerprint to PGP 64bit id - * @param f PGP fingerprint to convert - * @return PGP 64bit id extracted from fingerprint - */ - static RsPgpId pgpIdFromFingerprint(const RsPgpFingerprint& f); - - /** - * @brief Get PGP fingerprint for the given key - * @param id PGP 64bit key id - * @param fp storage for the retrived key fingerpring, the contained value - * is meaningfull only if true is returned - * @return true if the key was found, false if not - */ - bool getKeyFingerprint(const RsPgpId& id, RsPgpFingerprint& fp) const; - - // Gets info about the key. Who are the signers, what's the owner's name, etc. - // - bool getGPGDetailsFromBinaryBlock(const unsigned char *mem,size_t mem_size,RsPgpId& key_id, std::string& name, std::list& signers) const ; - - // Debug stuff. - virtual bool printKeys() const ; - - // Syncs the keyrings and trust database between memory and disk. The algorithm is: - // 1 - lock the keyrings - // 2 - compare file modification dates with last writing date - // - if file is modified, load it, and merge with memory - // 3 - look into memory modification flags - // - if flag says keyring has changed, write to disk - // - bool syncDatabase() ; - - private: - bool LoadCertificate(const unsigned char *bin_data,uint32_t bin_data_len, bool armoured, RsPgpId& gpg_id, std::string& error_string); - void initCertificateInfo(PGPCertificateInfo& cert,const ops_keydata_t *keydata,uint32_t i) ; - - // Returns true if the signatures have been updated - // - bool validateAndUpdateSignatures(PGPCertificateInfo& cert,const ops_keydata_t *keydata) ; - - /** Check public/private key and import them into the keyring - * @param keyring keyring with the new public/private key pair. Will be freed by the function. - * @param imported_key_id PGP id of the imported key - * @param import_error human readbale error message - * @returns true on success - * */ - bool checkAndImportKeyPair(ops_keyring_t *keyring, RsPgpId& imported_key_id,std::string& import_error); - - const ops_keydata_t *locked_getPublicKey(const RsPgpId&,bool stamp_the_key) const; - const ops_keydata_t *locked_getSecretKey(const RsPgpId&) const ; - - void locked_readPrivateTrustDatabase() ; - bool locked_writePrivateTrustDatabase() ; - - bool locked_syncPublicKeyring() ; - bool locked_syncTrustDatabase() ; - - void locked_mergeKeyringFromDisk(ops_keyring_t *keyring, std::map& kmap, const std::string& keyring_file) ; - bool locked_addOrMergeKey(ops_keyring_t *keyring,std::map& kmap,const ops_keydata_t *keydata) ; - - // Members. - // - mutable RsMutex pgphandlerMtx ; - - ops_keyring_t *_pubring ; - ops_keyring_t *_secring ; - - std::map _public_keyring_map ; // used for fast access to keys. Gives the index in the keyring. - std::map _secret_keyring_map ; - - const std::string _pubring_path ; - const std::string _secring_path ; - const std::string _trustdb_path ; - const std::string _pgp_lock_filename ; - - bool _pubring_changed ; - mutable bool _trustdb_changed ; - - rstime_t _pubring_last_update_time ; - rstime_t _secring_last_update_time ; - rstime_t _trustdb_last_update_time ; - - // Helper functions. - // - static std::string makeRadixEncodedPGPKey(const ops_keydata_t *key,bool include_signatures) ; - static ops_keyring_t *allocateOPSKeyring() ; - static void addNewKeyToOPSKeyring(ops_keyring_t*, const ops_keydata_t&) ; - static PassphraseCallback _passphrase_callback ; - static bool mergeKeySignatures(ops_keydata_t *dst,const ops_keydata_t *src) ; // returns true if signature lists are different -}; diff --git a/libretroshare/src/pgp/pgpkeyutil.cc b/libretroshare/src/pgp/pgpkeyutil.cc deleted file mode 100644 index 76b332edf..000000000 --- a/libretroshare/src/pgp/pgpkeyutil.cc +++ /dev/null @@ -1,373 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: pgpkeyutil.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include -#include "pgpkeyutil.h" - -#include -#include - -/****************************/ -/* #define DEBUG_PGPUTIL 1 */ -/****************************/ - -#define PGP_CRC24_INIT 0xB704CEL -#define PGP_CRC24_POLY 0x1864CFBL - -#define PGP_CERTIFICATE_START_STRING "-----BEGIN PGP PUBLIC KEY BLOCK-----" -#define PGP_CERTIFICATE_END_STRING "-----END PGP PUBLIC KEY BLOCK-----" -// -// All size are big endian -// MPI: 2 bytes size (length in bits) + string of octets -// -bool PGPKeyManagement::createMinimalKey(const std::string& pgp_certificate,std::string& cleaned_certificate) -{ - try - { - // 0 - Extract Radix64 portion of the certificate - // - std::string version_string ; - std::string radix_cert = PGPKeyParser::extractRadixPartFromArmouredKey(pgp_certificate,version_string) ; - - // 1 - Convert armored key into binary key - // - std::vector keydata = Radix64::decode(radix_cert) ; - - size_t new_len ; - findLengthOfMinimalKey(keydata.data(), keydata.size(), new_len) ; - - cleaned_certificate = makeArmouredKey(keydata.data(), new_len, version_string) ; - return true ; - } - catch(std::exception& e) - { - cleaned_certificate = "" ; - std::cerr << "Certificate cleaning failed: " << e.what() << std::endl; - return false ; - } -} - -void PGPKeyManagement::findLengthOfMinimalKey(const unsigned char *keydata,size_t len,size_t& new_len) -{ - unsigned char *data = (unsigned char *)keydata ; - -#ifdef DEBUG_PGPUTIL - std::cerr << "Total size: " << len << std::endl; -#endif - - uint8_t packet_tag; - uint32_t packet_length ; - - // 2 - parse key data, only keep public key data, user id and self-signature. - - bool public_key=false ; - bool own_signature=false ; - bool user_id=false ; - - while(true) - { - PGPKeyParser::read_packetHeader(data,packet_tag,packet_length) ; -#ifdef DEBUG_PGPUTIL - std::cerr << "Header:" << std::endl; - std::cerr << " Packet tag: " << (int)packet_tag << std::endl; - std::cerr << " Packet length: " << packet_length << std::endl; -#endif - - data += packet_length ; - - if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_PUBLIC_KEY) - public_key = true ; - if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_USER_ID) - user_id = true ; - if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_SIGNATURE) - own_signature = true ; - - if(public_key && own_signature && user_id) - break ; - - if( (uint64_t)data - (uint64_t)keydata >= len ) - break ; - } - - new_len = (uint64_t)data - (uint64_t)keydata ; -} - -std::string PGPKeyParser::extractRadixPartFromArmouredKey(const std::string& pgp_certificate,std::string& version_string) -{ - int n = pgp_certificate.length() ; - int i=0 ; - version_string = "" ; - - while(i < n && pgp_certificate[i] != '\n') ++i ; // remove first part -----BEGIN PGP CERTIFICATE----- - ++i ; - while(i < n && pgp_certificate[i] != '\n') version_string += pgp_certificate[i++] ; // remove first part Version: [fdfdfdf] - ++i ; - while(i < n && pgp_certificate[i] != '\n') ++i ; // remove blank line - - ++i ; - - int j=n-1 ; - - while(j>0 && pgp_certificate[j] != '=' && j>=i) --j ; - - std::string radix_cert = pgp_certificate.substr(i,j-i) ; - -#ifdef DEBUG_PGPUTIL - std::cerr << "extracted radix cert: " << std::endl; - std::cerr << radix_cert ; -#endif - return radix_cert ; -} - - -std::string PGPKeyManagement::makeArmouredKey(const unsigned char *keydata,size_t key_size,const std::string& version_string) -{ - std::string outstring ; - Radix64::encode(keydata,key_size,outstring) ; - - uint32_t crc = compute24bitsCRC((unsigned char *)keydata,key_size) ; - - unsigned char tmp[3] = { uint8_t((crc >> 16) & 0xff), uint8_t((crc >> 8) & 0xff), uint8_t(crc & 0xff) } ; - std::string crc_string ; - Radix64::encode(tmp,3,crc_string) ; - -#ifdef DEBUG_PGPUTIL - std::cerr << "After signature pruning: " << std::endl; - std::cerr << outstring << std::endl; -#endif - - std::string certificate = std::string(PGP_CERTIFICATE_START_STRING) + "\n" + version_string + "\n\n" ; - - for(uint32_t i=0;i= hashed_size ) - break ; - } - // non hashed sub-packets are ignored for now. - - return issuer_found ; -} - -uint64_t PGPKeyParser::read_KeyID(unsigned char *& data) -{ - uint64_t val = 0 ; - - val |= uint64_t( *data ) << 56 ; ++data ; - val |= uint64_t( *data ) << 48 ; ++data ; - val |= uint64_t( *data ) << 40 ; ++data ; - val |= uint64_t( *data ) << 32 ; ++data ; - val |= uint64_t( *data ) << 24 ; ++data ; - val |= uint64_t( *data ) << 16 ; ++data ; - val |= uint64_t( *data ) << 8 ; ++data ; - val |= uint64_t( *data ) << 0 ; ++data ; - - return val ; -} - -uint32_t PGPKeyParser::write_125Size(unsigned char *data,uint32_t size) -{ - if(size < 192)//192 To know if size is coded with One Char < 0xC0 - { - data[0] = size ; - return 1; - } - - if(size < 8384)//8384 To know if size is coded with Two Chars < 0xE0. See RFC4880 - { - data[1] = (size - 192) & 0xFF ;//Warning data[1] could be "negative", recode it using 8bits type - data[0] = ((size - 192 - data[1]) >> 8) + 192 ; - - return 2 ; - } - - data[0] = 0xFF ; //Else size is coded with 4 Chars + 1 at 0xFF - data[1] = (size >> 24) & 0xFF ; - data[2] = (size >> 16) & 0xFF ; - data[3] = (size >> 8) & 0xFF ; - data[4] = (size ) & 0xFF ; - - return 5 ; -} - -uint32_t PGPKeyParser::read_125Size(unsigned char *& data) -{ - uint8_t b1 = *data ; - ++data ; - - if (b1 < 192) //192 Size is coded with One Char. See RFC4880 https://tools.ietf.org/html/rfc4880#section-4.2.2.1 - return b1 ; - - uint8_t b2 = *data ; - ++data ; - - if (b1 < 224)//224 = 0xC0+0x20 Size is coded with Two Chars - return ( (b1-192) << 8 ) + b2 + 192 ; // see RFC4880 - - if(b1 != 0xFF)// Else Coded with 4 Chars but first == 0xFF - throw std::runtime_error("GPG parsing error") ; - - uint8_t b3 = *data ; ++data ; - uint8_t b4 = *data ; ++data ; - uint8_t b5 = *data ; ++data ; - - return (b2 << 24) | (b3 << 16) | (b4 << 8) | b5 ; -} - -uint32_t PGPKeyParser::read_partialBodyLength(unsigned char *& data) -{ - uint8_t b1 =*data ; - ++data ; - - return 1 << (b1 & 0x1F) ; -} - - -void PGPKeyParser::read_packetHeader(unsigned char *& data,uint8_t& packet_tag,uint32_t& packet_length) -{ - uint8_t b1 = *data ; - ++data ; - - bool new_format = b1 & 0x40 ; - - if(new_format) - { -#ifdef DEBUG_PGPUTIL - std::cerr << "Packet is in new format" << std::endl; -#endif - packet_tag = b1 & 0x3f ; - packet_length = read_125Size(data) ; - } - else - { -#ifdef DEBUG_PGPUTIL - std::cerr << "Packet is in old format" << std::endl; -#endif - uint8_t length_type = b1 & 0x03 ; - packet_tag = (b1 & 0x3c) >> 2 ; - - int length_size ; - switch(length_type) - { - case 0: length_size = 1 ; - break ; - case 1: length_size = 2 ; - break ; - case 2: length_size = 4 ; - break ; - default: - throw std::runtime_error("Unhandled length type!") ; - } - - packet_length = 0 ; - for(int k=0;k * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -// refer to RFC4880 specif document for loading GPG public keys: -// -// 11.1: transferable public keys -// Global structure of transferable public keys -// -// - one public key packet (see 12.2) -// - zero or more revocation signatures (See signature type 5.2.1 for key signature types) -// -// - user certification signatures (0x10 or 0x13) -// -// - 5.2.2: Signature format packet -// - 5.2.3.1: signature subpacket specification -// -// - 4.3: packet tags (1 byte) - -#pragma once - -#include -#include - -static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_UNKNOWN = 0 ; -static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_MD5 = 1 ; -static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_SHA1 = 2 ; -static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_SHA256 = 8 ; -static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_SHA512 = 10 ; - -static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_UNKNOWN = 0 ; -static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_ES = 1 ; -static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_E = 2 ; -static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_S = 3 ; -static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_DSA = 17 ; - -static const uint8_t PGP_PACKET_TAG_SIGNATURE_VERSION_UNKNOWN = 0 ; -static const uint8_t PGP_PACKET_TAG_SIGNATURE_VERSION_V3 = 3 ; -static const uint8_t PGP_PACKET_TAG_SIGNATURE_VERSION_V4 = 4 ; - -static const uint8_t PGP_PACKET_TAG_SIGNATURE_TYPE_UNKNOWN = 0xff ; -static const uint8_t PGP_PACKET_TAG_SIGNATURE_TYPE_BINARY_DOCUMENT = 0x00 ; -static const uint8_t PGP_PACKET_TAG_SIGNATURE_TYPE_CANONICAL_TEXT = 0x01 ; -static const uint8_t PGP_PACKET_TAG_SIGNATURE_TYPE_STANDALONE_SIG = 0x02 ; -// All other consts for signature types not used, so not defines. - -class PGPSignatureInfo -{ -public: - PGPSignatureInfo() : - signature_version (PGP_PACKET_TAG_SIGNATURE_VERSION_UNKNOWN), - signature_type (PGP_PACKET_TAG_SIGNATURE_TYPE_UNKNOWN), - issuer (0), - public_key_algorithm(PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_UNKNOWN), - hash_algorithm (PGP_PACKET_TAG_HASH_ALGORITHM_UNKNOWN) - {} - - uint8_t signature_version ; - uint8_t signature_type ; - uint64_t issuer ; - uint8_t public_key_algorithm ; - uint8_t hash_algorithm ; -}; - -// This class handles GPG keys. For now we only clean them from signatures, but -// in the future, we might cache them to avoid unnecessary calls to gpgme. -// -class PGPKeyManagement -{ - public: - // Create a minimal key, removing all signatures and third party info. - // Input: a clean PGP certificate (starts with "----BEGIN", - // ends with "-----END PGP PUBLIC KEY BLOCK-----" - // Output: the same certificate without signatures. - // - // Returns: - // - // true if the certificate cleaning succeeded - // false otherwise. - // - static bool createMinimalKey(const std::string& pgp_certificate,std::string& cleaned_certificate) ; - - static void findLengthOfMinimalKey(const unsigned char *keydata,size_t key_len,size_t& minimal_key_len) ; - static std::string makeArmouredKey(const unsigned char *keydata,size_t key_size,const std::string& version_string) ; - - // Computes the 24 bits CRC checksum necessary to all PGP data. - // - static uint32_t compute24bitsCRC(unsigned char *data,size_t len) ; - - static bool parseSignature(const unsigned char *signature, size_t sign_len, PGPSignatureInfo& info) ; -}; - -// This class handles the parsing of PGP packet headers under various (old and new) formats. -// -class PGPKeyParser -{ - public: - // These constants correspond to packet tags from RFC4880 - - static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY = 6 ; - static const uint8_t PGP_PACKET_TAG_USER_ID = 13 ; - static const uint8_t PGP_PACKET_TAG_SIGNATURE = 2 ; - static const uint8_t PGP_PACKET_TAG_ISSUER = 16 ; - - // These functions read and move the data pointer to the next byte after the read section. - // - static uint64_t read_KeyID(unsigned char *& data) ; - static uint32_t read_125Size(unsigned char *& data) ; - static uint32_t read_partialBodyLength(unsigned char *& data) ; - static void read_packetHeader(unsigned char *& data,uint8_t& packet_tag,uint32_t& packet_length) ; - - // These functions write, and indicate how many bytes where written. - // - static uint32_t write_125Size(unsigned char *data,uint32_t size) ; - - // Helper functions - // - static std::string extractRadixPartFromArmouredKey(const std::string& pgp_cert,std::string& version_string); -}; - - diff --git a/libretroshare/src/pgp/rscertificate.cc b/libretroshare/src/pgp/rscertificate.cc deleted file mode 100644 index f3007bb01..000000000 --- a/libretroshare/src/pgp/rscertificate.cc +++ /dev/null @@ -1,628 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: rscertificate.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Cyril Soler * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#include -#include -#include -#include - -#include -#include -#include -#include "rscertificate.h" -#include "util/rsstring.h" -#include "util/stacktrace.h" -#include "util/rsdebug.h" - -//#define DEBUG_RSCERTIFICATE - -static const uint8_t CERTIFICATE_VERSION_06 = 0x06; - -enum CertificatePtag : uint8_t -{ - CERTIFICATE_PTAG_PGP_SECTION = 0x01, - CERTIFICATE_PTAG_EXTIPANDPORT_SECTION = 0x02, - CERTIFICATE_PTAG_LOCIPANDPORT_SECTION = 0x03, - CERTIFICATE_PTAG_DNS_SECTION = 0x04, - CERTIFICATE_PTAG_SSLID_SECTION = 0x05, - CERTIFICATE_PTAG_NAME_SECTION = 0x06, - CERTIFICATE_PTAG_CHECKSUM_SECTION = 0x07, - CERTIFICATE_PTAG_HIDDENNODE_SECTION = 0x08, - CERTIFICATE_PTAG_VERSION_SECTION = 0x09, - CERTIFICATE_PTAG_EXTRA_LOCATOR = 10 -}; - -static bool is_acceptable_radix64Char(char c) -{ - return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '+' || c == '/' || c == '=' ; -} - - -RsCertificate::~RsCertificate() -{ - delete[] binary_pgp_key ; -} - -void RsCertificate::addPacket(uint8_t ptag, const unsigned char *mem, size_t size, unsigned char *& buf, size_t& offset, size_t& buf_size) -{ - // Check that the buffer has sufficient size. If not, increase it. - - while(offset + size + 6 >= buf_size) - { - unsigned char *newbuf = new unsigned char[2*buf_size] ; - - memcpy(newbuf, buf, buf_size) ; - buf_size *= 2 ; - - delete[] buf ; - - buf = newbuf ; - } - - // Write ptag and size - - buf[offset] = ptag ; - offset += 1 ; - - offset += PGPKeyParser::write_125Size(&buf[offset],size) ; - - // Copy the data - - memcpy(&buf[offset], mem, size) ; - offset += size ; -} - -const RsCertificate&RsCertificate::operator=(const RsCertificate&) -{ - memset(ipv4_external_ip_and_port,0,6); - memset(ipv4_internal_ip_and_port,0,6); - binary_pgp_key = nullptr; - binary_pgp_key_size = 0; - only_pgp = false; - hidden_node = false; - return *this; -} - -std::string RsCertificate::toStdString() const -{ - //std::string res ; - size_t BS = 1000 ; - size_t p = 0 ; - unsigned char *buf = new unsigned char[BS] ; - - addPacket( CERTIFICATE_PTAG_VERSION_SECTION, &CERTIFICATE_VERSION_06 , 1 , buf, p, BS ) ; - addPacket( CERTIFICATE_PTAG_PGP_SECTION , binary_pgp_key , binary_pgp_key_size , buf, p, BS ) ; - - if(!only_pgp) - { - if (hidden_node) - { - addPacket( CERTIFICATE_PTAG_HIDDENNODE_SECTION, (unsigned char *)hidden_node_address.c_str(), hidden_node_address.length() , buf, p, BS ) ; - } - else - { - addPacket( CERTIFICATE_PTAG_EXTIPANDPORT_SECTION, ipv4_external_ip_and_port , 6 , buf, p, BS ) ; - addPacket( CERTIFICATE_PTAG_LOCIPANDPORT_SECTION, ipv4_internal_ip_and_port , 6 , buf, p, BS ) ; - addPacket( CERTIFICATE_PTAG_DNS_SECTION , (unsigned char *)dns_name.c_str() , dns_name.length() , buf, p, BS ) ; - } - - addPacket( CERTIFICATE_PTAG_NAME_SECTION , (unsigned char *)location_name.c_str() ,location_name.length() , buf, p, BS ) ; - addPacket( CERTIFICATE_PTAG_SSLID_SECTION , location_id.toByteArray() ,location_id.SIZE_IN_BYTES, buf, p, BS ) ; - - for (const RsUrl& locator : mLocators) - { - std::string urlStr(locator.toString()); - addPacket( CERTIFICATE_PTAG_EXTRA_LOCATOR, - (unsigned char *) urlStr.c_str(), urlStr.size(), - buf, p, BS ); - } - } - - uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC(buf,p) ; - - // handle endian issues. - unsigned char mem[3] ; - mem[0] = computed_crc & 0xff ; - mem[1] = (computed_crc >> 8 ) & 0xff ; - mem[2] = (computed_crc >> 16) & 0xff ; - - addPacket( CERTIFICATE_PTAG_CHECKSUM_SECTION,mem,3,buf,p,BS) ; - - std::string out_string ; - - Radix64::encode(buf, p, out_string) ; - - // Now slice up to 64 chars. - // - std::string out2 ; - static const int LINE_LENGTH = 64 ; - - for(int i=0;i<(int)out_string.length();++i) - { - out2 += out_string[i] ; - - if(i % LINE_LENGTH == LINE_LENGTH-1) - out2 += '\n' ; - } - - delete[] buf ; - return out2 ; -} - -RsCertificate::RsCertificate(const RsPeerDetails& Detail, const unsigned char *binary_pgp_block,size_t binary_pgp_block_size) - :pgp_version("Version: OpenPGP:SDK v0.9") -{ - if(binary_pgp_block_size == 0 || binary_pgp_block == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " is deprecated because it can " - << "miserably fail like this! " << std::endl; - print_stacktrace(); - throw std::runtime_error("Cannot init a certificate with a void key block."); - } - - binary_pgp_key = new unsigned char[binary_pgp_block_size] ; - memcpy(binary_pgp_key,binary_pgp_block,binary_pgp_block_size) ; - binary_pgp_key_size = binary_pgp_block_size ; - - if(!Detail.isOnlyGPGdetail) - { - only_pgp = false ; - location_id = RsPeerId( Detail.id ) ; - location_name = Detail.location ; - - if (Detail.isHiddenNode) - { - hidden_node = true; - hidden_node_address = Detail.hiddenNodeAddress; - rs_sprintf_append(hidden_node_address, ":%u", Detail.hiddenNodePort); - - memset(ipv4_internal_ip_and_port,0,6) ; - memset(ipv4_external_ip_and_port,0,6) ; - dns_name = "" ; - } - else - { - hidden_node = false; - hidden_node_address = ""; - - try - { - scan_ip(Detail.localAddr,Detail.localPort,ipv4_internal_ip_and_port); - } - catch(...) - { - std::cerr << "RsCertificate::Invalid LocalAddress: " - << Detail.localAddr << std::endl; - memset(ipv4_internal_ip_and_port,0,6); - } - - - try - { - scan_ip(Detail.extAddr,Detail.extPort,ipv4_external_ip_and_port); - } - catch(...) - { - std::cerr << "RsCertificate::Invalid ExternalAddress: " - << Detail.extAddr << std::endl; - memset(ipv4_external_ip_and_port,0,6) ; - } - - dns_name = Detail.dyndns; - - for(auto&& ipr : Detail.ipAddressList) - mLocators.insert(RsUrl(ipr.substr(0, ipr.find(' ')))); - } - } - else - { - only_pgp = true ; - hidden_node = false; - hidden_node_address = ""; - location_id = RsPeerId() ; - location_name = "" ; - memset(ipv4_internal_ip_and_port,0,6) ; - memset(ipv4_external_ip_and_port,0,6) ; - dns_name = "" ; - } -} - - -/*static*/ std::unique_ptr RsCertificate::fromMemoryBlock( - const RsPeerDetails& details, const uint8_t* binary_pgp_block, - size_t binary_pgp_block_size ) -{ - if(binary_pgp_block_size == 0 || binary_pgp_block == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " invalid parameters! " << std::endl; - print_stacktrace(); - return nullptr; - } - - std::unique_ptr crt(new RsCertificate); - - crt->binary_pgp_key = new uint8_t[binary_pgp_block_size]; - memcpy(crt->binary_pgp_key, binary_pgp_block, binary_pgp_block_size); - crt->binary_pgp_key_size = binary_pgp_block_size; - - if(!details.isOnlyGPGdetail) - { - crt->only_pgp = false; - crt->location_id = RsPeerId(details.id); - crt->location_name = details.location; - - if (details.isHiddenNode) - { - crt->hidden_node = true; - crt->hidden_node_address = details.hiddenNodeAddress; - rs_sprintf_append( - crt->hidden_node_address, ":%u", details.hiddenNodePort); - - memset(crt->ipv4_internal_ip_and_port, 0, 6); - memset(crt->ipv4_external_ip_and_port, 0, 6); - crt->dns_name = ""; - } - else - { - crt->hidden_node = false; - crt->hidden_node_address = ""; - - try - { - scan_ip( details.localAddr, details.localPort, - crt->ipv4_internal_ip_and_port ); - } - catch(...) - { - RsErr() << __PRETTY_FUNCTION__ << " Invalid LocalAddress: " - << details.localAddr << std::endl; - memset(crt->ipv4_internal_ip_and_port, 0, 6); - } - - try - { - scan_ip( details.extAddr, details.extPort, - crt->ipv4_external_ip_and_port ); - } - catch(...) - { - RsErr() << __PRETTY_FUNCTION__ << " Invalid ExternalAddress: " - << details.extAddr << std::endl; - memset(crt->ipv4_external_ip_and_port, 0, 6); - } - - crt->dns_name = details.dyndns; - - for(auto&& ipr : details.ipAddressList) - crt->mLocators.insert(RsUrl(ipr.substr(0, ipr.find(' ')))); - } - } - else - { - crt->only_pgp = true; - crt->hidden_node = false; - crt->hidden_node_address = ""; - crt->location_id = RsPeerId(); - crt->location_name = ""; - memset(crt->ipv4_internal_ip_and_port, 0, 6); - memset(crt->ipv4_external_ip_and_port, 0, 6); - crt->dns_name = ""; - } - - return crt; // Implicit move semantic -} - -void RsCertificate::scan_ip(const std::string& ip_string, unsigned short port,unsigned char *ip_and_port) -{ - int d0,d1,d2,d3 ; - - if(4 != sscanf(ip_string.c_str(),"%d.%d.%d.%d",&d0,&d1,&d2,&d3)) - throw std::runtime_error( "Cannot parse ip from given string." ); - - ip_and_port[0] = d0 ; - ip_and_port[1] = d1 ; - ip_and_port[2] = d2 ; - ip_and_port[3] = d3 ; - - ip_and_port[4] = (port >> 8 ) & 0xff ; - ip_and_port[5] = port & 0xff ; -} - -/*static*/ std::unique_ptr RsCertificate::fromString( - const std::string& instr, uint32_t& err_code ) -{ - Dbg3() << __PRETTY_FUNCTION__ << std::endl; - - std::unique_ptr crt(new RsCertificate); - - std::string str; - err_code = CERTIFICATE_PARSING_ERROR_NO_ERROR; - - // 0 - clean the string and check that it is pure radix64 - for(uint32_t i=0;i bf = Radix64::decode(str); - size_t size = bf.size(); - - bool checksum_check_passed = false; - unsigned char* buf = bf.data(); - size_t total_s = 0; - crt->only_pgp = true; - uint8_t certificate_version = 0x00; - - while(total_s < size) - { - uint8_t ptag = buf[0]; - buf = &buf[1]; - - unsigned char *buf2 = buf; - uint32_t s = 0; - - try { s = PGPKeyParser::read_125Size(buf); } - catch (...) - { - err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR; - return nullptr; - } - - total_s += 1 + ( - reinterpret_cast(buf) - - reinterpret_cast(buf2) ); - - if(total_s > size) - { - err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR; - return nullptr; - } - - Dbg3() << __PRETTY_FUNCTION__ << " Read ptag: " - << static_cast(ptag) - << ", size " << s << ", total_s = " << total_s - << ", expected total = " << size << std::endl; - - switch(ptag) - { - case CERTIFICATE_PTAG_VERSION_SECTION: - certificate_version = buf[0]; - break; - case CERTIFICATE_PTAG_PGP_SECTION: - crt->binary_pgp_key = new unsigned char[s]; - memcpy(crt->binary_pgp_key, buf, s); - crt->binary_pgp_key_size = s; - break; - case CERTIFICATE_PTAG_NAME_SECTION: - crt->location_name = - std::string(reinterpret_cast(buf), s); - break; - case CERTIFICATE_PTAG_SSLID_SECTION: - if(s != crt->location_id.SIZE_IN_BYTES) - { - err_code = CERTIFICATE_PARSING_ERROR_INVALID_LOCATION_ID; - return nullptr; - } - // We just checked buffer size so next line is not unsafe - crt->location_id = RsPeerId::fromBufferUnsafe(buf); - crt->only_pgp = false; - break; - case CERTIFICATE_PTAG_DNS_SECTION: - crt->dns_name = std::string(reinterpret_cast(buf), s); - break; - case CERTIFICATE_PTAG_HIDDENNODE_SECTION: - crt->hidden_node_address = - std::string(reinterpret_cast(buf),s); - crt->hidden_node = true; - break; - case CERTIFICATE_PTAG_LOCIPANDPORT_SECTION: - if(s != 6) - { - err_code = CERTIFICATE_PARSING_ERROR_INVALID_LOCAL_IP; - return nullptr; - } - memcpy(crt->ipv4_internal_ip_and_port, buf, s); - break; - case CERTIFICATE_PTAG_EXTIPANDPORT_SECTION: - if(s != 6) - { - err_code = CERTIFICATE_PARSING_ERROR_INVALID_EXTERNAL_IP; - return nullptr; - } - memcpy(crt->ipv4_external_ip_and_port, buf, s); - break; - case CERTIFICATE_PTAG_CHECKSUM_SECTION: - { - if(s != 3 || total_s+3 != size) - { - err_code = - CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION; - return nullptr; - } - uint32_t computed_crc = - PGPKeyManagement::compute24bitsCRC(bf.data(),size-5); - uint32_t certificate_crc = static_cast( - buf[0] + (buf[1] << 8) + (buf[2] << 16) ); - if(computed_crc != certificate_crc) - { - err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR; - return nullptr; - } - else checksum_check_passed = true; - break; - } - case CERTIFICATE_PTAG_EXTRA_LOCATOR: - crt->mLocators.insert( - RsUrl(std::string(reinterpret_cast(buf), s))); - break; - default: - RsWarn() << __PRETTY_FUNCTION__ << " unknwown ptag: " - << static_cast(ptag) - << " in certificate! Ignoring it." << std::endl; - break; - } - - buf = &buf[s]; - total_s += s; - } - - if(!checksum_check_passed) - { - err_code = CERTIFICATE_PARSING_ERROR_MISSING_CHECKSUM; - return nullptr; - } - - if(certificate_version != CERTIFICATE_VERSION_06) - { - err_code = CERTIFICATE_PARSING_ERROR_WRONG_VERSION; - return nullptr; - } - - Dbg3() << __PRETTY_FUNCTION__ << " Certificate version: " - << static_cast(certificate_version) << std::endl; - - if(total_s != size) - RsWarn() << __PRETTY_FUNCTION__ << " Certificate contains trailing " - << "characters. Weird." << std::endl; - - return crt; // Implicit move semantic -} - -std::string RsCertificate::hidden_node_string() const -{ - if ((!only_pgp) && (hidden_node)) - { - return hidden_node_address; - } - - std::string empty; - return empty; -} - -std::string RsCertificate::ext_ip_string() const -{ - std::ostringstream os ; - os << (int)ipv4_external_ip_and_port[0] << "." << (int)ipv4_external_ip_and_port[1] << "." << (int)ipv4_external_ip_and_port[2] << "." << (int)ipv4_external_ip_and_port[3] ; - return os.str() ; -} - -std::string RsCertificate::loc_ip_string() const -{ - std::ostringstream os ; - os << (int)ipv4_internal_ip_and_port[0] << "." << (int)ipv4_internal_ip_and_port[1] << "." << (int)ipv4_internal_ip_and_port[2] << "." << (int)ipv4_internal_ip_and_port[3] ; - return os.str() ; -} - -unsigned short RsCertificate::ext_port_us() const -{ - return (int)ipv4_external_ip_and_port[4]*256 + (int)ipv4_external_ip_and_port[5] ; -} - -unsigned short RsCertificate::loc_port_us() const -{ - return (int)ipv4_internal_ip_and_port[4]*256 + (int)ipv4_internal_ip_and_port[5] ; -} - -bool RsCertificate::cleanCertificate( const std::string& input, std::string& output, Format& format, uint32_t& error_code, bool check_content ) -{ - if(cleanRadix64(input,output,error_code)) - { - RsPeerDetails details; - - if(rsPeers->parseShortInvite(output,details,error_code)) - { - format = RS_CERTIFICATE_SHORT_RADIX; - return true; - } - - format = RS_CERTIFICATE_RADIX; - - if(!check_content) return true; - - uint32_t errCode; - auto crt = RsCertificate::fromString(input, errCode); - error_code = static_cast(errCode); - return crt != nullptr; - } - - return false; -} - -std::string RsCertificate::armouredPGPKey() const -{ - return PGPKeyManagement::makeArmouredKey(binary_pgp_key,binary_pgp_key_size,pgp_version) ; -} - -// Yeah, this is simple, and that is what's good about the radix format. Can't be broken ;-) -// -bool RsCertificate::cleanRadix64(const std::string& instr,std::string& str,uint32_t& error_code) -{ - error_code = RS_PEER_CERT_CLEANING_CODE_NO_ERROR ; - - // 0 - clean the string and check that it is pure radix64 - // - for(uint32_t i=0;i * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rstypes.h" -#include "util/rsurl.h" -#include "util/rsmemory.h" -#include "util/rsdebug.h" - -#include -#include -#include - -struct RsPeerDetails; - -class RsCertificate -{ -public: - typedef enum { RS_CERTIFICATE_OLD_FORMAT, RS_CERTIFICATE_RADIX, RS_CERTIFICATE_SHORT_RADIX } Format; - - /** - * @brief Create certificate object from certificate string - * @param[in] str radix format certificate string - * @param[out] errorCode Optional storage for eventual error code, - * meaningful only on failure - * @return nullptr on failure, pointer to the generated certificate - * otherwise - */ - static std::unique_ptr fromString( - const std::string& str, - uint32_t& errorCode = RS_DEFAULT_STORAGE_PARAM(uint32_t) ); - - /** - * @brief Create certificate object from peer details and PGP memory block - * @param[in] details peer details - * @param[in] binary_pgp_block pointer to PGP memory block - * @param[in] binary_pgp_block_size size of PGP memory block - * @return nullptr on failure, pointer to the generated certificate - * otherwise - */ - static std::unique_ptr fromMemoryBlock( - const RsPeerDetails& details, const uint8_t* binary_pgp_block, - size_t binary_pgp_block_size ); - - ~RsCertificate(); - - /// Convert to certificate radix string - std::string toStdString() const; - - std::string ext_ip_string() const; - std::string loc_ip_string() const; - std::string location_name_string() const { return location_name; } - std::string dns_string() const { return dns_name ; } - RsPeerId sslid() const { return location_id ; } - std::string hidden_node_string() const; - - std::string armouredPGPKey() const; - - unsigned short ext_port_us() const; - unsigned short loc_port_us() const; - - const unsigned char *pgp_key() const { return binary_pgp_key ; } - size_t pgp_key_size() const { return binary_pgp_key_size ; } - - static bool cleanCertificate( - const std::string& input, std::string& output, - RsCertificate::Format& format, uint32_t& error_code, bool check_content); - - const std::set& locators() const { return mLocators; } - - /** - * @deprecated using this costructor may raise exception that cause - * crash if not handled. - */ - RS_DEPRECATED_FOR("RsCertificate::fromMemoryBlock(...)") - RsCertificate( const RsPeerDetails& details, - const unsigned char *gpg_mem_block, - size_t gpg_mem_block_size ); - -private: - // new radix format - static bool cleanRadix64(const std::string& input, std::string& output, uint32_t &); - - static void scan_ip( const std::string& ip_string, unsigned short port, - unsigned char *destination_memory ); - - static void addPacket(uint8_t ptag, const unsigned char *mem, size_t size, - unsigned char*& buf, size_t& offset, size_t& buf_size); - - RsCertificate(const RsCertificate&) {} /// non copy-able - const RsCertificate& operator=(const RsCertificate&); /// non copy-able - - /// @brief Costruct an empty certificate - RsCertificate() : - ipv4_external_ip_and_port{0,0,0,0,0,0}, - ipv4_internal_ip_and_port{0,0,0,0,0,0}, - binary_pgp_key(nullptr), binary_pgp_key_size(0), - pgp_version("Version: OpenPGP:SDK v0.9"), only_pgp(true), - hidden_node(false) {} - - unsigned char ipv4_external_ip_and_port[6]; - unsigned char ipv4_internal_ip_and_port[6]; - - unsigned char *binary_pgp_key; - size_t binary_pgp_key_size; - - std::string location_name; - RsPeerId location_id; - std::string pgp_version; - std::string dns_name; - std::string hidden_node_address; - std::set mLocators; - - bool only_pgp ; /// does the cert contain only pgp info? - bool hidden_node; /// IP or hidden Node Address. - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; - diff --git a/libretroshare/src/plugins/dlfcn_win32.cc b/libretroshare/src/plugins/dlfcn_win32.cc deleted file mode 100644 index b669cfa54..000000000 --- a/libretroshare/src/plugins/dlfcn_win32.cc +++ /dev/null @@ -1,322 +0,0 @@ -/******************************************************************************* - * libretroshare/src/plugins: dlfcn_win32.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007 Ramiro Polla * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifdef WINDOWS_SYS - -#include -#include -#include - -#include "dlfcn_win32.h" - -/* Note: - * MSDN says these functions are not thread-safe. We make no efforts to have - * any kind of thread safety. - */ - -typedef struct global_object { - HMODULE hModule; - struct global_object *previous; - struct global_object *next; -} global_object; - -static global_object first_object; - -/* These functions implement a double linked list for the global objects. */ -static global_object *global_search( HMODULE hModule ) -{ - global_object *pobject; - - if( hModule == NULL ) - return NULL; - - for( pobject = &first_object; pobject ; pobject = pobject->next ) - if( pobject->hModule == hModule ) - return pobject; - - return NULL; -} - -static void global_add( HMODULE hModule ) -{ - global_object *pobject; - global_object *nobject; - - if( hModule == NULL ) - return; - - pobject = global_search( hModule ); - - /* Do not add object again if it's already on the list */ - if( pobject ) - return; - - for( pobject = &first_object; pobject->next ; pobject = pobject->next ); - - nobject = (global_object*) malloc( sizeof(global_object) ); - - /* Should this be enough to fail global_add, and therefore also fail - * dlopen? - */ - if( !nobject ) - return; - - pobject->next = nobject; - nobject->next = NULL; - nobject->previous = pobject; - nobject->hModule = hModule; -} - -static void global_rem( HMODULE hModule ) -{ - global_object *pobject; - - if( hModule == NULL ) - return; - - pobject = global_search( hModule ); - - if( !pobject ) - return; - - if( pobject->next ) - pobject->next->previous = pobject->previous; - if( pobject->previous ) - pobject->previous->next = pobject->next; - - free( pobject ); -} - -/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one - * static buffer. - * MSDN says the buffer cannot be larger than 64K bytes, so we set it to - * the limit. - */ -static char error_buffer[65535]; -static char *current_error; - -static int copy_string( char *dest, int dest_size, const char *src ) -{ - int i = 0; - - /* gcc should optimize this out */ - if( !src && !dest ) - return 0; - - for( i = 0 ; i < dest_size-1 ; i++ ) - { - if( !src[i] ) - break; - else - dest[i] = src[i]; - } - dest[i] = '\0'; - - return i; -} - -static void save_err_str( const char *str ) -{ - DWORD dwMessageId; - DWORD pos; - - dwMessageId = GetLastError( ); - - if( dwMessageId == 0 ) - return; - - /* Format error message to: - * "": - */ - pos = copy_string( error_buffer, sizeof(error_buffer), "\"" ); - pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, str ); - pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, "\": " ); - pos += FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId, - MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), - error_buffer+pos, sizeof(error_buffer)-pos, NULL ); - - if( pos > 1 ) - { - /* POSIX says the string must not have trailing */ - if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' ) - error_buffer[pos-2] = '\0'; - } - - current_error = error_buffer; -} - -static void save_err_ptr_str( const void *ptr ) -{ - char ptr_buf[19]; /* 0x up to 64 bits. */ - - sprintf( ptr_buf, "0x%p", ptr ); - - save_err_str( ptr_buf ); -} - -void *dlopen( const char *file, int mode ) -{ - HMODULE hModule; - UINT uMode; - - current_error = NULL; - - /* Do not let Windows display the critical-error-handler message box */ - uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); - - if( file == 0 ) - { - /* POSIX says that if the value of file is 0, a handle on a global - * symbol object must be provided. That object must be able to access - * all symbols from the original program file, and any objects loaded - * with the RTLD_GLOBAL flag. - * The return value from GetModuleHandle( ) allows us to retrieve - * symbols only from the original program file. For objects loaded with - * the RTLD_GLOBAL flag, we create our own list later on. - */ - hModule = GetModuleHandle( NULL ); - - if( !hModule ) - save_err_ptr_str( file ); - } - else - { - char lpFileName[MAX_PATH]; - unsigned int i; - - /* MSDN says backslashes *must* be used instead of forward slashes. */ - for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ ) - { - if( !file[i] ) - break; - else if( file[i] == '/' ) - lpFileName[i] = '\\'; - else - lpFileName[i] = file[i]; - } - lpFileName[i] = '\0'; - - /* POSIX says the search path is implementation-defined. - * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely - * to UNIX's search paths (start with system folders instead of current - * folder). - */ - hModule = LoadLibraryExA( (LPSTR) lpFileName, NULL, - LOAD_WITH_ALTERED_SEARCH_PATH ); - - /* If the object was loaded with RTLD_GLOBAL, add it to list of global - * objects, so that its symbols may be retrieved even if the handle for - * the original program file is passed. POSIX says that if the same - * file is specified in multiple invocations, and any of them are - * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the - * symbols will remain global. - */ - if( !hModule ) - save_err_str( lpFileName ); - else if( (mode & RTLD_GLOBAL) ) - global_add( hModule ); - } - - /* Return to previous state of the error-mode bit flags. */ - SetErrorMode( uMode ); - - return (void *) hModule; -} - -int dlclose( void *handle ) -{ - HMODULE hModule = (HMODULE) handle; - BOOL ret; - - current_error = NULL; - - ret = FreeLibrary( hModule ); - - /* If the object was loaded with RTLD_GLOBAL, remove it from list of global - * objects. - */ - if( ret ) - global_rem( hModule ); - else - save_err_ptr_str( handle ); - - /* dlclose's return value in inverted in relation to FreeLibrary's. */ - ret = !ret; - - return (int) ret; -} - -void *dlsym( void *handle, const char *name ) -{ - FARPROC symbol; - - current_error = NULL; - - symbol = GetProcAddress( (HINSTANCE) handle, name ); - - if( symbol == NULL ) - { - HMODULE hModule; - - /* If the handle for the original program file is passed, also search - * in all globally loaded objects. - */ - - hModule = GetModuleHandle( NULL ); - - if( hModule == handle ) - { - global_object *pobject; - - for( pobject = &first_object; pobject ; pobject = pobject->next ) - { - if( pobject->hModule ) - { - symbol = GetProcAddress( pobject->hModule, name ); - if( symbol != NULL ) - break; - } - } - } - - // Do not close the handle of the calling process -// CloseHandle( hModule ); - } - - if( symbol == NULL ) - save_err_str( name ); - - return (void*) symbol; -} - -char *dlerror( void ) -{ - char *error_pointer = current_error; - - /* POSIX says that invoking dlerror( ) a second time, immediately following - * a prior invocation, shall result in NULL being returned. - */ - current_error = NULL; - - return error_pointer; -} -#endif diff --git a/libretroshare/src/plugins/dlfcn_win32.h b/libretroshare/src/plugins/dlfcn_win32.h deleted file mode 100644 index 3298777dd..000000000 --- a/libretroshare/src/plugins/dlfcn_win32.h +++ /dev/null @@ -1,51 +0,0 @@ -/******************************************************************************* - * libretroshare/src/plugins: dlfcn_win32.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007 Ramiro Polla * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#ifdef WINDOWS_SYS -#ifndef DLFCN_H -#define DLFCN_H - -/* POSIX says these are implementation-defined. - * To simplify use with Windows API, we treat them the same way. - */ - -#define RTLD_LAZY 0 -#define RTLD_NOW 0 - -#define RTLD_GLOBAL (1 << 1) -#define RTLD_LOCAL (1 << 2) - -/* These two were added in The Open Group Base Specifications Issue 6. - * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant. - */ - -#define RTLD_DEFAULT 0 -#define RTLD_NEXT 0 - -void *dlopen ( const char *file, int mode ); -int dlclose( void *handle ); -void *dlsym ( void *handle, const char *name ); -char *dlerror( void ); - -#endif /* DLFCN_H */ -#endif /* WINDOWS_SYS */ diff --git a/libretroshare/src/plugins/pluginmanager.cc b/libretroshare/src/plugins/pluginmanager.cc deleted file mode 100644 index dcd474f8f..000000000 --- a/libretroshare/src/plugins/pluginmanager.cc +++ /dev/null @@ -1,586 +0,0 @@ -/******************************************************************************* - * libretroshare/src/plugins: pluginmanager.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include - -#include "pluginmanager.h" -#include - -#if 0 -#include -#include -#include -#endif - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// lets disable the plugin system for now, as it's unfinished. -#ifdef WINDOWS_SYS -#include "dlfcn_win32.h" -#else -#include -#endif - -// #define DEBUG_PLUGIN_MANAGER 1 - -std::string RsPluginManager::_plugin_entry_symbol = "RETROSHARE_PLUGIN_provide" ; -std::string RsPluginManager::_plugin_revision_symbol = "RETROSHARE_PLUGIN_revision" ; -std::string RsPluginManager::_plugin_API_symbol = "RETROSHARE_PLUGIN_api" ; - -std::string RsPluginManager::_local_cache_dir ; -std::string RsPluginManager::_remote_cache_dir ; -std::vector RsPluginManager::_plugin_directories ; - -RsServiceControl *RsPluginManager::_service_control = NULL ; - -typedef RsPlugin *(*RetroSharePluginEntry)(void) ; -RsPluginHandler *rsPlugins ; - -RsPluginManager::RsPluginManager(const RsFileHash &hash) - : p3Config(),_current_executable_hash(hash) -{ - _allow_all_plugins = false ; -} - -bool RsPluginManager::loadConfiguration(RsFileHash &loadHash) -{ - return p3Config::loadConfiguration(loadHash); -} - -void RsPluginManager::loadConfiguration() -{ - RsFileHash dummyHash; - p3Config::loadConfiguration(dummyHash); -} - -void RsPluginManager::setInterfaces(RsPlugInInterfaces &interfaces) -{ - std::cerr << "RsPluginManager::setInterfaces() " << std::endl; - - for(uint32_t i=0;i<_plugins.size();++i) - if(_plugins[i].plugin != NULL) - { - std::cerr << " setting iterface for plugin " << _plugins[i].plugin->getPluginName() << ", with RS_ID " << _plugins[i].plugin->rs_service_id() << std::endl ; - _plugins[i].plugin->setInterfaces(interfaces); - } -} - -void RsPluginManager::setCacheDirectories(const std::string& local_cache, const std::string& remote_cache) -{ - _local_cache_dir = local_cache ; - _remote_cache_dir = remote_cache ; -} - -bool RsPluginManager::acceptablePluginName(const std::string& name) -{ - // Needs some windows specific code here - // -#ifdef WINDOWS_SYS - return name.size() > 4 && name.substr(name.size() - 4) == ".dll"; -#elif defined(__MACH__) - return name.size() > 6 && !strcmp(name.c_str()+name.size()-6,".dylib") ; -#else - return name.size() > 3 && !strcmp(name.c_str()+name.size()-3,".so") ; -#endif -} - -void RsPluginManager::disablePlugin(const RsFileHash& hash) -{ - std::set::iterator it = _accepted_hashes.find(hash) ; - - if(it != _accepted_hashes.end()) - { - std::cerr << "RsPluginManager::disablePlugin(): removing hash " << hash << " from white list" << std::endl; - - _accepted_hashes.erase(it) ; - IndicateConfigChanged() ; - } - if(_rejected_hashes.find(hash) == _rejected_hashes.end()) - { - std::cerr << "RsPluginManager::enablePlugin(): inserting hash " << hash << " in black list" << std::endl; - - _rejected_hashes.insert(hash) ; - IndicateConfigChanged() ; - } -} - -void RsPluginManager::enablePlugin(const RsFileHash& hash) -{ - if(_accepted_hashes.find(hash) == _accepted_hashes.end()) - { - std::cerr << "RsPluginManager::enablePlugin(): inserting hash " << hash << " in white list" << std::endl; - - _accepted_hashes.insert(hash) ; - IndicateConfigChanged() ; - } - std::set::const_iterator it(_rejected_hashes.find(hash)) ; - - if(it != _rejected_hashes.end()) - { - std::cerr << "RsPluginManager::enablePlugin(): removing hash " << hash << " from black list" << std::endl; - - _rejected_hashes.erase(it) ; - IndicateConfigChanged() ; - } -} - -void RsPluginManager::loadPlugins(const std::vector& plugin_directories) -{ - _plugin_directories = plugin_directories ; - _plugin_entry_symbol = "RETROSHARE_PLUGIN_provide" ; - _plugin_revision_symbol = "RETROSHARE_PLUGIN_revision" ; - - // 0 - get the list of files to read - - bool first_time = (_accepted_hashes.empty()) && _rejected_hashes.empty() ; - - for(uint32_t i=0;ip3_service(); - if (service) - { - pqih->removeService(service); - } - - _plugins[i].plugin->stop(); - delete _plugins[i].plugin; - _plugins[i].plugin = NULL; - } - if (_plugins[i].handle) - { - dlclose(_plugins[i].handle); - _plugins[i].handle = NULL; - } - } -} - -void RsPluginManager::getPluginStatus(int i,uint32_t& status,std::string& file_name,RsFileHash &hash,uint32_t& svn_revision,std::string& error_string) const -{ - if((uint32_t)i >= _plugins.size()) - return ; - - status = _plugins[i].status ; - error_string = _plugins[i].info_string ; - hash = _plugins[i].file_hash ; - file_name = _plugins[i].file_name ; - svn_revision = _plugins[i].svn_revision ; -} - -bool RsPluginManager::getAllowAllPlugins() const -{ - return _allow_all_plugins ; -} -void RsPluginManager::allowAllPlugins(bool b) -{ - _allow_all_plugins = b ; - IndicateConfigChanged() ; -} -RsSerialiser *RsPluginManager::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsPluginSerialiser()) ; - rss->addSerialType(new RsGeneralConfigSerialiser()) ; - - return rss ; -} - -void RsPluginManager::loadPlugins(const std::vector& plugins) -{ - for(uint32_t i=0;isetPlugInHandler(this); // WIN fix, cannot share global space with shared libraries - - // The following choice is conservative by forcing RS to resolve all dependencies at - // the time of loading the plugin. - - pinfo.status = PLUGIN_STATUS_LOADED ; - - _plugins.push_back(pinfo) ; - return true; -} - -bool RsPluginManager::loadPlugin(const std::string& plugin_name,bool first_time) -{ - std::cerr << " Loading plugin " << plugin_name << std::endl; - - PluginInfo pf ; - pf.plugin = NULL ; - pf.file_name = plugin_name ; - pf.info_string = "" ; - std::cerr << " -> hashing." << std::endl; - uint64_t size ; - - // Stage 1 - get information related to file (hash, name, ...) - // - if(!RsDirUtil::getFileHash(plugin_name,pf.file_hash,size)) - { - std::cerr << " -> cannot hash file. Plugin read canceled." << std::endl; - return false; - } - - _plugins.push_back(pf) ; - PluginInfo& pinfo(_plugins.back()) ; - - std::cerr << " -> hash = " << pinfo.file_hash << std::endl; - - if(!_allow_all_plugins) - { - if(_accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end() && _rejected_hashes.find(pinfo.file_hash) == _rejected_hashes.end() ) - if(!RsServer::notify()->askForPluginConfirmation(pinfo.file_name,pinfo.file_hash.toStdString(),first_time)) - _rejected_hashes.insert(pinfo.file_hash) ; // accepted hashes are treated at the end, for security. - - if(_rejected_hashes.find(pinfo.file_hash) != _rejected_hashes.end() ) - { - pinfo.status = PLUGIN_STATUS_REJECTED_HASH ; - std::cerr << " -> hash rejected. Giving up plugin. " << std::endl; - return false ; - } - } - else - std::cerr << " -> ALLOW_ALL_PLUGINS Enabled => plugin loaded by default." << std::endl; - - std::cerr << " -> hash authorized. Loading plugin. " << std::endl; - - // Stage 2 - open with dlopen, and get some basic info. - // - - // The following choice is conservative by forcing RS to resolve all dependencies at - // the time of loading the plugin. - - int link_mode = RTLD_NOW | RTLD_GLOBAL ; - - void *handle = dlopen(plugin_name.c_str(),link_mode) ; - - if(handle == NULL) - { - const char *val = dlerror() ; - std::cerr << " Cannot open plugin: " << val << std::endl ; - pinfo.status = PLUGIN_STATUS_DLOPEN_ERROR ; - pinfo.info_string = val ; - return false ; - } - - void *prev = dlsym(handle,_plugin_revision_symbol.c_str()) ; pinfo.svn_revision = (prev == NULL) ? 0 : (*(uint32_t *)prev) ; - void *papi = dlsym(handle,_plugin_API_symbol.c_str()) ; pinfo.API_version = (papi == NULL) ? 0 : (*(uint32_t *)papi) ; - - std::cerr << " -> plugin revision number: " << pinfo.svn_revision << std::endl; - std::cerr << " plugin API number : " << std::hex << pinfo.API_version << std::dec << std::endl; - - // Check that the plugin provides a svn revision number and a API number - // - if(pinfo.API_version == 0) - { - std::cerr << " -> No API version number." << std::endl; - pinfo.status = PLUGIN_STATUS_MISSING_API ; - pinfo.info_string = "" ; - dlclose(handle); - return false ; - } -#ifdef TO_REMOVE - if(pinfo.svn_revision == 0) - { - std::cerr << " -> No svn revision number." << std::endl; - pinfo.status = PLUGIN_STATUS_MISSING_SVN ; - pinfo.info_string = "" ; - dlclose(handle); - return false ; - } -#endif - - // Now look for the plugin class symbol. - // - void *pfe = dlsym(handle,_plugin_entry_symbol.c_str()) ; - - if(pfe == NULL) - { - std::cerr << dlerror() << std::endl ; - pinfo.status = PLUGIN_STATUS_MISSING_SYMBOL ; - pinfo.info_string = _plugin_entry_symbol ; - dlclose(handle); - return false ; - } - std::cerr << " -> Added function entry for symbol " << _plugin_entry_symbol << std::endl ; - - RsPlugin *p = ( (*(RetroSharePluginEntry)pfe)() ) ; - - if(p == NULL) - { - std::cerr << " Plugin entry function " << _plugin_entry_symbol << " returns NULL ! It should return an object of type RsPlugin* " << std::endl; - pinfo.status = PLUGIN_STATUS_NULL_PLUGIN ; - pinfo.info_string = "Plugin entry " + _plugin_entry_symbol + "() return NULL" ; - dlclose(handle); - return false ; - } - - pinfo.status = PLUGIN_STATUS_LOADED ; - pinfo.plugin = p ; - pinfo.handle = handle; - p->setPlugInHandler(this); // WIN fix, cannot share global space with shared libraries - pinfo.info_string = "" ; - - _accepted_hashes.insert(pinfo.file_hash) ; // do it now, to avoid putting in list a plugin that might have crashed during the load. - return true; -} - -const std::string& RsPluginManager::getLocalCacheDir() const -{ - assert(!_local_cache_dir.empty()) ; - return _local_cache_dir ; -} -const std::string& RsPluginManager::getRemoteCacheDir() const -{ - assert(!_remote_cache_dir.empty()) ; - return _remote_cache_dir ; -} -RsServiceControl *RsPluginManager::getServiceControl() const -{ - assert(_service_control); - return _service_control ; -} -void RsPluginManager::slowTickPlugins(rstime_t seconds) -{ - for(uint32_t i=0;i<_plugins.size();++i) - if(_plugins[i].plugin != NULL && _plugins[i].plugin->rs_cache_service() != NULL && (seconds % _plugins[i].plugin->rs_cache_service()->tickDelay() )) - { -#ifdef DEBUG_PLUGIN_MANAGER - std::cerr << " ticking plugin " << _plugins[i].plugin->getPluginName() << std::endl; -#endif - _plugins[i].plugin->rs_cache_service()->tick() ; - } -} - -void RsPluginManager::registerCacheServices() -{ - // this is removed since the old cache syste is gone, but we need to make it register new GXS group services instead. -#ifdef REMOVED - std::cerr << " Registering cache services." << std::endl; - - for(uint32_t i=0;i<_plugins.size();++i) - if(_plugins[i].plugin != NULL && _plugins[i].plugin->rs_cache_service() != NULL) - { - //rsFiles->getCacheStrapper()->addCachePair(CachePair(_plugins[i].plugin->rs_cache_service(),_plugins[i].plugin->rs_cache_service(),CacheId(_plugins[i].plugin->rs_service_id(), 0))) ; - std::cerr << " adding new cache pair for plugin " << _plugins[i].plugin->getPluginName() << ", with RS_ID " << _plugins[i].plugin->rs_service_id() << std::endl ; - } -#endif -} - -void RsPluginManager::registerClientServices(p3ServiceServer *pqih) -{ - std::cerr << " Registering pqi services." << std::endl; - - for(uint32_t i=0;i<_plugins.size();++i) - //if(_plugins[i].plugin != NULL && _plugins[i].plugin->rs_pqi_service() != NULL) - if(_plugins[i].plugin != NULL && _plugins[i].plugin->p3_service() != NULL) - { - //pqih->addService(_plugins[i].plugin->rs_pqi_service(), true) ; - pqih->addService(_plugins[i].plugin->p3_service(), true) ; - std::cerr << " Added pqi service for plugin " << _plugins[i].plugin->getPluginName() << std::endl; - } -} - -void RsPluginManager::addConfigurations(p3ConfigMgr *ConfigMgr) -{ - std::cerr << " Registering configuration files." << std::endl; - - for(uint32_t i=0;i<_plugins.size();++i) - if(_plugins[i].plugin != NULL && _plugins[i].plugin->configurationFileName().length() > 0) - { - if( _plugins[i].plugin->rs_cache_service() != NULL) - ConfigMgr->addConfiguration(_plugins[i].plugin->configurationFileName(), _plugins[i].plugin->rs_cache_service()); - //else if(_plugins[i].plugin->rs_pqi_service() != NULL) - // ConfigMgr->addConfiguration(_plugins[i].plugin->configurationFileName(), _plugins[i].plugin->rs_pqi_service()); - else if(_plugins[i].plugin->p3_config() != NULL) - ConfigMgr->addConfiguration(_plugins[i].plugin->configurationFileName(), _plugins[i].plugin->p3_config()); - else - continue ; - - std::cerr << " Added configuration for plugin " << _plugins[i].plugin->getPluginName() << ", with file " << _plugins[i].plugin->configurationFileName() << std::endl; - } -} - -bool RsPluginManager::loadList(std::list& list) -{ - std::set accepted_hash_candidates ; - std::set rejected_hash_candidates ; - - std::cerr << "RsPluginManager::loadList(): " << std::endl; - RsFileHash reference_executable_hash ; - - std::list::iterator it; - for(it = list.begin(); it != list.end(); ++it) - { - RsConfigKeyValueSet *witem = dynamic_cast(*it) ; - - if(witem) - for(std::list::const_iterator kit = witem->tlvkvs.pairs.begin(); kit != witem->tlvkvs.pairs.end(); ++kit) - { - if((*kit).key == "ALLOW_ALL_PLUGINS") - { - _allow_all_plugins = (kit->value == "YES"); - - if(_allow_all_plugins) - std::cerr << "WARNING: Allowing all plugins. No hash will be checked. Be careful! " << std::endl ; - } - else if((*kit).key == "REFERENCE_EXECUTABLE_HASH") - { - reference_executable_hash = RsFileHash(kit->value) ; - std::cerr << " Reference executable hash: " << kit->value << std::endl; - } - else if((*kit).key == "ACCEPTED") - { - accepted_hash_candidates.insert(RsFileHash((*kit).value)) ; - std::cerr << " Accepted hash: " << (*kit).value << std::endl; - } - else if((*kit).key == "REJECTED") - { - rejected_hash_candidates.insert(RsFileHash((*kit).value)) ; - std::cerr << " Rejected hash: " << (*kit).value << std::endl; - } - } - - delete (*it); - } - - // Rejected hashes are always kept, so that RS wont ask again if the executable hash has changed. - // - _rejected_hashes = rejected_hash_candidates ; - - if(reference_executable_hash == _current_executable_hash) - { - std::cerr << "(II) Executable hash matches. Updating the list of accepted/rejected plugins." << std::endl; - - _accepted_hashes = accepted_hash_candidates ; - } - else - std::cerr << "(WW) Executable hashes do not match. Executable hash has changed. Discarding the list of accepted/rejected plugins." << std::endl; - - return true; -} - -bool RsPluginManager::saveList(bool& cleanup, std::list& list) -{ - std::cerr << "PluginManager: saving list." << std::endl; - cleanup = true ; - - RsConfigKeyValueSet *witem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - kv.key = "ALLOW_ALL_PLUGINS" ; - kv.value = _allow_all_plugins?"YES":"NO" ; - witem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "REFERENCE_EXECUTABLE_HASH" ; - kv.value = _current_executable_hash.toStdString() ; - witem->tlvkvs.pairs.push_back(kv) ; - - std::cerr << " Saving current executable hash: " << kv.value << std::endl; - - // now push accepted and rejected hashes. - - for(std::set::const_iterator it(_accepted_hashes.begin());it!=_accepted_hashes.end();++it) - { - witem->tlvkvs.pairs.push_back( RsTlvKeyValue( "ACCEPTED", (*it).toStdString() ) ) ; - std::cerr << " " << *it << " : " << "ACCEPTED" << std::endl; - } - - for(std::set::const_iterator it(_rejected_hashes.begin());it!=_rejected_hashes.end();++it) - { - witem->tlvkvs.pairs.push_back( RsTlvKeyValue( "REJECTED", (*it).toStdString() ) ) ; - std::cerr << " " << *it << " : " << "REJECTED" << std::endl; - } - - list.push_back(witem) ; - - return true; -} - -RsPQIService::RsPQIService(uint16_t /*service_type*/, uint32_t /*tick_delay_in_seconds*/, RsPluginHandler* /*pgHandler*/) - : p3Service(),p3Config() -{ -} - diff --git a/libretroshare/src/plugins/pluginmanager.h b/libretroshare/src/plugins/pluginmanager.h deleted file mode 100644 index 965706bf1..000000000 --- a/libretroshare/src/plugins/pluginmanager.h +++ /dev/null @@ -1,159 +0,0 @@ -/******************************************************************************* - * libretroshare/src/plugins: pluginmanager.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include - -class p3ConfigMgr ; -class p3ServiceServer ; -class p3LinkMgr ; - -class PluginInfo -{ -public: - PluginInfo() : handle(NULL), plugin(NULL), API_version(0), svn_revision(0), status(0) {} - - public: - // Handle of the loaded plugin. - // - void *handle; - - // Main object provided by the plugin. NULL is the plugin could not be loaded. - // - RsPlugin *plugin ; - - // Information related to the file. Do not require the plugin to be loaded nor the DSO to be openned. - // - RsFileHash file_hash ; - std::string file_name ; - - // Information coming from directly loaded symbols. The plugin is responsible for providing them. - // - std::string creator ; // creator of the plugin - std::string name ; // name of the plugin - uint32_t API_version ; // API version. - uint32_t svn_revision ; // Coming from scripts. Same svn version but changing hash could be a security issue. - - // This info is filled when accessing the .so, and loading the plugin. - // - uint32_t status ; // See the flags in retroshare/rsplugin.h - std::string info_string ; -}; - -class RsPluginManager: public RsPluginHandler, public p3Config -{ - public: - explicit RsPluginManager(const RsFileHash& current_executable_sha1_hash) ; - virtual ~RsPluginManager() {} - - // ------------ Derived from RsPluginHandler ----------------// - // - virtual int nbPlugins() const { return _plugins.size() ; } - virtual RsPlugin *plugin(int i) { return _plugins[i].plugin ; } - virtual const std::vector& getPluginDirectories() const { return _plugin_directories ; } - virtual void getPluginStatus(int i, uint32_t& status,std::string& file_name, RsFileHash& hash,uint32_t& svn_revision,std::string& error_string) const ; - virtual void enablePlugin(const RsFileHash& hash) ; - virtual void disablePlugin(const RsFileHash &hash) ; - - virtual void slowTickPlugins(rstime_t sec) ; - virtual const std::string& getLocalCacheDir() const ; - virtual const std::string& getRemoteCacheDir() const ; - virtual RsServiceControl *getServiceControl() const ; - - virtual void allowAllPlugins(bool b) ; - virtual bool getAllowAllPlugins() const ; - - // ---------------- Derived from p3Config -------------------// - // - bool saveList(bool& cleanup, std::list& list) ; - bool loadList(std::list& list) ; - virtual RsSerialiser* setupSerialiser() ; - - // -------------------- Own members -------------------------// - // - virtual void addConfigurations(p3ConfigMgr *cfgMgr) ; - virtual bool loadConfiguration(RsFileHash &loadHash) ; - virtual void loadConfiguration() ; - - /*! - * sets interfaces for all loaded plugins - * @param interfaces - */ - void setInterfaces(RsPlugInInterfaces& interfaces); - - static bool acceptablePluginName(const std::string& s) ; - static void setCacheDirectories(const std::string& local,const std::string& remote) ; - static void setServiceControl(RsServiceControl *cm) { _service_control = cm ; } - - // Normal plugin loading system. Parses through the plugin directories and loads - // dso libraries, checks for the hash, and loads/rejects plugins according to - // the user's choice. - // - void loadPlugins(const std::vector& plugin_directories) ; - - // Explicit function to load a plugin programatically. - // No hash-checking is performed (there's no DSO file to hash!) - // Mostly convenient for insering plugins in development. - // - void loadPlugins(const std::vector& explicit_plugin_entries) ; - - void stopPlugins(p3ServiceServer *pqih); - - void registerCacheServices() ; - void registerClientServices(p3ServiceServer *pqih) ; - - private: - bool loadPlugin(RsPlugin *) ; - bool loadPlugin(const std::string& shared_library_name, bool first_time) ; - RsFileHash hashPlugin(const std::string& shared_library_name) ; - - std::vector _plugins ; - - // Should allow - // - searching - // - saving all hash - // - // At start - // * load reference executable hash. Compare with current executable. - // - if different => flush all plugin hashes from cache - // - if equal, - // - std::set _accepted_hashes ; // accepted hash values for reference executable hash. - std::set _rejected_hashes ; // rejected hash values for reference executable hash. - RsFileHash _current_executable_hash ; // At all times, the list of accepted plugins should be related to the current hash of the executable. - bool _allow_all_plugins ; - - static std::string _plugin_entry_symbol ; - static std::string _plugin_revision_symbol ; - static std::string _plugin_API_symbol ; - static std::string _remote_cache_dir ; - static std::string _local_cache_dir ; - - static RsServiceControl *_service_control ; - - static std::vector _plugin_directories ; -}; - diff --git a/libretroshare/src/plugins/rscacheservice.h b/libretroshare/src/plugins/rscacheservice.h deleted file mode 100644 index 82f43e0de..000000000 --- a/libretroshare/src/plugins/rscacheservice.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "plugins/pluginmanager.h" - -// This code needs to be re-written to work with GXS. For now it is obsolete. -// - -// The following class abstracts the construction of a cache service. The user only has to -// supply RS with a type ID. If the ID is already in use, RS will complain. -// -class RsCacheService: /* public CacheSource, public CacheStore, */ public p3Config -{ - public: - RsCacheService(uint16_t type,uint32_t tick_delay_in_seconds, RsPluginHandler* pgHandler) ; - - uint32_t tickDelay() const { return _tick_delay_in_seconds ; } - virtual void tick() {} - - // Functions from p3config - // - virtual RsSerialiser *setupSerialiser() { return NULL ; } - virtual bool saveList(bool&, std::list&) =0; - virtual bool loadList(std::list&) =0; - - private: - uint32_t _tick_delay_in_seconds ; -}; diff --git a/libretroshare/src/plugins/rspqiservice.h b/libretroshare/src/plugins/rspqiservice.h deleted file mode 100644 index f4ee6f313..000000000 --- a/libretroshare/src/plugins/rspqiservice.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "services/p3service.h" -#include "plugins/pluginmanager.h" - -// The following class abstracts the construction of a peer-to-peer service. The user only has to -// supply RS with a type ID. If the ID is already in use, RS will complain. -// -class RsPQIService: public p3Service, public p3Config -{ - public: - RsPQIService(uint16_t type,uint32_t tick_delay_in_seconds, RsPluginHandler* pgHandler) ; - - uint32_t tickDelay() const { return _tick_delay_in_seconds ; } - virtual int tick() = 0 ; - - // Functions from p3config - // - virtual RsSerialiser *setupSerialiser() { return NULL ; } - virtual bool saveList(bool&, std::list&) =0 ; - virtual bool loadList(std::list&) =0 ; - - private: - uint32_t _tick_delay_in_seconds ; -}; - diff --git a/libretroshare/src/pqi/authgpg.cc b/libretroshare/src/pqi/authgpg.cc deleted file mode 100644 index b41084cf0..000000000 --- a/libretroshare/src/pqi/authgpg.cc +++ /dev/null @@ -1,769 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: authgpg.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2009 by Robert Fernie, Retroshare Team. * - * * - * 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 . * - * * - *******************************************************************************/ -#include "authgpg.h" -#include "retroshare/rsiface.h" // For rsicontrol. -#include "retroshare/rspeers.h" // For RsPeerDetails. -#ifdef WINDOWS_SYS -#include "retroshare/rsinit.h" -#endif -#include "rsserver/p3face.h" -#include "pqi/p3notify.h" -#include "pgp/pgphandler.h" - -#include -#include -#include -#include /* for (u)sleep() */ -#include -#include -#include -#include -#include "rsitems/rsconfigitems.h" - -#define LIMIT_CERTIFICATE_SIZE 1 -#define MAX_CERTIFICATE_SIZE 10000 - -//#define DEBUG_AUTHGPG 1 - -//const rstime_t STORE_KEY_TIMEOUT = 1 * 60 * 60; //store key is call around every hour - -AuthGPG *AuthGPG::_instance = NULL ; - -void cleanupZombies(int numkill); // function to cleanup zombies under OSX. - -//#define GPG_DEBUG 1 - -/* Function to sign X509_REQ via GPGme. */ - -bool AuthGPG::decryptTextFromFile(std::string& text,const std::string& inputfile) -{ - return PGPHandler::decryptTextFromFile(mOwnGpgId,text,inputfile) ; -} - -bool AuthGPG::removeKeysFromPGPKeyring(const std::set& pgp_ids,std::string& backup_file,uint32_t& error_code) -{ -// std::list pids ; -// -// for(std::list::const_iterator it(pgp_ids.begin());it!=pgp_ids.end();++it) -// pids.push_back(RsPgpId(*it)) ; - - return PGPHandler::removeKeysFromPGPKeyring(pgp_ids,backup_file,error_code) ; -} - -// bool AuthGPG::decryptTextFromString(std::string& encrypted_text,std::string& output) -// { -// return PGPHandler::decryptTextFromString(mOwnGpgId,encrypted_text,output) ; -// } - -bool AuthGPG::encryptTextToFile(const std::string& text,const std::string& outfile) -{ - return PGPHandler::encryptTextToFile(mOwnGpgId,text,outfile) ; -} - -// bool AuthGPG::encryptTextToString(const std::string& pgp_id,const std::string& text,std::string& outstr) -// { -// return PGPHandler::encryptTextToString(RsPgpId(pgp_id),text,outstr) ; -// } - -std::string pgp_pwd_callback(void * /*hook*/, const char *uid_title, const char *uid_hint, const char * /*passphrase_info*/, int prev_was_bad,bool *cancelled) -{ -#ifdef GPG_DEBUG2 - fprintf(stderr, "pgp_pwd_callback() called.\n"); -#endif - std::string password; - RsServer::notify()->askForPassword(uid_title, uid_hint, prev_was_bad, password,cancelled) ; - - return password ; -} - -void AuthGPG::init( - const std::string& path_to_public_keyring, - const std::string& path_to_secret_keyring, - const std::string& path_to_trustdb, - const std::string& pgp_lock_file) -{ - if(_instance != NULL) - { - exit(); - std::cerr << "AuthGPG::init() called twice!" << std::endl ; - } - -// if(cb) PGPHandler::setPassphraseCallback(cb);else - PGPHandler::setPassphraseCallback(pgp_pwd_callback); - _instance = new AuthGPG( path_to_public_keyring, - path_to_secret_keyring, - path_to_trustdb, pgp_lock_file ); -} - -void AuthGPG::exit() -{ - if(_instance) - { - _instance->fullstop(); - delete _instance; - _instance = nullptr; - } -} - -AuthGPG::AuthGPG(const std::string& path_to_public_keyring,const std::string& path_to_secret_keyring,const std::string& path_to_trustdb,const std::string& pgp_lock_file) - :p3Config(), - PGPHandler(path_to_public_keyring,path_to_secret_keyring,path_to_trustdb,pgp_lock_file), - gpgMtxService("AuthGPG-service"), - gpgMtxEngine("AuthGPG-engine"), - gpgMtxData("AuthGPG-data"), - mStoreKeyTime(0), - gpgKeySelected(false), - _force_sync_database(false), - mCount(0) -{ - start("AuthGPG"); -} - -/* This function is called when retroshare is first started - * to get the list of available GPG certificates. - * This function should only return certs for which - * the private(secret) keys are available. - * - * returns false if GnuPG is not available. - */ -//bool AuthGPG::availableGPGCertificatesWithPrivateKeys(std::list &ids) -//{ -// std::list pids ; -// -// PGPHandler::availableGPGCertificatesWithPrivateKeys(pids) ; -// -// for(std::list::const_iterator it(pids.begin());it!=pids.end();++it) -// ids.push_back( (*it).toStdString() ) ; -// -// /* return false if there are no private keys */ -// return !ids.empty(); -//} - -/* You can initialise Retroshare with - * (a) load existing certificate. - * (b) a new certificate. - * - * This function must be called successfully (return == 1) - * before anything else can be done. (except above fn). - */ -int AuthGPG::GPGInit(const RsPgpId &ownId) -{ -#ifdef DEBUG_AUTHGPG - std::cerr << "AuthGPG::GPGInit() called with own gpg id : " << ownId.toStdString() << std::endl; -#endif - - mOwnGpgId = RsPgpId(ownId); - - //force the validity of the private key. When set to unknown, it caused signature and text encryptions bugs - privateTrustCertificate(ownId, 5); - updateOwnSignatureFlag(mOwnGpgId) ; - -#ifdef DEBUG_AUTHGPG - std::cerr << "AuthGPG::GPGInit finished." << std::endl; -#endif - - return 1; -} - - AuthGPG::~AuthGPG() -{ -} - -void AuthGPG::threadTick() -{ - rstime::rs_usleep(100 * 1000); //100 msec - - /// every 100 milliseconds - processServices(); - - /// every ten seconds - if (++mCount >= 100 || _force_sync_database) { - RsStackMutex stack(gpgMtxService); ///******* LOCKED ****** - - /// The call does multiple things at once: - /// - checks whether the keyring has changed in memory - /// - checks whether the keyring has changed on disk. - /// - merges/updates according to status. - /// - PGPHandler::syncDatabase() ; - mCount = 0; - _force_sync_database = false ; - }//if (++count >= 100 || _force_sync_database) -} - -void AuthGPG::processServices() -{ - AuthGPGOperation *operation = NULL; - AuthGPGService *service = NULL; - - { - RsStackMutex stack(gpgMtxService); /******* LOCKED ******/ - - std::list::iterator serviceIt; - for (serviceIt = services.begin(); serviceIt != services.end(); ++serviceIt) { - operation = (*serviceIt)->getGPGOperation(); - if (operation) { - service = *serviceIt; - break; - } - } - } /******* UNLOCKED ******/ - - if (operation == NULL) { - /* nothing to do */ - return; - } - - if (service == NULL) { - /* huh ? */ - delete operation; - return; - } - - AuthGPGOperationLoadOrSave *loadOrSave = dynamic_cast(operation); - if (loadOrSave) - { - if (loadOrSave->m_load) - { - /* process load operation */ - - - /* load the certificate */ - - - /* don't bother loading - if we already have the certificate */ - if (isGPGId(loadOrSave->m_certGpgId)) - { -#ifdef GPG_DEBUG - std::cerr << "AuthGPGimpl::processServices() Skipping load - already have it" << std::endl; -#endif - } - else - { -#ifdef GPG_DEBUG - std::cerr << "AuthGPGimpl::processServices() Process load operation" << std::endl; -#endif - std::string error_string ; - RsPgpId pgp_id ; - LoadCertificateFromString(loadOrSave->m_certGpg, pgp_id,error_string); - loadOrSave->m_certGpgId = pgp_id; - } - - - - } else { - /* process save operation */ - -#ifdef GPG_DEBUG - std::cerr << "AuthGPGimpl::processServices() Process save operation" << std::endl; -#endif - - /* save the certificate to string */ - /***** - * #define DISABLE_CERTIFICATE_SEND 1 - ****/ - - loadOrSave->m_certGpg = SaveCertificateToString(loadOrSave->m_certGpgId,true); - -#ifdef GPG_DEBUG - std::cerr << "Certificate for: " << loadOrSave->m_certGpgId << " is: "; - std::cerr << std::endl; - std::cerr << loadOrSave->m_certGpg; - std::cerr << std::endl; -#endif - - } - - service->setGPGOperation(loadOrSave); - } - else - { -#ifdef GPG_DEBUG - std::cerr << "AuthGPGimpl::processServices() Unknown operation" << std::endl; -#endif - } - - delete operation; -} - -bool AuthGPG::DoOwnSignature(const void *data, unsigned int datalen, void *buf_sigout, unsigned int *outl, std::string reason /* = "" */) -{ - return PGPHandler::SignDataBin(mOwnGpgId,data,datalen,(unsigned char *)buf_sigout,outl,false,reason) ; -} - - -/* import to GnuPG and other Certificates */ -bool AuthGPG::VerifySignature(const void *data, int datalen, const void *sig, unsigned int siglen, const PGPFingerprintType& withfingerprint) -{ - return PGPHandler::VerifySignBin((unsigned char*)data,datalen,(unsigned char*)sig,siglen,withfingerprint) ; -} - -bool AuthGPG::parseSignature(const void *sig, unsigned int siglen, RsPgpId& issuer_id) -{ - return PGPHandler::parseSignature((unsigned char*)sig,siglen,issuer_id) ; -} - -bool AuthGPG::exportProfile(const std::string& fname,const RsPgpId& exported_id) -{ - return PGPHandler::exportGPGKeyPair(fname,exported_id) ; -} - -bool AuthGPG::exportIdentityToString( - std::string& data, const RsPgpId& pgpId, bool includeSignatures, - std::string& errorMsg ) -{ - return PGPHandler::exportGPGKeyPairToString( - data, pgpId, includeSignatures, errorMsg); -} - -bool AuthGPG::importProfile(const std::string& fname,RsPgpId& imported_id,std::string& import_error) -{ - return PGPHandler::importGPGKeyPair(fname,imported_id,import_error) ; -} - -bool AuthGPG::importProfileFromString(const std::string &data, RsPgpId &gpg_id, std::string &import_error) -{ - return PGPHandler::importGPGKeyPairFromString(data, gpg_id, import_error); -} - -bool AuthGPG::active() -{ - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - - return gpgKeySelected; -} - -bool AuthGPG::GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId& pgpId, const int keynumbits, std::string& errString) -{ - RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ - - return PGPHandler::GeneratePGPCertificate(name, email, passwd, pgpId, keynumbits, errString) ; -} - -/**** These Two are common */ -std::string AuthGPG::getGPGName(const RsPgpId& id,bool *success) -{ - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - - const PGPCertificateInfo *info = getCertificateInfo(id) ; - - if(info != NULL) - { - if(success != NULL) *success = true ; - return info->_name ; - } - else - { - if(success != NULL) *success = false ; - return "[Unknown PGP Cert name]" ; - } -} - -/**** These Two are common */ -std::string AuthGPG::getGPGEmail(const RsPgpId& id,bool *success) -{ - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - const PGPCertificateInfo *info = getCertificateInfo(id) ; - - if(info != NULL) - { - if(success != NULL) *success = true ; - return info->_email ; - } - else - { - if(success != NULL) *success = false ; - return "[Unknown PGP Cert email]" ; - } -} - -/**** GPG versions ***/ - -const RsPgpId& AuthGPG::getGPGOwnId() -{ - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - return mOwnGpgId ; -} - -std::string AuthGPG::getGPGOwnName() -{ - return getGPGName(mOwnGpgId) ; -} - -bool AuthGPG::getGPGAllList(std::list &ids) -{ - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - - PGPHandler::getGPGFilteredList(ids) ; - - return true; -} -const PGPCertificateInfo *AuthGPG::getCertInfoFromStdString(const std::string& pgp_id) const -{ - try - { - return PGPHandler::getCertificateInfo(RsPgpId(pgp_id)) ; - } - catch(std::exception& e) - { - std::cerr << "(EE) exception raised while constructing a PGP certificate from id \"" << pgp_id << "\": " << e.what() << std::endl; - return NULL ; - } -} -bool AuthGPG::haveSecretKey(const RsPgpId& id) const -{ - return PGPHandler::haveSecretKey(id) ; -} -bool AuthGPG::isKeySupported(const RsPgpId& id) const -{ - const PGPCertificateInfo *pc = getCertificateInfo(id) ; - - if(pc == NULL) - return false ; - - return !(pc->_flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM) ; -} - -bool AuthGPG::getGPGDetails(const RsPgpId& pgp_id, RsPeerDetails &d) -{ - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - - const PGPCertificateInfo *pc = PGPHandler::getCertificateInfo(pgp_id) ; - - if(pc == NULL) - return false ; - - const PGPCertificateInfo& cert(*pc) ; - - d.id.clear() ; - d.gpg_id = pgp_id ; - d.name = cert._name; - d.lastUsed = cert._time_stamp; - d.email = cert._email; - d.trustLvl = cert._trustLvl; - d.validLvl = cert._trustLvl; - d.ownsign = cert._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE; - d.gpgSigners.clear() ; - - for(std::set::const_iterator it(cert.signers.begin());it!=cert.signers.end();++it) - d.gpgSigners.push_back( *it ) ; - - d.fpr = cert._fpr ; - d.accept_connection = cert._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION; - d.hasSignedMe = cert._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME; - - return true; -} - -bool AuthGPG::getGPGFilteredList(std::list& list,bool (*filter)(const PGPCertificateInfo&)) -{ - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - - return PGPHandler::getGPGFilteredList(list,filter) ; -} - -static bool filter_Validity(const PGPCertificateInfo& /*info*/) { return true ; } //{ return info._validLvl >= PGPCertificateInfo::GPGME_VALIDITY_MARGINAL ; } -static bool filter_Accepted(const PGPCertificateInfo& info) { return info._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ; } -static bool filter_OwnSigned(const PGPCertificateInfo& info) { return info._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ; } - -bool AuthGPG::getGPGValidList(std::list &ids) -{ - return getGPGFilteredList(ids,&filter_Validity); -} - -bool AuthGPG::getGPGAcceptedList(std::list &ids) -{ - return getGPGFilteredList(ids,&filter_Accepted); -} - -bool AuthGPG::getGPGSignedList(std::list &ids) -{ - return getGPGFilteredList(ids,&filter_OwnSigned); -} - -// bool AuthGPG::getCachedGPGCertificate(const RsPgpId &id, std::string &certificate) -// { -// RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ -// #ifdef LIMIT_CERTIFICATE_SIZE -// certificate = PGPHandler::SaveCertificateToString(RsPgpId(id),false) ; -// #else -// certificate = PGPHandler::SaveCertificateToString(RsPgpId(id),true) ; -// #endif -// -// // #ifdef LIMIT_CERTIFICATE_SIZE -// // std::string cleaned_key ; -// // if(PGPKeyManagement::createMinimalKey(certificate,cleaned_key)) -// // certificate = cleaned_key ; -// // #endif -// -// return certificate.length() > 0 ; -// } - -/***************************************************************** - * Loading and Saving Certificates - this has to - * be able to handle both openpgp and X509 certificates. - * - * X509 are passed onto AuthSSL, OpenPGP are passed to gpgme. - * - */ - - -/* SKTAN : do not know how to use std::string id */ - std::string AuthGPG::SaveCertificateToString(const RsPgpId &id,bool include_signatures) - { - RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ - - return PGPHandler::SaveCertificateToString(id,include_signatures) ; - } -/* import to GnuPG and other Certificates */ -bool AuthGPG::LoadPGPKeyFromBinaryData(const unsigned char *data,uint32_t data_len, RsPgpId& gpg_id,std::string& error_string) -{ - RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ - - if(PGPHandler::LoadCertificateFromBinaryData(data,data_len,gpg_id,error_string)) - { - updateOwnSignatureFlag(gpg_id,mOwnGpgId) ; - return true ; - } - - return false ; -} - -/* import to GnuPG and other Certificates */ -bool AuthGPG::LoadCertificateFromString(const std::string &str, RsPgpId& gpg_id,std::string& error_string) -{ - RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ - - if(PGPHandler::LoadCertificateFromString(str,gpg_id,error_string)) - { - updateOwnSignatureFlag(gpg_id,mOwnGpgId) ; - return true ; - } - - return false ; -} - -/***************************************************************** - * Auth...? Signing, Revoke, Trust are all done at - * the PGP level.... - * - * Only Signing of SSL is done at setup. - * Auth should be done... ?? not sure - * maybe - * - */ - - -/*************************************/ - -/* These take PGP Ids */ -bool AuthGPG::AllowConnection(const RsPgpId& gpg_id, bool accept) -{ -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::AllowConnection(" << gpg_id << ")" << std::endl; -#endif - - /* Was a "Reload Certificates" here -> be shouldn't be needed -> and very expensive, try without. */ - { - RsStackMutex stack(gpgMtxData); - PGPHandler::setAcceptConnexion(gpg_id,accept) ; - } - - IndicateConfigChanged(); - - RsServer::notify()->notifyListChange(NOTIFY_LIST_FRIENDS, accept ? NOTIFY_TYPE_ADD : NOTIFY_TYPE_DEL); - - return true; -} - -/* These take PGP Ids */ -bool AuthGPG::SignCertificateLevel0(const RsPgpId &id) -{ -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::SignCertificat(" << id << ")" << std::endl; -#endif - - return privateSignCertificate(id) ; -} - -bool AuthGPG::RevokeCertificate(const RsPgpId &id) -{ - /* remove unused parameter warnings */ - (void) id; - -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::RevokeCertificate(" << id << ") not implemented yet" << std::endl; -#endif - - return false; -} - -bool AuthGPG::TrustCertificate(const RsPgpId& id, int trustlvl) -{ -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::TrustCertificate(" << id << ", " << trustlvl << ")" << std::endl; -#endif - return privateTrustCertificate(id, trustlvl) ; -} - -bool AuthGPG::encryptDataBin(const RsPgpId& pgp_id,const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen) -{ - return PGPHandler::encryptDataBin(RsPgpId(pgp_id),data,datalen,sign,signlen) ; -} - -bool AuthGPG::decryptDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen) -{ - return PGPHandler::decryptDataBin(mOwnGpgId,data,datalen,sign,signlen) ; -} -bool AuthGPG::SignDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen, std::string reason /*= ""*/) -{ - return DoOwnSignature(data, datalen, sign, signlen, reason); -} - -bool AuthGPG::VerifySignBin(const void *data, uint32_t datalen, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint) -{ - return VerifySignature(data, datalen, sign, signlen, withfingerprint); -} - -/* Sign/Trust stuff */ - -int AuthGPG::privateSignCertificate(const RsPgpId &id) -{ - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - - int ret = PGPHandler::privateSignCertificate(mOwnGpgId,id) ; - _force_sync_database = true ; - return ret ; -} - -/* revoke the signature on Certificate */ -int AuthGPG::privateRevokeCertificate(const RsPgpId &/*id*/) -{ - //RsStackMutex stack(gpgMtx); /******* LOCKED ******/ - std::cerr << __PRETTY_FUNCTION__ << ": not implemented!" << std::endl; - - return 0; -} - -int AuthGPG::privateTrustCertificate(const RsPgpId& id, int trustlvl) -{ - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - - // csoler: Why are we not allowing this when the peer is not in the accepted peers list?? - // The trust level is only a user-defined property that has nothing to - // do with the fact that we allow connections or not. - - if(!isGPGAccepted(id)) - return 0; - - int res = PGPHandler::privateTrustCertificate(id,trustlvl) ; - _force_sync_database = true ; - return res ; -} - -// -----------------------------------------------------------------------------------// -// -------------------------------- Config functions ------------------------------ // -// -----------------------------------------------------------------------------------// -// -RsSerialiser *AuthGPG::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - return rss ; -} - -bool AuthGPG::saveList(bool& cleanup, std::list& lst) -{ -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::saveList() called" << std::endl ; -#endif - std::list ids ; - getGPGAcceptedList(ids) ; // needs to be done before the lock - - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - - cleanup = true ; - - // Now save config for network digging strategies - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - - for (std::list::const_iterator it(ids.begin()); it != ids.end(); ++it) - if((*it) != mOwnGpgId) // skip our own id. - { - RsTlvKeyValue kv; - kv.key = (*it).toStdString() ; -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::saveList() called (it->second) : " << (it->second) << std::endl ; -#endif - kv.value = "TRUE"; - vitem->tlvkvs.pairs.push_back(kv) ; - } - lst.push_back(vitem); - - return true; -} - -bool AuthGPG::loadList(std::list& load) -{ -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::loadList() Item Count: " << load.size() << std::endl; -#endif - - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - /* load the list of accepted gpg keys */ - std::list::iterator it; - for(it = load.begin(); it != load.end(); ++it) - { - RsConfigKeyValueSet *vitem = dynamic_cast(*it); - if(vitem) - { -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::loadList() General Variable Config Item:" << std::endl; - vitem->print(std::cerr, 10); - std::cerr << std::endl; -#endif - - std::list::iterator kit; - for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - if (kit->key != mOwnGpgId.toStdString()) - PGPHandler::setAcceptConnexion(RsPgpId(kit->key), (kit->value == "TRUE")); - } - delete (*it); - } - load.clear() ; - return true; -} - -bool AuthGPG::addService(AuthGPGService *service) -{ - RsStackMutex stack(gpgMtxService); /********* LOCKED *********/ - - if (std::find(services.begin(), services.end(), service) != services.end()) { - /* it exists already! */ - return false; - } - - services.push_back(service); - return true; -} - - diff --git a/libretroshare/src/pqi/authgpg.h b/libretroshare/src/pqi/authgpg.h deleted file mode 100644 index 4fe76194c..000000000 --- a/libretroshare/src/pqi/authgpg.h +++ /dev/null @@ -1,303 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: authgpg.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2009 by Raghu Dev R. * - * * - * 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 . * - * * - *******************************************************************************/ - -/**** - * Here's GPG policy : - * By default, all pgpg keys imported via a RS user (make friend and accept friend action) are signed at level 0. - * All signed keys by RS are set to be trusted marginally. You can change it to full or no trust in the friend profile - * For a key to be marginaly valid, it has to be signed by one fully trusted key, or at least by 3 marginally trusted keys. - * All keys that have at least marginal validity are designed as valid in RS. They are shown in the RS gui in order to be signed. - * If there is no validity then the key is not shown. - */ - -#ifndef RS_GPG_AUTH_HEADER -#define RS_GPG_AUTH_HEADER - -#include "util/rsthreads.h" -#include "pqi/p3cfgmgr.h" -#include "pgp/pgphandler.h" - -#define MAX_GPG_SIGNATURE_SIZE 4096 - -struct RsPeerDetails; - -/*! - * gpgcert is the identifier for a person. - * It is a wrapper class for a OpenPGP certificate. - */ - -class AuthGPGOperation -{ -public: - explicit AuthGPGOperation(void *userdata) - { - m_userdata = userdata; - } - virtual ~AuthGPGOperation() {} - -public: - void *m_userdata; -}; - -class AuthGPGOperationLoadOrSave : public AuthGPGOperation -{ -public: - AuthGPGOperationLoadOrSave(bool load, const RsPgpId &gpgId, const std::string &gpgCert, void *userdata) - : AuthGPGOperation(userdata) - { - m_load = load; - if (m_load) { - m_certGpg = gpgCert; - m_certGpgId = gpgId; - } else { - m_certGpgId = gpgId; - } - } - -public: - bool m_load; - RsPgpId m_certGpgId; // set for save & load. - std::string m_certGpg; // set for load -}; - -class AuthGPGService -{ -public: - AuthGPGService() {} - ~AuthGPGService() {} - - virtual AuthGPGOperation *getGPGOperation() = 0; - virtual void setGPGOperation(AuthGPGOperation *operation) = 0; -}; - -class AuthGPG: public p3Config, public RsTickingThread, public PGPHandler -{ -public: - static void init(const std::string& path_to_pubring, - const std::string& path_to_secring, - const std::string& path_to_trustdb, - const std::string& pgp_lock_file); - - static void exit(); - static AuthGPG *getAuthGPG() { return _instance ; } - - /** - * @param ids list of gpg certificate ids (note, not the actual certificates) - */ - //virtual bool availableGPGCertificatesWithPrivateKeys(std::list &ids); - - /*********************************************************************************/ - /************************* STAGE 1 ***********************************************/ - /*********************************************************************************/ - /***** - * STAGE 1: Initialisation.... As we are switching to OpenPGP the init functions - * will be different. Just move the initialisation functions over.... - * - * As GPGMe requires external calls to the GPG executable, which could potentially - * be expensive, We'll want to cache the GPG keys in this class. - * This should be done at initialisation, and saved in a map. - * (see storage at the end of the class) - * - ****/ - virtual bool active(); - - // /* Initialize */ - // virtual bool InitAuth (); - // virtual bool CloseAuth(); - - /* Init by generating new Own PGP Cert, or selecting existing PGP Cert */ - - virtual int GPGInit(const RsPgpId &ownId); - virtual bool GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId &pgpId, const int keynumbits, std::string &errString); - - /*********************************************************************************/ - /************************* STAGE 3 ***********************************************/ - /*********************************************************************************/ - /***** - * STAGE 3: These are some of the most commonly used functions in Retroshare. - * - * More commonly used functions. - * - * provide access to details in cache list. - * - ****/ - virtual std::string getGPGName(const RsPgpId &pgp_id,bool *success = NULL); - virtual std::string getGPGEmail(const RsPgpId &pgp_id,bool *success = NULL); - - /* PGP web of trust management */ - virtual const RsPgpId& getGPGOwnId(); - virtual std::string getGPGOwnName(); - - //virtual std::string getGPGOwnEmail(); - virtual bool isKeySupported(const RsPgpId &id) const ; - virtual bool haveSecretKey(const RsPgpId &id) const ; - virtual bool getGPGDetails(const RsPgpId& id, RsPeerDetails &d); - virtual bool getGPGAllList(std::list &ids); - virtual bool getGPGValidList(std::list &ids); - virtual bool getGPGAcceptedList(std::list &ids); - virtual bool getGPGSignedList(std::list &ids); - virtual bool importProfile(const std::string& filename,RsPgpId& gpg_id,std::string& import_error) ; - virtual bool importProfileFromString(const std::string& data,RsPgpId& gpg_id,std::string& import_error) ; - virtual bool exportProfile(const std::string& filename,const RsPgpId& gpg_id) ; - virtual bool exportIdentityToString( - std::string& data, const RsPgpId& pgpId, bool includeSignatures, - std::string& errorMsg ); - - virtual bool removeKeysFromPGPKeyring(const std::set &pgp_ids,std::string& backup_file,uint32_t& error_code) ; - - /*********************************************************************************/ - /************************* STAGE 4 ***********************************************/ - /*********************************************************************************/ - /***** - * STAGE 4: Loading and Saving Certificates. (Strings and Files) - * - ****/ - virtual bool LoadCertificateFromString(const std::string &pem, RsPgpId& gpg_id,std::string& error_string); - virtual bool LoadPGPKeyFromBinaryData(const unsigned char *data,uint32_t data_len, RsPgpId& gpg_id,std::string& error_string); - virtual std::string SaveCertificateToString(const RsPgpId &id,bool include_signatures) ; - - // Cached certificates. - //bool getCachedGPGCertificate(const RsPgpId &id, std::string &certificate); - - /*********************************************************************************/ - /************************* STAGE 6 ***********************************************/ - /*********************************************************************************/ - /***** - * STAGE 6: Authentication, Trust and Signing. - * - * This is some of the harder functions, but they should have been - * done in gpgroot already. - * - ****/ - virtual bool AllowConnection(const RsPgpId &gpg_id, bool accept); - - virtual bool SignCertificateLevel0(const RsPgpId &id); - virtual bool RevokeCertificate(const RsPgpId &id); /* Particularly hard - leave for later */ - - virtual bool TrustCertificate(const RsPgpId& id, int trustlvl); //trustlvl is 2 for none, 3 for marginal and 4 for full trust - - /*********************************************************************************/ - /************************* STAGE 7 ***********************************************/ - /*********************************************************************************/ - /***** - * STAGE 7: Signing Data. - * - * There should also be Encryption Functions... (do later). - * - ****/ - virtual bool SignDataBin(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, std::string reason = ""); - virtual bool VerifySignBin(const void*, uint32_t, unsigned char*, unsigned int, const PGPFingerprintType& withfingerprint); - virtual bool parseSignature(const void *sig, unsigned int siglen, RsPgpId& issuer_id); - - virtual bool encryptDataBin(const RsPgpId& pgp_id,const void *data, const uint32_t len, unsigned char *encr, unsigned int *encrlen); - virtual bool decryptDataBin(const void *data, const uint32_t len, unsigned char *decr, unsigned int *decrlen); - - virtual bool decryptTextFromFile( std::string& text,const std::string& filename); - virtual bool encryptTextToFile (const std::string& text,const std::string& filename); - -// virtual bool decryptTextFromString( std::string& encrypted_text,std::string& clear_string); -// virtual bool encryptTextToString (const std::string& pgp_id,const std::string& clear_text,std::string& encrypted_string); - - bool getGPGFilteredList(std::list& list,bool (*filter)(const PGPCertificateInfo&) = NULL) ; - - //END of PGP public functions - - /* GPG service */ - virtual bool addService(AuthGPGService *service) ; - - // This is for debug purpose only. Don't use it !! - static void setAuthGPG_debug(AuthGPG *auth_gpg) { _instance = auth_gpg ; } - - protected: - AuthGPG(const std::string& path_to_pubring, const std::string& path_to_secring,const std::string& path_to_trustdb,const std::string& pgp_lock_file); - virtual ~AuthGPG(); - - /*****************************************************************/ - /*********************** p3config ******************************/ - /* Key Functions to be overloaded for Full Configuration */ - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool &cleanup, std::list&); - virtual bool loadList(std::list& load); - /*****************************************************************/ - -private: - // Gets the certificate pointer and returns NULL if the string is invalid, or the - // cert was not found. - // - const PGPCertificateInfo *getCertInfoFromStdString(const std::string& ) const; - - /* SKTAN */ - //void showData(gpgme_data_t dh); - //void createDummyFriends(void); //NYI - - /* Internal functions */ - bool DoOwnSignature(const void *, unsigned int, void *, unsigned int *, std::string reason); - bool VerifySignature(const void *data, int datalen, const void *sig, unsigned int siglen, const PGPFingerprintType& withfingerprint); - - /* Sign/Trust stuff */ - int privateSignCertificate(const RsPgpId &id); - int privateRevokeCertificate(const RsPgpId &id); /* revoke the signature on Certificate */ - int privateTrustCertificate(const RsPgpId& id, int trustlvl); - - // store all keys in map mKeyList to avoid calling gpgme exe repeatedly - //bool storeAllKeys(); - //bool storeAllKeys_tick(); - - // Not used anymore - // bool updateTrustAllKeys_locked(); - - /* GPG service */ - void processServices(); - - bool printAllKeys_locked(); - bool printOwnKeys_locked(); - - void threadTick() override; /// @see RsTickingThread - -private: - - static AuthGPG *instance_gpg; // pointeur vers le singleton - - RsMutex gpgMtxService; - RsMutex gpgMtxEngine; - - /* Below is protected via the mutex */ - - // gpgme_engine_info_t INFO; - // gpgme_ctx_t CTX; - - RsMutex gpgMtxData; - /* Below is protected via the mutex */ - - rstime_t mStoreKeyTime; - - RsPgpId mOwnGpgId; - bool gpgKeySelected; - bool _force_sync_database ; - uint32_t mCount ; - - std::list services ; - - static AuthGPG *_instance ; -}; - -#endif diff --git a/libretroshare/src/pqi/authssl.cc b/libretroshare/src/pqi/authssl.cc deleted file mode 100644 index eb89a1ed5..000000000 --- a/libretroshare/src/pqi/authssl.cc +++ /dev/null @@ -1,1851 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: authssl.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#ifdef WINDOWS_SYS -#include "util/rswin.h" -#endif // WINDOWS_SYS - -#include "authssl.h" -#include "sslfns.h" - -#include "pqinetwork.h" -#include "authgpg.h" -#include "rsitems/rsconfigitems.h" -#include "util/rsdebug.h" -#include "util/rsdir.h" -#include "util/rsstring.h" -#include "pgp/pgpkeyutil.h" - -#include "retroshare/rspeers.h" // for RsPeerDetails structure -#include "retroshare/rsids.h" // for RsPeerDetails structure -#include "rsserver/p3face.h" - -/******************** notify of new Cert **************************/ - -#include -#include - -#include - -/* SSL connection diagnostic */ - -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_UNKNOWN = 0x00 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_OK = 0x01 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_CERTIFICATE_NOT_VALID = 0x02 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_ISSUER_UNKNOWN = 0x03 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR = 0x04 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE = 0x05 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_CERTIFICATE_MISSING = 0x06 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_HASH_ALGORITHM_NOT_ACCEPTED = 0x07 ; -//const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_KEY_ALGORITHM_NOT_ACCEPTED = 0x08 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE_TYPE = 0x09 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE_VERSION = 0x0a ; - -/**** - * #define AUTHSSL_DEBUG 1 - ***/ - -static pthread_mutex_t* mutex_buf = nullptr; - -struct CRYPTO_dynlock_value -{ - pthread_mutex_t mutex; -}; - -# if OPENSSL_VERSION_NUMBER < 0x10100000L -/** - * OpenSSL locking function. - * - * @param mode lock mode - * @param n lock number - * @param file source file name - * @param line source file line number - * @return none - */ -static void locking_function(int mode, int n, const char */*file*/, int /*line*/) -{ - if (mode & CRYPTO_LOCK) { - pthread_mutex_lock(&mutex_buf[n]); - } else { - pthread_mutex_unlock(&mutex_buf[n]); - } -} -#endif - -# if OPENSSL_VERSION_NUMBER < 0x10100000L -/** - * OpenSSL uniq id function. - * - * @return thread id - */ -static unsigned long id_function(void) -{ -#if defined( WINDOWS_SYS) && !defined(WIN_PTHREADS_H) - return (unsigned long) pthread_self().p; -#else - return (unsigned long) pthread_self(); -#endif -} -#endif - -# if OPENSSL_VERSION_NUMBER < 0x10100000L -/** - * OpenSSL allocate and initialize dynamic crypto lock. - * - * @param file source file name - * @param line source file line number - */ -static struct CRYPTO_dynlock_value *dyn_create_function(const char */*file*/, int /*line*/) -{ - struct CRYPTO_dynlock_value *value; - - value = (struct CRYPTO_dynlock_value*) rs_malloc(sizeof(struct CRYPTO_dynlock_value)); - if (!value) - return NULL; - - pthread_mutex_init(&value->mutex, NULL); - - return value; -} -#endif - -# if OPENSSL_VERSION_NUMBER < 0x10100000L -/** - * OpenSSL dynamic locking function. - * - * @param mode lock mode - * @param l lock structure pointer - * @param file source file name - * @param line source file line number - * @return none - */ -static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, const char */*file*/, int /*line*/) -{ - if (mode & CRYPTO_LOCK) { - pthread_mutex_lock(&l->mutex); - } else { - pthread_mutex_unlock(&l->mutex); - } -} -#endif - -# if OPENSSL_VERSION_NUMBER < 0x10100000L -/** - * OpenSSL destroy dynamic crypto lock. - * - * @param l lock structure pointer - * @param file source file name - * @param line source file line number - * @return none - */ -static void dyn_destroy_function(struct CRYPTO_dynlock_value *l, const char */*file*/, int /*line*/) -{ - pthread_mutex_destroy(&l->mutex); - free(l); -} -#endif - -/** - * Initialize TLS library. - * - * @return true on success, false on error - */ -bool tls_init() -{ - /* static locks area */ - mutex_buf = (pthread_mutex_t*) rs_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); - if (mutex_buf == NULL) - return false; - - for (int i = 0; i < CRYPTO_num_locks(); i++) { - pthread_mutex_init(&mutex_buf[i], NULL); - } -# if OPENSSL_VERSION_NUMBER < 0x10100000L - /* static locks callbacks */ - CRYPTO_set_locking_callback(locking_function); - CRYPTO_set_id_callback(id_function); - /* dynamic locks callbacks */ - CRYPTO_set_dynlock_create_callback(dyn_create_function); - CRYPTO_set_dynlock_lock_callback(dyn_lock_function); - CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function); -#endif - return true; -} - -/** - * Cleanup TLS library. - * - * @return 0 - */ -void tls_cleanup() -{ - CRYPTO_set_dynlock_create_callback(NULL); - CRYPTO_set_dynlock_lock_callback(NULL); - CRYPTO_set_dynlock_destroy_callback(NULL); - - CRYPTO_set_locking_callback(NULL); - CRYPTO_set_id_callback(NULL); - - if (mutex_buf != NULL) { - for (int i = 0; i < CRYPTO_num_locks(); i++) { - pthread_mutex_destroy(&mutex_buf[i]); - } - free(mutex_buf); - mutex_buf = NULL; - } -} - -/*static*/ AuthSSL& AuthSSL::instance() -{ - static AuthSSLimpl mInstance; - return mInstance; -} - -AuthSSL* AuthSSL::getAuthSSL() { return &instance(); } - -AuthSSL::~AuthSSL() = default; - - -/********************************************************************************/ -/********************************************************************************/ -/********************* Cert Search / Add / Remove **************************/ -/********************************************************************************/ -/********************************************************************************/ - -static int verify_x509_callback(int preverify_ok, X509_STORE_CTX *ctx); - -std::string RsX509Cert::getCertName(const X509& x509) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return getX509CNString(x509.cert_info->subject); -#else - return getX509CNString(X509_get_subject_name(&x509)); -#endif -} - -std::string RsX509Cert::getCertLocation(const X509& x509) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return getX509LocString(x509.cert_info->subject); -#else - return getX509LocString(X509_get_subject_name(&x509)); -#endif -} - -std::string RsX509Cert::getCertOrg(const X509& x509) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return getX509OrgString(x509.cert_info->subject); -#else - return getX509OrgString(X509_get_subject_name(&x509)); -#endif -} - -/*static*/ RsPgpId RsX509Cert::getCertIssuer(const X509& x509) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return RsPgpId(getX509CNString(x509.cert_info->issuer)); -#else - return RsPgpId(getX509CNString(X509_get_issuer_name(&x509))); -#endif -} - -/*static*/ std::string RsX509Cert::getCertIssuerString(const X509& x509) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return getX509CNString(x509.cert_info->issuer); -#else - return getX509CNString(X509_get_issuer_name(&x509)); -#endif -} - -/*static*/ RsPeerId RsX509Cert::getCertSslId(const X509& x509) -{ - RsPeerId sslid; - return getX509id(const_cast(&x509), sslid) ? sslid : RsPeerId(); -} - -/************************************************************************ - * - * - * CODE IS DIVIDED INTO - * - * 1) SSL Setup. - * 3) Cert Access. - * 4) Cert Sign / Verify. - * 5) Cert Authentication - * 2) Cert Add / Remove - * 6) Cert Storage - */ - -/********************************************************************************/ -/********************************************************************************/ -/********************* Cert Search / Add / Remove **************************/ -/********************************************************************************/ -/********************************************************************************/ - - -AuthSSLimpl::AuthSSLimpl() : - p3Config(), sslctx(nullptr), mOwnCert(nullptr), sslMtx("AuthSSL"), - mOwnPrivateKey(nullptr), mOwnPublicKey(nullptr), init(0) {} - -AuthSSLimpl::~AuthSSLimpl() -{ - RS_STACK_MUTEX(sslMtx); - - SSL_CTX_free(sslctx); - X509_free(mOwnCert); - - EVP_PKEY_free(mOwnPrivateKey); - EVP_PKEY_free(mOwnPublicKey); - - for(auto pcert: mCerts) - X509_free(pcert.second); -} - -bool AuthSSLimpl::active() { return init; } - -int AuthSSLimpl::InitAuth( - const char* cert_file, const char* priv_key_file, const char* passwd, - std::string locationName ) -{ - /* single call here si don't need to invoke mutex yet */ - static int initLib = 0; - if (!initLib) - { - initLib = 1; - - if (!tls_init()) { - return 0; - } - - SSL_load_error_strings(); - SSL_library_init(); - } - - - if (init == 1) - { - std::cerr << "AuthSSLimpl::InitAuth already initialized." << std::endl; - return 1; - } - - if ((cert_file == NULL) || - (priv_key_file == NULL) || - (passwd == NULL)) - { - //fprintf(stderr, "sslroot::initssl() missing parameters!\n"); - return 0; - } - - - // actions_to_seed_PRNG(); - RAND_seed(passwd, strlen(passwd)); - - std::cerr << "SSL Library Init!" << std::endl; - - // setup connection method - sslctx = SSL_CTX_new(SSLv23_method()); - SSL_CTX_set_options(sslctx,SSL_OP_NO_SSLv3) ; - - //SSL_OP_SINGLE_DH_USE CVE-2016-0701 - //https://www.openssl.org/docs/manmaster/ssl/SSL_CTX_set_options.html - //If "strong" primes were used, it is not strictly necessary to generate a new DH key during each handshake but it is also recommended. SSL_OP_SINGLE_DH_USE should therefore be enabled whenever temporary/ephemeral DH parameters are used. - //SSL_CTX_set_options() adds the options set via bitmask in options to ctx. Options already set before are not cleared! - SSL_CTX_set_options(sslctx,SSL_OP_SINGLE_DH_USE) ; - - - // Setup cipher lists: - // - // std::string cipherString = "HIGH:!DSS:!aNULL:!3DES"; - // std::string cipherString = "DEFAULT"; - // - // The current cipher list asks in priority for EDH which provides PFS. However EDH needs proper - // parameters to be set on the server side, so if we're a client for a RS instance that has no DH params, - // the connection will be refused. So we happend the HIGH cipher suite just after. In oder to force - // PFS, at the risk of not always connecting, one should use: - // - // std::string cipherString = "kEDH:HIGH:!DSS:!aNULL:!3DES"; - // - // The following safe primes are 2048/4096 bits long. Should be enough. - // - // std::string dh_prime_2048_dec = "30651576830996935311378276950670996791883170963804289256203421500259588715033040934547350194073369837229137842804826417332761673984632102152477971341551955103053338169949165519208562998954887445690136488713010579430413255432398961330773637820158790237012997356731669148258317860643591694814197514454546928317578771868379525705082166818553884557266645700906836702542808787791878865135741211056957383668479369231868698451684633965462539374994559481908068730787128654626819903401038534403722014687647173327537458614224702967073490136394698912372792187651228785689025073104374674728645661275001416541267543884923191810923"; - // - //Not used (should be here: /libretroshare/src/gxstunnel/p3gxstunnel.cc:1131 - //std::string dh_prime_2048_hex = "B3B86A844550486C7EA459FA468D3A8EFD71139593FE1C658BBEFA9B2FC0AD2628242C2CDC2F91F5B220ED29AAC271192A7374DFA28CDDCA70252F342D0821273940344A7A6A3CB70C7897A39864309F6CAC5C7EA18020EF882693CA2C12BB211B7BA8367D5A7C7252A5B5E840C9E8F081469EBA0B98BCC3F593A4D9C4D5DF539362084F1B9581316C1F80FDAD452FD56DBC6B8ED0775F596F7BB22A3FE2B4753764221528D33DB4140DE58083DB660E3E105123FC963BFF108AC3A268B7380FFA72005A1515C371287C5706FFA6062C9AC73A9B1A6AC842C2764CDACFC85556607E86611FDF486C222E4896CDF6908F239E177ACC641FCBFF72A758D1C10CBB" ; - - std::string dh_prime_4096_hex = "A6F5777292D9E6BB95559C9124B9119E6771F11F2048C8FE74F4E8140494520972A087EF1D60B73894F1C5D509DD15D96CF379E9DDD46CE51B748085BACB440D915565782C73AF3A9580CE788441D1DA4D114E3D302CAB45A061ABCFC1F7E9200AE019CB923B77E096FA9377454A16FFE91D86535FF23E075B3E714F785CD7606E9CBD9D06F01CAFA2271883D649F13ABE170D714F6B6EC064C5BF35C4F4BDA5EF5ED5E70D5DC78F1AC1CDC04EEDAE8ADD65C4A9E27368E0B2C8595DD7626D763BFFB15364B3CCA9FCE814B9226B35FE652F4B041F0FF6694D6A482B0EF48CA41163D083AD2DE7B7A068BB05C0453E9D008551C7F67993A3EF2C4874F0244F78C4E0997BD31AB3BD88446916B499B2513DD5BA002063BD38D2CE55D29D071399D5CEE99458AF6FDC104A61CA3FACDAC803CBDE62B4C0EAC946D0E12F05CE9E94497110D64E611D957423B8AA412D84EC83E6E70E0977A31D6EE056D0527D4667D7242A77C9B679D191562E4026DA9C35FF85666296D872ED548E0FFE1A677FCC373C1F490CAB4F53DFD8735C0F1DF02FEAD824A217FDF4E3404D38A5BBC719C6622630FCD34F6F1968AF1B66A4AB1A9FCF653DA96EB3A42AF6FCFEA0547B8F314A527C519949007D7FA1726FF3D33EC46393B0207AA029E5EA574BDAC94D78894B22A2E3303E65A3F820DF57DB44951DE4E973C016C57F7A242D0BC53BC563AF" ; - - std::string cipherString = "kEDH+HIGH:!DSS:!aNULL:!3DES:!EXP"; - - SSL_CTX_set_cipher_list(sslctx, cipherString.c_str()); - - DH* dh = DH_new(); - int codes = 0; - bool pfs_enabled = true ; - - if (dh) - { -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - BN_hex2bn(&dh->p,dh_prime_4096_hex.c_str()) ; - BN_hex2bn(&dh->g,"5") ; -#else - BIGNUM *pp=NULL,*gg=NULL ; - - BN_hex2bn(&pp,dh_prime_4096_hex.c_str()) ; - BN_hex2bn(&gg,"5"); - - DH_set0_pqg(dh,pp,NULL,gg) ; -#endif - - std::cout.flush() ; - -#ifndef RS_DISABLE_DIFFIE_HELLMAN_INIT_CHECK - if(DH_check(dh, &codes) && codes == 0) - SSL_CTX_set_tmp_dh(sslctx, dh); - else - pfs_enabled = false; -#else // ndef RS_DISABLE_DIFFIE_HELLMAN_INIT_CHECK - /* DH_check(...) is not strictly necessary and on Android devices it - * takes at least one minute which is untolerable there */ - SSL_CTX_set_tmp_dh(sslctx, dh); -#endif // ndef RS_DISABLE_DIFFIE_HELLMAN_INIT_CHECK - } - else - pfs_enabled = false ; - - // certificates (Set Local Server Certificate). - FILE *ownfp = RsDirUtil::rs_fopen(cert_file, "r"); - if (ownfp == NULL) - { - std::cerr << "Couldn't open Own Certificate!" << std::endl; - return -1; - } - - // get xPGP certificate. - X509 *x509 = PEM_read_X509(ownfp, NULL, NULL, NULL); - - fclose(ownfp); - - if (x509 == NULL) - { - std::cerr << "AuthSSLimpl::InitAuth() PEM_read_X509() Failed"; - std::cerr << std::endl; - return -1; - } - - int result = SSL_CTX_use_certificate(sslctx, x509); - -#if OPENSSL_VERSION_NUMBER >= 0x10101000L - if(result != 1) - { - // In debian Buster, openssl security level is set to 2 which preclude the use of SHA1, originally used to sign RS certificates. - // As a consequence, on these systems, locations created with RS previously to Jan.2020 will not start unless we revert the - // security level to a value of 1. - - int save_sec = SSL_CTX_get_security_level(sslctx); - SSL_CTX_set_security_level(sslctx,1); - result = SSL_CTX_use_certificate(sslctx, x509); - - if(result == 1) - { - std::cerr << std::endl; - std::cerr << " Your Retroshare certificate uses low security settings that are incompatible " << std::endl; - std::cerr << "(WW) with current security level " << save_sec << " of the OpenSSL library. Retroshare will still start " << std::endl; - std::cerr << " (with security level set to 1), but you should probably create a new location." << std::endl; - std::cerr << std::endl; - } - } -#endif - - if(result != 1) - { - std::cerr << "(EE) Cannot use your Retroshare certificate. Some error occured in SSL_CTX_use_certificate()" << std::endl; - return -1; - } - - mOwnPublicKey = X509_get_pubkey(x509); - - // get private key - FILE *pkfp = RsDirUtil::rs_fopen(priv_key_file, "rb"); - if (pkfp == NULL) - { - std::cerr << "Couldn't Open PrivKey File!" << std::endl; - CloseAuth(); - return -1; - } - - mOwnPrivateKey = PEM_read_PrivateKey(pkfp, NULL, NULL, (void *) passwd); - fclose(pkfp); - - if (mOwnPrivateKey == NULL) - { - std::cerr << "AuthSSLimpl::InitAuth() PEM_read_PrivateKey() Failed"; - std::cerr << std::endl; - return -1; - } - SSL_CTX_use_PrivateKey(sslctx, mOwnPrivateKey); - - if (1 != SSL_CTX_check_private_key(sslctx)) - { - std::cerr << "Issues With Private Key! - Doesn't match your Cert" << std::endl; - std::cerr << "Check your input key/certificate:" << std::endl; - std::cerr << priv_key_file << " & " << cert_file; - std::cerr << std::endl; - CloseAuth(); - return -1; - } - - RsPeerId mownidstr ; - - if (!getX509id(x509, mownidstr)) - { - std::cerr << "AuthSSLimpl::InitAuth() getX509id() Failed"; - std::cerr << std::endl; - - /* bad certificate */ - CloseAuth(); - return -1; - } - mOwnId = mownidstr ; - - assert(!mOwnId.isNull()) ; - - /* Check that Certificate is Ok ( virtual function ) - * for gpg/pgp or CA verification - */ - - if (!validateOwnCertificate(x509, mOwnPrivateKey)) - { - std::cerr << "AuthSSLimpl::InitAuth() validateOwnCertificate() Failed"; - std::cerr << std::endl; - - /* bad certificate */ - CloseAuth(); - exit(1); - return -1; - } - - - // enable verification of certificates (PEER) - // and install verify callback. - SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER | - SSL_VERIFY_FAIL_IF_NO_PEER_CERT, - verify_x509_callback); - - std::cerr << "SSL Verification Set" << std::endl; - - mOwnCert = x509; - - std::cerr << "Inited SSL context: " << std::endl; - std::cerr << " Certificate: " << mOwnId << std::endl; - std::cerr << " cipher list: " << cipherString << std::endl; - std::cerr << " PFS enabled: " << (pfs_enabled?"YES":"NO") ; - if(codes > 0) - { - std::cerr << " (reason: " ; - if(codes & DH_CHECK_P_NOT_PRIME ) std::cerr << "Not a prime number, " ; - if(codes & DH_CHECK_P_NOT_SAFE_PRIME) std::cerr << "Not a safe prime number, " ; - if(codes & DH_UNABLE_TO_CHECK_GENERATOR) std::cerr << "unable to check generator, " ; - if(codes & DH_NOT_SUITABLE_GENERATOR) std::cerr << "not a suitable generator" ; - std::cerr << ")" << std::endl; - } - else - std::cerr << std::endl; - - mOwnLocationName = locationName; - - init = 1; - return 1; -} - -/* Dummy function to be overloaded by real implementation */ -bool AuthSSLimpl::validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) -{ - (void) pkey; /* remove unused parameter warning */ - - uint32_t diagnostic ; - - /* standard authentication */ - if (!AuthX509WithGPG(x509,true,diagnostic)) - { - std::cerr << "Validate Own certificate ERROR: diagnostic = " << diagnostic << std::endl; - return false; - } - return true; -} - -bool AuthSSLimpl::CloseAuth() -{ - tls_cleanup(); - -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::CloseAuth()"; - std::cerr << std::endl; -#endif - SSL_CTX_free(sslctx); - - // clean up private key.... - // remove certificates etc -> opposite of initssl. - init = 0; - return 1; -} - -/* Context handling */ -SSL_CTX *AuthSSLimpl::getCTX() -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::getCTX()"; - std::cerr << std::endl; -#endif - return sslctx; -} - -const RsPeerId& AuthSSLimpl::OwnId() -{ -#ifdef AUTHSSL_DEBUG -// std::cerr << "AuthSSLimpl::OwnId()" << std::endl; -#endif - return mOwnId; -} - -std::string AuthSSLimpl::getOwnLocation() -{ return mOwnLocationName; } - -std::string AuthSSLimpl::SaveOwnCertificateToString() -{ return saveX509ToPEM(mOwnCert); } - -/********************************************************************************/ -/********************************************************************************/ -/********************* Cert Search / Add / Remove **************************/ -/********************************************************************************/ -/********************************************************************************/ - -bool AuthSSLimpl::SignData(std::string input, std::string &sign) -{ - return SignData(input.c_str(), input.length(), sign); -} - -bool AuthSSLimpl::SignData(const void *data, const uint32_t len, std::string &sign) -{ - - RsStackMutex stack(sslMtx); /***** STACK LOCK MUTEX *****/ - - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - unsigned int signlen = EVP_PKEY_size(mOwnPrivateKey); - unsigned char signature[signlen] ; - memset(signature,0,signlen) ; - - if (0 == EVP_SignInit(mdctx, EVP_sha1())) - { - std::cerr << "EVP_SignInit Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - if (0 == EVP_SignUpdate(mdctx, data, len)) - { - std::cerr << "EVP_SignUpdate Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - if (0 == EVP_SignFinal(mdctx, signature, &signlen, mOwnPrivateKey)) - { - std::cerr << "EVP_SignFinal Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - EVP_MD_CTX_destroy(mdctx); - - sign.clear(); - for(uint32_t i = 0; i < signlen; i++) - { - rs_sprintf_append(sign, "%02x", (uint32_t) (signature[i])); - } - - return true; -} - -bool AuthSSLimpl::SignDataBin(std::string input, unsigned char *sign, unsigned int *signlen) -{ - return SignDataBin(input.c_str(), input.length(), sign, signlen); -} - -bool AuthSSLimpl::SignDataBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int *signlen) -{ - RsStackMutex stack(sslMtx); /***** STACK LOCK MUTEX *****/ - return SSL_SignDataBin(data, len, sign, signlen, mOwnPrivateKey); -} - - -bool AuthSSLimpl::VerifySignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen, const RsPeerId& sslId) -{ - /* find certificate. - * if we don't have - fail. - */ - - RsStackMutex stack(sslMtx); /***** STACK LOCK MUTEX *****/ - - /* find the peer */ - X509* peercert; - if (sslId == mOwnId) peercert = mOwnCert; - else if (!locked_FindCert(sslId, &peercert)) - { - std::cerr << "VerifySignBin() no peer" << std::endl; - return false; - } - - return SSL_VerifySignBin(data, len, sign, signlen, peercert); -} - -bool AuthSSLimpl::VerifyOwnSignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen) -{ return SSL_VerifySignBin(data, len, sign, signlen, mOwnCert); } - - -/********************************************************************************/ -/********************************************************************************/ -/********************* Sign and Auth with GPG **************************/ -/********************************************************************************/ -/********************************************************************************/ - -/* Note these functions don't need Mutexes - - * only using GPG functions - which lock themselves - */ - -X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/) -{ - /* Transform the X509_REQ into a suitable format to - * generate DIGEST hash. (for SSL to do grunt work) - */ - -#define SERIAL_RAND_BITS 64 - - //const EVP_MD *digest = EVP_sha1(); - EVP_PKEY *tmppkey; - X509 *x509 = X509_new(); - if (x509 == NULL) - { - std::cerr << "AuthSSLimpl::SignX509Req() FAIL" << std::endl; - return NULL; - } - - //long version = 0x00; - unsigned long chtype = MBSTRING_UTF8; - X509_NAME *issuer_name = X509_NAME_new(); - X509_NAME_add_entry_by_txt(issuer_name, "CN", chtype, - (unsigned char *) AuthGPG::getAuthGPG()->getGPGOwnId().toStdString().c_str(), -1, -1, 0); -/**** - X509_NAME_add_entry_by_NID(issuer_name, 48, 0, - (unsigned char *) "email@email.com", -1, -1, 0); - X509_NAME_add_entry_by_txt(issuer_name, "O", chtype, - (unsigned char *) "org", -1, -1, 0); - X509_NAME_add_entry_by_txt(x509_name, "L", chtype, - (unsigned char *) "loc", -1, -1, 0); -****/ - - std::cerr << "AuthSSLimpl::SignX509Req() Issuer name: " << AuthGPG::getAuthGPG()->getGPGOwnId().toStdString() << std::endl; - -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_002 - static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_07_0001 ; -#else -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_001 - static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_06_0001 ; -#else - static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_06_0000 ; -#endif -#endif - - BIGNUM *btmp = BN_new(); - BN_set_word(btmp,CERTIFICATE_SERIAL_NUMBER) ; - -#ifdef OLD_CODE - if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) - { - std::cerr << "AuthSSLimpl::SignX509Req() rand FAIL" << std::endl; - return NULL; - } -#endif - ASN1_INTEGER *serial = ASN1_INTEGER_new(); - - if (!BN_to_ASN1_INTEGER(btmp, serial)) - { - std::cerr << "AuthSSLimpl::SignX509Req() asn1 FAIL" << std::endl; - return NULL; - } - BN_free(btmp); - - if (!X509_set_serialNumber(x509, serial)) - { - std::cerr << "AuthSSLimpl::SignX509Req() serial FAIL" << std::endl; - return NULL; - } - ASN1_INTEGER_free(serial); - - /* Generate SUITABLE issuer name. - * Must reference OpenPGP key, that is used to verify it - */ - - if (!X509_set_issuer_name(x509, issuer_name)) - { - std::cerr << "AuthSSLimpl::SignX509Req() issue FAIL" << std::endl; - return NULL; - } - X509_NAME_free(issuer_name); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - // (does not leak the key creation date to the outside anymore. for more privacy) - ASN1_TIME_set(X509_get_notBefore(x509), 0); - ASN1_TIME_set(X509_get_notAfter(x509), 0); -#else - // NEW code, set validity time between 2010 and 2110 (remember to change it when, if OpenSSL check it by default. ;) ) - // (does not leak the key creation date to the outside anymore. for more privacy) - if (!ASN1_TIME_set_string(X509_getm_notBefore(x509), "20100101000000Z")) - { - RsErr() << __PRETTY_FUNCTION__ << " Set notBefore FAIL" << std::endl; - return NULL; - } - if (!ASN1_TIME_set_string(X509_getm_notAfter(x509), "21100101000000Z")) - { - RsErr() << __PRETTY_FUNCTION__ << " Set notAfter FAIL" << std::endl; - return NULL; - } -#endif - - if (!X509_set_subject_name(x509, X509_REQ_get_subject_name(req))) - { - std::cerr << "AuthSSLimpl::SignX509Req() sub FAIL" << std::endl; - return NULL; - } - - tmppkey = X509_REQ_get_pubkey(req); - if (!tmppkey || !X509_set_pubkey(x509,tmppkey)) - { - std::cerr << "AuthSSLimpl::SignX509Req() pub FAIL" << std::endl; - return NULL; - } - - std::cerr << "X509 Cert, prepared for signing" << std::endl; - - /*** NOW The Manual signing bit (HACKED FROM asn1/a_sign.c) ***/ - // - // The code has been copied in order to use the PGP signing instead of supplying the - // private EVP_KEY to ASN1_sign(), which would be another alternative. - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - int (*i2d)(X509_CINF*, unsigned char**) = i2d_X509_CINF; - X509_ALGOR *algor1 = x509->cert_info->signature; - X509_ALGOR *algor2 = x509->sig_alg; - ASN1_BIT_STRING *signature = x509->signature; - X509_CINF *data = x509->cert_info; -#else - const X509_ALGOR *algor1 = X509_get0_tbs_sigalg(x509) ; - const X509_ALGOR *algor2 = NULL ; - - const ASN1_BIT_STRING *tmp_signature = NULL ; - - X509_get0_signature(&tmp_signature,&algor2,x509); - - ASN1_BIT_STRING *signature = const_cast(tmp_signature); -#endif - //EVP_PKEY *pkey = NULL; -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_002 - const EVP_MD *type = EVP_sha256(); -#else - const EVP_MD *type = EVP_sha1(); -#endif - - EVP_MD_CTX *ctx = EVP_MD_CTX_create(); - int inl=0; - X509_ALGOR *a; - - /* FIX ALGORITHMS */ - - a = const_cast(algor1); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - ASN1_TYPE_free(a->parameter); - a->parameter=ASN1_TYPE_new(); - a->parameter->type=V_ASN1_NULL; - - ASN1_OBJECT_free(a->algorithm); - a->algorithm=OBJ_nid2obj(type->pkey_type); -#else - X509_ALGOR_set0(a,OBJ_nid2obj(EVP_MD_pkey_type(type)),V_ASN1_NULL,NULL); -#endif - - a = const_cast(algor2); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - ASN1_TYPE_free(a->parameter); - a->parameter=ASN1_TYPE_new(); - a->parameter->type=V_ASN1_NULL; - - ASN1_OBJECT_free(a->algorithm); - a->algorithm=OBJ_nid2obj(type->pkey_type); -#else - X509_ALGOR_set0(a,OBJ_nid2obj(EVP_MD_pkey_type(type)),V_ASN1_NULL,NULL); -#endif - - - std::cerr << "Algorithms Fixed" << std::endl; - - unsigned int sigoutl=2048; // hashoutl; //EVP_PKEY_size(pkey); - unsigned char *buf_sigout=(unsigned char *)OPENSSL_malloc((unsigned int)sigoutl); - - /* input buffer */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - inl=i2d(data,NULL); - unsigned char *buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl); - - if(buf_in == NULL) - { - sigoutl=0; - fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n"); - return NULL ; - } - unsigned char *p=buf_in; // This because i2d modifies the pointer after writing to it. - i2d(data,&p); -#else - unsigned char *buf_in=NULL; - inl=i2d_re_X509_tbs(x509,&buf_in) ; // this does the i2d over x509->cert_info -#endif - -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 - if((buf_in == NULL) || (buf_sigout == NULL)) - { - sigoutl=0; - fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n"); - goto err; - } - std::cerr << "Buffers Allocated" << std::endl; - - /* NOW Sign via GPG Functions */ - if (!AuthGPG::getAuthGPG()->SignDataBin(buf_in, inl, buf_sigout, (unsigned int *) &sigoutl,"AuthSSLimpl::SignX509ReqWithGPG()")) - { - sigoutl = 0; - goto err; - } -#else - unsigned int hashoutl=EVP_MD_size(type); - unsigned char *buf_hashout=(unsigned char *)OPENSSL_malloc((unsigned int)hashoutl); - - if((buf_hashout == NULL) || (buf_sigout == NULL)) - { - hashoutl=0; - sigoutl=0; - fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n"); - goto err; - } - std::cerr << "Buffers Allocated" << std::endl; - - /* data in buf_in, ready to be hashed */ - EVP_DigestInit_ex(ctx,type, NULL); - EVP_DigestUpdate(ctx,(unsigned char *)buf_in,inl); - if (!EVP_DigestFinal(ctx,(unsigned char *)buf_hashout, (unsigned int *)&hashoutl)) - { - hashoutl=0; - fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB)\n"); - goto err; - } - - std::cerr << "Digest Applied: len: " << hashoutl << std::endl; - - /* NOW Sign via GPG Functions */ - if (!AuthGPG::getAuthGPG()->SignDataBin(buf_hashout, hashoutl, buf_sigout, (unsigned int *) &sigoutl,"AuthSSLimpl::SignX509ReqWithGPG()")) - { - sigoutl = 0; - goto err; - } -#endif - - std::cerr << "Buffer Sizes: in: " << inl; -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 - std::cerr << " HashOut: " << hashoutl; -#endif - std::cerr << " SigOut: " << sigoutl; - std::cerr << std::endl; - - //passphrase = "NULL"; - - std::cerr << "Signature done: len:" << sigoutl << std::endl; - - /* ADD Signature back into Cert... Signed!. */ - - if (signature->data != NULL) OPENSSL_free(signature->data); - signature->data=buf_sigout; - buf_sigout=NULL; - signature->length=sigoutl; - /* In the interests of compatibility, I'll make sure that - * the bit string has a 'not-used bits' value of 0 - */ - signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); - signature->flags|=ASN1_STRING_FLAG_BITS_LEFT; - - std::cerr << "Certificate Complete" << std::endl; - - EVP_MD_CTX_destroy(ctx) ; - - // debug - // { - // int pkey_nid = OBJ_obj2nid(x509->sig_alg->algorithm); - // const char* sslbuf = OBJ_nid2ln(pkey_nid); - // std::cerr << "Signature hash algorithm: " << sslbuf << std::endl; - // } - - return x509; - - /* XXX CLEANUP */ - err: - /* cleanup */ - if(buf_in != NULL) - OPENSSL_free(buf_in) ; -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 - if(buf_hashout != NULL) - OPENSSL_free(buf_hashout) ; -#endif - if(buf_sigout != NULL) - OPENSSL_free(buf_sigout) ; - std::cerr << "GPGAuthMgr::SignX509Req() err: FAIL" << std::endl; - - return NULL; -} - - -bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,bool verbose, uint32_t& diagnostic) -{ - RsPgpId issuer = RsX509Cert::getCertIssuer(*x509); - RsPeerDetails pd; - if (!AuthGPG::getAuthGPG()->getGPGDetails(issuer, pd)) - { - RsInfo() << __PRETTY_FUNCTION__ << " X509 NOT authenticated : " - << "AuthGPG::getAuthGPG()->getGPGDetails(" << issuer - << ",...) returned false." << std::endl; - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_ISSUER_UNKNOWN; - return false; - } - else - Dbg3() << __PRETTY_FUNCTION__ << " issuer: " << issuer << " found" - << std::endl; - - /* verify GPG signature */ - /*** NOW The Manual signing bit (HACKED FROM asn1/a_sign.c) ***/ - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - int (*i2d)(X509_CINF*, unsigned char**) = i2d_X509_CINF; - ASN1_BIT_STRING* signature = x509->signature; - X509_CINF* data = x509->cert_info; -#else - const ASN1_BIT_STRING* signature = nullptr; - const X509_ALGOR* algor2 = nullptr; - X509_get0_signature(&signature,&algor2,x509); -#endif - - uint32_t certificate_version = getX509RetroshareCertificateVersion(x509); - - EVP_MD_CTX* ctx = EVP_MD_CTX_create(); - int inl = 0; - - const unsigned char* signed_data = nullptr; - uint32_t signed_data_length = 0; - - /* input buffer */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - inl = i2d(data, nullptr); - unsigned char* buf_in = static_cast( - OPENSSL_malloc(static_cast(inl)) ); - unsigned char* p = nullptr; -#else - unsigned char* buf_in = nullptr; - inl=i2d_re_X509_tbs(x509,&buf_in) ; // this does the i2d over x509->cert_info -#endif - - if(buf_in == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ - << " ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)" << std::endl; - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR ; - return false; - } - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - p = buf_in; - i2d(data,&p); -#endif - - { // this scope is to avoid cross-initialization jumps to err. - - const Sha1CheckSum sha1 = RsDirUtil::sha1sum( - buf_in, static_cast(inl) ); - - if(certificate_version < RS_CERTIFICATE_VERSION_NUMBER_07_0001) - { - /* If the certificate belongs to 0.6 version, we hash it here, and - * then re-hash the hash it in the PGP signature */ - signed_data = sha1.toByteArray(); - signed_data_length = sha1.SIZE_IN_BYTES; - } - else - { - signed_data = buf_in ; - signed_data_length = static_cast(inl); - } - - /* NOW check sign via GPG Functions */ - - Dbg2() << __PRETTY_FUNCTION__ - << " verifying the PGP Key signature with finger print: " - << pd.fpr << std::endl; - - /* Take a early look at signature parameters. In particular we dont - * accept signatures with unsecure hash algorithms */ - - PGPSignatureInfo signature_info ; - PGPKeyManagement::parseSignature( - signature->data, static_cast(signature->length), - signature_info ); - - if(signature_info.signature_version != PGP_PACKET_TAG_SIGNATURE_VERSION_V4) - { - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE_VERSION; - goto err; - } - - std::string sigtypestring; - - switch(signature_info.signature_type) - { - case PGP_PACKET_TAG_SIGNATURE_TYPE_BINARY_DOCUMENT: break; - case PGP_PACKET_TAG_SIGNATURE_TYPE_STANDALONE_SIG: /*fallthrough*/ - case PGP_PACKET_TAG_SIGNATURE_TYPE_CANONICAL_TEXT: /*fallthrough*/ - case PGP_PACKET_TAG_SIGNATURE_TYPE_UNKNOWN: /*fallthrough*/ - default: - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE_TYPE; - goto err; - } - - switch(signature_info.public_key_algorithm) - { - case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_ES: /*fallthrough*/ - case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_S: - sigtypestring = "RSA"; - break ; - case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_DSA: - sigtypestring = "DSA"; - break ; - case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_E: /*fallthrough*/ - case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_UNKNOWN: /*fallthrough*/ - default: - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_HASH_ALGORITHM_NOT_ACCEPTED ; - goto err ; - } - - switch(signature_info.hash_algorithm) - { - case PGP_PACKET_TAG_HASH_ALGORITHM_SHA1: - sigtypestring += "+SHA1"; - break; - case PGP_PACKET_TAG_HASH_ALGORITHM_SHA256: - sigtypestring += "+SHA256"; - break; - case PGP_PACKET_TAG_HASH_ALGORITHM_SHA512: - sigtypestring += "+SHA512"; - break; - // We dont accept signatures with unknown or weak hash algorithms. - case PGP_PACKET_TAG_HASH_ALGORITHM_MD5: /*fallthrough*/ - case PGP_PACKET_TAG_HASH_ALGORITHM_UNKNOWN: /*fallthrough*/ - default: - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_HASH_ALGORITHM_NOT_ACCEPTED; - goto err; - } - - // passed, verify the signature itself - - if (!AuthGPG::getAuthGPG()->VerifySignBin( - signed_data, signed_data_length, signature->data, - static_cast(signature->length), pd.fpr )) - { - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE; - goto err; - } - - if(verbose) - RsInfo() << " Verified: " << sigtypestring - << " signature of certificate sslId: " - << RsX509Cert::getCertSslId(*x509) - << ", Version " << std::hex << certificate_version << std::dec - << " using PGP key " << pd.fpr << " " << pd.name << std::endl; - } - - EVP_MD_CTX_destroy(ctx); - - OPENSSL_free(buf_in); - - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_OK; - - return true; - -err: // TODO: this label is very short and might collide every easly - RsInfo() << __PRETTY_FUNCTION__ << " X509 PGP authentication failed with " - << "diagnostic: " << diagnostic << std::endl; - - if(buf_in) OPENSSL_free(buf_in); - - return false; -} - -/********************************************************************************/ -/********************************************************************************/ -/**************************** encrypt / decrypt fns ****************************/ -/********************************************************************************/ -/********************************************************************************/ - -static int verify_x509_callback(int preverify_ok, X509_STORE_CTX *ctx) -{ return AuthSSL::instance().VerifyX509Callback(preverify_ok, ctx); } - -int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx) -{ - /* According to OpenSSL documentation must return 0 if verification failed - * and 1 if succeded (aka can continue connection). - * About preverify_ok OpenSSL documentation doesn't tell which value is - * passed to the first callback in the authentication chain, it just says - * that the result of previous step is passed down, so I have tested it - * and we get passed 0 always so in our case as there is no other - * verifications step vefore we ignore it completely */ - - constexpr int verificationFailed = 0; - constexpr int verificationSuccess = 1; - - using Evt_t = RsAuthSslConnectionAutenticationEvent; - std::unique_ptr ev = std::unique_ptr(new Evt_t); - - X509* x509Cert = X509_STORE_CTX_get_current_cert(ctx); - if(!x509Cert) - { - std::string errMsg = "Cannot get certificate! OpenSSL error: " + - std::to_string(X509_STORE_CTX_get_error(ctx)) + " depth: " + - std::to_string(X509_STORE_CTX_get_error_depth(ctx)); - - RsErr() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; - - return verificationFailed; - } - - RsPeerId sslId = RsX509Cert::getCertSslId(*x509Cert); - std::string sslCn = RsX509Cert::getCertIssuerString(*x509Cert); - - RsPgpId pgpId(sslCn); - - if(sslCn.length() == RsPgpFingerprint::SIZE_IN_BYTES*2) - { - RsPgpFingerprint pgpFpr(sslCn); // we also accept fingerprint format, so that in the future we can switch to fingerprints without backward compatibility issues - - if(!pgpFpr.isNull()) - pgpId = PGPHandler::pgpIdFromFingerprint(pgpFpr); // in the future, we drop PGP ids and keep the fingerprint all along - } - - if(sslId.isNull()) - { - std::string errMsg = "x509Cert has invalid sslId!"; - - RsInfo() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; - - if(rsEvents) - { - ev->mSslCn = sslCn; - ev->mSslId = sslId; - ev->mPgpId = pgpId; - ev->mErrorMsg = errMsg; - ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO; - - rsEvents->postEvent(std::move(ev)); - } - - return verificationFailed; - } - - if(pgpId.isNull()) - { - std::string errMsg = "x509Cert has invalid pgpId! sslCn >>>" + sslCn + - "<<<"; - - RsInfo() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; - - if(rsEvents) - { - ev->mSslId = sslId; - ev->mSslCn = sslCn; - ev->mErrorMsg = errMsg; - ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO; - - rsEvents->postEvent(std::move(ev)); - } - - return verificationFailed; - } - - bool isSslOnlyFriend = false; - - // For SSL only friends (ones added through short invites) we check that the fingerprint - // in the key (det.gpg_id) matches the one of the handshake. - { - RsPeerDetails det; - - if(rsPeers->getPeerDetails(sslId,det)) - isSslOnlyFriend = det.skip_pgp_signature_validation; - - if(det.skip_pgp_signature_validation && det.gpg_id != pgpId)// in the future, we should compare fingerprints instead - { - std::string errorMsg = "Peer " + sslId.toStdString() + " trying to connect with issuer ID " + pgpId.toStdString() - + " whereas key ID " + det.gpg_id.toStdString() + " was expected! Refusing connection." ; - - RsErr() << __PRETTY_FUNCTION__ << errorMsg << std::endl; - - if(rsEvents) - { - ev->mSslId = sslId; - ev->mSslCn = sslCn; - ev->mPgpId = pgpId; - ev->mErrorMsg = errorMsg; - ev->mErrorCode = RsAuthSslError::MISMATCHED_PGP_ID; - rsEvents->postEvent(std::move(ev)); - } - - return verificationFailed; - } - } - - uint32_t auth_diagnostic; - if(!isSslOnlyFriend && !AuthX509WithGPG(x509Cert,true, auth_diagnostic)) - { - std::string errMsg = "Certificate was rejected because PGP " - "signature verification failed with diagnostic: " - + std::to_string(auth_diagnostic) + " certName: " + - RsX509Cert::getCertName(*x509Cert) + " sslId: " + - RsX509Cert::getCertSslId(*x509Cert).toStdString() + - " issuerString: " + RsX509Cert::getCertIssuerString(*x509Cert); - - RsInfo() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; - - if(rsEvents) - { - ev->mSslId = sslId; - ev->mSslCn = sslCn; - ev->mPgpId = pgpId; - - switch(auth_diagnostic) - { - case RS_SSL_HANDSHAKE_DIAGNOSTIC_ISSUER_UNKNOWN: - ev->mErrorCode = RsAuthSslError::NOT_A_FRIEND; - break; - case RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE: - ev->mErrorCode = RsAuthSslError::PGP_SIGNATURE_VALIDATION_FAILED; - break; - default: - ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO; - break; - } - - ev->mErrorMsg = errMsg; - rsEvents->postEvent(std::move(ev)); - } - - if (auth_diagnostic == RS_SSL_HANDSHAKE_DIAGNOSTIC_ISSUER_UNKNOWN) - RsServer::notify()->AddPopupMessage(RS_POPUP_CONNECT_ATTEMPT, pgpId.toStdString(), sslCn, sslId.toStdString()); /* notify Connect Attempt */ - - return verificationFailed; - } -#ifdef AUTHSSL_DEBUG - std::cerr << "******* VerifyX509Callback cert: " << std::hex << ctx->cert <getGPGOwnId() && !AuthGPG::getAuthGPG()->isGPGAccepted(pgpId) ) - { - std::string errMsg = "Connection attempt signed by PGP key id: " + - pgpId.toStdString() + " not accepted because it is not" - " a friend."; - - Dbg1() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; - - if(rsEvents) - { - ev->mSslId = sslId; - ev->mSslCn = sslCn; - ev->mPgpId = pgpId; - ev->mErrorMsg = errMsg; - ev->mErrorCode = RsAuthSslError::NOT_A_FRIEND; - rsEvents->postEvent(std::move(ev)); - } - - RsServer::notify()->AddPopupMessage(RS_POPUP_CONNECT_ATTEMPT, pgpId.toStdString(), sslCn, sslId.toStdString()); /* notify Connect Attempt */ - - return verificationFailed; - } - - LocalStoreCert(x509Cert); - - RsInfo() << __PRETTY_FUNCTION__ << " authentication successfull for " - << "sslId: " << sslId << " isSslOnlyFriend: " << isSslOnlyFriend - << std::endl; - - return verificationSuccess; -} - -bool AuthSSLimpl::parseX509DetailsFromFile( const std::string& certFilePath, RsPeerId& certId, RsPgpId& issuer, std::string& location ) -{ - FILE* tmpfp = RsDirUtil::rs_fopen(certFilePath.c_str(), "r"); - if(!tmpfp) - { - RsErr() << __PRETTY_FUNCTION__ << " Failed to open Certificate File: " - << certFilePath << std::endl; - return false; - } - - // get xPGP certificate. - X509* x509 = PEM_read_X509(tmpfp, nullptr, nullptr, nullptr); - fclose(tmpfp); - - if(!x509) - { - RsErr() << __PRETTY_FUNCTION__ << " PEM_read_X509 failed!" << std::endl; - return false; - } - - uint32_t diagnostic = 0; - - if(!AuthX509WithGPG(x509,false, diagnostic)) - { - RsErr() << __PRETTY_FUNCTION__ << " AuthX509WithGPG failed with " - << "diagnostic: " << diagnostic << std::endl; - - X509_free(x509); - return false; - } - - certId = RsX509Cert::getCertSslId(*x509); - issuer = RsX509Cert::getCertIssuer(*x509); - location = RsX509Cert::getCertLocation(*x509); - - X509_free(x509); - - if(certId.isNull() || issuer.isNull()) return false; - - return true; -} - - -/********************************************************************************/ -/********************************************************************************/ -/**************************** encrypt / decrypt fns ****************************/ -/********************************************************************************/ -/********************************************************************************/ - - -bool AuthSSLimpl::encrypt(void *&out, int &outlen, const void *in, int inlen, const RsPeerId& peerId) -{ - RS_STACK_MUTEX(sslMtx); - - /*const*/ EVP_PKEY* public_key = nullptr; - if (peerId == mOwnId) { public_key = mOwnPublicKey; } - else - { - auto it = mCerts.find(peerId); - - if (it == mCerts.end()) - { - RsErr() << __PRETTY_FUNCTION__ << " public key not found." << std::endl; - return false; - } - else public_key = const_cast( RsX509Cert::getPubKey(*it->second) ); - } - - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - int eklen, net_ekl; - unsigned char *ek; - unsigned char iv[EVP_MAX_IV_LENGTH]; - int out_currOffset = 0; - int out_offset = 0; - - int max_evp_key_size = EVP_PKEY_size(public_key); - ek = (unsigned char*)rs_malloc(max_evp_key_size); - - if(ek == NULL) - return false ; - - const EVP_CIPHER *cipher = EVP_aes_128_cbc(); - int cipher_block_size = EVP_CIPHER_block_size(cipher); - int size_net_ekl = sizeof(net_ekl); - - int max_outlen = inlen + cipher_block_size + EVP_MAX_IV_LENGTH + max_evp_key_size + size_net_ekl; - - // intialize context and send store encrypted cipher in ek - if(!EVP_SealInit(ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &public_key, 1)) { - free(ek); - return false; - } - - // now assign memory to out accounting for data, and cipher block size, key length, and key length val - out = (unsigned char*)rs_malloc(inlen + cipher_block_size + size_net_ekl + eklen + EVP_MAX_IV_LENGTH); - - if(out == NULL) - { - free(ek) ; - return false ; - } - net_ekl = htonl(eklen); - memcpy((unsigned char*)out + out_offset, &net_ekl, size_net_ekl); - out_offset += size_net_ekl; - - memcpy((unsigned char*)out + out_offset, ek, eklen); - out_offset += eklen; - - memcpy((unsigned char*)out + out_offset, iv, EVP_MAX_IV_LENGTH); - out_offset += EVP_MAX_IV_LENGTH; - - // now encrypt actual data - if(!EVP_SealUpdate(ctx, (unsigned char*) out + out_offset, &out_currOffset, (unsigned char*) in, inlen)) { - free(ek); - free(out); - out = NULL; - return false; - } - - // move along to partial block space - out_offset += out_currOffset; - - // add padding - if(!EVP_SealFinal(ctx, (unsigned char*) out + out_offset, &out_currOffset)) { - free(ek); - free(out) ; - out = NULL; - return false; - } - - // move to end - out_offset += out_currOffset; - - // make sure offset has not gone passed valid memory bounds - if(out_offset > max_outlen) return false; - - // free encrypted key data - free(ek); - - EVP_CIPHER_CTX_free(ctx); - - outlen = out_offset; - - #ifdef DISTRIB_DEBUG - std::cerr << "Authssl::encrypt() finished with outlen : " << outlen << std::endl; - #endif - - return true; -} - -bool AuthSSLimpl::decrypt(void *&out, int &outlen, const void *in, int inlen) -{ - RsStackMutex stack(sslMtx); /******* LOCKED ******/ - - - -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::decrypt() called with inlen : " << inlen << std::endl; -#endif - //TODO : use ssl to decrypt the binary input buffer -// out = malloc(inlen); -// memcpy(out, in, inlen); -// outlen = inlen; - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - int eklen = 0, net_ekl = 0; - unsigned char iv[EVP_MAX_IV_LENGTH]; - int ek_mkl = EVP_PKEY_size(mOwnPrivateKey); - unsigned char *ek = (unsigned char*)malloc(ek_mkl); - - if(ek == NULL) - { - std::cerr << "(EE) Cannot allocate memory for " << ek_mkl << " bytes in " << __PRETTY_FUNCTION__ << std::endl; - return false ; - } - - int in_offset = 0, out_currOffset = 0; - int size_net_ekl = sizeof(net_ekl); - - if(size_net_ekl > inlen) { - free(ek); - return false; - } - - memcpy(&net_ekl, (unsigned char*)in, size_net_ekl); - eklen = ntohl(net_ekl); - in_offset += size_net_ekl; - - if(eklen > (inlen-in_offset)) { - free(ek); - return false; - } - - memcpy(ek, (unsigned char*)in + in_offset, eklen); - in_offset += eklen; - - if(EVP_MAX_IV_LENGTH > (inlen-in_offset)) { - free(ek); - return false; - } - - memcpy(iv, (unsigned char*)in + in_offset, EVP_MAX_IV_LENGTH); - in_offset += EVP_MAX_IV_LENGTH; - - const EVP_CIPHER* cipher = EVP_aes_128_cbc(); - - if(0 == EVP_OpenInit(ctx, cipher, ek, eklen, iv, mOwnPrivateKey)) { - free(ek); - return false; - } - - out = (unsigned char*)rs_malloc(inlen - in_offset); - - if(out == NULL) - { - free(ek) ; - return false ; - } - if(!EVP_OpenUpdate(ctx, (unsigned char*) out, &out_currOffset, (unsigned char*)in + in_offset, inlen - in_offset)) { - free(ek); - free(out) ; - out = NULL; - return false; - } - - //in_offset += out_currOffset; - outlen += out_currOffset; - - if(!EVP_OpenFinal(ctx, (unsigned char*)out + out_currOffset, &out_currOffset)) { - free(ek); - free(out) ; - out = NULL; - return false; - } - - outlen += out_currOffset; - - if(ek != NULL) - free(ek); - - EVP_CIPHER_CTX_free(ctx); - -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::decrypt() finished with outlen : " << outlen << std::endl; -#endif - - return true; -} - -/* Locked search -> internal help function */ -bool AuthSSLimpl::locked_FindCert(const RsPeerId& id, X509** cert) -{ - std::map::iterator it; - - if (mCerts.end() != (it = mCerts.find(id))) - { - *cert = it->second; - return true; - } - return false; -} - - -/* Remove Certificate */ - -bool AuthSSLimpl::RemoveX509(RsPeerId id) -{ - std::map::iterator it; - - RsStackMutex stack(sslMtx); /******* LOCKED ******/ - - if (mCerts.end() != (it = mCerts.find(id))) - { - X509* cert = it->second; - X509_free(cert); - mCerts.erase(it); - return true; - } - return false; -} - - -bool AuthSSLimpl::LocalStoreCert(X509* x509) -{ - //store the certificate in the local cert list - RsPeerId peerId ; - if(!getX509id(x509, peerId)) - { - std::cerr << "AuthSSLimpl::LocalStoreCert() Cannot retrieve peer id from certificate." << std::endl; -#ifdef AUTHSSL_DEBUG -#endif - return false; - } - - if(peerId.isNull()) - { - std::cerr << "AuthSSLimpl::LocalStoreCert(): invalid peer id \"" << peerId << "\"" << std::endl; - return false ; - } - - - RsStackMutex stack(sslMtx); /******* LOCKED ******/ - - if (peerId == mOwnId) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::LocalStoreCert() not storing own certificate" << std::endl; -#endif - return false; - } - - /* do a search */ - std::map::iterator it; - - if (mCerts.end() != (it = mCerts.find(peerId))) - { - X509* cert = it->second; - - /* found something */ - /* check that they are exact */ - if (0 != X509_cmp(cert, x509)) - { - /* MAJOR ERROR */ - std::cerr << "ERROR : AuthSSLimpl::LocalStoreCert() got two ssl certificates with identical ids -> dropping second"; - std::cerr << std::endl; - return false; - } - /* otherwise - we have it already */ - return false; - } - -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::LocalStoreCert() storing certificate for " << peerId << std::endl; -#endif - mCerts[peerId] = X509_dup(x509); - - /* flag for saving config */ - IndicateConfigChanged(); - return true ; -} - - -/********************************************************************************/ -/********************************************************************************/ -/************************ Config Functions **********************************/ -/********************************************************************************/ -/********************************************************************************/ - - -RsSerialiser *AuthSSLimpl::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsGeneralConfigSerialiser()); - return rss ; -} - -bool AuthSSLimpl::saveList(bool& cleanup, std::list& lst) -{ - #ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::saveList() called" << std::endl ; - #endif - - RsStackMutex stack(sslMtx); /******* LOCKED ******/ - - cleanup = true ; - - // Now save config for network digging strategies - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - std::map::iterator mapIt; - for (mapIt = mCerts.begin(); mapIt != mCerts.end(); ++mapIt) { - if (mapIt->first == mOwnId) { - continue; - } - RsTlvKeyValue kv; - kv.key = mapIt->first.toStdString(); - #ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::saveList() called (mapIt->first) : " << (mapIt->first) << std::endl ; - #endif - kv.value = saveX509ToPEM(mapIt->second); - vitem->tlvkvs.pairs.push_back(kv) ; - } - lst.push_back(vitem); - - return true ; -} - -bool AuthSSLimpl::loadList(std::list& load) -{ - #ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::loadList() Item Count: " << load.size() << std::endl; - #endif - - /* load the list of accepted gpg keys */ - std::list::iterator it; - for(it = load.begin(); it != load.end(); ++it) { - RsConfigKeyValueSet *vitem = dynamic_cast(*it); - - if(vitem) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::loadList() General Variable Config Item:" << std::endl; - vitem->print(std::cerr, 10); - std::cerr << std::endl; -#endif - - std::list::iterator kit; - for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if (RsPeerId(kit->key) == mOwnId) { - continue; - } - - X509 *peer = loadX509FromPEM(kit->value); - /* authenticate it */ - uint32_t diagnos ; - if (peer && AuthX509WithGPG(peer,false,diagnos)) - LocalStoreCert(peer); - - X509_free(peer); - } - } - delete (*it); - } - load.clear() ; - return true; -} - -const EVP_PKEY*RsX509Cert::getPubKey(const X509& x509) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return x509.cert_info->key->pkey; -#else - return X509_get0_pubkey(&x509); -#endif -} diff --git a/libretroshare/src/pqi/authssl.h b/libretroshare/src/pqi/authssl.h deleted file mode 100644 index ddd5dc86d..000000000 --- a/libretroshare/src/pqi/authssl.h +++ /dev/null @@ -1,261 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: authssl.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - - -#include -#include - -#include -#include - -#include "util/rsthreads.h" -#include "pqi/pqi_base.h" -#include "pqi/pqinetwork.h" -#include "pqi/p3cfgmgr.h" -#include "util/rsmemory.h" -#include "retroshare/rsevents.h" - -/** - * Functions to interact elegantly with X509 certificates, using this functions - * you can avoid annoying #ifdef *SSL_VERSION_NUMBER all around the code. - * Function names should be self descriptive. - */ -namespace RsX509Cert -{ -std::string getCertName(const X509& x509); -std::string getCertLocation(const X509& x509); -std::string getCertOrg(const X509& x509); -RsPgpId getCertIssuer(const X509& x509); -std::string getCertIssuerString(const X509& x509); -RsPeerId getCertSslId(const X509& x509); -const EVP_PKEY* getPubKey(const X509& x509); -}; - -/** - * This is an implementation of SSL certificate authentication with PGP - * signatures, instead of centralized certification authority. - */ -class AuthSSL -{ -public: - static AuthSSL& instance(); - - RS_DEPRECATED_FOR(AuthSSL::instance()) - static AuthSSL* getAuthSSL(); - - /* Initialisation Functions (Unique) */ - virtual bool validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) = 0; - - virtual bool active() = 0; - virtual int InitAuth( - const char* srvr_cert, const char* priv_key, const char* passwd, - std::string locationName ) = 0; - virtual bool CloseAuth() = 0; - - /*********** Overloaded Functions from p3AuthMgr **********/ - - /* get Certificate Id */ - virtual const RsPeerId& OwnId() = 0; - virtual std::string getOwnLocation() = 0; - - /* Load/Save certificates */ - virtual std::string SaveOwnCertificateToString() = 0; - - /* Sign / Encrypt / Verify Data */ - virtual bool SignData(std::string input, std::string &sign) = 0; - virtual bool SignData( - const void* data, const uint32_t len, std::string& sign ) = 0; - - virtual bool SignDataBin(std::string, unsigned char*, unsigned int*) = 0; - virtual bool SignDataBin( - const void*, uint32_t, unsigned char*, unsigned int* ) = 0; - virtual bool VerifyOwnSignBin( - const void*, uint32_t, unsigned char*, unsigned int ) = 0; - virtual bool VerifySignBin( - const void* data, const uint32_t len, unsigned char* sign, - unsigned int signlen, const RsPeerId& sslId ) = 0; - - /// return false if failed - virtual bool encrypt( - void*& out, int& outlen, const void* in, int inlen, - const RsPeerId& peerId ) = 0; - /// return false if failed - virtual bool decrypt(void*& out, int& outlen, const void* in, int inlen) = 0; - - virtual X509* SignX509ReqWithGPG(X509_REQ* req, long days) = 0; - - /** - * @brief Verify PGP signature correcteness on given X509 certificate - * Beware this doesn't check if the PGP signer is friend or not, just if the - * signature is valid! - * @param[in] x509 pointer ti the X509 certificate to check - * @param[out] diagnostic one of RS_SSL_HANDSHAKE_DIAGNOSTIC_* diagnostic - * codes - * @param[in] verbose if true, prints the authentication result to screen. - * @return true if correctly signed, false otherwise - */ - virtual bool AuthX509WithGPG( - X509* x509, - bool verbose, - uint32_t& diagnostic = RS_DEFAULT_STORAGE_PARAM(uint32_t) - ) = 0; - - /** - * @brief Callback provided to OpenSSL to authenticate connections - * This is the ultimate place where connection attempts get accepted - * if authenticated or refused if not authenticated. - * Emits @see RsAuthSslConnectionAutenticationEvent. - * @param preverify_ok passed by OpenSSL ignored as this call is the first - * in the authentication callback chain - * @param ctx OpenSSL connection context - * @return 0 if authentication failed, 1 if success see OpenSSL - * documentation - */ - virtual int VerifyX509Callback(int preverify_ok, X509_STORE_CTX* ctx) = 0; - - /// SSL specific functions used in pqissl/pqissllistener - virtual SSL_CTX* getCTX() = 0; - - /** - * This function parse X509 certificate from the file and return some - * verified informations, like ID and signer - * @return false on error, true otherwise - */ - virtual bool parseX509DetailsFromFile( - const std::string& certFilePath, RsPeerId& certId, RsPgpId& issuer, - std::string& location ) = 0; - - virtual ~AuthSSL(); - -protected: - AuthSSL() {} - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; - - -class AuthSSLimpl : public AuthSSL, public p3Config -{ -public: - - /** Initialisation Functions (Unique) */ - AuthSSLimpl(); - virtual ~AuthSSLimpl(); - - bool validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) override; - - bool active() override; - int InitAuth( const char *srvr_cert, const char *priv_key, - const char *passwd, std::string locationName ) - override; - - bool CloseAuth() override; - - /*********** Overloaded Functions from p3AuthMgr **********/ - - const RsPeerId& OwnId() override; - virtual std::string getOwnLocation() override; - - /* Load/Save certificates */ - virtual std::string SaveOwnCertificateToString() override; - - /* Sign / Encrypt / Verify Data */ - bool SignData(std::string input, std::string &sign) override; - bool SignData( - const void *data, const uint32_t len, std::string &sign) override; - - bool SignDataBin(std::string, unsigned char*, unsigned int*) override; - virtual bool SignDataBin( - const void*, uint32_t, unsigned char*, unsigned int*) override; - bool VerifyOwnSignBin( - const void*, uint32_t, unsigned char*, unsigned int) override; - virtual bool VerifySignBin( - const void *data, const uint32_t len, unsigned char *sign, - unsigned int signlen, const RsPeerId& sslId) override; - - bool encrypt( - void*& out, int& outlen, const void* in, int inlen, - const RsPeerId& peerId ) override; - bool decrypt(void *&out, int &outlen, const void *in, int inlen) override; - - virtual X509* SignX509ReqWithGPG(X509_REQ *req, long days) override; - - /// @see AuthSSL - bool AuthX509WithGPG(X509 *x509, bool verbose, uint32_t& auth_diagnostic) override; - - /// @see AuthSSL - int VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx) override; - - /// @see AuthSSL - bool parseX509DetailsFromFile( - const std::string& certFilePath, RsPeerId& certId, - RsPgpId& issuer, std::string& location ) override; - - -/*****************************************************************/ -/*********************** p3config ******************************/ - /* Key Functions to be overloaded for Full Configuration */ - RsSerialiser* setupSerialiser() override; - bool saveList(bool &cleanup, std::list& ) override; - bool loadList(std::list& load) override; -/*****************************************************************/ - -public: - /* SSL specific functions used in pqissl/pqissllistener */ - SSL_CTX* getCTX() override; - -private: - - bool LocalStoreCert(X509* x509); - bool RemoveX509(const RsPeerId id); - - /*********** LOCKED Functions ******/ - bool locked_FindCert(const RsPeerId& id, X509** cert); - - /* Data */ - /* these variables are constants -> don't need to protect */ - SSL_CTX *sslctx; - RsPeerId mOwnId; - 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 */ - - EVP_PKEY* mOwnPrivateKey; - EVP_PKEY* mOwnPublicKey; - - int init; - std::map mCerts; - - RsPgpId _last_gpgid_to_connect; - std::string _last_sslcn_to_connect; - RsPeerId _last_sslid_to_connect; -}; diff --git a/libretroshare/src/pqi/p3cfgmgr.cc b/libretroshare/src/pqi/p3cfgmgr.cc deleted file mode 100644 index e51f9fe52..000000000 --- a/libretroshare/src/pqi/p3cfgmgr.cc +++ /dev/null @@ -1,615 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3cfgmgr.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie, Retroshare Team. * - * * - * 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 . * - * * - *******************************************************************************/ -#include "util/rsdir.h" -//#include "retroshare/rspeers.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/authssl.h" -#include "pqi/pqibin.h" -#include "pqi/pqistore.h" -#include -#include -#include -#include "util/rsstring.h" - -#include "rsitems/rsconfigitems.h" - -/* -#define CONFIG_DEBUG 1 -*/ -#define BACKEDUP_SAVE - - -p3ConfigMgr::p3ConfigMgr(std::string dir) - :basedir(dir), cfgMtx("p3ConfigMgr"), - mConfigSaveActive(true) -{ -} - -void p3ConfigMgr::tick() -{ - bool toSave = false; - - { - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - - /* iterate through and check if any have changed */ - std::list::iterator it; - for(it = mConfigs.begin(); it != mConfigs.end(); ++it) - { - if ((*it)->HasConfigChanged(0)) - { - -#ifdef CONFIG_DEBUG - std::cerr << "p3ConfigMgr::tick() Config Changed - Element: "; - std::cerr << *it; - std::cerr << std::endl; -#endif - - toSave = true; - } - } - - /* disable saving before exit */ - if (!mConfigSaveActive) - { - toSave = false; - } - } - - if (toSave) - { - saveConfiguration(); - } -} - - -void p3ConfigMgr::saveConfiguration() -{ - if(!RsDiscSpace::checkForDiscSpace(RS_CONFIG_DIRECTORY)) - return ; - - saveConfig(); - - -} - -void p3ConfigMgr::saveConfig() -{ - - bool ok= true; - - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - - std::list::iterator it; - for(it = mConfigs.begin(); it != mConfigs.end(); ++it) - { - if ((*it)->HasConfigChanged(1)) - { -#ifdef CONFIG_DEBUG - std::cerr << "p3ConfigMgr::globalSaveConfig() Saving Element: "; - std::cerr << *it; - std::cerr << std::endl; -#endif - ok &= (*it)->saveConfiguration(); - } - /* save metaconfig */ - } - return; -} - - -void p3ConfigMgr::loadConfiguration() -{ - loadConfig(); - - return; -} - -void p3ConfigMgr::loadConfig() -{ - std::list::iterator cit; - RsFileHash dummyHash ; - for (cit = mConfigs.begin(); cit != mConfigs.end(); ++cit) - { -#ifdef CONFIG_DEBUG - std::cerr << "p3ConfigMgr::loadConfig() Element: "; - std::cerr << *cit <<" Dummy Hash: " << dummyHash; - std::cerr << std::endl; -#endif - - (*cit)->loadConfiguration(dummyHash); - - /* force config to NOT CHANGED */ - (*cit)->HasConfigChanged(0); - (*cit)->HasConfigChanged(1); - } - - return; -} - - -void p3ConfigMgr::addConfiguration(std::string file, pqiConfig *conf) -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - - /* construct filename */ - std::string filename = basedir; - if (basedir != "") - { - filename += "/"; - } - filename += "config/"; - filename += file; - - std::list::iterator cit = std::find(mConfigs.begin(),mConfigs.end(),conf); - if (cit != mConfigs.end()) - { - std::cerr << "p3Config::addConfiguration() Config already added"; - std::cerr << std::endl; - std::cerr << "\tOriginal filename " << (*cit)->Filename(); - std::cerr << std::endl; - std::cerr << "\tIgnoring new filename " << filename; - std::cerr << std::endl; - return; - } - // Also check that the filename is not already registered for another config - - for(std::list::iterator it = mConfigs.begin(); it!= mConfigs.end();) - if((*it)->filename == filename) - { - std::cerr << "(WW) Registering a config for file \"" << filename << "\" that is already registered. Replacing previous component." << std::endl; - it = mConfigs.erase(it); - } - else - ++it; - - conf->setFilename(filename);// (cyril) this is quite terrible. The constructor of pqiConfig should take the filename as parameter and hold the information. - mConfigs.push_back(conf); -} - - -void p3ConfigMgr::completeConfiguration() -{ - saveConfiguration(); - - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - mConfigSaveActive = false; -} - - - -p3Config::p3Config() - :pqiConfig() -{ - return; -} - - -bool p3Config::loadConfiguration(RsFileHash& /* loadHash */) -{ - return loadConfig(); -} - -bool p3Config::loadConfig() -{ - -#ifdef CONFIG_DEBUG - std::cerr << "p3Config::loadConfig() loading Configuration\n File: " << Filename() << std::endl; -#endif - - bool pass = true; - std::string cfgFname = Filename(); - std::string cfgFnameBackup = cfgFname + ".tmp"; - - std::string signFname = Filename() +".sgn"; - std::string signFnameBackup = signFname + ".tmp"; - - std::list load; - std::list::iterator it; - - // try 1st attempt - if(!loadAttempt(cfgFname, signFname, load)) - { - -#ifdef CONFIG_DEBUG - std::cerr << "p3Config::loadConfig() Failed to Load" << std::endl; -#endif - - /* bad load */ - for(it = load.begin(); it != load.end(); ++it) - { - delete (*it); - } - pass = false; - - load.clear(); - } - - // try 2nd attempt with backup files if first failed - if(!pass) - { - if(!loadAttempt(cfgFnameBackup, signFnameBackup, load)) - { - -#ifdef CONFIG_DEBUG - std::cerr << "p3Config::loadConfig() Failed on 2nd Pass" << std::endl; -#endif - - /* bad load */ - for(it = load.begin(); it != load.end(); ++it) - { - delete (*it); - } - pass = false; - } - else - pass = true; - } - - - - if(pass) - loadList(load); - else - return false; - - return pass; -} - -bool p3Config::loadAttempt(const std::string& cfgFname,const std::string& signFname, std::list& load) -{ - -#ifdef CONFIG_DEBUG - std::cerr << "p3Config::loadAttempt() \nFilename: " << cfgFname << std::endl; -#endif - - - uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_READABLE; - uint32_t stream_flags = BIN_FLAGS_READABLE; - - BinEncryptedFileInterface *bio = new BinEncryptedFileInterface(cfgFname.c_str(), bioflags); - pqiSSLstore stream(setupSerialiser(), RsPeerId(), bio, stream_flags); - - if(!stream.getEncryptedItems(load)) - { -#ifdef CONFIG_DEBUG - std::cerr << "p3Config::loadAttempt() Error occurred trying to load Item" << std::endl; -#endif - return false; - } - - /* set hash */ - setHash(bio->gethash()); - - // In order to check the signature that is stored on disk, we compute the hash of the current data (which should match the hash of the data on disc because we just read it), - // and validate the signature from the disk on this data. The config file data is therefore hashed twice. Not a security issue, but - // this is a bit inelegant. - - std::string signatureRead; - RsFileHash strHash(Hash()); - - BinFileInterface bfi(signFname.c_str(), BIN_FLAGS_READABLE); - - if(bfi.getFileSize() == 0) - return false ; - - RsTemporaryMemory mem(bfi.getFileSize()) ; - - if(!bfi.readdata(mem,mem.size())) - return false; - - // signature is stored as ascii so we need to convert it back to binary - - RsTemporaryMemory mem2(bfi.getFileSize()/2) ; - - if(!RsUtil::HexToBin(std::string((char*)(unsigned char*)mem,mem.size()),mem2,mem2.size())) - { - std::cerr << "Input string is not a Hex string!!"<< std::endl; - return false ; - } - - bool signature_checks = AuthSSL::getAuthSSL()->VerifyOwnSignBin(strHash.toByteArray(), RsFileHash::SIZE_IN_BYTES,mem2,mem2.size()); - - std::cerr << "(II) checked signature of config file " << cfgFname << ": " << (signature_checks?"OK":"Wrong!") << std::endl; - - return signature_checks; -} - -bool p3Config::saveConfiguration() -{ - return saveConfig(); -} - -bool p3Config::saveConfig() -{ - bool cleanup = true; - std::list toSave; - saveList(cleanup, toSave); - - // temporarily append new to files as these will replace current configuration - std::string newCfgFname = Filename() + "_new"; - std::string newSignFname = Filename() + ".sgn" + "_new"; - - std::string tmpCfgFname = Filename() + ".tmp"; - std::string tmpSignFname = Filename() + ".sgn" + ".tmp"; - - std::string cfgFname = Filename(); - std::string signFname = Filename() + ".sgn"; - - std::cerr << "(II) Saving configuration file " << cfgFname << std::endl; - - uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_WRITEABLE; - uint32_t stream_flags = BIN_FLAGS_WRITEABLE; - bool written = true; - - if (!cleanup) - stream_flags |= BIN_FLAGS_NO_DELETE; - - BinEncryptedFileInterface *cfg_bio = new BinEncryptedFileInterface(newCfgFname.c_str(), bioflags); - pqiSSLstore *stream = new pqiSSLstore(setupSerialiser(), RsPeerId(), cfg_bio, stream_flags); - - written = written && stream->encryptedSendItems(toSave); - - if(!written) - std::cerr << "(EE) Error while writing config file " << Filename() << ": file dropped!!" << std::endl; - - /* store the hash */ - setHash(cfg_bio->gethash()); - - // bio is taken care of in stream's destructor, also forces file to close - delete stream; - - /* sign data */ - std::string signature; - RsFileHash strHash(Hash()); - AuthSSL::getAuthSSL()->SignData(strHash.toByteArray(),strHash.SIZE_IN_BYTES, signature); - - /* write signature to configuration */ - BinMemInterface *signbio = new BinMemInterface(signature.c_str(), - signature.length(), BIN_FLAGS_READABLE); - - signbio->writetofile(newSignFname.c_str()); - - delete signbio; - - // now rewrite current files to temp files - // rename back-up to current file - if(!RsDirUtil::renameFile(cfgFname, tmpCfgFname) || !RsDirUtil::renameFile(signFname, tmpSignFname)){ -#ifdef CONFIG_DEBUG - std::cerr << "p3Config::backedUpFileSave() Failed to rename backup meta files: " << std::endl - << cfgFname << " to " << tmpCfgFname << std::endl - << signFname << " to " << tmpSignFname << std::endl; -#endif - written = false; - } - - - - // now rewrite current files to temp files - // rename back-up to current file - if(!RsDirUtil::renameFile(newCfgFname, cfgFname) || !RsDirUtil::renameFile(newSignFname, signFname)){ - #ifdef CONFIG_DEBUG - std::cerr << "p3Config::() Failed to rename meta files: " << std::endl - << newCfgFname << " to " << cfgFname << std::endl - << newSignFname << " to " << signFname << std::endl; - #endif - - written = false; - } - - - - saveDone(); // callback to inherited class to unlock any Mutexes protecting saveList() data - - return written; - -} - - -/**************************** CONFIGURATION CLASSES ********************/ - -p3GeneralConfig::p3GeneralConfig() - :p3Config() -{ - return; -} - - // General Configuration System -std::string p3GeneralConfig::getSetting(const std::string &opt) -{ -#ifdef CONFIG_DEBUG - std::cerr << "p3GeneralConfig::getSetting(" << opt << ")"; - std::cerr << std::endl; -#endif - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - - /* extract from config */ - std::map::iterator it; - if (settings.end() == (it = settings.find(opt))) - { - std::string nullstring; - return nullstring; - } - return it->second; -} - -void p3GeneralConfig::setSetting(const std::string &opt, const std::string &val) -{ -#ifdef CONFIG_DEBUG - std::cerr << "p3GeneralConfig::setSetting(" << opt << " = " << val << ")"; - std::cerr << std::endl; -#endif - { - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - - /* extract from config */ - std::map::iterator it; - if (settings.end() != (it = settings.find(opt))) - { - if (it->second == val) - { - /* no change */ - return; - } - } - - settings[opt] = val; - } - /* outside mutex */ - IndicateConfigChanged(); - - return; -} - -RsSerialiser *p3GeneralConfig::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsGeneralConfigSerialiser()); - return rss; -} - -bool p3GeneralConfig::saveList(bool &cleanup, std::list& savelist) -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef CONFIG_DEBUG - std::cerr << "p3GeneralConfig::saveList() KV sets: " << settings.size(); - std::cerr << std::endl; -#endif - - cleanup = true; - - - RsConfigKeyValueSet *item = new RsConfigKeyValueSet(); - std::map::iterator it; - for(it = settings.begin(); it != settings.end(); ++it) - { - RsTlvKeyValue kv; - kv.key = it->first; - kv.value = it->second; - item->tlvkvs.pairs.push_back(kv); - - /* make sure we don't overload it */ - if (item->tlvkvs.TlvSize() > 4000) - { - savelist.push_back(item); - item = new RsConfigKeyValueSet(); - } - } - - if (item->tlvkvs.pairs.size() > 0) - { - savelist.push_back(item); - } else - delete item; - - return true; -} - - -bool p3GeneralConfig::loadList(std::list& load) -{ -#ifdef CONFIG_DEBUG - std::cerr << "p3GeneralConfig::loadList() count: " << load.size(); - std::cerr << std::endl; -#endif - - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - - /* add into settings */ - RsConfigKeyValueSet *item = NULL; - std::list::iterator it; - std::list::iterator kit; - - for(it = load.begin(); it != load.end();) - { - item = dynamic_cast(*it); - if (item) - { - for(kit = item->tlvkvs.pairs.begin(); - kit != item->tlvkvs.pairs.end(); ++kit) - { - settings[kit->key] = kit->value; - } - } - - /* cleanup */ - delete (*it); - it = load.erase(it); - } - - return true; -} - - -/**** MUTEX NOTE: - * have protected all, but think that - * only the Indication and hash really need it - */ - -pqiConfig::pqiConfig() - : cfgMtx("pqiConfig"), ConfInd(2) -{ - return; -} - -pqiConfig::~pqiConfig() -{ - return; -} - -const std::string& pqiConfig::Filename() -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - return filename; -} - -const RsFileHash& pqiConfig::Hash() -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - return hash; -} - -void pqiConfig::IndicateConfigChanged() -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - ConfInd.IndicateChanged(); -} - -bool pqiConfig::HasConfigChanged(uint16_t idx) -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - return ConfInd.Changed(idx); -} - -void pqiConfig::setFilename(const std::string& name) -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - filename = name; -} - -void pqiConfig::setHash(const RsFileHash& h) -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - hash = h; -} - diff --git a/libretroshare/src/pqi/p3cfgmgr.h b/libretroshare/src/pqi/p3cfgmgr.h deleted file mode 100644 index 768855d38..000000000 --- a/libretroshare/src/pqi/p3cfgmgr.h +++ /dev/null @@ -1,284 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3cfgmgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef P3_CONFIG_MGR_HEADER -#define P3_CONFIG_MGR_HEADER - -#include -#include -#include - -#include "pqi/pqi_base.h" -#include "pqi/pqiindic.h" -#include "pqi/pqinetwork.h" -#include "util/rsthreads.h" -#include "pqi/pqibin.h" - -/***** Configuration Management ***** - * - * we need to store: - * (1) Certificates. - * (2) List of Friends / Net Configuration - * (3) Stun List. / DHT peers. - * (4) general config. - * - * - * At top level we need: - * - * - type / filename / size / hash - - * and the file signed... - * - * - */ - -/**** THESE are STORED in CONFIGURATION FILES.... - * Cannot be changed - * - *********************/ - -/* CACHE ID Must be at the END so that other configurations - * are loaded First (Cache Config --> Cache Loading) - */ - -class p3ConfigMgr; - - - -//! abstract class for configuration saving -/*! - * Aim is that active objects in retroshare can dervie from this class - * and implement their method of saving and loading their configuration - */ -class pqiConfig -{ - public: - pqiConfig(); -virtual ~pqiConfig(); - -/** - * loads configuration of object - * @param loadHash This is the hash that will be compared to confirm saved configuration has not - * been tampered with - */ -virtual bool loadConfiguration(RsFileHash &loadHash) = 0; - -/** - * save configuration of object - */ -virtual bool saveConfiguration() = 0; - -/** - * The name of the configuration file - */ -const std::string& Filename(); - -/** - * The hash computed for this configuration, can use this to compare to externally stored hash - * for validation checking - */ -const RsFileHash& Hash(); - - protected: - -/** - * Checks if configuration has changed - */ -virtual void IndicateConfigChanged(); -void setHash(const RsFileHash& h); - - RsMutex cfgMtx; - - /** - * This sets the name of the pqi configuation file - */ - void setFilename(const std::string& name); - -private: - /** - * @param an index for the Confind which contains list of configuarations that can be tracked - */ - bool HasConfigChanged(uint16_t idx); - - Indicator ConfInd; - - std::string filename; - RsFileHash hash; - - friend class p3ConfigMgr; - /* so it can access: - * setFilename() and HasConfigChanged() - */ -}; - - - -/***********************************************************************************************/ - -/*! - * MUTEX NOTE - * Class data is protected by mutex's so that anyone can call these - * functions, at any time. - */ -class p3ConfigMgr -{ - public: - - /** - * @param bdir base directory: where config files will be saved - */ - explicit p3ConfigMgr(std::string bdir); - - /** - * checks and update all added configurations - * @see rsserver - */ - void tick(); - - /** - * save all added configuation including configuration files - * creates global signature file - */ - void saveConfiguration(); - - /** - * loads all configurations - */ - void loadConfiguration(); - - /** - * @param file The name for new configuration - * @param conf to the configuration to use - */ - void addConfiguration(std::string file, pqiConfig *conf); - - /** saves config, and disables further saving - * used for exiting the system - */ - void completeConfiguration(); - - - - private: - - /** - * saves configuration of pqiconfigs in object configs - */ - void saveConfig(); - - /** - * - */ - void loadConfig(); - - const std::string basedir; - - RsMutex cfgMtx; /* below is protected */ - - bool mConfigSaveActive; - std::list mConfigs; -}; - - - -/***************************************************************************************************/ - - -/** - * @brief Abstract class for configuration saving. - * Aimed at rs services that uses RsItem config data, provide a way for RS - * services to save and load particular configurations as items. - */ -class p3Config : public pqiConfig -{ -public: - p3Config(); - - virtual bool loadConfiguration(RsFileHash &loadHash); - virtual bool saveConfiguration(); - -protected: - - /// Key Functions to be overloaded for Full Configuration - virtual RsSerialiser *setupSerialiser() = 0; - - /** - * saves list of derived object - * @param cleanup this inform you if you need to call saveDone() to - * unlock/allow access to resources pointed to by handles (list) - * returned by function: thus false, call saveDone after returned list - * finished with and vice versa - * @return list of config items derived object wants to saves - */ - virtual bool saveList(bool &cleanup, std::list&) = 0; - - /** - * loads up list of configs items for derived object - * @param load list of config items to load up - */ - virtual bool loadList(std::list& load) = 0; - - /** - * callback for mutex unlocking - * in derived classes (should only be needed if cleanup = false) - */ - virtual void saveDone() {} - -private: - - bool loadConfig(); - bool saveConfig(); - - bool loadAttempt( const std::string&, const std::string&, - std::list& load ); -}; // end of p3Config - - -class p3GeneralConfig: public p3Config -{ - public: - p3GeneralConfig(); - -// General Configuration System -std::string getSetting(const std::string &opt); -void setSetting(const std::string &opt, const std::string &val); - - protected: - - /* Key Functions to be overloaded for Full Configuration */ -virtual RsSerialiser *setupSerialiser(); -virtual bool saveList(bool &cleanup, std::list&); -virtual bool loadList(std::list& ); - - private: - - /* protected by pqiConfig mutex as well! */ -std::map settings; - - -}; - - - - - - - -#endif // P3_CONFIG_MGR_HEADER diff --git a/libretroshare/src/pqi/p3historymgr.cc b/libretroshare/src/pqi/p3historymgr.cc deleted file mode 100644 index a15d18075..000000000 --- a/libretroshare/src/pqi/p3historymgr.cc +++ /dev/null @@ -1,697 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3historymgr.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Thunder. * - * * - * 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 . * - * * - *******************************************************************************/ -#include "util/rstime.h" - -#include "p3historymgr.h" -#include "rsitems/rshistoryitems.h" -#include "rsitems/rsconfigitems.h" -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" -#include "rsitems/rsmsgitems.h" -#include "rsserver/p3face.h" -#include "util/rsstring.h" - -/**** - * #define HISTMGR_DEBUG 1 - ***/ - -// clean too old messages every 5 minutes -// -#define MSG_HISTORY_CLEANING_PERIOD 300 - -RsHistory *rsHistory = NULL; - -p3HistoryMgr::p3HistoryMgr() - : p3Config() - , nextMsgId(1) - , mPublicEnable(false), mLobbyEnable(true), mPrivateEnable(true), mDistantEnable(true) - , mPublicSaveCount(0), mLobbySaveCount(0), mPrivateSaveCount(0), mDistantSaveCount(0) - , mMaxStorageDurationSeconds(10*86400) // store for 10 days at most. - , mLastCleanTime(0) - , mHistoryMtx("p3HistoryMgr") -{ -} - -p3HistoryMgr::~p3HistoryMgr() -{ -} - -/***** p3HistoryMgr *****/ - -void p3HistoryMgr::addMessage(const ChatMessage& cm) -{ - uint32_t addMsgId = 0; - - rstime_t now = time(NULL) ; - - if(mLastCleanTime + MSG_HISTORY_CLEANING_PERIOD < now) - { - cleanOldMessages() ; - mLastCleanTime = now ; - } - - { - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - - RsPeerId msgPeerId; // id of sending peer - RsPeerId chatPeerId; // id of chat endpoint - std::string peerName; //name of sending peer - - if (cm.chat_id.isBroadcast() && mPublicEnable == true) { - peerName = rsPeers->getPeerName(cm.broadcast_peer_id); - } - else if (cm.chat_id.isPeerId() && mPrivateEnable == true) { - msgPeerId = cm.incoming ? cm.chat_id.toPeerId() : rsPeers->getOwnId(); - peerName = rsPeers->getPeerName(msgPeerId); - } - else if (cm.chat_id.isLobbyId() && mLobbyEnable == true) { - msgPeerId = RsPeerId(cm.lobby_peer_gxs_id); - RsIdentityDetails details; - if (rsIdentity->getIdDetails(cm.lobby_peer_gxs_id, details)) - peerName = details.mNickname; - else - peerName = cm.lobby_peer_gxs_id.toStdString(); - } - else if(cm.chat_id.isDistantChatId()&& mDistantEnable == true) - { - DistantChatPeerInfo dcpinfo; - if (rsMsgs->getDistantChatStatus(cm.chat_id.toDistantChatId(), dcpinfo)) - { - RsIdentityDetails det; - RsGxsId writer_id = cm.incoming?(dcpinfo.to_id):(dcpinfo.own_id); - - if(rsIdentity->getIdDetails(writer_id,det)) - peerName = det.mNickname; - else - peerName = writer_id.toStdString(); - - msgPeerId = cm.incoming?RsPeerId(dcpinfo.own_id):RsPeerId(dcpinfo.to_id); - } - else - { - RS_ERR( "Cannot retrieve friend name for distant chat ", cm.chat_id.toDistantChatId() ); - peerName = ""; - } - - } - else - return; - - if(!chatIdToVirtualPeerId(cm.chat_id, chatPeerId)) - return; - - RsHistoryMsgItem* item = new RsHistoryMsgItem; - item->chatPeerId = chatPeerId; - item->incoming = cm.incoming; - item->msgPeerId = msgPeerId; - item->peerName = peerName; - item->sendTime = cm.sendTime; - item->recvTime = cm.recvTime; - - item->message = cm.msg ; - //librs::util::ConvertUtf16ToUtf8(chatItem->message, item->message); - - std::map >::iterator mit = mMessages.find(item->chatPeerId); - if (mit != mMessages.end()) { - item->msgId = nextMsgId++; - mit->second.insert(std::make_pair(item->msgId, item)); - addMsgId = item->msgId; - - // check the limit - uint32_t limit; - if (chatPeerId.isNull()) - limit = mPublicSaveCount; - else if (cm.chat_id.isLobbyId()) - limit = mLobbySaveCount; - else - limit = mPrivateSaveCount; - - if (limit) { - while (mit->second.size() > limit) { - delete(mit->second.begin()->second); - mit->second.erase(mit->second.begin()); - } - } - } else { - std::map msgs; - item->msgId = nextMsgId++; - msgs.insert(std::make_pair(item->msgId, item)); - mMessages.insert(std::make_pair(item->chatPeerId, msgs)); - addMsgId = item->msgId; - - // no need to check the limit - } - - IndicateConfigChanged(); - } - - if (addMsgId) { - RsServer::notify()->notifyHistoryChanged(addMsgId, NOTIFY_TYPE_ADD); - } -} - -void p3HistoryMgr::cleanOldMessages() -{ - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - -#ifdef HISTMGR_DEBUG - std::cerr << "****** cleaning old messages." << std::endl; -#endif - rstime_t now = time(NULL) ; - bool changed = false ; - - for(std::map >::iterator mit = mMessages.begin(); mit != mMessages.end();) - { - if (mMaxStorageDurationSeconds > 0) - { - for(std::map::iterator lit = mit->second.begin();lit!=mit->second.end();) - if(lit->second->recvTime + mMaxStorageDurationSeconds < now) - { - std::map::iterator lit2 = lit ; - ++lit2 ; - -#ifdef HISTMGR_DEBUG - std::cerr << " removing msg id " << lit->first << ", for peer id " << mit->first << std::endl; -#endif - delete lit->second ; - - mit->second.erase(lit) ; - lit = lit2 ; - - changed = true ; - } - else - ++lit ; - } - - if(mit->second.empty()) - { - std::map >::iterator mit2 = mit ; - ++mit2 ; -#ifdef HISTMGR_DEBUG - std::cerr << " removing peer id " << mit->first << ", since it has no messages" << std::endl; -#endif - mMessages.erase(mit) ; - mit = mit2 ; - - changed = true ; - } - else - ++mit ; - } - - if(changed) - IndicateConfigChanged() ; -} - -/***** p3Config *****/ - -RsSerialiser* p3HistoryMgr::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser; - rss->addSerialType(new RsHistorySerialiser); - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss; -} - -bool p3HistoryMgr::saveList(bool& cleanup, std::list& saveData) -{ - cleanup = false; - - mHistoryMtx.lock(); /********** STACK LOCKED MTX ******/ - - std::map >::iterator mit; - std::map::iterator lit; - for (mit = mMessages.begin(); mit != mMessages.end(); ++mit) { - for (lit = mit->second.begin(); lit != mit->second.end(); ++lit) { - if (lit->second->saveToDisc) { - saveData.push_back(lit->second); - } - } - } - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet; - - RsTlvKeyValue kv; - kv.key = "PUBLIC_ENABLE"; - kv.value = mPublicEnable ? "TRUE" : "FALSE"; - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "PRIVATE_ENABLE"; - kv.value = mPrivateEnable ? "TRUE" : "FALSE"; - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "LOBBY_ENABLE"; - kv.value = mLobbyEnable ? "TRUE" : "FALSE"; - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "DISTANT_ENABLE"; - kv.value = mDistantEnable ? "TRUE" : "FALSE"; - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "MAX_STORAGE_TIME"; - rs_sprintf(kv.value,"%d",mMaxStorageDurationSeconds) ; - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "LOBBY_SAVECOUNT"; - rs_sprintf(kv.value, "%lu", mLobbySaveCount); - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "PUBLIC_SAVECOUNT"; - rs_sprintf(kv.value, "%lu", mPublicSaveCount); - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "PRIVATE_SAVECOUNT"; - rs_sprintf(kv.value, "%lu", mPrivateSaveCount); - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "DISTANT_SAVECOUNT"; - rs_sprintf(kv.value, "%lu", mDistantSaveCount); - vitem->tlvkvs.pairs.push_back(kv); - - saveData.push_back(vitem); - saveCleanupList.push_back(vitem); - - return true; -} - -void p3HistoryMgr::saveDone() -{ - /* clean up the save List */ - std::list::iterator it; - for (it = saveCleanupList.begin(); it != saveCleanupList.end(); ++it) { - delete (*it); - } - - saveCleanupList.clear(); - - /* unlock mutex */ - mHistoryMtx.unlock(); /****** MUTEX UNLOCKED *******/ -} - -bool p3HistoryMgr::loadList(std::list& load) -{ - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - - RsHistoryMsgItem *msgItem; - std::list::iterator it; - - for (it = load.begin(); it != load.end(); ++it) - { - if (NULL != (msgItem = dynamic_cast(*it))) { - - std::map >::iterator mit = mMessages.find(msgItem->chatPeerId); - msgItem->msgId = nextMsgId++; - -#ifdef HISTMGR_DEBUG - std::cerr << "Loading msg history item: peer id=" << msgItem->chatPeerId << "), msg id =" << msgItem->msgId << std::endl; -#endif - - if (mit != mMessages.end()) { - mit->second.insert(std::make_pair(msgItem->msgId, msgItem)); - } else { - std::map msgs; - msgs.insert(std::make_pair(msgItem->msgId, msgItem)); - mMessages.insert(std::make_pair(msgItem->chatPeerId, msgs)); - } - - // don't delete the item !! - - continue; - } - - RsConfigKeyValueSet *rskv ; - if (NULL != (rskv = dynamic_cast(*it))) { - for (std::list::const_iterator kit = rskv->tlvkvs.pairs.begin(); kit != rskv->tlvkvs.pairs.end(); ++kit) { - if (kit->key == "PUBLIC_ENABLE") { - mPublicEnable = (kit->value == "TRUE") ? true : false; - continue; - } - - if (kit->key == "PRIVATE_ENABLE") { - mPrivateEnable = (kit->value == "TRUE") ? true : false; - continue; - } - - if (kit->key == "LOBBY_ENABLE") { - mLobbyEnable = (kit->value == "TRUE") ? true : false; - continue; - } - - if (kit->key == "DISTANT_ENABLE") { - mDistantEnable = (kit->value == "TRUE") ? true : false; - continue; - } - - if (kit->key == "MAX_STORAGE_TIME") { - uint32_t val ; - if (sscanf(kit->value.c_str(), "%u", &val) == 1) - mMaxStorageDurationSeconds = val ; - -#ifdef HISTMGR_DEBUG - std::cerr << "Loaded max storage time for history = " << val << " seconds" << std::endl; -#endif - continue; - } - - if (kit->key == "PUBLIC_SAVECOUNT") { - mPublicSaveCount = atoi(kit->value.c_str()); - continue; - } - if (kit->key == "PRIVATE_SAVECOUNT") { - mPrivateSaveCount = atoi(kit->value.c_str()); - continue; - } - if (kit->key == "LOBBY_SAVECOUNT") { - mLobbySaveCount = atoi(kit->value.c_str()); - continue; - } - if (kit->key == "DISTANT_SAVECOUNT") { - mDistantSaveCount = atoi(kit->value.c_str()); - continue; - } - } - - delete (*it); - continue; - } - - // delete unknown items - delete (*it); - } - - load.clear() ; - return true; -} - -// have to convert to virtual peer id, to be able to use existing serialiser and file format -bool p3HistoryMgr::chatIdToVirtualPeerId(const ChatId& chat_id, RsPeerId &peer_id) -{ - if (chat_id.isBroadcast()) { - peer_id = RsPeerId(); - return true; - } - if (chat_id.isPeerId()) { - peer_id = chat_id.toPeerId(); - return true; - } - if (chat_id.isLobbyId()) { - if(sizeof(ChatLobbyId) > RsPeerId::SIZE_IN_BYTES){ - std::cerr << "p3HistoryMgr::chatIdToVirtualPeerId() ERROR: ChatLobbyId does not fit into virtual peer id. Please report this error." << std::endl; - return false; - } - uint8_t bytes[RsPeerId::SIZE_IN_BYTES] ; - memset(bytes,0,RsPeerId::SIZE_IN_BYTES) ; - ChatLobbyId lobby_id = chat_id.toLobbyId(); - memcpy(bytes,&lobby_id,sizeof(ChatLobbyId)); - peer_id = RsPeerId(bytes); - return true; - } - - if (chat_id.isDistantChatId()) { - peer_id = RsPeerId(chat_id.toDistantChatId()); - return true; - } - - return false; -} - -/***** p3History *****/ - -static void convertMsg(const RsHistoryMsgItem* item, HistoryMsg &msg) -{ - msg.msgId = item->msgId; - msg.chatPeerId = item->chatPeerId; - msg.incoming = item->incoming; - msg.peerId = item->msgPeerId; - msg.peerName = item->peerName; - msg.sendTime = item->sendTime; - msg.recvTime = item->recvTime; - msg.message = item->message; -} - -bool p3HistoryMgr::getMessages(const ChatId &chatId, std::list &msgs, uint32_t loadCount) -{ - msgs.clear(); - - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - - RsPeerId chatPeerId; - bool enabled = false; - if (chatId.isBroadcast() && mPublicEnable == true) { - enabled = true; - } - if (chatId.isPeerId() && mPrivateEnable == true) { - enabled = true; - } - if (chatId.isLobbyId() && mLobbyEnable == true) { - enabled = true; - } - if (chatId.isDistantChatId() && mDistantEnable == true) { - enabled = true; - } - - if(enabled == false) - return false; - - if(!chatIdToVirtualPeerId(chatId, chatPeerId)) - return false; - -#ifdef HISTMGR_DEBUG - std::cerr << "Getting history for virtual peer " << chatPeerId << std::endl; -#endif - - uint32_t foundCount = 0; - - std::map >::iterator mit = mMessages.find(chatPeerId); - - if (mit != mMessages.end()) - { - std::map::reverse_iterator lit; - - for (lit = mit->second.rbegin(); lit != mit->second.rend(); ++lit) - { - HistoryMsg msg; - convertMsg(lit->second, msg); - msgs.insert(msgs.begin(), msg); - foundCount++; - if (loadCount && foundCount >= loadCount) { - break; - } - } - } -#ifdef HISTMGR_DEBUG - std::cerr << msgs.size() << " messages added." << std::endl; -#endif - - return true; -} - -bool p3HistoryMgr::getMessage(uint32_t msgId, HistoryMsg &msg) -{ - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - - std::map >::iterator mit; - for (mit = mMessages.begin(); mit != mMessages.end(); ++mit) { - std::map::iterator lit = mit->second.find(msgId); - if (lit != mit->second.end()) { - convertMsg(lit->second, msg); - return true; - } - } - - return false; -} - -void p3HistoryMgr::clear(const ChatId &chatId) -{ - { - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - - RsPeerId chatPeerId; - if(!chatIdToVirtualPeerId(chatId, chatPeerId)) - return; - -#ifdef HISTMGR_DEBUG - std::cerr << "********** p3History::clear()called for virtual peer id " << chatPeerId << std::endl; -#endif - - std::map >::iterator mit = mMessages.find(chatPeerId); - if (mit == mMessages.end()) { - return; - } - - std::map::iterator lit; - for (lit = mit->second.begin(); lit != mit->second.end(); ++lit) { - delete(lit->second); - } - mit->second.clear(); - mMessages.erase(mit); - - IndicateConfigChanged(); - } - - RsServer::notify()->notifyHistoryChanged(0, NOTIFY_TYPE_MOD); -} - -void p3HistoryMgr::removeMessages(const std::list &msgIds) -{ - std::list ids = msgIds; - std::list removedIds; - std::list::iterator iit; - -#ifdef HISTMGR_DEBUG - std::cerr << "********** p3History::removeMessages called()" << std::endl; -#endif - { - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - - std::map >::iterator mit; - for (mit = mMessages.begin(); mit != mMessages.end(); ++mit) - { - iit = ids.begin(); - while ( !ids.empty() || (iit != ids.end()) ) - { - std::map::iterator lit = mit->second.find(*iit); - if (lit != mit->second.end()) - { -#ifdef HISTMGR_DEBUG - std::cerr << "**** Removing " << mit->first << " msg id = " << lit->first << std::endl; -#endif - - delete(lit->second); - mit->second.erase(lit); - - removedIds.push_back(*iit); - iit = ids.erase(iit); - - continue; - } - - ++iit; - } - } - } - - if (!removedIds.empty()) - { - IndicateConfigChanged(); - - for (iit = removedIds.begin(); iit != removedIds.end(); ++iit) - RsServer::notify()->notifyHistoryChanged(*iit, NOTIFY_TYPE_DEL); - } -} - -bool p3HistoryMgr::getEnable(uint32_t chat_type) -{ - switch(chat_type) - { - case RS_HISTORY_TYPE_PUBLIC : return mPublicEnable ; - case RS_HISTORY_TYPE_LOBBY : return mLobbyEnable ; - case RS_HISTORY_TYPE_PRIVATE: return mPrivateEnable ; - case RS_HISTORY_TYPE_DISTANT: return mDistantEnable ; - default: - std::cerr << "Unexpected value " << chat_type<< " in p3HistoryMgr::getEnable(): this is a bug." << std::endl; - return 0 ; - } -} - -uint32_t p3HistoryMgr::getMaxStorageDuration() -{ - return mMaxStorageDurationSeconds ; -} - - -void p3HistoryMgr::setMaxStorageDuration(uint32_t seconds) -{ - if(mMaxStorageDurationSeconds != seconds) - IndicateConfigChanged() ; - - mMaxStorageDurationSeconds = seconds ; -} - -void p3HistoryMgr::setEnable(uint32_t chat_type, bool enable) -{ - bool oldValue; - - switch(chat_type) - { - case RS_HISTORY_TYPE_PUBLIC : oldValue = mPublicEnable ; - mPublicEnable = enable ; - break ; - - case RS_HISTORY_TYPE_LOBBY : oldValue = mLobbyEnable ; - mLobbyEnable = enable; - break ; - - case RS_HISTORY_TYPE_PRIVATE: oldValue = mPrivateEnable ; - mPrivateEnable = enable ; - break ; - case RS_HISTORY_TYPE_DISTANT: oldValue = mDistantEnable ; - mDistantEnable = enable ; - break ; - default: - return; - } - - if (oldValue != enable) - IndicateConfigChanged(); -} - -uint32_t p3HistoryMgr::getSaveCount(uint32_t chat_type) -{ - switch(chat_type) - { - case RS_HISTORY_TYPE_PUBLIC : return mPublicSaveCount ; - case RS_HISTORY_TYPE_LOBBY : return mLobbySaveCount ; - case RS_HISTORY_TYPE_PRIVATE: return mPrivateSaveCount ; - default: - std::cerr << "Unexpected value " << chat_type<< " in p3HistoryMgr::getSaveCount(): this is a bug." << std::endl; - return 0 ; - } -} - -void p3HistoryMgr::setSaveCount(uint32_t chat_type, uint32_t count) -{ - uint32_t oldValue; - - switch(chat_type) - { - case RS_HISTORY_TYPE_PUBLIC : oldValue = mPublicSaveCount ; - mPublicSaveCount = count ; - break ; - - case RS_HISTORY_TYPE_LOBBY : oldValue = mLobbySaveCount ; - mLobbySaveCount = count; - break ; - - case RS_HISTORY_TYPE_PRIVATE: oldValue = mPrivateSaveCount ; - mPrivateSaveCount = count ; - break ; - default: - return; - } - - if (oldValue != count) - IndicateConfigChanged(); -} diff --git a/libretroshare/src/pqi/p3historymgr.h b/libretroshare/src/pqi/p3historymgr.h deleted file mode 100644 index a74eff67e..000000000 --- a/libretroshare/src/pqi/p3historymgr.h +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3historymgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Thunder. * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_P3_HISTORY_MGR_H -#define RS_P3_HISTORY_MGR_H - -#include -#include - -#include "rsitems/rshistoryitems.h" -#include "retroshare/rshistory.h" -#include "pqi/p3cfgmgr.h" - -class RsChatMsgItem; -class ChatMessage; - -//! handles history -/*! - * The is a retroshare service which allows peers - * to store the history of the chat messages - */ -class p3HistoryMgr: public p3Config -{ -public: - p3HistoryMgr(); - virtual ~p3HistoryMgr(); - - /******** p3HistoryMgr *********/ - - void addMessage(const ChatMessage &cm); - - /********* RsHistory ***********/ - - bool getMessages(const ChatId &chatPeerId, std::list &msgs, uint32_t loadCount); - bool getMessage(uint32_t msgId, HistoryMsg &msg); - void clear(const ChatId &chatPeerId); - void removeMessages(const std::list &msgIds); - - virtual bool getEnable(uint32_t chat_type); - virtual void setEnable(uint32_t chat_type, bool enable); - virtual uint32_t getSaveCount(uint32_t chat_type); - virtual void setSaveCount(uint32_t chat_type, uint32_t count); - virtual void setMaxStorageDuration(uint32_t seconds) ; - virtual uint32_t getMaxStorageDuration() ; - - /********* p3config ************/ - - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool& cleanup, std::list& saveData); - virtual void saveDone(); - virtual bool loadList(std::list& load); - - static bool chatIdToVirtualPeerId(const ChatId& chat_id, RsPeerId& peer_id); - -private: - uint32_t nextMsgId; - std::map > mMessages; - - // Removes messages stored for more than mMaxMsgStorageDurationSeconds seconds. - // This avoids the stored list to grow crazy with time. - // - void cleanOldMessages() ; - - bool mPublicEnable; - bool mLobbyEnable; - bool mPrivateEnable; - bool mDistantEnable; - - uint32_t mPublicSaveCount; - uint32_t mLobbySaveCount; - uint32_t mPrivateSaveCount; - uint32_t mDistantSaveCount; - - uint32_t mMaxStorageDurationSeconds ; - rstime_t mLastCleanTime ; - - std::list saveCleanupList; /* TEMPORARY LIST WHEN SAVING */ - - RsMutex mHistoryMtx; -}; - -#endif diff --git a/libretroshare/src/pqi/p3linkmgr.cc b/libretroshare/src/pqi/p3linkmgr.cc deleted file mode 100644 index 97a889b79..000000000 --- a/libretroshare/src/pqi/p3linkmgr.cc +++ /dev/null @@ -1,2209 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3linkmgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2011 by Robert Fernie. * - * Copyright (C) 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#include "pqi/p3linkmgr.h" - -#include "pqi/p3peermgr.h" -#include "pqi/p3netmgr.h" - -#include "rsserver/p3face.h" -#include "pqi/authssl.h" -#include "tcponudp/tou.h" -#include "util/extaddrfinder.h" -#include "util/dnsresolver.h" -#include "util/rsnet.h" -#include "pqi/authgpg.h" - - -#include "util/rsprint.h" -#include "util/rsdebug.h" -#include "util/rsstring.h" - -#include "rsitems/rsconfigitems.h" - -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsdht.h" -#include "retroshare/rsbanlist.h" - -/* Network setup States */ - -static struct RsLog::logInfo p3connectzoneInfo = {RsLog::Default, "p3connect"}; -#define p3connectzone &p3connectzoneInfo - -/**** - * #define LINKMGR_DEBUG 1 - * #define LINKMGR_DEBUG_LOG 1 - * #define LINKMGR_DEBUG_CONNFAIL 1 - * #define LINKMGR_DEBUG_ACTIONS 1 - * #define LINKMGR_DEBUG_LINKTYPE 1 - ***/ - -/**** - * #define DISABLE_UDP_CONNECTIONS 1 - ***/ - -/**** - * #define P3CONNMGR_NO_TCP_CONNECTIONS 1 - ***/ -/**** - * #define P3CONNMGR_NO_AUTO_CONNECTION 1 - ***/ - -//#define P3CONNMGR_NO_TCP_CONNECTIONS 1 - -const uint32_t P3CONNMGR_TCP_DEFAULT_DELAY = 3; /* 2 Seconds? is it be enough! */ -//const uint32_t P3CONNMGR_UDP_DEFAULT_DELAY = 3; /* 2 Seconds? is it be enough! */ - -const uint32_t P3CONNMGR_TCP_DEFAULT_PERIOD = 10; -const uint32_t P3CONNMGR_UDP_DEFAULT_PERIOD = 30; // this represents how long it stays at the default TTL (4), before rising. - -#define MAX_AVAIL_PERIOD 230 //times a peer stay in available state when not connected -#define MIN_RETRY_PERIOD 140 - -#define MAX_RANDOM_ATTEMPT_OFFSET 6 // seconds. - -void printConnectState(std::ostream &out, peerConnectState &peer); - -peerConnectAddress::peerConnectAddress() - :delay(0), period(0), type(0), flags(0), ts(0), bandwidth(0), domain_port(0) -{ - sockaddr_storage_clear(addr); - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(srcaddr); -} - - -peerAddrInfo::peerAddrInfo() - :found(false), type(0), ts(0) -{ -} - -peerConnectState::peerConnectState() - : dhtVisible(false), - connecttype(0), - actAsServer(false), - lastavailable(0), - lastattempt(0), - name(""), - state(0), - actions(0), - linkType(0), - source(0), - inConnAttempt(false), - wasDeniedConnection(false), - deniedTS(0), - deniedInConnAttempt(false) -{ -} - -std::string textPeerConnectState(peerConnectState &state) -{ - return "Id: " + state.id.toStdString() + "\n"; -} - -/********* - * NOTES: - * - * p3LinkMgr doesn't store anything. All configuration is handled by p3PeerMgr. - * - * p3LinkMgr recvs the Discovery / Dht / Status updates.... tries the address. - * at success the address is pushed to p3PeerMgr for storage. - * - */ - - -p3LinkMgrIMPL::p3LinkMgrIMPL(p3PeerMgrIMPL *peerMgr, p3NetMgrIMPL *netMgr) - :mPeerMgr(peerMgr), mNetMgr(netMgr), mLinkMtx("p3LinkMgr"),mStatusChanged(false) -{ - - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - mDNSResolver = new DNSResolver(); - mRetryPeriod = MIN_RETRY_PERIOD; - - /* setup Banned Ip Address - static for now - */ - - struct sockaddr_storage bip; - sockaddr_storage_clear(bip); - struct sockaddr_in *addr = (struct sockaddr_in *) &bip; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = 1; - addr->sin_port = htons(0); - - mBannedIpList.push_back(bip); - } - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgr() Startup" << std::endl; -#endif - - return; -} - -p3LinkMgrIMPL::~p3LinkMgrIMPL() -{ - delete(mDNSResolver); -} - -bool p3LinkMgrIMPL::setLocalAddress(const struct sockaddr_storage &addr) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - mLocalAddress = addr; - - return true ; -} - -bool p3LinkMgrIMPL::getLocalAddress(struct sockaddr_storage &addr) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - addr = mLocalAddress; - return true; -} - - -bool p3LinkMgrIMPL::isOnline(const RsPeerId &ssl_id) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { - return false; - } - - if (it->second.state & RS_PEER_S_CONNECTED) - { - return true; - } - return false; -} - - - -uint32_t p3LinkMgrIMPL::getLinkType(const RsPeerId &ssl_id) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { - return 0; - } - - if (it->second.state & RS_PEER_S_CONNECTED) - { - return it->second.linkType; - } - return 0; -} - - - -void p3LinkMgrIMPL::getOnlineList(std::list &ssl_peers) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (it->second.state & RS_PEER_S_CONNECTED) - { - ssl_peers.push_back(it->first); - } - } - return; -} - -void p3LinkMgrIMPL::getFriendList(std::list &ssl_peers) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - ssl_peers.push_back(it->first); - } - return; -} - -bool p3LinkMgrIMPL::getPeerName(const RsPeerId &ssl_id, std::string &name) -{ - return mPeerMgr->getPeerName(ssl_id, name); -} - - -bool p3LinkMgrIMPL::getFriendNetStatus(const RsPeerId &id, peerConnectState &state) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - it = mFriendList.find(id); - if (it == mFriendList.end()) - { - return false; - } - - state = it->second; - - return true; -} - - - -void p3LinkMgrIMPL::setFriendVisibility(const RsPeerId &id, bool isVisible) -{ - /* set visibility */ - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - it = mFriendList.find(id); - if (it == mFriendList.end()) - { - /* */ - std::cerr << "p3LinkMgrIMPL::setFriendVisibility() ERROR peer unknown: " << id; - std::cerr << std::endl; - return; - } - - if (it->second.dhtVisible == isVisible) - { - /* no change in state */ - return; - } - - it->second.dhtVisible = isVisible; - - if (it->second.state & RS_PEER_S_CONNECTED) - { - /* dont worry about it */ - return; - } - } - - /* switch the NetAssistOn/Off */ - mNetMgr->netAssistFriend(id, isVisible); -} - - -void p3LinkMgrIMPL::tick() -{ - statusTick(); - tickMonitors(); -} - - -void p3LinkMgrIMPL::statusTick() -{ - /* iterate through peers ... - * if been available for long time ... remove flag - * if last attempt a while - retryConnect. - * etc. - */ - -#ifdef LINKMGR_DEBUG_TICK - std::cerr << "p3LinkMgrIMPL::statusTick()" << std::endl; -#endif - std::list retryIds; - //std::list dummyToRemove; - - { - rstime_t now = time(NULL); - rstime_t oldavail = now - MAX_AVAIL_PERIOD; - rstime_t retry = now - mRetryPeriod; - - RsStackMutex stack(mLinkMtx); /****** LOCK MUTEX ******/ - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (it->second.state & RS_PEER_S_CONNECTED) - { - continue; - } - - if ((it->second.state & RS_PEER_S_ONLINE) && - (it->second.lastavailable < oldavail)) - { -#ifdef LINKMGR_DEBUG_TICK - std::cerr << "p3LinkMgrIMPL::statusTick() ONLINE TIMEOUT for: "; - std::cerr << it->first; - std::cerr << std::endl; -#endif - it->second.state &= (~RS_PEER_S_ONLINE); - } - - if (it->second.lastattempt < retry) - { - retryIds.push_back(it->first); - } - } - } - -#ifndef P3CONNMGR_NO_AUTO_CONNECTION - std::list::iterator it2; - for(it2 = retryIds.begin(); it2 != retryIds.end(); ++it2) - { -#ifdef LINKMGR_DEBUG_TICK - std::cerr << "p3LinkMgrIMPL::statusTick() RETRY TIMEOUT for: "; - std::cerr << *it2; - std::cerr << std::endl; -#endif - /* retry it! */ - retryConnect(*it2); - } - -#endif - -} - - -/******************************** Network Status ********************************* - * Configuration Loading / Saving. - */ - -void p3LinkMgrIMPL::addMonitor(pqiMonitor *mon) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::list::iterator it; - it = std::find(clients.begin(), clients.end(), mon); - if (it != clients.end()) - { - return; - } - - mon->setLinkMgr(this); - clients.push_back(mon); - return; -} - -void p3LinkMgrIMPL::removeMonitor(pqiMonitor *mon) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::list::iterator it; - it = std::find(clients.begin(), clients.end(), mon); - if (it == clients.end()) - { - return; - } - (*it)->setLinkMgr(NULL); - clients.erase(it); - - return; -} - -void p3LinkMgrIMPL::tickMonitors() -{ - bool doStatusChange = false; - std::list actionList; - std::map::iterator it; - - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - if (mStatusChanged) - { -#ifdef LINKMGR_DEBUG_ACTIONS - std::cerr << "p3LinkMgrIMPL::tickMonitors() StatusChanged! List:" << std::endl; -#endif - /* assemble list */ - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (it->second.actions) - { - /* add in */ - pqipeer peer; - peer.id = it->second.id; - peer.name = it->second.name; - peer.state = it->second.state; - peer.actions = it->second.actions; - - /* reset action */ - it->second.actions = 0; - - actionList.push_back(peer); - -#ifdef LINKMGR_DEBUG_ACTIONS - std::cerr << "Friend: " << peer.name << " Id: " << peer.id.toStdString() << " State: " << peer.state; - if (peer.state & RS_PEER_S_FRIEND) - std::cerr << " S:RS_PEER_S_FRIEND"; - if (peer.state & RS_PEER_S_ONLINE) - std::cerr << " S:RS_PEER_S_ONLINE"; - if (peer.state & RS_PEER_S_CONNECTED) - std::cerr << " S:RS_PEER_S_CONNECTED"; - std::cerr << " Actions: " << peer.actions; - if (peer.actions & RS_PEER_NEW) - std::cerr << " A:RS_PEER_NEW"; - if (peer.actions & RS_PEER_MOVED) - std::cerr << " A:RS_PEER_MOVED"; - if (peer.actions & RS_PEER_CONNECTED) - std::cerr << " A:RS_PEER_CONNECTED"; - if (peer.actions & RS_PEER_DISCONNECTED) - std::cerr << " A:RS_PEER_DISCONNECTED"; - if (peer.actions & RS_PEER_CONNECT_REQ) - std::cerr << " A:RS_PEER_CONNECT_REQ"; - - std::cerr << std::endl; -#endif - -// if(peer.actions & RS_PEER_CONNECTED) -// { -// pqiIpAddress ip; -// ip.mAddr = it->second.currentConnAddrAttempt.addr; -// ip.mSeenTime = time(NULL); -// ip.mSrc = time(NULL); -// -// mPeerMgr->updateCurrentAddress(it->second.id,) -// std::cerr << "Peer " << it->second.id << " connected with IP " << sockaddr_storage_tostring(it->second.currentConnAddrAttempt.addr) << std::endl; -// } - - /* notify GUI */ - if (rsEvents && (peer.actions & RS_PEER_CONNECTED)) - { - auto e = std::make_shared(); - e->mConnectionInfoCode = RsConnectionEventCode::PEER_CONNECTED; - e->mSslId = peer.id; - rsEvents->postEvent(e); - } - if (rsEvents && (peer.actions & RS_PEER_DISCONNECTED)) - { - auto e = std::make_shared(); - e->mConnectionInfoCode = RsConnectionEventCode::PEER_DISCONNECTED; - e->mSslId = peer.id; - rsEvents->postEvent(e); - } - } - } - - /* do the Others as well! */ - for(it = mOthersList.begin(); it != mOthersList.end(); ++it) - { - if (it->second.actions) - { - /* add in */ - pqipeer peer; - peer.id = it->second.id; - peer.name = it->second.name; - peer.state = it->second.state; - peer.actions = it->second.actions; - - /* reset action */ - it->second.actions = 0; - -#ifdef LINKMGR_DEBUG_ACTIONS - std::cerr << "Other: " << peer.name << " Id: " << peer.id.toStdString() << " State: " << peer.state; - if (peer.state & RS_PEER_S_FRIEND) - std::cerr << " S:RS_PEER_S_FRIEND"; - if (peer.state & RS_PEER_S_ONLINE) - std::cerr << " S:RS_PEER_S_ONLINE"; - if (peer.state & RS_PEER_S_CONNECTED) - std::cerr << " S:RS_PEER_S_CONNECTED"; - std::cerr << " Actions: " << peer.actions; - if (peer.actions & RS_PEER_NEW) - std::cerr << " A:RS_PEER_NEW"; - if (peer.actions & RS_PEER_MOVED) - std::cerr << " A:RS_PEER_MOVED"; - if (peer.actions & RS_PEER_CONNECTED) - std::cerr << " A:RS_PEER_CONNECTED"; - if (peer.actions & RS_PEER_DISCONNECTED) - std::cerr << " A:RS_PEER_DISCONNECTED"; - if (peer.actions & RS_PEER_CONNECT_REQ) - std::cerr << " A:RS_PEER_CONNECT_REQ"; - - std::cerr << std::endl; -#endif - - actionList.push_back(peer); - } - } - mStatusChanged = false; - doStatusChange = true; - - } - } /****** UNLOCK STACK MUTEX ******/ - - - - - /* NOTE - clients is accessed without mutex protection!!!! - * At the moment this is okay - as they are only added at the start. - * IF this changes ---- must fix with second Mutex. - */ - - if (doStatusChange) - { -#ifdef LINKMGR_DEBUG_ACTIONS - std::cerr << "Sending to " << clients.size() << " monitorClients" << std::endl; -#endif - - /* send to all monitors */ - std::list::iterator mit; - for(mit = clients.begin(); mit != clients.end(); ++mit) - { - (*mit)->statusChange(actionList); - } - } - -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections - - /* notify all monitors */ - std::list::iterator mit; - for(mit = clients.begin(); mit != clients.end(); ++mit) { - (*mit)->statusChanged(); - } - -/////////////////////////////////////////////////////////// -#endif - - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - /* Now Cleanup OthersList (served its purpose (MOVE Action)) */ - mOthersList.clear(); - } - -} - - -const RsPeerId& p3LinkMgrIMPL::getOwnId() -{ - return AuthSSL::getAuthSSL()->OwnId(); -} - - -bool p3LinkMgrIMPL::connectAttempt(const RsPeerId &id, struct sockaddr_storage &raddr, - struct sockaddr_storage &proxyaddr, - struct sockaddr_storage &srcaddr, - uint32_t &delay, uint32_t &period, uint32_t &type, uint32_t &flags, uint32_t &bandwidth, - std::string &domain_addr, uint16_t &domain_port) - -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(id); - if (it == mFriendList.end()) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectAttempt() FAILED Not in FriendList! id: " << id << std::endl; -#endif - - return false; - } - - if (it->second.connAddrs.size() < 1) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectAttempt() FAILED No ConnectAddresses id: " << id << std::endl; -#endif - return false; - } - - - if (it->second.state & RS_PEER_S_CONNECTED) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectAttempt() Already FLAGGED as connected!!!!" << std::endl; - std::cerr << "p3LinkMgrIMPL::connectAttempt() But allowing anyway!!!" << std::endl; -#endif - - rslog(RSL_WARNING, p3connectzone, "p3LinkMgrIMPL::connectAttempt() ERROR ALREADY CONNECTED"); - - } - -#ifdef LINKMGR_DEBUG_LOG - rslog(RSL_WARNING, p3connectzone, "p3LinkMgrIMPL::connectAttempt() called id: " + id.toStdString()); -#endif - - it->second.lastattempt = time(NULL); - it->second.inConnAttempt = true; - it->second.currentConnAddrAttempt = it->second.connAddrs.front(); - it->second.connAddrs.pop_front(); - - raddr = it->second.currentConnAddrAttempt.addr; - delay = it->second.currentConnAddrAttempt.delay; - period = it->second.currentConnAddrAttempt.period; - type = it->second.currentConnAddrAttempt.type; - flags = it->second.currentConnAddrAttempt.flags; - - proxyaddr = it->second.currentConnAddrAttempt.proxyaddr; - srcaddr = it->second.currentConnAddrAttempt.srcaddr; - bandwidth = it->second.currentConnAddrAttempt.bandwidth; - - domain_addr = it->second.currentConnAddrAttempt.domain_addr; - domain_port = it->second.currentConnAddrAttempt.domain_port; - - /********* Setup LinkType parameters **********/ - -#define TRICKLE_LIMIT 2001 // 2kb -#define LOW_BANDWIDTH_LIMIT 5001 // 5kb - -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() Setting up LinkType" << std::endl; - std::cerr << "p3LinkMgrIMPL::connectAttempt() type = " << type << std::endl; -#endif - - it->second.linkType = 0; - if (type & RS_NET_CONN_TCP_ALL) - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() type & TCP_ALL => TCP_UNKNOWN" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_TRANS_TCP_UNKNOWN; - } - else if (type & RS_NET_CONN_UDP_ALL) - { - if (flags & RS_CB_FLAG_MODE_UDP_DIRECT) - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() type & UDP_ALL && flags & DIRECT => UDP_DIRECT" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_TRANS_UDP_DIRECT; - } - else if (flags & RS_CB_FLAG_MODE_UDP_PROXY) - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() type & UDP_ALL && flags & PROXY => UDP_PROXY" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_TRANS_UDP_PROXY; - } - else if (flags & RS_CB_FLAG_MODE_UDP_RELAY) - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() type & UDP_ALL && flags & RELAY => UDP_RELAY" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_TRANS_UDP_RELAY; - } - else - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() type & UDP_ALL && else => UDP_UNKNOWN" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_TRANS_UDP_UNKNOWN; - } - } - else - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() else => TRANS_UNKNOWN" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_TRANS_UNKNOWN; - } - - if ((type & RS_NET_CONN_UDP_ALL) && (flags & RS_CB_FLAG_MODE_UDP_RELAY)) - { - if (bandwidth < TRICKLE_LIMIT) - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() flags & RELAY && band < TRICKLE => SPEED_TRICKLE" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_SPEED_TRICKLE; - } - else if (bandwidth < LOW_BANDWIDTH_LIMIT) - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() flags & RELAY && band < LOW => SPEED_LOW" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_SPEED_LOW; - } - else - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() flags & RELAY && else => SPEED_NORMAL" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_SPEED_NORMAL; - } - } - else - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() else => SPEED_NORMAL" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_SPEED_NORMAL; - } - - uint32_t connType = mPeerMgr->getConnectionType(id); - it->second.linkType |= connType; - -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() connType: " << connType << std::endl; - std::cerr << "p3LinkMgrIMPL::connectAttempt() final LinkType: " << it->second.linkType << std::endl; - - - std::cerr << "p3LinkMgrIMPL::connectAttempt() found an address: id: " << id << std::endl; - std::cerr << " laddr: " << sockaddr_storage_tostring(raddr) << " delay: " << delay << " period: " << period; - std::cerr << " type: " << type << std::endl; - std::cerr << "p3LinkMgrIMPL::connectAttempt() set LinkType to: " << it->second.linkType << std::endl; -#endif - - - /********* Setup LinkType parameters **********/ - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectAttempt() found an address: id: " << id << std::endl; - std::cerr << " laddr: " << sockaddr_storage_tostring(raddr) << " delay: " << delay << " period: " << period; - std::cerr << " type: " << type << std::endl; - std::cerr << "p3LinkMgrIMPL::connectAttempt() set LinkType to: " << it->second.linkType << std::endl; -#endif - if (sockaddr_storage_isnull(raddr)) { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectAttempt() WARNING: address or port is null" << std::endl; - std::cerr << " type: " << type << std::endl; -#endif - } - - return true; -} - - -/**************************** - * Update state, - * trigger retry if necessary, - * - * remove from DHT? - * - */ - -bool p3LinkMgrIMPL::connectResult(const RsPeerId &id, bool success, bool isIncomingConnection, uint32_t flags, const struct sockaddr_storage &remote_peer_address) -{ - bool doDhtAssist = false ; - bool updatePeerAddr = false; - bool updateLastContact = false; - -#ifdef LINKMGR_DEBUG - std::cerr << "Connection result with peer " << id << ": " << success << ". Is incoming: " << isIncomingConnection << ", remote addr: " << sockaddr_storage_tostring(remote_peer_address) << std::endl; -#endif - - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - - if (id == getOwnId()) - { - rslog(RSL_ALERT, p3connectzone, "p3LinkMgrIMPL::connectResult() ERROR Trying to Connect to OwnId: " + id.toStdString()); - - return false; - } - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(id); - if (it == mFriendList.end()) - { - rslog(RSL_ALERT, p3connectzone, "p3LinkMgrIMPL::connectResult() ERROR Missing Friend: " + id.toStdString()); - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() ERROR, missing Friend " << " id: " << id << std::endl; -#endif - return false; - } - - /* now we can tell if we think we were connected - proper point to log */ - - { - std::string out = "p3LinkMgrIMPL::connectResult() id: " + id.toStdString(); - if (success) - { - out += " SUCCESS "; - if (it->second.state & RS_PEER_S_CONNECTED) - { - out += " WARNING: State says: Already Connected"; - } - } - else - { - if (it->second.state & RS_PEER_S_CONNECTED) - { - out += " FAILURE OF THE CONNECTION (Was Connected)"; - } - else - { - out += " FAILED ATTEMPT (Not Connected)"; - } - } -#ifdef LINKMGR_DEBUG_LOG - rslog(RSL_WARNING, p3connectzone, out); -#endif - } - - - - if (success) - { - /* update address (should also come through from DISC) */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Connect!: id: " << id << std::endl; - std::cerr << " Success: " << success << " flags: " << flags << ", remote IP = " << sockaddr_storage_iptostring(remote_peer_address) << std::endl; -#endif - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Connect!: id: " << id << std::endl; - std::cerr << " Success: " << success << " flags: " << flags << std::endl; - - rslog(RSL_WARNING, p3connectzone, "p3LinkMgrIMPL::connectResult() Success"); -#endif - - /* change state */ - it->second.state |= RS_PEER_S_CONNECTED; - it->second.actions |= RS_PEER_CONNECTED; - it->second.connecttype = flags; - it->second.connectaddr = remote_peer_address; - - it->second.actAsServer = isIncomingConnection; - - updateLastContact = true; /* time of connect */ - - /* only update the peer's address if we were in a connect attempt. - * Otherwise, they connected to us, and the address will be a - * random port of their outgoing TCP socket - * - * NB even if we received the connection, the IP address is likely to okay. - */ - - //used to send back to the peer it's own ext address - //it->second.currentserveraddr = remote_peer_address; - - // THIS TEST IS A Bit BAD XXX, we should update their address anyway... - // This means we only update connections that we've made.. so maybe not too bad? - - if ((it->second.inConnAttempt) && - (sockaddr_storage_same(it->second.currentConnAddrAttempt.addr, remote_peer_address))) - { - updatePeerAddr = true; -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() adding current peer address in list." << std::endl; -#endif - } - - /* remove other attempts */ - it->second.inConnAttempt = false; - it->second.connAddrs.clear(); - mStatusChanged = true; - } - else - { -#ifdef LINKMGR_DEBUG_CONNFAIL - std::cerr << "p3LinkMgrIMPL::connectResult() Disconnect/Fail: flags: " << flags << " id: " << id; - std::cerr << std::endl; - - if (it->second.inConnAttempt) - { - std::cerr << "p3LinkMgrIMPL::connectResult() Likely Connect Fail, as inConnAttempt Flag is set"; - std::cerr << std::endl; - } - if (it->second.state & RS_PEER_S_CONNECTED) - { - std::cerr << "p3LinkMgrIMPL::connectResult() Likely DISCONNECT, as state set to Connected"; - std::cerr << std::endl; - } -#endif - - it->second.inConnAttempt = false; - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Disconnect/Fail: id: " << id << std::endl; - std::cerr << " Success: " << success << " flags: " << flags << std::endl; -#endif - - /* if currently connected -> flag as failed */ - if (it->second.state & RS_PEER_S_CONNECTED) - { - it->second.state &= (~RS_PEER_S_CONNECTED); - it->second.actions |= RS_PEER_DISCONNECTED; - mStatusChanged = true; - - updateLastContact = true; /* time of disconnect */ - } - - if (it->second.connAddrs.size() >= 1) - { - it->second.actions |= RS_PEER_CONNECT_REQ; - mStatusChanged = true; - } - - if (it->second.dhtVisible) - { - doDhtAssist = true; - } - } - } - - if (updatePeerAddr) - { - pqiIpAddress raddr; - raddr.mAddr = remote_peer_address; - raddr.mSeenTime = time(NULL); - raddr.mSrc = 0; - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Success and we initiated connection... Updating Address"; - std::cerr << std::endl; -#endif - mPeerMgr->updateCurrentAddress(id, raddr); - } - - if (updateLastContact) - { - mPeerMgr->updateLastContact(id); - } - - - /* inform NetAssist of result. This is slightly duplicating below, as we switch it on/off - * in a second anyway. However, the FAILURE of UDP connection, must be informed. - * - * actually the way the DHT works at the moment, both forms of feedback are required. - * this handles connection requests, the other searches. As they are independent... do both. - */ - - if (flags == RS_NET_CONN_UDP_ALL) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Sending Feedback for UDP connection"; - std::cerr << std::endl; -#endif - if (success) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() UDP Update CONNECTED to: " << id; - std::cerr << std::endl; -#endif - - mNetMgr->netAssistStatusUpdate(id, NETMGR_DHT_FEEDBACK_CONNECTED); - } - else - { -#ifdef LINKMGR_DEBUG - - std::cerr << "p3LinkMgrIMPL::connectResult() UDP Update FAILED to: " << id; - std::cerr << std::endl; -#endif - - /* have no differentiation between failure and closed? */ - mNetMgr->netAssistStatusUpdate(id, NETMGR_DHT_FEEDBACK_CONN_FAILED); - } - } - - - if (success) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Success switching off DhtAssist for friend: " << id; - std::cerr << std::endl; -#endif - /* always switch it off now */ - mNetMgr->netAssistFriend(id,false); - - /* inform NetMgr that we know this peers address: but only if external address */ - if (sockaddr_storage_isExternalNet(remote_peer_address)) - { - mNetMgr->netAssistKnownPeer(id,remote_peer_address, - NETASSIST_KNOWN_PEER_FRIEND | NETASSIST_KNOWN_PEER_ONLINE); - } - } - else - { - if (doDhtAssist) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Fail, Enabling DhtAssist for: " << id; - std::cerr << std::endl; -#endif - mNetMgr->netAssistFriend(id,true) ; - } - else - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Fail, No DhtAssist, as No DHT visibility for: " << id; - std::cerr << std::endl; -#endif - } - - /* inform NetMgr that this peer is offline */ - mNetMgr->netAssistKnownPeer(id,remote_peer_address, NETASSIST_KNOWN_PEER_FRIEND | NETASSIST_KNOWN_PEER_OFFLINE); - } - - return success; -} - -/******************************** Feedback ...... ********************************* - * From various sources - */ - -void p3LinkMgrIMPL::peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs, - uint32_t type, uint32_t flags, uint32_t source) -{ - /* HACKED UP FIX ****/ - - std::map::iterator it; - bool isFriend = true; - - rstime_t now = time(NULL); - - peerAddrInfo details; - details.type = type; - details.found = true; - details.addrs = addrs; - details.ts = now; - - bool updateNetConfig = (source == RS_CB_PERSON); - uint32_t peer_vs_disc = 0; - uint32_t peer_vs_dht = 0; - uint32_t peerNetMode = 0; - - int ownNetMode; - { - peerState ps; - mPeerMgr->getOwnNetStatus(ps); - ownNetMode = ps.netMode; - } - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - { - /* Log */ - std::string out = "p3LinkMgrIMPL::peerStatus() id: " + id.toStdString(); - rs_sprintf_append(out, " type: %lu flags: %lu source: %lu\n", type, flags, source); - addrs.printAddrs(out); - - rslog(RSL_WARNING, p3connectzone, out); -#ifdef LINKMGR_DEBUG - std::cerr << out << std::endl; -#endif - } - - /* look up the id */ - it = mFriendList.find(id); - if (it == mFriendList.end()) - { - /* check Others list */ - isFriend = false; - it = mOthersList.find(id); - if (it == mOthersList.end()) - { - /* not found - ignore */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Peer Not Found - Ignore" << std::endl; -#endif - return; - } -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Peer is in mOthersList" << std::endl; -#endif - } - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Current Peer State:" << std::endl; - printConnectState(std::cerr, it->second); - std::cerr << std::endl; -#endif - - /* update the status */ - - /* if source is DHT */ - if (source == RS_CB_DHT) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Update From DHT:"; - std::cerr << std::endl; -#endif - /* DHT can tell us about - * 1) connect type (UDP/TCP/etc) - * 2) local/external address - */ - it->second.source = RS_CB_DHT; - it->second.dht = details; - - /* If we get a info -> then they are online */ - it->second.state |= RS_PEER_S_ONLINE; - it->second.lastavailable = now; - - } - else if (source == RS_CB_DISC) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Update From DISC:"; - std::cerr << std::endl; -#endif - /* DISC can tell us about - * 1) connect type (UDP/TCP/etc) - * 2) local/external addresses - */ - it->second.source = RS_CB_DISC; - it->second.disc = details; - - - if (flags & RS_NET_FLAGS_ONLINE) - { - it->second.actions |= RS_PEER_ONLINE; - it->second.state |= RS_PEER_S_ONLINE; - it->second.lastavailable = now; - mStatusChanged = true; - } - - } - else if (source == RS_CB_PERSON) - { - /* PERSON can tell us about - * 1) online / offline - * 2) connect address - * -> update all! - */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Update From PERSON:"; - std::cerr << std::endl; -#endif - - it->second.source = RS_CB_PERSON; - it->second.peer = details; - - it->second.state |= RS_PEER_S_ONLINE; - it->second.lastavailable = now; - - /* must be online to recv info (should be connected too!) - * but no need for action as should be connected already - * - * One problem with these states... is that we will never find them via DHT - * if these flags are switched off here... If we get a connection attempt via DHT - * we should switch the DHT search back on. - */ - - peerNetMode = 0; //it->second.netMode &= (~RS_NET_MODE_ACTUAL); /* clear actual flags */ - if (flags & RS_NET_FLAGS_EXTERNAL_ADDR) - { - peerNetMode = RS_NET_MODE_EXT; - } - else if (flags & RS_NET_FLAGS_STABLE_UDP) - { - peerNetMode = RS_NET_MODE_UDP; - } - else - { - peerNetMode = RS_NET_MODE_UNREACHABLE; - } - - - /* always update VIS status */ - if (flags & RS_NET_FLAGS_USE_DISC) - { - peer_vs_disc = RS_VS_DISC_FULL; - } - else - { - peer_vs_disc = RS_VS_DISC_OFF; - } - - if (flags & RS_NET_FLAGS_USE_DHT) - { - peer_vs_dht = RS_VS_DHT_FULL; - } - else - { - peer_vs_dht = RS_VS_DHT_OFF; - } - - - } - - /* Determine Reachability (only advisory) */ - if (ownNetMode & RS_NET_MODE_UDP) - { - if ((details.type & RS_NET_CONN_UDP_DHT_SYNC) || - (details.type & RS_NET_CONN_TCP_EXTERNAL)) - { - /* reachable! */ - it->second.state &= (~RS_PEER_S_UNREACHABLE); - } - else - { - /* unreachable */ - it->second.state |= RS_PEER_S_UNREACHABLE; - } - } - else if (ownNetMode & RS_NET_MODE_UNREACHABLE) - { - if (details.type & RS_NET_CONN_TCP_EXTERNAL) - { - /* reachable! */ - it->second.state &= (~RS_PEER_S_UNREACHABLE); - } - else - { - /* unreachable */ - it->second.state |= RS_PEER_S_UNREACHABLE; - } - } - else - { - it->second.state &= (~RS_PEER_S_UNREACHABLE); - } - - if (!isFriend) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() NOT FRIEND " << " id: " << id << std::endl; -#endif - - { - rslog(RSL_WARNING, p3connectzone, "p3LinkMgrIMPL::peerStatus() NO CONNECT (not friend)"); - } - return; - } - - /* if already connected -> done */ - if (it->second.state & RS_PEER_S_CONNECTED) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() PEER ONLINE ALREADY " << " id: " << id << std::endl; -#endif - { - /* Log */ - rslog(RSL_WARNING, p3connectzone, "p3LinkMgrIMPL::peerStatus() NO CONNECT (already connected!)"); - } - - return; - } - - - } /****** STACK UNLOCK MUTEX *******/ - - bool newAddrs = mPeerMgr->updateAddressList(id, addrs); - if (updateNetConfig) - { - mPeerMgr -> setVisState(id, peer_vs_disc, peer_vs_dht); - mPeerMgr -> setNetworkMode(id, peerNetMode); - } - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus()" << " id: " << id; - std::cerr << " type: " << type << " flags: " << flags; - std::cerr << " source: " << source << std::endl; - std::cerr << " addrs: " << std::endl; - std::string out; - addrs.printAddrs(out); - std::cerr << out << std::endl; - -#endif - -#ifndef P3CONNMGR_NO_AUTO_CONNECTION - -#ifndef P3CONNMGR_NO_TCP_CONNECTIONS - if (newAddrs) - { - retryConnectTCP(id); - } - -#endif // P3CONNMGR_NO_TCP_CONNECTIONS - - -#else -#endif // P3CONNMGR_NO_AUTO_CONNECTION - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Resulting Peer State:" << std::endl; - printConnectState(std::cerr, it->second); - std::cerr << std::endl; -#endif - -} - -/* This has become very unwieldy - as extra arguments are required for UDP connections */ -void p3LinkMgrIMPL::peerConnectRequest( - const RsPeerId& id, const sockaddr_storage &raddr, - const sockaddr_storage &proxyaddr, const sockaddr_storage &srcaddr, - uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth ) -{ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() id: " << id; - std::cerr << " raddr: " << sockaddr_storage_tostring(raddr); - std::cerr << " proxyaddr: " << sockaddr_storage_tostring(proxyaddr); - std::cerr << " srcaddr: " << sockaddr_storage_tostring(srcaddr); - std::cerr << " source: " << source; - std::cerr << " flags: " << flags; - std::cerr << " delay: " << delay; - std::cerr << " bandwidth: " << bandwidth; - std::cerr << std::endl; -#endif - { - /* Log */ - std::string out = "p3LinkMgrIMPL::peerConnectRequest() id: " + id.toStdString(); - out += " raddr: "; - out += sockaddr_storage_tostring(raddr); - out += " proxyaddr: "; - out += sockaddr_storage_tostring(proxyaddr); - out += " srcaddr: "; - out += sockaddr_storage_tostring(srcaddr); - - rs_sprintf_append(out, " source: %lu", source); - rs_sprintf_append(out, " flags: %lu", flags); - rs_sprintf_append(out, " delay: %lu", delay); - rs_sprintf_append(out, " bandwidth: %lu", bandwidth); - - rslog(RSL_WARNING, p3connectzone, out); - } - - /******************** TCP PART *****************************/ - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() (From DHT Only)" << std::endl; -#endif - - if (source == RS_CB_DHT) - { - - if (flags & RS_CB_FLAG_MODE_TCP) - { - -#ifndef P3CONNMGR_NO_TCP_CONNECTIONS - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() DHT says Online ==> so try TCP"; - std::cerr << std::endl; -#endif - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() ERROR Peer is not Friend" << std::endl; -#endif - return; - } - - /* if already connected -> done */ - if (it->second.state & RS_PEER_S_CONNECTED) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() ERROR Peer Already Connected" << std::endl; -#endif - return; - } - /* setup specific attempt for DHT found address. */ - locked_ConnectAttempt_SpecificAddress(&(it->second), raddr); - } - - retryConnect(id); - -#endif - - } - else - { - /* UDP Attempt! */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() DHT says CONNECT ==> tryConnectUDP()"; - std::cerr << std::endl; -#endif - tryConnectUDP(id, raddr, proxyaddr, srcaddr, flags, delay, bandwidth); - - } - return; - - } - else - { // IS THIS USED??? - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() ERROR source OTHER ==> NOOP" << std::endl; - std::cerr << std::endl; - - return; - } -} - - -/*******************************************************************/ -/*******************************************************************/ - /*************** External Control ****************/ -bool p3LinkMgrIMPL::retryConnect(const RsPeerId &id) -{ - /* push all available addresses onto the connect addr stack */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::retryConnect() id: " << id << std::endl; -#endif - -#ifndef P3CONNMGR_NO_TCP_CONNECTIONS - - retryConnectTCP(id); - -#endif // P3CONNMGR_NO_TCP_CONNECTIONS - - return true; -} - - - -bool p3LinkMgrIMPL::tryConnectUDP(const RsPeerId &id, const struct sockaddr_storage &rUdpAddr, - const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr, - uint32_t flags, uint32_t delay, uint32_t bandwidth) - -{ - -#ifdef DISABLE_UDP_CONNECTIONS - - std::cerr << "p3LinkMgrIMPL::tryConnectUDP() CONNECTIONS DISABLED FOR NOW... id: " << id << std::endl; - - std::cerr << "p3LinkMgrIMPL::tryConnectUDP() PARAMS id: " << id; - std::cerr << " raddr: " << rs_inet_ntoa(rUdpAddr.sin_addr) << ":" << ntohs(rUdpAddr.sin_port); - std::cerr << " proxyaddr: " << rs_inet_ntoa(proxyaddr.sin_addr) << ":" << ntohs(proxyaddr.sin_port); - std::cerr << " srcaddr: " << rs_inet_ntoa(srcaddr.sin_addr) << ":" << ntohs(srcaddr.sin_port); - std::cerr << " flags: " << flags; - std::cerr << " delay: " << delay; - std::cerr << " bandwidth: " << bandwidth; - std::cerr << std::endl; - - mNetMgr->netAssistStatusUpdate(id, NETMGR_DHT_FEEDBACK_CONN_FAILED); - - return false; -#endif - - if (mPeerMgr->isHidden()) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::tryConnectUDP() isHidden(): no connection attempts for : " << id; - std::cerr << std::endl; -#endif - return false; - } - - - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - /* push all available addresses onto the connect addr stack */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::tryConnectUDP() id: " << id << std::endl; -#endif - - if (id == getOwnId()) { - #ifdef LINKMGR_DEBUG - rslog(RSL_WARNING, p3connectzone, "p3LinkMgrIMPL::retryConnectUDP() Failed, connecting to own id: "); - #endif - return false; - } - - /* look up the id */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::retryConnectUDP() Peer is not Friend" << std::endl; -#endif - return false; - } - - /* if already connected -> done */ - if (it->second.state & RS_PEER_S_CONNECTED) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::retryConnectUDP() Peer Already Connected" << std::endl; -#endif - return false; - } - - /* Explicit Request to start the UDP connection */ - if (sockaddr_storage_isValidNet(rUdpAddr)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "Adding udp connection attempt: "; - std::cerr << "Addr: " << sockaddr_storage_tostring(rUdpAddr); - std::cerr << std::endl; -#endif - peerConnectAddress pca; - pca.addr = rUdpAddr; - pca.type = RS_NET_CONN_UDP_PEER_SYNC; - pca.delay = delay; - pca.ts = time(NULL); - pca.period = P3CONNMGR_UDP_DEFAULT_PERIOD; - pca.flags = flags; - - pca.proxyaddr = proxyaddr; - pca.srcaddr = srcaddr; - pca.bandwidth = bandwidth; - - // Push address to the front... so it happens quickly (before any timings are lost). - addAddressIfUnique(it->second.connAddrs, pca, true); - } - - /* finish it off */ - return locked_ConnectAttempt_Complete(&(it->second)); -} - - - - -/* push all available addresses onto the connect addr stack... - * with the following exceptions: - * - id is our own - * - id is not our friend - * - id is already connected - * - id is hidden but of an unkown type - * - we are hidden but id is not - */ -bool p3LinkMgrIMPL::retryConnectTCP(const RsPeerId &id) -{ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::retryConnectTCP() id: " << id << std::endl; -#endif - - if (id == getOwnId()) return false; - - { - RS_STACK_MUTEX(mLinkMtx); - std::map::iterator it = mFriendList.find(id); - if ( it == mFriendList.end() ) return false; - if ( it->second.state & RS_PEER_S_CONNECTED ) return false; - } - - // Extract the required info from p3PeerMgr - - // first possibility - is it a hidden peer - if (mPeerMgr->isHiddenPeer(id)) - { - /* check for valid hidden type */ - uint32_t type = mPeerMgr->getHiddenType(id); - if ( type & (~RS_HIDDEN_TYPE_MASK) ) return false; - - /* then we just have one connect attempt via the Proxy */ - struct sockaddr_storage proxy_addr; - std::string domain_addr; - uint16_t domain_port; - if ( mPeerMgr->getProxyAddress(id, proxy_addr, domain_addr, domain_port) ) - { - RS_STACK_MUTEX(mLinkMtx); - std::map::iterator it = mFriendList.find(id); - if (it != mFriendList.end()) - { - locked_ConnectAttempt_ProxyAddress(&(it->second), type, proxy_addr, domain_addr, domain_port); - return locked_ConnectAttempt_Complete(&(it->second)); - } - } - - return false; - } - - if (mPeerMgr->isHidden()) return false; - - struct sockaddr_storage lAddr; - struct sockaddr_storage eAddr; - pqiIpAddrSet histAddrs; - std::string dyndns; - if (mPeerMgr->getConnectAddresses(id, lAddr, eAddr, histAddrs, dyndns)) - { - RS_STACK_MUTEX(mLinkMtx); - - std::map::iterator it = mFriendList.find(id); - if ( it != mFriendList.end() ) - { - locked_ConnectAttempt_CurrentAddresses(&(it->second), lAddr, eAddr); - - uint16_t dynPort = 0; - if (!sockaddr_storage_isnull(eAddr)) dynPort = sockaddr_storage_port(eAddr); - if (!dynPort && !sockaddr_storage_isnull(lAddr)) - dynPort = sockaddr_storage_port(lAddr); - if (dynPort) - locked_ConnectAttempt_AddDynDNS(&(it->second), dyndns, dynPort); - - locked_ConnectAttempt_HistoricalAddresses(&(it->second), histAddrs); - - // finish it off - return locked_ConnectAttempt_Complete(&(it->second)); - } - else - std::cerr << "p3LinkMgrIMPL::retryConnectTCP() ERROR failed to find friend data : " << id << std::endl; - } - else - std::cerr << "p3LinkMgrIMPL::retryConnectTCP() ERROR failed to get addresses from PeerMgr for: " << id << std::endl; - - return false; -} - -bool p3LinkMgrIMPL::locked_CheckPotentialAddr(const sockaddr_storage& addr) -{ - /* if invalid - quick rejection */ - if ( ! sockaddr_storage_isValidNet(addr) ) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_CheckPotentialAddr() REJECTING - INVALID"; - std::cerr << std::endl; -#endif - return false; - } - - std::list::const_iterator it; - for(it = mBannedIpList.begin(); it != mBannedIpList.end(); ++it) - { -#ifdef LINKMGR_DEBUG - std::cerr << "Checking IP w.r.t. banned IP " << sockaddr_storage_iptostring(*it) << std::endl; -#endif - - if (sockaddr_storage_sameip(*it, addr)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_CheckPotentialAddr() REJECTING - ON BANNED IPLIST"; - std::cerr << std::endl; -#endif - return false; - } - } - - if(rsBanList != NULL && !rsBanList->isAddressAccepted(addr, RSBANLIST_CHECKING_FLAGS_BLACKLIST)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_CheckPotentialAddr() adding to local Banned IPList"; - std::cerr << std::endl; -#endif - return false ; - } - - return true; -} - - -void p3LinkMgrIMPL::locked_ConnectAttempt_SpecificAddress(peerConnectState *peer, const struct sockaddr_storage &remoteAddr) -{ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_SpecificAddresses()"; - std::cerr << std::endl; -#endif - if(locked_CheckPotentialAddr(remoteAddr)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_SpecificAddresses() "; - std::cerr << "Adding tcp connection attempt: "; - std::cerr << "Addr: " << sockaddr_storage_tostring(remoteAddr); - std::cerr << std::endl; -#endif - peerConnectAddress pca; - pca.addr = remoteAddr; - pca.type = RS_NET_CONN_TCP_EXTERNAL; - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - addAddressIfUnique(peer->connAddrs, pca, false); - } -} - - -void p3LinkMgrIMPL::locked_ConnectAttempt_CurrentAddresses(peerConnectState *peer, const struct sockaddr_storage &localAddr, const struct sockaddr_storage &serverAddr) -{ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_CurrentAddresses()"; - std::cerr << std::endl; -#endif - // Just push all the addresses onto the stack. - /* try "current addresses" first */ - if (locked_CheckPotentialAddr(localAddr)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_CurrentAddresses() "; - std::cerr << "Adding tcp connection attempt: "; - std::cerr << "Current Local Addr: " << sockaddr_storage_tostring(localAddr); - std::cerr << std::endl; -#endif - peerConnectAddress pca; - pca.addr = localAddr; - pca.type = RS_NET_CONN_TCP_LOCAL; - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - addAddressIfUnique(peer->connAddrs, pca, false); - } - - if (locked_CheckPotentialAddr(serverAddr)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_CurrentAddresses() "; - std::cerr << "Adding tcp connection attempt: "; - std::cerr << "Current Ext Addr: " << sockaddr_storage_tostring(serverAddr); - std::cerr << std::endl; -#endif - peerConnectAddress pca; - pca.addr = serverAddr; - pca.type = RS_NET_CONN_TCP_EXTERNAL; - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - addAddressIfUnique(peer->connAddrs, pca, false); - } -} - - -void p3LinkMgrIMPL::locked_ConnectAttempt_HistoricalAddresses(peerConnectState *peer, const pqiIpAddrSet &ipAddrs) -{ - /* now try historical addresses */ - /* try local addresses first */ - std::list::const_iterator ait; - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_HistoricalAddresses()"; - std::cerr << std::endl; -#endif - for(ait = ipAddrs.mLocal.mAddrs.begin(); ait != ipAddrs.mLocal.mAddrs.end(); ++ait) - { - if (locked_CheckPotentialAddr(ait->mAddr)) - { - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_HistoricalAddresses() "; - std::cerr << "Adding tcp connection attempt: "; - std::cerr << "Local Addr: " << sockaddr_storage_tostring(ait->mAddr); - std::cerr << std::endl; -#endif - - peerConnectAddress pca; - pca.addr = ait->mAddr; - pca.type = RS_NET_CONN_TCP_LOCAL; - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - addAddressIfUnique(peer->connAddrs, pca, false); - } - } - - for(ait = ipAddrs.mExt.mAddrs.begin(); - ait != ipAddrs.mExt.mAddrs.end(); ++ait) - { - if (locked_CheckPotentialAddr(ait->mAddr)) - { - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_HistoricalAddresses() "; - std::cerr << "Adding tcp connection attempt: "; - std::cerr << "Ext Addr: " << sockaddr_storage_tostring(ait->mAddr); - std::cerr << std::endl; -#endif - peerConnectAddress pca; - pca.addr = ait->mAddr; - pca.type = RS_NET_CONN_TCP_EXTERNAL; - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - addAddressIfUnique(peer->connAddrs, pca, false); - } - } -} - - -void p3LinkMgrIMPL::locked_ConnectAttempt_AddDynDNS(peerConnectState *peer, std::string dyndns, uint16_t port) -{ - /* try dyndns address too */ - struct sockaddr_storage addr; - if (!dyndns.empty() && port) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_AddDynDNS() Looking up DynDNS address: " << dyndns << std::endl; -#endif - if(mDNSResolver->getIPAddressFromString(dyndns, addr)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_AddDynDNS() "; - std::cerr << "Adding tcp connection attempt: "; - std::cerr << "DynDNS Addr: " << sockaddr_storage_iptostring(addr); - std::cerr << ":" << port; - std::cerr << std::endl; -#endif - peerConnectAddress pca; - sockaddr_storage_copyip(pca.addr, addr); - sockaddr_storage_setport(pca.addr, port); - pca.type = RS_NET_CONN_TCP_EXTERNAL; - //for the delay, we add a random time and some more time when the friend list is big - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - /* check address validity */ - if (locked_CheckPotentialAddr(pca.addr)) - { - addAddressIfUnique(peer->connAddrs, pca, true); - } - } - else - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_AddDynDNS() DNSResolver hasn't found addr yet"; - std::cerr << std::endl; -#endif - } - } - else - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_AddDynDNS() Address(" << dyndns << ") or Port(" << port << ") NULL ignoring"; - std::cerr << std::endl; -#endif - } -} - - -void p3LinkMgrIMPL::locked_ConnectAttempt_ProxyAddress(peerConnectState *peer, const uint32_t type, const struct sockaddr_storage &proxy_addr, const std::string &domain_addr, uint16_t domain_port) -{ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_ProxyAddress() trying address: " << domain_addr << ":" << domain_port << std::endl; -#endif - peerConnectAddress pca; - pca.addr = proxy_addr; - - switch (type) { - case RS_HIDDEN_TYPE_TOR: - pca.type = RS_NET_CONN_TCP_HIDDEN_TOR; - break; - case RS_HIDDEN_TYPE_I2P: - pca.type = RS_NET_CONN_TCP_HIDDEN_I2P; - break; - case RS_HIDDEN_TYPE_UNKNOWN: - default: - /**** THIS CASE SHOULD NOT BE TRIGGERED - since this function is called with a valid hidden type only ****/ - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_ProxyAddress() hidden type of addr: " << domain_addr << " is unkown -> THIS SHOULD NEVER HAPPEN!" << std::endl; - std::cerr << " - peer : " << peer->id << "(" << peer->name << ")" << std::endl; - std::cerr << " - proxy: " << sockaddr_storage_tostring(proxy_addr) << std::endl; - std::cerr << " - addr : " << domain_addr << ":" << domain_port << std::endl; - pca.type = RS_NET_CONN_TCP_UNKNOW_TOPOLOGY; - } - - //for the delay, we add a random time and some more time when the friend list is big - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - pca.domain_addr = domain_addr; - pca.domain_port = domain_port; - - /* check address validity */ - if (locked_CheckPotentialAddr(pca.addr)) - { - addAddressIfUnique(peer->connAddrs, pca, true); - } -} - - -bool p3LinkMgrIMPL::addAddressIfUnique(std::list &addrList, peerConnectAddress &pca, bool pushFront) -{ - /* iterate through the list, and make sure it isn't already - * in the list - */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::addAddressIfUnique() Checking Address: " << sockaddr_storage_iptostring(pca.addr); - std::cerr << std::endl; -#endif - - std::list::iterator it; - for(it = addrList.begin(); it != addrList.end(); ++it) - { - if (sockaddr_storage_same(pca.addr, it->addr) && - (pca.type == it->type)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::addAddressIfUnique() Discarding Duplicate Address"; - std::cerr << std::endl; -#endif - /* already */ - return false; - } - } - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::addAddressIfUnique() Adding New Address"; - std::cerr << std::endl; -#endif - - if (pushFront) - { - addrList.push_front(pca); - } - else - { - addrList.push_back(pca); - } - - return true; -} - - - -bool p3LinkMgrIMPL::locked_ConnectAttempt_Complete(peerConnectState *peer) -{ - - /* flag as last attempt to prevent loop */ - //add a random perturbation between 0 and 2 sec. - peer->lastattempt = time(NULL) + rand() % MAX_RANDOM_ATTEMPT_OFFSET; - - if (peer->inConnAttempt) - { - /* -> it'll automatically use the addresses we added */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_Complete() Already in CONNECT ATTEMPT"; - std::cerr << std::endl; - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_Complete() Remaining ConnAddr Count: " << peer->connAddrs.size(); - std::cerr << std::endl; -#endif - return true; - } - - /* start a connection attempt */ - if (peer->connAddrs.size() > 0) - { -#ifdef LINKMGR_DEBUG - std::string out = "p3LinkMgrIMPL::locked_ConnectAttempt_Complete() Started CONNECT ATTEMPT!\n" ; - rs_sprintf_append(out, "p3LinkMgrIMPL::locked_ConnectAttempt_Complete() ConnAddr Count: %u", peer->connAddrs.size()); - rslog(RSL_DEBUG_ALERT, p3connectzone, out); - std::cerr << out << std::endl; -#endif - - peer->actions |= RS_PEER_CONNECT_REQ; - mStatusChanged = true; - return true; - } - else - { -#ifdef LINKMGR_DEBUG - std::string out = "p3LinkMgrIMPL::locked_ConnectAttempt_Complete() No addr in the connect attempt list. Not suitable for CONNECT ATTEMPT!"; - rslog(RSL_DEBUG_ALERT, p3connectzone, out); - std::cerr << out << std::endl; -#endif - return false; - } - return false; -} - - -/*********************************************************************************************************** - ************************************* Handling of Friends ************************************************* - ***********************************************************************************************************/ - -int p3LinkMgrIMPL::addFriend(const RsPeerId &id, bool isVisible) -{ -#ifdef LINKMGR_DEBUG_LOG - rslog(RSL_WARNING, p3connectzone, "p3LinkMgr::addFriend() id: " + id.toStdString()); -#endif - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::addFriend(" << id << "," << isVisible << ")"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mFriendList.find(id); - - if (it != mFriendList.end()) - { - std::cerr << "p3LinkMgrIMPL::addFriend() ERROR, friend already exists : " << id; - std::cerr << std::endl; - return 0; - } - - peerConnectState pcs; - pcs.dhtVisible = isVisible; - pcs.id = id; - pcs.name = "NoName"; - pcs.state = RS_PEER_S_FRIEND; - pcs.actions = RS_PEER_NEW; - pcs.linkType = RS_NET_CONN_SPEED_UNKNOWN ; - - mFriendList[id] = pcs; - - mStatusChanged = true; - } - - mNetMgr->netAssistFriend(id, isVisible); - - return 1; -} - - -int p3LinkMgrIMPL::removeFriend(const RsPeerId &id) -{ - rslog(RSL_WARNING, p3connectzone, "p3LinkMgr::removeFriend() id: " + id.toStdString()); - - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - #ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::removeFriend(" << id << ")"; - std::cerr << std::endl; - #endif - - std::map::iterator it; - it = mFriendList.find(id); - - if (it == mFriendList.end()) - { - std::cerr << "p3LinkMgrIMPL::removeFriend() ERROR, friend not there : " << id; - std::cerr << std::endl; - return 0; - } - - /* Move to OthersList (so remove can be handled via the action) */ - peerConnectState peer = it->second; - - peer.state &= (~RS_PEER_S_FRIEND); - peer.state &= (~RS_PEER_S_CONNECTED); - peer.state &= (~RS_PEER_S_ONLINE); - peer.actions = RS_PEER_MOVED; - peer.inConnAttempt = false; - mOthersList[id] = peer; - - mStatusChanged = true; - - mFriendList.erase(it); - } - - mNetMgr->netAssistFriend(id, false); - - return 1; -} - -void p3LinkMgrIMPL::disconnectFriend(const RsPeerId& id) -{ - std::list disconnect_clients ; - - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - disconnect_clients = clients ; - - std::cerr << "Disconnecting friend " << id << std::endl; - - std::map::iterator it; - it = mFriendList.find(id); - - if (it == mFriendList.end()) - { - std::cerr << "p3LinkMgrIMPL::removeFriend() ERROR, friend not there : " << id; - std::cerr << std::endl; - return ; - } - - /* Move to OthersList (so remove can be handled via the action) */ - peerConnectState peer = it->second; - - peer.state &= (~RS_PEER_S_CONNECTED); - peer.state &= (~RS_PEER_S_ONLINE); - peer.actions = RS_PEER_DISCONNECTED; - peer.inConnAttempt = false; - } - - for(std::list::const_iterator it(disconnect_clients.begin());it!=disconnect_clients.end();++it) - (*it)->disconnectPeer(id) ; -} - -void p3LinkMgrIMPL::printPeerLists(std::ostream &out) -{ - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - out << "p3LinkMgrIMPL::printPeerLists() Friend List"; - out << std::endl; - - - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - out << "\t SSL ID: " << it->second.id.toStdString(); - out << "\t State: " << it->second.state; - out << std::endl; - } - - out << "p3LinkMgrIMPL::printPeerLists() Others List"; - out << std::endl; - for(it = mOthersList.begin(); it != mOthersList.end(); ++it) - { - out << "\t SSL ID: " << it->second.id.toStdString(); - out << "\t State: " << it->second.state; - } - } - - return; -} - -bool p3LinkMgrIMPL::checkPotentialAddr(const sockaddr_storage& addr) -{ - RS_STACK_MUTEX(mLinkMtx); - return locked_CheckPotentialAddr(addr); -} - - -void printConnectState(std::ostream &out, peerConnectState &peer) -{ - - out << "Friend: " << peer.name << " Id: " << peer.id.toStdString() << " State: " << peer.state; - if (peer.state & RS_PEER_S_FRIEND) - out << " S:RS_PEER_S_FRIEND"; - if (peer.state & RS_PEER_S_ONLINE) - out << " S:RS_PEER_S_ONLINE"; - if (peer.state & RS_PEER_S_CONNECTED) - out << " S:RS_PEER_S_CONNECTED"; - out << " Actions: " << peer.actions; - if (peer.actions & RS_PEER_NEW) - out << " A:RS_PEER_NEW"; - if (peer.actions & RS_PEER_MOVED) - out << " A:RS_PEER_MOVED"; - if (peer.actions & RS_PEER_CONNECTED) - out << " A:RS_PEER_CONNECTED"; - if (peer.actions & RS_PEER_DISCONNECTED) - out << " A:RS_PEER_DISCONNECTED"; - if (peer.actions & RS_PEER_CONNECT_REQ) - out << " A:RS_PEER_CONNECT_REQ"; - - out << std::endl; - return; -} - - - diff --git a/libretroshare/src/pqi/p3linkmgr.h b/libretroshare/src/pqi/p3linkmgr.h deleted file mode 100644 index 3b2c5c638..000000000 --- a/libretroshare/src/pqi/p3linkmgr.h +++ /dev/null @@ -1,340 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3linkmgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_LINK_MANAGER_HEADER -#define MRK_PQI_LINK_MANAGER_HEADER - -#include "pqi/pqimonitor.h" -#include "pqi/pqiipset.h" -#include "util/rstime.h" -#include "pqi/pqiassist.h" - -#include "pqi/p3cfgmgr.h" - -#include "util/rsthreads.h" - -class ExtAddrFinder ; -class DNSResolver ; - - -/* order of attempts ... */ -const uint32_t RS_NET_CONN_TCP_ALL = 0x00ff; -const uint32_t RS_NET_CONN_UDP_ALL = 0x0f00; - -const uint32_t RS_NET_CONN_TCP_LOCAL = 0x0001; -const uint32_t RS_NET_CONN_TCP_EXTERNAL = 0x0002; -const uint32_t RS_NET_CONN_TCP_UNKNOW_TOPOLOGY = 0x0004; -const uint32_t RS_NET_CONN_TCP_HIDDEN_TOR = 0x0008; -const uint32_t RS_NET_CONN_TCP_HIDDEN_I2P = 0x0010; - -const uint32_t RS_NET_CONN_UDP_DHT_SYNC = 0x0100; -const uint32_t RS_NET_CONN_UDP_PEER_SYNC = 0x0200; /* coming soon */ - -// These are set in pqipersongroup. -const uint32_t RS_TCP_STD_TIMEOUT_PERIOD = 5; /* 5 seconds! */ -const uint32_t RS_TCP_HIDDEN_TIMEOUT_PERIOD = 30; /* 30 seconds! */ -const uint32_t RS_UDP_STD_TIMEOUT_PERIOD = 80; /* 80 secs, allows UDP TTL to get to 40! - Plenty of time (30+80) = 110 secs */ - -class peerAddrInfo -{ - public: - peerAddrInfo(); /* init */ - - bool found; - uint32_t type; - pqiIpAddrSet addrs; - rstime_t ts; -}; - -class peerConnectAddress -{ - public: - peerConnectAddress(); /* init */ - - struct sockaddr_storage addr; - uint32_t delay; /* to stop simultaneous connects */ - uint32_t period; /* UDP only */ - uint32_t type; - uint32_t flags; /* CB FLAGS defined in pqimonitor.h */ - rstime_t ts; - - // Extra Parameters for Relay connections. - struct sockaddr_storage proxyaddr; - struct sockaddr_storage srcaddr; - uint32_t bandwidth; - - // Extra Parameters for Proxy/Hidden connection. - std::string domain_addr; - uint16_t domain_port; -}; - -class peerConnectState -{ - public: - peerConnectState(); /* init */ - - RsPeerId id; - - /***** Below here not stored permanently *****/ - - bool dhtVisible; - - uint32_t connecttype; // RS_NET_CONN_TCP_ALL / RS_NET_CONN_UDP_ALL - bool actAsServer; - rstime_t lastavailable; - rstime_t lastattempt; - - std::string name; - - uint32_t state; - uint32_t actions; - uint32_t linkType; - - uint32_t source; /* most current source */ - peerAddrInfo dht; - peerAddrInfo disc; - peerAddrInfo peer; - - struct sockaddr_storage connectaddr; // current connection address. Can be local or external. - - /* a list of connect attempts to make (in order) */ - bool inConnAttempt; - peerConnectAddress currentConnAddrAttempt; - std::list connAddrs; - - /* information about denial */ - bool wasDeniedConnection; - rstime_t deniedTS; - bool deniedInConnAttempt; /* is below valid */ - peerConnectAddress deniedConnectionAttempt; -}; - -class p3tunnel; -class RsPeerGroupItem_deprecated; -struct RsGroupInfo; - -class p3PeerMgr; -class p3NetMgr; - -class p3PeerMgrIMPL; -class p3NetMgrIMPL; - -std::string textPeerConnectState(peerConnectState &state); - -/******* - * Virtual Interface to allow testing - * - */ - -class p3LinkMgr: public pqiConnectCb -{ - public: - - p3LinkMgr() { return; } -virtual ~p3LinkMgr() { return; } - - -virtual const RsPeerId& getOwnId() = 0; -virtual bool isOnline(const RsPeerId &ssl_id) = 0; -virtual void getOnlineList(std::list &ssl_peers) = 0; -virtual bool getPeerName(const RsPeerId &ssl_id, std::string &name) = 0; -virtual uint32_t getLinkType(const RsPeerId &ssl_id) = 0; - - /**************** handle monitors *****************/ -virtual void addMonitor(pqiMonitor *mon) = 0; -virtual void removeMonitor(pqiMonitor *mon) = 0; - - /****************** Connections *******************/ -virtual bool connectAttempt(const RsPeerId &id, struct sockaddr_storage &raddr, - struct sockaddr_storage &proxyaddr, struct sockaddr_storage &srcaddr, - uint32_t &delay, uint32_t &period, uint32_t &type, uint32_t &flags, uint32_t &bandwidth, - std::string &domain_addr, uint16_t &domain_port) = 0; - -virtual bool connectResult(const RsPeerId &id, bool success, bool isIncomingConnection, uint32_t flags, const struct sockaddr_storage &remote_peer_address) = 0; -virtual bool retryConnect(const RsPeerId &id) = 0; - - /* Network Addresses */ -virtual bool setLocalAddress(const struct sockaddr_storage &addr) = 0; -virtual bool getLocalAddress(struct sockaddr_storage &addr) = 0; - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ - -virtual void getFriendList(std::list &ssl_peers) = 0; // ONLY used by p3peers.cc USE p3PeerMgr instead. -virtual bool getFriendNetStatus(const RsPeerId &id, peerConnectState &state) = 0; // ONLY used by p3peers.cc - - virtual bool checkPotentialAddr(const sockaddr_storage& addr) = 0; - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ -virtual int addFriend(const RsPeerId &ssl_id, bool isVisible) = 0; - /******* overloaded from pqiConnectCb *************/ -// THESE MUSTn't BE specfied HERE - as overloaded from pqiConnectCb. -//virtual void peerStatus(std::string id, const pqiIpAddrSet &addrs, -// uint32_t type, uint32_t flags, uint32_t source) = 0; -//virtual void peerConnectRequest(std::string id, const struct sockaddr_storage &raddr, -// const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr, -// uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth) = 0; - -/****************************************************************************/ -/****************************************************************************/ -/****************************************************************************/ - -}; - - - -class p3LinkMgrIMPL: public p3LinkMgr -{ - public: - -/************************************************************************************************/ -/* EXTERNAL INTERFACE */ -/************************************************************************************************/ - -virtual const RsPeerId& getOwnId(); -virtual bool isOnline(const RsPeerId &ssl_id); -virtual void getOnlineList(std::list &ssl_peers); -virtual bool getPeerName(const RsPeerId &ssl_id, std::string &name); -virtual uint32_t getLinkType(const RsPeerId &ssl_id); - - - /**************** handle monitors *****************/ -virtual void addMonitor(pqiMonitor *mon); -virtual void removeMonitor(pqiMonitor *mon); - - /****************** Connections *******************/ -virtual bool connectAttempt(const RsPeerId &id, struct sockaddr_storage &raddr, - struct sockaddr_storage &proxyaddr, struct sockaddr_storage &srcaddr, - uint32_t &delay, uint32_t &period, uint32_t &type, uint32_t &flags, uint32_t &bandwidth, - std::string &domain_addr, uint16_t &domain_port); - -virtual bool connectResult(const RsPeerId &id, bool success, bool isIncomingConnection, uint32_t flags, const struct sockaddr_storage &remote_peer_address); -virtual bool retryConnect(const RsPeerId &id); - - /* Network Addresses */ -virtual bool setLocalAddress(const struct sockaddr_storage &addr); -virtual bool getLocalAddress(struct sockaddr_storage &addr); - - /******* overloaded from pqiConnectCb *************/ -virtual void peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs, - uint32_t type, uint32_t flags, uint32_t source); -virtual void peerConnectRequest(const RsPeerId& id, const struct sockaddr_storage &raddr, - const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr, - uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth); - - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ - -virtual void getFriendList(std::list &ssl_peers); // ONLY used by p3peers.cc USE p3PeerMgr instead. -virtual bool getFriendNetStatus(const RsPeerId &id, peerConnectState &state); // ONLY used by p3peers.cc - -/************************************************************************************************/ -/* Extra IMPL Functions (used by p3PeerMgr, p3NetMgr + Setup) */ -/************************************************************************************************/ - - p3LinkMgrIMPL(p3PeerMgrIMPL *peerMgr, p3NetMgrIMPL *netMgr); - virtual ~p3LinkMgrIMPL(); - -void tick(); - - /* THIS COULD BE ADDED TO INTERFACE */ -void setFriendVisibility(const RsPeerId &id, bool isVisible); - - void disconnectFriend(const RsPeerId& id) ; - - /* add/remove friends */ -virtual int addFriend(const RsPeerId &ssl_id, bool isVisible); -int removeFriend(const RsPeerId &ssl_id); - -void printPeerLists(std::ostream &out); - - virtual bool checkPotentialAddr(const sockaddr_storage& addr); - -protected: - /* THESE CAN PROBABLY BE REMOVED */ -//bool shutdown(); /* blocking shutdown call */ -//bool getOwnNetStatus(peerConnectState &state); - - -protected: - /****************** Internal Interface *******************/ - - /* Internal Functions */ -void statusTick(); - - /* monitor control */ -void tickMonitors(); - - /* connect attempts UDP */ -bool tryConnectUDP(const RsPeerId &id, const struct sockaddr_storage &rUdpAddr, - const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr, - uint32_t flags, uint32_t delay, uint32_t bandwidth); - - /* connect attempts TCP */ -bool retryConnectTCP(const RsPeerId &id); - -void locked_ConnectAttempt_SpecificAddress(peerConnectState *peer, const struct sockaddr_storage &remoteAddr); -void locked_ConnectAttempt_CurrentAddresses(peerConnectState *peer, const struct sockaddr_storage &localAddr, const struct sockaddr_storage &serverAddr); -void locked_ConnectAttempt_HistoricalAddresses(peerConnectState *peer, const pqiIpAddrSet &ipAddrs); -void locked_ConnectAttempt_AddDynDNS(peerConnectState *peer, std::string dyndns, uint16_t dynPort); -void locked_ConnectAttempt_AddTunnel(peerConnectState *peer); -void locked_ConnectAttempt_ProxyAddress(peerConnectState *peer, const uint32_t type, const struct sockaddr_storage &proxy_addr, const std::string &domain_addr, uint16_t domain_port); - -bool locked_ConnectAttempt_Complete(peerConnectState *peer); - - bool locked_CheckPotentialAddr(const sockaddr_storage& addr); - -bool addAddressIfUnique(std::list &addrList, peerConnectAddress &pca, bool pushFront); - - -private: - // These should have their own Mutex Protection, - //p3tunnel *mP3tunnel; - DNSResolver *mDNSResolver ; - - p3PeerMgrIMPL *mPeerMgr; - p3NetMgrIMPL *mNetMgr; - - RsMutex mLinkMtx; /* protects below */ - - uint32_t mRetryPeriod; - - bool mStatusChanged; - - struct sockaddr_storage mLocalAddress; - - std::list clients; - - bool mAllowTunnelConnection; - - /* external Address determination */ - //bool mUpnpAddrValid, mStunAddrValid; - //struct sockaddr_in mUpnpExtAddr; - - //peerConnectState mOwnState; - - std::map mFriendList; - std::map mOthersList; - - /* relatively static list of banned ip addresses */ - std::list mBannedIpList; -}; - -#endif // MRK_PQI_LINK_MANAGER_HEADER diff --git a/libretroshare/src/pqi/p3netmgr.cc b/libretroshare/src/pqi/p3netmgr.cc deleted file mode 100644 index 32b413e7b..000000000 --- a/libretroshare/src/pqi/p3netmgr.cc +++ /dev/null @@ -1,2036 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3netmgr.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2011 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#include "util/rstime.h" -#include - -#include "pqi/p3netmgr.h" - -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" - -#include "util/rsnet.h" -#include "util/rsrandom.h" -#include "util/rsdebug.h" - -#include "util/extaddrfinder.h" -#include "util/dnsresolver.h" - - -struct RsLog::logInfo p3netmgrzoneInfo = {RsLog::Default, "p3netmgr"}; -#define p3netmgrzone &p3netmgrzoneInfo - -#include "rsitems/rsconfigitems.h" - -#include "retroshare/rsiface.h" -#include "retroshare/rsconfig.h" -#include "retroshare/rsbanlist.h" - -/* Network setup States */ - -const uint32_t RS_NET_NEEDS_RESET = 0x0000; -const uint32_t RS_NET_UNKNOWN = 0x0001; -const uint32_t RS_NET_UPNP_INIT = 0x0002; -const uint32_t RS_NET_UPNP_SETUP = 0x0003; -const uint32_t RS_NET_EXT_SETUP = 0x0004; -const uint32_t RS_NET_DONE = 0x0005; -const uint32_t RS_NET_LOOPBACK = 0x0006; -//const uint32_t RS_NET_DOWN = 0x0007; - -/* Stun modes (TODO) */ -//const uint32_t RS_STUN_DHT = 0x0001; -//const uint32_t RS_STUN_DONE = 0x0002; -//const uint32_t RS_STUN_LIST_MIN = 100; -//const uint32_t RS_STUN_FOUND_MIN = 10; - -const uint32_t MAX_UPNP_INIT = 60; /* seconds UPnP timeout */ -const uint32_t MAX_UPNP_COMPLETE = 600; /* 10 min... seems to take a while */ -//const uint32_t MAX_NETWORK_INIT = 70; /* timeout before network reset */ - -//const uint32_t MIN_TIME_BETWEEN_NET_RESET = 5; - -/**** - * #define NETMGR_DEBUG 1 - * #define NETMGR_DEBUG_RESET 1 - * #define NETMGR_DEBUG_TICK 1 - * #define NETMGR_DEBUG_STATEBOX 1 - ***/ -// #define NETMGR_DEBUG 1 -// #define NETMGR_DEBUG_RESET 1 -// #define NETMGR_DEBUG_TICK 1 -// #define NETMGR_DEBUG_STATEBOX 1 - -pqiNetStatus::pqiNetStatus() : - mExtAddrOk(false), mExtAddrStableOk(false), mUpnpOk(false), mDhtOk(false), - mDhtNetworkSize(0), mDhtRsNetworkSize(0), mResetReq(false) -{ - sockaddr_storage_clear(mLocalAddr); - sockaddr_storage_clear(mExtAddr); -} - - - -void pqiNetStatus::print(std::ostream &out) -{ - out << "pqiNetStatus: "; - out << " mExtAddrOk: " << mExtAddrOk; - out << " mExtAddrStableOk: " << mExtAddrStableOk; - out << std::endl; - out << " mUpnpOk: " << mUpnpOk; - out << " mDhtOk: " << mDhtOk; - out << " mResetReq: " << mResetReq; - out << std::endl; - out << "mDhtNetworkSize: " << mDhtNetworkSize << " mDhtRsNetworkSize: " << mDhtRsNetworkSize; - out << std::endl; - out << "mLocalAddr: " << sockaddr_storage_tostring(mLocalAddr) << " "; - out << "mExtAddr: " << sockaddr_storage_tostring(mExtAddr) << " "; - out << std::endl; -} - - -p3NetMgrIMPL::p3NetMgrIMPL() : mPeerMgr(nullptr), mLinkMgr(nullptr), - mNetMtx("p3NetMgr"), mNetStatus(RS_NET_UNKNOWN), mStatusChanged(false), - mDoNotNetCheckUntilTs(0) -{ - - { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - - mNetMode = RS_NET_MODE_UDP; - - mUseExtAddrFinder = true; - mExtAddrFinder = new ExtAddrFinder(); - mNetInitTS = 0; - - mNetFlags = pqiNetStatus(); - mOldNetFlags = pqiNetStatus(); - - mOldNatType = RsNatTypeMode::UNKNOWN; - mOldNatHole = RsNatHoleMode::UNKNOWN; - sockaddr_storage_clear(mLocalAddr); - sockaddr_storage_clear(mExtAddr); - - // force to IPv4 for the moment. - mLocalAddr.ss_family = AF_INET; - mExtAddr.ss_family = AF_INET; - - // default to full. - mVsDisc = RS_VS_DISC_FULL; - mVsDht = RS_VS_DHT_FULL; - - } - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgr() Startup" << std::endl; -#endif - - rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr() Startup, resetting network"); - netReset(); - - return; -} - -void p3NetMgrIMPL::setManagers(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr) -{ - mPeerMgr = peerMgr; - mLinkMgr = linkMgr; -} - -#ifdef RS_USE_DHT_STUNNER -void p3NetMgrIMPL::setAddrAssist(pqiAddrAssist *dhtStun, pqiAddrAssist *proxyStun) -{ - mDhtStunner = dhtStun; - mProxyStunner = proxyStun; -} -#endif // RS_USE_DHT_STUNNER - - -/***** Framework / initial implementation for a connection manager. - * - * This needs a state machine for Initialisation. - * - * Network state: - * RS_NET_UNKNOWN - * RS_NET_EXT_UNKNOWN * forwarded port (but Unknown Ext IP) * - * RS_NET_EXT_KNOWN * forwarded port with known IP/Port. * - * - * RS_NET_UPNP_CHECK * checking for UPnP * - * RS_NET_UPNP_KNOWN * confirmed UPnP ext Ip/port * - * - * RS_NET_UDP_UNKNOWN * not Ext/UPnP - to determine Ext IP/Port * - * RS_NET_UDP_KNOWN * have Stunned for Ext Addr * - * - * Transitions: - * - * RS_NET_UNKNOWN -(config)-> RS_NET_EXT_UNKNOWN - * RS_NET_UNKNOWN -(config)-> RS_NET_UPNP_UNKNOWN - * RS_NET_UNKNOWN -(config)-> RS_NET_UDP_UNKNOWN - * - * RS_NET_EXT_UNKNOWN -(DHT(ip)/Stun)-> RS_NET_EXT_KNOWN - * - * RS_NET_UPNP_UNKNOWN -(Upnp)-> RS_NET_UPNP_KNOWN - * RS_NET_UPNP_UNKNOWN -(timout/Upnp)-> RS_NET_UDP_UNKNOWN - * - * RS_NET_UDP_UNKNOWN -(stun)-> RS_NET_UDP_KNOWN - * - * - * STUN state: - * RS_STUN_INIT * done nothing * - * RS_STUN_DHT * looking up peers * - * RS_STUN_DONE * found active peer and stunned * - * - * - * Steps. - ******************************************************************* - * (1) Startup. - * - UDP port setup. - * - DHT setup. - * - Get Stun Keys -> add to DHT. - * - Feedback from DHT -> ask UDP to stun. - * - * (1) determine Network mode. - * If external Port.... Done: - * (2) - ******************************************************************* - * Stable operation: - * (1) tick and check peers. - * (2) handle callback. - * (3) notify of new/failed connections. - * - * - */ - -/* Called to reseet the whole network stack. this call is - * triggered by udp stun address tracking. - * - * must: - * - reset UPnP and DHT. - * - - */ - -void p3NetMgrIMPL::netReset() -{ -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() Called" << std::endl; -#endif - rslog(RSL_ALERT, p3netmgrzone, "p3NetMgr::netReset() Called"); - - shutdown(); /* blocking shutdown call */ - - // Will initiate a new call for determining the external ip. - if (mUseExtAddrFinder) - { -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() restarting AddrFinder" << std::endl; -#endif - mExtAddrFinder->reset() ; - } - else - { -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() ExtAddrFinder Disabled" << std::endl; -#endif - } - -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() resetting NetStatus" << std::endl; -#endif - - /* reset tcp network - if necessary */ - { - /* NOTE: nNetListeners should be protected via the Mutex. - * HOWEVER, as we NEVER change this list - once its setup - * we can get away without it - and assume its constant. - * - * NB: (*it)->reset_listener must be out of the mutex, - * as it calls back to p3ConnMgr. - */ - - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - - struct sockaddr_storage iaddr = mLocalAddr; - -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() resetting listeners" << std::endl; -#endif - std::list::const_iterator it; - for(it = mNetListeners.begin(); it != mNetListeners.end(); ++it) - { - (*it)->resetListener(iaddr); -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() reset listener" << std::endl; -#endif - } - } - - { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStatus = RS_NET_UNKNOWN; - netStatusReset_locked(); - } - - updateNetStateBox_reset(); - -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() done" << std::endl; -#endif -} - - -void p3NetMgrIMPL::netStatusReset_locked() -{ - //std::cerr << "p3NetMgrIMPL::netStatusReset()" << std::endl;; - - mNetFlags = pqiNetStatus(); -} - - -bool p3NetMgrIMPL::shutdown() /* blocking shutdown call */ -{ -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::shutdown()"; - std::cerr << std::endl; -#endif - { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStatus = RS_NET_UNKNOWN; - mNetInitTS = time(NULL); - netStatusReset_locked(); - } - netAssistFirewallShutdown(); - netAssistConnectShutdown(); - - return true; -} - - - - - - - - - -void p3NetMgrIMPL::netStartup() -{ - /* startup stuff */ - - /* StunInit gets a list of peers, and asks the DHT to find them... - * This is needed for all systems so startup straight away - */ -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup()" << std::endl; -#endif - - netDhtInit(); - - /* decide which net setup mode we're going into - */ - - - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - - mNetInitTS = time(NULL); - netStatusReset_locked(); - -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup() resetting mNetInitTS / Status" << std::endl; -#endif - mNetMode &= ~(RS_NET_MODE_ACTUAL); - - switch(mNetMode & RS_NET_MODE_TRYMODE) - { - - case RS_NET_MODE_TRY_EXT: /* v similar to UDP */ -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup() TRY_EXT mode"; - std::cerr << std::endl; -#endif - mNetMode |= RS_NET_MODE_EXT; - mNetStatus = RS_NET_EXT_SETUP; - break; - - case RS_NET_MODE_TRY_UDP: -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup() TRY_UDP mode"; - std::cerr << std::endl; -#endif - mNetMode |= RS_NET_MODE_UDP; - mNetStatus = RS_NET_EXT_SETUP; - break; - - case RS_NET_MODE_TRY_LOOPBACK: -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup() TRY_LOOPBACK mode"; - std::cerr << std::endl; -#endif - mNetMode |= RS_NET_MODE_HIDDEN; - mNetStatus = RS_NET_LOOPBACK; - break; - - default: // Fall through. - -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup() UNKNOWN mode"; - std::cerr << std::endl; -#endif - - case RS_NET_MODE_TRY_UPNP: -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup() TRY_UPNP mode"; - std::cerr << std::endl; -#endif - /* Force it here (could be default!) */ - mNetMode |= RS_NET_MODE_TRY_UPNP; - mNetMode |= RS_NET_MODE_UDP; /* set to UDP, upgraded is UPnP is Okay */ - mNetStatus = RS_NET_UPNP_INIT; - break; - } -} - - -void p3NetMgrIMPL::tick() -{ - rstime_t now = time(nullptr); - rstime_t dontCheckNetUntil; - { RS_STACK_MUTEX(mNetMtx); dontCheckNetUntil = mDoNotNetCheckUntilTs; } - - if(now >= dontCheckNetUntil) netStatusTick(); - - uint32_t netStatus; { RS_STACK_MUTEX(mNetMtx); netStatus = mNetStatus; } - switch (netStatus) - { - case RS_NET_LOOPBACK: - if(dontCheckNetUntil <= now) - { - RS_STACK_MUTEX(mNetMtx); - mDoNotNetCheckUntilTs = now + 30; - } - break; - default: - netAssistTick(); - updateNetStateBox_temporal(); -#ifdef RS_USE_DHT_STUNNER - if (mDhtStunner) mDhtStunner->tick(); - if (mProxyStunner) mProxyStunner->tick(); -#endif // RS_USE_DHT_STUNNER - break; - } -} - -#define STARTUP_DELAY 5 - - -void p3NetMgrIMPL::netStatusTick() -{ - -#ifdef NETMGR_DEBUG_TICK - std::cerr << "p3NetMgrIMPL::netTick()" << std::endl; - - std::cerr << "p3NetMgrIMPL::netTick() mNetMode: " << std::hex << mNetMode; - std::cerr << " ACTUALMODE: " << (mNetMode & RS_NET_MODE_ACTUAL); - std::cerr << " TRYMODE: " << (mNetMode & RS_NET_MODE_TRYMODE); - std::cerr << std::endl; -#endif - - // Check whether we are stuck on loopback. This happens if RS starts when - // the computer is not yet connected to the internet. In such a case we - // periodically check for a local net address. - // - checkNetAddress() ; - - uint32_t netStatus = 0; - rstime_t age = 0; - { - RsStackMutex stack(mNetMtx); /************** LOCK MUTEX ***************/ - - netStatus = mNetStatus; - age = time(NULL) - mNetInitTS; - - } - - if(netStatus <= RS_NET_UPNP_SETUP && mUseExtAddrFinder) - { - sockaddr_storage tmpip = mLocalAddr; // copies local port and correctly inits the IP family -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "Asking ExtAddrFinder for IP. Initializing port with " << sockaddr_storage_port(tmpip) << std::endl; -#endif - - if(mExtAddrFinder->hasValidIP(tmpip) && sockaddr_storage_ipv6_to_ipv4(tmpip) && !sockaddr_storage_same(tmpip,mExtAddr)) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext supplied by ExtAddrFinder" << std::endl; -#endif - -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() "; - std::cerr << "ExtAddr: " << sockaddr_storage_tostring(tmpip); - std::cerr << std::endl; -#endif - setExtAddress(tmpip); - } - } - - switch(netStatus) - { - case RS_NET_NEEDS_RESET: - -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() STATUS: NEEDS_RESET" << std::endl; -#endif - rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::netTick() RS_NET_NEEDS_RESET, resetting network"); - - netReset(); - break; - - case RS_NET_UNKNOWN: -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() STATUS: UNKNOWN" << std::endl; -#endif - - /* add a small delay to stop restarting straight after a RESET - * This is so can we shutdown cleanly - */ - if (age < STARTUP_DELAY) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() Delaying Startup" << std::endl; -#endif - } - else - { - netStartup(); - } - - break; - - case RS_NET_UPNP_INIT: -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() STATUS: UPNP_INIT" << std::endl; -#endif - netUpnpInit(); - break; - - case RS_NET_UPNP_SETUP: -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() STATUS: UPNP_SETUP" << std::endl; -#endif - netUpnpCheck(); - break; - - - case RS_NET_EXT_SETUP: -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() STATUS: EXT_SETUP" << std::endl; -#endif - // This could take a lot of time on some systems to get there: - // (e.g. 10 mins to get passed upnp on windows), so it would be better to call it right away, so other external address finding - // systems still have a chance to run early. - - netExtCheck(); - break; - - case RS_NET_DONE: -#ifdef NETMGR_DEBUG_TICK - std::cerr << "p3NetMgrIMPL::netTick() STATUS: DONE" << std::endl; -#endif - - break; - - case RS_NET_LOOPBACK: - //don't do a shutdown because a client in a computer without local network might be usefull for debug. - //shutdown(); -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() STATUS: RS_NET_LOOPBACK" << std::endl; -#endif - default: - break; - } - - return; -} - - -void p3NetMgrIMPL::netDhtInit() -{ -#if defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netDhtInit()" << std::endl; -#endif - - uint32_t vs = 0; - { - RsStackMutex stack(mNetMtx); /*********** LOCKED MUTEX ************/ - vs = mVsDht; - } - - enableNetAssistConnect(vs != RS_VS_DHT_OFF); -} - - -void p3NetMgrIMPL::netUpnpInit() -{ -#if defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUpnpInit()" << std::endl; -#endif - uint16_t eport, iport; - - mNetMtx.lock(); /* LOCK MUTEX */ - - /* get the ports from the configuration */ - - mNetStatus = RS_NET_UPNP_SETUP; - iport = sockaddr_storage_port(mLocalAddr); - eport = sockaddr_storage_port(mExtAddr); - if ((eport < 1000) || (eport > 30000)) - { - eport = iport; - } - - mNetMtx.unlock(); /* UNLOCK MUTEX */ - - netAssistFirewallPorts(iport, eport); - enableNetAssistFirewall(true); -} - -void p3NetMgrIMPL::netUpnpCheck() -{ - /* grab timestamp */ - mNetMtx.lock(); /* LOCK MUTEX */ - - rstime_t delta = time(NULL) - mNetInitTS; - -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUpnpCheck() age: " << delta << std::endl; -#endif - - mNetMtx.unlock(); /* UNLOCK MUTEX */ - - struct sockaddr_storage extAddr; - int upnpState = netAssistFirewallActive(); - - if (((upnpState == 0) && (delta > (rstime_t)MAX_UPNP_INIT)) || - ((upnpState > 0) && (delta > (rstime_t)MAX_UPNP_COMPLETE))) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUpnpCheck() "; - std::cerr << "Upnp Check failed." << std::endl; -#endif - /* fallback to UDP startup */ - mNetMtx.lock(); /* LOCK MUTEX */ - - /* UPnP Failed us! */ - mNetStatus = RS_NET_EXT_SETUP; - mNetFlags.mUpnpOk = false; - - mNetMtx.unlock(); /* UNLOCK MUTEX */ - } - else if ((upnpState > 0) && netAssistExtAddress(extAddr)) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUpnpCheck() "; - std::cerr << "Upnp Check success state: " << upnpState << std::endl; -#endif - /* switch to UDP startup */ - mNetMtx.lock(); /* LOCK MUTEX */ - - /* Set Net Status flags .... - * we now have external upnp address. Golden! - * don't set netOk flag until have seen some traffic. - */ - if (sockaddr_storage_isValidNet(extAddr)) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUpnpCheck() "; - std::cerr << "UpnpAddr: " << sockaddr_storage_tostring(extAddr); - std::cerr << std::endl; -#endif - mNetFlags.mUpnpOk = true; - mNetFlags.mExtAddr = extAddr; - mNetFlags.mExtAddrOk = true; - mNetFlags.mExtAddrStableOk = true; - - mNetStatus = RS_NET_EXT_SETUP; - /* Fix netMode & Clear others! */ - mNetMode = RS_NET_MODE_TRY_UPNP | RS_NET_MODE_UPNP; - } - mNetMtx.unlock(); /* UNLOCK MUTEX */ - } - else - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUpnpCheck() "; - std::cerr << "Upnp Check Continues: status: " << upnpState << std::endl; -#endif - } - -} - -class ZeroInt -{ - public: - ZeroInt() { n=0; } - uint32_t n ; -}; - -void p3NetMgrIMPL::netExtCheck() -{ -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck()" << std::endl; -#endif - bool netSetupDone = false; - - { - RS_STACK_MUTEX(mNetMtx); - - bool isStable = false; - sockaddr_storage tmpip; - - std::map address_votes; - - /* check for External Address */ - /* in order of importance */ - /* (1) UPnP -> which handles itself */ - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Not Ok" << std::endl; -#endif - /* net Assist */ - if ( netAssistExtAddress(tmpip) && - sockaddr_storage_isValidNet(tmpip) && - sockaddr_storage_ipv6_to_ipv4(tmpip) ) - { - if( !rsBanList || - rsBanList->isAddressAccepted( - tmpip, RSBANLIST_CHECKING_FLAGS_BLACKLIST ) ) - { - // must be stable??? - isStable = true; - mNetFlags.mExtAddrOk = true; - mNetFlags.mExtAddrStableOk = isStable; - address_votes[tmpip].n++ ; - std::cerr << __PRETTY_FUNCTION__ << " NetAssistAddress " - << " reported external address " - << sockaddr_storage_iptostring(tmpip) - << std::endl; - } - else - std::cerr << "(SS) netAssisExternalAddress returned banned " - << "own IP " << sockaddr_storage_iptostring(tmpip) - << " (banned). Rejecting." << std::endl; - } - } - - /* ask ExtAddrFinder */ - { - /* ExtAddrFinder */ - if (mUseExtAddrFinder) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() checking ExtAddrFinder" << std::endl; -#endif - sockaddr_storage tmpip = mLocalAddr; // copies local port and correctly inits the IP family - - bool extFinderOk = mExtAddrFinder->hasValidIP(tmpip); - - if (extFinderOk && sockaddr_storage_ipv6_to_ipv4(tmpip)) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext supplied by ExtAddrFinder" << std::endl; -#endif - sockaddr_storage_setport(tmpip, guessNewExtPort()); - -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() "; - std::cerr << "ExtAddr: " << sockaddr_storage_tostring(tmpip); - std::cerr << std::endl; -#endif - - mNetFlags.mExtAddrOk = true; - - address_votes[tmpip].n++ ; - - /* XXX HACK TO FIX drbob: ALLOWING - * ExtAddrFinder -> ExtAddrStableOk = true - * (which it is not normally) */ - mNetFlags.mExtAddrStableOk = true; - - std::cerr << __PRETTY_FUNCTION__ << " ExtAddrFinder " - << " reported external address " - << sockaddr_storage_iptostring(tmpip) - << std::endl; - } - } - } - - /* also ask peer mgr. */ - if (mPeerMgr) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() checking mPeerMgr" << std::endl; -#endif - uint8_t isstable; // unused - sockaddr_storage tmpaddr; - - if ( mPeerMgr->getExtAddressReportedByFriends(tmpaddr, isstable) && sockaddr_storage_ipv6_to_ipv4(tmpaddr) ) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext supplied by friends" << std::endl; -#endif - sockaddr_storage_setport(tmpaddr, guessNewExtPort()); - -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() "; - std::cerr << "ExtAddr: " << sockaddr_storage_tostring(tmpip); - std::cerr << std::endl; -#endif - - mNetFlags.mExtAddrOk = true; - mNetFlags.mExtAddrStableOk = isstable; - - address_votes[tmpaddr].n++; - - std::cerr << __PRETTY_FUNCTION__ << " PeerMgr reported external" - << " address " - << sockaddr_storage_iptostring(tmpaddr) << std::endl; - } -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - else - std::cerr << " No reliable address returned." << std::endl; -#endif - } - -#ifdef ALLOW_DHT_STUNNER - // (cyril) I disabled this because it's pretty dangerous. The DHT can report a wrong address quite easily - // if the other DHT peers are not collaborating. - // (sehraf) For the record: The udp stunner uses multiple (as for now: two) peers to ensure that the IP recieved is the correct one, see UdpStunner::locked_checkExternalAddress() - // Nevertheless this stays a more risky method to determine the external ip address. - - /* lastly ask the DhtStunner as fallback */ - if (address_votes.empty()) { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Not Ok, Checking DhtStunner" << std::endl; -#endif - uint8_t isstable = 0; - struct sockaddr_storage tmpaddr; - sockaddr_storage_clear(tmpaddr); - - if (mDhtStunner) - { - /* input network bits */ - if (mDhtStunner->getExternalAddr(tmpaddr, isstable)) - { - if((rsBanList == NULL) || rsBanList->isAddressAccepted(tmpaddr,RSBANLIST_CHECKING_FLAGS_BLACKLIST)) - { - // must be stable??? - isStable = (isstable == 1); - //mNetFlags.mExtAddr = tmpaddr; - mNetFlags.mExtAddrOk = true; - mNetFlags.mExtAddrStableOk = isStable; - - address_votes[tmpaddr].n++ ; -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::netExtCheck() From DhtStunner: "; - std::cerr << sockaddr_storage_tostring(tmpaddr); - std::cerr << " Stable: " << (uint32_t) isstable; - std::cerr << std::endl; -#endif - } - else - std::cerr << "(SS) DHTStunner returned wrong own IP " << sockaddr_storage_iptostring(tmpaddr) << " (banned). Rejecting." << std::endl; - } - } - } -#endif - - /* any other sources ??? */ - - /* finalise address */ - if (mNetFlags.mExtAddrOk) - { - // look at votes. - - std::cerr << "Figuring out ext addr from voting:" << std::endl; - uint32_t admax = 0 ; - - for(std::map::const_iterator it(address_votes.begin());it!=address_votes.end();++it) - { - std::cerr << " Vote: " << sockaddr_storage_iptostring(it->first) << " : " << it->second.n << " votes." ; - - if(it->second.n > admax) - { - mNetFlags.mExtAddr = it->first ; - admax = it->second.n ; - - std::cerr << " Kept!" << std::endl; - } - else - std::cerr << " Discarded." << std::endl; - } - -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() "; - std::cerr << "ExtAddr: " << sockaddr_storage_tostring(mNetFlags.mExtAddr); - std::cerr << std::endl; -#endif - //update ip address list - mExtAddr = mNetFlags.mExtAddr; - - mNetStatus = RS_NET_DONE; - netSetupDone = true; - -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Ok: RS_NET_DONE" << std::endl; -#endif - - - - if (!mNetFlags.mExtAddrStableOk) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUdpCheck() UDP Unstable :( "; - std::cerr << std::endl; - std::cerr << "p3NetMgrIMPL::netUdpCheck() We are unreachable"; - std::cerr << std::endl; - std::cerr << "netMode => RS_NET_MODE_UNREACHABLE"; - std::cerr << std::endl; -#endif - - // Due to the new UDP connections - we can still connect some of the time! - // So limit warning! - - //mNetMode &= ~(RS_NET_MODE_ACTUAL); - //mNetMode |= RS_NET_MODE_UNREACHABLE; - - /* send a system warning message */ - //pqiNotify *notify = getPqiNotify(); - //if (notify) - { - //std::string title = - // "Warning: Bad Firewall Configuration"; - - std::string msg; - msg += " **** WARNING **** \n"; - msg += "Retroshare has detected that you are behind"; - msg += " a restrictive Firewall\n"; - msg += "\n"; - msg += "You will have limited connectivity to other firewalled peers\n"; - msg += "\n"; - msg += "You can fix this by:\n"; - msg += " (1) opening an External Port\n"; - msg += " (2) enabling UPnP, or\n"; - msg += " (3) get a new (approved) Firewall/Router\n"; - - //notify->AddSysMessage(0, RS_SYS_WARNING, title, msg); - - std::cerr << msg << std::endl; - } - - } - - } - - if (mNetFlags.mExtAddrOk) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() setting netAssistSetAddress()" << std::endl; -#endif - netAssistSetAddress(mNetFlags.mLocalAddr, mNetFlags.mExtAddr, mNetMode); - } - - /* flag unreachables! */ - if ((mNetFlags.mExtAddrOk) && (!mNetFlags.mExtAddrStableOk)) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Unstable - Unreachable Check" << std::endl; -#endif - } - } - - if (netSetupDone) - { - std::cerr << "p3NetMgrIMPL::netExtCheck() netSetupDone" << std::endl; - - /* Setup NetStateBox with this info */ - updateNetStateBox_startup(); - - /* update PeerMgr with correct info */ - if (mPeerMgr) - { - mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); - } - - /* inform DHT about our external address */ - RsPeerId fakeId; - netAssistKnownPeer(fakeId, mExtAddr, NETASSIST_KNOWN_PEER_SELF | NETASSIST_KNOWN_PEER_ONLINE); - - std::cerr << __PRETTY_FUNCTION__ << " Network Setup Complete" - << std::endl; - } -} - -/********************************************************************************************** - ************************************** Interfaces ***************************************** - **********************************************************************************************/ - -bool p3NetMgrIMPL::checkNetAddress() -{ - bool addrChanged = false; - bool validAddr = false; - - sockaddr_storage prefAddr; - sockaddr_storage oldAddr; - - if (mNetMode & RS_NET_MODE_TRY_LOOPBACK) - { - RsInfo() << __PRETTY_FUNCTION__ <<" network mode set to LOOPBACK," - << " forcing address to 127.0.0.1" << std::endl; - - sockaddr_storage_ipv4_aton(prefAddr, "127.0.0.1"); - validAddr = true; - } - else - { - /* TODO: Sat Oct 24 15:51:24 CEST 2015 The fact of having just one local - * address is a flawed assumption, this should be redesigned as soon as - * possible. It will require complete reenginering of the network layer - * code. */ - - /* For retro-compatibility strictly accept only IPv4 addresses here, - * IPv6 addresses are handled in a retro-compatible manner in - * p3PeerMgrIMPL::UpdateOwnAddress */ - std::vector addrs; - if (getLocalAddresses(addrs)) - { - for (auto it = addrs.begin(); it != addrs.end(); ++it) - { - sockaddr_storage& addr(*it); - if( sockaddr_storage_isValidNet(addr) && - !sockaddr_storage_isLoopbackNet(addr) && - !sockaddr_storage_isLinkLocalNet(addr) && - sockaddr_storage_ipv6_to_ipv4(addr) ) - { - prefAddr = addr; - validAddr = true; - break; - } - } - - /* If no satisfactory local address has been found yet relax and - * accept also link local addresses */ - if(!validAddr) for (auto it = addrs.begin(); it!=addrs.end(); ++it) - { - sockaddr_storage& addr(*it); - if( sockaddr_storage_isValidNet(addr) && - !sockaddr_storage_isLoopbackNet(addr) && - sockaddr_storage_ipv6_to_ipv4(addr) ) - { - prefAddr = addr; - validAddr = true; - break; - } - } - - /* If no satisfactory local address has been found yet relax and - * accept also loopback addresses */ - if(!validAddr) for (auto it = addrs.begin(); it!=addrs.end(); ++it) - { - sockaddr_storage& addr(*it); - if( sockaddr_storage_isValidNet(addr) && - sockaddr_storage_ipv6_to_ipv4(addr) ) - { - prefAddr = addr; - validAddr = true; - break; - } - } - } - } - - if (!validAddr) - { - RsErr() << __PRETTY_FUNCTION__ << " no valid local network address " - <<" found. Report to developers." << std::endl; - print_stacktrace(); - - return false; - } - - /* check addresses */ - { RS_STACK_MUTEX(mNetMtx); - - sockaddr_storage_copy(mLocalAddr, oldAddr); - addrChanged = !sockaddr_storage_sameip(prefAddr, mLocalAddr); - - // update address. - sockaddr_storage_copyip(mLocalAddr, prefAddr); - sockaddr_storage_copy(mLocalAddr, mNetFlags.mLocalAddr); - - if(sockaddr_storage_isLoopbackNet(mLocalAddr)) - mNetStatus = RS_NET_LOOPBACK; - - // Check if local port is valid, reset it if not - if (!sockaddr_storage_port(mLocalAddr)) - { - /* Using same port as external may make some NAT happier */ - uint16_t port = sockaddr_storage_port(mExtAddr); - - /* Avoid to automatically set a local port to a reserved one < 1024 - * that needs special permissions or root access. - * This do not impede the user to set a reserved port manually, - * which make sense in some cases. */ - - std::cerr << __PRETTY_FUNCTION__ << " local port is 0. Ext port is " << port ; - - while (port < 1025) - port = static_cast(RsRandom::random_u32()); - - std::cerr << " new ext port is " << port << ": using these for local/ext ports" << std::endl; - - sockaddr_storage_setport(mLocalAddr, port); - sockaddr_storage_setport(mExtAddr, port); // this accounts for when the port was updated - addrChanged = true; - } - } // RS_STACK_MUTEX(mNetMtx); - - if (addrChanged) - { - RsInfo() << __PRETTY_FUNCTION__ << " local address changed, resetting network." << std::endl; - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mNetworkEventCode = RsNetworkEventCode::LOCAL_IP_UPDATED; - ev->mIPAddress = sockaddr_storage_iptostring(mLocalAddr); - rsEvents->postEvent(ev); - } - - if (mPeerMgr) mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); - - netReset(); - } - - return true; -} - - -/********************************************************************************************** - ************************************** Interfaces ***************************************** - **********************************************************************************************/ - -/* to allow resets of network stuff */ -void p3NetMgrIMPL::addNetListener(pqiNetListener *listener) -{ - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetListeners.push_back(listener); -} - - - -bool p3NetMgrIMPL::setLocalAddress(const struct sockaddr_storage &addr) -{ - bool changed = false; - { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - if (!sockaddr_storage_same(mLocalAddr, addr)) - { - changed = true; - } - - mLocalAddr = addr; - mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); - } - - if (changed) - { -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::setLocalAddress() Calling NetReset" << std::endl; -#endif - rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::setLocalAddress() local address changed, resetting network"); - netReset(); - } - return true; -} -bool p3NetMgrIMPL::getExtAddress(struct sockaddr_storage& addr) -{ - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - - if(mNetFlags.mExtAddrOk) - { - addr = mNetFlags.mExtAddr ; - return true ; - } - else - return false ; -} - -bool p3NetMgrIMPL::setExtAddress(const struct sockaddr_storage &addr) -{ - bool changed = false; - { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - if (!sockaddr_storage_same(mExtAddr, addr)) - { - changed = true; - } - - mExtAddr = addr; - mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); - } - - if (changed) - { -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::setExtAddress() Calling NetReset" << std::endl; -#endif - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mNetworkEventCode = RsNetworkEventCode::EXTERNAL_IP_UPDATED; - ev->mIPAddress = sockaddr_storage_iptostring(addr); - rsEvents->postEvent(ev); - } - - rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::setExtAddress() ext address changed, resetting network"); - netReset(); - } - return true; -} - -bool p3NetMgrIMPL::setNetworkMode(uint32_t netMode) -{ - uint32_t oldNetMode; - { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - /* only change TRY flags */ - - oldNetMode = mNetMode; - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::setNetworkMode()"; - std::cerr << " Existing netMode: " << mNetMode; - std::cerr << " Input netMode: " << netMode; - std::cerr << std::endl; -#endif - mNetMode &= ~(RS_NET_MODE_TRYMODE); - - switch(netMode & RS_NET_MODE_ACTUAL) - { - case RS_NET_MODE_EXT: - mNetMode |= RS_NET_MODE_TRY_EXT; - break; - case RS_NET_MODE_UPNP: - mNetMode |= RS_NET_MODE_TRY_UPNP; - break; - case RS_NET_MODE_HIDDEN: - mNetMode |= RS_NET_MODE_TRY_LOOPBACK; - break; - default: - case RS_NET_MODE_UDP: - mNetMode |= RS_NET_MODE_TRY_UDP; - break; - } - } - - - if ((netMode & RS_NET_MODE_ACTUAL) != (oldNetMode & RS_NET_MODE_ACTUAL)) - { -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::setNetworkMode() Calling NetReset" << std::endl; -#endif - rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::setNetworkMode() Net Mode changed, resetting network"); - netReset(); - } - return true; -} - - -bool p3NetMgrIMPL::setVisState(uint16_t vs_disc, uint16_t vs_dht) -{ - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - mVsDisc = vs_disc; - mVsDht = vs_dht; - - /* if we've started up - then tweak Dht On/Off */ - if (mNetStatus != RS_NET_UNKNOWN) - { - enableNetAssistConnect(mVsDht != RS_VS_DHT_OFF); - } - - return true; -} - - -/********************************************************************************************** - ************************************** Interfaces ***************************************** - **********************************************************************************************/ - -void p3NetMgrIMPL::addNetAssistFirewall(uint32_t id, pqiNetAssistFirewall *fwAgent) -{ - mFwAgents[id] = fwAgent; -} - - -bool p3NetMgrIMPL::enableNetAssistFirewall(bool on) -{ - std::map::iterator it; - for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it) - { - (it->second)->enable(on); - } - return true; -} - - -bool p3NetMgrIMPL::netAssistFirewallEnabled() -{ - std::map::iterator it; - for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it) - { - if ((it->second)->getEnabled()) - { - return true; - } - } - return false; -} - -bool p3NetMgrIMPL::netAssistFirewallActive() -{ - std::map::iterator it; - for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it) - { - if ((it->second)->getActive()) - { - return true; - } - } - return false; -} - -bool p3NetMgrIMPL::netAssistFirewallShutdown() -{ - std::map::iterator it; - for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it) - { - (it->second)->shutdown(); - } - return true; -} - -bool p3NetMgrIMPL::netAssistFirewallPorts(uint16_t iport, uint16_t eport) -{ - std::map::iterator it; - for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it) - { - (it->second)->setInternalPort(iport); - (it->second)->setExternalPort(eport); - } - return true; -} - - -bool p3NetMgrIMPL::netAssistExtAddress(struct sockaddr_storage &extAddr) -{ - std::map::iterator it; - for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it) - { - if ((it->second)->getActive()) - { - if ((it->second)->getExternalAddress(extAddr)) - { - return true; - } - } - } - return false; -} - - -void p3NetMgrIMPL::addNetAssistConnect(uint32_t id, pqiNetAssistConnect *dht) -{ - mDhts[id] = dht; -} - -bool p3NetMgrIMPL::enableNetAssistConnect(bool on) -{ - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::enableNetAssistConnect(" << on << ")"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->enable(on); - } - return true; -} - -bool p3NetMgrIMPL::netAssistConnectEnabled() -{ - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - if ((it->second)->getEnabled()) - { -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectEnabled() YES"; - std::cerr << std::endl; -#endif - - return true; - } - } - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectEnabled() NO"; - std::cerr << std::endl; -#endif - - return false; -} - -bool p3NetMgrIMPL::netAssistConnectActive() -{ - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - if ((it->second)->getActive()) - - { -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectActive() ACTIVE"; - std::cerr << std::endl; -#endif - - return true; - } - } - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectActive() INACTIVE"; - std::cerr << std::endl; -#endif - - return false; -} - -bool p3NetMgrIMPL::netAssistConnectStats(uint32_t &netsize, uint32_t &localnetsize) -{ - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - if (((it->second)->getActive()) && ((it->second)->getNetworkStats(netsize, localnetsize))) - - { -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectStats("; - std::cerr << netsize << ", " << localnetsize << ")"; - std::cerr << std::endl; -#endif - - return true; - } - } - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectStats() INACTIVE"; - std::cerr << std::endl; -#endif - - return false; -} - -bool p3NetMgrIMPL::netAssistConnectShutdown() -{ -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectShutdown()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->shutdown(); - } - return true; -} - -bool p3NetMgrIMPL::netAssistFriend(const RsPeerId &id, bool on) -{ - std::map::iterator it; - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistFriend(" << id << ", " << on << ")"; - std::cerr << std::endl; -#endif - - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - if (on) - (it->second)->findPeer(id); - else - (it->second)->dropPeer(id); - } - return true; -} - - -bool p3NetMgrIMPL::netAssistKnownPeer(const RsPeerId &id, const struct sockaddr_storage &addr, uint32_t flags) -{ - std::map::iterator it; - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistKnownPeer(" << id << ")"; - std::cerr << std::endl; -#endif - - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->addKnownPeer(id, addr, flags); - } - return true; -} - -bool p3NetMgrIMPL::netAssistBadPeer(const struct sockaddr_storage &addr, uint32_t reason, uint32_t flags, uint32_t age) -{ - std::map::iterator it; - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistBadPeer(" << sockaddr_storage_iptostring(addr) << ")"; - std::cerr << std::endl; -#endif - - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->addBadPeer(addr, reason, flags, age); - } - return true; -} - - -bool p3NetMgrIMPL::netAssistAttach(bool on) -{ - std::map::iterator it; - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistAttach(" << on << ")"; - std::cerr << std::endl; -#endif - - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->setAttachMode(on); - } - return true; -} - - - -bool p3NetMgrIMPL::netAssistStatusUpdate(const RsPeerId &id, int state) -{ - std::map::iterator it; - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistStatusUpdate(" << id << ", " << state << ")"; - std::cerr << std::endl; -#endif - - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->ConnectionFeedback(id, state); - } - return true; -} - - -bool p3NetMgrIMPL::netAssistSetAddress( const struct sockaddr_storage & /*laddr*/, - const struct sockaddr_storage & /*eaddr*/, - uint32_t /*mode*/) -{ -#if 0 - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->setExternalInterface(laddr, eaddr, mode); - } -#endif - return true; -} - -void p3NetMgrIMPL::netAssistTick() -{ - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->tick(); - } - - std::map::iterator fit; - for(fit = mFwAgents.begin(); fit != mFwAgents.end(); ++fit) - { - (fit->second)->tick(); - } - return; -} - - - -/********************************************************************** - ********************************************************************** - ******************** Network State *********************************** - ********************************************************************** - **********************************************************************/ - -bool p3NetMgrIMPL::getUPnPState() -{ - return netAssistFirewallActive(); -} - -bool p3NetMgrIMPL::getUPnPEnabled() -{ - return netAssistFirewallEnabled(); -} - -bool p3NetMgrIMPL::getDHTEnabled() -{ - return netAssistConnectEnabled(); -} - - -void p3NetMgrIMPL::getNetStatus(pqiNetStatus &status) -{ - /* cannot lock local stack, then call DHT... as this can cause lock up */ - /* must extract data... then update mNetFlags */ - - bool dhtOk = netAssistConnectActive(); - uint32_t netsize = 0, rsnetsize = 0; - netAssistConnectStats(netsize, rsnetsize); - - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - - /* quick update of the stuff that can change! */ - mNetFlags.mDhtOk = dhtOk; - mNetFlags.mDhtNetworkSize = netsize; - mNetFlags.mDhtRsNetworkSize = rsnetsize; - - status = mNetFlags; -} - - - - - - - - - -/********************************************************************************************** - ************************************** ExtAddrFinder ***************************************** - **********************************************************************************************/ - -bool p3NetMgrIMPL::getIPServersEnabled() -{ - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - return mUseExtAddrFinder; -} - -void p3NetMgrIMPL::getIPServersList(std::list& ip_servers) -{ - mExtAddrFinder->getIPServersList(ip_servers); -} - -void p3NetMgrIMPL::setIPServersEnabled(bool b) -{ - { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - mUseExtAddrFinder = b; - } - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgr: setIPServers to " << b << std::endl ; -#endif - -} - - - -/********************************************************************************************** - ************************************** NetStateBox ****************************************** - **********************************************************************************************/ - -RsNetState p3NetMgrIMPL::getNetStateMode() -{ - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - return mNetStateBox.getNetStateMode(); -} - -RsNetworkMode p3NetMgrIMPL::getNetworkMode() -{ - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - return mNetStateBox.getNetworkMode(); -} - -RsNatTypeMode p3NetMgrIMPL::getNatTypeMode() -{ - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - return mNetStateBox.getNatTypeMode(); -} - -RsNatHoleMode p3NetMgrIMPL::getNatHoleMode() -{ - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - return mNetStateBox.getNatHoleMode(); -} - -RsConnectModes p3NetMgrIMPL::getConnectModes() -{ - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - return mNetStateBox.getConnectModes(); -} - - -/* These are the regular updates from Dht / Stunners */ -void p3NetMgrIMPL::updateNetStateBox_temporal() -{ -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() "; - std::cerr << std::endl; -#endif - struct sockaddr_storage tmpaddr; - sockaddr_storage_clear(tmpaddr); - -#ifdef RS_USE_DHT_STUNNER - uint8_t isstable = 0; - - if (mDhtStunner) - { - - /* input network bits */ - if (mDhtStunner->getExternalAddr(tmpaddr, isstable)) - { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStateBox.setAddressStunDht(tmpaddr, isstable); - -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() DhtStunner: "; - std::cerr << sockaddr_storage_tostring(tmpaddr); - std::cerr << " Stable: " << (uint32_t) isstable; - std::cerr << std::endl; -#endif - - } - } - - if (mProxyStunner) - { - - /* input network bits */ - if (mProxyStunner->getExternalAddr(tmpaddr, isstable)) - { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStateBox.setAddressStunProxy(tmpaddr, isstable); - -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() ProxyStunner: "; - std::cerr << sockaddr_storage_tostring(tmpaddr); - std::cerr << " Stable: " << (uint32_t) isstable; - std::cerr << std::endl; -#endif - - } - } -#endif // RS_USE_DHT_STUNNER - - - { - bool dhtOn = netAssistConnectEnabled(); - bool dhtActive = netAssistConnectActive(); - - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStateBox.setDhtState(dhtOn, dhtActive); - } - - - /* now we check if a WebIP address is required? */ - -#ifdef NETMGR_DEBUG_STATEBOX - { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - - auto netstate = mNetStateBox.getNetStateMode(); - auto netMode = mNetStateBox.getNetworkMode(); - auto natType = mNetStateBox.getNatTypeMode(); - auto natHole = mNetStateBox.getNatHoleMode(); - auto connect = mNetStateBox.getConnectModes(); -#ifdef SUSPENDED - auto netstatestr = NetStateNetStateString(netstate); - auto connectstr = NetStateConnectModesString(connect); - auto natholestr = NetStateNatHoleString(natHole); - auto nattypestr = NetStateNatTypeString(natType); - auto netmodestr = NetStateNetworkModeString(netMode); - - std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() NetStateBox Thinking"; - std::cerr << std::endl; - std::cerr << "\tNetState: " << netstatestr; - std::cerr << std::endl; - std::cerr << "\tConnectModes: " << connectstr; - std::cerr << std::endl; - std::cerr << "\tNetworkMode: " << netmodestr; - std::cerr << std::endl; - std::cerr << "\tNatHole: " << natholestr; - std::cerr << std::endl; - std::cerr << "\tNatType: " << nattypestr; - std::cerr << std::endl; -#endif - - } -#endif - - updateNatSetting(); - -} - -#define NET_STUNNER_PERIOD_FAST (-1) // default of Stunner. -#define NET_STUNNER_PERIOD_SLOW (120) // This needs to be as small Routers will allow... try 2 minutes. -// FOR TESTING ONLY. -//#define NET_STUNNER_PERIOD_SLOW (60) // 3 minutes. - -void p3NetMgrIMPL::updateNatSetting() -{ - bool updateRefreshRate = false; - RsNatTypeMode natType = RsNatTypeMode::UNKNOWN; - RsNatHoleMode natHole = RsNatHoleMode::UNKNOWN; - { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - - natType = mNetStateBox.getNatTypeMode(); - natHole = mNetStateBox.getNatHoleMode(); - if ((natType != mOldNatType) || (natHole != mOldNatHole)) - { - mOldNatType = natType; - mOldNatHole = natHole; - updateRefreshRate = true; - -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() NatType Change!"; -// std::cerr << "\tNatType: " << NetStateNatTypeString(natType); -// std::cerr << "\tNatHole: "k << NetStateNatHoleString(natHole); - - std::cerr << std::endl; -#endif - - - } - } - - - // MUST also use this chance to set ATTACH flag for DHT. - if (updateRefreshRate) - { -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() Updating Refresh Rate, based on changed NatType"; - std::cerr << std::endl; -#endif - -#ifdef RS_USE_DHT_STUNNER - if (mProxyStunner) { - switch(natType) - { - case RsNatTypeMode::RESTRICTED_CONE: - { - if ((natHole == RsNatHoleMode::NONE) || (natHole == RsNatHoleMode::UNKNOWN)) - { - mProxyStunner->setRefreshPeriod(NET_STUNNER_PERIOD_FAST); - } - else - { - mProxyStunner->setRefreshPeriod(NET_STUNNER_PERIOD_SLOW); - } - break; - } - case RsNatTypeMode::NONE: - case RsNatTypeMode::UNKNOWN: - case RsNatTypeMode::SYMMETRIC: - case RsNatTypeMode::DETERM_SYM: - case RsNatTypeMode::FULL_CONE: - case RsNatTypeMode::OTHER: - - mProxyStunner->setRefreshPeriod(NET_STUNNER_PERIOD_SLOW); - break; - } - } -#endif // RS_USE_DHT_STUNNER - - /* This controls the Attach mode of the DHT... - * which effectively makes the DHT "attach" to Open Nodes. - * So that messages can get through. - * We only want to be attached - if we don't have a stable DHT port. - */ - if ((natHole == RsNatHoleMode::NONE) || (natHole == RsNatHoleMode::UNKNOWN)) - { - switch(natType) - { - /* switch to attach mode if we have a bad firewall */ - case RsNatTypeMode::UNKNOWN: - case RsNatTypeMode::SYMMETRIC: - case RsNatTypeMode::RESTRICTED_CONE: - case RsNatTypeMode::DETERM_SYM: - case RsNatTypeMode::OTHER: - netAssistAttach(true); - - break; - /* switch off attach mode if we have a nice firewall */ - case RsNatTypeMode::NONE: - case RsNatTypeMode::FULL_CONE: - netAssistAttach(false); - break; - } - } - else - { - // Switch off Firewall Mode (Attach) - netAssistAttach(false); - } - } -} - - - -void p3NetMgrIMPL::updateNetStateBox_startup() -{ -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << std::endl; -#endif - { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - - /* fill in the data */ - struct sockaddr_storage tmpip; - - /* net Assist */ - if (netAssistExtAddress(tmpip)) - { - -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << "Ext supplied from netAssistExternalAddress()"; - std::cerr << std::endl; -#endif - - if (sockaddr_storage_isValidNet(tmpip)) - { -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << "netAssist Returned: " << sockaddr_storage_tostring(tmpip); - std::cerr << std::endl; -#endif - mNetStateBox.setAddressUPnP(true, tmpip); - } - else - { - mNetStateBox.setAddressUPnP(false, tmpip); -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << "ERROR Bad Address supplied from netAssistExternalAddress()"; - std::cerr << std::endl; -#endif - } - } - else - { -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << " netAssistExtAddress() is not active"; - std::cerr << std::endl; -#endif - mNetStateBox.setAddressUPnP(false, tmpip); - } - - - /* ExtAddrFinder */ - if (mUseExtAddrFinder) - { - tmpip = mLocalAddr; - bool extFinderOk = mExtAddrFinder->hasValidIP(tmpip); - - if (extFinderOk) - { - sockaddr_storage_setport(tmpip, guessNewExtPort()); - -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << "ExtAddrFinder Returned: " << sockaddr_storage_iptostring(tmpip); - std::cerr << std::endl; -#endif - - mNetStateBox.setAddressWebIP(true, tmpip); - } - else - { - mNetStateBox.setAddressWebIP(false, tmpip); -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << " ExtAddrFinder hasn't found an address yet"; - std::cerr << std::endl; -#endif - } - } - else - { -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << " ExtAddrFinder is not active"; - std::cerr << std::endl; -#endif - mNetStateBox.setAddressWebIP(false, tmpip); - } - - - /* finally - if the user has set Forwarded, pass it on */ - if (mNetMode & RS_NET_MODE_TRY_EXT) - { - mNetStateBox.setPortForwarded(true, 0); // Port unknown for now. - } - } -} - -void p3NetMgrIMPL::updateNetStateBox_reset() -{ - { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - - mNetStateBox.reset(); - - mOldNatHole = RsNatHoleMode::UNKNOWN; - mOldNatType = RsNatTypeMode::UNKNOWN; - - } -} - -p3NetMgr::~p3NetMgr() = default; -pqiNetAssist::~pqiNetAssist() = default; -pqiNetAssistPeerShare::~pqiNetAssistPeerShare() = default; -pqiNetAssistConnect::~pqiNetAssistConnect() = default; diff --git a/libretroshare/src/pqi/p3netmgr.h b/libretroshare/src/pqi/p3netmgr.h deleted file mode 100644 index a847c07b1..000000000 --- a/libretroshare/src/pqi/p3netmgr.h +++ /dev/null @@ -1,330 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3netmgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2008 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "pqi/pqimonitor.h" -#include "pqi/pqiipset.h" -#include "pqi/pqiassist.h" -#include "pqi/pqinetstatebox.h" -#include "pqi/p3cfgmgr.h" -#include "util/rsthreads.h" -#include "util/rsdebug.h" - -class ExtAddrFinder ; -class DNSResolver ; - - /* RS_VIS_STATE_XXXX - * determines how public this peer wants to be... - * - * STD = advertise to Peers / DHT checking etc - * GRAY = share with friends / but not DHT - * DARK = hidden from all - * BROWN? = hidden from friends / but on DHT - */ - - - -struct pqiNetStatus -{ - pqiNetStatus(); - - bool mExtAddrOk; // have external address. - bool mExtAddrStableOk; // stable external address. - bool mUpnpOk; // upnp is ok. - bool mDhtOk; // dht is ok. - - uint32_t mDhtNetworkSize; - uint32_t mDhtRsNetworkSize; - - struct sockaddr_storage mLocalAddr; // percieved ext addr. - struct sockaddr_storage mExtAddr; // percieved ext addr. - - bool mResetReq; // Not Used yet!. - - void print(std::ostream &out); -}; - -class p3PeerMgr; -class p3LinkMgr; - -class p3PeerMgrIMPL; -class p3LinkMgrIMPL; - -class rsUdpStack; -class UdpStunner; -class p3BitDht; -class UdpRelayReceiver; - - -#define NETMGR_DHT_FEEDBACK_CONNECTED 0x0001 -#define NETMGR_DHT_FEEDBACK_CONN_FAILED 0x0002 -#define NETMGR_DHT_FEEDBACK_CONN_CLOSED 0x0003 - - -/********** - * p3NetMgr Interface.... - * This allows a drop-in replacement for testing. - */ - -class p3NetMgr -{ -public: - - /*************** External Control ****************/ - - // Setup Network State. -virtual bool setNetworkMode(uint32_t netMode) = 0; -virtual bool setVisState(uint16_t vs_disc, uint16_t vs_dht) = 0; - - // Switch DHT On/Off. -virtual bool netAssistFriend(const RsPeerId &id, bool on) = 0; -virtual bool netAssistKnownPeer(const RsPeerId &id, const struct sockaddr_storage &addr, uint32_t flags) = 0; -virtual bool netAssistBadPeer(const struct sockaddr_storage &addr, uint32_t reason, uint32_t flags, uint32_t age) = 0; -virtual bool netAssistStatusUpdate(const RsPeerId &id, int mode) = 0; - - /* Get Network State */ -virtual RsNetState getNetStateMode() = 0; -virtual RsNetworkMode getNetworkMode() = 0; -virtual RsNatTypeMode getNatTypeMode() = 0; -virtual RsNatHoleMode getNatHoleMode() = 0; -virtual RsConnectModes getConnectModes() = 0; - - /* Shut It Down! */ -virtual bool shutdown() = 0; /* blocking shutdown call */ - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ - - // THESE SHOULD BE MOVED TO p3PeerMgr (as it controls the config). - // The functional object should be transformed into a NetAssistFirewall object. - // ONLY USED by p3peers.cc & p3peermgr.cc -virtual bool getIPServersEnabled() = 0; -virtual void setIPServersEnabled(bool b) = 0; -virtual void getIPServersList(std::list& ip_servers) = 0; - - // ONLY USED by p3face-config.cc WHICH WILL BE REMOVED. -virtual void getNetStatus(pqiNetStatus &status) = 0; -virtual bool getUPnPState() = 0; -virtual bool getUPnPEnabled() = 0; -virtual bool getDHTEnabled() = 0; - - virtual ~p3NetMgr(); -}; - - -class p3NetMgrIMPL: public p3NetMgr -{ -public: - - p3NetMgrIMPL(); - -/************************************************************************************************/ -/* EXTERNAL INTERFACE */ -/************************************************************************************************/ - - /*************** External Control ****************/ - - // Setup Network State. -virtual bool setNetworkMode(uint32_t netMode); -virtual bool setVisState(uint16_t vs_disc, uint16_t vs_dht); - - // Switch DHT On/Off. -virtual bool netAssistFriend(const RsPeerId &id, bool on); -virtual bool netAssistKnownPeer(const RsPeerId &id, const struct sockaddr_storage &addr, uint32_t flags); -virtual bool netAssistBadPeer(const struct sockaddr_storage &addr, uint32_t reason, uint32_t flags, uint32_t age); -virtual bool netAssistStatusUpdate(const RsPeerId &id, int mode); - - /* Get Network State */ -virtual RsNetState getNetStateMode(); -virtual RsNetworkMode getNetworkMode(); -virtual RsNatTypeMode getNatTypeMode(); -virtual RsNatHoleMode getNatHoleMode(); -virtual RsConnectModes getConnectModes(); - - /* Shut It Down! */ -virtual bool shutdown(); /* blocking shutdown call */ - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ - - // THESE SHOULD BE MOVED TO p3PeerMgr (as it controls the config). - // The functional object should be transformed into a NetAssistFirewall object. - // ONLY USED by p3peers.cc & p3peermgr.cc -virtual bool getIPServersEnabled(); -virtual void setIPServersEnabled(bool b); -virtual void getIPServersList(std::list& ip_servers); - - // ONLY USED by p3face-config.cc WHICH WILL BE REMOVED. -virtual void getNetStatus(pqiNetStatus &status); -virtual bool getUPnPState(); -virtual bool getUPnPEnabled(); -virtual bool getDHTEnabled(); - -/************************************************************************************************/ -/* Extra IMPL Functions (used by p3PeerMgr, p3NetMgr + Setup) */ -/************************************************************************************************/ - -void setManagers(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr); -#ifdef RS_USE_DHT_STUNNER -void setAddrAssist(pqiAddrAssist *dhtStun, pqiAddrAssist *proxyStun); -#endif // RS_USE_DHT_STUNNER - -void tick(); - - // THESE MIGHT BE ADDED TO INTERFACE. -bool setLocalAddress(const struct sockaddr_storage &addr); -bool setExtAddress(const struct sockaddr_storage &addr); -bool getExtAddress(sockaddr_storage &addr); - - /*************** Setup ***************************/ -void addNetAssistConnect(uint32_t type, pqiNetAssistConnect *); -void addNetAssistFirewall(uint32_t type, pqiNetAssistFirewall *); - -void addNetListener(pqiNetListener *listener); - - // SHOULD MAKE THIS PROTECTED. -bool checkNetAddress(); /* check our address is sensible */ - -protected: - /****************** Internal Interface *******************/ -bool enableNetAssistFirewall(bool on); -bool netAssistFirewallEnabled(); -bool netAssistFirewallActive(); -bool netAssistFirewallShutdown(); - -bool enableNetAssistConnect(bool on); -bool netAssistConnectEnabled(); -bool netAssistConnectActive(); -bool netAssistConnectShutdown(); -bool netAssistConnectStats(uint32_t &netsize, uint32_t &localnetsize); - -void netAssistTick(); - -/* Assist Firewall */ -bool netAssistExtAddress(struct sockaddr_storage &extAddr); -bool netAssistFirewallPorts(uint16_t iport, uint16_t eport); - - /* Assist Connect */ -//virtual bool netAssistFriend(std::string id, bool on); (PUBLIC) -bool netAssistSetAddress(const struct sockaddr_storage &laddr, - const struct sockaddr_storage &eaddr, - uint32_t mode); - -bool netAssistAttach(bool on); - - - /* Internal Functions */ -void netReset(); - -void statusTick(); -void netStatusTick(); -void netStartup(); - - /* startup the bits */ -void netDhtInit(); -void netUdpInit(); -void netStunInit(); - - - -void netInit(); - -void netExtInit(); -void netExtCheck(); - -void netUpnpInit(); -void netUpnpCheck(); - -void netUnreachableCheck(); - - - /* net state via NetStateBox */ -void updateNetStateBox_temporal(); -void updateNetStateBox_startup(); -void updateNetStateBox_reset(); - void updateNatSetting(); - - /** Conservatively guess new external port, previous approach (aka always - * reset it to local port) break setups where external manually - * forwarded port is different then local port. A common case is having - * SSLH listening on port 80 on the router with public IP forwanding - * plain HTTP connections to a web server and --anyprot connections to - * retroshare to make censor/BOFH/bad firewall life a little more - * difficult */ - uint16_t guessNewExtPort() - { - uint16_t newExtPort = sockaddr_storage_port(mExtAddr); - if(!newExtPort) newExtPort = sockaddr_storage_port(mLocalAddr); - return newExtPort; - } - -private: - // These should have there own Mutex Protection, - ExtAddrFinder *mExtAddrFinder ; - - /* These are considered static from a MUTEX perspective */ - std::map mFwAgents; - std::map mDhts; - - std::list mNetListeners; - - p3PeerMgr *mPeerMgr; - p3LinkMgr *mLinkMgr; - - //p3BitDht *mBitDht; -#ifdef RS_USE_DHT_STUNNER - pqiAddrAssist *mDhtStunner = nullptr; - pqiAddrAssist *mProxyStunner = nullptr; -#endif // RS_USE_DHT_STUNNER - - RsMutex mNetMtx; /* protects below */ - -void netStatusReset_locked(); - - // TODO: Sat Oct 24 15:51:24 CEST 2015 The fact of having just two possible address is a flawed assumption, this should be redesigned soon. - struct sockaddr_storage mLocalAddr; - struct sockaddr_storage mExtAddr; - - uint32_t mNetMode; - uint16_t mVsDisc; - uint16_t mVsDht; - - rstime_t mNetInitTS; - uint32_t mNetStatus; - - bool mStatusChanged; - - bool mUseExtAddrFinder; - - /* network status flags (read by rsiface) */ - pqiNetStatus mNetFlags; - pqiNetStatus mOldNetFlags; - - - // Improved NetStatusBox, which uses the Stunners! - pqiNetStateBox mNetStateBox; - - rstime_t mDoNotNetCheckUntilTs; - RsNatTypeMode mOldNatType; - RsNatHoleMode mOldNatHole; - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; diff --git a/libretroshare/src/pqi/p3notify.cc b/libretroshare/src/pqi/p3notify.cc deleted file mode 100644 index 772a7e9bb..000000000 --- a/libretroshare/src/pqi/p3notify.cc +++ /dev/null @@ -1,314 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3notify.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2008 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/p3notify.h" -#include -#include - -RsNotify *rsNotify = NULL ; - -/* Output for retroshare-gui */ -bool p3Notify::NotifySysMessage(uint32_t &sysid, uint32_t &type, - std::string &title, std::string &msg) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - if (pendingSysMsgs.size() > 0) - { - p3NotifySysMsg smsg = pendingSysMsgs.front(); - pendingSysMsgs.pop_front(); - - sysid = smsg.sysid; - type = smsg.type; - title = smsg.title; - msg = smsg.msg; - - return true; - } - - return false; -} - - /* Output for retroshare-gui */ -bool p3Notify::NotifyLogMessage(uint32_t &sysid, uint32_t &type, - std::string &title, std::string &msg) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - if (pendingLogMsgs.size() > 0) - { - p3NotifyLogMsg smsg = pendingLogMsgs.front(); - pendingLogMsgs.pop_front(); - - sysid = smsg.sysid; - type = smsg.type; - title = smsg.title; - msg = smsg.msg; - - return true; - } - - return false; -} - - -bool p3Notify::NotifyPopupMessage(uint32_t &ptype, std::string &name, std::string &title, std::string &msg) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - if (pendingPopupMsgs.size() > 0) - { - p3NotifyPopupMsg pmsg = pendingPopupMsgs.front(); - pendingPopupMsgs.pop_front(); - - ptype = pmsg.type; - name = pmsg.name; - title = pmsg.title; - msg = pmsg.msg; - - return true; - } - - return false; -} - - - /* Control over Messages */ -bool p3Notify::GetSysMessageList(std::map &list) -{ - (void) list; /* suppress unused parameter warning */ - return false; -} - -bool p3Notify::GetPopupMessageList(std::map &list) -{ - (void) list; /* suppress unused parameter warning */ - return false; -} - - -bool p3Notify::SetSysMessageMode(uint32_t sysid, uint32_t mode) -{ - (void) sysid; /* suppress unused parameter warning */ - (void) mode; /* suppress unused parameter warning */ - return false; -} - -bool p3Notify::SetPopupMessageMode(uint32_t ptype, uint32_t mode) -{ - (void) ptype; /* suppress unused parameter warning */ - (void) mode; /* suppress unused parameter warning */ - return false; -} - - - /* Input from libretroshare */ -bool p3Notify::AddPopupMessage(uint32_t ptype, const std::string& name, const std::string& title, const std::string& msg) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - - p3NotifyPopupMsg pmsg; - - pmsg.type = ptype; - pmsg.name = name; - pmsg.title = title; - pmsg.msg = msg; - - pendingPopupMsgs.push_back(pmsg); - - return true; -} - - -bool p3Notify::AddSysMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - - p3NotifySysMsg smsg; - - smsg.sysid = sysid; - smsg.type = type; - smsg.title = title; - smsg.msg = msg; - - pendingSysMsgs.push_back(smsg); - - return true; -} - -bool p3Notify::AddLogMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - - p3NotifyLogMsg smsg; - - smsg.sysid = sysid; - smsg.type = type; - smsg.title = title; - smsg.msg = msg; - - pendingLogMsgs.push_back(smsg); - - return true; -} - - -bool p3Notify::GetFeedItem(RsFeedItem &item) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - if (pendingNewsFeed.size() > 0) - { - item = pendingNewsFeed.front(); - pendingNewsFeed.pop_front(); - - return true; - } - - return false; -} - - -bool p3Notify::AddFeedItem(uint32_t type, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4, uint32_t result1) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - pendingNewsFeed.push_back(RsFeedItem(type, id1, id2, id3, id4, result1)); - - return true; -} - -bool p3Notify::ClearFeedItems(uint32_t type) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - - std::list::iterator it; - for(it = pendingNewsFeed.begin(); it != pendingNewsFeed.end(); ) - { - if (it->mType == type) - { - it = pendingNewsFeed.erase(it); - } - else - { - ++it; - } - } - return true; -} - -#define FOR_ALL_NOTIFY_CLIENTS for(std::list::const_iterator it(notifyClients.begin());it!=notifyClients.end();++it) - -void p3Notify::notifyChatLobbyEvent(uint64_t lobby_id, uint32_t event_type,const RsGxsId& nickname,const std::string& any_string) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatLobbyEvent(lobby_id,event_type,nickname,any_string) ; } - -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::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::notifyChatStatus (const ChatId& chat_id, const std::string& status_string) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatStatus(chat_id,status_string) ; } -void p3Notify::notifyChatCleared (const ChatId& chat_id) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatCleared(chat_id) ; } - -void p3Notify::notifyChatLobbyTimeShift (int time_shift) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatLobbyTimeShift(time_shift) ; } -void p3Notify::notifyCustomState (const std::string& peer_id , const std::string& status_string ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyCustomState (peer_id,status_string) ; } -void p3Notify::notifyHashingInfo (uint32_t type , const std::string& fileinfo ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyHashingInfo (type,fileinfo) ; } -void p3Notify::notifyTurtleSearchResult (const RsPeerId& pid , uint32_t search_id , const std::list& files ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyTurtleSearchResult(pid,search_id,files) ; } -#warning MISSING CODE HERE -//void p3Notify::notifyTurtleSearchResult (uint32_t search_id , const std::list& groups ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyTurtleSearchResult(search_id,groups) ; } -void p3Notify::notifyPeerHasNewAvatar (std::string peer_id ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerHasNewAvatar(peer_id) ; } -void p3Notify::notifyOwnAvatarChanged () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyOwnAvatarChanged() ; } -void p3Notify::notifyOwnStatusMessageChanged() { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyOwnStatusMessageChanged() ; } -void p3Notify::notifyDiskFull (uint32_t location , uint32_t size_limit_in_MB ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDiskFull (location,size_limit_in_MB) ; } -void p3Notify::notifyPeerStatusChanged (const std::string& peer_id , uint32_t status ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerStatusChanged (peer_id,status) ; } - -void p3Notify::notifyPeerStatusChangedSummary () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerStatusChangedSummary() ; } -void p3Notify::notifyDiscInfoChanged () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDiscInfoChanged () ; } - -void p3Notify::notifyDownloadComplete (const std::string& fileHash ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDownloadComplete (fileHash) ; } -void p3Notify::notifyDownloadCompleteCount (uint32_t count ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDownloadCompleteCount (count) ; } -void p3Notify::notifyHistoryChanged (uint32_t msgId , int type) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyHistoryChanged (msgId,type) ; } - -bool p3Notify::cachePgpPassphrase(const std::string& s) -{ - clearPgpPassphrase() ; - cached_pgp_passphrase = s ; - - std::cerr << "(WW) Caching PGP passphrase." << std::endl; - return true ; -} -bool p3Notify::clearPgpPassphrase() -{ - std::cerr << "(WW) Clearing PGP passphrase." << std::endl; - - // Just whipe out the memory instead of just releasing it. - - for(uint32_t i=0;iaskForPassword(title,key_details,prev_is_bad,password,*cancelled) ) - return true; - - return false ; -} -bool p3Notify::askForPluginConfirmation (const std::string& plugin_filename, const std::string& plugin_file_hash,bool first_time) -{ - FOR_ALL_NOTIFY_CLIENTS - if( (*it)->askForPluginConfirmation(plugin_filename,plugin_file_hash,first_time)) - return true ; - - return false ; -} - -void p3Notify::registerNotifyClient(NotifyClient *cl) -{ - notifyClients.push_back(cl) ; -} - -bool p3Notify::unregisterNotifyClient(NotifyClient *nc) -{ - std::list::iterator it = std::find(notifyClients.begin(), notifyClients.end(), nc); - if(it != notifyClients.end()) - { - notifyClients.erase(it); - return true; - } - else - { - return false; - } -} diff --git a/libretroshare/src/pqi/p3notify.h b/libretroshare/src/pqi/p3notify.h deleted file mode 100644 index 3d78cdf8c..000000000 --- a/libretroshare/src/pqi/p3notify.h +++ /dev/null @@ -1,145 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3notify.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_P3_NOTIFY_INTERFACE_H -#define RS_P3_NOTIFY_INTERFACE_H - -#include "retroshare/rsnotify.h" -#include "retroshare/rsturtle.h" - -#include "util/rsthreads.h" - -class p3NotifySysMsg -{ - public: - - uint32_t sysid; - uint32_t type; - std::string title; - std::string msg; -}; - -class p3NotifyLogMsg -{ - public: - - uint32_t sysid; - uint32_t type; - std::string title; - std::string msg; -}; - -class p3NotifyPopupMsg -{ - public: - - uint32_t type; - std::string name; - std::string title; - std::string msg; -}; - - -class p3Notify: public RsNotify -{ - public: - - p3Notify() : noteMtx("p3Notify"), _disableAskPassword(false) { return; } - virtual ~p3Notify() { return; } - - virtual void registerNotifyClient(NotifyClient *nc) ; - virtual bool unregisterNotifyClient(NotifyClient *nc) ; - - /* Pull output methods for retroshare-gui */ - virtual bool NotifySysMessage(uint32_t &sysid, uint32_t &type, std::string &title, std::string &msg); - virtual bool NotifyPopupMessage(uint32_t &ptype, std::string &name, std::string &title, std::string &msg); - virtual bool NotifyLogMessage(uint32_t &sysid, uint32_t &type, std::string &title, std::string &msg); - - virtual bool GetFeedItem(RsFeedItem &item); - - /* Control over Messages */ - bool GetSysMessageList(std::map &list); - bool GetPopupMessageList(std::map &list); - - bool SetSysMessageMode(uint32_t sysid, uint32_t mode); - bool SetPopupMessageMode(uint32_t ptype, uint32_t mode); - - /* Notify messages */ - bool AddPopupMessage(uint32_t ptype, const std::string& name, const std::string& title, const std::string& msg); - bool AddSysMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg); - bool AddLogMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg); - bool AddFeedItem(uint32_t type, const std::string& id1, const std::string& id2 = "", const std::string& id3 = "", const std::string& id4 = "", uint32_t result1 = 0); - bool ClearFeedItems(uint32_t type); - - // Notifications of clients. Can be called from anywhere inside libretroshare. - // - void notifyListPreChange (int /* list */, int /* type */) ; - void notifyListChange (int /* list */, int /* type */) ; - void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) ; - void notifyChatMessage (const ChatMessage& /* msg */) ; - void notifyChatStatus (const ChatId& /* chat_id */, const std::string& /* status_string */) ; - void notifyChatCleared (const ChatId& /* chat_id */) ; - void notifyChatLobbyEvent (uint64_t /* lobby id */, uint32_t /* event type */ , const RsGxsId & /* nickname */, const std::string& /* any string */) ; - void notifyChatLobbyTimeShift (int /* time_shift*/) ; - void notifyCustomState (const std::string& /* peer_id */, const std::string& /* status_string */) ; - void notifyHashingInfo (uint32_t /* type */, const std::string& /* fileinfo */) ; - void notifyTurtleSearchResult (const RsPeerId &pid, uint32_t /* search_id */, const std::list& /* files */) ; -#warning MISSING CODE HERE -// void notifyTurtleSearchResult (uint32_t /* search_id */, const std::list& /* groups */) ; - void notifyPeerHasNewAvatar (std::string /* peer_id */) ; - void notifyOwnAvatarChanged () ; - void notifyOwnStatusMessageChanged () ; - void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) ; - void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) ; - void notifyConnectionWithoutCert (); - - void notifyPeerStatusChangedSummary () ; - void notifyDiscInfoChanged () ; - - void notifyDownloadComplete (const std::string& /* fileHash */) ; - void notifyDownloadCompleteCount (uint32_t /* count */) ; - void notifyHistoryChanged (uint32_t /* msgId */, int /* type */) ; - - bool askForPassword (const std::string& title, const std::string& /* key_details */, bool /* prev_is_bad */, std::string&, bool *cancelled /* password */ ) ; - bool askForPluginConfirmation (const std::string& /* plugin_filename */, const std::string& /* plugin_file_hash */,bool first_time) ; - - virtual bool cachePgpPassphrase (const std::string& /* pgp_passphrase */) ; - virtual bool clearPgpPassphrase () ; - - virtual bool setDisableAskPassword (const bool /*bValue*/) ; - - private: - - RsMutex noteMtx; - - std::list pendingSysMsgs; - std::list pendingLogMsgs; - std::list pendingPopupMsgs; - std::list pendingNewsFeed; - - std::list notifyClients ; - - std::string cached_pgp_passphrase; - bool _disableAskPassword; -}; - - -#endif diff --git a/libretroshare/src/pqi/p3peermgr.cc b/libretroshare/src/pqi/p3peermgr.cc deleted file mode 100644 index 83c4d9366..000000000 --- a/libretroshare/src/pqi/p3peermgr.cc +++ /dev/null @@ -1,3183 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3peermgr.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2011 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#include // for std::vector -#include // for std::random_shuffle - -#include "rsserver/p3face.h" -#include "util/rsnet.h" -#include "pqi/authgpg.h" -#include "pqi/authssl.h" - -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" -#include "pqi/p3historymgr.h" -#include "pqi/pqinetwork.h" // for getLocalAddresses - -#include "util/rsprint.h" -#include "util/rsstring.h" -#include "util/rsdebug.h" - -#include "rsitems/rsconfigitems.h" - -#include "retroshare/rsiface.h" // Needed for rsicontrol (should remove this dependancy) -#include "retroshare/rspeers.h" // Needed for Group Parameters. -#include "retroshare/rsbanlist.h" // Needed for banned IPs - -/* Network setup States */ - -//Defined and used in /libretroshare/src/pqi/p3netmgr.cc -//const uint32_t RS_NET_NEEDS_RESET = 0x0000; -//const uint32_t RS_NET_UNKNOWN = 0x0001; -//const uint32_t RS_NET_UPNP_INIT = 0x0002; -//const uint32_t RS_NET_UPNP_SETUP = 0x0003; -//const uint32_t RS_NET_EXT_SETUP = 0x0004; -//const uint32_t RS_NET_DONE = 0x0005; -//const uint32_t RS_NET_LOOPBACK = 0x0006; -//const uint32_t RS_NET_DOWN = 0x0007; - -//const uint32_t MIN_TIME_BETWEEN_NET_RESET = 5; - -//const uint32_t PEER_IP_CONNECT_STATE_MAX_LIST_SIZE = 4; - -static struct RsLog::logInfo p3peermgrzoneInfo = {RsLog::Default, "p3peermgr"}; -#define p3peermgrzone &p3peermgrzoneInfo - -/**** - * #define PEER_DEBUG 1 - * #define PEER_DEBUG_LOG 1 - ***/ - -#define MAX_AVAIL_PERIOD 230 //times a peer stay in available state when not connected -#define MIN_RETRY_PERIOD 140 - -static const std::string kConfigDefaultProxyServerIpAddr = "127.0.0.1"; -static const uint16_t kConfigDefaultProxyServerPortTor = 9050; // standard port. -static const uint16_t kConfigDefaultProxyServerPortI2P = 4447; // I2Pd's standard port - -static const std::string kConfigKeyExtIpFinder = "USE_EXTR_IP_FINDER"; -static const std::string kConfigKeyProxyServerIpAddrTor = "PROXY_SERVER_IPADDR"; -static const std::string kConfigKeyProxyServerPortTor = "PROXY_SERVER_PORT"; -static const std::string kConfigKeyProxyServerIpAddrI2P = "PROXY_SERVER_IPADDR_I2P"; -static const std::string kConfigKeyProxyServerPortI2P = "PROXY_SERVER_PORT_I2P"; - -void printConnectState(std::ostream &out, peerState &peer); - -peerState::peerState() - :skip_pgp_signature_validation(false),netMode(RS_NET_MODE_UNKNOWN), vs_disc(RS_VS_DISC_FULL), vs_dht(RS_VS_DHT_FULL), lastcontact(0), - hiddenNode(false), hiddenPort(0), hiddenType(RS_HIDDEN_TYPE_NONE) -{ - sockaddr_storage_clear(localaddr); - sockaddr_storage_clear(serveraddr); - - return; -} - -std::string textPeerConnectState(peerState &state) -{ - std::string out = "Id: " + state.id.toStdString() + "\n"; - rs_sprintf_append(out, "NetMode: %lu\n", state.netMode); - rs_sprintf_append(out, "VisState: Disc: %u Dht: %u\n", state.vs_disc, state.vs_dht); - - out += "laddr: "; - out += sockaddr_storage_tostring(state.localaddr); - out += "\neaddr: "; - out += sockaddr_storage_tostring(state.serveraddr); - out += "\n"; - - return out; -} - - -p3PeerMgrIMPL::p3PeerMgrIMPL(const RsPeerId& ssl_own_id, const RsPgpId& gpg_own_id, const std::string& gpg_own_name, const std::string& ssl_own_location) - :p3Config(), mPeerMtx("p3PeerMgr"), mStatusChanged(false) -{ - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - mLinkMgr = NULL; - mNetMgr = NULL; - - /* setup basics of own state */ - mOwnState.id = ssl_own_id ; - mOwnState.gpg_id = gpg_own_id ; - mOwnState.name = gpg_own_name ; - mOwnState.location = ssl_own_location ; - mOwnState.netMode = RS_NET_MODE_UPNP; // Default to UPNP. - mOwnState.vs_disc = RS_VS_DISC_FULL; - mOwnState.vs_dht = RS_VS_DHT_FULL; - - // setup default ProxyServerAddress. - // Tor - sockaddr_storage_clear(mProxyServerAddressTor); - sockaddr_storage_ipv4_aton(mProxyServerAddressTor, - kConfigDefaultProxyServerIpAddr.c_str()); - sockaddr_storage_ipv4_setport(mProxyServerAddressTor, - kConfigDefaultProxyServerPortTor); - // I2P - sockaddr_storage_clear(mProxyServerAddressI2P); - sockaddr_storage_ipv4_aton(mProxyServerAddressI2P, - kConfigDefaultProxyServerIpAddr.c_str()); - sockaddr_storage_ipv4_setport(mProxyServerAddressI2P, - kConfigDefaultProxyServerPortI2P); - - mProxyServerStatusTor = RS_NET_PROXY_STATUS_UNKNOWN ; - mProxyServerStatusI2P = RS_NET_PROXY_STATUS_UNKNOWN; - } - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgr() Startup" << std::endl; -#endif - - - return; -} - -void p3PeerMgrIMPL::setManagers(p3LinkMgrIMPL *linkMgr, p3NetMgrIMPL *netMgr) -{ - mLinkMgr = linkMgr; - mNetMgr = netMgr; -} - - -bool p3PeerMgrIMPL::setupHiddenNode(const std::string &hiddenAddress, const uint16_t hiddenPort) -{ - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setupHiddenNode()"; - std::cerr << " Address: " << hiddenAddress; - std::cerr << " Port: " << hiddenPort; - std::cerr << std::endl; -#endif - - mOwnState.hiddenNode = true; - mOwnState.hiddenPort = hiddenPort; - mOwnState.hiddenDomain = hiddenAddress; - mOwnState.hiddenType = hiddenDomainToHiddenType(hiddenAddress); - } - - forceHiddenNode(); - return true; -} - - -bool p3PeerMgrIMPL::forceHiddenNode() -{ - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - if (RS_NET_MODE_HIDDEN != mOwnState.netMode) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::forceHiddenNode() Required!"; - std::cerr << std::endl; -#endif - } - mOwnState.hiddenNode = true; - mOwnState.hiddenType = hiddenDomainToHiddenType(mOwnState.hiddenDomain); - - // force external address - otherwise its invalid. - sockaddr_storage_clear(mOwnState.serveraddr); - sockaddr_storage_ipv4_aton(mOwnState.serveraddr, "0.0.0.0"); - sockaddr_storage_ipv4_setport(mOwnState.serveraddr, 0); - } - - setOwnNetworkMode(RS_NET_MODE_HIDDEN); - - // switch off DHT too. - setOwnVisState(mOwnState.vs_disc, RS_VS_DHT_OFF); - - // Force the Port. - struct sockaddr_storage loopback; - sockaddr_storage_clear(loopback); - sockaddr_storage_ipv4_aton(loopback, "127.0.0.1"); - uint16_t port = sockaddr_storage_port(mOwnState.localaddr); - sockaddr_storage_ipv4_setport(loopback, port); - - setLocalAddress(AuthSSL::getAuthSSL()->OwnId(), loopback); - - mNetMgr->setIPServersEnabled(false); - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - return true; -} - - -bool p3PeerMgrIMPL::setOwnNetworkMode(uint32_t netMode) -{ - bool changed = false; - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setOwnNetworkMode() :"; - std::cerr << " Existing netMode: " << mOwnState.netMode; - std::cerr << " Input netMode: " << netMode; - std::cerr << std::endl; -#endif - - if (mOwnState.netMode != (netMode & RS_NET_MODE_ACTUAL)) - { - mOwnState.netMode = (netMode & RS_NET_MODE_ACTUAL); - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - changed = true; - } - } - - // Pass on Flags to NetMgr. - mNetMgr->setNetworkMode((netMode & RS_NET_MODE_ACTUAL)); - return changed; -} - -bool p3PeerMgrIMPL::setOwnVisState(uint16_t vs_disc, uint16_t vs_dht) -{ - bool changed = false; - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::string out; - rs_sprintf(out, "p3PeerMgr::setOwnVisState() Existing vis: %u/%u Input vis: %u/%u", - mOwnState.vs_disc, mOwnState.vs_dht, vs_disc, vs_dht); - rslog(RSL_WARNING, p3peermgrzone, out); - -#ifdef PEER_DEBUG - std::cerr << out.c_str() << std::endl; -#endif - - if (mOwnState.vs_disc != vs_disc || mOwnState.vs_dht != vs_dht) - { - mOwnState.vs_disc = vs_disc; - mOwnState.vs_dht = vs_dht; - changed = true; - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } - } - - // Pass on Flags to NetMgr. - mNetMgr->setVisState(vs_disc, vs_dht); - - return changed; -} - - -void p3PeerMgrIMPL::tick() -{ - static const rstime_t INTERVAL_BETWEEN_LOCATION_CLEANING = 300 ; // Remove unused locations and clean IPs every 10 minutes. - - static rstime_t last_friends_check = time(NULL) ; // first cleaning after 1 hour. - - rstime_t now = time(NULL) ; - - if(now > INTERVAL_BETWEEN_LOCATION_CLEANING + last_friends_check ) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::tick(): cleaning unused locations." << std::endl ; -#endif - - rslog(RSL_WARNING, p3peermgrzone, "p3PeerMgr::tick() removeUnusedLocations()"); - - removeUnusedLocations() ; - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::tick(): cleaning banned/old IPs." << std::endl ; -#endif - removeBannedIps() ; - - last_friends_check = now ; - } -} - - -/******************************** Network Status ********************************* - * Configuration Loading / Saving. - */ - - -const RsPeerId& p3PeerMgrIMPL::getOwnId() -{ - return AuthSSL::getAuthSSL()->OwnId(); -} - - -bool p3PeerMgrIMPL::getOwnNetStatus(peerState &state) -{ - RS_STACK_MUTEX(mPeerMtx); - state = mOwnState; - return true; -} - -bool p3PeerMgrIMPL::isFriend(const RsPeerId& id) -{ -#ifdef PEER_DEBUG_COMMON - std::cerr << "p3PeerMgrIMPL::isFriend(" << id << ") called" << std::endl; -#endif - RS_STACK_MUTEX(mPeerMtx); - bool ret = (mFriendList.end() != mFriendList.find(id)); -#ifdef PEER_DEBUG_COMMON - std::cerr << "p3PeerMgrIMPL::isFriend(" << id << ") returning : " << ret << std::endl; -#endif - return ret; -} -bool p3PeerMgrIMPL::isSslOnlyFriend(const RsPeerId& id) -{ -#ifdef PEER_DEBUG_COMMON - std::cerr << "p3PeerMgrIMPL::isFriend(" << id << ") called" << std::endl; -#endif - RS_STACK_MUTEX(mPeerMtx); - auto it = mFriendList.find(id); - bool ret = it != mFriendList.end() && it->second.skip_pgp_signature_validation ; - -#ifdef PEER_DEBUG_COMMON - std::cerr << "p3PeerMgrIMPL::isFriend(" << id << ") returning : " << ret << std::endl; -#endif - return ret; -} - -bool p3PeerMgrIMPL::getPeerName(const RsPeerId &ssl_id, std::string &name) -{ - RS_STACK_MUTEX(mPeerMtx); - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { - return false; - } - - name = it->second.name + " (" + it->second.location + ")"; - return true; -} - -bool p3PeerMgrIMPL::getGpgId(const RsPeerId &ssl_id, RsPgpId &gpgId) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { - return false; - } - - gpgId = it->second.gpg_id; - return true; -} - -/**** HIDDEN STUFF ****/ - -bool p3PeerMgrIMPL::isHidden() -{ - RS_STACK_MUTEX(mPeerMtx); - return mOwnState.hiddenNode; -} - -/** - * @brief checks the hidden type of the own peer. - * @param type type to check - * @return true when the peer has the same hidden type than type - */ -bool p3PeerMgrIMPL::isHidden(const uint32_t type) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - switch (type) { - case RS_HIDDEN_TYPE_TOR: - return mOwnState.hiddenType == RS_HIDDEN_TYPE_TOR; - break; - case RS_HIDDEN_TYPE_I2P: - return mOwnState.hiddenType == RS_HIDDEN_TYPE_I2P; - break; - default: -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::isHidden(" << type << ") unkown type -> false"; - std::cerr << std::endl; -#endif - return false; - break; - } -} - -bool p3PeerMgrIMPL::isHiddenPeer(const RsPeerId &ssl_id) -{ - return isHiddenPeer(ssl_id, RS_HIDDEN_TYPE_NONE); -} - -/** - * @brief checks the hidden type of a given ssl id. When type RS_HIDDEN_TYPE_NONE is choosen it returns the 'hiddenNode' value instead - * @param ssl_id to check - * @param type type to check. Use RS_HIDDEN_TYPE_NONE to check 'hiddenNode' value - * @return true when the peer has the same hidden type than type - */ -bool p3PeerMgrIMPL::isHiddenPeer(const RsPeerId &ssl_id, const uint32_t type) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::isHiddenPeer(" << ssl_id << ") Missing Peer => false"; - std::cerr << std::endl; -#endif - - return false; - } - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::isHiddenPeer(" << ssl_id << ") = " << (it->second).hiddenNode; - std::cerr << std::endl; -#endif - switch (type) { - case RS_HIDDEN_TYPE_TOR: - return (it->second).hiddenType == RS_HIDDEN_TYPE_TOR; - break; - case RS_HIDDEN_TYPE_I2P: - return (it->second).hiddenType == RS_HIDDEN_TYPE_I2P; - break; - default: - return (it->second).hiddenNode; - break; - } -} - -bool hasEnding (std::string const &fullString, std::string const &ending) { - if (fullString.length() < ending.length()) - return false; - - return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending)); -} - -/** - * @brief resolves the hidden type (tor or i2p) from a domain - * @param domain to check - * @return RS_HIDDEN_TYPE_TOR, RS_HIDDEN_TYPE_I2P or RS_HIDDEN_TYPE_NONE - * - * Tor: ^[a-z2-7]{16}\.onion$ - * - * I2P: There is more than one address: - * - pub. key in base64 - * - hash in base32 ( ^[a-z2-7]{52}\.b32\.i2p$ ) - * - "normal" .i2p domains - */ -uint32_t p3PeerMgrIMPL::hiddenDomainToHiddenType(const std::string &domain) -{ - if(hasEnding(domain, ".onion")) - return RS_HIDDEN_TYPE_TOR; - if(hasEnding(domain, ".i2p")) - return RS_HIDDEN_TYPE_I2P; - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::hiddenDomainToHiddenType() unknown hidden type: " << domain; - std::cerr << std::endl; -#endif - return RS_HIDDEN_TYPE_UNKNOWN; -} - -/** - * @brief returns the hidden type of a peer - * @param ssl_id peer id - * @return hidden type - */ -uint32_t p3PeerMgrIMPL::getHiddenType(const RsPeerId &ssl_id) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - if (ssl_id == AuthSSL::getAuthSSL()->OwnId()) - return mOwnState.hiddenType; - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::getHiddenType(" << ssl_id << ") Missing Peer => false"; - std::cerr << std::endl; -#endif - - return false; - } - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::getHiddenType(" << ssl_id << ") = " << (it->second).hiddenType; - std::cerr << std::endl; -#endif - return (it->second).hiddenType; -} - -bool p3PeerMgrIMPL::isHiddenNode(const RsPeerId& id) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - if (id == AuthSSL::getAuthSSL()->OwnId()) - return mOwnState.hiddenNode ; - else - { - std::map::const_iterator it = mFriendList.find(id); - - if (it == mFriendList.end()) - { - std::cerr << "p3PeerMgrIMPL::isHiddenNode() Peer Not Found" << std::endl; - return false; - } - return it->second.hiddenNode ; - } -} - -/** - * @brief sets hidden domain and port for a given ssl ID - * @param ssl_id peer to set domain and port for - * @param domain_addr - * @param domain_port - * @return true on success - */ -bool p3PeerMgrIMPL::setHiddenDomainPort(const RsPeerId &ssl_id, const std::string &domain_addr, const uint16_t domain_port) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setHiddenDomainPort()"; - std::cerr << std::endl; -#endif - - std::string domain = domain_addr; - // trim whitespace! - size_t pos = domain.find_last_not_of(" \t\n"); - if (std::string::npos != pos) - { - domain = domain.substr(0, pos + 1); - } - pos = domain.find_first_not_of(" \t\n"); - if (std::string::npos != pos) - { - domain = domain.substr(pos); - } - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - if (ssl_id == AuthSSL::getAuthSSL()->OwnId()) - { - mOwnState.hiddenNode = true; - mOwnState.hiddenDomain = domain; - mOwnState.hiddenPort = domain_port; - mOwnState.hiddenType = hiddenDomainToHiddenType(domain); -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setHiddenDomainPort() Set own State"; - std::cerr << std::endl; -#endif - return true; - } - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setHiddenDomainPort() Peer Not Found"; - std::cerr << std::endl; -#endif - return false; - } - - it->second.hiddenDomain = domain; - it->second.hiddenPort = domain_port; - it->second.hiddenNode = true; - it->second.hiddenType = hiddenDomainToHiddenType(domain); -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setHiddenDomainPort() Set Peers State"; - std::cerr << std::endl; -#endif - - return true; -} - -/** - * @brief sets the proxy server address for a hidden service - * @param type hidden service type - * @param proxy_addr proxy address - * @return true on success - */ -bool p3PeerMgrIMPL::setProxyServerAddress(const uint32_t type, const struct sockaddr_storage &proxy_addr) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - switch (type) { - case RS_HIDDEN_TYPE_I2P: - if (!sockaddr_storage_same(mProxyServerAddressI2P, proxy_addr)) - { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - mProxyServerAddressI2P = proxy_addr; - } - break; - case RS_HIDDEN_TYPE_TOR: - if (!sockaddr_storage_same(mProxyServerAddressTor, proxy_addr)) - { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - mProxyServerAddressTor = proxy_addr; - } - break; - case RS_HIDDEN_TYPE_UNKNOWN: - default: -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setProxyServerAddress() unknown hidden type " << type << " -> false"; - std::cerr << std::endl; -#endif - return false; - } - - return true; -} - -bool p3PeerMgrIMPL::resetOwnExternalAddressList() -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - mOwnState.ipAddrs.mLocal.mAddrs.clear() ; - mOwnState.ipAddrs.mExt.mAddrs.clear() ; - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - return true ; -} - -/** - * @brief returs proxy server status for a hidden service proxy - * @param type hidden service type - * @param proxy_status - * @return true on success - */ -bool p3PeerMgrIMPL::getProxyServerStatus(const uint32_t type, uint32_t& proxy_status) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - switch (type) { - case RS_HIDDEN_TYPE_I2P: - proxy_status = mProxyServerStatusI2P; - break; - case RS_HIDDEN_TYPE_TOR: - proxy_status = mProxyServerStatusTor; - break; - case RS_HIDDEN_TYPE_UNKNOWN: - default: -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::getProxyServerStatus() unknown hidden type " << type << " -> false"; - std::cerr << std::endl; -#endif - return false; - } - - return true; -} - -/** - * @brief returs proxy server address for a hidden service proxy - * @param type hidden service type - * @param proxy_addr - * @return true on success - */ -bool p3PeerMgrIMPL::getProxyServerAddress(const uint32_t type, struct sockaddr_storage &proxy_addr) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - switch (type) { - case RS_HIDDEN_TYPE_I2P: - proxy_addr = mProxyServerAddressI2P; - break; - case RS_HIDDEN_TYPE_TOR: - proxy_addr = mProxyServerAddressTor; - break; - case RS_HIDDEN_TYPE_UNKNOWN: - default: -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::getProxyServerAddress() unknown hidden type " << type << " -> false"; - std::cerr << std::endl; -#endif - return false; - } - return true; -} - -/** - * @brief looks up the proxy address and domain/port that have to be used when connecting to a peer - * @param ssl_id peer to connect to - * @param proxy_addr proxy address to be used - * @param domain_addr domain to connect to - * @param domain_port port to connect to - * @return true on success - */ -bool p3PeerMgrIMPL::getProxyAddress(const RsPeerId &ssl_id, struct sockaddr_storage &proxy_addr, std::string &domain_addr, uint16_t &domain_port) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { - return false; - } - - if (!it->second.hiddenNode) - { - return false; - } - - domain_addr = it->second.hiddenDomain; - domain_port = it->second.hiddenPort; - - switch (it->second.hiddenType) { - case RS_HIDDEN_TYPE_I2P: - proxy_addr = mProxyServerAddressI2P; - break; - case RS_HIDDEN_TYPE_TOR: - proxy_addr = mProxyServerAddressTor; - break; - case RS_HIDDEN_TYPE_UNKNOWN: - default: -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::getProxyAddress() no valid hidden type (" << it->second.hiddenType << ") for peer id " << ssl_id << " -> false"; - std::cerr << std::endl; -#endif - return false; - } - return true; -} - -// Placeholder until we implement this functionality. -uint32_t p3PeerMgrIMPL::getConnectionType(const RsPeerId &/*sslId*/) -{ - return RS_NET_CONN_TYPE_FRIEND; -} - -int p3PeerMgrIMPL::getFriendCount(bool ssl, bool online) -{ - if (online) { - // count only online id's - std::list onlineIds; - mLinkMgr->getOnlineList(onlineIds); - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::set gpgIds; - int count = 0; - - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) { - if (online && std::find(onlineIds.begin(), onlineIds.end(), it->first) == onlineIds.end()) { - continue; - } - if (ssl) { - // count ssl id's only - count++; - } else { - // count unique gpg id's - gpgIds.insert(it->second.gpg_id); - } - } - - return ssl ? count : gpgIds.size(); - } - - if (ssl) { - // count all ssl id's - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - return mFriendList.size(); - } - - // count all gpg id's - std::list gpgIds; - AuthGPG::getAuthGPG()->getGPGAcceptedList(gpgIds); - - // add own gpg id, if we have more than one location - std::list ownSslIds; - getAssociatedPeers(AuthGPG::getAuthGPG()->getGPGOwnId(), ownSslIds); - - return gpgIds.size() + ((ownSslIds.size() > 0) ? 1 : 0); -} - -bool p3PeerMgrIMPL::getFriendNetStatus(const RsPeerId &id, peerState &state) -{ - RS_STACK_MUTEX(mPeerMtx); - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(id); - if (it == mFriendList.end()) return false; - - state = it->second; - return true; -} - - -int p3PeerMgrIMPL::getConnectAddresses( - const RsPeerId &id, sockaddr_storage &lAddr, sockaddr_storage &eAddr, - pqiIpAddrSet &histAddrs, std::string &dyndns ) -{ - - RS_STACK_MUTEX(mPeerMtx); - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(id); - if (it == mFriendList.end()) - { - /* ERROR */ - std::cerr << "p3PeerMgrIMPL::getConnectAddresses() ERROR unknown Peer"; - std::cerr << std::endl; - return 0; - } - - lAddr = it->second.localaddr; - eAddr = it->second.serveraddr; - histAddrs = it->second.ipAddrs; - dyndns = it->second.dyndns; - - return 1; -} - - - -bool p3PeerMgrIMPL::haveOnceConnected() -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* check for existing */ - for(auto it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (it->second.lastcontact > 0) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::haveOnceConnected() lastcontact: "; - std::cerr << time(NULL) - it->second.lastcontact << " for id: " << it->first; - std::cerr << std::endl; -#endif - - return true; - } - } - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::haveOnceConnected() all Last Contacts = 0"; - std::cerr << std::endl; -#endif - - return false; -} - - -bool p3PeerMgrIMPL::notifyPgpKeyReceived(const RsPgpId& pgp_id) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - bool changed = false; - - for(auto it(mFriendList.begin());it!=mFriendList.end();++it) - { - if(it->second.gpg_id == pgp_id) - { - std::cerr << "(WW) notification that full key " << pgp_id << " is available. Reseting short invite flag for peer " << it->first << std::endl; - it->second.skip_pgp_signature_validation = false; - - changed = true; - } - } - - if(changed) - IndicateConfigChanged(); - - return true; -} - -/*******************************************************************/ -/*******************************************************************/ - -bool p3PeerMgrIMPL::addFriend(const RsPeerId& input_id, const RsPgpId& input_gpg_id, uint32_t netMode, uint16_t vs_disc, uint16_t vs_dht, rstime_t lastContact,ServicePermissionFlags service_flags) -{ - bool notifyLinkMgr = false; - RsPeerId id = input_id ; - RsPgpId gpg_id = input_gpg_id ; - -#ifdef PEER_DEBUG_LOG - rslog(RSL_WARNING, p3peermgrzone, "p3PeerMgr::addFriend() id: " + id.toStdString()); -#endif - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - RsErr() << "p3PeerMgrIMPL::addFriend() cannot add own id as a friend. That's a bug!" << std::endl; - /* (1) already exists */ - return false; - } - /* so four possibilities - * (1) already exists as friend -> do nothing. - * (2) is in others list -> move over. - * (3) is non-existant -> create new one. - */ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::addFriend() " << id << "; gpg_id : " << gpg_id << std::endl; -#endif - - std::map::iterator it; - if (mFriendList.end() != (it=mFriendList.find(id))) - { - // The friend may already be here, including with a short invite (meaning the PGP key is unknown). - - if(it->second.gpg_id != input_gpg_id)// already exists as a friend with a different PGP id!! - { - RsErr() << "Trying to add SSL id (" << id << ") that is already a friend with existing PGP key (" << it->second.gpg_id << ") but using a different PGP key (" << input_gpg_id << "). This is a bug!" << std::endl; - return false; - } - else - return true; /* (1) already exists */ - } - - // check that the PGP key is known - - if(!AuthGPG::getAuthGPG()->isGPGId(gpg_id)) - { - RsErr() << "Trying to add SSL id (" << id << ") to be validated with unknown PGP key (" << gpg_id << ". This is a bug!" << std::endl; - return false; - } - - //Authentication is now tested at connection time, we don't store the ssl cert anymore - // - if (!AuthGPG::getAuthGPG()->isGPGAccepted(gpg_id) && gpg_id != AuthGPG::getAuthGPG()->getGPGOwnId()) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::addFriend() gpg is not accepted" << std::endl; -#endif - /* no auth */ - return false; - } - - // after that, we know that we have the key, because AuthGPG wouldn't answer yes for a key it doesn't know. - - /* check if it is in others */ -// if (mOthersList.end() != (it = mOthersList.find(id))) -// { -// /* (2) in mOthersList -> move over */ -//#ifdef PEER_DEBUG -// std::cerr << "p3PeerMgrIMPL::addFriend() Move from Others" << std::endl; -//#endif -// if(!it->second.gpg_id.isNull() && it->second.gpg_id != input_gpg_id)// already exists as a friend with a different PGP id!! -// RsErr() << "Trying to add SSL id (" << id << ") that is already known (but not friend) with existing PGP key (" << it->second.gpg_id -// << ") but using a different PGP key (" << input_gpg_id << "). This looks like a bug! The friend will be added again with the new PGP key ID." << std::endl; -// -// mFriendList[id] = it->second; -// mOthersList.erase(it); -// -// it = mFriendList.find(id); -// -// /* setup connectivity parameters */ -// it->second.vs_disc = vs_disc; -// it->second.vs_dht = vs_dht; -// -// it->second.netMode = netMode; -// it->second.lastcontact = lastContact; -// -// it->second.gpg_id = input_gpg_id; -// it->second.skip_pgp_signature_validation = false; -// -// mStatusChanged = true; -// -// notifyLinkMgr = true; -// -// IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ -// } -// else - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::addFriend() Creating New Entry" << std::endl; -#endif - - /* create a new entry */ - peerState pstate; - - pstate.id = id; - pstate.gpg_id = gpg_id; - pstate.name = AuthGPG::getAuthGPG()->getGPGName(gpg_id); - - pstate.vs_disc = vs_disc; - pstate.vs_dht = vs_dht; - pstate.netMode = netMode; - pstate.lastcontact = lastContact; - - pstate.gpg_id = input_gpg_id; - pstate.skip_pgp_signature_validation = false; - - /* addr & timestamps -> auto cleared */ - - mFriendList[id] = pstate; - - mStatusChanged = true; - - notifyLinkMgr = true; - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } - - if (notifyLinkMgr) - { - mLinkMgr->addFriend(id, vs_dht != RS_VS_DHT_OFF); - } - - service_flags &= servicePermissionFlags(gpg_id) ; // Always reduce the permissions. -#ifdef RS_CHATSERVER //Defined by chatserver - setServicePermissionFlags(gpg_id,RS_NODE_PERM_NONE) ; -#else - setServicePermissionFlags(gpg_id,service_flags) ; -#endif - -#ifdef PEER_DEBUG - printPeerLists(std::cerr); - mLinkMgr->printPeerLists(std::cerr); -#endif - - return true; -} - - -bool p3PeerMgrIMPL::addSslOnlyFriend( const RsPeerId& sslId, const RsPgpId& pgp_id, const RsPeerDetails& dt ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(sslId.isNull()) - return failure("Cannot add a null ID as SSL-only friend"); - - if(pgp_id.isNull()) - return failure( " Cannot add as SSL-only friend a peer with null PGP"); - - if(sslId == getOwnId()) - return failure( "Cannot add yourself as SSL-only friend id:" + - sslId.toStdString() ); - - bool alreadySslFriend = false; - peerState pstate; - - { RS_STACK_MUTEX(mPeerMtx); - auto it = mFriendList.find(sslId); - if( it != mFriendList.end() ) - { - alreadySslFriend = true; - - /* If it is already friend override pstate so we don't loose already - * known information about the peer, in particular overriding - * pstate.skip_pgp_signature_validation is important for security. - */ - pstate = it->second; - } - } // RS_STACK_MUTEX(mPeerMtx); - - /* If it is already friend check if PGP id of the invite matches with the - * PGP id we already know, to avoid nasty tricks with malevolently forged - * short invites.*/ - if(alreadySslFriend && pstate.gpg_id != pgp_id) - return failure( "Cannot SSL-only friend for a pre-existing friend with " - "mismatching PGP-id known: " + - pstate.gpg_id.toStdString() + " new: " + - pgp_id.toStdString() ); - - /* It is very important to be expecially carefull setting - * pstate.skip_pgp_signature_validation to true because this effectively - * disables PGP signature verification on connection attempt. - * This check in particular avoid someone attempting to trick the user into - * accepting as SSL-only friend a malevolently forged short invite, with the - * PGP id of an already known friend but the SSL-id of a location generated - * by the attacker which doesn't have access to the legitimate PGP - * certificate. - * In that case being pstate.skip_pgp_signature_validation false on - * connection attempt the PGP signaure verification would fail and the - * connection closed. - * Instead if pstate.skip_pgp_signature_validation would have been - * superficially set to true the PGP signature verification would have been - * skipped and the attacker connection would be accepted. - * If the PGP key is available add it as full friend. */ - if(AuthGPG::getAuthGPG()->isPgpPubKeyAvailable(pgp_id)) - AuthGPG::getAuthGPG()->AllowConnection(pgp_id, true); - else - pstate.skip_pgp_signature_validation = true; - - pstate.gpg_id = pgp_id; - pstate.id = sslId; - - /* At this point if we got info about the peer just update with the new - * values. */ - if(!dt.name.empty()) pstate.name = dt.name; - if(!dt.dyndns.empty()) - { - pstate.dyndns = dt.dyndns; - if(dt.extPort) - { - /* If there is no IPv4 address available yet add a placeholder to - * not loose the port, because the address is invalid. */ - if(!sockaddr_storage_isValidNet(pstate.serveraddr)) - sockaddr_storage_inet_pton(pstate.serveraddr, "192.0.2.0"); - sockaddr_storage_setport(pstate.serveraddr, dt.extPort); - } - } - pstate.hiddenNode = dt.isHiddenNode; - if(!dt.hiddenNodeAddress.empty()) - pstate.hiddenDomain = dt.hiddenNodeAddress; - if(dt.hiddenNodePort) pstate.hiddenPort = dt.hiddenNodePort; - if(dt.hiddenType) pstate.hiddenType = dt.hiddenType; - if(!dt.location.empty()) pstate.location = dt.location; - - { RS_STACK_MUTEX(mPeerMtx); - mFriendList[sslId] = pstate; - mStatusChanged = true; - } // RS_STACK_MUTEX(mPeerMtx); - - IndicateConfigChanged(); - mLinkMgr->addFriend(sslId, dt.vs_dht != RS_VS_DHT_OFF); - - /* To update IP addresses is much more confortable to use locators, beside - * of the easy to use another benefit is that this way we don't loose - * previously known IP addresses */ - if(!dt.isHiddenNode) - { - for(const std::string& ipStr : dt.ipAddressList) - addPeerLocator(sslId, RsUrl(ipStr)); - - if(dt.extPort && !dt.extAddr.empty()) - { - RsUrl locator; - locator.setScheme("ipv4").setHost(dt.extAddr) - .setPort(dt.extPort); - addPeerLocator(sslId, locator); - } - - if(dt.localPort && !dt.localAddr.empty()) - { - RsUrl locator; - locator.setScheme("ipv4").setHost(dt.localAddr) - .setPort(dt.localPort); - addPeerLocator(sslId, locator); - } - } - - return true; -} - -bool p3PeerMgrIMPL::removeFriend(const RsPgpId &id) -{ -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::removeFriend() for id : " << id << std::endl; - std::cerr << "p3PeerMgrIMPL::removeFriend() mFriendList.size() : " << mFriendList.size() << std::endl; -#endif - - rslog(RSL_WARNING, p3peermgrzone, "p3PeerMgr::removeFriend() id: " + id.toStdString()); - - std::list sslid_toRemove; // This is a list of SSLIds. - rsPeers->getAssociatedSSLIds(id,sslid_toRemove) ; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* move to othersList */ - //bool success = false; - std::map::iterator it; - //remove ssl and gpg_ids - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (find(sslid_toRemove.begin(),sslid_toRemove.end(),it->second.id) != sslid_toRemove.end()) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::removeFriend() friend found in the list." << id << std::endl; -#endif - peerState peer = it->second; - - sslid_toRemove.push_back(it->second.id); - - //mOthersList[it->second.id] = peer; - mStatusChanged = true; - - //success = true; - } - } - - for(std::list::iterator rit = sslid_toRemove.begin(); rit != sslid_toRemove.end(); ++rit) - if (mFriendList.end() != (it = mFriendList.find(*rit))) - mFriendList.erase(it); - - std::map::iterator it2 = mFriendsPermissionFlags.find(id) ; - - if(it2 != mFriendsPermissionFlags.end()) - mFriendsPermissionFlags.erase(it2); - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::removeFriend() new mFriendList.size() : " << mFriendList.size() << std::endl; -#endif - } - - std::list::iterator rit; - for(rit = sslid_toRemove.begin(); rit != sslid_toRemove.end(); ++rit) - { - mLinkMgr->removeFriend(*rit); - } - - /* remove id from all groups */ - - std::list ids ; - ids.push_back(id) ; - assignPeersToGroup(RsNodeGroupId(), ids, false); - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - -#ifdef PEER_DEBUG - printPeerLists(std::cerr); - mLinkMgr->printPeerLists(std::cerr); -#endif - - return !sslid_toRemove.empty(); -} -bool p3PeerMgrIMPL::removeFriend(const RsPeerId &id, bool removePgpId) -{ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::removeFriend() for id : " << id << std::endl; - std::cerr << "p3PeerMgrIMPL::removeFriend() mFriendList.size() : " << mFriendList.size() << std::endl; -#endif - - rslog(RSL_WARNING, p3peermgrzone, "p3PeerMgr::removeFriend() id: " + id.toStdString()); - - std::list sslid_toRemove; // This is a list of SSLIds. - std::list pgpid_toRemove; // This is a list of SSLIds. - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* move to othersList */ - //bool success = false; - std::map::iterator it; - //remove ssl and gpg_ids - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (it->second.id == id) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::removeFriend() friend found in the list." << id << std::endl; -#endif - peerState peer = it->second; - - sslid_toRemove.push_back(it->second.id); - if(removePgpId) - pgpid_toRemove.push_back(it->second.gpg_id); - - //mOthersList[id] = peer; - mStatusChanged = true; - - //success = true; - } - } - - for(std::list::iterator rit = sslid_toRemove.begin(); rit != sslid_toRemove.end(); ++rit) - if (mFriendList.end() != (it = mFriendList.find(*rit))) - mFriendList.erase(it); - - std::map::iterator it2 ; - - for(std::list::iterator rit = pgpid_toRemove.begin(); rit != pgpid_toRemove.end(); ++rit) - if (mFriendsPermissionFlags.end() != (it2 = mFriendsPermissionFlags.find(*rit))) - mFriendsPermissionFlags.erase(it2); - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::removeFriend() new mFriendList.size() : " << mFriendList.size() << std::endl; -#endif - } - - std::list::iterator rit; - for(rit = sslid_toRemove.begin(); rit != sslid_toRemove.end(); ++rit) - { - mLinkMgr->removeFriend(*rit); - } - - /* remove id from all groups */ - - assignPeersToGroup(RsNodeGroupId(), pgpid_toRemove, false); - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - -#ifdef PEER_DEBUG - printPeerLists(std::cerr); - mLinkMgr->printPeerLists(std::cerr); -#endif - - return !sslid_toRemove.empty(); -} - - -void p3PeerMgrIMPL::printPeerLists(std::ostream &out) -{ - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - out << "p3PeerMgrIMPL::printPeerLists() Friend List"; - out << std::endl; - - - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - out << "\t SSL ID: " << it->second.id; - out << "\t GPG ID: " << it->second.gpg_id; - out << std::endl; - } - -// out << "p3PeerMgrIMPL::printPeerLists() Others List"; -// out << std::endl; -// for(it = mOthersList.begin(); it != mOthersList.end(); ++it) -// { -// out << "\t SSL ID: " << it->second.id; -// out << "\t GPG ID: " << it->second.gpg_id; -// out << std::endl; -// } - } - - return; -} - - - -/*******************************************************************/ -/*******************************************************************/ - - -/********************************************************************** - ********************************************************************** - ******************** External Setup ********************************** - ********************************************************************** - **********************************************************************/ - - -/* This function should only be called from NetMgr, - * as it doesn't call back to there. - */ - -bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& pLocalAddr, - const sockaddr_storage& pExtAddr ) -{ - sockaddr_storage localAddr; - sockaddr_storage_copy(pLocalAddr, localAddr); - sockaddr_storage_ipv6_to_ipv4(localAddr); - - sockaddr_storage extAddr; - sockaddr_storage_copy(pExtAddr, extAddr); - sockaddr_storage_ipv6_to_ipv4(extAddr); - -//#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress(" - << sockaddr_storage_tostring(localAddr) << ", " - << sockaddr_storage_tostring(extAddr) << ")" << std::endl; -//#endif - - if( rsBanList && - !rsBanList->isAddressAccepted(localAddr, - RSBANLIST_CHECKING_FLAGS_BLACKLIST) ) - { - std::cerr << "(SS) Trying to set own IP to a banned IP " - << sockaddr_storage_iptostring(localAddr) << ". This probably" - << "means that a friend in under traffic re-routing attack." - << std::endl; - return false; - } - - { - RS_STACK_MUTEX(mPeerMtx); - - //update ip address list - pqiIpAddress ipAddressTimed; - sockaddr_storage_copy(localAddr, ipAddressTimed.mAddr); - ipAddressTimed.mSeenTime = time(NULL); - ipAddressTimed.mSrc = 0; - mOwnState.ipAddrs.updateLocalAddrs(ipAddressTimed); - - if(!mOwnState.hiddenNode) - { - /* Workaround to spread multiple local ip addresses when presents. - * This is needed because RS wrongly assumes that there is just one - * active local ip address at time. */ - std::vector addrs; - if(getLocalAddresses(addrs)) - { - /* To work around MAX_ADDRESS_LIST_SIZE addresses limitation, - * let's shuffle the list of local addresses in the hope that - * with enough time every local address is advertised to - * trusted nodes so they may try to connect to all of them - * including the most convenient if a local connection exists. - */ - std::random_shuffle(addrs.begin(), addrs.end()); - - for (auto it = addrs.begin(); it!=addrs.end(); ++it) - { - sockaddr_storage& addr(*it); - if( sockaddr_storage_isValidNet(addr) && - !sockaddr_storage_isLoopbackNet(addr) && - /* Avoid IPv6 link local addresses as we don't have - * implemented the logic needed to handle sin6_scope_id. - * To properly handle sin6_scope_id it would probably - * require deep reenginering of the RetroShare - * networking stack */ - !sockaddr_storage_ipv6_isLinkLocalNet(addr) ) - { - sockaddr_storage_ipv6_to_ipv4(addr); - pqiIpAddress pqiIp; - sockaddr_storage_clear(pqiIp.mAddr); - pqiIp.mAddr.ss_family = addr.ss_family; - sockaddr_storage_copyip(pqiIp.mAddr, addr); - sockaddr_storage_setport( - pqiIp.mAddr, - sockaddr_storage_port(localAddr) ); - pqiIp.mSeenTime = time(nullptr); - pqiIp.mSrc = 0; - mOwnState.ipAddrs.updateLocalAddrs(pqiIp); - } - } - } - } - - sockaddr_storage_copy(localAddr, mOwnState.localaddr); - } - - - { - RS_STACK_MUTEX(mPeerMtx); - - //update ip address list - pqiIpAddress ipAddressTimed; - sockaddr_storage_copy(extAddr, ipAddressTimed.mAddr); - ipAddressTimed.mSeenTime = time(NULL); - ipAddressTimed.mSrc = 0; - mOwnState.ipAddrs.updateExtAddrs(ipAddressTimed); - - /* Attempted Fix to MANUAL FORWARD Mode.... - * don't update the server address - if we are in this mode - * - * It is okay - if they get it wrong, as we put the address in the address list anyway. - * This should keep people happy, and allow for misconfiguration! - */ - - if (mOwnState.netMode & RS_NET_MODE_TRY_EXT) - { - /**** THIS CASE SHOULD NOT BE TRIGGERED ****/ - std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress() Disabling Update of Server Port "; - std::cerr << " as MANUAL FORWARD Mode (ERROR - SHOULD NOT BE TRIGGERED: TRY_EXT_MODE)"; - std::cerr << std::endl; - std::cerr << "Address is Now: "; - std::cerr << sockaddr_storage_tostring(mOwnState.serveraddr); - std::cerr << std::endl; - } - else if (mOwnState.netMode & RS_NET_MODE_EXT) - { - sockaddr_storage_copyip(mOwnState.serveraddr, extAddr); - - std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress() Disabling Update of Server Port "; - std::cerr << " as MANUAL FORWARD Mode"; - std::cerr << std::endl; - std::cerr << "Address is Now: "; - std::cerr << sockaddr_storage_tostring(mOwnState.serveraddr); - std::cerr << std::endl; - } - else - { - sockaddr_storage_copy(extAddr, mOwnState.serveraddr); - } - } - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - mLinkMgr->setLocalAddress(localAddr); - - return true; -} - - -bool p3PeerMgrIMPL::addPeerLocator(const RsPeerId &sslId, const RsUrl& locator) -{ - std::string host(locator.host()); - pqiIpAddress ip; - if(!locator.hasPort() || host.empty() || - !sockaddr_storage_inet_pton(ip.mAddr, host) || - !sockaddr_storage_setport(ip.mAddr, locator.port())) return false; - ip.mSeenTime = time(NULL); - - bool changed = false; - - if (sslId == AuthSSL::getAuthSSL()->OwnId()) - { - RS_STACK_MUTEX(mPeerMtx); - changed = mOwnState.ipAddrs.updateLocalAddrs(ip); - } - else - { - RS_STACK_MUTEX(mPeerMtx); - auto it = mFriendList.find(sslId); - if (it == mFriendList.end()) - { -#ifdef PEER_DEBUG - std::cerr << __PRETTY_FUNCTION__ << "cannot add address " << "info, peer id: " << sslId << " not found in list" << std::endl; -#endif - return false; - } - - changed = it->second.ipAddrs.updateLocalAddrs(ip); - } - - if (changed) - { -#ifdef PEER_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " Added locator: " - << locator.toString() << std::endl; -#endif - IndicateConfigChanged(); - } - return changed; -} - -bool p3PeerMgrIMPL::setLocalAddress( const RsPeerId &id, - const sockaddr_storage &addr ) -{ - bool changed = false; - - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - { - RS_STACK_MUTEX(mPeerMtx); - if (!sockaddr_storage_same(mOwnState.localaddr, addr)) - { - mOwnState.localaddr = addr; - changed = true; - } - } - - if (changed) - { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - mNetMgr->setLocalAddress(addr); - mLinkMgr->setLocalAddress(addr); - } - return changed; - } - - RS_STACK_MUTEX(mPeerMtx); - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { - std::cerr << "(EE) p3PeerMgrIMPL::setLocalAddress() cannot add addres " << "info : peer id not found in friend list id: " << id << std::endl; - return false; - } - - /* "it" points to peer */ - if (!sockaddr_storage_same(it->second.localaddr, addr)) - { - it->second.localaddr = addr; - changed = true; - } - -#if 0 - //update ip address list - IpAddressTimed ipAddressTimed; - ipAddressTimed.ipAddr = addr; - ipAddressTimed.seenTime = time(NULL); - it->second.updateIpAddressList(ipAddressTimed); -#endif - - if (changed) IndicateConfigChanged(); - return changed; -} - -bool p3PeerMgrIMPL::setExtAddress( const RsPeerId &id, - const sockaddr_storage &addr ) -{ - bool changed = false; - uint32_t check_res = 0; - - if(rsBanList && !rsBanList->isAddressAccepted( - addr, RSBANLIST_CHECKING_FLAGS_BLACKLIST, check_res )) - { - RsErr() << __PRETTY_FUNCTION__ << " trying to set external contact " - << "address for peer: " << id << " to a banned address " << addr - << std::endl; - return false; - } - - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - { - RS_STACK_MUTEX(mPeerMtx); - if (!sockaddr_storage_same(mOwnState.serveraddr, addr)) - { - mOwnState.serveraddr = addr; - changed = true; - } - } - - mNetMgr->setExtAddress(addr); - - return changed; - } - - RS_STACK_MUTEX(mPeerMtx); - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { - std::cerr << "(EE) p3PeerMgrIMPL::setExtAddress() cannot add addres " << "info : peer id not found in friend list id: " << id << std::endl; - return false; - } - - /* "it" points to peer */ - if (!sockaddr_storage_same(it->second.serveraddr, addr)) - { - it->second.serveraddr = addr; - changed = true; - } - -#if 0 - //update ip address list - IpAddressTimed ipAddressTimed; - ipAddressTimed.ipAddr = addr; - ipAddressTimed.seenTime = time(NULL); - it->second.updateIpAddressList(ipAddressTimed); -#endif - - if (changed) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } - - return changed; -} - - -bool p3PeerMgrIMPL::setDynDNS(const RsPeerId &id, const std::string &dyndns) -{ - bool changed = false; - - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - if (mOwnState.dyndns.compare(dyndns) != 0) { - mOwnState.dyndns = dyndns; - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - changed = true; - } - return changed; - } - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setDynDNS() cannot add dyn dns info : peer id not found in friend list id: " << id << std::endl; -#endif - return false; - } - - /* "it" points to peer */ - if (it->second.dyndns.compare(dyndns) != 0) { - it->second.dyndns = dyndns; - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - changed = true; - } - - return changed; -} - -namespace pqi { - -struct ZeroedInt -{ - ZeroedInt() { n=0 ;} - int n ; -}; - -} - -bool p3PeerMgrIMPL::addCandidateForOwnExternalAddress(const RsPeerId &from, const sockaddr_storage &addr) -{ - // The algorithm is the following: - // - collect for each friend the last external connection address that is reported - // - everytime the list is changed, parse it entirely and - // * emit a warnign when the address is unknown - // * if multiple peers report the same address => notify the LinkMgr that the external address had changed. - - sockaddr_storage addr_filtered ; - sockaddr_storage_clear(addr_filtered) ; - sockaddr_storage_copyip(addr_filtered,addr) ; - -#ifndef PEER_DEBUG - std::cerr << "Own external address is " << sockaddr_storage_iptostring(addr_filtered) << ", as reported by friend " << from << std::endl; -#endif - - if(!sockaddr_storage_isExternalNet(addr_filtered)) - { -#ifdef PEER_DEBUG - std::cerr << " address is not an external address. Returning false" << std::endl ; -#endif - return false ; - } - - // Update a list of own IPs: - // - remove old values for that same peer - // - remove values for non connected peers - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - mReportedOwnAddresses[from] = addr_filtered ; - - for(std::map::iterator it(mReportedOwnAddresses.begin());it!=mReportedOwnAddresses.end();) - if(!mLinkMgr->isOnline(it->first)) - { - std::map::iterator tmp(it) ; - ++tmp ; - mReportedOwnAddresses.erase(it) ; - it=tmp ; - } - else - ++it ; - - sockaddr_storage current_best_ext_address_guess ; - uint32_t count ; - - locked_computeCurrentBestOwnExtAddressCandidate(current_best_ext_address_guess,count) ; - - std::cerr << "p3PeerMgr:: Current external address is calculated to be: " << sockaddr_storage_iptostring(current_best_ext_address_guess) << " (simultaneously reported by " << count << " peers)." << std::endl; - } - - // now current - - sockaddr_storage own_addr ; - - if(!mNetMgr->getExtAddress(own_addr)) - { -#ifdef PEER_DEBUG - std::cerr << " cannot get current external address. Returning false" << std::endl; -#endif - return false ; - } -#ifdef PEER_DEBUG - std::cerr << " current external address is known to be " << sockaddr_storage_iptostring(own_addr) << std::endl; -#endif - - // Notify for every friend that has reported a wrong external address, except if that address is in the IP whitelist. - - if((rsBanList && !rsBanList->isAddressAccepted(addr_filtered, RSBANLIST_CHECKING_FLAGS_WHITELIST)) - && !sockaddr_storage_sameip(own_addr, addr_filtered) ) - { - RsInfo() << __PRETTY_FUNCTION__ << " Peer " << from - << " reports a connection address (" << addr_filtered - <<") that is not your current external address (" - << own_addr << "). This is weird." << std::endl; - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mSslId = from; - ev->mOwnLocator = RsUrl(own_addr); - ev->mReportedLocator = RsUrl(addr); - ev->mConnectionInfoCode = RsConnectionEventCode::PEER_REPORTS_WRONG_IP; - rsEvents->postEvent(ev); - } - } - - // we could also sweep over all connected friends and see if some report a different address. - - return true ; -} - -bool p3PeerMgrIMPL::locked_computeCurrentBestOwnExtAddressCandidate(sockaddr_storage& addr, uint32_t& count) -{ - sockaddr_storage_clear(addr); - std::map addr_counts ; - - for(std::map::iterator it(mReportedOwnAddresses.begin());it!=mReportedOwnAddresses.end();++it) - ++addr_counts[it->second].n ; - -#ifdef PEER_DEBUG - std::cerr << "Current ext addr statistics:" << std::endl; -#endif - - count = 0 ; - - for(std::map::const_iterator it(addr_counts.begin());it!=addr_counts.end();++it) - { - if(uint32_t(it->second.n) > count) - { - addr = it->first ; - count = it->second.n ; - } - -#ifdef PEER_DEBUG - std::cerr << sockaddr_storage_iptostring(it->first) << " : " << it->second.n << std::endl; -#endif - } - - return count > 0 ; -} - -bool p3PeerMgrIMPL::getExtAddressReportedByFriends(sockaddr_storage &addr, uint8_t& /*isstable*/) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - uint32_t count =0; - - locked_computeCurrentBestOwnExtAddressCandidate(addr,count) ; - -#ifdef PEER_DEBUG - std::cerr << "Estimation count = " << count << ". Trusted? = " << (count>=2) << std::endl; -#endif - - return count >= 2 ;// 2 is not conservative enough. 3 should be probably better. -} - -static bool cleanIpList(std::list& lst,const RsPeerId& pid,p3LinkMgr *link_mgr) -{ - bool changed = false ; -#ifdef PEER_DEBUG - rstime_t now = time(NULL) ; -#endif - - for(std::list::iterator it2(lst.begin());it2 != lst.end();) - { -#ifdef PEER_DEBUG - std::cerr << "Checking IP address " << sockaddr_storage_iptostring( (*it2).mAddr) << " for peer " << pid << ", age = " << now - (*it2).mSeenTime << std::endl; -#else - /* remove unused parameter warnings */ - (void) pid; -#endif - if(!link_mgr->checkPotentialAddr((*it2).mAddr)) - { -#ifdef PEER_DEBUG - std::cerr << " (SS) Removing Banned/old IP address " << sockaddr_storage_iptostring( (*it2).mAddr) << " from peer " << pid << ", age = " << now - (*it2).mSeenTime << std::endl; -#endif - - std::list::iterator ittmp = it2 ; - ++ittmp ; - lst.erase(it2) ; - it2 = ittmp ; - - changed = true ; - } - else - ++it2 ; - } - - return changed ; -} - -bool p3PeerMgrIMPL::updateAddressList(const RsPeerId& id, const pqiIpAddrSet &addrs) -{ -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setAddressList() called for id : " << id << std::endl; -#endif - // first clean the list from potentially banned IPs. - - pqiIpAddrSet clean_set = addrs ; - - cleanIpList(clean_set.mExt.mAddrs,id,mLinkMgr) ; - cleanIpList(clean_set.mLocal.mAddrs,id,mLinkMgr) ; - - bool am_I_a_hidden_node = isHiddenNode(getOwnId()) ; - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* check if it is our own ip */ - if (id == getOwnId()) - { - mOwnState.ipAddrs.updateAddrs(clean_set); - return true; - } - - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setLocalAddress() cannot add addres info : peer id not found in friend list. id: " << id << std::endl; -#endif - return false; - } - - /* "it" points to peer */ - - if(!am_I_a_hidden_node) - it->second.ipAddrs.updateAddrs(clean_set); - else - it->second.ipAddrs.clear(); - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setLocalAddress() Updated Address for: " << id; - std::cerr << std::endl; - std::string addrstr; - it->second.ipAddrs.printAddrs(addrstr); - std::cerr << addrstr; - std::cerr << std::endl; -#endif - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - return true; -} - - -bool p3PeerMgrIMPL::updateCurrentAddress(const RsPeerId& id, const pqiIpAddress &addr) -{ -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::updateCurrentAddress() called for id : " << id << std::endl; -#endif - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* cannot be own id */ - - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { - std::cerr << "p3PeerMgrIMPL::updateCurrentAddress() ERROR peer id not found: " << id << std::endl; - return false; - } - - if (sockaddr_storage_isPrivateNet(addr.mAddr)) - { - it->second.ipAddrs.updateLocalAddrs(addr); - it->second.localaddr = addr.mAddr; - } - else - { - it->second.ipAddrs.updateExtAddrs(addr); - it->second.serveraddr = addr.mAddr; - } - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::updatedCurrentAddress() Updated Address for: " << id; - std::cerr << std::endl; - std::string addrstr; - it->second.ipAddrs.printAddrs(addrstr); - std::cerr << addrstr; - std::cerr << std::endl; -#endif - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - return true; -} - - -bool p3PeerMgrIMPL::updateLastContact(const RsPeerId& id) -{ -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::updateLastContact() called for id : " << id << std::endl; -#endif - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* cannot be own id */ - - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { - std::cerr << "p3PeerMgrIMPL::updateLastContact() ERROR peer id not found: " << id << std::endl; - return false; - } - - it->second.lastcontact = time(NULL); - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - return true; -} - -bool p3PeerMgrIMPL::setNetworkMode(const RsPeerId &id, uint32_t netMode) -{ - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - return setOwnNetworkMode(netMode); - } - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { - return false; - } - - bool changed = false; - - /* "it" points to peer */ - if (it->second.netMode != netMode) - { - it->second.netMode = netMode; - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - changed = true; - } - - return changed; -} - -bool p3PeerMgrIMPL::setLocation(const RsPeerId &id, const std::string &location) -{ - bool changed = false; - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setLocation() called for id : " << id << "; with location " << location << std::endl; -#endif - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - if (mOwnState.location.compare(location) != 0) { - mOwnState.location = location; - changed = true; - } - return changed; - } - - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() != (it = mFriendList.find(id))) { - if (it->second.location.compare(location) != 0) { - it->second.location = location; - changed = true; - } - } - return changed; -} - -bool p3PeerMgrIMPL::setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht) -{ - { - std::string out; - rs_sprintf(out, "p3PeerMgr::setVisState(%s, %u, %u)", id.toStdString().c_str(), vs_disc, vs_dht); - rslog(RSL_WARNING, p3peermgrzone, out); - } - - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - return setOwnVisState(vs_disc, vs_dht); - } - - bool isFriend = false; - bool changed = false; - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { - return false; - } - else - { - isFriend = true; - } - - /* "it" points to peer */ - if ((it->second.vs_disc != vs_disc) || (it->second.vs_dht = vs_dht)) - { - it->second.vs_disc = vs_disc; - it->second.vs_dht = vs_dht; - changed = true; - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setVisState(" << id << ", DISC: " << vs_disc << " DHT: " << vs_dht << ") "; - std::cerr << " NAME: " << it->second.name; - - switch(it->second.vs_disc) - { - default: - case RS_VS_DISC_OFF: - std::cerr << " NO-DISC "; - break; - case RS_VS_DISC_MINIMAL: - std::cerr << " MIN-DISC "; - break; - case RS_VS_DISC_FULL: - std::cerr << " FULL-DISC "; - break; - } - switch(it->second.vs_dht) - { - default: - case RS_VS_DHT_OFF: - std::cerr << " NO-DHT "; - break; - case RS_VS_DHT_PASSIVE: - std::cerr << " PASSIVE-DHT "; - break; - case RS_VS_DHT_FULL: - std::cerr << " FULL-DHT "; - break; - } - std::cerr << std::endl; -#endif - } - } - if(isFriend && changed) - { - mLinkMgr->setFriendVisibility(id, vs_dht != RS_VS_DHT_OFF); - } - - if (changed) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } - - return changed; -} - - - - -/*******************************************************************/ - - -/********************************************************************** - ********************************************************************** - ******************** p3Config functions ****************************** - ********************************************************************** - **********************************************************************/ - - /* Key Functions to be overloaded for Full Configuration */ - -RsSerialiser *p3PeerMgrIMPL::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsPeerConfigSerialiser()); - rss->addSerialType(new RsGeneralConfigSerialiser()) ; - - return rss; -} - - -bool p3PeerMgrIMPL::saveList(bool &cleanup, std::list& saveData) -{ - /* create a list of current peers */ - cleanup = true; - bool useExtAddrFinder = mNetMgr->getIPServersEnabled(); - - /* gather these information before mPeerMtx is locked! */ - struct sockaddr_storage proxy_addr_tor, proxy_addr_i2p; - getProxyServerAddress(RS_HIDDEN_TYPE_TOR, proxy_addr_tor); - getProxyServerAddress(RS_HIDDEN_TYPE_I2P, proxy_addr_i2p); - - mPeerMtx.lock(); /****** MUTEX LOCKED *******/ - - RsPeerNetItem *item = new RsPeerNetItem(); - item->clear(); - - item->nodePeerId = getOwnId(); - item->pgpId = mOwnState.gpg_id; - item->location = mOwnState.location; - -#if 0 - if (mOwnState.netMode & RS_NET_MODE_TRY_EXT) - { - item->netMode = RS_NET_MODE_EXT; - } - else if (mOwnState.netMode & RS_NET_MODE_TRY_UPNP) - { - item->netMode = RS_NET_MODE_UPNP; - } - else - { - item->netMode = RS_NET_MODE_UDP; - } -#endif - item->netMode = mOwnState.netMode; - - item->vs_disc = mOwnState.vs_disc; - item->vs_dht = mOwnState.vs_dht; - - item->lastContact = mOwnState.lastcontact; - - item->localAddrV4.addr = mOwnState.localaddr; - item->extAddrV4.addr = mOwnState.serveraddr; - sockaddr_storage_clear(item->localAddrV6.addr); - sockaddr_storage_clear(item->extAddrV6.addr); - - item->dyndns = mOwnState.dyndns; - mOwnState.ipAddrs.mLocal.loadTlv(item->localAddrList); - mOwnState.ipAddrs.mExt.loadTlv(item->extAddrList); - item->domain_addr = mOwnState.hiddenDomain; - item->domain_port = mOwnState.hiddenPort; - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::saveList() Own Config Item:" << std::endl; - item->print(std::cerr, 10); - std::cerr << std::endl; -#endif - - saveData.push_back(item); - - /* iterate through all friends and save */ - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - item = new RsPeerNetItem(); - item->clear(); - - item->nodePeerId = it->first; - item->pgpId = (it->second).gpg_id; - item->location = (it->second).location; - item->netMode = (it->second).netMode; - item->vs_disc = (it->second).vs_disc; - item->vs_dht = (it->second).vs_dht; - - item->lastContact = (it->second).lastcontact; - - item->localAddrV4.addr = (it->second).localaddr; - item->extAddrV4.addr = (it->second).serveraddr; - sockaddr_storage_clear(item->localAddrV6.addr); - sockaddr_storage_clear(item->extAddrV6.addr); - - - item->dyndns = (it->second).dyndns; - (it->second).ipAddrs.mLocal.loadTlv(item->localAddrList); - (it->second).ipAddrs.mExt.loadTlv(item->extAddrList); - - item->domain_addr = (it->second).hiddenDomain; - item->domain_port = (it->second).hiddenPort; - - saveData.push_back(item); -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::saveList() Peer Config Item:" << std::endl; - item->print(std::cerr, 10); - std::cerr << std::endl; -#endif - } - - RsPeerBandwidthLimitsItem *pblitem = new RsPeerBandwidthLimitsItem ; - pblitem->peers = mPeerBandwidthLimits ; - saveData.push_back(pblitem) ; - - RsPeerServicePermissionItem *sitem = new RsPeerServicePermissionItem ; - - for(std::map::const_iterator it(mFriendsPermissionFlags.begin());it!=mFriendsPermissionFlags.end();++it) - { - sitem->pgp_ids.push_back(it->first) ; - sitem->service_flags.push_back(it->second) ; - } - - saveData.push_back(sitem) ; - - // Now save config for network digging strategies - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - - RsTlvKeyValue kv; - kv.key = kConfigKeyExtIpFinder; - kv.value = (useExtAddrFinder)?"TRUE":"FALSE" ; - vitem->tlvkvs.pairs.push_back(kv) ; - - - // Store Proxy Server. - // Tor -#ifdef PEER_DEBUG - std::cerr << "Saving proxyServerAddress for Tor: " << sockaddr_storage_tostring(proxy_addr_tor); - std::cerr << std::endl; -#endif - - kv.key = kConfigKeyProxyServerIpAddrTor; - kv.value = sockaddr_storage_iptostring(proxy_addr_tor); - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = kConfigKeyProxyServerPortTor; - kv.value = sockaddr_storage_porttostring(proxy_addr_tor); - vitem->tlvkvs.pairs.push_back(kv) ; - - // I2P -#ifdef PEER_DEBUG - std::cerr << "Saving proxyServerAddress for I2P: " << sockaddr_storage_tostring(proxy_addr_i2p); - std::cerr << std::endl; -#endif - - kv.key = kConfigKeyProxyServerIpAddrI2P; - kv.value = sockaddr_storage_iptostring(proxy_addr_i2p); - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = kConfigKeyProxyServerPortI2P; - kv.value = sockaddr_storage_porttostring(proxy_addr_i2p); - vitem->tlvkvs.pairs.push_back(kv) ; - - saveData.push_back(vitem); - - /* save groups */ - - for ( std::map::iterator groupIt = groupList.begin(); groupIt != groupList.end(); ++groupIt) - { - RsNodeGroupItem *itm = new RsNodeGroupItem(groupIt->second); - saveData.push_back(itm) ; - } - - return true; -} - -bool p3PeerMgrIMPL::getMaxRates(const RsPeerId& pid,uint32_t& maxUp,uint32_t& maxDn) -{ - RsPgpId pgp_id ; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::const_iterator it = mFriendList.find(pid) ; - - if(it == mFriendList.end()) - { - maxUp = 0; - maxDn = 0; - return false ; - } - - pgp_id = it->second.gpg_id ; - } - - return getMaxRates(pgp_id,maxUp,maxDn) ; -} - -bool p3PeerMgrIMPL::getMaxRates(const RsPgpId& pid,uint32_t& maxUp,uint32_t& maxDn) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::const_iterator it2 = mPeerBandwidthLimits.find(pid) ; - - if(it2 != mPeerBandwidthLimits.end()) - { - maxUp = it2->second.max_up_rate_kbs ; - maxDn = it2->second.max_dl_rate_kbs ; - return true ; - } - else - { - maxUp = 0; - maxDn = 0; - return false ; - } -} -bool p3PeerMgrIMPL::setMaxRates(const RsPgpId& pid,uint32_t maxUp,uint32_t maxDn) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - PeerBandwidthLimits& p(mPeerBandwidthLimits[pid]) ; - - if(maxUp == p.max_up_rate_kbs && maxDn == p.max_dl_rate_kbs) - return true ; - - std::cerr << "Updating max rates for peer " << pid << " to " << maxUp << " kB/s (up), " << maxDn << " kB/s (dn)" << std::endl; - - p.max_up_rate_kbs = maxUp ; - p.max_dl_rate_kbs = maxDn ; - - IndicateConfigChanged(); - - return true ; -} - -void p3PeerMgrIMPL::saveDone() -{ - /* clean up the save List */ - std::list::iterator it; - for(it = saveCleanupList.begin(); it != saveCleanupList.end(); ++it) - { - delete (*it); - } - - saveCleanupList.clear(); - - /* unlock mutex */ - mPeerMtx.unlock(); /****** MUTEX UNLOCKED *******/ -} - -bool p3PeerMgrIMPL::loadList(std::list& load) -{ - // DEFAULTS. - bool useExtAddrFinder = true; - std::string proxyIpAddressTor = kConfigDefaultProxyServerIpAddr; - uint16_t proxyPortTor = kConfigDefaultProxyServerPortTor; - std::string proxyIpAddressI2P = kConfigDefaultProxyServerIpAddr; - uint16_t proxyPortI2P = kConfigDefaultProxyServerPortI2P; - - if (load.empty()) { - std::cerr << "p3PeerMgrIMPL::loadList() list is empty, it may be a configuration problem." << std::endl; - return false; - } - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::loadList() Item Count: " << load.size() << std::endl; -#endif - - RsPeerId ownId = getOwnId(); - bool am_I_a_hidden_node = isHiddenNode(ownId) ; - - /* load the list of peers */ - std::list::iterator it; - for(it = load.begin(); it != load.end(); ++it) - { - RsPeerNetItem *pitem = dynamic_cast(*it); - if (pitem) - { - RsPeerId peer_id = pitem->nodePeerId ; - RsPgpId peer_pgp_id = pitem->pgpId ; - - if (peer_id == ownId) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::loadList() Own Config Item:" << std::endl; - pitem->print(std::cerr, 10); - std::cerr << std::endl; -#endif - /* add ownConfig */ - setOwnNetworkMode(pitem->netMode); - setOwnVisState(pitem->vs_disc, pitem->vs_dht); - - mOwnState.gpg_id = AuthGPG::getAuthGPG()->getGPGOwnId(); - mOwnState.location = AuthSSL::getAuthSSL()->getOwnLocation(); - } - else - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::loadList() Peer Config Item:" << std::endl; - pitem->print(std::cerr, 10); - std::cerr << std::endl; -#endif - /* ************* */ - // permission flags is used as a mask for the existing perms, so we set it to 0xffff - - RsPeerDetails det ; - if(!rsPeers->getGPGDetails(peer_pgp_id,det)) - { - // would be better to add flags into RsPeerNetItem so that we already have this information. However, it's possible that the PGP key - // has been added in the meantime, so the peer would be loaded with the right pGP key attached. - - RsInfo() << __PRETTY_FUNCTION__ << " loading SSL-only " << "friend: " << peer_id << " " << pitem->location << std::endl; - addSslOnlyFriend(peer_id,peer_pgp_id); - } - else if(!addFriend( peer_id, peer_pgp_id, pitem->netMode, pitem->vs_disc, pitem->vs_dht, pitem->lastContact, RS_NODE_PERM_ALL )) - { - RsInfo() << __PRETTY_FUNCTION__ << " cannot add friend friend: " << peer_id << " " << pitem->location << ". Somthing's wrong." << std::endl; - } - setLocation(pitem->nodePeerId, pitem->location); - } - - if (pitem->netMode == RS_NET_MODE_HIDDEN) - { - /* set only the hidden stuff & localAddress */ - setLocalAddress(peer_id, pitem->localAddrV4.addr); - setHiddenDomainPort(peer_id, pitem->domain_addr, pitem->domain_port); - - } - else - { - pqiIpAddrSet addrs; - - if(!am_I_a_hidden_node) // clear IPs if w're a hidden node. Friend's clear node IPs where previously sent. - { - setLocalAddress(peer_id, pitem->localAddrV4.addr); - setExtAddress(peer_id, pitem->extAddrV4.addr); - setDynDNS (peer_id, pitem->dyndns); - - /* convert addresses */ - addrs.mLocal.extractFromTlv(pitem->localAddrList); - addrs.mExt.extractFromTlv(pitem->extAddrList); - } - - updateAddressList(peer_id, addrs); - } - - delete(*it); - - continue; - } - - RsConfigKeyValueSet *vitem = dynamic_cast(*it) ; - if (vitem) - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::loadList() General Variable Config Item:" << std::endl; - vitem->print(std::cerr, 10); - std::cerr << std::endl; -#endif - std::list::iterator kit; - for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if (kit->key == kConfigKeyExtIpFinder) - { - useExtAddrFinder = (kit->value == "TRUE"); -#ifdef PEER_DEBUG - std::cerr << "setting use_extr_addr_finder to " << useExtAddrFinder << std::endl ; -#endif - } - // Tor - else if (kit->key == kConfigKeyProxyServerIpAddrTor) - { - proxyIpAddressTor = kit->value; -#ifdef PEER_DEBUG - std::cerr << "Loaded proxyIpAddress for Tor: " << proxyIpAddressTor; - std::cerr << std::endl ; -#endif - - } - else if (kit->key == kConfigKeyProxyServerPortTor) - { - uint16_t p = atoi(kit->value.c_str()); - - if(p >= 1024) - proxyPortTor = p; -#ifdef PEER_DEBUG - std::cerr << "Loaded proxyPort for Tor: " << proxyPortTor; - std::cerr << std::endl ; -#endif - } - // I2p - else if (kit->key == kConfigKeyProxyServerIpAddrI2P) - { - proxyIpAddressI2P = kit->value; -#ifdef PEER_DEBUG - std::cerr << "Loaded proxyIpAddress for I2P: " << proxyIpAddressI2P; - std::cerr << std::endl ; -#endif - } - else if (kit->key == kConfigKeyProxyServerPortI2P) - { - uint16_t p = atoi(kit->value.c_str()); - - if(p >= 1024) - proxyPortI2P = p; -#ifdef PEER_DEBUG - std::cerr << "Loaded proxyPort for I2P: " << proxyPortI2P; - std::cerr << std::endl ; -#endif - } - } - - delete(*it); - - continue; - } - - RsNodeGroupItem *gitem2 = dynamic_cast(*it) ; - - if (gitem2) - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::loadList() Peer group item:" << std::endl; - gitem->print(std::cerr, 10); - std::cerr << std::endl; -#endif - RsGroupInfo info ; - info.peerIds = gitem2->pgpList.ids ; - info.id = gitem2->id ; - info.name = gitem2->name ; - info.flag = gitem2->flag ; - - std::cerr << "(II) Loaded group in new format. ID = " << info.id << std::endl; - groupList[info.id] = info ; - - delete *it ; - continue; - } - RsPeerBandwidthLimitsItem *pblitem = dynamic_cast(*it) ; - - if(pblitem) - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "Loaded service permission item: " << std::endl; -#endif - mPeerBandwidthLimits = pblitem->peers ; - } - RsPeerServicePermissionItem *sitem = dynamic_cast(*it) ; - - if(sitem) - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "Loaded service permission item: " << std::endl; -#endif - - for(uint32_t i=0;ipgp_ids.size();++i) - if(AuthGPG::getAuthGPG()->isGPGAccepted(sitem->pgp_ids[i]) || sitem->pgp_ids[i] == AuthGPG::getAuthGPG()->getGPGOwnId()) - { - mFriendsPermissionFlags[sitem->pgp_ids[i]] = sitem->service_flags[i] ; -#ifdef PEER_DEBUG - std::cerr << " " << sitem->pgp_ids[i] << " - " << sitem->service_flags[i] << std::endl; -#endif - } -#ifdef PEER_DEBUG - else - std::cerr << " " << sitem->pgp_ids[i] << " - Not a friend!" << std::endl; -#endif - } - - delete (*it); - } - - { - /* set missing groupIds */ - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* Standard groups */ - const int standardGroupCount = 5; - const RsNodeGroupId standardGroupIds [standardGroupCount] = { RS_GROUP_ID_FRIENDS, RS_GROUP_ID_FAMILY, RS_GROUP_ID_COWORKERS, RS_GROUP_ID_OTHERS, RS_GROUP_ID_FAVORITES }; - const char *standardGroupNames[standardGroupCount] = { RS_GROUP_DEFAULT_NAME_FRIENDS, RS_GROUP_DEFAULT_NAME_FAMILY, RS_GROUP_DEFAULT_NAME_COWORKERS, RS_GROUP_DEFAULT_NAME_OTHERS, RS_GROUP_DEFAULT_NAME_FAVORITES }; - - for(uint32_t k=0;kisGPGAccepted(*profileIdIt) || *profileIdIt == AuthGPG::getAuthGPG()->getGPGOwnId()) - ++profileIdIt; - else - { - std::cerr << "(WW) filtering out profile " << profileIdIt->toStdString() << " from group " << group_pair.first.toStdString() << " because it is not a friend anymore" << std::endl; - - auto tmp = profileIdIt; - ++tmp; - group_pair.second.peerIds.erase(profileIdIt); - profileIdIt=tmp; - - IndicateConfigChanged(); - } - } - } - - // If we are hidden - don't want ExtAddrFinder - ever! - if (isHidden()) - useExtAddrFinder = false; - - mNetMgr->setIPServersEnabled(useExtAddrFinder); - - // Configure Proxy Server. - struct sockaddr_storage proxy_addr; - // Tor - sockaddr_storage_clear(proxy_addr); - sockaddr_storage_ipv4_aton(proxy_addr, proxyIpAddressTor.c_str()); - sockaddr_storage_ipv4_setport(proxy_addr, proxyPortTor); - - if (sockaddr_storage_isValidNet(proxy_addr)) - { - setProxyServerAddress(RS_HIDDEN_TYPE_TOR, proxy_addr); - } - - // I2P - sockaddr_storage_clear(proxy_addr); - sockaddr_storage_ipv4_aton(proxy_addr, proxyIpAddressI2P.c_str()); - sockaddr_storage_ipv4_setport(proxy_addr, proxyPortI2P); - - if (sockaddr_storage_isValidNet(proxy_addr)) - { - setProxyServerAddress(RS_HIDDEN_TYPE_I2P, proxy_addr); - } - - load.clear() ; - return true; -} - - -#if 0 - -void printConnectState(std::ostream &out, peerState &peer) -{ - - out << "Friend: " << peer.name << " Id: " << peer.id << " State: " << peer.state; - if (peer.state & RS_PEER_S_FRIEND) - out << " S:RS_PEER_S_FRIEND"; - if (peer.state & RS_PEER_S_ONLINE) - out << " S:RS_PEER_S_ONLINE"; - if (peer.state & RS_PEER_S_CONNECTED) - out << " S:RS_PEER_S_CONNECTED"; - out << " Actions: " << peer.actions; - if (peer.actions & RS_PEER_NEW) - out << " A:RS_PEER_NEW"; - if (peer.actions & RS_PEER_MOVED) - out << " A:RS_PEER_MOVED"; - if (peer.actions & RS_PEER_CONNECTED) - out << " A:RS_PEER_CONNECTED"; - if (peer.actions & RS_PEER_DISCONNECTED) - out << " A:RS_PEER_DISCONNECTED"; - if (peer.actions & RS_PEER_CONNECT_REQ) - out << " A:RS_PEER_CONNECT_REQ"; - - out << std::endl; - return; -} - -#endif - - -/********************************************************************** - ********************************************************************** - ************************** Groups ************************************ - ********************************************************************** - **********************************************************************/ - -bool p3PeerMgrIMPL::addGroup(RsGroupInfo &groupInfo) -{ - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - do { groupInfo.id = RsNodeGroupId::random(); } while(groupList.find(groupInfo.id) != groupList.end()) ; - - RsGroupInfo groupItem(groupInfo) ; - - // remove standard flag - - groupItem.flag &= ~RS_GROUP_FLAG_STANDARD; - groupList[groupInfo.id] = groupItem; - - std::cerr << "(II) Added new group with ID " << groupInfo.id << ", name=\"" << groupInfo.name << "\"" << std::endl; - } - - RsServer::notify()->notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_ADD); - - IndicateConfigChanged(); - - return true; -} - -bool p3PeerMgrIMPL::editGroup(const RsNodeGroupId& groupId, RsGroupInfo &groupInfo) -{ - if (groupId.isNull()) - return false; - - bool changed = false; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it = groupList.find(groupId) ; - - if(it == groupList.end()) - { - std::cerr << "(EE) cannot find local node group with ID " << groupId << std::endl; - return false ; - } - - if (it->second.flag & RS_GROUP_FLAG_STANDARD) - { - // can't edit standard groups - std::cerr << "(EE) cannot edit standard group with ID " << groupId << std::endl; - return false ; - } - else - { - changed = true; - it->second = groupInfo; - } - } - - if (changed) - { - RsServer::notify()->notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_MOD); - - IndicateConfigChanged(); - } - - return changed; -} - -bool p3PeerMgrIMPL::removeGroup(const RsNodeGroupId& groupId) -{ - bool changed = false; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it = groupList.find(groupId) ; - - if (it != groupList.end()) { - if (it->second.flag & RS_GROUP_FLAG_STANDARD) - { - // can't remove standard groups - std::cerr << "(EE) cannot remove standard group with ID " << groupId << std::endl; - return false ; - } -#warning csoler: we need to check that the local group is not used. Otherwise deleting it is going to cause problems! -// else if(!it->second.used_gxs_groups.empty()) -// { -// std::cerr << "(EE) cannot remove standard group with ID " << groupId << " because it is used in the following groups: " << std::endl; -// for(std::set::const_iterator it2(it->second.used_gxs_groups.begin());it2!=it->second.used_gxs_groups.end();++it2) -// std::cerr << " " << *it2 << std::endl; -// -// return false ; -// } - else - { - changed = true; - groupList.erase(it); - } - } - } - - if (changed) { - RsServer::notify()->notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_DEL); - - IndicateConfigChanged(); - } - - return changed; -} - -bool p3PeerMgrIMPL::getGroupInfoByName(const std::string& groupName, RsGroupInfo &groupInfo) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - for(std::map::iterator it = groupList.begin();it!=groupList.end();++it) - if(it->second.name == groupName) - { - groupInfo = it->second ; - return true ; - } - - std::cerr << "(EE) getGroupInfoByName: no known group for name " << groupName << std::endl; - return false ; -} -bool p3PeerMgrIMPL::getGroupInfo(const RsNodeGroupId& groupId, RsGroupInfo &groupInfo) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it = groupList.find(groupId) ; - - if(it == groupList.end()) - return false ; - - groupInfo = it->second; - - return true; -} - -bool p3PeerMgrIMPL::getGroupInfoList(std::list& groupInfoList) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - for(std::map ::const_iterator groupIt = groupList.begin(); groupIt != groupList.end(); ++groupIt) - groupInfoList.push_back(groupIt->second) ; - - return true; -} - -// groupId.isNull() && assign == false -> remove from all groups - -bool p3PeerMgrIMPL::assignPeersToGroup(const RsNodeGroupId &groupId, const std::list &peerIds, bool assign) -{ - if (groupId.isNull() && assign == true) - return false; - - if (peerIds.empty()) - return false; - - bool changed = false; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - for (std::map::iterator groupIt = groupList.begin(); groupIt != groupList.end(); ++groupIt) - if (groupId.isNull() || groupIt->first == groupId) - { - RsGroupInfo& groupItem = groupIt->second; - - for (std::list::const_iterator peerIt = peerIds.begin(); peerIt != peerIds.end(); ++peerIt) - { - //std::set::iterator peerIt1 = groupItem.peerIds.find(*peerIt); - - if (assign) - { - groupItem.peerIds.insert(*peerIt); - changed = true; - } - else - { - groupItem.peerIds.erase(*peerIt); - changed = true; - } - } - - if (!groupId.isNull()) - break; - } - } - - if (changed) { - RsServer::notify()->notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_MOD); - - IndicateConfigChanged(); - } - - return changed; -} - - -/********************************************************************** - ********************************************************************** - ******************** Service permission stuff ************************ - ********************************************************************** - **********************************************************************/ - -ServicePermissionFlags p3PeerMgrIMPL::servicePermissionFlags(const RsPeerId& ssl_id) -{ - RsPgpId gpg_id ; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::const_iterator it = mFriendList.find(ssl_id); - - if(it == mFriendList.end()) - return RS_NODE_PERM_DEFAULT ; - - gpg_id = it->second.gpg_id ; - } - - return servicePermissionFlags(gpg_id) ; -} - - -ServicePermissionFlags p3PeerMgrIMPL::servicePermissionFlags(const RsPgpId& pgp_id) -{ - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::const_iterator it = mFriendsPermissionFlags.find( pgp_id ) ; - - if(it == mFriendsPermissionFlags.end()) - return RS_NODE_PERM_DEFAULT ; - else - return it->second ; - } -} -void p3PeerMgrIMPL::setServicePermissionFlags(const RsPgpId& pgp_id, const ServicePermissionFlags& flags) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - // Check that we have a PGP id. This should not be necessary, but because - // we use std::string, anything can get passed down here. - // - - mFriendsPermissionFlags[pgp_id] = flags ; - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ -} - -/********************************************************************** - ********************************************************************** - ******************** Stuff moved from p3peers ************************ - ********************************************************************** - **********************************************************************/ - -bool p3PeerMgrIMPL::removeAllFriendLocations(const RsPgpId &gpgid) -{ - std::list sslIds; - if (!getAssociatedPeers(gpgid, sslIds)) - { - return false; - } - - std::list::iterator it; - for(it = sslIds.begin(); it != sslIds.end(); ++it) - { - removeFriend(*it, true); - } - - return true; -} - - -bool p3PeerMgrIMPL::getAssociatedPeers(const RsPgpId &gpg_id, std::list &ids) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgr::getAssociatedPeers() for id : " << gpg_id << std::endl; -#endif - - int count = 0; - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (it->second.gpg_id == gpg_id) - { - count++; - ids.push_back(it->first); - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgr::getAssociatedPeers() found ssl id : " << it->first << std::endl; -#endif - - } - } - - return (count > 0); -} - -// goes through the list of known friend IPs and remove the ones that are banned by p3LinkMgr. - - -bool p3PeerMgrIMPL::removeBannedIps() -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "Cleaning known IPs for all peers." << std::endl; -#endif - - bool changed = false ; - for( std::map::iterator it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if(cleanIpList(it->second.ipAddrs.mExt.mAddrs,it->first,mLinkMgr)) changed = true ; - if(cleanIpList(it->second.ipAddrs.mLocal.mAddrs,it->first,mLinkMgr)) changed = true ; - - if(rsBanList!=NULL && !rsBanList->isAddressAccepted(it->second.serveraddr,RSBANLIST_CHECKING_FLAGS_BLACKLIST)) - { - sockaddr_storage_clear(it->second.serveraddr) ; - std::cerr << "(SS) Peer " << it->first << " has a banned server address. Wiping it out." << std::endl; - } - } - - if(cleanIpList(mOwnState.ipAddrs.mExt.mAddrs,mOwnState.id,mLinkMgr) ) changed = true ; - if(cleanIpList(mOwnState.ipAddrs.mLocal.mAddrs,mOwnState.id,mLinkMgr) ) changed = true ; - - if(changed) - IndicateConfigChanged(); - - return true ; -} - -// /* This only removes SSL certs, that are old... Can end up with no Certs per GPG Id -// * We are removing the concept of a "DummyId" - There is no need for it. -// */ -// -// bool isDummyFriend(RsPeerId id) -// { -// bool ret = (id.substr(0,5) == "dummy"); -// return ret; -// } - -/** - * @brief p3PeerMgrIMPL::removeUnusedLocations Removes all location offline for RS_PEER_OFFLINE_DELETE seconds or more. Keeps the most recent location per PGP id. - * @return true on success - * - * This function removes all location that are offline for too long defined by RS_PEER_OFFLINE_DELETE. - * It also makes sure that at least one location (the most recent) is kept. - * - * The idea of the function is the following: - * - keep track if there is at least one location per PGP id that is not offline for too long - * -> hasRecentLocation - * - keep track of most recent location per PGP id that is offline for too long (and its time stamp) - * -> mostRecentLocation - * -> mostRecentTime - * - * When a location is found that is offline for too long the following points are checked from the top to the bottom: - * 1) remove it when the PGP id has a location that is not offline for too long - * 2) remove it when the PGP id has a more recent location - * 3) keep it when it is the most recent location - * This location will possibly be removed when a more recent (but still offline for too long) is found - */ -bool p3PeerMgrIMPL::removeUnusedLocations() -{ - std::list toRemove; - std::map mostRecentTime; - - const rstime_t now = time(NULL); - - std::list pgpList ; - - if (!rsPeers->getGPGAcceptedList(pgpList)) - return false ; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - // First put a sensible number in all PGP ids - - for(std::list::const_iterator it = pgpList.begin(); it != pgpList.end(); ++it) - mostRecentTime[*it] = (rstime_t)0; - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgr::removeUnusedLocations()" << std::endl; -#endif - // Then compute the most recently used location for all PGP ids - - for( std::map::iterator it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - rstime_t& bst(mostRecentTime[it->second.gpg_id]) ; - bst = std::max(bst,it->second.lastcontact) ; - } - - // And remove all locations that are too old and also older than the most recent location. Doing this we're sure to always keep at least one location per PGP id. - - for( std::map::iterator it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (now > it->second.lastcontact + RS_PEER_OFFLINE_DELETE && it->second.lastcontact < mostRecentTime[it->second.gpg_id]) - toRemove.push_back(it->first); -#ifdef PEER_DEBUG - std::cerr << "Location " << it->first << " PGP id " << it->second.gpg_id << " last contact " << it->second.lastcontact << " remove: " << (now > it->second.lastcontact + RS_PEER_OFFLINE_DELETE) << " most recent: " << mostRecentTime[it->second.gpg_id] - << ". Final result remove: " << (it->second.lastcontact < mostRecentTime[it->second.gpg_id] && now > it->second.lastcontact + RS_PEER_OFFLINE_DELETE )<< std::endl; -#endif - } - } - - for (std::list::iterator it = toRemove.begin(); it != toRemove.end(); ++it) - removeFriend(*it, false) ; - - return true; -} - -p3PeerMgr::~p3PeerMgr() = default; diff --git a/libretroshare/src/pqi/p3peermgr.h b/libretroshare/src/pqi/p3peermgr.h deleted file mode 100644 index 2cc9e4888..000000000 --- a/libretroshare/src/pqi/p3peermgr.h +++ /dev/null @@ -1,431 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3peermgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2011 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_PEER_MANAGER_HEADER -#define MRK_PQI_PEER_MANAGER_HEADER - -#include -#include "pqi/pqimonitor.h" -#include "pqi/pqiipset.h" -#include "pqi/pqiassist.h" - -#include "pqi/p3cfgmgr.h" - -#include "util/rsthreads.h" - -/* RS_VIS_STATE -> specified in rspeers.h - */ - - /* Startup Modes (confirmed later) */ -const uint32_t RS_NET_MODE_TRYMODE = 0xff00; - -const uint32_t RS_NET_MODE_TRY_EXT = 0x0100; -const uint32_t RS_NET_MODE_TRY_UPNP = 0x0200; -const uint32_t RS_NET_MODE_TRY_UDP = 0x0400; -const uint32_t RS_NET_MODE_TRY_LOOPBACK = 0x0800; - - /* Actual State */ -const uint32_t RS_NET_MODE_ACTUAL = 0x00ff; - -const uint32_t RS_NET_MODE_UNKNOWN = 0x0000; -const uint32_t RS_NET_MODE_EXT = 0x0001; -const uint32_t RS_NET_MODE_UPNP = 0x0002; -const uint32_t RS_NET_MODE_UDP = 0x0004; -const uint32_t RS_NET_MODE_HIDDEN = 0x0008; -const uint32_t RS_NET_MODE_UNREACHABLE = 0x0010; - - -/* flags of peerStatus */ -const uint32_t RS_NET_FLAGS_USE_DISC = 0x0001; -const uint32_t RS_NET_FLAGS_USE_DHT = 0x0002; -const uint32_t RS_NET_FLAGS_ONLINE = 0x0004; -const uint32_t RS_NET_FLAGS_EXTERNAL_ADDR = 0x0008; -const uint32_t RS_NET_FLAGS_STABLE_UDP = 0x0010; -const uint32_t RS_NET_FLAGS_TRUSTS_ME = 0x0020; - -/* - * remove locations offline since 90 days - * stopt sending locations via discovery when offline for +30 days - */ -const rstime_t RS_PEER_OFFLINE_DELETE = (90 * 24 * 3600); -const rstime_t RS_PEER_OFFLINE_NO_DISC = (30 * 24 * 3600); - -class peerState -{ - public: - peerState(); /* init */ - - RsPeerId id; - RsPgpId gpg_id; - - // This flag is used when adding a single SSL cert as friend without adding its PGP key in the friend list. This allows to - // have short invites. However, because this represent a significant security risk, we perform multiple consistency checks - // whenever we use this flag, in particular: - // flat is true <==> friend SSL cert is in the friend list, but PGP id is not in the friend list - - bool skip_pgp_signature_validation; - - uint32_t netMode; /* EXT / UPNP / UDP / HIDDEN / INVALID */ - /* visState */ - uint16_t vs_disc; - uint16_t vs_dht; - - struct sockaddr_storage localaddr; - struct sockaddr_storage serveraddr; - std::string dyndns; - - rstime_t lastcontact; - - /* list of addresses from various sources */ - pqiIpAddrSet ipAddrs; - - bool hiddenNode; /* all IP addresses / dyndns must be blank */ - std::string hiddenDomain; - uint16_t hiddenPort; - uint32_t hiddenType; - - std::string location; - std::string name; - - uint32_t maxUpRate ; - uint32_t maxDnRate ; -}; - -class RsNodeGroupItem; -struct RsGroupInfo; - -class p3LinkMgr; -class p3NetMgr; - -class p3LinkMgrIMPL; -class p3NetMgrIMPL; - -class p3PeerMgr -{ -public: - virtual bool addFriend( const RsPeerId &ssl_id, const RsPgpId &gpg_id, - uint32_t netMode = RS_NET_MODE_UDP, - uint16_t vsDisc = RS_VS_DISC_FULL, - uint16_t vsDht = RS_VS_DHT_FULL, - rstime_t lastContact = 0, - ServicePermissionFlags = ServicePermissionFlags(RS_NODE_PERM_DEFAULT) ) = 0; - - virtual bool addSslOnlyFriend( - const RsPeerId& sslId, - const RsPgpId& pgpId, - const RsPeerDetails& details = RsPeerDetails() ) = 0; - - // Calling this removed the skip_pgp_signature_validation flag on all peers which PGP key is the one supplied. - virtual bool notifyPgpKeyReceived(const RsPgpId& pgp_key_id) = 0; - - virtual bool removeFriend(const RsPeerId &ssl_id, bool removePgpId) = 0; - virtual bool isFriend(const RsPeerId& ssl_id) = 0; - virtual bool isSslOnlyFriend(const RsPeerId &ssl_id)=0; - -virtual bool getAssociatedPeers(const RsPgpId &gpg_id, std::list &ids) = 0; -virtual bool removeAllFriendLocations(const RsPgpId &gpgid) = 0; - - - /******************** Groups **********************/ - /* This is solely used by p3peers - makes sense */ - -virtual bool addGroup(RsGroupInfo &groupInfo) = 0; -virtual bool editGroup(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) = 0; -virtual bool removeGroup(const RsNodeGroupId &groupId) = 0; -virtual bool getGroupInfo(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) = 0; -virtual bool getGroupInfoByName(const std::string& groupName, RsGroupInfo &groupInfo) = 0; -virtual bool getGroupInfoList(std::list &groupInfoList) = 0; -virtual bool assignPeersToGroup(const RsNodeGroupId &groupId, const std::list &peerIds, bool assign) = 0; - - virtual bool resetOwnExternalAddressList() = 0 ; - - virtual ServicePermissionFlags servicePermissionFlags(const RsPgpId& gpg_id) =0; - virtual ServicePermissionFlags servicePermissionFlags(const RsPeerId& ssl_id) =0; - virtual void setServicePermissionFlags(const RsPgpId& gpg_id,const ServicePermissionFlags& flags) =0; - - /**************** Set Net Info ****************/ - /* - * These functions are used by: - * 1) p3linkmgr - * 2) p3peers - reasonable - * 3) p3disc - reasonable - */ - - virtual bool addPeerLocator(const RsPeerId &ssl_id, const RsUrl& locator) = 0; -virtual bool setLocalAddress(const RsPeerId &id, const struct sockaddr_storage &addr) = 0; -virtual bool setExtAddress(const RsPeerId &id, const struct sockaddr_storage &addr) = 0; -virtual bool setDynDNS(const RsPeerId &id, const std::string &dyndns) = 0; -virtual bool addCandidateForOwnExternalAddress(const RsPeerId& from, const struct sockaddr_storage &addr) = 0; -virtual bool getExtAddressReportedByFriends(struct sockaddr_storage& addr,uint8_t& isstable) = 0; - -virtual bool setNetworkMode(const RsPeerId &id, uint32_t netMode) = 0; -virtual bool setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht) = 0; - -virtual bool setLocation(const RsPeerId &pid, const std::string &location) = 0; -virtual bool setHiddenDomainPort(const RsPeerId &id, const std::string &domain_addr, const uint16_t domain_port) = 0; -virtual bool isHiddenNode(const RsPeerId& id) = 0 ; - -virtual bool updateCurrentAddress(const RsPeerId& id, const pqiIpAddress &addr) = 0; -virtual bool updateLastContact(const RsPeerId& id) = 0; -virtual bool updateAddressList(const RsPeerId& id, const pqiIpAddrSet &addrs) = 0; - - - // THIS MUST ONLY BE CALLED BY NETMGR!!!! -virtual bool UpdateOwnAddress(const struct sockaddr_storage &local_addr, const struct sockaddr_storage &ext_addr) = 0; - - /**************** Net Status Info ****************/ - /* - * MUST RATIONALISE THE DATA FROM THESE FUNCTIONS - * These functions are used by: - * 1) p3face-config ... to remove! - * 2) p3peers - reasonable - * 3) p3disc - reasonable - */ - -virtual bool getOwnNetStatus(peerState &state) = 0; -virtual bool getFriendNetStatus(const RsPeerId &id, peerState &state) = 0; - -virtual bool getPeerName(const RsPeerId &ssl_id, std::string &name) = 0; -virtual bool getGpgId(const RsPeerId &sslId, RsPgpId &gpgId) = 0; -virtual uint32_t getConnectionType(const RsPeerId &sslId) = 0; - -virtual bool setProxyServerAddress(const uint32_t type, const struct sockaddr_storage &proxy_addr) = 0; -virtual bool getProxyServerAddress(const uint32_t type, struct sockaddr_storage &proxy_addr) = 0; -virtual bool getProxyServerStatus(const uint32_t type, uint32_t& status) = 0; -virtual bool isHidden() = 0; -virtual bool isHidden(const uint32_t type) = 0; -virtual bool isHiddenPeer(const RsPeerId &ssl_id) = 0; -virtual bool isHiddenPeer(const RsPeerId &ssl_id, const uint32_t type) = 0; -virtual bool getProxyAddress(const RsPeerId &ssl_id, struct sockaddr_storage &proxy_addr, std::string &domain_addr, uint16_t &domain_port) = 0; -virtual uint32_t hiddenDomainToHiddenType(const std::string &domain) = 0; -virtual uint32_t getHiddenType(const RsPeerId &ssl_id) = 0; - - -virtual int getFriendCount(bool ssl, bool online) = 0; -virtual bool setMaxRates(const RsPgpId& pid,uint32_t maxUp,uint32_t maxDn)=0; -virtual bool getMaxRates(const RsPgpId& pid,uint32_t& maxUp,uint32_t& maxDn)=0; -virtual bool getMaxRates(const RsPeerId& pid,uint32_t& maxUp,uint32_t& maxDn)=0; - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ - - // Single Use Function... shouldn't be here. used by p3serverconfig.cc -virtual bool haveOnceConnected() = 0; - -virtual bool locked_computeCurrentBestOwnExtAddressCandidate(sockaddr_storage &addr, uint32_t &count)=0; - -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ - - virtual ~p3PeerMgr(); -}; - - -class p3PeerMgrIMPL: public p3PeerMgr, public p3Config -{ -public: - - /************************************************************************************************/ - /* EXTERNAL INTERFACE */ - /************************************************************************************************/ - - virtual bool addFriend(const RsPeerId&ssl_id, const RsPgpId&gpg_id, uint32_t netMode = RS_NET_MODE_UDP, - uint16_t vsDisc = RS_VS_DISC_FULL, uint16_t vsDht = RS_VS_DHT_FULL, - rstime_t lastContact = 0,ServicePermissionFlags = ServicePermissionFlags(RS_NODE_PERM_DEFAULT)); - - bool addSslOnlyFriend(const RsPeerId& sslId, const RsPgpId &pgp_id, const RsPeerDetails& details = RsPeerDetails() ) override; - - virtual bool notifyPgpKeyReceived(const RsPgpId& pgp_key_id) override; - - virtual bool removeFriend(const RsPeerId &ssl_id, bool removePgpId); - virtual bool removeFriend(const RsPgpId &pgp_id); - - virtual bool isFriend(const RsPeerId &ssl_id); - virtual bool isSslOnlyFriend(const RsPeerId &ssl_id); - - virtual bool getAssociatedPeers(const RsPgpId &gpg_id, std::list &ids); - virtual bool removeAllFriendLocations(const RsPgpId &gpgid); - - - /******************** Groups **********************/ - /* This is solely used by p3peers - makes sense */ - - virtual bool addGroup(RsGroupInfo &groupInfo); - virtual bool editGroup(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo); - virtual bool removeGroup(const RsNodeGroupId &groupId); - virtual bool getGroupInfo(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo); - virtual bool getGroupInfoByName(const std::string& groupName, RsGroupInfo &groupInfo) ; - virtual bool getGroupInfoList(std::list &groupInfoList); - virtual bool assignPeersToGroup(const RsNodeGroupId &groupId, const std::list &peerIds, bool assign); - - virtual ServicePermissionFlags servicePermissionFlags(const RsPgpId& gpg_id) ; - virtual ServicePermissionFlags servicePermissionFlags(const RsPeerId& ssl_id) ; - virtual void setServicePermissionFlags(const RsPgpId& gpg_id,const ServicePermissionFlags& flags) ; - - /**************** Set Net Info ****************/ - /* - * These functions are used by: - * 1) p3linkmgr - * 2) p3peers - reasonable - * 3) p3disc - reasonable - */ - - virtual bool addPeerLocator(const RsPeerId &ssl_id, const RsUrl& locator); - virtual bool setLocalAddress(const RsPeerId &id, const struct sockaddr_storage &addr); - virtual bool setExtAddress(const RsPeerId &id, const struct sockaddr_storage &addr); - virtual bool setDynDNS(const RsPeerId &id, const std::string &dyndns); - virtual bool addCandidateForOwnExternalAddress(const RsPeerId& from, const struct sockaddr_storage &addr) ; - virtual bool getExtAddressReportedByFriends(struct sockaddr_storage& addr, uint8_t &isstable) ; - - virtual bool setNetworkMode(const RsPeerId &id, uint32_t netMode); - virtual bool setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht); - - virtual bool setLocation(const RsPeerId &pid, const std::string &location); - virtual bool setHiddenDomainPort(const RsPeerId &id, const std::string &domain_addr, const uint16_t domain_port); - virtual bool isHiddenNode(const RsPeerId& id); - - virtual bool updateCurrentAddress(const RsPeerId& id, const pqiIpAddress &addr); - virtual bool updateLastContact(const RsPeerId& id); - virtual bool updateAddressList(const RsPeerId& id, const pqiIpAddrSet &addrs); - - virtual bool resetOwnExternalAddressList() ; - - // THIS MUST ONLY BE CALLED BY NETMGR!!!! - virtual bool UpdateOwnAddress(const struct sockaddr_storage &local_addr, const struct sockaddr_storage &ext_addr); - /**************** Net Status Info ****************/ - /* - * MUST RATIONALISE THE DATA FROM THESE FUNCTIONS - * These functions are used by: - * 1) p3face-config ... to remove! - * 2) p3peers - reasonable - * 3) p3disc - reasonable - */ - - virtual bool getOwnNetStatus(peerState &state); - virtual bool getFriendNetStatus(const RsPeerId &id, peerState &state); - - virtual bool getPeerName(const RsPeerId& ssl_id, std::string& name); - virtual bool getGpgId(const RsPeerId& sslId, RsPgpId& gpgId); - virtual uint32_t getConnectionType(const RsPeerId& sslId); - - virtual bool setProxyServerAddress(const uint32_t type, const struct sockaddr_storage &proxy_addr); - virtual bool getProxyServerAddress(const uint32_t type, struct sockaddr_storage &proxy_addr); - virtual bool getProxyServerStatus(const uint32_t type, uint32_t &proxy_status); - virtual bool isHidden(); - virtual bool isHidden(const uint32_t type); - virtual bool isHiddenPeer(const RsPeerId &ssl_id); - virtual bool isHiddenPeer(const RsPeerId &ssl_id, const uint32_t type); - virtual bool getProxyAddress(const RsPeerId& ssl_id, struct sockaddr_storage &proxy_addr, std::string &domain_addr, uint16_t &domain_port); - virtual uint32_t hiddenDomainToHiddenType(const std::string &domain); - virtual uint32_t getHiddenType(const RsPeerId &ssl_id); - - virtual int getFriendCount(bool ssl, bool online); - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ - - // Single Use Function... shouldn't be here. used by p3serverconfig.cc - virtual bool haveOnceConnected(); - - virtual bool setMaxRates(const RsPgpId& pid,uint32_t maxUp,uint32_t maxDn); - virtual bool getMaxRates(const RsPgpId& pid,uint32_t& maxUp,uint32_t& maxDn); - virtual bool getMaxRates(const RsPeerId& pid,uint32_t& maxUp,uint32_t& maxDn); - - /************************************************************************************************/ - /* Extra IMPL Functions (used by p3LinkMgr, p3NetMgr + Setup) */ - /************************************************************************************************/ - - p3PeerMgrIMPL( const RsPeerId& ssl_own_id, - const RsPgpId& gpg_own_id, - const std::string& gpg_own_name, - const std::string& ssl_own_location) ; - - void setManagers(p3LinkMgrIMPL *linkMgr, p3NetMgrIMPL *netMgr); - - bool forceHiddenNode(); - bool setupHiddenNode(const std::string &hiddenAddress, const uint16_t hiddenPort); - - void tick(); - - const RsPeerId& getOwnId(); - bool setOwnNetworkMode(uint32_t netMode); - bool setOwnVisState(uint16_t vs_disc, uint16_t vs_dht); - - int getConnectAddresses( const RsPeerId &id, sockaddr_storage &lAddr, - sockaddr_storage &eAddr, pqiIpAddrSet &histAddrs, - std::string &dyndns ); - - -protected: - /* Internal Functions */ - - bool removeUnusedLocations(); - bool removeBannedIps(); - - void printPeerLists(std::ostream &out); - - virtual bool locked_computeCurrentBestOwnExtAddressCandidate(sockaddr_storage &addr, uint32_t &count); - -protected: - /*****************************************************************/ - /*********************** p3config ******************************/ - /* Key Functions to be overloaded for Full Configuration */ - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool &cleanup, std::list&); - virtual void saveDone(); - virtual bool loadList(std::list& load); - /*****************************************************************/ - - /* other important managers */ - - p3LinkMgrIMPL *mLinkMgr; - p3NetMgrIMPL *mNetMgr; - -private: - RsMutex mPeerMtx; /* protects below */ - - bool mStatusChanged; - - std::list clients; - - peerState mOwnState; - - std::map mFriendList; // - - std::map mReportedOwnAddresses ; - - std::map groupList; - //uint32_t lastGroupId; - - std::list saveCleanupList; /* TEMPORARY LIST WHEN SAVING */ - - std::map mFriendsPermissionFlags ; // permission flags for each gpg key - std::map mPeerBandwidthLimits ; // bandwidth limits for each gpg key - - struct sockaddr_storage mProxyServerAddressTor; - struct sockaddr_storage mProxyServerAddressI2P; - uint32_t mProxyServerStatusTor ; - uint32_t mProxyServerStatusI2P ; - -}; - -#endif // MRK_PQI_PEER_MANAGER_HEADER diff --git a/libretroshare/src/pqi/p3servicecontrol.cc b/libretroshare/src/pqi/p3servicecontrol.cc deleted file mode 100644 index 9bf3b3c62..000000000 --- a/libretroshare/src/pqi/p3servicecontrol.cc +++ /dev/null @@ -1,1416 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3servicecontrol.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2014-2014 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include - -#include "p3servicecontrol.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "serialiser/rstypeserializer.h" -#include "rsitems/rsnxsitems.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/pqiservice.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsevents.h" - -/*******************************/ -// #define SERVICECONTROL_DEBUG 1 -/*******************************/ - -static const uint8_t RS_PKT_SUBTYPE_SERVICE_CONTROL_SERVICE_PERMISSIONS = 0x01 ; - -class RsServiceControlItem: public RsItem -{ -public: - explicit RsServiceControlItem(uint8_t item_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_SERVICE_CONTROL,item_subtype) {} -}; - -class RsServicePermissionItem: public RsServiceControlItem, public RsServicePermissions -{ -public: - RsServicePermissionItem(): RsServiceControlItem(RS_PKT_SUBTYPE_SERVICE_CONTROL_SERVICE_PERMISSIONS) {} - explicit RsServicePermissionItem(const RsServicePermissions& perms) : RsServiceControlItem(RS_PKT_SUBTYPE_SERVICE_CONTROL_SERVICE_PERMISSIONS), RsServicePermissions(perms) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,mServiceId,"mServiceId") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,mServiceName,"mServiceName") ; - RsTypeSerializer::serial_process (j,ctx,mDefaultAllowed,"mDefaultAllowed") ; - - RsTypeSerializer::serial_process (j,ctx,mPeersAllowed,"mPeersAllowed"); - RsTypeSerializer::serial_process (j,ctx,mPeersDenied ,"mPeersDenied"); - } - - virtual void clear() {} -}; - -class ServiceControlSerialiser: public RsServiceSerializer -{ -public: - ServiceControlSerialiser() : RsServiceSerializer(RS_SERVICE_TYPE_SERVICE_CONTROL) {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const - { - if(RS_SERVICE_TYPE_SERVICE_CONTROL != service) - return NULL; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_SERVICE_CONTROL_SERVICE_PERMISSIONS: return new RsServicePermissionItem(); - default: - return NULL ; - } - } -}; - -RsServiceControl *rsServiceControl = NULL; - -p3ServiceControl::p3ServiceControl(p3LinkMgr *linkMgr) - : RsServiceControl(), p3Config(), - mLinkMgr(linkMgr), mOwnPeerId(linkMgr->getOwnId()), - mCtrlMtx("p3ServiceControl"), mMonitorMtx("P3ServiceControl::Monitor"), - mServiceServer(NULL) -{ - mSerialiser = new ServiceControlSerialiser ; -} - -RsSerialiser *p3ServiceControl::setupSerialiser() -{ - RsSerialiser *serial = new RsSerialiser; - serial->addSerialType(new ServiceControlSerialiser) ; - - return serial ; -} - -const RsPeerId& p3ServiceControl::getOwnId() -{ - return mOwnPeerId; -} - -bool p3ServiceControl::getServiceItemNames(uint32_t serviceId,std::map& names) -{ - if(mServiceServer != NULL) - return mServiceServer->getServiceItemNames(serviceId,names) ; - - return false ; -} - -/* Interface for Services */ -bool p3ServiceControl::registerService(const RsServiceInfo &info, bool defaultOn) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - std::map::iterator it; - it = mOwnServices.find(info.mServiceType); - if (it != mOwnServices.end()) - { - std::cerr << "p3ServiceControl::registerService() ERROR Duplicate Service ID"; - std::cerr << std::endl; - return false; - } - - /* sanity check ServiceInfo */ - mOwnServices[info.mServiceType] = info; - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::registerService() Registered ServiceID: " << info.mServiceType; - std::cerr << std::endl; - std::cerr << "p3ServiceControl::registerService() ServiceName: " << info.mServiceName; - std::cerr << std::endl; -#endif - - - /* create default permissions for this service - * this will be overwritten by configuration (if it exists). - */ - - createDefaultPermissions_locked(info.mServiceType, info.mServiceName, defaultOn); - return true; -} - -bool p3ServiceControl::deregisterService(uint32_t serviceId) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - std::map::iterator it; - it = mOwnServices.find(serviceId); - if (it == mOwnServices.end()) - { - std::cerr << "p3ServiceControl::deregisterService() ERROR No matching Service ID"; - std::cerr << std::endl; - return false; - } - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::deregisterService() Removed ServiceID: " << serviceId; - std::cerr << std::endl; -#endif - mOwnServices.erase(it); - return true; -} - - -/* Interface for Services */ -bool p3ServiceControl::registerServiceMonitor(pqiServiceMonitor *monitor, uint32_t serviceId) -{ - RsStackMutex stack(mMonitorMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::registerServiceMonitor() for ServiceId: "; - std::cerr << serviceId; - std::cerr << std::endl; -#endif - - mMonitors.insert(std::make_pair(serviceId, monitor)); - return true; -} - - -bool p3ServiceControl::deregisterServiceMonitor(pqiServiceMonitor *monitor) -{ - RsStackMutex stack(mMonitorMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::deregisterServiceMonitor()"; - std::cerr << std::endl; -#endif - - std::multimap::iterator it; - for(it = mMonitors.begin(); it != mMonitors.end(); ) - { - if (it->second == monitor) - { - mMonitors.erase(it++); - } - else - { - ++it; - } - } - return true; -} - -/* Interface to p3ServiceInfo */ -void p3ServiceControl::getServiceChanges(std::set &updateSet) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::getServiceChanges()"; - std::cerr << std::endl; -#endif - - std::set::iterator it; - for (it = mUpdatedSet.begin(); it != mUpdatedSet.end(); ++it) - { - updateSet.insert(*it); - } - - mUpdatedSet.clear(); -} - -std::string p3ServiceControl::getServiceName(uint32_t service_id) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - std::map::const_iterator it = mOwnServices.find(service_id) ; - - if(it == mOwnServices.end()) - { - std::cerr << "(EE) Cannot find own service for ID = " << std::hex << service_id << std::dec << std::endl; - return std::string(); - } - - return it->second.mServiceName; -} - -bool p3ServiceControl::getOwnServices(RsPeerServiceInfo &info) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::getOwnServices()"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - info.mPeerId.clear() ; - info.mServiceList = mOwnServices; - return true; -} - - -bool p3ServiceControl::getServicesAllowed(const RsPeerId &peerId, RsPeerServiceInfo &info) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::getServicesAllowed(" << peerId.toStdString() << ")"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - info.mPeerId = peerId; - - // For each registered Service.. check if peer has permissions. - std::map::iterator it; - for(it = mOwnServices.begin(); it != mOwnServices.end(); ++it) - { - if (peerHasPermissionForService_locked(peerId, it->first)) - { - info.mServiceList[it->first] = it->second; - } - } - return true; -} - -bool p3ServiceControl::peerHasPermissionForService_locked(const RsPeerId &peerId, uint32_t serviceId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::peerHasPermissionForService_locked()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mServicePermissionMap.find(serviceId); - if (it == mServicePermissionMap.end()) - { - return false; - } - return it->second.peerHasPermission(peerId); -} - -// This is used by both RsServiceControl and p3ServiceInfo. -bool p3ServiceControl::getServicesProvided(const RsPeerId &peerId, RsPeerServiceInfo &info) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::getServicesProvided()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mServicesProvided.find(peerId); - if (it == mServicesProvided.end()) - { - return false; - } - - info = it->second; - return true; -} - -bool p3ServiceControl::updateServicesProvided(const RsPeerId &peerId, const RsPeerServiceInfo &info) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateServicesProvided() from: " << peerId.toStdString(); - std::cerr << std::endl; - std::cerr << info; - std::cerr << std::endl; -#endif - - mServicesProvided[peerId] = info; - updateFilterByPeer_locked(peerId); - - IndicateConfigChanged() ; - return true; -} - -/* External Interface to RsServiceControl */ -bool p3ServiceControl::getServicePermissions(uint32_t serviceId, RsServicePermissions &permissions) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::getServicePermissions()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - - it = mServicePermissionMap.find(serviceId); - if (it == mServicePermissionMap.end()) - { - return false; - } - permissions = it->second; - return true; -} - -bool p3ServiceControl::createDefaultPermissions_locked(uint32_t serviceId, const std::string& serviceName, bool defaultOn) -{ - std::map::iterator it; - it = mServicePermissionMap.find(serviceId); - if (it == mServicePermissionMap.end()) - { - RsServicePermissions perms; - perms.mServiceId = serviceId; - perms.mServiceName = serviceName; - perms.mDefaultAllowed = defaultOn; - - mServicePermissionMap[serviceId] = perms; - IndicateConfigChanged() ; - return true; - } - return false; -} - - -bool p3ServiceControl::updateServicePermissions(uint32_t serviceId, const RsServicePermissions &permissions) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateServicePermissions()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mServicePermissionMap.find(serviceId); - if (it == mServicePermissionMap.end()) - { - std::cerr << "p3ServiceControl::updateServicePermissions()"; - std::cerr << " ERROR missing previous permissions"; - std::cerr << std::endl; - // ERROR. - return false; - } - - std::list onlinePeers; - mLinkMgr->getOnlineList(onlinePeers); - std::list::const_iterator pit; - if (it != mServicePermissionMap.end()) - { - for(pit = onlinePeers.begin(); pit != onlinePeers.end(); ++pit) - { - if (it->second.peerHasPermission(*pit) != - permissions.peerHasPermission(*pit)) - { - mUpdatedSet.insert(*pit); - } - } - } - - it->second = permissions; - it->second.mServiceId = serviceId; // just to make sure! - - // This is overkill - but will update everything. - updateAllFilters_locked(); - IndicateConfigChanged() ; - return true; -} - - -/****************************************************************************/ -/****************************************************************************/ -/****************************************************************************/ -/****************************************************************************/ - -// This is the basic system... -// which will be a little slow (2x maps). -// -// Potential improvement is to push the RsPeerFilter -// to the pqiStreamer, (when items have been sorted by peers already!). -// but we will do this later. - -bool p3ServiceControl::checkFilter(uint32_t serviceId, const RsPeerId &peerId) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() "; - std::cerr << " ServiceId: " << serviceId; -#endif - - std::map::iterator it; - it = mOwnServices.find(serviceId); - if (it != mOwnServices.end()) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << " ServiceName: " << it->second.mServiceName; -#endif - } - else - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << " ServiceName: Unknown! "; -#endif - } - -#ifdef SERVICECONTROL_DEBUG - std::cerr << " PeerId: " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - // must allow ServiceInfo through, or we have nothing! - if (serviceId == RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(RS_SERVICE_TYPE_SERVICEINFO)) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() Allowed SERVICEINFO"; - std::cerr << std::endl; -#endif - return true; - } - - - std::map::const_iterator pit; - pit = mPeerFilterMap.find(peerId); - if (pit == mPeerFilterMap.end()) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() Denied No PeerId"; - std::cerr << std::endl; -#endif - return false; - } - - if (pit->second.mDenyAll) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() Denied Peer.DenyAll"; - std::cerr << std::endl; -#endif - return false; - } - - if (pit->second.mAllowAll) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() Allowed Peer.AllowAll"; - std::cerr << std::endl; -#endif - return true; - } - - std::set::const_iterator sit; - sit = pit->second.mAllowedServices.find(serviceId); - if (sit == pit->second.mAllowedServices.end()) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() Denied !Peer.find(serviceId)"; - std::cerr << std::endl; -#endif - return false; - } -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() Allowed Peer.find(serviceId)"; - std::cerr << std::endl; -#endif - return true; -} - -bool versionOkay(uint16_t version_major, uint16_t version_minor, - uint16_t min_version_major, uint16_t min_version_minor) -{ - if (version_major > min_version_major) - { - return true; - } - if (version_major == min_version_major) - { - return (version_minor >= min_version_minor); - } - return false; -} - - -bool ServiceInfoCompatible(const RsServiceInfo &info1, const RsServiceInfo &info2) -{ - // Id, or Name mismatch. - if ((info1.mServiceType != info2.mServiceType) || - (info1.mServiceName != info2.mServiceName)) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "servicesCompatible: Type/Name mismatch"; - std::cerr << std::endl; - std::cerr << "Info1 ID: " << info1.mServiceType; - std::cerr << " " << info1.mServiceName; - std::cerr << std::endl; - std::cerr << "Info2 ID: " << info2.mServiceType; - std::cerr << " " << info2.mServiceName; - std::cerr << std::endl; -#endif - return false; - } - - // ensure that info1 meets minimum requirements for info2 - if (!versionOkay(info1.mVersionMajor, info1.mVersionMinor, - info2.mMinVersionMajor, info2.mMinVersionMinor)) - { - return false; - } - - // ensure that info2 meets minimum requirements for info1 - if (!versionOkay(info2.mVersionMajor, info2.mVersionMinor, - info1.mMinVersionMajor, info1.mMinVersionMinor)) - { - return false; - } - return true; -} - - -bool p3ServiceControl::updateFilterByPeer(const RsPeerId &peerId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateFilterByPeer()"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - return updateFilterByPeer_locked(peerId); -} - - -bool p3ServiceControl::updateAllFilters() -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateAllFilters()"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - return updateAllFilters_locked(); -} - - -bool p3ServiceControl::updateAllFilters_locked() -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateAllFilters_locked()"; - std::cerr << std::endl; -#endif - - // Create a peerSet from ServicesProvided + PeerFilters. - // This will completely refresh the Filters. - std::set peerSet; - std::set::const_iterator pit; - - std::map::const_iterator it; - for(it = mServicesProvided.begin(); it != mServicesProvided.end(); ++it) - { - peerSet.insert(it->first); - } - - std::map::const_iterator fit; - for(fit = mPeerFilterMap.begin(); fit != mPeerFilterMap.end(); ++fit) - { - peerSet.insert(fit->first); - } - - for(pit = peerSet.begin(); pit != peerSet.end(); ++pit) - { - updateFilterByPeer_locked(*pit); - } - return true; -} - - -// create filter. (the easy way). -bool p3ServiceControl::updateFilterByPeer_locked(const RsPeerId &peerId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateFilterByPeer_locked() : " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - ServicePeerFilter originalFilter; - ServicePeerFilter peerFilter; - - std::map::iterator fit; - fit = mPeerFilterMap.find(peerId); - if (fit != mPeerFilterMap.end()) - { - originalFilter = fit->second; - } - - std::map::iterator it; - it = mServicesProvided.find(peerId); - if (it == mServicesProvided.end()) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateFilterByPeer_locked() Empty ... Clearing"; - std::cerr << std::endl; -#endif - - // empty, remove... - recordFilterChanges_locked(peerId, originalFilter, peerFilter); - if (fit != mPeerFilterMap.end()) - { - std::cerr << std::endl; - mPeerFilterMap.erase(fit); - } - return true; - } - - // For each registered Service.. check if services compatible. - // then check for permissions. - - // similar maps, can iterate through in parallel. - std::map::const_iterator oit = mOwnServices.begin(); - std::map::const_iterator eoit = mOwnServices.end(); - std::map::const_iterator tit = it->second.mServiceList.begin(); - std::map::const_iterator etit = it->second.mServiceList.end(); - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateFilterByPeer_locked() Comparing lists"; - std::cerr << std::endl; -#endif - - - while((oit != eoit) && (tit != etit)) - { - if (oit->first == tit->first) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "\tChecking Matching Service ID: " << oit->first; - std::cerr << std::endl; -#endif - /* match of service IDs */ - /* check if compatible */ - if (ServiceInfoCompatible(oit->second, tit->second)) - { - if (peerHasPermissionForService_locked(peerId, oit->first)) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "\t\tMatched Service ID: " << oit->first; - std::cerr << std::endl; -#endif - peerFilter.mAllowedServices.insert(oit->first); - } - } - ++oit; - ++tit; - } - else - { - if (oit->first < tit->first) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "\tSkipping Only Own Service ID: " << oit->first; - std::cerr << std::endl; -#endif - ++oit; - } - else - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "\tSkipping Only Peer Service ID: " << tit->first; - std::cerr << std::endl; -#endif - ++tit; - } - } - } - - // small optimisations. - if (peerFilter.mAllowedServices.empty()) - { - peerFilter.mDenyAll = true; - } - else - { - peerFilter.mDenyAll = false; - if (peerFilter.mAllowedServices.size() == mOwnServices.size()) - { - peerFilter.mAllowAll = true; - } - } - - // update or remove. - if (peerFilter.mDenyAll) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateFilterByPeer_locked() Empty(2) ... Clearing"; - std::cerr << std::endl; -#endif - - if (fit != mPeerFilterMap.end()) - { - mPeerFilterMap.erase(fit); - } - } - else - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateFilterByPeer_locked() Installing PeerFilter"; - std::cerr << std::endl; -#endif - mPeerFilterMap[peerId] = peerFilter; - } - recordFilterChanges_locked(peerId, originalFilter, peerFilter); - - using Evt_t = RsPeerStateChangedEvent; - if(rsEvents) - rsEvents->postEvent(std::unique_ptr(new Evt_t(peerId))); - - return true; -} - -void p3ServiceControl::recordFilterChanges_locked(const RsPeerId &peerId, - ServicePeerFilter &originalFilter, ServicePeerFilter &updatedFilter) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::recordFilterChanges_locked()"; - std::cerr << std::endl; - std::cerr << "PeerId: " << peerId.toStdString(); - std::cerr << std::endl; - std::cerr << "OriginalFilter: " << originalFilter; - std::cerr << std::endl; - std::cerr << "UpdatedFilter: " << updatedFilter; - std::cerr << std::endl; -#endif - - /* find differences */ - //std::map changes; - std::set::const_iterator it1, it2, eit1, eit2; - it1 = originalFilter.mAllowedServices.begin(); - eit1 = originalFilter.mAllowedServices.end(); - it2 = updatedFilter.mAllowedServices.begin(); - eit2 = updatedFilter.mAllowedServices.end(); - - while((it1 != eit1) && (it2 != eit2)) - { - if (*it1 < *it2) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "Removed Service: " << *it1; - std::cerr << std::endl; -#endif - // removal - //changes[*it1] = false; - filterChangeRemoved_locked(peerId, *it1); - ++it1; - } - else if (*it2 < *it1) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "Added Service: " << *it2; - std::cerr << std::endl; -#endif - // addition. - filterChangeAdded_locked(peerId, *it2); - //changes[*it2] = true; - ++it2; - } - else - { - ++it1; - ++it2; - } - } - - // Handle the unfinished Set. - for(; it1 != eit1; ++it1) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "Removed Service: " << *it1; - std::cerr << std::endl; -#endif - // removal - //changes[*it1] = false; - filterChangeRemoved_locked(peerId, *it1); - } - - for(; it2 != eit2; ++it2) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "Added Service: " << *it2; - std::cerr << std::endl; -#endif - // addition. - //changes[*it2] = true; - filterChangeAdded_locked(peerId, *it2); - } - - // Can remove changes map... as only used below. -#if 0 - // now we to store for later notifications. - std::map::const_iterator cit; - for(cit = changes.begin(); cit != changes.end(); ++cit) - { - ServiceNotifications ¬es = mNotifications[cit->first]; - if (cit->second) - { - notes.mAdded.insert(peerId); - } - else - { - notes.mRemoved.insert(peerId); - } - } -#endif - -} - - -// when they go offline, etc. -void p3ServiceControl::removePeer(const RsPeerId &peerId) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::removePeer() : " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - ServicePeerFilter originalFilter; - bool hadFilter = false; - { - std::map::iterator fit; - fit = mPeerFilterMap.find(peerId); - if (fit != mPeerFilterMap.end()) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::removePeer() clearing mPeerFilterMap"; - std::cerr << std::endl; -#endif - - hadFilter = true; - originalFilter = fit->second; - mPeerFilterMap.erase(fit); - } - else - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::removePeer() Nothing in mPeerFilterMap"; - std::cerr << std::endl; -#endif - } - } - - { - std::map::iterator sit; - sit = mServicesProvided.find(peerId); - if (sit != mServicesProvided.end()) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::removePeer() clearing mServicesProvided"; - std::cerr << std::endl; -#endif - - mServicesProvided.erase(sit); - } - else - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::removePeer() Nothing in mServicesProvided"; - std::cerr << std::endl; -#endif - } - } - - if (hadFilter) - { - ServicePeerFilter emptyFilter; - recordFilterChanges_locked(peerId, originalFilter, emptyFilter); - } -} - -/****************************************************************************/ -/****************************************************************************/ -// need to provide list of connected peers per service. -// these are collected here. - -void p3ServiceControl::filterChangeRemoved_locked(const RsPeerId &peerId, uint32_t serviceId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::filterChangeRemoved_locked(" << peerId.toStdString(); - std::cerr << ", " << serviceId << ")"; - std::cerr << std::endl; -#endif - - //std::map >::iterator mit; - - std::set &peerSet = mServicePeerMap[serviceId]; - std::set::iterator sit; - - sit = peerSet.find(peerId); - if (sit != peerSet.end()) - { - peerSet.erase(sit); - } - else - { - // ERROR - std::cerr << "p3ServiceControl::filterChangeRemoved_locked() ERROR NOT FOUND"; - std::cerr << std::endl; - } - - // Add to Notifications too. - ServiceNotifications ¬es = mNotifications[serviceId]; - notes.mRemoved.insert(peerId); -} - - -void p3ServiceControl::filterChangeAdded_locked(const RsPeerId &peerId, uint32_t serviceId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::filterChangeAdded_locked(" << peerId.toStdString(); - std::cerr << ", " << serviceId << ")"; - std::cerr << std::endl; -#endif - - //std::map >::iterator mit; - - std::set &peerSet = mServicePeerMap[serviceId]; - - // This bit is only for error checking. - std::set::iterator sit = peerSet.find(peerId); - if (sit != peerSet.end()) - { - // ERROR. - std::cerr << "p3ServiceControl::filterChangeAdded_locked() ERROR NOT FOUND"; - std::cerr << std::endl; - } - peerSet.insert(peerId); - - // Add to Notifications too. - ServiceNotifications ¬es = mNotifications[serviceId]; - notes.mAdded.insert(peerId); -} - - - -void p3ServiceControl::getPeersConnected(uint32_t serviceId, std::set &peerSet) -{ - RS_STACK_MUTEX(mCtrlMtx); - - std::map >::iterator mit; - mit = mServicePeerMap.find(serviceId); - if (mit != mServicePeerMap.end()) - { - peerSet = mit->second; - } - else - { - peerSet.clear(); - } -} - - -bool p3ServiceControl::isPeerConnected(uint32_t serviceId, const RsPeerId &peerId) -{ - RS_STACK_MUTEX(mCtrlMtx); - - std::map >::iterator mit; - mit = mServicePeerMap.find(serviceId); - if (mit != mServicePeerMap.end()) - { - std::set::iterator sit; - sit = mit->second.find(peerId); - return (sit != mit->second.end()); - } - - return false; -} - - -/****************************************************************************/ -/****************************************************************************/ - -void p3ServiceControl::tick() -{ - notifyAboutFriends(); - notifyServices(); - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::tick()"; - std::cerr << std::endl; -#endif -} - -// configuration. -bool p3ServiceControl::saveList(bool &cleanup, std::list &saveList) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::saveList()"; - std::cerr << std::endl; -#endif - cleanup = true ; - - for(std::map::iterator it(mServicePermissionMap.begin());it!=mServicePermissionMap.end();++it) - { - RsServicePermissionItem *item = new RsServicePermissionItem(it->second) ; - saveList.push_back(item) ; - } - return true; -} - -bool p3ServiceControl::loadList(std::list& loadList) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::loadList()"; - std::cerr << std::endl; -#endif - for(std::list::const_iterator it(loadList.begin());it!=loadList.end();++it) - { - RsServicePermissionItem *item = dynamic_cast(*it) ; - - if(item != NULL) - mServicePermissionMap[item->mServiceId] = *item ; - - delete *it ; - } - - loadList.clear() ; - return true; -} - - -/****************************************************************************/ -/****************************************************************************/ - - // pqiMonitor. -void p3ServiceControl::statusChange(const std::list &plist) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::statusChange()"; - std::cerr << std::endl; -#endif - - std::list::const_iterator pit; - for(pit = plist.begin(); pit != plist.end(); ++pit) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::statusChange() for peer: "; - std::cerr << " peer: " << (pit->id).toStdString(); - std::cerr << " state: " << pit->state; - std::cerr << " actions: " << pit->actions; - std::cerr << std::endl; -#endif - if (pit->state & RS_PEER_S_FRIEND) - { - // Connected / Disconnected. (interal actions). - if (pit->actions & RS_PEER_CONNECTED) - { - updatePeerConnect(pit->id); - } - else if (pit->actions & RS_PEER_DISCONNECTED) - { - updatePeerDisconnect(pit->id); - } - - // Added / Removed. (pass on notifications). - if (pit->actions & RS_PEER_NEW) - { - updatePeerNew(pit->id); - } - } - else - { - if (pit->actions & RS_PEER_MOVED) - { - updatePeerRemoved(pit->id); - } - } - } - return; -} - -// Update Peer status. -void p3ServiceControl::updatePeerConnect(const RsPeerId &peerId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updatePeerConnect(): " << peerId.toStdString(); - std::cerr << std::endl; -#else - (void)peerId; -#endif - return; -} - -void p3ServiceControl::updatePeerDisconnect(const RsPeerId &peerId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updatePeerDisconnect(): " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - removePeer(peerId); - return; -} - - -// Update Peer status. -void p3ServiceControl::updatePeerNew(const RsPeerId &peerId) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updatePeerNew(): " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - pqiServicePeer peer; - peer.id = peerId; - peer.actions = RS_SERVICE_PEER_NEW; - mFriendNotifications.push_back(peer); - - return; -} - -void p3ServiceControl::updatePeerRemoved(const RsPeerId &peerId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updatePeerRemoved(): " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - removePeer(peerId); - - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - pqiServicePeer peer; - peer.id = peerId; - peer.actions = RS_SERVICE_PEER_REMOVED; - mFriendNotifications.push_back(peer); - - return; -} - -/****************************************************************************/ -/****************************************************************************/ - - -void p3ServiceControl::notifyAboutFriends() -{ - std::list friendNotifications; - { - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - if (mFriendNotifications.empty()) - { - return; - } -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyAboutFriends(): Something has changed!"; - std::cerr << std::endl; -#endif - - mFriendNotifications.swap(friendNotifications); - } - - { - RsStackMutex stack(mMonitorMtx); /***** LOCK STACK MUTEX ****/ - - std::multimap::const_iterator sit; - for(sit = mMonitors.begin(); sit != mMonitors.end(); ++sit) - { - sit->second->statusChange(friendNotifications); - } - } -} - - -void p3ServiceControl::notifyServices() -{ - std::map notifications; - { - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - if (mNotifications.empty()) - { - return; - } - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyServices()"; - std::cerr << std::endl; -#endif - - mNotifications.swap(notifications); - } - - { - RsStackMutex stack(mMonitorMtx); /***** LOCK STACK MUTEX ****/ - - std::map::const_iterator it; - std::multimap::const_iterator sit, eit; - for(it = notifications.begin(); it != notifications.end(); ++it) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyServices(): Notifications for Service: " << it->first; - std::cerr << std::endl; -#endif - - sit = mMonitors.lower_bound(it->first); - eit = mMonitors.upper_bound(it->first); - if (sit == eit) - { - /* nothing to notify - skip */ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyServices(): Noone Monitoring ... skipping"; - std::cerr << std::endl; -#endif - - continue; - } - - std::list peers; - std::set::const_iterator pit; - for(pit = it->second.mAdded.begin(); - pit != it->second.mAdded.end(); ++pit) - { - pqiServicePeer peer; - peer.id = *pit; - peer.actions = RS_SERVICE_PEER_CONNECTED; - - peers.push_back(peer); - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyServices(): Peer: " << *pit << " CONNECTED"; - std::cerr << std::endl; -#endif - } - - for(pit = it->second.mRemoved.begin(); - pit != it->second.mRemoved.end(); ++pit) - { - pqiServicePeer peer; - peer.id = *pit; - peer.actions = RS_SERVICE_PEER_DISCONNECTED; - - peers.push_back(peer); - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyServices(): Peer: " << *pit << " DISCONNECTED"; - std::cerr << std::endl; -#endif - } - - for(; sit != eit; ++sit) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyServices(): Sending to Monitoring Service"; - std::cerr << std::endl; -#endif - - sit->second->statusChange(peers); - } - } - } -} - - -/****************************************************************************/ -/****************************************************************************/ - - -RsServicePermissions::RsServicePermissions() -:mServiceId(0), mServiceName(), mDefaultAllowed(false) -{ - return; -} - -bool RsServicePermissions::peerHasPermission(const RsPeerId &peerId) const -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "RsServicePermissions::peerHasPermission()"; - std::cerr << std::endl; -#endif - - std::set::const_iterator it; - if (mDefaultAllowed) - { - it = mPeersDenied.find(peerId); - return (it == mPeersDenied.end()); - } - else - { - it = mPeersAllowed.find(peerId); - return (it != mPeersAllowed.end()); - } -} - -void RsServicePermissions::setPermission(const RsPeerId& peerId) -{ - std::set::const_iterator it; - if (mDefaultAllowed) - { - it = mPeersDenied.find(peerId); - mPeersDenied.erase(it) ; - } - else - mPeersAllowed.insert(peerId); -} -void RsServicePermissions::resetPermission(const RsPeerId& peerId) -{ - std::set::const_iterator it; - if (!mDefaultAllowed) - { - it = mPeersAllowed.find(peerId); - mPeersAllowed.erase(it) ; - } - else - mPeersDenied.insert(peerId); -} - -RsServiceInfo::RsServiceInfo( - const uint16_t service_type, - const std::string& service_name, - const uint16_t version_major, - const uint16_t version_minor, - const uint16_t min_version_major, - const uint16_t min_version_minor) - :mServiceName(service_name), - mServiceType(RsServiceInfoUIn16ToFullServiceId(service_type)), - mVersionMajor(version_major), - mVersionMinor(version_minor), - mMinVersionMajor(min_version_major), - mMinVersionMinor(min_version_minor) -{ - return; -} - -unsigned int RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(uint16_t serviceType) -{ - return (((uint32_t) RS_PKT_VERSION_SERVICE) << 24) + (((uint32_t) serviceType) << 8); -} - - -RsServiceInfo::RsServiceInfo() - :mServiceName("unknown"), - mServiceType(0), - mVersionMajor(0), - mVersionMinor(0), - mMinVersionMajor(0), - mMinVersionMinor(0) -{ - return; -} - -std::ostream &operator<<(std::ostream &out, const ServicePeerFilter &filter) -{ - out << "ServicePeerFilter DenyAll: " << filter.mDenyAll; - out << " AllowAll: " << filter.mAllowAll; - out << " Matched Services: "; - std::set::const_iterator it; - for(it = filter.mAllowedServices.begin(); it != filter.mAllowedServices.end(); ++it) - { - out << *it << " "; - } - out << std::endl; - return out; -} - - diff --git a/libretroshare/src/pqi/p3servicecontrol.h b/libretroshare/src/pqi/p3servicecontrol.h deleted file mode 100644 index fa4e4f37e..000000000 --- a/libretroshare/src/pqi/p3servicecontrol.h +++ /dev/null @@ -1,205 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3servicecontrol.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014-2014 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef P3_SERVICE_CONTROL_HEADER -#define P3_SERVICE_CONTROL_HEADER - -#include -#include - -#include "retroshare/rsservicecontrol.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/pqimonitor.h" -#include "pqi/pqiservicemonitor.h" -#include "pqi/p3linkmgr.h" - -class p3ServiceServer ; - -class ServiceNotifications -{ - public: - std::set mAdded; - std::set mRemoved; -}; - -class ServicePeerFilter -{ - public: - ServicePeerFilter() - :mDenyAll(true), mAllowAll(false) {} - - bool mDenyAll; - bool mAllowAll; - std::set mAllowedServices; -}; - -std::ostream &operator<<(std::ostream &out, const ServicePeerFilter &filter); - -class ServiceControlSerialiser ; - -class p3ServiceControl: public RsServiceControl, public pqiMonitor, public p3Config -{ -public: - - /** - */ - explicit p3ServiceControl(p3LinkMgr *linkMgr); - - /** - * checks and update all added configurations - * @see rsserver - */ - void tick(); - - /** - * provided so that services don't need linkMgr, and can get all info - * from ServiceControl. - * @see rsserver - */ - -virtual const RsPeerId& getOwnId(); - - /** - * External Interface (RsServiceControl). - */ - -virtual bool getOwnServices(RsPeerServiceInfo &info); -virtual std::string getServiceName(uint32_t service_id) ; - - // This is what is passed to peers, can be displayed by GUI too. -virtual bool getServicesAllowed(const RsPeerId &peerId, RsPeerServiceInfo &info); - - // Information provided by peer. -virtual bool getServicesProvided(const RsPeerId &peerId, RsPeerServiceInfo &info); - - // Main Permission Interface. -virtual bool getServicePermissions(uint32_t serviceId, RsServicePermissions &permissions); -virtual bool updateServicePermissions(uint32_t serviceId, const RsServicePermissions &permissions); - - // Get List of Peers using this Service. -virtual void getPeersConnected(uint32_t serviceId, std::set &peerSet); -virtual bool isPeerConnected(uint32_t serviceId, const RsPeerId &peerId); - - // Gets the list of items used by that service -virtual bool getServiceItemNames(uint32_t serviceId,std::map& names) ; - - /** - * Registration for all Services. - */ - -virtual bool registerService(const RsServiceInfo &info, bool defaultOn); -virtual bool deregisterService(uint32_t serviceId); - -virtual bool registerServiceMonitor(pqiServiceMonitor *monitor, uint32_t serviceId); -virtual bool deregisterServiceMonitor(pqiServiceMonitor *monitor); - - /** - * - */ - - - // Filter for services. -virtual bool checkFilter(uint32_t serviceId, const RsPeerId &peerId); - - /** - * Interface for ServiceInfo service. - */ - - // ServicesAllowed have changed for these peers. -virtual void getServiceChanges(std::set &updateSet); - - // Input from peers. -virtual bool updateServicesProvided(const RsPeerId &peerId, const RsPeerServiceInfo &info); - - // pqiMonitor. -virtual void statusChange(const std::list &plist); - - virtual void setServiceServer(p3ServiceServer *p) { mServiceServer = p ; } - -protected: - // configuration. -virtual bool saveList(bool &cleanup, std::list&); -virtual bool loadList(std::list& load); -virtual RsSerialiser *setupSerialiser() ; - -private: - -void notifyServices(); -void notifyAboutFriends(); - -void updatePeerConnect(const RsPeerId &peerId); -void updatePeerDisconnect(const RsPeerId &peerId); -void updatePeerNew(const RsPeerId &peerId); -void updatePeerRemoved(const RsPeerId &peerId); - -void removePeer(const RsPeerId &peerId); - - -bool updateAllFilters(); -bool updateAllFilters_locked(); -bool updateFilterByPeer(const RsPeerId &peerId); -bool updateFilterByPeer_locked(const RsPeerId &peerId); - - - void recordFilterChanges_locked(const RsPeerId &peerId, - ServicePeerFilter &originalFilter, ServicePeerFilter &updatedFilter); - - // Called from recordFilterChanges. - void filterChangeAdded_locked(const RsPeerId &peerId, uint32_t serviceId); - void filterChangeRemoved_locked(const RsPeerId &peerId, uint32_t serviceId); - -bool createDefaultPermissions_locked(uint32_t serviceId, const std::string& serviceName, bool defaultOn); -bool peerHasPermissionForService_locked(const RsPeerId &peerId, uint32_t serviceId); - - p3LinkMgr *mLinkMgr; - const RsPeerId mOwnPeerId; // const from constructor - - RsMutex mCtrlMtx; /* below is protected */ - - std::set mUpdatedSet; - - // From registration / deregistration. - std::map mOwnServices; - // From peers. - std::map mServicesProvided; - // derived from all the others. - std::map mPeerFilterMap; - - std::map mNotifications; - std::list mFriendNotifications; - - // Map of Connected Peers per Service. - std::map > mServicePeerMap; - - // Separate mutex here - must not hold both at the same time! - RsMutex mMonitorMtx; /* below is protected */ - std::multimap mMonitors; - - ServiceControlSerialiser *mSerialiser ; - - // Below here is saved in Configuration. - std::map mServicePermissionMap; - - p3ServiceServer *mServiceServer ; -}; - - -#endif // P3_SERVICE_CONTROL_HEADER diff --git a/libretroshare/src/pqi/p3upnpmgr.h b/libretroshare/src/pqi/p3upnpmgr.h deleted file mode 100644 index 6f58aa8ae..000000000 --- a/libretroshare/src/pqi/p3upnpmgr.h +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3upnpmgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2007 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_P3_UPNP_MANAGER_H -#define MRK_P3_UPNP_MANAGER_H - -/* platform independent networking... */ -#include "util/rsthreads.h" -#include "pqi/pqinetwork.h" - -class p3UpnpMgr: public pqiNetAssistFirewall -{ - public: - -virtual ~p3UpnpMgr() { return; } - - /* External Interface */ -virtual void enable(bool on) = 0; /* launches thread to start it up */ -virtual void shutdown() = 0; /* blocking shutdown call */ -virtual void restart() = 0; /* must be called if ports change */ - -virtual bool getEnabled() = 0; -virtual bool getActive() = 0; - - /* the address that the listening port is on */ -virtual void setInternalPort(unsigned short iport_in) = 0; -virtual void setExternalPort(unsigned short eport_in) = 0; - - /* as determined by uPnP */ -virtual bool getInternalAddress(struct sockaddr_storage &addr) = 0; -virtual bool getExternalAddress(struct sockaddr_storage &addr) = 0; - -}; - -#endif /* MRK_P3_UPNP_MANAGER_H */ - diff --git a/libretroshare/src/pqi/pqi.h b/libretroshare/src/pqi/pqi.h deleted file mode 100644 index 1bf581ff1..000000000 --- a/libretroshare/src/pqi/pqi.h +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqi.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef PQI_TOP_HEADER -#define PQI_TOP_HEADER - -#include "rsitems/rsitem.h" - -class P3Interface -{ -public: - P3Interface() {return; } -virtual ~P3Interface() {return; } - -virtual int tick() { return 1; } -virtual int status() { return 1; } - -virtual int SendRsRawItem(RsRawItem *) = 0; -}; - - -/** - * @brief Interface to allow outgoing messages to be sent directly through to - * the pqiperson, rather than being queued - */ -class pqiPublisher -{ - public: -virtual ~pqiPublisher() { return; } -virtual bool sendItem(RsRawItem *item) = 0; - -}; - - -#endif // PQI_TOP_HEADER diff --git a/libretroshare/src/pqi/pqi_base.h b/libretroshare/src/pqi/pqi_base.h deleted file mode 100644 index 51980b501..000000000 --- a/libretroshare/src/pqi/pqi_base.h +++ /dev/null @@ -1,417 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqi_base.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef PQI_BASE_ITEM_HEADER -#define PQI_BASE_ITEM_HEADER - -#include -#include -#include -#include -#include -#include - -#include "pqi/pqinetwork.h" - -struct RSTrafficClue; - -/*** Base DataTypes: ****/ -#include "serialiser/rsserial.h" -#include "retroshare/rstypes.h" - -int getPQIsearchId(); -int fixme(char *str, int n); - -struct RsPeerCryptoParams; - -//! controlling data rates -/*! - * For controlling data rates. - * #define DEBUG_RATECAP 1 - */ - -class RsBwRates -{ - public: - RsBwRates() - :mRateIn(0), mRateOut(0), mMaxRateIn(0), mMaxRateOut(0), mQueueIn(0), mQueueOut(0) {return;} - float mRateIn; - float mRateOut; - float mMaxRateIn; - float mMaxRateOut; - int mQueueIn; - int mQueueOut; -}; - - -class RateInterface -{ - -public: - - RateInterface() - :bw_in(0), bw_out(0), bwMax_in(0), bwMax_out(0), - bwCapEnabled(false), bwCap_in(0), bwCap_out(0) { return; } - - virtual ~RateInterface() { return; } - - virtual void getRates(RsBwRates &rates) - { - rates.mRateIn = bw_in; - rates.mRateOut = bw_out; - rates.mMaxRateIn = bwMax_in; - rates.mMaxRateOut = bwMax_out; - return; - } - - virtual int gatherStatistics(std::list& /* outqueue_lst */,std::list& /* inqueue_lst */) { return 0;} - - virtual int getQueueSize(bool /* in */) { return 0;} - virtual float getRate(bool in) - { - if (in) - return bw_in; - return bw_out; - } - - virtual float getMaxRate(bool in) - { - if (in) - return bwMax_in; - return bwMax_out; - } - - virtual void setMaxRate(bool in, float val) - { - if (in) - { - bwMax_in = val; - if (bwCapEnabled) - { - if (bwMax_in > bwCap_in) - { - bwMax_in = bwCap_in; - } - } - } - else - { - bwMax_out = val; - if (bwCapEnabled) - { - if (bwMax_out > bwCap_out) - { - bwMax_out = bwCap_out; - } - } - } - - return; - } - - - virtual void setRateCap(float val_in, float val_out) - { - if ((val_in == 0) && (val_out == 0)) - { -#ifdef DEBUG_RATECAP - std::cerr << "RateInterface::setRateCap() Now disabled" << std::endl; -#endif - bwCapEnabled = false; - } - else - { -#ifdef DEBUG_RATECAP - std::cerr << "RateInterface::setRateCap() Enabled "; - std::cerr << "in: " << bwCap_in << " out: " << bwCap_out << std::endl; -#endif - bwCapEnabled = true; - bwCap_in = val_in; - bwCap_out = val_out; - } - return; - } - -protected: - - virtual void setRate(bool in, float val) - { - if (in) - bw_in = val; - else - bw_out = val; - return; - } - -private: - float bw_in, bw_out, bwMax_in, bwMax_out; - bool bwCapEnabled; - float bwCap_in, bwCap_out; - -}; - - -class NetInterface; - -//! The basic exchange interface. -/*! - * - * This inherits the RateInterface, as Bandwidth control - * is critical to a networked application. - **/ -class PQInterface: public RateInterface -{ -public: - explicit PQInterface(const RsPeerId &id) : - traf_in(0), traf_out(0), peerId(id) {} - virtual ~PQInterface() {} - - /*! - * allows user to send RsItems to a particular facility (file, network) - */ - virtual int SendItem(RsItem *) = 0; - - // this function is overloaded in classes that need the serilized size to be returned. - virtual int SendItem(RsItem *item,uint32_t& size) - { - size = 0 ; - - static bool already=false ; - if(!already) - { - std::cerr << "Warning: PQInterface::SendItem(RsItem*,uint32_t&) calledbut not overloaded! Serialized size will not be returned." << std::endl; - already=true ; - } - return SendItem(item) ; - } - - virtual bool getCryptoParams(RsPeerCryptoParams&) { return false ;} - - /*! - * Retrieve RsItem from a facility - */ - virtual RsItem *GetItem() = 0; - virtual bool RecvItem(RsItem * /*item*/ ) { return false; } /* alternative for for GetItem(), when we want to push */ - - /** - * also there are tick + person id functions. - */ - virtual int tick() { return 0; } - virtual int status() { return 0; } - virtual const RsPeerId& PeerId() { return peerId; } - - // the callback from NetInterface Connection Events. - virtual int notifyEvent(NetInterface * /*ni*/, int /*event*/, - const sockaddr_storage & /*remote_peer_address*/) - { return 0; } - - virtual uint64_t getTraffic(bool in) - { - uint64_t ret = 0; - if (in) - { - ret = traf_in; - traf_in = 0; - return ret; - } - ret = traf_out; - traf_out = 0; - return ret; - } - uint64_t traf_in; - uint64_t traf_out; - - private: - - RsPeerId peerId; -}; - - - -/**** Consts for pqiperson -> placed here for NetBinDummy usage() */ - -const uint32_t PQI_CONNECT_TCP = 0x0001; -const uint32_t PQI_CONNECT_UDP = 0x0002; -const uint32_t PQI_CONNECT_HIDDEN_TOR_TCP = 0x0004; -const uint32_t PQI_CONNECT_HIDDEN_I2P_TCP = 0x0008; - - -#define BIN_FLAGS_NO_CLOSE 0x0001 -#define BIN_FLAGS_READABLE 0x0002 -#define BIN_FLAGS_WRITEABLE 0x0004 -#define BIN_FLAGS_NO_DELETE 0x0008 -#define BIN_FLAGS_HASH_DATA 0x0010 - -/*! - * This defines the binary interface used by Network/loopback/file - * interfaces - * e.g. sending binary data to file or to memory or even through a socket - */ -class BinInterface -{ -public: - BinInterface() {} - virtual ~BinInterface() {} - - /** - * To be called loop, for updating state - */ - virtual int tick() = 0; - - /** - * Sends data to a prescribed location (implementation dependent) - *@param data what will be sent - *@param len the size of data pointed to in memory - */ - virtual int senddata(void *data, int len) = 0; - - /** - * reads data from a prescribed location (implementation dependent) - *@param data what will be sent - *@param len the size of data pointed to in memory - */ - virtual int readdata(void *data, int len) = 0; - - /** - * Is more particular the case of the sending data through a socket (internet) - * moretoread and candsend, take a microsec timeout argument. - * - */ - virtual int netstatus() = 0; - virtual int isactive() = 0; - virtual bool moretoread(uint32_t usec) = 0; - virtual bool cansend(uint32_t usec) = 0; - - /** - * method for streamer to shutdown bininterface - **/ - virtual int close() = 0; - - /** - * If hashing data - **/ - virtual RsFileHash gethash() = 0; - - /** - * Number of bytes read/sent - */ - virtual uint64_t bytecount() { return 0; } - - /** - * used by pqistreamer to limit transfers - **/ - virtual bool bandwidthLimited() { return true; } -}; - - - -static const int NET_CONNECT_RECEIVED = 1; -static const int NET_CONNECT_SUCCESS = 2; -static const int NET_CONNECT_UNREACHABLE = 3; -static const int NET_CONNECT_FIREWALLED = 4; -static const int NET_CONNECT_FAILED = 5; - -static const uint32_t NET_PARAM_CONNECT_DELAY = 1; -static const uint32_t NET_PARAM_CONNECT_PERIOD = 2; -static const uint32_t NET_PARAM_CONNECT_TIMEOUT = 3; -static const uint32_t NET_PARAM_CONNECT_FLAGS = 4; -static const uint32_t NET_PARAM_CONNECT_BANDWIDTH = 5; - -static const uint32_t NET_PARAM_CONNECT_PROXY = 6; -static const uint32_t NET_PARAM_CONNECT_SOURCE = 7; - -static const uint32_t NET_PARAM_CONNECT_DOMAIN_ADDRESS = 8; -static const uint32_t NET_PARAM_CONNECT_REMOTE_PORT = 9; - - -/*! - * ******************** Network INTERFACE *************************** - * This defines the Network interface used by sockets/SSL/XPGP - * interfaces - * - * NetInterface: very pure interface, so no tick.... - * - * It is passed a pointer to a PQInterface *parent, - * this is used to notify the system of Connect/Disconnect Events. - * - * Below are the Events for callback. - **/ -class NetInterface -{ -public: - - /** - * @param p_in used to notify system of connect/disconnect events - */ - NetInterface(PQInterface *p_in, const RsPeerId& id) : p(p_in), peerId(id) {} - - virtual ~NetInterface() {} - - /* TODO - * The data entrypoint is connect(const struct sockaddr_storage &raddr) - * To generalize NetInterface we should have a more general type for raddr - * As an example a string containing an url or encoded like a domain name - */ - virtual int connect(const struct sockaddr_storage &raddr) = 0; - - virtual int listen() = 0; - virtual int stoplistening() = 0; - virtual int disconnect() = 0; - virtual int reset() = 0; - virtual const RsPeerId& PeerId() { return peerId; } - virtual int getConnectAddress(struct sockaddr_storage &raddr) = 0; - - virtual bool connect_parameter(uint32_t type, uint32_t value) = 0; - virtual bool connect_parameter(uint32_t /* type */ , const std::string & /* value */ ) { return false; } // not generally used. - virtual bool connect_additional_address(uint32_t /*type*/, const struct sockaddr_storage & /*addr*/) { return false; } // only needed by udp. - -protected: - PQInterface *parent() { return p; } - -private: - PQInterface *p; - RsPeerId peerId; -}; - -//! network binary interface (abstract) -/** - * Should be used for networking and connecting to addresses - * - * @see pqissl - * @see NetInterface - * @see BinInterface - **/ -class NetBinInterface: public NetInterface, public BinInterface -{ -public: - NetBinInterface(PQInterface *parent, const RsPeerId& id) : - NetInterface(parent, id) {} - virtual ~NetBinInterface() {} -}; - -#define CHAN_SIGN_SIZE 16 -#define CERTSIGNLEN 16 /* actual byte length of signature */ -#define PQI_PEERID_LENGTH 32 /* When expanded into a string */ - - - -#endif // PQI_BASE_ITEM_HEADER - diff --git a/libretroshare/src/pqi/pqiassist.h b/libretroshare/src/pqi/pqiassist.h deleted file mode 100644 index e7b508a3e..000000000 --- a/libretroshare/src/pqi/pqiassist.h +++ /dev/null @@ -1,172 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiassist.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2007 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include "retroshare/rstypes.h" -#include "pqi/pqinetwork.h" -#include "pqi/pqimonitor.h" - -/** - * @file - * This header file provides interfaces for assisting the connections to - * friends. - */ - -class pqiNetAssist -{ -public: - - /* External Interface */ -virtual void enable(bool on) = 0; -virtual void shutdown() = 0; /* blocking call */ -virtual void restart() = 0; - -virtual bool getEnabled() = 0; -virtual bool getActive() = 0; - -virtual int tick() { return 0; } /* for internal accounting */ - - virtual ~pqiNetAssist(); -}; - -struct PortForwardParams -{ - uint32_t fwdId; - uint32_t status; - uint32_t typeFlags; - sockaddr_storage intAddr; - sockaddr_storage extaddr; -}; - -/** - * Provides interfaces to functionality like upnp and apple's equivalent. - */ -class pqiNetAssistFirewall: public pqiNetAssist -{ -public: - /* the address that the listening port is on */ -virtual void setInternalPort(unsigned short iport_in) = 0; -virtual void setExternalPort(unsigned short eport_in) = 0; - - /* as determined by uPnP */ -virtual bool getInternalAddress(struct sockaddr_storage &addr) = 0; -virtual bool getExternalAddress(struct sockaddr_storage &addr) = 0; - - - /* New Port Forward interface to support as many ports as necessary */ -virtual bool requestPortForward(const PortForwardParams ¶ms) = 0; -virtual bool statusPortForward(const uint32_t fwdId, PortForwardParams ¶ms) = 0; - - -}; - - -#define PNASS_TYPE_BADPEER 0x0001 -#define PNASS_REASON_UNKNOWN 0x0001 - -class pqiNetAssistPeerShare -{ -public: - /** share Addresses for various reasons (bad peers, etc) */ - virtual void updatePeer( - const RsPeerId& id, const struct sockaddr_storage &addr, - int type, int reason, int age ) = 0; - - virtual ~pqiNetAssistPeerShare(); -}; - - -#ifdef RS_USE_DHT_STUNNER -/* this is for the Stunners - * - * - */ - -class pqiAddrAssist -{ - public: - - pqiAddrAssist() { return; } -virtual ~pqiAddrAssist() { return; } - -virtual bool getExternalAddr(struct sockaddr_storage &remote, uint8_t &stable) = 0; -virtual void setRefreshPeriod(int32_t period) = 0; -virtual int tick() = 0; /* for internal accounting */ - -}; -#endif // RS_USE_DHT_STUNNER - -#define NETASSIST_KNOWN_PEER_OFFLINE 0x0001 -#define NETASSIST_KNOWN_PEER_ONLINE 0x0002 - -#define NETASSIST_KNOWN_PEER_WHITELIST 0x0100 -#define NETASSIST_KNOWN_PEER_FRIEND 0x0200 -#define NETASSIST_KNOWN_PEER_FOF 0x0400 -#define NETASSIST_KNOWN_PEER_RELAY 0x0800 -#define NETASSIST_KNOWN_PEER_SELF 0x1000 - -#define NETASSIST_KNOWN_PEER_TYPE_MASK 0xff00 - -/** - * Provides interfaces to other networks like DHT that can provide information. - * These classes would be expected to use the pqiMonitor callback system to - * notify the connectionMgr. - */ -class pqiNetAssistConnect: public pqiNetAssist -{ -public: - pqiNetAssistConnect(const RsPeerId& id, pqiConnectCb *cb) : - mPeerId(id), mConnCb(cb) {} - - /********** External DHT Interface ************************ - * These Functions are the external interface - * for the DHT, and must be non-blocking and return quickly - */ - - /* add / remove peers */ -virtual bool findPeer(const RsPeerId& id) = 0; -virtual bool dropPeer(const RsPeerId& id) = 0; - - /* add non-active peers (can still toggle active/non-active via above) */ -virtual int addBadPeer(const struct sockaddr_storage &addr, uint32_t reason, uint32_t flags, uint32_t age) = 0; -virtual int addKnownPeer(const RsPeerId &pid, const struct sockaddr_storage &addr, uint32_t flags) = 0; - -virtual void ConnectionFeedback(const RsPeerId& pid, int mode) = 0; - - /* extract current peer status */ -virtual bool getPeerStatus(const RsPeerId& id, - struct sockaddr_storage &laddr, struct sockaddr_storage &raddr, - uint32_t &type, uint32_t &mode) = 0; // DEPRECIATE. - -virtual bool setAttachMode(bool on) = 0; // FIXUP. - - /***** Stats for Network / DHT *****/ -virtual bool getNetworkStats(uint32_t &netsize, uint32_t &localnetsize) = 0; // DEPRECIATE. - - ~pqiNetAssistConnect() override; - -protected: - RsPeerId mPeerId; - pqiConnectCb *mConnCb; -}; diff --git a/libretroshare/src/pqi/pqibin.cc b/libretroshare/src/pqi/pqibin.cc deleted file mode 100644 index 75e0b4b39..000000000 --- a/libretroshare/src/pqi/pqibin.cc +++ /dev/null @@ -1,746 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqibin.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/pqibin.h" -#include "pqi/authssl.h" -#include "util/rsnet.h" -#include "util/rsdir.h" -#include "util/rsmemory.h" - -// #define DEBUG_PQIBIN - -BinFileInterface::BinFileInterface(const char *fname, int flags) - :bin_flags(flags), buf(NULL), hash(NULL), bcount(0) -{ - /* if read + write - open r+ */ - if ((bin_flags & BIN_FLAGS_READABLE) && - (bin_flags & BIN_FLAGS_WRITEABLE)) - { - buf = RsDirUtil::rs_fopen(fname, "rb+"); - /* if the file don't exist */ - if (!buf) - { - buf = RsDirUtil::rs_fopen(fname, "wb+"); - } - - } - else if (bin_flags & BIN_FLAGS_READABLE) - { - buf = RsDirUtil::rs_fopen(fname, "rb"); - } - else if (bin_flags & BIN_FLAGS_WRITEABLE) - { - // This is enough to remove old file in Linux... - // but not in windows.... (what to do) - buf = RsDirUtil::rs_fopen(fname, "wb"); - fflush(buf); /* this might help windows! */ - } - else - { - /* not read or write! */ - } - - if (buf) - { -#ifdef DEBUG_PQIBIN - std::cerr << "BinFileInterface: " << (void*)this << ": openned file " << fname << std::endl; -#endif - /* no problem */ - - /* go to the end */ - fseek(buf, 0L, SEEK_END); - /* get size */ - size = ftell(buf); - /* back to the start */ - fseek(buf, 0L, SEEK_SET); - } - else - { - size = 0; - } - - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash = new pqihash(); - } -} - - -BinFileInterface::~BinFileInterface() -{ - if (buf) - { - fclose(buf); -#ifdef DEBUG_PQIBIN - std::cerr << "BinFileInterface: " << (void*)this << ": closed file " << std::endl; -#endif - } - - if (hash) - { - delete hash; - } -} - -int BinFileInterface::close() -{ - if (buf) - { - fclose(buf); -#ifdef DISTRIB_DEBUG - std::cerr << "BinFileInterface: " << (void*)this << ": closed file " << std::endl; -#endif - buf = NULL; - } - return 1; -} - -int BinFileInterface::senddata(void *data, int len) -{ - if (!buf) - return -1; - - if (1 != fwrite(data, len, 1, buf)) - { - return -1; - } - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash->addData(data, len); - bcount += len; - } - return len; -} - -int BinFileInterface::readdata(void *data, int len) -{ - if (!buf) - return -1; - - if (1 != fread(data, len, 1, buf)) - { - return -1; - } - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash->addData(data, len); - bcount += len; - } - return len; -} - -RsFileHash BinFileInterface::gethash() -{ - RsFileHash hashstr; - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash->Complete(hashstr); - } - return hashstr; -} - -uint64_t BinFileInterface::bytecount() -{ - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - return bcount; - } - return 0; -} - -uint64_t BinFileInterface::getFileSize() -{ - return size; -} - - - -BinEncryptedFileInterface::BinEncryptedFileInterface(const char* fname, int flags) - : BinFileInterface(fname, flags), data(NULL), haveData(false), sizeData(0), cpyCount(0) -{ -} - -BinEncryptedFileInterface::~BinEncryptedFileInterface() -{ - if((sizeData > 0) && data != NULL) - { - free(data); - } - -} - -int BinEncryptedFileInterface::senddata(void* data, int len) -{ - - void* encrytedData = NULL; - int encDataLen = 0; - - // encrypt using own ssl public key - if(len > 0) - AuthSSL::getAuthSSL()->encrypt((void*&)encrytedData, encDataLen, data, len, AuthSSL::getAuthSSL()->OwnId()); - else - return -1; - - - if((encDataLen > 0) && (encrytedData != NULL)) - { - BinFileInterface::senddata((unsigned char *)encrytedData, encDataLen); - free(encrytedData); - } - else - { - return -1; - } - - return len; -} - - -int BinEncryptedFileInterface::readdata(void* data, int len) -{ - // to respect the inherited behavior of BinInterface - // the whole file is read and decryped and store to be read by subsequent calls - char* encryptedData = NULL; - int encrypDataLen = 0; - - - if(!haveData) // read whole data for first call, or first call after close() - { - - uint64_t encrypDataLen64 = BinFileInterface::getFileSize(); - - if(encrypDataLen64 > uint64_t(~(int)0)) - { - std::cerr << __PRETTY_FUNCTION__ << ": cannot decrypt files of size > " << ~(int)0 << std::endl; - return -1 ; - } - encrypDataLen = (int)encrypDataLen64 ; - encryptedData = new char[encrypDataLen]; - - // make sure assign was successful - if(encryptedData == NULL) - return -1; - - - if(-1 == BinFileInterface::readdata(encryptedData, encrypDataLen)) - { - delete[] encryptedData; - return -1; - } - - if((encrypDataLen > 0) && (encryptedData != NULL)) - { - int sizeDataInt = 0 ; - - if(!AuthSSL::getAuthSSL()->decrypt((void*&)(this->data), sizeDataInt, encryptedData, encrypDataLen)) - { - delete[] encryptedData; - return -1; - } - - sizeData = sizeDataInt ; - haveData = true; - delete[] encryptedData; - } - - - if((uint64_t)len <= sizeData) - { - memcpy(data, this->data, len); - cpyCount += len; - } - else - { - std::cerr << "BinEncryptedFileInterface::readData(): Error, Asking for more data than present" << std::endl; - return -1; - } - } - else - { - - if((cpyCount + len) <= (uint64_t)sizeData) - { - memcpy(data, (void *) ((this->data) + cpyCount), len); - cpyCount += len; - } - else - { - std::cerr << "BinEncryptedFileInterface::readData(): Error, Asking for more data than present" << std::endl; - return -1; - } - } - - return len; -} - -int BinEncryptedFileInterface::close() -{ - if(data != NULL) - { - free(data); - sizeData = 0; - haveData = false; - cpyCount = 0; - } - - return BinFileInterface::close(); -} - -uint64_t BinEncryptedFileInterface::bytecount() -{ - return cpyCount; -} - -bool BinEncryptedFileInterface::moretoread(uint32_t /* usec */) -{ - if(haveData) - return (cpyCount < (uint64_t)sizeData); - else - return cpyCount < (uint64_t)getFileSize(); -} - -BinMemInterface::BinMemInterface(int defsize, int flags) - :bin_flags(flags), buf(NULL), size(defsize), - recvsize(0), readloc(0), hash(NULL), bcount(0) - { - buf = rs_malloc(defsize); - - if(buf == NULL) - { - close() ; - return ; - } - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash = new pqihash(); - } - } - - -BinMemInterface::BinMemInterface(const void *data, const int defsize, int flags) - :bin_flags(flags), buf(NULL), size(defsize), - recvsize(0), readloc(0), hash(NULL), bcount(0) - { - buf = rs_malloc(defsize); - - if(buf == NULL) - { - close() ; - return ; - } - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash = new pqihash(); - } - - /* just remove the const - * *BAD* but senddata don't change it anyway - */ - senddata((void *) data, defsize); - } - -BinMemInterface::~BinMemInterface() -{ - if (buf) - free(buf); - - if (hash) - delete hash; - return; -} - -int BinMemInterface::close() -{ - if (buf) - { - free(buf); - buf = NULL; - } - size = 0; - recvsize = 0; - readloc = 0; - return 1; -} - - /* some fns to mess with the memory */ -int BinMemInterface::fseek(int loc) - { - if (loc <= recvsize) - { - readloc = loc; - return 1; - } - return 0; - } - - -int BinMemInterface::senddata(void *data, const int len) - { - if(recvsize + len > size) - { - /* resize? */ - return -1; - } - memcpy((char *) buf + recvsize, data, len); - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash->addData(data, len); - bcount += len; - } - recvsize += len; - return len; - } - - -int BinMemInterface::readdata(void *data, int len) - { - if(readloc + len > recvsize) - { - /* no more stuff? */ - return -1; - } - memcpy(data, (char *) buf + readloc, len); - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash->addData(data, len); - bcount += len; - } - readloc += len; - return len; - } - - - -RsFileHash BinMemInterface::gethash() - { - RsFileHash hashstr; - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash->Complete(hashstr); - } - return hashstr; - } - - -uint64_t BinMemInterface::bytecount() -{ - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - return bcount; - } - return 0; -} - -bool BinMemInterface::writetofile(const char *fname) -{ - FILE *fd = RsDirUtil::rs_fopen(fname, "wb"); - if (!fd) - { - return false; - } - - if (1 != fwrite(buf, recvsize, 1, fd)) - { - fclose(fd); - return false; - } - - fclose(fd); - - return true; -} - -bool BinMemInterface::readfromfile(const char *fname) -{ - FILE *fd = RsDirUtil::rs_fopen(fname, "rb"); - if (!fd) - { - return false; - } - - /* get size */ - ::fseek(fd, 0L, SEEK_END); - int fsize = ftell(fd); - - if (fsize > size) - { - /* not enough room */ - std::cerr << "BinMemInterface::readfromfile() not enough room"; - std::cerr << std::endl; - - fclose(fd); - return false; - } - - ::fseek(fd, 0L, SEEK_SET); - if (1 != fread(buf, fsize, 1, fd)) - { - /* not enough room */ - std::cerr << "BinMemInterface::readfromfile() failed fread"; - std::cerr << std::endl; - - fclose(fd); - return false; - } - - recvsize = fsize; - readloc = 0; - fclose(fd); - - return true; -} - - -/**************************************************************************/ - - -void printNetBinID(std::ostream &out, const RsPeerId& id, uint32_t t) -{ - out << "NetBinId(" << id << ","; - if (t == PQI_CONNECT_TCP) - { - out << "TCP)"; - } - else if (t & (PQI_CONNECT_HIDDEN_TOR_TCP | PQI_CONNECT_HIDDEN_I2P_TCP)) - { - out << "HTCP"; - } - else - { - out << "UDP)"; - } -} - - -/************************** NetBinDummy ****************************** - * A test framework, - * - */ - -#include "pqi/pqiperson.h" - -const uint32_t DEFAULT_DUMMY_DELTA = 5; - -NetBinDummy::NetBinDummy(PQInterface *parent, const RsPeerId& id, uint32_t t) - :NetBinInterface(parent, id), type(t), dummyConnected(false), toConnect(false), connectDelta(DEFAULT_DUMMY_DELTA) -{ - return; -} - - // Net Interface -int NetBinDummy::connect(const struct sockaddr_storage &raddr) -{ - std::cerr << "NetBinDummy::connect("; - std::cerr << sockaddr_storage_tostring(raddr); - std::cerr << ") "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - std::cerr << "NetBinDummy::dummyConnect = true!"; - std::cerr << std::endl; - - if (type == PQI_CONNECT_TCP) - { - std::cerr << "NetBinDummy:: Not connecting TCP"; - std::cerr << std::endl; - if (parent()) - { - //struct sockaddr_storage addr = raddr; - parent()->notifyEvent(this, CONNECT_FAILED, raddr); - } - } - else if (!dummyConnected) - { - toConnect = true; - connectTS = time(NULL) + connectDelta; - std::cerr << "NetBinDummy::toConnect = true, connect in: "; - std::cerr << connectDelta << " secs"; - std::cerr << std::endl; - } - else - { - std::cerr << "NetBinDummy:: Already Connected!"; - std::cerr << std::endl; - } - - return 1; -} - -int NetBinDummy::listen() -{ - std::cerr << "NetBinDummy::connect() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return 1; -} - -int NetBinDummy::stoplistening() -{ - std::cerr << "NetBinDummy::stoplistening() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return 1; -} - -int NetBinDummy::disconnect() -{ - std::cerr << "NetBinDummy::disconnect() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - std::cerr << "NetBinDummy::dummyConnect = false!"; - std::cerr << std::endl; - dummyConnected = false; - - if (parent()) - { - struct sockaddr_storage addr; - sockaddr_storage_clear(addr); - - parent()->notifyEvent(this, CONNECT_FAILED, addr); - } - - return 1; -} - -int NetBinDummy::reset() -{ - std::cerr << "NetBinDummy::reset() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - disconnect(); - - return 1; -} - - - // Bin Interface. -int NetBinDummy::tick() -{ - - if (toConnect) - { - if (connectTS < time(NULL)) - { - std::cerr << "NetBinDummy::tick() dummyConnected = true "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - dummyConnected = true; - toConnect = false; - if (parent()) - { - struct sockaddr_storage addr; - sockaddr_storage_clear(addr); - - parent()->notifyEvent(this, CONNECT_SUCCESS, addr); - } - } - else - { - std::cerr << "NetBinDummy::tick() toConnect "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - } - } - return 0; -} - -int NetBinDummy::senddata(void */*data*/, int len) -{ - std::cerr << "NetBinDummy::senddata() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - if (dummyConnected) - return len; - return 0; -} - -int NetBinDummy::readdata(void */*data*/, int /*len*/) -{ - std::cerr << "NetBinDummy::readdata() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return 0; -} - -int NetBinDummy::netstatus() -{ - std::cerr << "NetBinDummy::netstatus() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return 1; -} - -int NetBinDummy::isactive() -{ - std::cerr << "NetBinDummy::isactive() "; - printNetBinID(std::cerr, PeerId(), type); - if (dummyConnected) - std::cerr << " true "; - else - std::cerr << " false "; - std::cerr << std::endl; - - return dummyConnected; -} - -bool NetBinDummy::moretoread(uint32_t /* usec */) -{ - std::cerr << "NetBinDummy::moretoread() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return false; -} - -bool NetBinDummy::cansend(uint32_t /* usec */) -{ - std::cerr << "NetBinDummy::cansend() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return dummyConnected; -} - -int NetBinDummy::close() -{ - std::cerr << "NetBinDummy::close() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return 1; -} - -RsFileHash NetBinDummy::gethash() -{ - std::cerr << "NetBinDummy::gethash() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return RsFileHash(); -} - diff --git a/libretroshare/src/pqi/pqibin.h b/libretroshare/src/pqi/pqibin.h deleted file mode 100644 index 59a79622d..000000000 --- a/libretroshare/src/pqi/pqibin.h +++ /dev/null @@ -1,236 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqibin.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef PQI_BIN_INTERFACE_HEADER -#define PQI_BIN_INTERFACE_HEADER - - -#include "pqi/pqi_base.h" -#include "pqi/pqihash.h" -#include "util/rstime.h" - -#include - - -//! handles writing to binary files -/*! - * This allows for handling of binary file within Rs, In particular writing - * binary data to file declared in constructor - */ -class BinFileInterface: public BinInterface -{ -public: - BinFileInterface(const char *fname, int flags); -virtual ~BinFileInterface(); - -virtual int tick() { return 1; } - -virtual int senddata(void *data, int len); -virtual int readdata(void *data, int len); -virtual int netstatus() { return 1;} -virtual int isactive() { return (buf != NULL);} -virtual bool moretoread(uint32_t /* usec */ ) - { - if ((buf) && (bin_flags & BIN_FLAGS_READABLE)) - { - if ((size - ftell(buf)) > 0) - { - return true; - } - } - return false; - } - -virtual int close(); -virtual bool cansend(uint32_t /* usec */) - { - return (bin_flags & BIN_FLAGS_WRITEABLE); - } -virtual bool bandwidthLimited() { return false; } - -//! if HASHing is switched on -virtual RsFileHash gethash(); -virtual uint64_t bytecount(); - - virtual uint64_t getFileSize(); - -private: - int bin_flags; - FILE *buf; - uint64_t size; - pqihash *hash; - uint64_t bcount; -}; - -/*! - * use this for writing encrypted data to file using user's (ownid) ssl key - * hash for encrypted data is calculated, not the unencrypted data - */ -class BinEncryptedFileInterface : public BinFileInterface -{ -public: - - BinEncryptedFileInterface(const char *fname, int flags); - virtual ~BinEncryptedFileInterface(); - - /*! - * pls note if hashing is on, it is the hash of the encrypted data that is calculated - * also note, sif data is sent more than once, in a single instance of this object, then you will need to store the - * encrypted file size for each send externally as they are encrypted with different random keys. - * @param data data to be sent - * @param len length of data in bytes - * @return -1 if failed to write data, if not number bytes sent to file is returned - */ - int senddata(void *data, int len); - - /*! - * uses the hash of the encrypted data - * @param location to place data - * @param the length of data to be read - * @return -1 if failed to write data, if not number of bytes read is returned - */ - int readdata(void *data, int len); - - /*! - * this releases resources held by an instance - */ - int close(); - - uint64_t bytecount(); - bool moretoread(uint32_t usec); - -private: - - char* data; - bool haveData; - uint64_t sizeData; - uint64_t cpyCount; - -}; - -//! handles writing to reading/writing to memory -/*! - * This provide a memory interface for storing/retrieving information in memory - * to be read/sent elsewhere - */ -class BinMemInterface: public BinInterface -{ -public: - BinMemInterface(int defsize, int flags); - BinMemInterface(const void *data, const int size, int flags); -virtual ~BinMemInterface(); - - /* Extra Interfaces */ -int fseek(int loc); -int memsize() { return recvsize; } -void *memptr() { return buf; } - - /* file interface */ -bool writetofile(const char *fname); -bool readfromfile(const char *fname); - -virtual int tick() { return 1; } - -virtual int senddata(void *data, int len); -virtual int readdata(void *data, int len); -virtual int netstatus() { return 1; } -virtual int isactive() { return 1; } -virtual bool moretoread(uint32_t /* usec */) - { - if ((buf) && (bin_flags & BIN_FLAGS_READABLE )) - { - if (readloc < recvsize) - { - return true; - } - } - return false; - } - -virtual int close(); -virtual bool cansend(uint32_t /* usec */) - { - return (bin_flags & BIN_FLAGS_WRITEABLE); - } -virtual bool bandwidthLimited() { return false; } - -virtual RsFileHash gethash(); -virtual uint64_t bytecount(); - - private: - int bin_flags; - void *buf; - int size; - int recvsize; - int readloc; - pqihash *hash; - uint64_t bcount; -}; - - -class NetBinDummy: public NetBinInterface -{ -public: - NetBinDummy(PQInterface *parent, const RsPeerId& id, uint32_t t); -virtual ~NetBinDummy() { return; } - - // Net Interface -virtual int connect(const struct sockaddr_storage &raddr); -virtual int listen(); -virtual int stoplistening(); -virtual int disconnect(); -virtual int reset(); -virtual bool connect_parameter(uint32_t type, uint32_t value) - { - (void) type; /* suppress unused parameter warning */ - (void) value; /* suppress unused parameter warning */ - return false; - } -virtual int getConnectAddress(struct sockaddr_storage &raddr) - { - (void) raddr; /* suppress unused parameter warning */ - return 0; - } - - // Bin Interface. -virtual int tick(); - -virtual int senddata(void *data, int len); -virtual int readdata(void *data, int len); -virtual int netstatus(); -virtual int isactive(); -virtual bool moretoread(uint32_t usec); -virtual bool cansend(uint32_t usec); -virtual int close(); - -virtual RsFileHash gethash(); - - private: - uint32_t type; - bool dummyConnected; - bool toConnect; - uint32_t connectDelta; - rstime_t connectTS; -}; - - -#endif // PQI_BINARY_INTERFACES_HEADER - diff --git a/libretroshare/src/pqi/pqihandler.cc b/libretroshare/src/pqi/pqihandler.cc deleted file mode 100644 index 1864354a0..000000000 --- a/libretroshare/src/pqi/pqihandler.cc +++ /dev/null @@ -1,510 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqihandler.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/pqihandler.h" - -#include // for NULL -#include "util/rstime.h" // for time, rstime_t -#include // for sort -#include // for dec -#include // for string, char_traits, operator+, bas... -#include // for pair - -#include "pqi/pqi_base.h" // for PQInterface, RsBwRates -#include "retroshare/rsconfig.h" // for RSTrafficClue -#include "retroshare/rsids.h" // for t_RsGenericIdType -#include "retroshare/rspeers.h" // for RsPeers, rsPeers -#include "serialiser/rsserial.h" // for RsItem, RsRawItem -#include "util/rsdebug.h" // for pqioutput, PQL_DEBUG_BASIC, PQL_ALERT -#include "util/rsstring.h" // for rs_sprintf_append - -using std::dec; - -#ifdef WINDOWS_SYS -#include -#endif - -struct RsLog::logInfo pqihandlerzoneInfo = {RsLog::Default, "pqihandler"}; -#define pqihandlerzone &pqihandlerzoneInfo - -//static const int PQI_HANDLER_NB_PRIORITY_LEVELS = 10 ; -//static const float PQI_HANDLER_NB_PRIORITY_RATIO = 2 ; - -//#define UPDATE_RATES_DEBUG 1 -// #define DEBUG_TICK 1 -// #define RSITEM_DEBUG 1 - -pqihandler::pqihandler() : coreMtx("pqihandler") -{ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - // setup minimal total+individual rates. - rateIndiv_out = 0.01; - rateIndiv_in = 0.01; - rateMax_out = 0.01; - rateMax_in = 0.01; - rateTotal_in = 0.0 ; - rateTotal_out = 0.0 ; - traffInSum = 0; - traffOutSum = 0; - last_m = time(NULL) ; - nb_ticks = 0 ; - mLastRateCapUpdate = 0 ; - ticks_per_sec = 5 ; // initial guess - return; -} - -int pqihandler::tick() -{ - int moreToTick = 0; - - { - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - // tick all interfaces... - std::map::iterator it; - for(it = mods.begin(); it != mods.end(); ++it) - { - if (0 < ((it -> second) -> pqi) -> tick()) - { -#ifdef DEBUG_TICK - std::cerr << "pqihandler::tick() moreToTick from mod()" << std::endl; -#endif - moreToTick = 1; - } - } -#ifdef TO_BE_REMOVED - // get the items, and queue them correctly - if (0 < locked_GetItems()) - { -#ifdef DEBUG_TICK - std::cerr << "pqihandler::tick() moreToTick from GetItems()" << std::endl; -#endif - moreToTick = 1; - } -#endif - } - - rstime_t now = time(NULL) ; - - if(now > mLastRateCapUpdate + 5) - { - std::map rateMap; - std::map::iterator it; - - - // every 5 secs, update the max rates for all modules - - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - for(std::map::iterator it = mods.begin(); it != mods.end(); ++it) - { - // This is rather inelegant, but pqihandler has searchModules that are dynamically allocated, so the max rates - // need to be updated from inside. - uint32_t maxUp = 0,maxDn =0 ; - if (rsPeers->getPeerMaximumRates(it->first,maxUp,maxDn) ) - it->second->pqi->setRateCap(maxDn,maxUp);// mind the order! Dn first, than Up. - } - - mLastRateCapUpdate = now ; - } - - UpdateRates(); - return moreToTick; -} - - -bool pqihandler::queueOutRsItem(RsItem *item) -{ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - uint32_t size ; - locked_HandleRsItem(item, size); - -#ifdef DEBUG_QOS - if(item->priority_level() == QOS_PRIORITY_UNKNOWN) - std::cerr << "Caught an unprioritized item !" << std::endl; - - print() ; -#endif - return true ; -} - -int pqihandler::status() -{ - std::map::iterator it; - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - { // for output - std::string out = "pqihandler::status() Active Modules:\n"; - - // display all interfaces... - for(it = mods.begin(); it != mods.end(); ++it) - { - rs_sprintf_append(out, "\tModule [%s] Pointer <%p>", it -> first.toStdString().c_str(), (void *) ((it -> second) -> pqi)); - } - - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out); - - } // end of output. - - - // status all interfaces... - for(it = mods.begin(); it != mods.end(); ++it) - { - ((it -> second) -> pqi) -> status(); - } - return 1; -} - -bool pqihandler::AddSearchModule(SearchModule *mod) -{ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - // if peerid used -> error. - //std::map::iterator it; - if (mod->peerid != mod->pqi->PeerId()) - { - // ERROR! - pqioutput(PQL_ALERT, pqihandlerzone, "ERROR peerid != PeerId!"); - return false; - } - - if (mod->peerid.isNull()) - { - // ERROR! - pqioutput(PQL_ALERT, pqihandlerzone, "ERROR peerid == NULL"); - return false; - } - - if (mods.find(mod->peerid) != mods.end()) - { - // ERROR! - pqioutput(PQL_ALERT, pqihandlerzone, "ERROR PeerId Module already exists!"); - return false; - } - - // store. - mods[mod->peerid] = mod; - return true; -} - -bool pqihandler::RemoveSearchModule(SearchModule *mod) -{ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - std::map::iterator it; - for(it = mods.begin(); it != mods.end(); ++it) - { - if (mod == it -> second) - { - mods.erase(it); - return true; - } - } - return false; -} - -// generalised output -int pqihandler::locked_HandleRsItem(RsItem *item, uint32_t& computed_size) -{ - computed_size = 0 ; - std::map::iterator it; - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, - "pqihandler::HandleRsItem()"); - - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, - "pqihandler::HandleRsItem() Sending to One Channel"); -#ifdef DEBUG_TICK - std::cerr << "pqihandler::HandleRsItem() Sending to One Channel" << std::endl; -#endif - - - // find module. - if ((it = mods.find(item->PeerId())) == mods.end()) - { - std::string out = "pqihandler::HandleRsItem() Invalid chan!"; - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out); -#ifdef DEBUG_TICK - std::cerr << out << std::endl; -#endif - - delete item; - return -1; - } - - std::string out = "pqihandler::HandleRsItem() sending to chan: " + it -> first.toStdString(); - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out); -#ifdef DEBUG_TICK - std::cerr << out << std::endl; -#endif - - // if yes send on item. - ((it -> second) -> pqi) -> SendItem(item,computed_size); - return 1; -} - -int pqihandler::SendRsRawItem(RsRawItem *ns) -{ - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, "pqihandler::SendRsRawItem()"); - - // directly send item to streamers - - return queueOutRsItem(ns) ; -} - -int pqihandler::ExtractTrafficInfo(std::list& out_lst,std::list& in_lst) -{ - in_lst.clear() ; - out_lst.clear() ; - - for( std::map::iterator it = mods.begin(); it != mods.end(); ++it) - { - std::list ilst,olst ; - - (it -> second)->pqi->gatherStatistics(olst,ilst) ; - - for(std::list::const_iterator it(ilst.begin());it!=ilst.end();++it) in_lst.push_back(*it) ; - for(std::list::const_iterator it(olst.begin());it!=olst.end();++it) out_lst.push_back(*it) ; - } - - return 1 ; -} - -// NEW extern fn to extract rates. -int pqihandler::ExtractRates(std::map &ratemap, RsBwRates &total) -{ - total.mMaxRateIn = getMaxRate(true); - total.mMaxRateOut = getMaxRate(false); - total.mRateIn = 0; - total.mRateOut = 0; - total.mQueueIn = 0; - total.mQueueOut = 0; - - /* Lock once rates have been retrieved */ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - std::map::iterator it; - for(it = mods.begin(); it != mods.end(); ++it) - { - SearchModule *mod = (it -> second); - - RsBwRates peerRates; - mod -> pqi -> getRates(peerRates); - - total.mRateIn += peerRates.mRateIn; - total.mRateOut += peerRates.mRateOut; - total.mQueueIn += peerRates.mQueueIn; - total.mQueueOut += peerRates.mQueueOut; - - ratemap[it->first] = peerRates; - - } - - return 1; -} - - - -// internal fn to send updates -int pqihandler::UpdateRates() -{ - std::map::iterator it; - - float avail_in = getMaxRate(true); - float avail_out = getMaxRate(false); - - float used_bw_in = 0; - float used_bw_out = 0; - - /* Lock once rates have been retrieved */ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - int num_sm = mods.size(); - float used_bw_in_table[num_sm]; /* table of in bandwidth currently used by each module */ - float used_bw_out_table[num_sm]; /* table of out bandwidth currently used by each module */ - - // loop through modules to get the used bandwidth -#ifdef UPDATE_RATES_DEBUG - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates Looping through modules" << std::endl; -#endif - - int index = 0; - - for(it = mods.begin(); it != mods.end(); ++it) - { - SearchModule *mod = (it -> second); - - traffInSum += mod -> pqi -> getTraffic(true); - traffOutSum += mod -> pqi -> getTraffic(false); - - float crate_in = mod -> pqi -> getRate(true); - float crate_out = mod -> pqi -> getRate(false); - - used_bw_in += crate_in; - used_bw_out += crate_out; - - /* fill the table of used bandwidths */ - used_bw_in_table[index] = crate_in; - used_bw_out_table[index] = crate_out; - - ++index; - } - -#ifdef UPDATE_RATES_DEBUG - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates Sorting used_bw_out_table: " << num_sm << " entries" << std::endl; -#endif - - /* Sort the used bw in/out table in ascending order */ - std::sort(used_bw_in_table, used_bw_in_table + num_sm); - std::sort(used_bw_out_table, used_bw_out_table + num_sm); - -#ifdef UPDATE_RATES_DEBUG - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates used_bw_out " << used_bw_out << std::endl; -#endif - - /* Calculate the optimal out_max value, taking into account avail_out and the out bw requested by modules */ - - float out_remaining_bw = avail_out; - float out_max_bw = 0; - bool keep_going = true; - int mod_index = 0; - - while (keep_going && (mod_index < num_sm)) { - float result = (num_sm - mod_index) * (used_bw_out_table[mod_index] - out_max_bw); - if (result > out_remaining_bw) { - /* There is not enough remaining out bw to satisfy all modules, - distribute the remaining out bw among modules, then exit */ - out_max_bw += out_remaining_bw / (num_sm - mod_index); - out_remaining_bw = 0; - keep_going = false; - } else { - /* Grant the requested out bandwidth to all modules, - then recalculate the remaining out bandwidth */ - out_remaining_bw -= result; - out_max_bw = used_bw_out_table[mod_index]; - ++mod_index; - } - } - -#ifdef UPDATE_RATES_DEBUG - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates mod_index " << mod_index << " out_max_bw " << out_max_bw << " remaining out bw " << out_remaining_bw << std::endl; -#endif - - /* Allocate only 50 pct the remaining out bw, if any, to make the transition more smooth */ - out_max_bw = out_max_bw + 0.5 * out_remaining_bw; - - /* Calculate the optimal in_max value, taking into account avail_in and the in bw requested by modules */ - - float in_remaining_bw = avail_in; - float in_max_bw = 0; - keep_going = true; - mod_index = 0; - - while (keep_going && mod_index < num_sm) { - float result = (num_sm - mod_index) * (used_bw_in_table[mod_index] - in_max_bw); - if (result > in_remaining_bw) { - /* There is not enough remaining in bw to satisfy all modules, - distribute the remaining in bw among modules, then exit */ - in_max_bw += in_remaining_bw / (num_sm - mod_index); - in_remaining_bw = 0; - keep_going = false; - } else { - /* Grant the requested in bandwidth to all modules, - then recalculate the remaining in bandwidth */ - in_remaining_bw -= result; - in_max_bw = used_bw_in_table[mod_index]; - ++mod_index; - } - } - -#ifdef UPDATE_RATES_DEBUG - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates mod_index " << mod_index << " in_max_bw " << in_max_bw << " remaining in bw " << in_remaining_bw << std::endl; -#endif - - // allocate only 75 pct of the remaining in bw, to make the transition more smooth - in_max_bw = in_max_bw + 0.75 * in_remaining_bw; - - // store current total in and out used bw - locked_StoreCurrentRates(used_bw_in, used_bw_out); - -#ifdef UPDATE_RATES_DEBUG - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates setting new out_max " << out_max_bw << " in_max " << in_max_bw << std::endl; -#endif - - // retrieve the bandwidth limits provided by peers via BwCtrl - std::map rateMap; - rsConfig->getAllBandwidthRates(rateMap); - std::map::iterator rateMap_it; - -#ifdef UPDATE_RATES_DEBUG - // dump RsConfigurationDataRates - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates RsConfigDataRates dump" << std::endl; - for (rateMap_it = rateMap.begin(); rateMap_it != rateMap.end(); rateMap_it++) - RsDbg () << "UPDATE_RATES pqihandler::UpdateRates PeerId " << rateMap_it->first.toStdString() << " mAllowedOut " << rateMap_it->second.mAllowedOut << std::endl; -#endif - - // update max rates - for(it = mods.begin(); it != mods.end(); ++it) - { - SearchModule *mod = (it -> second); - - // for our down bandwidth we use the calculated value without taking into account the max up provided by peers via BwCtrl - // this is harmless as they will control their up bw on their side - mod -> pqi -> setMaxRate(true, in_max_bw); - - // for our up bandwidth we take into account the max down provided by peers via BwCtrl - // because we don't want to clog our outqueues, the TCP buffers, and the peers inbound queues - mod -> pqi -> setMaxRate(false, out_max_bw); - if ((rateMap_it = rateMap.find(mod->pqi->PeerId())) != rateMap.end()) - if (rateMap_it->second.mAllowedOut > 0) - if (out_max_bw > rateMap_it->second.mAllowedOut) - mod -> pqi -> setMaxRate(false, rateMap_it->second.mAllowedOut); - } - -#ifdef UPDATE_RATES_DEBUG - // dump maxRates - for(it = mods.begin(); it != mods.end(); ++it) - { - SearchModule *mod = (it -> second); - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates PeerID " << (mod ->pqi -> PeerId()).toStdString() << " new bandwidth limits up " << mod -> pqi -> getMaxRate(false) << " down " << mod -> pqi -> getMaxRate(true) << std::endl; - } -#endif - - return 1; -} - -void pqihandler::getCurrentRates(float &in, float &out) -{ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - in = rateTotal_in; - out = rateTotal_out; -} - -void pqihandler::locked_StoreCurrentRates(float in, float out) -{ - rateTotal_in = in; - rateTotal_out = out; -} - -void pqihandler::GetTraffic(uint64_t &in, uint64_t &out) -{ - in = traffInSum; - out = traffOutSum; -} diff --git a/libretroshare/src/pqi/pqihandler.h b/libretroshare/src/pqi/pqihandler.h deleted file mode 100644 index 4bfd4f828..000000000 --- a/libretroshare/src/pqi/pqihandler.h +++ /dev/null @@ -1,152 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqihandler.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_HANDLER_HEADER -#define MRK_PQI_HANDLER_HEADER - -#include // for uint32_t -#include "util/rstime.h" // for rstime_t, NULL -#include // for list -#include // for map - -#include "pqi/pqi.h" // for P3Interface, pqiPublisher -#include "retroshare/rstypes.h" // for RsPeerId -#include "util/rsthreads.h" // for RsStackMutex, RsMutex - -class PQInterface; -struct RSTrafficClue; -class RsBwRates; -struct RsItem; -class RsRawItem; - -class SearchModule -{ - public: - SearchModule() : pqi(NULL) {} - - RsPeerId peerid ; - PQInterface *pqi; -}; - -// Presents a P3 Face to the world! -// and funnels data through to a PQInterface. -// -class pqihandler: public P3Interface, public pqiPublisher -{ - public: - pqihandler(); - - /**** Overloaded from pqiPublisher ****/ - virtual bool sendItem(RsRawItem *item) - { - return SendRsRawItem(item); - } - - bool AddSearchModule(SearchModule *mod); - bool RemoveSearchModule(SearchModule *mod); - - // Rest of P3Interface - virtual int tick(); - virtual int status(); - - // Service Data Interface - virtual int SendRsRawItem(RsRawItem *); -#ifdef TO_BE_REMOVED - virtual RsRawItem *GetRsRawItem(); -#endif - - // rate control. - //void setMaxRate(const RsPeerId& pid,bool in, uint32_t val_kBs); - void setMaxRate(bool in, float val); - float getMaxRate(bool in); - - void setMaxRates(const RsPeerId& pid,bool in,float val) ; - float getMaxRates(const RsPeerId& pid,bool in) ; - - void getCurrentRates(float &in, float &out); - - // TESTING INTERFACE. - int ExtractRates(std::map &ratemap, RsBwRates &totals); - int ExtractTrafficInfo(std::list &out_lst, std::list &in_lst); - - uint64_t traffInSum; - uint64_t traffOutSum; - void GetTraffic(uint64_t &in, uint64_t &out); - -protected: - /* check to be overloaded by those that can - * generates warnings otherwise - */ - - int locked_HandleRsItem(RsItem *ns, uint32_t& size); - bool queueOutRsItem(RsItem *) ; - -#ifdef TO_BE_REMOVED - int locked_GetItems(); - void locked_SortnStoreItem(RsItem *item); -#endif - - RsMutex coreMtx; /* MUTEX */ - - std::map mods; - - std::list in_service; - - private: - - // rate control. - int UpdateRates(); - void locked_StoreCurrentRates(float in, float out); - - float rateIndiv_in; - float rateIndiv_out; - float rateMax_in; - float rateMax_out; - - float rateTotal_in; - float rateTotal_out; - - uint32_t nb_ticks ; - rstime_t last_m ; - rstime_t mLastRateCapUpdate ; - float ticks_per_sec ; -}; - -inline void pqihandler::setMaxRate(bool in, float val) -{ - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - if (in) - rateMax_in = val; - else - rateMax_out = val; - return; -} - -inline float pqihandler::getMaxRate(bool in) -{ - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - if (in) - return rateMax_in; - else - return rateMax_out; -} - -#endif // MRK_PQI_HANDLER_HEADER diff --git a/libretroshare/src/pqi/pqihash.h b/libretroshare/src/pqi/pqihash.h deleted file mode 100644 index 9a36cb89c..000000000 --- a/libretroshare/src/pqi/pqihash.h +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqihash.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef PQI_HASH_ -#define PQI_HASH_ - -#include -#include -#include -#include -#include -#include "util/rsstring.h" -#include "retroshare/rstypes.h" -#include - -class pqihash -{ - public: - pqihash() -{ - - sha_hash = new uint8_t[SHA_DIGEST_LENGTH]; - memset(sha_hash,0,SHA_DIGEST_LENGTH*sizeof(uint8_t)) ; - sha_ctx = new SHA_CTX; - SHA1_Init(sha_ctx); - doHash = true; -} - - ~pqihash() -{ - delete[] sha_hash; - delete sha_ctx; -} - - -void addData(const void *data, uint32_t len) -{ - if (doHash) - { - SHA1_Update(sha_ctx, data, len); - } -} - -void Complete(RsFileHash &hash) -{ - if (!doHash) - { - hash = endHash; - return; - } - - SHA1_Final(sha_hash, sha_ctx); - - endHash.clear(); - endHash = hash = Sha1CheckSum(sha_hash); - -// for(int i = 0; i < SHA_DIGEST_LENGTH; i++) -// { -// rs_sprintf_append(endHash, "%02x", (unsigned int) (sha_hash[i])); -// } -// hash = endHash; - doHash = false; - - return; -} - - private: - - bool doHash; - RsFileHash endHash; - uint8_t *sha_hash; - SHA_CTX *sha_ctx; -}; - -#endif diff --git a/libretroshare/src/pqi/pqiindic.h b/libretroshare/src/pqi/pqiindic.h deleted file mode 100644 index 28f619b16..000000000 --- a/libretroshare/src/pqi/pqiindic.h +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiindic.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_INDICATOR_HEADER -#define MRK_PQI_INDICATOR_HEADER - -#include - -// This will indicate to num different sources -// when the event has occured. - -class Indicator -{ - public: - explicit Indicator(uint16_t n = 1) - :num(n), changeFlags(n) {IndicateChanged();} -void IndicateChanged() - { - for(uint16_t i = 0; i < num; i++) - changeFlags[i]=true; - } - -bool Changed(uint16_t idx = 0) - { - /* catch overflow */ - if (idx > num - 1) - return false; - - bool ans = changeFlags[idx]; - changeFlags[idx] = false; - return ans; - } - - private: - uint16_t num; - std::vector changeFlags; -}; - - - -#endif diff --git a/libretroshare/src/pqi/pqiipset.cc b/libretroshare/src/pqi/pqiipset.cc deleted file mode 100644 index 6c273b47c..000000000 --- a/libretroshare/src/pqi/pqiipset.cc +++ /dev/null @@ -1,264 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiipset.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "util/rstime.h" -#include "pqi/pqiipset.h" -#include "util/rsstring.h" - -bool pqiIpAddress::sameAddress(const pqiIpAddress &a) const -{ - return sockaddr_storage_same(mAddr, a.mAddr); -} - - -bool pqiIpAddress::validAddress() const -{ - /* filter for unlikely addresses */ - if(sockaddr_storage_isLoopbackNet(mAddr)) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddress::validAddress() ip parameter is loopback: disgarding." << std::endl ; -#endif - return false; - } - - if(sockaddr_storage_isnull(mAddr)) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddress::validAddress() ip parameter is 0.0.0.0/1, or port is 0, ignoring." << std::endl; -#endif - return false; - } - - return true; - -} - - -bool pqiIpAddrList::updateIpAddressList(const pqiIpAddress &addr) -{ - std::list::iterator it; - bool add = false; - bool newAddr = true; - -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList()"; - std::cerr << std::endl; -#endif - - if (mAddrs.size() < MAX_ADDRESS_LIST_SIZE) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() small list: Add"; - std::cerr << std::endl; -#endif - add = true; - } - else if (mAddrs.back().mSeenTime < addr.mSeenTime) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() oldAddr: Add"; - std::cerr << std::endl; -#endif - add = true; - } - - if ((!add) || (!addr.validAddress())) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() not Add or !valid.. fail"; - std::cerr << std::endl; -#endif - return false; - } - - for(it = mAddrs.begin(); it != mAddrs.end(); ++it) - { - if (it->sameAddress(addr)) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() found duplicate"; - std::cerr << std::endl; -#endif - if (it->mSeenTime > addr.mSeenTime) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() orig better, returning"; - std::cerr << std::endl; -#endif - /* already better -> quit */ - return false; - } - -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() deleting orig"; - std::cerr << std::endl; -#endif - it = mAddrs.erase(it); - newAddr = false; - break; - } - } - - // ordered by decreaseing time. (newest at front) - bool added = false; - for(it = mAddrs.begin(); it != mAddrs.end(); ++it) - { - if (it->mSeenTime < addr.mSeenTime) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() added orig SeenTime: " << it->mSeenTime << " new SeenTime: " << addr.mSeenTime; - std::cerr << std::endl; -#endif - - added = true; - mAddrs.insert(it, addr); - break; - } - } - if (!added) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() pushing to back"; - std::cerr << std::endl; -#endif - mAddrs.push_back(addr); - } - - /* pop if necessary */ - while (mAddrs.size() > MAX_ADDRESS_LIST_SIZE) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() popping back"; - std::cerr << std::endl; -#endif - mAddrs.pop_back(); - } - - return newAddr; -} - -void pqiIpAddrList::extractFromTlv(const RsTlvIpAddrSet &tlvAddrs) -{ - std::list::const_iterator it; - - //for(it = tlvAddrs.addrs.begin(); it != tlvAddrs.addrs.end() ; ++it) - for(it = tlvAddrs.mList.begin(); it != tlvAddrs.mList.end() ; ++it) - { - pqiIpAddress addr; - addr.mAddr = it->addr.addr; - addr.mSeenTime = it->seenTime; - addr.mSrc = it->source; - - mAddrs.push_back(addr); - } -} - -void pqiIpAddrList::loadTlv(RsTlvIpAddrSet &tlvAddrs) const -{ - std::list::const_iterator it; - - for(it = mAddrs.begin(); it != mAddrs.end() ; ++it) - { - RsTlvIpAddressInfo addr; - addr.addr.addr = it->mAddr; - addr.seenTime = it->mSeenTime; - addr.source = it->mSrc; - - //tlvAddrs.addrs.push_back(addr); - tlvAddrs.mList.push_back(addr); - } -} - - - -void pqiIpAddrList::printIpAddressList(std::string &out) const -{ - std::list::const_iterator it; - rstime_t now = time(NULL); - for(it = mAddrs.begin(); it != mAddrs.end(); ++it) - { - out += sockaddr_storage_tostring(it->mAddr); - rs_sprintf_append(out, "( %ld old)\n", now - it->mSeenTime); - } - return; -} - - -bool pqiIpAddrSet::updateLocalAddrs(const pqiIpAddress &addr) -{ - return mLocal.updateIpAddressList(addr); -} - -bool pqiIpAddrSet::updateExtAddrs(const pqiIpAddress &addr) -{ - return mExt.updateIpAddressList(addr); -} - -bool pqiIpAddrSet::updateAddrs(const pqiIpAddrSet &addrs) -{ -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrSet::updateAddrs()"; - std::cerr << std::endl; -#endif - - bool newAddrs = false; - std::list::const_iterator it; - for(it = addrs.mLocal.mAddrs.begin(); it != addrs.mLocal.mAddrs.end(); ++it) - { - if (mLocal.updateIpAddressList(*it)) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrSet::updateAddrs() Updated Local Addr"; - std::cerr << std::endl; -#endif - newAddrs = true; - } - } - - for(it = addrs.mExt.mAddrs.begin(); it != addrs.mExt.mAddrs.end(); ++it) - { - if (mExt.updateIpAddressList(*it)) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrSet::updateAddrs() Updated Ext Addr"; - std::cerr << std::endl; -#endif - newAddrs = true; - } - } - return newAddrs; -} - - - -void pqiIpAddrSet::printAddrs(std::string &out) const -{ - out += "Local Addresses: "; - mLocal.printIpAddressList(out); - out += "\nExt Addresses: "; - mExt.printIpAddressList(out); - out += "\n"; -} - - - - diff --git a/libretroshare/src/pqi/pqiipset.h b/libretroshare/src/pqi/pqiipset.h deleted file mode 100644 index 9f6c31b17..000000000 --- a/libretroshare/src/pqi/pqiipset.h +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiipset.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef PQI_IP_SET_H -#define PQI_IP_SET_H - -#include "util/rsnet.h" -#include "serialiser/rstlvaddrs.h" -#include "util/rstime.h" - -#define MAX_ADDRESS_LIST_SIZE 10 - -class pqiIpAddress -{ - public: - bool sameAddress(const pqiIpAddress &a) const; - bool validAddress() const; - - struct sockaddr_storage mAddr; - rstime_t mSeenTime; - uint32_t mSrc; -}; - - -class pqiIpAddrList -{ - public: - - // returns true if new address added. - bool updateIpAddressList(const pqiIpAddress &addr); - void printIpAddressList(std::string &out) const; - void extractFromTlv(const RsTlvIpAddrSet &tlvAddrs); - void loadTlv(RsTlvIpAddrSet &tlvAddrs) const; - - // sorted list... based on seen time. - std::list mAddrs; -}; - - -class pqiIpAddrSet -{ - public: - - bool updateLocalAddrs(const pqiIpAddress &addr); - bool updateExtAddrs(const pqiIpAddress &addr); - bool updateAddrs(const pqiIpAddrSet &addrs); - void printAddrs(std::string &out) const; - pqiIpAddrList mLocal; - pqiIpAddrList mExt; - - void clear() - { - mLocal.mAddrs.clear(); - mExt.mAddrs.clear(); - } -}; - - -#endif diff --git a/libretroshare/src/pqi/pqilistener.h b/libretroshare/src/pqi/pqilistener.h deleted file mode 100644 index 5f748dc8f..000000000 --- a/libretroshare/src/pqi/pqilistener.h +++ /dev/null @@ -1,41 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqilistener.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_GENERIC_LISTEN_HEADER -#define MRK_PQI_GENERIC_LISTEN_HEADER - -// operating system specific network header. -#include "pqi/pqinetwork.h" - -class pqilistener -{ -public: - pqilistener() {} - virtual ~pqilistener() {} - virtual int tick() { return 1; } - virtual int status() { return 1; } - virtual int setListenAddr(const sockaddr_storage & /*addr*/) { return 1; } - virtual int setuplisten() { return 1; } - virtual int resetlisten() { return 1; } -}; - - -#endif // MRK_PQI_GENERIC_LISTEN_HEADER diff --git a/libretroshare/src/pqi/pqiloopback.cc b/libretroshare/src/pqi/pqiloopback.cc deleted file mode 100644 index 69e70488b..000000000 --- a/libretroshare/src/pqi/pqiloopback.cc +++ /dev/null @@ -1,89 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiloopback.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/pqiloopback.h" - -#include // for NULL - -struct RsItem; - -/*** -#define LOOPBACK_DEBUG 1 -***/ - -pqiloopback::pqiloopback(const RsPeerId& id) - :PQInterface(id) -{ - setMaxRate(true, 0); - setMaxRate(false, 0); - setRate(true, 0); - setRate(false, 0); - - return; -} - -pqiloopback::~pqiloopback() -{ - return; -} - -int pqiloopback::SendItem(RsItem *i) -{ - -#ifdef LOOPBACK_DEBUG - std::cerr << "pqiloopback::SendItem()"; - std::cerr << std::endl; - i->print(std::cerr); - std::cerr << std::endl; -#endif - objs.push_back(i); - return 1; -} - -RsItem * pqiloopback::GetItem() -{ - if (objs.size() > 0) - { - RsItem *pqi = objs.front(); - objs.pop_front(); -#ifdef LOOPBACK_DEBUG - std::cerr << "pqiloopback::GetItem()"; - std::cerr << std::endl; - pqi->print(std::cerr); - std::cerr << std::endl; -#endif - return pqi; - } - return NULL; -} - -// PQI interface. -int pqiloopback::tick() -{ - return 0; -} - -int pqiloopback::status() -{ - return 0; -} - - diff --git a/libretroshare/src/pqi/pqiloopback.h b/libretroshare/src/pqi/pqiloopback.h deleted file mode 100644 index f8d40e667..000000000 --- a/libretroshare/src/pqi/pqiloopback.h +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiloopback.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_LOOPBACK_HEADER -#define MRK_PQI_LOOPBACK_HEADER - -#include // for list - -#include "pqi/pqi_base.h" // for NetInterface (ptr only), PQInterface -#include "retroshare/rstypes.h" // for RsPeerId - -struct RsItem; - -class pqiloopback: public PQInterface -{ -public: - pqiloopback(const RsPeerId& id); -virtual ~pqiloopback(); - -// search Interface. -virtual int SendItem(RsItem *item); -virtual RsItem *GetItem(); - -// PQI interface. -virtual int tick(); -virtual int status(); - -private: - std::list objs; -}; - -#endif //MRK_PQI_LOOPBACK_HEADER diff --git a/libretroshare/src/pqi/pqimonitor.cc b/libretroshare/src/pqi/pqimonitor.cc deleted file mode 100644 index 550cd7b5a..000000000 --- a/libretroshare/src/pqi/pqimonitor.cc +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqimonitor.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/pqimonitor.h" -#include "pqi/pqinetwork.h" -#include "pqi/pqiipset.h" -#include "util/rsprint.h" - -/***** DUMMY Connect CB for testing *****/ - -#include - - -pqiConnectCbDummy::pqiConnectCbDummy() -{ - std::cerr << "pqiConnectCbDummy()" << std::endl; - return; -} - -pqiConnectCbDummy::~pqiConnectCbDummy() -{ - return; -} - -void pqiConnectCbDummy::peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs, - uint32_t type, uint32_t mode, uint32_t source) -{ - std::cerr << "pqiConnectCbDummy::peerStatus()"; - std::cerr << " id: " << id; - std::cerr << " type: " << type; - std::cerr << " mode: " << mode; - std::cerr << " source: " << source; - std::cerr << std::endl; - - std::cerr << " addrs: "; - std::cerr << std::endl; - std::string out; - addrs.printAddrs(out); - std::cerr << out << std::endl; -} - -void pqiConnectCbDummy::peerConnectRequest(const RsPeerId &id, const sockaddr_storage &raddr - , const sockaddr_storage &proxyaddr, const sockaddr_storage &srcaddr - , uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth) -{ - std::cerr << "pqiConnectCbDummy::peerConnectRequest()"; - std::cerr << " id: " << id; - std::cerr << " raddr: " << sockaddr_storage_tostring(raddr); - std::cerr << " proxyaddr: " << sockaddr_storage_tostring(proxyaddr); - std::cerr << " srcaddr: " << sockaddr_storage_tostring(srcaddr); - std::cerr << " source: " << source; - std::cerr << " flags: " << flags; - std::cerr << " delay: " << delay; - std::cerr << " bandwidth: " << bandwidth; - std::cerr << std::endl; -} - -void pqiMonitor::disconnectPeer(const RsPeerId &/*peer*/) -{ - std::cerr << "(EE) pqiMonitor::disconnectPeer() shouldn't be called!!!"<< std::endl; -} - -#if 0 -void pqiConnectCbDummy::stunStatus(std::string id, const struct sockaddr_storage *raddr, - uint32_t type, uint32_t flags) -{ - std::cerr << "pqiConnectCbDummy::stunStatus()"; - std::cerr << " idhash: " << RsUtil::BinToHex(id) << " raddr: " << sockaddr_storage_tostring(raddr); - std::cerr << " type: " << type; - std::cerr << " flags: " << flags; - std::cerr << std::endl; -} -#endif - - diff --git a/libretroshare/src/pqi/pqimonitor.h b/libretroshare/src/pqi/pqimonitor.h deleted file mode 100644 index 34a858e66..000000000 --- a/libretroshare/src/pqi/pqimonitor.h +++ /dev/null @@ -1,193 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqimonitor.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef PQI_MONITOR_H -#define PQI_MONITOR_H - -/**** Rough sketch of a Monitor class - * expect it to change significantly - * - */ - -#include -#include -#include -#include "pqi/pqiipset.h" -#include "retroshare/rstypes.h" - -/************** Define Type/Mode/Source ***************/ - - -/* STATE MASK */ -const uint32_t RS_PEER_STATE_MASK = 0x00ff; -const uint32_t RS_PEER_ACTION_MASK = 0xff00; - -/* STATE */ -const uint32_t RS_PEER_S_FRIEND = 0x0001; -const uint32_t RS_PEER_S_ONLINE = 0x0002; /* heard from recently..*/ -const uint32_t RS_PEER_S_CONNECTED = 0x0004; -const uint32_t RS_PEER_S_UNREACHABLE = 0x0008; - -/* ACTIONS */ -const uint32_t RS_PEER_NEW = 0x0001; /* new Peer */ -const uint32_t RS_PEER_ONLINE = 0x0002; -const uint32_t RS_PEER_CONNECTED = 0x0004; -const uint32_t RS_PEER_MOVED = 0x0008; /* moved from F->O or O->F */ -const uint32_t RS_PEER_DISCONNECTED = 0x0010; -const uint32_t RS_PEER_CONNECT_REQ = 0x0020; - -/* Stun Status Flags */ -//const uint32_t RS_STUN_SRC_DHT = 0x0001; -//const uint32_t RS_STUN_SRC_PEER = 0x0002; -const uint32_t RS_STUN_ONLINE = 0x0010; -const uint32_t RS_STUN_FRIEND = 0x0020; -const uint32_t RS_STUN_FRIEND_OF_FRIEND = 0x0040; - - -#define RS_CB_DHT 0x0001 /* from dht */ -#define RS_CB_DISC 0x0002 /* from peers */ -#define RS_CB_PERSON 0x0003 /* from connection */ -#define RS_CB_PROXY 0x0004 /* via proxy */ - - -#define RS_CB_FLAG_MASK_MODE 0x00ff -#define RS_CB_FLAG_MASK_ORDER 0xff00 - -#define RS_CB_FLAG_MODE_TCP 0x0001 -#define RS_CB_FLAG_MODE_UDP_DIRECT 0x0002 -#define RS_CB_FLAG_MODE_UDP_PROXY 0x0004 -#define RS_CB_FLAG_MODE_UDP_RELAY 0x0008 - -#define RS_CB_FLAG_ORDER_UNSPEC 0x0100 -#define RS_CB_FLAG_ORDER_PASSIVE 0x0200 -#define RS_CB_FLAG_ORDER_ACTIVE 0x0400 - -#define RSUDP_NUM_TOU_RECVERS 3 - -#define RSUDP_TOU_RECVER_DIRECT_IDX 0 -#define RSUDP_TOU_RECVER_PROXY_IDX 1 -#define RSUDP_TOU_RECVER_RELAY_IDX 2 - - -class pqipeer -{ - public: - RsPeerId id; - std::string name; - uint32_t state; - uint32_t actions; -}; - -class p3LinkMgr; - -/*! - * This class should be implemented - * to use the information that is passed to it via - * from the p3ConnectMngr - * Useful information is sent via ticks such as a peer's - * state and a peer's action - */ -class pqiMonitor -{ - public: - pqiMonitor() :mLinkMgr(NULL) { return; } -virtual ~pqiMonitor() { return; } - - /*! - * passes a handle the retroshare connection manager - */ - void setLinkMgr(p3LinkMgr *lm) { mLinkMgr = lm; } - - /*! - * this serves as a call back function for server which has - * a handle on the subclass and updates this subclass on the - * action of peer's of the client (state and action information) - * - *@param plist contains list of states and actions of the client's peers - */ -virtual void statusChange(const std::list &plist) = 0; - - // This is used to force disconnection of a peer, if e.g. something suspicious happenned. - - virtual void disconnectPeer(const RsPeerId& peer) ; - -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections -virtual void statusChanged() {}; -/////////////////////////////////////////////////////////// -#endif - -//virtual void ownStatusChange(pqipeer &) { return; } // SIGNAL reset or similar. -//virtual void peerStatus(std::string id, uint32_t mode) = 0; - - protected: - p3LinkMgr *mLinkMgr; -}; - - - - -class pqiConnectCb -{ - public: -virtual ~pqiConnectCb() { return; } -virtual void peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs, - uint32_t type, uint32_t flags, uint32_t source) = 0; - -virtual void peerConnectRequest(const RsPeerId& id, const struct sockaddr_storage &raddr, - const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr, - uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth) = 0; - - -//virtual void stunStatus(std::string id, const struct sockaddr_storage &raddr, uint32_t type, uint32_t flags) = 0; -}; - - -/**** DUMMY CB FOR TESTING (just prints) ****/ -class pqiConnectCbDummy: public pqiConnectCb -{ - public: - pqiConnectCbDummy(); -virtual ~pqiConnectCbDummy(); -virtual void peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs, - uint32_t type, uint32_t mode, uint32_t source); - - virtual void peerConnectRequest(const RsPeerId& id, const struct sockaddr_storage &raddr, - const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr, - uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth); - -//virtual void stunStatus(std::string id, const struct sockaddr_storage &raddr, uint32_t type, uint32_t flags); -}; - - -/* network listener interface - used to reset network addresses */ -class pqiNetListener -{ - public: -virtual bool resetListener(const struct sockaddr_storage &local) = 0; - -}; - - -#endif // PQI_MONITOR_H - diff --git a/libretroshare/src/pqi/pqinetstatebox.cc b/libretroshare/src/pqi/pqinetstatebox.cc deleted file mode 100644 index 67d1fcef1..000000000 --- a/libretroshare/src/pqi/pqinetstatebox.cc +++ /dev/null @@ -1,616 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqinetstatebox.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "util/rsnet.h" -#include "pqi/pqinetstatebox.h" -#include "util/rstime.h" - -#ifdef RS_USE_BITDHT -#include "bitdht/bdiface.h" -#endif - -// External Interface. - -void pqiNetStateBox::setAddressStunDht(const struct sockaddr_storage &addr, bool stable) -{ - if ((!mStunDhtSet) || (mStunDhtStable != stable) || - (!sockaddr_storage_same(addr, mStunDhtAddr))) - { - mStunDhtSet = true; - mStunDhtStable = stable; - mStunDhtAddr = addr; - - mStatusOkay = false; - } - mStunDhtTS = time(NULL); -} - - -void pqiNetStateBox::setAddressStunProxy(const struct sockaddr_storage &addr, bool stable) -{ - if ((!mStunProxySet) || (mStunProxyStable != stable) || - (!sockaddr_storage_same(addr, mStunProxyAddr))) - { - - if (sockaddr_storage_sameip(addr,mStunProxyAddr)) - { - if (mStunProxyStable != stable) - { - mStunProxySemiStable = true; - } - } - else - { - mStunProxySemiStable = false; // change of address - must trigger this again! - } - - mStunProxySet = true; - mStunProxyStable = stable; - mStunProxyAddr = addr; - mStatusOkay = false; - } - mStunProxyTS = time(NULL); -} - - -void pqiNetStateBox::setAddressUPnP(bool active, const struct sockaddr_storage &addr) -{ - if ((!mUPnPSet) || (mUPnPActive != active) || - (!sockaddr_storage_same(addr, mUPnPAddr))) - { - mUPnPSet = true; - mUPnPAddr = addr; - mUPnPActive = active; - - mStatusOkay = false; - } - mUPnPTS = time(NULL); -} - - -void pqiNetStateBox::setAddressNatPMP(bool active, const struct sockaddr_storage &addr) -{ - if ((!mNatPMPSet) || (mNatPMPActive != active) || - (!sockaddr_storage_same(addr, mNatPMPAddr))) - { - mNatPMPSet = true; - mNatPMPAddr = addr; - mNatPMPActive = active; - - mStatusOkay = false; - } - mNatPMPTS = time(NULL); -} - - - -void pqiNetStateBox::setAddressWebIP(bool active, const struct sockaddr_storage &addr) -{ - if ((!mWebIPSet) || (mWebIPActive != active) || - (!sockaddr_storage_same(addr, mWebIPAddr))) - { - mWebIPSet = true; - mWebIPAddr = addr; - mWebIPActive = active; - - mStatusOkay = false; - } - mWebIPTS = time(NULL); -} - - -void pqiNetStateBox::setPortForwarded(bool /*active*/, uint16_t port) -{ - if ((!mPortForwardSet) || (mPortForwarded != port)) - - { - mPortForwardSet = true; - mPortForwarded = port; - - mStatusOkay = false; - } -} - - -void pqiNetStateBox::setDhtState(bool on, bool active) -{ - if ((!mDhtSet) || (mDhtActive != active) || (mDhtOn != on)) - { - mDhtSet = true; - mDhtActive = active; - mDhtOn = on; - - mStatusOkay = false; - } - mDhtTS = time(NULL); -} - - -/* Extract Net State */ -RsNetworkMode pqiNetStateBox::getNetworkMode() -{ - updateNetState(); - return mNetworkMode; -} - -RsNatTypeMode pqiNetStateBox::getNatTypeMode() -{ - updateNetState(); - return mNatTypeMode; -} - -RsNatHoleMode pqiNetStateBox::getNatHoleMode() -{ - updateNetState(); - return mNatHoleMode; -} - -RsConnectModes pqiNetStateBox::getConnectModes() -{ - updateNetState(); - return mConnectModes; -} - - -RsNetState pqiNetStateBox::getNetStateMode() -{ - updateNetState(); - return mNetStateMode; -} - - - -/******************************** Internal Workings *******************************/ -pqiNetStateBox::pqiNetStateBox() -{ - reset(); -} - - -void pqiNetStateBox::reset() -{ - - mStatusOkay = false; - //rstime_t mStatusTS; - - mNetworkMode = RsNetworkMode::UNKNOWN; - mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::UNKNOWN; - mConnectModes = RsConnectModes::NONE; - mNetStateMode = RsNetState::BAD_UNKNOWN; - - /* Parameters set externally */ - - mStunDhtSet = false; - mStunDhtTS = 0; - mStunDhtStable = false; - sockaddr_storage_clear(mStunDhtAddr); - - mStunProxySet = false; - mStunProxySemiStable = false; - mStunProxyTS = 0; - mStunProxyStable = false; - sockaddr_storage_clear(mStunProxyAddr); - - mUPnPSet = false; - mUPnPActive = false; - sockaddr_storage_clear(mUPnPAddr); - - mNatPMPSet = false; - mNatPMPActive = false; - sockaddr_storage_clear(mNatPMPAddr); - - mWebIPSet = false; - mWebIPActive = false; - sockaddr_storage_clear(mWebIPAddr); - - mPortForwardSet = false; - mPortForwarded = false; - - mDhtSet = false; - mDhtActive = false; - mDhtOn = false; - -} - -//#define NETSTATE_PARAM_TIMEOUT 600 -#define NETSTATE_PARAM_TIMEOUT 900 // Change to 15 minutes -> see if it has effect on reconnect time -#define NETSTATE_TIMEOUT 60 - - /* check/update Net State */ -int pqiNetStateBox::statusOkay() -{ - if (!mStatusOkay) - { - return 0; - } - rstime_t now = time(NULL); - if (now - mStatusTS > NETSTATE_TIMEOUT) - { - return 0; - } - return 1; -} - -int pqiNetStateBox::updateNetState() -{ - if (!statusOkay()) - { - determineNetworkState(); - } - return 1; -} - - - - -void pqiNetStateBox::clearOldNetworkData() -{ -#ifdef RS_USE_DHT_STUNNER - /* check if any measurements are too old to consider */ - rstime_t now = time(NULL); - if (now - mStunProxyTS > NETSTATE_PARAM_TIMEOUT) - { - mStunProxySet = false; - } - - if (now - mStunDhtTS > NETSTATE_PARAM_TIMEOUT) - { - mStunDhtSet = false; - } -#else - //Set values, as they are not updated. - mStunProxySet = true; - mStunDhtSet = true; - mStunProxyStable = true; - mStunDhtStable = true; -#endif - -} - - -void pqiNetStateBox::determineNetworkState() -{ - clearOldNetworkData(); - rstime_t now = time(NULL); - - /* now we use the remaining valid input to determine network state */ - - /* Most important Factor is whether we have DHT(STUN) info to ID connection */ - if (mDhtActive) - { - /* firstly lets try to identify OFFLINE / UNKNOWN */ - if ((!mStunProxySet) || (!mStunDhtSet)) - { - mNetworkMode = RsNetworkMode::UNKNOWN; - // Assume these. - mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::BAD_UNKNOWN; - - //mExtAddress = .... unknown; - //mExtAddrStable = false; - } - else // Both Are Set! - { - if (!mStunDhtStable) - { - //mExtAddress = mStunDhtExtAddress; - //mExtAddrStable = false; - - if (mStunProxySemiStable) - { - /* I'm guessing this will be a common mode for modern NAT/Firewalls. - * a DETERMINISTIC SYMMETRIC NAT.... This is likely to be the - * next iteration on the RESTRICTED CONE firewall described below. - * If you Stun fast, it looks like a SYMMETRIC NAT, but if you let - * the NAT timeout, you get back your original port so it looks like - * a RESTRICTED CONE nat... - * - * This kind of NAT is passable, if you only attempt one connection at - * a time, and are careful about it! - * - * NB: The StunDht port will never get this mode. - * It has unsolicited traffic which triggers SYM mode - * - */ - - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::DETERM_SYM; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::WARNING_NATTED; - - } - else if (!mStunProxyStable) - { - /* both unstable, Symmetric NAT, Firewalled, No UDP Hole */ - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::SYMMETRIC; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::BAD_NATSYM; - } - else - { - /* if DhtStun Unstable, but ProxyStable, then we have - * an interesting case. This is close to a Debian Firewall - * I tested in the past.... - * - * The big difference between DhtStun and ProxyStun is - * that Dht Port receives unsolicated packets, - * while Proxy Port always sends an outgoing one first. - * - * In the case of the debian firewall, the unsolicated pkts - * caused the outgoing port to change. - * - * We will label this difference RESTRICTED vs FULL CONE, - * but that label is really fully accurate. (gray area). - */ - - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::RESTRICTED_CONE; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::WARNING_NATTED; - } - } - else // Dht Stable. - { - /* DHT Stable port can be caused by: - * 1) Forwarded Port (UPNP, NATPMP, FORWARDED) - * 2) FULL CONE NAT. - * 3) EXT Port. - * Must look at Proxy Stability. - * - if Proxy Unstable, then must be forwarded port. - * - if Proxy Stable, then we cannot tell. - * -> Must use User Info (Upnp, PMP, Forwarded Flag). - * -> Also possible to be EXT Port (Check against iface) - */ - - //mExtAddress = mStunDhtExtAddress; - //mExtAddrStable = true; - - // Initial Fallback Guess at firewall state. - if (mStunProxySemiStable) - { - /* must be a forwarded port/ext or something similar */ - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::DETERM_SYM; - mNatHoleMode = RsNatHoleMode::FORWARDED; - mNetStateMode = RsNetState::GOOD; - } - else if (!mStunProxyStable) - { - /* must be a forwarded port/ext or something similar */ - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::SYMMETRIC; - mNatHoleMode = RsNatHoleMode::FORWARDED; - mNetStateMode = RsNetState::GOOD; - } - else - { - /* fallback is FULL CONE NAT */ - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::FULL_CONE; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::WARNING_NATTED; - } - - if (mUPnPActive) - { - // This Mode is OKAY. - mNetworkMode = RsNetworkMode::BEHINDNAT; - // Use Fallback Guess. - //mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::UPNP; - mNetStateMode = RsNetState::GOOD; - //mExtAddress = ... from UPnP, should match StunDht. - //mExtAddrStable = true; - } - else if (mNatPMPActive) - { - // This Mode is OKAY. - mNetworkMode = RsNetworkMode::BEHINDNAT; - // Use Fallback Guess. - //mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::NATPMP; - mNetStateMode = RsNetState::GOOD; - //mExtAddress = ... from NatPMP, should match NatPMP - //mExtAddrStable = true; - } - else - { - bool isExtAddress = false; - - if (isExtAddress) - { - mNetworkMode = RsNetworkMode::EXTERNALIP; - mNatTypeMode = RsNatTypeMode::NONE; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::GOOD; - - //mExtAddrStable = true; - } - else if (mPortForwardSet) - { - mNetworkMode = RsNetworkMode::BEHINDNAT; - // Use Fallback Guess. - //mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::FORWARDED; - mNetStateMode = RsNetState::ADV_FORWARD; - - //mExtAddrStable = true; // Probably, makin assumption. - } - else - { - /* At this point, we go with the fallback guesses */ - } - } - - } - } - } - else // DHT Inactive, must use other means... - { - /* If we get here we are dealing with a silly peer in "DarkMode". - * We have to primarily rely on the feedback from UPnP, PMP or WebSite "WhatsMyIp". - * This is in the "Advanced" Settings and liable to be set wrong. - * but thats the users fault! - */ - - if (mUPnPActive) - { - // This Mode is OKAY. - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::UPNP; - //mExtAddress = ... from UPnP. - //mExtAddrStable = true; - mNetStateMode = RsNetState::WARNING_NODHT; - } - else if (mNatPMPActive) - { - // This Mode is OKAY. - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::NATPMP; - //mExtAddress = ... from NatPMP. - //mExtAddrStable = true; - mNetStateMode = RsNetState::WARNING_NODHT; - } - else - { - /* if we reach this point, we really need a Web "WhatsMyIp" Check of our Ext Ip Address. */ - /* Check for the possibility of an EXT address ... */ - bool isExtAddress = false; - - //mExtAddress = ... from WhatsMyIp. - - if (isExtAddress) - { - mNetworkMode = RsNetworkMode::EXTERNALIP; - mNatTypeMode = RsNatTypeMode::NONE; - mNatHoleMode = RsNatHoleMode::NONE; - - //mExtAddrStable = true; - mNetStateMode = RsNetState::WARNING_NODHT; - } - else if (mPortForwardSet) - { - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::FORWARDED; - - //mExtAddrStable = true; // Probably, makin assumption. - mNetStateMode = RsNetState::WARNING_NODHT; - } - else - { - /* At this point we must assume firewalled. - * These people have destroyed the possibility of making connections ;( - * Should WARN about this. - */ - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::BAD_NODHT_NAT; - - //mExtAddrStable = false; // Unlikely to be stable. - } - } - } - - workoutNetworkMode(); - - /* say that things are okay */ - mStatusOkay = true; - mStatusTS = now; -} - - - -/* based on calculated settings, what is the network mode - */ - -void pqiNetStateBox::workoutNetworkMode() -{ - /* connectModes are dependent on the other modes */ - mConnectModes = RsConnectModes::NONE; - switch(mNetworkMode) - { - case RsNetworkMode::UNKNOWN: - case RsNetworkMode::OFFLINE: - case RsNetworkMode::LOCALNET: - case RsNetworkMode::RESTARTING: - /* nothing here */ - break; - case RsNetworkMode::EXTERNALIP: - mConnectModes = RsConnectModes::OUTGOING_TCP; - mConnectModes |= RsConnectModes::ACCEPT_TCP; - - if (mDhtActive) - { - mConnectModes |= RsConnectModes::DIRECT_UDP; - /* if open port. don't want PROXY or RELAY connect - * because we should be able to do direct with EVERYONE. - * Ability to do Proxy is dependent on FIREWALL status. - * Technically could do RELAY, but disable both. - */ - //mConnectModes |= RsConnectModes::PROXY_UDP; - //mConnectModes |= RsConnectModes::RELAY_UDP; - } - break; - case RsNetworkMode::BEHINDNAT: - mConnectModes = RsConnectModes::OUTGOING_TCP; - - /* we're okay if there's a NAT HOLE */ - if ((mNatHoleMode == RsNatHoleMode::UPNP) || - (mNatHoleMode == RsNatHoleMode::NATPMP) || - (mNatHoleMode == RsNatHoleMode::FORWARDED)) - { - mConnectModes |= RsConnectModes::ACCEPT_TCP; - if (mDhtActive) - { - mConnectModes |= RsConnectModes::DIRECT_UDP; - /* dont want PROXY | RELAY with open ports */ - } - } - else - { - /* If behind NAT without NATHOLE, this is where RELAY | PROXY - * are useful. We Flag DIRECT connections, cos we can do these - * with peers with Open Ports. (but not with other NATted peers). - */ - if (mDhtActive) - { - mConnectModes |= RsConnectModes::DIRECT_UDP; - mConnectModes |= RsConnectModes::RELAY_UDP; - - if ((mNatTypeMode == RsNatTypeMode::RESTRICTED_CONE) || - (mNatTypeMode == RsNatTypeMode::FULL_CONE) || - (mNatTypeMode == RsNatTypeMode::DETERM_SYM)) - { - mConnectModes |= RsConnectModes::PROXY_UDP; - } - } - } - break; - } -} diff --git a/libretroshare/src/pqi/pqinetstatebox.h b/libretroshare/src/pqi/pqinetstatebox.h deleted file mode 100644 index 26b85345a..000000000 --- a/libretroshare/src/pqi/pqinetstatebox.h +++ /dev/null @@ -1,120 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqinetstatebox.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef PQI_NET_STATUS_BOX_H -#define PQI_NET_STATUS_BOX_H - -/* a little state box to determine network status */ - -#include -#include - -#include -#include - -/*** Network state - * Want this to be all encompassing. - * - */ - -class pqiNetStateBox -{ - public: - pqiNetStateBox(); - - void reset(); - - /* input network bits */ - void setAddressStunDht(const struct sockaddr_storage &addr, bool stable); - void setAddressStunProxy(const struct sockaddr_storage &addr, bool stable); - - void setAddressUPnP(bool active, const struct sockaddr_storage &addr); - void setAddressNatPMP(bool active, const struct sockaddr_storage &addr); - void setAddressWebIP(bool active, const struct sockaddr_storage &addr); - - void setPortForwarded(bool active, uint16_t port); - - void setDhtState(bool dhtOn, bool dhtActive); - - RsNetState getNetStateMode(); - RsNetworkMode getNetworkMode(); - RsNatTypeMode getNatTypeMode(); - RsNatHoleMode getNatHoleMode(); - RsConnectModes getConnectModes(); - - private: - - /* calculate network state */ - void clearOldNetworkData(); - void determineNetworkState(); - int statusOkay(); - int updateNetState(); - - /* more internal fns */ - void workoutNetworkMode(); - - bool mStatusOkay; - rstime_t mStatusTS; - - RsNetworkMode mNetworkMode; - RsNatTypeMode mNatTypeMode; - RsNatHoleMode mNatHoleMode; - RsConnectModes mConnectModes; - RsNetState mNetStateMode; - - /* Parameters set externally */ - - bool mStunDhtSet; - rstime_t mStunDhtTS; - bool mStunDhtStable; - struct sockaddr_storage mStunDhtAddr; - - bool mStunProxySet; - rstime_t mStunProxyTS; - bool mStunProxyStable; - bool mStunProxySemiStable; - struct sockaddr_storage mStunProxyAddr; - - bool mDhtSet; - rstime_t mDhtTS; - bool mDhtOn; - bool mDhtActive; - - bool mUPnPSet; - struct sockaddr_storage mUPnPAddr; - bool mUPnPActive; - rstime_t mUPnPTS; - - bool mNatPMPSet; - struct sockaddr_storage mNatPMPAddr; - bool mNatPMPActive; - rstime_t mNatPMPTS; - - bool mWebIPSet; - struct sockaddr_storage mWebIPAddr; - bool mWebIPActive; - rstime_t mWebIPTS; - - bool mPortForwardSet; - uint16_t mPortForwarded; -}; - -#endif diff --git a/libretroshare/src/pqi/pqinetwork.cc b/libretroshare/src/pqi/pqinetwork.cc deleted file mode 100644 index 18fe71fc0..000000000 --- a/libretroshare/src/pqi/pqinetwork.cc +++ /dev/null @@ -1,533 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqinetwork.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#ifdef WINDOWS_SYS -# include "util/rswin.h" -# include "util/rsmemory.h" -# include -#endif // WINDOWS_SYS - -#ifdef __ANDROID__ -# include -#endif // def __ANDROID__ - -#include "pqi/pqinetwork.h" -#include "util/rsnet.h" - -#include -#include -#include -#include - -#include "util/rsdebug.h" -#include "util/rsstring.h" -#include "util/rsnet.h" -#include "util/stacktrace.h" - -static struct RsLog::logInfo pqinetzoneInfo = {RsLog::Default, "pqinet"}; -#define pqinetzone &pqinetzoneInfo - -/***** - * #define NET_DEBUG 1 - ****/ - -#ifdef WINDOWS_SYS /* Windows - define errno */ - -int errno; - -#else /* Windows - define errno */ - -#include - -#endif - -#ifdef __HAIKU__ - #include - #define IFF_RUNNING 0x0001 -#endif - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - -void showSocketError(std::string &out) -{ - int err = errno; - rs_sprintf_append(out, "\tSocket Error(%d) : %s\n", err, socket_errorType(err).c_str()); -} - -std::string socket_errorType(int err) -{ - if (err == EBADF) - { - return std::string("EBADF"); - } - else if (err == EINVAL) - { - return std::string("EINVAL"); - } - else if (err == EFAULT) - { - return std::string("EFAULT"); - } - else if (err == ENOTSOCK) - { - return std::string("ENOTSOCK"); - } - else if (err == EISCONN) - { - return std::string("EISCONN"); - } - else if (err == ECONNREFUSED) - { - return std::string("ECONNREFUSED"); - } - else if (err == ETIMEDOUT) - { - return std::string("ETIMEDOUT"); - } - else if (err == ENETUNREACH) - { - return std::string("ENETUNREACH"); - } - else if (err == EADDRINUSE) - { - return std::string("EADDRINUSE"); - } - else if (err == EINPROGRESS) - { - return std::string("EINPROGRESS"); - } - else if (err == EALREADY) - { - return std::string("EALREADY"); - } - else if (err == EAGAIN) - { - return std::string("EAGAIN"); - } - else if (err == EISCONN) - { - return std::string("EISCONN"); - } - else if (err == ENOTCONN) - { - return std::string("ENOTCONN"); - } - // These ones have been turning up in SSL CONNECTION FAILURES. - else if (err == EPIPE) - { - return std::string("EPIPE"); - } - else if (err == ECONNRESET) - { - return std::string("ECONNRESET"); - } - else if (err == EHOSTUNREACH) - { - return std::string("EHOSTUNREACH"); - } - else if (err == EADDRNOTAVAIL) - { - return std::string("EADDRNOTAVAIL"); - } - // - - return std::string("UNKNOWN ERROR CODE - ASK RS-DEVS TO ADD IT!"); -} - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else - -void showSocketError(std::string &out) -{ - int err = WSAGetLastError(); - rs_sprintf_append(out, "\tSocket Error(%d) : %s\n", err, socket_errorType(err).c_str()); -} - - -std::string socket_errorType(int err) -{ - if (err == WSAEBADF) - { - return std::string("WSABADF"); - } - - - else if (err == WSAEINTR) - { - return std::string("WSAEINTR"); - } - else if (err == WSAEACCES) - { - return std::string("WSAEACCES"); - } - else if (err == WSAEFAULT) - { - return std::string("WSAEFAULT"); - } - else if (err == WSAEINVAL) - { - return std::string("WSAEINVAL"); - } - else if (err == WSAEMFILE) - { - return std::string("WSAEMFILE"); - } - else if (err == WSAEWOULDBLOCK) - { - return std::string("WSAEWOULDBLOCK"); - } - else if (err == WSAEINPROGRESS) - { - return std::string("WSAEINPROGRESS"); - } - else if (err == WSAEALREADY) - { - return std::string("WSAEALREADY"); - } - else if (err == WSAENOTSOCK) - { - return std::string("WSAENOTSOCK"); - } - else if (err == WSAEDESTADDRREQ) - { - return std::string("WSAEDESTADDRREQ"); - } - else if (err == WSAEMSGSIZE) - { - return std::string("WSAEMSGSIZE"); - } - else if (err == WSAEPROTOTYPE) - { - return std::string("WSAEPROTOTYPE"); - } - else if (err == WSAENOPROTOOPT) - { - return std::string("WSAENOPROTOOPT"); - } - else if (err == WSAENOTSOCK) - { - return std::string("WSAENOTSOCK"); - } - else if (err == WSAEISCONN) - { - return std::string("WSAISCONN"); - } - else if (err == WSAECONNREFUSED) - { - return std::string("WSACONNREFUSED"); - } - else if (err == WSAECONNRESET) - { - return std::string("WSACONNRESET"); - } - else if (err == WSAETIMEDOUT) - { - return std::string("WSATIMEDOUT"); - } - else if (err == WSAENETUNREACH) - { - return std::string("WSANETUNREACH"); - } - else if (err == WSAEADDRINUSE) - { - return std::string("WSAADDRINUSE"); - } - else if (err == WSAEAFNOSUPPORT) - { - return std::string("WSAEAFNOSUPPORT (normally UDP related!)"); - } - - return std::string("----WINDOWS OPERATING SYSTEM FAILURE----"); -} - -// implement the improved unix inet address fn. -// using old one. -int inet_aton(const char *name, struct in_addr *addr) -{ - return (((*addr).s_addr = inet_addr(name)) != INADDR_NONE); -} - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - -#include -#ifdef WINDOWS_SYS -# include -# include -# pragma comment(lib, "IPHLPAPI.lib") -#elif defined(__ANDROID__) && __ANDROID_API__ < 24 -# include -# include -# include -# include -#else // not __ANDROID__ nor WINDOWS => Linux and other unixes -# include -# include -#endif // WINDOWS_SYS - -bool getLocalAddresses(std::vector& addrs) -{ - addrs.clear(); - -#ifdef WINDOWS_SYS - // Seems strange to me but M$ documentation suggests to allocate this way... - DWORD bf_size = 16000; - IP_ADAPTER_ADDRESSES* adapter_addresses = (IP_ADAPTER_ADDRESSES*) rs_malloc(bf_size); - - if(adapter_addresses == NULL) - return false ; - - DWORD error = GetAdaptersAddresses(AF_UNSPEC, - GAA_FLAG_SKIP_MULTICAST | - GAA_FLAG_SKIP_DNS_SERVER | - GAA_FLAG_SKIP_FRIENDLY_NAME, - NULL, - adapter_addresses, - &bf_size); - if (error != ERROR_SUCCESS) - { - std::cerr << "FATAL ERROR: getLocalAddresses failed!" << std::endl; - return false ; - } - - IP_ADAPTER_ADDRESSES* adapter(NULL); - for(adapter = adapter_addresses; NULL != adapter; adapter = adapter->Next) - { - IP_ADAPTER_UNICAST_ADDRESS* address; - for ( address = adapter->FirstUnicastAddress; address; address = address->Next) - { - sockaddr_storage tmp; - sockaddr_storage_clear(tmp); - if (sockaddr_storage_copyip(tmp, * reinterpret_cast(address->Address.lpSockaddr))) - addrs.push_back(tmp); - } - } - free(adapter_addresses); -#elif defined(__ANDROID__) && __ANDROID_API__ < 24 - foreach(QHostAddress qAddr, QNetworkInterface::allAddresses()) - { - sockaddr_storage tmpAddr; - sockaddr_storage_clear(tmpAddr); - if(sockaddr_storage_ipv4_aton(tmpAddr, qAddr.toString().toStdString().c_str())) - addrs.push_back(tmpAddr); - } -#else // not WINDOWS_SYS not ANDROID => Linux and other unixes - struct ifaddrs *ifsaddrs, *ifa; - if(getifaddrs(&ifsaddrs) != 0) - { - std::cerr << __PRETTY_FUNCTION__ << " FATAL ERROR: " << errno << " " - << strerror(errno) << std::endl; - print_stacktrace(); - return false; - } - for ( ifa = ifsaddrs; ifa; ifa = ifa->ifa_next ) - if ( ifa->ifa_addr && (ifa->ifa_flags & IFF_UP) ) - { - sockaddr_storage tmp; - sockaddr_storage_clear(tmp); - if (sockaddr_storage_copyip(tmp, *reinterpret_cast(ifa->ifa_addr))) - addrs.push_back(tmp); - } - freeifaddrs(ifsaddrs); -#endif // WINDOWS_SYS - -#ifdef NET_DEBUG - std::list::iterator it; - std::cout << "getLocalAddresses(...) returning: <" ; - for(it = addrs.begin(); it != addrs.end(); ++it) - std::cout << sockaddr_storage_iptostring(*it) << ", "; - std::cout << ">" << std::endl; -#endif - - return !addrs.empty(); -} - - -/************************************************************* - * Socket Library Wrapper Functions - * to get over the crapness of the windows. - * - */ - -int unix_close(int fd) -{ - int ret; -/******************* WINDOWS SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - ret = close(fd); -#else - -#ifdef NET_DEBUG - std::cerr << "unix_close()" << std::endl; -#endif - ret = closesocket(fd); - /* translate error */ -#endif -/******************* WINDOWS SPECIFIC PART ******************/ - return ret; -} - -int unix_socket(int domain, int type, int protocol) -{ - int osock = socket(domain, type, protocol); - -#ifdef WINDOWS_SYS -#ifdef NET_DEBUG - std::cerr << "unix_socket()" << std::endl; -#endif // NET_DEBUG - - if ((unsigned) osock == INVALID_SOCKET) - { - // Invalidate socket Unix style. - osock = -1; - errno = WinToUnixError(WSAGetLastError()); - } -#endif // WINDOWS_SYS - - return osock; -} - - -int unix_fcntl_nonblock(int fd) -{ - int ret; - -/******************* OS SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - int flags = fcntl(fd, F_GETFL); - ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK); - -#ifdef NET_DEBUG - std::cerr << "unix_fcntl_nonblock():" << ret << " errno:" << errno << std::endl; -#endif - -#else - unsigned long int on = 1; - ret = ioctlsocket(fd, FIONBIO, &on); - -#ifdef NET_DEBUG - std::cerr << "unix_fcntl_nonblock()" << std::endl; -#endif - if (ret != 0) - { - /* store unix-style error - */ - ret = -1; - errno = WinToUnixError(WSAGetLastError()); - } -#endif -/******************* WINDOWS SPECIFIC PART ******************/ - return ret; -} - - -int unix_connect(int fd, const sockaddr_storage &serv_addr) -{ -#ifdef NET_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - int ret = connect( fd, (const struct sockaddr *) &serv_addr, - sizeof(struct sockaddr_in6) ); - -/******************* WINDOWS SPECIFIC PART ******************/ -#ifdef WINDOWS_SYS // WINDOWS - if (ret != 0) - { - errno = WinToUnixError(WSAGetLastError()); - ret = -1; - } -#endif -/******************* WINDOWS SPECIFIC PART ******************/ - return ret; -} - - -int unix_getsockopt_error(int sockfd, int *err) -{ - int ret; - *err = 1; -/******************* WINDOWS SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - socklen_t optlen = 4; - ret=getsockopt(sockfd, SOL_SOCKET, SO_ERROR, err, &optlen); -#else // WINDOWS_SYS - int optlen = 4; - ret=getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *) err, &optlen); - /* translate */ -#ifdef NET_DEBUG - std::cerr << "unix_getsockopt_error() returned: " << (int) err << std::endl; -#endif - if (*err != 0) - { - *err = WinToUnixError(*err); - } -#endif -/******************* WINDOWS SPECIFIC PART ******************/ - return ret; -} - -/******************* WINDOWS SPECIFIC PART ******************/ -#ifdef WINDOWS_SYS // ie WINDOWS. - -int WinToUnixError(int error) -{ -#ifdef NET_DEBUG - std::cerr << "WinToUnixError(" << error << ")" << std::endl; -#endif - switch(error) - { - case WSAEINPROGRESS: - return EINPROGRESS; - break; - case WSAEWOULDBLOCK: - return EINPROGRESS; - break; - case WSAENETUNREACH: - return ENETUNREACH; - break; - case WSAETIMEDOUT: - return ETIMEDOUT; - break; - case WSAEHOSTDOWN: - return EHOSTDOWN; - break; - case WSAECONNREFUSED: - return ECONNREFUSED; - break; - case WSAECONNRESET: - return ECONNRESET; - break; - default: -#ifdef NET_DEBUG - std::cerr << "WinToUnixError(" << error << ") Code Unknown!"; - std::cerr << std::endl; -#endif - break; - } - return ECONNREFUSED; /* sensible default? */ -} - -#endif -/******************* WINDOWS SPECIFIC PART ******************/ diff --git a/libretroshare/src/pqi/pqinetwork.h b/libretroshare/src/pqi/pqinetwork.h deleted file mode 100644 index e4238ee5e..000000000 --- a/libretroshare/src/pqi/pqinetwork.h +++ /dev/null @@ -1,112 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqinetwork.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_NETWORKING_HEADER -#define MRK_PQI_NETWORKING_HEADER - -#include - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - -#include -#include -#include -#include - -#include -#include - -//socket blocking/options. -#include -#include - -#else - -#include "util/rsnet.h" /* more generic networking header */ - -// Some Network functions that are missing from windows. -int inet_aton(const char *name, struct in_addr *addr); - -extern int errno; /* Define extern errno, to duplicate unix behaviour */ - -/* define the Unix Error Codes that we use... - * NB. we should make the same, but not necessary - */ -#define EAGAIN 11 - -#define EUSERS 87 - -#define EHOSTDOWN 112 - -#ifndef __MINGW64_VERSION_MAJOR -#define EWOULDBLOCK EAGAIN - -#define ENOTSOCK 88 - -#define EOPNOTSUPP 95 - -#define EADDRINUSE 98 -#define EADDRNOTAVAIL 99 -#define ENETDOWN 100 -#define ENETUNREACH 101 - -#define ECONNRESET 104 - -#define ETIMEDOUT 10060 // value from pthread.h -#define ECONNREFUSED 111 -#define EHOSTUNREACH 113 -#define EALREADY 114 -#define EINPROGRESS 115 -#endif - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - -#include -#include -#include - -// Same def - different functions... -void showSocketError(std::string &out); - -std::string socket_errorType(int err); - -bool getLocalAddresses(std::vector & addrs); - -/* universal socket interface */ - -int unix_close(int sockfd); -int unix_socket(int domain, int type, int protocol); -int unix_fcntl_nonblock(int sockfd); -int unix_connect(int sockfd, const sockaddr_storage& serv_addr); -int unix_getsockopt_error(int sockfd, int *err); - -#ifdef WINDOWS_SYS // WINDOWS -/******************* WINDOWS SPECIFIC PART ******************/ -int WinToUnixError(int error); -#endif - - - -#endif - diff --git a/libretroshare/src/pqi/pqiperson.cc b/libretroshare/src/pqi/pqiperson.cc deleted file mode 100644 index 62d5e5412..000000000 --- a/libretroshare/src/pqi/pqiperson.cc +++ /dev/null @@ -1,697 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiperson.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/pqi.h" -#include "pqi/pqiperson.h" -#include "pqi/pqipersongrp.h" -#include "pqi/pqissl.h" -#include "util/rsdebug.h" -#include "util/rsstring.h" -#include "retroshare/rspeers.h" - -static struct RsLog::logInfo pqipersonzoneInfo = {RsLog::Default, "pqiperson"}; -#define pqipersonzone &pqipersonzoneInfo - -/**** - * #define PERSON_DEBUG 1 - ****/ - -pqiperson::pqiperson(const RsPeerId& id, pqipersongrp *pg) : - PQInterface(id), mNotifyMtx("pqiperson-notify"), mPersonMtx("pqiperson"), - active(false), activepqi(NULL), inConnectAttempt(false),// waittimes(0), - pqipg(pg) {} // TODO: must check id! - -pqiperson::~pqiperson() -{ - RS_STACK_MUTEX(mPersonMtx); - - // clean up the childrens - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - { - pqiconnect *pc = (it->second); - delete pc; - } - kids.clear(); -} - -int pqiperson::SendItem(RsItem *i,uint32_t& serialized_size) -{ - RS_STACK_MUTEX(mPersonMtx); - - if(active) - { - // every outgoing item goes through this function, so try to not waste cpu cycles - // check if debug output is wanted, to avoid unecessary work - // getZoneLevel() locks a global mutex and does a lookup in a map or returns a default value - // (not sure if this is a performance problem) - if (PQL_DEBUG_BASIC <= pqipersonzoneInfo.lvl) - { - std::string out = "pqiperson::SendItem() Active: Sending On\n"; - i->print_string(out, 5); // this can be very expensive -#ifdef PERSON_DEBUG - std::cerr << out << std::endl; -#endif - pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out); - } - return activepqi -> SendItem(i,serialized_size); - } - else - { - if (PQL_DEBUG_BASIC <= pqipersonzoneInfo.lvl) - { - std::string out = "pqiperson::SendItem()"; - out += " Not Active: Used to put in ToGo Store\n"; - out += " Now deleting..."; - pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out); - } - delete i; - } - return 0; // queued. -} - -RsItem *pqiperson::GetItem() -{ - RS_STACK_MUTEX(mPersonMtx); - - if (active) - return activepqi->GetItem(); - // else not possible. - return NULL; -} - -bool pqiperson::RecvItem(RsItem *item) -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::RecvItem()" << std::endl; -#endif - - return pqipg->recvItem((RsRawItem *) item); -} - - -int pqiperson::status() -{ - RS_STACK_MUTEX(mPersonMtx); - - if (active) - return activepqi -> status(); - return -1; -} - -int pqiperson::receiveHeartbeat() -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::receiveHeartbeat() from peer : " - << PeerId().toStdString() << std::endl; -#endif - - RS_STACK_MUTEX(mPersonMtx); - lastHeartbeatReceived = time(NULL); - - return 1; -} - -int pqiperson::tick() -{ - int activeTick = 0; - - { - RS_STACK_MUTEX(mPersonMtx); - -#ifdef PERSON_DEBUG - if(active) - { - std::cerr << "pqiperson: peer=" << (activepqi? (activepqi->PeerId()): (RsPeerId())) <<", active=" << active << ", last HB=" << time(NULL) - lastHeartbeatReceived << " secs ago." ; - if(lastHeartbeatReceived==0) - std::cerr << "!!!!!!!" << std::endl; - else - std::cerr << std::endl; - } -#endif - - //if lastHeartbeatReceived is 0, it might be not activated so don't do a net reset. - if ( active && time(NULL) > lastHeartbeatReceived + HEARTBEAT_REPEAT_TIME * 20) - { - int ageLastIncoming = time(NULL) - activepqi->getLastIncomingTS(); - -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::tick() WARNING No heartbeat from: " - << PeerId().toStdString() << " LastHeartbeat was: " - << time(NULL) - lastHeartbeatReceived - << "secs ago LastIncoming was: " << ageLastIncoming - << "secs ago" << std::endl; -#endif - - if (ageLastIncoming > 60) // Check timeout - { - std::cerr << "pqiperson::tick() " << PeerId().toStdString() << " No Heartbeat & No Packets for 60 secs -> assume dead." << std::endl; - this->reset_locked(); - } - - } - - - { -#ifdef PERSON_DEBUG - std::string statusStr = " inactive "; - if (active) - statusStr = " active "; - - std::string connectStr = " Not Connecting "; - if (inConnectAttempt) - connectStr = " In Connection Attempt "; - - std::cerr << "pqiperson::tick() Id: " << PeerId().toStdString() - << "activepqi: " << activepqi << " inConnectAttempt:" - << connectStr << std::endl; -#endif - - // tick the children. - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - { - if (0 < (it->second)->tick()) - activeTick = 1; -#ifdef PERSON_DEBUG - std::cerr << "\tTicking Child: "<< it->first << std::endl; -#endif - } - } - } - - // handle Notify Events that were generated. - processNotifyEvents(); - - return activeTick; -} - -// callback function for the child - notify of a change. -// This is only used for out-of-band info.... -// otherwise could get dangerous loops. -// - Actually, now we have - must store and process later. -int pqiperson::notifyEvent(NetInterface *ni, int newState, - const sockaddr_storage &remote_peer_address) -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::notifyEvent() adding event to Queue. newState=" - << newState << " from IP = " - << sockaddr_storage_tostring(remote_peer_address) << std::endl; -#endif - - if (mPersonMtx.trylock()) - { - handleNotifyEvent_locked(ni, newState, remote_peer_address); - mPersonMtx.unlock(); - return 1; - } - - RS_STACK_MUTEX(mNotifyMtx); - mNotifyQueue.push_back(NotifyData(ni, newState, remote_peer_address)); - return 1; -} - -void pqiperson::processNotifyEvents() -{ - NetInterface *ni; - int state; - sockaddr_storage addr; - - while(1) // While there is notification to handle - { - { - RS_STACK_MUTEX(mNotifyMtx); - - if(mNotifyQueue.empty()) - return; - - NotifyData &data = mNotifyQueue.front(); - ni = data.mNi; - state = data.mState; - addr = data.mAddr; - - mNotifyQueue.pop_front(); - } - - RS_STACK_MUTEX(mPersonMtx); - handleNotifyEvent_locked(ni, state, addr); - } -} - - -int pqiperson::handleNotifyEvent_locked(NetInterface *ni, int newState, - const sockaddr_storage &remote_peer_address) -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::handleNotifyEvent_locked() Id: " - << PeerId().toStdString() << " Message: " << newState - << " from: " << ni << std::endl; - int i = 0; -#endif - - /* find the pqi, */ - pqiconnect *pqi = NULL; - uint32_t type = 0; - std::map::iterator it; - - /* start again */ - for(it = kids.begin(); it != kids.end(); ++it) - { -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::handleNotifyEvent_locked() Kid# " << i - << " of " << kids.size() << " type: " << it->first - << " in_ni: " << ni << std::endl; - ++i; -#endif - - if ((it->second)->thisNetInterface(ni)) - { - pqi = (it->second); - type = (it->first); - } - } - - if (!pqi) - { - std::cerr << "pqiperson::handleNotifyEvent_locked Unknown Event Source!" - << std::endl; - return -1; - } - - - switch(newState) - { - case CONNECT_RECEIVED: - case CONNECT_SUCCESS: - { - - /* notify */ - if (pqipg) - { - pqissl *ssl = dynamic_cast(ni); - if(ssl) - pqipg->notifyConnect(PeerId(), type, true, ssl->actAsServer(), remote_peer_address); - else - pqipg->notifyConnect(PeerId(), type, true, false, remote_peer_address); - } - - if ((active) && (activepqi != pqi)) // already connected - trouble - { - // TODO: 2015/12/19 Is this block dead code? - - std::cerr << "pqiperson::handleNotifyEvent_locked Id: " - << PeerId().toStdString() << " CONNECT_SUCCESS+active->" - << "activing new connection, shutting others" - << std::endl; - - // This is the RESET that's killing the connections..... - //activepqi -> reset(); - // this causes a recursive call back into this fn. - // which cleans up state. - // we only do this if its not going to mess with new conn. - } - - /* now install a new one. */ - { -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::handleNotifyEvent_locked Id: " - << PeerId().toStdString() << " CONNECT_SUCCESS->marking " - << "so! (resetting others)" << std::endl; -#endif - - // mark as active. - active = true; - lastHeartbeatReceived = time(NULL) ; - activepqi = pqi; - inConnectAttempt = false; - - // STARTUP THREAD - activepqi->start("pqi " + PeerId().toStdString().substr(0, 11)); - - // reset all other children (clear up long UDP attempt) - for(it = kids.begin(); it != kids.end(); ++it) - if (!(it->second)->thisNetInterface(ni)) - it->second->reset(); - return 1; - } - break; - } - case CONNECT_UNREACHABLE: - case CONNECT_FIREWALLED: - case CONNECT_FAILED: - { - if (active && (activepqi == pqi)) - { -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::handleNotifyEvent_locked Id: " - << PeerId().toStdString() - << " CONNECT_FAILED->marking so!" << std::endl; -#endif - - activepqi->askForStop(); // STOP THREAD. - active = false; - activepqi = nullptr; - } -#ifdef PERSON_DEBUG - else - std::cerr << "pqiperson::handleNotifyEvent_locked Id: " - << PeerId().toStdString() + " CONNECT_FAILED-> from " - << "an unactive connection, don't flag the peer as " - << "not connected, just try next attempt !" << std::endl; -#endif - /* notify up */ - if (pqipg) - pqipg->notifyConnect(PeerId(), type, false, false, remote_peer_address); - - return 1; - } - default: - return -1; - } -} - -/***************** Not PQInterface Fns ***********************/ - -int pqiperson::reset() -{ - RS_STACK_MUTEX(mPersonMtx); - return reset_locked(); -} - -int pqiperson::reset_locked() -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::reset_locked() resetting all pqiconnect for Id: " - << PeerId().toStdString() << std::endl; -#endif - - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - { - it->second->askForStop(); // STOP THREAD. - (it->second) -> reset(); - } - - activepqi = NULL; - active = false; - lastHeartbeatReceived = 0; - - return 1; -} - -int pqiperson::fullstopthreads() -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::fullstopthreads() for Id: " - << PeerId().toStdString() << std::endl; -#endif - - RS_STACK_MUTEX(mPersonMtx); - - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - (it->second)->fullstop(); // WAIT FOR THREAD TO STOP. - - activepqi = NULL; - active = false; - lastHeartbeatReceived = 0; - - return 1; -} - -int pqiperson::addChildInterface(uint32_t type, pqiconnect *pqi) -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::addChildInterface() : Id " - << PeerId().toStdString() << " " << type << std::endl; -#endif - - RS_STACK_MUTEX(mPersonMtx); - - kids[type] = pqi; - return 1; -} - -/***************** PRIVATE FUNCTIONS ***********************/ -// functions to iterate over the connects and change state. - - -int pqiperson::listen() -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::listen() Id: " + PeerId().toStdString() << std::endl; -#endif - - RS_STACK_MUTEX(mPersonMtx); - - if (!active) - { - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - (it->second)->listen(); - } - return 1; -} - - -int pqiperson::stoplistening() -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::stoplistening() Id: " + PeerId().toStdString() - << std::endl; -#endif - - RS_STACK_MUTEX(mPersonMtx); - - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - (it->second)->stoplistening(); - - return 1; -} - -int pqiperson::connect(uint32_t type, const sockaddr_storage &raddr, - const sockaddr_storage &proxyaddr, - const sockaddr_storage &srcaddr, - uint32_t delay, uint32_t period, uint32_t timeout, - uint32_t flags, uint32_t bandwidth, - const std::string &domain_addr, uint16_t domain_port) -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::connect() Id: " << PeerId().toStdString() - << " type: " << type << " addr: " - << sockaddr_storage_tostring(raddr) << " proxyaddr: " - << sockaddr_storage_tostring(proxyaddr) << " srcaddr: " - << sockaddr_storage_tostring(srcaddr) << " delay: " << delay - << " period: " << period << " timeout: " << timeout << " flags: " - << flags << " bandwidth: " << bandwidth << std::endl; -#endif - - RS_STACK_MUTEX(mPersonMtx); - - std::map::iterator it; - - it = kids.find(type); - if (it == kids.end()) - { - /* notify of fail! */ - pqipg->notifyConnect(PeerId(), type, false, false, raddr); - return 0; - } - - pqiconnect *pqi = it->second; - -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::connect() resetting for new connection attempt" << std::endl; -#endif - - /* set the parameters */ - pqi->reset(); - -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::connect() clearing rate cap" << std::endl; -#endif - setRateCap_locked(0,0); - -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::connect() setting connect_parameters" << std::endl; -#endif - - // These two are universal. - pqi->connect_parameter(NET_PARAM_CONNECT_DELAY, delay); - pqi->connect_parameter(NET_PARAM_CONNECT_TIMEOUT, timeout); - - // these 5 are only used by UDP connections. - pqi->connect_parameter(NET_PARAM_CONNECT_PERIOD, period); - pqi->connect_parameter(NET_PARAM_CONNECT_FLAGS, flags); - pqi->connect_parameter(NET_PARAM_CONNECT_BANDWIDTH, bandwidth); - - pqi->connect_additional_address(NET_PARAM_CONNECT_PROXY, proxyaddr); - pqi->connect_additional_address(NET_PARAM_CONNECT_SOURCE, srcaddr); - - // These are used by Proxy/Hidden - pqi->connect_parameter(NET_PARAM_CONNECT_DOMAIN_ADDRESS, domain_addr); - pqi->connect_parameter(NET_PARAM_CONNECT_REMOTE_PORT, domain_port); - - pqi->connect(raddr); - - // flag if we started a new connectionAttempt. - inConnectAttempt = true; - - return 1; -} - - -void pqiperson::getRates(RsBwRates &rates) -{ - RS_STACK_MUTEX(mPersonMtx); - - // get the rate from the active one. - if ((!active) || (activepqi == NULL)) - return; - - activepqi->getRates(rates); -} - -int pqiperson::gatherStatistics(std::list& out_lst, - std::list& in_lst) -{ - RS_STACK_MUTEX(mPersonMtx); - - // Get the rate from the active one. - if( (!active) || (activepqi == NULL) ) - return 0 ; - - return activepqi->gatherStatistics(out_lst, in_lst); -} - -int pqiperson::getQueueSize(bool in) -{ - RS_STACK_MUTEX(mPersonMtx); - - // get the rate from the active one. - if ((!active) || (activepqi == NULL)) - return 0; - - return activepqi->getQueueSize(in); -} - -bool pqiperson::getCryptoParams(RsPeerCryptoParams & params) -{ - RS_STACK_MUTEX(mPersonMtx); - - if(active && activepqi != NULL) - return activepqi->getCryptoParams(params); - else - { - params.connexion_state = 0; - params.cipher_name.clear(); - - return false ; - } -} - -bool pqiconnect::getCryptoParams(RsPeerCryptoParams & params) -{ - pqissl *ssl = dynamic_cast(ni); - - if(ssl != NULL) - { - ssl->getCryptoParams(params); - return true; - } - else - { - params.connexion_state = 0 ; - params.cipher_name.clear() ; - return false ; - } -} - -float pqiperson::getRate(bool in) -{ - RS_STACK_MUTEX(mPersonMtx); - - // get the rate from the active one. - if ((!active) || (activepqi == NULL)) - return 0; - - return activepqi -> getRate(in); -} - -uint64_t pqiperson::getTraffic(bool in) -{ - if ((!active) || (activepqi == NULL)) - return 0; - return activepqi -> getTraffic(in); -} - -void pqiperson::setMaxRate(bool in, float val) -{ - RS_STACK_MUTEX(mPersonMtx); - - // set to all of them. (and us) - PQInterface::setMaxRate(in, val); - // clean up the children. - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - (it->second) -> setMaxRate(in, val); -} - -void pqiperson::setRateCap(float val_in, float val_out) -{ - // This methods might be called all the way down from pqiperson::tick() down - // to pqissludp while completing a UDP connexion, causing a deadlock. - // - // We need to make sure the mutex is not already locked by current thread. If so, we call the - // locked version directly if not, we lock, call, and unlock, possibly waiting if the - // lock is already acquired by another thread. - // - // The lock cannot be locked by the same thread between the first test and - // the "else" statement, so there is no possibility for this code to fail. - // - // We could actually put that code in RsMutex::lock()? - // TODO: 2015/12/19 This code is already in RsMutex::lock() but is guarded - // by RSTHREAD_SELF_LOCKING_GUARD which is specifically unset in the header - // Why is that code guarded? Do it have an impact on performance? - // Or we should not get in the situation of trying to relock the mutex on - // the same thread NEVER? - - if(pthread_equal(mPersonMtx.owner(), pthread_self())) - // Unlocked, or already locked by same thread - setRateCap_locked(val_in, val_out); - else - { - // Lock was free or locked by different thread => wait. - RS_STACK_MUTEX(mPersonMtx); - setRateCap_locked(val_in, val_out); - } -} - -void pqiperson::setRateCap_locked(float val_in, float val_out) -{ - // set to all of them. (and us) - PQInterface::setRateCap(val_in, val_out); - // clean up the children. - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - (it->second)->setRateCap(val_in, val_out); -} diff --git a/libretroshare/src/pqi/pqiperson.h b/libretroshare/src/pqi/pqiperson.h deleted file mode 100644 index 59bae7834..000000000 --- a/libretroshare/src/pqi/pqiperson.h +++ /dev/null @@ -1,175 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiperson.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_PERSON_HEADER -#define MRK_PQI_PERSON_HEADER - - -#include -#include "pqi/pqi.h" -#include "util/rsnet.h" - -#include - -class pqiperson; -struct RsPeerCryptoParams; - -static const int CONNECT_RECEIVED = 1; -static const int CONNECT_SUCCESS = 2; -static const int CONNECT_UNREACHABLE = 3; -static const int CONNECT_FIREWALLED = 4; -static const int CONNECT_FAILED = 5; - -static const rstime_t HEARTBEAT_REPEAT_TIME = 5; - -#include "pqi/pqiqosstreamer.h" -#include "pqi/pqithreadstreamer.h" - -class pqiconnect : public pqiQoSstreamer, public NetInterface -{ -public: - pqiconnect(PQInterface *parent, RsSerialiser *rss, NetBinInterface *ni_in) : - pqiQoSstreamer(parent, rss, ni_in->PeerId(), ni_in, 0), // pqistreamer will cleanup NetInterface. - NetInterface(NULL, ni_in->PeerId()), // No need for callback - ni(ni_in) {} - - virtual ~pqiconnect() {} - virtual bool getCryptoParams(RsPeerCryptoParams& params); - - // presents a virtual NetInterface -> passes to ni. - virtual int connect(const struct sockaddr_storage &raddr) { return ni->connect(raddr); } - virtual int listen() { return ni->listen(); } - virtual int stoplistening() { return ni->stoplistening(); } - virtual int reset() { pqistreamer::reset(); return ni->reset(); } - virtual int disconnect() { return reset() ; } - virtual bool connect_parameter(uint32_t type, uint32_t value) { return ni->connect_parameter(type, value);} - virtual bool connect_parameter(uint32_t type, const std::string &value) { return ni->connect_parameter(type, value);} - virtual bool connect_additional_address(uint32_t type, const struct sockaddr_storage &addr) { return ni->connect_additional_address(type, addr); } - virtual int getConnectAddress(struct sockaddr_storage &raddr){ return ni->getConnectAddress(raddr); } - - // get the contact from the net side! - virtual const RsPeerId& PeerId() { return ni->PeerId(); } - - // to check if our interface. - virtual bool thisNetInterface(NetInterface *ni_in) { return (ni_in == ni); } - -protected: - NetBinInterface *ni; -}; - - -class pqipersongrp; - -class NotifyData -{ -public: - NotifyData() : mNi(NULL), mState(0) - { - sockaddr_storage_clear(mAddr); - } - - NotifyData(NetInterface *ni, int state, const sockaddr_storage &addr) : - mNi(ni), mState(state), mAddr(addr) {} - - NetInterface *mNi; - int mState; - sockaddr_storage mAddr; -}; - - -class pqiperson: public PQInterface -{ -public: - pqiperson(const RsPeerId& id, pqipersongrp *ppg); - virtual ~pqiperson(); // must clean up children. - - // control of the connection. - int reset(); - int listen(); - int stoplistening(); - - int connect(uint32_t type, const sockaddr_storage &raddr, - const sockaddr_storage &proxyaddr, const sockaddr_storage &srcaddr, - uint32_t delay, uint32_t period, uint32_t timeout, uint32_t flags, - uint32_t bandwidth, const std::string &domain_addr, uint16_t domain_port); - - int fullstopthreads(); - int receiveHeartbeat(); - - // add in connection method. - int addChildInterface(uint32_t type, pqiconnect *pqi); - - virtual bool getCryptoParams(RsPeerCryptoParams&); - - // The PQInterface interface. - virtual int SendItem(RsItem *,uint32_t& serialized_size); - virtual int SendItem(RsItem *item) - { - std::cerr << "Warning pqiperson::sendItem(RsItem*) should not be called." - << "Plz call SendItem(RsItem *,uint32_t& serialized_size) instead." - << std::endl; - uint32_t serialized_size; - return SendItem(item, serialized_size); - } - - virtual RsItem *GetItem(); - virtual bool RecvItem(RsItem *item); - - virtual int status(); - virtual int tick(); - - // overloaded callback function for the child - notify of a change. - virtual int notifyEvent(NetInterface *ni, int event, const struct sockaddr_storage &addr); - - // PQInterface for rate control overloaded.... - virtual int getQueueSize(bool in); - virtual void getRates(RsBwRates &rates); - virtual float getRate(bool in); - virtual uint64_t getTraffic(bool in); - virtual void setMaxRate(bool in, float val); - virtual void setRateCap(float val_in, float val_out); - virtual int gatherStatistics(std::list& outqueue_lst, - std::list& inqueue_lst); - -private: - void processNotifyEvents(); - int handleNotifyEvent_locked(NetInterface *ni, int event, - const sockaddr_storage &addr); - - RsMutex mNotifyMtx; // LOCKS Notify Queue - std::list mNotifyQueue; - - RsMutex mPersonMtx; // LOCKS below - - int reset_locked(); - - void setRateCap_locked(float val_in, float val_out); - - std::map kids; - bool active; - pqiconnect *activepqi; - bool inConnectAttempt; - //int waittimes; - rstime_t lastHeartbeatReceived; // use to track connection failure - pqipersongrp *pqipg; /* parent for callback */ -}; - -#endif diff --git a/libretroshare/src/pqi/pqipersongrp.cc b/libretroshare/src/pqi/pqipersongrp.cc deleted file mode 100644 index 7146be7de..000000000 --- a/libretroshare/src/pqi/pqipersongrp.cc +++ /dev/null @@ -1,721 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqipersongrp.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/pqipersongrp.h" -#include "pqi/p3linkmgr.h" -#include "util/rsdebug.h" -#include "util/rsprint.h" -#include "serialiser/rsserializer.h" - -#include - -static struct RsLog::logInfo pqipersongrpzoneInfo = {RsLog::Default, "pqipersongrp"}; -#define pqipersongrpzone &pqipersongrpzoneInfo - -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections -#include "retroshare/rsinit.h" -static std::list waitingIds; -#define MAX_CONNECT_COUNT 3 -/////////////////////////////////////////////////////////// -#endif - -/**** - *#define PGRP_DEBUG 1 - *#define PGRP_DEBUG_LOG 1 - ****/ - -#define DEFAULT_DOWNLOAD_KB_RATE (200.0) -#define DEFAULT_UPLOAD_KB_RATE (50.0) - -/* MUTEX NOTES: - * Functions like GetRsRawItem() lock itself (pqihandler) and - * likewise ServiceServer and ConfigMgr mutex themselves. - * This means the only things we need to worry about are: - * pqilistener and when accessing pqihandlers data. - */ - - - // New speedy recv. -bool pqipersongrp::RecvRsRawItem(RsRawItem *item) -{ - std::cerr << "pqipersongrp::RecvRsRawItem()"; - std::cerr << std::endl; - - p3ServiceServer::recvItem(item); - - return true; -} - - - -#ifdef TO_BE_REMOVED -// handle the tunnel services. -int pqipersongrp::tickServiceRecv() -{ - RsRawItem *pqi = NULL; - int i = 0; - - pqioutput(PQL_DEBUG_ALL, pqipersongrpzone, "pqipersongrp::tickServiceRecv()"); - - //p3ServiceServer::tick(); - - while(NULL != (pqi = GetRsRawItem())) - { - static int ntimes=0 ; - if(++ntimes < 20) - { - std::cerr << "pqipersongrp::tickServiceRecv() GetRsRawItem()"; - std::cerr << " should never happen anymore! item data=" << RsUtil::BinToHex((char*)pqi->getRawData(),pqi->getRawLength()) ; - std::cerr << std::endl; - } - - ++i; - pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, - "pqipersongrp::tickServiceRecv() Incoming TunnelItem"); - recvItem(pqi); - } - - if (0 < i) - { - return 1; - } - return 0; -} -#endif - -// handle the tunnel services. - -// Improvements: -// This function is no longer necessary, and data is pushed directly to pqihandler. - -#ifdef TO_BE_REMOVED -int pqipersongrp::tickServiceSend() -{ - RsRawItem *pqi = NULL; - int i = 0; - - pqioutput(PQL_DEBUG_ALL, pqipersongrpzone, "pqipersongrp::tickServiceSend()"); - - p3ServiceServer::tick(); - - while(NULL != (pqi = outgoing())) /* outgoing has own locking */ - { - ++i; - pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, - "pqipersongrp::tickTunnelServer() OutGoing RsItem"); - - SendRsRawItem(pqi); /* Locked by pqihandler */ - } - if (0 < i) - { - return 1; - } - return 0; -} - -#endif - - - // init -pqipersongrp::pqipersongrp(p3ServiceControl *ctrl, unsigned long flags) - :pqihandler(), p3ServiceServer(this, ctrl), pqil(NULL), pqilMtx("pqipersongrp"), initFlags(flags) -{ -} - - -int pqipersongrp::tick() -{ - /* could limit the ticking of listener / tunnels to 1/sec... - * but not to important. - */ - - { - RsStackMutex stack(pqilMtx); /******* LOCKED MUTEX **********/ - if (pqil) - { - pqil -> tick(); - } - } /* UNLOCKED */ - - int i = 0; - -#ifdef TO_BE_REMOVED - if (tickServiceSend()) - { - i = 1; -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::tick() moreToTick from tickServiceSend()" << std::endl; -#endif - } - if (pqihandler::tick()) /* does Send/Recv */ - { - i = 1; -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::tick() moreToTick from pqihandler::tick()" << std::endl; -#endif - } - if (tickServiceRecv()) - { - i = 1; -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::tick() moreToTick from tickServiceRecv()" << std::endl; -#endif - } -#endif - - if(pqihandler::tick()) - i=1; - - p3ServiceServer::tick(); - - return i; -} - -int pqipersongrp::status() -{ - { - RsStackMutex stack(pqilMtx); /******* LOCKED MUTEX **********/ - if (pqil) - { - pqil -> status(); - } - } /* UNLOCKED */ - - return pqihandler::status(); -} - - -/* Initialise pqilistener */ -int pqipersongrp::init_listener() -{ - /* extract our information from the p3ConnectMgr */ - if (initFlags & PQIPERSON_NO_LISTENER) - { - RsStackMutex stack(pqilMtx); /******* LOCKED MUTEX **********/ - pqil = NULL; - } - else - { - /* extract details from - */ - struct sockaddr_storage laddr; - mLinkMgr->getLocalAddress(laddr); - - RsStackMutex stack(pqilMtx); /******* LOCKED MUTEX **********/ - pqil = locked_createListener(laddr); - } - return 1; -} - -bool pqipersongrp::resetListener(const struct sockaddr_storage &local) -{ - #ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::resetListener()" << std::endl; - #endif - - // stop it, - // change the address. - // restart. - - RsStackMutex stack(pqilMtx); /******* LOCKED MUTEX **********/ - - if (pqil != NULL) - { - #ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::resetListener() haveListener" << std::endl; - #endif - - pqil -> resetlisten(); - pqil -> setListenAddr(local); - pqil -> setuplisten(); - - #ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::resetListener() done!" << std::endl; - #endif - - } - return 1; -} - -void pqipersongrp::statusChange(const std::list &plist) -{ - - /* iterate through, only worry about the friends */ - std::list::const_iterator it; - for(it = plist.begin(); it != plist.end(); ++it) - { - if (it->state & RS_PEER_S_FRIEND) - { - /* now handle add/remove */ - if ((it->actions & RS_PEER_NEW) - || (it->actions & RS_PEER_MOVED)) - { - addPeer(it->id); - } - - if (it->actions & RS_PEER_CONNECT_REQ) - { - connectPeer(it->id); - } - } - else /* Not Friend */ - { - if (it->actions & RS_PEER_MOVED) - { - removePeer(it->id); - } - } - } -} - -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections -void pqipersongrp::statusChanged() -{ -#warning "Windows connection limited hacked together - please fix" - - if (RsInit::isWindowsXP() == false) { - /* the problem only exist in Windows XP */ - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - waitingIds.clear(); - return; - } - - { - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - if (waitingIds.empty()) - { - /* nothing to do */ - return; - } - } - - /* check for active connections and start waiting id's */ - long connect_count = 0; - std::list toConnect; - - { - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - - /* get address from p3connmgr */ - if (!mLinkMgr) { - return; - } - - /* check for active connections and start waiting id's */ - std::list peers; - mLinkMgr->getFriendList(peers); - - /* count connection attempts */ - std::list::iterator peer; - for (peer = peers.begin(); peer != peers.end(); ++peer) { - peerConnectState state; - if (mLinkMgr->getFriendNetStatus(*peer, state) == false) { - continue; - } - - if (state.inConnAttempt) { - connect_count++; - if (connect_count >= MAX_CONNECT_COUNT) { -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::statusChanged() Too many connections due to windows limitations. There are " << waitingIds.size() << " waiting connections." << std::endl; -#endif - return; - } - } - } - -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::statusChanged() There are "; - std::cerr << connect_count << " connection attempts and " << waitingIds.size(); - std::cerr << " waiting connections. Can start "; - std::cerr << (MAX_CONNECT_COUNT - connect_count) << " connection attempts."; - std::cerr << std::endl; -#endif - - /* start some waiting id's */ - for (int i = connect_count; i < MAX_CONNECT_COUNT; i++) - { - if (waitingIds.empty()) { - break; - } - RsPeerId waitingId = waitingIds.front(); - waitingIds.pop_front(); - -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::statusChanged() id: " << waitingId << " connect peer"; - std::cerr << std::endl; -#endif - - toConnect.push_back(waitingId); - } - } /* UNLOCKED */ - - std::list::iterator cit; - for(cit = toConnect.begin(); cit != toConnect.end(); ++cit) - { - connectPeer(*cit, true); - } -} -/////////////////////////////////////////////////////////// -#endif - -bool pqipersongrp::getCryptoParams(const RsPeerId& id,RsPeerCryptoParams& params) -{ - RsStackMutex stack(coreMtx); /******* LOCKED MUTEX **********/ - - std::map::iterator it = mods.find(id) ; - - if(it == mods.end()) - return false ; - - return it->second->pqi->getCryptoParams(params) ; - - //return locked_getCryptoParams(id,params) ; -} - -int pqipersongrp::addPeer(const RsPeerId& id) -{ - pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, "pqipersongrp::addPeer() PeerId: " + id.toStdString()); - - std::cerr << "pqipersongrp::addPeer() id: " << id; - std::cerr << std::endl; -#ifdef PGRP_DEBUG -#endif - - SearchModule *sm = NULL; - - { - // The Mutex is required here as pqiListener is not thread-safe. - RsStackMutex stack(pqilMtx); /******* LOCKED MUTEX **********/ - pqiperson *pqip = locked_createPerson(id, pqil); - - // attach to pqihandler - sm = new SearchModule(); - sm -> peerid = id; - sm -> pqi = pqip; - - // reset it to start it working. -#ifdef PGRP_DEBUG_LOG - pqioutput(PQL_WARNING, pqipersongrpzone, "pqipersongrp::addPeer() => reset() called to initialise new person"); -#endif - pqip -> reset(); - pqip -> listen(); - - } /* UNLOCKED */ - - return AddSearchModule(sm); -} - - -int pqipersongrp::removePeer(const RsPeerId& id) -{ - std::map::iterator it; - -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::removePeer() id: " << id; - std::cerr << std::endl; -#endif - - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - - it = mods.find(id); - if (it != mods.end()) - { - SearchModule *mod = it->second; - pqiperson *p = (pqiperson *) mod -> pqi; - p -> stoplistening(); - pqioutput(PQL_WARNING, pqipersongrpzone, "pqipersongrp::removePeer() => reset() called before deleting person"); - p -> reset(); - p -> fullstopthreads(); - delete p; - mods.erase(it); - } - else - { - std::cerr << " pqipersongrp::removePeer() ERROR doesn't exist! id: " << id; - std::cerr << std::endl; - } - return 1; -} - -int pqipersongrp::tagHeartbeatRecvd(const RsPeerId& id) -{ - std::map::iterator it; - -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::tagHeartbeatRecvd() id: " << id; - std::cerr << std::endl; -#endif - - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - - it = mods.find(id); - if (it != mods.end()) - { - SearchModule *mod = it->second; - pqiperson *p = (pqiperson *) mod -> pqi; - p->receiveHeartbeat(); - return 1; - } - return 0; -} - - - - - - -int pqipersongrp::connectPeer(const RsPeerId& id -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections - , bool bConnect /*= false*/ -/////////////////////////////////////////////////////////// -#endif - ) -{ - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - - if (!mLinkMgr) - return 0; - - if (id == mLinkMgr->getOwnId()) - { -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::connectPeer() ERROR Failed, connecting to own id." << std::endl; -#endif - return 0; - } - std::map::iterator it; - it = mods.find(id); - if (it == mods.end()) - { - return 0; - } - /* get the connect attempt details from the p3connmgr... */ - SearchModule *mod = it->second; - pqiperson *p = (pqiperson *) mod -> pqi; - -#ifdef WINDOWS_SYS - /////////////////////////////////////////////////////////// - // hack for too many connections - - if (RsInit::isWindowsXP()) { - /* the problem only exist in Windows XP */ - if (bConnect == false) { - /* check for id is waiting */ - if (std::find(waitingIds.begin(), waitingIds.end(), id) != waitingIds.end()) { - /* id is waiting for a connection */ -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() id: " << id << " is already waiting "; - std::cerr << std::endl; -#endif - return 0; - } - - /* check for connection type of the next connect attempt */ - peerConnectState state; - if (mLinkMgr->getFriendNetStatus(id, state) == false) { -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() id: " << id << " No friend net status"; - std::cerr << std::endl; -#endif - return 0; - } - if (state.connAddrs.size() < 1) { -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() id: " << id << " No existing connect addresses"; - std::cerr << std::endl; -#endif - return 0; - } - const peerConnectAddress ¤tConnAddrAttempt = state.connAddrs.front(); - if (currentConnAddrAttempt.type & RS_NET_CONN_TCP_ALL) { -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() id: " << id << " added to the waiting list"; - std::cerr << std::endl; -#endif - /* TCP connect, add id to waiting */ - waitingIds.push_back(id); - - /* wait for call to connectPeer with empty id */ - return 0; - } - - /* try all other types of connect directly */ - -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() id: " << id << " connect directly without wait"; - std::cerr << std::endl; -#endif - } - - /* remove id from waiting */ - waitingIds.remove(id); - } - - /////////////////////////////////////////////////////////// -#endif - - struct sockaddr_storage addr; - uint32_t delay; - uint32_t period; - uint32_t timeout; - uint32_t type; - uint32_t flags = 0 ; - - struct sockaddr_storage proxyaddr; - struct sockaddr_storage srcaddr; - uint32_t bandwidth; - std::string domain_addr; - uint16_t domain_port; - - if (!mLinkMgr->connectAttempt(id, addr, proxyaddr, srcaddr, delay, period, type, flags, bandwidth, domain_addr, domain_port)) - { -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() No Net Address"; - std::cerr << std::endl; -#endif - return 0; - } - -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() connectAttempt data id: " << id; - std::cerr << " addr: " << sockaddr_storage_tostring(addr); - std::cerr << " delay: " << delay; - std::cerr << " period: " << period; - std::cerr << " type: " << type; - std::cerr << " flags: " << flags; - std::cerr << " domain_addr: " << domain_addr; - std::cerr << " domain_port: " << domain_port; - std::cerr << std::endl; -#endif - - - uint32_t ptype; - if (type & RS_NET_CONN_TCP_ALL) - { - switch (type) { - case RS_NET_CONN_TCP_HIDDEN_TOR: - ptype = PQI_CONNECT_HIDDEN_TOR_TCP; - timeout = RS_TCP_HIDDEN_TIMEOUT_PERIOD; - break; - case RS_NET_CONN_TCP_HIDDEN_I2P: - ptype = PQI_CONNECT_HIDDEN_I2P_TCP; - timeout = RS_TCP_HIDDEN_TIMEOUT_PERIOD; - break; - default: - ptype = PQI_CONNECT_TCP; - timeout = RS_TCP_STD_TIMEOUT_PERIOD; - break; - } -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() connecting with TCP: Timeout :" << timeout; - std::cerr << std::endl; -#endif - } - else if (type & RS_NET_CONN_UDP_ALL) - { - ptype = PQI_CONNECT_UDP; - timeout = period + RS_UDP_STD_TIMEOUT_PERIOD; // Split of UNCERTAINTY + TIME FOR TTL to RISE to Connection. -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() connecting with UDP: Timeout :" << timeout; - std::cerr << std::endl; -#endif - } - else - { -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() Ignoring Unknown Type:" << type; - std::cerr << std::endl; -#endif - return 0; - } - - p->connect(ptype, addr, proxyaddr, srcaddr, delay, period, timeout, flags, bandwidth, domain_addr, domain_port); - - return 1; -} - -bool pqipersongrp::notifyConnect(const RsPeerId& id, uint32_t ptype, bool success, bool isIncomingConnection, const struct sockaddr_storage &raddr) -{ - uint32_t type = 0; - if (ptype == PQI_CONNECT_TCP) - { - type = RS_NET_CONN_TCP_ALL; - } - else if (ptype == PQI_CONNECT_UDP) - { - type = RS_NET_CONN_UDP_ALL; - } - - if (mLinkMgr) - mLinkMgr->connectResult(id, success, isIncomingConnection, type, raddr); - - return (NULL != mLinkMgr); -} - -/******************************** DUMMY Specific features ***************************/ - -#include "pqi/pqibin.h" - -pqilistener * pqipersongrpDummy::locked_createListener(const struct sockaddr_storage & /*laddr*/) -{ - pqilistener *listener = new pqilistener(); - return listener; -} - - -pqiperson * pqipersongrpDummy::locked_createPerson(const RsPeerId& id, pqilistener * /*listener*/) -{ - pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, "pqipersongrpDummy::createPerson() PeerId: " + id.toStdString()); - - pqiperson *pqip = new pqiperson(id, this); - - // TCP - NetBinDummy *d1 = new NetBinDummy(pqip, id, PQI_CONNECT_TCP); - - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsRawSerialiser()); - - pqiconnect *pqic = new pqiconnect(pqip, rss, d1); - - pqip -> addChildInterface(PQI_CONNECT_TCP, pqic); - - // UDP. - NetBinDummy *d2 = new NetBinDummy(pqip, id, PQI_CONNECT_UDP); - - RsSerialiser *rss2 = new RsSerialiser(); - rss2->addSerialType(new RsRawSerialiser()); - - pqiconnect *pqic2 = new pqiconnect(pqip, rss2, d2); - - pqip -> addChildInterface(PQI_CONNECT_UDP, pqic2); - - return pqip; -} - -/******************************** DUMMY Specific features ***************************/ - diff --git a/libretroshare/src/pqi/pqipersongrp.h b/libretroshare/src/pqi/pqipersongrp.h deleted file mode 100644 index 5b57aebb1..000000000 --- a/libretroshare/src/pqi/pqipersongrp.h +++ /dev/null @@ -1,141 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqipersongrp.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_PERSON_HANDLER_HEADER -#define MRK_PQI_PERSON_HANDLER_HEADER - -#include "pqi/pqihandler.h" -#include "pqi/pqiperson.h" -#include "pqi/pqilistener.h" -#include "pqi/pqiservice.h" -#include "pqi/pqimonitor.h" -#include "pqi/p3cfgmgr.h" - - -// So this is a specific implementation -// -// it is designed to have one pqilistensocket + a series of pqisockets -// -// as an added bonus, we are going to -// make this a pqitunnelserver, to which services can be attached. - -const unsigned long PQIPERSON_NO_LISTENER = 0x0001; - -const unsigned long PQIPERSON_ALL_BW_LIMITED = 0x0010; -struct RsPeerCryptoParams; - -class pqipersongrp: public pqihandler, public pqiMonitor, public p3ServiceServer, public pqiNetListener -{ - public: - pqipersongrp(p3ServiceControl *ctrl, unsigned long flags); - - /*************************** Setup *************************/ - /* pqilistener */ - -virtual bool resetListener(const struct sockaddr_storage &local); // overloaded from pqiNetListener -int init_listener(); - - /*************** pqiMonitor callback ***********************/ -virtual void statusChange(const std::list &plist); - -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections -virtual void statusChanged(); -/////////////////////////////////////////////////////////// -#endif - - /******************* Peer Control **************************/ -virtual int addPeer(const RsPeerId& id); /* can be overloaded for testing */ -int removePeer(const RsPeerId& id); -int connectPeer(const RsPeerId& id -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections - , bool bConnect = false -/////////////////////////////////////////////////////////// -#endif - ); - - // New speedy recv. -virtual bool RecvRsRawItem(RsRawItem *item); - - - /* Work-around to dodgy pointer stuff */ -int tagHeartbeatRecvd(const RsPeerId& id); - - /*** callback from children ****/ -bool notifyConnect(const RsPeerId& id, uint32_t type, bool success, bool isIncomingConnection, const struct sockaddr_storage &remote_peer_address); -//bool notifyConnect(std::string id, uint32_t type, bool success); - - // tick interfaces. -virtual int tick(); -virtual int status(); - -virtual bool getCryptoParams(const RsPeerId&,RsPeerCryptoParams&) ; - protected: - -virtual bool locked_getCryptoParams(const RsPeerId&, RsPeerCryptoParams&) { return false ;} - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ - // THESE NEED TO BE LOCKED UNTIL PQILISTENER IS THREAD-SAFE. -virtual pqilistener *locked_createListener(const struct sockaddr_storage &laddr) = 0; -virtual pqiperson *locked_createPerson(const RsPeerId& id, pqilistener *listener) = 0; - /********* FUNCTIONS to OVERLOAD for specialisation ********/ - - /* Overloaded RsItem Check - * checks item->cid vs Person - */ -virtual int checkOutgoingRsItem(RsItem *item, int global) - { - (void) item; /* suppress unused parameter warning */ - (void) global; /* suppress unused parameter warning */ - return 1; - } - - private: - - // The serviceserver operation. - //int tickServiceRecv(); - //int tickServiceSend(); - - pqilistener *pqil; - RsMutex pqilMtx; /* MUTEX */ - unsigned long initFlags; -}; - -class pqipersongrpDummy: public pqipersongrp -{ - public: - pqipersongrpDummy(p3ServiceControl *ctrl, unsigned long flags) - :pqipersongrp(ctrl, flags) { return; } - - protected: - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -virtual pqilistener *locked_createListener(const struct sockaddr_storage &laddr); -virtual pqiperson *locked_createPerson(const RsPeerId& id, pqilistener *listener); - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -}; - - - -#endif // MRK_PQI_PERSON_HANDLER_HEADER diff --git a/libretroshare/src/pqi/pqiqos.cc b/libretroshare/src/pqi/pqiqos.cc deleted file mode 100644 index 0b2b484fa..000000000 --- a/libretroshare/src/pqi/pqiqos.cc +++ /dev/null @@ -1,156 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiqos.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include -#include -#include -#include - -#include "pqiqos.h" - -const uint32_t pqiQoS::MAX_PACKET_COUNTER_VALUE = (1 << 24) ; - -pqiQoS::pqiQoS(uint32_t nb_levels,float alpha) - : _item_queues(nb_levels),_alpha(alpha) -{ -#ifdef DEBUG - assert(pow(alpha,nb_levels) < 1e+20) ; -#endif - - float c = 1.0f ; - float inc = alpha ; - _nb_items = 0 ; - _id_counter = 0 ; - -for(int i=((int)nb_levels)-1;i>=0;--i,c *= alpha) - { - _item_queues[i]._threshold = c ; - _item_queues[i]._counter = 0 ; - _item_queues[i]._inc = inc ; - } -} - -void pqiQoS::clear() -{ - void *item ; - - for(uint32_t i=0;i<_item_queues.size();++i) - while( (item = _item_queues[i].pop()) != NULL) - free(item) ; - - _nb_items = 0 ; -} - -void pqiQoS::print() const -{ - std::cerr << "pqiQoS: " << _item_queues.size() << " levels, alpha=" << _alpha ; - std::cerr << " Size = " << _nb_items ; - std::cerr << " Queues: " ; - for(uint32_t i=0;i<_item_queues.size();++i) - std::cerr << _item_queues[i]._items.size() << " " ; - std::cerr << std::endl; -} - -void pqiQoS::in_rsItem(void *ptr,int size,int priority) -{ - if(uint32_t(priority) >= _item_queues.size()) - { - std::cerr << "pqiQoS::in_rsRawItem() ****Warning****: priority " << priority << " out of scope [0," << _item_queues.size()-1 << "]. Priority will be clamped to maximum value." << std::endl; - priority = _item_queues.size()-1 ; - } - - _item_queues[priority].push(ptr,size,_id_counter++) ; - ++_nb_items ; - - if(_id_counter >= MAX_PACKET_COUNTER_VALUE) - _id_counter = 0 ; -} - -// int pqiQoS::gatherStatistics(std::vector& per_service_count,std::vector& per_priority_count) const -// { -// assert(per_priority_count.size() == 10) ; -// assert(per_service_count.size() == 65536) ; -// -// for(uint32_t i=0;i<_item_queues.size();++i) -// { -// per_priority_count[i] += _item_queues[i].size() ; -// -// for(std::list::const_iterator it(_item_queues[i]._items.begin());it!=_item_queues[i]._items.end();++it) -// { -// uint32_t type = 0; -// uint32_t offset = 0; -// getRawUInt32((uint8_t*)(*it), 4, &offset, &type); -// -// uint16_t service_id = (type >> 8) & 0xffff ; -// -// ++per_service_count[service_id] ; -// } -// } -// return 1 ; -// } - - -void *pqiQoS::out_rsItem(uint32_t max_slice_size, uint32_t& size, bool& starts, bool& ends, uint32_t& packet_id) -{ - // Go through the queues. Increment counters. - - if(_nb_items == 0) - return NULL ; - - float inc = 1.0f ; - int i = _item_queues.size()-1 ; - - while(i > 0 && _item_queues[i]._items.empty()) - --i, inc = _item_queues[i]._inc ; - - int last = i ; - - for(int j=i;j>=0;--j) - if( (!_item_queues[j]._items.empty()) && ((_item_queues[j]._counter += inc) >= _item_queues[j]._threshold )) - { - last = j ; - _item_queues[j]._counter -= _item_queues[j]._threshold ; - } - - if(last >= 0) - { -#ifdef DEBUG - assert(_nb_items > 0) ; -#endif - - // now chop a slice of this item - - void *res = _item_queues[last].slice(max_slice_size,size,starts,ends,packet_id) ; - - if(ends) - --_nb_items ; - - return res ; - } - else - return NULL ; -} - - - - - diff --git a/libretroshare/src/pqi/pqiqos.h b/libretroshare/src/pqi/pqiqos.h deleted file mode 100644 index 74ff8ba77..000000000 --- a/libretroshare/src/pqi/pqiqos.h +++ /dev/null @@ -1,179 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiqos.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -// This class handles the prioritisation of RsItem, based on the -// priority level. The QoS algorithm must ensure that: -// -// - lower priority items get out with lower rate than high priority items -// - items of equal priority get out of the queue in the same order than they got in -// - items of level n+1 are output \alpha times more often than items of level n. -// \alpha is a constant that is not necessarily an integer, but strictly > 1. -// - the set of possible priority levels is finite, and pre-determined. -// -#pragma once - -#include -#include -#include -#include -#include -#include - -#include - -class pqiQoS -{ -public: - pqiQoS(uint32_t max_levels,float alpha) ; - - struct ItemRecord - { - void *data ; - uint32_t current_offset ; - uint32_t size ; - uint32_t id ; - }; - - class ItemQueue - { - public: - ItemQueue() - : _threshold(0.0) - , _counter(0.0) - , _inc(0.0) - {} - void *pop() - { - if(_items.empty()) - return NULL ; - - void *item = _items.front().data ; - _items.pop_front() ; - - return item ; - } - - void *slice(uint32_t max_size,uint32_t& size,bool& starts,bool& ends,uint32_t& packet_id) - { - if(_items.empty()) - return NULL ; - - ItemRecord& rec(_items.front()) ; - packet_id = rec.id ; - - // readily get rid of the item if it can be sent as a whole - - if(rec.current_offset == 0 && rec.size < max_size) - { - starts = true ; - ends = true ; - size = rec.size ; - - return pop() ; - } - starts = (rec.current_offset == 0) ; - ends = (rec.current_offset + max_size >= rec.size) ; - - if(rec.size <= rec.current_offset) - { - std::cerr << "(EE) severe error in slicing in QoS." << std::endl; - pop() ; - return NULL ; - } - - size = std::min(max_size, uint32_t((int)rec.size - (int)rec.current_offset)) ; - void *mem = rs_malloc(size) ; - - if(!mem) - { - std::cerr << "(EE) memory allocation error in QoS." << std::endl; - pop() ; - return NULL ; - } - - memcpy(mem,&((unsigned char*)rec.data)[rec.current_offset],size) ; - - if(ends) // we're taking the whole stuff. So we can delete the entry. - { - free(rec.data) ; - _items.pop_front() ; - } - else - rec.current_offset += size ; // by construction, !ends implies rec.current_offset < rec.size - - return mem ; - } - - void push(void *item,uint32_t size,uint32_t id) - { - ItemRecord rec ; - - rec.data = item ; - rec.current_offset = 0 ; - rec.size = size ; - rec.id = id ; - - _items.push_back(rec) ; - } - - uint32_t size() const { return _items.size() ; } - - float _threshold ; - float _counter ; - float _inc ; - - std::list _items ; - }; - - // This function pops items from the queue, y order of priority - // - void *out_rsItem(uint32_t max_slice_size,uint32_t& size,bool& starts,bool& ends,uint32_t& packet_id) ; - - // This function is used to queue items. - // - void in_rsItem(void *item, int size, int priority) ; - - void print() const ; - uint64_t qos_queue_size() const { return _nb_items ; } - - // kills all waiting items. - void clear() ; - - // get some stats about what's going on. service_packets will contain the number of - // packets per service, and queue_sizes will contain the size of the different priority queues. - - //int gatherStatistics(std::vector& per_service_count,std::vector& per_priority_count) const ; - - void computeTotalItemSize() const ; - int debug_computeTotalItemSize() const ; -private: - // This vector stores the lists of items with equal priorities. - // - std::vector _item_queues ; - float _alpha ; - uint64_t _nb_items ; - uint32_t _id_counter ; - - static const uint32_t MAX_PACKET_COUNTER_VALUE ; -}; - - diff --git a/libretroshare/src/pqi/pqiqosstreamer.cc b/libretroshare/src/pqi/pqiqosstreamer.cc deleted file mode 100644 index 2818b3ee7..000000000 --- a/libretroshare/src/pqi/pqiqosstreamer.cc +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiqosstreamer.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2012 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqiqosstreamer.h" - -//#define DEBUG_PQIQOSSTREAMER 1 - -const float pqiQoSstreamer::PQI_QOS_STREAMER_ALPHA = 2.0f ; - -pqiQoSstreamer::pqiQoSstreamer(PQInterface *parent, RsSerialiser *rss, const RsPeerId& peerid, BinInterface *bio_in, int bio_flagsin) - : pqithreadstreamer(parent,rss,peerid,bio_in,bio_flagsin), pqiQoS(PQI_QOS_STREAMER_MAX_LEVELS, PQI_QOS_STREAMER_ALPHA) -{ - _total_item_size = 0 ; - _total_item_count = 0 ; -} - -int pqiQoSstreamer::getQueueSize(bool in) -{ - if(in) - return pqistreamer::getQueueSize(in) ; - else - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - return qos_queue_size() ; - } -} - -//int pqiQoSstreamer::locked_gatherStatistics(std::vector& per_service_count,std::vector& per_priority_count) const // extracting data. -//{ -// return pqiQoS::gatherStatistics(per_service_count,per_priority_count) ; -//} - -void pqiQoSstreamer::locked_storeInOutputQueue(void *ptr,int size,int priority) -{ - _total_item_size += size ; - ++_total_item_count ; - - pqiQoS::in_rsItem(ptr,size,priority) ; -} - -void pqiQoSstreamer::locked_clear_out_queue() -{ -#ifdef DEBUG_PQIQOSSTREAMER - if(qos_queue_size() > 0) - std::cerr << " pqiQoSstreamer::locked_clear_out_queue(): clearing " << qos_queue_size() << " pending outqueue elements." << std::endl; -#endif - - pqiQoS::clear() ; - _total_item_size = 0 ; - _total_item_count = 0 ; -} - -void *pqiQoSstreamer::locked_pop_out_data(uint32_t max_slice_size, uint32_t& size, bool& starts, bool& ends, uint32_t& packet_id) -{ - void *out = pqiQoS::out_rsItem(max_slice_size,size,starts,ends,packet_id) ; - - if(out != NULL) - { - _total_item_size -= size ; - - if(ends) - --_total_item_count ; - } - - return out ; -} - diff --git a/libretroshare/src/pqi/pqiqosstreamer.h b/libretroshare/src/pqi/pqiqosstreamer.h deleted file mode 100644 index 5964b6cbe..000000000 --- a/libretroshare/src/pqi/pqiqosstreamer.h +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiqosstreamer.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2012 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "pqiqos.h" -#include "pqithreadstreamer.h" - -class pqiQoSstreamer: public pqithreadstreamer, public pqiQoS -{ - public: - pqiQoSstreamer(PQInterface *parent, RsSerialiser *rss, const RsPeerId& peerid, BinInterface *bio_in, int bio_flagsin); - - static const uint32_t PQI_QOS_STREAMER_MAX_LEVELS = 10 ; - static const float PQI_QOS_STREAMER_ALPHA ; - - virtual void locked_storeInOutputQueue(void *ptr, int size, int priority) ; - virtual int locked_out_queue_size() const { return _total_item_count ; } - virtual void locked_clear_out_queue() ; - virtual int locked_compute_out_pkt_size() const { return _total_item_size ; } - virtual void *locked_pop_out_data(uint32_t max_slice_size,uint32_t& size,bool& starts,bool& ends,uint32_t& packet_id); - //virtual int locked_gatherStatistics(std::vector& per_service_count,std::vector& per_priority_count) const; // extracting data. - - - virtual int getQueueSize(bool in) ; - - private: - uint32_t _total_item_size ; - uint32_t _total_item_count ; -}; - diff --git a/libretroshare/src/pqi/pqiservice.cc b/libretroshare/src/pqi/pqiservice.cc deleted file mode 100644 index 86336631a..000000000 --- a/libretroshare/src/pqi/pqiservice.cc +++ /dev/null @@ -1,219 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/pqiservice.h" -#include "util/rsdebug.h" -#include "util/rsstring.h" - -#include -#include -static double getCurrentTS() -{ -#ifndef WINDOWS_SYS - struct timeval cts_tmp; - gettimeofday(&cts_tmp, NULL); - double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; -#else - struct _timeb timebuf; - _ftime( &timebuf); - double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; -#endif - return cts; -} - -#ifdef SERVICE_DEBUG -const int pqiservicezone = 60478; -#endif - -/**** - * #define SERVICE_DEBUG 1 - ****/ - -void pqiService::setServiceServer(p3ServiceServerIface *server) -{ - mServiceServer = server; -} - -bool pqiService::send(RsRawItem *item) -{ - return mServiceServer->sendItem(item); -} - - -p3ServiceServer::p3ServiceServer(pqiPublisher *pub, p3ServiceControl *ctrl) : mPublisher(pub), mServiceControl(ctrl), srvMtx("p3ServiceServer") -{ - RS_STACK_MUTEX(srvMtx); /********* LOCKED *********/ - -#ifdef SERVICE_DEBUG - pqioutput(PQL_DEBUG_BASIC, pqiservicezone, - "p3ServiceServer::p3ServiceServer()"); -#endif - - return; -} - -int p3ServiceServer::addService(pqiService *ts, bool defaultOn) -{ - RS_STACK_MUTEX(srvMtx); /********* LOCKED *********/ - -#ifdef SERVICE_DEBUG - pqioutput(PQL_DEBUG_BASIC, pqiservicezone, - "p3ServiceServer::addService()"); -#endif - - RsServiceInfo info = ts->getServiceInfo(); - std::map::iterator it; - it = services.find(info.mServiceType); - if (it != services.end()) - { - std::cerr << "p3ServiceServer::addService(): Service already added with id " << info.mServiceType << "!" << std::endl; - // it exists already! - return -1; - } - - ts->setServiceServer(this); - services[info.mServiceType] = ts; - - // This doesn't need to be in Mutex. - mServiceControl->registerService(info,defaultOn); - - return 1; -} - -bool p3ServiceServer::getServiceItemNames(uint32_t service_type,std::map& names) -{ - RS_STACK_MUTEX(srvMtx); /********* LOCKED *********/ - - std::map::iterator it=services.find(service_type) ; - - if(it != services.end()) - { - it->second->getItemNames(names) ; - return true ; - } - else - return false ; -} - -int p3ServiceServer::removeService(pqiService *ts) -{ - RS_STACK_MUTEX(srvMtx); /********* LOCKED *********/ - -#ifdef SERVICE_DEBUG - pqioutput(PQL_DEBUG_BASIC, pqiservicezone, "p3ServiceServer::removeService()"); -#endif - - RsServiceInfo info = ts->getServiceInfo(); - - // This doesn't need to be in Mutex. - mServiceControl->deregisterService(info.mServiceType); - - std::map::iterator it = services.find(info.mServiceType); - if (it == services.end()) - { - std::cerr << "p3ServiceServer::removeService(): Service not found with id " << info.mServiceType << "!" << std::endl; - return -1; - } - - services.erase(it); - - return 1; -} - -bool p3ServiceServer::recvItem(RsRawItem *item) -{ - // Packet Filtering. - // This doesn't need to be in Mutex. - if (!mServiceControl->checkFilter(item->PacketId() & 0xffffff00, item->PeerId())) - { - delete item; - return false; - } - - pqiService *s = NULL; - - // access the service map under mutex lock - { - RS_STACK_MUTEX(srvMtx); - auto it = services.find(item -> PacketId() & 0xffffff00); - if (it == services.end()) - { - delete item; - return false; - } - s = it->second; - } - - // then call recv off mutex - bool result = s->recv(item); - return result; -} - -bool p3ServiceServer::sendItem(RsRawItem *item) -{ -#ifdef SERVICE_DEBUG - std::cerr << "p3ServiceServer::sendItem()"; - std::cerr << std::endl; - item -> print(std::cerr); - std::cerr << std::endl; -#endif - if (!item) - { - std::cerr << "p3ServiceServer::sendItem() Caught Null item"; - std::cerr << std::endl; - return false; - } - - // Packet Filtering. - if (!mServiceControl->checkFilter(item->PacketId() & 0xffffff00, item->PeerId())) - { -#ifdef SERVICE_DEBUG - std::cerr << "p3ServiceServer::sendItem() Fails Filtering for packet id=" << std::hex << item->PacketId() << std::dec << ", and peer " << item->PeerId() << std::endl; -#endif - delete item; - return false; - } - - mPublisher->sendItem(item); - - return true; -} - -int p3ServiceServer::tick() -{ - mServiceControl->tick(); - - // make a copy of the service map - std::map local_map; - { - RS_STACK_MUTEX(srvMtx); - local_map=services; - } - - // tick all services off mutex - for(auto it(local_map.begin());it!=local_map.end();++it) - { - (it->second)->tick(); - } - - return 1; - -} diff --git a/libretroshare/src/pqi/pqiservice.h b/libretroshare/src/pqi/pqiservice.h deleted file mode 100644 index ad983266e..000000000 --- a/libretroshare/src/pqi/pqiservice.h +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef PQI_SERVICE_HEADER -#define PQI_SERVICE_HEADER - -#include "pqi/pqi.h" -#include "pqi/pqi_base.h" -#include "util/rsthreads.h" - -#include "retroshare/rsservicecontrol.h" -#include "pqi/p3servicecontrol.h" - -// PQI Service, is a generic lower layer on which services can run on. -// -// these packets get passed through the -// server, to a service that is registered. -// -// example services: -// proxytunnel. -> p3proxy. -// sockettunnel -// -> either broadcast (attach to -// open socket instead -// of broadcast address) -// -> or requested/signon. -// -// games, -// voice -// video -// -// -// DataType is defined in the serialiser directory. - -class RsRawItem; -class p3ServiceServerIface; - - -class pqiService -{ -protected: - - pqiService() // our type of packets. - :mServiceServer(NULL) { return; } - - virtual ~pqiService() { return; } - -public: - void setServiceServer(p3ServiceServerIface *server); - // - virtual bool recv(RsRawItem *) = 0; - virtual bool send(RsRawItem *item); - - virtual RsServiceInfo getServiceInfo() = 0; - - virtual int tick() { return 0; } - - virtual void getItemNames(std::map& /*names*/) const {} // This does nothing by default. Service should derive it in order to give info for the UI - -private: - p3ServiceServerIface *mServiceServer; // const, no need for mutex. -}; - -#include - -/* We are pushing the packets back through p3ServiceServer, - * so that we can filter services at this level later... - * if we decide not to do this, pqiService can call through - * to the base level pqiPublisher instead. - */ - -// use interface to allow DI -class p3ServiceServerIface -{ -public: - - virtual ~p3ServiceServerIface() {} - - - virtual bool recvItem(RsRawItem *) = 0; - virtual bool sendItem(RsRawItem *) = 0; - - virtual bool getServiceItemNames(uint32_t service_type,std::map& names) =0; -}; - -class p3ServiceServer : public p3ServiceServerIface -{ -public: - p3ServiceServer(pqiPublisher *pub, p3ServiceControl *ctrl); - - int addService(pqiService *, bool defaultOn); - int removeService(pqiService *); - - bool recvItem(RsRawItem *); - bool sendItem(RsRawItem *); - - bool getServiceItemNames(uint32_t service_type, std::map& names) ; - - int tick(); -public: - -private: - - pqiPublisher *mPublisher; // constant no need for mutex. - p3ServiceControl *mServiceControl; - - RsMutex srvMtx; - std::map services; - -}; - - -#endif // PQI_SERVICE_HEADER diff --git a/libretroshare/src/pqi/pqiservicemonitor.h b/libretroshare/src/pqi/pqiservicemonitor.h deleted file mode 100644 index c101feac4..000000000 --- a/libretroshare/src/pqi/pqiservicemonitor.h +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiservicemonitor.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef PQI_SERVICE_MONITOR_H -#define PQI_SERVICE_MONITOR_H - -#include -#include -#include -#include - -/* ACTIONS */ -const uint32_t RS_SERVICE_PEER_NEW = 0x0001; /* new Peer */ -const uint32_t RS_SERVICE_PEER_CONNECTED = 0x0002; /* service connected */ -const uint32_t RS_SERVICE_PEER_DISCONNECTED = 0x0010; -const uint32_t RS_SERVICE_PEER_REMOVED = 0x0020; - -class pqiServicePeer -{ - public: - RsPeerId id; - uint32_t actions; -}; - - -class pqiServiceMonitor -{ - public: - pqiServiceMonitor() { return; } -virtual ~pqiServiceMonitor() { return; } - - /*! - * this serves as a call back function for server which has - * a handle on the subclass and updates this subclass on the - * action of peer's of the client (state and action information) - * - *@param plist contains list of states and actions of the client's peers - */ -virtual void statusChange(const std::list &plist) = 0; -}; - -#endif // PQI_SERVICE_MONITOR_H diff --git a/libretroshare/src/pqi/pqissl.cc b/libretroshare/src/pqi/pqissl.cc deleted file mode 100644 index 76d447cc8..000000000 --- a/libretroshare/src/pqi/pqissl.cc +++ /dev/null @@ -1,1878 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissl.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * Copyright (C) 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/pqissl.h" -#include "pqi/pqinetwork.h" -#include "pqi/sslfns.h" - -#include "util/rsnet.h" -#include "util/rsdebug.h" -#include "util/rsstring.h" - -#include -#include -#include - -#include "pqi/pqissllistener.h" - -#include "pqi/p3linkmgr.h" -#include "retroshare/rspeers.h" -#include -#include - -#include "rsserver/p3face.h" - -static struct RsLog::logInfo pqisslzoneInfo = {RsLog::Default, "pqisslzone"}; -#define pqisslzone &pqisslzoneInfo - -/********* -#define WAITING_NOT 0 -#define WAITING_LOCAL_ADDR 1 -#define WAITING_REMOTE_ADDR 2 -#define WAITING_SOCK_CONNECT 3 -#define WAITING_SSL_CONNECTION 4 -#define WAITING_SSL_AUTHORISE 5 -#define WAITING_FAIL_INTERFACE 6 - -#define PQISSL_PASSIVE 0x00 -#define PQISSL_ACTIVE 0x01 - -const int PQISSL_LOCAL_FLAG = 0x01; -const int PQISSL_REMOTE_FLAG = 0x02; -const int PQISSL_UDP_FLAG = 0x02; -***********/ - -//#define PQISSL_DEBUG 1 -//#define PQISSL_LOG_DEBUG 1 -//#define PQISSL_LOG_DEBUG2 1 - -static const int PQISSL_MAX_READ_ZERO_COUNT = 20; -static const rstime_t PQISSL_MAX_READ_ZERO_TIME = 15; // 15 seconds of no data => reset. (atm HeartBeat pkt sent 5 secs) - -static const int PQISSL_SSL_CONNECT_TIMEOUT = 30; - -/********** PQI SSL STUFF ****************************************** - * - * A little note on the notifyEvent(FAILED).... - * - * this is called from - * (1) reset if needed! - * (2) Determine_Remote_Address (when all options have failed). - * - * reset() is only called when a TCP/SSL connection has been - * established, and there is an error. If there is a failed TCP - * connection, then an alternative address can be attempted. - * - * reset() is called from - * (1) destruction. - * (2) disconnect() - * (3) bad waiting state. - * - * // TCP/or SSL connection already established.... - * (5) pqissl::SSL_Connection_Complete() <- okay -> cos we made a TCP connection already. - * (6) pqissl::accept() <- okay cos something went wrong. - * (7) moretoread()/cansend() <- okay cos - * - */ - -pqissl::pqissl(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) : - NetBinInterface(parent, parent->PeerId()), - mLinkMgr(lm), pqil(l), mSslMtx("pqissl"), active(false), certvalid(false), - waiting(WAITING_NOT), sslmode(PQISSL_ACTIVE), ssl_connection(NULL), - sockfd(-1), readpkt(NULL), pktlen(0), total_len(0), attempt_ts(0), - n_read_zero(0), mReadZeroTS(0), ssl_connect_timeout(0), mConnectDelay(0), - mConnectTS(0), mConnectTimeout(0), mTimeoutTS(0) -{ sockaddr_storage_clear(remote_addr); } - - pqissl::~pqissl() -{ - rslog(RSL_ALERT, pqisslzone, - "pqissl::~pqissl -> destroying pqissl"); - stoplistening(); /* remove from pqissllistener only */ - - rslog(RSL_ALERT, pqisslzone, "pqissl::~pqissl() -> calling reset()"); - reset(); - return; -} - - -/********** Implementation of NetInterface *************************/ - -int pqissl::connect(const struct sockaddr_storage &raddr) -{ - RS_STACK_MUTEX(mSslMtx); - - remote_addr = raddr; - return ConnectAttempt(); -} - -// tells pqilistener to listen for us. -int pqissl::listen() -{ - if (pqil) - { - return pqil -> addlistenaddr(PeerId(), this); - } - return 0; -} - -int pqissl::stoplistening() -{ - if (pqil) - { - pqil -> removeListenPort(PeerId()); - } - return 1; -} - -int pqissl::disconnect() -{ - rslog(RSL_ALERT, pqisslzone, "pqissl::disconnect() -> calling reset()"); - return reset(); -} - -int pqissl::getConnectAddress(struct sockaddr_storage &raddr) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - raddr = remote_addr; - // TODO. - return (!sockaddr_storage_isnull(remote_addr)); -} - -/* BinInterface version of reset() for pqistreamer */ -int pqissl::close() -{ - rslog(RSL_ALERT, pqisslzone, "pqissl::close() -> calling reset()"); - return reset(); -} - -// put back on the listening queue. -int pqissl::reset() -{ - RS_STACK_MUTEX(mSslMtx); - return reset_locked(); -} - -int pqissl::reset_locked() -{ - std::string outLog; - bool neededReset = false; - - - /* a reset shouldn't cause us to stop listening - * only reasons for stoplistening() are; - * - * (1) destruction. - * (2) connection. - * (3) WillListen state change - * - */ - - outLog += "pqissl::reset():" + PeerId().toStdString(); - rs_sprintf_append(outLog, " (A: %d", (int) active); - rs_sprintf_append(outLog, " FD: %d", sockfd); - rs_sprintf_append(outLog, " W: %d", waiting); - rs_sprintf_append(outLog, " SSL: %p) ", ssl_connection); -#ifdef PQISSL_LOG_DEBUG - outLog += "\n"; -#endif - - - if (ssl_connection != NULL) - { - //outLog << "pqissl::reset() Shutting down SSL Connection"; - //outLog << std::endl; - SSL_shutdown(ssl_connection); - SSL_free (ssl_connection); - - neededReset = true; - } - - if (sockfd > 0) - { -#ifdef PQISSL_LOG_DEBUG - outLog += "pqissl::reset() Shutting down (active) socket\n"; -#endif - net_internal_close(sockfd); - sockfd = -1; - neededReset = true; - } - active = false; - sockfd = -1; - waiting = WAITING_NOT; - ssl_connection = NULL; - n_read_zero = 0; - mReadZeroTS = 0; - total_len = 0 ; - mTimeoutTS = 0; - - if (neededReset) - { -#ifdef PQISSL_LOG_DEBUG - outLog += "pqissl::reset() Reset Required!\n"; - outLog += "pqissl::reset() Will Attempt notifyEvent(FAILED)\n"; -#endif - } - -#ifdef PQISSL_LOG_DEBUG2 - rslog(RSL_ALERT, pqisslzone, outLog); -#endif - - // notify people of problem! - // but only if we really shut something down. - if (neededReset) - { - // clean up the streamer - if (parent()) - { - struct sockaddr_storage addr; - sockaddr_storage_clear(addr); - parent() -> notifyEvent(this, NET_CONNECT_FAILED, addr); - } - } - return 1; -} - -bool pqissl::connect_parameter(uint32_t type, uint32_t value) -{ -#ifdef PQISSL_LOG_DEBUG - std::cerr << "pqissl::connect_parameter() Peer: " << PeerId(); -#endif - - switch(type) - { - case NET_PARAM_CONNECT_DELAY: - { -#ifdef PQISSL_LOG_DEBUG - std::cerr << " DELAY: " << value << std::endl; -#endif - RS_STACK_MUTEX(mSslMtx); - mConnectDelay = value; - return true; - } - case NET_PARAM_CONNECT_TIMEOUT: - { -#ifdef PQISSL_LOG_DEBUG - std::cerr << " TIMEOUT: " << value << std::endl; -#endif - RS_STACK_MUTEX(mSslMtx); - mConnectTimeout = value; - return true; - } - default: - { -#ifdef PQISSL_LOG_DEBUG - std::cerr << " type: " << type << " value: " << value << std::endl; -#endif - return false; - } - } -} - - -/********** End of Implementation of NetInterface ******************/ -/********** Implementation of BinInterface ************************** - * Only status() + tick() are here ... as they are really related - * to the NetInterface, and not the BinInterface, - * - */ - -void pqissl::getCryptoParams(RsPeerCryptoParams& params) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - if(active) - { - params.connexion_state = 1 ; - - char *desc = SSL_CIPHER_description(SSL_get_current_cipher(ssl_connection), NULL, 0); - params.cipher_name = std::string(desc); - OPENSSL_free(desc); - } - else - { - params.connexion_state = 0 ; - params.cipher_name.clear() ; - } -} - -bool pqissl::actAsServer() -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return (bool)ssl_connection->server; -#else - return (bool)SSL_is_server(ssl_connection); -#endif -} - -/* returns ... - * -1 if inactive. - * 0 if connecting. - * 1 if connected. - */ - -int pqissl::status() -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - -#ifdef PQISSL_LOG_DEBUG - std::string out = "pqissl::status()"; - - if (active) - { - int alg; - - out += " active: \n"; - // print out connection. - out += "Connected TO : " + PeerId().toStdString() + "\n"; - // print out cipher. - rs_sprintf_append(out, "\t\tSSL Cipher:%s", SSL_get_cipher(ssl_connection)); - rs_sprintf_append(out, " (%d:%d)", SSL_get_cipher_bits(ssl_connection, &alg), alg); - rs_sprintf_append(out, "Vers:%s\n\n", SSL_get_cipher_version(ssl_connection)); - } - else - { - out += " Waiting for connection!\n"; - } - - rslog(RSL_DEBUG_BASIC, pqisslzone, out); -#endif - - if (active) - { - return 1; - } - else if (waiting > 0) - { - return 0; - } - return -1; -} - - // tick...... -int pqissl::tick() -{ - // there is no reason to lock pqissl mutex now - // we will lock the mutex later if we actually need to call to ConnectAttempt - // RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - // pqistreamer::tick(); - - // continue existing connection attempt. - if (!active) - { - // if we are waiting.. continue the connection (only) - if (waiting > 0) - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, "pqissl::tick() Continuing Connection Attempt!"); -#endif - // now lock pqissl mutex, that will take up to 10 ms - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - ConnectAttempt(); - return 1; - } - } - return 1; -} - -/********** End of Implementation of BinInterface ******************/ -/********** Internals of SSL Connection ****************************/ - - -int pqissl::ConnectAttempt() -{ - switch(waiting) - { - case WAITING_NOT: - - sslmode = PQISSL_ACTIVE; /* we're starting this one */ - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() STATE = Not Waiting, starting connection"); -#endif - /* fallthrough */ - case WAITING_DELAY: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() STATE = Waiting Delay, starting connection"); -#endif - - return Delay_Connection(); - //return Initiate_Connection(); /* now called by Delay_Connection() */ - - break; - - case WAITING_SOCK_CONNECT: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() STATE = Waiting Sock Connect"); -#endif - - return Initiate_SSL_Connection(); - break; - - case WAITING_SSL_CONNECTION: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() STATE = Waiting SSL Connection"); -#endif - - return Authorise_SSL_Connection(); - break; - - case WAITING_SSL_AUTHORISE: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() STATE = Waiting SSL Authorise"); -#endif - - return Authorise_SSL_Connection(); - break; - case WAITING_FAIL_INTERFACE: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() Failed - Retrying"); -#endif - - return Failed_Connection(); - break; - - - default: - rslog(RSL_ALERT, pqisslzone, - "pqissl::ConnectAttempt() STATE = Unknown - calling reset()"); - - reset_locked(); - break; - } - rslog(RSL_ALERT, pqisslzone, "pqissl::ConnectAttempt() Unknown"); - - return -1; -} - - -/****************************** FAILED ATTEMPT ****************************** - * Determine the Remote Address. - * - * Specifics: - * TCP / UDP - * TCP - check for which interface to use. - * UDP - check for request proxies.... - * - * X509 / XPGP - Same. - * - */ - -int pqissl::Failed_Connection() -{ -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() Failed - Notifying"); -#endif - - if (parent()) - { - struct sockaddr_storage addr; - sockaddr_storage_clear(addr); - parent() -> notifyEvent(this, NET_CONNECT_UNREACHABLE, addr); - } - - waiting = WAITING_NOT; - - return 1; -} - -/****************************** MAKE CONNECTION ***************************** - * Open Socket and Initiate Connection. - * - * Specifics: - * TCP / UDP - * TCP - socket()/connect() - * UDP - tou_socket()/tou_connect() - * - * X509 / XPGP - Same. - * - */ - -int pqissl::Delay_Connection() -{ -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Delay_Connection() Attempting Outgoing Connection...."); -#endif - - if (waiting == WAITING_NOT) - { - waiting = WAITING_DELAY; - - /* we cannot just jump to Initiate_Connection, - * but must switch to WAITING_DELAY for at least one cycle. - * to avoid deadlock between threads.... - * ie. so the connection stuff is called from tick(), rather than connect() - */ - - /* set Connection TS. - */ -#ifdef PQISSL_LOG_DEBUG - { - std::string out; - rs_sprintf(out, "pqissl::Delay_Connection() Delaying Connection to %s for %lu seconds", PeerId().toStdString(), mConnectDelay); - rslog(RSL_DEBUG_BASIC, pqisslzone, out); - } -#endif - - mConnectTS = time(NULL) + mConnectDelay; - return 0; - } - else if (waiting == WAITING_DELAY) - { -#ifdef PQISSL_LOG_DEBUG - { - std::string out; - rs_sprintf(out, "pqissl::Delay_Connection() Connection to %s starting in %ld seconds", PeerId().toStdString(), mConnectTS - time(NULL)); - rslog(RSL_DEBUG_BASIC, pqisslzone, out); - } -#endif - if (time(NULL) >= mConnectTS) - { - return Initiate_Connection(); - } - return 0; - } - - rslog(RSL_WARNING, pqisslzone, - "pqissl::Delay_Connection() Already Attempt in Progress!"); - return -1; -} - - -int pqissl::Initiate_Connection() -{ -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " " - << sockaddr_storage_tostring(remote_addr) << std::endl; -#endif - - int err; - sockaddr_storage addr; sockaddr_storage_copy(remote_addr, addr); - - if(waiting != WAITING_DELAY) - { - std::cerr << __PRETTY_FUNCTION__ << " Already Attempt in Progress!" - << std::endl; - return -1; - } - - // open socket connection to addr. - int osock = unix_socket(PF_INET6, SOCK_STREAM, 0); - -#ifdef PQISSL_LOG_DEBUG - { - std::string out; - rs_sprintf(out, "pqissl::Initiate_Connection() osock = %d", osock); - rslog(RSL_DEBUG_BASIC, pqisslzone, out); - } -#endif - - if (osock < 0) - { - std::string out = "pqissl::Initiate_Connection() Failed to open socket!\n"; - out += "Socket Error:" + socket_errorType(errno); - rslog(RSL_WARNING, pqisslzone, out); - - net_internal_close(osock); - waiting = WAITING_FAIL_INTERFACE; - return -1; - } - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_Connection() Making Non-Blocking"); -#endif - - err = unix_fcntl_nonblock(osock); - if (err < 0) - { - std::string out; - rs_sprintf(out, "pqissl::Initiate_Connection() Error: Cannot make socket NON-Blocking: %d", err); - rslog(RSL_WARNING, pqisslzone, out); - - waiting = WAITING_FAIL_INTERFACE; - net_internal_close(osock); - return -1; - } - - if (sockaddr_storage_isnull(addr)) - { - rslog(RSL_WARNING, pqisslzone, "pqissl::Initiate_Connection() Invalid (0.0.0.0) Remote Address, Aborting Connect."); - waiting = WAITING_FAIL_INTERFACE; - net_internal_close(osock); - return -1; - } - -#ifdef WINDOWS_SYS - /* Set TCP buffer size for Windows systems */ - - int sockbufsize = 0; - int size = sizeof(int); - - err = getsockopt(osock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size); -#ifdef PQISSL_DEBUG - if (err == 0) { - std::cerr << "pqissl::Initiate_Connection: Current TCP receive buffer size " << sockbufsize << std::endl; - } else { - std::cerr << "pqissl::Initiate_Connection: Error getting TCP receive buffer size. Error " << err << std::endl; - } -#endif - - sockbufsize = 0; - - err = getsockopt(osock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size); -#ifdef PQISSL_DEBUG - if (err == 0) { - std::cerr << "pqissl::Initiate_Connection: Current TCP send buffer size " << sockbufsize << std::endl; - } else { - std::cerr << "pqissl::Initiate_Connection: Error getting TCP send buffer size. Error " << err << std::endl; - } -#endif - - sockbufsize = WINDOWS_TCP_BUFFER_SIZE; - - err = setsockopt(osock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, sizeof(sockbufsize)); -#ifdef PQISSL_DEBUG - if (err == 0) { - std::cerr << "pqissl::Initiate_Connection: TCP receive buffer size set to " << sockbufsize << std::endl; - } else { - std::cerr << "pqissl::Initiate_Connection: Error setting TCP receive buffer size. Error " << err << std::endl; - } -#endif - - err = setsockopt(osock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, sizeof(sockbufsize)); -#ifdef PQISSL_DEBUG - if (err == 0) { - std::cerr << "pqissl::Initiate_Connection: TCP send buffer size set to " << sockbufsize << std::endl; - } else { - std::cerr << "pqissl::Initiate_Connection: Error setting TCP send buffer size. Error " << err << std::endl; - } -#endif -#endif // WINDOWS_SYS - - /* Systems that supports dual stack sockets defines IPV6_V6ONLY and some set - * it to 1 by default. This enable dual stack socket on such systems. - * Systems which don't support dual stack (only Windows older then XP SP3) - * will support IPv6 only and not IPv4 */ -#ifdef IPV6_V6ONLY - int no = 0; - err = rs_setsockopt( osock, IPPROTO_IPV6, IPV6_V6ONLY, - reinterpret_cast(&no), sizeof(no) ); -#ifdef PQISSL_DEBUG - if (err) std::cerr << __PRETTY_FUNCTION__ - << " Error setting IPv6 socket dual stack: " - << errno << " " << strerror(errno) << std::endl; - else std::cerr << __PRETTY_FUNCTION__ - << " Setting IPv6 socket dual stack" << std::endl; -#endif // PQISSL_DEBUG -#endif // IPV6_V6ONLY - - mTimeoutTS = time(NULL) + mConnectTimeout; - //std::cerr << "Setting Connect Timeout " << mConnectTimeout << " Seconds into Future " << std::endl; - - sockaddr_storage_ipv4_to_ipv6(addr); -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " Connecting To: " - << PeerId().toStdString() <<" via: " - << sockaddr_storage_tostring(addr) << std::endl; -#endif - - if (0 != (err = unix_connect(osock, addr))) - { - switch (errno) - { - case EINPROGRESS: - waiting = WAITING_SOCK_CONNECT; - sockfd = osock; - return 0; - default: -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " Failure connect " - << sockaddr_storage_tostring(addr) - << " returns: " - << err << " -> errno: " << errno << " " - << socket_errorType(errno) << std::endl; -#endif - - net_internal_close(osock); - osock = -1; - waiting = WAITING_FAIL_INTERFACE; - return -1; - } - } - - waiting = WAITING_SOCK_CONNECT; - sockfd = osock; - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_Connection() Waiting for Socket Connect"); -#endif - - return 1; -} - - -/****************************** CHECK SOCKET ***************************** - * Check the Socket. - * - * select() and getsockopt(). - * - * Specifics: - * TCP / UDP - * TCP - select()/getsockopt() - * UDP - tou_error() - * - * X509 / XPGP - Same. - * - */ - -bool pqissl::CheckConnectionTimeout() -{ - /* new TimeOut code. */ - if (time(NULL) > mTimeoutTS) - { - std::string out; - rs_sprintf(out, "pqissl::Basic_Connection_Complete() Connection Timed Out. Peer: %s Period: %lu", PeerId().toStdString().c_str(), mConnectTimeout); - -#ifdef PQISSL_LOG_DEBUG2 - rslog(RSL_WARNING, pqisslzone, out); -#endif - /* as sockfd is valid, this should close it all up */ - -#ifdef PQISSL_LOG_DEBUG2 - rslog(RSL_ALERT, pqisslzone, "pqissl::Basic_Connection_Complete() -> calling reset()"); -#endif - reset_locked(); - return true; - } - return false; -} - - - -int pqissl::Basic_Connection_Complete() -{ -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Basic_Connection_Complete()..."); -#endif - - if (CheckConnectionTimeout()) - { - // calls reset. - return -1; - } - - if (waiting != WAITING_SOCK_CONNECT) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::Basic_Connection_Complete() Wrong Mode"); - return -1; - } - - if (sockfd == -1) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::Basic_Connection_Complete() problem with the socket descriptor. Aborting"); - rslog(RSL_ALERT, pqisslzone, "pqissl::Basic_Connection_Complete() -> calling reset()"); - reset_locked(); - return -1; - } - - // use select on the opened socket. - // Interestingly - This code might be portable.... - - fd_set ReadFDs, WriteFDs, ExceptFDs; - FD_ZERO(&ReadFDs); - FD_ZERO(&WriteFDs); - FD_ZERO(&ExceptFDs); - - FD_SET(sockfd, &ReadFDs); - FD_SET(sockfd, &WriteFDs); - FD_SET(sockfd, &ExceptFDs); - - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Basic_Connection_Complete() Selecting ...."); -#endif - - int sr = 0; - if (0 > (sr = select(sockfd + 1, - &ReadFDs, &WriteFDs, &ExceptFDs, &timeout))) - { - // select error. - rslog(RSL_WARNING, pqisslzone, - "pqissl::Basic_Connection_Complete() Select ERROR(1)"); - - net_internal_close(sockfd); - sockfd=-1; - //reset(); - waiting = WAITING_FAIL_INTERFACE; - return -1; - } - -#ifdef PQISSL_LOG_DEBUG - { - std::string out; - rs_sprintf(out, "pqissl::Basic_Connection_Complete() Select returned %d", sr); - rslog(RSL_DEBUG_BASIC, pqisslzone, out); - } -#endif - - - if (FD_ISSET(sockfd, &ExceptFDs)) - { - // error - reset socket. - // this is a definite bad socket!. -#ifdef PQISSL_LOG_DEBUG2 - rslog(RSL_WARNING, pqisslzone, - "pqissl::Basic_Connection_Complete() Select ERROR(2)"); -#endif - net_internal_close(sockfd); - sockfd=-1; - //reset(); - waiting = WAITING_FAIL_INTERFACE; - return -1; - } - - if (FD_ISSET(sockfd, &WriteFDs)) - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Basic_Connection_Complete() Can Write!"); -#endif - } - else - { -#ifdef PQISSL_LOG_DEBUG - // happens frequently so switched to debug msg. - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Basic_Connection_Complete() Not Yet Ready!"); -#endif - return 0; - } - - if (FD_ISSET(sockfd, &ReadFDs)) - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Basic_Connection_Complete() Can Read!"); -#endif - } - else - { -#ifdef PQISSL_LOG_DEBUG - // not ready return -1; - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Basic_Connection_Complete() Cannot Read!"); -#endif - } - - int err = 1; - if (0==unix_getsockopt_error(sockfd, &err)) - { - if (err == 0) - { - { - std::string out; - rs_sprintf(out, "pqissl::Basic_Connection_Complete() TCP Connection Complete: cert: %s on osock: ", PeerId().toStdString().c_str(), sockfd); -#ifdef PQISSL_LOG_DEBUG2 - rslog(RSL_WARNING, pqisslzone, out); -#endif - } - return 1; - } - else if (err == EINPROGRESS) - { - rslog(RSL_WARNING, pqisslzone, "pqissl::Basic_Connection_Complete() EINPROGRESS: cert: " + PeerId().toStdString()); - - return 0; - } - else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) - { - rslog(RSL_WARNING, pqisslzone, "pqissl::Basic_Connection_Complete() ENETUNREACH/ETIMEDOUT: cert: " + PeerId().toStdString()); - - // Then send unreachable message. - net_internal_close(sockfd); - sockfd=-1; - //reset(); - - waiting = WAITING_FAIL_INTERFACE; - - return -1; - } - else if ((err == EHOSTUNREACH) || (err == EHOSTDOWN)) - { -#ifdef PQISSL_DEBUG - rslog(RSL_WARNING, pqisslzone, "pqissl::Basic_Connection_Complete() EHOSTUNREACH/EHOSTDOWN: cert: " + PeerId().toStdString()); -#endif - // Then send unreachable message. - net_internal_close(sockfd); - sockfd=-1; - //reset(); - waiting = WAITING_FAIL_INTERFACE; - - return -1; - } - else if (err == ECONNREFUSED) - { -#ifdef PQISSL_DEBUG - rslog(RSL_WARNING, pqisslzone, "pqissl::Basic_Connection_Complete() ECONNREFUSED: cert: " + PeerId().toStdString()); -#endif - - // Then send unreachable message. - net_internal_close(sockfd); - sockfd=-1; - //reset(); - waiting = WAITING_FAIL_INTERFACE; - - return -1; - } - - std::string out; - rs_sprintf(out, "Error: Connection Failed UNKNOWN ERROR: %d - %s", err, socket_errorType(err).c_str()); - rslog(RSL_WARNING, pqisslzone, out); - - net_internal_close(sockfd); - sockfd=-1; - //reset(); // which will send Connect Failed, - return -1; - } - - rslog(RSL_ALERT, pqisslzone, - "pqissl::Basic_Connection_Complete() BAD GETSOCKOPT!"); - waiting = WAITING_FAIL_INTERFACE; - - return -1; -} - - -int pqissl::Initiate_SSL_Connection() -{ - int err; - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_SSL_Connection() Checking Basic Connection"); -#endif - - if (0 >= (err = Basic_Connection_Complete())) - { - return err; - } - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_SSL_Connection() Basic Connection Okay"); -#endif - - // setup timeout value. - ssl_connect_timeout = time(NULL) + PQISSL_SSL_CONNECT_TIMEOUT; - - // Perform SSL magic. - // library already inited by sslroot(). - SSL *ssl = SSL_new(AuthSSL::getAuthSSL()->getCTX()); - if (ssl == NULL) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::Initiate_SSL_Connection() SSL_new failed!"); - - exit(1); - return -1; - } - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_SSL_Connection() SSL Connection Okay"); -#endif - - if(ssl_connection != NULL) - { - SSL_shutdown(ssl_connection); - SSL_free(ssl_connection) ; - } - - ssl_connection = ssl; - - net_internal_SSL_set_fd(ssl, sockfd); - if (err < 1) - { - std::string out = "pqissl::Initiate_SSL_Connection() SSL_set_fd failed!\n"; - printSSLError(ssl, err, SSL_get_error(ssl, err), ERR_get_error(), out); - - rslog(RSL_ALERT, pqisslzone, out); - } - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_SSL_Connection() Waiting for SSL Connection"); -#endif - - waiting = WAITING_SSL_CONNECTION; - return 1; -} - -int pqissl::SSL_Connection_Complete() -{ -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::SSL_Connection_Complete()??? ... Checking"); -#endif - - if (waiting == WAITING_SSL_AUTHORISE) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::SSL_Connection_Complete() Waiting = W_SSL_AUTH"); - - return 1; - } - if (waiting != WAITING_SSL_CONNECTION) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::SSL_Connection_Complete() Still Waiting.."); - - return -1; - } - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::SSL_Connection_Complete() Attempting SSL_connect"); -#endif - - /* if we are passive - then accept! */ - int err; - - if (sslmode == PQISSL_ACTIVE) - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, "--------> Active Connect! Client side."); -#endif - err = SSL_connect(ssl_connection); - } - else - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, "--------> Passive Accept! Server side."); -#endif - err = SSL_accept(ssl_connection); - } - - if (err != 1) - { - int serr = SSL_get_error(ssl_connection, err); - if ((serr == SSL_ERROR_WANT_READ) || (serr == SSL_ERROR_WANT_WRITE)) - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "Waiting for SSL handshake!"); -#endif - - waiting = WAITING_SSL_CONNECTION; - return 0; - } - - if(rsEvents) - { - X509 *x509 = SSL_get_peer_certificate(ssl_connection); - - if(x509) - { - auto ev = std::make_shared(); - ev->mSslId = RsX509Cert::getCertSslId(*x509); - ev->mErrorCode = RsAuthSslError::PEER_REFUSED_CONNECTION; - - if(!ev->mSslId.isNull()) - rsEvents->postEvent(ev); - } - } - - std::string out; - rs_sprintf(out, "pqissl::SSL_Connection_Complete()\nIssues with SSL Connect(%d)!\n", err); - printSSLError(ssl_connection, err, serr, ERR_get_error(), out); - - rslog(RSL_WARNING, pqisslzone, out); - - rslog(RSL_ALERT, pqisslzone, "pqissl::SSL_Connection_Complete() -> calling reset()"); - reset_locked(); - waiting = WAITING_FAIL_INTERFACE; - - return -1; - } - // if we get here... success v quickly. - - rslog(RSL_WARNING, pqisslzone, "pqissl::SSL_Connection_Complete() Success!: Peer: " + PeerId().toStdString()); - - waiting = WAITING_SSL_AUTHORISE; - return 1; -} - -int pqissl::Authorise_SSL_Connection() -{ - Dbg3() << __PRETTY_FUNCTION__ << std::endl; - - constexpr int failure = -1; - - if (time(nullptr) > ssl_connect_timeout) - { - RsInfo() << __PRETTY_FUNCTION__ << " Connection timed out reset!" - << std::endl; - reset_locked(); - } - - int err; - if (0 >= (err = SSL_Connection_Complete())) return err; - - Dbg3() << __PRETTY_FUNCTION__ << "SSL_Connection_Complete success." - << std::endl; - - // reset switch. - waiting = WAITING_NOT; - -#ifdef RS_PQISSL_AUTH_DOUBLE_CHECK - X509* peercert = SSL_get_peer_certificate(ssl_connection); - if (!peercert) - { - RsFatal() << __PRETTY_FUNCTION__ << " failed to retrieve peer " - << "certificate at this point this should never happen!" - << std::endl; - print_stacktrace(); - exit(failure); - } - - RsPeerId certPeerId = RsX509Cert::getCertSslId(*peercert); - if (RsPeerId(certPeerId) != PeerId()) - { - RsErr() << __PRETTY_FUNCTION__ << " the cert Id doesn't match the peer " - << "id we're trying to connect to." << std::endl; - - /* TODO: Considering how difficult is managing to get a connection to a - * friend nowadays on the Internet because of evil NAT everywhere. - * If the cert is from a friend anyway we should find a way to make good - * use of this connection instead of throwing it away... */ - - X509_free(peercert); - reset_locked(); - return failure; - } - - /* At this point the actual connection authentication has already been - * performed in AuthSSL::VerifyX509Callback, any furter authentication check - * like the followings are redundant. */ - - bool isSslOnlyFriend = rsPeers->isSslOnlyFriend(certPeerId); - - uint32_t authErrCode = 0; - if( !isSslOnlyFriend && !AuthSSL::instance().AuthX509WithGPG(peercert,false, authErrCode) ) - { - RsFatal() << __PRETTY_FUNCTION__ << " failure verifying peer " - << "certificate signature. This should never happen at this " - << "point!" << std::endl; - print_stacktrace(); - - X509_free(peercert); // not needed but just in case we change to return - exit(failure); - } - - RsPgpId pgpId = RsX509Cert::getCertIssuer(*peercert); - if( !isSslOnlyFriend && pgpId != AuthGPG::getAuthGPG()->getGPGOwnId() && - !AuthGPG::getAuthGPG()->isGPGAccepted(pgpId) ) - { - RsFatal() << __PRETTY_FUNCTION__ << " pgpId: " << pgpId - << " is not friend. It is very unlikely to happen at this " - << "point! Either the user must have been so fast to deny " - << "friendship just after VerifyX509Callback have returned " - << "success and just before this code being executed, or " - << "something really fishy is happening! Share the full log " - << "with developers." << std::endl; - print_stacktrace(); - - X509_free(peercert); // not needed but just in case we change to return - exit(failure); - } -#endif // def RS_PQISSL_AUTH_REDUNDANT_CHECK - - Dbg2() << __PRETTY_FUNCTION__ << " Accepting connection to peer: " - << PeerId() << " with address: " << remote_addr << std::endl; - - return accept_locked(ssl_connection, sockfd, remote_addr); -} - - -/* This function is public, and callable from pqilistener - so must be mutex protected */ -int pqissl::accept( SSL *ssl, int fd, - const sockaddr_storage &foreign_addr) -{ -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - RS_STACK_MUTEX(mSslMtx); - return accept_locked(ssl, fd, foreign_addr); -} - -int pqissl::accept_locked( SSL *ssl, int fd, - const sockaddr_storage &foreign_addr ) -{ - Dbg3() << __PRETTY_FUNCTION__ << std::endl; - - constexpr int failure = -1; - constexpr int success = 1; - -#ifdef RS_PQISSL_BANLIST_DOUBLE_CHECK - /* At this point, as we are actively attempting the connection, we decide - * the address to which to connect to, banned addresses should never get - * here as the filtering for banned addresses happens much before, this - * check is therefore redundant, and if it trigger something really fishy - * must be happening (a bug somewhere else in the code). */ - uint32_t check_result; - uint32_t checking_flags = RSBANLIST_CHECKING_FLAGS_BLACKLIST; - - if (rsPeers->servicePermissionFlags(PeerId()) & RS_NODE_PERM_REQUIRE_WL) - checking_flags |= RSBANLIST_CHECKING_FLAGS_WHITELIST; - - if( RsX509Cert::getCertSslId(*SSL_get_peer_certificate(ssl)) != PeerId()) - std::cerr << "(EE) pqissl::accept_locked(): PeerId() is " << PeerId() << " but certificate ID is " << RsX509Cert::getCertSslId(*SSL_get_peer_certificate(ssl)) << std::endl; - - if(rsBanList && !rsBanList->isAddressAccepted( foreign_addr, checking_flags, check_result )) - { - RsInfo() << __PRETTY_FUNCTION__ - << " Refusing incoming SSL connection from blacklisted " - << "foreign address " << foreign_addr - << ". Reason: " << check_result << ". This should never happen " - << "at this point! Please report full log to developers!" - << std::endl; - print_stacktrace(); - - if(rsEvents) - { - X509 *x509 = SSL_get_peer_certificate(ssl); - auto ev = std::make_shared(); - ev->mSslId = RsX509Cert::getCertSslId(*x509); - ev->mLocator = RsUrl(foreign_addr); - ev->mErrorCode = RsAuthSslError::IP_IS_BLACKLISTED; - rsEvents->postEvent(ev); - } - - reset_locked(); - return failure; - } -#endif //def RS_BANLIST_REDUNDANT_CHECK - - if (waiting != WAITING_NOT) - { - RsInfo() << __PRETTY_FUNCTION__ << " Peer: " << PeerId() - << " - Two connections in progress - Shut 1 down!" - << std::endl; - - // outgoing connection in progress. - // shut this baby down. - // - // Thought I should shut down one in progress, and continue existing one! - // But the existing one might be broke.... take second. - // all we need is to never stop listening. - - switch(waiting) - { - case WAITING_SOCK_CONNECT: -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " STATE = Waiting Sock Connect " - << "- close the socket" << std::endl; -#endif - break; - case WAITING_SSL_CONNECTION: -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " STATE = Waiting SSL " - << "Connection - close sockfd + ssl_conn" << std::endl; -#endif - break; - case WAITING_SSL_AUTHORISE: -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " STATE = Waiting SSL Authorise" - << " - close sockfd + ssl_conn" << std::endl; -#endif - break; - case WAITING_FAIL_INTERFACE: -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " STATE = Failed, ignore?" - << std::endl; -#endif - break; - default: - std::cerr << __PRETTY_FUNCTION__ << " STATE = Unknown - resetting!" - << std::endl; - reset_locked(); - break; - } - } - - /* shutdown existing - in all cases use the new one */ - if ((ssl_connection) && (ssl_connection != ssl)) - { - RsInfo() << __PRETTY_FUNCTION__ - << " closing Previous/Existing ssl_connection" << std::endl; - SSL_shutdown(ssl_connection); - SSL_free (ssl_connection); - } - - if ((sockfd > -1) && (sockfd != fd)) - { - RsInfo() << __PRETTY_FUNCTION__ << " closing Previous/Existing sockfd" - << std::endl; - net_internal_close(sockfd); - } - - - // save ssl + sock. - - ssl_connection = ssl; - sockfd = fd; - - /* if we connected - then just writing the same over, - * but if from ssllistener then we need to save the address. - */ - sockaddr_storage_copy(foreign_addr, remote_addr); - - RsInfo() << __PRETTY_FUNCTION__ << " SUCCESSFUL connection to: " - << PeerId().toStdString() << " remoteaddr: " - << sockaddr_storage_iptostring(remote_addr) << std::endl; - -#ifdef PQISSL_DEBUG - { - int alg; - std::cerr << __PRETTY_FUNCTION__ << "SSL Cipher: " - << SSL_get_cipher(ssl) << std::endl << "SSL Cipher Bits: " - << SSL_get_cipher_bits(ssl, &alg) << " - " << alg - << std::endl; - } -#endif - - // make non-blocking / or check..... - int err; - if ((err = net_internal_fcntl_nonblock(sockfd)) < 0) - { - std::cerr << __PRETTY_FUNCTION__ << "Cannot make socket NON-Blocking " - << "reset!" << std::endl; - - active = false; - waiting = WAITING_FAIL_INTERFACE; // failed completely. - - reset_locked(); - return failure; - } -#ifdef PQISSL_DEBUG - else std::cerr << __PRETTY_FUNCTION__ << " Socket made non-nlocking!" - << std::endl; -#endif - - // we want to continue listening - incase this socket is crap, and they try again. - //stoplistening(); - - active = true; - waiting = WAITING_NOT; - -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << "connection complete - notifying parent" - << std::endl; -#endif - - // Notify the pqiperson.... (Both Connect/Receive) - if (parent()) - { - // Is the copy necessary? - sockaddr_storage addr; sockaddr_storage_copy(remote_addr, addr); - parent()->notifyEvent(this, NET_CONNECT_SUCCESS, addr); - } - return success; -} - -/********** Implementation of BinInterface ************************** - * All the rest of the BinInterface. - * This functions much be Mutex protected. - * - */ - -int pqissl::senddata(void *data, int len) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - int tmppktlen ; - - // safety check. Apparently this avoids some SIGSEGV. - // - if(ssl_connection == NULL) - return -1; - -#ifdef PQISSL_DEBUG - std::cout << "Sending data thread=" << pthread_self() << ", ssl=" << (void*)this << ", size=" << len << std::endl ; -#endif - ERR_clear_error(); - tmppktlen = SSL_write(ssl_connection, data, len) ; - - if (len != tmppktlen) - { - std::string out = "pqissl::senddata() " + PeerId().toStdString(); - rs_sprintf_append(out, " Partial Send: len: %d sent: %d ", len, tmppktlen); - - int err = SSL_get_error(ssl_connection, tmppktlen); - // incomplete operations - to repeat.... - // handled by the pqistreamer... - if (err == SSL_ERROR_SYSCALL) - { - rs_sprintf_append(out, "SSL_write() SSL_ERROR_SYSCALL SOCKET_DEAD -> calling reset() errno: %d ", errno); - out += socket_errorType(errno); - std::cerr << out << std::endl; - rslog(RSL_ALERT, pqisslzone, out); - - /* extra debugging - based on SSL_get_error() man page */ - { - int errsys = errno; - int sslerr = 0; - std::string out2; - rs_sprintf(out2, "SSL_ERROR_SYSCALL, ret == %d errno: %d %s\n", tmppktlen, errsys, socket_errorType(errsys).c_str()); - - while(0 != (sslerr = ERR_get_error())) - { - rs_sprintf_append(out2, "SSLERR:%d:", sslerr); - - char sslbuf[256] = {0}; - out2 += ERR_error_string(sslerr, sslbuf); - out2 += "\n"; - } - rslog(RSL_ALERT, pqisslzone, out2); - } - - rslog(RSL_ALERT, pqisslzone, "pqissl::senddata() -> calling reset()"); - reset_locked(); - return -1; - } - else if (err == SSL_ERROR_WANT_WRITE) - { - out += "SSL_write() SSL_ERROR_WANT_WRITE"; - rslog(RSL_WARNING, pqisslzone, out); - return -1; - } - else if (err == SSL_ERROR_WANT_READ) - { - out += "SSL_write() SSL_ERROR_WANT_READ"; - rslog(RSL_WARNING, pqisslzone, out); - //std::cerr << out << std::endl; - return -1; - } - else - { - rs_sprintf_append(out, "SSL_write() UNKNOWN ERROR: %d\n", err); - printSSLError(ssl_connection, tmppktlen, err, ERR_get_error(), out); - out += "\n\tResetting!"; - std::cerr << out << std::endl; - rslog(RSL_ALERT, pqisslzone, out); - - rslog(RSL_ALERT, pqisslzone, "pqissl::senddata() -> calling reset()"); - reset_locked(); - return -1; - } - } - return tmppktlen; -} - -int pqissl::readdata(void *data, int len) -{ - RS_STACK_MUTEX(mSslMtx); - -#ifdef PQISSL_DEBUG - std::cout << "Reading data thread=" << pthread_self() << ", ssl=" - << (void*)this << std::endl; -#endif - - // Safety check. Apparently this avoids some SIGSEGV. - if (ssl_connection == NULL) return -1; - - // There is a do, because packets can be splitted into multiple ssl buffers - // when they are larger than 16384 bytes. Such packets have to be read in - // multiple slices. - do - { - int tmppktlen; - -#ifdef PQISSL_DEBUG - std::cerr << "calling SSL_read. len=" << len << ", total_len=" - << total_len << std::endl; -#endif - ERR_clear_error(); - - tmppktlen = SSL_read(ssl_connection, - (void*)( &(((uint8_t*)data)[total_len])), - len-total_len); - -#ifdef PQISSL_DEBUG - std::cerr << "have read " << tmppktlen << " bytes" << std::endl ; - std::cerr << "data[0] = " - << (int)((uint8_t*)data)[total_len+0] << " " - << (int)((uint8_t*)data)[total_len+1] << " " - << (int)((uint8_t*)data)[total_len+2] << " " - << (int)((uint8_t*)data)[total_len+3] << " " - << (int)((uint8_t*)data)[total_len+4] << " " - << (int)((uint8_t*)data)[total_len+5] << " " - << (int)((uint8_t*)data)[total_len+6] << " " - << (int)((uint8_t*)data)[total_len+7] << std::endl ; -#endif - - // Need to catch errors..... - if (tmppktlen <= 0) // probably needs a reset. - { - std::string out; - - int error = SSL_get_error(ssl_connection, tmppktlen); - unsigned long err2 = ERR_get_error(); - - if ((error == SSL_ERROR_ZERO_RETURN) && (err2 == 0)) - { - /* this code will be called when - * (1) moretoread -> returns true. + - * (2) SSL_read fails. - * - * There are two ways this can happen: - * (1) there is a little data on the socket, but not enough - * for a full SSL record, so there legimitately is no error, and the moretoread() - * was correct, but the read fails. - * - * (2) the socket has been closed correctly. this leads to moretoread() -> true, - * and ZERO error.... we catch this case by counting how many times - * it occurs in a row (cos the other one will not). - */ - if (n_read_zero == 0) - { - /* first read_zero */ - mReadZeroTS = time(NULL); - } - - ++n_read_zero; - out += "pqissl::readdata() " + PeerId().toStdString(); - rs_sprintf_append(out, " SSL_read() SSL_ERROR_ZERO_RETURN : nReadZero: %d", n_read_zero); - - if ((PQISSL_MAX_READ_ZERO_COUNT < n_read_zero) - && (time(NULL) - mReadZeroTS > PQISSL_MAX_READ_ZERO_TIME)) - { - out += " Count passed Limit, shutting down!"; - rs_sprintf_append(out, " ReadZero Age: %ld", time(NULL) - mReadZeroTS); - - rslog(RSL_ALERT, pqisslzone, "pqissl::readdata() -> calling reset()"); - reset_locked(); - } - -#ifdef PQISSL_LOG_DEBUG2 - rslog(RSL_ALERT, pqisslzone, out); -#endif - //std::cerr << out << std::endl ; - return -1; - } - - /* the only real error we expect */ - if (error == SSL_ERROR_SYSCALL) - { - out += "pqissl::readdata() " + PeerId().toStdString(); - out += " SSL_read() SSL_ERROR_SYSCALL"; - out += " SOCKET_DEAD -> calling reset()"; - rs_sprintf_append(out, " errno: %d", errno); - out += " " + socket_errorType(errno); - rslog(RSL_ALERT, pqisslzone, out); - - /* extra debugging - based on SSL_get_error() man page */ - { - int syserr = errno; - int sslerr = 0; - std::string out2; - rs_sprintf(out2, "SSL_ERROR_SYSCALL, ret == %d errno: %d %s\n", tmppktlen, syserr, socket_errorType(syserr).c_str()); - - while(0 != (sslerr = ERR_get_error())) - { - rs_sprintf_append(out2, "SSLERR:%d : ", sslerr); - - char sslbuf[256] = {0}; - out2 += ERR_error_string(sslerr, sslbuf); - out2 += "\n"; - } - rslog(RSL_ALERT, pqisslzone, out2); - } - - rslog(RSL_ALERT, pqisslzone, "pqissl::readdata() -> calling reset()"); - reset_locked(); - std::cerr << out << std::endl ; - return -1; - } - else if (error == SSL_ERROR_WANT_WRITE) - { - out += "SSL_read() SSL_ERROR_WANT_WRITE"; - rslog(RSL_WARNING, pqisslzone, out); - std::cerr << out << std::endl ; - return -1; - } - else if (error == SSL_ERROR_WANT_READ) - { - // SSL_WANT_READ is not a crittical error. It's just a sign that - // the internal SSL buffer is not ready to accept more data. So -1 - // is returned, and the connection will be retried as is on next - // call of readdata(). - -#ifdef PQISSL_DEBUG - out += "SSL_read() SSL_ERROR_WANT_READ"; - rslog(RSL_DEBUG_BASIC, pqisslzone, out); -#endif - return -1; - } - else - { - rs_sprintf_append(out, "SSL_read() UNKNOWN ERROR: %d Resetting!", error); - rslog(RSL_ALERT, pqisslzone, out); - std::cerr << out << std::endl ; - std::cerr << ", SSL_read() output is " << tmppktlen << std::endl ; - - printSSLError(ssl_connection, tmppktlen, error, err2, out); - - rslog(RSL_ALERT, pqisslzone, "pqissl::readdata() -> calling reset()"); - reset_locked(); - return -1; - } - - rslog(RSL_ALERT, pqisslzone, out); - //exit(1); - } - else - total_len+=tmppktlen ; - } while(total_len < len) ; - -#ifdef PQISSL_DEBUG - std::cerr << "pqissl: have read data of length " << total_len << ", expected is " << len << std::endl ; -#endif - - if (len != total_len) - { - std::string out; - rs_sprintf(out, "pqissl::readdata() Full Packet Not read!\n -> Expected len(%d) actually read(%d)", len, total_len); - std::cerr << out << std::endl; - rslog(RSL_WARNING, pqisslzone, out); - } - total_len = 0 ; // reset the packet pointer as we have finished a packet. - n_read_zero = 0; - return len;//tmppktlen; -} - - -// dummy function currently. -int pqissl::netstatus() -{ - return 1; -} - -int pqissl::isactive() -{ - return active; // no need to mutex this. It's atomic. -} - -bool pqissl::moretoread(uint32_t usec) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - -#ifdef PQISSL_DEBUG - { - std::string out; - rs_sprintf(out, "pqissl::moretoread() polling socket (%d)", sockfd); - rslog(RSL_DEBUG_ALL, pqisslzone, out); - } -#endif - - if(sockfd == -1) - { - std::cerr << "pqissl::moretoread(): socket is invalid or closed." << std::endl; - return 0 ; - } - - fd_set ReadFDs, WriteFDs, ExceptFDs; - FD_ZERO(&ReadFDs); - FD_ZERO(&WriteFDs); - FD_ZERO(&ExceptFDs); - - FD_SET(sockfd, &ReadFDs); - // Dont set WriteFDs. - FD_SET(sockfd, &ExceptFDs); - - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = usec; - - if (select(sockfd + 1, &ReadFDs, &WriteFDs, &ExceptFDs, &timeout) < 0) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::moretoread() Select ERROR!"); - return 0; - } - - if (FD_ISSET(sockfd, &ExceptFDs)) - { - // error - reset socket. - rslog(RSL_ALERT, pqisslzone, - "pqissl::moretoread() Select Exception ERROR!"); - - // this is a definite bad socket!. - // reset. - rslog(RSL_ALERT, pqisslzone, "pqissl::moretoread() -> calling reset()"); - reset_locked(); - return 0; - } - - - if (FD_ISSET(sockfd, &ReadFDs)) - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::moretoread() Data to Read!"); -#endif - return 1; - } - else if(SSL_pending(ssl_connection) > 0) - { - return 1 ; - } - else - { -#ifdef PQISSL_DEBUG - rslog(RSL_DEBUG_ALL, pqisslzone, - "pqissl::moretoread() No Data to Read!"); -#endif - return 0; - } - -} - -bool pqissl::cansend(uint32_t usec) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - -#ifdef PQISSL_DEBUG - rslog(RSL_DEBUG_ALL, pqisslzone, - "pqissl::cansend() polling socket!"); -#endif - - if(sockfd == -1) - { - std::cerr << "pqissl::cansend(): socket is invalid or closed." << std::endl; - return 0 ; - } - - // Interestingly - This code might be portable.... - - fd_set ReadFDs, WriteFDs, ExceptFDs; - FD_ZERO(&ReadFDs); - FD_ZERO(&WriteFDs); - FD_ZERO(&ExceptFDs); - - // Dont Set ReadFDs. - FD_SET(sockfd, &WriteFDs); - FD_SET(sockfd, &ExceptFDs); - - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = usec; - - - if (select(sockfd + 1, &ReadFDs, &WriteFDs, &ExceptFDs, &timeout) < 0) - { - // select error. - rslog(RSL_ALERT, pqisslzone, - "pqissl::cansend() Select Error!"); - - return 0; - } - - if (FD_ISSET(sockfd, &ExceptFDs)) - { - // error - reset socket. - rslog(RSL_ALERT, pqisslzone, - "pqissl::cansend() Select Exception!"); - - // this is a definite bad socket!. - // reset. - rslog(RSL_ALERT, pqisslzone, "pqissl::cansend() -> calling reset()"); - reset_locked(); - return 0; - } - - if (FD_ISSET(sockfd, &WriteFDs)) - { -#ifdef PQISSL_DEBUG - // write can work. - rslog(RSL_DEBUG_ALL, pqisslzone, - "pqissl::cansend() Can Write!"); -#endif - return 1; - } - else - { -#ifdef PQISSL_DEBUG - // write can work. - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::cansend() Can *NOT* Write!"); -#endif - - return 0; - } - -} - -RsFileHash pqissl::gethash() { return RsFileHash(); } - -/********** End of Implementation of BinInterface ******************/ - - -int pqissl::net_internal_close(int fd) -{ - return unix_close(fd); -} - -int pqissl::net_internal_SSL_set_fd(SSL *ssl, int fd) -{ - return SSL_set_fd(ssl, fd); -} - -int pqissl::net_internal_fcntl_nonblock(int fd) -{ - return unix_fcntl_nonblock(fd); -} diff --git a/libretroshare/src/pqi/pqissl.h b/libretroshare/src/pqi/pqissl.h deleted file mode 100644 index 30905be5e..000000000 --- a/libretroshare/src/pqi/pqissl.h +++ /dev/null @@ -1,274 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissl.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -// operating system specific network header. -#include "pqi/pqinetwork.h" - -#include -#include - -#include "pqi/pqi_base.h" -#include "pqi/authssl.h" - -#define RS_PQISSL_AUTH_DOUBLE_CHECK 1 - -#define RS_PQISSL_BANLIST_DOUBLE_CHECK 1 - - -#define WAITING_NOT 0 -#define WAITING_DELAY 1 -#define WAITING_SOCK_CONNECT 2 -#define WAITING_SSL_CONNECTION 3 -#define WAITING_SSL_AUTHORISE 4 -#define WAITING_FAIL_INTERFACE 5 - -#define PQISSL_PASSIVE 0x00 -#define PQISSL_ACTIVE 0x01 - -const int PQISSL_LOCAL_FLAG = 0x01; -const int PQISSL_REMOTE_FLAG = 0x02; -const int PQISSL_DNS_FLAG = 0x04; - -/* not sure about the value? */ -const int PQISSL_UDP_FLAG = 0x02; - -/* TCP buffer size for Windows systems */ -const int WINDOWS_TCP_BUFFER_SIZE = 512 * 1024; // 512 KB - - -// This is a (very) simple overview of the different state machnines. The tree includes high level funtions only. -// -// connect_parameter() is used to pass down settings, like address or timeout values -// -// tick() or connect() -// | -// +----- ConnectAttempt() -// | -// +--WAITING_NOT or WAITING_DELAY -// | | -// | +----- Delay_Connection() -// | | -// | +--WAITING_NOT -// | | - set 'waiting' to WAITING_DELAY and set delay for next connection attempt -// | | -// | +--WAITING_DELAY -// | | -// | +----- Initiate_Connection() -// | | -// | +----- setup socket -// | +----- connect -// | - on success: set "waiting" to WAITING_SOCK_CONNECT and "sockfd" to newly created socket -// | - on failure: set "waiting" to WAITING_FAIL_INTERFACE -// | -// +--WAITING_SOCK_CONNECT -// | | -// | +----- Initiate_SSL_Connection() -// | | -// | +----- Basic_Connection_Complete() -// | | | -// | | +----- CheckConnectionTimeout() -// | | | -// | | +----- ready up socket. -// | | - SOCKS, udp tou, i2p BOB intercept here -// | | - on failure: set "waiting" to WAITING_FAIL_INTERFACE and "sockfd" to -1 -// | | -// | +----- create SSL context and attach file descriptors -// | - on success:_set "waiting" to WAITING_SSL_CONNECTION -// | -// +--WAITING_SSL_CONNECTION or WAITING_SSL_AUTHORISE -// | | -// | +----- Authorise_SSL_Connection() -// | | -// | +----- SSL_Connection_Complete() -// | | | -// | | +----- performes TSL handshake -// | | - on success: set "waiting" to WAITING_SSL_AUTHORISE -// | | - on failure: set "waiting" to WAITING_FAIL_INTERFACE -// | | -// | +----- set "waiting" to WAITING_NOT -// | | -// | +----- accept_locked() -// | - add peer to the rest of RS and start pqi thread -// | -// | -// +--WAITING_FAIL_INTERFACE -// | -// +----- Failed_Connection() -// - set "waiting" to WAITING_NOT -// - - -/***************************** pqi Net SSL Interface ********************************* - * This provides the base SSL interface class, - * and handles most of the required functionality. - * - * there are a series of small fn's that can be overloaded - * to provide alternative behaviour.... - * - * Classes expected to inherit from this are: - * - * pqissllistener -> pqissllistener (tcp only) - * -> pqixpgplistener (tcp only) - * - * pqissl -> pqissltcp - * -> pqissludp - * -> pqixpgptcp - * -> pqixpgpudp - * - */ - -class pqissllistener; -class p3LinkMgr; -struct RsPeerCryptoParams; - -class pqissl: public NetBinInterface -{ -public: - pqissl(pqissllistener *l, PQInterface *parent, - p3LinkMgr *lm); -virtual ~pqissl(); - - // NetInterface -virtual int connect(const struct sockaddr_storage &raddr); -virtual int listen(); -virtual int stoplistening(); -virtual int reset(); -virtual int disconnect(); -virtual int getConnectAddress(struct sockaddr_storage &raddr); - -virtual bool connect_parameter(uint32_t /*type*/, const std::string & /*value*/) { return false; } -virtual bool connect_parameter(uint32_t type, uint32_t value); - - // BinInterface -virtual int tick(); -virtual int status(); - -virtual int senddata(void*, int); -virtual int readdata(void*, int); -virtual int netstatus(); -virtual int isactive(); -virtual bool moretoread(uint32_t usec); -virtual bool cansend(uint32_t usec); - -virtual int close(); /* BinInterface version of reset() */ -virtual RsFileHash gethash(); /* not used here */ -virtual bool bandwidthLimited() { return true ; } - -public: - -/// initiate incoming connection. -int accept(SSL *ssl, int fd, const struct sockaddr_storage &foreign_addr); - -void getCryptoParams(RsPeerCryptoParams& params) ; -bool actAsServer(); - - -protected: - - - /* no mutex protection for these ones */ - - p3LinkMgr *mLinkMgr; - pqissllistener *pqil; - - RsMutex mSslMtx; /**** MUTEX protects data and fn below ****/ - -virtual int reset_locked(); - - /// initiate incoming connection. - int accept_locked( SSL *ssl, int fd, - const sockaddr_storage& foreign_addr ); - - // A little bit of information to describe - // the SSL state, this is needed - // to allow full Non-Blocking Connect behaviour. - // This fn loops through the following fns. - // to complete an SSL. - -int ConnectAttempt(); - -virtual int Failed_Connection(); - - // Start up connection with delay... -virtual int Delay_Connection(); - - // These two fns are overloaded for udp/etc connections. -virtual int Initiate_Connection(); -virtual int Basic_Connection_Complete(); - - // These should be identical for all cases, - // differences are achieved via the net_internal_* fns. -int Initiate_SSL_Connection(); -int SSL_Connection_Complete(); -int Authorise_SSL_Connection(); - - // check connection timeout. -bool CheckConnectionTimeout(); - - - /* Do we really need this ? - * It is very specific TCP+SSL stuff and unlikely to be reused. - * In fact we are overloading them in pqissludp case where they do different things or nothing. - */ - virtual int net_internal_close(int fd); - virtual int net_internal_SSL_set_fd(SSL *ssl, int fd); - virtual int net_internal_fcntl_nonblock(int fd); - - - /* data */ - bool active; - bool certvalid; - - int waiting; - - // addition for udp (tcp version == ACTIVE). - int sslmode; - - SSL *ssl_connection; - int sockfd; - - struct sockaddr_storage remote_addr; - - void *readpkt; - int pktlen; - int total_len ; // saves the reading state accross successive calls. - - int attempt_ts; - - int n_read_zero; /* a counter to determine if the connection is really dead */ - rstime_t mReadZeroTS; /* timestamp of first READ_ZERO occurance */ - - int ssl_connect_timeout; /* timeout to ensure that we don't get stuck (can happen on udp!) */ - - uint32_t mConnectDelay; - rstime_t mConnectTS; - uint32_t mConnectTimeout; - rstime_t mTimeoutTS; - - RS_SET_CONTEXT_DEBUG_LEVEL(1) - -private: - // ssl only fns. - int connectInterface(const struct sockaddr_storage &addr); -}; diff --git a/libretroshare/src/pqi/pqissli2pbob.cpp b/libretroshare/src/pqi/pqissli2pbob.cpp deleted file mode 100644 index 5551ce788..000000000 --- a/libretroshare/src/pqi/pqissli2pbob.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissli2pbob.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Sehraf * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqissli2pbob.h" - -bool pqissli2pbob::connect_parameter(uint32_t type, const std::string &value) -{ - if (type == NET_PARAM_CONNECT_DOMAIN_ADDRESS) - { - RS_STACK_MUTEX(mSslMtx); - // a new line must be appended! - mI2pAddr = value + '\n'; - return true; - } - - return pqissl::connect_parameter(type, value); -} - -int pqissli2pbob::Basic_Connection_Complete() -{ - int ret; - - if ((ret = pqissl::Basic_Connection_Complete()) != 1) - { - // basic connection not complete. - return ret; - } - - // send addr. (new line is already appended) - ret = send(sockfd, mI2pAddr.c_str(), mI2pAddr.length(), 0); - if (ret != (int)mI2pAddr.length()) - return -1; - return 1; -} diff --git a/libretroshare/src/pqi/pqissli2pbob.h b/libretroshare/src/pqi/pqissli2pbob.h deleted file mode 100644 index b1a643a75..000000000 --- a/libretroshare/src/pqi/pqissli2pbob.h +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissli2pbob.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Sehraf * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef PQISSLI2PBOB_H -#define PQISSLI2PBOB_H - -#include "pqi/pqissl.h" - -/* - * This class is a minimal varied version of pqissl to work with I2P BOB tunnels. - * The only difference is that the [.b32].i2p addresses must be sent first. - * - * Everything else is untouched. - */ - -class pqissli2pbob : public pqissl -{ -public: - pqissli2pbob(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) - : pqissl(l, parent, lm) {} - - // NetInterface interface -public: - bool connect_parameter(uint32_t type, const std::string &value); - - // pqissl interface -protected: - int Basic_Connection_Complete(); - -private: - std::string mI2pAddr; -}; - -#endif // PQISSLI2PBOB_H diff --git a/libretroshare/src/pqi/pqissllistener.cc b/libretroshare/src/pqi/pqissllistener.cc deleted file mode 100644 index fa25bfe0b..000000000 --- a/libretroshare/src/pqi/pqissllistener.cc +++ /dev/null @@ -1,883 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissllistener.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * Copyright (C) 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#include "pqi/pqissl.h" -#include "pqi/pqissllistener.h" -#include "pqi/pqinetwork.h" -#include "pqi/sslfns.h" -#include "pqi/p3peermgr.h" -#include "util/rsdebug.h" -#include "util/rsstring.h" -#include "retroshare/rsbanlist.h" -#include "pqi/authgpg.h" - -#include -#include -#include - -static struct RsLog::logInfo pqissllistenzoneInfo = {RsLog::Default, "p3peermgr"}; -#define pqissllistenzone &pqissllistenzoneInfo - -/* NB: This #define makes the listener open 0.0.0.0:X port instead - * of a specific port - this might help retroshare work on PCs with - * multiple interfaces or unique network setups. - * #define OPEN_UNIVERSAL_PORT 1 - */ - -//#define DEBUG_LISTENNER -#define OPEN_UNIVERSAL_PORT 1 - -/************************ PQI SSL LISTEN BASE **************************** - * - * This provides all of the basic connection stuff, - * and calls completeConnection afterwards... - * - */ - - -pqissllistenbase::pqissllistenbase(const sockaddr_storage &addr, p3PeerMgr *pm) - : mPeerMgr(pm), active(false) -{ - sockaddr_storage_copy(addr, laddr); - - if (!(AuthSSL::getAuthSSL()-> active())) - { - pqioutput(PQL_ALERT, pqissllistenzone, - "SSL-CTX-CERT-ROOT not initialised!"); - exit(1); - } - - setuplisten(); -} - -pqissllistenbase::~pqissllistenbase() -{ - if(lsock != -1) - { -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - shutdown(lsock, SHUT_RDWR); - close(lsock); -#else //WINDOWS_SYS - closesocket(lsock); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - } -} - -int pqissllistenbase::tick() -{ - status(); - // check listen port. - acceptconnection(); - continueaccepts(); - return finaliseAccepts(); -} - -int pqissllistenbase::status() -{ - std::string out; - rs_sprintf(out, "pqissllistenbase::status(): Listening on port: %u", sockaddr_storage_port(laddr)); - pqioutput(PQL_DEBUG_ALL, pqissllistenzone, out); - return 1; -} - -int pqissllistenbase::setuplisten() -{ - int err; - if (active) return -1; - - lsock = socket(PF_INET6, SOCK_STREAM, 0); - -#ifdef IPV6_V6ONLY - int no = 0; - err = rs_setsockopt(lsock, IPPROTO_IPV6, IPV6_V6ONLY, - reinterpret_cast(&no), sizeof(no)); - if (err) std::cerr << __PRETTY_FUNCTION__ - << ": Error setting IPv6 socket dual stack" << std::endl; -#ifdef DEBUG_LISTENNER - else std::cerr << __PRETTY_FUNCTION__ - << ": Success setting IPv6 socket dual stack" << std::endl; -#endif -#endif // IPV6_V6ONLY - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - if (lsock < 0) - { - pqioutput(PQL_ALERT, pqissllistenzone, - "pqissllistenbase::setuplisten() Cannot Open Socket!"); - - return -1; - } - - err = fcntl(lsock, F_SETFL, O_NONBLOCK); - if (err < 0) - { - shutdown(lsock,SHUT_RDWR) ; - close(lsock) ; - lsock = -1 ; - - std::string out; - rs_sprintf(out, "Error: Cannot make socket NON-Blocking: %d", err); - pqioutput(PQL_ERROR, pqissllistenzone, out); - - return -1; - } - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else //WINDOWS_SYS - if ((unsigned) lsock == INVALID_SOCKET) - { - std::string out = "pqissllistenbase::setuplisten() Cannot Open Socket!\n"; - out += "Socket Error: "+ socket_errorType(WSAGetLastError()); - pqioutput(PQL_ALERT, pqissllistenzone, out); - - return -1; - } - - // Make nonblocking. - unsigned long int on = 1; - if (0 != (err = ioctlsocket(lsock, FIONBIO, &on))) - { - closesocket(lsock) ; - lsock = -1 ; - - std::string out; - rs_sprintf(out, "pqissllistenbase::setuplisten() Error: Cannot make socket NON-Blocking: %d\n", err); - out += "Socket Error: " + socket_errorType(WSAGetLastError()); - pqioutput(PQL_ALERT, pqissllistenzone, out); - - return -1; - } -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - // setup listening address. - - { - std::string out = "pqissllistenbase::setuplisten()\n"; - out += "\t FAMILY: " + sockaddr_storage_familytostring(laddr); - out += "\t ADDRESS: " + sockaddr_storage_tostring(laddr); - - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - //std::cerr << out.str() << std::endl; - } - - /* added a call to REUSEADDR, so that we can re-open an existing socket - * when we restart_listener. - */ - - { - int on = 1; - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - if (setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) -#else //WINDOWS_SYS - if (setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on)) < 0) -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - { - std::string out = "pqissllistenbase::setuplisten() Cannot setsockopt SO_REUSEADDR!\n"; - showSocketError(out); - pqioutput(PQL_ALERT, pqissllistenzone, out); - std::cerr << out << std::endl; - - exit(1); - } - } - - struct sockaddr_storage tmpaddr; - sockaddr_storage_copy(laddr, tmpaddr); - sockaddr_storage_ipv4_to_ipv6(tmpaddr); - if (!mPeerMgr->isHidden()) sockaddr_storage_zeroip(tmpaddr); - - if (0 != (err = rs_bind(lsock, tmpaddr))) - { - std::string out = "pqissllistenbase::setuplisten() Cannot Bind to Local Address!\n"; - showSocketError(out); - pqioutput(PQL_ALERT, pqissllistenzone, out); - std::cerr << out << std::endl - << "tmpaddr: " << sockaddr_storage_tostring(tmpaddr) - << std::endl; - print_stacktrace(); - - return -1; - } - else - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, - "pqissllistenbase::setuplisten() Bound to Address."); - } - -#ifdef WINDOWS_SYS - /* Set TCP buffer size for Windows systems */ - - int sockbufsize = 0; - int size = sizeof(int); - - err = getsockopt(lsock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size); - if (err == 0) { - std::cerr << "pqissllistenbase::setuplisten: Current TCP receive buffer size " << sockbufsize << std::endl; - } else { - std::cerr << "pqissllistenbase::setuplisten: Error getting TCP receive buffer size. Error " << err << std::endl; - } - - sockbufsize = 0; - - err = getsockopt(lsock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size); - - if (err == 0) { - std::cerr << "pqissllistenbase::setuplisten: Current TCP send buffer size " << sockbufsize << std::endl; - } else { - std::cerr << "pqissllistenbase::setuplisten: Error getting TCP send buffer size. Error " << err << std::endl; - } - - sockbufsize = WINDOWS_TCP_BUFFER_SIZE; - - err = setsockopt(lsock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, sizeof(sockbufsize)); - - if (err == 0) { - std::cerr << "pqissllistenbase::setuplisten: TCP receive buffer size set to " << sockbufsize << std::endl; - } else { - std::cerr << "pqissllistenbase::setuplisten: Error setting TCP receive buffer size. Error " << err << std::endl; - } - - err = setsockopt(lsock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, sizeof(sockbufsize)); - - if (err == 0) { - std::cerr << "pqissllistenbase::setuplisten: TCP send buffer size set to " << sockbufsize << std::endl; - } else { - std::cerr << "pqissllistenbase::setuplisten: Error setting TCP send buffer size. Error " << err << std::endl; - } -#endif - - if (0 != (err = listen(lsock, 100))) - { - std::string out; - rs_sprintf(out, "pqissllistenbase::setuplisten() Error: Cannot Listen to Socket: %d\n", err); - showSocketError(out); - pqioutput(PQL_ALERT, pqissllistenzone, out); - std::cerr << out << std::endl; - - exit(1); - return -1; - } - else - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, - "pqissllistenbase::setuplisten() Listening to Socket"); - } - active = true; - return 1; -} - -int pqissllistenbase::setListenAddr(const struct sockaddr_storage &addr) -{ - laddr = addr; - return 1; -} - -int pqissllistenbase::resetlisten() -{ - if (active) - { - // close ports etc. -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - shutdown(lsock, SHUT_RDWR); - close(lsock); -#else //WINDOWS_SYS - closesocket(lsock); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - lsock = -1; - active = false; - return 1; - } - - return 0; -} - - -int pqissllistenbase::acceptconnection() -{ - if (!active) - return 0; - // check port for any socets... - pqioutput(PQL_DEBUG_ALL, pqissllistenzone, "pqissllistenbase::accepting()"); - - // These are local but temp variables... - // can't be arsed making them all the time. - struct sockaddr_storage remote_addr; - socklen_t addrlen = sizeof(remote_addr); - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - int fd = accept(lsock, (struct sockaddr *) &remote_addr, &addrlen); - int err = 0; - - if (fd < 0) - { - pqioutput(PQL_DEBUG_ALL, pqissllistenzone, - "pqissllistenbase::acceptconnnection() Nothing to Accept!"); - return 0; - } - - err = fcntl(fd, F_SETFL, O_NONBLOCK); - if (err < 0) - { - std::string out; - rs_sprintf(out, "pqissllistenbase::acceptconnection() Error: Cannot make socket NON-Blocking: %d", err); - pqioutput(PQL_ERROR, pqissllistenzone, out); - - close(fd); - return -1; - } - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else //WINDOWS_SYS - SOCKET fd = accept(lsock, (struct sockaddr *) &remote_addr, &addrlen); - int err = 0; - - if (fd == INVALID_SOCKET) - { - pqioutput(PQL_DEBUG_ALL, pqissllistenzone, - "pqissllistenbase::acceptconnnection() Nothing to Accept!"); - return 0; - } - - // Make nonblocking. - unsigned long int on = 1; - if (0 != (err = ioctlsocket(fd, FIONBIO, &on))) - { - std::string out; - rs_sprintf(out, "pqissllistenbase::acceptconnection() Error: Cannot make socket NON-Blocking: %d\n", err); - out += "Socket Error:" + socket_errorType(WSAGetLastError()); - pqioutput(PQL_ALERT, pqissllistenzone, out); - - closesocket(fd); - return 0; - } -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - std::cerr << "(II) Checking incoming connection address: " << sockaddr_storage_iptostring(remote_addr) ; - if(rsBanList != NULL && !rsBanList->isAddressAccepted(remote_addr, RSBANLIST_CHECKING_FLAGS_BLACKLIST)) - { - std::cerr << " => early rejected at this point, because of blacklist." << std::endl; -#ifndef WINDOWS_SYS - close(fd); -#else - closesocket(fd); -#endif - return false ; - } - else - std::cerr << " => Accepted (i.e. whitelisted, or not blacklisted)." << std::endl; - - { - std::string out; - out += "Accepted Connection from "; - out += sockaddr_storage_tostring(remote_addr); - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - } - - // Negotiate certificates. SSL stylee. - // Allow negotiations for secure transaction. - - IncomingSSLInfo incoming_connexion_info ; - - incoming_connexion_info.ssl = SSL_new(AuthSSL::getAuthSSL() -> getCTX()); - incoming_connexion_info.addr = remote_addr ; - incoming_connexion_info.gpgid.clear() ; - incoming_connexion_info.sslid.clear() ; - incoming_connexion_info.sslcn = "" ; - - SSL_set_fd(incoming_connexion_info.ssl, fd); - - return continueSSL(incoming_connexion_info, true); // continue and save if incomplete. -} - -int pqissllistenbase::continueSSL(IncomingSSLInfo& incoming_connexion_info, bool addin) -{ - // attempt the accept again. - int fd = SSL_get_fd(incoming_connexion_info.ssl); - int err = SSL_accept(incoming_connexion_info.ssl); - - if (err <= 0) - { - int ssl_err = SSL_get_error(incoming_connexion_info.ssl, err); - int err_err = ERR_get_error(); - - { - std::string out; - rs_sprintf(out, "pqissllistenbase::continueSSL() Issues with SSL Accept(%d)!\n", err); - printSSLError(incoming_connexion_info.ssl, err, ssl_err, err_err, out); - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - } - - switch (ssl_err) { - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - { - std::string out = "pqissllistenbase::continueSSL() Connection Not Complete!\n"; - - if (addin) - { - out += "pqissllistenbase::continueSSL() Adding SSL to incoming!"; - - // add to incomingqueue. - incoming_ssl.push_back(incoming_connexion_info) ; - } - - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - - // zero means still continuing.... - return 0; - } - break; - case SSL_ERROR_SYSCALL: - { - std::string out = "pqissllistenbase::continueSSL() Connection failed!\n"; - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - - closeConnection(fd, incoming_connexion_info.ssl); - - // basic-error while connecting, no security message needed - return -1; - } - break; - } - - pqioutput(PQL_WARNING, pqissllistenzone, "Read Error on the SSL Socket\nShutting it down!"); - - // We use SSL_get_verify_result() in order to differentiate two cases: - // case 1: the incoming connection is closed because the peer is not a friend. This is already handled in authssl. - // case 2: the incoming connection is closed because no authentication info is available, in which case it returns X509_V_OK - auto vres = SSL_get_verify_result(incoming_connexion_info.ssl); - - if(vres == X509_V_OK && nullptr != rsEvents) - { - auto ev = std::make_shared(); - ev->mLocator = RsUrl(incoming_connexion_info.addr); - ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO; - rsEvents->postEvent(ev); - } - closeConnection(fd, incoming_connexion_info.ssl); - - // failure -1, pending 0, sucess 1. - return -1; - } - - // Now grab the connection info from the SSL itself, because the callback info might be - // tempered due to multiple connection attempts at once. - // - X509 *x509 = SSL_get_peer_certificate(incoming_connexion_info.ssl) ; - - if(x509) - { - incoming_connexion_info.gpgid = RsX509Cert::getCertIssuer(*x509); - incoming_connexion_info.sslcn = RsX509Cert::getCertName(*x509); - incoming_connexion_info.sslid = RsX509Cert::getCertSslId(*x509); - -#ifndef DEBUG_LISTENNER - std::cerr << "ContinueSSL:" << std::endl; - std::cerr << " Got PGP Id = " << incoming_connexion_info.gpgid << std::endl; - std::cerr << " Got SSL Id = " << incoming_connexion_info.sslid << std::endl; - std::cerr << " Got SSL CN = " << incoming_connexion_info.sslcn << std::endl; -#endif - } - -#ifdef DEBUG_LISTENNER - else - std::cerr << " no info." << std::endl; -#endif - - // if it succeeds - if (0 < completeConnection(fd, incoming_connexion_info)) - return 1; - - /* else we shut it down! */ - pqioutput(PQL_WARNING, pqissllistenzone, - "pqissllistenbase::completeConnection() Failed!"); - - closeConnection(fd, incoming_connexion_info.ssl) ; - - pqioutput(PQL_WARNING, pqissllistenzone, "Shutting it down!"); - - // failure -1, pending 0, sucess 1. - return -1; -} - - -int pqissllistenbase::closeConnection(int fd, SSL *ssl) -{ - /* else we shut it down! */ - pqioutput(PQL_WARNING, pqissllistenzone, "pqissllistenbase::closeConnection() Shutting it Down!"); - - // delete ssl connection. - SSL_shutdown(ssl); - - // close socket??? -/************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - shutdown(fd, SHUT_RDWR); - close(fd); -#else //WINDOWS_SYS - closesocket(fd); -#endif -/************************** WINDOWS/UNIX SPECIFIC PART ******************/ - // free connection. - SSL_free(ssl); - - return 1; -} - -int pqissllistenbase::continueaccepts() -{ - - // for each of the incoming sockets.... call continue. - - for(std::list::iterator it = incoming_ssl.begin(); it != incoming_ssl.end();) - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, "pqissllistenbase::continueaccepts() Continuing SSL"); - - if (0 != continueSSL( *it, false)) - { - pqioutput(PQL_DEBUG_ALERT, pqissllistenzone, - "pqissllistenbase::continueaccepts() SSL Complete/Dead!"); - - /* save and increment -> so we can delete */ - std::list::iterator itd = it++; - incoming_ssl.erase(itd); - } - else - ++it; - } - return 1; -} - -#define ACCEPT_WAIT_TIME 30 - -int pqissllistenbase::finaliseAccepts() -{ - - // for each of the incoming sockets.... call continue. - std::list::iterator it; - - rstime_t now = time(NULL); - for(it = accepted_ssl.begin(); it != accepted_ssl.end();) - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, - "pqissllistenbase::finalisedAccepts() Continuing SSL Accept"); - - /* check that the socket is still active - how? */ - int active = isSSLActive(it->mFd, it->mSSL); - if (active > 0) - { - pqioutput(PQL_WARNING, pqissllistenzone, - "pqissllistenbase::finaliseAccepts() SSL Connection Ok => finaliseConnection"); - - if (0 > finaliseConnection(it->mFd, it->mSSL, it->mPeerId, it->mAddr)) - { - closeConnection(it->mFd, it->mSSL); - } - it = accepted_ssl.erase(it); - } - else if (active < 0) - { - pqioutput(PQL_WARNING, pqissllistenzone, - "pqissllistenbase::finaliseAccepts() SSL Connection Dead => closeConnection"); - - closeConnection(it->mFd, it->mSSL); - it = accepted_ssl.erase(it); - } - else if (now - it->mAcceptTS > ACCEPT_WAIT_TIME) - { - pqioutput(PQL_WARNING, pqissllistenzone, - "pqissllistenbase::finaliseAccepts() SSL Connection Timed Out => closeConnection"); - closeConnection(it->mFd, it->mSSL); - it = accepted_ssl.erase(it); - } - else - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, - "pqissllistenbase::finaliseAccepts() SSL Connection Status Unknown"); - ++it; - } - } - return 1; -} - -int pqissllistenbase::isSSLActive(int /*fd*/, SSL *ssl) -{ - - /* can we just get error? */ - int bufsize = 8; /* just a little look */ - uint8_t buf[bufsize]; - int err = SSL_peek(ssl, buf, bufsize); - if (err <= 0) - { - int ssl_err = SSL_get_error(ssl, err); - int err_err = ERR_get_error(); - - { - std::string out; - rs_sprintf(out, "pqissllistenbase::isSSLActive() Issues with SSL_Accept(%d)!\n", err); - printSSLError(ssl, err, ssl_err, err_err, out); - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - } - - if (ssl_err == SSL_ERROR_ZERO_RETURN) - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, "pqissllistenbase::isSSLActive() SSL_ERROR_ZERO_RETURN Connection state unknown"); - - // zero means still continuing.... - return 0; - } - if ((ssl_err == SSL_ERROR_WANT_READ) || - (ssl_err == SSL_ERROR_WANT_WRITE)) - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, "pqissllistenbase::isSSLActive() SSL_ERROR_WANT_READ || SSL_ERROR_WANT_WRITE Connection state unknown"); - - // zero means still continuing.... - return 0; - } - else - { - std::string out; - rs_sprintf(out, "pqissllistenbase::isSSLActive() Issues with SSL Peek(%d) Likely the Connection was killed by Peer\n", err); - printSSLError(ssl, err, ssl_err, err_err, out); - pqioutput(PQL_ALERT, pqissllistenzone, out); - - return -1; - } - } - - pqioutput(PQL_WARNING, pqissllistenzone, "pqissllistenbase::isSSLActive() Successful Peer -> Connection Okay"); - - return 1; -} - -/************************ PQI SSL LISTENER **************************** - * - * This is the standard pqissl listener interface.... - * - * this class only allows connections from - * specific certificates, which are pre specified. - * - */ - -int pqissllistener::addlistenaddr(const RsPeerId& id, pqissl *acc) -{ - std::map::iterator it; - - std::string out = "Adding to Cert Listening Addresses Id: " + id.toStdString() + "\nCurrent Certs:\n"; - for(it = listenaddr.begin(); it != listenaddr.end(); ++it) - { - out += id.toStdString() + "\n"; - if (it -> first == id) - { - out += "pqissllistener::addlistenaddr() Already listening for Certificate!\n"; - - pqioutput(PQL_DEBUG_ALERT, pqissllistenzone, out); - return -1; - } - } - - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - - // not there can accept it! - listenaddr[id] = acc; - return 1; -} - -int pqissllistener::removeListenPort(const RsPeerId& id) -{ - // check where the connection is coming from. - // if in list of acceptable addresses, - // - // check if in list. - std::map::iterator it; - for(it = listenaddr.begin();it!=listenaddr.end(); ++it) - { - if (it->first == id) - { - listenaddr.erase(it); - - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, - "pqissllisten::removeListenPort() Success!"); - return 1; - } - } - - pqioutput(PQL_WARNING, pqissllistenzone, - "pqissllistener::removeListenPort() Failed to Find a Match"); - - return -1; -} - - -int pqissllistener::status() -{ - pqissllistenbase::status(); - // print certificates we are listening for. - std::map::iterator it; - - std::string out = "pqissllistener::status(): Listening ("; - out += sockaddr_storage_tostring(laddr); - out += ") for Certs:"; - for(it = listenaddr.begin(); it != listenaddr.end(); ++it) - { - out += "\n" + it -> first.toStdString() ; - } - pqioutput(PQL_DEBUG_ALL, pqissllistenzone, out); - - return 1; -} - -int pqissllistener::completeConnection(int fd, IncomingSSLInfo& info) -{ - constexpr int failure = -1; - constexpr int success = 1; - - // Get the Peer Certificate.... - X509* peercert = SSL_get_peer_certificate(info.ssl); - if(!peercert) - { - RsFatal() << __PRETTY_FUNCTION__ << " failed to retrieve peer " - << "certificate at this point this should never happen!" - << std::endl; - print_stacktrace(); - exit(failure); - } - - RsPgpId pgpId = RsX509Cert::getCertIssuer(*peercert); - RsPeerId newPeerId = RsX509Cert::getCertSslId(*peercert); - -#ifdef RS_PQISSL_AUTH_DOUBLE_CHECK - /* At this point the actual connection authentication has already been - * performed in AuthSSL::VerifyX509Callback, any furter authentication check - * like the followings are redundant. */ - - bool isSslOnlyFriend = rsPeers->isSslOnlyFriend(newPeerId); - - uint32_t authErrCode = 0; - if( !isSslOnlyFriend && - !AuthSSL::instance().AuthX509WithGPG(peercert,false, authErrCode) ) - { - RsFatal() << __PRETTY_FUNCTION__ << " failure verifying peer " - << "certificate signature. This should never happen at this " - << "point!" << std::endl; - print_stacktrace(); - - X509_free(peercert); // not needed but just in case we change to return - exit(failure); - } - - if( !isSslOnlyFriend && pgpId != AuthGPG::getAuthGPG()->getGPGOwnId() && - !AuthGPG::getAuthGPG()->isGPGAccepted(pgpId) ) - { - RsFatal() << __PRETTY_FUNCTION__ << " pgpId: " << pgpId - << " is not friend. It is very unlikely to happen at this " - << "point! Either the user must have been so fast to deny " - << "friendship just after VerifyX509Callback have returned " - << "success and just before this code being executed, or " - << "something really fishy is happening! Share the full log " - << "with developers." << std::endl; - print_stacktrace(); - - X509_free(peercert); // not needed but just in case we change to return - exit(failure); - } -#endif //def RS_PQISSL_AUTH_REDUNDANT_CHECK - - bool found = false; - for(auto it = listenaddr.begin(); !found && it != listenaddr.end(); ) - { - if (it -> first == newPeerId) found = true; - else ++it; - } - - if (!found) - { - Dbg1() << __PRETTY_FUNCTION__ << " got secure connection from address: " - << info.addr << " with previously unknown SSL certificate: " - << newPeerId << " signed by PGP friend: " << pgpId - << ". Adding the new location as SSL friend." << std::endl; - - mPeerMgr->addFriend(newPeerId, pgpId); - } - - // Cleanup cert. - X509_free(peercert); - - // Pushback into Accepted List. - AcceptedSSL as; - as.mFd = fd; - as.mSSL = info.ssl; - as.mPeerId = newPeerId; - as.mAddr = info.addr; - as.mAcceptTS = time(nullptr); - - accepted_ssl.push_back(as); - - Dbg1() << __PRETTY_FUNCTION__ << "Successful Connection with: " - << newPeerId << " with address: " << info.addr << std::endl; - - return success; -} - -int pqissllistener::finaliseConnection(int fd, SSL *ssl, const RsPeerId& peerId, const struct sockaddr_storage &remote_addr) -{ - std::map::iterator it; - - std::string out = "pqissllistener::finaliseConnection()\n"; - out += "checking: " + peerId.toStdString() + "\n"; - // check if cert is in the list..... - - it = listenaddr.find(peerId); - if (it == listenaddr.end()) - { - out += "No Matching Peer for Connection:"; - out += sockaddr_storage_tostring(remote_addr); - out += "\npqissllistener => Shutting Down!"; - pqioutput(PQL_WARNING, pqissllistenzone, out); - return -1; - } - - out += "Found Matching Peer for Connection:"; - out += sockaddr_storage_tostring(remote_addr); - out += "\npqissllistener => Passing to pqissl module!"; - pqioutput(PQL_WARNING, pqissllistenzone, out); - - std::cerr << "pqissllistenner::finaliseConnection() connected to " << sockaddr_storage_tostring(remote_addr) << std::endl; - - // hand off ssl conection. - pqissl *pqis = it -> second; - pqis -> accept(ssl, fd, remote_addr); - - return 1; -} diff --git a/libretroshare/src/pqi/pqissllistener.h b/libretroshare/src/pqi/pqissllistener.h deleted file mode 100644 index 85af2d869..000000000 --- a/libretroshare/src/pqi/pqissllistener.h +++ /dev/null @@ -1,193 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissllistener.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include -#include - -#include "pqi/pqi_base.h" -#include "pqi/pqilistener.h" -#include "pqi/authssl.h" -#include "util/rsdebug.h" -#include "pqi/pqinetwork.h" - -#define RS_PQISSL_AUTH_DOUBLE_CHECK 1 - - -// This is a simple overview of how the listener is setup, ticked (calling accept) and peers added to it. -// On the highest level (RsServer) the listener lives inside the pqisslpersongrp class (variable: "pqih"). -// Inside pqisslpersongrp the listener is stored in "pqil". -// -// The listener has an internal list with incoming connections that are handled in a similar fashion to pqissl. -// (Mainly setting up the socket (non-blocking) and establisching the ssl handshake.) -// When everything went fine the connection is passed to pqissl in finaliseConnection() -// -// This is how the listener is initialized during start up: -// -// RsServer::StartupRetroShare() -// | -// +----- pqih = new pqisslpersongrp(serviceCtrl, flags, mPeerMgr); -// +----- pqih->init_listener(); -// | -// +----- pqil = locked_createListener(laddr); -// | -// +----- return new pqissllistener(laddr, mPeerMgr); -// -// -// This is how the listener is ticked to call accept: -// -// RsServer::StartupRetroShare() -// | -// +----- pqih->tick(); -// | -// +----- pqil->tick(); -// | -// +----- acceptconnection(); -// | | -// | +----- accecpt() -// | -// +----- continueaccepts(); -// +----- finaliseAccepts(); -// | -// +----- finaliseConnection() -// | -// +----- pqis->accept() -// -// -// This is how peers (their id) are registered to the listener: -// (This is only used to tell if a connection peer is known or a new one (which is then added)) -// -// pqipersongrp::addPeer() -// | -// +----- pqiperson *pqip = locked_createPerson(id, pqil); -// | | -// | +----- pqiperson *pqip = new pqiperson(id, this); -// | +----- pqissl *pqis = new pqissl((pqissllistener *) listener, pqip, mLinkMgr); -// | +----- pqiconnect *pqisc = new pqiconnect(pqip, rss, pqis); -// | +----- pqip->addChildInterface(PQI_CONNECT_TCP, pqisc); -// | | -// | +-- sets kids[type] = pqisc; -// | -// +----- pqip->reset(); -// +----- pqip->listen(); -// | -// +-- for all kids[] -// | -// +----- listen() ( of class pqiconnect ) -// | -// +----- listen() ( of class pqissl ) -// | -// +----- pqil->addlistenaddr(PeerId(), this); - - -/***************************** pqi Net SSL Interface ********************************* - */ - -class pqissl; -class p3PeerMgr; - -class AcceptedSSL -{ -public: - int mFd; - SSL *mSSL; - RsPeerId mPeerId; - - sockaddr_storage mAddr; - rstime_t mAcceptTS; -}; - - - - -class pqissllistenbase: public pqilistener -{ -public: - pqissllistenbase(const struct sockaddr_storage &addr, p3PeerMgr *pm); - virtual ~pqissllistenbase(); - - /*************************************/ - /* LISTENER INTERFACE */ - virtual int tick(); - virtual int status(); - virtual int setListenAddr(const struct sockaddr_storage &addr); - virtual int setuplisten(); - virtual int resetlisten(); - /*************************************/ - - int acceptconnection(); - int continueaccepts(); - int finaliseAccepts(); - - struct IncomingSSLInfo - { - SSL *ssl ; - sockaddr_storage addr ; - RsPgpId gpgid ; - RsPeerId sslid ; - std::string sslcn ; - }; - - // fn to get cert, anyway - int continueSSL(IncomingSSLInfo&, bool); - int closeConnection(int fd, SSL *ssl); - int isSSLActive(int fd, SSL *ssl); - - virtual int completeConnection(int sockfd, IncomingSSLInfo&) = 0; - virtual int finaliseConnection(int fd, SSL *ssl, const RsPeerId& peerId, - const sockaddr_storage &raddr) = 0; - -protected: - struct sockaddr_storage laddr; - std::list accepted_ssl; - p3PeerMgr *mPeerMgr; - -private: - - bool active; - int lsock; - std::list incoming_ssl ; -}; - - -class pqissllistener: public pqissllistenbase -{ -public: - pqissllistener(const struct sockaddr_storage &addr, p3PeerMgr *pm) : - pqissllistenbase(addr, pm) {} - virtual ~pqissllistener() {} - - int addlistenaddr(const RsPeerId& id, pqissl *acc); - int removeListenPort(const RsPeerId& id); - - virtual int status(); - virtual int completeConnection(int sockfd, IncomingSSLInfo&); - virtual int finaliseConnection(int fd, SSL *ssl, const RsPeerId& peerId, - const sockaddr_storage &raddr); - -private: - std::map listenaddr; - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; diff --git a/libretroshare/src/pqi/pqisslpersongrp.cc b/libretroshare/src/pqi/pqisslpersongrp.cc deleted file mode 100644 index 7016a2fa6..000000000 --- a/libretroshare/src/pqi/pqisslpersongrp.cc +++ /dev/null @@ -1,184 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqisslpersongrp.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rsserializer.h" -#include "services/autoproxy/rsautoproxymonitor.h" -#include "util/rsdebug.h" - -#include "pqi/pqisslpersongrp.h" -#include "pqi/authssl.h" - -static struct RsLog::logInfo pqipersongrpzoneInfo = {RsLog::Default, "pqipersongrp"}; -#define pqipersongrpzone &pqipersongrpzoneInfo - -/**** - * #define PQI_DISABLE_UDP 1 - ***/ - -/********************************** SSL Specific features ***************************/ - -#include "pqi/pqissl.h" -#include "pqi/pqissllistener.h" -#include "pqi/p3peermgr.h" - -//#define PQISSLPERSON_DEBUG - -#ifndef PQI_DISABLE_UDP - #include "pqi/pqissludp.h" -#endif - -#include "pqi/pqisslproxy.h" -#include "pqi/pqissli2pbob.h" - -pqilistener * pqisslpersongrp::locked_createListener(const struct sockaddr_storage &laddr) -{ - pqilistener *listener = new pqissllistener(laddr, mPeerMgr); - return listener; -} - -pqiperson * pqisslpersongrp::locked_createPerson(const RsPeerId& id, pqilistener *listener) -{ -#ifdef PQISSLPERSON_DEBUG - std::cerr << "pqisslpersongrp::locked_createPerson() PeerId: " << id; - std::cerr << std::endl; -#endif - - pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, "pqipersongrp::createPerson() PeerId: " + id.toStdString()); - - pqiperson *pqip = new pqiperson(id, this); - - // If using proxy, then only create a proxy item, otherwise can use any. - // If we are a hidden node - then all connections should be via proxy. - if (mPeerMgr->isHiddenPeer(id) || mPeerMgr->isHidden()) - { -#ifdef PQISTREAMER_DEBUG - std::cerr << "pqisslpersongrp::locked_createPerson() Is Hidden Peer!"; - std::cerr << std::endl; -#endif - - // Use pqicI2PBOB for I2P - pqiconnect *pqicSOCKSProxy, *pqicI2PBOB; - { - pqisslproxy *pqis = new pqisslproxy((pqissllistener *) listener, pqip, mLinkMgr); - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsRawSerialiser()); - pqicSOCKSProxy = new pqiconnect(pqip, rss, pqis); - } - if (rsAutoProxyMonitor::instance()->isEnabled(autoProxyType::I2PBOB)) - { - pqissli2pbob *pqis = new pqissli2pbob((pqissllistener *) listener, pqip, mLinkMgr); - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsRawSerialiser()); - - pqicI2PBOB = new pqiconnect(pqip, rss, pqis); - } else { - pqicI2PBOB = pqicSOCKSProxy; - } - - - /* first select type based on peer */ - uint32_t typePeer = mPeerMgr->getHiddenType(id); - switch (typePeer) { - case RS_HIDDEN_TYPE_TOR: - pqip -> addChildInterface(PQI_CONNECT_HIDDEN_TOR_TCP, pqicSOCKSProxy); - break; - case RS_HIDDEN_TYPE_I2P: - pqip -> addChildInterface(PQI_CONNECT_HIDDEN_I2P_TCP, pqicI2PBOB); - break; - default: - /* peer is not a hidden one but we are */ - /* select type based on ourselves */ - uint32_t typeOwn = mPeerMgr->getHiddenType(AuthSSL::getAuthSSL()->OwnId()); - switch (typeOwn) { - case RS_HIDDEN_TYPE_I2P: - pqip -> addChildInterface(PQI_CONNECT_HIDDEN_I2P_TCP, pqicI2PBOB); - break; - default: - /* this case shouldn't happen! */ - std::cerr << "pqisslpersongrp::locked_createPerson WARNING INVALID HIDDEN TYPES - THIS SHOULD NOT HAPPEN!" << std::endl; - std::cerr << " - ID: " << id << std::endl; - std::cerr << " - mPeerMgr->isHidden(): " << mPeerMgr->isHidden() << std::endl; - std::cerr << " - mPeerMgr->isHiddenPeer(id): " << mPeerMgr->isHiddenPeer(id) << std::endl; - std::cerr << " - hidden types: peer=" << typePeer << " own=" << typeOwn << std::endl; - std::cerr << " --> falling back to Tor" << std::endl; - /* fallthrough */ - case RS_HIDDEN_TYPE_TOR: - pqip -> addChildInterface(PQI_CONNECT_HIDDEN_TOR_TCP, pqicSOCKSProxy); - break; - } - } - } - else - { -#ifdef PQISTREAMER_DEBUG - std::cerr << "pqisslpersongrp::locked_createPerson() Is Normal Peer!"; - std::cerr << std::endl; -#endif - - pqissl *pqis = new pqissl((pqissllistener *) listener, pqip, mLinkMgr); - - /* construct the serialiser .... - * Needs: - * * FileItem - * * FileData - * * ServiceGeneric - */ - - ssl_tunnels[id] = pqis ; // keeps for getting crypt info per peer. - - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsRawSerialiser()); - - pqiconnect *pqisc = new pqiconnect(pqip, rss, pqis); - - pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc); - -#ifndef PQI_DISABLE_UDP - pqissludp *pqius = new pqissludp(pqip, mLinkMgr); - - RsSerialiser *rss2 = new RsSerialiser(); - rss2->addSerialType(new RsRawSerialiser()); - - pqiconnect *pqiusc = new pqiconnect(pqip, rss2, pqius); - - // add a ssl + proxy interface. - // Add Proxy First. - pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc); -#endif - } - - return pqip; -} - -void pqisslpersongrp::disconnectPeer(const RsPeerId &peer) -{ - std::map::iterator it = ssl_tunnels.find(peer) ; - - if(it != ssl_tunnels.end()) - it->second->disconnect() ; - else - std::cerr << "pqisslpersongrp::cannot find peer " << peer << ". cannot disconnect!" << std::endl; -} - - -/********************************** SSL Specific features ***************************/ - - diff --git a/libretroshare/src/pqi/pqisslpersongrp.h b/libretroshare/src/pqi/pqisslpersongrp.h deleted file mode 100644 index ea94e616a..000000000 --- a/libretroshare/src/pqi/pqisslpersongrp.h +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqisslpersongrp.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_SSL_PERSON_HANDLER_HEADER -#define MRK_PQI_SSL_PERSON_HANDLER_HEADER - -#include "pqi/pqipersongrp.h" - -class p3PeerMgr; -struct RsPeerCryptoParams; -class pqissl ; - -class pqisslpersongrp: public pqipersongrp -{ - public: - pqisslpersongrp(p3ServiceControl *ctrl, unsigned long flags, p3PeerMgr *pm) - :pqipersongrp(ctrl, flags), mPeerMgr(pm) { return; } - - protected: - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -virtual pqilistener *locked_createListener(const struct sockaddr_storage &laddr); -virtual pqiperson *locked_createPerson(const RsPeerId& id, pqilistener *listener); - /********* FUNCTIONS to OVERLOAD for specialisation ********/ - - virtual void disconnectPeer(const RsPeerId& peer) ; - - private: - - p3PeerMgr *mPeerMgr; - std::map ssl_tunnels ; -}; - - -#endif // MRK_PQI_SSL_PERSON_HANDLER_HEADER diff --git a/libretroshare/src/pqi/pqisslproxy.cc b/libretroshare/src/pqi/pqisslproxy.cc deleted file mode 100644 index 1c61bef78..000000000 --- a/libretroshare/src/pqi/pqisslproxy.cc +++ /dev/null @@ -1,629 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqisslproxy.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/pqisslproxy.h" -#include "pqi/pqinetwork.h" - -#include -#include - -#include - -#include "util/rsdebug.h" -#include "util/rsnet.h" - -#include "pqi/p3linkmgr.h" - -static struct RsLog::logInfo pqisslproxyzoneInfo = {RsLog::Default, "pqisslproxy"}; -#define pqisslproxyzone &pqisslproxyzoneInfo - -// #define PROXY_DEBUG 1 -// #define PROXY_DEBUG_LOG 1 - -#define PROXY_STATE_FAILED 0 -#define PROXY_STATE_INIT 1 -#define PROXY_STATE_WAITING_METHOD_RESPONSE 2 -#define PROXY_STATE_WAITING_SOCKS_RESPONSE 3 -#define PROXY_STATE_CONNECTION_COMPLETE 4 - -pqisslproxy::pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) - :pqissl(l, parent, lm) -{ - sockaddr_storage_clear(remote_addr); - return; -} - - -pqisslproxy::~pqisslproxy() -{ - rslog(RSL_ALERT, pqisslproxyzone, - "pqisslproxy::~pqisslproxy -> destroying pqisslproxy"); - - stoplistening(); - reset(); - - return; -} - -int pqisslproxy::Initiate_Connection() -{ - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Initiate_Connection()"; - std::cerr << std::endl; -#endif - - rslog(RSL_DEBUG_BASIC, pqisslproxyzone, - "pqisslproxy::Initiate_Connection() Connection to Proxy"); - /* init proxy state */ - mProxyState = PROXY_STATE_INIT; - - /* call standard Init_Conn() */ - return pqissl::Initiate_Connection(); -} - - -/********* VERY DIFFERENT **********/ -int pqisslproxy::Basic_Connection_Complete() -{ - rslog(RSL_DEBUG_BASIC, pqisslproxyzone, - "pqisslproxy::Basic_Connection_Complete()..."); - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() STATE: " << mProxyState; - std::cerr << std::endl; -#endif - - if (CheckConnectionTimeout()) - { - // calls reset. - return -1; - } - - int ret = 0; - switch(mProxyState) - { - case PROXY_STATE_INIT: - ret = Proxy_Send_Method(); // checks basic conn, sends Method when able. - break; - - case PROXY_STATE_WAITING_METHOD_RESPONSE: - ret = Proxy_Send_Address(); // waits for Method Response, send Address when able. - break; - - case PROXY_STATE_WAITING_SOCKS_RESPONSE: - ret = Proxy_Connection_Complete(); // wait for ACK. - break; - - case PROXY_STATE_CONNECTION_COMPLETE: - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() COMPLETED"; - std::cerr << std::endl; -#endif - - return 1; - - case PROXY_STATE_FAILED: - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED"; - std::cerr << std::endl; -#endif - - reset_locked(); - return -1; - } - - if (ret < 0) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED(2)"; - std::cerr << std::endl; -#endif - reset_locked(); - return -1; // FAILURE. - } - - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() IN PROGRESS"; - std::cerr << std::endl; -#endif - - // In Progress. - return 0; -} - - -int pqisslproxy::Proxy_Send_Method() -{ - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Method() Checking pqissl::Basic_Connection_Complete()"; - std::cerr << std::endl; -#endif - - int ret = pqissl::Basic_Connection_Complete(); - if (ret != 1) - { - return ret; // basic connection not complete. - } - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Method() Basic complete, sending Method"; - std::cerr << std::endl; -#endif - - /* send hello to proxy server */ - char method_hello_data[3] = { 0x05, 0x01, 0x00 }; // [ Ver | nMethods (1) | No Auth Method ] - - int sent = send(sockfd, method_hello_data, 3, 0); - if (sent != 3) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Method() Send Failure"; - std::cerr << std::endl; -#endif - return -1; - } - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Method() Send Method Okay"; - std::cerr << std::endl; -#endif - - mProxyState = PROXY_STATE_WAITING_METHOD_RESPONSE; - - return 1; -} - -int pqisslproxy::Proxy_Method_Response() -{ - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response()"; - std::cerr << std::endl; -#endif - - /* get response from proxy server */ - - char method_response[2]; - - /* - first it was: - - int recvd = recv(sockfd, method_response, 2, MSG_WAITALL); - - this does not work on windows, because the socket is in nonblocking mode - the winsock reference says about the recv function and MSG_WAITALL: - - "Note that if the underlying transport does not support MSG_WAITALL, - or if the socket is in a non-blocking mode, then this call will fail with WSAEOPNOTSUPP." - - now it is a two step process: - - int recvd = recv(sockfd, method_response, 2, MSG_PEEK); // test how many bytes are in the input queue - if (enaugh bytes available){ - recvd = recv(sockfd, method_response, 2, 0); - } - - this does not work on windows: - if ((recvd == -1) && (errno == EAGAIN)) return TRY_AGAIN_LATER; - - instead have to do: - if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) return TRY_AGAIN_LATER; - */ - - // test how many bytes can be read from the queue - int recvd = recv(sockfd, method_response, 2, MSG_PEEK); - if (recvd != 2) - { -#ifdef WINDOWS_SYS - if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data (windows)"; - std::cerr << std::endl; -#endif - return 0; - } -#endif - if ((recvd == -1) && (errno == EAGAIN)) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() EAGAIN"; - std::cerr << std::endl; -#endif - - return 0; - } - else if (recvd == -1) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() recv error peek"; - std::cerr << std::endl; -#endif - return -1; - } - else - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data"; - std::cerr << std::endl; -#endif - return 0; - } - } - - // read the bytes - recvd = recv(sockfd, method_response, 2, 0); - if (recvd != 2) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() recv error"; - std::cerr << std::endl; -#endif - return -1; - } - - // does it make sense? - if (method_response[0] != 0x05) - { - - // Error. -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x05. Is: "; - std::cerr << (uint32_t) method_response[0]; - std::cerr << std::endl; -#endif - return -1; - } - - if (method_response[1] != 0x00) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x00. Is: "; - std::cerr << (uint32_t) method_response[1]; - std::cerr << std::endl; -#endif - // Error. - return -1; - } - - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() Response Okay"; - std::cerr << std::endl; -#endif - - return 1; -} - -#define MAX_SOCKS_REQUEST_LEN 262 // 4 + 1 + 255 + 2. - -int pqisslproxy::Proxy_Send_Address() -{ - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Address() Checking Method Response"; - std::cerr << std::endl; -#endif - - // Check Method Response. - int ret = Proxy_Method_Response(); - if (ret != 1) - { - return ret; // Method Response not complete. - } - - char socks_request[MAX_SOCKS_REQUEST_LEN] = - { 0x05, // SOCKS VERSION. - 0x01, // CONNECT (Tor doesn't support BIND or UDP). - 0x00, // RESERVED. - 0x03, // ADDRESS TYPE (Domain Name) - 0x00, // Length of Domain name... the rest is variable so can't hard code it! - }; - - /* get the length of the domain name, pack so we can't overflow uint8_t */ - uint8_t len = mDomainAddress.length(); - socks_request[4] = len; - for(int i = 0; i < len; i++) - { - socks_request[5 + i] = mDomainAddress[i]; - } - - /* now add the port, being careful with packing */ - uint16_t net_port = htons(mRemotePort); - socks_request[5 + len] = ((uint8_t *) &net_port)[0]; - socks_request[5 + len + 1] = ((uint8_t *) &net_port)[1]; - - int pkt_len = 5 + len + 2; - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Address() Sending String: "; - for(int i = 0; i < pkt_len; i++) - std::cerr << (uint32_t) socks_request[i]; - std::cerr << std::endl; -#endif - int sent = send(sockfd, socks_request, pkt_len, 0); - if (sent != pkt_len) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Address() Send Error"; - std::cerr << std::endl; -#endif - - return -1; - } - - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Address() Sent Okay"; - std::cerr << std::endl; -#endif - - mProxyState = PROXY_STATE_WAITING_SOCKS_RESPONSE; - return 1; -} - -int pqisslproxy::Proxy_Connection_Complete() -{ - /* get response from proxy server */ - /* response is similar format to request - with variable length data */ - - char socks_response[MAX_SOCKS_REQUEST_LEN]; - - // test how many bytes can be read - int recvd = recv(sockfd, socks_response, 5, MSG_PEEK); - if (recvd != 5) - { -#ifdef WINDOWS_SYS - if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data (windows)"; - std::cerr << std::endl; -#endif - return 0; - } -#endif - if ((recvd == -1) && (errno == EAGAIN)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() EAGAIN"; - std::cerr << std::endl; -#endif - return 0; - } - else if (recvd == -1) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error peek"; - std::cerr << std::endl; -#endif - return -1; - } - else - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data"; - std::cerr << std::endl; -#endif - return 0; - } - } - - // read the bytes - recvd = recv(sockfd, socks_response, 5, 0); - if (recvd != 5) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error"; - std::cerr << std::endl; -#endif - return -1; - } - - // error checking. - if (socks_response[0] != 0x05) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[0] != 0x05. is: "; - std::cerr << (uint32_t) socks_response[0]; - std::cerr << std::endl; -#endif - - // error. - return -1; - } - - if (socks_response[1] != 0x00) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[1] != 0x00. is: "; - std::cerr << (uint32_t) socks_response[1]; - std::cerr << std::endl; -#endif - - // connection failed. - return -1; - } - - int address_bytes = 0; - switch(socks_response[3]) // Address Type. - { - case 0x01: - // IPv4 4 address bytes. - address_bytes = 4; -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv4 Address Type"; - std::cerr << std::endl; -#endif - break; - case 0x04: - // IPv6 16 address bytes. - address_bytes = 16; -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv6 Address Type"; - std::cerr << std::endl; -#endif - break; - case 0x03: - // Variable address bytes - specified in next byte. - address_bytes = 1 + socks_response[4]; -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() Domain Address Type. len: " << address_bytes; - std::cerr << std::endl; -#endif - break; - default: - // unknown error. -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR Unknown Address Type"; - std::cerr << std::endl; -#endif - return -1; - break; - } - - - // test how many bytes can be read - recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, MSG_PEEK); // address_bytes - 1 + 2... - if (recvd != address_bytes + 1) - { -#ifdef WINDOWS_SYS - if((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2) (windows)"; - std::cerr << std::endl; -#endif - return 0; - } -#endif - if ((recvd == -1) && (errno == EAGAIN)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR EAGAIN at end."; - std::cerr << std::endl; -#endif - // Waiting - shouldn't happen. - return 0; - } - else if (recvd == -1) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR recving(2)"; - std::cerr << std::endl; -#endif - return -1; - } - else - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2)"; - std::cerr << std::endl; -#endif - return 0; - } - } - - // read the bytes - recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, 0); // address_bytes - 1 + 2... - if (recvd != address_bytes + 1) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error (2)"; - std::cerr << std::endl; -#endif - return -1; - } - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() Received String: "; - for(int i = 0; i < 4 + address_bytes + 2; i++) - std::cerr << (uint32_t) socks_response[i]; - std::cerr << std::endl; -#endif - - // should print address. - // if we get here - connection is good!. - mProxyState = PROXY_STATE_CONNECTION_COMPLETE; - return 1; - -} - -bool pqisslproxy::connect_parameter(uint32_t type, const std::string &value) -{ - { - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - if (type == NET_PARAM_CONNECT_DOMAIN_ADDRESS) - { - std::string out; - rs_sprintf(out, "pqisslproxy::connect_parameter() Peer: %s DOMAIN_ADDRESS: %s", PeerId().toStdString().c_str(), value.c_str()); -#ifdef PROXY_DEBUG_LOG - rslog(RSL_WARNING, pqisslproxyzone, out); -#endif - mDomainAddress = value; -#ifdef PROXY_DEBUG - std::cerr << out << std::endl; -#endif - return true; - } - } - - return pqissl::connect_parameter(type, value); -} - -bool pqisslproxy::connect_parameter(uint32_t type, uint32_t value) -{ - { - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - if (type == NET_PARAM_CONNECT_REMOTE_PORT) - { - std::string out; - rs_sprintf(out, "pqisslproxy::connect_parameter() Peer: %s REMOTE_PORT: %lu", PeerId().toStdString().c_str(), value); -#ifdef PROXY_DEBUG_LOG - rslog(RSL_WARNING, pqisslproxyzone, out); -#endif - mRemotePort = value; -#ifdef PROXY_DEBUG - std::cerr << out << std::endl; -#endif - return true; - } - } - return pqissl::connect_parameter(type, value); -} - - - - diff --git a/libretroshare/src/pqi/pqisslproxy.h b/libretroshare/src/pqi/pqisslproxy.h deleted file mode 100644 index dc34295ad..000000000 --- a/libretroshare/src/pqi/pqisslproxy.h +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqisslproxy.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_SSL_PROXY_HEADER -#define MRK_PQI_SSL_PROXY_HEADER - -// operating system specific network header. -#include "pqi/pqinetwork.h" - -#include -#include - -#include "pqi/pqissl.h" - - /* pqisslproxy uses SOCKS5 proxy to hidden your own address and connect to peers. - * It uses the Domain Name interface of SOCKS5, as opposed to an IP address. - */ - -/* This provides a NetBinInterface, which is - * primarily inherited from pqissl. - * fns declared here are different -> all others are identical. - */ - -class pqisslproxy: public pqissl -{ -public: - pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm); -virtual ~pqisslproxy(); - - // NetInterface. Is the same. - // BinInterface. Is the same. - -virtual bool connect_parameter(uint32_t type, const std::string &value); -virtual bool connect_parameter(uint32_t type, uint32_t value); - -protected: - -//Initiate is the same - except it uses the Proxy Address rather than the Peer Address. -// minor tweaks to setup data state. -virtual int Initiate_Connection(); - -// The real overloading is done in Basic Connection Complete. -// Instead of just checking for an open socket, we need to communicate with the SOCKS5 proxy. -virtual int Basic_Connection_Complete(); - -// These are the internal steps in setting up the Proxy Connection. -virtual int Proxy_Send_Method(); -virtual int Proxy_Method_Response(); -virtual int Proxy_Send_Address(); -virtual int Proxy_Connection_Complete(); - -private: - - uint32_t mProxyState; - - std::string mDomainAddress; - uint16_t mRemotePort; -}; - -#endif // MRK_PQI_SSL_PROXY_HEADER diff --git a/libretroshare/src/pqi/pqissludp.cc b/libretroshare/src/pqi/pqissludp.cc deleted file mode 100644 index 9700f7cdc..000000000 --- a/libretroshare/src/pqi/pqissludp.cc +++ /dev/null @@ -1,622 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissludp.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/pqissludp.h" -#include "pqi/pqinetwork.h" - -#include "tcponudp/tou.h" -#include "tcponudp/bio_tou.h" - -#include -#include - - -#include "util/rsdebug.h" -#include "util/rsnet.h" -#include "util/rstime.h" -#include "util/rsstring.h" - -#include "pqi/p3linkmgr.h" -#include - -static struct RsLog::logInfo pqissludpzoneInfo = {RsLog::Default, "pqissludp"}; -#define pqissludpzone &pqissludpzoneInfo - - /* a final timeout, to ensure this never blocks completely - * 300 secs to complete udp/tcp/ssl connection. - * This is long as the udp connect can take some time. - */ - -static const uint32_t PQI_SSLUDP_DEF_CONN_PERIOD = 300; /* 5 minutes? */ - -/********** PQI SSL UDP STUFF **************************************/ - -pqissludp::pqissludp(PQInterface *parent, p3LinkMgr *lm) : - pqissl(nullptr, parent, lm), tou_bio(nullptr), - mConnectPeriod(PQI_SSLUDP_DEF_CONN_PERIOD), mConnectFlags(0), - mConnectBandwidth(0), mConnectProxyAddr(), mConnectSrcAddr() {} - -/* - * No need to call reset() here as it will be called in the upper class, - * pqissludp::reset_locked() just reset a few members to 0 that (that will be - * deleted anyway when this destructor ends), so pqissl::reset_locked() that is - * called by in parent class destructor will do just fine. - * - * DISCLAIMER: do not double free tou_bio here, as it is implicitely freed - * by SSL_free(...) in pqissl::reset() - */ -pqissludp::~pqissludp() = default; - - -int pqissludp::reset_locked() -{ - /* reset for next time.*/ - mConnectFlags = 0; - mConnectPeriod = PQI_SSLUDP_DEF_CONN_PERIOD; - - return pqissl::reset_locked(); -} - - - /* <===================== UDP Difference *******************/ - // The Proxy Version takes a few more step - // - // connectInterface is sent via message from the proxy. - // and is set here. - /* <===================== UDP Difference *******************/ - -int pqissludp::attach() -{ - // IN THE IMPROVED TOU LIBRARY, we need to be careful with the tou_socket PARAMETERS. - // For now, this should do! - sockfd = -1; - - if (mConnectFlags & RS_CB_FLAG_MODE_UDP_DIRECT) - { - std::cerr << "pqissludp::attach() Opening DIRECT Socket"; - std::cerr << std::endl; - sockfd = tou_socket(RSUDP_TOU_RECVER_DIRECT_IDX,TOU_RECEIVER_TYPE_UDPPEER,0); - } - else if (mConnectFlags & RS_CB_FLAG_MODE_UDP_PROXY) - { - std::cerr << "pqissludp::attach() Opening PROXY Socket"; - std::cerr << std::endl; - sockfd = tou_socket(RSUDP_TOU_RECVER_PROXY_IDX,TOU_RECEIVER_TYPE_UDPPEER,0); - } - else if (mConnectFlags & RS_CB_FLAG_MODE_UDP_RELAY) - { - std::cerr << "pqissludp::attach() Opening RELAY Socket"; - std::cerr << std::endl; - sockfd = tou_socket(RSUDP_TOU_RECVER_RELAY_IDX,TOU_RECEIVER_TYPE_UDPRELAY,0); - } - else - { - std::cerr << "pqissludp::attach() ERROR unknown Connect Mode" << std::endl; - std::cerr << "pqissludp::attach() mConnectFlags: " << std::hex << mConnectFlags << std::dec; - std::cerr << std::endl; - sockfd = -1; - } - - if (0 > sockfd) - { - rslog(RSL_WARNING, pqissludpzone, - "pqissludp::attach() failed to create a socket"); - return -1; - } - - // setup remote address - rslog(RSL_WARNING, pqissludpzone, - "pqissludp::attach() Opened Local Udp Socket"); - - return 1; -} - - -// The Address determination is done centrally -int pqissludp::Initiate_Connection() -{ - int err=0; - - attach(); /* open socket */ - //remote_addr.sin_family = AF_INET; - - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Initiate_Connection() Attempting Outgoing Connection...."); - - /* decide if we're active or passive */ - if (mConnectFlags & RS_CB_FLAG_ORDER_ACTIVE) - { - sslmode = PQISSL_ACTIVE; - } - else if (mConnectFlags & RS_CB_FLAG_ORDER_PASSIVE) - { - sslmode = PQISSL_PASSIVE; - } - else // likely UNSPEC - use old method to decide. - { - if (PeerId() < mLinkMgr->getOwnId()) - { - sslmode = PQISSL_ACTIVE; - } - else - { - sslmode = PQISSL_PASSIVE; - } - } - - if (waiting != WAITING_DELAY) - { - rslog(RSL_WARNING, pqissludpzone, - "pqissludp::Initiate_Connection() Already Attempt in Progress!"); - return -1; - } - - if (sockfd < 0) - { - rslog(RSL_ALERT, pqissludpzone, - "pqissludp::Initiate_Connection() Socket Creation Failed!"); - waiting = WAITING_FAIL_INTERFACE; - return -1; - } - - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Initiate_Connection() Opening Socket"); - - { - std::string out = "pqissludp::Initiate_Connection() Connecting To: " + PeerId().toStdString(); - out += " via: "; - out += sockaddr_storage_tostring(remote_addr); - out += " "; - - if (sslmode == PQISSL_ACTIVE) - { - out += "ACTIVE Connect (SSL_Connect)"; - } - else - { - out += "PASSIVE Connect (SSL_Accept)"; - } - rslog(RSL_WARNING, pqissludpzone, out); - } - - if (sockaddr_storage_isnull(remote_addr)) - { - rslog(RSL_WARNING, pqissludpzone, "pqissludp::Initiate_Connection() Invalid (0.0.0.0) Remote Address, Aborting Connect."); - waiting = WAITING_FAIL_INTERFACE; - - reset_locked(); - return -1; - } - - if(!sockaddr_storage_ipv6_to_ipv4(remote_addr)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error: remote_addr is not " - << "valid IPv4!" << std::endl; - sockaddr_storage_dump(remote_addr); - print_stacktrace(); - return -EINVAL; - } - - mTimeoutTS = time(NULL) + mConnectTimeout; - //std::cerr << "Setting Connect Timeout " << mConnectTimeout << " Seconds into Future " << std::endl; - //std::cerr << " Connect Period is:" << mConnectPeriod << std::endl; - - /* <===================== UDP Difference *******************/ - - if (mConnectFlags & RS_CB_FLAG_MODE_UDP_DIRECT) - { - err = tou_connect(sockfd, (struct sockaddr *) &remote_addr, sizeof(remote_addr), mConnectPeriod); - } - else if (mConnectFlags & RS_CB_FLAG_MODE_UDP_PROXY) - { - err = tou_connect(sockfd, (struct sockaddr *) &remote_addr, sizeof(remote_addr), mConnectPeriod); - } - else if (mConnectFlags & RS_CB_FLAG_MODE_UDP_RELAY) - { - std::cerr << __PRETTY_FUNCTION__ << " Calling tou_connect_via_relay(" - << sockaddr_storage_tostring(mConnectSrcAddr) << "," - << sockaddr_storage_tostring(mConnectProxyAddr) << "," - << sockaddr_storage_tostring(remote_addr) << ")" << std::endl; - - if(!sockaddr_storage_ipv6_to_ipv4(mConnectSrcAddr)) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR mConnectSrcAddr is " - << "not a valid IPv4!" << std::endl; - sockaddr_storage_dump(mConnectSrcAddr); - print_stacktrace(); - return -EINVAL; - } - if(!sockaddr_storage_ipv6_to_ipv4(mConnectProxyAddr)) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR mConnectProxyAddr " - << "is not a valid IPv4!" << std::endl; - sockaddr_storage_dump(mConnectProxyAddr); - print_stacktrace(); - return -EINVAL; - - } - - err = tou_connect_via_relay( - sockfd, - reinterpret_cast(mConnectSrcAddr), - reinterpret_cast(mConnectProxyAddr), - reinterpret_cast(remote_addr) ); - -/*** It seems that the UDP Layer sees x 1.2 the traffic of the SSL layer. - * We need to compensate somewhere... we drop the maximum traffic to 75% of limit - * to allow for extra lost packets etc. - * NB: If we have a lossy UDP transmission - re-transmission could cause excessive data to - * exceed the limit... This is difficult to account for without hacking the TcpOnUdp layer. - * If it is noticed as a problem - we'll deal with it then - */ -#define UDP_RELAY_TRANSPORT_OVERHEAD_FACTOR (0.7) - - parent()->setRateCap( UDP_RELAY_TRANSPORT_OVERHEAD_FACTOR * mConnectBandwidth / 1000.0, - UDP_RELAY_TRANSPORT_OVERHEAD_FACTOR * mConnectBandwidth / 1000.0); // Set RateCap. - } - - if (0 != err) - /* <===================== UDP Difference *******************/ - { - int tou_err = tou_errno(sockfd); - - std::string out = "pqissludp::Initiate_Connection()"; - - if ((tou_err == EINPROGRESS) || (tou_err == EAGAIN)) - { - // set state to waiting..... - waiting = WAITING_SOCK_CONNECT; - - out += " EINPROGRESS Waiting for Socket Connection"; - rslog(RSL_WARNING, pqissludpzone, out); - - return 0; - } - else if ((tou_err == ENETUNREACH) || (tou_err == ETIMEDOUT)) - { - out += "ENETUNREACHABLE: cert: " + PeerId().toStdString() + "\n"; - - // Then send unreachable message. - waiting = WAITING_FAIL_INTERFACE; - } - - rs_sprintf_append(out, "Error: Connection Failed: %d - %s", tou_err, socket_errorType(tou_err).c_str()); - - rslog(RSL_WARNING, pqissludpzone, out); - - reset_locked(); - - return -1; - } - else - { - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Init_Connection() connect returned 0"); - } - - waiting = WAITING_SOCK_CONNECT; - - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Initiate_Connection() Waiting for Socket Connect"); - - return 1; -} - -/********* VERY DIFFERENT **********/ -int pqissludp::Basic_Connection_Complete() -{ - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Basic_Connection_Complete()..."); - - if (CheckConnectionTimeout()) - { - return -1; - } - - if (waiting != WAITING_SOCK_CONNECT) - { - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Basic_Connection_Complete() Wrong Mode"); - return -1; - } - - - /* new approach is to check for an error */ - /* check for an error */ - int err; - if (0 != (err = tou_errno(sockfd))) - { - if (err == EINPROGRESS) - { - rslog(RSL_DEBUG_BASIC, pqissludpzone, "pqissludp::Basic_Connection_Complete() EINPROGRESS: cert: " + PeerId().toStdString()); - } - else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) - { - rslog(RSL_WARNING, pqissludpzone, "pqissludp::Basic_Connection_Complete() ENETUNREACH/ETIMEDOUT: cert: " + PeerId().toStdString()); - - /* is the second one needed? */ - std::string out = "pqissludp::Basic_Connection_Complete() "; - rs_sprintf_append(out, "Error: Connection Failed: %d - %s", err, socket_errorType(err).c_str()); - rslog(RSL_DEBUG_BASIC, pqissludpzone, out); - - reset_locked(); - - // Then send unreachable message. - waiting = WAITING_FAIL_INTERFACE; - - return -1; - } - } - - /* <===================== UDP Difference *******************/ - if (tou_connected(sockfd)) - /* <===================== UDP Difference *******************/ - { - rslog(RSL_WARNING, pqissludpzone, "pqissludp::Basic_Connection_Complete() Connection Complete: cert: " + PeerId().toStdString()); - - return 1; - } - else - { - // not ready return -1; - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Basic_Connection_Complete() Not Yet Ready!"); - return 0; - } - - return -1; -} - - -/* New Internal Functions required to generalise tcp/udp version - * of the programs - */ - -// used everywhere -int pqissludp::net_internal_close(int fd) -{ - rslog(RSL_ALERT, pqissludpzone, - "pqissludp::net_internal_close() -> tou_close()"); - return tou_close(fd); -} - -// install udp BIO. -int pqissludp::net_internal_SSL_set_fd(SSL *ssl, int fd) -{ - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::net_internal_SSL_set_fd()"); - - /* create the bio's */ - tou_bio =BIO_new(BIO_s_tou_socket()); - - /* attach the fd's to the BIO's */ - BIO_set_fd(tou_bio, fd, BIO_NOCLOSE); - SSL_set_bio(ssl, tou_bio, tou_bio); - return 1; -} - -bool pqissludp::connect_parameter(uint32_t type, uint32_t value) -{ - { - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - //std::cerr << "pqissludp::connect_parameter() type: " << type << "value: " << value << std::endl; - if (type == NET_PARAM_CONNECT_PERIOD) - { - std::string out; - rs_sprintf(out, "pqissludp::connect_parameter() Peer: %s PERIOD: %lu", PeerId().toStdString().c_str(), value); - rslog(RSL_WARNING, pqissludpzone, out); - - mConnectPeriod = value; - std::cerr << out << std::endl; - return true; - } - else if (type == NET_PARAM_CONNECT_FLAGS) - { - std::string out; - rs_sprintf(out, "pqissludp::connect_parameter() Peer: %s FLAGS: %lu", PeerId().toStdString().c_str(), value); - rslog(RSL_WARNING, pqissludpzone, out); - - mConnectFlags = value; - std::cerr << out<< std::endl; - return true; - } - else if (type == NET_PARAM_CONNECT_BANDWIDTH) - { - std::string out; - rs_sprintf(out, "pqissludp::connect_parameter() Peer: %s BANDWIDTH: %lu", PeerId().toStdString().c_str(), value); - rslog(RSL_WARNING, pqissludpzone, out); - - mConnectBandwidth = value; - std::cerr << out << std::endl; - return true; - } - } - - return pqissl::connect_parameter(type, value); -} - -bool pqissludp::connect_additional_address(uint32_t type, const struct sockaddr_storage &addr) -{ - { - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - if (type == NET_PARAM_CONNECT_PROXY) - { - std::string out; - rs_sprintf(out, "pqissludp::connect_additional_address() Peer: %s PROXYADDR: ", PeerId().toStdString().c_str()); - out += sockaddr_storage_tostring(addr); - rslog(RSL_WARNING, pqissludpzone, out); - - mConnectProxyAddr = addr; - - std::cerr << out << std::endl; - return true; - } - else if (type == NET_PARAM_CONNECT_SOURCE) - { - std::string out; - rs_sprintf(out, "pqissludp::connect_additional_address() Peer: %s SRCADDR: ", PeerId().toStdString().c_str()); - out += sockaddr_storage_tostring(addr); - rslog(RSL_WARNING, pqissludpzone, out); - - mConnectSrcAddr = addr; - - std::cerr << out << std::endl; - return true; - } - } - return pqissl::connect_additional_address(type, addr); -} - -/********** PQI STREAMER OVERLOADING *********************************/ - -bool pqissludp::moretoread(uint32_t usec) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - // Extra Checks to avoid crashes in v0.6 ... pqithreadstreamer calls this function - // when sockfd = -1 during the shutdown of the thread. - // NB: it should never reach here if bio->isActive() returns false. - // Some mismatch to chase down when we have a chance. - // SAME test is at cansend. - if (sockfd < 0) - { - std::cerr << "pqissludp::moretoread() INVALID sockfd PARAMETER ... bad shutdown?"; - std::cerr << std::endl; - return false; - } - - - { - std::string out = "pqissludp::moretoread()"; - rs_sprintf_append(out, " polling socket (%d)", sockfd); - rslog(RSL_DEBUG_ALL, pqissludpzone, out); - } - - if (usec) - { - //std::cerr << "pqissludp::moretoread() usec parameter: " << usec; - //std::cerr << std::endl; - - if (0 < tou_maxread(sockfd)) - { - return true; - } - rstime::rs_usleep(usec); - } - - /* check for more to read first ... if nothing... check error - */ - /* <===================== UDP Difference *******************/ - if (tou_maxread(sockfd)) - /* <===================== UDP Difference *******************/ - { - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::moretoread() Data to Read!"); - return 1; - } - - /* else check the error */ - rslog(RSL_DEBUG_ALL, pqissludpzone, - "pqissludp::moretoread() No Data to Read!"); - - int err; - if (0 != (err = tou_errno(sockfd))) - { - if ((err == EAGAIN) || (err == EINPROGRESS)) - { - rslog(RSL_DEBUG_BASIC, pqissludpzone, "pqissludp::moretoread() EAGAIN/EINPROGRESS: cert " + PeerId().toStdString()); - return 0; - - } - else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) - { - rslog(RSL_WARNING, pqissludpzone, "pqissludp::moretoread() ENETUNREACH/ETIMEDOUT: cert " + PeerId().toStdString()); - } - else if (err == EBADF) - { - rslog(RSL_WARNING, pqissludpzone, "pqissludp::moretoread() EBADF: cert " + PeerId().toStdString()); - } - else - { - std::string out = "pqissludp::moretoread() "; - rs_sprintf_append(out, " Unknown ERROR: %d: cert ", err, PeerId().toStdString().c_str()); - rslog(RSL_WARNING, pqissludpzone, out); - } - - reset_locked(); - return 0; - } - - if(SSL_pending(ssl_connection) > 0) - return 1 ; - - /* otherwise - not error - strange! */ - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::moretoread() No Data + No Error (really nothing)"); - - return 0; - - -} - -bool pqissludp::cansend(uint32_t usec) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - // Extra Checks to avoid crashes in v0.6 ... pqithreadstreamer calls this function - // when sockfd = -1 during the shutdown of the thread. - // NB: it should never reach here if bio->isActive() returns false. - // Some mismatch to chase down when we have a chance. - // SAME test is at can moretoread. - if (sockfd < 0) - { - std::cerr << "pqissludp::cansend() INVALID sockfd PARAMETER ... bad shutdown?"; - std::cerr << std::endl; - return false; - } - - if (usec) - { - std::cerr << "pqissludp::cansend() usec parameter: " << usec; - std::cerr << std::endl; - - if (0 < tou_maxwrite(sockfd)) - { - return true; - } - - rstime::rs_usleep(usec); - } - - rslog(RSL_DEBUG_ALL, pqissludpzone, - "pqissludp::cansend() polling socket!"); - - /* <===================== UDP Difference *******************/ - return (0 < tou_maxwrite(sockfd)); - /* <===================== UDP Difference *******************/ - -} - - - diff --git a/libretroshare/src/pqi/pqissludp.h b/libretroshare/src/pqi/pqissludp.h deleted file mode 100644 index b716efb1e..000000000 --- a/libretroshare/src/pqi/pqissludp.h +++ /dev/null @@ -1,90 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissludp.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "pqi/pqissl.h" -#include "pqi/pqinetwork.h" -#include "util/rsdebug.h" - - -/** - * @brief pqissludp is the special NAT traversal protocol. - * This class will implement the basics of streaming ssl over udp using a - * tcponudp library. - * It provides a NetBinInterface, which is primarily inherited from pqissl. - * Some methods are override all others are identical. - */ -class pqissludp: public pqissl -{ -public: - pqissludp(PQInterface *parent, p3LinkMgr *lm); - ~pqissludp() override; - - int listen() override { return 1; } - int stoplistening() override { return 1; } - - virtual bool connect_parameter(uint32_t type, uint32_t value); - virtual bool connect_additional_address(uint32_t type, const struct sockaddr_storage &addr); - - // BinInterface. - // These are reimplemented. - virtual bool moretoread(uint32_t usec); - virtual bool cansend(uint32_t usec); - /* UDP always through firewalls -> always bandwidth Limited */ - virtual bool bandwidthLimited() { return true; } - -protected: - - // pqissludp specific. - // called to initiate a connection; - int attach(); - - virtual int reset_locked(); - - virtual int Initiate_Connection(); - virtual int Basic_Connection_Complete(); - - /* Do we really need this ? - * It is very specific UDP+ToU+SSL stuff and unlikely to be reused. - * In fact we are overloading them here becase they are very do different of pqissl. - */ - virtual int net_internal_close(int fd); - virtual int net_internal_SSL_set_fd(SSL *ssl, int fd); - virtual int net_internal_fcntl_nonblock(int /*fd*/) { return 0; } - -private: - - BIO *tou_bio; // specific to ssludp. - - uint32_t mConnectPeriod; - uint32_t mConnectFlags; - uint32_t mConnectBandwidth; - - struct sockaddr_storage mConnectProxyAddr; - struct sockaddr_storage mConnectSrcAddr; - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; diff --git a/libretroshare/src/pqi/pqistore.cc b/libretroshare/src/pqi/pqistore.cc deleted file mode 100644 index 090a6a794..000000000 --- a/libretroshare/src/pqi/pqistore.cc +++ /dev/null @@ -1,575 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqistore.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ - -/* This is dependent on the sslroot at the moment. - * -> as we need to create/restore references to the Person. - * -> and store the signatures to do this. - */ - -/******************************************************************* - * pqistore provides an store stream. - * This stores RsItem + Person Reference + Timestamp, - * - * and allows Objects to be replayed or restored, - * independently of the rest of the pqi system. - * - */ - -#include "rsitems/rsitem.h" -#include "pqi/pqistore.h" -#include "serialiser/rsserial.h" -#include -#include - -#include "util/rsdebug.h" -#include "util/rsmemory.h" -#include "util/rsstring.h" - -// -// #define PQISTORE_DEBUG -// - -static struct RsLog::logInfo pqistorezoneInfo = {RsLog::Default, "pqistore"}; -#define pqistorezone &pqistorezoneInfo - -pqistore::pqistore(RsSerialiser *rss, const RsPeerId& srcId, BinInterface *bio_in, int bio_flags_in) - :PQInterface(RsPeerId()), rsSerialiser(rss), bio_flags(bio_flags_in), - nextPkt(NULL), mSrcId(srcId), bio(bio_in) -{ - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::pqistore() Initialisation!"); - - if (!bio_in) - { - pqioutput(PQL_ALERT, pqistorezone, "pqistore::pqistore() NULL bio, FATAL ERROR!"); - exit(1); - } - - bStopReading=false; - return; -} - -pqistore::~pqistore() -{ - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::~pqistore() Destruction!"); - - if (bio_flags & BIN_FLAGS_NO_CLOSE) - { - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::~pqistore() Not Closing BinInterface!;"); - } - else if (bio) - { - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::~pqistore() Deleting BinInterface!"); - - delete bio; - } - - if (rsSerialiser) - delete rsSerialiser; - - if (nextPkt) - { - delete nextPkt; - } - return; -} - - -// Get/Send Items. -int pqistore::SendItem(RsItem *si) -{ -#ifdef PQISTORE_DEBUG - { - std::string out = "pqistore::SendItem()\n"; - si -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqistorezone, out); - } -#endif - - // check if this is a writing bio. - - if (!(bio_flags & BIN_FLAGS_WRITEABLE)) - { - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete si; - return -1; - } - -// std::cerr << "SendItem: si->PeerId()=" << si->PeerId() << std::endl ; - - int ret = writePkt(si); - return ret; /* 0 - failure, 1 - success*/ -} - -RsItem *pqistore::GetItem() -{ -#ifdef PQISTORE_DEBUG - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::GetItem()"); -#endif - - bStopReading=false; - // check if this is a reading bio. - if (!(bio_flags & BIN_FLAGS_READABLE)) - { - pqioutput(PQL_DEBUG_BASIC, pqistorezone, "pqistore::GetItem() Error Not Readable"); - bStopReading=true; - return NULL; - } - - // load if we dont have a packet. - if (!nextPkt) - { - if (!readPkt(&nextPkt)) - { - pqioutput(PQL_DEBUG_BASIC, pqistorezone, "pqistore::GetItem() Failed to ReadPkt"); - return NULL; - } - } - - if (!nextPkt) return NULL; - - RsItem *outPkt = nextPkt; - nextPkt = NULL; - -#ifdef PQISTORE_DEBUG - if (outPkt != NULL) - { - std::string out = "pqistore::GetItem() Returning:\n"; - outPkt -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqistorezone, out); - } -#endif - return outPkt; -} - - - - -// // PQInterface -int pqistore::tick() -{ -#ifdef PQISTORE_DEBUG - std::cerr << "pqistore::tick()" << std::endl; -#endif - return 0; -} - -int pqistore::status() -{ -#ifdef PQISTORE_DEBUG - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::status()"); -#endif - return 0; -} - -// -/**************** HANDLE OUTGOING TRANSLATION + TRANSMISSION ******/ - -int pqistore::writePkt(RsItem *pqi) -{ -// std::cerr << "writePkt, pqi->peerId()=" << pqi->PeerId() << std::endl ; -#ifdef PQISTORE_DEBUG - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::writePkt()"); -#endif - - uint32_t pktsize = rsSerialiser->size(pqi); - - RsTemporaryMemory ptr(pktsize) ; - - if(ptr == NULL) - return 0 ; - - if (!(rsSerialiser->serialise(pqi, ptr, &pktsize))) - { -#ifdef PQISTORE_DEBUG - std::string out = "pqistore::writePkt() Null Pkt generated!\nCaused By:\n"; - pqi -> print(out); - pqioutput(PQL_ALERT, pqistorezone, out); -#endif - - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - return 0; - } - - /* extract the extra details */ - uint32_t len = getRsItemSize(ptr); - if (len != pktsize) - { - std::string out; - rs_sprintf(out, "pqistore::writePkt() Length MisMatch: len: %u!= pktsize: %u\nCaused By:\n", len, pktsize); - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqistorezone, out); - - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - return 0; - } - - - if (!(bio->cansend(0))) - { - std::string out; - rs_sprintf(out, "pqistore::writePkt() BIO cannot write!\niscarding:\n"); - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqistorezone, out); - - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 0; - } - -#ifdef PQISTORE_DEBUG - std::string out = "Writing Pkt Body"; -#endif - // write packet. - if (len != (uint32_t) bio->senddata(ptr, len)) - { -#ifdef PQISTORE_DEBUG - out += " Problems with Send Data!"; - pqioutput(PQL_ALERT, pqistorezone, out); -#endif - - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 0; - } - -#ifdef PQISTORE_DEBUG - out += " Success!"; - pqioutput(PQL_DEBUG_BASIC, pqistorezone, out); -#endif - - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 1; -} - -/* Reads a single packet from the input stream - * gets the timestamp as well. - */ - -int pqistore::readPkt(RsItem **item_out) -{ -#ifdef PQISTORE_DEBUG - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::readPkt()"); -#endif - bStopReading = false ; - - if ((!(bio->isactive())) || (!(bio->moretoread(0)))) - { - bStopReading = true ; - return 0; - } - - // initial read size: basic packet. - int blen = getRsPktBaseSize(); - void *block = rs_malloc(blen); - - if(block == NULL) - return false ; - - int tmplen; - /* we have the header */ - - // read the basic block (minimum packet size) - if (blen != (tmplen = bio->readdata(block, blen))) - { - pqioutput(PQL_WARNING, pqistorezone, "pqistore::readPkt() bad read(2)"); - - free(block); - bStopReading=true; - return 0; - } - - // workout how much more to read. - int blocklength = getRsItemSize(block); - - // make sure that blocklength is not a crazy number. If so, we drop the entire stream that might be corrupted. - - if(blocklength < blen || blocklength > 1024*1024*10) - { - std::cerr << "pqistore: ERROR: trying to realloc memory for packet of length" << blocklength <<", which is either too small, or exceeds the safety limit (10 MB)" << std::endl ; - free(block) ; - bStopReading=true; - return 0 ; - } - int extralen = blocklength - blen; - - void *tmp = realloc(block, blocklength); - - if (tmp == NULL) - { - free(block); - std::cerr << "pqistore: ERROR: trying to realloc memory for packet of length" << blocklength << std::endl ; - std::cerr << "Have you got enought memory?" << std::endl ; - bStopReading=true; - return 0 ; - } - else - block = tmp; - - if (extralen > 0) - { - void *extradata = (void *) (((char *) block) + blen); - - if (extralen != (tmplen = bio->readdata(extradata, extralen))) - { - std::string out; - rs_sprintf(out, "pqistore::readPkt() Error Completing Read (read %d/%d)", tmplen, extralen); - pqioutput(PQL_ALERT, pqistorezone, out); - bStopReading=true; - - free(block); - return 0; - } - } - - // create packet, based on header. - uint32_t readbytes = extralen + blen; - - RsItem *item = rsSerialiser->deserialise(block, &readbytes); - free(block); - - if (item == NULL) - { - pqioutput(PQL_ALERT, pqistorezone, "pqistore::readPkt() Failed to create Item from store!"); - return 0; - } - - item->PeerId(mSrcId); - *item_out = item; - return 1; -} - -/**** Hashing Functions ****/ -RsFileHash pqistore::gethash() -{ - return bio->gethash(); -} - -pqiSSLstore::pqiSSLstore(RsSerialiser *rss, const RsPeerId& srcId, BinEncryptedFileInterface* bio_in, int bio_flagsin) -: pqistore(rss, srcId, bio_in, bio_flagsin), enc_bio(bio_in) -{ - bStopReading=false; - return; -} - -pqiSSLstore::~pqiSSLstore() -{ - // no need to delete member enc_bio, as it is deleted by the parent class. - return; -} - -bool pqiSSLstore::encryptedSendItems(const std::list& rsItemList) -{ - - std::list::const_iterator it; - uint32_t sizeItems = 0, sizeItem = 0; - uint32_t offset = 0; - - for(it = rsItemList.begin(); it != rsItemList.end(); ++it) - if(*it != NULL) sizeItems += rsSerialiser->size(*it); - - RsTemporaryMemory data( sizeItems ? sizeItems : 1 ); - - for(it = rsItemList.begin(); it != rsItemList.end(); ++it) - if(*it != NULL) - { - sizeItem = rsSerialiser->size(*it); - - if(rsSerialiser->serialise(*it, &data[offset],&sizeItem)) - offset += sizeItem; - else - { - std::cerr << "(EE) pqiSSLstore::encryptedSendItems(): One item did not serialize. The item is probably unknown from the serializer. Dropping the item. " << std::endl; - std::cerr << "Item content: " << std::endl; - (*it)->print(std::cerr) ; - } - - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete *it; - } - - bool result = true; - - if(sizeItems == offset) - enc_bio->senddata(data, sizeItems); - else - result = false; - - return result; -} - -bool pqiSSLstore::getEncryptedItems(std::list& rsItemList) -{ - RsItem* item; - bStopReading=false; - - do - { - if (NULL != (item = GetItem())) - rsItemList.push_back(item); - - } while (enc_bio->isactive() && enc_bio->moretoread(0) && !bStopReading); - - return true; -} - - -RsItem *pqiSSLstore::GetItem() -{ -#ifdef PQISTORE_DEBUG - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqiSSLstore::GetItem()"); -#endif - - bStopReading=false; - // check if this is a reading bio. - if (!(bio_flags & BIN_FLAGS_READABLE)) - { - pqioutput(PQL_DEBUG_BASIC, pqistorezone, "pqiSSLstore::GetItem() Error Not Readable"); - bStopReading=true; - return NULL; - } - - // load if we dont have a packet. - if (!nextPkt) - { - if (!readPkt(&nextPkt)) - { - pqioutput(PQL_DEBUG_BASIC, pqistorezone, "pqiSSLstore::GetItem() Failed to ReadPkt"); - return NULL; - } - } - - if (!nextPkt) return NULL; - - RsItem *outPkt = nextPkt; - nextPkt = NULL; - -#ifdef PQISTORE_DEBUG - if (outPkt != NULL) - { - std::string out; - rs_sprintf(out, "pqiSSLstore::GetItem() Returning:\n"); - outPkt -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqistorezone, out); - } -#endif - return outPkt; -} - - -int pqiSSLstore::readPkt(RsItem **item_out) -{ - *item_out = NULL ; -#ifdef PQISTORE_DEBUG - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::readPkt()"); -#endif - - bStopReading=false ; - if ((!(enc_bio->isactive())) || (!(enc_bio->moretoread(0)))) - { - bStopReading=true ; - return 0; - } - - // initial read size: basic packet. - int blen = getRsPktBaseSize(); - void *block = rs_malloc(blen); - - if(block == NULL) - return false ; - - int tmplen; - /* we have the header */ - - // read the basic block (minimum packet size) - if (blen != (tmplen = enc_bio->readdata(block, blen))) - { - pqioutput(PQL_WARNING, pqistorezone, "pqiSSLstore::readPkt() bad read(2)"); - - free(block); - bStopReading=true; - return 0; - } - - // workout how much more to read. - int blocklength = getRsItemSize(block); - - if(blocklength < blen || blocklength > 1024*1024*10) - { - free(block); - std::cerr << "pqiSSLstore: ERROR: block length has invalid value " << blocklength << " (either too small, or exceeds the safety limit of 10 MB)" << std::endl ; - bStopReading=true; - return 0 ; - } - int extralen = blocklength - blen; - - void *tmp = realloc(block, blocklength); - - if (tmp == NULL) - { - free(block); - std::cerr << "pqiSSLstore: ERROR: trying to realloc memory for packet of length" << extralen+blen << std::endl ; - std::cerr << "Have you got enought memory?" << std::endl ; - bStopReading=true; - return 0 ; - } - else - block = tmp; - - if (extralen > 0) - { - void *extradata = (void *) (((char *) block) + blen); - - if (extralen != (tmplen = enc_bio->readdata(extradata, extralen))) - { - std::string out; - rs_sprintf(out, "pqiSSLstore::readPkt() Error Completing Read (read %d/%d)", tmplen, extralen); - pqioutput(PQL_ALERT, pqistorezone, out); - - free(block); - bStopReading=true; - return 0; - } - } - - // create packet, based on header. - uint32_t readbytes = extralen + blen; - - RsItem *item = rsSerialiser->deserialise(block, &readbytes); - free(block); - - if (item == NULL) - { - pqioutput(PQL_ALERT, pqistorezone, "pqiSSLstore::readPkt() Failed to create Item from store!"); - return 0; - } - - item->PeerId(mSrcId); - *item_out = item; - return 1; -} - diff --git a/libretroshare/src/pqi/pqistore.h b/libretroshare/src/pqi/pqistore.h deleted file mode 100644 index f8a586c67..000000000 --- a/libretroshare/src/pqi/pqistore.h +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqistore.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_STORE_STREAMER_HEADER -#define MRK_PQI_STORE_STREAMER_HEADER - -#include "pqi/pqibin.h" - -#include - -/******************************************************************* - * pqistore provides a stream to file. - * objects only - like pqistreamer as opposed to pqiarchive. - * - */ - -class pqistore: public PQInterface -{ -public: - pqistore(RsSerialiser *rss, const RsPeerId&srcId, BinInterface *bio_in, int bio_flagsin); -virtual ~pqistore(); - -// PQInterface -virtual int SendItem(RsItem *); -virtual RsItem *GetItem(); - -virtual int tick(); -virtual int status(); - -RsFileHash gethash(); - -bool bStopReading; - -protected: - -// Serialiser -RsSerialiser *rsSerialiser; -unsigned int bio_flags; // only BIN_NO_CLOSE at the moment. - -// Temp Storage for transient data..... -RsItem *nextPkt; -RsPeerId mSrcId; - -private: - - int writePkt(RsItem *item); - int readPkt(RsItem **item_out); - - - - // Binary Interface for IO, initialisated at startup. - BinInterface *bio; - -}; - - -/*! - * provdes an ssl encrypted stream to file storage - */ -class pqiSSLstore: public pqistore -{ - -public: - - pqiSSLstore(RsSerialiser *rss, const RsPeerId& srcId, BinEncryptedFileInterface *bio_in, int bio_flagsin); - - virtual ~pqiSSLstore(); - - /*! - * send items encrypted to file using client's ssl key - */ - bool encryptedSendItems(const std::list&); - - /*! - * retrieve encrypted file using client's ssl key - */ - bool getEncryptedItems(std::list&); - -private: - - RsItem *GetItem(); - int readPkt(RsItem **item_out); - - BinEncryptedFileInterface* enc_bio; - - //bool bStopReading; - -}; - - -#endif //MRK_PQI_STORE_STREAMER_HEADER diff --git a/libretroshare/src/pqi/pqistreamer.cc b/libretroshare/src/pqi/pqistreamer.cc deleted file mode 100644 index db38bfde2..000000000 --- a/libretroshare/src/pqi/pqistreamer.cc +++ /dev/null @@ -1,1440 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqistreamer.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/pqistreamer.h" - -#include // for gettimeofday -#include // for free, realloc, exit -#include // for memcpy, memset, memcmp -#include "util/rstime.h" // for NULL, time, rstime_t -#include // for min -#include // for operator<<, ostream, basic_ostream -#include // for string, allocator, operator<<, oper... -#include // for pair - -#include "pqi/p3notify.h" // for p3Notify -#include "retroshare/rsids.h" // for operator<< -#include "retroshare/rsnotify.h" // for RS_SYS_WARNING -#include "rsserver/p3face.h" // for RsServer -#include "serialiser/rsserial.h" // for RsItem, RsSerialiser, getRsItemSize -#include "util/rsdebug.h" // for pqioutput, PQL_ALERT, PQL_DEBUG_ALL -#include "util/rsmemory.h" // for rs_malloc -#include "util/rsprint.h" // for BinToHex -#include "util/rsstring.h" // for rs_sprintf_append, rs_sprintf - -static struct RsLog::logInfo pqistreamerzoneInfo = {RsLog::Default, "pqistreamer"}; -#define pqistreamerzone &pqistreamerzoneInfo - -static const int PQISTREAM_ABS_MAX = 100000000; /* 100 MB/sec (actually per loop) */ -static const int PQISTREAM_AVG_PERIOD = 1; // update speed estimate every second -static const float PQISTREAM_AVG_FRAC = 0.8; // for bandpass filter over speed estimate. -static const float PQISTREAM_AVG_DT_FRAC = 0.99; // for low pass filter over elapsed time - -static const int PQISTREAM_OPTIMAL_PACKET_SIZE = 512; // It is believed that this value should be lower than TCP slices and large enough as compare to encryption padding. - // most importantly, it should be constant, so as to allow correct QoS. -static const int PQISTREAM_SLICE_FLAG_STARTS = 0x01; // -static const int PQISTREAM_SLICE_FLAG_ENDS = 0x02; // these flags should be kept in the range 0x01-0x08 -static const int PQISTREAM_SLICE_PROTOCOL_VERSION_ID_01 = 0x10; // Protocol version ID. Should hold on the 4 lower bits. -static const int PQISTREAM_PARTIAL_PACKET_HEADER_SIZE = 8; // Same size than normal header, to make the code simpler. -static const int PQISTREAM_PACKET_SLICING_PROBE_DELAY = 60; // send every 60 secs. - -// This is a probe packet, that won't deserialise (it's empty) but will not cause problems to old peers either, since they will ignore -// it. This packet however will be understood by new peers as a signal to enable packet slicing. This should go when all peers use the -// same protocol. - -static uint8_t PACKET_SLICING_PROBE_BYTES[8] = { 0x02, 0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x08 } ; - -/* Change to true to disable packet slicing and/or packet grouping, if needed */ -#define DISABLE_PACKET_SLICING false -#define DISABLE_PACKET_GROUPING false - -/* This removes the print statements (which hammer pqidebug) */ -/*** -#define RSITEM_DEBUG 1 -#define DEBUG_TRANSFERS 1 -#define DEBUG_PQISTREAMER 1 -#define DEBUG_PACKET_SLICING 1 - ***/ - -#ifdef DEBUG_TRANSFERS - #include "util/rsprint.h" -#endif - -static double getCurrentTS() -{ -#ifndef WINDOWS_SYS - struct timeval cts_tmp; - gettimeofday(&cts_tmp, NULL); - double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; -#else - struct _timeb timebuf; - _ftime( &timebuf); - double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; -#endif - return cts; -} - -pqistreamer::pqistreamer(RsSerialiser *rss, const RsPeerId& id, BinInterface *bio_in, int bio_flags_in) - :PQInterface(id), mStreamerMtx("pqistreamer"), - mBio(bio_in), mBio_flags(bio_flags_in), mRsSerialiser(rss), - mPkt_wpending(NULL), mPkt_wpending_size(0), - mTotalRead(0), mTotalSent(0), - mCurrRead(0), mCurrSent(0), - mAvgReadCount(0), mAvgSentCount(0), - mAvgDtOut(0), mAvgDtIn(0) -{ - - // 100 B/s (minimal) - setMaxRate(true, 0.1); - setMaxRate(false, 0.1); - setRate(true, 0); // needs to be off-mutex - setRate(false, 0); - - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - - mAcceptsPacketSlicing = false ; // by default. Will be turned into true when everyone's ready. - mLastSentPacketSlicingProbe = 0 ; - - mAvgLastUpdate = mCurrSentTS = mCurrReadTS = getCurrentTS(); - - mIncomingSize = 0 ; - mIncomingSize_bytes = 0; - - mStatisticsTimeStamp = 0 ; - /* allocated once */ - mPkt_rpend_size = 0; - mPkt_rpending = 0; - mReading_state = reading_state_initial ; - - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::pqistreamer() Initialisation!"); - - if (!bio_in) - { - pqioutput(PQL_ALERT, pqistreamerzone, "pqistreamer::pqistreamer() NULL bio, FATAL ERROR!"); - exit(1); - } - - mFailed_read_attempts = 0; // reset failed read, as no packet is still read. - - return; -} - -pqistreamer::~pqistreamer() -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ -#ifdef DEBUG_PQISTREAMER - std::cerr << "Closing pqistreamer." << std::endl; -#endif - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::~pqistreamer() Destruction!"); - - if (mBio_flags & BIN_FLAGS_NO_CLOSE) - { - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::~pqistreamer() Not Closing BinInterface!"); - } - else if (mBio) - { - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::~pqistreamer() Deleting BinInterface!"); - - delete mBio; - } - - /* clean up serialiser */ - if (mRsSerialiser) - delete mRsSerialiser; - - free_pend() ; - - // clean up incoming. - while (!mIncoming.empty()) - { - RsItem *i = mIncoming.front(); - mIncoming.pop_front() ; - --mIncomingSize; - delete i; - } - - if (mIncomingSize != 0) - std::cerr << "(EE) inconsistency after deleting pqistreamer queue. Remaining items: " << mIncomingSize << std::endl ; - return; -} - - -// Get/Send Items. -// This is the entry poing for methods willing to send items through our out queue -int pqistreamer::SendItem(RsItem *si,uint32_t& out_size) -{ -#ifdef RSITEM_DEBUG - { - std::string out = "pqistreamer::SendItem():\n"; - si -> print_string(out); - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out); - std::cerr << out; - } -#endif - - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - - return queue_outpqi_locked(si,out_size); -} - -RsItem *pqistreamer::GetItem() -{ -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::GetItem()"); -#endif - - if(mIncoming.empty()) - return NULL; - - RsItem *osr = mIncoming.front() ; - mIncoming.pop_front() ; - --mIncomingSize; -// for future use -// mIncomingSize_bytes -= - - return osr; -} - - -float pqistreamer::getMaxRate(bool b) -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - return getMaxRate_locked(b); -} - -float pqistreamer::getMaxRate_locked(bool b) -{ - return RateInterface::getMaxRate(b) ; -} - -float pqistreamer::getRate(bool b) -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - return RateInterface::getRate(b) ; -} - -void pqistreamer::setMaxRate(bool b,float f) -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - setMaxRate_locked(b,f); -} - -void pqistreamer::setMaxRate_locked(bool b,float f) -{ - RateInterface::setMaxRate(b,f) ; -} - -void pqistreamer::setRate(bool b,float f) -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - RateInterface::setRate(b,f) ; -} - - -void pqistreamer::updateRates() -{ - // update actual rates both ways. - - double t = getCurrentTS(); // get current timestamp. - double diff = t - mAvgLastUpdate; - - if (diff > PQISTREAM_AVG_PERIOD) - { - float avgReadpSec = PQISTREAM_AVG_FRAC * getRate(true ) + (1.0 - PQISTREAM_AVG_FRAC) * mAvgReadCount/(1024.0 * diff); - float avgSentpSec = PQISTREAM_AVG_FRAC * getRate(false) + (1.0 - PQISTREAM_AVG_FRAC) * mAvgSentCount/(1024.0 * diff); - -#ifdef DEBUG_PQISTREAMER - uint64_t t_now = 1000 * getCurrentTS(); - std::cerr << std::dec << t_now << " DEBUG_PQISTREAMER pqistreamer::updateRates PeerId " << this->PeerId().toStdString() << " Current speed estimates: down " << std::dec << (int)(1024 * avgReadpSec) << " B/s / up " << (int)(1024 * avgSentpSec) << " B/s" << std::endl; -#endif - - // now store the new rates, zero meaning that we are not bandwidthLimited() - - if (mBio->bandwidthLimited()) - { - setRate(true, avgReadpSec); - setRate(false, avgSentpSec); - } - else - { - setRate(true, 0); - setRate(false, 0); - } - - mAvgLastUpdate = t; - mAvgReadCount = 0; - - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - mAvgSentCount = 0; - } - } -} - -int pqistreamer::tick_bio() -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - mBio->tick(); - - /* short circuit everything if bio isn't active */ - if (!(mBio->isactive())) - { - return 0; - } - return 1; -} - -int pqistreamer::tick_recv(uint32_t timeout) -{ - if (mBio->moretoread(timeout)) - { - handleincoming(); - } - if(!(mBio->isactive())) - { - RsStackMutex stack(mStreamerMtx); - free_pend(); - } - return 1; -} - -int pqistreamer::tick_send(uint32_t timeout) -{ - /* short circuit everything if bio isn't active */ - if (!(mBio->isactive())) - { - RsStackMutex stack(mStreamerMtx); - free_pend(); - return 0; - } - - if (mBio->cansend(timeout)) - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - handleoutgoing_locked(); - } - - return 1; -} - -int pqistreamer::status() -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - - -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::status()"); - - if (mBio->isactive()) - { - std::string out; - rs_sprintf(out, "Data in:%d out:%d", mTotalRead, mTotalSent); - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out); - } -#endif - - return 0; -} - -// this method is overloaded by pqiqosstreamer -void pqistreamer::locked_storeInOutputQueue(void *ptr,int,int) -{ - mOutPkts.push_back(ptr); -} - -int pqistreamer::queue_outpqi_locked(RsItem *pqi,uint32_t& pktsize) -{ - pktsize = 0 ; -#ifdef DEBUG_PQISTREAMER - std::cerr << "pqistreamer::queue_outpqi() called." << std::endl; -#endif - - /* decide which type of packet it is */ - - pktsize = mRsSerialiser->size(pqi); - void *ptr = rs_malloc(pktsize); - - if(ptr == NULL) - return 0 ; - -#ifdef DEBUG_PQISTREAMER - std::cerr << "pqistreamer::queue_outpqi() serializing packet with packet size : " << pktsize << std::endl; -#endif - - /*******************************************************************************************/ - // keep info for stats for a while. Only keep the items for the last two seconds. sec n is ongoing and second n-1 - // is a full statistics chunk that can be used in the GUI - - locked_addTrafficClue(pqi,pktsize,mCurrentStatsChunk_Out) ; - - /*******************************************************************************************/ - - if (mRsSerialiser->serialise(pqi, ptr, &pktsize)) - { - locked_storeInOutputQueue(ptr,pktsize,pqi->priority_level()) ; - - if (!(mBio_flags & BIN_FLAGS_NO_DELETE)) - { - delete pqi; - } - return 1; - } - else - { - /* cleanup serialiser */ - free(ptr); - } - - std::string out = "pqistreamer::queue_outpqi() Null Pkt generated!\nCaused By:\n"; - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqistreamerzone, out); - - if (!(mBio_flags & BIN_FLAGS_NO_DELETE)) - { - delete pqi; - } - return 1; // keep error internal. -} - -int pqistreamer::handleincomingitem(RsItem *pqi,int len) -{ - -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::handleincomingitem()"); -#endif - // timestamp last received packet. - mLastIncomingTs = time(NULL); - - // Use overloaded Contact function - pqi -> PeerId(PeerId()); - - mIncoming.push_back(pqi); - ++mIncomingSize; - // for future use - // mIncomingSize_bytes += len; - - /*******************************************************************************************/ - // keep info for stats for a while. Only keep the items for the last two seconds. sec n is ongoing and second n-1 - // is a full statistics chunk that can be used in the GUI - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - locked_addTrafficClue(pqi,len,mCurrentStatsChunk_In) ; - } - /*******************************************************************************************/ - - return 1; -} - -void pqistreamer::locked_addTrafficClue(const RsItem *pqi,uint32_t pktsize,std::list& lst) -{ - rstime_t now = time(NULL) ; - - if(now > mStatisticsTimeStamp) // new chunk => get rid of oldest, replace old list by current list, clear current list. - { - mPreviousStatsChunk_Out = mCurrentStatsChunk_Out ; - mPreviousStatsChunk_In = mCurrentStatsChunk_In ; - mCurrentStatsChunk_Out.clear() ; - mCurrentStatsChunk_In.clear() ; - - mStatisticsTimeStamp = now ; - } - - RSTrafficClue tc ; - tc.TS = now ; - tc.size = pktsize ; - tc.priority = pqi->priority_level() ; - tc.peer_id = pqi->PeerId() ; - tc.count = 1 ; - tc.service_id = pqi->PacketService() ; - tc.service_sub_id = pqi->PacketSubType() ; - - lst.push_back(tc) ; -} - -rstime_t pqistreamer::getLastIncomingTS() -{ - // This is the only case where another thread (rs main for pqiperson) will access our data - // Still a mutex lock is not needed because the operation is atomic - return mLastIncomingTs; -} - -// Packet slicing: -// -// Old : 02 0014 03 00000026 [data, 26 bytes] => [version 1B] [service 2B][subpacket 1B] [size 4B] -// New2: pp ff xxxxxxxx ssss [data, sss bytes] => [protocol version 1B] [flags 1B] [2^32 packet count] [2^16 size] -// -// Encode protocol on 1.0 Bytes ( 8 bits) -// Encode flags on 1.0 Bytes ( 8 bits) -// 0x01 => incomplete packet continued after -// 0x02 => packet ending a previously incomplete packet -// -// Encode packet ID on 4.0 Bytes (32 bits) => packet counter = [0...2^32] -// Encode size on 2.0 Bytes (16 bits) => 65536 // max slice size = 65536 -// -// Backward compatibility: -// * send one packet with service + subpacket = aabbcc. Old peers will silently ignore such packets. Full packet header is: 02aabbcc 00000008 -// * if received, mark the peer as able to decode the new packet type -// In pqiQoS: -// - limit packet grouping to max size 512. -// - new peers need to read flux, and properly extract partial sizes, and combine packets based on packet counter. -// - on sending, RS grabs slices of max size 1024 from pqiQoS. If smaller, possibly pack them together. -// pqiQoS keeps track of sliced packets and makes sure the output is consistent: -// * when a large packet needs to be send, only takes a slice and return it, and update the remaining part -// * always consider priority when taking new slices => a newly arrived fast packet will always get through. -// -// Max slice size should be customisable, depending on bandwidth. To be tested... -// - -int pqistreamer::handleoutgoing_locked() -{ -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::handleoutgoing_locked()"); -#endif - - int maxbytes = outAllowedBytes_locked(); - int sentbytes = 0; - - // std::cerr << "pqistreamer: maxbytes=" << maxbytes<< std::endl ; - - std::list::iterator it; - - // if not connection, or cannot send anything... pause. - if (!(mBio->isactive())) - { - /* if we are not active - clear anything in the queues. */ - locked_clear_out_queue() ; -#ifdef DEBUG_PACKET_SLICING - std::cerr << "(II) Switching off packet slicing." << std::endl; -#endif - mAcceptsPacketSlicing = false ; - - /* also remove the pending packets */ - if (mPkt_wpending) - { - free(mPkt_wpending); - mPkt_wpending = NULL; - mPkt_wpending_size = 0 ; - } - - return 0; - } - - // a very simple round robin - - bool sent = true; - int nsent = 0 ; - while(sent) // catch if all items sent. - { - sent = false; - - if ((!(mBio->cansend(0))) || (maxbytes < sentbytes)) - { -#ifdef DEBUG_PQISTREAMER - if (sentbytes > maxbytes) - RsDbg() << "PQISTREAMER pqistreamer::handleoutgoing_locked() stopped sending max reached, sentbytes " << std::dec << sentbytes << " maxbytes " << maxbytes; - else - RsDbg() << "PQISTREAMER pqistreamer::handleoutgoing_locked() stopped sending bio not ready, sentbytes " << std::dec << sentbytes << " maxbytes " << maxbytes; -#endif - return 0; - } - // send a out_pkt., else send out_data. unless there is a pending packet. The strategy is to - // - grab as many packets as possible while below the optimal packet size, so as to allow some packing and decrease encryption padding overhead (suposeddly) - // - limit packets size to OPTIMAL_PACKET_SIZE when sending big packets so as to keep as much QoS as possible. - - if (!mPkt_wpending) - { - void *dta; - mPkt_wpending_size = 0 ; - int k=0; - - // Checks for inserting a packet slicing probe. We do that to send the other peer the information that packet slicing can be used. - // if so, we enable it for the session. This should be removed (because it's unnecessary) when all users have switched to the new version. - rstime_t now = time(NULL) ; - - if(now > mLastSentPacketSlicingProbe + PQISTREAM_PACKET_SLICING_PROBE_DELAY) - { -#ifdef DEBUG_PACKET_SLICING - std::cerr << "(II) Inserting packet slicing probe in traffic" << std::endl; -#endif - - mPkt_wpending_size = 8 ; - mPkt_wpending = rs_malloc(8) ; - memcpy(mPkt_wpending,PACKET_SLICING_PROBE_BYTES,8) ; - - mLastSentPacketSlicingProbe = now ; - } - - uint32_t slice_size=0; - bool slice_starts=true ; - bool slice_ends=true ; - uint32_t slice_packet_id=0 ; - - do - { - int desired_packet_size = mAcceptsPacketSlicing?PQISTREAM_OPTIMAL_PACKET_SIZE:(getRsPktMaxSize()); - - dta = locked_pop_out_data(desired_packet_size,slice_size,slice_starts,slice_ends,slice_packet_id) ; - - if(!dta) - break ; - - if(slice_starts && slice_ends) // good old method. Send the packet as is, since it's a full packet. - { -#ifdef DEBUG_PACKET_SLICING - std::cerr << "sending full slice, old style. Size=" << slice_size << std::endl; -#endif - mPkt_wpending = realloc(mPkt_wpending,slice_size+mPkt_wpending_size) ; - memcpy( &((char*)mPkt_wpending)[mPkt_wpending_size],dta,slice_size) ; - free(dta); - mPkt_wpending_size += slice_size ; - ++k ; - } - else // partial packet. We make a special header for it and insert it in the stream - { - if(slice_size > 0xffff || !mAcceptsPacketSlicing) - { - std::cerr << "(EE) protocol error in pqitreamer: slice size is too large and cannot be encoded." ; - free(mPkt_wpending) ; - mPkt_wpending_size = 0; - return -1 ; - } -#ifdef DEBUG_PACKET_SLICING - std::cerr << "sending partial slice, packet ID=" << std::hex << slice_packet_id << std::dec << ", size=" << slice_size << std::endl; -#endif - - mPkt_wpending = realloc(mPkt_wpending,slice_size+mPkt_wpending_size+PQISTREAM_PARTIAL_PACKET_HEADER_SIZE) ; - memcpy( &((char*)mPkt_wpending)[mPkt_wpending_size+PQISTREAM_PARTIAL_PACKET_HEADER_SIZE],dta,slice_size) ; - free(dta); - - // New2: pp ff xxxxxxxx ssss [data, sss bytes] => [flags 1B] [protocol version 1B] [2^32 packet count] [2^16 size] - - uint8_t partial_flags = 0 ; - if(slice_starts) partial_flags |= PQISTREAM_SLICE_FLAG_STARTS ; - if(slice_ends ) partial_flags |= PQISTREAM_SLICE_FLAG_ENDS ; - - ((char*)mPkt_wpending)[mPkt_wpending_size+0x00] = PQISTREAM_SLICE_PROTOCOL_VERSION_ID_01 ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x01] = partial_flags ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x02] = uint8_t(slice_packet_id >> 24) & 0xff ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x03] = uint8_t(slice_packet_id >> 16) & 0xff ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x04] = uint8_t(slice_packet_id >> 8) & 0xff ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x05] = uint8_t(slice_packet_id >> 0) & 0xff ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x06] = uint8_t(slice_size >> 8) & 0xff ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x07] = uint8_t(slice_size >> 0) & 0xff ; - - mPkt_wpending_size += slice_size + PQISTREAM_PARTIAL_PACKET_HEADER_SIZE; - ++k ; - } - } - while(mPkt_wpending_size < (uint32_t)maxbytes && mPkt_wpending_size < PQISTREAM_OPTIMAL_PACKET_SIZE && !DISABLE_PACKET_GROUPING) ; - -#ifdef DEBUG_PQISTREAMER - if(k > 1) - std::cerr << "Packed " << k << " packets into " << mPkt_wpending_size << " bytes." << std::endl; -#endif - } - - if (mPkt_wpending) - { - // write packet. -#ifdef DEBUG_PQISTREAMER - std::cout << "Sending Out Pkt of size " << mPkt_wpending_size << " !" << std::endl; -#endif - int ss=0; - - if (mPkt_wpending_size != (uint32_t)(ss = mBio->senddata(mPkt_wpending, mPkt_wpending_size))) - { -#ifdef DEBUG_PQISTREAMER - std::string out; - rs_sprintf(out, "Problems with Send Data! (only %d bytes sent, total pkt size=%d)", ss, mPkt_wpending_size); - // std::cerr << out << std::endl ; - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out); -#endif - std::cerr << PeerId() << ": sending failed. Only " << ss << " bytes sent over " << mPkt_wpending_size << std::endl; - - // pkt_wpending will kept til next time. - // ensuring exactly the same data is written (openSSL requirement). - return -1; - } -#ifdef DEBUG_PQISTREAMER - else - std::cerr << PeerId() << ": sent " << ss << " bytes " << std::endl; -#endif - - ++nsent; - - outSentBytes_locked(mPkt_wpending_size); // this is the only time where we know exactly what was sent. - -#ifdef DEBUG_TRANSFERS - std::cerr << "pqistreamer::handleoutgoing_locked() Sent Packet len: " << mPkt_wpending_size << " @ " << RsUtil::AccurateTimeString(); - std::cerr << std::endl; -#endif - - sentbytes += mPkt_wpending_size; - - free(mPkt_wpending); - mPkt_wpending = NULL; - mPkt_wpending_size = 0 ; - - sent = true; - } - } -#ifdef DEBUG_PQISTREAMER - if(nsent > 0) - std::cerr << "nsent = " << nsent << ", total bytes=" << sentbytes << std::endl; -#endif - return 1; -} - - -/* Handles reading from input stream. - */ -int pqistreamer::handleincoming() -{ - int readbytes = 0; - static const int max_failed_read_attempts = 2000 ; - -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::handleincoming()"); -#endif - - if(!(mBio->isactive())) - { - RsStackMutex stack(mStreamerMtx); - mReading_state = reading_state_initial ; - free_pend(); - return 0; - } - else - allocate_rpend(); - - // enough space to read any packet. - uint32_t maxlen = mPkt_rpend_size; - void *block = mPkt_rpending; - - // initial read size: basic packet. - int blen = getRsPktBaseSize(); // this is valid for both packet slices and normal un-sliced packets (same header size) - - int maxin = inAllowedBytes(); - -#ifdef DEBUG_PQISTREAMER - std::cerr << "[" << (void*)pthread_self() << "] " << "reading state = " << mReading_state << std::endl ; -#endif - switch(mReading_state) - { - case reading_state_initial: /*std::cerr << "jumping to start" << std::endl; */ goto start_packet_read ; - case reading_state_packet_started: /*std::cerr << "jumping to middle" << std::endl;*/ goto continue_packet ; - } - -start_packet_read: - { // scope to ensure variable visibility - // read the basic block (minimum packet size) - int tmplen; -#ifdef DEBUG_PQISTREAMER - std::cerr << "[" << (void*)pthread_self() << "] " << "starting packet" << std::endl ; -#endif - memset(block,0,blen) ; // reset the block, to avoid uninitialized memory reads. - - if (blen != (tmplen = mBio->readdata(block, blen))) - { - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, "pqistreamer::handleincoming() Didn't read BasePkt!"); - - // error.... (either blocked or failure) - if (tmplen == 0) - { -#ifdef DEBUG_PQISTREAMER - // most likely blocked! - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, "pqistreamer::handleincoming() read blocked"); - std::cerr << "[" << (void*)pthread_self() << "] " << "given up 1" << std::endl ; -#endif - return 0; - } - else if (tmplen < 0) - { - // Most likely it is that the packet is pending but could not be read by pqissl because of stream flow. - // So we return without an error, and leave the machine state in 'start_read'. - // - //pqioutput(PQL_WARNING, pqistreamerzone, "pqistreamer::handleincoming() Error in bio read"); -#ifdef DEBUG_PQISTREAMER - std::cerr << "[" << (void*)pthread_self() << "] " << "given up 2, state = " << mReading_state << std::endl ; -#endif - return 0; - } - else // tmplen > 0 - { - // strange case....This should never happen as partial reads are handled by pqissl below. -#ifdef DEBUG_PQISTREAMER - std::string out = "pqistreamer::handleincoming() Incomplete "; - rs_sprintf_append(out, "(Strange) read of %d bytes", tmplen); - pqioutput(PQL_ALERT, pqistreamerzone, out); - - std::cerr << "[" << (void*)pthread_self() << "] " << "given up 3" << std::endl ; -#endif - return -1; - } - } -#ifdef DEBUG_PQISTREAMER - std::cerr << "[" << (void*)pthread_self() << "] " << "block 0 : " << RsUtil::BinToHex((unsigned char*)block,8) << std::endl; -#endif - - readbytes += blen; - mReading_state = reading_state_packet_started ; - mFailed_read_attempts = 0 ; // reset failed read, as the packet has been totally read. - - // Check for packet slicing probe (04/26/2016). To be removed when everyone uses it. - - if(!memcmp(block,PACKET_SLICING_PROBE_BYTES,8)) - { - mAcceptsPacketSlicing = !DISABLE_PACKET_SLICING; -#ifdef DEBUG_PACKET_SLICING - std::cerr << "(II) Enabling packet slicing!" << std::endl; -#endif - } - } -continue_packet: - { - // workout how much more to read. - - bool is_partial_packet = false ; - bool is_packet_starting = (((char*)block)[1] == PQISTREAM_SLICE_FLAG_STARTS) ; // STARTS and ENDS flags are actually never combined. - bool is_packet_ending = (((char*)block)[1] == PQISTREAM_SLICE_FLAG_ENDS) ; - bool is_packet_middle = (((char*)block)[1] == 0x00) ; - - uint32_t extralen =0; - uint32_t slice_packet_id =0; - - if( ((char*)block)[0] == PQISTREAM_SLICE_PROTOCOL_VERSION_ID_01 && ( is_packet_starting || is_packet_middle || is_packet_ending)) - { - extralen = (uint32_t(((uint8_t*)block)[6]) << 8 ) + (uint32_t(((uint8_t*)block)[7])); - slice_packet_id = (uint32_t(((uint8_t*)block)[2]) << 24) + (uint32_t(((uint8_t*)block)[3]) << 16) + (uint32_t(((uint8_t*)block)[4]) << 8) + (uint32_t(((uint8_t*)block)[5]) << 0); - -#ifdef DEBUG_PACKET_SLICING - std::cerr << "Reading partial packet from mem block " << RsUtil::BinToHex((char*)block,8) << ": packet_id=" << std::hex << slice_packet_id << std::dec << ", len=" << extralen << std::endl; -#endif - is_partial_packet = true ; - - mAcceptsPacketSlicing = !DISABLE_PACKET_SLICING; // this is needed - } - else - extralen = getRsItemSize(block) - blen; // old style packet type - -#ifdef DEBUG_PACKET_SLICING - std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet getRsItemSize(block) = " << getRsItemSize(block) << std::endl ; - std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet extralen = " << extralen << std::endl ; - - std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet state=" << mReading_state << std::endl ; - std::cerr << "[" << (void*)pthread_self() << "] " << "block 1 : " << RsUtil::BinToHex((unsigned char*)block,8) << std::endl; -#endif - if (extralen + (uint32_t)blen > maxlen) - { - pqioutput(PQL_ALERT, pqistreamerzone, "ERROR: Read Packet too Big!"); - - p3Notify *notify = RsServer::notify(); - if (notify) - { - std::string title = - "Warning: Bad Packet Read"; - - std::string msg; - msg = " **** WARNING **** \n"; - msg += "Retroshare has caught a BAD Packet Read"; - msg += "\n"; - msg += "This is normally caused by connecting to an"; - msg += " OLD version of Retroshare"; - msg += "\n"; - rs_sprintf_append(msg, "(M:%d B:%d E:%d)\n", maxlen, blen, extralen); - msg += "\n"; - msg += "block = " ; - msg += RsUtil::BinToHex((char*)block,8); - - msg += "\n"; - msg += "Please get your friends to upgrade to the latest version"; - msg += "\n"; - msg += "\n"; - msg += "If you are sure the error was not caused by an old version"; - msg += "\n"; - msg += "Please report the problem to Retroshare's developers"; - msg += "\n"; - - notify->AddLogMessage(0, RS_SYS_WARNING, title, msg); - - std::cerr << "pqistreamer::handle_incoming() ERROR: Read Packet too Big" << std::endl; - std::cerr << msg; - std::cerr << std::endl; - - } - mBio->close(); - mReading_state = reading_state_initial ; // restart at state 1. - mFailed_read_attempts = 0 ; - return -1; - - // Used to exit now! exit(1); - } - - if (extralen > 0) - { - void *extradata = (void *) (((char *) block) + blen); - int tmplen ; - - // Don't reset the block now! If pqissl is in the middle of a multiple-chunk - // packet (larger than 16384 bytes), and pqistreamer jumped directly yo - // continue_packet:, then readdata is going to write after the beginning of - // extradata, yet not exactly at start -> the start of the packet would be wiped out. - // - // so, don't do that: - // memset( extradata,0,extralen ) ; - - if (extralen != (uint32_t)(tmplen = mBio->readdata(extradata, extralen))) - { -#ifdef DEBUG_PACKET_SLICING - if(tmplen > 0) - std::cerr << "[" << (void*)pthread_self() << "] " << "Incomplete packet read ! This is a real problem ;-)" << std::endl ; -#endif - - if(++mFailed_read_attempts > max_failed_read_attempts) - { - std::string out; - rs_sprintf(out, "Error Completing Read (read %d/%d)", tmplen, extralen); - std::cerr << out << std::endl ; - pqioutput(PQL_ALERT, pqistreamerzone, out); - - p3Notify *notify = RsServer::notify(); - if (notify) - { - std::string title = "Warning: Error Completing Read"; - - std::string msgout; - msgout = " **** WARNING **** \n"; - msgout += "Retroshare has experienced an unexpected Read ERROR"; - msgout += "\n"; - rs_sprintf_append(msgout, "(M:%d B:%d E:%d R:%d)\n", maxlen, blen, extralen, tmplen); - msgout += "\n"; - msgout += "Note: this error might as well happen (rarely) when a peer disconnects in between a transmission of a large packet.\n"; - msgout += "If it happens manny time, please contact the developers, and send them these numbers:"; - msgout += "\n"; - - msgout += "block = " ; - msgout += RsUtil::BinToHex((char*)block,8) + "\n" ; - - std::cerr << msgout << std::endl; - } - - mBio->close(); - mReading_state = reading_state_initial ; // restart at state 1. - mFailed_read_attempts = 0 ; - return -1; - } - else - { -#ifdef DEBUG_PQISTREAMER - std::cerr << "[" << (void*)pthread_self() << "] " << "given up 5, state = " << mReading_state << std::endl ; -#endif - return 0 ; // this is just a SSL_WANT_READ error. Don't panic, we'll re-try the read soon. - // we assume readdata() returned either -1 or the complete read size. - } - } -#ifdef DEBUG_PACKET_SLICING - std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet state=" << mReading_state << std::endl ; - std::cerr << "[" << (void*)pthread_self() << "] " << "block 2 : " << RsUtil::BinToHex((unsigned char*)extradata,8) << std::endl; -#endif - - mFailed_read_attempts = 0 ; - readbytes += extralen; - } - - // create packet, based on header. -#ifdef DEBUG_PQISTREAMER - { - std::string out; - rs_sprintf(out, "Read Data Block -> Incoming Pkt(%d)", blen + extralen); - //std::cerr << out ; - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out); - } -#endif - - uint32_t pktlen = blen+extralen ; -#ifdef DEBUG_PQISTREAMER - std::cerr << "[" << (void*)pthread_self() << "] " << RsUtil::BinToHex((char*)block,8) << "...: deserializing. Size=" << pktlen << std::endl ; -#endif - RsItem *pkt ; - - if(is_partial_packet) - { -#ifdef DEBUG_PACKET_SLICING - std::cerr << "Inputing partial packet " << RsUtil::BinToHex((char*)block,8) << std::endl; -#endif - uint32_t packet_length = 0 ; - pkt = addPartialPacket(block,pktlen,slice_packet_id,is_packet_starting,is_packet_ending,packet_length) ; - - pktlen = packet_length ; - } - else - pkt = mRsSerialiser->deserialise(block, &pktlen); - - if ((pkt != NULL) && (0 < handleincomingitem(pkt,pktlen))) - { -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, "Successfully Read a Packet!"); -#endif - inReadBytes(pktlen); // only count deserialised packets, because that's what is actually been transfered. - } - else if (!is_partial_packet) - { -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_ALERT, pqistreamerzone, "Failed to handle Packet!"); -#endif - std::cerr << "Incoming Packet could not be deserialised:" << std::endl; - std::cerr << " Incoming peer id: " << PeerId() << std::endl; - if(pktlen >= 8) - std::cerr << " Packet header : " << RsUtil::BinToHex((unsigned char*)block,8) << std::endl; - if(pktlen > 8) - std::cerr << " Packet data : " << RsUtil::BinToHex((unsigned char*)block+8,std::min(50u,pktlen-8)) << ((pktlen>58)?"...":"") << std::endl; - } - - mReading_state = reading_state_initial ; // restart at state 1. - mFailed_read_attempts = 0 ; // reset failed read, as the packet has been totally read. - } - - if(maxin > readbytes && mBio->moretoread(0)) - goto start_packet_read ; - -#ifdef DEBUG_PQISTREAMER - if (readbytes > maxin) - RsDbg() << "PQISTREAMER pqistreamer::handleincoming() stopped reading max reached, readbytes " << std::dec << readbytes << " maxin " << maxin; - else - RsDbg() << "PQISTREAMER pqistreamer::handleincoming() stopped reading no more to read, readbytes " << std::dec << readbytes << " maxin " << maxin; -#endif - - return 0; -} - -RsItem *pqistreamer::addPartialPacket(const void *block, uint32_t len, uint32_t slice_packet_id, bool is_packet_starting, bool is_packet_ending, uint32_t &total_len) -{ -#ifdef DEBUG_PACKET_SLICING - std::cerr << "Receiving partial packet. size=" << len << ", ID=" << std::hex << slice_packet_id << std::dec << ", starting:" << is_packet_starting << ", ending:" << is_packet_ending ; -#endif - - if(is_packet_starting && is_packet_ending) - { - std::cerr << " (EE) unexpected situation: both starting and ending" << std::endl; - return NULL ; - } - - uint32_t slice_length = len - PQISTREAM_PARTIAL_PACKET_HEADER_SIZE ; - unsigned char *slice_data = &((unsigned char*)block)[PQISTREAM_PARTIAL_PACKET_HEADER_SIZE] ; - - std::map::iterator it = mPartialPackets.find(slice_packet_id) ; - - if(it == mPartialPackets.end()) - { - // make sure we really have a starting packet. Otherwise this is an error. - - if(!is_packet_starting) - { - std::cerr << " (EE) non starting packet has no record. Dropping" << std::endl; - return NULL ; - } - PartialPacketRecord& rec = mPartialPackets[slice_packet_id] ; - - rec.mem = rs_malloc(slice_length) ; - - if(!rec.mem) - { - std::cerr << " (EE) Cannot allocate memory for slice of size " << slice_length << std::endl; - return NULL ; - } - - memcpy(rec.mem, slice_data, slice_length) ; ; - rec.size = slice_length ; - -#ifdef DEBUG_PACKET_SLICING - std::cerr << " => stored in new record (size=" << rec.size << std::endl; -#endif - - return NULL ; // no need to check for ending - } - else - { - PartialPacketRecord& rec = it->second ; - - if(is_packet_starting) - { - std::cerr << "(WW) dropping unfinished existing packet that gets to be replaced by new starting packet." << std::endl; - free(rec.mem); - rec.mem = NULL ; - rec.size = 0 ; - } - // make sure this is a continuing packet, otherwise this is an error. - - rec.mem = realloc(rec.mem, rec.size + slice_length) ; - memcpy( &((char*)rec.mem)[rec.size],slice_data,slice_length) ; - rec.size += slice_length ; - -#ifdef DEBUG_PACKET_SLICING - std::cerr << " => added to existing record size=" << rec.size ; -#endif - - if(is_packet_ending) - { -#ifdef DEBUG_PACKET_SLICING - std::cerr << " => deserialising: mem=" << RsUtil::BinToHex((char*)rec.mem,std::min(8u,rec.size)) << std::endl; -#endif - RsItem *item = mRsSerialiser->deserialise(rec.mem, &rec.size); - - total_len = rec.size ; - free(rec.mem) ; - mPartialPackets.erase(it) ; - return item ; - } - else - { -#ifdef DEBUG_PACKET_SLICING - std::cerr << std::endl; -#endif - return NULL ; - } - } -} - -/* BandWidth Management Assistance */ - -float pqistreamer::outTimeSlice_locked() -{ -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::outTimeSlice()"); -#endif - - //fixme("pqistreamer::outTimeSlice()", 1); - return 1; -} - -int pqistreamer::outAllowedBytes_locked() -{ - double t = getCurrentTS() ; // in sec, with high accuracy - - // allow a lot if not bandwidthLimited() - if (!mBio->bandwidthLimited()) - { - mCurrSent = 0; - mCurrSentTS = t; - return PQISTREAM_ABS_MAX; - } - - // dt is the time elapsed since the last round of sending data - double dt = t - mCurrSentTS; - - // ignore cases where dt > 1s - if (dt > 1) - dt = 1; - - // low pass filter on mAvgDtOut - mAvgDtOut = PQISTREAM_AVG_DT_FRAC * mAvgDtOut + (1 - PQISTREAM_AVG_DT_FRAC) * dt; - - double maxout = getMaxRate_locked(false) * 1024.0; - - // this is used to take into account a possible excess of data sent during the previous round - mCurrSent -= int(dt * maxout); - - // we dont allow negative value, any quota not used during the previous round is therefore lost - if (mCurrSent < 0) - mCurrSent = 0; - - mCurrSentTS = t; - - // now calculate the amount of data allowed to be sent during the next round - // we take into account the possible excess (but not deficit) of the previous round - // (this is handled differently when reading data, see below) - double quota = mAvgDtOut * maxout - mCurrSent; - -#ifdef DEBUG_PQISTREAMER - RsDbg() << "PQISTREAMER pqistreamer::outAllowedBytes_locked() dt " << std::dec << (int)(1000 * dt) << "ms, mAvgDtOut " << (int)(1000 * mAvgDtOut) << "ms, maxout " << (int)(maxout) << " bytes/s, mCurrSent " << mCurrSent << " bytes, quota " << (int)(quota) << " bytes"; -#endif - - return quota; -} - -int pqistreamer::inAllowedBytes() -{ - double t = getCurrentTS(); // in sec, with high accuracy - - // allow a lot if not bandwidthLimited() - if (!mBio->bandwidthLimited()) - { - mCurrRead = 0; - mCurrReadTS = t; - return PQISTREAM_ABS_MAX; - } - - // dt is the time elapsed since the last round of receiving data - double dt = t - mCurrReadTS; - - // limit dt to 1s - if (dt > 1) - dt = 1; - - // low pass filter on mAvgDtIn - mAvgDtIn = PQISTREAM_AVG_DT_FRAC * mAvgDtIn + (1 - PQISTREAM_AVG_DT_FRAC) * dt; - - double maxin = getMaxRate(true) * 1024.0; - - // this is used to take into account a possible excess/deficit of data received during the previous round - mCurrRead -= int(dt * maxin); - - // we allow negative value up to the average amount of data received during one round - // in that case we will use this credit during the next around - if (mCurrRead < - mAvgDtIn * maxin) - mCurrRead = - mAvgDtIn * maxin; - - mCurrReadTS = t; - - // we now calculate the max amount of data allowed to be received during the next round - // we take into account the excess/deficit of the previous round - double quota = mAvgDtIn * maxin - mCurrRead; - -#ifdef DEBUG_PQISTREAMER - RsDbg() << "PQISTREAMER pqistreamer::inAllowedBytes() dt " << std::dec << (int)(1000 * dt) << "ms, mAvgDtIn " << (int)(1000 * mAvgDtIn) << "ms, maxin " << (int)(maxin) << " bytes/s, mCurrRead " << mCurrRead << " bytes, quota " << (int)(quota) << " bytes"; -#endif - - return quota; -} - -void pqistreamer::outSentBytes_locked(uint32_t outb) -{ -#ifdef DEBUG_PQISTREAMER - { - std::string out; - rs_sprintf(out, "pqistreamer::outSentBytes(): %d@%gkB/s", outb, RateInterface::getRate(false)); - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out); - } -#endif - - /*** One theory for the massive delays - is that the queue here is filling up ****/ -//#define DEBUG_LAG 1 -#ifdef DEBUG_LAG - -#define MIN_PKTS_FOR_MSG 100 - if (out_queue_size() > MIN_PKTS_FOR_MSG) - { - std::cerr << "pqistreamer::outSentBytes() for: " << PeerId(); - std::cerr << " End of Write and still " << out_queue_size() << " pkts left"; - std::cerr << std::endl; - } - -#endif - mTotalSent += outb; - mCurrSent += outb; - mAvgSentCount += outb; - PQInterface::traf_out += outb; - return; -} - -void pqistreamer::inReadBytes(uint32_t inb) -{ -#ifdef DEBUG_PQISTREAMER - { - std::string out; - rs_sprintf(out, "pqistreamer::inReadBytes(): %d@%gkB/s", inb, RateInterface::getRate(true)); - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out); - } -#endif - - mTotalRead += inb; - mCurrRead += inb; - mAvgReadCount += inb; - PQInterface::traf_in += inb; - return; -} - -void pqistreamer::allocate_rpend() -{ - if(mPkt_rpending) - return; - - mPkt_rpend_size = getRsPktMaxSize(); - mPkt_rpending = rs_malloc(mPkt_rpend_size); - - if(mPkt_rpending == NULL) - return ; - - // avoid uninitialized (and random) memory read. - memset(mPkt_rpending,0,mPkt_rpend_size) ; -} - -// clean everything that is half-finished, to avoid causing issues when re-connecting later on. - -int pqistreamer::reset() -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ -#ifdef DEBUG_PQISTREAMER - std::cerr << "pqistreamer::reset()" << std::endl; -#endif - free_pend(); - - return 1 ; -} - -void pqistreamer::free_pend() -{ - if(mPkt_rpending) - { -#ifdef DEBUG_PQISTREAMER - std::cerr << "pqistreamer::free_pend(): pending input packet buffer" << std::endl; -#endif - free(mPkt_rpending); - mPkt_rpending = 0; - } - mPkt_rpend_size = 0; - - if (mPkt_wpending) - { -#ifdef DEBUG_PQISTREAMER - std::cerr << "pqistreamer::free_pend(): pending output packet buffer" << std::endl; -#endif - free(mPkt_wpending); - mPkt_wpending = NULL; - } - mPkt_wpending_size = 0 ; - -#ifdef DEBUG_PQISTREAMER - if(!mPartialPackets.empty()) - std::cerr << "pqistreamer::free_pend(): " << mPartialPackets.size() << " pending input partial packets" << std::endl; -#endif - // also delete any incoming partial packet - for(std::map::iterator it(mPartialPackets.begin());it!=mPartialPackets.end();++it) - free(it->second.mem) ; - - mPartialPackets.clear() ; - - // clean up outgoing. (cntrl packets) - locked_clear_out_queue() ; -} - -int pqistreamer::gatherStatistics(std::list& outqueue_lst,std::list& inqueue_lst) -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - - return locked_gatherStatistics(outqueue_lst,inqueue_lst); -} - -// this method is overloaded by pqiqosstreamer -int pqistreamer::getQueueSize(bool in) -{ - if (in) -// no mutex is needed here because this is atomic - return mIncomingSize; - else - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - return locked_out_queue_size(); - } -} - -int pqistreamer::getQueueSize_bytes(bool in) -{ - if (in) -// no mutex is needed here because this is atomic -// for future use, mIncomingSize_bytes is not updated yet - return mIncomingSize_bytes; - else - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - return locked_compute_out_pkt_size(); - } -} - -void pqistreamer::getRates(RsBwRates &rates) -{ - RateInterface::getRates(rates); - -// no mutex is needed here because this is atomic - rates.mQueueIn = mIncomingSize; - - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - rates.mQueueOut = locked_out_queue_size(); - } -} - -// this method is overloaded by pqiqosstreamer -int pqistreamer::locked_out_queue_size() const -{ - // Warning: because out_pkt is a list, calling size - // is O(n) ! Makign algorithms pretty inefficient. We should record how many - // items get stored and discarded to have a proper size value at any time - // - return mOutPkts.size() ; -} - -// this method is overloaded by pqiqosstreamer -void pqistreamer::locked_clear_out_queue() -{ - for(std::list::iterator it = mOutPkts.begin(); it != mOutPkts.end(); ) - { - free(*it); - it = mOutPkts.erase(it); -#ifdef DEBUG_PQISTREAMER - std::string out = "pqistreamer::locked_clear_out_queue() Not active -> Clearing Pkt!"; - std::cerr << out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out); -#endif - } -} - -// this method is overloaded by pqiqosstreamer -int pqistreamer::locked_compute_out_pkt_size() const -{ - int total = 0 ; - - for(std::list::const_iterator it = mOutPkts.begin(); it != mOutPkts.end(); ++it) - total += getRsItemSize(*it); - - return total ; -} - -int pqistreamer::locked_gatherStatistics(std::list& out_lst,std::list& in_lst) -{ - out_lst = mPreviousStatsChunk_Out ; - in_lst = mPreviousStatsChunk_In ; - - return 1 ; -} - -// this method is overloaded by pqiqosstreamer -void *pqistreamer::locked_pop_out_data(uint32_t /*max_slice_size*/, uint32_t &size, bool &starts, bool &ends, uint32_t &packet_id) -{ - size = 0 ; - starts = true ; - ends = true ; - packet_id = 0 ; - - void *res = NULL ; - - if (!mOutPkts.empty()) - { - res = *(mOutPkts.begin()); - mOutPkts.pop_front(); -#ifdef DEBUG_TRANSFERS - std::cerr << "pqistreamer::locked_pop_out_data() getting next pkt from mOutPkts queue"; - std::cerr << std::endl; -#endif - } - return res ; -} - diff --git a/libretroshare/src/pqi/pqistreamer.h b/libretroshare/src/pqi/pqistreamer.h deleted file mode 100644 index 0e7f6b815..000000000 --- a/libretroshare/src/pqi/pqistreamer.h +++ /dev/null @@ -1,190 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqistreamer.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_STREAMER_HEADER -#define MRK_PQI_STREAMER_HEADER - -#include // for uint32_t -#include "util/rstime.h" // for rstime_t -#include // for operator<<, basic_ostream, cerr, endl -#include // for list -#include // for map - -#include "pqi/pqi_base.h" // for BinInterface (ptr only), PQInterface -#include "retroshare/rsconfig.h" // for RSTrafficClue -#include "retroshare/rstypes.h" // for RsPeerId -#include "util/rsthreads.h" // for RsMutex - -struct RsItem; -class RsSerialiser; - -struct PartialPacketRecord -{ - void *mem ; - uint32_t size ; -}; - -/** - * @brief Fully implements the PQInterface and communicates with peer etc via - * the BinInterface. - * The interface does not handle connection, just communication. - * Possible BIN_FLAGS: BIN_FLAGS_NO_CLOSE | BIN_FLAGS_NO_DELETE - */ -class pqistreamer: public PQInterface -{ - public: - pqistreamer(RsSerialiser *rss, const RsPeerId& peerid, BinInterface *bio_in, int bio_flagsin); - virtual ~pqistreamer(); - - // PQInterface - virtual int SendItem(RsItem *item) - { - std::cerr << "Warning pqistreamer::sendItem(RsItem*) should not be called. Plz call SendItem(RsItem *,uint32_t& serialized_size) instead." << std::endl; - uint32_t serialized_size ; - return SendItem(item,serialized_size) ; - } - virtual int SendItem(RsItem *,uint32_t& serialized_size); - virtual RsItem *GetItem(); - virtual int status(); - - rstime_t getLastIncomingTS(); // Time of last data packet, for checking a connection is alive. - virtual void getRates(RsBwRates &rates); - virtual int getQueueSize(bool in); // extracting data. - virtual int getQueueSize_bytes(bool in); // size of incoming queue in bytes - virtual int gatherStatistics(std::list& outqueue_stats,std::list& inqueue_stats); // extracting data. - - // mutex protected versions of RateInterface calls. - virtual void setRate(bool b,float f) ; - virtual void setMaxRate(bool b,float f) ; - virtual void setMaxRate_locked(bool b,float f) ; - - virtual float getRate(bool b) ; - virtual float getMaxRate(bool b) ; - virtual float getMaxRate_locked(bool b); - - protected: - virtual int reset() ; - - int tick_bio(); - int tick_send(uint32_t timeout); - int tick_recv(uint32_t timeout); - - /* Implementation */ - - // These methods are redefined in pqiQoSstreamer - // - virtual void locked_storeInOutputQueue(void *ptr, int size, int priority) ; - virtual int locked_out_queue_size() const ; - virtual void locked_clear_out_queue() ; - virtual int locked_compute_out_pkt_size() const ; - virtual void *locked_pop_out_data(uint32_t max_slice_size,uint32_t& size,bool& starts,bool& ends,uint32_t& packet_id); - virtual int locked_gatherStatistics(std::list& outqueue_stats,std::list& inqueue_stats); // extracting data. - - void updateRates() ; - - protected: - RsMutex mStreamerMtx ; // Protects data, fns below, protected so pqiqos can use it too. - - // Binary Interface for IO, initialisated at startup. - BinInterface *mBio; - unsigned int mBio_flags; // BIN_FLAGS_NO_CLOSE | BIN_FLAGS_NO_DELETE - - private: - int queue_outpqi_locked(RsItem *i,uint32_t& serialized_size); - int handleincomingitem(RsItem *i, int len); - - // ticked regularly (manages out queues and sending - // via above interfaces. - virtual int handleoutgoing_locked(); - virtual int handleincoming(); - - // Bandwidth/Streaming Management. - float outTimeSlice_locked(); - - int outAllowedBytes_locked(); - void outSentBytes_locked(uint32_t ); - - int inAllowedBytes(); - void inReadBytes(uint32_t ); - - // cleans up everything that's pending / half finished. - void free_pend(); - - // RsSerialiser - determines which packets can be serialised. - RsSerialiser *mRsSerialiser; - - void *mPkt_wpending; // storage for pending packet to write. - uint32_t mPkt_wpending_size; // ... and its size. - - void allocate_rpend(); // use these two functions to allocate/free the buffer below - - int mPkt_rpend_size; // size of pkt_rpending. - void *mPkt_rpending; // storage for read in pending packets. - - enum {reading_state_packet_started=1, reading_state_initial=0 } ; - - int mReading_state ; - int mFailed_read_attempts ; - - // Temp Storage for transient data..... - std::list mOutPkts; // Cntrl / Search / Results queue - std::list mIncoming; - - uint32_t mIncomingSize; // size of mIncoming. To avoid calling linear cost std::list::size() - uint32_t mIncomingSize_bytes; // size of Incoming in btyes - - // data for network stats. - int mTotalRead; - int mTotalSent; - - // these are representative (but not exact) - int mCurrRead; - int mCurrSent; - - double mCurrReadTS; // TS from which these are measured. - double mCurrSentTS; - - double mAvgLastUpdate; // TS from which these are measured. - uint32_t mAvgReadCount; - uint32_t mAvgSentCount; - - double mAvgDtOut; // average time diff between 2 rounds of sending data - double mAvgDtIn; // average time diff between 2 rounds of receiving data - - rstime_t mLastIncomingTs; - - // traffic statistics - - std::list mPreviousStatsChunk_In ; - std::list mPreviousStatsChunk_Out ; - std::list mCurrentStatsChunk_In ; - std::list mCurrentStatsChunk_Out ; - rstime_t mStatisticsTimeStamp ; - - bool mAcceptsPacketSlicing ; - rstime_t mLastSentPacketSlicingProbe ; - void locked_addTrafficClue(const RsItem *pqi, uint32_t pktsize, std::list &lst); - RsItem *addPartialPacket(const void *block, uint32_t len, uint32_t slice_packet_id,bool packet_starting,bool packet_ending,uint32_t& total_len); - - std::map mPartialPackets ; -}; - -#endif //MRK_PQI_STREAMER_HEADER diff --git a/libretroshare/src/pqi/pqithreadstreamer.cc b/libretroshare/src/pqi/pqithreadstreamer.cc deleted file mode 100644 index 6745dc864..000000000 --- a/libretroshare/src/pqi/pqithreadstreamer.cc +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqithreadstreamer.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "util/rstime.h" -#include "pqi/pqithreadstreamer.h" -#include - -#define DEFAULT_STREAMER_TIMEOUT 10000 // 10 ms -#define DEFAULT_STREAMER_SLEEP 30000 // 30 ms -#define DEFAULT_STREAMER_IDLE_SLEEP 1000000 // 1 sec - -// #define PQISTREAMER_DEBUG - -pqithreadstreamer::pqithreadstreamer(PQInterface *parent, RsSerialiser *rss, const RsPeerId& id, BinInterface *bio_in, int bio_flags_in) -:pqistreamer(rss, id, bio_in, bio_flags_in), mParent(parent), mTimeout(0), mThreadMutex("pqithreadstreamer") -{ - mTimeout = DEFAULT_STREAMER_TIMEOUT; - mSleepPeriod = DEFAULT_STREAMER_SLEEP; -} - -bool pqithreadstreamer::RecvItem(RsItem *item) -{ - return mParent->RecvItem(item); -} - -int pqithreadstreamer::tick() -{ - // pqithreadstreamer mutex lock is not needed here - // we will only check if the connection is active, and if not we will try to establish it - tick_bio(); - - return 0; -} - -void pqithreadstreamer::threadTick() -{ - uint32_t recv_timeout = 0; - uint32_t sleep_period = 0; - bool isactive = false; - - { - RsStackMutex stack(mStreamerMtx); - recv_timeout = mTimeout; - sleep_period = mSleepPeriod; - isactive = mBio->isactive(); - } - - // update the connection rates - updateRates() ; - - // if the connection est not active, long sleep then return - if (!isactive) - { - rstime::rs_usleep(DEFAULT_STREAMER_IDLE_SLEEP); - return ; - } - - // fill incoming queue with items from SSL - { - RsStackMutex stack(mThreadMutex); - tick_recv(recv_timeout); - } - - // move items to appropriate service queue or shortcut to fast service - RsItem *incoming = NULL; - while((incoming = GetItem())) - { - RecvItem(incoming); - } - - // parse the outgoing queue and send items to SSL - { - RsStackMutex stack(mThreadMutex); - tick_send(0); - } - - // sleep - if (sleep_period) - { - rstime::rs_usleep(sleep_period); - } -} - diff --git a/libretroshare/src/pqi/pqithreadstreamer.h b/libretroshare/src/pqi/pqithreadstreamer.h deleted file mode 100644 index 7ba1690c8..000000000 --- a/libretroshare/src/pqi/pqithreadstreamer.h +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqithreadstreamer.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_THREAD_STREAMER_HEADER -#define MRK_PQI_THREAD_STREAMER_HEADER - -#include "pqi/pqistreamer.h" -#include "util/rsthreads.h" - -class pqithreadstreamer: public pqistreamer, public RsTickingThread -{ -public: - pqithreadstreamer(PQInterface *parent, RsSerialiser *rss, const RsPeerId& peerid, BinInterface *bio_in, int bio_flagsin); - - // from pqistreamer - virtual bool RecvItem(RsItem *item); - virtual int tick(); - -protected: - void threadTick() override; /// @see RsTickingThread - - PQInterface *mParent; - uint32_t mTimeout; - uint32_t mSleepPeriod; - -private: - /* thread variables */ - RsMutex mThreadMutex; -}; - -#endif //MRK_PQI_THREAD_STREAMER_HEADER diff --git a/libretroshare/src/pqi/sslfns.cc b/libretroshare/src/pqi/sslfns.cc deleted file mode 100644 index cb799ed86..000000000 --- a/libretroshare/src/pqi/sslfns.cc +++ /dev/null @@ -1,886 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: sslfns.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -/* Functions in this file are SSL only, - * and have no dependence on SSLRoot() etc. - * might need SSL_Init() to be called - thats it! - */ - -/******************** notify of new Cert **************************/ - -#include "pqi/sslfns.h" -#include "pqi/pqi_base.h" -#include "util/rsdir.h" -#include "util/rsstring.h" -#include "pqi/authssl.h" - -#include -#include -#include -#include - -#include -#include -#include - -/**** - * #define AUTHSSL_DEBUG 1 - ***/ - -/********************************************************************************/ - -#if defined(SSLFNS_ADD_CIPHER_CTX_RAND_KEY) - -int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key) -{ - //if (ctx->cipher->flags & EVP_CIPH_RAND_KEY) - // return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key); - if (RAND_bytes(key, ctx->key_len) <= 0) - return 0; - return 1; -} - -#endif - -/********************************************************************************/ -/********************************************************************************/ - -X509_REQ *GenerateX509Req( - std::string pkey_file, std::string passwd, - std::string name, std::string email, std::string org, - std::string loc, std::string state, std::string country, - int nbits_in, std::string &errString) -{ - /* generate request */ - X509_REQ *req=X509_REQ_new(); - - // setup output. - BIO *bio_out = BIO_new(BIO_s_file()); - BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); - - EVP_PKEY *pkey = NULL; - X509_NAME *x509_name = NULL ; - RSA *rsa = NULL ; - - try - { - // first generate a key.... - if ((pkey=EVP_PKEY_new()) == NULL) - { - fprintf(stderr,"GenerateX509Req: Couldn't Create Key\n"); - throw std::runtime_error("Couldn't Create Key") ; - } - - int nbits = 2048; - unsigned long e = 0x10001; - - if ((nbits_in >= 512) && (nbits_in <= 4096)) - { - nbits = nbits_in; - } - else - { - fprintf(stderr,"GenerateX509Req: strange num of nbits: %d\n", nbits_in); - fprintf(stderr,"GenerateX509Req: reverting to %d\n", nbits); - } - - - rsa = RSA_new(); - if ((rsa == NULL) || !EVP_PKEY_assign_RSA(pkey, rsa)) - throw std::runtime_error("Couldn't generate RSA Key"); - - BIGNUM *ebn = BN_new(); - BN_set_word(ebn, e); - RSA_generate_key_ex(rsa, nbits, ebn, NULL); - - // open the file. - FILE *out; - if (NULL == (out = RsDirUtil::rs_fopen(pkey_file.c_str(), "w"))) - throw std::runtime_error("Couldn't Create Key File \"" + pkey_file + "\""); - - const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); - - if (!PEM_write_PrivateKey(out,pkey,cipher, NULL,0,NULL,(void *) passwd.c_str())) - { - fclose(out) ; - throw std::runtime_error("Couldn't Save Private Key to file \""+pkey_file+"\""); - } - - fclose(out); - - // We have now created a private key.... - std::cerr << "GenerateX509Req() Saved Private Key to file \"" << pkey_file << "\"" << std::endl; - - /********** Test Loading the private Key.... ************/ - FILE *tst_in = NULL; - EVP_PKEY *tst_pkey = NULL; - - if (NULL == (tst_in = RsDirUtil::rs_fopen(pkey_file.c_str(), "rb"))) - throw std::runtime_error("GenerateX509Req() Couldn't Open Private Key file \""+pkey_file+"\"") ; - - if (NULL == (tst_pkey = PEM_read_PrivateKey(tst_in,NULL,NULL,(void *) passwd.c_str()))) - { - fclose(tst_in); - throw std::runtime_error("GenerateX509Req() Couldn't read Private Key file \""+pkey_file+"\"") ; - } - - fclose(tst_in); - EVP_PKEY_free(tst_pkey); - - /* Fill in details: fields. - req->req_info; - req->req_info->enc; - req->req_info->version; - req->req_info->subject; - req->req_info->pubkey; - ****************************/ - - long version = 0x00; - unsigned long chtype = MBSTRING_UTF8; - x509_name = X509_NAME_new(); - - // fill in the request. - - /**** X509_REQ -> Version ********************************/ - if(!X509_REQ_set_version(req,version)) /* version 1 */ - throw std::runtime_error("GenerateX509Req(): Couldn't Set SSL certificate Version!"); - - /**** X509_REQ -> Version ********************************/ - /**** X509_REQ -> Key ********************************/ - - if (!X509_REQ_set_pubkey(req,pkey)) - throw std::runtime_error("GenerateX509Req(): Couldn't Set SSL certificate PUBKEY!"); - - /**** SUBJECT ********************************/ - // create the name. - - // fields to add. - // commonName CN - // emailAddress (none) - // organizationName O - // localityName L - // stateOrProvinceName ST - // countryName C - - if (0 == strlen(name.c_str())) - throw std::runtime_error("No name! Aborting.") ; - - X509_NAME_add_entry_by_txt(x509_name, "CN", chtype, (unsigned char *) name.c_str(), -1, -1, 0); - - if (0 < strlen(email.c_str())) - X509_NAME_add_entry_by_NID(x509_name, 48, 0, (unsigned char *) email.c_str(), -1, -1, 0); - - if (0 < strlen(org.c_str())) - X509_NAME_add_entry_by_txt(x509_name, "O", chtype, (unsigned char *) org.c_str(), -1, -1, 0); - - if (0 < strlen(loc.c_str())) - X509_NAME_add_entry_by_txt(x509_name, "L", chtype, (unsigned char *) loc.c_str(), -1, -1, 0); - - if (0 < strlen(state.c_str())) - X509_NAME_add_entry_by_txt(x509_name, "ST", chtype, (unsigned char *) state.c_str(), -1, -1, 0); - - if (0 < strlen(country.c_str())) - X509_NAME_add_entry_by_txt(x509_name, "C", chtype, (unsigned char *) country.c_str(), -1, -1, 0); - - if (!X509_REQ_set_subject_name(req,x509_name)) - throw std::runtime_error("GenerateX509Req() Couldn't Set Name to Request!"); - - X509_NAME_free(x509_name); - - /**** SUBJECT ********************************/ - - if (!X509_REQ_sign(req,pkey,EVP_sha1())) - throw std::runtime_error("GenerateX509Req() Failed to sign REQ"); - - errString = "No Error"; - - return req; - } - catch(std::exception& e) - { - std::cerr << "(EE) Key creation failed: " << e.what() << std::endl; - errString = e.what() ; - req = NULL ; - } - - - if(rsa) - RSA_free(rsa); - - if(x509_name) - X509_NAME_free(x509_name); - - if(bio_out) - BIO_free_all(bio_out) ; - - if(pkey) - EVP_PKEY_free(pkey); - - return req ; -} - -#define SERIAL_RAND_BITS 64 - -#ifdef UNUSED_CODE -X509 *SignX509Certificate(X509_NAME *issuer, EVP_PKEY *privkey, X509_REQ *req, long days) -{ - const EVP_MD *digest = EVP_sha1(); - ASN1_INTEGER *serial = ASN1_INTEGER_new(); - EVP_PKEY *tmppkey; - X509 *x509 = X509_new(); - if (x509 == NULL) - return NULL; - - BIGNUM *btmp = BN_new(); - if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," pseudo_rand\n"); - - return NULL; - } - if (!BN_to_ASN1_INTEGER(btmp, serial)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," int\n"); - - return NULL; - } - BN_free(btmp); - - if (!X509_set_serialNumber(x509, serial)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," serialNumber\n"); - - return NULL; - } - ASN1_INTEGER_free(serial); - - if (!X509_set_issuer_name(x509, issuer)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," issuer\n"); - - return NULL; - } - - if (!X509_gmtime_adj(x509->cert_info->validity->notBefore, 0)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," notBefore\n"); - - return NULL; - } - - //x509->cert_info->validity->notAfter - //if (!X509_gmtime_adj(X509_get_notAfter(x509), (long)60*60*24*days)) - if (!X509_gmtime_adj(x509->cert_info->validity->notAfter, (long)60*60*24*days)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," notAfter\n"); - - return NULL; - } - - if (!X509_set_subject_name(x509, X509_REQ_get_subject_name(req))) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," subject_name\n"); - - return NULL; - } - - - tmppkey = X509_REQ_get_pubkey(req); - if (!tmppkey || !X509_set_pubkey(x509,tmppkey)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," pubkey\n"); - - return NULL; - } - - - /* Cleanup Algorithm part */ - - X509_ALGOR *algor1 = x509->cert_info->signature; - X509_ALGOR *algor2 = x509->sig_alg; - - X509_ALGOR *a; - - a = algor1; - ASN1_TYPE_free(a->parameter); - a->parameter=ASN1_TYPE_new(); - a->parameter->type=V_ASN1_NULL; - - ASN1_OBJECT_free(a->algorithm); - a->algorithm=OBJ_nid2obj(digest->pkey_type); - - a = algor2; - ASN1_TYPE_free(a->parameter); - a->parameter=ASN1_TYPE_new(); - a->parameter->type=V_ASN1_NULL; - - ASN1_OBJECT_free(a->algorithm); - a->algorithm=OBJ_nid2obj(digest->pkey_type); - - - if (!X509_sign(x509,privkey,digest)) - { - long e = ERR_get_error(); - - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," signing Error: %ld\n", e); - - fprintf(stderr,"ERR: %s, %s, %s\n", - ERR_lib_error_string(e), - ERR_func_error_string(e), - ERR_reason_error_string(e)); - - int inl=i2d_X509(x509,NULL); - int outl=EVP_PKEY_size(privkey); - fprintf(stderr,"Size Check: inl: %d, outl: %d\n", inl, outl); - - return NULL; - } - - fprintf(stderr,"SignX509Certificate() Success\n"); - - return x509; -} -#endif - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - - - /* Sign / Encrypt / Verify Data */ -bool SSL_SignDataBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int *signlen, EVP_PKEY *pkey) -{ - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - unsigned int req_signlen = EVP_PKEY_size(pkey); - if (req_signlen > *signlen) - { - /* not enough space */ - std::cerr << "SignDataBin() Not Enough Sign SpacegnInit Failure!" << std::endl; - return false; - } - - if (0 == EVP_SignInit(mdctx, EVP_sha1())) - { - std::cerr << "EVP_SignInit Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - if (0 == EVP_SignUpdate(mdctx, data, len)) - { - std::cerr << "EVP_SignUpdate Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - if (0 == EVP_SignFinal(mdctx, sign, signlen, pkey)) - { - std::cerr << "EVP_SignFinal Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - EVP_MD_CTX_destroy(mdctx); - return true; -} - -bool SSL_VerifySignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen, X509 *cert) -{ - - /* cert->cert_info->key->pkey is NULL.... - * but is instantiated when we call X509_get_pubkey() - */ - - EVP_PKEY *peerkey = X509_get_pubkey(cert); - - /* must free this key afterwards */ - bool ret = SSL_VerifySignBin(data, len, sign, signlen, peerkey); - - EVP_PKEY_free(peerkey); - - return ret; -} - -/* Correct form of this function ... Internal for AuthSSL's usage - */ - -bool SSL_VerifySignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen, EVP_PKEY *peerkey) -{ - if(peerkey == NULL) - { - std::cerr << "VerifySignBin: no public key available !!" << std::endl ; - return false ; - } - - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - if (0 == EVP_VerifyInit(mdctx, EVP_sha1())) - { - std::cerr << "EVP_VerifyInit Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - if (0 == EVP_VerifyUpdate(mdctx, data, len)) - { - std::cerr << "EVP_VerifyUpdate Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - if(signlen == 0 || sign == NULL) - { - std::cerr << "AuthSSL::VerifySignBin: signlen=" << signlen << ", sign=" << (void*)sign << "!!" << std::endl ; - EVP_MD_CTX_destroy(mdctx); - return false ; - } - - if (0 == EVP_VerifyFinal(mdctx, sign, signlen, peerkey)) - { - std::cerr << "EVP_VerifyFinal Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - EVP_MD_CTX_destroy(mdctx); - return true; -} - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - -X509 *loadX509FromPEM(std::string pem) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "loadX509FromPEM()"; - std::cerr << std::endl; -#endif - - /* Put the data into a mem BIO */ - char *certstr = strdup(pem.c_str()); - - BIO *bp = BIO_new_mem_buf(certstr, -1); - - X509 *pc = PEM_read_bio_X509(bp, NULL, NULL, NULL); - - BIO_free(bp); - free(certstr); - - return pc; -} - -std::string saveX509ToPEM(X509* x509) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "saveX509ToPEM() " << std::endl; -#endif - - /* get the cert first */ - std::string certstr; - BIO *bp = BIO_new(BIO_s_mem()); - - PEM_write_bio_X509(bp, x509); - - /* translate the bp data to a string */ - char *data; - int len = BIO_get_mem_data(bp, &data); - for(int i = 0; i < len; i++) - { - certstr += data[i]; - } - - BIO_free(bp); - - return certstr; -} - - -X509 *loadX509FromDER(const uint8_t *ptr, uint32_t len) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::LoadX509FromDER()"; - std::cerr << std::endl; -#endif - - X509 *tmp = NULL; -#ifdef __APPLE__ - // This depends on which version you are compiling for... OSX10.5 doesn't have consts (old OpenSSL!) - // With the Advent of Openpgpsdk, we are forced to move to OSX10.6 for a newer OpenSSL (probably a good thing). - // So we can change this around. - //unsigned char **certptr = (unsigned char **) &ptr; - const unsigned char **certptr = (const unsigned char **) &ptr; -#else - const unsigned char **certptr = (const unsigned char **) &ptr; -#endif - - X509 *x509 = d2i_X509(&tmp, certptr, len); - - return x509; -} - -bool saveX509ToDER(X509 *x509, uint8_t **ptr, uint32_t *len) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::saveX509ToDER()"; - std::cerr << std::endl; -#endif - - int certlen = i2d_X509(x509, (unsigned char **) ptr); - if (certlen > 0) - { - *len = certlen; - return true; - } - else - { - *len = 0; - return false; - } - return false; -} - - -bool getX509id(X509 *x509, RsPeerId& xid) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::getX509id()"; - std::cerr << std::endl; -#endif - - xid.clear() ; - if (x509 == NULL) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::getX509id() NULL pointer"; - std::cerr << std::endl; -#endif - return false; - } - - // get the signature from the cert, and copy to the array. -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - ASN1_BIT_STRING *signature = x509->signature; -#else - const ASN1_BIT_STRING *signature = NULL ; - const X509_ALGOR *algor ; - - X509_get0_signature(&signature,&algor,x509); -#endif - - uint32_t version_number = getX509RetroshareCertificateVersion(x509) ; - - if(version_number >= RS_CERTIFICATE_VERSION_NUMBER_06_0001) - { - // What: Computes the node id by performing a sha256 hash of the certificate's PGP signature, instead of simply picking up the last 20 bytes of it. - // - // Why: There is no real risk in forging a certificate with the same ID as the authentication is performed over the PGP signature of the certificate - // which hashes the full SSL certificate (i.e. the full serialized CERT_INFO structure). However the possibility to - // create two certificates with the same IDs is a problem, as it can be used to cause disturbance in the software. - // - // Backward compat: makes connexions impossible with non patched peers, probably because the SSL id that is computed is not the same on both side, - // and in particular unpatched peers see a cerficate with ID different (because computed with the old method) than the ID that was - // submitted when making friends. - // - // Note: the advantage of basing the ID on the signature rather than the public key is not very clear, given that the signature is based on a hash - // of the public key (and the rest of the certificate info). - // - - if(RsPeerId::SIZE_IN_BYTES > Sha256CheckSum::SIZE_IN_BYTES) - return false ; - - xid = RsPeerId(RsDirUtil::sha256sum(ASN1_STRING_data(const_cast(signature)),ASN1_STRING_length(signature)).toByteArray()) ; - } - else - { - int signlen = ASN1_STRING_length(signature); - if (signlen < CERTSIGNLEN) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::getX509id() ERROR: Short Signature"; - std::cerr << std::endl; -#endif - return false; - } - - // else copy in the first CERTSIGNLEN. - unsigned char *signdata = ASN1_STRING_data(const_cast(signature)); - - /* switched to the other end of the signature. for - * more randomness - */ - -#warning csoler 2017-02-19: This is cryptographically horrible. We should hash the entire signature here! - - xid = RsPeerId(&signdata[signlen - CERTSIGNLEN]) ; - } - - return true; -} - - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - -int pem_passwd_cb(char *buf, int size, int rwflag, void *password) -{ - /* remove unused parameter warnings */ - (void) rwflag; - - strncpy(buf, (char *)(password), size); - buf[size - 1] = '\0'; - return(strlen(buf)); -} - -uint64_t getX509SerialNumber(X509 *cert) -{ - ASN1_INTEGER *serial = X509_get_serialNumber(cert); - - BIGNUM *btmp = ASN1_INTEGER_to_BN(serial, NULL); - - uint64_t res = BN_get_word(btmp) ; - BN_free(btmp); - - return res ; -} - -uint32_t getX509RetroshareCertificateVersion(X509 *cert) -{ - // Because the serial number was totally random before being used to identity the handshake protocol, we check if we see known version strings. If not, - // we assume v0.6-0000 - // - // We compare the uint32_t into a uint64_t on purpose,to make sure that the highest bits are 0 and not random. - - switch(getX509SerialNumber(cert)) - { - case uint64_t(RS_CERTIFICATE_VERSION_NUMBER_06_0000): return RS_CERTIFICATE_VERSION_NUMBER_06_0000 ; - case uint64_t(RS_CERTIFICATE_VERSION_NUMBER_06_0001): return RS_CERTIFICATE_VERSION_NUMBER_06_0001 ; - case uint64_t(RS_CERTIFICATE_VERSION_NUMBER_07_0001): return RS_CERTIFICATE_VERSION_NUMBER_07_0001 ; - default: - return RS_CERTIFICATE_VERSION_NUMBER_06_0000; - } -} - -std::string getX509NameString(X509_NAME *name) -{ - std::string namestr; - for(int i = 0; i < X509_NAME_entry_count(name); i++) - { - X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); - ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); - ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); - - namestr += "\t"; - namestr += OBJ_nid2ln(OBJ_obj2nid(entry_obj)); - namestr += " : "; - - //namestr += entry_obj -> flags; - //namestr += entry_data -> length; - //namestr += entry_data -> type; - - //namestr += entry_data -> flags; - //entry -> set; - - if (entry_data -> data != NULL) - { - namestr += (char *) entry_data -> data; - } - else - { - namestr += "NULL"; - } - - if (i + 1 < X509_NAME_entry_count(name)) - { - namestr += "\n"; - } - } - return namestr; -} - -std::string getX509CNString(X509_NAME *name) -{ - std::string namestr; - for(int i = 0; i < X509_NAME_entry_count(name); i++) - { - X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); - ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); - ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); - - if (0 == strncmp("CN", OBJ_nid2sn(OBJ_obj2nid(entry_obj)), 2)) - { - if (entry_data -> data != NULL) - { - // do we need to convert ASN1_STRING to utf8 (ASN1_STRING_to_UTF8)? - namestr = (char *) entry_data->data; - } - else - { - namestr = "Unknown"; - } - break; - } - } - return namestr; -} - -std::string getX509TypeString(X509_NAME *name, const char *type, int len) -{ - std::string namestr; - for(int i = 0; i < X509_NAME_entry_count(name); i++) - { - X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); - ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); - ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); - - if (0 == strncmp(type, OBJ_nid2sn(OBJ_obj2nid(entry_obj)), len)) - { - if (entry_data -> data != NULL) - { - // do we need to convert ASN1_STRING to utf8 (ASN1_STRING_to_UTF8)? - namestr = (char *) entry_data -> data; - } - else - { - namestr = "Unknown"; - } - break; - } - } - return namestr; -} - -std::string getX509LocString(X509_NAME *name) -{ - return getX509TypeString(name, "L", 2); -} - -std::string getX509OrgString(X509_NAME *name) -{ - return getX509TypeString(name, "O", 2); -} - -std::string getX509CountryString(X509_NAME *name) -{ - return getX509TypeString(name, "C", 2); -} - - -#ifdef AUTHSSL_DEBUG -std::string getX509Info(X509 *cert) -{ - std::string out = "X509 Certificate:\n"; - - long l; - l=X509_get_version(cert); - rs_sprintf_append(out, " Version: %ld(0x%ld)\n", l+1, l); - out += " Subject: \n"; - out += " " + getX509NameString(cert->cert_info->subject) + "\n\n"; - out += " Signatures:\n"; - return out; -} -#endif - -/********** SSL ERROR STUFF ******************************************/ - -int printSSLError( - SSL*, int retval, int err, unsigned long err2, std::string& out ) -{ - std::string reason; - - std::string mainreason = std::string("UNKNOWN ERROR CODE"); - if (err == SSL_ERROR_NONE) - { - mainreason = std::string("SSL_ERROR_NONE"); - } - else if (err == SSL_ERROR_ZERO_RETURN) - { - mainreason = std::string("SSL_ERROR_ZERO_RETURN"); - } - else if (err == SSL_ERROR_WANT_READ) - { - mainreason = std::string("SSL_ERROR_WANT_READ"); - } - else if (err == SSL_ERROR_WANT_WRITE) - { - mainreason = std::string("SSL_ERROR_WANT_WRITE"); - } - else if (err == SSL_ERROR_WANT_CONNECT) - { - mainreason = std::string("SSL_ERROR_WANT_CONNECT"); - } - else if (err == SSL_ERROR_WANT_ACCEPT) - { - mainreason = std::string("SSL_ERROR_WANT_ACCEPT"); - } - else if (err == SSL_ERROR_WANT_X509_LOOKUP) - { - mainreason = std::string("SSL_ERROR_WANT_X509_LOOKUP"); - } - else if (err == SSL_ERROR_SYSCALL) - { - mainreason = std::string("SSL_ERROR_SYSCALL"); - } - else if (err == SSL_ERROR_SSL) - { - mainreason = std::string("SSL_ERROR_SSL"); - } - rs_sprintf_append( out, - "RetVal(%d) -> SSL Error: %s\n\t + ERR Error: %s\n", - retval, mainreason.c_str(), - ERR_error_string(err2, nullptr) ); - return 1; -} - - -std::string sslErrorToString(int retval, int err, unsigned long err2) -{ - std::string ret; - // When printSSLError will be removed it's code will be moved here - printSSLError(nullptr, retval, err, err2, ret); - return ret; -} diff --git a/libretroshare/src/pqi/sslfns.h b/libretroshare/src/pqi/sslfns.h deleted file mode 100644 index c22076c51..000000000 --- a/libretroshare/src/pqi/sslfns.h +++ /dev/null @@ -1,135 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: sslfns.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/* Functions in this file are SSL only, - * and have no dependence on SSLRoot() etc. - * might need SSL_Init() to be called - thats it! - */ - -/******************** notify of new Cert **************************/ - -#include -#include - -#include -#include - -#include "util/rsdeprecate.h" -#include "retroshare/rstypes.h" - - -/**** - * #define AUTHSSL_DEBUG 1 - ***/ - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - - -// IF we are compiling against ssl0.9.7 - these functions don't exist. - -#if (OPENSSL_VERSION_NUMBER & 0xfffff000) < 0x00908000 - #define SSLFNS_ADD_CIPHER_CTX_RAND_KEY 1 -#endif - -#if defined(SSLFNS_ADD_CIPHER_CTX_RAND_KEY) - -int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key); - -#endif - -// Certificates serial number is used to store the protocol version for the handshake. (*) means current version. -// -// 06_0000: < Nov.2017. -// * 06_0001: > Nov 2017. SSL id is computed by hashing the entire signature of the cert instead of simply picking up the last bytes. -// 07_0001: Signatures are performed using SHA256+RSA instead of SHA1+RSA - -static const uint32_t RS_CERTIFICATE_VERSION_NUMBER_06_0000 = 0x00060000 ; // means version RS-0.6, certificate version 0. Default version before patch. -static const uint32_t RS_CERTIFICATE_VERSION_NUMBER_06_0001 = 0x00060001 ; // means version RS-0.6, certificate version 1. -static const uint32_t RS_CERTIFICATE_VERSION_NUMBER_07_0001 = 0x00070001 ; // means version RS-0.7, certificate version 1. - -X509_REQ *GenerateX509Req( - std::string pkey_file, std::string passwd, - std::string name, std::string email, std::string org, - std::string loc, std::string state, std::string country, - int nbits_in, std::string &errString); - -X509 *SignX509Certificate(X509_NAME *issuer, EVP_PKEY *privkey, X509_REQ *req, long days); - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - - - /* Sign / Encrypt / Verify Data */ -bool SSL_SignDataBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int *signlen, EVP_PKEY *pkey); - -bool SSL_VerifySignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen, X509 *cert); - -bool SSL_VerifySignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen, EVP_PKEY *peerkey); - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - -X509 *loadX509FromPEM(std::string pem); -std::string saveX509ToPEM(X509* x509); -X509 *loadX509FromDER(const uint8_t *ptr, uint32_t len); -bool saveX509ToDER(X509 *x509, uint8_t **ptr, uint32_t *len); - -bool getX509id(X509 *x509, RsPeerId &xid); - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - -int pem_passwd_cb(char *buf, int size, int rwflag, void *password); - -std::string getX509NameString(X509_NAME *name); -std::string getX509CNString(X509_NAME *name); -std::string getX509TypeString(X509_NAME *name, const char *type, int len); -std::string getX509LocString(X509_NAME *name); -std::string getX509OrgString(X509_NAME *name); -std::string getX509CountryString(X509_NAME *name); -std::string getX509Info(X509 *cert); - -uint64_t getX509SerialNumber(X509 *cert); -uint32_t getX509RetroshareCertificateVersion(X509 *cert) ; - -/********** SSL ERROR STUFF ******************************************/ - -RS_DEPRECATED_FOR(sslErrorToString) -int printSSLError( - SSL* unused, int retval, int err, unsigned long err2, std::string& out); - -std::string sslErrorToString(int retval, int err, unsigned long err2); diff --git a/libretroshare/src/retroshare/rsbanlist.h b/libretroshare/src/retroshare/rsbanlist.h deleted file mode 100644 index c46ea0203..000000000 --- a/libretroshare/src/retroshare/rsbanlist.h +++ /dev/null @@ -1,157 +0,0 @@ -/******************************************************************************* - * IPv4 address filtering interface * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include "util/rsnet.h" -#include "util/rstime.h" -#include "util/rsmemory.h" - -class RsBanList; - -/** - * Pointer to global instance of RsBanList service implementation - * @jsonapi{development} - */ -extern RsBanList* rsBanList; - -// TODO: use enum class instead of defines -#define RSBANLIST_ORIGIN_UNKNOWN 0 -#define RSBANLIST_ORIGIN_SELF 1 -#define RSBANLIST_ORIGIN_FRIEND 2 -#define RSBANLIST_ORIGIN_FOF 3 - -#define RSBANLIST_REASON_UNKNOWN 0 -#define RSBANLIST_REASON_USER 1 -#define RSBANLIST_REASON_DHT 2 -#define RSBANLIST_REASON_AUTO_RANGE 3 - -// These are flags. Can be combined. - -#define RSBANLIST_CHECKING_FLAGS_NONE 0x00 -#define RSBANLIST_CHECKING_FLAGS_BLACKLIST 0x01 -#define RSBANLIST_CHECKING_FLAGS_WHITELIST 0x02 - -// These are not flags. Cannot be combined. Used to give the reson for acceptance/denial of connections. - -#define RSBANLIST_CHECK_RESULT_UNKNOWN 0x00 -#define RSBANLIST_CHECK_RESULT_NOCHECK 0x01 -#define RSBANLIST_CHECK_RESULT_BLACKLISTED 0x02 -#define RSBANLIST_CHECK_RESULT_NOT_WHITELISTED 0x03 -#define RSBANLIST_CHECK_RESULT_ACCEPTED 0x04 - -#define RSBANLIST_TYPE_PEERLIST 1 -#define RSBANLIST_TYPE_BLACKLIST 2 -#define RSBANLIST_TYPE_WHITELIST 3 - -class RsTlvBanListEntry; - -class BanListPeer -{ -public: - BanListPeer() ; - - void toRsTlvBanListEntry(RsTlvBanListEntry& e) const ; - void fromRsTlvBanListEntry(const RsTlvBanListEntry& e) ; - - struct sockaddr_storage addr; - uint8_t masked_bytes ; // 0 = []/32. 1=[]/24, 2=[]/16 - uint32_t reason; // User, DHT - uint32_t level; // LOCAL, FRIEND, FoF. - bool state ; // true=>active, false=>just stored but inactive - int connect_attempts ; // recorded by the BanList service - rstime_t mTs; - std::string comment ; // -}; - -class RsBanList -{ -public: - /** - * @brief Enable or disable IP filtering service - * @jsonapi{development} - * @param[in] enable pass true to enable, false to disable - */ - virtual void enableIPFiltering(bool enable) = 0; - - /** - * @brief Get ip filtering service status - * @jsonapi{development} - * @return true if enabled, false if disabled - */ - virtual bool ipFilteringEnabled() = 0; - - /** - * @brief addIpRange - * @param addr full IPv4 address. Port is ignored. - * @param masked_bytes 0=full IP, 1="/24", 2="/16" - * @param list_type RSBANLIST_TYPE_WHITELIST or RSBANLIST_TYPE_BLACKLIST - * @param comment anything, user-based - * @return - */ - virtual bool addIpRange( - const sockaddr_storage& addr, int masked_bytes, uint32_t list_type, - const std::string& comment ) = 0; - - /** - * @brief removeIpRange - * @param addr full IPv4 address. Port is ignored. - * @param masked_bytes 0=full IP, 1="/24", 2="/16" - * @param list_type RSBANLIST_TYPE_WHITELIST or RSBANLIST_TYPE_BLACKLIST - * @return - */ - virtual bool removeIpRange( - const sockaddr_storage& addr, int masked_bytes, uint32_t list_type - ) = 0; - - /** - * @brief isAddressAccepted - * @param addr full IPv4 address. Port is ignored. - * @param checking_flags any combination of - * RSBANLIST_CHECKING_FLAGS_BLACKLIST and - * RSBANLIST_CHECKING_FLAGS_WHITELIST - * @param check_result returned result of the check in - * RSBANLIST_CHECK_RESULT_* - * @return true if address is accepted, false false if address is rejected. - */ - virtual bool isAddressAccepted( - const sockaddr_storage& addr, uint32_t checking_flags, - uint32_t& check_result = RS_DEFAULT_STORAGE_PARAM(uint32_t) ) = 0; - - virtual void getBannedIps(std::list& list) = 0; - virtual void getWhiteListedIps(std::list& list) = 0; - - virtual bool autoRangeEnabled() = 0; - virtual void enableAutoRange(bool b) = 0; - - virtual int autoRangeLimit() = 0; - virtual void setAutoRangeLimit(int n) = 0; - - virtual void enableIPsFromFriends(bool b) = 0; - virtual bool IPsFromFriendsEnabled() = 0; - - virtual void enableIPsFromDHT(bool b) = 0; - virtual bool iPsFromDHTEnabled() = 0; - - virtual ~RsBanList(); -}; diff --git a/libretroshare/src/retroshare/rsbroadcastdiscovery.h b/libretroshare/src/retroshare/rsbroadcastdiscovery.h deleted file mode 100644 index 92b0e5b0e..000000000 --- a/libretroshare/src/retroshare/rsbroadcastdiscovery.h +++ /dev/null @@ -1,160 +0,0 @@ -/******************************************************************************* - * RetroShare Broadcast Domain Discovery * - * * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rsids.h" -#include "retroshare/rstypes.h" -#include "serialiser/rsserializable.h" -#include "util/rstime.h" -#include "util/rsurl.h" -#include "util/rsmemory.h" -#include "retroshare/rsevents.h" - -class RsBroadcastDiscovery; - -/** - * Pointer to global instance of RsBroadcastDiscovery service implementation - * @jsonapi{development} - * - * TODO: this should become std::weak_ptr once we have a reasonable services - * management. - */ -extern RsBroadcastDiscovery* rsBroadcastDiscovery; - - -struct RsBroadcastDiscoveryResult : RsSerializable -{ - RsPgpFingerprint mPgpFingerprint; - RsPeerId mSslId; - std::string mProfileName; - RsUrl mLocator; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(mPgpFingerprint); - RS_SERIAL_PROCESS(mSslId); - RS_SERIAL_PROCESS(mProfileName); - RS_SERIAL_PROCESS(mLocator); - } - - RsBroadcastDiscoveryResult() = default; - RsBroadcastDiscoveryResult (const RsBroadcastDiscoveryResult&) = default; - ~RsBroadcastDiscoveryResult() override; -}; - - -/** - * @brief Event emitted when a non friend new peer is found in the local network - * @see RsEvents - */ -enum class RsBroadcastDiscoveryEventType: uint32_t { - UNKNOWN = 0x00, - PEER_FOUND = 0x01 -}; - -struct RsBroadcastDiscoveryEvent : RsEvent -{ - RsBroadcastDiscoveryEvent() - : RsEvent(RsEventType::BROADCAST_DISCOVERY), - mDiscoveryEventType(RsBroadcastDiscoveryEventType::UNKNOWN) - {} - - virtual ~RsBroadcastDiscoveryEvent() override = default; - - RsBroadcastDiscoveryEventType mDiscoveryEventType; - RsBroadcastDiscoveryResult mData; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - - RS_SERIAL_PROCESS(mDiscoveryEventType); - RS_SERIAL_PROCESS(mData); - } -}; - - -/** - * Announce own RetroShare instace and look friends and peers in own broadcast - * domain (aka LAN). - * Emit event @see RsBroadcastDiscoveryPeerFoundEvent when a new peer (not - * friend yet) is found. - */ -class RsBroadcastDiscovery -{ -public: - /** - * @brief Get potential peers that have been discovered up until now - * @jsonapi{development} - * @return vector containing discovered peers, may be empty. - */ - virtual std::vector getDiscoveredPeers() = 0; - - /** - * @brief Check if multicast listening is enabled - * @jsonapi{development} - * On some platforms such as Android multicast listening, which is needed - * for broadcast discovery, is not enabled by default at WiFi driver level - * @see enableMulticastListening, so this method check if it is enabled. - * On platforms that are not expected to have such a limitation this method - * always return true. - * @return true if enabled, false otherwise. - */ - virtual bool isMulticastListeningEnabled() = 0; - - /** - * @brief On platforms that need it enable low level multicast listening - * @jsonapi{development} - * On Android and potencially other mobile platforms, WiFi drivers are - * configured by default to discard any packet that is not directed to the - * unicast mac address of the interface, this way they could save some - * battery but breaks anything that is not unicast, such as broadcast - * discovery. On such platforms this method enable low level multicast - * listening so we can receive advertisement from same broadcast domain - * nodes. - * On platforms without such limitation does nothing and always return - * false. - * It is exposed as a public API so the UI can decide the right equilibrium - * between discoverability and battery saving. - * @return true if multicast listening has been enabled due to this call, - * false otherwise. - */ - virtual bool enableMulticastListening() = 0; - - /** - * @brief Disable multicast listening - * @jsonapi{development} - * The opposite of @see enableMulticastListening. - * @return true if multicast listening has been disabled due to this call, - * false otherwise. - */ - virtual bool disableMulticastListening() = 0; - - virtual ~RsBroadcastDiscovery(); -}; diff --git a/libretroshare/src/retroshare/rsconfig.h b/libretroshare/src/retroshare/rsconfig.h deleted file mode 100644 index 918372b79..000000000 --- a/libretroshare/src/retroshare/rsconfig.h +++ /dev/null @@ -1,424 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsconfig.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_CONFIG_GUI_INTERFACE_H -#define RETROSHARE_CONFIG_GUI_INTERFACE_H - -#include -#include -#include -#include -#include - -/* The New Config Interface Class */ -class RsServerConfig; - -/** - * Pointer to global instance of RsServerConfig service implementation - * @jsonapi{development} - */ -extern RsServerConfig *rsConfig; - -enum class RsNetworkMode : uint8_t -{ - UNKNOWN = 1, - RESTARTING = 2, - OFFLINE = 3, - LOCALNET = 4, - BEHINDNAT = 5, - EXTERNALIP = 6 -}; - -enum class RsNatTypeMode : uint8_t -{ - NONE = 1, - UNKNOWN = 2, - SYMMETRIC = 3, - DETERM_SYM = 4, - RESTRICTED_CONE = 5, - FULL_CONE = 6, - OTHER = 7 -}; - -enum class RsNatHoleMode : uint8_t -{ - UNKNOWN = 0, - NONE = 1, - UPNP = 2, - NATPMP = 3, - FORWARDED = 4 -}; - -enum class RsConnectModes : uint16_t -{ - NONE = 0x0000, - ACCEPT_TCP = 0x0001, - OUTGOING_TCP= 0x0002, - DIRECT_UDP = 0x0100, - PROXY_UDP = 0x0200, - RELAY_UDP = 0x0400 -}; -RS_REGISTER_ENUM_FLAGS_TYPE(RsConnectModes) - -enum class RsNetState : uint8_t -{ - // BAD. (RED) - BAD_UNKNOWN = 1, - BAD_OFFLINE = 2, - BAD_NATSYM = 3, - BAD_NODHT_NAT = 4, - - // CAUTION. (ORANGE) - WARNING_RESTART = 5, - WARNING_NATTED = 6, - WARNING_NODHT = 7, - - // GOOD (GREEN) - // NAT with forwarded port, or EXT port. - GOOD = 8, - - // ADVANCED MODE (BLUE) - // If the user knows what they are doing... we cannot confirm this. - ADV_FORWARD = 9, - ADV_DARK_FORWARD= 10 -}; - - - -/************************** Indicate How experienced the RsUser is... based on Friends / Firewall status ******/ - -enum class RsConfigUserLvl : uint8_t -{ - NEW = 1, /* no friends */ - BASIC = 2, /* no connections */ - CASUAL = 3, /* firewalled */ - POWER = 4, /* good! */ - OVERRIDE= 5 /* forced to POWER level */ -}; - - - -// Must Match up with strings internal to Retroshare. -#define RS_CONFIG_ADVANCED 0x0101 - - -enum class RsOpMode : uint8_t -{ - FULL = 1, - NOTURTLE= 2, - GAMING = 3, - MINIMAL = 4 -}; - - -class RsConfigStartup -{ - public: - RsConfigStartup() - { - promptAtBoot = 1; - } - - -int promptAtBoot; /* popup the password prompt */ -}; - - -struct RsConfigDataRates : RsSerializable -{ - RsConfigDataRates() : - mRateIn(0), mRateMaxIn(0), mAllocIn(0), - mAllocTs(0), - mRateOut(0), mRateMaxOut(0), mAllowedOut(0), - mAllowedTs(0), - mQueueIn(0), mQueueOut(0) - {} - - /* all in kB/s */ - float mRateIn; - float mRateMaxIn; - float mAllocIn; - - rstime_t mAllocTs; - - float mRateOut; - float mRateMaxOut; - float mAllowedOut; - - rstime_t mAllowedTs; - - int mQueueIn; - int mQueueOut; - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(mRateIn); - RS_SERIAL_PROCESS(mRateMaxIn); - RS_SERIAL_PROCESS(mAllocIn); - - RS_SERIAL_PROCESS(mAllocTs); - - RS_SERIAL_PROCESS(mRateOut); - RS_SERIAL_PROCESS(mRateMaxOut); - RS_SERIAL_PROCESS(mAllowedOut); - - RS_SERIAL_PROCESS(mAllowedTs); - - RS_SERIAL_PROCESS(mQueueIn); - RS_SERIAL_PROCESS(mQueueOut); - } -}; - -struct RSTrafficClue : RsSerializable -{ - rstime_t TS ; - uint32_t size ; - uint8_t priority ; - uint16_t service_id ; - uint8_t service_sub_id ; - RsPeerId peer_id ; - uint32_t count ; - - RSTrafficClue() { TS=0;size=0;service_id=0;service_sub_id=0; count=0; } - RSTrafficClue& operator+=(const RSTrafficClue& tc) { size += tc.size; count += tc.count ; return *this ;} - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(TS); - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(priority); - RS_SERIAL_PROCESS(service_id); - RS_SERIAL_PROCESS(service_sub_id); - RS_SERIAL_PROCESS(peer_id); - RS_SERIAL_PROCESS(count); - } -}; - -struct RsConfigNetStatus : RsSerializable -{ - RsConfigNetStatus() : netLocalOk(true) - { - localPort = extPort = 0 ; - firewalled = forwardPort = false ; - DHTActive = uPnPActive = netUpnpOk = netDhtOk = netStunOk = netExtAddressOk = false ; - uPnPState = 0 ; - //DHTPeers = 0 ; - netDhtNetSize = netDhtRsNetSize = 0; - } - - RsPeerId ownId; - std::string ownName; - - std::string localAddr; - int localPort; - std::string extAddr; - int extPort; - std::string extDynDns; - - bool firewalled; - bool forwardPort; - - /* older data types */ - bool DHTActive; - bool uPnPActive; - - int uPnPState; - - /* Flags for Network Status */ - RS_DEPRECATED - bool netLocalOk; /// As of today it's meaningless - bool netUpnpOk; /* upnp is enabled and active */ - bool netDhtOk; /* response from dht */ - bool netStunOk; /* recvd stun / udp packets */ - bool netExtAddressOk;/* from Dht/Stun or External IP Finder */ - - uint32_t netDhtNetSize; /* response from dht */ - uint32_t netDhtRsNetSize;/* response from dht */ - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(ownId); - RS_SERIAL_PROCESS(ownName); - - RS_SERIAL_PROCESS(localAddr); - RS_SERIAL_PROCESS(localPort); - RS_SERIAL_PROCESS(extAddr); - RS_SERIAL_PROCESS(extPort); - RS_SERIAL_PROCESS(extDynDns); - - RS_SERIAL_PROCESS(firewalled); - RS_SERIAL_PROCESS(forwardPort); - - RS_SERIAL_PROCESS(DHTActive); - RS_SERIAL_PROCESS(uPnPActive); - - RS_SERIAL_PROCESS(uPnPState); - - RS_SERIAL_PROCESS(netLocalOk); - RS_SERIAL_PROCESS(netUpnpOk); - RS_SERIAL_PROCESS(netDhtOk); - RS_SERIAL_PROCESS(netStunOk); - RS_SERIAL_PROCESS(netExtAddressOk); - - RS_SERIAL_PROCESS(netDhtNetSize); - RS_SERIAL_PROCESS(netDhtRsNetSize); - } -}; - - -/********* - * This is a new style RsConfig Interface. - * It should contain much of the information for the Options/Config Window. - * - * To start with, I'm going to move the stuff from RsIface::RsConfig into here. - * - */ - - -class RsServerConfig -{ -public: - - RsServerConfig() {} - virtual ~RsServerConfig() {} - - /* From RsIface::RsConfig */ - // Implemented Only this one! - /** - * @brief getConfigNetStatus return the net status - * @jsonapi{development} - * @param[out] status network status - * @return returns 1 on succes and 0 otherwise - */ - virtual int getConfigNetStatus(RsConfigNetStatus &status) = 0; - - // NOT IMPLEMENTED YET! - //virtual int getConfigStartup(RsConfigStartup ¶ms) = 0; - - /** - * @brief getTotalBandwidthRates returns the current bandwidths rates - * @jsonapi{development} - * @param[out] rates - * @return returns 1 on succes and 0 otherwise - */ - virtual int getTotalBandwidthRates(RsConfigDataRates &rates) = 0; - - /** - * @brief getAllBandwidthRates get the bandwidth rates for all peers - * @jsonapi{development} - * @param[out] ratemap map with peers->rates - * @return returns 1 on succes and 0 otherwise - */ - virtual int getAllBandwidthRates(std::map &ratemap) = 0; - - /** - * @brief getTrafficInfo returns a list of all tracked traffic clues - * @jsonapi{development} - * @param[out] out_lst outgoing traffic clues - * @param[out] in_lst incomming traffic clues - * @return returns 1 on succes and 0 otherwise - */ - virtual int getTrafficInfo(std::list& out_lst,std::list& in_lst) = 0 ; - - /* From RsInit */ - - // NOT IMPLEMENTED YET! - //virtual std::string RsConfigDirectory() = 0; - //virtual std::string RsConfigKeysDirectory() = 0; - - //virtual std::string RsProfileConfigDirectory() = 0; - //virtual bool getStartMinimised() = 0; - //virtual std::string getRetroShareLink() = 0; - - //virtual bool getAutoLogin() = 0; - //virtual void setAutoLogin(bool autoLogin) = 0; - //virtual bool RsClearAutoLogin() = 0; - - //virtual std::string getRetroshareDataDirectory() = 0; - - /* New Stuff */ - - virtual RsConfigUserLvl getUserLevel() = 0; - - virtual RsNetState getNetState() = 0; - virtual RsNetworkMode getNetworkMode() = 0; - virtual RsNatTypeMode getNatTypeMode() = 0; - virtual RsNatHoleMode getNatHoleMode() = 0; - virtual RsConnectModes getConnectModes() = 0; - - virtual bool getConfigurationOption(uint32_t key, std::string &opt) = 0; - virtual bool setConfigurationOption(uint32_t key, const std::string &opt) = 0; - - - /* Operating Mode */ - /** - * @brief getOperatingMode get current operating mode - * @jsonapi{development} - * @return return the current operating mode - */ - virtual RsOpMode getOperatingMode() = 0; - - /** - * @brief setOperatingMode set the current oprating mode - * @jsonapi{development} - * @param[in] opMode new opearting mode - * @return - */ - virtual bool setOperatingMode(RsOpMode opMode) = 0; - - /** - * @brief setOperatingMode set the current operating mode from string - * @param[in] opModeStr new operating mode as string - * @return - */ - virtual bool setOperatingMode(const std::string &opModeStr) = 0; - - /* Data Rate Control - to be moved here */ - /** - * @brief SetMaxDataRates set maximum upload and download rates - * @jsonapi{development} - * @param[in] downKb download rate in kB - * @param[in] upKb upload rate in kB - * @return returns 1 on succes and 0 otherwise - */ - virtual int SetMaxDataRates( int downKb, int upKb ) = 0; - - /** - * @brief GetMaxDataRates get maximum upload and download rates - * @jsonapi{development} - * @param[out] inKb download rate in kB - * @param[out] outKb upload rate in kB - * @return returns 1 on succes and 0 otherwise - */ - virtual int GetMaxDataRates( int &inKb, int &outKb ) = 0; - - /** - * @brief GetCurrentDataRates get current upload and download rates - * @jsonapi{development} - * @param[out] inKb download rate in kB - * @param[out] outKb upload rate in kB - * @return returns 1 on succes and 0 otherwise - */ - virtual int GetCurrentDataRates( float &inKb, float &outKb ) = 0; - virtual int GetTrafficSum( uint64_t &inb, uint64_t &outb ) = 0; -}; - -#endif diff --git a/libretroshare/src/retroshare/rsdht.h b/libretroshare/src/retroshare/rsdht.h deleted file mode 100644 index f62d029eb..000000000 --- a/libretroshare/src/retroshare/rsdht.h +++ /dev/null @@ -1,230 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsdht.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_DHT_GUI_INTERFACE_H -#define RETROSHARE_DHT_GUI_INTERFACE_H - -#include -#include -#include -#include -#include "util/rsnet.h" -#include "retroshare/rsflags.h" - -/* The Main Interface Class - for information about your Peers */ -class RsDht; -extern RsDht *rsDht; - -//std::ostream &operator<<(std::ostream &out, const RsPhotoShowDetails &detail); -//std::ostream &operator<<(std::ostream &out, const RsPhotoDetails &detail); - -enum class RsDhtPeerType : uint8_t -{ - ANY = 0, - OTHER = 1, - FOF = 2, - FRIEND = 3 -}; - -enum class RsDhtPeerDht : uint8_t -{ - NOT_ACTIVE = 0, - SEARCHING = 1, - FAILURE = 2, - OFFLINE = 3, - UNREACHABLE = 4, - ONLINE = 5 -}; - -enum class RsDhtPeerConnectState : uint8_t -{ - DISCONNECTED = 1, - UDP_STARTED = 2, - CONNECTED = 3 -}; - -enum class RsDhtPeerRequest : uint8_t -{ - STOPPED = 1, - RUNNING = 2 -}; - -enum class RsDhtTouMode : uint8_t -{ - NONE = 0, - DIRECT = 1, - PROXY = 2, - RELAY = 3 -}; - -enum class RsDhtRelayClass : uint8_t -{ - ALL = 0, - GENERAL = 1, - FOF = 2, - FRIENDS = 3, - - NUM_CLASS = 4 -}; - -enum class RsDhtRelayMode : uint16_t -{ - DISABLED= 0x0000, - ENABLED = 0x0001, - - MASK = 0x00f0, - OFF = 0x0010, - ON = 0x0020, - SERVER = 0x0040 -}; -RS_REGISTER_ENUM_FLAGS_TYPE(RsDhtRelayMode) - -class RsDhtPeer -{ - public: - RsDhtPeer(); - - int mBucket; - std::string mDhtId; - std::string mAddr; - rstime_t mLastSendTime; - rstime_t mLastRecvTime; - rstime_t mFoundTime; - uint32_t mPeerFlags; - uint32_t mExtraFlags; -}; - -class RsDhtNetPeer -{ - public: - RsDhtNetPeer(); - - std::string mDhtId; - RsPeerId mRsId; - - RsDhtPeerType mPeerType; - RsDhtPeerDht mDhtState; - - std::string mConnectState; // connectLogic. - - RsDhtPeerConnectState mPeerConnectState; - RsDhtTouMode mPeerConnectMode; - bool mExclusiveProxyLock; - - std::string mPeerConnectProxyId; - - RsDhtPeerRequest mPeerReqState; - std::string mCbPeerMsg; // Peer Cb Mgs. - -}; - -class RsDhtRelayEnd -{ - public: - - RsDhtRelayEnd(); - std::string mLocalAddr; - std::string mProxyAddr; - std::string mRemoteAddr; - rstime_t mCreateTS; -}; - -class RsDhtRelayProxy -{ - public: - RsDhtRelayProxy(); - - std::string mSrcAddr; - std::string mDestAddr; - - double mBandwidth; - int mRelayClass; - rstime_t mLastTS; - rstime_t mCreateTS; - - //uint32_t mDataSize; - //rstime_t mLastBandwidthTS; - -}; -class RsDhtFilteredPeer -{ -public: - struct sockaddr_in mAddr; - uint32_t mFilterFlags; /* reasons why we are filtering */ - rstime_t mFilterTS; - rstime_t mLastSeen; -}; - -class RsDht -{ - public: - - RsDht() { return; } -virtual ~RsDht() { return; } - -virtual uint32_t getNetState(uint32_t type) = 0; -virtual int getDhtPeers(int lvl, std::list &peers) = 0; -virtual int getNetPeerList(std::list &peerIds) = 0; -virtual int getNetPeerStatus(const RsPeerId& peerId, RsDhtNetPeer &status) = 0; - -virtual int getRelayEnds(std::list &relayEnds) = 0; -virtual int getRelayProxies(std::list &relayProxies) = 0; - -//virtual int getNetFailedPeer(std::string peerId, PeerStatus &status); - -virtual std::string getUdpAddressString() = 0; - -virtual void getDhtRates(float &read, float &write) = 0; -virtual void getRelayRates(float &read, float &write, float &relay) = 0; - - // Interface for controlling Relays & DHT Relay Mode -virtual int getRelayServerList(std::list &ids) = 0; -virtual int addRelayServer(std::string ids) = 0; -virtual int removeRelayServer(std::string ids) = 0; - -virtual RsDhtRelayMode getRelayMode() = 0; -virtual int setRelayMode(RsDhtRelayMode mode) = 0; - -virtual int getRelayAllowance(RsDhtRelayClass classIdx, uint32_t &count, uint32_t &bandwidth) = 0; -virtual int setRelayAllowance(RsDhtRelayClass classIdx, uint32_t count, uint32_t bandwidth) = 0; - - // So we can provide to clients. -virtual bool getOwnDhtId(std::string &ownDhtId) = 0; - -virtual bool isAddressBanned(const struct sockaddr_storage& raddr) =0; -virtual void getListOfBannedIps(std::list& lst) =0; - -#if 0 -virtual std::string getPeerStatusString(); -virtual std::string getDhtStatusString(); - -virtual int get_dht_queries(std::map &queries); -virtual int get_query_status(std::string id, bdQuerySummary &query); - -virtual int get_peer_status(std::string peerId, PeerStatus &status); - -virtual int get_net_failedpeers(std::list &peerIds); -virtual int get_failedpeer_status(std::string peerId, PeerStatus &status); -#endif - -}; - -#endif diff --git a/libretroshare/src/retroshare/rsdisc.h b/libretroshare/src/retroshare/rsdisc.h deleted file mode 100644 index 06311be6c..000000000 --- a/libretroshare/src/retroshare/rsdisc.h +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************* - * RetroShare gossip discovery - discovery2 retro-compatibility include * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsgossipdiscovery.h" -#include "util/rsdeprecate.h" - -#warning "Including retroshare/rsdisc.h is deprecated, \ -use retroshare/rsgossipdiscovery.h instead" - -using RsDisc RS_DEPRECATED_FOR("RsGossipDiscovery") = RsGossipDiscovery; - -#define rsDisc rsGossipDiscovery.get() diff --git a/libretroshare/src/retroshare/rsevents.h b/libretroshare/src/retroshare/rsevents.h deleted file mode 100644 index ec2e7b97f..000000000 --- a/libretroshare/src/retroshare/rsevents.h +++ /dev/null @@ -1,254 +0,0 @@ -/******************************************************************************* - * Retroshare events service * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2019-2020 Retroshare Team * - * Copyright (C) 2019-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "util/rsmemory.h" -#include "util/rsurl.h" -#include "serialiser/rsserializable.h" -#include "serialiser/rstypeserializer.h" -#include "util/rstime.h" -#include "util/rsdebug.h" - -class RsEvents; - -/** - * Pointer to global instance of RsEvents service implementation - * @jsonapi{development} - * - * TODO: this should become std::weak_ptr once we have a reasonable services - * management. - */ -extern RsEvents* rsEvents; - -/** - * @brief Events types. - * When creating a new type of event, add a new type here and use that to - * initialize mType in the constructor of your derivative of @see RsEvent - */ -enum class RsEventType : uint32_t -{ - __NONE = 0, /// Used internally to detect invalid event type passed - - /// @see RsBroadcastDiscovery - BROADCAST_DISCOVERY = 1, - - /// @see RsDiscPendingPgpReceivedEvent - GOSSIP_DISCOVERY = 2, - - /// @see AuthSSL - AUTHSSL_CONNECTION_AUTENTICATION = 3, - - /// @see pqissl - PEER_CONNECTION = 4, - - /// @see RsGxsChanges, used also in @see RsGxsBroadcast - GXS_CHANGES = 5, - - /// Emitted when a peer state changes, @see RsPeers - PEER_STATE_CHANGED = 6, - - /// @see RsMailStatusEvent - MAIL_STATUS = 7, - - /// @see RsGxsCircleEvent - GXS_CIRCLES = 8, - - /// @see RsGxsChannelEvent - GXS_CHANNELS = 9, - - /// @see RsGxsForumEvent - GXS_FORUMS = 10, - - /// @see RsGxsPostedEvent - GXS_POSTED = 11, - - /// @see RsGxsPostedEvent - GXS_IDENTITY = 12, - - /// @see RsFiles - SHARED_DIRECTORIES = 13, - - /// @see RsFiles - FILE_TRANSFER = 14, - - /// @see RsMsgs - CHAT_MESSAGE = 15, - - /// @see rspeers.h - NETWORK = 16, - - __MAX /// Used internally, keep last -}; - -enum class RsEventsErrorNum : int32_t -{ - EVENT_TYPE_UNDEFINED = 3004, - EVENT_TYPE_OUT_OF_RANGE = 3005, - INVALID_HANDLER_ID = 3006, - NULL_EVENT_POINTER = 3007 -}; - -struct RsEventsErrorCategory: std::error_category -{ - const char* name() const noexcept override - { return "RetroShare Events"; } - - std::string message(int ev) const override - { - switch (static_cast(ev)) - { - case RsEventsErrorNum::EVENT_TYPE_UNDEFINED: - return "Undefined event type"; - case RsEventsErrorNum::EVENT_TYPE_OUT_OF_RANGE: - return "Event type out of range"; - case RsEventsErrorNum::INVALID_HANDLER_ID: - return "Invalid handler id"; - default: - return rsErrorNotInCategory(ev, name()); - } - } - - std::error_condition default_error_condition(int ev) const noexcept override; - - const static RsEventsErrorCategory instance; -}; - - -namespace std -{ -/** Register RsJsonApiErrorNum as an error condition enum, must be in std - * namespace */ -template<> struct is_error_condition_enum : true_type {}; -} - -/** Provide RsEventsErrorNum conversion to std::error_condition, must be in - * same namespace of RsJsonApiErrorNum */ -inline std::error_condition make_error_condition(RsEventsErrorNum e) noexcept -{ - return std::error_condition( - static_cast(e), RsEventsErrorCategory::instance ); -}; - - -/** - * This struct is not meant to be used directly, you should create events type - * deriving from it. - */ -struct RsEvent : RsSerializable -{ -protected: - explicit RsEvent(RsEventType type) : - mType(type), mTimePoint(std::chrono::system_clock::now()) {} - - RsEvent() = delete; - -public: - RsEventType mType; - std::chrono::system_clock::time_point mTimePoint; - - /** - * Derived types must call this method at beginning of their implementation - * of serial_process - * @see RsSerializable - */ - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(mType); - - rstime_t mTime = std::chrono::system_clock::to_time_t(mTimePoint); - RS_SERIAL_PROCESS(mTime); - mTimePoint = std::chrono::system_clock::from_time_t(mTime); - } - - ~RsEvent() override; -}; - -typedef uint32_t RsEventsHandlerId_t; - -class RsEvents -{ -public: - /** - * @brief Post event to the event queue. - * @param[in] event - * @return Success or error details. - */ - virtual std::error_condition postEvent( - std::shared_ptr event ) = 0; - - /** - * @brief Send event directly to handlers. Blocking API - * The handlers get exectuded on the caller thread. - * @param[in] event - * @return Success or error details. - */ - virtual std::error_condition sendEvent( - std::shared_ptr event ) = 0; - - /** - * @brief Generate unique handler identifier - * @return generate Id - */ - virtual RsEventsHandlerId_t generateUniqueHandlerId() = 0; - - /** - * @brief Register events handler - * Every time an event is dispatced the registered events handlers will get - * their method handleEvent called with the event passed as paramether. - * @attention Callbacks must not fiddle internally with methods of this - * class otherwise a deadlock will happen. - * @jsonapi{development,manualwrapper} - * @param multiCallback Function that will be called each time an event - * is dispatched. - * @param[inout] hId Optional storage for handler id, useful to - * eventually unregister the handler later. The - * value may be provided to the function call but - * must habe been generated with - * @see generateUniqueHandlerId() - * @param[in] eventType Optional type of event for which the callback is - * called, if __NONE is passed multiCallback is - * called for every events without filtering. - * @return Success or error details. - */ - virtual std::error_condition registerEventsHandler( - std::function)> multiCallback, - RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0), - RsEventType eventType = RsEventType::__NONE ) = 0; - - /** - * @brief Unregister event handler - * @param[in] hId Id of the event handler to unregister - * @return Success or error details. - */ - virtual std::error_condition unregisterEventsHandler( - RsEventsHandlerId_t hId ) = 0; - - virtual ~RsEvents(); -}; diff --git a/libretroshare/src/retroshare/rsexpr.h b/libretroshare/src/retroshare/rsexpr.h deleted file mode 100644 index 562d6e342..000000000 --- a/libretroshare/src/retroshare/rsexpr.h +++ /dev/null @@ -1,407 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsexpr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Kashif Kaleem * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "util/rsprint.h" -#include "retroshare/rstypes.h" -#include "util/rstime.h" - -/****************************************************************************************** -Enumerations defining the Operators usable in the Boolean search expressions -******************************************************************************************/ - -namespace RsRegularExpression -{ -enum LogicalOperator{ - AndOp=0, /* exp AND exp */ - OrOp=1, /* exp OR exp */ - XorOp=2 /* exp XOR exp */ -}; - - -/* Operators for String Queries */ -enum StringOperator{ - ContainsAnyStrings = 0, /* e.g. name contains any of 'conference' 'meeting' 'presentation' */ - ContainsAllStrings = 1, /* same as above except that it contains ALL of the strings */ - EqualsString = 2 /* exactly equal*/ -}; - -/* Comparison operators ( >, <, >=, <=, == and InRange ) */ -enum RelOperator{ - Equals = 0, - GreaterEquals = 1, - Greater = 2, - SmallerEquals = 3, - Smaller = 4, - InRange = 5 /* lower limit <= value <= upper limit*/ -}; - -/******************************************************************************************** - * Helper class for further serialisation - ********************************************************************************************/ - -class StringExpression ; -class Expression ; - -class LinearizedExpression -{ -public: - std::vector _tokens ; - std::vector _ints ; - std::vector _strings ; - - typedef enum { EXPR_DATE = 0, - EXPR_POP = 1, - EXPR_SIZE = 2, - EXPR_HASH = 3, - EXPR_NAME = 4, - EXPR_PATH = 5, - EXPR_EXT = 6, - EXPR_COMP = 7, - EXPR_SIZE_MB = 8 } token ; - - static Expression *toExpr(const LinearizedExpression& e) ; - - std::string GetStrings(); - -private: - static Expression *toExpr(const LinearizedExpression& e,int&,int&,int&) ; - static void readStringExpr(const LinearizedExpression& e,int& n_ints,int& n_strings,std::list& strings,bool& b,StringOperator& op) ; -}; - - -/****************************************************************************************** -Boolean Search Expression -classes: - - Expression: The base class of all expression typest - CompoundExpression: The expression which uses a logical operator to combine - the results of two expressions - StringExpression: An expression which uses some sort of string comparison. - RelExpression: A Relational Expression where > < >= <= == make sense. - e.g. size date etc - -******************************************************************************************/ - -/*! - * \brief The ExpFileEntry class - * This is the base class the regular expressions can operate on. Derive it to fit your own needs! - */ -class ExpFileEntry -{ -public: - virtual const std::string& file_name() const =0; - virtual uint64_t file_size() const =0; - virtual rstime_t file_modtime() const =0; - virtual uint32_t file_popularity() const =0; - virtual std::string file_parent_path() const =0; - virtual const RsFileHash& file_hash() const =0; -}; - -class Expression -{ -public: - virtual bool eval (const ExpFileEntry& file) = 0; - virtual ~Expression() {}; - - virtual void linearize(LinearizedExpression& e) const = 0 ; - virtual std::string toStdString() const = 0 ; -}; - -class CompoundExpression : public Expression -{ -public: - CompoundExpression( enum LogicalOperator op, Expression * exp1, Expression *exp2) - : Lexp(exp1), Rexp(exp2), Op(op){ } - - bool eval (const ExpFileEntry& file) { - if (Lexp == NULL or Rexp == NULL) { - return false; - } - switch (Op){ - case AndOp: - return Lexp->eval(file) && Rexp->eval(file); - case OrOp: - return Lexp->eval(file) || Rexp->eval(file); - case XorOp: - return Lexp->eval(file) ^ Rexp->eval(file); - default: - return false; - } - } - virtual ~CompoundExpression(){ - delete Lexp; - delete Rexp; - } - - virtual std::string toStdString() const - { - switch(Op) - { - case AndOp: return "(" + Lexp->toStdString() + ") AND (" + Rexp->toStdString() +")" ; - case OrOp: return "(" + Lexp->toStdString() + ") OR (" + Rexp->toStdString() +")" ; - case XorOp: return "(" + Lexp->toStdString() + ") XOR (" + Rexp->toStdString() +")" ; - default: - return "" ; - } - } - - virtual void linearize(LinearizedExpression& e) const ; -private: - Expression *Lexp; - Expression *Rexp; - enum LogicalOperator Op; - -}; - -class StringExpression: public Expression -{ -public: - StringExpression(enum StringOperator op, const std::list &t, bool ic): Op(op),terms(t), IgnoreCase(ic){} - - virtual void linearize(LinearizedExpression& e) const ; - virtual std::string toStdStringWithParam(const std::string& varstr) const; -protected: - bool evalStr(const std::string &str); - - enum StringOperator Op; - std::list terms; - bool IgnoreCase; -}; - -template -class RelExpression: public Expression -{ -public: - RelExpression(enum RelOperator op, T lv, T hv): Op(op), LowerValue(lv), HigherValue(hv) {} - - virtual void linearize(LinearizedExpression& e) const ; - virtual std::string toStdStringWithParam(const std::string& typestr) const; -protected: - bool evalRel(T val); - - enum RelOperator Op; - T LowerValue; - T HigherValue; -}; - -template<> void RelExpression::linearize(LinearizedExpression& e) const ; - -template -bool RelExpression::evalRel(T val) { - switch (Op) { - case Equals: - return LowerValue == val; - case GreaterEquals: - return LowerValue >= val; - case Greater: - return LowerValue > val; - case SmallerEquals: - return LowerValue <= val; - case Smaller: - return LowerValue < val; - case InRange: - return (LowerValue <= val) && (val <= HigherValue); - default: - return false; - } -} - -template -std::string RelExpression::toStdStringWithParam(const std::string& typestr) const -{ - std::string LowerValueStr = RsUtil::NumberToString(LowerValue) ; - - switch (Op) { - case Equals: return typestr + " = " + LowerValueStr ; - case GreaterEquals: return typestr + " <= "+ LowerValueStr ; - case Greater: return typestr + " < " + LowerValueStr ; - case SmallerEquals: return typestr + " >= "+ LowerValueStr ; - case Smaller: return typestr + " > " + LowerValueStr ; - case InRange: return LowerValueStr + " <= " + typestr + " <= " + RsUtil::NumberToString(HigherValue) ; - default: - return ""; - } -} - -/****************************************************************************************** -Binary Predicate for Case Insensitive search - -******************************************************************************************/ -/*Binary predicate for case insensitive character comparison.*/ -/*TODOS: - *Factor locales in the comparison - */ -struct CompareCharIC : - public std::binary_function< char , char , bool> { - - bool operator () ( char ch1 , char ch2 ) const { - return tolower( static_cast < unsigned char > (ch1) ) - == tolower( static_cast < unsigned char > (ch2) ); - } - -}; - -/****************************************************************************************** -Some implementations of StringExpressions. - -******************************************************************************************/ - -class NameExpression: public StringExpression -{ -public: - NameExpression(enum StringOperator op, const std::list &t, bool ic): - StringExpression(op,t,ic) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString() const { return StringExpression::toStdStringWithParam("NAME"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_NAME) ; - StringExpression::linearize(e) ; - } -}; - -class PathExpression: public StringExpression { -public: - PathExpression(enum StringOperator op, const std::list &t, bool ic): - StringExpression(op,t,ic) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString()const { return StringExpression::toStdStringWithParam("PATH"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_PATH) ; - StringExpression::linearize(e) ; - } -}; - -class ExtExpression: public StringExpression { -public: - ExtExpression(enum StringOperator op, const std::list &t, bool ic): - StringExpression(op,t,ic) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString()const { return StringExpression::toStdStringWithParam("EXTENSION"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_EXT) ; - StringExpression::linearize(e) ; - } -}; - -class HashExpression: public StringExpression { -public: - HashExpression(enum StringOperator op, const std::list &t): - StringExpression(op,t, true) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString() const { return StringExpression::toStdStringWithParam("HASH"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_HASH) ; - StringExpression::linearize(e) ; - } -}; - -/****************************************************************************************** -Some implementations of Relational Expressions. - -******************************************************************************************/ - -class DateExpression: public RelExpression -{ -public: - DateExpression(enum RelOperator op, int v): RelExpression(op,v,v){} - DateExpression(enum RelOperator op, int lv, int hv): - RelExpression(op,lv,hv) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString() const { return RelExpression::toStdStringWithParam("DATE"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_DATE) ; - RelExpression::linearize(e) ; - } -}; - -class SizeExpression: public RelExpression -{ -public: - SizeExpression(enum RelOperator op, int v): RelExpression(op,v,v){} - SizeExpression(enum RelOperator op, int lv, int hv): - RelExpression(op,lv,hv) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString() const { return RelExpression::toStdStringWithParam("SIZE"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_SIZE) ; - RelExpression::linearize(e) ; - } -}; - -class SizeExpressionMB: public RelExpression -{ -public: - SizeExpressionMB(enum RelOperator op, int v): RelExpression(op,v,v){} - SizeExpressionMB(enum RelOperator op, int lv, int hv): - RelExpression(op,lv,hv) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString() const { return RelExpression::toStdStringWithParam("SIZE"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_SIZE_MB) ; - RelExpression::linearize(e) ; - } -}; -class PopExpression: public RelExpression -{ -public: - PopExpression(enum RelOperator op, int v): RelExpression(op,v,v){} - PopExpression(enum RelOperator op, int lv, int hv): RelExpression(op,lv,hv) {} - PopExpression(const LinearizedExpression& e) ; - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString() const { return RelExpression::toStdStringWithParam("POPULARITY"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_POP) ; - RelExpression::linearize(e) ; - } -}; -} - - diff --git a/libretroshare/src/retroshare/rsfiles.h b/libretroshare/src/retroshare/rsfiles.h deleted file mode 100644 index f25d90957..000000000 --- a/libretroshare/src/retroshare/rsfiles.h +++ /dev/null @@ -1,996 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsfiles.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2008 Robert Fernie * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2019-2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include "rstypes.h" -#include "serialiser/rsserializable.h" -#include "rsturtle.h" -#include "util/rstime.h" -#include "retroshare/rsevents.h" -#include "util/rsmemory.h" -#include "util/rsdebug.h" - -class RsFiles; - -/** - * Pointer to global instance of RsFiles service implementation - * @jsonapi{development} - */ -extern RsFiles* rsFiles; - -enum class RsFilesErrorNum : int32_t -{ - FILES_HANDLE_NOT_FOUND = 2004, -}; - -struct RsFilesErrorCategory: std::error_category -{ - const char* name() const noexcept override - { return "RetroShare Files"; } - - std::string message(int ev) const override - { - switch (static_cast(ev)) - { - case RsFilesErrorNum::FILES_HANDLE_NOT_FOUND: - return "Files handle not found"; - default: - return rsErrorNotInCategory(ev, name()); - } - } - - std::error_condition default_error_condition(int ev) const noexcept override; - - const static RsFilesErrorCategory instance; -}; - - -namespace std -{ -/** Register RsFilesErrorNum as an error condition enum, must be in std - * namespace */ -template<> struct is_error_condition_enum : true_type {}; -} - -/** Provide RsJsonApiErrorNum conversion to std::error_condition, must be in - * same namespace of RsJsonApiErrorNum */ -inline std::error_condition make_error_condition(RsFilesErrorNum e) noexcept -{ - return std::error_condition( - static_cast(e), RsFilesErrorCategory::instance ); -}; - - -namespace RsRegularExpression { class Expression; } - -/* These are used mainly by ftController at the moment */ -const uint32_t RS_FILE_CTRL_PAUSE = 0x00000100; -const uint32_t RS_FILE_CTRL_START = 0x00000200; -const uint32_t RS_FILE_CTRL_FORCE_CHECK = 0x00000400; - -const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT = 0x00000001 ; -const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE = 0x00000002 ; - -const uint32_t RS_FILE_PERM_DIRECT_DL_YES = 0x00000001 ; -const uint32_t RS_FILE_PERM_DIRECT_DL_NO = 0x00000002 ; -const uint32_t RS_FILE_PERM_DIRECT_DL_PER_USER = 0x00000003 ; - -const uint32_t RS_FILE_RATE_TRICKLE = 0x00000001; -const uint32_t RS_FILE_RATE_SLOW = 0x00000002; -const uint32_t RS_FILE_RATE_STANDARD = 0x00000003; -const uint32_t RS_FILE_RATE_FAST = 0x00000004; -const uint32_t RS_FILE_RATE_STREAM_AUDIO = 0x00000005; -const uint32_t RS_FILE_RATE_STREAM_VIDEO = 0x00000006; - -const uint32_t RS_FILE_PEER_ONLINE = 0x00001000; -const uint32_t RS_FILE_PEER_OFFLINE = 0x00002000; - -const uint32_t RS_FILE_SHARE_FLAGS_IGNORE_PREFIXES = 0x0001 ; -const uint32_t RS_FILE_SHARE_FLAGS_IGNORE_SUFFIXES = 0x0002 ; -const uint32_t RS_FILE_SHARE_FLAGS_IGNORE_DUPLICATES = 0x0004 ; - -const uint32_t RS_FILE_SHARE_PARAMETER_DEFAULT_MAXIMUM_DEPTH = 8; - -/************************************ - * Used To indicate where to search. - * - * The Order of these is very important, - * it specifies the search order too. - * - */ - -// Flags used when requesting info about transfers, mostly to filter out the result. -// -const FileSearchFlags RS_FILE_HINTS_CACHE_deprecated ( 0x00000001 ); -const FileSearchFlags RS_FILE_HINTS_EXTRA ( 0x00000002 ); -const FileSearchFlags RS_FILE_HINTS_LOCAL ( 0x00000004 ); -const FileSearchFlags RS_FILE_HINTS_REMOTE ( 0x00000008 ); -const FileSearchFlags RS_FILE_HINTS_DOWNLOAD ( 0x00000010 ); -const FileSearchFlags RS_FILE_HINTS_UPLOAD ( 0x00000020 ); -const FileSearchFlags RS_FILE_HINTS_SPEC_ONLY ( 0x01000000 ); - -const FileSearchFlags RS_FILE_HINTS_NETWORK_WIDE ( 0x00000080 );// can be downloaded anonymously -const FileSearchFlags RS_FILE_HINTS_BROWSABLE ( 0x00000100 );// browsable by friends -const FileSearchFlags RS_FILE_HINTS_SEARCHABLE ( 0x00000200 );// can be searched anonymously -const FileSearchFlags RS_FILE_HINTS_PERMISSION_MASK ( 0x00000380 );// OR of the last tree flags. Used to filter out. - -/** Flags used when requesting a new file transfer */ -enum class FileRequestFlags: uint32_t -{ - /// Enable requesting file via turtle routing. - ANONYMOUS_ROUTING = 0x00000040, - - /// Asks (TODO: or enforce?) for end-to-end encryption of file trasfer - ENCRYPTED = 0x00000080, - - /// Asks (TODO: or enforce?) no end-to-end encryption of file trasfer - UNENCRYPTED = 0x00000100, - - /// Start trasfer very slow - SLOW = 0x00002000, - - /// Disable searching for potential direct sources - NO_DIRECT_SEARCH = 0x02000000 -}; -RS_REGISTER_ENUM_FLAGS_TYPE(FileRequestFlags) - -/// @deprecated Flags used when requesting a transfer -/// @see FileRequestFlags instead -const TransferRequestFlags RS_FILE_REQ_ANONYMOUS_ROUTING ( 0x00000040 ); // Use to ask turtle router to download the file. -const TransferRequestFlags RS_FILE_REQ_ENCRYPTED ( 0x00000080 ); // Asks for end-to-end encryption of file at the level of ftServer -const TransferRequestFlags RS_FILE_REQ_UNENCRYPTED ( 0x00000100 ); // Asks for no end-to-end encryption of file at the level of ftServer -const TransferRequestFlags RS_FILE_REQ_ASSUME_AVAILABILITY ( 0x00000200 ); // Assume full source availability. Used for cache files. -const TransferRequestFlags RS_FILE_REQ_CACHE_deprecated ( 0x00000400 ); // Old stuff used for cache files. Not used anymore. -const TransferRequestFlags RS_FILE_REQ_EXTRA ( 0x00000800 ); -const TransferRequestFlags RS_FILE_REQ_MEDIA ( 0x00001000 ); -const TransferRequestFlags RS_FILE_REQ_BACKGROUND ( 0x00002000 ); // To download slowly. -const TransferRequestFlags RS_FILE_REQ_NO_SEARCH ( 0x02000000 ); // disable searching for potential direct sources. - -// const uint32_t RS_FILE_HINTS_SHARE_FLAGS_MASK = RS_FILE_HINTS_NETWORK_WIDE_OTHERS | RS_FILE_HINTS_BROWSABLE_OTHERS -// | RS_FILE_HINTS_NETWORK_WIDE_GROUPS | RS_FILE_HINTS_BROWSABLE_GROUPS ; - -enum class RsSharedDirectoriesEventCode: uint8_t { - UNKNOWN = 0x00, - STARTING_DIRECTORY_SWEEP = 0x01, // (void) - HASHING_FILE = 0x02, // mMessage: full path and hashing speed of the file being hashed - DIRECTORY_SWEEP_ENDED = 0x03, // (void) - SAVING_FILE_INDEX = 0x04, // (void) - EXTRA_LIST_FILE_ADDED = 0x05, // (void) - EXTRA_LIST_FILE_REMOVED = 0x06, // (void) -}; - -enum class RsFileTransferEventCode: uint8_t { - UNKNOWN = 0x00, - DOWNLOAD_COMPLETE = 0x01, // mHash: hash of the complete file - COMPLETED_FILES_REMOVED = 0x02, // -}; - -struct RsSharedDirectoriesEvent: RsEvent -{ - RsSharedDirectoriesEvent() : RsEvent(RsEventType::SHARED_DIRECTORIES), mEventCode(RsSharedDirectoriesEventCode::UNKNOWN) {} - ~RsSharedDirectoriesEvent() override = default; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - - RS_SERIAL_PROCESS(mEventCode); - RS_SERIAL_PROCESS(mMessage); - } - - RsSharedDirectoriesEventCode mEventCode; - std::string mMessage; -}; - -struct RsFileTransferEvent: RsEvent -{ - RsFileTransferEvent() : RsEvent(RsEventType::FILE_TRANSFER), mFileTransferEventCode(RsFileTransferEventCode::UNKNOWN) {} - ~RsFileTransferEvent() override = default; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - - RS_SERIAL_PROCESS(mFileTransferEventCode); - RS_SERIAL_PROCESS(mHash); - } - - RsFileTransferEventCode mFileTransferEventCode; - RsFileHash mHash; -}; -struct SharedDirInfo : RsSerializable -{ - static bool sameLists(const std::list& l1,const std::list& l2) - { - std::list::const_iterator it1(l1.begin()) ; - std::list::const_iterator it2(l2.begin()) ; - - for(; (it1!=l1.end() && it2!=l2.end());++it1,++it2) - if(*it1 != *it2) - return false ; - - return it1 == l1.end() && it2 == l2.end() ; - } - - std::string filename; - std::string virtualname; - - /// combnation of DIR_FLAGS_ANONYMOUS_DOWNLOAD | DIR_FLAGS_BROWSABLE | ... - FileStorageFlags shareflags; - std::list parent_groups; - - /// @see RsSerializable::serial_process - virtual void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(filename); - RS_SERIAL_PROCESS(virtualname); - RS_SERIAL_PROCESS(shareflags); - RS_SERIAL_PROCESS(parent_groups); - } -}; - -struct SharedDirStats -{ - uint32_t total_number_of_files ; - uint64_t total_shared_size ; -}; - -/** This class represents a tree of directories and files, only with their names - * size and hash. It is used to create collection links in the GUI and to - * transmit directory information between services. This class is independent - * from the existing FileHierarchy classes used in storage because we need a - * very copact serialization and storage size since we create links with it. - * Besides, we cannot afford to risk the leak of other local information - * by using the orignal classes. - */ -struct RsFileTree : RsSerializable -{ -public: - RsFileTree() : mTotalFiles(0), mTotalSize(0) {} - - /** - * @brief Create a RsFileTree from directory details - * @param dd directory or file details - * @param remote - * @param remove_top_dirs - * @return pointer to the created file-tree - */ - static std::unique_ptr fromDirDetails( - const DirDetails& dd, bool remote, bool remove_top_dirs = true ); - - /** - * @brief Create a RsFileTree from Base64 representation - * @param base64 base64 or base64url string representation of the file-tree - * @return pointer to the parsed file-tree on success, nullptr plus error - * details on failure - */ - static std::tuple, std::error_condition> - fromBase64(const std::string& base64); - - /** @brief Convert to base64 representetion */ - std::string toBase64() const; - - /// @see RsSerializable - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mFiles); - RS_SERIAL_PROCESS(mDirs); - RS_SERIAL_PROCESS(mTotalFiles); - RS_SERIAL_PROCESS(mTotalSize); - } - - struct FileData: RsSerializable - { - std::string name; - uint64_t size; - RsFileHash hash; - - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - }; - - /// Allow browsing the hierarchy - bool getDirectoryContent( - std::string& name, std::vector& subdirs, - std::vector& subfiles, uint64_t handle = 0 ) const; - - struct DirData: RsSerializable - { - std::string name; - std::vector subdirs; - std::vector subfiles; - - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - }; - - static void recurs_buildFileTree( - RsFileTree& ft, uint32_t index, const DirDetails& dd, bool remote, - bool remove_top_dirs ); - - std::vector mFiles; - std::vector mDirs; - - uint32_t mTotalFiles; - uint64_t mTotalSize; - - virtual ~RsFileTree(); - - /** - * @brief Create a RsFileTree from Radix64 representation - * @deprecated kept for retrocompatibility with RetroShare-gui - * The format is not compatible with the new methods - * @param radix64_string - * @return nullptr if on failure, pointer to the created FileTree on success - */ - RS_DEPRECATED_FOR(fromBase64) - static std::unique_ptr fromRadix64( - const std::string& radix64_string ); - - /** @brief Convert to radix64 representetion - * @deprecated kept for retrocompatibility with RetroShare-gui - * The format is not compatible with the new methods - */ - RS_DEPRECATED_FOR(toBase64) - std::string toRadix64() const; - -private: - /** @deprecated kept for retrocompatibility with RetroShare-gui */ - RS_DEPRECATED_FOR(serial_process) - bool serialise(unsigned char *& data,uint32_t& data_size) const; - - /** @deprecated kept for retrocompatibility with RetroShare-gui */ - RS_DEPRECATED_FOR(serial_process) - bool deserialise(unsigned char* data, uint32_t data_size); -}; - -struct BannedFileEntry : RsSerializable -{ - BannedFileEntry() : mFilename(""), mSize(0), mBanTimeStamp(0) {} - - std::string mFilename; - uint64_t mSize; - rstime_t mBanTimeStamp; - - /// @see RsSerializable::serial_process - virtual void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(mFilename); - RS_SERIAL_PROCESS(mSize); - RS_SERIAL_PROCESS(mBanTimeStamp); - } -}; - -struct DeepFilesSearchResult; - -struct TurtleFileInfoV2 : RsSerializable -{ - TurtleFileInfoV2() : fSize(0), fWeight(0) {} - - explicit TurtleFileInfoV2(const TurtleFileInfo& oldInfo) : - fSize(oldInfo.size), fHash(oldInfo.hash), fName(oldInfo.name), - fWeight(0) {} - -#ifdef RS_DEEP_FILES_INDEX - explicit TurtleFileInfoV2(const DeepFilesSearchResult& dRes); -#endif // def RS_DEEP_FILES_INDEX - - uint64_t fSize; /// File size - RsFileHash fHash; /// File hash - std::string fName; /// File name - - /** @brief Xapian weight of the file which matched the search criteria - * This field is optional (its value is 0 when not specified). - * Given that Xapian weight for the same file is usually different on - * different nodes, it should not be used as an absolute refence, but just - * as an hint of how much the given file match the search criteria. - */ - float fWeight; - - /** @brief Xapian snippet of the file which matched the search criteria - * This field is optional (its value is an empty string when not specified). - */ - std::string fSnippet; - - - /// @see RsSerializable::serial_process - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(fSize); - RS_SERIAL_PROCESS(fHash); - RS_SERIAL_PROCESS(fName); - RS_SERIAL_PROCESS(fWeight); - RS_SERIAL_PROCESS(fSnippet); - } - - ~TurtleFileInfoV2() override; -}; - -class RsFiles -{ -public: - /** - * @brief Provides file data for the GUI, media streaming or API clients. - * It may return unverified chunks. This allows streaming without having to - * wait for hashes or completion of the file. - * This function returns an unspecified amount of bytes. Either as much data - * as available or a sensible maximum. Expect a block size of around 1MiB. - * To get more data, call this function repeatedly with different offsets. - * - * @jsonapi{development,manualwrapper} - * note the wrapper for this is written manually not autogenerated - * @see JsonApiServer. - * - * @param[in] hash hash of the file. The file has to be available on this node - * or it has to be in downloading state. - * @param[in] offset where the desired block starts - * @param[inout] requested_size size of pre-allocated data. Will be updated - * by the function. - * @param[out] data pre-allocated memory chunk of size 'requested_size' by the - * client - * @return Returns false in case - * - the files is not available on the local node - * - not downloading - * - the requested data was not downloaded yet - * - end of file was reached - */ - virtual bool getFileData( const RsFileHash& hash, uint64_t offset, - uint32_t& requested_size, uint8_t* data ) = 0; - - /** - * @brief Check if we already have a file - * @jsonapi{development} - * @param[in] hash file identifier - * @param[out] info storage for the possibly found file information - * @return true if the file is already present, false otherwise - */ - virtual bool alreadyHaveFile(const RsFileHash& hash, FileInfo &info) = 0; - - /** - * @brief Initiate downloading of a file - * @jsonapi{development} - * @param[in] fileName file name - * @param[in] hash file hash - * @param[in] size file size - * @param[in] destPath optional specify the destination directory - * @param[in] flags you usually want RS_FILE_REQ_ANONYMOUS_ROUTING - * @param[in] srcIds eventually specify known sources - * @return false if we already have the file, true otherwhise - */ - virtual bool FileRequest( - const std::string& fileName, const RsFileHash& hash, uint64_t size, - const std::string& destPath, TransferRequestFlags flags, - const std::list& srcIds ) = 0; - - /** - * @brief Initiate download of a files collection - * @jsonapi{development} - * An usually useful companion method of this is @see parseFilesLink() - * @param[in] collection collection of files to download - * @param[in] destPath optional base path on which to download the - * collection, if left empty the default download directory will be used - * @param[in] srcIds optional peers id known as direct source of the - * collection - * @param[in] flags optional flags to fine tune search and download - * algorithm - * @return success or error details. - */ - virtual std::error_condition requestFiles( - const RsFileTree& collection, - const std::string& destPath = "", - const std::vector& srcIds = std::vector(), - FileRequestFlags flags = FileRequestFlags::ANONYMOUS_ROUTING ) = 0; - - /** - * @brief Cancel file downloading - * @jsonapi{development} - * @param[in] hash - * @return false if the file is not in the download queue, true otherwhise - */ - virtual bool FileCancel(const RsFileHash& hash) = 0; - - /** - * @brief Set destination directory for given file - * @jsonapi{development} - * @param[in] hash file identifier - * @param[in] newPath - * @return false if some error occurred, true otherwise - */ - virtual bool setDestinationDirectory( - const RsFileHash& hash, const std::string& newPath ) = 0; - - /** - * @brief Set name for dowloaded file - * @jsonapi{development} - * @param[in] hash file identifier - * @param[in] newName - * @return false if some error occurred, true otherwise - */ - virtual bool setDestinationName( - const RsFileHash& hash, const std::string& newName ) = 0; - - /** - * @brief Set chunk strategy for file, useful to set streaming mode to be - * able of see video or other media preview while it is still downloading - * @jsonapi{development} - * @param[in] hash file identifier - * @param[in] newStrategy - * @return false if some error occurred, true otherwise - */ - virtual bool setChunkStrategy( - const RsFileHash& hash, - FileChunksInfo::ChunkStrategy newStrategy ) = 0; - - /** - * @brief Set default chunk strategy - * @jsonapi{development} - * @param[in] strategy - */ - virtual void setDefaultChunkStrategy( - FileChunksInfo::ChunkStrategy strategy ) = 0; - - /** - * @brief Get default chunk strategy - * @jsonapi{development} - * @return current default chunck strategy - */ - virtual FileChunksInfo::ChunkStrategy defaultChunkStrategy() = 0; - - /** - * @brief Get free disk space limit - * @jsonapi{development} - * @return current minimum free space on disk in MB - */ - virtual uint32_t freeDiskSpaceLimit() const = 0; - - /** - * @brief Set minimum free disk space limit - * @jsonapi{development} - * @param[in] minimumFreeMB minimum free space in MB - */ - virtual void setFreeDiskSpaceLimit(uint32_t minimumFreeMB) = 0; - - /** - * @brief Controls file transfer - * @jsonapi{development} - * @param[in] hash file identifier - * @param[in] flags action to perform. Pict into { RS_FILE_CTRL_PAUSE, RS_FILE_CTRL_START, RS_FILE_CTRL_FORCE_CHECK } } - * @return false if error occured such as unknown hash. - */ - virtual bool FileControl(const RsFileHash& hash, uint32_t flags) = 0; - - /** - * @brief Clear completed downloaded files list - * @jsonapi{development} - * @return false on error, true otherwise - */ - virtual bool FileClearCompleted() = 0; - - virtual void setDefaultEncryptionPolicy(uint32_t policy)=0; // RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT/PERMISSIVE - virtual uint32_t defaultEncryptionPolicy()=0; - virtual void setMaxUploadSlotsPerFriend(uint32_t n)=0; - virtual uint32_t getMaxUploadSlotsPerFriend()=0; - virtual void setFilePermDirectDL(uint32_t perm)=0; - virtual uint32_t filePermDirectDL()=0; - - /** - * @brief Request remote files search - * @jsonapi{development} - * @param[in] matchString string to look for in the search. If files deep - * indexing is enabled at compile time support advanced features described - * at https://xapian.org/docs/queryparser.html - * @param multiCallback function that will be called each time a search - * result is received - * @param[in] maxWait maximum wait time in seconds for search results - * @return false on error, true otherwise - */ - virtual bool turtleSearchRequest( - const std::string& matchString, - const std::function& results)>& multiCallback, - rstime_t maxWait = 300 ) = 0; - - virtual TurtleRequestId turtleSearch(const std::string& string_to_match) = 0; - virtual TurtleRequestId turtleSearch( - const RsRegularExpression::LinearizedExpression& expr) = 0; - - /*** - * Control of Downloads Priority. - ***/ - virtual uint32_t getQueueSize() = 0 ; - virtual void setQueueSize(uint32_t s) = 0 ; - virtual bool changeQueuePosition(const RsFileHash& hash, QueueMove mv) = 0; - virtual bool changeDownloadSpeed(const RsFileHash& hash, int speed) = 0; - virtual bool getDownloadSpeed(const RsFileHash& hash, int & speed) = 0; - virtual bool clearDownload(const RsFileHash& hash) = 0; - - /** - * @brief Get incoming files list - * @jsonapi{development} - * @param[out] hashs storage for files identifiers list - */ - virtual void FileDownloads(std::list& hashs) = 0; - - /** - * @brief Get outgoing files list - * @jsonapi{development} - * @param[out] hashs storage for files identifiers list - * @return false if some error occurred, true otherwise - */ - virtual bool FileUploads(std::list& hashs) = 0; - - /** - * @brief Get file details - * @jsonapi{development} - * @param[in] hash file identifier - * @param[in] hintflags filtering hint ( RS_FILE_HINTS_UPLOAD|...| - * RS_FILE_HINTS_EXTRA|RS_FILE_HINTS_LOCAL ) - * @param[out] info storage for file information - * @return true if file found, false otherwise - */ - virtual bool FileDetails( - const RsFileHash& hash, FileSearchFlags hintflags, FileInfo& info ) = 0; - - virtual bool isEncryptedSource(const RsPeerId& virtual_peer_id) =0; - - /** - * @brief Get chunk details about the downloaded file with given hash. - * @jsonapi{development} - * @param[in] hash file identifier - * @param[out] info storage for file information - * @return true if file found, false otherwise - */ - virtual bool FileDownloadChunksDetails( - const RsFileHash& hash, FileChunksInfo& info) = 0; - - /** - * @brief Get details about the upload with given hash - * @jsonapi{development} - * @param[in] hash file identifier - * @param[in] peerId peer identifier - * @param[out] map storage for chunk info - * @return true if file found, false otherwise - */ - virtual bool FileUploadChunksDetails( - const RsFileHash& hash, const RsPeerId& peerId, - CompressedChunkMap& map ) = 0; - - /** - * @brief Remove file from extra fila shared list - * @jsonapi{development} - * @param[in] hash hash of the file to remove - * @return return false on error, true otherwise - */ - virtual bool ExtraFileRemove(const RsFileHash& hash) = 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 - * explore a whole directory tree. - * @jsonapi{development} - * @param[out] details Storage for directory details - * @param[in] handle element handle 0 for root, pass the content of - * DirDetails::child[x].ref after first call to explore deeper, be aware - * that is not a real pointer but an index used internally by RetroShare. - * @param[in] flags file search flags RS_FILE_HINTS_* - * @return false if error occurred, true otherwise - */ - virtual bool requestDirDetails( - DirDetails &details, uint64_t handle = 0, - FileSearchFlags flags = RS_FILE_HINTS_LOCAL ) = 0; - - /*** - * Directory Listing / Search Interface - */ - /** - * Kept for retrocompatibility, it was originally written for easier - * interaction with Qt. As soon as you can, you should prefer to use the - * version of this method which take `uint64_t handle` as paramether. - */ - RS_DEPRECATED_FOR(requestDirDetails) - virtual int RequestDirDetails( - void* handle, DirDetails& details, FileSearchFlags flags ) = 0; - - virtual bool findChildPointer(void *ref, int row, void *& result, FileSearchFlags flags) =0; - virtual uint32_t getType(void *ref,FileSearchFlags flags) = 0; - - virtual int SearchKeywords(std::list keywords, std::list &results,FileSearchFlags flags) = 0; - virtual int SearchKeywords(std::list keywords, std::list &results,FileSearchFlags flags,const RsPeerId& peer_id) = 0; - virtual int SearchBoolExp(RsRegularExpression::Expression * exp, std::list &results,FileSearchFlags flags) = 0; - virtual int SearchBoolExp(RsRegularExpression::Expression * exp, std::list &results,FileSearchFlags flags,const RsPeerId& peer_id) = 0; - virtual int getSharedDirStatistics(const RsPeerId& pid, SharedDirStats& stats) =0; - - /** - * @brief Ban unwanted file from being, searched and forwarded by this node - * @jsonapi{development} - * @param[in] realFileHash this is what will really enforce banning - * @param[in] filename expected name of the file, for the user to read - * @param[in] fileSize expected file size, for the user to read - * @return meaningless value - */ - virtual int banFile( const RsFileHash& realFileHash, - const std::string& filename, uint64_t fileSize ) = 0; - - /** - * @brief Remove file from unwanted list - * @jsonapi{development} - * @param[in] realFileHash hash of the file - * @return meaningless value - */ - virtual int unbanFile(const RsFileHash& realFileHash) = 0; - - /** - * @brief Get list of banned files - * @jsonapi{development} - * @param[out] bannedFiles storage for banned files information - * @return meaningless value - */ - virtual bool getPrimaryBannedFilesList( - std::map& bannedFiles ) = 0; - - /** - * @brief Check if a file is on banned list - * @jsonapi{development} - * @param[in] hash hash of the file - * @return true if the hash is on the list, false otherwise - */ - virtual bool isHashBanned(const RsFileHash& hash) = 0; - - /*** - * Utility Functions. - ***/ - virtual bool ConvertSharedFilePath(std::string path, std::string &fullpath) = 0; - - /** - * @brief Force shared directories check - * @param[in] add_safe_delay Schedule the check 20 seconds from now, to ensure to capture files written just now. - * @jsonapi{development} - */ - virtual void ForceDirectoryCheck(bool add_safe_delay=false) = 0; - - virtual void updateSinceGroupPermissionsChanged() = 0; - virtual bool InDirectoryCheck() = 0; - virtual bool copyFile(const std::string& source,const std::string& dest) = 0; - - /*** - * Directory Control - ***/ - virtual void requestDirUpdate(void *ref) =0 ; // triggers the update of the given reference. Used when browsing. - - /** - * @brief Set default complete downloads directory - * @jsonapi{development} - * @param[in] path directory path - * @return false if something failed, true otherwhise - */ - virtual bool setDownloadDirectory(const std::string& path) = 0; - - /** - * @brief Set partial downloads directory - * @jsonapi{development} - * @param[in] path directory path - * @return false if something failed, true otherwhise - */ - virtual bool setPartialsDirectory(const std::string& path) = 0; - - /** - * @brief Get default complete downloads directory - * @jsonapi{development} - * @return default completed downloads directory path - */ - virtual std::string getDownloadDirectory() = 0; - - /** - * @brief Get partial downloads directory - * @jsonapi{development} - * @return partials downloads directory path - */ - virtual std::string getPartialsDirectory() = 0; - - /** - * @brief Get list of current shared directories - * @jsonapi{development} - * @param[out] dirs storage for the list of share directories - * @return false if something failed, true otherwhise - */ - virtual bool getSharedDirectories(std::list& dirs) = 0; - - /** - * @brief Set shared directories - * @jsonapi{development} - * @param[in] dirs list of shared directories with share options - * @return false if something failed, true otherwhise - */ - virtual bool setSharedDirectories(const std::list& dirs) = 0; - - /** - * @brief Add shared directory - * @jsonapi{development} - * @param[in] dir directory to share with sharing options - * @return false if something failed, true otherwhise - */ - virtual bool addSharedDirectory(const SharedDirInfo& dir) = 0; - - /** - * @brief Updates shared directory sharing flags. - * The directory should be already shared! - * @jsonapi{development} - * @param[in] dir Shared directory with updated sharing options - * @return false if something failed, true otherwhise - */ - virtual bool updateShareFlags(const SharedDirInfo& dir) = 0; - - /** - * @brief Remove directory from shared list - * @jsonapi{development} - * @param[in] dir Path of the directory to remove from shared list - * @return false if something failed, true otherwhise - */ - virtual bool removeSharedDirectory(std::string dir) = 0; - - /// Default base URL used for files links @see exportFilesLink - static const std::string DEFAULT_FILES_BASE_URL; - - /** Link query field used to store collection files count - * @see exportFilesLink */ - static const std::string FILES_URL_COUNT_FIELD; - - /// Link query field used to store collection data @see exportFilesLink - static const std::string FILES_URL_DATA_FIELD; - - /** Link query FILES_URL_DATA_FIELD field value used to instruct the parser - * to look for the data into the link fragment - * @see exportFilesLink and parseFilesLink */ - static const std::string FILES_URL_FAGMENT_FORWARD; - - /// Link query field used to store collection name @see exportFilesLink - static const std::string FILES_URL_NAME_FIELD; - - /// Link query field used to store collection size @see exportFilesLink - static const std::string FILES_URL_SIZE_FIELD; - - /** - * @brief Export link to a collection of files - * @jsonapi{development} - * @param[out] link storage for the generated link - * @param[in] handle directory RetroShare handle - * @param[in] fragSneak when true the file data is sneaked into fragment - * instead of FILES_URL_DATA_FIELD query field, this way if using an - * http[s] link to pass around a disguised file link a misconfigured host - * attempting to visit that link with a web browser will not send the file - * data to the server thus protecting at least some of the privacy of the - * user even in a misconfiguration scenario. - * @param[in] baseUrl URL into which to sneak in the RetroShare file link - * base64, this is primarly useful to induce applications into making the - * link clickable, or to disguise the RetroShare link into a "normal" - * looking web link. If empty the collection data link will be outputted in - * plain base64 format. - * @return error information if some error occurred, 0/SUCCESS otherwise - */ - virtual std::error_condition exportCollectionLink( - std::string& link, uint64_t handle, bool fragSneak = false, - const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL ) = 0; - - /** - * @brief Export link to a file - * @jsonapi{development} - * @param[out] link @see exportCollectionLink - * @param[in] fileHash hash of the file - * @param[in] fileSize size of the file - * @param[in] fileName name of the file - * @param[in] fragSneak @see exportCollectionLink - * @param[in] baseUrl @see exportCollectionLink - * @return error @see exportCollectionLink - */ - virtual std::error_condition exportFileLink( - std::string& link, const RsFileHash& fileHash, uint64_t fileSize, - const std::string& fileName, bool fragSneak = false, - const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL ) = 0; - - /** - * @brief Parse RetroShare files link - * @jsonapi{development} - * Support also old RetroShare-gui file and collections links format. - * @param[in] link files link either in base64 or URL format - * @param[out] collection storage for parsed files link - * @return error information if some error occurred, 0/SUCCESS otherwise - */ - virtual std::error_condition parseFilesLink( - const std::string& link, RsFileTree& collection ) = 0; - - /** - * @brief Get list of ignored file name prefixes and suffixes - * @param[out] ignoredPrefixes storage for ingored prefixes - * @param[out] ignoredSuffixes storage for ingored suffixes - * @param flags RS_FILE_SHARE_FLAGS_IGNORE_* - * @return false if something failed, true otherwhise - */ - virtual bool getIgnoreLists( - std::list& ignoredPrefixes, - std::list& ignoredSuffixes, - uint32_t& flags ) = 0; - - virtual void setIgnoreLists(const std::list& ignored_prefixes, const std::list& ignored_suffixes,uint32_t flags) =0; - - virtual void setWatchPeriod(int minutes) =0; - virtual void setWatchEnabled(bool b) =0; - virtual int watchPeriod() const =0; - virtual bool watchEnabled() =0; - virtual bool followSymLinks() const=0; - virtual void setFollowSymLinks(bool b)=0 ; - virtual void togglePauseHashingProcess() =0; // pauses/resumes the hashing process. - virtual bool hashingProcessPaused() =0; - - virtual bool getShareDownloadDirectory() = 0; - virtual bool shareDownloadDirectory(bool share) = 0; - - virtual void setMaxShareDepth(int depth) =0; - virtual int maxShareDepth() const=0; - - virtual bool ignoreDuplicates() = 0; - virtual void setIgnoreDuplicates(bool ignore) = 0; - - virtual ~RsFiles() = default; -}; diff --git a/libretroshare/src/retroshare/rsflags.h b/libretroshare/src/retroshare/rsflags.h deleted file mode 100644 index 8775f1dfb..000000000 --- a/libretroshare/src/retroshare/rsflags.h +++ /dev/null @@ -1,250 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsflags.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2019 by Retroshare Team * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -/** Check if given type is a scoped enum */ -template -using rs_is_scoped_enum = std::integral_constant< bool, - std::is_enum::value && !std::is_convertible::value >; - -/** - * @brief Register enum class as flags type - * To use this macro define a scoped enum with your flag values, then register - * it as flags type passing it as parameter of this macro. - * The result will be type safe flags, that cannot be mixed up with flag of a - * different type, but that are very comfortable to operate like plain old - * integers. All commom operation like &, | or ! can be used. To convert - * the result of such operation to boolean use !!: -@code{.cpp} -RsConnectModes connect = rsConfig->getConnectModes(); -if (!!(connect & RsConnectModes::OUTGOING_TCP)) -@endcode - * - * This macro support flag fields of different lenght depending on what - * underlining type (usually from uint8_t up to uint64_t) has been declared for - * the enum class. - * If you plan to serialize those flags it is important to specify the - * underlining type of the enum otherwise different compilers may serialize a - * flag variable with different lenght, potentially causing interoperability - * issues between differents builds. - * - * Usage example: -@code{.cpp} -enum class RsGrouterItemFlags : uint32_t -{ - NONE = 0x0, - ENCRYPTED = 0x1, - SERVICE_UNKNOWN = 0x2 -}; -RS_REGISTER_ENUM_FLAGS_TYPE(RsGrouterItemFlags) -@endcode - */ -#define RS_REGISTER_ENUM_FLAGS_TYPE(eft) \ -template<> struct Rs__BitFlagsOps \ -{ \ - static_assert( std::is_enum::value, \ - "Are you trying to register a non-enum type as flags?" ); \ - static_assert( rs_is_scoped_enum::value, \ - "Are you trying to register an unscoped enum as flags?" ); \ - static constexpr bool enabled = true; \ -}; - -// By defaults types are not valid flags, so bit flags operators are disabled -template struct Rs__BitFlagsOps -{ static constexpr bool enabled = false; }; - -template -typename std::enable_if::enabled, EFT>::type -/*EFT*/ operator &(EFT lhs, EFT rhs) -{ - using u_t = typename std::underlying_type::type; - return static_cast(static_cast(lhs) & static_cast(rhs)); -} - -template -typename std::enable_if::enabled, EFT>::type -/*EFT*/ operator &=(EFT& lhs, EFT rhs) { lhs = lhs & rhs; return lhs; } - -template -typename std::enable_if::enabled, EFT>::type -/*EFT*/ operator |(EFT lhs, EFT rhs) -{ - using u_t = typename std::underlying_type::type; - return static_cast(static_cast(lhs) | static_cast(rhs)); -} - -template -typename std::enable_if::enabled, EFT>::type -/*EFT*/ operator |=(EFT& lhs, EFT rhs) { lhs = lhs | rhs; return lhs; } - - -template -typename std::enable_if::enabled, EFT>::type -/*EFT*/ operator ^(EFT lhs, EFT rhs) -{ - using u_t = typename std::underlying_type::type; - return static_cast(static_cast(lhs) ^ static_cast(rhs)); -} - -template -typename std::enable_if::enabled, EFT>::type -/*EFT*/ operator ^=(EFT& lhs, EFT rhs) { lhs = lhs ^ rhs; return lhs; } - -template -typename std::enable_if::enabled, EFT>::type -operator ~(EFT val) -{ - using u_t = typename std::underlying_type::type; - return static_cast(~static_cast(val)); -} - -template -typename std::enable_if::enabled, bool>::type -operator !(EFT val) -{ - using u_t = typename std::underlying_type::type; - return static_cast(val) == 0; -} - -/// Nicely print flags bits as 1 and 0 -template -typename std::enable_if::enabled, std::ostream>::type& -operator <<(std::ostream& stream, EFT flags) -{ - using u_t = typename std::underlying_type::type; - return stream << std::bitset(static_cast(flags)); -} - -#include -#include "util/rsdeprecate.h" - - -/** - * @deprecated t_RsFlags32 has been deprecated because the newer - * @see RS_REGISTER_ENUM_FLAGS_TYPE provide more convenient flags facilities. - * -// 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 -// mixup flags belonging to different classes. This avoids many bugs due to confusion of flags types -// that occur when all flags are uint32_t values. -// -// To use this class, define an ID that is different than other flags classes, and do a typedef: -// -// #define TRANSFER_INFO_FLAGS_TAG 0x8133ea -// typedef t_RsFlags32 TransferInfoFlags ; -// -// Implementation details: -// - we cannot have at the same time a implicit contructor from uint32_t and a bool operator, otherwise c++ -// mixes up operators and transforms flags into booleans before combining them further. -// -// So I decided to have: -// - an explicit constructor from uint32_t -// - an implicit bool operator, that allows test like if(flags & FLAGS_VALUE) -// -*/ -template class RS_DEPRECATED_FOR(RS_REGISTER_ENUM_FLAGS_TYPE) t_RsFlags32 -{ - public: - inline t_RsFlags32() : _bits(0) {} - inline explicit t_RsFlags32(uint32_t N) : _bits(N) {} // allows initialization from a set of uint32_t - - - inline t_RsFlags32 operator| (const t_RsFlags32& f) const { return t_RsFlags32(_bits | f._bits) ; } - inline t_RsFlags32 operator^ (const t_RsFlags32& f) const { return t_RsFlags32(_bits ^ f._bits) ; } - inline t_RsFlags32 operator* (const t_RsFlags32& f) const { return t_RsFlags32(_bits & f._bits) ; } - - inline bool operator!=(const t_RsFlags32& f) const { return _bits != f._bits ; } - inline bool operator==(const t_RsFlags32& f) const { return _bits == f._bits ; } - inline bool operator& (const t_RsFlags32& f) const { return (_bits & f._bits)>0 ; } - - inline t_RsFlags32 operator|=(const t_RsFlags32& f) { _bits |= f._bits ; return *this ;} - inline t_RsFlags32 operator^=(const t_RsFlags32& f) { _bits ^= f._bits ; return *this ;} - inline t_RsFlags32 operator&=(const t_RsFlags32& f) { _bits &= f._bits ; return *this ;} - - inline t_RsFlags32 operator~() const { return t_RsFlags32(~_bits) ; } - - //inline explicit operator bool() const { return _bits>0; } - inline uint32_t toUInt32() const { return _bits ; } - - /// Easier porting to new flag system - template inline - typename std::enable_if<(Rs__BitFlagsOps::enabled && - sizeof(EFT) >= sizeof(uint32_t) ), EFT>::type - toEFT() { return static_cast(_bits); } - - /// Easier porting to new flag system - template - static inline typename std::enable_if< - Rs__BitFlagsOps::enabled && - sizeof(EFT) <= sizeof(uint32_t), t_RsFlags32>::type - fromEFT(EFT e) { return t_RsFlags32(static_cast(e)); } - - void clear() { _bits = 0 ; } - - friend std::ostream& operator<<(std::ostream& o,const t_RsFlags32& f) // friendly print with 0 and I - { - for(int i=31;i>=0;--i) { - std::string res = f._bits&(1< TransferRequestFlags; - -// Flags for file storage. Mainly permissions like BROWSABLE/NETWORK_WIDE for groups and peers. -// -typedef t_RsFlags32 FileStorageFlags ; - -// Flags for searching in files that could be local, downloads, remote, etc. -// -typedef t_RsFlags32 FileSearchFlags ; - -// Service permissions. Will allow each user to use or not use each service. -// -typedef t_RsFlags32 ServicePermissionFlags ; - -// Flags for chat lobbies -// -typedef t_RsFlags32 ChatLobbyFlags ; - diff --git a/libretroshare/src/retroshare/rsgossipdiscovery.h b/libretroshare/src/retroshare/rsgossipdiscovery.h deleted file mode 100644 index 9a6e2a792..000000000 --- a/libretroshare/src/retroshare/rsgossipdiscovery.h +++ /dev/null @@ -1,116 +0,0 @@ -/******************************************************************************* - * RetroShare remote peers gossip discovery * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2008 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rstypes.h" -#include "retroshare/rsevents.h" -#include "util/rsmemory.h" - -class RsGossipDiscovery; - -/** - * Pointer to global instance of RsGossipDiscovery service implementation - * @jsonapi{development} - * - * TODO: this should become std::weak_ptr once we have a reasonable services - * management. - */ -extern std::shared_ptr rsGossipDiscovery; - -/** - * @brief Emitted when a pending PGP certificate is received - */ - -enum class RsGossipDiscoveryEventType: uint32_t { - UNKNOWN = 0x00, - FRIEND_PEER_INFO_RECEIVED = 0x01, -}; - -struct RsGossipDiscoveryEvent : RsEvent -{ - RsGossipDiscoveryEvent(): RsEvent(RsEventType::GOSSIP_DISCOVERY) {} - virtual ~RsGossipDiscoveryEvent() override {} - - RsGossipDiscoveryEventType mGossipDiscoveryEventType; - RsPeerId mFromId; - RsPeerId mAboutId; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RsEvent::serial_process(j,ctx); - RS_SERIAL_PROCESS(mGossipDiscoveryEventType); - RS_SERIAL_PROCESS(mFromId); - RS_SERIAL_PROCESS(mAboutId); - } -}; - -class RsGossipDiscovery -{ -public: - virtual ~RsGossipDiscovery() = default; - - /** - * @brief getDiscFriends get a list of all friends of a given friend - * @jsonapi{development} - * @param[in] id peer to get the friends of - * @param[out] friends list of friends (ssl id) - * @return true on success false otherwise - */ - virtual bool getDiscFriends( const RsPeerId& id, - std::list& friends ) = 0; - - /** - * @brief getDiscPgpFriends get a list of all friends of a given friend - * @jsonapi{development} - * @param[in] pgpid peer to get the friends of - * @param[out] gpg_friends list of friends (gpg id) - * @return true on success false otherwise - */ - virtual bool getDiscPgpFriends( - const RsPgpId& pgpid, std::list& gpg_friends ) = 0; - - /** - * @brief getPeerVersion get the version string of a peer. - * @jsonapi{development} - * @param[in] id peer to get the version string of - * @param[out] version version string sent by the peer - * @return true on success false otherwise - */ - virtual bool getPeerVersion(const RsPeerId& id, std::string& version) = 0; - - /** - * @brief getWaitingDiscCount get the number of queued discovery packets. - * @jsonapi{development} - * @param[out] sendCount number of queued outgoing packets - * @param[out] recvCount number of queued incoming packets - * @return true on success false otherwise - */ - virtual bool getWaitingDiscCount(size_t& sendCount, size_t& recvCount) = 0; -}; diff --git a/libretroshare/src/retroshare/rsgrouter.h b/libretroshare/src/retroshare/rsgrouter.h deleted file mode 100644 index 84349f75e..000000000 --- a/libretroshare/src/retroshare/rsgrouter.h +++ /dev/null @@ -1,108 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgrouter.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "util/rsdir.h" -#include "util/rsdeprecate.h" -#include "retroshare/rsids.h" -#include "retroshare/rsgxsifacetypes.h" -#include "rsitems/rsserviceids.h" - -typedef RsGxsId GRouterKeyId ; // we use SSLIds, so that it's easier in the GUI to mix up peer ids with grouter ids. -typedef uint32_t GRouterServiceId ; -typedef uint64_t GRouterMsgPropagationId ; - -class GRouterClientService ; -class RsGRouterGenericDataItem ; - -class RsGRouter -{ -public: - // This is the interface file for the global router service. - // - struct GRouterRoutingCacheInfo - { - GRouterMsgPropagationId mid ; - std::set local_origin; - GRouterKeyId destination ; - rstime_t routing_time; - rstime_t last_tunnel_attempt_time; - rstime_t last_sent_time; - bool receipt_available ; - uint32_t duplication_factor ; - uint32_t data_status ; - uint32_t tunnel_status ; - uint32_t data_size ; - Sha1CheckSum item_hash ; - }; - - struct GRouterPublishedKeyInfo - { - std::string description_string ; - RsGxsId authentication_key ; - uint32_t service_id ; - }; - - struct GRouterRoutingMatrixInfo - { - // Probabilities of reaching a given key for each friend. - // This concerns all known keys. - // - std::map > per_friend_probabilities ; - - // List of friend ids in the same order. Should roughly correspond to the friends that are currently online. - // - std::vector friend_ids ; - - // List of own published keys, with associated service ID - // - std::map published_keys ; - }; - - //===================================================// - // Debugging info // - //===================================================// - - virtual bool getRoutingCacheInfo(std::vector& infos) =0; - virtual bool getRoutingMatrixInfo(GRouterRoutingMatrixInfo& info) =0; - - // retrieve the routing probabilities - - //===================================================// - // Communication to other services. // - //===================================================// - - virtual bool sendData(const RsGxsId& destination, const GRouterServiceId& client_id, const uint8_t *data, uint32_t data_size, const RsGxsId& signing_id, GRouterMsgPropagationId& id) =0; - virtual bool cancel(GRouterMsgPropagationId mid) =0; - - virtual bool registerKey(const RsGxsId& authentication_id, const GRouterServiceId& client_id,const std::string& description_string)=0 ; - - //===================================================// - // Routage feedback from other services // - //===================================================// - - virtual void addRoutingClue(const GRouterKeyId& destination, const RsPeerId& source) =0; -}; - -// To access the GRouter from anywhere -// -extern RsGRouter *rsGRouter ; diff --git a/libretroshare/src/retroshare/rsgxschannels.h b/libretroshare/src/retroshare/rsgxschannels.h deleted file mode 100644 index 421417bdc..000000000 --- a/libretroshare/src/retroshare/rsgxschannels.h +++ /dev/null @@ -1,741 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxschannels.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Robert Fernie * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2019-2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "retroshare/rsgxscommon.h" -#include "serialiser/rsserializable.h" -#include "retroshare/rsturtle.h" -#include "util/rsdeprecate.h" -#include "retroshare/rsgxscircles.h" -#include "util/rsmemory.h" - -class RsGxsChannels; - -/** - * Pointer to global instance of RsGxsChannels service implementation - * @jsonapi{development} - */ -extern RsGxsChannels* rsGxsChannels; - - -struct RsGxsChannelGroup : RsSerializable, RsGxsGenericGroupData -{ - RsGxsChannelGroup() : mAutoDownload(false) {} - - std::string mDescription; - RsGxsImage mImage; - - bool mAutoDownload; - - /// @see RsSerializable - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mDescription); - RS_SERIAL_PROCESS(mImage); - RS_SERIAL_PROCESS(mAutoDownload); - } - - ~RsGxsChannelGroup() override; -}; - -struct RsGxsChannelPost : RsSerializable, RsGxsGenericMsgData -{ - RsGxsChannelPost() : mAttachmentCount(0), mCommentCount(0), mUnreadCommentCount(0), mSize(0) {} - - std::set mOlderVersions; - std::string mMsg; // UTF8 encoded. - - std::list mFiles; - uint32_t mAttachmentCount; // auto calced. - uint32_t mCommentCount; // auto calced. - uint32_t mUnreadCommentCount; // auto calced. - uint64_t mSize; // auto calced. - - RsGxsImage mThumbnail; - - /// @see RsSerializable - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mOlderVersions); - - RS_SERIAL_PROCESS(mMsg); - RS_SERIAL_PROCESS(mFiles); - RS_SERIAL_PROCESS(mAttachmentCount); - RS_SERIAL_PROCESS(mCommentCount); - RS_SERIAL_PROCESS(mUnreadCommentCount); - RS_SERIAL_PROCESS(mSize); - RS_SERIAL_PROCESS(mThumbnail); - } - - ~RsGxsChannelPost() override; -}; - - -enum class RsChannelEventCode: uint8_t -{ - UNKNOWN = 0x00, - NEW_CHANNEL = 0x01, // emitted when new channel is received - UPDATED_CHANNEL = 0x02, // emitted when existing channel is updated - NEW_MESSAGE = 0x03, // new message reeived in a particular channel (group and msg id) - UPDATED_MESSAGE = 0x04, // existing message has been updated in a particular channel - RECEIVED_PUBLISH_KEY = 0x05, // publish key for this channel has been received - SUBSCRIBE_STATUS_CHANGED = 0x06, // subscription for channel mChannelGroupId changed. - READ_STATUS_CHANGED = 0x07, // existing message has been read or set to unread - RECEIVED_DISTANT_SEARCH_RESULT = 0x08, // result for the given group id available for the given turtle request id - STATISTICS_CHANGED = 0x09, // stats (nb of supplier friends, how many msgs they have etc) has changed - SYNC_PARAMETERS_UPDATED = 0x0a, // sync and storage times have changed - NEW_COMMENT = 0x0b, // new comment arrived/published. mChannelThreadId gives the ID of the commented message - NEW_VOTE = 0x0c, // new vote arrived/published. mChannelThreadId gives the ID of the votes message comment - DELETED_CHANNEL = 0x0d, // channel was deleted by auto-cleaning system -}; - -struct RsGxsChannelEvent: RsEvent -{ - RsGxsChannelEvent(): RsEvent(RsEventType::GXS_CHANNELS), mChannelEventCode(RsChannelEventCode::UNKNOWN) {} - - RsChannelEventCode mChannelEventCode; - RsGxsGroupId mChannelGroupId; - RsGxsMessageId mChannelMsgId; - RsGxsMessageId mChannelThreadId; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - - RS_SERIAL_PROCESS(mChannelEventCode); - RS_SERIAL_PROCESS(mChannelGroupId); - RS_SERIAL_PROCESS(mChannelMsgId); - } -}; - -// This event is used to factor multiple search results notifications in a single event. - -struct RsGxsChannelSearchResultEvent: RsEvent -{ - RsGxsChannelSearchResultEvent(): - RsEvent(RsEventType::GXS_CHANNELS), - mChannelEventCode(RsChannelEventCode::RECEIVED_DISTANT_SEARCH_RESULT) {} - - RsChannelEventCode mChannelEventCode; - std::map > mSearchResultsMap; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - - RS_SERIAL_PROCESS(mChannelEventCode); - RS_SERIAL_PROCESS(mSearchResultsMap); - } -}; - -class RsGxsChannels: public RsGxsIfaceHelper, public RsGxsCommentService -{ -public: - explicit RsGxsChannels(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - - /** - * @brief Create channel. Blocking API. - * @jsonapi{development} - * @param[in] name Name of the channel - * @param[in] description Description of the channel - * @param[in] thumbnail Optional image to show as channel thumbnail. - * @param[in] authorId Optional id of the author. Leave empty for an - * anonymous channel. - * @param[in] circleType Optional visibility rule, default public. - * @param[in] circleId If the channel is not public specify the id of - * the circle who can see the channel. Depending on - * the value you pass for - * circleType this should be be an external circle - * if EXTERNAL is passed, a local friend group id - * if NODES_GROUP is passed, empty otherwise. - * @param[out] channelId Optional storage for the id of the created - * channel, 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 createChannelV2( - const std::string& name, - const std::string& description, - const RsGxsImage& thumbnail = RsGxsImage(), - const RsGxsId& authorId = RsGxsId(), - RsGxsCircleType circleType = RsGxsCircleType::PUBLIC, - const RsGxsCircleId& circleId = RsGxsCircleId(), - RsGxsGroupId& channelId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) = 0; - - /** - * @brief Add a comment on a post or on another comment. Blocking API. - * @jsonapi{development} - * @param[in] channelId Id of the channel in which the comment is to be - * posted - * @param[in] threadId Id of the post (that is a thread) in the channel - * 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 - * channel post Id or the Id of another comment. - * @param[in] origCommentId If this is supposed to replace an already - * 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 - * that was created, meaningful only on success. - * @param[out] errorMessage Optional storage for error message, meaningful - * only on failure. - * @return false on error, true otherwise - */ - virtual bool createCommentV2( - const RsGxsGroupId& channelId, - const RsGxsMessageId& threadId, - const std::string& comment, - const RsGxsId& authorId, - const RsGxsMessageId& parentId = RsGxsMessageId(), - const RsGxsMessageId& origCommentId = RsGxsMessageId(), - RsGxsMessageId& commentMessageId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) = 0; - - /** - * @brief Create channel post. Blocking API. - * @jsonapi{development} - * @param[in] channelId Id of the channel where to put the post. Beware - * you need publish rights on that channel to post. - * @param[in] title Title of the post - * @param[in] mBody Text content of the post - * @param[in] files Optional list of attached files. These are - * supposed to be already shared, - * @see ExtraFileHash() below otherwise. - * @param[in] thumbnail Optional thumbnail image for the post. - * @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] postId Optional storage for the id of the created post, - * meaningful only on success. - * @param[out] errorMessage Optional storage for the error message, - * meaningful only on failure. - * @return false on error, true otherwise - */ - virtual bool createPostV2( - const RsGxsGroupId& channelId, const std::string& title, - const std::string& mBody, - const std::list& files = std::list(), - const RsGxsImage& thumbnail = RsGxsImage(), - const RsGxsMessageId& origPostId = RsGxsMessageId(), - RsGxsMessageId& postId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Create a vote - * @jsonapi{development} - * @param[in] channelId Id of the channel where to vote - * @param[in] postId Id of the channel post of which a comment is - * voted. - * @param[in] commentId Id of the comment that is voted - * @param[in] authorId Id of the author. Needs to be of an owned - * identity. - * @param[in] vote Vote value, either RsGxsVoteType::DOWN or - * RsGxsVoteType::UP - * @param[out] voteId Optional storage for the id of the created vote, - * meaningful only on success. - * @param[out] errorMessage Optional storage for error message, meaningful - * only on failure. - * @return false on error, true otherwise - */ - virtual bool createVoteV2( - const RsGxsGroupId& channelId, const RsGxsMessageId& postId, - const RsGxsMessageId& commentId, const RsGxsId& authorId, - RsGxsVoteType vote, - RsGxsMessageId& voteId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Edit channel details. - * @jsonapi{development} - * @param[in] channel Channel data (name, description...) with modifications - * @return false on error, true otherwise - */ - virtual bool editChannel(RsGxsChannelGroup& channel) = 0; - - /** - * @brief Share extra file - * Can be used to share extra file attached to a channel post - * @jsonapi{development} - * @param[in] path file path - * @return false on error, true otherwise - */ - virtual bool ExtraFileHash(const std::string& path) = 0; - - /** - * @brief Remove extra file from shared files - * @jsonapi{development} - * @param[in] hash hash of the file to remove - * @return false on error, true otherwise - */ - virtual bool ExtraFileRemove(const RsFileHash& hash) = 0; - - /** - * @brief Get channels summaries list. Blocking API. - * @jsonapi{development} - * @param[out] channels list where to store the channels - * @return false if something failed, true otherwhise - */ - virtual bool getChannelsSummaries(std::list& channels) = 0; - - /** - * @brief Get channels information (description, thumbnail...). - * Blocking API. - * @jsonapi{development} - * @param[in] chanIds ids of the channels of which to get the informations - * @param[out] channelsInfo storage for the channels informations - * @return false if something failed, true otherwhise - */ - virtual bool getChannelsInfo( - const std::list& chanIds, - std::vector& channelsInfo ) = 0; - - /** - * @brief Get all channel messages, comments and votes in a given channel - * @note It's the client's responsibility to figure out which message (resp. comment) - * a comment (resp. vote) refers to. - * - * @jsonapi{development} - * @param[in] channelId id of the channel of which the content is requested - * @param[out] posts storage for posts - * @param[out] comments storage for the comments - * @param[out] votes storage for votes - * @return false if something failed, true otherwhise - */ - virtual bool getChannelAllContent( const RsGxsGroupId& channelId, - std::vector& posts, - std::vector& comments, - std::vector& votes ) = 0; - - /** - * @brief Get channel messages, comments and votes corresponding to the given IDs. - * @note Since comments are internally themselves messages, this function actually - * returns the data for messages, comments or votes that have the given ID. - * It *does not* automatically retrieve the comments or votes for a given message - * which Id you supplied. - * - * @jsonapi{development} - * @param[in] channelId id of the channel of which the content is requested - * @param[in] contentsIds ids of requested contents - * @param[out] posts storage for posts - * @param[out] comments storage for the comments - * @param[out] votes storage for the votes - * @return false if something failed, true otherwhise - */ - virtual bool getChannelContent( const RsGxsGroupId& channelId, - const std::set& contentsIds, - std::vector& posts, - std::vector& comments, - std::vector& votes ) = 0; - - /** - * @brief Get channel comments corresponding to the given message IDs. - * If the set is empty, nothing is returned. - * - * @jsonapi{development} - * @param[in] channelId id of the channel of which the content is requested - * @param[in] contentIds ids of requested contents - * @param[out] comments storage for the comments - * @return false if something failed, true otherwhise - */ - virtual bool getChannelComments(const RsGxsGroupId &channelId, - const std::set &contentIds, - std::vector &comments) = 0; - - /** - * @brief Get channel content summaries - * @jsonapi{development} - * @param[in] channelId id of the channel of which the content is requested - * @param[out] summaries storage for summaries - * @return false if something failed, true otherwhise - */ - virtual bool getContentSummaries( const RsGxsGroupId& channelId, - std::vector& summaries ) = 0; - - /** - * @brief Toggle post read status. Blocking API. - * @jsonapi{development} - * @param[in] postId post identifier - * @param[in] read true to mark as read, false to mark as unread - * @return false on error, true otherwise - */ - virtual bool markRead(const RsGxsGrpMsgIdPair& postId, bool read) = 0; - - /** - * @brief Share channel publishing key - * This can be used to authorize other peers to post on the channel - * @jsonapi{development} - * @param[in] channelId id of the channel - * @param[in] peers peers to share the key with - * @return false on error, true otherwise - */ - virtual bool shareChannelKeys( - const RsGxsGroupId& channelId, const std::set& peers ) = 0; - - /** - * @brief Subscrbe to a channel. Blocking API - * @jsonapi{development} - * @param[in] channelId Channel id - * @param[in] subscribe true to subscribe, false to unsubscribe - * @return false on error, true otherwise - */ - virtual bool subscribeToChannel( const RsGxsGroupId& channelId, - bool subscribe ) = 0; - - /** - * \brief Retrieve statistics about the channel service - * @jsonapi{development} - * \param[out] stat Statistics structure - * \return - */ - virtual bool getChannelServiceStatistics(GxsServiceStatistic& stat) =0; - - /** - * \brief Retrieve statistics about the given channel - * @jsonapi{development} - * \param[in] channelId Id of the channel group - * \param[out] stat Statistics structure - * \return - */ - virtual bool getChannelStatistics(const RsGxsGroupId& channelId,GxsGroupStatistic& stat) =0; - - /// default base URL used for channels links @see exportChannelLink - static const std::string DEFAULT_CHANNEL_BASE_URL; - - /// Link query field used to store channel name @see exportChannelLink - static const std::string CHANNEL_URL_NAME_FIELD; - - /// Link query field used to store channel id @see exportChannelLink - static const std::string CHANNEL_URL_ID_FIELD; - - /// Link query field used to store channel data @see exportChannelLink - static const std::string CHANNEL_URL_DATA_FIELD; - - /** Link query field used to store channel message title - * @see exportChannelLink */ - static const std::string CHANNEL_URL_MSG_TITLE_FIELD; - - /// Link query field used to store channel message id @see exportChannelLink - static const std::string CHANNEL_URL_MSG_ID_FIELD; - - /** - * @brief Get link to a channel - * @jsonapi{development} - * @param[out] link storage for the generated link - * @param[in] chanId Id of the channel of which we want to generate a link - * @param[in] includeGxsData if true include the channel GXS group data so - * the receiver can subscribe to the channel even if she hasn't received it - * through GXS yet - * @param[in] baseUrl URL into which to sneak in the RetroShare link - * radix, this is primarly useful to induce applications into making the - * link clickable, or to disguise the RetroShare link into a - * "normal" looking web link. If empty the GXS data link will be outputted - * in plain base64 format. - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if something failed, true otherwhise - */ - virtual bool exportChannelLink( - std::string& link, const RsGxsGroupId& chanId, - bool includeGxsData = true, - const std::string& baseUrl = RsGxsChannels::DEFAULT_CHANNEL_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Import channel from full link - * @jsonapi{development} - * @param[in] link channel link either in radix or link format - * @param[out] chanId optional storage for parsed channel id - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if some error occurred, true otherwise - */ - virtual bool importChannelLink( - const std::string& link, - RsGxsGroupId& chanId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Search the turtle reachable network for matching channels - * @jsonapi{development} - * An @see RsGxsChannelSearchResultEvent is emitted when matching channels - * arrives from the network - * @param[in] matchString string to search into the channels - * @return search id - */ - virtual TurtleRequestId turtleSearchRequest(const std::string& matchString)=0; - - /** - * @brief Retrieve available search results - * @jsonapi{development} - * @param[in] searchId search id - * @param[out] results storage for search results - * @return false on error, true otherwise - */ - virtual bool retrieveDistantSearchResults( - TurtleRequestId searchId, - std::map& results ) = 0; - - /** - * @brief Request distant channel details - * @jsonapi{development} - * An @see RsGxsChannelSearchResultEvent is emitted once details are - * retrieved from the network - * @param[in] groupId if of the group to request to the network - * @return search id - */ - virtual TurtleRequestId turtleGroupRequest(const RsGxsGroupId& groupId) = 0; - - /** - * @brief Retrieve previously requested distant group - * @jsonapi{development} - * @param[in] groupId if of teh group - * @param[out] distantGroup storage for group data - * @return false on error, true otherwise - */ - virtual bool getDistantSearchResultGroupData(const RsGxsGroupId& groupId, RsGxsChannelGroup& distantGroup ) = 0; - - /** - * @brief getDistantSearchStatus - * Returns the status of ongoing search: unknown (probably not even searched), known as a search result, - * data request ongoing and data available - */ - virtual DistantSearchGroupStatus getDistantSearchStatus(const RsGxsGroupId& group_id) =0; - - /** - * @brief Clear accumulated search results - * @jsonapi{development} - * @param[in] reqId search id - * @return false on error, true otherwise - */ - virtual bool clearDistantSearchResults(TurtleRequestId reqId) = 0; - - ~RsGxsChannels() override; - - //////////////////////////////////////////////////////////////////////////// - /* Following functions are deprecated and should not be considered a safe to - * use API */ - - /** - * @brief Get auto-download option value for given channel - * @jsonapi{development} - * @deprecated This feature rely on very buggy code, the returned value is - * not reliable @see setChannelAutoDownload(). - * @param[in] channelId channel id - * @param[out] enabled storage for the auto-download option value - * @return false if something failed, true otherwhise - */ - RS_DEPRECATED - virtual bool getChannelAutoDownload( - const RsGxsGroupId& channelId, bool& enabled ) = 0; - - /** - * @brief Enable or disable auto-download for given channel. Blocking API - * @jsonapi{development} - * @deprecated This feature rely on very buggy code, when enabled the - * channel service start flooding erratically log with error messages, - * apparently without more dangerous consequences. Still those messages - * hints that something out of control is happening under the hood, use at - * your own risk. A safe alternative to this method can easly implemented - * at API client level instead. - * @param[in] channelId channel id - * @param[in] enable true to enable, false to disable - * @return false if something failed, true otherwhise - */ - RS_DEPRECATED - virtual bool setChannelAutoDownload( - const RsGxsGroupId& channelId, bool enable ) = 0; - - /** - * @brief Get download directory for the given channel - * @jsonapi{development} - * @deprecated @see setChannelAutoDownload() - * @param[in] channelId id of the channel - * @param[out] directory reference to string where to store the path - * @return false on error, true otherwise - */ - RS_DEPRECATED - virtual bool getChannelDownloadDirectory( const RsGxsGroupId& channelId, - std::string& directory ) = 0; - - /** - * @brief Set download directory for the given channel. Blocking API. - * @jsonapi{development} - * @deprecated @see setChannelAutoDownload() - * @param[in] channelId id of the channel - * @param[in] directory path - * @return false on error, true otherwise - */ - RS_DEPRECATED - virtual bool setChannelDownloadDirectory( - const RsGxsGroupId& channelId, const std::string& directory) = 0; - - /** - * @brief Create channel. Blocking API. - * @jsonapi{development} - * @deprecated { substituted by createChannelV2 } - * @param[inout] channel Channel data (name, description...) - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(createChannelV2) - virtual bool createChannel(RsGxsChannelGroup& channel) = 0; - - RS_DEPRECATED_FOR(getChannelsInfo) - virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; - - RS_DEPRECATED_FOR(getChannelContent) - virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts, std::vector &votes) = 0; - - RS_DEPRECATED_FOR(getChannelContent) - virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts) = 0; - - RS_DEPRECATED_FOR(getChannelContent) - virtual bool getPostData(const uint32_t &token, std::vector &posts) = 0; - - /** - * @brief toggle message read status - * @deprecated - * @param[out] token GXS token queue token - * @param[in] msgId - * @param[in] read - */ - RS_DEPRECATED_FOR(markRead) - virtual void setMessageReadStatus( - uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0; - - /** - * @brief Share channel publishing key - * This can be used to authorize other peers to post on the channel - * @deprecated - * @param[in] groupId Channel id - * @param[in] peers peers to which share the key - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(shareChannelKeys) - virtual bool groupShareKeys( - const RsGxsGroupId& groupId, const std::set& peers ) = 0; - - /** - * @brief Request subscription to a group. - * The action is performed asyncronously, so it could fail in a subsequent - * phase even after returning true. - * @deprecated - * @param[out] token Storage for RsTokenService token to track request - * status. - * @param[in] groupId Channel id - * @param[in] subscribe - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(subscribeToChannel) - virtual bool subscribeToGroup( uint32_t& token, const RsGxsGroupId &groupId, - bool subscribe ) = 0; - - /** - * @brief Request channel creation. - * The action is performed asyncronously, so it could fail in a subsequent - * phase even after returning true. - * @deprecated - * @param[out] token Storage for RsTokenService token to track request - * status. - * @param[in] group Channel data (name, description...) - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(createChannelV2) - virtual bool createGroup(uint32_t& token, RsGxsChannelGroup& group) = 0; - - /** - * @brief Add a comment on a post or on another comment - * @jsonapi{development} - * @deprecated - * @param[inout] comment - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(createCommentV2) - virtual bool createComment(RsGxsComment& comment) = 0; - - /** - * @brief Create channel post. Blocking API. - * @jsonapi{development} - * @deprecated - * @param[inout] post - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(createPostV2) - virtual bool createPost(RsGxsChannelPost& post) = 0; - - /** - * @brief Request post creation. - * The action is performed asyncronously, so it could fail in a subsequent - * phase even after returning true. - * @deprecated - * @param[out] token Storage for RsTokenService token to track request - * status. - * @param[in] post - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(createPostV2) - virtual bool createPost(uint32_t& token, RsGxsChannelPost& post) = 0; - - /** - * @brief createVote - * @jsonapi{development} - * @deprecated - * @param[inout] vote - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(createVoteV2) - virtual bool createVote(RsGxsVote& vote) = 0; - - /** - * @brief Request channel change. - * The action is performed asyncronously, so it could fail in a subsequent - * phase even after returning true. - * @deprecated - * @param[out] token Storage for RsTokenService token to track request - * status. - * @param[in] group Channel data (name, description...) with modifications - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(editChannel) - virtual bool updateGroup(uint32_t& token, RsGxsChannelGroup& group) = 0; -}; diff --git a/libretroshare/src/retroshare/rsgxscircles.h b/libretroshare/src/retroshare/rsgxscircles.h deleted file mode 100644 index 32bc8e547..000000000 --- a/libretroshare/src/retroshare/rsgxscircles.h +++ /dev/null @@ -1,525 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxscircles.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rstypes.h" -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "retroshare/rsidentity.h" -#include "serialiser/rsserializable.h" -#include "util/rsmemory.h" - - -class RsGxsCircles; - -/** - * Pointer to global instance of RsGxsCircles service implementation - * @jsonapi{development} - */ -extern RsGxsCircles* rsGxsCircles; - -enum class RsGxsCircleType : uint32_t // 32 bit overkill, just for retrocompat -{ - UNKNOWN = 0, /// Used to detect uninizialized values. - PUBLIC = 1, /// Public distribution, based on GxsIds - EXTERNAL = 2, /// Restricted to an external circle, based on GxsIds - - NODES_GROUP = 3, /// Restricted to a group of friend nodes, the administrator of the circle behave as a hub for them - /// Based on PGP nodes ids. - - LOCAL = 4, /// not distributed at all - - /** Self-restricted. Used only at creation time of self-restricted circles - * when the circle id isn't known yet. Once the circle id is known the type - * is set to EXTERNAL, and the external circle id is set to the id of the - * circle itself. Based on GxsIds. - */ - EXT_SELF = 5, - - YOUR_EYES_ONLY = 6 /// distributed to nodes signed by your own PGP key only. -}; - -// TODO: convert to enum class -static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST = 0x0001 ;// user is validated by circle admin -static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED = 0x0002 ;// user has subscribed the group -static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE = 0x0004 ;// key is available, so we can encrypt for this circle -static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_ALLOWED = 0x0007 ;// user is allowed. Combines all flags above. - - -struct RsGxsCircleGroup : RsSerializable -{ - RsGroupMetaData mMeta; - - std::set mLocalFriends; - std::set mInvitedMembers; - std::set mSubCircles; -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_UNNAMED -# error "Add description, and multiple owners/administrators to circles" - // or better in general to GXS groups -#endif - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mLocalFriends); - RS_SERIAL_PROCESS(mInvitedMembers); - RS_SERIAL_PROCESS(mSubCircles); - } - - ~RsGxsCircleGroup() override; -}; - -enum class RsGxsCircleSubscriptionType:uint8_t { - UNKNOWN = 0x00, - SUBSCRIBE = 0x01, - UNSUBSCRIBE = 0x02 -}; - -struct RsGxsCircleMsg : RsSerializable -{ - RsMsgMetaData mMeta; - -#ifdef TO_REMOVE - // This item is actually totally unused, so we can change it no problem -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_UNNAMED - /* This is horrible and should be changed into yet to be defined something - * reasonable in next non-retrocompatible version */ - std::string stuff; -#endif -#endif - RsGxsCircleSubscriptionType mSubscriptionType; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mSubscriptionType); - } - - ~RsGxsCircleMsg() override; -}; - -struct RsGxsCircleDetails : RsSerializable -{ - RsGxsCircleDetails() : mCircleType(RsGxsCircleType::EXTERNAL), mAmIAllowed(false),mAmIAdmin(false) {} - ~RsGxsCircleDetails() override; - - // helper functions. - bool isIdInCircle(const RsGxsId& id) const { return mAllowedGxsIds.find(id) != mAllowedGxsIds.end(); } - bool isIdInInviteeList(const RsGxsId& id) const - { - auto it = mSubscriptionFlags.find(id); - return (it != mSubscriptionFlags.end()) && (it->second & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST ); - } - bool isIdRequestingMembership(const RsGxsId& id) const - { - auto it = mSubscriptionFlags.find(id); - return it != mSubscriptionFlags.end() && (it->second & GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED ); - } - bool isGxsIdBased() const { return mCircleType==RsGxsCircleType::PUBLIC || mCircleType==RsGxsCircleType::EXTERNAL || mCircleType==RsGxsCircleType::EXT_SELF; } - - // Members - - RsGxsCircleId mCircleId; - std::string mCircleName; - - RsGxsCircleType mCircleType; - RsGxsCircleId mRestrictedCircleId; - - /** true when one of load GXS ids belong to the circle allowed list (admin - * list & subscribed list). */ - bool mAmIAllowed; - - /// true when we're an administrator of the circle group, meaning that we can add/remove members from the invitee list. - bool mAmIAdmin; - - /// This crosses admin list and subscribed list - std::set mAllowedGxsIds; - std::set mAllowedNodes; - - /// subscription flags for all ids - std::map mSubscriptionFlags; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(mCircleId); - RS_SERIAL_PROCESS(mCircleName); - RS_SERIAL_PROCESS(mCircleType); - RS_SERIAL_PROCESS(mRestrictedCircleId); - RS_SERIAL_PROCESS(mAmIAllowed); - RS_SERIAL_PROCESS(mAmIAdmin); - RS_SERIAL_PROCESS(mAllowedGxsIds); - RS_SERIAL_PROCESS(mAllowedNodes); - RS_SERIAL_PROCESS(mSubscriptionFlags); - } -}; - - -enum class RsGxsCircleEventCode: uint8_t -{ - // Notifications be only have 4 different possibilities: - // - // invitee list join/leave and - // membership request / leave request - // - // From there, depending on what the client displays, it is possible to interpret these - // as "some user joined the circle", or "membership pending for that Id", etc, depending - // on whether the current node owns the circle, or the admin is or is not yours. - // - // These should be decided in the UI based on what the circle cache is displaying. - // - UNKNOWN = 0x00, - - /** - * Sent when we receive a membership request msg for a particular circle. - * - * mCircleId contains the circle id and mGxsId is the id requesting membership */ - CIRCLE_MEMBERSHIP_REQUEST = 0x01, - - /** - * Sent when the ID has been added to the circle invitee list. - * - * mCircleId is the circle that invites me, and mGxsId is my own Id that is invited */ - CIRCLE_MEMBERSHIP_ID_ADDED_TO_INVITEE_LIST = 0x02, - - /** - * Sent when a GxsId annouces its will to not be in the circle. - * - * mCircleId contains the circle id and mGxsId is the id dropping membership */ - CIRCLE_MEMBERSHIP_LEAVE = 0x03, - - /** - * Sent when the Id has been removed from the invitee list. - * - * mCircleId contains the circle id and mGxsId is the id that was revoqued * by admin */ - CIRCLE_MEMBERSHIP_ID_REMOVED_FROM_INVITEE_LIST = 0x04, - - /** - * Means a new circle has been received. - * - * mCircleId contains the circle id */ - NEW_CIRCLE = 0x05, - - /** - * Means that the circle cache has updated, and membership status that is displayed should probably be updated to. - * - * no additional information. Simply means that the info previously from the cache has changed. */ - CACHE_DATA_UPDATED = 0x06, - - /** - * The circle has been deleted by auto-cleaning. - * */ - CIRCLE_DELETED = 0x07, - - /** - * Circle has been updated (name, parent circle, type, etc) - * */ - CIRCLE_UPDATED = 0x08, -}; - -struct RsGxsCircleEvent: RsEvent -{ - RsGxsCircleEvent() - : RsEvent(RsEventType::GXS_CIRCLES), - mCircleEventType(RsGxsCircleEventCode::UNKNOWN) {} - - - RsGxsCircleEventCode mCircleEventType; - RsGxsCircleId mCircleId; - RsGxsId mGxsId; - - ///* @see RsEvent @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mCircleEventType); - RS_SERIAL_PROCESS(mCircleId); - RS_SERIAL_PROCESS(mGxsId); - } - - ~RsGxsCircleEvent() override; -}; - -class RsGxsCircles: public RsGxsIfaceHelper -{ -public: - - RsGxsCircles(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - virtual ~RsGxsCircles(); - - /** - * @brief Create new circle - * @jsonapi{development} - * @param[in] circleName String containing cirlce name - * @param[in] circleType Circle type - * @param[out] circleId Optional storage to output created circle id - * @param[in] restrictedId Optional id of a pre-existent circle that see the - * created circle. Meaningful only if circleType == EXTERNAL, must be null - * in all other cases. - * @param[in] authorId Optional author of the circle. - * @param[in] gxsIdMembers GXS ids of the members of the circle. - * @param[in] localMembers PGP ids of the members if the circle. - * @return false if something failed, true otherwhise - */ - virtual bool createCircle( - const std::string& circleName, RsGxsCircleType circleType, - RsGxsCircleId& circleId = RS_DEFAULT_STORAGE_PARAM(RsGxsCircleId), - const RsGxsCircleId& restrictedId = RsGxsCircleId(), - const RsGxsId& authorId = RsGxsId(), - const std::set& gxsIdMembers = std::set(), - const std::set& localMembers = std::set() ) = 0; - -// TODO. If so, remove the other editCircle that has the same name, otherwise jsonapi will crash -// -// /** -// * @brief Edit an existing circle -// * @jsonapi{development} -// * @param[in] circleId Optional storage to output created circle id -// * @param[in] circleName String containing cirlce name -// * @param[in] circleType Circle type -// * @param[in] restrictedId Optional id of a pre-existent circle that see the -// * created circle. Meaningful only if circleType == EXTERNAL, must be null -// * in all other cases. -// * @param[in] authorId Optional author of the circle. -// * @param[in] gxsIdMembers GXS ids of the members of the circle. -// * @param[in] localMembers PGP ids of the members if the circle. -// * @return false if something failed, true otherwhise -// */ -// virtual bool editCircle( const RsGxsCircleId& circleId, const std::string& circleName, RsGxsCircleType circleType, -// const RsGxsCircleId& restrictedId, -// const RsGxsId& authorId, const std::set& gxsIdMembers, -// const std::set& localMembers ) =0; - - /** - * @brief Edit own existing circle - * @jsonapi{development} - * @param[inout] cData Circle data with modifications, storage for data - * updatedad during the operation. - * @return false if something failed, true otherwhise - */ - virtual bool editCircle(RsGxsCircleGroup& cData) = 0; - - /** - * @brief Get circle details. Memory cached - * @jsonapi{development} - * @param[in] id Id of the circle - * @param[out] details Storage for the circle details - * @return false if something failed, true otherwhise - */ - virtual bool getCircleDetails(const RsGxsCircleId& id, RsGxsCircleDetails& details ) = 0; - - /** - * @brief Get list of known external circles ids. Memory cached - * @jsonapi{development} - * @param[in] circleIds Storage for circles id list - * @return false if something failed, true otherwhise - */ - virtual bool getCircleExternalIdList(std::set& circleIds ) = 0; - - /** - * @brief Get circles summaries list. - * @jsonapi{development} - * @param[out] circles list where to store the circles summaries - * @return false if something failed, true otherwhise - */ - virtual bool getCirclesSummaries(std::list& circles) = 0; - - /** - * @brief Get circles information - * @jsonapi{development} - * @param[in] circlesIds ids of the circles of which to get the informations - * @param[out] circlesInfo storage for the circles informations - * @return false if something failed, true otherwhise - */ - virtual bool getCirclesInfo( - const std::list& circlesIds, - std::vector& circlesInfo ) = 0; - - /** - * @brief Get circle requests - * @jsonapi{development} - * @param[in] circleId id of the circle of which the requests are requested - * @param[out] requests storage for the circle requests - * @return false if something failed, true otherwhise - */ - virtual bool getCircleRequests( const RsGxsGroupId& circleId, - std::vector& requests ) = 0; - /** - * @brief Get specific circle request - * @jsonapi{development} - * @param[in] circleId id of the circle of which the requests are requested - * @param[in] msgId id of the request - * @param[out] msg storage for the circle request - * @return false if something failed, true otherwhise - */ - virtual bool getCircleRequest(const RsGxsGroupId& circleId, - const RsGxsMessageId& msgId, - RsGxsCircleMsg& msg) =0; - - /** - * @brief Invite identities to circle (admin key is required) - * @jsonapi{development} - * @param[in] identities ids of the identities to invite - * @param[in] circleId Id of the circle you own and want to invite ids in - * @return false if something failed, true otherwhise - */ - virtual bool inviteIdsToCircle( const std::set& identities, - const RsGxsCircleId& circleId ) = 0; - - /** - * @brief Remove identities from circle (admin key is required) - * @jsonapi{development} - * @param[in] identities ids of the identities to remove from the invite list - * @param[in] circleId Id of the circle you own and want to invite ids in - * @return false if something failed, true otherwhise - */ - virtual bool revokeIdsFromCircle( const std::set& identities, - const RsGxsCircleId& circleId ) = 0; - - /** - * @brief Request circle membership, or accept circle invitation - * @jsonapi{development} - * @param[in] ownGxsId Id of own identity to introduce to the circle - * @param[in] circleId Id of the circle to which ask for inclusion - * @return false if something failed, true otherwhise - */ - virtual bool requestCircleMembership( - const RsGxsId& ownGxsId, const RsGxsCircleId& circleId ) = 0; - - /** - * @brief Leave given circle - * @jsonapi{development} - * @param[in] ownGxsId Own id to remove from the circle - * @param[in] circleId Id of the circle to leave - * @return false if something failed, true otherwhise - */ - virtual bool cancelCircleMembership( - const RsGxsId& ownGxsId, const RsGxsCircleId& circleId ) = 0; - - /// default base URL used for circle links @see exportCircleLink - static const std::string DEFAULT_CIRCLE_BASE_URL; - - /// Circle link query field used to store circle name @see exportCircleLink - static const std::string CIRCLE_URL_NAME_FIELD; - - /// Circle link query field used to store circle id @see exportCircleLink - static const std::string CIRCLE_URL_ID_FIELD; - - /// Circle link query field used to store circle data @see exportCircleLink - static const std::string CIRCLE_URL_DATA_FIELD; - - /** - * @brief Get link to a circle - * @jsonapi{development} - * @param[out] link storage for the generated link - * @param[in] circleId Id of the circle of which we want to generate a link - * @param[in] includeGxsData if true include the circle GXS group data so - * the receiver can request circle membership even if the circle hasn't - * propagated through GXS to her yet - * @param[in] baseUrl URL into which to sneak in the RetroShare circle link - * radix, this is primarly useful to induce applications into making the - * link clickable, or to disguise the RetroShare circle link into a - * "normal" looking web link. If empty the circle data link will be - * outputted in plain base64 format. - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if something failed, true otherwhise - */ - virtual bool exportCircleLink( - std::string& link, const RsGxsCircleId& circleId, - bool includeGxsData = true, - const std::string& baseUrl = RsGxsCircles::DEFAULT_CIRCLE_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Import circle from full link - * @param[in] link circle link either in radix or link format - * @param[out] circleId optional storage for parsed circle id - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if some error occurred, true otherwise - */ - virtual bool importCircleLink( - const std::string& link, - RsGxsCircleId& circleId = RS_DEFAULT_STORAGE_PARAM(RsGxsCircleId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - RS_DEPRECATED_FOR("getCirclesSummaries getCirclesInfo") - virtual bool getGroupData( - const uint32_t& token, std::vector& groups ) = 0; - - RS_DEPRECATED_FOR(getCirclesRequests) - virtual bool getMsgData( - const uint32_t& token, std::vector& msgs ) = 0; - - /// make new group - RS_DEPRECATED_FOR(createCircle) - virtual void createGroup(uint32_t& token, RsGxsCircleGroup &group) = 0; - - /// update an existing group - RS_DEPRECATED_FOR("editCircle, inviteIdsToCircle") - virtual void updateGroup(uint32_t &token, RsGxsCircleGroup &group) = 0; -}; - - -/// @deprecated Used to detect uninizialized values. -RS_DEPRECATED_FOR("RsGxsCircleType::UNKNOWN") -static const uint32_t GXS_CIRCLE_TYPE_UNKNOWN = 0x0000; - -/// @deprecated not restricted to a circle -RS_DEPRECATED_FOR("RsGxsCircleType::PUBLIC") -static const uint32_t GXS_CIRCLE_TYPE_PUBLIC = 0x0001; - -/// @deprecated restricted to an external circle, made of RsGxsId -RS_DEPRECATED_FOR("RsGxsCircleType::EXTERNAL") -static const uint32_t GXS_CIRCLE_TYPE_EXTERNAL = 0x0002; - -/// @deprecated restricted to a subset of friend nodes of a given RS node given -/// by a RsPgpId list -RS_DEPRECATED_FOR("RsGxsCircleType::NODES_GROUP") -static const uint32_t GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY = 0x0003; - -/// @deprecated not distributed at all -RS_DEPRECATED_FOR("RsGxsCircleType::LOCAL") -static const uint32_t GXS_CIRCLE_TYPE_LOCAL = 0x0004; - -/// @deprecated self-restricted. Not used, except at creation time when the -/// circle ID isn't known yet. Set to EXTERNAL afterwards. -RS_DEPRECATED_FOR("RsGxsCircleType::EXT_SELF") -static const uint32_t GXS_CIRCLE_TYPE_EXT_SELF = 0x0005; - -/// @deprecated distributed to nodes signed by your own PGP key only. -RS_DEPRECATED_FOR("RsGxsCircleType::YOUR_EYES_ONLY") -static const uint32_t GXS_CIRCLE_TYPE_YOUR_EYES_ONLY = 0x0006; diff --git a/libretroshare/src/retroshare/rsgxscommon.h b/libretroshare/src/retroshare/rsgxscommon.h deleted file mode 100644 index c820e1999..000000000 --- a/libretroshare/src/retroshare/rsgxscommon.h +++ /dev/null @@ -1,190 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxscommon.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "rsgxsifacetypes.h" -#include "serialiser/rsserializable.h" - -struct RsGxsFile : RsSerializable -{ - RsGxsFile(); - std::string mName; - RsFileHash mHash; - uint64_t mSize; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mName); - RS_SERIAL_PROCESS(mHash); - RS_SERIAL_PROCESS(mSize); - } - - void clear() - { - mName.clear(); - mHash.clear(); - mSize = 0; - } -}; - -struct RsGxsImage : RsSerializable -{ - RsGxsImage(); - ~RsGxsImage(); - - /// Use copy constructor and duplicate memory. - RsGxsImage(const RsGxsImage& a); - - RsGxsImage &operator=(const RsGxsImage &a); // Need this as well? - - /** NB: Must make sure that we always use methods - to be consistent about - * malloc/free for this data. */ - static uint8_t *allocate(uint32_t size); - static void release(void *data); - - void take(uint8_t *data, uint32_t size); // Copies Pointer. - void copy(uint8_t *data, uint32_t size); // Allocates and Copies. - void clear(); // Frees. - void shallowClear(); // Clears Pointer. - bool empty() const; - - uint32_t mSize; - uint8_t* mData; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RsTypeSerializer::TlvMemBlock_proxy b(mData, mSize); - RsTypeSerializer::serial_process(j, ctx, b, "mData"); - } -}; - -enum class RsGxsVoteType : uint32_t -{ - NONE = 0, /// Used to detect unset vote? - DOWN = 1, /// Negative vote - UP = 2 /// Positive vote -}; - - -// Status Flags to indicate Voting.... -// All Services that use the Comment service must not Use This space. -namespace GXS_SERV { - /* Msg Vote Status */ - static const uint32_t GXS_MSG_STATUS_GXSCOMMENT_MASK = 0x000f0000; - static const uint32_t GXS_MSG_STATUS_VOTE_MASK = 0x00030000; - - static const uint32_t GXS_MSG_STATUS_VOTE_UP = 0x00010000; - static const uint32_t GXS_MSG_STATUS_VOTE_DOWN = 0x00020000; -} - - - - -struct RsGxsVote : RsSerializable -{ - RsGxsVote(); - RsMsgMetaData mMeta; - uint32_t mVoteType; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mVoteType); - } -}; - -struct RsGxsComment : RsSerializable -{ - RsGxsComment(); - RsMsgMetaData mMeta; - std::string mComment; - - // below is calculated. - uint32_t mUpVotes; - uint32_t mDownVotes; - double mScore; - - uint32_t mOwnVote; - - // This is filled in if detailed Comment Data is called. - std::list mVotes; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mComment); - RS_SERIAL_PROCESS(mUpVotes); - RS_SERIAL_PROCESS(mDownVotes); - RS_SERIAL_PROCESS(mScore); - RS_SERIAL_PROCESS(mOwnVote); - RS_SERIAL_PROCESS(mVotes); - } -}; - - -struct RsGxsCommentService -{ - RsGxsCommentService() {} - virtual ~RsGxsCommentService() {} - - /** Get previously requested comment data with token */ - virtual bool getCommentData( uint32_t token, - std::vector &comments ) = 0; - virtual bool getRelatedComments( uint32_t token, - std::vector &comments ) = 0; - - virtual bool createNewComment(uint32_t &token, const RsGxsComment &comment) = 0; // async API - virtual bool createComment(RsGxsComment& comment) = 0; // blocking API. Updates comment with new metadata. - - virtual bool createNewVote(uint32_t &token, RsGxsVote &vote) = 0; - - virtual bool acknowledgeComment( - uint32_t token, - std::pair& msgId ) = 0; - - virtual bool acknowledgeVote( - uint32_t token, - std::pair& msgId ) = 0; - - virtual bool setCommentAsRead(uint32_t& token,const RsGxsGroupId& gid,const RsGxsMessageId& comment_msg_id) = 0; -}; - -/// @deprecated use RsGxsVoteType::NONE instead @see RsGxsVoteType -#define GXS_VOTE_NONE 0x0000 - -/// @deprecated use RsGxsVoteType::DOWN instead @see RsGxsVoteType -#define GXS_VOTE_DOWN 0x0001 - -/// @deprecated use RsGxsVoteType::UP instead @see RsGxsVoteType -#define GXS_VOTE_UP 0x0002 diff --git a/libretroshare/src/retroshare/rsgxsdistsync.h b/libretroshare/src/retroshare/rsgxsdistsync.h deleted file mode 100644 index d65027d58..000000000 --- a/libretroshare/src/retroshare/rsgxsdistsync.h +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsdistsync.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -#pragma once - -#include "retroshare/rsfiles.h" -#include "retroshare/rsturtle.h" - -typedef RsPeerId RsGxsNetTunnelVirtualPeerId ; - -struct RsGxsNetTunnelVirtualPeerInfo -{ - enum { RS_GXS_NET_TUNNEL_VP_STATUS_UNKNOWN = 0x00, // unknown status. - RS_GXS_NET_TUNNEL_VP_STATUS_TUNNEL_OK = 0x01, // tunnel has been established and we're waiting for virtual peer id - RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE = 0x02 // virtual peer id is known. Data can transfer. - }; - - RsGxsNetTunnelVirtualPeerInfo() : vpid_status(RS_GXS_NET_TUNNEL_VP_STATUS_UNKNOWN), last_contact(0),side(0) { memset(encryption_master_key,0,32) ; } - virtual ~RsGxsNetTunnelVirtualPeerInfo(){} - - uint8_t vpid_status ; // status of the peer - rstime_t last_contact ; // last time some data was sent/recvd - uint8_t side ; // client/server - uint8_t encryption_master_key[32]; - - TurtleVirtualPeerId turtle_virtual_peer_id ; // turtle peer to use when sending data to this vpid. - - RsGxsGroupId group_id ; // group that virtual peer is providing - uint16_t service_id ; // this is used for checkng consistency of the incoming data -}; - -struct RsGxsNetTunnelGroupInfo -{ - enum GroupStatus { - RS_GXS_NET_TUNNEL_GRP_STATUS_UNKNOWN = 0x00, // unknown status - RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE = 0x01, // no virtual peers requested, just waiting - RS_GXS_NET_TUNNEL_GRP_STATUS_VPIDS_AVAILABLE = 0x02 // some virtual peers are available. Data can be read/written - }; - - enum GroupPolicy { - RS_GXS_NET_TUNNEL_GRP_POLICY_UNKNOWN = 0x00, // nothing has been set - RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE = 0x01, // group is available for server side tunnels, but does not explicitely request tunnels - RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE = 0x02, // group will only explicitely request tunnels if none available - RS_GXS_NET_TUNNEL_GRP_POLICY_REQUESTING = 0x03, // group explicitely requests tunnels - }; - - RsGxsNetTunnelGroupInfo() : group_policy(RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE),group_status(RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE),last_contact(0) {} - - GroupPolicy group_policy ; - GroupStatus group_status ; - rstime_t last_contact ; - RsFileHash hash ; - uint16_t service_id ; - - std::set virtual_peers ; // list of which virtual peers provide this group. Can me more than 1. -}; - -// This class is here to provide statistics about GXS dist sync internals. It -// -class RsGxsDistSync -{ - public: - virtual void getStatistics( - std::map& groups, // groups on the client and server side - std::map& virtual_peers, // current virtual peers, which group they provide, and how to talk to them through turtle - std::map& turtle_vpid_to_net_tunnel_vpid, - Bias20Bytes& bias - ) const =0; -}; - -extern RsGxsDistSync *rsGxsDistSync ; - diff --git a/libretroshare/src/retroshare/rsgxsflags.h b/libretroshare/src/retroshare/rsgxsflags.h deleted file mode 100644 index 7ef6d2c49..000000000 --- a/libretroshare/src/retroshare/rsgxsflags.h +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsflags.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2018 by Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSGXSFLAGS_H -#define RSGXSFLAGS_H - -#include "inttypes.h" - -/** - * The GXS_SERV namespace serves a single point of reference for definining grp and msg flags - * Declared and defined here are: - * - privacy flags which define the level of privacy that can be given \n - * to a group - * - authentication types which defined types of authentication needed for a given message to - * confirm its authenticity - * - subscription flags: This used only locally by the peer to subscription status to a \n - * a group - * - - */ -namespace GXS_SERV { - - /** START privacy **/ - - static const uint32_t FLAG_PRIVACY_MASK = 0x0000000f; - static const uint32_t FLAG_PRIVACY_PRIVATE = 0x00000001; // pub key encrypted. No-one can read unless he has the key to decrypt the publish key. - static const uint32_t FLAG_PRIVACY_RESTRICTED = 0x00000002; // publish private key needed to publish. Typical usage: channels. - static const uint32_t FLAG_PRIVACY_PUBLIC = 0x00000004; // anyone can publish, publish key pair not needed. Typical usage: forums. - - /** END privacy **/ - - /** END authentication **/ - - /** START author authentication flags **/ - 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_GPG = 0x00000100; // Anti-spam feature. Allows to ask higher reputation to anonymous IDs - 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_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_GROUP_SIGN_PUBLISH_MASK = 0x000000ff; - 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_THREADHEAD = 0x00000004; - static const uint32_t FLAG_GROUP_SIGN_PUBLISH_NONEREQ = 0x00000008; - - /** START msg authentication flags **/ - - static const uint8_t MSG_AUTHEN_MASK = 0x0f; - static const uint8_t MSG_AUTHEN_ROOT_PUBLISH_SIGN = 0x01; // means: new threads need to be signed by the publish signature of the group. Typical use: posts in channels. - static const uint8_t MSG_AUTHEN_CHILD_PUBLISH_SIGN = 0x02; // means: all messages need to be signed by the publish signature of the group. Typical use: channels were comments are restricted to the publisher. - static const uint8_t MSG_AUTHEN_ROOT_AUTHOR_SIGN = 0x04; // means: new threads need to be signed by the author of the message. Typical use: forums, since posts are signed. - static const uint8_t MSG_AUTHEN_CHILD_AUTHOR_SIGN = 0x08; // means: all messages need to be signed by the author of the message. Typical use: forums since response to posts are signed, and signed comments in channels. - - /** END msg authentication flags **/ - - /** START group options flag **/ - - static const uint8_t GRP_OPTION_AUTHEN_AUTHOR_SIGN = 0x01; // means: the group options (serialised grp data) needs to be signed by a specific author stored in GroupMeta.mAuthorId - // note that it is always signed by the *admin* (means the creator) of the group. This author signature is just an option here. - - /** END group options flag **/ - - /** START Subscription Flags. (LOCAL) **/ - - static const uint32_t GROUP_SUBSCRIBE_ADMIN = 0x01;// means: you have the admin key for this group - static const uint32_t GROUP_SUBSCRIBE_PUBLISH = 0x02;// means: you have the publish key for thiss group. Typical use: publish key in channels are shared with specific friends. - static const uint32_t GROUP_SUBSCRIBE_SUBSCRIBED = 0x04;// means: you are subscribed to a group, which makes you a source for this group to your friend nodes. - static const uint32_t GROUP_SUBSCRIBE_NOT_SUBSCRIBED = 0x08; - - /*! - * Simply defines the range of bits that deriving services - * should not use - */ - static const uint32_t GROUP_SUBSCRIBE_MASK = 0x0000000f; - - /** END Subscription Flags. (LOCAL) **/ - - /** START GXS Msg status flags **/ - - /*! - * Two lower bytes are reserved for Generic STATUS Flags listed here. - * Services are free to use the two upper bytes. (16 flags). - * - * NOTE: RsGxsCommentService uses 0x000f0000. - */ - static const uint32_t GXS_MSG_STATUS_GEN_MASK = 0x0000ffff; - static const uint32_t GXS_MSG_STATUS_UNPROCESSED = 0x00000001; // Flags to store the read/process status of group messages. - static const uint32_t GXS_MSG_STATUS_GUI_UNREAD = 0x00000002; // The actual meaning may depend on the type of service. - static const uint32_t GXS_MSG_STATUS_GUI_NEW = 0x00000004; // - static const uint32_t GXS_MSG_STATUS_KEEP_FOREVER = 0x00000008; // Do not delete message even if older then group maximum storage time - static const uint32_t GXS_MSG_STATUS_DELETE = 0x00000020; // - - /** END GXS Msg status flags **/ - - /** START GXS Grp status flags **/ - - static const uint32_t GXS_GRP_STATUS_UNPROCESSED = 0x000000100; - static const uint32_t GXS_GRP_STATUS_UNREAD = 0x000000200; - - /** END GXS Grp status flags **/ -} - - -// GENERIC GXS MACROS -#define IS_MSG_NEW(status) (status & GXS_SERV::GXS_MSG_STATUS_GUI_NEW) -#define IS_MSG_UNREAD(status) (status & GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD) -#define IS_MSG_UNPROCESSED(status) (status & GXS_SERV::GXS_MSG_STATUS_UNPROCESSED) - -#define IS_GROUP_PGP_AUTHED(signFlags) (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) -#define IS_GROUP_PGP_KNOWN_AUTHED(signFlags) (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN) -#define IS_GROUP_MESSAGE_TRACKING(signFlags) (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) - -#define IS_GROUP_ADMIN(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) -#define IS_GROUP_PUBLISHER(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH) -#define IS_GROUP_SUBSCRIBED(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) -#define IS_GROUP_NOT_SUBSCRIBED(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED) - -#endif // RSGXSFLAGS_H diff --git a/libretroshare/src/retroshare/rsgxsforums.h b/libretroshare/src/retroshare/rsgxsforums.h deleted file mode 100644 index 83a961fc3..000000000 --- a/libretroshare/src/retroshare/rsgxsforums.h +++ /dev/null @@ -1,421 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsforums.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2019-2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rsserializable.h" -#include "retroshare/rsgxscircles.h" - - -class RsGxsForums; - -/** - * Pointer to global instance of RsGxsForums service implementation - * @jsonapi{development} - */ -extern RsGxsForums* rsGxsForums; - - -/** Forum Service message flags, to be used in RsMsgMetaData::mMsgFlags - * 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. - * @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_MODERATED = 0x00000001; - -#define IS_FORUM_MSG_MODERATION(flags) (flags & RS_GXS_FORUM_MSG_FLAGS_MODERATED) - - -struct RsGxsForumGroup : RsSerializable, RsGxsGenericGroupData -{ - /** @brief Forum desciption */ - std::string mDescription; - - /** @brief List of forum moderators ids - * @todo run away from TLV old serializables as those types are opaque to - * JSON API! */ - 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; - - /// @see RsSerializable - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - ~RsGxsForumGroup() override; - - /* 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 -{ - /** @brief Forum post GXS metadata */ - RsMsgMetaData mMeta; - - /** @brief Forum post content */ - std::string mMsg; - - /// @see RsSerializable - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mMsg); - } - - ~RsGxsForumMsg() override; -}; - - -enum class RsForumEventCode: uint8_t -{ - UNKNOWN = 0x00, - NEW_FORUM = 0x01, /// emitted when new forum is received - UPDATED_FORUM = 0x02, /// emitted when existing forum is updated - NEW_MESSAGE = 0x03, /// new message reeived in a particular forum - UPDATED_MESSAGE = 0x04, /// existing message has been updated in a particular forum - SUBSCRIBE_STATUS_CHANGED = 0x05, /// forum was subscribed or unsubscribed - READ_STATUS_CHANGED = 0x06, /// msg was read or marked unread - STATISTICS_CHANGED = 0x07, /// suppliers and how many messages they have changed - MODERATOR_LIST_CHANGED = 0x08, /// forum moderation list has changed. - SYNC_PARAMETERS_UPDATED = 0x0a, /// sync and storage times have changed - PINNED_POSTS_CHANGED = 0x0b, /// some posts where pinned or un-pinned - DELETED_FORUM = 0x0c, /// forum was deleted by cleaning -}; - -struct RsGxsForumEvent: RsEvent -{ - RsGxsForumEvent() - : RsEvent(RsEventType::GXS_FORUMS), - mForumEventCode(RsForumEventCode::UNKNOWN) {} - - RsForumEventCode mForumEventCode; - RsGxsGroupId mForumGroupId; - RsGxsMessageId mForumMsgId; - std::list mModeratorsAdded; - std::list mModeratorsRemoved; - - ///* @see RsEvent @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mForumEventCode); - RS_SERIAL_PROCESS(mForumGroupId); - RS_SERIAL_PROCESS(mForumMsgId); - RS_SERIAL_PROCESS(mForumMsgId); - RS_SERIAL_PROCESS(mModeratorsAdded); - RS_SERIAL_PROCESS(mModeratorsRemoved); - } - - ~RsGxsForumEvent() override; -}; - -class RsGxsForums: public RsGxsIfaceHelper -{ -public: - explicit RsGxsForums(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - virtual ~RsGxsForums(); - - /** - * @brief Create forum. - * @jsonapi{development} - * @param[in] name Name of the forum - * @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 createForumV2( - const std::string& name, const std::string& description, - const RsGxsId& authorId = RsGxsId(), - const std::set& moderatorsIds = std::set(), - 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 a post on the given forum. - * @jsonapi{development} - * @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 - */ - 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. - * @jsonapi{development} - * @param[in] forum Forum data (name, description...) with modifications - * @return false on error, true otherwise - */ - virtual bool editForum(RsGxsForumGroup& forum) = 0; - - /** - * @brief Get forums summaries list. Blocking API. - * @jsonapi{development} - * @param[out] forums list where to store the forums summaries - * @return false if something failed, true otherwhise - */ - virtual bool getForumsSummaries(std::list& forums) = 0; - - /** - * @brief returns statistics for the forum service - * @jsonapi{development} - * @param[out] stat statistics struct - * @return false if the call fails - */ - virtual bool getForumServiceStatistics(GxsServiceStatistic& stat) =0; - - /** - * @brief returns statistics about a particular forum - * @jsonapi{development} - * @param[in] forumId Id of the forum - * @param[out] stat statistics struct - * @return false when the object doesn't exist or when the timeout is reached requesting the data - */ - virtual bool getForumStatistics(const RsGxsGroupId& forumId,GxsGroupStatistic& stat)=0; - - - /** - * @brief Get forums information (description, thumbnail...). - * Blocking API. - * @jsonapi{development} - * @param[in] forumIds ids of the forums of which to get the informations - * @param[out] forumsInfo storage for the forums informations - * @return false if something failed, true otherwhise - */ - virtual bool getForumsInfo( - const std::list& forumIds, - std::vector& forumsInfo ) = 0; - - /** - * @brief Get message metadatas for a specific forum. Blocking API - * @jsonapi{development} - * @param[in] forumId id of the forum of which the content is requested - * @param[out] msgMetas storage for the forum messages meta data - * @return false if something failed, true otherwhise - */ - virtual bool getForumMsgMetaData( const RsGxsGroupId& forumId, - std::vector& msgMetas) = 0; - - /** - * @brief Get specific list of messages from a single forum. Blocking API - * @jsonapi{development} - * @param[in] forumId id of the forum of which the content is requested - * @param[in] msgsIds list of message ids to request - * @param[out] msgs storage for the forum messages - * @return false if something failed, true otherwhise - */ - virtual bool getForumContent( - const RsGxsGroupId& forumId, - const std::set& msgsIds, - std::vector& msgs) = 0; - - /** - * @brief Toggle message read status. Blocking API. - * @jsonapi{development} - * @param[in] messageId post identifier - * @param[in] read true to mark as read, false to mark as unread - * @return false on error, true otherwise - */ - virtual bool markRead(const RsGxsGrpMsgIdPair& messageId, bool read) = 0; - - /** - * @brief Subscrbe to a forum. Blocking API - * @jsonapi{development} - * @param[in] forumId Forum id - * @param[in] subscribe true to subscribe, false to unsubscribe - * @return false on error, true otherwise - */ - virtual bool subscribeToForum( const RsGxsGroupId& forumId, - bool subscribe ) = 0; - - /// default base URL used for forums links @see exportForumLink - static const std::string DEFAULT_FORUM_BASE_URL; - - /// Link query field used to store forum name @see exportForumLink - static const std::string FORUM_URL_NAME_FIELD; - - /// Link query field used to store forum id @see exportForumLink - static const std::string FORUM_URL_ID_FIELD; - - /// Link query field used to store forum data @see exportForumLink - static const std::string FORUM_URL_DATA_FIELD; - - /** Link query field used to store forum message title - * @see exportForumLink */ - static const std::string FORUM_URL_MSG_TITLE_FIELD; - - /// Link query field used to store forum message id @see exportForumLink - static const std::string FORUM_URL_MSG_ID_FIELD; - - /** - * @brief Get link to a forum - * @jsonapi{development} - * @param[out] link storage for the generated link - * @param[in] forumId Id of the forum of which we want to generate a link - * @param[in] includeGxsData if true include the forum GXS group data so - * the receiver can subscribe to the forum even if she hasn't received it - * through GXS yet - * @param[in] baseUrl URL into which to sneak in the RetroShare link - * radix, this is primarly useful to induce applications into making the - * link clickable, or to disguise the RetroShare link into a - * "normal" looking web link. If empty the GXS data link will be outputted - * in plain base64 format. - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if something failed, true otherwhise - */ - virtual bool exportForumLink( - std::string& link, const RsGxsGroupId& forumId, - bool includeGxsData = true, - const std::string& baseUrl = RsGxsForums::DEFAULT_FORUM_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Import forum from full link - * @param[in] link forum link either in radix or URL format - * @param[out] forumId optional storage for parsed forum id - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if some error occurred, true otherwise - */ - virtual bool importForumLink( - const std::string& link, - RsGxsGroupId& forumId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Get posts related to the given post. - * If the set is empty, nothing is returned. - * @jsonapi{development} - * @param[in] forumId id of the forum of which the content is requested - * @param[in] parentId id of the post of which child posts (aka replies) - * are requested. - * @param[out] childPosts storage for the child posts - * @return Success or error details - */ - virtual std::error_condition getChildPosts( - const RsGxsGroupId& forumId, const RsGxsMessageId& parentId, - std::vector& childPosts ) = 0; - - /** - * @brief Set keep forever flag on a post so it is not deleted even if older - * then group maximum storage time - * @jsonapi{development} - * @param[in] forumId id of the forum of which the post pertain - * @param[in] postId id of the post on which to set the flag - * @param[in] keepForever true to set the flag, false to unset it - * @return Success or error details - */ - virtual std::error_condition setPostKeepForever( - const RsGxsGroupId& forumId, const RsGxsMessageId& postId, - bool keepForever ) = 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 */ - RS_DEPRECATED_FOR("getForumsSummaries, getForumsInfo") - virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; - RS_DEPRECATED_FOR(getForumContent) - virtual bool getMsgData(const uint32_t &token, std::vector &msgs) = 0; - RS_DEPRECATED_FOR(markRead) - virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0; - RS_DEPRECATED_FOR(createForum) - virtual bool createGroup(uint32_t &token, RsGxsForumGroup &group) = 0; - RS_DEPRECATED_FOR(createMessage) - virtual bool createMsg(uint32_t &token, RsGxsForumMsg &msg) = 0; - RS_DEPRECATED_FOR(editForum) - virtual bool updateGroup(uint32_t &token, const RsGxsForumGroup &group) = 0; -}; diff --git a/libretroshare/src/retroshare/rsgxsiface.h b/libretroshare/src/retroshare/rsgxsiface.h deleted file mode 100644 index ce64bf4ed..000000000 --- a/libretroshare/src/retroshare/rsgxsiface.h +++ /dev/null @@ -1,325 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsiface.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Christopher Evi-Parker * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsreputations.h" -#include "retroshare/rsgxsservice.h" -#include "gxs/rsgxsdata.h" -#include "retroshare/rsgxsifacetypes.h" -#include "util/rsdeprecate.h" -#include "serialiser/rsserializable.h" -#include "rsitems/rsserviceids.h" -#include "retroshare/rsevents.h" - -/*! - * This structure is used to transport group summary information when a GXS - * service is searched. It contains the group information as well as a context - * string to tell where the information was found. It is more compact than a - * GroupMeta object, so as to make search responses as light as possible. - */ -struct RsGxsGroupSummary : RsSerializable -{ - RsGxsGroupSummary() : - mPublishTs(0), mNumberOfMessages(0),mLastMessageTs(0), - mSignFlags(0),mPopularity(0) {} - - RsGxsGroupId mGroupId; - std::string mGroupName; - RsGxsId mAuthorId; - rstime_t mPublishTs; - uint32_t mNumberOfMessages; - rstime_t mLastMessageTs; - uint32_t mSignFlags; - uint32_t mPopularity; - - std::string mSearchContext; - - /// @see RsSerializable::serial_process - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mGroupId); - RS_SERIAL_PROCESS(mGroupName); - RS_SERIAL_PROCESS(mAuthorId); - RS_SERIAL_PROCESS(mPublishTs); - RS_SERIAL_PROCESS(mNumberOfMessages); - RS_SERIAL_PROCESS(mLastMessageTs); - RS_SERIAL_PROCESS(mSignFlags); - RS_SERIAL_PROCESS(mPopularity); - RS_SERIAL_PROCESS(mSearchContext); - } - - ~RsGxsGroupSummary(); -}; - -/*! - * This structure is used to locally store group search results for a given service. - * It contains the group information as well as a context - * strings to tell where the information was found. It is more compact than a - * GroupMeta object, so as to make search responses as light as possible. - */ -struct RsGxsGroupSearchResults : RsSerializable -{ - RsGxsGroupSearchResults() - : mPublishTs(0), mNumberOfMessages(0),mLastMessageTs(0), mSignFlags(0),mPopularity(0) - {} - - RsGxsGroupId mGroupId; - std::string mGroupName; - RsGxsId mAuthorId; - rstime_t mPublishTs; - uint32_t mNumberOfMessages; - rstime_t mLastMessageTs; - uint32_t mSignFlags; - uint32_t mPopularity; - - std::set mSearchContexts; - - /// @see RsSerializable::serial_process - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mGroupId); - RS_SERIAL_PROCESS(mGroupName); - RS_SERIAL_PROCESS(mAuthorId); - RS_SERIAL_PROCESS(mPublishTs); - RS_SERIAL_PROCESS(mNumberOfMessages); - RS_SERIAL_PROCESS(mLastMessageTs); - RS_SERIAL_PROCESS(mSignFlags); - RS_SERIAL_PROCESS(mPopularity); - RS_SERIAL_PROCESS(mSearchContexts); - } - - virtual ~RsGxsGroupSearchResults() = default; -}; - -/*! - * Stores ids of changed gxs groups and messages. - * It is used to notify about GXS changes. - */ -struct RsGxsChanges : RsEvent -{ - RsGxsChanges(); - - /// Type of the service - RsServiceType mServiceType; - std::map > mMsgs; - std::map > mMsgsMeta; - std::list mGrps; - std::list mGrpsMeta; - std::list mDistantSearchReqs; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j,ctx); - RS_SERIAL_PROCESS(mServiceType); - RS_SERIAL_PROCESS(mMsgs); - RS_SERIAL_PROCESS(mMsgsMeta); - RS_SERIAL_PROCESS(mGrps); - RS_SERIAL_PROCESS(mGrpsMeta); - RS_SERIAL_PROCESS(mDistantSearchReqs); - } - - RsTokenService* mService; /// Weak pointer, not serialized -}; - -enum class DistantSearchGroupStatus:uint8_t -{ - UNKNOWN = 0x00, // no search ongoing for this group - CAN_BE_REQUESTED = 0x01, // a search result mentions this group, so the group data can be requested - ONGOING_REQUEST = 0x02, // the group data has been requested and the request is pending - HAVE_GROUP_DATA = 0x03, // group data has been received. Group can be subscribed. -}; - -/*! - * All implementations must offer thread safety - */ -struct RsGxsIface -{ - /*! - * \brief serviceType - * \return The 16-bits service type. See @serialiser/rsserviceids.h - */ - virtual uint16_t serviceType() const =0; - -#ifdef TO_REMOVE - /*! - * Gxs services should call this for automatic handling of - * changes, send - * @param changes - */ - virtual void receiveChanges(std::vector& changes) = 0; -#endif - - /*! - * @return handle to token service for this GXS service - */ - virtual RsTokenService* getTokenService() = 0; - - /* Generic Lists */ - - /*! - * Retrieve list of group ids associated to a request token - * @param token token to be redeemed for this request - * @param groupIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getGroupList(const uint32_t &token, - std::list &groupIds) = 0; - - /*! - * Retrieves list of msg ids associated to a request token - * @param token token to be redeemed for this request - * @param msgIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgList(const uint32_t &token, - GxsMsgIdResult& msgIds) = 0; - - /*! - * Retrieves list of msg related ids associated to a request token - * @param token token to be redeemed for this request - * @param msgIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgRelatedList(const uint32_t &token, - MsgRelatedIdResult& msgIds) = 0; - - /*! - * @param token token to be redeemed for group summary request - * @param groupInfo the ids returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getGroupMeta(const uint32_t &token, - std::list &groupInfo) = 0; - - /*! - * @param token token to be redeemed for message summary request - * @param msgInfo the message metadata returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgMeta(const uint32_t &token, - GxsMsgMetaMap &msgInfo) = 0; - - /*! - * @param token token to be redeemed for message related summary request - * @param msgInfo the message metadata returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgRelatedMeta(const uint32_t &token, - GxsMsgRelatedMetaMap &msgInfo) = 0; - - /*! - * subscribes to group, and returns token which can be used - * to be acknowledged to get group Id - * @param token token to redeem for acknowledgement - * @param grpId the id of the group to subscribe to - */ - virtual bool subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) = 0; - - /*! - * This allows the client service to acknowledge that their msgs has - * been created/modified and retrieve the create/modified msg ids - * @param token the token related to modification/create request - * @param msgIds map of grpid->msgIds of message created/modified - * @return true if token exists false otherwise - */ - virtual bool acknowledgeTokenMsg(const uint32_t& token, std::pair& msgId) = 0; - - /*! - * This allows the client service to acknowledge that their grps has - * been created/modified and retrieve the create/modified grp ids - * @param token the token related to modification/create request - * @param msgIds vector of ids of groups created/modified - * @return true if token exists false otherwise - */ - virtual bool acknowledgeTokenGrp(const uint32_t& token, RsGxsGroupId& grpId) = 0; - - /*! - * Gets service statistic for a given services - * @param token value to to retrieve requested stats - * @param stats the status - * @return true if token exists false otherwise - */ - virtual bool getServiceStatistic(const uint32_t& token, GxsServiceStatistic& stats) = 0; - - /*! - * - * @param token to be redeemed - * @param stats the stats associated to token request - * @return true if token is false otherwise - */ - virtual bool getGroupStatistic(const uint32_t& token, GxsGroupStatistic& stats) = 0; - - /*! - * - * @param token value set to be redeemed with acknowledgement - * @param grpId group id for cutoff value to be set - * @param CutOff The cut off value to set - */ - virtual void setGroupReputationCutOff(uint32_t& token, const RsGxsGroupId& grpId, int CutOff) = 0; - - /*! - * @return storage/sync time of messages in secs - */ - virtual uint32_t getDefaultStoragePeriod() = 0; - virtual uint32_t getStoragePeriod(const RsGxsGroupId& grpId) = 0; - virtual void setStoragePeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) = 0; - - virtual uint32_t getDefaultSyncPeriod() = 0; - virtual uint32_t getSyncPeriod(const RsGxsGroupId& grpId) = 0; - virtual void setSyncPeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) = 0; - - virtual RsReputationLevel minReputationForForwardingMessages( - uint32_t group_sign_flags,uint32_t identity_flags ) = 0; - - /** - * @brief Export group public data in base64 format - * @jsonapi{development} - * @param[out] radix storage for the generated base64 data - * @param[in] groupId Id of the group of which to output the data - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if something failed, true otherwhise - */ - virtual bool exportGroupBase64( - std::string& radix, const RsGxsGroupId& groupId, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Import group public data from base64 string - * @param[in] radix group invite in radix format - * @param[out] groupId optional storage for imported group id - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if some error occurred, true otherwise - */ - virtual bool importGroupBase64( - const std::string& radix, - RsGxsGroupId& groupId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - virtual ~RsGxsIface(); -}; diff --git a/libretroshare/src/retroshare/rsgxsifacehelper.h b/libretroshare/src/retroshare/rsgxsifacehelper.h deleted file mode 100644 index 4339f95f0..000000000 --- a/libretroshare/src/retroshare/rsgxsifacehelper.h +++ /dev/null @@ -1,536 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsifacehelper.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2011 Christopher Evi-Parker * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "retroshare/rsgxsiface.h" -#include "retroshare/rsservicecontrol.h" -#include "retroshare/rsreputations.h" -#include "rsgxsflags.h" -#include "util/rsdeprecate.h" -#include "util/rsdebug.h" - -/*! - * This class only make method of internal members visible tu upper level to - * offer a more friendly API. - * This is just a workaround to awkward GXS API design, do not take it as an - * example for your coding. - * To properly fix the API design many changes with the implied chain reactions - * are necessary, so at this point this workaround seems acceptable. - */ - -//================================== -// #define DEBUG_GXSIFACEHELPER 1 -//================================== - -enum class TokenRequestType: uint8_t -{ - __NONE = 0x00, /// Used to detect uninitialized - GROUP_DATA = 0x01, - GROUP_META = 0x02, - GROUP_IDS = 0x03, - POSTS = 0x04, - ALL_POSTS = 0x05, - MSG_RELATED_INFO = 0x06, - GROUP_STATISTICS = 0x07, - SERVICE_STATISTICS = 0x08, - NO_KILL_TYPE = 0x09, - __MAX /// Used to detect out of range -}; - -class RsGxsIfaceHelper -{ -public: - /*! - * @param gxs handle to RsGenExchange instance of service (Usually the - * service class itself) - */ - explicit RsGxsIfaceHelper(RsGxsIface& gxs) : - mGxs(gxs), mTokenService(*gxs.getTokenService()), mMtx("GxsIfaceHelper") - {} - - ~RsGxsIfaceHelper() = default; - -#ifdef TO_REMOVE - /*! - * Gxs services should call this for automatic handling of - * changes, send - * @param changes - */ - void receiveChanges(std::vector &changes) - { - mGxs.receiveChanges(changes); - } -#endif - - /* Generic Lists */ - - /*! - * Retrieve list of group ids associated to a request token - * @param token token to be redeemed for this request - * @param groupIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - bool getGroupList(const uint32_t &token, std::list &groupIds) - { - return mGxs.getGroupList(token, groupIds); - } - - /*! - * Retrieves list of msg ids associated to a request token - * @param token token to be redeemed for this request - * @param msgIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - bool getMsgList(const uint32_t &token, - GxsMsgIdResult& msgIds) - { - return mGxs.getMsgList(token, msgIds); - } - - /*! - * Retrieves list of msg related ids associated to a request token - * @param token token to be redeemed for this request - * @param msgIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - bool getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult &msgIds) - { - return mGxs.getMsgRelatedList(token, msgIds); - } - - /*! - * @param token token to be redeemed for group summary request - * @param groupInfo the ids returned for given request token - * @return false if request token is invalid, check token status for error report - */ - bool getGroupSummary(const uint32_t &token, std::list &groupInfo) - { - return mGxs.getGroupMeta(token, groupInfo); - } - - /*! - * @param token token to be redeemed for message summary request - * @param msgInfo the message metadata returned for given request token - * @return false if request token is invalid, check token status for error report - */ - bool getMsgSummary(const uint32_t &token, GxsMsgMetaMap &msgInfo) - { - return mGxs.getMsgMeta(token, msgInfo); - } - - /*! - * @param token token to be redeemed for message related summary request - * @param msgInfo the message metadata returned for given request token - * @return false if request token is invalid, check token status for error report - */ - bool getMsgRelatedSummary(const uint32_t &token, GxsMsgRelatedMetaMap &msgInfo) - { - return mGxs.getMsgRelatedMeta(token, msgInfo); - } - - /*! - * subscribes to group, and returns token which can be used - * to be acknowledged to get group Id - * @param token token to redeem for acknowledgement - * @param grpId the id of the group to subscribe to - */ - bool subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) - { - return mGxs.subscribeToGroup(token, grpId, subscribe); - } - - /*! - * This allows the client service to acknowledge that their msgs has - * been created/modified and retrieve the create/modified msg ids - * @param token the token related to modification/create request - * @param msgIds map of grpid->msgIds of message created/modified - * @return true if token exists false otherwise - */ - bool acknowledgeMsg(const uint32_t& token, std::pair& msgId) - { - return mGxs.acknowledgeTokenMsg(token, msgId); - } - - /*! - * This allows the client service to acknowledge that their grps has - * been created/modified and retrieve the create/modified grp ids - * @param token the token related to modification/create request - * @param msgIds vector of ids of groups created/modified - * @return true if token exists false otherwise - */ - bool acknowledgeGrp(const uint32_t& token, RsGxsGroupId& grpId) - { - return mGxs.acknowledgeTokenGrp(token, grpId); - } - - /*! - * Gets service statistic for a given services - * @param token value to to retrieve requested stats - * @param stats the status - * @return true if token exists false otherwise - */ - bool getServiceStatistic(const uint32_t& token, GxsServiceStatistic& stats) - { - return mGxs.getServiceStatistic(token, stats); - } - - /*! - * - * @param token to be redeemed - * @param stats the stats associated to token request - * @return true if token is false otherwise - */ - bool getGroupStatistic(const uint32_t& token, GxsGroupStatistic& stats) - { - return mGxs.getGroupStatistic(token, stats); - } - - /*! - * This determines the reputation threshold messages need to surpass in order - * for it to be accepted by local user from remote source - * NOTE: threshold only enforced if service require author signature - * @param token value set to be redeemed with acknowledgement - * @param grpId group id for cutoff value to be set - * @param CutOff The cut off value to set - */ - void setGroupReputationCutOff(uint32_t& token, const RsGxsGroupId& grpId, int CutOff) - { - return mGxs.setGroupReputationCutOff(token, grpId, CutOff); - } - - /*! - * @return storage/sync time of messages in secs - */ - uint32_t getDefaultStoragePeriod() - { - return mGxs.getDefaultStoragePeriod(); - } - uint32_t getStoragePeriod(const RsGxsGroupId& grpId) - { - return mGxs.getStoragePeriod(grpId); - } - void setStoragePeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) - { - mGxs.setStoragePeriod(grpId,age_in_secs); - } - uint32_t getDefaultSyncPeriod() - { - return mGxs.getDefaultSyncPeriod(); - } - uint32_t getSyncPeriod(const RsGxsGroupId& grpId) - { - return mGxs.getSyncPeriod(grpId); - } - void setSyncPeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) - { - mGxs.setSyncPeriod(grpId,age_in_secs); - } - - RsReputationLevel minReputationForForwardingMessages( - uint32_t group_sign_flags, uint32_t identity_flags ) - { - return mGxs.minReputationForForwardingMessages(group_sign_flags,identity_flags); - } - - /// @see RsTokenService::requestGroupInfo - bool requestGroupInfo( uint32_t& token, const RsTokReqOptions& opts, const std::list &groupIds, bool high_priority_request = false ) - { - TokenRequestType token_request_type; - - switch(opts.mReqType) - { - case GXS_REQUEST_TYPE_GROUP_DATA: token_request_type = TokenRequestType::GROUP_DATA; break; - case GXS_REQUEST_TYPE_GROUP_META: token_request_type = TokenRequestType::GROUP_META; break; - case GXS_REQUEST_TYPE_GROUP_IDS: token_request_type = TokenRequestType::GROUP_IDS; break; - default: - RsErr() << __PRETTY_FUNCTION__ << "(EE) Unexpected request type " << opts.mReqType << "!!" << std::endl; - return false; - } - - cancelActiveRequestTokens(token_request_type); - - if( mTokenService.requestGroupInfo(token, 0, opts, groupIds)) - { - RS_STACK_MUTEX(mMtx); - mActiveTokens[token]=high_priority_request? (TokenRequestType::NO_KILL_TYPE) : token_request_type; -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - else - return false; - } - - /// @see RsTokenService::requestGroupInfo - bool requestGroupInfo(uint32_t& token, const RsTokReqOptions& opts, bool high_priority_request = false) - { - TokenRequestType token_request_type; - - switch(opts.mReqType) - { - case GXS_REQUEST_TYPE_GROUP_DATA: token_request_type = TokenRequestType::GROUP_DATA; break; - case GXS_REQUEST_TYPE_GROUP_META: token_request_type = TokenRequestType::GROUP_META; break; - case GXS_REQUEST_TYPE_GROUP_IDS: token_request_type = TokenRequestType::GROUP_IDS; break; - default: - RsErr() << __PRETTY_FUNCTION__ << "(EE) Unexpected request type " << opts.mReqType << "!!" << std::endl; - return false; - } - - cancelActiveRequestTokens(token_request_type); - - - if( mTokenService.requestGroupInfo(token, 0, opts)) - { - RS_STACK_MUTEX(mMtx); - mActiveTokens[token]=high_priority_request? (TokenRequestType::NO_KILL_TYPE) : token_request_type; -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - else - return false; - } - - /// @see RsTokenService::requestMsgInfo - bool requestMsgInfo( uint32_t& token, const RsTokReqOptions& opts, const GxsMsgReq& msgIds ) - { - if(mTokenService.requestMsgInfo(token, 0, opts, msgIds)) - { - RS_STACK_MUTEX(mMtx); - - mActiveTokens[token]= (msgIds.size()==1 && msgIds.begin()->second.size()==0) ?(TokenRequestType::ALL_POSTS):(TokenRequestType::POSTS); -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - else - return false; - } - - /// @see RsTokenService::requestMsgInfo - bool requestMsgInfo( uint32_t& token, const RsTokReqOptions& opts, const std::list& grpIds ) - { - if(mTokenService.requestMsgInfo(token, 0, opts, grpIds)) - { - RS_STACK_MUTEX(mMtx); - mActiveTokens[token]=TokenRequestType::ALL_POSTS; -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - else - return false; - } - - /// @see RsTokenService::requestMsgRelatedInfo - bool requestMsgRelatedInfo( - uint32_t& token, const RsTokReqOptions& opts, - const std::vector& msgIds ) - { - if( mTokenService.requestMsgRelatedInfo(token, 0, opts, msgIds)) - { - RS_STACK_MUTEX(mMtx); - mActiveTokens[token]=TokenRequestType::MSG_RELATED_INFO; -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - else - return false; - } - - /** - * @jsonapi{development} - * @param[in] token - */ - RsTokenService::GxsRequestStatus requestStatus(uint32_t token) - { return mTokenService.requestStatus(token); } - - /// @see RsTokenService::requestServiceStatistic - bool requestServiceStatistic(uint32_t& token) - { - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_SERVICE_STATS; - - mTokenService.requestServiceStatistic(token,opts); - - RS_STACK_MUTEX(mMtx); - mActiveTokens[token]=TokenRequestType::SERVICE_STATISTICS; - -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - - /// @see RsTokenService::requestGroupStatistic - bool requestGroupStatistic(uint32_t& token, const RsGxsGroupId& grpId) - { - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_STATS; - - mTokenService.requestGroupStatistic(token, grpId,opts); - - RS_STACK_MUTEX(mMtx); - mActiveTokens[token]=TokenRequestType::GROUP_STATISTICS; -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - - bool cancelActiveRequestTokens(TokenRequestType type) - { - RS_STACK_MUTEX(mMtx); - for(auto it = mActiveTokens.begin();it!=mActiveTokens.end();) - if(it->second == type) - { - mTokenService.cancelRequest(it->first); - it = mActiveTokens.erase(it); - } - else - ++it; - - return true; - } - - /// @see RsTokenService::cancelRequest - bool cancelRequest(uint32_t token) - { - { - RS_STACK_MUTEX(mMtx); - mActiveTokens.erase(token); - } - return mTokenService.cancelRequest(token); - } - - /** - * @deprecated - * Token service methods are already exposed by this helper, so you should - * not need to get token service pointer directly anymore. - */ - RS_DEPRECATED RsTokenService* getTokenService() { return &mTokenService; } - -protected: - /** - * Block caller while request is being processed. - * Useful for blocking API implementation. - * @param[in] token token associated to the request caller is waiting for - * @param[in] maxWait maximum waiting time in milliseconds - * @param[in] checkEvery time in millisecond between status checks - * @param[in] auto_delete_if_unsuccessful delete the request when it fails. This avoid leaving useless pending requests in the queue that would slow down additional calls. - */ - RsTokenService::GxsRequestStatus waitToken( - uint32_t token, - std::chrono::milliseconds maxWait = std::chrono::milliseconds(20000), - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100), - bool auto_delete_if_unsuccessful=true) - { -#if defined(__ANDROID__) && (__ANDROID_API__ < 24) - auto wkStartime = std::chrono::steady_clock::now(); - int maxWorkAroundCnt = 10; -LLwaitTokenBeginLabel: -#endif - auto timeout = std::chrono::steady_clock::now() + maxWait; - auto st = requestStatus(token); - - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) - && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = requestStatus(token); - } - if(st != RsTokenService::COMPLETE && auto_delete_if_unsuccessful) - cancelRequest(token); - -#if defined(__ANDROID__) && (__ANDROID_API__ < 24) - /* Work around for very slow/old android devices, we don't expect this - * to be necessary on newer devices. If it take unreasonably long - * something worser is already happening elsewere and we return anyway. - */ - if( st > RsTokenService::FAILED && st < RsTokenService::COMPLETE - && maxWorkAroundCnt-- > 0 ) - { - maxWait *= 10; - checkEvery *= 3; - Dbg3() << __PRETTY_FUNCTION__ << " Slow Android device " - << " workaround st: " << st - << " maxWorkAroundCnt: " << maxWorkAroundCnt - << " maxWait: " << maxWait.count() - << " checkEvery: " << checkEvery.count() << std::endl; - goto LLwaitTokenBeginLabel; - } - Dbg3() << __PRETTY_FUNCTION__ << " lasted: " - << std::chrono::duration_cast( - std::chrono::steady_clock::now() - wkStartime ).count() - << "ms" << std::endl; - -#endif - - { - RS_STACK_MUTEX(mMtx); - mActiveTokens.erase(token); - } - - return st; - } - -private: - RsGxsIface& mGxs; - RsTokenService& mTokenService; - RsMutex mMtx; - - std::map mActiveTokens; - -#ifdef DEBUG_GXSIFACEHELPER - void locked_dumpTokens() - { - const uint16_t service_id = mGxs.serviceType(); - const auto countSize = static_cast(TokenRequestType::__MAX); - uint32_t count[countSize] = {0}; - - RsDbg rsdbg; - rsdbg << __PRETTY_FUNCTION__ << " Service 0x" << std::hex << service_id - << " (" << rsServiceControl->getServiceName( - RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(service_id) ) - << ") this=0x" << static_cast(this) - << ") Active tokens (per type): "; - - // let's count how many token of each type we've got. - for(auto& it: mActiveTokens) ++count[static_cast(it.second)]; - - for(uint32_t i=0; i < countSize; ++i) - rsdbg /* << i << ":" */ << count[i] << " "; - } -#endif // def DEBUG_GXSIFACEHELPER - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; diff --git a/libretroshare/src/retroshare/rsgxsifacetypes.h b/libretroshare/src/retroshare/rsgxsifacetypes.h deleted file mode 100644 index 0f78b3738..000000000 --- a/libretroshare/src/retroshare/rsgxsifacetypes.h +++ /dev/null @@ -1,309 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsifacetypes.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2013 crispy * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSGXSIFACETYPES_H_ -#define RSGXSIFACETYPES_H_ - -#include -#include -#include -#include - -#include "retroshare/rstypes.h" -#include "retroshare/rsids.h" -#include "serialiser/rsserializable.h" -#include "serialiser/rstypeserializer.h" -#include "util/rstime.h" - -typedef std::map > GxsMsgIdResult; -typedef std::pair RsGxsGrpMsgIdPair; -typedef std::map > MsgRelatedIdResult; -typedef std::map > GxsMsgReq; - -struct RsMsgMetaData; - -typedef std::map > MsgMetaResult; - -enum class GxsRequestPriority { - VERY_HIGH = 0x00, - HIGH = 0x01, - NORMAL = 0x02, - LOW = 0x03, - VERY_LOW = 0x04, -}; - -class RsGxsGrpMetaData; -class RsGxsMsgMetaData; - -struct RsGroupMetaData : RsSerializable -{ - // (csoler) The correct default value to be used in mCircleType is GXS_CIRCLE_TYPE_PUBLIC, which is defined in rsgxscircles.h, - // but because of a loop in the includes, I cannot include it here. So I replaced with its current value 0x0001. - - RsGroupMetaData() : mGroupFlags(0), mSignFlags(0), mPublishTs(0), - mCircleType(0x0001), mAuthenFlags(0), mSubscribeFlags(0), mPop(0), - mVisibleMsgCount(0), mLastPost(0), mGroupStatus(0) {} - - virtual ~RsGroupMetaData() {} - - void operator =(const RsGxsGrpMetaData& rGxsMeta); - RsGroupMetaData(const RsGxsGrpMetaData& rGxsMeta) { operator=(rGxsMeta); } - - RsGxsGroupId mGroupId; - std::string mGroupName; - uint32_t mGroupFlags; // Combination of FLAG_PRIVACY_PRIVATE | FLAG_PRIVACY_RESTRICTED | FLAG_PRIVACY_PUBLIC: diffusion - uint32_t mSignFlags; // Combination of RSGXS_GROUP_SIGN_PUBLISH_MASK & RSGXS_GROUP_SIGN_AUTHOR_MASK, i.e. what signatures are required for parent and child msgs - - rstime_t mPublishTs; // Mandatory. - RsGxsId mAuthorId; // Author of the group. Left to "000....0" if anonymous - - // for circles - RsGxsCircleId mCircleId; // Id of the circle to which the group is restricted - uint32_t mCircleType; // combination of CIRCLE_TYPE_{ PUBLIC,EXTERNAL,YOUR_FRIENDS_ONLY,LOCAL,EXT_SELF,YOUR_EYES_ONLY } - - // other stuff. - uint32_t mAuthenFlags; // Actually not used yet. - RsGxsGroupId mParentGrpId; - - // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. - - uint32_t mSubscribeFlags; - - uint32_t mPop; // Popularity = number of friend subscribers - uint32_t mVisibleMsgCount; // Max messages reported by friends - rstime_t mLastPost; // Timestamp for last message. Not used yet. - rstime_t mLastSeen; // Last time the group was advertised by friends. - - uint32_t mGroupStatus; - - /// Service Specific Free-Form local (non-synced) extra storage. - std::string mServiceString; - RsPeerId mOriginator; - RsGxsCircleId mInternalCircle; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mGroupId); - RS_SERIAL_PROCESS(mGroupName); - RS_SERIAL_PROCESS(mGroupFlags); - RS_SERIAL_PROCESS(mSignFlags); - RS_SERIAL_PROCESS(mPublishTs); - RS_SERIAL_PROCESS(mAuthorId); - RS_SERIAL_PROCESS(mCircleId); - RS_SERIAL_PROCESS(mCircleType); - RS_SERIAL_PROCESS(mAuthenFlags); - RS_SERIAL_PROCESS(mParentGrpId); - RS_SERIAL_PROCESS(mSubscribeFlags); - RS_SERIAL_PROCESS(mPop); - RS_SERIAL_PROCESS(mVisibleMsgCount); - RS_SERIAL_PROCESS(mLastPost); - RS_SERIAL_PROCESS(mGroupStatus); - RS_SERIAL_PROCESS(mServiceString); - RS_SERIAL_PROCESS(mOriginator); - RS_SERIAL_PROCESS(mInternalCircle); - } -}; - -// This is the parent class of all interface-level GXS group data. Derived classes -// will include service-specific information, such as icon, description, etc - -struct RsGxsGenericGroupData -{ - virtual ~RsGxsGenericGroupData() = default; // making the type polymorphic - - RsGroupMetaData mMeta; -}; - -struct RsMsgMetaData : RsSerializable -{ - RsMsgMetaData() : mPublishTs(0), mMsgFlags(0), mMsgStatus(0), mChildTs(0) {} - - virtual ~RsMsgMetaData() {} - - void operator =(const RsGxsMsgMetaData& rGxsMeta); - RsMsgMetaData(const RsGxsMsgMetaData& rGxsMeta) { operator=(rGxsMeta); } - - RsGxsGroupId mGroupId; - RsGxsMessageId mMsgId; - - RsGxsMessageId mThreadId; - RsGxsMessageId mParentId; - RsGxsMessageId mOrigMsgId; - - RsGxsId mAuthorId; - - std::string mMsgName; - rstime_t mPublishTs; - - /** the lower 16 bits for service, upper 16 bits for GXS - * @todo mixing service level flags and GXS level flag into the same member - * is prone to confusion, use separated members for those things, this could - * be done without breaking network retro-compatibility */ - uint32_t mMsgFlags; - - // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. - // normally READ / UNREAD flags. LOCAL Data. - - /** the first 16 bits for service, last 16 for GXS - * @todo mixing service level flags and GXS level flag into the same member - * is prone to confusion, use separated members for those things, this could - * be done without breaking network retro-compatibility */ - uint32_t mMsgStatus; - - rstime_t mChildTs; - std::string mServiceString; // Service Specific Free-Form extra storage. - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mGroupId); - RS_SERIAL_PROCESS(mMsgId); - RS_SERIAL_PROCESS(mThreadId); - RS_SERIAL_PROCESS(mParentId); - RS_SERIAL_PROCESS(mOrigMsgId); - RS_SERIAL_PROCESS(mAuthorId); - RS_SERIAL_PROCESS(mMsgName); - RS_SERIAL_PROCESS(mPublishTs); - RS_SERIAL_PROCESS(mMsgFlags); - RS_SERIAL_PROCESS(mMsgStatus); - RS_SERIAL_PROCESS(mChildTs); - RS_SERIAL_PROCESS(mServiceString); - } -}; - -struct RsGxsGenericMsgData -{ - virtual ~RsGxsGenericMsgData() = default; // making the type polymorphic - - RsMsgMetaData mMeta; -}; - - -struct GxsGroupStatistic : RsSerializable -{ - GxsGroupStatistic() : - mNumMsgs(0), mTotalSizeOfMsgs(0), mNumThreadMsgsNew(0), - mNumThreadMsgsUnread(0), mNumChildMsgsNew(0), mNumChildMsgsUnread(0) {} - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mGrpId); - RS_SERIAL_PROCESS(mNumMsgs); - RS_SERIAL_PROCESS(mTotalSizeOfMsgs); - RS_SERIAL_PROCESS(mNumThreadMsgsNew); - RS_SERIAL_PROCESS(mNumThreadMsgsUnread); - RS_SERIAL_PROCESS(mNumChildMsgsNew); - RS_SERIAL_PROCESS(mNumChildMsgsUnread); - - } - - RsGxsGroupId mGrpId; - uint32_t mNumMsgs; /// number of message, from the database - uint32_t mTotalSizeOfMsgs; - uint32_t mNumThreadMsgsNew; - uint32_t mNumThreadMsgsUnread; - uint32_t mNumChildMsgsNew; - uint32_t mNumChildMsgsUnread; - - ~GxsGroupStatistic() override; -}; - -struct GxsServiceStatistic : RsSerializable -{ - GxsServiceStatistic() : - mNumMsgs(0), mNumGrps(0), mSizeOfMsgs(0), mSizeOfGrps(0), - mNumGrpsSubscribed(0), mNumThreadMsgsNew(0), mNumThreadMsgsUnread(0), - mNumChildMsgsNew(0), mNumChildMsgsUnread(0), mSizeStore(0) {} - - uint32_t mNumMsgs; - uint32_t mNumGrps; - uint32_t mSizeOfMsgs; - uint32_t mSizeOfGrps; - uint32_t mNumGrpsSubscribed; - uint32_t mNumThreadMsgsNew; - uint32_t mNumThreadMsgsUnread; - uint32_t mNumChildMsgsNew; - uint32_t mNumChildMsgsUnread; - uint32_t mSizeStore; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mNumMsgs); - RS_SERIAL_PROCESS(mNumGrps); - RS_SERIAL_PROCESS(mSizeOfMsgs); - RS_SERIAL_PROCESS(mSizeOfGrps); - RS_SERIAL_PROCESS(mNumGrpsSubscribed); - RS_SERIAL_PROCESS(mNumThreadMsgsNew); - RS_SERIAL_PROCESS(mNumThreadMsgsUnread); - RS_SERIAL_PROCESS(mNumChildMsgsNew); - RS_SERIAL_PROCESS(mNumChildMsgsUnread); - RS_SERIAL_PROCESS(mSizeStore); - } - - ~GxsServiceStatistic() override; -}; - -class RS_DEPRECATED RsGxsGroupUpdateMeta -{ -public: - - // expand as support is added for other utypes - enum UpdateType { DESCRIPTION, NAME }; - - explicit RsGxsGroupUpdateMeta(const RsGxsGroupId& groupId): - mGroupId(groupId) {} - - typedef std::map GxsMetaUpdate; - - /*! - * Only one item of a utype can exist - * @param utype the type of meta update - * @param item update item containing the change value - */ - void setMetaUpdate(UpdateType utype, const std::string& update) - { - mUpdates[utype] = update; - } - - /*! - * @param utype update type to remove - * @return false if update did not exist, true if update successfully removed - */ - bool removeUpdateType(UpdateType utype){ return mUpdates.erase(utype) == 1; } - - const GxsMetaUpdate* getUpdates() const { return &mUpdates; } - const RsGxsGroupId& getGroupId() const { return mGroupId; } - -private: - - GxsMetaUpdate mUpdates; - RsGxsGroupId mGroupId; -}; - -#endif /* RSGXSIFACETYPES_H_ */ diff --git a/libretroshare/src/retroshare/rsgxsservice.h b/libretroshare/src/retroshare/rsgxsservice.h deleted file mode 100644 index 152b018c9..000000000 --- a/libretroshare/src/retroshare/rsgxsservice.h +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSGXSSERVICE_H -#define RSGXSSERVICE_H - - -#include "retroshare/rsgxsifacetypes.h" -#include "retroshare/rstokenservice.h" - -struct RsMsgMetaData ; -typedef uint32_t TurtleRequestId; - -typedef std::map > GxsMsgMetaMap; -typedef std::map > GxsMsgRelatedMetaMap; - - - -#endif // RSGXSSERVICE_H diff --git a/libretroshare/src/retroshare/rsgxstrans.h b/libretroshare/src/retroshare/rsgxstrans.h deleted file mode 100644 index 8cbb514a6..000000000 --- a/libretroshare/src/retroshare/rsgxstrans.h +++ /dev/null @@ -1,152 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxstrans.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "retroshare/rsgxscommon.h" -#include "rsitems/rsserviceids.h" - -/** Subservices identifiers (like port for TCP) - * @deprecated pay special attention fixing this as it may break - * retro-compatibility */ -enum class RS_DEPRECATED_FOR(RsServiceType) GxsTransSubServices : uint16_t -{ - UNKNOWN = 0x00, - TEST_SERVICE = 0x01, - P3_MSG_SERVICE = 0x02, - P3_CHAT_SERVICE = 0x03 -}; - -/// Values must fit into uint8_t -enum class GxsTransItemsSubtypes : uint8_t -{ - GXS_TRANS_SUBTYPE_MAIL = 0x01, - GXS_TRANS_SUBTYPE_RECEIPT = 0x02, - GXS_TRANS_SUBTYPE_GROUP = 0x03, - OUTGOING_RECORD_ITEM_deprecated = 0x04, - OUTGOING_RECORD_ITEM = 0x05 -}; - -enum class GxsTransSendStatus : uint8_t -{ - UNKNOWN = 0x00, - PENDING_PROCESSING = 0x01, - PENDING_PREFERRED_GROUP = 0x02, - PENDING_RECEIPT_CREATE = 0x03, - PENDING_RECEIPT_SIGNATURE = 0x04, - PENDING_SERIALIZATION = 0x05, - PENDING_PAYLOAD_CREATE = 0x06, - PENDING_PAYLOAD_ENCRYPT = 0x07, - PENDING_PUBLISH = 0x08, - /** This will be useful so the user can know if the mail reached at least - * some friend node, in case of internet connection interruption */ - //PENDING_TRANSFER, - PENDING_RECEIPT_RECEIVE = 0x09, - /// Records with status >= RECEIPT_RECEIVED get deleted - RECEIPT_RECEIVED = 0x0a, - FAILED_RECEIPT_SIGNATURE = 0xf0, - FAILED_ENCRYPTION = 0xf1, - FAILED_TIMED_OUT = 0xf2 -}; - -typedef uint64_t RsGxsTransId; - -class RsGxsTransGroup: public RsGxsGenericGroupData -{ -}; - -class RsGxsTransMsg -{ -public: - RsGxsTransMsg() : size(0),data(NULL) {} - virtual ~RsGxsTransMsg() { free(data) ; } - -public: - RsMsgMetaData mMeta; - - uint32_t size ; - uint8_t *data ; -}; - -struct RsGxsTransOutgoingRecord -{ - GxsTransSendStatus status; - RsGxsId recipient; - RsGxsTransId trans_id; - - GxsTransSubServices client_service; - - uint32_t data_size ; - Sha1CheckSum data_hash ; - uint32_t send_TS ; - RsGxsGroupId group_id ; -}; - -class RsGxsTransGroupStatistics: public GxsGroupStatistic -{ -public: - RsGxsTransGroupStatistics() - { - last_publish_TS = 0; - popularity = 0; - subscribed = false; - } - - void addMessageMeta(const RsGxsGroupId& grp,const RsMsgMetaData& meta) - { - messages_metas[meta.mMsgId] = meta ; - last_publish_TS = std::max(last_publish_TS,meta.mPublishTs) ; - mGrpId = grp ; - } - - bool subscribed ; - int popularity ; - - rstime_t last_publish_TS; - - std::map messages_metas ; -}; - - -/// RetroShare GxsTrans asyncronous redundant small mail trasport on top of GXS -/// -class RsGxsTrans: public RsGxsIfaceHelper -{ -public: - class GxsTransStatistics - { - public: - GxsTransStatistics() {} - - RsGxsGroupId prefered_group_id ; - std::vector outgoing_records; - }; - - RsGxsTrans(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - - virtual ~RsGxsTrans() {} - - virtual bool getDataStatistics(GxsTransStatistics& stats)=0; - virtual bool getGroupStatistics(std::map& stats) =0; -}; - -extern RsGxsTrans *rsGxsTrans ; diff --git a/libretroshare/src/retroshare/rsgxstunnel.h b/libretroshare/src/retroshare/rsgxstunnel.h deleted file mode 100644 index 125a7c9a9..000000000 --- a/libretroshare/src/retroshare/rsgxstunnel.h +++ /dev/null @@ -1,131 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxstunnel.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "util/rsdir.h" -#include "retroshare/rsids.h" -#include "retroshare/rsturtle.h" -#include "retroshare/rsgxsifacetypes.h" - -class RsGxsTunnelService -{ -public: - enum { - RS_GXS_TUNNEL_ERROR_NO_ERROR = 0x0000, - RS_GXS_TUNNEL_ERROR_UNKNOWN_GXS_ID = 0x0001 - }; - - enum { - RS_GXS_TUNNEL_STATUS_UNKNOWN = 0x00, - RS_GXS_TUNNEL_STATUS_TUNNEL_DN = 0x01, - RS_GXS_TUNNEL_STATUS_CAN_TALK = 0x02, - RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED = 0x03 - }; - - class RsGxsTunnelClientService - { - public: - // The client should derive this in order to handle notifications from the tunnel service. - // This cannot be ignored because the client needs to know when the tunnel is active. - - virtual void notifyTunnelStatus(const RsGxsTunnelId& tunnel_id,uint32_t tunnel_status) =0; - - // Data obtained from the corresponding GXS id. The memory ownership is transferred to the client, which - // is responsible to free it using free() once used. - - virtual void receiveData(const RsGxsTunnelId& id,unsigned char *data,uint32_t data_size) =0; - - // Used by the creator of the service to supply a pointer to the GXS tunnel service for it to be able to send data etc. - - virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) =0; - - // Gives feedback about type of data that is allowed in. For security reasons, this always needs to be re-derived (Clients can return true on default) - - virtual bool acceptDataFromPeer(const RsGxsId& gxs_id,const RsGxsTunnelId& tunnel_id,bool am_I_client_side) = 0 ; - }; - - class GxsTunnelInfo - { - public: - // Tunnel information - - RsGxsTunnelId tunnel_id ; - RsGxsId destination_gxs_id ; // GXS Id we're talking to - RsGxsId source_gxs_id ; // GXS Id we're using to talk - uint32_t tunnel_status ; // active, requested, DH pending, etc. - uint32_t total_size_sent ; // total bytes sent through that tunnel since openned (including management). - uint32_t total_size_received ; // total bytes received through that tunnel since openned (including management). - bool is_client_side ; // specifiec wether we are client(managing the tunnel) or server. - - // Data packets - - uint32_t pending_data_packets; // number of packets not acknowledged by other side, still on their way. Should be 0 unless something bad happens. - uint32_t total_data_packets_sent ; // total number of data packets sent (does not include tunnel management) - uint32_t total_data_packets_received ; // total number of data packets received (does not include tunnel management) - }; - - // This is the interface file for the secured tunnel service - // - //===================================================// - // Debugging info // - //===================================================// - - virtual bool getTunnelsInfo(std::vector& infos) =0; - virtual bool getTunnelInfo(const RsGxsTunnelId& tunnel_id,GxsTunnelInfo& info) =0; - - // retrieve the routing probabilities - - //===================================================// - // Communication to other services. // - //===================================================// - - // Register a new client service. The service ID needs to be unique, and it's the coder's resonsibility to use an ID that is not used elsewhere - // for the same purpose. - - virtual bool registerClientService(uint32_t service_id,RsGxsTunnelClientService *service) =0; - - // Asks for a tunnel. The service will request it to turtle router, and exchange a AES key using DH. - // When the tunnel is secured, the client---here supplied as argument---will be notified. He can - // then send data into the tunnel. The same tunnel may be used by different clients. - // The service id is passed on so that the client is notified when the tunnel is up. - - virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,RsGxsTunnelId& tunnel_id,uint32_t service_id,uint32_t& error_code) =0 ; - - // Data is sent through the established tunnel, possibly multiple times, until reception is acknowledged. If the tunnel does not exist, the item is rejected and - // an error is issued. In any case, the memory ownership of the data is *not* transferred to the tunnel service, so the client should delete it afterwards, if needed. - - virtual bool sendData(const RsGxsTunnelId& tunnel_id, uint32_t client_service_id, const uint8_t *data, uint32_t data_size) =0; - - // Removes any established tunnel to this GXS id. This makes the tunnel refuse further data, but the tunnel will be however kept alive - // until all pending data is flushed. All clients attached to the tunnel will be notified that the tunnel gets closed. - - virtual bool closeExistingTunnel(const RsGxsTunnelId& to_id,uint32_t service_id) =0; - - //===================================================// - // Routage feedback from other services // - //===================================================// - -}; - -// To access the GRouter from anywhere -// -extern RsGxsTunnelService *rsGxsTunnel ; diff --git a/libretroshare/src/retroshare/rshistory.h b/libretroshare/src/retroshare/rshistory.h deleted file mode 100644 index f8eb7ecaa..000000000 --- a/libretroshare/src/retroshare/rshistory.h +++ /dev/null @@ -1,90 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rshistory.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Thunder * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_HISTORY_INTERFACE_H -#define RS_HISTORY_INTERFACE_H - -class RsHistory; -class ChatId; - -extern RsHistory *rsHistory; - -#include -#include -#include -#include "retroshare/rstypes.h" - -//! data object for message history -/*! - * data object used for message history - */ -static const uint32_t RS_HISTORY_TYPE_PUBLIC = 0 ; -static const uint32_t RS_HISTORY_TYPE_PRIVATE = 1 ; -static const uint32_t RS_HISTORY_TYPE_LOBBY = 2 ; -static const uint32_t RS_HISTORY_TYPE_DISTANT = 3 ; - -class HistoryMsg -{ -public: - HistoryMsg() - { - msgId = 0; - incoming = false; - sendTime = 0; - recvTime = 0; - } - -public: - uint32_t msgId; - RsPeerId chatPeerId; - bool incoming; - RsPeerId peerId; - std::string peerName; - uint32_t sendTime; - uint32_t recvTime; - std::string message; -}; - -//! Interface to retroshare for message history -/*! - * Provides an interface for retroshare's message history functionality - */ -class RsHistory -{ -public: - virtual bool chatIdToVirtualPeerId(const ChatId &chat_id, RsPeerId &peer_id) = 0; - virtual bool getMessages(const ChatId &chatPeerId, std::list &msgs, uint32_t loadCount) = 0; - virtual bool getMessage(uint32_t msgId, HistoryMsg &msg) = 0; - virtual void removeMessages(const std::list &msgIds) = 0; - virtual void clear(const ChatId &chatPeerId) = 0; - - virtual bool getEnable(uint32_t chat_type) = 0; - virtual void setEnable(uint32_t chat_type, bool enable) = 0; - - virtual uint32_t getMaxStorageDuration() = 0; - virtual void setMaxStorageDuration(uint32_t seconds) = 0; - - // 0 = no limit, >0 count of saved messages - virtual uint32_t getSaveCount(uint32_t chat_type) = 0; - virtual void setSaveCount(uint32_t chat_type, uint32_t count) = 0; -}; - -#endif diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h deleted file mode 100644 index 0c8c364e3..000000000 --- a/libretroshare/src/retroshare/rsidentity.h +++ /dev/null @@ -1,653 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsidentity.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "retroshare/rsreputations.h" -#include "retroshare/rsids.h" -#include "serialiser/rstlvimage.h" -#include "retroshare/rsgxscommon.h" -#include "serialiser/rsserializable.h" -#include "serialiser/rstypeserializer.h" -#include "util/rsdeprecate.h" - -class RsIdentity; - -/** - * Pointer to global instance of RsIdentity service implementation - * @jsonapi{development} - */ -extern RsIdentity* rsIdentity; - - -// GroupFlags: Only one so far: - -// The deprecated flag overlaps the privacy flags for mGroupFlags. This is an error that should be fixed. For the sake of keeping some -// backward compatibility, we need to make the change step by step. - -#define RSGXSID_GROUPFLAG_REALID_kept_for_compatibility 0x0001 -#define RSGXSID_GROUPFLAG_REALID 0x0100 - -// THESE ARE FLAGS FOR INTERFACE. -#define RSID_TYPE_MASK 0xff00 -#define RSID_RELATION_MASK 0x00ff - -#define RSID_TYPE_REALID 0x0100 -#define RSID_TYPE_PSEUDONYM 0x0200 - -#define RSID_RELATION_YOURSELF 0x0001 -#define RSID_RELATION_FRIEND 0x0002 -#define RSID_RELATION_FOF 0x0004 -#define RSID_RELATION_OTHER 0x0008 -#define RSID_RELATION_UNKNOWN 0x0010 - -/// @deprecated remove toghether with RsGxsIdGroup::mRecognTags -#define RSRECOGN_MAX_TAGINFO 5 - -// Unicode symbols. NOT utf-8 bytes, because of multi byte characters -#define RSID_MAXIMUM_NICKNAME_SIZE 30 -#define RSID_MINIMUM_NICKNAME_SIZE 2 - -std::string rsIdTypeToString(uint32_t idtype); - -static const uint32_t RS_IDENTITY_FLAGS_IS_A_CONTACT = 0x0001; -static const uint32_t RS_IDENTITY_FLAGS_PGP_LINKED = 0x0002; -static const uint32_t RS_IDENTITY_FLAGS_PGP_KNOWN = 0x0004; -static const uint32_t RS_IDENTITY_FLAGS_IS_OWN_ID = 0x0008; -static const uint32_t RS_IDENTITY_FLAGS_IS_DEPRECATED= 0x0010; // used to denote keys with deprecated fingerprint format. - -struct GxsReputation : RsSerializable -{ - GxsReputation(); - - bool updateIdScore(bool pgpLinked, bool pgpKnown); - bool update(); /// checks ranges and calculates overall score. - - int32_t mOverallScore; - int32_t mIdScore; /// PGP, Known, etc. - int32_t mOwnOpinion; - int32_t mPeerOpinion; - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mOverallScore); - RS_SERIAL_PROCESS(mIdScore); - RS_SERIAL_PROCESS(mOwnOpinion); - RS_SERIAL_PROCESS(mPeerOpinion); - } - - ~GxsReputation() override; -}; - - -struct RsGxsIdGroup : RsSerializable -{ - RsGxsIdGroup() : - mLastUsageTS(0), mPgpKnown(false), mIsAContact(false) {} - - RsGroupMetaData mMeta; - - // In GroupMetaData. - //std::string mNickname; (mGroupName) - //std::string mKeyId; (mGroupId) - //uint32_t mIdType; (mGroupFlags) - - // SHA(KeyId + Gpg Fingerprint) -> can only be IDed if GPG known. - // The length of the input must be long enough to make brute force search implausible. - - // Easy to do 1e9 SHA-1 hash computations per second on a GPU. - // We will need a minimum of 256 bits, ideally 1024 bits or 2048 bits. - - // Actually PgpIdHash is SHA1(.mMeta.mGroupId + PGPHandler->GpgFingerprint(ownId)) - // ??? 160 bits. - - Sha1CheckSum mPgpIdHash; - // Need a signature as proof - otherwise anyone could add others Hashes. - // This is a string, as the length is variable. - std::string mPgpIdSign; - - // Recognition Strings. MAX# defined above. - RS_DEPRECATED std::list mRecognTags; - - // Avatar - RsGxsImage mImage ; - rstime_t mLastUsageTS ; - - // Not Serialised - for GUI's benefit. - bool mPgpLinked; - bool mPgpKnown; - bool mIsAContact; // change that into flags one day - RsPgpId mPgpId; - GxsReputation mReputation; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - ~RsGxsIdGroup() override; -}; - -// DATA TYPE FOR EXTERNAL INTERFACE. - -struct RS_DEPRECATED RsRecognTag -{ - RsRecognTag(uint16_t tc, uint16_t tt, bool v) : - tag_class(tc), tag_type(tt), valid(v) {} - - uint16_t tag_class; - uint16_t tag_type; - bool valid; -}; - - -struct RS_DEPRECATED RsRecognTagDetails -{ - RsRecognTagDetails() : - valid_from(0), valid_to(0), tag_class(0), tag_type(0), is_valid(false), - is_pending(false) {} - - rstime_t valid_from; - rstime_t valid_to; - uint16_t tag_class; - uint16_t tag_type; - - std::string signer; - - bool is_valid; - bool is_pending; -}; - - -struct RsIdentityParameters -{ - RsIdentityParameters() : - isPgpLinked(false) {} - - bool isPgpLinked; - std::string nickname; - RsGxsImage mImage; -}; - -struct RsIdentityUsage : RsSerializable -{ - enum UsageCode : uint8_t - { - UNKNOWN_USAGE = 0x00, - - /** These 2 are normally not normal GXS identities, but nothing prevents - * it to happen either. */ - GROUP_ADMIN_SIGNATURE_CREATION = 0x01, - GROUP_ADMIN_SIGNATURE_VALIDATION = 0x02, - - /** Not typically used, since most services do not require group author - * signatures */ - GROUP_AUTHOR_SIGNATURE_CREATION = 0x03, - GROUP_AUTHOR_SIGNATURE_VALIDATION = 0x04, - - /// most common use case. Messages are signed by authors in e.g. forums. - MESSAGE_AUTHOR_SIGNATURE_CREATION = 0x05, - MESSAGE_AUTHOR_SIGNATURE_VALIDATION = 0x06, - - /** Identities are stamped regularly by crawlign the set of messages for - * all groups. That helps keepign the useful identities in hand. */ - GROUP_AUTHOR_KEEP_ALIVE = 0x07, - MESSAGE_AUTHOR_KEEP_ALIVE = 0x08, - - /** Chat lobby msgs are signed, so each time one comes, or a chat lobby - * event comes, a signature verificaiton happens. */ - CHAT_LOBBY_MSG_VALIDATION = 0x09, - - /// Global router message validation - GLOBAL_ROUTER_SIGNATURE_CHECK = 0x0a, - - /// Global router message signature - GLOBAL_ROUTER_SIGNATURE_CREATION = 0x0b, - - GXS_TUNNEL_DH_SIGNATURE_CHECK = 0x0c, - GXS_TUNNEL_DH_SIGNATURE_CREATION = 0x0d, - - /// Identity received through GXS sync - IDENTITY_NEW_FROM_GXS_SYNC = 0x0e, - /// Group update on that identity data. Can be avatar, name, etc. - IDENTITY_NEW_FROM_DISCOVERY = 0x0f, - /// Explicit request to friend - IDENTITY_NEW_FROM_EXPLICIT_REQUEST = 0x10, - - /// Any signature verified for that identity - IDENTITY_GENERIC_SIGNATURE_CHECK = 0x11, - - /// Any signature made by that identity - IDENTITY_GENERIC_SIGNATURE_CREATION = 0x12, - - IDENTITY_GENERIC_ENCRYPTION = 0x13, - IDENTITY_GENERIC_DECRYPTION = 0x14, - CIRCLE_MEMBERSHIP_CHECK = 0x15 - } ; - - RsIdentityUsage( RsServiceType service, - RsIdentityUsage::UsageCode code, - const RsGxsGroupId& gid = RsGxsGroupId(), - const RsGxsMessageId& message_id = RsGxsMessageId(), - const RsGxsMessageId& parent_id = RsGxsMessageId(), - const RsGxsMessageId& thread_id = RsGxsMessageId(), - uint64_t additional_id=0, - const std::string& comment = std::string() ); - - /// Id of the service using that identity, as understood by rsServiceControl - RsServiceType mServiceId; - - /** Specific code to use. Will allow forming the correct translated message - * in the GUI if necessary. */ - UsageCode mUsageCode; - - /// Group ID using the identity - RsGxsGroupId mGrpId; - - /// Message ID using the identity - RsGxsMessageId mMsgId; - - /// Reference message ID. Useful for votes/comments - RsGxsMessageId mParentId; - - /// Reference message ID. Useful for votes/comments - RsGxsMessageId mThreadId; - - /// Some additional ID. Can be used for e.g. chat lobbies. - uint64_t mAdditionalId; - - /// additional comment to be used mainly for debugging, but not GUI display - std::string mComment; - - bool operator<(const RsIdentityUsage& u) const { return mHash < u.mHash; } - RsFileHash mHash; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mServiceId); - RS_SERIAL_PROCESS(mUsageCode); - RS_SERIAL_PROCESS(mGrpId); - RS_SERIAL_PROCESS(mMsgId); - RS_SERIAL_PROCESS(mAdditionalId); - RS_SERIAL_PROCESS(mComment); - RS_SERIAL_PROCESS(mHash); - } - - friend struct RsTypeSerializer; -private: - /** Accessible only to friend class RsTypeSerializer needed for - * deserialization */ - RsIdentityUsage(); -}; - -enum class RsGxsIdentityEventCode: uint8_t -{ - UNKNOWN = 0x00, - NEW_IDENTITY = 0x01, - DELETED_IDENTITY = 0x02, - UPDATED_IDENTITY = 0x03, -}; - -struct RsGxsIdentityEvent: public RsEvent -{ - RsGxsIdentityEvent() - : RsEvent(RsEventType::GXS_IDENTITY), - mIdentityEventCode(RsGxsIdentityEventCode::UNKNOWN) {} - - RsGxsIdentityEventCode mIdentityEventCode; - RsGxsGroupId mIdentityId; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mIdentityEventCode); - RS_SERIAL_PROCESS(mIdentityId); - } - - ~RsGxsIdentityEvent() override = default; -}; - -struct RsIdentityDetails : RsSerializable -{ - RsIdentityDetails() : mFlags(0), mLastUsageTS(0) {} - - RsGxsId mId; - - std::string mNickname; - - uint32_t mFlags; - - RsPgpId mPgpId; - - /// @deprecated Recogn details. - RS_DEPRECATED std::list mRecognTags; - - /** Cyril: Reputation details. At some point we might want to merge - * information between the two into a single global score. Since the old - * reputation system is not finished yet, I leave this in place. We should - * decide what to do with it. - */ - RsReputationInfo mReputation; - - RsGxsImage mAvatar; - - rstime_t mPublishTS; - rstime_t mLastUsageTS; - - std::map mUseCases; - - /// @see RsSerializable - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mId); - RS_SERIAL_PROCESS(mNickname); - RS_SERIAL_PROCESS(mFlags); - RS_SERIAL_PROCESS(mPgpId); - RS_SERIAL_PROCESS(mReputation); - RS_SERIAL_PROCESS(mAvatar); - RS_SERIAL_PROCESS(mPublishTS); - RS_SERIAL_PROCESS(mLastUsageTS); - RS_SERIAL_PROCESS(mUseCases); - } - - ~RsIdentityDetails() override; -}; - - - -/** The Main Interface Class for GXS people identities */ -class RsIdentity: public RsGxsIfaceHelper -{ -public: - explicit RsIdentity(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - - /** - * @brief Create a new identity - * @jsonapi{development} - * @param[out] id storage for the created identity Id - * @param[in] name Name of the identity - * @param[in] avatar Image associated to the identity - * @param[in] pseudonimous true for unsigned identity, false otherwise - * @param[in] pgpPassword password to unlock PGP to sign identity, - * not implemented yet - * @return false on error, true otherwise - */ - virtual bool createIdentity( - RsGxsId& id, - const std::string& name, const RsGxsImage& avatar = RsGxsImage(), - bool pseudonimous = true, const std::string& pgpPassword = "" ) = 0; - - /** - * @brief Locally delete given identity - * @jsonapi{development} - * @param[in] id Id of the identity - * @return false on error, true otherwise - */ - virtual bool deleteIdentity(RsGxsId& id) = 0; - - /** - * @brief Update identity data (name, avatar...) - * @jsonapi{development} - * @param[in] id Id of the identity - * @param[in] name New name of the identity - * @param[in] avatar New avatar for the identity - * @param[in] pseudonimous Set to true to make the identity anonymous. If set to false, updating will require the profile passphrase. - * @param[in] pgpPassword Profile passphrase, if non pseudonymous. - * @return false on error, true otherwise - */ - virtual bool updateIdentity( const RsGxsId& id, const std::string& name, const RsGxsImage& avatar, bool pseudonimous, const std::string& pgpPassword) =0; - - /** - * @brief Get identity details, from the cache - * @jsonapi{development} - * @param[in] id Id of the identity - * @param[out] details Storage for the identity details - * @return false on error, true otherwise - */ - virtual bool getIdDetails(const RsGxsId& id, RsIdentityDetails& details) = 0; - - /** - * @brief Get last seen usage time of given identity - * @jsonapi{development} - * @param[in] id Id of the identity - * @return timestamp of last seen usage - */ - virtual rstime_t getLastUsageTS(const RsGxsId& id) = 0; - - /** - * @brief Get own signed ids - * @jsonapi{development} - * @param[out] ids storage for the ids - * @return false on error, true otherwise - */ - virtual bool getOwnSignedIds(std::vector& ids) = 0; - - /** - * @brief Get own pseudonimous (unsigned) ids - * @jsonapi{development} - * @param[out] ids storage for the ids - * @return false on error, true otherwise - */ - virtual bool getOwnPseudonimousIds(std::vector& ids) = 0; - - /** - * @brief Check if an id is known - * @jsonapi{development} - * @param[in] id Id to check - * @return true if the id is known, false otherwise - */ - virtual bool isKnownId(const RsGxsId& id) = 0; - - /** - * @brief Check if an id is own - * @jsonapi{development} - * @param[in] id Id to check - * @return true if the id is own, false otherwise - */ - virtual bool isOwnId(const RsGxsId& id) = 0; - - /** - * @brief Get identities summaries list. - * @jsonapi{development} - * @param[out] ids list where to store the identities - * @return false if something failed, true otherwhise - */ - virtual bool getIdentitiesSummaries(std::list& ids) = 0; - - /** - * @brief Get identities information (name, avatar...). - * Blocking API. - * @jsonapi{development} - * @param[in] ids ids of the channels of which to get the informations - * @param[out] idsInfo storage for the identities informations - * @return false if something failed, true otherwhise - */ - virtual bool getIdentitiesInfo( - const std::set& ids, - std::vector& idsInfo ) = 0; - - /** - * @brief Check if an identity is contact - * @jsonapi{development} - * @param[in] id Id of the identity - * @return true if it is a conctact, false otherwise - */ - virtual bool isARegularContact(const RsGxsId& id) = 0; - - /** - * @brief Set/unset identity as contact - * @jsonapi{development} - * @param[in] id Id of the identity - * @param[in] isContact true to set, false to unset - * @return false on error, true otherwise - */ - virtual bool setAsRegularContact(const RsGxsId& id, bool isContact) = 0; - - /** - * @brief Toggle automatic flagging signed by friends identity as contact - * @jsonapi{development} - * @param[in] enabled true to enable, false to disable - */ - virtual void setAutoAddFriendIdsAsContact(bool enabled) = 0; - - /** - * @brief Check if automatic signed by friend identity contact flagging is - * enabled - * @jsonapi{development} - * @return true if enabled, false otherwise - */ - virtual bool autoAddFriendIdsAsContact() = 0; - - /** - * @brief Get number of days after which delete a banned identities - * @jsonapi{development} - * @return number of days - */ - virtual uint32_t deleteBannedNodesThreshold() = 0; - - /** - * @brief Set number of days after which delete a banned identities - * @jsonapi{development} - * @param[in] days number of days - */ - 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 - * @param[in] peers optional list of the peers to ask for the key, if empty - * all online peers are asked. - * @return false on error, true otherwise - */ - virtual bool requestIdentity( - const RsGxsId& id, - const std::vector& peers = std::vector() ) = 0; - - /// default base URL used for indentity links @see exportIdentityLink - static const std::string DEFAULT_IDENTITY_BASE_URL; - - /// Link query field used to store indentity name @see exportIdentityLink - static const std::string IDENTITY_URL_NAME_FIELD; - - /// Link query field used to store indentity id @see exportIdentityLink - static const std::string IDENTITY_URL_ID_FIELD; - - /// Link query field used to store indentity data @see exportIdentityLink - static const std::string IDENTITY_URL_DATA_FIELD; - - /** - * @brief Get link to a identity - * @jsonapi{development} - * @param[out] link storage for the generated link - * @param[in] id Id of the identity of which you want to generate a link - * @param[in] includeGxsData if true include the identity GXS group data so - * the receiver can make use of the identity even if she hasn't received it - * through GXS yet - * @param[in] baseUrl URL into which to sneak in the RetroShare link - * radix, this is primarly useful to induce applications into making the - * link clickable, or to disguise the RetroShare link into a - * "normal" looking web link. If empty the GXS data link will be outputted - * in plain base64 format. - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if something failed, true otherwhise - */ - virtual bool exportIdentityLink( - std::string& link, const RsGxsId& id, - bool includeGxsData = true, - const std::string& baseUrl = RsIdentity::DEFAULT_IDENTITY_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Import identity from full link - * @param[in] link identity link either in radix or link format - * @param[out] id optional storage for parsed identity - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if some error occurred, true otherwise - */ - virtual bool importIdentityLink( - const std::string& link, - RsGxsId& id = RS_DEFAULT_STORAGE_PARAM(RsGxsId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - RS_DEPRECATED_FOR(exportIdentityLink) - virtual bool getGroupSerializedData( - const uint32_t& token, - std::map& serialized_groups ) = 0; - - RS_DEPRECATED - virtual bool parseRecognTag( - const RsGxsId &id, const std::string& nickname, - const std::string& tag, RsRecognTagDetails& details) = 0; - - RS_DEPRECATED - virtual bool getRecognTagRequest( - const RsGxsId& id, const std::string& comment, uint16_t tag_class, - uint16_t tag_type, std::string& tag) = 0; - - RS_DEPRECATED - virtual uint32_t nbRegularContacts() =0; - - RS_DEPRECATED_FOR(exportIdentityLink) - virtual bool serialiseIdentityToMemory( const RsGxsId& id, - std::string& radix_string ) = 0; - RS_DEPRECATED_FOR(importIdentityLink) - virtual bool deserialiseIdentityFromMemory( const std::string& radix_string, - RsGxsId* id = nullptr ) = 0; - - /// Fills up list of all own ids. Returns false if ids are not yet loaded. - RS_DEPRECATED_FOR("getOwnSignedIds getOwnPseudonimousIds") - virtual bool getOwnIds( std::list &ownIds, - bool only_signed_ids = false ) = 0; - - RS_DEPRECATED - virtual bool createIdentity(uint32_t& token, RsIdentityParameters ¶ms) = 0; - - RS_DEPRECATED_FOR(RsReputations) - virtual bool submitOpinion(uint32_t& token, const RsGxsId &id, - bool absOpinion, int score) = 0; - - RS_DEPRECATED - virtual bool deleteIdentity(uint32_t& token, RsGxsIdGroup &group) = 0; - - RS_DEPRECATED_FOR("getIdentitiesSummaries getIdentitiesInfo") - virtual bool getGroupData( const uint32_t& token, - std::vector& groups) = 0; - - virtual ~RsIdentity(); -}; diff --git a/libretroshare/src/retroshare/rsids.h b/libretroshare/src/retroshare/rsids.h deleted file mode 100644 index d38ee4518..000000000 --- a/libretroshare/src/retroshare/rsids.h +++ /dev/null @@ -1,339 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsids.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2013 Cyril Soler * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util/rsdebug.h" -#include "util/rsrandom.h" -#include "util/stacktrace.h" - -/** - * RsGenericIdType values might be random, but must be different, in order to - * make the various IDs incompatible with each other. - */ -enum class RsGenericIdType -{ - SSL, - PGP_ID, - SHA1, - PGP_FINGERPRINT, - GXS_GROUP, - GXS_ID, - GXS_MSG, - GXS_CIRCLE, - GROUTER, - GXS_TUNNEL, - DISTANT_CHAT, - NODE_GROUP, - SHA256, - BIAS_20_BYTES -}; - -/** - * This class aims at defining a generic ID type that is a list of bytes. It - * can be converted into a hexadecial string for printing, mainly) or for - * compatibility with old methods. - * - * To use this class, derive your own ID type from it. - * @see RsPpgFingerprint as an example. - * - * Take care to define and use a different @see RsGenericIdType for each ne type - * of ID you create, to avoid implicit conversion between subtypes, and - * therefore accidental ID mixup is impossible. - * - * ID Types with different lengths are not convertible even using explicit - * constructor and compilation would fail if that is attempted. - * - * Warning: never store references to a t_RsGenericIdType accross threads, since - * the cached string convertion is not thread safe. - */ -template -struct t_RsGenericIdType -{ - using Id_t = t_RsGenericIdType; - using std_list = std::list; - using std_vector = std::vector; - using std_set = std::set; - - /// by default, ids are set to null() - t_RsGenericIdType() { memset(bytes, 0, ID_SIZE_IN_BYTES); } - - /// Explicit constructor from a hexadecimal string - explicit t_RsGenericIdType(const std::string& hex_string); - - /** - * @brief Construct from a buffer of at least the size of SIZE_IN_BYTES - * This is dangerous if used without being absolutely sure of buffer size, - * nothing prevent a buffer of wrong size being passed at runtime! - * @param[in] buff pointer to the buffer - * @return empty id on failure, an id initialized from the bytes in the - * buffer - */ - static Id_t fromBufferUnsafe(const uint8_t* buff) - { - Id_t ret; - - if(!buff) - { - RsErr() << __PRETTY_FUNCTION__ << " invalid paramethers buff: " - << buff << std::endl; - print_stacktrace(); - return ret; - } - - memmove(ret.bytes, buff, SIZE_IN_BYTES); - return ret; - } - - /** - * Explicit constructor from a different type but with same size. - * - * This is used for conversions such as - * GroupId -> CircleId - * GroupId -> GxsId - */ - template - explicit t_RsGenericIdType( - const t_RsGenericIdType& - id ) - { memmove(bytes, id.toByteArray(), ID_SIZE_IN_BYTES); } - - /// Random initialization. Can be useful for testing and to generate new ids. - static Id_t random() - { - Id_t id; - RsRandom::random_bytes(id.bytes, ID_SIZE_IN_BYTES); - return id; - } - - inline void clear() { memset(bytes, 0, SIZE_IN_BYTES); } - - /// Converts to a std::string using cached value. - const uint8_t* toByteArray() const { return &bytes[0]; } - - static constexpr uint32_t SIZE_IN_BYTES = ID_SIZE_IN_BYTES; - - inline bool operator==(const Id_t& fp) const - { return !memcmp(bytes, fp.bytes, ID_SIZE_IN_BYTES); } - - inline bool operator!=(const Id_t& fp) const - { return !!memcmp(bytes, fp.bytes, ID_SIZE_IN_BYTES); } - - inline bool operator< (const Id_t& fp) const - { return (memcmp(bytes, fp.bytes, ID_SIZE_IN_BYTES) < 0); } - - inline Id_t operator~ () const - { - Id_t ret; - for(uint32_t i=0; i < ID_SIZE_IN_BYTES; ++i) - ret.bytes[i] = ~bytes[i]; - return ret; - } - - inline Id_t operator| (const Id_t& fp) const - { - Id_t ret; - for(uint32_t i=0; i < ID_SIZE_IN_BYTES; ++i) - ret.bytes[i] = bytes[i] | fp.bytes[i]; - return ret; - } - - inline bool isNull() const - { - for(uint32_t i=0; i < SIZE_IN_BYTES; ++i) - if(bytes[i] != 0) return false; - return true; - } - - friend std::ostream& operator<<(std::ostream& out, const Id_t& id) - { - switch (UNIQUE_IDENTIFIER) - { - case RsGenericIdType::PGP_FINGERPRINT: - { - uint8_t index = 0; - for(char c : id.toStdString()) - { - out << c; - if(++index % 4 == 0 && index < id.SIZE_IN_BYTES*2) out << ' '; - } - } - break; - default: out << id.toStdString(UPPER_CASE); break; - } - - return out; - } - - inline std::string toStdString() const { return toStdString(UPPER_CASE); } - - inline static uint32_t serial_size() { return SIZE_IN_BYTES; } - - bool serialise(void* data,uint32_t pktsize,uint32_t& offset) const - { - if(offset + SIZE_IN_BYTES > pktsize) return false; - memmove( &(reinterpret_cast(data))[offset], - bytes, SIZE_IN_BYTES ); - offset += SIZE_IN_BYTES; - return true; - } - - bool deserialise(const void* data, uint32_t pktsize, uint32_t& offset) - { - if(offset + SIZE_IN_BYTES > pktsize) return false; - memmove( bytes, - &(reinterpret_cast(data))[offset], - SIZE_IN_BYTES ); - offset += SIZE_IN_BYTES; - return true; - } - - /** Explicit constructor from a byte array. The array must have size at - * least ID_SIZE_IN_BYTES - * @deprecated This is too dangerous! - * Nothing prevent a buffer of wrong size being passed at runtime! - */ - RS_DEPRECATED_FOR("fromBufferUnsafe(const uint8_t* buff)") - explicit t_RsGenericIdType(const uint8_t bytes[]); - -private: - std::string toStdString(bool upper_case) const; - uint8_t bytes[ID_SIZE_IN_BYTES]; -}; - -template -std::string t_RsGenericIdType -::toStdString(bool upper_case) const -{ - static const char outh[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ; - static const char outl[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' } ; - - std::string res(ID_SIZE_IN_BYTES*2,' ') ; - - for(uint32_t j = 0; j < ID_SIZE_IN_BYTES; j++) - if(upper_case) - { - res[2*j ] = outh[ (bytes[j]>>4) ] ; - res[2*j+1] = outh[ bytes[j] & 0xf ] ; - } - else - { - res[2*j ] = outl[ (bytes[j]>>4) ] ; - res[2*j+1] = outl[ bytes[j] & 0xf ] ; - } - - return res ; -} - -template -t_RsGenericIdType -::t_RsGenericIdType(const std::string& s) -{ - std::string::size_type n = 0; - if(s.length() != ID_SIZE_IN_BYTES*2) - { - if(!s.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " supplied string in constructor " - << "has wrong size. Expected ID size=" << ID_SIZE_IN_BYTES*2 - << " String=\"" << s << "\" = " << s.length() << std::endl; - print_stacktrace(); - } - clear(); - return; - } - - for(uint32_t i = 0; i < ID_SIZE_IN_BYTES; ++i) - { - bytes[i] = 0 ; - - for(int k=0;k<2;++k) - { - char b = s[n++] ; - - if(b >= 'A' && b <= 'F') - bytes[i] += (b-'A'+10) << 4*(1-k) ; - else if(b >= 'a' && b <= 'f') - bytes[i] += (b-'a'+10) << 4*(1-k) ; - else if(b >= '0' && b <= '9') - bytes[i] += (b-'0') << 4*(1-k) ; - else - { - RsErr() << __PRETTY_FUNCTION__ << "supplied string is not " - << "purely hexadecimal: s=\"" << s << "\"" << std::endl; - clear(); - return; - } - } - } -} - -template -RS_DEPRECATED_FOR("t_RsGenericIdType::fromBuffer(...)") -t_RsGenericIdType:: -t_RsGenericIdType(const uint8_t mem[]) /// @deprecated Too dangerous! -{ - if(mem == nullptr) memset(bytes, 0, ID_SIZE_IN_BYTES); - else memcpy(bytes, mem, ID_SIZE_IN_BYTES); -} - -/** - * This constants are meant to be used only inside this file. - * Use @see t_RsGenericIdType::SIZE_IN_BYTES in other places. - */ -namespace _RsIdSize -{ -constexpr uint32_t SSL_ID = 16; // = CERT_SIGN -constexpr uint32_t CERT_SIGN = 16; // = SSL_ID -constexpr uint32_t PGP_ID = 8; -constexpr uint32_t PGP_FINGERPRINT = 20; -constexpr uint32_t SHA1 = 20; -constexpr uint32_t SHA256 = 32; -} - -using RsPeerId = t_RsGenericIdType<_RsIdSize::SSL_ID , false, RsGenericIdType::SSL >; -using RsPgpId = t_RsGenericIdType<_RsIdSize::PGP_ID , true, RsGenericIdType::PGP_ID >; -using Sha1CheckSum = t_RsGenericIdType<_RsIdSize::SHA1 , false, RsGenericIdType::SHA1 >; -using Sha256CheckSum = t_RsGenericIdType<_RsIdSize::SHA256 , false, RsGenericIdType::SHA256 >; -using RsPgpFingerprint = t_RsGenericIdType<_RsIdSize::PGP_FINGERPRINT, true, RsGenericIdType::PGP_FINGERPRINT>; -using Bias20Bytes = t_RsGenericIdType<_RsIdSize::SHA1 , true, RsGenericIdType::BIAS_20_BYTES >; -using RsGxsGroupId = t_RsGenericIdType<_RsIdSize::CERT_SIGN , false, RsGenericIdType::GXS_GROUP >; -using RsGxsMessageId = t_RsGenericIdType<_RsIdSize::SHA1 , false, RsGenericIdType::GXS_MSG >; -using RsGxsId = t_RsGenericIdType<_RsIdSize::CERT_SIGN , false, RsGenericIdType::GXS_ID >; -using RsGxsCircleId = t_RsGenericIdType<_RsIdSize::CERT_SIGN , false, RsGenericIdType::GXS_CIRCLE >; -using RsGxsTunnelId = t_RsGenericIdType<_RsIdSize::SSL_ID , false, RsGenericIdType::GXS_TUNNEL >; -using DistantChatPeerId = t_RsGenericIdType<_RsIdSize::SSL_ID , false, RsGenericIdType::DISTANT_CHAT >; -using RsNodeGroupId = t_RsGenericIdType<_RsIdSize::CERT_SIGN , false, RsGenericIdType::NODE_GROUP >; - -/// @deprecated Ugly name kept temporarly only because it is used in many places -using PGPFingerprintType RS_DEPRECATED_FOR(RsPpgFingerprint) = RsPgpFingerprint; diff --git a/libretroshare/src/retroshare/rsiface.h b/libretroshare/src/retroshare/rsiface.h deleted file mode 100644 index 1f9041d3e..000000000 --- a/libretroshare/src/retroshare/rsiface.h +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsiface.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsnotify.h" -#include "rstypes.h" - -#include -#include - -class RsServer; -class RsInit; -struct RsPeerCryptoParams; -class RsControl; - -/// RsInit -> Configuration Parameters for RetroShare Startup -RsInit* InitRsConfig(); - -/* extract various options for GUI */ -const char *RsConfigDirectory(RsInit *config); -bool RsConfigStartMinimised(RsInit *config); -void CleanupRsConfig(RsInit *); - - -// Called First... (handles comandline options) -int InitRetroShare(int argc, char **argv, RsInit *config); - -/** - * Pointer to global instance of RsControl needed to expose JSON API - * @jsonapi{development} - */ -extern RsControl* rsControl; - -/** The Main Interface Class - for controlling the server */ -class RsControl -{ -public: - /// TODO: This should return a reference instead of a pointer! - static RsControl* instance(); - static void earlyInitNotificationSystem() { rsControl = instance(); } - - /* Real Startup Fn */ - virtual int StartupRetroShare() = 0; - - /** - * @brief Check if core is fully ready, true only after StartupRetroShare() - * finish and before rsGlobalShutDown() begin - * @jsonapi{development} - */ - virtual bool isReady() = 0; - - virtual void ConfigFinalSave() = 0; - - /** - * @brief Turn off RetroShare - * @jsonapi{development,manualwrapper} - */ - virtual void rsGlobalShutDown() = 0; - - virtual bool getPeerCryptoDetails( - const RsPeerId& ssl_id,RsPeerCryptoParams& params ) = 0; - virtual void getLibraries(std::list &libraries) = 0; - - /** - * @brief Set shutdown callback, useful if main runlop is controlled by - * another entity such as QCoreApplication - * @param callback function to call when shutdown is almost complete - */ - virtual void setShutdownCallback(const std::function& callback) = 0; - -protected: - RsControl() {} // should not be used, hence it's private. -}; - diff --git a/libretroshare/src/retroshare/rsinit.h b/libretroshare/src/retroshare/rsinit.h deleted file mode 100644 index 73fea2684..000000000 --- a/libretroshare/src/retroshare/rsinit.h +++ /dev/null @@ -1,480 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsinit.h * - * * - * Copyright (C) 2004-2014 Robert Fernie * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/// @file RetroShare initialization and login API - -// Initialize ok, result >= 0 -#define RS_INIT_OK 0 // Initialize ok -#define RS_INIT_HAVE_ACCOUNT 1 // Initialize ok, have account -// Initialize failed, result < 0 -#define RS_INIT_AUTH_FAILED -1 // 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_EXECUTABLE -4 // executable path hasn't been set in config options - -#include -#include -#include -#include -#include - -#include "retroshare/rstypes.h" -#include "retroshare/rsversion.h" - - -class RsLoginHelper; - -/** - * Pointer to global instance of RsLoginHelper - * @jsonapi{development} - */ -extern RsLoginHelper* rsLoginHelper; - - -enum class RsInitErrorNum : int32_t -{ - ALREADY_LOGGED_IN = 6000, - CANT_ACQUIRE_LOCK = 6001, - INVALID_LOCATION_NAME = 6002, - PGP_NAME_OR_ID_NEEDED = 6003, - PGP_KEY_CREATION_FAILED = 6004, - SSL_KEY_CREATION_FAILED = 6005, - INVALID_SSL_ID = 6006, - LOGIN_FAILED = 6007 -}; - -struct RsInitErrorCategory: std::error_category -{ - const char* name() const noexcept override - { return "RetroShare init"; } - - std::string message(int ev) const override - { - switch (static_cast(ev)) - { - case RsInitErrorNum::ALREADY_LOGGED_IN: - return "Already logged in"; - case RsInitErrorNum::CANT_ACQUIRE_LOCK: - return "Cannot aquire lock on location data. Another instance is " - "already running with this profile?"; - case RsInitErrorNum::INVALID_LOCATION_NAME: - return "Invalid location name"; - case RsInitErrorNum::PGP_NAME_OR_ID_NEEDED: - return "Either PGP name or PGP id is needed"; - case RsInitErrorNum::PGP_KEY_CREATION_FAILED: - return "Failure creating PGP key"; - case RsInitErrorNum::SSL_KEY_CREATION_FAILED: - return "Failure creating SSL key"; - case RsInitErrorNum::INVALID_SSL_ID: - return "Invalid SSL id"; - case RsInitErrorNum::LOGIN_FAILED: - return "Generic login failure"; - default: - return rsErrorNotInCategory(ev, name()); - } - } - - const static RsInitErrorCategory instance; -}; - - -namespace std -{ -/** Register RsJsonApiErrorNum as an error condition enum, must be in std - * namespace */ -template<> struct is_error_condition_enum : true_type {}; -} - -/** Provide RsInitErrorNum conversion to std::error_condition, must be in - * same namespace of RsInitErrorNum */ -inline std::error_condition make_error_condition(RsInitErrorNum e) noexcept -{ - return std::error_condition( - static_cast(e), RsInitErrorCategory::instance ); -}; - - - -/** - * @brief The RsInitConfig struct - * This class contains common configuration options, that executables using libretroshare may want to - * set using e.g. commandline options. To be passed to RsInit::InitRetroShare(). - */ -struct RsConfigOptions -{ - RsConfigOptions(); - - // required - - std::string main_executable_path;/* this should be set to argv[0] */ - - // Optional. Only change if needed. - - bool autoLogin; /* try auto-login */ - - bool udpListenerOnly; /* only listen to udp */ - std::string forcedInetAddress; /* inet address to use.*/ - uint16_t forcedPort; /* port to listen to */ - - bool outStderr; - int debugLevel; - std::string logfname; /* output filename for log */ - - std::string opModeStr; /* operating mode. Acceptable values: "Full", "NoTurtle", "Gaming", "Minimal" */ - std::string optBaseDir; /* base directory where to find profiles, etc */ - - uint16_t jsonApiPort; /* port to use fo Json API */ - std::string jsonApiBindAddress; /* bind address for Json API */ -}; - - -/*! - * Initialisation Class (not publicly disclosed to RsIFace) - */ -class RsInit -{ -public: - enum RS_DEPRECATED_FOR(RsInitErrorNum) LoadCertificateStatus : uint8_t - { - OK, /// Everything go as expected, no error occurred - ERR_ALREADY_RUNNING, /// Another istance is running already - ERR_CANT_ACQUIRE_LOCK, /// Another istance is already running? - ERR_NO_AVAILABLE_ACCOUNT, /// Used in retroshare-service -U list when no account is available - ERR_UNKNOWN /// Unkown error, maybe password is wrong? - }; - - /* reorganised RsInit system */ - - /*! - * PreLogin - * Call before init retroshare, initialises rsinitconfig's public attributes - */ - static void InitRsConfig(); - - /*! - * Should be called to load up ssl cert and private key, and intialises gpg - * this must be called before accessing rsserver (e.g. ::startupretroshare) - * @param argc passed from executable - * @param argv commandline arguments passed to executable - * @param strictCheck set to true if you want rs to continue executing if - * invalid argument passed and vice versa - * @return RS_INIT_... - */ - static int InitRetroShare(const RsConfigOptions&); - - static bool isPortable(); - static bool isWindowsXP(); - static bool collectEntropy(uint32_t bytes) ; - - /*! - * \brief lockFilePath - * \return - * full path for the lock file. Can be used to warn the user about a non deleted lock that would prevent to start. - */ - static std::string lockFilePath(); - - /* - * Setup Hidden Location; - */ - static void SetHiddenLocation(const std::string& hiddenaddress, uint16_t port, bool useBob); - - static bool LoadPassword(const std::string& passwd) ; - - /* - * Final Certificate load. This can be called if: - * a) InitRetroshare() returns RS_INIT_HAVE_ACCOUNT -> autoLoad/password Set. - * b) or LoadPassword() - * - * This uses the preferredId from RsAccounts. - * This wrapper also locks the profile before finalising the login - */ - static LoadCertificateStatus LockAndLoadCertificates( - bool autoLoginNT, std::string& lockFilePath ); - - // Post Login Options - static bool getStartMinimised(); - - static int getSslPwdLen(); - static bool getAutoLogin(); - static void setAutoLogin(bool autoLogin); - static bool RsClearAutoLogin() ; - -private: - /** @brief Lock profile directory - * param[in] accountDir account directory to lock - * param[out] lockFilePath path of the created lock-file - */ - static LoadCertificateStatus LockConfigDirectory( - const std::string& accountDir, std::string& lockFilePath); - - /// @brief Unlock profile directory - static void UnlockConfigDirectory(); - - static int LoadCertificates(bool autoLoginNT); -}; - - - -/* Seperate static Class for dealing with Accounts */ - -class RsAccountsDetail; - -class RsAccounts -{ -public: - /// Should be called once before everything else. - static bool init(const std::string &opt_base_dir, int& error_code); - - /** - * @brief ConfigDirectory (usually ~/.retroshare) you can call this method - * even before initialisation (you can't with some other methods) - * @see RsAccountsDetail::PathBaseDirectory() - */ - static std::string ConfigDirectory(); - - /** - * @brief Get current account id. Beware that an account may be selected - * without actually logging in. - * @jsonapi{development,unauthenticated} - * @param[out] id storage for current account id - * @return false if account hasn't been selected yet, true otherwise - */ - static bool getCurrentAccountId(RsPeerId &id); - - /** - * @brief DataDirectory - * you can call this method even before initialisation (you can't with some other methods) - * @param check if set to true and directory does not exist, return empty string - * @return path where global platform independent files are stored, like bdboot.txt or webinterface files - */ - static std::string systemDataDirectory(bool check = true); - static std::string PGPDirectory(); - - /** - * @brief Get available PGP identities id list - * @jsonapi{development,unauthenticated} - * @param[out] pgpIds storage for PGP id list - * @return true on success, false otherwise - */ - static int GetPGPLogins(std::list &pgpIds); - static int GetPGPLoginDetails(const RsPgpId& id, std::string &name, std::string &email); - static bool GeneratePGPCertificate(const std::string&, const std::string& email, const std::string& passwd, RsPgpId &pgpId, const int keynumbits, std::string &errString); - - /** - * @brief Export full encrypted PGP identity to file - * @jsonapi{development} - * @param[in] filePath path of certificate file - * @param[in] pgpId PGP id to export - * @return true on success, false otherwise - */ - static bool ExportIdentity( const std::string& filePath, - const RsPgpId& pgpId ); - - /** - * @brief Import full encrypted PGP identity from file - * @jsonapi{development,unauthenticated} - * @param[in] filePath path of certificate file - * @param[out] pgpId storage for the PGP fingerprint of the imported key - * @param[out] errorMsg storage for eventual human readable error message - * @return true on success, false otherwise - */ - static bool ImportIdentity( - const std::string& filePath, RsPgpId& pgpId, std::string& errorMsg ); - - /** - * @brief Import full encrypted PGP identity from string - * @jsonapi{development,unauthenticated} - * @param[in] data certificate string - * @param[out] pgpId storage for the PGP fingerprint of the imported key - * @param[out] errorMsg storage for eventual human readable error message - * @return true on success, false otherwise - */ - static bool importIdentityFromString( - const std::string& data, RsPgpId& pgpId, - std::string& errorMsg ); - - /** - * @brief Export full encrypted PGP identity to string - * @jsonapi{development} - * @param[out] data storage for certificate string - * @param[in] pgpId PGP id to export - * @param[in] includeSignatures true to include signatures - * @param[out] errorMsg storage for eventual human readable error message - * @return true on success, false otherwise - */ - static bool exportIdentityToString( - std::string& data, const RsPgpId& pgpId, std::string& errorMsg, - bool includeSignatures = true ); - - static void GetUnsupportedKeys(std::map > &unsupported_keys); - static bool CopyGnuPGKeyrings() ; - - // Rs Accounts - static bool SelectAccount(const RsPeerId& id); - static bool GetPreferredAccountId(RsPeerId &id); - static bool GetAccountIds(std::list &ids); - - static bool GetAccountDetails(const RsPeerId &id, RsPgpId &gpgId, std::string &gpgName, std::string &gpgEmail, std::string &location); - - static bool createNewAccount( - const RsPgpId& pgp_id, const std::string& org, - const std::string& loc, const std::string& country, - bool ishiddenloc, bool is_auto_tor, const std::string& passwd, - RsPeerId &sslId, std::string &errString ); - - static void storeSelectedAccount() ; - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // All methods bellow can only be called ones SelectAccount() as been called. // - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - static bool getCurrentAccountOptions(bool& is_hidden,bool& is_tor_auto,bool& is_first_time) ; - - static bool checkCreateAccountDirectory(); // Generate the hierarchy of directories below ~/.retroshare/[SSL dir]/ - static bool isHiddenNode() ; // true if the running node is a hidden node. Used to choose which services to start. - static bool isTorAuto() ; // true if the running node is a hidden node using automated Tor management - - static std::string AccountDirectory(); // linux: ~/.retroshare/[SSL dir]/ - static std::string AccountKeysDirectory(); // linux: ~/.retroshare/[SSL dir]/keys/ - static std::string AccountPathCertFile(); // linux: ~/.retroshare/[SSL dir]/keys/user_cert.pem - static std::string AccountPathKeyFile(); // linux: ~/.retroshare/[SSL dir]/keys/user_pk.pem - static std::string AccountLocationName(); - - static bool lockPreferredAccount() ; // are these methods any useful?? - static void unlockPreferredAccount() ; - -private: - static RsAccountsDetail* rsAccountsDetails; -}; - -/** - * Pointer to global instance of RsAccounts needed to expose JSON API, as all - * the members of this class are static you should call them directly without - * using this pointer in the other parts of the code - * @jsonapi{development} - */ -extern RsAccounts* rsAccounts; - - -/** - * This helper class have been implemented because there was not reasonable way - * to login in the API that could be exposed via JSON API - */ -class RsLoginHelper -{ -public: - RsLoginHelper() = default; - - /** - * @brief Normal way to attempt login - * @jsonapi{development,unauthenticated} - * @param[in] account Id of the account to which attempt login - * @param[in] password Password for the given account - * @return RsInit::OK if login attempt success, error code otherwhise - */ - RsInit::LoadCertificateStatus attemptLogin( - const RsPeerId& account, const std::string& password ); - - /** - * @brief Feed extra entropy to the crypto libraries - * @jsonapi{development,unauthenticated} - * @param[in] bytes number to feed to the entropy pool - * @return false if error occurred, true otherwise - */ - static bool collectEntropy(uint32_t bytes); - - struct Location : RsSerializable - { - RsPeerId mLocationId; - RsPgpId mPgpId; - std::string mLocationName; - std::string mPgpName; - - /// @see RsSerializable::serial_process - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - }; - - /** - * @brief Get locations and associated information - * @jsonapi{development,unauthenticated} - * @param[out] locations storage for the retrived locations - */ - void getLocations(std::vector& locations); - - /** - * @brief Creates a new RetroShare location, and log in once is created - * @jsonapi{development,manualwrapper} - * @param[out] locationId storage for generated location SSL id - * @param[inout] pgpId specify PGP id to use to sign the location, if a null - * id is passed the PGP key is created too and this param is used as - * storage for its id. - * @param[in] password to protect and unlock the associated PGP key - * param[in] apiUser (JSON API only) string containing username for JSON API - * so it can be later used to authenticate JSON API calls. It is passed - * down to @see RsJsonApi::authorizeUser under the hood. - * param[in] apiPass (JSON API only) string containing password for JSON API - * so it can be later used to authenticate JSON API calls. It is passed - * down to @see RsJsonApi::authorizeUser under the hood. - * To improve security we strongly advise to not use the same as the - * password used for the PGP key. - * @return Success or error information - */ - std::error_condition createLocationV2( - RsPeerId& locationId, - RsPgpId& pgpId, - const std::string& locationName, - const std::string& pgpName, - const std::string& password - /* JSON API only - * const std::string& apiUser - * const std::string& apiPass */ ); - - /** - * @brief Check if RetroShare is already logged in, this usually return true - * after a successfull attemptLogin() and before closeSession() - * @jsonapi{development,unauthenticated} - * @return true if already logged in, false otherwise - */ - bool isLoggedIn(); - -#if !RS_VERSION_AT_LEAST(0,6,6) - /** - * @deprecated Use @see createLocationV2 instead - * @brief Creates a new RetroShare location, and log in once is created - * @jsonapi{development,manualwrapper} - * @param[inout] location provide input information to generate the location - * and storage to output the data of the generated location - * @param[in] password to protect and unlock the associated PGP key - * @param[out] errorMessage if some error occurred human readable error - * message - * @param[in] makeHidden pass true to create an hidden location. UNTESTED! - * @param[in] makeAutoTor pass true to create an automatically configured - * Tor hidden location. UNTESTED! - * @return true if success, false otherwise - */ - RS_DEPRECATED_FOR(createLocationV2) - bool createLocation( RsLoginHelper::Location& location, - const std::string& password, std::string& errorMessage, - bool makeHidden = false, bool makeAutoTor = false ); -#endif // !RS_VERSION_AT_LEAST(0,6,6) -}; diff --git a/libretroshare/src/retroshare/rsjsonapi.h b/libretroshare/src/retroshare/rsjsonapi.h deleted file mode 100644 index 38e33490e..000000000 --- a/libretroshare/src/retroshare/rsjsonapi.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * RetroShare JSON API public header - * - * Copyright (C) 2018-2020 Gioacchino Mazzurco - * Copyright (C) 2019 Cyril Soler - * Copyright (C) 2020 Asociación Civil Altermundi - * - * 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 - * - * SPDX-FileCopyrightText: 2004-2019 RetroShare Team - * SPDX-License-Identifier: LGPL-3.0-or-later - */ - -#pragma once - -#include -#include -#include -#include - -#include "util/rsdebug.h" -#include "util/rsmemory.h" - -class RsJsonApi; - -/** - * Pointer to global instance of RsJsonApi service implementation - * @jsonapi{development} - */ -extern RsJsonApi* rsJsonApi; - -enum class RsJsonApiErrorNum : int32_t -{ - TOKEN_FORMAT_INVALID = 2004, - UNKNOWN_API_USER = 2005, - WRONG_API_PASSWORD = 2006, - API_USER_CONTAIN_COLON = 2007, - AUTHORIZATION_REQUEST_DENIED = 2008, - CANNOT_EXECUTE_BEFORE_RS_LOGIN = 2009, - NOT_A_MACHINE_GUN = 2010 -}; - -struct RsJsonApiErrorCategory: std::error_category -{ - const char* name() const noexcept override - { return "RetroShare JSON API"; } - - std::string message(int ev) const override - { - switch (static_cast(ev)) - { - case RsJsonApiErrorNum::TOKEN_FORMAT_INVALID: - return "Invalid token format, must be alphanumeric_user:password"; - case RsJsonApiErrorNum::UNKNOWN_API_USER: - return "Unknown API user"; - case RsJsonApiErrorNum::WRONG_API_PASSWORD: - return "Wrong API password"; - case RsJsonApiErrorNum::API_USER_CONTAIN_COLON: - return "API user cannot contain colon character"; - case RsJsonApiErrorNum::AUTHORIZATION_REQUEST_DENIED: - return "User denied new token autorization"; - case RsJsonApiErrorNum::CANNOT_EXECUTE_BEFORE_RS_LOGIN: - return "This operation cannot be executed bedore RetroShare login"; - case RsJsonApiErrorNum::NOT_A_MACHINE_GUN: - return "Method must not be called in burst"; - default: - return rsErrorNotInCategory(ev, name()); - } - } - - std::error_condition default_error_condition(int ev) const noexcept override; - - const static RsJsonApiErrorCategory instance; -}; - - -namespace std -{ -/** Register RsJsonApiErrorNum as an error condition enum, must be in std - * namespace */ -template<> struct is_error_condition_enum : true_type {}; -} - -/** Provide RsJsonApiErrorNum conversion to std::error_condition, must be in - * same namespace of RsJsonApiErrorNum */ -inline std::error_condition make_error_condition(RsJsonApiErrorNum e) noexcept -{ - return std::error_condition( - static_cast(e), RsJsonApiErrorCategory::instance ); -}; - - -class p3ConfigMgr; -class JsonApiResourceProvider; - -class RsJsonApi -{ -public: - static const uint16_t DEFAULT_PORT = 9092; - static const std::string DEFAULT_BINDING_ADDRESS; // 127.0.0.1 - - /** - * @brief Restart RsJsonApi server. - * This method is asyncronous when called from JSON API. - * @jsonapi{development,manualwrapper} - * @return Success or error details - */ - virtual std::error_condition restart() = 0; - - /** @brief Request RsJsonApi to stop and wait until it has stopped. - * Do not expose this method to JSON API as fullstop must not be called from - * the same thread of service execution. - */ - virtual void fullstop() = 0; - - /** - * @brief Request RsJsonApi to stop asynchronously. - * @jsonapi{development} - * Be expecially carefull to call this from JSON API because you will loose - * access to the API. - * If you need to wait until stopping has completed @see isRunning(). - */ - virtual void askForStop() = 0; - - /** - * @brief Get status of the json api server - * @return Returns true if the server is running - */ - virtual bool isRunning() = 0; - - /** - * Sets the binding address of the JSON API server. Will only take effect - * after the server is restarted. - * @jsonapi{development} - * @param[in] address Binding address in IPv4 or IPv6 format. - */ - virtual void setBindingAddress(const std::string& address) = 0; - - /** - * Get the binding address of the JSON API server. - * @jsonapi{development} - * @return string representing binding address - */ - virtual std::string getBindingAddress() const = 0; - - /*! - * Set port on which JSON API server will listen. Will only take effect - * after the server is restarted. - * @jsonapi{development} - * @param[in] port Must be available otherwise the binding will fail - */ - virtual void setListeningPort(uint16_t port) = 0; - - /*! - * Get port on which JSON API server will listen. - * @jsonapi{development} - */ - virtual uint16_t listeningPort() const = 0; - - /*! - * Should be called after creating the JsonAPI object so that it publishes - * itself with the proper config file. - * Since JsonAPI is created *before* login, the config manager does not - * exist at that time. - * @param cfgmgr - */ - virtual void connectToConfigManager(p3ConfigMgr& cfgmgr) = 0; - - /** - * This is used to add/remove new web services to JsonAPI. The client - * should take care of not using a path range already used by the jsonAPI - * server - */ - virtual void registerResourceProvider(const JsonApiResourceProvider&) = 0; - virtual void unregisterResourceProvider(const JsonApiResourceProvider&) = 0; - virtual bool hasResourceProvider(const JsonApiResourceProvider&) = 0; - - /** - * @brief This function should be used by JSON API clients that aren't - * authenticated yet, to ask their token to be authorized, the success or - * failure will depend on mNewAccessRequestCallback return value, and it - * will likely need human user interaction in the process. - * @jsonapi{development,unauthenticated} - * @param[in] user user name to authorize - * @param[in] password password for the new user - * @return if an error occurred details about it. - */ - virtual std::error_condition requestNewTokenAutorization( - const std::string& user, const std::string& password) = 0; - - /** Split a token in USER:PASSWORD format into user and password */ - static bool parseToken( - const std::string& clear_token, - std::string& user, std::string& passwd ); - - /** - * Add new API auth user, passwd to the authorized set. - * @jsonapi{development} - * @param[in] user user name to autorize, must not contain ':' - * @param[in] password password for the user - * @return if some error occurred return details about it - */ - virtual std::error_condition authorizeUser( - const std::string& user, const std::string& password ) = 0; - - /** - * @brief Revoke given auth token - * @jsonapi{development} - * @param[in] user user name of which to revoke authorization - * @return true if the token has been revoked, false otherwise - */ - virtual bool revokeAuthToken(const std::string& user)=0; - - /** - * @brief Get authorized tokens - * @jsonapi{development} - * @return the set of authorized encoded tokens - */ - virtual std::map getAuthorizedTokens() = 0; - - /** - * @brief Check if given JSON API auth token is authorized - * @jsonapi{development,unauthenticated} - * @param[in] token decoded - * @param[out] error optional storage for error details - * @return true if authorized, false otherwise - */ - virtual bool isAuthTokenValid( - const std::string& token, - std::error_condition& error = RS_DEFAULT_STORAGE_PARAM(std::error_condition) - ) = 0; - - /** - * @brief Write version information to given paramethers - * @jsonapi{development,unauthenticated} - * @param[out] major storage - * @param[out] minor storage - * @param[out] mini storage - * @param[out] extra storage - * @param[out] human storage - */ - static void version( uint32_t& major, uint32_t& minor, uint32_t& mini, - std::string& extra, std::string& human ); - - virtual ~RsJsonApi() = default; -}; - diff --git a/libretroshare/src/retroshare/rsmsgs.h b/libretroshare/src/retroshare/rsmsgs.h deleted file mode 100644 index 614a99707..000000000 --- a/libretroshare/src/retroshare/rsmsgs.h +++ /dev/null @@ -1,1043 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsmsgs.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2008 Robert Fernie * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include - -#include "retroshare/rstypes.h" -#include "retroshare/rsgxsifacetypes.h" -#include "retroshare/rsevents.h" -#include "util/rsdeprecate.h" -#include "util/rsmemory.h" - -/********************** For Messages and Channels *****************/ - -#define RS_MSG_BOXMASK 0x000f /* Mask for determining Box */ - -#define RS_MSG_OUTGOING 0x0001 /* !Inbox */ -#define RS_MSG_PENDING 0x0002 /* OutBox */ -#define RS_MSG_DRAFT 0x0004 /* Draft */ - -/* ORs of above */ -#define RS_MSG_INBOX 0x00 /* Inbox */ -#define RS_MSG_SENTBOX 0x01 /* Sentbox */ -#define RS_MSG_OUTBOX 0x03 /* Outbox */ -#define RS_MSG_DRAFTBOX 0x05 /* Draftbox */ - -#define RS_MSG_NEW 0x000010 /* New */ -#define RS_MSG_TRASH 0x000020 /* Trash */ -#define RS_MSG_UNREAD_BY_USER 0x000040 /* Unread by user */ -#define RS_MSG_REPLIED 0x000080 /* Message is replied */ -#define RS_MSG_FORWARDED 0x000100 /* Message is forwarded */ -#define RS_MSG_STAR 0x000200 /* Message is marked with a star */ -// system message -#define RS_MSG_USER_REQUEST 0x000400 /* user request */ -#define RS_MSG_FRIEND_RECOMMENDATION 0x000800 /* friend recommendation */ -#define RS_MSG_DISTANT 0x001000 /* message is distant */ -#define RS_MSG_SIGNATURE_CHECKS 0x002000 /* message was signed, and signature checked */ -#define RS_MSG_SIGNED 0x004000 /* message was signed and signature didn't check */ -#define RS_MSG_LOAD_EMBEDDED_IMAGES 0x008000 /* load embedded images */ -#define RS_MSG_PUBLISH_KEY 0x020000 /* publish key */ -#define RS_MSG_SPAM 0x040000 /* Message is marked as spam */ - -#define RS_MSG_SYSTEM (RS_MSG_USER_REQUEST | RS_MSG_FRIEND_RECOMMENDATION | RS_MSG_PUBLISH_KEY) - -#define RS_CHAT_LOBBY_EVENT_PEER_LEFT 0x01 -#define RS_CHAT_LOBBY_EVENT_PEER_STATUS 0x02 -#define RS_CHAT_LOBBY_EVENT_PEER_JOINED 0x03 -#define RS_CHAT_LOBBY_EVENT_PEER_CHANGE_NICKNAME 0x04 -#define RS_CHAT_LOBBY_EVENT_KEEP_ALIVE 0x05 - -#define RS_MSGTAGTYPE_IMPORTANT 1 -#define RS_MSGTAGTYPE_WORK 2 -#define RS_MSGTAGTYPE_PERSONAL 3 -#define RS_MSGTAGTYPE_TODO 4 -#define RS_MSGTAGTYPE_LATER 5 -#define RS_MSGTAGTYPE_USER 100 - -//#define RS_CHAT_LOBBY_PRIVACY_LEVEL_CHALLENGE 0 /* Used to accept connection challenges only. */ -//#define RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC 1 /* lobby is visible by friends. Friends can connect.*/ -//#define RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE 2 /* lobby invisible by friends. Peers on invitation only .*/ - -#define RS_CHAT_TYPE_PUBLIC 1 -#define RS_CHAT_TYPE_PRIVATE 2 -#define RS_CHAT_TYPE_LOBBY 3 -#define RS_CHAT_TYPE_DISTANT 4 - -const ChatLobbyFlags RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE( 0x00000001 ) ; -const ChatLobbyFlags RS_CHAT_LOBBY_FLAGS_deprecated ( 0x00000002 ) ; -const ChatLobbyFlags RS_CHAT_LOBBY_FLAGS_PUBLIC ( 0x00000004 ) ; -const ChatLobbyFlags RS_CHAT_LOBBY_FLAGS_CHALLENGE ( 0x00000008 ) ; -const ChatLobbyFlags RS_CHAT_LOBBY_FLAGS_PGP_SIGNED ( 0x00000010 ) ; // requires the signing ID to be PGP-linked. Avoids anonymous crap. - -typedef uint64_t ChatLobbyId ; -typedef uint64_t ChatLobbyMsgId ; -typedef std::string ChatLobbyNickName ; -typedef std::string RsMailMessageId; // TODO: rebase on t_RsGenericIdType - -/** - * Used to return a tracker id so the API user can keep track of sent mail - * status, it contains mail id, and recipient id - */ -struct RsMailIdRecipientIdPair : RsSerializable -{ - RsMailIdRecipientIdPair(RsMailMessageId mailId, RsGxsId recipientId): - mMailId(mailId), mRecipientId(recipientId) {} - - RsMailMessageId mMailId; - RsGxsId mRecipientId; - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext &ctx ) override; - - bool operator<(const RsMailIdRecipientIdPair& other) const; - bool operator==(const RsMailIdRecipientIdPair& other) const; - - RsMailIdRecipientIdPair() = default; - ~RsMailIdRecipientIdPair() override = default; -}; - -namespace Rs -{ -namespace Msgs -{ - -class MsgAddress -{ - public: - typedef enum { MSG_ADDRESS_TYPE_UNKNOWN = 0x00, - MSG_ADDRESS_TYPE_RSPEERID = 0x01, - MSG_ADDRESS_TYPE_RSGXSID = 0x02, - MSG_ADDRESS_TYPE_EMAIL = 0x03 } AddressType; - - typedef enum { MSG_ADDRESS_MODE_UNKNOWN = 0x00, - MSG_ADDRESS_MODE_TO = 0x01, - MSG_ADDRESS_MODE_CC = 0x02, - MSG_ADDRESS_MODE_BCC = 0x03 } AddressMode; - - explicit MsgAddress(const RsGxsId& gid, MsgAddress::AddressMode mmode) - : _type(MSG_ADDRESS_TYPE_RSGXSID), _mode(mmode), _addr_string(gid.toStdString()){} - - explicit MsgAddress(const RsPeerId& pid, MsgAddress::AddressMode mmode) - : _type(MSG_ADDRESS_TYPE_RSPEERID), _mode(mmode), _addr_string(pid.toStdString()){} - - explicit MsgAddress(const std::string& email, MsgAddress::AddressMode mmode) - : _type(MSG_ADDRESS_TYPE_EMAIL), _mode(mmode), _addr_string(email){} - - MsgAddress::AddressType type() { return _type ;} - MsgAddress::AddressMode mode() { return _mode ;} - - RsGxsId toGxsId() const { assert(_type==MSG_ADDRESS_TYPE_RSGXSID );return RsGxsId (_addr_string);} - RsPeerId toRsPeerId() const { assert(_type==MSG_ADDRESS_TYPE_RSPEERID);return RsPeerId(_addr_string);} - std::string toEmail() const { assert(_type==MSG_ADDRESS_TYPE_EMAIL );return _addr_string ;} - - private: - AddressType _type ; - AddressMode _mode ; - std::string _addr_string ; -}; - -struct MessageInfo : RsSerializable -{ - MessageInfo(): msgflags(0), size(0), count(0), ts(0) {} - - std::string msgId; - - RsPeerId rspeerid_srcId; - RsGxsId rsgxsid_srcId; - - unsigned int msgflags; - - // friend destinations - // - std::set rspeerid_msgto; // RsPeerId is used here for various purposes: - std::set rspeerid_msgcc; // - real peer ids which are actual friend locations - std::set rspeerid_msgbcc; // - - - // distant peers - // - std::set rsgxsid_msgto; // RsPeerId is used here for various purposes: - std::set rsgxsid_msgcc; // - real peer ids which are actual friend locations - std::set rsgxsid_msgbcc; // - - - std::string title; - std::string msg; - - std::string attach_title; - std::string attach_comment; - std::list files; - - int size; /* total of files */ - int count; /* file count */ - - int ts; - - // RsSerializable interface - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext &ctx ) override - { - RS_SERIAL_PROCESS(msgId); - - RS_SERIAL_PROCESS(rspeerid_srcId); - RS_SERIAL_PROCESS(rsgxsid_srcId); - - RS_SERIAL_PROCESS(msgflags); - - RS_SERIAL_PROCESS(rspeerid_msgto); - RS_SERIAL_PROCESS(rspeerid_msgcc); - RS_SERIAL_PROCESS(rspeerid_msgbcc); - - RS_SERIAL_PROCESS(rsgxsid_msgto); - RS_SERIAL_PROCESS(rsgxsid_msgcc); - RS_SERIAL_PROCESS(rsgxsid_msgcc); - - RS_SERIAL_PROCESS(title); - RS_SERIAL_PROCESS(msg); - - RS_SERIAL_PROCESS(attach_title); - RS_SERIAL_PROCESS(attach_comment); - RS_SERIAL_PROCESS(files); - - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(count); - - RS_SERIAL_PROCESS(ts); - } - - ~MessageInfo() override; -}; - -struct MsgInfoSummary : RsSerializable -{ - MsgInfoSummary() : msgflags(0), count(0), ts(0) {} - - RsMailMessageId msgId; - RsPeerId srcId; - - uint32_t msgflags; - std::list msgtags; /// that leaves 25 bits for user-defined tags. - - std::string title; - int count; /** file count */ - rstime_t ts; - - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext &ctx) override - { - RS_SERIAL_PROCESS(msgId); - RS_SERIAL_PROCESS(srcId); - - RS_SERIAL_PROCESS(msgflags); - RS_SERIAL_PROCESS(msgtags); - - RS_SERIAL_PROCESS(title); - RS_SERIAL_PROCESS(count); - RS_SERIAL_PROCESS(ts); - } - - ~MsgInfoSummary() override; -}; - -struct MsgTagInfo : RsSerializable -{ - virtual ~MsgTagInfo() = default; - - std::string msgId; - std::list tagIds; - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(msgId); - RS_SERIAL_PROCESS(tagIds); - } -}; - -struct MsgTagType : RsSerializable -{ - virtual ~MsgTagType() = default; - /* map containing tagId -> pair (text, rgb color) */ - std::map > types; - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(types); - } -}; - -} //namespace Rs -} //namespace Msgs - -enum class RsMailStatusEventCode: uint8_t -{ - NEW_MESSAGE = 0x00, - MESSAGE_REMOVED = 0x01, - MESSAGE_SENT = 0x02, - - /// means the peer received the message - MESSAGE_RECEIVED_ACK = 0x03, - - /// An error occurred attempting to sign the message - SIGNATURE_FAILED = 0x04, -}; - -struct RsMailStatusEvent : RsEvent -{ - RsMailStatusEvent() : RsEvent(RsEventType::MAIL_STATUS) {} - - RsMailStatusEventCode mMailStatusEventCode; - std::set mChangedMsgIds; - - /// @see RsEvent - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mChangedMsgIds); - RS_SERIAL_PROCESS(mMailStatusEventCode); - } - - ~RsMailStatusEvent() override = default; -}; - -#define RS_CHAT_PUBLIC 0x0001 -#define RS_CHAT_PRIVATE 0x0002 -#define RS_CHAT_AVATAR_AVAILABLE 0x0004 - -#define RS_DISTANT_CHAT_STATUS_UNKNOWN 0x0000 -#define RS_DISTANT_CHAT_STATUS_TUNNEL_DN 0x0001 -#define RS_DISTANT_CHAT_STATUS_CAN_TALK 0x0002 -#define RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED 0x0003 - -#define RS_DISTANT_CHAT_ERROR_NO_ERROR 0x0000 -#define RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED 0x0001 -#define RS_DISTANT_CHAT_ERROR_SIGNATURE_MISMATCH 0x0002 -#define RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY 0x0003 -#define RS_DISTANT_CHAT_ERROR_UNKNOWN_HASH 0x0004 - -#define RS_DISTANT_CHAT_FLAG_SIGNED 0x0001 -#define RS_DISTANT_CHAT_FLAG_SIGNATURE_OK 0x0002 - -// flags to define who we accept to talk to. Each flag *removes* some people. - -#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NONE 0x0000 -#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS 0x0001 -#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY 0x0002 - -#define RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_NONE 0x0000 -#define RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS 0x0001 -#define RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY 0x0002 - -struct DistantChatPeerInfo : RsSerializable -{ - DistantChatPeerInfo() : status(0),pending_items(0) {} - - RsGxsId to_id ; - RsGxsId own_id ; - DistantChatPeerId peer_id ; // this is the tunnel id actually - uint32_t status ; // see the values in rsmsgs.h - uint32_t pending_items; // items not sent, waiting for a tunnel - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(to_id); - RS_SERIAL_PROCESS(own_id); - RS_SERIAL_PROCESS(peer_id); - RS_SERIAL_PROCESS(status); - RS_SERIAL_PROCESS(pending_items); - } -}; - -// Identifier for an chat endpoint like -// neighbour peer, distant peer, chatlobby, broadcast -class ChatId : RsSerializable -{ -public: - ChatId(); - virtual ~ChatId() = default; - - explicit ChatId(RsPeerId id); - explicit ChatId(ChatLobbyId id); - explicit ChatId(DistantChatPeerId id); - explicit ChatId(std::string str); - static ChatId makeBroadcastId(); - - std::string toStdString() const; - bool operator<(const ChatId& other) const; - bool isSameEndpoint(const ChatId& other) const; - - bool operator==(const ChatId& other) const { return isSameEndpoint(other) ; } - - bool isNotSet() const; - bool isPeerId() const; - bool isDistantChatId() const; - bool isLobbyId() const; - bool isBroadcast() const; - - RsPeerId toPeerId() const; - ChatLobbyId toLobbyId() const; - DistantChatPeerId toDistantChatId() const; - - // for the very specific case of transfering a status string - // from the chatservice to the gui, - // this defines from which peer the status string came from - RsPeerId broadcast_status_peer_id; -private: - enum Type : uint8_t - { TYPE_NOT_SET, - TYPE_PRIVATE, // private chat with directly connected friend, peer_id is valid - TYPE_PRIVATE_DISTANT, // private chat with distant peer, gxs_id is valid - TYPE_LOBBY, // chat lobby id, lobby_id is valid - TYPE_BROADCAST // message to/from all connected peers - }; - - Type type; - RsPeerId peer_id; - DistantChatPeerId distant_chat_id; - ChatLobbyId lobby_id; - - // RsSerializable interface -public: - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(broadcast_status_peer_id); - RS_SERIAL_PROCESS(type); - RS_SERIAL_PROCESS(peer_id); - RS_SERIAL_PROCESS(distant_chat_id); - RS_SERIAL_PROCESS(lobby_id); - } -}; - -struct ChatMessage : RsSerializable -{ - ChatId chat_id; // id of chat endpoint - RsPeerId broadcast_peer_id; // only used for broadcast chat: source peer id - RsGxsId lobby_peer_gxs_id; // only used for lobbys: nickname of message author - std::string peer_alternate_nickname; // only used when key is unknown. - - unsigned int chatflags; - uint32_t sendTime; - uint32_t recvTime; - std::string msg; - bool incoming; - bool online; // for outgoing messages: was this message send? - //bool system_message; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(chat_id); - RS_SERIAL_PROCESS(broadcast_peer_id); - RS_SERIAL_PROCESS(lobby_peer_gxs_id); - RS_SERIAL_PROCESS(peer_alternate_nickname); - - RS_SERIAL_PROCESS(chatflags); - RS_SERIAL_PROCESS(sendTime); - RS_SERIAL_PROCESS(recvTime); - RS_SERIAL_PROCESS(msg); - RS_SERIAL_PROCESS(incoming); - RS_SERIAL_PROCESS(online); - } -}; - -class ChatLobbyInvite : RsSerializable -{ -public: - virtual ~ChatLobbyInvite() = default; - - ChatLobbyId lobby_id ; - RsPeerId peer_id ; - std::string lobby_name ; - std::string lobby_topic ; - ChatLobbyFlags lobby_flags ; - - // RsSerializable interface -public: - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(lobby_id); - RS_SERIAL_PROCESS(peer_id); - RS_SERIAL_PROCESS(lobby_name); - RS_SERIAL_PROCESS(lobby_topic); - RS_SERIAL_PROCESS(lobby_flags); - } -}; - -struct VisibleChatLobbyRecord : RsSerializable -{ - VisibleChatLobbyRecord(): - lobby_id(0), total_number_of_peers(0), last_report_time(0) {} - - ChatLobbyId lobby_id ; // unique id of the lobby - std::string lobby_name ; // name to use for this lobby - std::string lobby_topic ; // topic to use for this lobby - std::set participating_friends ; // list of direct friend who participate. - - uint32_t total_number_of_peers ; // total number of particpating peers. Might not be - rstime_t last_report_time ; // last time the lobby was reported. - ChatLobbyFlags lobby_flags ; // see RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC / RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext &ctx) override - { - RS_SERIAL_PROCESS(lobby_id); - RS_SERIAL_PROCESS(lobby_name); - RS_SERIAL_PROCESS(lobby_topic); - RS_SERIAL_PROCESS(participating_friends); - - RS_SERIAL_PROCESS(total_number_of_peers); - RS_SERIAL_PROCESS(last_report_time); - RS_SERIAL_PROCESS(lobby_flags); - } - - ~VisibleChatLobbyRecord() override; -}; - -class ChatLobbyInfo : RsSerializable -{ -public: - virtual ~ChatLobbyInfo() = default; - - ChatLobbyId lobby_id ; // unique id of the lobby - std::string lobby_name ; // name to use for this lobby - std::string lobby_topic ; // topic to use for this lobby - std::set participating_friends ; // list of direct friend who participate. Used to broadcast sent messages. - RsGxsId gxs_id ; // ID to sign messages - - ChatLobbyFlags lobby_flags ; // see RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC / RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE - std::map 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. - - virtual void clear() { gxs_ids.clear(); lobby_id = 0; lobby_name.clear(); lobby_topic.clear(); participating_friends.clear(); } - - // RsSerializable interface -public: - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(lobby_id); - RS_SERIAL_PROCESS(lobby_name); - RS_SERIAL_PROCESS(lobby_topic); - RS_SERIAL_PROCESS(participating_friends); - RS_SERIAL_PROCESS(gxs_id); - - RS_SERIAL_PROCESS(lobby_flags); - RS_SERIAL_PROCESS(gxs_ids); - RS_SERIAL_PROCESS(last_activity); - } -}; - - -class RsMsgs; -/** - * @brief Pointer to retroshare's message service - * @jsonapi{development} - */ -extern RsMsgs* rsMsgs; - -class RsMsgs -{ -public: - - /** - * @brief getMessageSummaries - * @jsonapi{development} - * @param[out] msgList - * @return always true - */ - virtual bool getMessageSummaries(std::list &msgList) = 0; - - /** - * @brief getMessage - * @jsonapi{development} - * @param[in] msgId message ID to lookup - * @param[out] msg - * @return true on success - */ - virtual bool getMessage(const std::string &msgId, Rs::Msgs::MessageInfo &msg) = 0; - - /** - * @brief sendMail - * @jsonapi{development} - * @param[in] from GXS id of the author - * @param[in] subject Mail subject - * @param[in] mailBody Mail body - * @param[in] to list of To: recipients - * @param[in] cc list of CC: recipients - * @param[in] bcc list of BCC: recipients - * @param[in] attachments list of suggested files - * @param[out] trackingIds storage for tracking ids for each sent mail - * @param[out] errorMsg error message if errors occurred, empty otherwise - * @return number of successfully sent mails - */ - virtual uint32_t sendMail( - const RsGxsId from, - const std::string& subject, - const std::string& mailBody, - const std::set& to = std::set(), - const std::set& cc = std::set(), - const std::set& bcc = std::set(), - const std::vector& attachments = std::vector(), - std::set& trackingIds = - RS_DEFAULT_STORAGE_PARAM(std::set), - std::string& errorMsg = - RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief getMessageCount - * @jsonapi{development} - * @param[out] nInbox - * @param[out] nInboxNew - * @param[out] nOutbox - * @param[out] nDraftbox - * @param[out] nSentbox - * @param[out] nTrashbox - */ - virtual void getMessageCount(uint32_t &nInbox, uint32_t &nInboxNew, uint32_t &nOutbox, uint32_t &nDraftbox, uint32_t &nSentbox, uint32_t &nTrashbox) = 0; - - /** - * @brief SystemMessage - * @jsonapi{development} - * @param[in] title - * @param[in] message - * @param[in] systemFlag - * @return true on success - */ - virtual bool SystemMessage(const std::string &title, const std::string &message, uint32_t systemFlag) = 0; - - /** - * @brief MessageToDraft - * @jsonapi{development} - * @param[in] info - * @param[in] msgParentId - * @return true on success - */ - virtual bool MessageToDraft(Rs::Msgs::MessageInfo &info, const std::string &msgParentId) = 0; - - /** - * @brief MessageToTrash - * @jsonapi{development} - * @param[in] msgId Id of the message to mode to trash box - * @param[in] bTrash Move to trash if true, otherwise remove from trash - * @return true on success - */ - virtual bool MessageToTrash(const std::string &msgId, bool bTrash) = 0; - - /** - * @brief getMsgParentId - * @jsonapi{development} - * @param[in] msgId - * @param[out] msgParentId - * @return true on success - */ - virtual bool getMsgParentId(const std::string &msgId, std::string &msgParentId) = 0; - - /** - * @brief MessageDelete - * @jsonapi{development} - * @param[in] msgId - * @return true on success - */ - virtual bool MessageDelete(const std::string &msgId) = 0; - - /** - * @brief MessageRead - * @jsonapi{development} - * @param[in] msgId - * @param[in] unreadByUser - * @return true on success - */ - virtual bool MessageRead(const std::string &msgId, bool unreadByUser) = 0; - - /** - * @brief MessageReplied - * @jsonapi{development} - * @param[in] msgId - * @param[in] replied - * @return true on success - */ - virtual bool MessageReplied(const std::string &msgId, bool replied) = 0; - - /** - * @brief MessageForwarded - * @jsonapi{development} - * @param[in] msgId - * @param[in] forwarded - * @return true on success - */ - virtual bool MessageForwarded(const std::string &msgId, bool forwarded) = 0; - - /** - * @brief MessageStar - * @jsonapi{development} - * @param[in] msgId - * @param[in] mark - * @return true on success - */ - virtual bool MessageStar(const std::string &msgId, bool mark) = 0; - - /** - * @brief MessageJunk - * @jsonapi{development} - * @param[in] msgId - * @param[in] mark - * @return true on success - */ - virtual bool MessageJunk(const std::string &msgId, bool mark) = 0; - - /** - * @brief MessageLoadEmbeddedImages - * @jsonapi{development} - * @param[in] msgId - * @param[in] load - * @return true on success - */ - virtual bool MessageLoadEmbeddedImages(const std::string &msgId, bool load) = 0; - - /* message tagging */ - /** - * @brief getMessageTagTypes - * @jsonapi{development} - * @param[out] tags - * @return always true - */ - virtual bool getMessageTagTypes(Rs::Msgs::MsgTagType& tags) = 0; - - /** - * @brief setMessageTagType - * @jsonapi{development} - * @param[in] tagId - * @param[in] text - * @param[in] rgb_color - * @return true on success - */ - virtual bool setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color) = 0; - - /** - * @brief removeMessageTagType - * @jsonapi{development} - * @param[in] tagId - * @return true on success - */ - virtual bool removeMessageTagType(uint32_t tagId) = 0; - - /** - * @brief getMessageTag - * @jsonapi{development} - * @param[in] msgId - * @param[out] info - * @return true on success - */ - virtual bool getMessageTag(const std::string &msgId, Rs::Msgs::MsgTagInfo& info) = 0; - - /** - * @brief setMessageTag - * set == false && tagId == 0 --> remove all - * @jsonapi{development} - * @param[in] msgId - * @param[in] tagId - * @param[in] set - * @return true on success - */ - virtual bool setMessageTag(const std::string &msgId, uint32_t tagId, bool set) = 0; - - /** - * @brief resetMessageStandardTagTypes - * @jsonapi{development} - * @param[out] tags - * @return always true - */ - virtual bool resetMessageStandardTagTypes(Rs::Msgs::MsgTagType& tags) = 0; - - /****************************************/ - /* Private distant messages */ - /****************************************/ - - virtual uint32_t getDistantMessagingPermissionFlags()=0 ; - virtual void setDistantMessagingPermissionFlags(uint32_t flags)=0 ; - - /****************************************/ - /* Chat */ - /****************************************/ - // sendChat for broadcast, private, lobby and private distant chat - // note: for lobby chat, you first have to subscribe to a lobby - // for private distant chat, it is reqired to have an active distant chat session - - /** - * @brief sendChat send a chat message to a given id - * @jsonapi{development} - * @param[in] id id to send the message - * @param[in] msg message to send - * @return true on success - */ - virtual bool sendChat(ChatId id, std::string msg) = 0; - - /** - * @brief getMaxMessageSecuritySize get the maximum size of a chta message - * @jsonapi{development} - * @param[in] type chat type - * @return maximum size or zero for infinite - */ - virtual uint32_t getMaxMessageSecuritySize(int type) = 0; - - /** - * @brief sendStatusString send a status string - * @jsonapi{development} - * @param[in] id chat id to send the status string to - * @param[in] status_string status string - */ - virtual void sendStatusString(const ChatId &id, const std::string &status_string) = 0; - - /** - * @brief clearChatLobby clear a chat lobby - * @jsonapi{development} - * @param[in] id chat lobby id to clear - */ - virtual void clearChatLobby(const ChatId &id) = 0; - - /** - * @brief setCustomStateString set your custom status message - * @jsonapi{development} - * @param[in] status_string status message - */ - virtual void setCustomStateString(const std::string &status_string) = 0; - - /** - * @brief getCustomStateString get your custom status message - * @return status message - */ - virtual std::string getCustomStateString() = 0; - - /** - * @brief getCustomStateString get the custom status message from a peer - * @jsonapi{development} - * @param[in] peer_id peer id to the peer you want to get the status message from - * @return status message - */ - virtual std::string getCustomStateString(const RsPeerId &peer_id) = 0; - -// get avatar data for peer pid -virtual void getAvatarData(const RsPeerId& pid,unsigned char *& data,int& size) = 0 ; -// set own avatar data -virtual void setOwnAvatarData(const unsigned char *data,int size) = 0 ; -virtual void getOwnAvatarData(unsigned char *& data,int& size) = 0 ; - - /****************************************/ - /* Chat lobbies */ - /****************************************/ - /** - * @brief joinVisibleChatLobby join a lobby that is visible - * @jsonapi{development} - * @param[in] lobby_id lobby to join to - * @param[in] own_id chat id to use - * @return true on success - */ - virtual bool joinVisibleChatLobby(const ChatLobbyId &lobby_id, const RsGxsId &own_id) = 0 ; - - /** - * @brief getChatLobbyList get ids of subscribed lobbies - * @jsonapi{development} - * @param[out] cl_list lobby list - */ - virtual void getChatLobbyList(std::list &cl_list) = 0; - - /** - * @brief getChatLobbyInfo get lobby info of a subscribed chat lobby. Returns true if lobby id is valid. - * @jsonapi{development} - * @param[in] id id to get infos from - * @param[out] info lobby infos - * @return true on success - */ - virtual bool getChatLobbyInfo(const ChatLobbyId &id, ChatLobbyInfo &info) = 0 ; - - /** - * @brief getListOfNearbyChatLobbies get info about all lobbies, subscribed and unsubscribed - * @jsonapi{development} - * @param[out] public_lobbies list of all visible lobbies - */ - virtual void getListOfNearbyChatLobbies(std::vector &public_lobbies) = 0 ; - - /** - * @brief invitePeerToLobby invite a peer to join a lobby - * @jsonapi{development} - * @param[in] lobby_id lobby it to invite into - * @param[in] peer_id peer to invite - */ - virtual void invitePeerToLobby(const ChatLobbyId &lobby_id, const RsPeerId &peer_id) = 0; - - /** - * @brief acceptLobbyInvite accept a chat invite - * @jsonapi{development} - * @param[in] id chat lobby id you were invited into and you want to join - * @param[in] identity chat identity to use - * @return true on success - */ - virtual bool acceptLobbyInvite(const ChatLobbyId &id, const RsGxsId &identity) = 0 ; - - /** - * @brief denyLobbyInvite deny a chat lobby invite - * @jsonapi{development} - * @param[in] id chat lobby id you were invited into - */ - virtual void denyLobbyInvite(const ChatLobbyId &id) = 0 ; - - /** - * @brief getPendingChatLobbyInvites get a list of all pending chat lobby invites - * @jsonapi{development} - * @param[out] invites list of all pending chat lobby invites - */ - virtual void getPendingChatLobbyInvites(std::list &invites) = 0; - - /** - * @brief unsubscribeChatLobby leave a chat lobby - * @jsonapi{development} - * @param[in] lobby_id lobby to leave - */ - 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 - * @jsonapi{development} - * @param[in] lobby_id lobby to change the chat idnetity for - * @param[in] nick new chat identity - * @return true on success - */ - virtual bool setIdentityForChatLobby(const ChatLobbyId &lobby_id, const RsGxsId &nick) = 0; - - /** - * @brief getIdentityForChatLobby - * @jsonapi{development} - * @param[in] lobby_id lobby to get the chat id from - * @param[out] nick chat identity - * @return true on success - */ - virtual bool getIdentityForChatLobby(const ChatLobbyId &lobby_id, RsGxsId &nick) = 0 ; - - /** - * @brief setDefaultIdentityForChatLobby set the default identity used for chat lobbies - * @jsonapi{development} - * @param[in] nick chat identitiy to use - * @return true on success - */ - virtual bool setDefaultIdentityForChatLobby(const RsGxsId &nick) = 0; - - /** - * @brief getDefaultIdentityForChatLobby get the default identity used for chat lobbies - * @jsonapi{development} - * @param[out] id chat identitiy to use - */ - virtual void getDefaultIdentityForChatLobby(RsGxsId &id) = 0 ; - - /** - * @brief setLobbyAutoSubscribe enable or disable auto subscribe for a chat lobby - * @jsonapi{development} - * @param[in] lobby_id lobby to auto (un)subscribe - * @param[in] autoSubscribe set value for auto subscribe - */ - virtual void setLobbyAutoSubscribe(const ChatLobbyId &lobby_id, const bool autoSubscribe) = 0 ; - - /** - * @brief getLobbyAutoSubscribe get current value of auto subscribe - * @jsonapi{development} - * @param[in] lobby_id lobby to get value from - * @return wether lobby has auto subscribe enabled or disabled - */ - virtual bool getLobbyAutoSubscribe(const ChatLobbyId &lobby_id) = 0 ; - - /** - * @brief createChatLobby create a new chat lobby - * @jsonapi{development} - * @param[in] lobby_name lobby name - * @param[in] lobby_identity chat id to use for new lobby - * @param[in] lobby_topic lobby toppic - * @param[in] invited_friends list of friends to invite - * @param[in] lobby_privacy_type flag for new chat lobby - * @return chat id of new lobby - */ - virtual ChatLobbyId createChatLobby(const std::string &lobby_name, const RsGxsId &lobby_identity, const std::string &lobby_topic, const std::set &invited_friends, ChatLobbyFlags lobby_privacy_type) = 0 ; - -/****************************************/ -/* Distant chat */ -/****************************************/ - - virtual uint32_t getDistantChatPermissionFlags()=0 ; - virtual bool setDistantChatPermissionFlags(uint32_t flags)=0 ; - - /** - * @brief initiateDistantChatConnexion initiate a connexion for a distant chat - * @jsonapi{development} - * @param[in] to_pid RsGxsId to start the connection - * @param[in] from_pid owned RsGxsId who start the connection - * @param[out] pid distant chat id - * @param[out] error_code if the connection can't be stablished - * @param[in] notify notify remote that the connection is stablished - * @return true on success. If you try to initate a connection already started it will return the pid of it. - */ - virtual bool initiateDistantChatConnexion( - const RsGxsId& to_pid, const RsGxsId& from_pid, - DistantChatPeerId& pid, uint32_t& error_code, - bool notify = true ) = 0; - - /** - * @brief getDistantChatStatus receives distant chat info to a given distant chat id - * @jsonapi{development} - * @param[in] pid distant chat id - * @param[out] info distant chat info - * @return true on success - */ - virtual bool getDistantChatStatus(const DistantChatPeerId& pid, DistantChatPeerInfo& info)=0; - - /** - * @brief closeDistantChatConnexion - * @jsonapi{development} - * @param[in] pid distant chat id to close the connection - * @return true on success - */ - virtual bool closeDistantChatConnexion(const DistantChatPeerId& pid)=0; - - /** - * @brief MessageSend - * @jsonapi{development} - * @param[in] info - * @return always true - */ - RS_DEPRECATED_FOR(sendMail) - virtual bool MessageSend(Rs::Msgs::MessageInfo &info) = 0; - - virtual ~RsMsgs(); -}; diff --git a/libretroshare/src/retroshare/rsnotify.h b/libretroshare/src/retroshare/rsnotify.h deleted file mode 100644 index e8c9de614..000000000 --- a/libretroshare/src/retroshare/rsnotify.h +++ /dev/null @@ -1,248 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsnotify.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include - -#include "rsturtle.h" -#include "rsgxsifacetypes.h" -#include "util/rsdeprecate.h" - -class ChatId; -class ChatMessage; -struct RsGxsChanges; - -class RsNotify; -extern RsNotify *rsNotify; - -const uint32_t RS_SYS_ERROR = 0x0001; -const uint32_t RS_SYS_WARNING = 0x0002; -const uint32_t RS_SYS_INFO = 0x0004; - -const uint32_t RS_POPUP_MSG = 0x0001; -const uint32_t RS_POPUP_CHAT = 0x0002; -//const uint32_t RS_POPUP_CALL = 0x0004; -const uint32_t RS_POPUP_CONNECT = 0x0008; -const uint32_t RS_SYSTRAY_GROUP_MSG = 0x0010; -const uint32_t RS_POPUP_DOWNLOAD = 0x0020; -const uint32_t RS_POPUP_GROUPCHAT = 0x0040; -const uint32_t RS_POPUP_CHATLOBBY = 0x0080; -const uint32_t RS_POPUP_CONNECT_ATTEMPT = 0x0100; -const uint32_t RS_POPUP_ENCRYPTED_MSG = 0x0200; - -/* CHAT flags are here - so they are in the same place as - * other Notify flags... not used by libretroshare though - */ -const uint32_t RS_CHAT_OPEN = 0x0001; -//const uint32_t free = 0x0002; -const uint32_t RS_CHAT_FOCUS = 0x0004; -const uint32_t RS_CHAT_TABBED_WINDOW = 0x0008; -const uint32_t RS_CHAT_BLINK = 0x0010; - -const uint32_t RS_FEED_TYPE_PEER = 0x0010; -const uint32_t RS_FEED_TYPE_CHANNEL = 0x0020; -const uint32_t RS_FEED_TYPE_FORUM = 0x0040; -//const uint32_t RS_FEED_TYPE_BLOG = 0x0080; -const uint32_t RS_FEED_TYPE_CHAT = 0x0100; -const uint32_t RS_FEED_TYPE_MSG = 0x0200; -const uint32_t RS_FEED_TYPE_FILES = 0x0400; -const uint32_t RS_FEED_TYPE_SECURITY = 0x0800; -const uint32_t RS_FEED_TYPE_POSTED = 0x1000; -const uint32_t RS_FEED_TYPE_SECURITY_IP = 0x2000; -const uint32_t RS_FEED_TYPE_CIRCLE = 0x4000; - -const uint32_t RS_FEED_ITEM_PEER_CONNECT = RS_FEED_TYPE_PEER | 0x0001; -const uint32_t RS_FEED_ITEM_PEER_DISCONNECT = RS_FEED_TYPE_PEER | 0x0002; -const uint32_t RS_FEED_ITEM_PEER_HELLO = RS_FEED_TYPE_PEER | 0x0003; -const uint32_t RS_FEED_ITEM_PEER_NEW = RS_FEED_TYPE_PEER | 0x0004; -const uint32_t RS_FEED_ITEM_PEER_OFFSET = RS_FEED_TYPE_PEER | 0x0005; -const uint32_t RS_FEED_ITEM_PEER_DENIES_CONNEXION = RS_FEED_TYPE_PEER | 0x0006; - -const uint32_t RS_FEED_ITEM_SEC_CONNECT_ATTEMPT = RS_FEED_TYPE_SECURITY | 0x0001; -const uint32_t RS_FEED_ITEM_SEC_AUTH_DENIED = RS_FEED_TYPE_SECURITY | 0x0002; // locally denied connection -const uint32_t RS_FEED_ITEM_SEC_UNKNOWN_IN = RS_FEED_TYPE_SECURITY | 0x0003; -const uint32_t RS_FEED_ITEM_SEC_UNKNOWN_OUT = RS_FEED_TYPE_SECURITY | 0x0004; -const uint32_t RS_FEED_ITEM_SEC_WRONG_SIGNATURE = RS_FEED_TYPE_SECURITY | 0x0005; -const uint32_t RS_FEED_ITEM_SEC_BAD_CERTIFICATE = RS_FEED_TYPE_SECURITY | 0x0006; -const uint32_t RS_FEED_ITEM_SEC_INTERNAL_ERROR = RS_FEED_TYPE_SECURITY | 0x0007; -const uint32_t RS_FEED_ITEM_SEC_MISSING_CERTIFICATE = RS_FEED_TYPE_SECURITY | 0x0008; - -const uint32_t RS_FEED_ITEM_SEC_IP_BLACKLISTED = RS_FEED_TYPE_SECURITY_IP | 0x0001; -const uint32_t RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED = RS_FEED_TYPE_SECURITY_IP | 0x0002; - -const uint32_t RS_FEED_ITEM_CHANNEL_NEW = RS_FEED_TYPE_CHANNEL | 0x0001; -//const uint32_t RS_FEED_ITEM_CHANNEL_UPDATE = RS_FEED_TYPE_CHANNEL | 0x0002; -const uint32_t RS_FEED_ITEM_CHANNEL_MSG = RS_FEED_TYPE_CHANNEL | 0x0003; -const uint32_t RS_FEED_ITEM_CHANNEL_PUBLISHKEY = RS_FEED_TYPE_CHANNEL | 0x0004; - -const uint32_t RS_FEED_ITEM_FORUM_NEW = RS_FEED_TYPE_FORUM | 0x0001; -//const uint32_t RS_FEED_ITEM_FORUM_UPDATE = RS_FEED_TYPE_FORUM | 0x0002; -const uint32_t RS_FEED_ITEM_FORUM_MSG = RS_FEED_TYPE_FORUM | 0x0003; -const uint32_t RS_FEED_ITEM_FORUM_PUBLISHKEY = RS_FEED_TYPE_FORUM | 0x0004; - -//const uint32_t RS_FEED_ITEM_BLOG_NEW = RS_FEED_TYPE_BLOG | 0x0001; -//const uint32_t RS_FEED_ITEM_BLOG_UPDATE = RS_FEED_TYPE_BLOG | 0x0002; -//const uint32_t RS_FEED_ITEM_BLOG_MSG = RS_FEED_TYPE_BLOG | 0x0003; - -const uint32_t RS_FEED_ITEM_POSTED_NEW = RS_FEED_TYPE_POSTED | 0x0001; -//const uint32_t RS_FEED_ITEM_POSTED_UPDATE = RS_FEED_TYPE_POSTED | 0x0002; -const uint32_t RS_FEED_ITEM_POSTED_MSG = RS_FEED_TYPE_POSTED | 0x0003; - -const uint32_t RS_FEED_ITEM_CHAT_NEW = RS_FEED_TYPE_CHAT | 0x0001; -const uint32_t RS_FEED_ITEM_MESSAGE = RS_FEED_TYPE_MSG | 0x0001; -const uint32_t RS_FEED_ITEM_FILES_NEW = RS_FEED_TYPE_FILES | 0x0001; - -const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_REQ = RS_FEED_TYPE_CIRCLE | 0x0001; -const uint32_t RS_FEED_ITEM_CIRCLE_INVITE_REC = RS_FEED_TYPE_CIRCLE | 0x0002; -const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_LEAVE = RS_FEED_TYPE_CIRCLE | 0x0003; -const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_JOIN = RS_FEED_TYPE_CIRCLE | 0x0004; -const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_ACCEPTED = RS_FEED_TYPE_CIRCLE | 0x0005; -const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_REVOKED = RS_FEED_TYPE_CIRCLE | 0x0006; -const uint32_t RS_FEED_ITEM_CIRCLE_INVITE_CANCELLED= RS_FEED_TYPE_CIRCLE | 0x0007; - -const uint32_t RS_MESSAGE_CONNECT_ATTEMPT = 0x0001; - -const int NOTIFY_LIST_NEIGHBOURS = 1; -const int NOTIFY_LIST_FRIENDS = 2; -const int NOTIFY_LIST_SEARCHLIST = 4; -const int NOTIFY_LIST_MESSAGELIST = 5; -const int NOTIFY_LIST_CHANNELLIST = 6; -const int NOTIFY_LIST_TRANSFERLIST = 7; -const int NOTIFY_LIST_CONFIG = 8; -const int NOTIFY_LIST_DIRLIST_LOCAL = 9; -const int NOTIFY_LIST_DIRLIST_FRIENDS = 10; -const int NOTIFY_LIST_FORUMLIST_LOCKED = 11; // use connect with Qt::QueuedConnection -const int NOTIFY_LIST_MESSAGE_TAGS = 12; -const int NOTIFY_LIST_PUBLIC_CHAT = 13; -const int NOTIFY_LIST_PRIVATE_INCOMING_CHAT = 14; -const int NOTIFY_LIST_PRIVATE_OUTGOING_CHAT = 15; -const int NOTIFY_LIST_GROUPLIST = 16; -const int NOTIFY_LIST_CHANNELLIST_LOCKED = 17; // use connect with Qt::QueuedConnection -const int NOTIFY_LIST_CHAT_LOBBY_INVITATION = 18; -const int NOTIFY_LIST_CHAT_LOBBY_LIST = 19; - -const int NOTIFY_TYPE_SAME = 0x01; -const int NOTIFY_TYPE_MOD = 0x02; /* general purpose, check all */ -const int NOTIFY_TYPE_ADD = 0x04; /* flagged additions */ -const int NOTIFY_TYPE_DEL = 0x08; /* flagged deletions */ - -const uint32_t NOTIFY_HASHTYPE_EXAMINING_FILES = 1; /* Examining shared files */ -const uint32_t NOTIFY_HASHTYPE_FINISH = 2; /* Finish */ -const uint32_t NOTIFY_HASHTYPE_HASH_FILE = 3; /* Hashing file */ -const uint32_t NOTIFY_HASHTYPE_SAVE_FILE_INDEX = 4; /* Hashing file */ - -class RS_DEPRECATED RsFeedItem -{ - public: - RsFeedItem(uint32_t type, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4, uint32_t result1) - :mType(type), mId1(id1), mId2(id2), mId3(id3), mId4(id4), mResult1(result1) {} - - RsFeedItem() :mType(0), mResult1(0) { return; } - - uint32_t mType; - std::string mId1, mId2, mId3, mId4; - uint32_t mResult1; -}; - -// This class implements a generic notify client. To have your own components being notified by -// the Retroshare library, sub-class NotifyClient, and overload the methods you want to make use of -// (The other methods will just ignore the call), and register your ownclient into RsNotify, as: -// -// myNotifyClient: public NotifyClient -// { -// public: -// virtual void void notifyPeerHasNewAvatar(std::string peer_id) -// { -// doMyOwnThing() ; -// } -// } -// -// myNotifyClient *client = new myNotifyClient() ; -// -// rsNotify->registerNotifyClient(client) ; -// -// This mechanism can be used in plugins, new services, etc. -// - -class RS_DEPRECATED NotifyClient; - -class RS_DEPRECATED_FOR(RsEvents) RsNotify -{ - public: - /* registration of notifies clients */ - virtual void registerNotifyClient(NotifyClient *nc) = 0; - /* returns true if NotifyClient was found */ - virtual bool unregisterNotifyClient(NotifyClient *nc) = 0; - - /* Pull methods for retroshare-gui */ - /* this should probably go into a different service. */ - - virtual bool NotifySysMessage(uint32_t &sysid, uint32_t &type, std::string &title, std::string &msg) = 0; - virtual bool NotifyPopupMessage(uint32_t &ptype, std::string &name, std::string &title, std::string &msg) = 0; - virtual bool NotifyLogMessage(uint32_t &sysid, uint32_t &type, std::string &title, std::string &msg) = 0; - - virtual bool GetFeedItem(RsFeedItem &item) = 0; - - virtual bool cachePgpPassphrase (const std::string& /* pgp_passphrase */) { return false ; } - virtual bool clearPgpPassphrase () { return false ; } - - virtual bool setDisableAskPassword (const bool /*bValue*/) { return false ; } -}; - -class RS_DEPRECATED NotifyClient -{ -public: - NotifyClient() {} - virtual ~NotifyClient() {} - - virtual void notifyListPreChange (int /* list */, int /* type */) {} - virtual void notifyListChange (int /* list */, int /* type */) {} - virtual void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) {} - virtual void notifyChatMessage (const ChatMessage& /* msg */) {} - virtual void notifyChatStatus (const ChatId& /* chat_id */, const std::string& /* status_string */) {} - virtual void notifyChatCleared (const ChatId& /* chat_id */) {} - virtual void notifyChatLobbyEvent (uint64_t /* lobby id */, uint32_t /* event type */ ,const RsGxsId& /* nickname */,const std::string& /* any string */) {} - virtual void notifyChatLobbyTimeShift (int /* time_shift*/) {} - virtual void notifyCustomState (const std::string& /* peer_id */, const std::string& /* status_string */) {} - virtual void notifyHashingInfo (uint32_t /* type */, const std::string& /* fileinfo */) {} - virtual void notifyTurtleSearchResult (const RsPeerId& /* pid */, uint32_t /* search_id */, const std::list& /* files */) {} - virtual void notifyPeerHasNewAvatar (std::string /* peer_id */) {} - virtual void notifyOwnAvatarChanged () {} - virtual void notifyOwnStatusMessageChanged () {} - virtual void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) {} - virtual void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) {} - - /* one or more peers has changed the states */ - virtual void notifyPeerStatusChangedSummary () {} - virtual void notifyDiscInfoChanged () {} - - virtual void notifyDownloadComplete (const std::string& /* fileHash */) {} - virtual void notifyDownloadCompleteCount (uint32_t /* count */) {} - virtual void notifyHistoryChanged (uint32_t /* msgId */, int /* type */) {} - - virtual bool askForPassword (const std::string& /* title */, const std::string& /* key_details */, bool /* prev_is_bad */, std::string& /* password */,bool& /* cancelled */ ) { return false ;} - virtual bool askForPluginConfirmation (const std::string& /* plugin_filename */, const std::string& /* plugin_file_hash */,bool /* first_time */) { return false ;} -}; diff --git a/libretroshare/src/retroshare/rspeers.h b/libretroshare/src/retroshare/rspeers.h deleted file mode 100644 index 3fdbbaf17..000000000 --- a/libretroshare/src/retroshare/rspeers.h +++ /dev/null @@ -1,997 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rspeers.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 by Robert Fernie * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "retroshare/rstypes.h" -#include "retroshare/rsfiles.h" -#include "retroshare/rsids.h" -#include "util/rsurl.h" -#include "util/rsdeprecate.h" -#include "util/rstime.h" -#include "retroshare/rsevents.h" - -class RsPeers; - -/** - * Pointer to global instance of RsPeers service implementation - * @jsonapi{development} - */ -extern RsPeers* rsPeers; - -/* TODO: 2015/12/31 As for type safetyness all those constant must be declared as enum! - * C++ now supports typed enum so there is no ambiguity in serialization size - */ - -/* Trust Levels. Should be the same values than what is declared in PGPHandler.h */ - -const uint32_t RS_TRUST_LVL_UNDEFINED = 0; -const uint32_t RS_TRUST_LVL_UNKNOWN = 1; -const uint32_t RS_TRUST_LVL_NEVER = 2; -const uint32_t RS_TRUST_LVL_MARGINAL = 3; -const uint32_t RS_TRUST_LVL_FULL = 4; -const uint32_t RS_TRUST_LVL_ULTIMATE = 5; - - -const uint32_t SELF_SIGNATURE_RESULT_PENDING = 0x00; -const uint32_t SELF_SIGNATURE_RESULT_SUCCESS = 0x01; -const uint32_t SELF_SIGNATURE_RESULT_FAILED = 0x02; - -/* Net Mode */ -const uint32_t RS_NETMODE_UDP = 0x0001; -const uint32_t RS_NETMODE_UPNP = 0x0002; -const uint32_t RS_NETMODE_EXT = 0x0003; -const uint32_t RS_NETMODE_HIDDEN = 0x0004; -const uint32_t RS_NETMODE_UNREACHABLE = 0x0005; - -/* Hidden Type */ -const uint32_t RS_HIDDEN_TYPE_NONE = 0x0000; -const uint32_t RS_HIDDEN_TYPE_UNKNOWN = 0x0001; -const uint32_t RS_HIDDEN_TYPE_TOR = 0x0002; -const uint32_t RS_HIDDEN_TYPE_I2P = 0x0004; -/* mask to match all valid hidden types */ -const uint32_t RS_HIDDEN_TYPE_MASK = RS_HIDDEN_TYPE_I2P | RS_HIDDEN_TYPE_TOR; - -/* Visibility parameter for discovery */ -const uint32_t RS_VS_DISC_OFF = 0x0000; -const uint32_t RS_VS_DISC_MINIMAL = 0x0001; -const uint32_t RS_VS_DISC_FULL = 0x0002; - -const uint32_t RS_VS_DHT_OFF = 0x0000; -const uint32_t RS_VS_DHT_PASSIVE = 0x0001; -const uint32_t RS_VS_DHT_FULL = 0x0002; - -/* State */ -const uint32_t RS_PEER_STATE_FRIEND = 0x0001; -const uint32_t RS_PEER_STATE_ONLINE = 0x0002; -const uint32_t RS_PEER_STATE_CONNECTED = 0x0004; -const uint32_t RS_PEER_STATE_UNREACHABLE= 0x0008; - -// Service option flags. -// -const ServicePermissionFlags RS_NODE_PERM_NONE ( 0x00000000 ) ;// 0x1, 0x2 and Ox4 are deprecated. -const ServicePermissionFlags RS_NODE_PERM_DIRECT_DL ( 0x00000008 ) ;// Accept to directly DL from this peer (breaks anonymity) -const ServicePermissionFlags RS_NODE_PERM_ALLOW_PUSH ( 0x00000010 ) ;// Auto-DL files recommended by this peer -const ServicePermissionFlags RS_NODE_PERM_REQUIRE_WL ( 0x00000020 ) ;// Require white list clearance for connection -const ServicePermissionFlags RS_NODE_PERM_DEFAULT = RS_NODE_PERM_DIRECT_DL ; -const ServicePermissionFlags RS_NODE_PERM_ALL = RS_NODE_PERM_DIRECT_DL | RS_NODE_PERM_ALLOW_PUSH | RS_NODE_PERM_REQUIRE_WL; - -// ... - -/* Connect state */ -const uint32_t RS_PEER_CONNECTSTATE_OFFLINE = 0; -const uint32_t RS_PEER_CONNECTSTATE_TRYING_TCP = 2; -const uint32_t RS_PEER_CONNECTSTATE_TRYING_UDP = 3; -const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_TCP = 4; -const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_UDP = 5; -const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_TOR = 6; -const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_I2P = 7; -const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN = 8; - -/* Error codes for certificate cleaning and cert parsing. Numbers should not overlap. */ - -const int RS_PEER_CERT_CLEANING_CODE_NO_ERROR = 0x00 ; -const int RS_PEER_CERT_CLEANING_CODE_UNKOWN_ERROR = 0x01 ; -const int RS_PEER_CERT_CLEANING_CODE_NO_BEGIN_TAG = 0x02 ; -const int RS_PEER_CERT_CLEANING_CODE_NO_END_TAG = 0x03 ; -const int RS_PEER_CERT_CLEANING_CODE_NO_CHECKSUM = 0x04 ; -const int RS_PEER_CERT_CLEANING_CODE_WRONG_NUMBER = 0x05 ; -const int RS_PEER_CERT_CLEANING_CODE_WRONG_RADIX_CHAR = 0x06 ; - -const uint32_t CERTIFICATE_PARSING_ERROR_NO_ERROR = 0x10 ; -const uint32_t CERTIFICATE_PARSING_ERROR_SIZE_ERROR = 0x11 ; -const uint32_t CERTIFICATE_PARSING_ERROR_INVALID_LOCATION_ID = 0x12 ; -const uint32_t CERTIFICATE_PARSING_ERROR_INVALID_EXTERNAL_IP = 0x13 ; -const uint32_t CERTIFICATE_PARSING_ERROR_INVALID_LOCAL_IP = 0x14 ; -const uint32_t CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION = 0x15 ; -const uint32_t CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR = 0x16 ; -const uint32_t CERTIFICATE_PARSING_ERROR_UNKNOWN_SECTION_PTAG = 0x17 ; -const uint32_t CERTIFICATE_PARSING_ERROR_MISSING_CHECKSUM = 0x18 ; -const uint32_t CERTIFICATE_PARSING_ERROR_WRONG_VERSION = 0x19 ; -const uint32_t CERTIFICATE_PARSING_ERROR_MISSING_PGP_FINGERPRINT = 0x1a ; -const uint32_t CERTIFICATE_PARSING_ERROR_MISSING_LOCATION_ID = 0x1b ; - -const uint32_t PGP_KEYRING_REMOVAL_ERROR_NO_ERROR = 0x20 ; -const uint32_t PGP_KEYRING_REMOVAL_ERROR_CANT_REMOVE_SECRET_KEYS = 0x21 ; -const uint32_t PGP_KEYRING_REMOVAL_ERROR_CANNOT_CREATE_BACKUP = 0x22 ; -const uint32_t PGP_KEYRING_REMOVAL_ERROR_CANNOT_WRITE_BACKUP = 0x23 ; -const uint32_t PGP_KEYRING_REMOVAL_ERROR_DATA_INCONSISTENCY = 0x24 ; - -/* LinkType Flags */ - -// CONNECTION -const uint32_t RS_NET_CONN_TRANS_MASK = 0x0000ffff; -const uint32_t RS_NET_CONN_TRANS_TCP_MASK = 0x0000000f; -const uint32_t RS_NET_CONN_TRANS_TCP_UNKNOWN = 0x00000001; -const uint32_t RS_NET_CONN_TRANS_TCP_LOCAL = 0x00000002; -const uint32_t RS_NET_CONN_TRANS_TCP_EXTERNAL = 0x00000004; - -const uint32_t RS_NET_CONN_TRANS_UDP_MASK = 0x000000f0; -const uint32_t RS_NET_CONN_TRANS_UDP_UNKNOWN = 0x00000010; -const uint32_t RS_NET_CONN_TRANS_UDP_DIRECT = 0x00000020; -const uint32_t RS_NET_CONN_TRANS_UDP_PROXY = 0x00000040; -const uint32_t RS_NET_CONN_TRANS_UDP_RELAY = 0x00000080; - -const uint32_t RS_NET_CONN_TRANS_OTHER_MASK = 0x00000f00; - -const uint32_t RS_NET_CONN_TRANS_UNKNOWN = 0x00001000; - - -const uint32_t RS_NET_CONN_SPEED_MASK = 0x000f0000; -const uint32_t RS_NET_CONN_SPEED_UNKNOWN = 0x00000000; -const uint32_t RS_NET_CONN_SPEED_TRICKLE = 0x00010000; -const uint32_t RS_NET_CONN_SPEED_LOW = 0x00020000; -const uint32_t RS_NET_CONN_SPEED_NORMAL = 0x00040000; -const uint32_t RS_NET_CONN_SPEED_HIGH = 0x00080000; - -const uint32_t RS_NET_CONN_QUALITY_MASK = 0x00f00000; -const uint32_t RS_NET_CONN_QUALITY_UNKNOWN = 0x00000000; - -// THIS INFO MUST BE SUPPLIED BY PEERMGR.... -const uint32_t RS_NET_CONN_TYPE_MASK = 0x0f000000; -const uint32_t RS_NET_CONN_TYPE_UNKNOWN = 0x00000000; -const uint32_t RS_NET_CONN_TYPE_ACQUAINTANCE = 0x01000000; -const uint32_t RS_NET_CONN_TYPE_FRIEND = 0x02000000; -const uint32_t RS_NET_CONN_TYPE_SERVER = 0x04000000; -const uint32_t RS_NET_CONN_TYPE_CLIENT = 0x08000000; - -// working state of proxy - -const uint32_t RS_NET_PROXY_STATUS_UNKNOWN = 0x0000 ; -const uint32_t RS_NET_PROXY_STATUS_OK = 0x0001 ; - -// Potential certificate parsing errors. - - -/* Groups */ -static const RsNodeGroupId RS_GROUP_ID_FRIENDS ("00000000000000000000000000000001"); -static const RsNodeGroupId RS_GROUP_ID_FAMILY ("00000000000000000000000000000002"); -static const RsNodeGroupId RS_GROUP_ID_COWORKERS ("00000000000000000000000000000003"); -static const RsNodeGroupId RS_GROUP_ID_OTHERS ("00000000000000000000000000000004"); -static const RsNodeGroupId RS_GROUP_ID_FAVORITES ("00000000000000000000000000000005"); - -#define RS_GROUP_DEFAULT_NAME_FRIENDS "Friends" -#define RS_GROUP_DEFAULT_NAME_FAMILY "Family" -#define RS_GROUP_DEFAULT_NAME_COWORKERS "Co-Workers" -#define RS_GROUP_DEFAULT_NAME_OTHERS "Other Contacts" -#define RS_GROUP_DEFAULT_NAME_FAVORITES "Favorites" - -const uint32_t RS_GROUP_FLAG_STANDARD = 0x0001; - -/* A couple of helper functions for translating the numbers games */ - -std::string RsPeerTrustString(uint32_t trustLvl); -std::string RsPeerNetModeString(uint32_t netModel); -std::string RsPeerLastConnectString(uint32_t lastConnect); - -//===================================================================================================// -// Connexion and security events // -//===================================================================================================// - -enum class RsAuthSslError: uint8_t -{ -// NO_ERROR = 0x00, // enabling break windows build - MISSING_AUTHENTICATION_INFO = 0x01, - PGP_SIGNATURE_VALIDATION_FAILED = 0x02, - MISMATCHED_PGP_ID = 0x03, - NO_CERTIFICATE_SUPPLIED = 0x04, - NOT_A_FRIEND = 0x05, - MISSING_CERTIFICATE = 0x06, - IP_IS_BLACKLISTED = 0x07, - PEER_REFUSED_CONNECTION = 0x08, - UNKNOWN_ERROR = 0x09, -}; - -/** - * Event triggered by AuthSSL when authentication of a connection attempt either - * fail or success - */ -struct RsAuthSslConnectionAutenticationEvent : RsEvent -{ - RsAuthSslConnectionAutenticationEvent() : - RsEvent(RsEventType::AUTHSSL_CONNECTION_AUTENTICATION) {} - - RsPeerId mSslId; - std::string mSslCn; - RsPgpId mPgpId; - RsUrl mLocator; - std::string mErrorMsg; - RsAuthSslError mErrorCode; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mSslId); - RS_SERIAL_PROCESS(mSslCn); - RS_SERIAL_PROCESS(mPgpId); - RS_SERIAL_PROCESS(mLocator); - RS_SERIAL_PROCESS(mErrorMsg); - RS_SERIAL_PROCESS(mErrorCode); - } - - ~RsAuthSslConnectionAutenticationEvent() override; -}; - -enum class RsConnectionEventCode: uint8_t -{ - UNKNOWN = 0x00, - PEER_CONNECTED = 0x01, - PEER_DISCONNECTED = 0x02, - PEER_TIME_SHIFT = 0x03, // mTimeShift = time shift in seconds - PEER_REPORTS_WRONG_IP = 0x04, // mPeerLocator = address reported, mOwnLocator = own address -}; - -struct RsConnectionEvent : RsEvent -{ - RsConnectionEvent() - : RsEvent(RsEventType::PEER_CONNECTION), - mConnectionInfoCode(RsConnectionEventCode::UNKNOWN), mTimeShift(0) {} - - RsConnectionEventCode mConnectionInfoCode; - RsPeerId mSslId; - RsUrl mOwnLocator; - RsUrl mReportedLocator; - - /** If there is a time shift with the peer aka - * mConnectionInfoCode == PEER_TIME_SHIFT contains the time shift value in - * seconds */ - rstime_t mTimeShift; - - ///* @see RsEvent @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mConnectionInfoCode); - RS_SERIAL_PROCESS(mSslId); - RS_SERIAL_PROCESS(mOwnLocator); - RS_SERIAL_PROCESS(mReportedLocator); - RS_SERIAL_PROCESS(mTimeShift); - } - - ~RsConnectionEvent() override; -}; - -enum class RsNetworkEventCode: uint8_t { - UNKNOWN = 0x00, - LOCAL_IP_UPDATED = 0x01, - EXTERNAL_IP_UPDATED = 0x02, -}; - -struct RsNetworkEvent : RsEvent -{ - RsNetworkEvent() - : RsEvent(RsEventType::NETWORK), - mNetworkEventCode(RsNetworkEventCode::UNKNOWN){} - - RsNetworkEventCode mNetworkEventCode; - std::string mIPAddress; // local or external IP depending on the event type - - ///* @see RsEvent @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mNetworkEventCode); - RS_SERIAL_PROCESS(mIPAddress); - } -}; - -//===================================================================================================// -// Peer Details // -//===================================================================================================// - -/* We should definitely split this into 2 sub-structures: - * PGP info (or profile info) with all info related to PGP keys - * peer info: all network related information - * - * Plus top level information: - * isOnlyPgpDetail (this could be obsolete if the methods to query about PGP info is a different function) - * peer Id - */ -struct RsPeerDetails : RsSerializable -{ - RsPeerDetails(); - - /* Auth details */ - bool isOnlyGPGdetail; - RsPeerId id; - RsPgpId gpg_id; - - std::string name; - std::string email; - std::string location; - std::string org; - - RsPgpId issuer; - - RsPgpFingerprint fpr; /* pgp fingerprint */ - std::string authcode; // TODO: 2015/12/31 (cyril) what is this used for ????? - std::list gpgSigners; - - uint32_t trustLvl; - uint32_t validLvl; - - bool skip_pgp_signature_validation; - bool ownsign; /* we have signed the remote peer GPG key */ - bool hasSignedMe; /* the remote peer has signed my GPG key */ - - bool accept_connection; - - /* Peer permission flags. What services the peer can use (Only valid if friend).*/ - ServicePermissionFlags service_perm_flags ; - - /* Network details (only valid if friend) */ - uint32_t state; - bool actAsServer; - - // TODO: 2015/12/31 to take advantage of multiple connection this must be - // replaced by a set of addresses - std::string connectAddr ; // current address if connected. - uint16_t connectPort ; - - // Hidden Node details. - bool isHiddenNode; - std::string hiddenNodeAddress; - uint16_t hiddenNodePort; - uint32_t hiddenType; - - // Filled in for Standard Node. - std::string localAddr; - uint16_t localPort; - std::string extAddr; - uint16_t extPort; - std::string dyndns; - std::list ipAddressList; - - uint32_t netMode; - /* vis State */ - uint16_t vs_disc; - uint16_t vs_dht; - - /* basic stats */ - uint32_t lastConnect; /* how long ago */ - uint32_t lastUsed; /* how long ago since last used: signature verif, connect attempt, etc */ - uint32_t connectState; /* RS_PEER_CONNECTSTATE_... */ - std::string connectStateString; /* Additional string like ip address */ - uint32_t connectPeriod; - bool foundDHT; - - /* have we been denied */ - bool wasDeniedConnection; - rstime_t deniedTS; - - /* linkType */ - uint32_t linkType; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(isOnlyGPGdetail); - RS_SERIAL_PROCESS(id); - RS_SERIAL_PROCESS(gpg_id); - RS_SERIAL_PROCESS(name); - RS_SERIAL_PROCESS(email); - RS_SERIAL_PROCESS(location); - RS_SERIAL_PROCESS(org); - RS_SERIAL_PROCESS(issuer); - RS_SERIAL_PROCESS(fpr); - RS_SERIAL_PROCESS(authcode); - RS_SERIAL_PROCESS(gpgSigners); - RS_SERIAL_PROCESS(trustLvl); - RS_SERIAL_PROCESS(validLvl); - RS_SERIAL_PROCESS(ownsign); - RS_SERIAL_PROCESS(hasSignedMe); - RS_SERIAL_PROCESS(accept_connection); - RS_SERIAL_PROCESS(service_perm_flags); - RS_SERIAL_PROCESS(state); - RS_SERIAL_PROCESS(actAsServer); - RS_SERIAL_PROCESS(connectAddr); - RS_SERIAL_PROCESS(connectPort); - RS_SERIAL_PROCESS(isHiddenNode); - RS_SERIAL_PROCESS(hiddenNodeAddress); - RS_SERIAL_PROCESS(hiddenNodePort); - RS_SERIAL_PROCESS(hiddenType); - RS_SERIAL_PROCESS(localAddr); - RS_SERIAL_PROCESS(localPort); - RS_SERIAL_PROCESS(extAddr); - RS_SERIAL_PROCESS(extPort); - RS_SERIAL_PROCESS(dyndns); - RS_SERIAL_PROCESS(ipAddressList); - RS_SERIAL_PROCESS(netMode); - RS_SERIAL_PROCESS(vs_disc); - RS_SERIAL_PROCESS(vs_dht); - RS_SERIAL_PROCESS(lastConnect); - RS_SERIAL_PROCESS(lastUsed); - RS_SERIAL_PROCESS(connectState); - RS_SERIAL_PROCESS(connectStateString); - RS_SERIAL_PROCESS(connectPeriod); - RS_SERIAL_PROCESS(foundDHT); - RS_SERIAL_PROCESS(wasDeniedConnection); - RS_SERIAL_PROCESS(deniedTS); - RS_SERIAL_PROCESS(linkType); - } -}; - -// This class is used to get info about crytographic algorithms used with a -// particular peer. -struct RsPeerCryptoParams -{ - int connexion_state; - std::string cipher_name; -}; - -struct RsGroupInfo : RsSerializable -{ - RsGroupInfo(); - - RsNodeGroupId id; - std::string name; - uint32_t flag; - - std::set peerIds; - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext &ctx) - { - RS_SERIAL_PROCESS(id); - RS_SERIAL_PROCESS(name); - RS_SERIAL_PROCESS(flag); - RS_SERIAL_PROCESS(peerIds); - } -}; - -/** Event emitted when a peer change state */ -struct RsPeerStateChangedEvent : RsEvent -{ - /// @param[in] sslId is of the peer which changed state - explicit RsPeerStateChangedEvent(RsPeerId sslId); - - /// Storage fot the id of the peer that changed state - RsPeerId mSslId; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mSslId); - } -}; - -enum class RetroshareInviteFlags:uint32_t { - NOTHING = 0x00, - CURRENT_IP = 0x01, - FULL_IP_HISTORY = 0x02, - DNS = 0x04, - RADIX_FORMAT = 0x08, - PGP_SIGNATURES = 0x10, -}; -RS_REGISTER_ENUM_FLAGS_TYPE(RetroshareInviteFlags) - -/** The Main Interface Class - for information about your Peers - * A peer is another RS instance, means associated with an SSL certificate - * A same GPG person can have multiple peer running with different SSL certs - * signed by the same GPG key - * Thus a peer have SSL cert details, and also the parent GPG details - */ -class RsPeers -{ -public: - - /** - * @brief Get own SSL peer id - * @return own peer id - */ - virtual const RsPeerId& getOwnId() = 0; - - virtual bool haveSecretKey(const RsPgpId& gpg_id) = 0 ; - - /** - * @brief Get trusted peers list - * @jsonapi{development} - * @param[out] sslIds storage for the trusted peers - * @return false if error occurred, true otherwise - */ - virtual bool getFriendList(std::list& sslIds) = 0; - - /** - * @brief Get trusted PGP ids list - * @jsonapi{development} - * @param[out] pgpIds storage for the trusted PGP ids - * @return false if error occurred, true otherwise - */ - virtual bool getPgpFriendList(std::vector& pgpIds) = 0; - - /** - * @brief Get connected peers list - * @jsonapi{development} - * @param[out] sslIds storage for the peers - * @return false if error occurred, true otherwise - */ - virtual bool getOnlineList(std::list &sslIds) = 0; - - /** - * @brief Get peers count - * @jsonapi{development} - * @param[out] peersCount storage for trusted peers count - * @param[out] onlinePeersCount storage for online peers count - * @param[in] countLocations true to count multiple locations of same owner - * @return false if error occurred, true otherwise - */ - virtual bool getPeersCount( - uint32_t& peersCount, uint32_t& onlinePeersCount, - bool countLocations = true ) = 0; - - RS_DEPRECATED - virtual bool getPeerCount(unsigned int *pnFriendCount, unsigned int *pnnOnlineCount, bool ssl) = 0; - - /** - * @brief Check if there is an established connection to the given peer - * @jsonapi{development} - * @param[in] sslId id of the peer to check - * @return true if the connection is establisced, false otherwise - */ - virtual bool isOnline(const RsPeerId &sslId) = 0; - - /** - * @brief Check if given peer is a trusted node - * @jsonapi{development} - * @param[in] sslId id of the peer to check - * @return true if the node is trusted, false otherwise - */ - virtual bool isFriend(const RsPeerId& sslId) = 0; - - /** - * @brief Check if given PGP id is trusted - * @jsonapi{development} - * @param[in] pgpId PGP id to check - * @return true if the PGP id is trusted, false otherwise - */ - virtual bool isPgpFriend(const RsPgpId& pgpId) = 0; - - /** - * @brief Check if given peer is a trusted SSL node pending PGP approval - * Peers added through short invite remain in this state as long as their - * PGP key is not received and verified/approved by the user. - * @jsonapi{development} - * @param[in] sslId id of the peer to check - * @return true if the node is trusted, false otherwise - */ - virtual bool isSslOnlyFriend(const RsPeerId& sslId) = 0; - - virtual std::string getPeerName(const RsPeerId &ssl_id) = 0; - virtual std::string getGPGName(const RsPgpId& gpg_id) = 0; - - /** - * @brief Get details details of the given peer - * @jsonapi{development} - * @param[in] sslId id of the peer - * @param[out] det storage for the details of the peer - * @return false if error occurred, true otherwise - */ - virtual bool getPeerDetails(const RsPeerId& sslId, RsPeerDetails& det) = 0; - - virtual bool getGPGDetails(const RsPgpId& gpg_id, RsPeerDetails &d) = 0; - - /* Using PGP Ids */ - virtual const RsPgpId& getGPGOwnId() = 0; - - /** - * @brief Get PGP id for the given peer - * @jsonapi{development} - * @param[in] sslId SSL id of the peer - * @return PGP id of the peer - */ - virtual RsPgpId getGPGId(const RsPeerId& sslId) = 0; - virtual bool isKeySupported(const RsPgpId& gpg_ids) = 0; - - RS_DEPRECATED_FOR(getPgpFriendList) - virtual bool getGPGAcceptedList(std::list &gpg_ids) = 0; - virtual bool getGPGSignedList(std::list &gpg_ids) = 0;// keys signed by our own PGP key. - virtual bool getGPGValidList(std::list &gpg_ids) = 0;// all PGP keys without filtering - virtual bool getGPGAllList(std::list &gpg_ids) = 0;// all PGP keys as well - virtual bool getAssociatedSSLIds(const RsPgpId& gpg_id, std::list& ids) = 0; - virtual bool gpgSignData(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, std::string reason = "") = 0; - - /** - * @brief Convert PGP fingerprint to PGP id - * @jsonapi{development} - * Helper method useful while we port the whole RetroShare codebase from - * RsPgpId to RsPgpFingerprint - * @param[in] fpr PGP fingerprint to convert - * @return PGP id corresponding to the fingerprint - */ - virtual RsPgpId pgpIdFromFingerprint(const RsPgpFingerprint& fpr) = 0; - - // Note: the two methods below could be unified. The fact that one of them can take an optional RsPeerDetails struct as parameter - // seems quite inconsistent. - - /** - * @brief Add trusted node - * @jsonapi{development} - * @param[in] sslId SSL id of the node to add - * @param[in] gpgId PGP id of the node to add - * @param[in] flags service permissions flag - * @return false if error occurred, true otherwise - */ - virtual bool addFriend( - const RsPeerId& sslId, const RsPgpId& gpgId, - ServicePermissionFlags flags = RS_NODE_PERM_DEFAULT ) = 0; - - /** - * @brief Add SSL-only trusted node - * When adding an SSL-only node, it is authorized to connect. Every time a - * connection is established the user is notified about the need to verify - * the PGP fingerprint, until she does, at that point the node become a full - * SSL+PGP friend. - * @jsonapi{development} - * @param[in] sslId SSL id of the node to add - * @param[in] pgpId PGP id of the node to add. Will be used for validation when the key is available. - * @param[in] details Optional extra details known about the node to add - * @return false if error occurred, true otherwise - */ - virtual bool addSslOnlyFriend( - const RsPeerId& sslId, - const RsPgpId& pgpId, - const RsPeerDetails& details = RsPeerDetails() ) = 0; - - /** - * @brief Revoke connection trust from to node - * @jsonapi{development} - * @param[in] pgpId PGP id of the node - * @return false if error occurred, true otherwise - */ - virtual bool removeFriend(const RsPgpId& pgpId) = 0; - - /** - * @brief Remove location of a trusted node, useful to prune old unused - * locations of a trusted peer without revoking trust - * @jsonapi{development} - * @param[in] sslId SSL id of the location to remove - * @return false if error occurred, true otherwise - */ - virtual bool removeFriendLocation(const RsPeerId& sslId) = 0; - - /* keyring management */ - virtual bool removeKeysFromPGPKeyring( - const std::set& pgpIds, std::string& backupFile, - uint32_t& errorCode ) = 0; - - /* Network Stuff */ - - /** - * @brief Trigger connection attempt to given node - * @jsonapi{development} - * @param[in] sslId SSL id of the node to connect - * @return false if error occurred, true otherwise - */ - virtual bool connectAttempt(const RsPeerId& sslId) = 0; - - virtual bool setLocation(const RsPeerId &ssl_id, const std::string &location) = 0; // location is shown in the gui to differentiate ssl certs - - virtual bool setHiddenNode(const RsPeerId &id, const std::string &hidden_node_address) = 0; - virtual bool setHiddenNode(const RsPeerId &id, const std::string &address, uint16_t port) = 0; - virtual bool isHiddenNode(const RsPeerId &id) = 0; - - /** - * @brief Add URL locator for given peer - * @jsonapi{development} - * @param[in] sslId SSL id of the peer, own id is accepted too - * @param[in] locator peer url locator - * @return false if error occurred, true otherwise - */ - virtual bool addPeerLocator(const RsPeerId& sslId, const RsUrl& locator) = 0; - - /** - * @brief Set local IPv4 address for the given peer - * @jsonapi{development} - * @param[in] sslId SSL id of the peer, own id is accepted too - * @param[in] addr string representation of the local IPv4 address - * @param[in] port local listening port - * @return false if error occurred, true otherwise - */ - virtual bool setLocalAddress( - const RsPeerId& sslId, const std::string& addr, uint16_t port ) = 0; - - /** - * @brief Set external IPv4 address for given peer - * @jsonapi{development} - * @param[in] sslId SSL id of the peer, own id is accepted too - * @param[in] addr string representation of the external IPv4 address - * @param[in] port external listening port - * @return false if error occurred, true otherwise - */ - virtual bool setExtAddress( - const RsPeerId& sslId, const std::string &addr, uint16_t port ) = 0; - - /** - * @brief Set (dynamical) domain name associated to the given peer - * @jsonapi{development} - * @param[in] sslId SSL id of the peer, own id is accepted too - * @param[in] addr domain name string representation - * @return false if error occurred, true otherwise - */ - virtual bool setDynDNS(const RsPeerId& sslId, const std::string& addr) = 0; - - /** - * @brief Set network mode of the given peer - * @jsonapi{development} - * @param[in] sslId SSL id of the peer, own id is accepted too - * @param[in] netMode one of RS_NETMODE_* - * @return false if error occurred, true otherwise - */ - virtual bool setNetworkMode(const RsPeerId &sslId, uint32_t netMode) = 0; - - /** - * @brief set DHT and discovery modes - * @jsonapi{development} - * @param[in] sslId SSL id of the peer, own id is accepted too - * @param[in] vsDisc one of RS_VS_DISC_* - * @param[in] vsDht one of RS_VS_DHT_* - * @return false if error occurred, true otherwise - */ - virtual bool setVisState( const RsPeerId& sslId, - uint16_t vsDisc, uint16_t vsDht ) = 0; - - virtual bool getProxyServer(const uint32_t type, std::string &addr, uint16_t &port,uint32_t& status_flags) = 0; - virtual bool setProxyServer(const uint32_t type, const std::string &addr, const uint16_t port) = 0; - - virtual void getIPServersList(std::list& ip_servers) = 0; - virtual void allowServerIPDetermination(bool) = 0; - virtual bool resetOwnExternalAddressList() = 0; - virtual bool getAllowServerIPDetermination() = 0 ; - - /** - * @brief Get RetroShare invite of the given peer - * @jsonapi{development} - * @param[in] sslId Id of the peer of which we want to generate an invite, - * a null id (all 0) is passed, an invite for own node is returned. - * @param[in] inviteFlags specify extra data to include in the invite - * @return invite string - */ - virtual std::string GetRetroshareInvite( - const RsPeerId& sslId = RsPeerId(), - RetroshareInviteFlags inviteFlags = - RetroshareInviteFlags::DNS | RetroshareInviteFlags::CURRENT_IP ) = 0; - - /** - * @brief Get RetroShare short invite of the given peer - * @jsonapi{development} - * @param[out] invite storage for the generated invite - * @param[in] sslId Id of the peer of which we want to generate an invite, - * a null id (all 0) is passed, an invite for own node is returned. - * @param[in] inviteFlags specify extra data to include in the invite and - * format. - * @param[in] baseUrl URL into which to sneak in the RetroShare invite - * radix, this is primarly useful to trick other applications into making - * the invite clickable, or to disguise the RetroShare invite into a - * "normal" looking web link. Used only if formatRadix is false. - * @return false if error occurred, true otherwise - */ - virtual bool getShortInvite( - std::string& invite, const RsPeerId& sslId = RsPeerId(), - RetroshareInviteFlags inviteFlags = - RetroshareInviteFlags::CURRENT_IP | RetroshareInviteFlags::DNS, - const std::string& baseUrl = "https://retroshare.me/" ) = 0; - - /** - * @brief Parse the give short invite to extract contained information - * @jsonapi{development} - * @param[in] invite string containing the short invite to parse - * @param[out] details storage for the extracted information, consider it - * @param[out] err_code storage for the error code - * @return false if error occurred, true otherwise - */ - virtual bool parseShortInvite( - const std::string& invite, RsPeerDetails& details,uint32_t& err_code ) = 0; - - /** - * @brief Add trusted node from invite - * @jsonapi{development} - * @param[in] invite invite string being it in cert or URL format - * @param[in] flags service permissions flag - * @return false if error occurred, true otherwise - */ - virtual bool acceptInvite( - const std::string& invite, - ServicePermissionFlags flags = RS_NODE_PERM_DEFAULT ) = 0; - - - RS_DEPRECATED /// This function doesn't provide meaningful error reporting - virtual std::string getPGPKey(const RsPgpId& pgp_id,bool include_signatures) = 0; - virtual bool GetPGPBase64StringAndCheckSum(const RsPgpId& gpg_id,std::string& gpg_base64_string,std::string& gpg_base64_checksum) = 0; - - /** - * @brief Import certificate into the keyring - * @jsonapi{development} - * @param[in] cert string representation of the certificate - * @param[out] sslId storage for the SSL id of the certificate - * @param[out] pgpId storage for the PGP id of the certificate - * @param[out] errorString storage for the possible error string - * @return false if error occurred, true otherwise - */ - virtual bool loadCertificateFromString( - const std::string& cert, RsPeerId& sslId, RsPgpId& pgpId, - std::string& errorString) = 0; - - /** - * @brief Examine certificate and get details without importing into - * the keyring - * @jsonapi{development} - * @param[in] cert string representation of the certificate - * @param[out] certDetails storage for the certificate details - * @param[out] errorCode storage for possible error number - * @return false if error occurred, true otherwise - */ - virtual bool loadDetailsFromStringCert( - const std::string& cert, RsPeerDetails& certDetails, - uint32_t& errorCode ) = 0; - - virtual bool loadPgpKeyFromBinaryData( const unsigned char *bin_key_data, - uint32_t bin_key_len, - RsPgpId& gpg_id, - std::string& error_string )=0; - - // Certificate utils - virtual bool cleanCertificate( - const std::string& certstr, std::string& cleanCert, - bool& is_short_format, uint32_t& error_code ) = 0; - virtual std::string saveCertificateToString(const RsPeerId &id) = 0; - - virtual bool signGPGCertificate(const RsPgpId &gpg_id,const std::string& gpg_passphrase) = 0; - virtual bool trustGPGCertificate(const RsPgpId &gpg_id, uint32_t trustlvl) = 0; - - /* Group Stuff */ - /** - * @brief addGroup create a new group - * @jsonapi{development} - * @param[in] groupInfo - * @return - */ - virtual bool addGroup(RsGroupInfo& groupInfo) = 0; - - /** - * @brief editGroup edit an existing group - * @jsonapi{development} - * @param[in] groupId - * @param[in] groupInfo - * @return - */ - virtual bool editGroup(const RsNodeGroupId& groupId, RsGroupInfo& groupInfo) = 0; - - /** - * @brief removeGroup remove a group - * @jsonapi{development} - * @param[in] groupId - * @return - */ - virtual bool removeGroup(const RsNodeGroupId& groupId) = 0; - - /** - * @brief getGroupInfo get group information to one group - * @jsonapi{development} - * @param[in] groupId - * @param[out] groupInfo - * @return - */ - virtual bool getGroupInfo(const RsNodeGroupId& groupId, RsGroupInfo& groupInfo) = 0; - - /** - * @brief getGroupInfoByName get group information by group name - * @jsonapi{development} - * @param[in] groupName - * @param[out] groupInfo - * @return - */ - virtual bool getGroupInfoByName(const std::string& groupName, RsGroupInfo& groupInfo) = 0; - - /** - * @brief getGroupInfoList get list of all groups - * @jsonapi{development} - * @param[out] groupInfoList - * @return - */ - virtual bool getGroupInfoList(std::list& groupInfoList) = 0; - - // groupId == "" && assign == false -> remove from all groups - /** - * @brief assignPeerToGroup add a peer to a group - * @jsonapi{development} - * @param[in] groupId - * @param[in] peerId - * @param[in] assign true to assign a peer, false to remove a peer - * @return - */ - virtual bool assignPeerToGroup(const RsNodeGroupId& groupId, const RsPgpId& peerId, bool assign) = 0; - - /** - * @brief assignPeersToGroup add a list of peers to a group - * @jsonapi{development} - * @param[in] groupId - * @param[in] peerIds - * @param[in] assign true to assign a peer, false to remove a peer - * @return - */ - virtual bool assignPeersToGroup(const RsNodeGroupId& groupId, const std::list& peerIds, bool assign) = 0; - - /* Group sharing permission */ - - // Given - // - the peer id - // - the permission flags of a given hash, e.g. a combination of - // RS_DIR_FLAGS_NETWORK_WIDE_OTHERS, RS_DIR_FLAGS_NETWORK_WIDE_GROUPS, RS_DIR_FLAGS_BROWSABLE_OTHERS and RS_DIR_FLAGS_BROWSABLE_GROUPS - // - the parent groups of the file - // - // ... computes the sharing file permission hint flags set for this peer, that is a combination of - // RS_FILE_HINTS_NETWORK_WIDE and RS_FILE_HINTS_BROWSABLE. - // - virtual FileSearchFlags computePeerPermissionFlags( - const RsPeerId& peer_id, FileStorageFlags file_sharing_flags, - const std::list& file_parent_groups) = 0; - - /* Service permission flags */ - - virtual ServicePermissionFlags servicePermissionFlags(const RsPgpId& gpg_id) = 0; - virtual ServicePermissionFlags servicePermissionFlags(const RsPeerId& ssl_id) = 0; - virtual void setServicePermissionFlags(const RsPgpId& gpg_id,const ServicePermissionFlags& flags) = 0; - - virtual bool setPeerMaximumRates(const RsPgpId& pid,uint32_t maxUploadRate,uint32_t maxDownloadRate) =0; - virtual bool getPeerMaximumRates(const RsPeerId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) =0; - virtual bool getPeerMaximumRates(const RsPgpId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) =0; - - RS_DEPRECATED_FOR(isPgpFriend) - virtual bool isGPGAccepted(const RsPgpId &gpg_id_is_friend) = 0; - - virtual ~RsPeers(); -}; diff --git a/libretroshare/src/retroshare/rsphoto.h b/libretroshare/src/retroshare/rsphoto.h deleted file mode 100644 index 839b28a90..000000000 --- a/libretroshare/src/retroshare/rsphoto.h +++ /dev/null @@ -1,247 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsphoto.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2020 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSPHOTOV2_H -#define RSPHOTOV2_H - -#include -#include -#include -#include "retroshare/rsgxsservice.h" -#include "retroshare/rsgxscommon.h" -#include "retroshare/rsgxsifacehelper.h" - - -/* The Main Interface Class - for information about your Peers */ -class RsPhoto; -extern RsPhoto *rsPhoto; - -class RsPhotoPhoto -{ -public: - - RsMsgMetaData mMeta; - - RsPhotoPhoto(); - - // V2 PhotoMsg - keep it simple. - // mMeta.mTitle used for Photo Caption. - // mDescription optional field for addtional notes. - // mLowResImage - < 50k jpg of image. - // mPhotoFile - transfer details for original photo. - std::string mDescription; - uint32_t mOrder; - RsGxsImage mLowResImage; - RsGxsFile mPhotoFile; - - // These are not saved. - std::string mPath; // if New photo -}; - -#define RSPHOTO_SHAREMODE_LOWRESONLY (1) -#define RSPHOTO_SHAREMODE_ORIGINAL (2) -#define RSPHOTO_SHAREMODE_DUP_ORIGINAL (3) -#define RSPHOTO_SHAREMODE_DUP_200K (4) -#define RSPHOTO_SHAREMODE_DUP_1M (5) - -struct RsPhotoAlbum: RsGxsGenericGroupData -{ - RsPhotoAlbum(); - - // V2 Album - keep it simple. - // mMeta.mTitle. - uint32_t mShareMode; - - std::string mCaption; - std::string mDescription; - std::string mPhotographer; - std::string mWhere; - std::string mWhen; - - RsGxsImage mThumbnail; - - // Below is not saved. - bool mAutoDownload; -}; - -std::ostream &operator<<(std::ostream &out, const RsPhotoPhoto &photo); -std::ostream &operator<<(std::ostream &out, const RsPhotoAlbum &album); - -typedef std::map > PhotoResult; - -class RsPhoto: public RsGxsIfaceHelper, public RsGxsCommentService -{ -public: - explicit RsPhoto(RsGxsIface &gxs) : RsGxsIfaceHelper(gxs) { return; } - - virtual ~RsPhoto() { return; } - - /*! - * Use to enquire if groups or msgs have changed - * Poll regularly, particularly after a photo submission - * @return true if msgs or groups have changed - */ - virtual bool updated() = 0; - - /*! - * - * @param grpIds - */ - virtual void groupsChanged(std::list& grpIds) = 0; - - /*! - * - * @param msgs - */ - virtual void msgsChanged(GxsMsgIdResult& msgs) = 0; - - /*! - * To acquire a handle to token service handler - * needed to make requests to the service - * @return handle to token service for this gxs service - */ - virtual RsTokenService* getTokenService() = 0; - - /* Generic Lists */ - - /*! - * - * @param token token to be redeemed for this request - * @param groupIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getGroupList(const uint32_t &token, - std::list &groupIds) = 0; - - /*! - * @param token token to be redeemed for this request - * @param msgIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgList(const uint32_t &token, - GxsMsgIdResult &msgIds) = 0; - - /* Generic Summary */ - - /*! - * @param token token to be redeemed for group summary request - * @param groupInfo the ids returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getGroupSummary(const uint32_t &token, - std::list &groupInfo) = 0; - - /*! - * @param token token to be redeemed for message summary request - * @param msgInfo the message metadata returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgSummary(const uint32_t &token, - MsgMetaResult &msgInfo) = 0; - - /* Specific Service Data */ - - /*! - * @param token token to be redeemed for album request - * @param album the album returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getAlbum(const uint32_t &token, std::vector &album) = 0; - - /*! - * @param token token to be redeemed for photo request - * @param photo the photo returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getPhoto(const uint32_t &token, - PhotoResult &photo) = 0; - - /*! - * submits album, which returns a token that needs - * to be acknowledge to get album grp id - * @param token token to redeem for acknowledgement - * @param album album to be submitted - */ - virtual bool submitAlbumDetails(uint32_t& token, RsPhotoAlbum &album) = 0; - - /*! - * submits photo, which returns a token that needs - * to be acknowledged to get photo msg-grp id pair - * @param token token to redeem for acknowledgement - * @param photo photo to be submitted - */ - virtual bool submitPhoto(uint32_t& token, RsPhotoPhoto &photo) = 0; - - /*! - * subscribes to group, and returns token which can be used - * to be acknowledged to get group Id - * @param token token to redeem for acknowledgement - * @param grpId the id of the group to subscribe to - */ - virtual bool subscribeToAlbum(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) = 0; - - /*! - * This allows the client service to acknowledge that their msgs has - * been created/modified and retrieve the create/modified msg ids - * @param token the token related to modification/create request - * @param msgIds map of grpid->msgIds of message created/modified - * @return true if token exists false otherwise - */ - virtual bool acknowledgeMsg(const uint32_t& token, std::pair& msgId) = 0; - - - - /*! - * This allows the client service to acknowledge that their grps has - * been created/modified and retrieve the create/modified grp ids - * @param token the token related to modification/create request - * @param msgIds vector of ids of groups created/modified - * @return true if token exists false otherwise - */ - virtual bool acknowledgeGrp(const uint32_t& token, RsGxsGroupId& grpId) = 0; - - // Blocking versions. - /*! - * request to create a new album. Blocks until process completes. - * @param album album to be submitted - * @return true if created false otherwise - */ - virtual bool createAlbum(RsPhotoAlbum &album) = 0; - - /*! - * request to update an existing album. Blocks until process completes. - * @param album album to be submitted - * @return true if created false otherwise - */ - virtual bool updateAlbum(const RsPhotoAlbum &album) = 0; - - /*! - * retrieve albums based in groupIds. - * @param groupIds the ids to fetch. - * @param albums vector to be filled by request. - * @return true is successful, false otherwise. - */ - virtual bool getAlbums(const std::list &groupIds, - std::vector &albums) = 0; -}; - - -#endif // RSPHOTOV2_H diff --git a/libretroshare/src/retroshare/rsplugin.h b/libretroshare/src/retroshare/rsplugin.h deleted file mode 100644 index 1efa70399..000000000 --- a/libretroshare/src/retroshare/rsplugin.h +++ /dev/null @@ -1,248 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsplugin.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "util/rstime.h" -#include -#include -#include -#include -#include "retroshare/rspeers.h" -#include "retroshare/rsfiles.h" -#include "retroshare/rsversion.h" -#include "util/rsinitedptr.h" -#include "retroshare/rsdisc.h" - -class RsPluginHandler ; -extern RsPluginHandler *rsPlugins ; - -class p3Service ; -class RsServiceControl ; -class RsReputations ; -class RsTurtle ; -class RsGxsTunnelService ; -class RsDht ; -class RsMsgs ; -class RsGxsForums; -class RsGxsChannels; -class RsNotify; -class RsServiceControl; -class p3LinkMgr ; -class MainPage ; -class QIcon ; -class QString ; -class QDialog ; -class QWidget ; -class QTranslator; -class QApplication; -class RsCacheService ; -class ftServer ; -class ConfigPage ; -class RsPQIService ; -class RsAutoUpdatePage ; -class SoundEvents; -class FeedNotify; -class ToasterNotify; -class ChatWidget; -class ChatWidgetHolder; -// for gxs based plugins -struct RsIdentity; -class RsNxsNetMgr; -class RsGxsIdExchange; -class RsGcxs; -class PgpAuxUtils; -class p3Config; - -namespace resource_api -{ - class ResourceRouter; - class StateTokenServer; -} - -// Plugin API version. Not used yet, but will be in the future the -// main value that decides for compatibility. -// -#define RS_PLUGIN_API_VERSION 0x000101 - -// Used for the status of plugins. -// -#define PLUGIN_STATUS_NO_STATUS 0x0000 -#define PLUGIN_STATUS_REJECTED_HASH 0x0001 -#define PLUGIN_STATUS_DLOPEN_ERROR 0x0002 -#define PLUGIN_STATUS_MISSING_SYMBOL 0x0003 -#define PLUGIN_STATUS_NULL_PLUGIN 0x0004 -#define PLUGIN_STATUS_LOADED 0x0005 -#define PLUGIN_STATUS_WRONG_API 0x0006 -#define PLUGIN_STATUS_MISSING_API 0x0007 -#define PLUGIN_STATUS_MISSING_SVN 0x0008 - -class RsPluginHandler; - -/*! - * - * convenience class to store gui interfaces - * - */ -class RsPlugInInterfaces { -public: - RsUtil::inited_ptr mPeers; - RsUtil::inited_ptr mFiles; - RsUtil::inited_ptr mMsgs; - RsUtil::inited_ptr mTurtle; - RsUtil::inited_ptr mDisc; - RsUtil::inited_ptr mDht; - RsUtil::inited_ptr mNotify; - RsUtil::inited_ptr mServiceControl; - RsUtil::inited_ptr mPluginHandler; - - // gxs - std::string mGxsDir; - RsUtil::inited_ptr mIdentity; - RsUtil::inited_ptr mRsNxsNetMgr; - RsUtil::inited_ptr mGxsIdService; - RsUtil::inited_ptr mGxsCirlces; - RsUtil::inited_ptr mPgpAuxUtils; - RsUtil::inited_ptr mGxsForums; - RsUtil::inited_ptr mGxsChannels; - RsUtil::inited_ptr mGxsTunnels; - RsUtil::inited_ptr mReputations; -}; - -class RsPlugin -{ - public: - RsPlugin() {} - virtual ~RsPlugin() {} - - // - //================================ Services ==================================// - // - // Cache service. Use this for providing cache-based services, such as channels, forums. - // Example plugin: LinksCloud - // - virtual RsCacheService *rs_cache_service() const { return NULL ; } - - // Peer-to-Peer service. Use this for providing a service based to friend to friend - // exchange of data, such as chat, messages, etc. - // Example plugin: VOIP - // - //virtual RsPQIService *rs_pqi_service() const { return NULL ; } - // gxs netservice is not a RsPQIService - // so have two fns which result in the same gxs netservice to be returned - virtual p3Service *p3_service() const { return NULL ; } - virtual p3Config *p3_config() const { return NULL ; } - virtual uint16_t rs_service_id() const { return 0 ; } - - - // creates a new resource api handler object. ownership is transferred to the caller. - // the caller should supply a statetokenserver, and keep it valid until destruction - // the plugin should return a entry point name. this is to make the entry point name independent from file names - virtual resource_api::ResourceRouter* new_resource_api_handler(const RsPlugInInterfaces& /* ifaces */, resource_api::StateTokenServer* /* sts */, std::string & /*entrypoint*/) const { return 0;} - - // Shutdown - virtual void stop() {} - - // Filename used for saving the specific plugin configuration. Both RsCacheService and RsPQIService - // derive from p3Config, which means that the service provided by the plugin can load/save its own - // config by deriving loadList() and saveList() from p3Config. - // - virtual std::string configurationFileName() const - { - std::cerr << "(EE) Plugin configuration file name requested in non overloaded method! Plugin code should derive configurationFileName() method!" << std::endl; - return std::string() ; - } - - // - //=================================== GUI ====================================// - // - // Derive the following methods to provide GUI additions to RetroShare's GUI. - // - // Main page: like Transfers, Channels, Forums, etc. - // - virtual MainPage *qt_page() const { return NULL ; } // The page itself - virtual QIcon *qt_icon() const { return NULL ; } // the page icon. Todo: put icon as virtual in MainPage - - virtual QWidget *qt_config_panel() const { return NULL ; } // Config panel, to appear config->plugins->[]-> - virtual QDialog *qt_about_page() const { return NULL ; } // About/Help button in plugin entry will show this up - virtual ConfigPage *qt_config_page() const { return NULL ; } // Config tab to add in config panel. - virtual RsAutoUpdatePage *qt_transfers_tab() const { return NULL ; } // Tab to add in transfers, after turtle statistics. - virtual std::string qt_transfers_tab_name()const { return "Tab" ; } // Tab name - virtual void qt_sound_events(SoundEvents &/*events*/) const { } // Sound events - - // Provide buttons for the ChatWidget - virtual ChatWidgetHolder *qt_get_chat_widget_holder(ChatWidget */*chatWidget*/) const { return NULL ; } - - virtual std::string qt_stylesheet() { return ""; } - virtual QTranslator *qt_translator(QApplication * /* app */, const QString& /* languageCode */, const QString& /* externalDir */ ) const { return NULL ; } - - // - //================================== Notify ==================================// - // - virtual FeedNotify *qt_feedNotify() { return NULL; } - virtual ToasterNotify *qt_toasterNotify() { return NULL; } - - // - //========================== Plugin Description ==============================// - // - // All these items appear in the config->plugins tab, as a description of the plugin. - // - uint32_t getSvnRevision() const { return 0; } // This is read from libretroshare/retroshare/rsversion.h - - virtual std::string getShortPluginDescription() const = 0 ; - virtual std::string getPluginName() const = 0 ; - virtual void getPluginVersion(int& major,int& minor, int& build, int& svn_rev) const = 0 ; - virtual void getLibraries(std::list & /*libraries*/) {} - - // - //========================== Plugin Interface ================================// - // - // Use these methods to access main objects from RetroShare. - // - virtual void setInterfaces(RsPlugInInterfaces& interfaces) = 0; - virtual void setPlugInHandler(RsPluginHandler* pgHandler) = 0; -}; - -class RsPluginHandler -{ - public: - // Returns the number of loaded plugins. - // - virtual int nbPlugins() const = 0 ; - virtual RsPlugin *plugin(int i) = 0 ; - virtual const std::vector& getPluginDirectories() const = 0; - virtual void getPluginStatus(int i,uint32_t& status,std::string& file_name,RsFileHash& file_hash,uint32_t& svn_revision,std::string& error_string) const = 0 ; - virtual void enablePlugin(const RsFileHash& hash) = 0; - virtual void disablePlugin(const RsFileHash& hash) = 0; - - virtual void allowAllPlugins(bool b) = 0 ; - virtual bool getAllowAllPlugins() const = 0 ; - - virtual void slowTickPlugins(rstime_t sec) = 0 ; - - virtual const std::string& getLocalCacheDir() const =0; - virtual const std::string& getRemoteCacheDir() const =0; - - virtual RsServiceControl *getServiceControl() const = 0; -}; - - - diff --git a/libretroshare/src/retroshare/rsposted.h b/libretroshare/src/retroshare/rsposted.h deleted file mode 100644 index bdcaa3798..000000000 --- a/libretroshare/src/retroshare/rsposted.h +++ /dev/null @@ -1,228 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsposted.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2008-2012 Robert Fernie, Christopher Evi-Parker * - * Copyright (C) 2020 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "retroshare/rsgxscommon.h" -#include "serialiser/rsserializable.h" - -class RsPosted; - -/** - * Pointer to global instance of RsGxsChannels service implementation - * @jsonapi{development} - */ -extern RsPosted* rsPosted; - -struct RsPostedGroup: RsGxsGenericGroupData -{ - std::string mDescription; - RsGxsImage mGroupImage; -}; - -struct RsPostedPost: public RsGxsGenericMsgData -{ - RsPostedPost(): mHaveVoted(false), mUpVotes(0), mDownVotes(0), mComments(0), - mHotScore(0), mTopScore(0), mNewScore(0) {} - - bool calculateScores(rstime_t ref_time); - - std::string mLink; - std::string mNotes; - - bool mHaveVoted; - - // Calculated. - uint32_t mUpVotes; - uint32_t mDownVotes; - uint32_t mComments; - - - // and Calculated Scores:??? - double mHotScore; - double mTopScore; - double mNewScore; - - RsGxsImage mImage; - - /// @see RsSerializable - /*virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mImage); - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mLink); - RS_SERIAL_PROCESS(mHaveVoted); - RS_SERIAL_PROCESS(mUpVotes); - RS_SERIAL_PROCESS(mDownVotes); - RS_SERIAL_PROCESS(mComments); - RS_SERIAL_PROCESS(mHotScore); - RS_SERIAL_PROCESS(mTopScore); - RS_SERIAL_PROCESS(mNewScore); - }*/ -}; - - -//#define RSPOSTED_MSGTYPE_POST 0x0001 -//#define RSPOSTED_MSGTYPE_VOTE 0x0002 -//#define RSPOSTED_MSGTYPE_COMMENT 0x0004 - -#define RSPOSTED_PERIOD_YEAR 1 -#define RSPOSTED_PERIOD_MONTH 2 -#define RSPOSTED_PERIOD_WEEK 3 -#define RSPOSTED_PERIOD_DAY 4 -#define RSPOSTED_PERIOD_HOUR 5 - -#define RSPOSTED_VIEWMODE_LATEST 1 -#define RSPOSTED_VIEWMODE_TOP 2 -#define RSPOSTED_VIEWMODE_HOT 3 -#define RSPOSTED_VIEWMODE_COMMENTS 4 - - -enum class RsPostedEventCode: uint8_t -{ - UNKNOWN = 0x00, - NEW_POSTED_GROUP = 0x01, - NEW_MESSAGE = 0x02, - SUBSCRIBE_STATUS_CHANGED = 0x03, - UPDATED_POSTED_GROUP = 0x04, - UPDATED_MESSAGE = 0x05, - READ_STATUS_CHANGED = 0x06, - STATISTICS_CHANGED = 0x07, - MESSAGE_VOTES_UPDATED = 0x08, - SYNC_PARAMETERS_UPDATED = 0x09, - NEW_COMMENT = 0x0a, - NEW_VOTE = 0x0b, - BOARD_DELETED = 0x0c, -}; - - -struct RsGxsPostedEvent: RsEvent -{ - RsGxsPostedEvent(): - RsEvent(RsEventType::GXS_POSTED), - mPostedEventCode(RsPostedEventCode::UNKNOWN) {} - - RsPostedEventCode mPostedEventCode; - RsGxsGroupId mPostedGroupId; - RsGxsMessageId mPostedMsgId; - RsGxsMessageId mPostedThreadId; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mPostedEventCode); - RS_SERIAL_PROCESS(mPostedGroupId); - RS_SERIAL_PROCESS(mPostedMsgId); - } - - ~RsGxsPostedEvent() override; -}; - -class RsPosted : public RsGxsIfaceHelper, public RsGxsCommentService -{ -public: - explicit RsPosted(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - - virtual bool getBoardsInfo( - const std::list& boardsIds, - std::vector& boardsInfo ) = 0; - - virtual bool getBoardsSummaries(std::list& groupInfo) =0; - - virtual bool getBoardAllContent( - const RsGxsGroupId& boardId, - std::vector& posts, - std::vector& comments, - std::vector& votes ) = 0; - - virtual bool getBoardContent( - const RsGxsGroupId& boardId, - const std::set& contentsIds, - std::vector& posts, - std::vector& comments, - std::vector& votes ) = 0; - - virtual bool editBoard(RsPostedGroup& board) =0; - - virtual bool createBoard(RsPostedGroup& board) =0; - - virtual bool getBoardStatistics(const RsGxsGroupId& boardId,GxsGroupStatistic& stat) =0; - - virtual bool getBoardsServiceStatistics(GxsServiceStatistic& stat) =0; - - virtual bool voteForPost(bool up,const RsGxsGroupId& postGrpId,const RsGxsMessageId& postMsgId,const RsGxsId& voterId) =0; - - virtual bool setPostReadStatus(const RsGxsGrpMsgIdPair& msgId, bool read) = 0; - - enum RS_DEPRECATED RankType {TopRankType, HotRankType, NewRankType }; - - RS_DEPRECATED_FOR(getBoardsInfo) - virtual bool getGroupData( const uint32_t& token, - std::vector &groups ) = 0; - - RS_DEPRECATED_FOR(getBoardsContent) - virtual bool getPostData( - const uint32_t& token, std::vector& posts, - std::vector& cmts, std::vector& vots) = 0; - - RS_DEPRECATED_FOR(getBoardsContent) - virtual bool getPostData( - const uint32_t& token, std::vector& posts, - std::vector& cmts) = 0; - - RS_DEPRECATED_FOR(getBoardsContent) - virtual bool getPostData( - const uint32_t& token, std::vector& posts) = 0; - - virtual bool setCommentAsRead(uint32_t& token,const RsGxsGroupId& gid,const RsGxsMessageId& comment_msg_id) =0; - - //Not currently used -//virtual bool getRelatedPosts(const uint32_t &token, std::vector &posts) = 0; - - /* From RsGxsCommentService */ -//virtual bool getCommentData(const uint32_t &token, std::vector &comments) = 0; -//virtual bool getRelatedComments(const uint32_t &token, std::vector &comments) = 0; -//virtual bool createNewComment(uint32_t &token, RsGxsComment &comment) = 0; -//virtual bool createNewVote(uint32_t &token, RsGxsVote &vote) = 0; - - RS_DEPRECATED_FOR(setPostReadStatus) - virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0; - ////////////////////////////////////////////////////////////////////////////// - -virtual bool createGroup(uint32_t &token, RsPostedGroup &group) = 0; -virtual bool createPost(uint32_t &token, RsPostedPost &post) = 0; - -virtual bool updateGroup(uint32_t &token, RsPostedGroup &group) = 0; - - virtual bool groupShareKeys(const RsGxsGroupId& group,const std::set& peers) = 0 ; - - virtual ~RsPosted(); -}; diff --git a/libretroshare/src/retroshare/rsreputations.h b/libretroshare/src/retroshare/rsreputations.h deleted file mode 100644 index b8426e642..000000000 --- a/libretroshare/src/retroshare/rsreputations.h +++ /dev/null @@ -1,245 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsreputations.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Cyril Soler * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsids.h" -#include "retroshare/rsgxsifacetypes.h" -#include "serialiser/rsserializable.h" - -class RsReputations; - -/** - * Pointer to global instance of RsReputations service implementation - * @jsonapi{development} - */ -extern RsReputations* rsReputations; - - -constexpr float RS_REPUTATION_THRESHOLD_DEFAULT = 1.0f; - -enum struct RsOpinion : uint8_t -{ - NEGATIVE = 0, - NEUTRAL = 1, - POSITIVE = 2 -}; - -enum struct RsReputationLevel : uint8_t -{ - /// local opinion is negative - LOCALLY_NEGATIVE = 0x00, - - /// local opinion is neutral and friends are positive in average - REMOTELY_NEGATIVE = 0x01, - - /// no reputation information - NEUTRAL = 0x02, - - /// local opinion is neutral and friends are positive in average - REMOTELY_POSITIVE = 0x03, - - /// local opinion is positive - LOCALLY_POSITIVE = 0x04, - - /// missing info - UNKNOWN = 0x05 -}; - -struct RsReputationInfo : RsSerializable -{ - RsReputationInfo() : - mOwnOpinion(RsOpinion::NEUTRAL), mFriendsPositiveVotes(0), - mFriendsNegativeVotes(0), - mFriendAverageScore(RS_REPUTATION_THRESHOLD_DEFAULT), - mOverallReputationLevel(RsReputationLevel::NEUTRAL) {} - - RsOpinion mOwnOpinion; - - uint32_t mFriendsPositiveVotes; - uint32_t mFriendsNegativeVotes; - - float mFriendAverageScore; - - /// this should help clients in taking decisions - RsReputationLevel mOverallReputationLevel; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mOwnOpinion); - RS_SERIAL_PROCESS(mFriendsPositiveVotes); - RS_SERIAL_PROCESS(mFriendsNegativeVotes); - RS_SERIAL_PROCESS(mFriendAverageScore); - RS_SERIAL_PROCESS(mOverallReputationLevel); - } - - virtual ~RsReputationInfo(); -}; - - -class RsReputations -{ -public: - virtual ~RsReputations() {} - - /** - * @brief Set own opinion about the given identity - * @jsonapi{development} - * @param[in] id Id of the identity - * @param[in] op Own opinion - * @return false on error, true otherwise - */ - virtual bool setOwnOpinion(const RsGxsId& id, RsOpinion op) = 0; - - /** - * @brief Get own opition about the given identity - * @jsonapi{development} - * @param[in] id Id of the identity - * @param[out] op Own opinion - * @return false on error, true otherwise - */ - virtual bool getOwnOpinion(const RsGxsId& id, RsOpinion& op) = 0; - - /** - * @brief Get reputation data of given identity - * @jsonapi{development} - * @param[in] id Id of the identity - * @param[in] ownerNode Optiona PGP id of the signed identity, accept a null - * (all zero/noninitialized) PGP id - * @param[out] info storage for the information - * @param[in] stamp if true, timestamo the information - * @return false on error, true otherwise - */ - virtual bool getReputationInfo( - const RsGxsId& id, const RsPgpId& ownerNode, RsReputationInfo& info, - bool stamp = true ) = 0; - - /** - * @brief Get overall reputation level of given identity - * @jsonapi{development} - * @param[in] id Id of the identity - * @return the calculated reputation level based on available information - */ - virtual RsReputationLevel overallReputationLevel(const RsGxsId& id) = 0; - - /** - * @brief Enable giving automatic positive opinion when flagging as contact - * @jsonapi{development} - * @param[in] b true to enable, false to disable - */ - virtual void setAutoPositiveOpinionForContacts(bool b) = 0; - - /** - * @brief check if giving automatic positive opinion when flagging as - * contact is enbaled - * @jsonapi{development} - * @return true if enabled, false otherwise - */ - virtual bool autoPositiveOpinionForContacts() = 0; - - /** - * @brief Set threshold on remote reputation to consider it remotely - * negative - * @jsonapi{development} - * @param[in] thresh Threshold value - */ - virtual void setThresholdForRemotelyNegativeReputation(uint32_t thresh) = 0; - - /** - * * @brief Get threshold on remote reputation to consider it remotely - * negative - * @jsonapi{development} - * @return Threshold value - */ - virtual uint32_t thresholdForRemotelyNegativeReputation() = 0; - - /** - * @brief Set threshold on remote reputation to consider it remotely - * positive - * @jsonapi{development} - * @param[in] thresh Threshold value - */ - virtual void setThresholdForRemotelyPositiveReputation(uint32_t thresh) = 0; - - /** - * @brief Get threshold on remote reputation to consider it remotely - * negative - * @jsonapi{development} - * @return Threshold value - */ - virtual uint32_t thresholdForRemotelyPositiveReputation() = 0; - - /** - * @brief Get number of days to wait before deleting a banned identity from - * local storage - * @jsonapi{development} - * @return number of days to wait, 0 means never delete - */ - virtual uint32_t rememberBannedIdThreshold() = 0; - - /** - * @brief Set number of days to wait before deleting a banned identity from - * local storage - * @jsonapi{development} - * @param[in] days number of days to wait, 0 means never delete - */ - virtual void setRememberBannedIdThreshold(uint32_t days) = 0; - - /** - * @brief This method allow fast checking if a GXS identity is banned. - * @jsonapi{development} - * @param[in] id Id of the identity to check - * @return true if identity is banned, false otherwise - */ - virtual bool isIdentityBanned(const RsGxsId& id) = 0; - - /** - * @brief Check if automatic banning of all identities signed by the given - * node is enabled - * @jsonapi{development} - * @param[in] id PGP id of the node - * @return true if enabled, false otherwise - */ - virtual bool isNodeBanned(const RsPgpId& id) = 0; - - /** - * @brief Enable automatic banning of all identities signed by the given - * node - * @jsonapi{development} - * @param[in] id PGP id of the node - * @param[in] b true to enable, false to disable - */ - virtual void banNode(const RsPgpId& id, bool b) = 0; - - - /** - * @deprecated - * This returns the reputation level and also the flags of the identity - * service for that id. This is useful in order to get these flags without - * relying on the async method of p3Identity - */ - RS_DEPRECATED - virtual RsReputationLevel overallReputationLevel( - const RsGxsId& id, uint32_t* identity_flags ) = 0; -}; diff --git a/libretroshare/src/retroshare/rsrtt.h b/libretroshare/src/retroshare/rsrtt.h deleted file mode 100644 index e55220307..000000000 --- a/libretroshare/src/retroshare/rsrtt.h +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsposted.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_RTT_INTERFACE_H -#define RETROSHARE_RTT_INTERFACE_H - -#include -#include -#include -#include - -/* The Main Interface Class - for information about your Peers */ -class RsRtt; -extern RsRtt *rsRtt; - - -class RsRttPongResult -{ - public: - RsRttPongResult() - :mTS(0), mRTT(0), mOffset(0) { return; } - - RsRttPongResult(double ts, double rtt, double offset) - :mTS(ts), mRTT(rtt), mOffset(offset) { return; } - - double mTS; - double mRTT; - double mOffset; -}; - -class RsRtt -{ - public: - - RsRtt() { return; } -virtual ~RsRtt() { return; } - -virtual uint32_t getPongResults(const RsPeerId& id, int n, std::list &results) = 0; -virtual double getMeanOffset(const RsPeerId& id) = 0; - -}; - -#endif diff --git a/libretroshare/src/retroshare/rsservicecontrol.h b/libretroshare/src/retroshare/rsservicecontrol.h deleted file mode 100644 index 4946f5247..000000000 --- a/libretroshare/src/retroshare/rsservicecontrol.h +++ /dev/null @@ -1,200 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsservicecontrol.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014-2014 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_SERVICE_CONTROL_GUI_INTERFACE_H -#define RETROSHARE_SERVICE_CONTROL_GUI_INTERFACE_H - -#include -#include -#include -#include -#include -#include - -/* The Main Interface Class - for information about your Peers */ -class RsServiceControl; - -/** - * Pointer to global instance of RsServiceControl service implementation - * @jsonapi{development} - */ -extern RsServiceControl* rsServiceControl; - -struct RsServiceInfo : RsSerializable -{ - RsServiceInfo(); - RsServiceInfo( - const uint16_t service_type, - const std::string& service_name, - const uint16_t version_major, - const uint16_t version_minor, - const uint16_t min_version_major, - const uint16_t min_version_minor); - - static unsigned int RsServiceInfoUIn16ToFullServiceId(uint16_t serviceType); - - std::string mServiceName; - uint32_t mServiceType; - // current version, we running. - uint16_t mVersionMajor; - uint16_t mVersionMinor; - // minimum version can communicate with. - uint16_t mMinVersionMajor; - uint16_t mMinVersionMinor; - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(mServiceName); - RS_SERIAL_PROCESS(mServiceType); - RS_SERIAL_PROCESS(mVersionMajor); - RS_SERIAL_PROCESS(mVersionMinor); - RS_SERIAL_PROCESS(mMinVersionMajor); - RS_SERIAL_PROCESS(mMinVersionMinor); - } -}; - -bool ServiceInfoCompatible(const RsServiceInfo &info1, const RsServiceInfo &info2); - -/* this is what is transmitted to peers */ -struct RsPeerServiceInfo : RsSerializable -{ - RsPeerServiceInfo() : mPeerId(), mServiceList() {} - - RsPeerId mPeerId; - std::map mServiceList; - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(mPeerId); - RS_SERIAL_PROCESS(mServiceList); - } -}; - -struct RsServicePermissions : RsSerializable -{ - RsServicePermissions(); - - bool peerHasPermission(const RsPeerId &peerId) const; - - void setPermission(const RsPeerId& peerId) ; - void resetPermission(const RsPeerId& peerId) ; - - uint32_t mServiceId; - std::string mServiceName; - - bool mDefaultAllowed; - // note only one of these is checked. - // if DefaultAllowed = true, then only PeersDenied is checked. - // if DefaultAllowed = false, then only PeersAllowed is checked. - std::set mPeersAllowed; - std::set mPeersDenied; - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(mServiceId); - RS_SERIAL_PROCESS(mServiceName); - - RS_SERIAL_PROCESS(mDefaultAllowed); - - RS_SERIAL_PROCESS(mPeersAllowed); - RS_SERIAL_PROCESS(mPeersDenied); - } -}; - -class RsServiceControl -{ -public: - - RsServiceControl() {} - virtual ~RsServiceControl(){} - - /** - * @brief get a map off all services. - * @jsonapi{development} - * @param[out] info storage for service information - * @return always true - */ - virtual bool getOwnServices(RsPeerServiceInfo &info) = 0; - - /** - * @brief getServiceName lookup the name of a service. - * @jsonapi{development} - * @param[in] serviceId service to look up - * @return name of service - */ - virtual std::string getServiceName(uint32_t serviceId) = 0; - - /** - * @brief getServiceItemNames return a map of service item names. - * @jsonapi{development} - * @param[in] serviceId service to look up - * @param[out] names names of items - * @return true on success false otherwise - */ - virtual bool getServiceItemNames(uint32_t serviceId, std::map& names) = 0; - - /** - * @brief getServicesAllowed return a mpa with allowed service information. - * @jsonapi{development} - * @param[in] peerId peer to look up - * @param[out] info map with infomration - * @return always true - */ - virtual bool getServicesAllowed(const RsPeerId &peerId, RsPeerServiceInfo &info) = 0; - - /** - * @brief getServicesProvided return services provided by a peer. - * @jsonapi{development} - * @param[in] peerId peer to look up - * @param[out] info - * @return true on success false otherwise. - */ - virtual bool getServicesProvided(const RsPeerId &peerId, RsPeerServiceInfo &info) = 0; - - /** - * @brief getServicePermissions return permissions of one service. - * @jsonapi{development} - * @param[in] serviceId service id to look up - * @param[out] permissions - * @return true on success false otherwise. - */ - virtual bool getServicePermissions(uint32_t serviceId, RsServicePermissions &permissions) = 0; - - /** - * @brief updateServicePermissions update service permissions of one service. - * @jsonapi{development} - * @param[in] serviceId service to update - * @param[in] permissions new permissions - * @return true on success false otherwise. - */ - virtual bool updateServicePermissions(uint32_t serviceId, const RsServicePermissions &permissions) = 0; - - /** - * @brief getPeersConnected return peers using a service. - * @jsonapi{development} - * @param[in] serviceId service to look up. - * @param[out] peerSet set of peers using this service. - */ - virtual void getPeersConnected( uint32_t serviceId, - std::set& peerSet ) = 0; -}; - -#endif diff --git a/libretroshare/src/retroshare/rsstatus.h b/libretroshare/src/retroshare/rsstatus.h deleted file mode 100644 index 3173726bb..000000000 --- a/libretroshare/src/retroshare/rsstatus.h +++ /dev/null @@ -1,96 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsstatus.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Vinny Do, Chris Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_STATUS_INTERFACE_H -#define RS_STATUS_INTERFACE_H - -class RsStatus; - -extern RsStatus *rsStatus; - -#include -#include -#include -#include -#include - - -const uint32_t RS_STATUS_OFFLINE = 0x0000; -const uint32_t RS_STATUS_AWAY = 0x0001; -const uint32_t RS_STATUS_BUSY = 0x0002; -const uint32_t RS_STATUS_ONLINE = 0x0003; -const uint32_t RS_STATUS_INACTIVE = 0x0004; - -const uint32_t RS_STATUS_COUNT = 0x0005; // count of status - -//! data object for peer status information -/*! - * data object used for peer status information - */ -class StatusInfo -{ - public: - StatusInfo() : status(RS_STATUS_OFFLINE), time_stamp(0) {} - - public: - RsPeerId id; - uint32_t status; - rstime_t time_stamp; /// for owner time set, and for their peers time sent -}; - - -//! Interface to retroshare for Rs status -/*! - * Provides an interface for retroshare's status functionality - */ -class RsStatus -{ - public: - - /** - * This retrieves the own status info - * @param statusInfo is populated with own status - */ - virtual bool getOwnStatus(StatusInfo& statusInfo) = 0; - - /** - * This retrieves the status info on the client's peers - * @param statusInfo is populated with client's peer's status - */ - virtual bool getStatusList(std::list& statusInfo) = 0; - - /** - * This retrieves the status info one peer - * @param statusInfo is populated with client's peer's status - */ - virtual bool getStatus(const RsPeerId &id, StatusInfo &statusInfo) = 0; - - /** - * send the client's status to his/her peers - * @param id the peer to send the status (empty, send to all) - * @param status the status of the peers - * @return will return false if status info does not belong to client - */ - virtual bool sendStatus(const RsPeerId &id, uint32_t status) = 0; -}; - - -#endif diff --git a/libretroshare/src/retroshare/rstokenservice.h b/libretroshare/src/retroshare/rstokenservice.h deleted file mode 100644 index a0fbd7258..000000000 --- a/libretroshare/src/retroshare/rstokenservice.h +++ /dev/null @@ -1,285 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rstokenservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Chris Evi-Parker * - * Copyright (C) 2012 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "retroshare/rsgxsifacetypes.h" -#include "util/rsdeprecate.h" -#include "util/rsdebug.h" - -// TODO CLEANUP: GXS_REQUEST_TYPE_* should be an inner enum of RsTokReqOptions -#define GXS_REQUEST_TYPE_GROUP_DATA 0x00010000 -#define GXS_REQUEST_TYPE_GROUP_META 0x00020000 -#define GXS_REQUEST_TYPE_GROUP_IDS 0x00040000 -#define GXS_REQUEST_TYPE_MSG_DATA 0x00080000 -#define GXS_REQUEST_TYPE_MSG_META 0x00100000 -#define GXS_REQUEST_TYPE_MSG_IDS 0x00200000 - -#define GXS_REQUEST_TYPE_MSG_RELATED_DATA 0x00400000 -#define GXS_REQUEST_TYPE_MSG_RELATED_META 0x00800000 -#define GXS_REQUEST_TYPE_MSG_RELATED_IDS 0x01000000 - -#define GXS_REQUEST_TYPE_GROUP_STATS 0x01600000 -#define GXS_REQUEST_TYPE_SERVICE_STATS 0x03200000 -#define GXS_REQUEST_TYPE_GROUP_SERIALIZED_DATA 0x04000000 - - -// TODO CLEANUP: RS_TOKREQOPT_MSG_* should be an inner enum of RsTokReqOptions -#define RS_TOKREQOPT_MSG_VERSIONS 0x0001 // MSGRELATED: Returns All MsgIds with OrigMsgId = MsgId. -#define RS_TOKREQOPT_MSG_ORIGMSG 0x0002 // MSGLIST: All Unique OrigMsgIds in a Group. -#define RS_TOKREQOPT_MSG_LATEST 0x0004 // MSGLIST: All Latest MsgIds in Group. MSGRELATED: Latest MsgIds for Input Msgs. -#define RS_TOKREQOPT_MSG_THREAD 0x0010 // MSGRELATED: All Msgs in Thread. MSGLIST: All Unique Thread Ids in Group. -#define RS_TOKREQOPT_MSG_PARENT 0x0020 // MSGRELATED: All Children Msgs. -#define RS_TOKREQOPT_MSG_AUTHOR 0x0040 // MSGLIST: Messages from this AuthorId - - -/* TODO CLEANUP: RS_TOKREQ_ANSTYPE_* values are meaningless and not used by - * RsTokenService or its implementation, and may be arbitrarly defined by each - * GXS client as they are of no usage, their use is deprecated, up until the - * definitive cleanup is done new code must use RS_DEPRECATED_TOKREQ_ANSTYPE for - * easier cleanup. */ -#ifndef RS_NO_WARN_DEPRECATED -# warning RS_TOKREQ_ANSTYPE_* macros are deprecated! -#endif -#define RS_DEPRECATED_TOKREQ_ANSTYPE 0x0000 -#define RS_TOKREQ_ANSTYPE_LIST 0x0001 -#define RS_TOKREQ_ANSTYPE_SUMMARY 0x0002 -#define RS_TOKREQ_ANSTYPE_DATA 0x0003 -#define RS_TOKREQ_ANSTYPE_ACK 0x0004 - - -/*! - * This class provides useful generic support for GXS style services. - * I expect much of this will be incorporated into the base GXS. - */ -struct RsTokReqOptions -{ - RsTokReqOptions() : mOptions(0), mStatusFilter(0), mStatusMask(0), - mMsgFlagMask(0), mMsgFlagFilter(0), mReqType(0), mSubscribeFilter(0), - mSubscribeMask(0), mBefore(0), mAfter(0),mPriority(GxsRequestPriority::NORMAL) {} - - /** - * Can be one or multiple RS_TOKREQOPT_* - * TODO: cleanup this should be made with proper flags instead of macros - */ - uint32_t mOptions; - - // Request specific matches with Group / Message Status. - // Should be usable with any Options... applied afterwards. - uint32_t mStatusFilter; - uint32_t mStatusMask; - - // use - uint32_t mMsgFlagMask, mMsgFlagFilter; - - /** - * Must be one of GXS_REQUEST_TYPE_* - * TODO: cleanup this should be made an enum instead of macros - */ - uint32_t mReqType; - - uint32_t mSubscribeFilter, mSubscribeMask; // Only for Groups. - - // Time range... again applied after Options. - rstime_t mBefore; - rstime_t mAfter; - - GxsRequestPriority mPriority; -}; - -/*! - * A proxy class for requesting generic service data for GXS - * This seperates the request mechanism from the actual retrieval of data - */ -class RsTokenService -{ -public: - - enum GxsRequestStatus : uint8_t - { - FAILED = 0, - PENDING = 1, - PARTIAL = 2, - COMPLETE = 3, - DONE = 4, /// Once all data has been retrived - CANCELLED = 5 - }; - - RsTokenService() {} - virtual ~RsTokenService() {} - - /* Data Requests */ - - /*! - * Use this to request group related information - * @param token The token returned for the request, store this value to poll for request completion - * @param ansType The type of result (e.g. group data, meta, ids) - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds group id to request info for - * @return - */ - virtual bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) = 0; - - /*! - * Use this to request all group related info - * @param token The token returned for the request, store this value to poll for request completion - * @param ansType The type of result (e.g. group data, meta, ids) - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @return - */ - virtual bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts) = 0; - - /*! - * Use this to get msg related information, store this value to poll for request completion - * @param token The token returned for the request - * @param ansType The type of result wanted - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs - * @return true if request successful false otherwise - */ - virtual bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const GxsMsgReq& msgIds) = 0; - - /*! - * Use this to get msg related information, store this value to poll for request completion - * @param token The token returned for the request - * @param ansType The type of result wanted - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds The ids of the groups to get, this retrieves all the msgs info for each grpId in list - * @return true if request successful false otherwise - */ - virtual bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list& grpIds) = 0; - - /*! - * For requesting msgs related to a given msg id within a group - * @param token The token returned for the request - * @param ansType The type of result wanted - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs - * @return true if request successful false otherwise - */ - virtual bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::vector& msgIds) = 0; - - /*! - * This request statistics on amount of data held - * number of groups - * number of groups subscribed - * number of messages - * size of db store - * total size of messages - * total size of groups - * @param token - */ - virtual void requestServiceStatistic(uint32_t& token, const RsTokReqOptions &opts) = 0; - - /*! - * To request statistic on a group - * @param token set to value to be redeemed to get statistic - * @param grpId the id of the group - */ - virtual void requestGroupStatistic(uint32_t& token, const RsGxsGroupId& grpId, const RsTokReqOptions &opts) = 0; - - - /* Poll */ - - /*! - * Request the status of ongoing request. - * Please use this for polling as much cheaper - * than polling the specific service as they might - * not return intermediate status information - * @param token value of token to check status for - * @return the current status of request - */ - virtual GxsRequestStatus requestStatus(const uint32_t token) = 0; - - /*! - * @brief Cancel Request - * If this function returns false, it may be that the request has completed - * already. Useful for very expensive request. - * @param token the token of the request to cancel - * @return false if unusuccessful in cancelling request, true if successful - */ - virtual bool cancelRequest(const uint32_t &token) = 0; - -#ifdef TO_REMOVE - /** - * Block caller while request is being processed. - * Useful for blocking API implementation. - * @param[in] token token associated to the request caller is waiting for - * @param[in] maxWait maximum waiting time in milliseconds - * @param[in] checkEvery time in millisecond between status checks - */ - RsTokenService::GxsRequestStatus waitToken( - uint32_t token, - std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000), - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(20), - bool auto_delete_if_unsuccessful=true) - { -#if defined(__ANDROID__) && (__ANDROID_API__ < 24) - auto wkStartime = std::chrono::steady_clock::now(); - int maxWorkAroundCnt = 10; -LLwaitTokenBeginLabel: -#endif - auto timeout = std::chrono::steady_clock::now() + maxWait; - auto st = requestStatus(token); - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = requestStatus(token); - } - if(st != RsTokenService::COMPLETE && auto_delete_if_unsuccessful) - cancelRequest(token); - -#if defined(__ANDROID__) && (__ANDROID_API__ < 24) - /* Work around for very slow/old android devices, we don't expect this - * to be necessary on newer devices. If it take unreasonably long - * something worser is already happening elsewere and we return anyway. - */ - if( st > RsTokenService::FAILED && st < RsTokenService::COMPLETE - && maxWorkAroundCnt-- > 0 ) - { - maxWait *= 10; - checkEvery *= 3; - Dbg3() << __PRETTY_FUNCTION__ << " Slow Android device " - << " workaround st: " << st - << " maxWorkAroundCnt: " << maxWorkAroundCnt - << " maxWait: " << maxWait.count() - << " checkEvery: " << checkEvery.count() << std::endl; - goto LLwaitTokenBeginLabel; - } - Dbg3() << __PRETTY_FUNCTION__ << " lasted: " - << std::chrono::duration_cast( - std::chrono::steady_clock::now() - wkStartime ).count() - << "ms" << std::endl; - -#endif - - return st; - } -#endif - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; diff --git a/libretroshare/src/retroshare/rsturtle.h b/libretroshare/src/retroshare/rsturtle.h deleted file mode 100644 index 76120e85b..000000000 --- a/libretroshare/src/retroshare/rsturtle.h +++ /dev/null @@ -1,170 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsturtle.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2018 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "serialiser/rstlvbinary.h" -#include "retroshare/rstypes.h" -#include "retroshare/rsgxsifacetypes.h" -#include "serialiser/rsserializable.h" - -namespace RsRegularExpression { class LinearizedExpression ; } -class RsTurtleClientService ; - -class RsTurtle; - -/** - * Pointer to global instance of RsTurtle service implementation - */ -extern RsTurtle* rsTurtle; - -typedef uint32_t TurtleRequestId ; -typedef RsPeerId TurtleVirtualPeerId; - -struct TurtleFileInfo : RsSerializable -{ - TurtleFileInfo() : size(0) {} - - uint64_t size; /// File size - RsFileHash hash; /// File hash - std::string name; /// File name - - /// @see RsSerializable::serial_process - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(hash); - - // Use String TLV serial process for retrocompatibility - RsTypeSerializer::serial_process( - j, ctx, TLV_TYPE_STR_NAME, name, "name" ); - } -} RS_DEPRECATED_FOR(TurtleFileInfoV2); - -struct TurtleTunnelRequestDisplayInfo -{ - uint32_t request_id ; // Id of the request - RsPeerId source_peer_id ; // Peer that relayed the request - uint32_t age ; // Age in seconds - uint32_t depth ; // Depth of the request. Might be altered. -}; -struct TurtleSearchRequestDisplayInfo -{ - uint32_t request_id ; // Id of the request - RsPeerId source_peer_id ; // Peer that relayed the request - uint32_t age ; // Age in seconds - uint32_t depth ; // Depth of the request. Might be altered. - uint32_t hits ; - std::string keywords; -}; - -class TurtleTrafficStatisticsInfo -{ - public: - float unknown_updn_Bps ; // unknown data transit bitrate (in Bytes per sec.) - float data_up_Bps ; // upload (in Bytes per sec.) - float data_dn_Bps ; // download (in Bytes per sec.) - float tr_up_Bps ; // tunnel requests upload bitrate (in Bytes per sec.) - float tr_dn_Bps ; // tunnel requests dnload bitrate (in Bytes per sec.) - float total_up_Bps ; // turtle network management bitrate (in Bytes per sec.) - float total_dn_Bps ; // turtle network management bitrate (in Bytes per sec.) - - std::vector forward_probabilities ; // probability to forward a TR as a function of depth. -}; - -// Interface class for turtle hopping. -// -// This class mainly interacts with the turtle router, that is responsible -// for routing turtle packets between peers, accepting/forwarding search -// requests and dowloading files. -// -// As seen from here, the interface is really simple. -// -class RsTurtle -{ -public: - RsTurtle() {} - virtual ~RsTurtle() {} - - // This is saved permanently. - virtual void setEnabled(bool) = 0 ; - virtual bool enabled() const = 0 ; - - // This is temporary, used by Operating Mode. - virtual void setSessionEnabled(bool) = 0 ; - virtual bool sessionEnabled() const = 0 ; - - /** Lauches a search request through the pipes, and immediately returns - * the request id, which will be further used by client services to - * handle results as they come back. */ - virtual TurtleRequestId turtleSearch( - unsigned char *search_bin_data, uint32_t search_bin_data_len, - RsTurtleClientService* client_service ) = 0; - - // Initiates tunnel handling for the given file hash. tunnels. Launches - // an exception if an error occurs during the initialization process. The - // turtle router itself does not initiate downloads, it only maintains - // tunnels for the given hash. The download should be driven by the file - // transfer module by calling ftServer::FileRequest(). - // Aggressive mode causes the turtle router to regularly re-ask tunnels in addition to the ones already - // available without replacing them. In non aggressive mode, we wait for all tunnels to die before asking - // for new tunnels. - // - virtual void monitorTunnels(const RsFileHash& file_hash,RsTurtleClientService *client_service,bool use_aggressive_mode) = 0 ; - - // Tells the turtle router to stop handling tunnels for the given file hash. Traditionally this should - // be called after calling ftServer::fileCancel(). - // - virtual void stopMonitoringTunnels(const RsFileHash& file_hash) = 0 ; - - /// Adds a client tunnel service. This means that the service will be added - /// to the list of services that might respond to tunnel requests. - /// Example tunnel services include: - /// - /// p3ChatService: tunnels correspond to private distant chatting - /// ftServer : tunnels correspond to file data transfer - /// - virtual void registerTunnelService(RsTurtleClientService *service) = 0; - - virtual std::string getPeerNameForVirtualPeerId(const RsPeerId& virtual_peer_id) = 0; - - // Get info from the turtle router. I use std strings to hide the internal structs. - // - virtual void getInfo(std::vector >&,std::vector >&, - std::vector&,std::vector&) const = 0; - - // Get info about turtle traffic. See TurtleTrafficStatisticsInfo members for details. - // - virtual void getTrafficStatistics(TurtleTrafficStatisticsInfo& info) const = 0; - - // Convenience function. - virtual bool isTurtlePeer(const RsPeerId& peer_id) const = 0 ; - - // Hardcore handles - virtual void setMaxTRForwardRate(int max_tr_up_rate) = 0 ; - virtual int getMaxTRForwardRate() const = 0 ; -}; diff --git a/libretroshare/src/retroshare/rstypes.h b/libretroshare/src/retroshare/rstypes.h deleted file mode 100644 index 97d97f565..000000000 --- a/libretroshare/src/retroshare/rstypes.h +++ /dev/null @@ -1,564 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: rstypes.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_TYPES_GUI_INTERFACE_H -#define RS_TYPES_GUI_INTERFACE_H - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "util/rstime.h" - -#define USE_NEW_CHUNK_CHECKING_CODE - -typedef Sha1CheckSum RsFileHash ; - -const uint32_t FT_STATE_FAILED = 0x0000 ; -const uint32_t FT_STATE_OKAY = 0x0001 ; -const uint32_t FT_STATE_WAITING = 0x0002 ; -const uint32_t FT_STATE_DOWNLOADING = 0x0003 ; -const uint32_t FT_STATE_COMPLETE = 0x0004 ; -const uint32_t FT_STATE_QUEUED = 0x0005 ; -const uint32_t FT_STATE_PAUSED = 0x0006 ; -const uint32_t FT_STATE_CHECKING_HASH = 0x0007 ; - -// These constants are used by RsDiscSpace -// -const uint32_t RS_PARTIALS_DIRECTORY = 0x0000 ; -const uint32_t RS_DOWNLOAD_DIRECTORY = 0x0001 ; -const uint32_t RS_CONFIG_DIRECTORY = 0x0002 ; -const uint32_t RS_PGP_DIRECTORY = 0x0003 ; -const uint32_t RS_DIRECTORY_COUNT = 0x0004 ; - -struct TransferInfo : RsSerializable -{ - /**** Need Some of these Fields ****/ - RsPeerId peerId; - std::string name; /* if has alternative name? */ - double tfRate; /* kbytes */ - int status; /* FT_STATE_... */ - uint64_t transfered ; // used when no chunkmap data is available - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(peerId); - RS_SERIAL_PROCESS(name); - RS_SERIAL_PROCESS(tfRate); - RS_SERIAL_PROCESS(status); - RS_SERIAL_PROCESS(transfered); - } -}; - -enum QueueMove { QUEUE_TOP = 0x00, - QUEUE_UP = 0x01, - QUEUE_DOWN = 0x02, - QUEUE_BOTTOM = 0x03 -}; - -enum DwlSpeed : uint8_t -{ - SPEED_LOW = 0x00, - SPEED_NORMAL = 0x01, - SPEED_HIGH = 0x02 -}; - - - - -/********************** For Search Interface *****************/ - -/* This is still rough, implement later! */ - - /* text based ones */ -const std::string TypeExt = "ext"; -const std::string TypeName = "name"; -const std::string TypeHash = "hash"; -const std::string TypeSize = "size"; - -const int OpContains = 0x001; -const int OpExactMatch = 0x002; -const int OpLessThan = 0x003; -const int OpGreaterThan = 0x004; - -class Condition -{ - public: - - std::string type; - int op; - double value; - std::string name; -}; - -struct PeerBandwidthLimits : RsSerializable -{ - PeerBandwidthLimits() : max_up_rate_kbs(0), max_dl_rate_kbs(0) {} - - uint32_t max_up_rate_kbs; - uint32_t max_dl_rate_kbs; - - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(max_up_rate_kbs); - RS_SERIAL_PROCESS(max_dl_rate_kbs); - } -}; - -//class SearchRequest // unused stuff. -//{ -// public: -// int searchId; -// RsCertId toId; /* all zeros for everyone! */ -// std::list tests; -//}; - - -/********************** For FileCache Interface *****************/ - -#define DIR_TYPE_UNKNOWN 0x00 -#define DIR_TYPE_ROOT 0x01 -#define DIR_TYPE_PERSON 0x02 -#define DIR_TYPE_DIR 0x04 -#define DIR_TYPE_FILE 0x08 -#define DIR_TYPE_EXTRA_FILE 0x10 - -/* flags for Directry request - - * two types; - * (1) Local / Remote (top byte) - * (2) Request type: Parent / Child - allows reduction in workload. - * (TODO) - */ - -const FileStorageFlags DIR_FLAGS_PARENT ( 0x0001 ); -const FileStorageFlags DIR_FLAGS_DETAILS ( 0x0002 ); // apparently unused -const FileStorageFlags DIR_FLAGS_CHILDREN ( 0x0004 ); // apparently unused - -const FileStorageFlags DIR_FLAGS_ANONYMOUS_DOWNLOAD ( 0x0080 ); // Flags for directory sharing permissions. The last -//const FileStorageFlags DIR_FLAGS_BROWSABLE_OTHERS ( 0x0100 ); // one should be the OR of the all four flags. -//const FileStorageFlags DIR_FLAGS_NETWORK_WIDE_GROUPS ( 0x0200 ); -const FileStorageFlags DIR_FLAGS_BROWSABLE ( 0x0400 ); -const FileStorageFlags DIR_FLAGS_ANONYMOUS_SEARCH ( 0x0800 ); -const FileStorageFlags DIR_FLAGS_PERMISSIONS_MASK ( DIR_FLAGS_ANONYMOUS_DOWNLOAD | /*DIR_FLAGS_BROWSABLE_OTHERS - DIR_FLAGS_NETWORK_WIDE_GROUPS*/ DIR_FLAGS_BROWSABLE | DIR_FLAGS_ANONYMOUS_SEARCH); - -const FileStorageFlags DIR_FLAGS_LOCAL ( 0x1000 ); -const FileStorageFlags DIR_FLAGS_REMOTE ( 0x2000 ); - -struct FileInfo : RsSerializable -{ - FileInfo(): - mId(0), searchId(0), size(0), avail(0), rank(0), age(0), - queue_position(0), transfered(0), tfRate(0), downloadStatus(0), - priority(SPEED_NORMAL), lastTS(0) {} - - /// Combination of the four RS_DIR_FLAGS_*. Updated when the file is a local stored file. - FileStorageFlags storage_permission_flags; - - /// various flags from RS_FILE_HINTS_* - TransferRequestFlags transfer_info_flags; - - /** allow this to be tweaked by the GUI Model - * (GUI) Model Id -> unique number - */ - mutable unsigned int mId; - - - /// 0 if none - int searchId; - - std::string path; - std::string fname; - RsFileHash hash; - - RS_DEPRECATED std::string ext; /// @deprecated unused - - uint64_t size; - uint64_t avail; /// how much we have - - double rank; - int age; - uint32_t queue_position; - - /* Transfer Stuff */ - uint64_t transfered; - double tfRate; /// in kbytes - uint32_t downloadStatus; /// FT_STATE_DOWNLOADING & co. See rstypes.h - std::vector peers; - - DwlSpeed priority; - rstime_t lastTS; - - std::list parent_groups; - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(storage_permission_flags); - RS_SERIAL_PROCESS(transfer_info_flags); - RS_SERIAL_PROCESS(mId); - RS_SERIAL_PROCESS(searchId); - RS_SERIAL_PROCESS(path); - RS_SERIAL_PROCESS(fname); - RS_SERIAL_PROCESS(hash); - RS_SERIAL_PROCESS(ext); - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(avail); - RS_SERIAL_PROCESS(rank); - RS_SERIAL_PROCESS(age); - RS_SERIAL_PROCESS(queue_position); - RS_SERIAL_PROCESS(transfered); - RS_SERIAL_PROCESS(tfRate); - RS_SERIAL_PROCESS(downloadStatus); - RS_SERIAL_PROCESS(peers); - RS_SERIAL_PROCESS(priority); - RS_SERIAL_PROCESS(lastTS); - RS_SERIAL_PROCESS(parent_groups); - } -}; - -/** - * Pointers in this class have no real meaning as pointers, they are used as - * indexes, internally by retroshare. - */ -struct DirStub : RsSerializable -{ - DirStub() : type(DIR_TYPE_UNKNOWN), ref(nullptr) {} - - uint8_t type; - std::string name; - void *ref; - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(type); - RS_SERIAL_PROCESS(name); - -#if defined(__GNUC__) && !defined(__clang__) -# pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif // defined(__GNUC__) && !defined(__clang__) - // (Cyril) We have to do this because on some systems (MacOS) uintptr_t is unsigned long which is not well defined. It is always - // preferable to force type serialization to the correct size rather than letting the compiler choose for us. - // /!\ This structure cannot be sent over the network. The serialization would be inconsistent. - - if(sizeof(ref) == 4) - { - std::uint32_t& handle(reinterpret_cast(ref)); - RS_SERIAL_PROCESS(handle); - } - else if(sizeof(ref) == 8) - { - std::uint64_t& handle(reinterpret_cast(ref)); - RS_SERIAL_PROCESS(handle); - } - else - std::cerr << __PRETTY_FUNCTION__ << ": cannot serialize raw pointer of size " << sizeof(ref) << std::endl; - -#if defined(__GNUC__) && !defined(__clang__) -# pragma GCC diagnostic pop -#endif // defined(__GNUC__) && !defined(__clang__) - } -}; - -/** - * Pointers in this class have no real meaning as pointers, they are used as - * indexes, internally by retroshare. - */ -struct DirDetails : RsSerializable -{ - DirDetails() : parent(nullptr), prow(0), ref(nullptr), - type(DIR_TYPE_UNKNOWN), size(0), mtime(0), max_mtime(0) {} - - - /* G10h4ck do we still need to keep this as void* instead of uint64_t for - * retroshare-gui sake? */ - void* parent; - - int prow; /* parent row */ - - /* G10h4ck do we still need to keep this as void* instead of uint64_t for - * retroshare-gui sake? */ - void* ref; - - uint8_t type; - RsPeerId id; - std::string name; - RsFileHash hash; - std::string path; // full path of the parent directory, when it is a file; full path of the dir otherwise. - uint64_t size; // total size of directory, or size of the file. - uint32_t mtime; // file/directory modification time, according to what the system reports - FileStorageFlags flags; - uint32_t max_mtime ; // maximum modification time of the whole hierarchy below. - - std::vector children; - std::list parent_groups; // parent groups for the shared directory - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - /* Enforce serialization as uint64_t because void* changes size - * depending (usually 4 bytes on 32bit arch and 8 bytes on 64bit archs) - */ - uint64_t handle = reinterpret_cast(ref); - RS_SERIAL_PROCESS(handle); - ref = reinterpret_cast(handle); - - uint64_t parentHandle = reinterpret_cast(parent); - RS_SERIAL_PROCESS(parentHandle); - parent = reinterpret_cast(parentHandle); - - RS_SERIAL_PROCESS(prow); - RS_SERIAL_PROCESS(type); - RS_SERIAL_PROCESS(id); - RS_SERIAL_PROCESS(name); - RS_SERIAL_PROCESS(hash); - RS_SERIAL_PROCESS(path); - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(mtime); - RS_SERIAL_PROCESS(flags); - RS_SERIAL_PROCESS(max_mtime); - RS_SERIAL_PROCESS(children); - RS_SERIAL_PROCESS(parent_groups); - } - - ~DirDetails() override = default; -}; - -class FileDetail -{ - public: - RsPeerId id; - std::string name; - RsFileHash hash; - std::string path; - uint64_t size; - uint32_t age; - uint32_t rank; -}; - -class CompressedChunkMap ; - -struct FileChunksInfo : RsSerializable -{ - enum ChunkState : uint8_t - { - CHUNK_OUTSTANDING = 0, - CHUNK_ACTIVE = 1, - CHUNK_DONE = 2, - CHUNK_CHECKING = 3 - }; - - enum ChunkStrategy : uint8_t - { - CHUNK_STRATEGY_STREAMING, - CHUNK_STRATEGY_RANDOM, - CHUNK_STRATEGY_PROGRESSIVE - }; - - struct SliceInfo : RsSerializable - { - uint32_t start; - uint32_t size; - RsPeerId peer_id; - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(start); - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(peer_id); - } - }; - - uint64_t file_size; /// real size of the file - uint32_t chunk_size; /// size of chunks - ChunkStrategy strategy; - - /// dl state of chunks. Only the last chunk may have size < chunk_size - std::vector chunks; - - /// For each source peer, gives the compressed bit map of have/don't have sate - std::map compressed_peer_availability_maps; - - /// For each chunk (by chunk number), gives the completion of the chunk. - std::vector > active_chunks; - - /// The list of pending requests, chunk per chunk (by chunk id) - std::map > pending_slices; - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(file_size); - RS_SERIAL_PROCESS(chunk_size); - RS_SERIAL_PROCESS(strategy); - RS_SERIAL_PROCESS(chunks); - RS_SERIAL_PROCESS(compressed_peer_availability_maps); - RS_SERIAL_PROCESS(active_chunks); - RS_SERIAL_PROCESS(pending_slices); - } -}; - -class CompressedChunkMap : public RsSerializable -{ - public: - CompressedChunkMap() {} - - CompressedChunkMap(const std::vector& uncompressed_data) - { - _map.resize( getCompressedSize(uncompressed_data.size()),0 ) ; - - for(uint32_t i=0;i>5) + !!(size&31) ; } - - uint32_t filledChunks(uint32_t nbchks) const - { - uint32_t res = 0 ; - for(uint32_t i=0;i> 5] & (1 << (i & 31))) > 0 ; } - - inline void set(uint32_t j) { _map[j >> 5] |= (1 << (j & 31)) ; } - inline void reset(uint32_t j) { _map[j >> 5] &= ~(1 << (j & 31)) ; } - - /// compressed map, one bit per chunk - std::vector _map; - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { RS_SERIAL_PROCESS(_map); } -}; - - -template class t_CRCMap -{ - public: - // Build from a file. - // - t_CRCMap(uint64_t file_size,uint32_t chunk_size) - : _crcs( file_size/chunk_size + ( (file_size%chunk_size)>0)), _ccmap(file_size/chunk_size + ( (file_size%chunk_size)>0),0) - { - } - t_CRCMap() {} - - inline void set(uint32_t i,const CRCTYPE& val) { _crcs[i] = val ; _ccmap.set(i) ; } - inline bool isSet(uint32_t i) const { return _ccmap[i] ; } - - inline const CRCTYPE& operator[](int i) const { return _crcs[i] ; } - inline uint32_t size() const { return _crcs.size() ; } - private: - std::vector _crcs; - CompressedChunkMap _ccmap ; - - friend class RsTurtleFileCrcItem ; - friend class RsFileItemSerialiser ; - friend class RsFileCRC32Map ; -}; - -//typedef t_CRCMap CRC32Map ; -typedef t_CRCMap Sha1Map ; - -/* class which encapsulates download details */ -class DwlDetails { -public: - DwlDetails() { return; } - DwlDetails(const std::string& fname, const RsFileHash& hash, int count, std::string dest, - uint32_t flags, std::list srcIds, uint32_t queue_pos) - : fname(fname), hash(hash), count(count), dest(dest), flags(flags), - srcIds(srcIds), queue_position(queue_pos), retries(0) { return; } - - /* download details */ - std::string fname; - RsFileHash hash; - int count; - std::string dest; - uint32_t flags; - std::list srcIds; - - /* internally used in download queue */ - uint32_t queue_position; - - /* how many times a failed dwl will be requeued */ - unsigned int retries; -}; - -/* class for the information about a used library */ -class RsLibraryInfo -{ -public: - RsLibraryInfo() {} - RsLibraryInfo(const std::string &name, const std::string &version) : - mName(name), mVersion(version) - {} - -public: - std::string mName; - std::string mVersion; -}; - -#endif diff --git a/libretroshare/src/retroshare/rsversion.h b/libretroshare/src/retroshare/rsversion.h deleted file mode 100644 index c16f6b9e7..000000000 --- a/libretroshare/src/retroshare/rsversion.h +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsversion.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2018 Retroshare Team * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/** - * @def RS_MINI_VERSION - * First number of RetroShare versioning scheme - * Customize it trough qmake command line @see retroshare.pri - */ -#ifndef RS_MAJOR_VERSION -# define RS_MAJOR_VERSION 0 -#endif - -/** - * @def RS_MINI_VERSION - * Second number of RetroShare versioning scheme - * Customize it trough qmake command line @see retroshare.pri - */ -#ifndef RS_MINOR_VERSION -# define RS_MINOR_VERSION 6 -#endif - -/** - * @def RS_MINI_VERSION - * Third number of RetroShare versioning scheme - * Customize it trough qmake command line @see retroshare.pri - */ -#ifndef RS_MINI_VERSION -# define RS_MINI_VERSION 6 -#endif - -/** - * @def RS_EXTRA_VERSION - * An extra string to append to the version to make it more descriptive. - * Customize it trough qmake command line @see retroshare.pri - */ -#ifndef RS_EXTRA_VERSION -# define RS_EXTRA_VERSION "" -#endif - - -/** - * Use this macro to check in your code if version of RetroShare is at least the - * specified. - */ -#define RS_VERSION_AT_LEAST(A,B,C) (RS_MAJOR_VERSION > (A) || \ - (RS_MAJOR_VERSION == (A) && \ - (RS_MINOR_VERSION > (B) || \ - (RS_MINOR_VERSION == (B) && RS_MINI_VERSION >= (C))))) - - -#define RS_PRIVATE_STRINGIFY2(X) #X -#define RS_PRIVATE_STRINGIFY(X) RS_PRIVATE_STRINGIFY2(X) - -/** - * Human readable string describing RetroShare version - */ -constexpr auto RS_HUMAN_READABLE_VERSION = - RS_PRIVATE_STRINGIFY(RS_MAJOR_VERSION) "." \ - RS_PRIVATE_STRINGIFY(RS_MINOR_VERSION) "." \ - RS_PRIVATE_STRINGIFY(RS_MINI_VERSION) RS_EXTRA_VERSION; - -/* Because RetroShare-gui include this file in gui/images/retroshare_win.rc - * including any C++ things like `#include ` will break compilation of - * RetroShare-gui on Windows. Therefore this file must be kept minimal. */ diff --git a/libretroshare/src/retroshare/rswebui.h b/libretroshare/src/retroshare/rswebui.h deleted file mode 100644 index d7166f545..000000000 --- a/libretroshare/src/retroshare/rswebui.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * RetroShare Web User Interface public header - * - * Copyright (C) 2019 Cyril Soler - * - * 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 - * - * SPDX-FileCopyrightText: 2004-2019 RetroShare Team - * SPDX-License-Identifier: LGPL-3.0-or-later - */ - -#pragma once - -#include - -class RsWebUi; - -/** - * Pointer to global instance of RsWebUi service implementation - * jsonapi_temporarly_disabled{development} because it breaks compilation when - * webui is disabled - */ -extern RsWebUi* rsWebUi; - -class RsWebUi -{ -public: - static const std::string DEFAULT_BASE_DIRECTORY; - - /** - * @brief Restart WebUI - * @jsonapi{development} - */ - virtual bool restart() = 0; - - /** - * @brief Stop WebUI - * @jsonapi{development} - */ - virtual bool stop() = 0; - - /** - * @brief Set WebUI static files directory, need restart to apply - * @param[in] htmlDir directory path - * @jsonapi{development} - */ - virtual void setHtmlFilesDirectory(const std::string& htmlDir) = 0; - - /** - * @brief Set WebUI user password - * @param[in] password new password for WebUI - * @jsonapi{development} - */ - virtual void setUserPassword(const std::string& password) =0; - - /** - * @brief check if WebUI is running - * @jsonapi{development} - * @return true if running, false otherwise - */ - virtual bool isRunning() const = 0; - - virtual ~RsWebUi() = default; -}; diff --git a/libretroshare/src/retroshare/rswiki.h b/libretroshare/src/retroshare/rswiki.h deleted file mode 100644 index 401f2cbab..000000000 --- a/libretroshare/src/retroshare/rswiki.h +++ /dev/null @@ -1,134 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsturtle.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_WIKI_GUI_INTERFACE_H -#define RETROSHARE_WIKI_GUI_INTERFACE_H - -#include -#include -#include - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" - -/* The Main Interface Class - for information about your Peers */ -class RsWiki; -extern RsWiki *rsWiki; - - -/* so the basic idea of Wiki is a set of Collections about subjects. - * - * Collection: RS - * - page: DHT - * - edit - * - edit - * - official revision. (new version of thread head). - * - * A collection will be moderated by it creator - important to prevent stupid changes. - * We need a way to swap out / replace / fork collections if moderator is rubbish. - * - * This should probably be done that the collection level. - * and enable all the references to be modified. - * - * Collection1 (RS DHT) - * : Turtle Link: Collection 0x54e4dafc34 - * - Page 1 - * - Page 2 - * - Link to Self:Page 1 - * - Link to Turtle:Page 1 - * - * - */ - -#define FLAG_MSG_TYPE_WIKI_SNAPSHOT 0x0001 -#define FLAG_MSG_TYPE_WIKI_COMMENT 0x0002 - -class CollectionRef -{ - public: - - std::string KeyWord; - std::string CollectionId; -}; - -struct RsWikiCollection: RsGxsGenericGroupData -{ - public: - std::string mDescription; - std::string mCategory; - - std::string mHashTags; - - // std::map linkReferences; -}; - -class RsWikiSnapshot -{ - public: - - RsMsgMetaData mMeta; - - std::string mPage; // all the text is stored here. - std::string mHashTags; -}; - - -class RsWikiComment -{ - public: - - RsMsgMetaData mMeta; - std::string mComment; -}; - -std::ostream &operator<<(std::ostream &out, const RsWikiCollection &group); -std::ostream &operator<<(std::ostream &out, const RsWikiSnapshot &shot); -std::ostream &operator<<(std::ostream &out, const RsWikiComment &comment); - - -class RsWiki: public RsGxsIfaceHelper -{ -public: - - RsWiki(RsGxsIface& gxs): RsGxsIfaceHelper(gxs) {} - virtual ~RsWiki() {} - - /* Specific Service Data */ -virtual bool getCollections(const uint32_t &token, std::vector &collections) = 0; -virtual bool getSnapshots(const uint32_t &token, std::vector &snapshots) = 0; -virtual bool getComments(const uint32_t &token, std::vector &comments) = 0; - -virtual bool getRelatedSnapshots(const uint32_t &token, std::vector &snapshots) = 0; - -virtual bool submitCollection(uint32_t &token, RsWikiCollection &collection) = 0; -virtual bool submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot) = 0; -virtual bool submitComment(uint32_t &token, RsWikiComment &comment) = 0; - -virtual bool updateCollection(uint32_t &token, RsWikiCollection &collection) = 0; - - // Blocking Interfaces. -virtual bool createCollection(RsWikiCollection &collection) = 0; -virtual bool updateCollection(const RsWikiCollection &collection) = 0; -virtual bool getCollections(const std::list groupIds, std::vector &groups) = 0; - -}; - -#endif diff --git a/libretroshare/src/retroshare/rswire.h b/libretroshare/src/retroshare/rswire.h deleted file mode 100644 index 34c953cee..000000000 --- a/libretroshare/src/retroshare/rswire.h +++ /dev/null @@ -1,250 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsturtle.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2020 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_WIRE_GUI_INTERFACE_H -#define RETROSHARE_WIRE_GUI_INTERFACE_H - -#include -#include -#include - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "retroshare/rsgxscommon.h" - - -/* The Main Interface Class - for information about your Peers */ -class RsWire; -extern RsWire *rsWire; - -class RsWireGroup; -typedef std::shared_ptr RsWireGroupSPtr; -typedef std::shared_ptr RsWireGroupConstSPtr; - -class RsWireGroup: public RsGxsGenericGroupData -{ - public: - RsWireGroup(); - - std::string mTagline; - std::string mLocation; - - // Images max size should be enforced. - RsGxsImage mHeadshot; // max size? - RsGxsImage mMasthead; // max size? - - // Unserialised stuff --------------------- - - // These are this groups top-level msgs. - uint32_t mGroupPulses; - uint32_t mGroupRepublishes; - uint32_t mGroupLikes; - uint32_t mGroupReplies; - // how do we handle these. TODO - // uint32_t mGroupFollowing; - // uint32_t mGroupFollowers; - - // These are this groups REF / RESPONSE msgs from others. - uint32_t mRefMentions; // TODO how to handle this? - uint32_t mRefRepublishes; - uint32_t mRefLikes; - uint32_t mRefReplies; -}; - - -/*********************************************************************** - * RsWire - is intended to be a Twitter clone - but fully decentralised. - * - * From Twitter: - * twitter can be: embedded, replied to, favourited, unfavourited, - * retweeted, unretweeted and deleted - * - * See: https://dev.twitter.com/docs/platform-objects - * - * Format of message: .... - * - * #HashTags. - * @68769381495134 => ID of Sender. - * - * - ***********************************************************************/ - - - -/************************************************************************ - * Pulse comes in three flavours. - * - * - * Original Msg Pulse - * - Spontaneous msg, on your own group. - * - mPulseType = WIRE_PULSE_TYPE_ORIGINAL_MSG - * - Ref fields are empty. - * - * Reply to a Pulse (i.e Retweet), has two parts. - * as we want the retweet to reference the original, and the original to know about reply. - * This info will be duplicated in two msgs - but allow data to spread easier. - * - * Reply Msg Pulse, will be Top-Level Msg on Publisher's Group. - * - mPulseMode = WIRE_PULSE_TYPE_RESPONSE | WIRE_PULSE_TYPE_REPLY - * - Ref fields refer to Parent (InReplyTo) Msg. - * - * Reply Reference, is Child Msg of Parent Msg, on Parent Publisher's Group. - * - mPulseMode = WIRE_PULSE_TYPE_REFERENCE | WIRE_PULSE_TYPE_REPLY - * - Ref fields refer to Reply Msg. - * - NB: This Msg requires Parent Msg for complete info, while other two are self-contained. - * - * Additionally need to sort out additional relationships. - * - Mentions. - * - Followers. - * - Following. - ***********************************************************************/ - -#define WIRE_PULSE_TYPE_ORIGINAL (0x0001) -#define WIRE_PULSE_TYPE_RESPONSE (0x0002) -#define WIRE_PULSE_TYPE_REFERENCE (0x0004) - -#define WIRE_PULSE_RESPONSE_MASK (0x0f00) -#define WIRE_PULSE_TYPE_REPLY (0x0100) -#define WIRE_PULSE_TYPE_REPUBLISH (0x0200) -#define WIRE_PULSE_TYPE_LIKE (0x0400) - -#define WIRE_PULSE_SENTIMENT_NO_SENTIMENT (0x0000) -#define WIRE_PULSE_SENTIMENT_POSITIVE (0x0001) -#define WIRE_PULSE_SENTIMENT_NEUTRAL (0x0002) -#define WIRE_PULSE_SENTIMENT_NEGATIVE (0x0003) - -class RsWirePulse; - -typedef std::shared_ptr RsWirePulseSPtr; -typedef std::shared_ptr RsWirePulseConstSPtr; - -class RsWirePulse -{ - public: - - RsMsgMetaData mMeta; - - // Store actual Pulse here. - std::string mPulseText; - - uint32_t mPulseType; - uint32_t mSentiment; // sentiment can be asserted at any point. - - // These Ref to the related (parent or reply) if reply (RESPONSE set) - // Mode RESPONSE REFERENCE - RsGxsGroupId mRefGroupId; // PARENT_GrpId REPLY_GrpId - std::string mRefGroupName; // PARENT_GrpName REPLY_GrpName - RsGxsMessageId mRefOrigMsgId; // PARENT_OrigMsgId REPLY_OrigMsgId - RsGxsId mRefAuthorId; // PARENT_AuthorId REPLY_AuthorId - rstime_t mRefPublishTs; // PARENT_PublishTs REPLY_PublishTs - std::string mRefPulseText; // PARENT_PulseText REPLY_PulseText - uint32_t mRefImageCount; // PARENT_#Images REPLY_#Images - - // Additional Fields for version 2. - // Images, need to enforce 20k limit? - RsGxsImage mImage1; - RsGxsImage mImage2; - RsGxsImage mImage3; - RsGxsImage mImage4; - - // Below Here is not serialised. - // They are additional fields linking pulses together or parsing elements of msg. - - // functions. - uint32_t ImageCount(); - - // can't have self referencial list, so need to use pointers. - // using SharedPointers to automatically cleanup. - - // Pointer to WireGroups - // mRefGroupPtr is opportunistically filled in, but will often be empty. - RsWireGroupSPtr mRefGroupPtr; // ORIG: N/A, RESP: Parent, REF: Reply Group - RsWireGroupSPtr mGroupPtr; // ORIG: Own, RESP: Own, REF: Parent Group - - // These are the direct children of this message - // split into likes, replies and retweets. - std::list mReplies; - std::list mLikes; - std::list mRepublishes; - - // parsed from msg. - // do we need references..? - std::list mHashTags; - std::list mMentions; - std::list mUrls; -}; - - -std::ostream &operator<<(std::ostream &out, const RsWireGroup &group); -std::ostream &operator<<(std::ostream &out, const RsWirePulse &pulse); - - -class RsWire: public RsGxsIfaceHelper -{ - public: - - explicit RsWire(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - virtual ~RsWire() {} - - /*! - * To acquire a handle to token service handler - * needed to make requests to the service - * @return handle to token service for this gxs service - */ - virtual RsTokenService* getTokenService() = 0; - - /* Specific Service Data */ -virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; -virtual bool getPulseData(const uint32_t &token, std::vector &pulses) = 0; - -virtual bool createGroup(uint32_t &token, RsWireGroup &group) = 0; -virtual bool createPulse(uint32_t &token, RsWirePulse &pulse) = 0; - - // Blocking Interfaces. -virtual bool createGroup(RsWireGroup &group) = 0; -virtual bool updateGroup(const RsWireGroup &group) = 0; -virtual bool getGroups(const std::list grpIds, - std::vector &groups) = 0; - - // New Blocking Interfaces. - // Plan to migrate all GUI calls to these, and remove old interfaces above. - // These are not single requests, but return data graphs for display. -virtual bool createOriginalPulse(const RsGxsGroupId &grpId, RsWirePulseSPtr pPulse) = 0; -virtual bool createReplyPulse(RsGxsGroupId grpId, RsGxsMessageId msgId, - RsGxsGroupId replyWith, uint32_t reply_type, - RsWirePulseSPtr pPulse) = 0; - - - // Provide Individual Group Details for display. -virtual bool getWireGroup(const RsGxsGroupId &groupId, RsWireGroupSPtr &grp) = 0; -virtual bool getWirePulse(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, RsWirePulseSPtr &pPulse) = 0; - - // Provide list of pulses associated with groups. -virtual bool getPulsesForGroups(const std::list &groupIds, - std::list &pulsePtrs) = 0; - - // Provide pulse, and associated replies / like etc. -virtual bool getPulseFocus(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, - int type, RsWirePulseSPtr &pPulse) = 0; - -}; - -#endif diff --git a/libretroshare/src/rs_upnp/UPnPBase.cpp b/libretroshare/src/rs_upnp/UPnPBase.cpp deleted file mode 100644 index 353812469..000000000 --- a/libretroshare/src/rs_upnp/UPnPBase.cpp +++ /dev/null @@ -1,1755 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: UPnPBase.cpp * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2004-2009 Marcelo Roberto Jimenez ( phoenix@amule.org ) * - * Copyright (c) 2006-2009 aMule Team ( admin@amule.org / http://www.amule.org)* - * Copyright (c) 2009-2010 Retroshare Team * - * Copyright (C) 2019-2020 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#define UPNP_C - -#include "UPnPBase.h" - -#include -#include -#include // for std::istringstream -#include // For transform() - -#include "util/rsstring.h" -#include "rs_upnp/upnp18_retrocompat.h" -#include "util/rstime.h" -#include "util/rsdebug.h" - -#ifdef __GNUC__ - #if __GNUC__ >= 4 - #define REINTERPRET_CAST(x) reinterpret_cast - #endif -#endif -#ifndef REINTERPRET_CAST - // Let's hope that function pointers are equal in size to data pointers - #define REINTERPRET_CAST(x) (x) -#endif - - -/** - * Case insensitive std::string comparison - */ -bool stdStringIsEqualCI(const std::string &s1, const std::string &s2) -{ - std::string ns1(s1); - std::string ns2(s2); - std::transform(ns1.begin(), ns1.end(), ns1.begin(), tolower); - std::transform(ns2.begin(), ns2.end(), ns2.begin(), tolower); - return ns1 == ns2; -} - - -CUPnPPortMapping::CUPnPPortMapping( - int ex_port, - int in_port, - const std::string &protocol, - bool enabled, - const std::string &description) -: -m_ex_port(), -m_in_port(), -m_protocol(protocol), -m_enabled(enabled ? "1" : "0"), -m_description(description), -m_key() -{ - rs_sprintf(m_ex_port, "%d", ex_port); - rs_sprintf(m_in_port, "%d", in_port); - m_key = m_protocol + m_ex_port; -} - - -const std::string &CUPnPLib::UPNP_ROOT_DEVICE = - "upnp:rootdevice"; - -const std::string &CUPnPLib::UPNP_DEVICE_IGW = - "urn:schemas-upnp-org:device:InternetGatewayDevice:1"; -const std::string &CUPnPLib::UPNP_DEVICE_WAN = - "urn:schemas-upnp-org:device:WANDevice:1"; -const std::string &CUPnPLib::UPNP_DEVICE_WAN_CONNECTION = - "urn:schemas-upnp-org:device:WANConnectionDevice:1"; -const std::string &CUPnPLib::UPNP_DEVICE_LAN = - "urn:schemas-upnp-org:device:LANDevice:1"; - -const std::string &CUPnPLib::UPNP_SERVICE_LAYER3_FORWARDING = - "urn:schemas-upnp-org:service:Layer3Forwarding:1"; -const std::string &CUPnPLib::UPNP_SERVICE_WAN_COMMON_INTERFACE_CONFIG = - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"; -const std::string &CUPnPLib::UPNP_SERVICE_WAN_IP_CONNECTION = - "urn:schemas-upnp-org:service:WANIPConnection:1"; -const std::string &CUPnPLib::UPNP_SERVICE_WAN_PPP_CONNECTION = - "urn:schemas-upnp-org:service:WANPPPConnection:1"; - - -CUPnPLib::CUPnPLib(CUPnPControlPoint &ctrlPoint) -: -m_ctrlPoint(ctrlPoint) -{ -} - - -std::string CUPnPLib::GetUPnPErrorMessage(int code) const -{ - return UpnpGetErrorMessage(code); -} - - -std::string CUPnPLib::processUPnPErrorMessage( - const std::string &message, - int errorCode, - const DOMString errorString, - const IXML_Document* doc) const -{ - /* remove unused parameter warnings */ - (void) message; - (void) errorCode; - (void) errorString; - (void) doc; - - std::string msg; -#ifdef UPNP_DEBUG - if (errorString == NULL || *errorString == 0) { - errorString = "Not available"; - } - if (errorCode > 0) { - std::cerr << "CUPnPLib::processUPnPErrorMessage() Error: " << - message << - ": Error code :'"; - if (doc) { - CUPnPError e(*this, doc); - std::cerr << e.getErrorCode() << - "', Error description :'" << - e.getErrorDescription() << - "'."; - } else { - std::cerr << errorCode << - "', Error description :'" << - errorString << - "'."; - } - std::cerr << std::endl; - } else { - std::cerr << "CUPnPLib::processUPnPErrorMessage() Error: " << - message << - ": UPnP SDK error: " << - GetUPnPErrorMessage(errorCode) << - " (" << errorCode << ")."; - std::cerr << std::endl; - } -#endif - return msg; -} - - -void CUPnPLib::ProcessActionResponse( - const IXML_Document* RespDoc, - const std::string &actionName) const -{ - /* remove unused parameter warnings */ - (void) actionName; - - IXML_Element *root = Element_GetRootElement(RespDoc); - IXML_Element *child = Element_GetFirstChild(root); - if (child) { - while (child) { - const DOMString childTag = Element_GetTag(child); - std::string childValue = Element_GetTextValue(child); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPLib::ProcessActionResponse() \n " << - childTag << "='" << - childValue << "'"; -#endif - //add the variable to the wanservice property map - (m_ctrlPoint.m_WanService->propertyMap)[std::string(childTag)] = std::string(childValue); - child = Element_GetNextSibling(child); - } - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPLib::ProcessActionResponse() \n Empty response for action '" << - actionName << "'."; -#endif - } -#ifdef UPNP_DEBUG - std::cerr << std::endl; -#endif -} - - -/*! - * \brief Returns the root node of a given document. - */ -IXML_Element *CUPnPLib::Element_GetRootElement( - const IXML_Document* doc) const -{ - IXML_Element* root = REINTERPRET_CAST(IXML_Element *)( - ixmlNode_getFirstChild( - REINTERPRET_CAST(IXML_Node *)(const_cast(doc)))); - - return root; -} - - -/*! - * \brief Returns the first child of a given element. - */ -IXML_Element *CUPnPLib::Element_GetFirstChild( - IXML_Element *parent) const -{ - IXML_Node *node = REINTERPRET_CAST(IXML_Node *)(parent); - IXML_Node *child = ixmlNode_getFirstChild(node); - - return REINTERPRET_CAST(IXML_Element *)(child); -} - - -/*! - * \brief Returns the next sibling of a given child. - */ -IXML_Element *CUPnPLib::Element_GetNextSibling( - IXML_Element *child) const -{ - IXML_Node *node = REINTERPRET_CAST(IXML_Node *)(child); - IXML_Node *sibling = ixmlNode_getNextSibling(node); - - return REINTERPRET_CAST(IXML_Element *)(sibling); -} - - -/*! - * \brief Returns the element tag (name) - */ -const DOMString CUPnPLib::Element_GetTag( - IXML_Element *element) const -{ - IXML_Node *node = REINTERPRET_CAST(IXML_Node *)(element); - const DOMString tag = ixmlNode_getNodeName(node); - - return tag; -} - - -/*! - * \brief Returns the TEXT node value of the current node. - */ -const std::string CUPnPLib::Element_GetTextValue( - IXML_Element *element) const -{ - if (!element) { - return stdEmptyString; - } - IXML_Node *text = ixmlNode_getFirstChild( - REINTERPRET_CAST(IXML_Node *)(element)); - const DOMString s = ixmlNode_getNodeValue(text); - std::string ret; - if (s) { - ret = s; - } - - return ret; -} - - -/*! - * \brief Returns the TEXT node value of the first child matching tag. - */ -const std::string CUPnPLib::Element_GetChildValueByTag( - IXML_Element *element, - const DOMString tag) const -{ - IXML_Element *child = - Element_GetFirstChildByTag(element, tag); - - return Element_GetTextValue(child); -} - - -/*! - * \brief Returns the first child element that matches the requested tag or - * NULL if not found. - */ -IXML_Element *CUPnPLib::Element_GetFirstChildByTag( - IXML_Element *element, - const DOMString tag) const -{ - if (!element || !tag) { - return NULL; - } - - IXML_Node *node = REINTERPRET_CAST(IXML_Node *)(element); - IXML_Node *child = ixmlNode_getFirstChild(node); - const DOMString childTag = ixmlNode_getNodeName(child); - while(child && childTag && strcmp(tag, childTag)) { - child = ixmlNode_getNextSibling(child); - childTag = ixmlNode_getNodeName(child); - } - - return REINTERPRET_CAST(IXML_Element *)(child); -} - - -/*! - * \brief Returns the next sibling element that matches the requested tag. Should be - * used with the return value of Element_GetFirstChildByTag(). - */ -IXML_Element *CUPnPLib::Element_GetNextSiblingByTag( - IXML_Element *element, const DOMString tag) const -{ - if (!element || !tag) { - return NULL; - } - - IXML_Node *child = REINTERPRET_CAST(IXML_Node *)(element); - const DOMString childTag = NULL; - do { - child = ixmlNode_getNextSibling(child); - childTag = ixmlNode_getNodeName(child); - } while(child && childTag && strcmp(tag, childTag)); - - return REINTERPRET_CAST(IXML_Element *)(child); -} - - -const std::string CUPnPLib::Element_GetAttributeByTag( - IXML_Element *element, const DOMString tag) const -{ - IXML_NamedNodeMap *NamedNodeMap = ixmlNode_getAttributes( - REINTERPRET_CAST(IXML_Node *)(element)); - IXML_Node *attribute = ixmlNamedNodeMap_getNamedItem(NamedNodeMap, tag); - const DOMString s = ixmlNode_getNodeValue(attribute); - std::string ret; - if (s) { - ret = s; - } - ixmlNamedNodeMap_free(NamedNodeMap); - - return ret; -} - - -CUPnPError::CUPnPError( - const CUPnPLib &upnpLib, - const IXML_Document *errorDoc) - : - m_root (upnpLib.Element_GetRootElement(errorDoc)), - m_ErrorCode (upnpLib.Element_GetChildValueByTag(m_root, "errorCode")), - m_ErrorDescription(upnpLib.Element_GetChildValueByTag(m_root, "errorDescription")) -{ -} - - -CUPnPArgument::CUPnPArgument( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *argument, - const std::string &/*SCPDURL*/) -: -m_UPnPControlPoint(upnpControlPoint), -m_name (upnpLib.Element_GetChildValueByTag(argument, "name")), -m_direction (upnpLib.Element_GetChildValueByTag(argument, "direction")), -m_retval (upnpLib.Element_GetFirstChildByTag(argument, "retval")), -m_relatedStateVariable(upnpLib.Element_GetChildValueByTag(argument, "relatedStateVariable")) -{ - -#ifdef UPNP_DEBUG - std::cerr << "CUPnPArgument::CUPnPArgument() \n Argument:" << - "\n name: " << m_name << - "\n direction: " << m_direction << - "\n retval: " << m_retval << - "\n relatedStateVariable: " << m_relatedStateVariable; - std::cerr << std::endl; -#endif -} - - -CUPnPAction::CUPnPAction( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *action, - const std::string &SCPDURL) -: -m_UPnPControlPoint(upnpControlPoint), -m_ArgumentList(upnpControlPoint, upnpLib, action, SCPDURL), -m_name(upnpLib.Element_GetChildValueByTag(action, "name")) -{ -#ifdef UPNP_DEBUG - std::cerr << "CUPnPAction::CUPnPAction() \n Action:" << - "\n name: " << m_name; - std::cerr << std::endl; -#endif -} - - -CUPnPAllowedValue::CUPnPAllowedValue( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *allowedValue, - const std::string &/*SCPDURL*/) -: -m_UPnPControlPoint(upnpControlPoint), -m_allowedValue(upnpLib.Element_GetTextValue(allowedValue)) -{ -#ifdef UPNP_DEBUG - std::cerr << "CUPnPAllowedValue::CUPnPAllowedValue() \n AllowedValue:" << - "\n allowedValue: " << m_allowedValue; - std::cerr << std::endl; -#endif -} - - -CUPnPStateVariable::CUPnPStateVariable( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *stateVariable, - const std::string &SCPDURL) -: -m_UPnPControlPoint(upnpControlPoint), -m_AllowedValueList(upnpControlPoint, upnpLib, stateVariable, SCPDURL), -m_name (upnpLib.Element_GetChildValueByTag(stateVariable, "name")), -m_dataType (upnpLib.Element_GetChildValueByTag(stateVariable, "dataType")), -m_defaultValue(upnpLib.Element_GetChildValueByTag(stateVariable, "defaultValue")), -m_sendEvents (upnpLib.Element_GetAttributeByTag (stateVariable, "sendEvents")) -{ -#ifdef UPNP_DEBUG - std::cerr << "CUPnPStateVariable::CUPnPStateVariable() \n StateVariable:" << - "\n name: " << m_name << - "\n dataType: " << m_dataType << - "\n defaultValue: " << m_defaultValue << - "\n sendEvents: " << m_sendEvents; - std::cerr << std::endl; -#endif -} - - -CUPnPSCPD::CUPnPSCPD( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *scpd, - const std::string &SCPDURL) -: -m_UPnPControlPoint(upnpControlPoint), -m_ActionList(upnpControlPoint, upnpLib, scpd, SCPDURL), -m_ServiceStateTable(upnpControlPoint, upnpLib, scpd, SCPDURL), -m_SCPDURL(SCPDURL) -{ -} - - -CUPnPArgumentValue::CUPnPArgumentValue() -: -m_argument(), -m_value() -{ -} - - -CUPnPArgumentValue::CUPnPArgumentValue( - const std::string &argument, const std::string &value) -: -m_argument(argument), -m_value(value) -{ -} - - -CUPnPService::CUPnPService( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *service, - const std::string &URLBase) -: -m_UPnPControlPoint(upnpControlPoint), -m_upnpLib(upnpLib), -m_serviceType(upnpLib.Element_GetChildValueByTag(service, "serviceType")), -m_serviceId (upnpLib.Element_GetChildValueByTag(service, "serviceId")), -m_SCPDURL (upnpLib.Element_GetChildValueByTag(service, "SCPDURL")), -m_controlURL (upnpLib.Element_GetChildValueByTag(service, "controlURL")), -m_eventSubURL(upnpLib.Element_GetChildValueByTag(service, "eventSubURL")), -m_timeout(1801), -m_SCPD(NULL) -{ - int errcode; - m_SID[0]=0; - - std::vector vscpdURL(URLBase.length() + m_SCPDURL.length() + 1); - char *scpdURL = &vscpdURL[0]; - errcode = UpnpResolveURL( - URLBase.c_str(), - m_SCPDURL.c_str(), - scpdURL); - if( errcode != UPNP_E_SUCCESS ) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::CUPnPService() Error generating scpdURL from " << - "|" << URLBase << "|" << - m_SCPDURL << "|."; - std::cerr << std::endl; -#endif - } else { - m_absSCPDURL = scpdURL; - } - - std::vector vcontrolURL( - URLBase.length() + m_controlURL.length() + 1); - char *controlURL = &vcontrolURL[0]; - errcode = UpnpResolveURL( - URLBase.c_str(), - m_controlURL.c_str(), - controlURL); - if( errcode != UPNP_E_SUCCESS ) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::CUPnPService() Error generating controlURL from " << - "|" << URLBase << "|" << - m_controlURL << "|."; - std::cerr << std::endl; -#endif - } else { - m_absControlURL = controlURL; - } - - std::vector veventURL( - URLBase.length() + m_eventSubURL.length() + 1); - char *eventURL = &veventURL[0]; - errcode = UpnpResolveURL( - URLBase.c_str(), - m_eventSubURL.c_str(), - eventURL); - if( errcode != UPNP_E_SUCCESS ) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::CUPnPService() Error generating eventURL from " << - "|" << URLBase << "|" << - m_eventSubURL << "|."; - std::cerr << std::endl; -#endif - } else { - m_absEventSubURL = eventURL; - } - -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::CUPnPService() \n Service:" << - "\n serviceType: " << m_serviceType << - "\n serviceId: " << m_serviceId << - "\n SCPDURL: " << m_SCPDURL << - "\n absSCPDURL: " << m_absSCPDURL << - "\n controlURL: " << m_controlURL << - "\n absControlURL: " << m_absControlURL << - "\n eventSubURL: " << m_eventSubURL << - "\n absEventSubURL: " << m_absEventSubURL; - std::cerr << std::endl; -#endif - - if (m_serviceType == upnpLib.UPNP_SERVICE_WAN_IP_CONNECTION || - m_serviceType == upnpLib.UPNP_SERVICE_WAN_PPP_CONNECTION) { -#if 0 - m_serviceType == upnpLib.UPNP_SERVICE_WAN_PPP_CONNECTION || - m_serviceType == upnpLib.UPNP_SERVICE_WAN_COMMON_INTERFACE_CONFIG || - m_serviceType == upnpLib.UPNP_SERVICE_LAYER3_FORWARDING) { -#endif -#if 0 -//#warning Delete this code on release. - if (!upnpLib.m_ctrlPoint.WanServiceDetected()) { - // This condition can be used to suspend the parse - // of the XML tree. -#endif -//#warning Delete this code when m_WanService is no longer used. - upnpLib.m_ctrlPoint.SetWanService(this); - // Log it -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::CUPnPService() WAN Service Detected: '" << - m_serviceType << "'."; - std::cerr << std::endl; -#endif - // Subscribe - upnpLib.m_ctrlPoint.Subscribe(*this); -#if 0 -//#warning Delete this code on release. - } else { -#ifdef UPNP_DEBUG - std::cerr << "WAN service detected again: '" << - m_serviceType << - "'. Will only use the first instance."; - std::cerr << std::endl; -#endif - } -#endif - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::CUPnPService() Uninteresting service detected: '" << - m_serviceType << "'. Ignoring."; - std::cerr << std::endl; -#endif - } -} - - -CUPnPService::~CUPnPService() -{ -} - - -bool CUPnPService::Execute( - const std::string &ActionName, - const std::vector &ArgValue) const -{ -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() called." << std::endl; -#endif - if (m_SCPD.get() == NULL) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Service without SCPD Document, cannot execute action '" << ActionName << - "' for service '" << GetServiceType() << "'."; - std::cerr << std::endl; -#endif - return false; - } -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Sending action " << std::endl; -#endif - // Check for correct action name - ActionList::const_iterator itAction = - m_SCPD->GetActionList().find(ActionName); - if (itAction == m_SCPD->GetActionList().end()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() invalid action name '" << ActionName << - "' for service '" << GetServiceType() << "'."; - std::cerr << std::endl; -#endif - return false; - } -#ifdef UPNP_DEBUG - std::cerr << ActionName << "("; -#endif - bool firstTime = true; - // Check for correct Argument/Value pairs - const CUPnPAction &action = *(itAction->second); - for (unsigned int i = 0; i < ArgValue.size(); ++i) { - ArgumentList::const_iterator itArg = - action.GetArgumentList().find(ArgValue[i].GetArgument()); - if (itArg == action.GetArgumentList().end()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Invalid argument name '" << ArgValue[i].GetArgument() << - "' for action '" << action.GetName() << - "' for service '" << GetServiceType() << "'."; - std::cerr << std::endl; -#endif - return false; - } - const CUPnPArgument &argument = *(itArg->second); - if (tolower(argument.GetDirection()[0]) != 'i' || - tolower(argument.GetDirection()[1]) != 'n') { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Invalid direction for argument '" << - ArgValue[i].GetArgument() << - "' for action '" << action.GetName() << - "' for service '" << GetServiceType() << "'."; - std::cerr << std::endl; -#endif - return false; - } - const std::string relatedStateVariableName = - argument.GetRelatedStateVariable(); - if (!relatedStateVariableName.empty()) { - ServiceStateTable::const_iterator itSVT = - m_SCPD->GetServiceStateTable(). - find(relatedStateVariableName); - if (itSVT == m_SCPD->GetServiceStateTable().end()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Inconsistent Service State Table, did not find '" << - relatedStateVariableName << - "' for argument '" << argument.GetName() << - "' for action '" << action.GetName() << - "' for service '" << GetServiceType() << "'."; - std::cerr << std::endl; -#endif - return false; - } - const CUPnPStateVariable &stateVariable = *(itSVT->second); - if ( !stateVariable.GetAllowedValueList().empty() && - stateVariable.GetAllowedValueList().find(ArgValue[i].GetValue()) == - stateVariable.GetAllowedValueList().end()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Value not allowed '" << ArgValue[i].GetValue() << - "' for state variable '" << relatedStateVariableName << - "' for argument '" << argument.GetName() << - "' for action '" << action.GetName() << - "' for service '" << GetServiceType() << "'."; -#endif - - return false; - } - } - if (firstTime) { - firstTime = false; - } else { -#ifdef UPNP_DEBUG - std::cerr << ", "; -#endif - } -#ifdef UPNP_DEBUG - std::cerr << - ArgValue[i].GetArgument() << - "='" << - ArgValue[i].GetValue() << - "'"; -#endif - } -#ifdef UPNP_DEBUG - std::cerr << ")" << std::endl; -#endif - // Everything is ok, make the action - IXML_Document *ActionDoc = NULL; - if (ArgValue.size()) { - for (unsigned int i = 0; i < ArgValue.size(); ++i) { - int ret = UpnpAddToAction( - &ActionDoc, - action.GetName().c_str(), - GetServiceType().c_str(), - ArgValue[i].GetArgument().c_str(), - ArgValue[i].GetValue().c_str()); - if (ret != UPNP_E_SUCCESS) { - m_upnpLib.processUPnPErrorMessage( - "UpnpAddToAction", ret, NULL, NULL); - return false; - } - } - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() UpnpMakeAction" << std::endl; -#endif - ActionDoc = UpnpMakeAction( - action.GetName().c_str(), - GetServiceType().c_str(), - 0, NULL); - if (!ActionDoc) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Error: UpnpMakeAction returned NULL." << std::endl; -#endif - return false; - } - } - - // Send the action asynchronously - UpnpSendActionAsync( - m_UPnPControlPoint.GetUPnPClientHandle(), - GetAbsControlURL().c_str(), - GetServiceType().c_str(), - NULL, ActionDoc, - reinterpret_cast(&CUPnPControlPoint::Callback), - NULL); - return true; -} - - -const std::string CUPnPService::GetStateVariable( - const std::string &stateVariableName) -{ - std::map::iterator it; - it = propertyMap.find(stateVariableName); - if (it != propertyMap.end()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::GetStateVariable(" << stateVariableName << ") = " << (*it).second << std::endl; -#endif - return (*it).second; - } else { - //property map is not populated with the specified value. - //we will try to get it with an event - - //this getvar is just to make the event happening - DOMString StVarVal; - UpnpGetServiceVarStatus( - m_UPnPControlPoint.GetUPnPClientHandle(), - GetAbsControlURL().c_str(), - stateVariableName.c_str(), - &StVarVal); - if (StVarVal != NULL) { - std::string varValue = std::string(StVarVal); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::GetStateVariable() varValue returned by UpnpGetServiceVarStatus : " << varValue << std::endl; -#endif - return varValue; - } else { - //use event to get state variable -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::GetStateVariable() pausing in case of an UPnP event incomming."; -#endif - rstime_t begin_time = time(NULL); - while (true) { - if (time(NULL) - begin_time > 7) { - break; - } - } - } - - //propertyMap should be populated by nom - it = propertyMap.find(stateVariableName); - if (it != propertyMap.end()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::GetStateVariable(" << stateVariableName << ") = " << (*it).second << std::endl; -#endif - return (*it).second; - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::GetStateVariable(" << stateVariableName << ") = " << "Empty String" << std::endl; -#endif - return stdEmptyString; - } - } -} - - -CUPnPDevice::CUPnPDevice( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *device, - const std::string &URLBase) -: -m_UPnPControlPoint(upnpControlPoint), -m_DeviceList(upnpControlPoint, upnpLib, device, URLBase), -m_ServiceList(upnpControlPoint, upnpLib, device, URLBase), -m_deviceType (upnpLib.Element_GetChildValueByTag(device, "deviceType")), -m_friendlyName (upnpLib.Element_GetChildValueByTag(device, "friendlyName")), -m_manufacturer (upnpLib.Element_GetChildValueByTag(device, "manufacturer")), -m_manufacturerURL (upnpLib.Element_GetChildValueByTag(device, "manufacturerURL")), -m_modelDescription (upnpLib.Element_GetChildValueByTag(device, "modelDescription")), -m_modelName (upnpLib.Element_GetChildValueByTag(device, "modelName")), -m_modelNumber (upnpLib.Element_GetChildValueByTag(device, "modelNumber")), -m_modelURL (upnpLib.Element_GetChildValueByTag(device, "modelURL")), -m_serialNumber (upnpLib.Element_GetChildValueByTag(device, "serialNumber")), -m_UDN (upnpLib.Element_GetChildValueByTag(device, "UDN")), -m_UPC (upnpLib.Element_GetChildValueByTag(device, "UPC")), -m_presentationURL (upnpLib.Element_GetChildValueByTag(device, "presentationURL")) -{ - int presURLlen = strlen(URLBase.c_str()) + - strlen(m_presentationURL.c_str()) + 2; - std::vector vpresURL(presURLlen); - char* presURL = &vpresURL[0]; - int errcode = UpnpResolveURL( - URLBase.c_str(), - m_presentationURL.c_str(), - presURL); - if (errcode != UPNP_E_SUCCESS) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPDevice::CUPnPDevice() Error generating presentationURL from " << - "|" << URLBase << "|" << - m_presentationURL << "|."; - std::cerr << std::endl; -#endif - } else { - m_presentationURL = presURL; - } - -#ifdef UPNP_DEBUG - std::cerr << "CUPnPDevice::CUPnPDevice() \n Device: " << - "\n friendlyName: " << m_friendlyName << - "\n deviceType: " << m_deviceType << - "\n manufacturer: " << m_manufacturer << - "\n manufacturerURL: " << m_manufacturerURL << - "\n modelDescription: " << m_modelDescription << - "\n modelName: " << m_modelName << - "\n modelNumber: " << m_modelNumber << - "\n modelURL: " << m_modelURL << - "\n serialNumber: " << m_serialNumber << - "\n UDN: " << m_UDN << - "\n UPC: " << m_UPC << - "\n presentationURL: " << m_presentationURL - << std::endl; -#endif -} - - -CUPnPRootDevice::CUPnPRootDevice( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *rootDevice, - const std::string &OriginalURLBase, - const std::string &FixedURLBase, - const char *location, - int expires) -: -CUPnPDevice(upnpControlPoint, upnpLib, rootDevice, FixedURLBase), -m_UPnPControlPoint(upnpControlPoint), -m_URLBase(OriginalURLBase), -m_location(location), -m_expires(expires) -{ -#ifdef UPNP_DEBUG - std::cerr << - "CUPnPRootDevice::CUPnPRootDevice() \n Root Device: " << - "\n URLBase: " << m_URLBase << - "\n Fixed URLBase: " << FixedURLBase << - "\n location: " << m_location << - "\n expires: " << m_expires - << std::endl; -#endif -} - - -CUPnPControlPoint *CUPnPControlPoint::s_CtrlPoint = NULL; - - -CUPnPControlPoint::CUPnPControlPoint(unsigned short udpPort) -: -m_upnpLib(*this), -m_UPnPClientHandle(), -m_RootDeviceMap(), -m_ServiceMap(), -m_ActivePortMappingsMap(), -m_RootDeviceListMutex("UPnPControlPoint-RootDeviceList"), -m_IGWDeviceDetected(false), -m_WaitForSearchTimeoutMutex("UPnPControlPoint-WaitForSearchTimeout"), -m_WanService(NULL) -{ -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() Constructor" << std::endl; -#endif - // Pointer to self - s_CtrlPoint = this; - -#ifdef UPNP_DEBUG - int resLog = UpnpInitLog(); - std::cerr << "UPnPControlPoint::CUPnPControlPoint() Init log : " << resLog << std::endl; -#endif - -#if UPNP_VERSION < 11400 - int ret = UpnpInit(nullptr, udpPort); -#else - int ret = UpnpInit2(nullptr, udpPort); -#endif - -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint Constructor UpnpInit finished" << std::endl; -#endif - if (ret != UPNP_E_SUCCESS && ret !=UPNP_E_INIT) { -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() error(UpnpInit): Error code : "; -#endif - goto error; - } - - RS_INFO("bound to ", UpnpGetServerIpAddress(), ":", UpnpGetServerPort()); - - ret = UpnpRegisterClient( - reinterpret_cast(&CUPnPControlPoint::Callback), - &m_UPnPClientHandle, - &m_UPnPClientHandle); - if (ret != UPNP_E_SUCCESS) { -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() error(UpnpRegisterClient): Error registering callback: "; -#endif - goto error; - } - - // We could ask for just the right device here. If the root device - // contains the device we want, it will respond with the full XML doc, - // including the root device and every sub-device it has. - // - // But lets find out what we have in our network by calling UPNP_ROOT_DEVICE. - // - // We should not search twice, because this will produce two - // UPNP_DISCOVERY_SEARCH_TIMEOUT events, and we might end with problems - // on the mutex. -// UpnpSetContentLength(m_UPnPClientHandle, 5000000); -// UpnpSetMaxContentLength(5000000); - ret = UpnpSearchAsync(m_UPnPClientHandle, 20, m_upnpLib.UPNP_DEVICE_IGW.c_str(), NULL); - //ret = UpnpSearchAsync(m_UPnPClientHandle, 3, m_upnpLib.UPNP_DEVICE_IGW.c_str(), this); - //ret = UpnpSearchAsync(m_UPnPClientHandle, 3, m_upnpLib.UPNP_DEVICE_LAN.c_str(), this); - //ret = UpnpSearchAsync(m_UPnPClientHandle, 3, m_upnpLib.UPNP_DEVICE_WAN_CONNECTION.c_str(), this); - if (ret != UPNP_E_SUCCESS) { -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() error(UpnpSearchAsync): Error sending search request: "; -#endif - goto error; - } - - // Wait for the UPnP initialization to complete. - { - // Lock the search timeout mutex - m_WaitForSearchTimeoutMutex.lock(); - - // Lock it again, so that we block. Unlocking will only happen - // when the UPNP_DISCOVERY_SEARCH_TIMEOUT event occurs at the - // callback. -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() blocking m_WaitForSearchTimeoutMutex." << std::endl; -#endif - //RsMutex toto(m_WaitForSearchTimeoutMutex); - m_WaitForSearchTimeoutMutex.lock(); -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() m_WaitForSearchTimeoutMutex blocking finished." << std::endl; -#endif - } - - //clean the PortMappingNumberOfEntries as it is erroneus on the first event with the french neufbox - if (WanServiceDetected()) { - m_WanService->propertyMap.erase("PortMappingNumberOfEntries"); - } - -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() CUPnPControlPoint Constructor finished" << std::endl; -#endif - return; - - // Error processing -error: -#ifdef UPNP_DEBUG - std::cerr << ret << ": " << m_upnpLib.GetUPnPErrorMessage(ret) << "." << std::endl; -#endif - UpnpFinish(); -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() UpnpFinish called within CUPnPControlPoint constructor." << std::endl; -#endif -} - - -char* CUPnPControlPoint::getInternalIpAddress() -{ - char * addr = UpnpGetServerIpAddress(); - if (addr == NULL) { - addr = new char[10] ; - sprintf(addr,"%s","127.0.0.1"); - } - return addr; -} - -CUPnPControlPoint::~CUPnPControlPoint() -{ - for( RootDeviceMap::iterator it = m_RootDeviceMap.begin(); - it != m_RootDeviceMap.end(); - ++it) { - delete it->second; - } - // Remove all first - // RemoveAll(); - UpnpUnRegisterClient(m_UPnPClientHandle); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::~CUPnPControlPoint() UpnpFinish called within CUPnPControlPoint destructor." << std::endl; -#endif - UpnpFinish(); -} - - -bool CUPnPControlPoint::AddPortMappings( - std::vector &upnpPortMapping) -{ - if (!WanServiceDetected()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::AddPortMappings() UPnP Error: " - "CUPnPControlPoint::AddPortMapping: " - "WAN Service not detected." << std::endl; -#endif - return false; - } -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::AddPortMappings() called." << std::endl; -#endif - - int n = upnpPortMapping.size(); - bool ok = false; - - // Check the number of port mappings before - //have a little break in case we just modified the variable, so we have to wait for an event -// std::cerr << "GetStateVariable pausing in case of an UPnP event incomming."; -// rstime_t begin_time = time(NULL); -// while (true) { -// if (time(NULL) - begin_time > 7) { -// break; -// } -// } - std::istringstream OldPortMappingNumberOfEntries( - m_WanService->GetStateVariable( - "PortMappingNumberOfEntries")); - int oldNumberOfEntries; - OldPortMappingNumberOfEntries >> oldNumberOfEntries; - - // Add the enabled port mappings - for (int i = 0; i < n; ++i) { - if (upnpPortMapping[i].getEnabled() == "1") { - // Add the mapping to the control point - // active mappings list - m_ActivePortMappingsMap[upnpPortMapping[i].getKey()] = - upnpPortMapping[i]; - - // Add the port mapping - PrivateAddPortMapping(upnpPortMapping[i]); - } - } - - // Not very good, must find a better test : check the new number of port entries - //have a little break in case we just modified the variable, so we have to wait for an event -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::AddPortMappings() GetStateVariable pausing in case of an UPnP event incomming."; -#endif - rstime_t begin_time = time(NULL); - while (true) { - if (time(NULL) - begin_time > 4) { - break; - } - } - std::istringstream NewPortMappingNumberOfEntries( - m_WanService->GetStateVariable( - "PortMappingNumberOfEntries")); - int newNumberOfEntries; - NewPortMappingNumberOfEntries >> newNumberOfEntries; -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::AddPortMappings() CUPnPControlPoint::AddPortMappings() newNumberOfEntries - oldNumberOfEntries : " << (newNumberOfEntries - oldNumberOfEntries) << std::endl; -#endif - ok = newNumberOfEntries - oldNumberOfEntries >= 1; - -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::AddPortMappings() finished. Success = " << ok << std::endl; -#endif - - return ok; -} - -std::string CUPnPControlPoint::getExternalAddress() -{ - if (!WanServiceDetected()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::getExternalAddress() UPnP Error: " - "CUPnPControlPoint::AddPortMapping: " - "WAN Service not detected." << std::endl; -#endif - return ""; - } - std::string result = m_WanService->GetStateVariable("NewExternalIPAddress"); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::getExternalAddress() m_WanService->GetStateVariable(NewExternalIPAddress) = " << result << std::endl; -#endif - if (result == "") { - PrivateGetExternalIpAdress(); - result = m_WanService->GetStateVariable("NewExternalIPAddress"); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::getExternalAddress() m_WanService->GetStateVariable(NewExternalIPAddress) = " << result << std::endl; -#endif - if (result == "") { - result = m_WanService->GetStateVariable("ExternalIPAddress"); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::getExternalAddress() m_WanService->GetStateVariable(ExternalIPAddress) = " << result << std::endl; -#endif - } - } - return result; -} - -void CUPnPControlPoint::RefreshPortMappings() -{ - for ( PortMappingMap::iterator it = m_ActivePortMappingsMap.begin(); - it != m_ActivePortMappingsMap.end(); - ++it) { - PrivateAddPortMapping(it->second); - } -} - - -bool CUPnPControlPoint::PrivateAddPortMapping( - CUPnPPortMapping &upnpPortMapping) -{ - // Get an IP address. The UPnP server one must do. - std::string ipAddress(UpnpGetServerIpAddress()); - - // Start building the action - std::string actionName("AddPortMapping"); - std::vector argval(8); - - // Action parameters - argval[0].SetArgument("NewRemoteHost"); - argval[0].SetValue(""); - argval[1].SetArgument("NewExternalPort"); - argval[1].SetValue(upnpPortMapping.getExPort()); - argval[2].SetArgument("NewProtocol"); - argval[2].SetValue(upnpPortMapping.getProtocol()); - argval[3].SetArgument("NewInternalPort"); - argval[3].SetValue(upnpPortMapping.getInPort()); - argval[4].SetArgument("NewInternalClient"); - argval[4].SetValue(ipAddress); - argval[5].SetArgument("NewEnabled"); - argval[5].SetValue("1"); - argval[6].SetArgument("NewPortMappingDescription"); - argval[6].SetValue(upnpPortMapping.getDescription()); - argval[7].SetArgument("NewLeaseDuration"); - argval[7].SetValue("0"); - - // Execute - bool ret = true; - for (ServiceMap::iterator it = m_ServiceMap.begin(); - it != m_ServiceMap.end(); ++it) { - ret &= it->second->Execute(actionName, argval); - } - - return ret; -} - - -bool CUPnPControlPoint::DeletePortMappings( - std::vector &upnpPortMapping) -{ -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::DeletePortMappings() called." << std::endl; -#endif - if (!WanServiceDetected()) { -#ifdef UPNP_DEBUG - std::cerr << "UPnP Error: " - "CUPnPControlPoint::DeletePortMapping: " - "WAN Service not detected." << std::endl; -#endif - return false; - } - - int n = upnpPortMapping.size(); - - // Delete the enabled port mappings - for (int i = 0; i < n; ++i) { - if (upnpPortMapping[i].getEnabled() == "1") { - // Delete the mapping from the control point - // active mappings list - PortMappingMap::iterator it = - m_ActivePortMappingsMap.find( - upnpPortMapping[i].getKey()); - if (it != m_ActivePortMappingsMap.end()) { - m_ActivePortMappingsMap.erase(it); - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::DeletePortMappings() UPnP Error: " - "CUPnPControlPoint::DeletePortMapping: " - "Mapping was not found in the active " - "mapping map." << std::endl; -#endif - } - - // Delete the port mapping - PrivateDeletePortMapping(upnpPortMapping[i]); - } - } - - return true; -} - - -bool CUPnPControlPoint::PrivateDeletePortMapping( - CUPnPPortMapping &upnpPortMapping) -{ - // Start building the action - std::string actionName("DeletePortMapping"); - std::vector argval(3); - - // Action parameters - argval[0].SetArgument("NewRemoteHost"); - argval[0].SetValue(""); - argval[1].SetArgument("NewExternalPort"); - argval[1].SetValue(upnpPortMapping.getExPort()); - argval[2].SetArgument("NewProtocol"); - argval[2].SetValue(upnpPortMapping.getProtocol()); - - // Execute - bool ret = true; - for (ServiceMap::iterator it = m_ServiceMap.begin(); - it != m_ServiceMap.end(); ++it) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::PrivateDeletePortMapping() Sending a delete port mapping action." << std::endl; -#endif - ret &= it->second->Execute(actionName, argval); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::PrivateDeletePortMapping() Delete port mapping action finished." << std::endl; -#endif - } - - return ret; -} - -bool CUPnPControlPoint::PrivateGetExternalIpAdress() -{ - // Start building the action - std::string actionName("GetExternalIPAddress"); - std::vector argval(0); - - // Execute - bool ret = true; - for (ServiceMap::iterator it = m_ServiceMap.begin(); - it != m_ServiceMap.end(); ++it) { - ret &= it->second->Execute(actionName, argval); - } - - return ret; -} - - -// This function is static -int CUPnPControlPoint::Callback( - Upnp_EventType EventType, const void* Event, void * /*Cookie*/ ) -{ - if(!Event) return 0; - - std::string msg; - std::string msg2; - - CUPnPControlPoint* upnpCP = CUPnPControlPoint::s_CtrlPoint; - if (!upnpCP) return 0; - - switch (EventType) - { - case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE: /*fallthrough*/ - case UPNP_DISCOVERY_SEARCH_RESULT: - { - const UpnpDiscovery* d_event = static_cast(Event); - - // Get the XML tree device description in doc - IXML_Document* doc = nullptr; - UpnpDownloadXmlDoc(UpnpDiscovery_get_Location_cstr(d_event), &doc); - if (!doc) break; - - IXML_Element* root = upnpCP->m_upnpLib.Element_GetRootElement(doc); - - // Extract the URLBase - const std::string urlBase = upnpCP->m_upnpLib. - Element_GetChildValueByTag(root, "URLBase"); - // Get the root device - IXML_Element *rootDevice = upnpCP->m_upnpLib. - Element_GetFirstChildByTag(root, "device"); - // Extract the deviceType - std::string devType(upnpCP->m_upnpLib. - 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 - if (stdStringIsEqualCI(devType, upnpCP->m_upnpLib.UPNP_DEVICE_IGW)) - { - // This condition can be used to auto-detect - // the UPnP device we are interested in. - // Obs.: Don't block the entry here on this - // condition! There may be more than one device, - // and the first that enters may not be the one - // we are interested in! - upnpCP->SetIGWDeviceDetected(true); - // Log it if not UPNP_DISCOVERY_ADVERTISEMENT_ALIVE, - // we don't want to spam our logs. - //if (EventType != UPNP_DISCOVERY_ADVERTISEMENT_ALIVE) { - // Add the root device to our list - upnpCP->AddRootDevice( - rootDevice, urlBase, - UpnpDiscovery_get_Location_cstr(d_event), - UpnpDiscovery_get_Expires(d_event) ); - -#if (UPNP_VERSION > 10624) && (UPNP_VERSION < 10800) - upnpCP->m_WaitForSearchTimeoutMutex.unlock(); -#endif - } - - // Free the XML doc tree - ixmlDocument_free(doc); - break; - } - 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 - upnpCP->m_WaitForSearchTimeoutMutex.unlock(); - break; - } - case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE: // UPnP Device Removed - { - const UpnpDiscovery* dab_event = static_cast(Event); - if(!dab_event) break; - - std::string devType = UpnpDiscovery_get_DeviceType_cstr(dab_event); - - // Check for an InternetGatewayDevice and removes it from the list - std::transform(devType.begin(), devType.end(), devType.begin(), tolower); - if (stdStringIsEqualCI(devType, upnpCP->m_upnpLib.UPNP_DEVICE_IGW)) - upnpCP->RemoveRootDevice( - UpnpDiscovery_get_DeviceID_cstr(dab_event) ); - break; - } - case UPNP_EVENT_RECEIVED: - { - // Event reveived - const UpnpEvent* e_event = static_cast(Event); - - const std::string Sid = UpnpEvent_get_SID_cstr(e_event); - - // Parses the event - upnpCP->OnEventReceived( Sid, - UpnpEvent_get_EventKey(e_event), - UpnpEvent_get_ChangedVariables(e_event) ); - break; - } - case UPNP_EVENT_SUBSCRIBE_COMPLETE: - msg += "error(UPNP_EVENT_SUBSCRIBE_COMPLETE): "; - goto upnpEventRenewalComplete; - case UPNP_EVENT_UNSUBSCRIBE_COMPLETE: - msg += "error(UPNP_EVENT_UNSUBSCRIBE_COMPLETE): "; - goto upnpEventRenewalComplete; - case UPNP_EVENT_RENEWAL_COMPLETE: - { - msg += "error(UPNP_EVENT_RENEWAL_COMPLETE): "; -upnpEventRenewalComplete: - const UpnpEventSubscribe* es_event = - static_cast(Event); - - if (UpnpEventSubscribe_get_ErrCode(es_event) != UPNP_E_SUCCESS) - { - msg += "Error in Event Subscribe Callback"; - upnpCP->m_upnpLib.processUPnPErrorMessage( - msg, UpnpEventSubscribe_get_ErrCode(es_event), - nullptr, nullptr ); - } - - break; - } - case UPNP_EVENT_AUTORENEWAL_FAILED: - msg += "CUPnPControlPoint::Callback() error(UPNP_EVENT_AUTORENEWAL_FAILED): "; - msg2 += "UPNP_EVENT_AUTORENEWAL_FAILED: "; - goto upnpEventSubscriptionExpired; - case UPNP_EVENT_SUBSCRIPTION_EXPIRED: { - msg += "CUPnPControlPoint::Callback() error(UPNP_EVENT_SUBSCRIPTION_EXPIRED): "; - msg2 += "UPNP_EVENT_SUBSCRIPTION_EXPIRED: "; -upnpEventSubscriptionExpired: - const UpnpEventSubscribe* es_event = - static_cast(Event); - - Upnp_SID newSID; - int TimeOut = 1801; - int ret = UpnpSubscribe( - upnpCP->m_UPnPClientHandle, -#ifdef PATCHED_LIBUPNP - UpnpString_get_String(es_event->PublisherUrl), -#else - UpnpEventSubscribe_get_PublisherUrl_cstr(es_event), -#endif - &TimeOut, - newSID); - if (ret != UPNP_E_SUCCESS) - { - msg += "Error Subscribing to EventURL"; - upnpCP->m_upnpLib.processUPnPErrorMessage( - msg, UpnpEventSubscribe_get_ErrCode(es_event), - nullptr, nullptr ); - } - else - { - ServiceMap::iterator it = -#ifdef PATCHED_LIBUPNP - upnpCP->m_ServiceMap.find(UpnpString_get_String(es_event->PublisherUrl)); -#else - upnpCP->m_ServiceMap.find( - UpnpEventSubscribe_get_PublisherUrl_cstr(es_event) ); -#endif - if (it != upnpCP->m_ServiceMap.end()) { - CUPnPService &service = *(it->second); - service.SetTimeout(TimeOut); - service.SetSID(newSID); - std::cerr << "CUPnPControlPoint::Callback() Re-subscribed to EventURL '" << -#ifdef PATCHED_LIBUPNP - UpnpString_get_String(es_event->PublisherUrl) << -#else - UpnpEventSubscribe_get_PublisherUrl_cstr(es_event) << -#endif - "' with SID == '" << - newSID << "'." << std::endl; - // In principle, we should test to see if the - // service is the same. But here we only have one - // service, so... - upnpCP->RefreshPortMappings(); - } - else - { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Callback() Error: did not find service " << - newSID << " in the service map." << std::endl; -#endif - } - } - break; - } - case UPNP_CONTROL_ACTION_COMPLETE: - { - // This is here if we choose to do this asynchronously - const UpnpActionComplete* a_event = - static_cast(Event); - if(UpnpActionComplete_get_ErrCode(a_event) != UPNP_E_SUCCESS) - { - upnpCP->m_upnpLib.processUPnPErrorMessage( - "UpnpSendActionAsync", - UpnpActionComplete_get_ErrCode(a_event), nullptr, - UpnpActionComplete_get_ActionResult(a_event) ); - } - else - { - // Check the response document - upnpCP->m_upnpLib.ProcessActionResponse( - UpnpActionComplete_get_ActionResult(a_event), - "" ); - } - /* No need for any processing here, just print out results. - * Service state table updates are handled by events. - */ - break; - } - case UPNP_CONTROL_GET_VAR_COMPLETE: - { - msg += "CUPnPControlPoint::Callback() error(UPNP_CONTROL_GET_VAR_COMPLETE): "; - const UpnpStateVarComplete* sv_event = - static_cast(Event); - if (UpnpStateVarComplete_get_ErrCode(sv_event) != UPNP_E_SUCCESS) - { - msg += "m_UpnpGetServiceVarStatusAsync"; - upnpCP->m_upnpLib.processUPnPErrorMessage( - msg, UpnpStateVarComplete_get_ErrCode(sv_event), - nullptr, nullptr ); - } - else - { - //add the variable to the wanservice property map - (upnpCP->m_WanService->propertyMap)[ - std::string( - UpnpStateVarComplete_get_StateVarName_cstr(sv_event) ) ] - = std::string(UpnpStateVarComplete_get_CurrentVal_cstr(sv_event)); - } - break; - } - // ignore these cases, since this is not a device - case UPNP_CONTROL_GET_VAR_REQUEST: - //fprintf(stderr, "Callback: UPNP_CONTROL_GET_VAR_REQUEST\n"); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Callback() error(UPNP_CONTROL_GET_VAR_REQUEST): "; -#endif - goto eventSubscriptionRequest; - case UPNP_CONTROL_ACTION_REQUEST: - //fprintf(stderr, "Callback: UPNP_CONTROL_ACTION_REQUEST\n"); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Callback() error(UPNP_CONTROL_ACTION_REQUEST): "; -#endif - goto eventSubscriptionRequest; - case UPNP_EVENT_SUBSCRIPTION_REQUEST: - //fprintf(stderr, "Callback: UPNP_EVENT_SUBSCRIPTION_REQUEST\n"); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Callback() error(UPNP_EVENT_SUBSCRIPTION_REQUEST): "; -#endif -eventSubscriptionRequest: -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Callback() This is not a UPnP Device, this is a UPnP Control Point, event ignored." << std::endl; -#endif - break; - default: - // Humm, this is not good, we forgot to handle something... -#ifdef UPNP_DEBUG - fprintf(stderr, - "Callback: default... Unknown event:'%d', not good.\n", - EventType); - std::cerr << "CUPnPControlPoint::Callback() error(UPnP::Callback): Event not handled:'" << - EventType << "'." << std::endl; -#endif - // Better not throw in the callback. Who would catch it? - //throw CUPnPException(msg); - break; - } - - return 0; -} - - -void CUPnPControlPoint::OnEventReceived( - const std::string &Sid, - int EventKey, - const IXML_Document* ChangedVariablesDoc) -{ - /* remove unused parameter warnings */ - (void) EventKey; - -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::OnEventReceived() UPNP_EVENT_RECEIVED:" << - "\n SID: " << Sid << - "\n Key: " << EventKey << std::endl; - std::cerr << "CUPnPControlPoint::OnEventReceived() m_WanService->GetServiceId() : " << m_WanService->GetSID() << std::endl; -#endif - - if (m_WanService->GetSID() == Sid) { - //let's store the properties if it is an event of the wan device -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::OnEventReceived() \n Property list:"; -#endif - - IXML_Element *root = - m_upnpLib.Element_GetRootElement(ChangedVariablesDoc); - IXML_Element *child = - m_upnpLib.Element_GetFirstChild(root); - if (child) { - while (child) { - IXML_Element *child2 = - m_upnpLib.Element_GetFirstChild(child); - const DOMString childTag = - m_upnpLib.Element_GetTag(child2); - std::string childValue = - m_upnpLib.Element_GetTextValue(child2); -#ifdef UPNP_DEBUG - std::cerr << "\n " << - childTag << "='" << - childValue << "'"; -#endif - const std::string cTag(childTag); - const std::string cValue(childValue); - (m_WanService->propertyMap)[cTag] = cValue; - child = m_upnpLib.Element_GetNextSibling(child); - } - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::OnEventReceived() \n Empty property list."; -#endif - } -#ifdef UPNP_DEBUG - std::cerr << std::endl; -#endif - // Freeing that doc segfaults. Probably should not be freed. - //ixmlDocument_free(ChangedVariablesDoc); - } -} - - -void CUPnPControlPoint::AddRootDevice( - IXML_Element *rootDevice, const std::string &urlBase, - const char *location, int expires) -{ - // Lock the Root Device List - RsMutex toto(m_RootDeviceListMutex); - - // Root node's URLBase - std::string OriginalURLBase(urlBase); - std::string FixedURLBase(OriginalURLBase.empty() ? - location : - OriginalURLBase); - - // Get the UDN (Unique Device Name) - std::string UDN( - m_upnpLib.Element_GetChildValueByTag(rootDevice, "UDN")); - RootDeviceMap::iterator it = m_RootDeviceMap.find(UDN); - bool alreadyAdded = it != m_RootDeviceMap.end(); - if (alreadyAdded) { - // Just set the expires field - it->second->SetExpires(expires); - } else { - // Add a new root device to the root device list - CUPnPRootDevice *upnpRootDevice = new CUPnPRootDevice( - *this, m_upnpLib, rootDevice, - OriginalURLBase, FixedURLBase, - location, expires); - m_RootDeviceMap[upnpRootDevice->GetUDN()] = upnpRootDevice; - } -} - - -void CUPnPControlPoint::RemoveRootDevice(const char *udn) -{ - // Lock the Root Device List - RsMutex toto(m_RootDeviceListMutex); - - // Remove - std::string UDN(udn); - RootDeviceMap::iterator it = m_RootDeviceMap.find(UDN); - if (it != m_RootDeviceMap.end()) { - delete it->second; - m_RootDeviceMap.erase(UDN); - } -} - - -void CUPnPControlPoint::Subscribe(CUPnPService &service) -{ - - IXML_Document *scpdDoc = NULL; - int errcode = UpnpDownloadXmlDoc( - service.GetAbsSCPDURL().c_str(), &scpdDoc); - if (errcode == UPNP_E_SUCCESS) { - // Get the root node of this service (the SCPD Document) - IXML_Element *scpdRoot = - m_upnpLib.Element_GetRootElement(scpdDoc); - CUPnPSCPD *scpd = new CUPnPSCPD(*this, m_upnpLib, - scpdRoot, service.GetAbsSCPDURL()); - service.SetSCPD(scpd); - m_ServiceMap[service.GetAbsEventSubURL()] = &service; -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Subscribe() Successfully retrieved SCPD Document for service " << - service.GetServiceType() << ", absEventSubURL: " << - service.GetAbsEventSubURL() << "." << std::endl; -#endif - - // Now try to subscribe to this service. If the subscription - // is not successfull, we will not be notified about events, - // but it may be possible to use the service anyway. - errcode = UpnpSubscribe(m_UPnPClientHandle, - service.GetAbsEventSubURL().c_str(), - service.GetTimeoutAddr(), - service.GetSID()); - if (errcode == UPNP_E_SUCCESS) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Subscribe() Successfully subscribed to service " << - service.GetServiceType() << ", absEventSubURL: " << - service.GetAbsEventSubURL() << "." << std::endl; -#endif - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Subscribe() Error subscribing to service " << - service.GetServiceType() << ", absEventSubURL: " << - service.GetAbsEventSubURL() << ", error: " << - m_upnpLib.GetUPnPErrorMessage(errcode) << "."; -#endif - goto error; - } - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Subscribe() Error getting SCPD Document from " << - service.GetAbsSCPDURL() << "." << std::endl; -#endif - } - - return; - -error: - ; -#ifdef UPNP_DEBUG - std::cerr << std::endl; -#endif -} - - -void CUPnPControlPoint::Unsubscribe(CUPnPService &service) -{ - ServiceMap::iterator it = m_ServiceMap.find(service.GetAbsEventSubURL()); - if (it != m_ServiceMap.end()) { - m_ServiceMap.erase(it); - UpnpUnSubscribe(m_UPnPClientHandle, service.GetSID()); - } -} - - -// File_checked_for_headers diff --git a/libretroshare/src/rs_upnp/UPnPBase.h b/libretroshare/src/rs_upnp/UPnPBase.h deleted file mode 100644 index e1c41fb83..000000000 --- a/libretroshare/src/rs_upnp/UPnPBase.h +++ /dev/null @@ -1,620 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: UPnPBase.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2004-2009 Marcelo Roberto Jimenez ( phoenix@amule.org ) * - * Copyright (c) 2006-2009 aMule Team ( admin@amule.org / http://www.amule.org)* - * Copyright (c) 2009-2010 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "util/rsthreads.h" - -#include -#include - -#ifdef UPNP_C - std::string stdEmptyString; -#else // UPNP_C - extern std::string stdEmptyString; -#endif // UPNP_C - -//#define UPNP_DEBUG 1 - -/** - * Case insensitive std::string comparison - */ -bool stdStringIsEqualCI( - const std::string &s1, - const std::string &s2); - - -class CUPnPPortMapping -{ -private: - std::string m_ex_port; - std::string m_in_port; - std::string m_protocol; - std::string m_enabled; - std::string m_description; - std::string m_key; - -public: - CUPnPPortMapping( - int ex_port = 0, - int in_port = 0, - const std::string &protocol = stdEmptyString, - bool enabled = false, - const std::string &description = stdEmptyString); - ~CUPnPPortMapping() {} - - const std::string &getExPort() const - { return m_ex_port; } - const std::string &getInPort() const - { return m_in_port; } - const std::string &getProtocol() const - { return m_protocol; } - const std::string &getEnabled() const - { return m_enabled; } - const std::string &getDescription() const - { return m_description; } - const std::string &getKey() const - { return m_key; } -}; - - -class CUPnPControlPoint; - - -class CUPnPLib -{ -public: - static const std::string &UPNP_ROOT_DEVICE; - static const std::string &UPNP_DEVICE_IGW; - static const std::string &UPNP_DEVICE_WAN; - static const std::string &UPNP_DEVICE_WAN_CONNECTION; - static const std::string &UPNP_DEVICE_LAN; - static const std::string &UPNP_SERVICE_LAYER3_FORWARDING; - static const std::string &UPNP_SERVICE_WAN_COMMON_INTERFACE_CONFIG; - static const std::string &UPNP_SERVICE_WAN_IP_CONNECTION; - static const std::string &UPNP_SERVICE_WAN_PPP_CONNECTION; - CUPnPControlPoint &m_ctrlPoint; - -public: - explicit CUPnPLib(CUPnPControlPoint &ctrlPoint); - ~CUPnPLib() {} - - // Convenience function so we don't have to write explicit calls - // to char2unicode every time - std::string GetUPnPErrorMessage(int code) const; - - // Convenience function to avoid repetitive processing of error - // messages - std::string processUPnPErrorMessage(const std::string &messsage, - int code, - const DOMString errorString, - const IXML_Document* doc) const; - - // Processing response to actions - void ProcessActionResponse( - const IXML_Document* RespDoc, - const std::string& actionName ) const; - - // IXML_Element - IXML_Element* Element_GetRootElement(const IXML_Document* doc) const; - IXML_Element *Element_GetFirstChild( - IXML_Element *parent) const; - IXML_Element *Element_GetNextSibling( - IXML_Element *child) const; - const DOMString Element_GetTag( - IXML_Element *element) const; - const std::string Element_GetTextValue( - IXML_Element *element) const; - const std::string Element_GetChildValueByTag( - IXML_Element *element, - const DOMString tag) const; - IXML_Element *Element_GetFirstChildByTag( - IXML_Element *element, - const DOMString tag) const; - IXML_Element *Element_GetNextSiblingByTag( - IXML_Element *element, - const DOMString tag) const; - const std::string Element_GetAttributeByTag( - IXML_Element *element, - const DOMString tag) const; -}; - - -class CUPnPControlPoint; - -/* - * Even though we can retrieve the upnpLib handler from the upnpControlPoint, - * we must pass it separetly at this point, because the class CUPnPControlPoint - * must be declared after. - * - * CUPnPLib can only be removed from the constructor once we agree to link to - * UPnPLib explicitly, making this dlopen() stuff unnecessary. - */ -template -class CXML_List : public std::map -{ -public: - CXML_List( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *parent, - const std::string &url); - ~CXML_List(); -}; - - -template -CXML_List::CXML_List( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *parent, - const std::string &url) -{ - IXML_Element *elementList = - upnpLib.Element_GetFirstChildByTag(parent, XML_LIST_NAME); - unsigned int i = 0; - for ( IXML_Element *element = upnpLib.Element_GetFirstChildByTag(elementList, XML_ELEMENT_NAME); - element; - element = upnpLib.Element_GetNextSiblingByTag(element, XML_ELEMENT_NAME)) { - // Add a new element to the element list - T *upnpElement = new T(upnpControlPoint, upnpLib, element, url); - (*this)[upnpElement->GetKey()] = upnpElement; - ++i; - } - std::cerr << "\n " << XML_LIST_NAME << ": " << - i << " " << XML_ELEMENT_NAME << "s."; -} - - -template -CXML_List::~CXML_List() -{ - typename CXML_List::iterator it; - for(it = this->begin(); it != this->end(); ++it) { - delete (*it).second; - } -} - -extern const char s_argument[]; -extern const char s_argumentList[]; -extern const char s_action[]; -extern const char s_actionList[]; -extern const char s_allowedValue[]; -extern const char s_allowedValueList[]; -extern const char s_stateVariable[]; -extern const char s_serviceStateTable[]; -extern const char s_service[]; -extern const char s_serviceList[]; -extern const char s_device[]; -extern const char s_deviceList[]; - -#ifdef UPNP_C - const char s_argument[] = "argument"; - const char s_argumentList[] = "argumentList"; - const char s_action[] = "action"; - const char s_actionList[] = "actionList"; - const char s_allowedValue[] = "allowedValue"; - const char s_allowedValueList[] = "allowedValueList"; - const char s_stateVariable[] = "stateVariable"; - const char s_serviceStateTable[] = "serviceStateTable"; - const char s_service[] = "service"; - const char s_serviceList[] = "serviceList"; - const char s_device[] = "device"; - const char s_deviceList[] = "deviceList"; -#endif // UPNP_C - - -class CUPnPArgument; -typedef CXML_List ArgumentList; -class CUPnPAction; -typedef CXML_List ActionList; -class CUPnPStateVariable; -typedef CXML_List ServiceStateTable; -class CUPnPAllowedValue; -typedef CXML_List AllowedValueList; -class CUPnPService; -typedef CXML_List ServiceList; -class CUPnPDevice; -typedef CXML_List DeviceList; - - -class CUPnPError -{ -private: - IXML_Element *m_root; - const std::string m_ErrorCode; - const std::string m_ErrorDescription; -public: - CUPnPError( - const CUPnPLib &upnpLib, - const IXML_Document *errorDoc); - ~CUPnPError() {} - const std::string &getErrorCode() const - { return m_ErrorCode; } - const std::string &getErrorDescription() const - { return m_ErrorDescription; } -}; - - -class CUPnPArgument -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - const std::string m_name; - const std::string m_direction; - bool m_retval; - const std::string m_relatedStateVariable; - -public: - CUPnPArgument( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *argument, - const std::string &SCPDURL); - ~CUPnPArgument() {} - const std::string &GetName() const - { return m_name; } - const std::string &GetDirection() const - { return m_direction; } - bool GetRetVal() const - { return m_retval; } - const std::string &GetRelatedStateVariable() const - { return m_relatedStateVariable; } - const std::string &GetKey() const - { return m_name; } -}; - - - -class CUPnPAction -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - ArgumentList m_ArgumentList; - const std::string m_name; - -public: - CUPnPAction( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *action, - const std::string &SCPDURL); - ~CUPnPAction() {} - const std::string &GetName() const - { return m_name; } - const std::string &GetKey() const - { return m_name; } - const ArgumentList &GetArgumentList() const - { return m_ArgumentList; } -}; - - -class CUPnPAllowedValue -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - const std::string m_allowedValue; - -public: - CUPnPAllowedValue( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *allowedValue, - const std::string &SCPDURL); - ~CUPnPAllowedValue() {} - const std::string &GetAllowedValue() const - { return m_allowedValue; } - const std::string &GetKey() const - { return m_allowedValue; } -}; - - -class CUPnPStateVariable -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - AllowedValueList m_AllowedValueList; - const std::string m_name; - const std::string m_dataType; - const std::string m_defaultValue; - const std::string m_sendEvents; - -public: - CUPnPStateVariable( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *stateVariable, - const std::string &URLBase); - ~CUPnPStateVariable() {} - const std::string &GetNname() const - { return m_name; } - const std::string &GetDataType() const - { return m_dataType; } - const std::string &GetDefaultValue() const - { return m_defaultValue; } - const std::string &GetKey() const - { return m_name; } - const AllowedValueList &GetAllowedValueList() const - { return m_AllowedValueList; } -}; - - -class CUPnPSCPD -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - ActionList m_ActionList; - ServiceStateTable m_ServiceStateTable; - const std::string m_SCPDURL; - -public: - CUPnPSCPD( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *scpd, - const std::string &SCPDURL); - ~CUPnPSCPD() {} - const ActionList &GetActionList() const - { return m_ActionList; } - const ServiceStateTable &GetServiceStateTable() const - { return m_ServiceStateTable; } -}; - - -class CUPnPArgumentValue -{ -private: - std::string m_argument; - std::string m_value; - -public: - CUPnPArgumentValue(); - CUPnPArgumentValue(const std::string &argument, const std::string &value); - ~CUPnPArgumentValue() {} - - const std::string &GetArgument() const { return m_argument; } - const std::string &GetValue() const { return m_value; } - const std::string &SetArgument(const std::string& argument) { return m_argument = argument; } - const std::string &SetValue(const std::string &value) { return m_value = value; } -}; - - -class CUPnPService -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - CUPnPLib &m_upnpLib; - const std::string m_serviceType; - const std::string m_serviceId; - const std::string m_SCPDURL; - const std::string m_controlURL; - const std::string m_eventSubURL; - std::string m_absSCPDURL; - std::string m_absControlURL; - std::string m_absEventSubURL; - int m_timeout; - Upnp_SID m_SID; - std::auto_ptr m_SCPD; - -public: - std::map propertyMap; - CUPnPService( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *service, - const std::string &URLBase); - ~CUPnPService(); - - const std::string &GetServiceType() const - { return m_serviceType; } - const std::string &GetServiceId() const - { return m_serviceId; } - const std::string &GetSCPDURL() const - { return m_SCPDURL; } - const std::string &GetAbsSCPDURL() const - { return m_absSCPDURL; } - const std::string &GetControlURL() const - { return m_controlURL; } - const std::string &GetEventSubURL() const - { return m_eventSubURL; } - const std::string &GetAbsControlURL() const - { return m_absControlURL; } - const std::string &GetAbsEventSubURL() const - { return m_absEventSubURL; } - int GetTimeout() const - { return m_timeout; } - void SetTimeout(int t) - { m_timeout = t; } - int *GetTimeoutAddr() - { return &m_timeout; } - char *GetSID() - { return m_SID; } - void SetSID(const char *s) - { memcpy(m_SID, s, sizeof(Upnp_SID)); } - const std::string &GetKey() const - { return m_serviceId; } - bool IsSubscribed() const - { return m_SCPD.get() != NULL; } - void SetSCPD(CUPnPSCPD *SCPD) - { m_SCPD.reset(SCPD); } - - bool Execute( - const std::string &ActionName, - const std::vector &ArgValue) const; - const std::string GetStateVariable( - const std::string &stateVariableName); - -}; - - -class CUPnPDevice -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - - // Please, lock these lists before use - DeviceList m_DeviceList; - ServiceList m_ServiceList; - - const std::string m_deviceType; - const std::string m_friendlyName; - const std::string m_manufacturer; - const std::string m_manufacturerURL; - const std::string m_modelDescription; - const std::string m_modelName; - const std::string m_modelNumber; - const std::string m_modelURL; - const std::string m_serialNumber; - const std::string m_UDN; - const std::string m_UPC; - std::string m_presentationURL; - -public: - CUPnPDevice( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *device, - const std::string &URLBase); - ~CUPnPDevice() {} - - const std::string &GetUDN() const - { return m_UDN; } - const std::string &GetDeviceType() const - { return m_deviceType; } - const std::string &GetFriendlyName() const - { return m_friendlyName; } - const std::string &GetPresentationURL() const - { return m_presentationURL; } - const std::string &GetKey() const - { return m_UDN; } -}; - - -class CUPnPRootDevice : public CUPnPDevice -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - const std::string m_URLBase; - const std::string m_location; - int m_expires; - -public: - CUPnPRootDevice( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *rootDevice, - const std::string &OriginalURLBase, - const std::string &FixedURLBase, - const char *location, - int expires); - ~CUPnPRootDevice() {} - - const std::string &GetURLBase() const - { return m_URLBase; } - const std::string &GetLocation() const - { return m_location; } - int GetExpires() const - { return m_expires; } - void SetExpires(int expires) - { m_expires = expires; } -}; - - -typedef std::map RootDeviceMap; -typedef std::map ServiceMap; -typedef std::map PortMappingMap; - - -class CUPnPControlPoint -{ -private: - // upnp stuff - CUPnPLib m_upnpLib; - UpnpClient_Handle m_UPnPClientHandle; - RootDeviceMap m_RootDeviceMap; - ServiceMap m_ServiceMap; - PortMappingMap m_ActivePortMappingsMap; - RsMutex m_RootDeviceListMutex; - bool m_IGWDeviceDetected; - RsMutex m_WaitForSearchTimeoutMutex; - -public: - CUPnPService *m_WanService; - std::string m_getStateVariableLastResult; - static CUPnPControlPoint *s_CtrlPoint; - explicit CUPnPControlPoint(unsigned short udpPort); - ~CUPnPControlPoint(); - char* getInternalIpAddress(); - std::string getExternalAddress(); - void Subscribe(CUPnPService &service); - void Unsubscribe(CUPnPService &service); - bool AddPortMappings( - std::vector &upnpPortMapping); - bool DeletePortMappings( - std::vector &upnpPortMapping); - - UpnpClient_Handle GetUPnPClientHandle() const - { return m_UPnPClientHandle; } - - bool GetIGWDeviceDetected() const - { return m_IGWDeviceDetected; } - void SetIGWDeviceDetected(bool b) - { m_IGWDeviceDetected = b; } - bool WanServiceDetected() const - { return !m_ServiceMap.empty(); } - void SetWanService(CUPnPService *service) - { m_WanService = service; } - - // Callback function - static int Callback( - Upnp_EventType EventType, const void* Event, void* Cookie ); - void OnEventReceived(const std::string &Sid, - int EventKey, - const IXML_Document* ChangedVariables); - -private: - void AddRootDevice( - IXML_Element *rootDevice, - const std::string &urlBase, - const char *location, - int expires); - void RemoveRootDevice( - const char *udn); - void RefreshPortMappings(); - bool PrivateAddPortMapping( - CUPnPPortMapping &upnpPortMapping); - bool PrivateDeletePortMapping( - CUPnPPortMapping &upnpPortMapping); - bool PrivateGetExternalIpAdress(); -}; - -// File_checked_for_headers diff --git a/libretroshare/src/rs_upnp/upnp18_retrocompat.h b/libretroshare/src/rs_upnp/upnp18_retrocompat.h deleted file mode 100644 index 26fb0a524..000000000 --- a/libretroshare/src/rs_upnp/upnp18_retrocompat.h +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************* - * libupnp-1.8.x -> libupnp-1.6.x retrocompatibility header * - * * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include - - -#if UPNP_VERSION < 10800 - -using UpnpDiscovery = Upnp_Discovery; -using UpnpEvent = Upnp_Event; -using UpnpEventSubscribe = Upnp_Event_Subscribe; -using UpnpActionComplete = Upnp_Action_Complete; -using UpnpStateVarComplete = Upnp_State_Var_Complete; - -static inline const char* UpnpStateVarComplete_get_CurrentVal_cstr( - const UpnpStateVarComplete* esvc) noexcept { return esvc->CurrentVal; } - -#endif // UPNP_VERSION < 10800 - -#if UPNP_VERSION < 10624 - -static inline int UpnpDiscovery_get_Expires(const Upnp_Discovery* disc) noexcept -{ return disc->Expires; } - -static inline const char* UpnpDiscovery_get_DeviceID_cstr( - const Upnp_Discovery* disc ) noexcept -{ return disc->DeviceId; } - -static inline const char* UpnpDiscovery_get_DeviceType_cstr( - const Upnp_Discovery* disc ) noexcept -{ return disc->DeviceType; } - -static inline const char* UpnpDiscovery_get_Location_cstr( - const Upnp_Discovery* disc ) noexcept -{ return disc->Location; } - -static inline const char* UpnpEvent_get_SID_cstr(const UpnpEvent* ev) noexcept -{ return ev->Sid; } - -static inline int UpnpEvent_get_EventKey(const UpnpEvent* ev) noexcept -{ return ev->EventKey; } - -static inline const IXML_Document* UpnpEvent_get_ChangedVariables( - const UpnpEvent* ev) noexcept { return ev->ChangedVariables; } - -static inline int UpnpEventSubscribe_get_ErrCode(const UpnpEventSubscribe* evs) -noexcept { return evs->ErrCode; } - -static inline const char* UpnpEventSubscribe_get_PublisherUrl_cstr( - const UpnpEventSubscribe* evs ) noexcept { return evs->PublisherUrl; } - -static inline int UpnpActionComplete_get_ErrCode(const UpnpActionComplete* evc) -noexcept { return evc->ErrCode; } - -static inline const IXML_Document* UpnpActionComplete_get_ActionResult( - const UpnpActionComplete* evc ) noexcept { return evc->ActionResult; } - -static inline int UpnpStateVarComplete_get_ErrCode( - const UpnpStateVarComplete* esvc) noexcept { return esvc->ErrCode; } - -static inline const char* UpnpStateVarComplete_get_StateVarName_cstr( - const UpnpStateVarComplete* esvc) noexcept { return esvc->StateVarName; } - -#endif // UPNP_VERSION < 10624 diff --git a/libretroshare/src/rs_upnp/upnphandler_libupnp.cc b/libretroshare/src/rs_upnp/upnphandler_libupnp.cc deleted file mode 100644 index 17e096a08..000000000 --- a/libretroshare/src/rs_upnp/upnphandler_libupnp.cc +++ /dev/null @@ -1,466 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: upnphandler_libupnp.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2018 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} /* extern C */ -#endif -/* This stuff is actually C */ - -#include "rs_upnp/upnphandler_libupnp.h" - -#include "util/rsnet.h" - -bool upnphandler::initUPnPState() -{ - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState" << std::endl; - #endif - cUPnPControlPoint = new CUPnPControlPoint(2000); - - bool IGWDetected = cUPnPControlPoint->GetIGWDeviceDetected(); - - if (IGWDetected) { - /* MODIFY STATE */ - dataMtx.lock(); /* LOCK MUTEX */ - upnpState = RS_UPNP_S_READY; - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState cUPnPControlPoint internal ip adress : "; - std::cerr << cUPnPControlPoint->getInternalIpAddress() << std::endl; - #endif - - //const char ipaddr = cUPnPControlPoint->getInternalIpAddress().c_str(); - inet_aton(cUPnPControlPoint->getInternalIpAddress(), &(upnp_iaddr.sin_addr)); - upnp_iaddr.sin_port = htons(iport); - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState READY" << std::endl; - #endif - dataMtx.unlock(); /* UNLOCK MUTEX */ - - } else { - upnpState = RS_UPNP_S_UNAVAILABLE; - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState UNAVAILABLE" << std::endl; - #endif - } - - return 0; -} - -class upnpThreadData -{ - public: - upnphandler *handler; - bool start; - bool stop; -}; - - /* Thread routines */ -extern "C" void* doSetupUPnP(void* p) -{ - #ifdef UPNP_DEBUG - std::cerr << "doSetupUPnP Creating upnp thread." << std::endl; - #endif - upnpThreadData *data = (upnpThreadData *) p; - if ((!data) || (!data->handler)) - { - pthread_exit(NULL); - } - - /* publish it! */ - if (data -> stop) - { - data->handler->shutdown_upnp(); - } - - if (data -> start) - { - data->handler->initUPnPState(); - data->handler->start_upnp(); - } - - delete data; - pthread_exit(NULL); - - return NULL; -} - -bool upnphandler::background_setup_upnp(bool start, bool stop) -{ - pthread_t tid; - - /* launch thread */ - #ifdef UPNP_DEBUG - std::cerr << "background_setup_upnp Creating upnp thread." << std::endl; - #endif - upnpThreadData *data = new upnpThreadData(); - data->handler = this; - data->start = start; - data->stop = stop; - - if(! pthread_create(&tid, 0, &doSetupUPnP, (void *) data)) - { - pthread_detach(tid); /* so memory is reclaimed in linux */ - - return true; - } - else - { - delete data ; - std::cerr << "(EE) Could not start background upnp thread!" << std::endl; - return false ; - } -} - -bool upnphandler::start_upnp() -{ - if (!(upnpState >= RS_UPNP_S_READY)) - { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::start_upnp() Not Ready" << std::endl; - #endif - return false; - } - - struct sockaddr_in localAddr; - { - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - /* if we're to load -> load */ - /* select external ports */ - eport_curr = eport; - if (!eport_curr) - { - /* use local port if eport is zero */ - eport_curr = iport; - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::start_upnp() Using LocalPort for extPort." << std::endl; - #endif - } - - if (!eport_curr) - { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::start_upnp() Invalid eport ... " << std::endl; - #endif - return false; - } - - /* our port */ - char in_addr[256]; - char in_port1[256]; - - upnp_iaddr.sin_port = htons(iport); - localAddr = upnp_iaddr; - uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr); - snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port)); - snprintf(in_addr, 256, "%d.%d.%d.%d", - ((linaddr >> 24) & 0xff), - ((linaddr >> 16) & 0xff), - ((linaddr >> 8) & 0xff), - ((linaddr >> 0) & 0xff)); - - #ifdef UPNP_DEBUG - std::cerr << "Attempting Redirection: InAddr: " << in_addr; - std::cerr << " InPort: " << in_port1; - std::cerr << " ePort: " << eport_curr; - std::cerr << " eProt: " << "TCP and UDP"; - std::cerr << std::endl; - #endif - } - - //first of all, build the mappings - std::vector upnpPortMapping1; - CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "TCP", true, "tcp retroshare redirection"); - upnpPortMapping1.push_back(cUPnPPortMapping1); - std::vector upnpPortMapping2; - CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "UDP", true, "udp retroshare redirection"); - upnpPortMapping2.push_back(cUPnPPortMapping2); - - //attempt to remove formal port redirection rules - cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); - cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); - - //add new rules - bool res = cUPnPControlPoint->AddPortMappings(upnpPortMapping1); - bool res2 = cUPnPControlPoint->AddPortMappings(upnpPortMapping2); - - struct sockaddr_storage extAddr; - bool extAddrResult = getExternalAddress(extAddr); - - { - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - if (extAddrResult && (res || res2)) { - upnpState = RS_UPNP_S_ACTIVE; - } else { - upnpState = RS_UPNP_S_TCP_AND_FAILED; - } - - toStart = false; - } - - return (upnpState == RS_UPNP_S_ACTIVE); - -} - -bool upnphandler::shutdown_upnp() -{ - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - /* always attempt this (unless no port number) */ - if (eport_curr > 0 && eport > 0 && (upnpState >= RS_UPNP_S_ACTIVE)) - { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; - std::cerr << " Prot: TCP"; - std::cerr << std::endl; - #endif - - std::vector upnpPortMapping1; - CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, 0, "TCP", true, "tcp redirection"); - upnpPortMapping1.push_back(cUPnPPortMapping1); - cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; - std::cerr << " Prot: UDP"; - std::cerr << std::endl; - #endif - - std::vector upnpPortMapping2; - CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, 0, "UDP", true, "udp redirection"); - upnpPortMapping2.push_back(cUPnPPortMapping2); - cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); - - //destroy the upnp object - cUPnPControlPoint->~CUPnPControlPoint(); - cUPnPControlPoint=NULL ; - } else { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown_upnp() : avoid upnp connection for shutdonws because probably a net flag went down." << std::endl; - #endif - } - - //stopping os ok, set starting to true for next net reset - toStop = false; - toStart = true; - upnpState = RS_UPNP_S_UNINITIALISED; - - return true; - -} - -/************************ External Interface ***************************** - * - * - * - */ - -upnphandler::upnphandler() - : - upnpState(RS_UPNP_S_UNINITIALISED), dataMtx("upupState"), - cUPnPControlPoint(NULL), - toEnable(false), toStart(false), toStop(false), - iport(0),eport(0), eport_curr(0) -{ -} - -upnphandler::~upnphandler() -{ - return; -} - - /* RsIface */ -void upnphandler::enable(bool active) -{ - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::enable called with argument active : " << active << std::endl; - std::cerr << "toEnable : " << toEnable << std::endl; - std::cerr << "toStart : " << toStart << std::endl; - #endif - - dataMtx.lock(); /*** LOCK MUTEX ***/ - if (active != toEnable) - { - if (active) - { - toStart = true; - } - else - { - toStop = true; - } - } - toEnable = active; - - bool start = toStart; - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - if (start) - { - /* make background thread to startup UPnP */ - background_setup_upnp(true, false); - } -} - - -void upnphandler::shutdown() -{ - /* blocking call to shutdown upnp */ - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown() called." << std::endl; - #endif - shutdown_upnp(); -} - - -void upnphandler::restart() -{ - /* non-blocking call to shutdown upnp, and startup again. */ - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::restart() called." << std::endl; - #endif - background_setup_upnp(true, true); -} - - - -bool upnphandler::getEnabled() -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - bool on = toEnable; - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return on; -} - -bool upnphandler::getActive() -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - #ifdef UPNP_DEBUG - std::cerr <<"upnphandler::getActive() result : " << (upnpState == RS_UPNP_S_ACTIVE) << std::endl; - #endif - - bool on = (upnpState == RS_UPNP_S_ACTIVE); - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return on; -} - - /* the address that the listening port is on */ -void upnphandler::setInternalPort(unsigned short iport_in) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - if (iport != iport_in) - { - iport = iport_in; - if ((toEnable) && - (upnpState == RS_UPNP_S_ACTIVE)) - { - toStop = true; - toStart = true; - } - } - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ -} - -void upnphandler::setExternalPort(unsigned short eport_in) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - /* flag both shutdown/start -> for restart */ - if (eport != eport_in) - { - eport = eport_in; - if ((toEnable) && - (upnpState == RS_UPNP_S_ACTIVE)) - { - toStop = true; - toStart = true; - } - } - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ -} - - /* as determined by uPnP */ -bool upnphandler::getInternalAddress(struct sockaddr_storage &addr) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - bool valid = (upnpState >= RS_UPNP_S_ACTIVE); - - // copy to universal addr. - sockaddr_storage_clear(addr); - sockaddr_storage_setipv4(addr, &upnp_iaddr); - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return valid; -} - -bool upnphandler::getExternalAddress(struct sockaddr_storage &addr) -{ - std::string externalAdress = cUPnPControlPoint->getExternalAddress(); - - if(!externalAdress.empty() && externalAdress != "") - { - const char* externalIPAddress = externalAdress.c_str(); - - #ifdef UPNP_DEBUG - std::cerr << " upnphandler::getExternalAddress() : " << externalIPAddress; - std::cerr << ":" << eport_curr; - std::cerr << std::endl; - #endif - - dataMtx.lock(); /*** LOCK MUTEX ***/ - sockaddr_clear(&upnp_eaddr); - inet_aton(externalIPAddress, &(upnp_eaddr.sin_addr)); - upnp_eaddr.sin_family = AF_INET; - upnp_eaddr.sin_port = htons(eport_curr); - - // copy to universal addr. - sockaddr_storage_clear(addr); - sockaddr_storage_setipv4(addr, &upnp_eaddr); - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return true; - } - else - { - return false; - } -} - - - diff --git a/libretroshare/src/rs_upnp/upnphandler_libupnp.h b/libretroshare/src/rs_upnp/upnphandler_libupnp.h deleted file mode 100644 index bc04d6d36..000000000 --- a/libretroshare/src/rs_upnp/upnphandler_libupnp.h +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: upnphandler_libupnp.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2018 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include - -/* platform independent networking... */ -#include "pqi/pqinetwork.h" -#include "pqi/pqiassist.h" - -#include "util/rsthreads.h" - -#include -#include "rs_upnp/UPnPBase.h" - -#define RS_UPNP_S_UNINITIALISED 0 -#define RS_UPNP_S_UNAVAILABLE 1 -#define RS_UPNP_S_READY 2 -#define RS_UPNP_S_TCP_AND_FAILED 3 -//#define RS_UPNP_S_UDP_FAILED 4 -#define RS_UPNP_S_ACTIVE 5 - -class upnphandler: public pqiNetAssistFirewall -{ - public: - - upnphandler(); - virtual ~upnphandler(); - - /* External Interface (pqiNetAssistFirewall) */ - virtual void enable(bool active); - virtual void shutdown(); - virtual void restart(); - - virtual bool getEnabled(); - virtual bool getActive(); - - virtual void setInternalPort(unsigned short iport_in); - virtual void setExternalPort(unsigned short eport_in); - virtual bool getInternalAddress(struct sockaddr_storage &addr); - virtual bool getExternalAddress(struct sockaddr_storage &addr); - - /* TO IMPLEMENT: New Port Forward interface to support as many ports as necessary */ - virtual bool requestPortForward(const PortForwardParams & /* params */) { return false; } - virtual bool statusPortForward(const uint32_t /* fwdId */, PortForwardParams & /*params*/) { return false; } - - /* Public functions - for background thread operation, - * but effectively private from rest of RS, as in derived class - */ - unsigned int upnpState; - - bool start_upnp(); - bool shutdown_upnp(); - - bool initUPnPState(); - - /* Mutex for data below */ - RsMutex dataMtx; - - private: - - CUPnPControlPoint *cUPnPControlPoint; - - bool background_setup_upnp(bool, bool); - - - bool toEnable; /* overall on/off switch */ - bool toStart; /* if set start forwarding */ - bool toStop; /* if set stop forwarding */ - - unsigned short iport; - unsigned short eport; /* config */ - unsigned short eport_curr; /* current forwarded */ - - /* info from upnp */ - struct sockaddr_in upnp_iaddr; - struct sockaddr_in upnp_eaddr; -}; - -/* info from upnp */ -int CtrlPointCallbackEventHandler(Upnp_EventType ,void* , void*); diff --git a/libretroshare/src/rs_upnp/upnphandler_miniupnp.cc b/libretroshare/src/rs_upnp/upnphandler_miniupnp.cc deleted file mode 100644 index ca21804af..000000000 --- a/libretroshare/src/rs_upnp/upnphandler_miniupnp.cc +++ /dev/null @@ -1,677 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: upnphandler_miniupnp.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2018 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -// Windows / Mac version. -/* This stuff is actually C */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} /* extern C */ -#endif -/* This stuff is actually C */ - -#include "rs_upnp/upnphandler_miniupnp.h" -#include "rs_upnp/upnputil.h" - -class uPnPConfigData -{ - public: - struct UPNPDev * devlist; - struct UPNPUrls urls; - struct IGDdatas data; - char lanaddr[16]; /* my ip address on the LAN */ -}; - -#include - -#include "util/rsnet.h" - -bool upnphandler::initUPnPState() -{ - /* allocate memory */ - uPnPConfigData *upcd = new uPnPConfigData; -#if MINIUPNPC_API_VERSION >= 14 //1.9 2015/07/23 - /* $Id: miniupnpc.h,v 1.44 2015/07/23 20:40:10 nanard Exp $ */ - //upnpDiscover(int delay, const char * multicastif, - // const char * minissdpdsock, int sameport, - // int ipv6, unsigned char ttl, - // int * error); - unsigned char ttl = 2; /* defaulting to 2 */ - upcd->devlist = upnpDiscover(2000, NULL, - NULL, 0, - 0, ttl, - NULL); -#else -#if MINIUPNPC_API_VERSION >= 8 //1.5 2011/04/18 - /* $Id: miniupnpc.h,v 1.41 2015/05/22 10:23:48 nanard Exp $ */ - /* $Id: miniupnpc.h,v 1.23 2011/04/11 08:21:46 nanard Exp $ */ - //upnpDiscover(int delay, const char * multicastif, - // const char * minissdpdsock, int sameport, - // int ipv6, - // int * error); - upcd->devlist = upnpDiscover(2000, NULL, - NULL, 0, - 0, - NULL); -#else -#if MINIUPNPC_API_VERSION >= 6//1.5 2011/03/14 - /* $Id: miniupnpc.h,v 1.21 2011/03/14 13:37:12 nanard Exp $ */ - //upnpDiscover(int delay, const char * multicastif, - // const char * minissdpdsock, int sameport, - // int * error); - upcd->devlist = upnpDiscover(2000, NULL, - NULL, 0, - NULL); -#else -#if MINIUPNPC_API_VERSION >= -4//1.1 2008/09/25 - /* $Id: miniupnpc.h,v 1.20 2011/02/07 16:46:05 nanard Exp $ */ - /* $Id: miniupnpc.h,v 1.18 2008/09/25 18:02:50 nanard Exp $ */ - //upnpDiscover(int delay, const char * multicastif, - // const char * minissdpdsock, int sameport); - upcd->devlist = upnpDiscover(2000, NULL, - NULL, 0); -#else -#if MINIUPNPC_API_VERSION >= -5//1.0 2007/12/19 - /* $Id: miniupnpc.h,v 1.17 2007/12/19 14:58:54 nanard Exp $ */ - //upnpDiscover(int delay, const char * multicastif, - // const char * minissdpdsock); - upcd->devlist = upnpDiscover(2000, NULL, - NULL); -#else -#if MINIUPNPC_API_VERSION >= -6//1.0 2007/10/16 - /* $Id: miniupnpc.h,v 1.15 2007/10/16 15:07:32 nanard Exp $ */ - //LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif); - upcd->devlist = upnpDiscover(2000, NULL); -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - /* $Id: miniupnpc.h,v 1.14 2007/10/01 13:42:52 nanard Exp $ */ - /* $Id: miniupnpc.h,v 1.9 2006/09/04 09:30:17 nanard Exp $ */ - //struct UPNPDev * upnpDiscover(int); - upcd->devlist = upnpDiscover(2000); -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version - //2006/09/04 to 2007/10/01 => -7//Start return struct UPNPDev * for upnpDiscover - //2007/10/16 => -6 upnpDiscover - //2007/12/19 => -5 upnpDiscover - //2008/09/25 => -4 upnpDiscover - //2009/04/17 => -3 UPNP_AddPortMapping - //2010/12/09 => -2 //struct IGDdatas_service CIF; - //2011/02/15 => -1 UPNP_AddPortMapping - //2011/03/14 => 6 //Start of MINIUPNPC_API_VERSION -#endif//>=-7 -#endif//>=-6 -#endif//>=-5 -#endif//>=-4 -#endif//>=6 -#endif//>=8 -#endif//>=14 - - if(upcd->devlist) - { - struct UPNPDev * device; - printf("List of UPNP devices found on the network :\n"); - for(device=upcd->devlist;device;device=device->pNext) - { - printf("\n desc: %s\n st: %s\n", - device->descURL, device->st); - } - putchar('\n'); - if(UPNP_GetValidIGD(upcd->devlist, &(upcd->urls), - &(upcd->data), upcd->lanaddr, - sizeof(upcd->lanaddr))) - { - printf("Found valid IGD : %s\n", - upcd->urls.controlURL); - printf("Local LAN ip address : %s\n", - upcd->lanaddr); - - /* MODIFY STATE */ - dataMtx.lock(); /* LOCK MUTEX */ - - /* convert to ipaddress. */ - inet_aton(upcd->lanaddr, &(upnp_iaddr.sin_addr)); - upnp_iaddr.sin_port = htons(iport); - - upnpState = RS_UPNP_S_READY; - if (upnpConfig) - { - delete upnpConfig; - } - upnpConfig = upcd; /* */ - - dataMtx.unlock(); /* UNLOCK MUTEX */ - - - /* done -> READY */ - return 1; - - } - else - { - fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n"); - } - - - freeUPNPDevlist(upcd->devlist); - upcd->devlist = 0; - } - else - { - fprintf(stderr, "No IGD UPnP Device found on the network !\n"); - } - - /* MODIFY STATE */ - dataMtx.lock(); /* LOCK MUTEX */ - - upnpState = RS_UPNP_S_UNAVAILABLE; - delete upcd; - upnpConfig = NULL; - - dataMtx.unlock(); /* UNLOCK MUTEX */ - - /* done, FAILED -> NOT AVAILABLE */ - - return 0; -} - -bool upnphandler::printUPnPState() -{ - std::cerr << "upnphandler::printUPnPState() ... locking"; - std::cerr << std::endl; - - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - std::cerr << "upnphandler::printUPnPState() ... locked"; - std::cerr << std::endl; - - uPnPConfigData *config = upnpConfig; - if ((upnpState >= RS_UPNP_S_READY) && (config)) - { - DisplayInfos(&(config -> urls), &(config->data)); - GetConnectionStatus(&(config -> urls), &(config->data)); - ListRedirections(&(config -> urls), &(config->data)); - } - else - { - std::cerr << "UPNP not Ready" << std::endl; - } - - return 1; -} - - -bool upnphandler::checkUPnPActive() -{ - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - uPnPConfigData *config = upnpConfig; - if ((upnpState > RS_UPNP_S_READY) && (config)) - { - char eprot1[] = "TCP"; - char eprot2[] = "UDP"; - - char in_addr[256]; - char in_port1[256]; - char in_port2[256]; - char eport1[256]; - char eport2[256]; - - struct sockaddr_in localAddr = upnp_iaddr; - uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr); - - snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port)); - snprintf(in_port2, 256, "%d", ntohs(localAddr.sin_port)); - - snprintf(in_addr, 256, "%d.%d.%d.%d", - ((linaddr >> 24) & 0xff), - ((linaddr >> 16) & 0xff), - ((linaddr >> 8) & 0xff), - ((linaddr >> 0) & 0xff)); - - snprintf(eport1, 256, "%d", eport_curr); - snprintf(eport2, 256, "%d", eport_curr); - - std::cerr << "upnphandler::checkUPnPState()"; - std::cerr << " Checking Redirection: InAddr: " << in_addr; - std::cerr << " InPort: " << in_port1; - std::cerr << " ePort: " << eport1; - std::cerr << " eProt: " << eprot1; - std::cerr << std::endl; - - - bool tcpOk = TestRedirect(&(config -> urls), &(config->data), - in_addr, in_port1, eport1, eprot1); - bool udpOk = TestRedirect(&(config -> urls), &(config->data), - in_addr, in_port2, eport2, eprot2); - - if ((!tcpOk) || (!udpOk)) - { - std::cerr << "upnphandler::checkUPnPState() ... Redirect Expired, restarting"; - std::cerr << std::endl; - - toStop = true; - toStart = true; - } - } - - return true; -} - -class upnpThreadData -{ - public: - upnphandler *handler; - bool start; - bool stop; -}; - - /* Thread routines */ -extern "C" void* doSetupUPnP(void* p) -{ - upnpThreadData *data = (upnpThreadData *) p; - if ((!data) || (!data->handler)) - { - pthread_exit(NULL); - } - - /* publish it! */ - if (data -> stop) - { - data->handler->shutdown_upnp(); - } - - if (data -> start) - { - data->handler->initUPnPState(); - data->handler->start_upnp(); - } - - data->handler->printUPnPState(); - - delete data; - pthread_exit(NULL); - - return NULL; -} - -bool upnphandler::background_setup_upnp(bool start, bool stop) -{ - pthread_t tid; - - /* launch thread */ - upnpThreadData *data = new upnpThreadData(); - data->handler = this; - data->start = start; - data->stop = stop; - - if(!pthread_create(&tid, 0, &doSetupUPnP, (void *) data)) - { - pthread_detach(tid); /* so memory is reclaimed in linux */ - return true; - } - else - { - delete data ; - std::cerr << "(EE) Failed to start upnp thread." << std::endl; - return false ; - } -} - -bool upnphandler::start_upnp() -{ - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - uPnPConfigData *config = upnpConfig; - if (!((upnpState >= RS_UPNP_S_READY) && (config))) - { - std::cerr << "upnphandler::start_upnp() Not Ready"; - std::cerr << std::endl; - return false; - } - - char eprot1[] = "TCP"; - char eprot2[] = "UDP"; - - /* if we're to load -> load */ - /* select external ports */ - eport_curr = eport; - if (!eport_curr) - { - /* use local port if eport is zero */ - eport_curr = iport; - std::cerr << "Using LocalPort for extPort!"; - std::cerr << std::endl; - } - - if (!eport_curr) - { - std::cerr << "Invalid eport ... "; - std::cerr << std::endl; - return false; - } - - - /* our port */ - char in_addr[256]; - char in_port1[256]; - char in_port2[256]; - char eport1[256]; - char eport2[256]; - - upnp_iaddr.sin_port = htons(iport); - struct sockaddr_in localAddr = upnp_iaddr; - uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr); - - snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port)); - snprintf(in_port2, 256, "%d", ntohs(localAddr.sin_port)); - snprintf(in_addr, 256, "%d.%d.%d.%d", - ((linaddr >> 24) & 0xff), - ((linaddr >> 16) & 0xff), - ((linaddr >> 8) & 0xff), - ((linaddr >> 0) & 0xff)); - - snprintf(eport1, 256, "%d", eport_curr); - snprintf(eport2, 256, "%d", eport_curr); - - std::cerr << "Attempting Redirection: InAddr: " << in_addr; - std::cerr << " InPort: " << in_port1; - std::cerr << " ePort: " << eport1; - std::cerr << " eProt: " << eprot1; - std::cerr << std::endl; - - if (!SetRedirectAndTest(&(config -> urls), &(config->data), - in_addr, in_port1, eport1, eprot1, - NULL /*leaseDuration*/, "RetroShare_TCP" /*description*/, - 0)) - { - upnpState = RS_UPNP_S_TCP_FAILED; - } - else if (!SetRedirectAndTest(&(config -> urls), &(config->data), - in_addr, in_port2, eport2, eprot2, - NULL /*leaseDuration*/, "RetroShare_UDP" /*description*/, - 0)) - { - upnpState = RS_UPNP_S_UDP_FAILED; - } - else - { - upnpState = RS_UPNP_S_ACTIVE; - } - - - /* now store the external address */ - char externalIPAddress[32]; - UPNP_GetExternalIPAddress(config -> urls.controlURL, -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - config->data.first.servicetype, -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - config->data.servicetype, -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif -#endif - externalIPAddress); - - sockaddr_clear(&upnp_eaddr); - - if(externalIPAddress[0]) - { - std::cerr << "Stored External address: " << externalIPAddress; - std::cerr << ":" << eport_curr; - std::cerr << std::endl; - - inet_aton(externalIPAddress, &(upnp_eaddr.sin_addr)); - upnp_eaddr.sin_family = AF_INET; - upnp_eaddr.sin_port = htons(eport_curr); - } - else - { - std::cerr << "FAILED To get external Address"; - std::cerr << std::endl; - } - - toStart = false; - - return true; - -} - -bool upnphandler::shutdown_upnp() -{ - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - uPnPConfigData *config = upnpConfig; - if (!((upnpState >= RS_UPNP_S_READY) && (config))) - { - return false; - } - - char eprot1[] = "TCP"; - char eprot2[] = "UDP"; - - /* always attempt this (unless no port number) */ - if (eport_curr > 0) - { - - char eport1[256]; - char eport2[256]; - - snprintf(eport1, 256, "%d", eport_curr); - snprintf(eport2, 256, "%d", eport_curr); - - std::cerr << "Attempting To Remove Redirection: port: " << eport1; - std::cerr << " Prot: " << eprot1; - std::cerr << std::endl; - - RemoveRedirect(&(config -> urls), &(config->data), - eport1, eprot1); - - - std::cerr << "Attempting To Remove Redirection: port: " << eport2; - std::cerr << " Prot: " << eprot2; - std::cerr << std::endl; - - RemoveRedirect(&(config -> urls), &(config->data), - eport2, eprot2); - - upnpState = RS_UPNP_S_READY; - toStop = false; - } - - return true; - -} - -/************************ External Interface ***************************** - * - * - * - */ - - -upnphandler::upnphandler() - : dataMtx("upnpState"), toEnable(false), toStart(false), toStop(false), - eport(0), eport_curr(0), - upnpState(RS_UPNP_S_UNINITIALISED), - upnpConfig(NULL) -{ - return; -} - -upnphandler::~upnphandler() -{ - return; -} - - /* RsIface */ -void upnphandler::enable(bool active) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - if (active != toEnable) - { - if (active) - { - toStart = true; - } - else - { - toStop = true; - } - } - toEnable = active; - - bool start = toStart; - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - if (start) - { - /* make background thread to startup UPnP */ - background_setup_upnp(true, false); - } - - -} - - -void upnphandler::shutdown() -{ - /* blocking call to shutdown upnp */ - - shutdown_upnp(); -} - - -void upnphandler::restart() -{ - /* non-blocking call to shutdown upnp, and startup again. */ - background_setup_upnp(true, true); -} - - - -bool upnphandler::getEnabled() -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - bool on = toEnable; - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return on; -} - -bool upnphandler::getActive() -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - bool on = (upnpState == RS_UPNP_S_ACTIVE); - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return on; -} - - /* the address that the listening port is on */ -void upnphandler::setInternalPort(unsigned short iport_in) -{ -// std::cerr << "UPnPHandler::setInternalAddress() pre Lock!" << std::endl; - dataMtx.lock(); /*** LOCK MUTEX ***/ -// std::cerr << "UPnPHandler::setInternalAddress() postLock!" << std::endl; - - std::cerr << "UPnPHandler::setInternalPort(" << iport_in << ") current port: "; - std::cerr << iport << std::endl; - - if (iport != iport_in) - { - iport = iport_in; - if ((toEnable) && - (upnpState == RS_UPNP_S_ACTIVE)) - { - toStop = true; - toStart = true; - } - } - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ -} - -void upnphandler::setExternalPort(unsigned short eport_in) -{ -// std::cerr << "UPnPHandler::getExternalPort() pre Lock!" << std::endl; - dataMtx.lock(); /*** LOCK MUTEX ***/ -// std::cerr << "UPnPHandler::getExternalPort() postLock!" << std::endl; - - std::cerr << "UPnPHandler::setExternalPort(" << eport_in << ") current port: "; - std::cerr << eport << std::endl; - - /* flag both shutdown/start -> for restart */ - if (eport != eport_in) - { - eport = eport_in; - if ((toEnable) && - (upnpState == RS_UPNP_S_ACTIVE)) - { - toStop = true; - toStart = true; - } - } - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ -} - -/* as determined by uPnP */ -bool upnphandler::getInternalAddress(struct sockaddr_storage &addr) -{ - RS_STACK_MUTEX(dataMtx); - - // copy to universal addr. - sockaddr_storage_clear(addr); - sockaddr_storage_setipv4(addr, &upnp_iaddr); - - bool valid = (upnpState >= RS_UPNP_S_ACTIVE); - - Dbg2() << __PRETTY_FUNCTION__ << " valid: " << valid - << " addr: " << addr << std::endl; - - return valid; -} - -bool upnphandler::getExternalAddress(sockaddr_storage &addr) -{ - RS_STACK_MUTEX(dataMtx); - - // copy to universal addr. - sockaddr_storage_clear(addr); - sockaddr_storage_setipv4(addr, &upnp_eaddr); - - bool valid = (upnpState == RS_UPNP_S_ACTIVE); - - Dbg2() << __PRETTY_FUNCTION__ << " valid: " << valid - << " addr: " << addr << std::endl; - - return valid; -} - diff --git a/libretroshare/src/rs_upnp/upnphandler_miniupnp.h b/libretroshare/src/rs_upnp/upnphandler_miniupnp.h deleted file mode 100644 index 9449661e0..000000000 --- a/libretroshare/src/rs_upnp/upnphandler_miniupnp.h +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: upnphandler_miniupnp.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2018 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -/* platform independent networking... */ -#include "pqi/pqinetwork.h" -#include "pqi/pqiassist.h" -#include "util/rsdebug.h" -#include "util/rsthreads.h" - -class upnpentry -{ - public: - std::string name; - std::string id; - struct sockaddr_in addr; - unsigned int flags; - int status; - int lastTs; -}; - -class upnpforward -{ - public: - std::string name; - unsigned int flags; - struct sockaddr_in iaddr; - struct sockaddr_in eaddr; - int status; - int lastTs; -}; - - -#define RS_UPNP_S_UNINITIALISED 0 -#define RS_UPNP_S_UNAVAILABLE 1 -#define RS_UPNP_S_READY 2 -#define RS_UPNP_S_TCP_FAILED 3 -#define RS_UPNP_S_UDP_FAILED 4 -#define RS_UPNP_S_ACTIVE 5 - -class uPnPConfigData; - -class upnphandler: public pqiNetAssistFirewall -{ - public: - - upnphandler(); -virtual ~upnphandler(); - - /* External Interface (pqiNetAssistFirewall) */ -virtual void enable(bool active); -virtual void shutdown(); -virtual void restart(); - -virtual bool getEnabled(); -virtual bool getActive(); - -virtual void setInternalPort(unsigned short iport_in); -virtual void setExternalPort(unsigned short eport_in); -virtual bool getInternalAddress(struct sockaddr_storage &addr); -virtual bool getExternalAddress(struct sockaddr_storage &addr); - - /* TO IMPLEMENT: New Port Forward interface to support as many ports as necessary */ -virtual bool requestPortForward(const PortForwardParams &/*params*/) { return false; } -virtual bool statusPortForward(const uint32_t /*fwdId*/, PortForwardParams &/*params*/) { return false; } - -/* Public functions - for background thread operation, - * but effectively private from rest of RS, as in derived class - */ - -bool start_upnp(); -bool shutdown_upnp(); - -bool initUPnPState(); -bool printUPnPState(); - -private: - -bool background_setup_upnp(bool, bool); -bool checkUPnPActive(); - - /* Mutex for data below */ - RsMutex dataMtx; - - bool toEnable; /* overall on/off switch */ - bool toStart; /* if set start forwarding */ - bool toStop; /* if set stop forwarding */ - - unsigned short iport; - unsigned short eport; /* config */ - unsigned short eport_curr; /* current forwarded */ - - /* info from upnp */ - unsigned int upnpState; - uPnPConfigData *upnpConfig; - - struct sockaddr_in upnp_iaddr; - struct sockaddr_in upnp_eaddr; - - /* active port forwarding */ - std::list activeForwards; - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; diff --git a/libretroshare/src/rs_upnp/upnptest.cc b/libretroshare/src/rs_upnp/upnptest.cc deleted file mode 100644 index 80d98e4e5..000000000 --- a/libretroshare/src/rs_upnp/upnptest.cc +++ /dev/null @@ -1,86 +0,0 @@ -//this file use miniupnp - -#include - - -int main(int argc, char **argv) -{ - - int id = argc % 3; - - /********* - char *fhash1 = "3509426505463458576487"; - char *hash2 = "1549879882341985914515"; - char *hash3 = "8743598543269526505434"; - - int port1 = 8754; - int port2 = 2355; - int port3 = 6621; - **********/ - - std::cerr << "Starting dhttest Id: " << id << std::endl; -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - #ifdef PTW32_STATIC_LIB - pthread_win32_process_attach_np(); - #endif - - - upnphandler upnp; - - upnp.setInternalPort(12122); - - for(int i = 0; 1; i++) - { - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - sleep(1); -#else - - Sleep(1000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - if (i % 120 == 10) - { - /* start up a forward */ - upnp.enable(true); - - } - - if (i % 120 == 60) - { - /* shutdown a forward */ - upnp.restart(); - } - - if (i % 120 == 100) - { - /* shutdown a forward */ - upnp.shutdown(); - } - - } -} - diff --git a/libretroshare/src/rs_upnp/upnputil.cc b/libretroshare/src/rs_upnp/upnputil.cc deleted file mode 100644 index 28b0c4de6..000000000 --- a/libretroshare/src/rs_upnp/upnputil.cc +++ /dev/null @@ -1,611 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: upnputil.c * - * * - * libretroshare: retroshare core library * - * From MiniUPnPc, re-licensed with permission * - * * - * Copyright (c) 2005-2016, Thomas BERNARD * - * * - * 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 . * - * * - *******************************************************************************/ -//this file uses miniupnp -//From https://github.com/miniupnp/miniupnp/blob/master/miniupnpc/upnpc.c - -#include "rs_upnp/upnputil.h" - -#if MINIUPNPC_API_VERSION >= -4//1.0 2008/02/18 -#include "util/rstime.h" -#endif - -/* protofix() checks if protocol is "UDP" or "TCP" - * returns NULL if not */ -const char * protofix(const char * proto) -{ - static const char proto_tcp[4] = { 'T', 'C', 'P', 0}; - static const char proto_udp[4] = { 'U', 'D', 'P', 0}; - int i, b; - for(i=0, b=1; i<4; i++) - b = b && ( (proto[i] == proto_tcp[i]) - || (proto[i] == (proto_tcp[i] | 32)) ); - if(b) - return proto_tcp; - for(i=0, b=1; i<4; i++) - b = b && ( (proto[i] == proto_udp[i]) - || (proto[i] == (proto_udp[i] | 32)) ); - if(b) - return proto_udp; - return 0; -} - -void DisplayInfos(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - char externalIPAddress[40]; - char connectionType[64]; - char status[64]; - char lastconnerr[64]; - unsigned int uptime; - unsigned int brUp, brDown; - time_t timenow, timestarted; // Don't use rstime_t here or ctime break on windows - int r; -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - const char * servicetype = data->first.servicetype; - const char * servicetype_CIF = data->CIF.servicetype; -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - const char * servicetype = data->servicetype; - const char * servicetype_CIF = data->servicetype_CIF; -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif//>=-7 -#endif//>=-2 - -#if MINIUPNPC_API_VERSION >= -3//1.0 2009/04/17 - if(UPNP_GetConnectionTypeInfo(urls->controlURL, - servicetype, - connectionType) != UPNPCOMMAND_SUCCESS) -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - UPNP_GetConnectionTypeInfo(urls->controlURL, servicetype, - connectionType); - if(connectionType[0]) -#endif//>=-7 -#endif//>=-3 - printf("GetConnectionTypeInfo failed.\n"); - else - printf("Connection Type : %s\n", connectionType); - -#if MINIUPNPC_API_VERSION >= -4//1.0 2008/02/18 - if(UPNP_GetStatusInfo(urls->controlURL, servicetype, - status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS) - printf("GetStatusInfo failed.\n"); - else - printf("Status : %s, uptime=%us, LastConnectionError : %s\n", - status, uptime, lastconnerr); - timenow = time(NULL); - timestarted = timenow - uptime; - printf(" Time started : %s", ctime(×tarted)); -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - UPNP_GetStatusInfo(urls->controlURL, servicetype, - status, &uptime, lastconnerr); - printf("Status : %s, uptime=%u, LastConnectionError : %s\n", - status, uptime, lastconnerr); -#endif//>=-7 -#endif//>=-4 - -#if MINIUPNPC_API_VERSION >= -4//1.0 2008/02/18 - if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, servicetype_CIF, - &brDown, &brUp) != UPNPCOMMAND_SUCCESS) { - printf("GetLinkLayerMaxBitRates failed.\n"); - } else { - printf("MaxBitRateDown : %u bps", brDown); - if(brDown >= 1000000) { - printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10); - } else if(brDown >= 1000) { - printf(" (%u Kbps)", brDown / 1000); - } - printf(" MaxBitRateUp %u bps", brUp); - if(brUp >= 1000000) { - printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10); - } else if(brUp >= 1000) { - printf(" (%u Kbps)", brUp / 1000); - } - printf("\n"); - } -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, - servicetype_CIF, - &brDown, &brUp); - printf("MaxBitRateDown : %u bps MaxBitRateUp %u bps\n", brDown, brUp); -#endif//>=-7 -#endif//>=-4 - -#if MINIUPNPC_API_VERSION >= -5//1.0 2007/12/19 - r = UPNP_GetExternalIPAddress(urls->controlURL, - servicetype, - externalIPAddress); - if(r != UPNPCOMMAND_SUCCESS) { - printf("GetExternalIPAddress failed. (errorcode=%d)\n", r); - } else { - printf("ExternalIPAddress = %s\n", externalIPAddress); - } -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - UPNP_GetExternalIPAddress(urls->controlURL, - servicetype, - externalIPAddress); - if(externalIPAddress[0]) - printf("ExternalIPAddress = %s\n", externalIPAddress); - else - printf("GetExternalIPAddress failed.\n"); -#endif//>=-7 -#endif//>=-4 -} - -void GetConnectionStatus(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - unsigned int bytessent, bytesreceived, packetsreceived, packetssent; -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - const char * servicetype_CIF = data->CIF.servicetype; -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - const char * servicetype_CIF = data->servicetype_CIF; -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif//>=-7 -#endif//>=-2 - - DisplayInfos(urls, data); - bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, servicetype_CIF); - bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, servicetype_CIF); - packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, servicetype_CIF); - packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, servicetype_CIF); - printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); - printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); -} - -void ListRedirections(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - int r; - int i = 0; - char index[6]; - char intClient[40]; - char intPort[6]; - char extPort[6]; - char protocol[4]; - char desc[80]; - char enabled[6]; - char rHost[64]; - char duration[16]; -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - const char * servicetype = data->first.servicetype; -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - const char * servicetype = data->servicetype; -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif//>=-7 -#endif//>=-2 - - /*unsigned int num=0; - UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num); - printf("PortMappingNumberOfEntries : %u\n", num);*/ - do { - snprintf(index, 6, "%d", i); - rHost[0] = '\0'; enabled[0] = '\0'; - duration[0] = '\0'; desc[0] = '\0'; - extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0'; - r = UPNP_GetGenericPortMappingEntry(urls->controlURL, - servicetype, - index, - extPort, intClient, intPort, - protocol, desc, enabled, - rHost, duration); - if(r==0) - printf("%02d - %s %5s->%s:%-5s" - "\tenabled=%s leaseDuration=%s\n" - " desc='%s' rHost='%s'\n", - i, protocol, extPort, intClient, intPort, - enabled, duration, - desc, rHost); - else - printf("GetGenericPortMappingEntry() returned %d (%s)\n", - r, strupnperror(r)); - i++; - } while(r==0); -} - -/* Test function - * 1 - get connection type - * 2 - get extenal ip address - * 3 - Add port mapping - * 4 - get this port mapping from the IGD */ -int SetRedirectAndTest(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * iaddr, - const char * iport, - const char * eport, - const char * proto, - const char * leaseDuration, - const char * description, - int addAny) -{ - char externalIPAddress[40]; - char intClient[40]; - char intPort[6]; - char reservedPort[6]; - char duration[16]; - int r; - int ok = 1; -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - const char * servicetype = data->first.servicetype; -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - const char * servicetype = data->servicetype; -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif -#endif - - if(!iaddr || !iport || !eport || !proto) - { - fprintf(stderr, "Wrong arguments\n"); - return 0; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "invalid protocol\n"); - return 0; - } - -#if MINIUPNPC_API_VERSION >= -5//1.0 2007/12/19 - r = UPNP_GetExternalIPAddress(urls->controlURL, - servicetype, - externalIPAddress); - if(r != UPNPCOMMAND_SUCCESS) - printf("GetExternalIPAddress failed. (errorcode=%d)\n", r); - else - printf("ExternalIPAddress = %s\n", externalIPAddress); -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - UPNP_GetExternalIPAddress(urls->controlURL, - servicetype, - externalIPAddress); - if(externalIPAddress[0]) - printf("ExternalIPAddress = %s\n", externalIPAddress); - else - printf("GetExternalIPAddress failed.\n"); -#endif//>=-7 -#endif//>=-4 - -#if MINIUPNPC_API_VERSION >= 11 - if (addAny) { - r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype, - eport, iport, iaddr, description, - proto, 0, leaseDuration, reservedPort); - if(r==UPNPCOMMAND_SUCCESS) - eport = reservedPort; - else - printf("AddAnyPortMapping(%s, %s, %s) failed with code %d (%s)\n", - eport, iport, iaddr, r, strupnperror(r)); - } else -#endif - { -#if MINIUPNPC_API_VERSION >= -1 - /* $Id: upnpcommands.h,v 1.30 2015/07/15 12:21:28 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.20 2011/02/15 11:13:22 nanard Exp $ */ - //UPNP_AddPortMapping(const char * controlURL, const char * servicetype, - // const char * extPort, - // const char * inPort, - // const char * inClient, - // const char * desc, - // const char * proto, - // const char * remoteHost, - // const char * leaseDuration); - r = UPNP_AddPortMapping(urls->controlURL, servicetype, - eport, iport, iaddr, description, proto, NULL, NULL); -#else -#if MINIUPNPC_API_VERSION >= -3 //1.0 2009/04/17 - /* $Id: upnpcommands.h,v 1.18 2010/06/09 10:59:09 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.17 2009/04/17 21:21:19 nanard Exp $ */ - //UPNP_AddPortMapping(const char * controlURL, const char * servicetype, - // const char * extPort, - // const char * inPort, - // const char * inClient, - // const char * desc, - // const char * proto, - // const char * remoteHost); - r = UPNP_AddPortMapping(urls->controlURL, servicetype, - eport, iport, iaddr, description, proto, NULL); -#else -#if MINIUPNPC_API_VERSION >= -7//Before 1.0 - /* $Id: upnpcommands.h,v 1.14 2008/09/25 18:02:50 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.7 2006/07/09 12:00:54 nanard Exp $ */ - //UPNP_AddPortMapping(const char * controlURL, const char * servicetype, - // const char * extPort, - // const char * inPort, - // const char * inClient, - // const char * desc, - // const char * proto); - r = UPNP_AddPortMapping(urls->controlURL, servicetype, - eport, iport, iaddr, description, proto); -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif//>=-7 -#endif//>=-3 -#endif//>=-1 - -#if MINIUPNPC_API_VERSION >= -5//2007/12/19 - if(r!=UPNPCOMMAND_SUCCESS){ -#else -#if MINIUPNPC_API_VERSION >= -7//Before 1.0 - if(r==0){ -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif//>=-7 -#endif//>=-5 - printf("AddPortMapping(%s, %s, %s) failed and returns %d\n", eport, iport, iaddr, r); - //this seems to trigger for unknown reasons sometimes. - //rely on Checking it afterwards... - //should check IP address then! - ok = 0; - } - } - -#if MINIUPNPC_API_VERSION >= 10//1.0 2006/09/04 - /* $Id: upnpcommands.h,v 1.30 2015/07/15 12:21:28 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.26 2014/01/31 13:18:26 nanard Exp $ */ - //UPNP_GetSpecificPortMappingEntry(const char * controlURL, - // const char * servicetype, - // const char * extPort, - // const char * proto, - // const char * remoteHost, - // char * intClient, - // char * intPort, - // char * desc, - // char * enabled, - // char * leaseDuration); - r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, - data->first.servicetype, - eport, proto, NULL/*remoteHost*/, - intClient, intPort, NULL/*desc*/, - NULL/*enabled*/, duration); -#else -#if MINIUPNPC_API_VERSION >= 6//1.0 2006/09/04 - /* $Id: upnpcommands.h,v 1.24 2012/03/05 19:42:47 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.22 2011/03/14 13:36:01 nanard Exp $ */ - //UPNP_GetSpecificPortMappingEntry(const char * controlURL, - // const char * servicetype, - // const char * extPort, - // const char * proto, - // char * intClient, - // char * intPort, - // char * desc, - // char * enabled, - // char * leaseDuration); - r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, - data->first.servicetype, - eport, proto, - intClient, intPort, NULL/*desc*/, - NULL/*enabled*/, duration); -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - /* $Id: upnpcommands.h,v 1.20 2011/02/15 11:13:22 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.7 2006/07/09 12:00:54 nanard Exp $ */ - //UPNP_GetSpecificPortMappingEntry(const char * controlURL, - // const char * servicetype, - // const char * extPort, - // const char * proto, - // char * intClient, - // char * intPort); - UPNP_GetSpecificPortMappingEntry(urls->controlURL, - servicetype, - eport, - proto, - intClient, - intPort); - if(intClient[0]) r = UPNPCOMMAND_SUCCESS; -#endif//>=-7 -#endif//>=6 -#endif//>=10 - - if(r!=UPNPCOMMAND_SUCCESS) { - printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", - r, strupnperror(r)); - ok = 0; - } else if(intClient[0]) { - printf("InternalIP:Port = %s:%s\n", intClient, intPort); - printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n", - externalIPAddress, eport, proto, intClient, intPort, duration); - } - - if ((strcmp(iaddr, intClient) != 0) || (strcmp(iport, intPort) != 0)) - { - printf("PortMappingEntry to wrong location! FAILED\n"); - printf("IP1:\"%s\"\n", iaddr); - printf("IP2:\"%s\"\n", intClient); - printf("PORT1:\"%s\"\n", iport); - printf("PORT2:\"%s\"\n", intPort); - ok = 0; - } - - if (ok) - { - printf("uPnP Forward/Mapping Succeeded\n"); - } - else - { - printf("uPnP Forward/Mapping Failed\n"); - } - - return ok; -} - -int TestRedirect(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * iaddr, - const char * iport, - const char * eport, - const char * proto) -{ - char externalIPAddress[40]; - char intClient[40]; - char intPort[6]; - char duration[16]; - int r = 0; - int ok = 1; - - if(!iaddr || !iport || !eport || !proto) - { - fprintf(stderr, "Wrong arguments\n"); - return 0; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "invalid protocol\n"); - return 0; - } - -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - const char * servicetype = data->first.servicetype; -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - const char * servicetype = data->servicetype; -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif -#endif - -#if MINIUPNPC_API_VERSION >= 10//1.0 2006/09/04 - /* $Id: upnpcommands.h,v 1.30 2015/07/15 12:21:28 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.26 2014/01/31 13:18:26 nanard Exp $ */ - //UPNP_GetSpecificPortMappingEntry(const char * controlURL, - // const char * servicetype, - // const char * extPort, - // const char * proto, - // const char * remoteHost, - // char * intClient, - // char * intPort, - // char * desc, - // char * enabled, - // char * leaseDuration); - r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, - servicetype, - eport, proto, NULL/*remoteHost*/, - intClient, intPort, NULL/*desc*/, - NULL/*enabled*/, duration); -#else -#if MINIUPNPC_API_VERSION >= 6//1.0 2006/09/04 - /* $Id: upnpcommands.h,v 1.24 2012/03/05 19:42:47 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.22 2011/03/14 13:36:01 nanard Exp $ */ - //UPNP_GetSpecificPortMappingEntry(const char * controlURL, - // const char * servicetype, - // const char * extPort, - // const char * proto, - // char * intClient, - // char * intPort, - // char * desc, - // char * enabled, - // char * leaseDuration); - r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, - servicetype, - eport, proto, - intClient, intPort, NULL/*desc*/, - NULL/*enabled*/, duration); -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - /* $Id: upnpcommands.h,v 1.20 2011/02/15 11:13:22 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.7 2006/07/09 12:00:54 nanard Exp $ */ - //UPNP_GetSpecificPortMappingEntry(const char * controlURL, - // const char * servicetype, - // const char * extPort, - // const char * proto, - // char * intClient, - // char * intPort); - UPNP_GetSpecificPortMappingEntry(urls->controlURL, - servicetype, - eport, - proto, - intClient, - intPort); - if(intClient[0]) r = UPNPCOMMAND_SUCCESS; -#endif//>=-7 -#endif//>=6 -#endif//>=10 - - if(r!=UPNPCOMMAND_SUCCESS) { - printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", - r, strupnperror(r)); - ok = 0; - } else if(intClient[0]) { - printf("uPnP Check: InternalIP:Port = %s:%s\n", intClient, intPort); - printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n", - externalIPAddress, eport, proto, intClient, intPort, duration); - } - - if (ok) - { - printf("uPnP Check: uPnP Forward/Mapping still Active\n"); - } - else - { - printf("uPnP Check: Forward/Mapping has been Dropped\n"); - } - - return ok; -} - -int -RemoveRedirect(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * eport, - const char * proto) -{ - if(!proto || !eport) - { - fprintf(stderr, "invalid arguments\n"); - return 0; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "protocol invalid\n"); - return 0; - } -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, NULL); -#else -#if MINIUPNPC_API_VERSION >= -3//1.3 2009/04/17 - UPNP_DeletePortMapping(urls->controlURL, data->servicetype, eport, proto, NULL); -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - UPNP_DeletePortMapping(urls->controlURL, data->servicetype, eport, proto); -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif//>= -7 -#endif//>= -3 -#endif//>= -2 - - return 1; -} - - -/* EOF */ diff --git a/libretroshare/src/rs_upnp/upnputil.h b/libretroshare/src/rs_upnp/upnputil.h deleted file mode 100644 index 9586418a4..000000000 --- a/libretroshare/src/rs_upnp/upnputil.h +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: upnputil.h * - * * - * libretroshare: retroshare core library * - * From MiniUPnPc, re-licensed with permission * - * * - * Copyright (c) 2005-2016, Thomas BERNARD * - * * - * 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 . * - * * - *******************************************************************************/ - -//this file uses miniupnp - -#ifndef MINIUPNP_UTIL_H_ -#define MINIUPNP_UTIL_H_ - -#include -#include -#include -#ifdef WIN32 -#include -#define snprintf _snprintf -#endif -#include -#include -#include -#include - -//Define this variable follow the date of used MiniUPnP Library -//#define MINIUPNPC_API_VERSION -3 -#ifndef MINIUPNPC_API_VERSION -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version - //2006/09/04 to 2007/10/01 => -7//Start return struct UPNPDev * for upnpDiscover - //2007/10/16 => -6 upnpDiscover - //2007/12/19 => -5 upnpDiscover - //2008/09/25 => -4 upnpDiscover - //2009/04/17 => -3 UPNP_AddPortMapping - //2010/12/09 => -2 //struct IGDdatas_service CIF; - //2011/02/15 => -1 UPNP_AddPortMapping - //2011/03/14 => 6 //Start of MINIUPNPC_API_VERSION -#endif//>=-7 - -/* Ensure linking names are okay on OSX platform. (C interface) */ - -#ifdef __cplusplus -extern "C" { -#endif - - -/* protofix() checks if protocol is "UDP" or "TCP" - * returns NULL if not */ -const char * protofix(const char * proto); -void DisplayInfos(struct UPNPUrls * urls, - struct IGDdatas * data); - -void GetConnectionStatus(struct UPNPUrls * urls, - struct IGDdatas * data); - -void ListRedirections(struct UPNPUrls * urls, - struct IGDdatas * data); - -int SetRedirectAndTest(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * iaddr, - const char * iport, - const char * eport, - const char * proto, - const char *leaseDuration, - const char *description, - int addAny); - -int TestRedirect(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * iaddr, - const char * iport, - const char * eport, - const char * proto); - -int RemoveRedirect(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * eport, - const char * proto); - -#ifdef __cplusplus -} -#endif - -/* EOF */ -#endif diff --git a/libretroshare/src/rsitems/itempriorities.h b/libretroshare/src/rsitems/itempriorities.h deleted file mode 100644 index a376a9d64..000000000 --- a/libretroshare/src/rsitems/itempriorities.h +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsitempriorities.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include - -// This file centralises QoS priorities for all transfer RsItems -// -const uint8_t QOS_PRIORITY_UNKNOWN = 0 ; -const uint8_t QOS_PRIORITY_DEFAULT = 3 ; -const uint8_t QOS_PRIORITY_TOP = 9 ; - -// Turtle traffic -// -const uint8_t QOS_PRIORITY_RS_TURTLE_OPEN_TUNNEL = 7 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_TUNNEL_OK = 7 ; - -const uint8_t QOS_PRIORITY_RS_TURTLE_SEARCH_REQUEST = 6 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_REQUEST = 6 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_MAP_REQUEST = 6 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_CRC_REQUEST = 6 ; // unused -const uint8_t QOS_PRIORITY_RS_TURTLE_CHUNK_CRC_REQUEST = 6 ; // unused - -const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_DATA = 5 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_MAP = 6 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_CRC = 6 ; // unused -const uint8_t QOS_PRIORITY_RS_TURTLE_CHUNK_CRC = 6 ; // unused - -const uint8_t QOS_PRIORITY_RS_TURTLE_GENERIC_FAST_DATA = 7 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_SEARCH_RESULT = 6 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_GENERIC_DATA = 5 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_GENERIC_ITEM = 3 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_FORWARD_FILE_DATA = 3 ; // unused - -// File transfer -// -const uint8_t QOS_PRIORITY_RS_FILE_REQUEST = 6 ; -const uint8_t QOS_PRIORITY_RS_FILE_MAP_REQUEST = 6 ; -const uint8_t QOS_PRIORITY_RS_FILE_CRC_REQUEST = 6 ; // unused -const uint8_t QOS_PRIORITY_RS_CHUNK_CRC_REQUEST = 6 ; - -const uint8_t QOS_PRIORITY_RS_FILE_DATA = 5 ; -const uint8_t QOS_PRIORITY_RS_FILE_MAP = 6 ; -const uint8_t QOS_PRIORITY_RS_FILE_CRC = 6 ; // unused -const uint8_t QOS_PRIORITY_RS_CHUNK_CRC = 6 ; - -const uint8_t QOS_PRIORITY_RS_CACHE_ITEM = 3 ; // unused - -// Discovery -// -const uint8_t QOS_PRIORITY_RS_DISC_HEART_BEAT = 8 ; -const uint8_t QOS_PRIORITY_RS_DISC_ASK_INFO = 2 ; -const uint8_t QOS_PRIORITY_RS_DISC_REPLY = 2 ; -const uint8_t QOS_PRIORITY_RS_DISC_VERSION = 2 ; - -const uint8_t QOS_PRIORITY_RS_DISC_CONTACT = 2 ; // CONTACT and PGPLIST must have -const uint8_t QOS_PRIORITY_RS_DISC_PGP_LIST = 2 ; // same priority -const uint8_t QOS_PRIORITY_RS_DISC_SERVICES = 2 ; -const uint8_t QOS_PRIORITY_RS_DISC_PGP_CERT = 2 ; - -// File database -// -const uint8_t QOS_PRIORITY_RS_FAST_SYNC_REQUEST = 7 ; -const uint8_t QOS_PRIORITY_RS_SLOW_SYNC_REQUEST = 3 ; - -// Heartbeat -// -const uint8_t QOS_PRIORITY_RS_HEARTBEAT_PULSE = 8 ; - -// Chat/Msgs -// -const uint8_t QOS_PRIORITY_RS_CHAT_ITEM = 7 ; -const uint8_t QOS_PRIORITY_RS_CHAT_AVATAR_ITEM = 2 ; -const uint8_t QOS_PRIORITY_RS_MSG_ITEM = 2 ; // deprecated -const uint8_t QOS_PRIORITY_RS_MAIL_ITEM = 2 ; // new mail service -const uint8_t QOS_PRIORITY_RS_STATUS_ITEM = 2 ; - -// RTT -// -const uint8_t QOS_PRIORITY_RS_RTT_PING = 9 ; - -// BanList -// -const uint8_t QOS_PRIORITY_RS_BANLIST_ITEM = 3 ; - -// Bandwidth Control -// -const uint8_t QOS_PRIORITY_RS_BWCTRL_ALLOWED_ITEM = 9 ; - -// DsDv Routing -// -const uint8_t QOS_PRIORITY_RS_DSDV_ROUTE = 4 ; -const uint8_t QOS_PRIORITY_RS_DSDV_DATA = 2 ; - -// GXS -// -const uint8_t QOS_PRIORITY_RS_GXS_NET = 6 ; - -// GXS Reputation -// -const uint8_t QOS_PRIORITY_RS_GXSREPUTATION_ITEM = 3 ; - -// Service Info / Control -// -const uint8_t QOS_PRIORITY_RS_SERVICE_INFO_ITEM = 8 ; - diff --git a/libretroshare/src/rsitems/rsbanlistitems.cc b/libretroshare/src/rsitems/rsbanlistitems.cc deleted file mode 100644 index f283f5b43..000000000 --- a/libretroshare/src/rsitems/rsbanlistitems.cc +++ /dev/null @@ -1,67 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsbanlistitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rsbaseserial.h" -#include "rsitems/rsbanlistitems.h" - -#include "serialiser/rstypeserializer.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -/*************************************************************************/ - -void RsBanListItem::clear() -{ - peerList.TlvClear(); -} - -void RsBanListItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,peerList,"peerList") ; -} - -void RsBanListConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,banListType,"type") ; - RsTypeSerializer::serial_process (j,ctx,banListPeerId,"peerId") ; - RsTypeSerializer::serial_process (j,ctx,update_time,"update_time") ; - RsTypeSerializer::serial_process (j,ctx,banned_peers,"banned_peers") ; -} -RsItem *RsBanListSerialiser::create_item(uint16_t service_id,uint8_t item_sub_id) const -{ - if(service_id != RS_SERVICE_TYPE_BANLIST) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_BANLIST_CONFIG_ITEM: return new RsBanListConfigItem ; - case RS_PKT_SUBTYPE_BANLIST_ITEM: return new RsBanListItem ; - default: - std::cerr << "(EE) unknown item subtype " << (int)item_sub_id << " in RsBanListSerialiser::create_item()" << std::endl; - return NULL ; - } -} - - diff --git a/libretroshare/src/rsitems/rsbanlistitems.h b/libretroshare/src/rsitems/rsbanlistitems.h deleted file mode 100644 index 6422340af..000000000 --- a/libretroshare/src/rsitems/rsbanlistitems.h +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsbanlistitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_BANLIST_ITEMS_H -#define RS_BANLIST_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "rsitems/itempriorities.h" -#include "serialiser/rstlvbanlist.h" -#include "serialiser/rsserializer.h" - -#define RS_PKT_SUBTYPE_BANLIST_ITEM_deprecated 0x01 -#define RS_PKT_SUBTYPE_BANLIST_CONFIG_ITEM_deprecated 0x02 -#define RS_PKT_SUBTYPE_BANLIST_ITEM 0x03 -#define RS_PKT_SUBTYPE_BANLIST_CONFIG_ITEM 0x04 - -/**************************************************************************/ - -class RsBanListItem: public RsItem -{ - public: - RsBanListItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_BANLIST, RS_PKT_SUBTYPE_BANLIST_ITEM) - { - setPriorityLevel(QOS_PRIORITY_RS_BANLIST_ITEM); - return; - } - - virtual ~RsBanListItem(){} - virtual void clear(); - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsTlvBanList peerList; -}; - -class RsBanListConfigItem: public RsItem -{ -public: - RsBanListConfigItem() - : RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_BANLIST, RS_PKT_SUBTYPE_BANLIST_CONFIG_ITEM) - , banListType(0), update_time(0) - {} - - virtual ~RsBanListConfigItem(){} - virtual void clear() { banned_peers.TlvClear() ; } - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t banListType ; - RsPeerId banListPeerId ; - rstime_t update_time ; - RsTlvBanList banned_peers; -}; - -class RsBanListSerialiser: public RsServiceSerializer -{ -public: - RsBanListSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_BANLIST) {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_sub_id) const ; -}; - -/**************************************************************************/ - -#endif /* RS_BANLIST_ITEMS_H */ - - diff --git a/libretroshare/src/rsitems/rsbwctrlitems.cc b/libretroshare/src/rsitems/rsbwctrlitems.cc deleted file mode 100644 index 759264aa0..000000000 --- a/libretroshare/src/rsitems/rsbwctrlitems.cc +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsbwctrlitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rsbaseserial.h" -#include "rsitems/rsbwctrlitems.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -/*************************************************************************/ - -RsItem *RsBwCtrlSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const -{ - if(service != RS_SERVICE_TYPE_BWCTRL) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_BWCTRL_ALLOWED_ITEM: return new RsBwCtrlAllowedItem(); - default: - return NULL; - } -} - -void RsBwCtrlAllowedItem::clear() -{ - allowedBw = 0; -} - -void RsBwCtrlAllowedItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_UINT32_BW,allowedBw,"allowedBw") ; -} - - - diff --git a/libretroshare/src/rsitems/rsbwctrlitems.h b/libretroshare/src/rsitems/rsbwctrlitems.h deleted file mode 100644 index 300bd6f54..000000000 --- a/libretroshare/src/rsitems/rsbwctrlitems.h +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsbwctrlitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_BANDWIDTH_CONTROL_ITEMS_H -#define RS_BANDWIDTH_CONTROL_ITEMS_H - -#include - -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rsserializer.h" -#include "serialiser/rstypeserializer.h" - -#define RS_PKT_SUBTYPE_BWCTRL_ALLOWED_ITEM 0x01 - -/**************************************************************************/ - -class RsBwCtrlAllowedItem: public RsItem -{ -public: - RsBwCtrlAllowedItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_BWCTRL, RS_PKT_SUBTYPE_BWCTRL_ALLOWED_ITEM) - { - setPriorityLevel(QOS_PRIORITY_RS_BWCTRL_ALLOWED_ITEM); - return; - } - - virtual ~RsBwCtrlAllowedItem() {} - virtual void clear(); - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t allowedBw; // Units are bytes/sec => 4Gb/s; -}; - - -class RsBwCtrlSerialiser: public RsServiceSerializer -{ -public: - RsBwCtrlSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_BWCTRL) {} - virtual ~RsBwCtrlSerialiser() {} - - RsItem *create_item(uint16_t /* service */, uint8_t /* item_sub_id */) const; -}; - -/**************************************************************************/ - -#endif /* RS_BANDWIDTH_CONTROL_ITEMS_H */ - diff --git a/libretroshare/src/rsitems/rsconfigitems.cc b/libretroshare/src/rsitems/rsconfigitems.cc deleted file mode 100644 index 654d1a7f6..000000000 --- a/libretroshare/src/rsitems/rsconfigitems.cc +++ /dev/null @@ -1,239 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsconfigitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rsbaseserial.h" -#include "rsitems/rsconfigitems.h" -#include "retroshare/rspeers.h" // Needed for RsGroupInfo. - -#include "serialiser/rsserializable.h" -#include "serialiser/rstypeserializer.h" -/*** - * #define RSSERIAL_DEBUG 1 - * #define RSSERIAL_ERROR_DEBUG 1 - ***/ - -#define RSSERIAL_ERROR_DEBUG 1 - -#include - - -/*************************************************************************/ - -RsItem *RsFileConfigSerialiser::create_item(uint8_t item_type,uint8_t item_subtype) const -{ - if(item_type != RS_PKT_TYPE_FILE_CONFIG) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_FILE_TRANSFER: return new RsFileTransfer() ; - case RS_PKT_SUBTYPE_FILE_ITEM: return new RsFileConfigItem() ; - default: - return NULL ; - } -} -void RsFileTransfer::clear() -{ - - file.TlvClear(); - allPeerIds.TlvClear(); - cPeerId.clear() ; - state = 0; - in = false; - transferred = 0; - crate = 0; - trate = 0; - lrate = 0; - ltransfer = 0; - -} - -void RsFileTransfer::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,file,"file") ; - RsTypeSerializer::serial_process(j,ctx,allPeerIds,"allPeerIds") ; - - RsTypeSerializer::serial_process (j,ctx,cPeerId,"cPeerId") ; - - RsTypeSerializer::serial_process (j,ctx,state,"state") ; - RsTypeSerializer::serial_process (j,ctx,in,"in") ; - - RsTypeSerializer::serial_process (j,ctx,transferred,"transferred") ; - - RsTypeSerializer::serial_process (j,ctx,crate,"crate") ; - RsTypeSerializer::serial_process (j,ctx,trate,"trate") ; - RsTypeSerializer::serial_process (j,ctx,lrate,"lrate") ; - RsTypeSerializer::serial_process (j,ctx,ltransfer,"ltransfer") ; - - RsTypeSerializer::serial_process (j,ctx,flags,"flags") ; - RsTypeSerializer::serial_process (j,ctx,chunk_strategy,"chunk_strategy") ; - RS_SERIAL_PROCESS(compressed_chunk_map); -} - -void RsFileConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,file,"file") ; - RsTypeSerializer::serial_process (j,ctx,flags,"flags") ; - RsTypeSerializer::serial_process(j,ctx,parent_groups,"parent_groups") ; -} - -RsItem *RsGeneralConfigSerialiser::create_item(uint8_t item_type,uint8_t item_subtype) const -{ - if(item_type != RS_PKT_TYPE_GENERAL_CONFIG) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_KEY_VALUE: return new RsConfigKeyValueSet(); - default: - return NULL ; - } -} - -void RsConfigKeyValueSet::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tlvkvs,"tlvkvs") ; -} - -RsItem *RsPeerConfigSerialiser::create_item(uint8_t item_type,uint8_t item_subtype) const -{ - if(item_type != RS_PKT_TYPE_PEER_CONFIG) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_PEER_NET: return new RsPeerNetItem(); - case RS_PKT_SUBTYPE_PEER_STUN: return new RsPeerStunItem(); - case RS_PKT_SUBTYPE_NODE_GROUP: return new RsNodeGroupItem() ; - case RS_PKT_SUBTYPE_PEER_PERMISSIONS: return new RsPeerServicePermissionItem(); - case RS_PKT_SUBTYPE_PEER_BANDLIMITS: return new RsPeerBandwidthLimitsItem(); - default: - return NULL ; - } -} - -void RsPeerNetItem::clear() -{ - nodePeerId.clear(); - pgpId.clear(); - location.clear(); - netMode = 0; - vs_disc = 0; - vs_dht = 0; - lastContact = 0; - - localAddrV4.TlvClear(); - extAddrV4.TlvClear(); - localAddrV6.TlvClear(); - extAddrV6.TlvClear(); - - dyndns.clear(); - - localAddrList.TlvClear(); - extAddrList.TlvClear(); - - domain_addr.clear(); - domain_port = 0; -} -void RsPeerNetItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,nodePeerId,"peerId") ; - RsTypeSerializer::serial_process(j,ctx,pgpId,"pgpId") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_LOCATION,location,"location") ; - - RsTypeSerializer::serial_process(j,ctx,netMode,"netMode") ; - RsTypeSerializer::serial_process(j,ctx,vs_disc,"vs_disc") ; - RsTypeSerializer::serial_process(j,ctx,vs_dht,"vs_dht") ; - RsTypeSerializer::serial_process(j,ctx,lastContact,"lastContact") ; - - RsTypeSerializer::serial_process(j,ctx,localAddrV4,"localAddrV4") ; - RsTypeSerializer::serial_process(j,ctx,extAddrV4,"extAddrV4") ; - RsTypeSerializer::serial_process(j,ctx,localAddrV6,"localAddrV6") ; - RsTypeSerializer::serial_process(j,ctx,extAddrV6,"extAddrV6") ; - - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DYNDNS,dyndns,"dyndns") ; - - RsTypeSerializer::serial_process(j,ctx,localAddrList,"localAddrList") ; - RsTypeSerializer::serial_process(j,ctx,extAddrList,"extAddrList") ; - - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DOMADDR,domain_addr,"domain_addr") ; - RsTypeSerializer::serial_process(j,ctx,domain_port,"domain_port") ; -} - -void RsPeerBandwidthLimitsItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,peers,"peers") ; -} - -void RsPeerStunItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,stunList,"stunList") ; -} - - -RsNodeGroupItem::RsNodeGroupItem(const RsGroupInfo& g) - :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PEER_CONFIG, RS_PKT_SUBTYPE_NODE_GROUP) -{ - id = g.id ; - name = g.name ; - flag = g.flag ; - pgpList.ids = g.peerIds; -} - -void RsNodeGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - uint32_t v=0 ; - - RsTypeSerializer::serial_process(j,ctx,v,"dummy field 0") ; - RsTypeSerializer::serial_process (j,ctx,id,"id") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,name,"name") ; - RsTypeSerializer::serial_process(j,ctx,flag,"flag") ; - RsTypeSerializer::serial_process(j,ctx,pgpList,"pgpList") ; -} - -void RsPeerServicePermissionItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - // We need to hack this because of backward compatibility. The correct way to do it would be: - // - // RsTypeSerializer::serial_process(j,ctx,pgp_ids,"pgp_ids") ; - // RsTypeSerializer::serial_process(j,ctx,service_flags,"service_flags") ; - - if(j == RsGenericSerializer::DESERIALIZE) - { - uint32_t v=0 ; - RsTypeSerializer::serial_process(j,ctx,v,"pgp_ids.size()") ; - - pgp_ids.resize(v) ; - service_flags.resize(v) ; - } - else - { - uint32_t s = pgp_ids.size(); - RsTypeSerializer::serial_process(j,ctx,s,"pgp_ids.size()") ; - } - - for(uint32_t i=0;i * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_CONFIG_ITEMS_SERIALISER_H -#define RS_CONFIG_ITEMS_SERIALISER_H - -#include -#include - -#include "rsitems/rsitem.h" - -#include "retroshare/rstypes.h" -#include "serialiser/rsserial.h" - -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rstlvkeyvalue.h" -#include "serialiser/rstlvaddrs.h" - -#include "serialiser/rsserializer.h" - -struct RsGroupInfo; - -const uint8_t RS_PKT_TYPE_GENERAL_CONFIG = 0x01; -const uint8_t RS_PKT_TYPE_PEER_CONFIG = 0x02; -const uint8_t RS_PKT_TYPE_CACHE_CONFIG = 0x03; -const uint8_t RS_PKT_TYPE_FILE_CONFIG = 0x04; -const uint8_t RS_PKT_TYPE_PLUGIN_CONFIG = 0x05; -const uint8_t RS_PKT_TYPE_HISTORY_CONFIG = 0x06; - - /* GENERAL CONFIG SUBTYPES */ -const uint8_t RS_PKT_SUBTYPE_KEY_VALUE = 0x01; - - /* PEER CONFIG SUBTYPES */ -const uint8_t RS_PKT_SUBTYPE_PEER_STUN = 0x02; -const uint8_t RS_PKT_SUBTYPE_PEER_NET = 0x03; -const uint8_t RS_PKT_SUBTYPE_PEER_GROUP_deprecated = 0x04; -const uint8_t RS_PKT_SUBTYPE_PEER_PERMISSIONS = 0x05; -const uint8_t RS_PKT_SUBTYPE_PEER_BANDLIMITS = 0x06; -const uint8_t RS_PKT_SUBTYPE_NODE_GROUP = 0x07; - - /* FILE CONFIG SUBTYPES */ -const uint8_t RS_PKT_SUBTYPE_FILE_TRANSFER = 0x01; -const uint8_t RS_PKT_SUBTYPE_FILE_ITEM_deprecated = 0x02; -const uint8_t RS_PKT_SUBTYPE_FILE_ITEM = 0x03; - -/**************************************************************************/ - -class RsPeerNetItem: public RsItem -{ -public: - RsPeerNetItem() - :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, - RS_PKT_TYPE_PEER_CONFIG, - RS_PKT_SUBTYPE_PEER_NET) - , netMode(0), vs_disc(0), vs_dht(0), lastContact(0), domain_port(0) - {} - - virtual ~RsPeerNetItem(){} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - /* networking information */ - RsPeerId nodePeerId; /* Mandatory */ - RsPgpId pgpId; /* Mandatory */ - std::string location; /* Mandatory */ - uint32_t netMode; /* Mandatory */ - uint16_t vs_disc; /* Mandatory */ - uint16_t vs_dht; /* Mandatory */ - uint32_t lastContact; /* Mandatory */ - - RsTlvIpAddress localAddrV4; /* Mandatory */ - RsTlvIpAddress extAddrV4; /* Mandatory */ - RsTlvIpAddress localAddrV6; /* Mandatory */ - RsTlvIpAddress extAddrV6; /* Mandatory */ - - std::string dyndns; - - RsTlvIpAddrSet localAddrList; - RsTlvIpAddrSet extAddrList; - - // for proxy connection. - std::string domain_addr; - uint16_t domain_port; -}; - -// This item should be merged with the next item, but that is not backward compatible. -class RsPeerServicePermissionItem : public RsItem -{ - public: - RsPeerServicePermissionItem() : RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PEER_CONFIG, RS_PKT_SUBTYPE_PEER_PERMISSIONS) {} - virtual ~RsPeerServicePermissionItem() {} - - virtual void clear() - { - pgp_ids.clear() ; - service_flags.clear() ; - } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - - /* Mandatory */ - std::vector pgp_ids ; - std::vector service_flags ; -}; -class RsPeerBandwidthLimitsItem : public RsItem -{ - public: - RsPeerBandwidthLimitsItem() : RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PEER_CONFIG, RS_PKT_SUBTYPE_PEER_BANDLIMITS) {} - virtual ~RsPeerBandwidthLimitsItem() {} - - virtual void clear() - { - peers.clear() ; - } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - /* Mandatory */ - std::map peers ; -}; - -class RsNodeGroupItem: public RsItem -{ -public: - RsNodeGroupItem(): RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PEER_CONFIG, RS_PKT_SUBTYPE_NODE_GROUP), flag(0) {} - virtual ~RsNodeGroupItem() {} - - virtual void clear() { pgpList.TlvClear();} - - explicit RsNodeGroupItem(const RsGroupInfo&) ; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // /* set data from RsGroupInfo to RsPeerGroupItem */ - // void set(RsGroupInfo &groupInfo); - // /* get data from RsGroupInfo to RsPeerGroupItem */ - // void get(RsGroupInfo &groupInfo); - - /* Mandatory */ - RsNodeGroupId id; - std::string name; - uint32_t flag; - - RsTlvPgpIdSet pgpList; -}; - -class RsPeerStunItem: public RsItem -{ -public: - RsPeerStunItem() - :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, - RS_PKT_TYPE_PEER_CONFIG, - RS_PKT_SUBTYPE_PEER_STUN) {} - virtual ~RsPeerStunItem(){} - virtual void clear() { stunList.TlvClear() ;} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsTlvPeerIdSet stunList; /* Mandatory */ -}; - -class RsPeerConfigSerialiser: public RsConfigSerializer -{ - public: - RsPeerConfigSerialiser() :RsConfigSerializer(RS_PKT_CLASS_CONFIG,RS_PKT_TYPE_PEER_CONFIG) {} - - virtual ~RsPeerConfigSerialiser(){} - - virtual RsItem *create_item(uint8_t item_type, uint8_t item_subtype) const ; -}; - -/**************************************************************************/ - -class RsFileTransfer: public RsItem -{ - public: - RsFileTransfer() :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_FILE_CONFIG, RS_PKT_SUBTYPE_FILE_TRANSFER) - { - state = 0; - in = 0; - transferred = 0; - crate = 0; - trate = 0; - lrate = 0; - ltransfer = 0; - flags = 0; - chunk_strategy = 0; - } - virtual ~RsFileTransfer(){} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsTlvFileItem file; - RsTlvPeerIdSet allPeerIds; - - RsPeerId cPeerId; - - uint16_t state; - uint16_t in; - - uint64_t transferred; - uint32_t crate; - uint32_t trate; - - uint32_t lrate; - uint32_t ltransfer; - - // chunk information - uint32_t flags ; - uint32_t chunk_strategy ; // strategy flags for chunks - CompressedChunkMap compressed_chunk_map ; // chunk availability (bitwise) -}; - -/**************************************************************************/ - -const uint32_t RS_FILE_CONFIG_CLEANUP_DELETE = 0x0001; - -class RsFileConfigItem: public RsItem -{ -public: - RsFileConfigItem() :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_FILE_CONFIG, RS_PKT_SUBTYPE_FILE_ITEM), flags(0) {} - virtual ~RsFileConfigItem() {} - virtual void clear() { parent_groups.TlvClear(); } - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsTlvFileItem file; - uint32_t flags; - RsTlvNodeGroupIdSet parent_groups ; -}; -/**************************************************************************/ - -class RsFileConfigSerialiser: public RsConfigSerializer -{ - public: - RsFileConfigSerialiser() :RsConfigSerializer(RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_FILE_CONFIG) { } - virtual ~RsFileConfigSerialiser() {} - - virtual RsItem *create_item(uint8_t item_type, uint8_t item_subtype) const ; -}; - -/**************************************************************************/ - -/* Config items that are used generally */ - -class RsConfigKeyValueSet: public RsItem -{ -public: - RsConfigKeyValueSet() :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_GENERAL_CONFIG, RS_PKT_SUBTYPE_KEY_VALUE) {} - virtual ~RsConfigKeyValueSet(){} - virtual void clear() { tlvkvs.TlvClear();} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsTlvKeyValueSet tlvkvs; -}; - - -class RsGeneralConfigSerialiser: public RsConfigSerializer -{ - public: - RsGeneralConfigSerialiser() :RsConfigSerializer(RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_GENERAL_CONFIG) {} - - virtual RsItem *create_item(uint8_t item_type, uint8_t item_subtype) const ; -}; - -#endif /* RS_CONFIG_ITEMS_SERIALISER_H */ diff --git a/libretroshare/src/rsitems/rsfiletransferitems.cc b/libretroshare/src/rsitems/rsfiletransferitems.cc deleted file mode 100644 index 3c34acf6a..000000000 --- a/libretroshare/src/rsitems/rsfiletransferitems.cc +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsfiletransferitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" -#include "rsitems/rsfiletransferitems.h" - -#include "serialiser/rstypeserializer.h" - -/*** - * #define RSSERIAL_DEBUG 1 - * #define DEBUG_TRANSFERS 1 -***/ - - -#ifdef DEBUG_TRANSFERS - #include "util/rsprint.h" -#endif - -#include - -void RsFileTransferDataRequestItem::clear() -{ - file.TlvClear(); - fileoffset = 0; - chunksize = 0; -} -void RsFileTransferDataItem::clear() -{ - fd.TlvClear(); -} - -void RsFileTransferDataRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,fileoffset,"fileoffset") ; - RsTypeSerializer::serial_process (j,ctx,chunksize, "chunksize") ; - RsTypeSerializer::serial_process(j,ctx,file, "file") ; -} - -void RsFileTransferDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,fd,"fd") ; -} - -void RsFileTransferChunkMapRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,is_client,"is_client") ; - RsTypeSerializer::serial_process (j,ctx,hash, "hash") ; -} - -void RsFileTransferChunkMapItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,is_client, "is_client") ; - RsTypeSerializer::serial_process (j,ctx,hash, "hash") ; - RsTypeSerializer::serial_process (j,ctx,compressed_map,"compressed_map") ; -} - -void RsFileTransferSingleChunkCrcRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,hash, "hash") ; - RsTypeSerializer::serial_process(j,ctx,chunk_number,"chunk_number") ; -} - -void RsFileTransferSingleChunkCrcItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,hash, "hash") ; - RsTypeSerializer::serial_process(j,ctx,chunk_number,"chunk_number") ; - RsTypeSerializer::serial_process (j,ctx,check_sum, "check_sum") ; -} - -//===================================================================================================// -// Serializer // -//===================================================================================================// - -RsItem *RsFileTransferSerialiser::create_item(uint16_t service_type,uint8_t item_type) const -{ - if(service_type != RS_SERVICE_TYPE_FILE_TRANSFER) - return NULL ; - - switch(item_type) - { - case RS_PKT_SUBTYPE_FT_DATA_REQUEST : return new RsFileTransferDataRequestItem(); - case RS_PKT_SUBTYPE_FT_DATA : return new RsFileTransferDataItem(); - case RS_PKT_SUBTYPE_FT_CHUNK_MAP_REQUEST : return new RsFileTransferChunkMapRequestItem(); - case RS_PKT_SUBTYPE_FT_CHUNK_MAP : return new RsFileTransferChunkMapItem(); - case RS_PKT_SUBTYPE_FT_CHUNK_CRC_REQUEST : return new RsFileTransferSingleChunkCrcRequestItem(); - case RS_PKT_SUBTYPE_FT_CHUNK_CRC : return new RsFileTransferSingleChunkCrcItem() ; - default: - return NULL ; - } -} diff --git a/libretroshare/src/rsitems/rsfiletransferitems.h b/libretroshare/src/rsitems/rsfiletransferitems.h deleted file mode 100644 index 60514e41f..000000000 --- a/libretroshare/src/rsitems/rsfiletransferitems.h +++ /dev/null @@ -1,189 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsfiletransferitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include "retroshare/rstypes.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvfileitem.h" -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rsserializer.h" - -const uint8_t RS_PKT_SUBTYPE_FT_DATA_REQUEST = 0x01; -const uint8_t RS_PKT_SUBTYPE_FT_DATA = 0x02; -const uint8_t RS_PKT_SUBTYPE_FT_CHUNK_MAP_REQUEST = 0x04; -const uint8_t RS_PKT_SUBTYPE_FT_CHUNK_MAP = 0x05; -const uint8_t RS_PKT_SUBTYPE_FT_CHUNK_CRC_REQUEST = 0x08; -const uint8_t RS_PKT_SUBTYPE_FT_CHUNK_CRC = 0x09; - -const uint8_t RS_PKT_SUBTYPE_FT_CACHE_ITEM = 0x0A; -const uint8_t RS_PKT_SUBTYPE_FT_CACHE_REQUEST = 0x0B; - -//const uint8_t RS_PKT_SUBTYPE_FT_TRANSFER = 0x03; -//const uint8_t RS_PKT_SUBTYPE_FT_CRC32_MAP_REQUEST = 0x06; -//const uint8_t RS_PKT_SUBTYPE_FT_CRC32_MAP = 0x07; - -/**************************************************************************/ - -class RsFileTransferItem: public RsItem -{ - public: - RsFileTransferItem(uint8_t ft_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_FILE_TRANSFER,ft_subtype) {} - - virtual ~RsFileTransferItem() {} - - virtual void clear() = 0 ; -}; - -class RsFileTransferDataRequestItem: public RsFileTransferItem -{ - public: - RsFileTransferDataRequestItem() :RsFileTransferItem(RS_PKT_SUBTYPE_FT_DATA_REQUEST) - { - setPriorityLevel(QOS_PRIORITY_RS_FILE_REQUEST) ; - } - virtual ~RsFileTransferDataRequestItem() {} - virtual void clear(); - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // Private data part. - // - uint64_t fileoffset; /* start of data requested */ - uint32_t chunksize; /* size of data requested */ - RsTlvFileItem file; /* file information */ -}; - -/**************************************************************************/ - -class RsFileTransferDataItem: public RsFileTransferItem -{ - public: - RsFileTransferDataItem() :RsFileTransferItem(RS_PKT_SUBTYPE_FT_DATA) - { - setPriorityLevel(QOS_PRIORITY_RS_FILE_DATA) ; - } - virtual ~RsFileTransferDataItem() { clear() ; } - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - virtual void clear(); - - // Private data part. - // - RsTlvFileData fd; -}; - -class RsFileTransferChunkMapRequestItem: public RsFileTransferItem -{ - public: - RsFileTransferChunkMapRequestItem() :RsFileTransferItem(RS_PKT_SUBTYPE_FT_CHUNK_MAP_REQUEST) - { - setPriorityLevel(QOS_PRIORITY_RS_FILE_MAP_REQUEST) ; - } - virtual ~RsFileTransferChunkMapRequestItem() {} - virtual void clear() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // Private data part. - // - bool is_client ; // is the request for a client, or a server ? - RsFileHash hash ; // hash of the file for which we request the chunk map -}; - -class RsFileTransferChunkMapItem: public RsFileTransferItem -{ - public: - RsFileTransferChunkMapItem() - :RsFileTransferItem(RS_PKT_SUBTYPE_FT_CHUNK_MAP) - { - setPriorityLevel(QOS_PRIORITY_RS_FILE_MAP) ; - } - virtual ~RsFileTransferChunkMapItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - virtual void clear() {} - - // Private data part. - // - bool is_client ; // is the request for a client, or a server ? - RsFileHash hash ; // hash of the file for which we request the chunk map - CompressedChunkMap compressed_map ; // Chunk map of the file. -}; - -class RsFileTransferSingleChunkCrcRequestItem: public RsFileTransferItem -{ - public: - RsFileTransferSingleChunkCrcRequestItem() :RsFileTransferItem(RS_PKT_SUBTYPE_FT_CHUNK_CRC_REQUEST) - { - setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC_REQUEST) ; - } - virtual ~RsFileTransferSingleChunkCrcRequestItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - virtual void clear() {} - - // Private data part. - // - RsFileHash hash ; // hash of the file for which we request the crc - uint32_t chunk_number ; // chunk number -}; - -class RsFileTransferSingleChunkCrcItem: public RsFileTransferItem -{ - public: - RsFileTransferSingleChunkCrcItem() :RsFileTransferItem(RS_PKT_SUBTYPE_FT_CHUNK_CRC) - { - setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC) ; - } - virtual ~RsFileTransferSingleChunkCrcItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - virtual void clear() {} - - // Private data part. - // - RsFileHash hash ; // hash of the file for which we request the chunk map - uint32_t chunk_number ; - Sha1CheckSum check_sum ; // CRC32 map of the file. -}; - -/**************************************************************************/ - -class RsFileTransferSerialiser: public RsServiceSerializer -{ - public: - RsFileTransferSerialiser(): RsServiceSerializer(RS_SERVICE_TYPE_FILE_TRANSFER) {} - - virtual ~RsFileTransferSerialiser() {} - - RsItem *create_item(uint16_t service_type,uint8_t item_type) const ; - -}; - -/**************************************************************************/ - diff --git a/libretroshare/src/rsitems/rsgxschannelitems.cc b/libretroshare/src/rsitems/rsgxschannelitems.cc deleted file mode 100644 index 9ef37d746..000000000 --- a/libretroshare/src/rsitems/rsgxschannelitems.cc +++ /dev/null @@ -1,169 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxschannelitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include - -#include "rsgxschannelitems.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" - -#include "serialiser/rstypeserializer.h" - -RsItem *RsGxsChannelSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) const -{ - if(service_id != RS_SERVICE_GXS_TYPE_CHANNELS) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_GXSCHANNEL_GROUP_ITEM: return new RsGxsChannelGroupItem() ; - case RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM: return new RsGxsChannelPostItem(); - default: - return RsGxsCommentSerialiser::create_item(service_id,item_subtype) ; - } -} - -void RsGxsChannelGroupItem::clear() -{ - mDescription.clear(); - mImage.TlvClear(); -} - -bool RsGxsChannelGroupItem::fromChannelGroup(RsGxsChannelGroup &group, bool moveImage) -{ - clear(); - meta = group.mMeta; - mDescription = group.mDescription; - - if (moveImage) - { - mImage.binData.bin_data = group.mImage.mData; - mImage.binData.bin_len = group.mImage.mSize; - group.mImage.shallowClear(); - } - else - { - mImage.binData.setBinData(group.mImage.mData, group.mImage.mSize); - } - return true; -} - - - -bool RsGxsChannelGroupItem::toChannelGroup(RsGxsChannelGroup &group, bool moveImage) -{ - group.mMeta = meta; - group.mDescription = mDescription; - if (moveImage) - { - group.mImage.take((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); - // mImage doesn't have a ShallowClear at the moment! - mImage.binData.TlvShallowClear(); - } - else - { - group.mImage.copy((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); - } - return true; -} - -void RsGxsChannelGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_DESCR,mDescription,"mDescription") ; - RsTypeSerializer::serial_process(j,ctx,mImage,"mImage") ; -} - -bool RsGxsChannelPostItem::fromChannelPost(RsGxsChannelPost &post, bool moveImage) -{ - clear(); - meta = post.mMeta; - mMsg = post.mMsg; - - if (moveImage) - { - mThumbnail.binData.bin_data = post.mThumbnail.mData; - mThumbnail.binData.bin_len = post.mThumbnail.mSize; - post.mThumbnail.shallowClear(); - } - else - { - mThumbnail.binData.setBinData(post.mThumbnail.mData, post.mThumbnail.mSize); - } - - std::list::iterator fit; - for(fit = post.mFiles.begin(); fit != post.mFiles.end(); ++fit) - { - RsTlvFileItem fi; - fi.name = fit->mName; - fi.filesize = fit->mSize; - fi.hash = fit->mHash; - mAttachment.items.push_back(fi); - } - return true; -} - - - -bool RsGxsChannelPostItem::toChannelPost(RsGxsChannelPost &post, bool moveImage) -{ - post.mMeta = meta; - post.mMsg = mMsg; - if (moveImage) - { - post.mThumbnail.take((uint8_t *) mThumbnail.binData.bin_data, mThumbnail.binData.bin_len); - // mThumbnail doesn't have a ShallowClear at the moment! - mThumbnail.binData.TlvShallowClear(); - } - else - { - post.mThumbnail.copy((uint8_t *) mThumbnail.binData.bin_data, mThumbnail.binData.bin_len); - } - - post.mAttachmentCount = 0; - post.mSize = 0; - std::list::iterator fit; - for(fit = mAttachment.items.begin(); fit != mAttachment.items.end(); ++fit) - { - RsGxsFile fi; - fi.mName = RsDirUtil::getTopDir(fit->name); - fi.mSize = fit->filesize; - fi.mHash = fit->hash; - - post.mFiles.push_back(fi); - post.mAttachmentCount++; - post.mSize += fi.mSize; - } - return true; -} - -void RsGxsChannelPostItem::clear() -{ - mMsg.clear(); - mAttachment.TlvClear(); - mThumbnail.TlvClear(); -} - -void RsGxsChannelPostItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_MSG,mMsg,"mMsg") ; - RsTypeSerializer::serial_process(j,ctx,mAttachment,"mAttachment") ; - RsTypeSerializer::serial_process(j,ctx,mThumbnail,"mThumbnail") ; -} diff --git a/libretroshare/src/rsitems/rsgxschannelitems.h b/libretroshare/src/rsitems/rsgxschannelitems.h deleted file mode 100644 index fa52c8cfc..000000000 --- a/libretroshare/src/rsitems/rsgxschannelitems.h +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxschannelitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_GXS_CHANNEL_ITEMS_H -#define RS_GXS_CHANNEL_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsgxscommentitems.h" -#include "rsitems/rsgxsitems.h" - -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rstlvimage.h" - -#include "retroshare/rsgxschannels.h" - -#include "serialiser/rsserializer.h" - -#include "util/rsdir.h" - -const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_GROUP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM = 0x03; - -class RsGxsChannelGroupItem : public RsGxsGrpItem -{ -public: - - RsGxsChannelGroupItem(): RsGxsGrpItem(RS_SERVICE_GXS_TYPE_CHANNELS, RS_PKT_SUBTYPE_GXSCHANNEL_GROUP_ITEM) {} - virtual ~RsGxsChannelGroupItem() {} - - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // use conversion functions to transform: - bool fromChannelGroup(RsGxsChannelGroup &group, bool moveImage); - bool toChannelGroup(RsGxsChannelGroup &group, bool moveImage); - - std::string mDescription; - RsTlvImage mImage; -}; - -class RsGxsChannelPostItem : public RsGxsMsgItem -{ -public: - - RsGxsChannelPostItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_CHANNELS, RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM) {} - virtual ~RsGxsChannelPostItem() {} - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // Slightly unusual structure. - // use conversion functions to transform: - bool fromChannelPost(RsGxsChannelPost &post, bool moveImage); - bool toChannelPost(RsGxsChannelPost &post, bool moveImage); - - std::string mMsg; - RsTlvFileSet mAttachment; - RsTlvImage mThumbnail; -}; - - -class RsGxsChannelSerialiser : public RsGxsCommentSerialiser -{ -public: - - RsGxsChannelSerialiser() :RsGxsCommentSerialiser(RS_SERVICE_GXS_TYPE_CHANNELS) {} - virtual ~RsGxsChannelSerialiser() {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ; -}; - -#endif /* RS_GXS_CHANNEL_ITEMS_H */ diff --git a/libretroshare/src/rsitems/rsgxscircleitems.cc b/libretroshare/src/rsitems/rsgxscircleitems.cc deleted file mode 100644 index f93068b5b..000000000 --- a/libretroshare/src/rsitems/rsgxscircleitems.cc +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxscircleitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include - -#include "rsgxscircleitems.h" - -#include "serialiser/rstypeserializer.h" - -//#define CIRCLE_DEBUG 1 - -RsItem *RsGxsCircleSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const -{ - if(service != RS_SERVICE_GXS_TYPE_GXSCIRCLE) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_GXSCIRCLE_GROUP_ITEM: return new RsGxsCircleGroupItem(); -#ifdef TO_REMOVE - case RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM: return new RsGxsCircleMsgItem(); -#endif - case RS_PKT_SUBTYPE_GXSCIRCLE_SUBSCRIPTION_REQUEST_ITEM: return new RsGxsCircleSubscriptionRequestItem(); - default: - return NULL ; - } -} - -void RsGxsCircleSubscriptionRequestItem::clear() -{ - time_stamp = 0 ; - time_out = 0 ; - subscription_type = RsGxsCircleSubscriptionType::UNKNOWN; -} - -#ifdef TO_REMOVE -void RsGxsCircleMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - //RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,mMsg.stuff,"mMsg.stuff") ;//Should be this but not retrocompatible... - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,mMsg.stuff,"msg.stuff") ; -} - -void RsGxsCircleMsgItem::clear() -{ - mMsg.stuff.clear(); -} -#endif - -void RsGxsCircleSubscriptionRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,time_stamp,"time_stamp") ; - RsTypeSerializer::serial_process(j,ctx,time_out ,"time_out") ; - RsTypeSerializer::serial_process (j,ctx,subscription_type ,"subscription_type") ; -} - -void RsGxsCircleGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,pgpIdSet,"pgpIdSet") ; - RsTypeSerializer::serial_process(j,ctx,gxsIdSet,"gxsIdSet") ; - RsTypeSerializer::serial_process(j,ctx,subCircleSet,"subCircleSet") ; -} - -void RsGxsCircleGroupItem::clear() -{ - pgpIdSet.TlvClear(); - gxsIdSet.TlvClear(); - subCircleSet.TlvClear(); -} - -bool RsGxsCircleGroupItem::convertFrom(const RsGxsCircleGroup &group) -{ - clear(); - - meta = group.mMeta; - - // Enforce the local rules. - if (meta.mCircleType == GXS_CIRCLE_TYPE_LOCAL) - { - pgpIdSet.ids = group.mLocalFriends; - } - else - { - gxsIdSet.ids = group.mInvitedMembers; - } - - subCircleSet.ids = group.mSubCircles; - return true; -} - -bool RsGxsCircleGroupItem::convertTo(RsGxsCircleGroup &group) const -{ - group.mMeta = meta; - - // Enforce the local rules. - if (meta.mCircleType == GXS_CIRCLE_TYPE_LOCAL) - { - group.mLocalFriends = pgpIdSet.ids; - } - else - { - group.mInvitedMembers = gxsIdSet.ids; - } - - group.mSubCircles = subCircleSet.ids; - return true; -} - diff --git a/libretroshare/src/rsitems/rsgxscircleitems.h b/libretroshare/src/rsitems/rsgxscircleitems.h deleted file mode 100644 index fb720e070..000000000 --- a/libretroshare/src/rsitems/rsgxscircleitems.h +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxscircleitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_GXSCIRCLE_ITEMS_H -#define RS_GXSCIRCLE_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvstring.h" -#include "serialiser/rstlvidset.h" - -#include "rsitems/rsgxsitems.h" -#include "retroshare/rsgxscircles.h" - -const uint8_t RS_PKT_SUBTYPE_GXSCIRCLE_GROUP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM = 0x03; -const uint8_t RS_PKT_SUBTYPE_GXSCIRCLE_SUBSCRIPTION_REQUEST_ITEM = 0x04; - -const uint16_t GXSCIRCLE_PGPIDSET = 0x0001; -const uint16_t GXSCIRCLE_GXSIDSET = 0x0002; -const uint16_t GXSCIRCLE_SUBCIRCLESET = 0x0003; - -// These classes are a mess. Needs proper item serialisation etc. - -class RsGxsCircleGroupItem : public RsGxsGrpItem -{ - -public: - - RsGxsCircleGroupItem(): RsGxsGrpItem(RS_SERVICE_GXS_TYPE_GXSCIRCLE, RS_PKT_SUBTYPE_GXSCIRCLE_GROUP_ITEM) {} - virtual ~RsGxsCircleGroupItem() {} - - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - bool convertFrom(const RsGxsCircleGroup &group); - bool convertTo(RsGxsCircleGroup &group) const; - - // DIFFERENT FROM OTHER ONES, as stupid serialisation otherwise. - RsTlvPgpIdSet pgpIdSet; // For Local Groups. - RsTlvGxsIdSet gxsIdSet; // For External Groups. - RsTlvGxsCircleIdSet subCircleSet; -}; - -#ifdef TO_REMOVE -class RsGxsCircleMsgItem : public RsGxsMsgItem -{ -public: - - RsGxsCircleMsgItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_GXSCIRCLE, RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM) {} - virtual ~RsGxsCircleMsgItem() {} - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsGxsCircleMsg mMsg; -}; -#endif - -class RsGxsCircleSubscriptionRequestItem: public RsGxsMsgItem -{ -public: - - RsGxsCircleSubscriptionRequestItem() : RsGxsMsgItem(RS_SERVICE_GXS_TYPE_GXSCIRCLE, RS_PKT_SUBTYPE_GXSCIRCLE_SUBSCRIPTION_REQUEST_ITEM) { } - virtual ~RsGxsCircleSubscriptionRequestItem() {} - - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t time_stamp ; - uint32_t time_out ; - RsGxsCircleSubscriptionType subscription_type ; -}; - -class RsGxsCircleSerialiser : public RsServiceSerializer -{ -public: - - RsGxsCircleSerialiser() - :RsServiceSerializer(RS_SERVICE_GXS_TYPE_GXSCIRCLE) {} - virtual ~RsGxsCircleSerialiser() {} - - virtual RsItem *create_item(uint16_t service, uint8_t item_sub_id) const; -}; - -#endif /* RS_GXSCIRCLE_ITEMS_H */ diff --git a/libretroshare/src/rsitems/rsgxscommentitems.cc b/libretroshare/src/rsitems/rsgxscommentitems.cc deleted file mode 100644 index 2386fb069..000000000 --- a/libretroshare/src/rsitems/rsgxscommentitems.cc +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxscommentitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include - -#include "rsgxscommentitems.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstypeserializer.h" - -//#define GXSCOMMENT_DEBUG 1 - -RsItem *RsGxsCommentSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) const -{ - if(service_id != getRsItemService(PacketId())) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM: return new RsGxsCommentItem(getRsItemService(PacketId())) ; - case RS_PKT_SUBTYPE_GXSCOMMENT_VOTE_ITEM: return new RsGxsVoteItem(getRsItemService(PacketId())); - default: - return NULL ; - } -} - - -void RsGxsCommentItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,1,mMsg.mComment,"mMsg.mComment") ; -} - -void RsGxsVoteItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mMsg.mVoteType,"mMsg.mVoteType") ; -} - diff --git a/libretroshare/src/rsitems/rsgxscommentitems.h b/libretroshare/src/rsitems/rsgxscommentitems.h deleted file mode 100644 index c35c6c2aa..000000000 --- a/libretroshare/src/rsitems/rsgxscommentitems.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxscommentitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_GXS_COMMENT_ITEMS_H -#define RS_GXS_COMMENT_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" - -#include "rsgxsitems.h" - -#include "retroshare/rsgxscommon.h" - -const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM = 0xf1; -const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_VOTE_ITEM = 0xf2; - -class RsGxsCommentItem : public RsGxsMsgItem -{ -public: - - RsGxsCommentItem(uint16_t service_type): RsGxsMsgItem(service_type, RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM) {} - virtual ~RsGxsCommentItem() {} - void clear(){} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - RsGxsComment mMsg; -}; - - -class RsGxsVoteItem : public RsGxsMsgItem -{ -public: - - RsGxsVoteItem(uint16_t service_type): RsGxsMsgItem(service_type, RS_PKT_SUBTYPE_GXSCOMMENT_VOTE_ITEM) {} - virtual ~RsGxsVoteItem() {} - void clear(){} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - RsGxsVote mMsg; -}; - -class RsGxsCommentSerialiser : public RsServiceSerializer -{ -public: - - RsGxsCommentSerialiser(uint16_t service_type) :RsServiceSerializer(service_type) {} - virtual ~RsGxsCommentSerialiser() {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ; -}; - -#endif /* RS_GXS_COMMENT_ITEMS_H */ - diff --git a/libretroshare/src/rsitems/rsgxsforumitems.cc b/libretroshare/src/rsitems/rsgxsforumitems.cc deleted file mode 100644 index 1918fd980..000000000 --- a/libretroshare/src/rsitems/rsgxsforumitems.cc +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsforumitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include - -#include "rsgxsforumitems.h" - -#include "serialiser/rstypeserializer.h" - -//#define GXSFORUM_DEBUG 1 - -RsItem *RsGxsForumSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) const -{ - if(service_id != RS_SERVICE_GXS_TYPE_FORUMS) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_GXSFORUM_GROUP_ITEM: return new RsGxsForumGroupItem(); - case RS_PKT_SUBTYPE_GXSFORUM_MESSAGE_ITEM: return new RsGxsForumMsgItem(); - default: - return NULL ; - } -} -void RsGxsForumGroupItem::clear() -{ - mGroup.mDescription.clear(); -} - -void RsGxsForumGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR,mGroup.mDescription,"mGroup.Description"); - - // This is for backward compatibility: normally all members are serialized, but in the previous version, these members are missing. - - if(j == RsGenericSerializer::DESERIALIZE && ctx.mOffset == ctx.mSize) - return ; - - RsTypeSerializer::serial_process(j,ctx,mGroup.mAdminList ,"admin_list" ) ; - RsTypeSerializer::serial_process(j,ctx,mGroup.mPinnedPosts,"pinned_posts") ; -} - -void RsGxsForumMsgItem::clear() -{ - mMsg.mMsg.clear(); -} - -void RsGxsForumMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,mMsg.mMsg,"mGroup.Description"); -} - - - diff --git a/libretroshare/src/rsitems/rsgxsforumitems.h b/libretroshare/src/rsitems/rsgxsforumitems.h deleted file mode 100644 index 30c6c4e08..000000000 --- a/libretroshare/src/rsitems/rsgxsforumitems.h +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsforumitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_GXS_FORUM_ITEMS_H -#define RS_GXS_FORUM_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsgxsitems.h" - -#include "serialiser/rsserializer.h" - -#include "retroshare/rsgxsforums.h" - -const uint8_t RS_PKT_SUBTYPE_GXSFORUM_GROUP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_GXSFORUM_MESSAGE_ITEM = 0x03; - -class RsGxsForumGroupItem : public RsGxsGrpItem -{ - -public: - - RsGxsForumGroupItem(): RsGxsGrpItem(RS_SERVICE_GXS_TYPE_FORUMS, RS_PKT_SUBTYPE_GXSFORUM_GROUP_ITEM) {} - virtual ~RsGxsForumGroupItem() {} - - void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsGxsForumGroup mGroup; -}; - -class RsGxsForumMsgItem : public RsGxsMsgItem -{ -public: - - RsGxsForumMsgItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_FORUMS, RS_PKT_SUBTYPE_GXSFORUM_MESSAGE_ITEM) {} - virtual ~RsGxsForumMsgItem() {} - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsGxsForumMsg mMsg; -}; - -class RsGxsForumSerialiser : public RsServiceSerializer -{ -public: - RsGxsForumSerialiser() :RsServiceSerializer(RS_SERVICE_GXS_TYPE_FORUMS) {} - virtual ~RsGxsForumSerialiser() {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ; -}; - -#endif /* RS_GXS_FORUM_ITEMS_H */ diff --git a/libretroshare/src/rsitems/rsgxsiditems.cc b/libretroshare/src/rsitems/rsgxsiditems.cc deleted file mode 100644 index 0c37c110e..000000000 --- a/libretroshare/src/rsitems/rsgxsiditems.cc +++ /dev/null @@ -1,121 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsiditems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include - -#include "rsgxsiditems.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvstring.h" -#include "util/rsstring.h" - -#include "serialiser/rstypeserializer.h" - -// #define GXSID_DEBUG 1 - -RsItem *RsGxsIdSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) const -{ - if(service_id != RS_SERVICE_GXS_TYPE_GXSID) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_GXSID_GROUP_ITEM : return new RsGxsIdGroupItem (); - case RS_PKT_SUBTYPE_GXSID_LOCAL_INFO_ITEM: return new RsGxsIdLocalInfoItem() ; - default: - return NULL ; - } -} -void RsGxsIdLocalInfoItem::clear() -{ - mTimeStamps.clear() ; -} -void RsGxsIdGroupItem::clear() -{ - mPgpIdHash.clear(); - mPgpIdSign.clear(); - - mRecognTags.clear(); - mImage.TlvClear(); -} -void RsGxsIdLocalInfoItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mTimeStamps,"mTimeStamps") ; - RsTypeSerializer::serial_process(j,ctx,mContacts,"mContacts") ; -} - -void RsGxsIdGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mPgpIdHash,"mPgpIdHash") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_SIGN,mPgpIdSign,"mPgpIdSign") ; - - RsTlvStringSetRef rset(TLV_TYPE_RECOGNSET,mRecognTags) ; - - RsTypeSerializer::serial_process(j,ctx,rset,"mRecognTags") ; - - // image is optional - - if(j == RsGenericSerializer::DESERIALIZE && ctx.mOffset == ctx.mSize) - return ; - - RsTypeSerializer::serial_process(j,ctx,mImage,"mImage") ; -} - -bool RsGxsIdGroupItem::fromGxsIdGroup(RsGxsIdGroup &group, bool moveImage) -{ - clear(); - meta = group.mMeta; - mPgpIdHash = group.mPgpIdHash; - mPgpIdSign = group.mPgpIdSign; - mRecognTags = group.mRecognTags; - - if (moveImage) - { - mImage.binData.bin_data = group.mImage.mData; - mImage.binData.bin_len = group.mImage.mSize; - group.mImage.shallowClear(); - } - else - { - mImage.binData.setBinData(group.mImage.mData, group.mImage.mSize); - } - return true ; -} -bool RsGxsIdGroupItem::toGxsIdGroup(RsGxsIdGroup &group, bool moveImage) -{ - group.mMeta = meta; - group.mPgpIdHash = mPgpIdHash; - group.mPgpIdSign = mPgpIdSign; - group.mRecognTags = mRecognTags; - - if (moveImage) - { - group.mImage.take((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); - // mImage doesn't have a ShallowClear at the moment! - mImage.binData.TlvShallowClear(); - } - else - { - group.mImage.copy((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); - } - return true ; -} - diff --git a/libretroshare/src/rsitems/rsgxsiditems.h b/libretroshare/src/rsitems/rsgxsiditems.h deleted file mode 100644 index 440247403..000000000 --- a/libretroshare/src/rsitems/rsgxsiditems.h +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsiditems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_GXS_IDENTITY_ITEMS_H -#define RS_GXS_IDENTITY_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserial.h" - -#include "rsgxsitems.h" -#include "retroshare/rsidentity.h" - -//const uint8_t RS_PKT_SUBTYPE_GXSID_GROUP_ITEM_deprecated = 0x02; - -const uint8_t RS_PKT_SUBTYPE_GXSID_GROUP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_GXSID_OPINION_ITEM = 0x03; -const uint8_t RS_PKT_SUBTYPE_GXSID_COMMENT_ITEM = 0x04; -const uint8_t RS_PKT_SUBTYPE_GXSID_LOCAL_INFO_ITEM = 0x05; - -class RsGxsIdItem: public RsGxsGrpItem -{ - public: - RsGxsIdItem(uint8_t item_subtype) : RsGxsGrpItem(RS_SERVICE_GXS_TYPE_GXSID,item_subtype) {} -}; - -class RsGxsIdGroupItem : public RsGxsIdItem -{ -public: - - RsGxsIdGroupItem(): RsGxsIdItem(RS_PKT_SUBTYPE_GXSID_GROUP_ITEM) {} - virtual ~RsGxsIdGroupItem() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - virtual void clear(); - - bool fromGxsIdGroup(RsGxsIdGroup &group, bool moveImage); - bool toGxsIdGroup(RsGxsIdGroup &group, bool moveImage); - - Sha1CheckSum mPgpIdHash; - // Need a signature as proof - otherwise anyone could add others Hashes. - // This is a string, as the length is variable. - std::string mPgpIdSign; - - // Recognition Strings. MAX# defined above. - std::list mRecognTags; - - // Avatar - RsTlvImage mImage ; -}; - -struct RsGxsIdLocalInfoItem : public RsGxsIdItem -{ - RsGxsIdLocalInfoItem(): RsGxsIdItem(RS_PKT_SUBTYPE_GXSID_LOCAL_INFO_ITEM) {} - virtual ~RsGxsIdLocalInfoItem() {} - - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - std::map mTimeStamps ; - std::set mContacts ; -}; - -class RsGxsIdSerialiser : public RsServiceSerializer -{ -public: - RsGxsIdSerialiser() :RsServiceSerializer(RS_SERVICE_GXS_TYPE_GXSID) {} - virtual ~RsGxsIdSerialiser() {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ; -}; - -#endif /* RS_GXS_IDENTITY_ITEMS_H */ diff --git a/libretroshare/src/rsitems/rsgxsitems.cc b/libretroshare/src/rsitems/rsgxsitems.cc deleted file mode 100644 index 22c379f9e..000000000 --- a/libretroshare/src/rsitems/rsgxsitems.cc +++ /dev/null @@ -1,126 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * Copyright 2012-2012 by Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rstypeserializer.h" -#include "serialiser/rsbaseserial.h" -#include "rsgxsitems.h" -#include "gxs/rsgxsdata.h" -#include - - void RsMsgMetaData::operator =(const RsGxsMsgMetaData& rGxsMeta) - { - this->mAuthorId = rGxsMeta.mAuthorId; - this->mChildTs = rGxsMeta.mChildTs; - this->mGroupId = rGxsMeta.mGroupId; - this->mMsgFlags = rGxsMeta.mMsgFlags; - this->mMsgId = rGxsMeta.mMsgId; - this->mMsgName = rGxsMeta.mMsgName; - this->mMsgStatus = rGxsMeta.mMsgStatus; - this->mOrigMsgId = rGxsMeta.mOrigMsgId; - this->mParentId = rGxsMeta.mParentId; - this->mPublishTs = rGxsMeta.mPublishTs; - this->mThreadId = rGxsMeta.mThreadId; - this->mServiceString = rGxsMeta.mServiceString; - } - - - void RsGroupMetaData::operator =(const RsGxsGrpMetaData& rGxsMeta) - { - this->mAuthorId = rGxsMeta.mAuthorId; - this->mGroupFlags = rGxsMeta.mGroupFlags; - this->mGroupId = rGxsMeta.mGroupId; - this->mGroupStatus = rGxsMeta.mGroupStatus; - this->mLastPost = rGxsMeta.mLastPost; - this->mVisibleMsgCount = rGxsMeta.mVisibleMsgCount; - this->mPop = rGxsMeta.mPop; - this->mPublishTs = rGxsMeta.mPublishTs; - this->mSubscribeFlags = rGxsMeta.mSubscribeFlags; - this->mGroupName = rGxsMeta.mGroupName; - this->mServiceString = rGxsMeta.mServiceString; - this->mSignFlags = rGxsMeta.mSignFlags; - this->mCircleId = rGxsMeta.mCircleId; - this->mCircleType = rGxsMeta.mCircleType; - this->mInternalCircle = rGxsMeta.mInternalCircle; - this->mOriginator = rGxsMeta.mOriginator; - this->mAuthenFlags = rGxsMeta.mAuthenFlags; - this->mParentGrpId = rGxsMeta.mParentGrpId; - } - -template<> uint32_t RsTypeSerializer::serial_size(const TurtleGxsInfo& i) -{ - uint32_t s = 0 ; - - s += 2 ; // service_id - s += i.group_id.SIZE_IN_BYTES ; - s += GetTlvStringSize(i.name) ; - - return s; -} - -template<> bool RsTypeSerializer::deserialize(const uint8_t data[],uint32_t size,uint32_t& offset,TurtleGxsInfo& i) -{ - uint32_t saved_offset = offset ; - bool ok = true ; - - ok &= getRawUInt16(data, size, &offset, &i.service_id); // service_id - ok &= i.group_id.deserialise(data, size, offset); // group_id - ok &= GetTlvString(data, size, &offset, TLV_TYPE_STR_NAME, i.name); // group name - - if(!ok) - offset = saved_offset ; - - return ok; -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[],uint32_t size,uint32_t& offset,const TurtleGxsInfo& i) -{ - uint32_t saved_offset = offset ; - bool ok = true ; - - ok &= setRawUInt16(data, size, &offset, i.service_id); // service_id - ok &= i.group_id.serialise(data, size, offset); // group_id - ok &= SetTlvString(data, size, &offset, TLV_TYPE_STR_NAME, i.name); // group name - - if(!ok) - offset = saved_offset ; - - return ok; -} - -template<> void RsTypeSerializer::print_data(const std::string& n, const TurtleGxsInfo& i) -{ - std::cerr << " [GXS Info ] " << n << " group_id=" << i.group_id << " service=" << std::hex << i.service_id << std::dec << ", name=" << i.name << std::endl; -} - -void RsTurtleGxsSearchResultGroupSummaryItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,result,"result") ; -} -void RsTurtleGxsSearchResultGroupDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::TlvMemBlock_proxy prox(encrypted_nxs_group_data,encrypted_nxs_group_data_len) ; - RsTypeSerializer::serial_process(j,ctx,prox,"encrypted_nxs_data") ; -} - -RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(TurtleGxsInfo) -RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(TurtleGxsInfo) - diff --git a/libretroshare/src/rsitems/rsgxsitems.h b/libretroshare/src/rsitems/rsgxsitems.h deleted file mode 100644 index 9b47d5d6d..000000000 --- a/libretroshare/src/rsitems/rsgxsitems.h +++ /dev/null @@ -1,134 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * Copyright 2012-2012 by Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSGXSITEMS_H -#define RSGXSITEMS_H - -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "util/rstime.h" -#include "retroshare/rsgxsifacetypes.h" - -class RsGxsGrpItem : public RsItem -{ - -public: - - RsGxsGrpItem(uint16_t service, uint8_t subtype) - : RsItem(RS_PKT_VERSION_SERVICE, service, subtype) { return; } - virtual ~RsGxsGrpItem(){} - - RsGroupMetaData meta; -}; - -class RsGxsMsgItem : public RsItem -{ - -public: - RsGxsMsgItem(uint16_t service, uint8_t subtype) - : RsItem(RS_PKT_VERSION_SERVICE, service, subtype) { return; } - virtual ~RsGxsMsgItem(){} - - RsMsgMetaData meta; -}; - -// We should make these items templates or generic classes so that each GXS service will handle them on its own. - -static const uint8_t RS_PKT_SUBTYPE_GXS_SUBSTRING_SEARCH_ITEM = 0x20 ; -static const uint8_t RS_PKT_SUBTYPE_GXS_GROUP_SEARCH_ITEM = 0x21 ; -static const uint8_t RS_PKT_SUBTYPE_GXS_GROUP_SUMMARY_ITEM = 0x22 ; -static const uint8_t RS_PKT_SUBTYPE_GXS_GROUP_DATA_ITEM = 0x23 ; - -class RsGxsTurtleSubStringSearchItem: public RsItem -{ - public: - RsGxsTurtleSubStringSearchItem(uint16_t service): RsItem(RS_PKT_VERSION_SERVICE,service,RS_PKT_SUBTYPE_GXS_SUBSTRING_SEARCH_ITEM) {} - virtual ~RsGxsTurtleSubStringSearchItem() {} - - std::string match_string ; // string to match - - std::string GetKeywords() { return match_string; } - void clear() { match_string.clear() ; } - - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsGxsTurtleGroupSearchItem: public RsItem -{ - public: - RsGxsTurtleGroupSearchItem(uint16_t service): RsItem(RS_PKT_VERSION_SERVICE,service,RS_PKT_SUBTYPE_GXS_GROUP_SEARCH_ITEM) {} - virtual ~RsGxsTurtleGroupSearchItem() {} - - uint16_t service_id ; // searvice to search - Sha1CheckSum hashed_group_id ; // the group ID is hashed in order to keep it private. - - std::string GetKeywords() { return std::string("Group request for [hashed] ")+hashed_group_id.toStdString() ; } - void clear() { hashed_group_id.clear() ; } - - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -struct TurtleGxsInfo -{ - uint16_t service_id ; - RsGxsGroupId group_id ; - RsGxsId author; - std::string name ; - std::string description ; - rstime_t last_post ; - uint32_t number_of_posts ; -}; - -class RsTurtleGxsSearchResultGroupSummaryItem: public RsItem -{ - public: - RsTurtleGxsSearchResultGroupSummaryItem(uint16_t service) : RsItem(RS_PKT_VERSION_SERVICE,service,RS_PKT_SUBTYPE_GXS_GROUP_SUMMARY_ITEM){} - virtual ~RsTurtleGxsSearchResultGroupSummaryItem() {} - - std::list result ; - - void clear() { result.clear() ; } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleGxsSearchResultGroupDataItem: public RsItem -{ - public: - RsTurtleGxsSearchResultGroupDataItem(uint16_t service) : RsItem(RS_PKT_VERSION_SERVICE,service,RS_PKT_SUBTYPE_GXS_GROUP_DATA_ITEM){} - virtual ~RsTurtleGxsSearchResultGroupDataItem() {} - - unsigned char *encrypted_nxs_group_data; // data is encrypted with group ID. Only the requester, or anyone who already know the group id can decrypt. - uint32_t encrypted_nxs_group_data_len ; - - void clear() { free(encrypted_nxs_group_data); encrypted_nxs_group_data=NULL; encrypted_nxs_group_data_len=0; } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - - - - - -#endif // RSGXSITEMS_H diff --git a/libretroshare/src/rsitems/rsgxsrecognitems.cc b/libretroshare/src/rsitems/rsgxsrecognitems.cc deleted file mode 100644 index 4113a051c..000000000 --- a/libretroshare/src/rsitems/rsgxsrecognitems.cc +++ /dev/null @@ -1,114 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsrecogitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2013 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "rsitems/rsgxsrecognitems.h" -#include "serialiser/rstypeserializer.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -/*************************************************************************/ - -RsItem *RsGxsRecognSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const -{ - if(service != RS_SERVICE_TYPE_GXS_RECOGN) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_RECOGN_REQ: return new RsGxsRecognReqItem(); - case RS_PKT_SUBTYPE_RECOGN_SIGNER: return new RsGxsRecognSignerItem(); - case RS_PKT_SUBTYPE_RECOGN_TAG: return new RsGxsRecognTagItem(); - default: - return NULL ; - } -} - -void RsGxsRecognReqItem::clear() -{ - issued_at = 0; - period = 0; - tag_class = 0; - tag_type = 0; - - identity.clear(); - nickname.clear(); - comment.clear(); - - sign.TlvClear(); - -} -void RsGxsRecognReqItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,issued_at ,"issued_at") ; - RsTypeSerializer::serial_process (j,ctx,period ,"period") ; - RsTypeSerializer::serial_process (j,ctx,tag_class ,"tag_class") ; - RsTypeSerializer::serial_process (j,ctx,tag_type ,"tag_type") ; - RsTypeSerializer::serial_process (j,ctx,identity ,"identity") ; - RsTypeSerializer::serial_process (j,ctx,1,nickname ,"nickname") ; - RsTypeSerializer::serial_process (j,ctx,1,comment ,"comment") ; - RsTypeSerializer::serial_process(j,ctx,sign ,"sign") ; -} - -void RsGxsRecognTagItem::clear() -{ - valid_from = 0; - valid_to = 0; - - tag_class = 0; - tag_type = 0; - - identity.clear(); - nickname.clear(); - - sign.TlvClear(); -} - -void RsGxsRecognTagItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,valid_from ,"valid_from") ; - RsTypeSerializer::serial_process (j,ctx,valid_to ,"valid_to") ; - RsTypeSerializer::serial_process (j,ctx,tag_class ,"tag_class") ; - RsTypeSerializer::serial_process (j,ctx,tag_type ,"tag_type") ; - RsTypeSerializer::serial_process (j,ctx,identity ,"identity"); - RsTypeSerializer::serial_process (j,ctx,1,nickname ,"nickname") ; - RsTypeSerializer::serial_process(j,ctx,sign ,"sign") ; -} - -void RsGxsRecognSignerItem::clear() -{ - signing_classes.TlvClear(); - key.TlvClear(); - sign.TlvClear(); -} - -void RsGxsRecognSignerItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,signing_classes ,"signing_classes") ; - RsTypeSerializer::serial_process(j,ctx,key ,"key"); - RsTypeSerializer::serial_process(j,ctx,sign ,"sign") ; -} - - - diff --git a/libretroshare/src/rsitems/rsgxsrecognitems.h b/libretroshare/src/rsitems/rsgxsrecognitems.h deleted file mode 100644 index 3e049f0c2..000000000 --- a/libretroshare/src/rsitems/rsgxsrecognitems.h +++ /dev/null @@ -1,136 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsrecogitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2013 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_GXS_RECOG_ITEMS_H -#define RS_GXS_RECOG_ITEMS_H - -#include - -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rstlvkeys.h" -#include "serialiser/rstlvidset.h" - -#if 0 -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvtypes.h" - -#endif - -#include "retroshare/rsgxsifacetypes.h" - -/**************************************************************************/ - -#define RS_PKT_SUBTYPE_RECOGN_REQ 0x01 -#define RS_PKT_SUBTYPE_RECOGN_TAG 0x02 -#define RS_PKT_SUBTYPE_RECOGN_SIGNER 0x03 - - -class RsGxsRecognReqItem: public RsItem -{ -public: - RsGxsRecognReqItem() - :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_RECOGN, RS_PKT_SUBTYPE_RECOGN_REQ) - , issued_at(0), period(0), tag_class(0), tag_type(0) - { - setPriorityLevel(QOS_PRIORITY_DEFAULT); - return; - } - virtual ~RsGxsRecognReqItem(){} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t issued_at; - uint32_t period; - uint16_t tag_class; - uint16_t tag_type; - - RsGxsId identity; - std::string nickname; - std::string comment; - - RsTlvKeySignature sign; -}; - - -class RsGxsRecognTagItem: public RsItem -{ - public: - RsGxsRecognTagItem() - :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_RECOGN, RS_PKT_SUBTYPE_RECOGN_TAG) - , valid_from(0), valid_to(0), tag_class(0), tag_type(0) - { - setPriorityLevel(QOS_PRIORITY_DEFAULT); - return; - } - virtual ~RsGxsRecognTagItem(){} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t valid_from; - uint32_t valid_to; - uint16_t tag_class; - uint16_t tag_type; - - RsGxsId identity; - std::string nickname; - - RsTlvKeySignature sign; -}; - - -class RsGxsRecognSignerItem: public RsItem -{ -public: - RsGxsRecognSignerItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_RECOGN, RS_PKT_SUBTYPE_RECOGN_SIGNER) - { - setPriorityLevel(QOS_PRIORITY_DEFAULT); - return; - } - virtual ~RsGxsRecognSignerItem(){} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsTlvServiceIdSet signing_classes; - RsTlvPublicRSAKey key; // has from->to, and flags. - RsTlvKeySignature sign; -}; - - -class RsGxsRecognSerialiser: public RsServiceSerializer -{ - public: - RsGxsRecognSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_GXS_RECOGN) {} - virtual ~RsGxsRecognSerialiser() {} - - virtual RsItem *create_item(uint16_t service, uint8_t item_sub_id) const; -}; - -/**************************************************************************/ - -#endif /* RS_GXS_RECOGN_ITEMS_H */ - - diff --git a/libretroshare/src/rsitems/rsgxsreputationitems.cc b/libretroshare/src/rsitems/rsgxsreputationitems.cc deleted file mode 100644 index 97d33e3d1..000000000 --- a/libretroshare/src/rsitems/rsgxsreputationitems.cc +++ /dev/null @@ -1,106 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsreputationitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include "util/rstime.h" -#include "serialiser/rsbaseserial.h" -#include "rsitems/rsgxsreputationitems.h" - -#include "serialiser/rstypeserializer.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -/*************************************************************************/ - -void RsGxsReputationSetItem::clear() -{ - mOpinions.clear() ; -} - -void RsGxsReputationUpdateItem::clear() -{ - mOpinions.clear() ; -} - -void RsGxsReputationBannedNodeSetItem::clear() -{ - mKnownIdentities.TlvClear(); -} - -void RsGxsReputationConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,mPeerId,"mPeerId") ; - RsTypeSerializer::serial_process(j,ctx,mLatestUpdate,"mLatestUpdate") ; - RsTypeSerializer::serial_process(j,ctx,mLastQuery,"mLastQuery") ; -} - -void RsGxsReputationBannedNodeSetItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,mPgpId,"mPgpId") ; - RsTypeSerializer::serial_process (j,ctx,mLastActivityTS,"mLastActivityTS") ; - RsTypeSerializer::serial_process(j,ctx,mKnownIdentities,"mKnownIdentities") ; -} - -void RsGxsReputationSetItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,mGxsId,"mGxsId") ; - RsTypeSerializer::serial_process(j,ctx,mOwnOpinion,"mOwnOpinion") ; - RsTypeSerializer::serial_process(j,ctx,mOwnOpinionTS,"mOwnOpinionTS") ; - RsTypeSerializer::serial_process(j,ctx,mIdentityFlags,"mIdentityFlags") ; - RsTypeSerializer::serial_process(j,ctx,mLastUsedTS,"mLastUsedTS") ; - RsTypeSerializer::serial_process (j,ctx,mOwnerNodeId,"mOwnerNodeId") ; - RsTypeSerializer::serial_process (j,ctx,mOpinions,"mOpinions") ; -} - -void RsGxsReputationUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mLatestUpdate,"mLatestUpdate") ; - RsTypeSerializer::serial_process (j,ctx,mOpinions,"mOpinions") ; -} -void RsGxsReputationRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mLastUpdate,"mLastUpdate") ; -} - -/*************************************************************************/ - -RsItem *RsGxsReputationSerialiser::create_item(uint16_t service,uint8_t subtype) const -{ - if(service != RS_SERVICE_GXS_TYPE_REPUTATION) - return NULL ; - - switch(subtype) - { - case RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM : return new RsGxsReputationSetItem() ; - case RS_PKT_SUBTYPE_GXS_REPUTATION_BANNED_NODE_SET_ITEM : return new RsGxsReputationBannedNodeSetItem(); - case RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM : return new RsGxsReputationUpdateItem(); - case RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM : return new RsGxsReputationRequestItem() ; - case RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM : return new RsGxsReputationConfigItem () ; - default: - std::cerr << "(EE) RsGxsReputationSerialiser::create_item(): unhandled item type " << subtype << std::endl; - return NULL ; - } -} - diff --git a/libretroshare/src/rsitems/rsgxsreputationitems.h b/libretroshare/src/rsitems/rsgxsreputationitems.h deleted file mode 100644 index 8028e63f1..000000000 --- a/libretroshare/src/rsitems/rsgxsreputationitems.h +++ /dev/null @@ -1,178 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsreputationitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014-2014 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_GXSREPUTATION_ITEMS_H -#define RS_GXSREPUTATION_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rsserial.h" -#include "serialiser/rstlvidset.h" -#include "retroshare/rsgxsifacetypes.h" -#include "retroshare/rsreputations.h" - -#include "serialiser/rsserializer.h" - -#define RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM 0x01 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated2 0x02 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM 0x03 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM 0x04 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated1 0x05 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated3 0x06 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_BANNED_NODE_SET_ITEM 0x07 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM 0x08 - -/**************************************************************************/ -class RsReputationItem: public RsItem -{ - public: - RsReputationItem(uint8_t reputation_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_REPUTATION,reputation_subtype) - { - setPriorityLevel(QOS_PRIORITY_RS_GXSREPUTATION_ITEM); - } - - virtual ~RsReputationItem() {} - virtual void clear() = 0 ; -}; - -class RsGxsReputationConfigItem: public RsReputationItem -{ -public: - RsGxsReputationConfigItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM) {} - - virtual ~RsGxsReputationConfigItem() {} - virtual void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) ; - - RsPeerId mPeerId; - uint32_t mLatestUpdate; // timestamp they returned. - uint32_t mLastQuery; // when we sent out. -}; - -#ifdef TO_REMOVE -// This class should disappear. Deprecated since Jan 7, 2017. The class definition is actually not needed, -// that is why it's commented out. Kept here in order to explains how the deserialisation works. -// -class RsGxsReputationSetItem_deprecated3: public RsReputationItem -{ -public: - RsGxsReputationSetItem_deprecated3() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated3) {} - - virtual ~RsGxsReputationSetItem_deprecated3() {} - virtual void clear() {} - - virtual void serial_process(SerializeJob /* j */,SerializeContext& /* ctx */) ; - - RsGxsId mGxsId; - uint32_t mOwnOpinion; - uint32_t mOwnOpinionTS; - uint32_t mIdentityFlags ; - RsPgpId mOwnerNodeId; - std::map mOpinions; // RsPeerId -> Opinion. -}; -#endif - -class RsGxsReputationSetItem: public RsReputationItem -{ -public: - RsGxsReputationSetItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM) - { - mOwnOpinion = static_cast(RsOpinion::NEUTRAL); - mOwnOpinionTS = 0; - mIdentityFlags = 0; - mLastUsedTS = 0; - } - - virtual ~RsGxsReputationSetItem() {} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) ; - - RsGxsId mGxsId; - uint32_t mOwnOpinion; - uint32_t mOwnOpinionTS; - uint32_t mIdentityFlags; - uint32_t mLastUsedTS; - RsPgpId mOwnerNodeId; - std::map mOpinions; // RsPeerId -> Opinion. -}; -class RsGxsReputationBannedNodeSetItem: public RsReputationItem -{ -public: - RsGxsReputationBannedNodeSetItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_BANNED_NODE_SET_ITEM) {} - - virtual ~RsGxsReputationBannedNodeSetItem() {} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) ; - - RsPgpId mPgpId ; - uint32_t mLastActivityTS ; - RsTlvGxsIdSet mKnownIdentities ; -}; - -class RsGxsReputationUpdateItem: public RsReputationItem -{ -public: - RsGxsReputationUpdateItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM) {} - - virtual ~RsGxsReputationUpdateItem() {} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) ; - - uint32_t mLatestUpdate; - std::map mOpinions; // GxsId -> Opinion. -}; - -class RsGxsReputationRequestItem: public RsReputationItem -{ -public: - RsGxsReputationRequestItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM) {} - - virtual ~RsGxsReputationRequestItem() {} - virtual void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) ; - - uint32_t mLastUpdate; -}; - - -class RsGxsReputationSerialiser: public RsServiceSerializer -{ -public: - RsGxsReputationSerialiser() :RsServiceSerializer(RS_SERVICE_GXS_TYPE_REPUTATION){} - virtual ~RsGxsReputationSerialiser(){} - - virtual RsItem *create_item(uint16_t service,uint8_t item_type) const; -}; - -/**************************************************************************/ - -#endif /* RS_GXSREPUTATION_ITEMS_H */ - - diff --git a/libretroshare/src/rsitems/rsgxsupdateitems.cc b/libretroshare/src/rsitems/rsgxsupdateitems.cc deleted file mode 100644 index b129dc460..000000000 --- a/libretroshare/src/rsitems/rsgxsupdateitems.cc +++ /dev/null @@ -1,133 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsupdateitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rstypeserializer.h" -#include "serialiser/rsbaseserial.h" - -#include "rsgxsupdateitems.h" - -/**********************************************************************************************/ -/* SERIALIZER */ -/**********************************************************************************************/ - -RsItem* RsGxsUpdateSerialiser::create_item(uint16_t service,uint8_t item_subtype) const -{ - if(service != SERVICE_TYPE) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_GXS_MSG_UPDATE: return new RsGxsMsgUpdateItem(SERVICE_TYPE); - case RS_PKT_SUBTYPE_GXS_GRP_UPDATE: return new RsGxsGrpUpdateItem(SERVICE_TYPE); - case RS_PKT_SUBTYPE_GXS_SERVER_GRP_UPDATE: return new RsGxsServerGrpUpdateItem(SERVICE_TYPE); - case RS_PKT_SUBTYPE_GXS_SERVER_MSG_UPDATE: return new RsGxsServerMsgUpdateItem(SERVICE_TYPE); - case RS_PKT_SUBTYPE_GXS_GRP_CONFIG: return new RsGxsGrpConfigItem(SERVICE_TYPE); - default: - return NULL ; - } -} - -/**********************************************************************************************/ -/* CLEAR */ -/**********************************************************************************************/ - -void RsGxsGrpUpdateItem::clear() -{ - grpUpdateTS = 0; - peerID.clear(); -} - -void RsGxsMsgUpdateItem::clear() -{ - msgUpdateInfos.clear(); - peerID.clear(); -} - -void RsGxsServerMsgUpdateItem::clear() -{ - msgUpdateTS = 0; - grpId.clear(); -} - -void RsGxsServerGrpUpdateItem::clear() -{ - grpUpdateTS = 0; -} - -/**********************************************************************************************/ -/* SERIALISER */ -/**********************************************************************************************/ - -void RsGxsGrpUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,peerID,"peerID"); - RsTypeSerializer::serial_process(j,ctx,grpUpdateTS,"grpUpdateTS"); -} - -void RsGxsServerGrpUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,grpUpdateTS,"grpUpdateTS"); -} - -void RsGxsMsgUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,peerID,"peerID"); - RsTypeSerializer::serial_process(j,ctx,msgUpdateInfos,"msgUpdateInfos"); -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const RsGxsMsgUpdateItem::MsgUpdateInfo& info) -{ - bool ok = true ; - - ok = ok && setRawUInt32(data,size,&offset,info.time_stamp); - ok = ok && setRawUInt32(data,size,&offset,info.message_count); - - return ok; -} -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, RsGxsMsgUpdateItem::MsgUpdateInfo& info) -{ - bool ok = true ; - - ok = ok && getRawUInt32(data,size,&offset,&info.time_stamp); - ok = ok && getRawUInt32(data,size,&offset,&info.message_count); - - return ok; -} -template<> uint32_t RsTypeSerializer::serial_size(const RsGxsMsgUpdateItem::MsgUpdateInfo& /* info */) { return 8; } - -template<> void RsTypeSerializer::print_data(const std::string& name,const RsGxsMsgUpdateItem::MsgUpdateInfo& info) -{ - std::cerr << "[MsgUpdateInfo]: " << name << ": " << info.time_stamp << ", " << info.message_count << std::endl; -} - -void RsGxsServerMsgUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,grpId,"grpId"); - RsTypeSerializer::serial_process(j,ctx,msgUpdateTS,"msgUpdateTS"); -} -void RsGxsGrpConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,grpId,"grpId") ; - RsTypeSerializer::serial_process(j,ctx,msg_keep_delay,"msg_keep_delay") ; - RsTypeSerializer::serial_process(j,ctx,msg_send_delay,"msg_send_delay") ; - RsTypeSerializer::serial_process(j,ctx,msg_req_delay,"msg_req_delay") ; -} - diff --git a/libretroshare/src/rsitems/rsgxsupdateitems.h b/libretroshare/src/rsitems/rsgxsupdateitems.h deleted file mode 100644 index 03bd21800..000000000 --- a/libretroshare/src/rsitems/rsgxsupdateitems.h +++ /dev/null @@ -1,219 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsupdateitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSGXSUPDATEITEMS_H_ -#define RSGXSUPDATEITEMS_H_ - -#include "gxs/rsgxs.h" -#include "gxs/rsgxsdata.h" -#include "gxs/rsgxsnettunnel.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rstypeserializer.h" -#include "serialiser/rsserializable.h" - - -const uint8_t RS_PKT_SUBTYPE_GXS_GRP_UPDATE = 0x01; -const uint8_t RS_PKT_SUBTYPE_GXS_MSG_UPDATE_deprecated = 0x02; -const uint8_t RS_PKT_SUBTYPE_GXS_MSG_UPDATE = 0x03; -const uint8_t RS_PKT_SUBTYPE_GXS_SERVER_GRP_UPDATE = 0x04; -const uint8_t RS_PKT_SUBTYPE_GXS_SERVER_MSG_UPDATE = 0x08; -const uint8_t RS_PKT_SUBTYPE_GXS_GRP_CONFIG = 0x09; -const uint8_t RS_PKT_SUBTYPE_GXS_RANDOM_BIAS = 0x0a; - -class RsGxsNetServiceItem: public RsItem -{ -public: - RsGxsNetServiceItem(uint16_t serv_type,uint8_t subtype) : RsItem(RS_PKT_VERSION_SERVICE, serv_type, subtype) {} - - virtual ~RsGxsNetServiceItem() {} - virtual void clear() = 0 ; -}; - -class RsGxsGrpConfig -{ -public: - RsGxsGrpConfig() - { - msg_keep_delay = RS_GXS_DEFAULT_MSG_STORE_PERIOD ; - msg_send_delay = RS_GXS_DEFAULT_MSG_SEND_PERIOD ; - msg_req_delay = RS_GXS_DEFAULT_MSG_REQ_PERIOD ; - - max_visible_count = 0 ; - statistics_update_TS = 0 ; - last_group_modification_TS = 0 ; - } - - uint32_t msg_keep_delay ; // delay after which we discard the posts - uint32_t msg_send_delay ; // delay after which we dont send the posts anymore - uint32_t msg_req_delay ; // delay after which we dont get the posts from friends - - RsTlvPeerIdSet suppliers; // list of friends who feed this group - uint32_t max_visible_count ; // max visible count reported by contributing friends - rstime_t statistics_update_TS ; // last time the max visible count was updated. - rstime_t last_group_modification_TS ; // last time the group was modified, either in meta data or in the list of messages posted in it. -}; - -class RsGxsGrpConfigItem : public RsGxsNetServiceItem, public RsGxsGrpConfig -{ -public: - explicit RsGxsGrpConfigItem(uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_GRP_CONFIG) {} - RsGxsGrpConfigItem(const RsGxsGrpConfig& m,uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_GRP_CONFIG),RsGxsGrpConfig(m) {} - virtual ~RsGxsGrpConfigItem() {} - - virtual void clear() {} - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsGxsGroupId grpId ; -}; - -class RsGxsGrpUpdate -{ -public: - RsGxsGrpUpdate() { grpUpdateTS=0;} - - uint32_t grpUpdateTS; -}; - -class RsGxsGrpUpdateItem : public RsGxsNetServiceItem, public RsGxsGrpUpdate -{ -public: - explicit RsGxsGrpUpdateItem(uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_GRP_UPDATE) {clear();} - RsGxsGrpUpdateItem(const RsGxsGrpUpdate& u,uint16_t serv_type) : RsGxsNetServiceItem(serv_type, RS_PKT_SUBTYPE_GXS_GRP_UPDATE), RsGxsGrpUpdate(u) {} - - virtual ~RsGxsGrpUpdateItem() {} - - virtual void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsPeerId peerID; -}; - -struct RsPeerUpdateTsRecord -{ - RsPeerUpdateTsRecord() : mLastTsReceived(0), mTs(0) {} - - rstime_t mLastTsReceived; // last TS that was sent for this group by this peer ID. - rstime_t mTs; // time at which this TS was sent. -}; - -class RsGxsServerGrpUpdate -{ -public: - RsGxsServerGrpUpdate() { grpUpdateTS = 0 ; } - - uint32_t grpUpdateTS; - - std::map grpUpdateTsRecords; -}; - -class RsGxsServerGrpUpdateItem : public RsGxsNetServiceItem, public RsGxsServerGrpUpdate -{ -public: - explicit RsGxsServerGrpUpdateItem(uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_SERVER_GRP_UPDATE) { clear();} - RsGxsServerGrpUpdateItem(const RsGxsServerGrpUpdate& u,uint16_t serv_type) : RsGxsNetServiceItem(serv_type, RS_PKT_SUBTYPE_GXS_SERVER_GRP_UPDATE), RsGxsServerGrpUpdate(u) {} - - virtual ~RsGxsServerGrpUpdateItem() {} - - virtual void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsGxsMsgUpdate -{ -public: - struct MsgUpdateInfo : RsSerializable - { - MsgUpdateInfo(): time_stamp(0), message_count(0) {} - - uint32_t time_stamp ; - uint32_t message_count ; - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(time_stamp); - RS_SERIAL_PROCESS(message_count); - } - }; - - std::map msgUpdateInfos; -}; - - -class RsGxsMsgUpdateItem : public RsGxsNetServiceItem, public RsGxsMsgUpdate -{ -public: - explicit RsGxsMsgUpdateItem(uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_MSG_UPDATE) { clear();} - RsGxsMsgUpdateItem(const RsGxsMsgUpdate& m,uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_MSG_UPDATE), RsGxsMsgUpdate(m) {} - - virtual ~RsGxsMsgUpdateItem() {} - - virtual void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsPeerId peerID; -}; - -class RsGxsServerMsgUpdate -{ -public: - RsGxsServerMsgUpdate() { msgUpdateTS = 0 ;} - - uint32_t msgUpdateTS; // local time stamp at which this group last received a new msg - - // Now we also store for each peer the last own TS the peer sent and when it did so. This allows to detect when transactions are stuck because of - // outqueues clogging. If that happens, we receive multiple times the same TS from the friend, in which case we do not send the list of msgs - // again until a significant amount of time has passed. These values are obviously initialized to 0. - - std::map msgUpdateTsRecords; -}; - -class RsGxsServerMsgUpdateItem : public RsGxsNetServiceItem, public RsGxsServerMsgUpdate -{ -public: - explicit RsGxsServerMsgUpdateItem(uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_SERVER_MSG_UPDATE) { clear();} - RsGxsServerMsgUpdateItem(const RsGxsServerMsgUpdate& m,uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_SERVER_MSG_UPDATE),RsGxsServerMsgUpdate(m) {} - virtual ~RsGxsServerMsgUpdateItem() {} - - virtual void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsGxsGroupId grpId; -}; - -class RsGxsUpdateSerialiser : public RsServiceSerializer -{ -public: - - explicit RsGxsUpdateSerialiser(uint16_t servtype) : RsServiceSerializer(servtype), SERVICE_TYPE(servtype) {} - - virtual ~RsGxsUpdateSerialiser() {} - - virtual RsItem* create_item(uint16_t service,uint8_t item_subtype) const ; - - const uint16_t SERVICE_TYPE; -}; - - - - -#endif /* RSGXSUPDATEITEMS_H_ */ diff --git a/libretroshare/src/rsitems/rsheartbeatitems.h b/libretroshare/src/rsitems/rsheartbeatitems.h deleted file mode 100644 index b7e4f27c6..000000000 --- a/libretroshare/src/rsitems/rsheartbeatitems.h +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsheartbeatitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_HEARTBEAT_ITEMS_H -#define RS_HEARTBEAT_ITEMS_H - -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" - -const uint8_t RS_PKT_SUBTYPE_HEARTBEAT_PULSE = 0x01; - -class RsHeartbeatItem: public RsItem -{ -public: - RsHeartbeatItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_HEARTBEAT, RS_PKT_SUBTYPE_HEARTBEAT_PULSE) - { - setPriorityLevel(QOS_PRIORITY_RS_HEARTBEAT_PULSE) ; - } - virtual ~RsHeartbeatItem() {} - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) {} - - virtual void clear(){} -}; - -class RsHeartbeatSerialiser: public RsServiceSerializer -{ -public: - RsHeartbeatSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_HEARTBEAT) {} - - virtual ~RsHeartbeatSerialiser() {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const - { - if(service == RS_SERVICE_TYPE_HEARTBEAT && item_subtype == RS_PKT_SUBTYPE_HEARTBEAT_PULSE) - return new RsHeartbeatItem() ; - else - return NULL ; - } -}; - - -#endif // RS_DISC_ITEMS_H - diff --git a/libretroshare/src/rsitems/rshistoryitems.cc b/libretroshare/src/rsitems/rshistoryitems.cc deleted file mode 100644 index 4cfb04945..000000000 --- a/libretroshare/src/rsitems/rshistoryitems.cc +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rshistoryitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Thunder. * - * * - * 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 . * - * * - *******************************************************************************/ -#include "rsitems/rshistoryitems.h" -#include "rsitems/rsconfigitems.h" - -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" - -#include "serialiser/rstypeserializer.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -void RsHistoryMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - uint16_t version=0; - - RsTypeSerializer::serial_process(j,ctx,version,"version") ; - RsTypeSerializer::serial_process (j,ctx,chatPeerId,"chatPeerId") ; - RsTypeSerializer::serial_process (j,ctx,incoming,"incoming") ; - RsTypeSerializer::serial_process (j,ctx,msgPeerId,"peerId") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,peerName,"peerName") ; - RsTypeSerializer::serial_process(j,ctx,sendTime,"sendTime") ; - RsTypeSerializer::serial_process(j,ctx,recvTime,"recvTime") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_MSG,message,"message") ; -} - -RsItem *RsHistorySerialiser::create_item(uint8_t item_type,uint8_t item_subtype) const -{ - if(item_type != RS_PKT_TYPE_HISTORY_CONFIG) - return NULL ; - - if(item_subtype == RS_PKT_SUBTYPE_DEFAULT) - return new RsHistoryMsgItem(); - - return NULL ; -} - - -RsHistoryMsgItem::RsHistoryMsgItem() : RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_HISTORY_CONFIG, RS_PKT_SUBTYPE_DEFAULT) -{ - incoming = false; - sendTime = 0; - recvTime = 0; - msgId = 0; - saveToDisc = true; -} - - diff --git a/libretroshare/src/rsitems/rshistoryitems.h b/libretroshare/src/rsitems/rshistoryitems.h deleted file mode 100644 index 693817757..000000000 --- a/libretroshare/src/rsitems/rshistoryitems.h +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rshistoryitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Thunder. * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_HISTORY_ITEMS_H -#define RS_HISTORY_ITEMS_H - -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserial.h" -#include "rsitems/rsconfigitems.h" -#include "retroshare/rstypes.h" - -#include "serialiser/rsserializer.h" - -/**************************************************************************/ - -class RsHistoryMsgItem: public RsItem -{ -public: - RsHistoryMsgItem(); - virtual ~RsHistoryMsgItem() {} - virtual void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsPeerId chatPeerId; // empty for global chat - bool incoming; - RsPeerId msgPeerId; - std::string peerName; - uint32_t sendTime; - uint32_t recvTime; - std::string message; - - /* not serialised */ - uint32_t msgId; - bool saveToDisc; -}; - -class RsHistorySerialiser: public RsConfigSerializer -{ -public: - RsHistorySerialiser() : RsConfigSerializer(RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_HISTORY_CONFIG) {} - virtual ~RsHistorySerialiser() {} - - virtual RsItem *create_item(uint8_t item_type,uint8_t item_subtype) const ; -}; - -/**************************************************************************/ - -#endif /* RS_HISTORY_ITEMS_H */ - - diff --git a/libretroshare/src/rsitems/rsitem.h b/libretroshare/src/rsitems/rsitem.h deleted file mode 100644 index 1c8ea9789..000000000 --- a/libretroshare/src/rsitems/rsitem.h +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsitem.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include // for typeid - -#include "util/smallobject.h" -#include "retroshare/rstypes.h" -#include "serialiser/rsserializer.h" -#include "serialiser/rsserializable.h" -#include "util/stacktrace.h" - -#include - -struct RsItem : RsMemoryManagement::SmallObject, RsSerializable -{ - explicit RsItem(uint32_t t); - RsItem(uint8_t ver, uint8_t cls, uint8_t t, uint8_t subtype); -#ifdef DO_STATISTICS - void *operator new(size_t s) ; - void operator delete(void *,size_t s) ; -#endif - - virtual ~RsItem(); - - /// TODO: Do this make sense with the new serialization system? - virtual void clear() = 0; - - /// @deprecated use << ostream operator instead - RS_DEPRECATED_FOR("<< ostream operator") - virtual std::ostream &print(std::ostream &out, uint16_t /* indent */ = 0) - { - RsGenericSerializer::SerializeContext ctx( - nullptr, 0, RsSerializationFlags::NONE ); - serial_process(RsGenericSerializer::PRINT,ctx); - return out; - } - - void print_string(std::string &out, uint16_t indent = 0); - - /// source / destination id - const RsPeerId& PeerId() const { return peerId; } - void PeerId(const RsPeerId& id) { peerId = id; } - - /// complete id - uint32_t PacketId() const; - - /// id parts - uint8_t PacketVersion(); - uint8_t PacketClass(); - uint8_t PacketType(); - uint8_t PacketSubType() const; - - /// For Service Packets - RsItem(uint8_t ver, uint16_t service, uint8_t subtype); - uint16_t PacketService() const; /* combined Packet class/type (mid 16bits) */ - void setPacketService(uint16_t service); - - inline uint8_t priority_level() const { return _priority_level ;} - inline void setPriorityLevel(uint8_t l) { _priority_level = l ;} - - /* - * TODO: This default implementation should be removed and childs structs - * implement ::serial_process(...) as soon as all the codebase is ported to - * the new serialization system - */ - virtual void serial_process(RsGenericSerializer::SerializeJob, - RsGenericSerializer::SerializeContext&)// = 0; - { - std::cerr << "(EE) RsItem::serial_process(...) called by an item using" - << "new serialization classes, but not derived! Class is " - << typeid(*this).name() << std::endl; - print_stacktrace(); - } - -protected: - uint32_t type; - RsPeerId peerId; - uint8_t _priority_level; -}; - -/// TODO: Do this make sense with the new serialization system? -class RsRawItem: public RsItem -{ -public: - RsRawItem(uint32_t t, uint32_t size) : RsItem(t), len(size) - { data = rs_malloc(len); } - virtual ~RsRawItem() { free(data); } - - uint32_t getRawLength() { return len; } - void * getRawData() { return data; } - - virtual void clear() {} - virtual std::ostream &print(std::ostream &out, uint16_t indent = 0); - -private: - void *data; - uint32_t len; -}; diff --git a/libretroshare/src/rsitems/rsmsgitems.cc b/libretroshare/src/rsitems/rsmsgitems.cc deleted file mode 100644 index 8060248f4..000000000 --- a/libretroshare/src/rsitems/rsmsgitems.cc +++ /dev/null @@ -1,166 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsmsgitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include "util/rstime.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" - -#include "rsitems/rsmsgitems.h" - -#include "serialiser/rstypeserializer.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - - -RsItem *RsMsgSerialiser::create_item(uint16_t service,uint8_t type) const -{ - if(service != RS_SERVICE_TYPE_MSG) - return NULL ; - - switch(type) - { - case RS_PKT_SUBTYPE_DEFAULT : return new RsMsgItem() ; //= 0x01; - case RS_PKT_SUBTYPE_MSG_TAG_TYPE : return new RsMsgTagType() ; //= 0x03; - case RS_PKT_SUBTYPE_MSG_TAGS : return new RsMsgTags() ; //= 0x04; - case RS_PKT_SUBTYPE_MSG_SRC_TAG : return new RsMsgSrcId(); //= 0x05; - case RS_PKT_SUBTYPE_MSG_PARENT_TAG : return new RsMsgParentId() ; //= 0x06; - case RS_PKT_SUBTYPE_MSG_GROUTER_MAP : return new RsMsgGRouterMap(); //= 0x08; - case RS_PKT_SUBTYPE_MSG_DISTANT_MSG_MAP : return new RsMsgDistantMessagesHashMap();//= 0x09; - default: - return NULL ; - } -} - -void RsMsgItem::clear() -{ - msgId = 0; - msgFlags = 0; - sendTime = 0; - recvTime = 0; - subject.clear(); - message.clear(); - - rspeerid_msgto.TlvClear(); - rspeerid_msgcc.TlvClear(); - rspeerid_msgbcc.TlvClear(); - - rsgxsid_msgto.TlvClear(); - rsgxsid_msgcc.TlvClear(); - rsgxsid_msgbcc.TlvClear(); - - attachment.TlvClear(); -} - -void RsMsgTagType::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_NAME,text,"text") ; - RsTypeSerializer::serial_process(j,ctx,rgb_color,"rgb_color") ; - RsTypeSerializer::serial_process(j,ctx,tagId,"tagId") ; -} - -void RsMsgTags::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,msgId,"msgId") ; - -#warning this is not the correct way to serialise here. We should directly call serial_process >() but for backward compatibility, we cannot - - if(j == RsGenericSerializer::DESERIALIZE) - while(ctx.mOffset < ctx.mSize) - { - uint32_t n = 0;// No real need to initialize but otherwise the compiler complains. - RsTypeSerializer::serial_process(j,ctx,n,"tagIds element") ; - tagIds.push_back(n) ; - } - else - for(std::list::iterator it(tagIds.begin());it!=tagIds.end();++it) - RsTypeSerializer::serial_process(j,ctx,*it,"tagIds element") ; -} - -void RsMsgSrcId::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,msgId,"msgId") ; - RsTypeSerializer::serial_process (j,ctx,srcId,"srcId") ; -} - -void RsMsgGRouterMap::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,ongoing_msgs,"ongoing_msgs") ; -} - -void RsMsgGRouterMap::clear() -{ - ongoing_msgs.clear() ; - - return; -} - -void RsMsgDistantMessagesHashMap::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,hash_map,"hash_map") ; -} - -void RsMsgParentId::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,msgId,"msgId") ; - RsTypeSerializer::serial_process(j,ctx,msgParentId,"msgParentId") ; -} - -void RsMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,msgFlags,"msgFlags"); - RsTypeSerializer::serial_process(j,ctx,sendTime,"sendTime"); - RsTypeSerializer::serial_process(j,ctx,recvTime,"recvTime"); - - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_SUBJECT,subject,"subject"); - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_MSG,message,"message"); - - RsTypeSerializer::serial_process(j,ctx,rspeerid_msgto,"rspeerid_msgto"); - RsTypeSerializer::serial_process(j,ctx,rspeerid_msgcc,"rspeerid_msgcc"); - RsTypeSerializer::serial_process(j,ctx,rspeerid_msgbcc,"rspeerid_msgbcc"); - - RsTypeSerializer::serial_process(j,ctx,rsgxsid_msgto,"rsgxsid_msgto"); - RsTypeSerializer::serial_process(j,ctx,rsgxsid_msgcc,"rsgxsid_msgcc"); - RsTypeSerializer::serial_process(j,ctx,rsgxsid_msgbcc,"rsgxsid_msgbcc"); - - RsTypeSerializer::serial_process(j,ctx,attachment,"attachment"); - - if(!!(ctx.mFlags & RsSerializationFlags::CONFIG)) - RS_SERIAL_PROCESS(msgId); -} - -void RsMsgTagType::clear() -{ - text.clear(); - tagId = 0; - rgb_color = 0; -} - -void RsMsgTags::clear() -{ - msgId = 0; - tagIds.clear(); -} - diff --git a/libretroshare/src/rsitems/rsmsgitems.h b/libretroshare/src/rsitems/rsmsgitems.h deleted file mode 100644 index 27447aec0..000000000 --- a/libretroshare/src/rsitems/rsmsgitems.h +++ /dev/null @@ -1,225 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsmsgitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include "retroshare/rstypes.h" -#include "serialiser/rstlvkeys.h" -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserial.h" - -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvfileitem.h" -#include "grouter/grouteritems.h" - - -/**************************************************************************/ - -// for defining tags themselves and msg tags -const uint8_t RS_PKT_SUBTYPE_MSG_TAG_TYPE = 0x03; -const uint8_t RS_PKT_SUBTYPE_MSG_TAGS = 0x04; -const uint8_t RS_PKT_SUBTYPE_MSG_SRC_TAG = 0x05; -const uint8_t RS_PKT_SUBTYPE_MSG_PARENT_TAG = 0x06; -const uint8_t RS_PKT_SUBTYPE_MSG_INVITE = 0x07; -const uint8_t RS_PKT_SUBTYPE_MSG_GROUTER_MAP = 0x08; -const uint8_t RS_PKT_SUBTYPE_MSG_DISTANT_MSG_MAP = 0x09; - - -/**************************************************************************/ - -const uint32_t RS_MSG_FLAGS_OUTGOING = 0x00000001; -const uint32_t RS_MSG_FLAGS_PENDING = 0x00000002; -const uint32_t RS_MSG_FLAGS_DRAFT = 0x00000004; -const uint32_t RS_MSG_FLAGS_NEW = 0x00000010; -const uint32_t RS_MSG_FLAGS_TRASH = 0x00000020; -const uint32_t RS_MSG_FLAGS_UNREAD_BY_USER = 0x00000040; -const uint32_t RS_MSG_FLAGS_REPLIED = 0x00000080; -const uint32_t RS_MSG_FLAGS_FORWARDED = 0x00000100; -const uint32_t RS_MSG_FLAGS_STAR = 0x00000200; -const uint32_t RS_MSG_FLAGS_PARTIAL = 0x00000400; -const uint32_t RS_MSG_FLAGS_USER_REQUEST = 0x00000800; -const uint32_t RS_MSG_FLAGS_FRIEND_RECOMMENDATION = 0x00001000; -const uint32_t RS_MSG_FLAGS_RETURN_RECEPT = 0x00002000; -const uint32_t RS_MSG_FLAGS_ENCRYPTED = 0x00004000; -const uint32_t RS_MSG_FLAGS_DISTANT = 0x00008000; -const uint32_t RS_MSG_FLAGS_SIGNATURE_CHECKS = 0x00010000; -const uint32_t RS_MSG_FLAGS_SIGNED = 0x00020000; -const uint32_t RS_MSG_FLAGS_LOAD_EMBEDDED_IMAGES = 0x00040000; -const uint32_t RS_MSG_FLAGS_DECRYPTED = 0x00080000; -const uint32_t RS_MSG_FLAGS_ROUTED = 0x00100000; -const uint32_t RS_MSG_FLAGS_PUBLISH_KEY = 0x00200000; -const uint32_t RS_MSG_FLAGS_SPAM = 0x00400000; - -const uint32_t RS_MSG_FLAGS_SYSTEM = RS_MSG_FLAGS_USER_REQUEST | RS_MSG_FLAGS_FRIEND_RECOMMENDATION | RS_MSG_FLAGS_PUBLISH_KEY; - -class RsMessageItem: public RsItem -{ - public: - RsMessageItem(uint8_t msg_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_MSG,msg_subtype) - { - setPriorityLevel(QOS_PRIORITY_RS_MSG_ITEM) ; - } - - virtual ~RsMessageItem() {} - virtual void clear() {} -}; - - -class RsMsgItem: public RsMessageItem -{ - public: - RsMsgItem() :RsMessageItem(RS_PKT_SUBTYPE_DEFAULT) {} - - virtual ~RsMsgItem() {} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - // ----------- Specific fields ------------- // - - uint32_t msgFlags; - uint32_t msgId; - - uint32_t sendTime; - uint32_t recvTime; - - std::string subject; - std::string message; - - RsTlvPeerIdSet rspeerid_msgto; - RsTlvPeerIdSet rspeerid_msgcc; - RsTlvPeerIdSet rspeerid_msgbcc; - - RsTlvGxsIdSet rsgxsid_msgto; - RsTlvGxsIdSet rsgxsid_msgcc; - RsTlvGxsIdSet rsgxsid_msgbcc; - - RsTlvFileSet attachment; -}; - -class RsMsgTagType : public RsMessageItem -{ - public: - RsMsgTagType() :RsMessageItem(RS_PKT_SUBTYPE_MSG_TAG_TYPE) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - virtual ~RsMsgTagType() {} - virtual void clear(); - - // ----------- Specific fields ------------- // - // - std::string text; - uint32_t rgb_color; - uint32_t tagId; -}; - -class RsMsgTags : public RsMessageItem -{ -public: - RsMsgTags() - :RsMessageItem(RS_PKT_SUBTYPE_MSG_TAGS) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - virtual ~RsMsgTags() {} - virtual void clear(); - - // ----------- Specific fields ------------- // - // - uint32_t msgId; - std::list tagIds; -}; - -class RsMsgSrcId : public RsMessageItem -{ - public: - RsMsgSrcId() : RsMessageItem(RS_PKT_SUBTYPE_MSG_SRC_TAG) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - virtual ~RsMsgSrcId() {} - virtual void clear(){} - - // ----------- Specific fields ------------- // - // - - uint32_t msgId; - RsPeerId srcId; -}; - -class RsMsgGRouterMap : public RsMessageItem -{ - public: - RsMsgGRouterMap() : RsMessageItem(RS_PKT_SUBTYPE_MSG_GROUTER_MAP) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - virtual ~RsMsgGRouterMap() {} - virtual void clear(); - - // ----------- Specific fields ------------- // - // - std::map ongoing_msgs ; -}; -class RsMsgDistantMessagesHashMap : public RsMessageItem -{ - public: - RsMsgDistantMessagesHashMap() : RsMessageItem(RS_PKT_SUBTYPE_MSG_DISTANT_MSG_MAP) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - virtual ~RsMsgDistantMessagesHashMap() {} - virtual void clear() { hash_map.clear() ;} - - // ----------- Specific fields ------------- // - // - std::map hash_map ; -}; -class RsMsgParentId : public RsMessageItem -{ - public: - RsMsgParentId() : RsMessageItem(RS_PKT_SUBTYPE_MSG_PARENT_TAG) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - virtual ~RsMsgParentId() {} - virtual void clear(){} - - // ----------- Specific fields ------------- // - // - uint32_t msgId; - uint32_t msgParentId; -}; - -class RsMsgSerialiser: public RsServiceSerializer -{ -public: - RsMsgSerialiser( - RsSerializationFlags flags = RsSerializationFlags::NONE ): - RsServiceSerializer(RS_SERVICE_TYPE_MSG, flags){} - - RsItem* create_item(uint16_t service,uint8_t type) const override; - - ~RsMsgSerialiser() override = default; -}; diff --git a/libretroshare/src/rsitems/rsnxsitems.cc b/libretroshare/src/rsitems/rsnxsitems.cc deleted file mode 100644 index e8178e045..000000000 --- a/libretroshare/src/rsitems/rsnxsitems.cc +++ /dev/null @@ -1,253 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsnxsitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker,Robert Fernie* - * * - * 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 . * - * * - *******************************************************************************/ -#include "rsnxsitems.h" -#include "util/rsprint.h" -#include - -#include "serialiser/rstypeserializer.h" - -/*** - * #define RSSERIAL_DEBUG 1 - ***/ - -const uint8_t RsNxsSyncGrpItem::FLAG_REQUEST = 0x001; -const uint8_t RsNxsSyncGrpItem::FLAG_RESPONSE = 0x002; - -const uint8_t RsNxsSyncMsgItem::FLAG_REQUEST = 0x001; -const uint8_t RsNxsSyncMsgItem::FLAG_RESPONSE = 0x002; - -const uint8_t RsNxsSyncGrpItem::FLAG_USE_SYNC_HASH = 0x0001; -const uint8_t RsNxsSyncMsgItem::FLAG_USE_SYNC_HASH = 0x0001; - -const uint8_t RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID = 0x02; - -/** transaction state **/ -const uint16_t RsNxsTransacItem::FLAG_BEGIN_P1 = 0x0001; -const uint16_t RsNxsTransacItem::FLAG_BEGIN_P2 = 0x0002; -const uint16_t RsNxsTransacItem::FLAG_END_SUCCESS = 0x0004; -const uint16_t RsNxsTransacItem::FLAG_CANCEL = 0x0008; -const uint16_t RsNxsTransacItem::FLAG_END_FAIL_NUM = 0x0010; -const uint16_t RsNxsTransacItem::FLAG_END_FAIL_TIMEOUT = 0x0020; -const uint16_t RsNxsTransacItem::FLAG_END_FAIL_FULL = 0x0040; - - -/** transaction type **/ -const uint16_t RsNxsTransacItem::FLAG_TYPE_GRP_LIST_RESP = 0x0100; -const uint16_t RsNxsTransacItem::FLAG_TYPE_MSG_LIST_RESP = 0x0200; -const uint16_t RsNxsTransacItem::FLAG_TYPE_GRP_LIST_REQ = 0x0400; -const uint16_t RsNxsTransacItem::FLAG_TYPE_MSG_LIST_REQ = 0x0800; -const uint16_t RsNxsTransacItem::FLAG_TYPE_GRPS = 0x1000; -const uint16_t RsNxsTransacItem::FLAG_TYPE_MSGS = 0x2000; -const uint16_t RsNxsTransacItem::FLAG_TYPE_ENCRYPTED_DATA = 0x4000; - -RsItem *RsNxsSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) const -{ - if(service_id != SERVICE_TYPE) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM: return new RsNxsSyncGrpReqItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM: return new RsNxsSyncGrpItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM: return new RsNxsSyncMsgReqItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM: return new RsNxsSyncMsgItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_GRP_ITEM: return new RsNxsGrp(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_MSG_ITEM: return new RsNxsMsg(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_TRANSAC_ITEM: return new RsNxsTransacItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM:return new RsNxsGroupPublishKeyItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM: return new RsNxsEncryptedDataItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM: return new RsNxsSyncGrpStatsItem(SERVICE_TYPE) ; - - default: - return NULL; - } -} - -void RsNxsSyncMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process (j,ctx,flag ,"flag") ; - RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; - RsTypeSerializer::serial_process (j,ctx,msgId ,"msgId") ; - RsTypeSerializer::serial_process (j,ctx,authorId ,"authorId") ; -} - -void RsNxsMsg::serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(transactionNumber); - RS_SERIAL_PROCESS(pos); - RS_SERIAL_PROCESS(msgId); - RS_SERIAL_PROCESS(grpId); - RS_SERIAL_PROCESS(msg); - RS_SERIAL_PROCESS(meta); -} - -void RsNxsGrp::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process (j,ctx,pos ,"pos") ; - RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; - RsTypeSerializer::serial_process(j,ctx,grp ,"grp") ; - RsTypeSerializer::serial_process(j,ctx,meta ,"meta") ; -} - -void RsNxsSyncGrpStatsItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,request_type ,"request_type") ; - RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; - RsTypeSerializer::serial_process (j,ctx,number_of_posts,"number_of_posts") ; - RsTypeSerializer::serial_process (j,ctx,last_post_TS ,"last_post_TS") ; -} - -void RsNxsSyncGrpReqItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process (j,ctx,flag ,"flag") ; - RsTypeSerializer::serial_process(j,ctx,createdSince ,"createdSince") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_HASH_SHA1,syncHash,"syncHash") ; - RsTypeSerializer::serial_process(j,ctx,updateTS ,"updateTS") ; -} - -void RsNxsTransacItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process(j,ctx,transactFlag ,"transactFlag") ; - RsTypeSerializer::serial_process(j,ctx,nItems ,"nItems") ; - RsTypeSerializer::serial_process(j,ctx,updateTS ,"updateTS") ; -} -void RsNxsSyncGrpItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process (j,ctx,flag ,"flag") ; - RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; - RsTypeSerializer::serial_process(j,ctx,publishTs ,"publishTs") ; - RsTypeSerializer::serial_process (j,ctx,authorId ,"authorId") ; -} -void RsNxsSyncMsgReqItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process (j,ctx,flag ,"flag") ; - RsTypeSerializer::serial_process(j,ctx,createdSinceTS ,"createdSinceTS") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_HASH_SHA1,syncHash,"syncHash") ; - RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; - RsTypeSerializer::serial_process(j,ctx,updateTS ,"updateTS") ; -} -void RsNxsGroupPublishKeyItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; - RsTypeSerializer::serial_process(j,ctx,private_key ,"private_key") ; -} -void RsNxsEncryptedDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process(j,ctx,encrypted_data, "encrypted_data") ; -} - -int RsNxsGrp::refcount = 0; -int RsNxsMsg::refcount = 0; - -/** print and clear functions **/ -void RsNxsMsg::clear() -{ - - msg.TlvClear(); - meta.TlvClear(); -} - -void RsNxsGrp::clear() -{ - grpId.clear(); - grp.TlvClear(); - meta.TlvClear(); -} - -RsNxsGrp* RsNxsGrp::clone() const { - RsNxsGrp* grp = new RsNxsGrp(this->grp.tlvtype); - *grp = *this; - - if(this->metaData) - { - grp->metaData = new RsGxsGrpMetaData(); - *(grp->metaData) = *(this->metaData); - } - - return grp; -} - -void RsNxsSyncGrpReqItem::clear() -{ - flag = 0; - createdSince = 0; - updateTS = 0; - syncHash.clear(); -} -void RsNxsGroupPublishKeyItem::clear() -{ - private_key.TlvClear(); -} -void RsNxsSyncMsgReqItem::clear() -{ - grpId.clear(); - flag = 0; - createdSinceTS = 0; - updateTS = 0; - syncHash.clear(); -} -void RsNxsSyncGrpItem::clear() -{ - flag = 0; - publishTs = 0; - grpId.clear(); - authorId.clear(); -} - -void RsNxsSyncMsgItem::clear() -{ - flag = 0; - grpId.clear(); - msgId.clear(); - authorId.clear(); -} - -void RsNxsTransacItem::clear(){ - transactFlag = 0; - nItems = 0; - updateTS = 0; - timestamp = 0; - transactionNumber = 0; -} -void RsNxsEncryptedDataItem::clear(){ - encrypted_data.TlvClear() ; -} - -#ifdef SUSPENDED_CODE_27042017 -void RsNxsSessionKeyItem::clear() -{ - for(std::map::iterator it(encrypted_session_keys.begin());it!=encrypted_session_keys.end();++it) - it->second.TlvClear() ; - - encrypted_session_keys.clear() ; -} -#endif - - diff --git a/libretroshare/src/rsitems/rsnxsitems.h b/libretroshare/src/rsitems/rsnxsitems.h deleted file mode 100644 index 2b6731bfc..000000000 --- a/libretroshare/src/rsitems/rsnxsitems.h +++ /dev/null @@ -1,516 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsnxsitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker,Robert Fernie* - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSNXSITEMS_H -#define RSNXSITEMS_H - -#include -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvkeys.h" -#include "gxs/rsgxsdata.h" - -// These items have "flag type" numbers, but this is not used. - -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM = 0x01; -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM = 0x03; -const uint8_t RS_PKT_SUBTYPE_NXS_GRP_ITEM = 0x04; -const uint8_t RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM = 0x05; -const uint8_t RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM = 0x06; -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM = 0x08; -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM = 0x10; -const uint8_t RS_PKT_SUBTYPE_NXS_MSG_ITEM = 0x20; -const uint8_t RS_PKT_SUBTYPE_NXS_TRANSAC_ITEM = 0x40; -const uint8_t RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM = 0x80; - -// possibility create second service to deal with this functionality - -const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_GRP = 0x0001; -const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_MSG = 0x0002; -const uint8_t RS_PKT_SUBTYPE_EXT_DELETE_GRP = 0x0004; -const uint8_t RS_PKT_SUBTYPE_EXT_DELETE_MSG = 0x0008; -const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_REQ = 0x0010; - - -/*! - * Base class for Network exchange service - * Main purpose is for rtti based routing used in the - * serialisation and deserialisation of NXS packets - * - * Service type is set by plugin service - */ -class RsNxsItem : public RsItem -{ - -public: - RsNxsItem(uint16_t servtype, uint8_t subtype) : RsItem(RS_PKT_VERSION_SERVICE, servtype, subtype), transactionNumber(0) - { - setPriorityLevel(QOS_PRIORITY_RS_GXS_NET); - return; - } - virtual ~RsNxsItem(){} - virtual void clear() = 0; - - uint32_t transactionNumber; // set to zero if this is not a transaction item -}; - - -/*! - * Use to request grp list from peer - * Server may advise client peer to use sync file - * while serving his request. This results - */ -class RsNxsSyncGrpReqItem : public RsNxsItem -{ -public: - - static const uint8_t FLAG_USE_SYNC_HASH; - static const uint8_t FLAG_ONLY_CURRENT; // only send most current version of grps / ignores sync hash - - explicit RsNxsSyncGrpReqItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM) { clear();} - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - uint8_t flag; // advises whether to use sync hash - uint32_t createdSince; // how far back to sync data - uint32_t updateTS; // time of last group update - std::string syncHash; // use to determine if changes that have occured since last hash -}; - -/*! - * Use to request statistics about a particular group - */ -class RsNxsSyncGrpStatsItem : public RsNxsItem -{ -public: - - explicit RsNxsSyncGrpStatsItem(uint16_t servtype) - : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM) - , request_type(0), number_of_posts(0), last_post_TS(0) - {} - - virtual void clear() override {} - - static const uint8_t GROUP_INFO_TYPE_REQUEST = 0x01; - static const uint8_t GROUP_INFO_TYPE_RESPONSE = 0x02; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - uint32_t request_type; // used to determine the type of request - RsGxsGroupId grpId; // id of the group - uint32_t number_of_posts; // number of posts in that group - uint32_t last_post_TS; // time_stamp of last post -}; - -/*! - * Use to request grp list from peer - * Server may advise client peer to use sync file - * while serving his request. This results - */ -class RsNxsGroupPublishKeyItem : public RsNxsItem -{ -public: - explicit RsNxsGroupPublishKeyItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM) { clear(); } - - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - RsGxsGroupId grpId ; - RsTlvPrivateRSAKey private_key ; -}; - - - -/*! - * This RsNxsItem is for use in enabling transactions - * in order to guaranttee a collection of item have been - * received - */ -class RsNxsTransacItem: public RsNxsItem { - -public: - - static const uint16_t FLAG_STATE_MASK = 0xff; - static const uint16_t FLAG_TYPE_MASK = 0xff00; - - /** transaction state **/ - static const uint16_t FLAG_BEGIN_P1; - static const uint16_t FLAG_BEGIN_P2; - static const uint16_t FLAG_END_SUCCESS; - static const uint16_t FLAG_CANCEL; - static const uint16_t FLAG_END_FAIL_NUM; - static const uint16_t FLAG_END_FAIL_TIMEOUT; - static const uint16_t FLAG_END_FAIL_FULL; - - - /** transaction type **/ - static const uint16_t FLAG_TYPE_GRP_LIST_RESP; - static const uint16_t FLAG_TYPE_MSG_LIST_RESP; - static const uint16_t FLAG_TYPE_GRP_LIST_REQ; - static const uint16_t FLAG_TYPE_MSG_LIST_REQ; - static const uint16_t FLAG_TYPE_GRPS; - static const uint16_t FLAG_TYPE_MSGS; - static const uint16_t FLAG_TYPE_ENCRYPTED_DATA; - - explicit RsNxsTransacItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_TRANSAC_ITEM) { clear(); } - virtual ~RsNxsTransacItem() {} - - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - uint16_t transactFlag; - uint32_t nItems; - uint32_t updateTS; - - // not serialised - uint32_t timestamp; -}; - -/*! - * Use to send to peer list of grps - * held by server peer - */ -class RsNxsSyncGrpItem: public RsNxsItem -{ - -public: - - static const uint8_t FLAG_REQUEST; - static const uint8_t FLAG_RESPONSE; - static const uint8_t FLAG_USE_SYNC_HASH; - - explicit RsNxsSyncGrpItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM) { clear();} - virtual ~RsNxsSyncGrpItem() {} - - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - uint8_t flag; // request or response - uint32_t publishTs; // to compare to Ts of receiving peer's grp of same id - - /// grpId of grp held by sending peer - RsGxsGroupId grpId; - RsGxsId authorId; - -}; - -#ifdef SUSPENDED_CODE_27042017 -/*! - * Use to send to peer list of grps - * held by server peer - */ -class RsNxsSessionKeyItem : public RsNxsItem -{ - -public: - - explicit RsNxsSessionKeyItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM) { clear(); } - virtual ~RsNxsSessionKeyItem() {} - - virtual void clear() override; - - /// Session key encrypted for the whole group - /// - uint8_t iv[EVP_MAX_IV_LENGTH] ; // initialisation vector - std::map encrypted_session_keys; // encrypted session keys -}; -#endif -/*! - * Use to send to peer list of grps - * held by server peer - */ -class RsNxsEncryptedDataItem : public RsNxsItem -{ - -public: - - explicit RsNxsEncryptedDataItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM),encrypted_data(servtype) - { - encrypted_data.tlvtype = TLV_TYPE_BIN_ENCRYPTED ; - clear(); - } - virtual ~RsNxsEncryptedDataItem() {} - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - /// grpId of grp held by sending peer - /// - RsTlvBinaryData encrypted_data ; -}; - - -/*! - * Contains serialised group items - * Each item corresponds to a group which needs to be - * deserialised - */ -class RsNxsGrp : public RsNxsItem -{ - -public: - - explicit RsNxsGrp(uint16_t servtype) - : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_GRP_ITEM) - , pos(0), count(0), meta(servtype), grp(servtype), metaData(NULL) - { clear(); } - virtual ~RsNxsGrp() { delete metaData; } - - RsNxsGrp* clone() const; - - virtual void clear() override; - - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - uint8_t pos; /// used for splitting up grp - uint8_t count; /// number of split up messages - RsGxsGroupId grpId; /// group Id, needed to complete version Id (ncvi) - static int refcount; - - /*! - * This should contains all data - * which is not specific to the Gxs service data - */ - // This is the binary data for the group meta that is sent to friends. It *should not* contain any private - // key parts. This is ensured in RsGenExchange - - RsTlvBinaryData meta; - - RsTlvBinaryData grp; /// actual group data - - // Deserialised metaData, this is not serialised by the serialize() method. So it may contain private key parts in some cases. - RsGxsGrpMetaData* metaData; -}; - -/*! - * Use to request list of msg held by peer - * for a given group - */ -class RsNxsSyncMsgReqItem : public RsNxsItem -{ - -public: - -#ifdef UNUSED_CODE - static const uint8_t FLAG_USE_SYNC_HASH; -#endif - static const uint8_t FLAG_USE_HASHED_GROUP_ID; - - explicit RsNxsSyncMsgReqItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM) { clear(); } - - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - RsGxsGroupId grpId; - uint8_t flag; - uint32_t createdSinceTS; - uint32_t updateTS; // time of last update - std::string syncHash; -}; - -/*! - * Use to send list msgs for a group held by - * a peer - */ -class RsNxsSyncMsgItem : public RsNxsItem -{ -public: - - static const uint8_t FLAG_REQUEST; - static const uint8_t FLAG_RESPONSE; - static const uint8_t FLAG_USE_SYNC_HASH; - explicit RsNxsSyncMsgItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM) { clear(); } - - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - uint8_t flag; // response/req - RsGxsGroupId grpId; - RsGxsMessageId msgId; - RsGxsId authorId; - -}; - - -/*! - * Used to respond to a RsGrpMsgsReq - * with message items satisfying request - */ -struct RsNxsMsg : RsNxsItem -{ - explicit RsNxsMsg(uint16_t servtype) - : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_MSG_ITEM) - , pos(0), count(0), meta(servtype), msg(servtype), metaData(NULL) - { clear(); } - virtual ~RsNxsMsg() { delete metaData; } - - virtual void clear() override; - - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - uint8_t pos; /// used for splitting up msg - uint8_t count; /// number of split up messages - RsGxsGroupId grpId; /// group id, forms part of version id - RsGxsMessageId msgId; /// msg id - static int refcount; - - /*! - * This should contains all the data - * which is not specific to the Gxs service data - */ - RsTlvBinaryData meta; - - /*! - * This contains Gxs specific data - * only client of API knows how to decode this - */ - RsTlvBinaryData msg; - - RsGxsMsgMetaData* metaData; -}; - -/*! - * Used to request a search of user data - */ -class RsNxsSearchReqItem : public RsNxsItem -{ -public: - - explicit RsNxsSearchReqItem(uint16_t servtype) - : RsNxsItem(servtype, RS_PKT_SUBTYPE_EXT_SEARCH_REQ) - , nHops(0), token(0), serviceSearchItem(servtype), expiration(0) - {} - virtual ~RsNxsSearchReqItem() {} - virtual void clear() override {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - uint8_t nHops; /// how many peers to jump to - uint32_t token; // search token - RsTlvBinaryData serviceSearchItem; // service aware of item class - uint32_t expiration; // expiration date -}; - - -#ifdef UNUSED_CODE - -/*! - * Used to respond to a RsGrpSearchReq - * with grpId/MsgIds that satisfy search request - */ -class RsNxsSearchResultMsgItem -{ -public: - - RsNxsSearchResultMsgItem() - : token(0), context(0), expiration(0) - {} - - void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t token; // search token to be redeemed - RsTlvBinaryData context; // used by client service - std::string msgId; - std::string grpId; - RsTlvKeySignature idSign; - - uint32_t expiration; // expiration date -}; - -/*! - * Used to respond to a RsGrpSearchReq - * with grpId/MsgIds that satisfy search request - */ -class RsNxsSearchResultGrpItem -{ -public: - - RsNxsSearchResultGrpItem(); - - void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t token; // search token to be redeemed - RsTlvBinaryData context; // used by client service - - std::string grpId; - RsTlvKeySignature adminSign; - - uint32_t expiration; // expiration date -}; - -class RsNxsDeleteMsg -{ -public: - - RsNxsDeleteMsg() { return; } - - std::string msgId; - std::string grpId; - RsTlvKeySignature deleteSign; // ( msgId + grpId + msg data ) sign //TODO: add warning not to place msgId+grpId in msg! - -}; - -class RsNxsDeleteGrp -{ -public: - - RsNxsDeleteGrp() { return;} - - std::string grpId; - RsTlvKeySignature idSign; - RsTlvKeySignature deleteSign; // (grpId + grp data) sign // TODO: add warning not to place grpId in msg -}; -#endif - - -class RsNxsSerialiser : public RsServiceSerializer -{ -public: - - explicit RsNxsSerialiser(uint16_t servtype) : RsServiceSerializer(servtype), SERVICE_TYPE(servtype) {} - virtual ~RsNxsSerialiser() {} - - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ; -protected: - const uint16_t SERVICE_TYPE; -}; - - -#endif // RSNXSITEMS_H diff --git a/libretroshare/src/rsitems/rsphotoitems.cc b/libretroshare/src/rsitems/rsphotoitems.cc deleted file mode 100644 index f9200a83c..000000000 --- a/libretroshare/src/rsitems/rsphotoitems.cc +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsphotoitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker,Robert Fernie* - * * - * 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 . * - * * - *******************************************************************************/ -#include - -#include "rsitems/rsphotoitems.h" - -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstypeserializer.h" - -RsItem *RsGxsPhotoSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const -{ - if(service != RS_SERVICE_GXS_TYPE_PHOTO) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM: return new RsGxsPhotoPhotoItem() ; - case RS_PKT_SUBTYPE_PHOTO_ITEM: return new RsGxsPhotoAlbumItem() ; - default: - return RsGxsCommentSerialiser::create_item(service,item_sub_id) ; - } -} - -void RsGxsPhotoAlbumItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_UINT32_PARAM,album.mShareMode,"mShareMode"); - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_CAPTION, album.mCaption, "mCaption"); - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR, album.mDescription, "mDescription"); - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_NAME, album.mPhotographer, "mPhotographer"); - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_LOCATION, album.mWhere, "mWhere"); - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DATE, album.mWhen, "mWhen"); - - album.mThumbnail.serial_process(j, ctx); -} -void RsGxsPhotoPhotoItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR, photo.mDescription, "mDescription"); - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_UINT32_PARAM,photo.mOrder,"mOrder"); - photo.mLowResImage.serial_process(j, ctx); - photo.mPhotoFile.serial_process(j, ctx); -} - -void RsGxsPhotoAlbumItem::clear() -{ - album.mShareMode = RSPHOTO_SHAREMODE_LOWRESONLY; - album.mCaption.clear(); - album.mDescription.clear(); - album.mPhotographer.clear(); - album.mWhere.clear(); - album.mWhen.clear(); - album.mThumbnail.clear(); - - // not saved - album.mAutoDownload = false; -} - -void RsGxsPhotoPhotoItem::clear() -{ - photo.mDescription.clear(); - photo.mOrder = 0; - photo.mLowResImage.clear(); - photo.mPhotoFile.clear(); - - // not saved - photo.mPath.clear(); -} diff --git a/libretroshare/src/rsitems/rsphotoitems.h b/libretroshare/src/rsitems/rsphotoitems.h deleted file mode 100644 index a504ae29b..000000000 --- a/libretroshare/src/rsitems/rsphotoitems.h +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsphotoitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker,Robert Fernie* - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSPHOTOV2ITEMS_H_ -#define RSPHOTOV2ITEMS_H_ - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsgxsitems.h" -#include "rsitems/rsgxscommentitems.h" - -#include "serialiser/rsserial.h" -#include "serialiser/rsserializer.h" - -#include "retroshare/rsphoto.h" - -const uint8_t RS_PKT_SUBTYPE_PHOTO_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM = 0x03; - -class RsGxsPhotoAlbumItem : public RsGxsGrpItem -{ - -public: - - RsGxsPhotoAlbumItem(): RsGxsGrpItem(RS_SERVICE_GXS_TYPE_PHOTO, - RS_PKT_SUBTYPE_PHOTO_ITEM) { return;} - virtual ~RsGxsPhotoAlbumItem() { return;} - - void clear(); -// std::ostream &print(std::ostream &out, uint16_t indent = 0); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsPhotoAlbum album; -}; - -class RsGxsPhotoPhotoItem : public RsGxsMsgItem -{ -public: - - RsGxsPhotoPhotoItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_PHOTO, RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM) {} - virtual ~RsGxsPhotoPhotoItem() {} - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsPhotoPhoto photo; -}; - -class RsGxsPhotoSerialiser : public RsGxsCommentSerialiser -{ -public: - - RsGxsPhotoSerialiser() :RsGxsCommentSerialiser(RS_SERVICE_GXS_TYPE_PHOTO) {} - virtual ~RsGxsPhotoSerialiser() {} - - virtual RsItem *create_item(uint16_t service, uint8_t item_sub_id) const; -}; - -#endif /* RSPHOTOV2ITEMS_H_ */ diff --git a/libretroshare/src/rsitems/rspluginitems.h b/libretroshare/src/rsitems/rspluginitems.h deleted file mode 100644 index 29069815d..000000000 --- a/libretroshare/src/rsitems/rspluginitems.h +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rspluginitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "rsitems/rsitem.h" -#include "rsitems/rsconfigitems.h" - -#include "serialiser/rstypeserializer.h" - -const uint8_t RS_PKT_CLASS_PLUGIN_SUBTYPE_HASHSET = 0x01 ; - -class RsPluginItem: public RsItem -{ - public: - explicit RsPluginItem(uint8_t plugin_item_subtype): RsItem(RS_PKT_VERSION1,RS_PKT_CLASS_CONFIG,RS_PKT_TYPE_PLUGIN_CONFIG,plugin_item_subtype) {} - virtual ~RsPluginItem() {} - - virtual void clear() {} -}; - -class RsPluginHashSetItem: public RsPluginItem -{ - public: - RsPluginHashSetItem() : RsPluginItem(RS_PKT_CLASS_PLUGIN_SUBTYPE_HASHSET) {} - RsPluginHashSetItem(void *data,uint32_t size) ; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,hashes,"hashes"); - } - - RsTlvHashSet hashes ; -}; - -class RsPluginSerialiser: public RsConfigSerializer -{ - public: - RsPluginSerialiser() : RsConfigSerializer(RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PLUGIN_CONFIG) {} - - virtual RsItem *create_item(uint8_t class_type, uint8_t item_type) const - { - if(class_type == RS_PKT_TYPE_PLUGIN_CONFIG && item_type == RS_PKT_CLASS_PLUGIN_SUBTYPE_HASHSET) - return new RsPluginHashSetItem() ; - - return NULL ; - } -}; - - diff --git a/libretroshare/src/rsitems/rsposteditems.cc b/libretroshare/src/rsitems/rsposteditems.cc deleted file mode 100644 index 3c16ff5bd..000000000 --- a/libretroshare/src/rsitems/rsposteditems.cc +++ /dev/null @@ -1,158 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsposteditems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "rsitems/rsposteditems.h" -#include "serialiser/rstypeserializer.h" - - - -void RsGxsPostedPostItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_LINK,mPost.mLink,"mPost.mLink") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG ,mPost.mNotes,"mPost.mNotes") ; - - // Do not serialize mImage member if it is empty (keeps compatibility of new posts without image toward older RS) - // and do not expect to deserialize mImage member if the data block has been consummed entirely (keeps compatibility - // of new RS with older posts. - - if(j == RsGenericSerializer::DESERIALIZE && ctx.mOffset == ctx.mSize) - return ; - - if((j == RsGenericSerializer::SIZE_ESTIMATE || j == RsGenericSerializer::SERIALIZE) && mImage.empty()) - return ; - - RsTypeSerializer::serial_process(j,ctx,mImage,"mImage") ; -} - -void RsGxsPostedGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR ,mDescription,"mDescription") ; - - if(j == RsGenericSerializer::DESERIALIZE && ctx.mOffset == ctx.mSize) - return ; - - if((j == RsGenericSerializer::SIZE_ESTIMATE || j == RsGenericSerializer::SERIALIZE) && mGroupImage.empty()) - return ; - - RsTypeSerializer::serial_process(j,ctx,mGroupImage,"mGroupImage") ; -} - -RsItem *RsGxsPostedSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) const -{ - if(service_id != RS_SERVICE_GXS_TYPE_POSTED) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_POSTED_GRP_ITEM: return new RsGxsPostedGroupItem() ; - case RS_PKT_SUBTYPE_POSTED_POST_ITEM: return new RsGxsPostedPostItem() ; - default: - return RsGxsCommentSerialiser::create_item(service_id,item_subtype) ; - } -} - -bool RsGxsPostedPostItem::fromPostedPost(RsPostedPost &post, bool moveImage) -{ - clear(); - - mPost = post; - meta = post.mMeta; - - if (moveImage) - { - mImage.binData.bin_data = post.mImage.mData; - mImage.binData.bin_len = post.mImage.mSize; - post.mImage.shallowClear(); - } - else - { - mImage.binData.setBinData(post.mImage.mData, post.mImage.mSize); - } - - return true; -} - -bool RsGxsPostedPostItem::toPostedPost(RsPostedPost &post, bool moveImage) -{ - post = mPost; - post.mMeta = meta; - - if (moveImage) - { - post.mImage.take((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); - // mImage doesn't have a ShallowClear at the moment! - mImage.binData.TlvShallowClear(); - } - else - { - post.mImage.copy((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); - } - - return true; -} - -void RsGxsPostedPostItem::clear() -{ - mPost.mLink.clear(); - mPost.mNotes.clear(); - mImage.TlvClear(); -} -void RsGxsPostedGroupItem::clear() -{ - mDescription.clear(); - mGroupImage.TlvClear(); -} - -bool RsGxsPostedGroupItem::fromPostedGroup(RsPostedGroup &group, bool moveImage) -{ - clear(); - meta = group.mMeta; - mDescription = group.mDescription; - - if (moveImage) - { - mGroupImage.binData.bin_data = group.mGroupImage.mData; - mGroupImage.binData.bin_len = group.mGroupImage.mSize; - group.mGroupImage.shallowClear(); - } - else - { - mGroupImage.binData.setBinData(group.mGroupImage.mData, group.mGroupImage.mSize); - } - return true; -} - -bool RsGxsPostedGroupItem::toPostedGroup(RsPostedGroup &group, bool moveImage) -{ - group.mMeta = meta; - group.mDescription = mDescription; - if (moveImage) - { - group.mGroupImage.take((uint8_t *) mGroupImage.binData.bin_data, mGroupImage.binData.bin_len); - // mGroupImage doesn't have a ShallowClear at the moment! - mGroupImage.binData.TlvShallowClear(); - } - else - { - group.mGroupImage.copy((uint8_t *) mGroupImage.binData.bin_data, mGroupImage.binData.bin_len); - } - return true; -} diff --git a/libretroshare/src/rsitems/rsposteditems.h b/libretroshare/src/rsitems/rsposteditems.h deleted file mode 100644 index 910471c19..000000000 --- a/libretroshare/src/rsitems/rsposteditems.h +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsposteditems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSPOSTEDITEMS_H -#define RSPOSTEDITEMS_H - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsgxscommentitems.h" -#include "rsitems/rsgxsitems.h" -#include "serialiser/rstlvimage.h" - -#include "retroshare/rsposted.h" - -const uint8_t RS_PKT_SUBTYPE_POSTED_GRP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_POSTED_POST_ITEM = 0x03; - -class RsGxsPostedGroupItem : public RsGxsGrpItem -{ -public: - RsGxsPostedGroupItem() : RsGxsGrpItem(RS_SERVICE_GXS_TYPE_POSTED, RS_PKT_SUBTYPE_POSTED_GRP_ITEM) {} - virtual ~RsGxsPostedGroupItem() {} - - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // use conversion functions to transform: - bool fromPostedGroup(RsPostedGroup &group, bool moveImage); - bool toPostedGroup(RsPostedGroup &group, bool moveImage); - - std::string mDescription; - RsTlvImage mGroupImage; - -}; - -class RsGxsPostedPostItem : public RsGxsMsgItem -{ -public: - RsGxsPostedPostItem() : RsGxsMsgItem(RS_SERVICE_GXS_TYPE_POSTED, RS_PKT_SUBTYPE_POSTED_POST_ITEM) {} - virtual ~RsGxsPostedPostItem() {} - - void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // Slightly unusual structure. - // use conversion functions to transform: - bool fromPostedPost(RsPostedPost &post, bool moveImage); - bool toPostedPost(RsPostedPost &post, bool moveImage); - - RsPostedPost mPost; - RsTlvImage mImage; -}; - -class RsGxsPostedSerialiser : public RsGxsCommentSerialiser -{ -public: - - RsGxsPostedSerialiser() :RsGxsCommentSerialiser(RS_SERVICE_GXS_TYPE_POSTED) {} - - virtual ~RsGxsPostedSerialiser() {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ; -}; - - -#endif // RSPOSTEDITEMS_H diff --git a/libretroshare/src/rsitems/rsrttitems.cc b/libretroshare/src/rsitems/rsrttitems.cc deleted file mode 100644 index 739f1c06d..000000000 --- a/libretroshare/src/rsitems/rsrttitems.cc +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsrttitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2013 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "rsitems/rsrttitems.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -#include "serialiser/rstypeserializer.h" - -/*************************************************************************/ - -RsItem *RsRttSerialiser::create_item(uint16_t service,uint8_t type) const -{ - if(service != RS_SERVICE_TYPE_RTT) - return NULL ; - - switch(type) - { - case RS_PKT_SUBTYPE_RTT_PING: return new RsRttPingItem() ; //= 0x01; - case RS_PKT_SUBTYPE_RTT_PONG: return new RsRttPongItem() ; // = 0x02; - default: - return NULL ; - } -} - -void RsRttPingItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mSeqNo,"mSeqNo") ; - RsTypeSerializer::serial_process(j,ctx,mPingTS,"mPingTS") ; -} - -void RsRttPongItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mSeqNo,"mSeqNo") ; - RsTypeSerializer::serial_process(j,ctx,mPingTS,"mPingTS") ; - RsTypeSerializer::serial_process(j,ctx,mPongTS,"mPongTS") ; -} - - - diff --git a/libretroshare/src/rsitems/rsrttitems.h b/libretroshare/src/rsitems/rsrttitems.h deleted file mode 100644 index 54f612ee6..000000000 --- a/libretroshare/src/rsitems/rsrttitems.h +++ /dev/null @@ -1,99 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsrttitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2013 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_RTT_ITEMS_H -#define RS_RTT_ITEMS_H - -#include - -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" -#include "serialiser/rsserial.h" - -#include "serialiser/rsserializer.h" - -/**************************************************************************/ - -const uint8_t RS_PKT_SUBTYPE_RTT_PING = 0x01; -const uint8_t RS_PKT_SUBTYPE_RTT_PONG = 0x02; - -class RsRttItem: public RsItem -{ - public: - explicit RsRttItem(uint8_t subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_RTT,subtype) - { setPriorityLevel(QOS_PRIORITY_RS_RTT_PING) ;} // should be refined later. - - virtual ~RsRttItem() {} - virtual void clear() {} -}; - -class RsRttPingItem: public RsRttItem -{ - public: - RsRttPingItem() - : RsRttItem(RS_PKT_SUBTYPE_RTT_PING) - , mSeqNo(0), mPingTS(0) - {} - - virtual ~RsRttPingItem(){} - virtual void clear(){} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t mSeqNo; - uint64_t mPingTS; -}; - -class RsRttPongItem: public RsRttItem -{ - public: - RsRttPongItem() - : RsRttItem(RS_PKT_SUBTYPE_RTT_PONG) - , mSeqNo(0), mPingTS(0), mPongTS(0) - {} - - virtual ~RsRttPongItem(){} - virtual void clear(){} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t mSeqNo; - uint64_t mPingTS; - uint64_t mPongTS; -}; - - -class RsRttSerialiser: public RsServiceSerializer -{ - public: - RsRttSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_RTT) {} - - virtual ~RsRttSerialiser(){} - - virtual RsItem *create_item(uint16_t service,uint8_t type) const; -}; - -/**************************************************************************/ - -#endif /* RS_RTT_ITEMS_H */ - - diff --git a/libretroshare/src/rsitems/rsserviceids.h b/libretroshare/src/rsitems/rsserviceids.h deleted file mode 100644 index ead349e32..000000000 --- a/libretroshare/src/rsitems/rsserviceids.h +++ /dev/null @@ -1,152 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsserviceids.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2008 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "util/rsdeprecate.h" - -#include - -enum class RsServiceType : uint16_t -{ - NONE = 0, /// To detect non-initialized reads - GOSSIP_DISCOVERY = 0x0011, - CHAT = 0x0012, - MSG = 0x0013, - TURTLE = 0x0014, - TUNNEL = 0x0015, - HEARTBEAT = 0x0016, - FILE_TRANSFER = 0x0017, - GROUTER = 0x0018, - FILE_DATABASE = 0x0019, - SERVICEINFO = 0x0020, - BANDWIDTH_CONTROL = 0x0021, - MAIL = 0x0022, - DIRECT_MAIL = 0x0023, - DISTANT_MAIL = 0x0024, - GWEMAIL_MAIL = 0x0025, - SERVICE_CONTROL = 0x0026, - DISTANT_CHAT = 0x0027, - GXS_TUNNEL = 0x0028, - BANLIST = 0x0101, - STATUS = 0x0102, - NXS = 0x0200, - GXSID = 0x0211, - PHOTO = 0x0212, - WIKI = 0x0213, - WIRE = 0x0214, - FORUMS = 0x0215, - POSTED = 0x0216, - CHANNELS = 0x0217, - GXSCIRCLE = 0x0218, - /// not gxs, but used with identities. - REPUTATION = 0x0219, - GXS_RECOGN = 0x0220, - GXS_TRANS = 0x0230, - JSONAPI = 0x0240, - FORUMS_CONFIG = 0x0315, - POSTED_CONFIG = 0x0316, - CHANNELS_CONFIG = 0x0317, - RTT = 0x1011, /// Round Trip Time - - - /***************** IDS ALLOCATED FOR PLUGINS ******************/ - // 2000+ - PLUGIN_ARADO_ID = 0x2001, - PLUGIN_QCHESS_ID = 0x2002, - PLUGIN_FEEDREADER = 0x2003, - - /// Reserved for packet slicing probes. - PACKET_SLICING_PROBE = 0xAABB, - - // Nabu's experimental services. - PLUGIN_FIDO_GW = 0xF1D0, - PLUGIN_ZERORESERVE = 0xBEEF -}; - - - -// TODO: Port all services types to RsServiceType - -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_FILE_INDEX = 0x0001; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_DISC = 0x0011; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_CHAT = 0x0012; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_MSG = 0x0013; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_TURTLE = 0x0014; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_TUNNEL = 0x0015; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_HEARTBEAT = 0x0016; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_FILE_TRANSFER = 0x0017; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_GROUTER = 0x0018; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_FILE_DATABASE = 0x0019; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_SERVICEINFO = 0x0020; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_BWCTRL = 0x0021; /// Bandwidth Control -/// New Mail Service (replace old Msg Service) -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_MAIL = 0x0022; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_DIRECT_MAIL = 0x0023; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_DISTANT_MAIL = 0x0024; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_GWEMAIL_MAIL = 0x0025; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_SERVICE_CONTROL= 0x0026; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_DISTANT_CHAT = 0x0027; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_GXS_TUNNEL = 0x0028; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_BANLIST = 0x0101; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_STATUS = 0x0102; -/// Rs Network Exchange Service -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_NXS = 0x0200; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_GXSID = 0x0211; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_PHOTO = 0x0212; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_WIKI = 0x0213; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_WIRE = 0x0214; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_FORUMS = 0x0215; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_POSTED = 0x0216; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS = 0x0217; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_GXSCIRCLE = 0x0218; -/// not gxs, but used with identities. -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_REPUTATION = 0x0219; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_GXS_RECOGN = 0x0220; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_GXS_TRANS = 0x0230; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_JSONAPI = 0x0240; -/// used to save notification records in GXS and possible other service-based configuration -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_FORUMS_CONFIG = 0x0315; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_POSTED_CONFIG = 0x0316; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG = 0x0317; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_CIRCLES_CONFIG = 0x0318; - -// Experimental Services. -/* DSDV Testing at the moment - Service Only */ -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_DSDV = 0x1010; -/* Latency RTT Measurements */ -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_RTT = 0x1011; - - -/***************** IDS ALLOCATED FOR PLUGINS ******************/ -// 2000+ - -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_PLUGIN_ARADO_ID = 0x2001; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_PLUGIN_QCHESS_ID = 0x2002; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_PLUGIN_FEEDREADER = 0x2003; - -// Reserved for packet slicing probes. -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_PACKET_SLICING_PROBE = 0xAABB; - -// Nabu's services. -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_PLUGIN_FIDO_GW = 0xF1D0; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_PLUGIN_ZERORESERVE = 0xBEEF; diff --git a/libretroshare/src/rsitems/rsserviceinfoitems.cc b/libretroshare/src/rsitems/rsserviceinfoitems.cc deleted file mode 100644 index 8d007941d..000000000 --- a/libretroshare/src/rsitems/rsserviceinfoitems.cc +++ /dev/null @@ -1,169 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsserviceinfoitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstypeserializer.h" -#include "rsitems/rsserviceinfoitems.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -/*************************************************************************/ -/***** RsServiceInfo ****/ -/*************************************************************************/ - -void RsServiceInfoListItem::clear() -{ - mServiceInfo.clear(); -} - -void RsServiceInfoListItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTlvServiceInfoMapRef map(mServiceInfo); - - RsTypeSerializer::serial_process(j,ctx,map,"map") ; -} - -void RsServiceInfoPermissionsItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,allowedBw,"allowedBw") ; -} - -RsItem *RsServiceInfoSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const -{ - if(service != RS_SERVICE_TYPE_SERVICEINFO) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_SERVICELIST_ITEM: return new RsServiceInfoListItem() ; - case RS_PKT_SUBTYPE_SERVICEPERMISSIONS_ITEM: return new RsServiceInfoPermissionsItem() ; - default: - return NULL ; - } -} - - - - -template<> std::ostream& RsTlvParamRef::print(std::ostream &out, uint16_t /*indent*/) const -{ - out << "RsServiceInfo: " << mParam.mServiceType << " name " << mParam.mServiceName; - out << std::endl; - out << "Version(" << mParam.mVersionMajor << "," << mParam.mVersionMinor << ")"; - out << " MinVersion(" << mParam.mMinVersionMajor << "," << mParam.mMinVersionMinor << ")"; - out << std::endl; - return out; -} - -template<> -uint32_t RsTlvParamRef::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header + 4 for size */ - - s += getRawStringSize(mParam.mServiceName); - s += 4; // type. - s += 4; // version. - s += 4; // min version. - return s; -} - -template<> -void RsTlvParamRef::TlvClear() -{ - mParam = RsServiceInfo(); - mParam.mServiceName.clear(); -} - -template<> -bool RsTlvParamRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { - return false; /* not enough space */ - } - - bool ok = true; - - ok &= SetTlvBase(data, tlvend, offset, mParamType, tlvsize); - ok &= setRawString(data, tlvend, offset, mParam.mServiceName); - ok &= setRawUInt32(data, tlvend, offset, mParam.mServiceType); - ok &= setRawUInt16(data, tlvend, offset, mParam.mVersionMajor); - ok &= setRawUInt16(data, tlvend, offset, mParam.mVersionMinor); - ok &= setRawUInt16(data, tlvend, offset, mParam.mMinVersionMajor); - ok &= setRawUInt16(data, tlvend, offset, mParam.mMinVersionMinor); - - if (!ok) - { - std::cerr << "RsTlvParamRef::SetTlv() Failed"; - std::cerr << std::endl; - } - - return ok; -} - -template<> -bool RsTlvParamRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - { - return false; /* not enough space */ - } - - if (tlvtype != mParamType) /* check type */ - { - return false; - } - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - ok &= getRawString(data, tlvend, offset, mParam.mServiceName); - ok &= getRawUInt32(data, tlvend, offset, &(mParam.mServiceType)); - ok &= getRawUInt16(data, tlvend, offset, &(mParam.mVersionMajor)); - ok &= getRawUInt16(data, tlvend, offset, &(mParam.mVersionMinor)); - ok &= getRawUInt16(data, tlvend, offset, &(mParam.mMinVersionMajor)); - ok &= getRawUInt16(data, tlvend, offset, &(mParam.mMinVersionMinor)); - - return ok; -} - -template class RsTlvParamRef; - diff --git a/libretroshare/src/rsitems/rsserviceinfoitems.h b/libretroshare/src/rsitems/rsserviceinfoitems.h deleted file mode 100644 index e3d04b3c8..000000000 --- a/libretroshare/src/rsitems/rsserviceinfoitems.h +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsserviceinfoitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_SERVICE_INFO_ITEMS_H -#define RS_SERVICE_INFO_ITEMS_H - -// Provides serialiser for p3ServiceControl & p3ServiceInfo. - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rstlvgenericmap.h" -#include "retroshare/rsservicecontrol.h" - -#define RS_PKT_SUBTYPE_SERVICELIST_ITEM 0x01 -#define RS_PKT_SUBTYPE_SERVICEPERMISSIONS_ITEM 0x02 - -/**************************************************************************/ -#define SERVICE_INFO_MAP 0x01 -#define SERVICE_INFO_KEY 0x01 -#define SERVICE_ID 0x01 -#define SERVICE_INFO 0x01 - -class RsTlvServiceInfoMapRef: public RsTlvGenericMapRef -{ -public: - RsTlvServiceInfoMapRef(std::map &refmap) - :RsTlvGenericMapRef( - SERVICE_INFO_MAP, - SERVICE_INFO_KEY, - SERVICE_ID, - SERVICE_INFO, - refmap) - { - return; - } -}; - -class RsServiceInfoListItem: public RsItem -{ - public: - RsServiceInfoListItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_SERVICEINFO, RS_PKT_SUBTYPE_SERVICELIST_ITEM) - { - setPriorityLevel(QOS_PRIORITY_RS_SERVICE_INFO_ITEM); - return; - } - - virtual ~RsServiceInfoListItem(){} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - std::map mServiceInfo; -}; - -class RsServiceInfoPermissionsItem: public RsItem -{ - public: - RsServiceInfoPermissionsItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_SERVICEINFO, RS_PKT_SUBTYPE_SERVICEPERMISSIONS_ITEM) - { - setPriorityLevel(QOS_PRIORITY_RS_SERVICE_INFO_ITEM); - return; - } - - virtual ~RsServiceInfoPermissionsItem(){} - virtual void clear(){} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t allowedBw; // Units are bytes/sec => 4Gb/s; -}; - -class RsServiceInfoSerialiser: public RsServiceSerializer -{ - public: - RsServiceInfoSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_SERVICEINFO) {} - virtual ~RsServiceInfoSerialiser() {} - - virtual RsItem *create_item(uint16_t /* service */, uint8_t /* item_sub_id */) const; -}; - -/**************************************************************************/ - -#endif /* RS_SERVICE_INFO_ITEMS_H */ diff --git a/libretroshare/src/rsitems/rsstatusitems.h b/libretroshare/src/rsitems/rsstatusitems.h deleted file mode 100644 index e92db7816..000000000 --- a/libretroshare/src/rsitems/rsstatusitems.h +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsstatusitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Vinny Do. * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_STATUS_ITEMS_H -#define RS_STATUS_ITEMS_H - -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" -#include "rsitems/rsitem.h" - -#include "serialiser/rstypeserializer.h" - -/**************************************************************************/ - -class RsStatusItem: public RsItem -{ -public: - RsStatusItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_STATUS, RS_PKT_SUBTYPE_DEFAULT) - { - setPriorityLevel(QOS_PRIORITY_RS_STATUS_ITEM); - } - virtual ~RsStatusItem() {} - virtual void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,sendTime,"sendTime") ; - RsTypeSerializer::serial_process(j,ctx,status ,"status") ; - } - - uint32_t sendTime; - uint32_t status; - - /* not serialised */ - uint32_t recvTime; -}; - -class RsStatusSerialiser: public RsServiceSerializer -{ -public: - RsStatusSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_STATUS) {} - virtual ~RsStatusSerialiser() {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const - { - if(service == RS_SERVICE_TYPE_STATUS && item_subtype == RS_PKT_SUBTYPE_DEFAULT) - return new RsStatusItem(); - else - return NULL ; - } -}; - -/**************************************************************************/ - -#endif /* RS_STATUS_ITEMS_H */ - - diff --git a/libretroshare/src/rsitems/rswikiitems.cc b/libretroshare/src/rsitems/rswikiitems.cc deleted file mode 100644 index e7ffa8508..000000000 --- a/libretroshare/src/rsitems/rswikiitems.cc +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rswikiitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include - -#include "rsitems/rswikiitems.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstypeserializer.h" - -#define GXSID_DEBUG 1 - -RsItem *RsGxsWikiSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const -{ - if(service != RS_SERVICE_GXS_TYPE_WIKI) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_WIKI_COLLECTION_ITEM: return new RsGxsWikiCollectionItem(); - case RS_PKT_SUBTYPE_WIKI_COMMENT_ITEM: return new RsGxsWikiCommentItem(); - case RS_PKT_SUBTYPE_WIKI_SNAPSHOT_ITEM: return new RsGxsWikiSnapshotItem(); - default: - return NULL ; - } -} - -void RsGxsWikiCollectionItem::clear() -{ - collection.mDescription.clear(); - collection.mCategory.clear(); - collection.mHashTags.clear(); -} - -void RsGxsWikiCollectionItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR ,collection.mDescription,"collection.mDescription") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_CATEGORY,collection.mCategory ,"collection.mCategory") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_HASH_TAG,collection.mHashTags ,"collection.mHashTags") ; -} - -void RsGxsWikiSnapshotItem::clear() -{ - snapshot.mPage.clear(); - snapshot.mHashTags.clear(); -} - -void RsGxsWikiSnapshotItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_WIKI_PAGE,snapshot.mPage,"snapshot.mPage") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_HASH_TAG ,snapshot.mPage,"snapshot.mHashTags") ; -} - -void RsGxsWikiCommentItem::clear() -{ - comment.mComment.clear(); -} - -void RsGxsWikiCommentItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_COMMENT,comment.mComment,"comment.mComment") ; -} - diff --git a/libretroshare/src/rsitems/rswikiitems.h b/libretroshare/src/rsitems/rswikiitems.h deleted file mode 100644 index fa5cf1533..000000000 --- a/libretroshare/src/rsitems/rswikiitems.h +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rswikiitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef RS_WIKI_ITEMS_H -#define RS_WIKI_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "rsitems/rsgxsitems.h" - -#include "retroshare/rswiki.h" - -const uint8_t RS_PKT_SUBTYPE_WIKI_COLLECTION_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_WIKI_SNAPSHOT_ITEM = 0x03; -const uint8_t RS_PKT_SUBTYPE_WIKI_COMMENT_ITEM = 0x04; - -class RsGxsWikiCollectionItem : public RsGxsGrpItem -{ -public: - RsGxsWikiCollectionItem(): RsGxsGrpItem(RS_SERVICE_GXS_TYPE_WIKI, RS_PKT_SUBTYPE_WIKI_COLLECTION_ITEM) {} - virtual ~RsGxsWikiCollectionItem() {} - - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsWikiCollection collection; -}; - -class RsGxsWikiSnapshotItem : public RsGxsMsgItem -{ -public: - - RsGxsWikiSnapshotItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_WIKI, RS_PKT_SUBTYPE_WIKI_SNAPSHOT_ITEM) {} - virtual ~RsGxsWikiSnapshotItem() {} - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsWikiSnapshot snapshot; -}; - -class RsGxsWikiCommentItem : public RsGxsMsgItem -{ -public: - - RsGxsWikiCommentItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_WIKI, RS_PKT_SUBTYPE_WIKI_COMMENT_ITEM) {} - virtual ~RsGxsWikiCommentItem() {} - void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsWikiComment comment; - -}; - -class RsGxsWikiSerialiser : public RsServiceSerializer -{ -public: - - RsGxsWikiSerialiser() :RsServiceSerializer(RS_SERVICE_GXS_TYPE_WIKI) {} - virtual ~RsGxsWikiSerialiser() {} - - virtual RsItem *create_item(uint16_t /* service */, uint8_t /* item_sub_id */) const; -}; - -#endif /* RS_WIKI_ITEMS_H */ diff --git a/libretroshare/src/rsitems/rswireitems.cc b/libretroshare/src/rsitems/rswireitems.cc deleted file mode 100644 index a618336f7..000000000 --- a/libretroshare/src/rsitems/rswireitems.cc +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rswireitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include - -#include "rswireitems.h" -#include "serialiser/rstypeserializer.h" - -#define WIRE_DEBUG 1 - - -RsItem *RsGxsWireSerialiser::create_item(uint16_t service,uint8_t item_subtype) const -{ - if(service != RS_SERVICE_GXS_TYPE_WIRE) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_WIRE_GROUP_ITEM: return new RsGxsWireGroupItem(); - case RS_PKT_SUBTYPE_WIRE_PULSE_ITEM: return new RsGxsWirePulseItem(); - default: - return NULL ; - } -} - -void RsGxsWireGroupItem::clear() -{ - group.mTagline.clear(); - group.mLocation.clear(); - group.mHeadshot.clear(); - group.mMasthead.clear(); -} - -void RsGxsWireGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR,group.mTagline,"group.mTagline") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_LOCATION,group.mLocation,"group.mLocation") ; - group.mHeadshot.serial_process(j, ctx); - group.mMasthead.serial_process(j, ctx); -} - -void RsGxsWirePulseItem::clear() -{ - pulse.mPulseText.clear(); - pulse.mPulseType = 0; - pulse.mSentiment = 0; - pulse.mRefGroupId.clear(); - pulse.mRefGroupName.clear(); - pulse.mRefOrigMsgId.clear(); - pulse.mRefAuthorId.clear(); - pulse.mRefPublishTs = 0; - pulse.mRefPulseText.clear(); - pulse.mRefImageCount = 0; - - pulse.mImage1.clear(); - pulse.mImage2.clear(); - pulse.mImage3.clear(); - pulse.mImage4.clear(); -} - -void RsGxsWirePulseItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,pulse.mPulseText,"pulse.mPulseText") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_UINT32_PARAM,pulse.mPulseType,"pulse.mPulseType") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_UINT32_PARAM,pulse.mSentiment,"pulse.mSentiment") ; - RsTypeSerializer::serial_process(j,ctx,pulse.mRefGroupId,"pulse.mRefGroupId") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_NAME,pulse.mRefGroupName,"pulse.mRefGroupName") ; - RsTypeSerializer::serial_process(j,ctx,pulse.mRefOrigMsgId,"pulse.mRefOrigMsgId") ; - RsTypeSerializer::serial_process(j,ctx,pulse.mRefAuthorId,"pulse.mRefAuthorId") ; - RsTypeSerializer::serial_process(j,ctx,pulse.mRefPublishTs,"pulse.mRefPublishTs") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,pulse.mRefPulseText,"pulse.mRefPulseText") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_UINT32_PARAM,pulse.mRefImageCount,"pulse.mRefImageCount") ; - - pulse.mImage1.serial_process(j, ctx); - pulse.mImage2.serial_process(j, ctx); - pulse.mImage3.serial_process(j, ctx); - pulse.mImage4.serial_process(j, ctx); -} - diff --git a/libretroshare/src/rsitems/rswireitems.h b/libretroshare/src/rsitems/rswireitems.h deleted file mode 100644 index 4db5f3d25..000000000 --- a/libretroshare/src/rsitems/rswireitems.h +++ /dev/null @@ -1,76 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rswireitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef RS_WIRE_ITEMS_H -#define RS_WIRE_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserial.h" -//#include "serialiser/rstlvtypes.h" - -#include "rsgxsitems.h" -#include "retroshare/rswire.h" - -const uint8_t RS_PKT_SUBTYPE_WIRE_GROUP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_WIRE_PULSE_ITEM = 0x03; - -class RsGxsWireGroupItem : public RsGxsGrpItem -{ - -public: - - RsGxsWireGroupItem(): RsGxsGrpItem(RS_SERVICE_GXS_TYPE_WIRE, RS_PKT_SUBTYPE_WIRE_GROUP_ITEM) {} - virtual ~RsGxsWireGroupItem() {} - - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsWireGroup group; -}; - -class RsGxsWirePulseItem : public RsGxsMsgItem -{ -public: - - RsGxsWirePulseItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_WIRE, RS_PKT_SUBTYPE_WIRE_PULSE_ITEM) {} - virtual ~RsGxsWirePulseItem() {} - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsWirePulse pulse; -}; - -class RsGxsWireSerialiser : public RsServiceSerializer -{ -public: - - RsGxsWireSerialiser() :RsServiceSerializer(RS_SERVICE_GXS_TYPE_WIRE) {} - virtual ~RsGxsWireSerialiser() {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const ; -}; - -#endif /* RS_WIKI_ITEMS_H */ diff --git a/libretroshare/src/rsserver/p3face-config.cc b/libretroshare/src/rsserver/p3face-config.cc deleted file mode 100644 index 3251f33eb..000000000 --- a/libretroshare/src/rsserver/p3face-config.cc +++ /dev/null @@ -1,124 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3face-config.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie. * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "rsserver/p3face.h" - -#include -#include "pqi/authssl.h" -#include "pqi/authgpg.h" -#include "retroshare/rsinit.h" -#include "plugins/pluginmanager.h" -#include "util/rsdebug.h" - -#ifdef RS_JSONAPI -# include "jsonapi/jsonapi.h" -#endif // ifdef RS_JSONAPI - -#include -#include "util/rstime.h" - -#include "pqi/p3peermgr.h" -#include "pqi/p3netmgr.h" - - -// TO SHUTDOWN THREADS. -#ifdef RS_ENABLE_GXS - -#include "services/autoproxy/rsautoproxymonitor.h" - -#include "services/p3idservice.h" -#include "services/p3gxscircles.h" -#include "services/p3wiki.h" -#include "services/p3posted.h" -#include "services/p3photoservice.h" -#include "services/p3gxsforums.h" -#include "services/p3gxschannels.h" -#include "services/p3wire.h" - -#endif - -/****************************************/ -/* RsIface Config */ -/* Config */ - -void RsServer::ConfigFinalSave() -{ - //TODO: force saving of transfers - //ftserver->saveFileTransferStatus(); - -#ifdef RS_AUTOLOGIN - if(!RsInit::getAutoLogin()) RsInit::RsClearAutoLogin(); -#endif // RS_AUTOLOGIN - - //AuthSSL::getAuthSSL()->FinalSaveCertificates(); - mConfigMgr->completeConfiguration(); -} - -void RsServer::startServiceThread(RsTickingThread *t, const std::string &threadName) -{ - t->start(threadName) ; - mRegisteredServiceThreads.push_back(t) ; -} - -void RsServer::rsGlobalShutDown() -{ - coreReady = false; - // TODO: cache should also clean up old files - - ConfigFinalSave(); // save configuration before exit - - mPluginsManager->stopPlugins(pqih); - - mNetMgr->shutdown(); /* Handles UPnP */ - -#ifdef RS_JSONAPI - rsJsonApi->fullstop(); -#endif - - rsAutoProxyMonitor::instance()->stopAllRSShutdown(); - - fullstop() ; - - // kill all registered service threads - - for(std::list::iterator it= mRegisteredServiceThreads.begin();it!=mRegisteredServiceThreads.end();++it) - { - (*it)->fullstop() ; - } -// #ifdef RS_ENABLE_GXS -// // We should automate this. -// // -// if(mGxsCircles) mGxsCircles->join(); -// if(mGxsForums) mGxsForums->join(); -// if(mGxsChannels) mGxsChannels->join(); -// if(mGxsIdService) mGxsIdService->join(); -// if(mPosted) mPosted->join(); -// if(mWiki) mWiki->join(); -// if(mGxsNetService) mGxsNetService->join(); -// if(mPhoto) mPhoto->join(); -// if(mWire) mWire->join(); -// #endif - - AuthGPG::exit(); - - mShutdownCallback(0); -} diff --git a/libretroshare/src/rsserver/p3face-info.cc b/libretroshare/src/rsserver/p3face-info.cc deleted file mode 100644 index 18fdc40aa..000000000 --- a/libretroshare/src/rsserver/p3face-info.cc +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3face-info.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2015 by RetroShare Team * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "rsserver/p3face.h" -#include -#include -#include - -#ifdef NO_SQLCIPHER -# include -#else -# include -#endif - -#ifdef RS_USE_LIBUPNP -# include -#elif defined(RS_USE_LIBMINIUPNPC) -# include -#endif // def RS_USE_LIBUPNP - -std::string RsServer::getSQLCipherVersion() -{ - sqlite3* mDb; - std::string versionstring(""); - const char* version; - int rc = sqlite3_open_v2("", &mDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE , NULL); //create DB in a temp file - - if(rc){ - std::cerr << "Can't open database, Error code: " << sqlite3_errmsg(mDb) - << std::endl; - sqlite3_close(mDb); - mDb = NULL; - return ""; - } - - std::string sqlQuery = "PRAGMA cipher_version;"; - sqlite3_stmt* stmt = NULL; - rc = sqlite3_prepare_v2(mDb, sqlQuery.c_str(), sqlQuery.length(), &stmt, NULL); - if (rc == SQLITE_OK) { - rc = sqlite3_step(stmt); - switch (rc) { - case SQLITE_ROW: - version = (const char *)sqlite3_column_text(stmt, 0); //not needed to free - versionstring.append(version); - break; - case SQLITE_DONE: - break; - default: - std::cerr << "RetroDb::tableExists(): Error executing statement (code: " << rc << ")" - << std::endl; - break; - } - } - - if (stmt) { - sqlite3_finalize(stmt); - } - sqlite3_close(mDb); // no-op if mDb is NULL (https://www.sqlite.org/c3ref/close.html) - return versionstring; -} - -void RsServer::getLibraries(std::list &libraries) -{ - libraries.push_back(RsLibraryInfo("bzip2", BZ2_bzlibVersion())); - libraries.push_back(RsLibraryInfo("OpenSSL", SSLeay_version(SSLEAY_VERSION))); - libraries.push_back(RsLibraryInfo("SQLite", SQLITE_VERSION)); -#ifndef NO_SQLCIPHER - libraries.push_back(RsLibraryInfo("SQLCipher", getSQLCipherVersion())); -#endif - -#ifdef RS_USE_LIBUPNP - libraries.push_back(RsLibraryInfo("UPnP (libupnp)", UPNP_VERSION_STRING)); -#elif defined(RS_USE_LIBMINIUPNPC) - libraries.push_back(RsLibraryInfo("UPnP (MiniUPnP)", MINIUPNPC_VERSION)); -#endif // def RS_USE_LIBUPNP - - libraries.push_back(RsLibraryInfo("Zlib", ZLIB_VERSION)); -} diff --git a/libretroshare/src/rsserver/p3face-server.cc b/libretroshare/src/rsserver/p3face-server.cc deleted file mode 100644 index 8642860b8..000000000 --- a/libretroshare/src/rsserver/p3face-server.cc +++ /dev/null @@ -1,275 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3face-server.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2015 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "util/rstime.h" -#include "rsserver/p3face.h" -#include "retroshare/rsplugin.h" - -#include "tcponudp/tou.h" -#include - -#include "pqi/authssl.h" -#include -#include "util/rstime.h" - -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" - -#include "util/rsdebug.h" - -#include "retroshare/rsevents.h" -#include "services/rseventsservice.h" - -/******************* -#define TICK_DEBUG 1 -*******************/ - -#define WARN_BIG_CYCLE_TIME (0.2) - -#ifdef WINDOWS_SYS -#include "util/rstime.h" -#include -#endif - - -/*extern*/ RsControl* rsControl = nullptr; - -static double getCurrentTS() -{ - -#ifndef WINDOWS_SYS - struct timeval cts_tmp; - gettimeofday(&cts_tmp, NULL); - double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; -#else - struct _timeb timebuf; - _ftime( &timebuf); - double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; -#endif - return cts; -} - -// These values should be tunable from the GUI, to offer a compromise between speed and CPU use. -// In some cases (VOIP) it's likely that we will need to set them temporarily to a very low -// value, in order to favor a fast feedback - -const double RsServer::minTickInterval = 0.05; -const double RsServer::maxTickInterval = 0.2; - - -RsServer::RsServer() : - coreMutex("RsServer"), mShutdownCallback([](int){}), - coreReady(false) -{ - { - RsEventsService* tmpRsEvtPtr = new RsEventsService(); - rsEvents = tmpRsEvtPtr; - startServiceThread(tmpRsEvtPtr, "RsEventsService"); - } - - // This is needed asap. - // - mNotify = new p3Notify() ; - rsNotify = mNotify ; - - mPeerMgr = NULL; - mLinkMgr = NULL; - mNetMgr = NULL; - mHistoryMgr = NULL; - - pqih = NULL; - - mPluginsManager = NULL; - - /* services */ - mHeart = NULL; - mDisc = NULL; - msgSrv = NULL; - chatSrv = NULL; - mStatusSrv = NULL; - mGxsTunnels = NULL; - - /* timers */ - mLastts = getCurrentTS(); - mTickInterval = maxTickInterval ; - mAvgRunDuration = 0; - mLastRunDuration = 0; - mCycle1 = mLastts; - mCycle2 = mLastts; - mCycle3 = mLastts; - mCycle4 = mLastts; - - /* caches (that need ticking) */ - - /* config */ - mConfigMgr = NULL; - mGeneralConfig = NULL; -} - -RsServer::~RsServer() -{ - delete mGxsTrans; -} - -// General Internal Helper Functions ----> MUST BE LOCKED! - -void RsServer::threadTick() -{ -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking interval " << std::dec << (int) (1000 * mTickInterval) << " ms"; -#endif - -// we try to tick at a regular interval depending on the load -// if there is time left, we sleep - double timeToSleep = mTickInterval - mAvgRunDuration; - -// never sleep less than 50 ms - if (timeToSleep < 0.050) - timeToSleep = 0.050; - -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG will sleep " << std::dec << (int) (1000 * timeToSleep) << " ms"; -#endif - rstime::rs_usleep(timeToSleep * 1000000); - - double ts = getCurrentTS(); - mLastts = ts; - -// stuff we do always - // tick the core -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking RS core"; -#endif - lockRsCore(); - int moreToTick = pqih->tick(); - unlockRsCore(); - // tick the managers -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking mPeerMgr"; -#endif - mPeerMgr->tick(); -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking mLinkMgr"; -#endif - mLinkMgr->tick(); -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking mNetMgr"; -#endif - mNetMgr->tick(); - - -// stuff we do every second - if (ts - mCycle1 > 1) - { -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG every second"; -#endif - // slow services - if (rsPlugins) - { -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking slow tick plugins"; -#endif - rsPlugins->slowTickPlugins((rstime_t)ts); - } - // UDP keepalive - // tou_tick_stunkeepalive(); - // other stuff to tick - // update(); - mCycle1 = ts; - } - -// stuff we do every five seconds - if (ts - mCycle2 > 5) - { -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG every 5 seconds"; -#endif - mCycle2 = ts; - } - -// stuff we do every minute - if (ts - mCycle3 > 60) - { -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG every 60 seconds"; -#endif - // force saving FileTransferStatus TODO - // ftserver->saveFileTransferStatus(); - // see if we need to resave certs - // AuthSSL::getAuthSSL()->CheckSaveCertificates(); - mCycle3 = ts; - } - -// stuff we do every hour - if (ts - mCycle4 > 3600) - { -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG every hour"; -#endif - // save configuration files -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking mConfigMgr"; -#endif - mConfigMgr->tick(); - mCycle4 = ts; - } - -// ticking is done, now compute new values of mLastRunDuration, mAvgRunDuration and mTickInterval - ts = getCurrentTS(); - mLastRunDuration = ts - mLastts; - -// low-pass filter and don't let mAvgRunDuration exceeds maxTickInterval - mAvgRunDuration = 0.1 * mLastRunDuration + 0.9 * mAvgRunDuration; - if (mAvgRunDuration > maxTickInterval) - mAvgRunDuration = maxTickInterval; - -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG mLastRunDuration " << std::dec << (int) (1000 * mLastRunDuration) << " ms, mAvgRunDuration " << (int) (1000 * mAvgRunDuration) << " ms"; - if (mLastRunDuration > WARN_BIG_CYCLE_TIME) - RsDbg() << "TICK_DEBUG excessively long cycle time " << std::dec << (int) (1000 * mLastRunDuration) << " ms"; -#endif - -// if the core has returned that there is more to tick we decrease the ticking interval, else we increase it -// TODO: this should be investigated as it seems that the core never returns 1 -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG moreToTick " << moreToTick; -#endif - if (moreToTick == 1) - mTickInterval = 0.9 * mTickInterval; - else - mTickInterval = 1.1 * mTickInterval; -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG new tick interval " << std::dec << (int) (1000 * mTickInterval) << " ms"; -#endif - -// keep the tick interval target within allowed limits - if (mTickInterval < minTickInterval) - mTickInterval = minTickInterval; - else if (mTickInterval > maxTickInterval) - mTickInterval = maxTickInterval; -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG new tick interval after limiter " << std::dec << (int) (1000 * mTickInterval) << " ms"; -#endif -} - diff --git a/libretroshare/src/rsserver/p3face.h b/libretroshare/src/rsserver/p3face.h deleted file mode 100644 index 661cb244f..000000000 --- a/libretroshare/src/rsserver/p3face.h +++ /dev/null @@ -1,215 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3face.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include - -//#include "server/filedexserver.h" -#include "ft/ftserver.h" -//#include "pqi/pqissl.h" - -#include "pqi/p3cfgmgr.h" -#include "pqi/p3notify.h" -#include "pqi/pqipersongrp.h" - -#include "retroshare/rsiface.h" -#include "retroshare/rstypes.h" -#include "util/rsthreads.h" - -#include "chat/p3chatservice.h" -#include "gxstunnel/p3gxstunnel.h" - -#include "services/p3msgservice.h" -#include "services/p3statusservice.h" - -class p3heartbeat; -class p3discovery2; -class p3I2pBob; - -/* GXS Classes - just declare the classes. - so we don't have to totally recompile to switch */ - -class p3IdService; -class p3GxsCircles; -class p3GxsForums; -class p3GxsChannels; -class p3Wiki; -class p3Posted; -class p3PhotoService; -class p3Wire; - - -class p3PeerMgrIMPL; -class p3LinkMgrIMPL; -class p3NetMgrIMPL; -class p3HistoryMgr; -class RsPluginManager; - -/* The Main Interface Class - for controlling the server */ - -/* The init functions are actually Defined in p3face-startup.cc - */ -//RsInit *InitRsConfig(); -//void CleanupRsConfig(RsInit *); -//int InitRetroShare(int argc, char **argv, RsInit *config); -//int LoadCertificates(RsInit *config); - -class RsServer: public RsControl, public RsTickingThread -{ -public: - RsServer(); - virtual ~RsServer(); - - virtual int StartupRetroShare(); - - /// @see RsControl::isReady() - virtual bool isReady() { return coreReady; } - - /// @see RsControl::setShutdownCallback - void setShutdownCallback(const std::function& callback) - { mShutdownCallback = callback; } - - void threadTick() override; /// @see RsTickingThread - - /* locking stuff */ - void lockRsCore() - { - // std::cerr << "RsServer::lockRsCore()" << std::endl; - coreMutex.lock(); - } - - void unlockRsCore() - { - // std::cerr << "RsServer::unlockRsCore()" << std::endl; - coreMutex.unlock(); - } - - static p3Notify *notify() { return dynamic_cast(instance())->mNotify ; } - - private: - - /* mutex */ - RsMutex coreMutex; - - private: - - /****************************************/ - /****************************************/ - /****************************************/ - /****************************************/ - public: - /* Config */ - - virtual void ConfigFinalSave( ); - virtual void startServiceThread(RsTickingThread *t, const std::string &threadName) ; - - /************* Rs shut down function: in upnp 'port lease time' bug *****************/ - - /** - * This function is responsible for ensuring Retroshare exits in a legal state: - * i.e. releases all held resources and saves current configuration - */ - virtual void rsGlobalShutDown(); - - /****************************************/ - - public: - virtual bool getPeerCryptoDetails(const RsPeerId& ssl_id,RsPeerCryptoParams& params) { return pqih->getCryptoParams(ssl_id,params); } - virtual void getLibraries(std::list &libraries); - - private: - - std::string getSQLCipherVersion(); // TODO: move to rsversion.h - - // The real Server Parts. - - //filedexserver *server; - //ftServer *ftserver; - - p3PeerMgrIMPL *mPeerMgr; - p3LinkMgrIMPL *mLinkMgr; - p3NetMgrIMPL *mNetMgr; - p3HistoryMgr *mHistoryMgr; - - pqipersongrp *pqih; - - RsPluginManager *mPluginsManager; - - /* services */ - p3heartbeat *mHeart; - p3discovery2 *mDisc; - p3MsgService *msgSrv; - p3ChatService *chatSrv; - p3StatusService *mStatusSrv; - p3GxsTunnelService *mGxsTunnels; -#ifdef RS_USE_I2P_BOB - p3I2pBob *mI2pBob; -#endif - - // This list contains all threaded services. It will be used to shut them down properly. - - std::list mRegisteredServiceThreads ; - - /* GXS */ -// p3Wiki *mWiki; -// p3Posted *mPosted; -// p3PhotoService *mPhoto; -// p3GxsCircles *mGxsCircles; -// p3GxsNetService *mGxsNetService; -// p3IdService *mGxsIdService; -// p3GxsForums *mGxsForums; -// p3GxsChannels *mGxsChannels; -// p3Wire *mWire; - p3GxsTrans* mGxsTrans; - - /* Config */ - p3ConfigMgr *mConfigMgr; - p3GeneralConfig *mGeneralConfig; - - // notify - p3Notify *mNotify ; - - // Worker Data..... - - double mLastts; - double mTickInterval; - double mLastRunDuration; - double mAvgRunDuration; - double mCycle1, mCycle2, mCycle3, mCycle4; - - static const double minTickInterval; - static const double maxTickInterval; - - /// @see RsControl::setShutdownCallback - std::function mShutdownCallback; - - /** Keep track of the core being fully ready, true only after - * StartupRetroShare() finish and before rsGlobalShutDown() begin - */ - bool coreReady; -}; - -/* Helper function to convert windows paths - * into unix (ie switch \ to /) for FLTK's file chooser - */ - -std::string make_path_unix(std::string winpath); diff --git a/libretroshare/src/rsserver/p3history.cc b/libretroshare/src/rsserver/p3history.cc deleted file mode 100644 index 2818d9339..000000000 --- a/libretroshare/src/rsserver/p3history.cc +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3history.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Thunder. * - * * - * 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 . * - * * - *******************************************************************************/ -#include "p3history.h" -#include "pqi/p3historymgr.h" - -p3History::p3History(p3HistoryMgr* historyMgr) - : mHistoryMgr(historyMgr) -{ -} - -p3History::~p3History() -{ -} - -bool p3History::chatIdToVirtualPeerId(const ChatId &chat_id, RsPeerId &peer_id) -{ - return mHistoryMgr->chatIdToVirtualPeerId(chat_id, peer_id); -} - -void p3History::setMaxStorageDuration(uint32_t seconds) -{ - mHistoryMgr->setMaxStorageDuration(seconds) ; -} -uint32_t p3History::getMaxStorageDuration() -{ - return mHistoryMgr->getMaxStorageDuration() ; -} -bool p3History::getMessages(const ChatId &chatPeerId, std::list &msgs, const uint32_t loadCount) -{ - return mHistoryMgr->getMessages(chatPeerId, msgs, loadCount); -} - -bool p3History::getMessage(uint32_t msgId, HistoryMsg &msg) -{ - return mHistoryMgr->getMessage(msgId, msg); -} - -void p3History::removeMessages(const std::list &msgIds) -{ - mHistoryMgr->removeMessages(msgIds); -} - -void p3History::clear(const ChatId &chatPeerId) -{ - mHistoryMgr->clear(chatPeerId); -} - -bool p3History::getEnable(uint32_t chat_type) -{ - return mHistoryMgr->getEnable(chat_type); -} - -void p3History::setEnable(uint32_t chat_type, bool enable) -{ - mHistoryMgr->setEnable(chat_type, enable); -} - -uint32_t p3History::getSaveCount(uint32_t chat_type) -{ - return mHistoryMgr->getSaveCount(chat_type); -} - -void p3History::setSaveCount(uint32_t chat_type, uint32_t count) -{ - mHistoryMgr->setSaveCount(chat_type, count); -} diff --git a/libretroshare/src/rsserver/p3history.h b/libretroshare/src/rsserver/p3history.h deleted file mode 100644 index 2a75d328d..000000000 --- a/libretroshare/src/rsserver/p3history.h +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3history.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Thunder. * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_P3HISTORY_INTERFACE_H -#define RS_P3HISTORY_INTERFACE_H - -#include "retroshare/rshistory.h" - -class p3HistoryMgr; - -//! Implements abstract interface rsHistory -/*! - * Interfaces with p3HistoryMsg - */ -class p3History : public RsHistory -{ -public: - - p3History(p3HistoryMgr* historyMgr); - virtual ~p3History(); - - virtual bool chatIdToVirtualPeerId(const ChatId &chat_id, RsPeerId &peer_id); - virtual bool getMessages(const ChatId &chatPeerId, std::list &msgs, uint32_t loadCount); - virtual bool getMessage(uint32_t msgId, HistoryMsg &msg); - virtual void removeMessages(const std::list &msgIds); - virtual void clear(const ChatId &chatPeerId); - - virtual bool getEnable(uint32_t chat_type); - virtual void setEnable(uint32_t chat_type, bool enable); - - virtual uint32_t getMaxStorageDuration(); - virtual void setMaxStorageDuration(uint32_t seconds); - - // 0 = no limit, >0 count of saved messages - virtual uint32_t getSaveCount(uint32_t chat_type); - virtual void setSaveCount(uint32_t chat_type, uint32_t count); - -private: - p3HistoryMgr* mHistoryMgr; -}; - -#endif /* RS_P3HISTORY_INTERFACE_H */ diff --git a/libretroshare/src/rsserver/p3msgs.cc b/libretroshare/src/rsserver/p3msgs.cc deleted file mode 100644 index b877c0282..000000000 --- a/libretroshare/src/rsserver/p3msgs.cc +++ /dev/null @@ -1,587 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3msgs.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#include -#include - -#include "util/rsdir.h" -#include "util/rsdebug.h" -//const int p3facemsgzone = 11453; - -#include -#include "util/rstime.h" - -#include "retroshare/rstypes.h" -#include "rsserver/p3msgs.h" - -#include "services/p3msgservice.h" -#include "chat/p3chatservice.h" - -#include "pqi/authgpg.h" - -using namespace Rs::Msgs; - -/*extern*/ RsMsgs* rsMsgs = nullptr; - -/****************************************/ -/****************************************/ - -ChatId::ChatId(): - type(TYPE_NOT_SET), - lobby_id(0) -{ - -} - -ChatId::ChatId(RsPeerId id): - lobby_id(0) -{ - type = TYPE_PRIVATE; - peer_id = id; -} - -ChatId::ChatId(DistantChatPeerId id): - lobby_id(0) -{ - type = TYPE_PRIVATE_DISTANT; - distant_chat_id = id; -} - -ChatId::ChatId(ChatLobbyId id): - lobby_id(0) -{ - type = TYPE_LOBBY; - lobby_id = id; -} - -ChatId::ChatId(std::string str) : lobby_id(0) -{ - type = TYPE_NOT_SET; - if(str.empty()) return; - - if(str[0] == 'P') - { - type = TYPE_PRIVATE; - peer_id = RsPeerId(str.substr(1)); - } - else if(str[0] == 'D') - { - type = TYPE_PRIVATE_DISTANT; - distant_chat_id = DistantChatPeerId(str.substr(1)); - } - else if(str[0] == 'L') - { - if(sizeof(ChatLobbyId) != 8) - { - std::cerr << "ChatId::ChatId(std::string) Error: sizeof(ChatLobbyId) != 8. please report this" << std::endl; - return; - } - str = str.substr(1); - if(str.size() != 16) - return; - ChatLobbyId id = 0; - for(int i = 0; i<16; i++) - { - uint8_t c = str[i]; - if(c <= '9') - c -= '0'; - else - c -= 'A' - 10; - id = id << 4; - id |= c; - } - type = TYPE_LOBBY; - lobby_id = id; - } - else if(str[0] == 'B') - { - type = TYPE_BROADCAST; - } -} - -ChatId ChatId::makeBroadcastId() -{ - ChatId id; - id.type = TYPE_BROADCAST; - return id; -} - -std::string ChatId::toStdString() const -{ - std::string str; - if(type == TYPE_PRIVATE) - { - str += "P"; - str += peer_id.toStdString(); - } - else if(type == TYPE_PRIVATE_DISTANT) - { - str += "D"; - str += distant_chat_id.toStdString(); - } - else if(type == TYPE_LOBBY) - { - if(sizeof(ChatLobbyId) != 8) - { - std::cerr << "ChatId::toStdString() Error: sizeof(ChatLobbyId) != 8. please report this" << std::endl; - return ""; - } - str += "L"; - - ChatLobbyId id = lobby_id; - for(int i = 0; i<16; i++) - { - uint8_t c = id >>(64-4); - if(c > 9) - c += 'A' - 10; - else - c += '0'; - str += c; - id = id << 4; - } - } - else if(type == TYPE_BROADCAST) - { - str += "B"; - } - return str; -} - -bool ChatId::operator <(const ChatId& other) const -{ - if(type != other.type) - return type < other.type; - else - { - switch(type) - { - case TYPE_NOT_SET: - return false; - case TYPE_PRIVATE: - return peer_id < other.peer_id; - case TYPE_PRIVATE_DISTANT: - return distant_chat_id < other.distant_chat_id; - case TYPE_LOBBY: - return lobby_id < other.lobby_id; - case TYPE_BROADCAST: - return false; - default: - return false; - } - } -} - -bool ChatId::isSameEndpoint(const ChatId &other) const -{ - if(type != other.type) - return false; - else - { - switch(type) - { - case TYPE_NOT_SET: - return false; - case TYPE_PRIVATE: - return peer_id == other.peer_id; - case TYPE_PRIVATE_DISTANT: - return distant_chat_id == other.distant_chat_id; - case TYPE_LOBBY: - return lobby_id == other.lobby_id; - case TYPE_BROADCAST: - return true; - default: - return false; - } - } -} - -bool ChatId::isNotSet() const -{ - return type == TYPE_NOT_SET; -} -bool ChatId::isPeerId() const -{ - return type == TYPE_PRIVATE; -} -bool ChatId::isDistantChatId() const -{ - return type == TYPE_PRIVATE_DISTANT; -} -bool ChatId::isLobbyId() const -{ - return type == TYPE_LOBBY; -} -bool ChatId::isBroadcast() const -{ - return type == TYPE_BROADCAST; -} -RsPeerId ChatId::toPeerId() const -{ - if(type == TYPE_PRIVATE) - return peer_id; - else - { - std::cerr << "ChatId Warning: conversation to RsPeerId requested, but type is different. Current value=\"" << toStdString() << "\"" << std::endl; - return RsPeerId(); - } -} - -DistantChatPeerId ChatId::toDistantChatId() const -{ - if(type == TYPE_PRIVATE_DISTANT) - return distant_chat_id; - else - { - std::cerr << "ChatId Warning: conversation to DistantChatPeerId requested, but type is different. Current value=\"" << toStdString() << "\"" << std::endl; - return DistantChatPeerId(); - } -} -ChatLobbyId ChatId::toLobbyId() const -{ - if(type == TYPE_LOBBY) - return lobby_id; - else - { - std::cerr << "ChatId Warning: conversation to ChatLobbyId requested, but type is different. Current value=\"" << toStdString() << "\"" << std::endl; - return 0; - } -} - -bool p3Msgs::getMessageSummaries(std::list &msgList) -{ - return mMsgSrv->getMessageSummaries(msgList); -} - - -uint32_t p3Msgs::getDistantMessagingPermissionFlags() -{ - return mMsgSrv->getDistantMessagingPermissionFlags(); -} - -void p3Msgs::setDistantMessagingPermissionFlags(uint32_t flags) -{ - return mMsgSrv->setDistantMessagingPermissionFlags(flags); -} - - -bool p3Msgs::getMessage(const std::string &mid, MessageInfo &msg) -{ - return mMsgSrv->getMessage(mid, msg); -} - -void p3Msgs::getMessageCount(uint32_t &nInbox, uint32_t &nInboxNew, uint32_t &nOutbox, uint32_t &nDraftbox, uint32_t &nSentbox, uint32_t &nTrashbox) -{ - mMsgSrv->getMessageCount(nInbox, nInboxNew, nOutbox, nDraftbox, nSentbox, nTrashbox); -} - -/****************************************/ -/****************************************/ - /* Message Items */ -bool p3Msgs::MessageSend(MessageInfo &info) -{ - return mMsgSrv->MessageSend(info); -} - -uint32_t p3Msgs::sendMail( - const RsGxsId from, - const std::string& subject, - const std::string& body, - const std::set& to, - const std::set& cc, - const std::set& bcc, - const std::vector& attachments, - std::set& trackingIds, - std::string& errorMsg ) -{ - return mMsgSrv->sendMail( - from, subject, body, to, cc, bcc, attachments, - trackingIds, errorMsg ); -} - -bool p3Msgs::SystemMessage(const std::string &title, const std::string &message, uint32_t systemFlag) -{ - return mMsgSrv->SystemMessage(title, message, systemFlag); -} - -bool p3Msgs::MessageToDraft(MessageInfo &info, const std::string &msgParentId) -{ - return mMsgSrv->MessageToDraft(info, msgParentId); -} - -bool p3Msgs::MessageToTrash(const std::string &mid, bool bTrash) -{ - return mMsgSrv->MessageToTrash(mid, bTrash); -} - -bool p3Msgs::getMsgParentId(const std::string &msgId, std::string &msgParentId) -{ - return mMsgSrv->getMsgParentId(msgId, msgParentId); -} - -/****************************************/ -/****************************************/ -bool p3Msgs::MessageDelete(const std::string &mid) -{ - //std::cerr << "p3Msgs::MessageDelete() "; - //std::cerr << "mid: " << mid << std::endl; - - return mMsgSrv -> removeMsgId(mid); -} - -bool p3Msgs::MessageRead(const std::string &mid, bool unreadByUser) -{ - //std::cerr << "p3Msgs::MessageRead() "; - //std::cerr << "mid: " << mid << std::endl; - - return mMsgSrv -> markMsgIdRead(mid, unreadByUser); -} - -bool p3Msgs::MessageReplied(const std::string &mid, bool replied) -{ - return mMsgSrv->setMsgFlag(mid, replied ? RS_MSG_FLAGS_REPLIED : 0, RS_MSG_FLAGS_REPLIED); -} - -bool p3Msgs::MessageForwarded(const std::string &mid, bool forwarded) -{ - return mMsgSrv->setMsgFlag(mid, forwarded ? RS_MSG_FLAGS_FORWARDED : 0, RS_MSG_FLAGS_FORWARDED); -} - -bool p3Msgs::MessageLoadEmbeddedImages(const std::string &mid, bool load) -{ - return mMsgSrv->setMsgFlag(mid, load ? RS_MSG_FLAGS_LOAD_EMBEDDED_IMAGES : 0, RS_MSG_FLAGS_LOAD_EMBEDDED_IMAGES); -} - -bool p3Msgs::getMessageTagTypes(MsgTagType& tags) -{ - return mMsgSrv->getMessageTagTypes(tags); -} - -bool p3Msgs::MessageStar(const std::string &mid, bool star) -{ - return mMsgSrv->setMsgFlag(mid, star ? RS_MSG_FLAGS_STAR : 0, RS_MSG_FLAGS_STAR); -} - -bool p3Msgs::MessageJunk(const std::string &mid, bool junk) -{ - return mMsgSrv->setMsgFlag(mid, junk ? RS_MSG_FLAGS_SPAM : 0, RS_MSG_FLAGS_SPAM); -} - -bool p3Msgs::setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color) -{ - return mMsgSrv->setMessageTagType(tagId, text, rgb_color); -} - -bool p3Msgs::removeMessageTagType(uint32_t tagId) -{ - return mMsgSrv->removeMessageTagType(tagId); -} - -bool p3Msgs::getMessageTag(const std::string &msgId, MsgTagInfo& info) -{ - return mMsgSrv->getMessageTag(msgId, info); -} - -bool p3Msgs::setMessageTag(const std::string &msgId, uint32_t tagId, bool set) -{ - return mMsgSrv->setMessageTag(msgId, tagId, set); -} - -bool p3Msgs::resetMessageStandardTagTypes(MsgTagType& tags) -{ - return mMsgSrv->resetMessageStandardTagTypes(tags); -} - -/****************************************/ -/****************************************/ -bool p3Msgs::sendChat(ChatId destination, std::string msg) -{ - return mChatSrv->sendChat(destination, msg); -} - -uint32_t p3Msgs::getMaxMessageSecuritySize(int type) -{ - return mChatSrv->getMaxMessageSecuritySize(type); -} - -void p3Msgs::sendStatusString(const ChatId& id, const std::string& status_string) -{ - mChatSrv->sendStatusString(id, status_string); -} - -void p3Msgs::clearChatLobby(const ChatId &id) -{ - mChatSrv->clearChatLobby(id); -} - -void p3Msgs::getOwnAvatarData(unsigned char *& data,int& size) -{ - mChatSrv->getOwnAvatarJpegData(data,size) ; -} - -void p3Msgs::setOwnAvatarData(const unsigned char *data,int size) -{ - mChatSrv->setOwnAvatarJpegData(data,size) ; -} - -void p3Msgs::getAvatarData(const RsPeerId& pid,unsigned char *& data,int& size) -{ - mChatSrv->getAvatarJpegData(pid,data,size) ; -} - -std::string p3Msgs::getCustomStateString(const RsPeerId& peer_id) -{ - return mChatSrv->getCustomStateString(peer_id) ; -} - -std::string p3Msgs::getCustomStateString() -{ - return mChatSrv->getOwnCustomStateString() ; -} - -void p3Msgs::setCustomStateString(const std::string& state_string) -{ - mChatSrv->setOwnCustomStateString(state_string) ; -} - -bool p3Msgs::getChatLobbyInfo(const ChatLobbyId& id,ChatLobbyInfo& linfo) -{ - return mChatSrv->getChatLobbyInfo(id,linfo) ; -} -void p3Msgs::getChatLobbyList(std::list& lids) -{ - mChatSrv->getChatLobbyList(lids) ; -} -void p3Msgs::invitePeerToLobby(const ChatLobbyId& lobby_id, const RsPeerId& 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) -{ - mChatSrv->unsubscribeChatLobby(lobby_id) ; -} -bool p3Msgs::setDefaultIdentityForChatLobby(const RsGxsId& nick) -{ - return mChatSrv->setDefaultIdentityForChatLobby(nick) ; -} -void p3Msgs::getDefaultIdentityForChatLobby(RsGxsId& nick_name) -{ - mChatSrv->getDefaultIdentityForChatLobby(nick_name) ; -} - -bool p3Msgs::setIdentityForChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& nick) -{ - return mChatSrv->setIdentityForChatLobby(lobby_id,nick) ; -} -bool p3Msgs::getIdentityForChatLobby(const ChatLobbyId& lobby_id,RsGxsId& nick_name) -{ - return mChatSrv->getIdentityForChatLobby(lobby_id,nick_name) ; -} - -bool p3Msgs::joinVisibleChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& own_id) -{ - return mChatSrv->joinVisibleChatLobby(lobby_id,own_id) ; -} - -void p3Msgs::getListOfNearbyChatLobbies(std::vector& public_lobbies) -{ - mChatSrv->getListOfNearbyChatLobbies(public_lobbies) ; -} - -ChatLobbyId p3Msgs::createChatLobby(const std::string& lobby_name,const RsGxsId& lobby_identity,const std::string& lobby_topic,const std::set& invited_friends,ChatLobbyFlags privacy_type) -{ - return mChatSrv->createChatLobby(lobby_name,lobby_identity,lobby_topic,invited_friends,privacy_type) ; -} - -void p3Msgs::setLobbyAutoSubscribe(const ChatLobbyId& lobby_id, const bool autoSubscribe) -{ - mChatSrv->setLobbyAutoSubscribe(lobby_id, autoSubscribe); -} - -bool p3Msgs::getLobbyAutoSubscribe(const ChatLobbyId& lobby_id) -{ - return mChatSrv->getLobbyAutoSubscribe(lobby_id); -} - - -bool p3Msgs::acceptLobbyInvite(const ChatLobbyId& id,const RsGxsId& gxs_id) -{ - return mChatSrv->acceptLobbyInvite(id,gxs_id) ; -} -void p3Msgs::denyLobbyInvite(const ChatLobbyId& id) -{ - mChatSrv->denyLobbyInvite(id) ; -} -void p3Msgs::getPendingChatLobbyInvites(std::list& invites) -{ - mChatSrv->getPendingChatLobbyInvites(invites) ; -} -bool p3Msgs::initiateDistantChatConnexion( - const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, - DistantChatPeerId& pid, uint32_t& error_code, bool notify ) -{ - return mChatSrv->initiateDistantChatConnexion( to_gxs_id, from_gxs_id, pid, error_code, notify ); -} -bool p3Msgs::getDistantChatStatus(const DistantChatPeerId& pid,DistantChatPeerInfo& info) -{ - return mChatSrv->getDistantChatStatus(pid,info) ; -} -bool p3Msgs::closeDistantChatConnexion(const DistantChatPeerId &pid) -{ - return mChatSrv->closeDistantChatConnexion(pid) ; -} -bool p3Msgs::setDistantChatPermissionFlags(uint32_t flags) -{ - return mChatSrv->setDistantChatPermissionFlags(flags) ; -} -uint32_t p3Msgs::getDistantChatPermissionFlags() -{ - return mChatSrv->getDistantChatPermissionFlags() ; -} - -RsMsgs::~RsMsgs() = default; -Rs::Msgs::MessageInfo::~MessageInfo() = default; -MsgInfoSummary::~MsgInfoSummary() = default; -VisibleChatLobbyRecord::~VisibleChatLobbyRecord() = default; - -void RsMailIdRecipientIdPair::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(mMailId); - RS_SERIAL_PROCESS(mRecipientId); -} - -bool RsMailIdRecipientIdPair::operator<(const RsMailIdRecipientIdPair& o) const -{ - return std::tie( mMailId, mRecipientId) < - std::tie(o.mMailId, o.mRecipientId); -} - -bool RsMailIdRecipientIdPair::operator==(const RsMailIdRecipientIdPair& o) const -{ - return std::tie( mMailId, mRecipientId) == - std::tie(o.mMailId, o.mRecipientId); -} diff --git a/libretroshare/src/rsserver/p3msgs.h b/libretroshare/src/rsserver/p3msgs.h deleted file mode 100644 index 91d044ee5..000000000 --- a/libretroshare/src/rsserver/p3msgs.h +++ /dev/null @@ -1,190 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3msgs.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2008 Robert Fernie * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsmsgs.h" -#include "retroshare/rsgxsifacetypes.h" - -class p3MsgService; -class p3ChatService; - -class RsChatMsgItem; - -//! provides retroshares chatservice and messaging service -/*! - * Provides rs with the ability to send/receive messages, immediate status, - * custom status, avatar and - * chats (public(group) and private) to peers - */ -class p3Msgs: public RsMsgs -{ -public: - - p3Msgs(p3MsgService *p3m, p3ChatService *p3c) : - mMsgSrv(p3m), mChatSrv(p3c) {} - ~p3Msgs() override = default; - - /// @see RsMsgs - uint32_t sendMail( - const RsGxsId from, - const std::string& subject, - const std::string& body, - const std::set& to = std::set(), - const std::set& cc = std::set(), - const std::set& bcc = std::set(), - const std::vector& attachments = std::vector(), - std::set& trackingIds = - RS_DEFAULT_STORAGE_PARAM(std::set), - std::string& errorMsg = - RS_DEFAULT_STORAGE_PARAM(std::string) ) override; - - /****************************************/ - /* Message Items */ - - /*! - * @param msgList ref to list summarising client's msgs - */ - virtual bool getMessageSummaries(std::list &msgList); - virtual bool getMessage(const std::string &mId, Rs::Msgs::MessageInfo &msg); - virtual void getMessageCount(uint32_t &nInbox, uint32_t &nInboxNew, uint32_t &nOutbox, uint32_t &nDraftbox, uint32_t &nSentbox, uint32_t &nTrashbox); - - RS_DEPRECATED_FOR(sendMail) - virtual bool MessageSend(Rs::Msgs::MessageInfo &info); - virtual bool SystemMessage(const std::string &title, const std::string &message, uint32_t systemFlag); - virtual bool MessageToDraft(Rs::Msgs::MessageInfo &info, const std::string &msgParentId); - virtual bool MessageToTrash(const std::string &mid, bool bTrash); - virtual bool MessageDelete(const std::string &mid); - virtual bool MessageRead(const std::string &mid, bool unreadByUser); - virtual bool MessageReplied(const std::string &mid, bool replied); - virtual bool MessageForwarded(const std::string &mid, bool forwarded); - virtual bool MessageStar(const std::string &mid, bool star); - virtual bool MessageJunk(const std::string &mid, bool junk); - virtual bool MessageLoadEmbeddedImages(const std::string &mid, bool load); - virtual bool getMsgParentId(const std::string &msgId, std::string &msgParentId); - - virtual bool getMessageTagTypes(Rs::Msgs::MsgTagType& tags); - virtual bool setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color); - virtual bool removeMessageTagType(uint32_t tagId); - - virtual bool getMessageTag(const std::string &msgId, Rs::Msgs::MsgTagInfo& info); - /* set == false && tagId == 0 --> remove all */ - virtual bool setMessageTag(const std::string &msgId, uint32_t tagId, bool set); - - virtual bool resetMessageStandardTagTypes(Rs::Msgs::MsgTagType& tags); - - virtual uint32_t getDistantMessagingPermissionFlags() ; - virtual void setDistantMessagingPermissionFlags(uint32_t flags) ; - - /*! - * gets avatar from peer, image data in jpeg format - */ - virtual void getAvatarData(const RsPeerId& pid,unsigned char *& data,int& size); - - /*! - * sets clients avatar, image data should be in jpeg format - */ - virtual void setOwnAvatarData(const unsigned char *data,int size); - - /*! - * retrieve clients avatar, image data in jpeg format - */ - virtual void getOwnAvatarData(unsigned char *& data,int& size); - - /*! - * sets clients custom status (e.g. "i'm tired") - */ - virtual void setCustomStateString(const std::string& status_string) ; - - /*! - * retrieves client's custom status - */ - virtual std::string getCustomStateString() ; - - /*! - * retrieves peer's custom status - */ - virtual std::string getCustomStateString(const RsPeerId& peer_id) ; - - - /*! - * Send a chat message. - * @param destination where to send the chat message - * @param msg the message - * @see ChatId - */ - virtual bool sendChat(ChatId destination, std::string msg) ; - - /*! - * Return the max message size for security forwarding - */ - virtual uint32_t getMaxMessageSecuritySize(int type); - - /*! - * sends immediate status string to a specific peer, e.g. in a private chat - * @param chat_id chat id to send status string to - * @param status_string immediate status to send - */ - virtual void sendStatusString(const ChatId& id, const std::string& status_string) ; - - /** - * @brief clearChatLobby: Signal chat was cleared by GUI. - * @param id: Chat id cleared. - */ - virtual void clearChatLobby(const ChatId &id); - - /****************************************/ - - virtual bool joinVisibleChatLobby(const ChatLobbyId& id, const RsGxsId &own_id) ; - virtual void getListOfNearbyChatLobbies(std::vector& public_lobbies) ; - virtual void getChatLobbyList(std::list& cl_list) ; - virtual bool getChatLobbyInfo(const ChatLobbyId& id,ChatLobbyInfo& info) ; - virtual void invitePeerToLobby(const ChatLobbyId&, const RsPeerId&) ; - virtual bool acceptLobbyInvite(const ChatLobbyId& id, const RsGxsId &gxs_id) ; - virtual void denyLobbyInvite(const ChatLobbyId& id) ; - virtual void getPendingChatLobbyInvites(std::list& invites) ; - 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 getIdentityForChatLobby(const ChatLobbyId&,RsGxsId& nick) ; - virtual bool setDefaultIdentityForChatLobby(const RsGxsId&) ; - virtual void getDefaultIdentityForChatLobby(RsGxsId& nick) ; - virtual void setLobbyAutoSubscribe(const ChatLobbyId& lobby_id, const bool autoSubscribe); - virtual bool getLobbyAutoSubscribe(const ChatLobbyId& lobby_id); - virtual ChatLobbyId createChatLobby(const std::string& lobby_name,const RsGxsId& lobby_identity,const std::string& lobby_topic,const std::set& invited_friends,ChatLobbyFlags privacy_type) ; - - virtual bool initiateDistantChatConnexion( - const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, - DistantChatPeerId &pid, uint32_t& error_code, - bool notify = true ); - - virtual bool getDistantChatStatus(const DistantChatPeerId& gxs_id,DistantChatPeerInfo& info); - virtual bool closeDistantChatConnexion(const DistantChatPeerId &pid) ; - - virtual uint32_t getDistantChatPermissionFlags() ; - virtual bool setDistantChatPermissionFlags(uint32_t flags) ; - - private: - - p3MsgService *mMsgSrv; - p3ChatService *mChatSrv; -}; diff --git a/libretroshare/src/rsserver/p3peers.cc b/libretroshare/src/rsserver/p3peers.cc deleted file mode 100644 index c44877fc5..000000000 --- a/libretroshare/src/rsserver/p3peers.cc +++ /dev/null @@ -1,1933 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3peers.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2015-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "pgp/pgpkeyutil.h" - -#include "rsserver/p3peers.h" -#include "rsserver/p3face.h" - -#include "pqi/p3linkmgr.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3netmgr.h" - -#include "pqi/authssl.h" -#include "pqi/authgpg.h" -#include "retroshare/rsinit.h" -#include "retroshare/rsnotify.h" -#include "retroshare/rsfiles.h" -#include "util/rsurl.h" -#include "util/radix64.h" -#include "util/rsbase64.h" -#include "pgp/rscertificate.h" - -#include -#include - -//static const int MAX_TIME_KEEP_LOCATION_WITHOUT_CONTACT = 30*24*3600 ; // 30 days. - -#include "pqi/authssl.h" - - -RsPeers *rsPeers = NULL; - -/******* - * #define P3PEERS_DEBUG 1 - *******/ - -//int ensureExtension(std::string &name, std::string def_ext); - -std::string RsPeerTrustString(uint32_t trustLvl) -{ - std::string str; - - switch(trustLvl) - { - default: - case RS_TRUST_LVL_UNKNOWN: - str = "VALIDITY_UNKNOWN"; - break; - case RS_TRUST_LVL_UNDEFINED: - str = "VALIDITY_UNDEFINED"; - break; - case RS_TRUST_LVL_NEVER: - str = "VALIDITY_NEVER"; - break; - case RS_TRUST_LVL_MARGINAL: - str = "VALIDITY_MARGINAL"; - break; - case RS_TRUST_LVL_FULL: - str = "VALIDITY_FULL"; - break; - case RS_TRUST_LVL_ULTIMATE: - str = "VALIDITY_ULTIMATE"; - break; - } - return str; -} - -std::string RsPeerNetModeString(uint32_t netModel) -{ - std::string str; - if (netModel == RS_NETMODE_EXT) - { - str = "External Port"; - } - else if (netModel == RS_NETMODE_UPNP) - { - str = "Ext (UPnP)"; - } - else if (netModel == RS_NETMODE_UDP) - { - str = "UDP Mode"; - } - else if (netModel == RS_NETMODE_HIDDEN) - { - str = "Hidden"; - } - else if (netModel == RS_NETMODE_UNREACHABLE) - { - str = "UDP Mode (Unreachable)"; - } - else - { - str = "Unknown NetMode"; - } - return str; -} - - -p3Peers::p3Peers(p3LinkMgr *lm, p3PeerMgr *pm, p3NetMgr *nm) - :mLinkMgr(lm), mPeerMgr(pm), mNetMgr(nm) {} - - /* Updates ... */ -bool p3Peers::FriendsChanged(const RsPeerId& pid,bool add) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::FriendsChanged()" << std::endl; -#endif - if(rsEvents) - { - auto ev = std::make_shared(pid); - rsEvents->postEvent(ev); - } - RsServer::notify()->notifyListChange(NOTIFY_LIST_FRIENDS, add? NOTIFY_TYPE_ADD : NOTIFY_TYPE_DEL); // this is meant to disappear - - /* TODO */ - return false; -} - -bool p3Peers::OthersChanged() -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::OthersChanged()" << std::endl; -#endif - - /* TODO */ - return false; -} - - /* Peer Details (Net & Auth) */ -const RsPeerId& p3Peers::getOwnId() -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getOwnId()" << std::endl; -#endif - - return AuthSSL::getAuthSSL()->OwnId(); -} - -bool p3Peers::getOnlineList(std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getOnlineList()" << std::endl; -#endif - - /* get from mConnectMgr */ - mLinkMgr->getOnlineList(ids); - return true; -} - -bool p3Peers::getFriendList(std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getFriendList()" << std::endl; -#endif - - /* get from mConnectMgr */ - mLinkMgr->getFriendList(ids); - return true; -} - -//bool p3Peers::getOthersList(std::list &ids) -//{ -//#ifdef P3PEERS_DEBUG -// std::cerr << "p3Peers::getOthersList()"; -// std::cerr << std::endl; -//#endif -// -// /* get from mAuthMgr */ -// AuthSSL::getAuthSSL()->getAllList(ids); -// return true; -//} - -bool p3Peers::getPeersCount( - uint32_t& peersCount, uint32_t& onlinePeersCount, - bool countLocations ) -{ - peersCount = mPeerMgr->getFriendCount(countLocations, false); - onlinePeersCount = mPeerMgr->getFriendCount(countLocations, true); - return true; -} - -bool p3Peers::getPeerCount (unsigned int *friendCount, unsigned int *onlineCount, bool ssl) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPeerCount()" << std::endl; -#endif - - if (friendCount) *friendCount = mPeerMgr->getFriendCount(ssl, false); - if (onlineCount) *onlineCount = mPeerMgr->getFriendCount(ssl, true); - - return true; -} - -bool p3Peers::isOnline(const RsPeerId &id) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::isOnline() " << id << std::endl; -#endif - - /* get from mConnectMgr */ - peerConnectState state; - if (mLinkMgr->getFriendNetStatus(id, state) && - (state.state & RS_PEER_S_CONNECTED)) - { - return true; - } - return false; -} - -bool p3Peers::isFriend(const RsPeerId &ssl_id) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::isFriend() " << ssl_id << std::endl; -#endif - - /* get from mConnectMgr */ - return mPeerMgr->isFriend(ssl_id); -} - -bool p3Peers::getPeerMaximumRates(const RsPeerId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) -{ - return mPeerMgr->getMaxRates(pid,maxUploadRate,maxDownloadRate) ; -} -bool p3Peers::getPeerMaximumRates(const RsPgpId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) -{ - return mPeerMgr->getMaxRates(pid,maxUploadRate,maxDownloadRate) ; -} - -bool p3Peers::setPeerMaximumRates(const RsPgpId& pid,uint32_t maxUploadRate,uint32_t maxDownloadRate) -{ - return mPeerMgr->setMaxRates(pid,maxUploadRate,maxDownloadRate) ; -} - -bool p3Peers::haveSecretKey(const RsPgpId& id) -{ - return AuthGPG::getAuthGPG()->haveSecretKey(id); -} - -/* There are too many dependancies of this function - * to shift it immeidately - */ - -bool p3Peers::getPeerDetails(const RsPeerId& id, RsPeerDetails &d) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPeerDetails() called for id : " << id << std::endl; -#endif - - RsPeerId sOwnId = AuthSSL::getAuthSSL()->OwnId(); - peerState ps; - - if (id == sOwnId) - { - mPeerMgr->getOwnNetStatus(ps); - ps.gpg_id = AuthGPG::getAuthGPG()->getGPGOwnId(); - } - else if (!mPeerMgr->getFriendNetStatus(id, ps)) - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPeerDetails() ERROR not an SSL Id: " << id << std::endl; -#endif - return false; - } - - /* get from gpg (first), to fill in the sign and trust details */ - /* don't return now, we've got fill in the ssl and connection info */ - - if(!getGPGDetails(ps.gpg_id, d)) - { - if(!ps.skip_pgp_signature_validation) - return false; - - d.gpg_id = ps.gpg_id ; - d.skip_pgp_signature_validation = true; - } - else - d.skip_pgp_signature_validation = false; - - d.isOnlyGPGdetail = false; - - //get the ssl details - d.id = id; - d.location = ps.location; - - d.service_perm_flags = mPeerMgr->servicePermissionFlags(ps.gpg_id); - - /* generate */ - d.authcode = "AUTHCODE"; - - /* fill from pcs */ - d.lastConnect = ps.lastcontact; - d.connectPeriod = 0; - - if (ps.hiddenNode) - { - d.isHiddenNode = true; - d.hiddenNodeAddress = ps.hiddenDomain; - d.hiddenNodePort = ps.hiddenPort; - d.hiddenType = ps.hiddenType; - - if(sockaddr_storage_isnull(ps.localaddr)) // that happens if the address is not initialised. - { - d.localAddr = "INVALID_IP"; - d.localPort = 0 ; - } - else - { - d.localAddr = sockaddr_storage_iptostring(ps.localaddr); - d.localPort = sockaddr_storage_port(ps.localaddr); - } - d.extAddr = "hidden"; - d.extPort = 0; - d.dyndns = ""; - } - else - { - d.isHiddenNode = false; - d.hiddenNodeAddress = ""; - d.hiddenNodePort = 0; - d.hiddenType = RS_HIDDEN_TYPE_NONE; - - if(!sockaddr_storage_isnull(ps.localaddr)) - { - sockaddr_storage_ipv6_to_ipv4(ps.localaddr); - d.localAddr = sockaddr_storage_iptostring(ps.localaddr); - d.localPort = sockaddr_storage_port(ps.localaddr); - } - else - { - d.localAddr = "INVALID_IP"; - d.localPort = 0; - } - - if(!sockaddr_storage_isnull(ps.serveraddr)) - { - sockaddr_storage_ipv6_to_ipv4(ps.serveraddr); - d.extAddr = sockaddr_storage_iptostring(ps.serveraddr); - d.extPort = sockaddr_storage_port(ps.serveraddr); - } - else - { - d.extAddr = "INVALID_IP"; - d.extPort = 0; - } - - d.dyndns = ps.dyndns; - - std::list::iterator it; - for(it = ps.ipAddrs.mLocal.mAddrs.begin(); - it != ps.ipAddrs.mLocal.mAddrs.end(); ++it) - { - sockaddr_storage_ipv6_to_ipv4(it->mAddr); - std::string toto; - toto += sockaddr_storage_tostring(it->mAddr); - rs_sprintf_append(toto, " %ld sec", time(NULL) - it->mSeenTime); - d.ipAddressList.push_back(toto); - } - for(it = ps.ipAddrs.mExt.mAddrs.begin(); it != ps.ipAddrs.mExt.mAddrs.end(); ++it) - { - sockaddr_storage_ipv6_to_ipv4(it->mAddr); - std::string toto; - toto += sockaddr_storage_tostring(it->mAddr); - rs_sprintf_append(toto, " %ld sec", time(NULL) - it->mSeenTime); - d.ipAddressList.push_back(toto); - } - } - - - switch(ps.netMode & RS_NET_MODE_ACTUAL) - { - case RS_NET_MODE_EXT: - d.netMode = RS_NETMODE_EXT; - break; - case RS_NET_MODE_UPNP: - d.netMode = RS_NETMODE_UPNP; - break; - case RS_NET_MODE_UDP: - d.netMode = RS_NETMODE_UDP; - break; - case RS_NET_MODE_HIDDEN: - d.netMode = RS_NETMODE_HIDDEN; - break; - case RS_NET_MODE_UNREACHABLE: - case RS_NET_MODE_UNKNOWN: - default: - d.netMode = RS_NETMODE_UNREACHABLE; - break; - } - - d.vs_disc = ps.vs_disc; - d.vs_dht = ps.vs_dht; - - /* Translate */ - peerConnectState pcs; - if (!mLinkMgr->getFriendNetStatus(id, pcs)) - { - if(id != sOwnId) - std::cerr << "p3Peers::getPeerDetails() ERROR No Link Information : " << id << std::endl; - return true; - } - -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPeerDetails() got a SSL id and is returning SSL and GPG details for id : " << id << std::endl; -#endif - - if (pcs.state & RS_PEER_S_CONNECTED) - { - sockaddr_storage_ipv6_to_ipv4(pcs.connectaddr); - d.connectAddr = sockaddr_storage_iptostring(pcs.connectaddr); - d.connectPort = sockaddr_storage_port(pcs.connectaddr); - } - else - { - d.connectAddr = ""; - d.connectPort = 0 ; - } - - d.state = 0; - if (pcs.state & RS_PEER_S_FRIEND) d.state |= RS_PEER_STATE_FRIEND; - if (pcs.state & RS_PEER_S_ONLINE) d.state |= RS_PEER_STATE_ONLINE; - if (pcs.state & RS_PEER_S_CONNECTED) d.state |= RS_PEER_STATE_CONNECTED; - if (pcs.state & RS_PEER_S_UNREACHABLE) d.state |= RS_PEER_STATE_UNREACHABLE; - - d.actAsServer = pcs.actAsServer; - - d.linkType = pcs.linkType; - - /* Finally determine AutoConnect Status */ - d.foundDHT = pcs.dht.found; - - d.connectState = RS_PEER_CONNECTSTATE_OFFLINE; - d.connectStateString.clear(); - - if (pcs.inConnAttempt) - { - if (pcs.currentConnAddrAttempt.type & RS_NET_CONN_TCP_ALL) { - d.connectState = RS_PEER_CONNECTSTATE_TRYING_TCP; - d.connectStateString = sockaddr_storage_tostring(pcs.currentConnAddrAttempt.addr); - } else if (pcs.currentConnAddrAttempt.type & RS_NET_CONN_UDP_ALL) { - d.connectState = RS_PEER_CONNECTSTATE_TRYING_UDP; - d.connectStateString = sockaddr_storage_tostring(pcs.currentConnAddrAttempt.addr); - } - } - else if (pcs.state & RS_PEER_S_CONNECTED) - { - /* peer is connected - determine how and set proper connectState */ - if(mPeerMgr->isHidden()) - { - uint32_t type; - /* hidden location */ - /* use connection direction to determine connection type */ - if(pcs.actAsServer) - { - /* incoming connection */ - /* use own type to set connectState */ - type = mPeerMgr->getHiddenType(AuthSSL::getAuthSSL()->OwnId()); - switch (type) { - case RS_HIDDEN_TYPE_TOR: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TOR; - break; - case RS_HIDDEN_TYPE_I2P: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_I2P; - break; - default: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN; - break; - } - } - else - { - /* outgoing connection */ - /* use peer hidden type to set connectState */ - switch (ps.hiddenType) { - case RS_HIDDEN_TYPE_TOR: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TOR; - break; - case RS_HIDDEN_TYPE_I2P: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_I2P; - break; - default: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN; - break; - } - } - } - else if (ps.hiddenType & RS_HIDDEN_TYPE_MASK) - { - /* hidden peer */ - /* use hidden type to set connectState */ - switch (ps.hiddenType) { - case RS_HIDDEN_TYPE_TOR: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TOR; - break; - case RS_HIDDEN_TYPE_I2P: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_I2P; - break; - default: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN; - break; - } - } - else - { - /* peer and we are normal nodes */ - /* use normal detection to set connectState */ - if (pcs.connecttype == RS_NET_CONN_TCP_ALL) - { - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TCP; - } - else if (pcs.connecttype == RS_NET_CONN_UDP_ALL) - { - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UDP; - } - else - { - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN; - } - } - } - - d.wasDeniedConnection = pcs.wasDeniedConnection; - d.deniedTS = pcs.deniedTS; - - return true; -} - -bool p3Peers::isProxyAddress(const uint32_t type, const sockaddr_storage& addr) -{ - uint16_t port ; - std::string string_addr; - uint32_t status ; - - if(!getProxyServer(type, string_addr, port, status)) - return false ; - - return sockaddr_storage_iptostring(addr)==string_addr && sockaddr_storage_port(addr)==port ; -} - -bool p3Peers::isKeySupported(const RsPgpId& id) -{ - return AuthGPG::getAuthGPG()->isKeySupported(id); -} - -std::string p3Peers::getGPGName(const RsPgpId &gpg_id) -{ - /* get from mAuthMgr as it should have more peers? */ - return AuthGPG::getAuthGPG()->getGPGName(gpg_id); -} - -bool p3Peers::isPgpFriend(const RsPgpId& pgpId) -{ return AuthGPG::getAuthGPG()->isGPGAccepted(pgpId); } - -bool p3Peers::isSslOnlyFriend(const RsPeerId& sslId) -{ - bool has_ssl_only_flag = mPeerMgr->isSslOnlyFriend(sslId) ; - - if(has_ssl_only_flag) - { - if(isPgpFriend(getGPGId(sslId))) - { - RsErr() << __PRETTY_FUNCTION__ << ": Peer " << sslId << " has SSL-friend-only flag but his PGP id is in the list of friends. This is inconsistent (Bug in the code). Returning false for security reasons." << std::endl; - return false; - } - return true; - } - return false; -} - -bool p3Peers::isGPGAccepted(const RsPgpId &gpg_id_is_friend) -{ return isPgpFriend(gpg_id_is_friend); } - -std::string p3Peers::getPeerName(const RsPeerId& ssl) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPeerName() " << ssl_or_gpg_id << std::endl; -#endif - std::string name; - if (ssl == AuthSSL::getAuthSSL()->OwnId()) - return AuthGPG::getAuthGPG()->getGPGOwnName(); - - if (mPeerMgr->getPeerName(ssl, name)) - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPeerName() got a ssl id. Name is : " << name << std::endl; -#endif - return name; - } - return std::string() ; -} - - -bool p3Peers::getGPGAllList(std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getGPGAllList()" << std::endl; -#endif - - /* get from mAuthMgr */ - AuthGPG::getAuthGPG()->getGPGAllList(ids); - return true; -} - -bool p3Peers::getGPGValidList(std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPGPOthersList()" << std::endl; -#endif - - /* get from mAuthMgr */ - AuthGPG::getAuthGPG()->getGPGValidList(ids); - return true; -} - -bool p3Peers::getGPGSignedList(std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPGPOthersList()" << std::endl; -#endif - - /* get from mAuthMgr */ - AuthGPG::getAuthGPG()->getGPGSignedList(ids); - return true; -} - -bool p3Peers::getPgpFriendList(std::vector& pgpIds) -{ - std::list ids; - if(AuthGPG::getAuthGPG()->getGPGAcceptedList(ids)) - { - pgpIds.clear(); - std::copy(ids.begin(), ids.end(), std::back_inserter(pgpIds)); - return true; - } - return false; -} - -bool p3Peers::getGPGAcceptedList(std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getGPGAcceptedList()" << std::endl; -#endif - AuthGPG::getAuthGPG()->getGPGAcceptedList(ids); - return true; -} - - -bool p3Peers::getAssociatedSSLIds(const RsPgpId &gpg_id, std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getAssociatedSSLIds() for id : " << gpg_id << std::endl; -#endif - - return mPeerMgr->getAssociatedPeers(gpg_id, ids); -} - -bool p3Peers::gpgSignData(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, std::string reason /* = "" */) -{ - return AuthGPG::getAuthGPG()->SignDataBin(data,len,sign,signlen, reason); -} - -RsPgpId p3Peers::pgpIdFromFingerprint(const RsPgpFingerprint& fpr) -{ - return PGPHandler::pgpIdFromFingerprint(fpr); -} - -bool p3Peers::getGPGDetails(const RsPgpId &pgp_id, RsPeerDetails &d) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPgpDetails() called for id : " << pgp_id << std::endl; -#endif - - /* get from mAuthMgr */ - bool res = AuthGPG::getAuthGPG()->getGPGDetails(pgp_id, d); - - d.isOnlyGPGdetail = true ; - d.service_perm_flags = mPeerMgr->servicePermissionFlags(pgp_id) ; - - return res ; -} - -const RsPgpId& p3Peers::getGPGOwnId() -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPGPOwnId()" << std::endl; -#endif - - /* get from mAuthMgr */ - return AuthGPG::getAuthGPG()->getGPGOwnId(); -} - -RsPgpId p3Peers::getGPGId(const RsPeerId& sslid) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPGPId()" << std::endl; -#endif - - /* get from mAuthMgr */ - if (sslid == AuthSSL::getAuthSSL()->OwnId()) - { - return AuthGPG::getAuthGPG()->getGPGOwnId(); - } - peerState pcs; - if (mPeerMgr->getFriendNetStatus(sslid, pcs)) - return pcs.gpg_id; - - return RsPgpId(); -} - - - /* These Functions are now the only way to authorize a new gpg user... - * if we are passed a ssl_id, then use it... otherwise just auth gpg_id - */ - - /* Add/Remove Friends */ -bool p3Peers::addFriend(const RsPeerId &ssl_id, const RsPgpId &gpg_id,ServicePermissionFlags perm_flags) -{ - -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addFriend() with : id : " << id << "; gpg_id : " << gpg_id << std::endl; -#endif - if(AuthGPG::getAuthGPG()->isGPGId(gpg_id)) - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addFriend() Authorising GPG Id: " << gpg_id << std::endl; -#endif - if (AuthGPG::getAuthGPG()->AllowConnection(gpg_id, true)) - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addFriend() Authorization OK." << std::endl; -#endif - } - else - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addFriend() Authorization FAILED." << std::endl; -#endif - return false; - } - } - else - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addFriend() Bad gpg_id : " << gpg_id << std::endl; -#endif - return false; - } - - if(ssl_id.isNull()) - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addFriend() WARNING id is NULL or gpgId" << std::endl; -#endif - return true; - } - - FriendsChanged(ssl_id,true); - - /* otherwise - we install as ssl_id..... - * If we are adding an SSL certificate. we flag lastcontact as now. - * This will cause the SSL certificate to be retained for 30 days... and give the person a chance to connect! - * */ - rstime_t now = time(NULL); - return mPeerMgr->addFriend(ssl_id, gpg_id, RS_NET_MODE_UDP, RS_VS_DISC_FULL, RS_VS_DHT_FULL, now, perm_flags); -} - -bool p3Peers::addSslOnlyFriend( const RsPeerId& sslId, const RsPgpId& pgp_id,const RsPeerDetails& details ) -{ - if( mPeerMgr->addSslOnlyFriend(sslId, pgp_id,details)) - { - FriendsChanged(sslId,true); - return true; - } - else - return false; -} - -bool p3Peers::removeKeysFromPGPKeyring(const std::set& pgp_ids,std::string& backup_file,uint32_t& error_code) -{ - return AuthGPG::getAuthGPG()->removeKeysFromPGPKeyring(pgp_ids,backup_file,error_code) ; -} - -bool p3Peers::removeFriendLocation(const RsPeerId &sslId) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::removeFriendLocation() " << sslId << std::endl; -#endif - //will remove if it's a ssl id - mPeerMgr->removeFriend(sslId, false); - - FriendsChanged(sslId,false); - return true; -} - -bool p3Peers::removeFriend(const RsPgpId& gpgId) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::removeFriend() " << gpgId << std::endl; -#endif - if (gpgId == AuthGPG::getAuthGPG()->getGPGOwnId()) { - std::cerr << "p3Peers::removeFriend() ERROR we're not going to remove our own GPG id." << std::endl; - return false; - } - -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::removeFriend() Removing GPG Id: " << gpgId << std::endl; -#endif - if (AuthGPG::getAuthGPG()->AllowConnection(gpgId, false)) - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::removeFriend() OK." << std::endl; -#endif - mPeerMgr->removeAllFriendLocations(gpgId); - return true; - } - else - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::removeFriend() FAILED." << std::endl; -#endif - mPeerMgr->removeAllFriendLocations(gpgId); - return false; - } -} - - - - /* Network Stuff */ -bool p3Peers::connectAttempt(const RsPeerId &id) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::connectAttempt() " << id << std::endl; -#endif - - return mLinkMgr->retryConnect(id); -} - -void p3Peers::getIPServersList(std::list& ip_servers) -{ - mNetMgr->getIPServersList(ip_servers) ; -} -bool p3Peers::resetOwnExternalAddressList() -{ - return mPeerMgr->resetOwnExternalAddressList(); -} -void p3Peers::allowServerIPDetermination(bool b) -{ - mNetMgr->setIPServersEnabled(b) ; -} - -bool p3Peers::getAllowServerIPDetermination() -{ - return mNetMgr->getIPServersEnabled() ; -} - -bool p3Peers::setLocation(const RsPeerId &ssl_id, const std::string &location) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setLocation() " << ssl_id << std::endl; -#endif - - return mPeerMgr->setLocation(ssl_id, location); -} - - -bool splitAddressString(const std::string &addr, std::string &domain, uint16_t &port) -{ - std::cerr << "splitAddressString() Input: " << addr << std::endl; - - size_t cpos = addr.rfind(':'); - if (cpos == std::string::npos) - { - std::cerr << "splitAddressString Failed to parse (:)"; - std::cerr << std::endl; - return false; - } - - int lenport = addr.length() - (cpos + 1); // +1 to skip over : char. - if (lenport <= 0) - { - std::cerr << "splitAddressString() Missing Port "; - std::cerr << std::endl; - return false; - } - - domain = addr.substr(0, cpos); - std::string portstr = addr.substr(cpos + 1, std::string::npos); - int portint = atoi(portstr.c_str()); - - if ((portint < 0) || (portint > 65535)) - { - std::cerr << "splitAddressString() Invalid Port"; - std::cerr << std::endl; - return false; - } - port = portint; - - std::cerr << "splitAddressString() Domain: " << domain << " Port: " << port; - std::cerr << std::endl; - return true; -} - - -bool p3Peers::setHiddenNode(const RsPeerId &id, const std::string &hidden_node_address) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setHiddenNode() " << id << std::endl; -#endif - - std::string domain; - uint16_t port; - if (!splitAddressString(hidden_node_address, domain, port)) - { - return false; - } - mPeerMgr->setNetworkMode(id, RS_NET_MODE_HIDDEN); - mPeerMgr->setHiddenDomainPort(id, domain, port); - return true; -} - - -bool p3Peers::isHiddenNode(const RsPeerId &id) -{ - return mPeerMgr->isHiddenNode(id) ; -} - -bool p3Peers::setHiddenNode(const RsPeerId &id, const std::string &address, uint16_t port) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setHiddenNode() " << id << std::endl; -#endif - std::cerr << "p3Peers::setHiddenNode() Domain: " << address << " Port: " << port; - std::cerr << std::endl; - - mPeerMgr->setNetworkMode(id, RS_NET_MODE_HIDDEN); - mPeerMgr->setHiddenDomainPort(id, address, port); - return true; -} - -bool p3Peers::addPeerLocator(const RsPeerId &ssl_id, const RsUrl& locator) -{ return mPeerMgr->addPeerLocator(ssl_id, locator); } - -bool p3Peers::setLocalAddress(const RsPeerId &id, - const std::string &addr_str, uint16_t port) -{ -#ifdef P3PEERS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " " << id << " " << addr_str << " " - << port << std::endl; -#endif - - sockaddr_storage addr; - if (sockaddr_storage_inet_pton(addr, addr_str)) - if (sockaddr_storage_setport(addr, port)) - return mPeerMgr->setLocalAddress(id, addr); - return false; -} - -bool p3Peers::setExtAddress(const RsPeerId &id, - const std::string &addr_str, uint16_t port) -{ -#ifdef P3PEERS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " " << id << " " << addr_str << " " - << port << std::endl; -#endif - - sockaddr_storage addr; - if (sockaddr_storage_inet_pton(addr, addr_str)) - if (sockaddr_storage_setport(addr, port)) - return mPeerMgr->setExtAddress(id, addr); - return false; -} - -bool p3Peers::setDynDNS(const RsPeerId &id, const std::string &dyndns) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setDynDNS() called with id: " << id << " dyndns: " << dyndns <setDynDNS(id, dyndns); -} - -bool p3Peers::setNetworkMode(const RsPeerId &id, uint32_t extNetMode) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setNetworkMode() " << id << std::endl; -#endif - - /* translate */ - uint32_t netMode = 0; - switch(extNetMode) - { - case RS_NETMODE_EXT: - netMode = RS_NET_MODE_EXT; - break; - case RS_NETMODE_UPNP: - netMode = RS_NET_MODE_UPNP; - break; - case RS_NETMODE_UDP: - netMode = RS_NET_MODE_UDP; - break; - case RS_NETMODE_HIDDEN: - netMode = RS_NET_MODE_HIDDEN; - break; - case RS_NETMODE_UNREACHABLE: - netMode = RS_NET_MODE_UNREACHABLE; - break; - default: - break; - } - - return mPeerMgr->setNetworkMode(id, netMode); -} - - -bool p3Peers::setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setVisState() " << id << std::endl; -#endif - std::cerr << "p3Peers::setVisState() " << id << " DISC: " << vs_disc; - std::cerr << " DHT: " << vs_dht << std::endl; - - return mPeerMgr->setVisState(id, vs_disc, vs_dht); -} - -bool p3Peers::getProxyServer(const uint32_t type, std::string &addr, uint16_t &port, uint32_t &status) -{ - #ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getProxyServer()" << std::endl; - #endif - - struct sockaddr_storage proxy_addr; - mPeerMgr->getProxyServerAddress(type, proxy_addr); - addr = sockaddr_storage_iptostring(proxy_addr); - port = sockaddr_storage_port(proxy_addr); - mPeerMgr->getProxyServerStatus(type, status); - return true; -} - -bool p3Peers::setProxyServer(const uint32_t type, const std::string &addr_str, const uint16_t port) -{ - #ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setProxyServer() " << std::endl; - #endif - - if(port < 1024) - { - std::cerr << "(EE) attempt to set proxy server address to something not allowed: " << addr_str << ":" << port << std::endl; - return false ; - } - - std::cerr << "Settign proxy server address to " << addr_str << ":" << port << std::endl; - - struct sockaddr_storage addr; - struct sockaddr_in *addrv4p = (struct sockaddr_in *) &addr; - addrv4p->sin_family = AF_INET; - addrv4p->sin_port = htons(port); - - int ret = 1; -/********************************** WINDOWS/UNIX SPECIFIC PART *******************/ -#ifndef WINDOWS_SYS - if (ret && (0 != inet_aton(addr_str.c_str(), &(addrv4p->sin_addr)))) -#else - addrv4p->sin_addr.s_addr = inet_addr(addr_str.c_str()); - if (ret) -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART *******************/ - { - return mPeerMgr->setProxyServerAddress(type, addr); - } - else - { - std::cerr << "p3Peers::setProxyServer() Failed to Parse Address" << std::endl; - } - - return false; -} - - - - - -//=========================================================================== - /* Auth Stuff */ - -std::string p3Peers::getPGPKey(const RsPgpId& pgp_id,bool include_signatures) -{ - rs_owner_ptr mem_block = nullptr; - size_t mem_block_size = 0; - - if( !AuthGPG::getAuthGPG()->exportPublicKey( - RsPgpId(pgp_id), mem_block, mem_block_size, - false, include_signatures ) ) - { - RsErr() << __PRETTY_FUNCTION__ - << " Failure retriving certificate for id " << pgp_id - << std::endl; - return ""; - } - - RsPeerDetails details; - if(!getGPGDetails(pgp_id, details)) return ""; - - auto certPtr = - RsCertificate::fromMemoryBlock(details, mem_block, mem_block_size); - - free(mem_block); - - if(certPtr) return certPtr->armouredPGPKey(); - - return ""; -} - - -bool p3Peers::GetPGPBase64StringAndCheckSum( - const RsPgpId& gpg_id, - std::string& gpg_base64_string, std::string& gpg_base64_checksum ) -{ - gpg_base64_string = "" ; - gpg_base64_checksum = "" ; - - rs_owner_ptr mem_block = nullptr; - size_t mem_block_size = 0; - if(!AuthGPG::getAuthGPG()->exportPublicKey( - gpg_id,mem_block,mem_block_size,false,false )) - return false; - - RsBase64::encode(mem_block, mem_block_size, gpg_base64_string, true, false); - - uint32_t crc = PGPKeyManagement::compute24bitsCRC(mem_block,mem_block_size); - - free(mem_block); - - unsigned char tmp[3] = { - uint8_t((crc >> 16) & 0xff), - uint8_t((crc >> 8) & 0xff), - uint8_t(crc & 0xff) } ; - RsBase64::encode(tmp, 3, gpg_base64_checksum, true, false); - - return true; -} - -enum class RsShortInviteFieldType : uint8_t -{ - SSL_ID = 0x00, - PEER_NAME = 0x01, - LOCATOR = 0x02, - PGP_FINGERPRINT = 0x03, - CHECKSUM = 0x04, - - /* The following will be deprecated, and ported to LOCATOR when generic - * trasport layer will be implemented */ - HIDDEN_LOCATOR = 0x90, - DNS_LOCATOR = 0x91, - EXT4_LOCATOR = 0x92, // external IPv4 address - LOC4_LOCATOR = 0x93 // local IPv4 address -}; - -static void addPacketHeader(RsShortInviteFieldType ptag, size_t size, unsigned char *& buf, uint32_t& offset, uint32_t& buf_size) -{ - // Check that the buffer has sufficient size. If not, increase it. - - while(offset + size + 6 >= buf_size) - { - unsigned char *newbuf = new unsigned char[2*buf_size] ; - - memcpy(newbuf, buf, buf_size) ; - buf_size *= 2 ; - delete[] buf ; - buf = newbuf ; - } - - // Write ptag and size - - buf[offset] = static_cast(ptag) ; - offset += 1 ; - - offset += PGPKeyParser::write_125Size(&buf[offset],size) ; -} - -bool p3Peers::getShortInvite(std::string& invite, const RsPeerId& _sslId, RetroshareInviteFlags invite_flags, const std::string& baseUrl ) -{ - RsPeerId sslId = _sslId; - if(sslId.isNull()) sslId = getOwnId(); - - RsPeerDetails tDetails; - if(!getPeerDetails(sslId, tDetails)) return false; - - uint32_t buf_size = 100; - uint32_t offset = 0; - unsigned char *buf = (unsigned char*)malloc(buf_size); - - addPacketHeader(RsShortInviteFieldType::SSL_ID,RsPeerId::SIZE_IN_BYTES,buf,offset,buf_size); - sslId.serialise(buf,buf_size,offset); - - addPacketHeader(RsShortInviteFieldType::PGP_FINGERPRINT,RsPgpFingerprint::SIZE_IN_BYTES,buf,offset,buf_size); - tDetails.fpr.serialise(buf,buf_size,offset); - - addPacketHeader(RsShortInviteFieldType::PEER_NAME,tDetails.name.size(),buf,offset,buf_size); - memcpy(&buf[offset],tDetails.name.c_str(),tDetails.name.size()); - offset += tDetails.name.size(); - - /* If it is a hidden node, always use hidden address and port as locator */ - - if(tDetails.isHiddenNode) - { - addPacketHeader(RsShortInviteFieldType::HIDDEN_LOCATOR,4 + 2 + tDetails.hiddenNodeAddress.size(),buf,offset,buf_size); - - buf[offset+0] = (uint8_t)((tDetails.hiddenType >> 24) & 0xff); - buf[offset+1] = (uint8_t)((tDetails.hiddenType >> 16) & 0xff); - buf[offset+2] = (uint8_t)((tDetails.hiddenType >> 8) & 0xff); - buf[offset+3] = (uint8_t)((tDetails.hiddenType ) & 0xff); - - buf[offset+4] = (uint8_t)((tDetails.hiddenNodePort >> 8) & 0xff); - buf[offset+5] = (uint8_t)((tDetails.hiddenNodePort ) & 0xff); - - memcpy(&buf[offset+6],tDetails.hiddenNodeAddress.c_str(),tDetails.hiddenNodeAddress.size()); - offset += 4 + 2 + tDetails.hiddenNodeAddress.size(); - } - - if( !!(invite_flags & RetroshareInviteFlags::DNS) && !tDetails.dyndns.empty() && (tDetails.extPort || tDetails.localPort)) - { - uint16_t tPort = tDetails.extPort ? tDetails.extPort : tDetails.localPort; - - addPacketHeader(RsShortInviteFieldType::DNS_LOCATOR, 2 + tDetails.dyndns.size(),buf,offset,buf_size); - - buf[offset+0] = (uint8_t)((tPort >> 8) & 0xff); - buf[offset+1] = (uint8_t)((tPort ) & 0xff); - - memcpy(&buf[offset+2],tDetails.dyndns.c_str(),tDetails.dyndns.size()); - offset += 2 + tDetails.dyndns.size(); - } - - if( !!(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) && (!tDetails.ipAddressList.empty())) - for(auto& s: tDetails.ipAddressList) - { - const std::string& tLc = s; - std::string tLocator = tLc.substr(0, tLc.find_first_of(" ")-1); - - addPacketHeader(RsShortInviteFieldType::LOCATOR, tLocator.size(),buf,offset,buf_size); - memcpy(&buf[offset],tLocator.c_str(),tLocator.size()); - - offset += tLocator.size(); - } - else if( !!(invite_flags & RetroshareInviteFlags::CURRENT_IP) ) // only add at least the local and external IPs - { -#ifdef USE_NEW_LOCATOR_SYSTEM - // This new locator system as some advantages, but here it also has major drawbacks: (1) it cannot differentiate local and external addresses, - // and (2) it's quite larger than the old system, which tends to make certificates more than 1 line long. - - sockaddr_storage tLocal; - - if(sockaddr_storage_inet_pton(tLocal, tDetails.localAddr) && sockaddr_storage_isValidNet(tLocal) && tDetails.localPort ) - { - addPacketHeader(RsShortInviteFieldType::LOCATOR, tDetails.localAddr.size(),buf,offset,buf_size); - memcpy(&buf[offset],tDetails.localAddr.c_str(),tDetails.localAddr.size()); - - offset += tDetails.localAddr.size(); - } - sockaddr_storage tExt; - - if(sockaddr_storage_inet_pton(tExt, tDetails.extAddr) && sockaddr_storage_isValidNet(tExt) && tDetails.extPort ) - { - addPacketHeader(RsShortInviteFieldType::LOCATOR, tDetails.extAddr.size(),buf,offset,buf_size); - memcpy(&buf[offset],tDetails.extAddr.c_str(),tDetails.extAddr.size()); - - offset += tDetails.extAddr.size(); - } -#else - sockaddr_storage tLocal; - if(sockaddr_storage_inet_pton(tLocal, tDetails.localAddr) && sockaddr_storage_isValidNet(tLocal) && sockaddr_storage_ipv6_to_ipv4(tLocal) && tDetails.localPort ) - { - uint32_t t4Addr = reinterpret_cast(tLocal).sin_addr.s_addr; - - addPacketHeader(RsShortInviteFieldType::LOC4_LOCATOR, 4 + 2,buf,offset,buf_size); - - buf[offset+0] = (uint8_t)((t4Addr >> 24) & 0xff); - buf[offset+1] = (uint8_t)((t4Addr >> 16) & 0xff); - buf[offset+2] = (uint8_t)((t4Addr >> 8) & 0xff); - buf[offset+3] = (uint8_t)((t4Addr ) & 0xff); - - buf[offset+4] = (uint8_t)((tDetails.localPort >> 8) & 0xff); - buf[offset+5] = (uint8_t)((tDetails.localPort ) & 0xff); - - offset += 4+2; - } - - sockaddr_storage tExt; - if(sockaddr_storage_inet_pton(tExt, tDetails.extAddr) && sockaddr_storage_isValidNet(tExt) && sockaddr_storage_ipv6_to_ipv4(tExt) && tDetails.extPort ) - { - uint32_t t4Addr = reinterpret_cast(tExt).sin_addr.s_addr; - - addPacketHeader(RsShortInviteFieldType::EXT4_LOCATOR, 4 + 2,buf,offset,buf_size); - - buf[offset+0] = (uint8_t)((t4Addr >> 24) & 0xff); - buf[offset+1] = (uint8_t)((t4Addr >> 16) & 0xff); - buf[offset+2] = (uint8_t)((t4Addr >> 8) & 0xff); - buf[offset+3] = (uint8_t)((t4Addr ) & 0xff); - - buf[offset+4] = (uint8_t)((tDetails.extPort >> 8) & 0xff); - buf[offset+5] = (uint8_t)((tDetails.extPort ) & 0xff); - - offset += 4+2; - } -#endif - - } - - uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC(buf,offset) ; - - // handle endian issues. - unsigned char mem[3] ; - mem[0] = computed_crc & 0xff ; - mem[1] = (computed_crc >> 8 ) & 0xff ; - mem[2] = (computed_crc >> 16) & 0xff ; - - addPacketHeader( RsShortInviteFieldType::CHECKSUM,3,buf,offset,buf_size); - memcpy(&buf[offset],mem,3); - offset += 3; - - Radix64::encode(buf, static_cast(offset), invite); - - if(!(invite_flags & RetroshareInviteFlags::RADIX_FORMAT)) - { - RsUrl inviteUrl(baseUrl); - inviteUrl.setQueryKV("rsInvite", invite); - invite = inviteUrl.toString(); - } - - return true; -} - -bool p3Peers::parseShortInvite(const std::string& inviteStrUrl, RsPeerDetails& details, uint32_t &err_code ) -{ - if(inviteStrUrl.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " can't parse empty invite" - << std::endl; - return false; - } - std::string rsInvite = inviteStrUrl; - - RsUrl inviteUrl(inviteStrUrl); - - if(inviteUrl.hasQueryK("rsInvite")) - rsInvite = *inviteUrl.getQueryV("rsInvite"); - - std::vector bf = Radix64::decode(rsInvite); - size_t size = bf.size(); - - unsigned char* buf = bf.data(); - size_t total_s = 0; - bool CRC_ok = false ; // not checked yet - - while(total_s < size) - { - RsShortInviteFieldType ptag = RsShortInviteFieldType(buf[0]); - buf = &buf[1]; - - unsigned char *buf2 = buf; - uint32_t s = 0; - - try { s = PGPKeyParser::read_125Size(buf); } - catch (...) - { - err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR; - return false; - } - - total_s += 1 + ( reinterpret_cast(buf) - reinterpret_cast(buf2) ); - - if(total_s > size) - { - err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR; - return false; - } - - Dbg3() << __PRETTY_FUNCTION__ << " Read ptag: " - << static_cast(ptag) - << ", size " << s << ", total_s = " << total_s - << ", expected total = " << size << std::endl; - - switch(ptag) - { - case RsShortInviteFieldType::SSL_ID: - details.id = RsPeerId::fromBufferUnsafe(buf) ; - break; - - case RsShortInviteFieldType::PEER_NAME: - details.name = std::string((char*)buf,s); - break; - - case RsShortInviteFieldType::PGP_FINGERPRINT: - details.fpr = RsPgpFingerprint::fromBufferUnsafe(buf); - details.gpg_id = PGPHandler::pgpIdFromFingerprint(details.fpr); - break; - - case RsShortInviteFieldType::LOCATOR: - { - std::string locatorStr((char*)buf,s); - details.ipAddressList.push_back(locatorStr); - } - break; - - case RsShortInviteFieldType::DNS_LOCATOR: - details.extPort = (((int)buf[0]) << 8) + buf[1]; - details.dyndns = std::string((char*)&buf[2],s-2); - break; - - case RsShortInviteFieldType::LOC4_LOCATOR: - { - uint32_t t4Addr = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3]; - sockaddr_in tLocalAddr; - tLocalAddr.sin_addr.s_addr = t4Addr; - - details.localAddr = rs_inet_ntoa(tLocalAddr.sin_addr); - details.localPort = (((uint32_t)buf[4])<<8) + (uint32_t)buf[5]; - } - break; - - case RsShortInviteFieldType::EXT4_LOCATOR: - { - uint32_t t4Addr = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3]; - sockaddr_in tExtAddr; - tExtAddr.sin_addr.s_addr = t4Addr; - - details.extAddr = rs_inet_ntoa(tExtAddr.sin_addr); - details.extPort = (((uint32_t)buf[4])<<8) + (uint32_t)buf[5]; - } - break; - - case RsShortInviteFieldType::HIDDEN_LOCATOR: - details.hiddenType = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3]; - details.hiddenNodePort = (((uint32_t)buf[4]) << 8)+ (uint32_t)buf[5]; - details.isHiddenNode = true; - details.hiddenNodeAddress = std::string((char*)&buf[6],s-6); - break; - - case RsShortInviteFieldType::CHECKSUM: - { - if(s != 3 || total_s+3 != size) // make sure the checksum is the last section - { - err_code = CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION; - return false; - } - uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC(bf.data(),size-5); - uint32_t certificate_crc = static_cast( buf[0] + (buf[1] << 8) + (buf[2] << 16) ); - - if(computed_crc != certificate_crc) - { - err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR; - return false; - } - CRC_ok = true; - break; - } - - } - - buf = &buf[s]; - total_s += s; - } - - // now check if the PGP key is available. If so, add it in the PeerDetails: - - RsPeerDetails pgp_det ; - if(getGPGDetails(PGPHandler::pgpIdFromFingerprint(details.fpr),pgp_det) && pgp_det.fpr == details.fpr) - { - details.issuer = pgp_det.issuer; - details.gpg_id = pgp_det.gpg_id; - details.gpgSigners = pgp_det.gpgSigners; - details.trustLvl = pgp_det.trustLvl; - details.validLvl = pgp_det.validLvl; - details.ownsign = pgp_det.ownsign; - details.hasSignedMe = pgp_det.hasSignedMe; - details.accept_connection = pgp_det.accept_connection; - } - else - details.skip_pgp_signature_validation = true; - - if(!CRC_ok) - { - err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR; - return false; - } - if(details.gpg_id.isNull()) - { - err_code = CERTIFICATE_PARSING_ERROR_MISSING_PGP_FINGERPRINT; - return false; - } - if(details.id.isNull()) - { - err_code = CERTIFICATE_PARSING_ERROR_MISSING_LOCATION_ID; - return false; - } - err_code = CERTIFICATE_PARSING_ERROR_NO_ERROR; - return true; -} - -bool p3Peers::acceptInvite( const std::string& invite, - ServicePermissionFlags flags ) -{ - if(invite.empty()) return false; - - const std::string* radixPtr(&invite); - - RsUrl url(invite); - std::map query(url.query()); - - if(query.find("radix") != query.end()) - radixPtr = &query["radix"]; - - const std::string& radix(*radixPtr); - if(radix.empty()) return false; - - RsPgpId pgpId; - RsPeerId sslId; - std::string errorString; - - if(!loadCertificateFromString(radix, sslId, pgpId, errorString)) - return false; - - RsPeerDetails peerDetails; - uint32_t errorCode; - - if(!loadDetailsFromStringCert(radix, peerDetails, errorCode)) - return false; - - if(peerDetails.gpg_id.isNull()) - return false; - - addFriend(peerDetails.id, peerDetails.gpg_id, flags); - - if (!peerDetails.location.empty()) - setLocation(peerDetails.id, peerDetails.location); - - // Update new address even the peer already existed. - if (peerDetails.isHiddenNode) - { - setHiddenNode( peerDetails.id, - peerDetails.hiddenNodeAddress, - peerDetails.hiddenNodePort ); - } - else - { - //let's check if there is ip adresses in the certificate. - if (!peerDetails.extAddr.empty() && peerDetails.extPort) - setExtAddress( peerDetails.id, - peerDetails.extAddr, - peerDetails.extPort ); - if (!peerDetails.localAddr.empty() && peerDetails.localPort) - setLocalAddress( peerDetails.id, - peerDetails.localAddr, - peerDetails.localPort ); - if (!peerDetails.dyndns.empty()) - setDynDNS(peerDetails.id, peerDetails.dyndns); - for(auto&& ipr : peerDetails.ipAddressList) - addPeerLocator( - peerDetails.id, - RsUrl(ipr.substr(0, ipr.find(' '))) ); - } - - return true; -} - -std::string p3Peers::GetRetroshareInvite( const RsPeerId& sslId, RetroshareInviteFlags invite_flags) -{ -#ifdef P3PEERS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - const RsPeerId& ssl_id(sslId.isNull() ? getOwnId() : sslId); - - //add the sslid, location, ip local and external address after the signature - RsPeerDetails detail; - std::string invite; - - if (getPeerDetails(ssl_id, detail)) - { - if(!(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) || detail.isHiddenNode) - detail.ipAddressList.clear(); - - unsigned char *mem_block = nullptr; - size_t mem_block_size = 0; - - if(!AuthGPG::getAuthGPG()->exportPublicKey( RsPgpId(detail.gpg_id), mem_block, mem_block_size, false, !!(invite_flags & RetroshareInviteFlags::PGP_SIGNATURES) )) - { - std::cerr << "Cannot output certificate for id \"" << detail.gpg_id - << "\". Sorry." << std::endl; - return ""; - } - - RsCertificate cert(detail, mem_block, mem_block_size); - free(mem_block); - - return cert.toStdString(); - } - -#ifdef P3PEERS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " returns : \n" << invite << std::endl; -#endif - return invite; -} - -//=========================================================================== - -bool p3Peers::loadCertificateFromString( - const std::string& cert, RsPeerId& ssl_id, - RsPgpId& gpg_id, std::string& error_string ) -{ - uint32_t errNum = 0; - auto crt = RsCertificate::fromString(cert, errNum); - - if(!crt) - { - error_string = "RsCertificate failed with errno: " - + std::to_string(errNum) + " parsing: " + cert; - return false; - } - - RsPgpId gpgid; - bool res = AuthGPG::getAuthGPG()->LoadCertificateFromString( crt->armouredPGPKey(), gpgid, error_string ); - - gpg_id = gpgid; - ssl_id = crt->sslid(); - - // now get all friends who declare this key ID to be the one needed to check connections, and clear their "skip_pgp_signature_validation" flag - - if(res) - { - mPeerMgr->notifyPgpKeyReceived(gpgid); - FriendsChanged(ssl_id,true); - } - - return res; -} -bool p3Peers::loadPgpKeyFromBinaryData( const unsigned char *bin_key_data,uint32_t bin_key_len, RsPgpId& gpg_id, std::string& error_string ) -{ - bool res = AuthGPG::getAuthGPG()->LoadPGPKeyFromBinaryData( bin_key_data,bin_key_len, gpg_id, error_string ); - - if(res) - mPeerMgr->notifyPgpKeyReceived(gpg_id); - - return res; -} - -bool p3Peers::loadDetailsFromStringCert( const std::string &certstr, - RsPeerDetails &pd, - uint32_t& error_code ) -{ - Dbg3() << __PRETTY_FUNCTION__ << std::endl; - - auto certPtr = RsCertificate::fromString(certstr, error_code); - if(!certPtr) return false; - - RsCertificate& cert = *certPtr; - - if(!AuthGPG::getAuthGPG()->getGPGDetailsFromBinaryBlock( - cert.pgp_key(), cert.pgp_key_size(), - pd.gpg_id, pd.name, pd.gpgSigners )) - return false; - - Dbg4() << __PRETTY_FUNCTION__ << " Parsing cert for sslid, location, ext " - << " and local address details. : " << certstr << std::endl; - - pd.id = cert.sslid(); - pd.location = cert.location_name_string(); - - pd.isOnlyGPGdetail = pd.id.isNull(); - pd.service_perm_flags = RS_NODE_PERM_DEFAULT; - - if (!cert.hidden_node_string().empty()) - { - pd.isHiddenNode = true; - - std::string domain; - uint16_t port; - if (splitAddressString(cert.hidden_node_string(), domain, port)) - { - pd.hiddenNodeAddress = domain; - pd.hiddenNodePort = port; - pd.hiddenType = mPeerMgr->hiddenDomainToHiddenType(domain); - } - } - else - { - pd.isHiddenNode = false; - pd.localAddr = cert.loc_ip_string(); - pd.localPort = cert.loc_port_us(); - pd.extAddr = cert.ext_ip_string(); - pd.extPort = cert.ext_port_us(); - pd.dyndns = cert.dns_string(); - for(const RsUrl& locator : cert.locators()) - pd.ipAddressList.push_back(locator.toString()); - } - - return true; -} - -bool p3Peers::cleanCertificate(const std::string &certstr, std::string &cleanCert,bool& is_short_format,uint32_t& error_code) -{ - RsCertificate::Format format ; - - bool res = RsCertificate::cleanCertificate(certstr,cleanCert,format,error_code,true) ; - - if(format == RsCertificate::RS_CERTIFICATE_RADIX) - is_short_format = false; - else if(format == RsCertificate::RS_CERTIFICATE_SHORT_RADIX) - is_short_format = true; - else - return false ; - - return res; -} - -std::string p3Peers::saveCertificateToString(const RsPeerId &id) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::SaveCertificateToString() " << id; - std::cerr << std::endl; -#endif - if (id == AuthSSL::getAuthSSL()->OwnId()) { - return AuthSSL::getAuthSSL()->SaveOwnCertificateToString(); - } else { - return ""; - } -} - -bool p3Peers::signGPGCertificate(const RsPgpId &id, const std::string &gpg_passphrase) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::SignCertificate() " << id; - std::cerr << std::endl; -#endif - rsNotify->cachePgpPassphrase(gpg_passphrase); - rsNotify->setDisableAskPassword(true); - - bool res = AuthGPG::getAuthGPG()->SignCertificateLevel0(id); - - rsNotify->clearPgpPassphrase(); - rsNotify->setDisableAskPassword(false); - - return res; -} - -bool p3Peers::trustGPGCertificate(const RsPgpId &id, uint32_t trustlvl) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::TrustCertificate() " << id; - std::cerr << std::endl; -#endif - return AuthGPG::getAuthGPG()->TrustCertificate(id, trustlvl); -} - - /* Group Stuff */ -bool p3Peers::addGroup(RsGroupInfo &groupInfo) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addGroup()" << std::endl; -#endif - - bool res = mPeerMgr->addGroup(groupInfo); - rsFiles->updateSinceGroupPermissionsChanged() ; - return res ; -} - -bool p3Peers::editGroup(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::editGroup()" << std::endl; -#endif - - bool res = mPeerMgr->editGroup(groupId, groupInfo); - rsFiles->updateSinceGroupPermissionsChanged() ; - - return res ; -} - -bool p3Peers::removeGroup(const RsNodeGroupId &groupId) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::removeGroup()" << std::endl; -#endif - - bool res = mPeerMgr->removeGroup(groupId); - rsFiles->updateSinceGroupPermissionsChanged() ; - return res ; -} - -bool p3Peers::getGroupInfoByName(const std::string& groupName, RsGroupInfo &groupInfo) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getGroupInfo()" << std::endl; -#endif - - return mPeerMgr->getGroupInfoByName(groupName, groupInfo); -} -bool p3Peers::getGroupInfo(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getGroupInfo()" << std::endl; -#endif - - return mPeerMgr->getGroupInfo(groupId, groupInfo); -} - -bool p3Peers::getGroupInfoList(std::list &groupInfoList) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getGroupInfoList()" << std::endl; -#endif - - return mPeerMgr->getGroupInfoList(groupInfoList); -} - -bool p3Peers::assignPeerToGroup(const RsNodeGroupId &groupId, const RsPgpId& peerId, bool assign) -{ - std::list peerIds; - peerIds.push_back(peerId); - - return assignPeersToGroup(groupId, peerIds, assign); -} - -bool p3Peers::assignPeersToGroup(const RsNodeGroupId &groupId, const std::list &peerIds, bool assign) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::assignPeersToGroup()" << std::endl; -#endif - - bool res = mPeerMgr->assignPeersToGroup(groupId, peerIds, assign); - rsFiles->updateSinceGroupPermissionsChanged() ; - - return res ; -} - -FileSearchFlags p3Peers::computePeerPermissionFlags(const RsPeerId& peer_ssl_id, - FileStorageFlags share_flags, - const std::list& directory_parent_groups) -{ - // We should be able to do that in O(1), using groups based on packs of bits. - // - // But for now, because the implementation of groups is not totally decided yet, we revert to this - // very simple algorithm. - // - - bool found = directory_parent_groups.empty() ; // by default, empty list means browsable by everyone. - RsPgpId pgp_id = getGPGId(peer_ssl_id) ; - - for(std::list::const_iterator it(directory_parent_groups.begin());it!=directory_parent_groups.end() && !found;++it) - { - RsGroupInfo info ; - if(!getGroupInfo(*it,info)) - { - std::cerr << "(EE) p3Peers::computePeerPermissionFlags: no group named " << *it << ": cannot get info." << std::endl; - continue ; - } - - found = found || (info.peerIds.find(pgp_id) != info.peerIds.end()) ; - - //for(std::set::const_iterator it2(info.peerIds.begin());it2!=info.peerIds.end() && !found;++it2) - // if(*it2 == pgp_id) - // found = true ; - } - - bool network_wide = (share_flags & DIR_FLAGS_ANONYMOUS_DOWNLOAD) ;//|| ( (share_flags & DIR_FLAGS_NETWORK_WIDE_GROUPS) && found) ; - bool browsable = (share_flags & DIR_FLAGS_BROWSABLE) && found ; - bool searchable = (share_flags & DIR_FLAGS_ANONYMOUS_SEARCH) ; - - FileSearchFlags final_flags ; - - if(network_wide) final_flags |= RS_FILE_HINTS_NETWORK_WIDE ; - if(browsable ) final_flags |= RS_FILE_HINTS_BROWSABLE ; - if(searchable ) final_flags |= RS_FILE_HINTS_SEARCHABLE ; - - return final_flags ; -} - -RsPeerDetails::RsPeerDetails() - :isOnlyGPGdetail(false), - name(""),email(""),location(""), - org(""),authcode(""), - trustLvl(0), validLvl(0),skip_pgp_signature_validation(false),ownsign(false), - hasSignedMe(false),accept_connection(false), - state(0),actAsServer(false), - connectPort(0), - isHiddenNode(false), - hiddenNodePort(0), - hiddenType(RS_HIDDEN_TYPE_NONE), - localAddr(""),localPort(0),extAddr(""),extPort(0),netMode(0),vs_disc(0), vs_dht(0), - lastConnect(0),lastUsed(0),connectState(0),connectStateString(""), - connectPeriod(0), - foundDHT(false), wasDeniedConnection(false), deniedTS(0), - linkType ( RS_NET_CONN_TRANS_TCP_UNKNOWN) {} - -RsGroupInfo::RsGroupInfo() : flag(0) {} - -ServicePermissionFlags p3Peers::servicePermissionFlags(const RsPeerId& ssl_id) -{ - return mPeerMgr->servicePermissionFlags(ssl_id) ; -} -ServicePermissionFlags p3Peers::servicePermissionFlags(const RsPgpId& gpg_id) -{ - return mPeerMgr->servicePermissionFlags(gpg_id) ; -} -void p3Peers::setServicePermissionFlags(const RsPgpId& gpg_id,const ServicePermissionFlags& flags) -{ - mPeerMgr->setServicePermissionFlags(gpg_id,flags) ; -} - -RsPeerStateChangedEvent::RsPeerStateChangedEvent(RsPeerId sslId) : - RsEvent(RsEventType::PEER_STATE_CHANGED), mSslId(sslId) {} - -RsPeers::~RsPeers() = default; -RsAuthSslConnectionAutenticationEvent::~RsAuthSslConnectionAutenticationEvent() = default; -RsConnectionEvent::~RsConnectionEvent() = default; diff --git a/libretroshare/src/rsserver/p3peers.h b/libretroshare/src/rsserver/p3peers.h deleted file mode 100644 index 56f1f73e6..000000000 --- a/libretroshare/src/rsserver/p3peers.h +++ /dev/null @@ -1,201 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3peers.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_P3_PEER_INTERFACE_H -#define RETROSHARE_P3_PEER_INTERFACE_H -/* get OS-specific definitions for: - * struct sockaddr_storage - */ -#ifndef WINDOWS_SYS - #include -#else - #include -#endif - -#include "retroshare/rspeers.h" -#include "util/rsurl.h" -#include "util/rsdeprecate.h" -#include "util/rsdebug.h" - -class p3LinkMgr; -class p3PeerMgr; -class p3NetMgr; - - -class p3Peers: public RsPeers -{ -public: - - p3Peers(p3LinkMgr *lm, p3PeerMgr *pm, p3NetMgr *nm); - virtual ~p3Peers() {} - - /* Updates ... */ - virtual bool FriendsChanged(const RsPeerId &pid, bool add); - virtual bool OthersChanged(); - - /* Peer Details (Net & Auth) */ - virtual const RsPeerId& getOwnId() override; - - virtual bool haveSecretKey(const RsPgpId& gpg_id) override; - - virtual bool getOnlineList(std::list &ids) override; - virtual bool getFriendList(std::list &ids) override; - virtual bool getPeersCount( - uint32_t& peersCount, uint32_t& onlinePeersCount, - bool countLocations ) override; - - RS_DEPRECATED - virtual bool getPeerCount (unsigned int *friendCount, unsigned int *onlineCount, bool ssl) override; - - virtual bool isOnline(const RsPeerId &id) override; - virtual bool isFriend(const RsPeerId &id) override; - virtual bool isPgpFriend(const RsPgpId& pgpId) override; - - /// @see RsPeers - bool isSslOnlyFriend(const RsPeerId& sslId) override; - - RS_DEPRECATED_FOR(isPgpFriend) - virtual bool isGPGAccepted(const RsPgpId &gpg_id_is_friend) override; - - virtual std::string getGPGName(const RsPgpId &gpg_id) override; - virtual std::string getPeerName(const RsPeerId& ssl_or_gpg_id) override; - virtual bool getPeerDetails(const RsPeerId& ssl_or_gpg_id, RsPeerDetails &d) override; - - /* Using PGP Ids */ - virtual const RsPgpId& getGPGOwnId() override; - virtual RsPgpId getGPGId(const RsPeerId &ssl_id) override; - virtual bool isKeySupported(const RsPgpId& ids) override; - - /// @see RsPeers - bool getPgpFriendList(std::vector& pgpIds) override; - - RS_DEPRECATED_FOR(getPgpFriendList) - virtual bool getGPGAcceptedList(std::list &ids) override; - virtual bool getGPGSignedList(std::list &ids) override; - virtual bool getGPGValidList(std::list &ids) override; - virtual bool getGPGAllList(std::list &ids) override; - virtual bool getGPGDetails(const RsPgpId &id, RsPeerDetails &d) override; - virtual bool getAssociatedSSLIds(const RsPgpId& gpg_id, std::list &ids) override; - virtual bool gpgSignData(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, std::string reason = "") override; - - virtual RsPgpId pgpIdFromFingerprint(const RsPgpFingerprint& fpr) override; - - /* Add/Remove Friends */ - virtual bool addFriend(const RsPeerId &ssl_id, const RsPgpId &gpg_id,ServicePermissionFlags flags = RS_NODE_PERM_DEFAULT) override; - - /// @see RsPeers - bool addSslOnlyFriend( - const RsPeerId& sslId, - const RsPgpId& pgp_id, - const RsPeerDetails& details = RsPeerDetails() ) override; - - virtual bool removeFriend(const RsPgpId& gpgid) override; - virtual bool removeFriendLocation(const RsPeerId& sslId) override; - - /* keyring management */ - virtual bool removeKeysFromPGPKeyring(const std::set &pgp_ids,std::string& backup_file,uint32_t& error_code) override; - - /* Network Stuff */ - virtual bool connectAttempt(const RsPeerId &id) override; - virtual bool setLocation(const RsPeerId &ssl_id, const std::string &location) override;//location is shown in the gui to differentiate ssl certs - virtual bool setHiddenNode(const RsPeerId &id, const std::string &hidden_node_address) override; - virtual bool setHiddenNode(const RsPeerId &id, const std::string &address, uint16_t port) override; - virtual bool isHiddenNode(const RsPeerId &id) override; - - virtual bool addPeerLocator(const RsPeerId &ssl_id, const RsUrl& locator) override; - virtual bool setLocalAddress(const RsPeerId &id, const std::string &addr, uint16_t port) override; - virtual bool setExtAddress(const RsPeerId &id, const std::string &addr, uint16_t port) override; - virtual bool setDynDNS(const RsPeerId &id, const std::string &dyndns) override; - virtual bool setNetworkMode(const RsPeerId &id, uint32_t netMode) override; - virtual bool setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht) override; - - virtual bool getProxyServer(const uint32_t type, std::string &addr, uint16_t &port,uint32_t& status) override; - virtual bool setProxyServer(const uint32_t type, const std::string &addr, const uint16_t port) override; - virtual bool isProxyAddress(const uint32_t type, const sockaddr_storage &addr); - - virtual void getIPServersList(std::list& ip_servers) override; - virtual void allowServerIPDetermination(bool) override; - virtual bool getAllowServerIPDetermination() override; - virtual bool resetOwnExternalAddressList() override; - - /* Auth Stuff */ - // Get the invitation (GPG cert + local/ext address + SSL id for the given peer) - virtual std::string GetRetroshareInvite(const RsPeerId& ssl_id = RsPeerId(), RetroshareInviteFlags invite_flags = RetroshareInviteFlags::DNS | RetroshareInviteFlags::CURRENT_IP ) override; - - RS_DEPRECATED /// @see RsPeers - std::string getPGPKey(const RsPgpId& pgp_id,bool include_signatures) override; - - virtual bool GetPGPBase64StringAndCheckSum(const RsPgpId& gpg_id,std::string& gpg_base64_string,std::string& gpg_base64_checksum); - - /// @see RsPeers - bool getShortInvite(std::string& invite, const RsPeerId& sslId = RsPeerId(), - RetroshareInviteFlags invite_flags = RetroshareInviteFlags::CURRENT_IP | RetroshareInviteFlags::DNS, - const std::string& baseUrl = "https://retroshare.me/" ) override; - - /// @see RsPeers - bool parseShortInvite(const std::string& invite, RsPeerDetails& details, uint32_t &err_code ) override; - - /// @see RsPeers::acceptInvite - virtual bool acceptInvite( - const std::string& invite, - ServicePermissionFlags flags = RS_NODE_PERM_DEFAULT ) override; - - virtual bool loadCertificateFromString(const std::string& cert, RsPeerId& ssl_id,RsPgpId& pgp_id, std::string& error_string) override; - virtual bool loadPgpKeyFromBinaryData( const unsigned char *bin_key_data,uint32_t bin_key_len, RsPgpId& gpg_id, std::string& error_string ) override; - virtual bool loadDetailsFromStringCert(const std::string &cert, RsPeerDetails &pd, uint32_t& error_code) override; - - virtual bool cleanCertificate(const std::string &certstr, std::string &cleanCert, bool &is_short_format, uint32_t& error_code) override; - virtual std::string saveCertificateToString(const RsPeerId &id) override; - - virtual bool signGPGCertificate(const RsPgpId &id,const std::string& gpg_passphrase) override; - virtual bool trustGPGCertificate(const RsPgpId &id, uint32_t trustlvl) override; - - /* Group Stuff */ - virtual bool addGroup(RsGroupInfo &groupInfo) override; - virtual bool editGroup(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) override; - virtual bool removeGroup(const RsNodeGroupId &groupId) override; - virtual bool getGroupInfo(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) override; - virtual bool getGroupInfoByName(const std::string& groupName, RsGroupInfo& groupInfo) override; - virtual bool getGroupInfoList(std::list &groupInfoList) override; - virtual bool assignPeerToGroup(const RsNodeGroupId &groupId, const RsPgpId &peerId, bool assign) override; - virtual bool assignPeersToGroup(const RsNodeGroupId &groupId, const std::list& peerIds, bool assign) override; - - virtual FileSearchFlags computePeerPermissionFlags(const RsPeerId& peer_id, FileStorageFlags share_flags, const std::list &parent_groups) override; - - // service permission stuff - - virtual ServicePermissionFlags servicePermissionFlags(const RsPgpId& gpg_id) override; - virtual ServicePermissionFlags servicePermissionFlags(const RsPeerId & ssl_id) override; - virtual void setServicePermissionFlags(const RsPgpId& gpg_id,const ServicePermissionFlags& flags) override; - - virtual bool setPeerMaximumRates(const RsPgpId& pid,uint32_t maxUploadRate,uint32_t maxDownloadRate) override; - virtual bool getPeerMaximumRates(const RsPgpId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) override; - virtual bool getPeerMaximumRates(const RsPeerId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) override; -private: - - p3LinkMgr *mLinkMgr; - p3PeerMgr *mPeerMgr; - p3NetMgr *mNetMgr; - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; - -#endif diff --git a/libretroshare/src/rsserver/p3serverconfig.cc b/libretroshare/src/rsserver/p3serverconfig.cc deleted file mode 100644 index 6d3343dc7..000000000 --- a/libretroshare/src/rsserver/p3serverconfig.cc +++ /dev/null @@ -1,566 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3serverconfig.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include "rsserver/p3serverconfig.h" -#include "services/p3bwctrl.h" - -#include "pqi/authgpg.h" -#include "pqi/authssl.h" - -RsServerConfig *rsConfig = NULL; - -static const std::string pqih_ftr("PQIH_FTR"); - -#define DEFAULT_DOWNLOAD_KB_RATE (10000.0) -#define DEFAULT_UPLOAD_KB_RATE (10000.0) - -#define MIN_MINIMAL_RATE (5.0) - - -p3ServerConfig::p3ServerConfig(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr, p3NetMgr *netMgr, pqihandler *pqih, p3GeneralConfig *genCfg) -:configMtx("p3ServerConfig") -{ - mPeerMgr = peerMgr; - mLinkMgr = linkMgr; - mNetMgr = netMgr; - mPqiHandler = pqih; - - mGeneralConfig = genCfg; - - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - - mUserLevel = RsConfigUserLvl::NEW; /* START LEVEL */ - mRateDownload = DEFAULT_DOWNLOAD_KB_RATE; - mRateUpload = DEFAULT_UPLOAD_KB_RATE; - - mOpMode = RsOpMode::FULL; - - rsConfig = this; -} - - -p3ServerConfig::~p3ServerConfig() -{ - return; -} - - -void p3ServerConfig::load_config() -{ - /* get the real bandwidth setting from GeneralConfig */ - std::string rates = mGeneralConfig -> getSetting(pqih_ftr); - - float mri, mro; - if (2 == sscanf(rates.c_str(), "%f %f", &mri, &mro)) - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - - mRateDownload = mri; - mRateUpload = mro; - } - else - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - - mRateDownload = DEFAULT_DOWNLOAD_KB_RATE; - mRateUpload = DEFAULT_UPLOAD_KB_RATE; - } - - /* enable operating mode */ - RsOpMode opMode = getOperatingMode(); - switchToOperatingMode(opMode); -} - - -#define RS_CONFIG_ADVANCED_STRING "AdvMode" - -bool p3ServerConfig::findConfigurationOption(uint32_t key, std::string &keystr) -{ - bool found = false; - switch(key) - { - case RS_CONFIG_ADVANCED: - keystr = RS_CONFIG_ADVANCED_STRING; - found = true; - break; - } - return found; -} - - -bool p3ServerConfig::getConfigurationOption(uint32_t key, std::string &opt) -{ - std::string strkey; - if (!findConfigurationOption(key, strkey)) - { - std::cerr << "p3ServerConfig::getConfigurationOption() OPTION NOT VALID: " << key; - std::cerr << std::endl; - return false; - } - - opt = mGeneralConfig->getSetting(strkey); - return true; -} - - -bool p3ServerConfig::setConfigurationOption(uint32_t key, const std::string &opt) -{ - std::string strkey; - if (!findConfigurationOption(key, strkey)) - { - std::cerr << "p3ServerConfig::setConfigurationOption() OPTION NOT VALID: " << key; - std::cerr << std::endl; - return false; - } - - mGeneralConfig->setSetting(strkey, opt); - return true; -} - - /* From RsIface::RsConfig */ -int p3ServerConfig::getConfigNetStatus(RsConfigNetStatus &status) -{ - status.ownId = AuthSSL::getAuthSSL()->OwnId(); - status.ownName = AuthGPG::getAuthGPG()->getGPGOwnName(); - - // Details from PeerMgr. - peerState pstate; - mPeerMgr->getOwnNetStatus(pstate); - - status.localAddr = sockaddr_storage_iptostring(pstate.localaddr); - status.localPort = sockaddr_storage_port(pstate.localaddr); - - status.extAddr = sockaddr_storage_iptostring(pstate.serveraddr); - status.extPort = sockaddr_storage_port(pstate.serveraddr); - status.extDynDns = pstate.dyndns; - - status.firewalled = true; - status.forwardPort = true; - - /* update network configuration */ - pqiNetStatus nstatus; - mNetMgr->getNetStatus(nstatus); - - status.netUpnpOk = nstatus.mUpnpOk; - status.netStunOk = false; - status.netExtAddressOk = nstatus.mExtAddrOk; - - status.netDhtOk = nstatus.mDhtOk; - status.netDhtNetSize = nstatus.mDhtNetworkSize; - status.netDhtRsNetSize = nstatus.mDhtRsNetworkSize; - - /* update DHT/UPnP status */ - status.uPnPState = mNetMgr->getUPnPState(); - status.uPnPActive = mNetMgr->getUPnPEnabled(); - status.DHTActive = mNetMgr->getDHTEnabled(); - - return 1; -} - -int p3ServerConfig::getConfigStartup(RsConfigStartup &/*params*/) -{ - //status.promptAtBoot = true; /* popup the password prompt */ - return 0; -} - -/***** for RsConfig -> p3BandwidthControl ****/ - -int p3ServerConfig::getTrafficInfo(std::list& out_lst,std::list& in_lst) -{ - - if (rsBandwidthControl) - return rsBandwidthControl->ExtractTrafficInfo(out_lst,in_lst); - else - return 0 ; -} - -int p3ServerConfig::getTotalBandwidthRates(RsConfigDataRates &rates) -{ - if (rsBandwidthControl) - { - return rsBandwidthControl->getTotalBandwidthRates(rates); - } - return 0; -} - -int p3ServerConfig::getAllBandwidthRates(std::map &ratemap) -{ - if (rsBandwidthControl) - { - return rsBandwidthControl->getAllBandwidthRates(ratemap); - } - return 0; -} - - - /* From RsInit */ - -std::string p3ServerConfig::RsConfigDirectory() -{ - return std::string(); -} - -std::string p3ServerConfig::RsConfigKeysDirectory() -{ - return std::string(); -} - - -std::string p3ServerConfig::RsProfileConfigDirectory() -{ - return std::string(); -} - -bool p3ServerConfig::getStartMinimised() -{ - return 0; -} - -std::string p3ServerConfig::getRetroShareLink() -{ - return std::string(); -} - - -bool p3ServerConfig::getAutoLogin() -{ - return 0; -} - -void p3ServerConfig::setAutoLogin(bool /*autoLogin*/) -{ - return; -} - -bool p3ServerConfig::RsClearAutoLogin() -{ - return 0; -} - - -std::string p3ServerConfig::getRetroshareDataDirectory() -{ - return std::string(); -} - - /* New Stuff */ - -RsConfigUserLvl p3ServerConfig::getUserLevel() -{ - RsConfigUserLvl userLevel = RsConfigUserLvl::NEW; - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - userLevel = mUserLevel; - } - - switch(userLevel) - { - case RsConfigUserLvl::OVERRIDE: - break; - -#define MIN_BASIC_FRIENDS 2 - - // FALL THROUGH EVERYTHING. - default: - case RsConfigUserLvl::NEW: - { - - if (mPeerMgr->getFriendCount(true, false) > MIN_BASIC_FRIENDS) - { - userLevel = RsConfigUserLvl::BASIC; - } - } - /* fallthrough */ - case RsConfigUserLvl::BASIC: - { - /* check that we have some lastConnect > 0 */ - if (mPeerMgr->haveOnceConnected()) - { - userLevel = RsConfigUserLvl::CASUAL; - } - } - /* fallthrough */ - case RsConfigUserLvl::CASUAL: - case RsConfigUserLvl::POWER: - - { - /* check that the firewall is open */ - - RsNetworkMode netMode = mNetMgr->getNetworkMode(); - RsNatHoleMode firewallMode = mNetMgr->getNatHoleMode(); - - if ((RsNetworkMode::EXTERNALIP == netMode) || - ((RsNetworkMode::BEHINDNAT == netMode) && - (RsNatHoleMode::UPNP == firewallMode || - (RsNatHoleMode::NATPMP == firewallMode) || - (RsNatHoleMode::FORWARDED == firewallMode)))) - { - userLevel = RsConfigUserLvl::POWER; - } - } - break; /* for all */ - } - - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - mUserLevel = userLevel; - } - - return userLevel; -} - - -RsNetState p3ServerConfig::getNetState() -{ - return mNetMgr->getNetStateMode(); -} - -RsNetworkMode p3ServerConfig::getNetworkMode() -{ - return mNetMgr->getNetworkMode(); -} - -RsNatTypeMode p3ServerConfig::getNatTypeMode() -{ - return mNetMgr->getNatTypeMode(); -} - -RsNatHoleMode p3ServerConfig::getNatHoleMode() -{ - return mNetMgr->getNatHoleMode(); -} - -RsConnectModes p3ServerConfig::getConnectModes() -{ - return mNetMgr->getConnectModes(); -} - - /* Operating Mode */ -#define RS_CONFIG_OPERATING_STRING "OperatingMode" - -RsOpMode p3ServerConfig::getOperatingMode() -{ -#ifdef SAVE_OPERATING_MODE - std::string modestr = mGeneralConfig->getSetting(RS_CONFIG_OPERATING_STRING); - uint32_t mode = RsOpMode::FULL; - - if (modestr == "FULL") - { - mode = RsOpMode::FULL; - } - else if (modestr == "NOTURTLE") - { - mode = RsOpMode::NOTURTLE; - } - else if (modestr == "GAMING") - { - mode = RsOpMode::GAMING; - } - else if (modestr == "MINIMAL") - { - mode = RsOpMode::MINIMAL; - } - return mode; -#else - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - return mOpMode; -#endif -} - - -bool p3ServerConfig::setOperatingMode(RsOpMode opMode) -{ -#ifdef SAVE_OPERATING_MODE - std::string modestr = "FULL"; - switch(opMode) - { - case RsOpMode::FULL: - modestr = "FULL"; - break; - case RsOpMode::NOTURTLE: - modestr = "NOTURTLE"; - - break; - case RsOpMode::GAMING: - modestr = "GAMING"; - - break; - case RsOpMode::MINIMAL: - modestr = "MINIMAL"; - break; - } - mGeneralConfig->setSetting(RS_CONFIG_OPERATING_STRING, modestr); -#else - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - mOpMode = opMode; - } -#endif - return switchToOperatingMode(opMode); -} - -bool p3ServerConfig::setOperatingMode(const std::string &opModeStr) -{ - RsOpMode opMode = RsOpMode::FULL; - std::string upper; - stringToUpperCase(opModeStr, upper); - - if (upper == "NOTURTLE") - { - opMode = RsOpMode::NOTURTLE; - } - else if (upper == "GAMING") - { - opMode = RsOpMode::GAMING; - } - else if (upper == "MINIMAL") - { - opMode = RsOpMode::MINIMAL; - } - else // "FULL" by default - { - opMode = RsOpMode::FULL; - } - - return setOperatingMode(opMode); -} - -bool p3ServerConfig::switchToOperatingMode(RsOpMode opMode) -{ - float dl_rate = 0; - float ul_rate = 0; - bool turtle_enabled = true; - - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - dl_rate = mRateDownload; - ul_rate = mRateUpload; - } - - std::cerr << "p3ServerConfig::switchToOperatingMode(" << static_cast::type>(opMode) << ")"; - std::cerr << std::endl; - - switch (opMode) - { - default: - case RsOpMode::FULL: - /* switch on all transfers */ - /* 100% bandwidth */ - /* switch on popups, enable hashing */ - //setMaxRate(true, mri); // In / Download - //setMaxRate(false, mro); // Out / Upload. - turtle_enabled = true; - break; - case RsOpMode::NOTURTLE: - /* switch on all transfers - except turtle, enable hashing */ - /* 100% bandwidth */ - /* switch on popups, enable hashing */ - turtle_enabled = false; - - break; - case RsOpMode::GAMING: - /* switch on all transfers */ - /* reduce bandwidth to 25% */ - /* switch off popups, enable hashing */ - turtle_enabled = true; - - dl_rate *= 0.25; - ul_rate *= 0.25; - break; - case RsOpMode::MINIMAL: - /* switch off all transfers */ - /* reduce bandwidth to 10%, but make sure there is enough for VoIP */ - /* switch on popups, enable hashing */ - - turtle_enabled = false; - - dl_rate *= 0.10; - ul_rate *= 0.10; - if (dl_rate < MIN_MINIMAL_RATE) - { - dl_rate = MIN_MINIMAL_RATE; - } - if (ul_rate < MIN_MINIMAL_RATE) - { - ul_rate = MIN_MINIMAL_RATE; - } - - break; - } - - if (mPqiHandler) - { - mPqiHandler -> setMaxRate(true, dl_rate); - mPqiHandler -> setMaxRate(false, ul_rate); - - std::cerr << "p3ServerConfig::switchToOperatingMode() D/L: " << dl_rate << " U/L: " << ul_rate; - std::cerr << std::endl; - - } - - std::cerr << "p3ServerConfig::switchToOperatingMode() Turtle Mode: " << turtle_enabled; - std::cerr << std::endl; - - rsTurtle->setSessionEnabled(turtle_enabled); - return true; -} - -/* handle data rates. - * Mutex must be handled at the lower levels: TODO */ - -int p3ServerConfig::SetMaxDataRates( int downKb, int upKb ) /* in kbrates */ -{ - char line[512]; - - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - mRateDownload = downKb; - mRateUpload = upKb; - sprintf(line, "%f %f", mRateDownload, mRateUpload); - } - mGeneralConfig->setSetting(pqih_ftr, std::string(line)); - - load_config(); // load and setup everything. - return 1; -} - - -int p3ServerConfig::GetMaxDataRates( int &inKb, int &outKb ) /* in kbrates */ -{ - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - - inKb = mRateDownload; - outKb = mRateUpload; - return 1; -} - -int p3ServerConfig::GetCurrentDataRates( float &inKb, float &outKb ) -{ - mPqiHandler->getCurrentRates(inKb, outKb); - return 1; -} - -int p3ServerConfig::GetTrafficSum(uint64_t &inb, uint64_t &outb ) -{ - mPqiHandler->GetTraffic(inb, outb); - return 1; -} diff --git a/libretroshare/src/rsserver/p3serverconfig.h b/libretroshare/src/rsserver/p3serverconfig.h deleted file mode 100644 index c197aa1b0..000000000 --- a/libretroshare/src/rsserver/p3serverconfig.h +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3serverconfig.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef LIBRETROSHARE_CONFIG_IMPLEMENTATION_H -#define LIBRETROSHARE_CONFIG_IMPLEMENTATION_H - -#include "retroshare/rsconfig.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/pqihandler.h" - - -#define RS_CONFIG_ADVANCED_STRING "AdvMode" - - - -class p3ServerConfig: public RsServerConfig -{ - public: - - p3ServerConfig(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr, p3NetMgr *netMgr, pqihandler *pqih, p3GeneralConfig *genCfg); -virtual ~p3ServerConfig(); - - void load_config(); - - /* From RsIface::RsConfig */ - -virtual int getConfigNetStatus(RsConfigNetStatus &status); -virtual int getConfigStartup(RsConfigStartup ¶ms); -//virtual int getConfigDataRates(RsConfigDataRates ¶ms); - - /***** for RsConfig -> p3BandwidthControl ****/ - -virtual int getTotalBandwidthRates(RsConfigDataRates &rates); -virtual int getAllBandwidthRates(std::map &ratemap); - virtual int getTrafficInfo(std::list& out_lst, std::list &in_lst) ; - - /* From RsInit */ - -virtual std::string RsConfigDirectory(); -virtual std::string RsConfigKeysDirectory(); - -virtual std::string RsProfileConfigDirectory(); -virtual bool getStartMinimised(); -virtual std::string getRetroShareLink(); - -virtual bool getAutoLogin(); -virtual void setAutoLogin(bool autoLogin); -virtual bool RsClearAutoLogin(); - -virtual std::string getRetroshareDataDirectory(); - - /* New Stuff */ - -virtual RsConfigUserLvl getUserLevel(); - -virtual RsNetState getNetState(); -virtual RsNetworkMode getNetworkMode(); -virtual RsNatTypeMode getNatTypeMode(); -virtual RsNatHoleMode getNatHoleMode(); -virtual RsConnectModes getConnectModes(); - -virtual bool getConfigurationOption(uint32_t key, std::string &opt); -virtual bool setConfigurationOption(uint32_t key, const std::string &opt); - - /* Operating Mode */ -virtual RsOpMode getOperatingMode(); -virtual bool setOperatingMode(RsOpMode opMode); -virtual bool setOperatingMode(const std::string &opModeStr); - -virtual int SetMaxDataRates( int downKb, int upKb ); -virtual int GetMaxDataRates( int &downKb, int &upKb ); -virtual int GetCurrentDataRates( float &inKb, float &outKb ); -virtual int GetTrafficSum( uint64_t &inb, uint64_t &outb ); - -/********************* ABOVE is RsConfig Interface *******/ - - private: - -bool switchToOperatingMode(RsOpMode opMode); - -bool findConfigurationOption(uint32_t key, std::string &keystr); - - p3PeerMgr *mPeerMgr; - p3LinkMgr *mLinkMgr; - p3NetMgr *mNetMgr; - pqihandler *mPqiHandler; - p3GeneralConfig *mGeneralConfig; - - RsMutex configMtx; - RsConfigUserLvl mUserLevel; // store last one... will later be a config Item too. - float mRateDownload; - float mRateUpload; - - RsOpMode mOpMode; -}; - -#endif diff --git a/libretroshare/src/rsserver/p3status.cc b/libretroshare/src/rsserver/p3status.cc deleted file mode 100644 index 4185e6802..000000000 --- a/libretroshare/src/rsserver/p3status.cc +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3status.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Chris Evi-Parker. * - * * - * 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 . * - * * - *******************************************************************************/ -#include "p3status.h" -#include "services/p3statusservice.h" - -p3Status::p3Status(p3StatusService* statusSrv) - : mStatusSrv(statusSrv) { - - -} - -p3Status::~p3Status(){ - return; -} - -bool p3Status::getOwnStatus(StatusInfo& statusInfo){ - - return mStatusSrv->getOwnStatus(statusInfo); -} - -bool p3Status::getStatusList(std::list& statusInfo){ - - return mStatusSrv->getStatusList(statusInfo); -} - -bool p3Status::getStatus(const RsPeerId &id, StatusInfo &statusInfo) -{ - return mStatusSrv->getStatus(id, statusInfo); -} - -bool p3Status::sendStatus(const RsPeerId &id, uint32_t status){ - - return mStatusSrv->sendStatus(id, status); -} diff --git a/libretroshare/src/rsserver/p3status.h b/libretroshare/src/rsserver/p3status.h deleted file mode 100644 index a6ae941f0..000000000 --- a/libretroshare/src/rsserver/p3status.h +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3status.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Chris Evi-Parker. * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_P3STATUS_INTERFACE_H -#define RS_P3STATUS_INTERFACE_H - -#include "retroshare/rsstatus.h" - - -class p3StatusService; - -//! Implements abstract interface rsStatus -/*! - * Interfaces with p3StatusService - */ -class p3Status : public RsStatus -{ -public: - - explicit p3Status(p3StatusService* statusSrv); - virtual ~p3Status(); - - - virtual bool getOwnStatus(StatusInfo& statusInfo); - virtual bool getStatusList(std::list& statusInfo); - virtual bool getStatus(const RsPeerId &id, StatusInfo &statusInfo); - virtual bool sendStatus(const RsPeerId &id, uint32_t status); - -private: - - p3StatusService* mStatusSrv; - -}; - -#endif /* RS_P3STATUS_INTERFACE_H */ diff --git a/libretroshare/src/rsserver/rsaccounts.cc b/libretroshare/src/rsserver/rsaccounts.cc deleted file mode 100644 index 8be56073c..000000000 --- a/libretroshare/src/rsserver/rsaccounts.cc +++ /dev/null @@ -1,1449 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: rsaccounts.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2014 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -/********************************************************************* - * Libretroshare interface declared in rsaccounts.h. - * external interface in rsinit.h RsAccounts namespace. - * - */ - -#ifdef WINDOWS_SYS -#include "util/rswin.h" -#endif // WINDOWS_SYS - -#include -#include - -#include - -#include "retroshare/rsinit.h" -#include "rsaccounts.h" - -#include "util/rsdir.h" -#include "util/rsstring.h" -#include "util/folderiterator.h" - -#include "pqi/authssl.h" -#include "pqi/sslfns.h" -#include "pqi/authgpg.h" - -#include - -// Global singleton declaration of data. -RsAccountsDetail* RsAccounts::rsAccountsDetails = nullptr; - -/* Uses private class - so must be hidden */ -static bool checkAccount(const std::string &accountdir, AccountDetails &account,std::map >& unsupported_keys); - -AccountDetails::AccountDetails() - :mSslId(""), mAccountDir(""), mPgpId(""), mPgpName(""), mPgpEmail(""), - mLocation(""), mIsHiddenLoc(false), mFirstRun(false) -{ - return; -} - -RsAccountsDetail::RsAccountsDetail() : mAccountsLocked(false), mPreferredId("") -{} - -bool RsAccountsDetail::loadAccounts() -{ - int failing_accounts ; -#warning we might need some switch here for hidden nodes only - getAvailableAccounts(mAccounts,failing_accounts,mUnsupportedKeys,false); - - loadPreferredAccount(); - checkPreferredId(); - - if(failing_accounts > 0 && mAccounts.empty()) - return false; - - return true; -} - -bool RsAccountsDetail::lockPreferredAccount() -{ - if (checkPreferredId()) - { - mAccountsLocked = true; - return true; - } - - return false; -} - -void RsAccountsDetail::unlockPreferredAccount() -{ - mAccountsLocked = false; -} - -bool RsAccountsDetail::checkAccountDirectory() -{ - if (!checkPreferredId()) - { - return false; - } - - return setupAccount(getCurrentAccountPathAccountDirectory()); -} - -#warning we need to clean that up. Login should only ask for a SSL id, instead of a std::string. - -bool RsAccountsDetail::selectAccountByString(const std::string &prefUserString) -{ - if (mAccountsLocked) - { - std::cerr << "RsAccountsDetail::selectAccountByString() ERROR Accounts Locked"; - std::cerr << std::endl; - return false; - } - - // try both. - // - RsPeerId ssl_id(prefUserString) ; - RsPgpId pgp_id(prefUserString) ; - - std::cerr << "RsAccountsDetail::selectAccountByString(" << prefUserString << ")" << std::endl; - - //bool pgpNameFound = false; - std::map::const_iterator it; - for(it = mAccounts.begin() ; it!= mAccounts.end() ; ++it) - { - std::cerr << "\tChecking account (pgpid = " << it->second.mPgpId; - std::cerr << ", name=" << it->second.mPgpName << ", sslId="; - std::cerr << it->second.mSslId << ")" << std::endl; - - if(prefUserString == it->second.mPgpName || pgp_id == it->second.mPgpId || ssl_id == it->second.mSslId) - { - mPreferredId = it->second.mSslId; - //pgpNameFound = true; - - std::cerr << "Account selected: " << ssl_id << std::endl; - - return true; - } - } - std::cerr << "No suitable candidate found." << std::endl; - return false; -} - - -bool RsAccountsDetail::selectId(const RsPeerId& preferredId) -{ - - if (mAccountsLocked) - { - std::cerr << "RsAccountsDetail::selectId() ERROR Accounts Locked"; - std::cerr << std::endl; - return false; - } - - std::map::const_iterator it; - it = mAccounts.find(preferredId); - - if (it != mAccounts.end()) - { - mPreferredId = preferredId; - return true; - } - else - { - return false; - } -} - - -bool RsAccountsDetail::checkPreferredId() -{ - std::map::const_iterator it; - it = mAccounts.find(mPreferredId); - - if (it != mAccounts.end()) - { - return true; - } - else - { - mPreferredId.clear(); - return false; - } -} - -// initial configuration bootstrapping... - -const std::string kPathPGPDirectory = "pgp"; -const std::string kPathKeyDirectory = "keys"; -const std::string kPathConfigDirectory = "config"; - -const std::string kFilenamePreferredAccount = "default_cert_06.txt"; -const std::string kFilenameKey = "user_pk.pem"; -const std::string kFilenameCert = "user_cert.pem"; -const std::string kFilenameLocation = "location_name.txt"; - - -/********************************************************************* - * Directories... based on current PreferredId. - */ - -std::string RsAccountsDetail::PathPGPDirectory() -{ - return mBaseDirectory + "/" + kPathPGPDirectory; -} - - -std::string RsAccountsDetail::PathBaseDirectory() -{ - if(mBaseDirectory.empty()) defaultBaseDirectory(); - return mBaseDirectory; -} - - -std::string RsAccountsDetail::getCurrentAccountPathAccountDirectory() -{ - std::string path; - - std::map::const_iterator it; - it = mAccounts.find(mPreferredId); - if (it == mAccounts.end()) - { - return path; - } - - path = mBaseDirectory + "/"; - path += it->second.mAccountDir; - return path; -} - -std::string RsAccountsDetail::getCurrentAccountPathAccountKeysDirectory() -{ - std::string path = getCurrentAccountPathAccountDirectory(); - if (path.empty()) - { - return path; - } - - path += "/" + kPathKeyDirectory; - return path; -} - -std::string RsAccountsDetail::getCurrentAccountPathKeyFile() -{ - std::string path = getCurrentAccountPathAccountKeysDirectory(); - if (path.empty()) - { - return path; - } - - path += "/" + kFilenameKey; - return path; -} - -std::string RsAccountsDetail::getCurrentAccountPathCertFile() -{ - std::string path = getCurrentAccountPathAccountKeysDirectory(); - if (path.empty()) - { - return path; - } - path += "/" + kFilenameCert; - return path; -} - -std::string RsAccountsDetail::getCurrentAccountLocationName() -{ - std::map::const_iterator it; - it = mAccounts.find(mPreferredId); - if (it == mAccounts.end()) - { - return ""; - } - return it->second.mLocation; -} - - -/********************************************************************* - * Setup Base Directories. - * - */ - -bool RsAccountsDetail::setupBaseDirectory(std::string alt_basedir) -{ - if (alt_basedir.empty()) - { - if (!defaultBaseDirectory()) - { - std::cerr << "RsAccounts::setupBaseDirectory() Cannot find defaultBaseDirectory"; - std::cerr << std::endl; - return false; - } - } - else - { - mBaseDirectory = alt_basedir; - } - - /* Check for trailing '/' */ - if (!mBaseDirectory.empty()) - { - char lastChar = *mBaseDirectory.rbegin(); - if (lastChar == '/' -#ifdef WINDOWS_SYS - || lastChar == '\\' -#endif - ) - { - mBaseDirectory.erase(mBaseDirectory.end() - 1); - } - } - - if (!RsDirUtil::checkCreateDirectory(mBaseDirectory)) - { - std::cerr << "RsAccounts::setupBaseDirectory() Cannot Create BaseConfig Dir:" << mBaseDirectory; - std::cerr << std::endl; - return false ; - } - return true ; -} - - -bool RsAccountsDetail::defaultBaseDirectory() -{ - std::string basedir; - -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - - // unix: homedir + /.retroshare - char *h = getenv("HOME"); - if (h == NULL) - { - std::cerr << "defaultBaseDirectory() Error: cannot determine $HOME dir" - << std::endl; - return false ; - } - - basedir = h; - basedir += "/.retroshare"; - -#else - if (RsInit::isPortable()) - { - // use directory "Data" in portable version - basedir = "Data"; - } - else - { - wchar_t *wh = _wgetenv(L"APPDATA"); - std::string h; - librs::util::ConvertUtf16ToUtf8(std::wstring(wh), h); - if (h.empty()) - { - // generating default - std::cerr << "defaultBaseDirectory() Error: "; - std::cerr << " getEnv Error --Win95/98?"; - std::cerr << std::endl; - basedir="C:\\Retro"; - } - else - { - basedir = h; - } - - if (!RsDirUtil::checkCreateDirectory(basedir)) - { - std::cerr << "defaultBaseDirectory() Error: "; - std::cerr << "Cannot Create BaseConfig Dir : " << basedir << std::endl; - return false ; - } - basedir += "\\RetroShare"; - } -#endif -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - /* store to class variable */ - mBaseDirectory = basedir; - std::cerr << "defaultBaseDirectory() = " << mBaseDirectory; - std::cerr << std::endl; - return true; -} - - -bool RsAccountsDetail::loadPreferredAccount() -{ - std::string initfile = mBaseDirectory + "/"; - initfile += kFilenamePreferredAccount; - - // open and read in the lines. - FILE *ifd = RsDirUtil::rs_fopen(initfile.c_str(), "r"); - char path[1024]; - int i; - - if (ifd != NULL) - { - if (NULL != fgets(path, 1024, ifd)) - { - for(i = 0; (path[i] != '\0') && (path[i] != '\n'); i++) ; - path[i] = '\0'; - - // Store PreferredId. - mPreferredId = RsPeerId(std::string(path)); - - if(mPreferredId.isNull()) - { - fclose(ifd); - return false ; - } - } - fclose(ifd); - return true; - } - return false; -} - -bool RsAccountsDetail::storePreferredAccount() -{ - // Check for config file. - std::string initfile = mBaseDirectory + "/"; - initfile += kFilenamePreferredAccount; - - // open and read in the lines. - FILE *ifd = RsDirUtil::rs_fopen(initfile.c_str(), "w"); - - if (ifd != NULL) - { - fprintf(ifd, "%s\n", mPreferredId.toStdString().c_str()); - fclose(ifd); - - std::cerr << "Creating Init File: " << initfile << std::endl; - std::cerr << "\tId: " << mPreferredId << std::endl; - - return true; - } - std::cerr << "Failed To Create Init File: " << initfile << std::endl; - return false; -} - - -/********************************************************************* - * Accounts - * - */ - -bool RsAccountsDetail::getCurrentAccountId(RsPeerId &id) -{ - id = mPreferredId; - return (!mPreferredId.isNull()); -} - -bool RsAccountsDetail::getAccountIds(std::list &ids) -{ - std::map::iterator it; -#ifdef DEBUG_ACCOUNTS - std::cerr << "getAccountIds:" << std::endl; -#endif - - for(it = mAccounts.begin(); it != mAccounts.end(); ++it) - { -#ifdef DEBUG_ACCOUNTS - std::cerr << "SSL Id: " << it->second.mSslId << " PGP Id " << it->second.mPgpId; - std::cerr << " PGP Name: " << it->second.mPgpName; - std::cerr << " PGP Email: " << it->second.mPgpEmail; - std::cerr << " Location: " << it->second.mLocation; - std::cerr << std::endl; -#endif - - ids.push_back(it->first); - } - return true; -} - - -bool RsAccountsDetail::getCurrentAccountDetails(const RsPeerId &id, - RsPgpId &gpgId, std::string &gpgName, - std::string &gpgEmail, std::string &location) -{ - std::map::iterator it; - it = mAccounts.find(id); - if (it != mAccounts.end()) - { - gpgId = it->second.mPgpId; - gpgName = it->second.mPgpName; - gpgEmail = it->second.mPgpEmail; - location = it->second.mLocation; - return true; - } - return false; -} - -bool RsAccountsDetail::getCurrentAccountOptions(bool &ishidden,bool& isautotor, bool &isFirstTimeRun) -{ - std::map::iterator it; - it = mAccounts.find(mPreferredId); - if (it != mAccounts.end()) - { - ishidden = it->second.mIsHiddenLoc; - isFirstTimeRun = it->second.mFirstRun; - isautotor = it->second.mIsAutoTor; - - return true; - } - return false; -} - - -/* directories with valid certificates in the expected location */ -bool RsAccountsDetail::getAvailableAccounts(std::map &accounts,int& failing_accounts,std::map >& unsupported_keys,bool hidden_only) -{ - failing_accounts = 0 ; - /* get the directories */ - std::list directories; - std::list::iterator it; - - std::cerr << "RsAccounts::getAvailableAccounts()"; - std::cerr << std::endl; - - /* now iterate through the directory... - * directories - flags as old, - * files checked to see if they have changed. (rehashed) - */ - - /* check for the dir existance */ - librs::util::FolderIterator dirIt(mBaseDirectory,false); - - if (!dirIt.isValid()) - { - std::cerr << "Cannot Open Base Dir - No Available Accounts" << std::endl; - return false ; - } - - struct stat64 buf; - - for(;dirIt.isValid();dirIt.next()) - { - /* check entry type */ - std::string fname = dirIt.file_name(); - std::string fullname = mBaseDirectory + "/" + fname; -#ifdef FIM_DEBUG - std::cerr << "calling stats on " << fullname <length() != 32 + 6) - { - std::cerr << "getAvailableAccounts() Skipping Invalid sized dir: " << *it << std::endl; - continue; - } - - std::string prefix = (*it).substr(0, 6); - std::string lochex = (*it).substr(6); // rest of string. - - bool hidden_location = false; - bool auto_tor = false; - bool valid_prefix = false; - - if (prefix == "LOC06_") - { - valid_prefix = true; - } - else if (prefix == "HID06_") - { - valid_prefix = true; - hidden_location = true; - - auto_tor = RsDirUtil::checkDirectory(mBaseDirectory+"/"+*it+"/hidden_service"); - } - else - { - std::cerr << "getAvailableAccounts() Skipping Invalid Prefix dir: " << *it << std::endl; - continue; - } - - if(hidden_only && !hidden_location) - continue ; - - if(valid_prefix && isHexaString(lochex) && (lochex).length() == 32) - { - std::string accountdir = mBaseDirectory + "/" + *it; -#ifdef GPG_DEBUG - std::cerr << "getAvailableAccounts() Checking: " << *it << std::endl; -#endif - - AccountDetails tmpId; - tmpId.mIsHiddenLoc = hidden_location; - tmpId.mIsAutoTor = auto_tor; - tmpId.mAccountDir = *it; - - if (checkAccount(accountdir, tmpId,unsupported_keys)) - { -#ifdef GPG_DEBUG - std::cerr << "getAvailableAccounts() Accepted: " << *it << std::endl; -#endif - - std::map::iterator ait; - ait = accounts.find(tmpId.mSslId); - if (ait != accounts.end()) - { - std::cerr << "getAvailableAccounts() ERROR Duplicate SSLIDs"; - std::cerr << " - only one will be available"; - std::cerr << std::endl; - std::cerr << " ID1 (overridden) : " << ait->first << " Directory: " << ait->second.mAccountDir; - std::cerr << std::endl; - std::cerr << " ID2 (available) : " << tmpId.mSslId << " Directory: " << tmpId.mAccountDir; - std::cerr << std::endl; - - } - - accounts[tmpId.mSslId] = tmpId; - } - else - ++failing_accounts ; - } -#ifdef GPG_DEBUG - else - std::cerr << "Skipped non SSLid directory " << *it << std::endl; -#endif - } - return true; -} - - - -static bool checkAccount(const std::string &accountdir, AccountDetails &account,std::map >& unsupported_keys) -{ - /* check if the cert/key file exists */ - - // Create the filename. - // TODO: use kFilenameKey - std::string basename = accountdir + "/"; - basename += kPathKeyDirectory + "/"; - basename += "user"; - - std::string cert_name = basename + "_cert.pem"; - //std::string userName; - -#ifdef AUTHSSL_DEBUG - std::cerr << "checkAccount() dir: " << accountdir << std::endl; -#endif - bool ret = false; - - /* check against authmanagers private keys */ - if(AuthSSL::instance().parseX509DetailsFromFile( - cert_name, account.mSslId, account.mPgpId, account.mLocation )) - { - // new locations store the name in an extra file - if(account.mLocation == "") - RsDirUtil::loadStringFromFile(accountdir + "/" + kPathKeyDirectory + "/" + kFilenameLocation, - account.mLocation); -#ifdef AUTHSSL_DEBUG - std::cerr << "location: " << account.mLocation << " id: " << account.mSslId << std::endl; - std::cerr << "issuerName: " << account.mPgpId << " id: " << account.mSslId << std::endl; -#endif - - if(! RsAccounts::GetPGPLoginDetails(account.mPgpId, account.mPgpName, account.mPgpEmail)) - return false ; - - if(!AuthGPG::getAuthGPG()->haveSecretKey(account.mPgpId)) - return false ; - - if(!AuthGPG::getAuthGPG()->isKeySupported(account.mPgpId)) - { - std::string keystring = account.mPgpId.toStdString() + " " + account.mPgpName + "<" + account.mPgpEmail ; - unsupported_keys[keystring].push_back("Location: " + account.mLocation + "  (" + account.mSslId.toStdString() + ")") ; - return false ; - } - -#ifdef GPG_DEBUG - std::cerr << "PGPLoginDetails: " << account.mPgpId << " name: " << account.mPgpName; - std::cerr << " email: " << account.mPgpEmail << std::endl; -#endif - ret = true; - } - else - { - std::cerr << "GetIssuerName FAILED!" << std::endl; - ret = false; - } - - return ret; -} - - - - - -/**************************** Access Functions for Init Data **************************/ -/**************************** Private Functions for InitRetroshare ********************/ -/**************************** Private Functions for InitRetroshare ********************/ - - -/*********************************************************** - * This Directory is used to store data and "template" file that Retroshare requires. - * These files will either be copied into Retroshare's configuration directory, - * if they are to be modified. Or used directly, if read-only. - * - * This will initially be used for the DHT bootstrap file. - * - * Please modify the code below to suit your platform! - * - * WINDOWS: - * WINDOWS PORTABLE: - * Linux: - * OSX: - - ***********/ - -#ifdef __APPLE__ - /* needs CoreFoundation Framework */ - #include - //#include - //#include -#endif - -/*static*/ std::string RsAccountsDetail::PathDataDirectory(bool check) -{ - std::string dataDirectory; - -#ifdef __APPLE__ - /* NOTE: OSX also qualifies as BSD... so this #ifdef must be before the BSD check. */ - - /* For OSX, applications are Bundled in a directory... - * need to get the path to the executable Bundle. - * - * Code nicely supplied by Qt! - */ - - CFURLRef pluginRef = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef, - kCFURLPOSIXPathStyle); - const char *pathPtr = CFStringGetCStringPtr(macPath, - CFStringGetSystemEncoding()); - dataDirectory = pathPtr; - CFRelease(pluginRef); - CFRelease(macPath); - - dataDirectory += "/Contents/Resources"; - std::cerr << "getRetroshareDataDirectory() OSX: " << dataDirectory; - -#elif (defined(BSD) && (BSD >= 199103)) - /* For BSD, the default is LOCALBASE which will be set - * before compilation via the ports/pkg-src mechanisms. - * For compilation without ports/pkg-src it is set to - * /usr/local (default on Open and Free; Net has /usr/pkg) - */ - dataDirectory = "/usr/local/share/retroshare"; - std::cerr << "getRetroshareDataDirectory() BSD: " << dataDirectory; -#elif defined(WINDOWS_SYS) -// if (RsInitConfig::portable) -// { -// /* For Windows Portable, files must be in the data directory */ -// dataDirectory = "Data"; -// std::cerr << "getRetroshareDataDirectory() WINDOWS PORTABLE: " << dataDirectory; -// std::cerr << std::endl; -// } -// else -// { -// /* For Windows: environment variable APPDATA should be suitable */ -// dataDirectory = getenv("APPDATA"); -// dataDirectory += "\\RetroShare"; -// -// std::cerr << "getRetroshareDataDirectory() WINDOWS: " << dataDirectory; -// std::cerr << std::endl; -// } - - /* Use RetroShare's exe dir */ - dataDirectory = "."; -#elif defined(ANDROID) - dataDirectory = PathBaseDirectory()+"/usr/share/retroshare"; -#elif defined(DATA_DIR) - // cppcheck-suppress ConfigurationNotChecked - dataDirectory = DATA_DIR; - // For all other OS the data directory must be set in libretroshare.pro -#else -# error "For your target OS automatic data dir discovery is not supported, cannot compile if DATA_DIR variable not set." -#endif - - if (!check) - { - std::cerr << "getRetroshareDataDirectory() unckecked: " << dataDirectory << std::endl; - return dataDirectory; - } - - /* Make sure the directory exists, else return emptyString */ - if (!RsDirUtil::checkDirectory(dataDirectory)) - { - std::cerr << "getRetroshareDataDirectory() not found: " << dataDirectory << std::endl; - dataDirectory = ""; - } - else - { - std::cerr << "getRetroshareDataDirectory() found: " << dataDirectory << std::endl; - } - - return dataDirectory; -} - - - -/*****************************************************************************/ -/*****************************************************************************/ -/************************* Generating Certificates ***************************/ -/*****************************************************************************/ -/*****************************************************************************/ - - - /* Generating GPGme Account */ -int RsAccountsDetail::GetPGPLogins(std::list &pgpIds) { - AuthGPG::getAuthGPG()->availableGPGCertificatesWithPrivateKeys(pgpIds); - return 1; -} - -int RsAccountsDetail::GetPGPLoginDetails(const RsPgpId& id, std::string &name, std::string &email) -{ - #ifdef GPG_DEBUG - std::cerr << "RsInit::GetPGPLoginDetails for \"" << id << "\"" << std::endl; - #endif - - bool ok = true ; - name = AuthGPG::getAuthGPG()->getGPGName(id,&ok); - if(!ok) - return 0 ; - email = AuthGPG::getAuthGPG()->getGPGEmail(id,&ok); - if(!ok) - return 0 ; - - if (name != "") { - return 1; - } else { - return 0; - } -} - - - -/* Before any SSL stuff can be loaded, the correct PGP must be selected / generated: - **/ - -bool RsAccountsDetail::SelectPGPAccount(const RsPgpId& pgpId) -{ - bool retVal = false; - - if (0 < AuthGPG::getAuthGPG() -> GPGInit(pgpId)) - { - retVal = true; -#ifdef DEBUG_ACCOUNTS - std::cerr << "PGP Auth Success!"; -#endif - } - else - std::cerr << "PGP Auth Failed!"; - -#ifdef DEBUG_ACCOUNTS - std::cerr << " ID: " << pgpId << std::endl; -#endif - - return retVal; -} - - -bool RsAccountsDetail::GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId &pgpId, const int keynumbits, std::string &errString) -{ - return AuthGPG::getAuthGPG()->GeneratePGPCertificate(name, email, passwd, pgpId, keynumbits, errString); -} - - // PGP Support Functions. -void RsAccountsDetail::getUnsupportedKeys(std::map > &unsupported_keys) -{ - unsupported_keys = mUnsupportedKeys; - return; -} - -bool RsAccountsDetail::exportIdentity(const std::string& fname,const RsPgpId& id) -{ - return AuthGPG::getAuthGPG()->exportProfile(fname,id); -} - -bool RsAccountsDetail::importIdentity(const std::string& fname,RsPgpId& id,std::string& import_error) -{ - return AuthGPG::getAuthGPG()->importProfile(fname,id,import_error); -} - -bool RsAccountsDetail::importIdentityFromString(const std::string &data, RsPgpId &imported_pgp_id, std::string &import_error) -{ - return AuthGPG::getAuthGPG()->importProfileFromString(data, imported_pgp_id, import_error); -} - -bool RsAccountsDetail::exportIdentityToString( - std::string& data, const RsPgpId& pgpId, bool includeSignatures, - std::string& errorMsg ) -{ - return AuthGPG::getAuthGPG()->exportIdentityToString( - data, pgpId, includeSignatures, errorMsg ); -} - -bool RsAccountsDetail::copyGnuPGKeyrings() -{ - std::string pgp_dir = PathPGPDirectory() ; - - if(!RsDirUtil::checkCreateDirectory(pgp_dir)) - throw std::runtime_error("Cannot create pgp directory " + pgp_dir) ; - - std::string source_public_keyring; - std::string source_secret_keyring; - -#ifdef WINDOWS_SYS - source_public_keyring = mBaseDirectory + "/gnupg/pubring.gpg"; - source_secret_keyring = mBaseDirectory + "/gnupg/secring.gpg" ; -#else - char *env_gnupghome = getenv("GNUPGHOME") ; - - if(env_gnupghome != NULL) - { - std::cerr << "looking into $GNUPGHOME/" << std::endl; - - source_public_keyring = std::string(env_gnupghome) + "/pubring.gpg" ; - source_secret_keyring = std::string(env_gnupghome) + "/secring.gpg" ; - } - else - { - char *env_homedir = getenv("HOME") ; - - if(env_homedir != NULL) - { - std::cerr << "looking into $HOME/.gnupg/" << std::endl; - std::string home_dir(env_homedir) ; - - // We need a specific part for MacOS and Linux as well - source_public_keyring = home_dir + "/.gnupg/pubring.gpg" ; - source_secret_keyring = home_dir + "/.gnupg/secring.gpg" ; - } - else - return false ; - } -#endif - - if(!RsDirUtil::copyFile(source_public_keyring,pgp_dir + "/retroshare_public_keyring.gpg")) - { - std::cerr << "Cannot copy pub keyring " << source_public_keyring << " to destination file " << pgp_dir + "/retroshare_public_keyring.gpg. If you believe your keyring is in a different place, please make the copy yourself." << std::endl; - return false ; - } - if(!RsDirUtil::copyFile(source_secret_keyring,pgp_dir + "/retroshare_secret_keyring.gpg")) - { - std::cerr << "Cannot copy sec keyring " << source_secret_keyring << " to destination file " << pgp_dir + "/retroshare_secret_keyring.gpg. your keyring is in a different place, please make the copy yourself." << std::endl; - return false ; - } - - return true ; -} - - - - /* Create SSL Certificates */ -bool RsAccountsDetail::GenerateSSLCertificate(const RsPgpId& pgp_id, const std::string& org, const std::string& loc, const std::string& country, bool ishiddenloc,bool isautotor, const std::string& passwd, RsPeerId &sslId, std::string &errString) -{ - /* select the PGP Identity first */ - if (!SelectPGPAccount(pgp_id)) - { - errString = "Invalid PGP Identity"; - return false; - } - - // generate the private_key / certificate. - // save to file. - // - // then load as if they had entered a passwd. - - // check password. - if (passwd.length() < 4) - { - errString = "Password is Unsatisfactory (must be 4+ chars)"; - return false; - } - - int nbits = 4096; - - //std::string pgp_name = AuthGPG::getAuthGPG()->getGPGName(pgp_id); - - // Create the filename ..... - // Temporary Directory for creating files.... - std::string tmpdir = "TMPCFG"; - - std::string tmpbase = mBaseDirectory + "/" + tmpdir + "/"; - - if(!setupAccount(tmpbase)) - return false ; - - /* create directory structure */ - std::string keypath = tmpbase + kPathKeyDirectory + "/"; - std::string key_name = keypath + kFilenameKey; - std::string cert_name = keypath + kFilenameCert; - - /* Extra step required for SSL + PGP, user must have selected - * or generated a suitable key so the signing can happen. - */ - - X509_REQ *req = GenerateX509Req( - key_name.c_str(), - passwd.c_str(), - "-", //pgp_name.c_str(), // does not allow empty name, set to constant instead - "", //ui -> gen_email -> value(), - org.c_str(), - "", //loc.c_str(), - "", //ui -> gen_state -> value(), - country.c_str(), - nbits, errString); - - if (req == NULL) - { - fprintf(stderr,"RsGenerateCert() Couldn't create Request. Reason: %s\n", errString.c_str()); - return false; - } - - long days = 3000; - X509 *x509 = AuthSSL::getAuthSSL()->SignX509ReqWithGPG(req, days); - - X509_REQ_free(req); - if (x509 == NULL) { - fprintf(stderr,"RsGenerateCert() Couldn't sign ssl certificate. Probably PGP password is wrong.\n"); - return false; - } - - /* save to file */ - - bool gen_ok = true; - - /* Print the signed Certificate! */ - BIO *bio_out = BIO_new(BIO_s_file()); - BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); - - /* Print it out */ - int nmflag = 0; - int reqflag = 0; - - X509_print_ex(bio_out, x509, nmflag, reqflag); - - (void) BIO_flush(bio_out); - BIO_free(bio_out); - - /* Save cert to file */ - // open the file. - FILE *out = NULL; - if (NULL == (out = RsDirUtil::rs_fopen(cert_name.c_str(), "w"))) - { - fprintf(stderr,"RsGenerateCert() Couldn't create Cert File"); - fprintf(stderr," : %s\n", cert_name.c_str()); - gen_ok = false; - } - - if (!PEM_write_X509(out,x509)) - { - fprintf(stderr,"RsGenerateCert() Couldn't Save Cert"); - fprintf(stderr," : %s\n", cert_name.c_str()); - gen_ok = false; - } - - fclose(out); - X509_free(x509); - - // store location name in a file - if(!RsDirUtil::saveStringToFile(keypath + kFilenameLocation, loc)) - std::cerr << "RsInit::GenerateSSLCertificate() failed to save location name to into file." << std::endl; - - if (!gen_ok) - { - errString = "Generation of Certificate Failed"; - return false; - } - - /* try to load it, and get Id */ - - std::string location; - RsPgpId pgpid_retrieved; - - if(!AuthSSL::instance().parseX509DetailsFromFile( - cert_name, sslId, pgpid_retrieved, location )) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot check own signature, maybe " - << "the files are corrupted." << std::endl; - return false; - } - - /* Move directory to correct id */ - std::string accountdir; - if (ishiddenloc) - accountdir = "HID06_" + sslId.toStdString(); - else - accountdir = "LOC06_" + sslId.toStdString(); - - std::string fullAccountDir = mBaseDirectory + "/" + accountdir; - std::string finalbase = fullAccountDir + "/"; - - /* Rename Directory */ - std::cerr << "Mv Config Dir from: " << tmpbase << " to: " << finalbase; - std::cerr << std::endl; - - if (!RsDirUtil::renameFile(tmpbase, finalbase)) - { - std::cerr << "rename FAILED" << std::endl; - } - - AccountDetails newAccount; - - newAccount.mSslId = sslId; - newAccount.mAccountDir = accountdir; - newAccount.mPgpId = pgp_id; - - newAccount.mLocation = loc; - newAccount.mIsHiddenLoc = ishiddenloc; - newAccount.mIsAutoTor = isautotor; - - newAccount.mFirstRun = true; - - // rest of newAccount pgp filled in checkAccount. - if (!checkAccount(fullAccountDir, newAccount, mUnsupportedKeys)) - { - std::cerr << "RsInit::GenerateSSLCertificate() Cannot check own signature, maybe the files are corrupted." << std::endl; - return false; - } - - mAccounts[newAccount.mSslId] = newAccount; - mPreferredId = newAccount.mSslId; - - std::cerr << "RetroShare has Successfully generated a Certficate/Key" << std::endl; - std::cerr << "\tCert Located: " << cert_name << std::endl; - std::cerr << "\tLocated: " << key_name << std::endl; - - return true; -} - - -/******************* PRIVATE FNS TO HELP with GEN **************/ -bool RsAccountsDetail::setupAccount(const std::string& accountdir) -{ - /* actual config directory isd */ - - std::string subdir1 = accountdir + "/"; - subdir1 += kPathKeyDirectory; - - std::string subdir2 = accountdir + "/"; - subdir2 += kPathConfigDirectory; - - std::string subdir3 = accountdir + "/"; - subdir3 += "cache"; - - std::string subdir4 = subdir3 + "/"; - std::string subdir5 = subdir3 + "/"; - subdir4 += "local"; - subdir5 += "remote"; - - // fatal if cannot find/create. - std::cerr << "Checking For Directories" << std::endl; - if (!RsDirUtil::checkCreateDirectory(accountdir)) - { - std::cerr << "Cannot Create BaseConfig Dir" << std::endl; - return false ; - } - if (!RsDirUtil::checkCreateDirectory(subdir1)) - { - std::cerr << "Cannot Create Key Directory" << std::endl; - return false ; - } - if (!RsDirUtil::checkCreateDirectory(subdir2)) - { - std::cerr << "Cannot Create Config Directory" << std::endl; - return false ; - } - if (!RsDirUtil::checkCreateDirectory(subdir3)) - { - std::cerr << "Cannot Create Config/Cache Dir" << std::endl; - return false ; - } - if (!RsDirUtil::checkCreateDirectory(subdir4)) - { - std::cerr << "Cannot Create Config/Cache/local Dir" << std::endl; - return false ; - } - if (!RsDirUtil::checkCreateDirectory(subdir5)) - { - std::cerr << "Cannot Create Config/Cache/remote Dir" << std::endl; - return false ; - } - - return true; -} - - - - - - -/***************************** FINAL LOADING OF SETUP *************************/ - -#if 0 - /* Login SSL */ -bool RsInit::LoadPassword(const std::string& id, const std::string& inPwd) -{ - /* select configDir */ - - RsInitConfig::preferredId = id; - - std::map::iterator it = RsInitConfig::accountIds.find(id); - if (it == RsInitConfig::accountIds.end()) - { - std::cerr << "RsInit::LoadPassword() Cannot Locate Identity: " << id; - std::cerr << std::endl; - exit(1); - } - - std::string accountdir = it->second.accountDir; - - RsInitConfig::configDir = RsInitConfig::basedir + "/" + accountdir; - RsInitConfig::passwd = inPwd; - - // if(inPwd != "") - // RsInitConfig::havePasswd = true; - - // Create the filename. - std::string basename = RsInitConfig::configDir + "/"; - basename += configKeyDir + "/"; - basename += "user"; - - RsInitConfig::load_key = basename + "_pk.pem"; - RsInitConfig::load_cert = basename + "_cert.pem"; - - return true; -} -#endif - -/********************************************************************************* - * PUBLIC INTERFACE FUNCTIONS - ********************************************************************************/ - -bool RsAccounts::init(const std::string& opt_base_dir,int& error_code) -{ - rsAccountsDetails = new RsAccountsDetail; - rsAccounts = new RsAccounts; - - // first check config directories, and set bootstrap values. - if(!rsAccountsDetails->setupBaseDirectory(opt_base_dir)) - { - error_code = RS_INIT_BASE_DIR_ERROR ; - return false ; - } - - // Setup PGP stuff. - std::string pgp_dir = rsAccountsDetails->PathPGPDirectory(); - - if(!RsDirUtil::checkCreateDirectory(pgp_dir)) - throw std::runtime_error("Cannot create pgp directory " + pgp_dir) ; - - AuthGPG::init( pgp_dir + "/retroshare_public_keyring.gpg", - pgp_dir + "/retroshare_secret_keyring.gpg", - pgp_dir + "/retroshare_trustdb.gpg", - pgp_dir + "/lock"); - - // load Accounts. - if (!rsAccountsDetails->loadAccounts()) - { - error_code = RS_INIT_NO_KEYRING ; - return false ; - } - return true; -} - - // Directories. -std::string RsAccounts::ConfigDirectory() { return RsAccountsDetail::PathBaseDirectory(); } -std::string RsAccounts::systemDataDirectory(bool check) { return RsAccountsDetail::PathDataDirectory(check); } -std::string RsAccounts::PGPDirectory() { return rsAccountsDetails->PathPGPDirectory(); } -std::string RsAccounts::AccountDirectory() { return rsAccountsDetails->getCurrentAccountPathAccountDirectory(); } -std::string RsAccounts::AccountKeysDirectory() { return rsAccountsDetails->getCurrentAccountPathAccountKeysDirectory(); } -std::string RsAccounts::AccountPathCertFile() { return rsAccountsDetails->getCurrentAccountPathCertFile(); } -std::string RsAccounts::AccountPathKeyFile() { return rsAccountsDetails->getCurrentAccountPathKeyFile(); } -std::string RsAccounts::AccountLocationName() { return rsAccountsDetails->getCurrentAccountLocationName(); } - -bool RsAccounts::lockPreferredAccount() { return rsAccountsDetails->lockPreferredAccount();} // are these methods any useful?? -void RsAccounts::unlockPreferredAccount() { rsAccountsDetails->unlockPreferredAccount(); } - -bool RsAccounts::checkCreateAccountDirectory() { return rsAccountsDetails->checkAccountDirectory(); } - -// PGP Accounts. -int RsAccounts::GetPGPLogins(std::list &pgpIds) -{ - return rsAccountsDetails->GetPGPLogins(pgpIds); -} - -int RsAccounts::GetPGPLoginDetails(const RsPgpId& id, std::string &name, std::string &email) -{ - return rsAccountsDetails->GetPGPLoginDetails(id, name, email); -} - -bool RsAccounts::GeneratePGPCertificate(const std::string &name, const std::string& email, const std::string& passwd, RsPgpId &pgpId, const int keynumbits, std::string &errString) -{ - return rsAccountsDetails->GeneratePGPCertificate(name, email, passwd, pgpId, keynumbits, errString); -} - -// PGP Support Functions. -bool RsAccounts::ExportIdentity(const std::string& fname,const RsPgpId& pgp_id) -{ - return rsAccountsDetails->exportIdentity(fname,pgp_id); -} - -bool RsAccounts::ImportIdentity(const std::string& fname,RsPgpId& imported_pgp_id,std::string& import_error) -{ - return rsAccountsDetails->importIdentity(fname,imported_pgp_id,import_error); -} - -bool RsAccounts::importIdentityFromString( - const std::string& data, RsPgpId& imported_pgp_id, - std::string& import_error ) -{ - return rsAccountsDetails-> - importIdentityFromString(data, imported_pgp_id, import_error); -} - -/*static*/ bool RsAccounts::exportIdentityToString( - std::string& data, const RsPgpId& pgpId, std::string& errorMsg, - bool includeSignatures ) -{ - return rsAccountsDetails->exportIdentityToString( - data, pgpId, includeSignatures, errorMsg); -} - -void RsAccounts::GetUnsupportedKeys(std::map > &unsupported_keys) -{ - return rsAccountsDetails->getUnsupportedKeys(unsupported_keys); -} - -bool RsAccounts::CopyGnuPGKeyrings() -{ - return rsAccountsDetails->copyGnuPGKeyrings(); -} - -void RsAccounts::storeSelectedAccount() { rsAccountsDetails->storePreferredAccount() ;} -// Rs Accounts -bool RsAccounts::SelectAccount(const RsPeerId &id) -{ - return rsAccountsDetails->selectId(id); -} - -bool RsAccounts::GetPreferredAccountId(RsPeerId &id) -{ - return rsAccountsDetails->getCurrentAccountId(id); -} - -bool RsAccounts::getCurrentAccountOptions(bool& is_hidden,bool& is_tor_auto,bool& is_first_time) -{ - return rsAccountsDetails->getCurrentAccountOptions(is_hidden,is_tor_auto,is_first_time); -} -bool RsAccounts::isHiddenNode() -{ - bool hidden = false ; - bool is_tor_only = false ; - bool is_first_time = false ; - - if(!getCurrentAccountOptions(hidden,is_tor_only,is_first_time)) - { - std::cerr << "(EE) Critical problem: RsAccounts::getCurrentAccountOptions() called but no account chosen!" << std::endl; - throw std::runtime_error("inconsistent configuration") ; - } - - return hidden ; -} -bool RsAccounts::isTorAuto() -{ - bool hidden = false ; - bool is_tor_only = false ; - bool is_first_time = false ; - - if(!getCurrentAccountOptions(hidden,is_tor_only,is_first_time)) - { - std::cerr << "(EE) Critical problem: RsAccounts::getCurrentAccountOptions() called but no account chosen!" << std::endl; - throw std::runtime_error("inconsistent configuration") ; - } - - return is_tor_only ; -} - -bool RsAccounts::GetAccountIds(std::list &ids) -{ - return rsAccountsDetails->getAccountIds(ids); -} - -bool RsAccounts::GetAccountDetails(const RsPeerId &id, - RsPgpId &pgpId, std::string &pgpName, - std::string &pgpEmail, std::string &location) -{ - return rsAccountsDetails->getCurrentAccountDetails(id, pgpId, pgpName, pgpEmail, location); -} - -bool RsAccounts::createNewAccount( - const RsPgpId& pgp_id, const std::string& org, const std::string& loc, - const std::string& country, bool ishiddenloc, bool isautotor, - const std::string& passwd, RsPeerId &sslId, std::string &errString ) -{ - return rsAccountsDetails->GenerateSSLCertificate(pgp_id, org, loc, country, ishiddenloc, isautotor, passwd, sslId, errString); -} - -/********************************************************************************* - * END OF: PUBLIC INTERFACE FUNCTIONS - ********************************************************************************/ - -std::string RsAccountsDetail::mBaseDirectory; diff --git a/libretroshare/src/rsserver/rsaccounts.h b/libretroshare/src/rsserver/rsaccounts.h deleted file mode 100644 index 2db4552a7..000000000 --- a/libretroshare/src/rsserver/rsaccounts.h +++ /dev/null @@ -1,150 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: rsaccounts.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2014 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -/********************************************************************* - * Header providing interface for libretroshare access to RsAccounts stuff. - * External access must be through rsinit.g where a RsAccounts namespace + fns - * are available. - * - */ - -#pragma once - -#include -#include -#include -#include "retroshare/rstypes.h" - -class AccountDetails -{ - public: - AccountDetails(); - - RsPeerId mSslId; - std::string mAccountDir; - - RsPgpId mPgpId; - std::string mPgpName; - std::string mPgpEmail; - - std::string mLocation; - bool mIsHiddenLoc; - bool mFirstRun; - bool mIsAutoTor; - -}; - -class RsAccountsDetail -{ - public: - RsAccountsDetail(); - - // These functions are externally accessible via RsAccounts namespace. - // These functions are accessible from inside libretroshare. - - bool setupBaseDirectory(std::string alt_basedir); - bool loadAccounts(); - bool lockPreferredAccount(); - void unlockPreferredAccount(); - bool checkAccountDirectory(); - - // Paths. - /** - * @brief PathDataDirectory - * @param check if set to true and directory does not exist, return empty string - * @return path where global platform independent files are stored, like bdboot.txt or webinterface files - */ - static std::string PathDataDirectory(bool check = true); - - /** - * @brief PathBaseDirectory - * @return path where user data is stored ( on Linux and similar - * systems it is usually something like /home/USERNAME/.retroshare ). - */ - static std::string PathBaseDirectory(); - - // PGP Path is only dependent on BaseDirectory. - std::string PathPGPDirectory(); - - // Generate a new account based on a given PGP key returns its SSL id and sets it to be the preferred account. - - bool GenerateSSLCertificate(const RsPgpId& gpg_id, const std::string& org, const std::string& loc, const std::string& country, bool ishiddenloc, bool is_auto_tor,const std::string& passwd, RsPeerId &sslId, std::string &errString); - - // PGP Accounts. - - int GetPGPLogins(std::list &pgpIds); - int GetPGPLoginDetails(const RsPgpId& id, std::string &name, std::string &email); - bool GeneratePGPCertificate(const std::string&, const std::string& email, const std::string& passwd, RsPgpId &pgpId, const int keynumbits, std::string &errString); - bool SelectPGPAccount(const RsPgpId& pgpId); - - // PGP Support Functions. - bool exportIdentity(const std::string& fname,const RsPgpId& pgp_id) ; - bool importIdentity(const std::string& fname,RsPgpId& imported_pgp_id,std::string& import_error) ; - bool exportIdentityToString( - std::string& data, const RsPgpId& pgpId, bool includeSignatures, - std::string& errorMsg ); - bool importIdentityFromString(const std::string& data,RsPgpId& imported_pgp_id,std::string& import_error) ; - void getUnsupportedKeys(std::map > &unsupported_keys); - bool copyGnuPGKeyrings() ; - - // Selecting Rs Account. - bool getAccountIds(std::list &ids); - bool selectAccountByString(const std::string &prefUserString); - bool selectId(const RsPeerId& preferredId); - bool storePreferredAccount(); - bool loadPreferredAccount(); - - // Details of current Rs Account. - bool getCurrentAccountId(RsPeerId &id); - bool getCurrentAccountDetails(const RsPeerId &id, RsPgpId& gpgId, std::string &gpgName, std::string &gpgEmail, std::string &location); - bool getCurrentAccountOptions(bool &ishidden, bool &isautotor, bool &isFirstTimeRun); - - std::string getCurrentAccountPathAccountDirectory(); - std::string getCurrentAccountPathAccountKeysDirectory(); - std::string getCurrentAccountPathKeyFile(); - std::string getCurrentAccountPathCertFile(); - std::string getCurrentAccountLocationName(); - - - private: - bool checkPreferredId(); - - static bool defaultBaseDirectory(); - - bool getAvailableAccounts(std::map &accounts, - int& failing_accounts, - std::map >& unsupported_keys, bool hidden_only=false); - - bool setupAccount(const std::string& accountdir); - - private: - - bool mAccountsLocked; - - std::map mAccounts; - RsPeerId mPreferredId; - static std::string mBaseDirectory; - - std::map > mUnsupportedKeys ; -}; - - diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc deleted file mode 100644 index 8449a9e3e..000000000 --- a/libretroshare/src/rsserver/rsinit.cc +++ /dev/null @@ -1,2073 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsinit.cc * - * * - * Copyright (C) 2004-2014 Robert Fernie * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -/// RetroShare initialization and login API implementation - -#include - -#ifndef WINDOWS_SYS -// for locking instances -#include -#else -#include "util/rswin.h" -#endif - -#ifdef __ANDROID__ -# include // To install bdboot.txt -# include // for QString::fromStdString(...) -#endif - -#include "util/argstream.h" -#include "util/rsdebug.h" -#include "util/rsdir.h" -#include "util/rsrandom.h" -#include "util/folderiterator.h" -#include "util/rsstring.h" -#include "retroshare/rsinit.h" -#include "retroshare/rsnotify.h" -#include "retroshare/rsiface.h" -#include "plugins/pluginmanager.h" -#include "retroshare/rsversion.h" -#include "rsserver/rsloginhandler.h" -#include "rsserver/rsaccounts.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include "gxstunnel/p3gxstunnel.h" -#include "retroshare/rsgxsdistsync.h" -#include "file_sharing/p3filelists.h" - -#define ENABLE_GROUTER - -#if (defined(__unix__) || defined(unix)) && !defined(USG) -#include -#endif - -// This needs to be defined here, because when USE_BITDHT is unset, the variable, that is defined in libbitdht (not compiled!) will be missing. -#ifndef RS_USE_BITDHT -RsDht *rsDht = NULL ; -#endif - -// for blocking signals -#include - -#include - -#include "pqi/authssl.h" -#include "pqi/sslfns.h" -#include "pqi/authgpg.h" - -#ifdef ENABLE_GROUTER -#include "grouter/p3grouter.h" -#endif - -#ifdef RS_USE_DHT_STUNNER -#include "tcponudp/udpstunner.h" -#endif // RS_USE_DHT_STUNNER - -#ifdef RS_GXS_TRANS -# include "gxstrans/p3gxstrans.h" -#endif - -#ifdef RS_JSONAPI -# include "jsonapi/jsonapi.h" -#endif - -#ifdef RS_BROADCAST_DISCOVERY -# include "retroshare/rsbroadcastdiscovery.h" -# include "services/broadcastdiscoveryservice.h" -#endif // def RS_BROADCAST_DISCOVERY - -// #define GPG_DEBUG -// #define AUTHSSL_DEBUG -// #define FIM_DEBUG -// #define DEBUG_RSINIT - -//std::map > RsInit::unsupported_keys ; - -RsLoginHelper* rsLoginHelper = nullptr; - -RsAccounts* rsAccounts = nullptr; - -const RsInitErrorCategory RsInitErrorCategory::instance; - -RsConfigOptions::RsConfigOptions() - : - autoLogin(false), - udpListenerOnly(false), - forcedInetAddress("127.0.0.1"), /* inet address to use.*/ - forcedPort(0), - outStderr(false), - debugLevel(5) -#ifdef RS_JSONAPI - ,jsonApiPort(0) // JSonAPI server is enabled in each main() - ,jsonApiBindAddress("127.0.0.1") -#endif -{ -} - - -struct RsInitConfig -{ - RsInitConfig() -#ifdef RS_JSONAPI - : jsonApiPort(JsonApiServer::DEFAULT_PORT), - jsonApiBindAddress("127.0.0.1") -#endif - {} - - RsFileHash main_executable_hash; - -#ifdef WINDOWS_SYS - bool portable; - bool isWindowsXP; -#endif - rs_lock_handle_t lockHandle; - - std::string passwd; - std::string gxs_passwd; - - bool autoLogin; /* autoLogin allowed */ - bool startMinimised; /* Icon or Full Window */ - - /* Key Parameters that must be set before - * RetroShare will start up: - */ - - /* Listening Port */ - bool forceExtPort; - bool forceLocalAddr; - unsigned short port; - std::string inet ; - - /* v0.6 features */ - bool hiddenNodeSet; - std::string hiddenNodeAddress; - uint16_t hiddenNodePort; - - bool hiddenNodeI2PBOB; - - /* Logging */ - bool haveLogFile; - bool outStderr; - int debugLevel; - std::string logfname; - - bool udpListenerOnly; - std::string opModeStr; - std::string optBaseDir; - - uint16_t jsonApiPort; - std::string jsonApiBindAddress; -}; - -static RsInitConfig* rsInitConfig = nullptr; - -static const std::string configLogFileName = "retro.log"; -static const int SSLPWD_LEN = 64; - -void RsInit::InitRsConfig() -{ - RsInfo() << " libretroshare version: " << RS_HUMAN_READABLE_VERSION - << std::endl; - - rsInitConfig = new RsInitConfig; - - - /* TODO almost all of this should be moved to RsInitConfig::RsInitConfig - * initializers */ - - /* Directories */ -#ifdef WINDOWS_SYS - rsInitConfig->portable = false; - rsInitConfig->isWindowsXP = false; -#endif - /* v0.6 features */ - rsInitConfig->hiddenNodeSet = false; - - - // This doesn't seems a configuration... -#ifndef WINDOWS_SYS - rsInitConfig->lockHandle = -1; -#else - rsInitConfig->lockHandle = NULL; -#endif - - rsInitConfig->port = 0 ; - rsInitConfig->forceLocalAddr = false; - rsInitConfig->haveLogFile = false; - rsInitConfig->outStderr = false; - rsInitConfig->forceExtPort = false; - - rsInitConfig->inet = std::string("127.0.0.1"); - - rsInitConfig->autoLogin = false; // . - rsInitConfig->startMinimised = false; - rsInitConfig->passwd = ""; - rsInitConfig->debugLevel = PQL_WARNING; - rsInitConfig->udpListenerOnly = false; - rsInitConfig->opModeStr = std::string(""); - -#ifdef WINDOWS_SYS - // test for portable version - if (GetFileAttributes(L"portable") != (DWORD) -1) { - // use portable version - rsInitConfig->portable = true; - } - - // test for Windows XP - OSVERSIONINFOEX osvi; - memset(&osvi, 0, sizeof(osvi)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - - if (GetVersionEx((OSVERSIONINFO*) &osvi)) { - if (osvi.dwMajorVersion == 5) { - if (osvi.dwMinorVersion == 1) { - /* Windows XP */ - rsInitConfig->isWindowsXP = true; - } else if (osvi.dwMinorVersion == 2) { - SYSTEM_INFO si; - memset(&si, 0, sizeof(si)); - GetSystemInfo(&si); - if (osvi.wProductType == VER_NT_WORKSTATION && si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) { - /* Windows XP Professional x64 Edition */ - rsInitConfig->isWindowsXP = true; - } - } - } - } - - if (rsInitConfig->isWindowsXP) { - std::cerr << "Running Windows XP" << std::endl; - } else { - std::cerr << "Not running Windows XP" << std::endl; - } -#endif - - setOutputLevel(RsLog::Warning); -} - -#ifdef LOCALNET_TESTING - -std::string portRestrictions; -bool doPortRestrictions = false; - -#endif - -#ifdef WINDOWS_SYS -#ifdef PTW32_STATIC_LIB -#include -#endif -#endif - -/******** - * LOCALNET_TESTING - allows port restrictions - * - * #define LOCALNET_TESTING 1 - * - ********/ -int RsInit::InitRetroShare(const RsConfigOptions& conf) -{ - rsInitConfig->autoLogin = conf.autoLogin; - rsInitConfig->outStderr = conf.outStderr; - rsInitConfig->logfname = conf.logfname ; - rsInitConfig->inet = conf.forcedInetAddress ; - rsInitConfig->port = conf.forcedPort ; - rsInitConfig->debugLevel = conf.debugLevel; - rsInitConfig->udpListenerOnly = conf.udpListenerOnly; - rsInitConfig->optBaseDir = conf.optBaseDir; - rsInitConfig->jsonApiPort = conf.jsonApiPort; - rsInitConfig->jsonApiBindAddress = conf.jsonApiBindAddress; - -#ifdef PTW32_STATIC_LIB - // for static PThreads under windows... we need to init the library... - pthread_win32_process_attach_np(); -#endif - if( rsInitConfig->autoLogin) rsInitConfig->startMinimised = true ; - if( rsInitConfig->outStderr) rsInitConfig->haveLogFile = false ; - if(!rsInitConfig->logfname.empty()) rsInitConfig->haveLogFile = true; - if( rsInitConfig->inet != "127.0.0.1") rsInitConfig->forceLocalAddr = true; - if( rsInitConfig->port != 0) rsInitConfig->forceLocalAddr = true; // previously forceExtPort, which means nothing in this case -#ifdef LOCALNET_TESTING - if(!portRestrictions.empty()) doPortRestrictions = true; -#endif - - setOutputLevel((RsLog::logLvl)rsInitConfig->debugLevel); - - // set the debug file. - if (rsInitConfig->haveLogFile) - setDebugFile(rsInitConfig->logfname.c_str()); - - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif - /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - // SWITCH off the SIGPIPE - kills process on Linux. - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - struct sigaction sigact; - sigact.sa_handler = SIG_IGN; - sigact.sa_flags = 0; - - sigset_t set; - sigemptyset(&set); - //sigaddset(&set, SIGINT); // or whatever other signal - sigact.sa_mask = set; - - if (0 == sigaction(SIGPIPE, &sigact, NULL)) - { - std::cerr << "RetroShare:: Successfully installed the SIGPIPE Block" << std::endl; - } - else - { - std::cerr << "RetroShare:: Failed to install the SIGPIPE Block" << std::endl; - } -#endif - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - // Hash the main executable. - - uint64_t tmp_size ; - - if(conf.main_executable_path.empty()) - { - std::cerr << "Executable path is unknown. It should normally have been set in passed RsConfigOptions structure" << std::endl; - return 1; - } - if(!RsDirUtil::getFileHash(conf.main_executable_path,rsInitConfig->main_executable_hash,tmp_size,NULL)) - std::cerr << "Cannot hash executable! Plugins will not be loaded correctly." << std::endl; - else - std::cerr << "Hashed main executable: " << rsInitConfig->main_executable_hash << std::endl; - - /* At this point we want to. - * 1) Load up Dase Directory. - * 3) Get Prefered Id. - * 2) Get List of Available Accounts. - * 4) Get List of GPG Accounts. - */ - /* Initialize AuthSSL */ - AuthSSL::instance().InitAuth(nullptr, nullptr, nullptr, ""); - - rsLoginHelper = new RsLoginHelper; - - int error_code ; - - if(!RsAccounts::init(rsInitConfig->optBaseDir,error_code)) - return error_code ; - -#ifdef RS_JSONAPI - // We create the JsonApiServer this early, because it is needed *before* login - RsDbg() << __PRETTY_FUNCTION__ - << " Allocating JSON API server (not launched yet)" << std::endl; - JsonApiServer* jas = new JsonApiServer(); - jas->setListeningPort(conf.jsonApiPort); - jas->setBindingAddress(conf.jsonApiBindAddress); - - if(conf.jsonApiPort != 0) jas->restart(); - - rsJsonApi = jas; -#endif - -#ifdef RS_AUTOLOGIN - /* check that we have selected someone */ - RsPeerId preferredId; - bool existingUser = RsAccounts::GetPreferredAccountId(preferredId); - - if (existingUser) - { - if(RsLoginHandler::getSSLPassword(preferredId,false,rsInitConfig->passwd)) - { - RsInit::setAutoLogin(true); - std::cerr << "Autologin has succeeded" << std::endl; - return RS_INIT_HAVE_ACCOUNT; - } - } -#endif - - return RS_INIT_OK; -} - - -/* - * To prevent several running instances from using the same directory - * simultaneously we have to use a global lock. - * We use a lock file on Unix systems. - * - * Return value: - * 0 : Success - * 1 : Another instance already has the lock - * 2 : Unexpected error - */ -RsInit::LoadCertificateStatus RsInit::LockConfigDirectory( - const std::string& accountDir, std::string& lockFilePath ) -{ - const std::string lockFile = accountDir + "/" + "lock"; - lockFilePath = lockFile; - - int rt = RsDirUtil::createLockFile(lockFile,rsInitConfig->lockHandle); - - switch (rt) - { - case 0: return RsInit::OK; - case 1: return RsInit::ERR_ALREADY_RUNNING; - case 2: return RsInit::ERR_CANT_ACQUIRE_LOCK; - default: return RsInit::ERR_UNKNOWN; - } -} - -/* - * Unlock the currently locked profile, if there is one. - * For Unix systems we simply close the handle of the lock file. - */ -void RsInit::UnlockConfigDirectory() -{ - RsDirUtil::releaseLockFile(rsInitConfig->lockHandle) ; -} - - - - -bool RsInit::collectEntropy(uint32_t n) -{ - RAND_seed(&n,4) ; - - return true ; -} - -/***************************** FINAL LOADING OF SETUP *************************/ - - - /* Login SSL */ -bool RsInit::LoadPassword(const std::string& inPwd) -{ - rsInitConfig->passwd = inPwd; - return true; -} - -std::string RsInit::lockFilePath() -{ - return RsAccounts::AccountDirectory() + "/lock" ; -} - -RsInit::LoadCertificateStatus RsInit::LockAndLoadCertificates( - bool autoLoginNT, std::string& lockFilePath ) -{ - try - { - if (!RsAccounts::lockPreferredAccount()) - throw RsInit::ERR_UNKNOWN; // invalid PreferredAccount. - - // Logic that used to be external to RsInit... - RsPeerId accountId; - if (!RsAccounts::GetPreferredAccountId(accountId)) - throw RsInit::ERR_UNKNOWN; // invalid PreferredAccount; - - RsPgpId pgpId; - std::string pgpName, pgpEmail, location; - - if(!RsAccounts::GetAccountDetails(accountId, pgpId, pgpName, pgpEmail, location)) - throw RsInit::ERR_UNKNOWN; // invalid PreferredAccount; - - if(0 == AuthGPG::getAuthGPG() -> GPGInit(pgpId)) - throw RsInit::ERR_UNKNOWN; // PGP Error. - - LoadCertificateStatus retVal = - LockConfigDirectory(RsAccounts::AccountDirectory(), lockFilePath); - - if(retVal > 0) - throw retVal ; - - if(LoadCertificates(autoLoginNT) != 1) - { - UnlockConfigDirectory(); - throw RsInit::ERR_UNKNOWN; - } - - return RsInit::OK; - } - catch(LoadCertificateStatus retVal) - { - RsAccounts::unlockPreferredAccount(); - return retVal ; - } -} - - -/** *************************** FINAL LOADING OF SETUP ************************* - * Requires: - * PGPid to be selected (Password not required). - * CertId to be selected (Password Required). - * - * Return value: - * 0 : unexpected error - * 1 : success - */ -int RsInit::LoadCertificates(bool autoLoginNT) -{ - RsPeerId preferredId; - if (!RsAccounts::GetPreferredAccountId(preferredId)) - { - std::cerr << "No Account Selected" << std::endl; - return 0; - } - - - if (RsAccounts::AccountPathCertFile() == "") - { - std::cerr << "RetroShare needs a certificate" << std::endl; - return 0; - } - - if (RsAccounts::AccountPathKeyFile() == "") - { - std::cerr << "RetroShare needs a key" << std::endl; - return 0; - } - - //check if password is already in memory - - if(rsInitConfig->passwd == "") { - if (RsLoginHandler::getSSLPassword(preferredId,true,rsInitConfig->passwd) == false) { -#ifdef DEBUG_RSINIT - std::cerr << "RsLoginHandler::getSSLPassword() Failed!"; -#endif - return 0 ; - } - } else { - if (RsLoginHandler::checkAndStoreSSLPasswdIntoGPGFile(preferredId,rsInitConfig->passwd) == false) { - std::cerr << "RsLoginHandler::checkAndStoreSSLPasswdIntoGPGFile() Failed!"; - return 0; - } - } - - std::cerr << "rsAccounts->PathKeyFile() : " << RsAccounts::AccountPathKeyFile() << std::endl; - - if(0 == AuthSSL::getAuthSSL() -> InitAuth(RsAccounts::AccountPathCertFile().c_str(), RsAccounts::AccountPathKeyFile().c_str(), rsInitConfig->passwd.c_str(), - RsAccounts::AccountLocationName())) - { - std::cerr << "SSL Auth Failed!"; - return 0 ; - } - -#ifdef RS_AUTOLOGIN - if(autoLoginNT) - { - std::cerr << "RetroShare will AutoLogin next time" << std::endl; - - RsLoginHandler::enableAutoLogin(preferredId,rsInitConfig->passwd); - rsInitConfig->autoLogin = true ; - } -#else - (void) autoLoginNT; -#endif // RS_AUTOLOGIN - - /* wipe out password */ - - // store pword to allow gxs use it to services' key their databases - // ideally gxs should have its own password - rsInitConfig->gxs_passwd = rsInitConfig->passwd; - rsInitConfig->passwd = ""; - - RsAccounts::storeSelectedAccount(); - return 1; -} - -#ifdef RS_AUTOLOGIN -bool RsInit::RsClearAutoLogin() -{ - RsPeerId preferredId; - if (!RsAccounts::GetPreferredAccountId(preferredId)) - { - std::cerr << "RsInit::RsClearAutoLogin() No Account Selected" << std::endl; - return 0; - } - return RsLoginHandler::clearAutoLogin(preferredId); -} -#endif // RS_AUTOLOGIN - - -bool RsInit::isPortable() -{ -#ifdef WINDOWS_SYS - return rsInitConfig->portable; -#else - return false; -#endif -} - -bool RsInit::isWindowsXP() -{ -#ifdef WINDOWS_SYS - return rsInitConfig->isWindowsXP; -#else - return false; -#endif -} - -bool RsInit::getStartMinimised() -{ - return rsInitConfig->startMinimised; -} - -int RsInit::getSslPwdLen(){ - return SSLPWD_LEN; -} - -bool RsInit::getAutoLogin(){ - return rsInitConfig->autoLogin; -} - -void RsInit::setAutoLogin(bool autoLogin){ - rsInitConfig->autoLogin = autoLogin; -} - -/* Setup Hidden Location; */ -void RsInit::SetHiddenLocation(const std::string& hiddenaddress, uint16_t port, bool useBob) -{ - /* parse the bugger (todo) */ - rsInitConfig->hiddenNodeSet = true; - rsInitConfig->hiddenNodeAddress = hiddenaddress; - rsInitConfig->hiddenNodePort = port; - rsInitConfig->hiddenNodeI2PBOB = useBob; -} - - -/* - * - * Init Part of RsServer... needs the private - * variables so in the same file. - * - */ - -#include -//#include - -#include "ft/ftserver.h" -#include "ft/ftcontroller.h" - -#include "retroshare/rsiface.h" -#include "retroshare/rsturtle.h" - -/* global variable now points straight to - * ft/ code so variable defined here. - */ - -RsFiles *rsFiles = NULL; -RsTurtle *rsTurtle = NULL ; -RsReputations *rsReputations = NULL ; -#ifdef ENABLE_GROUTER -RsGRouter *rsGRouter = NULL ; -#endif - -#include "pqi/pqipersongrp.h" -#include "pqi/pqisslpersongrp.h" -#include "pqi/pqiloopback.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/p3historymgr.h" - -#include "util/rsdebug.h" -#include "util/rsdir.h" -#include "util/rsrandom.h" - -#ifdef RS_USE_LIBUPNP -# include "rs_upnp/upnphandler_libupnp.h" -#else // def RS_USE_LIBUPNP -# include "rs_upnp/upnphandler_miniupnp.h" -#endif // def RS_USE_LIBUPNP - -#include "services/autoproxy/p3i2pbob.h" -#include "services/autoproxy/rsautoproxymonitor.h" - -#include "services/p3gxsreputation.h" -#include "services/p3serviceinfo.h" -#include "services/p3heartbeat.h" -#include "gossipdiscovery/p3gossipdiscovery.h" -#include "services/p3msgservice.h" -#include "services/p3statusservice.h" - -#include "turtle/p3turtle.h" -#include "chat/p3chatservice.h" - -#ifdef RS_ENABLE_GXS -// NEW GXS SYSTEMS. -#include "gxs/rsdataservice.h" -#include "gxs/rsgxsnetservice.h" -#include "retroshare/rsgxsflags.h" - -#include "pgp/pgpauxutils.h" -#include "services/p3idservice.h" -#include "services/p3gxscircles.h" -#include "services/p3posted.h" -#include "services/p3gxsforums.h" -#include "services/p3gxschannels.h" - -#include "services/p3wiki.h" -#include "services/p3wire.h" -#include "services/p3photoservice.h" - -#endif // RS_ENABLE_GXS - - -#include -#include - -// for blocking signals -#include - -/* Implemented Rs Interfaces */ -#include "rsserver/p3face.h" -#include "rsserver/p3peers.h" -#include "rsserver/p3msgs.h" -#include "rsserver/p3status.h" -#include "rsserver/p3history.h" -#include "rsserver/p3serverconfig.h" - - -#include "pqi/p3notify.h" // HACK - moved to pqi for compilation order. - -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" - -#include "tcponudp/tou.h" -#include "tcponudp/rsudpstack.h" - -#ifdef RS_USE_BITDHT -#include "dht/p3bitdht.h" -#ifdef RS_USE_DHT_STUNNER -#include "dht/stunaddrassist.h" -#endif // RS_USE_DHT_STUNNER - -#include "udp/udpstack.h" -#include "tcponudp/udppeer.h" -#include "tcponudp/udprelay.h" -#endif - -/**** - * #define RS_RELEASE 1 - * #define RS_RTT 1 -****/ - -#define RS_RELEASE 1 -#define RS_RTT 1 - - -#ifdef RS_RTT -#include "services/p3rtt.h" -#endif - - -#include "services/p3banlist.h" -#include "services/p3bwctrl.h" - -#ifdef SERVICES_DSDV -#include "services/p3dsdv.h" -#endif - -RsControl *RsControl::instance() -{ - static RsServer rsicontrol; - return &rsicontrol; -} - - -/* - * The Real RetroShare Startup Function. - */ - -int RsServer::StartupRetroShare() -{ - RsPeerId ownId = AuthSSL::getAuthSSL()->OwnId(); - - std::cerr << "========================================================================" << std::endl; - std::cerr << "== RsInit:: starting up Retroshare core ==" << std::endl; - std::cerr << "== ==" << std::endl; - std::cerr << "== Account/SSL ID : " << ownId << " ==" << std::endl; - std::cerr << "== Node type : " << (RsAccounts::isHiddenNode()?"Hidden":"Normal") << " ==" << std::endl; - if(RsAccounts::isHiddenNode()) - std::cerr << "== Tor/I2P configuration : " << (RsAccounts::isTorAuto()?"Tor Auto":"Manual ") << " ==" << std::endl; - std::cerr << "========================================================================" << std::endl; - - /**************************************************************************/ - /* STARTUP procedure */ - /**************************************************************************/ - /**************************************************************************/ - /* (1) Load up own certificate (DONE ALREADY) - just CHECK */ - /**************************************************************************/ - - if (1 != AuthSSL::getAuthSSL() -> InitAuth(NULL, NULL, NULL, "")) - { - std::cerr << "main() - Fatal Error....." << std::endl; - std::cerr << "Invalid Certificate configuration!" << std::endl; - std::cerr << std::endl; - return false ; - } - - /**************************************************************************/ - /* Any Initial Configuration (Commandline Options) */ - /**************************************************************************/ - - /* set the debugging to crashMode */ - std::cerr << "set the debugging to crashMode." << std::endl; - if ((!rsInitConfig->haveLogFile) && (!rsInitConfig->outStderr)) - { - std::string crashfile = RsAccounts::AccountDirectory(); - crashfile += "/" + configLogFileName; - setDebugCrashMode(crashfile.c_str()); - } - - unsigned long flags = 0; - if (rsInitConfig->udpListenerOnly) - { - flags |= PQIPERSON_NO_LISTENER; - } - - /* check account directory */ - if (!RsAccounts::checkCreateAccountDirectory()) - { - std::cerr << "RsServer::StartupRetroShare() - Fatal Error....." << std::endl; - std::cerr << "checkAccount failed!" << std::endl; - std::cerr << std::endl; - return 0; - } - - /**************************************************************************/ - // Load up Certificates, and Old Configuration (if present) - std::cerr << "Load up Certificates, and Old Configuration (if present)." << std::endl; - - std::string emergencySaveDir = RsAccounts::AccountDirectory(); - std::string emergencyPartialsDir = RsAccounts::AccountDirectory(); - if (emergencySaveDir != "") - { - emergencySaveDir += "/"; - emergencyPartialsDir += "/"; - } - emergencySaveDir += "Downloads"; - emergencyPartialsDir += "Partials"; - - /**************************************************************************/ - /* setup Configuration */ - /**************************************************************************/ - std::cerr << "Load Configuration" << std::endl; - - mConfigMgr = new p3ConfigMgr(RsAccounts::AccountDirectory()); - mGeneralConfig = new p3GeneralConfig(); - - // Get configuration options from rsAccounts. - bool isHiddenNode = false; - bool isFirstTimeRun = false; - bool isTorAuto = false; - - RsAccounts::getCurrentAccountOptions(isHiddenNode,isTorAuto, isFirstTimeRun); - - /**************************************************************************/ - /* setup classes / structures */ - /**************************************************************************/ - std::cerr << "setup classes / structures" << std::endl; - - /* History Manager */ - mHistoryMgr = new p3HistoryMgr(); - mPeerMgr = new p3PeerMgrIMPL( AuthSSL::getAuthSSL()->OwnId(), - AuthGPG::getAuthGPG()->getGPGOwnId(), - AuthGPG::getAuthGPG()->getGPGOwnName(), - AuthSSL::getAuthSSL()->getOwnLocation()); - mNetMgr = new p3NetMgrIMPL(); - mLinkMgr = new p3LinkMgrIMPL(mPeerMgr, mNetMgr); - - /* Setup Notify Early - So we can use it. */ - rsPeers = new p3Peers(mLinkMgr, mPeerMgr, mNetMgr); - - mPeerMgr->setManagers(mLinkMgr, mNetMgr); - mNetMgr->setManagers(mPeerMgr, mLinkMgr); - - rsAutoProxyMonitor *autoProxy = rsAutoProxyMonitor::instance(); -#ifdef RS_USE_I2P_BOB - mI2pBob = new p3I2pBob(mPeerMgr); - autoProxy->addProxy(autoProxyType::I2PBOB, mI2pBob); -#endif - - //load all the SSL certs as friends - // std::list sslIds; - // AuthSSL::getAuthSSL()->getAuthenticatedList(sslIds); - // for (std::list::iterator sslIdsIt = sslIds.begin(); sslIdsIt != sslIds.end(); ++sslIdsIt) { - // mConnMgr->addFriend(*sslIdsIt); - // } - //p3DhtMgr *mDhtMgr = new OpenDHTMgr(ownId, mConnMgr, rsInitConfig->configDir); - /**************************** BITDHT ***********************************/ - - // Make up an address. XXX - - struct sockaddr_in tmpladdr; - sockaddr_clear(&tmpladdr); - tmpladdr.sin_port = htons(rsInitConfig->port); - - rsUdpStack *mDhtStack = NULL ; - - if(!RsAccounts::isHiddenNode()) - { -#ifdef LOCALNET_TESTING - - mDhtStack = new rsUdpStack(UDP_TEST_RESTRICTED_LAYER, tmpladdr); - - /* parse portRestrictions */ - unsigned int lport, uport; - - if (doPortRestrictions) - { - if (2 == sscanf(portRestrictions.c_str(), "%u-%u", &lport, &uport)) - { - std::cerr << "Adding Port Restriction (" << lport << "-" << uport << ")"; - std::cerr << std::endl; - } - else - { - std::cerr << "Failed to parse Port Restrictions ... exiting"; - std::cerr << std::endl; - exit(1); - } - - RestrictedUdpLayer *url = (RestrictedUdpLayer *) mDhtStack->getUdpLayer(); - url->addRestrictedPortRange(lport, uport); - } -#else //LOCALNET_TESTING -#ifdef RS_USE_BITDHT - mDhtStack = new rsUdpStack(tmpladdr); -#endif -#endif //LOCALNET_TESTING - } - -#ifdef RS_USE_BITDHT - -#define BITDHT_BOOTSTRAP_FILENAME "bdboot.txt" -#define BITDHT_FILTERED_IP_FILENAME "bdfilter.txt" - - - std::string bootstrapfile = RsAccounts::AccountDirectory(); - if (bootstrapfile != "") - bootstrapfile += "/"; - bootstrapfile += BITDHT_BOOTSTRAP_FILENAME; - - std::string installfile = ""; -#ifndef __ANDROID__ - installfile = RsAccounts::systemDataDirectory(); - installfile += "/"; - installfile += BITDHT_BOOTSTRAP_FILENAME; -#endif - - std::string filteredipfile = RsAccounts::AccountDirectory(); - if (filteredipfile != "") - filteredipfile += "/"; - filteredipfile += BITDHT_FILTERED_IP_FILENAME; - - std::cerr << "Checking for DHT bootstrap file: " << bootstrapfile << std::endl; - - /* check if bootstrap file exists... - * if not... copy from dataDirectory - */ - - uint64_t tmp_size ; - if (!RsDirUtil::checkFile(bootstrapfile,tmp_size,true)) - { - std::cerr << "DHT bootstrap file not in ConfigDir: " << bootstrapfile - << std::endl; -#ifdef __ANDROID__ - QFile bdbootRF("assets:/values/bdboot.txt"); - if(!bdbootRF.open(QIODevice::ReadOnly | QIODevice::Text)) - std::cerr << __PRETTY_FUNCTION__ - << " bdbootRF(assets:/values/bdboot.txt).open(...) fail: " - << bdbootRF.errorString().toStdString() << std::endl; - else - { - QFile bdbootCF(QString::fromStdString(bootstrapfile)); - if(!bdbootCF.open(QIODevice::WriteOnly | QIODevice::Text)) - std::cerr << __PRETTY_FUNCTION__ << " bdbootCF(" - << bootstrapfile << ").open(...) fail: " - << bdbootRF.errorString().toStdString() << std::endl; - else - { - bdbootCF.write(bdbootRF.readAll()); - bdbootCF.close(); - std::cerr << "Installed DHT bootstrap file not in ConfigDir: " - << bootstrapfile << std::endl; - } - - bdbootRF.close(); - } -#else - std::cerr << "Checking for Installation DHT bootstrap file " << installfile << std::endl; - if ((installfile != "") && (RsDirUtil::checkFile(installfile,tmp_size))) - { - std::cerr << "Copying Installation DHT bootstrap file..." << std::endl; - if (RsDirUtil::copyFile(installfile, bootstrapfile)) - { - std::cerr << "Installed DHT bootstrap file in configDir" << std::endl; - } - else - { - std::cerr << "Failed Installation DHT bootstrap file..." << std::endl; - } - } - else - { - std::cerr << "No Installation DHT bootstrap file to copy" << std::endl; - } -#endif // def __ANDROID__ - } - - /* construct the rest of the stack, important to build them in the correct order! */ - /* MOST OF THIS IS COMMENTED OUT UNTIL THE REST OF libretroshare IS READY FOR IT! */ - - p3BitDht *mBitDht = NULL ; - rsDht = NULL ; - rsFixedUdpStack *mProxyStack = NULL ; - - if(!RsAccounts::isHiddenNode()) - { - UdpSubReceiver *udpReceivers[RSUDP_NUM_TOU_RECVERS]; - int udpTypes[RSUDP_NUM_TOU_RECVERS]; - -#ifdef RS_USE_DHT_STUNNER - // FIRST DHT STUNNER. - UdpStunner *mDhtStunner = new UdpStunner(mDhtStack); - mDhtStunner->setTargetStunPeriod(300); /* slow (5mins) */ - mDhtStack->addReceiver(mDhtStunner); - -#ifdef LOCALNET_TESTING - mDhtStunner->SetAcceptLocalNet(); -#endif -#endif // RS_USE_DHT_STUNNER - - - // NEXT BITDHT. - - - mBitDht = new p3BitDht(ownId, mLinkMgr, mNetMgr, mDhtStack, bootstrapfile, installfile, filteredipfile); - - // NEXT THE RELAY (NEED to keep a reference for installing RELAYS) - UdpRelayReceiver *mRelay = new UdpRelayReceiver(mDhtStack); - udpReceivers[RSUDP_TOU_RECVER_RELAY_IDX] = mRelay; /* RELAY Connections (DHT Port) */ - udpTypes[RSUDP_TOU_RECVER_RELAY_IDX] = TOU_RECEIVER_TYPE_UDPRELAY; - mDhtStack->addReceiver(udpReceivers[RSUDP_TOU_RECVER_RELAY_IDX]); - - // LAST ON THIS STACK IS STANDARD DIRECT TOU - udpReceivers[RSUDP_TOU_RECVER_DIRECT_IDX] = new UdpPeerReceiver(mDhtStack); /* standard DIRECT Connections (DHT Port) */ - udpTypes[RSUDP_TOU_RECVER_DIRECT_IDX] = TOU_RECEIVER_TYPE_UDPPEER; - mDhtStack->addReceiver(udpReceivers[RSUDP_TOU_RECVER_DIRECT_IDX]); - - /* install external Pointer for Interface */ - rsDht = mBitDht; - - // NOW WE BUILD THE SECOND STACK. - // Create the Second UdpStack... Port should be random (but openable!). - // We do this by binding to xx.xx.xx.xx:0 which which gives us a random port. - - struct sockaddr_in sndladdr; - sockaddr_clear(&sndladdr); - -#ifdef LOCALNET_TESTING - - // // HACK Proxy Port near Dht Port - For Relay Testing. - // uint16_t rndport = rsInitConfig->port + 3; - // sndladdr.sin_port = htons(rndport); - - mProxyStack = new rsFixedUdpStack(UDP_TEST_RESTRICTED_LAYER, sndladdr); - - /* portRestrictions already parsed */ - if (doPortRestrictions) - { - RestrictedUdpLayer *url = (RestrictedUdpLayer *) mProxyStack->getUdpLayer(); - url->addRestrictedPortRange(lport, uport); - } -#else - mProxyStack = new rsFixedUdpStack(sndladdr); -#endif - -#ifdef RS_USE_DHT_STUNNER - // FIRSTLY THE PROXY STUNNER. - UdpStunner *mProxyStunner = new UdpStunner(mProxyStack); - mProxyStunner->setTargetStunPeriod(300); /* slow (5mins) */ - mProxyStack->addReceiver(mProxyStunner); - -#ifdef LOCALNET_TESTING - mProxyStunner->SetAcceptLocalNet(); -#endif -#endif // RS_USE_DHT_STUNNER - - - // FINALLY THE PROXY UDP CONNECTIONS - udpReceivers[RSUDP_TOU_RECVER_PROXY_IDX] = new UdpPeerReceiver(mProxyStack); /* PROXY Connections (Alt UDP Port) */ - udpTypes[RSUDP_TOU_RECVER_PROXY_IDX] = TOU_RECEIVER_TYPE_UDPPEER; - mProxyStack->addReceiver(udpReceivers[RSUDP_TOU_RECVER_PROXY_IDX]); - - // REAL INITIALISATION - WITH THREE MODES - tou_init((void **) udpReceivers, udpTypes, RSUDP_NUM_TOU_RECVERS); - -#ifdef RS_USE_DHT_STUNNER - mBitDht->setupConnectBits(mDhtStunner, mProxyStunner, mRelay); -#else // RS_USE_DHT_STUNNER - mBitDht->setupConnectBits(mRelay); -#endif // RS_USE_DHT_STUNNER - -#ifdef RS_USE_DHT_STUNNER - mNetMgr->setAddrAssist(new stunAddrAssist(mDhtStunner), new stunAddrAssist(mProxyStunner)); -#endif // RS_USE_DHT_STUNNER - // #else //RS_USE_BITDHT - // /* install NULL Pointer for rsDht Interface */ - // rsDht = NULL; -#endif //RS_USE_BITDHT - } - - - /**************************** BITDHT ***********************************/ - - p3ServiceControl *serviceCtrl = new p3ServiceControl(mLinkMgr); - rsServiceControl = serviceCtrl; - - pqih = new pqisslpersongrp(serviceCtrl, flags, mPeerMgr); - //pqih = new pqipersongrpDummy(none, flags); - - serviceCtrl->setServiceServer(pqih) ; - - /****** New Ft Server **** !!! */ - ftServer *ftserver = new ftServer(mPeerMgr, serviceCtrl); - ftserver->setConfigDirectory(RsAccounts::AccountDirectory()); - - ftserver->SetupFtServer() ; - - /* setup any extra bits (Default Paths) */ - ftserver->setPartialsDirectory(emergencyPartialsDir); - ftserver->setDownloadDirectory(emergencySaveDir); - - /* This should be set by config ... there is no default */ - //ftserver->setSharedDirectories(fileList); - - rsFiles = ftserver; - - std::vector plugins_directories ; - -#ifdef __APPLE__ - plugins_directories.push_back(RsAccounts::systemDataDirectory()) ; -#endif -#if !defined(WINDOWS_SYS) && defined(PLUGIN_DIR) - plugins_directories.push_back(std::string(PLUGIN_DIR)) ; -#endif - std::string extensions_dir = RsAccounts::ConfigDirectory() + "/extensions6/" ; - plugins_directories.push_back(extensions_dir) ; - - if(!RsDirUtil::checkCreateDirectory(extensions_dir)) - std::cerr << "(EE) Cannot create extensions directory " << extensions_dir - << ". This is not mandatory, but you probably have a permission problem." << std::endl; - -#ifdef DEBUG_PLUGIN_SYSTEM - plugins_directories.push_back(".") ; // this list should be saved/set to some correct value. - // possible entries include: /usr/lib/retroshare, ~/.retroshare/extensions/, etc. -#endif - - mPluginsManager = new RsPluginManager(rsInitConfig->main_executable_hash) ; - rsPlugins = mPluginsManager ; - mConfigMgr->addConfiguration("plugins.cfg", mPluginsManager); - mPluginsManager->loadConfiguration() ; - - // These are needed to load plugins: plugin devs might want to know the place of - // cache directories, get pointers to cache strapper, or access ownId() - // - mPluginsManager->setServiceControl(serviceCtrl) ; - - // Now load the plugins. This parses the available SO/DLL files for known symbols. - // - mPluginsManager->loadPlugins(plugins_directories) ; - - // Also load some plugins explicitly. This is helpful for - // - developping plugins - // - std::vector programatically_inserted_plugins ; - - // Push your own plugins into this list, before the call: - // - // programatically_inserted_plugins.push_back(myCoolPlugin) ; - // - mPluginsManager->loadPlugins(programatically_inserted_plugins) ; - -#ifdef RS_JSONAPI - // add jsonapi server to config manager so that it can save/load its tokens - if(rsJsonApi) rsJsonApi->connectToConfigManager(*mConfigMgr); -#endif - - /**** Reputation system ****/ - - p3GxsReputation *mReputations = new p3GxsReputation(mLinkMgr) ; - rsReputations = mReputations ; - -#ifdef RS_ENABLE_GXS - - std::string currGxsDir = RsAccounts::AccountDirectory() + "/gxs"; - RsDirUtil::checkCreateDirectory(currGxsDir); - - RsNxsNetMgr* nxsMgr = new RsNxsNetMgrImpl(serviceCtrl); - - /**** GXS Dist sync service ****/ - -#ifdef RS_USE_GXS_DISTANT_SYNC - RsGxsNetTunnelService *mGxsNetTunnel = new RsGxsNetTunnelService ; - rsGxsDistSync = mGxsNetTunnel ; -#else - RsGxsNetTunnelService *mGxsNetTunnel = NULL ; -#endif - - /**** Identity service ****/ - - RsGeneralDataService* gxsid_ds = new RsDataService(currGxsDir + "/", "gxsid_db", - RS_SERVICE_GXS_TYPE_GXSID, NULL, rsInitConfig->gxs_passwd); - - // init gxs services - PgpAuxUtils *pgpAuxUtils = new PgpAuxUtilsImpl(); - p3IdService *mGxsIdService = new p3IdService(gxsid_ds, NULL, pgpAuxUtils); - - // circles created here, as needed by Ids. - RsGeneralDataService* gxscircles_ds = new RsDataService(currGxsDir + "/", "gxscircles_db", - RS_SERVICE_GXS_TYPE_GXSCIRCLE, NULL, rsInitConfig->gxs_passwd); - - // create GxsCircles - early, as IDs need it. - p3GxsCircles *mGxsCircles = new p3GxsCircles(gxscircles_ds, NULL, mGxsIdService, pgpAuxUtils); - - // create GXS ID service - RsGxsNetService* gxsid_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_GXSID, gxsid_ds, nxsMgr, - mGxsIdService, mGxsIdService->getServiceInfo(), - mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils,mGxsNetTunnel, - false,false,true); // don't synchronise group automatic (need explicit group request) - // don't sync messages at all. - // allow distsync, so that we can grab GXS id requests for other services - - // Normally we wouldn't need this (we do in other service): - // mGxsIdService->setNetworkExchangeService(gxsid_ns) ; - // ...since GxsIds are propagated manually. But that requires the gen exchange of GXSids to - // constantly test that mNetService is not null. The call below is to make the service aware of the - // netService so that it can request the missing ids. We'll need to fix this. - - mGxsIdService->setNes(gxsid_ns); - - /**** GxsCircle service ****/ - - // create GXS Circle service - RsGxsNetService* gxscircles_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_GXSCIRCLE, gxscircles_ds, nxsMgr, - mGxsCircles, mGxsCircles->getServiceInfo(), - mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils); - - mGxsCircles->setNetworkExchangeService(gxscircles_ns) ; - - /**** Posted GXS service ****/ - - RsGeneralDataService* posted_ds = new RsDataService(currGxsDir + "/", "posted_db", - RS_SERVICE_GXS_TYPE_POSTED, - NULL, rsInitConfig->gxs_passwd); - - p3Posted *mPosted = new p3Posted(posted_ds, NULL, mGxsIdService); - - // create GXS photo service - RsGxsNetService* posted_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_POSTED, posted_ds, nxsMgr, - mPosted, mPosted->getServiceInfo(), - mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils); - - mPosted->setNetworkExchangeService(posted_ns) ; - - /**** Wiki GXS service ****/ - -#ifdef RS_USE_WIKI - RsGeneralDataService* wiki_ds = new RsDataService(currGxsDir + "/", "wiki_db", - RS_SERVICE_GXS_TYPE_WIKI, - NULL, rsInitConfig->gxs_passwd); - - p3Wiki *mWiki = new p3Wiki(wiki_ds, NULL, mGxsIdService); - // create GXS wiki service - RsGxsNetService* wiki_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_WIKI, wiki_ds, nxsMgr, - mWiki, mWiki->getServiceInfo(), - mReputations, mGxsCircles, mGxsIdService, - pgpAuxUtils); - - mWiki->setNetworkExchangeService(wiki_ns) ; -#endif - - /**** Forum GXS service ****/ - - RsGeneralDataService* gxsforums_ds = new RsDataService(currGxsDir + "/", "gxsforums_db", - RS_SERVICE_GXS_TYPE_FORUMS, NULL, rsInitConfig->gxs_passwd); - - - p3GxsForums *mGxsForums = new p3GxsForums(gxsforums_ds, NULL, mGxsIdService); - - // create GXS photo service - RsGxsNetService* gxsforums_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_FORUMS, gxsforums_ds, nxsMgr, - mGxsForums, mGxsForums->getServiceInfo(), - mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils);//,mGxsNetTunnel,true,true,true); - - mGxsForums->setNetworkExchangeService(gxsforums_ns) ; - - /**** Channel GXS service ****/ - - RsGeneralDataService* gxschannels_ds = new RsDataService(currGxsDir + "/", "gxschannels_db", - RS_SERVICE_GXS_TYPE_CHANNELS, NULL, rsInitConfig->gxs_passwd); - - p3GxsChannels *mGxsChannels = new p3GxsChannels(gxschannels_ds, NULL, mGxsIdService); - - // create GXS photo service - RsGxsNetService* gxschannels_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_CHANNELS, gxschannels_ds, nxsMgr, - mGxsChannels, mGxsChannels->getServiceInfo(), - mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils,mGxsNetTunnel,true,true,true); - - mGxsChannels->setNetworkExchangeService(gxschannels_ns) ; - -#ifdef RS_USE_PHOTO - /**** Photo service ****/ - RsGeneralDataService* photo_ds = new RsDataService(currGxsDir + "/", "photoV2_db", - RS_SERVICE_GXS_TYPE_PHOTO, NULL, rsInitConfig->gxs_passwd); - - // init gxs services - p3PhotoService *mPhoto = new p3PhotoService(photo_ds, NULL, mGxsIdService); - - // create GXS photo service - RsGxsNetService* photo_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_PHOTO, photo_ds, nxsMgr, - mPhoto, mPhoto->getServiceInfo(), - mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils); - - mPhoto->setNetworkExchangeService(photo_ns); -#endif - -#ifdef RS_USE_WIRE - /**** Wire GXS service ****/ - RsGeneralDataService* wire_ds = new RsDataService(currGxsDir + "/", "wire_db", - RS_SERVICE_GXS_TYPE_WIRE, NULL, rsInitConfig->gxs_passwd); - - p3Wire *mWire = new p3Wire(wire_ds, NULL, mGxsIdService); - - // create GXS photo service - RsGxsNetService* wire_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_WIRE, wire_ds, nxsMgr, - mWire, mWire->getServiceInfo(), - mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils); - - mWire->setNetworkExchangeService(wire_ns); -#endif - // now add to p3service - pqih->addService(gxsid_ns, true); - pqih->addService(gxscircles_ns, true); - pqih->addService(posted_ns, true); -#ifdef RS_USE_WIKI - pqih->addService(wiki_ns, true); -#endif - pqih->addService(gxsforums_ns, true); - pqih->addService(gxschannels_ns, true); -#ifdef RS_USE_PHOTO - pqih->addService(photo_ns, true); -#endif -#ifdef RS_USE_WIRE - pqih->addService(wire_ns, true); -#endif - -# ifdef RS_GXS_TRANS - RsGeneralDataService* gxstrans_ds = new RsDataService( - currGxsDir + "/", "gxstrans_db", RS_SERVICE_TYPE_GXS_TRANS, - NULL, rsInitConfig->gxs_passwd ); - mGxsTrans = new p3GxsTrans(gxstrans_ds, NULL, *mGxsIdService); - - RsGxsNetService* gxstrans_ns = new RsGxsNetService( - RS_SERVICE_TYPE_GXS_TRANS, gxstrans_ds, nxsMgr, mGxsTrans, - mGxsTrans->getServiceInfo(), mReputations, mGxsCircles, - mGxsIdService, pgpAuxUtils,NULL,true,true,false,p3GxsTrans::GXS_STORAGE_PERIOD,p3GxsTrans::GXS_SYNC_PERIOD); - - mGxsTrans->setNetworkExchangeService(gxstrans_ns); - pqih->addService(gxstrans_ns, true); -# endif // RS_GXS_TRANS - - // remove pword from memory - rsInitConfig->gxs_passwd = ""; - -#endif // RS_ENABLE_GXS. - - /* create Services */ - p3ServiceInfo *serviceInfo = new p3ServiceInfo(serviceCtrl); - mDisc = new p3discovery2(mPeerMgr, mLinkMgr, mNetMgr, serviceCtrl,mGxsIdService); - mHeart = new p3heartbeat(serviceCtrl, pqih); - msgSrv = new p3MsgService( serviceCtrl, mGxsIdService, *mGxsTrans ); - chatSrv = new p3ChatService( serviceCtrl,mGxsIdService, mLinkMgr, - mHistoryMgr, *mGxsTrans ); - mStatusSrv = new p3StatusService(serviceCtrl); - -#ifdef RS_BROADCAST_DISCOVERY - BroadcastDiscoveryService* broadcastDiscoveryService = - new BroadcastDiscoveryService(*rsPeers); - rsBroadcastDiscovery = broadcastDiscoveryService; -#endif // def RS_BROADCAST_DISCOVERY - -#ifdef ENABLE_GROUTER - p3GRouter *gr = new p3GRouter(serviceCtrl,mGxsIdService) ; - rsGRouter = gr ; - pqih->addService(gr,true) ; -#endif - - p3FileDatabase *fdb = new p3FileDatabase(serviceCtrl) ; - p3turtle *tr = new p3turtle(serviceCtrl,mLinkMgr) ; - rsTurtle = tr ; - pqih -> addService(tr,true); - pqih -> addService(fdb,true); - pqih -> addService(ftserver,true); - - mGxsTunnels = new p3GxsTunnelService(mGxsIdService) ; - mGxsTunnels->connectToTurtleRouter(tr) ; - rsGxsTunnel = mGxsTunnels; - - mGxsNetTunnel->connectToTurtleRouter(tr) ; - - rsGossipDiscovery.reset(mDisc); - rsMsgs = new p3Msgs(msgSrv, chatSrv); - - // connect components to turtle router. - - ftserver->connectToTurtleRouter(tr) ; - ftserver->connectToFileDatabase(fdb) ; - chatSrv->connectToGxsTunnelService(mGxsTunnels) ; - gr->connectToTurtleRouter(tr) ; -#ifdef ENABLE_GROUTER - msgSrv->connectToGlobalRouter(gr) ; -#endif - - pqih -> addService(serviceInfo,true); - pqih -> addService(mHeart,true); - pqih -> addService(mDisc,true); - pqih -> addService(msgSrv,true); - pqih -> addService(chatSrv,true); - pqih -> addService(mStatusSrv,true); - pqih -> addService(mGxsTunnels,true); - pqih -> addService(mReputations,true); - - // set interfaces for plugins - // - RsPlugInInterfaces interfaces; - interfaces.mFiles = rsFiles; - interfaces.mPeers = rsPeers; - interfaces.mMsgs = rsMsgs; - interfaces.mTurtle = rsTurtle; - interfaces.mDisc = rsDisc; -#ifdef RS_USE_BITDHT - interfaces.mDht = rsDht; -#else - interfaces.mDht = NULL; -#endif - interfaces.mNotify = mNotify; - interfaces.mServiceControl = serviceCtrl; - interfaces.mPluginHandler = mPluginsManager; - // gxs - interfaces.mGxsDir = currGxsDir; - interfaces.mIdentity = mGxsIdService; - interfaces.mRsNxsNetMgr = nxsMgr; - interfaces.mGxsIdService = mGxsIdService; - interfaces.mGxsCirlces = mGxsCircles; - interfaces.mPgpAuxUtils = pgpAuxUtils; - interfaces.mGxsForums = mGxsForums; - interfaces.mGxsChannels = mGxsChannels; - interfaces.mGxsTunnels = mGxsTunnels; - interfaces.mReputations = mReputations; - - mPluginsManager->setInterfaces(interfaces); - - // now add plugin objects inside the loop: - // - client services provided by plugins. - // - cache services provided by plugins. - // - mPluginsManager->registerClientServices(pqih) ; - mPluginsManager->registerCacheServices() ; - - - -#ifdef RS_RTT - p3rtt *mRtt = new p3rtt(serviceCtrl); - pqih -> addService(mRtt, true); - rsRtt = mRtt; -#endif - - // new services to test. - - p3BanList *mBanList = NULL; - - if(!RsAccounts::isHiddenNode()) - { - mBanList = new p3BanList(serviceCtrl, mNetMgr); - rsBanList = mBanList ; - pqih -> addService(mBanList, true); - } - else - rsBanList = NULL ; - - p3BandwidthControl *mBwCtrl = new p3BandwidthControl(pqih); - pqih -> addService(mBwCtrl, true); - -#ifdef SERVICES_DSDV - p3Dsdv *mDsdv = new p3Dsdv(serviceCtrl); - pqih -> addService(mDsdv, true); - rsDsdv = mDsdv; - mDsdv->addTestService(); -#endif - - /**************************************************************************/ - - if(!RsAccounts::isHiddenNode()) - { -#ifdef RS_USE_BITDHT - mBitDht->setupPeerSharer(mBanList); - - mNetMgr->addNetAssistConnect(1, mBitDht); - mNetMgr->addNetListener(mDhtStack); - mNetMgr->addNetListener(mProxyStack); -#endif - -#if defined(RS_USE_LIBMINIUPNPC) || defined(RS_USE_LIBUPNP) - // Original UPnP Interface. - pqiNetAssistFirewall *mUpnpMgr = new upnphandler(); - mNetMgr->addNetAssistFirewall(1, mUpnpMgr); -#endif // defined(RS_USE_LIBMINIUPNPC) || defined(RS_USE_LIBUPNP) - } - - /**************************************************************************/ - /* need to Monitor too! */ - mLinkMgr->addMonitor(pqih); - mLinkMgr->addMonitor(serviceCtrl); - mLinkMgr->addMonitor(serviceInfo); - - // Services that have been changed to pqiServiceMonitor - serviceCtrl->registerServiceMonitor(msgSrv, msgSrv->getServiceInfo().mServiceType); - serviceCtrl->registerServiceMonitor(mDisc, mDisc->getServiceInfo().mServiceType); - serviceCtrl->registerServiceMonitor(mStatusSrv, mStatusSrv->getServiceInfo().mServiceType); - serviceCtrl->registerServiceMonitor(chatSrv, chatSrv->getServiceInfo().mServiceType); - serviceCtrl->registerServiceMonitor(mBwCtrl, mBwCtrl->getServiceInfo().mServiceType); - - /**************************************************************************/ - // Turtle search for GXS services - - mGxsNetTunnel->registerSearchableService(gxschannels_ns) ; - - /**************************************************************************/ - - //mConfigMgr->addConfiguration("ftserver.cfg", ftserver); - // - mConfigMgr->addConfiguration("gpg_prefs.cfg" , AuthGPG::getAuthGPG()); - mConfigMgr->addConfiguration("gxsnettunnel.cfg", mGxsNetTunnel); - mConfigMgr->addConfiguration("peers.cfg" , mPeerMgr); - mConfigMgr->addConfiguration("general.cfg" , mGeneralConfig); - mConfigMgr->addConfiguration("msgs.cfg" , msgSrv); - mConfigMgr->addConfiguration("chat.cfg" , chatSrv); - mConfigMgr->addConfiguration("p3History.cfg" , mHistoryMgr); - mConfigMgr->addConfiguration("p3Status.cfg" , mStatusSrv); - mConfigMgr->addConfiguration("turtle.cfg" , tr); - - if(mBanList != NULL) - mConfigMgr->addConfiguration("banlist.cfg" , mBanList); - - mConfigMgr->addConfiguration("servicecontrol.cfg", serviceCtrl); - mConfigMgr->addConfiguration("reputations.cfg" , mReputations); -#ifdef ENABLE_GROUTER - mConfigMgr->addConfiguration("grouter.cfg" , gr); -#endif - -#ifdef RS_USE_BITDHT - if(mBitDht != NULL) - mConfigMgr->addConfiguration("bitdht.cfg" , mBitDht); -#endif - -#ifdef RS_ENABLE_GXS - -# ifdef RS_GXS_TRANS - mConfigMgr->addConfiguration("gxs_trans_ns.cfg", gxstrans_ns); - mConfigMgr->addConfiguration("gxs_trans.cfg" , mGxsTrans); -# endif // RS_GXS_TRANS - - mConfigMgr->addConfiguration("p3identity.cfg" , mGxsIdService); - mConfigMgr->addConfiguration("identity.cfg" , gxsid_ns); - mConfigMgr->addConfiguration("gxsforums.cfg" , gxsforums_ns); - mConfigMgr->addConfiguration("gxsforums_srv.cfg" , mGxsForums); - mConfigMgr->addConfiguration("gxschannels.cfg" , gxschannels_ns); - mConfigMgr->addConfiguration("gxschannels_srv.cfg", mGxsChannels); - mConfigMgr->addConfiguration("gxscircles.cfg" , gxscircles_ns); - mConfigMgr->addConfiguration("gxscircles_srv.cfg" , mGxsCircles); - mConfigMgr->addConfiguration("posted.cfg" , posted_ns); - mConfigMgr->addConfiguration("gxsposted_srv.cfg" , mPosted); -#ifdef RS_USE_WIKI - mConfigMgr->addConfiguration("wiki.cfg", wiki_ns); -#endif -#ifdef RS_USE_PHOTO - mConfigMgr->addConfiguration("photo.cfg", photo_ns); -#endif -#ifdef RS_USE_WIRE - mConfigMgr->addConfiguration("wire.cfg", wire_ns); -#endif -#endif //RS_ENABLE_GXS -#ifdef RS_USE_I2P_BOB - mConfigMgr->addConfiguration("I2PBOB.cfg", mI2pBob); -#endif - - mPluginsManager->addConfigurations(mConfigMgr) ; - - ftserver->addConfiguration(mConfigMgr); - - /**************************************************************************/ - /* (2) Load configuration files */ - /**************************************************************************/ - std::cerr << "(2) Load configuration files" << std::endl; - - mConfigMgr->loadConfiguration(); - - /**************************************************************************/ - /* trigger generalConfig loading for classes that require it */ - /**************************************************************************/ - p3ServerConfig *serverConfig = new p3ServerConfig(mPeerMgr, mLinkMgr, mNetMgr, pqih, mGeneralConfig); - serverConfig->load_config(); - - /**************************************************************************/ - /* Force Any Configuration before Startup (After Load) */ - /**************************************************************************/ - std::cerr << "Force Any Configuration before Startup (After Load)" << std::endl; - - if (rsInitConfig->forceLocalAddr) - { - struct sockaddr_storage laddr; - - /* clean sockaddr before setting values (MaxOSX) */ - sockaddr_storage_clear(laddr); - - struct sockaddr_in *lap = (struct sockaddr_in *) &laddr; - - lap->sin_family = AF_INET; - lap->sin_port = htons(rsInitConfig->port); - - // universal - lap->sin_addr.s_addr = inet_addr(rsInitConfig->inet.c_str()); - - mPeerMgr->setLocalAddress(ownId, laddr); - } - - if (rsInitConfig->forceExtPort) - { - mPeerMgr->setOwnNetworkMode(RS_NET_MODE_EXT); - mPeerMgr->setOwnVisState(RS_VS_DISC_FULL, RS_VS_DHT_FULL); - } - - if (rsInitConfig->hiddenNodeSet) - { - std::cout << "RsServer::StartupRetroShare setting up hidden locations" << std::endl; - - if (rsInitConfig->hiddenNodeI2PBOB) { - std::cout << "RsServer::StartupRetroShare setting up BOB" << std::endl; - - // we need a local port! - mNetMgr->checkNetAddress(); - - // add i2p proxy - // bob will use this address - sockaddr_storage i2pInstance; - sockaddr_storage_ipv4_aton(i2pInstance, rsInitConfig->hiddenNodeAddress.c_str()); - mPeerMgr->setProxyServerAddress(RS_HIDDEN_TYPE_I2P, i2pInstance); - - std::string addr; // will be set by auto proxy service - uint16_t port = rsInitConfig->hiddenNodePort; // unused by bob - - bool r = autoProxy->initialSetup(autoProxyType::I2PBOB, addr, port); - - if (r && !addr.empty()) { - mPeerMgr->setupHiddenNode(addr, port); - - // now enable bob - bobSettings bs; - autoProxy->taskSync(autoProxyType::I2PBOB, autoProxyTask::getSettings, &bs); - bs.enable = true; - autoProxy->taskSync(autoProxyType::I2PBOB, autoProxyTask::setSettings, &bs); - } else { - std::cerr << "RsServer::StartupRetroShare failed to receive keys" << std::endl; - /// TODO add notify for failed bob setup - } - } else { - mPeerMgr->setupHiddenNode(rsInitConfig->hiddenNodeAddress, rsInitConfig->hiddenNodePort); - } - - std::cout << "RsServer::StartupRetroShare hidden location set up" << std::endl; - } - else if (isHiddenNode) - { - mPeerMgr->forceHiddenNode(); - } - - if (!rsInitConfig->opModeStr.empty()) - { - rsConfig->setOperatingMode(rsInitConfig->opModeStr); - } - mNetMgr -> checkNetAddress(); - - if (rsInitConfig->hiddenNodeSet) { - // newly created location - // mNetMgr->checkNetAddress() will setup ports for us - // trigger updates for auto proxy services - std::vector types; - - // i2p bob need to rebuild its command map - types.push_back(autoProxyType::I2PBOB); - - rsAutoProxyMonitor::taskSync(types, autoProxyTask::reloadConfig); - } - - /**************************************************************************/ - /* startup (stuff dependent on Ids/peers is after this point) */ - /**************************************************************************/ - - autoProxy->startAll(); - - pqih->init_listener(); - mNetMgr->addNetListener(pqih); /* add listener so we can reset all sockets later */ - - /**************************************************************************/ - /* load caches and secondary data */ - /**************************************************************************/ - - // Clear the News Feeds that are generated by Initial Cache Loading. - - /* Peer stuff is up to date */ - - //getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_CHAT_NEW); - mNotify->ClearFeedItems(RS_FEED_ITEM_MESSAGE); - //getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_FILES_NEW); - - /**************************************************************************/ - /* Add AuthGPG services */ - /**************************************************************************/ - - //AuthGPG::getAuthGPG()->addService(mDisc); - - /**************************************************************************/ - /* Force Any Last Configuration Options */ - /**************************************************************************/ - - /**************************************************************************/ - /* Start up Threads */ - /**************************************************************************/ - - // auto proxy threads -#ifdef RS_USE_I2P_BOB - startServiceThread(mI2pBob, "I2P-BOB"); -#endif - -#ifdef RS_ENABLE_GXS - // Must Set the GXS pointers before starting threads. - rsIdentity = mGxsIdService; - rsGxsCircles = mGxsCircles; -#if RS_USE_WIKI - rsWiki = mWiki; -#endif - rsPosted = mPosted; - rsGxsForums = mGxsForums; - rsGxsChannels = mGxsChannels; - rsGxsTrans = mGxsTrans; - -#if RS_USE_PHOTO - rsPhoto = mPhoto; -#endif -#if RS_USE_WIRE - rsWire = mWire; -#endif - - /*** start up GXS core runner ***/ - - startServiceThread(mGxsNetTunnel, "gxs net tunnel"); - startServiceThread(mGxsIdService, "gxs id"); - startServiceThread(mGxsCircles, "gxs circle"); - startServiceThread(mPosted, "gxs posted"); -#if RS_USE_WIKI - startServiceThread(mWiki, "gxs wiki"); -#endif - startServiceThread(mGxsForums, "gxs forums"); - startServiceThread(mGxsChannels, "gxs channels"); - -#if RS_USE_PHOTO - startServiceThread(mPhoto, "gxs photo"); -#endif -#if RS_USE_WIRE - startServiceThread(mWire, "gxs wire"); -#endif - - // cores ready start up GXS net servers - startServiceThread(gxsid_ns, "gxs id ns"); - startServiceThread(gxscircles_ns, "gxs circle ns"); - startServiceThread(posted_ns, "gxs posted ns"); -#if RS_USE_WIKI - startServiceThread(wiki_ns, "gxs wiki ns"); -#endif - startServiceThread(gxsforums_ns, "gxs forums ns"); - startServiceThread(gxschannels_ns, "gxs channels ns"); - -#if RS_USE_PHOTO - startServiceThread(photo_ns, "gxs photo ns"); -#endif -#if RS_USE_WIRE - startServiceThread(wire_ns, "gxs wire ns"); -#endif - -# ifdef RS_GXS_TRANS - startServiceThread(mGxsTrans, "gxs trans"); - startServiceThread(gxstrans_ns, "gxs trans ns"); -# endif // def RS_GXS_TRANS - -#endif // RS_ENABLE_GXS - -#ifdef RS_BROADCAST_DISCOVERY - startServiceThread(broadcastDiscoveryService, "Broadcast Discovery"); -#endif // def RS_BROADCAST_DISCOVERY - - ftserver->StartupThreads(); - ftserver->ResumeTransfers(); - - //mDhtMgr->start(); -#ifdef RS_USE_BITDHT - if(mBitDht != NULL) - mBitDht->start(); -#endif - - /**************************************************************************/ - - // create loopback device, and add to pqisslgrp. - - SearchModule *mod = new SearchModule(); - pqiloopback *ploop = new pqiloopback(ownId); - - mod -> peerid = ownId; - mod -> pqi = ploop; - - pqih->AddSearchModule(mod); - - /* Setup GUI Interfaces. */ - - // rsDisc & RsMsgs done already. - rsBandwidthControl = mBwCtrl; - rsConfig = serverConfig; - - - rsStatus = new p3Status(mStatusSrv); - rsHistory = new p3History(mHistoryMgr); - - /* put a welcome message in! */ - if (isFirstTimeRun) - { - msgSrv->loadWelcomeMsg(); - ftserver->shareDownloadDirectory(true); - mGeneralConfig->saveConfiguration(); - } - - /* Startup this thread! */ - start("rs main") ; - - std::cerr << "========================================================================" << std::endl; - std::cerr << "== RsInit:: Retroshare core started ==" << std::endl; - std::cerr << "========================================================================" << std::endl; - - coreReady = true; - return 1; -} - -RsInit::LoadCertificateStatus RsLoginHelper::attemptLogin(const RsPeerId& account, const std::string& password) -{ - if(isLoggedIn()) return RsInit::ERR_ALREADY_RUNNING; - - { - if(!RsAccounts::SelectAccount(account)) - return RsInit::ERR_UNKNOWN; - - if(!password.empty()) - { - rsNotify->cachePgpPassphrase(password); - rsNotify->setDisableAskPassword(true); - } - std::string _ignore_lockFilePath; - RsInit::LoadCertificateStatus ret = RsInit::LockAndLoadCertificates(false, _ignore_lockFilePath); - - rsNotify->setDisableAskPassword(false) ; - rsNotify->clearPgpPassphrase() ; - - if(ret == RsInit::OK && RsControl::instance()->StartupRetroShare() == 1) - return RsInit::OK; - - return ret; - } -} - -/*static*/ bool RsLoginHelper::collectEntropy(uint32_t bytes) -{ return RsInit::collectEntropy(bytes); } - -void RsLoginHelper::getLocations(std::vector& store) -{ - std::list locIds; - RsAccounts::GetAccountIds(locIds); - store.clear(); - - for(const RsPeerId& locId : locIds ) - { - Location l; l.mLocationId = locId; - std::string discardPgpMail; - RsAccounts::GetAccountDetails( locId, l.mPgpId, l.mPgpName, - discardPgpMail, l.mLocationName ); - store.push_back(l); - } -} - -std::error_condition RsLoginHelper::createLocationV2( - RsPeerId& locationId, RsPgpId& pgpId, - const std::string& locationName, const std::string& pgpName, - const std::string& password ) -{ - if(isLoggedIn()) return RsInitErrorNum::ALREADY_LOGGED_IN; - if(locationName.empty()) return RsInitErrorNum::INVALID_LOCATION_NAME; - if(pgpId.isNull() && pgpName.empty()) - return RsInitErrorNum::PGP_NAME_OR_ID_NEEDED; - - std::string errorMessage; - if(pgpId.isNull() && !RsAccounts::GeneratePGPCertificate( - pgpName, "", password, pgpId, 4096, errorMessage ) ) - { - RS_ERR("Failure creating PGP key: ", errorMessage); - return RsInitErrorNum::PGP_KEY_CREATION_FAILED; - } - - std::string sslPassword = - RsRandom::random_alphaNumericString(RsInit::getSslPwdLen()); - - rsNotify->cachePgpPassphrase(password); - rsNotify->setDisableAskPassword(true); - - bool ret = RsAccounts::createNewAccount( - pgpId, "", locationName, "", false, false, sslPassword, - locationId, errorMessage ); - if(!ret) - { - RS_ERR("Failure creating SSL key: ", errorMessage); - return RsInitErrorNum::SSL_KEY_CREATION_FAILED; - } - - RsInit::LoadPassword(sslPassword); - ret = (RsInit::OK == attemptLogin(locationId, password)); - rsNotify->setDisableAskPassword(false); - - return (ret ? std::error_condition() : RsInitErrorNum::LOGIN_FAILED); -} - -#if !RS_VERSION_AT_LEAST(0,6,6) -bool RsLoginHelper::createLocation( - RsLoginHelper::Location& l, const std::string& password, - std::string& errorMessage, bool makeHidden, bool makeAutoTor ) -{ - if(isLoggedIn()) return (errorMessage="Already Running", false); - - if(l.mLocationName.empty()) - { - errorMessage = "Location name is needed"; - return false; - } - - if(l.mPgpId.isNull() && l.mPgpName.empty()) - { - errorMessage = "Either PGP name or PGP id is needed"; - return false; - } - - if(l.mPgpId.isNull() && !RsAccounts::GeneratePGPCertificate( - l.mPgpName, "", password, l.mPgpId, 4096, errorMessage) ) - { - errorMessage = "Failure creating PGP key: " + errorMessage; - return false; - } - - std::string sslPassword = - RSRandom::random_alphaNumericString(RsInit::getSslPwdLen()); - - if(!rsNotify->cachePgpPassphrase(password)) return false; - if(!rsNotify->setDisableAskPassword(true)) return false; - - bool ret = RsAccounts::createNewAccount( - l.mPgpId, "", l.mLocationName, "", makeHidden, makeAutoTor, - sslPassword, l.mLocationId, errorMessage ); - - ret = ret && RsInit::LoadPassword(sslPassword); - ret = ret && RsInit::OK == attemptLogin(l.mLocationId, password); - - rsNotify->setDisableAskPassword(false); - return ret; -} -#endif // !RS_VERSION_AT_LEAST(0,6,6) - -bool RsLoginHelper::isLoggedIn() -{ - return RsControl::instance()->isReady(); -} - -void RsLoginHelper::Location::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(mLocationId); - RS_SERIAL_PROCESS(mPgpId); - RS_SERIAL_PROCESS(mLocationName); - RS_SERIAL_PROCESS(mPgpName); -} - -/*static*/ bool RsAccounts::getCurrentAccountId(RsPeerId& id) -{ - return rsAccountsDetails->getCurrentAccountId(id); -} diff --git a/libretroshare/src/rsserver/rsloginhandler.cc b/libretroshare/src/rsserver/rsloginhandler.cc deleted file mode 100644 index dbe023235..000000000 --- a/libretroshare/src/rsserver/rsloginhandler.cc +++ /dev/null @@ -1,792 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: rsloginhandler.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 retroshare team * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include -#include -#include "rsloginhandler.h" -#include "util/rsdir.h" -#include "retroshare/rsinit.h" -#include "util/rsdebug.h" - -//#define DEBUG_RSLOGINHANDLER 1 - -bool RsLoginHandler::getSSLPassword( const RsPeerId& ssl_id, - bool enable_gpg_ask_passwd, - std::string& ssl_passwd ) -{ - -#ifdef RS_AUTOLOGIN - // First, see if autologin is available - if(tryAutoLogin(ssl_id,ssl_passwd)) return true; -#endif // RS_AUTOLOGIN - - // If we're not expecting to enter a passwd (e.g. test for autologin before - // display of the login window), safely respond false. - if(!enable_gpg_ask_passwd) return false; - - return getSSLPasswdFromGPGFile(ssl_id,ssl_passwd); -} - -bool RsLoginHandler::checkAndStoreSSLPasswdIntoGPGFile( - const RsPeerId& ssl_id, const std::string& ssl_passwd ) -{ - // We want to pursue login with gpg passwd. Let's do it: - FILE *sslPassphraseFile = RsDirUtil::rs_fopen( - getSSLPasswdFileName(ssl_id).c_str(), "r"); - - if(sslPassphraseFile) // already have it. - { - fclose(sslPassphraseFile); - return true ; - } - - bool ok = AuthGPG::getAuthGPG()->encryptTextToFile( - ssl_passwd, getSSLPasswdFileName(ssl_id)); - - if (!ok) std::cerr << "Encrypting went wrong !" << std::endl; - - return ok; -} - -bool RsLoginHandler::getSSLPasswdFromGPGFile(const RsPeerId& ssl_id,std::string& sslPassword) -{ - /* Let's read the password from an encrypted file, before check if there's - * an ssl_passpharese_file that we can decrypt with PGP */ - FILE *sslPassphraseFile = RsDirUtil::rs_fopen( - getSSLPasswdFileName(ssl_id).c_str(), "r"); - - if (!sslPassphraseFile) - { - std::cerr << "No password provided, and no sslPassphraseFile : " - << getSSLPasswdFileName(ssl_id).c_str() << std::endl; - return 0; - } - - fclose(sslPassphraseFile); - -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "opening sslPassphraseFile : " - << getSSLPasswdFileName(ssl_id).c_str() << std::endl; -#endif - - std::string plain; - if ( AuthGPG::getAuthGPG()->decryptTextFromFile( plain, getSSLPasswdFileName(ssl_id)) ) - { - sslPassword = plain; -#ifdef DEBUG_RSLOGINHANDLER - if(sslPassword.length() > 0) - std::cerr << "Decrypting went ok !" << std::endl; - else - std::cerr << "Passphrase is empty!" << std::endl; -#endif - - return sslPassword.length() > 0 ; - } - else - { - sslPassword = ""; - std::cerr << "Error : decrypting went wrong !" << std::endl; - - return false; - } -} - - -std::string RsLoginHandler::getSSLPasswdFileName(const RsPeerId& /*ssl_id*/) -{ - return RsAccounts::AccountKeysDirectory() + "/" + "ssl_passphrase.pgp"; -} - -#ifdef RS_AUTOLOGIN - -#if defined(HAS_GNOME_KEYRING) || defined(__FreeBSD__) || defined(__OpenBSD__) -# include - -GnomeKeyringPasswordSchema my_schema = { - GNOME_KEYRING_ITEM_ENCRYPTION_KEY_PASSWORD, - { - { "RetroShare SSL Id", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, - { NULL, (GnomeKeyringAttributeType)0 } - }, - NULL, - NULL, - NULL -}; -#elif defined(HAS_LIBSECRET) -#include -const SecretSchema *libsecret_get_schema(void) -{ - static const SecretSchema the_schema = { - "org.Retroshare.Password", SECRET_SCHEMA_NONE, - { - { "RetroShare SSL Id", SECRET_SCHEMA_ATTRIBUTE_STRING }, - { "NULL", static_cast(0) }, - }, - 0,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr - }; - return &the_schema; -} -#endif - - -#ifdef __APPLE__ - /* OSX Headers */ - -#include -#include - -#endif - -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -/* WINDOWS STRUCTURES FOR DPAPI */ - -#ifndef WINDOWS_SYS /* UNIX */ - -#include - -#else -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - -#include -#include -#include - -/* -class CRYPTPROTECT_PROMPTSTRUCT; -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef WINDOWS_SYS -#if defined(__CYGWIN__) - -typedef struct _CRYPTPROTECT_PROMPTSTRUCT { - DWORD cbSize; - DWORD dwPromptFlags; - HWND hwndApp; - LPCWSTR szPrompt; -} CRYPTPROTECT_PROMPTSTRUCT, - *PCRYPTPROTECT_PROMPTSTRUCT; - -#endif -#endif - -/* definitions for the two functions */ -__declspec (dllimport) -extern BOOL WINAPI CryptProtectData( - DATA_BLOB* pDataIn, - LPCWSTR szDataDescr, - DATA_BLOB* pOptionalEntropy, - PVOID pvReserved, - /* PVOID prompt, */ - /* CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, */ - CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, - DWORD dwFlags, - DATA_BLOB* pDataOut -); - -__declspec (dllimport) -extern BOOL WINAPI CryptUnprotectData( - DATA_BLOB* pDataIn, - LPWSTR* ppszDataDescr, - DATA_BLOB* pOptionalEntropy, - PVOID pvReserved, - /* PVOID prompt, */ - /* CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, */ - CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, - DWORD dwFlags, - DATA_BLOB* pDataOut -); - -#ifdef __cplusplus -} -#endif - -#endif - - -bool RsLoginHandler::tryAutoLogin(const RsPeerId& ssl_id,std::string& ssl_passwd) -{ -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "RsTryAutoLogin()" << std::endl; -#endif - - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef __HAIKU__ -#ifndef WINDOWS_SYS /* UNIX */ -#if defined(HAS_GNOME_KEYRING) || defined(__FreeBSD__) || defined(__OpenBSD__) - - gchar *passwd = NULL; - -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "Using attribute: " << ssl_id << std::endl; -#endif - if( gnome_keyring_find_password_sync(&my_schema, &passwd,"RetroShare SSL Id",ssl_id.toStdString().c_str(),NULL) == GNOME_KEYRING_RESULT_OK ) - { - std::cout << "Got SSL passwd ********************" /*<< passwd*/ << " from gnome keyring" << std::endl; - ssl_passwd = std::string(passwd); - return true ; - } - else - { -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "Could not get passwd from gnome keyring" << std::endl; -#endif - return false ; - } -#elif defined(HAS_LIBSECRET) - // do synchronous lookup - -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "Using attribute: " << ssl_id << std::endl; -#endif - - GError *error = nullptr; - gchar *password = secret_password_lookup_sync (libsecret_get_schema(), nullptr, &error, - "RetroShare SSL Id", ssl_id.toStdString().c_str(), - NULL); - - if (error) { - g_error_free (error); -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "Could not get passwd using libsecret: error" << std::endl; -#endif - return false; - } else if (!password) { - /* password will be null, if no matching password found */ -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "Could not get passwd using libsecret: not found" << std::endl; -#endif - return false; - } else { - std::cout << "Got SSL passwd ********************" /*<< passwd*/ << " using libsecret" << std::endl; - ssl_passwd = std::string(password); - - secret_password_free (password); - return true; - } -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "Could not get passwd from gnome keyring: unknown" << std::endl; -#endif - //return false; //Never used returned before -#else - /******************** OSX KeyChain stuff *****************************/ -#ifdef __APPLE__ - - std::cerr << "RsTryAutoLogin() OSX Version" << std::endl; - //Call SecKeychainFindGenericPassword to get a password from the keychain: - - void *passwordData = NULL; - UInt32 passwordLength = 0; - std::string idtemp = ssl_id.toStdString(); - const char *userId = idtemp.c_str(); - UInt32 uidLength = strlen(userId); - SecKeychainItemRef itemRef = NULL; - - OSStatus status = SecKeychainFindGenericPassword ( - NULL, // default keychain - 10, // length of service name - "Retroshare", // service name - uidLength, // length of account name - userId, // account name - &passwordLength, // length of password - &passwordData, // pointer to password data - &itemRef // the item reference - ); - - std::cerr << "RsTryAutoLogin() SecKeychainFindGenericPassword returned: " << status << std::endl; - - if (status != 0) - { - std::cerr << "RsTryAutoLogin() Error " << std::endl; - - /* error */ - if (status == errSecItemNotFound) - { - //Is password on keychain? - std::cerr << "RsTryAutoLogin() Error - Looks like password is not in KeyChain " << std::endl; - } - } - else - { - std::cerr << "RsTryAutoLogin() Password found on KeyChain! " << std::endl; - - /* load up password to correct location */ - ssl_passwd.clear(); - ssl_passwd.insert(0, (char*)passwordData, passwordLength); - } - - //Free the data allocated by SecKeychainFindGenericPassword: - - SecKeychainItemFreeContent ( - NULL, //No attribute data to release - passwordData //Release data buffer allocated by SecKeychainFindGenericPassword - ); - - if (itemRef) CFRelease(itemRef); - - return (status == 0); - - /******************** OSX KeyChain stuff *****************************/ -#endif // APPLE -#endif // HAS_GNOME_KEYRING / HAS_LIBSECRET -#else /******* WINDOWS BELOW *****/ - - /* try to load from file */ - std::string entropy = getSSLPasswdFileName(ssl_id); - /* get the data out */ - - DATA_BLOB DataIn; - DATA_BLOB DataEnt; - DATA_BLOB DataOut; - - BYTE *pbDataEnt =(BYTE *) strdup(entropy.c_str()); - DWORD cbDataEnt = strlen((char *)pbDataEnt)+1; - DataEnt.pbData = pbDataEnt; - DataEnt.cbData = cbDataEnt; - - char *dataptr = NULL; - int datalen = 0; - - /* open the data to the file */ - FILE *fp = RsDirUtil::rs_fopen(getAutologinFileName(ssl_id).c_str(), "rb"); - if (fp != NULL) - { - fseek(fp, 0, SEEK_END); - datalen = ftell(fp); - fseek(fp, 0, SEEK_SET); - dataptr = (char *) rs_malloc(datalen); - - if(dataptr == NULL) - { - fclose(fp); - return false; - } - fread(dataptr, 1, datalen, fp); - fclose(fp); - - /***** - std::cerr << "Data loaded from: " << passwdfile; - std::cerr << std::endl; - - std::cerr << "Size :"; - std::cerr << datalen << std::endl; - - for(unsigned int i = 0; i < datalen; i++) - { - std::cerr << std::setw(2) << (int) dataptr[i]; - std::cerr << " "; - } - std::cerr << std::endl; - *****/ - } - else - { - return false; - } - - BYTE *pbDataInput =(BYTE *) dataptr; - DWORD cbDataInput = datalen; - DataIn.pbData = pbDataInput; - DataIn.cbData = cbDataInput; - - - CRYPTPROTECT_PROMPTSTRUCT prom; - - prom.cbSize = sizeof(prom); - prom.dwPromptFlags = 0; - - - bool isDecrypt = CryptUnprotectData( - &DataIn, - NULL, - &DataEnt, /* entropy.c_str(), */ - NULL, // Reserved - &prom, // Opt. Prompt - 0, - &DataOut); - - if (isDecrypt) - { - //std::cerr << "Decrypted size: " << DataOut.cbData; - //std::cerr << std::endl; - if (DataOut.pbData[DataOut.cbData - 1] != '\0') - { - std::cerr << "Error: Decrypted Data not a string..."; - std::cerr << std::endl; - isDecrypt = false; - } - else - { - //std::cerr << "The decrypted data is: " << DataOut.pbData; - //std::cerr << std::endl; - ssl_passwd = (char *) DataOut.pbData; - } - } - else - { - std::cerr << "Decryption error!"; - std::cerr << std::endl; - } - - /* strings to be freed */ - free(pbDataInput); - free(pbDataEnt); - - /* generated data space */ - LocalFree(DataOut.pbData); - - return isDecrypt; -#endif -#endif - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - //return false; //never used -} - - -bool RsLoginHandler::enableAutoLogin(const RsPeerId& ssl_id,const std::string& ssl_passwd) -{ - std::cerr << "RsStoreAutoLogin()" << std::endl; - - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef __HAIKU__ -#ifndef WINDOWS_SYS /* UNIX */ -#if defined(HAS_GNOME_KEYRING) || defined(__FreeBSD__) || defined(__OpenBSD__) - if(GNOME_KEYRING_RESULT_OK == gnome_keyring_store_password_sync(&my_schema, NULL, (gchar*)("RetroShare password for SSL Id "+ssl_id.toStdString()).c_str(),(gchar*)ssl_passwd.c_str(),"RetroShare SSL Id",ssl_id.toStdString().c_str(),NULL)) - { - std::cout << "Stored passwd " << "************************" << " into gnome keyring" << std::endl; - return true ; - } - else - { - std::cerr << "Could not store passwd into gnome keyring" << std::endl; - return false ; - } -#elif defined(HAS_LIBSECRET) - // do synchronous store - - GError *error = nullptr; - secret_password_store_sync (libsecret_get_schema(), SECRET_COLLECTION_DEFAULT, - static_cast(("RetroShare password for SSL Id " + ssl_id.toStdString()).c_str()), - static_cast(ssl_passwd.c_str()), - nullptr, &error, - "RetroShare SSL Id", ssl_id.toStdString().c_str(), - NULL); - - if (error) { - RsErr() << __PRETTY_FUNCTION__ - << " Could not store passwd using libsecret with" - << " error.code=" << error->code - << " error.domain=" << error->domain - << " error.message=\"" << error->message << "\"" << std::endl; - if (error->code == 2) - RsErr() << "Do have a key wallet installed?" << std::endl - << "Like gnome-keyring or other using \"Secret Service\" by DBus." << std::endl; - g_error_free (error); - return false; - } - std::cout << "Stored passwd " << "************************" << " using libsecret" << std::endl; - return true; -#else -#ifdef __APPLE__ - /***************** OSX KEYCHAIN ****************/ - //Call SecKeychainAddGenericPassword to add a new password to the keychain: - - std::cerr << "RsStoreAutoLogin() OSX Version!" << std::endl; - - const void *password = ssl_passwd.c_str(); - UInt32 passwordLength = strlen(ssl_passwd.c_str()); - std::string idtemp = ssl_id.toStdString(); - const char *userid = idtemp.c_str(); - UInt32 uidLength = strlen(userid); - - OSStatus status = SecKeychainAddGenericPassword ( - NULL, // default keychain - 10, // length of service name - "Retroshare", // service name - uidLength, // length of account name - userid, // account name - passwordLength, // length of password - password, // pointer to password data - NULL // the item reference - ); - - std::cerr << "RsStoreAutoLogin() Call to SecKeychainAddGenericPassword returned: " << status << std::endl; - - if (status != 0) - { - std::cerr << "RsStoreAutoLogin() SecKeychainAddGenericPassword Failed" << std::endl; - return false; - } - return true; - - /***************** OSX KEYCHAIN ****************/ -#else -#ifdef TODO_CODE_ROTTEN - - /* WARNING: Autologin is inherently unsafe */ - FILE* helpFile = RsDirUtil::rs_fopen(getAutologinFileName.c_str(), "w"); - - if(helpFile == NULL){ - std::cerr << "\nRsStoreAutoLogin(): Failed to open help file\n" << std::endl; - return false; - } - - /* encrypt help */ - - const int DAT_LEN = ssl_passwd.length(); - const int KEY_DAT_LEN = RsInitConfig::load_cert.length(); - unsigned char* key_data = (unsigned char*)RsInitConfig::load_cert.c_str(); - unsigned char* indata = (unsigned char*)ssl_passwd.c_str(); - unsigned char* outdata = new unsigned char[DAT_LEN]; - - RC4_KEY* key = new RC4_KEY; - RC4_set_key(key, KEY_DAT_LEN, key_data); - - RC4(key, DAT_LEN, indata, outdata); - - - fprintf(helpFile, "%s", outdata); - fclose(helpFile); - - delete key; - delete[] outdata; - - - return true; -#endif // TODO_CODE_ROTTEN -#endif // __APPLE__ -#endif // HAS_GNOME_KEYRING / HAS_LIBSECRET -#else /* windows */ - - /* store password encrypted in a file */ - std::string entropy = getSSLPasswdFileName(ssl_id); - - DATA_BLOB DataIn; - DATA_BLOB DataEnt; - DATA_BLOB DataOut; - BYTE *pbDataInput = (BYTE *) strdup(ssl_passwd.c_str()); - DWORD cbDataInput = strlen((char *)pbDataInput)+1; - BYTE *pbDataEnt =(BYTE *) strdup(entropy.c_str()); - DWORD cbDataEnt = strlen((char *)pbDataEnt)+1; - DataIn.pbData = pbDataInput; - DataIn.cbData = cbDataInput; - DataEnt.pbData = pbDataEnt; - DataEnt.cbData = cbDataEnt; - - CRYPTPROTECT_PROMPTSTRUCT prom; - - prom.cbSize = sizeof(prom); - prom.dwPromptFlags = 0; - - /********* - std::cerr << "Password (" << cbDataInput << "):"; - std::cerr << pbDataInput << std::endl; - std::cerr << "Entropy (" << cbDataEnt << "):"; - std::cerr << pbDataEnt << std::endl; - *********/ - - if(CryptProtectData( - &DataIn, - NULL, - &DataEnt, /* entropy.c_str(), */ - NULL, // Reserved. - &prom, - 0, - &DataOut)) - { - - /********** - std::cerr << "The encryption phase worked. ("; - std::cerr << DataOut.cbData << ")" << std::endl; - - for(unsigned int i = 0; i < DataOut.cbData; i++) - { - std::cerr << std::setw(2) << (int) DataOut.pbData[i]; - std::cerr << " "; - } - std::cerr << std::endl; - **********/ - - //std::cerr << "Save to: " << passwdfile; - //std::cerr << std::endl; - - /* save the data to the file */ - FILE *fp = RsDirUtil::rs_fopen(getAutologinFileName(ssl_id).c_str(), "wb"); - if (fp != NULL) - { - fwrite(DataOut.pbData, 1, DataOut.cbData, fp); - fclose(fp); - - std::cerr << "AutoLogin Data saved: "; - std::cerr << std::endl; - } - } - else - { - std::cerr << "Encryption Failed"; - std::cerr << std::endl; - } - - free(pbDataInput); - free(pbDataEnt); - LocalFree(DataOut.pbData); - return false; -#endif - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - -#endif -} - -bool RsLoginHandler::clearAutoLogin(const RsPeerId& ssl_id) -{ -#ifdef HAS_GNOME_KEYRING - if(GNOME_KEYRING_RESULT_OK == gnome_keyring_delete_password_sync(&my_schema,"RetroShare SSL Id", ssl_id.toStdString().c_str(),NULL)) - { - std::cout << "Successfully Cleared gnome keyring passwd for SSLID " << ssl_id << std::endl; - return true ; - } - else - { - std::cerr << "Could not clear gnome keyring passwd for SSLID " << ssl_id << std::endl; - return false ; - } -#elif defined(HAS_LIBSECRET) - // do synchronous clear - - GError *error = nullptr; - gboolean removed = secret_password_clear_sync (libsecret_get_schema(), nullptr, &error, - "RetroShare SSL Id", ssl_id.toStdString().c_str(), - NULL); - - if (error) { - g_error_free (error); - std::cerr << "Could not clearpasswd for SSLID " << ssl_id << " using libsecret: error" << std::endl; - return false ; - } else if (removed == FALSE) { - std::cerr << "Could not clearpasswd for SSLID " << ssl_id << " using libsecret: false" << std::endl; - return false ; - } - - std::cout << "Successfully Cleared passwd for SSLID " << ssl_id << " using libsecret" << std::endl; - return true ; -#else // HAS_GNOME_KEYRING / HAS_LIBSECRET - #ifdef __APPLE__ - - std::cerr << "clearAutoLogin() OSX Version" << std::endl; - //Call SecKeychainFindGenericPassword to get a password from the keychain: - - void *passwordData = NULL; - UInt32 passwordLength = 0; - std::string idtemp = ssl_id.toStdString(); - const char *userId = idtemp.c_str(); - UInt32 uidLength = strlen(userId); - SecKeychainItemRef itemRef = NULL; - - OSStatus status = SecKeychainFindGenericPassword ( - NULL, // default keychain - 10, // length of service name - "Retroshare", // service name - uidLength, // length of account name - userId, // account name - &passwordLength, // length of password - &passwordData, // pointer to password data - &itemRef // the item reference - ); - - std::cerr << "RsTryAutoLogin() SecKeychainFindGenericPassword returned: " << status << std::endl; - - if (status != 0) - { - std::cerr << "clearAutoLogin() Error Finding password " << std::endl; - - /* error */ - if (status == errSecItemNotFound) - { - //Is password on keychain? - std::cerr << "RsTryAutoLogin() Error - Looks like password is not in KeyChain " << std::endl; - } - } - else - { - std::cerr << "clearAutoLogin() Password found on KeyChain! " << std::endl; - - OSStatus deleteStatus = SecKeychainItemDelete (itemRef); - if (status != 0) - { - std::cerr << "clearAutoLogin() Failed to Delete Password status: " << deleteStatus << std::endl; - } - else - { - std::cerr << "clearAutoLogin() Deleted Password" << std::endl; - } - } - - //Free the data allocated by SecKeychainFindGenericPassword: - - SecKeychainItemFreeContent ( - NULL, //No attribute data to release - passwordData //Release data buffer allocated by SecKeychainFindGenericPassword - ); - - if (itemRef) CFRelease(itemRef); - - return (status == 0); - - /******************** OSX KeyChain stuff *****************************/ - - #else // WINDOWS / Generic Linux. - - std::string passwdfile = getAutologinFileName(ssl_id) ; - - FILE *fp = RsDirUtil::rs_fopen(passwdfile.c_str(), "wb"); - - if (fp != NULL) - { - fwrite(" ", 1, 1, fp); - fclose(fp); - bool removed = remove(passwdfile.c_str()); - - if(removed != 0) - std::cerr << "RsLoginHandler::clearAutoLogin(): Failed to Removed help file" << std::endl; - - std::cerr << "AutoLogin Data cleared "; - std::cerr << std::endl; - return true; - } - - return false; - #endif -#endif -} - -std::string RsLoginHandler::getAutologinFileName(const RsPeerId& /*ssl_id*/) -{ - return RsAccounts::AccountKeysDirectory() + "/" + "help.dta" ; -} - -#endif // RS_AUTOLOGIN diff --git a/libretroshare/src/rsserver/rsloginhandler.h b/libretroshare/src/rsserver/rsloginhandler.h deleted file mode 100644 index 1c95a741b..000000000 --- a/libretroshare/src/rsserver/rsloginhandler.h +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: rsloginhandler.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 retroshare team * - * * - * 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 . * - * * - *******************************************************************************/ - -#pragma once - -#include - -/** - * This class handles login, meaning that it retrieves the SSL password from - * either the keyring or help.dta file, if autologin is enabled, or from the - * ssl_passphrase.pgp file, asking for the GPG password to decrypt it. - * - * This class should handle the following scenario: - * - * Normal login: - * - SSL key is stored -> do autologin - * - SSL key is not stored - * - if we're actually in the login process, ask for the gpg passwd, and - * decrypt the key file - * - if we're just trying for autologin, don't ask for the gpg passwd and - * return null - * - * Key creation: - * - the key should be stored in the gpg file. - */ -class RsLoginHandler -{ -public: - /** - * Gets the SSL passwd by any means: try autologin, and look into gpg file - * if enable_gpg_key_callback==true - */ - static bool getSSLPassword( const RsPeerId& ssl_id, - bool enable_gpg_key_callback, - std::string& ssl_password); - - /** - * Checks whether the ssl passwd is already in the gpg file. If the file's - * not here, the passwd is stored there, encrypted with the current GPG key. - */ - static bool checkAndStoreSSLPasswdIntoGPGFile( - const RsPeerId& ssl_id, const std::string& ssl_passwd ); - -#ifdef RS_AUTOLOGIN - /** - * Stores the given ssl_id/passwd pair into the keyring, or by default into - * a file in /[ssl_id]/keys/help.dta - */ - static bool enableAutoLogin(const RsPeerId& ssl_id,const std::string& passwd) ; - - /// Clears autologin entry. - static bool clearAutoLogin(const RsPeerId& ssl_id) ; -#endif // RS_AUTOLOGIN - -private: - static bool getSSLPasswdFromGPGFile(const RsPeerId& ssl_id,std::string& sslPassword); - static std::string getSSLPasswdFileName(const RsPeerId& ssl_id); - -#ifdef RS_AUTOLOGIN - static bool tryAutoLogin(const RsPeerId& ssl_id,std::string& ssl_passwd); - static std::string getAutologinFileName(const RsPeerId& ssl_id); -#endif // RS_AUTOLOGIN -}; - diff --git a/libretroshare/src/scripts/checks.mk b/libretroshare/src/scripts/checks.mk deleted file mode 100644 index 61d242ef0..000000000 --- a/libretroshare/src/scripts/checks.mk +++ /dev/null @@ -1,25 +0,0 @@ -#Basic checks - -ifndef RS_TOP_DIR -dummy: - echo "RS_TOP_DIR is not defined in your makefile" -endif - -ifndef SSL_DIR -dummy: - echo "you must define SSL_DIR before you can compile" - -endif - -ifneq ($(OS),Linux) - ifneq ($(OS),MacOSX) - ifndef PTHREADS_DIR -dummy: - echo "you must define PTHREADS_DIR before you can compile" - - endif - endif -endif - - - diff --git a/libretroshare/src/scripts/config-cygwin.mk b/libretroshare/src/scripts/config-cygwin.mk deleted file mode 100644 index ec4518f68..000000000 --- a/libretroshare/src/scripts/config-cygwin.mk +++ /dev/null @@ -1,118 +0,0 @@ -ifneq ($(OS),Cygwin) -dummy: - echo "ERROR Cygwin configuration file included, but (OS != Cygwin) - -endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -PQI_USE_XPGP = 1 -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -########################################################################### - -#### DrBobs Versions.... Please Don't Delete. -### Comment out if needed. -ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW -SRC_ROOT=../../../.. - -PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads/pthreads.2 - -################### - -#ALT_SRC_ROOT=/cygdrive/c/RetroShareBuild/src -#SRC_ROOT=/cygdrive/c/RetroShareBuild/src - -#PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads-w32-2-8-0-release - -################### - -ZLIB_DIR=$(ALT_SRC_ROOT)/zlib-1.2.3 - -SSL_DIR=$(SRC_ROOT)/openssl-0.9.7g-xpgp-0.1c -UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) - -ifdef PQI_DEBUG - CFLAGS = -Wall -g $(INCLUDE) -else - CFLAGS = -Wall -O2 $(INCLUDE) -endif - -ifdef PQI_USE_XPGP - INCLUDE += -I $(SSL_DIR)/include -endif - -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -RSCFLAGS = -Wall -g $(INCLUDE) - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# Cygwin - ?same? as Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM - -######################################################################### -# OS specific Linking. -######################################################################### - -# for static pthread libs.... -WININC += -DPTW32_STATIC_LIB -WININC += -mno-cygwin -mwindows -fno-exceptions -WININC += -DWINDOWS_SYS - -WINLIB = -lws2_32 -luuid -lole32 -liphlpapi -WINLIB += -lcrypt32 -lwinmm - -CFLAGS += -I$(PTHREADS_DIR) $(WININC) -CFLAGS += -I$(ZLIB_DIR) - -LIBS = -L$(LIBDIR) -lretroshare -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) -endif - -LIBS += -lssl -lcrypto -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += -L$(ZLIB_DIR) -lz -LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d -LIBS += $(WINLIB) - -RSCFLAGS += $(WININC) - - diff --git a/libretroshare/src/scripts/config-linux.mk b/libretroshare/src/scripts/config-linux.mk deleted file mode 100644 index e82e903c2..000000000 --- a/libretroshare/src/scripts/config-linux.mk +++ /dev/null @@ -1,98 +0,0 @@ - -ifneq ($(OS),Linux) -dummy: - echo "ERROR Linux configuration file included, but (OS != Linux) - -endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -#PQI_USE_SSLONLY = 1 -#PQI_USE_XPGP = 1 - - -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -SSL_DIR=../../../../openssl-0.9.7g-xpgp-0.1c -UPNPC_DIR=../../../../miniupnpc-1.0 - -# Need to define miniupnpc version because API changed a little between v1.0 and 1.2 -# put 10 for 1.0 and 12 for 1.2 -DEFINES += -DMINIUPNPC_VERSION=10 - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) -#-I$(KADC_DIR) -CFLAGS = -Wall -g $(INCLUDE) -CFLAGS += ${DEFINES} - -ifdef PQI_USE_XPGP - INCLUDE += -I $(SSL_DIR)/include -endif - -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_SSLONLY - CFLAGS += -DPQI_USE_SSLONLY -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -RSCFLAGS = -Wall -g $(INCLUDE) -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# march=i686 causes problems while 64Bit compiling, GCC tries to generate Output for a m64 machine, but the marchi686 -# doesnt allow the instructionfs for that. -# -# gcc docu: http://gcc.gnu.org/onlinedocs/gcc-4.0.3/gcc/i386-and-x86_002d64-Options.html#i386-and-x86_002d64-Options - -# Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include ${DEFINES} -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM - -######################################################################### -# OS specific Linking. -######################################################################### - -LIBS = -L$(LIBDIR) -lretroshare -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) - endif -LIBS += -lssl -lcrypto -lpthread -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += $(XLIB) -ldl -lz -LIBS += -lgpgme - -RSLIBS = $(LIBS) - - diff --git a/libretroshare/src/scripts/config-macosx.mk b/libretroshare/src/scripts/config-macosx.mk deleted file mode 100644 index 7aa56d361..000000000 --- a/libretroshare/src/scripts/config-macosx.mk +++ /dev/null @@ -1,152 +0,0 @@ - -ifneq ($(OS),MacOSX) -dummy: - echo "ERROR MacOSX configuration file included, but (OS != MacOSX) - -endif - -############ LINUX CONFIGURATION ######################## - - -# FLAGS to decide if we want i386 Build or ppc Build -# -# - -# PPC is default -# Could define both for combined compilation... -# except might not work for bio_tou.c file! -# -# MAC_I386_BUILD = 1 -# MAC_PPC_BUILD = 1 - -#MAC_I386_BUILD = 1 -#MAC_PPC_BUILD = 1 - -ifndef MAC_I386_BUILD - MAC_PPC_BUILD = 1 -endif - -# flags for components.... -#PQI_USE_SSLONLY = 1 -#PQI_USE_XPGP = 1 - -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -SSL_DIR=../../../../../src/openssl-0.9.7g-xpgp-0.1c -UPNPC_DIR=../../../../../src/miniupnpc-1.0 - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm - -RANLIB = ranlib - -# Dummy ranlib -> can't do it until afterwards with universal binaries. -# RANLIB = ls -l - -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -OPT_DIR = /opt/local -OPT_INCLUDE = $(OPT_DIR)/include -OPT_LIBS = $(OPT_DIR)/lib - -INCLUDE = -I $(RS_TOP_DIR) -I $(OPT_INCLUDE) -#CFLAGS = -Wall -O3 -CFLAGS = -Wall -g - -# Flags for architecture builds. -ifdef MAC_I386_BUILD - CFLAGS += -arch i386 -endif - -ifdef MAC_PPC_BUILD - CFLAGS += -arch ppc -endif - -CFLAGS += $(INCLUDE) - -# This Line is for Universal BUILD for 10.4 + 10.5 -# (but unlikely to work unless Qt Libraries are build properly) -# CFLAGS += -isysroot /Developer/SDKs/MacOSX10.4u.sdk - -ifdef PQI_USE_XPGP - INCLUDE += -I $(SSL_DIR)/include - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_SSLONLY - CFLAGS += -DPQI_USE_SSLONLY -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -# RSCFLAGS = -Wall -O3 $(INCLUDE) - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - - -# Flags for architecture builds. -ifdef MAC_I386_BUILD - BIOCFLAGS = -arch i386 -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -endif - -ifdef MAC_PPC_BUILD - BIOCFLAGS = -arch ppc -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN -endif - - - -# MacOSX flags -# BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN - -# This is for the Universal Build... -# but is unlikely to work... as options are PPC specific.... -# -# BIOCFLAGS = -arch ppc -arch i386 -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN - - -######################################################################### -# OS specific Linking. -######################################################################### - -LIBS = -Wl,-search_paths_first - -# for Univeral BUILD -# LIBS += -arch ppc -arch i386 -# LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386 - -LIBS += -L$(LIBDIR) -lretroshare -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) - endif -LIBS += -lssl -lcrypto -lpthread -LIBS += -L$(OPT_LIBS) -LIBS += -lgpgme -lgpg-error -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += $(XLIB) -ldl -lz - -RSLIBS = $(LIBS) - - diff --git a/libretroshare/src/scripts/config-mingw.mk b/libretroshare/src/scripts/config-mingw.mk deleted file mode 100644 index c0040ac4e..000000000 --- a/libretroshare/src/scripts/config-mingw.mk +++ /dev/null @@ -1,138 +0,0 @@ -#ifneq ($(OS),"Win ") -#dummy: -# echo "ERROR OS = $(OS)" -# echo "ERROR MinGW configuration file included, but (OS != Win) -# -#endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -#PQI_USE_XPGP = 1 -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -########################################################################### - -#### DrBobs Versions.... Please Don't Delete. -### Comment out if needed. -SRC_ROOT_PKG=/home/Mark/prog/retroshare/package/rs-win-v0.5.0/src -SRC_ROOT_GPG=/local - -#ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW -#SRC_ROOT=../../../.. - -PTHREADS_DIR=$(SRC_ROOT_PKG)/pthreads-w32-2-8-0/Pre-built.2 -ZLIB_DIR=$(SRC_ROOT_PKG)/zlib-1.2.3 -SSL_DIR=$(SRC_ROOT_PKG)/openssl-tmp -UPNPC_DIR=$(SRC_ROOT_PKG)/miniupnpc-1.3 - -########################################################################### - -#### Enable this section for compiling with MSYS/MINGW compile -#SRC_ROOT=/home/linux - -#SSL_DIR=$(SRC_ROOT)/OpenSSL -#GPGME_DIR=$(SRC_ROOT)/gpgme-1.1.8 -#GPG_ERROR_DIR=$(SRC_ROOT)/libgpg-error-1.7 - -#ZLIB_DIR=$(SRC_ROOT)/zlib-1.2.3 -#UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 -#PTHREADS_DIR=$(SRC_ROOT)/pthreads-w32-2-8-0-release - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ####################################### - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) - -ifdef PQI_DEBUG - CFLAGS = -Wall -g $(INCLUDE) -else - CFLAGS = -Wall -O2 $(INCLUDE) -endif - -# These aren't used anymore.... really. -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -# SSL / pthreads / Zlib -# included by default for Windows compilation. -INCLUDE += -I $(SSL_DIR)/include -INCLUDE += -I$(PTHREADS_DIR) -INCLUDE += -I$(ZLIB_DIR) - - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# Cygwin - ?same? as Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM -BIOCFLAGS += -DWINDOWS_SYS - -######################################################################### -# OS specific Linking. -######################################################################### - -# for static pthread libs.... -#WININC += -DPTW32_STATIC_LIB -#WININC += -mno-cygwin -mwindows -fno-exceptions - -WININC += -DWINDOWS_SYS - -WINLIB = -lws2_32 -luuid -lole32 -liphlpapi -WINLIB += -lcrypt32 -lwinmm - -CFLAGS += -I$(SSL_DIR)/include -CFLAGS += -I$(PTHREADS_DIR)/include -CFLAGS += -I$(ZLIB_DIR) -CFLAGS += -I$(SRC_ROOT_GPG)/include - -### Enable this for GPGME and GPG ERROR dirs -#CFLAGS += -I$(GPGME_DIR)/src -#CFLAGS += -I$(GPG_ERROR_DIR)/src - -CFLAGS += $(WININC) - - - -LIBS = -L$(LIBDIR) -lretroshare - -LIBS += -L$(SSL_DIR) - -LIBS += -lssl -lcrypto -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += -L$(ZLIB_DIR) -lz -LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d -LIBS += $(WINLIB) - -#RSCFLAGS = -Wall -g $(INCLUDE) -#RSCFLAGS += $(WININC) - - diff --git a/libretroshare/src/scripts/config.mk b/libretroshare/src/scripts/config.mk deleted file mode 100644 index 9f22fa363..000000000 --- a/libretroshare/src/scripts/config.mk +++ /dev/null @@ -1,27 +0,0 @@ - -# determine which operating system -# -########################################################################### -#Define OS. -# -OS = Linux -#OS = MacOSX -#OS = Cygwin -#OS = Win # MinGw. -########################################################################### - -ifeq ($(OS),Linux) - include $(RS_TOP_DIR)/scripts/config-linux.mk -else - ifeq ($(OS),MacOSX) - include $(RS_TOP_DIR)/scripts/config-macosx.mk - else - ifeq ($(OS),Cygwin) - include $(RS_TOP_DIR)/scripts/config-cygwin.mk - else - include $(RS_TOP_DIR)/scripts/config-mingw.mk - endif - endif -endif - -########################################################################### diff --git a/libretroshare/src/scripts/documentation-script b/libretroshare/src/scripts/documentation-script deleted file mode 100755 index 0d47217bc..000000000 --- a/libretroshare/src/scripts/documentation-script +++ /dev/null @@ -1,16 +0,0 @@ - -#!/bin/bash -# This script creates a doxygen documentation of retroshare -# you need to install doxygen and graph-viz(dot tool) for script to work - - -echo "doxygen and graph viz must be installed" - -# create documentation -doxygen rsDocumentation || exit - -#indicate finshed -echo "complete" - - - diff --git a/libretroshare/src/scripts/makeMacUniversalLibrary.sh b/libretroshare/src/scripts/makeMacUniversalLibrary.sh deleted file mode 100755 index b1222d049..000000000 --- a/libretroshare/src/scripts/makeMacUniversalLibrary.sh +++ /dev/null @@ -1,35 +0,0 @@ -# -## clean up all bits of libretroshare -echo make clobber -make clobber -# -## make the standard version (PPC) -echo make librs -make librs -# -LIB=libretroshare.a -LIB_PPC=libretroshare_ppc.a -LIB_X86=libretroshare_x86.a - -MAC_SCRIPT="./scripts/config-macosx.mk" - -echo cp lib/$LIB lib/$LIB_PPC -cp lib/$LIB lib/$LIB_PPC - -echo make clobber -make clobber - -echo make "MAC_I386_BUILD=1" librs -make "MAC_I386_BUILD=1" librs - -echo cp lib/$LIB lib/$LIB_X86 -cp lib/$LIB lib/$LIB_X86 - -# magic combine trick. -echo cd lib -cd lib - -echo lipo -create libretroshare_*.a -output $LIB -lipo -create libretroshare_*.a -output $LIB - - diff --git a/libretroshare/src/scripts/regress.mk b/libretroshare/src/scripts/regress.mk deleted file mode 100644 index f80b48451..000000000 --- a/libretroshare/src/scripts/regress.mk +++ /dev/null @@ -1,25 +0,0 @@ - -testoutputfiles = $(foreach tt,$(1),$(tt).tstout) - -%.tstout : %.sh - -sh ./$< > $@ 2>&1 - -%.tstout : % - -./$< > $@ 2>&1 - -TESTOUT = $(call testoutputfiles,$(TESTS)) - -.phony : tests regress retest clobber - -tests: $(TESTS) - -regress: $(TESTOUT) - @-echo "--------------- SUCCESS (count):" - @-grep -c SUCCESS $(TESTOUT) - @-echo "--------------- FAILURE REPORTS:" - @-grep FAILURE $(TESTOUT) || echo no failures - @-echo "--------------- end" - -retest: - -/bin/rm $(TESTOUT) - diff --git a/libretroshare/src/scripts/rsDocumentation b/libretroshare/src/scripts/rsDocumentation deleted file mode 100644 index d21dfaa1c..000000000 --- a/libretroshare/src/scripts/rsDocumentation +++ /dev/null @@ -1,281 +0,0 @@ -# Doxyfile 1.5.3 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = retroshare -PROJECT_NUMBER = 1.0 -OUTPUT_DIRECTORY = ../ -CREATE_SUBDIRS = YES -OUTPUT_LANGUAGE = English -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class " \ - "The $name widget " \ - "The $name file " \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = ../ -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -QT_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = NO -OPTIMIZE_OUTPUT_JAVA = NO -BUILTIN_STL_SUPPORT = NO -CPP_CLI_SUPPORT = NO -DISTRIBUTE_GROUP_DOC = NO -SUBGROUPING = YES -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = YES -EXTRACT_PRIVATE = YES -EXTRACT_STATIC = YES -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -EXTRACT_ANON_NSPACES = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = NO -FILE_VERSION_FILTER = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO -WARN_FORMAT = "$file:$line: $text " -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = ../ -INPUT_ENCODING = UTF-8 -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.d \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.idl \ - *.odl \ - *.cs \ - *.php \ - *.php3 \ - *.inc \ - *.m \ - *.mm \ - *.dox \ - *.py \ - *.C \ - *.CC \ - *.C++ \ - *.II \ - *.I++ \ - *.H \ - *.HH \ - *.H++ \ - *.CS \ - *.PHP \ - *.PHP3 \ - *.M \ - *.MM \ - *.PY -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXCLUDE_SYMBOLS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS = -FILTER_SOURCE_FILES = NO -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = NO -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION = NO -REFERENCES_LINK_SOURCE = YES -USE_HTAGS = NO -VERBATIM_HEADERS = NO -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = NO -COLS_IN_ALPHA_INDEX = 5 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -HTML_DYNAMIC_SECTIONS = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = YES -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = NO -USE_PDFLATEX = NO -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = NO -MSCGEN_PATH = -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = NO -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = NO -CALLER_GRAPH = NO -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = YES -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -DOT_GRAPH_MAX_NODES = 50 -MAX_DOT_GRAPH_DEPTH = 1000 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO diff --git a/libretroshare/src/scripts/rules.mk b/libretroshare/src/scripts/rules.mk deleted file mode 100644 index f8d75c21f..000000000 --- a/libretroshare/src/scripts/rules.mk +++ /dev/null @@ -1,23 +0,0 @@ - -# defines required / used. -# -# CFLAGS -# -# - -librs: $(RSOBJ) - $(AR) r $(LIBRS) $(RSOBJ) - $(RANLIB) $(LIBRS) - -.cc.o: - $(CC) $(CFLAGS) -c $< - -clean: - -/bin/rm $(RSOBJ) $(EXECOBJ) $(TESTOBJ) - -clobber: clean retest - -/bin/rm $(EXEC) $(TESTS) - - -include $(RS_TOP_DIR)/scripts/regress.mk - diff --git a/libretroshare/src/serialiser/rsbaseserial.cc b/libretroshare/src/serialiser/rsbaseserial.cc deleted file mode 100644 index 276872364..000000000 --- a/libretroshare/src/serialiser/rsbaseserial.cc +++ /dev/null @@ -1,311 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsbaseserial.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include /* Included because GCC4.4 wants it */ -#include /* Included because GCC4.4 wants it */ - -#include "retroshare/rstypes.h" -#include "serialiser/rsbaseserial.h" -#include "util/rsnet.h" -#include "util/rstime.h" - -#include -#include - -/* UInt8 get/set */ - -bool getRawUInt8(const void *data, uint32_t size, uint32_t *offset, uint8_t *out) -{ - /* first check there is space */ - if (size < *offset + 1) - { - std::cerr << "(EE) Cannot deserialise uint8_t: not enough size." << std::endl; - return false; - } - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* extract the data */ - memcpy(out, buf, sizeof(uint8_t)); - (*offset) += 1; - - return true; -} - -bool setRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t in) -{ - /* first check there is space */ - if (size < *offset + 1) - { - std::cerr << "(EE) Cannot serialise uint8_t: not enough size." << std::endl; - return false; - } - - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* pack it in */ - memcpy(buf, &in, sizeof(uint8_t)); - - (*offset) += 1; - return true; -} -/* UInt16 get/set */ - -bool getRawUInt16(const void *data, uint32_t size, uint32_t *offset, uint16_t *out) -{ - /* first check there is space */ - if (size < *offset + 2) - { - std::cerr << "(EE) Cannot deserialise uint16_t: not enough size." << std::endl; - return false; - } - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* extract the data */ - uint16_t netorder_num; - memcpy(&netorder_num, buf, sizeof(uint16_t)); - - (*out) = ntohs(netorder_num); - (*offset) += 2; - return true; -} - -bool setRawUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t in) -{ - /* first check there is space */ - if (size < *offset + 2) - { - std::cerr << "(EE) Cannot serialise uint16_t: not enough size." << std::endl; - return false; - } - - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* convert the data to the right format */ - uint16_t netorder_num = htons(in); - - /* pack it in */ - memcpy(buf, &netorder_num, sizeof(uint16_t)); - - (*offset) += 2; - return true; -} - -/* UInt32 get/set */ - -bool getRawUInt32(const void *data, uint32_t size, uint32_t *offset, uint32_t *out) -{ - /* first check there is space */ - if (size < *offset + 4) - { - std::cerr << "(EE) Cannot deserialise uint32_t: not enough size." << std::endl; - return false; - } - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* extract the data */ - uint32_t netorder_num; - memcpy(&netorder_num, buf, sizeof(uint32_t)); - - (*out) = ntohl(netorder_num); - (*offset) += 4; - return true; -} - -bool setRawUInt32(void *data, uint32_t size, uint32_t *offset, uint32_t in) -{ - /* first check there is space */ - if (size < *offset + 4) - { - std::cerr << "(EE) Cannot serialise uint32_t: not enough size." << std::endl; - return false; - } - - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* convert the data to the right format */ - uint32_t netorder_num = htonl(in); - - /* pack it in */ - memcpy(buf, &netorder_num, sizeof(uint32_t)); - - (*offset) += 4; - return true; -} - -/* UInt64 get/set */ - -bool getRawUInt64(const void *data, uint32_t size, uint32_t *offset, uint64_t *out) -{ - /* first check there is space */ - if (size < *offset + 8) - { - std::cerr << "(EE) Cannot deserialise uint64_t: not enough size." << std::endl; - return false; - } - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* extract the data */ - uint64_t netorder_num; - memcpy(&netorder_num, buf, sizeof(uint64_t)); - - (*out) = ntohll(netorder_num); - (*offset) += 8; - return true; -} - -bool setRawUInt64(void *data, uint32_t size, uint32_t *offset, uint64_t in) -{ - /* first check there is space */ - if (size < *offset + 8) - { - std::cerr << "(EE) Cannot serialise uint64_t: not enough size." << std::endl; - return false; - } - - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* convert the data to the right format */ - uint64_t netorder_num = htonll(in); - - /* pack it in */ - memcpy(buf, &netorder_num, sizeof(uint64_t)); - - (*offset) += 8; - return true; -} - -bool getRawUFloat32(const void *data, uint32_t size, uint32_t *offset, float& f) -{ - uint32_t n ; - if(!getRawUInt32(data, size, offset, &n) ) - return false ; - - f = 1.0f/ ( n/(float)(~(uint32_t)0)) - 1.0f ; - - return true ; -} - -bool setRawUFloat32(void *data,uint32_t size,uint32_t *offset,float f) -{ - uint32_t sz = 4; - - if ( !data || size <= *offset || size < sz + *offset ) - { - std::cerr << "(EE) not enough room. SIZE+offset=" << sz+*offset << " and size is only " << size << std::endl; - return false; - } - if(f < 0.0f) - { - std::cerr << "(EE) Cannot serialise invalid negative float value " << f << " in " << __PRETTY_FUNCTION__ << std::endl; - return false ; - } - - // This serialisation is quite accurate. The max relative error is approx. - // 0.01% and most of the time less than 1e-05% The error is well distributed - // over numbers also. - // - uint32_t n = (f < 1e-7)?(~(uint32_t)0): ((uint32_t)( (1.0f/(1.0f+f) * (~(uint32_t)0)))) ; - - return setRawUInt32(data, size, offset, n); -} - - -uint32_t getRawStringSize(const std::string &outStr) -{ - return outStr.length() + 4; -} - -bool getRawString(const void *data, uint32_t size, uint32_t *offset, std::string &outStr) -{ - outStr.clear(); - - uint32_t len = 0; - if (!getRawUInt32(data, size, offset, &len)) - { - std::cerr << "getRawString() get size failed" << std::endl; - return false; - } - - /* check there is space for string */ - if(len > size || size-len < *offset) // better than if(size < *offset + len) because it avoids integer overflow - { - std::cerr << "getRawString() not enough size" << std::endl; - print_stacktrace(); - return false; - } - uint8_t *buf = &(((uint8_t *) data)[*offset]); - - for (uint32_t i = 0; i < len; i++) - { - outStr += buf[i]; - } - - (*offset) += len; - return true; -} - -bool setRawString(void *data, uint32_t size, uint32_t *offset, const std::string &inStr) -{ - uint32_t len = inStr.length(); - /* first check there is space */ - - if(size < 4 || len > size-4 || size-len-4 < *offset) // better than if(size < *offset + len + 4) because it avoids integer overflow - { - std::cerr << "setRawString() Not enough size" << std::endl; - return false; - } - - if (!setRawUInt32(data, size, offset, len)) - { - std::cerr << "setRawString() set size failed" << std::endl; - return false; - } - - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* pack it in */ - memcpy(buf, inStr.c_str(), len); - - (*offset) += len; - return true; -} - -bool getRawTimeT(const void *data,uint32_t size,uint32_t *offset,rstime_t& t) -{ - uint64_t T; - bool res = getRawUInt64(data,size,offset,&T); - t = T; - - if(t < 0) // [[unlikely]] - std::cerr << __PRETTY_FUNCTION__ << " got a negative time: " << t - << " this seems fishy, report to the developers!" << std::endl; - - return res; -} -bool setRawTimeT(void *data, uint32_t size, uint32_t *offset, const rstime_t& t) -{ - if(t < 0) // [[unlikely]] - std::cerr << __PRETTY_FUNCTION__ << " got a negative time: " << t - << " this seems fishy, report to the developers!" << std::endl; - - return setRawUInt64(data,size,offset,t) ; -} diff --git a/libretroshare/src/serialiser/rsbaseserial.h b/libretroshare/src/serialiser/rsbaseserial.h deleted file mode 100644 index 839932927..000000000 --- a/libretroshare/src/serialiser/rsbaseserial.h +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsbaseserial.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_BASE_PACKING_H -#define RS_BASE_PACKING_H - -#include -#include -#include - -#include "retroshare/rsids.h" -#include "util/rstime.h" - -/******************************************************************* - * This is at the lowlevel packing routines. They are usually - * created in pairs - one to pack the data, the other to unpack. - * - * getRawXXX(void *data, uint32_t size, uint32_t *offset, XXX *out); - * setRawXXX(void *data, uint32_t size, uint32_t *offset, XXX *in); - * - * - * data - the base pointer to the serialised data. - * size - size of the memory pointed to by data. - * *offset - where we want to (un)pack the data. - * This is incremented by the datasize. - * - * *in / *out - the data to (un)pack. - * - ******************************************************************/ - -bool getRawUInt8(const void *data, uint32_t size, uint32_t *offset, uint8_t *out); -bool setRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t in); - -bool getRawUInt16(const void *data, uint32_t size, uint32_t *offset, uint16_t *out); -bool setRawUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t in); - -bool getRawUInt32(const void *data, uint32_t size, uint32_t *offset, uint32_t *out); -bool setRawUInt32(void *data, uint32_t size, uint32_t *offset, uint32_t in); - -bool getRawUInt64(const void *data, uint32_t size, uint32_t *offset, uint64_t *out); -bool setRawUInt64(void *data, uint32_t size, uint32_t *offset, uint64_t in); - -bool getRawUFloat32(const void *data, uint32_t size, uint32_t *offset, float& out); -bool setRawUFloat32(void *data, uint32_t size, uint32_t *offset, float in); - -uint32_t getRawStringSize(const std::string &outStr); -bool getRawString(const void *data, uint32_t size, uint32_t *offset, std::string &outStr); -bool setRawString(void *data, uint32_t size, uint32_t *offset, const std::string &inStr); - -bool getRawTimeT(const void *data, uint32_t size, uint32_t *offset, rstime_t& outTime); -bool setRawTimeT(void *data, uint32_t size, uint32_t *offset, const rstime_t& inTime); - -#endif - diff --git a/libretroshare/src/serialiser/rsserial.cc b/libretroshare/src/serialiser/rsserial.cc deleted file mode 100644 index 52123abf1..000000000 --- a/libretroshare/src/serialiser/rsserial.cc +++ /dev/null @@ -1,563 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsserial.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "serialiser/rsbaseserial.h" - -#include "util/rsthreads.h" -#include "util/rsstring.h" -#include "util/rsprint.h" - -#include "rsitems/rsitem.h" -#include "rsitems/itempriorities.h" - -#include -#include -#include -#include -#include - - -/*** - * #define RSSERIAL_DEBUG 1 - * #define RSSERIAL_ERROR_DEBUG 1 -***/ - -// As these represent SERIOUS ERRORs, this debug should be left one. -#define RSSERIAL_ERROR_DEBUG 1 - - -#if defined(RSSERIAL_DEBUG) || defined(RSSERIAL_ERROR_DEBUG) - #include -#endif - -RsItem::RsItem(uint32_t t) -:type(t) -{ - _priority_level = QOS_PRIORITY_UNKNOWN ; // This value triggers PQIInterface to complain about undefined priorities -} - - -#ifdef DO_STATISTICS -class Counter -{ - public: - Counter(int i): _i(i) {} - Counter(): _i(0) {} - - int v() const { return _i ; } - int& v() { return _i ; } - private: - int _i ; -}; - - static RsMutex smtx ; - static std::map size_hits ; - static int nb_rsitem_creations = 0 ; - static int total_rsitem_mallocs = 0 ; - static int total_rsitem_frees = 0 ; - static int total_rsitem_freed = 0 ; - static rstime_t last_time = 0 ; - -void *RsItem::operator new(size_t s) -{ -// std::cerr << "New RsItem: s=" << s << std::endl; - - RsStackMutex m(smtx) ; - - ++size_hits[ s ].v() ; - - rstime_t now = time(NULL); - ++nb_rsitem_creations ; - total_rsitem_mallocs += s ; - - if(last_time + 20 < now) - { - std::cerr << "Memory statistics:" << std::endl; - std::cerr << " Total RsItem memory: " << total_rsitem_mallocs << std::endl; - std::cerr << " Total RsItem creations: " << nb_rsitem_creations << std::endl; - std::cerr << " Total RsItem freed memory: " << total_rsitem_freed << std::endl; - std::cerr << " Total RsItem deletions: " << total_rsitem_frees << std::endl; - std::cerr << "Now printing histogram:" << std::endl; - - for(std::map::const_iterator it(size_hits.begin());it!=size_hits.end();++it) - std::cerr << it->first << " " << it->second.v() << std::endl; - last_time = now ; - } - - RsItem *a = static_cast(::operator new(s)) ; - return a ; -} -void RsItem::operator delete(void *p,size_t s) -{ -// std::cerr << "Delete RsItem: s=" << s << std::endl; - - RsStackMutex m(smtx) ; - total_rsitem_freed += s ; - ++total_rsitem_frees ; - - ::operator delete(p) ; -} -#endif - -RsItem::RsItem(uint8_t ver, uint8_t cls, uint8_t t, uint8_t subtype) -{ - _priority_level = QOS_PRIORITY_UNKNOWN ; // This value triggers PQIInterface to complain about undefined priorities - - type = (ver << 24) + (cls << 16) + (t << 8) + subtype; -} - -RsItem::~RsItem() = default; - -void RsItem::print_string(std::string &out, uint16_t indent) -{ - std::ostringstream stream; - print(stream, indent); - - out += stream.str(); -} -uint32_t RsItem::PacketId() const -{ - return type; -} - -uint8_t RsItem::PacketVersion() -{ - return (type >> 24); -} - - -uint8_t RsItem::PacketClass() -{ - return (type >> 16) & 0xFF; -} - - -uint8_t RsItem::PacketType() -{ - return (type >> 8) & 0xFF; -} - - -uint8_t RsItem::PacketSubType() const -{ - return (type & 0xFF); -} - - - /* For Service Packets */ -RsItem::RsItem(uint8_t ver, uint16_t service, uint8_t subtype) -{ - _priority_level = QOS_PRIORITY_UNKNOWN ; // This value triggers PQIInterface to complain about undefined priorities - type = (ver << 24) + (service << 8) + subtype; - return; -} - -uint16_t RsItem::PacketService() const -{ - return (type >> 8) & 0xFFFF; -} - -void RsItem::setPacketService(uint16_t service) -{ - type &= 0xFF0000FF; - type |= (uint32_t) (service << 8); -} - - -RsSerialType::RsSerialType(uint32_t t) - :type(t & 0xFFFFFF00) -{ - return; -} - -RsSerialType::RsSerialType(uint8_t ver, uint8_t cls, uint8_t t) -{ - type = (ver << 24) + (cls << 16) + (t << 8); - return; -} - -RsSerialType::RsSerialType(uint8_t ver, uint16_t service) -{ - type = (ver << 24) + (service << 8); - return; -} - -RsSerialType::~RsSerialType() -{ - return; -} - -uint32_t RsSerialType::size(RsItem *) -{ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsSerialType::size()" << std::endl; -#endif - - /* base size: type + length */ - return 8; -} - -bool RsSerialType::serialise(RsItem */*item*/, void */*data*/, uint32_t */*size*/) -{ - std::cerr << "(EE) Empty method called for missing serialize() method in serializer class " << typeid(this).name() << std::endl; -#ifdef RSSERIAL_DEBUG - std::cerr << "RsSerialType::serialise()" << std::endl; -#endif - return false; -} - -RsItem * RsSerialType::deserialise(void */*data*/, uint32_t */*size*/) -{ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsSerialType::deserialise()" << std::endl; -#endif - return NULL; -} - -uint32_t RsSerialType::PacketId() const -{ - return type; -} - - - - -RsSerialiser::RsSerialiser() = default; - - -RsSerialiser::~RsSerialiser() -{ - /* clean up the map */ - std::map::iterator it; - for(it = serialisers.begin(); it != serialisers.end(); ++it) - { - delete (it->second); - } - serialisers.clear(); - return; -} - - - -bool RsSerialiser::addSerialType(RsSerialType *serialiser) -{ - uint32_t type = (serialiser->PacketId() & 0xFFFFFF00); - std::map::iterator it; - if (serialisers.end() != (it = serialisers.find(type))) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsSerialiser::addSerialType() Error Serialiser already exists!"; - std::cerr << std::endl; -#endif - return false; - } - - serialisers[type] = serialiser; - return true; -} - - - -uint32_t RsSerialiser::size(RsItem *item) -{ - /* find the type */ - uint32_t type = (item->PacketId() & 0xFFFFFF00); - std::map::iterator it; - - if (serialisers.end() == (it = serialisers.find(type))) - { - /* remove 8 more bits -> try again */ - type &= 0xFFFF0000; - if (serialisers.end() == (it = serialisers.find(type))) - { - /* one more try */ - type &= 0xFF000000; - if (serialisers.end() == (it = serialisers.find(type))) - { - -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::size() ERROR serialiser missing!" << std::endl; - - std::string out; - rs_sprintf(out, "%x", item->PacketId()); - - std::cerr << "RsSerialiser::size() PacketId: "; - std::cerr << out; - std::cerr << std::endl; -#endif - return 0; - } - } - } - -#ifdef RSSERIAL_DEBUG - std::string out; - rs_sprintf(out, "RsSerialiser::size() Item->PacketId(): %x matched to Serialiser Type: %lu", item->PacketId(), type); - std::cerr << out << std::endl; -#endif - - return (it->second)->size(item); -} - -bool RsSerialiser::serialise (RsItem *item, void *data, uint32_t *size) -{ - /* find the type */ - uint32_t type = (item->PacketId() & 0xFFFFFF00); - std::map::iterator it; - - if (serialisers.end() == (it = serialisers.find(type))) - { - /* remove 8 more bits -> try again */ - type &= 0xFFFF0000; - if (serialisers.end() == (it = serialisers.find(type))) - { - /* one more try */ - type &= 0xFF000000; - if (serialisers.end() == (it = serialisers.find(type))) - { - -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::serialise() ERROR serialiser missing!"; - std::string out; - rs_sprintf(out, "%x", item->PacketId()); - - std::cerr << "RsSerialiser::serialise() PacketId: "; - std::cerr << out; - std::cerr << std::endl; -#endif - return false; - } - } - } - -#ifdef RSSERIAL_DEBUG - std::string out; - rs_sprintf(out, "RsSerialiser::serialise() Item->PacketId(): %x matched to Serialiser Type: %lu", item->PacketId(), type); - std::cerr << out << std::endl; -#endif - - return (it->second)->serialise(item, data, size); -} - - - -RsItem * RsSerialiser::deserialise(void *data, uint32_t *size) -{ - /* find the type */ - if (*size < 8) - { -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::deserialise() ERROR Not Enough Data(1)"; - std::cerr << std::endl; -#endif - return NULL; - } - - uint32_t type = (getRsItemId(data) & 0xFFFFFF00); - uint32_t pkt_size = getRsItemSize(data); - - //std::cerr << "RsSerialiser::deserialise() RsItem Type: " << std::hex << getRsItemId(data) << " Size: " << pkt_size; - //std::cerr << std::endl; - - if (pkt_size > *size) - { -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::deserialise() ERROR Size mismatch(2)"; - std::cerr << std::endl; -#endif - return NULL; - } - if(pkt_size > getRsPktMaxSize()) - { - std::cerr << "(EE) trying to deserialise a packet with absurdely large size " << pkt_size << ". This means there's a bug upward or packet corruption. Packet content: " << RsUtil::BinToHex((unsigned char*)data,std::min(300u,pkt_size)) ; - return NULL ; - } - - /* store the packet size to return the amount we should use up */ - *size = pkt_size; - - std::map::iterator it; - if (serialisers.end() == (it = serialisers.find(type))) - { - /* remove 8 more bits -> try again */ - type &= 0xFFFF0000; - if (serialisers.end() == (it = serialisers.find(type))) - { - /* one more try */ - type &= 0xFF000000; - if (serialisers.end() == (it = serialisers.find(type))) - { - -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::deserialise() ERROR deserialiser missing!"; - std::string out; - rs_sprintf(out, "%x", getRsItemId(data)); - - std::cerr << "RsSerialiser::deserialise() PacketId: "; - std::cerr << out << std::endl; -#endif - return NULL; - } - } - } - - RsItem *item = (it->second)->deserialise(data, &pkt_size); - if (!item) - { -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::deserialise() ERROR Failed!"; - std::cerr << std::endl; - std::cerr << "RsSerialiser::deserialise() pkt_size: " << pkt_size << " vs *size: " << *size; - std::cerr << std::endl; - - //RsItem *item2 = (it->second)->deserialise(data, &pkt_size); - - uint32_t failedtype = getRsItemId(data); - std::cerr << "RsSerialiser::deserialise() FAILED PACKET Size: "; - std::cerr << getRsItemSize(data) << " ID: "; - std::cerr << std::hex << failedtype << std::endl; - std::cerr << "RsSerialiser::deserialise() FAILED PACKET: "; - std::cerr << " Version: " << std::hex << (uint32_t) getRsItemVersion(failedtype) << std::dec; - std::cerr << " Class: " << std::hex << (uint32_t) getRsItemClass(failedtype) << std::dec; - std::cerr << " Type: " << std::hex << (uint32_t) getRsItemType(failedtype) << std::dec; - std::cerr << " SubType: " << std::hex << (uint32_t) getRsItemSubType(failedtype) << std::dec; - std::cerr << " Data: " << RsUtil::BinToHex((char*)data,pkt_size).substr(0,300) << std::endl; - std::cerr << std::endl; -#endif - return NULL; - } - - if (pkt_size != *size) - { -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::deserialise() ERROR: size mismatch!"; - std::cerr << std::endl; - std::cerr << "RsSerialiser::deserialise() pkt_size: " << pkt_size << " vs *size: " << *size; - std::cerr << std::endl; - - uint32_t failedtype = getRsItemId(data); - std::cerr << "RsSerialiser::deserialise() FAILED PACKET Size: "; - std::cerr << getRsItemSize(data) << " ID: "; - std::cerr << std::hex << failedtype << std::dec; - std::cerr << "RsSerialiser::deserialise() FAILED PACKET: "; - std::cerr << " Version: " << std::hex << (uint32_t) getRsItemVersion(failedtype) << std::dec; - std::cerr << " Class: " << std::hex << (uint32_t) getRsItemClass(failedtype) << std::dec; - std::cerr << " Type: " << std::hex << (uint32_t) getRsItemType(failedtype) << std::dec; - std::cerr << " SubType: " << std::hex << (uint32_t) getRsItemSubType(failedtype) << std::dec; - std::cerr << " Data: " << RsUtil::BinToHex((char*)data,pkt_size).substr(0,300) << std::endl; - std::cerr << std::endl; -#endif - } - return item; -} - - -bool setRsItemHeader(void *data, uint32_t size, uint32_t type, uint32_t pktsize) -{ - if (size < 8) - return false; - - uint32_t offset = 0; - bool ok = true; - ok &= setRawUInt32(data, 8, &offset, type); - ok &= setRawUInt32(data, 8, &offset, pktsize); - - return ok; -} - - - -uint32_t getRsItemId(void *data) -{ - uint32_t type = 0; - uint32_t offset = 0; - getRawUInt32(data, 4, &offset, &type); - return type; -} - - -uint32_t getRsItemSize(void *data) -{ - uint32_t size = 0; - uint32_t offset = 4; - getRawUInt32(data, 8, &offset, &size); - return size; -} - -uint8_t getRsItemVersion(uint32_t type) -{ - return (type >> 24); -} - -uint8_t getRsItemClass(uint32_t type) -{ - return (type >> 16) & 0xFF; -} - -uint8_t getRsItemType(uint32_t type) -{ - return (type >> 8) & 0xFF; -} - -uint8_t getRsItemSubType(uint32_t type) -{ - return (type & 0xFF); -} - -uint16_t getRsItemService(uint32_t type) -{ - return (type >> 8) & 0xFFFF; -} - - -std::ostream &printRsItemBase(std::ostream &out, std::string clsName, uint16_t indent) -{ - printIndent(out, indent); - out << "RsItem: " << clsName << " ####################################"; - out << std::endl; - return out; -} - -std::ostream &printRsItemEnd(std::ostream &out, std::string clsName, uint16_t indent) -{ - printIndent(out, indent); - out << "###################### " << clsName << " #####################"; - out << std::endl; - return out; -} - -std::ostream &RsRawItem::print(std::ostream &out, uint16_t indent) -{ - printRsItemBase(out, "RsRawItem", indent); - printIndent(out, indent); - out << "Size: " << len << std::endl; - printRsItemEnd(out, "RsRawItem", indent); - return out; -} - -uint32_t getRsPktMaxSize() { return RsSerialiser::MAX_SERIAL_SIZE; } - -uint32_t getRsPktBaseSize() -{ - return 8; /* 4 + 4 */ -} - diff --git a/libretroshare/src/serialiser/rsserial.h b/libretroshare/src/serialiser/rsserial.h deleted file mode 100644 index 168db8d75..000000000 --- a/libretroshare/src/serialiser/rsserial.h +++ /dev/null @@ -1,114 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsserial.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "util/rsdeprecate.h" - -/******************************************************************* - * This is the Top-Level serialiser/deserialise, - * - * Data is Serialised into the following format - * - * ----------------------------------------- - * | TYPE (4 bytes) | Size (4 bytes) | - * ----------------------------------------- - * | | - * | Data .... | - * | | - * ----------------------------------------- - * - * Size is the total size of the packet (including the 8 byte header) - * Type is composed of: - * - * 8 bits: Version (0x01) - * 8 bits: Class - * 8 bits: Type - * 8 bits: SubType - ******************************************************************/ - -const uint8_t RS_PKT_VERSION1 = 0x01; -const uint8_t RS_PKT_VERSION_SERVICE = 0x02; - -const uint8_t RS_PKT_CLASS_BASE = 0x01; -const uint8_t RS_PKT_CLASS_CONFIG = 0x02; - -const uint8_t RS_PKT_SUBTYPE_DEFAULT = 0x01; /* if only one subtype */ - -struct RsItem; -class RsSerialType ; - - -class RsSerialiser -{ -public: - /** Remember that every pqistreamer allocates an input buffer of this size! - * So don't make it too big! */ - static constexpr uint32_t MAX_SERIAL_SIZE = 262143; /* 2^18 -1 */ - - RsSerialiser(); - ~RsSerialiser(); - bool addSerialType(RsSerialType *type); - - uint32_t size(RsItem *); - bool serialise (RsItem *item, void *data, uint32_t *size); - RsItem * deserialise(void *data, uint32_t *size); - - -private: - std::map serialisers; -}; - -bool setRsItemHeader(void *data, uint32_t size, uint32_t type, uint32_t pktsize); - -/* Extract Header Information from Packet */ -uint32_t getRsItemId(void *data); -uint32_t getRsItemSize(void *data); - -uint8_t getRsItemVersion(uint32_t type); -uint8_t getRsItemClass(uint32_t type); -uint8_t getRsItemType(uint32_t type); -uint8_t getRsItemSubType(uint32_t type); - -uint16_t getRsItemService(uint32_t type); - -/* size constants */ -uint32_t getRsPktBaseSize(); - -RS_DEPRECATED_FOR(RsSerialiser::MAX_SERIAL_SIZE) -uint32_t getRsPktMaxSize(); - - - -/* helper fns for printing */ -std::ostream &printRsItemBase(std::ostream &o, std::string n, uint16_t i); -std::ostream &printRsItemEnd(std::ostream &o, std::string n, uint16_t i); - -/* defined in rstlvtypes.cc - redeclared here for ease */ -std::ostream &printIndent(std::ostream &out, uint16_t indent); -/* Wrapper class for data that is serialised somewhere else */ diff --git a/libretroshare/src/serialiser/rsserializable.cc b/libretroshare/src/serialiser/rsserializable.cc deleted file mode 100644 index a5a329e6d..000000000 --- a/libretroshare/src/serialiser/rsserializable.cc +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************* - * libretroshare: retroshare core library * - * * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#include "serialiser/rsserializable.h" - -#include - -std::ostream& operator<<(std::ostream& out, const RsSerializable& serializable) -{ - RsGenericSerializer::SerializeContext ctx; - const_cast(serializable) // safe with TO_JSON - .serial_process(RsGenericSerializer::TO_JSON, ctx); - return out << ctx.mJson; -} diff --git a/libretroshare/src/serialiser/rsserializable.h b/libretroshare/src/serialiser/rsserializable.h deleted file mode 100644 index 5e115e673..000000000 --- a/libretroshare/src/serialiser/rsserializable.h +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsserializable.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "serialiser/rsserializer.h" - -#include - - -/** @brief Minimal ancestor for all serializable structs in RetroShare. - * If you want your struct to be easly serializable you should inherit from this - * struct. - */ -struct RsSerializable -{ - /** Process struct members to serialize in this method taking advantage of - * the helper macro @see RS_SERIAL_PROCESS(I) - */ - virtual void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) = 0; - - virtual ~RsSerializable() = default; -}; - -/** @def RS_SERIAL_PROCESS(I) - * Use this macro to process the members of `YourSerializable` for serial - * processing inside `YourSerializable::serial_process(j, ctx)` - * - * Pay special attention for member of enum type which must be declared - * specifying the underlying type otherwise the serialization format may differ - * in an uncompatible way depending on the compiler/platform. - * - * Inspired by http://stackoverflow.com/a/39345864 - */ -#define RS_SERIAL_PROCESS(I) do { \ - RsTypeSerializer::serial_process(j, ctx, I, #I ); \ - } while(0) - -std::ostream &operator<<(std::ostream& out, const RsSerializable& serializable); diff --git a/libretroshare/src/serialiser/rsserializer.cc b/libretroshare/src/serialiser/rsserializer.cc deleted file mode 100644 index 1a029ee2e..000000000 --- a/libretroshare/src/serialiser/rsserializer.cc +++ /dev/null @@ -1,289 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsserializer.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Cyril Soler * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - ******************************************************************************/ - -#include - -#include "rsitems/rsitem.h" -#include "util/rsprint.h" -#include "serialiser/rsserializer.h" -#include "serialiser/rstypeserializer.h" -#include "util/stacktrace.h" -#include "util/rsdebug.h" - -RsItem *RsServiceSerializer::deserialise(void *data, uint32_t *size) -{ - if(!data || !size || *size < 8) - { - RsErr() << __PRETTY_FUNCTION__ << " Called with inconsistent parameters data: " << std::endl; - if(data) - RsErr() << "Data is: " << RsUtil::BinToHex(static_cast(data),std::min(50u,*size)) << ((*size>50)?"...":"") << std::endl; - else - RsErr() << "Null Data" << std::endl; - - RsErr() << " size: " << static_cast(size) << " *size: " << (size ? *size : 0) << std::endl - << " this should never happen!" - << std::endl; - print_stacktrace(); - return nullptr; - } - - if(!!(mFlags & RsSerializationFlags::SKIP_HEADER)) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot deserialise item with flag " - << "SKIP_HEADER. Check your code!" << std::endl; - print_stacktrace(); - return nullptr; - } - - uint32_t rstype = getRsItemId(const_cast((const void*)data)) ; - - RsItem *item = create_item(getRsItemService(rstype),getRsItemSubType(rstype)) ; - - if(!item) - { - std::cerr << "(EE) " << typeid(*this).name() << ": cannot deserialise unknown item subtype " << std::hex << (int)getRsItemSubType(rstype) << std::dec << std::endl; - std::cerr << "(EE) Data is: " << RsUtil::BinToHex(static_cast(data),std::min(50u,*size)) << ((*size>50)?"...":"") << std::endl; - return NULL ; - } - - SerializeContext ctx( - const_cast(static_cast(data)), *size, - mFlags ); - ctx.mOffset = 8 ; - - item->serial_process(RsGenericSerializer::DESERIALIZE, ctx) ; - - if(ctx.mSize < ctx.mOffset) - { - std::cerr << "RsSerializer::deserialise(): ERROR. offset does not match expected size!" << std::endl; - delete item ; - return NULL ; - } - *size = ctx.mOffset ; - - if(ctx.mOk) - return item ; - - delete item ; - return NULL ; -} -RsItem *RsConfigSerializer::deserialise(void *data, uint32_t *size) -{ - if(!!(mFlags & RsSerializationFlags::SKIP_HEADER)) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot deserialise item with flag " - << "SKIP_HEADER. Check your code!" << std::endl; - print_stacktrace(); - return nullptr; - } - - uint32_t rstype = getRsItemId(const_cast((const void*)data)) ; - - RsItem *item = create_item(getRsItemType(rstype),getRsItemSubType(rstype)) ; - - if(!item) - { - std::cerr << "(EE) " << typeid(*this).name() << ": cannot deserialise unknown item subtype " << std::hex << (int)getRsItemSubType(rstype) << std::dec << std::endl; - std::cerr << "(EE) Data is: " << RsUtil::BinToHex(static_cast(data),std::min(50u,*size)) << ((*size>50)?"...":"") << std::endl; - return NULL ; - } - - SerializeContext ctx( - const_cast(static_cast(data)), *size, - mFlags ); - ctx.mOffset = 8 ; - - item->serial_process(DESERIALIZE, ctx) ; - - if(ctx.mSize < ctx.mOffset) - { - std::cerr << "RsSerializer::deserialise(): ERROR. offset does not match expected size!" << std::endl; - delete item ; - return NULL ; - } - *size = ctx.mOffset ; - - if(ctx.mOk) - return item ; - - delete item ; - return NULL ; -} - -bool RsGenericSerializer::serialise(RsItem* item, void* data, uint32_t* size) -{ - uint32_t tlvsize = this->size(item); - - constexpr auto fName = __PRETTY_FUNCTION__; - const auto failure = [=](std::error_condition ec) - { - RsErr() << fName << " " << ec << std::endl; - print_stacktrace(); - return false; - }; - - if(tlvsize > *size) return failure(std::errc::no_buffer_space); - - SerializeContext ctx(static_cast(data), tlvsize, mFlags); - - if(!(mFlags & RsSerializationFlags::SKIP_HEADER)) - { - if(!setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize)) - return failure(std::errc::no_buffer_space); - ctx.mOffset = 8; - } - - item->serial_process(RsGenericSerializer::SERIALIZE,ctx); - - if(ctx.mSize != ctx.mOffset) return failure(std::errc::message_size); - - *size = ctx.mOffset; - return true; -} - -uint32_t RsGenericSerializer::size(RsItem *item) -{ - SerializeContext ctx(nullptr, 0, mFlags); - - if(!!(mFlags & RsSerializationFlags::SKIP_HEADER)) ctx.mOffset = 0; - else ctx.mOffset = 8; // header size - item->serial_process(SIZE_ESTIMATE, ctx) ; - - return ctx.mOffset ; -} - -void RsGenericSerializer::print(RsItem *item) -{ - SerializeContext ctx(nullptr, 0, mFlags); - - std::cerr << "***** RsItem class: \"" << typeid(*item).name() << "\" *****" << std::endl; - item->serial_process(PRINT, ctx) ; - std::cerr << "******************************" << std::endl; -} - -uint32_t RsRawSerialiser::size(RsItem *i) -{ - RsRawItem *item = dynamic_cast(i); - - if (item) - { - return item->getRawLength(); - } - return 0; -} - -/* serialise the data to the buffer */ -bool RsRawSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) -{ - RsRawItem *item = dynamic_cast(i); - if (!item) - { - return false; - } - - #ifdef RSSERIAL_DEBUG - std::cerr << "RsRawSerialiser::serialise() serializing raw item. pktsize : " << *pktsize; - #endif - - uint32_t tlvsize = item->getRawLength(); - #ifdef RSSERIAL_DEBUG - std::cerr << "tlvsize : " << tlvsize << std::endl; - #endif - - if (*pktsize < tlvsize) - return false; /* not enough space */ - - if (tlvsize > getRsPktMaxSize()) - { - std::cerr << "(EE) Serialised packet is too big. Maximum allowed size is " << getRsPktMaxSize() << ". Serialised size is " << tlvsize << ". Please tune your service to correctly split packets" << std::endl; - return false; /* packet too big */ - } - - *pktsize = tlvsize; - - /* its serialised already!!! */ - memcpy(data, item->getRawData(), tlvsize); - - return true; -} - -RsItem *RsRawSerialiser::deserialise(void *data, uint32_t *pktsize) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - if (RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) - { - return NULL; /* wrong type */ - } - - if (*pktsize < rssize) /* check size */ - return NULL; /* not enough data */ - - if (rssize > getRsPktMaxSize()) - return NULL; /* packet too big */ - - /* set the packet length */ - *pktsize = rssize; - - RsRawItem *item = new RsRawItem(rstype, rssize); - void *item_data = item->getRawData(); - - memcpy(item_data, data, rssize); - - return item; -} - - -RsGenericSerializer::SerializeContext::SerializeContext( - uint8_t* data, uint32_t size, RsSerializationFlags flags, - RsJson::AllocatorType* allocator ) : - mData(data), mSize(size), mOffset(0), mOk(true), mFlags(flags), - mJson(rapidjson::kObjectType, allocator) -{ - if(data) - { - if(size == 0) - { - RsFatal() << __PRETTY_FUNCTION__ << " data passed without " - << "size! This make no sense report to developers!" - << std::endl; - print_stacktrace(); - exit(-EINVAL); - } - - if(!!(flags & RsSerializationFlags::YIELDING)) - { - RsFatal() << __PRETTY_FUNCTION__ - << " Attempt to create a " - << "binary serialization context with " - << "SERIALIZATION_FLAG_YIELDING! " - << "This make no sense report to developers!" - << std::endl; - print_stacktrace(); - exit(-EINVAL); - } - } -} diff --git a/libretroshare/src/serialiser/rsserializer.h b/libretroshare/src/serialiser/rsserializer.h deleted file mode 100644 index 1b67e2675..000000000 --- a/libretroshare/src/serialiser/rsserializer.h +++ /dev/null @@ -1,319 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsserializer.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Cyril Soler * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Retroshare Serialization code // -/////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Classes -// ======= -// -// RsSerialiser ----------------+ std::map -// -// RsSerialType -// | -// +----------- RsRawSerializer -// | -// +----------- RsGenericSerializer -// | -// +----------- RsConfigSerializer -// | | -// | +----------- Specific config serializers -// | +----------- ... -// | -// +----------- RsServiceSerializer -// | -// +----------- Specific service serializers -// +----------- ... -// +----------- ... -// -// -// Steps to derive a serializer for a new service: -// ============================================== -// -// 1 - create a serializer class, and overload create_item() to create a new item of your own service for each item type constant: -// -// class MyServiceSerializer: public RsServiceSerializer -// { -// MyServiceSerializer() : RsServiceSerializer(MY_SERVICE_IDENTIFIER) {} -// -// RsItem *create_item(uint16_t service,uint8_t item_subtype) const // mind the "const"! -// { -// if(service != MY_SERVICE_IDENTIFIER) return NULL ; -// -// switch(item_subtype) -// { -// case MY_ITEM_SUBTYPE_01: return new MyServiceItem(); -// default: -// return NULL ; -// } -// } -// } -// -// 2 - create your own items, and overload serial_process in order to define the serialized structure: -// -// class MyServiceItem: public RsItem -// { -// virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -// { -// RsTypeSerializer::serial_process (j,ctx,count,"count") ; // uint32_t is not really needed here, except for explicitly avoiding int types convertion -// RsTypeSerializer::serial_process (j,ctx,update_times,"update_times") ; // will serialize the map and its content -// RsTypeSerializer::serial_process(j,ctx,key,"key") ; // note the explicit call to TlvItem -// RsTypeSerializer::serial_process (j,ctx,dh_key,"dh_key") ; // template will automatically require serialise/deserialise/size/print_data for your type -// } -// -// private: -// uint32_t count ; // example of an int type. All int sizes are supported -// std::map update_times ; // example of a std::map. All std containers are supported. -// RsTlvSecurityKey key ; // example of a TlvItem class. -// BIGNUM *dh_key; // example of a class that needs its own serializer (see below) -// }; -// -// Some types may not be already handled by RsTypeSerializer, so in this case, you need to specialise the template for your own type. But this is quite unlikely to -// happen. In most cases, for instance in your structure types, serialization is directly done by calling RsTypeSerializer::serial_process() on each member of the type. -// In case you really need a specific serialization for soe particular type, here is how to do it, with the example of BIGNUM* (a crypto primitive): -// -// template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, BIGNUM * const & member) -// { -// uint32_t s = BN_num_bytes(member) ; -// -// if(size < offset + 4 + s) -// return false ; -// -// bool ok = true ; -// ok &= setRawUInt32(data, size, &offset, s); -// -// BN_bn2bin(member,&((unsigned char *)data)[offset]) ; -// offset += s ; -// -// return ok; -// } -// template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, BIGNUM *& member) -// { -// uint32_t s=0 ; -// bool ok = true ; -// ok &= getRawUInt32(data, size, &offset, &s); -// -// if(s > size || size - s < offset) -// return false ; -// -// member = BN_bin2bn(&((unsigned char *)data)[offset],s,NULL) ; -// offset += s ; -// -// return ok; -// } -// template<> uint32_t RsTypeSerializer::serial_size(BIGNUM * const & member) -// { -// return 4 + BN_num_bytes(member) ; -// } -// template<> void RsTypeSerializer::print_data(const std::string& name,BIGNUM * const & /* member */) -// { -// std::cerr << "[BIGNUM] : " << name << std::endl; -// } -// -// 3 - in your service, overload the serialiser declaration to add your own: -// -// MyService::MyService() -// { -// addSerialType(new MyServiceSerializer()) ; -// } -// -// If needed, you may serialize your own items by calling: -// -// uint32_t size = MySerializer().size(item) ; -// uint8_t *data = (uint8_t*)malloc(size); -// MySerializer().serialise(item,data,size) ; -// -// 4 - in your service, receive and send items by calling recvItem() and sendItem() respectively. -// -#include -#include -#include -#include - -#include "retroshare/rsflags.h" -#include "serialiser/rsserial.h" -#include "util/rsdeprecate.h" -#include "util/rsjson.h" - -struct RsItem; - -// This is the base class for serializers. - -class RsSerialType -{ -public: - RsSerialType(uint32_t t); /* only uses top 24bits */ - RsSerialType(uint8_t ver, uint8_t cls, uint8_t t); - RsSerialType(uint8_t ver, uint16_t service); - - virtual ~RsSerialType(); - - virtual uint32_t size(RsItem *)=0; - virtual bool serialise (RsItem *item, void *data, uint32_t *size)=0; - virtual RsItem * deserialise(void *data, uint32_t *size)=0; - - uint32_t PacketId() const; -private: - uint32_t type; -}; - -// This class is only used internally to p3service. It should not be used explicitely otherwise. - -class RsRawSerialiser: public RsSerialType -{ - public: - RsRawSerialiser() :RsSerialType(RS_PKT_VERSION_SERVICE, 0, 0) {} - virtual ~RsRawSerialiser() { } - - virtual uint32_t size(RsItem *); - virtual bool serialise (RsItem *item, void *data, uint32_t *size); - virtual RsItem * deserialise(void *data, uint32_t *size); -}; - -/** These are convenience flags to be used by the items when processing the - * data. The names of the flags are not very important. What matters is that - * the serial_process() method of each item correctly deals with the data - * when it sees the flags, if the serialiser sets them. - * By default the flags are not set and shouldn't be handled. - * When deriving a new serializer, the user can set his own flags, using - * compatible values - */ -enum class RsSerializationFlags -{ - NONE = 0, - CONFIG = 1, - SIGNATURE = 2, - SKIP_HEADER = 4, - - /** Used for JSON deserialization in JSON API, it causes the deserialization - * to continue even if some field is missing (or incorrect), this way the - * API is more user friendly as some methods need just part of the structs - * they take as parameters. */ - YIELDING = 8, - - /** When set integers typer are serialized/deserialized in Variable Length - * Quantity mode - * @see https://en.wikipedia.org/wiki/Variable-length_quantity - * This type of encoding is efficent when absoulte value is usually much - * smaller then the maximum representable with the original type. - * This encoding is also capable of representing big values at expences of a - * one more byte used. - */ - INTEGER_VLQ = 16 -}; -RS_REGISTER_ENUM_FLAGS_TYPE(RsSerializationFlags); - -/// Top class for all services and config serializers. -struct RsGenericSerializer : RsSerialType -{ - typedef enum - { - SIZE_ESTIMATE = 0x01, - SERIALIZE = 0x02, - DESERIALIZE = 0x03, - PRINT = 0x04, /// @deprecated use rsdebug.h << operator instead - TO_JSON, - FROM_JSON - } SerializeJob; - - struct SerializeContext - { - /** Allow shared allocator usage to avoid costly JSON deepcopy for - * nested RsSerializable */ - SerializeContext( - uint8_t* data = nullptr, uint32_t size = 0, - RsSerializationFlags flags = RsSerializationFlags::NONE, - RsJson::AllocatorType* allocator = nullptr); - - unsigned char *mData; - uint32_t mSize; - uint32_t mOffset; - bool mOk; - RsSerializationFlags mFlags; - RsJson mJson; - }; - - /** - * The following functions overload RsSerialType. - * They *should not* need to be further overloaded. - */ - RsItem *deserialise(void *data,uint32_t *size) = 0; - bool serialise(RsItem *item,void *data,uint32_t *size); - uint32_t size(RsItem *item); - void print(RsItem *item); - -protected: - RsGenericSerializer( - uint8_t serial_class, uint8_t serial_type, - RsSerializationFlags flags ): - RsSerialType( RS_PKT_VERSION1, serial_class, serial_type), - mFlags(flags) {} - - RsGenericSerializer( - uint16_t service, RsSerializationFlags flags ): - RsSerialType( RS_PKT_VERSION_SERVICE, service ), mFlags(flags) {} - - RsSerializationFlags mFlags; -}; - - -/** Top class for service serializers. - * Derive your on service serializer from this class and overload creat_item(). - */ -struct RsServiceSerializer : RsGenericSerializer -{ - RsServiceSerializer( - uint16_t service_id, - RsSerializationFlags flags = RsSerializationFlags::NONE ) : - RsGenericSerializer(service_id, flags) {} - - /*! should be overloaded to create the correct type of item depending on the - * data */ - virtual RsItem *create_item( uint16_t /* service */, - uint8_t /* item_sub_id */ ) const = 0; - - RsItem *deserialise(void *data, uint32_t *size); -}; - - -/** Top class for config serializers. - * Config serializers are only used internally by RS core. - * The development of new services or plugins do not need this. - */ -struct RsConfigSerializer : RsGenericSerializer -{ - RsConfigSerializer( - uint8_t config_class, uint8_t config_type, - RsSerializationFlags flags = RsSerializationFlags::NONE ) : - RsGenericSerializer(config_class, config_type, flags) {} - - /*! should be overloaded to create the correct type of item depending on the - * data */ - virtual RsItem *create_item(uint8_t /* item_type */, - uint8_t /* item_sub_type */) const = 0; - - RsItem *deserialise(void *data,uint32_t *size); -}; - diff --git a/libretroshare/src/serialiser/rstlvaddrs.cc b/libretroshare/src/serialiser/rstlvaddrs.cc deleted file mode 100644 index 5f9a06390..000000000 --- a/libretroshare/src/serialiser/rstlvaddrs.cc +++ /dev/null @@ -1,434 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvaddr.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvaddrs.h" -#include "serialiser/rsbaseserial.h" - -/************************************* RsTlvIpAddress ************************************/ - -RsTlvIpAddress::RsTlvIpAddress() - :RsTlvItem() -{ - sockaddr_storage_clear(addr); - return; -} - -void RsTlvIpAddress::TlvClear() -{ - sockaddr_storage_clear(addr); -} - -uint32_t RsTlvIpAddress::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; - switch(addr.ss_family) - { - default: - case 0: - break; - case AF_INET: - s += GetTlvIpAddrPortV4Size(); - break; - case AF_INET6: - s += GetTlvIpAddrPortV6Size(); - break; - } - return s; -} - -bool RsTlvIpAddress::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_ADDRESS, tlvsize); - - switch(addr.ss_family) - { - default: - case 0: - break; - case AF_INET: - ok &= SetTlvIpAddrPortV4(data, tlvend, offset, TLV_TYPE_IPV4, (struct sockaddr_in *) &addr); - break; - - case AF_INET6: - ok &= SetTlvIpAddrPortV6(data, tlvend, offset, TLV_TYPE_IPV6, (struct sockaddr_in6 *) &addr); - break; - } - return ok; - -} - - -bool RsTlvIpAddress::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_ADDRESS) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - if (*offset == tlvend) - { - /* empty address */ - return ok; - } - - uint16_t iptype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - switch(iptype) - { - case TLV_TYPE_IPV4: - ok &= GetTlvIpAddrPortV4(data, tlvend, offset, TLV_TYPE_IPV4, (struct sockaddr_in *) &addr); - break; - case TLV_TYPE_IPV6: - ok &= GetTlvIpAddrPortV6(data, tlvend, offset, TLV_TYPE_IPV6, (struct sockaddr_in6 *) &addr); - break; - default: - break; - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvIpAddress::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - -std::ostream &RsTlvIpAddress::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvIpAddress", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "Address:" << sockaddr_storage_tostring(addr) << std::endl; - - printEnd(out, "RsTlvIpAddress", indent); - return out; -} - - - - -/************************************* RsTlvIpAddressInfo ************************************/ - -RsTlvIpAddressInfo::RsTlvIpAddressInfo() - :RsTlvItem(), seenTime(0), source(0) -{ - addr.TlvClear(); - return; -} - -void RsTlvIpAddressInfo::TlvClear() -{ - addr.TlvClear(); - seenTime = 0; - source = 0; -} - -uint32_t RsTlvIpAddressInfo::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header + IpAddr + 8 for time & 4 for size */ - - s += addr.TlvSize(); - s += 8; // seenTime - s += 4; // source - - return s; - -} - -bool RsTlvIpAddressInfo::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_ADDRESS_INFO, tlvsize); - - ok &= addr.SetTlv(data, tlvend, offset); - ok &= setRawUInt64(data, tlvend, offset, seenTime); - ok &= setRawUInt32(data, tlvend, offset, source); - - return ok; - -} - - -bool RsTlvIpAddressInfo::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_ADDRESS_INFO) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - ok &= addr.GetTlv(data, tlvend, offset); - ok &= getRawUInt64(data, tlvend, offset, &(seenTime)); - ok &= getRawUInt32(data, tlvend, offset, &(source)); - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvIpAddressInfo::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - -std::ostream &RsTlvIpAddressInfo::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvIpAddressInfo", indent); - uint16_t int_Indent = indent + 2; - - addr.print(out, int_Indent); - - printIndent(out, int_Indent); - out << "SeenTime:" << seenTime; - out << std::endl; - - printIndent(out, int_Indent); - out << "Source:" << source; - out << std::endl; - - printEnd(out, "RsTlvIpAddressInfo", indent); - return out; -} - - - -#if 0 -/************************************* RsTlvIpAddrSet ************************************/ - -void RsTlvIpAddrSet::TlvClear() -{ - addrs.clear(); -} - -uint32_t RsTlvIpAddrSet::TlvSize() const -{ - - uint32_t s = TLV_HEADER_SIZE; /* header */ - - std::list::iterator it; - - - if(!addrs.empty()) - { - - for(it = addrs.begin(); it != addrs.end() ; ++it) - s += it->TlvSize(); - - } - - return s; -} - -bool RsTlvIpAddrSet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_ADDRESS_SET , tlvsize); - - if(!addrs.empty()) - { - std::list::iterator it; - - for(it = addrs.begin(); it != addrs.end() ; ++it) - ok &= it->SetTlv(data, size, offset); - } - - -return ok; - -} - - -bool RsTlvIpAddrSet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_ADDRESS_SET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - switch(tlvsubtype) - { - case TLV_TYPE_ADDRESS_INFO: - { - RsTlvIpAddressInfo addr; - ok &= addr.GetTlv(data, size, offset); - if (ok) - { - addrs.push_back(addr); - } - } - break; - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - - } - - if (!ok) - break; - } - - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvIpAddrSet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -// prints out contents of RsTlvIpAddrSet -std::ostream &RsTlvIpAddrSet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvIpAddrSet", indent); - uint16_t int_Indent = indent + 2; - - std::list::iterator it; - for(it = addrs.begin(); it != addrs.end() ; ++it) - it->print(out, int_Indent); - - printEnd(out, "RsTlvIpAddrSet", indent); - return out; -} - - -/************************************* RsTlvIpAddressInfo ************************************/ - -#endif diff --git a/libretroshare/src/serialiser/rstlvaddrs.h b/libretroshare/src/serialiser/rstlvaddrs.h deleted file mode 100644 index 07b668559..000000000 --- a/libretroshare/src/serialiser/rstlvaddrs.h +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvaddr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include "util/rsnet.h" -#include - -#include "serialiser/rstlvlist.h" - -class RsTlvIpAddress: public RsTlvItem -{ - public: - RsTlvIpAddress(); -virtual ~RsTlvIpAddress() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - struct sockaddr_storage addr; // Mandatory : -}; - - -class RsTlvIpAddressInfo: public RsTlvItem -{ - public: - RsTlvIpAddressInfo(); -virtual ~RsTlvIpAddressInfo() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - RsTlvIpAddress addr; // Mandatory : - uint64_t seenTime; // Mandatory : - uint32_t source; // Mandatory : -}; - -typedef t_RsTlvList RsTlvIpAddrSet; - -#if 0 -class RsTlvIpAddrSet: public RsTlvItem -{ - public: - RsTlvIpAddrSet() { return; } -virtual ~RsTlvIpAddrSet() { return; } -virtual uint32_t TlvSize(); -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ -virtual std::ostream &print(std::ostream &out, uint16_t indent); - - std::list addrs; // Mandatory : -}; -#endif - - diff --git a/libretroshare/src/serialiser/rstlvbanlist.cc b/libretroshare/src/serialiser/rstlvbanlist.cc deleted file mode 100644 index 92bd3a6d2..000000000 --- a/libretroshare/src/serialiser/rstlvbanlist.cc +++ /dev/null @@ -1,172 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvbanlist.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rstlvbanlist.h" -#include "serialiser/rstlvbase.h" - -#include "serialiser/rsbaseserial.h" - - -/************************************* RsTlvBanListEntry ************************************/ - -RsTlvBanListEntry::RsTlvBanListEntry() - :RsTlvItem(), level(0), reason(0), age(0) -{ - return; -} - -void RsTlvBanListEntry::TlvClear() -{ - addr.TlvClear(); - level = 0; - reason = 0; - age = 0; - comment.clear(); - masked_bytes = 0; -} - -uint32_t RsTlvBanListEntry::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; - - s += addr.TlvSize(); - s += 4; // level; - s += 4; // reason; - s += 4; // age; - s += 1; // masked_bytes; - s += GetTlvStringSize(comment) ; - - return s; - -} - -bool RsTlvBanListEntry::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_BAN_ENTRY, tlvsize); - - ok &= addr.SetTlv(data, tlvend, offset); - ok &= setRawUInt32(data, tlvend, offset, level); - ok &= setRawUInt32(data, tlvend, offset, reason); - ok &= setRawUInt32(data, tlvend, offset, age); - ok &= setRawUInt8(data, tlvend, offset, masked_bytes); - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_COMMENT, comment); - - return ok; - -} - - -bool RsTlvBanListEntry::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_BAN_ENTRY) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - ok &= addr.GetTlv(data, tlvend, offset); - ok &= getRawUInt32(data, tlvend, offset, &(level)); - ok &= getRawUInt32(data, tlvend, offset, &(reason)); - ok &= getRawUInt32(data, tlvend, offset, &(age)); - - uint8_t tmp ; - ok &= getRawUInt8(data, tlvend, offset, &(tmp)); - masked_bytes = tmp ; - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_COMMENT, comment); - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvBanListEntry::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - -std::ostream &RsTlvBanListEntry::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvBanListEntry", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "addr:" << std::endl; - addr.print(out, int_Indent); - - printIndent(out, int_Indent); - out << "level:" << level; - out << std::endl; - - printIndent(out, int_Indent); - out << "reason:" << reason; - out << std::endl; - - printIndent(out, int_Indent); - out << "age:" << age; - out << std::endl; - - printIndent(out, int_Indent); - out << "masked bytes:" << masked_bytes; - out << std::endl; - - printEnd(out, "RsTlvBanListEntry", indent); - return out; -} - - - diff --git a/libretroshare/src/serialiser/rstlvbanlist.h b/libretroshare/src/serialiser/rstlvbanlist.h deleted file mode 100644 index a08f92a7a..000000000 --- a/libretroshare/src/serialiser/rstlvbanlist.h +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvbanlist.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvaddrs.h" -#include "serialiser/rstlvlist.h" -#include "serialiser/rstlvbase.h" - -#define RSDSDV_MAX_ROUTE_TABLE 1000 - -class RsTlvBanListEntry: public RsTlvItem -{ - public: - RsTlvBanListEntry(); -virtual ~RsTlvBanListEntry() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - RsTlvIpAddress addr; - uint32_t level; - uint32_t reason; - uint32_t age; - uint8_t masked_bytes ; - std::string comment ; -}; - -typedef t_RsTlvList RsTlvBanList; - - - diff --git a/libretroshare/src/serialiser/rstlvbase.cc b/libretroshare/src/serialiser/rstlvbase.cc deleted file mode 100644 index 9cf713193..000000000 --- a/libretroshare/src/serialiser/rstlvbase.cc +++ /dev/null @@ -1,1007 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvbase.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie, Horatio, Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#include - -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" - -//********************* - -// A facility func -inline void* right_shift_void_pointer(const void* p, uint32_t len) { - - return (void*)( (uint8_t*)p + len); -} -//********************* - -//#define TLV_BASE_DEBUG 1 - -/**** Basic TLV Functions ****/ -uint32_t GetTlvSize(void *data) { - if (!data) - return 0; - - uint32_t len; - - void * from =right_shift_void_pointer(data, TLV_HEADER_TYPE_SIZE); - - memcpy((void *)&len, from , TLV_HEADER_LEN_SIZE); - - len = ntohl(len); - - return len; -} - -uint16_t GetTlvType(void *data) { - if (!data) - return 0; - - uint16_t type; - - memcpy((void*)&type, data, TLV_HEADER_TYPE_SIZE); - - type = ntohs(type); - - return type; - -} - -//tested -bool SetTlvBase(void *data, uint32_t size, uint32_t *offset, uint16_t type, - uint32_t len) { - if (!data) - return false; - if (!offset) - return false; - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t type_n = htons(type); - - //copy type_n to (data+*offset) - void* to = right_shift_void_pointer(data, *offset); - memcpy(to , (void*)&type_n, TLV_HEADER_TYPE_SIZE); - - uint32_t len_n =htonl(len); - //copy len_n to (data + *offset +2) - to = right_shift_void_pointer(to, TLV_HEADER_TYPE_SIZE); - memcpy((void *)to, (void*)&len_n, TLV_HEADER_LEN_SIZE); - - *offset += TLV_HEADER_SIZE; - - return true; -} - -bool SetTlvType(void *data, uint32_t size, uint16_t type) -{ - if (!data) - return false; - - if(size < TLV_HEADER_SIZE ) - return false; - - uint16_t type_n = htons(type); - memcpy(data , (void*)&type_n, TLV_HEADER_TYPE_SIZE); - return true; -} - -//tested -bool SetTlvSize(void *data, uint32_t size, uint32_t len) { - if (!data) - return false; - - if(size < TLV_HEADER_SIZE ) - return false; - - uint32_t len_n = htonl(len); - - void * to = (void*)((uint8_t *) data + TLV_HEADER_TYPE_SIZE); - - memcpy(to, (void*) &len_n, TLV_HEADER_LEN_SIZE); - - return true; - -} - -/* Step past unknown TLV TYPE */ -bool SkipUnknownTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (!data) - return false; - - if (size < *offset + TLV_HEADER_SIZE) - return false; - - /* extract the type and size */ - void *tlvstart = right_shift_void_pointer(data, *offset); - //uint16_t tlvtype = GetTlvType(tlvstart); - uint32_t tlvsize = GetTlvSize(tlvstart); - - /* check that there is size */ - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SkipUnknownTlv() FAILED - not enough space." << std::endl; - std::cerr << "SkipUnknownTlv() size: " << size << std::endl; - std::cerr << "SkipUnknownTlv() tlvsize: " << tlvsize << std::endl; - std::cerr << "SkipUnknownTlv() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - /* step past this tlv item */ - *offset = tlvend; - return ok; -} - - -/**** Generic TLV Functions **** - * This have the same data (int or string for example), - * but they can have different types eg. a string could represent a name or a path, - * so we include a type parameter in the arguments - */ -//tested -bool SetTlvUInt32(void *data, uint32_t size, uint32_t *offset, uint16_t type, - uint32_t out) -{ - if (!data) - return false; - uint32_t tlvsize = GetTlvUInt32Size(); /* this will always be 8 bytes */ - uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SetTlvUInt32() FAILED - not enough space. (or earlier)" << std::endl; - std::cerr << "SetTlvUInt32() size: " << size << std::endl; - std::cerr << "SetTlvUInt32() tlvsize: " << tlvsize << std::endl; - std::cerr << "SetTlvUInt32() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - - /* Now use the function we got to set the TlvHeader */ - /* function shifts offset to the new start for the next data */ - ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); - -#ifdef TLV_BASE_DEBUG - if (!ok) - { - std::cerr << "SetTlvUInt32() SetTlvBase FAILED (or earlier)" << std::endl; - } -#endif - - /* now set the UInt32 ( in rsbaseserial.h???) */ - ok &= setRawUInt32(data, tlvend, offset, out); - -#ifdef TLV_BASE_DEBUG - if (!ok) - { - std::cerr << "SetTlvUInt32() setRawUInt32 FAILED (or earlier)" << std::endl; - } -#endif - - - return ok; - -} - -//tested -bool GetTlvUInt32(void *data, uint32_t size, uint32_t *offset, - uint16_t type, uint32_t *in) -{ - if (!data) - return false; - - if (size < *offset + TLV_HEADER_SIZE) - return false; - - /* extract the type and size */ - void *tlvstart = right_shift_void_pointer(data, *offset); - uint16_t tlvtype = GetTlvType(tlvstart); - uint32_t tlvsize = GetTlvSize(tlvstart); - - /* check that there is size */ - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvUInt32() FAILED - not enough space." << std::endl; - std::cerr << "GetTlvUInt32() size: " << size << std::endl; - std::cerr << "GetTlvUInt32() tlvsize: " << tlvsize << std::endl; - std::cerr << "GetTlvUInt32() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - if (type != tlvtype) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvUInt32() FAILED - Type mismatch" << std::endl; - std::cerr << "GetTlvUInt32() type: " << type << std::endl; - std::cerr << "GetTlvUInt32() tlvtype: " << tlvtype << std::endl; -#endif - return false; - } - - *offset += TLV_HEADER_SIZE; /* step past header */ - - bool ok = true; - ok &= getRawUInt32(data, tlvend, offset, in); - - return ok; -} - -// UInt16 -bool SetTlvUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t type, - uint16_t out) -{ - if (!data) - return false; - uint32_t tlvsize = GetTlvUInt16Size(); /* this will always be 8 bytes */ - uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SetTlvUInt16() FAILED - not enough space. (or earlier)" << std::endl; - std::cerr << "SetTlvUInt16() size: " << size << std::endl; - std::cerr << "SetTlvUInt16() tlvsize: " << tlvsize << std::endl; - std::cerr << "SetTlvUInt16() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - - /* Now use the function we got to set the TlvHeader */ - /* function shifts offset to the new start for the next data */ - ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); - -#ifdef TLV_BASE_DEBUG - if (!ok) - { - std::cerr << "SetTlvUInt16() SetTlvBase FAILED (or earlier)" << std::endl; - } -#endif - - /* now set the UInt16 ( in rsbaseserial.h???) */ - ok &= setRawUInt16(data, tlvend, offset, out); - -#ifdef TLV_BASE_DEBUG - if (!ok) - { - std::cerr << "SetTlvUInt16() setRawUInt16 FAILED (or earlier)" << std::endl; - } -#endif - - - return ok; - -} - -bool GetTlvUInt16(void *data, uint32_t size, uint32_t *offset, - uint16_t type, uint16_t *in) -{ - if (!data) - return false; - - if (size < *offset + TLV_HEADER_SIZE) - return false; - - /* extract the type and size */ - void *tlvstart = right_shift_void_pointer(data, *offset); - uint16_t tlvtype = GetTlvType(tlvstart); - uint32_t tlvsize = GetTlvSize(tlvstart); - - /* check that there is size */ - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvUInt16() FAILED - not enough space." << std::endl; - std::cerr << "GetTlvUInt16() size: " << size << std::endl; - std::cerr << "GetTlvUInt16() tlvsize: " << tlvsize << std::endl; - std::cerr << "GetTlvUInt16() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - if (type != tlvtype) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvUInt16() FAILED - Type mismatch" << std::endl; - std::cerr << "GetTlvUInt16() type: " << type << std::endl; - std::cerr << "GetTlvUInt16() tlvtype: " << tlvtype << std::endl; -#endif - return false; - } - - *offset += TLV_HEADER_SIZE; /* step past header */ - - bool ok = true; - ok &= getRawUInt16(data, tlvend, offset, in); - - return ok; -} - - -uint32_t GetTlvUInt64Size() { - return TLV_HEADER_SIZE + 8; -} - -uint32_t GetTlvUInt32Size() { - return TLV_HEADER_SIZE + 4; -} - -uint32_t GetTlvUInt16Size() { - return TLV_HEADER_SIZE + sizeof(uint16_t); - -} - -uint32_t GetTlvUInt8Size() { - return TLV_HEADER_SIZE + sizeof(uint8_t); - -} - - -bool SetTlvUInt64(void *data, uint32_t size, uint32_t *offset, uint16_t type, - uint64_t out) -{ - if (!data) - return false; - uint32_t tlvsize = GetTlvUInt64Size(); - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SetTlvUInt64() FAILED - not enough space. (or earlier)" << std::endl; - std::cerr << "SetTlvUInt64() size: " << size << std::endl; - std::cerr << "SetTlvUInt64() tlvsize: " << tlvsize << std::endl; - std::cerr << "SetTlvUInt64() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - - /* Now use the function we got to set the TlvHeader */ - /* function shifts offset to the new start for the next data */ - ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); - -#ifdef TLV_BASE_DEBUG - if (!ok) - { - std::cerr << "SetTlvUInt64() SetTlvBase FAILED (or earlier)" << std::endl; - } -#endif - - /* now set the UInt64 ( in rsbaseserial.h???) */ - ok &= setRawUInt64(data, tlvend, offset, out); - -#ifdef TLV_BASE_DEBUG - if (!ok) - { - std::cerr << "SetTlvUInt64() setRawUInt64 FAILED (or earlier)" << std::endl; - } -#endif - - return ok; - -} - -bool GetTlvUInt64(void *data, uint32_t size, uint32_t *offset, - uint16_t type, uint64_t *in) -{ - if (!data) - return false; - - if (size < *offset + TLV_HEADER_SIZE) - return false; - - /* extract the type and size */ - void *tlvstart = right_shift_void_pointer(data, *offset); - uint16_t tlvtype = GetTlvType(tlvstart); - uint32_t tlvsize = GetTlvSize(tlvstart); - - /* check that there is size */ - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvUInt64() FAILED - not enough space." << std::endl; - std::cerr << "GetTlvUInt64() size: " << size << std::endl; - std::cerr << "GetTlvUInt64() tlvsize: " << tlvsize << std::endl; - std::cerr << "GetTlvUInt64() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - if (type != tlvtype) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvUInt64() FAILED - Type mismatch" << std::endl; - std::cerr << "GetTlvUInt64() type: " << type << std::endl; - std::cerr << "GetTlvUInt64() tlvtype: " << tlvtype << std::endl; -#endif - return false; - } - - *offset += TLV_HEADER_SIZE; /* step past header */ - - bool ok = true; - ok &= getRawUInt64(data, tlvend, offset, in); - - return ok; -} - - -bool SetTlvString(void *data, uint32_t size, uint32_t *offset, - uint16_t type, std::string out) -{ - if (!data) - return false; - uint32_t tlvsize = GetTlvStringSize(out); - uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ - - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SetTlvString() FAILED - not enough space" << std::endl; - std::cerr << "SetTlvString() size: " << size << std::endl; - std::cerr << "SetTlvString() tlvsize: " << tlvsize << std::endl; - std::cerr << "SetTlvString() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); - - void * to = right_shift_void_pointer(data, *offset); - - uint32_t strlen = tlvsize - TLV_HEADER_SIZE; - memcpy(to, out.c_str(), strlen); - - *offset += strlen; - - return ok; -} - -static bool readHex(char s1,char s2,uint8_t& v) -{ - v=0 ; - - if(s1 >= 'a' && s1 <= 'f') - v += (s1-'a')+10; - else if(s1 >= 'A' && s1 <= 'F') - v += (s1-'A')+10; - else if(s1 >= '0' && s1 <= '9') - v += s1 - '0' ; - else - return false ; - - v = v << 4; - - if(s2 >= 'a' && s2 <= 'f') - v += (s2-'a')+10; - else if(s2 >= 'A' && s2 <= 'F') - v += (s2-'A')+10; - else if(s2 >= '0' && s2 <= '9') - v += s2 - '0' ; - else - return false ; - - return true ; -} - -static bool find_decoded_string(const std::string& in,const std::string& suspicious_string) -{ - uint32_t ss_pointer = 0 ; - - for(uint32_t i=0;i 0x7f. - // We do this for strings that should not contain some - // special characters by design. - - if( type == 0 // this is used for mGroupName and mMsgName - || type == TLV_TYPE_STR_PEERID - || type == TLV_TYPE_STR_NAME - || type == TLV_TYPE_STR_PATH - || type == TLV_TYPE_STR_TITLE - || type == TLV_TYPE_STR_SUBJECT - || type == TLV_TYPE_STR_LOCATION - || type == TLV_TYPE_STR_VERSION ) - { - bool modified = false ; - for(uint32_t i=0;i 0) - { - modified = true ; - in[i] = 0x20 ; - } - - if(modified) - std::cerr << "(WW) De-serialised string of type " << type << " contains forbidden characters. They have been replaced by spaces. New string: \"" << in << "\"" << std::endl; - } - - *offset += tlvsize; /* step along */ - return true; -} - -uint32_t GetTlvStringSize(const std::string &in) { - return TLV_HEADER_SIZE + in.size(); -} - - -#ifdef REMOVED_CODE -/* We must use a consistent wchar size for cross platform ness. - * As unix uses 4bytes, and windows 2bytes? we'll go with 4bytes for maximum flexibility - */ - -const uint32_t RS_WCHAR_SIZE = 4; - -bool SetTlvWideString(void *data, uint32_t size, uint32_t *offset, - uint16_t type, std::wstring out) -{ - if (!data) - return false; - uint32_t tlvsize = GetTlvWideStringSize(out); - uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ - - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SetTlvWideString() FAILED - not enough space" << std::endl; - std::cerr << "SetTlvWideString() size: " << size << std::endl; - std::cerr << "SetTlvWideString() tlvsize: " << tlvsize << std::endl; - std::cerr << "SetTlvWideString() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); - - uint32_t strlen = out.length(); - - /* Must convert manually to ensure its always the same! */ - for(uint32_t i = 0; i < strlen; i++) - { - uint32_t widechar = out[i]; - ok &= setRawUInt32(data, tlvend, offset, widechar); - } - return ok; -} - -//tested -bool GetTlvWideString(void *data, uint32_t size, uint32_t *offset, - uint16_t type, std::wstring &in) -{ - if (!data) - return false; - - if (size < *offset + TLV_HEADER_SIZE) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvWideString() FAILED - not enough space" << std::endl; - std::cerr << "GetTlvWideString() size: " << size << std::endl; - std::cerr << "GetTlvWideString() *offset: " << *offset << std::endl; -#endif - return false; - } - - /* extract the type and size */ - void *tlvstart = right_shift_void_pointer(data, *offset); - uint16_t tlvtype = GetTlvType(tlvstart); - uint32_t tlvsize = GetTlvSize(tlvstart); - - /* check that there is size */ - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvWideString() FAILED - not enough space" << std::endl; - std::cerr << "GetTlvWideString() size: " << size << std::endl; - std::cerr << "GetTlvWideString() tlvsize: " << tlvsize << std::endl; - std::cerr << "GetTlvWideString() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - if (type != tlvtype) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvWideString() FAILED - invalid type" << std::endl; - std::cerr << "GetTlvWideString() type: " << type << std::endl; - std::cerr << "GetTlvWideString() tlvtype: " << tlvtype << std::endl; -#endif - return false; - } - - - bool ok = true; - /* remove the header, calc string length */ - *offset += TLV_HEADER_SIZE; - uint32_t strlen = (tlvsize - TLV_HEADER_SIZE) / RS_WCHAR_SIZE; - - /* Must convert manually to ensure its always the same! */ - for(uint32_t i = 0; i < strlen; i++) - { - uint32_t widechar; - ok &= getRawUInt32(data, tlvend, offset, &widechar); - in += widechar; - } - - // Check for message content. We want to avoid possible lol bombs as soon as possible. - - static const int number_of_suspiscious_strings = 4 ; - static const std::wstring err_in = L"**** String removed (SVG bomb?) ****" ; - static std::wstring suspiscious_strings[number_of_suspiscious_strings] = { L"sin_family = AF_INET; /* set FAMILY */ - in->sin_addr.s_addr = ipaddr; - - uint16_t port; - ok &= getRawUInt16(data, tlvend, offset, &port); - in->sin_port = port; - - return ok; -} - -uint32_t GetTlvIpAddrPortV4Size() { - return TLV_HEADER_SIZE + 4 + 2; /* header + 4 (IP) + 2 (Port) */ -} - - -bool SetTlvIpAddrPortV6(void *data, uint32_t size, uint32_t *offset, - uint16_t type, struct sockaddr_in6 *out) { - if (!data) - return false; - - uint32_t tlvsize = GetTlvIpAddrPortV6Size(); - uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ - - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SetTlvIpAddrPortV6() FAILED - not enough space" << std::endl; - std::cerr << "SetTlvIpAddrPortV6() size: " << size << std::endl; - std::cerr << "SetTlvIpAddrPortV6() tlvsize: " << tlvsize << std::endl; - std::cerr << "SetTlvIpAddrPortV6() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); - - /* now add the data (keep in network order) */ - uint32_t *ip6addr = (uint32_t *) out->sin6_addr.s6_addr; - for(int i = 0; i < 4; i++) - { - ok &= setRawUInt32(data, tlvend, offset, ip6addr[i]); - } - ok &= setRawUInt16(data, tlvend, offset, out->sin6_port); - return ok; -} - -bool GetTlvIpAddrPortV6(void *data, uint32_t size, uint32_t *offset, - uint16_t type, struct sockaddr_in6 *in) { - if (!data) - return false; - - if (size < *offset + TLV_HEADER_SIZE) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetIpAddrPortV6() FAILED - not enough space" << std::endl; - std::cerr << "GetIpAddrPortV6() size: " << size << std::endl; - std::cerr << "GetIpAddrPortV6() *offset: " << *offset << std::endl; -#endif - return false; - } - - /* extract the type and size */ - void *tlvstart = right_shift_void_pointer(data, *offset); - uint16_t tlvtype = GetTlvType(tlvstart); - uint32_t tlvsize = GetTlvSize(tlvstart); - - /* check that there is size */ - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetIpAddrPortV6() FAILED - not enough space" << std::endl; - std::cerr << "GetIpAddrPortV6() size: " << size << std::endl; - std::cerr << "GetIpAddrPortV6() tlvsize: " << tlvsize << std::endl; - std::cerr << "GetIpAddrPortV6() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - if (type != tlvtype) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetIpAddrPortV6() FAILED - invalid type" << std::endl; - std::cerr << "GetIpAddrPortV6() type: " << type << std::endl; - std::cerr << "GetIpAddrPortV6() tlvtype: " << tlvtype << std::endl; -#endif - return false; - } - - *offset += TLV_HEADER_SIZE; /* skip header */ - - bool ok = true; - - /* now get the data (keep in network order) */ - uint32_t *ip6addr = (uint32_t *) in->sin6_addr.s6_addr; - for(int i = 0; i < 4; i++) - { - ok &= getRawUInt32(data, tlvend, offset, &(ip6addr[i])); - } - - in->sin6_family = AF_INET6; /* set FAMILY */ - ok &= getRawUInt16(data, tlvend, offset, &(in->sin6_port)); - - return ok; -} - -uint32_t GetTlvIpAddrPortV6Size() { - return TLV_HEADER_SIZE + 16 + 2; /* header + 16 (IP) + 2 (Port) */ -} - diff --git a/libretroshare/src/serialiser/rstlvbase.h b/libretroshare/src/serialiser/rstlvbase.h deleted file mode 100644 index e153f1797..000000000 --- a/libretroshare/src/serialiser/rstlvbase.h +++ /dev/null @@ -1,299 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvbase.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie, Horatio, Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the general TLV (un)packing routines. - * - * Data is Serialised into the following format - * - * ----------------------------------------- - * | TLV TYPE (2 bytes) | TLV LEN (4 bytes)| - * ----------------------------------------- - * | | - * | Data .... | - * | | - * ----------------------------------------- - * - * Originally TLV TYPE = 2 bytes, and TLV LEN = 2 bytes. - * However with HTML and WSTRINGS the 64K Limit becomes limiting. - * The TLV LEN = 4 bytes now! - * - * Size is the total size of the TLV Field (including the 4 byte header) - * - * Like the lowlevel packing routines. They are usually - * created in pairs - one to pack the data, the other to unpack. - * - * GetTlvXXX(void *data, uint32_t size, uint32_t *offset, XXX *out); - * SetTlvXXX(void *data, uint32_t size, uint32_t *offset, XXX *in); - * - * - * data - the base pointer to the serialised data. - * size - size of the memory pointed to by data. - * *offset - where we want to (un)pack the data. - * This is incremented by the datasize. - * - * *in / *out - the data to (un)pack. - * - ******************************************************************/ - -#include -#include -#include "util/rsnet.h" - - -/* 0b 0000 0000 0001 XXXX UInt8 */ -/* 0b 0000 0000 0010 XXXX UInt16 */ -/* 0b 0000 0000 0011 XXXX UInt32 */ -/* 0b 0000 0000 0100 XXXX UInt64 */ -/* 0b 0000 0000 0101 XXXX String */ -/* 0b 0000 0000 0110 XXXX Wide String */ -/* 0b 0000 0000 0111 XXXX Hashes */ -/* 0b 0000 0000 1000 XXXX IP:Port V4 */ - -/******* BINARY TYPES *****************/ -/* 0b 0000 0001 0000 XXXX CERT */ -/* 0b 0000 0001 0001 XXXX Priv Key */ -/* 0b 0000 0001 0010 XXXX Pub Key */ -/* 0b 0000 0001 0011 XXXX Signature */ - -/******* COMPOUND TYPES ***************/ -/* 0b 0001 XXXX XXXX XXXX Compound */ -/* 0b 0001 0000 0000 XXXX FILE */ -/* 0b 0001 0000 0001 XXXX KEY VALUE */ -/* 0b 0001 0000 0010 XXXX PEERS */ -/* 0b 0001 0000 0011 XXXX SERVICES */ - -/******* BIG LEN TYPES ***************/ - -/* 0b 1000 XXXX XXXX XXXX BIG LEN */ -/* 0b 1000 0000 0001 XXXX STRINGS */ -/* 0b 1000 0000 0010 XXXX WSTRINGS */ -/* 0b 1000 0000 0011 XXXX BINARY */ - -/* 0b 1001 XXXX XXXX XXXX Compound */ - - -/* TLV HEADER SIZE (Reference) *******************************/ -const uint32_t TLV_HEADER_TYPE_SIZE = 2; -const uint32_t TLV_HEADER_LEN_SIZE = 4; -const uint32_t TLV_HEADER_SIZE = TLV_HEADER_TYPE_SIZE + TLV_HEADER_LEN_SIZE; -/* TLV HEADER SIZE (Reference) *******************************/ - -const uint16_t TLV_TYPE_UINT32_SIZE = 0x0030; -const uint16_t TLV_TYPE_UINT32_POP = 0x0031; -const uint16_t TLV_TYPE_UINT32_AGE = 0x0032; -const uint16_t TLV_TYPE_UINT32_OFFSET = 0x0033; -const uint16_t TLV_TYPE_UINT32_SERID = 0x0034; -const uint16_t TLV_TYPE_UINT32_BW = 0x0035; -const uint16_t TLV_TYPE_UINT32_PARAM = 0x0030; - -const uint16_t TLV_TYPE_UINT64_SIZE = 0x0040; -const uint16_t TLV_TYPE_UINT64_OFFSET = 0x0041; - -const uint16_t TLV_TYPE_STR_PEERID = 0x0050; -const uint16_t TLV_TYPE_STR_NAME = 0x0051; -const uint16_t TLV_TYPE_STR_PATH = 0x0052; -const uint16_t TLV_TYPE_STR_KEY = 0x0053; -const uint16_t TLV_TYPE_STR_VALUE = 0x0054; -const uint16_t TLV_TYPE_STR_COMMENT = 0x0055; -const uint16_t TLV_TYPE_STR_TITLE = 0x0056; -const uint16_t TLV_TYPE_STR_MSG = 0x0057; -const uint16_t TLV_TYPE_STR_SUBJECT = 0x0058; -const uint16_t TLV_TYPE_STR_LINK = 0x0059; -const uint16_t TLV_TYPE_STR_GENID = 0x005a; -const uint16_t TLV_TYPE_STR_GPGID = 0x005b; /* depreciated */ -const uint16_t TLV_TYPE_STR_PGPID = 0x005b; /* same as GPG */ -const uint16_t TLV_TYPE_STR_LOCATION = 0x005c; -const uint16_t TLV_TYPE_STR_CERT_GPG = 0x005d; -const uint16_t TLV_TYPE_STR_PGPCERT = 0x005d; /* same as CERT_GPG */ -const uint16_t TLV_TYPE_STR_CERT_SSL = 0x005e; -const uint16_t TLV_TYPE_STR_VERSION = 0x005f; -const uint16_t TLV_TYPE_STR_PARAM = 0x0054; /* same as VALUE ---- TO FIX */ - -/* Hashs are always strings */ -const uint16_t TLV_TYPE_STR_HASH_SHA1 = 0x0070; -const uint16_t TLV_TYPE_STR_HASH_ED2K = 0x0071; - -const uint16_t TLV_TYPE_IPV4_LOCAL = 0x0080; -const uint16_t TLV_TYPE_IPV4_REMOTE = 0x0081; -const uint16_t TLV_TYPE_IPV4_LAST = 0x0082; -const uint16_t TLV_TYPE_STR_DYNDNS = 0x0083; -const uint16_t TLV_TYPE_STR_DOMADDR = 0x0084; - -// rearrange these in the future. -const uint16_t TLV_TYPE_IPV4 = 0x0085; -const uint16_t TLV_TYPE_IPV6 = 0x0086; - -/*** MORE STRING IDS ****/ -const uint16_t TLV_TYPE_STR_GROUPID = 0x00a0; -const uint16_t TLV_TYPE_STR_MSGID = 0x00a1; -const uint16_t TLV_TYPE_STR_PARENTID = 0x00a2; -const uint16_t TLV_TYPE_STR_THREADID = 0x00a3; -const uint16_t TLV_TYPE_STR_KEYID = 0x00a4; - -/* even MORE string Ids for GXS services */ - -const uint16_t TLV_TYPE_STR_CAPTION = 0x00b1; -const uint16_t TLV_TYPE_STR_CATEGORY = 0x00b2; -const uint16_t TLV_TYPE_STR_DESCR = 0x00b3; -const uint16_t TLV_TYPE_STR_SIGN = 0x00b4; -const uint16_t TLV_TYPE_STR_HASH_TAG = 0x00b5; -const uint16_t TLV_TYPE_STR_WIKI_PAGE = 0x00b6; -const uint16_t TLV_TYPE_STR_DATE = 0x00b7; -const uint16_t TLV_TYPE_STR_PIC_TYPE = 0x00b8; -const uint16_t TLV_TYPE_STR_PIC_AUTH = 0x00b9; -const uint16_t TLV_TYPE_STR_GXS_ID = 0x00ba; - - - /**** Binary Types ****/ -const uint16_t TLV_TYPE_CERT_XPGP_DER = 0x0100; -const uint16_t TLV_TYPE_CERT_X509 = 0x0101; -const uint16_t TLV_TYPE_CERT_OPENPGP = 0x0102; - -const uint16_t TLV_TYPE_KEY_EVP_PKEY = 0x0110; /* Used (Generic - Distrib) */ -const uint16_t TLV_TYPE_KEY_PRIV_RSA = 0x0111; /* not used yet */ -const uint16_t TLV_TYPE_KEY_PUB_RSA = 0x0112; /* not used yet */ - -const uint16_t TLV_TYPE_SIGN_RSA_SHA1 = 0x0120; /* Used (Distrib/Forums) */ - -const uint16_t TLV_TYPE_BIN_IMAGE = 0x0130; /* Used (Generic - Forums) */ -const uint16_t TLV_TYPE_BIN_FILEDATA = 0x0140; /* Used - ACTIVE! */ -const uint16_t TLV_TYPE_BIN_SERIALISE = 0x0150; /* Used (Generic - Distrib) */ -const uint16_t TLV_TYPE_BIN_GENERIC = 0x0160; /* Used (DSDV Data) */ -const uint16_t TLV_TYPE_BIN_ENCRYPTED = 0x0170; /* Encrypted data */ - - - /**** Compound Types ****/ -const uint16_t TLV_TYPE_FILEITEM = 0x1000; -const uint16_t TLV_TYPE_FILESET = 0x1001; -const uint16_t TLV_TYPE_FILEDATA = 0x1002; - -const uint16_t TLV_TYPE_KEYVALUE = 0x1010; -const uint16_t TLV_TYPE_KEYVALUESET = 0x1011; - -const uint16_t TLV_TYPE_STRINGSET = 0x1020; /* dummy non-existant */ -const uint16_t TLV_TYPE_PEERSET = 0x1021; -const uint16_t TLV_TYPE_HASHSET = 0x1022; - -const uint16_t TLV_TYPE_PGPIDSET = 0x1023; -const uint16_t TLV_TYPE_RECOGNSET = 0x1024; -const uint16_t TLV_TYPE_GXSIDSET = 0x1025; -const uint16_t TLV_TYPE_GXSCIRCLEIDSET= 0x1026; -const uint16_t TLV_TYPE_NODEGROUPIDSET= 0x1027; -const uint16_t TLV_TYPE_GXSMSGIDSET = 0x1028; - -const uint16_t TLV_TYPE_SERVICESET = 0x1030; - -// *_deprectate should not be used anymore!! -// We use 1040 for both public and private keys, so that transmitting them still works (backward compatibility), and so that -// signatures are kept. But the two different classes will check that the flags are correct when deserialising. - -const uint16_t TLV_TYPE_SECURITY_KEY = 0x1040; -const uint16_t TLV_TYPE_SECURITYKEYSET = 0x1041; - -const uint16_t TLV_TYPE_KEYSIGNATURE = 0x1050; -const uint16_t TLV_TYPE_KEYSIGNATURESET = 0x1051; -const uint16_t TLV_TYPE_KEYSIGNATURETYPE = 0x1052; - -const uint16_t TLV_TYPE_IMAGE = 0x1060; - -const uint16_t TLV_TYPE_ADDRESS_INFO = 0x1070; -const uint16_t TLV_TYPE_ADDRESS_SET = 0x1071; -const uint16_t TLV_TYPE_ADDRESS = 0x1072; - -const uint16_t TLV_TYPE_DSDV_ENDPOINT = 0x1080; -const uint16_t TLV_TYPE_DSDV_ENTRY = 0x1081; -const uint16_t TLV_TYPE_DSDV_ENTRY_SET= 0x1082; - -const uint16_t TLV_TYPE_BAN_ENTRY_dep = 0x1090; -const uint16_t TLV_TYPE_BAN_ENTRY = 0x1092; -const uint16_t TLV_TYPE_BAN_LIST = 0x1091; - -const uint16_t TLV_TYPE_MSG_ADDRESS = 0x10A0; -const uint16_t TLV_TYPE_MSG_ID = 0x10A1; - - -const uint32_t RSTLV_IMAGE_TYPE_PNG = 0x0001; -const uint32_t RSTLV_IMAGE_TYPE_JPG = 0x0002; - -/**** Basic TLV Functions ****/ -uint32_t GetTlvSize(void *data); -uint16_t GetTlvType(void *data); -bool SetTlvBase(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint32_t len); -bool SetTlvSize(void *data, uint32_t size, uint32_t len); -bool SetTlvType(void *data, uint32_t size, uint16_t type); - -/* skip past the unknown tlv elements */ -bool SkipUnknownTlv(void *data, uint32_t size, uint32_t *offset); - -/**** Generic TLV Functions **** - * This have the same data (int or string for example), - * but they can have different types eg. a string could represent a name or a path, - * so we include a type parameter in the arguments - */ - -bool SetTlvUInt8(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint8_t out); -bool GetTlvUInt8(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint8_t *in); - -bool SetTlvUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint16_t out); -bool GetTlvUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint16_t *in); - -bool SetTlvUInt32(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint32_t out); -bool GetTlvUInt32(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint32_t *in); - -bool SetTlvUInt64(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint64_t out); -bool GetTlvUInt64(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint64_t *in); - -uint32_t GetTlvUInt8Size(); -uint32_t GetTlvUInt16Size(); -uint32_t GetTlvUInt32Size(); -uint32_t GetTlvUInt64Size(); - - -bool SetTlvString(void *data, uint32_t size, uint32_t *offset, uint16_t type, std::string out); -bool GetTlvString(const void *data, uint32_t size, uint32_t *offset, uint16_t type, std::string &in); -uint32_t GetTlvStringSize(const std::string &in); - -#ifdef REMOVED_CODE -bool SetTlvWideString(void *data, uint32_t size, uint32_t *offset, uint16_t type, std::wstring out); -bool GetTlvWideString(void *data, uint32_t size, uint32_t *offset, uint16_t type, std::wstring &in); -uint32_t GetTlvWideStringSize(std::wstring &in); -#endif - -bool SetTlvIpAddrPortV4(void *data, uint32_t size, uint32_t *offset, uint16_t type, struct sockaddr_in *out); -bool GetTlvIpAddrPortV4(void *data, uint32_t size, uint32_t *offset, uint16_t type, struct sockaddr_in *in); -uint32_t GetTlvIpAddrPortV4Size(); - -bool SetTlvIpAddrPortV6(void *data, uint32_t size, uint32_t *offset, uint16_t type, struct sockaddr_in6 *out); -bool GetTlvIpAddrPortV6(void *data, uint32_t size, uint32_t *offset, uint16_t type, struct sockaddr_in6 *in); -uint32_t GetTlvIpAddrPortV6Size(); - -/* additional function to be added - -bool SetTlvBinData(void* data, uint32_t size, uint32_t* offset, uint16_t type, void* data_bin, uint32_t len_tlv) - -above(SetTlvbinData) is partially implemented - -bool GetTlvBinData(void* data, uint32_t size, uint32_t* offset, uint16_t type, void* data_bin, uint32_t len_tlv) - -*************************************/ diff --git a/libretroshare/src/serialiser/rstlvbinary.cc b/libretroshare/src/serialiser/rstlvbinary.cc deleted file mode 100644 index 7eabf74d9..000000000 --- a/libretroshare/src/serialiser/rstlvbinary.cc +++ /dev/null @@ -1,326 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvbinary.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#include "util/rsmemory.h" -#include "serialiser/rstlvbinary.h" - -#include "serialiser/rstlvbase.h" -#include -#include -#include - -// #define TLV_DEBUG 1 - -/*!********************************** RsTlvFileBinaryData **********************************/ - - -RsTlvBinaryData::RsTlvBinaryData() - :tlvtype(0), bin_len(0), bin_data(NULL) -{ -} - -RsTlvBinaryData::RsTlvBinaryData(uint16_t t) - :tlvtype(t), bin_len(0), bin_data(NULL) -{ -} - -RsTlvBinaryData::RsTlvBinaryData(const RsTlvBinaryData &b) - : tlvtype(b.tlvtype), bin_len(0) , bin_data(NULL) { - - setBinData(b.bin_data, b.bin_len); -} - -RsTlvBinaryData::~RsTlvBinaryData() -{ - TlvClear(); -} - -void RsTlvBinaryData::operator =(const RsTlvBinaryData& b){ - - setBinData(b.bin_data, b.bin_len); - tlvtype = b.tlvtype; -} - -/// used to allocate memory andinitialize binary data member -bool RsTlvBinaryData::setBinData(const void *data, uint32_t size) -{ - /* ready to load */ - TlvClear(); - - /* get mandatory */ - /* the rest of the TLV size binary data */ - bin_len = size; - if (bin_len == 0) - { - bin_data = NULL; - return true; - } - - bin_data = rs_malloc(bin_len); - - if(bin_data == NULL) - return false ; - - memcpy(bin_data, data, bin_len); - return true; -} - -void RsTlvBinaryData::TlvClear() -{ - free(bin_data); - TlvShallowClear(); -} - -void RsTlvBinaryData::TlvShallowClear() -{ - bin_data = NULL; - bin_len = 0; -} - -uint32_t RsTlvBinaryData::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - if (bin_data != NULL) - s += bin_len; // len is the size of data - - return s; -} - - -bool RsTlvBinaryData::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, tlvtype, tlvsize); - - /* add mandatory data */ - - // Warning: this is actually not an error if bin_len=0, as it does not - // corrupt the packet structure. We thus still return true in this case. - // - if (bin_data != NULL && bin_len > 0) - { - memcpy(&(((uint8_t *) data)[*offset]), bin_data, bin_len); - *offset += bin_len; - } - return ok; -} - - - -bool RsTlvBinaryData::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - { - return false; /* not enough space to get the header */ - } - - uint16_t tlvtype_in = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvsize < TLV_HEADER_SIZE) - { - return false; /* bad tlv size */ - } - - if (tlvtype != tlvtype_in) /* check type */ - return false; - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - bool ok = setBinData(&(((uint8_t *) data)[*offset]), tlvsize - TLV_HEADER_SIZE); - (*offset) += bin_len; - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvBinaryData::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} -std::ostream &RsTlvBinaryDataRef::print(std::ostream &out, uint16_t indent) const -{ - uint16_t int_Indent = indent + 2; - - uint32_t i; - std::ostringstream sout; - printIndent(sout, indent); - sout << "RsTlvBinaryData: Type: " << tlvtype << " Size: " << mSizeRef; - sout << std::hex; - - for(i = 0; i < mSizeRef; i++) - { - if (i % 16 == 0) - { - sout << std::endl; - printIndent(sout, int_Indent); - } - sout << std::setw(2) << std::setfill('0') - << (int) (((unsigned char *) mDataRef)[i]) << ":"; - } - - sout << std::endl; - out << sout.str(); - - printEnd(out, "RsTlvBinaryData", indent); - return out; - -} - -std::ostream &RsTlvBinaryData::print(std::ostream &out, uint16_t indent) const -{ - uint16_t int_Indent = indent + 2; - - uint32_t i; - std::ostringstream sout; - printIndent(sout, indent); - sout << "RsTlvBinaryData: Type: " << tlvtype << " Size: " << bin_len; - sout << std::hex; - - for(i = 0; i < bin_len; i++) - { - if (i % 16 == 0) - { - sout << std::endl; - printIndent(sout, int_Indent); - } - sout << std::setw(2) << std::setfill('0') - << (int) (((unsigned char *) bin_data)[i]) << ":"; - } - - sout << std::endl; - out << sout.str(); - - printEnd(out, "RsTlvBinaryData", indent); - return out; - -} - -bool RsTlvBinaryDataRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, tlvtype, tlvsize); - - /* add mandatory data */ - - // Warning: this is actually not an error if bin_len=0, as it does not - // corrupt the packet structure. We thus still return true in this case. - // - if (mDataRef != NULL && mSizeRef > 0) - { - memcpy(&(((uint8_t *) data)[*offset]), mDataRef, mSizeRef); - *offset += mSizeRef; - } - return ok; -} -bool RsTlvBinaryDataRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - { - return false; /* not enough space to get the header */ - } - - uint16_t tlvtype_in = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvsize < TLV_HEADER_SIZE) - return false; /* bad tlv size */ - - if (tlvtype != tlvtype_in) /* check type */ - return false; - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - mDataRef = (uint8_t*)rs_malloc(tlvsize - TLV_HEADER_SIZE) ; - - if(mDataRef == NULL) - return false ; - - mSizeRef = tlvsize - TLV_HEADER_SIZE; - - memcpy(mDataRef,&(((uint8_t *) data)[*offset]), tlvsize - TLV_HEADER_SIZE); - *offset += mSizeRef; - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvBinaryData::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return true; -} - -uint32_t RsTlvBinaryDataRef::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - if (mDataRef != NULL) - s += mSizeRef; // len is the size of data - - return s; -} diff --git a/libretroshare/src/serialiser/rstlvbinary.h b/libretroshare/src/serialiser/rstlvbinary.h deleted file mode 100644 index 3d41d5402..000000000 --- a/libretroshare/src/serialiser/rstlvbinary.h +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvbinary.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "serialiser/rstlvitem.h" - - -class RsTlvBinaryData: public RsTlvItem -{ -public: - RsTlvBinaryData(); - RsTlvBinaryData(uint16_t t); - RsTlvBinaryData(const RsTlvBinaryData& b); // as per rule of three - void operator=(const RsTlvBinaryData& b); // as per rule of three - - virtual ~RsTlvBinaryData(); // as per rule of three - - virtual uint32_t TlvSize() const; - virtual void TlvClear(); /*! Initialize fields to empty legal values ( "0", "", etc) */ - virtual void TlvShallowClear(); /*! Don't delete the binary data */ - - /// Serialise. - /*! Serialise Tlv to buffer(*data) of 'size' bytes starting at *offset */ - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - - /// Deserialise. - /*! Deserialise Tlv buffer(*data) of 'size' bytes starting at *offset */ - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - virtual std::ostream &print(std::ostream &out, uint16_t indent) const; /*! Error/Debug util function */ - - // mallocs the necessary size, and copies data into the allocated buffer in bin_data - bool setBinData(const void *data, uint32_t size); - - uint16_t tlvtype; /// set/checked against TLV input - uint32_t bin_len; /// size of malloc'ed data (not serialised) - void *bin_data; /// mandatory -}; - -// This class is mainly used for on-the-fly serialization - -class RsTlvBinaryDataRef: public RsTlvItem -{ -public: - RsTlvBinaryDataRef(uint16_t type,uint8_t *& data_ref,uint32_t& size_ref) : mDataRef(data_ref),mSizeRef(size_ref),tlvtype(type) {} - virtual ~RsTlvBinaryDataRef() {} - - virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - virtual uint32_t TlvSize() const; - virtual void TlvClear(){} - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - - uint8_t *& mDataRef ; - uint32_t & mSizeRef ; - uint16_t tlvtype ; -}; - - - diff --git a/libretroshare/src/serialiser/rstlvfileitem.cc b/libretroshare/src/serialiser/rstlvfileitem.cc deleted file mode 100644 index 098b8de6f..000000000 --- a/libretroshare/src/serialiser/rstlvfileitem.cc +++ /dev/null @@ -1,703 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvfileitem.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rsbaseserial.h" - -#if 0 -#include - -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvtypes.h" -#endif - -/*** - * #define TLV_FI_DEBUG 1 - **/ - - -RsTlvFileItem::RsTlvFileItem() -{ - TlvClear(); -} - -void RsTlvFileItem::TlvClear() -{ - filesize = 0; - hash.clear() ; - name.clear(); - path.clear(); - pop = 0; - age = 0; - piecesize = 0; - hashset.TlvClear(); -} - -uint32_t RsTlvFileItem::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - s += 8; /* filesize */ - s += hash.serial_size() ; -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() 8 + Hash: " << s << std::endl; -#endif - - - /* now optional ones */ - if (name.length() > 0) - { - s += GetTlvStringSize(name); -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() + Name: " << s << std::endl; -#endif - } - - if (path.length() > 0) - { - s += GetTlvStringSize(path); -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() + Path: " << s << std::endl; -#endif - } - - if (pop != 0) - { - s += GetTlvUInt32Size(); -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() + Pop: " << s << std::endl; -#endif - } - - if (age != 0) - { - s += GetTlvUInt32Size(); -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() 4 + Age: " << s << std::endl; -#endif - } - - if (piecesize != 0) - { - s += GetTlvUInt32Size(); -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() 4 + PieceSize: " << s << std::endl; -#endif - } - - if (hashset.ids.size() != 0) - { - s += hashset.TlvSize(); -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() 4 + HashSet: " << s << std::endl; -#endif - } - -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() Total: " << s << std::endl; -#endif - - return s; -} - -/* serialise the data to the buffer */ -bool RsTlvFileItem::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::SetTlv() Failed size (" << size; - std::cerr << ") < tlvend (" << tlvend << ")" << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_FILEITEM, tlvsize); - -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() SetTlvBase Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() PostBase:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - - /* add mandatory parts first */ - ok &= setRawUInt64(data, tlvend, offset, filesize); - -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() SetRawUInt32(FILESIZE) Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() PostSize:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - ok &= hash.serialise(data, tlvend, *offset) ; - - -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() SetTlvString(HASH) Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() PostHash:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - /* now optional ones */ - if (name.length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_NAME, name); -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Option:Name Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() PostName:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - if (path.length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_PATH, path); -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Option:Path Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() Pre Pop:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << " type: " << TLV_TYPE_UINT32_POP << " value: " << pop; - std::cerr << std::endl; -#endif - - if (pop != 0) - ok &= SetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_POP, pop); -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Option:Pop Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() Post Pop/Pre Age:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << " type: " << TLV_TYPE_UINT32_AGE << " value: " << age; - std::cerr << std::endl; -#endif - - if (age != 0) - ok &= SetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_AGE, age); -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Option:Age Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() Post Age:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - if (piecesize != 0) - ok &= SetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_SIZE, piecesize); -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Option:piecesize Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() Post PieceSize:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - if (hashset.ids.size() != 0) - ok &= hashset.SetTlv(data, tlvend, offset); -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Option:hashset Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() Post HashSet:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - - -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Options Failed (or earlier)" << std::endl; - } -#endif - - return ok; -} - -bool RsTlvFileItem::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_FILEITEM) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* get mandatory parts first */ - ok &= getRawUInt64(data, tlvend, offset, &filesize); - ok &= hash.deserialise(data, tlvend, *offset) ; - - /* while there is more TLV (optional part) */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - switch(tlvsubtype) - { - case TLV_TYPE_STR_NAME: - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_NAME, name); - break; - case TLV_TYPE_STR_PATH: - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_PATH, path); - break; - case TLV_TYPE_UINT32_POP: - ok &= GetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_POP, &pop); - break; - case TLV_TYPE_UINT32_AGE: - ok &= GetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_AGE, &age); - break; - case TLV_TYPE_UINT32_SIZE: - ok &= GetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_SIZE, &piecesize); - break; - case TLV_TYPE_HASHSET: - ok &= hashset.GetTlv(data, tlvend, offset); - break; - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - } - if (!ok) - { - break; - } - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvFileItem::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - - -/* print it out */ -std::ostream &RsTlvFileItem::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvFileItem", indent); - uint16_t int_Indent = indent + 2; - - - printIndent(out, int_Indent); - out << "Mandatory: FileSize: " << filesize << " Hash: " << hash; - out << std::endl; - - printIndent(out, int_Indent); - out << "Optional:" << std::endl; - - /* now optional ones */ - if (name.length() > 0) - { - printIndent(out, int_Indent); - out << "Name : " << name << std::endl; - } - if (path.length() > 0) - { - printIndent(out, int_Indent); - out << "Path : " << path << std::endl; - } - if (pop != 0) - { - printIndent(out, int_Indent); - out << "Pop: " << pop << std::endl; - } - if (age != 0) - { - printIndent(out, int_Indent); - out << "Age: " << age << std::endl; - } - if (piecesize != 0) - { - printIndent(out, int_Indent); - out << "PieceSize: " << piecesize << std::endl; - } - if (hashset.ids.size() != 0) - { - hashset.print(out, int_Indent); - } - - printEnd(out, "RsTlvFileItem", indent); - - return out; -} - - -/************************************* RsTlvFileSet ************************************/ - -void RsTlvFileSet::TlvClear() -{ - title.clear(); - comment.clear(); - items.clear(); -} - -uint32_t RsTlvFileSet::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* first determine the total size of RstlvFileItems in list */ - - std::list::const_iterator it; - - for(it = items.begin(); it != items.end() ; ++it) - { - s += (*it).TlvSize(); - } - - /* now add comment and title length of this tlv object */ - - if (title.length() > 0) - s += GetTlvStringSize(title); - if (comment.length() > 0) - s += GetTlvStringSize(comment); - - return s; -} - - -/* serialize data to the buffer */ - -bool RsTlvFileSet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_FILESET, tlvsize); - - /* add mandatory parts first */ - std::list::const_iterator it; - - for(it = items.begin(); it != items.end() ; ++it) - { - ok &= (*it).SetTlv(data, size, offset); - /* drop out if fails */ - if (!ok) - return false; - } - - /* now optional ones */ - if (title.length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_TITLE, title); - if (comment.length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_COMMENT, comment); - - return ok; - -} - - -bool RsTlvFileSet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_FILESET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is more TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - if (tlvsubtype == TLV_TYPE_FILEITEM) - { - RsTlvFileItem newitem; - ok &= newitem.GetTlv(data, size, offset); - if (ok) - { - items.push_back(newitem); - } - } - else if (tlvsubtype == TLV_TYPE_STR_TITLE) - { - ok &= GetTlvString(data, tlvend, offset, - TLV_TYPE_STR_TITLE, title); - } - else if (tlvsubtype == TLV_TYPE_STR_COMMENT) - { - ok &= GetTlvString(data, tlvend, offset, - TLV_TYPE_STR_COMMENT, comment); - } - else - { - /* unknown subtype -> error */ - ok &= SkipUnknownTlv(data, tlvend, offset); - } - - if (!ok) - { - break; - } - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvFileSet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -/* print it out */ - -std::ostream &RsTlvFileSet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvFileSet", indent); - uint16_t int_Indent = indent + 2; - - - printIndent(out, int_Indent); - out << "Mandatory:" << std::endl; - std::list::const_iterator it; - - for(it = items.begin(); it != items.end() ; ++it) - { - it->print(out, int_Indent); - } - printIndent(out, int_Indent); - out << "Optional:" << std::endl; - - /* now optional ones */ - if (title.length() > 0) - { - printIndent(out, int_Indent); - std::string cnv_title(title.begin(), title.end()); - out << "Title: " << cnv_title << std::endl; - } - if (comment.length() > 0) - { - printIndent(out, int_Indent); - std::string cnv_comment(comment.begin(), comment.end()); - out << "Comment: " << cnv_comment << std::endl; - } - - printEnd(out, "RsTlvFileSet", indent); - - return out; -} - - -/************************************* RsTlvFileData ************************************/ - -RsTlvFileData::RsTlvFileData() - :RsTlvItem(), file_offset(0), binData(TLV_TYPE_BIN_FILEDATA) -{ - return; -} - -void RsTlvFileData::TlvClear() -{ - file.TlvClear(); - binData.TlvClear(); - file_offset = 0; -} - - -uint32_t RsTlvFileData::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* collect sizes for both uInts and data length */ - s+= file.TlvSize(); - s+= GetTlvUInt64Size(); - s+= binData.TlvSize(); - - return s; -} - - -bool RsTlvFileData::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_FILEDATA , tlvsize); - - /* add mandatory part */ - ok &= file.SetTlv(data, size, offset); - ok &= SetTlvUInt64(data,size,offset, - TLV_TYPE_UINT64_OFFSET,file_offset); - ok &= binData.SetTlv(data, size, offset); - - return ok; - - -} - -bool RsTlvFileData::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - { - return false; - } - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_FILEDATA) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - ok &= file.GetTlv(data, size, offset); - ok &= GetTlvUInt64(data,size,offset, - TLV_TYPE_UINT64_OFFSET,&file_offset); - ok &= binData.GetTlv(data, size, offset); - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvFileData::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - -/* print it out */ -std::ostream &RsTlvFileData::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvFileData", indent); - uint16_t int_Indent = indent + 2; - - file.print(out, int_Indent); - - printIndent(out, int_Indent); - out << "FileOffset: " << file_offset; - out << std::endl; - - binData.print(out, int_Indent); - - printEnd(out, "RsTlvFileData", indent); - return out; - -} - diff --git a/libretroshare/src/serialiser/rstlvfileitem.h b/libretroshare/src/serialiser/rstlvfileitem.h deleted file mode 100644 index 174753364..000000000 --- a/libretroshare/src/serialiser/rstlvfileitem.h +++ /dev/null @@ -1,89 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvfileitem.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvbinary.h" - -class RsTlvFileItem: public RsTlvItem -{ - public: - RsTlvFileItem(); -virtual ~RsTlvFileItem() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint64_t filesize; /// Mandatory: size of file to be downloaded - RsFileHash hash; /// Mandatory: to find file - std::string name; /// Optional: name of file - std::string path; /// Optional: path on host computer - uint32_t pop; /// Optional: Popularity of file - uint32_t age; /// Optional: age of file - // For chunk hashing. - uint32_t piecesize; /// Optional: bytes/piece for hashset. - RsTlvHashSet hashset; /// Optional: chunk hashes. - -}; - -class RsTlvFileSet: public RsTlvItem -{ - public: - RsTlvFileSet() { return; } -virtual ~RsTlvFileSet() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - std::list items; /// Mandatory - std::string title; /// Optional: title of file set - std::string comment; /// Optional: comments for file -}; - - -class RsTlvFileData: public RsTlvItem -{ - public: - RsTlvFileData(); - virtual ~RsTlvFileData() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - RsTlvFileItem file; /// Mandatory: file information - uint64_t file_offset; /// Mandatory: where to start in bin data - RsTlvBinaryData binData; /// Mandatory: serialised file info -}; - - diff --git a/libretroshare/src/serialiser/rstlvgenericmap.h b/libretroshare/src/serialiser/rstlvgenericmap.h deleted file mode 100644 index 0cc4a3a88..000000000 --- a/libretroshare/src/serialiser/rstlvgenericmap.h +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvgenericmap.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_TLV_GENERIC_MAP_H -#define RS_TLV_GENERIC_MAP_H - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvgenericparam.h" - -#if 0 -#include - -#include -#include - -#endif - -/*********************************** RsTlvGenericPairRef ***********************************/ - -template -class RsTlvGenericPairRef: public RsTlvItem -{ - public: - RsTlvGenericPairRef(uint16_t pair_type, - uint16_t key_type, uint16_t value_type, K &k, V &v) - :mPairType(pair_type), mKeyType(key_type), - mValueType(value_type), mKey(k), mValue(v) { return; } - -virtual ~RsTlvGenericPairRef() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint16_t mPairType; - uint16_t mKeyType; - uint16_t mValueType; - K &mKey; - V &mValue; -}; - - -/************************************ RsTlvGenericMapRef ***********************************/ - -template -class RsTlvGenericMapRef: public RsTlvItem -{ - public: - RsTlvGenericMapRef(uint16_t map_type, uint16_t pair_type, - uint16_t key_type, uint16_t value_type, std::map &refmap) - :mMapType(map_type), mPairType(pair_type), - mKeyType(key_type), mValueType(value_type), mRefMap(refmap) { return; } - -virtual ~RsTlvGenericMapRef() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint16_t mMapType; - uint16_t mPairType; - uint16_t mKeyType; - uint16_t mValueType; - std::map &mRefMap; -}; - - -#include "rstlvgenericmap.inl" - -#endif - diff --git a/libretroshare/src/serialiser/rstlvgenericmap.inl b/libretroshare/src/serialiser/rstlvgenericmap.inl deleted file mode 100644 index b5239d2f7..000000000 --- a/libretroshare/src/serialiser/rstlvgenericmap.inl +++ /dev/null @@ -1,306 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvgenericmap.inl * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "serialiser/rstlvbase.h" - -// Must be different - as this is inline in headers. -//#define TLV_GENERICMAP_DEBUG 1 - -/*********************************** RsTlvGenericPairRef ***********************************/ - -template -void RsTlvGenericPairRef::TlvClear() -{ - RsTlvParamRef key(mKeyType, mKey); - RsTlvParamRef value(mValueType, mValue); - key.TlvClear(); - value.TlvClear(); -} - -template -uint32_t RsTlvGenericPairRef::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - RsTlvParamRef key(mKeyType, mKey); - RsTlvParamRef value(mValueType, mValue); - - s += key.TlvSize(); - s += value.TlvSize(); - return s; - -} - -template -bool RsTlvGenericPairRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, mPairType, tlvsize); - - RsTlvParamRef key(mKeyType, mKey); - RsTlvParamRef value(mValueType, mValue); - ok &= key.SetTlv(data, tlvend, offset); - ok &= value.SetTlv(data, tlvend, offset); - - if (!ok) - { - std::cerr << "RsTlvGenericPairRef<>::SetTlv() Failed"; - std::cerr << std::endl; - } -#ifdef TLV_GENERICMAP_DEBUG - else - { - std::cerr << "RsTlvGenericPairRef<>::SetTlv() Ok"; - std::cerr << std::endl; - } -#endif - return ok; -} - -template -bool RsTlvGenericPairRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != mPairType) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - RsTlvParamRef key(mKeyType, mKey); - RsTlvParamRef value(mValueType, mValue); - ok &= key.GetTlv(data, tlvend, offset); - ok &= value.GetTlv(data, tlvend, offset); - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_GENERICMAP_DEBUG - std::cerr << "RsTlvGenericPairRef::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - return ok; - -} - -template -std::ostream &RsTlvGenericPairRef::print(std::ostream &out, uint16_t indent) const -{ - //printBase(out, "RsTlvGenericPairRef", indent); - uint16_t int_Indent = indent + 2; - - RsTlvParamRef key(mKeyType, mKey); - RsTlvParamRef value(mValueType, mValue); - - printIndent(out, int_Indent); - out << "Key:"; - key.print(out, 0); - out << std::endl; - - printIndent(out, int_Indent); - out << "Value:"; - value.print(out, 0); - out << std::endl; - - //printEnd(out, "RsTlvGenericPairRef", indent); - return out; -} - -// declare likely combinations. -//template<> class RsTlvGenericPairRef; -//template<> class RsTlvGenericPairRef; -//template<> class RsTlvGenericPairRef; -//template<> class RsTlvGenericPairRef; - -/************************************ RsTlvGenericMapRef ***********************************/ - -template -void RsTlvGenericMapRef::TlvClear() -{ - mRefMap.clear(); //empty list -} - -template -uint32_t RsTlvGenericMapRef::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - typename std::map::iterator it; - for(it = mRefMap.begin(); it != mRefMap.end(); ++it) - { - RsTlvGenericPairRef pair(mPairType, mKeyType, mValueType, it->first, it->second); - s += pair.TlvSize(); - } - - return s; -} - -template -bool RsTlvGenericMapRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, mMapType, tlvsize); - - - typename std::map::iterator it; - for(it = mRefMap.begin(); it != mRefMap.end(); ++it) - { - RsTlvGenericPairRef pair(mPairType, mKeyType, mValueType, it->first, it->second); - ok &= pair.SetTlv(data, size, offset); - } - - if (!ok) - { - std::cerr << "RsTlvGenericMapRef<>::SetTlv() Failed"; - std::cerr << std::endl; - } - - return ok; -} - -template -bool RsTlvGenericMapRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != mMapType) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - if (tlvsubtype == mPairType) - { - K k; - V v; - RsTlvGenericPairRef pair(mPairType, mKeyType, mValueType, k, v); - ok &= pair.GetTlv(data, size, offset); - if (ok) - { - mRefMap[k] = v; - } - } - else - { - ok &= SkipUnknownTlv(data, tlvend, offset); - ok = false; - } - - if (!ok) - break; - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_GENERICMAP_DEBUG - std::cerr << "RsTlvGenericMapRef::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -template -std::ostream &RsTlvGenericMapRef::print(std::ostream &out, uint16_t indent) const -{ - //printBase(out, "RsTlvGenericMapRef", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "MapType:" << mMapType << std::endl; - - typename std::map::iterator it; - for(it = mRefMap.begin(); it != mRefMap.end() ; ++it) - { - RsTlvGenericPairRef pair(mPairType, mKeyType, mValueType, it->first, it->second); - pair.print(out, int_Indent); - } - - //printEnd(out, "RsTlvGenericMapRef", indent); - return out; -} - diff --git a/libretroshare/src/serialiser/rstlvgenericparam.cc b/libretroshare/src/serialiser/rstlvgenericparam.cc deleted file mode 100644 index ef3610813..000000000 --- a/libretroshare/src/serialiser/rstlvgenericparam.cc +++ /dev/null @@ -1,222 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvgenericparam.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rstlvgenericparam.h" -#include "serialiser/rstlvbase.h" -#include - -// #define TLV_DEBUG 1 - -/* generic print */ -template -std::ostream & RsTlvParamRef::print(std::ostream &out, uint16_t indent) const -{ - printIndent(out, indent); - out << "Type: " << mParamType << " Param: " << mParam; - return out; -} - - -/***** uint16_t ****/ -template<> -uint32_t RsTlvParamRef::TlvSize() const -{ - return GetTlvUInt16Size(); -} - -template<> -void RsTlvParamRef::TlvClear() -{ - mParam = 0; -} - -template<> -bool RsTlvParamRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - return SetTlvUInt16(data, size, offset, mParamType, mParam); -} - -template<> -bool RsTlvParamRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - uint16_t param; - bool retval = GetTlvUInt16(data, size, offset, mParamType, ¶m); - mParam = param; - return retval; -} - -template<> -std::ostream & RsTlvParamRef::print(std::ostream &out, uint16_t indent) const -{ - printIndent(out, indent); - out << "Type: " << mParamType << "Param: " << mParam; - return out; -} - - -/***** const uint16_t ****/ - -template<> -uint32_t RsTlvParamRef::TlvSize() const -{ - return GetTlvUInt16Size(); -} - -template<> -void RsTlvParamRef::TlvClear() -{ - //mParam = 0; -} - - -template<> -bool RsTlvParamRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - return SetTlvUInt16(data, size, offset, mParamType, mParam); -} - -template<> -bool RsTlvParamRef::GetTlv(void */*data*/, uint32_t /*size*/, uint32_t */*offset*/) -{ - return false; //GetTlvUInt16(data, size, offset, mParamType, &mParam); -} - - -template<> -std::ostream & RsTlvParamRef::print(std::ostream &out, uint16_t indent) const -{ - printIndent(out, indent); - out << "Type: " << mParamType << "Param: " << mParam; - return out; -} - -/***** uint32_t ****/ -template<> -uint32_t RsTlvParamRef::TlvSize() const -{ - return GetTlvUInt32Size(); -} - -template<> -void RsTlvParamRef::TlvClear() -{ - mParam = 0; -} - -template<> -bool RsTlvParamRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - return SetTlvUInt32(data, size, offset, mParamType, mParam); -} - -template<> -bool RsTlvParamRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - return GetTlvUInt32(data, size, offset, mParamType, &mParam); -} - -template<> -std::ostream & RsTlvParamRef::print(std::ostream &out, uint16_t indent) const -{ - printIndent(out, indent); - out << "Type: " << mParamType << "Param: " << mParam; - return out; -} - - - -/***** const uint32_t ****/ -template<> -uint32_t RsTlvParamRef::TlvSize() const -{ - return GetTlvUInt32Size(); -} - -template<> -void RsTlvParamRef::TlvClear() -{ - //mParam = 0; -} - -template<> -bool RsTlvParamRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - return SetTlvUInt32(data, size, offset, mParamType, mParam); -} - -template<> -bool RsTlvParamRef::GetTlv(void */*data*/, uint32_t /*size*/, uint32_t */*offset*/) -{ - return false; - //GetTlvUInt32(data, size, offset, mParamType, &mParam); -} - -template<> -std::ostream & RsTlvParamRef::print(std::ostream &out, uint16_t indent) const -{ - printIndent(out, indent); - out << "Type: " << mParamType << "Param: " << mParam; - return out; -} - - -/***** std::string ****/ -template<> -uint32_t RsTlvParamRef::TlvSize() const -{ - return GetTlvStringSize(mParam); -} - -template<> -void RsTlvParamRef::TlvClear() -{ - mParam.clear(); -} - -template<> -bool RsTlvParamRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - return SetTlvString(data, size, offset, mParamType, mParam); -} - -template<> -bool RsTlvParamRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - return GetTlvString(data, size, offset, mParamType, mParam); -} - -template<> -std::ostream & RsTlvParamRef::print(std::ostream &out, uint16_t indent) const -{ - printIndent(out, indent); - out << "Type: " << mParamType << "Param: " << mParam; - return out; -} - -// declare likely combinations. -//template class RsTlvParamRef; -//template class RsTlvParamRef; -//template class RsTlvParamRef; - -//template class RsTlvParamRef; -//template class RsTlvParamRef; -//template class RsTlvParamRef; - diff --git a/libretroshare/src/serialiser/rstlvgenericparam.h b/libretroshare/src/serialiser/rstlvgenericparam.h deleted file mode 100644 index b1b6417a7..000000000 --- a/libretroshare/src/serialiser/rstlvgenericparam.h +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvgenericparam.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_TLV_GENERIC_PARAM_H -#define RS_TLV_GENERIC_PARAM_H - -#include "serialiser/rstlvitem.h" - -#if 0 -#include - -#include -#include -#endif - - -/**** TLV ***** - * Generic Parameters / Maps. - */ - - -template -class RsTlvParamRef: public RsTlvItem -{ - public: - RsTlvParamRef(uint16_t param_type, T &p): mParamType(param_type), mParam(p) {} -virtual ~RsTlvParamRef() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint16_t mParamType; - T &mParam; -}; - - -#endif - diff --git a/libretroshare/src/serialiser/rstlvidset.cc b/libretroshare/src/serialiser/rstlvidset.cc deleted file mode 100644 index ef60aca36..000000000 --- a/libretroshare/src/serialiser/rstlvidset.cc +++ /dev/null @@ -1,166 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvidset.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#include "rstlvidset.h" - -// #define TLV_DEBUG 1 - -/************************************* Service Id Set ************************************/ - -void RsTlvServiceIdSet::TlvClear() -{ - ids.clear(); - -} - -uint32_t RsTlvServiceIdSet::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* determine the total size of ids strings in list */ - std::list::const_iterator it; - for(it = ids.begin(); it != ids.end() ; ++it) - { - if (*it > 0) - s += GetTlvUInt32Size(); - } - - return s; -} - -bool RsTlvServiceIdSet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_SERVICESET , tlvsize); - - /* determine the total size of ids strings in list */ - std::list::const_iterator it; - for(it = ids.begin(); it != ids.end() ; ++it) - { - if (*it > 0) - ok &= SetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_SERID, *it); - } - - return ok; - -} - -bool RsTlvServiceIdSet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_SERVICESET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - -/* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - if (tlvsubtype == TLV_TYPE_UINT32_SERID) - { - uint32_t newIds; - ok &= GetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_SERID, &newIds); - if(ok) - { - ids.push_back(newIds); - - } - } - else - { - /* Step past unknown TLV TYPE */ - ok &= SkipUnknownTlv(data, tlvend, offset); - } - - if (!ok) - { - break; - } - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvServiceIdSet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - - return ok; -} - -/// print to screen RsTlvServiceSet contents -std::ostream &RsTlvServiceIdSet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvServiceIdSet", indent); - uint16_t int_Indent = indent + 2; - - std::list::const_iterator it; - for(it = ids.begin(); it != ids.end() ; ++it) - { - printIndent(out, int_Indent); - out << "id:" << *it; - out << std::endl; - } - - printEnd(out, "RsTlvServiceIdSet", indent); - return out; - -} - - - diff --git a/libretroshare/src/serialiser/rstlvidset.h b/libretroshare/src/serialiser/rstlvidset.h deleted file mode 100644 index 2e8a3f882..000000000 --- a/libretroshare/src/serialiser/rstlvidset.h +++ /dev/null @@ -1,145 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvidset.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvitem.h" -#include "util/rsdeprecate.h" -#include -#include - -#include - -/// @deprecated use plain std::set<> instead -template class RS_DEPRECATED_FOR(std::set<>) t_RsTlvIdSet - : public RsTlvItem -{ - public: - t_RsTlvIdSet() {} - virtual ~t_RsTlvIdSet() {} - - virtual uint32_t TlvSize() const { return ID_CLASS::SIZE_IN_BYTES * ids.size() + TLV_HEADER_SIZE; } - virtual void TlvClear(){ ids.clear() ; } - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const - { /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok = ok && SetTlvBase(data, tlvend, offset, TLV_TYPE, tlvsize); - - for(typename std::set::const_iterator it(ids.begin());it!=ids.end();++it) - ok = ok && (*it).serialise(data,tlvend,*offset) ; - - return ok ; - } - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset) - { - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - while(*offset + ID_CLASS::SIZE_IN_BYTES <= tlvend) - { - ID_CLASS id ; - ok = ok && id.deserialise(data,tlvend,*offset) ; - ids.insert(id) ; - } - if(*offset != tlvend) - { - std::cerr << "(EE) deserialisaiton error in " << __PRETTY_FUNCTION__ << std::endl; - ok = false; - } - - if(!ok) - std::cerr << "(WW) something wrong in ID_CLASS.deserialise in " << __PRETTY_FUNCTION__ << std::endl; - - return ok; - } - virtual std::ostream &print(std::ostream &out, uint16_t /* indent */) const - { - for(typename std::set::const_iterator it(ids.begin());it!=ids.end();++it) - out << (*it).toStdString() << ", " ; - - return out ; - } - virtual std::ostream &printHex(std::ostream &out, uint16_t /* indent */) const /* SPECIAL One */ - { - for(typename std::set::const_iterator it(ids.begin());it!=ids.end();++it) - out << (*it).toStdString() << ", " ; - - return out ; - } - - std::set ids ; -}; - -typedef t_RsTlvIdSet RsTlvPeerIdSet ; -typedef t_RsTlvIdSet RsTlvPgpIdSet ; -typedef t_RsTlvIdSet RsTlvHashSet ; -typedef t_RsTlvIdSet RsTlvGxsIdSet ; -typedef t_RsTlvIdSet RsTlvGxsMsgIdSet ; -typedef t_RsTlvIdSet RsTlvGxsCircleIdSet ; -typedef t_RsTlvIdSet RsTlvNodeGroupIdSet ; - -class RS_DEPRECATED RsTlvServiceIdSet: public RsTlvItem -{ - public: - RsTlvServiceIdSet() { return; } -virtual ~RsTlvServiceIdSet() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - std::list ids; /* Mandatory */ -}; - - diff --git a/libretroshare/src/serialiser/rstlvimage.cc b/libretroshare/src/serialiser/rstlvimage.cc deleted file mode 100644 index ce8ea5d6c..000000000 --- a/libretroshare/src/serialiser/rstlvimage.cc +++ /dev/null @@ -1,198 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvimage.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rstlvimage.h" - -#if 0 -#include - -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" -#endif - -/*** - * #define TLV_IMG_DEBUG 1 - **/ - -/************************************* RsTlvImage ************************************/ - -RsTlvImage::RsTlvImage() - :RsTlvItem(), image_type(0), binData(TLV_TYPE_BIN_IMAGE) -{ - return; -} - -void RsTlvImage::TlvClear() -{ - image_type = 0; - binData.TlvClear(); -} - - -uint32_t RsTlvImage::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* collect sizes for both uInts and data length */ - s+= 4; - s+= binData.TlvSize(); - - return s; -} - - -bool RsTlvImage::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::SetTlv()" << std::endl; -#endif - - - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::SetTlv() no space" << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_IMAGE , tlvsize); -#ifdef TLV_IMG_DEBUG - if (!ok) - std::cerr << "RsTlvImage::SetTlv() NOK base" << std::endl; -#endif - - /* add mandatory part */ - ok &= setRawUInt32(data, tlvend, offset, image_type); -#ifdef TLV_IMG_DEBUG - if (!ok) - std::cerr << "RsTlvImage::SetTlv() NOK image" << std::endl; -#endif - - ok &= binData.SetTlv(data, size, offset); -#ifdef TLV_IMG_DEBUG - if (!ok) - std::cerr << "RsTlvImage::SetTlv() NOK binData" << std::endl; -#endif - - - return ok; - - -} - -bool RsTlvImage::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::GetTlv()" << std::endl; -#endif - if (size < *offset + TLV_HEADER_SIZE) - { - return false; - } - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - { -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::GetTlv() FAIL no space" << std::endl; -#endif - return false; /* not enough space */ - } - - if (tlvtype != TLV_TYPE_IMAGE) /* check type */ - { -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::GetTlv() FAIL wrong type" << std::endl; -#endif - return false; - } - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* add mandatory parts first */ - ok &= getRawUInt32(data, tlvend, offset, &(image_type)); - ok &= binData.GetTlv(data, size, offset); - -#ifdef TLV_IMG_DEBUG - if (!ok) - std::cerr << "RsTlvImage::GetTlv() NOK" << std::endl; -#endif - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvImage::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - -/* print it out */ -std::ostream &RsTlvImage::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvImage", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "Image_Type: " << image_type; - out << std::endl; - - binData.print(out, int_Indent); - - printEnd(out, "RsTlvImage", indent); - return out; - -} - -RsTlvImage::RsTlvImage(const RsTlvImage& rightOp) -:RsTlvItem(), image_type(0), binData(TLV_TYPE_BIN_IMAGE) -{ - this->image_type = rightOp.image_type; - this->binData.setBinData(rightOp.binData.bin_data, rightOp.binData.bin_len); -} diff --git a/libretroshare/src/serialiser/rstlvimage.h b/libretroshare/src/serialiser/rstlvimage.h deleted file mode 100644 index 562c29090..000000000 --- a/libretroshare/src/serialiser/rstlvimage.h +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvimage.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" - -class RsTlvImage: public RsTlvItem -{ -public: - RsTlvImage(); - RsTlvImage(const RsTlvImage& ); - virtual ~RsTlvImage() { return; } - virtual uint32_t TlvSize() const; - virtual void TlvClear(); - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - - bool empty() const { return binData.bin_len == 0 ; } - virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint32_t image_type; // Mandatory: - RsTlvBinaryData binData; // Mandatory: serialised file info -}; - - diff --git a/libretroshare/src/serialiser/rstlvitem.cc b/libretroshare/src/serialiser/rstlvitem.cc deleted file mode 100644 index 62b40e761..000000000 --- a/libretroshare/src/serialiser/rstlvitem.cc +++ /dev/null @@ -1,192 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvitem.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#include "rstlvitem.h" -#include "rstlvbase.h" -#include - -#if 0 -#include "rsbaseserial.h" -#include "util/rsprint.h" -#include -#include -#include -#endif - -// #define TLV_DEBUG 1 - -void RsTlvItem::TlvShallowClear() -{ - TlvClear(); /* unless overloaded! */ -} - -std::ostream &RsTlvItem::printBase(std::ostream &out, std::string clsName, uint16_t indent) const -{ - printIndent(out, indent); - out << "RsTlvItem: " << clsName << " Size: " << TlvSize() << " ***********************"; - out << std::endl; - return out; -} - -std::ostream &RsTlvItem::printEnd(std::ostream &out, std::string clsName, uint16_t indent) const -{ - printIndent(out, indent); - out << "********************** " << clsName << " *********************"; - out << std::endl; - return out; -} - -std::ostream &printIndent(std::ostream &out, uint16_t indent) -{ - for(int i = 0; i < indent; i++) - { - out << " "; - } - return out; -} - - - -RsTlvUnit::RsTlvUnit(const uint16_t tlv_type) - :RsTlvItem(), mTlvType(tlv_type) -{ - return; -} - -uint32_t RsTlvUnit::TlvSize() const -{ - return TLV_HEADER_SIZE + TlvSizeUnit(); -} - -/* serialise */ -bool RsTlvUnit::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ -#ifdef TLV_DEBUG - std::cerr << "RsTlvUnit::SetTlv()" << std::endl; -#endif - - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvImage::SetTlv() ERROR not enough space" << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_IMAGE , tlvsize); - - if (!ok) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvUnit::SetTlv() ERROR Setting base" << std::endl; -#endif - return false; - } - - ok &= SetTlvUnit(data, tlvend, offset); - -#ifdef TLV_DEBUG - if (!ok) - std::cerr << "RsTlvUnit::SetTlv() ERROR in SetTlvUnit" << std::endl; -#endif - return ok; -} - -/* deserialise */ -bool RsTlvUnit::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvUnit::GetTlv() ERROR not enough size for header"; - std::cerr << std::endl; -#endif - return false; - } - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - { -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::GetTlv() ERROR no space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - if (tlvtype != mTlvType) /* check type */ - { -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::GetTlv() ERROR wrong type"; - std::cerr << std::endl; -#endif - return false; - } - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* extract components */ - ok &= GetTlvUnit(data, tlvend, offset); - -#ifdef TLV_IMG_DEBUG - if (!ok) - { - std::cerr << "RsTlvUnit::GetTlv() ERROR GetTlvUnit() NOK"; - std::cerr << std::endl; - } -#endif - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvUnit::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - diff --git a/libretroshare/src/serialiser/rstlvitem.h b/libretroshare/src/serialiser/rstlvitem.h deleted file mode 100644 index 4d45cd120..000000000 --- a/libretroshare/src/serialiser/rstlvitem.h +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvitem.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "util/rsdeprecate.h" - -#include -#include -#include - -/*! A base class for all tlv items - * This class is provided to allow the serialisation and deserialization of - * compund tlv items - * @deprecated TLV serialization system is deprecated! - */ -class RS_DEPRECATED_FOR(RsSerializable) RsTlvItem -{ - public: - RsTlvItem() { return; } -virtual ~RsTlvItem() { return; } -virtual uint32_t TlvSize() const = 0; -virtual void TlvClear() = 0; -virtual void TlvShallowClear(); /*! Don't delete allocated data */ -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const = 0; /* serialise */ -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset) = 0; /* deserialise */ -virtual std::ostream &print(std::ostream &out, uint16_t indent) const = 0; -std::ostream &printBase(std::ostream &out, std::string clsName, uint16_t indent) const; -std::ostream &printEnd(std::ostream &out, std::string clsName, uint16_t indent) const; -}; - -std::ostream &printIndent(std::ostream &out, uint16_t indent); - -class RS_DEPRECATED_FOR(RsSerializable) RsTlvUnit: public RsTlvItem -{ - public: - RsTlvUnit(uint16_t tlv_type); -virtual ~RsTlvUnit() { return; } -virtual uint32_t TlvSize() const; -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - -virtual uint16_t TlvType() const { return mTlvType; } - -// These Functions need to be implemented. -//virtual void TlvClear() = 0; -//virtual std::ostream &print(std::ostream &out, uint16_t indent) = 0 const; - -virtual uint32_t TlvSizeUnit() const = 0; -virtual bool SetTlvUnit(void *data, uint32_t size, uint32_t *offset) const = 0; -virtual bool GetTlvUnit(void *data, uint32_t size, uint32_t *offset) = 0; - - - private: - uint16_t mTlvType; -}; - - diff --git a/libretroshare/src/serialiser/rstlvkeys.cc b/libretroshare/src/serialiser/rstlvkeys.cc deleted file mode 100644 index e2be0b666..000000000 --- a/libretroshare/src/serialiser/rstlvkeys.cc +++ /dev/null @@ -1,830 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvkeys.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "rstlvkeys.h" -#include "rstlvbase.h" -#include "rsbaseserial.h" -#include "util/stacktrace.h" -#include "gxs/gxssecurity.h" - -#include - -// #define TLV_DEBUG 1 - -// This should be removed eventually, but will break backward compatibility -#define KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - -/************************************* RsTlvSecurityKey ************************************/ - -RsTlvRSAKey::RsTlvRSAKey() - :RsTlvItem(), keyFlags(0), startTS(0), endTS(0), keyData(TLV_TYPE_KEY_EVP_PKEY) -{ - return; -} - -void RsTlvRSAKey::TlvClear() -{ - keyId.clear(); - keyFlags = 0; - startTS = 0; - endTS = 0; - keyData.TlvClear(); -} - -/* clears keyData - but doesn't delete */ -void RsTlvRSAKey::ShallowClear() -{ - keyId.clear(); - keyFlags = 0; - startTS = 0; - endTS = 0; - keyData.bin_data = 0; - keyData.bin_len = 0; -} - -uint32_t RsTlvRSAKey::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header + 4 for size */ - - /* now add comment and title length of this tlv object */ - -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - s += GetTlvStringSize(keyId.toStdString()) ; -#else - s += keyId.serial_size(); -#endif - s += 4; - s += 4; - s += 4; - s += keyData.TlvSize(); - - return s; -} - -bool RsTlvRSAKey::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { - std::cerr << "RsTlvSecurityKey::SetTlv() Failed not enough space"; - std::cerr << std::endl; - return false; /* not enough space */ - } - - bool ok = checkKey(); // check before serialise, just in case - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_SECURITY_KEY, tlvsize); -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId.toStdString()); -#else - ok &= keyId.serialise(data, tlvend, *offset) ; -#endif - ok &= setRawUInt32(data, tlvend, offset, keyFlags); - ok &= setRawUInt32(data, tlvend, offset, startTS); - ok &= setRawUInt32(data, tlvend, offset, endTS); - ok &= keyData.SetTlv(data, tlvend, offset); - - return ok; - -} - -bool RsTlvRSAKey::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKey::GetTlv() Fail, not enough space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - if (tlvtype != TLV_TYPE_SECURITY_KEY) /* check type */ - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKey::GetTlv() Fail, wrong type"; - std::cerr << std::endl; -#endif - return false; - } - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - std::string s ; - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, s); - keyId = RsGxsId(s) ; -#else - ok &= keyId.deserialise(data, tlvend, *offset) ; -#endif - ok &= getRawUInt32(data, tlvend, offset, &(keyFlags)); - ok &= getRawUInt32(data, tlvend, offset, &(startTS)); - ok &= getRawUInt32(data, tlvend, offset, &(endTS)); - ok &= keyData.GetTlv(data, tlvend, offset); - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKey::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - if (!ok) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKey::GetTlv() Failed somewhere ok == false"; - std::cerr << std::endl; -#endif - } - return ok && checkKey() ; -} - -/** - * @brief RsTlvRSAKey::getKeyTypeTlv: Deserialize data in temp value to get type of key. - * @param data: Serialized data - * @param size: Size of the data - * @param constoffset: Offset where find first data. Not updated by this function. - * @return The keyFlag filtered by RSTLV_KEY_TYPE_MASK. 0 if failed - */ -uint32_t RsTlvRSAKey::getKeyTypeTlv(void *data, uint32_t size, uint32_t *constoffset) const -{ - //Temporay Value. The same name than class to get same code than RsTlvRSAKey::GetTlv - uint32_t offValue = *constoffset; - uint32_t *offset = &offValue; - RsGxsId keyId; // Mandatory : - uint32_t keyFlags; // Mandatory ; - //The Code below have to be same as RsTlvRSAKey::GetTlv excepted last lines until flag is desserialized. - //Just comment TlvClear(); and unused values - - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKey::GetTlv() Fail, not enough space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - if (tlvtype != TLV_TYPE_SECURITY_KEY) /* check type */ - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKey::GetTlv() Fail, wrong type"; - std::cerr << std::endl; -#endif - return false; - } - - bool ok = true; - - /* ready to load */ - //TlvClear();//RsTlvRSAKey::getKeyTypeTlv - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - std::string s ; - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, s); - keyId = RsGxsId(s) ; -#else - ok &= keyId.deserialise(data, tlvend, *offset) ; -#endif - ok &= getRawUInt32(data, tlvend, offset, &(keyFlags)); - //Stop here no need more data - //RsTlvRSAKey::getKeyTypeTlv specific lines - uint32_t ret = keyFlags & RSTLV_KEY_TYPE_MASK; - if (!ok) - { - ret = 0; -#ifdef TLV_DEBUG - std::cerr << "RsTlvRSAKey::getKeyTypeTlv() Failed somewhere ok == false" << std::endl; -#endif - } - return ret ; -} - -std::ostream& RsTlvRSAKey::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvSecurityKey", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "KeyId:" << keyId; - out << std::endl; - - printIndent(out, int_Indent); - out << "KeyFlags:" << keyFlags; - out << std::endl; - - printIndent(out, int_Indent); - out << "StartTS:" << startTS; - out << std::endl; - - printIndent(out, int_Indent); - out << "EndTS:" << endTS; - out << std::endl; - - keyData.print(out, int_Indent); - - out << std::endl; - - printEnd(out, "RsTlvSecurityKey", indent); - return out; -} - - -bool RsTlvPrivateRSAKey::checkKey() const -{ - bool keyFlags_TYPE_FULL = (keyFlags & RSTLV_KEY_TYPE_FULL); - if (!keyFlags_TYPE_FULL) {std::cout << "RsTlvPrivateRSAKey::checkKey() keyFlags not Type Full " << std::hex << keyFlags << " & " << RSTLV_KEY_TYPE_FULL << std::dec << std::endl;} - bool keyFlags_not_PUBLIC_ONLY = !(keyFlags & RSTLV_KEY_TYPE_PUBLIC_ONLY); - if (!keyFlags_not_PUBLIC_ONLY) {std::cout << "RsTlvPrivateRSAKey::checkKey() keyFlags is Public Only " << std::hex << keyFlags << " & " << RSTLV_KEY_TYPE_PUBLIC_ONLY << std::dec << std::endl;} - bool security_OK = false; - if (keyFlags_TYPE_FULL && keyFlags_not_PUBLIC_ONLY) - { - //Don't trigg error if flags already wrong - security_OK = GxsSecurity::checkPrivateKey(*this); - if (!security_OK) {std::cout << "RsTlvPublicRSAKey::checkKey() key is not secure."<< std::endl;} - } - - return keyFlags_TYPE_FULL && keyFlags_not_PUBLIC_ONLY && security_OK ; -} - -bool RsTlvPublicRSAKey::checkKey() const -{ - bool keyFlags_PUBLIC_ONLY = (keyFlags & RSTLV_KEY_TYPE_PUBLIC_ONLY); - if (!keyFlags_PUBLIC_ONLY) {std::cout << "RsTlvPublicRSAKey::checkKey() keyFlags not Public Only " << std::hex << keyFlags << " & " << RSTLV_KEY_TYPE_PUBLIC_ONLY << std::dec << std::endl;} - bool keyFlags_not_TYPE_FULL = !(keyFlags & RSTLV_KEY_TYPE_FULL); - if (!keyFlags_not_TYPE_FULL) {std::cout << "RsTlvPublicRSAKey::checkKey() keyFlags is Type Full " << std::hex << keyFlags << " & " << RSTLV_KEY_TYPE_FULL << std::dec << std::endl;} - bool security_OK = false; - if (keyFlags_PUBLIC_ONLY && keyFlags_not_TYPE_FULL) - { - //Don't trigg error if flags already wrong - security_OK = GxsSecurity::checkPublicKey(*this); - if (!security_OK) {std::cout << "RsTlvPublicRSAKey::checkKey() key is not secure."<< std::endl;} - } - - return keyFlags_PUBLIC_ONLY && keyFlags_not_TYPE_FULL && security_OK ; -} - -/************************************* RsTlvSecurityKeySet ************************************/ - -void RsTlvSecurityKeySet::TlvClear() -{ - groupId.clear(); -#ifdef TODO - public_keys.clear(); //empty list - private_keys.clear(); //empty list -#endif -} - -uint32_t RsTlvSecurityKeySet::TlvSize() const -{ - - uint32_t s = TLV_HEADER_SIZE; /* header */ - - s += GetTlvStringSize(groupId); - - for(std::map::const_iterator it = public_keys.begin(); it != public_keys.end() ; ++it) - s += (it->second).TlvSize(); - - for(std::map::const_iterator it = private_keys.begin(); it != private_keys.end() ; ++it) - s += (it->second).TlvSize(); - - return s; -} - -bool RsTlvSecurityKeySet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKeySet::SetTlv() Failed not enough space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_SECURITYKEYSET , tlvsize); - - /* groupId */ - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_GROUPID, groupId); - - for(std::map::const_iterator it = public_keys.begin(); it != public_keys.end() ; ++it) - ok &= (it->second).SetTlv(data, size, offset); - - for(std::map::const_iterator it = private_keys.begin(); it != private_keys.end() ; ++it) - ok &= (it->second).SetTlv(data, size, offset); - - return ok; -} - - -bool RsTlvSecurityKeySet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_SECURITYKEYSET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* groupId */ - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_GROUPID, groupId); - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - // Security key set can be composed of public or private keys. We first ask type to desserialize in good one to not trigg errors. - switch(tlvsubtype) - { - case TLV_TYPE_SECURITY_KEY: - { - RsTlvPublicRSAKey gen_key; - uint32_t keyType = gen_key.getKeyTypeTlv(data, tlvend, offset); - if(keyType == RSTLV_KEY_TYPE_PUBLIC_ONLY) - { - - RsTlvPublicRSAKey public_key; - - if(public_key.GetTlv(data, tlvend, offset)) - public_keys[public_key.keyId] = public_key; - } - else if(keyType == RSTLV_KEY_TYPE_FULL) - { - - RsTlvPrivateRSAKey private_key; - - if(private_key.GetTlv(data, tlvend, offset)) - private_keys[private_key.keyId] = private_key; - } - } - break ; - - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - - } - - if (!ok) - break; - } - - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKeySet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - - -// prints out contents of RsTlvSecurityKeySet -std::ostream &RsTlvSecurityKeySet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvSecurityKeySet", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "GroupId: " << groupId; - out << std::endl; - - for( std::map::const_iterator it = public_keys.begin(); it != public_keys.end() ; ++it) - (it->second).print(out, int_Indent); - for( std::map::const_iterator it = private_keys.begin(); it != private_keys.end() ; ++it) - (it->second).print(out, int_Indent); - - printEnd(out, "RsTlvSecurityKeySet", indent); - return out; -} - - -/************************************* RsTlvSecurityKey ************************************/ - -RsTlvKeySignature::RsTlvKeySignature() - :RsTlvItem(), signData(TLV_TYPE_SIGN_RSA_SHA1) -{ - ShallowClear() ; // avoids uninitialized memory if the fields are not initialized. -} - -void RsTlvKeySignature::TlvClear() -{ - keyId.clear(); - signData.TlvClear(); -} - -/* clears signData - but doesn't delete */ -void RsTlvKeySignature::ShallowClear() -{ - keyId.clear(); - signData.bin_data = 0; - signData.bin_len = 0; -} - -uint32_t RsTlvKeySignature::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header + 4 for size */ - -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - s += GetTlvStringSize(keyId.toStdString()) ; -#else - s += keyId.serial_size() ; -#endif - s += signData.TlvSize(); - return s; - -} - -bool RsTlvKeySignature::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignature::SetTlv() Fail, not enough space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_KEYSIGNATURE, tlvsize); - -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId.toStdString()); -#else - ok &= keyId.serialise(data, tlvend, *offset) ; -#endif - ok &= signData.SetTlv(data, tlvend, offset); - - if (!ok) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignature::SetTlv() Failed somewhere"; - std::cerr << std::endl; -#endif - } - - return ok; - -} - - -bool RsTlvKeySignature::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignature::GetTlv() Not Enough Space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - if (tlvtype != TLV_TYPE_KEYSIGNATURE) /* check type */ - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignature::GetTlv() Type Fail"; - std::cerr << std::endl; -#endif - return false; - } - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - std::string s ; - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, s); - keyId = RsGxsId(s) ; -#else - ok &= keyId.deserialise(data, tlvend, *offset) ; -#endif - ok &= signData.GetTlv(data, tlvend, offset); - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignature::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - -std::ostream &RsTlvKeySignature::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvKeySignature", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "KeyId:" << keyId; - out << std::endl; - - signData.print(out, int_Indent); - - out << std::endl; - - printEnd(out, "RsTlvKeySignature", indent); - return out; -} - - -/************************************* RsTlvKeySignatureSet ************************************/ - -RsTlvKeySignatureSet::RsTlvKeySignatureSet() -{ - -} - -std::ostream &RsTlvKeySignatureSet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvKeySignatureSet", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - - std::map::const_iterator mit = keySignSet.begin(); - - for(; mit != keySignSet.end(); ++mit) - { - out << "SignType: " << mit->first << std::endl; - const RsTlvKeySignature& sign = mit->second; - sign.print(out, indent); - } - - out << std::endl; - - printEnd(out, "RsTlvKeySignatureSet", indent); - return out; -} - -void RsTlvKeySignatureSet::TlvClear() -{ - keySignSet.clear(); -} - -bool RsTlvKeySignatureSet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignatureSet::SetTlv() Failed not enough space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_KEYSIGNATURESET , tlvsize); - - - if(!keySignSet.empty()) - { - std::map::const_iterator it; - - for(it = keySignSet.begin(); it != keySignSet.end() ; ++it) - { - ok &= SetTlvUInt32(data, size, offset, TLV_TYPE_KEYSIGNATURETYPE, it->first); - ok &= (it->second).SetTlv(data, size, offset); - } - } - - -return ok; -} - -bool RsTlvKeySignatureSet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_KEYSIGNATURESET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - SignType sign_type = 0; - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - switch(tlvsubtype) - { - case TLV_TYPE_KEYSIGNATURE: - { - RsTlvKeySignature sign; - ok &= sign.GetTlv(data, size, offset); - if (ok) - { - keySignSet[sign_type] = sign; - } - } - break; - case TLV_TYPE_KEYSIGNATURETYPE: - { - ok = GetTlvUInt32(data, size, offset, TLV_TYPE_KEYSIGNATURETYPE, &sign_type); - } - break; - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - } - - if (!ok) - break; - } - - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignatureSet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -uint32_t RsTlvKeySignatureSet::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; // header size - std::map::const_iterator it; - - for(it = keySignSet.begin(); it != keySignSet.end() ; ++it) - { - s += GetTlvUInt32Size(); // sign type - s += it->second.TlvSize(); // signature - } - - return s; -} - - - - - - - - - - - - - - - - - - - - diff --git a/libretroshare/src/serialiser/rstlvkeys.h b/libretroshare/src/serialiser/rstlvkeys.h deleted file mode 100644 index 5f82e51f0..000000000 --- a/libretroshare/src/serialiser/rstlvkeys.h +++ /dev/null @@ -1,146 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvkeys.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvbase.h" -#include "retroshare/rsgxsifacetypes.h" - -#include - -const uint32_t RSTLV_KEY_TYPE_MASK = 0x000f; -const uint32_t RSTLV_KEY_TYPE_PUBLIC_ONLY = 0x0001; -const uint32_t RSTLV_KEY_TYPE_FULL = 0x0002; - -const uint32_t RSTLV_KEY_DISTRIB_PUBLIC_deprecated = 0x0010;// was used as PUBLISH flag. Probably a typo. - -const uint32_t RSTLV_KEY_DISTRIB_PUBLISH = 0x0020; -const uint32_t RSTLV_KEY_DISTRIB_ADMIN = 0x0040; -const uint32_t RSTLV_KEY_DISTRIB_IDENTITY = 0x0080; -const uint32_t RSTLV_KEY_DISTRIB_MASK = 0x00f0; - -// Old class for RsTlvSecurityKey. Is kept for backward compatibility, but should not be serialised anymore - -class RsTlvRSAKey: public RsTlvItem -{ -public: - RsTlvRSAKey(); - virtual bool checkKey() const = 0 ; // this pure virtual forces people to explicitly declare if they use a public or a private key. - - virtual uint32_t TlvSize() const; - virtual void TlvClear(); - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - virtual std::ostream& print(std::ostream &out, uint16_t indent) const; - - /* clears KeyData - but doesn't delete - to transfer ownership */ - void ShallowClear(); - - uint32_t getKeyTypeTlv(void *data, uint32_t size, uint32_t *offset) const; - - RsGxsId keyId; // Mandatory : - uint32_t keyFlags; // Mandatory ; - uint32_t startTS; // Mandatory : - uint32_t endTS; // Mandatory : - RsTlvBinaryData keyData; // Mandatory : -}; - -// The two classes below are by design incompatible, making it impossible to pass a private key as a public key - -class RsTlvPrivateRSAKey: public RsTlvRSAKey -{ -public: - RsTlvPrivateRSAKey():RsTlvRSAKey() {} - virtual ~RsTlvPrivateRSAKey() {} - - virtual bool checkKey() const ; -}; -class RsTlvPublicRSAKey: public RsTlvRSAKey -{ -public: - RsTlvPublicRSAKey():RsTlvRSAKey() {} - virtual ~RsTlvPublicRSAKey() {} - - virtual bool checkKey() const ; -}; - -class RsTlvSecurityKeySet: public RsTlvItem -{ -public: - RsTlvSecurityKeySet() { return; } - virtual ~RsTlvSecurityKeySet() { return; } - - // creates the public keys that are possible missing although the private keys are present. - - void createPublicFromPrivateKeys(); - - virtual uint32_t TlvSize() const; - virtual void TlvClear(); - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - std::string groupId; // Mandatory : - std::map public_keys; // Mandatory : - std::map private_keys; // Mandatory : -}; - - -class RsTlvKeySignature: public RsTlvItem -{ - public: - RsTlvKeySignature(); - virtual ~RsTlvKeySignature() { return; } - virtual uint32_t TlvSize() const; - virtual void TlvClear(); - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - void ShallowClear(); /* clears signData - but doesn't delete */ - - RsGxsId keyId; // Mandatory : - RsTlvBinaryData signData; // Mandatory : -}; - -typedef uint32_t SignType; - -class RsTlvKeySignatureSet : public RsTlvItem -{ -public: - RsTlvKeySignatureSet(); - virtual ~RsTlvKeySignatureSet() { return; } - virtual uint32_t TlvSize() const; - virtual void TlvClear(); - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - std::map keySignSet; // mandatory -}; - - diff --git a/libretroshare/src/serialiser/rstlvkeyvalue.cc b/libretroshare/src/serialiser/rstlvkeyvalue.cc deleted file mode 100644 index c666307ef..000000000 --- a/libretroshare/src/serialiser/rstlvkeyvalue.cc +++ /dev/null @@ -1,295 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvkeyvalue.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#include "rstlvkeyvalue.h" -#include "rstlvbase.h" - -// #define TLV_DEBUG 1 - -void RsTlvKeyValue::TlvClear() -{ - key = ""; - value = ""; -} - -uint32_t RsTlvKeyValue::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* now add comment and title length of this tlv object */ - - if (key.length() > 0) - s += GetTlvStringSize(key); - if (value.length() > 0) - s += GetTlvStringSize(value); - - return s; - -} - -bool RsTlvKeyValue::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_KEYVALUE, tlvsize); - - - - /* now optional ones */ - if (key.length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEY, key); // no base tlv type for title? - if (value.length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_VALUE, value); // no base tlv type for comment? - -return ok; - -} - -bool RsTlvKeyValue::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_KEYVALUE) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - switch(tlvsubtype) - { - case TLV_TYPE_STR_KEY: - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEY, key); - break; - case TLV_TYPE_STR_VALUE: - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_VALUE, value); - break; - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - - } - - if (!ok) - { - break; - } - } - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeyValue::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - -std::ostream &RsTlvKeyValue::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvKeyValue", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "Key:" << key; - printIndent(out, int_Indent); - out << "Value:" << value; - out << std::endl; - - - printEnd(out, "RsTlvKeyValue", indent); - return out; -} - -/************************************* RsTlvKeyValueSet ************************************/ - -void RsTlvKeyValueSet::TlvClear() -{ - pairs.clear(); //empty list -} - -uint32_t RsTlvKeyValueSet::TlvSize() const -{ - - uint32_t s = TLV_HEADER_SIZE; /* header */ - - std::list::const_iterator it; - - if(!pairs.empty()) - { - - for(it = pairs.begin(); it != pairs.end() ; ++it) - s += it->TlvSize(); - - } - - return s; -} - -bool RsTlvKeyValueSet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_KEYVALUESET , tlvsize); - - - if(!pairs.empty()) - { - std::list::const_iterator it; - - for(it = pairs.begin(); it != pairs.end() ; ++it) - ok &= it->SetTlv(data, size, offset); - } - - -return ok; - -} - - -bool RsTlvKeyValueSet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_KEYVALUESET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - switch(tlvsubtype) - { - case TLV_TYPE_KEYVALUE: - { - RsTlvKeyValue kv; - ok &= kv.GetTlv(data, size, offset); - if (ok) - { - pairs.push_back(kv); - } - } - break; - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - - } - - if (!ok) - break; - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeyValueSet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -/// prints out contents of RsTlvKeyValueSet -std::ostream &RsTlvKeyValueSet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvKeyValue", indent); - - std::list::const_iterator it; - - for(it = pairs.begin(); it != pairs.end() ; ++it) - it->print(out, indent); - - printEnd(out, "RsTlvKeyValue", indent); - return out; -} - diff --git a/libretroshare/src/serialiser/rstlvkeyvalue.h b/libretroshare/src/serialiser/rstlvkeyvalue.h deleted file mode 100644 index 63cf3091f..000000000 --- a/libretroshare/src/serialiser/rstlvkeyvalue.h +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvkeyvalue.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include - -class RsTlvKeyValue: public RsTlvItem -{ - public: - RsTlvKeyValue() { return; } - RsTlvKeyValue(const std::string& k,const std::string& v): key(k),value(v) {} -virtual ~RsTlvKeyValue() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - std::string key; /// Mandatory : For use in hash tables - std::string value; /// Mandatory : For use in hash tables -}; - -class RsTlvKeyValueSet: public RsTlvItem -{ - public: - RsTlvKeyValueSet() { return; } -virtual ~RsTlvKeyValueSet() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - std::list pairs; /// For use in hash tables -}; - - diff --git a/libretroshare/src/serialiser/rstlvlist.h b/libretroshare/src/serialiser/rstlvlist.h deleted file mode 100644 index 90c430ede..000000000 --- a/libretroshare/src/serialiser/rstlvlist.h +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvlist.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvitem.h" - -#include - -// #define TLV_DEBUG_LIST 1 - -template class t_RsTlvList: public RsTlvItem -{ - public: - t_RsTlvList() {} - virtual ~t_RsTlvList() {} - - virtual uint32_t TlvSize() const - { - uint32_t size = TLV_HEADER_SIZE; - typename std::list::const_iterator it; - for(it = mList.begin();it != mList.end(); ++it) - { - size += it->TlvSize(); - } - return size; - } - virtual void TlvClear(){ mList.clear(); } - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const - { - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - /* must check sizes */ - - if (size < tlvend) - { -#ifdef TLV_DEBUG_LIST - std::cerr << "RsTlvList::SetTlv() Not enough size"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE, tlvsize); - - typename std::list::const_iterator it; - for(it = mList.begin();it != mList.end(); ++it) - { - ok &= it->SetTlv(data,tlvend,offset) ; - } - return ok ; - } - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset) - { - if (size < *offset + TLV_HEADER_SIZE) - { -#ifdef TLV_DEBUG_LIST - std::cerr << "RsTlvList::GetTlv() Not enough size"; - std::cerr << std::endl; -#endif - return false; - } - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is TLV : 2 (type) + 4 (len) */ - while(ok && ((*offset) + 6 < tlvend)) - { - TLV_CLASS item; - ok &= item.GetTlv(data,tlvend,offset); - if (ok) - { - mList.push_back(item); - } - } - - if(*offset != tlvend) - { - std::cerr << "(EE) deserialisation error in " << __PRETTY_FUNCTION__ << std::endl; - } - return *offset == tlvend ; - } - - virtual std::ostream &print(std::ostream &out, uint16_t indent) const - { - printBase(out, "Template TlvList", indent); - typename std::list::const_iterator it; - for(it = mList.begin();it != mList.end(); ++it) - { - it->print(out, indent + 2) ; - } - printEnd(out, "Template TlvList", indent); - return out ; - } - - std::list mList; -}; - - - diff --git a/libretroshare/src/serialiser/rstlvmaps.h b/libretroshare/src/serialiser/rstlvmaps.h deleted file mode 100644 index 49b05e382..000000000 --- a/libretroshare/src/serialiser/rstlvmaps.h +++ /dev/null @@ -1,34 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvmaps.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_TLV_MAPS_H -#define RS_TLV_MAPS_H - -class RsTlvOpinionMapRef: public RsTlvGenericMapRef -{ -public: - RsTlvOpinionMapRef(std::map &refmap) - :RsTlvGenericMapRef(OPINION, STRING_INT_PAIR, refmap) { return; } -}; - - -#endif - diff --git a/libretroshare/src/serialiser/rstlvstring.cc b/libretroshare/src/serialiser/rstlvstring.cc deleted file mode 100644 index d1e636d52..000000000 --- a/libretroshare/src/serialiser/rstlvstring.cc +++ /dev/null @@ -1,371 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvstring.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rstlvstring.h" - -#include "serialiser/rstlvbase.h" -#include "util/rsprint.h" -#include - -// #define TLV_DEBUG 1 - -/************************************* Peer Id Set ************************************/ - - -RsTlvStringSet::RsTlvStringSet(uint16_t type) :mType(type) -{ -} - - -bool RsTlvStringSet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, mType , tlvsize); - - /* determine the total size of ids strings in list */ - - std::list::const_iterator it; - - for(it = ids.begin(); it != ids.end() ; ++it) - { - if (it->length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, *it); - } - - return ok; - -} - - -void RsTlvStringSet::TlvClear() -{ - ids.clear(); - -} - -uint32_t RsTlvStringSet::TlvSize() const -{ - - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* determine the total size of ids strings in list */ - - std::list::const_iterator it; - - for(it = ids.begin(); it != ids.end() ; ++it) - { - if (it->length() > 0) - s += GetTlvStringSize(*it); - } - - return s; -} - - -bool RsTlvStringSet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != mType) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - - -/* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - if (tlvsubtype == TLV_TYPE_STR_GENID) - { - std::string newIds; - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, newIds); - if(ok) - { - ids.push_back(newIds); - - } - } - else - { - /* Step past unknown TLV TYPE */ - ok &= SkipUnknownTlv(data, tlvend, offset); - } - - if (!ok) - { - break; - } - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvPeerIdSet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -/// print to screen RsTlvStringSet contents -std::ostream &RsTlvStringSet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvStringSet", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "type:" << mType; - out << std::endl; - - std::list::const_iterator it; - for(it = ids.begin(); it != ids.end() ; ++it) - { - printIndent(out, int_Indent); - out << "id:" << *it; - out << std::endl; - } - - printEnd(out, "RsTlvStringSet", indent); - return out; - -} - -/// print to screen RsTlvStringSet contents -std::ostream &RsTlvStringSet::printHex(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvStringSet", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "type:" << mType; - out << std::endl; - - std::list::const_iterator it; - for(it = ids.begin(); it != ids.end() ; ++it) - { - printIndent(out, int_Indent); - out << "id: 0x" << RsUtil::BinToHex(*it); - out << std::endl; - } - - printEnd(out, "RsTlvStringSet", indent); - return out; - -} - - -/************************************* String Set Ref ************************************/ -/* This is exactly the same as StringSet, but it uses an alternative list. - */ -RsTlvStringSetRef::RsTlvStringSetRef(uint16_t type, std::list &refids) - :mType(type), ids(refids) -{ -} - -void RsTlvStringSetRef::TlvClear() -{ - ids.clear(); - -} - -uint32_t RsTlvStringSetRef::TlvSize() const -{ - - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* determine the total size of ids strings in list */ - - std::list::const_iterator it; - - for(it = ids.begin(); it != ids.end() ; ++it) - { - if (it->length() > 0) - s += GetTlvStringSize(*it); - } - - return s; -} - - -bool RsTlvStringSetRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, mType , tlvsize); - - /* determine the total size of ids strings in list */ - - std::list::const_iterator it; - - for(it = ids.begin(); it != ids.end() ; ++it) - { - if (it->length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, *it); - } - - return ok; - -} - - -bool RsTlvStringSetRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != mType) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - - -/* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - if (tlvsubtype == TLV_TYPE_STR_GENID) - { - std::string newIds; - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, newIds); - if(ok) - { - ids.push_back(newIds); - - } - } - else - { - /* Step past unknown TLV TYPE */ - ok &= SkipUnknownTlv(data, tlvend, offset); - } - - if (!ok) - { - break; - } - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvPeerIdSetRef::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -/// print to screen RsTlvStringSet contents -std::ostream &RsTlvStringSetRef::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvStringSetRef", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "type:" << mType; - out << std::endl; - - std::list::const_iterator it; - for(it = ids.begin(); it != ids.end() ; ++it) - { - printIndent(out, int_Indent); - out << "id:" << *it; - out << std::endl; - } - - printEnd(out, "RsTlvStringSetRef", indent); - return out; - -} - diff --git a/libretroshare/src/serialiser/rstlvstring.h b/libretroshare/src/serialiser/rstlvstring.h deleted file mode 100644 index 5e0c2f276..000000000 --- a/libretroshare/src/serialiser/rstlvstring.h +++ /dev/null @@ -1,64 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvstring.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "serialiser/rstlvitem.h" - -#include - -class RsTlvStringSet: public RsTlvItem -{ - public: -explicit RsTlvStringSet(uint16_t type); -virtual ~RsTlvStringSet() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; -virtual std::ostream &printHex(std::ostream &out, uint16_t indent) const; - - uint16_t mType; - std::list ids; /* Mandatory */ -}; - -class RsTlvStringSetRef: public RsTlvItem -{ - public: - RsTlvStringSetRef(uint16_t type, std::list &refids); -virtual ~RsTlvStringSetRef() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint16_t mType; - std::list &ids; /* Mandatory */ -}; - - diff --git a/libretroshare/src/serialiser/rstypeserializer.cc b/libretroshare/src/serialiser/rstypeserializer.cc deleted file mode 100644 index 0c7bfc435..000000000 --- a/libretroshare/src/serialiser/rstypeserializer.cc +++ /dev/null @@ -1,712 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstypeserializer.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Cyril Soler * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#include "serialiser/rsserializer.h" -#include "serialiser/rstypeserializer.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvkeys.h" -#include "serialiser/rsserializable.h" -#include "util/rsbase64.h" -#include "util/rsprint.h" -#include "util/rstime.h" - -#include -#include -#include // for typeid -#include - -#ifdef RSSERIAL_DEBUG -# define SAFE_GET_JSON_V() \ - const char* mName = memberName.c_str(); \ - bool ret = jDoc.HasMember(mName); \ - if(!ret) \ - { \ - std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName \ - << "\" not found in JSON:" << std::endl \ - << jDoc << std::endl << std::endl; \ - return false; \ - } \ - rapidjson::Value& v = jDoc[mName] -#else // ifdef RSSERIAL_DEBUG -# define SAFE_GET_JSON_V() \ - const char* mName = memberName.c_str(); \ - bool ret = jDoc.HasMember(mName); \ - if(!ret) return false; \ - rapidjson::Value& v = jDoc[mName] -#endif // ifdef RSSERIAL_DEBUG - -//============================================================================// -// std::string // -//============================================================================// - -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(membername.length()), - allocator ); - - rapidjson::Value value; - value.SetString( member.c_str(), - static_cast(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; -} - - -//============================================================================// -// Integral types // -//============================================================================// - -#define SIMPLE_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(memberName.length()), \ - allocator ); \ - \ - rapidjson::Value value(member); \ - \ - jDoc.AddMember(key, value, allocator); \ - \ - return true; \ -} - -SIMPLE_TO_JSON_DEF(bool) -SIMPLE_TO_JSON_DEF(int32_t) - -SIMPLE_TO_JSON_DEF(uint8_t) -SIMPLE_TO_JSON_DEF(uint16_t) -SIMPLE_TO_JSON_DEF(uint32_t) - -/** Be very careful in changing this constant as it would break 64 bit integers - * members JSON string representation retrocompatibility */ -static constexpr char strReprKey[] = "xstr64"; - -/** Be very careful in changing this constant as it would break 64 bit integers - * members JSON string representation retrocompatibility */ -static constexpr char intReprKey[] = "xint64"; - -/** While JSON doesn't have problems representing 64 bits integers JavaScript, - * Dart and other languages represents numbers in a double-like format thus they - * are not capable to handle safely integers outside the range - * [-(2^53 - 1), 2^53 - 1]. - * To overcome this limitation we represent 64 bit integers as an object with - * two keys, one as integer and one as string representation. - * In our case we need to wrap those into an object instead of just adding a key - * with a suffix so support well also containers like std::map or std::vector. - * More discussion on the topic at @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 ) \ -{ \ - using namespace rapidjson; \ - Document::AllocatorType& allocator = jDoc.GetAllocator(); \ - \ - Document wrapper(rapidjson::kObjectType, &allocator); \ - \ - Value intKey; \ - intKey.SetString(intReprKey, allocator ); \ - Value intValue(member); \ - wrapper.AddMember(intKey, intValue, allocator); \ - \ - bool ok = to_JSON(strReprKey, std::to_string(member), wrapper); \ - \ - Value key; \ - key.SetString( memberName.c_str(), \ - static_cast(memberName.length()), \ - allocator ); \ - jDoc.AddMember(key, wrapper, allocator); \ - \ - return ok; \ -} - -SIXTYFOUR_INTEGERS_TO_JSON_DEF(int64_t); -SIXTYFOUR_INTEGERS_TO_JSON_DEF(uint64_t); - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, bool& member, - RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsBool(); - if(ret) member = v.GetBool(); - return ret; -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - int32_t& member, RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsInt(); - if(ret) member = v.GetInt(); - return ret; -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint8_t& member, RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsUint(); - if(ret) member = static_cast(v.GetUint()); - return ret; -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint16_t& member, RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsUint(); - if(ret) member = static_cast(v.GetUint()); - return ret; -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint32_t& member, RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsUint(); - if(ret) member = v.GetUint(); - return ret; -} - -/** inverse of @see SIXTYFOUR_INTEGERS_TO_JSON_DEF */ -#define SIXTYFOUR_INTEGERS_FROM_JSON_DEF(T, PRED, GET, CONV) \ -template<> bool RsTypeSerializer::from_JSON( \ - const std::string& memberName, T& member, RsJson& jDoc ) \ -{ \ - using namespace rapidjson; \ - \ - SAFE_GET_JSON_V(); \ - \ - /* For retro-compatibility take it directly if it is passed as integer */ \ - if(v.PRED()) \ - { \ - member = v.GET(); \ - return true; \ - } \ - \ - ret = ret && v.IsObject(); \ - \ - if(!ret) \ - { \ - RS_DBG3(memberName, " not found"); \ - return false; \ - } \ - \ - if(v.HasMember(intReprKey)) \ - { \ - Value& iVal = v[intReprKey]; \ - if(iVal.PRED()) \ - { \ - member = iVal.GET(); \ - return true; \ - } \ - } \ - \ - Dbg4() << __PRETTY_FUNCTION__ << " integer representation of " << memberName \ - << " not found in JSON then attempt to look for string representation" \ - << std::endl; \ - \ - \ - if(v.HasMember(strReprKey)) \ - { \ - Value& sVal = v[strReprKey]; \ - if(sVal.IsString()) \ - { \ - try { member = CONV(sVal.GetString()); } \ - catch (...) \ - { \ - RsErr() << __PRETTY_FUNCTION__ << " cannot convert " \ - << sVal.GetString() << " to integral type" << std::endl; \ - return false; \ - } \ - \ - return true; \ - } \ - } \ - \ - Dbg3() << __PRETTY_FUNCTION__ << " neither integral representation nor " \ - << "string representation found for: " << memberName << std::endl; \ - \ - return false; \ -} - -SIXTYFOUR_INTEGERS_FROM_JSON_DEF(uint64_t, IsUint64, GetUint64, std::stoull) -SIXTYFOUR_INTEGERS_FROM_JSON_DEF( int64_t, IsInt64, GetInt64, std::stoll) - -//============================================================================// -// Floats // -//============================================================================// - -template<> uint32_t RsTypeSerializer::serial_size(const float&){ return 4; } - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t& offset, const float& f) -{ - return setRawUFloat32(data,size,&offset,f) ; -} -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, float& f) -{ - return getRawUFloat32(data,size,&offset,f) ; -} -template<> void RsTypeSerializer::print_data(const std::string& n, const float& V) -{ - std::cerr << " [float ] " << n << ": " << V << std::endl; -} - -SIMPLE_TO_JSON_DEF(float) - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - float& member, RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsFloat(); - if(ret) member = v.GetFloat(); - return ret; -} - -template<> /*static*/ -uint32_t RsTypeSerializer::serial_size(const double&) -{ - std::cerr << "Binary [de]serialization not implemented yet for double" - << std::endl; - print_stacktrace(); - return 0; -} - -template<> /*static*/ -bool RsTypeSerializer::serialize(uint8_t[], uint32_t, uint32_t&, const double&) -{ - std::cerr << "Binary [de]serialization not implemented yet for double" - << std::endl; - print_stacktrace(); - return false; -} - -template<> /*static*/ -bool RsTypeSerializer::deserialize(const uint8_t[], uint32_t, uint32_t&, double&) -{ - std::cerr << "Binary [de]serialization not implemented yet for double" - << std::endl; - print_stacktrace(); - return false; -} - -template<> /*static*/ -void RsTypeSerializer::print_data(const std::string& n, const double& V) -{ std::cerr << " [double ] " << n << ": " << V << std::endl; } - -SIMPLE_TO_JSON_DEF(double) - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - double& member, RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsDouble(); - if(ret) member = v.GetDouble(); - return ret; -} - - -//============================================================================// -// TlvString with subtype // -//============================================================================// - -template<> uint32_t RsTypeSerializer::serial_size(uint16_t /* type_subtype */,const std::string& s) -{ - return GetTlvStringSize(s) ; -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,uint16_t type_substring,const std::string& s) -{ - return SetTlvString(data,size,&offset,type_substring,s) ; -} - -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,uint16_t type_substring,std::string& s) -{ - return GetTlvString((void*)data,size,&offset,type_substring,s) ; -} - -template<> void RsTypeSerializer::print_data(const std::string& n, uint16_t type_substring,const std::string& V) -{ - std::cerr << " [TlvString ] " << n << ": type=" << std::hex < /*static*/ -bool RsTypeSerializer::to_JSON( const std::string& memberName, - uint16_t /*sub_type*/, - const std::string& member, RsJson& jDoc ) -{ - return to_JSON(memberName, member, jDoc); -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint16_t /*sub_type*/, - std::string& member, RsJson& jDoc ) -{ - return from_JSON(memberName, member, jDoc); -} - -//============================================================================// -// TlvInt with subtype // -//============================================================================// - -template<> uint32_t RsTypeSerializer::serial_size( uint16_t /* type_subtype */, - const uint32_t& /*s*/ ) -{ - return GetTlvUInt32Size(); -} - -template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size, - uint32_t &offset,uint16_t sub_type, - const uint32_t& s) -{ - return SetTlvUInt32(data,size,&offset,sub_type,s); -} - -template<> bool RsTypeSerializer::deserialize( const uint8_t data[], - uint32_t size, uint32_t& offset, - uint16_t sub_type, uint32_t& s) -{ - return GetTlvUInt32((void*)data, size, &offset, sub_type, &s); -} - -template<> void RsTypeSerializer::print_data(const std::string& n, uint16_t sub_type,const uint32_t& V) -{ - std::cerr << " [TlvUInt32 ] " << n << ": type=" << std::hex - << std::setw(4) << std::setfill('0') << sub_type << std::dec - << " s=\"" << V << "\"" << std::endl; -} - -template<> /*static*/ -bool RsTypeSerializer::to_JSON( const std::string& memberName, - uint16_t /*sub_type*/, - const uint32_t& member, RsJson& jDoc ) -{ - return to_JSON(memberName, member, jDoc); -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint16_t /*sub_type*/, - uint32_t& member, RsJson& jDoc ) -{ - return from_JSON(memberName, member, jDoc); -} - - -//============================================================================// -// TlvItems // -//============================================================================// - -template<> uint32_t RsTypeSerializer::serial_size(const RsTlvItem& s) -{ - return s.TlvSize(); -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, - uint32_t &offset,const RsTlvItem& s) -{ - return s.SetTlv(data,size,&offset); -} - -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], - uint32_t size,uint32_t& offset, - RsTlvItem& s) -{ - return s.GetTlv((void*)data,size,&offset) ; -} - -template<> void RsTypeSerializer::print_data( const std::string& n, - const RsTlvItem& s ) -{ - std::cerr << " [" << typeid(s).name() << "] " << n << std::endl; -} - -template<> /*static*/ -bool RsTypeSerializer::to_JSON( const std::string& memberName, - const RsTlvItem& member, RsJson& jDoc ) -{ - rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); - - rapidjson::Value key; - key.SetString(memberName.c_str(), memberName.length(), allocator); - - rapidjson::Value value; - const char* tName = typeid(member).name(); - value.SetString(tName, allocator); - - jDoc.AddMember(key, value, allocator); - - return true; -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& /*memberName*/, - RsTlvItem& member, RsJson& /*jDoc*/) -{ - member.TlvClear(); - return true; -} - - -//============================================================================// -// Binary blocks // -//============================================================================// - -#if __cplusplus < 201703L -/* Solve weird undefined reference error with C++ < 17 see: - * https://stackoverflow.com/questions/8016780/undefined-reference-to-static-constexpr-char - */ -/*static*/ decltype(RsTypeSerializer::RawMemoryWrapper::base64_key) constexpr -RsTypeSerializer::RawMemoryWrapper::base64_key; - -/*static*/ /* without this Android compilation breaks */ -constexpr uint32_t RsTypeSerializer::RawMemoryWrapper::MAX_SERIALIZED_CHUNK_SIZE; -#endif - -/*static*/ -void RsTypeSerializer::RawMemoryWrapper::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - RS_SERIAL_PROCESS(second); - ctx.mOffset += second; - break; - case RsGenericSerializer::SERIALIZE: - if(!ctx.mOk) break; - if(second > MAX_SERIALIZED_CHUNK_SIZE) - { - RsErr() << __PRETTY_FUNCTION__ - << std::errc::message_size << " " - << second << " > " << MAX_SERIALIZED_CHUNK_SIZE - << std::endl; - print_stacktrace(); - break; - } - RS_SERIAL_PROCESS(second); - if(!ctx.mOk) break; - ctx.mOk = ctx.mSize >= ctx.mOffset + second; - if(!ctx.mOk) - { - RsErr() << __PRETTY_FUNCTION__ << std::errc::no_buffer_space - << std::endl; - print_stacktrace(); - break; - } - memcpy(ctx.mData + ctx.mOffset, first, second); - ctx.mOffset += second; - break; - case RsGenericSerializer::DESERIALIZE: - freshMemCheck(); - - RS_SERIAL_PROCESS(second); - if(!ctx.mOk) break; - ctx.mOk = (second <= MAX_SERIALIZED_CHUNK_SIZE); - if(!ctx.mOk) - { - RsErr() << __PRETTY_FUNCTION__ - << std::errc::message_size << " " - << second << " > " << MAX_SERIALIZED_CHUNK_SIZE - << std::endl; - clear(); - break; - } - - if(!second) - { - Dbg3() << __PRETTY_FUNCTION__ << " Deserialized empty memory chunk" - << std::endl; - clear(); - break; - } - - ctx.mOk = ctx.mSize >= ctx.mOffset + second; - if(!ctx.mOk) - { - RsErr() << __PRETTY_FUNCTION__ << std::errc::no_buffer_space - << std::endl; - print_stacktrace(); - - clear(); - break; - } - - first = reinterpret_cast(malloc(second)); - memcpy(first, ctx.mData + ctx.mOffset, second); - ctx.mOffset += second; - break; - case RsGenericSerializer::PRINT: break; - case RsGenericSerializer::TO_JSON: - { - if(!ctx.mOk) break; - std::string encodedValue; - RsBase64::encode(first, second, encodedValue, true, false); - ctx.mOk = ctx.mOk && - RsTypeSerializer::to_JSON(base64_key, encodedValue, ctx.mJson); - break; - } - case RsGenericSerializer::FROM_JSON: - { - freshMemCheck(); - - const auto failure = [&]() -> void { ctx.mOk = false; clear(); }; - const bool yielding = !!( - RsSerializationFlags::YIELDING & ctx.mFlags ); - if(!(ctx.mOk || yielding)) return failure(); - - std::string encodedValue; - if(!RsTypeSerializer::from_JSON( - base64_key, encodedValue, ctx.mJson )) return failure(); - - if( encodedValue.length() > - RsBase64::encodedSize(MAX_SERIALIZED_CHUNK_SIZE, true) ) - { - RsErr() << __PRETTY_FUNCTION__ << " " - << std::errc::message_size << std::endl; - print_stacktrace(); - - return failure(); - } - - std::vector decoded; - auto ec = RsBase64::decode(encodedValue, decoded); - if(ec) - { - RsErr() << __PRETTY_FUNCTION__ << " " << ec << std::endl; - print_stacktrace(); - - return failure(); - } - - const auto decodedSize = decoded.size(); - - if(!decodedSize) - { - clear(); - break; - } - - first = reinterpret_cast(malloc(decodedSize)); - second = static_cast(decodedSize); - - memcpy(first, decoded.data(), second); - break; - } - default: RsTypeSerializer::fatalUnknownSerialJob(j); - } -} - -void RsTypeSerializer::RawMemoryWrapper::clear() -{ - free(first); - first = nullptr; - second = 0; -} - -bool RsTypeSerializer::RawMemoryWrapper::freshMemCheck() -{ - if(first || second) - { - /* Items are created anew before deserialization so buffer pointer - * must be null and size 0 at this point */ - - RsWarn() << __PRETTY_FUNCTION__ << " got uninitialized " - << " or pre-allocated buffer! Buffer pointer: " << first - << " must be null and size: " << second << " must be 0 at " - << "this point. Does your item costructor initialize them " - << "properly?" << std::endl; - print_stacktrace(); - return false; - } - return true; -} - -//============================================================================// -// std::error_condition // -//============================================================================// - -void RsTypeSerializer::ErrConditionWrapper::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: // fallthrough - case RsGenericSerializer::DESERIALIZE: // fallthrough - case RsGenericSerializer::SERIALIZE: // fallthrough - case RsGenericSerializer::FROM_JSON: // [[fallthrough]] - case RsGenericSerializer::PRINT: - RsFatal() << __PRETTY_FUNCTION__ << " SerializeJob: " << j - << "is not supported on std::error_condition " << std::endl; - print_stacktrace(); - exit(-2); - case RsGenericSerializer::TO_JSON: - { - constexpr RsGenericSerializer::SerializeJob rj = - RsGenericSerializer::TO_JSON; - - int32_t tNum = mec.value(); - RsTypeSerializer::serial_process(rj, ctx, tNum, "errorNumber"); - - std::string tStr = mec.category().name(); - RsTypeSerializer::serial_process(rj, ctx, tStr, "errorCategory"); - - tStr = mec.message(); - RsTypeSerializer::serial_process(rj, ctx, tStr, "errorMessage"); - break; - } - default: RsTypeSerializer::fatalUnknownSerialJob(j); - } -} diff --git a/libretroshare/src/serialiser/rstypeserializer.h b/libretroshare/src/serialiser/rstypeserializer.h deleted file mode 100644 index 6474f6971..000000000 --- a/libretroshare/src/serialiser/rstypeserializer.h +++ /dev/null @@ -1,1369 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstypeserializer.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Cyril Soler * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include // for typeid -#include -#include -#include -#include -#include - -#include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvlist.h" -#include "retroshare/rsflags.h" -#include "retroshare/rsids.h" -#include "util/rsendian.h" -#include "serialiser/rsserializer.h" -#include "serialiser/rsserializable.h" -#include "util/rsjson.h" -#include "util/rsdebuglevel1.h" -#include "util/cxx14retrocompat.h" - - -struct RsTypeSerializer -{ - /** Use this wrapper to serialize raw memory chunks - * RsTypeSerializer::RawMemoryWrapper chunkWrapper(chunk_data, chunk_size); - * RsTypeSerializer::serial_process(j, ctx, chunkWrapper, "chunk_data"); - **/ - struct RawMemoryWrapper: std::pair, RsSerializable - { - RawMemoryWrapper(uint8_t*& p,uint32_t& s) : - std::pair(p,s) {} - RawMemoryWrapper(void*& p, uint32_t& s) : - std::pair(*(uint8_t**)(&p),s) {} - - /// Maximum supported size 10MB - static constexpr uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024; - - /** Key used for JSON serialization. - * @note Changing this value breaks JSON API retro-compatibility */ - static constexpr char base64_key[] = "base64"; - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - private: - void clear(); - bool freshMemCheck(); - }; - - /// Most types are not valid sequence containers - template - struct is_sequence_container : std::false_type {}; - - /// Trait to match supported strings types - template - struct is_string : std::is_same, std::string> {}; - - /// Integral types - template - typename std::enable_if::value>::type - static /*void*/ serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - INTT& member, const std::string& member_name ) - { - const bool VLQ_ENCODING = !!( - RsSerializationFlags::INTEGER_VLQ & ctx.mFlags ); - - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - if(VLQ_ENCODING) ctx.mOffset += VLQ_size(member); - else ctx.mOffset += sizeof(INTT); - break; - case RsGenericSerializer::SERIALIZE: - { - if(!ctx.mOk) break; - if(VLQ_ENCODING) - ctx.mOk = VLQ_serialize( - ctx.mData, ctx.mSize, ctx.mOffset, member ); - else - { - ctx.mOk = ctx.mSize >= ctx.mOffset + sizeof(INTT); - if(!ctx.mOk) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot serialise " - << typeid(INTT).name() << " " - << " ctx.mSize: " << ctx.mSize - << " ctx.mOffset: " << ctx.mOffset - << " sizeof(INTT): " << sizeof(INTT) - << std::error_condition(std::errc::no_buffer_space) - << std::endl; - print_stacktrace(); - break; - } - INTT netorder_num = rs_endian_fix(member); - memcpy(ctx.mData + ctx.mOffset, &netorder_num, sizeof(INTT)); - ctx.mOffset += sizeof(INTT); - } - break; - } - case RsGenericSerializer::DESERIALIZE: - if(!ctx.mOk) break; - if(VLQ_ENCODING) ctx.mOk = VLQ_deserialize( - ctx.mData, ctx.mSize, ctx.mOffset, member ); - else - { - ctx.mOk = ctx.mSize >= ctx.mOffset + sizeof(INTT); - if(!ctx.mOk) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot deserialise " - << typeid(INTT).name() << " " - << " ctx.mSize: " << ctx.mSize - << " ctx.mOffset: " << ctx.mOffset - << " sizeof(INTT): " << sizeof(INTT) - << std::error_condition(std::errc::no_buffer_space) - << std::endl; - print_stacktrace(); - exit(-1); - break; - } - memcpy(&member, ctx.mData + ctx.mOffset, sizeof(INTT)); - member = rs_endian_fix(member); - ctx.mOffset += sizeof(INTT); - } - break; - case RsGenericSerializer::PRINT: break; - case RsGenericSerializer::TO_JSON: - ctx.mOk = ctx.mOk && to_JSON(member_name, member, ctx.mJson); - break; - case RsGenericSerializer::FROM_JSON: - ctx.mOk &= ( ctx.mOk || - !!(RsSerializationFlags::YIELDING & ctx.mFlags) ) - && from_JSON(member_name, member, ctx.mJson); - break; - default: fatalUnknownSerialJob(j); - } - } - -//============================================================================// -// Generic types // -//============================================================================// - - template - typename - std::enable_if< std::is_same::value || !( - std::is_integral::value || - std::is_base_of::value || - std::is_enum::value || - std::is_base_of::value || - std::is_same::value || - is_sequence_container::value || is_string::value ) >::type - static /*void*/ serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - T& memberC, const std::string& member_name ) - { - // Avoid problems with const sneaking into template paramether - using m_t = std::remove_const_t; - m_t& member = const_cast(memberC); - - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - ctx.mOffset += serial_size(member); - break; - case RsGenericSerializer::DESERIALIZE: - ctx.mOk = ctx.mOk && - deserialize(ctx.mData,ctx.mSize,ctx.mOffset,member); - break; - case RsGenericSerializer::SERIALIZE: - ctx.mOk = ctx.mOk && - serialize(ctx.mData,ctx.mSize,ctx.mOffset,member); - break; - case RsGenericSerializer::PRINT: - print_data(member_name,member); - break; - case RsGenericSerializer::TO_JSON: - ctx.mOk = ctx.mOk && to_JSON(member_name, member, ctx.mJson); - break; - case RsGenericSerializer::FROM_JSON: - ctx.mOk &= ( ctx.mOk || - !!(ctx.mFlags & RsSerializationFlags::YIELDING) ) - && from_JSON(member_name, member, ctx.mJson); - break; - default: fatalUnknownSerialJob(j); - } - } - -//============================================================================// -// Generic types + type_id // -//============================================================================// - - /// Generic types + type_id - template RS_DEPRECATED - static void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - uint16_t type_id, T& member, const std::string& member_name ) - { - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - ctx.mOffset += serial_size(type_id,member); - break; - case RsGenericSerializer::DESERIALIZE: - ctx.mOk = ctx.mOk && - deserialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member); - break; - case RsGenericSerializer::SERIALIZE: - ctx.mOk = ctx.mOk && - serialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member); - break; - case RsGenericSerializer::PRINT: break; - case RsGenericSerializer::TO_JSON: - ctx.mOk = ctx.mOk && - to_JSON(member_name, type_id, member, ctx.mJson); - break; - case RsGenericSerializer::FROM_JSON: - ctx.mOk &= - (ctx.mOk || !!(ctx.mFlags & RsSerializationFlags::YIELDING)) - && from_JSON(member_name, type_id, member, ctx.mJson); - break; - default: fatalUnknownSerialJob(j); - } - } - -//============================================================================// -// std::map // -//============================================================================// - - /// std::map - template - static void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - std::map& member, - const std::string& memberName ) - { - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: // [[falltrough]] - case RsGenericSerializer::SERIALIZE: - { - uint32_t mapSize = member.size(); - RS_SERIAL_PROCESS(mapSize); - - for( auto it = member.begin(); - ctx.mOk && it != member.end(); ++it ) - { - RS_SERIAL_PROCESS(const_cast(it->first)); - RS_SERIAL_PROCESS(const_cast(it->second)); - } - break; - } - case RsGenericSerializer::DESERIALIZE: - { - uint32_t mapSize = 0; - RS_SERIAL_PROCESS(mapSize); - - for(uint32_t i=0; ctx.mOk && i(memberName.length()), allocator ); - Value arr(kArrayType); - - for (auto& kv : member) - { - // Use same allocator to avoid deep copy - RsGenericSerializer::SerializeContext kCtx( - nullptr, 0, ctx.mFlags, &allocator ); - serial_process(j, kCtx, const_cast(kv.first), "key"); - - RsGenericSerializer::SerializeContext vCtx( - nullptr, 0, ctx.mFlags, &allocator ); - serial_process(j, vCtx, const_cast(kv.second), "value"); - - if(kCtx.mOk && vCtx.mOk) - { - Value el(kObjectType); - el.AddMember("key", kCtx.mJson["key"], allocator); - el.AddMember("value", vCtx.mJson["value"], allocator); - - arr.PushBack(el, allocator); - } - } - - ctx.mJson.AddMember(arrKey, arr, allocator); - - break; - } - case RsGenericSerializer::FROM_JSON: - { - using namespace rapidjson; - - bool ok = ctx.mOk || !!(ctx.mFlags & RsSerializationFlags::YIELDING); - Document& jDoc(ctx.mJson); - Document::AllocatorType& allocator = jDoc.GetAllocator(); - - Value arrKey; - arrKey.SetString( memberName.c_str(), - static_cast(memberName.length()) ); - - ok = ok && jDoc.IsObject(); - ok = ok && jDoc.HasMember(arrKey); - - if(ok && jDoc[arrKey].IsArray()) - { - for (auto&& kvEl : jDoc[arrKey].GetArray()) - { - ok = ok && kvEl.IsObject(); - ok = ok && kvEl.HasMember("key"); - ok = ok && kvEl.HasMember("value"); - if (!ok) break; - - RsGenericSerializer::SerializeContext kCtx( - nullptr, 0, ctx.mFlags, &allocator ); - if(ok) - kCtx.mJson.AddMember("key", kvEl["key"], allocator); - - T key; - ok = ok && (serial_process(j, kCtx, key, "key"), kCtx.mOk); - - RsGenericSerializer::SerializeContext vCtx( - nullptr, 0, ctx.mFlags, &allocator ); - if(ok) - vCtx.mJson.AddMember("value", kvEl["value"], allocator); - - U value; - ok = ok && ( serial_process(j, vCtx, value, "value"), - vCtx.mOk ); - - ctx.mOk &= ok; - if(ok) member.insert(std::pair(key,value)); - else break; - } - } - else ctx.mOk = false; - break; - } - default: fatalUnknownSerialJob(j); - } - } - - -//============================================================================// -// std::pair // -//============================================================================// - - /// std::pair - template - static void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - std::pair& member, const std::string& memberName ) - { - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: // [[fallthrough]] - case RsGenericSerializer::DESERIALIZE: // [[fallthrough]] - case RsGenericSerializer::SERIALIZE: // [[fallthrough]] - case RsGenericSerializer::PRINT: - RS_SERIAL_PROCESS(member.first); - RS_SERIAL_PROCESS(member.second); - break; - case RsGenericSerializer::TO_JSON: - { - RsJson& jDoc(ctx.mJson); - RsJson::AllocatorType& allocator = jDoc.GetAllocator(); - - // Reuse allocator to avoid deep copy later - RsGenericSerializer::SerializeContext lCtx( - nullptr, 0, ctx.mFlags, &allocator ); - - serial_process(j, lCtx, member.first, "first"); - serial_process(j, lCtx, member.second, "second"); - - rapidjson::Value key; - key.SetString( memberName.c_str(), - static_cast(memberName.length()), - allocator); - - /* Because the passed allocator is reused it doesn't go out of scope - * and there is no need of deep copy and we can take advantage of - * the much faster rapidjson move semantic */ - jDoc.AddMember(key, lCtx.mJson, allocator); - - ctx.mOk = ctx.mOk && lCtx.mOk; - break; - } - case RsGenericSerializer::FROM_JSON: - { - RsJson& jDoc(ctx.mJson); - const char* mName = memberName.c_str(); - bool hasMember = jDoc.HasMember(mName); - bool yielding = !!(ctx.mFlags & RsSerializationFlags::YIELDING); - - if(!hasMember) - { - if(!yielding) - { - RsErr() << __PRETTY_FUNCTION__ << " \"" << memberName - << "\" not found in JSON" << std::endl; - print_stacktrace(); - } - ctx.mOk = false; - break; - } - - rapidjson::Value& v = jDoc[mName]; - - RsGenericSerializer::SerializeContext lCtx(nullptr, 0, ctx.mFlags); - lCtx.mJson.SetObject() = v; // Beware of move semantic!! - - serial_process(j, lCtx, member.first, "first"); - serial_process(j, lCtx, member.second, "second"); - ctx.mOk &= lCtx.mOk; - - break; - } - default: fatalUnknownSerialJob(j); - } - } - -//============================================================================// -// Sequence containers // -//============================================================================// - - /** std::list is supported */ template - struct is_sequence_container>: std::true_type {}; - - /** std::set is supported */ template - struct is_sequence_container>: std::true_type {}; - - /** std::vector is supported */ template - struct is_sequence_container>: std::true_type {}; - - - /// STL compatible sequence containers std::list, std::set, std::vector... - template - typename std::enable_if::value>::type - static serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - T& member, const std::string& memberName ) - { - using el_t = typename T::value_type; - - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: // [[falltrough]]; - case RsGenericSerializer::SERIALIZE: - { - uint32_t aSize = member.size(); - RS_SERIAL_PROCESS(aSize); - for(auto it = member.begin(); it != member.end(); ++it) - { - if(!ctx.mOk) break; - RS_SERIAL_PROCESS(*it); - } - break; - } - case RsGenericSerializer::DESERIALIZE: - { - uint32_t elCount = 0; - RS_SERIAL_PROCESS(elCount); - if(!ctx.mOk) break; - - /* This check is not perfect but will catch most pathological cases. - * Avoid multiplying by sizeof(el_t) as it is not a good estimation - * of the actual serialized size, depending on the elements - * structure and on the so it would raises many false positives. - * Arithmetic operations on elCount are also at risk of overflow */ - if(elCount > RsSerialiser::MAX_SERIAL_SIZE) - { - ctx.mOk = false; - RsErr() << __PRETTY_FUNCTION__ << " attempt to deserialize a " - << "sequence with apparently malformed elements count." - << " elCount: " << elCount - << " ctx.mSize: " << ctx.mSize - << " ctx.mOffset: " << ctx.mOffset << " " - << std::errc::argument_out_of_domain - << std::endl; - print_stacktrace(); - break; - } - - for(uint32_t i=0; ctx.mOk && i < elCount; ++i ) - { - el_t elem; - RS_SERIAL_PROCESS(elem); - member.insert(member.end(), elem); - } - break; - } - case RsGenericSerializer::PRINT: break; - case RsGenericSerializer::TO_JSON: - { - using namespace rapidjson; - - Document::AllocatorType& allocator = ctx.mJson.GetAllocator(); - - Value arrKey; arrKey.SetString(memberName.c_str(), allocator); - Value arr(kArrayType); - - for(auto& const_el : member) - { - auto el = const_cast(const_el); - - /* Use same allocator to avoid deep copy */ - RsGenericSerializer::SerializeContext elCtx( - nullptr, 0, ctx.mFlags, &allocator ); - serial_process(j, elCtx, el, memberName); - - elCtx.mOk = elCtx.mOk && elCtx.mJson.HasMember(arrKey); - if(elCtx.mOk) arr.PushBack(elCtx.mJson[arrKey], allocator); - else - { - ctx.mOk = false; - break; - } - } - - ctx.mJson.AddMember(arrKey, arr, allocator); - break; - } - case RsGenericSerializer::FROM_JSON: - { - using namespace rapidjson; - - bool ok = ctx.mOk || !!(ctx.mFlags & RsSerializationFlags::YIELDING); - Document& jDoc(ctx.mJson); - Document::AllocatorType& allocator = jDoc.GetAllocator(); - - Value arrKey; - arrKey.SetString( memberName.c_str(), - static_cast(memberName.length()) ); - - ok = ok && jDoc.IsObject() && jDoc.HasMember(arrKey) - && jDoc[arrKey].IsArray(); - if(!ok) { ctx.mOk = false; break; } - - for (auto&& arrEl : jDoc[arrKey].GetArray()) - { - Value arrKeyT; - arrKeyT.SetString( - memberName.c_str(), - static_cast(memberName.length()) ); - - RsGenericSerializer::SerializeContext elCtx( - nullptr, 0, ctx.mFlags, &allocator ); - elCtx.mJson.AddMember(arrKeyT, arrEl, allocator); - - el_t el; - serial_process(j, elCtx, el, memberName); - ok = ok && elCtx.mOk; - ctx.mOk &= ok; - if(ok) member.insert(member.end(), el); - else break; - } - - break; - } - default: fatalUnknownSerialJob(j); - } - } - -//============================================================================// -// Strings // -//============================================================================// - - /// Strings - template - typename std::enable_if::value>::type - static serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - T& memberC, - const std::string& memberName ) - { - // Avoid problems with const sneaking into template paramether - using m_t = std::remove_const_t; - m_t& member = const_cast(memberC); - - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - { - uint32_t aSize = static_cast(member.size()); - RS_SERIAL_PROCESS(aSize); - ctx.mOffset += aSize; - break; - } - case RsGenericSerializer::SERIALIZE: - { - uint32_t len = static_cast(member.length()); - RS_SERIAL_PROCESS(len); - if(len + ctx.mOffset > ctx.mSize) - { - RsErr() << __PRETTY_FUNCTION__ << std::errc::no_buffer_space - << std::endl; - ctx.mOk = false; - } - memcpy(ctx.mData + ctx.mOffset, member.c_str(), len); - ctx.mOffset += len; - break; - } - case RsGenericSerializer::DESERIALIZE: - { - uint32_t len; - RS_SERIAL_PROCESS(len); - if(!ctx.mOk) break; - - if(len > RsSerialiser::MAX_SERIAL_SIZE) - { - ctx.mOk = false; - RsErr() << __PRETTY_FUNCTION__ << " attempt to deserialize a " - << "string with apparently malformed length." - << " len: " << len - << " ctx.mSize: " << ctx.mSize - << " ctx.mOffset: " << ctx.mOffset << " " - << std::errc::argument_out_of_domain << std::endl; - print_stacktrace(); - break; - } - - if(len + ctx.mOffset > ctx.mSize) - { - ctx.mOk = false; - RsErr() << __PRETTY_FUNCTION__ << " attempt to deserialize a " - << "string with a length bigger available data." - << " len: " << len - << " ctx.mSize: " << ctx.mSize - << " ctx.mOffset: " << ctx.mOffset << " " - << std::errc::no_buffer_space << std::endl; - print_stacktrace(); - break; - } - - member.resize(len); - memcpy(&member[0], ctx.mData + ctx.mOffset, len); - ctx.mOffset += len; - break; - } - case RsGenericSerializer::PRINT: break; - case RsGenericSerializer::TO_JSON: - ctx.mOk = ctx.mOk && to_JSON(memberName, member, ctx.mJson); - break; - case RsGenericSerializer::FROM_JSON: - { - bool ok = ctx.mOk || !!( - ctx.mFlags & RsSerializationFlags::YIELDING ); - ctx.mOk = ok && from_JSON(memberName, member, ctx.mJson) && ctx.mOk; - break; - } - default: fatalUnknownSerialJob(j); - } - } - - /// t_RsFlags32<> types - template - static void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - t_RsFlags32& v, - const std::string& memberName ) - { serial_process(j, ctx, v._bits, memberName); } - - /** - * @brief serial process enum types - * On declaration of your member of enum type you must specify the - * underlying type otherwise the serialization format may differ in an - * uncompatible way depending on the compiler/platform. - */ - template - typename std::enable_if::value>::type - static /*void*/ serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - E& member, - const std::string& memberName ) - { - RS_DBG4( "processing enum: ", typeid(E).name(), " as ", - typeid(typename std::underlying_type::type).name() ); - - serial_process( - j, ctx, - reinterpret_cast::type&>(member), - memberName ); - } - - /// RsSerializable and derivatives - template - typename std::enable_if::value>::type - static serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - T& memberC, const std::string& memberName ) - { - using m_t = std::remove_const_t; - m_t& member = const_cast(memberC); - - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: // fallthrough - case RsGenericSerializer::DESERIALIZE: // fallthrough - case RsGenericSerializer::SERIALIZE: // fallthrough - case RsGenericSerializer::PRINT: - member.serial_process(j, ctx); - break; - case RsGenericSerializer::TO_JSON: - { - rapidjson::Document& jDoc(ctx.mJson); - rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); - - // Reuse allocator to avoid deep copy later - RsGenericSerializer::SerializeContext lCtx( - nullptr, 0, ctx.mFlags, &allocator ); - - member.serial_process(j, lCtx); - - rapidjson::Value key; - key.SetString( - memberName.c_str(), - static_cast(memberName.length()), - allocator ); - - /* Because the passed allocator is reused it doesn't go out of scope - * and there is no need of deep copy and we can take advantage of - * the much faster rapidjson move semantic */ - jDoc.AddMember(key, lCtx.mJson, allocator); - - ctx.mOk = ctx.mOk && lCtx.mOk; - break; - } - case RsGenericSerializer::FROM_JSON: - { - RsJson& jDoc(ctx.mJson); - const char* mName = memberName.c_str(); - bool hasMember = jDoc.HasMember(mName); - bool yielding = !!(ctx.mFlags & RsSerializationFlags::YIELDING); - - if(!hasMember) - { - if(!yielding) - { - RsErr() << __PRETTY_FUNCTION__ << " \"" << memberName - << "\" not found in JSON:" << std::endl - << jDoc << std::endl << std::endl; - print_stacktrace(); - } - ctx.mOk = false; - break; - } - - rapidjson::Value& v = jDoc[mName]; - - if(!v.IsObject()) - { - RsErr() << __PRETTY_FUNCTION__ << " \"" << memberName - << "\" has wrong type in JSON, object expected, got:" - << std::endl << jDoc << std::endl << std::endl; - print_stacktrace(); - ctx.mOk = false; - break; - } - - RsGenericSerializer::SerializeContext lCtx(nullptr, 0, ctx.mFlags); - lCtx.mJson.SetObject() = v; // Beware of move semantic!! - - member.serial_process(j, lCtx); - ctx.mOk &= lCtx.mOk; - - break; - } - default: fatalUnknownSerialJob(j); - } - } - - /// RsTlvItem derivatives only - template - typename std::enable_if< - std::is_base_of::value && - !std::is_same::value >::type - static serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - T& member, const std::string& memberName ) - { serial_process(j, ctx, static_cast(member), memberName); } - - /** std::error_condition - * supports only TO_JSON ErrConditionWrapper::serial_process will explode - * at runtime if a different SerializeJob is passed down */ - template - typename std::enable_if< std::is_base_of::value >::type - static /*void*/ serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - T& cond, const std::string& member_name ) - { - ErrConditionWrapper ew(cond); - serial_process(j, ctx, ew, member_name); - } - - RS_DEPRECATED_FOR(RawMemoryWrapper) - typedef RawMemoryWrapper TlvMemBlock_proxy; - -protected: - -//============================================================================// -// Generic types declarations // -//============================================================================// - - template static bool serialize( - uint8_t data[], uint32_t size, uint32_t &offset, const T& member ); - - template static bool deserialize( - const uint8_t data[], uint32_t size, uint32_t &offset, T& member); - - template static uint32_t serial_size(const T& member); - - template static void print_data( - const std::string& name, const T& member); - - template static bool to_JSON( const std::string& membername, - const T& member, RsJson& jDoc ); - - template static bool from_JSON( const std::string& memberName, - T& member, RsJson& jDoc ); - -//============================================================================// -// Generic types + type_id declarations // -//============================================================================// - - template RS_DEPRECATED - static bool serialize( - uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id, - const T& member ); - - template RS_DEPRECATED - static bool deserialize( - const uint8_t data[], uint32_t size, uint32_t &offset, - uint16_t type_id, T& member ); - - template RS_DEPRECATED - static uint32_t serial_size(uint16_t type_id,const T& member); - - template RS_DEPRECATED - static void print_data( - const std::string& n, uint16_t type_id,const T& member ); - - template RS_DEPRECATED - static bool to_JSON( - const std::string& membername, uint16_t type_id, - const T& member, RsJson& jVal ); - - template RS_DEPRECATED - static bool from_JSON( - const std::string& memberName, uint16_t type_id, - T& member, RsJson& jDoc ); - -//============================================================================// -// t_RsGenericId<...> declarations // -//============================================================================// - - template - static bool serialize( - uint8_t data[], uint32_t size, uint32_t &offset, - const t_RsGenericIdType& member ); - - template - static bool deserialize( - const uint8_t data[], uint32_t size, uint32_t &offset, - t_RsGenericIdType& member ); - - template - static uint32_t serial_size( - const t_RsGenericIdType< - ID_SIZE_IN_BYTES, UPPER_CASE, UNIQUE_IDENTIFIER>& member ); - - template - static void print_data( - const std::string& name, - const t_RsGenericIdType& member ); - - template - static bool to_JSON( - const std::string& membername, - const t_RsGenericIdType& member, - RsJson& jVal ); - - template - static bool from_JSON( - const std::string& memberName, - t_RsGenericIdType& member, - RsJson& jDoc ); - -//============================================================================// -// t_RsTlvList<...> declarations // -//============================================================================// - - template - static bool serialize( - uint8_t data[], uint32_t size, uint32_t &offset, - const t_RsTlvList& member ); - - template - static bool deserialize( - const uint8_t data[], uint32_t size, uint32_t &offset, - t_RsTlvList& member ); - - template - static uint32_t serial_size(const t_RsTlvList& member); - - template - static void print_data( - const std::string& name, - const t_RsTlvList& member); - - template - static bool to_JSON( const std::string& membername, - const t_RsTlvList& member, - RsJson& jVal ); - - template - static bool from_JSON( const std::string& memberName, - t_RsTlvList& member, - RsJson& jDoc ); - -//============================================================================// -// Integral types VLQ // -//============================================================================// - - /** - * Size calculation of unsigned integers as Variable Lenght Quantity - * @see RsSerializationFlags::INTEGER_VLQ - * @see https://en.wikipedia.org/wiki/Variable-length_quantity - * @see https://golb.hplar.ch/2019/06/variable-length-int-java.html - * @see https://techoverflow.net/2013/01/25/efficiently-encoding-variable-length-integers-in-cc/ - */ - template static - std::enable_if_t>::value, uint32_t> - VLQ_size(T member) - { - std::decay_t memberBackup = member; - uint32_t ret = 1; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wbool-compare" - while(member > 127) { ++ret; member >>= 7; } -#pragma GCC diagnostic pop - Dbg2() << __PRETTY_FUNCTION__ << " memberBackup: " << memberBackup - << " return: " << ret << std::endl; - return ret; - } - - /** - * Serialization of unsigned integers as Variable Lenght Quantity - * @see RsSerializationFlags::INTEGER_VLQ - * @see https://en.wikipedia.org/wiki/Variable-length_quantity - * @see https://golb.hplar.ch/2019/06/variable-length-int-java.html - * @see https://techoverflow.net/2013/01/25/efficiently-encoding-variable-length-integers-in-cc/ - */ - template static - std::enable_if_t>::value, bool> - VLQ_serialize( - uint8_t data[], uint32_t size, uint32_t &offset, T member ) - { - std::decay_t backupMember = member; -#if RS_DEBUG_LEVEL >= 3 - uint32_t offsetBackup = offset; -#endif - - bool ok = true; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wbool-compare" - /* Check with < and not with <= here as we write last byte after - * the loop. Order of && operands very important here! */ - while(member > 127 && (ok = (offset < size))) - { - // | 128: Set the next byte flag - data[offset++] = (static_cast(member & 127)) | 128; - // Remove the seven bits we just wrote - member >>= 7; - } -#pragma GCC diagnostic pop - - if(!(ok = ok && offset <= size)) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot serialise " - << typeid(T).name() - << " member " << member - << " size: " << size - << " offset: " << offset - << " backupMember: " << backupMember - << std::error_condition(std::errc::no_buffer_space) - << std::endl; - print_stacktrace(); - return false; - } - - data[offset++] = static_cast(member & 127); - -#if RS_DEBUG_LEVEL >= 3 - RsDbg tdbg( __PRETTY_FUNCTION__, " backupMember: ", backupMember, - " offsetBackup: ", offsetBackup, " offeset: ", offset, - " serialized as: " ); - for(; offsetBackup < offset; ++offsetBackup) - tdbg << " " << std::bitset<8>(data[offsetBackup]); -#endif - return ok; - } - - /** - * Deserialization for unsigned integers as Variable Lenght Quantity - * @see RsSerializationFlags::INTEGER_VLQ - * @see https://en.wikipedia.org/wiki/Variable-length_quantity - * @see https://golb.hplar.ch/2019/06/variable-length-int-java.html - * @see https://techoverflow.net/2013/01/25/efficiently-encoding-variable-length-integers-in-cc/ - */ - template static - std::enable_if_t>::value, bool> - VLQ_deserialize( - const uint8_t data[], uint32_t size, uint32_t& offset, T& member ) - { - member = 0; - uint32_t offsetBackup = offset; - - /* In a reasonable VLQ coding representing an integer - * could take at maximum sizeof(integer) + 1 space, if it is - * not the case something fishy is happening. */ - for (size_t i = 0; offset < size && i <= sizeof(T); ++i) - { - member |= (data[offset] & 127) << (7 * i); - // If the next-byte flag is not set. ++ is after on purpose - if(!(data[offset++] & 128)) - { - Dbg2() << __PRETTY_FUNCTION__ - << " size: " << size - << " backupOffset " << offsetBackup - << " offset: " << offset - << " member " << member << std::endl; - return true; - } - } - - /* If return is not triggered inside the for loop, either the buffer - * ended before we encountered the end of the number, or the number - * is VLQ encoded improperly */ - RsErr rserr; - rserr << __PRETTY_FUNCTION__ << std::errc::illegal_byte_sequence - << " size: " << size - << " offsetBackup: " << offsetBackup - << " offset: " << offset << " bytes: "; - for(; offsetBackup < offset; ++offsetBackup) - rserr << " " << std::bitset<8>(data[offsetBackup]); - print_stacktrace(); - - return false; - } - - /** - * Size calculation of signed integers as Variable Lenght Quantity - * @see RsSerializationFlags::INTEGER_VLQ - * @see https://en.wikipedia.org/wiki/Variable-length_quantity#Zigzag_encoding - * @see https://golb.hplar.ch/2019/06/variable-length-int-java.html - */ - template static - std::enable_if_t>::value, uint32_t> - VLQ_size(T member) - { - member = (member << 1) ^ (member >> (sizeof(T)-1)); // ZigZag encoding - return VLQ_size( - static_cast::type>(member)); - } - - /** - * Serialization of signed integers as Variable Lenght Quantity - * @see RsSerializationFlags::INTEGER_VLQ - * @see https://en.wikipedia.org/wiki/Variable-length_quantity#Zigzag_encoding - * @see https://golb.hplar.ch/2019/06/variable-length-int-java.html - */ - template static - std::enable_if_t>::value, bool> - VLQ_serialize( - uint8_t data[], uint32_t size, uint32_t &offset, T member ) - { - member = (member << 1) ^ (member >> (sizeof(T)-1)); // ZigZag encoding - return VLQ_serialize( - data, size, offset, - static_cast::type>(member)); - } - - /** - * Deserialization for signed integers as Variable Lenght Quantity - * @see RsSerializationFlags::INTEGER_VLQ - * @see https://en.wikipedia.org/wiki/Variable-length_quantity#Zigzag_encoding - * @see https://golb.hplar.ch/2019/06/variable-length-int-java.html - */ - template static - std::enable_if_t>::value, bool> - VLQ_deserialize( - const uint8_t data[], uint32_t size, uint32_t& offset, T& member ) - { - using DT = std::decay_t; - typename std::make_unsigned
::type temp = 0; - bool ok = VLQ_deserialize(data, size, offset, temp); - // ZizZag decoding - member = (static_cast
(temp) >> 1) ^ -(static_cast
(temp) & 1); - return ok; - } - -//============================================================================// -// Error Condition Wrapper // -//============================================================================// - - struct ErrConditionWrapper : RsSerializable - { - explicit ErrConditionWrapper(const std::error_condition& ec): mec(ec) {} - - /** supports only TO_JSON if a different SerializeJob is passed it will - * explode at runtime */ - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - private: - const std::error_condition& mec; - }; - -//============================================================================// -// Miscellanea // -//============================================================================// - - [[noreturn]] static void fatalUnknownSerialJob(int j) - { - RsFatal() << " Unknown serial job: " << j << std::endl; - print_stacktrace(); - exit(EINVAL); - } - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; - - -//============================================================================// -// t_RsGenericId<...> // -//============================================================================// - -template -bool RsTypeSerializer::serialize ( - uint8_t data[], uint32_t size, uint32_t &offset, - const t_RsGenericIdType< - ID_SIZE_IN_BYTES, UPPER_CASE, UNIQUE_IDENTIFIER>& member ) -{ - return (*const_cast *>(&member) - ).serialise(data, size, offset); -} - -template -bool RsTypeSerializer::deserialize( - const uint8_t data[], uint32_t size, uint32_t &offset, - t_RsGenericIdType& member ) -{ return member.deserialise(data, size, offset); } - -template -uint32_t RsTypeSerializer::serial_size( - const t_RsGenericIdType& member ) -{ return member.serial_size(); } - -template -void RsTypeSerializer::print_data( - const std::string& /*name*/, - const t_RsGenericIdType& member ) -{ - std::cerr << " [RsGenericId<" << std::hex - << static_cast(UNIQUE_IDENTIFIER) << ">] : " - << member << std::endl; -} - -template -bool RsTypeSerializer::to_JSON( - const std::string& memberName, - const t_RsGenericIdType& member, - RsJson& jDoc ) -{ - rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); - - rapidjson::Value key; - key.SetString(memberName.c_str(), memberName.length(), allocator); - - const std::string vStr = member.toStdString(); - rapidjson::Value value; - value.SetString(vStr.c_str(), vStr.length(), allocator); - - jDoc.AddMember(key, value, allocator); - - return true; -} - -template -bool RsTypeSerializer::from_JSON( - const std::string& membername, - t_RsGenericIdType& member, - RsJson& jVal ) -{ - const char* mName = membername.c_str(); - bool ret = jVal.HasMember(mName); - if(ret) - { - rapidjson::Value& v = jVal[mName]; - ret = ret && v.IsString(); - if(ret) member = - t_RsGenericIdType( - std::string(v.GetString()) ); - } - return ret; -} - -//============================================================================// -// t_RsTlvList<...> // -//============================================================================// - -template -bool RsTypeSerializer::serialize( - uint8_t data[], uint32_t size, uint32_t &offset, - const t_RsTlvList& member ) -{ - return (*const_cast *>(&member)).SetTlv(data,size,&offset); -} - -template -bool RsTypeSerializer::deserialize( - const uint8_t data[], uint32_t size, uint32_t &offset, - t_RsTlvList& member ) -{ - return member.GetTlv(const_cast(data),size,&offset); -} - -template -uint32_t RsTypeSerializer::serial_size( - const t_RsTlvList& member) -{ return member.TlvSize(); } - -template -void RsTypeSerializer::print_data( - const std::string& /*name*/, - const t_RsTlvList& member) -{ - std::cerr << " [t_RsTlvString<" << std::hex << TLV_TYPE << ">] : size=" - << member.mList.size() << std::endl; -} - -template /* static */ -bool RsTypeSerializer::to_JSON( const std::string& memberName, - const t_RsTlvList& member, - RsJson& jDoc ) -{ - rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); - - rapidjson::Value key; - key.SetString(memberName.c_str(), memberName.length(), allocator); - - rapidjson::Value value; - const char* tName = typeid(member).name(); - value.SetString(tName, allocator); - - jDoc.AddMember(key, value, allocator); - - std::cerr << __PRETTY_FUNCTION__ << " JSON serialization for type " - << typeid(member).name() << " " << memberName - << " not available." << std::endl; - print_stacktrace(); - return true; -} - -template -bool RsTypeSerializer::from_JSON( const std::string& memberName, - t_RsTlvList& member, - RsJson& /*jVal*/ ) -{ - std::cerr << __PRETTY_FUNCTION__ << " JSON deserialization for type " - << typeid(member).name() << " " << memberName - << " not available." << std::endl; - print_stacktrace(); - return true; -} - -//============================================================================// -// Not implemented types macros // -//============================================================================// - -/** - * @def RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(T) - * @def RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(T) - * Helper macros for types that has not yet implemented to/from JSON - * should be deleted from the code as soon as they are not needed anymore - */ -#define RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(T) \ -template<> /*static*/ \ -bool RsTypeSerializer::to_JSON(const std::string& memberName, T const& member, \ - RsJson& jDoc ) \ -{ \ - rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); \ - \ - rapidjson::Value key; \ - key.SetString(memberName.c_str(), memberName.length(), allocator); \ - \ - rapidjson::Value value; \ - const char* tName = typeid(member).name(); \ - value.SetString(tName, allocator); \ - \ - jDoc.AddMember(key, value, allocator); \ - \ - std::cerr << __FILE__ << __LINE__ << __PRETTY_FUNCTION__ \ - << " JSON serialization for type " \ - << typeid(member).name() << " " << memberName \ - << " not available." << std::endl; \ - print_stacktrace(); \ - return true; \ -} - -#define RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(T) \ -template<> /*static*/ \ -bool RsTypeSerializer::from_JSON( const std::string& memberName, \ - T& member, RsJson& /*jDoc*/ ) \ -{ \ - std::cerr << __FILE__ << __LINE__ << __PRETTY_FUNCTION__ \ - << " JSON deserialization for type " \ - << typeid(member).name() << " " << memberName \ - << " not available." << std::endl; \ - print_stacktrace(); \ - return true; \ -} diff --git a/libretroshare/src/services/autoproxy/p3i2pbob.cc b/libretroshare/src/services/autoproxy/p3i2pbob.cc deleted file mode 100644 index f9eb3d9b3..000000000 --- a/libretroshare/src/services/autoproxy/p3i2pbob.cc +++ /dev/null @@ -1,1117 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services/autoproxy: p3i2pbob.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Sehraf * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include /* for usleep() */ - -#include "p3i2pbob.h" - -#include "pqi/p3peermgr.h" -#include "rsitems/rsconfigitems.h" -#include "util/radix32.h" -#include "util/radix64.h" -#include "util/rsdebug.h" -#include "util/rstime.h" -#include "util/rsprint.h" -#include "util/rsrandom.h" - -static const std::string kConfigKeyBOBEnable = "BOB_ENABLE"; -static const std::string kConfigKeyBOBKey = "BOB_KEY"; -static const std::string kConfigKeyBOBAddr = "BOB_ADDR"; -static const std::string kConfigKeyInLength = "IN_LENGTH"; -static const std::string kConfigKeyInQuantity = "IN_QUANTITY"; -static const std::string kConfigKeyInVariance = "IN_VARIANCE"; -static const std::string kConfigKeyOutLength = "OUT_LENGTH"; -static const std::string kConfigKeyOutQuantity = "OUT_QUANTITY"; -static const std::string kConfigKeyOutVariance = "OUT_VARIANCE"; - -/// Sleep duration for receiving loop in error/no-data case -static const useconds_t sleepTimeRecv = 250; // times 1000 = 250ms -/// Sleep duration for everything else -static const useconds_t sleepTimeWait = 50; // times 1000 = 50ms or 0.05s -static const int sleepFactorDefault = 10; // 0.5s -static const int sleepFactorFast = 1; // 0.05s -static const int sleepFactorSlow = 20; // 1s - -static const rstime_t selfCheckPeroid = 30; - -void doSleep(useconds_t timeToSleepMS) { - rstime::rs_usleep((useconds_t) (timeToSleepMS * 1000)); -} - -p3I2pBob::p3I2pBob(p3PeerMgr *peerMgr) - : RsTickingThread(), p3Config(), - mState(csIdel), mTask(ctIdle), - mStateOld(csIdel), mTaskOld(ctIdle), - mBOBState(bsCleared), mPeerMgr(peerMgr), - mConfigLoaded(false), mSocket(0), - mLastProxyCheck(time(NULL)), - mProcessing(NULL), mLock("I2P-BOB") -{ - // set defaults - mSetting.initDefault(); - - mCommands.clear(); -} - -bool p3I2pBob::isEnabled() -{ - RS_STACK_MUTEX(mLock); - return mSetting.enable; -} - -bool p3I2pBob::initialSetup(std::string &addr, uint16_t &/*port*/) -{ - RS_DBG(""); - - // update config - { - RS_STACK_MUTEX(mLock); - if (!mConfigLoaded) { - finalizeSettings_locked(); - mConfigLoaded = true; - } else { - updateSettings_locked(); - } - } - - RS_DBG("config updated"); - - // request keys - // p3I2pBob::stateMachineBOB expects mProcessing to be set therefore - // we create this fake ticket without a callback or data - // ticket gets deleted later by this service - taskTicket *fakeTicket = rsAutoProxyMonitor::getTicket(); - fakeTicket->task = autoProxyTask::receiveKey; - processTaskAsync(fakeTicket); - - RS_DBG("fakeTicket requested"); - - // now start thread - start("I2P-BOB gen key"); - - RS_DBG("thread started"); - - int counter = 0; - // wait for keys - for(;;) { - doSleep(sleepTimeWait * sleepFactorDefault); - - RS_STACK_MUTEX(mLock); - - // wait for tast change - if (mTask != ctRunGetKeys) - break; - - if (++counter > 30) { - RS_DBG4("timeout!"); - return false; - } - } - - RS_DBG("got keys"); - - // stop thread - fullstop(); - - RS_DBG("thread stopped"); - - { - RS_STACK_MUTEX(mLock); - addr = mSetting.address.base32; - } - - RS_DBG4("addr ", addr); - - return true; -} - -void p3I2pBob::processTaskAsync(taskTicket *ticket) -{ - switch (ticket->task) { - case autoProxyTask::start: - case autoProxyTask::stop: - case autoProxyTask::receiveKey: - case autoProxyTask::proxyStatusCheck: - { - RS_STACK_MUTEX(mLock); - mPending.push(ticket); - } - break; - default: - RS_DBG("unknown task"); - rsAutoProxyMonitor::taskError(ticket); - break; - } -} - -void p3I2pBob::processTaskSync(taskTicket *ticket) -{ - bool data = !!ticket->data; - - // check wether we can process the task immediately or have to queue it - switch (ticket->task) { - case autoProxyTask::status: - // check if everything needed is set - if (!data) { - RS_DBG("autoProxyTask::status data is missing"); - rsAutoProxyMonitor::taskError(ticket); - break; - } - - // get states - getStates((struct bobStates*)ticket->data); - - // finish task - rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); - break; - case autoProxyTask::getSettings: - // check if everything needed is set - if (!data) { - RS_DBG("autoProxyTask::getSettings data is missing"); - rsAutoProxyMonitor::taskError(ticket); - break; - } - - // get settings - getBOBSettings((struct bobSettings *)ticket->data); - - // finish task - rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); - break; - case autoProxyTask::setSettings: - // check if everything needed is set - if (!data) { - RS_DBG("autoProxyTask::setSettings data is missing"); - rsAutoProxyMonitor::taskError(ticket); - break; - } - - // set settings - setBOBSettings((struct bobSettings *)ticket->data); - - // finish task - rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); - break; - case autoProxyTask::reloadConfig: - { - RS_STACK_MUTEX(mLock); - updateSettings_locked(); - } - rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); - break; - case autoProxyTask::getErrorInfo: - if (!data) { - RS_DBG("autoProxyTask::getErrorInfo data is missing"); - rsAutoProxyMonitor::taskError(ticket); - } else { - RS_STACK_MUTEX(mLock); - *(std::string *)ticket->data = mErrorMsg; - rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); - } - break; - default: - RS_DBG("unknown task"); - rsAutoProxyMonitor::taskError(ticket); - break; - } -} - -bool inline isAnswerOk(const std::string &answer) { - return (answer.compare(0, 2, "OK") == 0); -} - -bool inline isTunnelActiveError(const std::string &answer) { - return answer.compare(0, 22, "ERROR tunnel is active") == 0; -} - -void p3I2pBob::threadTick() -{ - int sleepTime = 0; - { - RS_STACK_MUTEX(mLock); - RS_DBG4("data_tick mState: ", mState, " mTask: ", mTask, " mBOBState: ", mBOBState, " mPending: ", mPending.size()); - } - - sleepTime += stateMachineController(); - sleepTime += stateMachineBOB(); - - sleepTime >>= 1; - - // sleep outisde of lock! - doSleep(sleepTime * sleepTimeWait); -} - -int p3I2pBob::stateMachineBOB() -{ - std::string answer; - bobStateInfo currentState; - - { - RS_STACK_MUTEX(mLock); - if (mBOBState == bsCleared || !mConfigLoaded) { - // we don't have work to do - sleep longer - return sleepFactorSlow; - } - - // get next command - currentState = mCommands[mBOBState]; - } - - // this call can take a while - // do NOT hold the lock - answer = executeCommand(currentState.command); - - // can hold the lock for the rest of the function - RS_STACK_MUTEX(mLock); - - // special state first - if (mBOBState == bsList) { - int counter = 0; - while (answer.find("OK Listing done") == std::string::npos) { - RS_DBG3("stateMachineBOB status check: read loop, counter: ", counter); - answer += recv(); - counter++; - } - - if (answer.find(mTunnelName) == std::string::npos) { - RS_DBG("status check: tunnel down!"); - // signal error - *((bool *)mProcessing->data) = true; - } - - mBOBState = currentState.nextState; - } else if (isAnswerOk(answer)) { - // check for other special states - std::string key; - switch (mBOBState) { - case bsNewkeysN: - key = answer.substr(3, answer.length()-3); - mSetting.address.base32 = i2p::keyToBase32Addr(key); - IndicateConfigChanged(); - break; - case bsGetkeys: - key = answer.substr(3, answer.length()-3); - mSetting.address.privateKey = key; - IndicateConfigChanged(); - break; - default: - break; - } - - // goto next command - mBOBState = currentState.nextState; - } else { - return stateMachineBOB_locked_failure(answer, currentState); - } - return sleepFactorFast; -} - -int p3I2pBob::stateMachineBOB_locked_failure(const std::string &answer, const bobStateInfo ¤tState) -{ - // wait in case of active tunnel - // happens when trying to clear a stopping tunnel - if (isTunnelActiveError(answer)) { - return sleepFactorDefault; - } - - RS_DBG("FAILED to run command: ", currentState.command); - RS_DBG("answer: ", answer); - - mErrorMsg.append("FAILED to run command '" + currentState.command + "'" + '\n'); - mErrorMsg.append("reason '" + answer + "'" + '\n'); - - // this error handling needs testing! - mStateOld = mState; - mState = csError; - switch (mBOBState) { - case bsGetnick: - // failed getting nick - // tunnel is probably non existing - case bsClear: - // tunnel is cleared - mBOBState = bsQuit; - break; - case bsStop: - // failed stopping - // tunnel us probably not running - // continue to clearing - mBOBState = bsClear; - break; - case bsQuit: - // this can happen when the - // connection is somehow broken - // just try to disconnect - disconnectI2P(); - mBOBState = bsCleared; - break; - default: - // try to recover - mBOBState = bsGetnick; - break; - } - - return sleepFactorFast; -} - -int p3I2pBob::stateMachineController() -{ - RS_STACK_MUTEX(mLock); - - switch (mState) { - case csIdel: - return stateMachineController_locked_idle(); - case csDoConnect: - if (!connectI2P()) { - RS_DBG("doConnect: unable to connect"); - mStateOld = mState; - mState = csError; - mErrorMsg = "unable to connect to BOB port"; - return sleepFactorSlow; - } - - RS_DBG4("doConnect: connected"); - mState = csConnected; - break; - case csConnected: - return stateMachineController_locked_connected(); - case csWaitForBob: - // check connection problems - if (mSocket == 0) { - RS_DBG("waitForBob: conection lost"); - mStateOld = mState; - mState = csError; - mErrorMsg = "connection lost to BOB"; - return sleepFactorDefault; - } - - // check for finished BOB protocol - if (mBOBState == bsCleared) { - // done - RS_DBG4("waitForBob: mBOBState == bsCleared"); - mState = csDoDisconnect; - } - break; - case csDoDisconnect: - if (!disconnectI2P() || mSocket != 0) { - // just in case - RS_DBG("doDisconnect: can't disconnect"); - mStateOld = mState; - mState = csError; - mErrorMsg = "unable to disconnect from BOB"; - return sleepFactorDefault; - } - - RS_DBG4("doDisconnect: disconnected"); - mState = csDisconnected; - break; - case csDisconnected: - return stateMachineController_locked_disconnected(); - case csError: - return stateMachineController_locked_error(); - } - - return sleepFactorFast; -} - -int p3I2pBob::stateMachineController_locked_idle() -{ - // do some sanity checks - // use asserts becasue these things indicate wrong/broken state machines that need to be fixed ASAP! - assert(mBOBState == bsCleared); - assert(mSocket == 0); - assert(mState == csIdel || mState == csDisconnected); - - controllerTask oldTask = mTask; - // check for new task - if (mProcessing == NULL && !mPending.empty()) { - mProcessing = mPending.front(); - mPending.pop(); - - if (!mSetting.enable && ( - mProcessing->task == autoProxyTask::start || - mProcessing->task == autoProxyTask::stop || - mProcessing->task == autoProxyTask::proxyStatusCheck)) { - // skip since we are not enabled - RS_DBG1("disabled -> skipping ticket"); - rsAutoProxyMonitor::taskDone(mProcessing, autoProxyStatus::disabled); - mProcessing = NULL; - } else { - // set states - switch (mProcessing->task) { - case autoProxyTask::start: - mLastProxyCheck = time(NULL); - mTask = ctRunSetUp; - break; - case autoProxyTask::stop: - mTask = ctRunShutDown; - break; - case autoProxyTask::receiveKey: - mTaskOld = mTask; - mTask = ctRunGetKeys; - break; - case autoProxyTask::proxyStatusCheck: - mTaskOld = mTask; - mTask = ctRunCheck; - break; - default: - RS_DBG1("unknown async task"); - rsAutoProxyMonitor::taskError(mProcessing); - mProcessing = NULL; - break; - } - } - - mErrorMsg.clear(); - } - - // periodically check - if (mTask == ctRunSetUp && mLastProxyCheck < time(NULL) - selfCheckPeroid) { - taskTicket *tt = rsAutoProxyMonitor::getTicket(); - tt->task = autoProxyTask::proxyStatusCheck; - tt->data = (void *) new bool; - - *((bool *)tt->data) = false; - - mPending.push(tt); - - mLastProxyCheck = time(NULL); - } - - // wait for new task - if (!!mProcessing) { - // check if task was changed - if (mTask != oldTask) { - mState = csDoConnect; - } else { - // A ticket shall be processed but the state didn't change. - // This means that what ever is requested in the ticket - // was requested before already. - // -> set mState to csDisconnected to answer the ticket - mState = csDisconnected; - } - return sleepFactorFast; - } - - return sleepFactorSlow; -} - -int p3I2pBob::stateMachineController_locked_connected() -{ - // set proper bob state - switch (mTask) { - case ctRunSetUp: - // when we have a key use it for server tunnel! - if(mSetting.address.privateKey.empty()) { - RS_DBG4("setting mBOBState = setnickC"); - mBOBState = bsSetnickC; - } else { - RS_DBG4("setting mBOBState = setnickS"); - mBOBState = bsSetnickS; - } - break; - case ctRunShutDown: - // shut down existing tunnel - RS_DBG4("setting mBOBState = getnick"); - mBOBState = bsGetnick; - break; - case ctRunCheck: - RS_DBG4("setting mBOBState = list"); - mBOBState = bsList; - break; - case ctRunGetKeys: - RS_DBG4("setting mBOBState = setnickN"); - mBOBState = bsSetnickN; - break; - case ctIdle: - RS_DBG("task is idle. This should not happen!"); - break; - } - - mState = csWaitForBob; - return sleepFactorFast; -} - -int p3I2pBob::stateMachineController_locked_disconnected() -{ - // check if we had an error - bool errorHappened = (mStateOld == csError); - - if(errorHappened) { - // reset old state - mStateOld = csIdel; - RS_DBG("error during process!"); - } - - // answer ticket - controllerState newState = csIdel; - switch (mTask) { - case ctRunSetUp: - if (errorHappened) { - rsAutoProxyMonitor::taskError(mProcessing); - // switch to error - newState = csError; - } else { - rsAutoProxyMonitor::taskDone(mProcessing, autoProxyStatus::online); - } - break; - case ctRunShutDown: - // don't care about error here - rsAutoProxyMonitor::taskDone(mProcessing, autoProxyStatus::offline); - break; - case ctRunCheck: - // get result and delete dummy ticket - errorHappened |= *((bool *)mProcessing->data); - delete (bool *)mProcessing->data; - delete mProcessing; - - // restore old task - mTask = mTaskOld; - - if (!errorHappened) { - RS_DBG4("run check result: ok"); - break; - } - // switch to error - newState = csError; - RS_DBG("run check result: error"); - mErrorMsg = "Connection check failed. Will try to restart tunnel."; - - break; - case ctRunGetKeys: - if (!errorHappened) { - // rebuild commands - updateSettings_locked(); - - if (mProcessing->data) - *((struct bobSettings *)mProcessing->data) = mSetting; - - rsAutoProxyMonitor::taskDone(mProcessing, autoProxyStatus::ok); - } else { - rsAutoProxyMonitor::taskError(mProcessing); - // switch to error - newState = csError; - } - - // restore old task - mTask = mTaskOld; - break; - case ctIdle: - RS_DBG("task is idle. This should not happen!"); - rsAutoProxyMonitor::taskError(mProcessing); - } - mProcessing = NULL; - mState = newState; - - if (newState == csError) - mLastProxyCheck = time(NULL); - - return sleepFactorFast; -} - -int p3I2pBob::stateMachineController_locked_error() -{ - // wait for bob protocoll - if (mBOBState != bsCleared) { - RS_DBG4("waiting for BOB"); - return sleepFactorFast; - } - -#if 0 - RS_DBG4("stateMachineController_locked_error: mProcessing: ", (mProcessing ? "not null" : "null")); -#endif - - // try to finish ticket - if (mProcessing) { - switch (mTask) { - case ctRunCheck: - // connection check failed at some point - RS_DBG("failed to check proxy status (it's likely dead)!"); - *((bool *)mProcessing->data) = true; - mState = csDoDisconnect; - mStateOld = csIdel; - // keep the error message - break; - case ctRunShutDown: - // not a big deal though - RS_DBG("failed to shut down tunnel (it's likely dead though)!"); - mState = csDoDisconnect; - mStateOld = csIdel; - mErrorMsg.clear(); - break; - case ctIdle: - // should not happen but we need to deal with it - // this will produce some error messages in the log and finish the task (marked as failed) - RS_DBG("task is idle. This should not happen!"); - mState = csDoDisconnect; - mStateOld = csIdel; - mErrorMsg.clear(); - break; - case ctRunGetKeys: - case ctRunSetUp: - RS_DBG("failed to receive key / start up"); - mStateOld = csError; - mState = csDoDisconnect; - // keep the error message - break; - } - return sleepFactorFast; - } - - // periodically retry - if (mLastProxyCheck < time(NULL) - (selfCheckPeroid >> 1) && mTask == ctRunSetUp) { - RS_DBG("retrying"); - - mLastProxyCheck = time(NULL); - mErrorMsg.clear(); - - // create fake ticket - taskTicket *tt = rsAutoProxyMonitor::getTicket(); - tt->task = autoProxyTask::start; - mPending.push(tt); - } - - // check for new tickets - if (!mPending.empty()) { - RS_DBG4("processing new ticket"); - - // reset and try new task - mTask = ctIdle; - mState = csIdel; - return sleepFactorFast; - } - - return sleepFactorDefault; -} - -RsSerialiser *p3I2pBob::setupSerialiser() -{ - RsSerialiser* rsSerialiser = new RsSerialiser(); - rsSerialiser->addSerialType(new RsGeneralConfigSerialiser()); - - return rsSerialiser; -} - -#define addKVS(_vitem, _kv, _key, _value) \ - _kv.key = _key;\ - _kv.value = _value;\ - _vitem->tlvkvs.pairs.push_back(_kv); - -#define addKVSInt(_vitem, _kv, _key, _value) \ - _kv.key = _key;\ - rs_sprintf(_kv.value, "%d", _value);\ - _vitem->tlvkvs.pairs.push_back(_kv); - -bool p3I2pBob::saveList(bool &cleanup, std::list &lst) -{ - RS_DBG4(""); - - cleanup = true; - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet; - RsTlvKeyValue kv; - - RS_STACK_MUTEX(mLock); - addKVS(vitem, kv, kConfigKeyBOBEnable, mSetting.enable ? "TRUE" : "FALSE") - addKVS(vitem, kv, kConfigKeyBOBKey, mSetting.address.privateKey) - addKVS(vitem, kv, kConfigKeyBOBAddr, mSetting.address.base32) - addKVSInt(vitem, kv, kConfigKeyInLength, mSetting.inLength) - addKVSInt(vitem, kv, kConfigKeyInQuantity, mSetting.inQuantity) - addKVSInt(vitem, kv, kConfigKeyInVariance, mSetting.inVariance) - addKVSInt(vitem, kv, kConfigKeyOutLength, mSetting.outLength) - addKVSInt(vitem, kv, kConfigKeyOutQuantity, mSetting.outQuantity) - addKVSInt(vitem, kv, kConfigKeyOutVariance, mSetting.outVariance) - - lst.push_back(vitem); - - return true; -} - -#undef addKVS -#undef addKVSUInt - -#define getKVSUInt(_kit, _key, _value) \ - else if (_kit->key == _key) {\ - std::istringstream is(_kit->value);\ - int tmp;\ - is >> tmp;\ - _value = (int8_t)tmp;\ - } - -bool p3I2pBob::loadList(std::list &load) -{ - RS_DBG4(""); - - for(std::list::const_iterator it = load.begin(); it!=load.end(); ++it) { - RsConfigKeyValueSet *vitem = dynamic_cast(*it); - if(vitem != NULL) { - RS_STACK_MUTEX(mLock); - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) { - if (kit->key == kConfigKeyBOBEnable) - mSetting.enable = kit->value == "TRUE"; - else if (kit->key == kConfigKeyBOBKey) - mSetting.address.privateKey = kit->value; - else if (kit->key == kConfigKeyBOBAddr) - mSetting.address.base32 = kit->value; - getKVSUInt(kit, kConfigKeyInLength, mSetting.inLength) - getKVSUInt(kit, kConfigKeyInQuantity, mSetting.inQuantity) - getKVSUInt(kit, kConfigKeyInVariance, mSetting.inVariance) - getKVSUInt(kit, kConfigKeyOutLength, mSetting.outLength) - getKVSUInt(kit, kConfigKeyOutQuantity, mSetting.outQuantity) - getKVSUInt(kit, kConfigKeyOutVariance, mSetting.outVariance) - else - RS_DBG("unknown key: ", kit->key); - } - } - delete vitem; - } - - RS_STACK_MUTEX(mLock); - finalizeSettings_locked(); - mConfigLoaded = true; - - return true; -} - -#undef getKVSUInt - -void p3I2pBob::getBOBSettings(bobSettings *settings) -{ - if (settings == NULL) - return; - - RS_STACK_MUTEX(mLock); - *settings = mSetting; - -} - -void p3I2pBob::setBOBSettings(const bobSettings *settings) -{ - if (settings == NULL) - return; - - RS_STACK_MUTEX(mLock); - mSetting = *settings; - - IndicateConfigChanged(); - - // Note: - // We don't take care of updating a running BOB session here - // This can be done manually by stoping and restarting the session - - // Note2: - // In case there is no config yet to load - // finalize settings here instead - if (!mConfigLoaded) { - finalizeSettings_locked(); - mConfigLoaded = true; - } else { - updateSettings_locked(); - } -} - -void p3I2pBob::getStates(bobStates *bs) -{ - if (bs == NULL) - return; - - RS_STACK_MUTEX(mLock); - bs->cs = mState; - bs->ct = mTask; - bs->bs = mBOBState; - bs->tunnelName = mTunnelName; -} - -std::string p3I2pBob::executeCommand(const std::string &command) -{ - RS_DBG4("running: ", command); - - std::string copy = command; - copy.push_back('\n'); - - // send command - // there is only one thread that touches mSocket - no need for a lock - ::send(mSocket, copy.c_str(), copy.size(), 0); - - // receive answer (trailing new line is already removed!) - std::string ans = recv(); - - RS_DBG4("answer: ", ans); - - return ans; -} - -bool p3I2pBob::connectI2P() -{ - // there is only one thread that touches mSocket - no need for a lock - - if (mSocket != 0) { - RS_DBG("mSocket != 0"); - return false; - } - - // create socket - mSocket = unix_socket(PF_INET, SOCK_STREAM, 0); - if (mSocket < 0) - { - RS_DBG("Failed to open socket! Socket Error: ", socket_errorType(errno)); - return false; - } - - // connect - int err = unix_connect(mSocket, mI2PProxyAddr); - if (err != 0) { - RS_DBG("Failed to connect to BOB! Socket Error: ", socket_errorType(errno)); - return false; - } - - // receive hello msg - recv(); - - RS_DBG4("done"); - return true; -} - -bool p3I2pBob::disconnectI2P() -{ - // there is only one thread that touches mSocket - no need for a lock - - if (mSocket == 0) { - RS_DBG("mSocket == 0"); - return true; - } - - int err = unix_close(mSocket); - if (err != 0) { - RS_DBG("Failed to close socket! Socket Error: ", socket_errorType(errno)); - return false; - } - - RS_DBG4("done"); - mSocket = 0; - return true; -} - -std::string toString(const std::string &a, const int b) { - std::ostringstream oss; - oss << b; - return a + oss.str();; -} - -std::string toString(const std::string &a, const uint16_t b) { - return toString(a, (int)b); -} - -std::string toString(const std::string &a, const int8_t b) { - return toString(a, (int)b); -} - -void p3I2pBob::finalizeSettings_locked() -{ - RS_DBG4(""); - - sockaddr_storage_clear(mI2PProxyAddr); - // get i2p proxy addr - sockaddr_storage proxy; - mPeerMgr->getProxyServerAddress(RS_HIDDEN_TYPE_I2P, proxy); - - // overwrite port to bob port - sockaddr_storage_setipv4(mI2PProxyAddr, (sockaddr_in*)&proxy); - sockaddr_storage_setport(mI2PProxyAddr, 2827); - - RS_DBG4("using ", mI2PProxyAddr); - RS_DBG4("using ", mSetting.address.base32); - - peerState ps; - mPeerMgr->getOwnNetStatus(ps); - - // setup commands - // new lines are appended later! - - // generate 8 characater long random suffix for name - constexpr size_t len = 8; - const std::string location = RsRandom::alphaNumeric(len); - RS_DBG4("using suffix ", location); - mTunnelName = "RetroShare-" + location; - - const std::string setnick = "setnick RetroShare-" + location; - const std::string getnick = "getnick RetroShare-" + location; - const std::string newkeys = "newkeys"; - const std::string getkeys = "getkeys"; - const std::string setkeys = "setkeys " + mSetting.address.privateKey; - const std::string inhost = "inhost " + sockaddr_storage_iptostring(proxy); - const std::string inport = toString("inport ", sockaddr_storage_port(proxy)); - const std::string outhost = "outhost " + sockaddr_storage_iptostring(ps.localaddr); - const std::string outport = toString("outport ", sockaddr_storage_port(ps.localaddr)); - // length - const std::string inlength = toString("option inbound.length=", mSetting.inLength); - const std::string outlength = toString("option outbound.length=", mSetting.outLength); - // variance - const std::string invariance = toString("option inbound.lengthVariance=", mSetting.inVariance); - const std::string outvariance= toString("option outbound.lengthVariance=", mSetting.outVariance); - // quantity - const std::string inquantity = toString("option inbound.quantity=", mSetting.inQuantity); - const std::string outquantity= toString("option outbound.quantity=", mSetting.outQuantity); - const std::string quiet = "quiet true"; - const std::string start = "start"; - const std::string stop = "stop"; - const std::string clear = "clear"; - const std::string list = "list"; - const std::string quit = "quit"; - - // setup state machine - - // start chain - // -> A: server and client tunnel - mCommands[bsSetnickS] = {setnick, bsSetkeys}; - mCommands[bsSetkeys] = {setkeys, bsOuthost}; - mCommands[bsOuthost] = {outhost, bsOutport}; - mCommands[bsOutport] = {outport, bsInhost}; - // -> B: only client tunnel - mCommands[bsSetnickC] = {setnick, bsNewkeysC}; - mCommands[bsNewkeysC] = {newkeys, bsInhost}; - // -> both - mCommands[bsInhost] = {inhost, bsInport}; - mCommands[bsInport] = {inport, bsInlength}; - mCommands[bsInlength] = {inlength, bsOutlength}; - mCommands[bsOutlength] = {outlength, bsInvariance}; - mCommands[bsInvariance] = {invariance, bsOutvariance}; - mCommands[bsOutvariance]= {outvariance,bsInquantity}; - mCommands[bsInquantity] = {inquantity, bsOutquantity}; - mCommands[bsOutquantity]= {outquantity,bsQuiet}; - mCommands[bsQuiet] = {quiet, bsStart}; - mCommands[bsStart] = {start, bsQuit}; - mCommands[bsQuit] = {quit, bsCleared}; - - // stop chain - mCommands[bsGetnick] = {getnick, bsStop}; - mCommands[bsStop] = {stop, bsClear}; - mCommands[bsClear] = {clear, bsQuit}; - - // getkeys chain - mCommands[bsSetnickN] = {setnick, bsNewkeysN}; - mCommands[bsNewkeysN] = {newkeys, bsGetkeys}; - mCommands[bsGetkeys] = {getkeys, bsClear}; - - // list chain - mCommands[bsList] = {list, bsQuit}; -} - -void p3I2pBob::updateSettings_locked() -{ - RS_DBG4(""); - - sockaddr_storage proxy; - mPeerMgr->getProxyServerAddress(RS_HIDDEN_TYPE_I2P, proxy); - - peerState ps; - mPeerMgr->getOwnNetStatus(ps); - - const std::string setkeys = "setkeys " + mSetting.address.privateKey; - const std::string inhost = "inhost " + sockaddr_storage_iptostring(proxy); - const std::string inport = toString("inport ", sockaddr_storage_port(proxy)); - const std::string outhost = "outhost " + sockaddr_storage_iptostring(ps.localaddr); - const std::string outport = toString("outport ", sockaddr_storage_port(ps.localaddr)); - - // length - const std::string inlength = toString("option inbound.length=", mSetting.inLength); - const std::string outlength = toString("option outbound.length=", mSetting.outLength); - // variance - const std::string invariance = toString("option inbound.lengthVariance=", mSetting.inVariance); - const std::string outvariance= toString("option outbound.lengthVariance=", mSetting.outVariance); - // quantity - const std::string inquantity = toString("option inbound.quantity=", mSetting.inQuantity); - const std::string outquantity= toString("option outbound.quantity=", mSetting.outQuantity); - - mCommands[bsSetkeys] = {setkeys, bsOuthost}; - mCommands[bsOuthost] = {outhost, bsOutport}; - mCommands[bsOutport] = {outport, bsInhost}; - mCommands[bsInhost] = {inhost, bsInport}; - mCommands[bsInport] = {inport, bsInlength}; - - mCommands[bsInlength] = {inlength, bsOutlength}; - mCommands[bsOutlength] = {outlength, bsInvariance}; - mCommands[bsInvariance] = {invariance, bsOutvariance}; - mCommands[bsOutvariance]= {outvariance,bsInquantity}; - mCommands[bsInquantity] = {inquantity, bsOutquantity}; - mCommands[bsOutquantity]= {outquantity,bsQuiet}; -} - -std::string p3I2pBob::recv() -{ - // BOB works line based - // -> \n indicates and of the line - - constexpr uint16_t bufferSize = 128; - char buffer[bufferSize]; - - std::string ans; - uint16_t retry = 10; - - do { - memset(buffer, 0, bufferSize); - - // peek at data - auto length = ::recv(mSocket, buffer, bufferSize, MSG_PEEK); - if (length <= 0) { - if (length < 0) { - // error - perror(__PRETTY_FUNCTION__); - } - retry--; - doSleep(sleepTimeRecv); - continue; - } - - // at least one byte was read - - // search for new line - auto bufferStr = std::string(buffer); - size_t pos = bufferStr.find('\n'); - - if (pos == std::string::npos) { - // no new line found -> more to read - - // sanity check - if (length != bufferSize) { - // expectation: a full buffer was peeked) - RS_DBG1("peeked less than bufferSize but also didn't found a new line character"); - } - // this should never happen - assert(length <= bufferSize); - } else { - // new line found -> end of message - - // calculate how much there is to read, read the \n, too! - length = pos + 1; - - // end loop - retry = 0; - } - - // now read for real - memset(buffer, 0, bufferSize); - length = ::recv(mSocket, buffer, length, 0); - bufferStr = std::string(buffer); - ans.append(bufferStr); - } while(retry > 0); - - return ans; -} diff --git a/libretroshare/src/services/autoproxy/p3i2pbob.h b/libretroshare/src/services/autoproxy/p3i2pbob.h deleted file mode 100644 index 29bcbcb61..000000000 --- a/libretroshare/src/services/autoproxy/p3i2pbob.h +++ /dev/null @@ -1,256 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services/autoproxy: p3i2pbob.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Sehraf * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef P3I2PBOB_H -#define P3I2PBOB_H - -#include -#include -#include -#include "util/rstime.h" -#ifndef WINDOWS_SYS - #include -#endif - -#include "pqi/p3cfgmgr.h" -#include "services/autoproxy/rsautoproxymonitor.h" -#include "util/rsthreads.h" -#include "util/i2pcommon.h" - -/* - * This class implements I2P BOB (BASIC OPEN BRIDGE) communication to allow RS - * to automatically remote control I2P to setup the needed tunnel. - * BOB is a simple text-based interface: https://geti2p.net/en/docs/api/bob - * - * Note 1: - * One tunnel is enough even for hidden locations since it can be used - * bidirectional. (In contrast to what RS I2P users had to set up manually.) - * - * Note 2: - * BOB tunnels are no SOCKS tunnel. Therefore pqissli2pbob implements a simplified - * proxy specially for BOB tunnels. - * - * Note 3: - * BOB needs a unique name as an ID for each tunnel. - * We use 'RetroShare-' + 8 random base32 characters. - * - * Design: - * The service uses three state machines to manage its task: - * int stateMachineBOB(); - * mBOBState - * int stateMachineController(); - * mState - * mTask - * - * stateMachineBOB: - * This state machine manages the low level communication with BOB. It basically has a linked - * list (currently a implemented as a std::map) that contains a command and the next - * state. - * Each high level operation (start up / shut down / get keys) is represented by a - * chain of states. E.g. the chain to retrieve new keys: - * mCommands[bobState::setnickN] = {setnick, bobState::newkeysN}; - * mCommands[bobState::newkeysN] = {newkeys, bobState::getkeys}; - * mCommands[bobState::getkeys] = {getkeys, bobState::clear}; - * mCommands[bobState::clear] = {clear, bobState::quit}; - * mCommands[bobState::quit] = {quit, bobState::cleared}; - * - * stateMachineController: - * This state machine manages the high level tasks. - * It is controlled by mState and mTask. - * - * mTast: - * Tracks the high level operation (like start up). - * It will keep its value even when a task is done to track - * the requested BOB state. - * When other operations are performed like a conection check - * the last task gets backed up and is later restored again - * - * mState: - * This state lives only for one operation an manages the communication - * with the BOB instance. This is basically connecting, starting BOB - * protocol and disconnecting - * - * How a task looks like: - * 1) RS sets task using the ticket system - * 2) stateMachineController connects to BOBs control port, sets mBobState to a lists head - * 3) stateMachineBOB processes command chain - * 4) stateMachineBOB is done and sets mBobState to cleared signaling that the connection - * is cleared and can be closed - * 5) stateMachineController disconnects from BOBs control port and updates mState - */ - -/// -/// \brief The controllerState enum -/// States for the controller to keep track of what he is currently doing -enum controllerState { - csIdel, - csDoConnect, - csConnected, - csWaitForBob, - csDoDisconnect, - csDisconnected, - csError -}; - -/// -/// \brief The controllerTask enum -/// This state tracks the controllers tast (e.g. setup a BOB tunnel or shut down -/// an existing one). -enum controllerTask { - ctIdle, - ctRunSetUp, - ctRunShutDown, - ctRunGetKeys, - ctRunCheck -}; - -/// -/// \brief The bobState enum -/// One state for each message -/// -enum bobState { - bsCleared, - bsSetnickC, // chain head for only client tunnel - bsSetnickN, // chain head for getting new (server) keys - bsSetnickS, // chain head for client and server tunnel - bsGetnick, - bsNewkeysC, // part of chain for only client tunnel - bsNewkeysN, // part of chain for getting new (server) keys - bsGetkeys, - bsSetkeys, - bsInhost, - bsOuthost, - bsInport, - bsOutport, - bsInlength, - bsOutlength, - bsInvariance, - bsOutvariance, - bsInquantity, - bsOutquantity, - bsQuiet, - bsStart, - bsStop, - bsClear, - bsList, // chain head for 'list' command - bsQuit -}; - -/// -/// \brief The bobStateInfo struct -/// State machine with commands -/// \todo This could be replaced by a linked list instead of a map -struct bobStateInfo { - std::string command; - bobState nextState; -}; - -struct bobSettings : i2p::settings {}; - -/// -/// \brief The bobStates struct -/// This container struct is used to pass all states. -/// Additionally, the tunnel name is included to to show it in the GUI. -/// The advantage of a struct is that it can be forward declared. -struct bobStates { - bobState bs; - controllerState cs; - controllerTask ct; - - std::string tunnelName; -}; - -class p3PeerMgr; - -class p3I2pBob : public RsTickingThread, public p3Config, public autoProxyService -{ -public: - explicit p3I2pBob(p3PeerMgr *peerMgr); - - // autoProxyService interface -public: - bool isEnabled(); - bool initialSetup(std::string &addr, uint16_t &); - void processTaskAsync(taskTicket *ticket); - void processTaskSync(taskTicket *ticket); - - void threadTick() override; /// @see RsTickingThread - -private: - int stateMachineBOB(); - int stateMachineBOB_locked_failure(const std::string &answer, const bobStateInfo ¤tState); - - int stateMachineController(); - int stateMachineController_locked_idle(); - int stateMachineController_locked_connected(); - int stateMachineController_locked_disconnected(); - int stateMachineController_locked_error(); - - // p3Config interface -protected: - RsSerialiser *setupSerialiser(); - bool saveList(bool &cleanup, std::list &lst); - bool loadList(std::list &load); - -private: - // helpers - void getBOBSettings(bobSettings *settings); - void setBOBSettings(const bobSettings *settings); - void getStates(bobStates *bs); - - std::string executeCommand(const std::string &command); - bool connectI2P(); - bool disconnectI2P(); - - void finalizeSettings_locked(); - void updateSettings_locked(); - - std::string recv(); - - // states for state machines - controllerState mState; - controllerTask mTask; - // used to store old state when in error state - // mStateOld is also used as a flag when an error occured in BOB protocol - controllerState mStateOld; - // mTaskOld is used to keep the previous task (start up / shut down) when requesting keys or checking the connection - controllerTask mTaskOld; - bobSettings mSetting; - bobState mBOBState; - - // used variables - p3PeerMgr *mPeerMgr; - bool mConfigLoaded; - int mSocket; - rstime_t mLastProxyCheck; - sockaddr_storage mI2PProxyAddr; - std::map mCommands; - std::string mErrorMsg; - std::string mTunnelName; - - std::queue mPending; - taskTicket *mProcessing; - - // mutex - RsMutex mLock; -}; - -#endif // P3I2PBOB_H diff --git a/libretroshare/src/services/autoproxy/rsautoproxymonitor.cc b/libretroshare/src/services/autoproxy/rsautoproxymonitor.cc deleted file mode 100644 index d58c871e3..000000000 --- a/libretroshare/src/services/autoproxy/rsautoproxymonitor.cc +++ /dev/null @@ -1,342 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services/autoproxy: rsautoproximonitor.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Sehraf * - * * - * 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 . * - * * - *******************************************************************************/ -#include "rsautoproxymonitor.h" - -#include /* for usleep() */ -#include "util/rsdebug.h" -#include "util/rstime.h" - -rsAutoProxyMonitor *rsAutoProxyMonitor::mInstance = NULL; - -rsAutoProxyMonitor::rsAutoProxyMonitor() - : mRSShutDown(false), mLock("rs auto proxy monitor") -{ - mProxies.clear(); -} - -rsAutoProxyMonitor *rsAutoProxyMonitor::instance() -{ - if (mInstance == NULL) - mInstance = new rsAutoProxyMonitor(); - return mInstance; -} - -void rsAutoProxyMonitor::addProxy(autoProxyType::autoProxyType_enum type, autoProxyService *service) -{ - RS_STACK_MUTEX(mLock); - if (mProxies.find(type) != mProxies.end()) { - RS_ERR("type ", type, " already added - OVERWRITING"); - print_stacktrace(); - } - - mProxies[type] = service; -} - -void rsAutoProxyMonitor::startAll() -{ - // create ticket - taskTicket *tt = getTicket(); - tt->cb = this; - tt->task = autoProxyTask::start; - - { - std::map::const_iterator it; - - // fill types - RS_STACK_MUTEX(mLock); - for (it = mProxies.begin(); it != mProxies.end(); ++it) - if (it->second->isEnabled()) - tt->types.push_back(it->first); - } - - task(tt); -} - -void rsAutoProxyMonitor::stopAll() -{ - // create ticket - taskTicket *tt = getTicket(); - tt->cb = this; - tt->task = autoProxyTask::stop; - - { - std::map::const_iterator it; - - // fill types - RS_STACK_MUTEX(mLock); - for (it = mProxies.begin(); it != mProxies.end(); ++it) - if (it->second->isEnabled()) - tt->types.push_back(it->first); - } - - task(tt); -} - -void rsAutoProxyMonitor::stopAllRSShutdown() -{ - { - RS_STACK_MUTEX(mLock); - mRSShutDown = true; - - // remove disabled services - std::vector toRemove; - std::map::const_iterator it; - for (it = mProxies.begin(); it != mProxies.end(); ++it) { - if (!it->second->isEnabled()) { - toRemove.push_back(it->first); - } - } - - std::vector::const_iterator it2; - for (it2 = toRemove.begin(); it2 != toRemove.end(); ++it2) { - mProxies.erase(*it2); - } - } - - // stop all remaining - stopAll(); - - // wait for shutdown of all services - uint32_t t = 0, timeout = 15; - do { - rstime::rs_usleep(1000 * 1000); - RS_STACK_MUTEX(mLock); - RS_DBG("waiting for auto proxy service(s) to shut down ", t, "/", timeout, " (remaining: ", mProxies.size(), ")"); - if (mProxies.empty()) - break; - t++; - } while (t < timeout ); -} - -bool rsAutoProxyMonitor::isEnabled(autoProxyType::autoProxyType_enum t) -{ - autoProxyService *s = lookUpService(t); - if (s == NULL) - return false; - - return s->isEnabled(); -} - -bool rsAutoProxyMonitor::initialSetup(autoProxyType::autoProxyType_enum t, std::string &addr, uint16_t &port) -{ - autoProxyService *s = lookUpService(t); - if (s == NULL) - return false; - - return s->initialSetup(addr, port); -} - -void rsAutoProxyMonitor::task(taskTicket *ticket) -{ - // sanity checks - if (!ticket->async && ticket->types.size() > 1) { - RS_ERR("synchronous call to multiple services. This can cause problems!"); - print_stacktrace(); - } - if (ticket->async && !ticket->cb && ticket->data) { - RS_ERR("asynchronous call with data but no callback. This will likely causes memory leak!"); - print_stacktrace(); - } - if (ticket->types.size() > 1 && ticket->data) { - RS_ERR("call with data to multiple services. This will likely causes memory leak!"); - print_stacktrace(); - } - - std::vector::const_iterator it; - - for (it = ticket->types.begin(); it != ticket->types.end(); ++it) { - autoProxyService* s = lookUpService(*it); - if (s == NULL) - continue; - - if (ticket->async) { - // copy ticket - taskTicket *tt = new taskTicket(); - *tt = *ticket; - tt->types.clear(); - tt->types.push_back(*it); - - // it's async! - RsThread::async([s, tt] { - s->processTaskAsync(tt); - }); - } else { - s->processTaskSync(ticket); - } - } -} - -void rsAutoProxyMonitor::taskAsync(autoProxyType::autoProxyType_enum type, autoProxyTask::autoProxyTask_enum task, autoProxyCallback *cb, void *data) -{ - std::vector types; - types.push_back(type); - taskAsync(types, task, cb, data); -} - -void rsAutoProxyMonitor::taskAsync(std::vector types, autoProxyTask::autoProxyTask_enum task, autoProxyCallback *cb, void *data) -{ - if (!isAsyncTask(task)) { - // Usually the services will reject this ticket. - // Just print a warning - maybe there is some special case where this is a good idea. - RS_ERR("called with a synchronous task!"); - print_stacktrace(); - } - - taskTicket *tt = getTicket(); - tt->task = task; - tt->types = types; - if (cb) - tt->cb = cb; - if (data) - tt->data = data; - - instance()->task(tt); - // tickets were copied, clean up - delete tt; -} - -void rsAutoProxyMonitor::taskSync(autoProxyType::autoProxyType_enum type, autoProxyTask::autoProxyTask_enum task, void *data) -{ - std::vector types; - types.push_back(type); - taskSync(types, task, data); -} - -void rsAutoProxyMonitor::taskSync(std::vector types, autoProxyTask::autoProxyTask_enum task, void *data) -{ - if (isAsyncTask(task)) { - // Usually the services will reject this ticket. - // Just print a warning - maybe there is some special case where this is a good idea. - RS_ERR("called with an asynchronous task!"); - print_stacktrace(); - } - - taskTicket *tt = getTicket(); - tt->async = false; - tt->task = task; - tt->types = types; - if (data) - tt->data = data; - - instance()->task(tt); - // call done, clean up - delete tt; -} - -void rsAutoProxyMonitor::taskError(taskTicket *t) -{ - taskDone(t, autoProxyStatus::error); -} - -void rsAutoProxyMonitor::taskDone(taskTicket *t, autoProxyStatus::autoProxyStatus_enum status) -{ - bool cleanUp = false; - - t->result = status; - if (t->cb) { - t->cb->taskFinished(t); - if (t != NULL) { - // callack did not clean up properly - RS_ERR("callback did not clean up!"); - print_stacktrace(); - cleanUp = true; - } - } else if (t->async){ - // async and no callback - // we must take care of deleting - cleanUp = true; - if(t->data) - RS_ERR("async call with data attached but no callback set!"); - } - - if (cleanUp) { - if (t->data) { - RS_ERR("will try to delete void pointer!"); - print_stacktrace(); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdelete-incomplete" - delete t->data; -#pragma GCC diagnostic pop - t->data = NULL; - } - delete t; - t = NULL; - } -} - -taskTicket *rsAutoProxyMonitor::getTicket() -{ - taskTicket *tt = new taskTicket(); - tt->cb = NULL; - tt->data = NULL; - tt->async = true; - tt->result = autoProxyStatus::undefined; - return tt; -} - -void rsAutoProxyMonitor::taskFinished(taskTicket *&ticket) -{ - { - RS_STACK_MUTEX(mLock); - if (mRSShutDown && ticket->task == autoProxyTask::stop) { - mProxies.erase(ticket->types.front()); - } - } - - // clean up - if (ticket->data) { - RS_ERR(" data set. Will try to delete void pointer"); - print_stacktrace(); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdelete-incomplete" - delete ticket->data; -#pragma GCC diagnostic pop - ticket->data = NULL; - } - delete ticket; - ticket = NULL; -} - -autoProxyService *rsAutoProxyMonitor::lookUpService(autoProxyType::autoProxyType_enum t) -{ - RS_STACK_MUTEX(mLock); - std::map::const_iterator itService; - if ((itService = mProxies.find(t)) != mProxies.end()) { - return itService->second; - } - RS_DBG("no service for type ", t, " found!"); - return NULL; -} - -bool rsAutoProxyMonitor::isAsyncTask(autoProxyTask::autoProxyTask_enum t) -{ - switch (t) { - case autoProxyTask::start: - case autoProxyTask::stop: - case autoProxyTask::receiveKey: - return true; - break; - default: - break; - } - return false; -} diff --git a/libretroshare/src/services/autoproxy/rsautoproxymonitor.h b/libretroshare/src/services/autoproxy/rsautoproxymonitor.h deleted file mode 100644 index d9a4c16aa..000000000 --- a/libretroshare/src/services/autoproxy/rsautoproxymonitor.h +++ /dev/null @@ -1,237 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services/autoproxy: rsautoproximonitor.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Sehraf * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSAUTOPROXYMONITOR_H -#define RSAUTOPROXYMONITOR_H - -#include -#include - -#include - -class autoProxyCallback; - -namespace autoProxyType { - enum autoProxyType_enum { - I2PBOB - }; -} - -namespace autoProxyTask { - enum autoProxyTask_enum { - /* async tasks */ - start, ///< start up proxy - stop, ///< shut down proxy - receiveKey, ///< renew proxy key (if any) - proxyStatusCheck, ///< use to check if the proxy is still running - /* sync tasks */ - status, ///< get status from auto proxy - getSettings, ///< get setting from auto proxy - setSettings, ///< set setting of auto proxy - reloadConfig, ///< signal config reload/rebuild - getErrorInfo ///< get error information from auto proxy - }; -} - -namespace autoProxyStatus { - enum autoProxyStatus_enum { - undefined, ///< undefined - usually not yet set - disabled, ///< used when a task cannot be done (e.g. a disabled service cannot be startet or stopped) - offline, ///< proxy is not set up - online, ///< proxy is set up - ok, ///< generic ok - error ///< generic error - }; -} - -struct taskTicket { - /// - /// \brief types auto proxy service types that should get the ticket - /// - std::vector types; - - /// - /// \brief task the task to satisfy - /// - autoProxyTask::autoProxyTask_enum task; - - /// - /// \brief cb (optional) callback that gets called once the task is done - /// - autoProxyCallback *cb; - - /// - /// \brief result (optional) result - /// - autoProxyStatus::autoProxyStatus_enum result; - - /// - /// \brief data (optional) service dependent data - /// - /// Needs to be allocated and freed by caller! - /// - void *data; - - /// - /// \brief async is the call Asynchronous - /// - /// Will create a copy of the ticket for each - /// service and delete the original ticket. - /// - bool async; -}; - -class autoProxyCallback { -public: - /// - /// \brief taskFinished called when a task is finished - /// \param ticket - /// - /// Remove everything: ticket and attached data if any! - /// - virtual void taskFinished(taskTicket *&ticket) = 0; -}; - -class autoProxyService { -public: - /// - /// \brief isEnabled must be provided to directly get a result without going through the ticket system - /// \return whether the auto proxy service is enabled or not - /// - virtual bool isEnabled() = 0; - - /// - /// \brief initialSetup used when creating a node - /// \param addr new address for the hidden service - /// \param port new port for the hidden service - /// \return true on success - /// - /// This function is used to do an initial setup when creating a new hidden node. - /// Nothing has been set up at this point to the auto proxy service must take care - /// of everything (e.g. starting (and stoping) of needed threads) - /// - virtual bool initialSetup(std::string &addr, uint16_t &port) = 0; - - /// - /// \brief processTaskAsync adds a ticket to the auto proxies task list - /// \param ticket - /// - /// Don't call the callback in this function as this can cause dead locks! - /// - virtual void processTaskAsync(taskTicket *ticket) = 0; - - /// - /// \brief processTaskSync taskTicket must be satisfied immediately - /// \param ticket - /// - virtual void processTaskSync(taskTicket *ticket) = 0; -}; - -class rsAutoProxyMonitor : autoProxyCallback -{ -public: - static rsAutoProxyMonitor *instance(); - - /// - /// \brief addProxy adds a new auto proxy service to the monitor - /// \param type type of the new auto proxy service - /// \param service pointer to the service - /// - void addProxy(autoProxyType::autoProxyType_enum type, autoProxyService *service); - - // global functions - void startAll(); - void stopAll(); - void stopAllRSShutdown(); - bool isEnabled(autoProxyType::autoProxyType_enum t); - // use this when creating a new node - bool initialSetup(autoProxyType::autoProxyType_enum t, std::string &addr, uint16_t &port); - - /// - /// \brief task Sends a task to all requested services - /// \param ticket Ticket containing required information - /// - /// There are two kind of tasks: asyn and sync. - /// All tasks that involve communication with the target program (e.g. I2P or Tor) are asynchronous. - /// All other task are synchronous (e.g. getting settings) - /// - /// - /// Synchronous: - /// When you want to get the settings from a service you can call task() with a ticket only listing - /// one service and data pointing to the service's settings class/struct. Set async to false so - /// that the service gets your original ticket. Ther service will process the request (get settings) - /// immediately and when the call to task() is done you can access the settings from your ticket. - /// - /// When additionally a call back is set the service will also call it. This can cause deadlocks! - /// - /// - /// Asynchronous: - /// When you want to start up all services or request new keys for all services you can call task() with a list - /// of services and set async to true. When each service has fullfilled the resquest he will - /// use the callback. The original caller ticket will be copied and each call to the callback - /// will use its copy of the original ticket. The attached data is not copied so each service gets - /// the same pointer! - /// - /// - /// Note: - /// Services should not delet or allocate anything unless no call back is provided and it is an - /// async call. In that case the service should delete the ticket and the attacked data. - /// Otherwise the caller must take care of cleaning up. - /// This class provides two wrappers to take care of this that should be used: taskError and taskDone - /// - /// Note2: - /// This function is private so that each user must use the wrappers taskAsync and taskSync that include - /// more sanity checks - /// -private: - void task(taskTicket *ticket); - -public: - static void taskAsync(autoProxyType::autoProxyType_enum type, autoProxyTask::autoProxyTask_enum task, autoProxyCallback *cb = NULL, void *data = NULL); - static void taskAsync(std::vector types, autoProxyTask::autoProxyTask_enum task, autoProxyCallback *cb = NULL, void *data = NULL); - static void taskSync (autoProxyType::autoProxyType_enum type, autoProxyTask::autoProxyTask_enum task, void *data = NULL); - static void taskSync (std::vector types, autoProxyTask::autoProxyTask_enum task, void *data = NULL); - - // usefull helpers - static void taskError(taskTicket *t); - static void taskDone(taskTicket *t, autoProxyStatus::autoProxyStatus_enum status); - static taskTicket *getTicket(); - - // autoProxyCallback interface -public: - void taskFinished(taskTicket *&ticket); - -private: - rsAutoProxyMonitor(); - - autoProxyService *lookUpService(autoProxyType::autoProxyType_enum t); - static bool isAsyncTask(autoProxyTask::autoProxyTask_enum t); - - std::map mProxies; - bool mRSShutDown; - RsMutex mLock; - - static rsAutoProxyMonitor *mInstance; -}; - - - -#endif // RSAUTOPROXYMONITOR_H diff --git a/libretroshare/src/services/broadcastdiscoveryservice.cc b/libretroshare/src/services/broadcastdiscoveryservice.cc deleted file mode 100644 index 076244b44..000000000 --- a/libretroshare/src/services/broadcastdiscoveryservice.cc +++ /dev/null @@ -1,319 +0,0 @@ -/******************************************************************************* - * RetroShare Broadcast Domain Discovery * - * * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#ifdef __ANDROID__ -# include -#endif // def __ANDROID__ - -#include "services/broadcastdiscoveryservice.h" -#include "retroshare/rspeers.h" -#include "serialiser/rsserializable.h" -#include "serialiser/rsserializer.h" -#include "retroshare/rsevents.h" - -/*extern*/ RsBroadcastDiscovery* rsBroadcastDiscovery = nullptr; - -struct BroadcastDiscoveryPack : RsSerializable -{ - BroadcastDiscoveryPack() : mLocalPort(0) {} - - RsPgpFingerprint mPgpFingerprint; - RsPeerId mSslId; - uint16_t mLocalPort; - std::string mProfileName; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mPgpFingerprint); - RS_SERIAL_PROCESS(mSslId); - RS_SERIAL_PROCESS(mLocalPort); - RS_SERIAL_PROCESS(mProfileName); - } - - static BroadcastDiscoveryPack fromPeerDetails(const RsPeerDetails& pd) - { - BroadcastDiscoveryPack bdp; - bdp.mPgpFingerprint = pd.fpr; - bdp.mSslId = pd.id; - bdp.mLocalPort = pd.localPort; - bdp.mProfileName = pd.name; - return bdp; - } - - static BroadcastDiscoveryPack fromSerializedString(const std::string& st) - { - RsGenericSerializer::SerializeContext ctx( - reinterpret_cast(const_cast(st.data())), - static_cast(st.size()) ); - BroadcastDiscoveryPack bdp; - bdp.serial_process(RsGenericSerializer::DESERIALIZE, ctx); - return bdp; - } - - std::string serializeToString() - { - /* After some experiments it seems very unlikely that UDP broadcast - * packets bigger then this could get trought a network */ - std::vector buffer(512, 0); - RsGenericSerializer::SerializeContext ctx( - buffer.data(), static_cast(buffer.size()) ); - serial_process(RsGenericSerializer::SERIALIZE, ctx); - return std::string(reinterpret_cast(buffer.data()), ctx.mOffset); - } - - BroadcastDiscoveryPack(const BroadcastDiscoveryPack&) = default; - ~BroadcastDiscoveryPack() override; -}; - - -BroadcastDiscoveryService::BroadcastDiscoveryService( - RsPeers& pRsPeers ) : - mDiscoveredDataMutex("BroadcastDiscoveryService discovered data mutex"), - mRsPeers(pRsPeers) -{ - if(mRsPeers.isHiddenNode(mRsPeers.getOwnId())) return; - -#ifdef __ANDROID__ - createMulticastLock(); -#endif // def __ANDROID__ - - enableMulticastListening(); - - mUdcParameters.set_can_discover(true); - mUdcParameters.set_can_be_discovered(true); - mUdcParameters.set_port(port); - mUdcParameters.set_application_id(appId); - - mUdcPeer.Start(mUdcParameters, ""); - updatePublishedData(); -} - -BroadcastDiscoveryService::~BroadcastDiscoveryService() -{ - mUdcPeer.Stop(true); - disableMulticastListening(); -} - -std::vector -BroadcastDiscoveryService::getDiscoveredPeers() -{ - std::vector ret; - - RS_STACK_MUTEX(mDiscoveredDataMutex); - for(auto&& pp: mDiscoveredData) - ret.push_back(createResult(pp.first, pp.second)); - - return ret; -} - -void BroadcastDiscoveryService::updatePublishedData() -{ - RsPeerDetails od; - mRsPeers.getPeerDetails(mRsPeers.getOwnId(), od); - mUdcPeer.SetUserData( - BroadcastDiscoveryPack::fromPeerDetails(od).serializeToString()); -} - -void BroadcastDiscoveryService::threadTick() -{ - if( mUdcParameters.can_discover() && - !mRsPeers.isHiddenNode(mRsPeers.getOwnId()) ) - { - auto currentEndpoints = mUdcPeer.ListDiscovered(); - std::map currentMap; - std::map updateMap; - - mDiscoveredDataMutex.lock(); - for(auto&& dEndpoint: currentEndpoints) - { - currentMap[dEndpoint.ip_port()] = dEndpoint.user_data(); - - auto findIt = mDiscoveredData.find(dEndpoint.ip_port()); - if( !dEndpoint.user_data().empty() && ( - findIt == mDiscoveredData.end() || - findIt->second != dEndpoint.user_data() ) ) - updateMap[dEndpoint.ip_port()] = dEndpoint.user_data(); - } - mDiscoveredData = currentMap; - mDiscoveredDataMutex.unlock(); - - if(!updateMap.empty()) - { - for (auto&& pp : updateMap) - { - RsBroadcastDiscoveryResult rbdr = - createResult(pp.first, pp.second); - - const bool isFriend = mRsPeers.isFriend(rbdr.mSslId); - if( isFriend && rbdr.mLocator.hasPort() && - !mRsPeers.isOnline(rbdr.mSslId) ) - { - mRsPeers.setLocalAddress( - rbdr.mSslId, rbdr.mLocator.host(), - rbdr.mLocator.port() ); - mRsPeers.connectAttempt(rbdr.mSslId); - } - else if(!isFriend) - { - if(rsEvents) - { - auto ev = std::make_shared(); - - ev->mDiscoveryEventType = RsBroadcastDiscoveryEventType::PEER_FOUND; - ev->mData = rbdr; - - rsEvents->postEvent(ev); - } - } - } - } - } - - /* Probably this would be better if done only on actual change */ - if( mUdcParameters.can_be_discovered() && - !mRsPeers.isHiddenNode(mRsPeers.getOwnId()) ) updatePublishedData(); - - // This avoids waiting 5 secs when the thread should actually terminate (when RS closes). - for(uint32_t i=0;i<10;++i) - { - if(shouldStop()) - return; - rstime::rs_usleep(500*1000); // sleep for 0.5 sec. - } -} - -RsBroadcastDiscoveryResult BroadcastDiscoveryService::createResult( - const udpdiscovery::IpPort& ipp, const std::string& uData ) -{ - BroadcastDiscoveryPack bdp = - BroadcastDiscoveryPack::fromSerializedString(uData); - - RsBroadcastDiscoveryResult rbdr; - rbdr.mPgpFingerprint = bdp.mPgpFingerprint; - rbdr.mSslId = bdp.mSslId; - rbdr.mProfileName = bdp.mProfileName; - rbdr.mLocator. - setScheme("ipv4"). - setHost(UDC::IpToString(ipp.ip())). - setPort(bdp.mLocalPort); - - return rbdr; -} - -bool BroadcastDiscoveryService::isMulticastListeningEnabled() -{ -#ifdef __ANDROID__ - return assertMulticastLockIsvalid() && - mWifiMulticastLock.callMethod("isHeld"); -#endif // def __ANDROID__ - - return true; -} - -bool BroadcastDiscoveryService::enableMulticastListening() -{ -#ifdef __ANDROID__ - if(assertMulticastLockIsvalid() && !isMulticastListeningEnabled()) - { - mWifiMulticastLock.callMethod("acquire"); - return true; - } -#endif // def __ANDROID__ - - return false; -} - -bool BroadcastDiscoveryService::disableMulticastListening() -{ -#ifdef __ANDROID__ - if(assertMulticastLockIsvalid() && isMulticastListeningEnabled()) - { - mWifiMulticastLock.callMethod("release"); - return true; - } -#endif // def __ANDROID__ - - return false; -} - -#ifdef __ANDROID__ -bool BroadcastDiscoveryService::createMulticastLock() -{ - Dbg2() << __PRETTY_FUNCTION__ << std::endl; - - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(mWifiMulticastLock.isValid()) - return failure("mWifiMulticastLock is already initialized"); - - QAndroidJniObject context = QtAndroid::androidContext(); - if(!context.isValid()) - return failure("Cannot retrieve Android context"); - - QAndroidJniObject WIFI_SERVICE = QAndroidJniObject::getStaticObjectField( - "android.content.Context", "WIFI_SERVICE", "Ljava/lang/String;"); - if(!WIFI_SERVICE.isValid()) - return failure("Cannot retrieve Context.WIFI_SERVICE value"); - - QAndroidJniObject wifiManager = context.callObjectMethod( - "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;", - WIFI_SERVICE.object() ); - if(!wifiManager.isValid()) - return failure("Cannot retrieve Android Wifi Manager"); - - mWifiMulticastLock = wifiManager.callObjectMethod( - "createMulticastLock", - "(Ljava/lang/String;)Landroid/net/wifi/WifiManager$MulticastLock;", - QAndroidJniObject::fromString(fname).object() ); - if(!mWifiMulticastLock.isValid()) - return failure("Cannot create WifiManager.MulticastLock"); - - return true; -} - -bool BroadcastDiscoveryService::assertMulticastLockIsvalid() -{ - if(!mWifiMulticastLock.isValid()) - { - RsErr() << __PRETTY_FUNCTION__ << " mWifiMulticastLock is invalid!" - << std::endl; - print_stacktrace(); - return false; - } - return true; -} -#endif // def __ANDROID__ - -RsBroadcastDiscovery::~RsBroadcastDiscovery() = default; -RsBroadcastDiscoveryResult::~RsBroadcastDiscoveryResult() = default; -BroadcastDiscoveryPack::~BroadcastDiscoveryPack() = default; diff --git a/libretroshare/src/services/broadcastdiscoveryservice.h b/libretroshare/src/services/broadcastdiscoveryservice.h deleted file mode 100644 index ebbec04c1..000000000 --- a/libretroshare/src/services/broadcastdiscoveryservice.h +++ /dev/null @@ -1,96 +0,0 @@ -/******************************************************************************* - * RetroShare Broadcast Domain Discovery * - * * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include - -#include - -#ifdef __ANDROID__ -# include -#endif // def __ANDROID__ - -#include "retroshare/rsbroadcastdiscovery.h" -#include "util/rsthreads.h" -#include "util/rsdebug.h" - -namespace UDC = udpdiscovery; -class RsPeers; - -class BroadcastDiscoveryService : - public RsBroadcastDiscovery, public RsTickingThread -{ -public: - BroadcastDiscoveryService(RsPeers& pRsPeers); - ~BroadcastDiscoveryService() override; - - /// @see RsBroadcastDiscovery - std::vector getDiscoveredPeers() override; - - /// @see RsBroadcastDiscovery - bool isMulticastListeningEnabled() override; - - /// @see RsBroadcastDiscovery - bool enableMulticastListening() override; - - /// @see RsBroadcastDiscovery - bool disableMulticastListening() override; - - void threadTick() override; /// @see RsTickingThread - -protected: - constexpr static uint16_t port = 36405; - constexpr static uint32_t appId = 904571; - - void updatePublishedData(); - - UDC::PeerParameters mUdcParameters; - UDC::Peer mUdcPeer; - - std::map mDiscoveredData; - RsMutex mDiscoveredDataMutex; - - RsPeers& mRsPeers; // TODO: std::shared_ptr mRsPeers; - - RsBroadcastDiscoveryResult createResult( - const UDC::IpPort& ipp, const std::string& uData ); - -#ifdef __ANDROID__ - /** Android WifiManager.MulticastLock */ - QAndroidJniObject mWifiMulticastLock; - - /** Initialize the wifi multicast lock without acquiring it - * Needed to enable multicast listening in Android, for RetroShare broadcast - * discovery inspired by: - * https://github.com/flutter/flutter/issues/16335#issuecomment-420547860 - */ - bool createMulticastLock(); - - /** Return false if mWifiMulticastLock is invalid and print error messages */ - bool assertMulticastLockIsvalid(); - -#endif // def __ANDROID__ - - RS_SET_CONTEXT_DEBUG_LEVEL(3) -}; diff --git a/libretroshare/src/services/p3banlist.cc b/libretroshare/src/services/p3banlist.cc deleted file mode 100644 index a257d2772..000000000 --- a/libretroshare/src/services/p3banlist.cc +++ /dev/null @@ -1,1303 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3banlist.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/p3servicecontrol.h" -#include "pqi/p3netmgr.h" -#include "pqi/p3cfgmgr.h" - -#include "util/rsnet.h" - -#include "services/p3banlist.h" -#include "retroshare/rsdht.h" -#include "retroshare/rsbanlist.h" - -#include "rsitems/rsbanlistitems.h" -#include "rsitems/rsconfigitems.h" - -#include -#include - -/**** - * #define DEBUG_BANLIST 1 - ****/ -// #define DEBUG_BANLIST 1 -//#define DEBUG_BANLIST_CONDENSE 1 - - -/* DEFINE INTERFACE POINTER! */ -//RsBanList *rsBanList = NULL; - -#define RSBANLIST_ENTRY_MAX_AGE (60 * 60 * 24) // 24 HOURS -#define RSBANLIST_SEND_PERIOD 600 // 10 Minutes. - -#define RSBANLIST_DELAY_BETWEEN_TALK_TO_DHT 240 // every 4 mins. - -/************ IMPLEMENTATION NOTES ********************************* - * - * Get Bad Peers passed to us (from DHT mainly). - * we distribute and track the network list of bad peers. - * - */ -RsBanList *rsBanList = NULL ; - -p3BanList::p3BanList(p3ServiceControl *sc, p3NetMgr */*nm*/) - : p3Service(), mBanMtx("p3BanList"), mServiceCtrl(sc) - , mSentListTime(0), mLastDhtInfoRequest(0) - // default number of IPs in same range to trigger a complete IP /24 filter. - , mAutoRangeLimit(2), mAutoRangeIps(true) - , mIPFilteringEnabled(true) - , mIPFriendGatheringEnabled(false) - , mIPDHTGatheringEnabled(false) -{ addSerialType(new RsBanListSerialiser()); } - -const std::string BANLIST_APP_NAME = "banlist"; -const uint16_t BANLIST_APP_MAJOR_VERSION = 1; -const uint16_t BANLIST_APP_MINOR_VERSION = 0; -const uint16_t BANLIST_MIN_MAJOR_VERSION = 1; -const uint16_t BANLIST_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3BanList::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_BANLIST, - BANLIST_APP_NAME, - BANLIST_APP_MAJOR_VERSION, - BANLIST_APP_MINOR_VERSION, - BANLIST_MIN_MAJOR_VERSION, - BANLIST_MIN_MINOR_VERSION); -} - -bool p3BanList::ipFilteringEnabled() { return mIPFilteringEnabled ; } -void p3BanList::enableIPFiltering(bool b) { mIPFilteringEnabled = b ; } -void p3BanList::enableIPsFromFriends(bool b) { mIPFriendGatheringEnabled = b; mLastDhtInfoRequest=0;} -void p3BanList::enableIPsFromDHT(bool b) -{ - mIPDHTGatheringEnabled = b; - mLastDhtInfoRequest=0; - - IndicateConfigChanged(); -} -void p3BanList::enableAutoRange(bool b) -{ - mAutoRangeIps = b; - autoFigureOutBanRanges() ; - - IndicateConfigChanged(); -} -void p3BanList::setAutoRangeLimit(int n) -{ - mAutoRangeLimit = n; - autoFigureOutBanRanges(); - - IndicateConfigChanged(); -} - -namespace services { - -class ZeroedInt -{ - public: - ZeroedInt() { n = 0 ; } - uint32_t n ; -}; - -} - -BanListPeer::BanListPeer() -{ - memset(&addr, 0, sizeof(addr)); - masked_bytes=0; - reason=RSBANLIST_REASON_UNKNOWN ; - level=RSBANLIST_ORIGIN_UNKNOWN ; - state = true ; - connect_attempts=0; - mTs=0; -} - -void BanListPeer::toRsTlvBanListEntry(RsTlvBanListEntry &e) const -{ - e.addr.addr = addr; - e.masked_bytes = masked_bytes; - e.reason = reason; - e.level = level; - e.comment = comment; - e.age = time(NULL) - mTs; -} - -void BanListPeer::fromRsTlvBanListEntry(const RsTlvBanListEntry &e) -{ - addr = e.addr.addr; - masked_bytes = e.masked_bytes; // 0 = []/32. 1=[]/24, 2=[]/16 - reason = e.reason; // User, DHT - level = e.level; // LOCAL, FRIEND, FoF. - state = true; // true=>active, false=>just stored but inactive - connect_attempts = 0; // recorded by the BanList service - comment = e.comment; // recorded by the BanList service - mTs = time(NULL) - e.age; -} - -static uint32_t getBitRange(const sockaddr_storage& addr) -{ - sockaddr_storage s ; - sockaddr_storage_clear(s) ; - sockaddr_storage_copyip(s,addr) ; - - sockaddr_in *ad = (sockaddr_in*)(&s) ; - - if( (ad->sin_addr.s_addr & 0xff000000) != 0xff000000) - return 0 ; - - if( (ad->sin_addr.s_addr & 0x00ff0000) != 0x00ff0000) - return 1 ; - - if( (ad->sin_addr.s_addr & 0x0000ff00) != 0x0000ff00) - return 2 ; - - if( (ad->sin_addr.s_addr & 0x000000ff) != 0x000000ff) - return 3 ; - - return 4 ; -} -static sockaddr_storage makeBitsRange(const sockaddr_storage& addr,int masked_bytes) -{ - sockaddr_storage s ; - sockaddr_storage_clear(s) ; - sockaddr_storage_copyip(s,addr) ; - - sockaddr_in *ad = (sockaddr_in*)(&s) ; - - if(masked_bytes == 1) - ad->sin_addr.s_addr |= 0xff000000 ; - else if(masked_bytes == 2) - ad->sin_addr.s_addr |= 0xffff0000 ; - else if(masked_bytes != 0) - std::cerr << "Warning: unhandled mask size for IP range: " << masked_bytes << std::endl; - - return s ; -} - -void p3BanList::autoFigureOutBanRanges() -{ - RS_STACK_MUTEX(mBanMtx) ; - - // clear automatic ban ranges - - for(std::map::iterator it(mBanRanges.begin()); - it!=mBanRanges.end(); ) - { - if(it->second.reason == RSBANLIST_REASON_AUTO_RANGE) - { - std::map::iterator it2=it ; - ++it2 ; - mBanRanges.erase(it) ; - it=it2 ; - } - else ++it; - } - - IndicateConfigChanged(); - - if(!mAutoRangeIps) return; - -#ifdef DEBUG_BANLIST - std::cerr << "Automatically figuring out IP ranges from banned IPs." << std::endl; -#endif - - std::map range_map ; - - for(std::map::iterator it(mBanSet.begin());it!=mBanSet.end();++it) - ++range_map[makeBitsRange(it->first,1)].n ; - - rstime_t now = time(NULL) ; - - for(std::map::const_iterator it=range_map.begin();it!=range_map.end();++it) - { -#ifdef DEBUG_BANLIST - std::cerr << "Ban range: " << sockaddr_storage_iptostring(it->first) << " : " << it->second.n << std::endl; -#endif - - if(it->second.n >= mAutoRangeLimit) - { -#ifdef DEBUG_BANLIST - std::cerr << " --> creating new ban range." << std::endl; -#endif - BanListPeer& peer(mBanRanges[it->first]) ; - - if (peer.reason == RSBANLIST_REASON_USER) - continue; - - peer.addr = it->first ; - peer.masked_bytes = 1 ; - peer.reason = RSBANLIST_REASON_AUTO_RANGE ; - peer.level = RSBANLIST_ORIGIN_SELF ; - peer.state = true ; - peer.mTs = now ; - peer.connect_attempts = 0 ; - peer.connect_attempts = it->second.n; - } - } - - condenseBanSources_locked() ; -} - -bool p3BanList::acceptedBanSet_locked(const BanListPeer& blp) -{ - // REASON_USER REASON_DHT REASON_AUTO - // --------------------------------------------------------- - // banDHT Y/Y/N Y/Y/Y - // --------------------------------------------------------- - // banFriends - // --------------------------------------------------------- - // banAutoRanges - // - - if(blp.level > 1 && mIPFriendGatheringEnabled) - return true ; - - switch(blp.reason) - { - case RSBANLIST_REASON_USER: return true ; - - case RSBANLIST_REASON_DHT: return mIPDHTGatheringEnabled && blp.level==1; - - default: - case RSBANLIST_REASON_AUTO_RANGE: std::cerr << "(EE) Shouldn't find an AUTO RANGE in BanSet. Wrong call?" << std::endl; - return false ; - } - return false ; -} -bool p3BanList::acceptedBanRanges_locked(const BanListPeer& blp) -{ - // REASON_USER REASON_DHT REASON_AUTO - // --------------------------------------------------------- - // banDHT Y/Y/N Y/Y/Y - // --------------------------------------------------------- - // banFriends - // --------------------------------------------------------- - // banAutoRanges - // - - switch(blp.reason) - { - case RSBANLIST_REASON_USER: return true ; - - default: - case RSBANLIST_REASON_DHT: std::cerr << "(EE) Shouldn't find a DHT ip in BanRange. Wrong call?" << std::endl; - return false ; - - case RSBANLIST_REASON_AUTO_RANGE: return mAutoRangeIps ; - } - return false ; -} - -bool p3BanList::isAddressAccepted( - const sockaddr_storage& dAddr, uint32_t checking_flags, - uint32_t& check_result ) -{ - check_result = RSBANLIST_CHECK_RESULT_NOCHECK; - - sockaddr_storage addr; sockaddr_storage_copy(dAddr, addr); - - if(!sockaddr_storage_ipv6_to_ipv4(addr)) return true; - if(sockaddr_storage_isLoopbackNet(addr)) return true; - - - RS_STACK_MUTEX(mBanMtx); - - if(!mIPFilteringEnabled) return true; - -#ifdef DEBUG_BANLIST - std::cerr << "isAddressAccepted(): tested addr=" << sockaddr_storage_iptostring(addr) << ", checking flags=" << checking_flags ; -#endif - - // we should normally work this including entire ranges of IPs. For now, just check the exact IPs. - - sockaddr_storage addr_32 = makeBitsRange(addr,0) ; // this is necessay because it cleans the address - sockaddr_storage addr_24 = makeBitsRange(addr,1) ; - sockaddr_storage addr_16 = makeBitsRange(addr,2) ; - - bool white_list_found = false ; - - white_list_found = white_list_found || (mWhiteListedRanges.find(addr_16) != mWhiteListedRanges.end()) ; - white_list_found = white_list_found || (mWhiteListedRanges.find(addr_24) != mWhiteListedRanges.end()) ; - white_list_found = white_list_found || (mWhiteListedRanges.find(addr_32) != mWhiteListedRanges.end()) ; - - if(white_list_found) - { - check_result = RSBANLIST_CHECK_RESULT_ACCEPTED; -#ifdef DEBUG_BANLIST - std::cerr << ". Address is in whitelist. Accepting" << std::endl; -#endif - return true ; - } - - if(checking_flags & RSBANLIST_CHECKING_FLAGS_WHITELIST) - { - check_result = RSBANLIST_CHECK_RESULT_NOT_WHITELISTED; -#ifdef DEBUG_BANLIST - std::cerr << ". Address is not whitelist, and whitelist is required. Rejecting" << std::endl; -#endif - return false ; - } - - if(!(checking_flags & RSBANLIST_CHECKING_FLAGS_BLACKLIST)) - { -#ifdef DEBUG_BANLIST - std::cerr << ". No blacklisting required. Accepting." << std::endl; -#endif - check_result = RSBANLIST_CHECK_RESULT_ACCEPTED; - return true; - } - - std::map::iterator it ; - - if(((it=mBanRanges.find(addr_16)) != mBanRanges.end()) && acceptedBanRanges_locked(it->second)) - { - ++it->second.connect_attempts; -#ifdef DEBUG_BANLIST - std::cerr << " found in blacklisted range " << sockaddr_storage_iptostring(it->first) << "/16. returning false. attempts=" << it->second.connect_attempts << std::endl; -#endif - check_result = RSBANLIST_CHECK_RESULT_BLACKLISTED; - return false ; - } - - if(((it=mBanRanges.find(addr_24)) != mBanRanges.end()) && acceptedBanRanges_locked(it->second)) - { - ++it->second.connect_attempts; -#ifdef DEBUG_BANLIST - std::cerr << " found in blacklisted range " << sockaddr_storage_iptostring(it->first) << "/24. returning false. attempts=" << it->second.connect_attempts << std::endl; -#endif - check_result = RSBANLIST_CHECK_RESULT_BLACKLISTED; - return false ; - } - - if(((it=mBanRanges.find(addr_32)) != mBanRanges.end()) && acceptedBanRanges_locked(it->second)) - { - ++it->second.connect_attempts; -#ifdef DEBUG_BANLIST - std::cerr << " found in blacklisted range " << sockaddr_storage_iptostring(it->first) << "/32. returning false. attempts=" << it->second.connect_attempts << std::endl; -#endif - check_result = RSBANLIST_CHECK_RESULT_BLACKLISTED; - return false ; - } - - if((it=mBanSet.find(addr_32)) != mBanSet.end() && acceptedBanSet_locked(it->second)) - { - ++it->second.connect_attempts; -#ifdef DEBUG_BANLIST - std::cerr << "found as blacklisted address " << sockaddr_storage_iptostring(it->first) << ". returning false. attempts=" << it->second.connect_attempts << std::endl; -#endif - check_result = RSBANLIST_CHECK_RESULT_BLACKLISTED; - return false ; - } - -#ifdef DEBUG_BANLIST - std::cerr << " not blacklisted. Accepting." << std::endl; -#endif - check_result = RSBANLIST_CHECK_RESULT_ACCEPTED; - return true ; -} - -void p3BanList::getWhiteListedIps(std::list &lst) -{ - RS_STACK_MUTEX(mBanMtx) ; - - lst.clear() ; - for(std::map::const_iterator it(mWhiteListedRanges.begin());it!=mWhiteListedRanges.end();++it) - lst.push_back(it->second) ; -} -void p3BanList::getBannedIps(std::list &lst) -{ - RS_STACK_MUTEX(mBanMtx) ; - - - lst.clear() ; - for(std::map::const_iterator it(mBanSet.begin());it!=mBanSet.end();++it) - { - if(!acceptedBanSet_locked(it->second)) - continue ; - - std::map::const_iterator found1 = mBanRanges.find(makeBitsRange(it->first,1)) ; - - if(found1!=mBanRanges.end() && acceptedBanRanges_locked(found1->second)) - continue ; - - std::map::const_iterator found2 = mBanRanges.find(makeBitsRange(it->first,2)) ; - - if(found2!=mBanRanges.end() && acceptedBanRanges_locked(found2->second)) - continue ; - - lst.push_back(it->second) ; - } - - for(std::map::const_iterator it(mBanRanges.begin());it!=mBanRanges.end();++it) - if(acceptedBanRanges_locked(it->second)) - lst.push_back(it->second) ; -} - -bool p3BanList::removeIpRange( const struct sockaddr_storage& dAddr, - int masked_bytes, uint32_t list_type ) -{ - sockaddr_storage addr; sockaddr_storage_copy(dAddr, addr); - if(!sockaddr_storage_ipv6_to_ipv4(addr)) - { - std::cerr << __PRETTY_FUNCTION__ << " Cannot handle " - << sockaddr_storage_tostring(dAddr) - << " IPv6 not implemented yet!" - << std::endl; - return false; - } - - RS_STACK_MUTEX(mBanMtx); - - bool changed = false; - std::map::iterator it ; - - if(list_type == RSBANLIST_TYPE_BLACKLIST) - { - if( mBanRanges.end() != (it = mBanRanges.find(makeBitsRange(addr,masked_bytes)))) - { - mBanRanges.erase(it) ; - IndicateConfigChanged(); - changed = true; - } - } - else if(list_type == RSBANLIST_TYPE_WHITELIST) - { - if( mWhiteListedRanges.end() != (it = mWhiteListedRanges.find(makeBitsRange(addr,masked_bytes)))) - { - mWhiteListedRanges.erase(it) ; - IndicateConfigChanged(); - changed = true; - } - } - else - std::cerr << "(EE) Only whitelist or blacklist ranges can be removed." << std::endl; - - condenseBanSources_locked() ; - return changed; -} - -bool p3BanList::addIpRange( const sockaddr_storage &dAddr, int masked_bytes, - uint32_t list_type, const std::string& comment ) -{ - sockaddr_storage addr; sockaddr_storage_copy(dAddr, addr); - if(!sockaddr_storage_ipv6_to_ipv4(addr)) - { - std::cerr << __PRETTY_FUNCTION__ << " Cannot handle " - << sockaddr_storage_tostring(dAddr) - << " IPv6 not implemented yet!" - << std::endl; - return false; - } - - RS_STACK_MUTEX(mBanMtx); - - if(getBitRange(addr) > uint32_t(masked_bytes)) - { - std::cerr << "(EE) Input to p3BanList::addIpRange is inconsistent: ip=" << sockaddr_storage_iptostring(addr) << "/" << 32-8*masked_bytes << std::endl; - return false ; - } - - BanListPeer blp ; - blp.level = RSBANLIST_ORIGIN_SELF ; - blp.connect_attempts = 0 ; - blp.addr = addr ; - blp.masked_bytes = masked_bytes ; - blp.mTs = time(NULL) ; - blp.reason = RSBANLIST_REASON_USER; - blp.comment = comment ; - - if(masked_bytes != 0 && masked_bytes != 1 && masked_bytes != 2) - { - std::cerr << "Unhandled masked byte size " << masked_bytes << ". Should be 0,1 or 2" << std::endl; - return false; - } - if(list_type != RSBANLIST_TYPE_BLACKLIST && list_type != RSBANLIST_TYPE_WHITELIST) - { - std::cerr << "(EE) Cannot add IP range. Bad list_type. Should be eiter RSBANLIST_TYPE_BLACKLIST or RSBANLIST_TYPE_WHITELIST" << std::endl; - return false ; - } - - // Remove all existing ranges that are included into current range. - - std::map& banlist( (list_type == RSBANLIST_TYPE_BLACKLIST)?mBanRanges:mWhiteListedRanges) ; - - for(int i=0;i::iterator it = banlist.find(makeBitsRange(addr,i)) ; - - if(it != banlist.end()) - banlist.erase(it) ; - } - // Add range to list. - - banlist[makeBitsRange(addr,masked_bytes)] = blp ; - - IndicateConfigChanged() ; - condenseBanSources_locked() ; - - return true; -} - -int p3BanList::tick() -{ - processIncoming(); - sendPackets(); - - rstime_t now = time(NULL) ; - - if(mLastDhtInfoRequest + RSBANLIST_DELAY_BETWEEN_TALK_TO_DHT < now) - { - getDhtInfo() ; // This is always done, since these IPs are also sent to friends. - - mLastDhtInfoRequest = now; - - if(mAutoRangeIps) - autoFigureOutBanRanges() ; - } - -#ifdef DEBUG_BANLIST - static rstime_t last_print = 0 ; - - if(now > 10+last_print) - { - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - printBanSet_locked(std::cerr); - last_print = now ; - } -#endif - - return 0; -} - -void p3BanList::getDhtInfo() -{ - // Get the list of masquerading peers from the DHT. Add them as potential IPs to be banned. - // Don't make them active. Just insert them in the list. - - std::list filtered_peers ; - - rsDht->getListOfBannedIps(filtered_peers) ; - -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::getDhtInfo() Got list of banned IPs." << std::endl; -#endif - RsPeerId ownId = mServiceCtrl->getOwnId(); - - for(std::list::const_iterator it(filtered_peers.begin());it!=filtered_peers.end();++it) - { -#ifdef DEBUG_BANLIST - std::cerr << " filtered peer: " << rs_inet_ntoa((*it).mAddr.sin_addr) << std::endl; -#endif - - int int_reason = RSBANLIST_REASON_DHT ; - int time_stamp = (*it).mLastSeen ; - - sockaddr_storage ad ; - sockaddr_storage_setipv4(ad,&(*it).mAddr) ; - - addBanEntry(ownId, ad, RSBANLIST_ORIGIN_SELF, int_reason, time_stamp); - } - - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - condenseBanSources_locked() ; -} - -/***** Implementation ******/ - -bool p3BanList::processIncoming() -{ - /* for each packet - pass to specific handler */ - RsItem *item = NULL; - bool updated = false; - while(NULL != (item = recvItem())) - { -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::processingIncoming() Received Item:"; - std::cerr << std::endl; - item->print(std::cerr); - std::cerr << std::endl; -#endif - switch(item->PacketSubType()) - { - default: - break; - case RS_PKT_SUBTYPE_BANLIST_ITEM: - { - // Order is important!. - updated = (recvBanItem((RsBanListItem *) item) || updated); - } - break; - } - - /* clean up */ - delete item; - } - - if (updated) - { - { - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - - condenseBanSources_locked(); - } - - /* pass list to NetAssist */ - - } - - return true ; -} - - -bool p3BanList::recvBanItem(RsBanListItem *item) -{ - bool updated = false; - - rstime_t now = time(NULL) ; - std::list::const_iterator it; - - for(it = item->peerList.mList.begin(); it != item->peerList.mList.end(); ++it) - { - // Order is important!. - updated = (addBanEntry(item->PeerId(), it->addr.addr, it->level, it->reason, now - it->age) || updated); - } - return updated; -} - -/* overloaded from pqiNetAssistSharePeer */ -void p3BanList::updatePeer( const RsPeerId& /*id*/, - const sockaddr_storage &dAddr, - int /*type*/, int /*reason*/, int time_stamp ) -{ - sockaddr_storage addr; sockaddr_storage_copy(dAddr, addr); - if(!sockaddr_storage_ipv6_to_ipv4(addr)) - { - std::cerr << __PRETTY_FUNCTION__ << " Cannot handle " - << sockaddr_storage_tostring(dAddr) - << " IPv6 not implemented yet!" - << std::endl; - return; - } - - RsPeerId ownId = mServiceCtrl->getOwnId(); - - int int_reason = RSBANLIST_REASON_DHT; - - addBanEntry(ownId, addr, RSBANLIST_ORIGIN_SELF, int_reason, time_stamp); - - /* process */ - { - RS_STACK_MUTEX(mBanMtx); - condenseBanSources_locked(); - } -} - -RsSerialiser *p3BanList::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - - rss->addSerialType(new RsBanListSerialiser()) ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss ; -} - -bool p3BanList::saveList(bool &cleanup, std::list& itemlist) -{ - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - - cleanup = true ; - - for(std::map::const_iterator it(mBanSources.begin());it!=mBanSources.end();++it) - { - RsBanListConfigItem *item = new RsBanListConfigItem ; - - item->banListType = RSBANLIST_TYPE_PEERLIST ; - item->banListPeerId = it->second.mPeerId ; - item->update_time = it->second.mLastUpdate ; - item->banned_peers.TlvClear() ; - - for(std::map::const_iterator it2 = it->second.mBanPeers.begin();it2!=it->second.mBanPeers.end();++it2) - { - RsTlvBanListEntry e ; - it2->second.toRsTlvBanListEntry(e) ; - - item->banned_peers.mList.push_back(e) ; - } - - itemlist.push_back(item) ; - } - - // Add whitelist - RsBanListConfigItem *item = new RsBanListConfigItem ; - - item->banListType = RSBANLIST_TYPE_WHITELIST ; - item->banListPeerId.clear() ; - item->update_time = 0 ; - item->banned_peers.TlvClear() ; - - for(std::map::const_iterator it2 = mWhiteListedRanges.begin();it2!=mWhiteListedRanges.end();++it2) - { - RsTlvBanListEntry e ; - it2->second.toRsTlvBanListEntry(e) ; - - item->banned_peers.mList.push_back(e) ; - } - - itemlist.push_back(item) ; - - // addblacklist - - item = new RsBanListConfigItem ; - - item->banListType = RSBANLIST_TYPE_BLACKLIST ; - item->banListPeerId.clear(); - item->update_time = 0 ; - item->banned_peers.TlvClear() ; - - for(std::map::const_iterator it2 = mBanRanges.begin();it2!=mBanRanges.end();++it2) - { - RsTlvBanListEntry e ; - it2->second.toRsTlvBanListEntry(e) ; - - item->banned_peers.mList.push_back(e) ; - } - - itemlist.push_back(item) ; - - // Other variables - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - - RsTlvKeyValue kv; - - kv.key = "IP_FILTERING_ENABLED"; - kv.value = mIPFilteringEnabled?"TRUE":"FALSE" ; - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "IP_FILTERING_AUTORANGE_IPS"; - kv.value = mAutoRangeIps?"TRUE":"FALSE" ; - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "IP_FILTERING_FRIEND_GATHERING_ENABLED"; - kv.value = mIPFriendGatheringEnabled?"TRUE":"FALSE" ; - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "IP_FILTERING_DHT_GATHERING_ENABLED"; - kv.value = mIPDHTGatheringEnabled?"TRUE":"FALSE" ; - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "IP_FILTERING_AUTORANGE_IPS_LIMIT" ; - std::ostringstream os ; - os << mAutoRangeLimit ; - os.flush() ; - kv.value = os.str() ; - vitem->tlvkvs.pairs.push_back(kv) ; - - itemlist.push_back(vitem) ; - - return true ; -} - -bool p3BanList::loadList(std::list& load) -{ - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - - for(std::list::const_iterator it(load.begin());it!=load.end();++it) - { - RsConfigKeyValueSet *vitem = dynamic_cast( *it ) ; - - if(vitem != NULL) - for(std::list::const_iterator it2(vitem->tlvkvs.pairs.begin());it2!=vitem->tlvkvs.pairs.end();++it2) - { - if(it2->key == "IP_FILTERING_ENABLED") mIPFilteringEnabled = (it2->value=="TRUE") ; - if(it2->key == "IP_FILTERING_AUTORANGE_IPS") mAutoRangeIps = (it2->value=="TRUE") ; - if(it2->key == "IP_FILTERING_FRIEND_GATHERING_ENABLED") mIPFriendGatheringEnabled = (it2->value=="TRUE") ; - if(it2->key == "IP_FILTERING_DHT_GATHERING_ENABLED") mIPDHTGatheringEnabled = (it2->value=="TRUE") ; - - if(it2->key == "IP_FILTERING_AUTORANGE_IPS_LIMIT") - { - int val ; - if(sscanf(it2->value.c_str(),"%d",&val) == 1) - mAutoRangeLimit = val ; - } - } - - RsBanListConfigItem *citem = dynamic_cast( *it ) ; - - if(citem != NULL) - { - if(citem->banListType == RSBANLIST_TYPE_PEERLIST) - { - BanList& bl(mBanSources[citem->banListPeerId]) ; - - bl.mPeerId = citem->banListPeerId ; - bl.mLastUpdate = citem->update_time ; - - bl.mBanPeers.clear() ; - - for(std::list::const_iterator it2(citem->banned_peers.mList.begin());it2!=citem->banned_peers.mList.end();++it2) - { - BanListPeer blp ; - blp.fromRsTlvBanListEntry(*it2) ; - - if(sockaddr_storage_isValidNet(blp.addr)) - bl.mBanPeers[blp.addr] = blp ; - else - std::cerr << "(WW) removed wrong address " << sockaddr_storage_iptostring(blp.addr) << std::endl; - } - } - else if(citem->banListType == RSBANLIST_TYPE_BLACKLIST) - { - mBanRanges.clear() ; - - for(std::list::const_iterator it2(citem->banned_peers.mList.begin());it2!=citem->banned_peers.mList.end();++it2) - { - BanListPeer blp ; - blp.fromRsTlvBanListEntry(*it2) ; - - if(sockaddr_storage_isValidNet(blp.addr)) - mBanRanges[makeBitsRange(blp.addr,blp.masked_bytes)] = blp ; - else - std::cerr << "(WW) removed wrong address " << sockaddr_storage_iptostring(blp.addr) << std::endl; - } - } - else if(citem->banListType == RSBANLIST_TYPE_WHITELIST) - { - mWhiteListedRanges.clear() ; - - for(std::list::const_iterator it2(citem->banned_peers.mList.begin());it2!=citem->banned_peers.mList.end();++it2) - { - BanListPeer blp ; - blp.fromRsTlvBanListEntry(*it2) ; - - if(sockaddr_storage_isValidNet(blp.addr)) - mWhiteListedRanges[makeBitsRange(blp.addr,blp.masked_bytes)] = blp ; - else - std::cerr << "(WW) removed wrong address " << sockaddr_storage_iptostring(blp.addr) << std::endl; - - std::cerr << "Read whitelisted range " << sockaddr_storage_iptostring(blp.addr) << "/" << 32 - 8*(blp.masked_bytes) << std::endl; - } - } - else - std::cerr << "(EE) BanList item unknown type " << citem->banListType << ". This is a bug." << std::endl; - } - - delete *it ; - } - - load.clear() ; - return true ; -} - -bool p3BanList::addBanEntry( const RsPeerId &peerId, - const sockaddr_storage &dAddr, - int level, uint32_t reason, rstime_t time_stamp ) -{ - sockaddr_storage addr; sockaddr_storage_copy(dAddr, addr); - if(!sockaddr_storage_ipv6_to_ipv4(addr)) - { - std::cerr << __PRETTY_FUNCTION__ << " Cannot handle " - << sockaddr_storage_tostring(dAddr) - << " IPv6 not implemented yet!" - << std::endl; - return false; - } - - RS_STACK_MUTEX(mBanMtx); - - rstime_t now = time(NULL); - bool updated = false; - -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::addBanEntry() Addr: " << sockaddr_storage_iptostring(addr) << " Origin: " << level; - std::cerr << " Reason: " << reason << " Age: " << now - time_stamp; - std::cerr << std::endl; -#endif - - /* Only Accept it - if external address */ - if (!sockaddr_storage_isExternalNet(addr)) - { -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::addBanEntry() Ignoring Non External Addr: " << sockaddr_storage_iptostring(addr); - std::cerr << std::endl; -#endif - return false; - } - - - std::map::iterator it; - it = mBanSources.find(peerId); - if (it == mBanSources.end()) - { - BanList bl; - bl.mPeerId = peerId; - bl.mLastUpdate = now; - mBanSources[peerId] = bl; - - it = mBanSources.find(peerId); - updated = true; - } - - // index is FAMILY + IP - the rest should be Zeros.. - struct sockaddr_storage bannedaddr; - sockaddr_storage_clear(bannedaddr); - bannedaddr.ss_family = AF_INET ; - sockaddr_storage_copyip(bannedaddr, addr); - sockaddr_storage_setport(bannedaddr, 0); - - std::map::iterator mit; - mit = it->second.mBanPeers.find(bannedaddr); - if (mit == it->second.mBanPeers.end()) - { - /* add in */ - BanListPeer blp; - blp.addr = addr; - blp.reason = reason; - blp.level = level; - blp.mTs = time_stamp ; - blp.masked_bytes = 0 ; - - it->second.mBanPeers[bannedaddr] = blp; - it->second.mLastUpdate = now; - updated = true; - } - else - { - /* see if it needs an update */ - if ((mit->second.reason != reason) || - (mit->second.level != uint32_t(level)) || - (mit->second.mTs < time_stamp)) - { - /* update */ - mit->second.addr = addr; - mit->second.reason = reason; - mit->second.level = level; - mit->second.mTs = time_stamp; - mit->second.masked_bytes = 0 ; - - it->second.mLastUpdate = now; - updated = true; - } - } - - if (updated) - IndicateConfigChanged() ; - - return updated; -} - -bool p3BanList::isWhiteListed_locked(const sockaddr_storage& addr) -{ - if(mWhiteListedRanges.find(makeBitsRange(addr,0)) != mWhiteListedRanges.end()) - return true ; - - if(mWhiteListedRanges.find(makeBitsRange(addr,1)) != mWhiteListedRanges.end()) - return true ; - - if(mWhiteListedRanges.find(makeBitsRange(addr,2)) != mWhiteListedRanges.end()) - return true ; - - return false ; - -} - -/*** - * EXTRA DEBUGGING. - * #define DEBUG_BANLIST_CONDENSE 1 - ***/ - -int p3BanList::condenseBanSources_locked() -{ - mBanSet.clear(); - - rstime_t now = time(NULL); - RsPeerId ownId = mServiceCtrl->getOwnId(); - -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::condenseBanSources_locked()"; - std::cerr << std::endl; -#endif - - std::map::const_iterator it; - for(it = mBanSources.begin(); it != mBanSources.end(); ++it) - { - if (now - it->second.mLastUpdate > RSBANLIST_ENTRY_MAX_AGE) - { -#ifdef DEBUG_BANLIST_CONDENSE - std::cerr << std::dec ; - std::cerr << "p3BanList::condenseBanSources_locked()"; - std::cerr << " Ignoring Out-Of-Date peer: " << it->first; - std::cerr << std::endl; -#endif - continue; - } - -#ifdef DEBUG_BANLIST_CONDENSE - std::cerr << std::dec ; - std::cerr << "p3BanList::condenseBanSources_locked()"; - std::cerr << " Condensing Info from peer: " << it->first; - std::cerr << std::endl; -#endif - - std::map::const_iterator lit; - for(lit = it->second.mBanPeers.begin(); lit != it->second.mBanPeers.end(); ++lit) - { - /* check timestamp */ - if (now > RSBANLIST_ENTRY_MAX_AGE + lit->second.mTs) - { -#ifdef DEBUG_BANLIST_CONDENSE - std::cerr << std::dec ; - std::cerr << "p3BanList::condenseBanSources_locked()"; - std::cerr << " Ignoring Out-Of-Date Entry for: "; - std::cerr << sockaddr_storage_iptostring(lit->second.addr); - std::cerr << " time stamp= " << lit->second.mTs << ", age=" << now - lit->second.mTs; - std::cerr << std::endl; -#endif - continue; - } - - uint32_t lvl = lit->second.level; - if (it->first != ownId) - { - /* as from someone else, increment level */ - lvl++; - } - - struct sockaddr_storage bannedaddr; - sockaddr_storage_clear(bannedaddr); - bannedaddr.ss_family = AF_INET; - sockaddr_storage_copyip(bannedaddr, lit->second.addr); - sockaddr_storage_setport(bannedaddr, 0); - - if (isWhiteListed_locked(bannedaddr)) - continue; - - /* check if it exists in the Set already */ - std::map::iterator sit; - sit = mBanSet.find(bannedaddr); - - if ((sit == mBanSet.end()) || (lvl < sit->second.level)) - { - BanListPeer bp = lit->second; - bp.level = lvl; - bp.masked_bytes = 0 ; - sockaddr_storage_setport(bp.addr, 0); - mBanSet[bannedaddr] = bp; -#ifdef DEBUG_BANLIST_CONDENSE - std::cerr << "p3BanList::condenseBanSources_locked()"; - std::cerr << " Added New Entry for: "; - std::cerr << sockaddr_storage_iptostring(bannedaddr); - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_BANLIST_CONDENSE - std::cerr << "p3BanList::condenseBanSources_locked()"; - std::cerr << " Merging Info for: "; - std::cerr << sockaddr_storage_iptostring(bannedaddr); - std::cerr << std::endl; -#endif - /* update if necessary */ - if (lvl == sit->second.level) - { - sit->second.reason |= lit->second.reason; - if (sit->second.mTs < lit->second.mTs) - { - sit->second.mTs = lit->second.mTs; - } - } - } - } - } - - -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::condenseBanSources_locked() Printing New Set:"; - std::cerr << std::endl; - - printBanSet_locked(std::cerr); -#endif - - return true ; -} - - - -int p3BanList::sendPackets() -{ - rstime_t now = time(NULL); - rstime_t pt; - { - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - pt = mSentListTime; - } - - if (now - pt > RSBANLIST_SEND_PERIOD) - { - sendBanLists(); - - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::sendPackets() Regular Broadcast"; - std::cerr << std::endl; - - printBanSources_locked(std::cerr); - printBanSet_locked(std::cerr); -#endif - - mSentListTime = now; - } - return true ; -} - -void p3BanList::sendBanLists() -{ - - /* we ping our peers */ - /* who is online? */ - std::set idList; - - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, idList); - -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::sendBanList()"; - std::cerr << std::endl; -#endif - - /* prepare packets */ - std::set::iterator it; - for(it = idList.begin(); it != idList.end(); ++it) - { -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::sendBanList() To: " << *it; - std::cerr << std::endl; -#endif - sendBanSet(*it); - } -} - -// Send all manually banned ranges to friends - -int p3BanList::sendBanSet(const RsPeerId& peerid) -{ - /* */ - RsBanListItem *item = new RsBanListItem(); - item->PeerId(peerid); - - //rstime_t now = time(NULL); - - { - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - std::map::iterator it; - for(it = mBanSet.begin(); it != mBanSet.end(); ++it) - { - if (it->second.level >= RSBANLIST_ORIGIN_FRIEND) - continue; // only share OWN for the moment. - - RsTlvBanListEntry bi; - it->second.toRsTlvBanListEntry(bi) ; - - bi.masked_bytes = 0 ; - bi.comment.clear() ; // don't send comments. - item->peerList.mList.push_back(bi); - } - } - - sendItem(item); - return 1; -} - - -int p3BanList::printBanSet_locked(std::ostream &out) -{ - rstime_t now = time(NULL); - - out << "p3BanList::printBanSet_locked()"; - out << " Only printing active filters (due to user options)."; - out << std::endl; - - std::map::iterator it; - for(it = mBanSet.begin(); it != mBanSet.end(); ++it) - if(acceptedBanSet_locked(it->second)) - { - out << "Ban: " << sockaddr_storage_iptostring(it->second.addr); - out << " Reason: " << it->second.reason; - out << " Level: " << it->second.level; - if (it->second.level > RSBANLIST_ORIGIN_FRIEND) - { - out << " (unused)"; - } - - out << " Age: " << now - it->second.mTs; - out << std::endl; - } - - std::cerr << "Current IP black list (only showing manual ranges, not automatically banned IPs): " << std::dec << std::endl; - - for(std::map::const_iterator it(mBanRanges.begin());it!=mBanRanges.end();++it) - if(acceptedBanRanges_locked(it->second)) - std::cerr << " " << sockaddr_storage_iptostring(it->first) << ". masked_bytes=" << (int)it->second.masked_bytes - << ", IP=" << sockaddr_storage_iptostring(it->second.addr) << "/" << ((int)32 - 8*(int)(it->second.masked_bytes)) << std::endl; - - std::cerr << "Current IP white list: " << std::endl; - - for(std::map::const_iterator it(mWhiteListedRanges.begin());it!=mWhiteListedRanges.end();++it) - if(acceptedBanRanges_locked(it->second)) - std::cerr << " " << sockaddr_storage_iptostring(it->first) << ". masked_bytes=" << (int)it->second.masked_bytes - << ", IP=" << sockaddr_storage_iptostring(it->second.addr) << "/" << ((int)32 - 8*(int)(it->second.masked_bytes)) << std::endl; - - return true ; -} - - - -int p3BanList::printBanSources_locked(std::ostream &out) -{ - rstime_t now = time(NULL); - - std::map::const_iterator it; - for(it = mBanSources.begin(); it != mBanSources.end(); ++it) - { - out << "BanList from: " << it->first; - out << " LastUpdate: " << now - it->second.mLastUpdate; - out << std::endl; - - std::map::const_iterator lit; - for(lit = it->second.mBanPeers.begin(); - lit != it->second.mBanPeers.end(); ++lit) - { - out << "\t"; - out << "Ban: " << sockaddr_storage_iptostring(lit->second.addr); - out << " Reason: " << lit->second.reason; - out << " Level: " << lit->second.level; - out << " Age: " << now - lit->second.mTs; - out << std::endl; - } - } - - return true ; -} - -RsBanList::~RsBanList() = default; diff --git a/libretroshare/src/services/p3banlist.h b/libretroshare/src/services/p3banlist.h deleted file mode 100644 index b61b7cb71..000000000 --- a/libretroshare/src/services/p3banlist.h +++ /dev/null @@ -1,166 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3banlist.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef SERVICE_RSBANLIST_HEADER -#define SERVICE_RSBANLIST_HEADER - -#include -#include -#include - -#include "rsitems/rsbanlistitems.h" -#include "services/p3service.h" -#include "retroshare/rsbanlist.h" - -class p3ServiceControl; -class p3NetMgr; - -class BanList -{ - public: - - RsPeerId mPeerId; /* from */ - rstime_t mLastUpdate; - std::map mBanPeers; -}; - -/** - * The RS BanList service. - * Exchange list of Banned IPv4 addresses with peers. - * - * @warning IPv4 only, IPv6 not supported yet! - */ -class p3BanList: public RsBanList, public p3Service, public pqiNetAssistPeerShare, public p3Config /*, public pqiMonitor */ -{ -public: - p3BanList(p3ServiceControl *sc, p3NetMgr *nm); - virtual RsServiceInfo getServiceInfo(); - - /***** overloaded from RsBanList *****/ - - /// @see RsBanList - virtual bool isAddressAccepted( - const sockaddr_storage& addr, uint32_t checking_flags, - uint32_t& check_result = RS_DEFAULT_STORAGE_PARAM(uint32_t) - ) override; - - virtual void getBannedIps(std::list& list) ; - virtual void getWhiteListedIps(std::list& list) ; - - virtual bool addIpRange( const sockaddr_storage& addr, int masked_bytes, - uint32_t list_type, const std::string& comment ); - virtual bool removeIpRange( const sockaddr_storage &addr, int masked_bytes, - uint32_t list_type ); - - virtual void enableIPFiltering(bool b) ; - virtual bool ipFilteringEnabled() ; - - virtual bool autoRangeEnabled() { return mAutoRangeIps ; } - virtual void enableAutoRange(bool b) ; - - virtual int autoRangeLimit() { return mAutoRangeLimit ; } - virtual void setAutoRangeLimit(int b) ; - - virtual void enableIPsFromFriends(bool b) ; - virtual bool IPsFromFriendsEnabled() { return mIPFriendGatheringEnabled ;} - - virtual void enableIPsFromDHT(bool b) ; - virtual bool iPsFromDHTEnabled() { return mIPDHTGatheringEnabled ;} - - /***** overloaded from pqiNetAssistPeerShare *****/ - - virtual void updatePeer( const RsPeerId& id, const sockaddr_storage &addr, - int type, int reason, int time_stamp ); - - /*********************** p3config ******************************/ - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool &cleanup, std::list& itemlist); - virtual bool loadList(std::list& load); - - /***** overloaded from p3Service *****/ - /*! - * This retrieves all chat msg items and also (important!) - * processes chat-status items that are in service item queue. chat msg item requests are also processed and not returned - * (important! also) notifications sent to notify base on receipt avatar, immediate status and custom status - * : notifyCustomState, notifyChatStatus, notifyPeerHasNewAvatar - * @see NotifyBase - - */ - virtual int tick(); - - int sendPackets(); - bool processIncoming(); - - bool recvBanItem(RsBanListItem *item); - bool addBanEntry( const RsPeerId &peerId, - const sockaddr_storage &addr, int level, uint32_t reason, - rstime_t time_stamp ); - void sendBanLists(); - int sendBanSet(const RsPeerId& peerid); - - - /*! - * Interface stuff. - */ - - /*************** pqiMonitor callback ***********************/ - //virtual void statusChange(const std::list &plist); - - - /************* from p3Config *******************/ - //virtual RsSerialiser *setupSerialiser() ; - //virtual bool saveList(bool& cleanup, std::list&) ; - //virtual void saveDone(); - //virtual bool loadList(std::list& load) ; - -private: - void getDhtInfo() ; - - RsMutex mBanMtx; - - bool acceptedBanSet_locked(const BanListPeer &blp); - bool acceptedBanRanges_locked(const BanListPeer &blp); - void autoFigureOutBanRanges(); - int condenseBanSources_locked(); - int printBanSources_locked(std::ostream &out); - int printBanSet_locked(std::ostream &out); - bool isWhiteListed_locked(const sockaddr_storage &addr); - - p3ServiceControl *mServiceCtrl; - //p3NetMgr *mNetMgr; - rstime_t mSentListTime; - std::map mBanSources; - std::map mBanSet; - std::map mBanRanges; - std::map mWhiteListedRanges; - - rstime_t mLastDhtInfoRequest ; - - uint32_t mAutoRangeLimit ; - bool mAutoRangeIps ; - - bool mIPFilteringEnabled ; - bool mIPFriendGatheringEnabled ; - bool mIPDHTGatheringEnabled ; -}; - -#endif // SERVICE_RSBANLIST_HEADER - diff --git a/libretroshare/src/services/p3bwctrl.cc b/libretroshare/src/services/p3bwctrl.cc deleted file mode 100644 index 65add3935..000000000 --- a/libretroshare/src/services/p3bwctrl.cc +++ /dev/null @@ -1,349 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3bwctrl.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" -#include "pqi/pqipersongrp.h" - -#include "util/rsnet.h" - -#include "services/p3bwctrl.h" -#include "rsitems/rsbwctrlitems.h" - -#include - -/**** - * #define DEBUG_BWCTRL 1 - ****/ - - -/************ IMPLEMENTATION NOTES ********************************* - * - */ - -p3BandwidthControl *rsBandwidthControl; - - -p3BandwidthControl::p3BandwidthControl(pqipersongrp *pg) - :p3Service(), mPg(pg), mBwMtx("p3BwCtrl") -{ - addSerialType(new RsBwCtrlSerialiser()); - - mLastCheck = 0; -} - - -const std::string BANDWIDTH_CTRL_APP_NAME = "bandwidth_ctrl"; -const uint16_t BANDWIDTH_CTRL_APP_MAJOR_VERSION = 1; -const uint16_t BANDWIDTH_CTRL_APP_MINOR_VERSION = 0; -const uint16_t BANDWIDTH_CTRL_MIN_MAJOR_VERSION = 1; -const uint16_t BANDWIDTH_CTRL_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3BandwidthControl::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_BWCTRL, - BANDWIDTH_CTRL_APP_NAME, - BANDWIDTH_CTRL_APP_MAJOR_VERSION, - BANDWIDTH_CTRL_APP_MINOR_VERSION, - BANDWIDTH_CTRL_MIN_MAJOR_VERSION, - BANDWIDTH_CTRL_MIN_MINOR_VERSION); -} - - - -int p3BandwidthControl::tick() -{ - processIncoming(); - - bool doCheck = false; - { - RsStackMutex stack(mBwMtx); /****** LOCKED MUTEX *******/ - -#define CHECK_PERIOD 5 - - rstime_t now = time(NULL); - if (now - mLastCheck > CHECK_PERIOD) - { - doCheck = true; - mLastCheck = now; - } - } - - if (doCheck) - { - checkAvailableBandwidth(); - } - - return 0; -} - -int p3BandwidthControl::status() -{ - return 1; -} - - -/***** Implementation ******/ - - -bool p3BandwidthControl::checkAvailableBandwidth() -{ - /* check each connection status */ - std::map rateMap; - RsBwRates total; - - mPg->ExtractRates(rateMap, total); - std::map::iterator it; - std::map::iterator bit; - - /* have to merge with existing list, - * erasing as we go ... then any left have to deal with - */ - RsStackMutex stack(mBwMtx); /****** LOCKED MUTEX *******/ - - mTotalRates = total; - - rstime_t now = time(NULL); - std::list oldIds; // unused for now! - - for(bit = mBwMap.begin(); bit != mBwMap.end(); ++bit) - { - /* check alloc rate */ - //rstime_t age = now - bit->second.mLastSend; - - /* find a matching entry */ - it = rateMap.find(bit->first); - if (it == rateMap.end()) - { - oldIds.push_back(bit->first); - continue; - } - - //float delta = bit->second.mAllocated - it->second.mMaxRateIn; - /* if delta < 0 ... then need update (or else we get a queue) */ - /* if delta > 0 ... then need update (to allow more data) */ - - /* for the moment - always send an update */ - bool updatePeer = true; - -#if 0 - /* if changed significantly */ - if (sig) - { - updatePeer = true; - } - - /* if changed small but old */ - if ((any change) && (timeperiod)) - { - updatePeer = true; - } -#endif - - /* update rates info */ - bit->second.mRates = it->second; - bit->second.mRateUpdateTs = now; - - if (updatePeer) - { -#define ALLOC_FACTOR (1.0) - // save value sent, - bit->second.mAllocated = ALLOC_FACTOR * 1000.0 * it->second.mMaxRateIn; - bit->second.mLastSend = now; - - RsBwCtrlAllowedItem *item = new RsBwCtrlAllowedItem(); - item->PeerId(bit->first); - item->allowedBw = bit->second.mAllocated; - - sendItem(item); - } - - /* now cleanup */ - rateMap.erase(it); - } - - //printRateInfo_locked(std::cerr); - - /* any left over rateMaps ... are bad! (or not active - more likely) */ - return true; -} - - - -bool p3BandwidthControl::processIncoming() -{ - RsItem *item = NULL; - rstime_t now = time(NULL); - - while(NULL != (item = recvItem())) - { - RsBwCtrlAllowedItem *bci = dynamic_cast(item); - if (!bci) - { - delete item; - continue; - } - - /* For each packet */ - RsStackMutex stack(mBwMtx); /****** LOCKED MUTEX *******/ - std::map::iterator bit; - - bit = mBwMap.find(bci->PeerId()); - if (bit == mBwMap.end()) - { - // ERROR. - delete item; - continue; - } - - /* update allowed bandwidth */ - bit->second.mAllowedOut = bci->allowedBw; - bit->second.mLastRecvd = now; - delete item; - - /* store info in data */ - //mPg->setAllowedRate(bit->first, bit->second.mAllowedOut / 1000.0); - } - return true; -} - -int p3BandwidthControl::getTotalBandwidthRates(RsConfigDataRates &rates) -{ - RsStackMutex stack(mBwMtx); /****** LOCKED MUTEX *******/ - - rates.mRateIn = mTotalRates.mRateIn; - rates.mRateMaxIn = mTotalRates.mMaxRateIn; - rates.mRateOut = mTotalRates.mRateOut; - rates.mRateMaxOut = mTotalRates.mMaxRateOut; - - rates.mAllocIn = 0; - rates.mAllocTs = 0; - - rates.mAllowedOut = 0; - rates.mAllowedTs = 0; - - rates.mQueueIn = mTotalRates.mQueueIn; - rates.mQueueOut = mTotalRates.mQueueOut; - - return 1; -} - -int p3BandwidthControl::getAllBandwidthRates(std::map &ratemap) -{ - RsStackMutex stack(mBwMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator bit; - for(bit = mBwMap.begin(); bit != mBwMap.end(); ++bit) - { - RsConfigDataRates rates; - - rates.mRateIn = bit->second.mRates.mRateIn; - rates.mRateMaxIn = bit->second.mRates.mMaxRateIn; - rates.mRateOut = bit->second.mRates.mRateOut; - rates.mRateMaxOut = bit->second.mRates.mMaxRateOut; - - rates.mAllocIn = bit->second.mAllocated / 1000.0; - rates.mAllocTs = bit->second.mLastSend; - - rates.mAllowedOut = bit->second.mAllowedOut / 1000.0; - rates.mAllowedTs = bit->second.mLastRecvd; - - rates.mQueueIn = bit->second.mRates.mQueueIn; - rates.mQueueOut = bit->second.mRates.mQueueOut; - - ratemap[bit->first] = rates; - } - return true ; - - -} - -int p3BandwidthControl::ExtractTrafficInfo(std::list& out_stats, std::list& in_stats) -{ - return mPg->ExtractTrafficInfo(out_stats,in_stats) ; -} - - - - - - -int p3BandwidthControl::printRateInfo_locked(std::ostream &out) -{ - out << "p3BandwidthControl::printRateInfo_locked()"; - out << std::endl; - - //rstime_t now = time(NULL); - out << "Totals: "; - out << " In: " << mTotalRates.mRateIn; - out << " MaxIn: " << mTotalRates.mMaxRateIn; - out << " Out: " << mTotalRates.mRateOut; - out << " MaxOut: " << mTotalRates.mMaxRateOut; - out << std::endl; - - std::map::iterator bit; - for(bit = mBwMap.begin(); bit != mBwMap.end(); ++bit) - { - out << "\t" << bit->first; - out << " In: " << bit->second.mRates.mRateIn; - out << " MaxIn: " << bit->second.mRates.mMaxRateIn; - out << " Out: " << bit->second.mRates.mRateOut; - out << " MaxOut: " << bit->second.mRates.mMaxRateOut; - out << std::endl; - } - return true ; -} - - /*************** pqiMonitor callback ***********************/ -void p3BandwidthControl::statusChange(const std::list &plist) -{ - std::list::const_iterator it; - for (it = plist.begin(); it != plist.end(); ++it) - { - RsStackMutex stack(mBwMtx); /****** LOCKED MUTEX *******/ - - if (it->actions & RS_SERVICE_PEER_DISCONNECTED) - { - /* remove from map */ - std::map::iterator bit; - bit = mBwMap.find(it->id); - if (bit == mBwMap.end()) - { - std::cerr << "p3BandwidthControl::statusChange() ERROR"; - std::cerr << " Entry not in map"; - std::cerr << std::endl; - } - else - { - mBwMap.erase(bit); - } - } - else if (it->actions & RS_SERVICE_PEER_CONNECTED) - { - /* stuff */ - BwCtrlData data; - mBwMap[it->id] = data; - } - } - return; -} - - diff --git a/libretroshare/src/services/p3bwctrl.h b/libretroshare/src/services/p3bwctrl.h deleted file mode 100644 index bd6276d5f..000000000 --- a/libretroshare/src/services/p3bwctrl.h +++ /dev/null @@ -1,126 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3bwctrl.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef SERVICE_RSBANDWIDTH_CONTROL_HEADER -#define SERVICE_RSBANDWIDTH_CONTROL_HEADER - -#include -#include -#include - -#include "rsitems/rsbwctrlitems.h" -#include "services/p3service.h" -#include "pqi/pqiservicemonitor.h" -#include "retroshare/rsconfig.h" // for datatypes. - -class pqipersongrp; - -// Extern is defined here - as this is bundled with rsconfig.h -class p3BandwidthControl; -extern p3BandwidthControl *rsBandwidthControl; - - -class BwCtrlData -{ - public: - BwCtrlData() - :mRateUpdateTs(0), mAllocated(0), mLastSend(0), mAllowedOut(0), mLastRecvd(0) - { return; } - - /* Rates are floats in KB/s */ - RsBwRates mRates; - rstime_t mRateUpdateTs; - - /* these are integers (B/s) */ - uint32_t mAllocated; - rstime_t mLastSend; - - uint32_t mAllowedOut; - rstime_t mLastRecvd; -}; - - -//!The RS bandwidth Control Service. - /** - * - * Exchange packets to regulate p2p bandwidth. - * - * Sadly this has to be strongly integrated into pqi, with ref to pqipersongrp. - */ - -class p3BandwidthControl: public p3Service, public pqiServiceMonitor -{ - public: - explicit p3BandwidthControl(pqipersongrp *pg); - virtual RsServiceInfo getServiceInfo(); - - /***** overloaded from RsBanList *****/ - - - /***** overloaded from p3Service *****/ - /*! - * This retrieves all BwCtrl items - */ - virtual int tick(); - virtual int status(); - - - /***** for RsConfig (not directly overloaded) ****/ - - virtual int getTotalBandwidthRates(RsConfigDataRates &rates); - virtual int getAllBandwidthRates(std::map &ratemap); - - - virtual int ExtractTrafficInfo(std::list &out_stats, std::list &in_stats); - - /*! - * Interface stuff. - */ - - /*************** pqiMonitor callback ***********************/ - virtual void statusChange(const std::list &plist); - - - /************* from p3Config *******************/ - //virtual RsSerialiser *setupSerialiser() ; - //virtual bool saveList(bool& cleanup, std::list&) ; - //virtual void saveDone(); - //virtual bool loadList(std::list& load) ; - -private: - - bool checkAvailableBandwidth(); - bool processIncoming(); - - pqipersongrp *mPg; - - RsMutex mBwMtx; - - int printRateInfo_locked(std::ostream &out); - - rstime_t mLastCheck; - - RsBwRates mTotalRates; - std::map mBwMap; - -}; - -#endif // SERVICE_RSBANDWIDTH_CONTROL_HEADER diff --git a/libretroshare/src/services/p3gxschannels.cc b/libretroshare/src/services/p3gxschannels.cc deleted file mode 100644 index 1ee9f6d75..000000000 --- a/libretroshare/src/services/p3gxschannels.cc +++ /dev/null @@ -1,2738 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxschannels.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#include "services/p3gxschannels.h" -#include "rsitems/rsgxschannelitems.h" -#include "util/radix64.h" -#include "util/rsmemory.h" - -#include -#include - - -#include "retroshare/rsgxsflags.h" -#include "retroshare/rsfiles.h" -#include "retroshare/rspeers.h" - -#include "rsserver/p3face.h" -#include "retroshare/rsnotify.h" - -#include -#include -#include - -// For Dummy Msgs. -#include "util/rsrandom.h" -#include "util/rsstring.h" - -#ifdef RS_DEEP_CHANNEL_INDEX -# include "deep_search/channelsindex.hpp" -#endif // RS_DEEP_CHANNEL_INDEX - - -/**** - * #define GXSCHANNEL_DEBUG 1 - ****/ - -/*extern*/ RsGxsChannels* rsGxsChannels = nullptr; - - -#define GXSCHANNEL_STOREPERIOD (3600 * 24 * 30) - -#define GXSCHANNELS_SUBSCRIBED_META 1 -#define GXSCHANNELS_UNPROCESSED_SPECIFIC 2 -#define GXSCHANNELS_UNPROCESSED_GENERIC 3 - -#define CHANNEL_PROCESS 0x0001 -#define CHANNEL_TESTEVENT_DUMMYDATA 0x0002 -#define DUMMYDATA_PERIOD 60 // Long enough for some RsIdentities to be generated. - -#define CHANNEL_DOWNLOAD_PERIOD (3600 * 24 * 7) -#define CHANNEL_MAX_AUTO_DL (8 * 1024 * 1024 * 1024ull) // 8 GB. Just a security ;-) -#define CHANNEL_UNUSED_BY_FRIENDS_DELAY (3600*24*60) // Two months. Will be used to delete a channel if too old -#define CHANNEL_DELAY_FOR_CHECKING_AND_DELETING_OLD_GROUPS 300 // check for old channels every 30 mins. Far too often than above delay by RS needs to run it at least once per session - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3GxsChannels::p3GxsChannels( - RsGeneralDataService *gds, RsNetworkExchangeService *nes, - RsGixs* gixs ) : - RsGenExchange( gds, nes, new RsGxsChannelSerialiser(), - RS_SERVICE_GXS_TYPE_CHANNELS, gixs, channelsAuthenPolicy() ), - RsGxsChannels(static_cast(*this)), GxsTokenQueue(this), - mSubscribedGroupsMutex("GXS channels subscribed groups cache"), - mKnownChannelsMutex("GXS channels known channels timestamp cache") -#ifdef TO_REMOVE - mSearchCallbacksMapMutex("GXS channels search callbacks map"), - mDistantChannelsCallbacksMapMutex("GXS channels distant channels callbacks map") -#endif -{ - // For Dummy Msgs. - mGenActive = false; - mLastDistantSearchNotificationTS = 0; - mCommentService = new p3GxsCommentService(this, RS_SERVICE_GXS_TYPE_CHANNELS); - - // This is not needed since it just loads all channel data ever 5 mins which takes a lot - // of useless CPU/memory. - // - RsTickEvent::schedule_in(CHANNEL_PROCESS, 0); - // - // Test Data disabled in repo. - // - // RsTickEvent::schedule_in(CHANNEL_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD); - - mGenToken = 0; - mGenCount = 0; -} - - -const std::string GXS_CHANNELS_APP_NAME = "gxschannels"; -const uint16_t GXS_CHANNELS_APP_MAJOR_VERSION = 1; -const uint16_t GXS_CHANNELS_APP_MINOR_VERSION = 0; -const uint16_t GXS_CHANNELS_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_CHANNELS_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3GxsChannels::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_CHANNELS, - GXS_CHANNELS_APP_NAME, - GXS_CHANNELS_APP_MAJOR_VERSION, - GXS_CHANNELS_APP_MINOR_VERSION, - GXS_CHANNELS_MIN_MAJOR_VERSION, - GXS_CHANNELS_MIN_MINOR_VERSION); -} - - -uint32_t p3GxsChannels::channelsAuthenPolicy() -{ - uint32_t policy = 0; - uint32_t flag = 0; - - flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - flag |= GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -static const uint32_t GXS_CHANNELS_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months -static const uint8_t GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ; - -struct RsGxsChannelNotifyRecordsItem: public RsItem -{ - - RsGxsChannelNotifyRecordsItem() - : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG,GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD) - {} - - virtual ~RsGxsChannelNotifyRecordsItem() {} - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { RS_SERIAL_PROCESS(records); } - - void clear() {} - - std::map records; -}; - -class GxsChannelsConfigSerializer : public RsServiceSerializer -{ -public: - GxsChannelsConfigSerializer() : RsServiceSerializer(RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG) {} - virtual ~GxsChannelsConfigSerializer() {} - - RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const - { - if(service_id != RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG) - return NULL; - - switch(item_sub_id) - { - case GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsChannelNotifyRecordsItem(); - default: - return NULL; - } - } -}; - -bool p3GxsChannels::saveList(bool &cleanup, std::list&saveList) -{ - cleanup = true ; - - RsGxsChannelNotifyRecordsItem *item = new RsGxsChannelNotifyRecordsItem ; - - { - RS_STACK_MUTEX(mKnownChannelsMutex); - item->records = mKnownChannels; - } - - saveList.push_back(item) ; - return true; -} - -bool p3GxsChannels::loadList(std::list& loadList) -{ - while(!loadList.empty()) - { - RsItem *item = loadList.front(); - loadList.pop_front(); - - rstime_t now = time(NULL); - - RsGxsChannelNotifyRecordsItem *fnr = dynamic_cast(item) ; - - if(fnr) - { - RS_STACK_MUTEX(mKnownChannelsMutex); - mKnownChannels.clear(); - - for(auto it(fnr->records.begin());it!=fnr->records.end();++it) - if(now < it->second + GXS_CHANNELS_CONFIG_MAX_TIME_NOTIFY_STORAGE) - mKnownChannels.insert(*it) ; - } - - delete item ; - } - return true; -} - -RsSerialiser* p3GxsChannels::setupSerialiser() -{ - RsSerialiser* rss = new RsSerialiser; - rss->addSerialType(new GxsChannelsConfigSerializer()); - - return rss; -} - - - /** Overloaded to cache new groups **/ -RsGenExchange::ServiceCreate_Return p3GxsChannels::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& /* keySet */) -{ - updateSubscribedGroup(grpItem->meta); - return SERVICE_CREATE_SUCCESS; -} - - -void p3GxsChannels::notifyChanges(std::vector &changes) -{ -#ifdef GXSCHANNEL_DEBUG - RsDbg() << " Processing " << changes.size() << " channel changes..." << std::endl; -#endif - /* iterate through and grab any new messages */ - std::set unprocessedGroups; - - std::vector::iterator it; - for(it = changes.begin(); it != changes.end(); ++it) - { - RsGxsMsgChange *msgChange = dynamic_cast(*it); - - if (msgChange) - { - if (msgChange->getType() == RsGxsNotify::TYPE_RECEIVED_NEW|| msgChange->getType() == RsGxsNotify::TYPE_PUBLISHED) - { - /* message received */ - if (rsEvents) - { - auto ev = std::make_shared(); - - ev->mChannelMsgId = msgChange->mMsgId; - ev->mChannelGroupId = msgChange->mGroupId; - - if(nullptr != dynamic_cast(msgChange->mNewMsgItem)) - ev->mChannelEventCode = RsChannelEventCode::NEW_COMMENT; - else - if(nullptr != dynamic_cast(msgChange->mNewMsgItem)) - ev->mChannelEventCode = RsChannelEventCode::NEW_VOTE; - else - ev->mChannelEventCode = RsChannelEventCode::NEW_MESSAGE; - - rsEvents->postEvent(ev); - } - } - - if (!msgChange->metaChange()) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::notifyChanges() Found Message Change Notification"; - std::cerr << std::endl; -#endif - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::notifyChanges() Msgs for Group: " << mit->first; - std::cerr << std::endl; -#endif - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::notifyChanges() AutoDownload for Group: " << mit->first; - std::cerr << std::endl; -#endif - - /* problem is most of these will be comments and votes, should make it occasional - every 5mins / 10minutes TODO */ - // We do not call if(autoDownLoadEnabled()) here, because it would be too costly when - // many msgs are received from the same group. We back the groupIds and then request one by one. - - unprocessedGroups.insert(msgChange->mGroupId); - } - } - } - - RsGxsGroupChange *grpChange = dynamic_cast(*it); - - if (grpChange && rsEvents) - { -#ifdef GXSCHANNEL_DEBUG - RsDbg() << " Grp Change Event or type " << grpChange->getType() << ":" << std::endl; -#endif - - switch (grpChange->getType()) - { - case RsGxsNotify::TYPE_PROCESSED: // happens when the group is subscribed - { - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::SUBSCRIBE_STATUS_CHANGED; - rsEvents->postEvent(ev); - - unprocessedGroups.insert(grpChange->mGroupId); - } - break; - - case RsGxsNotify::TYPE_GROUP_SYNC_PARAMETERS_UPDATED: - { - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::SYNC_PARAMETERS_UPDATED; - rsEvents->postEvent(ev); - - unprocessedGroups.insert(grpChange->mGroupId); - } - break; - - case RsGxsNotify::TYPE_STATISTICS_CHANGED: - { - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::STATISTICS_CHANGED; - rsEvents->postEvent(ev); - - // also update channel usage. Statistics are updated when a friend sends some sync packets - RS_STACK_MUTEX(mKnownChannelsMutex); - mKnownChannels[grpChange->mGroupId] = time(NULL); - IndicateConfigChanged(); - } - break; - - case RsGxsNotify::TYPE_UPDATED: - { - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::UPDATED_CHANNEL; - rsEvents->postEvent(ev); - - unprocessedGroups.insert(grpChange->mGroupId); - } - break; - - case RsGxsNotify::TYPE_PUBLISHED: - case RsGxsNotify::TYPE_RECEIVED_NEW: - { - /* group received or updated */ - - bool unknown ; - { - RS_STACK_MUTEX(mKnownChannelsMutex); - - unknown = (mKnownChannels.find(grpChange->mGroupId) == mKnownChannels.end()); - mKnownChannels[grpChange->mGroupId] = time(NULL); - IndicateConfigChanged(); - } - -#ifdef GXSCHANNEL_DEBUG - RsDbg() << " Type = Published/New " << std::endl; -#endif - if(unknown) - { -#ifdef GXSCHANNEL_DEBUG - RsDbg() << " Status: unknown. Sending notification event." << std::endl; -#endif - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::NEW_CHANNEL; - rsEvents->postEvent(ev); - } -#ifdef GXSCHANNEL_DEBUG - else - RsDbg() << " Not notifying already known channel " << grpChange->mGroupId << std::endl; -#endif - - unprocessedGroups.insert(grpChange->mGroupId); - } - break; - - case RsGxsNotify::TYPE_GROUP_DELETED: - { - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::DELETED_CHANNEL; - rsEvents->postEvent(ev); - - unprocessedGroups.insert(grpChange->mGroupId); - } - break; - - case RsGxsNotify::TYPE_RECEIVED_PUBLISHKEY: - { - /* group received */ - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::RECEIVED_PUBLISH_KEY; - - rsEvents->postEvent(ev); - - unprocessedGroups.insert(grpChange->mGroupId); - } - break; - - default: - RsErr() << " Got a GXS event of type " << grpChange->getType() << " Currently not handled." << std::endl; - break; - } - } - - /* shouldn't need to worry about groups - as they need to be subscribed to */ - delete *it; - } - - std::list grps; - for(auto& grp_id:unprocessedGroups) - grps.push_back(grp_id); - - if(!grps.empty()) - request_SpecificSubscribedGroups(grps); -} - -void p3GxsChannels::service_tick() -{ - static rstime_t last_dummy_tick = 0; - rstime_t now = time(NULL); - - if (time(NULL) > last_dummy_tick + 5) - { - dummy_tick(); - last_dummy_tick = now; - } - - RsTickEvent::tick_events(); - GxsTokenQueue::checkRequests(); - - mCommentService->comment_tick(); - - // Notify distant search results, not more than once per sec. Normally we should - // rather send one item for all, but that needs another class type - - if(now > mLastDistantSearchNotificationTS+2 && !mSearchResultsToNotify.empty()) - { - auto ev = std::make_shared(); - ev->mSearchResultsMap = mSearchResultsToNotify; - - mLastDistantSearchNotificationTS = now; - mSearchResultsToNotify.clear(); - - rsEvents->postEvent(ev); - } -} - -bool p3GxsChannels::service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) -{ -#ifdef GXSFORUMS_CHANNELS - std::cerr << "p3gxsChannels: Checking unused channel: called by GxsCleaning." << std::endl; -#endif - - // request all group infos at once - - rstime_t now = time(nullptr); - - RS_STACK_MUTEX(mKnownChannelsMutex); - - auto it = mKnownChannels.find(meta.mGroupId); - bool unknown_channel = it == mKnownChannels.end(); - -#ifdef GXSFORUMS_CHANNELS - std::cerr << " Channel " << meta.mGroupId ; -#endif - - if(unknown_channel) - { - // This case should normally not happen. It does because this channel was never registered since it may - // arrived before this code was here - -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". Not known yet. Adding current time as new TS." << std::endl; -#endif - mKnownChannels[meta.mGroupId] = now; - IndicateConfigChanged(); - - return true; - } - else - { - bool used_by_friends = (now < it->second + CHANNEL_UNUSED_BY_FRIENDS_DELAY); - bool subscribed = static_cast(meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED); - -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". subscribed: " << subscribed << ", used_by_friends: " << used_by_friends << " last TS: " << now - it->second << " secs ago (" << (now-it->second)/86400 << " days)"; -#endif - - if(!subscribed && !used_by_friends) - { -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". Scheduling for deletion" << std::endl; -#endif - return false; - } - else - { -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". Keeping!" << std::endl; -#endif - return true; - } - } -} - -bool p3GxsChannels::getGroupData(const uint32_t &token, std::vector &groups) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::getGroupData()"; - std::cerr << std::endl; -#endif - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsChannelGroupItem* item = dynamic_cast(*vit); - if (item) - { - RsGxsChannelGroup grp; - item->toChannelGroup(grp, true); - delete item; - groups.push_back(grp); - } - else - { - std::cerr << "p3GxsChannels::getGroupData() ERROR in decode"; - std::cerr << std::endl; - delete(*vit); - } - } - } - else - { - std::cerr << "p3GxsChannels::getGroupData() ERROR in request"; - std::cerr << std::endl; - } - - return ok; -} - -bool p3GxsChannels::groupShareKeys( - const RsGxsGroupId &groupId, const std::set& peers ) -{ - RsGenExchange::shareGroupPublishKey(groupId,peers); - return true; -} - - -/* Okay - chris is not going to be happy with this... - * but I can't be bothered with crazy data structures - * at the moment - fix it up later - */ - -bool p3GxsChannels::getPostData( const uint32_t& token, std::vector& msgs, - std::vector& cmts, - std::vector& vots) -{ -#ifdef GXSCHANNELS_DEBUG - RsDbg() << __PRETTY_FUNCTION__ << std::endl; -#endif - - GxsMsgDataMap msgData; - if(!RsGenExchange::getMsgData(token, msgData)) - { - RsErr() << __PRETTY_FUNCTION__ << " ERROR in request" << std::endl; - return false; - } - - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsChannelPostItem* postItem = - dynamic_cast(*vit); - - if(postItem) - { - RsGxsChannelPost msg; - postItem->toChannelPost(msg, true); - msgs.push_back(msg); - delete postItem; - } - else - { - RsGxsCommentItem* cmtItem = - dynamic_cast(*vit); - if(cmtItem) - { - RsGxsComment cmt; - RsGxsMsgItem *mi = (*vit); - cmt = cmtItem->mMsg; - cmt.mMeta = mi->meta; -#ifdef GXSCOMMENT_DEBUG - RsDbg() << __PRETTY_FUNCTION__ << " Found Comment:" << std::endl; - cmt.print(std::cerr," ", "cmt"); -#endif - cmts.push_back(cmt); - delete cmtItem; - } - else - { - RsGxsVoteItem* votItem = - dynamic_cast(*vit); - if(votItem) - { - RsGxsVote vot; - RsGxsMsgItem *mi = (*vit); - vot = votItem->mMsg; - vot.mMeta = mi->meta; - vots.push_back(vot); - delete votItem; - } - else - { - RsGxsMsgItem* msg = (*vit); - //const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS = 0x0217; - //const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM = 0x03; - //const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM = 0xf1; - //const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_VOTE_ITEM = 0xf2; - RsErr() << __PRETTY_FUNCTION__ - << " Not a GxsChannelPostItem neither a " - << "RsGxsCommentItem neither a RsGxsVoteItem" - << " PacketService=" << std::hex << (int)msg->PacketService() << std::dec - << " PacketSubType=" << std::hex << (int)msg->PacketSubType() << std::dec - << " type name =" << typeid(*msg).name() - << " , deleting!" << std::endl; - delete *vit; - } - } - } - } - } - - return true; -} - -bool p3GxsChannels::getPostData( - const uint32_t& token, std::vector& posts, std::vector& cmts ) -{ - std::vector vots; - return getPostData(token, posts, cmts, vots); -} - -bool p3GxsChannels::getPostData( - const uint32_t& token, std::vector& posts ) -{ - std::vector cmts; - std::vector vots; - return getPostData(token, posts, cmts, vots); -} - -//Not currently used -/*bool p3GxsChannels::getRelatedPosts(const uint32_t &token, std::vector &msgs) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::getRelatedPosts()"; - std::cerr << std::endl; -#endif - - GxsMsgRelatedDataMap msgData; - bool ok = RsGenExchange::getMsgRelatedData(token, msgData); - - if(ok) - { - GxsMsgRelatedDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsChannelPostItem* item = dynamic_cast(*vit); - - if(item) - { - RsGxsChannelPost msg; - item->toChannelPost(msg, true); - msgs.push_back(msg); - delete item; - } - else - { - RsGxsCommentItem* cmt = dynamic_cast(*vit); - if(!cmt) - { - RsGxsMsgItem* msg = (*vit); - //const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS = 0x0217; - //const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM = 0x03; - //const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM = 0xf1; - std::cerr << "Not a GxsChannelPostItem neither a RsGxsCommentItem" - << " PacketService=" << std::hex << (int)msg->PacketService() << std::dec - << " PacketSubType=" << std::hex << (int)msg->PacketSubType() << std::dec - << " , deleting!" << std::endl; - } - delete *vit; - } - } - } - } - else - { - std::cerr << "p3GxsChannels::getRelatedPosts() ERROR in request"; - std::cerr << std::endl; - } - - return ok; -}*/ - - -/********************************************************************************************/ -/********************************************************************************************/ - -bool p3GxsChannels::setChannelAutoDownload(const RsGxsGroupId &groupId, bool enabled) -{ - return setAutoDownload(groupId, enabled); -} - - -bool p3GxsChannels::getChannelAutoDownload(const RsGxsGroupId &groupId, bool& enabled) -{ - return autoDownloadEnabled(groupId,enabled); -} - -bool p3GxsChannels::setChannelDownloadDirectory( - const RsGxsGroupId &groupId, const std::string& directory ) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " id: " << groupId << " to: " - << directory << std::endl; -#endif - - RS_STACK_MUTEX(mSubscribedGroupsMutex); - - std::map::iterator it; - it = mSubscribedGroups.find(groupId); - if (it == mSubscribedGroups.end()) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Unknown groupId: " - << groupId.toStdString() << std::endl; - return false; - } - - /* extract from ServiceString */ - GxsChannelGroupInfo ss; - ss.load(it->second.mServiceString); - - if (directory == ss.mDownloadDirectory) - { - std::cerr << __PRETTY_FUNCTION__ << " Warning! groupId: " << groupId - << " Was already configured to download into: " << directory - << std::endl; - return false; - } - - ss.mDownloadDirectory = directory; - std::string serviceString = ss.save(); - uint32_t token; - - it->second.mServiceString = serviceString; // update Local Cache. - RsGenExchange::setGroupServiceString(token, groupId, serviceString); // update dbase. - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Feiled setting group " - << " service string" << std::endl; - return false; - } - - /* now reload it */ - std::list groups; - groups.push_back(groupId); - - request_SpecificSubscribedGroups(groups); - - return true; -} - -bool p3GxsChannels::getChannelDownloadDirectory(const RsGxsGroupId & groupId,std::string& directory) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::getChannelDownloadDirectory(" << id << ")" << std::endl; -#endif - - RS_STACK_MUTEX(mSubscribedGroupsMutex); - - std::map::iterator it; - - it = mSubscribedGroups.find(groupId); - if (it == mSubscribedGroups.end()) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Unknown groupId: " - << groupId.toStdString() << std::endl; - return false; - } - - /* extract from ServiceString */ - GxsChannelGroupInfo ss; - ss.load(it->second.mServiceString); - directory = ss.mDownloadDirectory; - - return true; -} - -void p3GxsChannels::request_AllSubscribedGroups() -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::request_SubscribedGroups()"; - std::cerr << std::endl; -#endif // GXSCHANNELS_DEBUG - - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, GXSCHANNELS_SUBSCRIBED_META); - -//#define PERIODIC_ALL_PROCESS 300 // This -// RsTickEvent::schedule_in(CHANNEL_PROCESS, PERIODIC_ALL_PROCESS); -} - - -void p3GxsChannels::request_SpecificSubscribedGroups( const std::list &groups ) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::request_SpecificSubscribedGroups()"; - std::cerr << std::endl; -#endif // GXSCHANNELS_DEBUG - - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - - uint32_t token = 0; - - if(!RsGenExchange::getTokenService()-> requestGroupInfo(token, ansType, opts, groups)) - { - std::cerr << __PRETTY_FUNCTION__ << " Failed requesting groups info!" - << std::endl; - return; - } - - if(!GxsTokenQueue::queueRequest(token, GXSCHANNELS_SUBSCRIBED_META)) - { - std::cerr << __PRETTY_FUNCTION__ << " Failed queuing request!" - << std::endl; - } -} - - -void p3GxsChannels::load_SubscribedGroups(const uint32_t &token) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::load_SubscribedGroups()"; - std::cerr << std::endl; -#endif // GXSCHANNELS_DEBUG - - std::list groups; - std::list groupList; - - getGroupMeta(token, groups); - - std::list::iterator it; - for(it = groups.begin(); it != groups.end(); ++it) - { - if (it->mSubscribeFlags & - (GXS_SERV::GROUP_SUBSCRIBE_ADMIN | - GXS_SERV::GROUP_SUBSCRIBE_PUBLISH | - GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED )) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::load_SubscribedGroups() updating Subscribed Group: " << it->mGroupId; - std::cerr << std::endl; -#endif - - updateSubscribedGroup(*it); - bool enabled = false ; - - if (autoDownloadEnabled(it->mGroupId,enabled) && enabled) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::load_SubscribedGroups() remembering AutoDownload Group: " << it->mGroupId; - std::cerr << std::endl; -#endif - groupList.push_back(it->mGroupId); - } - } - else - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::load_SubscribedGroups() clearing unsubscribed Group: " << it->mGroupId; - std::cerr << std::endl; -#endif - clearUnsubscribedGroup(it->mGroupId); - } - } - - /* Query for UNPROCESSED POSTS from checkGroupList */ - request_GroupUnprocessedPosts(groupList); -} - - - -void p3GxsChannels::updateSubscribedGroup(const RsGroupMetaData &group) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::updateSubscribedGroup() id: " << group.mGroupId; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(mSubscribedGroupsMutex); - mSubscribedGroups[group.mGroupId] = group; -} - - -void p3GxsChannels::clearUnsubscribedGroup(const RsGxsGroupId &id) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::clearUnsubscribedGroup() id: " << id; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(mSubscribedGroupsMutex); - std::map::iterator it; - it = mSubscribedGroups.find(id); - if (it != mSubscribedGroups.end()) - { - mSubscribedGroups.erase(it); - } -} - - -bool p3GxsChannels::subscribeToGroup(uint32_t &token, const RsGxsGroupId &groupId, bool subscribe) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::subscribedToGroup() id: " << groupId << " subscribe: " << subscribe; - std::cerr << std::endl; -#endif - - std::list groups; - groups.push_back(groupId); - - // Call down to do the real work. - bool response = RsGenExchange::subscribeToGroup(token, groupId, subscribe); - - // reload Group afterwards. - request_SpecificSubscribedGroups(groups); - - return response; -} - - -void p3GxsChannels::request_SpecificUnprocessedPosts(std::list > &ids) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::request_SpecificUnprocessedPosts()"; - std::cerr << std::endl; -#endif // GXSCHANNELS_DEBUG - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - // Only Fetch UNPROCESSED messages. - opts.mStatusFilter = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - opts.mStatusMask = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - - uint32_t token = 0; - - /* organise Ids how they want them */ - GxsMsgReq msgIds; - std::list >::iterator it; - for(it = ids.begin(); it != ids.end(); ++it) - msgIds[it->first].insert(it->second); - - RsGenExchange::getTokenService()->requestMsgInfo(token, ansType, opts, msgIds); - GxsTokenQueue::queueRequest(token, GXSCHANNELS_UNPROCESSED_SPECIFIC); -} - - -void p3GxsChannels::request_GroupUnprocessedPosts(const std::list &grouplist) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::request_GroupUnprocessedPosts()"; - std::cerr << std::endl; -#endif // GXSCHANNELS_DEBUG - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - // Only Fetch UNPROCESSED messages. - opts.mStatusFilter = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - opts.mStatusMask = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestMsgInfo(token, ansType, opts, grouplist); - GxsTokenQueue::queueRequest(token, GXSCHANNELS_UNPROCESSED_GENERIC); -} - - -void p3GxsChannels::load_unprocessedPosts(uint32_t token) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::load_SpecificUnprocessedPosts" << std::endl; -#endif - - std::vector posts; - if (!getPostData(token, posts)) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR getting post data!" - << std::endl; - return; - } - - std::vector::iterator it; - for(it = posts.begin(); it != posts.end(); ++it) - { - /* autodownload the files */ - handleUnprocessedPost(*it); - } -} - -void p3GxsChannels::handleUnprocessedPost(const RsGxsChannelPost &msg) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " GroupId: " << msg.mMeta.mGroupId - << " MsgId: " << msg.mMeta.mMsgId << std::endl; -#endif - - if (!IS_MSG_UNPROCESSED(msg.mMeta.mMsgStatus)) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR Msg already Processed! " - << "mMsgId: " << msg.mMeta.mMsgId << std::endl; - return; - } - - /* check that autodownload is set */ - bool enabled = false; - if (autoDownloadEnabled(msg.mMeta.mGroupId, enabled) && enabled) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " AutoDownload Enabled... handling" - << std::endl; -#endif - - /* check the date is not too old */ - rstime_t age = time(NULL) - msg.mMeta.mPublishTs; - - if (age < (rstime_t) CHANNEL_DOWNLOAD_PERIOD ) - { - /* start download */ - // NOTE WE DON'T HANDLE PRIVATE CHANNELS HERE. - // MORE THOUGHT HAS TO GO INTO THAT STUFF. - -#ifdef GXSCHANNELS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " START DOWNLOAD" << std::endl; -#endif - - std::list::const_iterator fit; - for(fit = msg.mFiles.begin(); fit != msg.mFiles.end(); ++fit) - { - std::string fname = fit->mName; - Sha1CheckSum hash = Sha1CheckSum(fit->mHash); - uint64_t size = fit->mSize; - - std::list srcIds; - std::string localpath = ""; - TransferRequestFlags flags = RS_FILE_REQ_BACKGROUND | RS_FILE_REQ_ANONYMOUS_ROUTING; - - if (size < CHANNEL_MAX_AUTO_DL) - { - std::string directory ; - if(getChannelDownloadDirectory(msg.mMeta.mGroupId,directory)) - localpath = directory ; - - rsFiles->FileRequest(fname, hash, size, localpath, flags, srcIds); - } - else - std::cerr << __PRETTY_FUNCTION__ << "Channel file is not auto-" - << "downloaded because its size exceeds the threshold" - << " of " << CHANNEL_MAX_AUTO_DL << " bytes." - << std::endl; - } - } - - /* mark as processed */ - uint32_t token; - RsGxsGrpMsgIdPair msgId(msg.mMeta.mGroupId, msg.mMeta.mMsgId); - setMessageProcessedStatus(token, msgId, true); - } -#ifdef GXSCHANNELS_DEBUG - else - { - std::cerr << "p3GxsChannels::handleUnprocessedPost() AutoDownload Disabled ... skipping"; - std::cerr << std::endl; - } -#endif -} - - - // Overloaded from GxsTokenQueue for Request callbacks. -void p3GxsChannels::handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::handleResponse(" << token << "," << req_type << "," << status << ")" << std::endl; -#endif // GXSCHANNELS_DEBUG - if (status != RsTokenService::COMPLETE) - return; //For now, only manage Complete request - - // stuff. - switch(req_type) - { - case GXSCHANNELS_SUBSCRIBED_META: - load_SubscribedGroups(token); - break; - - case GXSCHANNELS_UNPROCESSED_SPECIFIC: - load_unprocessedPosts(token); - break; - - case GXSCHANNELS_UNPROCESSED_GENERIC: - load_unprocessedPosts(token); - break; - - default: - std::cerr << __PRETTY_FUNCTION__ << "ERROR Unknown Request Type: " - << req_type << std::endl; - break; - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Blocking API implementation begin -//////////////////////////////////////////////////////////////////////////////// - -bool p3GxsChannels::getChannelsSummaries( - std::list& channels ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - if( !requestGroupInfo(token, opts) - || waitToken(token) != RsTokenService::COMPLETE ) return false; - return getGroupSummary(token, channels); -} - -bool p3GxsChannels::getChannelsInfo( const std::list& chanIds, std::vector& channelsInfo ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if(chanIds.empty()) - { - if( !requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - else - { - if( !requestGroupInfo(token, opts, chanIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - - return getGroupData(token, channelsInfo) && !channelsInfo.empty(); -} - -bool p3GxsChannels::getChannelStatistics(const RsGxsGroupId& channelId,GxsGroupStatistic& stat) -{ - uint32_t token; - if(!RsGxsIfaceHelper::requestGroupStatistic(token, channelId) || waitToken(token) != RsTokenService::COMPLETE) - return false; - - return RsGenExchange::getGroupStatistic(token,stat); -} - -bool p3GxsChannels::getChannelServiceStatistics(GxsServiceStatistic& stat) -{ - uint32_t token; - if(!RsGxsIfaceHelper::requestServiceStatistic(token) || waitToken(token) != RsTokenService::COMPLETE) - return false; - - return RsGenExchange::getServiceStatistic(token,stat); -} - -bool p3GxsChannels::getContentSummaries( - const RsGxsGroupId& channelId, std::vector& summaries ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - - std::list channelIds; - channelIds.push_back(channelId); - - if( !requestMsgInfo(token, opts, channelIds) || - waitToken(token, std::chrono::seconds(5)) != RsTokenService::COMPLETE ) - return false; - - GxsMsgMetaMap metaMap; - bool res = RsGenExchange::getMsgMeta(token, metaMap); - summaries = metaMap[channelId]; - - return res; -} - -bool p3GxsChannels::getChannelAllContent( const RsGxsGroupId& channelId, - std::vector& posts, - std::vector& comments, - std::vector& votes ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - if( !requestMsgInfo(token, opts,std::list({channelId})) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - - return getPostData(token, posts, comments,votes); -} - -bool p3GxsChannels::getChannelContent( const RsGxsGroupId& channelId, - const std::set& contentIds, - std::vector& posts, - std::vector& comments, - std::vector& votes ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - GxsMsgReq msgIds; - msgIds[channelId] = contentIds; - - if( !requestMsgInfo(token, opts, msgIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - - return getPostData(token, posts, comments, votes); -} - -bool p3GxsChannels::getChannelComments(const RsGxsGroupId &channelId, - const std::set &contentIds, - std::vector &comments) -{ - std::vector msgIds; - for (auto& msg:contentIds) - msgIds.push_back(RsGxsGrpMsgIdPair(channelId,msg)); - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; - opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST; - - uint32_t token; - if( !requestMsgRelatedInfo(token, opts, msgIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - - return getRelatedComments(token,comments); -} - -bool p3GxsChannels::createChannelV2( - const std::string& name, const std::string& description, - const RsGxsImage& thumbnail, const RsGxsId& authorId, - RsGxsCircleType circleType, const RsGxsCircleId& circleId, - RsGxsGroupId& channelId, std::string& errorMessage ) -{ - const auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errorMessage = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(!authorId.isNull() && !rsIdentity->isOwnId(authorId)) - return failure("authorId must be either null, or of an owned identity"); - - if( circleType != RsGxsCircleType::PUBLIC - && circleType != RsGxsCircleType::EXTERNAL - && circleType != RsGxsCircleType::NODES_GROUP - && circleType != RsGxsCircleType::LOCAL - && circleType != RsGxsCircleType::YOUR_EYES_ONLY) - return failure("circleType has invalid value"); - - switch(circleType) - { - case RsGxsCircleType::EXTERNAL: - if(circleId.isNull()) - return failure("circleType is EXTERNAL but circleId is null"); - break; - case RsGxsCircleType::NODES_GROUP: - { - RsGroupInfo ginfo; - - if(!rsPeers->getGroupInfo(RsNodeGroupId(circleId), ginfo)) - return failure( "circleType is NODES_GROUP but circleId does not " - "correspond to an actual group of friends" ); - break; - } - default: - if(!circleId.isNull()) - return failure( "circleType requires a null circleId, but a non " - "null circleId (" + circleId.toStdString() + - ") was supplied" ); - break; - } - - // Create a consistent channel group meta from the information supplied - RsGxsChannelGroup channel; - - channel.mMeta.mGroupName = name; - channel.mMeta.mAuthorId = authorId; - channel.mMeta.mCircleType = static_cast(circleType); - - channel.mMeta.mSignFlags = GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ - | GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED; - - channel.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; - - channel.mMeta.mCircleId.clear(); - channel.mMeta.mInternalCircle.clear(); - - switch(circleType) - { - case RsGxsCircleType::NODES_GROUP: - channel.mMeta.mInternalCircle = circleId; break; - case RsGxsCircleType::EXTERNAL: - channel.mMeta.mCircleId = circleId; break; - default: break; - } - - // Create the channel - channel.mDescription = description; - channel.mImage = thumbnail; - - uint32_t token; - if(!createGroup(token, channel)) - return failure("Failure creating GXS group"); - - // wait for the group creation to complete. - RsTokenService::GxsRequestStatus wSt = - waitToken( token, std::chrono::seconds(5), - std::chrono::milliseconds(50) ); - if(wSt != RsTokenService::COMPLETE) - return failure( "GXS operation waitToken failed with: " + - std::to_string(wSt) ); - - if(!RsGenExchange::getPublishedGroupMeta(token, channel.mMeta)) - return failure("Failure getting updated group data."); - - channelId = channel.mMeta.mGroupId; - -#ifdef RS_DEEP_CHANNEL_INDEX - DeepChannelsIndex::indexChannelGroup(channel); -#endif // RS_DEEP_CHANNEL_INDEX - - return true; -} - -bool p3GxsChannels::createChannel(RsGxsChannelGroup& channel) -{ - uint32_t token; - if(!createGroup(token, channel)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failed creating group." - << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, channel.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting updated " - << " group data." << std::endl; - return false; - } - -#ifdef RS_DEEP_CHANNEL_INDEX - DeepChannelsIndex::indexChannelGroup(channel); -#endif // RS_DEEP_CHANNEL_INDEX - - return true; -} - -bool p3GxsChannels::createVoteV2( - const RsGxsGroupId& channelId, const RsGxsMessageId& postId, - const RsGxsMessageId& commentId, const RsGxsId& authorId, - RsGxsVoteType tVote, RsGxsMessageId& voteId, std::string& errorMessage ) -{ - std::vector channelsInfo; - if(!getChannelsInfo(std::list({channelId}),channelsInfo)) - { - errorMessage = "Channel with Id " + channelId.toStdString() - + " does not exist."; - return false; - } - - if(commentId.isNull()) - { - errorMessage = "You cannot vote on null comment " - + commentId.toStdString(); - return false; - } - - std::set s({commentId}); - std::vector posts; - std::vector comments; - std::vector votes; - - if(!getChannelContent(channelId, s, posts, comments, votes)) - { - errorMessage = "You cannot vote on comment " - + commentId.toStdString() + " of channel with Id " - + channelId.toStdString() - + ": this comment does not exists locally!"; - return false; - } - - // is the ID a comment ID or a post ID? - // It should be comment => should have a parent ID - if(posts.front().mMeta.mParentId.isNull()) - { - errorMessage = "You cannot vote on channel message " - + commentId.toStdString() + " of channel with Id " - + channelId.toStdString() - + ": given id refers to a post, not a comment!"; - return false; - } - - if( tVote != RsGxsVoteType::NONE - && tVote != RsGxsVoteType::UP - && tVote != RsGxsVoteType::DOWN ) - { - errorMessage = "Your vote to channel with Id " - + channelId.toStdString() + " has wrong vote type. " - + " Only RsGxsVoteType::NONE, RsGxsVoteType::UP, " - + "RsGxsVoteType::DOWN are accepted."; - return false; - } - - if(!rsIdentity->isOwnId(authorId)) - { - errorMessage = "You cannot vote to channel with Id " - + channelId.toStdString() + " with identity " - + authorId.toStdString() + " because it is not yours."; - return false; - } - - // Create the vote - RsGxsVote vote; - vote.mMeta.mGroupId = channelId; - vote.mMeta.mThreadId = postId; - vote.mMeta.mParentId = commentId; - vote.mMeta.mAuthorId = authorId; - vote.mVoteType = static_cast(tVote); - - uint32_t token; - if(!createNewVote(token, vote)) - { - errorMessage = "Error! Failed creating vote."; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - errorMessage = "GXS operation failed."; - return false; - } - - if(!RsGenExchange::getPublishedMsgMeta(token, vote.mMeta)) - { - errorMessage = "Failure getting generated vote data."; - return false; - } - - voteId = vote.mMeta.mMsgId; - return true; -} - -/// @deprecated use createVoteV2 instead -bool p3GxsChannels::createVote(RsGxsVote& vote) -{ - uint32_t token; - if(!createNewVote(token, vote)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failed creating vote." - << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedMsgMeta(token, vote.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting generated " - << " vote data." << std::endl; - return false; - } - - return true; -} - -bool p3GxsChannels::editChannel(RsGxsChannelGroup& channel) -{ - uint32_t token; - if(!updateGroup(token, channel)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failed updating group." - << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, channel.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting updated " - << " group data." << std::endl; - return false; - } - -#ifdef RS_DEEP_CHANNEL_INDEX - DeepChannelsIndex::indexChannelGroup(channel); -#endif // RS_DEEP_CHANNEL_INDEX - - return true; -} - -bool p3GxsChannels::createPostV2( - const RsGxsGroupId& channelId, const std::string& title, - const std::string& body, const std::list& files, - const RsGxsImage& thumbnail, const RsGxsMessageId& origPostId, - RsGxsMessageId& postId, std::string& errorMessage ) -{ - // Do some checks - - std::vector channelsInfo; - - if(!getChannelsInfo(std::list({channelId}),channelsInfo)) - { - errorMessage = "Channel with Id " + channelId.toStdString() + - " does not exist."; - return false; - } - - const RsGxsChannelGroup& cg(*channelsInfo.begin()); - - if(!(cg.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH)) - { - errorMessage = "You cannot post to channel with Id " + - channelId.toStdString() + ": missing publish rights!"; - return false; - } - - if(!origPostId.isNull()) - { - std::set s({origPostId}); - std::vector posts; - std::vector comments; - std::vector votes; - - if(!getChannelContent(channelId,s,posts,comments,votes)) - { - errorMessage = "You cannot edit post " + origPostId.toStdString() - + " of channel with Id " + channelId.toStdString() - + ": this post does not exist locally!"; - return false; - } - } - - // Create the post - RsGxsChannelPost post; - - post.mMeta.mGroupId = channelId; - post.mMeta.mOrigMsgId = origPostId; - post.mMeta.mMsgName = title; - - post.mMsg = body; - post.mFiles = files; - post.mThumbnail = thumbnail; - - uint32_t token; - if(!createPost(token, post) || waitToken(token) != RsTokenService::COMPLETE) - { - errorMessage = "GXS operation failed"; - return false; - } - - if(RsGenExchange::getPublishedMsgMeta(token,post.mMeta)) - { -#ifdef RS_DEEP_CHANNEL_INDEX - DeepChannelsIndex::indexChannelPost(post); -#endif // RS_DEEP_CHANNEL_INDEX - - postId = post.mMeta.mMsgId; - return true; - } - - errorMessage = "Failed to retrive created post metadata"; - return false; -} - -bool p3GxsChannels::createCommentV2( - const RsGxsGroupId& channelId, - const RsGxsMessageId& threadId, - const std::string& comment, - const RsGxsId& authorId, - const RsGxsMessageId& parentId, - const RsGxsMessageId& origCommentId, - RsGxsMessageId& commentMessageId, - std::string& errorMessage ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errorMessage = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(channelId.isNull()) return failure("channelId cannot be null"); - if(threadId.isNull()) return failure("threadId cannot be null"); - if(parentId.isNull()) return failure("parentId cannot be null"); - - std::vector channelsInfo; - if(!getChannelsInfo(std::list({channelId}),channelsInfo)) - return failure( "Channel with Id " + channelId.toStdString() - + " does not exist." ); - - std::vector posts; - std::vector comments; - std::vector votes; - - if(!getChannelContent( // does the post thread exist? - channelId, std::set({threadId}), - posts, comments, votes) ) - return failure( "You cannot comment post " + threadId.toStdString() + - " of channel with Id " + channelId.toStdString() + - ": this post does not exists locally!" ); - - // check that the post thread Id is actually that of a post thread - if(posts.size() != 1 || !posts[0].mMeta.mParentId.isNull()) - return failure( "You cannot comment post " + threadId.toStdString() + - " of channel with Id " + channelId.toStdString() + - ": supplied threadId is not a thread, or parentMsgId is" - " not a comment!"); - - if(!getChannelContent( // does the post parent exist? - channelId, std::set({parentId}), - posts, comments, votes) ) - return failure( "You cannot comment post " + parentId.toStdString() + - ": supplied parent doesn't exists locally!" ); - - if(!origCommentId.isNull()) - { - std::set s({origCommentId}); - std::vector cmts; - - if( !getChannelContent(channelId, s, posts, cmts, votes) || - comments.size() != 1 ) - return failure( "You cannot edit comment " + - origCommentId.toStdString() + - " of channel with Id " + channelId.toStdString() + - ": this comment does not exist locally!"); - - const RsGxsId& commentAuthor = comments[0].mMeta.mAuthorId; - if(commentAuthor != authorId) - return failure( "Editor identity and creator doesn't match " - + authorId.toStdString() + " != " - + commentAuthor.toStdString() ); - } - - if(!rsIdentity->isOwnId(authorId)) // is the author ID actually ours? - return failure( "You cannot comment to channel with Id " + - channelId.toStdString() + " with identity " + - authorId.toStdString() + " because it is not yours." ); - - // Now create the comment - RsGxsComment cmt; - cmt.mMeta.mGroupId = channelId; - cmt.mMeta.mThreadId = threadId; - cmt.mMeta.mParentId = parentId; - cmt.mMeta.mAuthorId = authorId; - cmt.mMeta.mOrigMsgId = origCommentId; - cmt.mComment = comment; - - uint32_t token; - if(!createNewComment(token, cmt)) - return failure("createNewComment failed"); - - RsTokenService::GxsRequestStatus wSt = waitToken(token); - if(wSt != RsTokenService::COMPLETE) - return failure( "GXS operation waitToken failed with: " + - std::to_string(wSt) ); - - if(!RsGenExchange::getPublishedMsgMeta(token, cmt.mMeta)) - return failure("Failure getting created comment data."); - - commentMessageId = cmt.mMeta.mMsgId; - return true; -} - -bool p3GxsChannels::createComment(RsGxsComment& comment) // deprecated -{ - uint32_t token; - if(!createNewComment(token, comment)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failed creating comment." - << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedMsgMeta(token, comment.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting generated " - << " comment data." << std::endl; - return false; - } - - return true; -} - -bool p3GxsChannels::subscribeToChannel( const RsGxsGroupId& groupId, bool subscribe ) -{ - uint32_t token; - if( !subscribeToGroup(token, groupId, subscribe) || waitToken(token) != RsTokenService::COMPLETE ) return false; - - RsGxsGroupId grpId; - acknowledgeGrp(token,grpId); - return true; -} - -bool p3GxsChannels::markRead(const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t token; - setMessageReadStatus(token, msgId, read); - if(waitToken(token) != RsTokenService::COMPLETE ) return false; - - RsGxsGrpMsgIdPair p; - acknowledgeMsg(token,p); - - return true; -} - -bool p3GxsChannels::shareChannelKeys( - const RsGxsGroupId& channelId, const std::set& peers) -{ - return groupShareKeys(channelId, peers); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Blocking API implementation end -//////////////////////////////////////////////////////////////////////////////// - - -/********************************************************************************************/ -/********************************************************************************************/ - - -bool p3GxsChannels::autoDownloadEnabled(const RsGxsGroupId &groupId,bool& enabled) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::autoDownloadEnabled(" << groupId << ")"; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(mSubscribedGroupsMutex); - std::map::iterator it; - it = mSubscribedGroups.find(groupId); - if (it == mSubscribedGroups.end()) - { - std::cerr << __PRETTY_FUNCTION__ << " WARNING requested channel: " - << groupId << " is not subscribed" << std::endl; - return false; - } - - /* extract from ServiceString */ - GxsChannelGroupInfo ss; - ss.load(it->second.mServiceString); - enabled = ss.mAutoDownload; - - return true; -} - -bool GxsChannelGroupInfo::load(const std::string &input) -{ - if(input.empty()) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "SSGxsChannelGroup::load() asked to load a null string." << std::endl; -#endif - return true ; - } - int download_val; - mAutoDownload = false; - mDownloadDirectory.clear(); - - - RsTemporaryMemory tmpmem(input.length()); - - if (1 == sscanf(input.c_str(), "D:%d", &download_val)) - { - if (download_val == 1) - mAutoDownload = true; - } - else if( 2 == sscanf(input.c_str(),"v2 {D:%d} {P:%[^}]}",&download_val,(unsigned char*)tmpmem)) - { - if (download_val == 1) - mAutoDownload = true; - - std::vector vals = Radix64::decode(std::string((char*)(unsigned char *)tmpmem)) ; - mDownloadDirectory = std::string((char*)vals.data(),vals.size()); - } - else if( 1 == sscanf(input.c_str(),"v2 {D:%d}",&download_val)) - { - if (download_val == 1) - mAutoDownload = true; - } - else - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "SSGxsChannelGroup::load(): could not parse string \"" << input << "\"" << std::endl; -#endif - return false ; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "DECODED STRING: autoDL=" << mAutoDownload << ", directory=\"" << mDownloadDirectory << "\"" << std::endl; -#endif - - return true; -} - -std::string GxsChannelGroupInfo::save() const -{ - std::string output = "v2 "; - - if (mAutoDownload) - output += "{D:1}"; - else - output += "{D:0}"; - - if(!mDownloadDirectory.empty()) - { - std::string encoded_str ; - Radix64::encode((unsigned char*)mDownloadDirectory.c_str(),mDownloadDirectory.length(),encoded_str); - - output += " {P:" + encoded_str + "}"; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "ENCODED STRING: " << output << std::endl; -#endif - - return output; -} - -bool p3GxsChannels::setAutoDownload(const RsGxsGroupId& groupId, bool enabled) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " id: " << groupId - << " enabled: " << enabled << std::endl; -#endif - - RS_STACK_MUTEX(mSubscribedGroupsMutex); - std::map::iterator it; - it = mSubscribedGroups.find(groupId); - if (it == mSubscribedGroups.end()) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR requested channel: " - << groupId.toStdString() << " is not subscribed!" << std::endl; - return false; - } - - /* extract from ServiceString */ - GxsChannelGroupInfo ss; - ss.load(it->second.mServiceString); - if (enabled == ss.mAutoDownload) - { - std::cerr << __PRETTY_FUNCTION__ << " WARNING mAutoDownload was already" - << " properly set to: " << enabled << " for channel:" - << groupId.toStdString() << std::endl; - return false; - } - - ss.mAutoDownload = enabled; - std::string serviceString = ss.save(); - - uint32_t token; - RsGenExchange::setGroupServiceString(token, groupId, serviceString); - - if(waitToken(token) != RsTokenService::COMPLETE) return false; - - it->second.mServiceString = serviceString; // update Local Cache. - - return true; -} - -/********************************************************************************************/ -/********************************************************************************************/ - -void p3GxsChannels::setMessageProcessedStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool processed) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::setMessageProcessedStatus()"; - std::cerr << std::endl; -#endif - - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - uint32_t status = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - if (processed) - { - status = 0; - } - setMsgStatusFlags(token, msgId, status, mask); -} - -void p3GxsChannels::setMessageReadStatus( uint32_t& token, - const RsGxsGrpMsgIdPair& msgId, - bool read ) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::setMessageReadStatus()"; - std::cerr << std::endl; -#endif - - /* Always remove status unprocessed */ - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - uint32_t status = GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - if (read) status = 0; - - setMsgStatusFlags(token, msgId, status, mask); - - if (rsEvents) - { - auto ev = std::make_shared(); - - ev->mChannelMsgId = msgId.second; - ev->mChannelGroupId = msgId.first; - ev->mChannelEventCode = RsChannelEventCode::READ_STATUS_CHANGED; - rsEvents->postEvent(ev); - } -} - -/********************************************************************************************/ -/********************************************************************************************/ - -bool p3GxsChannels::createGroup(uint32_t &token, RsGxsChannelGroup &group) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::createGroup()" << std::endl; -#endif - - RsGxsChannelGroupItem* grpItem = new RsGxsChannelGroupItem(); - grpItem->fromChannelGroup(group, true); - - RsGenExchange::publishGroup(token, grpItem); - return true; -} - - -bool p3GxsChannels::updateGroup(uint32_t &token, RsGxsChannelGroup &group) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::updateGroup()" << std::endl; -#endif - - RsGxsChannelGroupItem* grpItem = new RsGxsChannelGroupItem(); - grpItem->fromChannelGroup(group, true); - - RsGenExchange::updateGroup(token, grpItem); - return true; -} - -/// @deprecated use createPostV2 instead -bool p3GxsChannels::createPost(RsGxsChannelPost& post) -{ - uint32_t token; - if( !createPost(token, post) - || waitToken(token) != RsTokenService::COMPLETE ) return false; - - if(RsGenExchange::getPublishedMsgMeta(token,post.mMeta)) - { -#ifdef RS_DEEP_CHANNEL_INDEX - DeepChannelsIndex::indexChannelPost(post); -#endif // RS_DEEP_CHANNEL_INDEX - - return true; - } - - return false; -} - - -bool p3GxsChannels::createPost(uint32_t &token, RsGxsChannelPost &msg) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " GroupId: " << msg.mMeta.mGroupId - << std::endl; -#endif - - RsGxsChannelPostItem* msgItem = new RsGxsChannelPostItem(); - msgItem->fromChannelPost(msg, true); - - RsGenExchange::publishMsg(token, msgItem); - return true; -} - -/********************************************************************************************/ -/********************************************************************************************/ - -bool p3GxsChannels::ExtraFileHash(const std::string& path) -{ - TransferRequestFlags flags = RS_FILE_REQ_ANONYMOUS_ROUTING; - return rsFiles->ExtraFileHash(path, GXSCHANNEL_STOREPERIOD, flags); -} - - -bool p3GxsChannels::ExtraFileRemove(const RsFileHash& hash) -{ return rsFiles->ExtraFileRemove(hash); } - - -/********************************************************************************************/ -/********************************************************************************************/ - -/* so we need the same tick idea as wiki for generating dummy channels - */ - -#define MAX_GEN_GROUPS 20 -#define MAX_GEN_POSTS 500 -#define MAX_GEN_COMMENTS 600 -#define MAX_GEN_VOTES 700 - -std::string p3GxsChannels::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - -bool p3GxsChannels::generateDummyData() -{ - mGenCount = 0; - mGenRefs.resize(MAX_GEN_VOTES); - - std::string groupName; - rs_sprintf(groupName, "TestChannel_%d", mGenCount); - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::generateDummyData() Starting off with Group: " << groupName; - std::cerr << std::endl; -#endif - - /* create a new group */ - generateGroup(mGenToken, groupName); - - mGenActive = true; - - return true; -} - - -void p3GxsChannels::dummy_tick() -{ - /* check for a new callback */ - - if (mGenActive) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummyTick() Gen Active"; - std::cerr << std::endl; -#endif - - uint32_t status = RsGenExchange::getTokenService()->requestStatus(mGenToken); - if (status != RsTokenService::COMPLETE) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Status: " << status; - std::cerr << std::endl; -#endif - - if (status == RsTokenService::FAILED) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() generateDummyMsgs() FAILED"; - std::cerr << std::endl; -#endif - mGenActive = false; - } - return; - } - - if (mGenCount < MAX_GEN_GROUPS) - { - /* get the group Id */ - RsGxsGroupId groupId; - RsGxsMessageId emptyId; - if (!acknowledgeTokenGrp(mGenToken, groupId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Acknowledged GroupId: " << groupId; - std::cerr << std::endl; -#endif - - ChannelDummyRef ref(groupId, emptyId, emptyId); - mGenRefs[mGenCount] = ref; - } - else if (mGenCount < MAX_GEN_POSTS) - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeTokenMsg(mGenToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Acknowledged Post "; - std::cerr << std::endl; -#endif - - /* store results for later selection */ - - ChannelDummyRef ref(msgId.first, mGenThreadId, msgId.second); - mGenRefs[mGenCount] = ref; - } - else if (mGenCount < MAX_GEN_COMMENTS) - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeTokenMsg(mGenToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Acknowledged Comment "; - std::cerr << std::endl; -#endif - - /* store results for later selection */ - - ChannelDummyRef ref(msgId.first, mGenThreadId, msgId.second); - mGenRefs[mGenCount] = ref; - } - else if (mGenCount < MAX_GEN_VOTES) - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeVote(mGenToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Acknowledged Vote "; - std::cerr << std::endl; -#endif - - /* store results for later selection */ - - ChannelDummyRef ref(msgId.first, mGenThreadId, msgId.second); - mGenRefs[mGenCount] = ref; - } - else - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Finished"; - std::cerr << std::endl; -#endif - - /* done */ - mGenActive = false; - return; - } - - mGenCount++; - - if (mGenCount < MAX_GEN_GROUPS) - { - std::string groupName; - rs_sprintf(groupName, "TestChannel_%d", mGenCount); - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Generating Group: " << groupName; - std::cerr << std::endl; -#endif - - /* create a new group */ - generateGroup(mGenToken, groupName); - } - else if (mGenCount < MAX_GEN_POSTS) - { - /* create a new post */ - uint32_t idx = (uint32_t) (MAX_GEN_GROUPS * RSRandom::random_f32()); - ChannelDummyRef &ref = mGenRefs[idx]; - - RsGxsGroupId grpId = ref.mGroupId; - RsGxsMessageId parentId = ref.mMsgId; - mGenThreadId = ref.mThreadId; - if (mGenThreadId.isNull()) - { - mGenThreadId = parentId; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Generating Post ... "; - std::cerr << " GroupId: " << grpId; - std::cerr << " ThreadId: " << mGenThreadId; - std::cerr << " ParentId: " << parentId; - std::cerr << std::endl; -#endif - - generatePost(mGenToken, grpId); - } - else if (mGenCount < MAX_GEN_COMMENTS) - { - /* create a new post */ - uint32_t idx = (uint32_t) ((mGenCount - MAX_GEN_GROUPS) * RSRandom::random_f32()); - ChannelDummyRef &ref = mGenRefs[idx + MAX_GEN_GROUPS]; - - RsGxsGroupId grpId = ref.mGroupId; - RsGxsMessageId parentId = ref.mMsgId; - mGenThreadId = ref.mThreadId; - if (mGenThreadId.isNull()) - { - mGenThreadId = parentId; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Generating Comment ... "; - std::cerr << " GroupId: " << grpId; - std::cerr << " ThreadId: " << mGenThreadId; - std::cerr << " ParentId: " << parentId; - std::cerr << std::endl; -#endif - - generateComment(mGenToken, grpId, parentId, mGenThreadId); - } - else - { - /* create a new post */ - uint32_t idx = (uint32_t) ((MAX_GEN_COMMENTS - MAX_GEN_POSTS) * RSRandom::random_f32()); - ChannelDummyRef &ref = mGenRefs[idx + MAX_GEN_POSTS]; - - RsGxsGroupId grpId = ref.mGroupId; - RsGxsMessageId parentId = ref.mMsgId; - mGenThreadId = ref.mThreadId; - if (mGenThreadId.isNull()) - { - mGenThreadId = parentId; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Generating Vote ... "; - std::cerr << " GroupId: " << grpId; - std::cerr << " ThreadId: " << mGenThreadId; - std::cerr << " ParentId: " << parentId; - std::cerr << std::endl; -#endif - - generateVote(mGenToken, grpId, parentId, mGenThreadId); - } - - } - -#ifdef TO_REMOVE - cleanTimedOutCallbacks(); -#endif -} - - -bool p3GxsChannels::generatePost(uint32_t &token, const RsGxsGroupId &grpId) -{ - RsGxsChannelPost msg; - - std::string rndId = genRandomId(); - - rs_sprintf(msg.mMsg, "Channel Msg: GroupId: %s, some randomness: %s", - grpId.toStdString().c_str(), rndId.c_str()); - - msg.mMeta.mMsgName = msg.mMsg; - - msg.mMeta.mGroupId = grpId; - msg.mMeta.mThreadId.clear() ; - msg.mMeta.mParentId.clear() ; - - msg.mMeta.mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - - createPost(token, msg); - - return true; -} - - -bool p3GxsChannels::generateComment(uint32_t &token, const RsGxsGroupId &grpId, const RsGxsMessageId &parentId, const RsGxsMessageId &threadId) -{ - RsGxsComment msg; - - std::string rndId = genRandomId(); - - rs_sprintf(msg.mComment, "Channel Comment: GroupId: %s, ThreadId: %s, ParentId: %s + some randomness: %s", - grpId.toStdString().c_str(), threadId.toStdString().c_str(), parentId.toStdString().c_str(), rndId.c_str()); - - msg.mMeta.mMsgName = msg.mComment; - - msg.mMeta.mGroupId = grpId; - msg.mMeta.mThreadId = threadId; - msg.mMeta.mParentId = parentId; - - msg.mMeta.mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - - /* chose a random Id to sign with */ - std::list ownIds; - std::list::iterator it; - - rsIdentity->getOwnIds(ownIds); - - uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); - uint32_t i = 0; - for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); ++it, ++i); - - if (it != ownIds.end()) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::generateComment() Author: " << *it; - std::cerr << std::endl; -#endif - msg.mMeta.mAuthorId = *it; - } -#ifdef GXSCHANNELS_DEBUG - else - { - std::cerr << "p3GxsChannels::generateComment() No Author!"; - std::cerr << std::endl; - } -#endif - - createNewComment(token, msg); - - return true; -} - - -bool p3GxsChannels::generateVote(uint32_t &token, const RsGxsGroupId &grpId, const RsGxsMessageId &parentId, const RsGxsMessageId &threadId) -{ - RsGxsVote vote; - - vote.mMeta.mGroupId = grpId; - vote.mMeta.mThreadId = threadId; - vote.mMeta.mParentId = parentId; - vote.mMeta.mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - - /* chose a random Id to sign with */ - std::list ownIds; - std::list::iterator it; - - rsIdentity->getOwnIds(ownIds); - - uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); - uint32_t i = 0; - for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); ++it, ++i) ; - - if (it != ownIds.end()) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::generateVote() Author: " << *it; - std::cerr << std::endl; -#endif - vote.mMeta.mAuthorId = *it; - } -#ifdef GXSCHANNELS_DEBUG - else - { - std::cerr << "p3GxsChannels::generateVote() No Author!"; - std::cerr << std::endl; - } -#endif - - if (0.7 > RSRandom::random_f32()) - { - // 70 % postive votes - vote.mVoteType = GXS_VOTE_UP; - } - else - { - vote.mVoteType = GXS_VOTE_DOWN; - } - - createNewVote(token, vote); - - return true; -} - - -bool p3GxsChannels::generateGroup(uint32_t &token, std::string groupName) -{ - /* generate a new channel */ - RsGxsChannelGroup channel; - channel.mMeta.mGroupName = groupName; - - createGroup(token, channel); - - return true; -} - - - // Overloaded from RsTickEvent for Event callbacks. -void p3GxsChannels::handle_event(uint32_t event_type, const std::string &elabel) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::handle_event(" << event_type << ")"; - std::cerr << std::endl; -#endif - - // stuff. - switch(event_type) - { - case CHANNEL_TESTEVENT_DUMMYDATA: - generateDummyData(); - break; - - case CHANNEL_PROCESS: - request_AllSubscribedGroups(); - break; - - default: - /* error */ - std::cerr << "p3GxsChannels::handle_event() Unknown Event Type: " << event_type << " elabel:" << elabel; - std::cerr << std::endl; - break; - } -} - -TurtleRequestId p3GxsChannels::turtleGroupRequest(const RsGxsGroupId& group_id) -{ - return netService()->turtleGroupRequest(group_id) ; -} -TurtleRequestId p3GxsChannels::turtleSearchRequest(const std::string& match_string) -{ - return netService()->turtleSearchRequest(match_string); -} - -bool p3GxsChannels::clearDistantSearchResults(TurtleRequestId req) -{ - return netService()->clearDistantSearchResults(req); -} -bool p3GxsChannels::retrieveDistantSearchResults(TurtleRequestId req,std::map& results) -{ - return netService()->retrieveDistantSearchResults(req,results); -} - -DistantSearchGroupStatus p3GxsChannels::getDistantSearchStatus(const RsGxsGroupId& group_id) -{ - return netService()->getDistantSearchStatus(group_id); -} -bool p3GxsChannels::getDistantSearchResultGroupData(const RsGxsGroupId& group_id,RsGxsChannelGroup& distant_group) -{ - RsGxsGroupSearchResults gs; - - if(netService()->retrieveDistantGroupSummary(group_id,gs)) - { - // This is a placeholder information by the time we receive the full group meta data and check the signature. - distant_group.mMeta.mGroupId = gs.mGroupId ; - distant_group.mMeta.mGroupName = gs.mGroupName; - distant_group.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC ; - distant_group.mMeta.mSignFlags = gs.mSignFlags; - - distant_group.mMeta.mPublishTs = gs.mPublishTs; - distant_group.mMeta.mAuthorId = gs.mAuthorId; - - distant_group.mMeta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC ;// guessed, otherwise the group would not be search-able. - - // other stuff. - distant_group.mMeta.mAuthenFlags = 0; // wild guess... - - distant_group.mMeta.mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED ; - - distant_group.mMeta.mPop = gs.mPopularity; // Popularity = number of friend subscribers - distant_group.mMeta.mVisibleMsgCount = gs.mNumberOfMessages; // Max messages reported by friends - distant_group.mMeta.mLastPost = gs.mLastMessageTs; // Timestamp for last message. Not used yet. - - return true ; - } - else - return false ; -} - -#ifdef TO_REMOVE -bool p3GxsChannels::turtleSearchRequest( - const std::string& matchString, - const std::function& multiCallback, - rstime_t maxWait ) -{ - if(matchString.empty()) - { - std::cerr << __PRETTY_FUNCTION__ << " match string can't be empty!" - << std::endl; - return false; - } - - TurtleRequestId sId = turtleSearchRequest(matchString); - - { - RS_STACK_MUTEX(mSearchCallbacksMapMutex); - mSearchCallbacksMap.emplace( - sId, - std::make_pair( - multiCallback, - std::chrono::system_clock::now() + - std::chrono::seconds(maxWait) ) ); - } - - return true; -} - -/// @see RsGxsChannels::turtleChannelRequest -bool p3GxsChannels::turtleChannelRequest( - const RsGxsGroupId& channelId, - const std::function& multiCallback, - rstime_t maxWait) -{ - if(channelId.isNull()) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! channelId can't be null!" - << std::endl; - return false; - } - - TurtleRequestId sId = turtleGroupRequest(channelId); - - { - RS_STACK_MUTEX(mDistantChannelsCallbacksMapMutex); - mDistantChannelsCallbacksMap.emplace( - sId, - std::make_pair( - multiCallback, - std::chrono::system_clock::now() + - std::chrono::seconds(maxWait) ) ); - } - - return true; -} - -/// @see RsGxsChannels::localSearchRequest -bool p3GxsChannels::localSearchRequest( - const std::string& matchString, - const std::function& multiCallback, - rstime_t maxWait ) -{ - if(matchString.empty()) - { - std::cerr << __PRETTY_FUNCTION__ << " match string can't be empty!" - << std::endl; - return false; - } - - auto timeout = std::chrono::steady_clock::now() + std::chrono::seconds(maxWait); - RsThread::async([=]() - { - std::list results; - RsGenExchange::localSearch(matchString, results); - if(std::chrono::steady_clock::now() < timeout) - for(const RsGxsGroupSummary& result : results) multiCallback(result); - }); - - return true; -} -#endif - -void p3GxsChannels::receiveDistantSearchResults( TurtleRequestId id, const RsGxsGroupId& grpId ) -{ - if(!rsEvents) - return; - - // We temporise here, in order to avoid notifying clients with many events - // So we put some data in there and will send an event with all of them at once every 1 sec at most. - - mSearchResultsToNotify[id].insert(grpId); -} - -bool p3GxsChannels::exportChannelLink( std::string& link, const RsGxsGroupId& chanId, bool includeGxsData, const std::string& baseUrl, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(chanId.isNull()) return failure("chanId cannot be null"); - - const bool outputRadix = baseUrl.empty(); - if(outputRadix && !includeGxsData) return - failure("includeGxsData must be true if format requested is base64"); - - if( includeGxsData && - !RsGenExchange::exportGroupBase64(link, chanId, errMsg) ) - return failure(errMsg); - - if(outputRadix) return true; - - std::vector chansInfo; - if( !getChannelsInfo(std::list({chanId}), chansInfo) - || chansInfo.empty() ) - return failure("failure retrieving channel information"); - - RsUrl inviteUrl(baseUrl); - inviteUrl.setQueryKV(CHANNEL_URL_ID_FIELD, chanId.toStdString()); - inviteUrl.setQueryKV(CHANNEL_URL_NAME_FIELD, chansInfo[0].mMeta.mGroupName); - if(includeGxsData) inviteUrl.setQueryKV(CHANNEL_URL_DATA_FIELD, link); - - link = inviteUrl.toString(); - return true; -} - -bool p3GxsChannels::importChannelLink( const std::string& link, RsGxsGroupId& chanId, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(link.empty()) return failure("link is empty"); - - const std::string* radixPtr(&link); - - RsUrl url(link); - const auto& query = url.query(); - const auto qIt = query.find(CHANNEL_URL_DATA_FIELD); - if(qIt != query.end()) radixPtr = &qIt->second; - - if(radixPtr->empty()) return failure(CHANNEL_URL_DATA_FIELD + " is empty"); - - if(!RsGenExchange::importGroupBase64(*radixPtr, chanId, errMsg)) - return failure(errMsg); - - return true; -} - -/*static*/ const std::string RsGxsChannels::DEFAULT_CHANNEL_BASE_URL = "retroshare:///channels"; -/*static*/ const std::string RsGxsChannels::CHANNEL_URL_NAME_FIELD = "chanName"; -/*static*/ const std::string RsGxsChannels::CHANNEL_URL_ID_FIELD = "chanId"; -/*static*/ const std::string RsGxsChannels::CHANNEL_URL_DATA_FIELD = "chanData"; -/*static*/ const std::string RsGxsChannels::CHANNEL_URL_MSG_TITLE_FIELD = "chanMsgTitle"; -/*static*/ const std::string RsGxsChannels::CHANNEL_URL_MSG_ID_FIELD = "chanMsgId"; - -RsGxsChannelGroup::~RsGxsChannelGroup() = default; -RsGxsChannelPost::~RsGxsChannelPost() = default; -RsGxsChannels::~RsGxsChannels() = default; diff --git a/libretroshare/src/services/p3gxschannels.h b/libretroshare/src/services/p3gxschannels.h deleted file mode 100644 index b5fe1426f..000000000 --- a/libretroshare/src/services/p3gxschannels.h +++ /dev/null @@ -1,415 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxschannels.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - - -#include "retroshare/rsgxschannels.h" -#include "services/p3gxscommon.h" -#include "gxs/rsgenexchange.h" -#include "gxs/gxstokenqueue.h" -#include "util/rsmemory.h" -#include "util/rsdebug.h" -#include "util/rstickevent.h" - -#include -#include - - -// This class is only a helper to parse the channel group service string. - -class GxsChannelGroupInfo -{ - public: - GxsChannelGroupInfo(): mAutoDownload(false), mDownloadDirectory("") {} - bool load(const std::string &input); - std::string save() const; - - bool mAutoDownload; - std::string mDownloadDirectory; -}; - - -class p3GxsChannels: public RsGenExchange, public RsGxsChannels, - public GxsTokenQueue, public p3Config, - public RsTickEvent /* only needed for testing - remove after */ -{ -public: - p3GxsChannels( RsGeneralDataService* gds, RsNetworkExchangeService* nes, - RsGixs* gixs ); - virtual RsServiceInfo getServiceInfo() override; - - virtual void service_tick() override; - -protected: - - virtual bool service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) override; // see RsGenExchange - - virtual RsSerialiser* setupSerialiser() override; // @see p3Config::setupSerialiser() - virtual bool saveList(bool &cleanup, std::list&saveList) override; // @see p3Config::saveList(bool &cleanup, std::list&) - virtual bool loadList(std::list& loadList) override; // @see p3Config::loadList(std::list&) - - virtual TurtleRequestId turtleGroupRequest(const RsGxsGroupId& group_id) override; - virtual TurtleRequestId turtleSearchRequest(const std::string& match_string) override; - virtual bool retrieveDistantSearchResults(TurtleRequestId req, std::map &results) override; - virtual bool clearDistantSearchResults(TurtleRequestId req) override; - virtual bool getDistantSearchResultGroupData(const RsGxsGroupId& group_id,RsGxsChannelGroup& distant_group) override; - virtual DistantSearchGroupStatus getDistantSearchStatus(const RsGxsGroupId& group_id) override; - - // Overloaded to cache new groups. -virtual RsGenExchange::ServiceCreate_Return service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet) override; - -virtual void notifyChanges(std::vector& changes) override; - - // Overloaded from RsTickEvent. -virtual void handle_event(uint32_t event_type, const std::string &elabel) override; - -public: - -virtual bool getGroupData(const uint32_t &token, std::vector &groups ) override; -virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts, std::vector &vots) override; -virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts) override; -virtual bool getPostData(const uint32_t &token, std::vector &posts) override; -//Not currently used -//virtual bool getRelatedPosts(const uint32_t &token, std::vector &posts); - - ////////////////////////////////////////////////////////////////////////////// - -//virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); -//virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); - -//virtual bool groupRestoreKeys(const std::string &groupId); - virtual bool groupShareKeys( - const RsGxsGroupId &groupId, const std::set& peers) override; - -virtual bool createGroup(uint32_t &token, RsGxsChannelGroup &group) override; -virtual bool createPost(uint32_t &token, RsGxsChannelPost &post) override; - -virtual bool updateGroup(uint32_t &token, RsGxsChannelGroup &group) override; - -// no tokens... should be cached. -virtual bool setChannelAutoDownload(const RsGxsGroupId &groupId, bool enabled) override; -virtual bool getChannelAutoDownload(const RsGxsGroupId &groupid, bool& enabled) override; -virtual bool setChannelDownloadDirectory(const RsGxsGroupId &groupId, const std::string& directory) override; -virtual bool getChannelDownloadDirectory(const RsGxsGroupId &groupId, std::string& directory) override; - -#ifdef TO_REMOVE - /// @see RsGxsChannels::turtleSearchRequest - virtual bool turtleSearchRequest(const std::string& matchString, - const std::function& multiCallback, - rstime_t maxWait = 300 ) override; - - /// @see RsGxsChannels::turtleChannelRequest - virtual bool turtleChannelRequest( - const RsGxsGroupId& channelId, - const std::function& multiCallback, - rstime_t maxWait = 300 ) override; - - /// @see RsGxsChannels::localSearchRequest - virtual bool localSearchRequest(const std::string& matchString, - const std::function& multiCallback, - rstime_t maxWait = 30 ) override; -#endif - - /** - * Receive results from turtle search @see RsGenExchange @see RsNxsObserver - * @see RsGxsNetService::receiveTurtleSearchResults - * @see p3turtle::handleSearchResult - */ - void receiveDistantSearchResults( TurtleRequestId id, - const RsGxsGroupId& grpId ) override; - - /* Comment service - Provide RsGxsCommentService - redirect to p3GxsCommentService */ - virtual bool getCommentData(uint32_t token, std::vector &msgs) override - { return mCommentService->getGxsCommentData(token, msgs); } - - virtual bool getRelatedComments( uint32_t token, - std::vector &msgs ) override - { return mCommentService->getGxsRelatedComments(token, msgs); } - - virtual bool createNewComment(uint32_t &token, const RsGxsComment &msg) override - { - return mCommentService->createGxsComment(token, msg); - } - - virtual bool setCommentAsRead(uint32_t& token,const RsGxsGroupId& gid,const RsGxsMessageId& comment_msg_id) override - { - setMessageReadStatus(token,RsGxsGrpMsgIdPair(gid,comment_msg_id),true); - return true; - } - - virtual bool createNewVote(uint32_t &token, RsGxsVote &msg) override - { - return mCommentService->createGxsVote(token, msg); - } - - virtual bool acknowledgeComment(uint32_t token, std::pair& msgId) override - { - return acknowledgeMsg(token, msgId); - } - - virtual bool acknowledgeVote(uint32_t token, std::pair& msgId) override - { - if (mCommentService->acknowledgeVote(token, msgId)) - { - return true; - } - return acknowledgeMsg(token, msgId); - } - - - // Overloaded from RsGxsIface. -virtual bool subscribeToGroup(uint32_t &token, const RsGxsGroupId &groupId, bool subscribe) override; - - // Set Statuses. -virtual void setMessageProcessedStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool processed); -virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) override; - - // File Interface - virtual bool ExtraFileHash(const std::string& path) override; -virtual bool ExtraFileRemove(const RsFileHash &hash) override; - - - /// Implementation of @see RsGxsChannels::getChannelsSummaries - bool getChannelsSummaries(std::list& channels) override; - - /// Implementation of @see RsGxsChannels::getChannelsInfo - bool getChannelsInfo( - const std::list& chanIds, - std::vector& channelsInfo ) override; - - /// Implementation of @see RsGxsChannels::getChannelAllMessages - bool getChannelAllContent(const RsGxsGroupId& channelId, - std::vector& posts, - std::vector& comments, - std::vector& votes ) override; - - /// Implementation of @see RsGxsChannels::getChannelMessages - bool getChannelContent(const RsGxsGroupId& channelId, - const std::set& contentIds, - std::vector& posts, - std::vector& comments, - std::vector& votes ) override; - - /// Implementation of @see RsGxsChannels::getChannelComments - virtual bool getChannelComments(const RsGxsGroupId &channelId, - const std::set &contentIds, - std::vector &comments) override; - - /// Implementation of @see RsGxsChannels::getContentSummaries - bool getContentSummaries( - const RsGxsGroupId& channelId, - std::vector& summaries ) override; - - /// Implementation of @see RsGxsChannels::getChannelStatistics - bool getChannelStatistics(const RsGxsGroupId& channelId,GxsGroupStatistic& stat) override; - - /// Iplementation of @see RsGxsChannels::getChannelServiceStatistics - bool getChannelServiceStatistics(GxsServiceStatistic& stat) override; - - /// Implementation of @see RsGxsChannels::createChannelV2 - bool createChannelV2( - const std::string& name, const std::string& description, - const RsGxsImage& thumbnail = RsGxsImage(), - const RsGxsId& authorId = RsGxsId(), - RsGxsCircleType circleType = RsGxsCircleType::PUBLIC, - const RsGxsCircleId& circleId = RsGxsCircleId(), - RsGxsGroupId& channelId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// Implementation of @see RsGxsChannels::createComment - bool createCommentV2( - const RsGxsGroupId& channelId, - const RsGxsMessageId& threadId, - const std::string& comment, - const RsGxsId& authorId, - 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; - - /// Implementation of @see RsGxsChannels::editChannel - bool editChannel(RsGxsChannelGroup& channel) override; - - /// Implementation of @see RsGxsChannels::createPostV2 - bool createPostV2( - const RsGxsGroupId& channelId, const std::string& title, - const std::string& body, - const std::list& files = std::list(), - const RsGxsImage& thumbnail = RsGxsImage(), - const RsGxsMessageId& origPostId = RsGxsMessageId(), - RsGxsMessageId& postId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// Implementation of @see RsGxsChannels::createVoteV2 - bool createVoteV2( - const RsGxsGroupId& channelId, const RsGxsMessageId& postId, - const RsGxsMessageId& commentId, const RsGxsId& authorId, - RsGxsVoteType vote, - RsGxsMessageId& voteId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// Implementation of @see RsGxsChannels::subscribeToChannel - bool subscribeToChannel( const RsGxsGroupId &groupId, - bool subscribe ) override; - - /// @see RsGxsChannels - virtual bool markRead(const RsGxsGrpMsgIdPair& msgId, bool read) override; - - /// @see RsGxsChannels - bool exportChannelLink( - std::string& link, const RsGxsGroupId& chanId, - bool includeGxsData = true, - const std::string& baseUrl = DEFAULT_CHANNEL_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsGxsChannels - bool importChannelLink( - const std::string& link, - RsGxsGroupId& chanId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - virtual bool shareChannelKeys( - const RsGxsGroupId& channelId, const std::set& peers ) override; - - /// Implementation of @see RsGxsChannels::createChannel - RS_DEPRECATED_FOR(createChannelV2) - bool createChannel(RsGxsChannelGroup& channel) override; - - /// @deprecated Implementation of @see RsGxsChannels::createPost - RS_DEPRECATED_FOR(createPostV2) - bool createPost(RsGxsChannelPost& post) override; - - /// @deprecated Implementation of @see RsGxsChannels::createComment - RS_DEPRECATED_FOR(createCommentV2) - bool createComment(RsGxsComment &comment) override; - - /// @deprecated Implementation of @see RsGxsChannels::createVote - RS_DEPRECATED_FOR(createVoteV2) - bool createVote(RsGxsVote& vote) override; - - -protected: - // Overloaded from GxsTokenQueue for Request callbacks. - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) override; - - -private: - -static uint32_t channelsAuthenPolicy(); - - // Handle Processing. - void request_AllSubscribedGroups(); - void request_SpecificSubscribedGroups(const std::list &groups); - void load_SubscribedGroups(const uint32_t &token); - - void request_SpecificUnprocessedPosts(std::list > &ids); - void request_GroupUnprocessedPosts(const std::list &grouplist); - void load_unprocessedPosts(uint32_t token); - - void handleUnprocessedPost(const RsGxsChannelPost &msg); - - // Local Cache of Subscribed Groups. and AutoDownload Flag. - void updateSubscribedGroup(const RsGroupMetaData &group); - void clearUnsubscribedGroup(const RsGxsGroupId &id); - bool setAutoDownload(const RsGxsGroupId &groupId, bool enabled); - bool autoDownloadEnabled(const RsGxsGroupId &groupId, bool &enabled); - bool checkForOldAndUnusedChannels(); - -// DUMMY DATA, -virtual bool generateDummyData(); - -std::string genRandomId(); - -void dummy_tick(); - -bool generatePost(uint32_t &token, const RsGxsGroupId &grpId); -bool generateComment(uint32_t &token, const RsGxsGroupId &grpId, - const RsGxsMessageId &parentId, const RsGxsMessageId &threadId); -bool generateVote(uint32_t &token, const RsGxsGroupId &grpId, - const RsGxsMessageId &parentId, const RsGxsMessageId &threadId); - -bool generateGroup(uint32_t &token, std::string groupName); - - class ChannelDummyRef - { - public: - ChannelDummyRef() {} - ChannelDummyRef( - const RsGxsGroupId &grpId, const RsGxsMessageId &threadId, - const RsGxsMessageId &msgId ) : - mGroupId(grpId), mThreadId(threadId), mMsgId(msgId) {} - - RsGxsGroupId mGroupId; - RsGxsMessageId mThreadId; - RsGxsMessageId mMsgId; - }; - - std::map mSubscribedGroups; - RsMutex mSubscribedGroupsMutex; - - /** G10h4ck: Is this stuff really used? And for what? BEGIN */ - uint32_t mGenToken; - bool mGenActive; - int mGenCount; - std::vector mGenRefs; - RsGxsMessageId mGenThreadId; - /** G10h4ck: Is this stuff really used? And for what? END */ - - p3GxsCommentService* mCommentService; - - std::map mKnownChannels; - RsMutex mKnownChannelsMutex; - - rstime_t mLastDistantSearchNotificationTS; - - std::map > mSearchResultsToNotify; -#ifdef TO_REMOVE - /** Store search callbacks with timeout*/ - std::map< - TurtleRequestId, - std::pair< - std::function, - std::chrono::system_clock::time_point > - > mSearchCallbacksMap; - RsMutex mSearchCallbacksMapMutex; - - /** Store distant channels requests callbacks with timeout*/ - std::map< - TurtleRequestId, - std::pair< - std::function, - std::chrono::system_clock::time_point > - > mDistantChannelsCallbacksMap; - RsMutex mDistantChannelsCallbacksMapMutex; - - /// Cleanup mSearchCallbacksMap and mDistantChannelsCallbacksMap - void cleanTimedOutCallbacks(); -#endif -}; diff --git a/libretroshare/src/services/p3gxscircles.cc b/libretroshare/src/services/p3gxscircles.cc deleted file mode 100644 index 0b7bc9570..000000000 --- a/libretroshare/src/services/p3gxscircles.cc +++ /dev/null @@ -1,2822 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxscircles.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#include "rsitems/rsgxscircleitems.h" - -#include "services/p3gxscircles.h" -#include "retroshare/rsgxsflags.h" -#include "util/rsrandom.h" -#include "util/rsdir.h" -#include "util/radix64.h" -#include "util/rsstring.h" -#include "util/rsdebug.h" -#include "pgp/pgpauxutils.h" -#include "retroshare/rsgxscircles.h" -#include "retroshare/rspeers.h" -#include "rsserver/p3face.h" - -#include -#include - -/**** - * #define DEBUG_CIRCLES 1 - ****/ - -/*extern*/ RsGxsCircles* rsGxsCircles = nullptr; - -/*static*/ const std::string RsGxsCircles::DEFAULT_CIRCLE_BASE_URL = - "retroshare:///circles"; -/*static*/ const std::string RsGxsCircles::CIRCLE_URL_NAME_FIELD = "circleName"; -/*static*/ const std::string RsGxsCircles::CIRCLE_URL_ID_FIELD = "circleId"; -/*static*/ const std::string RsGxsCircles::CIRCLE_URL_DATA_FIELD = "circleData"; - -static const uint32_t CIRCLES_UNUSED_BY_FRIENDS_DELAY = 60*86400 ; // 60 days ...O... - -RsGxsCircles::~RsGxsCircles() = default; -RsGxsCircleMsg::~RsGxsCircleMsg() = default; -RsGxsCircleDetails::~RsGxsCircleDetails() = default; -RsGxsCircleGroup::~RsGxsCircleGroup() = default; -RsGxsCircleEvent::~RsGxsCircleEvent() = default; - -/****** - * - * GxsCircles are used to limit the spread of Gxs Groups and Messages. - * - * This is done via GxsCircle parameters in GroupMetaData: - * mCircleType (ALL, External, Internal). - * mCircleId. - * - * The Circle Group contains the definition of who is allowed access to the Group. - * and GXS asks this service before forwarding any data. - * - * The CircleGroup contains: - * list of invited GxsId's - * list of GxsCircleId's (subcircles also allowed). - * - * This service runs a background task to transform the CircleGroups - * into a list of friends/peers who are allowed access. - * These results are cached to provide GXS with quick access to the information. - * This involves: - * - fetching the GroupData via GXS. - * - querying the list of GxsId to see if they are known (NB: this will cause caching of GxsId in p3IdService. - * - recursively loading subcircles to complete Circle definition. - * - saving the result into Cache. - * - * For Phase 1, we will only use the list of GxsIds. No subcircles will be allowed. - * Recursively determining membership via sub-circles is complex and needs more thought. - * The data-types for the full system, however, will be in-place. - * - * Circle Membership - * - Actual members of the circle are computed by intersecting the set of invited IDs with the set of IDs actually requesting membership. - * - To be a member, one therefore has to publish a membership message. To leave the circle, a new message is published accordingly. - * - * Circle Subscription system - * - Circles are subscribed only when we need to dispatch information about our own membership, or when we are admin of the circle. - * - Circle (group) membership is decided automatically. Not to be mixed up with whether or not to be a member of the circle, which is GUI based. - * - * Handling of old/dead circles - * - auto-subscription based on own membership requests should limit the spread of unwanted circles (such as when one adds all visible IDs into - * the invited list of a new circle. Such a circle would not be visible beyond friend nodes of the node creating that circle. - * - * - since this feature is new (in 0.6.6), there is already a bunch of unwanted circles. How we can get rid of them is not entirely clear. - * Indeed, once a node requests membership (and even later on denies it), it will have to remain subscribed to the circle group in order - * to ensure that this unsubscribe request keeps spreading from its actual source. A some point however, the circle msgs disappear, and - * therefore the circle will switch to unsubscribe automatically. - */ - -#define CIRCLEREQ_CACHELOAD 0x0001 -#define CIRCLEREQ_CIRCLE_LIST 0x0002 -#define CIRCLEREQ_MESSAGE_DATA 0x0003 - -//#define CIRCLEREQ_PGPHASH 0x0010 -//#define CIRCLEREQ_REPUTATION 0x0020 - -//#define CIRCLEREQ_CACHETEST 0x1000 - -// Events. -#define CIRCLE_EVENT_LOADIDS 0x0001 -#define CIRCLE_EVENT_CACHELOAD 0x0002 -#define CIRCLE_EVENT_RELOADIDS 0x0003 -#define CIRCLE_EVENT_DUMMYSTART 0x0004 -#define CIRCLE_EVENT_DUMMYLOAD 0x0005 -#define CIRCLE_EVENT_DUMMYGEN 0x0006 - -#define CIRCLE_DUMMY_STARTPERIOD 300 // MUST BE LONG ENOUGH FOR IDS TO HAVE BEEN MADE. -#define CIRCLE_DUMMY_GENPERIOD 10 - -//#define CIRCLE_EVENT_CACHETEST 0x1000 -//#define CACHETEST_PERIOD 60 -//#define OWNID_RELOAD_DELAY 10 - -#define GXSID_LOAD_CYCLE 10 // GXSID completes a load in this period. - -#define MIN_CIRCLE_LOAD_GAP 5 -#define GXS_CIRCLE_DELAY_TO_FORCE_MEMBERSHIP_UPDATE 60 // re-check every 1 mins. Normally this shouldn't be necessary since notifications inform abotu new messages. -#define GXS_CIRCLE_DELAY_TO_CHECK_MEMBERSHIP_UPDATE 60 // re-check every 1 mins. Normally this shouldn't be necessary since notifications inform abotu new messages. -#define GXS_CIRCLE_DELAY_TO_SEND_CACHE_UPDATED_EVENT 2 // do not send cache update events more often than every 2 secs. - -//====================================================================================// -// Startup // -//====================================================================================// - -p3GxsCircles::p3GxsCircles( RsGeneralDataService *gds, RsNetworkExchangeService *nes, p3IdService *identities, PgpAuxUtils *pgpUtils) - : RsGxsCircleExchange( gds, nes, new RsGxsCircleSerialiser(), RS_SERVICE_GXS_TYPE_GXSCIRCLE, identities, circleAuthenPolicy() ), - RsGxsCircles(static_cast(*this)), GxsTokenQueue(this), - RsTickEvent(), mIdentities(identities), mPgpUtils(pgpUtils), - mCircleMtx("p3GxsCircles"), - mKnownCirclesMtx("p3GxsCircles"), -// mCircleCache(DEFAULT_MEM_CACHE_SIZE, "GxsCircleCache" ), - mShouldSendCacheUpdateNotification(false) -{ - // Kick off Cache Testing, + Others. - //RsTickEvent::schedule_in(CIRCLE_EVENT_CACHETEST, CACHETEST_PERIOD); - mLastCacheMembershipUpdateTS = 0 ; - mLastCacheUpdateEvent = 0; - mLastDebugPrintTS = 0; - - RsTickEvent::schedule_now(CIRCLE_EVENT_CACHELOAD); - - mDummyIdToken = 0; -} - -static bool allowedGxsIdFlagTest(uint32_t subscription_flags,bool group_is_self_restricted) -{ - if(group_is_self_restricted) - return (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) && (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE); - else - return (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) && (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED) && (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE); -} - -const std::string GXS_CIRCLES_APP_NAME = "gxscircle"; -const uint16_t GXS_CIRCLES_APP_MAJOR_VERSION = 1; -const uint16_t GXS_CIRCLES_APP_MINOR_VERSION = 0; -const uint16_t GXS_CIRCLES_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_CIRCLES_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3GxsCircles::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_GXSCIRCLE, - GXS_CIRCLES_APP_NAME, - GXS_CIRCLES_APP_MAJOR_VERSION, - GXS_CIRCLES_APP_MINOR_VERSION, - GXS_CIRCLES_MIN_MAJOR_VERSION, - GXS_CIRCLES_MIN_MINOR_VERSION); -} - -//====================================================================================// -// Synchroneous API from rsGxsCircles // -//====================================================================================// - -bool p3GxsCircles::createCircle( - const std::string& circleName, RsGxsCircleType circleType, - RsGxsCircleId& circleId, const RsGxsCircleId& restrictedId, - const RsGxsId& authorId, const std::set& gxsIdMembers, - const std::set& localMembers ) -{ - // 1 - Check consistency of the request data - - if(!checkCircleParamConsistency(circleName,circleType,restrictedId,authorId,gxsIdMembers,localMembers)) - { - RsErr() << __PRETTY_FUNCTION__ << " Circle parameters are inconsistent" << std::endl; - return false; - } - - // 2 - Create the actual request - - RsGxsCircleGroup cData; - cData.mMeta.mGroupName = circleName; - cData.mMeta.mAuthorId = authorId; - cData.mMeta.mCircleType = static_cast(circleType); - cData.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; - cData.mMeta.mCircleId = restrictedId; - cData.mMeta.mSignFlags = GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ | GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED; - cData.mLocalFriends = localMembers; - cData.mInvitedMembers = gxsIdMembers; - - - // 3 - Send it and wait, for a sync response. - - uint32_t token; - createGroup(token, cData); - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, cData.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting created" << " group data." << std::endl; - return false; - } - - circleId = static_cast(cData.mMeta.mGroupId); - return true; -}; - -bool p3GxsCircles::checkCircleParamConsistency( const std::string& circleName, RsGxsCircleType circleType, - const RsGxsCircleId& restrictedId, - const RsGxsId& authorId, const std::set& gxsIdMembers, - const std::set& localMembers ) const -{ - if(circleName.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " Circle name is empty" << std::endl; - return false; - } - - switch(circleType) - { - case RsGxsCircleType::PUBLIC: - if(!restrictedId.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " restrictedId: " << restrictedId - << " must be null with RsGxsCircleType::PUBLIC" - << std::endl; - return false; - } - break; - case RsGxsCircleType::EXTERNAL: - if(restrictedId.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " restrictedId can't be null " - << "with RsGxsCircleType::EXTERNAL" << std::endl; - return false; - } - break; - case RsGxsCircleType::NODES_GROUP: - if(localMembers.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " localMembers can't be empty " - << "with RsGxsCircleType::NODES_GROUP" << std::endl; - return false; - } - break; - case RsGxsCircleType::LOCAL: - break; - case RsGxsCircleType::EXT_SELF: - if(!restrictedId.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " restrictedId: " << restrictedId - << " must be null with RsGxsCircleType::EXT_SELF" - << std::endl; - return false; - } - if(gxsIdMembers.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " gxsIdMembers can't be empty " - << "with RsGxsCircleType::EXT_SELF" << std::endl; - return false; - } - break; - case RsGxsCircleType::YOUR_EYES_ONLY: - break; - default: - RsErr() << __PRETTY_FUNCTION__ << " Invalid circle type: " - << static_cast(circleType) << std::endl; - return false; - } - return true; -} - -bool p3GxsCircles::editCircle(RsGxsCircleGroup& cData) -{ - uint32_t token; - updateGroup(token, cData); - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, cData.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated" - << " group data." << std::endl; - return false; - } - - return true; -} - -bool p3GxsCircles::editCircle(const RsGxsCircleId &circleId, const std::string& circleName, RsGxsCircleType circleType, const RsGxsCircleId& restrictedId, - const RsGxsId& authorId, const std::set& gxsIdMembers, - const std::set& localMembers ) -{ - // 1 - Check consistency of the request data - - if(!checkCircleParamConsistency(circleName,circleType,restrictedId,authorId,gxsIdMembers,localMembers)) - { - RsErr() << __PRETTY_FUNCTION__ << " Circle data is not consistent." << std::endl; - return false; - } - - // 2 - Create the actual request - - RsGxsCircleGroup cData; - cData.mMeta.mGroupId = RsGxsGroupId(circleId); - cData.mMeta.mGroupName = circleName; - cData.mMeta.mAuthorId = authorId; - cData.mMeta.mCircleType = static_cast(circleType); - cData.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; - cData.mMeta.mCircleId = restrictedId; - cData.mLocalFriends = localMembers; - cData.mInvitedMembers = gxsIdMembers; - - // 3 - Send it and wait, for a sync response. - - uint32_t token; - updateGroup(token, cData); - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, cData.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated" - << " group data." << std::endl; - return false; - } - - return true; -}; - -bool p3GxsCircles::getCirclesSummaries(std::list& circles) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - if( !requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - { - std::cerr << "Cannot get circles summary. Token queue is overloaded?" << std::endl; - return false; - } - else - return getGroupSummary(token, circles); -} - -bool p3GxsCircles::getCirclesInfo( const std::list& circlesIds, - std::vector& circlesInfo ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - if( !requestGroupInfo(token, opts, circlesIds) || waitToken(token) != RsTokenService::COMPLETE ) - { - std::cerr << "Cannot get circle info. Token queue is overloaded?" << std::endl; - return false; - } - else - return getGroupData(token, circlesInfo); -} - -bool p3GxsCircles::getCircleRequests( const RsGxsGroupId& circleId, - std::vector& requests ) -{ - uint32_t token; - std::list grpIds { circleId }; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - if( !requestMsgInfo(token, opts, grpIds) || - waitToken(token) != RsTokenService::COMPLETE ) return false; - - return getMsgData(token, requests); -} - -bool p3GxsCircles::getCircleRequest(const RsGxsGroupId& circleId,const RsGxsMessageId& msgId,RsGxsCircleMsg& msg) -{ - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - std::set contentsIds; - contentsIds.insert(msgId); - - GxsMsgReq msgIds; - msgIds[circleId] = contentsIds; - - uint32_t token; - if( !requestMsgInfo(token, opts, msgIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - - std::vector msgs; - - if(getMsgData(token, msgs) && msgs.size() == 1) - { - msg = msgs.front(); - return true; - } - else - return false; -} - -bool p3GxsCircles::inviteIdsToCircle( const std::set& identities, - const RsGxsCircleId& circleId ) -{ - const std::list circlesIds{ RsGxsGroupId(circleId) }; - std::vector circlesInfo; - - if(!getCirclesInfo(circlesIds, circlesInfo)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting group data." - << std::endl; - return false; - } - - if(circlesInfo.empty()) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Circle: " - << circleId.toStdString() << " not found!" << std::endl; - return false; - } - - RsGxsCircleGroup& circleGrp = circlesInfo[0]; - - if(!(circleGrp.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Attempt to edit non-own " - << "circle: " << circleId.toStdString() << std::endl; - return false; - } - - circleGrp.mInvitedMembers.insert(identities.begin(), identities.end()); - - return editCircle(circleGrp); -} - -bool p3GxsCircles::revokeIdsFromCircle( const std::set& identities, const RsGxsCircleId& circleId ) -{ - const std::list circlesIds{ RsGxsGroupId(circleId) }; - std::vector circlesInfo; - - if(!getCirclesInfo(circlesIds, circlesInfo)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting group data." << std::endl; - return false; - } - - if(circlesInfo.empty()) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Circle: " << circleId.toStdString() << " not found!" << std::endl; - return false; - } - - RsGxsCircleGroup& circleGrp = circlesInfo[0]; - - if(!(circleGrp.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Attempt to edit non-own " << "circle: " << circleId.toStdString() << std::endl; - return false; - } - - // /!\ AVOID calling circleGrp.mInvitedMembers.erase(identities.begin(),identities.end()), because it is not the same set. Consequently - // STL code would corrupt the structure of mInvitedMembers. - - std::set new_invited_members; - for(auto& gxs_id: circleGrp.mInvitedMembers) - if(identities.find(gxs_id) == identities.end()) - new_invited_members.insert(gxs_id); - - circleGrp.mInvitedMembers = new_invited_members; - - return editCircle(circleGrp); -} - -bool p3GxsCircles::exportCircleLink( - std::string& link, const RsGxsCircleId& circleId, - bool includeGxsData, const std::string& baseUrl, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(circleId.isNull()) return failure("circleId cannot be null"); - - const bool outputRadix = baseUrl.empty(); - if(outputRadix && !includeGxsData) return - failure("includeGxsData must be true if format requested is base64"); - - RsGxsGroupId&& groupId = static_cast(circleId); - if( includeGxsData && - !RsGenExchange::exportGroupBase64(link, groupId, errMsg) ) - return failure(errMsg); - - if(outputRadix) return true; - - std::vector circlesInfo; - if( !getCirclesInfo( - std::list({groupId}), circlesInfo ) - || circlesInfo.empty() ) - return failure("failure retrieving circle information"); - - RsUrl inviteUrl(baseUrl); - inviteUrl.setQueryKV(CIRCLE_URL_ID_FIELD, circleId.toStdString()); - inviteUrl.setQueryKV(CIRCLE_URL_NAME_FIELD, circlesInfo[0].mMeta.mGroupName); - if(includeGxsData) inviteUrl.setQueryKV(CIRCLE_URL_DATA_FIELD, link); - - link = inviteUrl.toString(); - return true; -} - -bool p3GxsCircles::importCircleLink( - const std::string& link, RsGxsCircleId& circleId, - std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(link.empty()) return failure("link is empty"); - - const std::string* radixPtr(&link); - - RsUrl url(link); - const auto& query = url.query(); - const auto qIt = query.find(CIRCLE_URL_DATA_FIELD); - if(qIt != query.end()) radixPtr = &qIt->second; - - if(radixPtr->empty()) return failure(CIRCLE_URL_DATA_FIELD + " is empty"); - - if(!RsGenExchange::importGroupBase64( - *radixPtr, reinterpret_cast(circleId), errMsg) ) - return failure(errMsg); - - return true; -} - -uint32_t p3GxsCircles::circleAuthenPolicy() -{ - uint32_t policy = 0; - uint8_t flag = 0; - - flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - flag |= GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -//====================================================================================// -// Tick // -//====================================================================================// - -void p3GxsCircles::service_tick() -{ - RsTickEvent::tick_events(); - GxsTokenQueue::checkRequests(); // GxsTokenQueue handles all requests. - - rstime_t now = time(NULL); - - if(mShouldSendCacheUpdateNotification && now > mLastCacheUpdateEvent + GXS_CIRCLE_DELAY_TO_SEND_CACHE_UPDATED_EVENT) - { - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mCircleEventType = RsGxsCircleEventCode::CACHE_DATA_UPDATED; - rsEvents->postEvent(ev); - } - - mLastCacheUpdateEvent = now; - mShouldSendCacheUpdateNotification = false; - } - - if(now > mLastCacheMembershipUpdateTS + GXS_CIRCLE_DELAY_TO_CHECK_MEMBERSHIP_UPDATE) - { - checkCircleCache(); - mLastCacheMembershipUpdateTS = now ; - } - -#ifdef DEBUG_CIRCLES - if(now > mLastDebugPrintTS) - { - mLastDebugPrintTS = now; - debug_dumpCache(); - } -#endif -} - -//====================================================================================// -// Handling of GXS changes // -//====================================================================================// - -void p3GxsCircles::notifyChanges(std::vector &changes) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::notifyChanges()"; - std::cerr << std::endl; -#endif - - //p3Notify *notify = RsServer::notify(); - std::set circles_to_reload; - - for(auto it = changes.begin(); it != changes.end(); ++it) - { - RsGxsNotify *c = *it; - RsGxsMsgChange *msgChange = dynamic_cast(c); - - if (msgChange) - { -#ifdef DEBUG_CIRCLES - std::cerr << " Found circle Message Change Notification for group " << msgChange->mGroupId << ", msg ID " << msgChange->mMsgId << std::endl; - std::cerr << " Msgs for Group: " << msgChange->mGroupId << std::endl; -#endif - RsGxsCircleId circle_id(msgChange->mGroupId); - - if(rsEvents && ((c->getType() == RsGxsNotify::TYPE_RECEIVED_NEW) || (c->getType() == RsGxsNotify::TYPE_PUBLISHED))) - { - const RsGxsCircleSubscriptionRequestItem *item = dynamic_cast(msgChange->mNewMsgItem); - - if(item) - { - auto ev = std::make_shared(); - ev->mCircleId = circle_id; - ev->mGxsId = msgChange->mNewMsgItem->meta.mAuthorId; - - if (item->subscription_type == RsGxsCircleSubscriptionType::UNSUBSCRIBE) - { - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_MEMBERSHIP_LEAVE; - rsEvents->postEvent(ev); - } - else if(item->subscription_type == RsGxsCircleSubscriptionType::SUBSCRIBE) - { - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_MEMBERSHIP_REQUEST; - rsEvents->postEvent(ev); - } - else - RsErr() << __PRETTY_FUNCTION__ << " Unknown subscription request type " << static_cast(item->subscription_type) << " in msg item" << std::endl; - } - else - RsErr() << __PRETTY_FUNCTION__ << ": missing SubscriptionRequestItem in msg notification for msg " << msgChange->mMsgId << std::endl; - } - - circles_to_reload.insert(circle_id); - } - - RsGxsGroupChange *groupChange = dynamic_cast(c); - - /* add groups to ExternalIdList (Might get Personal Circles here until NetChecks in place) */ - if (groupChange) - { - const RsGxsGroupId *git(&groupChange->mGroupId); - -#ifdef DEBUG_CIRCLES - std::cerr << " Found Group Change Notification of type " << c->getType() << std::endl; -#endif - switch(c->getType()) - { - case RsGxsNotify::TYPE_RECEIVED_NEW: - case RsGxsNotify::TYPE_UPDATED: - case RsGxsNotify::TYPE_PUBLISHED: - { -#ifdef DEBUG_CIRCLES - std::cerr << " Incoming/created/updated Group: " << *git << ". Forcing cache load." << std::endl; -#endif - - // for new circles we need to add them to the list. - // we don't know the type of this circle here - // original behavior was to add all ids to the external ids list - circles_to_reload.insert(RsGxsCircleId(*git)); - - } // fallthrough - case RsGxsNotify::TYPE_STATISTICS_CHANGED: - { - RS_STACK_MUTEX(mKnownCirclesMtx); - mKnownCircles[*git] = time(nullptr); - IndicateConfigChanged(); - } - break; - default: -#ifdef DEBUG_CIRCLES - std::cerr << " Type: " << c->getType() << " is ignored" << std::endl; -#endif - break; - } - - // Now compute which events should be sent. - - if(rsEvents) - { - if(c->getType() == RsGxsNotify::TYPE_RECEIVED_NEW|| c->getType() == RsGxsNotify::TYPE_PUBLISHED) - { - auto ev = std::make_shared(); - ev->mCircleId = RsGxsCircleId(*git); - ev->mCircleEventType = RsGxsCircleEventCode::NEW_CIRCLE; - - rsEvents->postEvent(ev); - - // we also need to look into invitee list here! - - RsGxsCircleGroupItem *new_circle_grp_item = dynamic_cast(groupChange->mNewGroupItem); - - if(new_circle_grp_item) // groups published by us do not come in the mNewGroupItem field. It's possible to add them, in rsgenexchange.cc:2806 - for(auto& gxs_id: new_circle_grp_item->gxsIdSet.ids) - { - auto ev = std::make_shared(); - - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_MEMBERSHIP_ID_ADDED_TO_INVITEE_LIST; - ev->mCircleId = RsGxsCircleId(*git); - ev->mGxsId = gxs_id; - - rsEvents->postEvent(ev); - } - } - else if(c->getType()==RsGxsNotify::TYPE_UPDATED) - { - // Happens when the group data has changed. In this case we need to analyse the old and new group in order to detect possible notifications for clients - - RsGxsCircleGroupItem *old_circle_grp_item = dynamic_cast(groupChange->mOldGroupItem); - RsGxsCircleGroupItem *new_circle_grp_item = dynamic_cast(groupChange->mNewGroupItem); - - if(old_circle_grp_item == nullptr || new_circle_grp_item == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " received GxsGroupUpdate item with mOldGroup and mNewGroup not of type RsGxsCircleGroupItem. This is inconsistent!" << std::endl; - delete groupChange; - continue; - } - - const RsGxsCircleId circle_id ( old_circle_grp_item->meta.mGroupId ); - - // First of all, we check if there is a difference between the old and new list of invited members - - for(auto& gxs_id: new_circle_grp_item->gxsIdSet.ids) - if(old_circle_grp_item->gxsIdSet.ids.find(gxs_id) == old_circle_grp_item->gxsIdSet.ids.end()) - { - auto ev = std::make_shared(); - - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_MEMBERSHIP_ID_ADDED_TO_INVITEE_LIST; - ev->mCircleId = circle_id; - ev->mGxsId = gxs_id; - - rsEvents->postEvent(ev); - } - - for(auto& gxs_id: old_circle_grp_item->gxsIdSet.ids) - if(new_circle_grp_item->gxsIdSet.ids.find(gxs_id) == old_circle_grp_item->gxsIdSet.ids.end()) - { - auto ev = std::make_shared(); - - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_MEMBERSHIP_ID_REMOVED_FROM_INVITEE_LIST; - ev->mCircleId = circle_id; - ev->mGxsId = gxs_id; - - rsEvents->postEvent(ev); - } - - if( old_circle_grp_item->meta.mGroupName != new_circle_grp_item->meta.mGroupName - || old_circle_grp_item->meta.mGroupFlags != new_circle_grp_item->meta.mGroupFlags - || old_circle_grp_item->meta.mAuthorId != new_circle_grp_item->meta.mAuthorId - || old_circle_grp_item->meta.mCircleId != new_circle_grp_item->meta.mCircleId - ) - { - auto ev = std::make_shared(); - ev->mCircleId = RsGxsCircleId(new_circle_grp_item->meta.mGroupId); - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_UPDATED; - rsEvents->postEvent(ev); - } - } - else if(c->getType()==RsGxsNotify::TYPE_GROUP_DELETED) - { - auto ev = std::make_shared(); - - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_DELETED; - ev->mCircleId = RsGxsCircleId(groupChange->mGroupId); - - rsEvents->postEvent(ev); - } - } - } - - delete c; - } - - for(auto& circle_id:circles_to_reload) - force_cache_reload(circle_id); -} - -//====================================================================================// -// Synchroneous API using cache storage // -//====================================================================================// - -bool p3GxsCircles::getCircleDetails(const RsGxsCircleId& id, RsGxsCircleDetails& details) -{ - -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::getCircleDetails(" << id << ")"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - { - bool should_reload = false; - - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - RsGxsCircleCache& data(mCircleCache[id]); - - if(data.mStatus < CircleEntryCacheStatus::LOADING) - should_reload = true; - - if(data.mStatus == CircleEntryCacheStatus::LOADING) - return false; - - // should also have meta data.... - - if(!should_reload) - { - details.mCircleId = id; - details.mCircleName = data.mCircleName; - - details.mCircleType = data.mCircleType; - details.mRestrictedCircleId = data.mRestrictedCircleId; - - details.mAllowedNodes = data.mAllowedNodes; - details.mSubscriptionFlags.clear(); - details.mAllowedGxsIds.clear(); - details.mAmIAllowed = false ; - details.mAmIAdmin = bool(data.mGroupSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN); - - for(std::map::const_iterator it(data.mMembershipStatus.begin());it!=data.mMembershipStatus.end();++it) - { - details.mSubscriptionFlags[it->first] = it->second.subscription_flags ; - - if(it->second.subscription_flags == GXS_EXTERNAL_CIRCLE_FLAGS_ALLOWED) - { - details.mAllowedGxsIds.insert(it->first) ; - - if(rsIdentity->isOwnId(it->first)) - details.mAmIAllowed = true ; - } - } - - return true; - } - } - - cache_request_load(id); - return false; -} - -bool p3GxsCircles::getCircleExternalIdList(std::set &circleIds) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::getCircleIdList()"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - for(auto& cache: mCircleCache) - if(cache.second.mIsExternal) - circleIds.insert(cache.first); - - return true; -} - -bool p3GxsCircles::isLoaded(const RsGxsCircleId &circleId) -{ - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - return mCircleCache.is_cached(circleId) && (mCircleCache[circleId].mStatus >= CircleEntryCacheStatus::UPDATING); -} - -bool p3GxsCircles::loadCircle(const RsGxsCircleId &circleId) -{ - return cache_request_load(circleId); -} - -int p3GxsCircles::canSend(const RsGxsCircleId &circleId, const RsPgpId &id, bool& should_encrypt) -{ - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - if (mCircleCache.is_cached(circleId)) - { - RsGxsCircleCache& data = mCircleCache.ref(circleId); - - if(data.mStatus < CircleEntryCacheStatus::UPDATING) - return 0; - - should_encrypt = (data.mCircleType == RsGxsCircleType::EXTERNAL); - - if (data.isAllowedPeer(id)) - return 1; - - return 0; - } - return -1; -} - -int p3GxsCircles::canReceive(const RsGxsCircleId &circleId, const RsPgpId &id) -{ - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - if (mCircleCache.is_cached(circleId)) - { - RsGxsCircleCache &data = mCircleCache.ref(circleId); - - if(data.mStatus < CircleEntryCacheStatus::UPDATING) - return 0; - - if (data.isAllowedPeer(id)) - { - return 1; - } - return 0; - } - return -1; -} - -bool p3GxsCircles::recipients(const RsGxsCircleId &circleId, std::list& friendlist) -{ - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - if (mCircleCache.is_cached(circleId)) - { - RsGxsCircleCache &data = mCircleCache.ref(circleId); - - if(data.mStatus < CircleEntryCacheStatus::UPDATING) - return 0; - - data.getAllowedPeersList(friendlist); - return true; - } - return false; -} - -bool p3GxsCircles::isRecipient(const RsGxsCircleId &circleId, const RsGxsGroupId& destination_group, const RsGxsId& id) -{ - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - if (mCircleCache.is_cached(circleId)) - { - const RsGxsCircleCache &data = mCircleCache.ref(circleId); - - if(data.mStatus < CircleEntryCacheStatus::UPDATING) - return 0; - - return data.isAllowedPeer(id,destination_group); - } - return false; -} - -// This function uses the destination group for the transaction in order to decide which list of -// keys to ecnrypt to. When sending to a self-restricted group, the list of recipients is extended to -// the admin list rather than just the members list. - -bool p3GxsCircles::recipients(const RsGxsCircleId& circleId, const RsGxsGroupId& dest_group, std::list& gxs_ids) -{ - gxs_ids.clear() ; - - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - if (!mCircleCache.is_cached(circleId)) - return false ; - - const RsGxsCircleCache& cache = mCircleCache.ref(circleId); - - if(cache.mStatus < CircleEntryCacheStatus::UPDATING) - return 0; - - for(std::map::const_iterator it(cache.mMembershipStatus.begin());it!=cache.mMembershipStatus.end();++it) - if(allowedGxsIdFlagTest(it->second.subscription_flags, RsGxsCircleId(dest_group) == circleId)) - gxs_ids.push_back(it->first) ; - - return true; -} - -//====================================================================================// -// Asynchroneous API using token system // -//====================================================================================// - - -bool p3GxsCircles::getGroupData(const uint32_t &token, std::vector &groups) -{ - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsCircleGroupItem* item = dynamic_cast(*vit); - if (item) - { - RsGxsCircleGroup group; - item->convertTo(group); - - // If its cached - add that info (TODO). - groups.push_back(group); - delete(item); - } - else - { - std::cerr << "p3GxsCircles::getGroupData()"; - std::cerr << " Not a RsGxsCircleGroupItem, deleting!"; - std::cerr << std::endl; - delete *vit; - } - } - } - - return ok; -} - -bool p3GxsCircles::getMsgData(const uint32_t &token, std::vector &msgs) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsCircleSubscriptionRequestItem* rsItem = dynamic_cast(*vit); - - if (rsItem) - { - RsGxsCircleMsg msg ;//= rsItem->mMsg; - msg.mMeta = rsItem->meta; - msg.mSubscriptionType = rsItem->subscription_type; - - msgs.push_back(msg); - delete rsItem; - } - else - { - std::cerr << "Not a GxsCircleMsgItem, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -} - -void p3GxsCircles::createGroup(uint32_t& token, RsGxsCircleGroup &group) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::createGroup()"; - std::cerr << " CircleType: " << (uint32_t) group.mMeta.mCircleType; - std::cerr << " CircleId: " << group.mMeta.mCircleId.toStdString(); - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - RsGxsCircleGroupItem* item = new RsGxsCircleGroupItem(); - item->convertFrom(group); - - RsGenExchange::publishGroup(token, item); -} - -void p3GxsCircles::updateGroup(uint32_t &token, RsGxsCircleGroup &group) -{ - // note: refresh of circle cache gets triggered in the RsGenExchange::notifyChanges() callback - RsGxsCircleGroupItem* item = new RsGxsCircleGroupItem(); - item->convertFrom(group); - - RsGenExchange::updateGroup(token, item); -} - -RsGenExchange::ServiceCreate_Return p3GxsCircles::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& /*keySet*/) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::service_CreateGroup()"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - RsGxsCircleGroupItem *item = dynamic_cast(grpItem); - if (!item) - { - std::cerr << "p3GxsCircles::service_CreateGroup() ERROR invalid cast"; - std::cerr << std::endl; - return SERVICE_CREATE_FAIL; - } - - // Now copy the GroupId into the mCircleId, and set the mode. - if (item->meta.mCircleType == GXS_CIRCLE_TYPE_EXT_SELF) - { - item->meta.mCircleType = GXS_CIRCLE_TYPE_EXTERNAL; - item->meta.mCircleId = RsGxsCircleId(item->meta.mGroupId); - } - - return SERVICE_CREATE_SUCCESS; -} - -//====================================================================================// -// Cache system management // -//====================================================================================// - -RsGxsCircleCache::RsGxsCircleCache() -{ - mCircleType = RsGxsCircleType::EXTERNAL; - mIsExternal = true; - mLastUpdateTime = 0; - mGroupStatus = 0; - mGroupSubscribeFlags = 0; - mLastUpdatedMembershipTS = 0 ; - mStatus = CircleEntryCacheStatus::NO_DATA_YET; - mAllIdsHere = false; - mDoIAuthorAMembershipMsg = false; - - return; -} - -bool RsGxsCircleCache::loadBaseCircle(const RsGxsCircleGroup& circle) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "RsGxsCircleCache::loadBaseCircle(" << mCircleId << "):" << std::endl; -#endif // DEBUG_CIRCLES - - mCircleId = RsGxsCircleId(circle.mMeta.mGroupId); - mCircleName = circle.mMeta.mGroupName; - // mProcessedCircles.insert(mCircleId); - - mCircleType = static_cast(circle.mMeta.mCircleType); - mIsExternal = (mCircleType != RsGxsCircleType::LOCAL); - mGroupStatus = circle.mMeta.mGroupStatus; - mGroupSubscribeFlags = circle.mMeta.mSubscribeFlags; - mOriginator = circle.mMeta.mOriginator ; - - mAllowedNodes = circle.mLocalFriends ; - mRestrictedCircleId = circle.mMeta.mCircleId ; - - // We do not clear mMembershipStatus because this might be an update and if we do, it will clear membership requests - // that are not in the invited list! - - for(std::set::const_iterator it(circle.mInvitedMembers.begin());it!=circle.mInvitedMembers.end();++it) - { - RsGxsCircleMembershipStatus& s(mMembershipStatus[*it]) ; - s.subscription_flags |= GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST ; - - // This one can be cleared because it will anyway be updated to the latest when loading subscription request messages and it wil only - // be used there as well. - - s.last_subscription_TS = 0 ; - -#ifdef DEBUG_CIRCLES - std::cerr << " Invited member " << *it << " Initializing/updating membership status to " << std::hex << s.subscription_flags << std::dec << std::endl; -#endif // DEBUG_CIRCLES - } - - // also sweep through the list of subscribed members and remove the membership to those who are not in the invitee list anymore - - for(auto& m:mMembershipStatus) - if(circle.mInvitedMembers.find(m.first) == circle.mInvitedMembers.end()) - { - m.second.subscription_flags &= ~GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST; -#ifdef DEBUG_CIRCLES - std::cerr << " member " << m.first << " is not in invitee list. Updating flags to " << std::hex << m.second.subscription_flags << std::dec << std::endl; -#endif // DEBUG_CIRCLES - } - - return true; -} - -bool RsGxsCircleCache::loadSubCircle(const RsGxsCircleCache &subcircle) -{ - /* copy across all the lists */ - - /* should not be any unprocessed circles or peers */ -#ifdef DEBUG_CIRCLES -#endif // DEBUG_CIRCLES - - std::cerr << "RsGxsCircleCache::loadSubCircle(" << subcircle.mCircleId << ") TODO"; - std::cerr << std::endl; - - return true; -} - -bool RsGxsCircleCache::getAllowedPeersList(std::list& friendlist) const -{ - friendlist.clear() ; - - for(auto it = mAllowedNodes.begin(); it != mAllowedNodes.end(); ++it) - friendlist.push_back(*it) ; - - return true; -} - -bool RsGxsCircleCache::isAllowedPeer(const RsGxsId& id,const RsGxsGroupId& destination_group) const -{ - auto it = mMembershipStatus.find(id) ; - - if(it == mMembershipStatus.end()) - return false ; - - return allowedGxsIdFlagTest(it->second.subscription_flags, RsGxsGroupId(mCircleId) == destination_group) ; -} - -bool RsGxsCircleCache::isAllowedPeer(const RsPgpId &id) const -{ - return mAllowedNodes.find(id) != mAllowedNodes.end() ; -} - -bool RsGxsCircleCache::addLocalFriend(const RsPgpId &pgpId) -{ - /* empty list as no GxsID associated */ - mAllowedNodes.insert(pgpId) ; - return true; -} - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ -// Complicated deal of loading Circles. - -bool p3GxsCircles::force_cache_reload(const RsGxsCircleId& id) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::force_cache_reload(): Forcing cache reload of Circle ID " << id << std::endl; -#endif - - cache_request_load(id) ; - return true ; -} - -bool p3GxsCircles::cache_request_load(const RsGxsCircleId &id) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::cache_request_load(" << id << ")"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - { - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - /* check it is not already being loaded */ - - RsGxsCircleCache& cache(mCircleCache[id]); - - if(cache.mStatus < CircleEntryCacheStatus::LOADING) - cache.mCircleId = id; - - if(cache.mStatus == CircleEntryCacheStatus::LOADING || cache.mStatus == CircleEntryCacheStatus::UPDATING) - return false; - - // Put it into the Loading Cache - so we will detect it later. - - if(cache.mLastUpdateTime > 0) - cache.mStatus = CircleEntryCacheStatus::UPDATING; - else - cache.mStatus = CircleEntryCacheStatus::LOADING; - - mCirclesToLoad.insert(id); - } - - if (RsTickEvent::event_count(CIRCLE_EVENT_CACHELOAD) > 0) /* its already scheduled */ - return true; - - int32_t age = 0; - if (RsTickEvent::prev_event_ago(CIRCLE_EVENT_CACHELOAD, age) && age groupIds; - { - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - /* now we process the modGroupList -> a map so we can use it easily later, and create id list too */ - - for(auto& circle_id:mCirclesToLoad) - { -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::cache_start_load() GroupId: " << circle_id << std::endl; -#endif // DEBUG_CIRCLES - - groupIds.push_back(RsGxsGroupId(circle_id.toStdString())); // might need conversion? - } - - mCirclesToLoad.clear(); - } - - if (groupIds.size() > 0) - { -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::cache_start_load() #Groups: " << groupIds.size(); - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts, groupIds); - GxsTokenQueue::queueRequest(token, CIRCLEREQ_CACHELOAD); - } - return true; -} - - -bool p3GxsCircles::cache_load_for_token(uint32_t token) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::cache_load_for_token() : " << token << std::endl; -#endif // DEBUG_CIRCLES - - std::vector grpData; - - if(!RsGenExchange::getGroupData(token, grpData)) - { - std::cerr << "p3GxsCircles::cache_load_for_token() ERROR no data"; - std::cerr << std::endl; - - return false; - } - - for(auto vit = grpData.begin(); vit != grpData.end(); ++vit) - { - RsGxsCircleGroupItem *item = dynamic_cast(*vit); - - if (!item) - { - std::cerr << " Not a RsGxsCircleGroupItem Item, deleting!" << std::endl; - delete(*vit); - continue; - } - RsGxsCircleGroup group; - item->convertTo(group); - -#ifdef DEBUG_CIRCLES - std::cerr << " Loaded Id with Meta: " << item->meta << std::endl; -#endif // DEBUG_CIRCLES - - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - /* should already have a LoadingCache entry */ - RsGxsCircleId id = RsGxsCircleId(item->meta.mGroupId) ; - RsGxsCircleCache& cache(mCircleCache[id]); - - cache.loadBaseCircle(group); - delete item; - - if(locked_processLoadingCacheEntry(cache)) - { -#ifdef DEBUG_CIRCLES - std::cerr << " All peers available. Moving to cache..." << std::endl; -#endif - cache.mAllIdsHere = true; - - // We can check for self inclusion in the circle right away, since own ids are always loaded. - // that allows to subscribe/unsubscribe uncomplete circles - - cache.mStatus = CircleEntryCacheStatus::CHECKING_MEMBERSHIP; - cache.mLastUpdatedMembershipTS = 0; // force processing of membership request - locked_checkCircleCacheForMembershipUpdate(cache); - } - else - { -#ifdef DEBUG_CIRCLES - std::cerr << " Unprocessed peers. Requesting reload..." << std::endl; -#endif - cache.mAllIdsHere = false; - cache.mStatus = CircleEntryCacheStatus::UPDATING; - - /* schedule event to try reload gxsIds */ - RsTickEvent::schedule_in(CIRCLE_EVENT_RELOADIDS, GXSID_LOAD_CYCLE, id.toStdString()); - } - mShouldSendCacheUpdateNotification = true; - } - - return true; -} - -// This method parses the cache entry and makes sure that all ids are known. If not, requests the missing ids -// when done, the entry is removed from mLoadingCache - -bool p3GxsCircles::locked_processLoadingCacheEntry(RsGxsCircleCache& cache) -{ - //bool isUnprocessedPeers = false; - - if (!cache.mIsExternal) - return true; - -#ifdef DEBUG_CIRCLES - std::cerr << "Processing External Circle " << cache.mCircleId << std::endl; -#endif - bool all_ids_here = true; - - // Do we actually need to retrieve the missing keys for all members of a circle??? - // These keys are needed for subscribtion request signature checking. But this is only - // when a subscription msg is posted, which would trigger retrieval of the key anyway - // Maybe this can be made an option of p3GxsCircles, or of rsIdentity. - - // need to trigger the searches. - for(std::map::iterator pit = cache.mMembershipStatus.begin(); pit != cache.mMembershipStatus.end(); ++pit) - { -#ifdef DEBUG_CIRCLES - std::cerr << " Member status: " << pit->first << " : " << pit->second.subscription_flags; -#endif - - /* check cache */ - if(!(pit->second.subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE)) - { - if(mIdentities->haveKey(pit->first)) - { - pit->second.subscription_flags |= GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE; - -#ifdef DEBUG_CIRCLES - std::cerr << " Key is now available!"<< std::endl; -#endif - } - else - { - std::list peers; - - if(!cache.mOriginator.isNull()) - { - peers.push_back(cache.mOriginator) ; -#ifdef DEBUG_CIRCLES - std::cerr << " Requesting unknown/unloaded identity: " << pit->first << " to originator " << cache.mOriginator << std::endl; -#endif - } - else - { -#ifdef DEBUG_CIRCLES - std::cerr << " (WW) cache entry for circle " << cache.mCircleId << " has empty originator. Asking info for GXS id " << pit->first << " to all connected friends." << std::endl; -#endif - - rsPeers->getOnlineList(peers) ; - } - - mIdentities->requestKey(pit->first, peers,RsIdentityUsage(RsServiceType::GXSCIRCLE,RsIdentityUsage::CIRCLE_MEMBERSHIP_CHECK,RsGxsGroupId(cache.mCircleId))); - - all_ids_here = false; - } - } -#ifdef DEBUG_CIRCLES - else - std::cerr << " Key is available. Nothing to process." << std::endl; -#endif - } - - return all_ids_here; -} - -bool p3GxsCircles::cache_reloadids(const RsGxsCircleId &circleId) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::cache_reloadids()"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - RsGxsCircleCache& cache(mCircleCache[circleId]); - - /* fetch from loadMap */ - - if(locked_processLoadingCacheEntry(cache)) - { - cache.mAllIdsHere = true; - - // We can check for self inclusion in the circle right away, since own ids are always loaded. - // that allows to subscribe/unsubscribe uncomplete circles - - cache.mStatus = CircleEntryCacheStatus::CHECKING_MEMBERSHIP; - locked_checkCircleCacheForMembershipUpdate(cache); - - std::cerr << " Loading complete." << std::endl; - - return true ; - } - - else - { - cache.mAllIdsHere = false; - -#ifdef DEBUG_CIRCLES - std::cerr << " Unprocessed peers. Requesting reload for circle " << circleId << std::endl; -#endif - - /* schedule event to try reload gxsIds */ - RsTickEvent::schedule_in(CIRCLE_EVENT_RELOADIDS, GXSID_LOAD_CYCLE, circleId.toStdString()); - } - - return true; -} - -bool p3GxsCircles::checkCircleCache() -{ -#ifdef DEBUG_CIRCLES - std::cerr << "checkCircleCache(): calling auto-subscribe check and membership update check." << std::endl; -#endif - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - mCircleCache.applyToAllCachedEntries(*this,&p3GxsCircles::locked_checkCircleCacheForMembershipUpdate) ; - - return true ; -} - -bool p3GxsCircles::locked_setGroupUnprocessedStatus(RsGxsCircleCache& cache,bool unprocessed) -{ - uint32_t token2; - - if(unprocessed) - cache.mGroupStatus |= GXS_SERV::GXS_GRP_STATUS_UNPROCESSED; - else - cache.mGroupStatus &= ~GXS_SERV::GXS_GRP_STATUS_UNPROCESSED; - - RsGenExchange::setGroupStatusFlags(token2, RsGxsGroupId(cache.mCircleId), unprocessed, GXS_SERV::GXS_GRP_STATUS_UNPROCESSED); - - // Now we need to async acknowledge the token when the job is finished. We cannot do this sync because it's the - // current thread that takes care of calling the handling of group processing. - - RsThread::async([token2,this]() - { - std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000); - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100); - - auto timeout = std::chrono::steady_clock::now() + maxWait; // wait for 10 secs at most - auto st = requestStatus(token2); - - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = requestStatus(token2); - } - - RsGxsGroupId grpId; - acknowledgeGrp(token2,grpId); - }); - return true; -} - -bool p3GxsCircles::locked_subscribeToCircle(const RsGxsCircleId &grpId, bool subscribe) -{ - uint32_t token; - if(!RsGenExchange::subscribeToGroup(token, RsGxsGroupId(grpId), subscribe)) - return false; - - // Now we need to async acknowledge the token when the job is finished. We cannot do this sync because it's the - // current thread that takes care of calling the handling of group processing. - - RsThread::async([token,this]() - { - std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000); - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100); - - auto timeout = std::chrono::steady_clock::now() + maxWait; // wait for 10 secs at most - auto st = requestStatus(token); - - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = requestStatus(token); - } - - RsGxsGroupId grpId; - acknowledgeGrp(token,grpId); - }); - - return true; -} - -bool p3GxsCircles::locked_checkCircleCacheForMembershipUpdate(RsGxsCircleCache& cache) -{ - rstime_t now = time(NULL) ; - - if(cache.mStatus < CircleEntryCacheStatus::UPDATING) - return false; - - if(cache.mLastUpdatedMembershipTS + GXS_CIRCLE_DELAY_TO_FORCE_MEMBERSHIP_UPDATE < now) - { -#ifdef DEBUG_CIRCLES - std::cerr << "Cache entry for circle " << cache.mCircleId << " needs a swab over membership requests. Re-scheduling it." << std::endl; -#endif - locked_setGroupUnprocessedStatus(cache,true); // forces the re-check of the group - - // this should be called regularly - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - std::list grpIds ; - uint32_t token2; - - grpIds.push_back(RsGxsGroupId(cache.mCircleId)) ; - - RsGenExchange::getTokenService()->requestMsgInfo(token2, RS_TOKREQ_ANSTYPE_SUMMARY, opts, grpIds); - GxsTokenQueue::queueRequest(token2, CIRCLEREQ_MESSAGE_DATA); - } - return true ; -} - -/* We need to AutoSubscribe if the Circle is relevent to us */ - -bool p3GxsCircles::locked_checkCircleCacheForAutoSubscribe(RsGxsCircleCache& cache) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::locked_checkCircleCacheForAutoSubscribe() : "<< cache.mCircleId << std::endl; -#endif - - /* if processed already - ignore */ - if (!(cache.mGroupStatus & GXS_SERV::GXS_GRP_STATUS_UNPROCESSED)) - { -#ifdef DEBUG_CIRCLES - std::cerr << " Already Processed" << std::endl; -#endif - - return false; - } - - /* if personal - we created ... is subscribed already */ - if (!cache.mIsExternal) - { -#ifdef DEBUG_CIRCLES - std::cerr << " Personal Circle. Nothing to do." << std::endl; -#endif - - return false; - } - - if(cache.mStatus < CircleEntryCacheStatus::UPDATING) - return false; - - /* if we appear in the group - then autosubscribe, and mark as processed. This also applies if we're the group admin */ - - std::list myOwnIds; - - if(!rsIdentity->getOwnIds(myOwnIds)) - { - std::cerr << " own ids not loaded yet." << std::endl; - - /* schedule event to try reload gxsIds */ - RsTickEvent::schedule_in(CIRCLE_EVENT_RELOADIDS, GXSID_LOAD_CYCLE, cache.mCircleId.toStdString()); - return false ; - } - - bool am_I_invited = false ; - - for(std::list::const_iterator it(myOwnIds.begin());it!=myOwnIds.end() && (!am_I_invited);++it) - { - std::map::const_iterator it2 = cache.mMembershipStatus.find(*it) ; - - if(it2 != cache.mMembershipStatus.end()) - am_I_invited = am_I_invited || bool(it2->second.subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) ; - } - - bool am_I_admin( cache.mGroupSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) ; - bool do_I_have_a_msg( cache.mDoIAuthorAMembershipMsg ); - -#ifdef DEBUG_CIRCLES - std::cerr << " own ID invited in circle: " << am_I_invited << ", membership msg author: " << do_I_have_a_msg << ", admin: " << am_I_admin << std::endl; -#endif - if(do_I_have_a_msg || am_I_admin) - { - if(! (cache.mGroupSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED)) - { -#ifdef DEBUG_CIRCLES - /* we are part of this group - subscribe, clear unprocessed flag */ - std::cerr << " either admin or have posted a subscribe/unsubscribe message => AutoSubscribing!" << std::endl; -#endif - locked_subscribeToCircle(cache.mCircleId,true); - mShouldSendCacheUpdateNotification = true; - } -#ifdef DEBUG_CIRCLES - else - std::cerr << " either admin or have posted a subscribe/unsubscribe message, already subscribed." << std::endl; -#endif - - cache.mGroupStatus &= ~GXS_SERV::GXS_GRP_STATUS_UNPROCESSED; - - return true; - } - else - { - /* we know all the peers - we are not part - we can flag as PROCESSED. */ - if(cache.mGroupSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) - { - locked_subscribeToCircle(cache.mCircleId,false); - mShouldSendCacheUpdateNotification = true; -#ifdef DEBUG_CIRCLES - std::cerr << " Neither admin nor subscription msg author! Let's unsubscribe this circle of unfriendly Napoleons!" << std::endl; -#endif - } -#ifdef DEBUG_CIRCLES - else - std::cerr << " Neither admin nor subscription msg author! Not subscribed either." << std::endl; -#endif - return true ; - } - -#ifdef DEBUG_CIRCLES - std::cerr << " Marking the cache entry as processed." << std::endl; -#endif - locked_setGroupUnprocessedStatus(cache,false); - - return true; -} - -rstime_t p3GxsCircles::service_getLastGroupSeenTs(const RsGxsGroupId& gid) -{ - rstime_t now = time(nullptr); - - RS_STACK_MUTEX(mKnownCirclesMtx); - - auto it = mKnownCircles.find(gid); - bool unknown_posted = (it == mKnownCircles.end()); - - if(unknown_posted) - { - mKnownCircles[gid] = now; - IndicateConfigChanged(); - return now; - } - else - return it->second; -} -bool p3GxsCircles::service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) -{ -#ifdef GXSFORUMS_CIRCLES - std::cerr << "p3gxsChannels: Checking unused circles: called by GxsCleaning." << std::endl; -#endif - - // request all group infos at once - - rstime_t now = time(nullptr); - - RS_STACK_MUTEX(mKnownCirclesMtx); - - auto it = mKnownCircles.find(meta.mGroupId); - bool unknown_posted = (it == mKnownCircles.end()); - -#ifdef GXSFORUMS_CIRCLES - std::cerr << " Circle " << meta.mGroupId ; -#endif - - if(unknown_posted) - { - // This case should normally not happen. It does because this board was never registered since it may - // arrived before this code was here - -#ifdef GXSFORUMS_CIRCLES - std::cerr << ". Not known yet. Adding current time as new TS." << std::endl; -#endif - mKnownCircles[meta.mGroupId] = now; - IndicateConfigChanged(); - - return true; - } - else - { - bool used_by_friends = (now < it->second + CIRCLES_UNUSED_BY_FRIENDS_DELAY); - bool subscribed = static_cast(meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED); - -#ifdef GXSFORUMS_CIRCLES - std::cerr << ". subscribed: " << subscribed << ", used_by_friends: " << used_by_friends << " last TS: " << now - it->second << " secs ago (" << (now-it->second)/86400 << " days)"; -#endif - - if(!subscribed && !used_by_friends) - { -#ifdef GXSFORUMS_CIRCLES - std::cerr << ". Scheduling for deletion" << std::endl; -#endif - return false; - } - else - { -#ifdef GXSFORUMS_CIRCLES - std::cerr << ". Keeping!" << std::endl; -#endif - return true; - } - } -} - -//====================================================================================// -// Event handling // -//====================================================================================// - - // Overloaded from GxsTokenQueue for Request callbacks. -void p3GxsCircles::handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::handleResponse(" << token << "," << req_type << "," << status << ")" << std::endl; -#endif // DEBUG_CIRCLES - if (status != RsTokenService::COMPLETE) - return; //For now, only manage Complete request - - - // stuff. - switch(req_type) - { - case CIRCLEREQ_MESSAGE_DATA: - processMembershipRequests(token); - break; - - case CIRCLEREQ_CACHELOAD: - cache_load_for_token(token); - break; - default: - RsErr() << __PRETTY_FUNCTION__ << " Unknown Request Type: " - << req_type << std::endl; - break; - } -} - - // Overloaded from RsTickEvent for Event callbacks. -void p3GxsCircles::handle_event(uint32_t event_type, const std::string &elabel) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::handle_event(" << event_type << ")"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - // stuff. - switch(event_type) - { - case CIRCLE_EVENT_CACHELOAD: - cache_start_load(); - break; - - case CIRCLE_EVENT_RELOADIDS: - cache_reloadids(RsGxsCircleId(elabel)); - break; - - case CIRCLE_EVENT_DUMMYSTART: - generateDummyData(); - break; - - case CIRCLE_EVENT_DUMMYLOAD: - checkDummyIdData(); - break; - - case CIRCLE_EVENT_DUMMYGEN: - generateDummyCircle(); - break; - - default: - RsErr() << __PRETTY_FUNCTION__ << " Unknown Event Type: " << event_type - << std::endl; - break; - } -} - -//====================================================================================// -// Membership request handling // -//====================================================================================// - -// Circle membership is requested/denied by posting a message into the cicle group, according to the following rules: -// -// - a subscription request is a RsItem (which serialises into a radix64 message, that is further signed by the group message publishing system) -// The item contains: -// * subscribe order (yes/no), boolean -// * circle ID (this is important, otherwise people can copy subscribe messages from one circle to another) -// * subscribe date -// * subscribe timeout (how long is the message kept. When timed out, the message is removed and subscription cancelled) -// -// - subscribe messages follow the following rules, which are enforced by a timer-based method: -// * subscription requests from a given user are always replaced by the last subscription request -// * a complete list of who's subscribed to a given group is kept, saved, and regularly updated when new subscribe messages are received, or when admin list is changed. -// * getGroupDetails reads this list in order to respond who's subscribed to a group. The list of -// -// - compatibility with self-restricted circles: -// * subscription should be based on admin list, so that non subscribed peers still receive the invitation -// -// - two possible subscription models for circle member list (Restricted forums only propagate to members): -// 1 - list of admin who have not opposed subscription -// - solves propagation issue. Only admin see data. They can however unsubscribe using a negative req. Admin needs to remove them. -// - bad for security. Admin can refuse to remove them => back to square one -// 2 - list of admin who have also requested membership -// - propagation is ok. On restricted circle, the circle msgs/group should be sent to admin list, instead of member list. -// - solves membership issue since people need to actively be in the group. -// => choose 2 -// - forum group : encrypted for Member list -// - circle group : clear / encrypted for admin list (for self-restricted) -// We decide between the two by comparing the group we're sending and the circle id it is restricted to. -// -// - Use cases -// * user sees group (not self restricted) and requests to subscribe => RS subscribes the group and the user can propagate the response -// * user is invited to self-restricted circle. He will see it and can subscribe, so he will be in admin list and receive e.g. forum posts. -// * -// -// - Threat model -// * a malicious user forges a new subscription request: NP-hard as it needs to break the RSA key of the GXS id. -// * a malicious corrupts a subscription request: NP-hard. Messages are signed. -// * a malicious user copies an old subscription of someone else and inserts it in the system. -// => not possible. Either this existing old susbscription already exists, or it has been replaced by a more recent one, which -// will always replace the old one because of the date. -// * a malicious user removes someone's subscription messages. This is possible, but the mesh nature of the network will allow the message to propagate anyway. -// * a malicious user creates a circle with an incriminating name/content and adds everyone in it -// => people can oppose their membership in the circle using a msg -// -// -// - the table below summarizes the various choices: forum and circle propagation when restricted to a circle, and group subscribe to the circle -// -// +------------------------------+-----------------------------+ -// | User in admin list | User not in admin list | -// +-------------+------------------------------+-----------------------------+ -// | User request| Forum Grp/Msg: YES | Forum Grp/Msg: NO | -// | Subscription| Circle Grp/Msg: YES/YES | Circle Grp/Msg: YES/NO | -// | | Grp Subscribed: YES | Grp Subscribed: YES | -// +-------------+------------------------------+-----------------------------+ -// | No request | Forum Grp/Msg: NO | Forum Grp/Msg: NO | -// | Subscription| Circle Grp/Msg: YES/YES | Circle Grp/Msg: YES/NO | -// | | Grp Subscribed: NO | Grp Subscribed: NO | -// +-------------+------------------------------+-----------------------------+ - -bool p3GxsCircles::pushCircleMembershipRequest( const RsGxsId& own_gxsid, const RsGxsCircleId& circle_id, RsGxsCircleSubscriptionType request_type ) -{ - Dbg3() << __PRETTY_FUNCTION__ << "own_gxsid = " << own_gxsid - << ", circle=" << circle_id << ", req type=" << request_type - << std::endl; - - if( request_type != RsGxsCircleSubscriptionType::SUBSCRIBE && request_type != RsGxsCircleSubscriptionType::UNSUBSCRIBE ) - { - RsErr() << __PRETTY_FUNCTION__ << " Unknown request type: " << static_cast(request_type) << std::endl; - return false; - } - - if(!rsIdentity->isOwnId(own_gxsid)) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot generate membership request " - << "from not-own id: " << own_gxsid << std::endl; - return false; - } - - if(!getCirclesInfo( std::list{static_cast(circle_id)}, RS_DEFAULT_STORAGE_PARAM(std::vector) )) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot generate membership request from unknown circle: " << circle_id << std::endl; - return false; - } - // If the circle is not subscribed, then subscribe, whatever the subscription type. Indeed, if we publish a msg, even a msg for - // unsubscribing, we need to have a subscribed group first. - - if(!locked_subscribeToCircle(circle_id,true)) - { - std::cerr << __PRETTY_FUNCTION__ << " Could not subscribe to Circle group." << std::endl; - return false; - } - - // Create a subscribe item - - RsGxsCircleSubscriptionRequestItem *s = new RsGxsCircleSubscriptionRequestItem ; - - s->time_stamp = time(NULL) ; - s->time_out = 0 ; // means never - s->subscription_type = request_type ; - - RsTemporaryMemory tmpmem(circle_id.serial_size() + own_gxsid.serial_size()) ; - - uint32_t off = 0 ; - circle_id.serialise(tmpmem,tmpmem.size(),off) ; - own_gxsid.serialise(tmpmem,tmpmem.size(),off) ; - - s->meta.mGroupId = RsGxsGroupId(circle_id) ; - s->meta.mMsgId.clear(); - s->meta.mThreadId = RsGxsMessageId(RsDirUtil::sha1sum(tmpmem,tmpmem.size())); // make the ID from the hash of the cirle ID and the author ID - s->meta.mAuthorId = own_gxsid; - - // msgItem->meta.mParentId = ; // leave these blank - // msgItem->meta.mOrigMsgId= ; - -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::publishSubscribeRequest()" << std::endl; - std::cerr << " GroupId : " << circle_id << std::endl; - std::cerr << " AuthorId : " << s->meta.mAuthorId << std::endl; - std::cerr << " ThreadId : " << s->meta.mThreadId << std::endl; -#endif - - uint32_t token; - RsGenExchange::publishMsg(token, s); - - // This is manual handling of token. We need to clear it up from the notification when done, and that needs - // to be async-ed, since the processing of message publication is done in the same thread. - - RsThread::async( [this,token]() - { - std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000); - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100); - - auto timeout = std::chrono::steady_clock::now() + maxWait; // wait for 10 secs at most - auto st = requestStatus(token); - - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = requestStatus(token); - } - - std::pair grpmsgId; - acknowledgeMsg(token,grpmsgId); - }); - - // update the cache. - force_cache_reload(circle_id); - - return true; -} - -bool p3GxsCircles::requestCircleMembership(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id) -{ - return pushCircleMembershipRequest(own_gxsid,circle_id,RsGxsCircleSubscriptionType::SUBSCRIBE) ; -} -bool p3GxsCircles::cancelCircleMembership(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id) -{ - return pushCircleMembershipRequest(own_gxsid,circle_id,RsGxsCircleSubscriptionType::UNSUBSCRIBE) ; -} - -bool p3GxsCircles::locked_processMembershipMessages(RsGxsCircleCache& cache, const std::vector& items, GxsMsgReq& messages_to_delete, const std::set &own_ids) -{ -#ifdef DEBUG_CIRCLES - std::cerr << " Circle found in cache!" << std::endl; - std::cerr << " Retrieving messages..." << std::endl; -#endif - cache.mDoIAuthorAMembershipMsg = false; // default - - for(uint32_t i=0;imeta.mGroupId << ", Message ID: " << items[i]->meta.mMsgId << ", thread ID: " << items[i]->meta.mThreadId << ", author: " << items[i]->meta.mAuthorId << ": " ; -#endif - RsGxsCircleSubscriptionRequestItem *item = dynamic_cast(items[i]) ; - - if(item == NULL) - { - std::cerr << " (EE) item is not a RsGxsCircleSubscriptionRequestItem. Weird. Scheduling for deletion." << std::endl; - - messages_to_delete[RsGxsGroupId(cache.mCircleId)].insert(item->meta.mMsgId); - continue ; - } - - RsGxsCircleMembershipStatus& info(cache.mMembershipStatus[item->meta.mAuthorId]) ; - -#ifdef DEBUG_CIRCLES - std::cerr << " " << time(NULL) - item->time_stamp << " seconds ago, " ; -#endif - - if(info.last_subscription_TS <= item->time_stamp) // the <= here allows to make sure we update the flags is something happenned - { - info.last_subscription_TS = item->time_stamp ; - - if(item->subscription_type == RsGxsCircleSubscriptionType::SUBSCRIBE) - info.subscription_flags |= GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED; - else if(item->subscription_type == RsGxsCircleSubscriptionType::UNSUBSCRIBE) - info.subscription_flags &= ~GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED; - else - std::cerr << " (EE) unknown subscription order type: " << static_cast(item->subscription_type) ; - - mShouldSendCacheUpdateNotification = true; -#ifdef DEBUG_CIRCLES - std::cerr << " UPDATING status to " << std::hex << info.subscription_flags << std::dec << std::endl; -#endif - - if(own_ids.end() != own_ids.find(item->meta.mAuthorId)) // we have at least one subscribe/unsubscribe message. So we update the flag accordingly. - cache.mDoIAuthorAMembershipMsg = true; - } - else if(info.last_subscription_TS > item->time_stamp) - std::cerr << " Too old: item->TS=" << item->time_stamp << ", last_subscription_TS=" << info.last_subscription_TS << ". IGNORING." << std::endl; - } - - // now do another sweep and remove all msgs that are older than the latest - -#ifdef DEBUG_CIRCLES - std::cerr << " Cleaning older messages..." << std::endl; -#endif - - for(uint32_t i=0;imeta.mAuthorId]) ; - RsGxsCircleSubscriptionRequestItem *item = dynamic_cast(items[i]) ; - - if(item && info.last_subscription_TS > item->time_stamp) - { -#ifdef DEBUG_CIRCLES - std::cerr << " " << item->meta.mMsgId << ": Older than last known (" << (long int)info.last_subscription_TS - (long int)item->time_stamp << " seconds before): deleting." << std::endl; -#endif - messages_to_delete[RsGxsGroupId(cache.mCircleId)].insert(item->meta.mMsgId) ; - } - } - -#ifdef DEBUG_CIRCLES - std::cerr << " Cleaning older messages..." << std::endl; -#endif - - cache.mLastUpdatedMembershipTS = time(NULL) ; - cache.mStatus = CircleEntryCacheStatus::UP_TO_DATE; - cache.mLastUpdateTime = time(NULL); - mShouldSendCacheUpdateNotification = true; - - return true; -} - -bool p3GxsCircles::processMembershipRequests(uint32_t token) -{ - // Go through membership request messages and process them according to the following rule: - // * for each ID only keep the latest membership request. Delete the older ones. - // * for each circle, keep a list of IDs sorted into membership categories (e.g. keep updated flags for each IDs) - // Because msg loading is async-ed, the job in split in two methods: one calls the loading, the other one handles the loaded data. - -#ifdef DEBUG_CIRCLES - std::cerr << "Processing circle membership requests." << std::endl; -#endif - t_RsGxsGenericDataTemporaryMapVector msgItems; - - if(!RsGenExchange::getMsgData(token, msgItems)) - { - std::cerr << "(EE) Cannot get msg data for circle. Something's weird." << std::endl; - return false; - } - - std::list own_ids ; - rsIdentity->getOwnIds(own_ids); - std::set own_ids_set; - for(auto& id:own_ids) - own_ids_set.insert(id); - - GxsMsgReq messages_to_delete ; - - for(GxsMsgDataMap::const_iterator it(msgItems.begin());it!=msgItems.end();++it) - { - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ -#ifdef DEBUG_CIRCLES - std::cerr << " Circle ID: " << it->first << std::endl; -#endif - // Find the circle ID in cache and process the list of messages to keep the latest order in time. - - RsGxsCircleId circle_id(it->first); - RsGxsCircleCache& cache( mCircleCache[circle_id] ); - - // First process membership messages -#ifdef DEBUG_CIRCLES - std::cerr << " Processing membership messages..." << std::endl; -#endif - locked_processMembershipMessages(cache,it->second,messages_to_delete,own_ids_set); -#ifdef DEBUG_CIRCLES - std::cerr << " Now checking for auto-subscribe..." << std::endl; -#endif - locked_checkCircleCacheForAutoSubscribe(cache); - } - - if(!messages_to_delete.empty()) - { - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - uint32_t token2; - RsGenExchange::deleteMsgs(token2,messages_to_delete); - } - return true ; -} - -//====================================================================================// -// p3Config methods // -//====================================================================================// - -static const uint32_t GXS_FORUMS_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months -static const uint8_t GXS_CIRCLES_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ; - -struct RsGxsCirclesNotifyRecordsItem: public RsItem -{ - - RsGxsCirclesNotifyRecordsItem() - : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_CIRCLES_CONFIG,GXS_CIRCLES_CONFIG_SUBTYPE_NOTIFY_RECORD) - {} - - virtual ~RsGxsCirclesNotifyRecordsItem() {} - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { RS_SERIAL_PROCESS(records); } - - void clear() {} - - std::map records; -}; - -class GxsCirclesConfigSerializer : public RsServiceSerializer -{ -public: - GxsCirclesConfigSerializer() : RsServiceSerializer(RS_SERVICE_GXS_TYPE_CIRCLES_CONFIG) {} - virtual ~GxsCirclesConfigSerializer() {} - - RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const - { - if(service_id != RS_SERVICE_GXS_TYPE_CIRCLES_CONFIG) - return NULL; - - switch(item_sub_id) - { - case GXS_CIRCLES_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsCirclesNotifyRecordsItem(); - default: - return NULL; - } - } -}; - -bool p3GxsCircles::saveList(bool& cleanup, std::list&saveList) -{ - cleanup = true ; - - RsGxsCirclesNotifyRecordsItem *item = new RsGxsCirclesNotifyRecordsItem ; - - { - RS_STACK_MUTEX(mKnownCirclesMtx); - item->records = mKnownCircles ; - } - - saveList.push_back(item) ; - return true; -} - -bool p3GxsCircles::loadList(std::list& loadList) -{ - while(!loadList.empty()) - { - RsItem *item = loadList.front(); - loadList.pop_front(); - - rstime_t now = time(NULL); - - RsGxsCirclesNotifyRecordsItem *fnr = dynamic_cast(item) ; - - if(fnr != NULL) - { - RS_STACK_MUTEX(mKnownCirclesMtx); - - mKnownCircles.clear(); - - for(auto it(fnr->records.begin());it!=fnr->records.end();++it) - if( now < it->second + GXS_FORUMS_CONFIG_MAX_TIME_NOTIFY_STORAGE) - mKnownCircles.insert(*it) ; - } - - delete item ; - } - return true; -} - -RsSerialiser* p3GxsCircles::setupSerialiser() -{ - RsSerialiser* rss = new RsSerialiser; - rss->addSerialType(new GxsCirclesConfigSerializer()); - - return rss; -} - -//====================================================================================// -// DEBUG STUFF // -//====================================================================================// - -bool p3GxsCircles::debug_dumpCacheEntry(RsGxsCircleCache& cache) -{ - std::cerr << " Circle: " << cache.mCircleId - << " status: " << static_cast(cache.mStatus) - << " MembershipTS: " << cache.mLastUpdatedMembershipTS - << " UpdateTS: " << cache.mLastUpdateTime - << " All Ids here: " << cache.mAllIdsHere - << " Has own msg: " << cache.mDoIAuthorAMembershipMsg << std::endl; - - return true; -} - -void p3GxsCircles::debug_dumpCache() -{ - std::cerr << "Debug dump of CircleCache:" << std::endl; - - mCircleCache.printStats(); - mCircleCache.applyToAllCachedEntries(*this,&p3GxsCircles::debug_dumpCacheEntry); -} - -std::string p3GxsCircles::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - -void p3GxsCircles::generateDummyData() -{ - // request Id Data... -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::generateDummyData() getting Id List"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - uint32_t token; - rsIdentity->getTokenService()->requestGroupInfo(token, ansType, opts); - - { - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - mDummyIdToken = token; - } - - RsTickEvent::schedule_in(CIRCLE_EVENT_DUMMYLOAD, CIRCLE_DUMMY_GENPERIOD); -} - - -void p3GxsCircles::checkDummyIdData() -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::checkDummyIdData()"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - // check the token. - uint32_t status = rsIdentity->getTokenService()->requestStatus(mDummyIdToken); - if ( (RsTokenService::FAILED == status) || - (RsTokenService::COMPLETE == status) ) - { - std::vector ids; - if (!rsIdentity->getGroupData(mDummyIdToken, ids)) - { - std::cerr << "p3GxsCircles::checkDummyIdData() ERROR getting data"; - std::cerr << std::endl; - /* error */ - return; - } - - std::vector::iterator it; - for(it = ids.begin(); it != ids.end(); ++it) - { - if (it->mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility) - { -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::checkDummyIdData() PgpLinkedId: " << it->mMeta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - mDummyPgpLinkedIds.push_back(RsGxsId(it->mMeta.mGroupId.toStdString())); - - if (it->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) - { -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::checkDummyIdData() OwnId: " << it->mMeta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - mDummyOwnIds.push_back(RsGxsId(it->mMeta.mGroupId.toStdString())); - } - } - else - { -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::checkDummyIdData() Other Id: " << it->mMeta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - } - } - - /* schedule the generate events */ -#define MAX_CIRCLES 10 - for(int i = 0; i < MAX_CIRCLES; i++) - { - RsTickEvent::schedule_in(CIRCLE_EVENT_DUMMYGEN, i * CIRCLE_DUMMY_GENPERIOD); - } - return; - } - - // Otherwise - reschedule to come back here. - RsTickEvent::schedule_in(CIRCLE_EVENT_DUMMYLOAD, CIRCLE_DUMMY_GENPERIOD); - return; -} - - -void p3GxsCircles::generateDummyCircle() -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::generateDummyCircle()"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - int npgps = mDummyPgpLinkedIds.size(); - - if(npgps == 0) - return ; - - RsGxsCircleGroup group; - - std::set idset; - // select a random number of them. -#define MAX_PEERS_PER_CIRCLE_GROUP 20 - int nIds = 1 + (RSRandom::random_u32() % MAX_PEERS_PER_CIRCLE_GROUP); - for(int i = 0; i < nIds; i++) - { - - int selection = (RSRandom::random_u32() % npgps); - std::list::iterator it = mDummyPgpLinkedIds.begin(); - for(int j = 0; (it != mDummyPgpLinkedIds.end()) && (j < selection); j++, ++it) ; - if (it != mDummyPgpLinkedIds.end()) - { - idset.insert(*it); - } - } - - /* be sure to add one of our IDs too (otherwise we wouldn't get the group) - */ - { - - int selection = (RSRandom::random_u32() % mDummyOwnIds.size()); - std::list::iterator it = mDummyOwnIds.begin(); - mDummyOwnIds.push_back(*it); - for(int j = 0; (it != mDummyOwnIds.end()) && (j < selection); j++, ++it) ; - if (it != mDummyOwnIds.end()) - { - idset.insert(*it); - } - } - - group.mMeta.mGroupName = genRandomId(); -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::generateDummyCircle() Name: " << group.mMeta.mGroupName; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - std::set::iterator it; - for(it = idset.begin(); it != idset.end(); ++it) - { - group.mInvitedMembers.insert(*it); -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::generateDummyCircle() Adding: " << *it; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - } - - uint32_t dummyToken; - createGroup(dummyToken, group); -} - - -/****************************************************************************/ -// ID STUFF. \/ \/ \/ \/ \/ \/ \/ :) -/****************************************************************************/ -#if 0 - -/************************************************************************************/ -/************************************************************************************/ - -bool p3GxsCircles::cachetest_getlist() -{ - std::cerr << "p3GxsCircles::cachetest_getlist() making request"; - std::cerr << std::endl; - - uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, CIRCLEREQ_CACHETEST); - - // Schedule Next Event. - RsTickEvent::schedule_in(CIRCLE_EVENT_CACHETEST, CACHETEST_PERIOD); - return true; -} - -bool p3GxsCircles::cachetest_handlerequest(uint32_t token) -{ - std::cerr << "p3GxsCircles::cachetest_handlerequest() token: " << token; - std::cerr << std::endl; - - std::list grpIds; - bool ok = RsGenExchange::getGroupList(token, grpIds); - - if(ok) - { - std::list::iterator vit = grpIds.begin(); - for(; vit != grpIds.end(); ++vit) - { - /* 5% chance of checking it! */ - if (RSRandom::random_f32() < 0.25) - { - std::cerr << "p3GxsCircles::cachetest_request() Testing Id: " << *vit; - std::cerr << std::endl; - - /* try the cache! */ - if (!haveKey(*vit)) - { - std::list nullpeers; - requestKey(*vit, nullpeers); - - std::cerr << "p3GxsCircles::cachetest_request() Requested Key Id: " << *vit; - std::cerr << std::endl; - } - else - { - RsTlvSecurityKey seckey; - if (getKey(*vit, seckey)) - { - std::cerr << "p3GxsCircles::cachetest_request() Got Key OK Id: " << *vit; - std::cerr << std::endl; - - // success! - seckey.print(std::cerr, 10); - std::cerr << std::endl; - - - } - else - { - std::cerr << "p3GxsCircles::cachetest_request() ERROR no Key for Id: " << *vit; - std::cerr << std::endl; - } - } - - /* try private key too! */ - if (!havePrivateKey(*vit)) - { - requestPrivateKey(*vit); - std::cerr << "p3GxsCircles::cachetest_request() Requested PrivateKey Id: " << *vit; - std::cerr << std::endl; - } - else - { - RsTlvSecurityKey seckey; - if (getPrivateKey(*vit, seckey)) - { - // success! - std::cerr << "p3GxsCircles::cachetest_request() Got PrivateKey OK Id: " << *vit; - std::cerr << std::endl; - } - else - { - std::cerr << "p3GxsCircles::cachetest_request() ERROR no PrivateKey for Id: " << *vit; - std::cerr << std::endl; - } - } - } - } - } - else - { - std::cerr << "p3GxsCircles::cache_load_for_token() ERROR no data"; - std::cerr << std::endl; - - return false; - } - return true; -} - -/****************************************************************************/ -// ID STUFF. /\ /\ /\ /\ /\ /\ /\ /\ :) -/****************************************************************************/ -#endif - -#ifdef HANDLE_SUBCIRCLES -#if 0 -/**** TODO BELOW ****/ - -bool p3GxsCircles::cache_load_subcircles(uint32_t token) -{ - std::cerr << "p3GxsCircles::cache_load_subcircles() : " << token; - std::cerr << std::endl; - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsIdGroupItem* item = dynamic_cast(*vit); - - RsGxsCircleId id = item->meta.mGroupId; - RsGxsCircleGroup group = item->group; - group.mMeta = item->meta; - delete item; - - std::cerr << "p3GxsCircles::cache_load_subcircles() Loaded Id with Meta: "; - std::cerr << item->meta; - std::cerr << std::endl; - - - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - /* stage 2 of loading, load subcircles */ - std::map >::iterator sit; - sit = mCacheLoad_SubCircle.find(id) - if (sit == mCacheLoad_SubCircle.end()) - { - /* ERROR */ - continue; - } - - std::list updateCaches = sit->second; - // cleanup while we're here. - mCacheLoad_SubCircle.erase(sit); - - /* Now iterate through peers / subcircles, and apply - * - similarly to base load function - */ - - - RsGxsCircleCache &cache = it->second; - cache.loadBaseCircle(group); - - bool isComplete = true; - - std::list &peers = group.peers; - std::list::const_iterator pit; - - // need to trigger the searches. - for(pit = peers.begin(); pit != peers.end(); ++pit) - { - /* check cache */ - if (mIdentities->is_cached(*pit)) - { - /* we can process now! */ - RsIdentityDetails details; - if (mIdentities->getDetails(*pit, details)) - { - if (details.isPgpKnown) - { - // Problem - could have multiple GxsIds here! - // TODO. - //cache.mAllowedPeers[details.mPgpId] = *pit; - - for(uit = updateCaches.begin(); uit != updateCaches.end(); ++uit) - { - /* fetch the cache - and update */ - mLoadingCache[id] = RsGxsCircleCache(); - std::map::iterator it; - it = mLoadingCache.find(id); - } - - } - else - { - //cache.mUnknownPeers.push_back(*pit); - } - } - else - { - // ERROR. - } - } - else - { - /* store in to_process queue. */ - cache.mUnprocessedPeers.push_back(*pit); - - if (isComplete) - { - /* store reference to update */ - isComplete = false; - mCacheLoad_KeyWait.push_back(id); - } - } - } - - std::list &circles = group.circles; - std::list::const_iterator cit; - for(cit = circles.begin(); cit != circles.end(); ++cit) - { - /* if its cached already -> then its complete. */ - if (mCircleCache.is_loaded(*cit)) - { - RsGxsCircleCache cachedCircle; - if (mCircleCache.fetch(&cit, cachedCircle)) - { - /* copy cached circle into circle */ - cache.loadSubCircle(cachedCircle); - } - else - { - /* error */ - continue; - } - } - else - { - /* push into secondary processing queues */ - std::list &proc_circles = mCacheLoad_SubCircle[id]; - proc_circles.push_back(id); - - subCirclesToLoad.push_back(id); - - isComplete = false; - } - } - - if (isComplete) - { - /* move straight into the cache */ - mCircleCache.store(id, cache); - - /* remove from loading queue */ - mLoadingCache.erase(it); - } - } - } - else - { - std::cerr << "p3GxsCircles::cache_load_for_token() ERROR no data"; - std::cerr << std::endl; - - return false; - } - - if (!keysToLoad.empty()) - { - /* schedule event to try reload gxsIds */ - - } - - if (!subCirclesToLoad.empty()) - { - /* request load of subcircles */ - - - } - return true; -} - -#endif -#endif - -#ifdef HANDLE_SUBCIRCLES -#if 0 - std::list &circles = group.mSubCircles; - std::list::const_iterator cit; - for(cit = circles.begin(); cit != circles.end(); ++cit) - { - /* if its cached already -> then its complete. */ - if (mCircleCache.is_loaded(*cit)) - { - RsGxsCircleCache cachedCircle; - if (mCircleCache.fetch(&cit, cachedCircle)) - { - /* copy cached circle into circle */ - cache.loadSubCircle(cachedCircle); - } - else - { - /* error */ - continue; - } - } - else - { - /* push into secondary processing queues */ - std::list &proc_circles = mCacheLoad_SubCircle[*cit]; - proc_circles.push_back(id); - - subCirclesToLoad.push_back(*cit); - - isComplete = false; - isUnprocessedCircles = true; - } - } -#endif -#endif diff --git a/libretroshare/src/services/p3gxscircles.h b/libretroshare/src/services/p3gxscircles.h deleted file mode 100644 index e71e26ed0..000000000 --- a/libretroshare/src/services/p3gxscircles.h +++ /dev/null @@ -1,400 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxscircles.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - - -#include "retroshare/rsgxscircles.h" // External Interfaces. -#include "gxs/rsgenexchange.h" // GXS service. -#include "gxs/rsgixs.h" // Internal Interfaces. -#include "services/p3idservice.h" // For constructing Caches -#include "gxs/gxstokenqueue.h" -#include "util/rstickevent.h" -#include "util/rsmemcache.h" -#include "util/rsdebug.h" - -#include -#include - -// TODO: -// can now edit circles. this leads to the following situation: -// if someone gets removed from a self.retricted circle, he won't notice -// because he can't receive the updated circle group if he is not part of the group anymore -// -// idea 1: refresh circle groups for example every week -// if a circle was not refreshed since two weeks we can assume we where deleted -// pro: does not leak info, simple to implement, does work even if the network topology changed (unfriending) -// con: delay until we know about the deletion -// -// idea 2: add a field with deleted members to the circle group -// then circle members can tell deleted circle members that they where deleted -// pro: faster notification about deletion -// con: more complicated, leaks info because the deleted member learns who is still a member -// question: how to authenticate the deletion message? -// -// idea 3: make a two phase deletion process -// first add members to a to-delete list -// then wait a week to let the changes propagate -// then remove from allowed peers list -// pro: easy to implement -// con: deletion process is slow -// improvement idea: let only circle groups sync when the member is on he to-delete list -// but don't allow sync of data from other services -// this requires that the netservice knows that he is dealing with a circle group -// -// fact: have to use a timeout mechanism. -// a timeout is the only thing which works even with a two months old backup - -/* - * Circles Identity Service - * - * A collection of notes: - * - * We want to be able to express the following types of Circles. - * - * - Public - * - Groups & Messages can be passed onto anyone. ( No Restrictions. ) - * - GXS Notes: - * - This is what we have currently. - * - * - External Circle - * - List of Identities that can receive the Group / Messages. - * - This list will be defined via a set of RsIdentities - which have PGPHashes set. - * - We need the PGPHashes to be able to identify which peers can receive msgs. - * - Messages are passed to the Intersection of (Identified PGPHashes & Friends) - * - Distribution of Circle Definitions can be also be restricted via circles. - * - You can have Public External Groups, or Groups that only the Members know about. - * - Control of these External Groups is determined by Admin / Publish Keys. - * - The Danger with External Groups, is your ID wll be associated with other people... - * - Leaking information!!! - * - GXS Notes: - * - p3Circles will provide a distrib list for a given Circle Group. - * - * - Personal Circle or "Your Eyes Only". - * - Same as an Internal Circle Definition. (What will be used for File Sharing initially) - * - Each peer will have a bunch of these, Friends, Family, etc. - * - * - The list is not publically shared, only the originator of the message will distribute. - * - You can communicate back to the originator, who will share with the other members. - * but you mustn't discuss / share content with anyone else. - * - This is quite a Weak / Fragile Group, as there is only one distributor. - * - GXS NOTES: - * - TO make this work, we need GXS or RsCircles to maintain extra info: - * - GXS stores the original source, so communications can go back there. - * - If Originator, GXS store a REFERENCE, Circles turn this into a distrib list of peers. - * - * - * - * Like RsIdentities are used to validation messages, - * RsCircles will be used to determine if a peer can receive a group / messages. - * - * bool RsCircles::canSend(RsGxsCircleId, RsPeerId) - * bool RsCircles::canSend(RsCircleInternalId, RsPeerId) - * - * or maybe just: - * - * bool RsCircles::recipients(GxsPermission &perms, std::list friendlist); - * - */ - -/* Permissions is part of GroupMetaData - */ - -class RsGxsCircleMembershipStatus -{ -public: - RsGxsCircleMembershipStatus() : last_subscription_TS(0), subscription_flags(0) {} - - rstime_t last_subscription_TS ; - uint32_t subscription_flags ; // combination of GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST and GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED -}; - -enum class CircleEntryCacheStatus: uint8_t { - UNKNOWN = 0x00, // Used to detect uninitialized memory - NO_DATA_YET = 0x01, // Used in the constuctor - LOADING = 0x02, // When the token request to load cache has been sent and no data is present - UPDATING = 0x03, // Starting from this level the cache entry can be used - CHECKING_MEMBERSHIP = 0x04, // Means we're actually looking into msgs to update membership status - UP_TO_DATE = 0x05 // Everything should be loaded here. -}; - -class RsGxsCircleCache -{ -public: - RsGxsCircleCache(); - - bool loadBaseCircle(const RsGxsCircleGroup &circle); - bool loadSubCircle(const RsGxsCircleCache &subcircle); - - bool getAllowedPeersList(std::list &friendlist) const; - bool isAllowedPeer(const RsPgpId &id) const; - bool isAllowedPeer(const RsGxsId &id, const RsGxsGroupId &destination_group) const; - bool addAllowedPeer(const RsPgpId &pgpid); - bool addLocalFriend(const RsPgpId &pgpid); - - // Cache related data - - rstime_t mLastUpdatedMembershipTS ; // Last time the subscribe messages have been requested. Should be reset when new messages arrive. - rstime_t mLastUpdateTime; // Last time the cache entry was loaded - CircleEntryCacheStatus mStatus; // Overall state of the cache entry - bool mAllIdsHere ; // True when all ids are knwon and available. - - // GxsCircle related data - - RsGxsCircleId mCircleId; - std::string mCircleName; - - RsGxsCircleType mCircleType; - bool mIsExternal; - RsGxsCircleId mRestrictedCircleId ; // circle ID that circle is restricted to. - - bool mDoIAuthorAMembershipMsg; // Do I have a subscribe/unsubscribe message in the circle group? Will be used to determine if we subscribe to the group or not - uint32_t mGroupStatus; // Copy of the group status from the GXS group. - uint32_t mGroupSubscribeFlags; // Subscribe flags of the group. - -#ifdef SUBSCIRCLES - std::set mUnprocessedCircles; - std::set mProcessedCircles; -#endif - std::map mMembershipStatus; // Membership status of each ID cited in the group (including the ones posting a message) - - std::set mAllowedGxsIds; // IDs that are allowed in the circle and have requested membership. This is the official members list. - std::set mAllowedNodes; // List of friend nodes allowed in the circle (local circles only) - - RsPeerId mOriginator ; // peer who sent the data, in case we need to ask for ids -}; - - -class PgpAuxUtils; - -class RsCirclesMemCache : public std::map -{ -public: - RsCirclesMemCache() : std::map(){} - - bool is_cached(const RsGxsCircleId& id) { return end() != find(id) ; } - RsGxsCircleCache& ref(const RsGxsCircleId& id) { return operator[](id) ; } - - void printStats() { std::cerr << "CircleMemCache: " << size() << " elements." << std::endl; } - - template void applyToAllCachedEntries(ClientClass& c,bool (ClientClass::*method)(RsGxsCircleCache&)) - { - for(auto& it:*this) - (c.*method)(it.second); - } - template void applyToAllCachedEntries(ClientClass& c,bool (ClientClass::*method)(const RsGxsCircleCache&)) - { - for(const auto& it:*this) - (c.*method)(it.second); - } -}; - -class p3GxsCircles: public RsGxsCircleExchange, public RsGxsCircles, public GxsTokenQueue, public RsTickEvent, public p3Config -{ -public: - p3GxsCircles( - RsGeneralDataService* gds, RsNetworkExchangeService* nes, - p3IdService* identities, PgpAuxUtils* pgpUtils ); - - RsServiceInfo getServiceInfo() override; - - /// @see RsGxsCircles - bool createCircle( - const std::string& circleName, RsGxsCircleType circleType, - RsGxsCircleId& circleId = RS_DEFAULT_STORAGE_PARAM(RsGxsCircleId), - const RsGxsCircleId& restrictedId = RsGxsCircleId(), - const RsGxsId& authorId = RsGxsId(), - const std::set& gxsIdMembers = std::set(), - const std::set& localMembers = std::set() - ) override; - - bool editCircle( const RsGxsCircleId& circleId,const std::string& circleName, RsGxsCircleType circleType, - const RsGxsCircleId& restrictedId, - const RsGxsId& authorId, const std::set& gxsIdMembers, - const std::set& localMembers ) ; - - /// @see RsGxsCircles - bool editCircle(RsGxsCircleGroup& cData) override; - - /// @see RsGxsCircles - bool getCirclesSummaries(std::list& circles) override; - - /// @see RsGxsCircles - bool getCirclesInfo( - const std::list& circlesIds, - std::vector& circlesInfo ) override; - - /// @see RsGxsCircles - bool getCircleRequests( const RsGxsGroupId& circleId, - std::vector& requests ) override; - - /// @see RsGxsCircles - bool inviteIdsToCircle( const std::set& identities, - const RsGxsCircleId& circleId ) override; - - /// @see RsGxsCircles - bool revokeIdsFromCircle( const std::set& identities, - const RsGxsCircleId& circleId ) override; - - /// @see RsGxsCircles - bool getCircleRequest(const RsGxsGroupId& circleId, - const RsGxsMessageId& msgId, - RsGxsCircleMsg& msg) override; - - /// @see RsGxsCircles - bool exportCircleLink( - std::string& link, const RsGxsCircleId& circleId, - bool includeGxsData = true, - const std::string& baseUrl = DEFAULT_CIRCLE_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsGxsCircles - bool importCircleLink( - const std::string& link, - RsGxsCircleId& circleId = RS_DEFAULT_STORAGE_PARAM(RsGxsCircleId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - virtual bool getCircleDetails(const RsGxsCircleId &id, RsGxsCircleDetails &details) override; - virtual bool getCircleExternalIdList(std::set &circleIds) override; - - virtual bool isLoaded(const RsGxsCircleId &circleId) override; - virtual bool loadCircle(const RsGxsCircleId &circleId) override; - - virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id, bool &should_encrypt) override; - virtual int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id) override; - - virtual bool recipients(const RsGxsCircleId &circleId, std::list &friendlist) override; - virtual bool recipients(const RsGxsCircleId &circleId, const RsGxsGroupId& dest_group, std::list &gxs_ids) override; - virtual bool isRecipient(const RsGxsCircleId &circleId, const RsGxsGroupId& destination_group, const RsGxsId& id) override; - - - virtual bool getGroupData(const uint32_t &token, std::vector &groups) override; - virtual bool getMsgData(const uint32_t &token, std::vector &msgs) override; - virtual void createGroup(uint32_t& token, RsGxsCircleGroup &group) override; - virtual void updateGroup(uint32_t &token, RsGxsCircleGroup &group) override; - - virtual bool service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) override; - virtual rstime_t service_getLastGroupSeenTs(const RsGxsGroupId&) override; - - /* membership management for external circles */ - - virtual bool requestCircleMembership(const RsGxsId &own_gxsid, const RsGxsCircleId& circle_id) override; - virtual bool cancelCircleMembership(const RsGxsId &own_gxsid, const RsGxsCircleId& circle_id) override; - - /**********************************************/ - - // needed for background processing. - virtual void service_tick() override; - -protected: - bool checkCircleParamConsistency( const std::string& circleName, RsGxsCircleType circleType, - const RsGxsCircleId& restrictedId, - const RsGxsId& authorId, const std::set& gxsIdMembers, - const std::set& localMembers ) const ; - - // overloads p3Config - virtual bool saveList(bool &cleanup, std::list&saveList) override; - virtual bool loadList(std::list& loadList) override; - virtual RsSerialiser *setupSerialiser() override; - - bool pushCircleMembershipRequest(const RsGxsId& own_gxsid, const RsGxsCircleId& circle_id, RsGxsCircleSubscriptionType request_type) ; - static uint32_t circleAuthenPolicy(); - - /** Notifications **/ - virtual void notifyChanges(std::vector& changes) override; - - /** Overloaded to add PgpIdHash to Group Definition **/ - virtual ServiceCreate_Return service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet) override; - - // Overloaded from GxsTokenQueue for Request callbacks. - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) override; - - // Overloaded from RsTickEvent. - virtual void handle_event(uint32_t event_type, const std::string &elabel) override; - - private: - - // Load data. - bool processMembershipRequests(uint32_t token); - - // Need some crazy arsed cache to store the circle info. - // so we don't have to keep loading groups. - - int cache_tick(); - - bool cache_request_load(const RsGxsCircleId &id); - bool cache_start_load(); - bool force_cache_reload(const RsGxsCircleId& id); - bool cache_load_for_token(uint32_t token); - bool cache_reloadids(const RsGxsCircleId &circleId); - - bool checkCircleCache(); - - bool locked_checkCircleCacheForAutoSubscribe(RsGxsCircleCache &cache); - bool locked_processMembershipMessages(RsGxsCircleCache& cache,const std::vector& items, GxsMsgReq& messages_to_delete,const std::set& own_ids); - bool locked_processLoadingCacheEntry(RsGxsCircleCache &cache); - bool locked_checkCircleCacheForMembershipUpdate(RsGxsCircleCache &cache); - bool locked_setGroupUnprocessedStatus(RsGxsCircleCache& cache,bool unprocessed); - bool locked_subscribeToCircle(const RsGxsCircleId &grpId, bool subscribe); - - p3IdService *mIdentities; // Needed for constructing Circle Info, - PgpAuxUtils *mPgpUtils; - - RsMutex mCircleMtx; /* Locked Below Here */ - RsMutex mKnownCirclesMtx; /* Locked Below Here */ - - std::map mKnownCircles; - - /***** Caching Circle Info, *****/ - - // waiting for subcircle to load. (first is part of each of the second list) - // TODO. - //std::map > mCacheLoad_SubCircle; - - std::set mCirclesToLoad; // list of circles to update/load, so that we can treat them by groups. - RsCirclesMemCache mCircleCache; - //RsMemCache mCircleCache; // actual cache data - - void debug_dumpCache(); // debug method to overview what's going on - bool debug_dumpCacheEntry(RsGxsCircleCache &cache); -private: - - std::string genRandomId(); - - void generateDummyData(); - void checkDummyIdData(); - void generateDummyCircle(); - - rstime_t mLastCacheMembershipUpdateTS ; - - uint32_t mDummyIdToken; - std::list mDummyPgpLinkedIds; - std::list mDummyOwnIds; - bool mShouldSendCacheUpdateNotification ; - rstime_t mLastCacheUpdateEvent; - rstime_t mLastDebugPrintTS; - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; diff --git a/libretroshare/src/services/p3gxscommon.cc b/libretroshare/src/services/p3gxscommon.cc deleted file mode 100644 index 7c37bd6aa..000000000 --- a/libretroshare/src/services/p3gxscommon.cc +++ /dev/null @@ -1,772 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxscommon.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "retroshare/rsgxscommon.h" -#include "services/p3gxscommon.h" -#include "rsitems/rsgxscommentitems.h" -#include "util/rsstring.h" - -#include -#include -#include - -//#define DEBUG_GXSCOMMON - -RsGxsComment::RsGxsComment() -{ - mUpVotes = 0; - mDownVotes = 0; - mScore = 0; - mOwnVote = 0; -} - -/********************************************************************************/ - -RsGxsImage::RsGxsImage() -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "RsGxsImage(" << this << ")"; - std::cerr << std::endl; -#endif - mData = NULL; - mSize = 0; -} - -RsGxsImage::RsGxsImage(const RsGxsImage& a) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "RsGxsImage(" << this << ") = RsGxsImage(" << (void *) &a << ")"; - std::cerr << std::endl; -#endif - mData = NULL; - mSize = 0; - copy(a.mData, a.mSize); -} - - -RsGxsImage::~RsGxsImage() -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "~RsGxsImage(" << this << ")"; - std::cerr << std::endl; -#endif - clear(); -} - - -RsGxsImage &RsGxsImage::operator=(const RsGxsImage &a) -{ - copy(a.mData, a.mSize); - return *this; -} - - -bool RsGxsImage::empty() const -{ - return ((mData == NULL) || (mSize == 0)); -} - -void RsGxsImage::take(uint8_t *data, uint32_t size) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "RsGxsImage(" << this << ")::take(" << (void *) data << "," << size << ")"; - std::cerr << std::endl; -#endif - // Copies Pointer. - clear(); - mData = data; - mSize = size; -} - -// NB Must make sure that we always use malloc/free for this data. -uint8_t *RsGxsImage::allocate(uint32_t size) -{ - uint8_t *val = (uint8_t *) rs_malloc(size); - -#ifdef DEBUG_GXSCOMMON - std::cerr << "RsGxsImage()::allocate(" << (void *) val << ")"; - std::cerr << std::endl; -#endif - return val; -} - -void RsGxsImage::release(void *data) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "RsGxsImage()::release(" << (void *) data << ")"; - std::cerr << std::endl; -#endif - free(data); -} - -void RsGxsImage::copy(uint8_t *data, uint32_t size) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "RsGxsImage(" << this << ")::copy(" << (void *) data << "," << size << ")"; - std::cerr << std::endl; -#endif - // Allocates and Copies. - clear(); - if (data && size) - { - mData = allocate(size); - memcpy(mData, data, size); - mSize = size; - } -} - -void RsGxsImage::clear() -{ - // Frees. - if (mData) - { - release(mData); - } - mData = NULL; - mSize = 0; -} - -void RsGxsImage::shallowClear() -{ - // Clears Pointer. - mData = NULL; - mSize = 0; -} - -/********************************************************************************/ - - -RsGxsFile::RsGxsFile() -{ - mSize = 0; -} - -RsGxsVote::RsGxsVote() -{ - mVoteType = 0; -} - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -#define GXSCOMMENTS_VOTE_CHECK 0x0002 -#define GXSCOMMENTS_VOTE_DONE 0x0003 - -p3GxsCommentService::p3GxsCommentService(RsGenExchange *exchange, uint16_t service_type) - : GxsTokenQueue(exchange), mExchange(exchange), mServiceType(service_type) -{ - return; -} - -void p3GxsCommentService::comment_tick() -{ - GxsTokenQueue::checkRequests(); -} - -bool p3GxsCommentService::getGxsCommentData(const uint32_t &token, std::vector &comments) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::getGxsCommentData()"; - std::cerr << std::endl; -#endif - - GxsMsgDataMap msgData; - bool ok = mExchange->getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - std::multimap voteMap; - - for(; mit != msgData.end(); ++mit) - { - //RsGxsGroupId grpId = mit->first; - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - /* now split into Comments and Votes */ - - for(; vit != msgItems.end(); ++vit) - { - RsGxsCommentItem* item = dynamic_cast(*vit); - - if(item) - { - RsGxsComment comment = item->mMsg; - comment.mMeta = item->meta; - comments.push_back(comment); - delete item; - } - else - { - RsGxsVoteItem* vote = dynamic_cast(*vit); - if (vote) - { - voteMap.insert(std::make_pair(vote->meta.mParentId, vote)); - } - else - { - std::cerr << "Not a Comment or Vote, deleting!" << std::endl; - delete *vit; - } - } - } - } - - /* now iterate through comments - and set the vote counts */ - std::vector::iterator cit; - std::multimap::iterator it; - for(cit = comments.begin(); cit != comments.end(); ++cit) - { - for (it = voteMap.lower_bound(cit->mMeta.mMsgId); it != voteMap.upper_bound(cit->mMeta.mMsgId); ++it) - { - if (it->second->mMsg.mVoteType == GXS_VOTE_UP) - { - cit->mUpVotes++; - } - else - { - cit->mDownVotes++; - } - } - cit->mScore = calculateBestScore(cit->mUpVotes, cit->mDownVotes); - - /* convert Status -> mHaveVoted */ - if (cit->mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) - { - if (cit->mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_UP) - { - cit->mOwnVote = GXS_VOTE_UP; - } - else - { - cit->mOwnVote = GXS_VOTE_DOWN; - } - } - else - { - cit->mOwnVote = GXS_VOTE_NONE; - } - } - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::getGxsCommentData() Found " << comments.size() << " Comments"; - std::cerr << std::endl; - std::cerr << "p3GxsCommentService::getGxsCommentData() Found " << voteMap.size() << " Votes"; - std::cerr << std::endl; -#endif - - /* delete the votes */ - for (it = voteMap.begin(); it != voteMap.end(); ++it) - { - delete it->second; - } - - - - } - - return ok; -} - - - - -bool p3GxsCommentService::getGxsRelatedComments(const uint32_t &token, std::vector &comments) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::getGxsRelatedComments()"; - std::cerr << std::endl; -#endif - - GxsMsgRelatedDataMap msgData; - bool ok = mExchange->getMsgRelatedData(token, msgData); - - if(ok) - { - GxsMsgRelatedDataMap::iterator mit = msgData.begin(); - std::multimap voteMap; - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsCommentItem* item = dynamic_cast(*vit); - - if(item) - { - RsGxsComment comment = item->mMsg; - comment.mMeta = item->meta; - comments.push_back(comment); - delete item; - } - else - { - RsGxsVoteItem* vote = dynamic_cast(*vit); - if (vote) - { - voteMap.insert(std::make_pair(vote->meta.mParentId, vote)); - } - else - { - std::cerr << "Not a Comment or Vote, deleting!" << std::endl; - delete *vit; - } - } - } - } - - /* now iterate through comments - and set the vote counts */ - std::vector::iterator cit; - std::multimap::iterator it; - for(cit = comments.begin(); cit != comments.end(); ++cit) - { - for (it = voteMap.lower_bound(cit->mMeta.mMsgId); it != voteMap.upper_bound(cit->mMeta.mMsgId); ++it) - { - if (it->second->mMsg.mVoteType == GXS_VOTE_UP) - { - cit->mUpVotes++; - } - else - { - cit->mDownVotes++; - } - } - cit->mScore = calculateBestScore(cit->mUpVotes, cit->mDownVotes); - - /* convert Status -> mHaveVoted */ - if (cit->mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) - { - if (cit->mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_UP) - { - cit->mOwnVote = GXS_VOTE_UP; - } - else - { - cit->mOwnVote = GXS_VOTE_DOWN; - } - } - else - { - cit->mOwnVote = GXS_VOTE_NONE; - } - } - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::getGxsRelatedComments() Found " << comments.size() << " Comments"; - std::cerr << std::endl; - std::cerr << "p3GxsCommentService::getGxsRelatedComments() Found " << voteMap.size() << " Votes"; - std::cerr << std::endl; -#endif - - /* delete the votes */ - for (it = voteMap.begin(); it != voteMap.end(); ++it) - { - delete it->second; - } - } - - return ok; -} - - - -double p3GxsCommentService::calculateBestScore(int upVotes, int downVotes) -{ - - float score; - int n = upVotes + downVotes; - - if(n==0) - score = 0.0; - else - { - // See https://github.com/reddit/reddit/blob/master/r2/r2/lib/db/_sorts.pyx#L45 for the source of this nice formula. - // http://www.evanmiller.org/how-not-to-sort-by-average-rating.html for the mathematical explanation. - - float p = upVotes/n; - float z = 1.281551565545 ; - - float left = p + 1/(2*n)*z*z ; - float right = z*sqrt(p*(1-p)/n + z*z/(4*n*n)) ; - float under = 1+1/n*z*z ; - - score = (left - right)/under ; - - //static float z = 1.0; - //score = sqrt(phat+z*z/(2*n)-z*((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n); - } - return score; -} - - - -/********************************************************************************************/ - -bool p3GxsCommentService::createGxsComment(uint32_t &token, const RsGxsComment &msg) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::createGxsComment() GroupId: " << msg.mMeta.mGroupId; - std::cerr << std::endl; -#endif - - RsGxsCommentItem* msgItem = new RsGxsCommentItem(mServiceType); - msgItem->mMsg = msg; - msgItem->meta = msg.mMeta; - - mExchange->publishMsg(token, msgItem); - return true; -} - - - -bool p3GxsCommentService::createGxsVote(uint32_t &token, RsGxsVote &vote) -{ - // NOTE Because we cannot do this operation immediately, we create a token, - // and monitor acknowledgeTokenMsg ... to return correct answer. - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::createGxsVote() GroupId: " << vote.mMeta.mGroupId; - std::cerr << std::endl; -#endif - - /* vote must be associated with another item */ - if (vote.mMeta.mThreadId.isNull()) - { - std::cerr << "p3GxsCommentService::createGxsVote() ERROR Missing Required ThreadId"; - std::cerr << std::endl; - return false; - } - - if (vote.mMeta.mParentId.isNull()) - { - std::cerr << "p3GxsCommentService::createGxsVote() ERROR Missing Required ParentId"; - std::cerr << std::endl; - return false; - } - - if (vote.mMeta.mGroupId.isNull()) - { - std::cerr << "p3GxsCommentService::createGxsVote() ERROR Missing Required GroupId"; - std::cerr << std::endl; - return false; - } - - if (vote.mMeta.mAuthorId.isNull()) - { - std::cerr << "p3GxsCommentService::createGxsVote() ERROR Missing Required AuthorId"; - std::cerr << std::endl; - return false; - } - - - /* now queue */ - - RsGxsGrpMsgIdPair parentId(vote.mMeta.mGroupId, vote.mMeta.mParentId); - - std::map::iterator it; - it = mPendingVotes.find(parentId); - if (it != mPendingVotes.end()) - { - std::cerr << "p3GxsCommentService::createGxsVote() ERROR Already a pending vote!"; - std::cerr << std::endl; - return false; - } - - token = mExchange->generatePublicToken(); - mPendingVotes[parentId] = VoteHolder(vote, token); - - // request parent, and queue for response. - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - - GxsMsgReq msgIds; - std::set &vect_msgIds = msgIds[parentId.first]; - vect_msgIds.insert(parentId.second); - - uint32_t int_token; - mExchange->getTokenService()->requestMsgInfo(int_token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, msgIds); - GxsTokenQueue::queueRequest(int_token, GXSCOMMENTS_VOTE_CHECK); - - return true; -} - - - - - - - -void p3GxsCommentService::load_PendingVoteParent(const uint32_t &token) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::load_PendingVoteParent()"; - std::cerr << std::endl; -#endif - GxsMsgMetaMap msginfo; - if (!mExchange->getMsgMeta(token, msginfo)) - { - std::cerr << "p3GxsCommentService::load_PendingVoteParent() ERROR Fetching Data"; - std::cerr << std::endl; - std::cerr << "p3GxsCommentService::load_PendingVoteParent() Warning - this means LOST QUEUE ENTRY"; - std::cerr << std::endl; - std::cerr << "p3GxsCommentService::load_PendingVoteParent() Need to track tokens - if this happens"; - std::cerr << std::endl; - return; - } - - GxsMsgMetaMap::iterator it; - for(it = msginfo.begin(); it != msginfo.end(); ++it) - { - std::vector::iterator mit; - for(mit = it->second.begin(); mit != it->second.end(); ++mit) - { - /* find the matching Pending Vote */ - RsMsgMetaData &meta = *mit; - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::load_PendingVoteParent() recv (groupId: " << meta.mGroupId; - std::cerr << ", msgId: " << meta.mMsgId << ")"; - std::cerr << std::endl; -#endif - - RsGxsGrpMsgIdPair parentId(meta.mGroupId, meta.mMsgId); - std::map::iterator pit; - pit = mPendingVotes.find(parentId); - if (pit == mPendingVotes.end()) - { - std::cerr << __PRETTY_FUNCTION__ - << " ERROR Finding Pending Vote" << std::endl; - continue; - } - - RsGxsVote vote = pit->second.mVote; - if (meta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR Already Voted" - << std::endl - << "mGroupId: " << meta.mGroupId << std::endl - << "mMsgId: " << meta.mMsgId << std::endl; - - pit->second.mStatus = VoteHolder::VOTE_ERROR; - mExchange->updatePublicRequestStatus( - pit->second.mReqToken, RsTokenService::FAILED ); - continue; - } - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::load_PendingVoteParent() submitting Vote"; - std::cerr << std::endl; -#endif - - uint32_t status_token; - if (vote.mVoteType == GXS_VOTE_UP) - { - mExchange->setMsgStatusFlags(status_token, parentId, - GXS_SERV::GXS_MSG_STATUS_VOTE_UP, GXS_SERV::GXS_MSG_STATUS_VOTE_MASK); - } - else - { - mExchange->setMsgStatusFlags(status_token, parentId, - GXS_SERV::GXS_MSG_STATUS_VOTE_DOWN, GXS_SERV::GXS_MSG_STATUS_VOTE_MASK); - } - - uint32_t vote_token; - castVote(vote_token, vote); - GxsTokenQueue::queueRequest(vote_token, GXSCOMMENTS_VOTE_DONE); - - pit->second.mVoteToken = vote_token; - pit->second.mStatus = VoteHolder::VOTE_SUBMITTED; - } - } -} - - - -void p3GxsCommentService::completeInternalVote(uint32_t &token) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::completeInternalVote() token: " << token; - std::cerr << std::endl; -#endif - std::map::iterator it; - for (it = mPendingVotes.begin(); it != mPendingVotes.end(); ++it) - { - if (it->second.mVoteToken == token) - { - RsTokenService::GxsRequestStatus status = - mExchange->getTokenService()->requestStatus(token); - mExchange->updatePublicRequestStatus(it->second.mReqToken, status); - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::completeInternalVote() Matched to PendingVote. status: " << status; - std::cerr << std::endl; -#endif - - it->second.mStatus = VoteHolder::VOTE_READY; - return; - } - } - - std::cerr << "p3GxsCommentService::completeInternalVote() ERROR Failed to match PendingVote"; - std::cerr << std::endl; - - return; -} - - -bool p3GxsCommentService::acknowledgeVote(const uint32_t& token, RsGxsGrpMsgIdPair& msgId) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::acknowledgeVote() token: " << token; - std::cerr << std::endl; -#endif - - std::map::iterator it; - for (it = mPendingVotes.begin(); it != mPendingVotes.end(); ++it) - { - if (it->second.mReqToken == token) - { -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::acknowledgeVote() Matched to PendingVote"; - std::cerr << std::endl; -#endif - - bool ans = false; - if (it->second.mStatus == VoteHolder::VOTE_READY) - { -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::acknowledgeVote() PendingVote = READY"; - std::cerr << std::endl; -#endif - - // Finally finish this Vote off. - ans = mExchange->acknowledgeTokenMsg(it->second.mVoteToken, msgId); - } - else if (it->second.mStatus == VoteHolder::VOTE_ERROR) - { - std::cerr << "p3GxsCommentService::acknowledgeVote() PendingVote = ERROR ???"; - std::cerr << std::endl; - } -#ifdef DEBUG_GXSCOMMON - else - { - std::cerr << "p3GxsCommentService::acknowledgeVote() PendingVote = OTHER STATUS"; - std::cerr << std::endl; - } - - std::cerr << "p3GxsCommentService::acknowledgeVote() cleanup token & PendingVote"; - std::cerr << std::endl; -#endif - mExchange->disposeOfPublicToken(it->second.mReqToken); - mPendingVotes.erase(it); - - return ans; - } - } - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::acknowledgeVote() Failed to match PendingVote"; - std::cerr << std::endl; -#endif - - return false; -} - - - // Overloaded from GxsTokenQueue for Request callbacks. -void p3GxsCommentService::handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::handleResponse(" << token << "," << req_type << "," << status << ")" << std::endl; -#endif - if (status != RsTokenService::COMPLETE) - return; //For now, only manage Complete request - - - // stuff. - switch(req_type) - { - case GXSCOMMENTS_VOTE_CHECK: - load_PendingVoteParent(token); - break; - - case GXSCOMMENTS_VOTE_DONE: - completeInternalVote(token); - break; - - default: - /* error */ - std::cerr << "p3GxsCommentService::handleResponse() Unknown Request Type: " << req_type; - std::cerr << std::endl; - break; - } -} - - - - - -bool p3GxsCommentService::castVote(uint32_t &token, RsGxsVote &msg) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::castVote() GroupId: " << msg.mMeta.mGroupId; - std::cerr << std::endl; -#endif - - RsGxsVoteItem* msgItem = new RsGxsVoteItem(mServiceType); - msgItem->mMsg = msg; - msgItem->meta = msg.mMeta; - - mExchange->publishMsg(token, msgItem); - return true; -} - - - - - - - -/********************************************************************************************/ -/********************************************************************************************/ - -#if 0 -void p3GxsCommentService::setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_UNREAD | GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - uint32_t status = GXS_SERV::GXS_MSG_STATUS_UNREAD; - if (read) - { - status = 0; - } - - setMsgStatusFlags(token, msgId, status, mask); - -} - -#endif - diff --git a/libretroshare/src/services/p3gxscommon.h b/libretroshare/src/services/p3gxscommon.h deleted file mode 100644 index fb51a0d30..000000000 --- a/libretroshare/src/services/p3gxscommon.h +++ /dev/null @@ -1,106 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxscommon.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef P3_GXSCOMMON_SERVICE_HEADER -#define P3_GXSCOMMON_SERVICE_HEADER - -#include "retroshare/rsgxscommon.h" -#include "gxs/rsgenexchange.h" -#include "gxs/gxstokenqueue.h" -#include - - -/**** - * This mirrors rsGxsCommentService, with slightly different names, - * provides the implementation for any services requiring Comments. - */ - -# -class VoteHolder -{ - public: - - static const uint32_t VOTE_ERROR = 0; - static const uint32_t VOTE_QUEUED = 1; - static const uint32_t VOTE_SUBMITTED = 2; - static const uint32_t VOTE_READY = 3; - - VoteHolder() :mVoteToken(0), mReqToken(0), mStatus(VOTE_ERROR) { return; } - - VoteHolder(const RsGxsVote &vote, uint32_t reqToken) - :mVote(vote), mVoteToken(0), mReqToken(reqToken), mStatus(VOTE_QUEUED) { return; } - - RsGxsVote mVote; - uint32_t mVoteToken; - uint32_t mReqToken; - uint32_t mStatus; -}; - - -class p3GxsCommentService: public GxsTokenQueue -{ - public: - - p3GxsCommentService(RsGenExchange *exchange, uint16_t service_type); - - void comment_tick(); - - bool getGxsCommentData(const uint32_t &token, std::vector &msgs); - bool getGxsRelatedComments(const uint32_t &token, std::vector &msgs); - - bool createGxsComment(uint32_t &token, const RsGxsComment &msg); - bool createGxsVote(uint32_t &token, RsGxsVote &msg); - - // Special Acknowledge. - bool acknowledgeVote(const uint32_t& token, RsGxsGrpMsgIdPair& msgId); - -static double calculateBestScore(int upVotes, int downVotes); - - -#if 0 - void setGxsMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read); -#endif - - protected: - - // Overloaded from GxsTokenQueue for Request callbacks. - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) override; - - private: - - void load_PendingVoteParent(const uint32_t &token); - void completeInternalVote(uint32_t &token); - - bool castVote(uint32_t &token, RsGxsVote &msg); - - RsGenExchange *mExchange; - uint16_t mServiceType; - - /* pending queue of Votes */ - std::map mPendingVotes; - - -}; - - -#endif - diff --git a/libretroshare/src/services/p3gxsforums.cc b/libretroshare/src/services/p3gxsforums.cc deleted file mode 100644 index a301997e6..000000000 --- a/libretroshare/src/services/p3gxsforums.cc +++ /dev/null @@ -1,1389 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxsforums.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2019-2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include - -#include "services/p3gxsforums.h" -#include "rsitems/rsgxsforumitems.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsidentity.h" -#include "util/rsdebug.h" -#include "rsserver/p3face.h" -#include "retroshare/rsnotify.h" -#include "util/rsdebuglevel2.h" -#include "retroshare/rsgxsflags.h" - - -// For Dummy Msgs. -#include "util/rsrandom.h" -#include "util/rsstring.h" - -/**** - * #define GXSFORUM_DEBUG 1 - ****/ - -RsGxsForums *rsGxsForums = NULL; - -#define FORUM_TESTEVENT_DUMMYDATA 0x0001 -#define DUMMYDATA_PERIOD 60 // long enough for some RsIdentities to be generated. -#define FORUM_UNUSED_BY_FRIENDS_DELAY (2*30*86400) // unused forums are deleted after 2 months - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3GxsForums::p3GxsForums( RsGeneralDataService *gds, - RsNetworkExchangeService *nes, RsGixs* gixs ) : - RsGenExchange( gds, nes, new RsGxsForumSerialiser(), - RS_SERVICE_GXS_TYPE_FORUMS, gixs, forumsAuthenPolicy()), - RsGxsForums(static_cast(*this)), mGenToken(0), - mGenActive(false), mGenCount(0), mKnownForumsMutex("GXS forums known forums timestamp cache") -{ - // Test Data disabled in Repo. - //RsTickEvent::schedule_in(FORUM_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD); -} - - -const std::string GXS_FORUMS_APP_NAME = "gxsforums"; -const uint16_t GXS_FORUMS_APP_MAJOR_VERSION = 1; -const uint16_t GXS_FORUMS_APP_MINOR_VERSION = 0; -const uint16_t GXS_FORUMS_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_FORUMS_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3GxsForums::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_FORUMS, - GXS_FORUMS_APP_NAME, - GXS_FORUMS_APP_MAJOR_VERSION, - GXS_FORUMS_APP_MINOR_VERSION, - GXS_FORUMS_MIN_MAJOR_VERSION, - GXS_FORUMS_MIN_MINOR_VERSION); -} - - -uint32_t p3GxsForums::forumsAuthenPolicy() -{ - uint32_t policy = 0; - uint32_t flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - flag |= GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -static const uint32_t GXS_FORUMS_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months -static const uint8_t GXS_FORUMS_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ; - -struct RsGxsForumNotifyRecordsItem: public RsItem -{ - - RsGxsForumNotifyRecordsItem() - : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_FORUMS_CONFIG,GXS_FORUMS_CONFIG_SUBTYPE_NOTIFY_RECORD) - {} - - virtual ~RsGxsForumNotifyRecordsItem() {} - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { RS_SERIAL_PROCESS(records); } - - void clear() {} - - std::map records; -}; - -class GxsForumsConfigSerializer : public RsServiceSerializer -{ -public: - GxsForumsConfigSerializer() : RsServiceSerializer(RS_SERVICE_GXS_TYPE_FORUMS_CONFIG) {} - virtual ~GxsForumsConfigSerializer() {} - - RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const - { - if(service_id != RS_SERVICE_GXS_TYPE_FORUMS_CONFIG) - return NULL; - - switch(item_sub_id) - { - case GXS_FORUMS_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsForumNotifyRecordsItem(); - default: - return NULL; - } - } -}; - -bool p3GxsForums::saveList(bool &cleanup, std::list&saveList) -{ - cleanup = true ; - - RsGxsForumNotifyRecordsItem *item = new RsGxsForumNotifyRecordsItem ; - - { - RS_STACK_MUTEX(mKnownForumsMutex); - item->records = mKnownForums ; - } - - saveList.push_back(item) ; - return true; -} - -bool p3GxsForums::loadList(std::list& loadList) -{ - while(!loadList.empty()) - { - RsItem *item = loadList.front(); - loadList.pop_front(); - - rstime_t now = time(NULL); - - RsGxsForumNotifyRecordsItem *fnr = dynamic_cast(item) ; - - if(fnr != NULL) - { - RS_STACK_MUTEX(mKnownForumsMutex); - - mKnownForums.clear(); - - for(auto it(fnr->records.begin());it!=fnr->records.end();++it) - if( now < it->second + GXS_FORUMS_CONFIG_MAX_TIME_NOTIFY_STORAGE) - mKnownForums.insert(*it) ; - } - - delete item ; - } - return true; -} - -RsSerialiser* p3GxsForums::setupSerialiser() -{ - RsSerialiser* rss = new RsSerialiser; - rss->addSerialType(new GxsForumsConfigSerializer()); - - return rss; -} - -void p3GxsForums::notifyChanges(std::vector &changes) -{ -#ifdef GXSFORUMS_DEBUG - std::cerr << "p3GxsForums::notifyChanges() : " << changes.size() << "changes to notify" << std::endl; -#endif - - std::vector::iterator it; - for(it = changes.begin(); it != changes.end(); ++it) - { - RsGxsMsgChange *msgChange = dynamic_cast(*it); - - if (msgChange) - { - if (msgChange->getType() == RsGxsNotify::TYPE_RECEIVED_NEW || msgChange->getType() == RsGxsNotify::TYPE_PUBLISHED) /* message received */ - if (rsEvents) - { - auto ev = std::make_shared(); - ev->mForumMsgId = msgChange->mMsgId; - ev->mForumGroupId = msgChange->mGroupId; - ev->mForumEventCode = RsForumEventCode::NEW_MESSAGE; - rsEvents->postEvent(ev); - } - -#ifdef NOT_USED_YET - if (!msgChange->metaChange()) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsForums::notifyChanges() Found Message Change Notification"; - std::cerr << std::endl; -#endif - - std::map > &msgChangeMap = msgChange->msgChangeMap; - for(auto mit = msgChangeMap.begin(); mit != msgChangeMap.end(); ++mit) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsForums::notifyChanges() Msgs for Group: " << mit->first; - std::cerr << std::endl; -#endif - bool enabled = false; - if (autoDownloadEnabled(mit->first, enabled) && enabled) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::notifyChanges() AutoDownload for Group: " << mit->first; - std::cerr << std::endl; -#endif - - /* problem is most of these will be comments and votes, - * should make it occasional - every 5mins / 10minutes TODO */ - unprocessedGroups.push_back(mit->first); - } - } - } -#endif - } - else - { - if (rsEvents) - { - RsGxsGroupChange *grpChange = dynamic_cast(*it); - if (grpChange) - { - switch (grpChange->getType()) - { - case RsGxsNotify::TYPE_PROCESSED: // happens when the group is subscribed - { - auto ev = std::make_shared(); - ev->mForumGroupId = grpChange->mGroupId; - ev->mForumEventCode = RsForumEventCode::SUBSCRIBE_STATUS_CHANGED; - rsEvents->postEvent(ev); - } - break; - - case RsGxsNotify::TYPE_GROUP_SYNC_PARAMETERS_UPDATED: - { - auto ev = std::make_shared(); - ev->mForumGroupId = grpChange->mGroupId; - ev->mForumEventCode = RsForumEventCode::SYNC_PARAMETERS_UPDATED; - rsEvents->postEvent(ev); - } - break; - - case RsGxsNotify::TYPE_PUBLISHED: - case RsGxsNotify::TYPE_RECEIVED_NEW: - { - /* group received */ - - bool unknown; - { - RS_STACK_MUTEX(mKnownForumsMutex); - unknown = (mKnownForums.find(grpChange->mGroupId)==mKnownForums.end()); - mKnownForums[grpChange->mGroupId] = time(nullptr); - IndicateConfigChanged(); - } - - if(unknown) - { - auto ev = std::make_shared(); - ev->mForumGroupId = grpChange->mGroupId; - ev->mForumEventCode = RsForumEventCode::NEW_FORUM; - rsEvents->postEvent(ev); - } - else - RsInfo() << __PRETTY_FUNCTION__ - << " Not notifying already known forum " - << grpChange->mGroupId << std::endl; - } - break; - - case RsGxsNotify::TYPE_GROUP_DELETED: - { - auto ev = std::make_shared(); - ev->mForumGroupId = grpChange->mGroupId; - ev->mForumEventCode = RsForumEventCode::DELETED_FORUM; - rsEvents->postEvent(ev); - } - break; - - case RsGxsNotify::TYPE_STATISTICS_CHANGED: - { - auto ev = std::make_shared(); - ev->mForumGroupId = grpChange->mGroupId; - ev->mForumEventCode = RsForumEventCode::STATISTICS_CHANGED; - rsEvents->postEvent(ev); - - RS_STACK_MUTEX(mKnownForumsMutex); - mKnownForums[grpChange->mGroupId] = time(nullptr); - IndicateConfigChanged(); - } - break; - - case RsGxsNotify::TYPE_UPDATED: - { - // Happens when the group data has changed. In this case we need to analyse the old and new group in order to detect possible notifications for clients - - RsGxsForumGroupItem *old_forum_grp_item = dynamic_cast(grpChange->mOldGroupItem); - RsGxsForumGroupItem *new_forum_grp_item = dynamic_cast(grpChange->mNewGroupItem); - - if(old_forum_grp_item == nullptr || new_forum_grp_item == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " received GxsGroupUpdate item with mOldGroup and mNewGroup not of type RsGxsForumGroupItem or NULL. This is inconsistent!" << std::endl; - delete grpChange; - continue; - } - - // First of all, we check if there is a difference between the old and new list of moderators - - std::list added_mods, removed_mods; - - for(auto& gxs_id: new_forum_grp_item->mGroup.mAdminList.ids) - if(old_forum_grp_item->mGroup.mAdminList.ids.find(gxs_id) == old_forum_grp_item->mGroup.mAdminList.ids.end()) - added_mods.push_back(gxs_id); - - for(auto& gxs_id: old_forum_grp_item->mGroup.mAdminList.ids) - if(new_forum_grp_item->mGroup.mAdminList.ids.find(gxs_id) == new_forum_grp_item->mGroup.mAdminList.ids.end()) - removed_mods.push_back(gxs_id); - - if(!added_mods.empty() || !removed_mods.empty()) - { - auto ev = std::make_shared(); - - ev->mForumGroupId = new_forum_grp_item->meta.mGroupId; - ev->mModeratorsAdded = added_mods; - ev->mModeratorsRemoved = removed_mods; - ev->mForumEventCode = RsForumEventCode::MODERATOR_LIST_CHANGED; - - rsEvents->postEvent(ev); - } - - // check the list of pinned posts - - std::list added_pins, removed_pins; - - for(auto& msg_id: new_forum_grp_item->mGroup.mPinnedPosts.ids) - if(old_forum_grp_item->mGroup.mPinnedPosts.ids.find(msg_id) == old_forum_grp_item->mGroup.mPinnedPosts.ids.end()) - added_pins.push_back(msg_id); - - for(auto& msg_id: old_forum_grp_item->mGroup.mPinnedPosts.ids) - if(new_forum_grp_item->mGroup.mPinnedPosts.ids.find(msg_id) == new_forum_grp_item->mGroup.mPinnedPosts.ids.end()) - removed_pins.push_back(msg_id); - - if(!added_pins.empty() || !removed_pins.empty()) - { - auto ev = std::make_shared(); - - ev->mForumGroupId = new_forum_grp_item->meta.mGroupId; - ev->mForumEventCode = RsForumEventCode::PINNED_POSTS_CHANGED; - - rsEvents->postEvent(ev); - } - - if( old_forum_grp_item->mGroup.mDescription != new_forum_grp_item->mGroup.mDescription - || old_forum_grp_item->meta.mGroupName != new_forum_grp_item->meta.mGroupName - || old_forum_grp_item->meta.mGroupFlags != new_forum_grp_item->meta.mGroupFlags - || old_forum_grp_item->meta.mAuthorId != new_forum_grp_item->meta.mAuthorId - || old_forum_grp_item->meta.mCircleId != new_forum_grp_item->meta.mCircleId - ) - { - auto ev = std::make_shared(); - ev->mForumGroupId = new_forum_grp_item->meta.mGroupId; - ev->mForumEventCode = RsForumEventCode::UPDATED_FORUM; - rsEvents->postEvent(ev); - } - } - break; - - - default: - RsErr() << " Got a GXS event of type " << grpChange->getType() << " Currently not handled." << std::endl; - break; - } - } - } - } - - /* shouldn't need to worry about groups - as they need to be subscribed to */ - - delete *it; - } -} - -void p3GxsForums::service_tick() -{ - dummy_tick(); - RsTickEvent::tick_events(); - return; -} - -rstime_t p3GxsForums::service_getLastGroupSeenTs(const RsGxsGroupId& gid) -{ - rstime_t now = time(nullptr); - - RS_STACK_MUTEX(mKnownForumsMutex); - - auto it = mKnownForums.find(gid); - bool unknown_forum = it == mKnownForums.end(); - - if(unknown_forum) - { - mKnownForums[gid] = now; - IndicateConfigChanged(); - return now; - } - else - return it->second; -} -bool p3GxsForums::service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) -{ -#ifdef GXSFORUMS_DEBUG - std::cerr << "p3gxsForums: Checking unused forums: called by GxsCleaning." << std::endl; -#endif - - // request all group infos at once - - rstime_t now = time(nullptr); - - RS_STACK_MUTEX(mKnownForumsMutex); - - auto it = mKnownForums.find(meta.mGroupId); - bool unknown_forum = it == mKnownForums.end(); - -#ifdef GXSFORUMS_DEBUG - std::cerr << " Forum " << meta.mGroupId ; -#endif - - if(unknown_forum) - { - // This case should normally not happen. It does because this forum was never registered since it may - // arrived before this code was here - -#ifdef GXSFORUMS_DEBUG - std::cerr << ". Not known yet. Adding current time as new TS." << std::endl; -#endif - mKnownForums[meta.mGroupId] = now; - IndicateConfigChanged(); - - return true; - } - else - { - bool used_by_friends = (now < it->second + FORUM_UNUSED_BY_FRIENDS_DELAY); - bool subscribed = static_cast(meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED); - -#ifdef GXSFORUMS_DEBUG - std::cerr << ". subscribed: " << subscribed << ", used_by_friends: " << used_by_friends << " last TS: " << now - it->second << " secs ago (" << (now-it->second)/86400 << " days)"; -#endif - - if(!subscribed && !used_by_friends) - { -#ifdef GXSFORUMS_DEBUG - std::cerr << ". Scheduling for deletion" << std::endl; -#endif - return false; - } - else - { -#ifdef GXSFORUMS_DEBUG - std::cerr << ". Keeping!" << std::endl; -#endif - return true; - } - } -} -bool p3GxsForums::getGroupData(const uint32_t &token, std::vector &groups) -{ - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsForumGroupItem* item = dynamic_cast(*vit); - if (item) - { - RsGxsForumGroup grp = item->mGroup; - grp.mMeta = item->meta; - delete item; - groups.push_back(grp); - } - else - { - std::cerr << "Not a GxsForumGrpItem, deleting!" << std::endl; - delete *vit; - } - } - } - return ok; -} - -bool p3GxsForums::getMsgMetaData(const uint32_t &token, GxsMsgMetaMap& msg_metas) -{ - return RsGenExchange::getMsgMeta(token, msg_metas); -} - -/* Okay - chris is not going to be happy with this... - * but I can't be bothered with crazy data structures - * at the moment - fix it up later - */ - -bool p3GxsForums::getMsgData(const uint32_t &token, std::vector &msgs) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsForumMsgItem* item = dynamic_cast(*vit); - - if(item) - { - RsGxsForumMsg msg = item->mMsg; - msg.mMeta = item->meta; - msgs.push_back(msg); - delete item; - } - else - { - std::cerr << "Not a GxsForumMsgItem, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -} - -bool p3GxsForums::createForumV2( - const std::string& name, const std::string& description, - const RsGxsId& authorId, const std::set& 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(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 msgs; - if( getForumContent(forumId, std::set({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 forumInfo; - if(!getForumsInfo(std::list({forumId}), forumInfo)) - return failure( "Forum with Id " + forumId.toStdString() - + " does not exist locally." ); - - if(!origPostId.isNull()) - { - std::vector msgs; - if( getForumContent( forumId, - std::set({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) -{ - uint32_t token; - if(!createGroup(token, forum)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failed creating group." - << std::endl; - return false; - } - - if(waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, forum.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated " - << " group data." << std::endl; - return false; - } - - return true; -} - -bool p3GxsForums::editForum(RsGxsForumGroup& forum) -{ - uint32_t token; - if(!updateGroup(token, forum)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failed updating group." - << std::endl; - return false; - } - - if(waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, forum.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated " - << " group data." << std::endl; - return false; - } - - return true; -} - -bool p3GxsForums::getForumsSummaries( std::list& forums ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - if( !requestGroupInfo(token, opts) - || waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) return false; - return getGroupSummary(token, forums); -} - -bool p3GxsForums::getForumsInfo( const std::list& forumIds, std::vector& forumsInfo ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if(forumIds.empty()) - { - if( !requestGroupInfo(token, opts) || waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) - return false; - } - else - { - if( !requestGroupInfo(token, opts, forumIds, forumIds.size()==1) || waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) - return false; - } - return getGroupData(token, forumsInfo); -} - -bool p3GxsForums::getForumContent( - const RsGxsGroupId& forumId, - const std::set& msgs_to_request, - std::vector& msgs ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - GxsMsgReq msgIds; - msgIds[forumId] = msgs_to_request; - - if( !requestMsgInfo(token, opts, msgIds) || waitToken(token,std::chrono::seconds(5)) != RsTokenService::COMPLETE ) - return false; - - return getMsgData(token, msgs); -} - - -bool p3GxsForums::getForumMsgMetaData(const RsGxsGroupId& forumId, std::vector& msg_metas) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - - GxsMsgMetaMap meta_map; - std::list forumIds; - forumIds.push_back(forumId); - - if( !requestMsgInfo(token, opts, forumIds) || waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) return false; - - bool res = getMsgMetaData(token, meta_map); - - msg_metas = meta_map[forumId]; - - return res; -} - -bool p3GxsForums::markRead(const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t token; - setMessageReadStatus(token, msgId, read); - if(waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) return false; - - RsGxsGrpMsgIdPair p; - acknowledgeMsg(token,p); - - return true; -} - -bool p3GxsForums::subscribeToForum(const RsGxsGroupId& groupId, bool subscribe ) -{ - uint32_t token; - if( !RsGenExchange::subscribeToGroup(token, groupId, subscribe) || waitToken(token) != RsTokenService::COMPLETE ) return false; - - RsGxsGroupId grp; - acknowledgeGrp(token,grp); - - return true; -} - -bool p3GxsForums::exportForumLink( - std::string& link, const RsGxsGroupId& forumId, bool includeGxsData, - const std::string& baseUrl, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(forumId.isNull()) return failure("forumId cannot be null"); - - const bool outputRadix = baseUrl.empty(); - if(outputRadix && !includeGxsData) return - failure("includeGxsData must be true if format requested is base64"); - - if( includeGxsData && - !RsGenExchange::exportGroupBase64(link, forumId, errMsg) ) - return failure(errMsg); - - if(outputRadix) return true; - - std::vector forumsInfo; - if( !getForumsInfo(std::list({forumId}), forumsInfo) - || forumsInfo.empty() ) - return failure("failure retrieving forum information"); - - RsUrl inviteUrl(baseUrl); - inviteUrl.setQueryKV(FORUM_URL_ID_FIELD, forumId.toStdString()); - inviteUrl.setQueryKV(FORUM_URL_NAME_FIELD, forumsInfo[0].mMeta.mGroupName); - if(includeGxsData) inviteUrl.setQueryKV(FORUM_URL_DATA_FIELD, link); - - link = inviteUrl.toString(); - return true; -} - -bool p3GxsForums::importForumLink( - const std::string& link, RsGxsGroupId& forumId, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(link.empty()) return failure("link is empty"); - - const std::string* radixPtr(&link); - - RsUrl url(link); - const auto& query = url.query(); - const auto qIt = query.find(FORUM_URL_DATA_FIELD); - if(qIt != query.end()) radixPtr = &qIt->second; - - if(radixPtr->empty()) return failure(FORUM_URL_DATA_FIELD + " is empty"); - - if(!RsGenExchange::importGroupBase64(*radixPtr, forumId, errMsg)) - return failure(errMsg); - - return true; -} - -std::error_condition p3GxsForums::getChildPosts( - const RsGxsGroupId& forumId, const RsGxsMessageId& parentId, - std::vector& childPosts ) -{ - RS_DBG3("forumId: ", forumId, " parentId: ", parentId); - - if(forumId.isNull() || parentId.isNull()) - return std::errc::invalid_argument; - - std::vector msgIds; - msgIds.push_back(RsGxsGrpMsgIdPair(forumId, parentId)); - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; - opts.mOptions = RS_TOKREQOPT_MSG_PARENT | RS_TOKREQOPT_MSG_LATEST; - - uint32_t token; - if( !requestMsgRelatedInfo(token, opts, msgIds) || - waitToken(token) != RsTokenService::COMPLETE ) - return std::errc::timed_out; - - GxsMsgRelatedDataMap msgData; - if(!getMsgRelatedData(token, msgData)) - return std::errc::no_message_available; - - for(auto& mit: msgData) - { - for(auto& vit: mit.second) - { - auto msgItem = dynamic_cast(vit); - if(msgItem) - { - RsGxsForumMsg post = msgItem->mMsg; - post.mMeta = msgItem->meta; - childPosts.push_back(post); - } - else RS_WARN("Got item of unexpected type: ", vit); - - delete vit; - } - } - - return std::error_condition(); -} - -bool p3GxsForums::createGroup(uint32_t &token, RsGxsForumGroup &group) -{ - std::cerr << "p3GxsForums::createGroup()" << std::endl; - - RsGxsForumGroupItem* grpItem = new RsGxsForumGroupItem(); - grpItem->mGroup = group; - grpItem->meta = group.mMeta; - - RsGenExchange::publishGroup(token, grpItem); - return true; -} - -bool p3GxsForums::getForumServiceStatistics(GxsServiceStatistic& stat) -{ - uint32_t token; - if(!RsGxsIfaceHelper::requestServiceStatistic(token) || waitToken(token) != RsTokenService::COMPLETE) - return false; - - return RsGenExchange::getServiceStatistic(token,stat); -} - -bool p3GxsForums::getForumStatistics(const RsGxsGroupId& ForumId,GxsGroupStatistic& stat) -{ - uint32_t token; - if(!RsGxsIfaceHelper::requestGroupStatistic(token, ForumId) || waitToken(token) != RsTokenService::COMPLETE) - return false; - - return RsGenExchange::getGroupStatistic(token,stat); -} - -bool p3GxsForums::updateGroup(uint32_t &token, const RsGxsForumGroup &group) -{ - std::cerr << "p3GxsForums::updateGroup()" << std::endl; - - - if(group.mMeta.mGroupId.isNull()) - return false; - - RsGxsForumGroupItem* grpItem = new RsGxsForumGroupItem(); - grpItem->mGroup = group; - grpItem->meta = group.mMeta; - - RsGenExchange::updateGroup(token, grpItem); - return true; -} - -bool p3GxsForums::createMessage(RsGxsForumMsg& message) -{ - uint32_t token; - if( !createMsg(token, message) - || waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) return false; - - if(RsGenExchange::getPublishedMsgMeta(token, message.mMeta)) return true; - - return false; -} - -bool p3GxsForums::createMsg(uint32_t &token, RsGxsForumMsg &msg) -{ - std::cerr << "p3GxsForums::createForumMsg() GroupId: " << msg.mMeta.mGroupId; - std::cerr << std::endl; - - RsGxsForumMsgItem* msgItem = new RsGxsForumMsgItem(); - msgItem->mMsg = msg; - msgItem->meta = msg.mMeta; - - RsGenExchange::publishMsg(token, msgItem); - return true; -} - - -/********************************************************************************************/ -/********************************************************************************************/ - -void p3GxsForums::setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - uint32_t status = GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - if (read) - status = 0; - - setMsgStatusFlags(token, msgId, status, mask); - - /* WARNING: The event may be received before the operation is completed! - * TODO: move notification to blocking method markRead(...) which wait the - * operation to complete */ - if (rsEvents) - { - auto ev = std::make_shared(); - - ev->mForumMsgId = msgId.second; - ev->mForumGroupId = msgId.first; - ev->mForumEventCode = RsForumEventCode::READ_STATUS_CHANGED; - rsEvents->postEvent(ev); - } -} - -/********************************************************************************************/ -/********************************************************************************************/ - -std::error_condition p3GxsForums::setPostKeepForever( - const RsGxsGroupId& forumId, const RsGxsMessageId& postId, - bool keepForever ) -{ - if(forumId.isNull() || postId.isNull()) return std::errc::invalid_argument; - - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_KEEP_FOREVER; - uint32_t status = keepForever ? GXS_SERV::GXS_MSG_STATUS_KEEP_FOREVER : 0; - - uint32_t token; - setMsgStatusFlags(token, RsGxsGrpMsgIdPair(forumId, postId), status, mask); - - switch(waitToken(token)) - { - case RsTokenService::PENDING: // [[fallthrough]]; - case RsTokenService::PARTIAL: return std::errc::timed_out; - case RsTokenService::COMPLETE: // [[fallthrough]]; - case RsTokenService::DONE: - { - auto ev = std::make_shared(); - ev->mForumGroupId = forumId; - ev->mForumMsgId = postId; - ev->mForumEventCode = RsForumEventCode::UPDATED_MESSAGE; - rsEvents->postEvent(ev); - return std::error_condition(); - } - case RsTokenService::CANCELLED: return std::errc::operation_canceled; - default: return std::errc::bad_message; - } -} - -/* so we need the same tick idea as wiki for generating dummy forums - */ - -#define MAX_GEN_GROUPS 5 -#define MAX_GEN_MESSAGES 100 - -std::string p3GxsForums::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - -bool p3GxsForums::generateDummyData() -{ - mGenCount = 0; - mGenRefs.resize(MAX_GEN_MESSAGES); - - std::string groupName; - rs_sprintf(groupName, "TestForum_%d", mGenCount); - - std::cerr << "p3GxsForums::generateDummyData() Starting off with Group: " << groupName; - std::cerr << std::endl; - - /* create a new group */ - generateGroup(mGenToken, groupName); - - mGenActive = true; - - return true; -} - - -void p3GxsForums::dummy_tick() -{ - /* check for a new callback */ - - if (mGenActive) - { - std::cerr << "p3GxsForums::dummyTick() AboutActive"; - std::cerr << std::endl; - - uint32_t status = RsGenExchange::getTokenService()->requestStatus(mGenToken); - if (status != RsTokenService::COMPLETE) - { - std::cerr << "p3GxsForums::dummy_tick() Status: " << status; - std::cerr << std::endl; - - if (status == RsTokenService::FAILED) - { - std::cerr << "p3GxsForums::dummy_tick() generateDummyMsgs() FAILED"; - std::cerr << std::endl; - mGenActive = false; - } - return; - } - - if (mGenCount < MAX_GEN_GROUPS) - { - /* get the group Id */ - RsGxsGroupId groupId; - RsGxsMessageId emptyId; - if (!acknowledgeTokenGrp(mGenToken, groupId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - - std::cerr << "p3GxsForums::dummy_tick() Acknowledged GroupId: " << groupId; - std::cerr << std::endl; - - ForumDummyRef ref(groupId, emptyId, emptyId); - mGenRefs[mGenCount] = ref; - } - else if (mGenCount < MAX_GEN_MESSAGES) - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeTokenMsg(mGenToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - - std::cerr << "p3GxsForums::dummy_tick() Acknowledged "; - std::cerr << std::endl; - - /* store results for later selection */ - - ForumDummyRef ref(msgId.first, mGenThreadId, msgId.second); - mGenRefs[mGenCount] = ref; - } - else - { - std::cerr << "p3GxsForums::dummy_tick() Finished"; - std::cerr << std::endl; - - /* done */ - mGenActive = false; - return; - } - - mGenCount++; - - if (mGenCount < MAX_GEN_GROUPS) - { - std::string groupName; - rs_sprintf(groupName, "TestForum_%d", mGenCount); - - std::cerr << "p3GxsForums::dummy_tick() Generating Group: " << groupName; - std::cerr << std::endl; - - /* create a new group */ - generateGroup(mGenToken, groupName); - } - else - { - /* create a new message */ - uint32_t idx = (uint32_t) (mGenCount * RSRandom::random_f32()); - ForumDummyRef &ref = mGenRefs[idx]; - - RsGxsGroupId grpId = ref.mGroupId; - RsGxsMessageId parentId = ref.mMsgId; - mGenThreadId = ref.mThreadId; - if (mGenThreadId.isNull()) - { - mGenThreadId = parentId; - } - - std::cerr << "p3GxsForums::dummy_tick() Generating Msg ... "; - std::cerr << " GroupId: " << grpId; - std::cerr << " ThreadId: " << mGenThreadId; - std::cerr << " ParentId: " << parentId; - std::cerr << std::endl; - - generateMessage(mGenToken, grpId, parentId, mGenThreadId); - } - } -} - - -bool p3GxsForums::generateMessage(uint32_t &token, const RsGxsGroupId &grpId, const RsGxsMessageId &parentId, const RsGxsMessageId &threadId) -{ - RsGxsForumMsg msg; - - std::string rndId = genRandomId(); - - rs_sprintf(msg.mMsg, "Forum Msg: GroupId: %s, ThreadId: %s, ParentId: %s + some randomness: %s", - grpId.toStdString().c_str(), threadId.toStdString().c_str(), parentId.toStdString().c_str(), rndId.c_str()); - - msg.mMeta.mMsgName = msg.mMsg; - - msg.mMeta.mGroupId = grpId; - msg.mMeta.mThreadId = threadId; - msg.mMeta.mParentId = parentId; - - msg.mMeta.mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - - /* chose a random Id to sign with */ - std::list ownIds; - std::list::iterator it; - - rsIdentity->getOwnIds(ownIds); - - uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); - uint32_t i = 0; - for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); ++it, i++) ; - - if (it != ownIds.end()) - { - std::cerr << "p3GxsForums::generateMessage() Author: " << *it; - std::cerr << std::endl; - msg.mMeta.mAuthorId = *it; - } - else - { - std::cerr << "p3GxsForums::generateMessage() No Author!"; - std::cerr << std::endl; - } - - createMsg(token, msg); - - return true; -} - - -bool p3GxsForums::generateGroup(uint32_t &token, std::string groupName) -{ - /* generate a new forum */ - RsGxsForumGroup forum; - forum.mMeta.mGroupName = groupName; - - createGroup(token, forum); - - return true; -} - - - // Overloaded from RsTickEvent for Event callbacks. -void p3GxsForums::handle_event(uint32_t event_type, const std::string &/*elabel*/) -{ - std::cerr << "p3GxsForums::handle_event(" << event_type << ")"; - std::cerr << std::endl; - - // stuff. - switch(event_type) - { - case FORUM_TESTEVENT_DUMMYDATA: - generateDummyData(); - break; - - default: - /* error */ - std::cerr << "p3GxsForums::handle_event() Unknown Event Type: " << event_type; - std::cerr << std::endl; - 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; -} - -/*static*/ const std::string RsGxsForums::DEFAULT_FORUM_BASE_URL = - "retroshare:///forums"; -/*static*/ const std::string RsGxsForums::FORUM_URL_NAME_FIELD = - "forumName"; -/*static*/ const std::string RsGxsForums::FORUM_URL_ID_FIELD = - "forumId"; -/*static*/ const std::string RsGxsForums::FORUM_URL_DATA_FIELD = - "forumData"; -/*static*/ const std::string RsGxsForums::FORUM_URL_MSG_TITLE_FIELD = - "forumMsgTitle"; -/*static*/ const std::string RsGxsForums::FORUM_URL_MSG_ID_FIELD = - "forumMsgId"; - -RsGxsForumGroup::~RsGxsForumGroup() = default; -RsGxsForumMsg::~RsGxsForumMsg() = default; -RsGxsForums::~RsGxsForums() = default; -RsGxsForumEvent::~RsGxsForumEvent() = default; diff --git a/libretroshare/src/services/p3gxsforums.h b/libretroshare/src/services/p3gxsforums.h deleted file mode 100644 index 97f04cc7b..000000000 --- a/libretroshare/src/services/p3gxsforums.h +++ /dev/null @@ -1,192 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxsforums.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2019-2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#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, - public RsTickEvent /* only needed for testing - remove after */ -{ -public: - p3GxsForums( - RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs); - - virtual RsServiceInfo getServiceInfo() override; - virtual void service_tick() override; - -protected: - virtual void notifyChanges(std::vector& changes) override; - /// Overloaded from RsTickEvent. - virtual void handle_event(uint32_t event_type, const std::string &elabel) override; - - virtual RsSerialiser* setupSerialiser() override; // @see p3Config::setupSerialiser() - virtual bool saveList(bool &cleanup, std::list&saveList) override; // @see p3Config::saveList(bool &cleanup, std::list&) - virtual bool loadList(std::list& loadList) override; // @see p3Config::loadList(std::list&) - - virtual bool service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) override; - virtual rstime_t service_getLastGroupSeenTs(const RsGxsGroupId&) override; -public: - /// @see RsGxsForums::createForumV2 - bool createForumV2( - const std::string& name, const std::string& description, - const RsGxsId& authorId = RsGxsId(), - const std::set& moderatorsIds = std::set(), - 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) override; - - /// @see RsGxsForums::createMessage @deprecated - RS_DEPRECATED_FOR(createPost) - virtual bool createMessage(RsGxsForumMsg& message) override; - - /// @see RsGxsForums::editForum - virtual bool editForum(RsGxsForumGroup& forum) override; - - /// @see RsGxsForums::getForumsSummaries - virtual bool getForumsSummaries(std::list& forums) override; - - /// @see RsGxsForums::getForumsInfo - virtual bool getForumsInfo( - const std::list& forumIds, - std::vector& forumsInfo ) override; - - /// Implementation of @see RsGxsForums::getForumStatistics - bool getForumStatistics(const RsGxsGroupId& ForumId,GxsGroupStatistic& stat) override; - - /// Implementation of @see RsGxsForums::getForumServiceStatistics - bool getForumServiceStatistics(GxsServiceStatistic& stat) override; - - /// @see RsGxsForums::getForumMsgMetaData - virtual bool getForumMsgMetaData(const RsGxsGroupId& forumId, std::vector& msg_metas) override; - - /// @see RsGxsForums::getForumContent - virtual bool getForumContent( - const RsGxsGroupId& forumId, - const std::set& msgs_to_request, - std::vector& msgs ) override; - - /// @see RsGxsForums::markRead - virtual bool markRead(const RsGxsGrpMsgIdPair& messageId, bool read) override; - - /// @see RsGxsForums::subscribeToForum - virtual bool subscribeToForum( const RsGxsGroupId& forumId, - bool subscribe ) override; - - /// @see RsGxsForums - bool exportForumLink( - std::string& link, const RsGxsGroupId& forumId, - bool includeGxsData = true, - const std::string& baseUrl = DEFAULT_FORUM_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsGxsForums - bool importForumLink( - const std::string& link, - RsGxsGroupId& forumId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsGxsForums - std::error_condition getChildPosts( - const RsGxsGroupId& forumId, const RsGxsMessageId& parentId, - std::vector& childPosts ) override; - - /// @see RsGxsForums - std::error_condition setPostKeepForever( - const RsGxsGroupId& forumId, const RsGxsMessageId& postId, - bool keepForever ) override; - - /// implementation of rsGxsGorums - /// - bool getGroupData(const uint32_t &token, std::vector &groups) override; - bool getMsgData(const uint32_t &token, std::vector &msgs) override; - void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) override; - bool createGroup(uint32_t &token, RsGxsForumGroup &group) override; - bool createMsg(uint32_t &token, RsGxsForumMsg &msg) override; - bool updateGroup(uint32_t &token, const RsGxsForumGroup &group) override; - - bool getMsgMetaData(const uint32_t &token, GxsMsgMetaMap& msg_metas) ; - -private: - -static uint32_t forumsAuthenPolicy(); - -virtual bool generateDummyData(); - -std::string genRandomId(); - -void dummy_tick(); - -bool generateMessage(uint32_t &token, const RsGxsGroupId &grpId, - const RsGxsMessageId &parentId, const RsGxsMessageId &threadId); -bool generateGroup(uint32_t &token, std::string groupName); - - class ForumDummyRef - { - public: - ForumDummyRef() { return; } - ForumDummyRef(const RsGxsGroupId &grpId, const RsGxsMessageId &threadId, const RsGxsMessageId &msgId) - :mGroupId(grpId), mThreadId(threadId), mMsgId(msgId) { return; } - - RsGxsGroupId mGroupId; - RsGxsMessageId mThreadId; - RsGxsMessageId mMsgId; - }; - - uint32_t mGenToken; - bool mGenActive; - int mGenCount; - std::vector mGenRefs; - RsGxsMessageId mGenThreadId; - std::map mKnownForums ; - - RsMutex mKnownForumsMutex; -}; diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc deleted file mode 100644 index 4b7383a93..000000000 --- a/libretroshare/src/services/p3gxsreputation.cc +++ /dev/null @@ -1,1635 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxsreputation.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014-2014 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include "pqi/p3linkmgr.h" - -#include "retroshare/rspeers.h" - -#include "services/p3gxsreputation.h" - -#include "rsitems/rsgxsreputationitems.h" -#include "rsitems/rsconfigitems.h" - -#include - -#include - -/**** - * #define DEBUG_REPUTATION 1 - ****/ - -/************ IMPLEMENTATION NOTES ********************************* - * - * p3GxsReputation shares opinions / reputations with peers. - * This is closely linked to p3IdService, receiving info, updating - * reputations as needed. - * - * It is designed as separate service as the exchange of peer opinions - * is not well suited to Gxs Groups / Messages... - * - * Instead we can broadcast opinions to all peers. - * - * To avoid too much traffic, changes are transmitted rather than whole lists. - * Peer A Peer B - * last update -----------> - * <----------- modified opinions. - * - * If not clever enough, this service will have to store a huge amount of data. - * To make things tractable we do this: - * - do not store reputations when no data is present, or when all friends are neutral - * - only send a neutral opinion when they are a true change over someone's opinion - * - only send a neutral opinion when it is a true change over someone's opinion - * - auto-clean reputations for default values - * - * std::map mReputations. - * std::multimap mUpdated. - * - * std::map mConfig; - * - * Updates from p3GxsReputation -> p3IdService. - * Updates from p3IdService -> p3GxsReputation. - * - * Each peer locally stores reputations for all GXS ids. If not stored, a default value - * is used, corresponding to a neutral opinion. Peers also share their reputation level - * with their neighbor nodes. - * - * The calculation method is the following: - * - * Local values: - * Good: 2 - * Neutral: 1 - * Bad: 0 - * - * Overall reputation score: - * - * if(own_opinion == 0) // means we dont' care - * r = average_of_friends_opinions - * else - * r = own_opinion - * - * Decisions based on reputation score: - * - * 0 x1 1 x2 2 - * | <-----------------------------------------------------------------------> | - * ---------+ - * Lobbies | Msgs dropped - * Forums | Msgs dropped - * Messages | Msgs dropped - * ---------+---------------------------------------------------------------------------- - * - * We select x1=0.5 - * - * => to kill an identity, either you, or at least 50% of your friends need to flag it - * as bad. - * Rules: - * * a single peer cannot drastically change the behavior of a given GXS id - * * it should be easy for many peers to globally kill a GXS id - * - * Typical examples: - * - * Friends | Friend average | Own | alpha | Score - * -----------+---------------------+----------+------------+-------------- - * 10 | 0.5 | 1 | 0.25 | 0.375 - * 10 | 1.0 | 1 | 0.25 | 1.0 - * 10 | 1.0 | 0 | 0.25 | 1.0 - * - * To check: - * [X] Opinions are saved/loaded accross restart - * [X] Opinions are transmitted to friends - * [X] Opinions are transmitted to friends when updated - * - * To do: - * [X] Add debug info - * [X] Test the whole thing - * [X] Implement a system to allow not storing info when we don't have it - */ - -//static const uint32_t LOWER_LIMIT = 0; // used to filter valid Opinion values from serialized data -static const uint32_t UPPER_LIMIT = 2; // used to filter valid Opinion values from serialized data -//static const int kMaximumPeerAge = 180; // half a year. -static const int kMaximumSetSize = 100; // max set of updates to send at once. -static const int CLEANUP_PERIOD = 600 ; // 10 minutes -//static const int ACTIVE_FRIENDS_ONLINE_DELAY = 86400*7 ; // 1 week. -static const int kReputationRequestPeriod = 600; // 10 mins -static const int kReputationStoreWait = 180; // 3 minutes. -//static const float REPUTATION_ASSESSMENT_THRESHOLD_X1 = 0.5f ; // reputation under which the peer gets killed. Warning there's a 1 shift with what's shown in GUI. Be careful. -//static const uint32_t PGP_AUTO_BAN_THRESHOLD_DEFAULT = 2 ; // above this, auto ban any GXS id signed by this node -static const uint32_t IDENTITY_FLAGS_UPDATE_DELAY = 100 ; // -static const uint32_t BANNED_NODES_UPDATE_DELAY = 313 ; // update approx every 5 mins. Chosen to not be a multiple of IDENTITY_FLAGS_UPDATE_DELAY -static const uint32_t REPUTATION_INFO_KEEP_DELAY_DEFAULT = 86400*35; // remove old reputation info 5 days after last usage limit, in case the ID would come back.. -static const uint32_t BANNED_NODES_INACTIVITY_KEEP_DEFAULT = 86400*60; // remove all info about banned nodes after 2 months of inactivity - -static const uint32_t REPUTATION_DEFAULT_MIN_VOTES_FOR_REMOTELY_POSITIVE = 1; // min difference in votes that makes friends opinion globally positive -static const uint32_t REPUTATION_DEFAULT_MIN_VOTES_FOR_REMOTELY_NEGATIVE = 1; // min difference in votes that makes friends opinion globally negative -static const uint32_t MIN_DELAY_BETWEEN_REPUTATION_CONFIG_SAVE = 61 ; // never save more often than once a minute. - -p3GxsReputation::p3GxsReputation(p3LinkMgr *lm) - :p3Service(), p3Config(), - mReputationMtx("p3GxsReputation"), mLinkMgr(lm) -{ - addSerialType(new RsGxsReputationSerialiser()); - - //mPgpAutoBanThreshold = PGP_AUTO_BAN_THRESHOLD_DEFAULT ; - mRequestTime = 0; - mStoreTime = 0; - mReputationsUpdated = false; - mLastIdentityFlagsUpdate = time(NULL) - 3; - mLastBannedNodesUpdate = 0 ; - mBannedNodesProxyNeedsUpdate = false; - - mAutoSetPositiveOptionToContacts = true; // default - mMinVotesForRemotelyPositive = REPUTATION_DEFAULT_MIN_VOTES_FOR_REMOTELY_POSITIVE; - mMinVotesForRemotelyNegative = REPUTATION_DEFAULT_MIN_VOTES_FOR_REMOTELY_NEGATIVE; - - mLastReputationConfigSaved = 0; - mChanged = false ; - mMaxPreventReloadBannedIds = 0 ; // default is "never" - mLastCleanUp = time(NULL) ; -} - -const std::string GXS_REPUTATION_APP_NAME = "gxsreputation"; -const uint16_t GXS_REPUTATION_APP_MAJOR_VERSION = 1; -const uint16_t GXS_REPUTATION_APP_MINOR_VERSION = 0; -const uint16_t GXS_REPUTATION_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_REPUTATION_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3GxsReputation::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_REPUTATION, - GXS_REPUTATION_APP_NAME, - GXS_REPUTATION_APP_MAJOR_VERSION, - GXS_REPUTATION_APP_MINOR_VERSION, - GXS_REPUTATION_MIN_MAJOR_VERSION, - GXS_REPUTATION_MIN_MINOR_VERSION); -} - -int p3GxsReputation::tick() -{ - processIncoming(); - sendPackets(); - - rstime_t now = time(NULL); - - if(mLastCleanUp + CLEANUP_PERIOD < now) - { - cleanup() ; - - mLastCleanUp = now ; - } - - // no more than once per 5 second chunk. - - if(now > IDENTITY_FLAGS_UPDATE_DELAY+mLastIdentityFlagsUpdate) - { - updateStaticIdentityFlags() ; - mLastIdentityFlagsUpdate = now ; - } - if(now > BANNED_NODES_UPDATE_DELAY+mLastBannedNodesUpdate) // 613 is not a multiple of 100, to avoid piling up work - { - updateStaticIdentityFlags() ; // needed before updateBannedNodesList! - updateBannedNodesProxy(); - mLastBannedNodesUpdate = now ; - } - - if(mBannedNodesProxyNeedsUpdate) - { - updateBannedNodesProxy(); - mBannedNodesProxyNeedsUpdate = false ; - } - -#ifdef DEBUG_REPUTATION - static rstime_t last_debug_print = time(NULL) ; - - if(now > 10+last_debug_print) - { - last_debug_print = now ; - debug_print() ; - } -#endif - - if(mChanged && now > mLastReputationConfigSaved + MIN_DELAY_BETWEEN_REPUTATION_CONFIG_SAVE) - { - IndicateConfigChanged() ; - mLastReputationConfigSaved = now ; - mChanged = false ; - } - - return 0; -} - -void p3GxsReputation::setAutoPositiveOpinionForContacts(bool b) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - if(b != mAutoSetPositiveOptionToContacts) - { - mLastIdentityFlagsUpdate = 0 ; - mLastCleanUp = 0 ; - mAutoSetPositiveOptionToContacts = b ; - - IndicateConfigChanged() ; - } -} -bool p3GxsReputation::autoPositiveOpinionForContacts() -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - return mAutoSetPositiveOptionToContacts ; -} - -void p3GxsReputation::setRememberBannedIdThreshold(uint32_t days) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - if(mMaxPreventReloadBannedIds != days*86400) - { - mMaxPreventReloadBannedIds = days*86400 ; - IndicateConfigChanged(); - } -} -uint32_t p3GxsReputation::rememberBannedIdThreshold() -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - return mMaxPreventReloadBannedIds/86400; -} - -int p3GxsReputation::status() -{ - return 1; -} -class ZeroInitCnt -{ - public: - ZeroInitCnt(): cnt(0) {} - uint32_t cnt ; - - operator uint32_t& () { return cnt ; } - operator uint32_t() const { return cnt ; } -}; - -void p3GxsReputation::updateBannedNodesProxy() -{ - // This function keeps the Banned GXS id proxy up to date. - // - - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - mPerNodeBannedIdsProxy.clear(); - - for( std::map::iterator rit = mBannedPgpIds.begin();rit!=mBannedPgpIds.end();++rit) - for(std::set::const_iterator it(rit->second.known_identities.begin());it!=rit->second.known_identities.end();++it) - mPerNodeBannedIdsProxy.insert(*it) ; -} - -void p3GxsReputation::updateStaticIdentityFlags() -{ - // This function is the *only* place where rsIdentity is called. Normally the cross calls between p3IdService and p3GxsReputations should only - // happen one way: from rsIdentity to rsReputations. Still, reputations need to keep track of some identity flags. It's very important to make sure that - // rsIdentity is not called inside a mutex-protected zone, because normally calls happen in the other way. - - std::list to_update ; - - // we need to gather the list to be used in a non locked frame - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_REPUTATION - std::cerr << "Updating reputation identity flags" << std::endl; -#endif - - for( std::map::iterator rit = mReputations.begin();rit!=mReputations.end();++rit) - { - if( (!(rit->second.mIdentityFlags & REPUTATION_IDENTITY_FLAG_UP_TO_DATE)) && (mPerNodeBannedIdsProxy.find(rit->first) == mPerNodeBannedIdsProxy.end())) - to_update.push_back(rit->first) ; - } - } - - for(std::list::const_iterator rit(to_update.begin());rit!=to_update.end();++rit) - { - RsIdentityDetails details; - - if(!rsIdentity->getIdDetails(*rit,details)) - { -#ifdef DEBUG_REPUTATION - std::cerr << " cannot obtain info for " << *rit << ". Will do it later." << std::endl; -#endif - continue ; - } - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - std::map::iterator it = mReputations.find(*rit) ; - - if(it == mReputations.end()) - { - std::cerr << " Weird situation: item " << *rit << " has been deleted from the list??" << std::endl; - continue ; - } - it->second.mIdentityFlags = REPUTATION_IDENTITY_FLAG_UP_TO_DATE ; // resets the NEEDS_UPDATE flag. All other flags set later on. - - if(details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) - { - it->second.mIdentityFlags |= REPUTATION_IDENTITY_FLAG_PGP_LINKED ; - it->second.mOwnerNode = details.mPgpId ; - } - if(details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN ) it->second.mIdentityFlags |= REPUTATION_IDENTITY_FLAG_PGP_KNOWN ; - -#ifdef DEBUG_REPUTATION - std::cerr << " updated flags for " << *rit << " to " << std::hex << it->second.mIdentityFlags << std::dec << std::endl; -#endif - - it->second.updateReputation() ; - mChanged = true ; - } - } -} - -void p3GxsReputation::cleanup() -{ - // remove opinions from friends that havn't been seen online for more than the specified delay - -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::cleanup() " << std::endl; -#endif - rstime_t now = time(NULL) ; - - // We should keep opinions about identities that do not exist anymore, but only rely on the usage TS. That will in particular avoid asking p3idservice about deleted - // identities, which would cause an excess of hits to the database. We do it in two steps to avoid a deadlock when calling rsIdentity from here. - // Also, neutral opinions for banned PGP linked nodes are kept, so as to be able to not request them again. - - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - for(std::map::iterator it(mReputations.begin());it!=mReputations.end();) - { - bool should_delete = false ; - - if( it->second.mOwnOpinion == - static_cast(RsOpinion::NEGATIVE) && - mMaxPreventReloadBannedIds != 0 && - it->second.mOwnOpinionTs + mMaxPreventReloadBannedIds < now ) - { -#ifdef DEBUG_REPUTATION - std::cerr << " ID " << it->first << ": own is negative for more than " << mMaxPreventReloadBannedIds/86400 << " days. Reseting it!" << std::endl; -#endif - should_delete = true; - } - - // Delete slots with basically no information - - if( it->second.mOpinions.empty() && - it->second.mOwnOpinion == - static_cast(RsOpinion::NEUTRAL) && - it->second.mOwnerNode.isNull() ) - { -#ifdef DEBUG_REPUTATION - std::cerr << " ID " << it->first << ": own is neutral and no opinions from friends => remove entry" << std::endl; -#endif - should_delete = true ; - } - - // Delete slots that havn't been used for a while. The else below is here for debug display purposes, and not harmful since both conditions lead the same effect. - - else if(it->second.mLastUsedTS + REPUTATION_INFO_KEEP_DELAY_DEFAULT < now) - { -#ifdef DEBUG_REPUTATION - std::cerr << " ID " << it->first << ": no request for reputation for more than " << REPUTATION_INFO_KEEP_DELAY_DEFAULT/86400 << " days => deleting." << std::endl; -#endif - should_delete = true ; - } -#ifdef DEBUG_REPUTATION - else - std::cerr << " ID " << it->first << ": flags=" << std::hex << it->second.mIdentityFlags << std::dec << ". Last used: " << (now - it->second.mLastUsedTS)/86400 << " days ago: kept." << std::endl; -#endif - - if(should_delete) - { - std::map::iterator tmp(it) ; - ++tmp ; - mReputations.erase(it) ; - it = tmp ; - mChanged = true ; - } - else - ++it; - } - } - - // Clean up of the banned PGP ids. - - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - for(std::map::iterator it(mBannedPgpIds.begin());it!=mBannedPgpIds.end();) - if(it->second.last_activity_TS + BANNED_NODES_INACTIVITY_KEEP_DEFAULT < now) - { -#ifdef DEBUG_REPUTATION - std::cerr << " Removing all info about banned node " << it->first << " by lack of activity." << std::endl; -#endif - std::map::iterator tmp(it ) ; - ++tmp ; - mBannedPgpIds.erase(it) ; - it = tmp ; - - mChanged = true ; - } - else - ++it ; - } - - // Update opinions based on flags and contact information. - // Note: the call to rsIdentity->isARegularContact() is done off-mutex, in order to avoid a cross-deadlock, as - // normally, p3GxsReputation gets called by p3dentity and not te reverse. That explains the weird implementation - // of these two loops. - { - std::list should_set_to_positive_candidates ; - - if(mAutoSetPositiveOptionToContacts) - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - for(std::map::iterator it(mReputations.begin());it!=mReputations.end();++it) - if( it->second.mOwnOpinion == - static_cast(RsOpinion::NEUTRAL) ) - should_set_to_positive_candidates.push_back(it->first) ; - } - - for(std::list::const_iterator it(should_set_to_positive_candidates.begin());it!=should_set_to_positive_candidates.end();++it) - if(rsIdentity->isARegularContact(*it)) - setOwnOpinion(*it, RsOpinion::POSITIVE); - } -} - -static RsOpinion safe_convert_uint32t_to_opinion(uint32_t op) -{ - return RsOpinion(std::min( static_cast(op), UPPER_LIMIT )); -} -/***** Implementation ******/ - -bool p3GxsReputation::processIncoming() -{ - /* for each packet - pass to specific handler */ - RsItem *item = NULL; - while(NULL != (item = recvItem())) - { -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::processingIncoming() Received Item:"; - std::cerr << std::endl; - item->print(std::cerr); - std::cerr << std::endl; -#endif - bool itemOk = true; - switch(item->PacketSubType()) - { - default: - case RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM: - case RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM: - std::cerr << "p3GxsReputation::processingIncoming() Unknown Item"; - std::cerr << std::endl; - itemOk = false; - break; - - case RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM: - { - RsGxsReputationRequestItem *requestItem = dynamic_cast(item); - if (requestItem) - SendReputations(requestItem); - else - itemOk = false; - } - break; - - case RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM: - { - RsGxsReputationUpdateItem *updateItem = dynamic_cast(item); - - if (updateItem) - RecvReputations(updateItem); - else - itemOk = false; - } - break; - } - - if (!itemOk) - { - std::cerr << "p3GxsReputation::processingIncoming() Error with Item"; - std::cerr << std::endl; - } - - /* clean up */ - delete item; - } - return true ; -} - - -bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request) -{ -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::SendReputations()" << std::endl; -#endif - - RsPeerId peerId = request->PeerId(); - rstime_t last_update = request->mLastUpdate; - rstime_t now = time(NULL); - - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - std::multimap::iterator tit; - tit = mUpdated.upper_bound(last_update); // could skip some - (fixed below). - - int count = 0; - int totalcount = 0; - RsGxsReputationUpdateItem *pkt = new RsGxsReputationUpdateItem(); - - pkt->PeerId(peerId); - for(;tit != mUpdated.end(); ++tit) - { - /* find */ - std::map::iterator rit = mReputations.find(tit->second); - - if (rit == mReputations.end()) - { - std::cerr << "p3GxsReputation::SendReputations() ERROR Missing Reputation"; - std::cerr << std::endl; - // error. - continue; - } - - if (rit->second.mOwnOpinionTs == 0) - { - std::cerr << "p3GxsReputation::SendReputations() ERROR OwnOpinionTS = 0"; - std::cerr << std::endl; - // error. - continue; - } - - RsGxsId gxsId = rit->first; - pkt->mOpinions[gxsId] = rit->second.mOwnOpinion; - pkt->mLatestUpdate = rit->second.mOwnOpinionTs; - - if (pkt->mLatestUpdate == (uint32_t) now) - { - // if we could possibly get another Update at this point (same second). - // then set Update back one second to ensure there are none missed. - pkt->mLatestUpdate--; - } - - count++; - totalcount++; - - if (count > kMaximumSetSize) - { -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::SendReputations() Sending Full Packet"; - std::cerr << std::endl; -#endif - - sendItem(pkt); - - pkt = new RsGxsReputationUpdateItem(); - pkt->PeerId(peerId); - count = 0; - } - } - - if (!pkt->mOpinions.empty()) - { -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::SendReputations() Sending Final Packet"; - std::cerr << std::endl; -#endif - - sendItem(pkt); - } - else - { - delete pkt; - } - -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::SendReputations() Total Count: " << totalcount; - std::cerr << std::endl; -#endif - - return true; -} - -void p3GxsReputation::locked_updateOpinion( - const RsPeerId& from, const RsGxsId& about, RsOpinion op ) -{ - /* find matching Reputation */ - std::map::iterator rit = mReputations.find(about); - - RsOpinion new_opinion = op; - RsOpinion old_opinion = RsOpinion::NEUTRAL ; // default if not set - - bool updated = false ; - -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::update opinion of " << about << " from " << from << " to " << op << std::endl; -#endif - // now 4 cases; - // Opinion already stored - // New opinion is same: nothing to do - // New opinion is different: if neutral, remove entry - // Nothing stored - // New opinion is neutral: nothing to do - // New opinion is != 1: create entry and store - - if (rit == mReputations.end()) - { -#ifdef DEBUG_REPUTATION - std::cerr << " no preview record"<< std::endl; -#endif - - if(new_opinion != RsOpinion::NEUTRAL) - { - mReputations[about] = Reputation(); - rit = mReputations.find(about); - } - else - { -#ifdef DEBUG_REPUTATION - std::cerr << " no changes!"<< std::endl; -#endif - return ; // nothing to do - } - } - - Reputation& reputation = rit->second; - - std::map::iterator it2 = reputation.mOpinions.find(from) ; - - if(it2 == reputation.mOpinions.end()) - { - if(new_opinion != RsOpinion::NEUTRAL) - { - reputation.mOpinions[from] = new_opinion; // filters potentially tweaked reputation score sent by friend - updated = true ; - } - } - else - { - old_opinion = it2->second ; - - if(new_opinion == RsOpinion::NEUTRAL) - { - reputation.mOpinions.erase(it2) ; // don't store when the opinion is neutral - updated = true ; - } - else if(new_opinion != old_opinion) - { - it2->second = new_opinion ; - updated = true ; - } - } - - if( reputation.mOpinions.empty() && - reputation.mOwnOpinion == static_cast(RsOpinion::NEUTRAL) ) - { - mReputations.erase(rit) ; -#ifdef DEBUG_REPUTATION - std::cerr << " own is neutral and no opinions from friends => remove entry" << std::endl; -#endif - updated = true ; - } - else if(updated) - { -#ifdef DEBUG_REPUTATION - std::cerr << " reputation changed. re-calculating." << std::endl; -#endif - reputation.updateReputation() ; - } - - if(updated) - IndicateConfigChanged() ; -} - -bool p3GxsReputation::RecvReputations(RsGxsReputationUpdateItem *item) -{ -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::RecvReputations() from " << item->PeerId() << std::endl; -#endif - - RsPeerId peerid = item->PeerId(); - - for( std::map::iterator it = item->mOpinions.begin(); it != item->mOpinions.end(); ++it) - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - locked_updateOpinion(peerid,it->first,safe_convert_uint32t_to_opinion(it->second)); - } - - updateLatestUpdate(peerid,item->mLatestUpdate); - - return true; -} - - -bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid,rstime_t latest_update) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator it = mConfig.find(peerid); - - if (it == mConfig.end()) - { - mConfig[peerid] = ReputationConfig(peerid); - it = mConfig.find(peerid) ; - } - it->second.mLatestUpdate = latest_update ; - - mReputationsUpdated = true; - // Switched to periodic save due to scale of data. - - IndicateConfigChanged(); - - return true; -} - -/******************************************************************** - * Opinion - ****/ - -RsReputationLevel p3GxsReputation::overallReputationLevel( - const RsGxsId& id, uint32_t* identity_flags ) -{ - RsReputationInfo info ; - getReputationInfo(id,RsPgpId(),info) ; - - RsPgpId owner_id ; - - if(identity_flags) - getIdentityFlagsAndOwnerId(id,*identity_flags,owner_id); - - return info.mOverallReputationLevel ; -} - -bool p3GxsReputation::getIdentityFlagsAndOwnerId(const RsGxsId& gxsid, uint32_t& identity_flags,RsPgpId& owner_id) -{ - if(gxsid.isNull()) - return false ; - - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator it = mReputations.find(gxsid) ; - - if(it == mReputations.end()) - return false ; - - if(!(it->second.mIdentityFlags & REPUTATION_IDENTITY_FLAG_UP_TO_DATE)) - return false ; - - if(it->second.mIdentityFlags & REPUTATION_IDENTITY_FLAG_PGP_LINKED) - identity_flags |= RS_IDENTITY_FLAGS_PGP_LINKED ; - - if(it->second.mIdentityFlags & REPUTATION_IDENTITY_FLAG_PGP_KNOWN) - identity_flags |= RS_IDENTITY_FLAGS_PGP_KNOWN ; - - owner_id = it->second.mOwnerNode ; - - return true ; -} - -bool p3GxsReputation::getReputationInfo( - const RsGxsId& gxsid, const RsPgpId& ownerNode, RsReputationInfo& info, - bool stamp ) -{ - if(gxsid.isNull()) - return false ; - - rstime_t now = time(nullptr); - - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_REPUTATION2 - std::cerr << "getReputationInfo() for " << gxsid << ", stamp = " << stamp << std::endl; -#endif - std::map::iterator it = mReputations.find(gxsid) ; - RsPgpId owner_id ; - - if(it == mReputations.end()) - { - info.mOwnOpinion = RsOpinion::NEUTRAL ; - info.mFriendAverageScore = RS_REPUTATION_THRESHOLD_DEFAULT ; - info.mFriendsNegativeVotes = 0 ; - info.mFriendsPositiveVotes = 0 ; - - owner_id = ownerNode ; - } - else - { - Reputation& rep(it->second) ; - - info.mOwnOpinion = - safe_convert_uint32t_to_opinion( - static_cast(rep.mOwnOpinion) ); - info.mFriendAverageScore = rep.mFriendAverage ; - info.mFriendsNegativeVotes = rep.mFriendsNegative ; - info.mFriendsPositiveVotes = rep.mFriendsPositive ; - - if(rep.mOwnerNode.isNull() && !ownerNode.isNull()) - rep.mOwnerNode = ownerNode ; - - owner_id = rep.mOwnerNode ; - - if(stamp) - rep.mLastUsedTS = now ; - - mChanged = true ; - } - - // now compute overall score and reputation - - // 0 - check for own opinion. If positive or negative, it decides on the result - - if(info.mOwnOpinion == RsOpinion::NEGATIVE) - { - // own opinion is always read in priority - - info.mOverallReputationLevel = RsReputationLevel::LOCALLY_NEGATIVE; - return true ; - } - if(info.mOwnOpinion == RsOpinion::POSITIVE) - { - // own opinion is always read in priority - - info.mOverallReputationLevel = RsReputationLevel::LOCALLY_POSITIVE; - return true ; - } - - // 1 - check for banned PGP ids. - - std::map::iterator it2 ; - - if(!owner_id.isNull() && (it2 = mBannedPgpIds.find(owner_id))!=mBannedPgpIds.end()) - { - // Check if current identity is present in the list of known identities for this banned node. - - if(it2->second.known_identities.find(gxsid) == it2->second.known_identities.end()) - { - it2->second.known_identities.insert(gxsid) ; - it2->second.last_activity_TS = now ; - - // if so, update - - mBannedNodesProxyNeedsUpdate = true ; - } - -#ifdef DEBUG_REPUTATION2 - std::cerr << "p3GxsReputations: identity " << gxsid << " is banned because owner node ID " << owner_id << " is banned (found in banned nodes list)." << std::endl; -#endif - info.mOverallReputationLevel = RsReputationLevel::LOCALLY_NEGATIVE; - return true ; - } - // also check the proxy - - if(mPerNodeBannedIdsProxy.find(gxsid) != mPerNodeBannedIdsProxy.end()) - { -#ifdef DEBUG_REPUTATION2 - std::cerr << "p3GxsReputations: identity " << gxsid << " is banned because owner node ID " << owner_id << " is banned (found in proxy)." << std::endl; -#endif - info.mOverallReputationLevel = RsReputationLevel::LOCALLY_NEGATIVE; - return true; - } - // 2 - now, our own opinion is neutral, which means we rely on what our friends tell - - if(info.mFriendsPositiveVotes >= info.mFriendsNegativeVotes + mMinVotesForRemotelyPositive) - info.mOverallReputationLevel = RsReputationLevel::REMOTELY_POSITIVE; - else if(info.mFriendsPositiveVotes + mMinVotesForRemotelyNegative <= info.mFriendsNegativeVotes) - info.mOverallReputationLevel = RsReputationLevel::REMOTELY_NEGATIVE; - else - info.mOverallReputationLevel = RsReputationLevel::NEUTRAL; - -#ifdef DEBUG_REPUTATION2 - std::cerr << " information present. OwnOp = " << info.mOwnOpinion << ", owner node=" << owner_id << ", overall score=" << info.mAssessment << std::endl; -#endif - - return true ; -} - -uint32_t p3GxsReputation::thresholdForRemotelyNegativeReputation() -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - return mMinVotesForRemotelyNegative ; -} -uint32_t p3GxsReputation::thresholdForRemotelyPositiveReputation() -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - return mMinVotesForRemotelyPositive ; -} -void p3GxsReputation::setThresholdForRemotelyPositiveReputation(uint32_t thresh) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - if(mMinVotesForRemotelyPositive == thresh || thresh==0) - return ; - - mMinVotesForRemotelyPositive = thresh ; - IndicateConfigChanged(); -} - -void p3GxsReputation::setThresholdForRemotelyNegativeReputation(uint32_t thresh) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - if(mMinVotesForRemotelyNegative == thresh || thresh==0) - return ; - - mMinVotesForRemotelyNegative = thresh ; - IndicateConfigChanged(); -} - -void p3GxsReputation::banNode(const RsPgpId& id,bool b) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - if(b) - { - if(mBannedPgpIds.find(id) == mBannedPgpIds.end()) - { - mBannedPgpIds[id] = BannedNodeInfo() ; - IndicateConfigChanged(); - } - } - else - { - if(mBannedPgpIds.find(id) != mBannedPgpIds.end()) - { - mBannedPgpIds.erase(id) ; - IndicateConfigChanged(); - } - } -} - -RsReputationLevel p3GxsReputation::overallReputationLevel(const RsGxsId& id) -{ return overallReputationLevel(id, nullptr); } - -bool p3GxsReputation::isNodeBanned(const RsPgpId& id) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - return mBannedPgpIds.find(id) != mBannedPgpIds.end(); -} - -bool p3GxsReputation::isIdentityBanned(const RsGxsId &id) -{ - RsReputationInfo info; - - if(!getReputationInfo(id,RsPgpId(),info)) - return false ; - -#ifdef DEBUG_REPUTATION - std::cerr << "isIdentityBanned(): returning " << (info.mOverallReputationLevel == RsReputations::REPUTATION_LOCALLY_NEGATIVE) << " for GXS id " << id << std::endl; -#endif - return info.mOverallReputationLevel == RsReputationLevel::LOCALLY_NEGATIVE; -} - -bool p3GxsReputation::getOwnOpinion( - const RsGxsId& gxsid, RsOpinion& opinion ) -{ -#ifdef DEBUG_REPUTATION - std::cerr << "setOwnOpinion(): for GXS id " << gxsid << " to " << opinion << std::endl; -#endif - if(gxsid.isNull()) - { - std::cerr << " ID " << gxsid << " is rejected. Look for a bug in calling method." << std::endl; - return false ; - } - - RS_STACK_MUTEX(mReputationMtx); - - std::map::iterator rit = mReputations.find(gxsid); - - if(rit != mReputations.end()) - opinion = safe_convert_uint32t_to_opinion( - static_cast(rit->second.mOwnOpinion) ); - else - opinion = RsOpinion::NEUTRAL; - - return true; -} - -bool p3GxsReputation::setOwnOpinion( - const RsGxsId& gxsid, RsOpinion opinion ) -{ -#ifdef DEBUG_REPUTATION - std::cerr << "setOwnOpinion(): for GXS id " << gxsid << " to " << opinion << std::endl; -#endif - if(gxsid.isNull()) - { - std::cerr << " ID " << gxsid << " is rejected. Look for a bug in calling method." << std::endl; - return false ; - } - - RS_STACK_MUTEX(mReputationMtx); - - std::map::iterator rit; - - /* find matching Reputation */ - rit = mReputations.find(gxsid); - - if (rit == mReputations.end()) - { -#warning csoler 2017-01-05: We should set the owner node id here. - mReputations[gxsid] = Reputation(); - rit = mReputations.find(gxsid); - } - - // we should remove previous entries from Updates... - Reputation &reputation = rit->second; - if (reputation.mOwnOpinionTs != 0) - { - if (reputation.mOwnOpinion == static_cast(opinion)) - { - // if opinion is accurate, don't update. - return false; - } - - std::multimap::iterator uit, euit; - uit = mUpdated.lower_bound(reputation.mOwnOpinionTs); - euit = mUpdated.upper_bound(reputation.mOwnOpinionTs); - for(; uit != euit; ++uit) - { - if (uit->second == gxsid) - { - mUpdated.erase(uit); - break; - } - } - } - - rstime_t now = time(nullptr); - reputation.mOwnOpinion = static_cast(opinion); - reputation.mOwnOpinionTs = now; - reputation.updateReputation(); - - mUpdated.insert(std::make_pair(now, gxsid)); - mReputationsUpdated = true; - mLastBannedNodesUpdate = 0 ; // for update of banned nodes - - // Switched to periodic save due to scale of data. - IndicateConfigChanged(); - - return true; -} - - -/******************************************************************** - * Configuration. - ****/ - -RsSerialiser *p3GxsReputation::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsGxsReputationSerialiser()); - rss->addSerialType(new RsGeneralConfigSerialiser()); - return rss ; -} - -bool p3GxsReputation::saveList(bool& cleanup, std::list &savelist) -{ - cleanup = true; - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::saveList()" << std::endl; -#endif - - /* save */ - std::map::iterator it; - for(it = mConfig.begin(); it != mConfig.end(); ++it) - { - if (!rsPeers->isFriend(it->first)) - { - // discard info from non-friends. - continue; - } - - RsGxsReputationConfigItem *item = new RsGxsReputationConfigItem(); - item->mPeerId = it->first; - item->mLatestUpdate = it->second.mLatestUpdate; - item->mLastQuery = it->second.mLastQuery; - savelist.push_back(item); - } - - int count = 0; - std::map::iterator rit; - for(rit = mReputations.begin(); rit != mReputations.end(); ++rit, count++) - { - RsGxsReputationSetItem *item = new RsGxsReputationSetItem(); - item->mGxsId = rit->first; - item->mOwnOpinion = rit->second.mOwnOpinion; - item->mOwnOpinionTS = rit->second.mOwnOpinionTs; - item->mIdentityFlags = rit->second.mIdentityFlags; - item->mOwnerNodeId = rit->second.mOwnerNode; - item->mLastUsedTS = rit->second.mLastUsedTS; - - std::map::iterator oit; - for(oit = rit->second.mOpinions.begin(); oit != rit->second.mOpinions.end(); ++oit) - { - // should be already limited. - item->mOpinions[oit->first] = (uint32_t)oit->second; - } - - savelist.push_back(item); - count++; - } - - for(std::map::const_iterator it(mBannedPgpIds.begin());it!=mBannedPgpIds.end();++it) - { - RsGxsReputationBannedNodeSetItem *item = new RsGxsReputationBannedNodeSetItem(); - - item->mPgpId = it->first ; - item->mLastActivityTS = it->second.last_activity_TS; - item->mKnownIdentities.ids = it->second.known_identities; - - savelist.push_back(item) ; - } - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - - kv.key = "AUTO_REMOTELY_POSITIVE_THRESHOLD" ; - rs_sprintf(kv.value, "%d", mMinVotesForRemotelyPositive); - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "AUTO_REMOTELY_NEGATIVE_THRESHOLD" ; - rs_sprintf(kv.value, "%d", mMinVotesForRemotelyNegative); - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "AUTO_POSITIVE_CONTACTS" ; - kv.value = mAutoSetPositiveOptionToContacts?"YES":"NO"; - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "MAX_PREVENT_RELOAD_BANNED_IDS" ; - rs_sprintf(kv.value, "%d", mMaxPreventReloadBannedIds) ; - vitem->tlvkvs.pairs.push_back(kv) ; - - savelist.push_back(vitem) ; - - return true; -} - -void p3GxsReputation::saveDone() -{ - return; -} - -bool p3GxsReputation::loadList(std::list& loadList) -{ -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::loadList()" << std::endl; -#endif - std::list::iterator it; - std::set peerSet; - - for(it = loadList.begin(); it != loadList.end(); ++it) - { - RsGxsReputationConfigItem *item = dynamic_cast(*it); - - // Configurations are loaded first. (to establish peerSet). - if (item) - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - RsPeerId peerId(item->mPeerId); - ReputationConfig &config = mConfig[peerId]; - config.mPeerId = peerId; - config.mLatestUpdate = item->mLatestUpdate; - config.mLastQuery = 0; - - peerSet.insert(peerId); - } - - RsGxsReputationSetItem *set = dynamic_cast(*it); - - if (set) - loadReputationSet(set, peerSet); - -#ifdef TO_REMOVE - RsGxsReputationSetItem_deprecated3 *set2 = dynamic_cast(*it); - - if(set2) - { - std::cerr << "(II) reading and converting old format ReputationSetItem." << std::endl; - loadReputationSet_deprecated3(set2, peerSet); - } -#endif - - RsGxsReputationBannedNodeSetItem *itm2 = dynamic_cast(*it) ; - - if(itm2 != NULL) - { - BannedNodeInfo& info(mBannedPgpIds[itm2->mPgpId]) ; - info.last_activity_TS = itm2->mLastActivityTS ; - info.known_identities = itm2->mKnownIdentities.ids ; - } - - RsConfigKeyValueSet *vitem = dynamic_cast(*it); - - if(vitem) - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if(kit->key == "AUTO_REMOTELY_POSITIVE_THRESHOLD") - { - int val ; - if (sscanf(kit->value.c_str(), "%d", &val) == 1) - { - mMinVotesForRemotelyPositive = val ; - std::cerr << "Setting mMinVotesForRemotelyPositive threshold to " << val << std::endl ; - } - }; - if(kit->key == "AUTO_REMOTELY_NEGATIVE_THRESHOLD") - { - int val ; - if (sscanf(kit->value.c_str(), "%d", &val) == 1) - { - mMinVotesForRemotelyNegative = val ; - std::cerr << "Setting mMinVotesForRemotelyNegative threshold to " << val << std::endl ; - } - }; - if(kit->key == "AUTO_POSITIVE_CONTACTS") - { - mAutoSetPositiveOptionToContacts = (kit->value == "YES"); - std::cerr << "Setting AutoPositiveContacts to " << kit->value << std::endl ; - mLastBannedNodesUpdate = 0 ; // force update - } - if(kit->key == "MAX_PREVENT_RELOAD_BANNED_IDS" ) - { - int val ; - if (sscanf(kit->value.c_str(), "%d", &val) == 1) - { - mMaxPreventReloadBannedIds = val ; - std::cerr << "Setting mMaxPreventReloadBannedIds threshold to " << val << std::endl ; - } - } - } - - delete (*it); - } - - updateBannedNodesProxy(); - loadList.clear() ; - return true; -} -#ifdef TO_REMOVE -bool p3GxsReputation::loadReputationSet_deprecated3(RsGxsReputationSetItem_deprecated3 *item, const std::set &peerSet) -{ - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator rit; - - if(item->mGxsId.isNull()) // just a protection against potential errors having put 00000 into ids. - return false ; - - /* find matching Reputation */ - RsGxsId gxsId(item->mGxsId); - rit = mReputations.find(gxsId); - if (rit != mReputations.end()) - { - std::cerr << "ERROR"; - std::cerr << std::endl; - } - - Reputation &reputation = mReputations[gxsId]; - - // install opinions. - std::map::const_iterator oit; - for(oit = item->mOpinions.begin(); oit != item->mOpinions.end(); ++oit) - { - // expensive ... but necessary. - RsPeerId peerId(oit->first); - if (peerSet.end() != peerSet.find(peerId)) - reputation.mOpinions[peerId] = safe_convert_uint32t_to_opinion(oit->second); - } - - reputation.mOwnOpinion = item->mOwnOpinion; - reputation.mOwnOpinionTs = item->mOwnOpinionTS; - reputation.mOwnerNode = item->mOwnerNodeId; - reputation.mIdentityFlags = item->mIdentityFlags & (~REPUTATION_IDENTITY_FLAG_UP_TO_DATE); - reputation.mLastUsedTS = time(NULL); - - // if dropping entries has changed the score -> must update. - - reputation.updateReputation() ; - - mUpdated.insert(std::make_pair(reputation.mOwnOpinionTs, gxsId)); - } -#ifdef DEBUG_REPUTATION - RsReputations::ReputationInfo info ; - getReputationInfo(item->mGxsId,item->mOwnerNodeId,info) ; - std::cerr << item->mGxsId << " : own: " << info.mOwnOpinion << ", owner node: " << item->mOwnerNodeId << ", overall level: " << info.mOverallReputationLevel << std::endl; -#endif - return true; -} -#endif - -bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std::set &peerSet) -{ - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator rit; - - if(item->mGxsId.isNull()) // just a protection against potential errors having put 00000 into ids. - return false ; - - /* find matching Reputation */ - RsGxsId gxsId(item->mGxsId); - rit = mReputations.find(gxsId); - if (rit != mReputations.end()) - { - std::cerr << "ERROR"; - std::cerr << std::endl; - } - - Reputation &reputation = mReputations[gxsId]; - - // install opinions. - std::map::const_iterator oit; - for(oit = item->mOpinions.begin(); oit != item->mOpinions.end(); ++oit) - { - // expensive ... but necessary. - RsPeerId peerId(oit->first); - if (peerSet.end() != peerSet.find(peerId)) - reputation.mOpinions[peerId] = safe_convert_uint32t_to_opinion(oit->second); - } - - reputation.mOwnOpinion = item->mOwnOpinion; - reputation.mOwnOpinionTs = item->mOwnOpinionTS; - reputation.mOwnerNode = item->mOwnerNodeId; - reputation.mIdentityFlags = item->mIdentityFlags; - reputation.mLastUsedTS = item->mLastUsedTS; - - // if dropping entries has changed the score -> must update. - - reputation.updateReputation() ; - - mUpdated.insert(std::make_pair(reputation.mOwnOpinionTs, gxsId)); - } -#ifdef DEBUG_REPUTATION - RsReputations::ReputationInfo info ; - getReputationInfo(item->mGxsId,item->mOwnerNodeId,info,false) ; - std::cerr << item->mGxsId << " : own: " << info.mOwnOpinion << ", owner node: " << item->mOwnerNodeId << ", level: " << info.mOverallReputationLevel << std::endl; -#endif - return true; -} - - -/******************************************************************** - * Send Requests. - ****/ - -int p3GxsReputation::sendPackets() -{ - rstime_t now = time(NULL); - rstime_t requestTime, storeTime; - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - requestTime = mRequestTime; - storeTime = mStoreTime; - } - - if (now > requestTime + kReputationRequestPeriod) - { - sendReputationRequests(); - - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::sendPackets() Regular Broadcast"; - std::cerr << std::endl; -#endif - mRequestTime = now; - mStoreTime = now + kReputationStoreWait; - } - - if (now > storeTime) - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::sendPackets() Regular Broadcast"; - std::cerr << std::endl; -#endif - // push it into the future. - // store time will be reset when requests are send. - mStoreTime = now + kReputationRequestPeriod; - - if (mReputationsUpdated) - { - IndicateConfigChanged(); - mReputationsUpdated = false; - } - } - - return true ; -} - -void p3GxsReputation::sendReputationRequests() -{ - /* we ping our peers */ - /* who is online? */ - std::list idList; - - mLinkMgr->getOnlineList(idList); - - /* prepare packets */ - std::list::iterator it; - for(it = idList.begin(); it != idList.end(); ++it) - sendReputationRequest(*it); -} - -int p3GxsReputation::sendReputationRequest(RsPeerId peerid) -{ -#ifdef DEBUG_REPUTATION - rstime_t now = time(NULL) ; - std::cerr << " p3GxsReputation::sendReputationRequest(" << peerid << ") " ; -#endif - - /* */ - RsGxsReputationRequestItem *requestItem = new RsGxsReputationRequestItem(); - requestItem->PeerId(peerid); - - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - /* find the last timestamp we have */ - std::map::iterator it = mConfig.find(peerid); - - if (it != mConfig.end()) - { -#ifdef DEBUG_REPUTATION - std::cerr << " lastUpdate = " << now - it->second.mLatestUpdate << " secs ago. Requesting only more recent." << std::endl; -#endif - requestItem->mLastUpdate = it->second.mLatestUpdate; - } - else - { -#ifdef DEBUG_REPUTATION - std::cerr << " lastUpdate = never. Requesting all!" << std::endl; -#endif - // get whole list. - requestItem->mLastUpdate = 0; - } - } - - sendItem(requestItem); - return 1; -} - -void Reputation::updateReputation() -{ - // the calculation of reputation makes the whole thing - - int friend_total = 0; - - mFriendsNegative = 0 ; - mFriendsPositive = 0 ; - - // accounts for all friends. Neutral opinions count for 1-1=0 - // because the average is performed over only accessible peers (not the total number) we need to shift to 1 - - for( std::map::const_iterator it(mOpinions.begin()); - it != mOpinions.end(); ++it ) - { - if( it->second == RsOpinion::NEGATIVE) - ++mFriendsNegative ; - - if( it->second == RsOpinion::POSITIVE) - ++mFriendsPositive ; - - friend_total += static_cast(it->second) - 1; - } - - if(mOpinions.empty()) // includes the case of no friends! - mFriendAverage = 1.0f ; - else - { - static const float REPUTATION_FRIEND_FACTOR_ANON = 2.0f ; - static const float REPUTATION_FRIEND_FACTOR_PGP_LINKED = 5.0f ; - static const float REPUTATION_FRIEND_FACTOR_PGP_KNOWN = 10.0f ; - - // For positive votes, start from 1 and slowly tend to 2 - // for negative votes, start from 1 and slowly tend to 0 - // depending on signature state, the ID is harder (signed ids) or easier (anon ids) to ban or to promote. - // - // when REPUTATION_FRIEND_VARIANCE = 3, that gives the following values: - // - // total votes | mFriendAverage anon | mFriendAverage PgpLinked | mFriendAverage PgpKnown | - // | F=2.0 | F=5.0 | F=10.0 | - // -------------+----------------------+---------------------------+--------------------------+ - // -10 | 0.00 Banned | 0.13 Banned | 0.36 Banned | - // -5 | 0.08 Banned | 0.36 Banned | 0.60 | - // -4 | 0.13 Banned | 0.44 Banned | 0.67 | - // -3 | 0.22 Banned | 0.54 | 0.74 | - // -2 | 0.36 Banned | 0.67 | 0.81 | - // -1 | 0.60 | 0.81 | 0.90 | - // 0 | 1.0 | 1.0 | 1.00 | - // 1 | 1.39 | 1.18 | 1.09 | - // 2 | 1.63 | 1.32 | 1.18 | - // 3 | 1.77 | 1.45 | 1.25 | - // 4 | 1.86 | 1.55 | 1.32 | - // 5 | 1.91 | 1.63 | 1.39 | - // - // Banning info is provided by the reputation system, and does not depend on PGP-sign state. - // - // However, each service might have its own rules for the different cases. For instance - // PGP-favoring forums might want a score > 1.4 for anon ids, and >= 1.0 for PGP-signed. - - float reputation_bias ; - - if(mIdentityFlags & REPUTATION_IDENTITY_FLAG_PGP_KNOWN) - reputation_bias = REPUTATION_FRIEND_FACTOR_PGP_KNOWN ; - else if(mIdentityFlags & REPUTATION_IDENTITY_FLAG_PGP_LINKED) - reputation_bias = REPUTATION_FRIEND_FACTOR_PGP_LINKED ; - else - reputation_bias = REPUTATION_FRIEND_FACTOR_ANON ; - - if(friend_total > 0) - mFriendAverage = 2.0f-exp(-friend_total / reputation_bias) ; - else - mFriendAverage = exp( friend_total / reputation_bias) ; - } - - // now compute a bias for PGP-signed ids. - - if(mOwnOpinion == static_cast(RsOpinion::NEUTRAL)) - mReputationScore = mFriendAverage; - else mReputationScore = static_cast(mOwnOpinion); -} - -void p3GxsReputation::debug_print() -{ - std::cerr << "Reputations database: " << std::endl; - std::cerr << " GXS ID data: " << std::endl; - std::cerr << std::dec ; - - std::map rep_copy; - - { - RS_STACK_MUTEX(mReputationMtx); - rep_copy = mReputations; - } - - rstime_t now = time(nullptr); - - - for( std::map::const_iterator it(rep_copy.begin()); - it != rep_copy.end(); ++it ) - { - RsReputationInfo info; - getReputationInfo(it->first, RsPgpId(), info, false); - uint32_t lev = static_cast(info.mOverallReputationLevel); - - std::cerr << " " << it->first << ": own: " << it->second.mOwnOpinion - << ", PGP id=" << it->second.mOwnerNode - << ", flags=" << std::setfill('0') << std::setw(4) << std::hex << it->second.mIdentityFlags << std::dec - << ", Friend pos/neg: " << it->second.mFriendsPositive << "/" << it->second.mFriendsNegative - << ", reputation lev: [" << lev - << "], last own update: " << std::setfill(' ') << std::setw(10) << now - it->second.mOwnOpinionTs << " secs ago" - << ", last needed: " << std::setfill(' ') << std::setw(10) << now - it->second.mLastUsedTS << " secs ago, " - << std::endl; - -#ifdef DEBUG_REPUTATION2 - for(std::map::const_iterator it2(it->second.mOpinions.begin());it2!=it->second.mOpinions.end();++it2) - std::cerr << " " << it2->first << ": " << it2->second << std::endl; -#endif - } - - RS_STACK_MUTEX(mReputationMtx); - std::cerr << " Banned RS nodes by ID: " << std::endl; - - for(std::map::const_iterator it(mBannedPgpIds.begin());it!=mBannedPgpIds.end();++it) - { - std::cerr << " Node " << it->first << ", last activity: " << now - it->second.last_activity_TS << " secs ago." << std::endl; - - for(std::set::const_iterator it2(it->second.known_identities.begin());it2!=it->second.known_identities.end();++it2) - std::cerr << " " << *it2 << std::endl; - } - - std::cerr << " Per node Banned GXSIds proxy: " << std::endl; - - for(std::set::const_iterator it(mPerNodeBannedIdsProxy.begin());it!=mPerNodeBannedIdsProxy.end();++it) - std::cerr << " " << *it << std::endl; -} - diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h deleted file mode 100644 index 2045e6f05..000000000 --- a/libretroshare/src/services/p3gxsreputation.h +++ /dev/null @@ -1,204 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxsreputation.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014-2014 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef SERVICE_RSGXSREPUTATION_HEADER -#define SERVICE_RSGXSREPUTATION_HEADER - -#include -#include -#include -#include - -static const uint32_t REPUTATION_IDENTITY_FLAG_UP_TO_DATE = 0x0100; // This flag means that the static info has been initialised from p3IdService. Normally such a call should happen once. -static const uint32_t REPUTATION_IDENTITY_FLAG_PGP_LINKED = 0x0001; -static const uint32_t REPUTATION_IDENTITY_FLAG_PGP_KNOWN = 0x0002; - -#include "rsitems/rsgxsreputationitems.h" - -#include "retroshare/rsidentity.h" -#include "retroshare/rsreputations.h" -#include "gxs/rsgixs.h" -#include "services/p3service.h" - - -class p3LinkMgr; - -class ReputationConfig -{ -public: - ReputationConfig() - :mPeerId(), mLatestUpdate(0), mLastQuery(0) { return; } - - ReputationConfig(const RsPeerId& peerId) - :mPeerId(peerId), mLatestUpdate(0), mLastQuery(0) { return; } - - RsPeerId mPeerId; - rstime_t mLatestUpdate; - rstime_t mLastQuery; -}; - -struct BannedNodeInfo -{ - rstime_t last_activity_TS ; // updated everytime a node or one of its former identities is required - std::set known_identities ; // list of known identities from this node. This is kept for a while, and useful in order to avoid re-asking these keys. -}; - -class Reputation -{ -public: - Reputation() : - mOwnOpinion(static_cast(RsOpinion::NEUTRAL)), - mOwnOpinionTs(0), - mFriendAverage(1.0f), - mFriendsPositive(0), - mFriendsNegative(0), - mReputationScore(1.0f), - mIdentityFlags(0), - mLastUsedTS(0) {} - - void updateReputation(); - - std::map mOpinions; - int32_t mOwnOpinion; - rstime_t mOwnOpinionTs; - - float mFriendAverage ; - uint32_t mFriendsPositive ; // number of positive vites from friends - uint32_t mFriendsNegative ; // number of negative vites from friends - - float mReputationScore; - - RsPgpId mOwnerNode; - - uint32_t mIdentityFlags; - - rstime_t mLastUsedTS ; // last time the reputation was asked. Used to keep track of activity and clean up some reputation data. -}; - - -//!The p3GxsReputation service. -class p3GxsReputation: public p3Service, public p3Config, public RsGixsReputation, public RsReputations /* , public pqiMonitor */ -{ -public: - p3GxsReputation(p3LinkMgr *lm); - virtual RsServiceInfo getServiceInfo(); - - /***** Interface for RsReputations *****/ - virtual bool setOwnOpinion(const RsGxsId& key_id, RsOpinion op); - virtual bool getOwnOpinion(const RsGxsId& key_id, RsOpinion& op) ; - virtual bool getReputationInfo( - const RsGxsId& id, const RsPgpId& ownerNode, RsReputationInfo& info, - bool stamp = true ); - virtual bool isIdentityBanned(const RsGxsId& id) ; - - virtual bool isNodeBanned(const RsPgpId& id); - virtual void banNode(const RsPgpId& id,bool b) ; - - RsReputationLevel overallReputationLevel(const RsGxsId& id) override; - - virtual RsReputationLevel overallReputationLevel( - const RsGxsId& id, uint32_t* identity_flags ); - - virtual void setAutoPositiveOpinionForContacts(bool b) ; - virtual bool autoPositiveOpinionForContacts() ; - - virtual void setRememberBannedIdThreshold(uint32_t days) ; - virtual uint32_t rememberBannedIdThreshold() ; - - uint32_t thresholdForRemotelyNegativeReputation(); - uint32_t thresholdForRemotelyPositiveReputation(); - void setThresholdForRemotelyNegativeReputation(uint32_t thresh); - void setThresholdForRemotelyPositiveReputation(uint32_t thresh); - - /***** overloaded from p3Service *****/ - virtual int tick(); - virtual int status(); - - /*! - * Interface stuff. - */ - - /************* from p3Config *******************/ - virtual RsSerialiser *setupSerialiser() ; - virtual bool saveList(bool& cleanup, std::list&) ; - virtual void saveDone(); - virtual bool loadList(std::list& load) ; - -private: - bool getIdentityFlagsAndOwnerId(const RsGxsId& gxsid, uint32_t& identity_flags, RsPgpId &owner_id); - - bool processIncoming(); - - bool SendReputations(RsGxsReputationRequestItem *request); - bool RecvReputations(RsGxsReputationUpdateItem *item); - bool updateLatestUpdate(RsPeerId peerid, rstime_t latest_update); - - void updateBannedNodesProxy(); - - // internal update of data. Takes care of cleaning empty boxes. - void locked_updateOpinion( - const RsPeerId& from, const RsGxsId& about, RsOpinion op); - bool loadReputationSet(RsGxsReputationSetItem *item, const std::set &peerSet); -#ifdef TO_REMOVE - bool loadReputationSet_deprecated3(RsGxsReputationSetItem_deprecated3 *item, const std::set &peerSet); -#endif - int sendPackets(); - void cleanup(); - void sendReputationRequests(); - int sendReputationRequest(RsPeerId peerid); - void debug_print() ; - void updateStaticIdentityFlags(); - -private: - RsMutex mReputationMtx; - - rstime_t mLastCleanUp; - rstime_t mRequestTime; - rstime_t mStoreTime; - rstime_t mLastBannedNodesUpdate ; - rstime_t mLastIdentityFlagsUpdate ; - bool mReputationsUpdated; - - //float mAutoBanIdentitiesLimit ; - bool mAutoSetPositiveOptionToContacts; - - p3LinkMgr *mLinkMgr; - - // Data for Reputation. - std::map mConfig; - std::map mReputations; - std::multimap mUpdated; - - // PGP Ids auto-banned. This is updated regularly. - std::map mBannedPgpIds ; - std::set mPerNodeBannedIdsProxy ; - bool mBannedNodesProxyNeedsUpdate ; - - uint32_t mMinVotesForRemotelyPositive ; - uint32_t mMinVotesForRemotelyNegative ; - uint32_t mMaxPreventReloadBannedIds ; - - bool mChanged ; // slow version of IndicateConfigChanged(); - rstime_t mLastReputationConfigSaved ; -}; - -#endif //SERVICE_RSGXSREPUTATION_HEADER - diff --git a/libretroshare/src/services/p3heartbeat.cc b/libretroshare/src/services/p3heartbeat.cc deleted file mode 100644 index 38426a454..000000000 --- a/libretroshare/src/services/p3heartbeat.cc +++ /dev/null @@ -1,143 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3heartbeat.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "util/rstime.h" - -#include "services/p3heartbeat.h" -#include "rsitems/rsheartbeatitems.h" - -#include "pqi/p3servicecontrol.h" -#include "pqi/pqipersongrp.h" - -//#define HEART_DEBUG 1 - - -p3heartbeat::p3heartbeat(p3ServiceControl *sc, pqipersongrp *pqipg) -:p3Service(), mServiceCtrl(sc), mPqiPersonGrp(pqipg), - mHeartMtx("p3heartbeat") -{ - RsStackMutex stack(mHeartMtx); /********** STACK LOCKED MTX ******/ - - addSerialType(new RsHeartbeatSerialiser()); - -#ifdef HEART_DEBUG - std::cerr << "p3heartbeat::p3heartbeat()"; - std::cerr << std::endl; -#endif - - mLastHeartbeat = 0; - - return; -} - -p3heartbeat::~p3heartbeat() -{ - return; - -} - - -const std::string HEARTBEAT_APP_NAME = "heartbeat"; -const uint16_t HEARTBEAT_APP_MAJOR_VERSION = 1; -const uint16_t HEARTBEAT_APP_MINOR_VERSION = 0; -const uint16_t HEARTBEAT_MIN_MAJOR_VERSION = 1; -const uint16_t HEARTBEAT_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3heartbeat::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_HEARTBEAT, - HEARTBEAT_APP_NAME, - HEARTBEAT_APP_MAJOR_VERSION, - HEARTBEAT_APP_MINOR_VERSION, - HEARTBEAT_MIN_MAJOR_VERSION, - HEARTBEAT_MIN_MINOR_VERSION); -} - - -int p3heartbeat::tick() -{ - //send a heartbeat to all connected peers - RsStackMutex stack(mHeartMtx); /********** STACK LOCKED MTX ******/ - - if (time(NULL) - mLastHeartbeat > HEARTBEAT_REPEAT_TIME) - { - mLastHeartbeat = time(NULL); - - std::set peers; - std::set::const_iterator pit; - - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, peers); - for (pit = peers.begin(); pit != peers.end(); ++pit) - { - sendHeartbeat(*pit); - } - } - - int nhandled = 0; - RsItem *item = NULL; - - // While messages read - while(NULL != (item = recvItem())) - { - RsHeartbeatItem *beat = NULL; - nhandled++; - - // if discovery reply then respond if haven't already. - if (NULL != (beat = dynamic_cast (item))) - { - recvHeartbeat(beat->PeerId()); - } - else - { - // unknown. - } - - delete item; - } - - return nhandled ; -} - -void p3heartbeat::sendHeartbeat(const RsPeerId &toId) -{ - -#ifdef HEART_DEBUG - std::cerr << "p3heartbeat::sendHeartbeat() to " << toId; - std::cerr << std::endl; -#endif - RsHeartbeatItem *item = new RsHeartbeatItem(); - item->PeerId(toId); - sendItem(item); -} - - -void p3heartbeat::recvHeartbeat(const RsPeerId &fromId) -{ - -#ifdef HEART_DEBUG - std::cerr << "p3heartbeat::recvHeartbeat() from " << fromId; - std::cerr << std::endl; -#endif - - mPqiPersonGrp->tagHeartbeatRecvd(fromId); -} - - diff --git a/libretroshare/src/services/p3heartbeat.h b/libretroshare/src/services/p3heartbeat.h deleted file mode 100644 index 6dd9f6e5b..000000000 --- a/libretroshare/src/services/p3heartbeat.h +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3heartbeat.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MRK_SERVICES_HEARTBEAT_H -#define MRK_SERVICES_HEARTBEAT_H - -// Moved Heartbeat to a seperate service. - -#include "services/p3service.h" - -class p3ServiceControl; -class pqipersongrp; - -class p3heartbeat: public p3Service -{ - public: - - p3heartbeat(p3ServiceControl *sc, pqipersongrp *pqipg); -virtual ~p3heartbeat(); - -virtual RsServiceInfo getServiceInfo(); - - int tick(); - - private: - - void sendHeartbeat(const RsPeerId &toId); - void recvHeartbeat(const RsPeerId &fromId); - - private: - - p3ServiceControl *mServiceCtrl; - pqipersongrp *mPqiPersonGrp; - - /* data */ - RsMutex mHeartMtx; - - rstime_t mLastHeartbeat; -}; - -#endif // MRK_SERVICES_HEARTBEAT_H diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc deleted file mode 100644 index d35d3afe0..000000000 --- a/libretroshare/src/services/p3idservice.cc +++ /dev/null @@ -1,5002 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3idservice.cc * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2017-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -/// RetroShare GXS identities service - - -#include -#include -#include -#include - -#include "services/p3idservice.h" -#include "pgp/pgpauxutils.h" -#include "rsitems/rsgxsiditems.h" -#include "rsitems/rsconfigitems.h" -#include "retroshare/rsgxsflags.h" -#include "util/rsrandom.h" -#include "util/rsstring.h" -#include "util/radix64.h" -#include "util/rsdir.h" -#include "util/rstime.h" -#include "crypto/hashstream.h" -#include "gxs/gxssecurity.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsnotify.h" - - -/**** - * #define DEBUG_IDS 1 - * #define DEBUG_RECOGN 1 - * #define DEBUG_OPINION 1 - * #define DEBUG_SERVICE_STRING 1 - * #define GXSID_GEN_DUMMY_DATA 1 - ****/ - -#define ID_REQUEST_LIST 0x0001 -#define ID_REQUEST_IDENTITY 0x0002 -#define ID_REQUEST_REPUTATION 0x0003 -#define ID_REQUEST_OPINION 0x0004 - -#define GXSID_MAX_CACHE_SIZE 15000 - -// unused keys are deleted according to some heuristic that should favor known keys, signed keys etc. - -static const rstime_t MAX_KEEP_KEYS_BANNED_DEFAULT = 2 * 86400 ; // get rid of banned ids after 1 days. That gives a chance to un-ban someone before he gets definitely kicked out - -static const rstime_t MAX_KEEP_KEYS_DEFAULT = 5 * 86400 ; // default for unsigned identities: 5 days -static const rstime_t MAX_KEEP_KEYS_SIGNED = 8 * 86400 ; // signed identities by unknown key -static const rstime_t MAX_KEEP_KEYS_SIGNED_KNOWN = 30 * 86400 ; // signed identities by known node keys - -static const uint32_t MAX_DELAY_BEFORE_CLEANING= 1800 ; // clean old keys every 30 mins - -static const uint32_t MAX_SERIALISED_IDENTITY_AGE = 600 ; // after 10 mins, a serialised identity record must be renewed. - -RsIdentity* rsIdentity = nullptr; - -/****** - * Some notes: - * Identity tasks: - * - Provide keys for signing / validating author signatures. - * - Reputations - * - Identify Known Friend's IDs. - * - Provide details to other services (nicknames, reputations, gpg ids, etc) - * - * Background services: - * - Lookup and cache keys / details of identities. - * - Check GPGHashes. - * - Calculate Reputations. - * - * We have a lot of information to store in Service Strings. - * - GPGId or last check ts. - * - Reputation stuff. - */ - -#define RSGXSID_MAX_SERVICE_STRING 1024 - -#define BG_PGPHASH 1 -#define BG_RECOGN 2 -#define BG_REPUTATION 3 - - -#define GXSIDREQ_CACHELOAD 0x0001 -#define GXSIDREQ_CACHEOWNIDS 0x0002 -#define GXSIDREQ_PGPHASH 0x0010 -#define GXSIDREQ_RECOGN 0x0020 -#define GXSIDREQ_OPINION 0x0030 -#define GXSIDREQ_SERIALIZE_TO_MEMORY 0x0040 -#define GXSIDREQ_LOAD_PGPIDDATA 0x0080 - -#define GXSIDREQ_CACHETEST 0x1000 - -// Events. -#define GXSID_EVENT_CACHEOWNIDS 0x0001 -#define GXSID_EVENT_CACHELOAD 0x0002 - -#define GXSID_EVENT_PGPHASH 0x0010 -#define GXSID_EVENT_PGPHASH_PROC 0x0011 - -#define GXSID_EVENT_RECOGN 0x0020 -#define GXSID_EVENT_RECOGN_PROC 0x0021 - -#define GXSID_EVENT_REPUTATION 0x0030 - -#define GXSID_EVENT_CACHETEST 0x1000 - -#define GXSID_EVENT_DUMMYDATA 0x2000 -#define GXSID_EVENT_DUMMY_OWNIDS 0x2001 -#define GXSID_EVENT_DUMMY_PGPID 0x2002 -#define GXSID_EVENT_DUMMY_UNKNOWN_PGPID 0x2003 -#define GXSID_EVENT_DUMMY_PSEUDOID 0x2004 -#define GXSID_EVENT_REQUEST_IDS 0x2005 - - -/* delays */ - -#define CACHETEST_PERIOD 60 -#define DELAY_BETWEEN_CONFIG_UPDATES 300 -#define GXS_MAX_KEY_TS_USAGE_MAP_SIZE 5 - -#define OWNID_RELOAD_DELAY 10 - -#define PGPHASH_PERIOD 60 -#define PGPHASH_RETRY_PERIOD 11 -#define PGPHASH_PROC_PERIOD 1 - -#define RECOGN_PERIOD 90 -#define RECOGN_RETRY_PERIOD 17 -#define RECOGN_PROC_PERIOD 1 - -#define REPUTATION_PERIOD 60 -#define REPUTATION_RETRY_PERIOD 13 -#define REPUTATION_PROC_PERIOD 1 - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3IdService::p3IdService( RsGeneralDataService *gds - , RsNetworkExchangeService *nes - , PgpAuxUtils *pgpUtils ) - : RsGxsIdExchange( gds, nes, new RsGxsIdSerialiser(), - RS_SERVICE_GXS_TYPE_GXSID, idAuthenPolicy() ) - , RsIdentity(static_cast(*this)) - , GxsTokenQueue(this), RsTickEvent(), p3Config() - , mKeyCache(GXSID_MAX_CACHE_SIZE, "GxsIdKeyCache") - , mBgSchedule_Active(false), mBgSchedule_Mode(0) - , mIdMtx("p3IdService"), mNes(nes), mPgpUtils(pgpUtils) - , mLastConfigUpdate(0), mOwnIdsLoaded(false) - , mAutoAddFriendsIdentitiesAsContacts(true) /*default*/ - , mMaxKeepKeysBanned(MAX_KEEP_KEYS_BANNED_DEFAULT) -{ - mLastKeyCleaningTime = time(NULL) - int(MAX_DELAY_BEFORE_CLEANING * 0.9) ; - mLastPGPHashProcessTime = 0; - - // Kick off Cache Testing, + Others. - RsTickEvent::schedule_now(GXSID_EVENT_CACHEOWNIDS);//First Thing to do - RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH, PGPHASH_PERIOD); - RsTickEvent::schedule_in(GXSID_EVENT_REPUTATION, REPUTATION_PERIOD); - - //RsTickEvent::schedule_in(GXSID_EVENT_CACHETEST, CACHETEST_PERIOD); - -#ifdef GXSID_GEN_DUMMY_DATA - //RsTickEvent::schedule_now(GXSID_EVENT_DUMMYDATA); -#endif - - loadRecognKeys(); -} - -const std::string GXSID_APP_NAME = "gxsid"; -const uint16_t GXSID_APP_MAJOR_VERSION = 1; -const uint16_t GXSID_APP_MINOR_VERSION = 0; -const uint16_t GXSID_MIN_MAJOR_VERSION = 1; -const uint16_t GXSID_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3IdService::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_GXSID, - GXSID_APP_NAME, - GXSID_APP_MAJOR_VERSION, - GXSID_APP_MINOR_VERSION, - GXSID_MIN_MAJOR_VERSION, - GXSID_MIN_MINOR_VERSION); -} - - - -void p3IdService::setNes(RsNetworkExchangeService *nes) -{ - RsStackMutex stack(mIdMtx); - mNes = nes; -} - -bool p3IdService::getIdentitiesInfo( - const std::set& ids, std::vector& idsInfo ) -{ - uint32_t token; - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - std::list idsList; - for (auto&& id : ids) idsList.push_back(RsGxsGroupId(id)); - - if( !requestGroupInfo(token, opts, idsList) - || waitToken(token) != RsTokenService::COMPLETE ) return false; - return getGroupData(token, idsInfo); -} - -bool p3IdService::getIdentitiesSummaries(std::list& ids) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - if( !requestGroupInfo(token, opts) - || waitToken(token) != RsTokenService::COMPLETE ) return false; - return getGroupSummary(token, ids); -} - -uint32_t p3IdService::idAuthenPolicy() -{ - uint32_t policy = 0; - uint8_t flag = 0; - - // Messages are send reputations. normally not by ID holder - so need signatures. - flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - // No ID required. - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -uint32_t p3IdService::nbRegularContacts() -{ - RsStackMutex stack(mIdMtx); - return mContacts.size(); -} - -bool p3IdService::isARegularContact(const RsGxsId& id) -{ - RsStackMutex stack(mIdMtx); - return mContacts.find(id) != mContacts.end() ; -} - -bool p3IdService::receiveNewIdentity(RsNxsGrp *identity_grp) -{ - receiveNewGroups(std::vector{ identity_grp }); - return true; -} - -bool p3IdService::retrieveNxsIdentity(const RsGxsId& group_id,RsNxsGrp *& identity_grp) -{ - return RsGenExchange::retrieveNxsIdentity(RsGxsGroupId(group_id),identity_grp); -} - -bool p3IdService::setAsRegularContact(const RsGxsId& id,bool b) -{ - RsStackMutex stack(mIdMtx); - std::set::iterator it = mContacts.find(id) ; - - if(b && (it == mContacts.end())) - { - mContacts.insert(id) ; - slowIndicateConfigChanged() ; - } - - if( (!b) &&(it != mContacts.end())) - { - mContacts.erase(it) ; - slowIndicateConfigChanged() ; - } - - return true ; -} - -void p3IdService::slowIndicateConfigChanged() -{ - rstime_t now = time(NULL) ; - - if(mLastConfigUpdate + DELAY_BETWEEN_CONFIG_UPDATES < now) - { - IndicateConfigChanged() ; - mLastConfigUpdate = now ; - } -} -rstime_t p3IdService::locked_getLastUsageTS(const RsGxsId& gxs_id) -{ - std::map::const_iterator it = mKeysTS.find(gxs_id) ; - - if(it == mKeysTS.end()) - return 0 ; - else - return it->second.TS ; -} -void p3IdService::timeStampKey(const RsGxsId& gxs_id, const RsIdentityUsage& reason) -{ - if(rsReputations->isIdentityBanned(gxs_id) ) - { - std::cerr << "(II) p3IdService:timeStampKey(): refusing to time stamp key " << gxs_id << " because it is banned." << std::endl; - return ; - } -#ifdef DEBUG_IDS - std::cerr << "(II) time stamping key " << gxs_id << " for the following reason: " << reason.mUsageCode << std::endl; -#endif - - RS_STACK_MUTEX(mIdMtx) ; - - rstime_t now = time(NULL) ; - - keyTSInfo& info(mKeysTS[gxs_id]) ; - - info.TS = now ; - info.usage_map[reason] = now; - - while(info.usage_map.size() > GXS_MAX_KEY_TS_USAGE_MAP_SIZE) - { - // This is very costly, but normally the outerloop should never be rolled more than once. - - std::map::iterator best_it ; - rstime_t best_time = now+1; - - for(std::map::iterator it(info.usage_map.begin());it!=info.usage_map.end();++it) - if(it->second < best_time) - { - best_time = it->second ; - best_it = it; - } - - info.usage_map.erase(best_it) ; - } - - slowIndicateConfigChanged() ; -} - -bool p3IdService::loadList(std::list& items) -{ - RS_STACK_MUTEX(mIdMtx) ; - RsGxsIdLocalInfoItem *lii; - - for(std::list::const_iterator it = items.begin();it!=items.end();++it) - { - if( (lii = dynamic_cast(*it)) != NULL) - { - for(std::map::const_iterator it2 = lii->mTimeStamps.begin();it2!=lii->mTimeStamps.end();++it2) - mKeysTS[it2->first].TS = it2->second; - - mContacts = lii->mContacts ; - } - - RsConfigKeyValueSet *vitem = dynamic_cast(*it); - - if(vitem) - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if(kit->key == "REMOVE_BANNED_IDENTITIES_DELAY") - { - int val ; - if (sscanf(kit->value.c_str(), "%d", &val) == 1) - { - mMaxKeepKeysBanned = val ; - std::cerr << "Setting mMaxKeepKeysBanned threshold to " << val << std::endl ; - } - }; - if(kit->key == "AUTO_SET_FRIEND_IDENTITIES_AS_CONTACT") - mAutoAddFriendsIdentitiesAsContacts = (kit->value == "YES") ; - } - - delete *it ; - } - - items.clear() ; - return true ; -} - -void p3IdService::setDeleteBannedNodesThreshold(uint32_t days) -{ - RsStackMutex stack(mIdMtx); /****** LOCKED MUTEX *******/ - if(mMaxKeepKeysBanned != days*86400) - { - mMaxKeepKeysBanned = days*86400 ; - IndicateConfigChanged(); - } -} -uint32_t p3IdService::deleteBannedNodesThreshold() -{ - RsStackMutex stack(mIdMtx); /****** LOCKED MUTEX *******/ - - return mMaxKeepKeysBanned/86400; -} - -void p3IdService::setAutoAddFriendIdsAsContact(bool b) -{ - RS_STACK_MUTEX(mIdMtx) ; - if(b != mAutoAddFriendsIdentitiesAsContacts) - { - IndicateConfigChanged(); - mAutoAddFriendsIdentitiesAsContacts=b; - } -} -bool p3IdService::autoAddFriendIdsAsContact() -{ - RS_STACK_MUTEX(mIdMtx) ; - return mAutoAddFriendsIdentitiesAsContacts; -} - -bool p3IdService::saveList(bool& cleanup,std::list& items) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::saveList()" << std::endl; -#endif - - RS_STACK_MUTEX(mIdMtx) ; - cleanup = true ; - RsGxsIdLocalInfoItem *item = new RsGxsIdLocalInfoItem ; - - for(std::map::const_iterator it(mKeysTS.begin());it!=mKeysTS.end();++it) - item->mTimeStamps[it->first] = it->second.TS; - - item->mContacts = mContacts ; - - items.push_back(item) ; - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - - kv.key = "REMOVE_BANNED_IDENTITIES_DELAY" ; - rs_sprintf(kv.value, "%d", mMaxKeepKeysBanned); - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "AUTO_SET_FRIEND_IDENTITIES_AS_CONTACT" ; - kv.value = mAutoAddFriendsIdentitiesAsContacts?"YES":"NO"; - vitem->tlvkvs.pairs.push_back(kv) ; - - items.push_back(vitem) ; - - return true ; -} - -class IdCacheEntryCleaner -{ -public: - IdCacheEntryCleaner(const std::map& last_usage_TSs,uint32_t m) : mLastUsageTS(last_usage_TSs),mMaxKeepKeysBanned(m) {} - - bool processEntry(RsGxsIdCache& entry) - { - rstime_t now = time(NULL); - const RsGxsId& gxs_id = entry.details.mId ; - - bool is_id_banned = rsReputations->isIdentityBanned(gxs_id) ; - bool is_own_id = (bool)(entry.details.mFlags & RS_IDENTITY_FLAGS_IS_OWN_ID) ; - bool is_known_id = (bool)(entry.details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN) ; - bool is_signed_id = (bool)(entry.details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) ; - bool is_a_contact = (bool)(entry.details.mFlags & RS_IDENTITY_FLAGS_IS_A_CONTACT) ; - -#ifdef DEBUG_IDS - std::cerr << "Identity: " << gxs_id << ": banned: " << is_id_banned << ", own: " << is_own_id << ", contact: " << is_a_contact << ", signed: " << is_signed_id << ", known: " << is_known_id; -#endif - - if(is_own_id || is_a_contact) - { -#ifdef DEBUG_IDS - std::cerr << " => kept" << std::endl; -#endif - return true ; - } - - std::map::const_iterator it = mLastUsageTS.find(gxs_id) ; - - bool no_ts = (it == mLastUsageTS.end()) ; - - rstime_t last_usage_ts = no_ts?0:(it->second.TS); - rstime_t max_keep_time = 0; - bool should_check = true ; - - if(no_ts) - max_keep_time = 0 ; - else if(is_id_banned) - { - if(mMaxKeepKeysBanned == 0) - should_check = false ; - else - max_keep_time = mMaxKeepKeysBanned ; - } - else if(is_known_id) - max_keep_time = MAX_KEEP_KEYS_SIGNED_KNOWN ; - else if(is_signed_id) - max_keep_time = MAX_KEEP_KEYS_SIGNED ; - else - max_keep_time = MAX_KEEP_KEYS_DEFAULT ; - -#ifdef DEBUG_IDS - std::cerr << ". Max keep = " << max_keep_time/86400 << " days. Unused for " << (now - last_usage_ts + 86399)/86400 << " days " ; -#endif - - if(should_check && now > last_usage_ts + max_keep_time) - { -#ifdef DEBUG_IDS - std::cerr << " => delete " << std::endl; -#endif - ids_to_delete.push_back(gxs_id) ; - } -#ifdef DEBUG_IDS - else - std::cerr << " => keep " << std::endl; -#endif - - return true; - } - - std::list ids_to_delete ; - const std::map& mLastUsageTS; - uint32_t mMaxKeepKeysBanned ; -}; - -void p3IdService::cleanUnusedKeys() -{ - std::list ids_to_delete ; - - std::cerr << "Cleaning unused keys:" << std::endl; - - // we need to stash all ids to delete into an off-mutex structure since deleteIdentity() will trigger the lock - { - RS_STACK_MUTEX(mIdMtx) ; - - if(!mOwnIdsLoaded) - { - std::cerr << "(EE) Own ids not loaded. Cannot clean unused keys." << std::endl; - return ; - } - - // grab at most 10 identities to delete. No need to send too many requests to the token queue at once. - IdCacheEntryCleaner idcec(mKeysTS,mMaxKeepKeysBanned) ; - - mKeyCache.applyToAllCachedEntries(idcec,&IdCacheEntryCleaner::processEntry); - - ids_to_delete = idcec.ids_to_delete ; - } - std::cerr << "Collected " << ids_to_delete.size() << " keys to delete among " << mKeyCache.size() << std::endl; - - for(std::list::const_iterator it(ids_to_delete.begin());it!=ids_to_delete.end();++it) - { -#ifdef DEBUG_IDS - std::cerr << "Deleting identity " << *it << " which is too old." << std::endl; -#endif - uint32_t token ; - RsGxsIdGroup group; - group.mMeta.mGroupId=RsGxsGroupId(*it); - rsIdentity->deleteIdentity(token, group); - - { - RS_STACK_MUTEX(mIdMtx) ; - mKeysTS.erase(*it) ; - - // mPublicKeyCache.erase(*it) ; no need to do it now. It's done in p3IdService::deleteGroup() - } - } -} - -void p3IdService::service_tick() -{ - RsTickEvent::tick_events(); - GxsTokenQueue::checkRequests(); // GxsTokenQueue handles all requests. - - rstime_t now = time(NULL) ; - - if(mLastKeyCleaningTime + MAX_DELAY_BEFORE_CLEANING < now) - { - cleanUnusedKeys() ; - mLastKeyCleaningTime = now ; - } - - if(mLastPGPHashProcessTime + PGPHASH_PROC_PERIOD < now && !mGroupsToProcess.empty()) - { - pgphash_process(); - mLastPGPHashProcessTime=now; - } - - return; -} - -bool p3IdService::acceptNewGroup(const RsGxsGrpMetaData *grpMeta) -{ - bool res = !rsReputations->isIdentityBanned(RsGxsId(grpMeta->mGroupId)) ; - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::acceptNewGroup: ID=" << grpMeta->mGroupId << ": " << (res?"ACCEPTED":"DENIED") << std::endl; -#endif - - return res ; -} - -void p3IdService::notifyChanges(std::vector &changes) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::notifyChanges()"; - std::cerr << std::endl; -#endif - - /* iterate through and grab any new messages */ - std::list unprocessedGroups; - - for(uint32_t i = 0;i(changes[i]); - - if (msgChange && !msgChange->metaChange()) - RsWarn() << __PRETTY_FUNCTION__ << " Found a Msg data change in p3IdService. This is quite unexpected." << std::endl; - - RsGxsGroupChange *groupChange = dynamic_cast(changes[i]); - - if (groupChange) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::notifyChanges() Found Group Change Notification"; - std::cerr << std::endl; -#endif - const RsGxsGroupId& gid(groupChange->mGroupId); -#ifdef DEBUG_IDS - std::cerr << "p3IdService::notifyChanges() Auto Subscribe to Incoming Groups: " << gid; - std::cerr << std::endl; -#endif - - if(!rsReputations->isIdentityBanned(RsGxsId(gid))) - { - // notify that a new identity is received, if needed - - bool should_subscribe = false; - - switch(groupChange->getType()) - { - case RsGxsNotify::TYPE_PROCESSED: break ; // Happens when the group is subscribed. This is triggered by RsGenExchange::subscribeToGroup, so better not - // call it again from here!! - - case RsGxsNotify::TYPE_UPDATED: - case RsGxsNotify::TYPE_PUBLISHED: - { - auto ev = std::make_shared(); - ev->mIdentityId = gid; - ev->mIdentityEventCode = RsGxsIdentityEventCode::UPDATED_IDENTITY; - rsEvents->postEvent(ev); - - // also time_stamp the key that this group represents - timeStampKey(RsGxsId(gid),RsIdentityUsage(RsServiceType(serviceType()),RsIdentityUsage::IDENTITY_NEW_FROM_GXS_SYNC)) ; - should_subscribe = true; - } - break; - - case RsGxsNotify::TYPE_RECEIVED_NEW: - { - auto ev = std::make_shared(); - ev->mIdentityId = gid; - ev->mIdentityEventCode = RsGxsIdentityEventCode::NEW_IDENTITY; - rsEvents->postEvent(ev); - - // also time_stamp the key that this group represents - timeStampKey(RsGxsId(gid),RsIdentityUsage(RsServiceType(serviceType()),RsIdentityUsage::IDENTITY_NEW_FROM_GXS_SYNC)) ; - should_subscribe = true; - - std::cerr << "Received new identity " << gid << " and subscribing to it" << std::endl; - } - break; - - default: - break; - } - - if(should_subscribe) - { - uint32_t token; - RsGenExchange::subscribeToGroup(token, gid, true); - - // we need to acknowledge the token in a async process - - RsThread::async( [this,token]() - { - std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000); - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100); - - auto timeout = std::chrono::steady_clock::now() + maxWait; // wait for 10 secs at most - auto st = requestStatus(token); - - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = requestStatus(token); - } - - RsGxsGroupId grpId; - acknowledgeGrp(token,grpId); - }); - } - - } - } - - delete changes[i]; - } -} - -/********************************************************************************/ -/******************* RsIdentity Interface ***************************************/ -/********************************************************************************/ - -#if 0 -bool p3IdService:: getNickname(const RsGxsId &id, std::string &nickname) -{ - return false; -} -#endif - -rstime_t p3IdService::getLastUsageTS(const RsGxsId &id) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - return locked_getLastUsageTS(id) ; -} - -bool p3IdService::getIdDetails(const RsGxsId &id, RsIdentityDetails &details) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getIdDetails(" << id << ")"; - std::cerr << std::endl; -#endif - - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - RsGxsIdCache data; - - if (mKeyCache.fetch(id, data)) - { - bool is_a_contact = (mContacts.find(id) != mContacts.end()); - - details = data.details; - - if(mAutoAddFriendsIdentitiesAsContacts && (!is_a_contact) && (details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN) && rsPeers->isPgpFriend(details.mPgpId)) - { - mContacts.insert(id) ; - slowIndicateConfigChanged() ; - - is_a_contact = true; - } - - // This step is needed, because p3GxsReputation does not know all identities, and might not have any data for - // the ones in the contact list. So we change them on demand. - - if(is_a_contact && rsReputations->autoPositiveOpinionForContacts()) - { - RsOpinion op; - if( rsReputations->getOwnOpinion(id,op) && - op == RsOpinion::NEUTRAL ) - rsReputations->setOwnOpinion(id, RsOpinion::POSITIVE); - } - - std::map::const_iterator it = mKeysTS.find(id) ; - - if(it == mKeysTS.end()) - details.mLastUsageTS = 0 ; - else - { - details.mLastUsageTS = it->second.TS ; - details.mUseCases = it->second.usage_map ; - } - details.mPublishTS = data.mPublishTs; - - // one utf8 symbol can be at most 4 bytes long - would be better to measure real unicode length !!! - if(details.mNickname.length() > RSID_MAXIMUM_NICKNAME_SIZE*4) - details.mNickname = "[too long a name]" ; - - rsReputations->getReputationInfo(id,details.mPgpId,details.mReputation) ; - - return true; - } - } - - /* it isn't there - add to public requests */ - cache_request_load(id); - - return false; -} - -bool p3IdService::isOwnId(const RsGxsId& id) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - return std::find(mOwnIds.begin(),mOwnIds.end(),id) != mOwnIds.end() ; -} - - -bool p3IdService::getOwnSignedIds(std::vector& ids) -{ - ids.clear(); - - std::chrono::seconds maxWait(5); - auto timeout = std::chrono::steady_clock::now() + maxWait; - while( !ownIdsAreLoaded() && std::chrono::steady_clock::now() < timeout ) - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - - if(ownIdsAreLoaded()) - { - RS_STACK_MUTEX(mIdMtx); - ids.resize(mOwnSignedIds.size()); - std::copy(mOwnSignedIds.begin(), mOwnSignedIds.end(), ids.begin()); - return true; - } - - return false; -} - -bool p3IdService::getOwnPseudonimousIds(std::vector& ids) -{ - ids.clear(); - std::vector signedV; - - // this implicitely ensure ids are already loaded ;) - if(!getOwnSignedIds(signedV)) return false; - - std::set signedS(signedV.begin(), signedV.end()); - - { - RS_STACK_MUTEX(mIdMtx); - ids.resize(mOwnIds.size() - signedV.size()); - std::copy_if( mOwnIds.begin(), mOwnIds.end(), ids.begin(), - [&](const RsGxsId& id) {return !signedS.count(id);} ); - } - - return true; -} - -bool p3IdService::getOwnIds(std::list &ownIds,bool signed_only) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - if(!mOwnIdsLoaded) - { - std::cerr << "p3IdService::getOwnIds(): own identities are not loaded yet." << std::endl; - return false ; - } - - ownIds = signed_only ? mOwnSignedIds : mOwnIds; - - return true ; -} - -bool p3IdService::isKnownId(const RsGxsId& id) -{ - RS_STACK_MUTEX(mIdMtx); - return mKeyCache.is_cached(id) || - std::find(mOwnIds.begin(), mOwnIds.end(),id) != mOwnIds.end(); -} - -bool p3IdService::serialiseIdentityToMemory( const RsGxsId& id, - std::string& radix_string ) -{ - RS_STACK_MUTEX(mIdMtx); - - // look into cache. If available, return the data. If not, request it. - - std::map::const_iterator it = mSerialisedIdentities.find(id); - - if(it != mSerialisedIdentities.end()) - { - Radix64::encode(it->second.mMem,it->second.mSize,radix_string) ; - - if(it->second.mLastUsageTS + MAX_SERIALISED_IDENTITY_AGE > time(NULL)) - return true ; - - std::cerr << "Identity " << id << " will be re-serialised, because the last record is too old." << std::endl; - } - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - uint32_t token = 0; - std::list groupIds; - - groupIds.push_back(RsGxsGroupId(id)) ; - - RsGenExchange::getTokenService()->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds); - GxsTokenQueue::queueRequest(token, GXSIDREQ_SERIALIZE_TO_MEMORY); - - return false; -} - -void p3IdService::handle_get_serialized_grp(uint32_t token) -{ - // store the serialized data in cache. - - unsigned char *mem = NULL; - uint32_t size; - RsGxsGroupId id ; - - if(!RsGenExchange::getSerializedGroupData(token,id, mem,size)) - { - std::cerr << "(EE) call to RsGenExchage::getSerializedGroupData() failed." << std::endl; - return ; - } - - std::cerr << "Received serialised group from RsGenExchange." << std::endl; - - std::map::const_iterator it = mSerialisedIdentities.find(RsGxsId(id)); - - if(it != mSerialisedIdentities.end()) - free(it->second.mMem) ; - - SerialisedIdentityStruct s ; - s.mMem = mem ; - s.mSize = size ; - s.mLastUsageTS = time(NULL) ; - - mSerialisedIdentities[RsGxsId(id)] = s ; -} - -bool p3IdService::deserialiseIdentityFromMemory(const std::string& radix_string, - RsGxsId* id /* = nullptr */) -{ - std::vector mem = Radix64::decode(radix_string); - - if(mem.empty()) - { - std::cerr << __PRETTY_FUNCTION__ << "Cannot decode radix string \"" - << radix_string << "\"" << std::endl; - return false; - } - - if( !RsGenExchange::deserializeGroupData( - mem.data(), mem.size(), reinterpret_cast(id)) ) - { - std::cerr << __PRETTY_FUNCTION__ << "Cannot load identity from radix " - << "string \"" << radix_string << "\"" << std::endl; - return false; - } - - return true; -} - -bool p3IdService::createIdentity( RsGxsId& id, const std::string& name, const RsGxsImage& avatar, bool pseudonimous, const std::string& pgpPassword) -{ - bool ret = true; - 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.nickname = name; - params.mImage = avatar; - - if(!createIdentity(token, params)) - { - RsErr() << __PRETTY_FUNCTION__ << " Failed creating GXS group." << std::endl; - ret = false; - goto LabelCreateIdentityCleanup; - } - - /* 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 ) - { - RsErr() << __PRETTY_FUNCTION__ << " waitToken("<< token << ") failed with: " << wtStatus << std::endl; - ret = false; - goto LabelCreateIdentityCleanup; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, meta)) - { - RsErr() << __PRETTY_FUNCTION__ << " Failure getting updated group data." << std::endl; - ret = false; - goto LabelCreateIdentityCleanup; - } - - id = RsGxsId(meta.mGroupId); - - { - RS_STACK_MUTEX(mIdMtx); - mOwnIds.push_back(id); - if(!pseudonimous) mOwnSignedIds.push_back(id); - } - -LabelCreateIdentityCleanup: - if(!pseudonimous && !pgpPassword.empty()) - { - rsNotify->setDisableAskPassword(false); - rsNotify->clearPgpPassphrase(); - } - - return ret; -} - -bool p3IdService::createIdentity(uint32_t& token, RsIdentityParameters ¶ms) -{ - - RsGxsIdGroup id; - - id.mMeta.mGroupName = params.nickname; - id.mMeta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC ; - id.mImage = params.mImage; - - if (params.isPgpLinked) - { -#warning csoler 2017-02-07: Backward compatibility issue to fix here in v0.7.0 - - // This is a hack, because a bad decision led to having RSGXSID_GROUPFLAG_REALID be equal to GXS_SERV::FLAG_PRIVACY_PRIVATE. - // In order to keep backward compatibility, we'll also add the new value - // When the ID is not PGP linked, the group flag cannot be let empty, so we use PUBLIC. - // - // The correct combination of flags should be: - // PGP-linked: GXS_SERV::FLAGS_PRIVACY_PUBLIC | RSGXSID_GROUPFLAG_REALID - // Anonymous : GXS_SERV::FLAGS_PRIVACY_PUBLIC - - id.mMeta.mGroupFlags |= GXS_SERV::FLAG_PRIVACY_PRIVATE; // this is also equal to RSGXSID_GROUPFLAG_REALID_deprecated - id.mMeta.mGroupFlags |= RSGXSID_GROUPFLAG_REALID; - - // The current version should be able to produce new identities that old peers will accept as well. - // In the future, we need to: - // - set the current group flags here (see above) - // - replace all occurences of RSGXSID_GROUPFLAG_REALID_deprecated by RSGXSID_GROUPFLAG_REALID in the code. - } - else - id.mMeta.mGroupFlags |= GXS_SERV::FLAG_PRIVACY_PUBLIC; - - // Anticipate signature validation, since we're creating the signature ourselves. - - SSGxsIdGroup ssdata; - ssdata.pgp.validatedSignature = params.isPgpLinked; - - if(params.isPgpLinked) - { - ssdata.pgp.pgpId = AuthGPG::getAuthGPG()->getGPGOwnId(); - ssdata.pgp.lastCheckTs = time(nullptr); - } - - /* save string */ - id.mMeta.mServiceString = ssdata.save(); - - createGroup(token, id); - - return true; -} - -bool p3IdService::updateIdentity( const RsGxsId& id, const std::string& name, const RsGxsImage& avatar, bool pseudonimous, const std::string& pgpPassword) -{ - // 1 - get back the identity group - - std::vector idsInfo; - - if(!getIdentitiesInfo(std::set{ id }, idsInfo)) - return false; - - RsGxsIdGroup& group(idsInfo[0]); - - // 2 - update it with the new information - - group.mMeta.mGroupName = name; - group.mMeta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC ; - group.mImage = avatar; - - if(!pseudonimous) - { -#warning csoler 2020-01-21: Backward compatibility issue to fix here in v0.7.0 - - // This is a hack, because a bad decision led to having RSGXSID_GROUPFLAG_REALID be equal to GXS_SERV::FLAG_PRIVACY_PRIVATE. - // In order to keep backward compatibility, we'll also add the new value - // When the ID is not PGP linked, the group flag cannot be let empty, so we use PUBLIC. - // - // The correct combination of flags should be: - // PGP-linked: GXS_SERV::FLAGS_PRIVACY_PUBLIC | RSGXSID_GROUPFLAG_REALID - // Anonymous : GXS_SERV::FLAGS_PRIVACY_PUBLIC - - group.mMeta.mGroupFlags |= GXS_SERV::FLAG_PRIVACY_PRIVATE; // this is also equal to RSGXSID_GROUPFLAG_REALID_deprecated - group.mMeta.mGroupFlags |= RSGXSID_GROUPFLAG_REALID; - - // The current version should be able to produce new identities that old peers will accept as well. - // In the future, we need to: - // - set the current group flags here (see above) - // - replace all occurences of RSGXSID_GROUPFLAG_REALID_deprecated by RSGXSID_GROUPFLAG_REALID in the code. - } - else - group.mMeta.mGroupFlags |= GXS_SERV::FLAG_PRIVACY_PUBLIC; - - uint32_t token; - bool ret = true; - - // Cache pgp passphrase to allow a proper re-signing of the group data - - if(!pseudonimous && !pgpPassword.empty()) - { - if(!rsNotify->cachePgpPassphrase(pgpPassword)) - { - RsErr() << __PRETTY_FUNCTION__ << " Failure caching password" << std::endl; - ret = false; - goto LabelUpdateIdentityCleanup; - } - - if(!rsNotify->setDisableAskPassword(true)) - { - RsErr() << __PRETTY_FUNCTION__ << " Failure disabling password user request" << std::endl; - ret = false; - goto LabelUpdateIdentityCleanup; - } - } - mKeyCache.erase(id); - - if(!updateGroup(token, group)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failed updating group." << std::endl; - ret = false; - goto LabelUpdateIdentityCleanup; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." << std::endl; - ret = false; - goto LabelUpdateIdentityCleanup; - } - - // clean the Identity cache as well - cache_request_load(id); - -LabelUpdateIdentityCleanup: - if(!pseudonimous && !pgpPassword.empty()) - rsNotify->clearPgpPassphrase(); - - return ret; -} - -bool p3IdService::deleteIdentity(RsGxsId& id) -{ - uint32_t token; - RsGxsGroupId grouId = RsGxsGroupId(id); - if(!deleteGroup(token, grouId)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failed deleting group." - << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." - << std::endl; - return false; - } - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mIdentityId = grouId; - ev->mIdentityEventCode = RsGxsIdentityEventCode::DELETED_IDENTITY; - rsEvents->postEvent(ev); - } - - return true; -} - -bool p3IdService::deleteIdentity(uint32_t& token, RsGxsIdGroup &group) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::deleteIdentity()"; - std::cerr << std::endl; -#endif - - deleteGroup(token, group.mMeta.mGroupId); - - return false; -} - - -bool p3IdService::parseRecognTag(const RsGxsId &id, const std::string &nickname, - const std::string &tag, RsRecognTagDetails &details) -{ -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::parseRecognTag()"; - std::cerr << std::endl; -#endif - - RsGxsRecognTagItem *tagitem = RsRecogn::extractTag(tag); - if (!tagitem) - { - return false; - } - - bool isPending = false; - bool isValid = recogn_checktag(id, nickname, tagitem, true, isPending); - - details.valid_from = tagitem->valid_from; - details.valid_to = tagitem->valid_to; - details.tag_class = tagitem->tag_class; - details.tag_type = tagitem->tag_type; - details.signer = tagitem->sign.keyId.toStdString(); - - details.is_valid = isValid; - details.is_pending = isPending; - - delete tagitem; - - return true; -} - -bool p3IdService::getRecognTagRequest(const RsGxsId &id, const std::string &comment, uint16_t tag_class, uint16_t tag_type, std::string &tag) -{ -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::getRecognTagRequest()"; - std::cerr << std::endl; -#endif - if(!isOwnId(id)) - { - std::cerr << "(EE) cannot retrieve own key to create tag request. KeyId=" << id << std::endl; - return false ; - } - - RsTlvPrivateRSAKey key; - std::string nickname; - RsGxsIdCache data ; - - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - if(!mKeyCache.fetch(id, data)) - return false ; - - nickname = data.details.mNickname ; - key = data.priv_key ; - } - - return RsRecogn::createTagRequest(key, id, nickname, tag_class, tag_type, comment, tag); -} - - - -/********************************************************************************/ -/******************* RsGixs Interface ***************************************/ -/********************************************************************************/ - -bool p3IdService::haveKey(const RsGxsId &id) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - return mKeyCache.is_cached(id); -} - -bool p3IdService::havePrivateKey(const RsGxsId &id) -{ - if(! isOwnId(id)) - return false ; - - RS_STACK_MUTEX(mIdMtx); - return mKeyCache.is_cached(id); -} - -static void mergeIds(std::map >& idmap,const RsGxsId& id,const std::list& peers) -{ - /* merge the two lists, use std::set to avoid duplicates efficiently */ - - std::set new_peers(std::begin(peers), std::end(peers)); - - std::list& stored_peers(idmap[id]); - std::copy( std::begin(stored_peers), std::end(stored_peers), - std::inserter(new_peers, std::begin(new_peers)) ); - stored_peers.clear(); - std::copy( std::begin(new_peers), std::end(new_peers), - std::inserter(stored_peers, std::begin(stored_peers)) ); -} - -bool p3IdService::requestIdentity( - const RsGxsId& id, const std::vector& peers ) -{ - std::list askPeersList(peers.begin(), peers.end()); - - // Empty list passed? Ask to all online peers. - if(askPeersList.empty()) rsPeers->getOnlineList(askPeersList); - - if(askPeersList.empty()) // Still empty? Fail! - { - RsErr() << __PRETTY_FUNCTION__ << " failure retrieving peers list" - << std::endl; - return false; - } - - RsIdentityUsage usageInfo( RsServiceType::GXSID, RsIdentityUsage::IDENTITY_NEW_FROM_EXPLICIT_REQUEST ); - - return requestKey(id, askPeersList, usageInfo); -} - -bool p3IdService::requestKey(const RsGxsId &id, const std::list& peers,const RsIdentityUsage& use_info) -{ - Dbg3() << __PRETTY_FUNCTION__ << " id: " << id << std::endl; - - if(id.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " cannot request null id" - << std::endl; - return false; - } - - if(peers.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " cannot request id: " << id - << " to empty lists of peers" << std::endl; - return false; - } - - if(isKnownId(id)) return true; - - /* Normally we should call getIdDetails(), but since the key is not known, - * we need to dig a possibly old information from the reputation system, - * which keeps its own list of banned keys. - * Of course, the owner ID is not known at this point.c*/ - - RsReputationInfo info; - rsReputations->getReputationInfo(id, RsPgpId(), info); - - if( info.mOverallReputationLevel == RsReputationLevel::LOCALLY_NEGATIVE ) - { -#ifdef DEBUG_IDS - RsInfo() << __PRETTY_FUNCTION__ << " not requesting Key " << id << " because it has been banned." << std::endl; -#endif - - RS_STACK_MUTEX(mIdMtx); - mIdsNotPresent.erase(id); - - return false; - } - - { - RS_STACK_MUTEX(mIdMtx); - mergeIds(mIdsNotPresent, id, peers); - mKeysTS[id].usage_map[use_info] = time(nullptr); - } - - return cache_request_load(id, peers); -} - -bool p3IdService::isPendingNetworkRequest(const RsGxsId& gxsId) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - // if ids has beens confirmed as not physically present return - // immediately, id will be removed from list if found by auto nxs net search - if(mIdsNotPresent.find(gxsId) != mIdsNotPresent.end()) - return true; - - return false; -} - -bool p3IdService::getKey(const RsGxsId &id, RsTlvPublicRSAKey &key) -{ - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - RsGxsIdCache data; - - if (mKeyCache.fetch(id, data)) - { - key = data.pub_key; - return true; - } - } - - cache_request_load(id); - - key.keyId.clear() ; - return false; -} - -bool p3IdService::requestPrivateKey(const RsGxsId &id) -{ - if (havePrivateKey(id)) - return true; - - return cache_request_load(id); -} - -bool p3IdService::getPrivateKey(const RsGxsId &id, RsTlvPrivateRSAKey &key) -{ - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - RsGxsIdCache data; - - if (mKeyCache.fetch(id, data)) - { - key = data.priv_key; - return true; - } - } - - key.keyId.clear() ; - cache_request_load(id); - - return false ; -} - - -bool p3IdService::signData(const uint8_t *data,uint32_t data_size,const RsGxsId& own_gxs_id,RsTlvKeySignature& signature,uint32_t& error_status) -{ - RsTlvPrivateRSAKey signature_key ; - - int i ; - for(i=0;i<6;++i) - if(!getPrivateKey(own_gxs_id,signature_key) || signature_key.keyData.bin_data == NULL) - { -#ifdef DEBUG_IDS - std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl; -#endif - rstime::rs_usleep(500 * 1000) ; // sleep for 500 msec. - } - else - break ; - - if(i == 6) - { - std::cerr << " (EE) Could not retrieve own private key for ID = " << own_gxs_id << ". Giging up sending DH session params. This should not happen." << std::endl; - error_status = RS_GIXS_ERROR_KEY_NOT_AVAILABLE ; - return false ; - } - -#ifdef DEBUG_IDS - std::cerr << " Signing..." << std::endl; -#endif - - if(!GxsSecurity::getSignature((char *)data,data_size,signature_key,signature)) - { - std::cerr << " (EE) Cannot sign for id " << own_gxs_id << ". Signature call failed." << std::endl; - error_status = RS_GIXS_ERROR_UNKNOWN ; - return false ; - } - error_status = RS_GIXS_ERROR_NO_ERROR ; - timeStampKey(own_gxs_id,RsIdentityUsage(RsServiceType(serviceType()),RsIdentityUsage::IDENTITY_GENERIC_SIGNATURE_CREATION)) ; - - return true ; -} -bool p3IdService::validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,const RsIdentityUsage& info,uint32_t& signing_error) -{ - // RsIdentityDetails details ; - // getIdDetails(signature.keyId,details); - RsTlvPublicRSAKey signature_key ; - - for(int i=0;i< (force_load?6:1);++i) - if(!getKey(signature.keyId,signature_key) || signature_key.keyData.bin_data == NULL) - { -#ifdef DEBUG_IDS - std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl; -#endif - if(force_load) rstime::rs_usleep(500 * 1000) ; // sleep for 500 msec. - } - else - break ; - - if(signature_key.keyData.bin_data == NULL) - { -#ifdef DEBUG_IDS - std::cerr << "(EE) Cannot validate signature for unknown key " << signature.keyId << std::endl; -#endif - signing_error = RS_GIXS_ERROR_KEY_NOT_AVAILABLE ; - return false; - } - - if(!GxsSecurity::validateSignature((char*)data,data_size,signature_key,signature)) - { - std::cerr << "(SS) Signature was verified and it doesn't check! This is a security issue!" << std::endl; - signing_error = RS_GIXS_ERROR_SIGNATURE_MISMATCH ; - return false; - } - signing_error = RS_GIXS_ERROR_NO_ERROR ; - - timeStampKey(signature.keyId,info); - return true ; -} - -bool p3IdService::encryptData( const uint8_t *decrypted_data, - uint32_t decrypted_data_size, - uint8_t *& encrypted_data, - uint32_t& encrypted_data_size, - const RsGxsId& encryption_key_id, - uint32_t& error_status, - bool force_load ) -{ - RsTlvPublicRSAKey encryption_key ; - - // get the key, and let the cache find it. - for(int i=0; i<(force_load?6:1);++i) - if(getKey(encryption_key_id,encryption_key)) - break ; - else - rstime::rs_usleep(500*1000) ; // sleep half a sec. - - if(encryption_key.keyId.isNull()) - { - std::cerr << " (EE) Cannot get encryption key for id " << encryption_key_id << std::endl; - error_status = RS_GIXS_ERROR_KEY_NOT_AVAILABLE ; - return false ; - } - - if(!GxsSecurity::encrypt(encrypted_data,encrypted_data_size,decrypted_data,decrypted_data_size,encryption_key)) - { - std::cerr << " (EE) Encryption failed." << std::endl; - error_status = RS_GIXS_ERROR_UNKNOWN ; - return false ; - } - error_status = RS_GIXS_ERROR_NO_ERROR ; - timeStampKey(encryption_key_id,RsIdentityUsage(RsServiceType::GXSID,RsIdentityUsage::IDENTITY_GENERIC_ENCRYPTION)) ; - - return true ; -} - -bool p3IdService::encryptData( const uint8_t* decrypted_data, - uint32_t decrypted_data_size, - uint8_t*& encrypted_data, - uint32_t& encrypted_data_size, - const std::set& encrypt_ids, - uint32_t& error_status, bool force_load ) -{ - std::set keyNotYetFoundIds; - - for( std::set::const_iterator it = encrypt_ids.begin(); - it != encrypt_ids.end(); ++it ) - { - const RsGxsId& gId(*it); - if(gId.isNull()) - { - std::cerr << "p3IdService::encryptData(...) (EE) got null GXS id" - << std::endl; - return false; - } - else keyNotYetFoundIds.insert(&gId); - } - - if(keyNotYetFoundIds.empty()) - { - std::cerr << "p3IdService::encryptData(...) (EE) got empty GXS ids set" - << std::endl; - print_stacktrace(); - return false; - } - - std::vector encryption_keys; - int maxRounds = force_load ? 6 : 1; - for( int i=0; i < maxRounds; ++i ) - { - for( std::set::iterator it = keyNotYetFoundIds.begin(); - it !=keyNotYetFoundIds.end(); ) - { - RsTlvPublicRSAKey encryption_key; - if(getKey(**it, encryption_key) && !encryption_key.keyId.isNull()) - { - encryption_keys.push_back(encryption_key); - it = keyNotYetFoundIds.erase(it); - } - else - { - ++it; - } - } - - if(keyNotYetFoundIds.empty()) break; - else rstime::rs_usleep(500*1000); - } - - if(!keyNotYetFoundIds.empty()) - { - std::cerr << "p3IdService::encryptData(...) (EE) Cannot get " - << "encryption key for: "; - for( std::set::iterator it = keyNotYetFoundIds.begin(); - it !=keyNotYetFoundIds.end(); ++it ) - std::cerr << **it << " "; - std::cerr << std::endl; - print_stacktrace(); - - error_status = RS_GIXS_ERROR_KEY_NOT_AVAILABLE; - return false; - } - - if(!GxsSecurity::encrypt( encrypted_data, encrypted_data_size, - decrypted_data, decrypted_data_size, - encryption_keys )) - { - std::cerr << "p3IdService::encryptData(...) (EE) Encryption failed." - << std::endl; - print_stacktrace(); - - error_status = RS_GIXS_ERROR_UNKNOWN; - return false ; - } - - for( std::set::const_iterator it = encrypt_ids.begin(); - it != encrypt_ids.end(); ++it ) - { - timeStampKey( *it, - RsIdentityUsage( - RsServiceType::GXSID, - RsIdentityUsage::IDENTITY_GENERIC_ENCRYPTION ) ); - } - - error_status = RS_GIXS_ERROR_NO_ERROR; - return true; -} - -bool p3IdService::decryptData( const uint8_t *encrypted_data, - uint32_t encrypted_data_size, - uint8_t *& decrypted_data, - uint32_t& decrypted_size, - const RsGxsId& key_id, uint32_t& error_status, - bool force_load ) -{ - RsTlvPrivateRSAKey encryption_key ; - - // Get the key, and let the cache find it. It's our own key, so we should be able to find it, even if it takes - // some seconds. - - int maxRounds = force_load ? 6 : 1; - for(int i=0; i& decrypt_ids, - uint32_t& error_status, - bool force_load ) -{ - std::set keyNotYetFoundIds; - - for( std::set::const_iterator it = decrypt_ids.begin(); - it != decrypt_ids.end(); ++it ) - { - const RsGxsId& gId(*it); - if(gId.isNull()) - { - std::cerr << "p3IdService::decryptData(...) (EE) got null GXS id" - << std::endl; - print_stacktrace(); - return false; - } - else keyNotYetFoundIds.insert(&gId); - } - - if(keyNotYetFoundIds.empty()) - { - std::cerr << "p3IdService::decryptData(...) (EE) got empty GXS ids set" - << std::endl; - print_stacktrace(); - return false; - } - - std::vector decryption_keys; - int maxRounds = force_load ? 6 : 1; - for( int i=0; i < maxRounds; ++i ) - { - for( std::set::iterator it = keyNotYetFoundIds.begin(); - it !=keyNotYetFoundIds.end(); ) - { - RsTlvPrivateRSAKey decryption_key; - if( getPrivateKey(**it, decryption_key) - && !decryption_key.keyId.isNull() ) - { - decryption_keys.push_back(decryption_key); - it = keyNotYetFoundIds.erase(it); - } - else - { - ++it; - } - } - - if(keyNotYetFoundIds.empty()) break; - else rstime::rs_usleep(500*1000); - } - - if(!keyNotYetFoundIds.empty()) - { - std::cerr << "p3IdService::decryptData(...) (EE) Cannot get private key" - << " for: "; - for( std::set::iterator it = keyNotYetFoundIds.begin(); - it !=keyNotYetFoundIds.end(); ++it ) - std::cerr << **it << " "; - std::cerr << std::endl; - print_stacktrace(); - - error_status = RS_GIXS_ERROR_KEY_NOT_AVAILABLE; - return false; - } - - if(!GxsSecurity::decrypt( decrypted_data, decrypted_data_size, - encrypted_data, encrypted_data_size, - decryption_keys )) - { - std::cerr << "p3IdService::decryptData(...) (EE) Decryption failed." - << std::endl; - print_stacktrace(); - - error_status = RS_GIXS_ERROR_UNKNOWN; - return false ; - } - - for( std::set::const_iterator it = decrypt_ids.begin(); - it != decrypt_ids.end(); ++it ) - { - timeStampKey( *it, - RsIdentityUsage( - RsServiceType::GXSID, - RsIdentityUsage::IDENTITY_GENERIC_DECRYPTION ) ); - } - - error_status = RS_GIXS_ERROR_NO_ERROR; - return true; -} - -#ifdef TO_BE_REMOVED -/********************************************************************************/ -/******************* RsGixsReputation ***************************************/ -/********************************************************************************/ - -bool p3IdService::haveReputation(const RsGxsId &id) -{ - return haveKey(id); -} - -bool p3IdService::loadReputation(const RsGxsId &id, const std::list& peers) -{ - if (haveKey(id)) - return true; - else - { - if(isPendingNetworkRequest(id)) - return true; - } - - - return cache_request_load(id, peers); -} - -bool p3IdService::getReputation(const RsGxsId &id, GixsReputation &rep) -{ - /* this is the key part for accepting messages */ - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - RsGxsIdCache data; - - if (mKeyCache.fetch(id, data)) - { - rep.id = id; - rep.score = 0;//data.details.mReputation.mOverallScore; -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getReputation() id: "; - std::cerr << id.toStdString() << " score: " << - rep.score; - std::cerr << std::endl; -#endif - - return true; - } - else - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getReputation() id: "; - std::cerr << id.toStdString() << " not cached"; - std::cerr << std::endl; -#endif - } - return false; -} -#endif - -#if 0 -class RegistrationRequest -{ -public: - RegistrationRequest(uint32_t token, RsGxsId &id, int score) - :m_extToken(token), m_id(id), m_score(score) { return; } - - uint32_t m_intToken; - uint32_t m_extToken; - RsGxsId m_id; - int m_score; -}; -#endif - - -bool p3IdService::submitOpinion(uint32_t& token, const RsGxsId &id, bool absOpinion, int score) -{ -#ifdef DEBUG_OPINION - std::cerr << "p3IdService::submitOpinion()"; - std::cerr << std::endl; -#endif - - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - - token = RsGenExchange::generatePublicToken(); - - uint32_t intToken; - std::list groups; - groups.push_back(RsGxsGroupId(id)); - - RsGenExchange::getTokenService()->requestGroupInfo(intToken, ansType, opts, groups); - GxsTokenQueue::queueRequest(intToken, GXSIDREQ_OPINION); - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - mPendingOpinion[intToken] = OpinionRequest(token, id, absOpinion, score); - return true; -} - - - -bool p3IdService::opinion_handlerequest(uint32_t token) -{ -#ifdef DEBUG_OPINION - std::cerr << "p3IdService::opinion_handlerequest()"; - std::cerr << std::endl; -#endif - - OpinionRequest req; - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - /* find in pendingReputation */ - std::map::iterator it; - it = mPendingOpinion.find(token); - if (it == mPendingOpinion.end()) - { - std::cerr << "p3IdService::opinion_handlerequest() ERROR finding PendingOpinion"; - std::cerr << std::endl; - - return false; - } - req = it->second; - mPendingOpinion.erase(it); - } - -#ifdef DEBUG_OPINION - std::cerr << "p3IdService::opinion_handlerequest() Id: " << req.mId << " score: " << req.mScore; - std::cerr << std::endl; -#endif - - std::list groups; - std::list groupList; - - if (!getGroupMeta(token, groups)) - { - std::cerr << "p3IdService::opinion_handlerequest() ERROR getGroupMeta()"; - std::cerr << std::endl; - - updatePublicRequestStatus(req.mToken, RsTokenService::FAILED); - return false; - } - - if (groups.size() != 1) - { - std::cerr << "p3IdService::opinion_handlerequest() ERROR group.size() != 1"; - std::cerr << std::endl; - - // error. - updatePublicRequestStatus(req.mToken, RsTokenService::FAILED); - return false; - } - RsGroupMetaData &meta = *(groups.begin()); - - if (meta.mGroupId != RsGxsGroupId(req.mId)) - { - std::cerr << "p3IdService::opinion_handlerequest() ERROR Id mismatch"; - std::cerr << std::endl; - - // error. - updatePublicRequestStatus(req.mToken, RsTokenService::FAILED); - return false; - } - - /* get the string */ - SSGxsIdGroup ssdata; - ssdata.load(meta.mServiceString); // attempt load - okay if fails. - - /* modify score */ - if (req.mAbsOpinion) - { - ssdata.score.rep.mOwnOpinion = req.mScore; - } - else - { - ssdata.score.rep.mOwnOpinion += req.mScore; - } - - // update IdScore too. - bool pgpId = (meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility); - ssdata.score.rep.updateIdScore(pgpId, ssdata.pgp.validatedSignature); - ssdata.score.rep.update(); - - /* save string */ - std::string serviceString = ssdata.save(); -#ifdef DEBUG_OPINION - std::cerr << "p3IdService::opinion_handlerequest() new service_string: " << serviceString; - std::cerr << std::endl; -#endif - - /* set new Group ServiceString */ - uint32_t dummyToken = 0; - setGroupServiceString(dummyToken, meta.mGroupId, serviceString); - cache_update_if_cached(RsGxsId(meta.mGroupId), serviceString); - - updatePublicRequestStatus(req.mToken, RsTokenService::COMPLETE); - return true; -} - - -/********************************************************************************/ -/******************* Get/Set Data ******************************************/ -/********************************************************************************/ - -RsSerialiser *p3IdService::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - - rss->addSerialType(new RsGxsIdSerialiser()) ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss ; -} - -bool p3IdService::getGroupData(const uint32_t &token, std::vector &groups) -{ - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsIdGroupItem* item = dynamic_cast(*vit); - if (item) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getGroupData() Item is:"; - std::cerr << std::endl; - item->print(std::cerr); - std::cerr << std::endl; -#endif // DEBUG_IDS - RsGxsIdGroup group ; - item->toGxsIdGroup(group,false) ; - - { - RS_STACK_MUTEX(mIdMtx) ; - group.mLastUsageTS = locked_getLastUsageTS(RsGxsId(group.mMeta.mGroupId)) ; - } - - // Decode information from serviceString. - SSGxsIdGroup ssdata; - if (ssdata.load(group.mMeta.mServiceString)) - { - group.mPgpKnown = ssdata.pgp.validatedSignature; - group.mPgpId = ssdata.pgp.pgpId; - group.mReputation = ssdata.score.rep; -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getGroupData() Success decoding ServiceString"; - std::cerr << std::endl; - std::cerr << "\t mGpgKnown: " << group.mPgpKnown; - std::cerr << std::endl; - std::cerr << "\t mGpgId: " << group.mPgpId; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { - group.mPgpKnown = false; - group.mPgpId.clear(); - - if(!group.mMeta.mServiceString.empty()) - std::cerr << "p3IdService::getGroupData() " << group.mMeta.mGroupId << " (" << group.mMeta.mGroupName << ") : Failed to decode, or no ServiceString \"" << group.mMeta.mServiceString << "\"" << std::endl; - } - - group.mIsAContact = (mContacts.find(RsGxsId(group.mMeta.mGroupId)) != mContacts.end()); - group.mPgpLinked = (!!(group.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility)) || !!(group.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID); - - groups.push_back(group); - delete(item); - } - else - { - std::cerr << "Not a Id Item, deleting!" << std::endl; - delete(*vit); - } - } - } - - return ok; -} - -bool p3IdService::getGroupSerializedData(const uint32_t &token, std::map& serialized_groups) -{ - unsigned char *mem = NULL; - uint32_t size; - RsGxsGroupId id ; - - serialized_groups.clear() ; - - if(!RsGenExchange::getSerializedGroupData(token,id, mem,size)) - { - std::cerr << "(EE) call to RsGenExchage::getSerializedGroupData() failed." << std::endl; - return false; - } - - std::string radix ; - - Radix64::encode(mem,size,radix) ; - - serialized_groups[RsGxsId(id)] = radix ; - - return true; -} - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - -bool p3IdService::createGroup(uint32_t& token, RsGxsIdGroup &group) -{ - RsGxsIdGroupItem* item = new RsGxsIdGroupItem(); - - item->meta = group.mMeta; - item->mImage.binData.setBinData(group.mImage.mData, group.mImage.mSize); - - RsGenExchange::publishGroup(token, item); - return true; -} - -bool p3IdService::updateGroup(uint32_t& token, RsGxsIdGroup &group) -{ - RsGxsId id(group.mMeta.mGroupId); - RsGxsIdGroupItem* item = new RsGxsIdGroupItem(); - - item->fromGxsIdGroup(group,false) ; - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::updateGroup() Updating RsGxsId: " << id; - std::cerr << std::endl; -#endif - - RsGenExchange::updateGroup(token, item); - - // if its in the cache - clear it. - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - if (mKeyCache.erase(id)) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::updateGroup() Removed from PublicKeyCache"; - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::updateGroup() Not in PublicKeyCache"; - std::cerr << std::endl; -#endif - } - } - - return true; -} - -bool p3IdService::deleteGroup(uint32_t& token, RsGxsGroupId& groupId) -{ - RsGxsId id(groupId); - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::deleteGroup() Deleting RsGxsId: " << id; - std::cerr << std::endl; -#endif - - RsGenExchange::deleteGroup(token, groupId); - - // if its in the cache - clear it. - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - if (mKeyCache.erase(id)) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::deleteGroup() Removed from PublicKeyCache"; - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::deleteGroup() Not in PublicKeyCache"; - std::cerr << std::endl; -#endif - } - - std::list::iterator lit = std::find( mOwnIds.begin(), mOwnIds.end(), id); - if (lit != mOwnIds.end()) - { - mOwnIds.remove((RsGxsId)*lit); -#ifdef DEBUG_IDS - std::cerr << "p3IdService::deleteGroup() Removed from OwnIds"; - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::deleteGroup() Not in OwnIds"; - std::cerr << std::endl; -#endif - } - } - - return true; -} - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -/* Encoding / Decoding Group Service String stuff - * - * Pgp stuff. - * - * If flagged as pgp id.... - * then we need to know if its been matched, or when we last tried to match. - * - */ - -bool SSGxsIdPgp::load(const std::string &input) -{ - char pgpline[RSGXSID_MAX_SERVICE_STRING]; - int timestamp = 0; - uint32_t attempts = 0; - if (1 == sscanf(input.c_str(), "K:1 I:%[^)]", pgpline)) - { - validatedSignature = true; - std::string str_line = pgpline; - pgpId = RsPgpId(str_line); - return true; - } - else if (3 == sscanf(input.c_str(), "K:0 T:%d C:%d I:%[^)]", ×tamp, &attempts,pgpline)) - { - lastCheckTs = timestamp; - checkAttempts = attempts; - validatedSignature = false; - std::string str_line = pgpline; - pgpId = RsPgpId(str_line); - return true; - } - else if (2 == sscanf(input.c_str(), "K:0 T:%d C:%d", ×tamp, &attempts)) - { - lastCheckTs = timestamp; - checkAttempts = attempts; - validatedSignature = false; - return true; - } - else if (1 == sscanf(input.c_str(), "K:0 T:%d", ×tamp)) - { - lastCheckTs = timestamp; - checkAttempts = 0; - validatedSignature = false; - return true; - } - else - { - lastCheckTs = 0; - checkAttempts = 0; - validatedSignature = false; - return false; - } -} - -std::string SSGxsIdPgp::save() const -{ - std::string output; - if (validatedSignature) - { - output += "K:1 I:"; - output += pgpId.toStdString(); - } - else - { - rs_sprintf(output, "K:0 T:%d C:%d", lastCheckTs, checkAttempts); - - if(!pgpId.isNull()) - output += " I:"+pgpId.toStdString(); - } - return output; -} - - -/* Encoding / Decoding Group Service String stuff - * - * RecognTags. - */ - -bool SSGxsIdRecognTags::load(const std::string &input) -{ - //char pgpline[RSGXSID_MAX_SERVICE_STRING]; - int pubTs = 0; - int lastTs = 0; - uint32_t flags = 0; - - if (3 == sscanf(input.c_str(), "F:%u P:%d T:%d", &flags, &pubTs, &lastTs)) - { - publishTs = pubTs; - lastCheckTs = lastTs; - tagFlags = flags; - } - else - { - return false; - } - return true; -} - -std::string SSGxsIdRecognTags::save() const -{ - std::string output; - rs_sprintf(output, "F:%u P:%d T:%d", tagFlags, publishTs, lastCheckTs); - return output; -} - -bool SSGxsIdRecognTags::tagsProcessed() const -{ - return (tagFlags & 0x1000); -} - -bool SSGxsIdRecognTags::tagsPending() const -{ - return (tagFlags & 0x2000); -} - -bool SSGxsIdRecognTags::tagValid(int i) const -{ - uint32_t idx = 0x01 << i; - -#ifdef DEBUG_RECOGN - std::cerr << "SSGxsIdRecognTags::tagValid(" << i << ") idx: " << idx; - std::cerr << " result: " << (tagFlags & idx); - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - return (tagFlags & idx); -} - -void SSGxsIdRecognTags::setTags(bool processed, bool pending, uint32_t flags) -{ - flags &= 0x00ff; // clear top bits; - if (processed) - { - flags |= 0x1000; - } - if (pending) - { - flags |= 0x2000; - } - -#ifdef DEBUG_RECOGN - std::cerr << "SSGxsIdRecognTags::setTags(" << processed << "," << pending << "," << flags << ")"; - std::cerr << " tagFlags: " << tagFlags; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - tagFlags = flags; -} - - -GxsReputation::GxsReputation() - :mOverallScore(0), mIdScore(0), mOwnOpinion(0), mPeerOpinion(0) -{ - updateIdScore(false, false); - update(); -} - -static const int kIdReputationPgpKnownScore = 50; -static const int kIdReputationPgpUnknownScore = 20; -static const int kIdReputationAnonScore = 5; - -bool GxsReputation::updateIdScore(bool pgpLinked, bool pgpKnown) -{ - if (pgpLinked) - { - if (pgpKnown) - { - mIdScore = kIdReputationPgpKnownScore; - } - else - { - mIdScore = kIdReputationPgpUnknownScore; - } - } - else - { - mIdScore = kIdReputationAnonScore; - } - return true; -} - -bool GxsReputation::update() -{ - mOverallScore = mIdScore + mOwnOpinion + mPeerOpinion; - return true; -} - - -bool SSGxsIdReputation::load(const std::string &input) -{ - return (4 == sscanf(input.c_str(), "%d %d %d %d", - &(rep.mOverallScore), &(rep.mIdScore), &(rep.mOwnOpinion), &(rep.mPeerOpinion))); -} - -std::string SSGxsIdReputation::save() const -{ - std::string output; - rs_sprintf(output, "%d %d %d %d", rep.mOverallScore, rep.mIdScore, rep.mOwnOpinion, rep.mPeerOpinion); - return output; -} - - -bool SSGxsIdCumulator::load(const std::string &input) -{ - return (4 == sscanf(input.c_str(), "%d %d %lf %lf", &count, &nullcount, &sum, &sumsq)); -} - -std::string SSGxsIdCumulator::save() const -{ - std::string output; - rs_sprintf(output, "%d %d %lf %lf", count, nullcount, sum, sumsq); - return output; -} - -bool SSGxsIdGroup::load(const std::string &input) -{ - char pgpstr[RSGXSID_MAX_SERVICE_STRING]; - char recognstr[RSGXSID_MAX_SERVICE_STRING]; - char scorestr[RSGXSID_MAX_SERVICE_STRING]; - - // split into parts. - if (3 != sscanf(input.c_str(), "v2 {P:%[^}]}{T:%[^}]}{R:%[^}]}", pgpstr, recognstr, scorestr)) - { -#ifdef DEBUG_SERVICE_STRING - std::cerr << "SSGxsIdGroup::load() Failed to extract 4 Parts"; - std::cerr << std::endl; -#endif // DEBUG_IDS - return false; - } - - bool ok = true; - if (pgp.load(pgpstr)) - { -#ifdef DEBUG_SERVICE_STRING - std::cerr << "SSGxsIdGroup::load() pgpstr: " << pgpstr; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { -#ifdef DEBUG_SERVICE_STRING - std::cerr << "SSGxsIdGroup::load() Invalid pgpstr: " << pgpstr; - std::cerr << std::endl; -#endif // DEBUG_IDS - ok = false; - } - - if (recogntags.load(recognstr)) - { -#ifdef DEBUG_RECOGN - std::cerr << "SSGxsIdGroup::load() recognstr: " << recognstr; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - } - else - { -#ifdef DEBUG_RECOGN - std::cerr << "SSGxsIdGroup::load() Invalid recognstr: " << recognstr; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - ok = false; - } - - if (score.load(scorestr)) - { -#ifdef DEBUG_SERVICE_STRING - std::cerr << "SSGxsIdGroup::load() scorestr: " << scorestr; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { -#ifdef DEBUG_SERVICE_STRING - std::cerr << "SSGxsIdGroup::load() Invalid scorestr: " << scorestr; - std::cerr << std::endl; -#endif // DEBUG_IDS - ok = false; - } - -#if 0 - if (opinion.load(opinionstr)) - { -#ifdef DEBUG_IDS - std::cerr << "SSGxsIdGroup::load() opinionstr: " << opinionstr; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { -#ifdef DEBUG_IDS - std::cerr << "SSGxsIdGroup::load() Invalid opinionstr: " << opinionstr; - std::cerr << std::endl; -#endif // DEBUG_IDS - ok = false; - } - - if (reputation.load(repstr)) - { -#ifdef DEBUG_IDS - std::cerr << "SSGxsIdGroup::load() repstr: " << repstr; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { -#ifdef DEBUG_IDS - std::cerr << "SSGxsIdGroup::load() Invalid repstr: " << repstr; - std::cerr << std::endl; -#endif // DEBUG_IDS - ok = false; - } -#endif - -#ifdef DEBUG_IDS - std::cerr << "SSGxsIdGroup::load() regurgitated: " << save(); - std::cerr << std::endl; - - std::cerr << "SSGxsIdGroup::load() isOkay?: " << ok; - std::cerr << std::endl; -#endif // DEBUG_IDS - return ok; -} - -std::string SSGxsIdGroup::save() const -{ - std::string output = "v2 "; - - output += "{P:"; - output += pgp.save(); - output += "}"; - - output += "{T:"; - output += recogntags.save(); - output += "}"; - - output += "{R:"; - output += score.save(); - output += "}"; - - //std::cerr << "SSGxsIdGroup::save() output: " << output; - //std::cerr << std::endl; - - return output; -} - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -/* Cache of recently used keys - * - * It is expensive to fetch the keys, so we want to keep them around if possible. - * It only stores the immutable stuff. - * - * This is probably crude and crap to start with. - * Want Least Recently Used (LRU) discard policy, without having to search whole cache. - * Use two maps: - * - CacheMap[key] => data. - * - LRUMultiMap[AccessTS] => key - * - * NOTE: This could be moved to a seperate class and templated to make generic - * as it might be generally useful. - * - */ - -RsGxsIdCache::RsGxsIdCache() {} - -RsGxsIdCache::RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pkey, const std::list &tagList) -{ - init(item,in_pkey,RsTlvPrivateRSAKey(),tagList) ; -} - -RsGxsIdCache::RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pkey, const RsTlvPrivateRSAKey& privkey, const std::list &tagList) -{ - init(item,in_pkey,privkey,tagList) ; -} - -void RsGxsIdCache::init(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pub_key, const RsTlvPrivateRSAKey& in_priv_key,const std::list &tagList) -{ - // Save Keys. - pub_key = in_pub_key; - priv_key = in_priv_key; - - // Save Time for ServiceString comparisions. - mPublishTs = item->meta.mPublishTs; - - // Save RecognTags. - mRecognTags = tagList; - - details.mAvatar.copy((uint8_t *) item->mImage.binData.bin_data, item->mImage.binData.bin_len); - - // Fill in Details. - details.mNickname = item->meta.mGroupName; - details.mId = RsGxsId(item->meta.mGroupId); - -#ifdef DEBUG_IDS - std::cerr << "RsGxsIdCache::RsGxsIdCache() for: " << details.mId; - std::cerr << std::endl; -#endif // DEBUG_IDS - - details.mFlags = 0 ; - - if(item->meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) details.mFlags |= RS_IDENTITY_FLAGS_IS_OWN_ID; - if(item->meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility) details.mFlags |= RS_IDENTITY_FLAGS_PGP_LINKED; - - // do some tests - if(details.mFlags & RS_IDENTITY_FLAGS_IS_OWN_ID) - { - if(!priv_key.checkKey()) - std::cerr << "(EE) Private key missing for own identity " << pub_key.keyId << std::endl; - - } - if(!pub_key.checkKey()) - std::cerr << "(EE) Public key missing for identity " << pub_key.keyId << std::endl; - - if(!GxsSecurity::checkFingerprint(pub_key)) - details.mFlags |= RS_IDENTITY_FLAGS_IS_DEPRECATED; - - /* rest must be retrived from ServiceString */ - updateServiceString(item->meta.mServiceString); -} - -void RsGxsIdCache::updateServiceString(std::string serviceString) -{ - details.mRecognTags.clear(); - - SSGxsIdGroup ssdata; - if (ssdata.load(serviceString)) - { - if (details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) - { - if(ssdata.pgp.validatedSignature) details.mFlags |= RS_IDENTITY_FLAGS_PGP_KNOWN ; - - if (details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) - details.mPgpId = ssdata.pgp.pgpId; - else - details.mPgpId.clear(); - } - - - // process RecognTags. - if (ssdata.recogntags.tagsProcessed()) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsGxsIdCache::updateServiceString() updating recogntags"; - std::cerr << std::endl; -#endif - if (ssdata.recogntags.publishTs == mPublishTs) - { - std::list::iterator it; - int i = 0; - for(it = mRecognTags.begin(); it != mRecognTags.end(); ++it, i++) - { - if (ssdata.recogntags.tagValid(i) && it->valid) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsGxsIdCache::updateServiceString() Valid Tag: " << it->tag_class << ":" << it->tag_type; - std::cerr << std::endl; -#endif - details.mRecognTags.push_back(*it); - } - else - { -#ifdef DEBUG_RECOGN - std::cerr << "RsGxsIdCache::updateServiceString() Invalid Tag: " << it->tag_class << ":" << it->tag_type; - std::cerr << std::endl; -#endif - } - } - } - else - { -#ifdef DEBUG_RECOGN - std::cerr << "RsGxsIdCache::updateServiceString() recogntags old publishTs"; - std::cerr << std::endl; -#endif - } - - } - else - { -#ifdef DEBUG_RECOGN - std::cerr << "RsGxsIdCache::updateServiceString() recogntags unprocessed"; - std::cerr << std::endl; -#endif - } - - // copy over Reputation scores. - //details.mReputation = ssdata.score.rep; - } - else - { - details.mFlags &= ~RS_IDENTITY_FLAGS_PGP_KNOWN ; - details.mPgpId.clear(); - //details.mReputation.updateIdScore(false, false); - //details.mReputation.update(); - } -} - - -bool p3IdService::recogn_extract_taginfo(const RsGxsIdGroupItem *item, std::list &tagItems) -{ -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_extract_taginfo()"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - /* process Recogn Tags */ - - std::list::const_iterator rit; - int count = 0; - for(rit = item->mRecognTags.begin(); rit != item->mRecognTags.end(); ++rit) - { - if (++count > RSRECOGN_MAX_TAGINFO) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_extract_taginfo() Too many tags."; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - return true; - } - - RsGxsRecognTagItem *tagitem = RsRecogn::extractTag(*rit); - - if (!tagitem) - { - continue; - } - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_extract_taginfo() Got TagItem: "; - std::cerr << std::endl; - tagitem->print(std::cerr); -#endif // DEBUG_RECOGN - - tagItems.push_back(tagitem); - } - return true; -} - - -bool p3IdService::cache_process_recogntaginfo(const RsGxsIdGroupItem *item, std::list &tagList) -{ - /* ServiceString decode */ - SSGxsIdGroup ssdata; - bool recognProcess = false; - if (ssdata.load(item->meta.mServiceString)) - { - if (!ssdata.recogntags.tagsProcessed()) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::cache_process_recogntaginfo() tags not processed"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - /* we need to reprocess it */ - recognProcess = true; - } - else - { - if (item->meta.mPublishTs != ssdata.recogntags.publishTs) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::cache_process_recogntaginfo() publishTs old"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - recognProcess = true; - } - else if (ssdata.recogntags.tagsPending()) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::cache_process_recogntaginfo() tagsPending"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - /* reprocess once a day */ - recognProcess = true; - } - } - } - else - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::cache_process_recogntaginfo() ServiceString invalid"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - recognProcess = true; - } - - std::list tagItems; - std::list::iterator it; - - recogn_extract_taginfo(item, tagItems); - - //rstime_t now = time(NULL); - for(it = tagItems.begin(); it != tagItems.end(); ++it) - { - RsRecognTag info((*it)->tag_class, (*it)->tag_type, false); - bool isPending = false; - if (recogn_checktag(RsGxsId(item->meta.mGroupId.toStdString()), item->meta.mGroupName, *it, false, isPending)) - { - info.valid = true; - } -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::cache_process_recogntaginfo() Adding Tag: "; - std::cerr << info.tag_class << ":"; - std::cerr << info.tag_type << ":"; - std::cerr << info.valid; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - tagList.push_back(info); - delete *it; - } - - - if (recognProcess) - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - mRecognGroupIds.push_back(item->meta.mGroupId); - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::cache_process_recogntaginfo() Reprocessing groupId: "; - std::cerr << item->meta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - recogn_schedule(); - } - - return true; -} - -// Loads in the cache the group data from the given group item, retrieved from sqlite storage. - -bool p3IdService::cache_store(const RsGxsIdGroupItem *item) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_store() Item: " << item->meta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_IDS - //item->print(std::cerr, 0); NEEDS CONST!!!! TODO - //std::cerr << std::endl; - - /* extract key from keys */ - RsTlvSecurityKeySet keySet; - - RsTlvPublicRSAKey pubkey; - RsTlvPrivateRSAKey fullkey; - - bool pub_key_ok = false; - bool full_key_ok = false; - - RsGxsId id (item->meta.mGroupId.toStdString()); - - if (!getGroupKeys(RsGxsGroupId(id.toStdString()), keySet)) - { - std::cerr << "p3IdService::cache_store() ERROR getting GroupKeys for: "<< item->meta.mGroupId << std::endl; - return false; - } - - for (std::map::iterator kit = keySet.private_keys.begin(); kit != keySet.private_keys.end(); ++kit) - if (kit->second.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_store() Found Admin Key" << std::endl; -#endif - fullkey = kit->second; - full_key_ok = true; - } - for (std::map::iterator kit = keySet.public_keys.begin(); kit != keySet.public_keys.end(); ++kit) - if (kit->second.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_store() Found Admin public Key" << std::endl; -#endif - pubkey = kit->second; - pub_key_ok = true ; - } - - assert(!( pubkey.keyFlags & RSTLV_KEY_TYPE_FULL)) ; - assert(!full_key_ok || (fullkey.keyFlags & RSTLV_KEY_TYPE_FULL)) ; - - if (!pub_key_ok) - { - std::cerr << "p3IdService::cache_store() ERROR No Public Key Found"; - std::cerr << std::endl; - return false; - } - - // extract tags. - std::list tagList; - cache_process_recogntaginfo(item, tagList); - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - // Create Cache Data. - RsGxsIdCache keycache(item, pubkey, fullkey,tagList); - - if(mContacts.find(id) != mContacts.end()) - keycache.details.mFlags |= RS_IDENTITY_FLAGS_IS_A_CONTACT; - - mKeyCache.store(id, keycache); - mKeyCache.resize(); - - return true; -} - - - -/***** BELOW LOADS THE CACHE FROM GXS DATASTORE *****/ - -#define MIN_CYCLE_GAP 2 - -bool p3IdService::cache_request_load(const RsGxsId &id, const std::list &peers) -{ - Dbg4() << __PRETTY_FUNCTION__ << " id: " << id << std::endl; - - { - RS_STACK_MUTEX(mIdMtx); - // merge, even if peers is empty - mergeIds(mCacheLoad_ToCache, id, peers); - } - - if(RsTickEvent::event_count(GXSID_EVENT_CACHELOAD) > 0) - { - Dbg3() << __PRETTY_FUNCTION__ << " cache reload already scheduled " - << "skipping" << std::endl; - return true; - } - - int32_t age = 0; - if( RsTickEvent::prev_event_ago(GXSID_EVENT_CACHELOAD, age) && age < MIN_CYCLE_GAP ) - { - RsTickEvent::schedule_in(GXSID_EVENT_CACHELOAD, MIN_CYCLE_GAP - age); - return true; - } - - RsTickEvent::schedule_now(GXSID_EVENT_CACHELOAD); - return true; -} - - -bool p3IdService::cache_start_load() -{ - /* trigger request to load missing ids into cache */ - std::list groupIds; - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - /* now we process the modGroupList -> a map so we can use it easily later, and create id list too */ - std::map >::iterator it; - for(it = mCacheLoad_ToCache.begin(); it != mCacheLoad_ToCache.end(); ++it) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_start_load() GroupId: " << it->first; - std::cerr << std::endl; -#endif // DEBUG_IDS - groupIds.push_back(RsGxsGroupId(it->first)); // might need conversion? - } - - for(std::map >::const_iterator it(mCacheLoad_ToCache.begin());it!=mCacheLoad_ToCache.end();++it) - mergeIds(mPendingCache,it->first,it->second) ; - - mCacheLoad_ToCache.clear(); - } - - if (groupIds.size() > 0) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_start_load() #Groups: " << groupIds.size(); - std::cerr << std::endl; -#endif // DEBUG_IDS - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts, groupIds); - GxsTokenQueue::queueRequest(token, GXSIDREQ_CACHELOAD); - } - return 1; -} - - -bool p3IdService::cache_load_for_token(uint32_t token) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_load_for_token() : " << token; - std::cerr << std::endl; -#endif // DEBUG_IDS - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsIdGroupItem* item = dynamic_cast(*vit); - if (!item) - { - std::cerr << "Not a RsGxsIdGroupItem Item, deleting!" << std::endl; - delete(*vit); - continue; - } - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_load_for_token() Loaded Id with Meta: "; - std::cerr << item->meta; - std::cerr << std::endl; -#endif // DEBUG_IDS - - - { - // remove identities that are present - RsStackMutex stack(mIdMtx); - mPendingCache.erase(RsGxsId(item->meta.mGroupId.toStdString())); - } - - /* cache the data */ - cache_store(item); - delete item; - } - - { - // now store identities that aren't present - - RsStackMutex stack(mIdMtx); - - // No need to merge empty peers since the request would fail. - - for(std::map >::const_iterator itt(mPendingCache.begin());itt!=mPendingCache.end();++itt) - if(!itt->second.empty()) - mergeIds(mIdsNotPresent,itt->first,itt->second) ; -#ifdef DEBUG_IDS - else - std::cerr << "(WW) empty list of peers to request ID " << itt->first << ": cannot request" << std::endl; -#endif - - - mPendingCache.clear(); - - if(!mIdsNotPresent.empty()) - schedule_now(GXSID_EVENT_REQUEST_IDS); - } - - } - else - { - std::cerr << "p3IdService::cache_load_for_token() ERROR no data"; - std::cerr << std::endl; - - return false; - } - return true; -} - -void p3IdService::requestIdsFromNet() -{ - RS_STACK_MUTEX(mIdMtx); - - if(!mNes) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot request missing GXS IDs " - << "because network service is not present." << std::endl; - return; - } - - std::map >::iterator cit; - std::map > requests; - - /* Transform to appropriate structure ( > map) - * to make request to nes per peer ID - * Only delete entries in mIdsNotPresent that can actually be performed, or - * that have empty peer list */ - - for(cit = mIdsNotPresent.begin(); cit != mIdsNotPresent.end();) - { -#ifdef DEBUG_IDS - Dbg2() << __PRETTY_FUNCTION__ << " Processing missing key RsGxsId: " << cit->first << std::endl; -#endif - RsGxsIdCache data; - - if(mKeyCache.fetch(cit->first,data)) - { -#ifdef DEBUG_IDS - std::cerr << __PRETTY_FUNCTION__ << ". Dropping request for ID " << cit->first << " at last minute, because it was found in cache"<< std::endl; -#endif - auto tmp(cit); - ++tmp; - mIdsNotPresent.erase(cit); - cit = tmp; - continue; - } - - const RsGxsId& gxsId = cit->first; - const std::list& peers = cit->second; - std::list::const_iterator cit2; - - bool request_can_proceed = false ; - - for(cit2 = peers.begin(); cit2 != peers.end(); ++cit2) - { - const RsPeerId& peer = *cit2; - - if(rsPeers->isOnline(peer) || mNes->isDistantPeer(peer)) - { - /* make sure that the peer in online, so that we know that the - * request has some chance to succeed.*/ - requests[peer].push_back(cit->first); - request_can_proceed = true ; - -#ifdef DEBUG_IDS - Dbg2() << __PRETTY_FUNCTION__ << " Moving missing key RsGxsId:" - << gxsId << " to peer: " << peer << " requests queue" - << std::endl; -#endif - } - } - - const bool noPeersFound = peers.empty(); - if(noPeersFound) - RsWarn() << __PRETTY_FUNCTION__ << " No peers supplied to request " - << "RsGxsId: " << gxsId << " dropping." << std::endl; - - if(request_can_proceed || noPeersFound) - { - std::map >::iterator tmp(cit); - ++tmp; - mIdsNotPresent.erase(cit); - cit = tmp; - } - else - { -#ifdef DEBUG_IDS - RsInfo() << __PRETTY_FUNCTION__ << " no online peers among supplied" - << " list in request for RsGxsId: " << gxsId - << ". Keeping it until peers show up."<< std::endl; -#endif - ++cit; - } - } - - for( std::map >::const_iterator cit2( - requests.begin() ); cit2 != requests.end(); ++cit2 ) - { - const RsPeerId& peer = cit2->first; - std::list grpIds; - for( std::list::const_iterator gxs_id_it = cit2->second.begin(); gxs_id_it != cit2->second.end(); ++gxs_id_it ) - { -#ifdef DEBUG_IDS - Dbg2() << __PRETTY_FUNCTION__ << " passing RsGxsId: " << *gxs_id_it - << " request for peer: " << peer - << " to RsNetworkExchangeService " << std::endl; -#endif - grpIds.push_back(RsGxsGroupId(*gxs_id_it)); - } - - mNes->requestGrp(grpIds, peer); - } -} - -bool p3IdService::cache_update_if_cached(const RsGxsId &id, std::string serviceString) -{ - /* if these entries are cached - update with new info */ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_update_if_cached(" << id << ")"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - /* retrieve - update, save */ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - RsGxsIdCache updated_data; - - if(mKeyCache.fetch(id, updated_data)) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_update_if_cached() Updating Public Cache"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - updated_data.updateServiceString(serviceString); - - mKeyCache.store(id, updated_data); - } - - return true; -} - -/************************************************************************************/ -/************************************************************************************/ - -bool p3IdService::cache_request_ownids() -{ - /* trigger request to load missing ids into cache */ - std::list groupIds; -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_request_ownids()"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - //opts.mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN; - - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, GXSIDREQ_CACHEOWNIDS); - return true; -} - - -bool p3IdService::cache_load_ownids(uint32_t token) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_load_ownids() : " << token; - std::cerr << std::endl; -#endif // DEBUG_IDS - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - // Save List - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - mOwnIds.clear(); - for(vit = grpData.begin(); vit != grpData.end(); ++vit) - { - RsGxsIdGroupItem* item = dynamic_cast(*vit); - if (!item) - { - std::cerr << "Not a IdOpinion Item, deleting!" << std::endl; - delete(*vit); - continue; - } - - if (item->meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) - { - mOwnIds.push_back(RsGxsId(item->meta.mGroupId)); - - SSGxsIdGroup ssdata; - - std::cerr << "Adding own ID " << item->meta.mGroupId << " mGroupFlags=" << std::hex << item->meta.mGroupFlags << std::dec; - - if (ssdata.load(item->meta.mServiceString) && ssdata.pgp.validatedSignature) // (cyril) note: we cannot use if(item->meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) - { // or we need to cmbine it with the deprecated value that overlaps with GXS_SERV::FLAG_PRIVACY_PRIVATE - std::cerr << " signed = YES" << std::endl; // see comments line 799 in ::createIdentity(); - mOwnSignedIds.push_back(RsGxsId(item->meta.mGroupId)); - } - else - std::cerr << " signed = NO" << std::endl; - - // This prevents automatic deletion to get rid of them. - // In other words, own ids are always used. - - mKeysTS[RsGxsId(item->meta.mGroupId)].TS = time(NULL) ; - } - delete item ; - } - mOwnIdsLoaded = true ; - - std::cerr << mOwnIds.size() << " own Ids loaded, " << mOwnSignedIds.size() << " of which are signed" << std::endl; - } - - // No need to cache these items... - // as it just causes the cache to be flushed. -#if 0 - // Cache Items too. - for(vit = grpData.begin(); vit != grpData.end(); ++vit) - { - RsGxsIdGroupItem* item = dynamic_cast(*vit); - if (item->meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) - { - - std::cerr << "p3IdService::cache_load_ownids() Loaded Id with Meta: "; - std::cerr << item->meta; - std::cerr << std::endl; - - /* cache the data */ - cache_store(item); - } - delete item; - } -#endif - - } - else - { - std::cerr << "p3IdService::cache_load_ownids() ERROR no data"; - std::cerr << std::endl; - - return false; - } - return true; -} - -/************************************************************************************/ -/************************************************************************************/ - -bool p3IdService::cachetest_getlist() -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_getlist() making request"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, GXSIDREQ_CACHETEST); - - // Schedule Next Event. - RsTickEvent::schedule_in(GXSID_EVENT_CACHETEST, CACHETEST_PERIOD); - return true; -} - -bool p3IdService::cachetest_handlerequest(uint32_t token) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_handlerequest() token: " << token; - std::cerr << std::endl; -#endif // DEBUG_IDS - - std::list grpIds; - std::list grpIdsC; - bool ok = RsGenExchange::getGroupList(token, grpIdsC); - - std::list::const_iterator cit = grpIdsC.begin(); - for(; cit != grpIdsC.end(); ++cit) - grpIds.push_back(RsGxsId(cit->toStdString())); - - if(ok) - { - std::list::iterator vit = grpIds.begin(); - for(; vit != grpIds.end(); ++vit) - { - /* 5% chance of checking it! */ - if (RSRandom::random_f32() < 0.25) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_request() Testing Id: " << *vit; - std::cerr << std::endl; -#endif // DEBUG_IDS - - /* try the cache! */ - if (!haveKey(*vit)) - { - std::list nullpeers; - requestKey(*vit, nullpeers,RsIdentityUsage(RsServiceType::GXSID,RsIdentityUsage::UNKNOWN_USAGE)); - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_request() Requested Key Id: " << *vit; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { - RsTlvPublicRSAKey seckey; - if (getKey(*vit, seckey)) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_request() Got Key OK Id: " << *vit; - std::cerr << std::endl; -#endif // DEBUG_IDS - - // success! - seckey.print(std::cerr, 10); - std::cerr << std::endl; - - - } - else - { - std::cerr << "p3IdService::cachetest_request() ERROR no Key for Id: " << *vit; - std::cerr << std::endl; - } - } - - /* try private key too! */ - if (!havePrivateKey(*vit)) - { - requestPrivateKey(*vit); -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_request() Requested PrivateKey Id: " << *vit; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { - RsTlvPrivateRSAKey seckey; - if (getPrivateKey(*vit, seckey)) - { - // success! -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_request() Got PrivateKey OK Id: " << *vit; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { - std::cerr << "p3IdService::cachetest_request() ERROR no PrivateKey for Id: " << *vit; - std::cerr << std::endl; - } - } - } - } - } - else - { - std::cerr << "p3IdService::cache_load_for_token() ERROR no data"; - std::cerr << std::endl; - - return false; - } - return true; -} - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -/* - * We have three background tasks that use the ServiceString: PGPHash & Reputation & Recogn - * - * Only one task can be run at a time - otherwise potential overwrite issues. - * So this part coordinates that part of the code. - * - * We are going to have a "fetcher task", which gets all the UNPROCESSED / UPDATED GROUPS. - * and sets the CHECK_PGP, CHECK_RECOGN, etc... this will reduce the "Get All" calls. - * - */ - - -bool p3IdService::CacheArbitration(uint32_t mode) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - if (!mBgSchedule_Active) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::CacheArbitration() Okay: mode " << mode; - std::cerr << std::endl; -#endif // DEBUG_IDS - - mBgSchedule_Active = true; - mBgSchedule_Mode = mode; - return true; - } - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::CacheArbitration() Is busy in mode: " << mBgSchedule_Mode; - std::cerr << std::endl; -#endif // DEBUG_IDS - - return false; -} - -void p3IdService::CacheArbitrationDone(uint32_t mode) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - if (mBgSchedule_Mode != mode) - { - /* issues */ - std::cerr << "p3IdService::CacheArbitrationDone() ERROR Wrong Current Mode"; - std::cerr << std::endl; - return; - } - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::CacheArbitrationDone()"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - mBgSchedule_Active = false; -} - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -/* Task to determine PGPHash matches - * - * Info to be stored in GroupServiceString + Cache. - * - * Actually - it must be a Signature here - otherwise, you could - * put in a hash from someone else! - * - * Don't think that we need to match very often - maybe once a day? - * Actually - we should scale the matching based on number of keys we have. - * - * imagine - 10^6 rsa keys + 10^3 gpg keys => 10^9 combinations. - * -- far too many to check all quickly. - * - * Need to grab and cache data we need... then check over slowly. - * - * maybe grab a list of all gpgids - that we know of: store id list. - * then big GroupRequest, and iterate through these. - **/ - -//const int SHA_DIGEST_LENGTH = 20; - -static void calcPGPHash(const RsGxsId &id, const PGPFingerprintType &pgp, Sha1CheckSum &hash); - - -// Must Use meta. -RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup( - RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet ) -{ - Dbg2() << __PRETTY_FUNCTION__ << std::endl; - - RsGxsIdGroupItem *item = dynamic_cast(grpItem); - if (!item) - { - std::cerr << "p3IdService::service_CreateGroup() ERROR invalid cast"; - std::cerr << std::endl; - return SERVICE_CREATE_FAIL; - } - - item->meta.mGroupId.clear(); - - /********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/ - // find private admin key - for( std::map::iterator mit = - 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); - break; - } - - if(item->meta.mGroupId.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " missing admin key!" << std::endl; - return SERVICE_CREATE_FAIL; - } - mKeysTS[RsGxsId(item->meta.mGroupId)].TS = time(NULL) ; - - /********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/ - - // SANITY CHECK. - // if (item->mMeta.mAuthorId != item->meta.mAuthorId) - // { - // std::cerr << "p3IdService::service_CreateGroup() AuthorId mismatch("; - // std::cerr << item->mMeta.mAuthorId; - // std::cerr << " vs "; - // std::cerr << item->meta.mAuthorId; - // std::cerr << std::endl; - // } - // - // if (item->group.mMeta.mGroupId != item->meta.mGroupId) - // { - // std::cerr << "p3IdService::service_CreateGroup() GroupId mismatch("; - // std::cerr << item->mMeta.mGroupId; - // std::cerr << " vs "; - // std::cerr << item->meta.mGroupId; - // std::cerr << std::endl; - // } - // - // - // if (item->group.mMeta.mGroupFlags != item->meta.mGroupFlags) - // { - // std::cerr << "p3IdService::service_CreateGroup() GroupFlags mismatch("; - // std::cerr << item->mMeta.mGroupFlags; - // std::cerr << " vs "; - // std::cerr << item->meta.mGroupFlags; - // std::cerr << std::endl; - // } - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::service_CreateGroup() for : " << item->meta.mGroupId; - std::cerr << std::endl; - std::cerr << "p3IdService::service_CreateGroup() Alt GroupId : " << item->meta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_IDS - - ServiceCreate_Return createStatus; - - if (item->meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility) - { - /* create the hash */ - Sha1CheckSum hash; - - RsPgpFingerprint ownFinger; - RsPgpId ownId(mPgpUtils->getPGPOwnId()); - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::service_CreateGroup() OwnPgpID: " << ownId.toStdString(); - std::cerr << std::endl; -#endif - -#ifdef GXSID_GEN_DUMMY_DATA - // if (item->group.mMeta.mAuthorId != "") - // { - // ownId = RsPgpId(item->group.mMeta.mAuthorId); - // } -#endif - - if(!mPgpUtils->getKeyFingerprint(ownId,ownFinger)) - { - RsErr() << __PRETTY_FUNCTION__ - << " failure retriving own PGP fingerprint" << std::endl; - return SERVICE_CREATE_FAIL; // abandon attempt! - } - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::service_CreateGroup() OwnFingerprint: " << ownFinger.toStdString(); - std::cerr << std::endl; -#endif - - RsGxsId gxsId(item->meta.mGroupId.toStdString()); - calcPGPHash(gxsId, ownFinger, hash); - item->mPgpIdHash = hash; - -#ifdef DEBUG_IDS - - std::cerr << "p3IdService::service_CreateGroup() Calculated PgpIdHash : " << item->mPgpIdHash; - std::cerr << std::endl; -#endif // DEBUG_IDS - - /* do signature */ - - -#define MAX_SIGN_SIZE 2048 - uint8_t signarray[MAX_SIGN_SIZE]; - unsigned int sign_size = MAX_SIGN_SIZE; - memset(signarray,0,MAX_SIGN_SIZE) ; // just in case. - - int result = AuthGPG::getAuthGPG()->SignDataBin( - static_cast(hash.toByteArray()), - hash.SIZE_IN_BYTES, signarray, &sign_size, - __PRETTY_FUNCTION__ ) - ? - SELF_SIGNATURE_RESULT_SUCCESS : - SELF_SIGNATURE_RESULT_FAILED; - - switch(result) - { - case SELF_SIGNATURE_RESULT_PENDING: - createStatus = SERVICE_CREATE_FAIL_TRY_LATER; - Dbg1() << __PRETTY_FUNCTION__ << " signature still pending" - << std::endl; - break; - case SELF_SIGNATURE_RESULT_SUCCESS: - { - // Additional consistency checks. - if(sign_size == MAX_SIGN_SIZE) - { - RsErr() << __PRETTY_FUNCTION__ << "Inconsistent result. " - << "Signature uses full buffer. This is probably an " - << "error." << std::endl; - return SERVICE_CREATE_FAIL; - } - - /* push binary into string -> really bad! */ - item->mPgpIdSign = ""; - for(unsigned int i = 0; i < sign_size; i++) - item->mPgpIdSign += static_cast(signarray[i]); - - createStatus = SERVICE_CREATE_SUCCESS; - break; - } - case SELF_SIGNATURE_RESULT_FAILED: /* fall-through */ - default: - RsErr() << __PRETTY_FUNCTION__ << " signature failed with: " - << result << std::endl; - return SERVICE_CREATE_FAIL; - } - } - else createStatus = SERVICE_CREATE_SUCCESS; - - // Enforce no AuthorId. - item->meta.mAuthorId.clear() ; - //item->mMeta.mAuthorId.clear() ; - // copy meta data to be sure its all the same. - //item->group.mMeta = item->meta; - - // do it like p3gxscircles: save the new grp id - // this allows the user interface - // to see the grp id on the list of ownIds immediately after the group was created - { - RS_STACK_MUTEX(mIdMtx); - RsGxsId gxsId(item->meta.mGroupId); - if (std::find(mOwnIds.begin(), mOwnIds.end(), gxsId) == mOwnIds.end()) - { - mOwnIds.push_back(gxsId); - mKeysTS[gxsId].TS = time(nullptr); - } - } - -#ifdef DEBUG_IDS - Dbg2() << __PRETTY_FUNCTION__ << " returns: " << createStatus << std::endl; -#endif - return createStatus; -} - - -#define HASHPGP_PERIOD 180 - - -bool p3IdService::pgphash_start() -{ - if (!CacheArbitration(BG_PGPHASH)) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_start() Other Events running... Rescheduling"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - /* reschedule in a bit */ - RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH, PGPHASH_RETRY_PERIOD); - return false; - } - - // SCHEDULE NEXT ONE. - RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH, PGPHASH_PERIOD); - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_start() making request"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - // ACTUALLY only need summary - but have written code for data. - // Also need to use opts.groupFlags to filter stuff properly to REALID's only. - // TODO - - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, GXSIDREQ_PGPHASH); - - return true; -} - - -bool p3IdService::pgphash_handlerequest(uint32_t token) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_handlerequest(" << token << ")"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - // We need full data - for access to Hash & Signature. - // Perhaps we will change this to an initial pass through Meta, - // and use this to discard lots of things. - - // Even better - we can set flags in the Meta Data, (IdType), - // And use GXS to filter out all the AnonIds, and only have to process - // Proper Ids. - - // We Will do this later! - - std::list group_metas; - std::list groups_to_process; - bool ok = getGroupMeta(token, group_metas); - - if(ok) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_request() Have " << group_metas.size() << " Groups" << std::endl; -#endif // DEBUG_IDS - - for(auto vit = group_metas.begin(); vit != group_metas.end(); ++vit) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_request() Group Id: " << vit->mGroupId << " "; -#endif // DEBUG_IDS - - /* Filter based on IdType */ - - if (!(vit->mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility)) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_request() discarding AnonID" << std::endl; -#endif // DEBUG_IDS - continue; - } - - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - if(mGroupsToProcess.find(vit->mGroupId) != mGroupsToProcess.end()) - { -#ifdef DEBUG_IDS - std::cerr << " => already in checking list!" << std::endl; -#endif - continue; - } - } - - /* now we need to decode the Service String - see what is saved there */ - SSGxsIdGroup ssdata; - - if (ssdata.load(vit->mServiceString)) - { - if (ssdata.pgp.validatedSignature) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_request() discarding Already Known" << std::endl; -#endif // DEBUG_IDS - continue; - } - - /* Have a linear attempt policy - - * if zero checks - try now. - * if 1 check, at least a day. - * if 2 checks: 2days, etc. - */ - -#define SECS_PER_DAY (3600 * 24) - rstime_t age = time(NULL) - ssdata.pgp.lastCheckTs; - rstime_t wait_period = ssdata.pgp.checkAttempts * SECS_PER_DAY; - - if (wait_period > 30 * SECS_PER_DAY) - wait_period = 30 * SECS_PER_DAY; - -#ifdef DEBUG_IDS - std::cerr << "p3IdService: group " << *vit << " age=" << age << ", attempts=" << ssdata.pgp.checkAttempts << ", wait period = " << wait_period ; -#endif - - if (age < wait_period) - { -#ifdef DEBUG_IDS - std::cerr << " => discard." << std::endl; -#endif // DEBUG_IDS - continue; - } - - -#ifdef DEBUG_IDS - std::cerr << " => recheck!" << std::endl; -#endif - } - - /* if we get here -> then its to be processed */ - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - groups_to_process.push_back(vit->mGroupId); - } - } - else - { - std::cerr << "p3IdService::pgphash_request() getGroupData ERROR"; - std::cerr << std::endl; - } - - // If they are groups to process, load the data for these groups - - if(!groups_to_process.empty()) - { - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts,groups_to_process); - GxsTokenQueue::queueRequest(token, GXSIDREQ_LOAD_PGPIDDATA); - } - - return true; -} - -bool p3IdService::pgphash_load_group_data(uint32_t token) -{ - // Update PgpIdList -> if there are groups to process. - - getPgpIdList(); - std::vector groups; - - // Add the loaded groups into the list of groups to process - - getGroupData(token, groups); - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - for(auto grp:groups) - { - mGroupsToProcess[grp.mMeta.mGroupId] = grp; -#ifdef DEBUG_IDS - std::cerr << "pgphash_load_group_data(): loaded group data for group " << grp.mMeta.mGroupId << ". mGroupsToProcess contains " << mGroupsToProcess.size() << " elements." << std::endl; -#endif - } - - return true; -} - -bool p3IdService::pgphash_process() -{ - /* each time this is called - process one Id from mGroupsToProcess */ - RsGxsIdGroup pg; - bool isDone = false; - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - if (!mGroupsToProcess.empty()) - { - pg = mGroupsToProcess.begin()->second; - mGroupsToProcess.erase(mGroupsToProcess.begin()); - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_process() Popped Group: " << pg.mMeta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - isDone = true; - } - - if (isDone) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_process() List Empty... Done"; - std::cerr << std::endl; -#endif // DEBUG_IDS - // FINISHED. - CacheArbitrationDone(BG_PGPHASH); - return true; - } - - - SSGxsIdGroup ssdata; - ssdata.load(pg.mMeta.mServiceString); // attempt load - okay if fails. - - RsPgpId pgpId; - bool error = false ; - - if (checkId(pg, pgpId,error)) - { - /* found a match - update everything */ - /* Consistency issues here - what if Reputation was recently updated? */ - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_process() CheckId Success for Group: " << pg.mMeta.mGroupId; - std::cerr << " PgpId: " << pgpId; - std::cerr << std::endl; -#endif // DEBUG_IDS - - /* update */ - ssdata.pgp.validatedSignature = true; - ssdata.pgp.pgpId = pgpId; - - } - else if(error) - { - std::cerr << "Identity has an invalid signature. It will be deleted." << std::endl; - - uint32_t token ; - deleteIdentity(token,pg) ; - } - else - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_process() No Match for Group: " << pg.mMeta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_IDS - - ssdata.pgp.lastCheckTs = time(NULL); - ssdata.pgp.checkAttempts++; - ssdata.pgp.pgpId = pgpId; // read from the signature, but not verified - } - - if(!error) - { - // update IdScore too. - ssdata.score.rep.updateIdScore(true, ssdata.pgp.validatedSignature); - ssdata.score.rep.update(); - - /* set new Group ServiceString */ - uint32_t dummyToken = 0; - std::string serviceString = ssdata.save(); - setGroupServiceString(dummyToken, pg.mMeta.mGroupId, serviceString); - - cache_update_if_cached(RsGxsId(pg.mMeta.mGroupId), serviceString); - } - return true; -} - -// This method allows to have a null issuer ID in the signature, in which case the signature is anonymous. -// The correct PGP key to check is looked for by bruteforcing -// -// grp.mPgpIdHash == SHA1( GroupId | PgpFingerPrint ) -// -// For now, this is probably never used because signed IDs use a clear signature. The advntage of hiding the -// ID has not been clearly demonstrated anyway, which allows to directly look for the ID in the list of -// known keys instead of computing tons of hashes. - -bool p3IdService::checkId(const RsGxsIdGroup &grp, RsPgpId &pgpId,bool& error) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::checkId() Starting Match Check for RsGxsId: "; - std::cerr << grp.mMeta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_IDS - - error = false ; - - /* some sanity checking... make sure hash is the right size */ - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::checkId() PgpIdHash is: " << grp.mPgpIdHash; - std::cerr << std::endl; -#endif // DEBUG_IDS - - /* iterate through and check hash */ - Sha1CheckSum hash; - -#ifdef DEBUG_IDS - std::string esign ; - Radix64::encode((unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(),esign) ; - std::cerr << "Checking group signature " << esign << std::endl; -#endif - RsPgpId issuer_id ; - RsPgpFingerprint pgp_fingerprint; - pgpId.clear() ; - - if(mPgpUtils->parseSignature((unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(),issuer_id) && !issuer_id.isNull()) - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - pgpId = issuer_id ; - - auto mit = mPgpFingerprintMap.find(issuer_id); - - if(mit == mPgpFingerprintMap.end()) - { -#ifdef DEBUG_IDS - std::cerr << "Issuer Id: " << issuer_id << " is not known. Key will be marked as non verified." << std::endl; -#endif - error = false; - return false; - } - calcPGPHash(RsGxsId(grp.mMeta.mGroupId), mit->second, hash); -#ifdef DEBUG_IDS - std::cerr << "Issuer from PGP signature: " << issuer_id << " is known. Computed corresponding hash: " << hash << std::endl; -#endif - if(grp.mPgpIdHash != hash) - { - std::cerr << "(EE) Unexpected situation: GxsId signature hash (" << hash << ") doesn't correspond to what's listed in the mPgpIdHash field (" << grp.mPgpIdHash << ")." << std::endl; - error = true; - return false; - } - pgp_fingerprint = mit->second; - } - else - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_IDS - std::cerr << "Bruteforcing PGP hash from GxsId mPgpHash: " << grp.mPgpIdHash << std::endl; -#endif - for(auto mit = mPgpFingerprintMap.begin(); mit != mPgpFingerprintMap.end(); ++mit) - { - calcPGPHash(RsGxsId(grp.mMeta.mGroupId), mit->second, hash); - - std::cerr << " profile key " << mit->first << " (" << mit->second << ") : "; - - if (grp.mPgpIdHash == hash) - { -#ifdef DEBUG_IDS - std::cerr << "MATCH!" << std::endl; -#endif - pgpId = mit->first; - pgp_fingerprint = mit->second; - break; - } -#ifdef DEBUG_IDS - else - std::cerr << "fails" << std::endl; -#endif - } - } - - // Look for the PGP id given by the signature - -#ifdef DEBUG_IDS - std::cerr << "Now checking the signature: "; -#endif - - if (mPgpUtils->VerifySignBin((void *) hash.toByteArray(), hash.SIZE_IN_BYTES, (unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(), pgp_fingerprint)) - { -#ifdef DEBUG_IDS - std::cerr << " Signature validates!" << std::endl; -#endif - error = false; - return true; - } - else - { -#ifdef DEBUG_IDS - std::cerr << " Signature fails!" << std::endl; -#endif - error = true; - return false; - } -} - -/* worker functions */ -void p3IdService::getPgpIdList() -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getPgpIdList() Starting...."; - std::cerr << std::endl; -#endif // DEBUG_IDS - - std::list list; - mPgpUtils->getGPGAllList(list); - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - mPgpFingerprintMap.clear(); - - std::list::iterator it; - for(it = list.begin(); it != list.end(); ++it) - { - RsPgpId pgpId(*it); - PGPFingerprintType fp; - mPgpUtils->getKeyFingerprint(pgpId, fp); - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getPgpIdList() Id: " << pgpId.toStdString() << " => " << fp.toStdString(); - std::cerr << std::endl; -#endif // DEBUG_IDS - - mPgpFingerprintMap[pgpId] = fp; - } - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getPgpIdList() Items: " << mPgpFingerprintMap.size(); - std::cerr << std::endl; -#endif // DEBUG_IDS -} - - -void calcPGPHash(const RsGxsId &id, const PGPFingerprintType &pgp, Sha1CheckSum &hash) -{ - unsigned char signature[SHA_DIGEST_LENGTH]; - /* hash id + pubkey => pgphash */ - SHA_CTX *sha_ctx = new SHA_CTX; - SHA1_Init(sha_ctx); - - SHA1_Update(sha_ctx, id.toStdString().c_str(), id.toStdString().length()); // TO FIX ONE DAY. - SHA1_Update(sha_ctx, pgp.toByteArray(), pgp.SIZE_IN_BYTES); - SHA1_Final(signature, sha_ctx); - hash = Sha1CheckSum(signature); - -#ifdef DEBUG_IDS - std::cerr << "calcPGPHash():"; - std::cerr << std::endl; - std::cerr << "\tRsGxsId: " << id; - std::cerr << std::endl; - std::cerr << "\tFingerprint: " << pgp.toStdString(); - std::cerr << std::endl; - std::cerr << "\tFinal Hash: " << hash.toStdString(); - std::cerr << std::endl; -#endif // DEBUG_IDS - - delete sha_ctx; -} - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -/* Task to validate Recogn Tags. - * - * Info to be stored in GroupServiceString + Cache. - **/ - -bool p3IdService::recogn_schedule() -{ -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_schedule()"; - std::cerr << std::endl; -#endif - - int32_t age = 0; - int32_t next_event = 0; - - if (RsTickEvent::event_count(GXSID_EVENT_RECOGN) > 0) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_schedule() Skipping GXSIS_EVENT_RECOGN already scheduled"; - std::cerr << std::endl; -#endif - return false; - } - - if (RsTickEvent::prev_event_ago(GXSID_EVENT_RECOGN, age)) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_schedule() previous event " << age << " secs ago"; - std::cerr << std::endl; -#endif - - next_event = RECOGN_PERIOD - age; - if (next_event < 0) - { - next_event = 0; - } - } - - RsTickEvent::schedule_in(GXSID_EVENT_RECOGN, next_event); - return true; -} - - -bool p3IdService::recogn_start() -{ - if (!CacheArbitration(BG_RECOGN)) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_start() Other Events running... Rescheduling"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - /* reschedule in a bit */ - RsTickEvent::schedule_in(GXSID_EVENT_RECOGN, RECOGN_RETRY_PERIOD); - return false; - } - - // NEXT EVENT is scheduled via recogn_schedule. - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_start() making request"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - std::list recognList; - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - recognList = mRecognGroupIds; - mRecognGroupIds.clear(); - } - - if (recognList.empty()) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_start() List is Empty, cancelling"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - // FINISHED. - CacheArbitrationDone(BG_RECOGN); - return false; - } - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts, recognList); - GxsTokenQueue::queueRequest(token, GXSIDREQ_RECOGN); - return true; - -} - - -bool p3IdService::recogn_handlerequest(uint32_t token) -{ -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_handlerequest(" << token << ")"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_request() Have " << grpData.size() << " Groups"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsIdGroupItem* item = dynamic_cast(*vit); - if (item) - { - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_request() Group Id: " << item->meta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - mRecognGroupsToProcess.push_back(item); - } - else - { - delete (*vit); - } - } - } - else - { - std::cerr << "p3IdService::recogn_request() getGroupData ERROR"; - std::cerr << std::endl; - } - - // Schedule Processing. - RsTickEvent::schedule_in(GXSID_EVENT_RECOGN_PROC, RECOGN_PROC_PERIOD); - return true; -} - - -bool p3IdService::recogn_process() -{ - /* each time this is called - process one Id from mGroupsToProcess */ - RsGxsIdGroupItem *item; - bool isDone = false; - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - if (!mRecognGroupsToProcess.empty()) - { - item = mRecognGroupsToProcess.front(); - mRecognGroupsToProcess.pop_front(); - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_process() Popped Group: " << item->meta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - } - else - { - isDone = true; - } - } - - if (isDone) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_process() List Empty... Done"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - // FINISHED. - CacheArbitrationDone(BG_RECOGN); - return true; - } - - - - std::list tagItems; - std::list::iterator it; - - recogn_extract_taginfo(item, tagItems); - - bool isPending = false; - int i = 1; - uint32_t tagValidFlags = 0; - for(it = tagItems.begin(); it != tagItems.end(); ++it) - { - bool isTagPending = false; - bool isTagOk = recogn_checktag(RsGxsId(item->meta.mGroupId.toStdString()), item->meta.mGroupName, *it, true, isPending); - if (isTagOk) - { - tagValidFlags |= i; - } - else - { - isPending |= isTagPending; - } - - delete *it; - i *= 2; - } - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_process() Tags Checked, saving"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - SSGxsIdGroup ssdata; - ssdata.load(item->meta.mServiceString); // attempt load - okay if fails. - - ssdata.recogntags.setTags(true, isPending, tagValidFlags); - ssdata.recogntags.lastCheckTs = time(NULL); - ssdata.recogntags.publishTs = item->meta.mPublishTs; - - // update IdScore too. - bool pgpId = (item->meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility); - ssdata.score.rep.updateIdScore(pgpId, ssdata.pgp.validatedSignature); - ssdata.score.rep.update(); - - /* set new Group ServiceString */ - uint32_t dummyToken = 0; - std::string serviceString = ssdata.save(); - setGroupServiceString(dummyToken, item->meta.mGroupId, serviceString); - - cache_update_if_cached(RsGxsId(item->meta.mGroupId.toStdString()), serviceString); - - delete item; - - // Schedule Next Processing. - RsTickEvent::schedule_in(GXSID_EVENT_RECOGN_PROC, RECOGN_PROC_PERIOD); - return false; // as there are more items on the queue to process. -} - - -bool p3IdService::recogn_checktag(const RsGxsId &id, const std::string &nickname, RsGxsRecognTagItem *item, bool doSignCheck, bool &isPending) -{ - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_checktag() groupId: " << id; - std::cerr << std::endl; - std::cerr << "p3IdService::recogn_checktag() nickname: " << nickname; - std::cerr << std::endl; - std::cerr << "p3IdService::recogn_checktag() item: "; - std::cerr << std::endl; - ((RsGxsRecognTagItem *) item)->print(std::cerr); -#endif // DEBUG_RECOGN - - // To check: - // ------------------- - // date range. - // id matches. - // nickname matches. - // signer is valid. - // ------ - // signature is valid. (only if doSignCheck == true) - - rstime_t now = time(NULL); - isPending = false; - - // check date range. - if ((item->valid_from > now) || (item->valid_to < now)) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_checktag() failed timestamp"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - return false; - } - - // id match. - if (id != item->identity) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_checktag() failed identity"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - // nickname match. - if (nickname != item->nickname) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_checktag() failed nickname"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - - - { - /* check they validity of the Tag */ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - - std::map::iterator it; - it = mRecognSignKeys.find(item->sign.keyId); - if (it == mRecognSignKeys.end()) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_checktag() failed to find signkey"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - // If OldKey, then we don't want to reprocess. - if (mRecognOldSignKeys.end() != - mRecognOldSignKeys.find(item->sign.keyId)) - { - isPending = true; // need to reprocess later with new key - } - return false; - } - - // Check tag_class is okay for signer. - if (it->second->signing_classes.ids.end() == - std::find(it->second->signing_classes.ids.begin(), it->second->signing_classes.ids.end(), item->tag_class)) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_checktag() failed signing_class check"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - // ALL Okay, just signature to check. - if (!doSignCheck) - { - return true; - } - - return RsRecogn::validateTagSignature(it->second, item); - } -} - - -void p3IdService::loadRecognKeys() -{ - RsStackMutex stack(mIdMtx); /**** LOCKED MUTEX ****/ - - RsRecogn::loadSigningKeys(mRecognSignKeys); -} - - - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -#define MAX_KNOWN_PGPIDS 20 -#define MAX_UNKNOWN_PGPIDS 20 -#define MAX_PSEUDOIDS 20 - -#define DUMMY_GXSID_DELAY 5 - -void p3IdService::generateDummyData() -{ - - generateDummy_OwnIds(); - - rstime_t age = 0; - for(int i = 0; i < MAX_KNOWN_PGPIDS; i++) - { - age += DUMMY_GXSID_DELAY; - RsTickEvent::schedule_in(GXSID_EVENT_DUMMY_PGPID, age); - } - - for(int i = 0; i < MAX_PSEUDOIDS; i++) - { - age += DUMMY_GXSID_DELAY; - RsTickEvent::schedule_in(GXSID_EVENT_DUMMY_PSEUDOID, age); - } - - for(int i = 0; i < MAX_UNKNOWN_PGPIDS; i++) - { - age += DUMMY_GXSID_DELAY; - RsTickEvent::schedule_in(GXSID_EVENT_DUMMY_UNKNOWN_PGPID, age); - } -} - - - - - -void p3IdService::generateDummy_OwnIds() -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - /* grab all the gpg ids... and make some ids */ - - /*RsPgpId ownId = */mPgpUtils->getPGPOwnId(); - -#if 0 - // generate some ownIds. - //int genCount = 0; - int i; - - int nIds = 2 + (RSRandom::random_u32() % 2); - for(i = 0; i < nIds; i++) - { - RsGxsIdGroup id; - RsPeerDetails details; - - id.mMeta.mGroupFlags = RSGXSID_GROUPFLAG_REALID; - -// // HACK FOR DUMMY GENERATION. -// id.mMeta.mAuthorId = ownId.toStdString(); -// if (rsPeers->getPeerDetails(ownId, details)) -// { -// std::ostringstream out; -// out << details.name << "_" << i + 1; -// -// id.mMeta.mGroupName = out.str(); -// } - - uint32_t dummyToken = 0; - createGroup(dummyToken, id); - } -#endif -} - - -void p3IdService::generateDummy_FriendPGP() -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - // Now Generate for friends. - std::list gpgids; - std::list::const_iterator it; - mPgpUtils->getGPGAllList(gpgids); - - RsGxsIdGroup id; - - id.mMeta.mGroupFlags = RSGXSID_GROUPFLAG_REALID_kept_for_compatibility; - - int idx = RSRandom::random_f32() * (gpgids.size() - 1); - it = gpgids.begin(); - for(int j = 0; j < idx; j++, ++it) ; - -#if 0 - // HACK FOR DUMMY GENERATION. - id.mMeta.mAuthorId = RsGxsId::random() ; - - RsPeerDetails details; - if (/*rsPeers->getPeerDetails(*it, details)*/false) - { - std::ostringstream out; - out << details.name << "_" << RSRandom::random_u32() % 1000; - id.mMeta.mGroupName = out.str(); - } - else - { - std::cerr << "p3IdService::generateDummy_FriendPGP() missing" << std::endl; - std::cerr << std::endl; - id.mMeta.mGroupName = RSRandom::random_alphaNumericString(10) ; - } - - uint32_t dummyToken = 0; - createGroup(dummyToken, id); -#endif -} - - -void p3IdService::generateDummy_UnknownPGP() -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - RsGxsIdGroup id; - - // FAKE DATA. - id.mMeta.mGroupFlags = RSGXSID_GROUPFLAG_REALID_kept_for_compatibility; - id.mPgpIdHash = Sha1CheckSum::random() ; - id.mPgpIdSign = RSRandom::random_alphaNumericString(20) ; - id.mMeta.mGroupName = RSRandom::random_alphaNumericString(10) ; - - uint32_t dummyToken = 0; - createGroup(dummyToken, id); -} - - -void p3IdService::generateDummy_UnknownPseudo() -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - RsGxsIdGroup id; - - // FAKE DATA. - id.mMeta.mGroupFlags = 0; - id.mMeta.mGroupName = RSRandom::random_alphaNumericString(10) ; - - uint32_t dummyToken = 0; - createGroup(dummyToken, id); -} - - -std::string rsIdTypeToString(uint32_t idtype) -{ - std::string str; - if (idtype & RSID_TYPE_REALID) - { - str += "GPGID "; - } - if (idtype & RSID_TYPE_PSEUDONYM) - { - str += "PSEUDO "; - } - if (idtype & RSID_RELATION_YOURSELF) - { - str += "YOURSELF "; - } - if (idtype & RSID_RELATION_FRIEND) - { - str += "FRIEND "; - } - if (idtype & RSID_RELATION_FOF) - { - str += "FOF "; - } - if (idtype & RSID_RELATION_OTHER) - { - str += "OTHER "; - } - if (idtype & RSID_RELATION_UNKNOWN) - { - str += "UNKNOWN "; - } - return str; -} - - - - - - - - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - - -/* here we are running a background process that calculates the reputation scores - * for each of the IDs.... - * - * As this class will be extensively used by many other threads... it is best - * that we don't block at all. This should be in a background thread. - * Perhaps a generic method to handle this will be advisable.... but we do that later. - * - * - * So Reputation.... - * 4 components: - * 1) Your Opinion: Should override everything else. - * 2) Implicit Factors: Know the associated GPG Key. - * 3) Your Friends Opinions: - * 4) Your Friends Calculated Reputation Scores. - * - * Must make sure that there is no Feedback loop in the Reputation calculation. - * - * So: Our Score + Friends Scores => Local Reputation. - * Local Reputation + Friends Reputations => Final Reputation? - * - * Do we need to 'ignore' Non-scores? - * ---> This becomes like the "Best Comment" algorithm from Reddit... - * Use a statistical mechanism to work out a lower bound on Reputation. - * - * But what if your opinion is wrong?.... well likely your friends will - * get their messages and reply... you'll see the missing message - request it - check reputation etc. - * - * So we are going to have three different scores (Own, Peers, (the neighbour) Hood)... - * - * So next question, when do we need to incrementally calculate the score? - * .... how often do we need to recalculate everything -> this could lead to a flux of messages. - * - * - * - * MORE NOTES: - * - * The Opinion Messages will have to be signed by PGP or SSL Keys, to guarantee that we don't - * multiple votes per person... As the message system doesn't handle uniqueness in this respect, - * we might have to do FULL_CALC for everything - This bit TODO. - * - * This will make IdService quite different to the other GXS services. - */ - -/************************************************************************************/ -/* - * Processing Algorithm: - * - Grab all Groups which have received messages. - * (opt 1)-> grab latest msgs for each of these and process => score. - * (opt 2)-> try incremental system (people probably won't change opinions often -> just set them once) - * --> if not possible, fallback to full calculation. - * - * - */ - -void p3IdService::checkPeerForIdentities() -{ - RsStackMutex stack(mIdMtx); - - // crud, i needed peers instead! - mGroupNotPresent.clear(); -} - - -// Overloaded from GxsTokenQueue for Request callbacks. -void p3IdService::handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::handleResponse(" << token << "," << req_type << "," << status << ")" << std::endl; -#endif // DEBUG_IDS - - // stuff. - switch(req_type) - { - case GXSIDREQ_CACHEOWNIDS: - if (status == RsTokenService::COMPLETE) cache_load_ownids(token); - if (status == RsTokenService::CANCELLED) RsTickEvent::schedule_now(GXSID_EVENT_CACHEOWNIDS);//Cancelled by time-out so ask a new time - break; - case GXSIDREQ_CACHELOAD: - if (status == RsTokenService::COMPLETE) cache_load_for_token(token); - break; - case GXSIDREQ_PGPHASH: - if (status == RsTokenService::COMPLETE) pgphash_handlerequest(token); - break; - case GXSIDREQ_RECOGN: - if (status == RsTokenService::COMPLETE) recogn_handlerequest(token); - break; - case GXSIDREQ_CACHETEST: - if (status == RsTokenService::COMPLETE) cachetest_handlerequest(token); - break; - case GXSIDREQ_OPINION: - if (status == RsTokenService::COMPLETE) opinion_handlerequest(token); - break; - case GXSIDREQ_LOAD_PGPIDDATA: - if (status == RsTokenService::COMPLETE) pgphash_load_group_data(token); - break; - case GXSIDREQ_SERIALIZE_TO_MEMORY: - if (status == RsTokenService::COMPLETE) handle_get_serialized_grp(token); - break; - default: - std::cerr << "p3IdService::handleResponse() Unknown Request Type: " - << req_type << std::endl; - break; - } -} - - - // Overloaded from RsTickEvent for Event callbacks. -void p3IdService::handle_event(uint32_t event_type, const std::string &/*elabel*/) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::handle_event(" << event_type << ")"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - // stuff. - switch(event_type) - { - case GXSID_EVENT_CACHEOWNIDS: - cache_request_ownids(); - break; - - case GXSID_EVENT_CACHELOAD: - cache_start_load(); - break; - - case GXSID_EVENT_CACHETEST: - cachetest_getlist(); - break; - - case GXSID_EVENT_PGPHASH: - pgphash_start(); - break; - - case GXSID_EVENT_RECOGN: - recogn_start(); - break; - - case GXSID_EVENT_RECOGN_PROC: - recogn_process(); - break; - - case GXSID_EVENT_DUMMYDATA: - generateDummyData(); - break; - - case GXSID_EVENT_DUMMY_OWNIDS: - generateDummy_OwnIds(); - break; - - case GXSID_EVENT_DUMMY_PGPID: - generateDummy_FriendPGP(); - break; - - case GXSID_EVENT_DUMMY_UNKNOWN_PGPID: - generateDummy_UnknownPGP(); - break; - - case GXSID_EVENT_DUMMY_PSEUDOID: - generateDummy_UnknownPseudo(); - break; - case GXSID_EVENT_REQUEST_IDS: - requestIdsFromNet(); - break; - case GXSID_EVENT_REPUTATION: - break; - default: - RsErr() << __PRETTY_FUNCTION__ << " Unknown Event Type: " - << event_type << std::endl; - print_stacktrace(); - break; - } -} - -/*static*/ const std::string RsIdentity::DEFAULT_IDENTITY_BASE_URL = - "retroshare:///identities"; -/*static*/ const std::string RsIdentity::IDENTITY_URL_NAME_FIELD = "identityName"; -/*static*/ const std::string RsIdentity::IDENTITY_URL_ID_FIELD = "identityId"; -/*static*/ const std::string RsIdentity::IDENTITY_URL_DATA_FIELD = "identityData"; - -bool p3IdService::exportIdentityLink( - std::string& link, const RsGxsId& id, bool includeGxsData, - const std::string& baseUrl, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(id.isNull()) return failure("id cannot be null"); - - const bool outputRadix = baseUrl.empty(); - if(outputRadix && !includeGxsData) return - failure("includeGxsData must be true if format requested is base64"); - - if( includeGxsData && - !RsGenExchange::exportGroupBase64( - link, reinterpret_cast(id), errMsg ) ) - return failure(errMsg); - - if(outputRadix) return true; - - std::vector idsInfo; - if( !getIdentitiesInfo(std::set({id}), idsInfo ) - || idsInfo.empty() ) - return failure("failure retrieving identity information"); - - RsUrl inviteUrl(baseUrl); - inviteUrl.setQueryKV(IDENTITY_URL_ID_FIELD, id.toStdString()); - inviteUrl.setQueryKV(IDENTITY_URL_NAME_FIELD, idsInfo[0].mMeta.mGroupName); - if(includeGxsData) inviteUrl.setQueryKV(IDENTITY_URL_DATA_FIELD, link); - - link = inviteUrl.toString(); - return true; -} - -bool p3IdService::importIdentityLink( - const std::string& link, RsGxsId& id, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(link.empty()) return failure("link is empty"); - - const std::string* radixPtr(&link); - - RsUrl url(link); - const auto& query = url.query(); - const auto qIt = query.find(IDENTITY_URL_DATA_FIELD); - if(qIt != query.end()) radixPtr = &qIt->second; - - if(radixPtr->empty()) return failure(IDENTITY_URL_DATA_FIELD + " is empty"); - - if(!RsGenExchange::importGroupBase64( - *radixPtr, reinterpret_cast(id), errMsg )) - return failure(errMsg); - - return true; -} - - -void RsGxsIdGroup::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mPgpIdHash); - RS_SERIAL_PROCESS(mPgpIdSign); - RS_SERIAL_PROCESS(mImage); - RS_SERIAL_PROCESS(mLastUsageTS); - RS_SERIAL_PROCESS(mPgpKnown); - RS_SERIAL_PROCESS(mIsAContact); - RS_SERIAL_PROCESS(mPgpId); - RS_SERIAL_PROCESS(mReputation); -} - -RsIdentityUsage::RsIdentityUsage(RsServiceType service, RsIdentityUsage::UsageCode code, - const RsGxsGroupId& gid, const RsGxsMessageId& mid, const RsGxsMessageId &pid, const RsGxsMessageId &tid, - uint64_t additional_id, const std::string& comment ) : - mServiceId(service), mUsageCode(code), mGrpId(gid), mMsgId(mid),mParentId(pid),mThreadId(tid), - 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(service); // G10h4ck: Why uint32 if it's 16 bits? - hs << static_cast(code); - hs << gid; - hs << mid; - hs << static_cast(additional_id); - hs << comment; - - mHash = hs.hash(); -} - -RsIdentityUsage::RsIdentityUsage() : - mServiceId(RsServiceType::NONE), mUsageCode(UNKNOWN_USAGE), mAdditionalId(0) -{} - -RsIdentity::~RsIdentity() = default; -RsReputationInfo::~RsReputationInfo() = default; -RsGixs::~RsGixs() = default; -RsIdentityDetails::~RsIdentityDetails() = default; -GxsReputation::~GxsReputation() = default; -RsGxsIdGroup::~RsGxsIdGroup() = default; diff --git a/libretroshare/src/services/p3idservice.h b/libretroshare/src/services/p3idservice.h deleted file mode 100644 index 370c7a35a..000000000 --- a/libretroshare/src/services/p3idservice.h +++ /dev/null @@ -1,640 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3idservice.h * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2017-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/// RetroShare GXS identities service - - -#include -#include - -#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/rstickevent.h" -#include "util/rsrecogn.h" -#include "pqi/authgpg.h" -#include "rsitems/rsgxsrecognitems.h" - -class PgpAuxUtils; - -class OpinionRequest -{ - public: - OpinionRequest(uint32_t token, RsGxsId id, bool absOpinion, int32_t score) - :mToken(token), mId(id), mAbsOpinion(absOpinion), mScore(score) - { return; } - OpinionRequest() - :mToken(0), mId(), mAbsOpinion(false), mScore(0) - { return; } - - uint32_t mToken; - RsGxsId mId; - bool mAbsOpinion; - int32_t mScore; -}; - - -// INTERNAL DATA TYPES. -// Describes data stored in GroupServiceString. - -class SSBit -{ - public: -virtual bool load(const std::string &input) = 0; -virtual std::string save() const = 0; -}; - - - -class SSGxsIdPgp: public SSBit -{ - public: - SSGxsIdPgp() - :validatedSignature(false), lastCheckTs(0), checkAttempts(0) { return; } - -virtual bool load(const std::string &input); -virtual std::string save() const; - - bool validatedSignature; - rstime_t lastCheckTs; - uint32_t checkAttempts; - RsPgpId pgpId; -}; - -class SSGxsIdRecognTags: public SSBit -{ - public: - SSGxsIdRecognTags() - :tagFlags(0), publishTs(0), lastCheckTs(0) { return; } - -virtual bool load(const std::string &input); -virtual std::string save() const; - - void setTags(bool processed, bool pending, uint32_t flags); - - bool tagsProcessed() const; // have we processed? - bool tagsPending() const; // should we reprocess? - bool tagValid(int i) const; - - uint32_t tagFlags; - rstime_t publishTs; - rstime_t lastCheckTs; -}; - - -class SSGxsIdReputation: public SSBit -{ - public: - SSGxsIdReputation() - :rep() { return; } - -virtual bool load(const std::string &input); -virtual std::string save() const; - - GxsReputation rep; -}; - -class SSGxsIdCumulator: public SSBit -{ -public: - SSGxsIdCumulator() - :count(0), nullcount(0), sum(0), sumsq(0) { return; } - -virtual bool load(const std::string &input); -virtual std::string save() const; - - uint32_t count; - uint32_t nullcount; - double sum; - double sumsq; - - // derived parameters: -}; - -class SSGxsIdGroup: public SSBit -{ -public: - SSGxsIdGroup() { return; } - -virtual bool load(const std::string &input); -virtual std::string save() const; - - // pgphash status - SSGxsIdPgp pgp; - - // recogTags. - SSGxsIdRecognTags recogntags; - - // reputation score. - SSGxsIdReputation score; - - // These are depreciated (will load, but not save) - SSGxsIdCumulator opinion; - SSGxsIdCumulator reputation; - -}; - -#define ID_LOCAL_STATUS_FULL_CALC_FLAG 0x00010000 -#define ID_LOCAL_STATUS_INC_CALC_FLAG 0x00020000 - -class RsGxsIdGroupItem; - -class RsGxsIdCache -{ -public: - RsGxsIdCache(); - - RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pkey, const RsTlvPrivateRSAKey& privkey, const std::list &tagList); - RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pkey, const std::list &tagList); - - void updateServiceString(std::string serviceString); - - rstime_t mPublishTs; - std::list mRecognTags; // Only partially validated. - - RsIdentityDetails details; - - RsTlvPublicRSAKey pub_key; - RsTlvPrivateRSAKey priv_key; - -private: - void init(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pub_key, const RsTlvPrivateRSAKey& in_priv_key,const std::list &tagList); -}; - -struct SerialisedIdentityStruct -{ - unsigned char *mMem ; - uint32_t mSize ; - rstime_t mLastUsageTS; -}; - -// We cache all identities, and provide alternative (instantaneous) -// functions to extract info, rather than the horrible Token system. -class p3IdService: public RsGxsIdExchange, public RsIdentity, public GxsTokenQueue, public RsTickEvent, public p3Config -{ -public: - p3IdService(RsGeneralDataService* gds, RsNetworkExchangeService* nes, PgpAuxUtils *pgpUtils); - - virtual RsServiceInfo getServiceInfo()override; - static uint32_t idAuthenPolicy(); - - virtual void service_tick()override; // needed for background processing. - - - /*! - * Design hack, id service must be constructed first as it - * is need for construction of subsequent net services - */ - void setNes(RsNetworkExchangeService* nes); - - /* General Interface is provided by RsIdentity / RsGxsIfaceImpl. */ - - /* Data Specific Interface */ - - /// @see RsIdentity - bool getIdentitiesInfo(const std::set& ids, - std::vector& idsInfo ) override; - - /// @see RsIdentity - bool getIdentitiesSummaries(std::list& ids) override; - - // These are exposed via RsIdentity. - virtual bool getGroupData(const uint32_t &token, std::vector &groups) override; - virtual bool getGroupSerializedData(const uint32_t &token, std::map& serialized_groups) override; - - //virtual bool getMsgData(const uint32_t &token, std::vector &opinions); - - // These are local - and not exposed via RsIdentity. - virtual bool createGroup(uint32_t& token, RsGxsIdGroup &group); - virtual bool updateGroup(uint32_t& token, RsGxsIdGroup &group); - virtual bool deleteGroup(uint32_t& token, RsGxsGroupId& group); - //virtual bool createMsg(uint32_t& token, RsGxsIdOpinion &opinion); - - virtual bool receiveNewIdentity(RsNxsGrp *identity_grp) override; - virtual bool retrieveNxsIdentity(const RsGxsId& group_id,RsNxsGrp *& identity_grp)override; - - /**************** RsIdentity External Interface. - * Notes: - * - * All the data is cached together for the moment - We should probably - * seperate and sort this out. - * - * Also need to handle Cache updates / invalidation from internal changes. - * - */ - //virtual bool getNickname(const RsGxsId &id, std::string &nickname); - virtual bool getIdDetails(const RsGxsId &id, RsIdentityDetails &details) override; - - RS_DEPRECATED_FOR(RsReputations) - virtual bool submitOpinion(uint32_t& token, const RsGxsId &id, - bool absOpinion, int score) override; - - /// @see RsIdentity - virtual bool createIdentity( - RsGxsId& id, - const std::string& name, const RsGxsImage& avatar = RsGxsImage(), - bool pseudonimous = true, const std::string& pgpPassword = "" ) override; - - virtual bool createIdentity(uint32_t& token, RsIdentityParameters ¶ms) override; - - /// @see RsIdentity - bool updateIdentity( const RsGxsId& id, const std::string& name, const RsGxsImage& avatar, bool pseudonimous, const std::string& pgpPassword) override; - - /// @see RsIdentity - bool deleteIdentity(RsGxsId& id) override; - - RS_DEPRECATED - virtual bool deleteIdentity(uint32_t& token, RsGxsIdGroup &group) override; - - virtual void setDeleteBannedNodesThreshold(uint32_t days) override; - virtual uint32_t deleteBannedNodesThreshold() override; - - virtual bool parseRecognTag(const RsGxsId &id, const std::string &nickname, - const std::string &tag, RsRecognTagDetails &details) override; - virtual bool getRecognTagRequest(const RsGxsId &id, const std::string &comment, - uint16_t tag_class, uint16_t tag_type, std::string &tag) override; - - virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) override; - virtual bool isARegularContact(const RsGxsId& id) override; - virtual void setAutoAddFriendIdsAsContact(bool b) override; - virtual bool autoAddFriendIdsAsContact() override; - - virtual uint32_t nbRegularContacts() override; - virtual rstime_t getLastUsageTS(const RsGxsId &id) override ; - - /**************** RsGixs Implementation ***************/ - - /// @see RsIdentity - bool getOwnSignedIds(std::vector& ids) override; - - /// @see RsIdentity - bool getOwnPseudonimousIds(std::vector& ids) override; - - /// @see RsIdentity - bool getOwnIds( - std::list &ownIds, bool signed_only = false ) override; - - /// @see RsIdentity - bool isKnownId(const RsGxsId& id) override; - - /// @see RsIdentity - bool isOwnId(const RsGxsId& key_id) override; - - /// @see RsIdentity - bool exportIdentityLink( - std::string& link, const RsGxsId& id, - bool includeGxsData = true, - const std::string& baseUrl = DEFAULT_IDENTITY_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsIdentity - bool importIdentityLink( - const std::string& link, - RsGxsId& id = RS_DEFAULT_STORAGE_PARAM(RsGxsId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - - virtual bool signData( const uint8_t* data, - uint32_t data_size, - const RsGxsId& signer_id, - RsTlvKeySignature& signature, - uint32_t& signing_error)override; - - virtual bool validateData( const uint8_t *data, uint32_t data_size, - const RsTlvKeySignature& signature, - bool force_load, const RsIdentityUsage &info, - uint32_t& signing_error )override; - - virtual bool encryptData( const uint8_t* decrypted_data, - uint32_t decrypted_data_size, - uint8_t*& encrypted_data, - uint32_t& encrypted_data_size, - const RsGxsId& encryption_key_id, - uint32_t& error_status, - bool force_load = true )override; - - bool encryptData( const uint8_t* decrypted_data, - uint32_t decrypted_data_size, - uint8_t*& encrypted_data, - uint32_t& encrypted_data_size, - const std::set& encrypt_ids, - uint32_t& error_status, bool force_loa = true ); - - virtual bool decryptData( const uint8_t* encrypted_data, - uint32_t encrypted_data_size, - uint8_t*& decrypted_data, - uint32_t& decrypted_data_size, - const RsGxsId& decryption_key_id, - uint32_t& error_status, - bool force_load = true )override; - - virtual bool decryptData(const uint8_t* encrypted_data, - uint32_t encrypted_data_size, - uint8_t*& decrypted_data, - uint32_t& decrypted_data_size, - const std::set& decrypt_ids, - uint32_t& error_status, - bool force_load = true ); - - - virtual bool haveKey(const RsGxsId &id)override; - virtual bool havePrivateKey(const RsGxsId &id)override; - - virtual bool getKey(const RsGxsId &id, RsTlvPublicRSAKey &key)override; - virtual bool getPrivateKey(const RsGxsId &id, RsTlvPrivateRSAKey &key)override; - - virtual bool requestKey( const RsGxsId &id, - const std::list &peers, - const RsIdentityUsage &use_info )override; - virtual bool requestPrivateKey(const RsGxsId &id)override; - - RS_DEPRECATED_FOR(exportIdentityLink) - virtual bool serialiseIdentityToMemory(const RsGxsId& id, std::string& radix_string) override; - RS_DEPRECATED_FOR(importIdentityLink) - virtual bool deserialiseIdentityFromMemory(const std::string& radix_string, RsGxsId* id = nullptr) override; - - /// @see RsIdentity - bool requestIdentity( - const RsGxsId& id, - const std::vector& peers = std::vector() - ) override; - - /**************** RsGixsReputation Implementation ****************/ - - // get Reputation. -#ifdef TO_BE_REMOVED - virtual bool haveReputation(const RsGxsId &id); - virtual bool loadReputation(const RsGxsId &id, const std::list& peers); - virtual bool getReputation(const RsGxsId &id, GixsReputation &rep); -#endif - - -protected: - /** Notifications **/ - virtual void notifyChanges(std::vector& changes) override; - - /** Overloaded to add PgpIdHash to Group Definition **/ - virtual ServiceCreate_Return service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet) override; - - // Overloads RsGxsGenExchange - virtual bool acceptNewGroup(const RsGxsGrpMetaData *grpMeta) override ; - - // Overloaded from GxsTokenQueue for Request callbacks. - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) override; - - // Overloaded from RsTickEvent. - virtual void handle_event(uint32_t event_type, const std::string &elabel) override; - - //===================================================// - // p3Config methods // - //===================================================// - - // Load/save the routing info, the pending items in transit, and the config variables. - // - virtual bool loadList(std::list& items) override ; - virtual bool saveList(bool& cleanup,std::list& items) override ; - - virtual RsSerialiser *setupSerialiser() override ; - - -private: - - /************************************************************************ - * This is the Cache for minimising calls to the DataStore. - * - */ - int cache_tick(); - - bool cache_request_load(const RsGxsId &id, const std::list& peers = std::list()); - bool cache_start_load(); - bool cache_load_for_token(uint32_t token); - - bool cache_store(const RsGxsIdGroupItem *item); - bool cache_update_if_cached(const RsGxsId &id, std::string serviceString); - - bool isPendingNetworkRequest(const RsGxsId& gxsId); - void requestIdsFromNet(); - - // Mutex protected. - - //std::list mCacheLoad_ToCache; - std::map > mCacheLoad_ToCache, mPendingCache; - - // Switching to RsMemCache for Key Caching. - RsMemCache mKeyCache; - - /************************************************************************ - * Refreshing own Ids. - * - */ - bool cache_request_ownids(); - bool cache_load_ownids(uint32_t token); - - std::list mOwnIds; - std::list mOwnSignedIds; - - /************************************************************************ - * Test fns for Caching. - * - */ - bool cachetest_tick(); - bool cachetest_getlist(); - bool cachetest_handlerequest(uint32_t token); - - /************************************************************************ - * for processing background tasks that use the serviceString. - * - must be mutually exclusive to avoid clashes. - */ - bool CacheArbitration(uint32_t mode); - void CacheArbitrationDone(uint32_t mode); - - bool mBgSchedule_Active; - uint32_t mBgSchedule_Mode; - - /***********************************8 - * Fonction to receive and handle group serialisation to memory - */ - - virtual void handle_get_serialized_grp(uint32_t token); - - /************************************************************************ - * pgphash processing. - * - */ - bool pgphash_start(); - bool pgphash_load_group_data(uint32_t token); - bool pgphash_handlerequest(uint32_t token); - bool pgphash_process(); - - bool checkId(const RsGxsIdGroup &grp, RsPgpId &pgp_id, bool &error); - void getPgpIdList(); - - /* MUTEX PROTECTED DATA (mIdMtx - maybe should use a 2nd?) */ - - std::map mPgpFingerprintMap; - std::map mGroupsToProcess; - - /************************************************************************ - * recogn processing. - * - */ - bool recogn_schedule(); - bool recogn_start(); - bool recogn_handlerequest(uint32_t token); - bool recogn_process(); - - // helper functions. - bool recogn_extract_taginfo(const RsGxsIdGroupItem *item, std::list &tagItems); - bool cache_process_recogntaginfo(const RsGxsIdGroupItem *item, std::list &tagList); - - bool recogn_checktag(const RsGxsId &id, const std::string &nickname, RsGxsRecognTagItem *item, bool doSignCheck, bool &isPending); - - void loadRecognKeys(); - - - /************************************************************************ - * opinion processing. - * - */ - - bool opinion_handlerequest(uint32_t token); - - /* MUTEX PROTECTED DATA */ - std::map mPendingOpinion; - - - /************************************************************************ - * for getting identities that are not present - * - */ - void checkPeerForIdentities(); - - - /* MUTEX PROTECTED DATA (mIdMtx - maybe should use a 2nd?) */ - - bool checkRecognSignature_locked(std::string encoded, RSA &key, std::string signature); - bool getRecognKey_locked(std::string signer, RSA &key); - - std::list mRecognGroupIds; - std::list mRecognGroupsToProcess; - std::map mRecognSignKeys; - std::map mRecognOldSignKeys; - - /************************************************************************ - * Below is the background task for processing opinions => reputations - * - */ - - virtual void generateDummyData(); - void generateDummy_OwnIds(); - void generateDummy_FriendPGP(); - void generateDummy_UnknownPGP(); - void generateDummy_UnknownPseudo(); - - void cleanUnusedKeys() ; - void slowIndicateConfigChanged() ; - - virtual void timeStampKey(const RsGxsId& id, const RsIdentityUsage& reason) override; - rstime_t locked_getLastUsageTS(const RsGxsId& gxs_id); - - std::string genRandomId(int len = 20); - -#if 0 - bool reputation_start(); - bool reputation_continue(); - - int background_tick(); - bool background_checkTokenRequest(); - bool background_requestGroups(); - bool background_requestNewMessages(); - bool background_processNewMessages(); - bool background_FullCalcRequest(); - bool background_processFullCalc(); - - bool background_cleanup(); -#endif - - RsMutex mIdMtx; - -#if 0 - /***** below here is locked *****/ - bool mLastBgCheck; - bool mBgProcessing; - - uint32_t mBgToken; - uint32_t mBgPhase; - - std::map mBgGroupMap; - std::list mBgFullCalcGroups; -#endif - - /************************************************************************ - * Other Data that is protected by the Mutex. - */ - -private: - - struct keyTSInfo - { - keyTSInfo() : TS(0) {} - - rstime_t TS ; - std::map usage_map ; - }; - friend class IdCacheEntryCleaner; - - std::map > mIdsPendingCache; - std::map > mGroupNotPresent; - std::map > mIdsNotPresent; - std::map mKeysTS ; - - std::map mSerialisedIdentities ; - - // keep a list of regular contacts. This is useful to sort IDs, and allow some services to priviledged ids only. - std::set mContacts; - RsNetworkExchangeService* mNes; - - /************************** - * AuxUtils provides interface to Security Function (e.g. GPGAuth(), notify etc.) - * without depending directly on all these classes. - */ - - PgpAuxUtils *mPgpUtils; - rstime_t mLastPGPHashProcessTime ; - rstime_t mLastKeyCleaningTime ; - rstime_t mLastConfigUpdate ; - - bool mOwnIdsLoaded; - bool ownIdsAreLoaded() { RS_STACK_MUTEX(mIdMtx); return mOwnIdsLoaded; } - - bool mAutoAddFriendsIdentitiesAsContacts; - uint32_t mMaxKeepKeysBanned; - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; diff --git a/libretroshare/src/services/p3msgservice.cc b/libretroshare/src/services/p3msgservice.cc deleted file mode 100644 index 5974d7bf3..000000000 --- a/libretroshare/src/services/p3msgservice.cc +++ /dev/null @@ -1,2463 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3msgservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsidentity.h" - -#include "pqi/pqibin.h" -#include "pqi/p3linkmgr.h" -#include "pqi/authgpg.h" -#include "pqi/p3cfgmgr.h" - -#include "gxs/gxssecurity.h" - -#include "services/p3idservice.h" -#include "services/p3msgservice.h" - -#include "pgp/pgpkeyutil.h" -#include "rsserver/p3face.h" - -#include "rsitems/rsconfigitems.h" - -#include "grouter/p3grouter.h" -#include "grouter/groutertypes.h" - -#include "util/rsdebug.h" -#include "util/rsdir.h" -#include "util/rsstring.h" -#include "util/radix64.h" -#include "util/rsrandom.h" -#include "util/rsmemory.h" -#include "util/rsprint.h" -#include "util/rsthreads.h" - -#include -#include -#include -#include - -using namespace Rs::Msgs; - -/// keep msg hashes for 2 months to avoid re-sent msgs -static constexpr uint32_t RS_MSG_DISTANT_MESSAGE_HASH_KEEP_TIME = 2*30*86400; - -/* Another little hack ..... unique message Ids - * will be handled in this class..... - * These are unique within this run of the server, - * and are not stored long term.... - * - * Only 3 entry points: - * (1) from network.... - * (2) from local send - * (3) from storage... - */ - -p3MsgService::p3MsgService( p3ServiceControl *sc, p3IdService *id_serv, - p3GxsTrans& gxsMS ) - : p3Service(), p3Config(), - gxsOngoingMutex("p3MsgService Gxs Outgoing Mutex"), mIdService(id_serv), - mServiceCtrl(sc), mMsgMtx("p3MsgService"), mMsgUniqueId(0), - recentlyReceivedMutex("p3MsgService recently received hash mutex"), - mGxsTransServ(gxsMS) -{ - /* this serialiser is used for services. It's not the same than the one - * returned by setupSerialiser(). We need both!! */ - _serialiser = new RsMsgSerialiser(); - addSerialType(_serialiser); - - /* MsgIds are not transmitted, but only used locally as a storage index. - * As such, thay do not need to be different at friends nodes. */ - mMsgUniqueId = 1; - - mShouldEnableDistantMessaging = true; - mDistantMessagingEnabled = false; - mDistantMessagePermissions = RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NONE; - - if(sc) initStandardTagTypes(); // Initialize standard tag types - - mGxsTransServ.registerGxsTransClient( GxsTransSubServices::P3_MSG_SERVICE, - this ); -} - -const std::string MSG_APP_NAME = "msg"; -const uint16_t MSG_APP_MAJOR_VERSION = 1; -const uint16_t MSG_APP_MINOR_VERSION = 0; -const uint16_t MSG_MIN_MAJOR_VERSION = 1; -const uint16_t MSG_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3MsgService::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_MSG, - MSG_APP_NAME, - MSG_APP_MAJOR_VERSION, - MSG_APP_MINOR_VERSION, - MSG_MIN_MAJOR_VERSION, - MSG_MIN_MINOR_VERSION); -} - -p3MsgService::~p3MsgService() -{ - RS_STACK_MUTEX(mMsgMtx); /********** STACK LOCKED MTX ******/ - - for(auto tag:mTags) delete tag.second; - for(auto tag:mMsgTags) delete tag.second; - for(auto msgid:mSrcIds) delete msgid.second; - for(auto parentid:mParentId) delete parentid.second; - for(auto img:imsg) delete img.second; - for(auto mout:msgOutgoing) delete mout.second; - - for(auto mpend:_pendingPartialMessages) delete mpend.second; -} - -uint32_t p3MsgService::getNewUniqueMsgId() -{ - RS_STACK_MUTEX(mMsgMtx); /********** STACK LOCKED MTX ******/ - return mMsgUniqueId++; -} - -int p3MsgService::tick() -{ - /* don't worry about increasing tick rate! - * (handled by p3service) - */ - - incomingMsgs(); - - static rstime_t last_management_time = 0 ; - rstime_t now = time(NULL) ; - - if(now > last_management_time + 5) - { - manageDistantPeers(); - checkOutgoingMessages(); - cleanListOfReceivedMessageHashes(); - - last_management_time = now; - } - - return 0; -} - -void p3MsgService::cleanListOfReceivedMessageHashes() -{ - RS_STACK_MUTEX(recentlyReceivedMutex); - - rstime_t now = time(nullptr); - - for( auto it = mRecentlyReceivedMessageHashes.begin(); - it != mRecentlyReceivedMessageHashes.end(); ) - if( now > RS_MSG_DISTANT_MESSAGE_HASH_KEEP_TIME + it->second ) - { - std::cerr << "p3MsgService(): cleanListOfReceivedMessageHashes(). " - << "Removing old hash " << it->first << ", aged " - << now - it->second << " secs ago" << std::endl; - - it = mRecentlyReceivedMessageHashes.erase(it); - } - else ++it; -} - -void p3MsgService::processIncomingMsg(RsMsgItem *mi) -{ - mi -> recvTime = static_cast(time(nullptr)); - mi -> msgId = getNewUniqueMsgId(); - - { - RS_STACK_MUTEX(mMsgMtx); - - /* from a peer */ - - mi->msgFlags &= (RS_MSG_FLAGS_DISTANT | RS_MSG_FLAGS_SYSTEM); // remove flags except those - mi->msgFlags |= RS_MSG_FLAGS_NEW; - - if (rsEvents) - { - auto ev = std::make_shared(); - ev->mMailStatusEventCode = RsMailStatusEventCode::NEW_MESSAGE; - ev->mChangedMsgIds.insert(std::to_string(mi->msgId)); - rsEvents->postEvent(ev); - } - - imsg[mi->msgId] = mi; - RsMsgSrcId* msi = new RsMsgSrcId(); - msi->msgId = mi->msgId; - msi->srcId = mi->PeerId(); - mSrcIds.insert(std::pair(msi->msgId, msi)); - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - /**** STACK UNLOCKED ***/ - } - - // If the peer is allowed to push files, then auto-download the recommended files. - - RsIdentityDetails id_details; - if(rsIdentity->getIdDetails(RsGxsId(mi->PeerId()),id_details) && !id_details.mPgpId.isNull() && (rsPeers->servicePermissionFlags(id_details.mPgpId) & RS_NODE_PERM_ALLOW_PUSH)) - { - std::list srcIds; - srcIds.push_back(mi->PeerId()); - - for(std::list::const_iterator it(mi->attachment.items.begin());it!=mi->attachment.items.end();++it) - rsFiles->FileRequest((*it).name,(*it).hash,(*it).filesize,std::string(),RS_FILE_REQ_ANONYMOUS_ROUTING,srcIds) ; - } - - RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_ADD); -} - -bool p3MsgService::checkAndRebuildPartialMessage(RsMsgItem *ci) -{ - // Check is the item is ending an incomplete item. - // - std::map::iterator it = _pendingPartialMessages.find(ci->PeerId()) ; - - bool ci_is_partial = ci->msgFlags & RS_MSG_FLAGS_PARTIAL ; - - if(it != _pendingPartialMessages.end()) - { -#ifdef MSG_DEBUG - std::cerr << "Pending message found. Appending it." << std::endl; -#endif - // Yes, there is. Append the item to ci. - - ci->message = it->second->message + ci->message ; - ci->msgFlags |= it->second->msgFlags ; - - delete it->second ; - - if(!ci_is_partial) - _pendingPartialMessages.erase(it) ; - } - - if(ci_is_partial) - { -#ifdef MSG_DEBUG - std::cerr << "Message is partial, storing for later." << std::endl; -#endif - // The item is a partial message. Push it, and wait for the rest. - // - _pendingPartialMessages[ci->PeerId()] = ci ; - return false ; - } - else - { -#ifdef MSG_DEBUG - std::cerr << "Message is complete, using it now." << std::endl; -#endif - return true ; - } -} - -int p3MsgService::incomingMsgs() -{ - RsMsgItem *mi; - int i = 0; - - while((mi = (RsMsgItem *) recvItem()) != NULL) - { - handleIncomingItem(mi) ; - ++i ; - } - - return i; -} - -void p3MsgService::handleIncomingItem(RsMsgItem *mi) -{ - bool changed = false ; - - // only returns true when a msg is complete. - if(checkAndRebuildPartialMessage(mi)) - { - processIncomingMsg(mi); - changed = true ; - } - if(changed) - RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); -} - -void p3MsgService::statusChange(const std::list &plist) -{ - /* should do it properly! */ - /* only do this when a new peer is connected */ - bool newPeers = false; - std::list::const_iterator it; - for(it = plist.begin(); it != plist.end(); ++it) - { - if (it->actions & RS_SERVICE_PEER_CONNECTED) - { - newPeers = true; - } - } - - if (newPeers) - { - checkOutgoingMessages(); - } -} - -void p3MsgService::checkSizeAndSendMessage(RsMsgItem *msg) -{ - // We check the message item, and possibly split it into multiple messages, if the message is too big. - - static const uint32_t MAX_STRING_SIZE = 15000 ; - - std::cerr << "Msg is size " << msg->message.size() << std::endl; - - while(msg->message.size() > MAX_STRING_SIZE) - { - // chop off the first 15000 wchars - - RsMsgItem *item = new RsMsgItem(*msg) ; - - item->message = item->message.substr(0,MAX_STRING_SIZE) ; - msg->message = msg->message.substr(MAX_STRING_SIZE,msg->message.size()-MAX_STRING_SIZE) ; - -#ifdef DEBUG_DISTANT_MSG - std::cerr << " Chopped off msg of size " << item->message.size() << std::endl; -#endif - - // Indicate that the message is to be continued. - // - item->msgFlags |= RS_MSG_FLAGS_PARTIAL ; - sendItem(item) ; - } -#ifdef DEBUG_DISTANT_MSG - std::cerr << " Chopped off msg of size " << msg->message.size() << std::endl; -#endif - - sendItem(msg) ; -} - -int p3MsgService::checkOutgoingMessages() -{ - bool changed = false; - std::list output_queue; - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_SENT; - - { - RS_STACK_MUTEX(mMsgMtx); /********** STACK LOCKED MTX ******/ - - const RsPeerId& ownId = mServiceCtrl->getOwnId(); - - std::list::iterator it; - std::list toErase; - - std::map::iterator mit; - for( mit = msgOutgoing.begin(); mit != msgOutgoing.end(); ++mit ) - { - if (mit->second->msgFlags & RS_MSG_FLAGS_TRASH) continue; - - /* find the certificate */ - RsPeerId pid = mit->second->PeerId(); - bool should_send = false; - - if( pid == ownId) should_send = true; - - // FEEDBACK Msg to Ourselves - if( mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, - pid) ) - should_send = true; - - if( (mit->second->msgFlags & RS_MSG_FLAGS_DISTANT) && - !(mit->second->msgFlags & RS_MSG_FLAGS_ROUTED)) - should_send = true; - - if(should_send) - { - Dbg3() << __PRETTY_FUNCTION__ << " Sending out message" - << std::endl; - /* remove the pending flag */ - - output_queue.push_back(mit->second); - pEvent->mChangedMsgIds.insert(std::to_string(mit->first)); - - /* When the message is a distant msg, dont remove it yet from - * the list. Only mark it as being sent, so that we don't send - * it again. */ - if(!(mit->second->msgFlags & RS_MSG_FLAGS_DISTANT)) - { - (mit->second)->msgFlags &= ~RS_MSG_FLAGS_PENDING; - toErase.push_back(mit->first); - changed = true; - } - else - { -#ifdef DEBUG_DISTANT_MSG - std::cerr << "Message id " << mit->first << " is distant: " - << "kept in outgoing, and marked as ROUTED" - << std::endl; -#endif - mit->second->msgFlags |= RS_MSG_FLAGS_ROUTED; - } - } -#ifdef DEBUG_DISTANT_MSG - else - Dbg3() << __PRETTY_FUNCTION__ << " Delaying until available..." << std::endl; -#endif - } - - /* clean up */ - for(it = toErase.begin(); it != toErase.end(); ++it) - { - mit = msgOutgoing.find(*it); - if ( mit != msgOutgoing.end() ) msgOutgoing.erase(mit); - - std::map::iterator srcIt = mSrcIds.find(*it); - if (srcIt != mSrcIds.end()) - { - delete (srcIt->second); - mSrcIds.erase(srcIt); - } - } - - if (toErase.size() > 0) IndicateConfigChanged(); - } - - for( std::list::const_iterator it(output_queue.begin()); - it != output_queue.end(); ++it ) - if( (*it)->msgFlags & RS_MSG_FLAGS_DISTANT ) // don't split distant messages. The global router takes care of it. - sendDistantMsgItem(*it); - else - checkSizeAndSendMessage(*it); - - if(changed) - RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); - - if(rsEvents && !pEvent->mChangedMsgIds.empty()) - rsEvents->postEvent(pEvent); - - return 0; -} - -bool p3MsgService::saveList(bool& cleanup, std::list& itemList) -{ - RsMsgGRouterMap* gxsmailmap = new RsMsgGRouterMap; - { - RS_STACK_MUTEX(gxsOngoingMutex); - gxsmailmap->ongoing_msgs = gxsOngoingMessages; - } - itemList.push_front(gxsmailmap); - - std::map::iterator mit; - std::map::iterator mit2; - std::map::iterator mit3; - std::map::iterator lit; - std::map::iterator mit4; - - cleanup = true; - - mMsgMtx.lock(); - - for(mit = imsg.begin(); mit != imsg.end(); ++mit) - itemList.push_back(new RsMsgItem(*mit->second)); - - for(lit = mSrcIds.begin(); lit != mSrcIds.end(); ++lit) - itemList.push_back(new RsMsgSrcId(*lit->second)); - - - for(mit = msgOutgoing.begin(); mit != msgOutgoing.end(); ++mit) - itemList.push_back(new RsMsgItem(*mit->second)) ; - - for(mit2 = mTags.begin(); mit2 != mTags.end(); ++mit2) - itemList.push_back(new RsMsgTagType(*mit2->second)); - - for(mit3 = mMsgTags.begin(); mit3 != mMsgTags.end(); ++mit3) - itemList.push_back(new RsMsgTags(*mit3->second)); - - for(mit4 = mParentId.begin(); mit4 != mParentId.end(); ++mit4) - itemList.push_back(new RsMsgParentId(*mit4->second)); - - RsMsgGRouterMap *grmap = new RsMsgGRouterMap ; - grmap->ongoing_msgs = _ongoing_messages ; - - itemList.push_back(grmap) ; - - RsMsgDistantMessagesHashMap *ghm = new RsMsgDistantMessagesHashMap; - { - RS_STACK_MUTEX(recentlyReceivedMutex); - ghm->hash_map = mRecentlyReceivedMessageHashes; - } - itemList.push_back(ghm); - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - kv.key = "DISTANT_MESSAGES_ENABLED" ; - kv.value = mShouldEnableDistantMessaging?"YES":"NO" ; - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "DISTANT_MESSAGE_PERMISSION_FLAGS" ; - kv.value = RsUtil::NumberToString(mDistantMessagePermissions) ; - vitem->tlvkvs.pairs.push_back(kv) ; - - itemList.push_back(vitem); - - return true; -} - -void p3MsgService::saveDone() -{ - // unlocks mutex which has been locked by savelist - mMsgMtx.unlock(); -} - -RsSerialiser* p3MsgService::setupSerialiser() // this serialiser is used for config. So it adds somemore info in the serialised items -{ - RsSerialiser *rss = new RsSerialiser ; - - rss->addSerialType(new RsMsgSerialiser(RsSerializationFlags::CONFIG)); - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss; -} - -// build list of standard tag types -static void getStandardTagTypes(MsgTagType &tags) -{ - /* create standard tag types, the text must be translated in the GUI */ - tags.types [RS_MSGTAGTYPE_IMPORTANT] = std::pair ("Important", 0xFF0000); - tags.types [RS_MSGTAGTYPE_WORK] = std::pair ("Work", 0xFF9900); - tags.types [RS_MSGTAGTYPE_PERSONAL] = std::pair ("Personal", 0x009900); - tags.types [RS_MSGTAGTYPE_TODO] = std::pair ("Todo", 0x3333FF); - tags.types [RS_MSGTAGTYPE_LATER] = std::pair ("Later", 0x993399); -} - -// Initialize the standard tag types after load -void p3MsgService::initStandardTagTypes() -{ - bool bChanged = false; - const RsPeerId& ownId = mServiceCtrl->getOwnId(); - - MsgTagType tags; - getStandardTagTypes(tags); - - std::map >::iterator tit; - for (tit = tags.types.begin(); tit != tags.types.end(); ++tit) { - std::map::iterator mit = mTags.find(tit->first); - if (mit == mTags.end()) { - RsMsgTagType* tagType = new RsMsgTagType(); - tagType->PeerId (ownId); - tagType->tagId = tit->first; - tagType->text = tit->second.first; - tagType->rgb_color = tit->second.second; - - mTags.insert(std::pair(tit->first, tagType)); - - bChanged = true; - } - } - - if (bChanged) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } -} - -bool p3MsgService::loadList(std::list& load) -{ - auto gxsmIt = load.begin(); - RsMsgGRouterMap* gxsmailmap = dynamic_cast(*gxsmIt); - if(gxsmailmap) - { - { - RS_STACK_MUTEX(gxsOngoingMutex); - gxsOngoingMessages = gxsmailmap->ongoing_msgs; - } - delete *gxsmIt; load.erase(gxsmIt); - } - - RsMsgItem *mitem; - RsMsgTagType* mtt; - RsMsgTags* mti; - RsMsgSrcId* msi; - RsMsgParentId* msp; - RsMsgGRouterMap* grm; - RsMsgDistantMessagesHashMap *ghm; - - std::list items; - std::list::iterator it; - std::map::iterator tagIt; - std::map srcIdMsgMap; - std::map::iterator srcIt; - - uint32_t max_msg_id = 0 ; - - // load items and calculate next unique msgId - for(it = load.begin(); it != load.end(); ++it) - { - if (NULL != (mitem = dynamic_cast(*it))) - { - /* STORE MsgID */ - if (mitem->msgId > max_msg_id) - max_msg_id = mitem->msgId ; - - items.push_back(mitem); - } - else if (NULL != (grm = dynamic_cast(*it))) - { - typedef std::map tT; - for( tT::const_iterator bit = grm->ongoing_msgs.begin(); - bit != grm->ongoing_msgs.end(); ++bit ) - _ongoing_messages.insert(*bit); - delete *it; - continue; - } - else if(NULL != (ghm = dynamic_cast(*it))) - { - { - RS_STACK_MUTEX(recentlyReceivedMutex); - mRecentlyReceivedMessageHashes = ghm->hash_map; - } -#ifdef DEBUG_DISTANT_MSG - std::cerr << " loaded recently received message map: " << std::endl; - - for(std::map::const_iterator it(mRecentlyReceivedDistantMessageHashes.begin());it!=mRecentlyReceivedDistantMessageHashes.end();++it) - std::cerr << " " << it->first << " received " << time(NULL)-it->second << " secs ago." << std::endl; -#endif - delete *it ; - continue ; - } - else if(NULL != (mtt = dynamic_cast(*it))) - { - // delete standard tags as they are now save in config - if(mTags.end() == (tagIt = mTags.find(mtt->tagId))) - { - mTags.insert(std::pair(mtt->tagId, mtt)); - } - else - { - delete mTags[mtt->tagId]; - mTags.erase(tagIt); - mTags.insert(std::pair(mtt->tagId, mtt)); - } - - } - else if(NULL != (mti = dynamic_cast(*it))) - { - mMsgTags.insert(std::pair(mti->msgId, mti)); - } - else if(NULL != (msi = dynamic_cast(*it))) - { - srcIdMsgMap.insert(std::pair(msi->msgId, msi->srcId)); - mSrcIds.insert(std::pair(msi->msgId, msi)); // does not need to be kept - } - else if(NULL != (msp = dynamic_cast(*it))) - { - mParentId.insert(std::pair(msp->msgId, msp)); - } - - RsConfigKeyValueSet *vitem = NULL ; - - if(NULL != (vitem = dynamic_cast(*it))) - { - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if(kit->key == "DISTANT_MESSAGES_ENABLED") - { -#ifdef MSG_DEBUG - std::cerr << "Loaded config default nick name for distant chat: " << kit->value << std::endl ; -#endif - mShouldEnableDistantMessaging = (kit->value == "YES") ; - } - if(kit->key == "DISTANT_MESSAGE_PERMISSION_FLAGS") - { -#ifdef MSG_DEBUG - std::cerr << "Loaded distant message permission flags: " << kit->value << std::endl ; -#endif - if (!kit->value.empty()) - { - std::istringstream is(kit->value) ; - - uint32_t tmp ; - is >> tmp ; - - if(tmp < 3) - mDistantMessagePermissions = tmp ; - else - std::cerr << "(EE) Invalid value read for DistantMessagePermission flags in config: " << tmp << std::endl; - } - } - } - - delete *it ; - continue ; - } - } - mMsgUniqueId = max_msg_id + 1; // make it unique with respect to what was loaded. Not totally safe, but works 99.9999% of the cases. - load.clear() ; - - // sort items into lists - std::list::iterator msgIt; - for (msgIt = items.begin(); msgIt != items.end(); ++msgIt) - { - mitem = *msgIt; - - /* STORE MsgID */ - if (mitem->msgId == 0) { - mitem->msgId = getNewUniqueMsgId(); - } - - RS_STACK_MUTEX(mMsgMtx); - - srcIt = srcIdMsgMap.find(mitem->msgId); - if(srcIt != srcIdMsgMap.end()) { - mitem->PeerId(srcIt->second); - srcIdMsgMap.erase(srcIt); - } - - /* switch depending on the PENDING - * flags - */ - if (mitem -> msgFlags & RS_MSG_FLAGS_PENDING) - { - - //std::cerr << "MSG_PENDING"; - //std::cerr << std::endl; - //mitem->print(std::cerr); - - msgOutgoing[mitem->msgId] = mitem; - } - else - { - imsg[mitem->msgId] = mitem; - } - } - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - /* remove missing msgId in mSrcIds */ - for (srcIt = srcIdMsgMap.begin(); srcIt != srcIdMsgMap.end(); ++srcIt) { - std::map::iterator it = mSrcIds.find(srcIt->first); - if (it != mSrcIds.end()) { - delete(it->second); - mSrcIds.erase(it); - } - } - - /* remove missing msgId in mParentId */ - std::map::iterator mit = mParentId.begin(); - while (mit != mParentId.end()) { - if (imsg.find(mit->first) == imsg.end()) { - if (msgOutgoing.find(mit->first) == msgOutgoing.end()) { - /* not found */ - mParentId.erase(mit++); - continue; - } - } - - ++mit; - } - - return true; -} - -void p3MsgService::loadWelcomeMsg() -{ - /* Load Welcome Message */ - RsMsgItem *msg = new RsMsgItem(); - - //msg -> PeerId(mServiceCtrl->getOwnId()); - - msg -> sendTime = time(NULL); - msg -> recvTime = time(NULL); - msg -> msgFlags = RS_MSG_FLAGS_NEW; - - msg -> subject = "Welcome to Retroshare"; - - msg -> message = "Send and receive messages with your friends...\n"; - msg -> message += "These can hold recommendations from your local shared files.\n\n"; - msg -> message += "Add recommendations through the Local Files Dialog.\n\n"; - msg -> message += "Enjoy."; - - msg -> msgId = getNewUniqueMsgId(); - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - imsg[msg->msgId] = msg; - - IndicateConfigChanged(); -} - - -/***********************************************************************/ -/***********************************************************************/ -/***********************************************************************/ -/***********************************************************************/ - - -/****************************************/ -/****************************************/ - -bool p3MsgService::getMessageSummaries(std::list &msgList) -{ - /* do stuff */ - msgList.clear(); - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator mit; - for(mit = imsg.begin(); mit != imsg.end(); ++mit) - { - MsgInfoSummary mis; - initRsMIS(mit->second, mis); - msgList.push_back(mis); - } - - for(mit = msgOutgoing.begin(); mit != msgOutgoing.end(); ++mit) - { - MsgInfoSummary mis; - initRsMIS(mit->second, mis); - msgList.push_back(mis); - } - return true; -} - -bool p3MsgService::getMessage(const std::string &mId, MessageInfo &msg) -{ - std::map::iterator mit; - uint32_t msgId = atoi(mId.c_str()); - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - mit = imsg.find(msgId); - if (mit == imsg.end()) - { - mit = msgOutgoing.find(msgId); - if (mit == msgOutgoing.end()) - { - return false; - } - } - - /* mit valid */ - initRsMI(mit->second, msg); - - std::map::const_iterator it = mSrcIds.find(msgId) ; - if(it != mSrcIds.end()) - msg.rsgxsid_srcId = RsGxsId(it->second->srcId) ; // (cyril) this is a hack. Not good. I'm not removing it because it may have consequences, but I dont like this. - - return true; -} - -void p3MsgService::getMessageCount(uint32_t &nInbox, uint32_t &nInboxNew, uint32_t &nOutbox, uint32_t &nDraftbox, uint32_t &nSentbox, uint32_t &nTrashbox) -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - nInbox = 0; - nInboxNew = 0; - nOutbox = 0; - nDraftbox = 0; - nSentbox = 0; - nTrashbox = 0; - - std::map::iterator mit; - std::map *apMsg [2] = { &imsg, &msgOutgoing }; - - for (int i = 0; i < 2; i++) { - for (mit = apMsg [i]->begin(); mit != apMsg [i]->end(); ++mit) { - MsgInfoSummary mis; - initRsMIS(mit->second, mis); - - if (mis.msgflags & RS_MSG_TRASH) { - ++nTrashbox; - continue; - } - switch (mis.msgflags & RS_MSG_BOXMASK) { - case RS_MSG_INBOX: - ++nInbox; - if ((mis.msgflags & RS_MSG_NEW) == RS_MSG_NEW) - ++nInboxNew; - break; - case RS_MSG_OUTBOX: - ++nOutbox; - break; - case RS_MSG_DRAFTBOX: - ++nDraftbox; - break; - case RS_MSG_SENTBOX: - ++nSentbox; - break; - } - } - } -} - -/* remove based on the unique mid (stored in sid) */ -bool p3MsgService::removeMsgId(const std::string &mid) -{ - std::map::iterator mit; - uint32_t msgId = atoi(mid.c_str()); - if (msgId == 0) { - std::cerr << "p3MsgService::removeMsgId: Unknown msgId " << msgId << std::endl; - return false; - } - - bool changed = false; - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_REMOVED; - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - mit = imsg.find(msgId); - if (mit != imsg.end()) - { - changed = true; - RsMsgItem *mi = mit->second; - imsg.erase(mit); - delete mi; - pEvent->mChangedMsgIds.insert(mid); - } - - mit = msgOutgoing.find(msgId); - if (mit != msgOutgoing.end()) - { - changed = true ; - RsMsgItem *mi = mit->second; - msgOutgoing.erase(mit); - delete mi; - pEvent->mChangedMsgIds.insert(mid); - } - - std::map::iterator srcIt = mSrcIds.find(msgId); - if (srcIt != mSrcIds.end()) { - changed = true; - delete (srcIt->second); - mSrcIds.erase(srcIt); - pEvent->mChangedMsgIds.insert(mid); - } - } - - if(changed) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - setMessageTag(mid, 0, false); - setMsgParentId(msgId, 0); - - RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); - } - - if(rsEvents && !pEvent->mChangedMsgIds.empty()) - rsEvents->postEvent(pEvent); - - return changed; -} - -bool p3MsgService::markMsgIdRead(const std::string &mid, bool unreadByUser) -{ - std::map::iterator mit; - uint32_t msgId = atoi(mid.c_str()); - bool changed = false; - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - mit = imsg.find(msgId); - if (mit != imsg.end()) - { - RsMsgItem *mi = mit->second; - - uint32_t msgFlags = mi->msgFlags; - - /* remove new state */ - mi->msgFlags &= ~(RS_MSG_FLAGS_NEW); - - /* set state from user */ - if (unreadByUser) { - mi->msgFlags |= RS_MSG_FLAGS_UNREAD_BY_USER; - } else { - mi->msgFlags &= ~RS_MSG_FLAGS_UNREAD_BY_USER; - } - - if (mi->msgFlags != msgFlags) - { - changed = true; - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } - } else { - return false; - } - } /* UNLOCKED */ - - if (changed) { - RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); - } - - return true; -} - -bool p3MsgService::setMsgFlag(const std::string &mid, uint32_t flag, uint32_t mask) -{ - std::map::iterator mit; - uint32_t msgId = atoi(mid.c_str()); - - bool changed = false; - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - mit = imsg.find(msgId); - if (mit == imsg.end()) - { - mit = msgOutgoing.find(msgId); - if (mit == msgOutgoing.end()) - { - return false; - } - } - - uint32_t oldFlag = mit->second->msgFlags; - - mit->second->msgFlags &= ~mask; - mit->second->msgFlags |= flag; - - if (mit->second->msgFlags != oldFlag) { - changed = true; - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } - } /* UNLOCKED */ - - if (changed) { - RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); - } - - return true; -} - -bool p3MsgService::getMsgParentId(const std::string &msgId, std::string &msgParentId) -{ - msgParentId.clear(); - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator mit = mParentId.find(atoi(msgId.c_str())); - if (mit == mParentId.end()) { - return false; - } - - rs_sprintf(msgParentId, "%lu", mit->second->msgParentId); - - return true; -} - -bool p3MsgService::setMsgParentId(uint32_t msgId, uint32_t msgParentId) -{ - std::map::iterator mit; - - bool changed = false; - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - mit = mParentId.find(msgId); - if (mit == mParentId.end()) - { - if (msgParentId) { - RsMsgParentId* msp = new RsMsgParentId(); - msp->PeerId (mServiceCtrl->getOwnId()); - msp->msgId = msgId; - msp->msgParentId = msgParentId; - mParentId.insert(std::pair(msgId, msp)); - - changed = true; - } - } else { - if (msgParentId) { - if (mit->second->msgParentId != msgParentId) { - mit->second->msgParentId = msgParentId; - changed = true; - } - } else { - delete mit->second; - mParentId.erase(mit); - changed = true; - } - } - } /* UNLOCKED */ - - if (changed) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } - - return true; -} - -/****************************************/ -/****************************************/ - /* Message Items */ -// no from field because it's implicitly our own PeerId -uint32_t p3MsgService::sendMessage(RsMsgItem* item) -{ - if(!item) - { - RsErr() << __PRETTY_FUNCTION__ << " item can't be null" << std::endl; - return 0; - } - - item->msgId = getNewUniqueMsgId(); /* grabs Mtx as well */ - item->msgFlags |= (RS_MSG_FLAGS_OUTGOING | RS_MSG_FLAGS_PENDING); /* add pending flag */ - - { - RS_STACK_MUTEX(mMsgMtx) ; - - /* STORE MsgID */ - msgOutgoing[item->msgId] = item; - - if (item->PeerId() != mServiceCtrl->getOwnId()) - { - /* not to the loopback device */ - - RsMsgSrcId* msi = new RsMsgSrcId(); - msi->msgId = item->msgId; - msi->srcId = mServiceCtrl->getOwnId(); - mSrcIds.insert(std::pair(msi->msgId, msi)); - } - } - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST, NOTIFY_TYPE_ADD); // deprecated - - return item->msgId; -} - -uint32_t p3MsgService::sendDistantMessage(RsMsgItem *item, const RsGxsId& from) -{ - if(!item) - { - RsErr() << __PRETTY_FUNCTION__ << " item can't be null" << std::endl; - print_stacktrace(); - return 0; - } - - item->msgId = getNewUniqueMsgId(); /* grabs Mtx as well */ - item->msgFlags |= ( RS_MSG_FLAGS_DISTANT | RS_MSG_FLAGS_OUTGOING | - RS_MSG_FLAGS_PENDING ); /* add pending flag */ - - { - RS_STACK_MUTEX(mMsgMtx); - - /* STORE MsgID */ - msgOutgoing[item->msgId] = item; - mDistantOutgoingMsgSigners[item->msgId] = from ; - - if (item->PeerId() != mServiceCtrl->getOwnId()) - { - /* not to the loopback device */ - - RsMsgSrcId* msi = new RsMsgSrcId(); - msi->msgId = item->msgId; - msi->srcId = RsPeerId(from); - mSrcIds.insert(std::pair(msi->msgId, msi)); - } - } - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - RsServer::notify()->notifyListChange( NOTIFY_LIST_MESSAGELIST, - NOTIFY_TYPE_ADD ); - return item->msgId; -} - -bool p3MsgService::MessageSend(MessageInfo &info) -{ - for(std::set::const_iterator pit = info.rspeerid_msgto.begin(); pit != info.rspeerid_msgto.end(); ++pit) sendMessage(initMIRsMsg(info, *pit)); - for(std::set::const_iterator pit = info.rspeerid_msgcc.begin(); pit != info.rspeerid_msgcc.end(); ++pit) sendMessage(initMIRsMsg(info, *pit)); - for(std::set::const_iterator pit = info.rspeerid_msgbcc.begin(); pit != info.rspeerid_msgbcc.end(); ++pit) sendMessage(initMIRsMsg(info, *pit)); - - for(std::set::const_iterator pit = info.rsgxsid_msgto.begin(); pit != info.rsgxsid_msgto.end(); ++pit) sendDistantMessage(initMIRsMsg(info, *pit),info.rsgxsid_srcId); - for(std::set::const_iterator pit = info.rsgxsid_msgcc.begin(); pit != info.rsgxsid_msgcc.end(); ++pit) sendDistantMessage(initMIRsMsg(info, *pit),info.rsgxsid_srcId); - for(std::set::const_iterator pit = info.rsgxsid_msgbcc.begin(); pit != info.rsgxsid_msgbcc.end(); ++pit) sendDistantMessage(initMIRsMsg(info, *pit),info.rsgxsid_srcId); - - // store message in outgoing list. In order to appear as sent the message needs to have the OUTGOING flg, but no pending flag on. - - RsMsgItem *msg = initMIRsMsg(info, mServiceCtrl->getOwnId()); - - if (msg) - { - if (msg->msgFlags & RS_MSG_FLAGS_SIGNED) - msg->msgFlags |= RS_MSG_FLAGS_SIGNATURE_CHECKS; // this is always true, since we are sending the message - - /* use processMsg to get the new msgId */ - msg->recvTime = time(NULL); - msg->msgId = getNewUniqueMsgId(); - - msg->msgFlags |= RS_MSG_OUTGOING; - - imsg[msg->msgId] = msg; - - // Update info for caller - info.msgId = std::to_string(msg->msgId); - info .msgflags = msg->msgFlags; - - RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_ADD);// deprecated. Should be removed. Oct. 28, 2020 - } - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_SENT; - pEvent->mChangedMsgIds.insert(std::to_string(msg->msgId)); - rsEvents->postEvent(pEvent); - - return true; -} - -uint32_t p3MsgService::sendMail( - const RsGxsId from, - const std::string& subject, - const std::string& body, - const std::set& to, - const std::set& cc, - const std::set& bcc, - const std::vector& attachments, - std::set& trackingIds, - std::string& errorMsg ) -{ - errorMsg.clear(); - const std::string fname = __PRETTY_FUNCTION__; - auto pCheck = [&](bool test, const std::string& errMsg) - { - if(!test) - { - errorMsg = errMsg; - RsErr() << fname << " " << errMsg << std::endl; - } - return test; - }; - - if(!pCheck(!from.isNull(), "from can't be null")) return false; - if(!pCheck( rsIdentity->isOwnId(from), - "from must be own identity") ) return false; - if(!pCheck(!(to.empty() && cc.empty() && bcc.empty()), - "You must specify at least one recipient" )) return false; - - auto dstCheck = - [&](const std::set& dstSet, const std::string& setName) - { - for(const RsGxsId& dst: dstSet) - { - if(dst.isNull()) - { - errorMsg = setName + " contains a null recipient"; - RsErr() << fname << " " << errorMsg << std::endl; - return false; - } - - if(!rsIdentity->isKnownId(dst)) - { - rsIdentity->requestIdentity(dst); - errorMsg = setName + " contains an unknown recipient: " + - dst.toStdString(); - RsErr() << fname << " " << errorMsg << std::endl; - return false; - } - } - return true; - }; - - if(!dstCheck(to, "to")) return false; - if(!dstCheck(cc, "cc")) return false; - if(!dstCheck(bcc, "bcc")) return false; - - MessageInfo msgInfo; - - msgInfo.rsgxsid_srcId = from; - msgInfo.title = subject; - msgInfo.msg = body; - msgInfo.rsgxsid_msgto = to; - msgInfo.rsgxsid_msgcc = cc; - msgInfo.rsgxsid_msgbcc = bcc; - std::copy( attachments.begin(), attachments.end(), - std::back_inserter(msgInfo.files) ); - - uint32_t ret = 0; - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_SENT; - - auto pSend = [&](const std::set& sDest) - { - for(const RsGxsId& dst : sDest) - { - RsMsgItem* msgItem = initMIRsMsg(msgInfo, dst); - if(!msgItem) - { - errorMsg += " initMIRsMsg from: " + from.toStdString() - + " dst: " + dst.toStdString() + " subject: " + subject - + " returned nullptr!\n"; - RsErr() << fname << errorMsg; - continue; - } - - uint32_t msgId = sendDistantMessage(msgItem, from); - // ensure we don't use that ptr again without noticing - msgItem = nullptr; - - if(!msgId) - { - errorMsg += " sendDistantMessage from: " + from.toStdString() - + " dst: " + dst.toStdString() + " subject: " + subject - + " returned 0!\n"; - RsErr() << fname << errorMsg; - continue; - } - - const RsMailMessageId mailId = std::to_string(msgId); - pEvent->mChangedMsgIds.insert(mailId); - trackingIds.insert(RsMailIdRecipientIdPair(mailId, dst)); - ++ret; - } - }; - - pSend(to); - pSend(cc); - pSend(bcc); - - if(rsEvents) rsEvents->postEvent(pEvent); - return ret; -} - -bool p3MsgService::SystemMessage(const std::string &title, const std::string &message, uint32_t systemFlag) -{ - if ((systemFlag & RS_MSG_SYSTEM) == 0) { - /* no flag specified */ - return false; - } - - - RsMsgItem *msg = new RsMsgItem(); - - msg->PeerId();// Notification == null - - msg->msgFlags = 0; - - if (systemFlag & RS_MSG_USER_REQUEST) { - msg->msgFlags |= RS_MSG_FLAGS_USER_REQUEST; - } - if (systemFlag & RS_MSG_FRIEND_RECOMMENDATION) { - msg->msgFlags |= RS_MSG_FLAGS_FRIEND_RECOMMENDATION; - } - if (systemFlag & RS_MSG_PUBLISH_KEY) { - msg->msgFlags |= RS_MSG_FLAGS_PUBLISH_KEY; - } - - msg->msgId = 0; - msg->sendTime = time(NULL); - msg->recvTime = 0; - - msg->subject = title; - msg->message = message; - - msg->rspeerid_msgto.ids.insert(mServiceCtrl->getOwnId()); - - processIncomingMsg(msg); - - return true; -} - -bool p3MsgService::MessageToDraft(MessageInfo &info, const std::string &msgParentId) -{ - RsMsgItem *msg = initMIRsMsg(info, mServiceCtrl->getOwnId()); - if (msg) - { - uint32_t msgId = 0; - if (info.msgId.empty() == false) { - msgId = atoi(info.msgId.c_str()); - } - - if (msgId) { - msg->msgId = msgId; - } else { - msg->msgId = getNewUniqueMsgId(); /* grabs Mtx as well */ - } - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - /* add pending flag */ - msg->msgFlags |= (RS_MSG_OUTGOING | RS_MSG_FLAGS_DRAFT); - - if (msgId) { - // remove existing message - std::map::iterator mit; - mit = imsg.find(msgId); - if (mit != imsg.end()) { - RsMsgItem *mi = mit->second; - imsg.erase(mit); - delete mi; - } - } - /* STORE MsgID */ - imsg[msg->msgId] = msg; - - // return new message id - rs_sprintf(info.msgId, "%lu", msg->msgId); - } - - setMsgParentId(msg->msgId, atoi(msgParentId.c_str())); - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - // RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_SENT; - rsEvents->postEvent(pEvent); - - return true; - } - - return false; -} - -bool p3MsgService::getMessageTag(const std::string &msgId, Rs::Msgs::MsgTagInfo& info) -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - return locked_getMessageTag(msgId,info); -} - -bool p3MsgService::getMessageTagTypes(MsgTagType& tags) -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator mit; - - for(mit = mTags.begin(); mit != mTags.end(); ++mit) { - std::pair p(mit->second->text, mit->second->rgb_color); - tags.types.insert(std::pair >(mit->first, p)); - } - - return true; -} - -bool p3MsgService::setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color) -{ - int nNotifyType = 0; - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator mit; - mit = mTags.find(tagId); - - if (mit == mTags.end()) { - if (tagId < RS_MSGTAGTYPE_USER) { - std::cerr << "p3MsgService::MessageSetTagType: Standard tag type " << tagId << " cannot be inserted" << std::endl; - return false; - } - - /* new tag */ - RsMsgTagType* tagType = new RsMsgTagType(); - tagType->PeerId (mServiceCtrl->getOwnId()); - tagType->rgb_color = rgb_color; - tagType->tagId = tagId; - tagType->text = text; - - mTags.insert(std::pair(tagId, tagType)); - - nNotifyType = NOTIFY_TYPE_ADD; - } else { - if (mit->second->text != text || mit->second->rgb_color != rgb_color) { - /* modify existing tag */ - if (tagId >= RS_MSGTAGTYPE_USER) { - mit->second->text = text; - } else { - /* don't change text for standard tag types */ - if (mit->second->text != text) { - std::cerr << "p3MsgService::MessageSetTagType: Text " << text << " for standard tag type " << tagId << " cannot be changed" << std::endl; - } - } - mit->second->rgb_color = rgb_color; - - nNotifyType = NOTIFY_TYPE_MOD; - } - } - - } /* UNLOCKED */ - - if (nNotifyType) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGE_TAGS, nNotifyType); - - return true; - } - - return false; -} - -bool p3MsgService::removeMessageTagType(uint32_t tagId) -{ - if (tagId < RS_MSGTAGTYPE_USER) { - std::cerr << "p3MsgService::MessageRemoveTagType: Can't delete standard tag type " << tagId << std::endl; - return false; - } - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator mit; - mit = mTags.find(tagId); - - if (mit == mTags.end()) { - /* tag id not found */ - std::cerr << "p3MsgService::MessageRemoveTagType: Tag Id not found " << tagId << std::endl; - return false; - } - - /* search for messages with this tag type */ - std::map::iterator mit1; - for (mit1 = mMsgTags.begin(); mit1 != mMsgTags.end(); ) { - RsMsgTags* tag = mit1->second; - - std::list::iterator lit; - lit = std::find(tag->tagIds.begin(), tag->tagIds.end(), tagId); - if (lit != tag->tagIds.end()) { - tag->tagIds.erase(lit); - - if (tag->tagIds.empty()) { - /* remove empty tag */ - delete(tag); - - mMsgTags.erase(mit1++); - continue; - } - } - ++mit1; - } - - /* remove tag type */ - delete(mit->second); - mTags.erase(mit); - - } /* UNLOCKED */ - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGE_TAGS, NOTIFY_TYPE_DEL); - - return true; -} - -bool p3MsgService::locked_getMessageTag(const std::string &msgId, MsgTagInfo& info) -{ - uint32_t mid = atoi(msgId.c_str()); - if (mid == 0) { - std::cerr << "p3MsgService::MessageGetMsgTag: Unknown msgId " << msgId << std::endl; - return false; - } - - std::map::iterator mit; - - if(mMsgTags.end() != (mit = mMsgTags.find(mid))) { - rs_sprintf(info.msgId, "%lu", mit->second->msgId); - info.tagIds = mit->second->tagIds; - - return true; - } - - return false; -} - -/* set == false && tagId == 0 --> remove all */ -bool p3MsgService::setMessageTag(const std::string &msgId, uint32_t tagId, bool set) -{ - uint32_t mid = atoi(msgId.c_str()); - if (mid == 0) { - std::cerr << "p3MsgService::MessageSetMsgTag: Unknown msgId " << msgId << std::endl; - return false; - } - - if (tagId == 0) { - if (set == true) { - std::cerr << "p3MsgService::MessageSetMsgTag: No valid tagId given " << tagId << std::endl; - return false; - } - } - - int nNotifyType = 0; - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator mit; - mit = mMsgTags.find(mid); - - if (mit == mMsgTags.end()) { - if (set) { - /* new msg */ - RsMsgTags* tag = new RsMsgTags(); - tag->PeerId (mServiceCtrl->getOwnId()); - - tag->msgId = mid; - tag->tagIds.push_back(tagId); - - mMsgTags.insert(std::pair(tag->msgId, tag)); - - nNotifyType = NOTIFY_TYPE_ADD; - } - } else { - RsMsgTags* tag = mit->second; - - /* search existing tagId */ - std::list::iterator lit; - if (tagId) { - lit = std::find(tag->tagIds.begin(), tag->tagIds.end(), tagId); - } else { - lit = tag->tagIds.end(); - } - - if (set) { - if (lit == tag->tagIds.end()) { - tag->tagIds.push_back(tagId); - /* keep the list sorted */ - tag->tagIds.sort(); - nNotifyType = NOTIFY_TYPE_ADD; - } - } else { - if (tagId == 0) { - /* remove all */ - delete(tag); - mMsgTags.erase(mit); - nNotifyType = NOTIFY_TYPE_DEL; - } else { - if (lit != tag->tagIds.end()) { - tag->tagIds.erase(lit); - nNotifyType = NOTIFY_TYPE_DEL; - - if (tag->tagIds.empty()) { - /* remove empty tag */ - delete(tag); - mMsgTags.erase(mit); - } - } - } - } - } - - } /* UNLOCKED */ - - if (nNotifyType) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGE_TAGS, nNotifyType); - - return true; - } - - return false; -} - -bool p3MsgService::resetMessageStandardTagTypes(MsgTagType& tags) -{ - MsgTagType standardTags; - getStandardTagTypes(standardTags); - - std::map >::iterator mit; - for (mit = standardTags.types.begin(); mit != standardTags.types.end(); ++mit) { - tags.types[mit->first] = mit->second; - } - - return true; -} - -/* move message to trash based on the unique mid */ -bool p3MsgService::MessageToTrash(const std::string &mid, bool bTrash) -{ - std::map::iterator mit; - uint32_t msgId = atoi(mid.c_str()); - - bool bChanged = false; - bool bFound = false; - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - RsMsgItem *mi = NULL; - - mit = imsg.find(msgId); - if (mit != imsg.end()) { - mi = mit->second; - } else { - mit = msgOutgoing.find(msgId); - if (mit != msgOutgoing.end()) { - mi = mit->second; - } - } - - if (mi) { - bFound = true; - - if (bTrash) { - if ((mi->msgFlags & RS_MSG_FLAGS_TRASH) == 0) { - mi->msgFlags |= RS_MSG_FLAGS_TRASH; - bChanged = true; - } - } else { - if (mi->msgFlags & RS_MSG_FLAGS_TRASH) { - mi->msgFlags &= ~RS_MSG_FLAGS_TRASH; - bChanged = true; - } - } - } - } - - if (bChanged) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - checkOutgoingMessages(); - - RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); - } - - return bFound; -} - -/****************************************/ -/****************************************/ - - -/****************************************/ - -/**** HELPER FNS For Chat/Msg/Channel Lists ************ - * These aren't required to be locked, unless - * the data used is from internal stores -> then they should be. - */ - -void p3MsgService::initRsMI(RsMsgItem *msg, MessageInfo &mi) -{ - - mi.msgflags = 0; - - /* translate flags, if we sent it... outgoing */ - - if (msg->msgFlags & RS_MSG_FLAGS_OUTGOING) mi.msgflags |= RS_MSG_OUTGOING; - if (msg->msgFlags & RS_MSG_FLAGS_PENDING) mi.msgflags |= RS_MSG_PENDING; /* if it has a pending flag, then its in the outbox */ - if (msg->msgFlags & RS_MSG_FLAGS_DRAFT) mi.msgflags |= RS_MSG_DRAFT; - if (msg->msgFlags & RS_MSG_FLAGS_NEW) mi.msgflags |= RS_MSG_NEW; - - if (msg->msgFlags & RS_MSG_FLAGS_SIGNED) mi.msgflags |= RS_MSG_SIGNED ; - if (msg->msgFlags & RS_MSG_FLAGS_SIGNATURE_CHECKS) mi.msgflags |= RS_MSG_SIGNATURE_CHECKS ; - if (msg->msgFlags & RS_MSG_FLAGS_DISTANT) mi.msgflags |= RS_MSG_DISTANT ; - if (msg->msgFlags & RS_MSG_FLAGS_TRASH) mi.msgflags |= RS_MSG_TRASH; - if (msg->msgFlags & RS_MSG_FLAGS_UNREAD_BY_USER) mi.msgflags |= RS_MSG_UNREAD_BY_USER; - if (msg->msgFlags & RS_MSG_FLAGS_REPLIED) mi.msgflags |= RS_MSG_REPLIED; - if (msg->msgFlags & RS_MSG_FLAGS_FORWARDED) mi.msgflags |= RS_MSG_FORWARDED; - if (msg->msgFlags & RS_MSG_FLAGS_STAR) mi.msgflags |= RS_MSG_STAR; - if (msg->msgFlags & RS_MSG_FLAGS_SPAM) mi.msgflags |= RS_MSG_SPAM; - if (msg->msgFlags & RS_MSG_FLAGS_USER_REQUEST) mi.msgflags |= RS_MSG_USER_REQUEST; - if (msg->msgFlags & RS_MSG_FLAGS_FRIEND_RECOMMENDATION) mi.msgflags |= RS_MSG_FRIEND_RECOMMENDATION; - if (msg->msgFlags & RS_MSG_FLAGS_PUBLISH_KEY) mi.msgflags |= RS_MSG_PUBLISH_KEY; - if (msg->msgFlags & RS_MSG_FLAGS_LOAD_EMBEDDED_IMAGES) mi.msgflags |= RS_MSG_LOAD_EMBEDDED_IMAGES; - - mi.ts = msg->sendTime; - mi.rspeerid_srcId = msg->PeerId(); - - mi.rspeerid_msgto = msg->rspeerid_msgto.ids ; - mi.rspeerid_msgcc = msg->rspeerid_msgcc.ids ; - mi.rspeerid_msgbcc = msg->rspeerid_msgbcc.ids ; - - mi.rsgxsid_msgto = msg->rsgxsid_msgto.ids ; - mi.rsgxsid_msgcc = msg->rsgxsid_msgcc.ids ; - mi.rsgxsid_msgbcc = msg->rsgxsid_msgbcc.ids ; - - mi.title = msg->subject; - mi.msg = msg->message; - { - //msg->msgId; - rs_sprintf(mi.msgId, "%lu", msg->msgId); - } - - mi.attach_title = msg->attachment.title; - mi.attach_comment = msg->attachment.comment; - - mi.count = 0; - mi.size = 0; - - for(std::list::iterator it = msg->attachment.items.begin(); it != msg->attachment.items.end(); ++it) - { - FileInfo fi; - fi.fname = RsDirUtil::getTopDir(it->name); - fi.size = it->filesize; - fi.hash = it->hash; - fi.path = it->path; - mi.files.push_back(fi); - mi.count++; - mi.size += fi.size; - } -} - -void p3MsgService::initRsMIS(RsMsgItem *msg, MsgInfoSummary &mis) -{ - mis.msgflags = 0; - - if(msg->msgFlags & RS_MSG_FLAGS_DISTANT) - mis.msgflags |= RS_MSG_DISTANT ; - - if (msg->msgFlags & RS_MSG_FLAGS_SIGNED) - mis.msgflags |= RS_MSG_SIGNED ; - - if (msg->msgFlags & RS_MSG_FLAGS_SIGNATURE_CHECKS) - mis.msgflags |= RS_MSG_SIGNATURE_CHECKS ; - - /* translate flags, if we sent it... outgoing */ - if ((msg->msgFlags & RS_MSG_FLAGS_OUTGOING) - /*|| (msg->PeerId() == mServiceCtrl->getOwnId())*/) - { - mis.msgflags |= RS_MSG_OUTGOING; - } - /* if it has a pending flag, then its in the outbox */ - if (msg->msgFlags & RS_MSG_FLAGS_PENDING) - { - mis.msgflags |= RS_MSG_PENDING; - } - if (msg->msgFlags & RS_MSG_FLAGS_DRAFT) - { - mis.msgflags |= RS_MSG_DRAFT; - } - if (msg->msgFlags & RS_MSG_FLAGS_NEW) - { - mis.msgflags |= RS_MSG_NEW; - } - if (msg->msgFlags & RS_MSG_FLAGS_TRASH) - { - mis.msgflags |= RS_MSG_TRASH; - } - if (msg->msgFlags & RS_MSG_FLAGS_UNREAD_BY_USER) - { - mis.msgflags |= RS_MSG_UNREAD_BY_USER; - } - if (msg->msgFlags & RS_MSG_FLAGS_REPLIED) - { - mis.msgflags |= RS_MSG_REPLIED; - } - if (msg->msgFlags & RS_MSG_FLAGS_FORWARDED) - { - mis.msgflags |= RS_MSG_FORWARDED; - } - if (msg->msgFlags & RS_MSG_FLAGS_STAR) - { - mis.msgflags |= RS_MSG_STAR; - } - if (msg->msgFlags & RS_MSG_FLAGS_SPAM) - { - mis.msgflags |= RS_MSG_SPAM; - } - if (msg->msgFlags & RS_MSG_FLAGS_USER_REQUEST) - { - mis.msgflags |= RS_MSG_USER_REQUEST; - } - if (msg->msgFlags & RS_MSG_FLAGS_FRIEND_RECOMMENDATION) - { - mis.msgflags |= RS_MSG_FRIEND_RECOMMENDATION; - } - if (msg->msgFlags & RS_MSG_FLAGS_PUBLISH_KEY) - { - mis.msgflags |= RS_MSG_PUBLISH_KEY; - } - if (msg->msgFlags & RS_MSG_FLAGS_LOAD_EMBEDDED_IMAGES) - { - mis.msgflags |= RS_MSG_LOAD_EMBEDDED_IMAGES; - } - - mis.srcId = msg->PeerId(); - { - //msg->msgId; - rs_sprintf(mis.msgId, "%lu", msg->msgId); - } - - mis.title = msg->subject; - mis.count = msg->attachment.items.size(); - mis.ts = msg->sendTime; - - MsgTagInfo taginfo; - locked_getMessageTag(mis.msgId,taginfo); - mis.msgtags = taginfo.tagIds ; -} - -void p3MsgService::initMIRsMsg(RsMsgItem *msg,const MessageInfo& info) -{ - msg -> msgFlags = 0; - msg -> msgId = 0; - msg -> sendTime = time(NULL); - msg -> recvTime = 0; - msg -> subject = info.title; - msg -> message = info.msg; - - msg->rspeerid_msgto.ids = info.rspeerid_msgto ; - msg->rspeerid_msgcc.ids = info.rspeerid_msgcc ; - - msg->rsgxsid_msgto.ids = info.rsgxsid_msgto ; - msg->rsgxsid_msgcc.ids = info.rsgxsid_msgcc ; - - /* We don't fill in bcc (unless to ourselves) */ - - if (msg->PeerId() == mServiceCtrl->getOwnId()) - { - msg->rsgxsid_msgbcc.ids = info.rsgxsid_msgbcc ; - msg->rspeerid_msgbcc.ids = info.rspeerid_msgbcc ; - } - - msg -> attachment.title = info.attach_title; - msg -> attachment.comment = info.attach_comment; - - for(std::list::const_iterator it = info.files.begin(); it != info.files.end(); ++it) - { - RsTlvFileItem mfi; - mfi.hash = it -> hash; - mfi.name = it -> fname; - mfi.filesize = it -> size; - msg -> attachment.items.push_back(mfi); - } - /* translate flags from outside */ - if (info.msgflags & RS_MSG_USER_REQUEST) - msg->msgFlags |= RS_MSG_FLAGS_USER_REQUEST; - - if (info.msgflags & RS_MSG_FRIEND_RECOMMENDATION) - msg->msgFlags |= RS_MSG_FLAGS_FRIEND_RECOMMENDATION; -} -RsMsgItem *p3MsgService::initMIRsMsg(const MessageInfo& info, const RsGxsId& to) -{ - RsMsgItem *msg = new RsMsgItem(); - - initMIRsMsg(msg,info) ; - - msg->PeerId(RsPeerId(to)); - msg->msgFlags |= RS_MSG_FLAGS_DISTANT; - - if (info.msgflags & RS_MSG_SIGNED) - msg->msgFlags |= RS_MSG_FLAGS_SIGNED; - -// // We replace the msg text by the whole message serialized possibly signed, -// // and binary encrypted, so as to obfuscate all its content. -// // -// if(!createDistantMessage(to,info.rsgxsid_srcId,msg)) -// { -// std::cerr << "Cannot encrypt distant message. Something went wrong." << std::endl; -// delete msg ; -// return NULL ; -// } - - return msg ; -} - -RsMsgItem *p3MsgService::initMIRsMsg(const MessageInfo &info, const RsPeerId& to) -{ - RsMsgItem *msg = new RsMsgItem(); - - initMIRsMsg(msg,info) ; - - msg->PeerId(to) ; - - /* load embedded images from own messages */ - msg->msgFlags |= RS_MSG_FLAGS_LOAD_EMBEDDED_IMAGES; - - return msg; -} - -void p3MsgService::connectToGlobalRouter(p3GRouter *gr) -{ - mGRouter = gr ; - gr->registerClientService(GROUTER_CLIENT_ID_MESSAGES,this) ; -} - -void p3MsgService::enableDistantMessaging(bool b) -{ - // We use a temporary variable because the call to OwnIds() might fail. - - mShouldEnableDistantMessaging = b ; - IndicateConfigChanged() ; -} - -bool p3MsgService::distantMessagingEnabled() -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - return mShouldEnableDistantMessaging ; -} - -void p3MsgService::manageDistantPeers() -{ - // now possibly flush pending messages - - if(mShouldEnableDistantMessaging == mDistantMessagingEnabled) - return ; - -#ifdef DEBUG_DISTANT_MSG - std::cerr << "p3MsgService::manageDistantPeers()" << std::endl; -#endif - std::list own_id_list ; - - if(mIdService->getOwnIds(own_id_list)) - { -#ifdef DEBUG_DISTANT_MSG - for(std::list::const_iterator it(own_id_list.begin());it!=own_id_list.end();++it) - std::cerr << (mShouldEnableDistantMessaging?"Enabling":"Disabling") << " distant messaging, with peer id = " << *it << std::endl; -#endif - - for(std::list::const_iterator it(own_id_list.begin());it!=own_id_list.end();++it) - { - if(mShouldEnableDistantMessaging) - mGRouter->registerKey(*it,GROUTER_CLIENT_ID_MESSAGES,"Messaging contact") ; - else - mGRouter->unregisterKey(*it,GROUTER_CLIENT_ID_MESSAGES) ; - } - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - mDistantMessagingEnabled = mShouldEnableDistantMessaging ; - } -} - -void p3MsgService::notifyDataStatus( const GRouterMsgPropagationId& id, - const RsGxsId &signer_id, - uint32_t data_status ) -{ - if(data_status == GROUTER_CLIENT_SERVICE_DATA_STATUS_FAILED) - { - RS_STACK_MUTEX(mMsgMtx); - - auto it = _ongoing_messages.find(id); - if(it == _ongoing_messages.end()) - { - RsErr() << __PRETTY_FUNCTION__ - << " cannot find pending message to acknowledge. " - << "Weird. grouter id: " << id << std::endl; - return; - } - - uint32_t msg_id = it->second; - - RsWarn() << __PRETTY_FUNCTION__ << " Global router tells " - << "us that item ID " << id - << " could not be delivered on time. Message id: " - << msg_id << std::endl; - - /* this is needed because it's not saved in config, but we should - * probably include it in _ongoing_messages */ - mDistantOutgoingMsgSigners[msg_id] = signer_id; - - std::map::iterator mit = msgOutgoing.find(msg_id); - if(mit == msgOutgoing.end()) - { - RsInfo() << __PRETTY_FUNCTION__ - << " message has been notified as not delivered, " - << "but it's not in outgoing list. Probably it has been " - << "delivered successfully by other means." << std::endl; - } - else - { - std::cerr << " reseting the ROUTED flag so that the message is " - << "requested again" << std::endl; - - // clear the routed flag so that the message is requested again - mit->second->msgFlags &= ~RS_MSG_FLAGS_ROUTED; - } - - return; - } - - if(data_status == GROUTER_CLIENT_SERVICE_DATA_STATUS_RECEIVED) - { - RS_STACK_MUTEX(mMsgMtx); -#ifdef DEBUG_DISTANT_MSG - std::cerr << "p3MsgService::acknowledgeDataReceived(): acknowledging data received for msg propagation id " << id << std::endl; -#endif - auto it = _ongoing_messages.find(id); - if(it == _ongoing_messages.end()) - { - std::cerr << " (EE) cannot find pending message to acknowledge. " - << "Weird. grouter id = " << id << std::endl; - return; - } - - uint32_t msg_id = it->second; - - // we should now remove the item from the msgOutgoing list. - std::map::iterator it2 = msgOutgoing.find(msg_id); - if(it2 == msgOutgoing.end()) - { - std::cerr << "(II) message has been notified as delivered, but it's" - << " not in outgoing list. Probably it has been delivered" - << " successfully by other means." << std::endl; - return; - } - -#if 0 - delete it2->second; - msgOutgoing.erase(it2); -#else - // Do not delete it move to sent folder instead! - it2->second->msgFlags &= ~RS_MSG_FLAGS_PENDING; - imsg[msg_id] = it2->second; - msgOutgoing.erase(it2); -#endif - - RsServer::notify()->notifyListChange( NOTIFY_LIST_MESSAGELIST, - NOTIFY_TYPE_ADD ); - IndicateConfigChanged(); - - if(rsEvents) - { - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::NEW_MESSAGE; - pEvent->mChangedMsgIds.insert(std::to_string(msg_id)); - rsEvents->postEvent(pEvent); - } - - return; - } - - RsErr() << __PRETTY_FUNCTION__ - << " unhandled data status info from global router" - << " for msg ID " << id << ": this is a bug." << std::endl; -} - -bool p3MsgService::acceptDataFromPeer(const RsGxsId& to_gxs_id) -{ - if(mDistantMessagePermissions & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS) - return (rsIdentity!=NULL) && rsIdentity->isARegularContact(to_gxs_id) ; - - if(mDistantMessagePermissions & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY) - return false ; - - return true ; -} - -void p3MsgService::setDistantMessagingPermissionFlags(uint32_t flags) -{ - if(flags != mDistantMessagePermissions) - { - mDistantMessagePermissions = flags ; - - IndicateConfigChanged() ; - } -} - -uint32_t p3MsgService::getDistantMessagingPermissionFlags() -{ - return mDistantMessagePermissions ; -} - -bool p3MsgService::receiveGxsTransMail( const RsGxsId& authorId, - const RsGxsId& recipientId, - const uint8_t* data, uint32_t dataSize ) -{ - Dbg2() << __PRETTY_FUNCTION__ << " " << authorId << ", " << recipientId - << ",, " << dataSize << std::endl; - - Sha1CheckSum hash = RsDirUtil::sha1sum(data, dataSize); - - { - RS_STACK_MUTEX(recentlyReceivedMutex); - if( mRecentlyReceivedMessageHashes.find(hash) != mRecentlyReceivedMessageHashes.end() ) - { - RsInfo() << __PRETTY_FUNCTION__ << " (II) receiving " - << "message of hash " << hash << " more than once. " - << "Probably it has arrived before by other means." - << std::endl; - return true; - } - mRecentlyReceivedMessageHashes[hash] = static_cast(time(nullptr)); - } - - IndicateConfigChanged(); - - RsItem *item = _serialiser->deserialise( const_cast(data), &dataSize ); - RsMsgItem *msg_item = dynamic_cast(item); - - if(msg_item) - { - Dbg3() << __PRETTY_FUNCTION__ << " Encrypted item correctly " - << "deserialised. Passing on to incoming list." - << std::endl; - - msg_item->msgFlags |= RS_MSG_FLAGS_DISTANT; - /* we expect complete msgs - remove partial flag just in case - * someone has funny ideas */ - msg_item->msgFlags &= ~RS_MSG_FLAGS_PARTIAL; - - // hack to pass on GXS id. - msg_item->PeerId(RsPeerId(authorId)); - handleIncomingItem(msg_item); - } - else - { - RsWarn() << __PRETTY_FUNCTION__ << " Item could not be " - << "deserialised. Format error?" << std::endl; - return false; - } - - return true; -} - -bool p3MsgService::notifyGxsTransSendStatus( RsGxsTransId mailId, - GxsTransSendStatus status ) -{ - Dbg2() << __PRETTY_FUNCTION__ << " " << mailId << ", " - << static_cast(status) << std::endl; - - auto pEvent = std::make_shared(); - - if( status == GxsTransSendStatus::RECEIPT_RECEIVED ) - { - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_RECEIVED_ACK; - uint32_t msg_id; - - { - RS_STACK_MUTEX(gxsOngoingMutex); - - auto it = gxsOngoingMessages.find(mailId); - if(it == gxsOngoingMessages.end()) - { - RsErr() << __PRETTY_FUNCTION__<< " " << mailId << ", " - << static_cast(status) - << " cannot find pending message to acknowledge!" - << std::endl; - return false; - } - - msg_id = it->second; - } - - // we should now remove the item from the msgOutgoing list. - - { - RS_STACK_MUTEX(mMsgMtx); - - auto it2 = msgOutgoing.find(msg_id); - if(it2 == msgOutgoing.end()) - { - RsInfo() << __PRETTY_FUNCTION__ << " " << mailId - << ", " << static_cast(status) - << " received receipt for message that is not in " - << "outgoing list, probably it has been acknoweldged " - << "before by other means." << std::endl; - } - else - { -#if 0 - delete it2->second; - msgOutgoing.erase(it2); -#else - // Do not delete it move to sent folder instead! - it2->second->msgFlags &= ~RS_MSG_FLAGS_PENDING; - imsg[msg_id] = it2->second; - msgOutgoing.erase(it2); -#endif - pEvent->mChangedMsgIds.insert(std::to_string(msg_id)); - } - } - - RsServer::notify()->notifyListChange( NOTIFY_LIST_MESSAGELIST, - NOTIFY_TYPE_ADD ); - IndicateConfigChanged(); - } - else if( status >= GxsTransSendStatus::FAILED_RECEIPT_SIGNATURE ) - { - uint32_t msg_id; - pEvent->mMailStatusEventCode = RsMailStatusEventCode::SIGNATURE_FAILED; - - { - RS_STACK_MUTEX(gxsOngoingMutex); - RsErr() << __PRETTY_FUNCTION__ << " mail delivery " - << "mailId: " << mailId - << " failed with " << static_cast(status); - - auto it = gxsOngoingMessages.find(mailId); - if(it == gxsOngoingMessages.end()) - { - RsErr() << __PRETTY_FUNCTION__ - << " cannot find pending message to notify" - << std::endl; - return false; - } - - msg_id = it->second; - } - - std::cerr << " message id = " << msg_id << std::endl; - - { - RS_STACK_MUTEX(mMsgMtx); - auto mit = msgOutgoing.find(msg_id); - if( mit == msgOutgoing.end() ) - { - std::cerr << " message has been notified as not delivered, " - << "but it not on outgoing list." - << std::endl; - } - else - { - std::cerr << " reseting the ROUTED flag so that the message is " - << "requested again" << std::endl; - // clear the routed flag so that the message is requested again - mit->second->msgFlags &= ~RS_MSG_FLAGS_ROUTED; - - pEvent->mChangedMsgIds.insert(std::to_string(msg_id)); - } - } - } - - if(rsEvents && !pEvent->mChangedMsgIds.empty()) - rsEvents->postEvent(pEvent); - - return true; -} - -void p3MsgService::receiveGRouterData( const RsGxsId &destination_key, - const RsGxsId &signing_key, - GRouterServiceId &/*client_id*/, - uint8_t *data, uint32_t data_size ) -{ - std::cerr << "p3MsgService::receiveGRouterData(): received message item of" - << " size " << data_size << ", for key " << destination_key - << std::endl; - - /* first make sure that we havn't already received the data. Since we allow - * to re-send messages, it's necessary to check. */ - - Sha1CheckSum hash = RsDirUtil::sha1sum(data, data_size); - - { - RS_STACK_MUTEX(recentlyReceivedMutex); - if( mRecentlyReceivedMessageHashes.find(hash) != - mRecentlyReceivedMessageHashes.end() ) - { - std::cerr << "p3MsgService::receiveGRouterData(...) (II) receiving" - << "distant message of hash " << hash << " more than once" - << ". Probably it has arrived before by other means." - << std::endl; - free(data); - return; - } - mRecentlyReceivedMessageHashes[hash] = time(NULL); - } - - IndicateConfigChanged() ; - - RsItem *item = _serialiser->deserialise(data,&data_size) ; - free(data) ; - - RsMsgItem *msg_item = dynamic_cast(item) ; - - if(msg_item != NULL) - { - std::cerr << " Encrypted item correctly deserialised. Passing on to incoming list." << std::endl; - - msg_item->msgFlags |= RS_MSG_FLAGS_DISTANT ; - /* we expect complete msgs - remove partial flag just in case someone has funny ideas */ - msg_item->msgFlags &= ~RS_MSG_FLAGS_PARTIAL; - - msg_item->PeerId(RsPeerId(signing_key)) ; // hack to pass on GXS id. - handleIncomingItem(msg_item) ; - } - else - std::cerr << " Item could not be deserialised. Format error??" << std::endl; -} - -void p3MsgService::sendDistantMsgItem(RsMsgItem *msgitem) -{ - RsGxsId destination_key_id(msgitem->PeerId()); - RsGxsId signing_key_id; - - /* just in case, but normally we should always have this flag set, when - * ending up here. */ - msgitem->msgFlags |= RS_MSG_FLAGS_DISTANT; - - { - RS_STACK_MUTEX(mMsgMtx); - - std::map::const_iterator it = - mDistantOutgoingMsgSigners.find(msgitem->msgId); - - if(it == mDistantOutgoingMsgSigners.end()) - { - std::cerr << "(EE) no signer registered for distant message " - << msgitem->msgId << ". Cannot send!" << std::endl; - return; - } - - signing_key_id = it->second; - - if(signing_key_id.isNull()) - { - std::cerr << "ERROR: cannot find signing key id for msg id " - << msgitem->msgId << " available keys are:" << std::endl; - typedef std::map::const_iterator itT; - for( itT it = mDistantOutgoingMsgSigners.begin(); - it != mDistantOutgoingMsgSigners.end(); ++it ) - std::cerr << "\t" << it->first << " " << it->second - << std::endl; - return; - } - } -#ifdef DEBUG_DISTANT_MSG - std::cerr << "p3MsgService::sendDistanteMsgItem(): sending distant msg item" - << " msg ID: " << msgitem->msgId << " to peer:" - << destination_key_id << " signing: " << signing_key_id - << std::endl; -#endif - - /* The item is serialized and turned into a generic turtle item. Use use the - * explicit serialiser to make sure that the msgId is not included */ - - uint32_t msg_serialized_rssize = RsMsgSerialiser().size(msgitem); - RsTemporaryMemory msg_serialized_data(msg_serialized_rssize) ; - - if( !RsMsgSerialiser(). - serialise(msgitem,msg_serialized_data,&msg_serialized_rssize) ) - { - std::cerr << "(EE) p3MsgService::sendTurtleData(): Serialization error." << std::endl; - return ; - } -#ifdef DEBUG_DISTANT_MSG - std::cerr << " serialised size : " << msg_serialized_rssize << std::endl; -#endif - - GRouterMsgPropagationId grouter_message_id; - mGRouter->sendData( destination_key_id, GROUTER_CLIENT_ID_MESSAGES, - msg_serialized_data, msg_serialized_rssize, - signing_key_id, grouter_message_id ); - RsGxsTransId gxsMailId; - mGxsTransServ.sendData( gxsMailId, GxsTransSubServices::P3_MSG_SERVICE, - signing_key_id, destination_key_id, - msg_serialized_data, msg_serialized_rssize ); - - /* now store the grouter id along with the message id, so that we can keep - * track of received messages */ - - { - RS_STACK_MUTEX(mMsgMtx); - _ongoing_messages[grouter_message_id] = msgitem->msgId; - } - - { - RS_STACK_MUTEX(gxsOngoingMutex); - gxsOngoingMessages[gxsMailId] = msgitem->msgId; - } - - IndicateConfigChanged(); // save _ongoing_messages -} - - - - diff --git a/libretroshare/src/services/p3msgservice.h b/libretroshare/src/services/p3msgservice.h deleted file mode 100644 index 30ad1e135..000000000 --- a/libretroshare/src/services/p3msgservice.h +++ /dev/null @@ -1,248 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3msgservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef MESSAGE_SERVICE_HEADER -#define MESSAGE_SERVICE_HEADER - -#include -#include -#include - -#include "retroshare/rsmsgs.h" - -#include "pqi/pqi.h" -#include "pqi/pqiindic.h" - -#include "pqi/pqiservicemonitor.h" -#include "pqi/p3cfgmgr.h" - -#include "services/p3service.h" -#include "rsitems/rsmsgitems.h" -#include "util/rsthreads.h" -#include "util/rsdebug.h" -#include "retroshare/rsgxsifacetypes.h" - -#include "grouter/p3grouter.h" -#include "grouter/grouterclientservice.h" -#include "turtle/p3turtle.h" -#include "turtle/turtleclientservice.h" -#include "gxstrans/p3gxstrans.h" - -class p3LinkMgr; -class p3IdService; - -// Temp tweak to test grouter -class p3MsgService : - public p3Service, public p3Config, public pqiServiceMonitor, GRouterClientService, - GxsTransClient -{ -public: - p3MsgService(p3ServiceControl *sc, p3IdService *id_service, p3GxsTrans& gxsMS); - virtual ~p3MsgService(); - - virtual RsServiceInfo getServiceInfo(); - - /// @see RsMsgs::sendMail - uint32_t sendMail(const RsGxsId from, - const std::string& subject, - const std::string& body, - const std::set& to = std::set(), - const std::set& cc = std::set(), - const std::set& bcc = std::set(), - const std::vector& attachments = std::vector(), - std::set& trackingIds = - RS_DEFAULT_STORAGE_PARAM(std::set), - std::string& errorMsg = - RS_DEFAULT_STORAGE_PARAM(std::string) ); - - /* External Interface */ - bool getMessageSummaries(std::list &msgList); - bool getMessage(const std::string &mid, Rs::Msgs::MessageInfo &msg); - void getMessageCount(uint32_t &nInbox, uint32_t &nInboxNew, uint32_t &nOutbox, uint32_t &nDraftbox, uint32_t &nSentbox, uint32_t &nTrashbox); - - bool decryptMessage(const std::string& mid) ; - bool removeMsgId(const std::string &mid); - bool markMsgIdRead(const std::string &mid, bool bUnreadByUser); - bool setMsgFlag(const std::string &mid, uint32_t flag, uint32_t mask); - bool getMsgParentId(const std::string &msgId, std::string &msgParentId); - // msgParentId == 0 --> remove - bool setMsgParentId(uint32_t msgId, uint32_t msgParentId); - - RS_DEPRECATED_FOR(sendMail) - bool MessageSend(Rs::Msgs::MessageInfo &info); - bool SystemMessage(const std::string &title, const std::string &message, uint32_t systemFlag); - bool MessageToDraft(Rs::Msgs::MessageInfo &info, const std::string &msgParentId); - bool MessageToTrash(const std::string &mid, bool bTrash); - - bool getMessageTag(const std::string &msgId, Rs::Msgs::MsgTagInfo& info); - bool getMessageTagTypes(Rs::Msgs::MsgTagType& tags); - bool setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color); - bool removeMessageTagType(uint32_t tagId); - - /* set == false && tagId == 0 --> remove all */ - bool setMessageTag(const std::string &msgId, uint32_t tagId, bool set); - - bool resetMessageStandardTagTypes(Rs::Msgs::MsgTagType& tags); - - void loadWelcomeMsg(); /* startup message */ - - - //std::list &getMsgList(); - //std::list &getMsgOutList(); - - int tick(); - - /*** Overloaded from p3Config ****/ - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool& cleanup, std::list&); - virtual bool loadList(std::list& load); - virtual void saveDone(); - /*** Overloaded from p3Config ****/ - - /*** Overloaded from pqiMonitor ***/ - virtual void statusChange(const std::list &plist); - - /// iterate through the outgoing queue if online, send - int checkOutgoingMessages(); - /*** Overloaded from pqiMonitor ***/ - - /*** overloaded from p3turtle ***/ - - virtual void connectToGlobalRouter(p3GRouter *) ; - - struct DistantMessengingInvite - { - rstime_t time_of_validity ; - }; - struct DistantMessengingContact - { - rstime_t last_hit_time ; - RsPeerId virtual_peer_id ; - uint32_t status ; - bool pending_messages ; - }; - void enableDistantMessaging(bool b) ; - bool distantMessagingEnabled() ; - - void setDistantMessagingPermissionFlags(uint32_t flags) ; - uint32_t getDistantMessagingPermissionFlags() ; - - /// @see GxsTransClient::receiveGxsTransMail(...) - virtual bool receiveGxsTransMail( const RsGxsId& authorId, - const RsGxsId& recipientId, - const uint8_t* data, uint32_t dataSize ); - - /// @see GxsTransClient::notifyGxsTransSendStatus(...) - virtual bool notifyGxsTransSendStatus( RsGxsTransId mailId, - GxsTransSendStatus status ); - -private: - void sendDistantMsgItem(RsMsgItem *msgitem); - bool locked_getMessageTag(const std::string &msgId, Rs::Msgs::MsgTagInfo& info); - - /** This contains the ongoing tunnel handling contacts. - * The map is indexed by the hash */ - std::map _ongoing_messages; - - /// Contains ongoing messages handed to gxs mail - std::map gxsOngoingMessages; - RsMutex gxsOngoingMutex; - - // Overloaded from GRouterClientService - virtual bool acceptDataFromPeer(const RsGxsId& gxs_id) ; - virtual void receiveGRouterData(const RsGxsId& destination_key,const RsGxsId& signing_key, GRouterServiceId &client_id, uint8_t *data, uint32_t data_size) ; - virtual void notifyDataStatus(const GRouterMsgPropagationId& msg_id,const RsGxsId& signer_id,uint32_t data_status) ; - - // Utility functions - - bool createDistantMessage(const RsGxsId& destination_gxs_id,const RsGxsId& source_gxs_id,RsMsgItem *msg) ; - bool locked_findHashForVirtualPeerId(const RsPeerId& pid,Sha1CheckSum& hash) ; - void sendGRouterData(const RsGxsId &key_id,RsMsgItem *) ; - - void manageDistantPeers() ; - - void handleIncomingItem(RsMsgItem *) ; - - uint32_t getNewUniqueMsgId(); - uint32_t sendMessage(RsMsgItem *item); - uint32_t sendDistantMessage(RsMsgItem *item,const RsGxsId& signing_gxs_id); - void checkSizeAndSendMessage(RsMsgItem *msg); - void cleanListOfReceivedMessageHashes(); - - int incomingMsgs(); - void processIncomingMsg(RsMsgItem *mi) ; - bool checkAndRebuildPartialMessage(RsMsgItem*) ; - - void initRsMI(RsMsgItem *msg, Rs::Msgs::MessageInfo &mi); - void initRsMIS(RsMsgItem *msg, Rs::Msgs::MsgInfoSummary &mis); - - RsMsgItem *initMIRsMsg(const Rs::Msgs::MessageInfo &info, const RsPeerId& to); - RsMsgItem *initMIRsMsg(const Rs::Msgs::MessageInfo &info, const RsGxsId& to); - void initMIRsMsg(RsMsgItem *item,const Rs::Msgs::MessageInfo &info) ; - - void initStandardTagTypes(); - - p3IdService *mIdService ; - p3ServiceControl *mServiceCtrl; - p3GRouter *mGRouter ; - - /* Mutex Required for stuff below */ - - RsMutex mMsgMtx; - RsMsgSerialiser *_serialiser ; - - /* stored list of messages */ - std::map imsg; - /* ones that haven't made it out yet! */ - std::map msgOutgoing; - - std::map _pendingPartialMessages ; - - /* maps for tags types and msg tags */ - - std::map mTags; - std::map mMsgTags; - - uint32_t mMsgUniqueId; - std::map mRecentlyReceivedMessageHashes; - RsMutex recentlyReceivedMutex; - - // used delete msgSrcIds after config save - std::map mSrcIds; - - // temporary storage. Will not be needed when messages have a proper "from" field. Not saved! - std::map mDistantOutgoingMsgSigners; - - // save the parent of the messages in draft for replied and forwarded - std::map mParentId; - - std::string config_dir; - - bool mDistantMessagingEnabled ; - uint32_t mDistantMessagePermissions ; - bool mShouldEnableDistantMessaging ; - - p3GxsTrans& mGxsTransServ; - - RS_SET_CONTEXT_DEBUG_LEVEL(3) -}; - -#endif // MESSAGE_SERVICE_HEADER diff --git a/libretroshare/src/services/p3photoservice.cc b/libretroshare/src/services/p3photoservice.cc deleted file mode 100644 index 24e9d90b6..000000000 --- a/libretroshare/src/services/p3photoservice.cc +++ /dev/null @@ -1,351 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3photoservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2012 Robert Fernie,Chris Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#include "p3photoservice.h" -#include "rsitems/rsphotoitems.h" -#include "retroshare/rsgxsflags.h" - -RsPhoto *rsPhoto = NULL; - -RsPhotoPhoto::RsPhotoPhoto() - :mOrder(0) -{ - return; -} - -RsPhotoAlbum::RsPhotoAlbum() - :mShareMode(RSPHOTO_SHAREMODE_LOWRESONLY), mAutoDownload(false) -{ - return; -} - -std::ostream &operator<<(std::ostream &out, const RsPhotoPhoto &photo) -{ - out << "RsPhotoPhoto [ "; - out << "Title: " << photo.mMeta.mMsgName; - out << "]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsPhotoAlbum &album) -{ - out << "RsPhotoAlbum [ "; - out << "Title: " << album.mMeta.mGroupName; - out << "]"; - return out; -} - -p3PhotoService::p3PhotoService(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs) - : RsGenExchange(gds, nes, new RsGxsPhotoSerialiser(), RS_SERVICE_GXS_TYPE_PHOTO, gixs, photoAuthenPolicy()), - RsPhoto(static_cast(*this)), - mPhotoMutex(std::string("Photo Mutex")) -{ - mCommentService = new p3GxsCommentService(this, RS_SERVICE_GXS_TYPE_PHOTO); -} - -const std::string GXS_PHOTO_APP_NAME = "gxsphoto"; -const uint16_t GXS_PHOTO_APP_MAJOR_VERSION = 1; -const uint16_t GXS_PHOTO_APP_MINOR_VERSION = 0; -const uint16_t GXS_PHOTO_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_PHOTO_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3PhotoService::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_PHOTO, - GXS_PHOTO_APP_NAME, - GXS_PHOTO_APP_MAJOR_VERSION, - GXS_PHOTO_APP_MINOR_VERSION, - GXS_PHOTO_MIN_MAJOR_VERSION, - GXS_PHOTO_MIN_MINOR_VERSION); -} - -uint32_t p3PhotoService::photoAuthenPolicy() -{ - uint32_t policy = 0; - uint8_t flag = 0; - - flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - flag |= GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = GXS_SERV::GRP_OPTION_AUTHEN_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -bool p3PhotoService::updated() -{ - RsStackMutex stack(mPhotoMutex); - - bool changed = (!mGroupChange.empty() || !mMsgChange.empty()); - - return changed; -} - -void p3PhotoService::service_tick() -{ - mCommentService->comment_tick(); -} - - -void p3PhotoService::groupsChanged(std::list& grpIds) -{ - RsStackMutex stack(mPhotoMutex); - - while(!mGroupChange.empty()) - { - RsGxsGroupChange* gc = mGroupChange.back(); - grpIds.push_back(gc->mGroupId); - - mGroupChange.pop_back(); - delete gc; - } -} - - -void p3PhotoService::msgsChanged(GxsMsgIdResult& msgs) -{ - RsStackMutex stack(mPhotoMutex); - - while(!mMsgChange.empty()) - { - RsGxsMsgChange* mc = mMsgChange.back(); - - msgs[mc->mGroupId].insert(mc->mMsgId); - mMsgChange.pop_back(); - delete mc; - } -} - - -RsTokenService* p3PhotoService::getTokenService() { - - return RsGenExchange::getTokenService(); -} - - -bool p3PhotoService::getGroupList(const uint32_t& token, - std::list& groupIds) -{ - bool okay = RsGenExchange::getGroupList(token, groupIds); - return okay; -} - - -bool p3PhotoService::getMsgList(const uint32_t& token, - GxsMsgIdResult& msgIds) -{ - - return RsGenExchange::getMsgList(token, msgIds); -} - - -bool p3PhotoService::getGroupSummary(const uint32_t& token, - std::list& groupInfo) -{ - bool okay = RsGenExchange::getGroupMeta(token, groupInfo); - return okay; -} - - -bool p3PhotoService::getMsgSummary(const uint32_t& token, - MsgMetaResult& msgInfo) -{ - return RsGenExchange::getMsgMeta(token, msgInfo); -} - - -bool p3PhotoService::getAlbum(const uint32_t& token, std::vector& albums) -{ - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsPhotoAlbumItem* item = dynamic_cast(*vit); - if (item) - { - RsPhotoAlbum album = item->album; - item->album.mMeta = item->meta; - album.mMeta = item->album.mMeta; - delete item; - albums.push_back(album); - } - else - { - std::cerr << "Not a RsGxsPhotoAlbumItem, deleting!" << std::endl; - delete *vit; - } - } - } - - return ok; -} - -bool p3PhotoService::getPhoto(const uint32_t& token, PhotoResult& photos) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - RsGxsGroupId grpId = mit->first; - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsPhotoPhotoItem* item = dynamic_cast(*vit); - - if(item) - { - RsPhotoPhoto photo = item->photo; - photo.mMeta = item->meta; - photos[grpId].push_back(photo); - delete item; - }else - { - std::cerr << "Not a photo Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -} - -bool p3PhotoService::submitAlbumDetails(uint32_t& token, RsPhotoAlbum& album) -{ - RsGxsPhotoAlbumItem* albumItem = new RsGxsPhotoAlbumItem(); - albumItem->album = album; - albumItem->meta = album.mMeta; - RsGenExchange::publishGroup(token, albumItem); - return true; -} - -void p3PhotoService::notifyChanges(std::vector& changes) -{ - - RsStackMutex stack(mPhotoMutex); - - std::vector::iterator vit = changes.begin(); - - for(; vit != changes.end(); ++vit) - { - RsGxsNotify* n = *vit; - RsGxsGroupChange* gc; - RsGxsMsgChange* mc; - if((mc = dynamic_cast(n)) != NULL) - { - mMsgChange.push_back(mc); - } - else if((gc = dynamic_cast(n)) != NULL) - { - mGroupChange.push_back(gc); - } - else - { - delete n; - } - } -} - -bool p3PhotoService::submitPhoto(uint32_t& token, RsPhotoPhoto& photo) -{ - RsGxsPhotoPhotoItem* photoItem = new RsGxsPhotoPhotoItem(); - photoItem->photo = photo; - photoItem->meta = photo.mMeta; - - RsGenExchange::publishMsg(token, photoItem); - return true; -} - -bool p3PhotoService::acknowledgeMsg(const uint32_t& token, - std::pair& msgId) -{ - return RsGenExchange::acknowledgeTokenMsg(token, msgId); -} - - -bool p3PhotoService::acknowledgeGrp(const uint32_t& token, - RsGxsGroupId& grpId) -{ - return RsGenExchange::acknowledgeTokenGrp(token, grpId); -} - -bool p3PhotoService::subscribeToAlbum(uint32_t &token, const RsGxsGroupId &grpId, bool subscribe) -{ - if(subscribe) - RsGenExchange::setGroupSubscribeFlags(token, grpId, GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED, GXS_SERV::GROUP_SUBSCRIBE_MASK); - else - RsGenExchange::setGroupSubscribeFlags(token, grpId, 0, GXS_SERV::GROUP_SUBSCRIBE_MASK); - - return true; -} - -// Blocking versions ============================================================= - -bool p3PhotoService::createAlbum(RsPhotoAlbum &album) -{ - uint32_t token; - return submitAlbumDetails(token, album) && waitToken(token) == RsTokenService::COMPLETE; -} - -bool p3PhotoService::updateAlbum(const RsPhotoAlbum &/*album*/) -{ - // TODO - return false; -} - -bool p3PhotoService::getAlbums(const std::list &groupIds, - std::vector &albums) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if (groupIds.empty()) - { - if (!requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - else - { - if (!requestGroupInfo(token, opts, groupIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - - return getAlbum(token, albums) && !albums.empty(); -} - diff --git a/libretroshare/src/services/p3photoservice.h b/libretroshare/src/services/p3photoservice.h deleted file mode 100644 index f540d4f66..000000000 --- a/libretroshare/src/services/p3photoservice.h +++ /dev/null @@ -1,214 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3photoservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2012 Robert Fernie,Chris Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef P3PHOTOSERVICEV2_H -#define P3PHOTOSERVICEV2_H - -#include "gxs/rsgenexchange.h" -#include "retroshare/rsphoto.h" -#include "services/p3gxscommon.h" - -class p3PhotoService : public RsGenExchange, public RsPhoto -{ -public: - - p3PhotoService(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs); - virtual RsServiceInfo getServiceInfo() override; - - static uint32_t photoAuthenPolicy(); - -public: - - /*! - * @return true if a change has occured - */ - bool updated() override; - - /*! - * - */ - void service_tick() override; - -protected: - - void notifyChanges(std::vector& changes) override; -public: - - /** Requests **/ - - void groupsChanged(std::list& grpIds) override; - - - void msgsChanged(GxsMsgIdResult& msgs) override; - - RsTokenService* getTokenService() override; - - bool getGroupList(const uint32_t &token, std::list &groupIds) override; - bool getMsgList(const uint32_t &token, GxsMsgIdResult& msgIds) override; - - /* Generic Summary */ - bool getGroupSummary(const uint32_t &token, std::list &groupInfo) override; - - bool getMsgSummary(const uint32_t &token, MsgMetaResult &msgInfo) override; - - /* Specific Service Data */ - bool getAlbum(const uint32_t &token, std::vector &albums) override; - bool getPhoto(const uint32_t &token, PhotoResult &photos) override; - -public: - /* Comment service - Provide RsGxsCommentService - redirect to p3GxsCommentService */ - virtual bool getCommentData(uint32_t token, std::vector &msgs) override - { - return mCommentService->getGxsCommentData(token, msgs); - } - - virtual bool getRelatedComments( uint32_t token, std::vector &msgs ) override - { - return mCommentService->getGxsRelatedComments(token, msgs); - } - - virtual bool createNewComment(uint32_t &token, const RsGxsComment &msg) override - { - return mCommentService->createGxsComment(token, msg); - } - - virtual bool createNewVote(uint32_t &token, RsGxsVote &msg) override - { - return mCommentService->createGxsVote(token, msg); - } - - virtual bool acknowledgeComment(uint32_t token, std::pair& msgId) override - { - return acknowledgeMsg(token, msgId); - } - - virtual bool acknowledgeVote(uint32_t token, std::pair& msgId) override - { - if (mCommentService->acknowledgeVote(token, msgId)) - { - return true; - } - return acknowledgeMsg(token, msgId); - } - - //Not currently used - virtual bool setCommentAsRead(uint32_t& /*token*/,const RsGxsGroupId& /*gid*/,const RsGxsMessageId& /*comment_msg_id*/) override - { - return true; - } - - - // Blocking versions. - virtual bool createComment(RsGxsComment &msg) override - { - uint32_t token; - return mCommentService->createGxsComment(token, msg) && waitToken(token) == RsTokenService::COMPLETE; - } - -public: - - /** Modifications **/ - - /*! - * submits album, which returns a token that needs - * to be acknowledge to get album grp id - * @param token token to redeem for acknowledgement - * @param album album to be submitted - */ - bool submitAlbumDetails(uint32_t& token, RsPhotoAlbum &album) override; - - /*! - * submits photo, which returns a token that needs - * to be acknowledge to get photo msg-grp id pair - * @param token token to redeem for acknowledgement - * @param photo photo to be submitted - */ - bool submitPhoto(uint32_t& token, RsPhotoPhoto &photo) override; - - /*! - * submits photo comment, which returns a token that needs - * to be acknowledged to get photo msg-grp id pair - * The mParentId needs to be set to an existing msg for which - * commenting is enabled - * @param token token to redeem for acknowledgement - * @param comment comment to be submitted - */ - // bool submitComment(uint32_t& token, RsPhotoComment &photo); - - /*! - * subscribes to group, and returns token which can be used - * to be acknowledged to get group Id - * @param token token to redeem for acknowledgement - * @param grpId the id of the group to subscribe to - */ - bool subscribeToAlbum(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) override; - - /*! - * This allows the client service to acknowledge that their msgs has - * been created/modified and retrieve the create/modified msg ids - * @param token the token related to modification/create request - * @param msgIds map of grpid->msgIds of message created/modified - * @return true if token exists false otherwise - */ - bool acknowledgeMsg(const uint32_t& token, std::pair& msgId) override; - - /*! - * This allows the client service to acknowledge that their grps has - * been created/modified and retrieve the create/modified grp ids - * @param token the token related to modification/create request - * @param msgIds vector of ids of groups created/modified - * @return true if token exists false otherwise - */ - bool acknowledgeGrp(const uint32_t& token, RsGxsGroupId& grpId) override; - - // Blocking versions. - /*! - * request to create a new album. Blocks until process completes. - * @param album album to be submitted - * @return true if created false otherwise - */ - virtual bool createAlbum(RsPhotoAlbum &album) override; - - /*! - * request to update an existing album. Blocks until process completes. - * @param album album to be submitted - * @return true if created false otherwise - */ - virtual bool updateAlbum(const RsPhotoAlbum &album) override; - - /*! - * retrieve albums based in groupIds. - * @param groupIds the ids to fetch. - * @param albums vector to be filled by request. - * @return true is successful, false otherwise. - */ - virtual bool getAlbums(const std::list &groupIds, - std::vector &albums) override; -private: - p3GxsCommentService* mCommentService; - - std::vector mGroupChange; - std::vector mMsgChange; - - RsMutex mPhotoMutex; -}; - -#endif // P3PHOTOSERVICEV2_H diff --git a/libretroshare/src/services/p3postbase.cc b/libretroshare/src/services/p3postbase.cc deleted file mode 100644 index 6792255a4..000000000 --- a/libretroshare/src/services/p3postbase.cc +++ /dev/null @@ -1,1028 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3postbase.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2012 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include - -#include "retroshare/rsgxsflags.h" -#include -#include - -#include "services/p3postbase.h" -#include "rsitems/rsgxscommentitems.h" - -#include "rsserver/p3face.h" -#include "retroshare/rsposted.h" - -// For Dummy Msgs. -#include "util/rsrandom.h" -#include "util/rsstring.h" - -/**** - * #define POSTBASE_DEBUG 1 - ****/ - -#define POSTBASE_BACKGROUND_PROCESSING 0x0002 -#define PROCESSING_START_PERIOD 30 -#define PROCESSING_INC_PERIOD 15 - -#define POSTBASE_ALL_GROUPS 0x0011 -#define POSTBASE_UNPROCESSED_MSGS 0x0012 -#define POSTBASE_ALL_MSGS 0x0013 -#define POSTBASE_BG_POST_META 0x0014 - -#define POSTED_UNUSED_BY_FRIENDS_DELAY (2*30*86400) // delete unused posted groups after 2 months - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3PostBase::p3PostBase(RsGeneralDataService *gds, RsNetworkExchangeService *nes, RsGixs* gixs, - RsSerialType* serviceSerialiser, uint16_t serviceType) - : RsGenExchange(gds, nes, serviceSerialiser, serviceType, gixs, postBaseAuthenPolicy()), GxsTokenQueue(this), RsTickEvent(), - mPostBaseMtx("PostBaseMutex"), - mKnownPostedMutex("PostBaseKnownPostedMutex") -{ - mBgProcessing = false; - - mCommentService = new p3GxsCommentService(this, serviceType); - RsTickEvent::schedule_in(POSTBASE_BACKGROUND_PROCESSING, PROCESSING_START_PERIOD); -} - - -uint32_t p3PostBase::postBaseAuthenPolicy() -{ - uint32_t policy = 0; - uint32_t flag = 0; - - flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - flag |= GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -void p3PostBase::notifyChanges(std::vector &changes) -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::notifyChanges()"; - std::cerr << std::endl; -#endif - - for(auto it = changes.begin(); it != changes.end(); ++it) - { - RsGxsMsgChange *msgChange = dynamic_cast(*it); - - if(msgChange) - { - // To start with we are just going to trigger updates on these groups. - // FUTURE OPTIMISATION. - // It could be taken a step further and directly request these msgs for an update. - addGroupForProcessing(msgChange->mGroupId); - - if (rsEvents) - { - switch(msgChange->getType()) - { - case RsGxsNotify::TYPE_RECEIVED_NEW: - case RsGxsNotify::TYPE_PUBLISHED: - { - auto ev = std::make_shared(); - ev->mPostedMsgId = msgChange->mMsgId; - ev->mPostedThreadId = msgChange->mNewMsgItem->meta.mThreadId; - ev->mPostedGroupId = msgChange->mGroupId; - - if(nullptr != dynamic_cast(msgChange->mNewMsgItem)) - ev->mPostedEventCode = RsPostedEventCode::NEW_COMMENT; - else - if(nullptr != dynamic_cast(msgChange->mNewMsgItem)) - ev->mPostedEventCode = RsPostedEventCode::NEW_VOTE; - else - ev->mPostedEventCode = RsPostedEventCode::NEW_MESSAGE; - - rsEvents->postEvent(ev); -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::notifyChanges() Found Message Change Notification: NEW/PUBLISHED ID=" << msgChange->mMsgId << " in group " << msgChange->mGroupId << ", thread ID = " << msgChange->mNewMsgItem->meta.mThreadId << std::endl; -#endif - - } - break; - - - case RsGxsNotify::TYPE_PROCESSED: - { - auto ev = std::make_shared(); - ev->mPostedMsgId = msgChange->mMsgId; - ev->mPostedGroupId = msgChange->mGroupId; - ev->mPostedEventCode = RsPostedEventCode::MESSAGE_VOTES_UPDATED; - rsEvents->postEvent(ev); -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::notifyChanges() Found Message Change Notification: PROCESSED ID=" << msgChange->mMsgId << " in group " << msgChange->mGroupId << std::endl; -#endif - } - break; - default: -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::notifyChanges() Found Message Change Notification: type " << msgChange->getType() << " (ignored) " << msgChange->mMsgId << std::endl; -#endif - break; - } - } - } - - RsGxsGroupChange *grpChange = dynamic_cast(*it); - - /* pass on Group Changes to GUI */ - if (grpChange && rsEvents) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::notifyChanges() Found Group Change Notification"; - std::cerr << std::endl; -#endif - const RsGxsGroupId& group_id(grpChange->mGroupId); - - switch(grpChange->getType()) - { - case RsGxsNotify::TYPE_PROCESSED: // happens when the group is subscribed - { - auto ev = std::make_shared(); - ev->mPostedGroupId = group_id; - ev->mPostedEventCode = RsPostedEventCode::SUBSCRIBE_STATUS_CHANGED; - rsEvents->postEvent(ev); - } - break; - - case RsGxsNotify::TYPE_GROUP_SYNC_PARAMETERS_UPDATED: - { - auto ev = std::make_shared(); - ev->mPostedGroupId = group_id; - ev->mPostedEventCode = RsPostedEventCode::SYNC_PARAMETERS_UPDATED; - rsEvents->postEvent(ev); - } - break; - - case RsGxsNotify::TYPE_GROUP_DELETED: - { - auto ev = std::make_shared(); - ev->mPostedGroupId = group_id; - ev->mPostedEventCode = RsPostedEventCode::BOARD_DELETED; - - rsEvents->postEvent(ev); - } - break; - - case RsGxsNotify::TYPE_STATISTICS_CHANGED: - { - auto ev = std::make_shared(); - ev->mPostedGroupId = group_id; - ev->mPostedEventCode = RsPostedEventCode::STATISTICS_CHANGED; - rsEvents->postEvent(ev); - - RS_STACK_MUTEX(mKnownPostedMutex); - mKnownPosted[group_id] = time(nullptr); - IndicateConfigChanged(); - } - break; - - case RsGxsNotify::TYPE_UPDATED: - { - // Happens when the group data has changed. In this case we need to analyse the old and new group in order to detect possible notifications for clients - - auto ev = std::make_shared(); - ev->mPostedGroupId = grpChange->mGroupId; - ev->mPostedEventCode = RsPostedEventCode::UPDATED_POSTED_GROUP; - rsEvents->postEvent(ev); - } - break; - - - case RsGxsNotify::TYPE_PUBLISHED: - case RsGxsNotify::TYPE_RECEIVED_NEW: - { - /* group received */ - - bool unknown; - { - RS_STACK_MUTEX(mKnownPostedMutex); - - unknown = (mKnownPosted.find(grpChange->mGroupId) == mKnownPosted.end()); - mKnownPosted[group_id] = time(nullptr); - IndicateConfigChanged(); - } - if(unknown) - { - auto ev = std::make_shared(); - ev->mPostedGroupId = group_id; - ev->mPostedEventCode = RsPostedEventCode::NEW_POSTED_GROUP; - rsEvents->postEvent(ev); - -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::notifyChanges() Incoming Group: " << group_id; - std::cerr << std::endl; -#endif - } - else - RsInfo() << __PRETTY_FUNCTION__ - << " Not notifying already known forum " - << group_id << std::endl; - } - break; - - default: - RsErr() << " Got a GXS event of type " << grpChange->getType() << " Currently not handled." << std::endl; - break; - } - } - - delete *it; - } -} - -void p3PostBase::service_tick() -{ - RsTickEvent::tick_events(); - GxsTokenQueue::checkRequests(); - - mCommentService->comment_tick(); - - return; -} - -/********************************************************************************************/ -/********************************************************************************************/ - -void p3PostBase::setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - uint32_t status = GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - if (read) - { - status = 0; - } - - setMsgStatusFlags(token, msgId, status, mask); - - if (rsEvents) - { - auto ev = std::make_shared(); - - ev->mPostedMsgId = msgId.second; - ev->mPostedGroupId = msgId.first; - ev->mPostedEventCode = RsPostedEventCode::READ_STATUS_CHANGED; - rsEvents->postEvent(ev); - } -} - - - // Overloaded from RsTickEvent for Event callbacks. -void p3PostBase::handle_event(uint32_t event_type, const std::string & /* elabel */) -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::handle_event(" << event_type << ")"; - std::cerr << std::endl; -#endif - - // stuff. - switch(event_type) - { - case POSTBASE_BACKGROUND_PROCESSING: - background_tick(); - break; - - default: - /* error */ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::handle_event() Unknown Event Type: " << event_type; - std::cerr << std::endl; -#endif - break; - } -} - - -/********************************************************************************* - * Background Calculations. - * - * Get list of change groups from Notify.... - * this doesn't imclude your own submissions (at this point). - * So they will not be processed until someone else changes something. - * TODO FIX: Must push for that change. - * - * Eventually, we should just be able to get the new messages from Notify, - * and only process them! - */ - -void p3PostBase::background_tick() -{ - -#if 0 - { - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - if (mBgGroupList.empty()) - { - background_requestAllGroups(); - } - } -#endif - - background_requestUnprocessedGroup(); - - RsTickEvent::schedule_in(POSTBASE_BACKGROUND_PROCESSING, PROCESSING_INC_PERIOD); - -} - -bool p3PostBase::background_requestAllGroups() -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_requestAllGroups()"; - std::cerr << std::endl; -#endif - - uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; - - uint32_t token = 0; - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, POSTBASE_ALL_GROUPS); - - return true; -} - - -void p3PostBase::background_loadGroups(const uint32_t &token) -{ - /* get messages */ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_loadGroups()"; - std::cerr << std::endl; -#endif - - std::list groupList; - bool ok = RsGenExchange::getGroupList(token, groupList); - - if (!ok) - { - return; - } - - std::list::iterator it; - for(it = groupList.begin(); it != groupList.end(); ++it) - { - addGroupForProcessing(*it); - } -} - - -void p3PostBase::addGroupForProcessing(RsGxsGroupId grpId) -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::addGroupForProcessing(" << grpId << ")"; - std::cerr << std::endl; -#endif // POSTBASE_DEBUG - - { - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - // no point having multiple lookups queued. - mBgGroupList.insert(grpId); - } -} - - -void p3PostBase::background_requestUnprocessedGroup() -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_requestUnprocessedGroup()"; - std::cerr << std::endl; -#endif // POSTBASE_DEBUG - - - RsGxsGroupId grpId; - { - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - if (mBgProcessing) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_requestUnprocessedGroup() Already Active"; - std::cerr << std::endl; -#endif - return; - } - if (mBgGroupList.empty()) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_requestUnprocessedGroup() No Groups to Process"; - std::cerr << std::endl; -#endif - return; - } - - grpId = *mBgGroupList.begin(); - mBgGroupList.erase(grpId); - mBgProcessing = true; - } - - background_requestGroupMsgs(grpId, true); -} - - - - - -void p3PostBase::background_requestGroupMsgs(const RsGxsGroupId &grpId, bool unprocessedOnly) -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_requestGroupMsgs() id: " << grpId; - std::cerr << std::endl; -#endif - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - if (unprocessedOnly) - { - opts.mStatusFilter = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - opts.mStatusMask = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - } - - std::list grouplist; - grouplist.push_back(grpId); - - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestMsgInfo(token, ansType, opts, grouplist); - - if (unprocessedOnly) - { - GxsTokenQueue::queueRequest(token, POSTBASE_UNPROCESSED_MSGS); - } - else - { - GxsTokenQueue::queueRequest(token, POSTBASE_ALL_MSGS); - } -} - - - - -void p3PostBase::background_loadUnprocessedMsgs(const uint32_t &token) -{ - background_loadMsgs(token, true); -} - - -void p3PostBase::background_loadAllMsgs(const uint32_t &token) -{ - background_loadMsgs(token, false); -} - - -/* This function is generalised to support any collection of messages, across multiple groups */ - -void p3PostBase::background_loadMsgs(const uint32_t &token, bool unprocessed) -{ - /* get messages */ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_loadMsgs()"; - std::cerr << std::endl; -#endif - - std::map > msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if (!ok) - { - std::cerr << "p3PostBase::background_loadMsgs() Failed to getMsgData()"; - std::cerr << std::endl; - - /* cleanup */ - background_cleanup(); - return; - - } - - { - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - mBgStatsMap.clear(); - mBgIncremental = unprocessed; - } - - std::map > postMap; - - // generate vector of changes to push to the GUI. - std::vector changes; - - RsGxsGroupId groupId; - std::map >::iterator mit; - std::vector::iterator vit; - for (mit = msgData.begin(); mit != msgData.end(); ++mit) - { - groupId = mit->first; - for (vit = mit->second.begin(); vit != mit->second.end(); ++vit) - { - RsGxsMessageId parentId = (*vit)->meta.mParentId; - RsGxsMessageId threadId = (*vit)->meta.mThreadId; - - - bool inc_counters = false; - uint32_t vote_up_inc = 0; - uint32_t vote_down_inc = 0; - uint32_t comment_inc = 0; - - bool add_voter = false; - RsGxsId voterId; - RsGxsCommentItem *commentItem; - RsGxsVoteItem *voteItem; - - /* THIS Should be handled by UNPROCESSED Filter - but isn't */ - if (!IS_MSG_UNPROCESSED((*vit)->meta.mMsgStatus)) - { - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - if (mBgIncremental) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_loadMsgs() Msg already Processed - Skipping"; - std::cerr << std::endl; - std::cerr << "p3PostBase::background_loadMsgs() ERROR This should not happen"; - std::cerr << std::endl; -#endif - delete(*vit); - continue; - } - } - - /* 3 types expected: PostedPost, Comment and Vote */ - if (parentId.isNull()) - { -#ifdef POSTBASE_DEBUG - /* we don't care about top-level (Posts) */ - std::cerr << "\tIgnoring TopLevel Item"; - std::cerr << std::endl; -#endif - - /* but we need to notify GUI about them */ - changes.push_back(new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED, mit->first,(*vit)->meta.mMsgId, false)); - } - else if (NULL != (commentItem = dynamic_cast(*vit))) - { -#ifdef POSTBASE_DEBUG - /* comment - want all */ - /* Comments are counted by Thread Id */ - std::cerr << "\tProcessing Comment: " << commentItem; - std::cerr << std::endl; -#endif - - inc_counters = true; - comment_inc = 1; - } - else if (NULL != (voteItem = dynamic_cast(*vit))) - { - /* vote - only care about direct children */ - if (parentId == threadId) - { - /* Votes are organised by Parent Id, - * ie. you can vote for both Posts and Comments - */ -#ifdef POSTBASE_DEBUG - std::cerr << "\tProcessing Vote: " << voteItem; - std::cerr << std::endl; -#endif - - inc_counters = true; - add_voter = true; - voterId = voteItem->meta.mAuthorId; - - if (voteItem->mMsg.mVoteType == GXS_VOTE_UP) - { - vote_up_inc = 1; - } - else - { - vote_down_inc = 1; - } - } - } - else - { - /* unknown! */ - std::cerr << "p3PostBase::background_processNewMessages() ERROR Strange NEW Message:" << std::endl; - std::cerr << "\t" << (*vit)->meta; - std::cerr << std::endl; - - } - - if (inc_counters) - { - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator sit = mBgStatsMap.find(threadId); - if (sit == mBgStatsMap.end()) - { - // add to map of ones to update. - postMap[groupId].insert(threadId); - - mBgStatsMap[threadId] = PostStats(0,0,0); - sit = mBgStatsMap.find(threadId); - } - - sit->second.comments += comment_inc; - sit->second.up_votes += vote_up_inc; - sit->second.down_votes += vote_down_inc; - - - if (add_voter) - { - sit->second.voters.push_back(voterId); - } - -#ifdef POSTBASE_DEBUG - std::cerr << "\tThreadId: " << threadId; - std::cerr << " Comment Total: " << sit->second.comments; - std::cerr << " UpVote Total: " << sit->second.up_votes; - std::cerr << " DownVote Total: " << sit->second.down_votes; - std::cerr << std::endl; -#endif - } - - /* flag all messages as processed and new for the gui */ - if ((*vit)->meta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_UNPROCESSED) - { - uint32_t token_a; - RsGxsGrpMsgIdPair msgId = std::make_pair(groupId, (*vit)->meta.mMsgId); - RsGenExchange::setMsgStatusFlags(token_a, msgId, GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD, GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD); - } - delete(*vit); - } - } - - /* push updates of new Posts */ - notifyChanges(changes); - - /* request the summary info from the parents */ - uint32_t token_b; - uint32_t anstype = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - RsGenExchange::getTokenService()->requestMsgInfo(token_b, anstype, opts, postMap); - - GxsTokenQueue::queueRequest(token_b, POSTBASE_BG_POST_META); - return; -} - - -#define RSGXS_MAX_SERVICE_STRING 1024 -bool encodePostCache(std::string &str, const PostStats &s) -{ - char line[RSGXS_MAX_SERVICE_STRING]; - - snprintf(line, RSGXS_MAX_SERVICE_STRING, "%d %d %d", s.comments, s.up_votes, s.down_votes); - - str = line; - return true; -} - -bool extractPostCache(const std::string &str, PostStats &s) -{ - - uint32_t iupvotes, idownvotes, icomments; - if (3 == sscanf(str.c_str(), "%u %u %u", &icomments, &iupvotes, &idownvotes)) - { - s.comments = icomments; - s.up_votes = iupvotes; - s.down_votes = idownvotes; - return true; - } - return false; -} - - -void p3PostBase::background_updateVoteCounts(const uint32_t &token) -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_updateVoteCounts()"; - std::cerr << std::endl; -#endif - - GxsMsgMetaMap parentMsgList; - GxsMsgMetaMap::iterator mit; - std::vector::iterator vit; - - bool ok = RsGenExchange::getMsgMeta(token, parentMsgList); - - if (!ok) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_updateVoteCounts() ERROR"; - std::cerr << std::endl; -#endif - background_cleanup(); - return; - } - - // generate vector of changes to push to the GUI. - std::vector changes; - - for(mit = parentMsgList.begin(); mit != parentMsgList.end(); ++mit) - { - for(vit = mit->second.begin(); vit != mit->second.end(); ++vit) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_updateVoteCounts() Processing Msg(" << mit->first; - std::cerr << ", " << vit->mMsgId << ")"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - - /* extract current vote count */ - PostStats stats; - if (mBgIncremental) - { - if (!extractPostCache(vit->mServiceString, stats)) - { - if (!(vit->mServiceString.empty())) - { - std::cerr << "p3PostBase::background_updateVoteCounts() Failed to extract Votes"; - std::cerr << std::endl; - std::cerr << "\tFrom String: " << vit->mServiceString; - std::cerr << std::endl; - } - } - } - - /* get increment */ - std::map::iterator it; - it = mBgStatsMap.find(vit->mMsgId); - - if (it != mBgStatsMap.end()) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_updateVoteCounts() Adding to msgChangeMap: "; - std::cerr << mit->first << " MsgId: " << vit->mMsgId; - std::cerr << std::endl; -#endif - - stats.increment(it->second); - - changes.push_back(new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED,mit->first,vit->mMsgId, false)); - } - else - { -#ifdef POSTBASE_DEBUG - // warning. - std::cerr << "p3PostBase::background_updateVoteCounts() Warning No New Votes found."; - std::cerr << " For MsgId: " << vit->mMsgId; - std::cerr << std::endl; -#endif - } - - std::string str; - if (!encodePostCache(str, stats)) - { - std::cerr << "p3PostBase::background_updateVoteCounts() Failed to encode Votes"; - std::cerr << std::endl; - } - else - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_updateVoteCounts() Encoded String: " << str; - std::cerr << std::endl; -#endif - /* store new result */ - uint32_t token_c; - RsGxsGrpMsgIdPair msgId = std::make_pair(vit->mGroupId, vit->mMsgId); - RsGenExchange::setMsgServiceString(token_c, msgId, str); - } - } - } - - notifyChanges(changes); - - // DONE!. - background_cleanup(); - return; - -} - - -bool p3PostBase::background_cleanup() -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_cleanup()"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - - // Cleanup. - mBgStatsMap.clear(); - mBgProcessing = false; - - return true; -} - - - // Overloaded from GxsTokenQueue for Request callbacks. -void p3PostBase::handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::handleResponse(" << token << "," << req_type << "," << status << ")" << std::endl; -#endif - if (status != RsTokenService::COMPLETE) - return; //For now, only manage Complete request - - // stuff. - switch(req_type) - { - case POSTBASE_ALL_GROUPS: - background_loadGroups(token); - break; - case POSTBASE_UNPROCESSED_MSGS: - background_loadUnprocessedMsgs(token); - break; - case POSTBASE_ALL_MSGS: - background_loadAllMsgs(token); - break; - case POSTBASE_BG_POST_META: - background_updateVoteCounts(token); - break; - default: - /* error */ - std::cerr << "p3PostBase::handleResponse() Unknown Request Type: " << req_type; - std::cerr << std::endl; - break; - } -} - -static const uint32_t GXS_POSTED_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months -static const uint8_t GXS_POSTED_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ; - -struct RsGxsPostedNotifyRecordsItem: public RsItem -{ - - RsGxsPostedNotifyRecordsItem() - : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_POSTED_CONFIG,GXS_POSTED_CONFIG_SUBTYPE_NOTIFY_RECORD) - {} - - virtual ~RsGxsPostedNotifyRecordsItem() {} - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { RS_SERIAL_PROCESS(records); } - - void clear() {} - - std::map records; -}; - -class GxsPostedConfigSerializer : public RsServiceSerializer -{ -public: - GxsPostedConfigSerializer() : RsServiceSerializer(RS_SERVICE_GXS_TYPE_POSTED_CONFIG) {} - virtual ~GxsPostedConfigSerializer() {} - - RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const - { - if(service_id != RS_SERVICE_GXS_TYPE_POSTED_CONFIG) - return NULL; - - switch(item_sub_id) - { - case GXS_POSTED_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsPostedNotifyRecordsItem(); - default: - return NULL; - } - } -}; - -bool p3PostBase::service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) -{ -#ifdef GXSFORUMS_CHANNELS - std::cerr << "p3gxsChannels: Checking unused board: called by GxsCleaning." << std::endl; -#endif - - // request all group infos at once - - rstime_t now = time(nullptr); - - RS_STACK_MUTEX(mKnownPostedMutex); - - auto it = mKnownPosted.find(meta.mGroupId); - bool unknown_posted = (it == mKnownPosted.end()); - -#ifdef GXSFORUMS_CHANNELS - std::cerr << " Board " << meta.mGroupId ; -#endif - - if(unknown_posted) - { - // This case should normally not happen. It does because this board was never registered since it may - // arrived before this code was here - -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". Not known yet. Adding current time as new TS." << std::endl; -#endif - mKnownPosted[meta.mGroupId] = now; - IndicateConfigChanged(); - - return true; - } - else - { - bool used_by_friends = (now < it->second + POSTED_UNUSED_BY_FRIENDS_DELAY); - bool subscribed = static_cast(meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED); - - std::cerr << ". subscribed: " << subscribed << ", used_by_friends: " << used_by_friends << " last TS: " << now - it->second << " secs ago (" << (now-it->second)/86400 << " days)"; - - if(!subscribed && !used_by_friends) - { -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". Scheduling for deletion" << std::endl; -#endif - return false; - } - else - { -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". Keeping!" << std::endl; -#endif - return true; - } - } -} - -bool p3PostBase::saveList(bool& cleanup, std::list&saveList) -{ - cleanup = true ; - - RsGxsPostedNotifyRecordsItem *item = new RsGxsPostedNotifyRecordsItem ; - - { - RS_STACK_MUTEX(mKnownPostedMutex); - item->records = mKnownPosted ; - } - - saveList.push_back(item) ; - return true; -} - -bool p3PostBase::loadList(std::list& loadList) -{ - while(!loadList.empty()) - { - RsItem *item = loadList.front(); - loadList.pop_front(); - - rstime_t now = time(NULL); - - RsGxsPostedNotifyRecordsItem *fnr = dynamic_cast(item) ; - - if(fnr != NULL) - { - RS_STACK_MUTEX(mKnownPostedMutex); - - mKnownPosted.clear(); - - for(auto it(fnr->records.begin());it!=fnr->records.end();++it) - if( now < it->second + GXS_POSTED_CONFIG_MAX_TIME_NOTIFY_STORAGE) - mKnownPosted.insert(*it) ; - } - - delete item ; - } - return true; -} - -RsSerialiser* p3PostBase::setupSerialiser() -{ - RsSerialiser* rss = new RsSerialiser; - rss->addSerialType(new GxsPostedConfigSerializer()); - - return rss; -} - diff --git a/libretroshare/src/services/p3postbase.h b/libretroshare/src/services/p3postbase.h deleted file mode 100644 index 3c2f5f67f..000000000 --- a/libretroshare/src/services/p3postbase.h +++ /dev/null @@ -1,137 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3postbase.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2012 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef P3_POSTBASE_SERVICE_HEADER -#define P3_POSTBASE_SERVICE_HEADER - - -#include "services/p3gxscommon.h" -#include "gxs/rsgenexchange.h" - -#include "util/rstickevent.h" - -#include - -#include -#include -#include - -/* - * - */ - - -class PostStats -{ - public: - PostStats() :up_votes(0), down_votes(0), comments(0) { return; } - PostStats(int up, int down, int c) :up_votes(up), down_votes(down), comments(c) { return; } - - void increment(const PostStats &s) - { - up_votes += s.up_votes; - down_votes += s.down_votes; - comments += s.comments; - return; - } - - int up_votes; - int down_votes; - int comments; - std::list voters; -}; - -bool encodePostCache(std::string &str, const PostStats &s); -bool extractPostCache(const std::string &str, PostStats &s); - - -class p3PostBase: public RsGenExchange, public GxsTokenQueue, public RsTickEvent, public p3Config -{ -public: - - p3PostBase(RsGeneralDataService *gds, RsNetworkExchangeService *nes, RsGixs* gixs, - RsSerialType* serviceSerialiser, uint16_t serviceType); - - virtual void service_tick() override; - -protected: - - virtual void notifyChanges(std::vector& changes) override; - - // Overloaded from GxsTokenQueue for Request callbacks. - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) override; - - // Overloaded from RsTickEvent. - virtual void handle_event(uint32_t event_type, const std::string &elabel) override; - - // overloads p3Config - virtual RsSerialiser* setupSerialiser() override; // @see p3Config::setupSerialiser() - virtual bool saveList(bool &cleanup, std::list&saveList) override; // @see p3Config::saveList(bool &cleanup, std::list&) - virtual bool loadList(std::list& loadList) override; // @see p3Config::loadList(std::list&) - - virtual bool service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) override; -public: - - ////////////////////////////////////////////////////////////////////////////// - - virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read); - - -protected: - - p3GxsCommentService *mCommentService; - -private: - - static uint32_t postBaseAuthenPolicy(); - - // Background processing. - void background_tick(); - - bool background_requestAllGroups(); - void background_loadGroups(const uint32_t &token); - - void addGroupForProcessing(RsGxsGroupId grpId); - void background_requestUnprocessedGroup(); - - void background_requestGroupMsgs(const RsGxsGroupId &grpId, bool unprocessedOnly); - void background_loadUnprocessedMsgs(const uint32_t &token); - void background_loadAllMsgs(const uint32_t &token); - void background_loadMsgs(const uint32_t &token, bool unprocessed); - - - void background_updateVoteCounts(const uint32_t &token); - bool background_cleanup(); - - - RsMutex mPostBaseMtx; - RsMutex mKnownPostedMutex; - - bool mBgProcessing; - bool mBgIncremental; - std::set mBgGroupList; - std::map mBgStatsMap; - - std::map mKnownPosted; -}; - -#endif diff --git a/libretroshare/src/services/p3posted.cc b/libretroshare/src/services/p3posted.cc deleted file mode 100644 index 20c3f2151..000000000 --- a/libretroshare/src/services/p3posted.cc +++ /dev/null @@ -1,526 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3posted.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "services/p3posted.h" -#include "rsitems/rsposteditems.h" - -#include -#include - - -/**** - * #define POSTED_DEBUG 1 - ****/ - -/*extern*/ RsPosted* rsPosted = nullptr; - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3Posted::p3Posted( - RsGeneralDataService *gds, RsNetworkExchangeService *nes, - RsGixs* gixs ) : - p3PostBase( gds, nes, gixs, new RsGxsPostedSerialiser(), - RS_SERVICE_GXS_TYPE_POSTED ), - RsPosted(static_cast(*this)) {} - -const std::string GXS_POSTED_APP_NAME = "gxsposted"; -const uint16_t GXS_POSTED_APP_MAJOR_VERSION = 1; -const uint16_t GXS_POSTED_APP_MINOR_VERSION = 0; -const uint16_t GXS_POSTED_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_POSTED_MIN_MINOR_VERSION = 0; - -static const uint32_t GXS_POSTED_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months -static const uint8_t GXS_POSTED_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ; - -RsServiceInfo p3Posted::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_POSTED, - GXS_POSTED_APP_NAME, - GXS_POSTED_APP_MAJOR_VERSION, - GXS_POSTED_APP_MINOR_VERSION, - GXS_POSTED_MIN_MAJOR_VERSION, - GXS_POSTED_MIN_MINOR_VERSION); -} - -bool p3Posted::groupShareKeys(const RsGxsGroupId& groupId,const std::set& peers) -{ - RsGenExchange::shareGroupPublishKey(groupId,peers) ; - return true ; -} - -bool p3Posted::getGroupData(const uint32_t &token, std::vector &groups) -{ - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsPostedGroupItem* item = dynamic_cast(*vit); - if (item) - { - RsPostedGroup grp; - item->toPostedGroup(grp, true); - delete item; - groups.push_back(grp); - } - else - { - std::cerr << "Not a RsGxsPostedGroupItem, deleting!" << std::endl; - delete *vit; - } - } - } - return ok; -} - -bool p3Posted::getPostData( - const uint32_t &token, std::vector &msgs, - std::vector &cmts, - std::vector &vots) -{ -#ifdef POSTED_DEBUG - RsDbg() << __PRETTY_FUNCTION__ << std::endl; -#endif - - GxsMsgDataMap msgData; - rstime_t now = time(NULL); - if(!RsGenExchange::getMsgData(token, msgData)) - { - RsErr() << __PRETTY_FUNCTION__ << " ERROR in request" << std::endl; - return false; - } - - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsPostedPostItem* postItem = - dynamic_cast(*vit); - - if(postItem) - { - // TODO Really needed all of these lines? - RsPostedPost msg = postItem->mPost; - msg.mMeta = postItem->meta; - postItem->toPostedPost(msg, true); - msg.calculateScores(now); - - msgs.push_back(msg); - delete postItem; - } - else - { - RsGxsCommentItem* cmtItem = - dynamic_cast(*vit); - if(cmtItem) - { - RsGxsComment cmt; - RsGxsMsgItem *mi = (*vit); - cmt = cmtItem->mMsg; - cmt.mMeta = mi->meta; -#ifdef GXSCOMMENT_DEBUG - RsDbg() << __PRETTY_FUNCTION__ << " Found Comment:" << std::endl; - cmt.print(std::cerr," ", "cmt"); -#endif - cmts.push_back(cmt); - delete cmtItem; - } - else - { - RsGxsVoteItem* votItem = - dynamic_cast(*vit); - if(votItem) - { - RsGxsVote vot; - RsGxsMsgItem *mi = (*vit); - vot = votItem->mMsg; - vot.mMeta = mi->meta; - vots.push_back(vot); - delete votItem; - } - else - { - RsGxsMsgItem* msg = (*vit); - //const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS = 0x0217; - //const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM = 0x03; - //const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM = 0xf1; - //const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_VOTE_ITEM = 0xf2; - RsErr() << __PRETTY_FUNCTION__ - << "Not a PostedPostItem neither a " - << "RsGxsCommentItem neither a RsGxsVoteItem" - << " PacketService=" << std::hex << (int)msg->PacketService() << std::dec - << " PacketSubType=" << std::hex << (int)msg->PacketSubType() << std::dec - << " type name =" << typeid(*msg).name() - << " , deleting!" << std::endl; - delete *vit; - } - } - } - } - } - - return true; -} - -bool p3Posted::getPostData( - const uint32_t &token, std::vector &posts, std::vector &cmts) -{ - std::vector vots; - return getPostData( token, posts, cmts, vots); -} - -bool p3Posted::getPostData( - const uint32_t &token, std::vector &posts) -{ - std::vector cmts; - std::vector vots; - return getPostData( token, posts, cmts, vots); -} - -//Not currently used -/*bool p3Posted::getRelatedPosts(const uint32_t &token, std::vector &msgs) -{ - GxsMsgRelatedDataMap msgData; - bool ok = RsGenExchange::getMsgRelatedData(token, msgData); - rstime_t now = time(NULL); - - if(ok) - { - GxsMsgRelatedDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsPostedPostItem* item = dynamic_cast(*vit); - - if(item) - { - RsPostedPost msg = item->mPost; - msg.mMeta = item->meta; - msg.calculateScores(now); - - msgs.push_back(msg); - delete item; - } - else - { - std::cerr << "Not a PostedPostItem, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -}*/ - - -/********************************************************************************************/ -/********************************************************************************************/ -/********************************************************************************************/ - -/* Switched from having explicit Ranking calculations to calculating the set of scores - * on each RsPostedPost item. - * - * TODO: move this function to be part of RsPostedPost - then the GUI - * can reuse is as necessary. - * - */ - -bool RsPostedPost::calculateScores(rstime_t ref_time) -{ - /* so we want to calculate all the scores for this Post. */ - - PostStats stats; - extractPostCache(mMeta.mServiceString, stats); - - mUpVotes = stats.up_votes; - mDownVotes = stats.down_votes; - mComments = stats.comments; - mHaveVoted = (mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK); - - rstime_t age_secs = ref_time - mMeta.mPublishTs; -#define POSTED_AGESHIFT (2.0) -#define POSTED_AGEFACTOR (3600.0) - - mTopScore = ((int) mUpVotes - (int) mDownVotes); - if (mTopScore > 0) - { - // score drops with time. - mHotScore = mTopScore / pow(POSTED_AGESHIFT + age_secs / POSTED_AGEFACTOR, 1.5); - } - else - { - // gets more negative with time. - mHotScore = mTopScore * pow(POSTED_AGESHIFT + age_secs / POSTED_AGEFACTOR, 1.5); - } - mNewScore = -age_secs; - - return true; -} - -/********************************************************************************************/ -/********************************************************************************************/ - -bool p3Posted::createGroup(uint32_t &token, RsPostedGroup &group) -{ - std::cerr << "p3Posted::createGroup()" << std::endl; - - RsGxsPostedGroupItem* grpItem = new RsGxsPostedGroupItem(); - grpItem->fromPostedGroup(group, true); - - - RsGenExchange::publishGroup(token, grpItem); - return true; -} - - -bool p3Posted::updateGroup(uint32_t &token, RsPostedGroup &group) -{ - std::cerr << "p3Posted::updateGroup()" << std::endl; - - RsGxsPostedGroupItem* grpItem = new RsGxsPostedGroupItem(); - grpItem->fromPostedGroup(group, true); - - - RsGenExchange::updateGroup(token, grpItem); - return true; -} - - -bool p3Posted::createPost(uint32_t &token, RsPostedPost &msg) -{ - std::cerr << "p3Posted::createPost() GroupId: " << msg.mMeta.mGroupId; - std::cerr << std::endl; - - RsGxsPostedPostItem* msgItem = new RsGxsPostedPostItem(); - //msgItem->mPost = msg; - //msgItem->meta = msg.mMeta; - msgItem->fromPostedPost(msg, true); - - - RsGenExchange::publishMsg(token, msgItem); - return true; -} - -bool p3Posted::getBoardsInfo( - const std::list& boardsIds, - std::vector& groupsInfo ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if(boardsIds.empty()) - { - if( !requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - else - { - if( !requestGroupInfo(token, opts, boardsIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - - return getGroupData(token, groupsInfo) && !groupsInfo.empty(); -} - -bool p3Posted::getBoardAllContent( const RsGxsGroupId& groupId, - std::vector& posts, - std::vector& comments, - std::vector& votes ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - if( !requestMsgInfo(token, opts, std::list({groupId})) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - - return getPostData(token, posts, comments, votes); -} - -bool p3Posted::getBoardContent( const RsGxsGroupId& groupId, - const std::set& contentsIds, - std::vector& posts, - std::vector& comments, - std::vector& votes ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - GxsMsgReq msgIds; - msgIds[groupId] = contentsIds; - - if( !requestMsgInfo(token, opts, msgIds) || - waitToken(token) != RsTokenService::COMPLETE ) return false; - - return getPostData(token, posts, comments, votes); -} - -bool p3Posted::getBoardsSummaries(std::list& boards ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - if( !requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) return false; - - return getGroupSummary(token, boards); -} - -bool p3Posted::getBoardsServiceStatistics(GxsServiceStatistic& stat) -{ - uint32_t token; - if(!RsGxsIfaceHelper::requestServiceStatistic(token) || waitToken(token) != RsTokenService::COMPLETE) - return false; - - return RsGenExchange::getServiceStatistic(token,stat); -} - - -bool p3Posted::getBoardStatistics(const RsGxsGroupId& boardId,GxsGroupStatistic& stat) -{ - uint32_t token; - if(!RsGxsIfaceHelper::requestGroupStatistic(token, boardId) || waitToken(token) != RsTokenService::COMPLETE) - return false; - - return RsGenExchange::getGroupStatistic(token,stat); -} - -bool p3Posted::createBoard(RsPostedGroup& board) -{ - uint32_t token; - if(!createGroup(token, board)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failed creating group." << std::endl; - return false; - } - - if(waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, board.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated " << " group data." << std::endl; - return false; - } - - return true; -} - -bool p3Posted::voteForPost(bool up,const RsGxsGroupId& postGrpId,const RsGxsMessageId& postMsgId,const RsGxsId& authorId) -{ - // Do some basic tests - - if(!rsIdentity->isOwnId(authorId)) // This is ruled out before waitToken complains. Not sure it's needed. - { - std::cerr << __PRETTY_FUNCTION__ << ": vote submitted with an ID that is not yours! This cannot work." << std::endl; - return false; - } - - RsGxsVote vote; - - vote.mMeta.mGroupId = postGrpId; - vote.mMeta.mThreadId = postMsgId; - vote.mMeta.mParentId = postMsgId; - vote.mMeta.mAuthorId = authorId; - - if (up) - vote.mVoteType = GXS_VOTE_UP; - else - vote.mVoteType = GXS_VOTE_DOWN; - - uint32_t token; - - if(!createNewVote(token, vote)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failed submitting vote to (group,msg) " << postGrpId << "," << postMsgId << " from author " << authorId << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." << std::endl; - return false; - } - return true; -} - -bool p3Posted::setPostReadStatus(const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t token; - - setMessageReadStatus(token,msgId,read); - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." << std::endl; - return false; - } - RsGxsGrpMsgIdPair p; - acknowledgeMsg(token,p); - return true; -} -bool p3Posted::editBoard(RsPostedGroup& board) -{ - uint32_t token; - if(!updateGroup(token, board)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failed updating group." << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, board.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting updated " << " group data." << std::endl; - return false; - } - - return true; -} - -RsPosted::~RsPosted() = default; -RsGxsPostedEvent::~RsGxsPostedEvent() = default; diff --git a/libretroshare/src/services/p3posted.h b/libretroshare/src/services/p3posted.h deleted file mode 100644 index 0965ec1d1..000000000 --- a/libretroshare/src/services/p3posted.h +++ /dev/null @@ -1,158 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3posted.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef P3_POSTED_SERVICE_HEADER -#define P3_POSTED_SERVICE_HEADER - - -#include "retroshare/rsposted.h" -#include "services/p3postbase.h" - -#include - -#include -#include -#include - -/* - * - */ - -class p3Posted: public p3PostBase, public RsPosted -{ -public: - - p3Posted(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs); - virtual RsServiceInfo getServiceInfo(); - -protected: - -virtual void notifyChanges(std::vector& changes) -{ - return p3PostBase::notifyChanges(changes); -} - - public: - -#ifdef TO_REMOVE -virtual void receiveHelperChanges(std::vector& changes) -{ - return RsGxsIfaceHelper::receiveChanges(changes); -} -#endif - - bool getBoardsInfo(const std::list& boardsIds, - std::vector& groupsInfo ) override; - - bool getBoardAllContent(const RsGxsGroupId& groupId, - std::vector& posts, - std::vector& comments, - std::vector& votes ) override; - - bool getBoardContent(const RsGxsGroupId& groupId, - const std::set& contentsIds, - std::vector& posts, - std::vector& comments, - std::vector& votes ) override; - - bool getBoardsSummaries(std::list& groupInfo) override; - - bool getBoardStatistics(const RsGxsGroupId& boardId,GxsGroupStatistic& stat) override; - - bool getBoardsServiceStatistics(GxsServiceStatistic& stat) override; - - bool editBoard(RsPostedGroup& board) override; - - bool createBoard(RsPostedGroup& board) override; - - bool voteForPost(bool up,const RsGxsGroupId& postGrpId,const RsGxsMessageId& postMsgId,const RsGxsId& voterId) override; - - bool setPostReadStatus(const RsGxsGrpMsgIdPair& msgId, bool read) override; - - virtual bool getGroupData(const uint32_t &token, std::vector &groups) override; - virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts, std::vector &vots) override; - virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts) override; - virtual bool getPostData(const uint32_t &token, std::vector &posts) override; - -//Not currently used -//virtual bool getRelatedPosts(const uint32_t &token, std::vector &posts); - -virtual bool createGroup(uint32_t &token, RsPostedGroup &group) override; -virtual bool createPost(uint32_t &token, RsPostedPost &post) override; - -virtual bool updateGroup(uint32_t &token, RsPostedGroup &group) override; -virtual bool groupShareKeys(const RsGxsGroupId &group, const std::set& peers) override; - - ////////////////////////////////////////////////////////////////////////////// - // WRAPPERS due to the separate Interface. - -virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) override - { - return p3PostBase::setMessageReadStatus(token, msgId, read); - } - - virtual bool setCommentAsRead(uint32_t& token,const RsGxsGroupId& gid,const RsGxsMessageId& comment_msg_id) override - { - p3PostBase::setMessageReadStatus(token,RsGxsGrpMsgIdPair(gid,comment_msg_id),true); - return true; - } - - - - /** Comment service - Provide RsGxsCommentService - - * redirect to p3GxsCommentService */ - virtual bool getCommentData(uint32_t token, std::vector &msgs) override - { return mCommentService->getGxsCommentData(token, msgs); } - - virtual bool getRelatedComments( uint32_t token, - std::vector &msgs ) override - { return mCommentService->getGxsRelatedComments(token, msgs); } - - virtual bool createNewComment(uint32_t &token, const RsGxsComment &msg) override - { - return mCommentService->createGxsComment(token, msg); - } - virtual bool createComment(RsGxsComment& msg) override - { - uint32_t token; - - return mCommentService->createGxsComment(token, msg) && waitToken(token) == RsTokenService::COMPLETE ; - } - - virtual bool createNewVote(uint32_t &token, RsGxsVote &msg) override - { - return mCommentService->createGxsVote(token, msg); - } - - virtual bool acknowledgeComment( - uint32_t token, std::pair& msgId ) override - { return acknowledgeMsg(token, msgId); } - - virtual bool acknowledgeVote( - uint32_t token, std::pair& msgId ) override - { - if (mCommentService->acknowledgeVote(token, msgId)) return true; - return acknowledgeMsg(token, msgId); - } -}; - -#endif diff --git a/libretroshare/src/services/p3rtt.cc b/libretroshare/src/services/p3rtt.cc deleted file mode 100644 index 0dc2f41e2..000000000 --- a/libretroshare/src/services/p3rtt.cc +++ /dev/null @@ -1,461 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3rtt.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2013 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include -#include - -#include "util/rsdir.h" -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" -#include "pqi/pqibin.h" -#include "pqi/pqistore.h" -#include "pqi/p3linkmgr.h" -#include "rsserver/p3face.h" -#include "util/cxx17retrocompat.h" -#include "services/p3rtt.h" -#include "rsitems/rsrttitems.h" - - -/**** - * #define DEBUG_RTT 1 - ****/ - -/* DEFINE INTERFACE POINTER! */ -RsRtt *rsRtt = NULL; - - -#define MAX_PONG_RESULTS 150 -#define RTT_PING_PERIOD 10 - -/************ IMPLEMENTATION NOTES ********************************* - * - * Voice over Retroshare ;) - * - * This will be a simple test VoIP system aimed at testing out the possibilities. - * - * Important things to test: - * 1) lag, and variability in data rate - * - To do this we time tag every packet..., the destination can use this info to calculate the results. - * - Like imixitup. Dt = clock_diff + lag. - * we expect clock_diff to be relatively constant, but lag to vary. - * lag cannot be negative, so minimal Dt is ~clock_diff, and delays on this are considered +lag. - * - * 2) we could directly measure lag. ping back and forth with Timestamps. - * - * 3) we also want to measure bandwidth... - * - not sure the best method? - * one way: send a ping, then a large amount of data (5 seconds worth), then another ping. - * the delta in timestamps should be a decent indication of bandwidth. - * say we have a 100kb/s connection... need 500kb. - * actually the amount of data should be based on a reasonable maximum that we require. - * what does decent video require? - * Audio we can test for 64kb/s - which seems like a decent rate: e.g. mono, 16bit 22k = 1 x 2 x 22k = 44 kilobytes/sec - * best to do this without a VoIP call going on ;) - * - * - */ - - -#ifdef WINDOWS_SYS -#include "util/rstime.h" -#include -#endif - -static double getCurrentTS() -{ - -#ifndef WINDOWS_SYS - struct timeval cts_tmp; - gettimeofday(&cts_tmp, NULL); - double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; -#else - struct _timeb timebuf; - _ftime( &timebuf); - double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; -#endif - return cts; -} - -static uint64_t convertTsTo64bits(double ts) -{ - uint32_t secs = (uint32_t) ts; - uint32_t usecs = (uint32_t) ((ts - (double) secs) * 1000000); - uint64_t bits = (((uint64_t) secs) << 32) + usecs; - return bits; -} - - -static double convert64bitsToTs(uint64_t bits) -{ - uint32_t usecs = (uint32_t) (bits & 0xffffffff); - uint32_t secs = (uint32_t) ((bits >> 32) & 0xffffffff); - double ts = (secs) + ((double) usecs) / 1000000.0; - - return ts; -} - - - - -p3rtt::p3rtt(p3ServiceControl *sc) - :p3FastService(), mRttMtx("p3rtt"), mServiceCtrl(sc) -{ - addSerialType(new RsRttSerialiser()); - - mSentPingTime = 0; - mCounter = 0; - -} - - -const std::string RTT_APP_NAME = "rtt"; -const uint16_t RTT_APP_MAJOR_VERSION = 1; -const uint16_t RTT_APP_MINOR_VERSION = 0; -const uint16_t RTT_MIN_MAJOR_VERSION = 1; -const uint16_t RTT_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3rtt::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_RTT, - RTT_APP_NAME, - RTT_APP_MAJOR_VERSION, - RTT_APP_MINOR_VERSION, - RTT_MIN_MAJOR_VERSION, - RTT_MIN_MINOR_VERSION); -} - - - -int p3rtt::tick() -{ - sendPackets(); - - return 0; -} - -int p3rtt::status() -{ - return 1; -} - - - -int p3rtt::sendPackets() -{ - rstime_t now = time(NULL); - rstime_t pt; - { - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - pt = mSentPingTime; - } - - if (now >= pt+RTT_PING_PERIOD) - { - sendPingMeasurements(); - - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - mSentPingTime = now; - } - return true ; -} - - - -void p3rtt::sendPingMeasurements() -{ - - - /* we ping our peers */ - /* who is online? */ - std::set idList; - - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, idList); - - /* prepare packets */ - std::set::iterator it; - for(it = idList.begin(); it != idList.end(); ++it) - { - double ts = getCurrentTS(); - - /* create the packet */ - RsRttPingItem *pingPkt = new RsRttPingItem(); - pingPkt->PeerId(*it); - pingPkt->mSeqNo = mCounter; - pingPkt->mPingTS = convertTsTo64bits(ts); - - storePingAttempt(*it, ts, mCounter); - -#ifdef DEBUG_RTT - std::cerr << "p3rtt::sendPingMeasurements() Pinging: " << *it << " [" << pingPkt->mSeqNo << "," << std::hex << pingPkt->mPingTS << std::dec << "]" << std::endl;; -#endif - sendItem(pingPkt); - } - - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - mCounter++; -} - - -bool p3rtt::recvItem(RsItem *item) -{ - switch(item->PacketSubType()) - { - default: - break; - case RS_PKT_SUBTYPE_RTT_PING: - { - handlePing(item); - } - break; - case RS_PKT_SUBTYPE_RTT_PONG: - { - handlePong(item); - } - break; - } - - /* clean up */ - delete item; - return true ; -} - - -int p3rtt::handlePing(RsItem *item) -{ - /* cast to right type */ - RsRttPingItem *ping = (RsRttPingItem *) item; - - double ts = getCurrentTS(); -#ifdef DEBUG_RTT - std::cerr << "p3rtt::handlePing() from: " << ping->PeerId() << " - [" << ping->mSeqNo << "," << std::hex << ping->mPingTS << std::dec << "] " << std::endl; - std::cerr << "incoming ping travel time: " << ts - convert64bitsToTs(ping->mPingTS) << std::endl; -#endif - - /* with a ping, we just respond as quickly as possible - they do all the analysis */ - RsRttPongItem *pong = new RsRttPongItem(); - - pong->PeerId(ping->PeerId()); - pong->mPingTS = ping->mPingTS; - pong->mSeqNo = ping->mSeqNo; - - // add our timestamp. - pong->mPongTS = convertTsTo64bits(ts); - -#ifdef DEBUG_RTT - static double mLastResponseToPong = 0.0 ;// bad stuff - std::cerr << "Delay since last response to PONG: " << ts - mLastResponseToPong << std::endl; - mLastResponseToPong = ts ; -#endif - - sendItem(pong); - return true ; -} - - -int p3rtt::handlePong(RsItem *item) -{ - /* cast to right type */ - RsRttPongItem *pong = (RsRttPongItem *) item; - -#ifdef DEBUG_RTT - std::cerr << "p3rtt::handlePong() from: " << pong->PeerId() << " - [" << pong->mSeqNo << "," << std::hex << pong->mPingTS << " -> " << pong->mPongTS << std::dec << "] "<< std::endl; -#endif - - /* with a pong, we do the maths! */ - double recvTS = getCurrentTS(); - double pingTS = convert64bitsToTs(pong->mPingTS); - double pongTS = convert64bitsToTs(pong->mPongTS); - - double rtt = recvTS - pingTS; - double offset = pongTS - (recvTS - rtt / 2.0); // so to get to their time, we go ourTS + offset. - -#ifdef DEBUG_RTT - std::cerr << "incoming pong travel time: " << recvTS - convert64bitsToTs(pong->mPongTS) << std::endl; - std::cerr << " RTT analysis: pingTS: " << std::setprecision(16) << pingTS << ", pongTS: " << pongTS - << ", recvTS: " << std::setprecision(16) << recvTS << " ==> rtt: " << rtt << ", offset: " << offset << std::endl; -#endif - - storePongResult(pong->PeerId(), pong->mSeqNo, recvTS, rtt, offset); - return true ; -} - - - - -int p3rtt::storePingAttempt(const RsPeerId& id, double ts, uint32_t seqno) -{ - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - - /* find corresponding local data */ - RttPeerInfo *peerInfo = locked_GetPeerInfo(id); - -#ifdef DEBUG_RTT - std::cerr << "Delay since previous ping attempt: " << ts - peerInfo->mCurrentPingTS << std::endl; -#endif - peerInfo->mCurrentPingTS = ts; - peerInfo->mCurrentPingCounter = seqno; - - peerInfo->mSentPings++; - if (!peerInfo->mCurrentPongRecvd) - { - peerInfo->mLostPongs++; - } - - peerInfo->mCurrentPongRecvd = true; - - return 1; -} - - - -int p3rtt::storePongResult(const RsPeerId& id, uint32_t counter, double recv_ts, double rtt, double offset) -{ - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - - /* find corresponding local data */ - RttPeerInfo *peerInfo = locked_GetPeerInfo(id); - - if (peerInfo->mCurrentPingCounter != counter) - { -#ifdef DEBUG_RTT - std::cerr << "p3rtt::storePongResult() ERROR Severly Delayed Measurements!" << std::endl; -#endif - } - else - { - peerInfo->mCurrentPongRecvd = true; - } -#ifdef DEBUG_RTT - if(!peerInfo->mPongResults.empty()) - std::cerr << "Delay since last pong: " << recv_ts - peerInfo->mPongResults.back().mTS << std::endl; -#endif - - peerInfo->mPongResults.push_back(RsRttPongResult(recv_ts, rtt, offset)); - - - while(peerInfo->mPongResults.size() > MAX_PONG_RESULTS) - peerInfo->mPongResults.pop_front(); - - //Wait at least 20 pongs before compute mean time offset - if(peerInfo->mPongResults.size() > 20) - { - double mean = 0; - for(auto prIt : std::as_const(peerInfo->mPongResults)) - mean += prIt.mOffset; - peerInfo->mCurrentMeanOffset = mean / peerInfo->mPongResults.size(); - - if(fabs(peerInfo->mCurrentMeanOffset) > 120) - { - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mSslId = peerInfo->mId; - ev->mTimeShift = static_cast(peerInfo->mCurrentMeanOffset); - ev->mConnectionInfoCode = RsConnectionEventCode::PEER_TIME_SHIFT; - rsEvents->postEvent(ev); - } - RsWarn() << __PRETTY_FUNCTION__ << " Peer: " << peerInfo->mId - << " have a time offset of more than two minutes with you" - << std::endl; - } - } - return 1; -} - - -uint32_t p3rtt::getPongResults(const RsPeerId& id, int n, std::list &results) -{ - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - - RttPeerInfo *peer = locked_GetPeerInfo(id); - - std::list::reverse_iterator it; - int i = 0; - for(it = peer->mPongResults.rbegin(); (it != peer->mPongResults.rend()) && (i < n); ++it, i++) - { - /* reversing order - so its easy to trim later */ - results.push_back(*it); - } - return i ; -} - -double p3rtt::getMeanOffset(const RsPeerId &id) -{ - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - - RttPeerInfo *peer = locked_GetPeerInfo(id); - if(peer) - return peer->mCurrentMeanOffset; - else - return 0; -} - -RttPeerInfo *p3rtt::locked_GetPeerInfo(const RsPeerId& id) -{ - std::map::iterator it; - it = mPeerInfo.find(id); - if (it == mPeerInfo.end()) - { - /* add it in */ - RttPeerInfo pinfo; - - /* initialise entry */ - pinfo.initialisePeerInfo(id); - - mPeerInfo[id] = pinfo; - - it = mPeerInfo.find(id); - - } - - return &(it->second); -} - - - -bool RttPeerInfo::initialisePeerInfo(const RsPeerId& id) -{ - mId = id; - - /* reset variables */ - mCurrentPingTS = 0; - mCurrentPingCounter = 0; - mCurrentPongRecvd = true; - mCurrentMeanOffset = 0; - - mSentPings = 0; - mLostPongs = 0; - - mPongResults.clear(); - - return true; -} - - - - - - - - - - diff --git a/libretroshare/src/services/p3rtt.h b/libretroshare/src/services/p3rtt.h deleted file mode 100644 index c8df64034..000000000 --- a/libretroshare/src/services/p3rtt.h +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3rtt.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2013 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef SERVICE_RSRTT_HEADER -#define SERVICE_RSRTT_HEADER - -#include -#include - -#include "rsitems/rsrttitems.h" -#include "services/p3service.h" -#include "retroshare/rsrtt.h" - -class p3ServiceControl; - -class RttPeerInfo -{ - public: - RttPeerInfo() - : mCurrentPingTS(0.0),mCurrentPingCounter(0.0),mCurrentPongRecvd(false),mCurrentMeanOffset(0.0),mLostPongs(0),mSentPings(0){} - - bool initialisePeerInfo(const RsPeerId& id); - - RsPeerId mId; - double mCurrentPingTS; - double mCurrentPingCounter; - bool mCurrentPongRecvd; - double mCurrentMeanOffset; - - uint32_t mLostPongs; - uint32_t mSentPings; - - std::list mPongResults; -}; - - -//!The RS Rtt Test service. - /** - * - * Used to test Latency. - */ - -class p3rtt: public RsRtt, public p3FastService -{ - public: - p3rtt(p3ServiceControl *sc); -virtual RsServiceInfo getServiceInfo(); - - /***** overloaded from rsRtt *****/ - -virtual uint32_t getPongResults(const RsPeerId& id, int n, std::list &results); -virtual double getMeanOffset(const RsPeerId &id); - - /***** overloaded from p3Service *****/ - - virtual int tick(); - virtual int status(); - - int sendPackets(); - void sendPingMeasurements(); - -virtual bool recvItem(RsItem *item); // Overloaded from p3FastService. - - int handlePing(RsItem *item); - int handlePong(RsItem *item); - - int storePingAttempt(const RsPeerId& id, double ts, uint32_t mCounter); - int storePongResult(const RsPeerId& id, uint32_t counter, double recv_ts, double rtt, double offset); - - - /*! - * This retrieves all public chat msg items - */ - //bool getPublicChatQueue(std::list &chats); - - /*************** pqiMonitor callback ***********************/ - //virtual void statusChange(const std::list &plist); - - - /************* from p3Config *******************/ - //virtual RsSerialiser *setupSerialiser() ; - //virtual bool saveList(bool& cleanup, std::list&) ; - //virtual void saveDone(); - //virtual bool loadList(std::list& load) ; - - private: - RsMutex mRttMtx; - - RttPeerInfo *locked_GetPeerInfo(const RsPeerId& id); - - std::map mPeerInfo; - rstime_t mSentPingTime; - uint32_t mCounter; - - p3ServiceControl *mServiceCtrl; - -}; - -#endif // SERVICE_RSRTT_HEADER - diff --git a/libretroshare/src/services/p3service.cc b/libretroshare/src/services/p3service.cc deleted file mode 100644 index 54ba176ef..000000000 --- a/libretroshare/src/services/p3service.cc +++ /dev/null @@ -1,223 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3service.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "rsitems/itempriorities.h" - -#include "pqi/pqi.h" -#include "util/rsstring.h" -#include "services/p3service.h" -#include - -#ifdef WINDOWS_SYS -#include "util/rstime.h" -#endif - -/***** - * #define SERV_DEBUG 1 - ****/ - - - -RsItem *p3Service::recvItem() -{ - RsStackMutex stack(srvMtx); /***** LOCK MUTEX *****/ - - if (recv_queue.empty()) - { - return NULL; /* nothing there! */ - } - - /* get something off front */ - RsItem *item = recv_queue.front(); - recv_queue.pop_front(); - - return item; -} - - -bool p3Service::receivedItems() -{ - RsStackMutex stack(srvMtx); /***** LOCK MUTEX *****/ - - return (!recv_queue.empty()); -} - - -bool p3Service::recvItem(RsItem *item) -{ - if (item) - { - RsStackMutex stack(srvMtx); /***** LOCK MUTEX *****/ - - recv_queue.push_back(item); - } - return true; -} - - - - - -void p3FastService::addSerialType(RsSerialType *st) -{ - rsSerialiser->addSerialType(st); -} - - - // overloaded pqiService interface. -bool p3FastService::recv(RsRawItem *raw) -{ - RsItem *item = NULL; - { - RsStackMutex stack(srvMtx); /***** LOCK MUTEX *****/ - - #ifdef SERV_DEBUG - std::cerr << "p3Service::recv()"; - std::cerr << std::endl; - #endif - - /* convert to RsServiceItem */ - uint32_t size = raw->getRawLength(); - item = rsSerialiser->deserialise(raw->getRawData(), &size); - if ((!item) || (size != raw->getRawLength())) - { - /* error in conversion */ - #ifdef SERV_DEBUG - std::cerr << "p3Service::recv() Error" << std::endl; - std::cerr << "p3Service::recv() Size: " << size << std::endl; - std::cerr << "p3Service::recv() RawLength: " << raw->getRawLength() << std::endl; - #endif - - if (item) - { - #ifdef SERV_DEBUG - std::cerr << "p3Service::recv() Bad Item:"; - std::cerr << std::endl; - item->print(std::cerr, 0); - std::cerr << std::endl; - #endif - delete item; - item=NULL ; - } - } - } - - /* if we have something - pass it on */ - if (item) - { -#ifdef SERV_DEBUG - std::cerr << "p3Service::recv() item:"; - std::cerr << std::endl; - item->print(std::cerr, 0); - std::cerr << std::endl; -#endif - - /* ensure PeerId is transferred */ - item->PeerId(raw->PeerId()); - recvItem(item); - } - - /* cleanup input */ - delete raw; - return (item != NULL); -} - - - -int p3FastService::sendItem(RsItem *si) -{ - RsStackMutex stack(srvMtx); /***** LOCK MUTEX *****/ - -#ifdef SERV_DEBUG - std::cerr << "p3Service::sendItem() Sending item:"; - std::cerr << std::endl; - si->print(std::cerr, 0); - std::cerr << std::endl; -#endif - - /* try to convert */ - uint32_t size = rsSerialiser->size(si); - if (!size) - { - std::cerr << "p3Service::send() ERROR size == 0"; - std::cerr << std::endl; - - /* can't convert! */ - delete si; - return 0; - } - - RsRawItem *raw = new RsRawItem(si->PacketId(), size); - if (!rsSerialiser->serialise(si, raw->getRawData(), &size)) - { - std::cerr << "p3Service::send() ERROR serialise failed"; - std::cerr << std::endl; - - delete raw; - raw = NULL; - } - - if ((raw) && (size != raw->getRawLength())) - { - std::cerr << "p3Service::send() ERROR serialise size mismatch"; - std::cerr << std::endl; - - delete raw; - raw = NULL; - } - - /* ensure PeerId is transferred */ - if (raw) - { - raw->PeerId(si->PeerId()); - - if(si->priority_level() == QOS_PRIORITY_UNKNOWN) - { - std::cerr << "************************************************************" << std::endl; - std::cerr << "********** Warning: p3Service::send() ********" << std::endl; - std::cerr << "********** Warning: caught a RsItem with undefined ********" << std::endl; - std::cerr << "********** priority level. That should not ********" << std::endl; - std::cerr << "********** happen. Please fix your items! ********" << std::endl; - std::cerr << "************************************************************" << std::endl; - } - raw->setPriorityLevel(si->priority_level()) ; - -#ifdef SERV_DEBUG - std::cerr << "p3Service::send() returning RawItem."; - std::cerr << std::endl; -#endif - delete si; - - return pqiService::send(raw); - } - else - { - std::cerr << "p3service: item could not be properly serialised. Will be wasted. Item is: "<< std::endl; - si->print(std::cerr,0) ; - - /* cleanup */ - delete si; - - return 0 ; - } -} - - diff --git a/libretroshare/src/services/p3service.h b/libretroshare/src/services/p3service.h deleted file mode 100644 index a394b1094..000000000 --- a/libretroshare/src/services/p3service.h +++ /dev/null @@ -1,173 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3service.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef P3_GENERIC_SERVICE_HEADER -#define P3_GENERIC_SERVICE_HEADER - -#include "pqi/pqi.h" -#include "pqi/pqiservice.h" -#include "util/rsthreads.h" - -/* This provides easy to use extensions to the pqiservice class provided in src/pqi. - * - * We will have a number of different strains. - * - * (1) p3Service -> pqiService - * - * Basic service with serialisation handled by a RsSerialiser. - * - * (2) p3ThreadedService -> p3service. - * - * Independent thread with mutex locks for i/o Queues. - * ideal for games etc. - * - * (3) p3CacheService -> p3service + CacheSource + CacheStore. - * - * For both Cached and Messages. - */ - -std::string generateRandomServiceId(); - -//TODO : encryption and upload / download rate implementation - - -// p3FastService(uint16_t type) -// :pqiService((RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(type)), - - -class p3FastService: public pqiService -{ - protected: - - p3FastService() - :pqiService(), - srvMtx("p3FastService"), rsSerialiser(NULL) - { - rsSerialiser = new RsSerialiser(); - return; - } - - public: - -virtual ~p3FastService() { delete rsSerialiser; return; } - -/*************** INTERFACE ******************************/ -int sendItem(RsItem *); -virtual int tick() { return 0; } -/*************** INTERFACE ******************************/ - - public: - // overloaded pqiService interface. -virtual bool recv(RsRawItem *); - - // called by recv(). -virtual bool recvItem(RsItem *item) = 0; - - - protected: -void addSerialType(RsSerialType *); - - RsMutex srvMtx; /* below locked by Mutex */ - - RsSerialiser *rsSerialiser; -}; - - -class p3Service: public p3FastService -{ - protected: - - p3Service() - :p3FastService() - { - return; - } - - public: - -/*************** INTERFACE ******************************/ - /* called from Thread/tick/GUI */ -//int sendItem(RsItem *); -RsItem * recvItem(); -bool receivedItems(); - -//virtual int tick() { return 0; } -/*************** INTERFACE ******************************/ - - public: - // overloaded p3FastService interface. -virtual bool recvItem(RsItem *item); - - private: - - /* below locked by srvMtx Mutex */ - std::list recv_queue; -}; - - -class nullService: public pqiService -{ - protected: - - nullService() - :pqiService() - { - return; - } - -//virtual int tick() - - public: - // overloaded NULL pqiService interface. -virtual bool recv(RsRawItem *item) - { - /* drop any items */ - delete item; - return true; - } - -virtual bool send(RsRawItem *item) - { - delete item; - return true; - } - -}; - - -class p3ThreadedService: public p3Service, public RsTickingThread -{ - protected: - - p3ThreadedService() - :p3Service() { return; } - - public: - -virtual ~p3ThreadedService() { return; } - - private: - -}; - - -#endif // P3_GENERIC_SERVICE_HEADER - diff --git a/libretroshare/src/services/p3serviceinfo.cc b/libretroshare/src/services/p3serviceinfo.cc deleted file mode 100644 index f05604021..000000000 --- a/libretroshare/src/services/p3serviceinfo.cc +++ /dev/null @@ -1,260 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3serviceinfo.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" - -#include "util/rsnet.h" - -#include "services/p3serviceinfo.h" -#include "rsitems/rsbanlistitems.h" - -#include - -/**** - * #define DEBUG_INFO 1 - ****/ - -/************ IMPLEMENTATION NOTES ********************************* - * - * Send Info to peers about services we are providing. - */ - -p3ServiceInfo::p3ServiceInfo(p3ServiceControl *serviceControl) - :p3Service(), mInfoMtx("p3ServiceInfo"), - mServiceControl(serviceControl) -{ - addSerialType(new RsServiceInfoSerialiser()); -} - -const std::string SERVICE_INFO_APP_NAME = "serviceinfo"; -const uint16_t SERVICE_INFO_APP_MAJOR_VERSION = 1; -const uint16_t SERVICE_INFO_APP_MINOR_VERSION = 0; -const uint16_t SERVICE_INFO_MIN_MAJOR_VERSION = 1; -const uint16_t SERVICE_INFO_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3ServiceInfo::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_SERVICEINFO, - SERVICE_INFO_APP_NAME, - SERVICE_INFO_APP_MAJOR_VERSION, - SERVICE_INFO_APP_MINOR_VERSION, - SERVICE_INFO_MIN_MAJOR_VERSION, - SERVICE_INFO_MIN_MINOR_VERSION); -} - - - -int p3ServiceInfo::tick() -{ - processIncoming(); - sendPackets(); - return 0; -} - -int p3ServiceInfo::status() -{ - return 1; -} - - -/***** Implementation ******/ - -bool p3ServiceInfo::processIncoming() -{ - /* for each packet - pass to specific handler */ - RsItem *item = NULL; - while(NULL != (item = recvItem())) - { -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::processingIncoming() Received Item:"; - std::cerr << std::endl; - item->print(std::cerr); - std::cerr << std::endl; -#endif - switch(item->PacketSubType()) - { - default: - break; - case RS_PKT_SUBTYPE_SERVICELIST_ITEM: - { - // Order is important!. - RsServiceInfoListItem *listItem = dynamic_cast(item); - if (listItem) - { - recvServiceInfoList(listItem); - } - else - { - // error. - std::cerr << "p3ServiceInfo::processingIncoming() Error with Received Item:"; - std::cerr << std::endl; - item->print(std::cerr); - std::cerr << std::endl; - } - } - break; - } - - /* clean up */ - delete item; - } - return true ; -} - - -bool convertServiceInfoToItem( - const RsPeerServiceInfo &info, - RsServiceInfoListItem *item) -{ - item->mServiceInfo = info.mServiceList; - item->PeerId(info.mPeerId); - return true; -} - -bool convertServiceItemToInfo( - const RsServiceInfoListItem *item, - RsPeerServiceInfo &info) -{ - info.mServiceList = item->mServiceInfo; - info.mPeerId = item->PeerId(); - return true; -} - - -bool p3ServiceInfo::recvServiceInfoList(RsServiceInfoListItem *item) -{ - RsPeerId peerId = item->PeerId(); - -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::recvServiceInfoList() from: " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - RsPeerServiceInfo info; - if (convertServiceItemToInfo(item, info)) - { - -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::recvServiceInfoList() Info: "; - std::cerr << std::endl; - std::cerr << info; - std::cerr << std::endl; -#endif - - /* update service control */ - mServiceControl->updateServicesProvided(peerId, info); - return true; - } - return false; -} - - -bool p3ServiceInfo::sendPackets() -{ - std::set updateSet; - - { - RsStackMutex stack(mInfoMtx); /****** LOCKED MUTEX *******/ - updateSet = mPeersToUpdate; - mPeersToUpdate.clear(); - } - - mServiceControl->getServiceChanges(updateSet); - - RsStackMutex stack(mInfoMtx); /****** LOCKED MUTEX *******/ - std::set::iterator it; - for(it = updateSet.begin(); it != updateSet.end(); ++it) - { - sendServiceInfoList(*it); - } - - return (!updateSet.empty()); -} - - -int p3ServiceInfo::sendServiceInfoList(const RsPeerId &peerId) -{ -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::sendServiceInfoList() to " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - RsServiceInfoListItem *item = new RsServiceInfoListItem(); - - RsPeerServiceInfo info; - bool sent = false; - if (mServiceControl->getServicesAllowed(peerId, info)) - { -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::sendServiceInfoList() Info: "; - std::cerr << std::endl; - std::cerr << info; - std::cerr << std::endl; -#endif - - if (convertServiceInfoToItem(info, item)) - { - item->PeerId(peerId); - - sent = true; - sendItem(item); - } - } - - if (!sent) - { - delete item; - } - - return sent; -} - -void p3ServiceInfo::statusChange(const std::list &plist) -{ -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::statusChange()"; - std::cerr << std::endl; -#endif - - std::list::const_iterator it; - for (it = plist.begin(); it != plist.end(); ++it) - { - if (it->state & RS_PEER_S_FRIEND) - { - if (it->actions & RS_PEER_CONNECTED) - { -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::statusChange()"; - std::cerr << "Peer: " << it->id; - std::cerr << " Connected"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mInfoMtx); /****** LOCKED MUTEX *******/ - mPeersToUpdate.insert(it->id); - } - } - } -} - - - diff --git a/libretroshare/src/services/p3serviceinfo.h b/libretroshare/src/services/p3serviceinfo.h deleted file mode 100644 index 2d8f8a8af..000000000 --- a/libretroshare/src/services/p3serviceinfo.h +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3serviceinfo.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef SERVICE_RSSERVICEINFO_HEADER -#define SERVICE_RSSERVICEINFO_HEADER - -#include -#include -#include - -#include "pqi/p3servicecontrol.h" -#include "pqi/pqimonitor.h" - -#include "services/p3service.h" - -#include "rsitems/rsserviceinfoitems.h" - -//!The ServiceInfo service. - /** - * - * Exchange list of Available Services with peers. - */ - -class p3ServiceInfo: public p3Service, public pqiMonitor -{ - public: - p3ServiceInfo(p3ServiceControl *serviceControl); - virtual RsServiceInfo getServiceInfo(); - - virtual int tick(); - virtual int status(); - - /*************** pqiMonitor callback ***********************/ - virtual void statusChange(const std::list &plist); - - private: - - bool sendPackets(); - bool processIncoming(); - - bool recvServiceInfoList(RsServiceInfoListItem *item); - int sendServiceInfoList(const RsPeerId &peerid); - - private: - RsMutex mInfoMtx; - - std::set mPeersToUpdate; - p3ServiceControl *mServiceControl; -}; - -#endif // SERVICE_RSSERVICEINFO_HEADER - diff --git a/libretroshare/src/services/p3statusservice.cc b/libretroshare/src/services/p3statusservice.cc deleted file mode 100644 index f3f44cf9b..000000000 --- a/libretroshare/src/services/p3statusservice.cc +++ /dev/null @@ -1,416 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3statusservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Vinny Do, Chris Evi-Parker. * - * * - * 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 . * - * * - *******************************************************************************/ -#include "services/p3statusservice.h" -#include "rsitems/rsstatusitems.h" -#include "rsserver/p3face.h" -#include "retroshare/rsiface.h" - -#include -#include -#include -#include -#include "util/rstime.h" - -#include "pqi/p3linkmgr.h" - -std::ostream& operator<<(std::ostream& out, const StatusInfo& si) -{ - out << "StatusInfo: " << std::endl; - out << "id: " << si.id << std::endl; - out << "status: " << si.status << std::endl; - out << "time_stamp: " << si.time_stamp << std::endl; - return out; -} - -RsStatus *rsStatus = NULL; - -p3StatusService::p3StatusService(p3ServiceControl *sc) - :p3Service(), p3Config(), mServiceCtrl(sc), mStatusMtx("p3StatusService") -{ - addSerialType(new RsStatusSerialiser()); - -} - -p3StatusService::~p3StatusService() -{ -} - - -const std::string STATUS_APP_NAME = "status"; -const uint16_t STATUS_APP_MAJOR_VERSION = 1; -const uint16_t STATUS_APP_MINOR_VERSION = 0; -const uint16_t STATUS_MIN_MAJOR_VERSION = 1; -const uint16_t STATUS_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3StatusService::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_STATUS, - STATUS_APP_NAME, - STATUS_APP_MAJOR_VERSION, - STATUS_APP_MINOR_VERSION, - STATUS_MIN_MAJOR_VERSION, - STATUS_MIN_MINOR_VERSION); -} - - -bool p3StatusService::getOwnStatus(StatusInfo& statusInfo) -{ -#ifdef STATUS_DEBUG - std::cerr << "p3StatusService::getOwnStatus() " << std::endl; -#endif - - std::map::iterator it; - const RsPeerId& ownId = mServiceCtrl->getOwnId(); - - RsStackMutex stack(mStatusMtx); - it = mStatusInfoMap.find(ownId); - - if (it == mStatusInfoMap.end()){ - std::cerr << "p3StatusService::saveList() :" << "Did not find your status" << ownId << std::endl; - - // own status not set, set it to online - statusInfo.id = ownId; - statusInfo.status = RS_STATUS_ONLINE; - - std::pair pr(ownId, statusInfo); - mStatusInfoMap.insert(pr); - IndicateConfigChanged(); - - return true; - } - - statusInfo = it->second; - - return true; -} - -bool p3StatusService::getStatusList(std::list& statusInfo) -{ -#ifdef STATUS_DEBUG - std::cerr << "p3StatusService::getStatusList() " << std::endl; -#endif - - statusInfo.clear(); - - RsStackMutex stack(mStatusMtx); - - // fill up statusInfo list with this information - std::map::iterator mit; - for(mit = mStatusInfoMap.begin(); mit != mStatusInfoMap.end(); ++mit){ - statusInfo.push_back(mit->second); - } - - return true; -} - -bool p3StatusService::getStatus(const RsPeerId &id, StatusInfo &statusInfo) -{ -#ifdef STATUS_DEBUG - std::cerr << "p3StatusService::getStatus() " << std::endl; -#endif - - RsStackMutex stack(mStatusMtx); - - std::map::iterator mit = mStatusInfoMap.find(id); - - if (mit == mStatusInfoMap.end()) { - /* return fake status info as offline */ - statusInfo = StatusInfo(); - - statusInfo.id = id; - statusInfo.status = RS_STATUS_OFFLINE; - return false; - } - - statusInfo = mit->second; - - return true; -} - -/* id = "", status is sent to all online peers */ -bool p3StatusService::sendStatus(const RsPeerId &id, uint32_t status) -{ - StatusInfo statusInfo; - std::set onlineList; - - { - RsStackMutex stack(mStatusMtx); - - statusInfo.id = mServiceCtrl->getOwnId(); - statusInfo.status = status; - - // don't save inactive status - if(statusInfo.status != RS_STATUS_INACTIVE){ - - // If your id is not set, set it - if(mStatusInfoMap.find(statusInfo.id) == mStatusInfoMap.end()){ - - std::pair pr(statusInfo.id, statusInfo); - mStatusInfoMap.insert(pr); - IndicateConfigChanged(); - } else if(mStatusInfoMap[statusInfo.id].status != statusInfo.status){ - - IndicateConfigChanged(); - mStatusInfoMap[statusInfo.id] = statusInfo; - } - } - - if (id.isNull()) { - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, onlineList); - } else { - onlineList.insert(id); - } - } - - std::set::iterator it; - -#ifdef STATUS_DEBUG - std::cerr << "p3StatusService::sendStatus() " << std::endl; - std::cerr << statusInfo; -#endif - - // send to all peers online - for(it = onlineList.begin(); it != onlineList.end(); ++it){ - RsStatusItem* statusItem = new RsStatusItem(); - statusItem->sendTime = time(NULL); - statusItem->status = statusInfo.status; - statusItem->PeerId(*it); - sendItem(statusItem); - } - - /* send notify of own status change */ - RsServer::notify()->notifyPeerStatusChanged(statusInfo.id.toStdString(), statusInfo.status); - - return true; -} - -/******************************/ - -void p3StatusService::receiveStatusQueue() -{ - std::map changed; - - { - RsStackMutex stack(mStatusMtx); - - RsItem* item; - - while(NULL != (item = recvItem())){ - - RsStatusItem* status_item = dynamic_cast(item); - - if(status_item == NULL) { - std::cerr << "p3Status::getStatusQueue() " << "Failed to cast Item \n" << std::endl; - delete (item); - continue; - } - -#ifdef STATUS_DEBUG - std::cerr << "p3StatusService::getStatusQueue()" << std::endl; - std::cerr << "PeerId : " << status_item->PeerId() << std::endl; - std::cerr << "Status: " << status_item->status << std::endl; - std::cerr << "Got status Item" << std::endl; -#endif - - std::map::iterator mit = mStatusInfoMap.find(status_item->PeerId()); - - if(mit != mStatusInfoMap.end()){ - mit->second.id = status_item->PeerId(); - - if (mit->second.status != status_item->status) { - changed [mit->second.id] = status_item->status; - } - - mit->second.status = status_item->status; - mit->second.time_stamp = status_item->sendTime; -#ifdef STATUS_DEBUG - } else { - std::cerr << "getStatus() " << "Could not find Peer" << status_item->PeerId(); - std::cerr << std::endl; -#endif - } - - delete (status_item); - } - - } /* UNLOCKED */ - - if (changed.size()) { - std::map::iterator it; - for (it = changed.begin(); it != changed.end(); ++it) { - RsServer::notify()->notifyPeerStatusChanged(it->first.toStdString(), it->second); - } - RsServer::notify()->notifyPeerStatusChangedSummary(); - } -} - -/* p3Config */ - -RsSerialiser* p3StatusService::setupSerialiser(){ - - RsSerialiser *rss = new RsSerialiser; - rss->addSerialType(new RsStatusSerialiser); - - return rss; -} - -bool p3StatusService::saveList(bool& cleanup, std::list& ilist){ - - // save your status before quiting - cleanup = true; - RsStatusItem* own_status = new RsStatusItem; - StatusInfo own_info; - - std::map::iterator it; - - { - RsStackMutex stack(mStatusMtx); - it = mStatusInfoMap.find(mServiceCtrl->getOwnId()); - - if(it == mStatusInfoMap.end()){ - std::cerr << "p3StatusService::saveList() :" << "Did not find your status" - << mServiceCtrl->getOwnId() << std::endl; - delete own_status; - return false; - } - - own_info = it->second; - } - - own_status->PeerId(own_info.id); - own_status->sendTime = own_info.time_stamp; - own_status->status = own_info.status; - - ilist.push_back(own_status); - - return true; -} - -bool p3StatusService::loadList(std::list& load) -{ - // load your status from last rs session - StatusInfo own_info; - - - for(std::list::const_iterator it = load.begin() ; it != load.end(); ++it) - { - RsStatusItem* own_status = dynamic_cast(*it); - - if(own_status != NULL) - { - own_info.id = mServiceCtrl->getOwnId(); - own_info.status = own_status->status; - own_info.time_stamp = own_status->sendTime; - - { - RsStackMutex stack(mStatusMtx); - std::pair pr(mServiceCtrl->getOwnId(), own_info); - mStatusInfoMap.insert(pr); - } - - } - - delete *it ; - } - load.clear() ; - return false; -} - - -int p3StatusService::tick() -{ - if (receivedItems()) { - receiveStatusQueue(); - } - - return 0; -} - -int p3StatusService::status(){ - return 1; -} - -/*************** pqiMonitor callback ***********************/ - -void p3StatusService::statusChange(const std::list &plist) -{ - bool changedState = false; - - StatusInfo statusInfo; - std::list::const_iterator it; - for (it = plist.begin(); it != plist.end(); ++it) - { - if (it->actions & RS_SERVICE_PEER_DISCONNECTED) - { - { - RsStackMutex stack(mStatusMtx); - /* remove peer from status map */ - mStatusInfoMap.erase(it->id); - } /* UNLOCKED */ - - changedState = true; - RsServer::notify()->notifyPeerStatusChanged(it->id.toStdString(), RS_STATUS_OFFLINE); - } - - if (it->actions & RS_SERVICE_PEER_CONNECTED) - { - /* send current status, only call getOwnStatus once in the loop */ - if (statusInfo.id.isNull() == false || getOwnStatus(statusInfo)) - { - sendStatus(it->id, statusInfo.status); - } - - { - RsStackMutex stack(mStatusMtx); - - /* We assume that the peer is online. If not, he send us a new status */ - StatusInfo info; - info.id = it->id; - info.status = RS_STATUS_ONLINE; - info.time_stamp = time(NULL); - - mStatusInfoMap[it->id] = info; - } /* UNLOCKED */ - - changedState = true; - RsServer::notify()->notifyPeerStatusChanged(it->id.toStdString(), RS_STATUS_ONLINE); - } - - if (it->actions & RS_SERVICE_PEER_REMOVED) - { - /* now handle remove */ - { - RsStackMutex stack(mStatusMtx); - /* remove peer from status map */ - mStatusInfoMap.erase(it->id); - } /* UNLOCKED */ - - changedState = true; - RsServer::notify()->notifyPeerStatusChanged(it->id.toStdString(), RS_STATUS_OFFLINE); - } - } - - if (changedState) - { - RsServer::notify()->notifyPeerStatusChangedSummary(); - } -} diff --git a/libretroshare/src/services/p3statusservice.h b/libretroshare/src/services/p3statusservice.h deleted file mode 100644 index ac0b70653..000000000 --- a/libretroshare/src/services/p3statusservice.h +++ /dev/null @@ -1,102 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3statusservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Vinny Do, Chris Evi-Parker. * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_P3_STATUS_INTERFACE_H -#define RS_P3_STATUS_INTERFACE_H - -#include -#include - -#include "rsitems/rsstatusitems.h" -#include "retroshare/rsstatus.h" -#include "services/p3service.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/pqiservicemonitor.h" - -class p3ServiceControl; - -//! handles standard status messages (busy, away, online, offline) set by user -/*! - * The is a retroshare service which allows peers - * to inform each other about their status in a standard way, as opposed to - * custom string. - * @see rsiface/rsstatus.h for status constants - */ -class p3StatusService: public p3Service, public p3Config, public pqiServiceMonitor -{ - public: - - p3StatusService(p3ServiceControl *sc); -virtual ~p3StatusService(); - -virtual RsServiceInfo getServiceInfo(); - -/***** overloaded from p3Service *****/ -virtual int tick(); -virtual int status(); - -/*************** pqiMonitor callback ***********************/ -virtual void statusChange(const std::list &plist); - -/********* RsStatus ***********/ - -/** - * Status is set to offline as default if no info received from relevant peer - */ -virtual bool getOwnStatus(StatusInfo& statusInfo); -virtual bool getStatusList(std::list& statusInfo); -virtual bool getStatus(const RsPeerId &id, StatusInfo &statusInfo); -/* id = "", status is sent to all online peers */ -virtual bool sendStatus(const RsPeerId &id, uint32_t status); - -/******************************/ - - -/** implemented from p3Config **/ - -/*! - * @return The serialiser the enables storage of save info - */ -virtual RsSerialiser *setupSerialiser(); - -/*! - * This stores information on what your status was before you exited rs - */ -virtual bool saveList(bool& cleanup, std::list&); - -/*! - * @param load Should contain a single item which is clients status from last rs session - */ -virtual bool loadList(std::list& load); - - private: - -virtual void receiveStatusQueue(); - -p3ServiceControl *mServiceCtrl; - -std::map mStatusInfoMap; - -RsMutex mStatusMtx; - -}; - -#endif diff --git a/libretroshare/src/services/p3wiki.cc b/libretroshare/src/services/p3wiki.cc deleted file mode 100644 index c1b8f86e1..000000000 --- a/libretroshare/src/services/p3wiki.cc +++ /dev/null @@ -1,798 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3wiki.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "services/p3wiki.h" -#include "retroshare/rsgxsflags.h" -#include "rsitems/rswikiitems.h" - -#include "util/rsrandom.h" - -/**** - * #define WIKI_DEBUG 1 - ****/ - -RsWiki *rsWiki = NULL; - - -#define WIKI_EVENT_DUMMYTICK 0x0001 -#define WIKI_EVENT_DUMMYSTART 0x0002 - -#define DUMMYSTART_PERIOD 60 // some time for dummyIds to be generated. -#define DUMMYTICK_PERIOD 3 - -p3Wiki::p3Wiki(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs *gixs) - :RsGenExchange(gds, nes, new RsGxsWikiSerialiser(), RS_SERVICE_GXS_TYPE_WIKI, gixs, wikiAuthenPolicy()), - RsWiki(static_cast(*this)) -{ - // Setup of dummy Pages. - mAboutActive = false; - mImprovActive = false; - mMarkdownActive = false; - - // TestData disabled in Repo. - //RsTickEvent::schedule_in(WIKI_EVENT_DUMMYSTART, DUMMYSTART_PERIOD); - -} - - -const std::string GXS_WIKI_APP_NAME = "gxswiki"; -const uint16_t GXS_WIKI_APP_MAJOR_VERSION = 1; -const uint16_t GXS_WIKI_APP_MINOR_VERSION = 0; -const uint16_t GXS_WIKI_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_WIKI_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3Wiki::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_WIKI, - GXS_WIKI_APP_NAME, - GXS_WIKI_APP_MAJOR_VERSION, - GXS_WIKI_APP_MINOR_VERSION, - GXS_WIKI_MIN_MAJOR_VERSION, - GXS_WIKI_MIN_MINOR_VERSION); -} - - -uint32_t p3Wiki::wikiAuthenPolicy() -{ - uint32_t policy = 0; - uint8_t flag = 0; - - // Edits generally need an authors signature. - - flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - flag |= GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - - -void p3Wiki::service_tick() -{ - RsTickEvent::tick_events(); - return; -} - - -void p3Wiki::notifyChanges(std::vector& changes) -{ - std::cerr << "p3Wiki::notifyChanges() New stuff"; - std::cerr << std::endl; -} - - /* Specific Service Data */ -bool p3Wiki::getCollections(const uint32_t &token, std::vector &collections) -{ - std::cerr << "p3Wiki::getCollections()"; - std::cerr << std::endl; - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsWikiCollectionItem* item = dynamic_cast(*vit); - - if (item) - { - RsWikiCollection collection = item->collection; - collection.mMeta = item->meta; - delete item; - collections.push_back(collection); - - std::cerr << "p3Wiki::getCollections() Adding Collection to Vector: "; - std::cerr << std::endl; - std::cerr << collection; - std::cerr << std::endl; - } - else - { - std::cerr << "Not a WikiCollectionItem, deleting!" << std::endl; - delete *vit; - } - - } - } - return ok; -} - - -bool p3Wiki::getSnapshots(const uint32_t &token, std::vector &snapshots) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - RsGxsGroupId grpId = mit->first; - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsWikiSnapshotItem* item = dynamic_cast(*vit); - - if(item) - { - RsWikiSnapshot snapshot = item->snapshot; - snapshot.mMeta = item->meta; - snapshots.push_back(snapshot); - delete item; - } - else - { - std::cerr << "Not a WikiSnapshot Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -} - - -bool p3Wiki::getRelatedSnapshots(const uint32_t &token, std::vector &snapshots) -{ - GxsMsgRelatedDataMap msgData; - bool ok = RsGenExchange::getMsgRelatedData(token, msgData); - - if(ok) - { - GxsMsgRelatedDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsWikiSnapshotItem* item = dynamic_cast(*vit); - - if(item) - { - RsWikiSnapshot snapshot = item->snapshot; - snapshot.mMeta = item->meta; - snapshots.push_back(snapshot); - delete item; - } - else - { - std::cerr << "Not a WikiSnapshot Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -} - - -bool p3Wiki::getComments(const uint32_t &token, std::vector &comments) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - RsGxsGroupId grpId = mit->first; - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); vit++) - { - RsGxsWikiCommentItem* item = dynamic_cast(*vit); - - if(item) - { - RsWikiComment comment = item->comment; - comment.mMeta = item->meta; - comments.push_back(comment); - delete item; - } - else - { - std::cerr << "Not a WikiComment Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; - return false; -} - - - -bool p3Wiki::submitCollection(uint32_t &token, RsWikiCollection &collection) -{ - RsGxsWikiCollectionItem* collectionItem = new RsGxsWikiCollectionItem(); - collectionItem->collection = collection; - collectionItem->meta = collection.mMeta; - - std::cerr << "p3Wiki::submitCollection(): "; - std::cerr << std::endl; - std::cerr << collection; - std::cerr << std::endl; - - std::cerr << "p3Wiki::submitCollection() pushing to RsGenExchange"; - std::cerr << std::endl; - - RsGenExchange::publishGroup(token, collectionItem); - return true; -} - - -bool p3Wiki::submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot) -{ - std::cerr << "p3Wiki::submitSnapshot(): " << snapshot; - std::cerr << std::endl; - - RsGxsWikiSnapshotItem* snapshotItem = new RsGxsWikiSnapshotItem(); - snapshotItem->snapshot = snapshot; - snapshotItem->meta = snapshot.mMeta; - snapshotItem->meta.mMsgFlags = FLAG_MSG_TYPE_WIKI_SNAPSHOT; - - RsGenExchange::publishMsg(token, snapshotItem); - return true; -} - - -bool p3Wiki::submitComment(uint32_t &token, RsWikiComment &comment) -{ - std::cerr << "p3Wiki::submitComment(): " << comment; - std::cerr << std::endl; - - RsGxsWikiCommentItem* commentItem = new RsGxsWikiCommentItem(); - commentItem->comment = comment; - commentItem->meta = comment.mMeta; - commentItem->meta.mMsgFlags = FLAG_MSG_TYPE_WIKI_COMMENT; - - RsGenExchange::publishMsg(token, commentItem); - return true; -} - -bool p3Wiki::updateCollection(uint32_t &token, RsWikiCollection &group) -{ - std::cerr << "p3Wiki::updateCollection()" << std::endl; - - RsGxsWikiCollectionItem* grpItem = new RsGxsWikiCollectionItem(); - grpItem->collection = group; - grpItem->meta = group.mMeta; - - RsGenExchange::updateGroup(token, grpItem); - return true; -} - -// Blocking Interfaces. -bool p3Wiki::createCollection(RsWikiCollection &group) -{ - uint32_t token; - return submitCollection(token, group) && waitToken(token) == RsTokenService::COMPLETE; -} - -bool p3Wiki::updateCollection(const RsWikiCollection &group) -{ - uint32_t token; - RsWikiCollection update(group); - return updateCollection(token, update) && waitToken(token) == RsTokenService::COMPLETE; -} - -bool p3Wiki::getCollections(const std::list groupIds, std::vector &groups) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if (groupIds.empty()) - { - if (!requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - else - { - if (!requestGroupInfo(token, opts, groupIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - return getCollections(token, groups) && !groups.empty(); -} - -std::ostream &operator<<(std::ostream &out, const RsWikiCollection &group) -{ - out << "RsWikiCollection [ "; - out << " Name: " << group.mMeta.mGroupName; - out << " Desc: " << group.mDescription; - out << " Category: " << group.mCategory; - out << " ]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsWikiSnapshot &shot) -{ - out << "RsWikiSnapshot [ "; - out << "Title: " << shot.mMeta.mMsgName; - out << "]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsWikiComment &comment) -{ - out << "RsWikiComment [ "; - out << "Title: " << comment.mMeta.mMsgName; - out << "]"; - return out; -} - - -/***** FOR TESTING *****/ - -const int about_len = 10; -const std::string about_txt[] = - { "Welcome to RsWiki, a fully distributed Wiki system that anyone can edit.", - "Please read through these dummy Wiki pages to learn how it should work\n", - "Basic Functionality:", - " - New Group: creates a collection of Wiki Pages, the creator of group", - " and anyone they share the publish keys with) is the moderator\n", - " - New Page: Create a new Wiki Page, only Group Moderators can do this\n", - " - Edit: Anyone Can Edit the Wiki Page, and the changes form a tree under the original\n", - " - RePublish: This is used by the Moderators to accept and reject Edits.", - " the republished page becomes a new version of the Root Page, allowing more edits to be done\n", - "Please read the improvements section to see how we envision the wiki's working", - }; - - -const int improvements_len = 14; -const std::string improvements_txt[] = - { "As you can see, the current Wiki is a basic framework waiting to be expanded.", - "There are lots of potential improvements... some of my ideas are listed below\n", - "Ideas:", - " - Formatting: No HTML, lets use Markdown or something similar.\n", - " - Diffs, lots of edits will lead to complex merges - a robust merge tool is essential\n", - " - Read Mode... hide all the Edits, and only show the most recently published versions\n", - " - Easy Duplication - to take over an Abandoned or badly moderated Wiki. Copies All base versions to a new group\n", - " - WikiLinks. A generic Wiki Cross Linking system. This should be combined with Easy Duplication option,", - " to allow easy replacement of groups if necessary... A good design here is critical to a successful Wiki ecosystem\n", - " - work out how to include media (photos, audio, video, etc) without embedding in pages", - " this would leverage the turtle transfer system somehow - maybe like channels.\n", - " - Comments, reviews etc can be incorporated - ideas here are welcome.\n", - " - Any other suggestion???", - " - Come on more ideas!" - }; - - -const int markdown_len = 34; -const std::string markdown_txt[] = { - "# An Example of Markdown Editing.", - "", - "Markdown is quite simple to use, and allows simple HTML.", - "", - "## Some Blocks below an H2 heading.", - "", - " * Firstly, we can put a link [in here][]", - " * Secondly, as you can see we're in a list.", - " * Thirdly, I don't know.", - "", - "### A Sub (H3) heading.", - "", - "#### If we want to get into the very small details. (H6).", - "", - " A bit of code.", - " This is a lit", - " foreach(in loop)", - " a++", - " Double quoted stuff.", - "", - "Or it can be indented like this:", - "", - "> A block of indented stuff looks like this", - "> > With double indenting and ", - "> > > triple indenting possible too", - "", - "Images can be embedded, but thats somethinng to work on in the future.", - "", - "Sadly it doesn't support tables or div's or anything that complex.", - "", - "Keep it simple and help write good wiki pages, thx.", - "", - "[in here]: http://example.com/ \"Optional Title Here\"", - "" - }; - - -void p3Wiki::generateDummyData() -{ - std::cerr << "p3Wiki::generateDummyData()"; - std::cerr << std::endl; - -#define GEN_COLLECTIONS 0 - - int i; - for(i = 0; i < GEN_COLLECTIONS; i++) - { - RsWikiCollection wiki; - wiki.mMeta.mGroupId = RsGxsGroupId::random(); - wiki.mMeta.mGroupFlags = 0; - wiki.mMeta.mGroupName = RsGxsGroupId::random().toStdString(); - - uint32_t dummyToken = 0; - submitCollection(dummyToken, wiki); - } - - - RsWikiCollection wiki; - wiki.mMeta.mGroupFlags = 0; - wiki.mMeta.mGroupName = "About RsWiki"; - - submitCollection(mAboutToken, wiki); - - wiki.mMeta.mGroupFlags = 0; - wiki.mMeta.mGroupName = "RsWiki Improvements"; - - submitCollection(mImprovToken, wiki); - - wiki.mMeta.mGroupFlags = 0; - wiki.mMeta.mGroupName = "RsWiki Markdown"; - - submitCollection(mMarkdownToken, wiki); - - mAboutLines = 0; - mImprovLines = 0; - mMarkdownLines = 0; - - mAboutActive = true; - mImprovActive = true; - mMarkdownActive = true; - - RsTickEvent::schedule_in(WIKI_EVENT_DUMMYTICK, DUMMYTICK_PERIOD); -} - - -bool generateNextDummyPage(const RsGxsMessageId &threadId, const int lines, const RsGxsGrpMsgIdPair &parentId, - const std::string *page_lines, const int num_pagelines, RsWikiSnapshot &snapshot) -{ - snapshot.mMeta.mGroupId = parentId.first; - - // Create an About Page. -#define NUM_SUB_PAGES 3 - - if ((lines % NUM_SUB_PAGES == 0) || (lines == num_pagelines)) - { - /* do a new baseline */ - snapshot.mMeta.mOrigMsgId = threadId; - } - else - { - snapshot.mMeta.mParentId = parentId.second; - snapshot.mMeta.mThreadId = threadId; - } - - std::string page; - for(int i = 0; (i < lines) && (i < num_pagelines); i++) - { - snapshot.mPage += page_lines[i]; - snapshot.mPage += '\n'; - } - - return (lines <= num_pagelines); -} - - -#include - -RsGxsId chooseRandomAuthorId() -{ - /* chose a random Id to sign with */ - std::list ownIds; - std::list::iterator it; - - rsIdentity->getOwnIds(ownIds); - - uint32_t idx = (uint32_t) (RSRandom::random_u32() % (int)ownIds.size()) ; - int i = 0; - for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); ++it, i++) ; - - return *it ; -} - - - -void p3Wiki::dummyTick() -{ - if (mAboutActive) - { - std::cerr << "p3Wiki::dummyTick() AboutActive"; - std::cerr << std::endl; - - uint32_t status = RsGenExchange::getTokenService()->requestStatus(mAboutToken); - - if (status == RsTokenService::COMPLETE) - { - std::cerr << "p3Wiki::dummyTick() AboutActive, Lines: " << mAboutLines; - std::cerr << std::endl; - - if (mAboutLines == 0) - { - /* get the group Id */ - RsGxsGroupId groupId; - if (!acknowledgeTokenGrp(mAboutToken, groupId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mAboutActive = false; - } - - /* create baseline snapshot */ - RsWikiSnapshot page; - page.mMeta.mGroupId = groupId; - page.mPage = "Baseline page... a placeholder for About Wiki"; - page.mMeta.mMsgName = "About RsWiki"; - page.mMeta.mAuthorId = chooseRandomAuthorId(); - - submitSnapshot(mAboutToken, page); - mAboutLines++; - } - else - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeTokenMsg(mAboutToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mAboutActive = false; - } - - if (mAboutLines == 1) - { - mAboutThreadId = msgId.second; - } - - RsWikiSnapshot page; - page.mMeta.mMsgName = "About RsWiki"; - page.mMeta.mAuthorId = chooseRandomAuthorId(); - if (!generateNextDummyPage(mAboutThreadId, mAboutLines, msgId, about_txt, about_len, page)) - { - std::cerr << "About Pages Done"; - std::cerr << std::endl; - mAboutActive = false; - } - else - { - mAboutLines++; - submitSnapshot(mAboutToken, page); - } - } - } - } - - if (mImprovActive) - { - std::cerr << "p3Wiki::dummyTick() ImprovActive"; - std::cerr << std::endl; - - uint32_t status = RsGenExchange::getTokenService()->requestStatus(mImprovToken); - - if (status == RsTokenService::COMPLETE) - { - std::cerr << "p3Wiki::dummyTick() ImprovActive, Lines: " << mImprovLines; - std::cerr << std::endl; - - if (mImprovLines == 0) - { - /* get the group Id */ - RsGxsGroupId groupId; - if (!acknowledgeTokenGrp(mImprovToken, groupId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mImprovActive = false; - } - - /* create baseline snapshot */ - RsWikiSnapshot page; - page.mMeta.mGroupId = groupId; - page.mPage = "Baseline page... a placeholder for Improv Wiki"; - page.mMeta.mMsgName = "Improv RsWiki"; - page.mMeta.mAuthorId = chooseRandomAuthorId(); - - submitSnapshot(mImprovToken, page); - mImprovLines++; - } - else - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeTokenMsg(mImprovToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mImprovActive = false; - } - - if (mImprovLines == 1) - { - mImprovThreadId = msgId.second; - } - - RsWikiSnapshot page; - page.mMeta.mMsgName = "Improv RsWiki"; - page.mMeta.mAuthorId = chooseRandomAuthorId(); - if (!generateNextDummyPage(mImprovThreadId, mImprovLines, msgId, improvements_txt, improvements_len, page)) - { - std::cerr << "Improv Pages Done"; - std::cerr << std::endl; - mImprovActive = false; - } - else - { - mImprovLines++; - submitSnapshot(mImprovToken, page); - } - } - } - } - - - if (mMarkdownActive) - { - std::cerr << "p3Wiki::dummyTick() MarkdownActive"; - std::cerr << std::endl; - - uint32_t status = RsGenExchange::getTokenService()->requestStatus(mMarkdownToken); - - if (status == RsTokenService::COMPLETE) - { - std::cerr << "p3Wiki::dummyTick() MarkdownActive, Lines: " << mMarkdownLines; - std::cerr << std::endl; - - if (mMarkdownLines == 0) - { - /* get the group Id */ - RsGxsGroupId groupId; - if (!acknowledgeTokenGrp(mMarkdownToken, groupId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mMarkdownActive = false; - } - - /* create baseline snapshot */ - RsWikiSnapshot page; - page.mMeta.mGroupId = groupId; - page.mPage = "Baseline page... a placeholder for Markdown Wiki"; - page.mMeta.mMsgName = "Markdown RsWiki"; - page.mMeta.mAuthorId = chooseRandomAuthorId(); - - submitSnapshot(mMarkdownToken, page); - mMarkdownLines++; - } - else - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeTokenMsg(mMarkdownToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mMarkdownActive = false; - } - - if (mMarkdownLines == 1) - { - mMarkdownThreadId = msgId.second; - } - - RsWikiSnapshot page; - page.mMeta.mMsgName = "Markdown RsWiki"; - page.mMeta.mAuthorId = chooseRandomAuthorId(); - if (!generateNextDummyPage(mMarkdownThreadId, mMarkdownLines, msgId, markdown_txt, markdown_len, page)) - { - std::cerr << "Markdown Pages Done"; - std::cerr << std::endl; - mMarkdownActive = false; - } - else - { - mMarkdownLines++; - submitSnapshot(mMarkdownToken, page); - } - } - } - } - - if ((mAboutActive) || (mImprovActive) || (mMarkdownActive)) - { - /* reschedule next one */ - RsTickEvent::schedule_in(WIKI_EVENT_DUMMYTICK, DUMMYTICK_PERIOD); - } -} - - - - - - // Overloaded from RsTickEvent for Event callbacks. -void p3Wiki::handle_event(uint32_t event_type, const std::string &elabel) -{ - std::cerr << "p3Wiki::handle_event(" << event_type << ")"; - std::cerr << std::endl; - - // stuff. - switch(event_type) - { - case WIKI_EVENT_DUMMYSTART: - generateDummyData(); - break; - - case WIKI_EVENT_DUMMYTICK: - dummyTick(); - break; - - default: - /* error */ - std::cerr << "p3Wiki::handle_event() Unknown Event Type: " << event_type; - std::cerr << std::endl; - break; - } -} - - diff --git a/libretroshare/src/services/p3wiki.h b/libretroshare/src/services/p3wiki.h deleted file mode 100644 index a92aec795..000000000 --- a/libretroshare/src/services/p3wiki.h +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3wiki.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef P3_WIKI_SERVICE_HEADER -#define P3_WIKI_SERVICE_HEADER - -#include "retroshare/rswiki.h" -#include "gxs/rsgenexchange.h" - -#include "util/rstickevent.h" - -#include -#include - -/* - * Wiki Service - * - * - */ - -class p3Wiki: public RsGenExchange, public RsWiki, - public RsTickEvent -{ -public: - p3Wiki(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs *gixs); -virtual RsServiceInfo getServiceInfo(); -static uint32_t wikiAuthenPolicy(); - -protected: - -virtual void notifyChanges(std::vector& changes) ; - - // Overloaded from RsTickEvent. -virtual void handle_event(uint32_t event_type, const std::string &elabel); - -public: - -virtual void service_tick(); - - /* Specific Service Data */ -virtual bool getCollections(const uint32_t &token, std::vector &collections) override; -virtual bool getSnapshots(const uint32_t &token, std::vector &snapshots) override; -virtual bool getComments(const uint32_t &token, std::vector &comments) override; - -virtual bool getRelatedSnapshots(const uint32_t &token, std::vector &snapshots) override; - -virtual bool submitCollection(uint32_t &token, RsWikiCollection &collection) override; -virtual bool submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot) override; -virtual bool submitComment(uint32_t &token, RsWikiComment &comment) override; - -virtual bool updateCollection(uint32_t &token, RsWikiCollection &collection) override; - -// Blocking Interfaces. -virtual bool createCollection(RsWikiCollection &collection) override; -virtual bool updateCollection(const RsWikiCollection &collection) override; -virtual bool getCollections(const std::list groupIds, std::vector &groups) override; - - private: - -std::string genRandomId(); -// RsMutex mWikiMtx; - - -virtual void generateDummyData(); - - // Dummy Stuff. - void dummyTick(); - - bool mAboutActive; - uint32_t mAboutToken; - int mAboutLines; - RsGxsMessageId mAboutThreadId; - - bool mImprovActive; - uint32_t mImprovToken; - int mImprovLines; - RsGxsMessageId mImprovThreadId; - - bool mMarkdownActive; - uint32_t mMarkdownToken; - int mMarkdownLines; - RsGxsMessageId mMarkdownThreadId; -}; - -#endif diff --git a/libretroshare/src/services/p3wire.cc b/libretroshare/src/services/p3wire.cc deleted file mode 100644 index 283e9a804..000000000 --- a/libretroshare/src/services/p3wire.cc +++ /dev/null @@ -1,1351 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3wire.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2020 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "services/p3wire.h" -#include "rsitems/rswireitems.h" - -#include "util/rsrandom.h" - -/**** - * #define WIRE_DEBUG 1 - ****/ - -RsWire *rsWire = NULL; - -RsWireGroup::RsWireGroup() - :mGroupPulses(0),mGroupRepublishes(0),mGroupLikes(0),mGroupReplies(0) - ,mRefMentions(0),mRefRepublishes(0),mRefLikes(0),mRefReplies(0) -{ - return; -} - -uint32_t RsWirePulse::ImageCount() -{ - uint32_t images = 0; - if (!mImage1.empty()) { - images++; - } - if (!mImage2.empty()) { - images++; - } - if (!mImage3.empty()) { - images++; - } - if (!mImage4.empty()) { - images++; - } - return images; -} - -p3Wire::p3Wire(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs *gixs) - :RsGenExchange(gds, nes, new RsGxsWireSerialiser(), RS_SERVICE_GXS_TYPE_WIRE, gixs, wireAuthenPolicy()), - RsWire(static_cast(*this)), mWireMtx("WireMtx") -{ - -} - - -const std::string WIRE_APP_NAME = "gxswire"; -const uint16_t WIRE_APP_MAJOR_VERSION = 1; -const uint16_t WIRE_APP_MINOR_VERSION = 0; -const uint16_t WIRE_MIN_MAJOR_VERSION = 1; -const uint16_t WIRE_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3Wire::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_WIRE, - WIRE_APP_NAME, - WIRE_APP_MAJOR_VERSION, - WIRE_APP_MINOR_VERSION, - WIRE_MIN_MAJOR_VERSION, - WIRE_MIN_MINOR_VERSION); -} - - - -uint32_t p3Wire::wireAuthenPolicy() -{ - uint32_t policy = 0; - uint8_t flag = 0; - - // Edits generally need an authors signature. - - // Wire requires all TopLevel (Orig/Reply) msgs to be signed with both PUBLISH & AUTHOR. - // Reply References need to be signed by Author. - flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - flag |= GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - // expect the requirements to be the same for RESTRICTED / PRIVATE groups too. - // This needs to be worked through / fully evaluated. - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -void p3Wire::service_tick() -{ - return; -} - -RsTokenService* p3Wire::getTokenService() { - - return RsGenExchange::getTokenService(); -} - -void p3Wire::notifyChanges(std::vector& /*changes*/) -{ - std::cerr << "p3Wire::notifyChanges() New stuff"; - std::cerr << std::endl; -} - - /* Specific Service Data */ -bool p3Wire::getGroupData(const uint32_t &token, std::vector &groups) -{ - std::cerr << "p3Wire::getGroupData()"; - std::cerr << std::endl; - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsWireGroupItem* item = dynamic_cast(*vit); - - if (item) - { - RsWireGroup group = item->group; - group.mMeta = item->meta; - delete item; - groups.push_back(group); - - std::cerr << "p3Wire::getGroupData() Adding WireGroup to Vector: "; - std::cerr << std::endl; - std::cerr << group; - std::cerr << std::endl; - } - else - { - std::cerr << "Not a WireGroupItem, deleting!" << std::endl; - delete *vit; - } - - } - } - return ok; -} - -bool p3Wire::getGroupPtrData(const uint32_t &token, std::map &groups) -{ - std::cerr << "p3Wire::getGroupPtrData()"; - std::cerr << std::endl; - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsWireGroupItem* item = dynamic_cast(*vit); - - if (item) - { - RsWireGroupSPtr pGroup = std::make_shared(item->group); - pGroup->mMeta = item->meta; - delete item; - - groups[pGroup->mMeta.mGroupId] = pGroup; - - std::cerr << "p3Wire::getGroupPtrData() Adding WireGroup to Vector: "; - std::cerr << pGroup->mMeta.mGroupId.toStdString(); - std::cerr << std::endl; - } - else - { - std::cerr << "Not a WireGroupItem, deleting!" << std::endl; - delete *vit; - } - - } - } - return ok; -} - - -bool p3Wire::getPulseData(const uint32_t &token, std::vector &pulses) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsWirePulseItem* item = dynamic_cast(*vit); - - if(item) - { - RsWirePulse pulse = item->pulse; - pulse.mMeta = item->meta; - pulses.push_back(pulse); - delete item; - } - else - { - std::cerr << "Not a WirePulse Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - return ok; -} - -bool p3Wire::getPulsePtrData(const uint32_t &token, std::list &pulses) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsWirePulseItem* item = dynamic_cast(*vit); - - if(item) - { - RsWirePulseSPtr pPulse = std::make_shared(item->pulse); - pPulse->mMeta = item->meta; - pulses.push_back(pPulse); - delete item; - } - else - { - std::cerr << "Not a WirePulse Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - return ok; -} - -bool p3Wire::getRelatedPulseData(const uint32_t &token, std::vector &pulses) -{ - GxsMsgRelatedDataMap msgData; - std::cerr << "p3Wire::getRelatedPulseData()"; - std::cerr << std::endl; - bool ok = RsGenExchange::getMsgRelatedData(token, msgData); - - if (ok) - { - std::cerr << "p3Wire::getRelatedPulseData() is OK"; - std::cerr << std::endl; - GxsMsgRelatedDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsWirePulseItem* item = dynamic_cast(*vit); - - if(item) - { - RsWirePulse pulse = item->pulse; - pulse.mMeta = item->meta; - pulses.push_back(pulse); - delete item; - } - else - { - std::cerr << "Not a WirePulse Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - else - { - std::cerr << "p3Wire::getRelatedPulseData() is NOT OK"; - std::cerr << std::endl; - } - - return ok; -} - - -bool p3Wire::createGroup(uint32_t &token, RsWireGroup &group) -{ - RsGxsWireGroupItem* groupItem = new RsGxsWireGroupItem(); - groupItem->group = group; - groupItem->meta = group.mMeta; - - std::cerr << "p3Wire::createGroup(): "; - std::cerr << std::endl; - std::cerr << group; - std::cerr << std::endl; - - std::cerr << "p3Wire::createGroup() pushing to RsGenExchange"; - std::cerr << std::endl; - - RsGenExchange::publishGroup(token, groupItem); - return true; -} - - -bool p3Wire::createPulse(uint32_t &token, RsWirePulse &pulse) -{ - std::cerr << "p3Wire::createPulse(): " << pulse; - std::cerr << std::endl; - - RsGxsWirePulseItem* pulseItem = new RsGxsWirePulseItem(); - pulseItem->pulse = pulse; - pulseItem->meta = pulse.mMeta; - - RsGenExchange::publishMsg(token, pulseItem); - return true; -} - -// Blocking Interfaces. -bool p3Wire::createGroup(RsWireGroup &group) -{ - uint32_t token; - return createGroup(token, group) && waitToken(token) == RsTokenService::COMPLETE; -} - -bool p3Wire::updateGroup(const RsWireGroup & /*group*/) -{ - // TODO - return false; -} - -bool p3Wire::getGroups(const std::list groupIds, std::vector &groups) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if (groupIds.empty()) - { - if (!requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - { - return false; - } - } - else - { - if (!requestGroupInfo(token, opts, groupIds) || waitToken(token) != RsTokenService::COMPLETE ) - { - return false; - } - } - return getGroupData(token, groups) && !groups.empty(); -} - - -std::ostream &operator<<(std::ostream &out, const RsWireGroup &group) -{ - out << "RsWireGroup [ "; - out << " Name: " << group.mMeta.mGroupName; - out << " Tagline: " << group.mTagline; - out << " Location: " << group.mLocation; - out << " ]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsWirePulse &pulse) -{ - out << "RsWirePulse [ "; - out << "Title: " << pulse.mMeta.mMsgName; - out << "PulseText: " << pulse.mPulseText; - out << "]"; - return out; -} - -/***** FOR TESTING *****/ - -std::string p3Wire::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - -void p3Wire::generateDummyData() -{ - -} - - -// New Interfaces. -bool p3Wire::fetchPulse(RsGxsGroupId grpId, RsGxsMessageId msgId, RsWirePulseSPtr &pPulse) -{ - std::cerr << "p3Wire::fetchPulse(" << grpId << ", " << msgId << ") waiting for token"; - std::cerr << std::endl; - - uint32_t token; - { - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST; - - GxsMsgReq ids; - std::set &set_msgIds = ids[grpId]; - set_msgIds.insert(msgId); - - getTokenService()->requestMsgInfo( - token, RS_TOKREQ_ANSTYPE_DATA, opts, ids); - } - - // wait for pulse request to completed. - std::cerr << "p3Wire::fetchPulse() waiting for token"; - std::cerr << std::endl; - - int result = waitToken(token); - if (result != RsTokenService::COMPLETE) - { - std::cerr << "p3Wire::fetchPulse() token FAILED, result: " << result; - std::cerr << std::endl; - return false; - } - - // retrieve Pulse. - std::cerr << "p3Wire::fetchPulse() retrieving token"; - std::cerr << std::endl; - { - bool okay = true; - std::vector pulses; - if (getPulseData(token, pulses)) { - if (pulses.size() == 1) { - // save to output pulse. - pPulse = std::make_shared(pulses[0]); - std::cerr << "p3Wire::fetchPulse() retrieved token: " << *pPulse; - std::cerr << std::endl; - std::cerr << "p3Wire::fetchPulse() ANS GrpId: " << pPulse->mMeta.mGroupId; - std::cerr << " MsgId: " << pPulse->mMeta.mMsgId; - std::cerr << " OrigMsgId: " << pPulse->mMeta.mOrigMsgId; - std::cerr << std::endl; - } else { - std::cerr << "p3Wire::fetchPulse() ERROR multiple pulses"; - std::cerr << std::endl; - okay = false; - } - } else { - std::cerr << "p3Wire::fetchPulse() ERROR failed to retrieve token"; - std::cerr << std::endl; - okay = false; - } - - if (!okay) { - std::cerr << "p3Wire::fetchPulse() tokenPulse ERROR"; - std::cerr << std::endl; - // TODO cancel other request. - return false; - } - } - return true; -} - -// New Interfaces. -bool p3Wire::createOriginalPulse(const RsGxsGroupId &grpId, RsWirePulseSPtr pPulse) -{ - // request Group. - std::list groupIds = { grpId }; - std::vector groups; - bool groupOkay = getGroups(groupIds, groups); - if (!groupOkay) { - std::cerr << "p3Wire::createOriginalPulse() getGroups failed"; - std::cerr << std::endl; - return false; - } - - if (groups.size() != 1) { - std::cerr << "p3Wire::createOriginalPulse() getGroups invalid size"; - std::cerr << std::endl; - return false; - } - - // ensure Group is suitable. - RsWireGroup group = groups[0]; - if ((group.mMeta.mGroupId != grpId) || - (!(group.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH))) - { - std::cerr << "p3Wire::createOriginalPulse() Group unsuitable"; - std::cerr << std::endl; - return false; - } - - // Create Msg. - // Start fresh, just to be sure nothing dodgy happens in UX world. - RsWirePulse pulse; - - pulse.mMeta.mGroupId = group.mMeta.mGroupId; - pulse.mMeta.mAuthorId = group.mMeta.mAuthorId; - pulse.mMeta.mThreadId.clear(); - pulse.mMeta.mParentId.clear(); - pulse.mMeta.mOrigMsgId.clear(); - - // copy info over - pulse.mPulseType = WIRE_PULSE_TYPE_ORIGINAL; - pulse.mSentiment = pPulse->mSentiment; - pulse.mPulseText = pPulse->mPulseText; - pulse.mImage1 = pPulse->mImage1; - pulse.mImage2 = pPulse->mImage2; - pulse.mImage3 = pPulse->mImage3; - pulse.mImage4 = pPulse->mImage4; - - // all mRefs should empty. - - uint32_t token; - createPulse(token, pulse); - - int result = waitToken(token); - if (result != RsTokenService::COMPLETE) - { - std::cerr << "p3Wire::createOriginalPulse() Failed to create Pulse"; - std::cerr << std::endl; - return false; - } - - return true; -} - -bool p3Wire::createReplyPulse(RsGxsGroupId grpId, RsGxsMessageId msgId, RsGxsGroupId replyWith, uint32_t reply_type, RsWirePulseSPtr pPulse) -{ - // check reply_type. can only be ONE. - if (!((reply_type == WIRE_PULSE_TYPE_REPLY) || - (reply_type == WIRE_PULSE_TYPE_REPUBLISH) || - (reply_type == WIRE_PULSE_TYPE_LIKE))) - { - std::cerr << "p3Wire::createReplyPulse() reply_type is invalid"; - std::cerr << std::endl; - return false; - } - - // request both groups. - std::list groupIds = { grpId, replyWith }; - std::vector groups; - bool groupOkay = getGroups(groupIds, groups); - if (!groupOkay) { - std::cerr << "p3Wire::createReplyPulse() getGroups failed"; - std::cerr << std::endl; - return false; - } - - // extract group info. - RsWireGroup replyToGroup; - RsWireGroup replyWithGroup; - - if (grpId == replyWith) - { - if (groups.size() != 1) { - std::cerr << "p3Wire::createReplyPulse() getGroups != 1"; - std::cerr << std::endl; - return false; - } - - replyToGroup = groups[0]; - replyWithGroup = groups[0]; - } - else - { - if (groups.size() != 2) { - std::cerr << "p3Wire::createReplyPulse() getGroups != 2"; - std::cerr << std::endl; - return false; - } - - if (groups[0].mMeta.mGroupId == grpId) { - replyToGroup = groups[0]; - replyWithGroup = groups[1]; - } else { - replyToGroup = groups[1]; - replyWithGroup = groups[0]; - } - } - - // check groupIds match - if ((replyToGroup.mMeta.mGroupId != grpId) || - (replyWithGroup.mMeta.mGroupId != replyWith)) - { - std::cerr << "p3Wire::createReplyPulse() groupid mismatch"; - std::cerr << std::endl; - return false; - } - - // ensure Group is suitable. - if ((!(replyToGroup.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED)) || - (!(replyWithGroup.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH))) - { - std::cerr << "p3Wire::createReplyPulse() Group unsuitable"; - std::cerr << std::endl; - return false; - } - - // ********************************************************** - RsWirePulseSPtr replyToPulse; - if (!fetchPulse(grpId, msgId, replyToPulse)) - { - std::cerr << "p3Wire::createReplyPulse() fetchPulse FAILED"; - std::cerr << std::endl; - return false; - } - - // create Reply Msg. - RsWirePulse responsePulse; - - responsePulse.mMeta.mGroupId = replyWithGroup.mMeta.mGroupId; - responsePulse.mMeta.mAuthorId = replyWithGroup.mMeta.mAuthorId; - responsePulse.mMeta.mThreadId.clear(); - responsePulse.mMeta.mParentId.clear(); - responsePulse.mMeta.mOrigMsgId.clear(); - - responsePulse.mPulseType = WIRE_PULSE_TYPE_RESPONSE | reply_type; - responsePulse.mSentiment = pPulse->mSentiment; - responsePulse.mPulseText = pPulse->mPulseText; - responsePulse.mImage1 = pPulse->mImage1; - responsePulse.mImage2 = pPulse->mImage2; - responsePulse.mImage3 = pPulse->mImage3; - responsePulse.mImage4 = pPulse->mImage4; - - // mRefs refer to parent post. - responsePulse.mRefGroupId = replyToPulse->mMeta.mGroupId; - responsePulse.mRefGroupName = replyToGroup.mMeta.mGroupName; - responsePulse.mRefOrigMsgId = replyToPulse->mMeta.mOrigMsgId; - responsePulse.mRefAuthorId = replyToPulse->mMeta.mAuthorId; - responsePulse.mRefPublishTs = replyToPulse->mMeta.mPublishTs; - responsePulse.mRefPulseText = replyToPulse->mPulseText; - responsePulse.mRefImageCount = replyToPulse->ImageCount(); - - std::cerr << "p3Wire::createReplyPulse() create Response Pulse"; - std::cerr << std::endl; - - uint32_t token; - if (!createPulse(token, responsePulse)) - { - std::cerr << "p3Wire::createReplyPulse() FAILED to create Response Pulse"; - std::cerr << std::endl; - return false; - } - - int result = waitToken(token); - if (result != RsTokenService::COMPLETE) - { - std::cerr << "p3Wire::createReplyPulse() FAILED(2) to create Response Pulse"; - std::cerr << std::endl; - return false; - } - - // get MsgId. - std::pair responsePair; - if (!acknowledgeMsg(token, responsePair)) - { - std::cerr << "p3Wire::createReplyPulse() FAILED acknowledgeMsg for Response Pulse"; - std::cerr << std::endl; - return false; - } - - std::cerr << "p3Wire::createReplyPulse() Response Pulse ID: ("; - std::cerr << responsePair.first.toStdString() << ", "; - std::cerr << responsePair.second.toStdString() << ")"; - std::cerr << std::endl; - - // retrieve newly generated message. - // ********************************************************** - RsWirePulseSPtr createdResponsePulse; - if (!fetchPulse(responsePair.first, responsePair.second, createdResponsePulse)) - { - std::cerr << "p3Wire::createReplyPulse() fetch createdReponsePulse FAILED"; - std::cerr << std::endl; - return false; - } - - /* Check that pulses is created properly */ - if ((createdResponsePulse->mMeta.mGroupId != responsePulse.mMeta.mGroupId) || - (createdResponsePulse->mPulseText != responsePulse.mPulseText) || - (createdResponsePulse->mRefGroupId != responsePulse.mRefGroupId) || - (createdResponsePulse->mRefOrigMsgId != responsePulse.mRefOrigMsgId)) - { - std::cerr << "p3Wire::createReplyPulse() fetch createdReponsePulse FAILED"; - std::cerr << std::endl; - return false; - } - - // create ReplyTo Ref Msg. - std::cerr << "PulseAddDialog::postRefPulse() create Reference!"; - std::cerr << std::endl; - - // Reference Pulse. posted on Parent's Group. - RsWirePulse refPulse; - - refPulse.mMeta.mGroupId = replyToPulse->mMeta.mGroupId; - refPulse.mMeta.mAuthorId = replyWithGroup.mMeta.mAuthorId; // own author Id. - refPulse.mMeta.mThreadId = replyToPulse->mMeta.mOrigMsgId; - refPulse.mMeta.mParentId = replyToPulse->mMeta.mOrigMsgId; - refPulse.mMeta.mOrigMsgId.clear(); - - refPulse.mPulseType = WIRE_PULSE_TYPE_REFERENCE | reply_type; - refPulse.mSentiment = 0; // should this be =? createdResponsePulse->mSentiment; - - // Dont put parent PulseText into refPulse - it is available on Thread Msg. - // otherwise gives impression it is correctly setup Parent / Reply... - // when in fact the parent PublishTS, and AuthorId are wrong. - refPulse.mPulseText = ""; - - // refs refer back to own Post. - refPulse.mRefGroupId = replyWithGroup.mMeta.mGroupId; - refPulse.mRefGroupName = replyWithGroup.mMeta.mGroupName; - refPulse.mRefOrigMsgId = createdResponsePulse->mMeta.mOrigMsgId; - refPulse.mRefAuthorId = replyWithGroup.mMeta.mAuthorId; - refPulse.mRefPublishTs = createdResponsePulse->mMeta.mPublishTs; - refPulse.mRefPulseText = createdResponsePulse->mPulseText; - refPulse.mRefImageCount = createdResponsePulse->ImageCount(); - - // publish Ref Msg. - if (!createPulse(token, refPulse)) - { - std::cerr << "p3Wire::createReplyPulse() FAILED to create Ref Pulse"; - std::cerr << std::endl; - return false; - } - - result = waitToken(token); - if (result != RsTokenService::COMPLETE) - { - std::cerr << "p3Wire::createReplyPulse() FAILED(2) to create Ref Pulse"; - std::cerr << std::endl; - return false; - } - - // get MsgId. - std::pair refPair; - if (!acknowledgeMsg(token, refPair)) - { - std::cerr << "p3Wire::createReplyPulse() FAILED acknowledgeMsg for Ref Pulse"; - std::cerr << std::endl; - return false; - } - - std::cerr << "p3Wire::createReplyPulse() Success: Ref Pulse ID: ("; - std::cerr << refPair.first.toStdString() << ", "; - std::cerr << refPair.second.toStdString() << ")"; - std::cerr << std::endl; - - return true; -} - - - // Blocking, request structures for display. -#if 0 -bool p3Wire::createReplyPulse(uint32_t &token, RsWirePulse &pulse) -{ - - return true; -} - -bool p3Wire::createRepublishPulse(uint32_t &token, RsWirePulse &pulse) -{ - - return true; -} - -bool p3Wire::createLikePulse(uint32_t &token, RsWirePulse &pulse) -{ - - return true; -} -#endif - - // WireGroup Details. -bool p3Wire::getWireGroup(const RsGxsGroupId &groupId, RsWireGroupSPtr &grp) -{ - std::list groupIds = { groupId }; - std::map groups; - if (!fetchGroupPtrs(groupIds, groups)) - { - std::cerr << "p3Wire::getWireGroup() failed to fetchGroupPtrs"; - std::cerr << std::endl; - return false; - } - - if (groups.size() != 1) - { - std::cerr << "p3Wire::getWireGroup() invalid group size"; - std::cerr << std::endl; - return false; - } - - grp = groups.begin()->second; - - // TODO Should fill in Counters of pulses/likes/republishes/replies - return true; -} - -// TODO Remove duplicate ... -bool p3Wire::getWirePulse(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, RsWirePulseSPtr &pPulse) -{ - return fetchPulse(groupId, msgId, pPulse); -} - - - - -bool compare_time(const RsWirePulseSPtr& first, const RsWirePulseSPtr &second) -{ - return first->mMeta.mPublishTs > second->mMeta.mPublishTs; -} - - // should this filter them in some way? - // date, or count would be more likely. -bool p3Wire::getPulsesForGroups(const std::list &groupIds, std::list &pulsePtrs) -{ - // request all the pulses (Top-Level Thread Msgs). - std::cerr << "p3Wire::getPulsesForGroups()"; - std::cerr << std::endl; - - uint32_t token; - { - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_THREAD; - - getTokenService()->requestMsgInfo( - token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds); - } - - // wait for pulse request to completed. - std::cerr << "p3Wire::getPulsesForGroups() waiting for token"; - std::cerr << std::endl; - - int result = waitToken(token); - if (result != RsTokenService::COMPLETE) - { - std::cerr << "p3Wire::getPulsesForGroups() token FAILED, result: " << result; - std::cerr << std::endl; - return false; - } - - // retrieve Pulses. - std::cerr << "p3Wire::getPulsesForGroups() retrieving token"; - std::cerr << std::endl; - if (!getPulsePtrData(token, pulsePtrs)) - { - std::cerr << "p3Wire::getPulsesForGroups() tokenPulse ERROR"; - std::cerr << std::endl; - return false; - } - - std::cerr << "p3Wire::getPulsesForGroups() size = " << pulsePtrs.size(); - std::cerr << std::endl; - { - std::list::iterator it; - for (it = pulsePtrs.begin(); it != pulsePtrs.end(); it++) - { - std::cerr << "p3Wire::getPulsesForGroups() Flags: "; - std::cerr << (*it)->mPulseType << " Msg: " << (*it)->mPulseText; - std::cerr << std::endl; - } - } - - std::cerr << "p3Wire::getPulsesForGroups() size = " << pulsePtrs.size(); - std::cerr << " sorting and trimming"; - std::cerr << std::endl; - - // sort and filter list. - pulsePtrs.sort(compare_time); - - // trim to N max. - uint32_t N = 10; - if (pulsePtrs.size() > N) { - pulsePtrs.resize(N); - } - - // for each fill in details. - std::list::iterator it; - for (it = pulsePtrs.begin(); it != pulsePtrs.end(); it++) - { - if (!updatePulse(*it, 1)) - { - std::cerr << "p3Wire::getPulsesForGroups() Failed to updatePulse"; - std::cerr << std::endl; - return false; - } - } - - // update GroupPtrs for all pulsePtrs. - if (!updateGroups(pulsePtrs)) - { - std::cerr << "p3Wire::getPulsesForGroups() failed to updateGroups"; - std::cerr << std::endl; - return false; - } - - return true; -} - - -bool p3Wire::getPulseFocus(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, int /* type */, RsWirePulseSPtr &pPulse) -{ - std::cerr << "p3Wire::getPulseFocus("; - std::cerr << "grpId: " << groupId << " msgId: " << msgId; - std::cerr << " )"; - std::cerr << std::endl; - - if (!fetchPulse(groupId, msgId, pPulse)) - { - std::cerr << "p3Wire::getPulseFocus() failed to fetch Pulse"; - std::cerr << std::endl; - return false; - } - - if (!updatePulse(pPulse, 3)) - { - std::cerr << "p3Wire::getPulseFocus() failed to update Pulse"; - std::cerr << std::endl; - return false; - } - - /* Fill in GroupPtrs */ - std::list pulsePtrs; - pulsePtrs.push_back(pPulse); - - if (!updateGroups(pulsePtrs)) - { - std::cerr << "p3Wire::getPulseFocus() failed to updateGroups"; - std::cerr << std::endl; - return false; - } - - return true; -} - - -// function to update a pulse with the (Ref) child with actual data. -bool p3Wire::updatePulse(RsWirePulseSPtr pPulse, int levels) -{ - bool okay = true; - - // setup logging label. - std::ostringstream out; - out << "pulse[" << (void *) pPulse.get() << "], " << levels; - std::string label = out.str(); - - std::cerr << "p3Wire::updatePulse(" << label << ") starting"; - std::cerr << std::endl; - - // is pPulse is a REF, then request the original. - // if no original available the done. - if (pPulse->mPulseType & WIRE_PULSE_TYPE_REFERENCE) - { - RsWirePulseSPtr fullPulse; - std::cerr << "p3Wire::updatePulse(" << label << ") fetching REF ("; - std::cerr << "grpId: " << pPulse->mRefGroupId << " msgId: " << pPulse->mRefOrigMsgId; - std::cerr << " )"; - std::cerr << std::endl; - if (!fetchPulse(pPulse->mRefGroupId, pPulse->mRefOrigMsgId, fullPulse)) - { - std::cerr << "p3Wire::updatePulse(" << label << ") failed to fetch REF"; - std::cerr << std::endl; - return false; - } - std::cerr << "p3Wire::updatePulse(" << label << ") replacing REF"; - std::cerr << std::endl; - - *pPulse = *fullPulse; - } - - // Request children: (Likes / Retweets / Replies) - std::cerr << "p3Wire::updatePulse(" << label << ") requesting children"; - std::cerr << std::endl; - - uint32_t token; - { - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; - // OR opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_PARENT; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_THREAD; - - std::vector msgIds = { - std::make_pair(pPulse->mMeta.mGroupId, pPulse->mMeta.mOrigMsgId) - }; - - getTokenService()->requestMsgRelatedInfo( - token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds); - } - - // wait for request to complete - std::cerr << "p3Wire::updatePulse(" << label << ") waiting for token"; - std::cerr << std::endl; - - int result = waitToken(token); - if (result != RsTokenService::COMPLETE) - { - std::cerr << "p3Wire::updatePulse(" << label << ") token FAILED, result: " << result; - std::cerr << std::endl; - return false; - } - - /* load children */ - okay = updatePulseChildren(pPulse, token); - if (!okay) - { - std::cerr << "p3Wire::updatePulse(" << label << ") FAILED to update Children"; - std::cerr << std::endl; - return false; - } - - /* if down to last level, no need to updateChildren */ - if (levels <= 1) - { - std::cerr << "p3Wire::updatePulse(" << label << ") Level <= 1 finished"; - std::cerr << std::endl; - return okay; - } - - /* recursively update children */ - std::cerr << "p3Wire::updatePulse(" << label << ") updating children recursively"; - std::cerr << std::endl; - std::list::iterator it; - for (it = pPulse->mReplies.begin(); it != pPulse->mReplies.end(); it++) - { - bool childOkay = updatePulse(*it, levels - 1); - if (!childOkay) { - std::cerr << "p3Wire::updatePulse(" << label << ") update children (reply) failed"; - std::cerr << std::endl; - } - } - - for (it = pPulse->mRepublishes.begin(); it != pPulse->mRepublishes.end(); it++) - { - bool childOkay = updatePulse(*it, levels - 1); - if (!childOkay) { - std::cerr << "p3Wire::updatePulse(" << label << ") update children (repub) failed"; - std::cerr << std::endl; - } - } - - return okay; -} - - -// function to update the (Ref) child with actual data. -bool p3Wire::updatePulseChildren(RsWirePulseSPtr pParent, uint32_t token) -{ - { - bool okay = true; - std::vector pulses; - if (getRelatedPulseData(token, pulses)) { - std::vector::iterator it; - for (it = pulses.begin(); it != pulses.end(); it++) - { - std::cerr << "p3Wire::updatePulseChildren() retrieved child: " << *it; - std::cerr << std::endl; - - RsWirePulseSPtr pPulse = std::make_shared(*it); - // switch on type. - if (it->mPulseType & WIRE_PULSE_TYPE_LIKE) { - pParent->mLikes.push_back(pPulse); - std::cerr << "p3Wire::updatePulseChildren() adding Like"; - std::cerr << std::endl; - } - else if (it->mPulseType & WIRE_PULSE_TYPE_REPUBLISH) { - pParent->mRepublishes.push_back(pPulse); - std::cerr << "p3Wire::updatePulseChildren() adding Republish"; - std::cerr << std::endl; - } - else if (it->mPulseType & WIRE_PULSE_TYPE_REPLY) { - pParent->mReplies.push_back(pPulse); - std::cerr << "p3Wire::updatePulseChildren() adding Reply"; - std::cerr << std::endl; - } - else { - std::cerr << "p3Wire::updatePulseChildren() unknown child type: " << it->mPulseType; - std::cerr << std::endl; - } - } - } else { - std::cerr << "p3Wire::updatePulseChildren() ERROR failed to retrieve token"; - std::cerr << std::endl; - okay = false; - } - - if (!okay) { - std::cerr << "p3Wire::updatePulseChildren() token ERROR"; - std::cerr << std::endl; - } - return okay; - } -} - -/* High-level utility function to update mGroupPtr / mRefGroupPtr links. - * fetches associated groups and reference them from pulses - * - * extractGroupIds (owner + refs). - * fetch all available GroupIDs. (just IDs - so light). - * do intersection of IDs. - * apply IDs. - */ - -bool p3Wire::updateGroups(std::list &pulsePtrs) -{ - std::set pulseGroupIds; - - std::list::iterator it; - for (it = pulsePtrs.begin(); it != pulsePtrs.end(); it++) - { - if (!extractGroupIds(*it, pulseGroupIds)) - { - std::cerr << "p3Wire::updateGroups() failed to extractGroupIds"; - std::cerr << std::endl; - return false; - } - } - - std::list availGroupIds; - if (!trimToAvailGroupIds(pulseGroupIds, availGroupIds)) - { - std::cerr << "p3Wire::updateGroups() failed to trimToAvailGroupIds"; - std::cerr << std::endl; - return false; - } - - std::map groups; - if (!fetchGroupPtrs(availGroupIds, groups)) - { - std::cerr << "p3Wire::updateGroups() failed to fetchGroupPtrs"; - std::cerr << std::endl; - return false; - } - - for (it = pulsePtrs.begin(); it != pulsePtrs.end(); it++) - { - if (!updateGroupPtrs(*it, groups)) - { - std::cerr << "p3Wire::updateGroups() failed to updateGroupPtrs"; - std::cerr << std::endl; - return false; - } - } - return true; -} - - -// this function doesn't depend on p3Wire, could make static. -bool p3Wire::extractGroupIds(RsWirePulseConstSPtr pPulse, std::set &groupIds) -{ - std::cerr << "p3Wire::extractGroupIds()"; - std::cerr << std::endl; - - if (!pPulse) { - std::cerr << "p3Wire::extractGroupIds() INVALID pPulse"; - std::cerr << std::endl; - return false; - } - - // install own groupId. - groupIds.insert(pPulse->mMeta.mGroupId); - - /* do this recursively */ - if (pPulse->mPulseType & WIRE_PULSE_TYPE_REFERENCE) { - // REPLY: mRefGroupId, PARENT was in mMeta.mGroupId. - groupIds.insert(pPulse->mRefGroupId); - /* skipping */ - return true; - } - - - if (pPulse->mPulseType & WIRE_PULSE_TYPE_RESPONSE) { - // REPLY: meta.mGroupId, PARENT: mRefGroupId - groupIds.insert(pPulse->mRefGroupId); - } - - /* iterate through children, recursively */ - std::list::const_iterator it; - for (it = pPulse->mReplies.begin(); it != pPulse->mReplies.end(); it++) - { - bool childOkay = extractGroupIds(*it, groupIds); - if (!childOkay) { - std::cerr << "p3Wire::extractGroupIds() update children (reply) failed"; - std::cerr << std::endl; - return false; - } - } - - for (it = pPulse->mRepublishes.begin(); it != pPulse->mRepublishes.end(); it++) - { - bool childOkay = extractGroupIds(*it, groupIds); - if (!childOkay) { - std::cerr << "p3Wire::extractGroupIds() update children (repub) failed"; - std::cerr << std::endl; - return false; - } - } - - // not bothering with LIKEs at the moment. TODO. - return true; -} - -bool p3Wire::updateGroupPtrs(RsWirePulseSPtr pPulse, const std::map &groups) -{ - std::map::const_iterator git; - git = groups.find(pPulse->mMeta.mGroupId); - if (git == groups.end()) { - // error - return false; - } - - pPulse->mGroupPtr = git->second; - - // if REF, fill in mRefGroupPtr based on mRefGroupId. - if (pPulse->mPulseType & WIRE_PULSE_TYPE_REFERENCE) { - // if RefGroupId is in list, fill in. No error if its not there. - std::map::const_iterator rgit; - rgit = groups.find(pPulse->mRefGroupId); - if (rgit != groups.end()) { - pPulse->mRefGroupPtr = rgit->second; - } - - // no children for REF pulse, so can return now. - return true; - } - - // if Response, fill in mRefGroupPtr based on mRefGroupId. - if (pPulse->mPulseType & WIRE_PULSE_TYPE_RESPONSE) { - // if RefGroupId is in list, fill in. No error if its not there. - std::map::const_iterator rgit; - rgit = groups.find(pPulse->mRefGroupId); - if (rgit != groups.end()) { - pPulse->mRefGroupPtr = rgit->second; - } - // do children as well. - } - - /* recursively apply to children */ - std::list::iterator it; - for (it = pPulse->mReplies.begin(); it != pPulse->mReplies.end(); it++) - { - bool childOkay = updateGroupPtrs(*it, groups); - if (!childOkay) { - std::cerr << "p3Wire::updateGroupPtrs() update children (reply) failed"; - std::cerr << std::endl; - return false; - } - } - - for (it = pPulse->mRepublishes.begin(); it != pPulse->mRepublishes.end(); it++) - { - bool childOkay = updateGroupPtrs(*it, groups); - if (!childOkay) { - std::cerr << "p3Wire::updateGroupPtrs() update children (repub) failed"; - std::cerr << std::endl; - return false; - } - } - - // not bothering with LIKEs at the moment. TODO. - return true; -} - -bool p3Wire::trimToAvailGroupIds(const std::set &pulseGroupIds, - std::list &availGroupIds) -{ - /* request all groupIds */ - std::cerr << "p3Wire::trimToAvailGroupIds()"; - std::cerr << std::endl; - - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; - - if (!requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - { - std::cerr << "p3Wire::trimToAvailGroupIds() failed to fetch groups"; - std::cerr << std::endl; - return false; - } - - std::list localGroupIds; - if (!RsGenExchange::getGroupList(token, localGroupIds)) - { - std::cerr << "p3Wire::trimToAvailGroupIds() failed to get GroupIds"; - std::cerr << std::endl; - return false; - } - - /* do intersection between result ^ pulseGroups -> availGroupIds */ - std::set_intersection(localGroupIds.begin(), localGroupIds.end(), - pulseGroupIds.begin(), pulseGroupIds.end(), - std::back_inserter(availGroupIds)); - - return true; -} - -bool p3Wire::fetchGroupPtrs(const std::list &groupIds, - std::map &groups) -{ - std::cerr << "p3Wire::fetchGroupPtrs()"; - std::cerr << std::endl; - - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if (!requestGroupInfo(token, opts, groupIds) || waitToken(token) != RsTokenService::COMPLETE ) - { - std::cerr << "p3Wire::fetchGroupPtrs() failed to fetch groups"; - std::cerr << std::endl; - return false; - } - return getGroupPtrData(token, groups); -} - diff --git a/libretroshare/src/services/p3wire.h b/libretroshare/src/services/p3wire.h deleted file mode 100644 index 2e7375578..000000000 --- a/libretroshare/src/services/p3wire.h +++ /dev/null @@ -1,119 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3wire.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2020 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef P3_WIRE_SERVICE_HEADER -#define P3_WIRE_SERVICE_HEADER - -#include "retroshare/rswire.h" -#include "gxs/rsgenexchange.h" - -#include -#include - -/* - * Wire Service - * - * - */ - -class p3Wire: public RsGenExchange, public RsWire -{ -public: - p3Wire(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs *gixs); - virtual RsServiceInfo getServiceInfo(); - static uint32_t wireAuthenPolicy(); - -protected: - virtual void notifyChanges(std::vector& changes) ; - -public: - virtual void service_tick(); - - virtual RsTokenService* getTokenService(); - - /* Specific Service Data */ - virtual bool getGroupData(const uint32_t &token, std::vector &groups) override; - virtual bool getPulseData(const uint32_t &token, std::vector &pulses) override; - - virtual bool createGroup(uint32_t &token, RsWireGroup &group) override; - virtual bool createPulse(uint32_t &token, RsWirePulse &pulse) override; - - // Blocking Interfaces. - virtual bool createGroup(RsWireGroup &group) override; - virtual bool updateGroup(const RsWireGroup &group) override; - virtual bool getGroups(const std::list grpIds, std::vector &groups) override; - - // New Interfaces. - // Blocking, request structures for display. - virtual bool createOriginalPulse(const RsGxsGroupId &grpId, RsWirePulseSPtr pPulse) override; - virtual bool createReplyPulse(RsGxsGroupId grpId, RsGxsMessageId msgId, - RsGxsGroupId replyWith, uint32_t reply_type, - RsWirePulseSPtr pPulse) override; - -#if 0 - virtual bool createReplyPulse(uint32_t &token, RsWirePulse &pulse) override; - virtual bool createRepublishPulse(uint32_t &token, RsWirePulse &pulse) override; - virtual bool createLikePulse(uint32_t &token, RsWirePulse &pulse) override; -#endif - - virtual bool getWireGroup(const RsGxsGroupId &groupId, RsWireGroupSPtr &grp) override; - virtual bool getWirePulse(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, RsWirePulseSPtr &pPulse) override; - - virtual bool getPulsesForGroups(const std::list &groupIds, std::list &pulsePtrs) override; - - virtual bool getPulseFocus(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, int type, RsWirePulseSPtr &pPulse) override; - -private: - // Internal Service Data. - // They should eventually all be here. - bool getRelatedPulseData(const uint32_t &token, std::vector &pulses); - bool getGroupPtrData(const uint32_t &token, - std::map &groups); - bool getPulsePtrData(const uint32_t &token, std::list &pulses); - - // util functions fetching data. - bool fetchPulse(RsGxsGroupId grpId, RsGxsMessageId msgId, RsWirePulseSPtr &pPulse); - bool updatePulse(RsWirePulseSPtr pPulse, int levels); - bool updatePulseChildren(RsWirePulseSPtr pParent, uint32_t token); - - // update GroupPtrs - bool updateGroups(std::list &pulsePtrs); - - // sub utility functions used by updateGroups. - bool extractGroupIds(RsWirePulseConstSPtr pPulse, std::set &groupIds); - - bool updateGroupPtrs(RsWirePulseSPtr pPulse, - const std::map &groups); - - bool trimToAvailGroupIds(const std::set &pulseGroupIds, - std::list &availGroupIds); - - bool fetchGroupPtrs(const std::list &groupIds, - std::map &groups); - - - virtual void generateDummyData(); - std::string genRandomId(); - - RsMutex mWireMtx; -}; - -#endif diff --git a/libretroshare/src/services/rseventsservice.cc b/libretroshare/src/services/rseventsservice.cc deleted file mode 100644 index 3bbb852be..000000000 --- a/libretroshare/src/services/rseventsservice.cc +++ /dev/null @@ -1,197 +0,0 @@ -/******************************************************************************* - * Retroshare events service * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2019-2020 Gioacchino Mazzurco * - * Copyright (C) 2019-2020 Retroshare Team * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ - -#include -#include - -#include "services/rseventsservice.h" - - -/*extern*/ RsEvents* rsEvents = nullptr; - -RsEvent::~RsEvent() = default; -RsEvents::~RsEvents() = default; - -/*static*/ const RsEventsErrorCategory RsEventsErrorCategory::instance; - -std::error_condition RsEventsErrorCategory::default_error_condition(int ev) -const noexcept -{ - switch(static_cast(ev)) - { - case RsEventsErrorNum::INVALID_HANDLER_ID: // [[fallthrough]]; - case RsEventsErrorNum::NULL_EVENT_POINTER: // [[fallthrough]]; - case RsEventsErrorNum::EVENT_TYPE_UNDEFINED: // [[fallthrough]]; - case RsEventsErrorNum::EVENT_TYPE_OUT_OF_RANGE: - return std::errc::invalid_argument; - default: - return std::error_condition(ev, *this); - } -} - -std::error_condition RsEventsService::isEventTypeInvalid(RsEventType eventType) -{ - if(eventType == RsEventType::__NONE) - return RsEventsErrorNum::EVENT_TYPE_UNDEFINED; - - if( eventType < RsEventType::__NONE || - eventType >= static_cast(mHandlerMaps.size()) ) - return RsEventsErrorNum::EVENT_TYPE_OUT_OF_RANGE; - - return std::error_condition(); -} - -std::error_condition RsEventsService::isEventInvalid( - std::shared_ptr event) -{ - if(!event) return RsEventsErrorNum::NULL_EVENT_POINTER; - return isEventTypeInvalid(event->mType); -} - -std::error_condition RsEventsService::postEvent( - std::shared_ptr event ) -{ - if(std::error_condition ec = isEventInvalid(event)) return ec; - - RS_STACK_MUTEX(mEventQueueMtx); - mEventQueue.push_back(event); - return std::error_condition(); -} - -std::error_condition RsEventsService::sendEvent( - std::shared_ptr event ) -{ - if(std::error_condition ec = isEventInvalid(event)) return ec; - handleEvent(event); - return std::error_condition(); -} - -RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId() -{ - RS_STACK_MUTEX(mHandlerMapMtx); - return generateUniqueHandlerId_unlocked(); -} - -RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId_unlocked() -{ - if(++mLastHandlerId) return mLastHandlerId; // Avoid 0 after overflow - return 1; -} - -std::error_condition RsEventsService::registerEventsHandler( - std::function)> multiCallback, - RsEventsHandlerId_t& hId, RsEventType eventType ) -{ - RS_STACK_MUTEX(mHandlerMapMtx); - - if(eventType != RsEventType::__NONE) - if(std::error_condition ec = isEventTypeInvalid(eventType)) - return ec; - - if(!hId) hId = generateUniqueHandlerId_unlocked(); - else if (hId > mLastHandlerId) - { - print_stacktrace(); - return RsEventsErrorNum::INVALID_HANDLER_ID; - } - - mHandlerMaps[static_cast(eventType)][hId] = multiCallback; - return std::error_condition(); -} - -std::error_condition RsEventsService::unregisterEventsHandler( - RsEventsHandlerId_t hId ) -{ - RS_STACK_MUTEX(mHandlerMapMtx); - - for(uint32_t i=0; i eventPtr(nullptr); - size_t futureEventsCounter = 0; - -dispatchEventFromQueueLock: - mEventQueueMtx.lock(); - if(mEventQueue.size() > futureEventsCounter) - { - eventPtr = mEventQueue.front(); - mEventQueue.pop_front(); - - if(eventPtr->mTimePoint >= nextRunAt) - { - mEventQueue.push_back(eventPtr); - ++futureEventsCounter; - } - } - mEventQueueMtx.unlock(); - - if(eventPtr) - { - /* It is relevant that this stays out of mEventQueueMtx */ - handleEvent(eventPtr); - eventPtr = nullptr; // ensure refcounter is decremented before sleep - goto dispatchEventFromQueueLock; - } - - std::this_thread::sleep_until(nextRunAt); -} - -void RsEventsService::handleEvent(std::shared_ptr event) -{ - if(std::error_condition ec = isEventInvalid(event)) - { - RsErr() << __PRETTY_FUNCTION__ << " " << ec << std::endl; - print_stacktrace(); - return; - } - - RS_STACK_MUTEX(mHandlerMapMtx); - /* It is important to also call the callback under mutex protection to - * ensure they are not unregistered in the meanwhile. - * If a callback try to fiddle with registering/unregistering it will - * deadlock */ - - // Call all clients that registered a callback for this event type - for(auto cbit: mHandlerMaps[static_cast(event->mType)]) - cbit.second(event); - - /* Also call all clients that registered with NONE, meaning that they - * expect all events */ - for(auto cbit: mHandlerMaps[static_cast(RsEventType::__NONE)]) - cbit.second(event); -} diff --git a/libretroshare/src/services/rseventsservice.h b/libretroshare/src/services/rseventsservice.h deleted file mode 100644 index 4f6ce98eb..000000000 --- a/libretroshare/src/services/rseventsservice.h +++ /dev/null @@ -1,88 +0,0 @@ -/******************************************************************************* - * Retroshare events service * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2019-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rsevents.h" -#include "util/rsthreads.h" -#include "util/rsdebug.h" - -class RsEventsService : - public RsEvents, public RsTickingThread -{ -public: - RsEventsService(): - mHandlerMapMtx("RsEventsService::mHandlerMapMtx"), mLastHandlerId(1), - mEventQueueMtx("RsEventsService::mEventQueueMtx") {} - - /// @see RsEvents - std::error_condition postEvent( - std::shared_ptr event ) override; - - /// @see RsEvents - std::error_condition sendEvent( - std::shared_ptr event ) override; - - /// @see RsEvents - RsEventsHandlerId_t generateUniqueHandlerId() override; - - /// @see RsEvents - std::error_condition registerEventsHandler( - std::function)> multiCallback, - RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0), - RsEventType eventType = RsEventType::__NONE ) override; - - /// @see RsEvents - std::error_condition unregisterEventsHandler( - RsEventsHandlerId_t hId ) override; - -protected: - std::error_condition isEventTypeInvalid(RsEventType eventType); - std::error_condition isEventInvalid(std::shared_ptr event); - - RsMutex mHandlerMapMtx; - RsEventsHandlerId_t mLastHandlerId; - - /** Storage for event handlers, keep 10 extra types for plugins that might - * be released indipendently */ - std::array< - std::map< - RsEventsHandlerId_t, - std::function)> >, - static_cast(RsEventType::__MAX) + 10 - > mHandlerMaps; - - RsMutex mEventQueueMtx; - std::deque< std::shared_ptr > mEventQueue; - - void threadTick() override; /// @see RsTickingThread - - void handleEvent(std::shared_ptr event); - RsEventsHandlerId_t generateUniqueHandlerId_unlocked(); - - RS_SET_CONTEXT_DEBUG_LEVEL(3) -}; diff --git a/libretroshare/src/tcponudp/bio_tou.h b/libretroshare/src/tcponudp/bio_tou.h deleted file mode 100644 index a82444ccc..000000000 --- a/libretroshare/src/tcponudp/bio_tou.h +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: bio_tou.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef BIO_TCPONUDP_H -#define BIO_TCPONUDP_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -int BIO_tou_socket_should_retry(int s, int e); -int BIO_tou_socket_non_fatal_error(int error); - -#define BIO_TYPE_TOU_SOCKET (30|0x0400|0x0100) /* NEW rmfern type */ - -BIO_METHOD *BIO_s_tou_socket(void); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/libretroshare/src/tcponudp/bss_tou.cc b/libretroshare/src/tcponudp/bss_tou.cc deleted file mode 100644 index 286201f53..000000000 --- a/libretroshare/src/tcponudp/bss_tou.cc +++ /dev/null @@ -1,355 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: bss_tou.c * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 1995-1998 Eric Young * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#ifndef OPENSSL_NO_SOCK - -#include "bio_tou.h" - -#include -#include -#include /* for strlen() */ - -#define USE_SOCKETS -#include - -#include "tou.h" -#include "util/rsdebug.h" - -RS_SET_CONTEXT_DEBUG_LEVEL(0); - -static int tou_socket_write(BIO *h, const char *buf, int num); -static int tou_socket_read(BIO *h, char *buf, int size); -static int tou_socket_puts(BIO *h, const char *str); -static long tou_socket_ctrl(BIO *h, int cmd, long arg1, void *arg2); -static int tou_socket_new(BIO *h); -static int tou_socket_free(BIO *data); -static int get_last_tou_socket_error(int s); -static int clear_tou_socket_error(int s); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - -static int BIO_get_init(BIO *a) { return a->init; } - -#if (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000) \ - || (!defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) - -static int BIO_get_shutdown(BIO *a) { return a->shutdown; } -static void BIO_set_init(BIO *a,int i) { a->init=i; } -static void BIO_set_data(BIO *a,void *p) { a->ptr = p; } -long (*BIO_meth_get_ctrl(const BIO_METHOD* biom)) (BIO*, int, long, void*) -{ return biom->ctrl; } - -#endif /* (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000) \ -|| (!defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) */ - -static BIO_METHOD methods_tou_sockp = -{ - BIO_TYPE_TOU_SOCKET, - "tou_socket", - tou_socket_write, - tou_socket_read, - tou_socket_puts, - nullptr, // bgets - tou_socket_ctrl, - tou_socket_new, - tou_socket_free, - nullptr, // callback_ctrl -}; - -BIO_METHOD* BIO_s_tou_socket(void) -{ - Dbg2() << __PRETTY_FUNCTION__ << std::endl; - return(&methods_tou_sockp); -} - -#else // OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - -BIO_METHOD* BIO_s_tou_socket(void) -{ - static BIO_METHOD* methods_tou_sockp_ptr = NULL; - if(!methods_tou_sockp_ptr) - { - methods_tou_sockp_ptr = BIO_meth_new(BIO_TYPE_TOU_SOCKET, "tou_socket"); - - BIO_meth_set_write( methods_tou_sockp_ptr, tou_socket_write ); - BIO_meth_set_read( methods_tou_sockp_ptr, tou_socket_read ); - BIO_meth_set_puts( methods_tou_sockp_ptr, tou_socket_puts ); - BIO_meth_set_ctrl( methods_tou_sockp_ptr, tou_socket_ctrl ); - BIO_meth_set_create( methods_tou_sockp_ptr, tou_socket_new ); - BIO_meth_set_destroy( methods_tou_sockp_ptr, tou_socket_free ); - } - - return methods_tou_sockp_ptr; -} - -#endif // OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - -static int tou_socket_new(BIO *bi) -{ - Dbg2() << __PRETTY_FUNCTION__ << std::endl; - - BIO_set_init(bi,0) ; - BIO_set_data(bi, nullptr); // sets bi->ptr - BIO_set_flags(bi,0) ; - BIO_set_fd(bi,0,0) ; - return(1); -} - -static int tou_socket_free(BIO *a) -{ - Dbg2() << __PRETTY_FUNCTION__ << std::endl; - - if (!a) return(0); - - if(BIO_get_shutdown(a)) - { - if(BIO_get_init(a)) tou_close(static_cast(BIO_get_fd(a, nullptr))); - BIO_set_init(a,0) ; - BIO_set_flags(a,0) ; - } - return(1); - } - -static int tou_socket_read(BIO *b, char *out, int outl) -{ - Dbg2() << __PRETTY_FUNCTION__ << std::endl; - - int ret=0; - - if (out) - { - clear_tou_socket_error(BIO_get_fd(b,NULL)); - /* call tou library */ - ret=tou_read(BIO_get_fd(b,NULL),out,outl); - BIO_clear_retry_flags(b); - if (ret <= 0) - { - if (BIO_tou_socket_should_retry(BIO_get_fd(b,NULL), ret)) - BIO_set_retry_read(b); - } - } -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_socket_read() = %d\n", ret); -#endif - return(ret); - } - -static int tou_socket_write(BIO *b, const char *in, int inl) - { - int ret; -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_socket_write(%p,%p,%d)\n",b,in,inl); -#endif - - clear_tou_socket_error(BIO_get_fd(b,NULL)); - /* call tou library */ - ret=tou_write(BIO_get_fd(b,NULL),in,inl); - BIO_clear_retry_flags(b); - if (ret <= 0) - { - if (BIO_tou_socket_should_retry(BIO_get_fd(b,NULL),ret)) - { - BIO_set_retry_write(b); -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_socket_write() setting retry flag\n"); -#endif - } - } -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_socket_write() = %d\n", ret); -#endif - return(ret); - } - -static long tou_socket_ctrl(BIO *b, int cmd, long num, void *ptr) - { - long ret=1; -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_socket_ctrl(%p,%d,%ld)\n", b, cmd, num); -#endif - - // We are not allowed to call BIO_set_fd here, because it will trigger a callback, which re-ends here - - switch (cmd) - { - case BIO_CTRL_RESET: - num=0; - /* fallthrough */ - case BIO_C_FILE_SEEK: - ret=0; - break; - case BIO_C_FILE_TELL: - case BIO_CTRL_INFO: - ret=0; - break; - case BIO_C_SET_FD: - tou_socket_free(b); - ret = BIO_meth_get_ctrl((BIO_METHOD*)BIO_s_fd())(b,cmd,num,ptr); - break; - case BIO_C_GET_FD: - ret = BIO_meth_get_ctrl((BIO_METHOD*)BIO_s_fd())(b,cmd,num,ptr); - break; - case BIO_CTRL_GET_CLOSE: - ret = BIO_meth_get_ctrl((BIO_METHOD*)BIO_s_fd())(b,cmd,num,ptr); - break; - case BIO_CTRL_SET_CLOSE: - ret = BIO_meth_get_ctrl((BIO_METHOD*)BIO_s_fd())(b,cmd,num,ptr); - break; - case BIO_CTRL_PENDING: - ret = tou_maxread(BIO_get_fd(b,NULL)); -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_pending = %ld\n", ret); -#endif - break; - case BIO_CTRL_WPENDING: - ret = tou_maxwrite(BIO_get_fd(b,NULL)); -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_wpending = %ld\n", ret); -#endif - break; - case BIO_CTRL_DUP: - case BIO_CTRL_FLUSH: - ret=1; - break; - default: - ret=0; - break; - } - return(ret); - } - -static int tou_socket_puts(BIO *bp, const char *str) - { - int n,ret; - -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_socket_puts()\n"); -#endif - - n=strlen(str); - ret=tou_socket_write(bp,str,n); - return(ret); - } - -static int clear_tou_socket_error(int fd) -{ -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "clear_tou_socket_error()\n"); -#endif - return tou_clear_error(fd); -} - -static int get_last_tou_socket_error(int s) -{ -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "get_last_tou_socket_error()\n"); -#endif - return tou_errno(s); -} - -int BIO_tou_socket_should_retry(int s, int i) - { - int err; -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "BIO_tou_socket_should_retry()\n"); -#endif - - if ((i == 0) || (i == -1)) - { - err=get_last_tou_socket_error(s); - -#if defined(OPENSSL_SYS_WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */ - if ((i == -1) && (err == 0)) - return(1); -#endif - - return(BIO_tou_socket_non_fatal_error(err)); - } - return(0); - } - -int BIO_tou_socket_non_fatal_error(int err) -{ - constexpr int fatalError = 0; - constexpr int nonFatalError = 1; - - switch (err) - { -#if defined(OPENSSL_SYS_WINDOWS) -# if defined(WSAEWOULDBLOCK) - case WSAEWOULDBLOCK: -# endif // defined(WSAEWOULDBLOCK) -#endif // defined(OPENSSL_SYS_WINDOWS) - -#ifdef EWOULDBLOCK -# ifdef WSAEWOULDBLOCK -# if WSAEWOULDBLOCK != EWOULDBLOCK - case EWOULDBLOCK: -# endif // WSAEWOULDBLOCK != EWOULDBLOCK -# else // def WSAEWOULDBLOCK - case EWOULDBLOCK: -# endif // def WSAEWOULDBLOCK -#endif - -#if defined(ENOTCONN) - case ENOTCONN: -#endif // defined(ENOTCONN) - -#ifdef EINTR - case EINTR: -#endif // def EINTR - -#ifdef EAGAIN -# if EWOULDBLOCK != EAGAIN - case EAGAIN: -# endif // EWOULDBLOCK != EAGAIN -#endif // def EAGAIN - -#ifdef EPROTO - case EPROTO: -#endif // def EPROTO - -#ifdef EINPROGRESS - case EINPROGRESS: -#endif // def EINPROGRESS - -#ifdef EALREADY - case EALREADY: -#endif // def EALREADY - - Dbg2() << __PRETTY_FUNCTION__ << " err: " << err - << " return nonFatalError " << nonFatalError << std::endl; - return nonFatalError; - - default: - break; - } - - Dbg2() << __PRETTY_FUNCTION__ << " err: " << err << " return fatalError " - << fatalError << std::endl; - - return fatalError; -} - -#endif // ndef OPENSSL_NO_SOCK diff --git a/libretroshare/src/tcponudp/rsudpstack.h b/libretroshare/src/tcponudp/rsudpstack.h deleted file mode 100644 index 77c25692c..000000000 --- a/libretroshare/src/tcponudp/rsudpstack.h +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: rsudpstack.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef RS_UDP_STACK_RECEIVER_H -#define RS_UDP_STACK_RECEIVER_H - -#ifdef RS_USE_BITDHT - -#include "udp/udpstack.h" - - -#else - -class UdpStack -{ - public: - UdpStack(int testmode, struct sockaddr_in &local) { return; } - UdpStack(struct sockaddr_in &local) { return; } - - /* from pqiNetListener */ -virtual bool resetAddress(struct sockaddr_in &local) { return false; } - -}; - -#endif -/*******************************************************/ - -#include "pqi/pqimonitor.h" -#include "util/rsnet.h" -#include "util/stacktrace.h" - -#include - -class rsUdpStack: public UdpStack, public pqiNetListener -{ -public: - rsUdpStack(struct sockaddr_in &local) : UdpStack(local) {} - - rsUdpStack(int testmode, struct sockaddr_in &local) : - UdpStack(testmode, local) {} - - /// @see pqiNetListener - virtual bool resetListener(const sockaddr_storage& local) - { - sockaddr_storage temp; - sockaddr_storage_copy(local, temp); - - if (!sockaddr_storage_ipv6_to_ipv4(temp)) - { - std::cerr << __PRETTY_FUNCTION__ << " Got non IPv4 address ERROR" - << std::endl; - sockaddr_storage_dump(local); - print_stacktrace(); - return -EINVAL; - } - - sockaddr_in *addr = reinterpret_cast(&temp); - return resetAddress(*addr); - } -}; - -class rsFixedUdpStack: public UdpStack, public pqiNetListener -{ - public: - rsFixedUdpStack(struct sockaddr_in &local) - :UdpStack(local) { return; } - - rsFixedUdpStack(int testmode, struct sockaddr_in &local) - :UdpStack(testmode, local) { return; } - - /* from pqiNetListener */ -virtual bool resetListener(const struct sockaddr_storage & /* local */) - { - struct sockaddr_in addr; - getLocalAddress(addr); - - // The const_cast below is not so nice but without it, the compiler can't - // find the correct operator<<(). No idea why! - //std::cerr << "rsFixedUdpStack::resetListener(" << sockaddr_storage_tostring(local) << ")"; - //std::cerr << " Resetting with original addr: " << const_cast(addr); - //std::cerr << std::endl; - - return resetAddress(addr); - } - -}; - -#endif diff --git a/libretroshare/src/tcponudp/tcppacket.cc b/libretroshare/src/tcponudp/tcppacket.cc deleted file mode 100644 index 2da199288..000000000 --- a/libretroshare/src/tcponudp/tcppacket.cc +++ /dev/null @@ -1,262 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: tcppacket.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "tcppacket.h" - -/* - * #include - */ - -#include "util/rsnet.h" /* for winsock.h -> htons etc */ - -#include -#include -#include - -#include - -/* NOTE That these BIT #defines will only - * work on little endian machines.... - * due to the ntohs ... - */ - -/* flags 16bit is: - * - * || 0 1 2 3 | 4 5 6 7 || 8 9 | 10 11 12 13 14 15 || - * <- HLen -> <--- unused ---> <---- flags -------> - * URG PSH SYN - * ACK RST FIN - * - * - * So in little endian world. - * 0 & 1 -> unused... - * URG -> bit 2 => 0x0004 - * ACK -> bit 3 => 0x0008 - * PSH -> bit 4 => 0x0010 - * RST -> bit 5 => 0x0020 - * SYN -> bit 6 => 0x0040 - * FIN -> bit 7 => 0x0080 - * - * and second byte 0-3 -> hlen, 4-7 unused. - */ - -#define TCP_URG_BIT 0x0004 -#define TCP_ACK_BIT 0x0008 -#define TCP_PSH_BIT 0x0010 -#define TCP_RST_BIT 0x0020 -#define TCP_SYN_BIT 0x0040 -#define TCP_FIN_BIT 0x0080 - - -TcpPacket::TcpPacket(uint8 *ptr, int size) - :data(0), datasize(0), seqno(0), ackno(0), hlen_flags(0), - winsize(0), ts(0), retrans(0) - { - if (size > 0) - { - datasize = size; - data = (uint8 *) rs_malloc(datasize); - - if(data != NULL) - memcpy(data, (void *) ptr, size); - } - return; - } - -TcpPacket::TcpPacket() /* likely control packet */ - :data(0), datasize(0), seqno(0), ackno(0), hlen_flags(0), - winsize(0), ts(0), retrans(0) - { - return; - } - - -TcpPacket::~TcpPacket() - { - if (data) - free(data); - } - - -int TcpPacket::writePacket(void *buf, int &size) -{ - if (size < TCP_PSEUDO_HDR_SIZE + datasize) - { - size = 0; - return -1; - } - - /* byte: 0 => uint16 srcport = 0 */ - *((uint16 *) &(((uint8 *) buf)[0])) = htons(0); - - /* byte: 2 => uint16 destport = 0 */ - *((uint16 *) &(((uint8 *) buf)[2])) = htons(0); - - /* byte: 4 => uint32 seqno */ - *((uint32 *) &(((uint8 *) buf)[4])) = htonl(seqno); - - /* byte: 8 => uint32 ackno */ - *((uint32 *) &(((uint8 *) buf)[8])) = htonl(ackno); - - /* byte: 12 => uint16 len + flags */ - *((uint16 *) &(((uint8 *) buf)[12])) = htons(hlen_flags); - - /* byte: 14 => uint16 winsize */ - *((uint16 *) &(((uint8 *) buf)[14])) = htons(winsize); - - /* byte: 16 => uint16 chksum */ - *((uint16 *) &(((uint8 *) buf)[16])) = htons(0); - - /* byte: 18 => uint16 urgptr */ - *((uint16 *) &(((uint8 *) buf)[18])) = htons(0); - - /* total 20 bytes */ - - /* now the data */ - memcpy((void *) &(((uint8 *) buf)[20]), data, datasize); - - return size = TCP_PSEUDO_HDR_SIZE + datasize; -} - - -int TcpPacket::readPacket(void *buf, int size) -{ - if (size < TCP_PSEUDO_HDR_SIZE) - { - std::cerr << "TcpPacket::readPacket() Failed Too Small!"; - std::cerr << std::endl; - return -1; - } - - /* byte: 0 => uint16 srcport = 0 ******************* - *((uint16 *) &(((uint8 *) buf)[0])) = htons(0); - ***********/ - - /* byte: 2 => uint16 destport = 0 ****************** - *((uint16 *) &(((uint8 *) buf)[2])) = htons(0); - ***********/ - - /* byte: 4 => uint32 seqno */ - seqno = ntohl( *((uint32 *) &(((uint8 *) buf)[4])) ); - - /* byte: 8 => uint32 ackno */ - ackno = ntohl( *((uint32 *) &(((uint8 *) buf)[8])) ); - - /* byte: 12 => uint16 len + flags */ - hlen_flags = ntohs( *((uint16 *) &(((uint8 *) buf)[12])) ); - - /* byte: 14 => uint16 winsize */ - winsize = ntohs( *((uint16 *) &(((uint8 *) buf)[14])) ); - - /* byte: 16 => uint16 chksum ************************* - *((uint16 *) &(((uint8 *) buf)[16])) = htons(0); - ***********/ - - /* byte: 18 => uint16 urgptr ************************* - *((uint16 *) &(((uint8 *) buf)[18])) = htons(0); - ***********/ - - /* total 20 bytes */ - - if (data) - { - free(data); - data = NULL ; - } - datasize = size - TCP_PSEUDO_HDR_SIZE; - - // this happens for control packets (e.g. syn/ack/fin) - if(datasize == 0) - { - // data is already NULL - // just return packet size - return size; - } - - data = (uint8 *) rs_malloc(datasize); - - if(data == NULL) - { - // malloc failed! - // return 0 to drop packet (will be retransmitted eventually) - return 0 ; - } - - /* now the data */ - memcpy(data, (void *) &(((uint8 *) buf)[20]), datasize); - - return size; -} - - /* flags */ -bool TcpPacket::hasSyn() -{ - return (hlen_flags & TCP_SYN_BIT); -} - -bool TcpPacket::hasFin() -{ - return (hlen_flags & TCP_FIN_BIT); -} - -bool TcpPacket::hasAck() -{ - return (hlen_flags & TCP_ACK_BIT); -} - -bool TcpPacket::hasRst() -{ - return (hlen_flags & TCP_RST_BIT); -} - - -void TcpPacket::setSyn() -{ - hlen_flags |= TCP_SYN_BIT; -} - -void TcpPacket::setFin() -{ - hlen_flags |= TCP_FIN_BIT; -} - -void TcpPacket::setRst() -{ - hlen_flags |= TCP_RST_BIT; -} - -void TcpPacket::setAckFlag() -{ - hlen_flags |= TCP_ACK_BIT; -} - -void TcpPacket::setAck(uint32 val) -{ - setAckFlag(); - ackno = val; -} - -uint32 TcpPacket::getAck() -{ - return ackno; -} - - diff --git a/libretroshare/src/tcponudp/tcppacket.h b/libretroshare/src/tcponudp/tcppacket.h deleted file mode 100644 index e87c3e394..000000000 --- a/libretroshare/src/tcponudp/tcppacket.h +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: tcppacket.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef TOU_TCP_PACKET_H -#define TOU_TCP_PACKET_H - -#include - - -typedef unsigned int uint32; -typedef unsigned short uint16; -typedef unsigned char uint8; - -#define TCP_PSEUDO_HDR_SIZE 20 - -class TcpPacket -{ - public: - - uint8 *data; - int datasize; - - - /* ports aren't needed -> in udp - * uint16 srcport, destport - **************************/ - uint32 seqno, ackno; - uint16 hlen_flags; - uint16 winsize; - /* don't need these -> in udp + not supported - uint16 chksum, urgptr; - **************************/ - /* no options. - **************************/ - - - /* other variables */ - double ts; /* transmit time */ - uint16 retrans; /* retransmit counter */ - - TcpPacket(uint8 *ptr, int size); - TcpPacket(); /* likely control packet */ - ~TcpPacket(); - -int writePacket(void *buf, int &size); -int readPacket(void *buf, int size); - -void *getData(); -void *releaseData(); - -void *setData(void *data, int size); -int getDataSize(); - - /* flags */ -bool hasSyn(); -bool hasFin(); -bool hasAck(); -bool hasRst(); - -void setSyn(); -void setFin(); -void setRst(); -void setAckFlag(); - -void setAck(uint32 val); -uint32 getAck(); - - -}; - - -#endif - diff --git a/libretroshare/src/tcponudp/tcpstream.cc b/libretroshare/src/tcponudp/tcpstream.cc deleted file mode 100644 index 439f98854..000000000 --- a/libretroshare/src/tcponudp/tcpstream.cc +++ /dev/null @@ -1,2792 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: tcpstream.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include - -#include "tcpstream.h" -#include -#include -#include -#include -#include -#include - -#include -#include "util/rstime.h" - -/* Debugging for STATE change, and Startup SYNs */ -#include "util/rsdebug.h" -#include "util/rsstring.h" -#include "util/rsrandom.h" - -static struct RsLog::logInfo rstcpstreamzoneInfo = {RsLog::Default, "rstcpstream"}; -#define rstcpstreamzone &rstcpstreamzoneInfo - -/* - * #define DEBUG_TCP_STREAM 1 - * #define DEBUG_TCP_STREAM_RETRANS 1 - * #define DEBUG_TCP_STREAM_CLOSE 1 - */ - -//#define DEBUG_TCP_STREAM_RETRANS 1 -//#define DEBUG_TCP_STREAM_CLOSE 1 - -/* - *#define DEBUG_TCP_STREAM_EXTRA 1 - */ - -/* - * #define TCP_NO_PARTIAL_READ 1 - */ - -#ifdef DEBUG_TCP_STREAM -int checkData(uint8 *data, int size, int idx); -int setupBinaryCheck(std::string fname); -#endif - -static const uint32 kMaxQueueSize = 300; // Was 100, which means max packet size of 100k (smaller than max packet size). -static const uint32 kMaxPktRetransmit = 10; -static const uint32 kMaxSynPktRetransmit = 100; // 100 => 200secs = over 3 minutes startup -static const int TCP_STD_TTL = 64; -static const int TCP_DEFAULT_FIREWALL_TTL = 4; - -static const double RTT_ALPHA = 0.875; - -int dumpPacket(std::ostream &out, unsigned char *pkt, uint32_t size); - -// platform independent fractional timestamp. -static double getCurrentTS(); - -TcpStream::TcpStream(UdpSubReceiver *lyr) - : tcpMtx("TcpStream"), inSize(0), outSizeRead(0), outSizeNet(0), - state(TCP_CLOSED), - inStreamActive(false), - outStreamActive(false), - outSeqno(0), outAcked(0), outWinSize(0), - inAckno(0), inWinSize(0), - maxWinSize(TCP_MAX_WIN), - keepAliveTimeout(TCP_ALIVE_TIMEOUT), - retransTimerOn(false), - retransTimeout(TCP_RETRANS_TIMEOUT), - retransTimerTs(0), - keepAliveTimer(0), - lastIncomingPkt(0), - lastSentAck(0), - lastSentWinSize(0), - initOurSeqno(0), - initPeerSeqno(0), - lastWriteTF(0),lastReadTF(0), - wcount(0), rcount(0), - errorState(0), - /* retranmission variables - init to large */ - rtt_est(TCP_RETRANS_TIMEOUT), - rtt_dev(0), - congestThreshold(TCP_MAX_WIN), - congestWinSize(MAX_SEG), - congestUpdate(0), - ttl(0), - mTTL_period(0), - mTTL_start(0), - mTTL_end(0), - peerKnown(false), - udp(lyr) -{ - sockaddr_clear(&peeraddr); - - return; -} - -/* Stream Control! */ -int TcpStream::connect(const struct sockaddr_in &raddr, uint32_t conn_period) -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - setRemoteAddress(raddr); - - /* check state */ - if (state != TCP_CLOSED) - { - if (state == TCP_ESTABLISHED) - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return 0; - } - else if (state < TCP_ESTABLISHED) - { - errorState = EAGAIN; - } - else - { - // major issues! - errorState = EFAULT; - } - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return -1; - } - - /* setup Seqnos */ - outSeqno = genSequenceNo(); - initOurSeqno = outSeqno; - - outAcked = outSeqno; /* min - 1 expected */ - inWinSize = maxWinSize; - - congestThreshold = TCP_MAX_WIN; - congestWinSize = MAX_SEG; - congestUpdate = outAcked + congestWinSize; - - /* Init Connection */ - /* send syn packet */ - TcpPacket *pkt = new TcpPacket(); - pkt -> setSyn(); - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::connect() Send Init Pkt" << std::endl; -#endif - - - /* ********* SLOW START ************* - * As this is the only place where a syn - * is sent ..... we switch the ttl to 0, - * and increment it as we retransmit the packet.... - * This should help the firewalls along. - */ - - setTTL(1); - - mTTL_start = getCurrentTS(); - mTTL_period = conn_period; - mTTL_end = mTTL_start + mTTL_period; - - toSend(pkt); - /* change state */ - state = TCP_SYN_SENT; - errorState = EAGAIN; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream STATE -> TCP_SYN_SENT" << std::endl; -#endif - { - rslog(RSL_WARNING,rstcpstreamzone,"TcpStream::state => TCP_SYN_SENT (Connect)"); - } - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return -1; -} - - -int TcpStream::listenfor(const struct sockaddr_in &raddr) -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - setRemoteAddress(raddr); - - /* check state */ - if (state != TCP_CLOSED) - { - if (state == TCP_ESTABLISHED) - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return 0; - } - else if (state < TCP_ESTABLISHED) - { - errorState = EAGAIN; - } - else - { - // major issues! - errorState = EFAULT; - } - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return -1; - } - - errorState = EAGAIN; - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return -1; -} - - -/* Stream Control! */ -int TcpStream::close() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - cleanup(); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return 0; -} - -int TcpStream::closeWrite() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - /* check state */ - /* will always close socket.... */ - /* if in TCP_ESTABLISHED.... - * -> to state: TCP_FIN_WAIT_1 - * and shutdown outward stream. - */ - - /* if in CLOSE_WAIT.... - * -> to state: TCP_LAST_ACK - * and shutdown outward stream. - * do this one first!. - */ - - outStreamActive = false; - - if (state == TCP_CLOSE_WAIT) - { - /* don't think we need to be - * graceful at this point... - * connection already closed by other end. - * XXX might fix later with scheme - * - * flag stream closed, and when outqueue - * emptied then fin will be sent. - */ - - /* do nothing */ - } - - if (state == TCP_ESTABLISHED) - { - /* fire off the damned thing. */ - /* by changing state */ - - /* again this is handled by internals - * the flag however indicates that - * no more data can be send, - * and once the queue empties - * the FIN will be sent. - */ - - } - if (state == TCP_CLOSED) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::close() Flag Set" << std::endl; -#endif - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return 0; - } - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::close() pending" << std::endl; -#endif - errorState = EAGAIN; - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return -1; -} - -bool TcpStream::isConnected() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - bool isConn = (state == TCP_ESTABLISHED); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return isConn; -} - -int TcpStream::status(std::ostream &out) -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - int s = status_locked(out); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return s; -} - - -int TcpStream::status_locked(std::ostream &out) -{ - - int tmpstate = state; - - // can leave the timestamp here as time()... rough but okay. - out << "TcpStream::status @ (" << time(NULL) << ")" << std::endl; - out << "TcpStream::state = " << (int) state << std::endl; - out << std::endl; - out << "writeBuffer: " << inSize << " + MAX_SEG * " << inQueue.size(); - out << " bytes Queued for transmission" << std::endl; - out << "readBuffer: " << outSizeRead << " + MAX_SEG * "; - out << outQueue.size() << " + " << outSizeNet; - out << " incoming bytes waiting" << std::endl; - out << std::endl; - out << "inPkts: " << inPkt.size() << " packets waiting for processing"; - out << std::endl; - out << "outPkts: " << outPkt.size() << " packets waiting for acks"; - out << std::endl; - out << "us -> peer: nextSeqno: " << outSeqno << " lastAcked: " << outAcked; - out << " winsize: " << outWinSize; - out << std::endl; - out << "peer -> us: Expected SeqNo: " << inAckno; - out << " winsize: " << inWinSize; - out << std::endl; - out << std::endl; - - return tmpstate; -} - -int TcpStream::write_allowed() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - int ret = 1; - if (state == TCP_CLOSED) - { - errorState = EBADF; - ret = -1; - } - else if (state < TCP_ESTABLISHED) - { - errorState = EAGAIN; - ret = -1; - } - else if (!outStreamActive) - { - errorState = EBADF; - ret = -1; - } - - if (ret < 1) - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return ret; - } - - int maxwrite = (kMaxQueueSize - inQueue.size()) * MAX_SEG; - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return maxwrite; -} - -int TcpStream::read_pending() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - /* error should be detected next time */ - int maxread = int_read_pending(); - if (state == TCP_CLOSED) - { - errorState = EBADF; - maxread = -1; - } - else if (state < TCP_ESTABLISHED) - { - errorState = EAGAIN; - maxread = -1; - } - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return maxread; -} - -/* INTERNAL */ -int TcpStream::int_read_pending() -{ - return outSizeRead + outQueue.size() * MAX_SEG + outSizeNet; -} - - - /* stream Interface */ -int TcpStream::write(char *dta, int size) /* write -> pkt -> net */ -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - int ret = 1; /* initial error checking */ - -#ifdef DEBUG_TCP_STREAM_EXTRA -static uint32 TMPtotalwrite = 0; -#endif - - if (state == TCP_CLOSED) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::write() Error TCP_CLOSED" << std::endl; -#endif - errorState = EBADF; - ret = -1; - } - else if (state < TCP_ESTABLISHED) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::write() Error TCP Not Established" << std::endl; -#endif - errorState = EAGAIN; - ret = -1; - } - else if (inQueue.size() > kMaxQueueSize) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::write() Error EAGAIN" << std::endl; -#endif - errorState = EAGAIN; - ret = -1; - } - else if (!outStreamActive) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::write() Error TCP_CLOSED" << std::endl; -#endif - errorState = EBADF; - ret = -1; - } - - if (ret < 1) /* check for initial error */ - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return ret; - } - - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() = Will Succeed " << size << std::endl; - std::cerr << "TcpStream::write() Write Start: " << TMPtotalwrite << std::endl; - std::cerr << printPktOffset(TMPtotalwrite, dta, size) << std::endl; - TMPtotalwrite += size; -#endif - - - if (size + inSize < MAX_SEG) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() Add Itty Bit" << std::endl; - std::cerr << "TcpStream::write() inData: " << (void *) inData; - std::cerr << " inSize: " << inSize << " dta: " << (void *) dta; - std::cerr << " size: " << size << " dest: " << (void *) &(inData[inSize]); - std::cerr << std::endl; -#endif -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::write() = " << size << std::endl; -#endif - memcpy((void *) &(inData[inSize]), dta, size); - inSize += size; - //std::cerr << "Small Packet - write to net:" << std::endl; - //std::cerr << printPkt(dta, size) << std::endl; - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return size; - } - - /* otherwise must construct a dataBuffer. - */ - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() filling 1 dataBuffer" << std::endl; - std::cerr << "TcpStream::write() from inData(" << inSize << ")" << std::endl; - std::cerr << "TcpStream::write() + dta(" << MAX_SEG - inSize; - std::cerr << "/" << size << ")" << std::endl; -#endif - - /* first create 1. */ - dataBuffer *db = new dataBuffer; - memcpy((void *) db->data, (void *) inData, inSize); - - - int remSize = size; - memcpy((void *) &(db->data[inSize]), dta, MAX_SEG - inSize); - - inQueue.push_back(db); - remSize -= (MAX_SEG - inSize); - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() remaining " << remSize << " bytes to load" << std::endl; -#endif - - while(remSize >= MAX_SEG) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() filling whole dataBuffer" << std::endl; - std::cerr << "TcpStream::write() from dta[" << size-remSize << "]" << std::endl; -#endif - db = new dataBuffer; - memcpy((void *) db->data, (void *) &(dta[size-remSize]), MAX_SEG); - - inQueue.push_back(db); - remSize -= MAX_SEG; - } - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::write() = " << size << std::endl; -#endif - - if (remSize > 0) - { - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() putting last bit in inData" << std::endl; - std::cerr << "TcpStream::write() from dta[" << size-remSize << "] size: "; - std::cerr << remSize << std::endl; -#endif - memcpy((void *) inData, (void *) &(dta[size-remSize]), remSize); - inSize = remSize; - } - else - { - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() Data fitted exactly in dataBuffer!" << std::endl; -#endif - inSize = 0; - } - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return size; -} - -int TcpStream::read(char *dta, int size) /* net -> pkt -> read */ -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - -#ifdef DEBUG_TCP_STREAM_EXTRA -static uint32 TMPtotalread = 0; -#endif - /* max available data is - * outDataRead + outQueue + outDataNet - */ - - int maxread = outSizeRead + outQueue.size() * MAX_SEG + outSizeNet; - int ret = 1; /* used only for initial errors */ - - if (state == TCP_CLOSED) - { - errorState = EBADF; - ret = -1; - } - else if (state < TCP_ESTABLISHED) - { - errorState = EAGAIN; - ret = -1; - } - else if ((!inStreamActive) && (maxread == 0)) - { - // finished stream. - ret = 0; - } - else if (maxread == 0) - { - /* must wait for more data */ - errorState = EAGAIN; - ret = -1; - } - - if (ret < 1) /* if ret has been changed */ - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return ret; - } - - if (maxread < size) - { -#ifdef TCP_NO_PARTIAL_READ - if (inStreamActive) - { - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::read() No Partial Read! "; - std::cerr << "Can only supply " << maxread << " of "; - std::cerr << size; - std::cerr << std::endl; -#endif - errorState = EAGAIN; - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return -1; - } -#endif /* TCP_NO_PARTIAL_READ */ - size = maxread; - } - - /* if less than outDataRead size */ - if (((unsigned) (size) < outSizeRead) && (outSizeRead)) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() Add Itty Bit" << std::endl; - std::cerr << "TcpStream::read() outSizeRead: " << outSizeRead; - std::cerr << " size: " << size << " remaining: " << outSizeRead - size; - std::cerr << std::endl; -#endif - memcpy(dta,(void *) outDataRead, size); - memmove((void *) outDataRead, - (void *) &(outDataRead[size]), outSizeRead - (size)); - outSizeRead -= size; - - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() = Succeeded " << size << std::endl; - std::cerr << "TcpStream::read() Read Start: " << TMPtotalread << std::endl; - std::cerr << printPktOffset(TMPtotalread, dta, size) << std::endl; -#endif - -#ifdef DEBUG_TCP_STREAM_EXTRA - checkData((uint8 *) dta, size, TMPtotalread); - TMPtotalread += size; -#endif - - /* can allow more in! - update inWinSize */ - UpdateInWinSize(); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return size; - } - - /* move the whole of outDataRead. */ - if (outSizeRead) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() Move All outSizeRead" << std::endl; - std::cerr << "TcpStream::read() outSizeRead: " << outSizeRead; - std::cerr << " size: " << size; - std::cerr << std::endl; -#endif - memcpy(dta,(void *) outDataRead, outSizeRead); - - } - - int remSize = size - outSizeRead; - outSizeRead = 0; - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() remaining size: " << remSize << std::endl; -#endif - - while((outQueue.size() > 0) && (remSize > 0)) - { - dataBuffer *db = outQueue.front(); - outQueue.pop_front(); /* remove */ - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() Taking Data from outQueue" << std::endl; -#endif - - /* load into outDataRead */ - if (remSize < MAX_SEG) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() Partially using Segment" << std::endl; - std::cerr << "TcpStream::read() moving: " << remSize << " to dta @: " << size-remSize; - std::cerr << std::endl; - std::cerr << "TcpStream::read() rest to outDataRead: " << MAX_SEG - remSize; - std::cerr << std::endl; -#endif - memcpy((void *) &(dta[(size)-remSize]), (void *) db->data, remSize); - memcpy((void *) outDataRead, (void *) &(db->data[remSize]), MAX_SEG - remSize); - outSizeRead = MAX_SEG - remSize; - - delete db; - - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() = Succeeded " << size << std::endl; - std::cerr << "TcpStream::read() Read Start: " << TMPtotalread << std::endl; - std::cerr << printPktOffset(TMPtotalread, dta, size) << std::endl; -#endif - -#ifdef DEBUG_TCP_STREAM_EXTRA - checkData((uint8 *) dta, size, TMPtotalread); - TMPtotalread += size; -#endif - - /* can allow more in! - update inWinSize */ - UpdateInWinSize(); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return size; - } -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() Move Whole Segment to dta @ " << size-remSize << std::endl; -#endif - - /* else copy whole segment */ - memcpy((void *) &(dta[(size)-remSize]), (void *) db->data, MAX_SEG); - remSize -= MAX_SEG; - delete db; - } - - /* assumes that outSizeNet >= remSize due to initial - * constraint - */ - if ((remSize > 0)) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() Using up : " << remSize; - std::cerr << " last Bytes, leaving: " << outSizeNet - remSize << std::endl; -#endif - - - memcpy((void *) &(dta[(size)-remSize]),(void *) outDataNet, remSize); - outSizeNet -= remSize; - if (outSizeNet > 0) - { - /* move to the outDataRead */ - memcpy((void *) outDataRead,(void *) &(outDataNet[remSize]), outSizeNet); - outSizeRead = outSizeNet; - outSizeNet = 0; -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() moving last of outSizeNet to outSizeRead: " << outSizeRead; - std::cerr << std::endl; -#endif - - } - - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() = Succeeded " << size << std::endl; - std::cerr << "TcpStream::read() Read Start: " << TMPtotalread << std::endl; - std::cerr << printPktOffset(TMPtotalread, dta, size) << std::endl; -#endif - -#ifdef DEBUG_TCP_STREAM_EXTRA - checkData((uint8 *) dta, size, TMPtotalread); - TMPtotalread += size; -#endif - - /* can allow more in! - update inWinSize */ - UpdateInWinSize(); - - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return size; - } - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() = Succeeded " << size << std::endl; - std::cerr << "TcpStream::read() Read Start: " << TMPtotalread << std::endl; - std::cerr << printPktOffset(TMPtotalread, dta, size) << std::endl; -#endif - -#ifdef DEBUG_TCP_STREAM_EXTRA - checkData((uint8 *) dta, size, TMPtotalread); - TMPtotalread += size; -#endif - - /* can allow more in! - update inWinSize */ - UpdateInWinSize(); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return size; -} - - - /* Callback from lower Layers */ -void TcpStream::recvPkt(void *data, int size) -{ -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::recvPkt()"; - std::cerr << std::endl; -#endif - - tcpMtx.lock(); /********** LOCK MUTEX *********/ - uint8 *input = (uint8 *) data; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::recvPkt() Past Lock!"; - std::cerr << std::endl; -#endif - -#ifdef DEBUG_TCP_STREAM - if (state > TCP_SYN_RCVD) - { - int availRead = outSizeRead + outQueue.size() * MAX_SEG + outSizeNet; - std::cerr << "TcpStream::recvPkt() CC: "; - std::cerr << " iWS: " << inWinSize; - std::cerr << " aRead: " << availRead; - std::cerr << " iAck: " << inAckno; - std::cerr << std::endl; - } - else - { - std::cerr << "TcpStream::recv() Not Connected"; - std::cerr << std::endl; - } -#endif - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::recv() ReadPkt(" << size << ")" << std::endl; - //std::cerr << printPkt(input, size); - //std::cerr << std::endl; -#endif - TcpPacket *pkt = new TcpPacket(); - if (0 < pkt -> readPacket(input, size)) - { - lastIncomingPkt = getCurrentTS(); - handleIncoming(pkt); - } - else - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::recv() Bad Packet Deleting!"; - std::cerr << std::endl; -#endif - delete pkt; - } - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return; -} - - -int TcpStream::tick() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - //std::cerr << "TcpStream::tick()" << std::endl; - recv_check(); /* recv is async */ - send(); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return 1; -} - -bool TcpStream::getRemoteAddress(struct sockaddr_in &raddr) -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - if (peerKnown) - { - raddr = peeraddr; - } - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return peerKnown; -} - -uint8 TcpStream::TcpState() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - uint8 err = state; - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return err; -} - -int TcpStream::TcpErrorState() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - int err = errorState; - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return err; -} - - - -/********************* SOME EXPOSED DEBUGGING FNS ******************/ - -static int ilevel = 100; - -bool TcpStream::widle() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - /* init */ - if (!lastWriteTF) - { - lastWriteTF = int_wbytes(); - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return false; - } - - if ((lastWriteTF == int_wbytes()) && (inSize == 0) && inQueue.empty()) - { - wcount++; - if (wcount > ilevel) - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return true; - } - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return false; - } - wcount = 0; - lastWriteTF = int_wbytes(); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return false; -} - - -bool TcpStream::ridle() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - /* init */ - if (!lastReadTF) - { - lastReadTF = int_rbytes(); - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return false; - } - - if ((lastReadTF == int_rbytes()) && (outSizeRead + outQueue.size() + outSizeNet== 0)) - { - rcount++; - if (rcount > ilevel) - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return true; - } - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return false; - } - rcount = 0; - lastReadTF = int_rbytes(); - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return false; -} - -uint32 TcpStream::wbytes() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - uint32 wb = int_wbytes(); - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return wb; -} - -uint32 TcpStream::rbytes() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - uint32 rb = int_rbytes(); - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return rb; -} - -/********************* ALL BELOW HERE IS INTERNAL ****************** - ******************* AND ALWAYS PROTECTED BY A MUTEX ***************/ - -int TcpStream::recv_check() -{ - double cts = getCurrentTS(); // fractional seconds. - -#ifdef DEBUG_TCP_STREAM - if (state > TCP_SYN_RCVD) - { - int availRead = outSizeRead + outQueue.size() * MAX_SEG + outSizeNet; - std::cerr << "TcpStream::recv_check() CC: "; - std::cerr << " iWS: " << inWinSize; - std::cerr << " aRead: " << availRead; - std::cerr << " iAck: " << inAckno; - std::cerr << std::endl; - } - else - { - std::cerr << "TcpStream::recv_check() Not Connected"; - std::cerr << std::endl; - } -#endif - - // make sure we've rcvd something! - if ((state > TCP_SYN_RCVD) && - (cts - lastIncomingPkt > kNoPktTimeout)) - { - /* shut it all down */ - /* this period should be equivalent - * to the firewall timeouts ??? - * - * for max efficiency - */ - -#ifdef DEBUG_TCP_STREAM_CLOSE - std::cerr << "TcpStream::recv_check() state = CLOSED (NoPktTimeout)"; - std::cerr << std::endl; - dumpstate_locked(std::cerr); -#endif - - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_CLOSED (kNoPktTimeout)"); - - outStreamActive = false; - inStreamActive = false; - state = TCP_CLOSED; - cleanup(); - } - return 1; -} - -int TcpStream::cleanup() -{ - // This shuts it all down! no matter what. - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::cleanup() state = TCP_CLOSED"); - - outStreamActive = false; - inStreamActive = false; - state = TCP_CLOSED; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream STATE -> TCP_CLOSED" << std::endl; -#endif - - //peerKnown = false; //??? NOT SURE -> for a rapid reconnetion this might be key?? - - /* reset TTL */ - setTTL(TCP_STD_TTL); - - // clear arrays. - inSize = 0; - while(inQueue.size() > 0) - { - dataBuffer *db = inQueue.front(); - inQueue.pop_front(); - delete db; - } - - while(outPkt.size() > 0) - { - TcpPacket *pkt = outPkt.front(); - outPkt.pop_front(); - delete pkt; - } - - - // clear arrays. - outSizeRead = 0; - outSizeNet = 0; - while(outQueue.size() > 0) - { - dataBuffer *db = outQueue.front(); - outQueue.pop_front(); - delete db; - } - - while(inPkt.size() > 0) - { - TcpPacket *pkt = inPkt.front(); - inPkt.pop_front(); - delete pkt; - } - return 1; -} - -int TcpStream::handleIncoming(TcpPacket *pkt) -{ -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::handleIncoming()" << std::endl; -#endif - switch(state) - { - case TCP_CLOSED: - case TCP_LISTEN: - /* if receive SYN - * -> respond SYN/ACK - * To State: SYN_RCVD - * - * else Discard. - */ - return incoming_Closed(pkt); - break; - case TCP_SYN_SENT: - /* if receive SYN - * -> respond SYN/ACK - * To State: SYN_RCVD - * - * if receive SYN+ACK - * -> respond ACK - * To State: TCP_ESTABLISHED - * - * else Discard. - */ - return incoming_SynSent(pkt); - break; - case TCP_SYN_RCVD: - /* if receive ACK - * To State: TCP_ESTABLISHED - */ - return incoming_SynRcvd(pkt); - break; - case TCP_ESTABLISHED: - /* if receive FIN - * -> respond ACK - * To State: TCP_CLOSE_WAIT - * else Discard. - */ - return incoming_Established(pkt); - break; - case TCP_FIN_WAIT_1: - /* state entered by close() call. - * if receive FIN - * -> respond ACK - * To State: TCP_CLOSING - * - * if receive ACK - * -> no response - * To State: TCP_FIN_WAIT_2 - * - * if receive FIN+ACK - * -> respond ACK - * To State: TCP_TIMED_WAIT - * - */ - return incoming_Established(pkt); - //return incoming_FinWait1(pkt); - break; - case TCP_FIN_WAIT_2: - /* if receive FIN - * -> respond ACK - * To State: TCP_TIMED_WAIT - */ - return incoming_Established(pkt); - //return incoming_FinWait2(pkt); - break; - case TCP_CLOSING: - /* if receive ACK - * To State: TCP_TIMED_WAIT - */ - /* all handled in Established */ - return incoming_Established(pkt); - //return incoming_Closing(pkt); - break; - case TCP_CLOSE_WAIT: - /* - * wait for our close to be called. - */ - /* all handled in Established */ - return incoming_Established(pkt); - //return incoming_CloseWait(pkt); - break; - case TCP_LAST_ACK: - /* entered by the local close() after sending FIN. - * if receive ACK - * To State: TCP_CLOSED - */ - /* all handled in Established */ - return incoming_Established(pkt); - /* - return incoming_LastAck(pkt); - */ - - break; - /* this is actually the only - * final state where packets not expected! - */ - case TCP_TIMED_WAIT: - /* State: TCP_TIMED_WAIT - * - * discard all -> both connections FINed - * timeout of this state. - * - */ - -#ifdef DEBUG_TCP_STREAM_CLOSE - std::cerr << "TcpStream::handleIncoming() state = CLOSED (TimedWait)"; - std::cerr << std::endl; - dumpstate_locked(std::cerr); -#endif - - state = TCP_CLOSED; - // return incoming_TimedWait(pkt); - { - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_CLOSED (recvd TCP_TIMED_WAIT?)"); - } - break; - } - delete pkt; - return 1; -} - - -int TcpStream::incoming_Closed(TcpPacket *pkt) -{ - /* if receive SYN - * -> respond SYN/ACK - * To State: SYN_RCVD - * - * else Discard. - */ - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_Closed()" << std::endl; -#endif - if ((pkt -> hasSyn()) && (!pkt -> hasAck())) - { - /* Init Connection */ - - /* save seqno */ - initPeerSeqno = pkt -> seqno; - inAckno = initPeerSeqno + 1; - outWinSize = pkt -> winsize; - - - inWinSize = maxWinSize; - - /* we can get from SynSent as well, - * but only send one SYN packet - */ - - /* start packet */ - TcpPacket *rsp = new TcpPacket(); - - if (state == TCP_CLOSED) - { - outSeqno = genSequenceNo(); - initOurSeqno = outSeqno; - outAcked = outSeqno; /* min - 1 expected */ - - /* setup Congestion Charging */ - congestThreshold = TCP_MAX_WIN; - congestWinSize = MAX_SEG; - congestUpdate = outAcked + congestWinSize; - - rsp -> setSyn(); - } - - rsp -> setAck(inAckno); - /* seq + winsize set in toSend() */ - - /* as we have received something ... we can up the TTL */ - setTTL(TCP_STD_TTL); - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_Closed() Sending reply" << std::endl; - std::cerr << "SeqNo: " << rsp->seqno << " Ack: " << rsp->ackno; - std::cerr << std::endl; -#endif - - toSend(rsp); - /* change state */ - state = TCP_SYN_RCVD; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream STATE -> TCP_SYN_RCVD" << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_SYN_RECVD (recvd SYN & !ACK)"); - } - - delete pkt; - return 1; -} - - -int TcpStream::incoming_SynSent(TcpPacket *pkt) -{ - /* if receive SYN - * -> respond SYN/ACK - * To State: SYN_RCVD - * - * if receive SYN+ACK - * -> respond ACK - * To State: TCP_ESTABLISHED - * - * else Discard. - */ - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_SynSent()" << std::endl; -#endif - - if ((pkt -> hasSyn()) && (pkt -> hasAck())) - { - /* check stuff */ - if (pkt -> getAck() != outSeqno) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_SynSent() Bad Ack - Deleting " << std::endl; -#endif - /* bad ignore */ - delete pkt; - return -1; - } - - /* Complete Connection */ - - /* save seqno */ - initPeerSeqno = pkt -> seqno; - inAckno = initPeerSeqno + 1; - - outWinSize = pkt -> winsize; - - outAcked = pkt -> getAck(); - - /* before ACK, reset the TTL - * As they have sent something, and we have received - * through the firewall, set to STD. - */ - setTTL(TCP_STD_TTL); - - /* ack the Syn Packet */ - sendAck(); - - /* change state */ - state = TCP_ESTABLISHED; - outStreamActive = true; - inStreamActive = true; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream STATE -> TCP_ESTABLISHED" << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_ESTABLISHED (recvd SUN & ACK)"); - - delete pkt; - } - else /* same as if closed! (simultaneous open) */ - { - return incoming_Closed(pkt); - } - return 1; -} - - -int TcpStream::incoming_SynRcvd(TcpPacket *pkt) -{ - /* if receive ACK - * To State: TCP_ESTABLISHED - */ - if (pkt -> hasRst()) - { - /* trouble */ - state = TCP_CLOSED; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream STATE -> TCP_CLOSED" << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_CLOSED (recvd RST)"); - - delete pkt; - return 1; - } - - bool ackWithData = false; - - if (pkt -> hasAck()) - { - if (pkt -> hasSyn()) - { - /* has resent syn -> check it matches */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "incoming_SynRcvd -> Pkt with ACK + SYN" << std::endl; -#endif - } - - /* check stuff */ - if (pkt -> getAck() != outSeqno) - { - /* bad ignore */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "incoming_SynRcvd -> Ignoring Pkt with bad ACK" << std::endl; -#endif - delete pkt; - return -1; - } - - /* Complete Connection */ - - /* save seqno */ - if (pkt -> datasize > 0) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_SynRcvd() ACK with Data!" << std::endl; - std::cerr << "TcpStream::incoming_SynRcvd() Shoudn't recv ... unless initACK lost!" << std::endl; -#endif - // managed to trigger this under windows... - // perhaps the initial Ack was lost, - // believe we should just pass this packet - // directly to the incoming_Established... once - // the following has been done. - // and it should all work! - //exit(1); - ackWithData = true; - } - - inAckno = pkt -> seqno; /* + pkt -> datasize; */ - outWinSize = pkt -> winsize; - - outAcked = pkt -> getAck(); - - - /* As they have sent something, and we have received - * through the firewall, set to STD. - */ - setTTL(TCP_STD_TTL); - - /* change state */ - state = TCP_ESTABLISHED; - outStreamActive = true; - inStreamActive = true; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream STATE -> TCP_ESTABLISHED" << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_ESTABLISHED (have SYN, recvd ACK)"); - } - - if (ackWithData) - { - /* connection Established -> handle normally */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "incoming_SynRcvd -> Handling Data with Ack Pkt!"; - std::cerr << std::endl; -#endif - incoming_Established(pkt); - } - else - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "incoming_SynRcvd -> Ignoring Pkt!" << std::endl; -#endif - /* else nothing */ - delete pkt; - } - return 1; -} - -int TcpStream::incoming_Established(TcpPacket *pkt) -{ - /* first handle the Ack ... - * this must be done before the queue, - * to keep the values as up-to-date as possible. - * - * must sanity check ..... - * make sure that the sequence number is within the correct range. - */ - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_Established() "; - std::cerr << " Pkt->seqno: " << std::hex << pkt->seqno; - std::cerr << " Pkt->datasize: " << std::hex << pkt->datasize; - std::cerr << std::dec << std::endl; -#endif - - if ((!isOldSequence(pkt->seqno, inAckno)) && // seq >= inAckno - isOldSequence(pkt->seqno, inAckno + maxWinSize)) // seq < inAckno + maxWinSize. - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_Established() valid Packet Seqno."; - std::cerr << std::endl; -#endif - if (pkt->hasAck()) - { -#ifdef DEBUG_TCP_STREAM - if (outAcked != pkt->ackno) - { - std::cerr << "TcpStream::incoming_Established() valid Packet Seqno & new Ackno."; - std::cerr << std::endl; - std::cerr << "\tUpdating OutAcked to: " << outAcked; - std::cerr << std::endl; - } -#endif - outAcked = pkt->ackno; - } - - outWinSize = pkt->winsize; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "\tUpdating OutWinSize to: " << outWinSize; - std::cerr << std::endl; -#endif - } - else - { - /* what we do! (This is actually okay - and happens occasionally) */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_Established() ERROR out-of-range Packet Seqno."; - std::cerr << std::endl; - std::cerr << "\t Pkt->SeqNo: " << std::hex << pkt->seqno; - std::cerr << std::endl; - std::cerr << "\t inAckno: " << std::hex << inAckno; - std::cerr << std::endl; - std::cerr << "\t inAckno + maxWinSize: " << std::hex << inAckno + maxWinSize; - std::cerr << std::endl; - std::cerr << "\t outAcked: " << std::hex << outAcked; - std::cerr << std::endl; - std::cerr << "\t Pkt->SeqNo: " << std::hex << pkt->seqno; - std::cerr << std::dec << std::endl; - std::cerr << "\t !isOldSequence(pkt->seqno, inAckno): " << (!isOldSequence(pkt->seqno, inAckno)); - std::cerr << std::endl; - std::cerr << "\t isOldSequence(pkt->seqno, inAckno + maxWinSize): " << isOldSequence(pkt->seqno, inAckno + maxWinSize); - std::cerr << std::endl; - std::cerr << std::endl; - - std::cerr << "TcpStream::incoming_Established() Sending Ack to update Peer"; - std::cerr << std::endl; -#endif - - sendAck(); - } - - - /* add to queue */ - inPkt.push_back(pkt); - - if (inPkt.size() > kMaxQueueSize) - { - TcpPacket *pkt = inPkt.front(); - inPkt.pop_front(); - delete pkt; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_Established() inPkt reached max size...Discarding Oldest Pkt"; - std::cerr << std::endl; -#endif - - } - - /* use as many packets as possible */ - return check_InPkts(); -} - -int TcpStream::check_InPkts() -{ - bool found = true; - TcpPacket *pkt; - std::list::iterator it; - while(found) - { - found = false; - for(it = inPkt.begin(); (!found) && (it != inPkt.end());) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "Checking expInAck: " << std::hex << inAckno; - std::cerr << " vs: " << std::hex << (*it)->seqno << std::dec << std::endl; -#endif - - pkt = *it; - if ((*it)->seqno == inAckno) - { - //std::cerr << "\tFOUND MATCH!"; - //std::cerr << std::endl; - - found = true; - it = inPkt.erase(it); - - } - - /* see if we can discard it */ - /* if smaller seqno, and not wrapping around */ - else if (isOldSequence((*it)->seqno, inAckno)) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "Discarding Old Packet expAck: " << std::hex << inAckno; - std::cerr << " seqno: " << std::hex << (*it)->seqno; - std::cerr << " pkt->size: " << std::hex << (*it)->datasize; - std::cerr << " pkt->seqno+size: " << std::hex << (*it)->seqno + (*it)->datasize; - std::cerr << std::dec << std::endl; -#endif - - /* discard */ - it = inPkt.erase(it); - delete pkt; - - } - else - { - ++it; - } - } - if (found) - { - -#ifdef DEBUG_TCP_STREAM_EXTRA - if (pkt->datasize) - { - checkData(pkt->data, pkt->datasize, pkt->seqno-initPeerSeqno-1); - } -#endif - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::check_inPkts() Updating inAckno from: " << std::hex << inAckno; -#endif - - /* update ack number - let it rollover */ - inAckno = pkt->seqno + pkt->datasize; - -#ifdef DEBUG_TCP_STREAM - std::cerr << " to: " << std::hex << inAckno; - std::cerr << std::dec << std::endl; -#endif - - /* XXX This shouldn't be here, as it prevents - * the Ack being used until the packet is. - * This means that a dropped packet will stop traffic in both - * directions.... - * - * Moved it to incoming_Established .... but extra - * check here to be sure! - */ - - if (pkt->hasAck()) - { - if (isOldSequence(outAcked, pkt->ackno)) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::check_inPkts() ERROR Ack Not Already Used!"; - std::cerr << std::endl; - std::cerr << "\t Pkt->ackno: " << std::hex << pkt->ackno; - std::cerr << std::endl; - std::cerr << "\t outAcked: " << std::hex << outAcked; - std::cerr << std::endl; - std::cerr << "\t Pkt->winsize: " << std::hex << pkt->winsize; - std::cerr << std::endl; - std::cerr << "\t outWinSize: " << std::hex << outWinSize; - std::cerr << std::endl; - std::cerr << "\t isOldSequence(outAcked, pkt->ackno): " << isOldSequence(outAcked, pkt->ackno); - std::cerr << std::endl; - std::cerr << std::endl; -#endif - - outAcked = pkt->ackno; - outWinSize = pkt->winsize; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "\tUpdating OutAcked to: " << outAcked; - std::cerr << std::endl; - std::cerr << "\tUpdating OutWinSize to: " << outWinSize; - std::cerr << std::endl; -#endif - - } - else - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::check_inPkts() GOOD Ack Already Used!"; - std::cerr << std::endl; -#endif - } - } - - /* push onto queue */ - - if (outSizeNet + pkt->datasize < MAX_SEG) - { - /* move onto outSizeNet */ - if (pkt->datasize) - { - memcpy((void *) &(outDataNet[outSizeNet]), pkt->data, pkt->datasize); - outSizeNet += pkt->datasize; - } - } - else - { - /* if it'll overflow the buffer. */ - dataBuffer *db = new dataBuffer(); - - /* move outDatNet -> buffer */ - memcpy((void *) db->data, (void *) outDataNet, outSizeNet); - - /* fill rest of space */ - int remSpace = MAX_SEG - outSizeNet; - memcpy((void *) &(db->data[outSizeNet]), (void *) pkt->data, remSpace); - - /* push packet onto queue */ - outQueue.push_back(db); - - /* any big chunks that will take up a full dataBuffer */ - int remData = pkt->datasize - remSpace; - while(remData >= MAX_SEG) - { - db = new dataBuffer(); - memcpy((void *) db->data, (void *) &(pkt->data[remSpace]), MAX_SEG); - - remData -= MAX_SEG; - outQueue.push_back(db); - } - - /* remove any remaining to outDataNet */ - outSizeNet = remData; - if (outSizeNet > 0) - { - memcpy((void *) outDataNet, (void *) &(pkt->data[pkt->datasize - remData]), outSizeNet); - } - } - - /* can allow more in! - update inWinSize */ - UpdateInWinSize(); - - /* if pkt is FIN */ - /* these must be here -> at the end of the reliable stream */ - /* if the fin is set, ack it specially close stream */ - if (pkt->hasFin()) - { - /* send final ack */ - sendAck(); - - /* closedown stream */ - inStreamActive = false; - - if (state == TCP_ESTABLISHED) - { - state = TCP_CLOSE_WAIT; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_CLOSE_WAIT"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_CLOSE_WAIT (recvd FIN)"); - } - else if (state == TCP_FIN_WAIT_1) - { - state = TCP_CLOSING; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_CLOSING"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_CLOSING (FIN_WAIT_1, recvd FIN)"); - } - else if (state == TCP_FIN_WAIT_2) - { - state = TCP_TIMED_WAIT; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_TIMED_WAIT"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_TIMED_WAIT (FIN_WAIT_2, recvd FIN)"); - - cleanup(); - } - } - - /* if ack for our FIN */ - if ((pkt->hasAck()) && (!outStreamActive) - && (pkt->ackno == outSeqno)) - { - if (state == TCP_FIN_WAIT_1) - { - state = TCP_FIN_WAIT_2; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_FIN_WAIT_2"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_FIN_WAIT_2 (FIN_WAIT_1, recvd ACK)"); - } - else if (state == TCP_LAST_ACK) - { -#ifdef DEBUG_TCP_STREAM_CLOSE - std::cerr << "TcpStream::state = TCP_CLOSED (LastAck)"; - std::cerr << std::endl; - dumpstate_locked(std::cerr); -#endif - - state = TCP_CLOSED; - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_CLOSED (LAST_ACK, recvd ACK)"); - - cleanup(); - } - else if (state == TCP_CLOSING) - { - state = TCP_TIMED_WAIT; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_TIMED_WAIT"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_TIMED_WAIT (TCP_CLOSING, recvd ACK)"); - - cleanup(); - } - } - - delete pkt; - - } /* end of found */ - } /* while(found) */ - return 1; -} - -/* This Fn should be called after each read, or recvd data (thats added to the buffer) - */ -int TcpStream::UpdateInWinSize() -{ - /* InWinSize = maxWinSze - QueuedData, - * actually we can allow a lot more to queue up... - * inWinSize = 65536, unless QueuedData > 65536. - * inWinSize = 2 * maxWinSize - QueuedData; - * - */ - - uint32 queuedData = int_read_pending(); - if (queuedData < maxWinSize) - { - inWinSize = maxWinSize; - } - else if (queuedData < 2 * maxWinSize) - { - inWinSize = 2 * maxWinSize - queuedData; - } - else - { - inWinSize = 0; - } - return inWinSize; -} - -int TcpStream::sendAck() -{ - /* simple -> toSend fills in ack/winsize - * and the rest is history - */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::sendAck()"; - std::cerr << std::endl; -#endif - - return toSend(new TcpPacket(), false); -} - -void TcpStream::setRemoteAddress(const struct sockaddr_in &raddr) -{ - peeraddr = raddr; - peerKnown = true; -} - - -int TcpStream::toSend(TcpPacket *pkt, bool retrans) -{ - int outPktSize = MAX_SEG + TCP_PSEUDO_HDR_SIZE; - char tmpOutPkt[outPktSize]; - - if (!peerKnown) - { - /* Major Error! */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::toSend() peerUnknown ERROR!!!"; - std::cerr << std::endl; -#endif - delete pkt; - return 0; - } - - /* get accurate timestamp */ - double cts = getCurrentTS(); - - pkt -> winsize = inWinSize; - pkt -> seqno = outSeqno; - - /* increment seq no */ - if (pkt->datasize) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - checkData(pkt->data, pkt->datasize, outSeqno-initOurSeqno-1); -#endif - outSeqno += pkt->datasize; - } - - if (pkt->hasSyn()) - { - /* should not have data! */ - if (pkt->datasize) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "SYN Packet shouldn't contain data!" << std::endl; -#endif - } - outSeqno++; - } - else - { - /* cannot auto Ack SynPackets */ - pkt -> setAck(inAckno); - } - - pkt -> winsize = inWinSize; - - /* store old info */ - lastSentAck = pkt -> ackno; - lastSentWinSize = pkt -> winsize; - keepAliveTimer = cts; - - pkt -> writePacket(tmpOutPkt, outPktSize); - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::toSend() Seqno: "; - std::cerr << pkt->seqno << " size: " << pkt->datasize; - std::cerr << " Ackno: "; - std::cerr << pkt->ackno << " winsize: " << pkt->winsize; - std::cerr << std::endl; - //std::cerr << printPkt(tmpOutPkt, outPktSize) << std::endl; -#endif - - udp -> sendPkt(tmpOutPkt, outPktSize, peeraddr, ttl); - - if (retrans) - { - /* restart timers */ - pkt -> ts = cts; - pkt -> retrans = 0; - - startRetransmitTimer(); - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::toSend() Adding to outPkt --> Seqno: "; - std::cerr << pkt->seqno << " size: " << pkt->datasize; - std::cerr << std::endl; -#endif - - outPkt.push_back(pkt); - } - else - { - delete pkt; - } - return 1; -} - - -/* single retransmit timer. - * - */ -void TcpStream::startRetransmitTimer() -{ - if (retransTimerOn) - { - return; - } - - retransTimerTs = getCurrentTS(); - retransTimerOn = true; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::startRetransmitTimer() peer: " << peeraddr; - std::cerr << " retransTimeout: " << retransTimeout; - std::cerr << " retransTimerTs: " << std::setprecision(12) < TCP_RETRANS_MAX_TIMEOUT) - { - retransTimeout = TCP_RETRANS_MAX_TIMEOUT; - } - -#ifdef DEBUG_TCP_STREAM_RETRANS - std::cerr << "TcpStream::incRetransmitTimer() peer: " << peeraddr; - std::cerr << " retransTimeout: " << std::setprecision(12) << retransTimeout; - std::cerr << std::endl; -#endif - -} - - - - - -int TcpStream::retrans() -{ - int outPktSize = MAX_SEG + TCP_PSEUDO_HDR_SIZE; - char tmpOutPkt[outPktSize]; - - if (!peerKnown) - { - /* Major Error! */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::retrans() peerUnknown ERROR!!!"; - std::cerr << std::endl; -#endif - return 0; - } - - if (!retransTimerOn) - { - return 0; - } - - double cts = getCurrentTS(); - if (cts - retransTimerTs < retransTimeout) - { - return 0; - } - - if (outPkt.begin() == outPkt.end()) - { - resetRetransmitTimer(); - return 0; - } - - TcpPacket *pkt = outPkt.front(); - - if (!pkt) - { - /* error */ - return 0; - } - - /* retransmission -> adjust the congestWinSize and congestThreshold - */ - - congestThreshold = congestWinSize / 2; - congestWinSize = MAX_SEG; - congestUpdate = outAcked + congestWinSize; // point when we can up the winSize. - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::retrans() Adjusting Congestion Parameters: "; - std::cerr << std::endl; - std::cerr << "\tcongestWinSize: " << congestWinSize; - std::cerr << " congestThreshold: " << congestThreshold; - std::cerr << " congestUpdate: " << congestUpdate; - std::cerr << std::endl; -#endif - - /* update ackno and winsize */ - if (!(pkt->hasSyn())) - { - pkt->setAck(inAckno); - lastSentAck = pkt -> ackno; - } - - pkt->winsize = inWinSize; - lastSentWinSize = pkt -> winsize; - - keepAliveTimer = cts; - - pkt->writePacket(tmpOutPkt, outPktSize); - -#ifdef DEBUG_TCP_STREAM_RETRANS - std::cerr << "TcpStream::retrans()"; - std::cerr << " peer: " << peeraddr; - std::cerr << " hasSyn: " << pkt->hasSyn(); - std::cerr << " Seqno: "; - std::cerr << pkt->seqno << " size: " << pkt->datasize; - std::cerr << " Ackno: "; - std::cerr << pkt->ackno << " winsize: " << pkt->winsize; - std::cerr << " retrans: " << (int) pkt->retrans; - std::cerr << " timeout: " << std::setprecision(12) << retransTimeout; - std::cerr << std::endl; - - //std::cerr << printPkt(tmpOutPkt, outPktSize) << std::endl; -#endif - - /* if its a syn packet ** thats been - * transmitting for a while, maybe - * we should increase the ttl. - */ - - if ((pkt->hasSyn()) && (getTTL() < TCP_STD_TTL)) - { - /* calculate a new TTL */ - if (mTTL_end > cts) - { - setTTL(TCP_DEFAULT_FIREWALL_TTL); - } - else - { - setTTL(getTTL() + 1); - } - - std::string out; - rs_sprintf(out, "TcpStream::retrans() Startup SYNs retrans count: %u New TTL: %d", pkt->retrans, getTTL()); - - rslog(RSL_WARNING, rstcpstreamzone, out); - -#ifdef DEBUG_TCP_STREAM - std::cerr << out.str() << std::endl; -#endif - } - - /* catch excessive retransmits - * - Allow Syn case more.... - * - if not SYN or TTL has reached STD then timeout quickly. - - * OLD 2nd Logic (below) has been replaced with lower logic. - * (((!pkt->hasSyn()) || (TCP_STD_TTL == getTTL())) - * && (pkt->retrans > kMaxPktRetransmit))) - * Problem was that the retransmit of Syn packet had STD_TTL, and was triggering Close (and SeqNo change). - * It seemed to work anyway.... But might cause coonnection failures. Will reduce the MaxSyn Retransmit - * so something more reasonable as well. - * ((!pkt->hasSyn()) && (pkt->retrans > kMaxPktRetransmit))) - */ - - if ((pkt->hasSyn() && (pkt->retrans > kMaxSynPktRetransmit)) || - ((!pkt->hasSyn()) && (pkt->retrans > kMaxPktRetransmit))) - - { - - /* too many attempts close stream */ -#ifdef DEBUG_TCP_STREAM_CLOSE - std::cerr << "TcpStream::retrans() Too many Retransmission Attempts ("; - std::cerr << (int) pkt->retrans << ") for Peer: " << peeraddr << std::endl; - std::cerr << "TcpStream::retrans() Closing Socket Connection"; - std::cerr << std::endl; - - //dumpPacket(std::cerr, (unsigned char *) tmpOutPkt, outPktSize); - dumpstate_locked(std::cerr); -#endif - - rslog(RSL_WARNING,rstcpstreamzone,"TcpStream::state => TCP_CLOSED (Too Many Retransmits)"); - - outStreamActive = false; - inStreamActive = false; - state = TCP_CLOSED; - cleanup(); - return 0; - } - - - udp -> sendPkt(tmpOutPkt, outPktSize, peeraddr, ttl); - - /* restart timers */ - pkt->ts = cts; - pkt->retrans++; - - /* - * finally - double the retransTimeout ... (Karn's Algorithm) - * except if we are starting a connection... i.e. hasSyn() - */ - - if (!pkt->hasSyn()) - { - incRetransmitTimeout(); - restartRetransmitTimer(); - } - else - { - resetRetransmitTimer(); - startRetransmitTimer(); - } - - return 1; -} - - -void TcpStream::acknowledge() -{ - /* cleans up acknowledge packets */ - /* packets are pushed back in order */ - std::list::iterator it; - double cts = getCurrentTS(); - bool updateRTT = true; - bool clearedPkts = false; - - for(it = outPkt.begin(); (it != outPkt.end()) && - (isOldSequence((*it)->seqno, outAcked)); - it = outPkt.erase(it)) - { - TcpPacket *pkt = (*it); - clearedPkts = true; - - /* adjust the congestWinSize and congestThreshold - * congestUpdate <= outAcked - * - ***/ - - if (!isOldSequence(outAcked, congestUpdate)) - { - if (congestWinSize < congestThreshold) - { - /* double it baby! */ - congestWinSize *= 2; - } - else - { - /* linear increase */ - congestWinSize += MAX_SEG; - } - - if (congestWinSize > maxWinSize) - { - congestWinSize = maxWinSize; - } - - congestUpdate = outAcked + congestWinSize; // point when we can up the winSize. - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::acknowledge() Adjusting Congestion Parameters: "; - std::cerr << std::endl; - std::cerr << "\tcongestWinSize: " << congestWinSize; - std::cerr << " congestThreshold: " << congestThreshold; - std::cerr << " congestUpdate: " << congestUpdate; - std::cerr << std::endl; -#endif - } - - - /* update the RoundTripTime, - * using Jacobson's values. - * RTT = a RTT + (1-a) M - * where - * RTT is RoundTripTime estimate. - * a = 7/8, - * M = time for ack. - * - * D = a D + (1 - a) | RTT - M | - * where - * D is approx Deviation. - * a,RTT & M are the same as above. - * - * Timeout = RTT + 4 * D. - * - * And Karn's Algorithm... - * which says - * (1) do not update RTT or D for retransmitted packets. - * + the ones that follow .... (the ones whos ack was - * delayed by the retranmission) - * (2) double timeout, when packets fail. (done in retrans). - */ - - if (pkt->retrans) - { - updateRTT = false; - } - - if (updateRTT) /* can use for RTT calc */ - { - double ack_time = cts - pkt->ts; - rtt_est = RTT_ALPHA * rtt_est + (1.0 - RTT_ALPHA) * ack_time; - rtt_dev = RTT_ALPHA * rtt_dev + (1.0 - RTT_ALPHA) * fabs(rtt_est - ack_time); - retransTimeout = rtt_est + 4.0 * rtt_dev; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::acknowledge() Updating RTT: "; - std::cerr << std::endl; - std::cerr << "\tAckTime: " << ack_time; - std::cerr << std::endl; - std::cerr << "\tRRT_est: " << rtt_est; - std::cerr << std::endl; - std::cerr << "\tRTT_dev: " << rtt_dev; - std::cerr << std::endl; - std::cerr << "\tTimeout: " << retransTimeout; - std::cerr << std::endl; -#endif - } - -#ifdef DEBUG_TCP_STREAM - else - { - std::cerr << "TcpStream::acknowledge() Not Updating RTT for retransmitted Pkt Sequence"; - std::cerr << std::endl; - } -#endif - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::acknowledge() Removing Seqno: "; - std::cerr << pkt->seqno << " size: " << pkt->datasize; - std::cerr << std::endl; -#endif - delete pkt; - } - - /* This is triggered if we have recieved acks for retransmitted packets.... - * In this case we want to reset the timeout, and remove the doubling. - * - * If we don't do this, and there have been more dropped packets, - * the the timeout gets continually doubled. which will virtually stop - * all communication. - * - * This will effectively trigger the retransmission of the next dropped packet. - */ - - /* - * if have acked all data - resetRetransTimer() - */ - - if (it == outPkt.end()) - { - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::acknowledge() peer: " << peeraddr; - std::cerr << " Backlog cleared, resetRetransmitTimer"; - std::cerr << std::endl; -#endif - resetRetransmitTimer(); - } - else if (clearedPkts) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::acknowledge() peer: " << peeraddr; - std::cerr << " Cleared some packets -> resetRetransmitTimer + start"; - std::cerr << std::endl; -#endif - resetRetransmitTimer(); - startRetransmitTimer(); - } - return; -} - - -int TcpStream::send() -{ - /* handle network interface always */ - /* clean up as much as possible */ - acknowledge(); - /* send any old packets */ - retrans(); - - - if (state < TCP_ESTABLISHED) - { - return -1; - } - - /* get the inQueue, can send */ - - - /* determine exactly how much we can send */ - uint32 maxsend = congestWinSize; - uint32 inTransit; - - if (outWinSize < congestWinSize) - { - maxsend = outWinSize; - } - - if (outSeqno < outAcked) - { - inTransit = (TCP_MAX_SEQ - outAcked) + outSeqno; - } - else - { - inTransit = outSeqno - outAcked; - } - - if (maxsend > inTransit) - { - maxsend -= inTransit; - } - else - { - maxsend = 0; - } - -#ifdef DEBUG_TCP_STREAM - int availSend = inQueue.size() * MAX_SEG + inSize; - std::cerr << "TcpStream::send() CC: "; - std::cerr << "oWS: " << outWinSize; - std::cerr << " cWS: " << congestWinSize; - std::cerr << " | inT: " << inTransit; - std::cerr << " mSnd: " << maxsend; - std::cerr << " aSnd: " << availSend; - std::cerr << " | oSeq: " << outSeqno; - std::cerr << " oAck: " << outAcked; - std::cerr << " cUpd: " << congestUpdate; - std::cerr << std::endl; -#endif - - int sent = 0; - while((inQueue.size() > 0) && (maxsend >= MAX_SEG)) - { - dataBuffer *db = inQueue.front(); - inQueue.pop_front(); - - TcpPacket *pkt = new TcpPacket(db->data, MAX_SEG); -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::send() Segment ===> Seqno: "; - std::cerr << pkt->seqno << " size: " << pkt->datasize; - std::cerr << std::endl; -#endif - sent++; - maxsend -= MAX_SEG; - toSend(pkt); - delete db; - } - - /* if inqueue empty, and enough window space, send partial stuff */ - if ((!sent) && (inQueue.empty()) && (maxsend >= inSize) && (inSize)) - { - TcpPacket *pkt = new TcpPacket(inData, inSize); -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::send() Remaining ===>"; - std::cerr << std::endl; -#endif - inSize = 0; - sent++; - maxsend -= inSize; - toSend(pkt); - } - - /* if send nothing */ - bool needsAck = false; - - if (!sent) - { - double cts = getCurrentTS(); - /* if needs ack */ - if (isOldSequence(lastSentAck,inAckno)) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::send() Ack Triggered (Ackno)"; - std::cerr << std::endl; -#endif - needsAck = true; - } - - /* if needs window - * if added enough space for packet, or - * (this case is equivalent to persistence timer) - * haven't sent anything for a while, and the - * window size has drastically increased. - * */ - if (((lastSentWinSize < MAX_SEG) && (inWinSize > MAX_SEG)) || - ((cts - keepAliveTimer > retransTimeout * 4) && - (inWinSize > lastSentWinSize + 4 * MAX_SEG))) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::send() Ack Triggered (Window)"; - std::cerr << std::endl; -#endif - needsAck = true; - } - - /* if needs keepalive */ - if (cts - keepAliveTimer > keepAliveTimeout) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::send() Ack Triggered (KAlive)"; - std::cerr << std::endl; -#endif - needsAck = true; - } - - - /* if end of stream -> switch mode -> send fin (with ack) */ - if ((!outStreamActive) && (inQueue.size() + inSize == 0) && - ((state == TCP_ESTABLISHED) || (state == TCP_CLOSE_WAIT))) - { - /* finish the stream */ - TcpPacket *pkt = new TcpPacket(); - pkt -> setFin(); - - needsAck = false; - toSend(pkt, false); - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::send() Fin Triggered"; - std::cerr << std::endl; -#endif - - if (state == TCP_ESTABLISHED) - { - state = TCP_FIN_WAIT_1; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_FIN_WAIT_1"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_FIN_WAIT_1 (End of Stream)"); - } - else if (state == TCP_CLOSE_WAIT) - { - state = TCP_LAST_ACK; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_LAST_ACK"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_LAST_ACK (CLOSE_WAIT, End of Stream)"); - } - - } - - if (needsAck) - { - sendAck(); - } -#ifdef DEBUG_TCP_STREAM_EXTRA - else - { - std::cerr << "TcpStream::send() No Ack"; - std::cerr << std::endl; - } -#endif - } -#ifdef DEBUG_TCP_STREAM_EXTRA - else - { - std::cerr << "TcpStream::send() Stuff Sent"; - std::cerr << std::endl; - } -#endif - return 1; -} - - -uint32 TcpStream::genSequenceNo() -{ - return RSRandom::random_u32(); - //return 1000; // TCP_MAX_SEQ - 1000; //1000; //(rand() - 100000) + time(NULL) % 100000; - //return (rand() - 100000) + time(NULL) % 100000; - -} - - -bool TcpStream::isOldSequence(uint32 tst, uint32 curr) -{ - return ((int)((tst)-(curr)) < 0); - - std::cerr << "TcpStream::isOldSequence(): Case "; - /* if tst < curr */ - if ((int)((tst)-(curr)) < 0) - { - if (curr - tst < TCP_MAX_SEQ/2) /* diff less than half span -> old */ - { - std::cerr << "1T" << std::endl; - return true; - } - std::cerr << "2F" << std::endl; - return false; - } - else if ((tst - curr) > TCP_MAX_SEQ/2) - { - std::cerr << "3T: tst-curr:" << (tst-curr) << std::endl; - return true; - } - std::cerr << "4F: tst-curr:" << (tst-curr) << std::endl; - return false; -} - -#ifdef WINDOWS_SYS -#include "util/rstime.h" -#include -#endif - -// Little fn to get current timestamp in an independent manner. -static double getCurrentTS() -{ - -#ifndef WINDOWS_SYS - struct timeval cts_tmp; - gettimeofday(&cts_tmp, NULL); - double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; -#else - struct _timeb timebuf; - _ftime( &timebuf); - double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; -#endif - return cts; -} - - - -uint32 TcpStream::int_wbytes() -{ - return outSeqno - initOurSeqno - 1; -} - -uint32 TcpStream::int_rbytes() -{ - return inAckno - initPeerSeqno - 1; -} - - - - -/********* Special debugging stuff *****/ - -#ifdef DEBUG_TCP_STREAM_EXTRA - -#include - -static FILE *bc_fd = 0; -int setupBinaryCheck(std::string fname) -{ - bc_fd = RsDirUtil::rs_fopen(fname.c_str(), "r"); - return 1; -} - -/* uses seq number to track position -> ensure no rollover */ -int checkData(uint8 *data, int size, int idx) -{ - if (bc_fd <= 0) - { - return -1; - } - std::cerr << "checkData(" << idx << "+" << size << ")"; - - int tmpsize = size; - uint8 tmpdata[tmpsize]; - if (-1 == fseek(bc_fd, idx, SEEK_SET)) - { - std::cerr << "Fseek Issues!" << std::endl; - exit(1); - return -1; - } - - if (1 != fread(tmpdata, tmpsize, 1, bc_fd)) - { - std::cerr << "Length Difference!" << std::endl; - exit(1); - return -1; - } - - for(int i = 0; i < size; i++) - { - if (data[i] != tmpdata[i]) - { - std::cerr << "Byte Difference!" << std::endl; - exit(1); - return -1; - } - } - std::cerr << "OK" << std::endl; - return 1; -} - -#endif - - -/***** Dump state of TCP Stream - to workout why it was closed ****/ -int TcpStream::dumpstate_locked(std::ostream &out) -{ - out << "TcpStream::dumpstate()"; - out << "======================================================="; - - out << std::endl; - out << "state: " << (int) state; - out << " errorState: " << (int) errorState; - out << std::endl; - - out << "(Streams) inStreamActive: " << inStreamActive; - out << " outStreamActive: " << outStreamActive; - out << std::endl; - - out << "(Timeouts) maxWinSize: " << maxWinSize; - out << " keepAliveTimeout: " << keepAliveTimeout; - out << " retransTimeout: " << retransTimeout; - out << std::endl; - - out << "(Timers) keepAliveTimer: " << std::setprecision(12) << keepAliveTimer; - out << " lastIncomingPkt: " << std::setprecision(12) << lastIncomingPkt; - out << std::endl; - - out << "(Tracking) lastSendAck: " << lastSentAck; - out << " lastSendWinSize: " << lastSentWinSize; - out << std::endl; - - out << "(Init) initOutSeqno: " << initOurSeqno; - out << " initPeerSeqno: " << initPeerSeqno; - out << std::endl; - - out << "(r/w) lastWriteTF: " << lastWriteTF; - out << " lastReadTF: " << lastReadTF; - out << " wcount: " << wcount; - out << " rcount: " << rcount; - out << std::endl; - - out << "(rtt) rtt_est: " << rtt_est; - out << " rtt_dev: " << rtt_dev; - out << std::endl; - - out << "(congestion) congestThreshold: " << congestThreshold; - out << " congestWinSize: " << congestWinSize; - out << " congestUpdate: " << congestUpdate; - out << std::endl; - - out << "(TTL) mTTL_period: " << mTTL_period; - out << " mTTL_start: " << std::setprecision(12) << mTTL_start; - out << " mTTL_end: " << std::setprecision(12) << mTTL_end; - out << std::endl; - - out << "(Peer) peerKnown: " << peerKnown; - out << " peerAddr: " << peeraddr; - out << std::endl; - - out << "-------------------------------------------------------"; - out << std::endl; - status_locked(out); - out << "======================================================="; - out << std::endl; - - return 1; -} - - -int TcpStream::dumpstate(std::ostream &out) -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - dumpstate_locked(out); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return 1; -} - - -int dumpPacket(std::ostream &out, unsigned char *pkt, uint32_t size) -{ - uint32_t i; - - out << "dumpPacket() Size: " << size; - out << std::endl; - out << "------------------------------------------------------"; - for(i = 0; i < size; i++) - { - if (i % 16 == 0) - { - out << std::endl; - } - out << std::hex << std::setfill('0') << std::setw(2) << (int) pkt[i] << ":"; - } - if ((i - 1) % 16 != 0) - { - out << std::endl; - } - out << "------------------------------------------------------"; - out << std::dec << std::endl; - - return 1; -} - - diff --git a/libretroshare/src/tcponudp/tcpstream.h b/libretroshare/src/tcponudp/tcpstream.h deleted file mode 100644 index 87ed693d0..000000000 --- a/libretroshare/src/tcponudp/tcpstream.h +++ /dev/null @@ -1,266 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: tcpstream.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef TOU_TCP_PROTO_H -#define TOU_TCP_PROTO_H - - -/* so the packet will contain - * a tcp header + data. - * - * This is done simplistically for speed. - */ - -#include "tcppacket.h" -#include "udppeer.h" - -// WINDOWS doesn't like UDP packets bigger than 1492 (truncates them). -// We have up to 64 bytes of headers: 28(udp) + 16(relay) + 20(tou) = 64 bytes. -// 64 bytes + 1400 = 1464, leaves a small margin, but close to maximum throughput. -//#define MAX_SEG 1400 -// We are going to start at 1000 (to avoid any fragmentation, and work up). -#define MAX_SEG 1000 - -#define TCP_MAX_SEQ UINT_MAX -#define TCP_MAX_WIN 65500 -#define TCP_ALIVE_TIMEOUT 15 /* 15 sec ... < 20 sec UDP state limit on some firewalls */ -#define TCP_RETRANS_TIMEOUT 1 /* 1 sec (Initial value) */ -#define TCP_RETRANS_MAX_TIMEOUT 15 /* 15 secs */ -#define kNoPktTimeout 60 /* 1 min */ - - -#define TCP_CLOSED 0 -#define TCP_LISTEN 1 -#define TCP_SYN_SENT 2 -#define TCP_SYN_RCVD 3 -#define TCP_ESTABLISHED 4 -#define TCP_FIN_WAIT_1 5 -#define TCP_FIN_WAIT_2 6 -#define TCP_TIMED_WAIT 7 -#define TCP_CLOSING 8 -#define TCP_CLOSE_WAIT 9 -#define TCP_LAST_ACK 10 - -class dataBuffer -{ - public: - uint8 data[MAX_SEG]; -}; - -#include -#include - - -class TcpStream: public UdpPeer -{ - public: - /* Top-Level exposed */ - - TcpStream(UdpSubReceiver *udp); -virtual ~TcpStream() { return; } - - /* user interface */ -int status(std::ostream &out); -int connect(const struct sockaddr_in &raddr, uint32_t conn_period); -int listenfor(const struct sockaddr_in &raddr); -bool isConnected(); - - /* get tcp information */ -bool getRemoteAddress(struct sockaddr_in &raddr); -uint8 TcpState(); -int TcpErrorState(); - - /* stream Interface */ -int write(char *dta, int size); /* write -> pkt -> net */ -int read(char *dta, int size); /* net -> pkt -> read */ - - /* check ahead for allowed bytes */ -int write_allowed(); -int read_pending(); - -int closeWrite(); /* non-standard, but for clean exit */ -int close(); /* standard unix behaviour */ - -int tick(); /* check iface etc */ - - /* Callback Funcion from UDP Layers */ -virtual void recvPkt(void *data, int size); /* overloaded */ - - - - /* Exposed Data Counting */ -bool widle(); /* write idle */ -bool ridle(); /* read idle */ -uint32 wbytes(); -uint32 rbytes(); - - /* Exposed for debugging */ -int dumpstate(std::ostream &out); - - private: - - /* Internal Functions - use the Mutex (not reentrant) */ - /* Internal Functions - that don't need mutex protection */ - -uint32 genSequenceNo(); -bool isOldSequence(uint32 tst, uint32 curr); - - RsMutex tcpMtx; - - /* Internal Functions - only called inside mutex protection */ - -int dumpstate_locked(std::ostream &out); -int status_locked(std::ostream &out); - -int cleanup(); - -/* incoming data */ -int recv_check(); -int handleIncoming(TcpPacket *pkt); -int incoming_Closed(TcpPacket *pkt); -int incoming_SynSent(TcpPacket *pkt); -int incoming_SynRcvd(TcpPacket *pkt); -int incoming_Established(TcpPacket *pkt); -int incoming_FinWait1(TcpPacket *pkt); -int incoming_FinWait2(TcpPacket *pkt); -int incoming_TimedWait(TcpPacket *pkt); -int incoming_Closing(TcpPacket *pkt); -int incoming_CloseWait(TcpPacket *pkt); -int incoming_LastAck(TcpPacket *pkt); -int check_InPkts(); -int UpdateInWinSize(); -int int_read_pending(); - -/* outgoing data */ -int send(); -int toSend(TcpPacket *pkt, bool retrans = true); -void acknowledge(); -int retrans(); -int sendAck(); -void setRemoteAddress(const struct sockaddr_in &raddr); - -int getTTL() { return ttl; } -void setTTL(int t) { ttl = t; } - -/* retransmission */ -void startRetransmitTimer(); -void restartRetransmitTimer(); -void stopRetransmitTimer(); -void resetRetransmitTimer(); -void incRetransmitTimeout(); - - -/* data counting */ -uint32 int_wbytes(); -uint32 int_rbytes(); - - /* Internal Data - must have mutex to access! */ - - /* data (in -> pkts) && (pkts -> out) */ - - /* for small amounts of data */ - uint8 inData[MAX_SEG]; - uint32 inSize; - - - /* two variable sized buffers required here */ - uint8 outDataRead[MAX_SEG]; - uint32 outSizeRead; - uint8 outDataNet[MAX_SEG]; - uint32 outSizeNet; - - /* get packed into here as size increases */ - std::deque inQueue, outQueue; - - /* packets waiting for acks */ - std::list inPkt, outPkt; - - - uint8 state; /* stream state */ - bool inStreamActive; - bool outStreamActive; - - uint32 outSeqno; /* next out */ - uint32 outAcked; /* other size has received */ - uint32 outWinSize; /* we allowed to send */ - - uint32 inAckno; /* next expected */ - uint32 inWinSize; /* allowing other to send */ - - /* some (initially) consts */ - uint32 maxWinSize; - uint32 keepAliveTimeout; - - /* retransmit */ - bool retransTimerOn; - double retransTimeout; - double retransTimerTs; - - /* some timers */ - double keepAliveTimer; - double lastIncomingPkt; - - /* tracking */ - uint32 lastSentAck; - uint32 lastSentWinSize; - uint32 initOurSeqno; - uint32 initPeerSeqno; - - uint32 lastWriteTF,lastReadTF; - uint16 wcount, rcount; - - int errorState; - - /* RoundTripTime estimations */ - double rtt_est; - double rtt_dev; - - /* congestion limits */ - uint32 congestThreshold; - uint32 congestWinSize; - uint32 congestUpdate; - - /* existing TTL for this stream (tweaked at startup) */ - int ttl; - - double mTTL_period; - double mTTL_start; - double mTTL_end; - - struct sockaddr_in peeraddr; - bool peerKnown; - - /* UdpSubReceiver (has own Mutex!) */ - UdpSubReceiver *udp; - -}; - - -/* for debugging */ - -#ifdef TCP_DEBUG_STREAM_EXTRA /* for extra checking! */ -int setupBinaryCheck(std::string fname); -#endif - - - -#endif - diff --git a/libretroshare/src/tcponudp/tou.cc b/libretroshare/src/tcponudp/tou.cc deleted file mode 100644 index 96c8797d9..000000000 --- a/libretroshare/src/tcponudp/tou.cc +++ /dev/null @@ -1,663 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: tou.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "tou.h" - -static const int kInitStreamTable = 5; - -#include -#include -#include -#include -#include - -#include "util/rstime.h" -#include "udp/udpstack.h" -#include "pqi/pqinetwork.h" -#include "tcpstream.h" -#include "util/stacktrace.h" - -#define DEBUG_TOU_INTERFACE 1 -#define EUSERS 87 - -struct TcpOnUdp_t -{ - int tou_fd; - int lasterrno; - TcpStream *tcp; - UdpSubReceiver *udpsr; - int udptype; - bool idle; -}; - -typedef struct TcpOnUdp_t TcpOnUdp; - -static RsMutex touMutex("touMutex"); -// Mutex is used to control addition / removals from tou_streams. -// Lookup should be okay - as long as you stick to your allocated ID! - -static std::vector tou_streams; - -static int tou_inited = 0; - - -#include "tcponudp/udppeer.h" -#include "tcponudp/udprelay.h" - -static UdpSubReceiver *udpSR[MAX_TOU_RECEIVERS] = {NULL}; -static uint32_t udpType[MAX_TOU_RECEIVERS] = { 0 }; -static uint32_t noUdpSR = 0; - -/* tou_init - * - * Modified to accept a number of UdpSubRecievers! - * these can be linked to arbitary UdpStacks. - * (removed all UdpStack references here!) - * - * Unfortunately, the UdpSubReceivers have different initialisation for starting a connection. - * So the TOU interface has to accomodate this. - * - */ -/* tou_init - opens the udp port (universal bind) */ -int tou_init(void **in_udpsubrecvs, int *type, int number) -{ - RsStackMutex stack(touMutex); /***** LOCKED ******/ - - UdpSubReceiver **usrArray = (UdpSubReceiver **) in_udpsubrecvs; - if (number > MAX_TOU_RECEIVERS) - { - std::cerr << "tou_init() Invalid number of receivers"; - std::cerr << std::endl; - return 0; - } - - if (tou_inited) - { - return 1; - } - - noUdpSR = number; - uint32_t i; - for(i = 0; i < noUdpSR; i++) - { - udpSR[i] = usrArray[i]; - udpType[i] = type[i]; - } - - tou_streams.resize(kInitStreamTable); - - tou_inited = 1; - return 1; -} - - -/* open - allocates a sockfd, and checks that the type is okay */ -int tou_socket(uint32_t recvIdx, uint32_t type, int /*protocol*/) -{ - RsStackMutex stack(touMutex); /***** LOCKED ******/ - - if (!tou_inited) - { - return -1; - } - - if (recvIdx >= noUdpSR) - { - std::cerr << "tou_socket() ERROR recvIdx greater than #receivers"; - std::cerr << std::endl; - return -1; - } - - /* check that the index matches the type */ - UdpSubReceiver *recver = udpSR[recvIdx]; - uint32_t recverType = udpType[recvIdx]; - - if (recverType != type) - { - std::cerr << "tou_socket() ERROR type doesn't match expected type"; - std::cerr << std::endl; - return -1; - } - - for(unsigned int i = 1; i < tou_streams.size(); i++) - { - if (tou_streams[i] == NULL) - { - tou_streams[i] = new TcpOnUdp(); - tou_streams[i] -> tou_fd = i; - tou_streams[i] -> tcp = NULL; - tou_streams[i] -> udpsr = recver; - tou_streams[i] -> udptype = recverType; - return i; - } - } - - TcpOnUdp *tou = new TcpOnUdp(); - - tou_streams.push_back(tou); - - if (tou == tou_streams[tou_streams.size() -1]) - { - tou -> tou_fd = tou_streams.size() -1; - tou -> tcp = NULL; - tou -> udpsr = recver; - tou -> udptype = recverType; - return tou->tou_fd; - } - - tou -> lasterrno = EUSERS; - - return -1; -} - - -bool tou_stream_check(int sockfd) -{ - if(sockfd < 0) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR sockfd: " << sockfd - << " < 0" << std::endl; - print_stacktrace(); - return false; - } - - if(sockfd >= tou_streams.size()) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR sockfd: " << sockfd - << " out of bound!" << std::endl; - print_stacktrace(); - return false; - } - - if(!tou_streams[sockfd]) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR tou_streams[sockfd] == NULL" - << std::endl; - print_stacktrace(); - return false; - } - - return true; -} - -/* bind - opens the udp port */ -int tou_bind(int sockfd, const struct sockaddr * /* my_addr */, socklen_t /* addrlen */ ) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - /* this now always returns an error! */ - tous -> lasterrno = EADDRINUSE; - return -1; -} - -/* records peers address, and sends syn pkt - * the timeout is very slow initially - to give - * the peer a chance to startup - * - * - like a tcp/ip connection, the connect - * will return -1 EAGAIN, until connection complete. - * - always non blocking. - */ -int tou_connect(int sockfd, const struct sockaddr *serv_addr, - socklen_t addrlen, uint32_t conn_period) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - - if (addrlen < sizeof(struct sockaddr_in)) - { - std::cerr << "tou_connect() ERROR invalid size of sockaddr"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - // only IPv4 for the moment. - const struct sockaddr_storage *ss_addr = (struct sockaddr_storage *) serv_addr; - if (ss_addr->ss_family != AF_INET) - { - std::cerr << "tou_connect() ERROR not ipv4"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - /* enforce that the udptype is correct */ - if (tous -> udptype != TOU_RECEIVER_TYPE_UDPPEER) - { - std::cerr << "tou_connect() ERROR connect method invalid for udptype"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - -#ifdef TOU_DYNAMIC_CAST_CHECK - /* extra checking -> for testing purposes (dynamic cast) */ - UdpPeerReceiver *upr = dynamic_cast(tous->udpsr); - if (!upr) - { - std::cerr << "tou_connect() ERROR cannot convert type to UdpPeerReceiver"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } -#else - UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr); -#endif - - /* create a TCP stream to connect with. */ - if (!tous->tcp) - { - tous->tcp = new TcpStream(tous->udpsr); - upr->addUdpPeer(tous->tcp, - *((const struct sockaddr_in *) serv_addr)); - } - - tous->tcp->connect(*(const struct sockaddr_in *) serv_addr, conn_period); - tous->tcp->tick(); - if (tous->tcp->isConnected()) - { - return 0; - } - - tous -> lasterrno = EINPROGRESS; - return -1; -} - -/* is this ever used? should it be depreciated? */ -int tou_listenfor(int sockfd, const struct sockaddr *serv_addr, - socklen_t addrlen) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - if (addrlen < sizeof(struct sockaddr_in)) - { - std::cerr << "tou_listenfor() ERROR invalid size of sockaddr"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - // only IPv4 for the moment. - const struct sockaddr_storage *ss_addr = (struct sockaddr_storage *) serv_addr; - if (ss_addr->ss_family != AF_INET) - { - std::cerr << "tou_listenfor() ERROR not ipv4"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - - /* enforce that the udptype is correct */ - if (tous -> udptype != TOU_RECEIVER_TYPE_UDPPEER) - { - std::cerr << "tou_connect() ERROR connect method invalid for udptype"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - -#ifdef TOU_DYNAMIC_CAST_CHECK - /* extra checking -> for testing purposes (dynamic cast) */ - UdpPeerReceiver *upr = dynamic_cast(tous->udpsr); - if (!upr) - { - std::cerr << "tou_connect() ERROR cannot convert type to UdpPeerReceiver"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } -#else - UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr); -#endif - - /* create a TCP stream to connect with. */ - if (!tous->tcp) - { - tous->tcp = new TcpStream(tous->udpsr); - upr->addUdpPeer(tous->tcp, - *((const struct sockaddr_in *) serv_addr)); - } - - tous->tcp->listenfor(*((struct sockaddr_in *) serv_addr)); - tous->tcp->tick(); - - return 0; -} - -int tou_listen(int /* sockfd */ , int /* backlog */ ) -{ - return 1; -} - -/* - * This is the alternative RELAY connection. - * - * User needs to provide 3 ip addresses. - * These addresses should have been provided by the RELAY negogiation - * a) own ip:port - * b) proxy ip:port - * c) dest ip:port - * - * The reset of the startup is similar to other TOU connections. - * As this is likely to be run over an established UDP connection, - * there is little need for a big connection period. - * - * - like a tcp/ip connection, the connect - * will return -1 EAGAIN, until connection complete. - * - always non blocking. - */ -#define DEFAULT_RELAY_CONN_PERIOD 1 - -int tou_connect_via_relay( int sockfd, const sockaddr_in& own_addr, - const sockaddr_in& proxy_addr, - const sockaddr_in& dest_addr ) - -{ - std::cerr << __PRETTY_FUNCTION__ << std::endl; - - if (!tou_stream_check(sockfd)) return -EINVAL; - - TcpOnUdp& tous = *tou_streams[sockfd]; - - /* enforce that the udptype is correct */ - if (tous.udptype != TOU_RECEIVER_TYPE_UDPRELAY) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR connect method invalid for " - << "udptype" << std::endl; - tous.lasterrno = EINVAL; - return -EINVAL; - } - - UdpRelayReceiver* urr_ptr = dynamic_cast(tous.udpsr); - if(!urr_ptr) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR cannot convert to " - << "UdpRelayReceiver" << std::endl; - tous.lasterrno = EINVAL; - return -EINVAL; - } - - UdpRelayReceiver& urr = *urr_ptr; urr_ptr = nullptr; - - /* create a TCP stream to connect with. */ - if (!tous.tcp) - { - tous.tcp = new TcpStream(tous.udpsr); - - UdpRelayAddrSet addrSet(&own_addr, &dest_addr); - urr.addUdpPeer(tous.tcp, &addrSet, &proxy_addr); - } - - /* We Point it at the Destination Address. - * The UdpRelayReceiver wraps and re-directs the packets to the proxy - */ - tous.tcp->connect(dest_addr, DEFAULT_RELAY_CONN_PERIOD); - tous.tcp->tick(); - if (tous.tcp->isConnected()) return 0; - - tous.lasterrno = EINPROGRESS; - return -EINPROGRESS; -} - - - /* slightly different - returns sockfd on connection */ -int tou_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - if (*addrlen < sizeof(struct sockaddr_in)) - { - std::cerr << "tou_accept() ERROR invalid size of sockaddr"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - // only IPv4 for the moment. - const struct sockaddr_storage *ss_addr = (struct sockaddr_storage *) addr; - if (ss_addr->ss_family != AF_INET) - { - std::cerr << "tou_accept() ERROR not ipv4"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - //tous->tcp->connect(); - tous->tcp->tick(); - if (tous->tcp->isConnected()) - { - // should get remote address - tous->tcp->getRemoteAddress(*((struct sockaddr_in *) addr)); - return sockfd; - } - - tous -> lasterrno = EAGAIN; - return -1; -} - - -int tou_connected(int sockfd) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - tous->tcp->tick(); - - return (tous->tcp->TcpState() == 4); -} - - -/* standard stream read/write non-blocking of course - */ - -ssize_t tou_read(int sockfd, void *buf, size_t count) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - tous->tcp->tick(); - - int err = tous->tcp->read((char *) buf, count); - if (err < 0) - { - tous->lasterrno = tous->tcp->TcpErrorState(); - return -1; - } - return err; -} - -ssize_t tou_write(int sockfd, const void *buf, size_t count) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - - int err = tous->tcp->write((char *) buf, count); - if (err < 0) - { - tous->lasterrno = tous->tcp->TcpErrorState(); - tous->tcp->tick(); - return -1; - } - tous->tcp->tick(); - return err; -} - - /* check stream */ -int tou_maxread(int sockfd) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - tous->tcp->tick(); - - int ret = tous->tcp->read_pending(); - if (ret < 0) - { - tous->lasterrno = tous->tcp->TcpErrorState(); - return 0; // error detected next time. - } - return ret; -} - -int tou_maxwrite(int sockfd) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - tous->tcp->tick(); - - int ret = tous->tcp->write_allowed(); - if (ret < 0) - { - tous->lasterrno = tous->tcp->TcpErrorState(); - return 0; // error detected next time? - } - return ret; -} - - -/* close down the tcp over udp connection */ -int tou_close(int sockfd) -{ - TcpOnUdp *tous = NULL; - { - RsStackMutex stack(touMutex); /***** LOCKED ******/ - if (!tou_stream_check(sockfd)) - { - return -1; - } - tous = tou_streams[sockfd]; - tou_streams[sockfd] = NULL; - } - - if (tous->tcp) - { - tous->tcp->tick(); - - /* shut it down */ - tous->tcp->close(); - - /* now we need to work out which type of receiver we have */ -#ifdef TOU_DYNAMIC_CAST_CHECK - /* extra checking -> for testing purposes (dynamic cast) */ - UdpRelayReceiver *urr = dynamic_cast(tous->udpsr); - UdpPeerReceiver *upr = dynamic_cast(tous->udpsr); - if (urr) - { - urr->removeUdpPeer(tous->tcp); - } - else if (upr) - { - upr->removeUdpPeer(tous->tcp); - } - else - { - /* error */ - std::cerr << "tou_close() ERROR unknown udptype"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - } -#else - if (tous -> udptype == TOU_RECEIVER_TYPE_UDPRELAY) - { - UdpRelayReceiver *urr = (UdpRelayReceiver *) (tous->udpsr); - urr->removeUdpPeer(tous->tcp); - } - else if (tous -> udptype == TOU_RECEIVER_TYPE_UDPPEER) - { - UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr); - upr->removeUdpPeer(tous->tcp); - } - else - { - /* error */ - std::cerr << "tou_close() ERROR unknown udptype"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - } - -#endif - - delete tous->tcp; - tous->tcp = NULL ; // prevents calling - - } - - delete tous; - return 1; -} - -/* get an error number */ -int tou_errno(int sockfd) -{ - if (!tou_stream_check(sockfd)) - { - return ENOTSOCK; - } - TcpOnUdp *tous = tou_streams[sockfd]; - return tous->lasterrno; -} - -int tou_clear_error(int sockfd) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - tous->lasterrno = 0; - return 0; -} - diff --git a/libretroshare/src/tcponudp/tou.h b/libretroshare/src/tcponudp/tou.h deleted file mode 100644 index 5635c50c5..000000000 --- a/libretroshare/src/tcponudp/tou.h +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: tou.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef TOU_C_HEADER_H -#define TOU_C_HEADER_H - - -/* get OS-specific definitions for: - * struct sockaddr, socklen_t, ssize_t - */ - -#ifndef WINDOWS_SYS - - #include - #include - #include - -#else - #include - #include - #include -// #include - typedef int socklen_t; -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -/* standard C interface (as Unix-like as possible) - * for the tou (Tcp On Udp) library - */ - /* - * Init: - * The TOU library no longer references any UdpStack items. - * instead, two arrays should be passed to the init function. - * int tou_init( (void **) UdpSubReceiver **udpRecvers, int *udpType, int nUdps); - * - * The UdpSubReceivers should be derived classes, with corresponding types: - * UdpPeerReceiver TOU_RECEIVER_TYPE_UDPPEER - * UdpRelayReceiver TOU_RECEIVER_TYPE_UDPRELAY - * - */ - -#define MAX_TOU_RECEIVERS 16 - -#define TOU_RECEIVER_TYPE_NONE 0x0000 -#define TOU_RECEIVER_TYPE_UDPPEER 0x0001 -#define TOU_RECEIVER_TYPE_UDPRELAY 0x0002 - -// hack to avoid classes in C code. (MacOSX complaining) -int tou_init(void **udpSubRecvs, int *udpTypes, int nUdps); - - /* Connections are as similar to UNIX as possible - * (1) create a socket: tou_socket() this reserves a socket id. - * (2) connect: active: tou_connect() or passive: tou_listenfor(). - * (3) use as a normal socket. - * - * connect() now has a conn_period parameter - this is the - * estimate (in seconds) of how slowly the connection should proceed. - * - * tou_bind() is not valid. tou_init performs this role. - * tou_listen() is not valid. (must listen for a specific address) use tou_listenfor() instead. - * tou_accept() can still be used. - * - ****** THE ABOVE IS BECOMING LESS TRUE ******** - * - * I have now added Multiple type of TOU Connections (Proxy, Relay), - * and multiple UDP Receivers (meaning you can use different ports too). - * - * The UDP receivers must be specified at startup (new tou_init()) - * and the Receiver, and Type of connection must be specified when you - * open the socket. - * - * The parameters to tou_socket, therefore mean something! - * some extra checking has been put in to try and catch bad usage. - */ - - /* creation/connections */ -int tou_socket(uint32_t domain, uint32_t type, int protocol); -int tou_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen); /* null op now */ -int tou_listen(int sockfd, int backlog); /* null op now */ -int tou_connect(int sockfd, const struct sockaddr *serv_addr, - socklen_t addrlen, uint32_t conn_period); -int tou_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); - -/* non-standard bonuses */ -int tou_connected(int sockfd); -int tou_listenfor(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); - - - - /* UNIX interface: minimum for the SSL BIO interface */ -ssize_t tou_read(int sockfd, void *buf, size_t count); -ssize_t tou_write(int sockfd, const void *buf, size_t count); -int tou_close(int sockfd); - - /* non-standard */ -int tou_errno(int sockfd); -int tou_clear_error(int sockfd); - - /* check stream */ -int tou_maxread(int sockfd); -int tou_maxwrite(int sockfd); - - -#ifdef __cplusplus -} - -typedef struct sockaddr_in sockaddr_in; - -/// for relay connections -int tou_connect_via_relay( int sockfd, const sockaddr_in& own_addr, - const sockaddr_in& proxy_addr, - const sockaddr_in& dest_addr ); - -#endif -#endif - diff --git a/libretroshare/src/tcponudp/udppeer.cc b/libretroshare/src/tcponudp/udppeer.cc deleted file mode 100644 index b3cf10913..000000000 --- a/libretroshare/src/tcponudp/udppeer.cc +++ /dev/null @@ -1,140 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: udppeer.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "udppeer.h" -#include - -/* - * #define DEBUG_UDP_PEER 1 - */ - - -UdpPeerReceiver::UdpPeerReceiver(UdpPublisher *pub) - :UdpSubReceiver(pub), peerMtx("UdpSubReceiver") -{ - return; -} - -/* higher level interface */ -int UdpPeerReceiver::recvPkt(void *data, int size, struct sockaddr_in &from) -{ - /* print packet information */ -#ifdef DEBUG_UDP_PEER - std::cerr << "UdpPeerReceiver::recvPkt(" << size << ") from: " << from; - std::cerr << std::endl; -#endif - - RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/ - - /* look for a peer */ - std::map::iterator it; - it = streams.find(from); - - if (it == streams.end()) - { - /* peer unknown */ -#ifdef DEBUG_UDP_PEER - std::cerr << "UdpPeerReceiver::recvPkt() Peer Unknown!"; - std::cerr << std::endl; -#endif - return 0; - } - else - { - /* forward to them */ -#ifdef DEBUG_UDP_PEER - std::cerr << "UdpPeerReceiver::recvPkt() Sending to UdpPeer: "; - std::cerr << it->first; - std::cerr << std::endl; -#endif - (it->second)->recvPkt(data, size); - return 1; - } - /* done */ -} - - -int UdpPeerReceiver::status(std::ostream &out) -{ - RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/ - - out << "UdpPeerReceiver::status()" << std::endl; - out << "UdpPeerReceiver::peers:" << std::endl; - std::map::iterator it; - for(it = streams.begin(); it != streams.end(); ++it) - { - out << "\t" << it->first << std::endl; - } - out << std::endl; - - return 1; -} - - /* add a TCPonUDP stream */ -int UdpPeerReceiver::addUdpPeer(UdpPeer *peer, const struct sockaddr_in &raddr) -{ - RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/ - - - /* check for duplicate */ - std::map::iterator it; - it = streams.find(raddr); - bool ok = (it == streams.end()); - if (!ok) - { -#ifdef DEBUG_UDP_PEER - std::cerr << "UdpPeerReceiver::addUdpPeer() Peer already exists!" << std::endl; - std::cerr << "UdpPeerReceiver::addUdpPeer() ERROR" << std::endl; -#endif - } - else - { - streams[raddr] = peer; - } - - return ok; -} - -int UdpPeerReceiver::removeUdpPeer(UdpPeer *peer) -{ - RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/ - - /* check for duplicate */ - std::map::iterator it; - for(it = streams.begin(); it != streams.end(); ++it) - { - if (it->second == peer) - { -#ifdef DEBUG_UDP_PEER - std::cerr << "UdpPeerReceiver::removeUdpPeer() SUCCESS" << std::endl; -#endif - streams.erase(it); - return 1; - } - } - -#ifdef DEBUG_UDP_PEER - std::cerr << "UdpPeerReceiver::removeUdpPeer() ERROR" << std::endl; -#endif - return 0; -} - - diff --git a/libretroshare/src/tcponudp/udppeer.h b/libretroshare/src/tcponudp/udppeer.h deleted file mode 100644 index 9ecf23419..000000000 --- a/libretroshare/src/tcponudp/udppeer.h +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: udppeer.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_UDP_PEER_RECV_H -#define RS_UDP_PEER_RECV_H - -#ifndef WINDOWS_SYS -#include -#endif - -#include "util/rsthreads.h" - -#include -#include -#include - -#include "tcponudp/rsudpstack.h" - -class UdpPeer -{ - public: -virtual ~UdpPeer() { return; } -virtual void recvPkt(void *data, int size) = 0; -}; - - -class UdpPeerReceiver: public UdpSubReceiver -{ - public: - - UdpPeerReceiver(UdpPublisher *pub); -virtual ~UdpPeerReceiver() { return; } - - /* add a TCPonUDP stream */ -int addUdpPeer(UdpPeer *peer, const struct sockaddr_in &raddr); -int removeUdpPeer(UdpPeer *peer); - - /* callback for recved data (overloaded from UdpReceiver) */ -virtual int recvPkt(void *data, int size, struct sockaddr_in &from); - -int status(std::ostream &out); - - private: - - RsMutex peerMtx; /* for all class data (below) */ - - std::map streams; - -}; - - -#endif diff --git a/libretroshare/src/tcponudp/udprelay.cc b/libretroshare/src/tcponudp/udprelay.cc deleted file mode 100644 index 68062b860..000000000 --- a/libretroshare/src/tcponudp/udprelay.cc +++ /dev/null @@ -1,1117 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: udprelay.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "udprelay.h" -#include -#include "util/rstime.h" -#include - -/* - * #define DEBUG_UDP_RELAY 1 - * #define DEBUG_UDP_RELAY_PKTS 1 - * #define DEBUG_UDP_RELAY_ERRORS 1 - */ - -#define DEBUG_UDP_RELAY_ERRORS 1 - -#ifdef DEBUG_UDP_RELAY -// DEBUG FUNCTION -#include "util/rsstring.h" -#include -int displayUdpRelayPacketHeader(const void *data, const int size); -#endif - -/****************** UDP RELAY STUFF **********/ - -// This packet size must be able to handle TcpStream Packets. -// At the moment, they can be 1000 + 20 for TcpOnUdp ... + 16 => 1036 minimal size. -// See Notes in tcpstream.h for more info -#define MAX_RELAY_UDP_PACKET_SIZE (1400 + 20 + 16) - - -UdpRelayReceiver::UdpRelayReceiver(UdpPublisher *pub) - :UdpSubReceiver(pub), udppeerMtx("UdpSubReceiver"), relayMtx("UdpSubReceiver") -{ - mClassLimit.resize(UDP_RELAY_NUM_CLASS); - mClassCount.resize(UDP_RELAY_NUM_CLASS); - mClassBandwidth.resize(UDP_RELAY_NUM_CLASS); - - - for(int i = 0; i < UDP_RELAY_NUM_CLASS; i++) - { - mClassCount[i] = 0; - mClassBandwidth[i] = 0; - } - - setRelayTotal(UDP_RELAY_DEFAULT_COUNT_ALL); - setRelayClassMax(UDP_RELAY_CLASS_FRIENDS, UDP_RELAY_DEFAULT_FRIEND, UDP_RELAY_DEFAULT_BANDWIDTH); - setRelayClassMax(UDP_RELAY_CLASS_FOF, UDP_RELAY_DEFAULT_FOF, UDP_RELAY_DEFAULT_BANDWIDTH); - setRelayClassMax(UDP_RELAY_CLASS_GENERAL, UDP_RELAY_DEFAULT_GENERAL, UDP_RELAY_DEFAULT_BANDWIDTH); - - /* only allocate this space once */ - mTmpSendPkt = rs_malloc(MAX_RELAY_UDP_PACKET_SIZE); - mTmpSendSize = MAX_RELAY_UDP_PACKET_SIZE; - - clearDataTransferred(); - - return; -} - -UdpRelayReceiver::~UdpRelayReceiver() -{ - free(mTmpSendPkt); -} - - -int UdpRelayReceiver::addUdpPeer(UdpPeer *peer, UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr) -{ - struct sockaddr_in realPeerAddr = endPoints->mDestAddr; - { - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* check for duplicate */ - std::map::iterator it; - it = mStreams.find(realPeerAddr); - bool ok = (it == mStreams.end()); - if (!ok) - { -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::addUdpPeer() ERROR Peer already exists!" << std::endl; -#endif - return 0; - } - - /* setup a peer */ - UdpRelayEnd ure(endPoints, proxyaddr); - -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::addUdpPeer() Installing UdpRelayEnd: " << ure << std::endl; -#endif - - mStreams[realPeerAddr] = ure; - } - - { - RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ - - -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::addUdpPeer() Installing UdpPeer" << std::endl; -#endif - - /* just overwrite */ - mPeers[realPeerAddr] = peer; - - } - - return 1; -} - - -int UdpRelayReceiver::removeUdpPeer(UdpPeer *peer) -{ - bool found = false; - struct sockaddr_in realPeerAddr; - - /* cleanup UdpPeer, and get reference for data */ - { - RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ - - std::map::iterator it; - for(it = mPeers.begin(); it != mPeers.end(); ++it) - { - if (it->second == peer) - { - realPeerAddr = it->first; - mPeers.erase(it); - found = true; - -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::removeUdpPeer() removing UdpPeer" << std::endl; -#endif - break; - } - } - } - - if (!found) - { -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::removeUdpPeer() Warning: Failed to find UdpPeer" << std::endl; -#endif - return 0; - } - - /* now we cleanup the associated data */ - { - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - std::map::iterator it; - it = mStreams.find(realPeerAddr); - if (it != mStreams.end()) - { - mStreams.erase(it); - } - else - { - /* ERROR */ -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::removeUdpPeer() ERROR failed to find Mapping" << std::endl; -#endif - } - } - return 1; -} - -int UdpRelayReceiver::getRelayEnds(std::list &relayEnds) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - std::map::iterator rit; - - for(rit = mStreams.begin(); rit != mStreams.end(); ++rit) - { - relayEnds.push_back(rit->second); - } - return 1; - - -} - -int UdpRelayReceiver::getRelayProxies(std::list &relayProxies) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - std::map::iterator rit; - - for(rit = mRelays.begin(); rit != mRelays.end(); ++rit) - { - relayProxies.push_back(rit->second); - } - return 1; -} - -#define RELAY_MAX_BANDWIDTH 1000 -#define RELAY_TIMEOUT 30 - - -int UdpRelayReceiver::checkRelays() -{ - -#ifdef DEBUG_UDP_RELAY - // As this locks - must be out of the Mutex. - status(std::cerr); -#endif - - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* iterate through the Relays */ - -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::checkRelays()"; - std::cerr << std::endl; -#endif - - std::list eraseList; - std::map::iterator rit; - rstime_t now = time(NULL); - -#define BANDWIDTH_FILTER_K (0.8) - - for(rit = mRelays.begin(); rit != mRelays.end(); ++rit) - { - /* calc bandwidth */ - //rit->second.mBandwidth = rit->second.mDataSize / (float) (now - rit->second.mLastBandwidthTS); - // Switch to a Low-Pass Filter to average it out. - float instantBandwidth = rit->second.mDataSize / (float) (now - rit->second.mLastBandwidthTS); - - rit->second.mBandwidth *= (BANDWIDTH_FILTER_K); - rit->second.mBandwidth += (1.0 - BANDWIDTH_FILTER_K) * instantBandwidth; - - rit->second.mDataSize = 0; - rit->second.mLastBandwidthTS = now; - -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::checkRelays()"; - std::cerr << "Relay: " << rit->first; - std::cerr << " using bandwidth: " << rit->second.mBandwidth; - std::cerr << std::endl; -#endif - - // ONLY A WARNING. -#ifdef DEBUG_UDP_RELAY - if (instantBandwidth > rit->second.mBandwidthLimit) - { - std::cerr << "UdpRelayReceiver::checkRelays() "; - std::cerr << "Warning instantBandwidth: " << instantBandwidth; - std::cerr << " Exceeding Limit: " << rit->second.mBandwidthLimit; - std::cerr << " for Relay: " << rit->first; - std::cerr << std::endl; - } -#endif - - if (rit->second.mBandwidth > rit->second.mBandwidthLimit) - { -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::checkRelays() "; - std::cerr << "Dropping Relay due to excessive Bandwidth: " << rit->second.mBandwidth; - std::cerr << " Exceeding Limit: " << rit->second.mBandwidthLimit; - std::cerr << " Relay: " << rit->first; - std::cerr << std::endl; -#endif - - /* if exceeding bandwidth -> drop */ - eraseList.push_back(rit->first); - } - else if (now - rit->second.mLastTS > RELAY_TIMEOUT) - { -#ifdef DEBUG_UDP_RELAY_ERRORS - /* if haven't transmitted for ages -> drop */ - std::cerr << "UdpRelayReceiver::checkRelays() "; - std::cerr << "Dropping Relay due to Timeout: " << rit->first; - std::cerr << std::endl; -#endif - eraseList.push_back(rit->first); - } - else - { - /* check the length of the relay - we will drop them after a certain amount of time */ - int lifetime = 0; - switch(rit->second.mRelayClass) - { - default: - case UDP_RELAY_CLASS_GENERAL: - lifetime = UDP_RELAY_LIFETIME_GENERAL; - break; - case UDP_RELAY_CLASS_FOF: - lifetime = UDP_RELAY_LIFETIME_FOF; - break; - case UDP_RELAY_CLASS_FRIENDS: - lifetime = UDP_RELAY_LIFETIME_FRIENDS; - break; - } - if (now - rit->second.mStartTS > lifetime) - { -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::checkRelays() "; - std::cerr << "Dropping Relay due to Passing Lifetime Limit: " << lifetime; - std::cerr << " for class: " << rit->second.mRelayClass; - std::cerr << " Relay: " << rit->first; - std::cerr << std::endl; -#endif - - eraseList.push_back(rit->first); - } - } - } - - std::list::iterator it; - for(it = eraseList.begin(); it != eraseList.end(); ++it) - { - removeUdpRelay_relayLocked(&(*it)); - } - - return 1; -} - - -int UdpRelayReceiver::removeUdpRelay(UdpRelayAddrSet *addrSet) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::removeUdpRelay() :" << *addrSet << std::endl; -#endif - - return removeUdpRelay_relayLocked(addrSet); -} - - -int UdpRelayReceiver::addUdpRelay(UdpRelayAddrSet *addrSet, int &relayClass, uint32_t &bandwidth) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* check for duplicate */ - std::map::iterator rit = mRelays.find(*addrSet); - int ok = (rit == mRelays.end()); - if (!ok) - { -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::addUdpRelay() ERROR Peer already exists!" << std::endl; -#endif - return 0; - } - - /* will install if there is space! */ - if (installRelayClass_relayLocked(relayClass, bandwidth)) - { -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::addUdpRelay() adding Relay" << std::endl; -#endif - /* create UdpRelay */ - UdpRelayProxy udpRelay(addrSet, relayClass, bandwidth); - UdpRelayAddrSet alt = addrSet->flippedSet(); - UdpRelayProxy altUdpRelay(&alt, relayClass, bandwidth); - - /* must install two (A, B) & (B, A) */ - mRelays[*addrSet] = udpRelay; - mRelays[alt] = altUdpRelay; - - /* grab bandwidth from one set */ - bandwidth = altUdpRelay.mBandwidthLimit; - - return 1; - } - -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::addUdpRelay() WARNING Too many Relays!" << std::endl; -#endif - return 0; -} - - - -int UdpRelayReceiver::removeUdpRelay_relayLocked(UdpRelayAddrSet *addrSet) -{ -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::removeUdpRelay_relayLocked() :" << *addrSet << std::endl; -#endif - - /* find in Relay list */ - std::map::iterator rit = mRelays.find(*addrSet); - if (rit == mRelays.end()) - { - /* ERROR */ - std::cerr << "UdpRelayReceiver::removeUdpRelay()"; - std::cerr << "ERROR Finding Relay: " << *addrSet; - std::cerr << std::endl; - } - else - { - /* lets drop the count here too */ - removeRelayClass_relayLocked(rit->second.mRelayClass); - mRelays.erase(rit); - } - - /* rotate around and delete matching set */ - UdpRelayAddrSet alt = addrSet->flippedSet(); - - rit = mRelays.find(alt); - if (rit == mRelays.end()) - { - std::cerr << "UdpRelayReceiver::removeUdpRelay()"; - std::cerr << "ERROR Finding Alt Relay: " << alt; - std::cerr << std::endl; - /* ERROR */ - } - else - { - mRelays.erase(rit); - } - return 1; -} - - /* Need some stats, to work out how many relays we are supporting - * modified the code to allow degrading of class .... - * so if you have too many friends, they will fill a FOF spot - */ -int UdpRelayReceiver::installRelayClass_relayLocked(int &classIdx, uint32_t &bandwidth) -{ - /* check for total number of Relays */ - if (mClassCount[UDP_RELAY_CLASS_ALL] >= mClassLimit[UDP_RELAY_CLASS_ALL]) - { - std::cerr << "UdpRelayReceiver::installRelayClass() WARNING Too many Relays already"; - std::cerr << std::endl; - return 0; - } - - /* check the idx too */ - if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) - { - std::cerr << "UdpRelayReceiver::installRelayClass() ERROR class Idx invalid"; - std::cerr << std::endl; - return 0; - } - - /* now check the specifics of the class */ - while(mClassCount[classIdx] >= mClassLimit[classIdx]) - { - std::cerr << "UdpRelayReceiver::installRelayClass() WARNING Relay Class Limit Exceeded"; - std::cerr << std::endl; - std::cerr << "UdpRelayReceiver::installRelayClass() ClassIdx: " << classIdx; - std::cerr << std::endl; - std::cerr << "UdpRelayReceiver::installRelayClass() ClassLimit: " << mClassLimit[classIdx]; - std::cerr << std::endl; - std::cerr << "UdpRelayReceiver::installRelayClass() Degrading Class =>: " << classIdx; - std::cerr << std::endl; - - classIdx--; - if (classIdx == 0) - { - std::cerr << "UdpRelayReceiver::installRelayClass() No Spaces Left"; - std::cerr << std::endl; - - return 0; - } - } - - std::cerr << "UdpRelayReceiver::installRelayClass() Relay Class Ok, Count incremented"; - std::cerr << std::endl; - - /* if we get here we can add one */ - ++mClassCount[UDP_RELAY_CLASS_ALL]; - ++mClassCount[classIdx]; - bandwidth = mClassBandwidth[classIdx]; - - return 1; -} - -int UdpRelayReceiver::removeRelayClass_relayLocked(int classIdx) -{ - /* check for total number of Relays */ - if (mClassCount[UDP_RELAY_CLASS_ALL] < 1) - { - std::cerr << "UdpRelayReceiver::removeRelayClass() ERROR no relays installed"; - std::cerr << std::endl; - return 0; - } - - /* check the idx too */ - if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) - { - std::cerr << "UdpRelayReceiver::removeRelayClass() ERROR class Idx invalid"; - std::cerr << std::endl; - return 0; - } - - /* now check the specifics of the class */ - if (mClassCount[classIdx] < 1) - { - std::cerr << "UdpRelayReceiver::removeRelayClass() ERROR no relay of class installed"; - std::cerr << std::endl; - - return 0; - } - - std::cerr << "UdpRelayReceiver::removeRelayClass() Ok, Count decremented"; - std::cerr << std::endl; - - /* if we get here we can add one */ - mClassCount[UDP_RELAY_CLASS_ALL]--; - mClassCount[classIdx]--; - - return 1; -} - - -int UdpRelayReceiver::setRelayTotal(int count) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - mClassLimit[UDP_RELAY_CLASS_ALL] = count; - mClassLimit[UDP_RELAY_CLASS_GENERAL] = (int) (UDP_RELAY_FRAC_GENERAL * count); - mClassLimit[UDP_RELAY_CLASS_FOF] = (int) (UDP_RELAY_FRAC_FOF * count); - mClassLimit[UDP_RELAY_CLASS_FRIENDS] = (int) (UDP_RELAY_FRAC_FRIENDS * count); - - return count; -} - - -int UdpRelayReceiver::setRelayClassMax(int classIdx, int count, int bandwidth) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* check the idx */ - if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) - { - std::cerr << "UdpRelayReceiver::setRelayMaximum() ERROR class Idx invalid"; - std::cerr << std::endl; - return 0; - } - - mClassLimit[classIdx] = count; - mClassBandwidth[classIdx] = bandwidth; - return 1; -} - - -int UdpRelayReceiver::getRelayClassMax(int classIdx) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* check the idx */ - if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) - { - std::cerr << "UdpRelayReceiver::getRelayMaximum() ERROR class Idx invalid"; - std::cerr << std::endl; - return 0; - } - - return mClassLimit[classIdx]; -} - -int UdpRelayReceiver::getRelayClassBandwidth(int classIdx) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* check the idx */ - if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) - { - std::cerr << "UdpRelayReceiver::getRelayMaximum() ERROR class Idx invalid"; - std::cerr << std::endl; - return 0; - } - - return mClassBandwidth[classIdx]; -} - -int UdpRelayReceiver::getRelayCount(int classIdx) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* check the idx */ - if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) - { - std::cerr << "UdpRelayReceiver::getRelayCount() ERROR class Idx invalid"; - std::cerr << std::endl; - return 0; - } - - return mClassCount[classIdx]; -} - - -int UdpRelayReceiver::RelayStatus(std::ostream &out) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* iterate through the Relays */ - out << "UdpRelayReceiver::RelayStatus()"; - out << std::endl; - - std::map::iterator rit; - for(rit = mRelays.begin(); rit != mRelays.end(); ++rit) - { - out << "Relay for: " << rit->first; - out << std::endl; - - out << "\tClass: " << rit->second.mRelayClass; - out << "\tBandwidth: " << rit->second.mBandwidth; - out << "\tDataSize: " << rit->second.mDataSize; - out << "\tLastBandwidthTS: " << rit->second.mLastBandwidthTS; - out << std::endl; - } - - out << "ClassLimits:" << std::endl; - for(int i = 0; i < UDP_RELAY_NUM_CLASS; i++) - { - out << "Limit[" << i << "] = " << mClassLimit[i]; - out << " Count: " << mClassCount[i]; - out << " Bandwidth: " << mClassBandwidth[i]; - out << std::endl; - } - - return 1; -} - -int UdpRelayReceiver::status(std::ostream &out) -{ - - out << "UdpRelayReceiver::status()" << std::endl; - out << "UdpRelayReceiver::Relayed Connections:" << std::endl; - - RelayStatus(out); - - { - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - out << "UdpRelayReceiver::Connections:" << std::endl; - - std::map::iterator pit; - for(pit = mStreams.begin(); pit != mStreams.end(); ++pit) - { - out << "\t" << pit->first << " : " << pit->second; - out << std::endl; - } - } - - UdpPeersStatus(out); - - return 1; -} - -int UdpRelayReceiver::UdpPeersStatus(std::ostream &out) -{ - RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ - - /* iterate through the Relays */ - out << "UdpRelayReceiver::UdpPeersStatus()"; - out << std::endl; - - std::map::iterator pit; - for(pit = mPeers.begin(); pit != mPeers.end(); ++pit) - { - out << "UdpPeer for: " << pit->first; - out << " is: " << pit->second; - out << std::endl; - } - return 1; -} - - -void UdpRelayReceiver::clearDataTransferred() -{ - { - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - mWriteBytes = 0; - mRelayBytes = 0; - } - - { - RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ - - mReadBytes = 0; - } -} - - -void UdpRelayReceiver::getDataTransferred(uint32_t &read, uint32_t &write, uint32_t &relay) -{ - { - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - write = mWriteBytes; - relay = mRelayBytes; - } - - { - RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ - - read = mReadBytes; - } - clearDataTransferred(); -} - - - -#define UDP_RELAY_HEADER_SIZE 16 - -/* higher level interface */ -int UdpRelayReceiver::recvPkt(void *data, int size, struct sockaddr_in &from) -{ - /* remove unused parameter warnings */ - (void) from; - - /* print packet information */ -#ifdef DEBUG_UDP_RELAY_PKTS - std::cerr << "UdpRelayReceiver::recvPkt(" << size << ") from: " << from; - std::cerr << std::endl; - displayUdpRelayPacketHeader(data, size); - -#endif - - if (!isUdpRelayPacket(data, size)) - { -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::recvPkt() ERROR: is Not RELAY Pkt"; - std::cerr << std::endl; -#endif - return 0; - } - - /* decide if we are the relay, or the endpoint */ - UdpRelayAddrSet addrSet; - if (!extractUdpRelayAddrSet(data, size, addrSet)) - { -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::recvPkt() ERROR: cannot extract Addresses"; - std::cerr << std::endl; -#endif - /* fails most basic test, drop */ - return 0; - } - - { - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* lookup relay first (double entries) */ - std::map::iterator rit = mRelays.find(addrSet); - if (rit != mRelays.end()) - { - /* we are the relay */ -#ifdef DEBUG_UDP_RELAY_PKTS - std::cerr << "UdpRelayReceiver::recvPkt() We are the Relay. Passing onto: "; - std::cerr << rit->first.mDestAddr; - std::cerr << std::endl; -#endif - /* do accounting */ - rit->second.mLastTS = time(NULL); - rit->second.mDataSize += size; - - mRelayBytes += size; - - mPublisher->sendPkt(data, size, rit->first.mDestAddr, STD_RELAY_TTL); - return 1; - } - } - - /* otherwise we are likely to be the endpoint, - * use the peers Address from the header - */ - - { - RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ - - std::map::iterator pit = mPeers.find(addrSet.mSrcAddr); - if (pit != mPeers.end()) - { - /* we are the end-point */ -#ifdef DEBUG_UDP_RELAY_PKTS - std::cerr << "UdpRelayReceiver::recvPkt() Sending to UdpPeer: "; - std::cerr << pit->first; - std::cerr << std::endl; -#endif - mReadBytes += size; - - /* remove the header */ - void *pktdata = (void *) (((uint8_t *) data) + UDP_RELAY_HEADER_SIZE); - int pktsize = size - UDP_RELAY_HEADER_SIZE; - if (pktsize > 0) - { - (pit->second)->recvPkt(pktdata, pktsize); - } - else - { - /* packet undersized */ -//#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::recvPkt() ERROR Packet Undersized"; - std::cerr << std::endl; -//#endif - } - return 1; - } - /* done */ - } - - /* unknown */ -//#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::recvPkt() Peer Unknown!"; - std::cerr << std::endl; -//#endif - return 0; -} - - -/* the address here must be the end point!, - * it cannot be proxy, as we could be using the same proxy for multiple connections. - */ -int UdpRelayReceiver::sendPkt(const void *data, int size, const struct sockaddr_in &to, int /*ttl*/) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* work out who the proxy is */ - std::map::iterator it; - it = mStreams.find(to); - if (it == mStreams.end()) - { -//#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::sendPkt() Peer Unknown!"; - std::cerr << std::endl; -//#endif - return 0; - } - -#ifdef DEBUG_UDP_RELAY_PKTS - std::cerr << "UdpRelayReceiver::sendPkt() to Relay: " << it->second; - std::cerr << std::endl; -#endif - - mWriteBytes += size; - - /* add a header to packet */ - int finalPktSize = createRelayUdpPacket(data, size, mTmpSendPkt, MAX_RELAY_UDP_PACKET_SIZE, &(it->second)); - - /* send the packet on */ - return mPublisher->sendPkt(mTmpSendPkt, finalPktSize, it->second.mProxyAddr, STD_RELAY_TTL); -} - -/***** RELAY PACKET FORMAT **************************** - * - * - * [ 0 | 1 | 2 | 3 ] - * - * [ 'R' 'L' 'Y' Version ] - * [ IP Address 1 ] - * [ Port 1 ][ IP Address 2 .... - * ... IP Address 2][ Port 2 ] - * [.... TUNNELLED DATA .... - * - * - * ... ] - * - * 16 Bytes: 4 ID, 6 IP:Port 1, 6 IP:Port 2 - */ - -#define UDP_IDENTITY_STRING_V1 "RLY1" -#define UDP_IDENTITY_SIZE_V1 4 - -int isUdpRelayPacket(const void *data, const int size) -{ - if (size < UDP_RELAY_HEADER_SIZE) - return 0; - - return (0 == strncmp((char *) data, UDP_IDENTITY_STRING_V1, UDP_IDENTITY_SIZE_V1)); -} - -#ifdef DEBUG_UDP_RELAY - -int displayUdpRelayPacketHeader(const void *data, const int size) -{ - int dsize = UDP_RELAY_HEADER_SIZE + 16; - if (size < dsize) - { - dsize = size; - } - - std::string out; - for(int i = 0; i < dsize; i++) - { - if ((i > 0) && (i % 16 == 0)) - { - out += "\n"; - } - - rs_sprintf_append(out, "%02x", (uint32_t) ((uint8_t*) data)[i]); - } - - std::cerr << "displayUdpRelayPacketHeader()" << std::endl; - std::cerr << out; - std::cerr << std::endl; - - return 1; -} -#endif - - -int extractUdpRelayAddrSet(const void *data, const int size, UdpRelayAddrSet &addrSet) -{ - if (size < UDP_RELAY_HEADER_SIZE) - { - std::cerr << "createRelayUdpPacket() ERROR invalid size"; - std::cerr << std::endl; - return 0; - } - - uint8_t *header = (uint8_t *) data; - - sockaddr_clear(&(addrSet.mSrcAddr)); - sockaddr_clear(&(addrSet.mDestAddr)); - - /* as IP:Port are already in network byte order, we can just write them to the dataspace */ - uint32_t ipaddr; - uint16_t port; - - memcpy(&ipaddr, &(header[4]), 4); - memcpy(&port, &(header[8]), 2); - - addrSet.mSrcAddr.sin_addr.s_addr = ipaddr; - addrSet.mSrcAddr.sin_port = port; - - memcpy(&ipaddr, &(header[10]), 4); - memcpy(&port, &(header[14]), 2); - - addrSet.mDestAddr.sin_addr.s_addr = ipaddr; - addrSet.mDestAddr.sin_port = port; - - return 1; -} - - -int createRelayUdpPacket(const void *data, const int size, void *newpkt, int newsize, UdpRelayEnd *ure) -{ - int pktsize = size + UDP_RELAY_HEADER_SIZE; - if (newsize < pktsize) - { - std::cerr << "createRelayUdpPacket() ERROR invalid size"; - std::cerr << std::endl; - std::cerr << "Incoming DataSize: " << size << " + Header: " << UDP_RELAY_HEADER_SIZE; - std::cerr << " > " << newsize; - std::cerr << std::endl; - return 0; - } - uint8_t *header = (uint8_t *) newpkt; - memcpy(header, UDP_IDENTITY_STRING_V1, UDP_IDENTITY_SIZE_V1); - - /* as IP:Port are already in network byte order, we can just write them to the dataspace */ - uint32_t ipaddr = ure->mLocalAddr.sin_addr.s_addr; - uint16_t port = ure->mLocalAddr.sin_port; - - memcpy(&(header[4]), &ipaddr, 4); - memcpy(&(header[8]), &port, 2); - - ipaddr = ure->mRemoteAddr.sin_addr.s_addr; - port = ure->mRemoteAddr.sin_port; - - memcpy(&(header[10]), &ipaddr, 4); - memcpy(&(header[14]), &port, 2); - - memcpy(&(header[16]), data, size); - - return pktsize; -} - - - -/******* Small Container Class Helper Functions ****/ - -UdpRelayAddrSet::UdpRelayAddrSet() -{ - sockaddr_clear(&mSrcAddr); - sockaddr_clear(&mDestAddr); -} - -UdpRelayAddrSet::UdpRelayAddrSet(const sockaddr_in *ownAddr, const sockaddr_in *destAddr) -{ - mSrcAddr = *ownAddr; - mDestAddr = *destAddr; -} - -UdpRelayAddrSet UdpRelayAddrSet::flippedSet() -{ - UdpRelayAddrSet flipped(&mDestAddr, &mSrcAddr); - return flipped; -} - - -int operator<(const UdpRelayAddrSet &a, const UdpRelayAddrSet &b) -{ - if (a.mSrcAddr < b.mSrcAddr) - { - return 1; - } - - if (a.mSrcAddr == b.mSrcAddr) - { - if (a.mDestAddr < b.mDestAddr) - { - return 1; - } - } - return 0; -} - - -UdpRelayProxy::UdpRelayProxy() -{ - mBandwidth = 0; - mDataSize = 0; - mLastBandwidthTS = 0; - mLastTS = time(NULL); // Must be set here, otherwise Proxy Timesout before anything can happen! - mRelayClass = 0; - - mStartTS = time(NULL); - mBandwidthLimit = 0; -} - -UdpRelayProxy::UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass, uint32_t bandwidth) - : mAddrs(*addrSet), - mBandwidth(0), - mDataSize(0), - mLastBandwidthTS(0), - mLastTS(time(NULL)), - mStartTS(time(NULL)), - mBandwidthLimit(bandwidth), - mRelayClass(relayClass) -{ - /* bandwidth fallback */ - if (bandwidth == 0) - { - switch(relayClass) - { - default: - case UDP_RELAY_CLASS_GENERAL: - mBandwidthLimit = RELAY_MAX_BANDWIDTH; - break; - case UDP_RELAY_CLASS_FOF: - mBandwidthLimit = RELAY_MAX_BANDWIDTH; - break; - case UDP_RELAY_CLASS_FRIENDS: - mBandwidthLimit = RELAY_MAX_BANDWIDTH; - break; - } - } -} - -UdpRelayEnd::UdpRelayEnd() -{ - sockaddr_clear(&mLocalAddr); - sockaddr_clear(&mProxyAddr); - sockaddr_clear(&mRemoteAddr); - -} - -UdpRelayEnd::UdpRelayEnd(UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr) -{ - mLocalAddr = endPoints->mSrcAddr; - mRemoteAddr = endPoints->mDestAddr; - mProxyAddr = *proxyaddr; -} - - - - - -std::ostream &operator<<(std::ostream &out, const UdpRelayAddrSet &uras) -{ - out << "<" << uras.mSrcAddr << "," << uras.mDestAddr << ">"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const UdpRelayProxy &urp) -{ - rstime_t now = time(NULL); - out << "UdpRelayProxy for " << urp.mAddrs; - out << std::endl; - out << "\tRelayClass: " << urp.mRelayClass; - out << std::endl; - out << "\tBandwidth: " << urp.mBandwidth; - out << std::endl; - out << "\tDataSize: " << urp.mDataSize; - out << std::endl; - out << "\tLastBandwidthTS: " << now - urp.mLastBandwidthTS << " secs ago"; - out << std::endl; - out << "\tLastTS: " << now - urp.mLastTS << " secs ago"; - out << std::endl; - - return out; -} - -std::ostream &operator<<(std::ostream &out, const UdpRelayEnd &ure) -{ - out << "UdpRelayEnd: <" << ure.mLocalAddr << " => " << ure.mProxyAddr << " <= "; - out << ure.mRemoteAddr << ">"; - return out; -} - - - - diff --git a/libretroshare/src/tcponudp/udprelay.h b/libretroshare/src/tcponudp/udprelay.h deleted file mode 100644 index ba412ac5a..000000000 --- a/libretroshare/src/tcponudp/udprelay.h +++ /dev/null @@ -1,215 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: udprelay.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_UDP_RELAY_H -#define RS_UDP_RELAY_H - -#include "tcponudp/udppeer.h" -#include -#include - -class UdpRelayAddrSet; - -class UdpRelayAddrSet -{ - public: - UdpRelayAddrSet(); - UdpRelayAddrSet(const sockaddr_in *ownAddr, const sockaddr_in *destAddr); - - UdpRelayAddrSet flippedSet(); - - struct sockaddr_in mSrcAddr; /* msg source */ - struct sockaddr_in mDestAddr; /* final destination */ -}; - -int operator<(const UdpRelayAddrSet &a, const UdpRelayAddrSet &b); - -class UdpRelayProxy -{ - public: - UdpRelayProxy(); - UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass, uint32_t bandwidth); - - UdpRelayAddrSet mAddrs; - double mBandwidth; - uint32_t mDataSize; - rstime_t mLastBandwidthTS; - rstime_t mLastTS; - - rstime_t mStartTS; - double mBandwidthLimit; - - int mRelayClass; -}; - - -class UdpRelayEnd -{ - public: - - UdpRelayEnd(); - UdpRelayEnd(UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr); - - struct sockaddr_in mLocalAddr; - struct sockaddr_in mProxyAddr; - struct sockaddr_in mRemoteAddr; -}; - -std::ostream &operator<<(std::ostream &out, const UdpRelayAddrSet &uras); -std::ostream &operator<<(std::ostream &out, const UdpRelayProxy &urp); -std::ostream &operator<<(std::ostream &out, const UdpRelayEnd &ure); - -/* we define a couple of classes (determining which class is done elsewhere) - * There will be various maximums for each type. - * Ideally you want to allow your friends to use your proxy in preference - * to randoms. - * - * At N x 2 x maxBandwidth. - * - * 10 x 2 x 1Kb/s => 20Kb/s In and Out. (quite a bit!) - * 20 x 2 x 1Kb/s => 40Kb/s Huge. - */ - -#define UDP_RELAY_DEFAULT_COUNT_ALL 2 -#define UDP_RELAY_DEFAULT_FRIEND 0 -#define UDP_RELAY_DEFAULT_FOF 1 -#define UDP_RELAY_DEFAULT_GENERAL 1 -#define UDP_RELAY_DEFAULT_BANDWIDTH 1024 - -#define UDP_RELAY_FRAC_GENERAL (0.5) -#define UDP_RELAY_FRAC_FOF (0.5) -#define UDP_RELAY_FRAC_FRIENDS (0.0) - - - -/**** DEFINED IN EXTERNAL HEADER FILE ***/ -// sehraf: this is a bit ugly but since the int is used as an integer i'lll stick to this hack for now -/// TODO fix me! -#define UDP_RELAY_NUM_CLASS static_cast::type>(RsDhtRelayClass::NUM_CLASS) - -#define UDP_RELAY_CLASS_ALL static_cast::type>(RsDhtRelayClass::ALL) -#define UDP_RELAY_CLASS_GENERAL static_cast::type>(RsDhtRelayClass::GENERAL) -#define UDP_RELAY_CLASS_FOF static_cast::type>(RsDhtRelayClass::FOF) -#define UDP_RELAY_CLASS_FRIENDS static_cast::type>(RsDhtRelayClass::FRIENDS) - -// Just for some testing fun! -//#define UDP_RELAY_LIFETIME_GENERAL 180 // 3 minutes -//#define UDP_RELAY_LIFETIME_FOF 360 // 6 minutes. -//#define UDP_RELAY_LIFETIME_FRIENDS 720 // 12 minutes. - -#define UDP_RELAY_LIFETIME_GENERAL 3600 // 1 hour (chosen so we at least transfer 1 or 2 meg at lowest speed) -#define UDP_RELAY_LIFETIME_FOF 7200 // 2 Hours. -#define UDP_RELAY_LIFETIME_FRIENDS 14400 // 4 Hours. - -#define STD_RELAY_TTL 64 - -class UdpRelayReceiver: public UdpSubReceiver -{ - public: - - UdpRelayReceiver(UdpPublisher *pub); -virtual ~UdpRelayReceiver(); - - /* add a TCPonUDP stream (ENDs) */ -int addUdpPeer(UdpPeer *peer, UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr); -int removeUdpPeer(UdpPeer *peer); - - /* add a Relay Point (for the Relay). - * These don't have to be explicitly removed. - * They will be timed out when - * the end-points drop the connections - */ - - int addUdpRelay(UdpRelayAddrSet *addrSet, int &relayClass, uint32_t &bandwidth); - int removeUdpRelay(UdpRelayAddrSet *addrs); - - /* Need some stats, to work out how many relays we are supporting */ - int checkRelays(); - - int setRelayTotal(int count); /* sets all the Relay Counts (frac based on total) */ - int setRelayClassMax(int classIdx, int count, int bandwidth); /* set a specific class maximum */ - int getRelayClassMax(int classIdx); - int getRelayClassBandwidth(int classIdx); - int getRelayCount(int classIdx); /* how many relays (of this type) do we have */ - int RelayStatus(std::ostream &out); - - /* Extract Relay Data */ - int getRelayEnds(std::list &relayEnds); - int getRelayProxies(std::list &relayProxies); - - /* callback for recved data (overloaded from UdpReceiver) */ -virtual int recvPkt(void *data, int size, struct sockaddr_in &from); - - /* wrapper function for relay (overloaded from UdpSubReceiver) */ -virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); - -int status(std::ostream &out); -int UdpPeersStatus(std::ostream &out); - -void getDataTransferred(uint32_t &read, uint32_t &write, uint32_t &relay); - - private: - - void clearDataTransferred(); - - int removeUdpRelay_relayLocked(UdpRelayAddrSet *addrs); - int installRelayClass_relayLocked(int &classIdx, uint32_t &bandwidth); - int removeRelayClass_relayLocked(int classIdx); - - /* Unfortunately, Due the reentrant nature of this classes activities... - * the SendPkt() must be callable from inside RecvPkt(). - * This means we need two seperate mutexes. - * - one for UdpPeer's, and one for Relay Data. - * - * care must be taken to lock these mutex's in a consistent manner to avoid deadlock. - * - You are not allowed to hold both at the same time! - */ - - RsMutex udppeerMtx; /* for all class data (below) */ - - std::map mPeers; /* indexed by */ - uint32_t mReadBytes; - - RsMutex relayMtx; /* for all class data (below) */ - - std::vector mClassLimit, mClassCount, mClassBandwidth; - std::map mStreams; /* indexed by */ - std::map mRelays; /* indexed by */ - - void *mTmpSendPkt; - uint32_t mTmpSendSize; - - uint32_t mWriteBytes; - uint32_t mRelayBytes; - -}; - -/* utility functions for creating / extracting UdpRelayPackets */ -int isUdpRelayPacket(const void *data, const int size); -int getPacketFromUdpRelayPacket(const void *data, const int size, void **realdata, int *realsize); - -int createRelayUdpPacket(const void *data, const int size, void *newpkt, int newsize, UdpRelayEnd *ure); -int extractUdpRelayAddrSet(const void *data, const int size, UdpRelayAddrSet &addrSet); - - - - -#endif diff --git a/libretroshare/src/tcponudp/udpstunner.cc b/libretroshare/src/tcponudp/udpstunner.cc deleted file mode 100644 index 4409f256f..000000000 --- a/libretroshare/src/tcponudp/udpstunner.cc +++ /dev/null @@ -1,1194 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: udpstunner.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "tcponudp/udpstunner.h" -#include -#include "util/rstime.h" - -#include "util/rsrandom.h" -#include "util/rsprint.h" -#include "util/rsmemory.h" -#include "util/rsstring.h" - -static const int STUN_TTL = 64; - -#define TOU_STUN_MIN_PEERS 20 - -/* - * #define DEBUG_UDP_STUNNER 1 - * #define DEBUG_UDP_STUNNER_FILTER 1 - */ - -//#define DEBUG_UDP_STUNNER 1 - -const uint32_t TOU_STUN_MAX_FAIL_COUNT = 3; /* 3 tries (could be higher?) */ -const int32_t TOU_STUN_MAX_SEND_RATE = 5; /* every 5 seconds */ -const uint32_t TOU_STUN_MAX_RECV_RATE = 25; /* every 25 seconds */ -// TIMEOUT is now tied to STUN RATE ... const int32_t TOU_STUN_ADDR_MAX_AGE = 120; /* 2 minutes */ - -const int32_t TOU_STUN_DEFAULT_TARGET_RATE = 15; /* 20 secs is minimum to keep a NAT UDP port open */ -const double TOU_SUCCESS_LPF_FACTOR = 0.90; - -#define EXCLUSIVE_MODE_TIMEOUT 300 - -UdpStunner::UdpStunner(UdpPublisher *pub) - :UdpSubReceiver(pub), stunMtx("UdpSubReceiver"), eaddrKnown(false), eaddrStable(false), - mStunLastRecvResp(0), mStunLastRecvAny(0), - mStunLastSendStun(0), mStunLastSendAny(0) -{ -#ifdef UDPSTUN_ALLOW_LOCALNET - mAcceptLocalNet = false; - mSimExclusiveNat = false; - mSimSymmetricNat = false; - mSimUnstableExt = false; -#endif - - - - /* these parameters determine the rate we attempt stuns */ - mPassiveStunMode = false; - mSuccessRate = 0.0; - mTargetStunPeriod = TOU_STUN_DEFAULT_TARGET_RATE; - - mExclusiveMode = false; - mExclusiveModeTS = 0; - mForceRestun = false; - - return; -} - -#ifdef UDPSTUN_ALLOW_LOCALNET - - // For Local Testing Only (Releases should have the #define disabled) -void UdpStunner::SetAcceptLocalNet() -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - mAcceptLocalNet = true; -} - - // For Local Testing Only (Releases should have the #define disabled) -void UdpStunner::SimExclusiveNat() -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - mSimExclusiveNat = true; - mSimUnstableExt = true; -} - -void UdpStunner::SimSymmetricNat() -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - mSimSymmetricNat = true; - mSimUnstableExt = true; -} - - - -#endif - - - -int UdpStunner::grabExclusiveMode(std::string holder) /* returns seconds since last send/recv */ -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - rstime_t now = time(NULL); - - -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::grabExclusiveMode()"; - std::cerr << std::endl; -#endif - - if (mExclusiveMode) - { -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::grabExclusiveMode() FAILED"; - std::cerr << std::endl; -#endif - - std::cerr << "UdpStunner::grabExclusiveMode() FAILED, already held by: " << mExclusiveHolder; - std::cerr << std::endl; - std::cerr << "UdpStunner::grabExclusiveMode() Was Grabbed: " << now - mExclusiveModeTS; - std::cerr << " secs ago"; - std::cerr << std::endl; - - /* This can happen if AUTH, but START never received! (occasionally). - */ - if (now - mExclusiveModeTS > EXCLUSIVE_MODE_TIMEOUT) - { - mExclusiveMode = false; - mForceRestun = true; - - std::cerr << "UdpStunner::grabExclusiveMode() Held for too Long... TIMEOUT & Stun Forced"; - std::cerr << std::endl; - } - - return 0; - } - - mExclusiveMode = true; - mExclusiveModeTS = now; - mExclusiveHolder = holder; - - int lastcomms = mStunLastRecvAny; - if (mStunLastSendAny > lastcomms) - { - lastcomms = mStunLastSendAny; - } - - int commsage = now - lastcomms; - - /* cannot return 0, as this indicates error */ - if (commsage == 0) - { - commsage = 1; - } -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::grabExclusiveMode() SUCCESS. last comms: " << commsage; - std::cerr << " ago"; - std::cerr << std::endl; - std::cerr << "UdpStunner::grabExclusiveMode() Exclusive held by: " << mExclusiveHolder; - std::cerr << std::endl; -#endif - - return commsage; -} - -int UdpStunner::releaseExclusiveMode(std::string holder, bool forceStun) -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - if (!mExclusiveMode) - { -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::cancelExclusiveMode() ERROR, not in exclusive Mode"; - std::cerr << std::endl; -#endif - return 0; - } - - mExclusiveMode = false; - if (forceStun) - { - mForceRestun = true; - } - -#ifdef UDPSTUN_ALLOW_LOCALNET - /* if we are simulating an exclusive NAT, then immediately after we release - it'll become unstable. - * In reality, it will only become unstable if we have tried a UDP connection. - * so we use the forceStun parameter (which is true when a UDP connection has been tried). - */ - - if ((mSimExclusiveNat) && (forceStun)) - { - mSimUnstableExt = true; - } -#endif - - if (mExclusiveHolder != holder) - { - std::cerr << "UdpStunner::cancelExclusiveMode() ERROR release MisMatch: "; - std::cerr << " Original Grabber: "; - std::cerr << mExclusiveHolder; - std::cerr << " Releaser: "; - std::cerr << holder; - std::cerr << std::endl; - } - -#ifdef DEBUG_UDP_STUNNER_FILTER - rstime_t now = time(nullptr); - std::cerr << "UdpStunner::cancelExclusiveMode() Canceled. Was in ExclusiveMode for: " << now - mExclusiveModeTS; - std::cerr << " secs"; - std::cerr << std::endl; -#endif - - return 1; -} - - -void UdpStunner::setTargetStunPeriod(int32_t sec_per_stun) -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - if (sec_per_stun < 0) - { - mPassiveStunMode = false; - mTargetStunPeriod = TOU_STUN_DEFAULT_TARGET_RATE; - } - else - { - if (sec_per_stun == 0) - { - mPassiveStunMode = true; - } - else - { - mPassiveStunMode = false; - } - mTargetStunPeriod = sec_per_stun; - } - -} - -/* higher level interface */ -int UdpStunner::recvPkt(void *data, int size, struct sockaddr_in &from) -{ - /* print packet information */ -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::recvPkt(" << size << ") from: " << from; - std::cerr << std::endl; -#endif - - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - /* check for STUN packet */ - if (UdpStun_isStunPacket(data, size)) - { - mStunLastRecvAny = time(NULL); -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::recvPkt() is Stun Packet"; - std::cerr << std::endl; -#endif - - /* respond */ - locked_handleStunPkt(data, size, from); - - return 1; - } - return 0; -} - - -int UdpStunner::status(std::ostream &out) -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - out << "UdpStunner::status() TargetStunPeriod: " << mTargetStunPeriod; - out << " SuccessRate: " << mSuccessRate; - out << std::endl; - - out << "UdpStunner::status()" << std::endl; - - locked_printStunList(); - - return 1; -} - -int UdpStunner::tick() -{ - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::tick()" << std::endl; -#endif - - if (checkStunDesired()) - { - attemptStun(); -#ifdef DEBUG_UDP_STUNNER - status(std::cerr); -#endif - } - - return 1; -} - -/******************************* STUN Handling ********************************/ - - /* respond */ -bool UdpStunner::locked_handleStunPkt(void *data, int size, struct sockaddr_in &from) -{ - if (size == 20) /* request */ - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::handleStunPkt() got Request from: "; - std::cerr << inet_ntoa(from.sin_addr) << ":" << ntohs(from.sin_port); - std::cerr << std::endl; -#endif - /* generate a response */ - int len; - void *pkt = UdpStun_generate_stun_reply(&from, &len, data); - if (!pkt) - return false; - - rstime_t now = time(NULL); - mStunLastSendAny = now; - int sentlen = sendPkt(pkt, len, from, STUN_TTL); - free(pkt); - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::handleStunPkt() sent Response size:" << sentlen; - std::cerr << std::endl; -#endif - - return (len == sentlen); - } - else if (size == 28) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::handleStunPkt() got Response"; - std::cerr << std::endl; -#endif - /* got response */ - struct sockaddr_in eAddr; - bool good = UdpStun_response(data, size, eAddr); - if (good) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::handleStunPkt() got Ext Addr: "; - std::cerr << inet_ntoa(eAddr.sin_addr) << ":" << ntohs(eAddr.sin_port); - std::cerr << " from: " << from; - std::cerr << std::endl; -#endif - locked_recvdStun(from, eAddr); - - return true; - } - } - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::handleStunPkt() Bad Packet"; - std::cerr << std::endl; -#endif - return false; -} - - -bool UdpStunner::externalAddr(struct sockaddr_in &external, uint8_t &stable) -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - if (eaddrKnown) - { - /* address timeout - * no timeout if in exclusive mode - */ - if ((time(NULL) - eaddrTime > (long) (mTargetStunPeriod * 2)) && (!mExclusiveMode)) - { - std::cerr << "UdpStunner::externalAddr() eaddr expired"; - std::cerr << std::endl; - - eaddrKnown = false; - return false; - } - - /* Force Restun is triggered after an Exclusive Mode... as Ext Address is likely to have changed - * Until the Restun has got an address - we act as if we don't have an external address - */ - if (mForceRestun) - { - return false; - } - - external = eaddr; - - if (eaddrStable) - stable = 1; - else - stable = 0; - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::externalAddr() eaddr:" << inet_ntoa(external.sin_addr); - std::cerr << ":" << ntohs(external.sin_port) << " stable: " << (int) stable; - std::cerr << std::endl; -#endif - - - return true; - } -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::externalAddr() eaddr unknown"; - std::cerr << std::endl; -#endif - - return false; -} - - -int UdpStunner::doStun(struct sockaddr_in stun_addr) -{ -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::doStun()"; - std::cerr << std::endl; -#endif - - /* send out a stun packet -> save in the local variable */ - -#define MAX_STUN_SIZE 64 - char stundata[MAX_STUN_SIZE]; - int tmplen = MAX_STUN_SIZE; - bool done = UdpStun_generate_stun_pkt(stundata, &tmplen); - if (!done) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::doStun() Failed"; - std::cerr << std::endl; -#endif - //pqioutput(PQL_ALERT, pqistunzone, "pqistunner::stun() Failed!"); - return 0; - } - - /* send it off */ -#ifdef DEBUG_UDP_STUNNER - int sentlen = -#endif - sendPkt(stundata, tmplen, stun_addr, STUN_TTL); - - { - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - rstime_t now = time(NULL); - mStunLastSendStun = now; - mStunLastSendAny = now; - } - -#ifdef DEBUG_UDP_STUNNER - std::string out; - rs_sprintf(out, "UdpStunner::doStun() Sent Stun Packet(%d) to:%s:%u", sentlen, rs_inet_ntoa(stun_addr.sin_addr).c_str(), ntohs(stun_addr.sin_port)); - - std::cerr << out << std::endl; - - //pqioutput(PQL_ALERT, pqistunzone, out); -#endif - - return 1; -} - -/******************************* STUN Handling ********************************/ -/***** These next functions are generic and not dependent on class variables **/ -/******************************* STUN Handling ********************************/ - -bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr) -{ - /* check what type it is */ - if (size < 28) - { - return false; - } - - if (htons(((uint16_t *) stun_pkt)[0]) != UdpStunner::STUN_BINDING_RESPONSE) - { - /* not a response */ - return false; - } - - /* iterate through the packet */ - /* for now assume the address follows the header directly */ - /* all stay in netbyteorder! */ - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = ((uint32_t *) stun_pkt)[6]; - addr.sin_port = ((uint16_t *) stun_pkt)[11]; - - -#ifdef DEBUG_UDP_STUNNER_FILTER - std::string out; - rs_sprintf(out, "UdpStunner::response() Recvd a Stun Response, ext_addr: %s:%u", rs_inet_ntoa(addr.sin_addr).c_str(), ntohs(addr.sin_port)); - std::cerr << out << std::endl; -#endif - - return true; - -} - -bool UdpStun_generate_stun_pkt(void *stun_pkt, int *len) -{ - if (*len < 20) - { - return false; - } - - /* just the header */ - ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(UdpStunner::STUN_BINDING_REQUEST); - ((uint16_t *) stun_pkt)[1] = (uint16_t) htons(20); /* only header */ - /* RFC 3489 - * The transaction ID is used to correlate requests and responses. - * - * RFC 5389 introduces a mmgic cokie at the location where preciously the transaction ID was located: - * In RFC 3489, this field was part of - * the transaction ID; placing the magic cookie in this location allows - * a server to detect if the client will understand certain attributes - * that were added in this revised specification. - */ - RsRandom::random_bytes(&((uint8_t *) stun_pkt)[4], 4 * sizeof (uint32_t)); - *len = 20; - return true; -} - - -void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len, const void *transId) -{ - /* just the header */ - void *stun_pkt = rs_malloc(28); - - if(!stun_pkt) - return nullptr ; - - ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(UdpStunner::STUN_BINDING_RESPONSE); - ((uint16_t *) stun_pkt)[1] = (uint16_t) htons(28); /* only header + 8 byte addr */ - /* RFC 3489 - * The Binding Response MUST contain the same transaction ID contained in the Binding Request. - */ - memcpy(&((uint32_t *) stun_pkt)[1], &((uint32_t *) transId)[1], 4 * sizeof (uint32_t)); - - /* now add address - * 0 1 2 3 - * - * - */ - - /* THESE SHOULD BE NET ORDER ALREADY */ - ((uint16_t *) stun_pkt)[10] = AF_INET; - ((uint16_t *) stun_pkt)[11] = stun_addr->sin_port; - ((uint32_t *) stun_pkt)[6] = stun_addr->sin_addr.s_addr; - - *len = 28; - return stun_pkt; -} - -bool UdpStun_isStunPacket(void *data, int size) -{ -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::isStunPacket() ?"; - std::cerr << std::endl; -#endif - - if (size < 20) - { -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::isStunPacket() (size < 20) -> false"; - std::cerr << std::endl; -#endif - return false; - } - - /* match size field */ - uint16_t pktsize = ntohs(((uint16_t *) data)[1]); - if (size != pktsize) - { -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::isStunPacket() (size != pktsize) -> false"; - std::cerr << std::endl; -#endif - return false; - } - - if ((size == 20) && (UdpStunner::STUN_BINDING_REQUEST == ntohs(((uint16_t *) data)[0]))) - { -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::isStunPacket() (size=20 & data[0]=STUN_BINDING_REQUEST) -> true"; - std::cerr << std::endl; -#endif - /* request */ - return true; - } - - if ((size == 28) && (UdpStunner::STUN_BINDING_RESPONSE == ntohs(((uint16_t *) data)[0]))) - { -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::isStunPacket() (size=28 & data[0]=STUN_BINDING_RESPONSE) -> true"; - std::cerr << std::endl; -#endif - /* response */ - return true; - } - return false; -} - - -/******************************* STUN Handling ******************************** - * KeepAlive has been replaced by a targetStunRate. Set this to zero to disable. - */ - -/******************************* STUN Handling ********************************/ - - -bool UdpStunner::addStunPeer(const struct sockaddr_in &remote, const char *peerid) -{ - /* add to the list */ -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::addStunPeer()"; - std::cerr << std::endl; -#endif - - bool toStore = true; - { - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - /* only store if we're active */ - toStore = !mPassiveStunMode; - } - - if (toStore) - { - storeStunPeer(remote, peerid, 0); - } - return true; -} - -bool UdpStunner::storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool sent) -{ - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::storeStunPeer()"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - std::list::iterator it; - for(it = mStunList.begin(); it != mStunList.end(); ++it) - { - if ((remote.sin_addr.s_addr == it->remote.sin_addr.s_addr) && - (remote.sin_port == it->remote.sin_port)) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::storeStunPeer() Peer Already There!"; - std::cerr << std::endl; -#endif - /* already there */ - if (sent) - { - it->failCount += 1; - it->lastsend = time(NULL); - } - return false; - } - } - - std::string peerstring; - if (peerid) - { - peerstring = std::string(peerid); - } - - TouStunPeer peer(peerstring, remote); - if (sent) - { - peer.failCount += 1; - peer.lastsend = time(NULL); - } - - mStunList.push_back(peer); - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::storeStunPeer() Added Peer"; - std::cerr << std::endl; -#endif - - return true; -} - - -bool UdpStunner::dropStunPeer(const struct sockaddr_in &remote) -{ - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::dropStunPeer() : "; - std::cerr << std::endl; -#endif - - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - std::list::iterator it; - int count = 0; - for(it = mStunList.begin(); it != mStunList.end();) - { - if ((remote.sin_addr.s_addr == it->remote.sin_addr.s_addr) && - (remote.sin_port == it->remote.sin_port)) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::dropStunPeer() Found Entry"; - std::cerr << std::endl; -#endif - - it = mStunList.erase(it); - count++; - } - else - { - ++it; - } - } - - if (count) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::dropStunPeer() Dropped " << count << " Instances"; - std::cerr << std::endl; -#endif - return true; - } - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::dropStunPeer() Peer Not Here"; - std::cerr << std::endl; -#endif - - return false; -} - - -bool UdpStunner::checkStunDesired() -{ - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::checkStunDesired()"; - std::cerr << std::endl; -#endif - - rstime_t now; - { - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - if (mPassiveStunMode) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::checkStunDesired() In Passive Mode"; - std::cerr << std::endl; -#endif - return false; /* all good */ - } - - if (mExclusiveMode) - { - return false; /* no pings in exclusive mode */ - } - - if (mForceRestun) - { - return true; - } - - - if (!eaddrKnown) - { - /* check properly! (this will limit it to two successful stuns) */ - if (!locked_checkExternalAddress()) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::checkStunDesired() YES, we don't have extAddr Yet"; - std::cerr << std::endl; -#endif - return true; /* want our external address */ - } - } - - /* check if we need to send one now */ - now = time(NULL); - - /* based on SuccessRate & TargetStunRate, we work out if we should send one - * - * if we have 100% success rate, then we can delay until exactly TARGET RATE. - * if we have 0% success rate, then try at double TARGET RATE. - * - * generalised to a rate_scale parameter below... - */ - -#define RATE_SCALE (3.0) - double stunPeriod = (mTargetStunPeriod / (RATE_SCALE)) * (1.0 + mSuccessRate * (RATE_SCALE - 1.0)); - rstime_t nextStun = mStunLastRecvResp + (int) stunPeriod; - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::checkStunDesired() TargetStunPeriod: " << mTargetStunPeriod; - std::cerr << " SuccessRate: " << mSuccessRate; - std::cerr << " DesiredStunPeriod: " << stunPeriod; - std::cerr << " NextStun: " << nextStun - now << " secs"; - std::cerr << std::endl; -#endif - - if (now >= nextStun) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::checkStunDesired() Stun is Desired"; - std::cerr << std::endl; -#endif - return true; - } - else - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::checkStunDesired() Stun is Not Needed"; - std::cerr << std::endl; -#endif - return false; - } - } -} - - -bool UdpStunner::attemptStun() -{ - bool found = false; - TouStunPeer peer; - rstime_t now = time(NULL); - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::attemptStun()"; - std::cerr << std::endl; -#endif - - { - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - size_t i; - for(i = 0; ((i < mStunList.size()) && (mStunList.size() > 0) && (!found)); i++) - { - /* extract entry */ - peer = mStunList.front(); - mStunList.pop_front(); - - /* check if expired */ - if (peer.failCount > TOU_STUN_MAX_FAIL_COUNT) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::attemptStun() Peer has expired, dropping"; - std::cerr << std::endl; -#endif - } - else - { - // Peer Okay, check last send time. - if (now - peer.lastsend < TOU_STUN_MAX_SEND_RATE) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::attemptStun() Peer was sent to Too Recently, pushing back"; - std::cerr << std::endl; -#endif - mStunList.push_back(peer); - } - else - { - /* we have found a peer! */ -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::attemptStun() Found Peer to Stun."; - std::cerr << std::endl; -#endif - peer.failCount++; - peer.lastsend = now; - mStunList.push_back(peer); - mSuccessRate *= TOU_SUCCESS_LPF_FACTOR; - - found = true; - } - } - } // END OF WHILE LOOP. - - if (mStunList.size() < 1) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::attemptStun() No Peers in List. FAILED"; - std::cerr << std::endl; -#endif - return false; - } - -#ifdef DEBUG_UDP_STUNNER - locked_printStunList(); -#endif - - } // END OF MUTEX LOCKING. - - if (found) - { - doStun(peer.remote); - return true; - } - return false; -} - - -bool UdpStunner::locked_recvdStun(const struct sockaddr_in &remote, const struct sockaddr_in &extaddr) -{ -#ifdef DEBUG_UDP_STUNNER - std::string out; - rs_sprintf(out, "UdpStunner::locked_recvdStun() from:%s:%u", rs_inet_ntoa(remote.sin_addr).c_str(), ntohs(remote.sin_port)); - rs_sprintf_append(out, " claiming ExtAddr is:%s:%u", rs_inet_ntoa(extaddr.sin_addr).c_str(), ntohs(extaddr.sin_port)); - - std::cerr << out << std::endl; -#endif - -#ifdef UDPSTUN_ALLOW_LOCALNET - struct sockaddr_in fakeExtaddr = extaddr; - if (mSimUnstableExt) - { - std::cerr << "UdpStunner::locked_recvdStun() TEST SIM UNSTABLE EXT: Forcing Port to be wrong to sim an ExclusiveNat"; - std::cerr << std::endl; - -#define UNSTABLE_PORT_RANGE 100 - - fakeExtaddr.sin_port = htons(ntohs(fakeExtaddr.sin_port) - (UNSTABLE_PORT_RANGE / 2) + RSRandom::random_u32() % UNSTABLE_PORT_RANGE); - if (!mSimSymmetricNat) - { - mSimUnstableExt = false; - } - } -#endif - - /* sanoty checks on the address - * have nasty peer that is returning its own address.... - */ - -#ifndef UDPSTUN_ALLOW_LOCALNET // CANNOT HAVE THIS CHECK IN TESTING MODE! - - if (remote.sin_addr.s_addr == extaddr.sin_addr.s_addr) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::locked_recvdStun() WARNING, BAD PEER: "; - std::cerr << "Stun Peer Returned its own address: " << rs_inet_ntoa(remote.sin_addr); - std::cerr << std::endl; -#endif - return false; - } -#endif - - bool found = false; - std::list::iterator it; - for(it = mStunList.begin(); it != mStunList.end(); ++it) - { - if ((remote.sin_addr.s_addr == it->remote.sin_addr.s_addr) && - (remote.sin_port == it->remote.sin_port)) - { - it->failCount = 0; -#ifdef UDPSTUN_ALLOW_LOCALNET - it->eaddr = fakeExtaddr; -#else - it->eaddr = extaddr; -#endif - it->response = true; - - found = true; - break; - } - } - - /* We've received a Stun, so the ForceStun can be cancelled */ - if (found) - { - mForceRestun = false; - } - - /* if not found.. should we add it back in? */ - - /* How do we calculate the success rate? - * Don't want to count all the stuns? - * Low Pass filter won't work either... - * at send... - * mSuccessRate = 0.95 * mSuccessRate. - * at recv... - * mSuccessRate = 0.95 * mSuccessRate + 0.05; - * - * But if we split into a two stage eqn. it'll work! - * a - * mSuccessRate = 0.95 * mSuccessRate. - * at recv... - * mSuccessRate += 0.05; - */ - - mSuccessRate += (1.0-TOU_SUCCESS_LPF_FACTOR); - - rstime_t now = time(NULL); - mStunLastRecvResp = now; - mStunLastRecvAny = now; - -#ifdef DEBUG_UDP_STUNNER - locked_printStunList(); -#endif - - if (!mExclusiveMode) - { - locked_checkExternalAddress(); - } - - return found; -} - -bool UdpStunner::locked_checkExternalAddress() -{ -#ifdef DEBUG_UDP_STUNNER - std::string out = "UdpStunner::locked_checkExternalAddress()"; - std::cerr << out << std::endl; -#endif - - bool found1 = false; - bool found2 = false; - rstime_t now = time(NULL); - /* iterator backwards - as these are the most recent */ - - /******** - * DUE TO PEERS SENDING BACK FAKE STUN PACKETS... we are increasing. - * requirements to three peers...they all need matching IP addresses to have a known ExtAddr - * - * Wanted to compare 3 peer addresses... but this will mean that the UDP connections - * will take much longer... have to think of a better solution. - * - */ - std::list::reverse_iterator it; - std::list::reverse_iterator p1; - std::list::reverse_iterator p2; - for(it = mStunList.rbegin(); it != mStunList.rend(); ++it) - { - /* check: - 1) have response. - 2) have eaddr. - 3) no fails. - 4) recent age. - */ - - rstime_t age = (now - it->lastsend); - if (it->response && -#ifdef UDPSTUN_ALLOW_LOCALNET - ( mAcceptLocalNet || isExternalNet(&(it->eaddr.sin_addr))) && -#else - (isExternalNet(&(it->eaddr.sin_addr))) && -#endif - (it->failCount == 0) && (age < (long) (mTargetStunPeriod * 2))) - { - if (!found1) - { - p1 = it; - found1 = true; - } - else - { - p2 = it; - found2 = true; - break; - } - } - } - - if (found1 && found2) - { - /* If any of the addresses are different - two possibilities... - * 1) We have changed IP address. - * 2) Someone has sent us a fake STUN Packet. (Wrong Address). - * - */ - if (p1->eaddr.sin_addr.s_addr == p2->eaddr.sin_addr.s_addr) - { - eaddrKnown = true; - } - else - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::locked_checkExternalAddress() Found Address mismatch:"; - std::cerr << std::endl; - std::cerr << " " << inet_ntoa(p1->eaddr.sin_addr); - std::cerr << " " << inet_ntoa(p2->eaddr.sin_addr); - std::cerr << std::endl; - std::cerr << "UdpStunner::locked_checkExternalAddress() Flagging Ext Addr as Unknown"; - std::cerr << std::endl; -#endif - eaddrKnown = false; - } - - if ((eaddrKnown) && - (p1->eaddr.sin_port == p2->eaddr.sin_port)) - { - eaddrStable = true; - } - else - { - eaddrStable = false; - } - - eaddr = p1->eaddr; - eaddrTime = now; - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::locked_checkExternalAddress() Found State:"; - if (eaddrStable) - std::cerr << " Stable NAT translation (GOOD!) "; - else - std::cerr << " unStable (symmetric NAT translation (BAD!) or Address Unknown"; - - std::cerr << std::endl; -#endif - - return true; - } - - return false; -} - - - -bool UdpStunner::locked_printStunList() -{ -#ifdef DEBUG_UDP_STUNNER - std::string out = "locked_printStunList()\n"; - - rstime_t now = time(NULL); - rs_sprintf_append(out, "\tLastSendStun: %ld\n", now - mStunLastSendStun); - rs_sprintf_append(out, "\tLastSendAny: %ld\n", now - mStunLastSendAny); - rs_sprintf_append(out, "\tLastRecvResp: %ld\n", now - mStunLastRecvResp); - rs_sprintf_append(out, "\tLastRecvAny: %ld\n", now - mStunLastRecvAny); - - std::list::iterator it; - for(it = mStunList.begin(); it != mStunList.end(); ++it) - { - out += "id:" + RsUtil::BinToHex(it->id); - rs_sprintf_append(out, " addr: %s:%u", rs_inet_ntoa(it->remote.sin_addr).c_str(), htons(it->remote.sin_port)); - rs_sprintf_append(out, " eaddr: %s:%u", rs_inet_ntoa(it->eaddr.sin_addr).c_str(), htons(it->eaddr.sin_port)); - rs_sprintf_append(out, " failCount: %lu", it->failCount); - rs_sprintf_append(out, " lastSend: %ld\n", now - it->lastsend); - } - - std::cerr << out; -#endif - - return true; -} - - -bool UdpStunner::getStunPeer(int idx, std::string &id, - struct sockaddr_in &remote, struct sockaddr_in &eaddr, - uint32_t &failCount, rstime_t &lastSend) -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - std::list::iterator it; - int i; - for(i=0, it=mStunList.begin(); (iid); - remote = it->remote; - eaddr = it->eaddr; - failCount = it->failCount; - lastSend = it->lastsend; - return true; - } - - return false; -} - - -bool UdpStunner::needStunPeers() -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - return (mStunList.size() < TOU_STUN_MIN_PEERS); -} - - diff --git a/libretroshare/src/tcponudp/udpstunner.h b/libretroshare/src/tcponudp/udpstunner.h deleted file mode 100644 index 00accaa45..000000000 --- a/libretroshare/src/tcponudp/udpstunner.h +++ /dev/null @@ -1,197 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: udpstunner.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_UDP_STUN_H -#define RS_UDP_STUN_H - -#ifndef WINDOWS_SYS -#include -#endif - -#include "tcponudp/rsudpstack.h" -#include "util/rsthreads.h" -#include - -/** - * @brief The TouStunPeer class - * Stuns peers to determine external addresses. - */ -class TouStunPeer -{ - public: - TouStunPeer() - :response(false), lastsend(0), failCount(0) - { - eaddr.sin_addr.s_addr = 0; - eaddr.sin_port = 0; - return; - } - - TouStunPeer(std::string id_in, const struct sockaddr_in &addr) - :id(id_in), remote(addr), response(false), lastsend(0), failCount(0) - { - eaddr.sin_addr.s_addr = 0; - eaddr.sin_port = 0; - return; - } - - /// id for identification - std::string id; - /// Remote address of the peer. - struct sockaddr_in remote; - /// Our external IP address as reported by the peer. - struct sockaddr_in eaddr; - /// true when a response was received in the past - bool response; - /// used to rate limit STUN requests - rstime_t lastsend; - /// fail counter for dead/bad peer detection (0 = good) - uint32_t failCount; -}; - -/* - * FOR TESTING ONLY. - * #define UDPSTUN_ALLOW_LOCALNET 1 - */ - -/** - * @brief The UdpStunner class - * The UDP stunner implements the STUN protocol to determin the NAT type (behind that RS is usually running). - * It maintains a list of DHT peers that are regulary contacted. - * - * The actual NAT type determination logic is located in void pqiNetStateBox::determineNetworkState() - */ -class UdpStunner: public UdpSubReceiver -{ - public: - - UdpStunner(UdpPublisher *pub); -virtual ~UdpStunner() { return; } - -#ifdef UDPSTUN_ALLOW_LOCALNET - // For Local Testing Mode. - void SetAcceptLocalNet(); - void SimExclusiveNat(); - void SimSymmetricNat(); -#endif - -int grabExclusiveMode(std::string holder); /* returns seconds since last send/recv */ -int releaseExclusiveMode(std::string holder, bool forceStun); - - -void setTargetStunPeriod(int32_t sec_per_stun); -bool addStunPeer(const struct sockaddr_in &remote, const char *peerid); -bool dropStunPeer(const struct sockaddr_in &remote); - -bool getStunPeer(int idx, std::string &id, - struct sockaddr_in &remote, struct sockaddr_in &eaddr, - uint32_t &failCount, rstime_t &lastSend); - -bool needStunPeers(); - -bool externalAddr(struct sockaddr_in &remote, uint8_t &stable); - - /* Packet IO */ -virtual int recvPkt(void *data, int size, struct sockaddr_in &from); -virtual int status(std::ostream &out); - - /* monitoring / updates */ - int tick(); - - /* - * based on RFC 3489 - */ - static constexpr uint16_t STUN_BINDING_REQUEST = 0x0001; - static constexpr uint16_t STUN_BINDING_RESPONSE = 0x0101; - - private: - -bool checkStunDesired(); -bool attemptStun(); - -int doStun(struct sockaddr_in stun_addr); -bool storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool sent); - - - /* STUN handling */ -bool locked_handleStunPkt(void *data, int size, struct sockaddr_in &from); - -bool locked_printStunList(); -bool locked_recvdStun(const struct sockaddr_in &remote, const struct sockaddr_in &extaddr); -bool locked_checkExternalAddress(); - - - RsMutex stunMtx; /* for all class data (below) */ - - struct sockaddr_in eaddr; /* external addr */ - - bool eaddrKnown; - bool eaddrStable; /* if true then usable. if false -> Symmettric NAT */ - rstime_t eaddrTime; - - rstime_t mStunLastRecvResp; - rstime_t mStunLastRecvAny; - rstime_t mStunLastSendStun; - rstime_t mStunLastSendAny; - - std::list mStunList; /* potentials */ - -#ifdef UDPSTUN_ALLOW_LOCALNET - // For Local Testing Mode. - bool mAcceptLocalNet; - bool mSimUnstableExt; - bool mSimExclusiveNat; - bool mSimSymmetricNat; - -#endif - - /// The UDP stunner will only (actively) contact it's peers when mPassiveStunMode is false. (has priority over mForceRestun - bool mPassiveStunMode; - /// Time between STUNs - uint32_t mTargetStunPeriod; - /// Rate that determines how often STUN attempts are successfull - double mSuccessRate; - - /// Some variables used for tracking who and when exclusive mode is enabled - bool mExclusiveMode; /* when this is switched on, the stunner stays silent (and extAddr is maintained) */ - rstime_t mExclusiveModeTS; - std::string mExclusiveHolder; - - /// force a STUN immediately - bool mForceRestun; - -}; - - /* generic stun functions */ - -bool UdpStun_isStunPacket(void *data, int size); -bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr); -/** - * @brief UdpStun_generate_stun_reply Generates a STUN reply package. - * @param stun_addr The address to set in the response field. - * @param len Lenght of the generated package (always 28). - * @param transId The transaction ID of the request package. - * @return Pointer to the generated reply package. - */ -void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len, const void* transId); -bool UdpStun_generate_stun_pkt(void *stun_pkt, int *len); - -#endif diff --git a/libretroshare/src/tests/TestNotes.txt b/libretroshare/src/tests/TestNotes.txt deleted file mode 100644 index 5d993d8d1..000000000 --- a/libretroshare/src/tests/TestNotes.txt +++ /dev/null @@ -1,39 +0,0 @@ - -This file documents the high-level status of the regression cases. ------------+----------------------+------------------------------------------------- -DIRECTORY | STATUS | TODO ------------+----------------------+------------------------------------------------- -services | NO TESTS | write test framework for services. -turtle | NO TESTS | write tests -rsserver | NO TESTS | write tests -upnp | automatic tests | [--S] -pgp | automatic tests | [---] -util | automatic tests | [---] -dbase | automatic tests | [--S] -pqi | automatic tests | [C--] -ft | automatic tests | [-FS] (ftcontrollertest, ftserver2test, fttransfermoduletest) -tcponudp | automatic tests | [-F-] Takes 15 mins. test_tou,bidir_tou,stacks_tou fail -dht | NO TESTS | write tests -serialiser | automatic tests | [-F-] (tlvrandom_test) ------------+----------------------+------------------------------------------------- - -Legend: - [---] : nothing to do. All work perfectly. - [ S] : needs scripts - [ F ] : some tests fail - [C ] : some tests don't compile - [E ] : some test execution fail - -Commands: - - to launch tests in a directory: - > \rm *.tstout - > make regress - - - to use parameters: - * create a script [testname].sh where [testname] is the name of the - executable test. It will be used automatically by the above command. - * in the script, use a single command, or if necessary put all commands - on one line using &&. - - - diff --git a/libretroshare/src/tests/common/testutils.h b/libretroshare/src/tests/common/testutils.h deleted file mode 100644 index f5323139c..000000000 --- a/libretroshare/src/tests/common/testutils.h +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -class TestUtils -{ - public: - // Creates a random file of the given size at the given place. Useful for file transfer tests. - // - static bool createRandomFile(const std::string& filename,const uint64_t size) - { - FILE *f = fopen(filename.c_str(),"wb") ; - - if(f == NULL) - return 0 ; - - uint32_t S = 5000 ; - uint32_t *data = new uint32_t[S] ; - - for(uint64_t i=0;i::random().toStdString(false); - } - static std::string createRandomSSLId() - { - return t_RsGenericIdType<16>::random().toStdString(false); - } - static std::string createRandomPGPId() - { - return t_RsGenericIdType<8>::random().toStdString(true); - } - - class DummyAuthGPG: public AuthGPG - { - public: - DummyAuthGPG(const std::string& ownId) - :AuthGPG("pgp_pubring.pgp","pgp_secring.pgp","pgp_trustdb.pgp","lock"), mOwnId(ownId) - { - } - - virtual std::string getGPGOwnId() - { - return mOwnId ; - } - - virtual bool isGPGAccepted(const std::string& pgp_id) { return true ; } - - private: - std::string mOwnId ; - }; - - class DummyAuthSSL: public AuthSSLimpl - { - public: - DummyAuthSSL(const std::string& ownId) - : mOwnId(ownId) - { - } - - virtual std::string OwnId() - { - return mOwnId ; - } - - private: - std::string mOwnId ; - }; - - class DummyRsPeers: public p3Peers - { - public: - DummyRsPeers(p3LinkMgr *lm, p3PeerMgr *pm, p3NetMgr *nm) : p3Peers(lm,pm,nm) {} - - //virtual bool getFriendList(std::list& fl) { ; return true ;} - - private: - std::list mFriends ; - }; -}; diff --git a/libretroshare/src/tests/dbase/ficachetest.cc b/libretroshare/src/tests/dbase/ficachetest.cc deleted file mode 100644 index 3d2c62074..000000000 --- a/libretroshare/src/tests/dbase/ficachetest.cc +++ /dev/null @@ -1,208 +0,0 @@ -/* - * RetroShare FileCache Module: ficachetest.cc - * - * Copyright 2004-2007 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "dbase/cachestrapper.h" -#include "dbase/cachetest.h" -#include "pqi/p3connmgr.h" - -#include -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS -#else - #include -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - -void handleQuery(CacheStrapper *csp, RsPeerId pid, - std::map &strappers); - -/* A simple test of the CacheStrapper Code. - * - * create 3 different CacheStrappers, each with a Source/Store Pair and Transfer Class. - * pass queries and responses between the CacheStrappers, - * and ensure that the hashes in the Caches are updated. - * - */ - -int main(int argc, char **argv) -{ - - rstime_t period = 11; - RsPeerId pid1("0x0101"); - RsPeerId pid2("0x0102"); - RsPeerId pid3("0x0103"); - - p3ConnectMgr *connMgr1 = new p3ConnectMgr(); - p3ConnectMgr *connMgr2 = connMgr1; - p3ConnectMgr *connMgr3 = connMgr1; - - CacheStrapper sc1(connMgr1); - CacheStrapper sc2(connMgr2); - CacheStrapper sc3(connMgr3); - CacheTransfer ctt1(&sc1); - CacheTransfer ctt2(&sc2); - CacheTransfer ctt3(&sc3); - - std::map strappers; - strappers[pid1] = &sc1; - strappers[pid2] = &sc2; - strappers[pid3] = &sc3; - - - std::string nulldir = ""; - - CacheSource *csrc1 = new CacheTestSource(&sc1, nulldir); - CacheStore *cstore1 = new CacheTestStore(&ctt1, &sc1, nulldir); - CacheId cid1(TESTID, 0); - - CacheSource *csrc2 = new CacheTestSource(&sc2, nulldir); - CacheStore *cstore2 = new CacheTestStore(&ctt2, &sc2, nulldir); - CacheId cid2(TESTID, 0); - - CacheSource *csrc3 = new CacheTestSource(&sc3, nulldir); - CacheStore *cstore3 = new CacheTestStore(&ctt3, &sc3, nulldir); - CacheId cid3(TESTID, 0); - - CachePair cp1(csrc1, cstore1, cid1); - CachePair cp2(csrc2, cstore2, cid2); - CachePair cp3(csrc3, cstore3, cid3); - - sc1.addCachePair(cp1); - sc2.addCachePair(cp2); - sc3.addCachePair(cp3); - - /* add in a cache to sc2 */ - RsCacheData cdata; - - cdata.pid = pid1; - cdata.cid = cid1; - cdata.name = "Perm Cache"; - cdata.path = "./"; - cdata.hash = "GHJKI"; - - csrc1->refreshCache(cdata); - - cdata.pid = pid2; - cdata.cid = cid2; - cdata.name = "Funny Cache"; - cdata.path = "./"; - cdata.hash = "ABCDEF"; - - csrc2->refreshCache(cdata); - - /* now exercise it */ - - for(int i = 0; 1 ; i++) - { - RsPeerId src(""); - CacheStrapper *csp = NULL; - - if (i % 5 == 1) - { - src = pid1; - csp = &sc1; - } - else if (i % 5 == 2) - { - src = pid2; - csp = &sc2; - } - else if (i % 5 == 3) - { - src = pid3; - csp = &sc3; - } - std::cerr << std::endl; - std::cerr << "Cache Iteraton: " << time(NULL) << std::endl; - std::cerr << std::endl; - - if (src != "") - { - handleQuery(csp, src, strappers); - } - - - if (i % 21 == 0) - { - /* print out the resources */ - sc1.listCaches(std::cerr); - sc2.listCaches(std::cerr); - sc3.listCaches(std::cerr); - } - - /* every once in a while change the cache on 2 */ - if (i % 31 == 25) - { - cdata.hash += "X"; - csrc2->refreshCache(cdata); - } - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - sleep(1); -#else - Sleep(1000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - /* tick the systems */ - - } - - /* Cleanup - TODO */ - - return 1; -} - -void handleQuery(CacheStrapper *csp, RsPeerId pid, - std::map &strappers) -{ - /* query */ - std::list ids; - std::list::iterator pit; - - std::cerr << "Cache Query from: " << pid << std::endl; - - //csp -> sendCacheQuery(ids, time(NULL)); - for(pit = ids.begin(); pit != ids.end(); pit++) - { - std::cerr << "Cache Query for: " << (*pit) << std::endl; - std::map::iterator sit; - if (strappers.end() != (sit = strappers.find(*pit))) - { - std::map hashs; - std::map::iterator hit; - (sit -> second) -> handleCacheQuery(pid, hashs); - for(hit = hashs.begin(); hit != hashs.end(); hit++) - { - csp -> recvCacheResponse(hit->second, time(NULL)); - } - } - else - { - std::cerr << "Unknown Query Destination!" << std::endl; - } - } -} - diff --git a/libretroshare/src/tests/dbase/fimontest.cc b/libretroshare/src/tests/dbase/fimontest.cc deleted file mode 100644 index ec9e9989b..000000000 --- a/libretroshare/src/tests/dbase/fimontest.cc +++ /dev/null @@ -1,99 +0,0 @@ -/* - * RetroShare FileCache Module: fimontest.cc - * - * Copyright 2004-2007 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -//#include "pqi/p3connmgr.h" -#include "retroshare/rsiface.h" -#include "dbase/cachestrapper.h" -#include "dbase/findex.h" -#include "dbase/fimonitor.h" - -#include - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-p ] shareDir1 [shareDir2 [shareDir3 [...]]]"; - std::cerr << std::endl; - exit(1); -} - - -/*! - * What is tested: - * 1. - * 2. - * 3. - */ -int main(int argc, char **argv) -{ - /* handle commandline arguments */ - int c; - int period = 60; /* recheck period in seconds */ - - while((c = getopt(argc, argv,"p:")) != -1) - { - switch(c) - { - case 'p': - period = atoi(optarg); - break; - default: - std::cerr << "Bad Option."; - std::cerr << std::endl; - usage(argv[0]); - break; - } - } - - std::list rootdirs; - - /* add all the rest of the commandline arguments to rootdirs list */ - for(; optind < argc; optind++) - { - SharedDirInfo dir; - dir.filename = argv[optind]; - dir.shareflags = DIR_FLAGS_PERMISSIONS_MASK ; - rootdirs.push_back(dir); - std::cerr << "Adding shared directory: " << argv[optind] << std::endl; - } - - if (rootdirs.size() < 1) - { - usage(argv[0]); - } - - //p3ConnectMgr connMgr; - NotifyBase nb; - CacheStrapper* cs = NULL; - - FileIndexMonitor mon(cs, &nb, "", "OWN ID", std::string(".")); - - /* setup monitor */ - mon.setSharedDirectories(rootdirs); - - /* simulate running the thread */ - mon.run(); - - return 1; -} - - diff --git a/libretroshare/src/tests/dbase/fisavetest.cc b/libretroshare/src/tests/dbase/fisavetest.cc deleted file mode 100644 index 94d2905d6..000000000 --- a/libretroshare/src/tests/dbase/fisavetest.cc +++ /dev/null @@ -1,123 +0,0 @@ -/* - * RetroShare FileCache Module: fisavetest.cc - * - * Copyright 2004-2007 by Kefei Zhou. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "dbase/findex.h" -#include - -FileIndex *createBasicFileIndex(rstime_t age); - -int main() -{ - FileIndex *fi1 = createBasicFileIndex(100); - FileIndex *fi2 = new FileIndex("A SILLY ID"); - - std::string out ; - fi1->printFileIndex(out); - std::cout << out < forbiddenroots; - fi1->saveIndex("test.index", fhash, size, forbiddenroots); - - std::cout << " Saved Index: Size: " << size << " Hash: " << fhash << std::endl; - std::cout << " -- new file index -- " << std::endl; - - fi2->loadIndex("test.index", fhash, size); - out.clear() ; - fi2->printFileIndex(out); - std::cout << out << std::endl; - - delete fi1; - delete fi2; - - return 1; -} - - -FileIndex *createBasicFileIndex(rstime_t age) -{ - FileIndex *fi = new FileIndex("A SILLY ID"); - - FileEntry fe; - - std::list rootdirs; - rootdirs.push_back("base1"); - rootdirs.push_back("base2"); - rootdirs.push_back("base3"); - - fi -> setRootDirectories(rootdirs, age); - - /* add some entries */ - fe.name = "dir1"; - fi -> updateDirEntry("base1",fe, age); - fe.name = "dir2"; - fi -> updateDirEntry("base1",fe, age); - - fe.name = "dir01"; - fi -> updateDirEntry("/base1/dir1/",fe, age); - - fe.name = "dir001"; - fi -> updateDirEntry("/base1/dir1/dir01/",fe, age); - - fe.name = "file1"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - fe.name = "file2"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - fe.name = "file3"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - fe.name = "file4"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - - - fe.name = "dir2"; - fi -> updateDirEntry("/base1",fe, age); - fe.name = "file5"; - fi -> updateFileEntry("/base1/dir2/",fe, age); - fe.name = "file6"; - fi -> updateFileEntry("/base1/dir2/",fe, age); - fe.name = "file7"; - fi -> updateFileEntry("/base1/dir2/",fe, age); - fe.name = "file8"; - fi -> updateFileEntry("/base1/",fe, age); - - - fe.name = "dir3"; - fi -> updateDirEntry("/base1/dir2/",fe, age); - fe.name = "file10"; - fi -> updateFileEntry("/base1/dir2/dir3",fe, age); - fe.name = "file11"; - fi -> updateFileEntry("/base1/dir2/dir3",fe, age); - fe.name = "file12"; - fi -> updateFileEntry("/base1/dir2/dir3",fe, age); - - - fe.name = "dir4"; - fi -> updateDirEntry("/base3/",fe, age); - fe.name = "file20"; - fi -> updateFileEntry("/base3/dir4/",fe, age); - fe.name = "file21"; - fi -> updateFileEntry("/base3/dir4",fe, age); - - return fi; -} - diff --git a/libretroshare/src/tests/dbase/fitest2.cc b/libretroshare/src/tests/dbase/fitest2.cc deleted file mode 100644 index b3f74775d..000000000 --- a/libretroshare/src/tests/dbase/fitest2.cc +++ /dev/null @@ -1,226 +0,0 @@ -/* - * RetroShare FileCache Module: fitest2.cc - * - * Copyright 2004-2007 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "dbase/findex.h" - -#include - -FileIndex *createBasicFileIndex(rstime_t age); - -int test1(FileIndex *fi); -int test2(FileIndex *fi); - -int main() -{ - FileIndex *fi = createBasicFileIndex(100); - - test1(fi); - - delete fi; - - return 1; -} - -int test1(FileIndex *fi) -{ - /* in this test we are going to get the old directories - and update them */ - rstime_t stamp = 200; - - DirEntry *olddir = NULL; - FileEntry fe; - while((olddir = fi -> findOldDirectory(stamp))) - { - /* update the directories and files here */ - std::map::iterator dit; - std::map::iterator fit; - - /* update this dir */ - fe.name = olddir->name; - fi -> updateDirEntry(olddir->parent->path, fe, stamp); - - /* update subdirs */ - for(dit = olddir->subdirs.begin(); dit != olddir->subdirs.end(); dit++) - { - fe.name = (dit->second)->name; - /* set the age as out-of-date so that it gets checked */ - fi -> updateDirEntry(olddir->path, fe, 0); - } - - /* update files */ - for(fit = olddir->files.begin(); fit != olddir->files.end(); fit++) - { - fe.name = (fit->second)->name; - fi -> updateFileEntry(olddir->path, fe, stamp); - } - - /* clean up the dir (should have no effect) */ - fi -> removeOldDirectory(olddir->parent->path, olddir->name, stamp); - - std::string out ; - fi -> printFileIndex(out); - std::cout << out << std::endl; - } - - std::string out ; - fi -> printFileIndex(out); - std::cout << out << std::endl; - - return 1; -} - - -int test2(FileIndex *fi) -{ - /* in this test we are going to simulate that 2 directories have disappeared */ - rstime_t stamp = 200; - - DirEntry *olddir = NULL; - FileEntry fe; - bool missingdir = false; - int i = 0; - - while((olddir = fi -> findOldDirectory(stamp))) - { - missingdir = false; - if (i % 2 == 0) - { - std::cerr << " Simulating that dir doesnt exist :" << olddir->path; - std::cerr << std::endl; - missingdir = true; - } - i++; - - if (!missingdir) - { - /* update the directories and files here */ - std::map::iterator dit; - std::map::iterator fit; - - /* update this dir */ - fe.name = olddir->name; - fi -> updateDirEntry(olddir->parent->path, fe, stamp); - - /* update subdirs */ - for(dit = olddir->subdirs.begin(); dit != olddir->subdirs.end(); dit++) - { - fe.name = (dit->second)->name; - /* set the age as out-of-date so that it gets checked */ - fi -> updateDirEntry(olddir->path, fe, 0); - } - - /* update files */ - for(fit = olddir->files.begin(); fit != olddir->files.end(); fit++) - { - fe.name = (fit->second)->name; - fi -> updateFileEntry(olddir->path, fe, stamp); - } - } - /* clean up the dir */ - fi -> removeOldDirectory(olddir->parent->path, olddir->name, stamp); - - std::string out ; - fi -> printFileIndex(out); - std::cout << out << std::endl; - } - - std::string out ; - fi -> printFileIndex(out); - std::cout << out << std::endl; - - return 1; -} - - - - - -FileIndex *createBasicFileIndex(rstime_t age) -{ - FileIndex *fi = new FileIndex("A SILLY ID"); - - FileEntry fe; - - /* print empty FileIndex */ - std::string out ; - fi -> printFileIndex(out); - std::cout << out << std::endl; - - std::list rootdirs; - rootdirs.push_back("base1"); - rootdirs.push_back("base2"); - rootdirs.push_back("base3"); - - fi -> setRootDirectories(rootdirs, age); - - /* add some entries */ - fe.name = "dir1"; - fi -> updateDirEntry("base1",fe, age); - fe.name = "file1"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - fe.name = "file2"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - fe.name = "file3"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - fe.name = "file4"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - - fe.name = "dir2"; - fi -> updateDirEntry("/base1",fe, age); - fe.name = "file5"; - fi -> updateFileEntry("/base1/dir2/",fe, age); - fe.name = "file6"; - fi -> updateFileEntry("/base1/dir2/",fe, age); - fe.name = "file7"; - fi -> updateFileEntry("/base1/dir2/",fe, age); - fe.name = "file8"; - fi -> updateFileEntry("/base1/",fe, age); - - - fe.name = "dir3"; - fi -> updateDirEntry("/base1/dir2/",fe, age); - fe.name = "file10"; - fi -> updateFileEntry("/base1/dir2/dir3",fe, age); - fe.name = "file11"; - fi -> updateFileEntry("/base1/dir2/dir3",fe, age); - fe.name = "file12"; - fi -> updateFileEntry("/base1/dir2/dir3",fe, age); - - - fe.name = "dir4"; - fi -> updateDirEntry("/base3/",fe, age); - fe.name = "file20"; - fi -> updateFileEntry("/base3/dir4/",fe, age); - fe.name = "file21"; - fi -> updateFileEntry("/base3/dir4",fe, age); - - // one that will fail. - fe.name = "file20"; - fi -> updateFileEntry("/base3/",fe, age); - - out.clear() ; - fi -> printFileIndex(out); - std::cout << out << std::endl; - - return fi; -} - diff --git a/libretroshare/src/tests/dbase/searchtest.cc b/libretroshare/src/tests/dbase/searchtest.cc deleted file mode 100644 index d09e1b565..000000000 --- a/libretroshare/src/tests/dbase/searchtest.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* - * RetroShare FileCache Module: searchtest.cc - * - * Copyright 2004-2007 by Kefei Zhou. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "dbase/findex.h" -#include -#include - -int main() -{ - - std::cout << std::string::npos << std::endl; - std::string testfile = "searchtest.index"; - std::string fhash = "6851c28d99a6616a86942c3914476bf11997242a"; - FileIndex *fi = new FileIndex("DUMB ID"); - - // loading fileindex - std::cout << std::endl << "Test load" << std::endl; - fi->loadIndex(testfile, fhash, 1532); - fi->printFileIndex(std::cout); - std::cout << "FileIndex Loaded" << std::endl << std::endl; - - std::list hashresult; - std::list termresult; - - // searchhash - std::string findhash = "82bffa6e1cdf8419397311789391238174817481"; - - - std::cout << "Search hash : " << findhash << std::endl; - fi->searchHash(findhash, hashresult); - - while(!hashresult.empty()) - { - std::string out ; - hashresult.back()->print(out); - std::cout << out << std::endl; - hashresult.pop_back(); - } - - // searchterm - std::list terms; - terms.push_back("paper"); - terms.push_back("doc"); - - std::cout << "Search terms" << std::endl; - fi->searchTerms(terms, termresult); - - while(!termresult.empty()) - { - std::string out ; - termresult.back()->print(out); - std::cout << out << std::endl; - termresult.pop_back(); - } - - delete fi; - return 1; -} diff --git a/libretroshare/src/tests/ft/TestNotes.txt b/libretroshare/src/tests/ft/TestNotes.txt deleted file mode 100644 index 013fe879e..000000000 --- a/libretroshare/src/tests/ft/TestNotes.txt +++ /dev/null @@ -1,54 +0,0 @@ - -Features that need to be tested, and which test checks it. ------------------------------------------------------------ - -(*) Transfer Related - -(*) Search Related - -(*) ExtraList Related - -(*) Cache Related - -(*) Config / Storage. - Change Config Directory works dynamically. (no restart required). - - -(*) Miscelleous - - - ------------------------------------------------------------ ------------------------------------------------------------ -Actual Tests, and what they check. ------------------------------------------------------------ - -ftserver1test.cc -================== - -Used to develop test framework. -Tests. - 1) Test Framework. OK - 2) File Indexing. OK - 3) Cache Packet Exchange. OK - 4) Cache downloads (including loopback). FAILS - 5) FileIndex Store loading. - 6) Basic Search. - -ftserver2test.cc -================== - -Test out the ExtraList functions. -Demonstrates the use of libretroshare/src/util/utest.h - -Tests. - 1) Load ExtraList path OK - 2) Hashing of ExtraList File OK - 3) ExtraHashDone. OK - 4) Local Search for ExtraList Data. OK - 5) Remote Search of ExtraList (should Fail) OK - 6) Transfer of ExtraList File (Local) TODO - 7) Transfer of ExtraList File (Remote) TODO - - - diff --git a/libretroshare/src/tests/ft/ftcontrollertest.cc b/libretroshare/src/tests/ft/ftcontrollertest.cc deleted file mode 100644 index 00fb95fa2..000000000 --- a/libretroshare/src/tests/ft/ftcontrollertest.cc +++ /dev/null @@ -1,451 +0,0 @@ -/* - * libretroshare/src/ft: ftserver1test.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * ftServer2Test - Demonstrates how to check for test stuff. - */ - -#include "retroshare/rsfiles.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsiface.h" -#include "rsserver/p3peers.h" -#include "ft/ftserver.h" - -#include "ft/ftextralist.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftfilesearch.h" - -//#include "pqi/p3authmgr.h" -//#include "pqi/p3connmgr.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" - -#include "pqi/authssl.h" -#include "pqi/authgpg.h" - -#include "common/testutils.h" -#include "util/rsdebug.h" - -#include "pqitestor.h" -#include "util/rsdir.h" -#include "util/utest.h" - - -#include - -class TestData -{ - public: - - ftServer *loadServer; - std::list otherServers; - std::list extraList; -}; - - -extern "C" void *do_server_test_thread(void *p); - - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-sa] [-p ] [-d ] [-e ] [ [ ... ]] "; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint32_t debugLevel = 5; - bool loadAll = false; - - std::list fileList; - std::list extraList; - std::list peerIds; - std::map mFtServers; - std::map mLinkMgrs; - - ftServer *mLoadServer = NULL; - std::list mOtherServers; - std::list::iterator eit; - - while(-1 != (c = getopt(argc, argv, "asd:p:e:"))) - { - switch (c) - { - case 'p': - peerIds.push_back(optarg); - break; - case 'd': - debugLevel = atoi(optarg); - break; -// case 's': -// debugStderr = true; -// break; - case 'e': - extraList.push_back(optarg); - break; - case 'a': - loadAll = true; - break; - default: - usage(argv[0]); - break; - } - } - - if(peerIds.empty()) - { - peerIds.push_back(TestUtils::createRandomSSLId()) ; - - // then add some other peer ids. - peerIds.push_back(TestUtils::createRandomSSLId()) ; - peerIds.push_back(TestUtils::createRandomSSLId()) ; - peerIds.push_back(TestUtils::createRandomSSLId()) ; - } - - std::string ssl_own_id = TestUtils::createRandomSSLId() ; - std::string gpg_own_id = TestUtils::createRandomPGPId() ; - - TestUtils::DummyAuthGPG fakeGPG(gpg_own_id) ; - AuthGPG::setAuthGPG_debug(&fakeGPG) ; - - TestUtils::DummyAuthSSL fakeSSL(ssl_own_id) ; - AuthSSL::setAuthSSL_debug(&fakeSSL) ; - - /* do logging */ - setOutputLevel(debugLevel); - - if (optind >= argc) - { - std::cerr << "Missing Shared Directories" << std::endl; - usage(argv[0]); - } - - for(; optind < argc; optind++) - { - std::cerr << "Adding: " << argv[optind] << std::endl; - - SharedDirInfo info ; - info.shareflags = DIR_FLAGS_PERMISSIONS_MASK; - info.filename = std::string(argv[optind]); - info.virtualname = info.filename ; - - fileList.push_back(info) ; - } - - /* We need to setup a series 2 - 4 different ftServers.... - * - * Each one needs: - * - * - * A List of peerIds... - */ - - std::list::const_iterator it, jit; - - std::list baseFriendList, friendList; - std::list::iterator fit; - - P3Hub *testHub = new P3Hub(0,NULL); - testHub->start(); - - /* Setup Base Friend Info */ - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - RsPeerDetails pad; - pad.id = *it; - pad.gpg_id = TestUtils::createRandomPGPId() ; - pad.name = *it; - pad.trustLvl = 5; - pad.ownsign = true; - //pad.trusted = false; - - baseFriendList.push_back(pad); - - std::cerr << "ftserver1test::setup peer: " << *it << std::endl; - } - - std::ostringstream pname; - pname << "/tmp/rstst-" << time(NULL); - - std::string basepath = pname.str(); - RsDirUtil::checkCreateDirectory(basepath); - - - - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - friendList = baseFriendList; - /* remove current one */ - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - if (fit->id == *it) - { - friendList.erase(fit); - break; - } - } - - //p3AuthMgr *authMgr = new p3DummyAuthMgr(*it, friendList); - p3PeerMgrIMPL *peerMgr = new p3PeerMgrIMPL(ssl_own_id,gpg_own_id,"My GPG name","My SSL location"); - - p3NetMgrIMPL *netMgr = new p3NetMgrIMPL ; - p3LinkMgrIMPL *linkMgr = new p3LinkMgrIMPL(peerMgr,netMgr); - mLinkMgrs[*it] = linkMgr; - - rsPeers = new TestUtils::DummyRsPeers(linkMgr,peerMgr,netMgr) ; - - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - /* add as peer to authMgr */ - peerMgr->addFriend(fit->id,fit->gpg_id); - } - - P3Pipe *pipe = new P3Pipe(); //(*it); - - /* add server */ - ftServer *server; - server = new ftServer(peerMgr,linkMgr); - mFtServers[*it] = server; - if (!mLoadServer) - { - mLoadServer = server; - } - else - { - mOtherServers.push_back(server); - } - - - server->setP3Interface(pipe); - - std::string configpath = basepath + "/" + *it; - RsDirUtil::checkCreateDirectory(configpath); - - std::string cachepath = configpath + "/cache"; - RsDirUtil::checkCreateDirectory(cachepath); - - std::string localpath = cachepath + "/local"; - RsDirUtil::checkCreateDirectory(localpath); - - std::string remotepath = cachepath + "/remote"; - RsDirUtil::checkCreateDirectory(remotepath); - - server->setConfigDirectory(configpath); - - NotifyBase *base = new NotifyBase; - server->SetupFtServer(base); - - testHub->addP3Pipe(*it, pipe, linkMgr); - server->StartupThreads(); - - /* setup any extra bits */ - if (loadAll) - { - server->setSharedDirectories(fileList); - for(eit = extraList.begin(); eit != extraList.end(); eit++) - { - server->ExtraFileHash(*eit, 3600, TransferRequestFlags(0)); - } - } - - } - - if (mLoadServer) - { - mLoadServer->setSharedDirectories(fileList); - for(eit = extraList.begin(); eit != extraList.end(); eit++) - { - mLoadServer->ExtraFileHash(*eit, 3600, TransferRequestFlags(0)); - } - } - - - /* stick your real test here */ - std::map::iterator sit; - std::map::iterator cit; - - /* Start up test thread */ - pthread_t tid; - TestData *mFt = new TestData; - - /* set data */ - mFt->loadServer = mLoadServer; - mFt->otherServers = mOtherServers; - mFt->extraList = extraList; - - void *data = (void *) mFt; - pthread_create(&tid, 0, &do_server_test_thread, data); - pthread_detach(tid); /* so memory is reclaimed in linux */ - - while(1) - { - std::cerr << "ftserver2test::sleep()"; - std::cerr << std::endl; - sleep(1); - - /* tick the connmgrs */ - for(sit = mFtServers.begin(); sit != mFtServers.end(); sit++) - { - /* update */ - (sit->second)->tick(); - } - - for(cit = mLinkMgrs.begin(); cit != mLinkMgrs.end(); cit++) - { - /* update */ - (cit->second)->tick(); - } - } -} - -/* So our actual test can run here..... - * - */ - -INITTEST(); - -void *do_server_test_thread(void *data) -{ - TestData *mFt = (TestData *) data; - - std::cerr << "do_server_test_thread() running"; - std::cerr << std::endl; - - /************************* TEST 1 ********************** - * Check that the extra List has been processed. - */ - rstime_t start = time(NULL); - - FileInfo info, info2; - rstime_t now = time(NULL); - std::list::iterator eit; - for(eit = mFt->extraList.begin(); eit != mFt->extraList.end(); eit++) - { - std::cerr << "Treating extra file " << *eit << std::endl; - - while(!mFt->loadServer->ExtraFileStatus(*eit, info)) - { - - /* max of 30 seconds */ - now = time(NULL); - if (now - start > 30) - { - /* FAIL */ - REPORT2( false, "Extra File Hashing"); - } - - sleep(1); - } - - /* Got ExtraFileStatus */ - REPORT("Successfully Found ExtraFile"); - - /* now we can try a search (should succeed) */ - FileSearchFlags hintflags = RS_FILE_HINTS_EXTRA; - - if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) - { - CHECK(info2.hash == info.hash); - CHECK(info2.size == info.size); - CHECK(info2.fname == info.fname); - } - else - { - REPORT2( false, "Search for Extra File (Basic)"); - } - - /* search with flags (should succeed) */ - hintflags = RS_FILE_HINTS_EXTRA; - if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) - { - CHECK(info2.hash == info.hash); - CHECK(info2.size == info.size); - CHECK(info2.fname == info.fname); - } - else - { - REPORT2( false, "Search for Extra File (Extra Flag)"); - } - - /* search with other flags (should fail) */ - hintflags = RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY; - - if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) - { - REPORT2( false, "Search for Extra File (Fail Flags)"); - } - else - { - REPORT("Search for Extra File (Fail Flags)"); - } - - /* if we try to download it ... should just find existing one*/ - - REPORT("Testing with Extra File"); - } - - FINALREPORT("ExtraList Hashing, Searching and Downloading"); - - /************************* TEST 2 ********************** - * test ftController and ftTransferModule - */ - ftServer *server=mFt->loadServer; - - std::string fname,filehash,destination; - FileSearchFlags flags; - std::list srcIds; - - /* select a file from otherServers */ - if (mFt->otherServers.empty() ) - { - REPORT2(false,"No otherServers available"); - exit(1); - } - - DirDetails details; - flags = RS_FILE_HINTS_REMOTE; - void *ref = NULL; - - if(!server->RequestDirDetails(ref,details,flags)) - { - REPORT2(false,"fail to call RequestDirDetails"); - } - - if (details.type == DIR_TYPE_FILE) - { - REPORT("RemoteDirModel::downloadSelected() Calling File Request"); - std::list srcIds; - srcIds.push_back(details.id); - server->FileRequest(details.name, details.hash, details.count, "", TransferRequestFlags(0), srcIds); - } - - exit(1); -} - - - - diff --git a/libretroshare/src/tests/ft/ftcontrollertest.sh b/libretroshare/src/tests/ft/ftcontrollertest.sh deleted file mode 100755 index e4a9d2fa5..000000000 --- a/libretroshare/src/tests/ft/ftcontrollertest.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -./ftcontrollertest -p 8cb3a1677872c9e8248fd5ddeac84000 -p 8cb3a1677872c9e8248fd5ddeac84001 -p 8cb3a1677872c9e8248fd5ddeac84002 -e ftcontrollertest . diff --git a/libretroshare/src/tests/ft/ftcrc32test.cc b/libretroshare/src/tests/ft/ftcrc32test.cc deleted file mode 100644 index f20144df9..000000000 --- a/libretroshare/src/tests/ft/ftcrc32test.cc +++ /dev/null @@ -1,127 +0,0 @@ -/* - * libretroshare/src/ft: ftcrc32test.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include -#include "retroshare/rstypes.h" -#include -#include - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include "util/rsdir.h" -#include "util/utest.h" -#include -#include - -INITTEST() ; - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t dPeriod = 600; /* default 10 minutes */ - - std::string inputfile ; - - argstream as(argc,argv) ; - - as >> parameter('i',"input",inputfile,"Input file to hash. If none, a random file will be created in /tmp",false) - >> help() ; - - as.defaultErrorHandling() ; - - if(inputfile == "") - { - uint64_t S = 3983782 ; - std::cerr << "Creating a dummy input file in /tmp, of size " << S << std::endl; - inputfile = "crc_test_data.bin" ; - - if(!TestUtils::createRandomFile(inputfile,S)) - return 1 ; - } - - std::list hashList ; - hashList.push_back(inputfile) ; - - uint32_t flags = 0; - for(std::list::const_iterator it(hashList.begin()); it != hashList.end(); it++) - { - std::cerr << "Hashing file :" << *it << std::endl ; - - std::string hash ; - uint64_t size ; - std::string name ; - RsDirUtil::hashFile( *it,name,hash,size) ; - - std::cerr << "Hash = " << hash << std::endl; - - FILE *f = fopen( (*it).c_str(),"rb" ) ; - - if(f == NULL) - { - std::cerr << "Could not open this file! Sorry." << std::endl ; - return 1 ; - } - CRC32Map crc_map ; - - if(fseek(f,0,SEEK_END)) - { - std::cerr << "Could not fseek to end of this file! Sorry." << std::endl ; - fclose(f) ; - return 1 ; - } - - size = ftell(f) ; - - if(fseek(f,0,SEEK_SET)) - { - std::cerr << "Could not fseek to beginning of this file! Sorry." << std::endl ; - fclose(f) ; - return 1 ; - } - - std::cerr << "File size:" << size << std::endl ; - - RsDirUtil::crc32File(f,size,ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE,crc_map) ; - fclose(f) ; - - std::cerr << "Got this CRC map: "<< std::endl ; - - for(uint32_t i=0;i -#include "ft/ftfilecreator.h" - -#include "util/utest.h" -#include "util/rsdir.h" -#include "util/rsdiscspace.h" -#include - -#include "util/rswin.h" -#include "ft/ftserver.h" - -INITTEST(); - -static void createTmpFile(const std::string& name,uint64_t size,std::string& hash) ; -static void transfer(ftFileProvider *server, const std::string& server_peer_id,ftFileCreator *client,const std::string& client_peer_id) ; - -static const float TRANSFER_FAIL_PROBABILITY = 0.0f ; - -void validateChunksToCheck(const Sha1Map& chunk_crc_map,ftFileCreator *client,const std::string& client_name) -{ - std::vector chunks ; - client->getChunksToCheck(chunks) ; - - if(chunks.size() > 0) - for(uint32_t i=0;iverifyChunk(chunks[i],chunk_crc_map[chunks[i]]) ; - } -} - -void initChunkCrcMap(const std::string& fname,Sha1Map& map) -{ - FILE *fd = fopen(fname.c_str(),"rb") ; - unsigned char *buf = new unsigned char[ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE] ; - - if(fd == NULL) - { - std::cerr << "Cannot read file " << fname << ". Something's wrong!" << std::endl; - delete[] buf ; - exit(1) ; - } - - for(int i=0;isetChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; - client2->setChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) ; - - // 3 - Exchange chunks, and build two copies of the file. - // - std::string peer_id_1("client peer id 1") ; - std::string peer_id_2("client peer id 2") ; - std::string server_id("server peer id") ; - - // 4 - prepare a chunk crc map to verify chunks. - - Sha1Map chunk_crc_map(size,ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE) ; - - initChunkCrcMap(fname,chunk_crc_map) ; - - std::cerr << "Computed chunk CRC map: " << std::endl; - - for(int i=0;ifinished() && client2->finished())) - { - // 1 - select a random client, get the data from him. - - ftFileProvider *tmpserver ; - ftFileCreator *tmpclient ; - std::string tmpserver_pid ; - std::string tmpclient_pid ; - - // choose client and server, randomly, provided that they are not finished. - // - if((!client1->finished()) && (client2->finished() || (lrand48()&1))) - { - //std::cerr << "###### Client 1 asking to " ; - tmpclient = client1 ; - tmpclient_pid = peer_id_1 ; - - if(lrand48()&1) - { - //std::cerr << "Client 2 " ; - tmpserver = client2 ; - tmpserver_pid = peer_id_2 ; - } - else - { - //std::cerr << "Server "; - tmpserver = server ; - tmpserver_pid = server_id ; - } - } - else // client 2 is necessarily unfinished there. - { - //std::cerr << "###### Client 2 asking to " ; - tmpclient = client2 ; - tmpclient_pid = peer_id_2 ; - - if(lrand48()&1) - { - //std::cerr << "Client 1 " ; - tmpserver = client1 ; - tmpserver_pid = peer_id_1 ; - } - else - { - //std::cerr << "Server " ; - tmpserver = server ; - tmpserver_pid = server_id ; - } - - } - - // 2 - transfer from the server to the client. - - transfer(tmpserver,tmpserver_pid,tmpclient,tmpclient_pid) ; - - printf("Client1: %08lld, Client2: %08lld, transfer from %s to %s\r",client1->getRecvd(),client2->getRecvd(),tmpserver_pid.c_str(),tmpclient_pid.c_str()) ; - fflush(stdout) ; - - // Also get chunk checking list from each server, and validate them. - - validateChunksToCheck(chunk_crc_map,client1,"client 1") ; - validateChunksToCheck(chunk_crc_map,client2,"client 2") ; - } - - // hash the received data - - std::string hash1 ; client1->hashReceivedData(hash1) ; - std::string hash2 ; client2->hashReceivedData(hash2) ; - - std::cout << "Hash = " << hash << std::endl ; - std::cout << "Hash1 = " << hash1 << std::endl ; - std::cout << "Hash2 = " << hash2 << std::endl ; - - if(hash != hash1) FAILED("hashs 0/1 defer after transfer !") ; - if(hash != hash2) FAILED("hashs 0/2 defer after transfer !") ; - if(hash1 != hash2) FAILED("hashs 1/2 defer after transfer !") ; - - FINALREPORT("File transfer test"); - - return TESTRESULT(); -} - -void transfer(ftFileProvider *server, const std::string& server_peer_id,ftFileCreator *client,const std::string& client_peer_id) -{ - uint32_t size_hint = 128 + (lrand48()%1000) ; - uint64_t offset = 0; - uint32_t chunk_size = 0; - bool toOld = false ; - - //std::cerr << " for a pending chunk of size " << size_hint ; - - if(! client->getMissingChunk(server_peer_id, size_hint, offset, chunk_size, toOld)) - { - std::cerr << "###### Server does not have any chunk to offer: server is " << server_peer_id << ", client is " << client_peer_id << std::endl ; - // Normally this can't be true, because the ChunkMap class assumes availability for non turtle - // peers. - if(toOld) - { - std::cerr << "###### Map is too old. Transferring chunk map" << std::endl ; - CompressedChunkMap map ; - server->getAvailabilityMap(map) ; - client->setSourceMap(server_peer_id,map) ; - } - return ; - } - - std::cerr << "###### Got chunk " << offset << ", size=" << chunk_size << std::endl ; - - void *data = malloc(chunk_size) ; - std::cerr << "###### Asking data " << offset << ", size=" << chunk_size << std::endl ; - - if( server->getFileData(client_peer_id,offset,chunk_size,data) ) - { - if(drand48() < TRANSFER_FAIL_PROBABILITY) - { - std::cerr << "simulating faulting data chunk " << offset << " + " << chunk_size << "." << std::endl; - } - else - { - client->addFileData(offset,chunk_size,data) ; - std::cerr << "###### Added data " << offset << ", size=" << chunk_size << std::endl ; - } - } - - std::cerr << ", completion=" << client->getRecvd() << std::endl ; - - - free(data) ; -} - -void createTmpFile(const std::string& name,uint64_t S,std::string& hash) -{ - FILE *tmpf = fopen("source_tmp.bin","w") ; - - // write 1MB chunks - uint64_t C = 1024*1024 ; - uint8_t *data = new uint8_t[C] ; - - for(uint i=0;i<=S/C;++i) - { - int Cp = C ; - if(i==S/C) - { - if(S%C>0) - Cp = S%C ; - else - break ; - } - - for(int k=0;krecvDataRequest(peerId,hash,size,offset,chunksize); -} - - /* Server Send */ -bool ftDataSendPair::sendData(const std::string &peerId, const std::string &hash, - uint64_t size, uint64_t offset, uint32_t chunksize, void *data) -{ - return mDataRecv->recvData(peerId, hash,size,offset,chunksize,data); -} - - /* Send a request for a chunk map */ -bool ftDataSendPair::sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) -{ - return mDataRecv->recvChunkMapRequest(peer_id,hash,is_client); -} - - /* Send a chunk map */ -bool ftDataSendPair::sendChunkMap(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap,bool is_client) -{ - return mDataRecv->recvChunkMap(peer_id,hash,cmap, is_client); -} - /* Send a request for a chunk map */ -bool ftDataSendPair::sendCRC32MapRequest(const std::string& peer_id,const std::string& hash) -{ - return mDataRecv->recvCRC32MapRequest(peer_id,hash); -} - - /* Send a chunk map */ -bool ftDataSendPair::sendCRC32Map(const std::string& peer_id,const std::string& hash, const CRC32Map& crcmap) -{ - return mDataRecv->recvCRC32Map(peer_id,hash,crcmap) ; -} - -bool ftDataSendPair::sendSingleChunkCRCRequest(const std::string& peer_id, const std::string& hash, unsigned int c_id) -{ - return mDataRecv->recvSingleChunkCRCRequest(peer_id,hash,c_id) ; -} -bool ftDataSendPair::sendSingleChunkCRC(const std::string& peer_id, const std::string& hash, uint32_t c_id, const Sha1CheckSum& crc) -{ - return mDataRecv->recvSingleChunkCRC(peer_id,hash,c_id,crc) ; -} - /* Client Send */ -bool ftDataSendDummy::sendDataRequest(const std::string &/*peerId*/, const std::string &/*hash*/, - uint64_t /*size*/, uint64_t /*offset*/, uint32_t /*chunksize*/) -{ - return true; -} - - /* Server Send */ -bool ftDataSendDummy::sendData(const std::string &/*peerId*/, const std::string &/*hash*/, - uint64_t /*size*/, uint64_t /*offset*/, uint32_t /*chunksize*/, void */*data*/) -{ - return true; -} - - - /* Send a request for a chunk map */ -bool ftDataSendDummy::sendChunkMapRequest(const std::string& /*peer_id*/,const std::string& /*hash*/,bool /*is_client*/) -{ - return true; -} - - /* Send a chunk map */ -bool ftDataSendDummy::sendChunkMap(const std::string& /*peer_id*/,const std::string& /*hash*/, const CompressedChunkMap& /*cmap*/,bool /*is_client*/) -{ - return true; -} -bool ftDataSendDummy::sendCRC32MapRequest(const std::string& /*peer_id*/,const std::string& /*hash*/) -{ - return true; -} - - /* Send a chunk map */ -bool ftDataSendDummy::sendCRC32Map(const std::string& /*peer_id*/,const std::string& /*hash*/, const CRC32Map& /*cmap*/) -{ - return true; -} - - /* Client Recv */ -bool ftDataRecvDummy::recvData(const std::string &/*peerId*/, const std::string &/*hash*/, - uint64_t /*size*/, uint64_t /*offset*/, uint32_t /*chunksize*/, void */*data*/) -{ - return true; -} - - - /* Server Recv */ -bool ftDataRecvDummy::recvDataRequest(const std::string &/*peerId*/, const std::string &/*hash*/, - uint64_t /*size*/, uint64_t /*offset*/, uint32_t /*chunksize*/) -{ - return true; -} - - /* Send a request for a chunk map */ -bool ftDataRecvDummy::recvChunkMapRequest(const std::string& /*peer_id*/,const std::string& /*hash*/, - bool /*is_client*/) -{ - return true; -} - - /* Send a chunk map */ -bool ftDataRecvDummy::recvChunkMap(const std::string& /*peer_id*/,const std::string& /*hash*/, - const CompressedChunkMap& /*cmap*/,bool /*is_client*/) -{ - return true; -} -bool ftDataRecvDummy::recvSingleChunkCrcRequest(const std::string& peer_id,const std::string& hash,uint32_t chunk_id) -{ - return true ; -} -bool ftDataRecvDummy::recvSingleChunkCrc(const std::string& peer_id,const std::string& hash,uint32_t chunk_id,const Sha1CheckSum& sum) -{ - return true ; -} - -bool ftDataRecvDummy::recvCRC32MapRequest(const std::string& /*peer_id*/,const std::string& /*hash*/) -{ - return true ; -} - - /* Send a chunk map */ -bool ftDataRecvDummy::recvCRC32Map(const std::string& /*peer_id*/,const std::string& /*hash*/, const CompressedChunkMap& /*cmap*/) -{ - return true ; -} - -bool ftDataSendDummy::sendSingleChunkCRCRequest(const std::string&, const std::string&, unsigned int) -{ - return true ; -} -bool ftDataSendDummy::sendSingleChunkCRC(const std::string&, const std::string&, uint32_t, const Sha1CheckSum&) -{ - return true ; -} diff --git a/libretroshare/src/tests/ft/ftdata_dummy.h b/libretroshare/src/tests/ft/ftdata_dummy.h deleted file mode 100644 index 6a30b5606..000000000 --- a/libretroshare/src/tests/ft/ftdata_dummy.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * libretroshare/src/ft: ftdata.h - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef FT_DATA_TEST_INTERFACE_HEADER -#define FT_DATA_TEST_INTERFACE_HEADER - -/* - * ftData. - * - * Internal Interfaces for sending and receiving data. - * Most likely to be implemented by ftServer. - * Provided as an independent interface for testing purposes. - * - */ - -#include -#include - -#include -#include - - /*************** SEND INTERFACE *******************/ - -class CompressedChunkMap ; -class Sha1CheckSum ; - - /**************** FOR TESTING ***********************/ - -/******* Pair of Send/Recv (Only need to handle Send side) ******/ -class ftDataSendPair: public ftDataSend -{ - public: - - ftDataSendPair(ftDataRecv *recv); -virtual ~ftDataSendPair() { return; } - - /* Client Send */ -virtual bool sendDataRequest(const std::string &peerId, const std::string &hash, - uint64_t size, uint64_t offset, uint32_t chunksize); - - /* Server Send */ -virtual bool sendData(const std::string &peerId, const std::string &hash, uint64_t size, - uint64_t offset, uint32_t chunksize, void *data); - - /* Send a request for a chunk map */ -virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client); - - /* Send a chunk map */ -virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap,bool is_client); - - /* Send a request for a chunk map */ -virtual bool sendCRC32MapRequest(const std::string& peer_id,const std::string& hash); - - /* Send a chunk map */ -virtual bool sendCRC32Map(const std::string& peer_id,const std::string& hash, const CRC32Map& cmap); - ftDataRecv *mDataRecv; - - virtual bool sendSingleChunkCRCRequest(const std::string&, const std::string&, uint32_t); - virtual bool sendSingleChunkCRC(const std::string&, const std::string&, uint32_t, const Sha1CheckSum&); -}; - - -class ftDataSendDummy: public ftDataSend -{ - public: - virtual ~ftDataSendDummy() { return; } - - /* Client Send */ - virtual bool sendDataRequest(const std::string &peerId, const std::string &hash, - uint64_t size, uint64_t offset, uint32_t chunksize); - - /* Server Send */ - virtual bool sendData(const std::string &peerId, const std::string &hash, uint64_t size, - uint64_t offset, uint32_t chunksize, void *data); - - /* Send a request for a chunk map */ - virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client); - - /* Send a chunk map */ - virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap,bool is_client); - - /* Send a request for a chunk map */ - virtual bool sendCRC32MapRequest(const std::string& peer_id,const std::string& hash); - - /* Send a chunk map */ - virtual bool sendCRC32Map(const std::string& peer_id,const std::string& hash, const CRC32Map& cmap); - - virtual bool sendSingleChunkCRCRequest(const std::string&, const std::string&, uint32_t); - virtual bool sendSingleChunkCRC(const std::string&, const std::string&, uint32_t, const Sha1CheckSum&); - -}; - -class ftDataRecvDummy: public ftDataRecv -{ - public: - -virtual ~ftDataRecvDummy() { return; } - - /* Client Recv */ -virtual bool recvData(const std::string& peerId, const std::string& hash, - uint64_t size, uint64_t offset, uint32_t chunksize, void *data); - - /* Server Recv */ -virtual bool recvDataRequest(const std::string& peerId, const std::string& hash, - uint64_t size, uint64_t offset, uint32_t chunksize); - - /* Send a request for a chunk map */ -virtual bool recvChunkMapRequest(const std::string& peer_id,const std::string& hash, - bool is_client); - - /* Send a chunk map */ -virtual bool recvChunkMap(const std::string& peer_id,const std::string& hash, - const CompressedChunkMap& cmap,bool is_client); - - /* Send a request for a chunk map */ -virtual bool recvCRC32MapRequest(const std::string& peer_id,const std::string& hash); - - /* Send a chunk map */ -virtual bool recvCRC32Map(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap); - -virtual bool recvSingleChunkCrcRequest(const std::string& peer_id,const std::string& hash,uint32_t chunk_id) ; -virtual bool recvSingleChunkCrc(const std::string& peer_id,const std::string& hash,uint32_t chunk_id,const Sha1CheckSum& sum); -}; - -#endif diff --git a/libretroshare/src/tests/ft/ftdataplextest.cc b/libretroshare/src/tests/ft/ftdataplextest.cc deleted file mode 100644 index 7872aa72d..000000000 --- a/libretroshare/src/tests/ft/ftdataplextest.cc +++ /dev/null @@ -1,200 +0,0 @@ -/* - * libretroshare/src/ft: ftextralisttest.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * Test for Multiplexor..... - * As this is a key middle component, it is hard to test without other bits. - * It relies on ftFileProvider/ftFileCreator/ftTransferModule... - * - * And has dummy ftDataSend and ftSearch. - * - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include -#include -#include -#include "ft/ftextralist.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftfilesearch.h" - -#include "ftdata_dummy.h" -#include "ftsearch_dummy.h" - -void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files); - -INITTEST() ; - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-p ] [-d ] [ ... ] "; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t dPeriod = 600; /* default 10 minutes */ - - std::list fileList; - - while(-1 != (c = getopt(argc, argv, "d:p:"))) - { - switch (c) - { - case 'p': - period = atoi(optarg); - break; - case 'd': - dPeriod = atoi(optarg); - break; - default: - usage(argv[0]); - break; - } - } - - if (optind >= argc) - { - uint32_t N = 4 ; - std::cerr << "Missing Files. Generating " << N << " random files." << std::endl; - - for(uint32_t i=0;istart(); - - ftSearch *ftsd = new ftSearchDummy(); - ftFileSearch *ftfs = new ftFileSearch(); - - ftfs-> addSearchMode(ftsd, RS_FILE_HINTS_LOCAL); - ftfs-> addSearchMode(eList, RS_FILE_HINTS_EXTRA); - - ftDataSend *ftds = new ftDataSendDummy(); - - /* setup Actual Test bit */ - ftDataMultiplex *ftmplex = new ftDataMultiplex("ownId", ftds, ftfs); - ftmplex->start(); - - /* Setup Search with some valid results */ - - - /* Request Data */ - - /* now work the thread */ - std::list::iterator it; - TransferRequestFlags flags(0); - for(it = fileList.begin(); it != fileList.end(); it++) - { - eList->hashExtraFile(*it, dPeriod, flags); - } - - - /* now request files from ftDataMultiplex */ - - /* just request random data packets first */ - do_random_server_test(ftmplex, eList, fileList); - - FINALREPORT("FtDataPlex test") ; - - return TESTRESULT() ; -} - - - -uint32_t do_random_server_iteration(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files) -{ - std::cerr << "do_random_server_iteration()"; - std::cerr << std::endl; - - std::list::iterator it; - uint32_t i = 0; - for(it = files.begin(); it != files.end(); it++) - { - FileInfo info; - if (eList->hashExtraFileDone(*it, info)) - { - std::cerr << "Hash Done for: " << *it; - std::cerr << std::endl; - std::cerr << info << std::endl; - - std::cerr << "Requesting Data Packet"; - std::cerr << std::endl; - - /* Server Recv */ - uint64_t offset = 10000; - uint32_t chunk = 20000; - mplex->recvDataRequest("Peer", info.hash, info.size, offset, chunk); - - i++; - } - else - { - std::cerr << "do_random_server_iteration() Hash Not Done for: " << *it; - std::cerr << std::endl; - } - } - - return i; - -} - - -void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files) -{ - std::cerr << "do_random_server_test()"; - std::cerr << std::endl; - - uint32_t size = files.size(); - while(size > do_random_server_iteration(mplex, eList, files)) - { - std::cerr << "do_random_server_test() sleep"; - std::cerr << std::endl; - - sleep(10); - } -} - - diff --git a/libretroshare/src/tests/ft/ftextralisttest.cc b/libretroshare/src/tests/ft/ftextralisttest.cc deleted file mode 100644 index 65f443eb1..000000000 --- a/libretroshare/src/tests/ft/ftextralisttest.cc +++ /dev/null @@ -1,172 +0,0 @@ -/* - * libretroshare/src/ft: ftextralisttest.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include "ft/ftextralist.h" -#include "util/utest.h" - -extern "C" void* runExtraList(void* p) -{ - ftExtraList *eList = (ftExtraList *) p; - if (!eList) - { - pthread_exit(NULL); - } - - while (1) - { - //eList->tick(); - sleep(1); - - } - - delete eList; - - pthread_exit(NULL); - - return NULL; -} - - - -void displayExtraListDetails(ftExtraList *eList, std::list toHash, std::list hashed); - - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " -h -p -d "; - std::cerr << std::endl; -} - -INITTEST() ; - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t dPeriod = 600; /* default 10 minutes */ - - std::list hashList; - - while(-1 != (c = getopt(argc, argv, "h:p:d:"))) - { - switch (c) - { - case 'h': - hashList.push_back(std::string(optarg)); - break; - case 'p': - period = atoi(optarg); - break; - case 'd': - dPeriod = atoi(optarg); - break; - default: - usage(argv[0]); - break; - } - } - - ftExtraList *eList = new ftExtraList(); - - /* now startup background thread to keep it reunning */ - eList->start(); - - - - /* now work the thread */ - std::list toHash; - std::list hashed; - std::list::iterator it; - - TransferRequestFlags flags(0); - for(it = hashList.begin(); it != hashList.end(); it++) - { - sleep(period); - - /* load up file */ - //eList->addExtraFile(*it); - eList->hashExtraFile(*it, dPeriod, flags); - - toHash.push_back(*it); - - displayExtraListDetails(eList, toHash, hashed); - } - - for(int i=0;i<20;++i) - { - sleep(period); - - displayExtraListDetails(eList, toHash, hashed); - } - - FINALREPORT("Extra list test.") ; - return 0; -} - -void displayExtraListDetails(ftExtraList *eList, std::list toHash, std::list hashed) -{ - std::cerr << "displayExtraListDetails()"; - std::cerr << std::endl; - - std::list::iterator it; - for(it = toHash.begin(); it != toHash.end(); it++) - { - FileInfo info; - if (eList->hashExtraFileDone(*it, info)) - { - std::cerr << "displayExtraListDetails() Hash Completed for: " << *it; - std::cerr << std::endl; - std::cerr << info << std::endl; - } - else - { - std::cerr << "displayExtraListDetails() Hash Not Done for: " << *it; - std::cerr << std::endl; - } - } - - for(it = hashed.begin(); it != hashed.end(); it++) - { - FileInfo info; - if (eList->search(*it, FileSearchFlags(0), info)) - { - std::cerr << "displayExtraListDetails() Found Hash: " << *it; - std::cerr << std::endl; - std::cerr << info << std::endl; - } - else - { - std::cerr << "displayExtraListDetails() Hash Not Found: " << *it; - std::cerr << std::endl; - } - } -} - - - diff --git a/libretroshare/src/tests/ft/ftfilecreatortest.cc b/libretroshare/src/tests/ft/ftfilecreatortest.cc deleted file mode 100644 index ae03ded20..000000000 --- a/libretroshare/src/tests/ft/ftfilecreatortest.cc +++ /dev/null @@ -1,165 +0,0 @@ -#include "ft/ftfilecreator.h" - -#include "util/utest.h" -#include "common/testutils.h" -#include - -#include "util/rswin.h" -#include "util/rsdir.h" -#include "util/rsdiscspace.h" -#include "pqi/p3cfgmgr.h" -#include "ft/ftserver.h" -#include "turtle/p3turtle.h" - -INITTEST(); - -static int test_timeout(ftFileCreator *creator); -static int test_fill(ftFileCreator *creator); - -int main() -{ - RsDiscSpace::setDownloadPath("/tmp") ; - RsDiscSpace::setPartialsPath("/tmp") ; - - /* use ftcreator to create a file on tmp drive */ - std::string hash = TestUtils::createRandomFileHash() ; - uint64_t size = 12943090 ; - - ftFileCreator fcreator1("/tmp/rs-ftfc-test.dta",size,hash,true); - ftFileCreator fcreator2("/tmp/rs-ftfc-test.dta",size,hash,true); - - test_timeout(&fcreator1); - test_fill(&fcreator2); - - FINALREPORT("RsTlvItem Stack Tests"); - - return TESTRESULT(); -} - - -int test_timeout(ftFileCreator *creator) -{ - uint32_t chunk = 1000; - uint64_t offset = 0; - int max_timeout = 5; - int max_offset = chunk * max_timeout; - int i; - std::cerr << "60 second test of chunk queue."; - std::cerr << std::endl; - - uint32_t size_hint = 1000; - std::string peer_id = "dummyId"; - bool toOld = false; - - for(i = 0; i < max_timeout; i++) - { - creator->getMissingChunk(peer_id, size_hint, offset, chunk, toOld); - std::cerr << "Allocated Offset: " << offset << " chunk: " << chunk << std::endl; - - CHECK(offset <= max_offset); - // sleep(1); - } - - std::cerr << "Expect Repeats now"; - std::cerr << std::endl; - - for(i = 0; i < max_timeout; i++) - { - // sleep(1); - creator->getMissingChunk(peer_id, size_hint, offset, chunk, toOld); - std::cerr << "Allocated Offset: " << offset << " chunk: " << chunk << std::endl; - - CHECK(offset <= max_offset); - } - REPORT("Chunk Queue"); - - return 1; -} - - -int test_fill(ftFileCreator *creator) -{ - uint32_t chunk = 1000; - uint64_t offset = 0; - - uint64_t init_size = creator->getFileSize(); - uint64_t init_trans = creator->getRecvd(); - std::cerr << "Initial FileSize: " << init_size << std::endl; - std::cerr << "Initial Transferred:" << init_trans << std::endl; - - uint32_t size_hint = 1000; - std::string peer_id = TestUtils::createRandomSSLId(); - bool toOld = false; - std::cerr << "Allocating data size in memory for " << creator->fileSize() << " bytes." << std::endl; - unsigned char *total_file_data = new unsigned char[creator->fileSize()] ; - - while(creator->getMissingChunk(peer_id, size_hint, offset, chunk, toOld)) - { - if (chunk == 0) - { - std::cerr << "Missing Data already Alloced... wait"; - std::cerr << std::endl; - sleep(1); - chunk = 1000; - continue; - } - - /* give it to them */ - void *data = malloc(chunk); - /* fill with ascending numbers */ - for(int i = 0; i < chunk; i++) - { - ((uint8_t *) data)[i] = 'a' + i % 27; - if (i % 27 == 26) - { - ((uint8_t *) data)[i] = '\n'; - } - } - memcpy(total_file_data+offset,data,chunk) ; - - //std::cerr << " adding file data at offset " << offset << ", size = " << chunk << std::endl; - - creator->addFileData(offset, chunk, data); - free(data); -//#ifndef WINDOWS_SYS -///********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -// usleep(250000); /* 1/4 of sec */ -//#else -///********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -// Sleep(250); /* 1/4 of sec */ -//#endif -///********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - chunk = 1000; /* reset chunk size */ - - } - // validate all chunks - - std::vector chunks_to_check ; - creator->getChunksToCheck(chunks_to_check) ; - - std::cerr << "Validating " << chunks_to_check.size() << " chunks." << std::endl; - - uint32_t CHUNKMAP_SIZE = 1024*1024 ; - - for(uint32_t i=0;ifileSize() - chunks_to_check[i]*CHUNKMAP_SIZE)) ; - Sha1CheckSum crc = RsDirUtil::sha1sum(total_file_data+chunks_to_check[i]*CHUNKMAP_SIZE,chunk_size) ; - std::cerr << " Checking crc for chunk " << chunks_to_check[i] << " of size " << chunk_size << ". Reference is " << crc.toStdString() << std::endl; - creator->verifyChunk(chunks_to_check[i],crc) ; - } - delete[] total_file_data ; - - uint64_t end_size = creator->getFileSize(); - uint64_t end_trans = creator->getRecvd(); - std::cerr << "End FileSize: " << end_size << std::endl; - std::cerr << "End Transferred:" << end_trans << std::endl; - CHECK(init_size == end_size); - CHECK(end_trans == end_size); - - REPORT("Test Fill"); - - return 1; -} - diff --git a/libretroshare/src/tests/ft/ftfilemappertest.cc b/libretroshare/src/tests/ft/ftfilemappertest.cc deleted file mode 100644 index 69c97a3c4..000000000 --- a/libretroshare/src/tests/ft/ftfilemappertest.cc +++ /dev/null @@ -1,91 +0,0 @@ -#include "ft/ftfilemapper.h" -#include "ft/ftchunkmap.h" -#include "retroshare/rstypes.h" - -#include -#include -#include -#include -#include - -INITTEST(); - -int main() -{ - /* Use ftfilemapper to create a file with chunks downloaded on a random direction. */ - - static const std::string tmpdir = "." ; - static const std::string input_file = tmpdir+"/"+"input.bin" ; - static const std::string output_file = tmpdir+"/"+"output.bin" ; - static const uint64_t size = 1024*1024*12+234;//4357283 ; // some size. Not an integer number of chunks - static const uint32_t chunk_size = 1024*1024 ; // 1MB - - pid_t pid = getpid() ; - srand48(pid) ; - srand(pid) ; - std::cerr << "Inited random number generator with seed " << pid << std::endl; - - // 0 - create a random file in memory, of size SIZE - - void *membuf = malloc(size) ; - CHECK(membuf != NULL) ; - - for(int i=0;i - -#include "util/rswin.h" - -INITTEST() - -int main() -{ - std::string ownId = TestUtils::createRandomSSLId() ; - - RsDiscSpace::setPartialsPath("/tmp") ; - RsDiscSpace::setDownloadPath("/tmp") ; - - /* create a random file */ - uint64_t size = 10000000; - uint32_t max_chunk = 10000; - uint32_t chunk = 1000; - uint64_t offset = 0; - - std::string filename = "/tmp/ft_test.dta"; - std::string filename2 = "/tmp/ft_test.dta.dup"; - - std::string hash = TestUtils::createRandomFileHash() ; - - /* use creator to make it */ - - TestUtils::createRandomFile(filename,size) ; - - std::cerr << "Created file: " << filename << " of size: " << size; - std::cerr << std::endl; - - /* load it with file provider */ - ftFileCreator *creator = new ftFileCreator(filename2, size, hash, true); - ftFileProvider *provider = new ftFileProvider(filename, size, hash); - - /* create duplicate with file creator */ - std::string peer_id = TestUtils::createRandomSSLId() ; - uint32_t size_hint = 10000; - bool toOld = false; - unsigned char *data = new unsigned char[max_chunk]; - - while(creator->getMissingChunk(peer_id, size_hint, offset, chunk, toOld)) - { - if (chunk == 0) - { - std::cerr << "All currently allocated .... waiting"; - std::cerr << std::endl; - sleep(1); - /* reset chunk size */ - chunk = (uint64_t) max_chunk * (rand() / (1.0 + RAND_MAX)); - std::cerr << "ChunkSize = " << chunk << std::endl; - continue; - } - - if (!provider->getFileData(ownId,offset, chunk, data)) - { - FAILED("Read from Test Data File"); - std::cerr << "Failed to get data"; - std::cerr << std::endl; - } - - if (!creator->addFileData(offset, chunk, data)) - { - FAILED("Write to Duplicate"); - std::cerr << "Failed to add data"; - std::cerr << std::endl; - } - - std::cerr << "Transferred: " << chunk << " @ " << offset; - std::cerr << std::endl; - - - /* reset chunk size */ - chunk = (uint64_t) max_chunk * (rand() / (1.0 + RAND_MAX)); - - std::cerr << "ChunkSize = " << chunk << std::endl; - } - std::string path,hash2 ; - - RsDirUtil::hashFile(filename ,path,hash,size) ; - RsDirUtil::hashFile(filename2,path,hash2,size) ; - - std::cerr << "Checking hash1 : " << hash << std::endl; - std::cerr << "Checking hash2 : " << hash2 << std::endl; - - CHECK(hash == hash2) ; - - FINALREPORT("ftfilecreatortest") ; - - return TESTRESULT(); -} - diff --git a/libretroshare/src/tests/ft/ftsearch_dummy.cc b/libretroshare/src/tests/ft/ftsearch_dummy.cc deleted file mode 100644 index 72b59d471..000000000 --- a/libretroshare/src/tests/ft/ftsearch_dummy.cc +++ /dev/null @@ -1,16 +0,0 @@ -#include "ftsearch_dummy.h" - -bool ftSearchDummy::search(const std::string& /*hash*/, FileSearchFlags hintflags, FileInfo &/*info*/) const -{ - /* remove unused parameter warnings */ - (void) hintflags; - -#ifdef DEBUG_SEARCH - std::cerr << "ftSearchDummy::search(" << hash ; - std::cerr << ", " << hintflags << ");"; - std::cerr << std::endl; -#endif - return false; -} - - diff --git a/libretroshare/src/tests/ft/ftsearch_dummy.h b/libretroshare/src/tests/ft/ftsearch_dummy.h deleted file mode 100644 index 9a5ffcdff..000000000 --- a/libretroshare/src/tests/ft/ftsearch_dummy.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * libretroshare/src/ft: ftsearch.h - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#pragma once - -#include "ft/ftsearch.h" - -class ftSearchDummy: public ftSearch -{ - public: - - ftSearchDummy() { return; } -virtual ~ftSearchDummy() { return; } -virtual bool search(const std::string& hash, FileSearchFlags hintflags, FileInfo &info) const; -}; - diff --git a/libretroshare/src/tests/ft/ftserver1test.cc b/libretroshare/src/tests/ft/ftserver1test.cc deleted file mode 100644 index d8722eb9c..000000000 --- a/libretroshare/src/tests/ft/ftserver1test.cc +++ /dev/null @@ -1,351 +0,0 @@ -/* - * libretroshare/src/ft: ftserver1test.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * Test for Whole Basic system..... - * - * Put it all together, and make it compile. - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include "ft/ftserver.h" - -#include "ft/ftextralist.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftfilesearch.h" - -#include "pqi/p3linkmgr.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3netmgr.h" - -#include "util/rsdebug.h" -#include "util/utest.h" -#include "common/testutils.h" -#include "retroshare/rsiface.h" - -#include "pqitestor.h" -#include "util/rsdir.h" - -#include - - -INITTEST(); - -void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files); - - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-p ] [-d ] [ ... ] "; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t debugLevel = 5; - bool debugStderr = true; - - std::list fileList; - std::list peerIds; - std::map mFtServers; - std::map mLinkMgrs; - -#ifdef PTW32_STATIC_LIB - pthread_win32_process_attach_np(); -#endif - -#ifdef WIN32 - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif - - - while(-1 != (c = getopt(argc, argv, "d:p:s"))) - { - switch (c) - { - case 'p': - peerIds.push_back(optarg); - break; - case 'd': - debugLevel = atoi(optarg); - break; - case 's': - debugStderr = true; - break; - default: - usage(argv[0]); - break; - } - } - - /* do logging */ - setOutputLevel(debugLevel); - - if (optind >= argc) - { - std::cerr << "Missing Files" << std::endl; - usage(argv[0]); - } - std::cerr << "Point 1" << std::endl; - - for(; optind < argc; optind++) - { - std::cerr << "Adding: " << argv[optind] << std::endl; - - SharedDirInfo info ; - info.filename = std::string(argv[optind]) ; - info.virtualname = info.filename ; - info.shareflags = DIR_FLAGS_PERMISSIONS_MASK ; - info.parent_groups.clear() ; - - fileList.push_back(info); - } - std::cerr << "Point 2" << std::endl; - - std::string ssl_own_id = TestUtils::createRandomSSLId() ; - std::string gpg_own_id = TestUtils::createRandomPGPId() ; - - TestUtils::DummyAuthGPG fakeGPG(gpg_own_id) ; - AuthGPG::setAuthGPG_debug(&fakeGPG) ; - - TestUtils::DummyAuthSSL fakeSSL(ssl_own_id) ; - AuthSSL::setAuthSSL_debug(&fakeSSL) ; - - /* We need to setup a series 2 - 4 different ftServers.... - * - * Each one needs: - * - * - * A List of peerIds... - */ - - std::list::const_iterator it, jit; - - std::list baseFriendList, friendList; - std::list::iterator fit; - - P3Hub *testHub = new P3Hub(0,NULL); - testHub->start(); - - /* Setup Base Friend Info */ - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - RsPeerDetails pad; - pad.id = *it; - pad.gpg_id = TestUtils::createRandomPGPId() ; - pad.name = *it; - pad.trustLvl = 5; - pad.ownsign = true; - //pad.trusted = false; - - baseFriendList.push_back(pad); - - std::cerr << "ftserver1test::setup peer: " << *it << std::endl; - } - - std::ostringstream pname; - pname << "/tmp/rstst-" << time(NULL); - - std::string basepath = pname.str(); - RsDirUtil::checkCreateDirectory(basepath); - - - - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - friendList = baseFriendList; - /* remove current one */ - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - if (fit->id == *it) - { - friendList.erase(fit); - break; - } - } - - //p3AuthMgr *authMgr = new p3DummyAuthMgr(*it, friendList); - p3PeerMgrIMPL *peerMgr = new p3PeerMgrIMPL(ssl_own_id,gpg_own_id,"My GPG name","My SSL location"); - - p3NetMgrIMPL *netMgr = new p3NetMgrIMPL ; - p3LinkMgrIMPL *linkMgr = new p3LinkMgrIMPL(peerMgr,netMgr); - mLinkMgrs[*it] = linkMgr; - - rsPeers = new TestUtils::DummyRsPeers(linkMgr,peerMgr,netMgr) ; - - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - /* add as peer to authMgr */ - peerMgr->addFriend(fit->id,fit->gpg_id); - } - - P3Pipe *pipe = new P3Pipe(); //(*it); - - /* add server */ - ftServer *server; - server = new ftServer(peerMgr,linkMgr); - mFtServers[*it] = server; - - server->setP3Interface(pipe); - - std::string configpath = basepath + "/" + *it; - RsDirUtil::checkCreateDirectory(configpath); - - std::string cachepath = configpath + "/cache"; - RsDirUtil::checkCreateDirectory(cachepath); - - std::string partialspath = configpath + "/partials"; - RsDirUtil::checkCreateDirectory(partialspath); - - std::string downloadpath = configpath + "/downloads"; - RsDirUtil::checkCreateDirectory(downloadpath); - - std::string localpath = cachepath + "/local"; - RsDirUtil::checkCreateDirectory(localpath); - - std::string remotepath = cachepath + "/remote"; - RsDirUtil::checkCreateDirectory(remotepath); - - server->setConfigDirectory(configpath); - - //sleep(60); - - NotifyBase *base = new NotifyBase; - server->SetupFtServer(base); - - testHub->addP3Pipe(*it, pipe, linkMgr); - server->StartupThreads(); - - /* setup any extra bits */ - server->setPartialsDirectory(partialspath); - server->setDownloadDirectory(downloadpath); - server->setSharedDirectories(fileList); - } - - /* stick your real test here */ - std::map::iterator sit; - std::map::iterator cit; - - for(int i=0;i < 20;++i) - { - std::cerr << "ftserver1test::sleep()"; - std::cerr << std::endl; - sleep(1); - - /* tick the connmgrs */ - for(sit = mFtServers.begin(); sit != mFtServers.end(); sit++) - { - /* update */ - (sit->second)->tick(); - } - - for(cit = mLinkMgrs.begin(); cit != mLinkMgrs.end(); cit++) - { - /* update */ - (cit->second)->tick(); - } - } - - FINALREPORT("FtServer running.") ; -} - - -#if 0 - -uint32_t do_random_server_iteration(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files) -{ - std::cerr << "do_random_server_iteration()"; - std::cerr << std::endl; - - std::list::iterator it; - uint32_t i = 0; - for(it = files.begin(); it != files.end(); it++) - { - FileInfo info; - if (eList->hashExtraFileDone(*it, info)) - { - std::cerr << "Hash Done for: " << *it; - std::cerr << std::endl; - std::cerr << info << std::endl; - - std::cerr << "Requesting Data Packet"; - std::cerr << std::endl; - - /* Server Recv */ - uint64_t offset = 10000; - uint32_t chunk = 20000; - mplex->recvDataRequest("Peer", info.hash, info.size, offset, chunk); - - i++; - } - else - { - std::cerr << "do_random_server_iteration() Hash Not Done for: " << *it; - std::cerr << std::endl; - } - } - - return i; - -} - - -void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files) -{ - std::cerr << "do_random_server_test()"; - std::cerr << std::endl; - - uint32_t size = files.size(); - while(size > do_random_server_iteration(mplex, eList, files)) - { - std::cerr << "do_random_server_test() sleep"; - std::cerr << std::endl; - - sleep(10); - } -} - - -#endif - diff --git a/libretroshare/src/tests/ft/ftserver1test.sh b/libretroshare/src/tests/ft/ftserver1test.sh deleted file mode 100755 index 379ecc7fa..000000000 --- a/libretroshare/src/tests/ft/ftserver1test.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -./ftserver1test -p 8cb3a1677872c9e8248fd5ddeac84000 -p 8cb3a1677872c9e8248fd5ddeac84001 -p 8cb3a1677872c9e8248fd5ddeac84002 . diff --git a/libretroshare/src/tests/ft/ftserver2test.cc b/libretroshare/src/tests/ft/ftserver2test.cc deleted file mode 100644 index 84f4c9937..000000000 --- a/libretroshare/src/tests/ft/ftserver2test.cc +++ /dev/null @@ -1,444 +0,0 @@ -/* - * libretroshare/src/ft: ftserver1test.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * Test for Whole Basic system..... - * - * Put it all together, and make it compile. - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include "ft/ftserver.h" - -#include "ft/ftextralist.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftfilesearch.h" - -#include "pqi/p3linkmgr.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3netmgr.h" - -#include "util/rsdebug.h" -#include "util/utest.h" -#include "common/testutils.h" -#include "retroshare/rsiface.h" - -#include "pqitestor.h" -#include "util/rsdir.h" -#include "util/utest.h" - - -#include - - -class TestData -{ - public: - - ftServer *loadServer; - std::list otherServers; - std::list extraList; -}; - - -extern "C" void *do_server_test_thread(void *p); - - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-sa] [-p ] [-d ] [-e ] [ [ ... ]] "; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t debugLevel = 5; - bool debugStderr = true; - bool loadAll = false; - - std::list fileList; - std::list extraList; - std::list peerIds; - std::map mFtServers; - std::map mLinkMgrs; - - ftServer *mLoadServer = NULL; - std::list mOtherServers; - std::list::iterator eit; - -#ifdef PTW32_STATIC_LIB - pthread_win32_process_attach_np(); -#endif - -#ifdef WIN32 - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif - - - while(-1 != (c = getopt(argc, argv, "asd:p:e:"))) - { - switch (c) - { - case 'p': - peerIds.push_back(optarg); - break; - case 'd': - debugLevel = atoi(optarg); - break; - case 's': - debugStderr = true; - break; - case 'e': - extraList.push_back(optarg); - break; - case 'a': - loadAll = true; - break; - default: - usage(argv[0]); - break; - } - } - - /* do logging */ - setOutputLevel(debugLevel); - - if (optind >= argc) - { - std::cerr << "Missing Shared Directories" << std::endl; - usage(argv[0]); - } - - for(; optind < argc; optind++) - { - std::cerr << "Adding: " << argv[optind] << std::endl; - SharedDirInfo info ; - info.shareflags = DIR_FLAGS_PERMISSIONS_MASK; - info.filename = std::string(argv[optind]); - info.virtualname = std::string(argv[optind]); - fileList.push_back(info) ; - } - std::cerr << "Point 2" << std::endl; - - std::string ssl_own_id = TestUtils::createRandomSSLId() ; - std::string gpg_own_id = TestUtils::createRandomPGPId() ; - - TestUtils::DummyAuthGPG fakeGPG(gpg_own_id) ; - AuthGPG::setAuthGPG_debug(&fakeGPG) ; - - TestUtils::DummyAuthSSL fakeSSL(ssl_own_id) ; - AuthSSL::setAuthSSL_debug(&fakeSSL) ; - - /* We need to setup a series 2 - 4 different ftServers.... - * - * Each one needs: - * - * - * A List of peerIds... - */ - - std::list::const_iterator it, jit; - - std::list baseFriendList, friendList; - std::list::iterator fit; - - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - rss->addSerialType(new RsCacheItemSerialiser()); - rss->addSerialType(new RsServiceSerialiser()); - - - P3Hub *testHub = new P3Hub(0, rss); - testHub->start(); - - /* Setup Base Friend Info */ - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - RsPeerDetails pad; - pad.id = *it; - pad.gpg_id = TestUtils::createRandomPGPId() ; - pad.name = *it; - pad.trustLvl = 5; - pad.ownsign = true; - //pad.trusted = false; - - baseFriendList.push_back(pad); - - std::cerr << "ftserver1test::setup peer: " << *it << std::endl; - } - - std::ostringstream pname; - pname << "/tmp/rstst-" << time(NULL); - - std::string basepath = pname.str(); - RsDirUtil::checkCreateDirectory(basepath); - - - - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - friendList = baseFriendList; - /* remove current one */ - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - if (fit->id == *it) - { - friendList.erase(fit); - break; - } - } - - //p3AuthMgr *authMgr = new p3DummyAuthMgr(*it, friendList); - p3PeerMgrIMPL *peerMgr = new p3PeerMgrIMPL(ssl_own_id,gpg_own_id,"My GPG name","My SSL location"); - - p3NetMgrIMPL *netMgr = new p3NetMgrIMPL ; - p3LinkMgrIMPL *linkMgr = new p3LinkMgrIMPL(peerMgr,netMgr); - mLinkMgrs[*it] = linkMgr; - - //rsPeers = new TestUtils::DummyRsPeers(linkMgr,peerMgr,netMgr) ; - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - /* add as peer to authMgr */ - peerMgr->addFriend(fit->id,fit->gpg_id); - linkMgr->addFriend(fit->id,true); - } - - P3Pipe *pipe = new P3Pipe(); //(*it); - - /* add server */ - ftServer *server; - server = new ftServer(peerMgr,linkMgr); - mFtServers[*it] = server; - if (!mLoadServer) - { - mLoadServer = server; - } - else - { - mOtherServers.push_back(server); - } - - server->setP3Interface(pipe); - - std::string configpath = basepath + "/" + *it; - RsDirUtil::checkCreateDirectory(configpath); - - std::string cachepath = configpath + "/cache"; - RsDirUtil::checkCreateDirectory(cachepath); - - std::string partialspath = configpath + "/partials"; - RsDirUtil::checkCreateDirectory(partialspath); - - std::string downloadpath = configpath + "/downloads"; - RsDirUtil::checkCreateDirectory(downloadpath); - - std::string localpath = cachepath + "/local"; - RsDirUtil::checkCreateDirectory(localpath); - - std::string remotepath = cachepath + "/remote"; - RsDirUtil::checkCreateDirectory(remotepath); - - server->setConfigDirectory(configpath); - - //sleep(60); - - NotifyBase *base = new NotifyBase; - server->SetupFtServer(base); - - testHub->addP3Pipe(*it, pipe, linkMgr); - server->StartupThreads(); - - /* setup any extra bits */ - /* everyone gets download directories */ - server->setPartialsDirectory(partialspath); - server->setDownloadDirectory(downloadpath); - - if (loadAll) - { - server->setSharedDirectories(fileList); - for(eit = extraList.begin(); eit != extraList.end(); eit++) - { - server->ExtraFileHash(*eit, 3600, TransferRequestFlags(0)); - } - } - - } - - if (mLoadServer) - { - mLoadServer->setSharedDirectories(fileList); - for(eit = extraList.begin(); eit != extraList.end(); eit++) - { - mLoadServer->ExtraFileHash(*eit, 3600, TransferRequestFlags(0)); - } - } - - /* stick your real test here */ - std::map::iterator sit; - std::map::iterator cit; - - /* Start up test thread */ - pthread_t tid; - TestData *mFt = new TestData; - - /* set data */ - mFt->loadServer = mLoadServer; - mFt->otherServers = mOtherServers; - mFt->extraList = extraList; - - void *data = (void *) mFt; - pthread_create(&tid, 0, &do_server_test_thread, data); - pthread_detach(tid); /* so memory is reclaimed in linux */ - - while(1) - { - std::cerr << "ftserver2test::sleep()"; - std::cerr << std::endl; - sleep(1); - - /* tick the connmgrs */ - for(sit = mFtServers.begin(); sit != mFtServers.end(); sit++) - { - /* update */ - (sit->second)->tick(); - } - - for(cit = mLinkMgrs.begin(); cit != mLinkMgrs.end(); cit++) - { - /* update */ - (cit->second)->tick(); - } - } -} - -/* So our actual test can run here..... - * - */ - -INITTEST(); - -void *do_server_test_thread(void *data) -{ - TestData *mFt = (TestData *) data; - - std::cerr << "do_server_test_thread() running"; - std::cerr << std::endl; - - /************************* TEST 1 ********************** - * Check that the extra List has been processed. - */ - rstime_t start = time(NULL); - - FileInfo info, info2; - rstime_t now = time(NULL); - std::list::iterator eit; - for(eit = mFt->extraList.begin(); eit != mFt->extraList.end(); eit++) - { - while(!mFt->loadServer->ExtraFileStatus(*eit, info)) - { - - /* max of 30 seconds */ - now = time(NULL); - if (now - start > 30) - { - /* FAIL */ - REPORT2( false, "Extra File Hashing"); - } - - sleep(1); - } - - /* Got ExtraFileStatus */ - REPORT("Successfully Found ExtraFile"); - - /* now we can try a search (should succeed) */ - FileSearchFlags hintflags = RS_FILE_HINTS_EXTRA; - - if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) - { - CHECK(info2.hash == info.hash); - CHECK(info2.size == info.size); - CHECK(info2.fname == info.fname); - } - else - { - REPORT2( false, "Search for Extra File (Basic)"); - } - - /* search with flags (should succeed) */ - hintflags = RS_FILE_HINTS_EXTRA; - if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) - { - CHECK(info2.hash == info.hash); - CHECK(info2.size == info.size); - CHECK(info2.fname == info.fname); - } - else - { - REPORT2( false, "Search for Extra File (Extra Flag)"); - } - - /* search with other flags (should fail) */ - hintflags = RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY; - if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) - { - REPORT2( false, "Search for Extra File (Fail Flags)"); - } - else - { - REPORT("Search for Extra File (Fail Flags)"); - } - - /* if we try to download it ... should just find existing one*/ - - REPORT("Testing with Extra File"); - } - - FINALREPORT("ExtraList Hashing, Searching and Downloading"); - exit(1); -} - - - - diff --git a/libretroshare/src/tests/ft/ftserver2test.sh b/libretroshare/src/tests/ft/ftserver2test.sh deleted file mode 100755 index fce1f4fa6..000000000 --- a/libretroshare/src/tests/ft/ftserver2test.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -./ftserver2test -p 8cb3a1677872c9e8248fd5ddeac84000 -p 8cb3a1677872c9e8248fd5ddeac84001 -p 8cb3a1677872c9e8248fd5ddeac84002 . -e ftserver1test ftcontrollertest diff --git a/libretroshare/src/tests/ft/ftserver3test.cc b/libretroshare/src/tests/ft/ftserver3test.cc deleted file mode 100644 index e887eee6b..000000000 --- a/libretroshare/src/tests/ft/ftserver3test.cc +++ /dev/null @@ -1,491 +0,0 @@ -/* - * libretroshare/src/ft: ftserver3test.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * ftServer3Test - Test of the file transfer from a server level. - * Steps: - * 1) load shared directories into others, and let them be - transferred between clients. - * 2) search for local item on others. - * 3) request item on load server. - should transfer from all others simultaneously. - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include -#include "retroshare/rsexpr.h" -#include "retroshare/rstypes.h" -#include "retroshare/rsfiles.h" - -#include "ft/ftserver.h" - -#include "ft/ftextralist.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftfilesearch.h" - -#include "pqi/p3linkmgr.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3netmgr.h" - -#include "util/rsdebug.h" -#include "util/utest.h" -#include "common/testutils.h" -#include "retroshare/rsiface.h" - -#include "pqitestor.h" -#include "util/rsdir.h" -#include "util/utest.h" - - -#include - - -class TestData -{ - public: - - ftServer *loadServer; - std::list otherServers; - std::list extraList; -}; - - -extern "C" void *do_server_test_thread(void *p); - - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-soa] [-p ] [-d ] [-e ] [ [ ... ]] "; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t debugLevel = 5; - bool debugStderr = true; - bool loadAll = false; - bool loadOthers = false; - - std::list fileList; - std::list extraList; - std::list peerIds; - std::map mFtServers; - std::map mLinkMgrs; - - ftServer *mLoadServer = NULL; - std::list mOtherServers; - std::list::iterator eit; - -#ifdef PTW32_STATIC_LIB - pthread_win32_process_attach_np(); -#endif - -#ifdef WIN32 - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif - - - while(-1 != (c = getopt(argc, argv, "aosd:p:e:"))) - { - switch (c) - { - case 'p': - peerIds.push_back(optarg); - break; - case 'd': - debugLevel = atoi(optarg); - break; - case 's': - debugStderr = true; - break; - case 'e': - extraList.push_back(optarg); - break; - case 'a': - loadAll = true; - break; - case 'o': - loadOthers = true; - break; - default: - usage(argv[0]); - break; - } - } - - /* do logging */ - setOutputLevel(debugLevel); - - if (optind >= argc) - { - std::cerr << "Missing Shared Directories" << std::endl; - usage(argv[0]); - } - - for(; optind < argc; optind++) - { - std::cerr << "Adding: " << argv[optind] << std::endl; - - SharedDirInfo info ; - info.filename = std::string(argv[optind]); - info.virtualname = info.filename ; - info.shareflags = DIR_FLAGS_PERMISSIONS_MASK; - - fileList.push_back(info) ; - } - std::cerr << "Point 2" << std::endl; - - std::string ssl_own_id = TestUtils::createRandomSSLId() ; - std::string gpg_own_id = TestUtils::createRandomPGPId() ; - - TestUtils::DummyAuthGPG fakeGPG(gpg_own_id) ; - AuthGPG::setAuthGPG_debug(&fakeGPG) ; - - TestUtils::DummyAuthSSL fakeSSL(ssl_own_id) ; - AuthSSL::setAuthSSL_debug(&fakeSSL) ; - - /* We need to setup a series 2 - 4 different ftServers.... - * - * Each one needs: - * - * - * A List of peerIds... - */ - - std::list::const_iterator it, jit; - - std::list baseFriendList, friendList; - std::list::iterator fit; - - /* Add in Serialiser Test - */ - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - rss->addSerialType(new RsCacheItemSerialiser()); - rss->addSerialType(new RsServiceSerialiser()); - - P3Hub *testHub = new P3Hub(0, rss); - testHub->start(); - - /* Setup Base Friend Info */ - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - RsPeerDetails pad; - pad.id = *it; - pad.gpg_id = TestUtils::createRandomPGPId() ; - pad.name = *it; - pad.trustLvl = 5; - pad.ownsign = true; - //pad.trusted = false; - - baseFriendList.push_back(pad); - - std::cerr << "ftserver1test::setup peer: " << *it << std::endl; - } - - std::ostringstream pname; - pname << "/tmp/rstst-" << time(NULL); - - std::string basepath = pname.str(); - RsDirUtil::checkCreateDirectory(basepath); - - - - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - friendList = baseFriendList; - /* remove current one */ - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - if (fit->id == *it) - { - friendList.erase(fit); - break; - } - } - - //p3AuthMgr *authMgr = new p3DummyAuthMgr(*it, friendList); - p3PeerMgrIMPL *peerMgr = new p3PeerMgrIMPL(ssl_own_id,gpg_own_id,"My GPG name","My SSL location"); - - p3NetMgrIMPL *netMgr = new p3NetMgrIMPL ; - p3LinkMgrIMPL *linkMgr = new p3LinkMgrIMPL(peerMgr,netMgr); - mLinkMgrs[*it] = linkMgr; - - rsPeers = new TestUtils::DummyRsPeers(linkMgr,peerMgr,netMgr) ; - - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - /* add as peer to authMgr */ - peerMgr->addFriend(fit->id,fit->gpg_id); - } - - P3Pipe *pipe = new P3Pipe(); //(*it); - - /* add server */ - ftServer *server; - server = new ftServer(peerMgr,linkMgr); - mFtServers[*it] = server; - bool isOther; - if (!mLoadServer) - { - mLoadServer = server; - isOther = false; - } - else - { - mOtherServers.push_back(server); - isOther = true; - } - - - server->setP3Interface(pipe); - - std::string configpath = basepath + "/" + *it; - RsDirUtil::checkCreateDirectory(configpath); - - std::string cachepath = configpath + "/cache"; - RsDirUtil::checkCreateDirectory(cachepath); - - std::string partialspath = configpath + "/partials"; - RsDirUtil::checkCreateDirectory(partialspath); - - std::string downloadpath = configpath + "/downloads"; - RsDirUtil::checkCreateDirectory(downloadpath); - - std::string localpath = cachepath + "/local"; - RsDirUtil::checkCreateDirectory(localpath); - - std::string remotepath = cachepath + "/remote"; - RsDirUtil::checkCreateDirectory(remotepath); - - server->setConfigDirectory(configpath); - - //sleep(60); - - NotifyBase *base = new NotifyBase; - server->SetupFtServer(base); - - testHub->addP3Pipe(*it, pipe, linkMgr); - server->StartupThreads(); - - /* setup any extra bits */ - server->setPartialsDirectory(partialspath); - server->setDownloadDirectory(downloadpath); - - if ((loadAll) || (isOther && loadOthers)) - { - server->setSharedDirectories(fileList); - for(eit = extraList.begin(); eit != extraList.end(); eit++) - { - server->ExtraFileHash(*eit, 3600, TransferRequestFlags(0)); - } - } - - } - - if ((mLoadServer) && (!loadOthers)) - { - mLoadServer->setSharedDirectories(fileList); - for(eit = extraList.begin(); eit != extraList.end(); eit++) - { - mLoadServer->ExtraFileHash(*eit, 3600, TransferRequestFlags(0)); - } - } - - - /* stick your real test here */ - std::map::iterator sit; - std::map::iterator cit; - - /* Start up test thread */ - pthread_t tid; - TestData *mFt = new TestData; - - /* set data */ - mFt->loadServer = mLoadServer; - mFt->otherServers = mOtherServers; - mFt->extraList = extraList; - - void *data = (void *) mFt; - pthread_create(&tid, 0, &do_server_test_thread, data); - pthread_detach(tid); /* so memory is reclaimed in linux */ - - while(1) - { - //std::cerr << "ftserver3test::sleep()"; - //std::cerr << std::endl; - sleep(1); - - /* tick the connmgrs */ - for(sit = mFtServers.begin(); sit != mFtServers.end(); sit++) - { - /* update */ - (sit->second)->tick(); - } - - for(cit = mLinkMgrs.begin(); cit != mLinkMgrs.end(); cit++) - { - /* update */ - (cit->second)->tick(); - } - } -} - -/* So our actual test can run here..... - * - */ - -INITTEST(); - -void *do_server_test_thread(void *data) -{ - TestData *mFt = (TestData *) data; - rstime_t startTS = time(NULL); - - std::cerr << "do_server_test_thread() running"; - std::cerr << std::endl; - - /* search Others for a suitable file - * (Tests GUI search functionality) - */ - if (mFt->otherServers.size() < 1) - { - std::cerr << "no Other Servers to search on"; - std::cerr << std::endl; - exit(1); - return NULL; - } - - - for(int i = 0; i < 90; i++) - { - int age = time(NULL) - startTS; - std::cerr << "Waited " << age << " seconds to share caches"; - std::cerr << std::endl; - sleep(1); - } - - ftServer *oServer = *(mFt->otherServers.begin()); - std::string oId = oServer->OwnId(); - - /* create Expression */ - uint64_t minFileSize = 1000; - SizeExpression se(Greater, minFileSize); - //SizeExpression se(Smaller, minFileSize); - Expression *expr = &se; - - std::list results; - std::list::iterator it; - - oServer->SearchBoolExp(expr, results, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE); - - if (results.size() < 1) - { - std::cerr << "no Shared Files > " << minFileSize; - std::cerr << std::endl; - exit(1); - return NULL; - } - - /* find the first remote entry */ - DirDetails sFile; - bool foundFile = false; - for(it = results.begin(); (it != results.end()); it++) - { - std::cerr << "Shared File: " << it->name; - std::cerr << std::endl; - - if (!foundFile) - { - if (it->id != mFt->loadServer->OwnId()) - { - std::cerr << "Selected: " << it->name; - std::cerr << std::endl; - foundFile = true; - sFile = *it; - } - else - { - std::cerr << "LoadId: "; - std::cerr << mFt->loadServer->OwnId(); - std::cerr << "FileId: "; - std::cerr << it->id; - std::cerr << std::endl; - } - } - } - - if (!foundFile) - { - std::cerr << "Not Found Suitable File"; - std::cerr << std::endl; - } - - - /*** Now Download it! ***/ - std::list srcIds; - //srcIds.push_back(sFile.id); - // Don't add srcId - to test whether the search works - or not - //srcIds.push_back(oId); - if (foundFile) - { - mFt->loadServer->FileRequest(sFile.name, sFile.hash, sFile.count, "", TransferRequestFlags(0), srcIds); - } - - /* Give it a while to transfer */ - for(int i = 0; i < 100; i++) - { - int age = time(NULL) - startTS; - std::cerr << "Waited " << age << " seconds for tranfer"; - std::cerr << std::endl; - sleep(1); - } - - FINALREPORT("Shared Directories, Bool Search, multi-source transfers"); - exit(1); -} - - - - diff --git a/libretroshare/src/tests/ft/ftserver3test.sh b/libretroshare/src/tests/ft/ftserver3test.sh deleted file mode 100644 index 80ffb1166..000000000 --- a/libretroshare/src/tests/ft/ftserver3test.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -./ftserver3test -p 8cb3a1677872c9e8248fd5ddeac84000 -p 8cb3a1677872c9e8248fd5ddeac84001 -p 8cb3a1677872c9e8248fd5ddeac84002 . ftserver3test diff --git a/libretroshare/src/tests/ft/fttransfermoduletest.cc b/libretroshare/src/tests/ft/fttransfermoduletest.cc deleted file mode 100644 index f98d47a93..000000000 --- a/libretroshare/src/tests/ft/fttransfermoduletest.cc +++ /dev/null @@ -1,182 +0,0 @@ -/* - * libretroshare/src/ft: fttransfermoduletest.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * Test for Multiplexor..... - * As this is a key middle component, it is hard to test without other bits. - * It relies on ftFileProvider/ftFileCreator/ftTransferModule... - * - * And has dummy ftDataSend and ftSearch. - * - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include "ft/ftextralist.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftfilesearch.h" - -#include "ft/ftfileprovider.h" -#include "ft/ftfilecreator.h" -#include "ft/ftcontroller.h" -#include "ft/fttransfermodule.h" - -#include "util/utest.h" -#include "ftdata_dummy.h" -#include "ftsearch_dummy.h" - -INITTEST() - - -void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files); - - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-p ] [-d ] [ ... ] "; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t dPeriod = 600; /* default 10 minutes */ - - std::list fileList; - - while(-1 != (c = getopt(argc, argv, "d:p:"))) - { - switch (c) - { - case 'p': - period = atoi(optarg); - break; - case 'd': - dPeriod = atoi(optarg); - break; - default: - usage(argv[0]); - break; - } - } - - if (optind >= argc) - { - std::cerr << "Missing Files" << std::endl; - usage(argv[0]); - } - - for(; optind < argc; optind++) - { - std::cerr << "Adding: " << argv[optind] << std::endl; - fileList.push_back(std::string(argv[optind])); - } - - ftExtraList *eList = new ftExtraList(); - eList->start(); - - ftSearch *ftsd = new ftSearchDummy(); - ftFileSearch *ftfs = new ftFileSearch(); - - ftfs-> addSearchMode(ftsd, RS_FILE_HINTS_LOCAL); - ftfs-> addSearchMode(eList, RS_FILE_HINTS_EXTRA); - - ftDataSendPair *ftds1 = new ftDataSendPair(NULL); - ftDataSendPair *ftds2 = new ftDataSendPair(NULL); - - /* setup Actual Test bit */ - ftDataMultiplex *ftmplex1 = new ftDataMultiplex("ownId", ftds2, ftfs); - ftDataMultiplex *ftmplex2 = new ftDataMultiplex("ownId", ftds1, ftfs); - - ftds1->mDataRecv = ftmplex1; - ftds2->mDataRecv = ftmplex2; - - ftmplex1->start(); - ftmplex2->start(); - - /* Setup Search with some valid results */ - /* Request Data */ - - /* now work the thread */ - std::list::iterator it; - TransferRequestFlags flags(0); - for(it = fileList.begin(); it != fileList.end(); it++) - { - eList->hashExtraFile(*it, dPeriod, flags); - } - - if (fileList.size() < 1) - { - std::cerr << "come on, give us some files..."; - std::cerr << std::endl; - return 0; - } - - /* now request files from ftDataMultiplex - * by adding in a ftTransferModule! - */ - std::string filename = *(fileList.begin()); - - /* wait for file to hash */ - FileInfo info; - while(!eList->hashExtraFileDone(filename, info)) - { - std::cerr << "Waiting for file to hash"; - std::cerr << std::endl; - sleep(1); - } - - std::string savename = "/tmp/" + info.fname; - ftFileCreator *creator = new ftFileCreator(savename, info.size, info.hash,false); - ftController *controller = NULL; - - ftTransferModule *transfer = new ftTransferModule(creator, ftmplex1, controller); - - ftmplex1->addTransferModule(transfer, creator); - - std::list peerIds; - peerIds.push_back("ownId2"); - - transfer->setFileSources(peerIds); - transfer->setPeerState("ownId2", PQIPEER_IDLE, 1000); - //transfer->resumeTransfer(); - - /* check file progress */ - while(1) - { - std::cerr << "File Transfer Status"; - std::cerr << std::endl; - - std::cerr << "Transfered: " << creator->getRecvd(); - std::cerr << std::endl; - - transfer->tick(); - sleep(1); - } -} - diff --git a/libretroshare/src/tests/ft/pqitestor.cc b/libretroshare/src/tests/ft/pqitestor.cc deleted file mode 100644 index 2e879ff7b..000000000 --- a/libretroshare/src/tests/ft/pqitestor.cc +++ /dev/null @@ -1,333 +0,0 @@ -/* - * libretroshare/src/ft: pqitestor.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "ft/pqitestor.h" -#include "pqi/p3linkmgr.h" - -/****** - *#define HUB_DEBUG 1 - *****/ - -P3Hub::P3Hub(uint32_t flags, RsSerialiser *rss) - :mSerialiser(rss), mUseSerialiser(false) -{ - if (rss) - { - mUseSerialiser = true; - } - return; -} - -void P3Hub::addP3Pipe(std::string id, P3Pipe *pqi, p3LinkMgr *mgr) -{ - hubItem item(id, pqi, mgr); - - std::map::iterator it; - for(it = mPeers.begin(); it != mPeers.end(); it++) - { - sockaddr_in remote_addr ; - (it->second).mLinkMgr->connectResult(id, true, 0,remote_addr); - mgr->connectResult(it->first, true, 0,remote_addr); - } - - mPeers[id] = item; - - /* tell all the other peers we are connected */ - -#ifdef HUB_DEBUG - std::cerr << "P3Hub::addPQIPipe()"; - std::cerr << std::endl; -#endif - -} - -RsItem *P3Hub::SerialiserPass(RsItem *inItem) -{ - /* pass through serialiser */ - - RsItem *item = NULL; - - uint32_t pktsize = mSerialiser->size(inItem); - void *ptr = malloc(pktsize); - -#ifdef HUB_DEBUG - std::cerr << "P3Hub::SerialiserPass() Expected Size: " << pktsize; - std::cerr << std::endl; -#endif - - if (!mSerialiser->serialise(inItem, ptr, &pktsize)) - { - -#ifdef HUB_DEBUG - std::cerr << "P3Hub::SerialiserPass() serialise Failed"; - std::cerr << std::endl; -#endif - - } - else - { - -#ifdef HUB_DEBUG - std::cerr << "P3Hub::SerialiserPass() serialise success, size: " << pktsize; - std::cerr << std::endl; -#endif - - item = mSerialiser->deserialise(ptr, &pktsize); - item->PeerId(inItem->PeerId()); - - if (!item) - { -#ifdef HUB_DEBUG - std::cerr << "P3Hub::SerialiserPass() deSerialise Failed"; - std::cerr << std::endl; -#endif - } - } - - delete inItem; - free(ptr); - return item; -} - - -void P3Hub::run() -{ -#ifdef HUB_DEBUG - std::cerr << "P3Hub::run()"; - std::cerr << std::endl; -#endif - - RsItem *item; - std::list > recvdQ; - std::list >::iterator lit; - while(1) - { -#ifdef HUB_DEBUG - std::cerr << "P3Hub::run()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - for(it = mPeers.begin(); it != mPeers.end(); it++) - { - while (NULL != (item = it->second.mPQI->PopSentItem())) - { -#ifdef HUB_DEBUG - std::cerr << "P3Hub::run() recvd msg from: "; - std::cerr << it->first; - std::cerr << " for " << item->PeerId(); - std::cerr << std::endl; - item->print(std::cerr, 10); - std::cerr << std::endl; -#endif - - if (mUseSerialiser) - { - item = SerialiserPass(item); - } - - /* serialiser might hav munched it. */ - if (item) - { - recvdQ.push_back(make_pair(it->first, item)); - } - } - } - - /* now send out */ - for(lit = recvdQ.begin(); lit != recvdQ.end(); lit++) - { - std::string srcId = lit->first; - std::string destId = (lit->second)->PeerId(); - if (mPeers.end() == (it = mPeers.find(destId))) - { -#ifdef HUB_DEBUG - std::cerr << "Failed to Find destination: " << destId; - std::cerr << std::endl; - std::cerr << "Deleting Packet"; - std::cerr << std::endl; -#endif - - delete (lit->second); - - } - else - { - /* now we have dest, set source Id */ - (lit->second)->PeerId(srcId); -#ifdef HUB_DEBUG - std::cerr << "P3Hub::run() sending msg from: "; - std::cerr << srcId << "to: "; - std::cerr << destId; - std::cerr << std::endl; - (lit->second)->print(std::cerr, 10); - std::cerr << std::endl; -#endif - - (it->second).mPQI->PushRecvdItem(lit->second); - } - } - - recvdQ.clear(); - - - - /* Tick the Connection Managers (normally done by rsserver) - */ - - /* sleep a bit */ -#ifdef WIN32 - Sleep(1000); -#else - sleep(1); -#endif - } -} - - - - - - -PQIPipe::PQIPipe(std::string peerId) - :PQInterface(peerId),pipeMtx("Pipe mutex") -{ - return; -} - -int PQIPipe::SendItem(RsItem *item) -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - mSentItems.push_back(item); - - return 1; -} - -RsItem *PQIPipe::PopSentItem() -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - if (mSentItems.size() == 0) - { - return NULL; - } - - RsItem *item = mSentItems.front(); - mSentItems.pop_front(); - - return item; -} - -int PQIPipe::PushRecvdItem(RsItem *item) -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - mRecvdItems.push_back(item); - - return 1; -} - -RsItem *PQIPipe::GetItem() -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - if (mRecvdItems.size() == 0) - { - return NULL; - } - - RsItem *item = mRecvdItems.front(); - mRecvdItems.pop_front(); - - return item; -} - - - - -/***** P3Pipe here *****/ - - - - -int P3Pipe::SendAllItem(RsItem *item) -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - mSentItems.push_back(item); - - return 1; -} - -RsItem *P3Pipe::PopSentItem() -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - if (mSentItems.size() == 0) - { - return NULL; - } - - RsItem *item = mSentItems.front(); - mSentItems.pop_front(); - - return item; -} - -int P3Pipe::PushRecvdItem(RsItem *item) -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - RsCacheRequest *rcr; - RsCacheItem *rci; - RsFileRequest *rfr; - RsFileData *rfd; - RsRawItem *rri; - - if (NULL != (rcr = dynamic_cast(item))) - { - mRecvdRsCacheRequests.push_back(rcr); - } - else if (NULL != (rci = dynamic_cast(item))) - { - mRecvdRsCacheItems.push_back(rci); - } - else if (NULL != (rfr = dynamic_cast(item))) - { - mRecvdRsFileRequests.push_back(rfr); - } - else if (NULL != (rfd = dynamic_cast(item))) - { - mRecvdRsFileDatas.push_back(rfd); - } - else if (NULL != (rri = dynamic_cast(item))) - { - mRecvdRsRawItems.push_back(rri); - } - - return 1; -} - diff --git a/libretroshare/src/tests/ft/pqitestor.h b/libretroshare/src/tests/ft/pqitestor.h deleted file mode 100644 index 744426e0d..000000000 --- a/libretroshare/src/tests/ft/pqitestor.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * libretroshare/src/ft: pqitestor.h - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef PQI_HUB_TEST_H -#define PQI_HUB_TEST_H - -/* - * pqi Test Interface. - */ - -/*** - * Structures for ftserver simulations - * - ****/ - -#include "pqi/pqi.h" -#include "util/rsthreads.h" -#include "serialiser/rsbaseitems.h" - -#include - -class hubItem; -class PQIPipe; -class PQIHub; -class P3Pipe; -class P3Hub; -class p3LinkMgr; - -class hubItem -{ - public: - hubItem() - :mPQI(NULL), mLinkMgr(NULL) { return; } - - hubItem(std::string id, P3Pipe *pqi, p3LinkMgr *mgr) - :mPeerId(id), mPQI(pqi), mLinkMgr(mgr) { return; } - - std::string mPeerId; - P3Pipe *mPQI; - p3LinkMgr *mLinkMgr; -}; - - -class P3Hub: public RsThread -{ - public: - - P3Hub(uint32_t flags, RsSerialiser *rss); -void addP3Pipe(std::string id, P3Pipe *, p3LinkMgr *mgr); - -virtual void run(); - - private: - -RsItem* SerialiserPass(RsItem *inItem); - - std::map mPeers; - RsSerialiser *mSerialiser; - bool mUseSerialiser; -}; - - -class PQIPipe: public PQInterface -{ -public: - PQIPipe(std::string peerId); - -virtual int SendItem(RsItem *); -virtual RsItem *GetItem(); - - // PQIHub Interface. -RsItem *PopSentItem(); -int PushRecvdItem(RsItem *); - - /* - */ - -private: - - RsMutex pipeMtx; - - std::list mSentItems; - std::list mRecvdItems; - -}; - -class P3Pipe: public P3Interface -{ - public: - P3Pipe() : pipeMtx(std::string("Pipe mutex")) {return; } - virtual ~P3Pipe() {return; } - - virtual int tick() { return 1; } - virtual int status() { return 1; } - - /* Overloaded from P3Interface */ - - virtual RsCacheRequest *RequestedSearch() { return GetSpecificItem(mRecvdRsCacheRequests) ; } - virtual RsCacheItem *GetSearchResult() { return GetSpecificItem(mRecvdRsCacheItems) ; } - virtual RsFileRequest *GetFileRequest() { return GetSpecificItem(mRecvdRsFileRequests) ; } - virtual RsFileData *GetFileData() { return GetSpecificItem(mRecvdRsFileDatas) ; } - virtual RsRawItem *GetRsRawItem() { return GetSpecificItem(mRecvdRsRawItems) ; } - virtual RsFileChunkMapRequest* GetFileChunkMapRequest() { return GetSpecificItem(mRecvdRsChunkMapRequests) ; } - virtual RsFileChunkMap* GetFileChunkMap() { return GetSpecificItem(mRecvdRsChunkMaps) ; } - virtual RsFileCRC32MapRequest* GetFileCRC32MapRequest() { return GetSpecificItem(mRecvdRsCRC32MapRequests) ; } - virtual RsFileCRC32Map* GetFileCRC32Map() { return GetSpecificItem(mRecvdRsCRC32Maps) ; } - virtual RsFileSingleChunkCrcRequest* GetFileSingleChunkCrcRequest() { return GetSpecificItem(mRecvdRsSingleChunkCRCRequests) ; } - virtual RsFileSingleChunkCrc* GetFileSingleChunkCrc() { return GetSpecificItem(mRecvdRsSingleChunkCRCs) ; } - - virtual int SearchSpecific(RsCacheRequest *item) { SendAllItem(item); return 1 ; } - virtual int SendSearchResult(RsCacheItem *item) { SendAllItem(item); return 1 ; } - virtual int SendFileRequest(RsFileRequest *item) { SendAllItem(item); return 1 ; } - virtual int SendFileData(RsFileData *item) { SendAllItem(item); return 1 ; } - virtual int SendRsRawItem(RsRawItem *item) { SendAllItem(item); return 1 ; } - virtual int SendFileChunkMapRequest(RsFileChunkMapRequest*item) { SendAllItem(item); return 1 ; } - virtual int SendFileChunkMap(RsFileChunkMap*item) { SendAllItem(item); return 1 ; } - virtual int SendFileCRC32MapRequest(RsFileCRC32MapRequest*item) { SendAllItem(item); return 1 ; } - virtual int SendFileCRC32Map(RsFileCRC32Map*item) { SendAllItem(item); return 1 ; } - virtual int SendFileSingleChunkCrcRequest(RsFileSingleChunkCrcRequest*item) { SendAllItem(item); return 1 ; } - virtual int SendFileSingleChunkCrc(RsFileSingleChunkCrc*item) { SendAllItem(item); return 1 ; } - - /* Lower Interface for PQIHub */ - - RsItem *PopSentItem(); - int PushRecvdItem(RsItem *item); - - private: - template T *GetSpecificItem(std::list& item_list) - { - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - if (item_list.size() == 0) - return NULL; - - T *item = item_list.front(); - item_list.pop_front(); - - return item; - } - - int SendAllItem(RsItem *item); - - RsMutex pipeMtx; - - std::list mSentItems; - - std::list mRecvdRsCacheRequests; - std::list mRecvdRsCacheItems; - std::list mRecvdRsFileRequests; - std::list mRecvdRsFileDatas; - std::list mRecvdRsRawItems; - std::list mRecvdRsChunkMapRequests; - std::list mRecvdRsChunkMaps; - std::list mRecvdRsCRC32MapRequests; - std::list mRecvdRsCRC32Maps; - std::list mRecvdRsSingleChunkCRCRequests; - std::list mRecvdRsSingleChunkCRCs; -}; - - -#endif diff --git a/libretroshare/src/tests/general/memory_management_test.cc b/libretroshare/src/tests/general/memory_management_test.cc deleted file mode 100644 index 2b680a293..000000000 --- a/libretroshare/src/tests/general/memory_management_test.cc +++ /dev/null @@ -1,61 +0,0 @@ -#ifdef LINUX -#include -#endif -#include -#include -#include -#include -#include "util/utest.h" -#include "serialiser/rsserial.h" - -INITTEST(); - -// Make a fake class of size n. -// -template class RsTestItem: public RsItem -{ - public: - unsigned char buff[n] ; - - RsTestItem(uint32_t s) : RsItem(s) {} - virtual void clear() {} - virtual std::ostream& print(std::ostream& o, uint16_t) { return o ; } -}; - -int main(int argc, char **argv) -{ -#ifdef LINUX - feenableexcept(FE_INVALID) ; - feenableexcept(FE_DIVBYZERO) ; -#endif - typedef RsTestItem<17> Test17 ; - typedef RsTestItem<31> Test31 ; - - std::vector v; - - for(int i=0;i<300;++i) - v.push_back(new Test17(0)) ; - for(int i=0;i<700;++i) - v.push_back(new Test31(0)) ; - - RsMemoryManagement::printStatistics() ; - - // Now delete objects randomly. - // - for(int i=0;i<1000;++i) - { - int indx = lrand48()%(int)v.size() ; - - delete v[indx] ; - v[indx] = v.back() ; - v.pop_back() ; - } - - std::cerr << "After memory free: " << std::endl; - - RsMemoryManagement::printStatistics() ; - - FINALREPORT("memory_management_test"); - exit(TESTRESULT()); -} - diff --git a/libretroshare/src/tests/general/netsetup_test.cc b/libretroshare/src/tests/general/netsetup_test.cc deleted file mode 100644 index 7fe740dfd..000000000 --- a/libretroshare/src/tests/general/netsetup_test.cc +++ /dev/null @@ -1,281 +0,0 @@ - -//#include "pqi/p3connmgr.h" -//#include "pqi/p3authmgr.h" -#include "util/utest.h" - -#include "upnp/upnphandler_linux.h" -#include "dht/opendhtmgr.h" -#include "tcponudp/tou.h" - - -INITTEST(); - -int end_test() -{ - FINALREPORT("net_test1"); - - exit(TESTRESULT()); -} - - -void printNetworkStatus(p3ConnectMgr *connMgr) -{ - std::cerr << "network status for : " << connMgr->getOwnId() << std::endl; - std::cerr << "Net Ok:" << connMgr->getNetStatusOk() << std::endl; - std::cerr << "Upnp Ok:" << connMgr->getNetStatusUpnpOk() << std::endl; - std::cerr << "DHT Ok:" << connMgr->getNetStatusDhtOk() << std::endl; - std::cerr << "Ext Ok:" << connMgr->getNetStatusExtOk() << std::endl; - std::cerr << "Udp Ok:" << connMgr->getNetStatusUdpOk() << std::endl; - std::cerr << "Tcp Ok:" << connMgr->getNetStatusTcpOk() << std::endl; - std::cerr << "network status for : " << connMgr->getOwnId() << std::endl; - - peerConnectState state; - if (connMgr->getOwnNetStatus(state)) - { - std::string txt = textPeerConnectState(state); - std::cerr << "State: " << txt << std::endl; - } - else - { - std::cerr << "No Net Status" << std::endl; - } -} - - -void setupTest(int i, p3ConnectMgr *cMgr) -{ - switch(i) - { - case 1: - { - /* Test One */ - - } - break; - - case 10: - { - /* Test One */ - - } - break; - - case 15: - { - /* Test One */ - - } - break; - - case 20: - { - /* Test One */ - - } - break; - - case 13: - { - /* Test One */ - - } - break; - - default: - std::cerr << "setupTest(" << i << ") no test here" << std::endl; - } -} - -void checkResults(int i, p3ConnectMgr *cMgr) -{ - switch(i) - { - /* Test One: Setup - without any support */ - case 1: - { - /* Expect UDP ports to be established by now */ - - //CHECK(isExternalNet(&loopback_addr)==false); - } - break; - - case 10: - { - /* Expect Local IP Address to be known */ - - } - break; - - case 15: - { - - REPORT("Basic Networking Setup"); - } - break; - - /* Test Two: DHT Running */ - case 111: - { - /* Expect UDP ports to be established by now */ - - //CHECK(isExternalNet(&loopback_addr)==false); - } - break; - - case 110: - { - /* Expect Local IP Address to be known */ - - } - break; - - /* Test 3: */ - case 145: - { - - } - break; - - case 100: - { - /* Test One */ - - } - break; - - case 5000: - { - /* End of Tests */ - end_test(); - } - break; - - default: - { - std::cerr << "checkResults(" << i << ") no test here" << std::endl; - printNetworkStatus(cMgr); - - } - } -} - -class TestMonitor: public pqiMonitor -{ - public: -virtual void statusChange(const std::list &plist) -{ - std::cerr << "TestMonitor::statusChange()"; - std::cerr << std::endl; - std::list::const_iterator it; - for(it = plist.begin(); it != plist.end(); it++) - { - std::cerr << "Event!"; - std::cerr << std::endl; - } -} - -}; - -int main(int argc, char **argv) -{ - /* options */ - bool enable_upnp = true; - bool enable_dht = true; - bool enable_forward = true; - - /* handle options */ - - int testtype = 1; - switch(testtype) - { - case 1: - /* udp test */ - enable_upnp = false; - enable_forward = false; - enable_dht = true; - break; - - } - - -#ifndef WINDOWS_SYS -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - - std::string ownId = "OWNID"; - - /* create a dummy auth mgr */ - p3AuthMgr *authMgr = new p3DummyAuthMgr(); - p3ConnectMgr *connMgr = new p3ConnectMgr(authMgr); - - /* Setup Notify Early - So we can use it. */ - //rsNotify = new p3Notify(); - - pqiNetAssistFirewall *upnpMgr = NULL; - p3DhtMgr *dhtMgr = NULL; - - if (enable_upnp) - { - std::cerr << "Switching on UPnP" << std::endl; - upnpMgr = new upnphandler(); - connMgr->addNetAssistFirewall(1, upnpMgr); - } - - if (enable_dht) - { - p3DhtMgr *dhtMgr = new OpenDHTMgr(ownId, connMgr, "./"); - connMgr->addNetAssistConnect(1, dhtMgr); - - dhtMgr->start(); - std::cerr << "Switching on DHT" << std::endl; - dhtMgr->enable(true); - } - - - /**************************************************************************/ - /* need to Monitor too! */ - - TestMonitor *testmonitor = new TestMonitor(); - connMgr->addMonitor(testmonitor); - - connMgr->checkNetAddress(); - int i; - for(i=0; 1; i++) - { - connMgr->tick(); - - setupTest(i, connMgr); -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - sleep(1); -#else - Sleep(1000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - connMgr->tick(); - - checkResults(i, connMgr); - - tou_tick_stunkeepalive(); - } -} - diff --git a/libretroshare/src/tests/general/pgpkey_test.cc b/libretroshare/src/tests/general/pgpkey_test.cc deleted file mode 100644 index a6b49651f..000000000 --- a/libretroshare/src/tests/general/pgpkey_test.cc +++ /dev/null @@ -1,59 +0,0 @@ -#ifdef LINUX -#include -#endif -#include -#include -#include -#include -#include -#include "util/utest.h" -#include "pgp/pgpkeyutil.h" - -INITTEST(); - -int main(int argc, char **argv) -{ -#ifdef LINUX - feenableexcept(FE_INVALID) ; - feenableexcept(FE_DIVBYZERO) ; -#endif - try - { - if(argc < 2) - { - std::cerr << argv[0] << ": test gpg certificate cleaning method. " << std::endl; - std::cerr << " Usage: " << argv[0] << " certificate.asc" << std::endl; - return 0 ; - } - - FILE *f = fopen(argv[1],"r") ; - - if(f == NULL) - throw std::runtime_error(std::string("Could not open file ") + argv[1]) ; - - std::string cert ; - int c ; - - while((c = getc(f) ) != EOF) - cert += (char)c ; - - std::cerr << "got this certificate: " << std::endl; - std::cerr << cert << std::endl; - - std::cerr << "Calling cert simplification code..." << std::endl; - std::string cleaned_key ; - - PGPKeyManagement::createMinimalKey(cert,cleaned_key) ; - - std::cerr << "Minimal key produced: " << std::endl; - std::cerr << cleaned_key << std::endl; - FINALREPORT("pgpkey_test"); - exit(TESTRESULT()); - } - catch(std::exception& e) - { - std::cerr << "Exception never handled: " << e.what() << std::endl ; - return 1 ; - } -} - diff --git a/libretroshare/src/tests/general/random_test.cc b/libretroshare/src/tests/general/random_test.cc deleted file mode 100644 index 8340b1d67..000000000 --- a/libretroshare/src/tests/general/random_test.cc +++ /dev/null @@ -1,168 +0,0 @@ -#ifdef LINUX -#include -#endif -#include -#include -#include -#include -#include -#include "util/utest.h" -#include "util/rsrandom.h" - -INITTEST(); -typedef double (* Ifctn)( double t); -/* Numerical integration method */ -double Simpson3_8( Ifctn f, double a, double b, int N) -{ - int j; - double l1; - double h = (b-a)/N; - double h1 = h/3.0; - double sum = f(a) + f(b); - - for (j=3*N-1; j>0; j--) { - l1 = (j%3)? 3.0 : 2.0; - sum += l1*f(a+h1*j) ; - } - return h*sum/8.0; -} - -#define A 12 -double Gamma_Spouge( double z ) -{ - int k; - static double cspace[A]; - static double *coefs = NULL; - double accum; - double a = A; - - if (!coefs) { - double k1_factrl = 1.0; - coefs = cspace; - coefs[0] = sqrt(2.0*M_PI); - for(k=1; k 2.0e-8) && (y < x)) y += .4; - if (y>x) y=x; - - return 1.0 - Simpson3_8( &f0, 0, y, std::max(5,(int)(y/h)))/Gamma_Spouge(a); -} - -double chi2Probability( int dof, double distance) -{ - return GammaIncomplete_Q( 0.5*dof, 0.5*distance); -} - -class myThread: public RsThread -{ - public: - myThread() - { - _finished = false ; - } - virtual void run() - { - // test that random numbers are regularly disposed - // - int N = 5000 ; - int B = 8 ; - - std::vector buckets(B,0) ; - - for(int i=0;i significance) - std::cerr << ": passed" << std::endl ; - else - std::cerr << ": failed" << std::endl ; - - _finished = true ; - } - - bool finished() const { return _finished ; } - private: - bool _finished ; -}; - - -int main(int argc, char **argv) -{ -#ifdef LINUX - feenableexcept(FE_INVALID) ; - feenableexcept(FE_DIVBYZERO) ; -#endif - std::cerr << "Generating random 64 chars string (run that again to test that it's changing): " << RSRandom::random_alphaNumericString(64) << std::endl; - std::cerr << "Generating 10 random uint64_t:" << std::endl; - - for(int i=0;i<10;++i) - std::cerr << std::hex << RSRandom::random_u64() << std::endl; - - int nt = 10 ; // number of threads. - std::vector threads(nt,(myThread*)NULL) ; - - for(int i=0;istart() ; - } - - while(true) - { - bool finished = true ; - - for(int i=0;ifinished()) - finished = false ; - - if(finished) - break ; - } - for(int i=0;imGroupId); - randString(SHORT_STR, metaGrp->mOrigGrpId); - randString(SHORT_STR, metaGrp->mAuthorId); - randString(SHORT_STR, metaGrp->mGroupName); - - init_item(metaGrp->signSet); - init_item(metaGrp->keys); - - metaGrp->mPublishTs = rand()%3452; - metaGrp->mGroupFlags = rand()%43; - - metaGrp->mGroupStatus = rand()%313; - metaGrp->mSubscribeFlags = rand()%2251; - metaGrp->mMsgCount = rand()%2421; - metaGrp->mLastPost = rand()%2211; - metaGrp->mPop = rand()%5262; -} - -void init_item(RsGxsMsgMetaData* metaMsg) -{ - - randString(SHORT_STR, metaMsg->mGroupId); - randString(SHORT_STR, metaMsg->mMsgId); - randString(SHORT_STR, metaMsg->mThreadId); - randString(SHORT_STR, metaMsg->mParentId); - randString(SHORT_STR, metaMsg->mAuthorId); - randString(SHORT_STR, metaMsg->mOrigMsgId); - randString(SHORT_STR, metaMsg->mMsgName); - - init_item(metaMsg->signSet); - - metaMsg->mPublishTs = rand()%313; - metaMsg->mMsgFlags = rand()%224; - metaMsg->mMsgStatus = rand()%4242; - metaMsg->mChildTs = rand()%221; -} diff --git a/libretroshare/src/tests/gxs/common/data_support.h b/libretroshare/src/tests/gxs/common/data_support.h deleted file mode 100644 index 930cfbdc1..000000000 --- a/libretroshare/src/tests/gxs/common/data_support.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DATA_SUPPORT_H -#define DATA_SUPPORT_H - -#include "serialiser/rsnxsitems.h" -#include "gxs/rsgxsdata.h" - -bool operator==(const RsNxsGrp&, const RsNxsGrp&); -bool operator==(const RsNxsMsg&, const RsNxsMsg&); - -void init_item(RsNxsGrp& nxg); -void init_item(RsNxsMsg& nxm); -void init_item(RsGxsGrpMetaData* metaGrp); -void init_item(RsGxsMsgMetaData* metaMsg); - -#endif // DATA_SUPPORT_H diff --git a/libretroshare/src/tests/gxs/common/support.cc b/libretroshare/src/tests/gxs/common/support.cc deleted file mode 100644 index 9003b6b60..000000000 --- a/libretroshare/src/tests/gxs/common/support.cc +++ /dev/null @@ -1,340 +0,0 @@ -/* - * libretroshare/src/serialiser: t_support.h.cc - * - * RetroShare Serialiser tests. - * - * Copyright 2007-2008 by Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include - -#include "support.h" -#include "serialiser/rstlvbase.h" - -void randString(const uint32_t length, std::string& outStr) -{ - char alpha = 'a'; - char* stringData = NULL; - - stringData = new char[length]; - - for(uint32_t i=0; i != length; i++) - stringData[i] = alpha + (rand() % 26); - - outStr.assign(stringData, length); - delete[] stringData; - - return; -} - -void randString(const uint32_t length, std::wstring& outStr) -{ - wchar_t alpha = L'a'; - wchar_t* stringData = NULL; - - stringData = new wchar_t[length]; - - for(uint32_t i=0; i != length; i++) - stringData[i] = (alpha + (rand() % 26)); - - outStr.assign(stringData, length); - delete[] stringData; - - return; -} - -void init_item(RsTlvSecurityKeySet& ks) -{ - int n = rand()%24; - randString(SHORT_STR, ks.groupId); - for(int i=1; i::const_iterator l_cit = l.keys.begin(), - r_cit = r.keys.begin(); - - for(; l_cit != l.keys.end(); l_cit++, r_cit++){ - if(l_cit->first != r_cit->first) return false; - if(!(l_cit->second == r_cit->second)) return false; - } - - return true; -} - -bool operator==(const RsTlvSecurityKey& sk1, const RsTlvSecurityKey& sk2) -{ - - if(sk1.startTS != sk2.startTS) return false; - if(sk1.endTS != sk2.endTS) return false; - if(sk1.keyFlags != sk2.keyFlags) return false; - if(sk1.keyId != sk2.keyId) return false; - if(!(sk1.keyData == sk1.keyData)) return false; - - return true; -} - -bool operator==(const RsTlvKeySignatureSet& kss1, const RsTlvKeySignatureSet& kss2) -{ - const std::map& set1 = kss1.keySignSet, - &set2 = kss2.keySignSet; - - if(set1.size() != set2.size()) return false; - - std::map::const_iterator it1 = set1.begin(), it2; - - for(; it1 != set1.end(); it1++) - { - SignType st1 = it1->first; - - if( (it2 =set2.find(st1)) == set2.end()) - return false; - - if(!(it1->second == it2->second)) - return false; - - } - - return true; -} - -bool operator==(const RsTlvKeySignature& ks1, const RsTlvKeySignature& ks2) -{ - - if(ks1.keyId != ks2.keyId) return false; - if(!(ks1.signData == ks2.signData)) return false; - - return true; -} - -bool operator==(const RsTlvPeerIdSet& pids1, const RsTlvPeerIdSet& pids2) -{ - std::list::const_iterator it1 = pids1.ids.begin(), - it2 = pids2.ids.begin(); - - - for(; ((it1 != pids1.ids.end()) && (it2 != pids2.ids.end())); it1++, it2++) - { - if(*it1 != *it2) return false; - } - - return true; - -} - - -void init_item(RsTlvImage& im) -{ - std::string imageData; - randString(LARGE_STR, imageData); - im.binData.setBinData(imageData.c_str(), imageData.size()); - im.image_type = RSTLV_IMAGE_TYPE_PNG; - - return; -} - -void init_item(RsTlvKeySignatureSet &kss) -{ - int numSign = rand()%21; - - for(int i=0; i < numSign; i++) - { - RsTlvKeySignature sign; - SignType sType = rand()%2452; - init_item(sign); - kss.keySignSet.insert(std::make_pair(sType, sign)); - } -} - -bool operator==(const RsTlvBinaryData& bd1, const RsTlvBinaryData& bd2) -{ - if(bd1.tlvtype != bd2.tlvtype) return false; - if(bd1.bin_len != bd2.bin_len) return false; - - unsigned char *bin1 = (unsigned char*)(bd1.bin_data), - *bin2 = (unsigned char*)(bd2.bin_data); - - for(uint32_t i=0; i < bd1.bin_len; bin1++, bin2++, i++) - { - if(*bin1 != *bin2) - return false; - } - - return true; -} - - -void init_item(RsTlvSecurityKey& sk) -{ - int randnum = rand()%313131; - - sk.endTS = randnum; - sk.keyFlags = randnum; - sk.startTS = randnum; - randString(SHORT_STR, sk.keyId); - - std::string randomStr; - randString(LARGE_STR, randomStr); - - sk.keyData.setBinData(randomStr.c_str(), randomStr.size()); - - return; -} - -void init_item(RsTlvKeySignature& ks) -{ - randString(SHORT_STR, ks.keyId); - - std::string signData; - randString(LARGE_STR, signData); - - ks.signData.setBinData(signData.c_str(), signData.size()); - - return; -} - - -bool operator==(const RsTlvImage& img1, const RsTlvImage& img2) -{ - if(img1.image_type != img2.image_type) return false; - if(!(img1.binData == img2.binData)) return false; - - return true; - -} - -/** channels, forums and blogs **/ - -void init_item(RsTlvHashSet& hs) -{ - std::string hash; - - for(int i=0; i < 10; i++) - { - randString(SHORT_STR, hash); - hs.ids.push_back(hash); - } - - hs.mType = TLV_TYPE_HASHSET; - return; -} - -void init_item(RsTlvPeerIdSet& ps) -{ - std::string peer; - - for(int i=0; i < 10; i++) - { - randString(SHORT_STR, peer); - ps.ids.push_back(peer); - } - - ps.mType = TLV_TYPE_PEERSET; - return; -} - -bool operator==(const RsTlvHashSet& hs1,const RsTlvHashSet& hs2) -{ - if(hs1.mType != hs2.mType) return false; - - std::list::const_iterator it1 = hs1.ids.begin(), - it2 = hs2.ids.begin(); - - for(; ((it1 != hs1.ids.end()) && (it2 != hs2.ids.end())); it1++, it2++) - { - if(*it1 != *it2) return false; - } - - return true; -} - -void init_item(RsTlvFileItem& fi) -{ - fi.age = rand()%200; - fi.filesize = rand()%34030313; - randString(SHORT_STR, fi.hash); - randString(SHORT_STR, fi.name); - randString(SHORT_STR, fi.path); - fi.piecesize = rand()%232; - fi.pop = rand()%2354; - init_item(fi.hashset); - - return; -} - -void init_item(RsTlvBinaryData& bd){ - bd.TlvClear(); - std::string data; - randString(LARGE_STR, data); - bd.setBinData(data.data(), data.length()); -} - -void init_item(RsTlvFileSet& fSet){ - - randString(LARGE_STR, fSet.comment); - randString(SHORT_STR, fSet.title); - RsTlvFileItem fi1, fi2; - init_item(fi1); - init_item(fi2); - fSet.items.push_back(fi1); - fSet.items.push_back(fi2); - - return; -} - -bool operator==(const RsTlvFileSet& fs1,const RsTlvFileSet& fs2) -{ - if(fs1.comment != fs2.comment) return false; - if(fs1.title != fs2.title) return false; - - std::list::const_iterator it1 = fs1.items.begin(), - it2 = fs2.items.begin(); - - for(; ((it1 != fs1.items.end()) && (it2 != fs2.items.end())); it1++, it2++) - if(!(*it1 == *it2)) return false; - - return true; -} - -bool operator==(const RsTlvFileItem& fi1,const RsTlvFileItem& fi2) -{ - if(fi1.age != fi2.age) return false; - if(fi1.filesize != fi2.filesize) return false; - if(fi1.hash != fi2.hash) return false; - if(!(fi1.hashset == fi2.hashset)) return false; - if(fi1.name != fi2.name) return false; - if(fi1.path != fi2.path) return false; - if(fi1.piecesize != fi2.piecesize) return false; - if(fi1.pop != fi2.pop) return false; - - return true; -} diff --git a/libretroshare/src/tests/gxs/common/support.h b/libretroshare/src/tests/gxs/common/support.h deleted file mode 100644 index bf33716af..000000000 --- a/libretroshare/src/tests/gxs/common/support.h +++ /dev/null @@ -1,226 +0,0 @@ -#ifndef SUPPORT_H_ -#define SUPPORT_H_ - -/* - * libretroshare/src/tests/serialiser: - * - * RetroShare Serialiser tests. - * - * Copyright 2007-2008 by Christopher Evi-Parker, Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include -#include - -#include "util/utest.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvutil.h" -#include "serialiser/rstlvkeys.h" -#include "serialiser/rstlvtypes.h" - - - -/** - * This contains functions that may be useful for testing throughout the - * retroshare's serialiser - * package, if you find a function you keep using everywhere, might be a good idea to add it here - */ - - -#define SHORT_STR 100 -#define LARGE_STR 1000 - -void randString(const uint32_t, std::string&); -void randString(const uint32_t, std::wstring&); - - -/* for testing compound tlv items */ - -void init_item(RsTlvSecurityKey&); -void init_item(RsTlvKeySignature&); -void init_item(RsTlvKeySignatureSet&); -void init_item(RsTlvBinaryData&); -void init_item(RsTlvFileItem&); -void init_item(RsTlvFileSet&); -void init_item(RsTlvHashSet&); -void init_item(RsTlvPeerIdSet&); -void init_item(RsTlvImage&); -void init_item(RsTlvPeerIdSet&); -void init_item(RsTlvSecurityKeySet& ); - -bool operator==(const RsTlvSecurityKey&, const RsTlvSecurityKey& ); -bool operator==(const RsTlvKeySignature&, const RsTlvKeySignature& ); -bool operator==(const RsTlvBinaryData&, const RsTlvBinaryData&); -bool operator==(const RsTlvFileItem&, const RsTlvFileItem&); -bool operator==(const RsTlvFileSet&, const RsTlvFileSet& ); -bool operator==(const RsTlvHashSet&, const RsTlvHashSet&); -bool operator==(const RsTlvImage&, const RsTlvImage& ); -bool operator==(const RsTlvPeerIdSet& , const RsTlvPeerIdSet& ); -bool operator==(const RsTlvSecurityKeySet& , const RsTlvSecurityKeySet& ); -bool operator==(const RsTlvKeySignatureSet& , const RsTlvKeySignatureSet& ); - - - -/*! - * This templated test function which allows you to test - * retroshare serialiser items (except compound tlv items) - * you the function must implement a function - * - * 'RsSerialType* init_item(YourRsItem& rs_item)' - * which returns valid serialiser that - * can serialiser rs_item. You also need to implement an operator - * - * Also need to implement a function - * 'bool operator =(YourRsItem& rs_itemL, YourRsItem& rs_temR)' - * which allows this function to test for equality between both parameters. - * rs_temR is the result of deserialising the left operand (1st parameter). - * not YourRsItem in specifier in about functions should be a derived type from RsItem - * - * @param T the item you want to test - */ - -template int test_RsItem() -{ - /* make a serialisable RsTurtleItem */ - - RsSerialiser srl; - - /* initialise */ - T rsfi ; - RsSerialType *rsfis = init_item(rsfi) ; - - /* attempt to serialise it before we add it to the serialiser */ - - CHECK(0 == srl.size(&rsfi)); - - static const uint32_t MAX_BUFSIZE = 22000 ; - - char *buffer = new char[MAX_BUFSIZE]; - uint32_t sersize = MAX_BUFSIZE; - - CHECK(false == srl.serialise(&rsfi, (void *) buffer, &sersize)); - - /* now add to serialiser */ - - srl.addSerialType(rsfis); - - uint32_t size = srl.size(&rsfi); - bool done = srl.serialise(&rsfi, (void *) buffer, &sersize); - - std::cerr << "test_Item() size: " << size << std::endl; - std::cerr << "test_Item() done: " << done << std::endl; - std::cerr << "test_Item() sersize: " << sersize << std::endl; - - std::cerr << "test_Item() serialised:" << std::endl; - //displayRawPacket(std::cerr, (void *) buffer, sersize); - - CHECK(done == true); - - uint32_t sersize2 = sersize; - RsItem *output = srl.deserialise((void *) buffer, &sersize2); - - CHECK(output != NULL); - CHECK(sersize2 == sersize); - - T *outfi = dynamic_cast(output); - - CHECK(outfi != NULL); - - if (outfi) - CHECK(*outfi == rsfi) ; - - sersize2 = MAX_BUFSIZE; - bool done2 = srl.serialise(outfi, (void *) &(buffer[16*8]), &sersize2); - - CHECK(done2) ; - CHECK(sersize2 == sersize); - -// displayRawPacket(std::cerr, (void *) buffer, 16 * 8 + sersize2); - - delete[] buffer ; - //delete rsfis; - - return 1; -} - -template int test_RsItem(uint16_t servtype) -{ - /* make a serialisable RsTurtleItem */ - - RsSerialiser srl; - - /* initialise */ - T rsfi(servtype) ; - RsSerialType *rsfis = init_item(rsfi) ; // deleted on destruction of srl - - /* attempt to serialise it before we add it to the serialiser */ - - CHECK(0 == srl.size(&rsfi)); - - static const uint32_t MAX_BUFSIZE = 22000 ; - - char *buffer = new char[MAX_BUFSIZE]; - uint32_t sersize = MAX_BUFSIZE; - - CHECK(false == srl.serialise(&rsfi, (void *) buffer, &sersize)); - - /* now add to serialiser */ - - srl.addSerialType(rsfis); - - uint32_t size = srl.size(&rsfi); - bool done = srl.serialise(&rsfi, (void *) buffer, &sersize); - - std::cerr << "test_Item() size: " << size << std::endl; - std::cerr << "test_Item() done: " << done << std::endl; - std::cerr << "test_Item() sersize: " << sersize << std::endl; - - std::cerr << "test_Item() serialised:" << std::endl; - //displayRawPacket(std::cerr, (void *) buffer, sersize); - - CHECK(done == true); - - uint32_t sersize2 = sersize; - RsItem *output = srl.deserialise((void *) buffer, &sersize2); - - CHECK(output != NULL); - CHECK(sersize2 == sersize); - - T *outfi = dynamic_cast(output); - - CHECK(outfi != NULL); - - if (outfi) - CHECK(*outfi == rsfi) ; - - sersize2 = MAX_BUFSIZE; - bool done2 = srl.serialise(outfi, (void *) &(buffer[16*8]), &sersize2); - - CHECK(done2) ; - CHECK(sersize2 == sersize); - -// displayRawPacket(std::cerr, (void *) buffer, 16 * 8 + sersize2); - - delete[] buffer ; - - return 1; -} -#endif /* SUPPORT_H_ */ diff --git a/libretroshare/src/tests/gxs/data_service/nxs_tests.pro b/libretroshare/src/tests/gxs/data_service/nxs_tests.pro deleted file mode 100644 index 8fa292c61..000000000 --- a/libretroshare/src/tests/gxs/data_service/nxs_tests.pro +++ /dev/null @@ -1,203 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2012-05-06T09:19:26 -# -#------------------------------------------------- - - -# -QT += core network - -QT -= gui - -#CONFIG += gen_exchange_target -CONFIG += nxs_net_test -#CONFIG += dstore_target -#CONFIG += gxsdata_target - -CONFIG += bitdht - - - -#gen_exchange_target { - -#TARGET = gen_exchange_test - -#} - -#nxs_net_test { - -TARGET = nxs_net_test - -#} - -#gxsdata_target { - -#TARGET = gxsdata_test -#} - -CONFIG += console -CONFIG -= app_bundle - -TEMPLATE = app - -CONFIG += debug - -debug { -# DEFINES *= DEBUG -# DEFINES *= OPENDHT_DEBUG DHT_DEBUG CONN_DEBUG DEBUG_UDP_SORTER P3DISC_DEBUG DEBUG_UDP_LAYER FT_DEBUG EXTADDRSEARCH_DEBUG -# DEFINES *= CONTROL_DEBUG FT_DEBUG DEBUG_FTCHUNK P3TURTLE_DEBUG -# DEFINES *= P3TURTLE_DEBUG -# DEFINES *= NET_DEBUG -# DEFINES *= DISTRIB_DEBUG -# DEFINES *= P3TURTLE_DEBUG FT_DEBUG DEBUG_FTCHUNK MPLEX_DEBUG -# DEFINES *= STATUS_DEBUG SERV_DEBUG RSSERIAL_DEBUG #CONN_DEBUG - - QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer - QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer -} -################################# Linux ########################################## -# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib -linux-* { - #CONFIG += version_detail_bash_script - QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 - - system(which gpgme-config >/dev/null 2>&1) { - INCLUDEPATH += $$system(gpgme-config --cflags | sed -e "s/-I//g") - } else { - message(Could not find gpgme-config on your system, assuming gpgme.h is in /usr/include) - } - - PRE_TARGETDEPS *= ../../lib/libretroshare.a - - LIBS += ../../lib/libretroshare.a - LIBS += ../../../../libbitdht/src/lib/libbitdht.a - LIBS += ../../../../openpgpsdk/src/lib/libops.a - LIBS += -lssl -lgpgme -lupnp -lixml -lgnome-keyring -lsqlite3 -lbz2 - LIBS *= -rdynamic -frtti - DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions - DEFINES *= HAS_GNOME_KEYRING -} - -linux-g++ { - OBJECTS_DIR = temp/linux-g++/obj -} - -linux-g++-64 { - OBJECTS_DIR = temp/linux-g++-64/obj -} - -#################################### Windows ##################################### - -win32 { - - DEFINES *= WINDOWS_SYS \ - WIN32 \ - STATICLIB \ - MINGW - # Switch on extra warnings - QMAKE_CFLAGS += -Wextra - QMAKE_CXXFLAGS += -Wextra - - # Switch off optimization for release version - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -O0 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE += -O0 - - # Switch on optimization for debug version - #QMAKE_CXXFLAGS_DEBUG += -O2 - #QMAKE_CFLAGS_DEBUG += -O2 - -# PRE_TARGETDEPS += ../../libretroshare/src/lib/libretroshare.a - PRE_TARGETDEPS += ../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a - - LIBS += ../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a - LIBS += C:\Development\Rs\v0.5-gxs-b1\openpgpsdk\openpgpsdk-build-desktop\lib\libops.a - LIBS += C:\Development\Libraries\sqlite\sqlite-autoconf-3070900\lib\libsqlite3.a - LIBS += -L"../../../../../lib" - LIBS += -lssl -lcrypto -lgpgme -lpthreadGC2d -lminiupnpc -lz -lbz2 -# added after bitdht -# LIBS += -lws2_32 - LIBS += -luuid -lole32 -liphlpapi -lcrypt32 -lgdi32 - LIBS += -lole32 -lwinmm - - # export symbols for the plugins - #LIBS += -Wl,--export-all-symbols,--out-implib,lib/libretroshare-gui.a - - GPG_ERROR_DIR = ../../../../libgpg-error-1.7 - GPGME_DIR = ../../../../gpgme-1.1.8 - GPG_ERROR_DIR = ../../../../lib/libgpg-error-1.7 - GPGME_DIR = ../../../../lib/gpgme-1.1.8 - SSL_DIR = ../../../../../OpenSSL - OPENPGPSDK_DIR = ../../../../openpgpsdk/src - INCLUDEPATH += . $${SSL_DIR}/include $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src \ - $${OPENPGPSDK_DIR} - - SQLITE_DIR = ../../../../../../Libraries/sqlite/sqlite-autoconf-3070900 - INCLUDEPATH += . \ - $${SQLITE_DIR} - - - - -} - -bitdht { - - # Chris version. - #LIBS += ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a - #PRE_TARGETDEPS *= ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a -} - -win32 { -# must be added after bitdht - LIBS += -lws2_32 -} - -version_detail_bash_script { - DEFINES += ADD_LIBRETROSHARE_VERSION_INFO - QMAKE_EXTRA_TARGETS += write_version_detail - PRE_TARGETDEPS = write_version_detail - write_version_detail.commands = ./version_detail.sh -} - -install_rs { - INSTALLS += binary_rs - binary_rs.path = $$(PREFIX)/usr/bin - binary_rs.files = ./RetroShare -} - - -#gen_exchange_target { - -# SOURCES += \ -# support.cc \ -# genexchangetester.cpp \ -# genexchangetestservice.cpp \ -# rsdummyservices.cc \ -# rsgenexchange_test.cc - -# HEADERS += support.h \ -# rsdataservice_test.h \ -# rsdummyservices.h \ -# data_support.h -#} - -nxs_net_test { - - SOURCES += \ - support.cc \ - data_support.cc \ - nxstesthub.cc \ - nxstestscenario.cc \ - rsgxsnetservice_test.cc - - HEADERS += support.h \ - nxstestscenario.h \ - nxstesthub.h \ - data_support.h - -} - -INCLUDEPATH += ../../ diff --git a/libretroshare/src/tests/gxs/data_service/rsdataservice_test.cc b/libretroshare/src/tests/gxs/data_service/rsdataservice_test.cc deleted file mode 100644 index 4cb126cce..000000000 --- a/libretroshare/src/tests/gxs/data_service/rsdataservice_test.cc +++ /dev/null @@ -1,337 +0,0 @@ - -#include "support.h" -#include "data_support.h" -#include "rsdataservice_test.h" -#include "gxs/rsgds.h" -#include "gxs/rsdataservice.h" - -#define DATA_BASE_NAME "msg_grp_Store" - -INITTEST(); -RsGeneralDataService* dStore = NULL; - -void setUp(); -void tearDown(); - -int main() -{ - - std::cerr << "RsDataService Tests" << std::endl; - - test_groupStoreAndRetrieve(); REPORT("test_groupStoreAndRetrieve"); - test_messageStoresAndRetrieve(); REPORT("test_messageStoresAndRetrieve"); - - FINALREPORT("RsDataService Tests"); - - return TESTRESULT(); - -} - - - -/*! - * All memory is disposed off, good for looking - * for memory leaks - */ -void test_groupStoreAndRetrieve(){ - - setUp(); - - int nGrp = rand()%32; - std::map grps, grps_copy; - RsNxsGrp* grp; - RsGxsGrpMetaData* grpMeta; - for(int i = 0; i < nGrp; i++){ - std::pair p; - grp = new RsNxsGrp(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); - grpMeta = new RsGxsGrpMetaData(); - p.first = grp; - p.second = grpMeta; - init_item(*grp); - init_item(grpMeta); - grpMeta->mGroupId = grp->grpId; - grps.insert(p); - RsNxsGrp* grp_copy = new RsNxsGrp(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); - *grp_copy = *grp; - RsGxsGrpMetaData* grpMeta_copy = new RsGxsGrpMetaData(); - *grpMeta_copy = *grpMeta; - grps_copy.insert(std::make_pair(grp_copy, grpMeta_copy )); - grpMeta = NULL; - grp = NULL; - } - - dStore->storeGroup(grps); - - //use copy, a grps are deleted in store - grps.clear(); - grps = grps_copy; - - std::map gR; - std::map grpMetaR; - dStore->retrieveNxsGrps(gR, false, false); - dStore->retrieveGxsGrpMetaData(grpMetaR); - - std::map::iterator mit = grps.begin(); - - bool grpMatch = true, grpMetaMatch = true; - - for(; mit != grps.end(); mit++) - { - const std::string grpId = mit->first->grpId; - - // check if it exists - if(gR.find(grpId) == gR.end()) { - grpMatch = false; - break; - } - - RsNxsGrp *l = mit->first, - *r = gR[grpId]; - - // assign transaction number - // to right to as tn is not stored - // in db - r->transactionNumber = l->transactionNumber; - - // then do a comparison - if(!( *l == *r)) { - grpMatch = false; - break; - } - - // now do a comparison of grp meta types - - if(grpMetaR.find(grpId) == grpMetaR.end()) - { - grpMetaMatch = false; - break; - } - - RsGxsGrpMetaData *l_Meta = mit->second, - *r_Meta = grpMetaR[grpId]; - - if(!(*l_Meta == *r_Meta)) - { - grpMetaMatch = false; - break; - } - - /* release resources */ - delete l_Meta; - delete r_Meta; - delete l; - delete r; - - remove(grpId.c_str()); - } - - grpMetaR.clear(); - - CHECK(grpMatch); - tearDown(); -} - -/*! - * Test for both selective and - * bulk msg retrieval - */ -void test_messageStoresAndRetrieve() -{ - setUp(); - - // first create a grpId - std::string grpId0, grpId1; - - randString(SHORT_STR, grpId0); - randString(SHORT_STR, grpId1); - std::vector grpV; // stores grpIds of all msgs stored and retrieved - grpV.push_back(grpId0); - grpV.push_back(grpId1); - - std::map msgs; - std::map msgs_copy; - RsNxsMsg* msg = NULL; - RsGxsMsgMetaData* msgMeta = NULL; - int nMsgs = rand()%120; - GxsMsgReq req; - - std::map VergrpId0, VergrpId1; - std::map VerMetagrpId0, VerMetagrpId1; - - for(int i=0; i p(msg, msgMeta); - int chosen = 0; - if(rand()%50 > 24){ - chosen = 1; - - } - - const std::string& grpId = grpV[chosen]; - - if(chosen) - req[grpId].push_back(msg->msgId); - - msgMeta->mMsgId = msg->msgId; - msgMeta->mGroupId = msg->grpId = grpId; - - RsNxsMsg* msg_copy = new RsNxsMsg(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); - RsGxsMsgMetaData* msgMeta_copy = new RsGxsMsgMetaData(); - - *msg_copy = *msg; - *msgMeta_copy = *msgMeta; - - // store msgs in map to use for verification - std::pair vP(msg->msgId, msg_copy); - std::pair vPmeta(msg->msgId, msgMeta_copy); - - if(!chosen) - { - VergrpId0.insert(vP); - VerMetagrpId0.insert(vPmeta); - } - else - { - VergrpId1.insert(vP); - VerMetagrpId0.insert(vPmeta); - } - - - - msg = NULL; - msgMeta = NULL; - - msgs.insert(p); - msgs_copy.insert(std::make_pair(msg_copy, msgMeta_copy)); - } - - req[grpV[0]] = std::vector(); // assign empty list for other - - dStore->storeMessage(msgs); - msgs.clear(); - msgs = msgs_copy; - - // now retrieve msgs for comparison - // first selective retrieval - - GxsMsgResult msgResult; - GxsMsgMetaResult msgMetaResult; - dStore->retrieveNxsMsgs(req, msgResult, false); - - dStore->retrieveGxsMsgMetaData(req, msgMetaResult); - - // now look at result for grpId 1 - std::vector& result0 = msgResult[grpId0]; - std::vector& result1 = msgResult[grpId1]; - std::vector& resultMeta0 = msgMetaResult[grpId0]; - std::vector& resultMeta1 = msgMetaResult[grpId1]; - - - - bool msgGrpId0_Match = true, msgGrpId1_Match = true; - bool msgMetaGrpId0_Match = true, msgMetaGrpId1_Match = true; - - // MSG test, selective retrieval - for(std::vector::size_type i = 0; i < result0.size(); i++) - { - RsNxsMsg* l = result0[i] ; - - if(VergrpId0.find(l->msgId) == VergrpId0.end()) - { - msgGrpId0_Match = false; - break; - } - - RsNxsMsg* r = VergrpId0[l->msgId]; - r->transactionNumber = l->transactionNumber; - - if(!(*l == *r)) - { - msgGrpId0_Match = false; - break; - } - } - - CHECK(msgGrpId0_Match); - - // META test - for(std::vector::size_type i = 0; i < resultMeta0.size(); i++) - { - RsGxsMsgMetaData* l = resultMeta0[i] ; - - if(VerMetagrpId0.find(l->mMsgId) == VerMetagrpId0.end()) - { - msgMetaGrpId0_Match = false; - break; - } - - RsGxsMsgMetaData* r = VerMetagrpId0[l->mMsgId]; - - if(!(*l == *r)) - { - msgMetaGrpId0_Match = false; - break; - } - } - - CHECK(msgMetaGrpId0_Match); - - // MSG test, bulk retrieval - for(std::vector::size_type i = 0; i < result1.size(); i++) - { - RsNxsMsg* l = result1[i] ; - - if(VergrpId1.find(l->msgId) == VergrpId1.end()) - { - msgGrpId1_Match = false; - break; - } - - RsNxsMsg* r = VergrpId1[l->msgId]; - - r->transactionNumber = l->transactionNumber; - - if(!(*l == *r)) - { - msgGrpId1_Match = false; - break; - } - } - - CHECK(msgGrpId1_Match); - - //dStore->retrieveGxsMsgMetaData(); - std::string msgFile = grpId0 + "-msgs"; - remove(msgFile.c_str()); - msgFile = grpId1 + "-msgs"; - remove(msgFile.c_str()); - tearDown(); -} - - - -void setUp(){ - dStore = new RsDataService(".", DATA_BASE_NAME, RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -void tearDown(){ - - dStore->resetDataStore(); // reset to clean up store files except db - delete dStore; - dStore = NULL; - int rc = remove(DATA_BASE_NAME); - - if(rc == 0){ - std::cerr << "Successful tear down" << std::endl; - } - else{ - std::cerr << "Tear down failed" << std::endl; - perror("Error: "); - } - -} - diff --git a/libretroshare/src/tests/gxs/data_service/rsdataservice_test.h b/libretroshare/src/tests/gxs/data_service/rsdataservice_test.h deleted file mode 100644 index 89d4a4f5c..000000000 --- a/libretroshare/src/tests/gxs/data_service/rsdataservice_test.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef RSDATASERVICE_TEST_H -#define RSDATASERVICE_TEST_H - -#include "util/rsthreads.h" -#include "serialiser/rsnxsitems.h" -#include "gxs/rsgds.h" - -void test_messageStoresAndRetrieve(); - -void test_groupStoreAndRetrieve(); - -void test_storeAndDeleteGroup(); -void test_storeAndDeleteMessage(); - -void test_searchMsg(); -void test_searchGrp(); - -bool operator ==(const RsGxsGrpMetaData& l, const RsGxsGrpMetaData& r); -bool operator ==(const RsGxsMsgMetaData& l, const RsGxsMsgMetaData& r); - -void test_multiThreaded(); - -class DataReadWrite : RsThread -{ - - - -}; - -void test_cacheSize(); - - -#endif // RSDATASERVICE_TEST_H diff --git a/libretroshare/src/tests/gxs/data_service/rsgxsdata_test.cc b/libretroshare/src/tests/gxs/data_service/rsgxsdata_test.cc deleted file mode 100644 index fa5dc3c6b..000000000 --- a/libretroshare/src/tests/gxs/data_service/rsgxsdata_test.cc +++ /dev/null @@ -1,78 +0,0 @@ - -#include "support.h" -#include "data_support.h" -#include "gxs/rsgxsdata.h" -#include "util/utest.h" - -INITTEST(); - -bool operator ==(const RsGxsGrpMetaData& l, const RsGxsGrpMetaData& r); -bool operator ==(const RsGxsMsgMetaData& l, const RsGxsMsgMetaData& r); - -int main() -{ - - RsGxsGrpMetaData grpMeta1, grpMeta2; - RsGxsMsgMetaData msgMeta1, msgMeta2; - - grpMeta1.clear(); - init_item(&grpMeta1); - - msgMeta1.clear(); - init_item(&msgMeta1); - - uint32_t pktsize = grpMeta1.serial_size(); - char grp_data[pktsize]; - - bool ok = true; - - ok &= grpMeta1.serialise(grp_data, pktsize); - grpMeta2.clear(); - ok &= grpMeta2.deserialise(grp_data, pktsize); - - CHECK(grpMeta1 == grpMeta2); - - pktsize = msgMeta1.serial_size(); - char msg_data[pktsize]; - - ok &= msgMeta1.serialise(msg_data, &pktsize); - msgMeta2.clear(); - ok &= msgMeta2.deserialise(msg_data, &pktsize); - - CHECK(msgMeta1 == msgMeta2); - - FINALREPORT("GxsMeta Data Test"); - - return TESTRESULT(); -} - - -bool operator ==(const RsGxsGrpMetaData& l, const RsGxsGrpMetaData& r) -{ - if(!(l.signSet == r.signSet)) return false; - if(!(l.keys == r.keys)) return false; - if(l.mGroupFlags != r.mGroupFlags) return false; - if(l.mPublishTs != r.mPublishTs) return false; - if(l.mAuthorId != r.mAuthorId) return false; - if(l.mGroupName != r.mGroupName) return false; - if(l.mGroupId != r.mGroupId) return false; - - return true; -} - -bool operator ==(const RsGxsMsgMetaData& l, const RsGxsMsgMetaData& r) -{ - - if(!(l.signSet == r.signSet)) return false; - if(l.mGroupId != r.mGroupId) return false; - if(l.mAuthorId != r.mAuthorId) return false; - if(l.mParentId != r.mParentId) return false; - if(l.mOrigMsgId != r.mOrigMsgId) return false; - if(l.mThreadId != r.mThreadId) return false; - if(l.mMsgId != r.mMsgId) return false; - if(l.mMsgName != r.mMsgName) return false; - if(l.mPublishTs != r.mPublishTs) return false; - if(l.mMsgFlags != r.mMsgFlags) return false; - - return true; -} diff --git a/libretroshare/src/tests/gxs/gen_exchange/genexchange_test.pro b/libretroshare/src/tests/gxs/gen_exchange/genexchange_test.pro deleted file mode 100644 index d95c4bcd4..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/genexchange_test.pro +++ /dev/null @@ -1,180 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2012-05-06T09:19:26 -# -#------------------------------------------------- - - -# -QT += core network - -QT -= gui - -CONFIG += gen_exchange_target - - -CONFIG += bitdht - - - -TARGET = gen_exchange_test - -CONFIG += console -CONFIG -= app_bundle - -TEMPLATE = app - -CONFIG += debug - -debug { -# DEFINES *= DEBUG -# DEFINES *= OPENDHT_DEBUG DHT_DEBUG CONN_DEBUG DEBUG_UDP_SORTER P3DISC_DEBUG DEBUG_UDP_LAYER FT_DEBUG EXTADDRSEARCH_DEBUG -# DEFINES *= CONTROL_DEBUG FT_DEBUG DEBUG_FTCHUNK P3TURTLE_DEBUG -# DEFINES *= P3TURTLE_DEBUG -# DEFINES *= NET_DEBUG -# DEFINES *= DISTRIB_DEBUG -# DEFINES *= P3TURTLE_DEBUG FT_DEBUG DEBUG_FTCHUNK MPLEX_DEBUG -# DEFINES *= STATUS_DEBUG SERV_DEBUG RSSERIAL_DEBUG #CONN_DEBUG - - QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer - QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer -} -################################# Linux ########################################## -# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib -linux-* { - #CONFIG += version_detail_bash_script - QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 - - system(which gpgme-config >/dev/null 2>&1) { - INCLUDEPATH += $$system(gpgme-config --cflags | sed -e "s/-I//g") - } else { - message(Could not find gpgme-config on your system, assuming gpgme.h is in /usr/include) - } - - PRE_TARGETDEPS *= ../../../lib/libretroshare.a - - LIBS += ../../../lib/libretroshare.a - LIBS += ../../../../../libbitdht/src/lib/libbitdht.a - LIBS += ../../../../../openpgpsdk/src/lib/libops.a - LIBS += -lssl -lgpgme -lupnp -lixml -lgnome-keyring -lbz2 - # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. - LIBS += /home/crispy/Development/retroshare/sqlcipher/sqlcipher/.libs/libsqlite3.a - LIBS *= -rdynamic -frtti - DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions - DEFINES *= HAS_GNOME_KEYRING -} - -linux-g++ { - OBJECTS_DIR = temp/linux-g++/obj -} - -linux-g++-64 { - OBJECTS_DIR = temp/linux-g++-64/obj -} - -#################################### Windows ##################################### - -win32 { - - DEFINES *= WINDOWS_SYS \ - WIN32 \ - STATICLIB \ - MINGW - # Switch on extra warnings - QMAKE_CFLAGS += -Wextra - QMAKE_CXXFLAGS += -Wextra - - # Switch off optimization for release version - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -O0 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE += -O0 - - # Switch on optimization for debug version - #QMAKE_CXXFLAGS_DEBUG += -O2 - #QMAKE_CFLAGS_DEBUG += -O2 - -# PRE_TARGETDEPS += ../../libretroshare/src/lib/libretroshare.a - PRE_TARGETDEPS += ../../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a - - LIBS += ../../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a - LIBS += C:\Development\Rs\v0.5-gxs-b1\openpgpsdk\openpgpsdk-build-desktop\lib\libops.a - LIBS += C:\Development\Libraries\sqlite\sqlite-autoconf-3070900\lib\libsqlite3.a - LIBS += -L"../../../../../lib" - LIBS += -lssl -lcrypto -lgpgme -lpthreadGC2d -lminiupnpc -lz -lbz2 -# added after bitdht -# LIBS += -lws2_32 - LIBS += -luuid -lole32 -liphlpapi -lcrypt32 -lgdi32 - LIBS += -lole32 -lwinmm - - # export symbols for the plugins - #LIBS += -Wl,--export-all-symbols,--out-implib,lib/libretroshare-gui.a - - GPG_ERROR_DIR = ../../../../libgpg-error-1.7 - GPGME_DIR = ../../../../gpgme-1.1.8 - GPG_ERROR_DIR = ../../../../lib/libgpg-error-1.7 - GPGME_DIR = ../../../../lib/gpgme-1.1.8 - SSL_DIR = ../../../../../OpenSSL - OPENPGPSDK_DIR = ../../../../openpgpsdk/src - INCLUDEPATH += . $${SSL_DIR}/include $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src \ - $${OPENPGPSDK_DIR} - - SQLITE_DIR = ../../../../../../Libraries/sqlite/sqlite-autoconf-3070900 - INCLUDEPATH += . \ - $${SQLITE_DIR} - - - - -} - -bitdht { - - # Chris version. - #LIBS += ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a - #PRE_TARGETDEPS *= ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a -} - -win32 { -# must be added after bitdht - LIBS += -lws2_32 -} - -version_detail_bash_script { - DEFINES += ADD_LIBRETROSHARE_VERSION_INFO - QMAKE_EXTRA_TARGETS += write_version_detail - PRE_TARGETDEPS = write_version_detail - write_version_detail.commands = ./version_detail.sh -} - -install_rs { - INSTALLS += binary_rs - binary_rs.path = $$(PREFIX)/usr/bin - binary_rs.files = ./RetroShare -} - - -gen_exchange_target { - - SOURCES += \ - ../common/support.cc \ - genexchangetester.cpp \ - genexchangetestservice.cpp \ - rsdummyservices.cc \ - gxspublishgrouptest.cc \ - gxspublishmsgtest.cc \ - rsgenexchange_test.cc - - HEADERS += ../common/support.h \ - ../data_service/rsdataservice_test.h \ - gxspublishgrouptest.h \ - gxspublishmsgtest.h \ - rsdummyservices.h \ - ../common/data_support.h \ - ../common/support.h - -} - - -INCLUDEPATH += ../../../ -INCLUDEPATH += ../common diff --git a/libretroshare/src/tests/gxs/gen_exchange/genexchangetester.cpp b/libretroshare/src/tests/gxs/gen_exchange/genexchangetester.cpp deleted file mode 100644 index f46594d9a..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/genexchangetester.cpp +++ /dev/null @@ -1,589 +0,0 @@ -#include "genexchangetester.h" -#include "support.h" -#include "gxs/rsdataservice.h" -#include "retroshare/rsgxsflags.h" - - -GenExchangeTest::GenExchangeTest(GenExchangeTestService* const mTestService, RsGeneralDataService* dataService, int pollingTO) - : mDataService(dataService), mTestService(mTestService), mTokenService(mTestService->getTokenService()), - mPollingTO(pollingTO) -{ -} - -GenExchangeTest::~GenExchangeTest() -{ -} - - -void GenExchangeTest::pollForToken(uint32_t token, const RsTokReqOptions &opts, bool fill) -{ - double timeDelta = 0.2; - rstime_t now = time(NULL); - rstime_t stopw = now + mPollingTO; - - while(now < stopw) - { -#ifndef WINDOWS_SYS - usleep((int) (timeDelta * 1000000)); -#else - Sleep((int) (timeDelta * 1000)); -#endif - - if((RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == mTokenService->requestStatus(token))) - { - switch(opts.mReqType) - { - case GXS_REQUEST_TYPE_GROUP_DATA: - if(fill) - mTestService->getGroupDataTS(token, mGrpDataIn); - break; - case GXS_REQUEST_TYPE_GROUP_META: - if(fill) - mTestService->getGroupMetaTS(token, mGrpMetaDataIn); - break; - case GXS_REQUEST_TYPE_GROUP_IDS: - if(fill) - mTestService->getGroupListTS(token, mGrpIdsIn); - break; - case GXS_REQUEST_TYPE_MSG_DATA: - if(fill) - mTestService->getMsgDataTS(token, mMsgDataIn); - break; - case GXS_REQUEST_TYPE_MSG_META: - if(fill) - mTestService->getMsgMetaTS(token, mMsgMetaDataIn); - break; - case GXS_REQUEST_TYPE_MSG_IDS: - if(fill) - mTestService->getMsgListTS(token, mMsgIdsIn); - break; - case GXS_REQUEST_TYPE_MSG_RELATED_IDS: - if(fill) - mTestService->getMsgRelatedListTS(token, mMsgRelatedIdsIn); - break; - case GXS_REQUEST_TYPE_MSG_RELATED_DATA: - if(fill) - mTestService->getMsgRelatedDataTS(token, mMsgRelatedDataMapIn); - break; - } - break; - } - else if(RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == mTokenService->requestStatus(token)) - { - mTokenService->cancelRequest(token); - break; - } - now = time(NULL); - } -} - - - -bool GenExchangeTest::pollForMsgAcknowledgement(uint32_t token, - RsGxsGrpMsgIdPair& msgId) -{ - double timeDelta = 0.2; - - rstime_t now = time(NULL); - rstime_t stopw = now + mPollingTO; - - while(now < stopw) - { -#ifndef WINDOWS_SYS - usleep((int) (timeDelta * 1000000)); -#else - Sleep((int) (timeDelta * 1000)); -#endif - - if((RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == mTokenService->requestStatus(token))) - { - mTestService->acknowledgeTokenMsg(token, msgId); - return true; - } - else if(RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == mTokenService->requestStatus(token)) - { - mTokenService->cancelRequest(token); - return false; - } - now = time(NULL); - } - return false; -} - -GenExchangeTestService* GenExchangeTest::getTestService() -{ - return mTestService; -} - -RsTokenService* GenExchangeTest::getTokenService() -{ - return mTokenService; -} -bool GenExchangeTest::pollForGrpAcknowledgement(uint32_t token, - RsGxsGroupId& grpId) -{ - double timeDelta = 0.2; - rstime_t now = time(NULL); - rstime_t stopw = now + mPollingTO; - while(now < stopw) - { -#ifndef WINDOWS_SYS - usleep((int) (timeDelta * 1000000)); -#else - Sleep((int) (timeDelta * 1000)); -#endif - - if((RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == mTokenService->requestStatus(token))) - { - mTestService->acknowledgeTokenGrp(token, grpId); - return true; - } - else if(RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == mTokenService->requestStatus(token)) - { - mTokenService->cancelRequest(token); - return false; - } - now = time(NULL); - } - return false; -} - -void GenExchangeTest::setUp() -{ - mDataService->resetDataStore(); - - // would be useful for genexchange services - // to have a protected reset button - mTestService->start(); -} - -void GenExchangeTest::breakDown() -{ - mDataService->resetDataStore(); - mTestService->join(); - clearAllData(); -} - -bool msgDataSort(const RsDummyMsg* m1, const RsDummyMsg* m2) -{ - return m1->meta.mMsgId < m2->meta.mMsgId; -} - -bool GenExchangeTest::compareMsgDataMaps() -{ - DummyMsgMap::iterator mit = mMsgDataOut.begin(); - - bool ok = true; - for(; mit != mMsgDataOut.end(); mit++) - { - const RsGxsGroupId& grpId = mit->first; - std::vector& v1 = mit->second, - &v2 = mMsgDataIn[grpId]; - - if(v1.size() != v2.size()) - return false; - - std::sort(v1.begin(), v1.end(), msgDataSort); - std::sort(v2.begin(), v2.end(), msgDataSort); - - ok &= Comparison, RsDummyMsg*>::comparison(v1, v2); - } - - return ok; -} - - -bool GenExchangeTest::compareMsgIdMaps() -{ - GxsMsgIdResult::const_iterator mit = mMsgIdsOut.begin(); - bool ok = true; - for(; mit != mMsgIdsOut.end(); mit++) - { - const RsGxsGroupId& grpId = mit->first; - const std::vector& v1 = mit->second, - &v2 = mMsgIdsIn[grpId]; - - ok &= Comparison, RsGxsMessageId>::comparison(v1, v2); - } - return ok; -} - - -bool GenExchangeTest::compareMsgMetaMaps() -{ - GxsMsgMetaMap::iterator mit = mMsgMetaDataOut.begin(); - bool ok = true; - for(; mit != mMsgMetaDataOut.end(); mit++) - { - const RsGxsGroupId& grpId = mit->first; - const std::vector& v1 = mit->second, - &v2 = mMsgMetaDataOut[grpId]; - ok &= Comparison, RsMsgMetaData>::comparison(v1, v2); - } - return ok; -} - - -bool GenExchangeTest::compareMsgRelateIdsMap() -{ - return false; -} - - -bool GenExchangeTest::compareMsgRelatedDataMap() -{ - return false; -} - -bool grpDataSort(const RsDummyGrp* g1, const RsDummyGrp* g2) -{ - return g1->meta.mGroupId < g2->meta.mGroupId; -} - -bool GenExchangeTest::compareGrpData() -{ - - std::sort(mGrpDataIn.begin(), mGrpDataIn.end(), grpDataSort); - std::sort(mGrpDataOut.begin(), mGrpDataOut.end(), grpDataSort); - bool ok = Comparison, RsDummyGrp*>::comparison - (mGrpDataIn, mGrpDataOut); - return ok; -} - -bool operator<(const RsGroupMetaData& l, const RsGroupMetaData& r) -{ - return l.mGroupId < r.mGroupId; -} - -bool GenExchangeTest::compareGrpMeta() -{ - - mGrpMetaDataIn.sort(); - mGrpMetaDataOut.sort(); - - bool ok = Comparison, RsGroupMetaData>::comparison - (mGrpMetaDataIn, mGrpMetaDataOut); - return ok; -} - - -bool GenExchangeTest::compareGrpIds() -{ - mGrpIdsIn.sort(); - mGrpIdsOut.sort(); - bool ok = Comparison, RsGxsGroupId>::comparison - (mGrpIdsIn, mGrpIdsOut); - return ok; -} - -void GenExchangeTest::createGrps(uint32_t nGrps, - std::list& groupId) -{ - // create n groups and publish all nGrps and collect id information - for(uint32_t i=0; i < nGrps; i++) - { - RsDummyGrp* grp = new RsDummyGrp(); - init(*grp); - uint32_t token; - mTestService->publishDummyGrp(token, grp); - RsGxsGroupId grpId; - pollForGrpAcknowledgement(token, grpId); - groupId.push_back(grpId); - } -} - -void GenExchangeTest::init(RsMsgMetaData& msgMetaData) const -{ - //randString(SHORT_STR, msgMeta.mAuthorId); - randString(SHORT_STR, msgMetaData.mMsgName); - randString(SHORT_STR, msgMetaData.mServiceString); - randString(SHORT_STR, msgMetaData.mOrigMsgId); - randString(SHORT_STR, msgMetaData.mParentId); - randString(SHORT_STR, msgMetaData.mThreadId); - randString(SHORT_STR, msgMetaData.mGroupId); - - msgMetaData.mChildTs = randNum(); - msgMetaData.mMsgStatus = randNum(); - msgMetaData.mMsgFlags = randNum(); - msgMetaData.mPublishTs = randNum(); -} - -uint32_t GenExchangeTest::randNum() const -{ - return rand()%23562424; -} - -void GenExchangeTest::init(RsGroupMetaData& grpMetaData) const -{ - randString(SHORT_STR, grpMetaData.mGroupId); - //randString(SHORT_STR, grpMetaData.mAuthorId); - randString(SHORT_STR, grpMetaData.mGroupName); - randString(SHORT_STR, grpMetaData.mServiceString); - - - grpMetaData.mGroupFlags = randNum(); - grpMetaData.mLastPost = randNum(); - grpMetaData.mGroupStatus = randNum(); - grpMetaData.mMsgCount = randNum(); - grpMetaData.mPop = randNum(); - grpMetaData.mSignFlags = randNum(); - grpMetaData.mPublishTs = randNum(); - grpMetaData.mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN; -} - -void GenExchangeTest::init(RsDummyGrp& grpItem) const -{ - randString(SHORT_STR, grpItem.grpData); - init(grpItem.meta); -} - - -void GenExchangeTest::init(RsDummyMsg& msgItem) const -{ - randString(SHORT_STR, msgItem.msgData); - init(msgItem.meta); -} - -void GenExchangeTest::storeToMsgDataOutMaps(const DummyMsgMap& msgDataOut) -{ - mMsgDataOut.insert(msgDataOut.begin(), msgDataOut.end()); -} - - -void GenExchangeTest::storeToMsgIdsOutMaps(const GxsMsgIdResult& msgIdsOut) -{ - mMsgIdsOut.insert(msgIdsOut.begin(), msgIdsOut.end()); -} - - -void GenExchangeTest::storeToMsgMetaOutMaps(const GxsMsgMetaMap& msgMetaOut) -{ - mMsgMetaDataOut.insert(msgMetaOut.begin(), msgMetaOut.end()); -} - - -void GenExchangeTest::storeToMsgDataInMaps(const DummyMsgMap& msgDataIn) -{ - mMsgDataIn.insert(msgDataIn.begin(), msgDataIn.end()); -} - - -void GenExchangeTest::storeToMsgIdsInMaps(const GxsMsgIdResult& msgIdsIn) -{ - mMsgIdsIn.insert(msgIdsIn.begin(), msgIdsIn.end()); -} - - -void GenExchangeTest::storeToMsgMetaInMaps(const GxsMsgMetaMap& msgMetaIn) -{ - mMsgMetaDataIn.insert(msgMetaIn.begin(), msgMetaIn.end()); -} - - -void GenExchangeTest::storeToGrpIdsOutList( - const std::list& grpIdOut) -{ - mGrpIdsOut.insert(mGrpIdsOut.end(), grpIdOut.begin(), grpIdOut.end()); -} - - -void GenExchangeTest::storeToGrpMetaOutList( - const std::list& grpMetaOut) -{ - mGrpMetaDataOut.insert(mGrpMetaDataOut.end(), grpMetaOut.begin(), grpMetaOut.end()); -} - - -void GenExchangeTest::storeToGrpDataOutList( - const std::vector& grpDataOut) -{ - mGrpDataOut.insert(mGrpDataOut.end(), grpDataOut.begin(), grpDataOut.end()); -} - - -void GenExchangeTest::storeToGrpIdsInList( - const std::list& grpIdIn) -{ - mGrpIdsIn.insert(mGrpIdsIn.end(), grpIdIn.begin(), grpIdIn.end()); -} - - -void GenExchangeTest::storeToGrpMetaInList( - const std::list& grpMetaIn) -{ - mGrpMetaDataIn.insert(mGrpMetaDataIn.end(), grpMetaIn.begin(), grpMetaIn.end()); -} - - -void GenExchangeTest::storeToGrpDataInList( - const std::vector& grpDataIn) -{ - mGrpDataIn.insert(mGrpDataIn.begin(), grpDataIn.begin(), grpDataIn.end()); -} -void GenExchangeTest::clearAllData() -{ - clearMsgDataInMap(); - clearMsgDataOutMap(); - clearMsgIdInMap(); - clearMsgIdOutMap(); - clearMsgMetaInMap(); - clearMsgMetaOutMap(); - clearGrpDataInList(); - clearGrpDataOutList(); - clearGrpMetaInList(); - clearGrpMetaOutList(); - clearGrpIdInList(); - clearGrpIdOutList(); -} -void GenExchangeTest::clearMsgDataInMap() -{ - mMsgDataIn.clear(); -} - - -void GenExchangeTest::clearMsgDataOutMap() -{ - - clearMsgDataMap(mMsgDataOut); -} - -void GenExchangeTest::clearMsgDataMap(DummyMsgMap& msgDataMap) const -{ - DummyMsgMap::iterator it = msgDataMap.begin(); - - for(; it != msgDataMap.end(); it++) - { - deleteResVector(it->second); - } -} - -void GenExchangeTest::clearMsgMetaInMap() -{ - mMsgMetaDataIn.clear(); -} - - -void GenExchangeTest::clearMsgMetaOutMap() -{ - mMsgMetaDataOut.clear(); -} - - -void GenExchangeTest::clearMsgIdInMap() -{ - mMsgIdsIn.clear(); -} - - -void GenExchangeTest::clearMsgIdOutMap() -{ - mMsgIdsOut.clear(); -} - - -void GenExchangeTest::clearMsgRelatedIdInMap() -{ - mMsgRelatedIdsIn.clear(); -} - - -void GenExchangeTest::clearGrpDataInList() -{ - clearGrpDataList(mGrpDataIn); -} - -void GenExchangeTest::clearGrpDataList(std::vector& grpData) const -{ - deleteResVector(grpData); -} - - -void GenExchangeTest::clearGrpDataOutList() -{ - clearGrpDataList(mGrpDataOut); -} - - -void GenExchangeTest::clearGrpMetaInList() -{ - mGrpMetaDataIn.clear(); -} - - -void GenExchangeTest::clearGrpMetaOutList() -{ - mGrpMetaDataOut.clear(); -} - - -void GenExchangeTest::clearGrpIdInList() -{ - mGrpIdsIn.clear(); -} - - -void GenExchangeTest::clearGrpIdOutList() -{ - mGrpIdsOut.clear(); -} - - -bool operator ==(const RsMsgMetaData& lMeta, const RsMsgMetaData& rMeta) -{ - - if(lMeta.mAuthorId != rMeta.mAuthorId) return false; - if(lMeta.mChildTs != rMeta.mChildTs) return false; - if(lMeta.mGroupId != rMeta.mGroupId) return false; - if(lMeta.mMsgFlags != rMeta.mMsgFlags) return false; - if(lMeta.mMsgId != rMeta.mMsgId) return false; - if(lMeta.mMsgName != rMeta.mMsgName) return false; - //if(lMeta.mMsgStatus != rMeta.mMsgStatus) return false; - if(lMeta.mOrigMsgId != rMeta.mOrigMsgId) return false; - if(lMeta.mParentId != rMeta.mParentId) return false; - //if(lMeta.mPublishTs != rMeta.mPublishTs) return false; // don't compare this as internally set in gxs - if(lMeta.mThreadId != rMeta.mThreadId) return false; - if(lMeta.mServiceString != rMeta.mServiceString) return false; - - return true; -} - -bool operator ==(const RsGroupMetaData& lMeta, const RsGroupMetaData& rMeta) -{ - if(lMeta.mAuthorId != rMeta.mAuthorId) return false; - if(lMeta.mGroupFlags != rMeta.mGroupFlags) return false; - if(lMeta.mGroupId != rMeta.mGroupId) return false; - if(lMeta.mGroupName != rMeta.mGroupName) return false; - if(lMeta.mGroupStatus != rMeta.mGroupStatus) return false; - if(lMeta.mLastPost != rMeta.mLastPost) return false; - if(lMeta.mMsgCount != rMeta.mMsgCount) return false; - if(lMeta.mPop != rMeta.mPop) return false; - // if(lMeta.mPublishTs != rMeta.mPublishTs) return false; set in gxs - if(lMeta.mServiceString != rMeta.mServiceString) return false; - if(lMeta.mSignFlags != rMeta.mSignFlags) return false; - // if(lMeta.mSubscribeFlags != rMeta.mSubscribeFlags) return false; - - return true; -} - -bool operator ==(const RsDummyGrp& lGrp, const RsDummyGrp& rGrp) -{ - - if(lGrp.grpData != rGrp.grpData) return false; - if(! (lGrp.meta == rGrp.meta)) return false; - - return true; -} - -bool operator ==(const RsDummyMsg& lMsg, const RsDummyMsg& rMsg) -{ - if(lMsg.msgData != rMsg.msgData) return false; - if(!(lMsg.meta == rMsg.meta)) return false; - - return true; -} - -bool operator ==(const RsGxsGrpItem& lGrp, const RsGxsGrpItem& rGrp) -{ - return false; -} - diff --git a/libretroshare/src/tests/gxs/gen_exchange/genexchangetester.h b/libretroshare/src/tests/gxs/gen_exchange/genexchangetester.h deleted file mode 100644 index 13bb1cf6e..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/genexchangetester.h +++ /dev/null @@ -1,278 +0,0 @@ -#ifndef GENEXCHANGETESTER_H -#define GENEXCHANGETESTER_H - -#include "genexchangetestservice.h" -#include "gxs/rsgds.h" -#include "gxs/rsnxs.h" - -bool operator ==(const RsMsgMetaData& lMeta, const RsMsgMetaData& rMeta); -bool operator ==(const RsDummyMsg& lMsg, const RsDummyMsg& rMsg); -bool operator ==(const RsGxsGrpItem& lMsg, const RsGxsGrpItem& rMsg); - -bool operator ==(const RsGroupMetaData& lMeta, const RsGroupMetaData& rMeta); -bool operator ==(const RsDummyGrp& lMsg, const RsDummyGrp& rMsg); -bool operator ==(const RsGxsMsgItem& lMsg, const RsGxsMsgItem& rMsg); - -/*! - * The idea of GenExchangeTest is to simplify test - * of the RsGenExchange via the RsGxsDummyService - * One can test all publish/request/meta-modify - * capabilities of RsGenExchange - * Simplifications comes from: \n - * - * - ability to store in and out data for comparison (in data are - * usually from requests, out data are from publications, - * but generally what you want to compare) \n - * - convenience function to poll tokens \n - * - also allows filling in-data automatically from polls \n - * - convenience interface for running tests - */ -class GenExchangeTest -{ -public: - - /*! - * Constructs the GenExchangeTest with a tokenService - * @param tokenService This is needed. If not an instance of token service, - * behaviour of GenExchangeTest is undefined - */ - GenExchangeTest(GenExchangeTestService* const mTestService, RsGeneralDataService* dataService, int pollingTO = 5 /* 5 secs default */); - - virtual ~GenExchangeTest(); - - /*! - * This should be called in the main - * routines to execute all tests - * When implementing ensure units test header - * is in same file scope as implementation - * (you chould be using the CHECK functions - * to assert tests has passed) - */ - virtual void runTests() = 0; - -protected: - - /*! - * After each request and publish operation this should - * be called to ensure the operation has completed - * Requests will result in in data maps being filled - * @param - * @param opts - * @param fill if set to true, the received that is - * routed to IN data structures - */ - void pollForToken(uint32_t token, const RsTokReqOptions& opts, bool fill = false); - - /*! - * Allows to poll for token, and receive the message id - * as acknowledgement. This function blocks for as long the - * timeout value set on construction of tester - * @param token - * @param msgId - */ - bool pollForMsgAcknowledgement(uint32_t token, RsGxsGrpMsgIdPair& msgId); - - /*! - * Allows to poll for token, and receive the group id - * as acknowledgement. This function blocks for as long the - * timeout value set on construction of tester - * @param token - * @param msgId - */ - bool pollForGrpAcknowledgement(uint32_t token, RsGxsGroupId& msgId); - - GenExchangeTestService* getTestService(); - RsTokenService* getTokenService(); -// bool testGrpMetaModRequest(); -// bool testMsgMetaModRequest(); - - // convenience functions for clearing IN and OUT data structures - void clearMsgDataInMap(); - void clearMsgDataOutMap(); - void clearMsgMetaInMap(); - void clearMsgMetaOutMap(); - void clearMsgIdInMap(); - void clearMsgIdOutMap(); - void clearMsgRelatedIdInMap(); - void clearGrpDataInList(); - void clearGrpDataOutList(); - void clearGrpMetaInList(); - void clearGrpMetaOutList(); - void clearGrpIdInList(); - void clearGrpIdOutList(); - - /*! - * clears up all internal - * IN and OUT data structure for - * both msgs and groups - * frees resources in relation to allocated data - */ - void clearAllData(); - - template - void deleteResVector(std::vector& v) const - { - typename std::vector::iterator vit = v.begin(); - for(; vit != v.end(); vit++) - delete *vit; - v.clear(); - } - - // using class to enable partial - // function specialisation, bit of a hack in a - // way - template - class Comparison - { - public: - - static bool comparison(const Cont& l, const Cont& r) - { - if(l.size() != r.size()) return false; - - typename Cont::const_iterator vit1 = l.begin(), vit2 = r.begin(); - - while(vit1 != l.end()) - { - const Item& item1 = (*vit1); - const Item& item2 = (*vit2); - if(!(item1 == item2)) return false; - - vit1++; - vit2++; - } - return true; - } - }; - - - template - class Comparison - { - public: - - static bool comparison(const Cont& l, const Cont& r) - { - if(l.size() != r.size()) - return false; - - typename Cont::const_iterator vit1 = l.begin(), vit2 = r.begin(); - - while(vit1 != l.end()) - { - const Item* item1 = (*vit1); - const Item* item2 = (*vit2); - if(!(*item1 == *item2)) - return false; - - vit1++; - vit2++; - } - return true; - } - }; - - // convenience function for comparing IN and OUT data structures - bool compareMsgDataMaps() ; - bool compareMsgIdMaps() ; - bool compareMsgMetaMaps() ; - bool compareMsgRelateIdsMap() ; - bool compareMsgRelatedDataMap() ; - bool compareGrpData() ; - bool compareGrpMeta() ; - bool compareGrpIds() ; - - void storeToMsgDataOutMaps(const DummyMsgMap& msgDataOut); - void storeToMsgIdsOutMaps(const GxsMsgIdResult& msgIdsOut); - void storeToMsgMetaOutMaps(const GxsMsgMetaMap& msgMetaOut); - - void storeToMsgDataInMaps(const DummyMsgMap& msgDataOut); - void storeToMsgIdsInMaps(const GxsMsgIdResult& msgIdsOut); - void storeToMsgMetaInMaps(const GxsMsgMetaMap& msgMetaOut); - - void storeToGrpIdsOutList(const std::list& grpIdOut); - void storeToGrpMetaOutList(const std::list& grpMetaOut); - void storeToGrpDataOutList(const std::vector& grpDataOut); - - void storeToGrpIdsInList(const std::list& grpIdIn); - void storeToGrpMetaInList(const std::list& grpMetaOut); - void storeToGrpDataInList(const std::vector& grpDataOut); - - /*! - * This sets up any resources required to operate a test - */ - void setUp(); - - /*! - * Call at end of test to ensure resources - * used in tests are released - * This can invalidate other test runs if not called - */ - void breakDown(); - - /*! - * initialises item to random data - * @param grpItem item to initialise - */ - void init(RsDummyGrp& grpItem) const; - - /*! - * Initialises meta data to random data - * @param grpMetaData - */ - void init(RsGroupMetaData& grpMetaData) const; - - /*! - * Initialises msg item to random data - * @param msgItem - */ - void init(RsDummyMsg& msgItem) const; - - /*! - * Initialises meta data to random data - * @param msgMetaData - */ - void init(RsMsgMetaData& msgMetaData) const; - - - void clearMsgDataMap(DummyMsgMap& msgDataMap) const; - void clearGrpDataList(std::vector& grpData) const; - - /*! - * Helper function which sets up groups - * data in to be used for publication - * group data - * @param nGrps number of groups to publish - * @param groupId the ids for the created groups - */ - void createGrps(uint32_t nGrps, std::list& groupId); - - /*! - * @return random number - */ - uint32_t randNum() const; - -private: - - std::vector mGrpDataOut, mGrpDataIn; - std::list mGrpMetaDataOut, mGrpMetaDataIn; - std::list mGrpIdsOut, mGrpIdsIn; - - std::map > mMsgDataOut, mMsgDataIn; - GxsMsgMetaMap mMsgMetaDataOut, mMsgMetaDataIn; - GxsMsgIdResult mMsgIdsOut, mMsgIdsIn; - - MsgRelatedIdResult mMsgRelatedIdsOut, mMsgRelatedIdsIn; - GxsMsgRelatedDataMap mMsgRelatedDataMapOut, mMsgRelatedDataMapIn; - - std::vector mRandGrpIds; // ids that exist to help group testing - -private: - - RsGeneralDataService* mDataService; - GenExchangeTestService* mTestService; - RsTokenService* mTokenService; - int mPollingTO; -}; - -#endif // GENEXCHANGETESTER_H diff --git a/libretroshare/src/tests/gxs/gen_exchange/genexchangetestservice.cpp b/libretroshare/src/tests/gxs/gen_exchange/genexchangetestservice.cpp deleted file mode 100644 index dd9ba328a..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/genexchangetestservice.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "genexchangetestservice.h" - -GenExchangeTestService::GenExchangeTestService(RsGeneralDataService *dataServ, RsNetworkExchangeService * netService, - RsGixs* gixs) - : RsGenExchange(dataServ, netService, new RsDummySerialiser(), RS_SERVICE_TYPE_DUMMY, gixs, 0) -{ - -} - -void GenExchangeTestService::notifyChanges(std::vector &changes) -{ - return; -} - -void GenExchangeTestService::publishDummyGrp(uint32_t &token, RsDummyGrp *grp) -{ - publishGroup(token, grp); -} - -void GenExchangeTestService::updateDummyGrp(uint32_t &token, RsGxsGroupUpdateMeta &updateMeta, RsDummyGrp *group) -{ - updateGroup(token, updateMeta, group); -} - -void GenExchangeTestService::publishDummyMsg(uint32_t &token, RsDummyMsg *msg) -{ - publishMsg(token, msg); -} - -bool GenExchangeTestService::getGroupListTS(const uint32_t &token, std::list &groupIds) -{ - return getGroupList(token, groupIds); -} - -bool GenExchangeTestService::getGroupMetaTS(const uint32_t &token, std::list &groupInfo) -{ - return getGroupMeta(token, groupInfo); -} - -bool GenExchangeTestService::getGroupDataTS(const uint32_t &token, std::vector& grpItem) -{ - return getGroupDataT(token, grpItem); -} - -bool GenExchangeTestService::getMsgDataTS(const uint32_t &token, DummyMsgMap &msgItems) -{ - return getMsgDataT(token, msgItems); -} - -bool GenExchangeTestService::getMsgRelatedDataTS(const uint32_t &token, GxsMsgRelatedDataMap &msgItems) -{ - return getMsgRelatedData(token, msgItems); -} - -bool GenExchangeTestService::getMsgMetaTS(const uint32_t &token, GxsMsgMetaMap &msgInfo) -{ - return getMsgMeta(token, msgInfo); -} - -bool GenExchangeTestService::getMsgListTS(const uint32_t &token, GxsMsgIdResult &msgIds) -{ - return getMsgList(token, msgIds); -} - -bool GenExchangeTestService::getMsgRelatedListTS(const uint32_t &token, MsgRelatedIdResult &msgIds) -{ - return getMsgRelatedList(token, msgIds); -} - -void GenExchangeTestService::setGroupServiceStringTS(uint32_t &token, const RsGxsGroupId &grpId, const std::string &servString) -{ - RsGenExchange::setGroupServiceString(token, grpId, servString); -} - -void GenExchangeTestService::setGroupStatusFlagTS(uint32_t &token, const RsGxsGroupId &grpId, const uint32_t &status, const uint32_t& mask) -{ - RsGenExchange::setGroupStatusFlags(token, grpId, status, mask); -} - -void GenExchangeTestService::setGroupSubscribeFlagTS(uint32_t &token, const RsGxsGroupId &grpId, const uint32_t &status, const uint32_t& mask) -{ - RsGenExchange::setGroupSubscribeFlags(token, grpId, status, mask); -} - -void GenExchangeTestService::setMsgServiceStringTS(uint32_t &token, const RsGxsGrpMsgIdPair &msgId, const std::string &servString) -{ - RsGenExchange::setMsgServiceString(token, msgId, servString); -} - -void GenExchangeTestService::setMsgStatusFlagTS(uint32_t &token, const RsGxsGrpMsgIdPair &msgId, const uint32_t &status, const uint32_t& mask) -{ - RsGenExchange::setMsgStatusFlags(token, msgId, status, mask); -} - -void GenExchangeTestService::service_tick() -{ - -} diff --git a/libretroshare/src/tests/gxs/gen_exchange/genexchangetestservice.h b/libretroshare/src/tests/gxs/gen_exchange/genexchangetestservice.h deleted file mode 100644 index 588808eb9..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/genexchangetestservice.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef GENEXCHANGETESTSERVICE_H -#define GENEXCHANGETESTSERVICE_H - -#include "gxs/rsgenexchange.h" -#include "retroshare/rsgxsifacehelper.h" -#include "rsdummyservices.h" - -typedef std::map > DummyMsgMap; - -class GenExchangeTestService : public RsGenExchange -{ -public: - GenExchangeTestService(RsGeneralDataService* dataServ, RsNetworkExchangeService* nxs, RsGixs* gixs); - - void notifyChanges(std::vector& changes); - - void publishDummyGrp(uint32_t& token, RsDummyGrp* grp); - void updateDummyGrp(uint32_t &token, RsGxsGroupUpdateMeta& meta, RsDummyGrp *group); - void publishDummyMsg(uint32_t& token, RsDummyMsg* msg); - - /*! - * Retrieve group list for a given token - * @param token - * @param groupIds - * @return false if token cannot be redeemed, if false you may have tried to redeem when not ready - */ - bool getGroupListTS(const uint32_t &token, std::list &groupIds); - - /*! - * Retrieve msg list for a given token sectioned by group Ids - * @param token token to be redeemed - * @param msgIds a map of grpId -> msgList (vector) - */ - bool getMsgListTS(const uint32_t &token, GxsMsgIdResult &msgIds); - - - /*! - * retrieve group meta data associated to a request token - * @param token - * @param groupInfo - */ - bool getGroupMetaTS(const uint32_t &token, std::list &groupInfo); - - /*! - * retrieves message meta data associated to a request token - * @param token token to be redeemed - * @param msgInfo the meta data to be retrieved for token store here - */ - bool getMsgMetaTS(const uint32_t &token, GxsMsgMetaMap &msgInfo); - - /*! - * retrieves group data associated to a request token - * @param token token to be redeemed for grpitem retrieval - * @param grpItem the items to be retrieved for token are stored here - */ - bool getGroupDataTS(const uint32_t &token, std::vector& grpItem); - - - - /*! - * retrieves message data associated to a request token - * @param token token to be redeemed for message item retrieval - * @param msgItems - */ - bool getMsgDataTS(const uint32_t &token, DummyMsgMap& msgItems); - - /*! - * Retrieve msg related list for a given token sectioned by group Ids - * @param token token to be redeemed - * @param msgIds a map of grpMsgIdPair -> msgList (vector) - */ - bool getMsgRelatedListTS(const uint32_t &token, MsgRelatedIdResult &msgIds); - - /*! - * retrieves msg related data msgItems as a map of msg-grpID pair to vector - * of items - * @param token token to be redeemed - * @param msgItems map of msg items - */ - bool getMsgRelatedDataTS(const uint32_t &token, GxsMsgRelatedDataMap& msgItems); - - - void setGroupSubscribeFlagTS(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask); - - void setGroupStatusFlagTS(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask); - - void setGroupServiceStringTS(uint32_t& token, const RsGxsGroupId& grpId, const std::string& servString); - - void setMsgStatusFlagTS(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const uint32_t& status, const uint32_t& mask); - - void setMsgServiceStringTS(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const std::string& servString ); - - void service_tick(); - -}; - -#endif // GENEXCHANGETESTSERVICE_H diff --git a/libretroshare/src/tests/gxs/gen_exchange/gxsmsgrelatedtest.cpp b/libretroshare/src/tests/gxs/gen_exchange/gxsmsgrelatedtest.cpp deleted file mode 100644 index 8b2eacd88..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/gxsmsgrelatedtest.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/* - * gxsmsgrelatedtest.cpp - * - * Created on: 27 Apr 2013 - * Author: crispy - */ - -#include "gxsmsgrelatedtest.h" - -GxsMsgRelatedTest::GxsMsgRelatedTest() { - // TODO Auto-generated constructor stub - -} - -GxsMsgRelatedTest::~GxsMsgRelatedTest() { - // TODO Auto-generated destructor stub -} - diff --git a/libretroshare/src/tests/gxs/gen_exchange/gxsmsgrelatedtest.h b/libretroshare/src/tests/gxs/gen_exchange/gxsmsgrelatedtest.h deleted file mode 100644 index 2277142d9..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/gxsmsgrelatedtest.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * gxsmsgrelatedtest.h - * - * Created on: 27 Apr 2013 - * Author: crispy - */ - -#ifndef GXSMSGRELATEDTEST_H_ -#define GXSMSGRELATEDTEST_H_ - -#include "genexchangetester.h" - -class GxsMsgRelatedTest: public GenExchangeTest { -public: - GxsMsgRelatedTest(); - virtual ~GxsMsgRelatedTest(); - - // request msg related tests - bool testMsgRelatedChildIdRetrieval(); - bool testMsgRelatedChildDataRetrieval(); - bool testMsgRelatedChildDataRetrieval_Multi(); - bool testMsgAllVersions(); -}; - -#endif /* GXSMSGRELATEDTEST_H_ */ diff --git a/libretroshare/src/tests/gxs/gen_exchange/gxspublishgrouptest.cc b/libretroshare/src/tests/gxs/gen_exchange/gxspublishgrouptest.cc deleted file mode 100644 index 2fe0d5fac..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/gxspublishgrouptest.cc +++ /dev/null @@ -1,301 +0,0 @@ -/* - * gxspublishgrouptest.cc - * - * Created on: 27 Apr 2013 - * Author: crispy - */ - -#include "gxspublishgrouptest.h" -#include "util/utest.h" -#include "support.h" - -#define POLLING_TIME_OUT 5 - -GxsPublishGroupTest::GxsPublishGroupTest(GenExchangeTestService* const testService, - RsGeneralDataService* dataService) - : GenExchangeTest(testService, dataService, POLLING_TIME_OUT) -{ - -} - -GxsPublishGroupTest::~GxsPublishGroupTest() -{ -} - -bool GxsPublishGroupTest::testGrpSubmissionRetrieval() -{ - - setUp(); - - GenExchangeTestService* testService = getTestService(); - RsTokenService* tokenService = getTokenService(); - - // create some random grps to allow msg testing - - RsDummyGrp* dgrp1 = new RsDummyGrp(); - RsDummyGrp* dgrp2 = new RsDummyGrp(); - RsDummyGrp* dgrp3 = new RsDummyGrp(); - - RsDummyGrp* dgrp1_copy = new RsDummyGrp(); - RsDummyGrp* dgrp2_copy = new RsDummyGrp(); - RsDummyGrp* dgrp3_copy = new RsDummyGrp(); - - init(*dgrp1); - init(*dgrp2); - init(*dgrp3); - - RsTokReqOptions opts; - opts.mReqType = 45000; - uint32_t token; - RsGxsGroupId grpId; - - std::vector groupsPublished; - - *dgrp1_copy = *dgrp1; - testService->publishDummyGrp(token, dgrp1); - pollForGrpAcknowledgement(token, grpId); - dgrp1_copy->meta.mGroupId = grpId; - groupsPublished.push_back(dgrp1_copy); - - *dgrp2_copy = *dgrp2; - testService->publishDummyGrp(token, dgrp2); - pollForGrpAcknowledgement(token, grpId); - dgrp2_copy->meta.mGroupId = grpId; - groupsPublished.push_back(dgrp2_copy); - - *dgrp3_copy = *dgrp3; - testService->publishDummyGrp(token, dgrp3); - pollForGrpAcknowledgement(token, grpId); - dgrp3_copy->meta.mGroupId = grpId; - groupsPublished.push_back(dgrp3_copy); - - - storeToGrpDataOutList(groupsPublished); - - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - std::list grpIds; - tokenService->requestGroupInfo(token, 0, opts); - - pollForToken(token, opts, true); - - - bool ok = compareGrpData(); - - breakDown(); - - return ok; -} - -bool GxsPublishGroupTest::testSpecificGrpRetrieval() -{ - setUp(); - - GenExchangeTestService* testService = getTestService(); - RsTokenService* tokenService = getTokenService(); - - // create some random grps to allow msg testing - - RsDummyGrp* dgrp1 = new RsDummyGrp(); - RsDummyGrp* dgrp2 = new RsDummyGrp(); - RsDummyGrp* dgrp3 = new RsDummyGrp(); - - RsDummyGrp* dgrp1_copy = new RsDummyGrp(); - RsDummyGrp* dgrp2_copy = new RsDummyGrp(); - - init(*dgrp1); - init(*dgrp2); - init(*dgrp3); - - RsTokReqOptions opts; - opts.mReqType = 45000; - uint32_t token; - RsGxsGroupId grpId; - - std::vector groupsPublished; - std::list grpIds; - - *dgrp1_copy = *dgrp1; - testService->publishDummyGrp(token, dgrp1); - pollForGrpAcknowledgement(token, grpId); - dgrp1_copy->meta.mGroupId = grpId; - groupsPublished.push_back(dgrp1_copy); - grpIds.push_back(grpId); - - *dgrp2_copy = *dgrp2; - testService->publishDummyGrp(token, dgrp2); - pollForGrpAcknowledgement(token, grpId); - dgrp2_copy->meta.mGroupId = grpId; - groupsPublished.push_back(dgrp2_copy); - grpIds.push_back(grpId); - - - testService->publishDummyGrp(token, dgrp3); - pollForGrpAcknowledgement(token, grpId); - - - storeToGrpDataOutList(groupsPublished); - - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - tokenService->requestGroupInfo(token, 0, opts, grpIds); - - pollForToken(token, opts, true); - - - bool ok = compareGrpData(); - - breakDown(); - - return ok; -} - -bool GxsPublishGroupTest::testGrpIdRetrieval() -{ - setUp(); - - std::list grpIds; - createGrps(5, grpIds); - storeToGrpIdsOutList(grpIds); - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; - uint32_t token; - - getTokenService()->requestGroupInfo(token, 0, opts); - - pollForToken(token, opts, true); - - bool ok = compareGrpIds(); - - breakDown(); - - return ok; -} - -bool GxsPublishGroupTest::testUpdateGroup() -{ - setUp(); - - GenExchangeTestService* testService = getTestService(); - RsTokenService* tokenService = getTokenService(); - -// create some random grps to allow msg testing - - RsDummyGrp* dgrp1 = new RsDummyGrp(); - RsDummyGrp* dgrp2 = new RsDummyGrp(); - - RsDummyGrp* dgrp2_copy = new RsDummyGrp(); - - init(*dgrp1); - init(*dgrp2); - - RsTokReqOptions opts; - opts.mReqType = 45000; - uint32_t token; - RsGxsGroupId grpId; - - std::vector groupsPublished; - std::list grpIds; - - std::string name = dgrp1->meta.mGroupName; - *dgrp2 = *dgrp1; - testService->publishDummyGrp(token, dgrp1); - bool ok = pollForGrpAcknowledgement(token, grpId); - - grpIds.push_back(grpId); - RsGxsGroupUpdateMeta updateMeta(grpId); - - updateMeta.setMetaUpdate(RsGxsGroupUpdateMeta::NAME, name); - randString(SHORT_STR, dgrp2->grpData); - dgrp2->meta.mGroupId = grpId; - *dgrp2_copy = *dgrp2; - dgrp2->grpData ="ojfosfjsofjsof"; - testService->updateDummyGrp(token, updateMeta, dgrp2); - ok &= pollForGrpAcknowledgement(token, grpId); - - groupsPublished.push_back(dgrp2_copy); - - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - tokenService->requestGroupInfo(token, 0, opts, grpIds); - - pollForToken(token, opts, true); - - - ok &= compareGrpData(); - - breakDown(); - - return ok; - -} - -bool GxsPublishGroupTest::testGrpMetaRetrieval() -{ - - setUp(); - - GenExchangeTestService* testService = getTestService(); - - // create some random grps to allow msg testing - - RsDummyGrp* dgrp1 = new RsDummyGrp(); - RsDummyGrp* dgrp2 = new RsDummyGrp(); - RsDummyGrp* dgrp3 = new RsDummyGrp(); - - init(*dgrp1); - init(*dgrp2); - init(*dgrp3); - - RsTokReqOptions opts; - opts.mReqType = 45000; - uint32_t token; - RsGxsGroupId grpId; - - RsGroupMetaData meta1(dgrp1->meta); - RsGroupMetaData meta2(dgrp2->meta); - RsGroupMetaData meta3(dgrp3->meta); - - std::list groupsMetaPublished; - - testService->publishDummyGrp(token, dgrp1); - pollForGrpAcknowledgement(token, grpId); - meta1.mGroupId = grpId; - groupsMetaPublished.push_back(meta1); - - testService->publishDummyGrp(token, dgrp2); - pollForGrpAcknowledgement(token, grpId); - meta2.mGroupId = grpId; - groupsMetaPublished.push_back(meta2); - - testService->publishDummyGrp(token, dgrp3); - pollForGrpAcknowledgement(token, grpId); - meta3.mGroupId = grpId; - groupsMetaPublished.push_back(meta3); - - storeToGrpMetaOutList(groupsMetaPublished); - - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - std::list grpIds; - - getTokenService()->requestGroupInfo(token, 0, opts); - - pollForToken(token, opts, true); - - bool ok = compareGrpMeta(); - - breakDown(); - - return ok; -} -void GxsPublishGroupTest::runTests() -{ -// CHECK(testGrpSubmissionRetrieval()); -// CHECK(testGrpIdRetrieval()); -// CHECK(testGrpMetaRetrieval()); - // CHECK(testSpecificGrpRetrieval()); - CHECK(testUpdateGroup()); -} - - - - diff --git a/libretroshare/src/tests/gxs/gen_exchange/gxspublishgrouptest.h b/libretroshare/src/tests/gxs/gen_exchange/gxspublishgrouptest.h deleted file mode 100644 index a0f642828..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/gxspublishgrouptest.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * gxspublishgrouptest.h - * - * Created on: 27 Apr 2013 - * Author: crispy - */ - -#ifndef GXSPUBLISHGROUPTEST_H_ -#define GXSPUBLISHGROUPTEST_H_ - -#include "genexchangetester.h" - -class GxsPublishGroupTest : public GenExchangeTest { -public: - - GxsPublishGroupTest(GenExchangeTestService* const testService, - RsGeneralDataService* dataService); - virtual ~GxsPublishGroupTest(); - - void runTests(); - -private: - - // group tests - bool testGrpSubmissionRetrieval(); - bool testSpecificGrpRetrieval(); - bool testGrpIdRetrieval(); - bool testGrpMetaRetrieval(); - bool testUpdateGroup(); - - -private: - -}; - -#endif /* GXSPUBLISHGROUPTEST_H_ */ diff --git a/libretroshare/src/tests/gxs/gen_exchange/gxspublishmsgtest.cc b/libretroshare/src/tests/gxs/gen_exchange/gxspublishmsgtest.cc deleted file mode 100644 index adfa2026c..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/gxspublishmsgtest.cc +++ /dev/null @@ -1,75 +0,0 @@ -/* - * gxspublishmsgtest.cpp - * - * Created on: 27 Apr 2013 - * Author: crispy - */ - -#include "gxspublishmsgtest.h" -#include "util/utest.h" - -#define POLLING_TIME_OUT 5 - -GxsPublishMsgTest::GxsPublishMsgTest(GenExchangeTestService* const testService, - RsGeneralDataService* dataService) - : GenExchangeTest(testService, dataService, POLLING_TIME_OUT) -{ -} - -GxsPublishMsgTest::~GxsPublishMsgTest() -{ -} - -void GxsPublishMsgTest::runTests() -{ - CHECK(testMsgSubmissionRetrieval()); -} - -bool GxsPublishMsgTest::testMsgSubmissionRetrieval() -{ - // start up - setUp(); - std::list grpIds; - createGrps(4, grpIds); - - /********************/ - - RsDummyMsg* msg = new RsDummyMsg(); - init(*msg); - - msg->meta.mGroupId = grpIds.front(); - uint32_t token; - RsDummyMsg* msgOut = new RsDummyMsg(); - *msgOut = *msg; - getTestService()->publishDummyMsg(token, msg); - - - RsGxsGrpMsgIdPair msgId; - pollForMsgAcknowledgement(token, msgId); - msgOut->meta.mMsgId = msgId.second; - - DummyMsgMap msgMap; - std::vector msgV; - msgV.push_back(msgOut); - msgMap[msgOut->meta.mGroupId] = msgV; - storeToMsgDataOutMaps(msgMap); - - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - getTokenService()->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds); - - // poll again - pollForToken(token, opts, true); - - bool ok = compareMsgDataMaps(); - - // complete - breakDown(); - - return ok; -} - - - diff --git a/libretroshare/src/tests/gxs/gen_exchange/gxspublishmsgtest.h b/libretroshare/src/tests/gxs/gen_exchange/gxspublishmsgtest.h deleted file mode 100644 index bcdfa6aeb..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/gxspublishmsgtest.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * gxspublishmsgtest.h - * - * Created on: 27 Apr 2013 - * Author: crispy - */ - -#ifndef GXSPUBLISHMSGTEST_H_ -#define GXSPUBLISHMSGTEST_H_ - -#include "genexchangetester.h" - -class GxsPublishMsgTest: public GenExchangeTest { -public: - GxsPublishMsgTest(GenExchangeTestService* const testService, - RsGeneralDataService* dataService); - virtual ~GxsPublishMsgTest(); - - void runTests(); - - // message tests - bool testMsgSubmissionRetrieval(); -// bool testMsgIdRetrieval(); -// bool testMsgIdRetrieval_OptParents(); -// bool testMsgIdRetrieval_OptOrigMsgId(); -// bool testMsgIdRetrieval_OptLatest(); -// bool testSpecificMsgMetaRetrieval(); - - -}; - -#endif /* GXSPUBLISHMSGTEST_H_ */ diff --git a/libretroshare/src/tests/gxs/gen_exchange/rsdummyservices.cc b/libretroshare/src/tests/gxs/gen_exchange/rsdummyservices.cc deleted file mode 100644 index 4d8dd4984..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/rsdummyservices.cc +++ /dev/null @@ -1,226 +0,0 @@ - - -#include "rsdummyservices.h" - - -uint32_t RsDummySerialiser::size(RsItem *item) -{ - RsDummyMsg* msg; - RsDummyGrp* grp; - - if( (msg = dynamic_cast(item)) != NULL ) - { - return sizeDummyMsgItem(msg); - }else if( (grp = dynamic_cast(item)) != NULL ) - { - return sizeDummyGrpItem(grp); - }else - { - std::cerr << "RsDummySerialiser::size(RsItem *item) Error with dummy cast!\n"; - } - - return 0; -} - - -bool RsDummySerialiser::serialise(RsItem *item, void *data, uint32_t *size) -{ - RsDummyMsg* msg; - RsDummyGrp* grp; - - if( (msg = dynamic_cast(item)) != NULL ) - { - return serialiseDummyMsgItem(msg, data, size); - }else if( (grp = dynamic_cast(item)) != NULL ) - { - return serialiseDummyGrpItem(grp, data, size); - }else - { - std::cerr << "RsDummySerialiser::size(RsItem *item) Error with dummy cast!\n"; - } - - return false; -} - -RsItem* RsDummySerialiser::deserialise(void *data, uint32_t *size) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_DUMMY != getRsItemService(rstype))) - { - return NULL; /* wrong type */ - } - - switch(getRsItemSubType(rstype)) - { - case RS_PKT_SUBTYPE_DUMMY_MSG: - return deserialiseDummyMsgItem(data, size); - case RS_PKT_SUBTYPE_DUMMY_GRP: - return deserialiseDummyGrpItem(data, size); - default: - return NULL; - } - - return NULL; -} - - -uint32_t RsDummySerialiser::sizeDummyMsgItem(RsDummyMsg *item) -{ - uint32_t s = 8; // header - s += GetTlvStringSize(item->msgData); - - return s; -} - -bool RsDummySerialiser::serialiseDummyMsgItem (RsDummyMsg *item, void *data, uint32_t *size) -{ - uint32_t tlvsize = sizeDummyMsgItem(item); - uint32_t offset = 0; - - if (*size < tlvsize) - return false; /* not enough space */ - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - /* RsDistribMsg first */ - - ok &= SetTlvString(data, *size, &offset, 1, item->msgData); - - if (offset != tlvsize) - { - ok = false; - std::cerr << "RsDummySerialiser::serialiseDummyMsgItem Size Error! " << std::endl; - } - - return ok; -} - -RsDummyMsg * RsDummySerialiser::deserialiseDummyMsgItem(void *data, uint32_t *size) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_DUMMY != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_DUMMY_MSG != getRsItemSubType(rstype))) - { - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - return NULL; /* not enough data */ - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - /* ready to load */ - RsDummyMsg *item = new RsDummyMsg(); - - /* skip the header */ - offset += 8; - - ok &= GetTlvString(data, *size, &offset, 1, item->msgData); - - if (!ok) - { - delete item; - return NULL; - } - - return item; -} - -uint32_t RsDummySerialiser::sizeDummyGrpItem(RsDummyGrp *item) -{ - uint32_t s = 8; - s += GetTlvStringSize(item->grpData); - - return s; -} - -bool RsDummySerialiser::serialiseDummyGrpItem (RsDummyGrp *item, void *data, uint32_t *size) -{ - uint32_t tlvsize = sizeDummyGrpItem(item); - uint32_t offset = 0; - - if (*size < tlvsize) - return false; /* not enough space */ - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - ok &= SetTlvString(data, *size, &offset, 1, item->grpData); - - if (offset != tlvsize) - { - ok = false; - std::cerr << "RsDummySerialiser::serialiseDummyGrpItem Size Error! " << std::endl; - } - - return ok; -} - -RsDummyGrp * RsDummySerialiser::deserialiseDummyGrpItem(void *data, uint32_t *size) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_DUMMY != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_DUMMY_GRP != getRsItemSubType(rstype))) - { - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - return NULL; /* not enough data */ - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - /* ready to load */ - RsDummyGrp *item = new RsDummyGrp(); - - /* skip the header */ - offset += 8; - - ok &= GetTlvString(data, *size, &offset, 1, item->grpData); - - if (!ok) - { - delete item; - return NULL; - } - - return item; -} - - diff --git a/libretroshare/src/tests/gxs/gen_exchange/rsdummyservices.h b/libretroshare/src/tests/gxs/gen_exchange/rsdummyservices.h deleted file mode 100644 index 4720f6be7..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/rsdummyservices.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef RSDUMMYSERVICES_H -#define RSDUMMYSERVICES_H - - -// dummy services to make - -#include "gxs/rsnxs.h" -#include "gxs/rsgixs.h" -#include "serialiser/rsgxsitems.h" - -class RsDummyNetService: public RsNetworkExchangeService -{ -public: - - RsDummyNetService(){ return;} - virtual ~RsDummyNetService() { } - - void setSyncAge(uint32_t age){} - - void requestGroupsOfPeer(const std::string& peerId){} - - void requestMessagesOfPeer(const std::string& peerId, const std::string& grpId){} - - void pauseSynchronisation(bool enabled) {} - - int requestMsg(const std::string& msgId, uint8_t hops){ return 0;} - - int requestGrp(const std::list& grpId, uint8_t hops) { return 0;} -}; - - - -const uint16_t RS_SERVICE_TYPE_DUMMY = 0x01; -const uint8_t RS_PKT_SUBTYPE_DUMMY_MSG = 0x02; -const uint8_t RS_PKT_SUBTYPE_DUMMY_GRP = 0x03; - - -class RsDummyMsg : public RsGxsMsgItem -{ -public: - RsDummyMsg() : RsGxsMsgItem(RS_SERVICE_TYPE_DUMMY, RS_PKT_SUBTYPE_DUMMY_MSG) { return; } - virtual ~RsDummyMsg() { return; } - - std::string msgData; - - std::ostream &print(std::ostream &out, uint16_t indent = 0){ return out; } - void clear() { msgData.clear(); } - -}; - -class RsDummyGrp : public RsGxsGrpItem -{ -public: - - RsDummyGrp() : RsGxsGrpItem(RS_SERVICE_TYPE_DUMMY, RS_PKT_SUBTYPE_DUMMY_GRP) { return; } - virtual ~RsDummyGrp() { return; } - - - std::string grpData; - void clear() { grpData.clear(); } - std::ostream &print(std::ostream &out, uint16_t indent = 0){ return out; } -}; - - - -class RsDummySerialiser : public RsSerialType -{ - -public: - - - RsDummySerialiser() - : RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DUMMY) - { return; } - virtual ~RsDummySerialiser() { return; } - - uint32_t size(RsItem *item); - bool serialise (RsItem *item, void *data, uint32_t *size); - RsItem * deserialise(void *data, uint32_t *size); - - private: - - uint32_t sizeDummyMsgItem(RsDummyMsg *item); - bool serialiseDummyMsgItem (RsDummyMsg *item, void *data, uint32_t *size); - RsDummyMsg * deserialiseDummyMsgItem(void *data, uint32_t *size); - - uint32_t sizeDummyGrpItem(RsDummyGrp *item); - bool serialiseDummyGrpItem (RsDummyGrp *item, void *data, uint32_t *size); - RsDummyGrp * deserialiseDummyGrpItem(void *data, uint32_t *size); - - -}; - -/*! - * Dummy implementation of Gixs service for - * testing - * Limited to creating two ids upon construction which can be used - * for signing data - */ -class RsGixsDummy : public RsGixs -{ - -public: - - /*! - * constructs keys for both incoming and outgoing id (no private keys for incoming id) - * @param - * @param dummyId This is is the only id thats exists in this dummy interface - */ - RsGixsDummy(const RsGxsId& incomingId, const RsGxsId& outgoingId){} - - virtual ~RsGixsDummy(){} - - /*! - * - * @return id used for signing incoming data (should have both public and private components) - */ - const RsGxsId& getOutgoing(){ return mOutgoingId; } - - /*! - * - * @return id used for signing outgoing data(only have public parts) - */ - const RsGxsId& getIncoming(){ return mIncomingId; } - - // Key related interface - used for validating msgs and groups. - /*! - * Use to query a whether given key is available by its key reference - * @param keyref the keyref of key that is being checked for - * @return true if available, false otherwise - */ - bool haveKey(const RsGxsId &id){ return false;} - - /*! - * Use to query whether private key member of the given key reference is available - * @param keyref the KeyRef of the key being checked for - * @return true if private key is held here, false otherwise - */ - bool havePrivateKey(const RsGxsId &id){ return false; } - - // The fetchKey has an optional peerList.. this is people that had the msg with the signature. - // These same people should have the identity - so we ask them first. - /*! - * Use to request a given key reference - * @param keyref the KeyRef of the key being requested - * @return will - */ - bool requestKey(const RsGxsId &id, const std::list &peers){ return false ;} - bool requestPrivateKey(const RsGxsId &id){ return false;} - - - /*! - * Retrieves a key identity - * @param keyref - * @return a pointer to a valid profile if successful, otherwise NULL - * - */ - int getKey(const RsGxsId &id, RsTlvSecurityKey &key){ return false; } - int getPrivateKey(const RsGxsId &id, RsTlvSecurityKey &key){ return false; } // For signing outgoing messages. - -private: - - RsGxsId mIncomingId, mOutgoingId; -}; - - -#endif // RSDUMMYSERVICES_H diff --git a/libretroshare/src/tests/gxs/gen_exchange/rsgenexchange_test.cc b/libretroshare/src/tests/gxs/gen_exchange/rsgenexchange_test.cc deleted file mode 100644 index 8b28bad17..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/rsgenexchange_test.cc +++ /dev/null @@ -1,47 +0,0 @@ - - -#include "genexchangetester.h" -#include "gxspublishgrouptest.h" -#include "gxspublishmsgtest.h" -#include "util/utest.h" -#include "gxs/rsdataservice.h" -#include "rsdummyservices.h" - - -/*! - * It always hard to say exactly what coverage of a test would - * be ahead of time. Partly because its difficult to create the - * actual conditions of a test or the permutations of different request - * options to a module is extremely large (and there are probably ways to deal with this) - * In so far as the genexchange test is concerned we are primarily interested that it - * retrieves and stores data correctly - * The auxillary (and important) requirement is authentication and ensuring the authentication - * rules are respected. This auxillary requirement is of the "hard" situation to create as - * genexchange depends on an external module (rsidentity) for satisfying a significant sum - * of its authentication. This difficulty is solved with a dummy identity service. - * Which passes all authentications (In this respect authentication) is reserved for "online" - * testing and is relatively straight forward. - * - */ - -INITTEST(); - - -int main() -{ - - RsGeneralDataService* dataStore = new RsDataService("./", "testServiceDb", RS_SERVICE_TYPE_DUMMY, NULL, ""); - - // we want to use default authentication which is NO authentication :) - GenExchangeTestService testService(dataStore, NULL, NULL); - - GxsPublishGroupTest testGrpPublishing(&testService, dataStore); - testGrpPublishing.runTests(); - - //GxsPublishMsgTest testMsgPublishing(&testService, dataStore); - //testMsgPublishing.runTests(); - - FINALREPORT("RsGenExchangeTest"); - - return 0; -} diff --git a/libretroshare/src/tests/gxs/nxs_test/nxs_tests.pro b/libretroshare/src/tests/gxs/nxs_test/nxs_tests.pro deleted file mode 100644 index 8fa292c61..000000000 --- a/libretroshare/src/tests/gxs/nxs_test/nxs_tests.pro +++ /dev/null @@ -1,203 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2012-05-06T09:19:26 -# -#------------------------------------------------- - - -# -QT += core network - -QT -= gui - -#CONFIG += gen_exchange_target -CONFIG += nxs_net_test -#CONFIG += dstore_target -#CONFIG += gxsdata_target - -CONFIG += bitdht - - - -#gen_exchange_target { - -#TARGET = gen_exchange_test - -#} - -#nxs_net_test { - -TARGET = nxs_net_test - -#} - -#gxsdata_target { - -#TARGET = gxsdata_test -#} - -CONFIG += console -CONFIG -= app_bundle - -TEMPLATE = app - -CONFIG += debug - -debug { -# DEFINES *= DEBUG -# DEFINES *= OPENDHT_DEBUG DHT_DEBUG CONN_DEBUG DEBUG_UDP_SORTER P3DISC_DEBUG DEBUG_UDP_LAYER FT_DEBUG EXTADDRSEARCH_DEBUG -# DEFINES *= CONTROL_DEBUG FT_DEBUG DEBUG_FTCHUNK P3TURTLE_DEBUG -# DEFINES *= P3TURTLE_DEBUG -# DEFINES *= NET_DEBUG -# DEFINES *= DISTRIB_DEBUG -# DEFINES *= P3TURTLE_DEBUG FT_DEBUG DEBUG_FTCHUNK MPLEX_DEBUG -# DEFINES *= STATUS_DEBUG SERV_DEBUG RSSERIAL_DEBUG #CONN_DEBUG - - QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer - QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer -} -################################# Linux ########################################## -# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib -linux-* { - #CONFIG += version_detail_bash_script - QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 - - system(which gpgme-config >/dev/null 2>&1) { - INCLUDEPATH += $$system(gpgme-config --cflags | sed -e "s/-I//g") - } else { - message(Could not find gpgme-config on your system, assuming gpgme.h is in /usr/include) - } - - PRE_TARGETDEPS *= ../../lib/libretroshare.a - - LIBS += ../../lib/libretroshare.a - LIBS += ../../../../libbitdht/src/lib/libbitdht.a - LIBS += ../../../../openpgpsdk/src/lib/libops.a - LIBS += -lssl -lgpgme -lupnp -lixml -lgnome-keyring -lsqlite3 -lbz2 - LIBS *= -rdynamic -frtti - DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions - DEFINES *= HAS_GNOME_KEYRING -} - -linux-g++ { - OBJECTS_DIR = temp/linux-g++/obj -} - -linux-g++-64 { - OBJECTS_DIR = temp/linux-g++-64/obj -} - -#################################### Windows ##################################### - -win32 { - - DEFINES *= WINDOWS_SYS \ - WIN32 \ - STATICLIB \ - MINGW - # Switch on extra warnings - QMAKE_CFLAGS += -Wextra - QMAKE_CXXFLAGS += -Wextra - - # Switch off optimization for release version - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -O0 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE += -O0 - - # Switch on optimization for debug version - #QMAKE_CXXFLAGS_DEBUG += -O2 - #QMAKE_CFLAGS_DEBUG += -O2 - -# PRE_TARGETDEPS += ../../libretroshare/src/lib/libretroshare.a - PRE_TARGETDEPS += ../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a - - LIBS += ../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a - LIBS += C:\Development\Rs\v0.5-gxs-b1\openpgpsdk\openpgpsdk-build-desktop\lib\libops.a - LIBS += C:\Development\Libraries\sqlite\sqlite-autoconf-3070900\lib\libsqlite3.a - LIBS += -L"../../../../../lib" - LIBS += -lssl -lcrypto -lgpgme -lpthreadGC2d -lminiupnpc -lz -lbz2 -# added after bitdht -# LIBS += -lws2_32 - LIBS += -luuid -lole32 -liphlpapi -lcrypt32 -lgdi32 - LIBS += -lole32 -lwinmm - - # export symbols for the plugins - #LIBS += -Wl,--export-all-symbols,--out-implib,lib/libretroshare-gui.a - - GPG_ERROR_DIR = ../../../../libgpg-error-1.7 - GPGME_DIR = ../../../../gpgme-1.1.8 - GPG_ERROR_DIR = ../../../../lib/libgpg-error-1.7 - GPGME_DIR = ../../../../lib/gpgme-1.1.8 - SSL_DIR = ../../../../../OpenSSL - OPENPGPSDK_DIR = ../../../../openpgpsdk/src - INCLUDEPATH += . $${SSL_DIR}/include $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src \ - $${OPENPGPSDK_DIR} - - SQLITE_DIR = ../../../../../../Libraries/sqlite/sqlite-autoconf-3070900 - INCLUDEPATH += . \ - $${SQLITE_DIR} - - - - -} - -bitdht { - - # Chris version. - #LIBS += ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a - #PRE_TARGETDEPS *= ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a -} - -win32 { -# must be added after bitdht - LIBS += -lws2_32 -} - -version_detail_bash_script { - DEFINES += ADD_LIBRETROSHARE_VERSION_INFO - QMAKE_EXTRA_TARGETS += write_version_detail - PRE_TARGETDEPS = write_version_detail - write_version_detail.commands = ./version_detail.sh -} - -install_rs { - INSTALLS += binary_rs - binary_rs.path = $$(PREFIX)/usr/bin - binary_rs.files = ./RetroShare -} - - -#gen_exchange_target { - -# SOURCES += \ -# support.cc \ -# genexchangetester.cpp \ -# genexchangetestservice.cpp \ -# rsdummyservices.cc \ -# rsgenexchange_test.cc - -# HEADERS += support.h \ -# rsdataservice_test.h \ -# rsdummyservices.h \ -# data_support.h -#} - -nxs_net_test { - - SOURCES += \ - support.cc \ - data_support.cc \ - nxstesthub.cc \ - nxstestscenario.cc \ - rsgxsnetservice_test.cc - - HEADERS += support.h \ - nxstestscenario.h \ - nxstesthub.h \ - data_support.h - -} - -INCLUDEPATH += ../../ diff --git a/libretroshare/src/tests/gxs/nxs_test/nxstesthub.cc b/libretroshare/src/tests/gxs/nxs_test/nxstesthub.cc deleted file mode 100644 index e0c505464..000000000 --- a/libretroshare/src/tests/gxs/nxs_test/nxstesthub.cc +++ /dev/null @@ -1,129 +0,0 @@ -#include "nxstesthub.h" - -NxsTestHub::NxsTestHub(NxsTestScenario * nts, std::set &peers) : mTestScenario(nts) -{ - - std::set::iterator sit = peers.begin(); - - for(; sit != peers.end(); sit++) - { - std::set msgPeers = peers; - - // add peers all peers except one iterator currently points to - msgPeers.erase(*sit); - NxsNetDummyMgr* dummyMgr = new NxsNetDummyMgr(*sit, msgPeers); - RsGeneralDataService* ds = mTestScenario->getDataService(*sit); - NxsMessageTestObserver* obs = new NxsMessageTestObserver(ds); - - RsGxsNetService* netService = - new RsGxsNetService(mTestScenario->getServiceType(), - ds, dummyMgr, obs); - - - mNetServices.insert(std::make_pair(*sit, netService)); - mObservers.insert(std::make_pair(*sit, obs)); - } - - sit = peers.begin(); - - // launch net services - for(; sit != peers.end(); sit++) - { - RsGxsNetService* n = mNetServices[*sit]; - createThread(*n); - mServices.insert(std::make_pair(*sit, n)); - } -} - -NxsTestHub::~NxsTestHub() -{ - std::map::iterator mit = mNetServices.begin(); - - for(; mit != mNetServices.end(); mit++) - delete mit->second; -} - - -void NxsTestHub::run() -{ - double timeDelta = .2; - - while(isRunning()){ - - // make thread sleep for a bit - #ifndef WINDOWS_SYS - usleep((int) (timeDelta * 1000000)); - #else - Sleep((int) (timeDelta * 1000)); - #endif - - - std::map::iterator mit = mServices.begin(); - - for(; mit != mServices.end(); mit++) - { - p3Service* s = mit->second; - s->tick(); - } - - mit = mServices.begin(); - - // collect msgs to send to peers from peers - for(; mit != mServices.end(); mit++) - { - const std::string& peer = mit->first; - p3Service* s = mit->second; - - // first store all the sends from all services - RsItem* item = NULL; - - while((item = s->send()) != NULL){ - - const std::string peerToReceive = item->PeerId(); - - // set the peer this item comes from - item->PeerId(peer); - mPeerQueues[peerToReceive].push_back(item); - } - - - } - - // now route items to peers - std::map >::iterator mit_queue = mPeerQueues.begin(); - - for(; mit_queue != mPeerQueues.end(); mit_queue++) - { - std::vector& queueV = mit_queue->second; - std::vector::iterator vit = queueV.begin(); - const std::string peerToReceive = mit_queue->first; - for(; vit != queueV.end(); vit++) - { - - RsItem* item = *vit; - p3Service* service = mServices[peerToReceive]; - - service->receive(dynamic_cast(item)); - } - queueV.clear(); - } - } -} - -void NxsTestHub::cleanUp() -{ - std::map::iterator mit = mNetServices.begin(); - for(; mit != mNetServices.end(); mit++) - { - RsGxsNetService* n = mit->second; - n->join(); - } - - // also shut down this net service peers if this goes down - mTestScenario->cleanUp(); -} - -bool NxsTestHub::testsPassed() -{ - return false; -} diff --git a/libretroshare/src/tests/gxs/nxs_test/nxstesthub.h b/libretroshare/src/tests/gxs/nxs_test/nxstesthub.h deleted file mode 100644 index 15f10e0b4..000000000 --- a/libretroshare/src/tests/gxs/nxs_test/nxstesthub.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef NXSTESTHUB_H -#define NXSTESTHUB_H - -#include "util/rsthreads.h" -#include "gxs/rsgxsnetservice.h" -#include "nxstestscenario.h" - -// it would probably be useful if the test scenario -// provided the net dummy managers -// hence one could envision synchronising between an arbitrary number -// of peers - - -class NxsNetDummyMgr : public RsNxsNetMgr -{ - -public: - - NxsNetDummyMgr(std::string ownId, std::set peers) : mOwnId(ownId), mPeers(peers) { - - } - - std::string getOwnId() { return mOwnId; } - void getOnlineList(std::set& ssl_peers) { ssl_peers = mPeers; } - -private: - - std::string mOwnId; - std::set mPeers; - -}; - - -/*! - * Testing of nxs services occurs through use of two services - * When a service sends this class can interrogate the send and the receives of - * - * NxsScenario stores the type of synchronisation to be tested - * Operation: - * First NxsTestHub needs to be instantiated with a test scenario - * * The scenario contains two databases to be used on the communicating pair of RsGxsNetService instances (net instances) - * The Test hub has a ticker service for the p3Services which allows the netservices to search what groups and messages they have - * and synchronise according to their subscriptions. The default is to subscribe to all groups held by other peer - * The threads for both net instances are started which begins their processing of transactions - */ -class NxsTestHub : public RsThread -{ -public: - - - /*! - * This construct the test hub - * for a give scenario in mind - */ - NxsTestHub(NxsTestScenario*, std::set& peers); - - - /*! - * - */ - virtual ~NxsTestHub(); - - /*! - * To be called only after this thread has - * been shutdown - */ - bool testsPassed(); - - /*! - * This simulates the p3Service ticker and calls both gxs net services tick methods - * Also enables transport of messages between both services - */ - void run(); - - - void cleanUp(); -private: - - std::map mServices; - std::map mNetServices; - std::map mObservers; - - std::map > mPeerQueues; - - NxsTestScenario *mTestScenario; - -}; - -#endif // NXSTESTHUB_H diff --git a/libretroshare/src/tests/gxs/nxs_test/nxstestscenario.cc b/libretroshare/src/tests/gxs/nxs_test/nxstestscenario.cc deleted file mode 100644 index c4cf5c666..000000000 --- a/libretroshare/src/tests/gxs/nxs_test/nxstestscenario.cc +++ /dev/null @@ -1,177 +0,0 @@ -/* - * nxstestscenario.cc - * - * Created on: 10 Jul 2012 - * Author: crispy - */ - -#include "nxstestscenario.h" -#include "gxs/rsdataservice.h" -#include "retroshare/rsgxsflags.h" -#include "data_support.h" -#include - -NxsMessageTest::NxsMessageTest(uint16_t servtype) -: mServType(servtype), mMsgTestMtx("mMsgTestMtx") -{ - -} - -std::string NxsMessageTest::getTestName() -{ - return std::string("Nxs Message Test!"); -} - -NxsMessageTest::~NxsMessageTest(){ - - std::map::iterator mit = mPeerStoreMap.begin(); - - for(; mit != mPeerStoreMap.end(); mit++) - { - delete mit->second; - } - - std::set::iterator sit = mStoreNames.begin(); - - // remove db file - for(; sit != mStoreNames.end(); sit++) - { - const std::string& name = *sit; - remove(name.c_str()); - } -} -RsGeneralDataService* NxsMessageTest::getDataService(const std::string& peer) -{ - if(mPeerStoreMap.find(peer) != mPeerStoreMap.end()) return NULL; - - RsDataService* dStore = new RsDataService("./", peer, mServType); - mStoreNames.insert(peer); - mPeerStoreMap.insert(std::make_pair(peer, dStore)); - populateStore(dStore); - - return dStore; -} - -uint16_t NxsMessageTest::getServiceType() -{ - return mServType; -} - -void NxsMessageTest::populateStore(RsGeneralDataService* dStore) -{ - - int nGrp = (rand()%2)+1; - std::vector grpIdList; - std::map grps; - RsNxsGrp* grp = NULL; - RsGxsGrpMetaData* grpMeta =NULL; - for(int i = 0; i < nGrp; i++) - { - std::pair p; - grp = new RsNxsGrp(mServType); - grpMeta = new RsGxsGrpMetaData(); - p.first = grp; - p.second = grpMeta; - init_item(*grp); - init_item(grpMeta); - grpMeta->mGroupId = grp->grpId; - grps.insert(p); - grpIdList.push_back(grp->grpId); - grpMeta = NULL; - grp = NULL; - } - - dStore->storeGroup(grps); - - int nMsgs = rand()%23; - std::map msgs; - RsNxsMsg* msg = NULL; - RsGxsMsgMetaData* msgMeta = NULL; - - for(int i=0; i p(msg, msgMeta); - - // pick a grp at random to associate the msg to - const std::string& grpId = grpIdList[rand()%nGrp]; - msgMeta->mMsgId = msg->msgId; - msgMeta->mGroupId = msg->grpId = grpId; - - msg = NULL; - msgMeta = NULL; - - msgs.insert(p); - } - - - dStore->storeMessage(msgs); - - return; -} - -void NxsMessageTest::cleanUp() -{ - - std::map::iterator mit = mPeerStoreMap.begin(); - - for(; mit != mPeerStoreMap.end(); mit++) - { - RsGeneralDataService* d = mit->second; - d->resetDataStore(); - } - - return; -} - -bool NxsMessageTest::testPassed(){ - return false; -} - -/*******************************/ - -NxsMessageTestObserver::NxsMessageTestObserver(RsGeneralDataService *dStore) - :mStore(dStore) -{ - -} - -void NxsMessageTestObserver::notifyNewGroups(std::vector &groups) -{ - std::vector::iterator vit = groups.begin(); - std::map grps; - - for(; vit != groups.end(); vit++) - { - RsNxsGrp* grp = *vit; - RsGxsGrpMetaData* meta = new RsGxsGrpMetaData(); - meta->deserialise(grp->meta.bin_data, grp->meta.bin_len); - meta->mSubscribeFlags |= GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED; - meta->mGroupId = grp->grpId; - grps.insert(std::make_pair(grp, meta)); - } - - mStore->storeGroup(grps); -} - -void NxsMessageTestObserver::notifyNewMessages(std::vector &messages) -{ - - std::vector::iterator vit = messages.begin(); - std::map msgs; - - for(; vit != messages.end(); vit++) - { - RsNxsMsg* msg = *vit; - RsGxsMsgMetaData* meta = new RsGxsMsgMetaData(); - meta->mGroupId = msg->grpId; - meta->mMsgId = msg->msgId; - msgs.insert(std::make_pair(msg, meta)); - } - - mStore->storeMessage(msgs); -} - diff --git a/libretroshare/src/tests/gxs/nxs_test/nxstestscenario.h b/libretroshare/src/tests/gxs/nxs_test/nxstestscenario.h deleted file mode 100644 index 72500e4d3..000000000 --- a/libretroshare/src/tests/gxs/nxs_test/nxstestscenario.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * nxstestscenario.h - * - * Created on: 10 Jul 2012 - * Author: crispy - */ - -#ifndef NXSTESTSCENARIO_H_ -#define NXSTESTSCENARIO_H_ - -#include -#include "gxs/rsdataservice.h" -#include "gxs/rsnxsobserver.h" - -/*! - * This scenario module provides data resources - */ -class NxsTestScenario -{ - -public: - - virtual std::string getTestName() = 0; - - /*! - * @param peer - * @param namePath - * @return data service with populated with random grp/msg data, null if peer or pathname exists - */ - virtual RsGeneralDataService* getDataService(const std::string& peer) = 0; - - - virtual bool testPassed() = 0; - /*! - * Service type for this test - * should correspond to serialiser service type - */ - virtual uint16_t getServiceType() = 0; - - /*! - * Call to remove files created - * in the test directory - */ - virtual void cleanUp() = 0; - - -}; - -class NxsMessageTestObserver : public RsNxsObserver -{ -public: - - NxsMessageTestObserver(RsGeneralDataService* dStore); - - /*! - * @param messages messages are deleted after function returns - */ - void notifyNewMessages(std::vector& messages); - - /*! - * @param messages messages are deleted after function returns - */ - void notifyNewGroups(std::vector& groups); - -private: - - RsGeneralDataService* mStore; - -}; - -class NxsMessageTest : public NxsTestScenario -{ - -public: - - NxsMessageTest(uint16_t servtype); - virtual ~NxsMessageTest(); - std::string getTestName(); - uint16_t getServiceType(); - RsGeneralDataService* getDataService(const std::string& peer); - - /*! - * Call to remove files created - * in the test directory - */ - void cleanUp(); - - bool testPassed(); - -private: - void setUpDataBases(); - void populateStore(RsGeneralDataService* dStore); - -private: - - std::string mTestName; - std::map mPeerStoreMap; - std::set mStoreNames; - uint16_t mServType; - - RsMutex mMsgTestMtx; - -}; - - -#endif /* NXSTESTSCENARIO_H_ */ diff --git a/libretroshare/src/tests/gxs/nxs_test/rsgxsnetservice_test.cc b/libretroshare/src/tests/gxs/nxs_test/rsgxsnetservice_test.cc deleted file mode 100644 index ddcc2f6c0..000000000 --- a/libretroshare/src/tests/gxs/nxs_test/rsgxsnetservice_test.cc +++ /dev/null @@ -1,46 +0,0 @@ -/* - * rsgxsnetservice_test.cc - * - * Created on: 11 Jul 2012 - * Author: crispy - */ - -#include "util/utest.h" -#include "nxstesthub.h" -#include "nxstestscenario.h" - -INITTEST(); - - -int main() -{ - - // first setup - NxsMessageTest msgTest(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); - std::set peers; - peers.insert("PeerA"); - peers.insert("PeerB"); - NxsTestHub hub(&msgTest, peers); - - // now get things started - createThread(hub); - - double timeDelta = 50; - - // put this thread to sleep for 10 secs - // make thread sleep for a bit -#ifndef WINDOWS_SYS - usleep((int) (timeDelta * 1000000)); -#else - Sleep((int) (timeDelta * 1000)); -#endif - - hub.join(); - CHECK(hub.testsPassed()); - - hub.cleanUp(); - - FINALREPORT("RsGxsNetService Tests"); - - return TESTRESULT(); -} diff --git a/libretroshare/src/tests/network_simulator/README.txt b/libretroshare/src/tests/network_simulator/README.txt deleted file mode 100644 index 2a669d3c3..000000000 --- a/libretroshare/src/tests/network_simulator/README.txt +++ /dev/null @@ -1,87 +0,0 @@ -TODO -==== - -Testing the router algorithm with network simulator - * generate a random network - * simulate disconnections (also in GUI) - * send messages from/to random peers and measure: - - how many times a given message is stored - - how much time a given message took to arrive. - -Implement - * clueing of GR from GXS (simulated in network simulator, when initing the network) - -In GLobal Router, by order of priority - * when a ACK is received for a msg that is already ACKed, we should still update the routing matrix and add a clue, but with lower prioity, - so that the matrix gets filled with additional routes. Can be checked in the simulator - - * routing strategy: - - when a route is known and available, always select it, but possibly add another random route, very rarely. - Peer disconnection is likely to cause the discovery of new routes anyway. - - * we should use clues from GXS to improve the routing matrix - - That would avoid lots of spamming. - - allows to init the routing matrices for all keys - - random walk will be a supplemental help, but restricted to small depth if no indication of route is available. - - needs to be implemented in network simulator. When providing a new key, the key should be spread in the network and new clues - should be added to the RGrouter matrix. - - * make sure the depth is accounted better: - - if single route is known => don't limit depth - - if no route is known => strictly limit depth - => add a counter which is increased when no route is available, and *reset* otherwise, so that the max number of bounce - we can do without knowledge of the keys is limited, but the total depth has no limits. - -Unsolved questions: - * handle dead routes correctly. How? - * should we send ACKs everywhere even upward? No, if we severely limit the depth of random walk. - * better distribute routing events, so that the matrix gets filled better? - * find a strategy to avoid storing too many items - * how to handle cases where a ACK cannot be sent back? The previous peer is going to try indefinitly? - => the ACK will be automatically collected by another route! - * how to make sure ACKed messages are not stored any longer than necessary? - * send signed ACKs, so that the receiver cannot be spoofed. - * only ACK when the message was properly received by the client service. No ACK if the client does not register that item? - -================================================================================================================ - - -The purpose of this directory is to write a Network simulator, that can have multiple turtle routers interact -together. The routers will talk to a fake link manager, which reports the peers for each node of a network graph. - -Required components: -=================== - NetworkGraph: a set of friends, with connections. Should be able to be saved to a file for debugging. - - GraphNode: a RS peer, represented by a random SSL id, a link manager, and possibly components such as file transfer, etc. - - Main loop: a loop calling tick() on all turtle routers. - - Functions: - * gather statistics over network load. See if tunnels are ok, improve bandwidth allocation strategy, see request broadcast. - - GUI: - * visualization of the graph. OpenGL + qglviewer window. Show tunnels, data flow as colors, etc. - * give quantitative information under mouse - * the user can trigger behaviors, execute tunnel handling orders, cause file transfer, etc. - - -Implementation constraints -========================== - * sendItem() and recvItems() should come from above. The class p3Service thus needs to be re-implemented to get/send the - data properly. - - => define subclass of p3turtle , where send() and recv() are redefined. - - * LinkMgr: - getOwnId(), getLinkType(), getOnlineList() - - used by turtle - - * turtle needs LinkMgr and ftServer. The ftServer can be contructed from PeerMgr (not called except in ftServer::setupFtServer. not needed here. - -Complilation -============ - * needs the QGLViewer-dev library (standard on ubuntu, package name is libqglviewer-qt4-dev) - * should compile on windows and MacOS as well. Use http://www.libqglviewer.com - diff --git a/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.cpp b/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.cpp deleted file mode 100644 index c1642cbb6..000000000 --- a/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/**************************************************************** - * RetroShare is distributed under the following license: - * - * Copyright (C) 20011, RetroShare Team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - ****************************************************************/ - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include "GlobalRouterStatistics.h" - -static const int MAX_TUNNEL_REQUESTS_DISPLAY = 10 ; - -static QColor colorScale(float f) -{ - if(f == 0) - return QColor::fromHsv(0,0,192) ; - else - return QColor::fromHsv((int)((1.0-f)*280),200,255) ; -} - -GlobalRouterStatistics::GlobalRouterStatistics(QWidget *parent) - : RsAutoUpdatePage(2000,parent) -{ - setupUi(this) ; - - _router_F->setWidget( _tst_CW = new GlobalRouterStatisticsWidget() ) ; - _grouter = NULL ; -} - -GlobalRouterStatistics::~GlobalRouterStatistics() -{ -} - -void GlobalRouterStatistics::setGlobalRouter(const RsGRouter *grouter) -{ - _grouter = const_cast(grouter); - updateDisplay() ; -} -void GlobalRouterStatistics::updateDisplay() -{ - if(_grouter != NULL) - _tst_CW->updateContent(_grouter) ; -} - -QString GlobalRouterStatistics::getPeerName(const RsPeerId &peer_id) -{ - static std::map names ; - - std::map::const_iterator it = names.find(peer_id) ; - - if( it != names.end()) - return it->second ; - else - { - RsPeerDetails detail ; - if(!rsPeers->getPeerDetails(peer_id,detail)) - return tr("Unknown Peer"); - - return (names[peer_id] = QString::fromUtf8(detail.name.c_str())) ; - } -} - -GlobalRouterStatisticsWidget::GlobalRouterStatisticsWidget(QWidget *parent) - : QWidget(parent) -{ - maxWidth = 400 ; - maxHeight = 0 ; -} - -void GlobalRouterStatisticsWidget::updateContent(RsGRouter *grouter) -{ - std::vector cache_infos ; - RsGRouter::GRouterRoutingMatrixInfo matrix_info ; - - grouter->getRoutingCacheInfo(cache_infos) ; - grouter->getRoutingMatrixInfo(matrix_info) ; - - // What do we need to draw? - // - // Routing matrix - // Key [][][][][][][][][][] - // - // -> each [] shows a square (one per friend location) that is the routing probabilities for all connected friends - // computed using the "computeRoutingProbabilitites()" method. - // - // Own key ids - // key service id description - // - // Data items - // Msg id Local origin Destination Time Status - // - static const int cellx = 6 ; - static const int celly = 10+4 ; - - QPixmap tmppixmap(maxWidth, maxHeight); - tmppixmap.fill(this, 0, 0); - setFixedHeight(maxHeight); - - QPainter painter(&tmppixmap); - painter.initFrom(this); - painter.setPen(QColor::fromRgb(0,0,0)) ; - - maxHeight = 500 ; - - // std::cerr << "Drawing into pixmap of size " << maxWidth << "x" << maxHeight << std::endl; - // draw... - int ox=5,oy=5 ; - - painter.drawText(ox,oy+celly,tr("Pending packets")+":" + QString::number(cache_infos.size())) ; oy += celly*2 ; - - for(uint32_t i=0;i::const_iterator it(matrix_info.published_keys.begin());it!=matrix_info.published_keys.end();++it) - { - QString packet_string ; - packet_string += QString::fromStdString(it->first.toStdString()) ; - packet_string += tr(" : Service ID = ")+QString::number(it->second.service_id,16) ; - packet_string += " \""+QString::fromUtf8(it->second.description_string.c_str()) + "\"" ; - - painter.drawText(ox+2*cellx,oy+celly,packet_string ) ; oy += celly ; - } - oy += celly ; - - QString prob_string ; - - painter.drawText(ox+0*cellx,oy+celly,tr("Routing matrix (")) ; - - // draw scale - - for(int i=0;i<100;++i) - { - painter.setPen(colorScale(i/100.0)) ; - painter.drawLine(ox+120+i,oy+celly+2,ox+120+i,oy+2) ; - } - painter.setPen(QColor::fromRgb(0,0,0)) ; - - painter.drawText(ox+230,oy+celly,")") ; - - oy += celly ; - oy += celly ; - - static const int MaxKeySize = 20 ; - - for(std::map >::const_iterator it(matrix_info.per_friend_probabilities.begin());it!=matrix_info.per_friend_probabilities.end();++it) - { - painter.drawText(ox+2*cellx,oy+celly,QString::fromStdString(it->first.toStdString())+" : ") ; - - for(uint32_t i=0;isecond[i])) ; - - oy += celly ; - } - - oy += celly ; - oy += celly ; - - // update the pixmap - // - pixmap = tmppixmap; - maxHeight = oy ; -} - -QString GlobalRouterStatisticsWidget::speedString(float f) -{ - if(f < 1.0f) - return QString("0 B/s") ; - if(f < 1024.0f) - return QString::number((int)f)+" B/s" ; - - return QString::number(f/1024.0,'f',2) + " KB/s"; -} - -void GlobalRouterStatisticsWidget::paintEvent(QPaintEvent */*event*/) -{ - QStylePainter(this).drawPixmap(0, 0, pixmap); -} - -void GlobalRouterStatisticsWidget::resizeEvent(QResizeEvent *event) -{ - QRect TaskGraphRect = geometry(); - maxWidth = TaskGraphRect.width(); - maxHeight = TaskGraphRect.height() ; - - QWidget::resizeEvent(event); -// updateContent(); -} - diff --git a/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.h b/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.h deleted file mode 100644 index b3bc067de..000000000 --- a/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************** - * RetroShare is distributed under the following license: - * - * Copyright (C) 20011, RetroShare Team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - ****************************************************************/ - -#pragma once - -#include -#include -#include - -#include "RsAutoUpdatePage.h" -#include "ui_GlobalRouterStatistics.h" - -class GlobalRouterStatisticsWidget ; -class p3GRouter ; - -class GlobalRouterStatistics: public RsAutoUpdatePage, public Ui::GlobalRouterStatistics -{ - Q_OBJECT - - public: - GlobalRouterStatistics(QWidget *parent = NULL) ; - ~GlobalRouterStatistics(); - - // Cache for peer names. - static QString getPeerName(const RsPeerId& peer_id) ; - - void setGlobalRouter(const RsGRouter *grouter) ; - virtual void updateDisplay() ; - - private: - - - GlobalRouterStatisticsWidget *_tst_CW ; - RsGRouter *_grouter ; -} ; - -class GlobalRouterStatisticsWidget: public QWidget -{ - Q_OBJECT - - public: - GlobalRouterStatisticsWidget(QWidget *parent = NULL) ; - - virtual void paintEvent(QPaintEvent *event) ; - virtual void resizeEvent(QResizeEvent *event); - - void updateContent(RsGRouter *grouter) ; - private: - static QString speedString(float f) ; - - QPixmap pixmap ; - int maxWidth,maxHeight ; -}; - diff --git a/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.ui b/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.ui deleted file mode 100644 index 0e6e28f7b..000000000 --- a/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.ui +++ /dev/null @@ -1,55 +0,0 @@ - - - GlobalRouterStatistics - - - - 0 - 0 - 611 - 408 - - - - Router Statistics - - - - :/images/rstray3.png:/images/rstray3.png - - - - - - Qt::Vertical - - - - QFrame::NoFrame - - - Qt::ScrollBarAlwaysOff - - - true - - - - - 0 - 0 - 593 - 390 - - - - - - - - - - - - - diff --git a/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.cpp b/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.cpp deleted file mode 100644 index b32e70931..000000000 --- a/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include - -#include "NetworkSimulatorGUI.h" -#include "NetworkViewer.h" -#include "TurtleRouterStatistics.h" -#include "GlobalRouterStatistics.h" - -NetworkSimulatorGUI::NetworkSimulatorGUI(Network& net) -{ - setupUi(this) ; - tickTimerId = 0 ; - - QVBoxLayout *layout = new QVBoxLayout(networkViewFrame) ; - layout->addWidget(_viewer = new NetworkViewer(networkViewFrame,net)) ; - - QObject::connect(_viewer,SIGNAL(nodeSelected(int)),this,SLOT(updateSelectedNode(int))) ; - QObject::connect(flow_CB,SIGNAL(toggled(bool)),this,SLOT(toggleNetworkTraffic(bool))) ; - - QVBoxLayout *layout2 = new QVBoxLayout(inspectorFrame) ; - QTabWidget *tabwidget = new QTabWidget() ; - - layout2->addWidget(tabwidget) ; - - tabwidget->addTab(_turtle_router_statistics = new TurtleRouterStatistics(),"Turtle router" ) ; - tabwidget->addTab(_global_router_statistics = new GlobalRouterStatistics(),"Global router" ) ; -} - -void NetworkSimulatorGUI::updateSelectedNode(int node_id) -{ - const RsTurtle *turtle = _viewer->network().node(node_id).turtle_service() ; - const RsGRouter *grouter = _viewer->network().node(node_id).global_router_service() ; - - _turtle_router_statistics->setTurtleRouter( turtle ) ; - _global_router_statistics->setGlobalRouter( grouter ) ; - - // make only the selected node to display grouter info - - for(uint32_t i=0;i<_viewer->network().n_nodes();++i) - _viewer->network().node(i).global_router_service()->setDebugEnabled(i==node_id) ; - - std::cerr << "Selected objects: turtle=" << std::hex << turtle << ", grouter=" << grouter << std::dec << std::endl; -} - -void NetworkSimulatorGUI::toggleNetworkTraffic(bool b) -{ - if(!b && tickTimerId > 0) - { - killTimer(tickTimerId) ; - tickTimerId = 0 ; - return ; - } - - if(b && tickTimerId == 0) - { - tickTimerId = startTimer(1000) ; - return ; - } - - std::cerr << "ERROR !!" << std::endl; -} - -void NetworkSimulatorGUI::timerEvent(QTimerEvent *event) -{ - Q_UNUSED(event) ; - - //std::cerr << "timer event!" << std::endl; - - _viewer->network().tick() ; - -} - diff --git a/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.h b/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.h deleted file mode 100644 index ddd2abef6..000000000 --- a/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.h +++ /dev/null @@ -1,28 +0,0 @@ -#include "ui_NetworkSimulatorGUI.h" - -class TurtleRouterStatistics ; -class GlobalRouterStatistics ; -class NetworkViewer ; -class Network ; - -class NetworkSimulatorGUI: public QMainWindow, public Ui::NetworkSimulatorGUI -{ - Q_OBJECT - - public: - NetworkSimulatorGUI(Network& net) ; - - public slots: - void updateSelectedNode(int) ; - void toggleNetworkTraffic(bool) ; - - virtual void timerEvent(QTimerEvent *e) ; - - private: - NetworkViewer *_viewer ; - TurtleRouterStatistics *_turtle_router_statistics ; - GlobalRouterStatistics *_global_router_statistics ; - - int tickTimerId ; -}; - diff --git a/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.ui b/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.ui deleted file mode 100644 index 6ac45d8bf..000000000 --- a/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.ui +++ /dev/null @@ -1,106 +0,0 @@ - - - NetworkSimulatorGUI - - - - 0 - 0 - 901 - 600 - - - - MainWindow - - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - flow - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - 0 - 0 - 901 - 25 - - - - - File - - - - - - - - - - Load network - - - - - Save network - - - - - - diff --git a/libretroshare/src/tests/network_simulator/gui/NetworkViewer.cpp b/libretroshare/src/tests/network_simulator/gui/NetworkViewer.cpp deleted file mode 100644 index 8f1cf9535..000000000 --- a/libretroshare/src/tests/network_simulator/gui/NetworkViewer.cpp +++ /dev/null @@ -1,681 +0,0 @@ -#include -#include -#include - -#include - -#include "nscore/Network.h" -#include "nscore/MonitoredGRouterClient.h" -#include "NetworkViewer.h" - -NetworkViewer::NetworkViewer(QWidget *parent,Network&net) - : QGLViewer(parent),_network(net) , timerId(0) -{ - _current_selected_node = -1 ; - _current_displayed_node = -1 ; - _current_acted_node = -1 ; - - _dragging = false ; - _nodes_need_recomputing = true ; - - _node_coords.resize(net.n_nodes()) ; - _node_speeds.resize(net.n_nodes()) ; - - for(int i=0;i<_node_coords.size();++i) - { - _node_coords[i].x = drand48()*width()*5; - _node_coords[i].y = drand48()*height()*5 ; - _node_speeds[i].x = 0 ; - _node_speeds[i].y = 0 ; - } - - timerId = startTimer(1000/25) ; - - connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenu(QPoint))); - - action_ClientForHash = new QAction(tr("Client for new random hash"),this) ; - QObject::connect(action_ClientForHash,SIGNAL(triggered()),this,SLOT(actionClientForHash())) ; - - action_ProvideGRKey = new QAction(tr("Provide new GRouter key"),this) ; - QObject::connect(action_ProvideGRKey,SIGNAL(triggered()),this,SLOT(actionProvideGRKey())) ; - - setMouseTracking(true) ; -} - -void NetworkViewer::draw() -{ - glDisable(GL_DEPTH_TEST) ; - glClear(GL_COLOR_BUFFER_BIT) ; - - // for now, view is fixed. - - glMatrixMode(GL_MODELVIEW) ; - glPushMatrix() ; - glLoadIdentity() ; - glMatrixMode(GL_PROJECTION) ; - glPushMatrix() ; - glLoadIdentity() ; - glOrtho(0,width(),0,height(),1,-1) ; - - glEnable(GL_BLEND) ; - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) ; - - // Now, draw all edges - - std::set tunnel_nodes ; - - glEnable(GL_LINE_SMOOTH) ; - glBegin(GL_LINES) ; - - for(uint32_t i=0;i<_network.n_nodes();++i) - { - PeerNode::NodeTrafficInfo traffic_info ; - _network.node(i).getTrafficInfo(traffic_info) ; - - const std::set& neighs( _network.neighbors(i) ) ; - - for(std::set::const_iterator it(neighs.begin());it!=neighs.end();++it) - { - if(traffic_info.local_src.find(_network.node(*it).id().toStdString())!=traffic_info.local_src.end() || traffic_info.local_dst.find(_network.node(*it).id().toStdString())!=traffic_info.local_dst.end()) - { - glColor3f(0.9f,0.4f,0.2f) ; - tunnel_nodes.insert(i) ; - tunnel_nodes.insert(*it) ; - } - else - glColor3f(0.4f,0.4f,0.4f) ; - - if( i < *it ) - { - glVertex2f(_node_coords[ i].x, _node_coords[ i].y) ; - glVertex2f(_node_coords[*it].x, _node_coords[*it].y) ; - } - } - } - - glEnd() ; - - // Draw all nodes. - // - glEnable(GL_POINT_SMOOTH) ; - glPointSize(20.0f) ; - glBegin(GL_POINTS) ; - - if(_current_selected_node > -1) - { - glColor4f(1.0f,0.2f,0.1f,0.7f) ; - glVertex2f(_node_coords[_current_selected_node].x, _node_coords[_current_selected_node].y) ; - } - glEnd() ; - - glPointSize(10.0f) ; - glBegin(GL_POINTS) ; - - for(uint32_t i=0;i<_network.n_nodes();++i) - { - float r = 0.8 ; - float g = 0.8 ; - float b = 0.8 ; - - if(!_network.node(i).providedHashes().empty()) - r *= 2.0, g /= 2.0, b /= 2.0f ; - - if(!_network.node(i).managedHashes().empty()) - g *= 2.0, b /= 2.0, r /= 2.0f ; - - if(tunnel_nodes.find(i) != tunnel_nodes.end() && r==0.8f && g==0.8f && b==0.8f) - r = 0.9f, g=0.4f,b=0.2f ; - - std::vector infos ; - _network.node(i).global_router_service()->getRoutingCacheInfo(infos) ; - - if(infos.size() == 1) - switch(infos[0].status) - { - case 1: r=1 ; g=0.5; b=0.1 ; break ; - case 2: r=0.4; g=0.5; b=0.4 ; break ; - case 3: r=0.2; g=0.2; b=0.7 ; break ; - case 4: r=0.6; g=0.1; b=0.2 ; break ; - default: - r=0.2; g=0.2; b=0.2 ; break ; - } - - glColor3f(r,g,b) ; - - glVertex2f(_node_coords[i].x, _node_coords[i].y) ; - } - - glEnd() ; - - // Draw info about current node under mouse. - // - if(_current_displayed_node > -1) - { - const PeerNode& node(_network.node(_current_displayed_node)) ; - int offset = 0 ; - int text_height = 15 ; - - drawText(10+_node_coords[_current_displayed_node].x,offset + height()-_node_coords[_current_displayed_node].y, "Node id = " + QString::fromStdString(node.id().toStdString())) ; - offset += text_height ; - - for(std::set::const_iterator it(node.providedHashes().begin());it!=node.providedHashes().end();++it) - { - drawText(10+_node_coords[_current_displayed_node].x,offset + height()-_node_coords[_current_displayed_node].y, "Server for hash " + QString::fromStdString((*it).toStdString()) ); - offset += text_height ; - } - - for(std::set::const_iterator it(node.managedHashes().begin());it!=node.managedHashes().end();++it) - { - drawText(10+_node_coords[_current_displayed_node].x,offset + height()-_node_coords[_current_displayed_node].y, "Client for hash " + QString::fromStdString((*it).toStdString()) ) ; - offset += text_height ; - } - } - - glMatrixMode(GL_MODELVIEW) ; - glPopMatrix() ; - glMatrixMode(GL_PROJECTION) ; - glPopMatrix() ; -} - -#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr - -void fourn(double data[],unsigned long nn[],unsigned long ndim,int isign) -{ - int i1,i2,i3,i2rev,i3rev,ip1,ip2,ip3,ifp1,ifp2; - int ibit,idim,k1,k2,n,nprev,nrem,ntot; - double tempi,tempr; - double theta,wi,wpi,wpr,wr,wtemp; - - ntot=1; - for (idim=1;idim<=(long)ndim;idim++) - ntot *= nn[idim]; - nprev=1; - for (idim=ndim;idim>=1;idim--) { - n=nn[idim]; - nrem=ntot/(n*nprev); - ip1=nprev << 1; - ip2=ip1*n; - ip3=ip2*nrem; - i2rev=1; - for (i2=1;i2<=ip2;i2+=ip1) { - if (i2 < i2rev) { - for (i1=i2;i1<=i2+ip1-2;i1+=2) { - for (i3=i1;i3<=ip3;i3+=ip2) { - i3rev=i2rev+i3-i2; - SWAP(data[i3],data[i3rev]); - SWAP(data[i3+1],data[i3rev+1]); - } - } - } - ibit=ip2 >> 1; - while (ibit >= ip1 && i2rev > ibit) { - i2rev -= ibit; - ibit >>= 1; - } - i2rev += ibit; - } - ifp1=ip1; - while (ifp1 < ip2) { - ifp2=ifp1 << 1; - theta=isign*6.28318530717959/(ifp2/ip1); - wtemp=sin(0.5*theta); - wpr = -2.0*wtemp*wtemp; - wpi=sin(theta); - wr=1.0; - wi=0.0; - for (i3=1;i3<=ifp1;i3+=ip1) { - for (i1=i3;i1<=i3+ip1-2;i1+=2) { - for (i2=i1;i2<=ip3;i2+=ifp2) { - k1=i2; - k2=k1+ifp1; - tempr=wr*data[k2]-wi*data[k2+1]; - tempi=wr*data[k2+1]+wi*data[k2]; - data[k2]=data[k1]-tempr; - data[k2+1]=data[k1+1]-tempi; - data[k1] += tempr; - data[k1+1] += tempi; - } - } - wr=(wtemp=wr)*wpr-wi*wpi+wr; - wi=wi*wpr+wtemp*wpi+wi; - } - ifp1=ifp2; - } - nprev *= n; - } -} - -#undef SWAP - -static void convolveWithGaussian(double *forceMap,int S,int /*s*/) -{ - static double *bf = NULL ; - - if(bf == NULL) - { - bf = new double[S*S*2] ; - - for(int i=0;i derivative is constant - bf[2*(i+S*j)+1] = 0 ; - } - - unsigned long nn[2] = {S,S}; - fourn(&bf[-1],&nn[-1],2,1) ; - } - - unsigned long nn[2] = {S,S}; - fourn(&forceMap[-1],&nn[-1],2,1) ; - - for(int i=0;i=0 && i=0 && j new_coords(_node_coords) ; - - for(uint32_t i=0;i<_network.n_nodes();++i) - if(i != _current_selected_node || !_dragging) - { - float x = _node_coords[i].x ; - float y = _node_coords[i].y ; - - calculateForces(i,forceMap,S,S,x,y,speedf,new_coords[i].x,new_coords[i].y); - } - - bool itemsMoved = false; - for(uint32_t i=0;i<_node_coords.size();++i) - { - if( fabsf(_node_coords[i].x - new_coords[i].x) > 1.0 || fabsf(_node_coords[i].y - new_coords[i].y) > 1.0) - itemsMoved = true; - - //std::cerr << "Old i = " << _node_coords[i].x << ", new = " << new_coords[i].x << std::endl; - _node_coords[i] = new_coords[i] ; - } - - if (!itemsMoved) { - // killTimer(timerId); - //#ifdef DEBUG_ELASTIC - std::cerr << "Killing timr" << std::endl ; - _nodes_need_recomputing = false ; - //#endif - timerId = 0; - } - else - { - updateGL() ; - usleep(2000) ; - } - } - else - updateGL() ; - -} - -void NetworkViewer::mouseMoveEvent(QMouseEvent *e) -{ - if(_dragging && _current_selected_node >= 0) - { - _node_coords[_current_selected_node].x = e->x() ; - _node_coords[_current_selected_node].y = height() - e->y() ; - - _nodes_need_recomputing = true ; - - updateGL() ; - } - - float x = e->x() ; - float y = height()-e->y() ; - - _current_displayed_node = -1 ; - - for(uint32_t i=0;i<_node_coords.size();++i) - if( pow(_node_coords[i].x-x,2)+pow(_node_coords[i].y-y,2) < 5*5) - { - _current_displayed_node = i; - break ; - } -} - -void NetworkViewer::mouseReleaseEvent(QMouseEvent *e) -{ - _dragging = false ; -} - -void NetworkViewer::mousePressEvent(QMouseEvent *e) -{ - float x = e->x() ; - float y = height() - e->y() ; - - // find which node is selected - - for(uint32_t i=0;i<_node_coords.size();++i) - if( pow(_node_coords[i].x - x,2)+pow(_node_coords[i].y - y,2) < 10*10 ) - { - if(e->button() == Qt::LeftButton) - { - _current_selected_node = i ; - _dragging = true ; - updateGL() ; - emit nodeSelected(i) ; - return ; - } - - if(e->button() == Qt::RightButton) - { - _current_acted_node = i ; - emit customContextMenuRequested(QPoint(e->x(),e->y())) ; - return ; - } - } - - _dragging = false ; - _current_selected_node = -1 ; -} - -void NetworkViewer::calculateForces(const Network::NodeId& node_id,const double *map,int W,int H,float x,float y,float /*speedf*/,float& new_x, float& new_y) -{ -#ifdef A_FAIRE - if (mouseGrabberItem() == this) - { - new_x = x ; - new_y = y ; - return; - } -#endif - - // Sum up all forces pushing this item away - qreal xforce = 0; - qreal yforce = 0; - - float dei=0.0f ; - float dej=0.0f ; - - static float *e = NULL ; - static const int KS = 5 ; - - if(e == NULL) - { - e = new float[(2*KS+1)*(2*KS+1)] ; - - for(int i=-KS;i<=KS;++i) - for(int j=-KS;j<=KS;++j) - e[i+KS+(2*KS+1)*(j+KS)] = exp( -(i*i+j*j)/30.0 ) ; // can be precomputed - } - - for(int i=-KS;i<=KS;++i) - for(int j=-KS;j<=KS;++j) - { - int X = std::min(W-1,std::max(0,(int)rint(x/(float)width()*W))) ; - int Y = std::min(H-1,std::max(0,(int)rint(y/(float)height()*H))) ; - - float val = map[2*((i+X+W)%W + W*((j+Y+H)%H))] ; - - dei += i * e[i+KS+(2*KS+1)*(j+KS)] * val ; - dej += j * e[i+KS+(2*KS+1)*(j+KS)] * val ; - } - - xforce = REPULSION_FACTOR * dei/25.0; - yforce = REPULSION_FACTOR * dej/25.0; - - // Now subtract all forces pulling items together - // - const std::set& neighbs(_network.neighbors(node_id)) ; - double weight = neighbs.size() + 1 ; - - for(std::set::const_iterator it(neighbs.begin());it!=neighbs.end();++it) - { - NodeCoord pos; - double w2 ; // This factor makes the edge length depend on connectivity, so clusters of friends tend to stay in the - // same location. - // - - pos.x = _node_coords[*it].x - x ; //mapFromItem(edge->destNode(), 0, 0); - pos.y = _node_coords[*it].y - y ; //mapFromItem(edge->destNode(), 0, 0); - - w2 = sqrtf(std::min(neighbs.size(),_network.neighbors(*it).size())) ; - - float dist = sqrtf(pos.x*pos.x + pos.y*pos.y) ; - float val = dist - NODE_DISTANCE * w2 ; - - xforce += 0.01*pos.x * val / weight; - yforce += 0.01*pos.y * val / weight; - } - - xforce -= FRICTION_FACTOR * _node_speeds[node_id].x ; - yforce -= FRICTION_FACTOR * _node_speeds[node_id].y ; - - // This term drags nodes away from the sides. - // - if(x < 15) xforce += 100.0/(x+0.1) ; - if(y < 15) yforce += 100.0/(y+0.1) ; - if(x > width()-15) xforce -= 100.0/(width()-x+0.1) ; - if(y > height()-15) yforce -= 100.0/(height()-y+0.1) ; - - // now time filter: - - _node_speeds[node_id].x += xforce / MASS_FACTOR; - _node_speeds[node_id].y += yforce / MASS_FACTOR; - - if(_node_speeds[node_id].x > 10) _node_speeds[node_id].x = 10.0f ; - if(_node_speeds[node_id].y > 10) _node_speeds[node_id].y = 10.0f ; - if(_node_speeds[node_id].x <-10) _node_speeds[node_id].x =-10.0f ; - if(_node_speeds[node_id].y <-10) _node_speeds[node_id].y =-10.0f ; - - new_x = x + _node_speeds[node_id].x ; - new_y = y + _node_speeds[node_id].y ; - - new_x = std::min(std::max(new_x, 10.0f), width() - 10.0f); - new_y = std::min(std::max(new_y, 10.0f), height() - 10.0f); -} - -void NetworkViewer::contextMenu(QPoint p) -{ - std::cerr << "Context menu request at point " << p.x() << " " << p.y() << std::endl; - - QMenu contextMnu ;//= ui.msgText->createStandardContextMenu(matrix.map(point)); - - contextMnu.addAction(action_ClientForHash); - - if(_current_acted_node == -1) - return ; - - std::cerr << "acting on node " << _network.node(_current_acted_node).id() << std::endl; - - // make a list of hashes provided by all nodes except this one - std::set managed_hashes ; - std::set provided_hashes ; - - for(uint32_t i=0;i<_network.n_nodes();++i) - if(i != _current_acted_node) - { - managed_hashes.insert( _network.node(i).managedHashes().begin(), _network.node(i).managedHashes().end()) ; - provided_hashes.insert( _network.node(i).providedHashes().begin(), _network.node(i).providedHashes().end()) ; - } - - if(!managed_hashes.empty()) - { - QMenu *Mnu2 = contextMnu.addMenu("Provide hash") ; - - for(std::set::const_iterator it(managed_hashes.begin());it!=managed_hashes.end();++it) - { - QAction* provide_hash_action = new QAction(QString::fromStdString((*it).toStdString()), Mnu2); - connect(provide_hash_action, SIGNAL(triggered()), this, SLOT(actionProvideHash())); - Mnu2->addAction(provide_hash_action); - } - } - if(!provided_hashes.empty()) - { - QMenu *Mnu2 = contextMnu.addMenu("Client for hash") ; - - for(std::set::const_iterator it(provided_hashes.begin());it!=provided_hashes.end();++it) - { - QAction* manage_hash_action = new QAction(QString::fromStdString((*it).toStdString()), Mnu2); - connect(manage_hash_action, SIGNAL(triggered()), this, SLOT(actionClientForHash())); - Mnu2->addAction(manage_hash_action); - } - } - contextMnu.addSeparator() ; - - // GRouter stuff - - contextMnu.addAction(action_ProvideGRKey); - - std::set provided_keys ; - - for(uint32_t i=0;i<_network.n_nodes();++i) - if(i != _current_acted_node) - provided_keys.insert( _network.node(i).providedGRKeys().begin(), _network.node(i).providedGRKeys().end()) ; - - if(!provided_keys.empty()) - { - QMenu *Mnu2 = contextMnu.addMenu("Send message to Key") ; - - for(std::set::const_iterator it(provided_keys.begin());it!=provided_keys.end();++it) - { - QAction* send_message_action = new QAction(QString::fromStdString((*it).toStdString()), Mnu2); - connect(send_message_action, SIGNAL(triggered()), this, SLOT(actionSendToGRKey())); - Mnu2->addAction(send_message_action); - } - } - // Execute! - - contextMnu.exec(mapToGlobal(p)); -} - -void NetworkViewer::actionClientForHash() -{ - if(_current_acted_node < 0) - return ; - - RsFileHash hash ; - - if(qobject_cast(sender())->text().length() == 40) //data().toString().toStdString(); - { - hash = RsFileHash(qobject_cast(sender())->text().toStdString()) ; - - std::cerr << "Managing existing hash " << hash << std::endl; - } - else - { - std::cerr << "Managing random hash..." << std::endl; - - hash = RsFileHash::random() ; - } - - - std::cerr << " current node = " << _current_acted_node << std::endl ; - std::cerr << " adding random hash = " << hash << std::endl; - - _network.node(_current_acted_node).manageFileHash(hash) ; - - updateGL() ; -} - -void NetworkViewer::actionProvideHash() -{ - QString hash = qobject_cast(sender())->text() ;//data().toString().toStdString(); - - if(_current_acted_node < 0) - return ; - - std::cerr << "Providing hash " << hash.toStdString() << std::endl; - _network.node(_current_acted_node).provideFileHash(RsFileHash(hash.toStdString())) ; - - updateGL() ; -} - -void NetworkViewer::actionSendToGRKey() -{ - if(_current_acted_node < 0) - return ; - - GRouterKeyId key_id ; - - if(qobject_cast(sender())->text().length() == 32) //data().toString().toStdString(); - { - key_id = GRouterKeyId(qobject_cast(sender())->text().toStdString()) ; - - std::cerr << "Sending to existing key " << key_id << std::endl; - } - - std::cerr << " current node = " << _current_acted_node << std::endl ; - std::cerr << " sending message = " << key_id << std::endl; - - _network.node(_current_acted_node).sendToGRKey(key_id) ; - - updateGL() ; -} - -void NetworkViewer::actionProvideGRKey() -{ - if(_current_acted_node < 0) - return ; - - GRouterKeyId key_id = GRouterKeyId::random(); - QString key = QString::fromStdString(key_id.toStdString()) ; - - std::cerr << "Providing new grouter key " << key_id << std::endl; - _network.node(_current_acted_node).provideGRKey(key_id) ; - - updateGL() ; -} - - diff --git a/libretroshare/src/tests/network_simulator/gui/NetworkViewer.h b/libretroshare/src/tests/network_simulator/gui/NetworkViewer.h deleted file mode 100644 index f06e493e2..000000000 --- a/libretroshare/src/tests/network_simulator/gui/NetworkViewer.h +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -// The network simulator GUI has the following functionalities: -// -// 1 - show the network graph -// * the graph should spread in space automatically. We should use the code from the NetworkView for that. -// * each edge will be drawn with a color that displays used bandwidth along the edge, or TR sent to the edge, etc. -// * individual tunnels should be shown, in order to see what shape they have -// -// 2 - show info about each node. One needs a node widget that gets updated with whatever is to be read from the current node -// -// 3 - buttons to re-initiate a new network, or reset the network. -// -// 4 - buttons to inject information into the network: -// * shared files in some nodes. Should be handled by derivign the component that the turtle router accesses for local searches. -// * file requests in other nodes. Eazy: one just needs to ask the turtle router of the node to handle the hash. -// -// 5 - perturbate the network -// * change the load of each node, and the delay when forwarding requests. -// -#include "nscore/Network.h" - -class NetworkViewer: public QGLViewer -{ - Q_OBJECT - - public: - NetworkViewer(QWidget *parent,Network& network) ; - - virtual void draw() ; - virtual void keyPressEvent(QKeyEvent *) {} - virtual void mousePressEvent(QMouseEvent *) ; - virtual void mouseReleaseEvent(QMouseEvent *) ; - virtual void mouseMoveEvent(QMouseEvent *) ; - - const Network& network() const { return _network ; } - Network& network() { return _network ; } - - signals: - void nodeSelected(int) ; - - public slots: - void timerEvent(QTimerEvent *) ; - void contextMenu(QPoint) ; - void actionClientForHash() ; - void actionProvideHash() ; - void actionSendToGRKey() ; - void actionProvideGRKey() ; - - private: - void calculateForces(const Network::NodeId& node_id,const double *map,int W,int H,float x,float y,float /*speedf*/,float& new_x, float& new_y) ; - - typedef struct - { - float x ; - float y ; - } NodeCoord ; - - Network& _network ; - - std::vector _node_coords ; - std::vector _node_speeds ; - - static const float MASS_FACTOR = 10 ; - static const float FRICTION_FACTOR = 15.8 ; - static const float REPULSION_FACTOR = 8 ; - static const float NODE_DISTANCE = 30.0 ; - - int timerId ; - - int _current_selected_node ; - int _current_displayed_node ; - int _current_acted_node ; - bool _dragging ; - bool _nodes_need_recomputing ; - - QAction *action_SendToGRKey ; - QAction *action_ProvideGRKey ; - QAction *action_ClientForHash ; - QAction *action_ProvideHash ; -}; - diff --git a/libretroshare/src/tests/network_simulator/gui/RsAutoUpdatePage.cpp b/libretroshare/src/tests/network_simulator/gui/RsAutoUpdatePage.cpp deleted file mode 100644 index 9cb849e7f..000000000 --- a/libretroshare/src/tests/network_simulator/gui/RsAutoUpdatePage.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include "RsAutoUpdatePage.h" - -bool RsAutoUpdatePage::_locked = false ; - -RsAutoUpdatePage::RsAutoUpdatePage(int ms_update_period, QWidget *parent, Qt::WindowFlags flags) - : QWidget(parent, flags) -{ - _timer = new QTimer ; - _timer->setInterval(ms_update_period); - _timer->setSingleShot(true); - - QObject::connect(_timer,SIGNAL(timeout()),this,SLOT(timerUpdate())) ; - - _timer->start() ; -} - -RsAutoUpdatePage::~RsAutoUpdatePage() -{ - if(_timer != NULL) - delete _timer ; - - _timer = NULL ; -} - -void RsAutoUpdatePage::showEvent(QShowEvent */*event*/) -{ - //std::cout << "RsAutoUpdatePage::showEvent() In show event !!" << std::endl ; - if(!_locked) - updateDisplay(); -} - -void RsAutoUpdatePage::timerUpdate() -{ - // only update when the widget is visible. - // - if(_locked == false && isVisible()) { - updateDisplay(); - update() ; // Qt flush - } - - _timer->start() ; -} - -void RsAutoUpdatePage::lockAllEvents() { _locked = true ; } -void RsAutoUpdatePage::unlockAllEvents() { _locked = false ; } -bool RsAutoUpdatePage::eventsLocked() { return _locked ; } diff --git a/libretroshare/src/tests/network_simulator/gui/RsAutoUpdatePage.h b/libretroshare/src/tests/network_simulator/gui/RsAutoUpdatePage.h deleted file mode 100644 index ea1b0c8c8..000000000 --- a/libretroshare/src/tests/network_simulator/gui/RsAutoUpdatePage.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include - -// This class implement a basic RS functionality which is that widgets displayign info -// should update regularly. They also should update only when visible, to save CPU time. -// -// Using this class simply needs to derive your widget from RsAutoUpdateWidget -// and oveload the update() function with the actual code that updates the -// widget. -// -class QTimer ; - -class RsAutoUpdatePage: public QWidget -{ - Q_OBJECT - - public: - RsAutoUpdatePage(int ms_update_period = 1000, QWidget *parent = NULL, Qt::WindowFlags flags = 0) ; - virtual ~RsAutoUpdatePage() ; - - virtual void updateDisplay() {} - - static void lockAllEvents() ; - static void unlockAllEvents() ; - static bool eventsLocked() ; - - protected: - virtual void showEvent(QShowEvent *e) ; - - private slots: - void timerUpdate() ; - - private: - QTimer *_timer ; - - static bool _locked ; -}; - diff --git a/libretroshare/src/tests/network_simulator/gui/TurtleRouterStatistics.cpp b/libretroshare/src/tests/network_simulator/gui/TurtleRouterStatistics.cpp deleted file mode 100644 index b45ac9996..000000000 --- a/libretroshare/src/tests/network_simulator/gui/TurtleRouterStatistics.cpp +++ /dev/null @@ -1,318 +0,0 @@ -/**************************************************************** - * RetroShare is distributed under the following license: - * - * Copyright (C) 20011, RetroShare Team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - ****************************************************************/ - -#include -#include -#include - -#include -#include - -#include -#include -#include "TurtleRouterStatistics.h" - -static const int MAX_TUNNEL_REQUESTS_DISPLAY = 10 ; - -class TRHistogram -{ - public: - TRHistogram(const std::vector& info) :_infos(info) {} - - QColor colorScale(float f) - { - if(f == 0) - return QColor::fromHsv(0,0,192) ; - else - return QColor::fromHsv((int)((1.0-f)*280),200,255) ; - } - - virtual void draw(QPainter *painter,int& ox,int& oy,const QString& title) - { - static const int MaxTime = 61 ; - static const int MaxDepth = 8 ; - static const int cellx = 7 ; - static const int celly = 12 ; - - int save_ox = ox ; - painter->setPen(QColor::fromRgb(0,0,0)) ; - painter->drawText(2+ox,celly+oy,title) ; - oy+=2+2*celly ; - - if(_infos.empty()) - return ; - - ox += 10 ; - std::map > hits ; - std::map > depths ; - std::map >::iterator it ; - - int max_hits = 1; - int max_depth = 1; - - for(uint32_t i=0;i<_infos.size();++i) - { - std::vector& h(hits[_infos[i].source_peer_id]) ; - std::vector& g(depths[_infos[i].source_peer_id]) ; - - if(h.size() <= _infos[i].age) - h.resize(MaxTime,0) ; - - if(g.empty()) - g.resize(MaxDepth,0) ; - - if(_infos[i].age < h.size()) - { - h[_infos[i].age]++ ; - if(h[_infos[i].age] > max_hits) - max_hits = h[_infos[i].age] ; - } - if(_infos[i].depth < g.size()) - { - g[_infos[i].depth]++ ; - - if(g[_infos[i].depth] > max_depth) - max_depth = g[_infos[i].depth] ; - } - } - - int max_bi = std::max(max_hits,max_depth) ; - int p=0 ; - - for(it=depths.begin();it!=depths.end();++it,++p) - for(int i=0;ifillRect(ox+MaxTime*cellx+20+i*cellx,oy+p*celly,cellx,celly,colorScale(it->second[i]/(float)max_bi)) ; - - painter->setPen(QColor::fromRgb(0,0,0)) ; - painter->drawRect(ox+MaxTime*cellx+20,oy,MaxDepth*cellx,p*celly) ; - - for(int i=0;idrawText(ox+i*cellx,oy+(p+1)*celly+4,QString::number(i)) ; - - p=0 ; - int great_total = 0 ; - - for(it=hits.begin();it!=hits.end();++it,++p) - { - int total = 0 ; - - for(int i=0;ifillRect(ox+i*cellx,oy+p*celly,cellx,celly,colorScale(it->second[i]/(float)max_bi)) ; - total += it->second[i] ; - } - - painter->setPen(QColor::fromRgb(0,0,0)) ; - painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx,oy+(p+1)*celly,TurtleRouterStatistics::getPeerName(it->first)) ; - painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx+120,oy+(p+1)*celly,"("+QString::number(total)+")") ; - great_total += total ; - } - - painter->drawRect(ox,oy,MaxTime*cellx,p*celly) ; - - for(int i=0;idrawText(ox+i*cellx,oy+(p+1)*celly+4,QString::number(i)) ; - for(int i=0;idrawText(ox+MaxTime*cellx+20+i*cellx,oy+(p+1)*celly+4,QString::number(i)) ; - painter->setPen(QColor::fromRgb(255,130,80)) ; - painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx+120,oy+(p+1)*celly+4,"("+QString::number(great_total)+")"); - - oy += (p+1)*celly+6 ; - - painter->setPen(QColor::fromRgb(0,0,0)) ; - painter->drawText(ox,oy+celly,"("+QApplication::translate("TurtleRouterStatistics", "Age in seconds")+")"); - painter->drawText(ox+MaxTime*cellx+20,oy+celly,"("+QApplication::translate("TurtleRouterStatistics", "Depth")+")"); - - painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx+120,oy+celly,"("+QApplication::translate("TurtleRouterStatistics", "total")+")"); - - oy += 3*celly ; - - // now, draw a scale - - int last_hts = -1 ; - int cellid = 0 ; - - for(int i=0;i<=10;++i) - { - int hts = (int)(max_bi*i/10.0) ; - - if(hts > last_hts) - { - painter->fillRect(ox+cellid*(cellx+22),oy,cellx,celly,colorScale(i/10.0f)) ; - painter->setPen(QColor::fromRgb(0,0,0)) ; - painter->drawRect(ox+cellid*(cellx+22),oy,cellx,celly) ; - painter->drawText(ox+cellid*(cellx+22)+cellx+4,oy+celly,QString::number(hts)) ; - last_hts = hts ; - ++cellid ; - } - } - - oy += celly*2 ; - - ox = save_ox ; - } - - private: - const std::vector& _infos ; -}; - -TurtleRouterStatistics::TurtleRouterStatistics(QWidget *parent) - : RsAutoUpdatePage(2000,parent) -{ - setupUi(this) ; - - _turtle = NULL ; - - _tunnel_statistics_F->setWidget( _tst_CW = new TurtleRouterStatisticsWidget() ) ; - _tunnel_statistics_F->setWidgetResizable(true); - _tunnel_statistics_F->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - _tunnel_statistics_F->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - _tunnel_statistics_F->viewport()->setBackgroundRole(QPalette::NoRole); - _tunnel_statistics_F->setFrameStyle(QFrame::NoFrame); - _tunnel_statistics_F->setFocusPolicy(Qt::NoFocus); -} - -TurtleRouterStatistics::~TurtleRouterStatistics() -{ -} - -void TurtleRouterStatistics::updateDisplay() -{ - if(_turtle == NULL) - return ; - - std::vector > hashes_info ; - std::vector > tunnels_info ; - std::vector search_reqs_info ; - std::vector tunnel_reqs_info ; - - _turtle->getInfo(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; - - //updateTunnelRequests(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; - _tst_CW->updateTunnelStatistics(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info,_turtle) ; - _tst_CW->update(); -} - -QString TurtleRouterStatistics::getPeerName(const RsPeerId& peer_id) -{ - static std::map names ; - - std::map::const_iterator it = names.find(peer_id) ; - - if( it != names.end()) - return it->second ; - else - return (names[peer_id] = QString::fromStdString(peer_id.toStdString())) ; -} - -TurtleRouterStatisticsWidget::TurtleRouterStatisticsWidget(QWidget *parent) - : QWidget(parent) -{ - maxWidth = 200 ; - maxHeight = 0 ; -} - -void TurtleRouterStatisticsWidget::updateTunnelStatistics(const std::vector >& /*hashes_info*/, - const std::vector >& /*tunnels_info*/, - const std::vector& search_reqs_info, - const std::vector& tunnel_reqs_info, - const RsTurtle *turtle) - -{ - static const int cellx = 6 ; - static const int celly = 10+4 ; - - QPixmap tmppixmap(maxWidth, maxHeight); - tmppixmap.fill(this, 0, 0); - setFixedHeight(maxHeight); - - QPainter painter(&tmppixmap); - painter.initFrom(this); - - maxHeight = 500 ; - - // std::cerr << "Drawing into pixmap of size " << maxWidth << "x" << maxHeight << std::endl; - // draw... - int ox=5,oy=5 ; - - TRHistogram(search_reqs_info).draw(&painter,ox,oy,tr("Search requests repartition") + ":") ; - - painter.setPen(QColor::fromRgb(70,70,70)) ; - painter.drawLine(0,oy,maxWidth,oy) ; - oy += celly ; - - TRHistogram(tunnel_reqs_info).draw(&painter,ox,oy,tr("Tunnel requests repartition") + ":") ; - - // now give information about turtle traffic. - // - TurtleTrafficStatisticsInfo info ; - turtle->getTrafficStatistics(info) ; - - painter.setPen(QColor::fromRgb(70,70,70)) ; - painter.drawLine(0,oy,maxWidth,oy) ; - oy += celly ; - - painter.drawText(ox,oy+celly,tr("Turtle router traffic")+":") ; oy += celly*2 ; - painter.drawText(ox+2*cellx,oy+celly,tr("Tunnel requests Up")+"\t: " + speedString(info.tr_up_Bps) ) ; oy += celly ; - painter.drawText(ox+2*cellx,oy+celly,tr("Tunnel requests Dn")+"\t: " + speedString(info.tr_dn_Bps) ) ; oy += celly ; - painter.drawText(ox+2*cellx,oy+celly,tr("Incoming file data")+"\t: " + speedString(info.data_dn_Bps) ) ; oy += celly ; - painter.drawText(ox+2*cellx,oy+celly,tr("Outgoing file data")+"\t: " + speedString(info.data_up_Bps) ) ; oy += celly ; - painter.drawText(ox+2*cellx,oy+celly,tr("Forwarded data ")+"\t: " + speedString(info.unknown_updn_Bps) ) ; oy += celly ; - - QString prob_string ; - - for(uint i=0;i -#include -#include "ui_TurtleRouterStatistics.h" -#include "RsAutoUpdatePage.h" - -class TurtleRouterStatisticsWidget ; - -class TurtleRouterStatistics: public RsAutoUpdatePage, public Ui::TurtleRouterStatistics -{ - Q_OBJECT - - public: - TurtleRouterStatistics(QWidget *parent = NULL) ; - ~TurtleRouterStatistics(); - - // Cache for peer names. - static QString getPeerName(const RsPeerId& peer_id) ; - - void setTurtleRouter(const RsTurtle *turtle) { _turtle = turtle ; } - - virtual void updateDisplay() ; - private: - - TurtleRouterStatisticsWidget *_tst_CW ; - const RsTurtle *_turtle ; -} ; - -class TurtleRouterStatisticsWidget: public QWidget -{ - Q_OBJECT - - public: - TurtleRouterStatisticsWidget(QWidget *parent = NULL) ; - - virtual void paintEvent(QPaintEvent *event) ; - virtual void resizeEvent(QResizeEvent *event); - - void updateTunnelStatistics( const std::vector > >&, - const std::vector > >&, - const std::vector&, - const std::vector&, - const RsTurtle *turtle) ; - - private: - static QString speedString(float f) ; - - QPixmap pixmap ; - int maxWidth,maxHeight ; -}; - diff --git a/libretroshare/src/tests/network_simulator/gui/TurtleRouterStatistics.ui b/libretroshare/src/tests/network_simulator/gui/TurtleRouterStatistics.ui deleted file mode 100644 index 365d3f362..000000000 --- a/libretroshare/src/tests/network_simulator/gui/TurtleRouterStatistics.ui +++ /dev/null @@ -1,55 +0,0 @@ - - - TurtleRouterStatistics - - - - 0 - 0 - 611 - 408 - - - - Router Statistics - - - - :/images/rstray3.png:/images/rstray3.png - - - - - - Qt::Vertical - - - - QFrame::NoFrame - - - Qt::ScrollBarAlwaysOff - - - true - - - - - 0 - 0 - 593 - 390 - - - - - - - - - - - - - diff --git a/libretroshare/src/tests/network_simulator/gui/gui.pro b/libretroshare/src/tests/network_simulator/gui/gui.pro deleted file mode 100644 index 8cb01b4a2..000000000 --- a/libretroshare/src/tests/network_simulator/gui/gui.pro +++ /dev/null @@ -1,25 +0,0 @@ -TEMPLATE = app - -CONFIG *= qt qglviewer uic -QT *= xml opengl - -INCLUDEPATH *= ../../.. .. - -TARGET = NetworkSim -DESTDIR = ../bin - -PRE_TARGETDEPS = ../nscore/nscore.pro - -SOURCES = main.cpp NetworkViewer.cpp NetworkSimulatorGUI.cpp \ - TurtleRouterStatistics.cpp RsAutoUpdatePage.cpp GlobalRouterStatistics.cpp - -HEADERS = NetworkViewer.h NetworkSimulatorGUI.h \ - TurtleRouterStatistics.h RsAutoUpdatePage.h GlobalRouterStatistics.h - -FORMS = NetworkSimulatorGUI.ui TurtleRouterStatistics.ui GlobalRouterStatistics.ui - -LIBS *= ../../../lib/libretroshare.a \ - ../../../../../libbitdht/src/lib/libbitdht.a \ - ../../../../../openpgpsdk/src/lib/libops.a \ - ../lib/libnscore.a \ - -lsqlcipher -lgnome-keyring -lupnp -lssl -lcrypto -lbz2 -lixml diff --git a/libretroshare/src/tests/network_simulator/gui/main.cpp b/libretroshare/src/tests/network_simulator/gui/main.cpp deleted file mode 100644 index f6c1e1c22..000000000 --- a/libretroshare/src/tests/network_simulator/gui/main.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include - -#include "nscore/Network.h" -#include "nscore/MonitoredRsPeers.h" - -#include - -#include "NetworkSimulatorGUI.h" - -int main(int argc, char *argv[]) -{ - feenableexcept(FE_INVALID) ; - feenableexcept(FE_DIVBYZERO) ; - -#ifndef DEBUG - try - { -#endif - argstream as(argc,argv) ; - bool show_gui = false; - int nb_nodes = 20 ; - float connexion_probability = 0.2 ; - - as >> option('i',"gui",show_gui,"show gui (vs. do the pipeline automatically)") - >> parameter('n',"nodes",nb_nodes,"number of nodes in the network",false) - >> parameter('p',"connexion probability",connexion_probability,"probability that two nodes are connected (exponential law)",false) - >> help() ; - - as.defaultErrorHandling() ; - - // 2 - call the full pipeline - - Network network ; - - network.initRandom(nb_nodes,connexion_probability) ; - - rsPeers = new MonitoredRsPeers(network) ; - - if(show_gui) - { - QApplication app(argc,argv) ; - - NetworkSimulatorGUI pgui(network); - pgui.show() ; - - return app.exec() ; - } - - return 0 ; -#ifndef DEBUG - } - catch(std::exception& e) - { - std::cerr << "Unhandled exception: " << e.what() << std::endl; - return 1 ; - } -#endif -} - diff --git a/libretroshare/src/tests/network_simulator/network_simulator.pro b/libretroshare/src/tests/network_simulator/network_simulator.pro deleted file mode 100644 index 8564c70fe..000000000 --- a/libretroshare/src/tests/network_simulator/network_simulator.pro +++ /dev/null @@ -1,2 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = nscore gui diff --git a/libretroshare/src/tests/network_simulator/nscore/FakeComponents.h b/libretroshare/src/tests/network_simulator/nscore/FakeComponents.h deleted file mode 100644 index b54ed8681..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/FakeComponents.h +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once - -#include -#include -#include - -class FakeLinkMgr: public p3LinkMgrIMPL -{ - public: - FakeLinkMgr(const RsPeerId& own_id,const std::list& friends) - : p3LinkMgrIMPL(NULL,NULL),_own_id(own_id),_friends(friends) - { - } - - virtual const RsPeerId& getOwnId() { return _own_id ; } - virtual void getOnlineList(std::list& lst) { lst = _friends ; } - virtual uint32_t getLinkType(const RsPeerId&) { return RS_NET_CONN_TCP_ALL | RS_NET_CONN_SPEED_NORMAL; } - - virtual bool getPeerName(const RsPeerId &ssl_id, std::string &name) { name = ssl_id.toStdString() ; return true ;} - - private: - RsPeerId _own_id ; - std::list _friends ; -}; - -class FakePublisher: public pqiPublisher -{ - public: - virtual bool sendItem(RsRawItem *item) - { - _item_queue.push_back(item) ; - return true ; - } - - RsRawItem *outgoing() - { - if(_item_queue.empty()) - return NULL ; - - RsRawItem *item = _item_queue.front() ; - _item_queue.pop_front() ; - return item ; - } - - private: - std::list _item_queue ; -}; - -class FakePeerMgr: public p3PeerMgrIMPL -{ - public: - FakePeerMgr(const RsPeerId& own,const std::list& ids) - : p3PeerMgrIMPL(own,RsPgpId(),"no name","location name") - { - for(std::list::const_iterator it(ids.begin());it!=ids.end();++it) - _ids.insert(*it) ; - } - - virtual bool idFriend(const RsPeerId& ssl_id) { return _ids.find(ssl_id) != _ids.end() ; } - - virtual ServicePermissionFlags servicePermissionFlags(const RsPeerId& ssl_id) - { - return ~ServicePermissionFlags(0) ; - } - std::set _ids ; -}; - -class FakeServiceControl: public p3ServiceControl -{ - public: - FakeServiceControl(p3LinkMgr *lm) - : p3ServiceControl(lm),mLink(lm) - { - } - - virtual void getPeersConnected(const uint32_t serviceId, std::set &peerSet) - { - std::list ids ; - mLink->getOnlineList(ids) ; - - for(std::list::const_iterator it(ids.begin());it!=ids.end();++it) - peerSet.insert(*it) ; - } - - virtual bool checkFilter(uint32_t,const RsPeerId& id) - { - return true ; - } - p3LinkMgr *mLink; -}; - diff --git a/libretroshare/src/tests/network_simulator/nscore/MainLoop.cpp b/libretroshare/src/tests/network_simulator/nscore/MainLoop.cpp deleted file mode 100644 index 22e89127e..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MainLoop.cpp +++ /dev/null @@ -1,24 +0,0 @@ - -void NetworkLoop() -{ - while(true) - { - std::cerr<< "network loop: tick()" << std::endl; - - // Get items for each components and send them to their destination. - // - for(int i=0;in_nodes();++i) - { - RsRawItem *item ; - - while(item = network->node(i).outgoing()) - { - PeerNode& node = network->node_by_id(item->peerId()) - item->peerId(network->node(i)->id()) ; - - node.received(item) ; - } - } - usleep(500000) ; - } -} diff --git a/libretroshare/src/tests/network_simulator/nscore/MonitoredGRouterClient.cpp b/libretroshare/src/tests/network_simulator/nscore/MonitoredGRouterClient.cpp deleted file mode 100644 index 9371bbd29..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MonitoredGRouterClient.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "MonitoredGRouterClient.h" - -const uint32_t MonitoredGRouterClient::GROUTER_CLIENT_SERVICE_ID_00 = 0x0111 ; - -void MonitoredGRouterClient::receiveGRouterData(const GRouterKeyId& destination_key,const RsGRouterGenericDataItem *item) -{ - std::cerr << "received one global grouter item for key " << destination_key << std::endl; -} - -void MonitoredGRouterClient::provideKey(const GRouterKeyId& key_id) -{ - _grouter->registerKey(key_id,GROUTER_CLIENT_SERVICE_ID_00,"test grouter address") ; - - std::cerr << "Registered new key " << key_id << " for service " << std::hex << GROUTER_CLIENT_SERVICE_ID_00 << std::dec << std::endl; -} - -void MonitoredGRouterClient::sendMessage(const GRouterKeyId& destination_key_id) const -{ - RsGRouterGenericDataItem *item = new RsGRouterGenericDataItem ; - item->data_size = 1000 + (RSRandom::random_u32()%1000) ; - item->data_bytes = (unsigned char *)malloc(item->data_size) ; - - RSRandom::random_bytes(item->data_bytes,item->data_size) ; - GRouterMsgPropagationId propagation_id ; - - _grouter->sendData(destination_key_id,GROUTER_CLIENT_SERVICE_ID_00,item,propagation_id) ; -} diff --git a/libretroshare/src/tests/network_simulator/nscore/MonitoredGRouterClient.h b/libretroshare/src/tests/network_simulator/nscore/MonitoredGRouterClient.h deleted file mode 100644 index a778c8c37..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MonitoredGRouterClient.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include - -class MonitoredGRouterClient: public GRouterClientService -{ - public: - static const uint32_t GROUTER_CLIENT_SERVICE_ID_00 ; - - // Derived from grouterclientservice.h - // - virtual void connectToGlobalRouter(p3GRouter *p) { _grouter = p ; p->registerClientService(GROUTER_CLIENT_SERVICE_ID_00,this) ; } - virtual void receiveGRouterData(const GRouterKeyId& destination_key,const RsGRouterGenericDataItem *item); - - // Own functionality - // - void sendMessage(const GRouterKeyId& destination_key) const ; - void provideKey(const GRouterKeyId& key) ; - - private: - p3GRouter *_grouter ; -}; - diff --git a/libretroshare/src/tests/network_simulator/nscore/MonitoredRsPeers.cpp b/libretroshare/src/tests/network_simulator/nscore/MonitoredRsPeers.cpp deleted file mode 100644 index aa952ea68..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MonitoredRsPeers.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include "MonitoredRsPeers.h" - -MonitoredRsPeers::MonitoredRsPeers(const Network& net) - : p3Peers(NULL,NULL,NULL),_network(net) -{ -} - -bool MonitoredRsPeers::getPeerDetails(const std::string& str,RsPeerDetails& details) -{ - std::cerr << __PRETTY_FUNCTION__ << " called" << std::endl; -} diff --git a/libretroshare/src/tests/network_simulator/nscore/MonitoredRsPeers.h b/libretroshare/src/tests/network_simulator/nscore/MonitoredRsPeers.h deleted file mode 100644 index 4706cc316..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MonitoredRsPeers.h +++ /dev/null @@ -1,14 +0,0 @@ -#include - -class Network ; - -class MonitoredRsPeers: public p3Peers -{ - public: - MonitoredRsPeers(const Network& net) ; - - virtual bool getPeerDetails(const std::string& peer_id,RsPeerDetails& details) ; - - private: - const Network& _network ; -}; diff --git a/libretroshare/src/tests/network_simulator/nscore/MonitoredTurtleClient.cpp b/libretroshare/src/tests/network_simulator/nscore/MonitoredTurtleClient.cpp deleted file mode 100644 index 3ed946ac3..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MonitoredTurtleClient.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "MonitoredTurtleClient.h" - -bool MonitoredTurtleClient::handleTunnelRequest(const TurtleFileHash& hash,const RsPeerId& peer_id) -{ - std::map::const_iterator it( _local_files.find(hash) ) ; - - return (it != _local_files.end() ) ; -} - -void MonitoredTurtleClient::provideFileHash(const RsFileHash& hash) -{ - FileInfo& info( _local_files[hash] ) ; - - info.fname = "File 1" ; - info.size = 100000 ; - info.hash = hash ; -} - diff --git a/libretroshare/src/tests/network_simulator/nscore/MonitoredTurtleClient.h b/libretroshare/src/tests/network_simulator/nscore/MonitoredTurtleClient.h deleted file mode 100644 index bb03af705..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MonitoredTurtleClient.h +++ /dev/null @@ -1,17 +0,0 @@ -#include - -class MonitoredTurtleClient: public RsTurtleClientService -{ -public: - virtual void addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) {} - virtual void removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) {} - virtual void connectToTurtleRouter(p3turtle*p) { p->registerTunnelService(this) ; } - - bool handleTunnelRequest(const TurtleFileHash& hash,const RsPeerId& peer_id); - void provideFileHash(const RsFileHash& hash); - void requestFileHash(const RsFileHash& hash) ; - -private: - std::map _local_files ; -}; - diff --git a/libretroshare/src/tests/network_simulator/nscore/Network.cpp b/libretroshare/src/tests/network_simulator/nscore/Network.cpp deleted file mode 100644 index a24d4a40c..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/Network.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include "Network.h" -#include "MonitoredTurtleClient.h" -#include "FakeComponents.h" - -bool Network::initRandom(uint32_t nb_nodes,float connexion_probability) -{ - _nodes.clear() ; - _neighbors.clear() ; - - std::vector ids ; - - _neighbors.resize(nb_nodes) ; - ids.resize(nb_nodes) ; - - for(uint32_t i=0;i friends ; - for(std::set::const_iterator it(_neighbors[i].begin());it!=_neighbors[i].end();++it) - friends.push_back( ids[*it] ) ; - - _nodes.push_back( new PeerNode( ids[i], friends )); - } - return true ; -} - -void Network::tick() -{ - //std::cerr<< "network loop: tick()" << std::endl; - - // Tick all nodes. - - for(uint32_t i=0;iPeerId() << " to " << Network::node(i).id() << std::endl; - - PeerNode& node = node_by_id(item->PeerId()) ; - item->PeerId(Network::node(i).id()) ; - - node.incoming(item) ; - } - } - } - catch(...) - { - } -} - -PeerNode& Network::node_by_id(const RsPeerId& id) -{ - std::map::const_iterator it = _node_ids.find(id) ; - - if(it == _node_ids.end()) - throw std::runtime_error("Error. Bad id passed to node_by_id ("+id.toStdString()+")") ; - - return node(it->second) ; -} - diff --git a/libretroshare/src/tests/network_simulator/nscore/Network.h b/libretroshare/src/tests/network_simulator/nscore/Network.h deleted file mode 100644 index adecc5665..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/Network.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include "PeerNode.h" - -template class Graph -{ - public: - typedef uint32_t NodeId ; - - void symmetric_connect(uint32_t n1,uint32_t n2) ; - const std::set& neighbors(const NodeId& n) const { return _neighbors[n] ; } - - // number of nodes. - // - uint32_t n_nodes() const { return _nodes.size() ;} - const NODE_TYPE& node(int i) const { return *_nodes[i] ; } - NODE_TYPE& node(int i) { return *_nodes[i] ; } - - protected: - - std::vector _nodes ; - std::vector > _neighbors ; -}; - -class Network: public Graph -{ - public: - // inits the graph as random. Returns true if connected, false otherwise. - // - bool initRandom(uint32_t n_nodes, float connexion_probability) ; - - // ticks all services of all nodes. - // - void tick() ; - - PeerNode& node_by_id(const RsPeerId& node_id) ; - - private: - std::map _node_ids ; -}; - diff --git a/libretroshare/src/tests/network_simulator/nscore/PeerNode.cpp b/libretroshare/src/tests/network_simulator/nscore/PeerNode.cpp deleted file mode 100644 index 569a1347c..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/PeerNode.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "PeerNode.h" -#include "FakeComponents.h" -#include "MonitoredTurtleClient.h" -#include "MonitoredGRouterClient.h" - -PeerNode::PeerNode(const RsPeerId& id,const std::list& friends) - : _id(id) -{ - // add a service server. - - p3LinkMgr *link_mgr = new FakeLinkMgr(id, friends) ; - p3PeerMgr *peer_mgr = new FakePeerMgr(id, friends) ; - - _publisher = new FakePublisher ; - p3ServiceControl *ctrl = new FakeServiceControl(link_mgr) ; - - _service_server = new p3ServiceServer(_publisher,ctrl); - - RsServicePermissions perms; - perms.mDefaultAllowed = true ; - perms.mServiceId = RS_SERVICE_TYPE_TURTLE ; - - ctrl->updateServicePermissions(RS_SERVICE_TYPE_TURTLE,perms) ; - - perms.mDefaultAllowed = true ; - perms.mServiceId = RS_SERVICE_TYPE_GROUTER ; - - ctrl->updateServicePermissions(RS_SERVICE_TYPE_GROUTER,perms) ; - - // Turtle business - - _service_server->addService(_turtle = new p3turtle(ctrl,link_mgr),true) ; - _turtle_client = new MonitoredTurtleClient ; - _turtle_client->connectToTurtleRouter(_turtle) ; - - // global router business. - // - - _service_server->addService(_grouter = new p3GRouter(ctrl,link_mgr),true) ; - _grouter_client = new MonitoredGRouterClient ; - _grouter_client->connectToGlobalRouter(_grouter) ; -} - -PeerNode::~PeerNode() -{ - delete _service_server ; -} - -void PeerNode::tick() -{ - //std::cerr << " ticking peer node " << _id << std::endl; - _service_server->tick() ; -} - -void PeerNode::incoming(RsRawItem *item) -{ - _service_server->recvItem(item) ; -} -RsRawItem *PeerNode::outgoing() -{ - return dynamic_cast(_publisher)->outgoing() ; -} - -void PeerNode::provideFileHash(const RsFileHash& hash) -{ - _provided_hashes.insert(hash) ; - _turtle_client->provideFileHash(hash) ; -} - -void PeerNode::manageFileHash(const RsFileHash& hash) -{ - _managed_hashes.insert(hash) ; - _turtle->monitorTunnels(hash,_turtle_client, false) ; -} -void PeerNode::sendToGRKey(const GRouterKeyId& key_id) -{ - _grouter_client->sendMessage(key_id) ; -} -void PeerNode::provideGRKey(const GRouterKeyId& key_id) -{ - _grouter_client->provideKey(key_id) ; - _provided_keys.insert(key_id); -} -void PeerNode::getTrafficInfo(NodeTrafficInfo& info) -{ - std::vector > hashes_info ; - std::vector > tunnels_info ; - std::vector search_reqs_info ; - std::vector tunnel_reqs_info ; - - _turtle->getInfo(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; - - for(uint32_t i=0;i -#include -#include - -class MonitoredTurtleClient ; -class MonitoredGRouterClient ; -class RsTurtle ; -class p3turtle ; -class p3GRouter ; -class pqiPublisher ; -class RsRawItem ; -class p3ServiceServer ; - -class PeerNode -{ - public: - struct NodeTrafficInfo - { - std::map local_src ; // peer id., tunnel id - std::map local_dst ; - }; - - PeerNode(const RsPeerId& id,const std::list& friends) ; - ~PeerNode() ; - - RsRawItem *outgoing() ; - void incoming(RsRawItem *) ; - - const RsPeerId& id() const { return _id ;} - - void tick() ; - - // Turtle-related methods - // - const RsTurtle *turtle_service() const { return _turtle ; } - p3GRouter *global_router_service() const { return _grouter ; } - - void manageFileHash(const RsFileHash& hash) ; - void provideFileHash(const RsFileHash& hash) ; - - const std::set& providedHashes() const { return _provided_hashes; } - const std::set& managedHashes() const { return _managed_hashes; } - - void getTrafficInfo(NodeTrafficInfo& trinfo) ; // - - // GRouter-related methods - // - void provideGRKey(const GRouterKeyId& key_id) ; - void sendToGRKey(const GRouterKeyId& key_id) ; - - const std::set& providedGRKeys() const { return _provided_keys; } - - private: - p3ServiceServer *_service_server ; - pqiPublisher *_publisher ; - RsPeerId _id ; - - // turtle stuff - // - p3turtle *_turtle ; - MonitoredTurtleClient *_turtle_client ; - - // grouter stuff - // - p3GRouter *_grouter ; - MonitoredGRouterClient *_grouter_client ; - - std::set _provided_hashes ; - std::set _managed_hashes ; - std::set _provided_keys ; -}; - diff --git a/libretroshare/src/tests/network_simulator/nscore/nscore.pro b/libretroshare/src/tests/network_simulator/nscore/nscore.pro deleted file mode 100644 index 5a3989a15..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/nscore.pro +++ /dev/null @@ -1,20 +0,0 @@ -TEMPLATE = lib -CONFIG *= staticlib - -INCLUDEPATH *= ../../.. .. - -TARGET = nscore - -SOURCES = Network.cpp \ - PeerNode.cpp \ - MonitoredRsPeers.cpp \ - MonitoredTurtleClient.cpp \ - MonitoredGRouterClient.cpp - -HEADERS = Network.h \ - PeerNode.h \ - MonitoredRsPeers.h \ - MonitoredTurtleClient.h \ - MonitoredGRouterClient.h - -DESTDIR = ../lib diff --git a/libretroshare/src/tests/perform_all_auto_tests.sh b/libretroshare/src/tests/perform_all_auto_tests.sh deleted file mode 100755 index 648bf63c5..000000000 --- a/libretroshare/src/tests/perform_all_auto_tests.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# This is the main script for performing all tests automatically. -# - in order to add new directories, just list them in the $subdirs variable below - -echo "****************************************" -echo "*** RetroShare automatic test suite. ***" -echo "****************************************" -echo "Performing all tests on subdirs." -echo "(Some tests take a few minutes. Be patient) " -echo -echo - -subdirs="util serialiser dbase upnp general pgp tcponudp" - -for dir in $subdirs; do - echo Tests for directory: $dir - cd $dir - ./perform_auto_tests.sh - cd .. -done - diff --git a/libretroshare/src/tests/pgp/test_certificate.cc b/libretroshare/src/tests/pgp/test_certificate.cc deleted file mode 100644 index 6659ea86a..000000000 --- a/libretroshare/src/tests/pgp/test_certificate.cc +++ /dev/null @@ -1,137 +0,0 @@ -#include -#include - -#include -#include -//#include -#include -#include -#include - -INITTEST() ; - -static std::string pgp_pwd_cb(void * /*hook*/, const char *uid_hint, const char * /*passphrase_info*/, int prev_was_bad) -{ -#define GPG_DEBUG2 -#ifdef GPG_DEBUG2 - fprintf(stderr, "pgp_pwd_callback() called.\n"); -#endif - std::string password; - - std::cerr << "SHould not be called!" << std::endl; - return password ; -} - -int main(int argc,char *argv[]) -{ - try - { - argstream as(argc,argv) ; - std::string keyfile ; - bool clean_cert = false ; - - as >> parameter('i',"input",keyfile,"input certificate file (old or new formats)",true) - >> option('c',"clean",clean_cert,"clean cert before parsing") - >> help() ; - - as.defaultErrorHandling() ; - - FILE *f = fopen(keyfile.c_str(),"rb") ; - - CHECK(f != NULL) ; - - std::string res ; - char c ; - - while( (c = fgetc(f)) != EOF) - res += c ; - - fclose(f) ; - - std::cerr << "Read this string from the file:" << std::endl; - std::cerr << "==========================================" << std::endl; - std::cerr << res << std::endl; - std::cerr << "==========================================" << std::endl; - - if(clean_cert) - { - std::string res2 ; - int err ; - - //res2 = cleanUpCertificate(res,err) ; - - //if(res2 == "") - // std::cerr << "Error while cleaning: " << err << std::endl; - //else - // res = res2 ; - - std::cerr << "Certificate after cleaning:" << std::endl; - std::cerr << "==========================================" << std::endl; - std::cerr << res << std::endl; - std::cerr << "==========================================" << std::endl; - } - std::cerr << "Parsing..." << std::endl; - - RsCertificate cert(res) ; - - std::cerr << "Output from certificate:" << std::endl; - - std::cerr << cert.toStdString_oldFormat() << std::endl ; - - std::cerr << "Output from certificate (new format):" << std::endl; - std::cerr << cert.toStdString() << std::endl ; - - std::string key_id ; - std::string name ; - std::list signers ; - - PGPHandler::setPassphraseCallback(pgp_pwd_cb) ; - PGPHandler handler("toto1","toto2","toto3","toto4") ; - handler.getGPGDetailsFromBinaryBlock(cert.pgp_key(),cert.pgp_key_size(),key_id,name,signers) ; - - CHECK(key_id == "660FB771727CE286") ; - CHECK(name == "Cyril-test (generated by Retroshare) ") ; - - std::cerr << "Details loaded from certificate:" << std::endl; - std::cerr << "PGP id\t: " << key_id << std::endl; - std::cerr << "Key name\t: " << name << std::endl; - std::cerr << "Signers\t:" << std::endl; - - bool found = false ; - - for(std::list::const_iterator it(signers.begin());it!=signers.end();++it) - { - std::cerr << " " << *it << std::endl; - - if(*it == key_id) - found = true ; - } - CHECK(found) ; - - // try to load the certificate. - - std::cerr << "Checking that the certificate is imported correctly" << std::endl; - - std::string error_string ; - PGPIdType found_id ; - - bool result = handler.LoadCertificateFromString(res,found_id,error_string) ; - - if(!result) - std::cerr << "Certificate error: " << error_string << std::endl; - else - std::cerr << "Certificate loaded correctly. Id = " << found_id.toStdString() << std::endl; - - CHECK(result) ; - - FINALREPORT("Test certificate parsing") ; - - return TESTRESULT(); - } - catch(std::exception& e) - { - std::cerr << "Exception never handled: " << e.what() << std::endl; - return 1 ; - } -} - diff --git a/libretroshare/src/tests/pgp/test_certificate.newformat.rsc b/libretroshare/src/tests/pgp/test_certificate.newformat.rsc deleted file mode 100644 index 9bcd0273b..000000000 --- a/libretroshare/src/tests/pgp/test_certificate.newformat.rsc +++ /dev/null @@ -1,15 +0,0 @@ -Af8AAAKHmQENBEyoe/MBCAC9rKm/ehp9Iv1XrOiKIyj1X5nJzQ660+OhmQf4lbJv -krcnvdrdcmlfZQfupWMXHo7A3+27lOpfTvA1xpO8Gze0bRbLsbpx2dARjLUzXJAI -FNCYzH5xlIixxOwgX3tinKfoP3WvZv+nYBac/HeAPUW8BVqx6Y6V/gM3c71XNf9u -hPgArN0jvLOeqAJY+lACJZYlAIw6Jt2FzarC+orWndkvrsgrWmdxkorfZKBfdNwd -f1YYrpUmGaf51x4DkrMWpfHxS8b6cgOmSN3LeAC8LCm5oEXPfNgaRehN9LKrSmcp -cPS2jvDipgGBx+nL7gytCREMJkJoxppXQpVt1whaFDJVABEBAAG0OkN5cmlsLXRl -c3QgKGdlbmVyYXRlZCBieSBSZXRyb3NoYXJlKSA8Y3lyaWwuc29sZXJAaW1hZy5m -cj6JATgEEwECACIFAkyoe/MCGy8GCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJ -EGYPt3FyfOKG+h0H/A+vvryYmGcGFl82D4M0mAPAlbjZFkGCB8qJJSFuor55GJ3V -8pBb4UK7jnLhQhqsdXxAawT9R5RzTDITWHkS4KVaFalOYLxQ8x4s31FWXUiprAvJ -AIVw9gnBC7kDLro2irCljZB5ro8fsg0SJ0ZFc4cZMPZxnMKm5ovC6WggbblyaHrR -rV8jhHFIR+RG9/nnw0PgvGOmV9f4Q0a/7E18AxdBXYMZSp7p/mwbQdkqgm7p73bg -7E2Zz/Fhg1/PguwjlDal+HyUEPDvcPG41NAKwpMeL78qVJTQcBzzo1Irqj5f5UFJ -p4/H7QDlEsz/ZGxXXq3PdAP5BICwiOD44G9dIUECBlLktZUcsQMGwKgAZxyxBAAG -BmxhcHRvcAUQXVLApuPC+s1X/RPnFumDgQ== diff --git a/libretroshare/src/tests/pgp/test_certificate.oldformat.rsc b/libretroshare/src/tests/pgp/test_certificate.oldformat.rsc deleted file mode 100644 index 501e4abd7..000000000 --- a/libretroshare/src/tests/pgp/test_certificate.oldformat.rsc +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: OpenPGP:SDK v0.9 - -mQENBEyoe/MBCAC9rKm/ehp9Iv1XrOiKIyj1X5nJzQ660+OhmQf4lbJvkrcnvdrd -cmlfZQfupWMXHo7A3+27lOpfTvA1xpO8Gze0bRbLsbpx2dARjLUzXJAIFNCYzH5x -lIixxOwgX3tinKfoP3WvZv+nYBac/HeAPUW8BVqx6Y6V/gM3c71XNf9uhPgArN0j -vLOeqAJY+lACJZYlAIw6Jt2FzarC+orWndkvrsgrWmdxkorfZKBfdNwdf1YYrpUm -Gaf51x4DkrMWpfHxS8b6cgOmSN3LeAC8LCm5oEXPfNgaRehN9LKrSmcpcPS2jvDi -pgGBx+nL7gytCREMJkJoxppXQpVt1whaFDJVABEBAAG0OkN5cmlsLXRlc3QgKGdl -bmVyYXRlZCBieSBSZXRyb3NoYXJlKSA8Y3lyaWwuc29sZXJAaW1hZy5mcj6JATgE -EwECACIFAkyoe/MCGy8GCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEGYPt3Fy -fOKG+h0H/A+vvryYmGcGFl82D4M0mAPAlbjZFkGCB8qJJSFuor55GJ3V8pBb4UK7 -jnLhQhqsdXxAawT9R5RzTDITWHkS4KVaFalOYLxQ8x4s31FWXUiprAvJAIVw9gnB -C7kDLro2irCljZB5ro8fsg0SJ0ZFc4cZMPZxnMKm5ovC6WggbblyaHrRrV8jhHFI -R+RG9/nnw0PgvGOmV9f4Q0a/7E18AxdBXYMZSp7p/mwbQdkqgm7p73bg7E2Zz/Fh -g1/PguwjlDal+HyUEPDvcPG41NAKwpMeL78qVJTQcBzzo1Irqj5f5UFJp4/H7QDl -Esz/ZGxXXq3PdAP5BICwiOD44G9dIUE= -=BWkb ------END PGP PUBLIC KEY BLOCK----- ---SSLID--5d52c0a6e3c2facd57fd13e716e98381;--LOCATION--laptop; ---LOCAL--192.168.0.103:7345;--EXT--82.228.181.149:7345; diff --git a/libretroshare/src/tests/pgp/test_certificate.sh b/libretroshare/src/tests/pgp/test_certificate.sh deleted file mode 100755 index e81d89f98..000000000 --- a/libretroshare/src/tests/pgp/test_certificate.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -./test_certificate -i test_certificate.oldformat.rsc && ./test_certificate -i test_certificate.newformat.rsc diff --git a/libretroshare/src/tests/pgp/test_identity_import.c b/libretroshare/src/tests/pgp/test_identity_import.c deleted file mode 100644 index 7fcd14066..000000000 --- a/libretroshare/src/tests/pgp/test_identity_import.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include - -#include -#include -//#include -#include -#include -#include - -INITTEST() ; - -static std::string pgp_pwd_cb(void * /*hook*/, const char *uid_hint, const char * /*passphrase_info*/, int prev_was_bad) -{ -#define GPG_DEBUG2 -#ifdef GPG_DEBUG2 - fprintf(stderr, "pgp_pwd_callback() called.\n"); -#endif - std::string password; - - std::cerr << "SHould not be called!" << std::endl; - return password ; -} - -int main(int argc,char *argv[]) -{ - try - { - argstream as(argc,argv) ; - std::string idfile ; - bool clean_cert = false ; - - as >> parameter('i',"input",idfile,"input retroshare identity file, ascii format",true) - >> help() ; - - as.defaultErrorHandling() ; - - PGPHandler handler("toto1","toto2","toto3","toto4") ; - - PGPIdType imported_key_id ; - std::string import_error_string ; - - bool res = handler.importGPGKeyPair(idfile,imported_key_id,import_error_string) ; - - handler.syncDatabase() ; - - if(!res) - std::cerr << "Identity Import error: " << import_error_string << std::endl; - - CHECK(res) ; - } - catch(std::exception& e) - { - std::cerr << "Exception never handled: " << e.what() << std::endl; - return 1 ; - } -} - diff --git a/libretroshare/src/tests/pgp/test_key_parsing.cc b/libretroshare/src/tests/pgp/test_key_parsing.cc deleted file mode 100644 index 8e4a8ff64..000000000 --- a/libretroshare/src/tests/pgp/test_key_parsing.cc +++ /dev/null @@ -1,64 +0,0 @@ -// COMPILE_LINE: g++ -o test_key_parsing test_key_parsing.cc -g -I../../../openpgpsdk/include -I../ -L../lib ../../../openpgpsdk/src/lib/libops.a -lssl -lcrypto -lbz2 -// -#include -#include - -extern "C" -{ - #include - #include - #include -} - -#include -#include - -INITTEST() ; - -int main(int argc,char *argv[]) -{ - try - { - // test PGPHandler - // - // 0 - init - - bool armoured = false ; - std::string keyfile ; - - argstream as(argc,argv) ; - - as >> parameter('i',"input-key",keyfile,"input key file.",true) - >> option('a',"armoured",armoured,"input is armoured") - >> help() ; - - as.defaultErrorHandling() ; - - ops_keyring_t *kr = (ops_keyring_t*)malloc(sizeof(ops_keyring_t)) ; - kr->nkeys = 0 ; - kr->nkeys_allocated = 0 ; - kr->keys = 0 ; - - CHECK(ops_false != ops_keyring_read_from_file(kr,armoured, keyfile.c_str())) ; - - for(int i=0;inkeys;++i) - { - ops_print_public_keydata(&kr->keys[i]) ; - ops_print_public_keydata_verbose(&kr->keys[i]) ; - ops_print_public_key(&kr->keys[i].key.pkey) ; - } - - ops_list_packets(const_cast(keyfile.c_str()),armoured,kr,NULL) ; - - FINALREPORT("Test key parsing") ; - - return TESTRESULT() ; - } - catch(std::exception& e) - { - std::cerr << "Caught exception: " << e.what() << std::endl; - return 1 ; - } -} - - diff --git a/libretroshare/src/tests/pgp/test_key_parsing.sh b/libretroshare/src/tests/pgp/test_key_parsing.sh deleted file mode 100644 index dd9ee9139..000000000 --- a/libretroshare/src/tests/pgp/test_key_parsing.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -./test_key_parsing -i test_pubring.gpg diff --git a/libretroshare/src/tests/pgp/test_pgp_handler.cc b/libretroshare/src/tests/pgp/test_pgp_handler.cc deleted file mode 100644 index b78adc5f5..000000000 --- a/libretroshare/src/tests/pgp/test_pgp_handler.cc +++ /dev/null @@ -1,397 +0,0 @@ -// COMPILE_LINE: g++ -o test_pgp_handler test_pgp_handler.cc -I../../../openpgpsdk/include -I../ -L../lib -lretroshare ../../../libbitdht/src/lib/libbitdht.a ../../../openpgpsdk/lib/libops.a -lgnome-keyring -lupnp -lssl -lcrypto -lbz2 -// -#include -#include -#include -#include -#include -#include -#include - -INITTEST() ; - -static std::string static_passphrase = "" ; -static std::string passphrase_callback(void *data,const char *uid_info,const char *what,int prev_was_bad) -{ - if(!static_passphrase.empty()) - return static_passphrase ; - - if(prev_was_bad) - std::cerr << "Bad passphrase." << std::endl; - - std::string wt = std::string("Please enter passphrase for key id ") + uid_info + " :"; - - return std::string(getpass(wt.c_str())) ; -} - -static std::string stringFromBytes(unsigned char *bytes,size_t len) -{ - static const char out[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ; - - std::string res ; - - for(uint32_t j = 0; j < len; j++) - { - res += out[ (bytes[j]>>4) ] ; - res += out[ bytes[j] & 0xf ] ; - } - - return res ; -} - -static std::string askForKeyId(PGPHandler& pgph) -{ - // 0 - print keys and key types - - std::list lst ; - pgph.availableGPGCertificatesWithPrivateKeys(lst) ; - - std::cerr << lst.size() << " available key pairs: " << std::endl; - int i=0 ; - - for(std::list::const_iterator it(lst.begin());it!=lst.end();++it,++i) - { - std::cerr << "(" << i << ") ID=" << (*it).toStdString() << ", type = " ; - - const PGPCertificateInfo *cert = pgph.getCertificateInfo(*it) ; - - switch(cert->_type) - { - case PGPCertificateInfo::PGP_CERTIFICATE_TYPE_DSA: std::cerr << "DSA" << std::endl; - break ; - case PGPCertificateInfo::PGP_CERTIFICATE_TYPE_RSA: std::cerr << "RSA" << std::endl; - break ; - default: std::cerr << "Unknown" << std::endl; - } - } - - if(i == 0) - throw std::runtime_error("No key pair available in supplied keyring.") ; - - // 1 - ask for which key to use. - - int num = -1 ; - - while(true) - { - std::cerr << "Please enter selected key number (0 - " << i-1 << ") : " ; - std::cerr.flush() ; - - char buf[10]; - fgets(buf,10,stdin) ; - - if(sscanf(buf,"%d",&num) == 1 && num >= 0 && num < i) - break ; - } - - // 2 - return the id string. - - std::list::const_iterator it(lst.begin()) ; - for(int i=0;i> option('1',"pgptype",test_pgpid_type,"Test pgp ID type") - >> option('2',"keyring-read",test_keyring_read,"Test keyring read") - >> option('3',"file-encryption",test_file_encryption,"Test file encryption. Needs -f, -i, -p and -s") - >> option('4',"keygen",test_gen_key,"Test key generation.") - >> option('5',"signature",test_signature,"Test signature.") - >> option('6',"output",test_output,"Test output.") - >> option('7',"memory-encryption",test_memory_encryption,"Test output.") - >> option('F',"fulltest",full_test,"Test everything.") - >> parameter('f',"file",file_to_encrypt,"File to encrypt. Used with -3",false) - >> parameter('p',"pubring",pubring_file,"Public keyring file.",false) - >> parameter('s',"secring",secring_file,"Secret keyring file.",false) - >> parameter('i',"keyid",key_id_string,"Key id to use. If not supplied, will be asked.",false) - >> help() ; - - as.defaultErrorHandling() ; - - if(!full_test) - if(test_pgpid_type + test_keyring_read + test_file_encryption + test_gen_key + test_signature + test_output + test_memory_encryption != 1) - { - std::cerr << "Options 1 to 6 are mutually exclusive." << std::endl; - return 1; - } - if(full_test || test_pgpid_type) - { - // test pgp ids. - // - std::string st("3e5b22140ef56abb") ; - PGPIdType id = PGPIdType(std::string(st)) ; - - //std::cerr << "Id is : " << std::hex << id.toUInt64() << std::endl; - std::cerr << "Id st : " << id.toStdString() << std::endl; - - CHECK(id.toStdString(false) == st) ; - } - - // test PGPHandler - // - // 0 - init - - std::string pubring = pubring_file.empty()?"pubring.gpg":pubring_file ; - std::string secring = secring_file.empty()?"secring.gpg":secring_file ; - - static const std::string trustdb = "trustdb.gpg" ; - static const std::string lockfile = "lock" ; - - PGPHandler::setPassphraseCallback(&passphrase_callback) ; - PGPHandler pgph(pubring,secring,trustdb,lockfile) ; - - std::string email_str("test@gmail.com") ; - std::string name_str("test") ; - std::string passw_str("test00") ; - PGPIdType cert_id ; ; - - if(full_test || test_gen_key) - { - std::cerr << "Now generating a new PGP certificate: " << std::endl; - std::cerr << " email: " << email_str << std::endl; - std::cerr << " passw: " << passw_str << std::endl; - std::cerr << " name : " << name_str << std::endl; - - PGPIdType newid ; - std::string errString ; - static_passphrase = passw_str ; - - bool res = pgph.GeneratePGPCertificate(name_str, email_str, passw_str, newid, errString) ; - - cert_id = newid ; - - CHECK(res) ; - - if(!res) - std::cerr << "Generation of certificate returned error: " << errString << std::endl; - else - std::cerr << "Certificate generation success. New id = " << newid.toStdString() << std::endl; - } - - if(full_test) - key_id_string = cert_id.toStdString(true) ; - - if(full_test || test_keyring_read) - { - pgph.printKeys() ; - - std::cerr << std::endl ; - std::cerr << std::endl ; - - std::cerr << "Looking for keys with complete secret/public key pair: " << std::endl; - - std::list lst ; - pgph.availableGPGCertificatesWithPrivateKeys(lst) ; - - bool found = false ; - - for(std::list::const_iterator it(lst.begin());it!=lst.end();++it) - { - std::cerr << "Found id : " << (*it).toStdString() << std::endl; - if(cert_id == *it) - found = true ; - } - CHECK(found) ; - } - - if(full_test || test_output) - { - PGPIdType id2( (key_id_string.empty())?askForKeyId(pgph):key_id_string) ; - - std::cerr << "Now extracting key " << id2.toStdString() << " from keyring:" << std::endl ; - std::string cert = pgph.SaveCertificateToString(id2,false) ; - - std::cerr << "Now, trying to re-read this cert from the string:" << std::endl; - - PGPIdType id3 ; - std::string error_string ; - pgph.LoadCertificateFromString(cert,id3,error_string) ; - - std::cerr << "Loaded cert id: " << id3.toStdString() << ", Error string=\"" << error_string << "\"" << std::endl; - - CHECK(id3 == id2) ; - - std::cerr << cert << std::endl; - } - - if(test_passphrase_callback) - { - std::cerr << "Testing password callback: " << std::endl; - std::string newid = "XXXXXXXXXXXXXXXX" ; - std::string pass = passphrase_callback(NULL,newid.c_str(),"Please enter password: ",false) ; - std::cerr << "Password = \"" << pass << "\"" << std::endl; - } - - if(full_test || test_signature) - { - if(key_id_string.empty()) - key_id_string = askForKeyId(pgph) ; - - PGPIdType key_id(key_id_string) ; - std::cerr << "Testing signature with keypair " << key_id_string << std::endl; - - static const size_t BUFF_LEN = 25 ; - unsigned char *test_bin = new unsigned char[BUFF_LEN] ; - for(size_t i=0;i -#include -#include -#include -#include - -INITTEST() ; - -static std::string passphrase_callback(void *data,const char *uid_info,const char *what,int prev_was_bad) -{ - return std::string(getpass(what)) ; -} - -static std::string stringFromBytes(unsigned char *bytes,size_t len) -{ - static const char out[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ; - - std::string res ; - - for(int j = 0; j < len; j++) - { - res += out[ (bytes[j]>>4) ] ; - res += out[ bytes[j] & 0xf ] ; - } - - return res ; -} - -int main(int argc,char *argv[]) -{ - // test pgp ids. - // - PGPIdType id("3e5b22140ef56abb") ; - - std::cerr << "Id st : " << id.toStdString() << std::endl; - - // test PGPHandler - // - // 0 - init - - static const std::string pubring = "pubring.gpg" ; - static const std::string secring = "secring.gpg" ; - static const std::string trustdb = "trustdb.gpg" ; - static const std::string lockfil = "lock" ; - - PGPHandler::setPassphraseCallback(&passphrase_callback) ; - PGPHandler pgph(pubring,secring,trustdb,lockfil) ; - - pgph.printKeys() ; - - FINALREPORT("Signature parsing") ; - - return TESTRESULT() ; -} - diff --git a/libretroshare/src/tests/pgp/test_pubring.gpg b/libretroshare/src/tests/pgp/test_pubring.gpg deleted file mode 100644 index 338dfe86b..000000000 Binary files a/libretroshare/src/tests/pgp/test_pubring.gpg and /dev/null differ diff --git a/libretroshare/src/tests/pqi/TestNotes.txt b/libretroshare/src/tests/pqi/TestNotes.txt deleted file mode 100644 index 6d6089e9b..000000000 --- a/libretroshare/src/tests/pqi/TestNotes.txt +++ /dev/null @@ -1,94 +0,0 @@ - -There are a huge amount of testing to be done here. - -Components and Tests. -============================================================ ------------------------------------------------------------- -Basic Components ------------------------------------------------------------- -pqinetwork.cc: net_test, net_test1, netiface_test -pqi_base.cc: no need. -pqimonitor.cc: no need. -p3notify.cc: no need. -pqisecurity.cc: no need. -pqiservice.cc: no need. -cleanupxpgp.cc to test. - ------------------------------------------------------------- -Serialisation Components ------------------------------------------------------------- -pqiarchive.cc: pqiarchive_test -pqibin.cc: pqiarchive_test -pqistreamer.cc -pqistore.cc - ------------------------------------------------------------- -SSL Network Components ------------------------------------------------------------- -pqiloopback.cc -pqissltunnel.cc -pqissludp.cc -pqissl.cc -pqiperson.cc -pqipersongrp.cc -pqisslpersongrp.cc -pqissllistener.cc - ------------------------------------------------------------- -Authentication Components ------------------------------------------------------------- -sslcert.cc -xpgpcert.cc -authgpg.cc -authssl.cc - ------------------------------------------------------------- -Manager Components ------------------------------------------------------------- -p3connmgr.cc -pqihandler.cc -p3dhtmgr.cc: dht_test -p3cfgmgr.cc - -============================================================ -Test Specifics -============================================================ ------------------------------------------------------------- -net_test ------------------------------------------------------------- -Tested Code: pqinetwork.cc, rsnet.cc -Description: -(1) Tests ntohll / htonll -(3) Tests socket binding. - ------------------------------------------------------------- -net_test1 ------------------------------------------------------------- -Tested Code: pqinetwork.cc, rsnet.cc -Description: -(1) isExternalNet() -(2) isPrivateNet() -(3) isLoopbackNet() -(5) isValidNet() - ------------------------------------------------------------- -pqiarchive_test ------------------------------------------------------------- -Tested Code: pqiarchive.cc pqibin.cc -Description : - Stores increasingly large packets into an archive file then retrieves them. - - NOTE: This tests packets up to size of 1Mb. This causes the test to FAIL - due to getRsPktMaxSize() returning 262142.... What to do? This needs to be fixed! - - see comments at serialiser/rsserial.cc line 448 - ------------------------------------------------------------- -dht_test ------------------------------------------------------------- -Tested Code : p3dhtmgr.cc -Description : - -This is a manual test of the DHT manager. needs to be -converted to an automatic test. - diff --git a/libretroshare/src/tests/pqi/conn_harness.cc b/libretroshare/src/tests/pqi/conn_harness.cc deleted file mode 100644 index 72da573d4..000000000 --- a/libretroshare/src/tests/pqi/conn_harness.cc +++ /dev/null @@ -1,284 +0,0 @@ -/* - * libretroshare/src/test/pqi testconnect.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pqiperson acts as the wrapper for all connection methods to a single peer. - * - * This test creates, a pqiperson and simulates connections, disconnections. - * packets passing through. - * - */ - - -#include "conn_harness.h" -#include "pqi/pqibin.h" -#include -#include - -/******************************************************* - * - * Test structure - *****************/ - - -/* static test variables */ -uint32_t testCounter = 0; -pqiconnect *testConnectPointer[NUM_CONN_MAX]; -PQInterface *testConnectParent[NUM_CONN_MAX]; -uint32_t testConnectState[NUM_CONN_MAX]; -std::list testConnectTimes[NUM_CONN_MAX]; -std::list testConnectAddrs[NUM_CONN_MAX]; - -std::list testResetState[NUM_CONN_MAX]; -std::list testResetTimes[NUM_CONN_MAX]; - -uint32_t testConnectAction[NUM_CONN_MAX] = { 0 }; -rstime_t testConnectPeriod[NUM_CONN_MAX] = { 0 }; - -uint32_t defTestConnectAction = TST_ACTION_FAILED; - - -uint32_t findWhichConnect(pqiconnect *conn) -{ - int i; - for(i = 0; i < NUM_CONN_MAX; i++) - { - if (testConnectPointer[i] == conn) - { - return i; - } - } - // error. - std::cerr << "Connect Missing" << std::endl; - exit(1); - return 0; -} - -void addTestConnect(pqiconnect *pqi, PQInterface *parent) -{ - testConnectPointer[testCounter] = pqi; - testConnectParent[testCounter] = parent; - testConnectState[testCounter] = 0; - testCounter++; - if (testCounter > NUM_CONN_MAX) - { - std::cerr << "Too Many Connects" << std::endl; - exit(1); - } -} - -void resetTestConnects() -{ - testCounter = 0; - int i; - for(i = 0; i < NUM_CONN_MAX; i++) - { - testConnectAddrs[i].clear(); - testConnectTimes[i].clear(); - testResetState[i].clear(); - testResetTimes[i].clear(); - } -} - -/* setup callback actions */ -void setDefaultTestConnectAction(uint32_t action) -{ - defTestConnectAction = action; -} - -void forceConnect(uint32_t idx) -{ - /* flag as con */ -} - - -testConnect::testConnect(RsSerialiser *rss, NetBinInterface *ni_in) - :pqiconnect(rss, ni_in) -{ - -} - -testConnect::~testConnect() -{ - return; -} - - /* dummyConnect */ -int testConnect::connect(struct sockaddr_in raddr) -{ - int cidx = findWhichConnect(this); - rstime_t now = time(NULL); - - testConnectState[cidx] |= TST_STATE_CONNECT; - testConnectTimes[cidx].push_back(now); - testConnectAddrs[cidx].push_back(raddr); - testConnectAction[cidx] = defTestConnectAction; - - std::cerr << "testConnect[" << cidx << "].connect() called"; - std::cerr << std::endl; - return 0; -} - -int testConnect::listen() -{ - int cidx = findWhichConnect(this); - testConnectState[cidx] |= TST_STATE_LISTEN; - std::cerr << "testConnect[" << cidx << "].listen() called"; - std::cerr << std::endl; - return 1; -} - -int testConnect::stoplistening() -{ - int cidx = findWhichConnect(this); - testConnectState[cidx] &= ~TST_STATE_LISTEN; - std::cerr << "testConnect[" << cidx << "].stoplistening() called"; - std::cerr << std::endl; - return 1; -} - -int testConnect::reset() -{ - int cidx = findWhichConnect(this); - rstime_t now = time(NULL); - - // reset everything except listening. - testResetState[cidx].push_back(testConnectState[cidx]); - testResetTimes[cidx].push_back(now); - testConnectState[cidx] &= TST_STATE_LISTEN; - - std::cerr << "testConnect[" << cidx << "].reset() called"; - std::cerr << std::endl; - return 1; -} - -// leave this as is virtual int disconnect() { return ni -> reset(); } - -bool testConnect::connect_parameter(uint32_t type, uint32_t value) -{ - int cidx = findWhichConnect(this); - //testConnectState[cidx] |= TST_STATE_LISTEN; - std::cerr << "testConnect[" << cidx << "].connect_parameter() called"; - std::cerr << std::endl; - - /* sum up PERIOD and DELAY */ - if (type == NET_PARAM_CONNECT_DELAY) - { - std::cerr << "PARAMETER: DELAY: " << value; - std::cerr << std::endl; - - //testConnectPeriod[cidx] = value; - } - else if (type == NET_PARAM_CONNECT_PERIOD) - { - std::cerr << "PARAMETER: PERIOD: " << value; - std::cerr << std::endl; - - //testConnectPeriod[cidx] += value; - } - else if (type == NET_PARAM_CONNECT_TIMEOUT) - { - std::cerr << "PARAMETER: TIMEOUT: " << value; - std::cerr << std::endl; - - testConnectPeriod[cidx] = value; - //testConnectPeriod[cidx] += value; - } - std::cerr << "total testConnectPeriod: " << testConnectPeriod[cidx]; - std::cerr << std::endl; - - return true; -} - -int testConnect::getConnectAddress(struct sockaddr_in &raddr) -{ - int cidx = findWhichConnect(this); - if (testConnectAddrs[cidx].size() > 0) - { - raddr = testConnectAddrs[cidx].back(); - return 1; - } - std::cerr << "testConnect[" << cidx << "].getConnectAddress() called"; - std::cerr << std::endl; - return 0; -} - - -int testConnect::tick() -{ - int cidx = findWhichConnect(this); - - std::cerr << "testConnect[" << cidx << "].tick()"; - std::cerr << std::endl; - - if (testConnectState[cidx] & TST_STATE_CONNECT) - { - rstime_t now = time(NULL); - rstime_t cTime = testConnectTimes[cidx].back(); - if (now - cTime > testConnectPeriod[cidx]) - { - - std::cerr << "testConnect[" << cidx << "].tick() reached ConnectPeriod"; - std::cerr << " age: " << now - cTime << " period: " << testConnectPeriod[cidx]; - std::cerr << std::endl; - - PQInterface *connParent = testConnectParent[cidx]; - - testConnectState[cidx] &= ~TST_STATE_CONNECT; - /* do callback now */ - if (testConnectAction[cidx] == TST_ACTION_SUCCESS) - { - std::cerr << "testConnect[" << cidx << "].tick() CONNECTED callback"; - std::cerr << std::endl; - - testConnectState[cidx] &= ~TST_STATE_CONNECTED; - /* do callback */ - connParent -> notifyEvent(this->ni, NET_CONNECT_SUCCESS); - - } - else if (testConnectAction[cidx] == TST_ACTION_FAILED) - { - std::cerr << "testConnect[" << cidx << "].tick() FAILED callback"; - std::cerr << std::endl; - - /* do callback */ - connParent -> notifyEvent(this->ni, NET_CONNECT_FAILED); - - } - else - { - std::cerr << "testConnect[" << cidx << "].tick() no callback (BAD)"; - std::cerr << std::endl; - } - - } - } - return 0; -} - - - - - diff --git a/libretroshare/src/tests/pqi/conn_harness.h b/libretroshare/src/tests/pqi/conn_harness.h deleted file mode 100644 index 697faca99..000000000 --- a/libretroshare/src/tests/pqi/conn_harness.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef TEST_PQICONNECT_H -#define TEST_PQICONNECT_H - -/* - * libretroshare/src/test/pqi testconnect.h - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "pqi/pqiperson.h" -//#include "pqi/pqibin.h" -#include "util/rsnet.h" - -/******************************************************* - * - * Test structure - *****************/ - - -#define NUM_CONN_MAX 50 - -#define TST_STATE_CONNECT 0x0001 -#define TST_STATE_LISTEN 0x0002 -#define TST_STATE_CONNECTED 0x0004 - -#define TST_ACTION_NONE 0x0000 -#define TST_ACTION_FAILED 0x0001 -#define TST_ACTION_SUCCESS 0x0002 - -/* static test variables */ -extern uint32_t testCounter; -extern pqiconnect *testConnectPointer[NUM_CONN_MAX]; -extern uint32_t testConnectState[NUM_CONN_MAX]; -extern std::list testConnectTimes[NUM_CONN_MAX]; -extern std::list testConnectAddrs[NUM_CONN_MAX]; - -extern std::list testResetState[NUM_CONN_MAX]; -extern std::list testResetTimes[NUM_CONN_MAX]; - -uint32_t findWhichConnect(pqiconnect *conn); -void addTestConnect(pqiconnect *pqi, PQInterface *parent); -void resetTestConnects(); - -void setDefaultTestConnectAction(uint32_t action); - -class testConnect: public pqiconnect -{ - public: - - testConnect(RsSerialiser *rss, NetBinInterface *ni_in); - virtual ~testConnect(); - - /* dummyConnect */ - virtual int tick(); - virtual int connect(struct sockaddr_in raddr); - virtual int listen(); - virtual int stoplistening(); - virtual int reset(); - virtual bool connect_parameter(uint32_t type, uint32_t value); - virtual int getConnectAddress(struct sockaddr_in &raddr); -}; // end of testConnect. - - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg); - - -#endif - diff --git a/libretroshare/src/tests/pqi/conn_test.cc b/libretroshare/src/tests/pqi/conn_test.cc deleted file mode 100644 index 57ffceafe..000000000 --- a/libretroshare/src/tests/pqi/conn_test.cc +++ /dev/null @@ -1,363 +0,0 @@ - - -#include "pqi/p3connmgr.h" - - -/***** Test for the new DHT system *****/ - - -#include "util/rsnet.h" -#include "util/rsthreads.h" -#include "util/rsprint.h" -#include "pqi/p3dhtmgr.h" -#include "pqi/p3connmgr.h" -#error secpolicy was removed, also remove it from test to fix compile -#include "pqi/pqisecurity.h" -#include "pqi/pqipersongrp.h" - -#include -#include - -#include "tcponudp/udpsorter.h" - -/***** Test Framework *****/ - -const int NumOfPeers = 10; -std::string peerIds[NumOfPeers] = - {"PEER01", - "PEER02", /* Always online, no notify */ - "PEER03", /* notify/online at 20sec */ - "PEER04", /* Always online, notify at 30 sec */ - "PEER05", - "PEER06", /* notify/online at 50sec */ - "PEER07", - "PEER08", - "PEER09", /* notify/online at 80sec */ - "PEER10"}; - -#define STUN_PORT 7777 - -std::string ownId = "OWNID-AAAA"; -rstime_t ownPublishTs; - -RsMutex frmMtx; -std::list searchIds; -std::list searchModes; - -std::map onlineMap; -std::map notifyMap; - -void initTestData() -{ - ownPublishTs = 0; - /* setup Peers that are online always */ - bool online; - uint32_t ts; - for(int i = 0; i < NumOfPeers; i++) - { - online = false; - if ((i == 1) || (i == 3)) - { - online = true; - } - onlineMap[peerIds[i]] = online; - - if ((i == 2) || (i == 3) || - (i == 5) || (i == 8)) - { - ts = i * 10; - notifyMap[ts] = peerIds[i]; - } - } -} - -void respondPublish() -{ - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - if (!ownPublishTs) - { - std::cerr << "Own ID first published!" << std::endl; - ownPublishTs = time(NULL); - } - frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ -} - -void respondSearch(p3DhtMgr *mgr, std::string id, uint32_t mode) -{ - std::cerr << "Checking for Search Results" << std::endl; - rstime_t now = time(NULL); - bool doNotify = false; - bool doOnline = false; - std::string notifyId; - - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - if ((mode == DHT_MODE_NOTIFY) && (ownPublishTs)) - { - /* */ - std::map::iterator it; - uint32_t delta_t = now - ownPublishTs; - it = notifyMap.begin(); - if (it != notifyMap.end()) - { - if (it->first <= delta_t) - { - notifyId = it->second; - onlineMap[notifyId] = true; - notifyMap.erase(it); - doNotify = true; - } - } - } - else if (mode == DHT_MODE_SEARCH) - { - - /* translate */ - std::map::iterator mit; - for(mit = onlineMap.begin(); (mit != onlineMap.end()) && - (RsUtil::HashId(mit->first, false) != id); mit++); - - if (mit != onlineMap.end()) - { - doOnline = mit->second; - } - } - - frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ - - uint32_t type = 0; - - struct sockaddr_in laddr; - inet_aton("10.0.0.129", &(laddr.sin_addr)); - laddr.sin_port = htons(7812); - laddr.sin_family = AF_INET; - - struct sockaddr_in raddr; - inet_aton("127.0.0.1", &(raddr.sin_addr)); - raddr.sin_port = htons(STUN_PORT); - raddr.sin_family = AF_INET; - - if (doNotify) - { - std::cerr << "Responding to Notify: id:" << notifyId << std::endl; - mgr->dhtResultNotify(RsUtil::HashId(notifyId, true)); - } - - if (doOnline) - { - std::cerr << "Responding to Search" << std::endl; - mgr->dhtResultSearch(id, laddr, raddr, type, ""); - } - -} - - -/***** Test Framework *****/ - -class DhtMgrTester: public p3DhtMgr -{ - - /* Implementation */ - public: - - DhtMgrTester(std::string id, pqiConnectCb *cb) - :p3DhtMgr(id, cb) - { - return; - } - - - - - - /* Blocking calls (only from thread) */ -virtual bool dhtPublish(std::string id, - struct sockaddr_in &laddr, struct sockaddr_in &raddr, - uint32_t type, std::string sign) -{ - std::cerr << "DhtMgrTester::dhtPublish() id: " << RsUtil::BinToHex(id); - std::cerr << " laddr: " << rs_inet_ntoa(laddr.sin_addr) << " lport: " << ntohs(laddr.sin_port); - std::cerr << " raddr: " << rs_inet_ntoa(raddr.sin_addr) << " rport: " << ntohs(raddr.sin_port); - std::cerr << " type: " << type << " sign: " << sign; - std::cerr << std::endl; - - respondPublish(); - - return true; -} - -virtual bool dhtNotify(std::string peerid, std::string ownid, std::string sign) -{ - std::cerr << "DhtMgrTester::dhtNotify() id: " << RsUtil::BinToHex(peerid) << ", ownId: " << RsUtil::BinToHex(ownId); - std::cerr << " sign: " << sign; - std::cerr << std::endl; - - return true; -} - -virtual bool dhtSearch(std::string id, uint32_t mode) -{ - std::cerr << "DhtMgrTester::dhtSearch(id: " << RsUtil::BinToHex(id) << ", mode: " << mode << ")" << std::endl; - - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - searchIds.push_back(id); - searchModes.push_back(mode); - frmMtx.unlock(); /* LOCK TEST FRAMEWORK MUTEX */ - - return true; -} - -}; - - -/* OVERLOAD THE ConnMgr - to insert peers */ -class p3TestConnMgr: public p3ConnectMgr -{ - public: - p3TestConnMgr(int mode) - :p3ConnectMgr(new p3DummyAuthMgr()), mTestMode(mode) { return; } - - protected: - /* must be virtual for testing */ -virtual void loadConfiguration() -{ - - /* setup own address */ - ownState.id = ownId; - ownState.name = "SELF NAME"; - ownState.localaddr.sin_family = AF_INET; - inet_aton("127.0.0.1", &(ownState.localaddr.sin_addr)); - ownState.localaddr.sin_port = htons(7812); - ownState.netMode = RS_NET_MODE_UDP; - ownState.visState = RS_VIS_STATE_STD; - - /* others not important */ - //ownState.state = 0; - //ownState.actions = 0; - - - if (mTestMode == 1) /* Add to Stun List */ - { - for(int i = 0; i < NumOfPeers; i++) - { - mStunList.push_back(peerIds[i]); - } - } - else if (mTestMode == 2) /* add to peers */ - { - /* add in as peers */ - //addPeer(); - for(int i = 0; i < NumOfPeers; i++) - { - if (i < 5) - { - mStunList.push_back(RsUtil::HashId(peerIds[i])); - } - else - { - addFriend(peerIds[i]); - } - } - } -} - - protected: - - uint32_t mTestMode; -}; - - -int main() -{ - rstime_t startTime = time(NULL); - /* setup system */ - initTestData(); - - /* setup a Stunner to respond to ConnMgr */ - - struct sockaddr_in saddr; - saddr.sin_family = AF_INET; - inet_aton("127.0.0.1", &(saddr.sin_addr)); - saddr.sin_port = htons(STUN_PORT); - UdpSorter stunner(saddr); /* starts a receiving thread */ - - p3TestConnMgr connMgr(2); - DhtMgrTester dhtTester(ownId, &connMgr); - - /* now add in some peers */ - connMgr.setDhtMgr(&dhtTester); - connMgr.setUpnpMgr(NULL); - - /************ ADD pqipersongrp as pqimonitor *****************/ -#error secpolicy was removed, should remove it from tests too - SecurityPolicy *pol = secpolicy_create(); - unsigned long flags = 0; - pqipersongrp *pqipg = new pqipersongrpDummy(pol, flags); - - connMgr.addMonitor(pqipg); - - /************ ADD pqipersongrp as pqimonitor *****************/ - - - /* startup dht */ - std::cerr << "Starting up DhtTester()" << std::endl; - dhtTester.start(); - - /* wait for a little before switching on */ -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - sleep(1); -#else - Sleep(1000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - std::cerr << "Switching on DhtTester()" << std::endl; - dhtTester.setDhtOn(true); - - /* wait loop */ - while(1) - { -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - sleep(1); -#else - Sleep(1000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - connMgr.tick(); - pqipg->tick(); - - /* handle async search */ - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - - std::string id; - uint32_t mode; - bool doRespond = false; - if (searchIds.size() > 0) - { - id = searchIds.front(); - mode = searchModes.front(); - doRespond = true; - searchIds.pop_front(); - searchModes.pop_front(); - } - - frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ - - if (doRespond) - { - respondSearch(&dhtTester, id, mode); - } - } -}; - - - - - - - - - - diff --git a/libretroshare/src/tests/pqi/dht_test.cc b/libretroshare/src/tests/pqi/dht_test.cc deleted file mode 100644 index ccfd117b5..000000000 --- a/libretroshare/src/tests/pqi/dht_test.cc +++ /dev/null @@ -1,310 +0,0 @@ - - -/***** Test for the new DHT system *****/ - - -#include "pqi/pqinetwork.h" - -#include "util/rsnet.h" -#include "util/rsthreads.h" -#include "util/rsprint.h" - -#include "pqi/p3dhtmgr.h" - -#include -#include - - -/***** Test Framework *****/ - -const int NumOfPeers = 10; -std::string peerIds[NumOfPeers] = - {"PEER01", - "PEER02", /* Always online, no notify */ - "PEER03", /* notify/online at 20sec */ - "PEER04", /* Always online, notify at 30 sec */ - "PEER05", - "PEER06", /* notify/online at 50sec */ - "PEER07", - "PEER08", - "PEER09", /* notify/online at 80sec */ - "PEER10"}; - -std::string ownId = "AAAA"; -rstime_t ownPublishTs; - -RsMutex frmMtx; -std::list searchIds; -std::list searchModes; - -std::map onlineMap; -std::map notifyMap; - -void initTestData() -{ - ownPublishTs = 0; - /* setup Peers that are online always */ - bool online; - uint32_t ts; - for(int i = 0; i < NumOfPeers; i++) - { - online = false; - if ((i == 1) || (i == 3)) - { - online = true; - } - onlineMap[peerIds[i]] = online; - - if ((i == 2) || (i == 3) || - (i == 5) || (i == 8)) - { - ts = i * 10; - notifyMap[ts] = peerIds[i]; - } - } -} - -void respondPublish() -{ - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - if (!ownPublishTs) - { - std::cerr << "Own ID first published!" << std::endl; - ownPublishTs = time(NULL); - } - frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ -} - -void respondSearch(p3DhtMgr *mgr, std::string id, uint32_t mode) -{ - std::cerr << "Checking for Search Results" << std::endl; - rstime_t now = time(NULL); - bool doNotify = false; - bool doOnline = false; - std::string notifyId; - - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - if ((mode == DHT_MODE_NOTIFY) && (ownPublishTs)) - { - /* */ - std::map::iterator it; - uint32_t delta_t = now - ownPublishTs; - it = notifyMap.begin(); - if (it != notifyMap.end()) - { - if (it->first <= delta_t) - { - notifyId = it->second; - onlineMap[notifyId] = true; - notifyMap.erase(it); - doNotify = true; - } - } - } - else if (mode == DHT_MODE_SEARCH) - { - /* translate */ - std::map::iterator mit; - for(mit = onlineMap.begin(); (mit != onlineMap.end()) && - (RsUtil::HashId(mit->first, false) != id); mit++); - - if (mit != onlineMap.end()) - { - doOnline = mit->second; - } - } - - frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ - - uint32_t type = 0; - - struct sockaddr_in laddr; - inet_aton("10.0.0.129", &(laddr.sin_addr)); - laddr.sin_port = htons(7812); - laddr.sin_family = AF_INET; - - struct sockaddr_in raddr; - inet_aton("10.0.0.19", &(raddr.sin_addr)); - raddr.sin_port = htons(7812); - raddr.sin_family = AF_INET; - - if (doNotify) - { - std::cerr << "Responding to Notify" << std::endl; - mgr->dhtResultNotify(RsUtil::HashId(notifyId, true)); - } - - if (doOnline) - { - std::cerr << "Responding to Search" << std::endl; - mgr->dhtResultSearch(id, laddr, raddr, type, ""); - } -} - - - - - - -/***** Test Framework *****/ - - - - -class DhtMgrTester: public p3DhtMgr -{ - - /* Implementation */ - public: - - DhtMgrTester(std::string id, pqiConnectCb *cb) - :p3DhtMgr(id, cb) - { - return; - } - - - /* Blocking calls (only from thread) */ -virtual bool dhtPublish(std::string id, - struct sockaddr_in &laddr, struct sockaddr_in &raddr, - uint32_t type, std::string sign) -{ - std::cerr << "DhtMgrTester::dhtPublish() id: " << RsUtil::BinToHex(id); - std::cerr << " laddr: " << rs_inet_ntoa(laddr.sin_addr) << " lport: " << ntohs(laddr.sin_port); - std::cerr << " raddr: " << rs_inet_ntoa(raddr.sin_addr) << " rport: " << ntohs(raddr.sin_port); - std::cerr << " type: " << type << " sign: " << sign; - std::cerr << std::endl; - - respondPublish(); - - return true; -} - -virtual bool dhtNotify(std::string peerid, std::string ownid, std::string sign) -{ - std::cerr << "DhtMgrTester::dhtNotify() id: " << RsUtil::BinToHex(peerid) << ", ownId: " << RsUtil::BinToHex(ownId); - std::cerr << " sign: " << sign; - std::cerr << std::endl; - - return true; -} - -virtual bool dhtSearch(std::string id, uint32_t mode) -{ - std::cerr << "DhtMgrTester::dhtSearch(id: " << RsUtil::BinToHex(id) << ", mode: " << mode << ")" << std::endl; - - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - searchIds.push_back(id); - searchModes.push_back(mode); - frmMtx.unlock(); /* LOCK TEST FRAMEWORK MUTEX */ - - return true; -} - -}; - -int main() -{ - rstime_t startTime = time(NULL); - bool haveOwnAddress = false; - /* setup system */ - initTestData(); - - pqiConnectCbDummy cbTester; - DhtMgrTester dhtTester(ownId, &cbTester); - - /* now add in some peers */ - - /* startup dht */ - std::cerr << "Starting up DhtTester()" << std::endl; - dhtTester.start(); - - /* wait for a little before switching on */ -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - sleep(1); -#else - Sleep(1000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - std::cerr << "Switching on DhtTester()" << std::endl; - dhtTester.enable(true); - - std::cerr << "Adding a List of Peers" << std::endl; - for(int i = 0; i < NumOfPeers; i++) - { - dhtTester.findPeer(peerIds[i]); - } - - - /* wait loop */ - while(1) - { - std::cerr << "Main waiting..." << std::endl; -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - sleep(3); -#else - Sleep(3000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - - /* handle async search */ - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - - std::string id; - uint32_t mode; - bool doRespond = false; - if (searchIds.size() > 0) - { - id = searchIds.front(); - mode = searchModes.front(); - doRespond = true; - searchIds.pop_front(); - searchModes.pop_front(); - } - - frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ - - if (doRespond) - { - respondSearch(&dhtTester, id, mode); - } - - if (!haveOwnAddress) - { - if (time(NULL) - startTime > 20) - { - std::cerr << "Setting Own Address!" << std::endl; - haveOwnAddress = true; - - uint32_t type = DHT_ADDR_UDP; - - struct sockaddr_in laddr; - inet_aton("10.0.0.111", &(laddr.sin_addr)); - laddr.sin_port = htons(7812); - laddr.sin_family = AF_INET; - - struct sockaddr_in raddr; - inet_aton("10.0.0.11", &(raddr.sin_addr)); - raddr.sin_port = htons(7812); - raddr.sin_family = AF_INET; - - dhtTester.setExternalInterface(laddr, raddr, type); - } - } - - } -}; - - - - - - - - - - diff --git a/libretroshare/src/tests/pqi/dnsresolver_test.cc b/libretroshare/src/tests/pqi/dnsresolver_test.cc deleted file mode 100644 index 2a20ecc90..000000000 --- a/libretroshare/src/tests/pqi/dnsresolver_test.cc +++ /dev/null @@ -1,83 +0,0 @@ - -/* - * "$Id:$" - * - * RetroShare C++ Interface. - * - * Copyright 2010-2011 by Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - -#include "util/dnsresolver.h" - -#include -#include -#include - -int main() -{ - std::list names; - - DNSResolver *r = new DNSResolver ; - - names.push_back("cortinaire.inrialpes.fr") ; - names.push_back("www.google.com") ; - names.push_back("www.ego.cn") ; - names.push_back("free.fr") ; - - for(int i=0;i<5;++i) - { - for(std::list::const_iterator it = names.begin(); it != names.end(); it++) - { - in_addr addr ; - bool res = r->getIPAddressFromString(*it,addr) ; - - if(res) - std::cerr << "Lookup of " << *it << ": " << (res?"done":"pending") << ": addr = " << (void*)addr.s_addr << std::endl; - else - std::cerr << "Lookup of " << *it << ": " << (res?"done":"pending") << std::endl; - } - - std::cerr << std::endl; - usleep(200000) ; - } - - r->reset() ; - - for(int i=0;i<5;++i) - { - for(std::list::const_iterator it = names.begin(); it != names.end(); it++) - { - in_addr addr ; - bool res = r->getIPAddressFromString(*it,addr) ; - - if(res) - std::cerr << "Lookup of " << *it << ": " << (res?"done":"pending") << ": addr = " << (void*)addr.s_addr << std::endl; - else - std::cerr << "Lookup of " << *it << ": " << (res?"done":"pending") << std::endl ; - } - std::cerr << std::endl; - usleep(200000) ; - } - - delete r ; -} - diff --git a/libretroshare/src/tests/pqi/extaddrfinder_test.cc b/libretroshare/src/tests/pqi/extaddrfinder_test.cc deleted file mode 100644 index 550011d09..000000000 --- a/libretroshare/src/tests/pqi/extaddrfinder_test.cc +++ /dev/null @@ -1,37 +0,0 @@ -#include "util/utest.h" - -#include -#include "pqi/pqinetwork.h" - -#include -#include - -INITTEST(); - -int main() -{ - std::cerr << "Testing the ext address finder service. This might take up to 10 secs..." << std::endl ; - - ExtAddrFinder fnd ; - in_addr addr ; - uint32_t tries = 0 ; - - while(! fnd.hasValidIP( &addr )) - { - sleep(1) ; - - if(++tries > 20) - { - std::cerr << "Failed !" << std::endl ; - CHECK(false) ; - } - } - - std::cerr << "Found the following IP: " << inet_ntoa(addr) << std::endl ; - - FINALREPORT("extaddrfinder_test"); - - return TESTRESULT() ; -} - - diff --git a/libretroshare/src/tests/pqi/gpgme_tst.c b/libretroshare/src/tests/pqi/gpgme_tst.c deleted file mode 100644 index ec88a8439..000000000 --- a/libretroshare/src/tests/pqi/gpgme_tst.c +++ /dev/null @@ -1,76 +0,0 @@ - -#include "pqi/authgpg.h" - -const std::string key_path("./tmp/privkey.pem"); -const std::string passwd("8764"); -const std::string gpg_passwd("aaaa"); -const std::string name("Test X509"); -const std::string email("test@email.com"); -const std::string org("Org"); -const std::string loc("Loc"); -const std::string state("State"); -const std::string country("GB"); - -int main() -{ - /* Init the auth manager */ - - GPGAuthMgr mgr; - - - /* Select which GPG Keys we use */ - - /* print all keys */ - mgr.printKeys(); - - std::list idList; - mgr.availablePGPCertificates(idList); - - if (idList.size() < 1) - { - fprintf(stderr, "No GPG Certificate to use!\n"); - exit(1); - } - std::string id = idList.front(); - fprintf(stderr, "Using GPG Certificate:%s \n", id.c_str()); - - std::string noname; - mgr.GPGInit(id); - mgr.LoadGPGPassword(gpg_passwd); - - /* Init SSL library */ - mgr.InitAuth(NULL, NULL, NULL); - - /* then try to generate and sign a X509 certificate */ - int nbits_in = 2048; - std::string errString; - - /* Generate a Certificate Request */ - X509_REQ *req = GenerateX509Req(key_path, passwd, name, email, org, - loc, state, country, nbits_in, errString); - - // setup output. - BIO *bio_out = NULL; - bio_out = BIO_new(BIO_s_file()); - BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); - - /* Print it out */ - int nmflag = 0; - int reqflag = 0; - - X509_REQ_print_ex(bio_out, req, nmflag, reqflag); - - X509 *x509 = mgr.SignX509Req(req, 100, gpg_passwd); - - X509_print_ex(bio_out, x509, nmflag, reqflag); - - BIO_flush(bio_out); - BIO_free(bio_out); - - /* now try to validate it */ - mgr.AuthX509(x509); - - //sleep(10); -} - - diff --git a/libretroshare/src/tests/pqi/net_test.cc b/libretroshare/src/tests/pqi/net_test.cc deleted file mode 100644 index ff7744141..000000000 --- a/libretroshare/src/tests/pqi/net_test.cc +++ /dev/null @@ -1,127 +0,0 @@ -/* - * libretroshare/src/test/pqi net_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * NETWORKING Test to check Big/Little Endian behaviour - * as well as socket behaviour - * - */ - -#include "util/utest.h" - -#include "pqi/pqinetwork.h" -#include "util/rsnet.h" -#include -#include - - -bool test_byte_manipulation(); -bool test_local_address_manipulation(); - - -INITTEST(); - -int main(int argc, char **argv) -{ - std::cerr << "libretroshare:pqi " << argv[0] << std::endl; - - test_byte_manipulation(); - - FINALREPORT("libretroshare Net Basics Tests"); - return TESTRESULT(); -} - - /* test 1: byte manipulation */ -bool test_byte_manipulation() -{ - uint64_t num1 = 0x0000000000000000ffULL; /* 255 */ - uint64_t num2 = 0x00000000000000ff00ULL; /* */ - - uint64_t n_num1 = htonll(num1); - uint64_t n_num2 = htonll(num2); - - uint64_t h_num1 = ntohll(n_num1); - uint64_t h_num2 = ntohll(n_num2); - - std::ostringstream out; - out << std::hex; - out << "num1: " << num1 << " netOrder: " << n_num1 << " hostOrder: " << h_num1 << std::endl; - out << "num2: " << num2 << " netOrder: " << n_num2 << " hostOrder: " << h_num2 << std::endl; - - std::cerr << out.str(); - - CHECK( num1 == h_num1 ); - CHECK( num2 == h_num2 ); - - REPORT("Test Byte Manipulation"); - - return true; -} - -const char * loopback_addrstr = "127.0.0.1"; -const char * localnet1_addrstr = "192.168.0.1"; -const char * localnet2_addrstr = "10.0.0.1"; -const char * localnet3_addrstr = "10.5.63.78"; -const char * localnet4_addrstr = "192.168.74.91"; - -bool test_bind_addr(struct sockaddr_in addr); - -bool test_bind_addr(struct sockaddr_in addr) -{ - - int err; - - std::cerr << "test_bind_addr()"; - std::cerr << std::endl; - - std::cerr << "\tAddress Family: " << (int) addr.sin_family; - std::cerr << std::endl; - std::cerr << "\tAddress: " << rs_inet_ntoa(addr.sin_addr); - std::cerr << std::endl; - std::cerr << "\tPort: " << ntohs(addr.sin_port); - std::cerr << std::endl; - - int sockfd = unix_socket(PF_INET, SOCK_STREAM, 0); - CHECK( 0 < sockfd ); - - if (0 != (err = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)))) - { - std::cerr << " Failed to Bind to Local Address!" << std::endl; - std::string out ; - showSocketError(out) ; - std::cerr << out << std::endl; - - FAILED("Couldn't Bind to socket"); - - return false; - } - - std::cerr << " Successfully Bound Socket to Address" << std::endl; - unix_close(sockfd); - - return true; -} - - diff --git a/libretroshare/src/tests/pqi/net_test1.cc b/libretroshare/src/tests/pqi/net_test1.cc deleted file mode 100644 index fe0f7e353..000000000 --- a/libretroshare/src/tests/pqi/net_test1.cc +++ /dev/null @@ -1,170 +0,0 @@ -/* - * libretroshare/src/pqi net_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * NETWORKING Test to check Big/Little Endian behaviour - * as well as socket behaviour - * - */ - -#include "pqi/pqinetwork.h" -#include "util/rsnet.h" -#include -#include -#include "util/utest.h" - -const char * loopback_addrstr = "127.0.0.1"; - -const char * localnet1_addrstr = "10.0.0.1"; -const char * localnet2_addrstr = "169.254.0.1"; -const char * localnet3_addrstr = "172.16.0.1"; -const char * localnet4_addrstr = "192.168.1.1"; - -const char * localnet5_addrstr = "10.4.28.34"; -const char * localnet6_addrstr = "169.254.1.81"; -const char * localnet7_addrstr = "172.20.9.201"; -const char * localnet8_addrstr = "192.168.1.254"; - -const char * external_addrstr = "74.125.19.99"; /* google */ -const char * invalid_addrstr = "AAA.BBB.256.256"; - -int test_isExternalNet(); -int test_isPrivateNet(); -int test_isLoopbackNet(); -int test_isValidNet(); - -INITTEST(); - -int main(int argc, char **argv) -{ - std::cerr << "net_test1" << std::endl; - - test_isExternalNet(); - test_isPrivateNet(); - test_isLoopbackNet(); - test_isValidNet(); - - FINALREPORT("net_test1"); - - return TESTRESULT(); -} - -int test_isExternalNet() -{ - struct in_addr loopback_addr; - struct in_addr localnet1_addr; - struct in_addr localnet2_addr; - struct in_addr localnet3_addr; - struct in_addr localnet4_addr; - struct in_addr external_addr; - struct in_addr invalid_addr; - struct in_addr invalid_addr2; - - inet_aton(loopback_addrstr, &loopback_addr); - inet_aton(localnet1_addrstr, &localnet1_addr); - inet_aton(localnet2_addrstr, &localnet2_addr); - inet_aton(localnet3_addrstr, &localnet3_addr); - inet_aton(localnet4_addrstr, &localnet4_addr); - inet_aton(external_addrstr, &external_addr); - invalid_addr.s_addr = 0; - invalid_addr2.s_addr = -1; - - CHECK(isExternalNet(&loopback_addr)==false); - CHECK(isExternalNet(&localnet1_addr)==false); - CHECK(isExternalNet(&localnet2_addr)==false); - CHECK(isExternalNet(&localnet3_addr)==false); - CHECK(isExternalNet(&localnet4_addr)==false); - CHECK(isExternalNet(&external_addr)==true); - CHECK(isExternalNet(&invalid_addr)==false); - CHECK(isExternalNet(&invalid_addr2)==false); - - REPORT("isExternalNet()"); - - return 1; -} - -int test_isPrivateNet() -{ - struct in_addr loopback_addr; - struct in_addr localnet1_addr; - struct in_addr localnet2_addr; - struct in_addr localnet3_addr; - struct in_addr localnet4_addr; - struct in_addr external_addr; - - inet_aton(loopback_addrstr, &loopback_addr); - inet_aton(localnet1_addrstr, &localnet1_addr); - inet_aton(localnet2_addrstr, &localnet2_addr); - inet_aton(localnet3_addrstr, &localnet3_addr); - inet_aton(localnet4_addrstr, &localnet4_addr); - inet_aton(external_addrstr, &external_addr); - - CHECK(isPrivateNet(&loopback_addr)==false); //loopback not considered a "private network" - CHECK(isPrivateNet(&localnet1_addr)==true); - CHECK(isPrivateNet(&localnet2_addr)==true); - CHECK(isPrivateNet(&localnet3_addr)==true); - CHECK(isPrivateNet(&localnet4_addr)==true); - CHECK(isPrivateNet(&external_addr)==false); - - REPORT("isPrivateNet()"); - - return 1; -} - -int test_isLoopbackNet() -{ - struct in_addr loopback_addr; - struct in_addr localnet1_addr; - struct in_addr external_addr; - - inet_aton(loopback_addrstr, &loopback_addr); - inet_aton(localnet1_addrstr, &localnet1_addr); - inet_aton(external_addrstr, &external_addr); - - CHECK(isLoopbackNet(&loopback_addr)==true); - CHECK(isLoopbackNet(&localnet1_addr)==false); - CHECK(isLoopbackNet(&external_addr)==false); - - REPORT("isLoopbackNet()"); - - return 1; -} - -int test_isValidNet() -{ - struct in_addr localnet1_addr; - struct in_addr invalid_addr; - - inet_aton(localnet1_addrstr, &localnet1_addr); - CHECK(isValidNet(&localnet1_addr)==true); - - CHECK(inet_aton(invalid_addrstr, &invalid_addr)==0); - std::cerr << rs_inet_ntoa(invalid_addr) << std::endl; - //CHECK(isValidNet(&invalid_addr)==false); - - REPORT("isValidNet()"); - - return 1; -} diff --git a/libretroshare/src/tests/pqi/p3connmgr_connect_test.cc b/libretroshare/src/tests/pqi/p3connmgr_connect_test.cc deleted file mode 100644 index 991fb99f3..000000000 --- a/libretroshare/src/tests/pqi/p3connmgr_connect_test.cc +++ /dev/null @@ -1,195 +0,0 @@ -/* - * libretroshare/src/test/pqi p3connmgr_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * p3connmgr test module. - * - * create a p3connmgr and run the following tests. - * 1) UDP test - * 2) UPNP test - * 3) ExtAddr test. - * 4) full reset in between. - * - */ - - -#include -#include -#include - - -#include "ppg_harness.h" -#include "conn_harness.h" - -#include "pqi/p3connmgr.h" -#include "pqi/authssltest.h" -#include "pqi/authgpgtest.h" - -#include "pqi/p3dhtmgr.h" -#include "upnp/upnphandler.h" - -#include "util/rsnet.h" -#include -#include -#include "util/utest.h" - -INITTEST(); - -/* generic startup test */ -#define MAX_TIME_SHORT_TEST 10 -#define MAX_TIME_BASIC_TEST 60 - -int run_connect_test(rstime_t timeout); - -/******************************************************* - * - * Test structure - *****************/ - -#define FLAG_UPNP 1 -#define FLAG_UDP 2 -#define FLAG_DHT 4 -#define FLAG_EXT 8 - -p3ConnectMgr *mConnMgr; -pqiNetAssistFirewall *mUpnpMgr = NULL; -p3DhtMgr *mDhtMgr = NULL; - -void createP3ConnMgr(std::string id, uint32_t testFlags) -{ - /* now add test children */ - { - std::cerr << "createP3ConnMgr()"; - std::cerr << std::endl; - } - - mConnMgr = new p3ConnectMgr(); - - mDhtMgr = NULL; //new p3DhtMgr(); - - /* setup status */ - //mConnMgr->setStatus(UPNP); -} - - -/* ACTUAL TEST */ -int main(int argc, char **argv) -{ - /* test p3connmgr net stuff */ - std::cerr << "p3connmgr_net_connect_test" << std::endl; - - // setup test authssl. - setAuthGPG(new AuthGPGtest()); - setAuthSSL(new AuthSSLtest()); - - createP3ConnMgr("abcd", 0); - pqiNetStatus status; - - setupPqiPersonGrpTH(); - - /* install ppg as a monitor */ - - mConnMgr->addMonitor(mPqiPersonGrpTH); - - - std::string peer1_gpgid = "PEERID0001_GPG__"; - std::string peer1_sslid = "PEERID0001_SSL__"; - - /* first test, add a single peer (no Addresses) */ - mConnMgr->addFriend(peer1_sslid, peer1_gpgid); - - run_connect_test(MAX_TIME_SHORT_TEST); - - mConnMgr->getNetStatus(status); - - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - - // Check that there have been... 1 reset / 0 connects / 1 listen - // per connect. - - REPORT("p3connmgr_connect_test() SINGLE PEER - NO Addresses"); - /* second test, add addresses for peer */ - - rstime_t now = time(NULL); - - pqiIpAddrSet peer1_tst2_addrs; - pqiIpAddress paddr; - inet_aton("192.168.1.1", &(paddr.mAddr.sin_addr)); - paddr.mAddr.sin_port = htons(6411); - paddr.mSeenTime = now - 10; - peer1_tst2_addrs.mLocal.updateIpAddressList(paddr); - - inet_aton("192.168.1.2", &(paddr.mAddr.sin_addr)); - paddr.mAddr.sin_port = htons(6422); - paddr.mSeenTime = now - 20; - peer1_tst2_addrs.mLocal.updateIpAddressList(paddr); - - inet_aton("23.56.25.1", &(paddr.mAddr.sin_addr)); - paddr.mAddr.sin_port = htons(6511); - paddr.mSeenTime = now - 30; - peer1_tst2_addrs.mExt.updateIpAddressList(paddr); - - inet_aton("23.56.25.2", &(paddr.mAddr.sin_addr)); - paddr.mAddr.sin_port = htons(6522); - paddr.mSeenTime = now - 40; - peer1_tst2_addrs.mExt.updateIpAddressList(paddr); - - mConnMgr->updateAddressList(peer1_sslid, peer1_tst2_addrs); - mConnMgr->retryConnect(peer1_sslid); - - run_connect_test(MAX_TIME_BASIC_TEST); - - // Check that there have been: - // 0 Listens / 0 resets. - // 0 connect attempts on UDP - // 4 connect attempts on TCP - // 0 connect attempts on TUNNEL - REPORT("p3connmgr_connect_test() SINGLE PEER - 4 Addresses"); - - /* third test, add an second peer with addresses */ - - /* fourth test, setup default action as connect */ - setDefaultTestConnectAction(TST_ACTION_SUCCESS); -} - -/* Generic restart test */ -int run_connect_test(rstime_t timeout) -{ - /* tick */ - rstime_t start = time(NULL); - bool extAddr = false; - - while ((start > time(NULL) - timeout) && (!extAddr)) - { - mConnMgr->tick(); - tickPqiPersonGrpTH(); - - sleep(1); - } - return 1; -} - - diff --git a/libretroshare/src/tests/pqi/p3connmgr_reset_test.cc b/libretroshare/src/tests/pqi/p3connmgr_reset_test.cc deleted file mode 100644 index d5485101a..000000000 --- a/libretroshare/src/tests/pqi/p3connmgr_reset_test.cc +++ /dev/null @@ -1,320 +0,0 @@ -/* - * libretroshare/src/test/pqi p3connmgr_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * p3connmgr test module. - * - * create a p3connmgr and run the following tests. - * 1) UDP test - * 2) UPNP test - * 3) ExtAddr test. - * 4) full reset in between. - * - */ - - -#include -#include -#include - - - - -//#include "pqi/p3connmgr.h" -#include "pqi/authssltest.h" -#include "pqi/authgpgtest.h" - -#include "pqi/p3dhtmgr.h" -#include "upnp/upnphandler_linux.h" - -#include "util/rsnet.h" -#include -#include -#include "util/utest.h" - -INITTEST(); - -/* generic startup test */ -#define MAX_TIME_BASIC_TEST 40 -#define MAX_TIME_UPNP_TEST 700 /* seems to take a while */ - -#define RESTART_EXPECT_NO_EXT_ADDR 1 -#define RESTART_EXPECT_EXTFINDER_ADDR 2 -#define RESTART_EXPECT_UPNP_ADDR 3 -#define RESTART_EXPECT_DHT_ADDR 4 - -int test_p3connmgr_restart_test(uint32_t expectState, rstime_t timeout); - - -#define RESET_VIA_LOCAL_ADDR 1 -#define RESET_VIA_REMOTE_ADDR 2 - - -int force_reset(uint32_t method); - - -/******************************************************* - * - * Test structure - *****************/ - -#define FLAG_UPNP 1 -#define FLAG_UDP 2 -#define FLAG_DHT 4 -#define FLAG_EXT 8 - -p3ConnectMgr *mConnMgr; -pqiNetAssistFirewall *mUpnpMgr = NULL; -p3DhtMgr *mDhtMgr = NULL; - -void createP3ConnMgr(std::string id, uint32_t testFlags) -{ - /* now add test children */ - { - std::cerr << "createP3ConnMgr()"; - std::cerr << std::endl; - } - - mConnMgr = new p3ConnectMgr(); - - mDhtMgr = NULL; //new p3DhtMgr(); - - /* setup status */ - //mConnMgr->setStatus(UPNP); -} - -void add_upnp() -{ - pqiNetAssistFirewall *mUpnpMgr = new upnphandler(); - mDhtMgr = NULL; //new p3DhtMgr(); - - //mConnMgr->addNetAssistConnect(1, mDhtMgr); - mConnMgr->addNetAssistFirewall(1, mUpnpMgr); -} - -void disableUpnp() -{ - //mConnMgr-> -} - - -void enableUpnp() -{ - - - -} - -void disableExtFinder() -{ - //mConnMgr-> - mConnMgr->setIPServersEnabled(false); -} - - -void enableExtFinder() -{ - mConnMgr->setIPServersEnabled(true); -} - - -/* ACTUAL TEST */ -int main(int argc, char **argv) -{ - /* test p3connmgr net stuff */ - std::cerr << "p3connmgr_net_restart_test" << std::endl; - - // setup test authssl. - setAuthGPG(new AuthGPGtest()); - setAuthSSL(new AuthSSLtest()); - - createP3ConnMgr("abcd", 0); - pqiNetStatus status; - - - /* first test, no Upnp / ExtFinder -> expect no Ext Address */ - mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UDP); - disableExtFinder(); - - mConnMgr->getNetStatus(status); - - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - test_p3connmgr_restart_test(RESTART_EXPECT_NO_EXT_ADDR, MAX_TIME_BASIC_TEST); - - REPORT("test_p3connmgr_restart_test()"); - - /* second test, add ExtFinder -> expect Ext Address */ - enableExtFinder(); - mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UDP); - force_reset(RESET_VIA_LOCAL_ADDR); - - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - test_p3connmgr_restart_test(RESTART_EXPECT_EXTFINDER_ADDR, MAX_TIME_BASIC_TEST); - - /* third test. disable ExtFinder again -> expect No Ext Address */ - disableExtFinder(); - mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UDP); - force_reset(RESET_VIA_LOCAL_ADDR); - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - test_p3connmgr_restart_test(RESTART_EXPECT_NO_EXT_ADDR, MAX_TIME_BASIC_TEST); - - - /* fourth test. enable Upnp -> expect Upnp Ext Address */ - add_upnp(); - enableUpnp(); - mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UPNP); - force_reset(RESET_VIA_LOCAL_ADDR); - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - - - test_p3connmgr_restart_test(RESTART_EXPECT_UPNP_ADDR, MAX_TIME_UPNP_TEST); - /* fifth test. disable Upnp -> expect No Ext Address */ - disableUpnp(); - mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UDP); - force_reset(RESET_VIA_LOCAL_ADDR); - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - - test_p3connmgr_restart_test(RESTART_EXPECT_NO_EXT_ADDR, MAX_TIME_BASIC_TEST); - /* sixth test. enable both Ext and Upnp -> expect UpnP Ext Address (prefered) */ - enableExtFinder(); - enableUpnp(); - mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UPNP); - force_reset(RESET_VIA_LOCAL_ADDR); - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - - test_p3connmgr_restart_test(RESTART_EXPECT_UPNP_ADDR, MAX_TIME_UPNP_TEST); - REPORT("test_p3connmgr_restart_test()"); - - FINALREPORT("p3connmgr_net_restart_test"); - - return TESTRESULT(); -} - -/****************************************************** - * - */ - -int force_reset(uint32_t method) -{ - /* force reset network */ - struct sockaddr_in tst_addr; - inet_aton("123.45.2.2", &(tst_addr.sin_addr)); - tst_addr.sin_port = ntohs(8461); - - mConnMgr->setLocalAddress(AuthSSL::getAuthSSL()->OwnId(), tst_addr); - - return 1; -} - -/* Generic restart test */ -int test_p3connmgr_restart_test(uint32_t expectState, rstime_t timeout) -{ - /* force reset network */ - struct sockaddr_in tst_addr; - inet_aton("123.45.2.2", &(tst_addr.sin_addr)); - tst_addr.sin_port = ntohs(8461); - - mConnMgr->setLocalAddress(AuthSSL::getAuthSSL()->OwnId(), tst_addr); - - /* tick */ - rstime_t start = time(NULL); - bool extAddr = false; - - while ((start > time(NULL) - timeout) && (!extAddr)) - { - mConnMgr->tick(); - - pqiNetStatus status; - mConnMgr->getNetStatus(status); - std::cerr << "test_p3connmgr_restart_test() Age: " << time(NULL) - start; - std::cerr << " netStatus:"; - std::cerr << std::endl; - status.print(std::cerr); - - if (status.mExtAddrOk) - { - std::cerr << "test_p3connmgr_restart_test() Got ExtAddr. Finished Restart."; - std::cerr << std::endl; - extAddr = true; - } - sleep(1); - } - - std::cerr << "test_p3connmgr_restart_test() Test Mode: " << expectState << " Complete"; - std::cerr << std::endl; - - pqiNetStatus status; - mConnMgr->getNetStatus(status); - status.print(std::cerr); - if (status.mExtAddrOk) - { - CHECK(isValidNet(&(status.mExtAddr.sin_addr))); - } - CHECK(isValidNet(&(status.mLocalAddr.sin_addr))); - - /* check expectState */ - switch(expectState) - { - default: - case RESTART_EXPECT_NO_EXT_ADDR: - CHECK(status.mLocalAddrOk == true); - CHECK(status.mExtAddrOk == false); - CHECK(status.mExtAddrStableOk == false); - CHECK(status.mUpnpOk == false); - CHECK(status.mDhtOk == false); - break; - - case RESTART_EXPECT_EXTFINDER_ADDR: - CHECK(status.mLocalAddrOk == true); - CHECK(status.mExtAddrOk == true); - CHECK(status.mExtAddrStableOk == false); - CHECK(status.mUpnpOk == false); - break; - - case RESTART_EXPECT_UPNP_ADDR: - CHECK(status.mLocalAddrOk == true); - CHECK(status.mExtAddrOk == true); - CHECK(status.mExtAddrStableOk == true); - CHECK(status.mUpnpOk == true); - break; - - case RESTART_EXPECT_DHT_ADDR: - CHECK(status.mLocalAddrOk == true); - CHECK(status.mExtAddrOk == false); - CHECK(status.mUpnpOk == false); - CHECK(status.mDhtOk == true); - break; - } - - return 1; -} - - diff --git a/libretroshare/src/tests/pqi/pkt_test.cc b/libretroshare/src/tests/pqi/pkt_test.cc deleted file mode 100644 index 49f6edd47..000000000 --- a/libretroshare/src/tests/pqi/pkt_test.cc +++ /dev/null @@ -1,109 +0,0 @@ -/* - * libretroshare/src/tests/pqi pkt_tst.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2009-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pkt_tst. - * - * This is not testing serialisation.... so we only need 1 type of packet. - * using FileData packets - as these can have arbitary size. - */ - -#include "pkt_test.h" -#include - -uint8_t testdata[TEST_DATA_LEN]; - -void generate_test_data() -{ - srand(1); - - int i; - for(i = 0; i < TEST_DATA_LEN; i++) - { - testdata[i] = rand() % 256; - } -} - -bool check_data(void *data_in, int len) -{ - int i; - uint8_t *data = (uint8_t *) data_in; - - for(i = 0; i < len; i++) - { - if (data[i] != testdata[i]) - { - std::cerr << "check_data() Different Byte: " << i; - std::cerr << std::endl; - - return false; - } - } - return true; -} - -RsFileData *gen_packet(int datasize, std::string pid) -{ - /* generate some packets */ - RsFileData *data = new RsFileData(); - data->fd.file.filesize = TEST_PKT_SIZE; - data->fd.file.hash = TEST_PKT_HASH; - data->fd.file_offset = TEST_PKT_OFFSET; - data->fd.binData.setBinData(testdata, datasize); - data->PeerId(pid); - - return data; -} - -bool check_packet(RsFileData *pkt) -{ - if (pkt->fd.file.filesize != TEST_PKT_SIZE) - { - std::cerr << "check_packet() FileSize Different"; - std::cerr << std::endl; - - return false; - } - - if (pkt->fd.file.hash != TEST_PKT_HASH) - { - std::cerr << "check_packet() FileHash Different"; - std::cerr << std::endl; - - return false; - } - - if (pkt->fd.file_offset != TEST_PKT_OFFSET) - { - std::cerr << "check_packet() FileOffset Different"; - std::cerr << std::endl; - - return false; - } - - return check_data(pkt->fd.binData.bin_data, pkt->fd.binData.bin_len); -} - - diff --git a/libretroshare/src/tests/pqi/pkt_test.h b/libretroshare/src/tests/pqi/pkt_test.h deleted file mode 100644 index 072274574..000000000 --- a/libretroshare/src/tests/pqi/pkt_test.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef RS_TEST_PACKETS -#define RS_TEST_PACKETS -/* - * libretroshare/src/tests/pqi pkt_tst.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2009-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pkt_tst. - * - * This is not testing serialisation.... so we only need 1 type of packet. - * using FileData packets - as these can have arbitary size. - */ - -#include "serialiser/rsbaseitems.h" - -#define TEST_PKT_SIZE 1234567 -#define TEST_PKT_HASH "HASHTESTHASH" -#define TEST_PKT_OFFSET 1234 - -#define TEST_DATA_LEN (1024 * 1024) // MB - -void generate_test_data(); -bool check_data(void *data_in, int len); - -RsFileData *gen_packet(int datasize, std::string pid); -bool check_packet(RsFileData *pkt); - - -#endif diff --git a/libretroshare/src/tests/pqi/ppg_harness.cc b/libretroshare/src/tests/pqi/ppg_harness.cc deleted file mode 100644 index 58b89a971..000000000 --- a/libretroshare/src/tests/pqi/ppg_harness.cc +++ /dev/null @@ -1,141 +0,0 @@ -/* - * libretroshare/src/test/pqi pqiperson_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pqiperson acts as the wrapper for all connection methods to a single peer. - * - * This test creates, a pqiperson and simulates connections, disconnections. - * packets passing through. - * - */ - - -#include "conn_harness.h" -#include "ppg_harness.h" - -#include "pqi/pqiperson.h" -#include "pqi/pqibin.h" - -#include "util/rsnet.h" -#include -#include - -/******************************************************* - * - * Test structure - *****************/ - - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg); - -pqipersongrpTestHarness *mPqiPersonGrpTH = NULL; - -void setupPqiPersonGrpTH() -{ - mPqiPersonGrpTH = new pqipersongrpTestHarness(NULL, 0); -} - -void tickPqiPersonGrpTH() -{ - mPqiPersonGrpTH->tick(); -} - - -pqipersongrpTestHarness::pqipersongrpTestHarness(SecurityPolicy *pol, unsigned long flags) - :pqipersongrp(pol, flags) -{ - return; -} - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -pqilistener *pqipersongrpTestHarness::createListener(struct sockaddr_in laddr) -{ - return new pqilistener(); -} - -pqiperson *pqipersongrpTestHarness::createPerson(std::string id, pqilistener *listener) -{ - return createTestPerson(id, this); -} - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ - - - - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg) -{ - /* now add test children */ - { - std::cerr << "createTestPerson()"; - std::cerr << std::endl; - } - - pqiperson *pqip = new pqiperson(id, ppg); - - /* construct the serialiser .... - * Needs: - * * FileItem - * * FileData - * * ServiceGeneric - */ - - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - rss->addSerialType(new RsCacheItemSerialiser()); - rss->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy1 = new NetBinDummy(pqip, id, PQI_CONNECT_TCP); - pqiconnect *pqisc = new testConnect(rss, dummy1); - addTestConnect(pqisc, pqip); - pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc); - - RsSerialiser *rss2 = new RsSerialiser(); - rss2->addSerialType(new RsFileItemSerialiser()); - rss2->addSerialType(new RsCacheItemSerialiser()); - rss2->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy2 = new NetBinDummy(pqip, id, PQI_CONNECT_TUNNEL); - pqiconnect *pqicontun = new testConnect(rss2, dummy2); - addTestConnect(pqicontun, pqip); - pqip -> addChildInterface(PQI_CONNECT_TUNNEL, pqicontun); - - - RsSerialiser *rss3 = new RsSerialiser(); - rss3->addSerialType(new RsFileItemSerialiser()); - rss3->addSerialType(new RsCacheItemSerialiser()); - rss3->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy3 = new NetBinDummy(pqip, id, PQI_CONNECT_UDP); - pqiconnect *pqiusc = new testConnect(rss3, dummy3); - addTestConnect(pqiusc, pqip); - pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc); - - return pqip; -} - - - - diff --git a/libretroshare/src/tests/pqi/ppg_harness.h b/libretroshare/src/tests/pqi/ppg_harness.h deleted file mode 100644 index 85e664548..000000000 --- a/libretroshare/src/tests/pqi/ppg_harness.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef PPG_HARNESS_TEST_H -#define PPG_HARNESS_TEST_H - -/* - * libretroshare/src/test/pqi ppg_harness.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * test harness for pqipersongrp / pqihandler. - */ - -#include "pqi/pqiperson.h" -#include "pqi/pqipersongrp.h" - -/******************************************************* - * - * Test structure - *****************/ - -void setupPqiPersonGrpTH(); -void tickPqiPersonGrpTH(); - -class pqipersongrpTestHarness; -extern pqipersongrpTestHarness *mPqiPersonGrpTH; - -class pqipersongrpTestHarness: public pqipersongrp -{ - public: - pqipersongrpTestHarness(SecurityPolicy *pol, unsigned long flags); - - protected: - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -virtual pqilistener *createListener(struct sockaddr_in laddr); -virtual pqiperson *createPerson(std::string id, pqilistener *listener); - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -}; - -#endif diff --git a/libretroshare/src/tests/pqi/pqiarchive_test.cc b/libretroshare/src/tests/pqi/pqiarchive_test.cc deleted file mode 100644 index abe88bab7..000000000 --- a/libretroshare/src/tests/pqi/pqiarchive_test.cc +++ /dev/null @@ -1,130 +0,0 @@ -/* - * libretroshare/src/tests/pqi pqiarchive_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2009-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pqiarchive test. - * - * This is not testing serialisation.... so we only need 1 type of packet. - * using FileData packets - as these can have arbitary size. - */ - -#include "pqi/pqiarchive.h" -#include "pqi/pqibin.h" - -#include "serialiser/rsbaseitems.h" - -#include "util/rsnet.h" -#include -#include -#include "util/utest.h" - -#include "pkt_test.h" - -INITTEST(); - -int test_pqiarchive_generate(); - -int main(int argc, char **argv) -{ - std::cerr << "pqiarchive_test" << std::endl; - - generate_test_data(); - - test_pqiarchive_generate(); - - FINALREPORT("pqiarchive_test"); - - return TESTRESULT(); -} - -const char *archive_fname = "/tmp/rs_tst_archive.tmp"; - -int test_pqiarchive_generate() -{ - - std::string pid = "123456789012345678901234567890ZZ"; - /* create a pqiarchive */ - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - - int flags = BIN_FLAGS_WRITEABLE; - BinInterface *bio_in = new BinFileInterface(archive_fname, flags); - - int bio_flagsin = flags; - pqiarchive *pqia = new pqiarchive(rss, bio_in, bio_flagsin); - CHECK(pqia != NULL); - - int i; - for(i = 10; i < TEST_DATA_LEN; i = (int) (i * 1.1)) - { - RsFileData *pkt = gen_packet(i, pid); - pqia->SendItem(pkt); - pqia->tick(); - } - - /* close it up */ - delete pqia; - - /* setup read */ - flags = BIN_FLAGS_READABLE; - - rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - - bio_in = new BinFileInterface(archive_fname, flags); - bio_flagsin = flags; - pqia = new pqiarchive(rss, bio_in, bio_flagsin); - - for(i = 10; i < TEST_DATA_LEN; i = (int) (i * 1.1)) - //for(i = 10; i < TEST_DATA_LEN; i += 111) - { - RsItem *pkt = pqia->GetItem(); - pqia->tick(); - - /* check the packet */ - RsFileData *data = dynamic_cast(pkt); - CHECK(data != NULL); - if (data) - { - CHECK(data->fd.binData.bin_len == i); - CHECK(check_packet(data) == true); - delete data; - } - } - - /* if there are anymore packets -> error! */ - for(i = 0; i < 1000; i++) - { - RsItem *pkt = pqia->GetItem(); - CHECK(pkt == NULL); - } - - REPORT("pqiarchive_generate()"); - - return 1; -} - - - diff --git a/libretroshare/src/tests/pqi/pqiipset_test.cc b/libretroshare/src/tests/pqi/pqiipset_test.cc deleted file mode 100644 index 893fc5223..000000000 --- a/libretroshare/src/tests/pqi/pqiipset_test.cc +++ /dev/null @@ -1,157 +0,0 @@ -/* - * libretroshare/src/test/pqi pqiipset_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * NETWORKING Test to check Big/Little Endian behaviour - * as well as socket behaviour - * - */ - -#include "util/utest.h" - -#include "pqi/pqiipset.h" -#include "pqi/pqinetwork.h" -#include "util/rsnet.h" -#include -#include - - -bool test_addr_list(); - - -INITTEST(); - -int main(int argc, char **argv) -{ - std::cerr << "libretroshare:pqi " << argv[0] << std::endl; - - test_addr_list(); - - FINALREPORT("libretroshare pqiipset Tests"); - return TESTRESULT(); -} - - /* test 1: byte manipulation */ -bool test_addr_list() -{ - pqiIpAddress addr; - pqiIpAddrList list; - - for(int i = 100; i < 150; i++) - { - std::ostringstream out; - out << "192.168.2." << i; - inet_aton(out.str().c_str(), &(addr.mAddr.sin_addr)); - addr.mAddr.sin_port = htons(7812); - addr.mSeenTime = time(NULL) - i; - - list.updateIpAddressList(addr); - - if (i < 100 + 4) - { - /* check that was added to the back */ - CHECK(list.mAddrs.back().mSeenTime == addr.mSeenTime); - CHECK(list.mAddrs.back().mAddr.sin_addr.s_addr == addr.mAddr.sin_addr.s_addr); - CHECK(list.mAddrs.back().mAddr.sin_port == addr.mAddr.sin_port); - } - else - { - /* check that wasn't added to the back */ - CHECK(list.mAddrs.back().mSeenTime != addr.mSeenTime); - CHECK(list.mAddrs.back().mAddr.sin_addr.s_addr != addr.mAddr.sin_addr.s_addr); - } - } - - /* print out the list */ - std::cerr << "IpAddressList (expect variation: 192.168.2.[100-103]:7812)"; - std::cerr << std::endl; - std::string out ; - list.printIpAddressList(out) ; - std::cerr << out << std::endl; - - const uint32_t expectedListSize = 4; - CHECK(list.mAddrs.size() == expectedListSize); - - rstime_t min_time = time(NULL) - expectedListSize + 100; - - /* expect the most recent ones to appear */ - std::list::iterator it; - for(it = list.mAddrs.begin(); it != list.mAddrs.end(); it++) - { - CHECK(it->mSeenTime < min_time); - } - - /* now add some with same address + port */ - { - std::ostringstream out; - out << "192.168.2.200"; - inet_aton(out.str().c_str(), &(addr.mAddr.sin_addr)); - addr.mAddr.sin_port = htons(8812); - } - - /* make sure it more recent than the previous ones */ - for(int i = 99; i > 89; i--) - { - addr.mSeenTime = time(NULL) - i; - list.updateIpAddressList(addr); - - /* check that was added to the front */ - CHECK(list.mAddrs.front().mSeenTime == addr.mSeenTime); - CHECK(list.mAddrs.front().mAddr.sin_addr.s_addr == addr.mAddr.sin_addr.s_addr); - CHECK(list.mAddrs.front().mAddr.sin_port == addr.mAddr.sin_port); - } - - /* print out the list */ - std::cerr << "IpAddressList (first item to be 192.168.2.200:8812)"; - std::cerr << std::endl; - list.printIpAddressList(out) ; - std::cerr << out<< std::endl; - - /* now add with the different ports */ - - for(int i = 70; i > 50; i--) - { - addr.mAddr.sin_port = htons(8000 + i); - addr.mSeenTime = time(NULL) - i; - - list.updateIpAddressList(addr); - - /* check that was added to the back */ - CHECK(list.mAddrs.front().mSeenTime == addr.mSeenTime); - CHECK(list.mAddrs.front().mAddr.sin_addr.s_addr == addr.mAddr.sin_addr.s_addr); - CHECK(list.mAddrs.front().mAddr.sin_port == addr.mAddr.sin_port); - - } - - std::cerr << "IpAddressList (expect same Ip, but variations in port)"; - std::cerr << std::endl; - list.printIpAddressList(out) ; - std::cerr << out < -#include -#include "util/utest.h" - -INITTEST(); - -int test_person_basic_reset(); -int test_person_basic_listen(); - - -int main(int argc, char **argv) -{ - std::cerr << "pqiperson_test" << std::endl; - - test_person_basic_reset(); - test_person_basic_listen(); - - FINALREPORT("pqiperson_test"); - - return TESTRESULT(); -} - -/****************************************************** - * - * tests() - * - **** ensure that functions call children - * pqiperson::reset() - * pqiperson::listen() - * pqiperson::stoplistening() - * - * - * pqiperson::connect(...) - * -> check that gets through to children. - * -> check that cannot have simultaneous connections. - * -> - * - */ - - -/******************************************************* - * - * Test structure - *****************/ - -#define NUM_CHILDREN 3 - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg) -{ - /* now add test children */ - { - std::cerr << "createTestPerson()"; - std::cerr << std::endl; - } - - pqiperson *pqip = new pqiperson(id, ppg); - - /* construct the serialiser .... - * Needs: - * * FileItem - * * FileData - * * ServiceGeneric - */ - - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - rss->addSerialType(new RsCacheItemSerialiser()); - rss->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy1 = new NetBinDummy(pqip, id, PQI_CONNECT_TCP); - pqiconnect *pqisc = new testConnect(rss, dummy1); - addTestConnect(pqisc); - pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc); - - RsSerialiser *rss2 = new RsSerialiser(); - rss2->addSerialType(new RsFileItemSerialiser()); - rss2->addSerialType(new RsCacheItemSerialiser()); - rss2->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy2 = new NetBinDummy(pqip, id, PQI_CONNECT_TUNNEL); - pqiconnect *pqicontun = new testConnect(rss2, dummy2); - addTestConnect(pqicontun); - pqip -> addChildInterface(PQI_CONNECT_TUNNEL, pqicontun); - - - RsSerialiser *rss3 = new RsSerialiser(); - rss3->addSerialType(new RsFileItemSerialiser()); - rss3->addSerialType(new RsCacheItemSerialiser()); - rss3->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy3 = new NetBinDummy(pqip, id, PQI_CONNECT_UDP); - pqiconnect *pqiusc = new testConnect(rss3, dummy3); - addTestConnect(pqiusc); - pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc); - - return pqip; -} - - -/* First Sets of Tests are very basic: - * reset() - * connect() - * listen() / stoplistening() - * disconnect() - */ - -int test_person_basic_reset() -{ - /* reset test */ - resetTestConnects(); - - /* create test person */ - std::string id = "12345678901234567890123456789012"; - pqipersongrp *ppg = NULL; - pqiperson *person = createTestPerson(id, ppg); - - /* reset person */ - person->reset(); - - /* count number of resets */ - CHECK(NUM_CHILDREN == testCounter); - - int i; - for(i = 0; i < NUM_CHILDREN; i++) - { - CHECK(testResetTimes[i].size() == 1); - CHECK(testConnectState[i] == 0); - CHECK(testConnectTimes[i].size() == 0); - } - - /* clean up */ - delete person; - - REPORT("test_person_basic_reset()"); - - return 1; -} - - -int test_person_basic_listen() -{ - /* reset test */ - resetTestConnects(); - - /* create test person */ - std::string id = "12345678901234567890123456789012"; - pqipersongrp *ppg = NULL; - pqiperson *person = createTestPerson(id, ppg); - - /* reset person */ - person->listen(); - - /* count number of resets */ - CHECK(NUM_CHILDREN == testCounter); - - int i; - for(i = 0; i < NUM_CHILDREN; i++) - { - CHECK(testResetTimes[i].size() == 0); - CHECK(testConnectTimes[i].size() == 0); - CHECK(testConnectState[i] == TST_STATE_LISTEN); - } - - person->stoplistening(); - - for(i = 0; i < NUM_CHILDREN; i++) - { - CHECK(testResetTimes[i].size() == 0); - CHECK(testConnectTimes[i].size() == 0); - CHECK(testConnectState[i] == 0); - } - - /* clean up */ - delete person; - - REPORT("test_person_basic_listen()"); - - return 1; -} - - - - diff --git a/libretroshare/src/tests/pqi/pqipersongrp_test.cc b/libretroshare/src/tests/pqi/pqipersongrp_test.cc deleted file mode 100644 index d189c94fc..000000000 --- a/libretroshare/src/tests/pqi/pqipersongrp_test.cc +++ /dev/null @@ -1,266 +0,0 @@ -/* - * libretroshare/src/test/pqi pqiperson_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pqiperson acts as the wrapper for all connection methods to a single peer. - * - * This test creates, a pqiperson and simulates connections, disconnections. - * packets passing through. - * - */ - - - - - - -#include "pqi/pqiperson.h" -#include "pqi/pqibin.h" - -#include "testconnect.h" - -#include "util/rsnet.h" -#include -#include -#include "util/utest.h" - -INITTEST(); - -int test_person_basic_reset(); -int test_person_basic_listen(); - - -int main(int argc, char **argv) -{ - std::cerr << "pqiperson_test" << std::endl; - - test_person_basic_reset(); - test_person_basic_listen(); - - FINALREPORT("pqiperson_test"); - - return TESTRESULT(); -} - -/****************************************************** - * - * tests() - * - **** ensure that functions call children - * pqiperson::reset() - * pqiperson::listen() - * pqiperson::stoplistening() - * - * - * pqiperson::connect(...) - * -> check that gets through to children. - * -> check that cannot have simultaneous connections. - * -> - * - */ - - -/******************************************************* - * - * Test structure - *****************/ - -#define NUM_CHILDREN 3 - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg); - -class pqipersongrpTestHarness: public pqipersongrp -{ - public: - pqipersongrpTestHarness(SecurityPolicy *pol, unsigned long flags) - :pqipersongrp(pol, flags) - { - return; - } - - protected: - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -virtual pqilistener *createListener(struct sockaddr_in laddr) -{ - return new pqilistener(laddr); -} - -virtual pqiperson *createPerson(std::string id, pqilistener *listener) -{ - return createTestPerson(id, this); -} - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -}; - - - - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg) -{ - /* now add test children */ - { - std::cerr << "createTestPerson()"; - std::cerr << std::endl; - } - - pqiperson *pqip = new pqiperson(id, ppg); - - /* construct the serialiser .... - * Needs: - * * FileItem - * * FileData - * * ServiceGeneric - */ - - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - rss->addSerialType(new RsCacheItemSerialiser()); - rss->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy1 = new NetBinDummy(pqip, id, PQI_CONNECT_TCP); - pqiconnect *pqisc = new testConnect(rss, dummy1); - addTestConnect(pqisc); - pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc); - - RsSerialiser *rss2 = new RsSerialiser(); - rss2->addSerialType(new RsFileItemSerialiser()); - rss2->addSerialType(new RsCacheItemSerialiser()); - rss2->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy2 = new NetBinDummy(pqip, id, PQI_CONNECT_TUNNEL); - pqiconnect *pqicontun = new testConnect(rss2, dummy2); - addTestConnect(pqicontun); - pqip -> addChildInterface(PQI_CONNECT_TUNNEL, pqicontun); - - - RsSerialiser *rss3 = new RsSerialiser(); - rss3->addSerialType(new RsFileItemSerialiser()); - rss3->addSerialType(new RsCacheItemSerialiser()); - rss3->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy3 = new NetBinDummy(pqip, id, PQI_CONNECT_UDP); - pqiconnect *pqiusc = new testConnect(rss3, dummy3); - addTestConnect(pqiusc); - pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc); - - return pqip; -} - - -/* First Sets of Tests are very basic: - * reset() - * connect() - * listen() / stoplistening() - * disconnect() - */ - -int test_person_basic_reset() -{ - /* reset test */ - resetTestConnects(); - - /* create test person */ - std::string id = "12345678901234567890123456789012"; - - pqipersongrp *ppg = pqipersongrpTestHarness(NULL, 0); - - /* setup fake other bits */ - - - /* add peers - and watch it all happen! */ - - - - pqiperson *person = createTestPerson(id, ppg); - - /* reset person */ - person->reset(); - - /* count number of resets */ - CHECK(NUM_CHILDREN == testCounter); - - int i; - for(i = 0; i < NUM_CHILDREN; i++) - { - CHECK(testResetTimes[i].size() == 1); - CHECK(testConnectState[i] == 0); - CHECK(testConnectTimes[i].size() == 0); - } - - /* clean up */ - delete person; - - REPORT("test_person_basic_reset()"); - - return 1; -} - - -int test_person_basic_listen() -{ - /* reset test */ - resetTestConnects(); - - /* create test person */ - std::string id = "12345678901234567890123456789012"; - pqipersongrp *ppg = NULL; - pqiperson *person = createTestPerson(id, ppg); - - /* reset person */ - person->listen(); - - /* count number of resets */ - CHECK(NUM_CHILDREN == testCounter); - - int i; - for(i = 0; i < NUM_CHILDREN; i++) - { - CHECK(testResetTimes[i].size() == 0); - CHECK(testConnectTimes[i].size() == 0); - CHECK(testConnectState[i] == TST_STATE_LISTEN); - } - - person->stoplistening(); - - for(i = 0; i < NUM_CHILDREN; i++) - { - CHECK(testResetTimes[i].size() == 0); - CHECK(testConnectTimes[i].size() == 0); - CHECK(testConnectState[i] == 0); - } - - /* clean up */ - delete person; - - REPORT("test_person_basic_listen()"); - - return 1; -} - - - - diff --git a/libretroshare/src/tests/pqi/pqiqos_test.cc b/libretroshare/src/tests/pqi/pqiqos_test.cc deleted file mode 100644 index eea4846ae..000000000 --- a/libretroshare/src/tests/pqi/pqiqos_test.cc +++ /dev/null @@ -1,191 +0,0 @@ -#include "util/utest.h" - -#include -#include -#include -#include "serialiser/rsserial.h" -#include "util/rsrandom.h" -#include "pqi/pqiqos.h" - -INITTEST(); - -// Class of RsItem with ids to check order -// -class testRawItem: public RsItem -{ - public: - testRawItem() - : RsItem(0,0,0), _id(_static_id++) - { - } - - virtual void clear() {} - virtual std::ostream& print(std::ostream& o, uint16_t) { return o ; } - - static const uint32_t rs_rawitem_size = 10 ; - static uint64_t _static_id ; - uint64_t _id ; -}; -uint64_t testRawItem::_static_id = 1; - -int main() -{ - float alpha = 3 ; - int nb_levels = 10 ; - - ////////////////////////////////////////////// - // 1 - Test consistency of output and order // - ////////////////////////////////////////////// - { - pqiQoS qos(nb_levels,alpha) ; - - // 0 - Fill the queue with fake RsItem. - // - static const uint32_t pushed_items = 10000 ; - - for(uint32_t i=0;isetPriorityLevel(i % nb_levels) ; - - qos.in_rsItem(item,item->priority_level()) ; - } - std::cerr << "QOS is filled with: " << std::endl; - qos.print() ; - - // 1 - checks that all items eventually got out in the same order for - // items of equal priority - // - uint32_t poped = 0; - std::vector last_ids(nb_levels,0) ; - - while(testRawItem *item = static_cast(qos.out_rsItem())) - { - CHECK(last_ids[item->priority_level()] < item->_id) ; - - last_ids[item->priority_level()] = item->_id ; - delete item, ++poped ; - } - - std::cerr << "Push " << pushed_items << " items, poped " << poped << std::endl; - - if(pushed_items != poped) - { - std::cerr << "Queues are: " << std::endl; - qos.print() ; - } - CHECK(pushed_items == poped) ; - } - - ////////////////////////////////////////////////// - // 2 - tests proportionality // - ////////////////////////////////////////////////// - { - // Now we feed the QoS, and check that items get out with probability proportional - // to the priority - // - pqiQoS qos(nb_levels,alpha) ; - - std::cerr << "Feeding 10^6 packets to the QoS service." << std::endl; - for(int i=0;i<1000000;++i) - { - if(i%10000 == 0) - { - fprintf(stderr,"%1.2f %% completed.\r",i/(float)1000000*100.0f) ; - fflush(stderr) ; - } - testRawItem *item = new testRawItem ; - - switch(i%5) - { - case 0: item->setPriorityLevel( 1 ) ; break ; - case 1: item->setPriorityLevel( 4 ) ; break ; - case 2: item->setPriorityLevel( 6 ) ; break ; - case 3: item->setPriorityLevel( 7 ) ; break ; - case 4: item->setPriorityLevel( 8 ) ; break ; - } - - qos.in_rsItem(item,item->priority_level()) ; - } - - // Now perform stats on outputs for the 10000 first elements - - std::vector hist(nb_levels,0) ; - - for(uint32_t i=0;i<10000;++i) - { - testRawItem *item = static_cast(qos.out_rsItem()) ; - hist[item->priority_level()]++ ; - delete item ; - } - - std::cerr << "Histogram: " ; - for(uint32_t i=0;isetPriorityLevel(i%nb_levels) ; - qos.in_rsItem(item,item->priority_level()) ; - } - - // pop a random number of packets out - - std::vector last_ids(nb_levels,0) ; - - for(uint32_t i=0;i(qos.out_rsItem()) ; - - if(item == NULL) - { - std::cerr << "Null output !" << std::endl; - break ; - } - - CHECK(last_ids[item->priority_level()] < item->_id) ; - - last_ids[item->priority_level()] = item->_id ; - delete item ; - } - - // print some info - static rstime_t last = 0 ; - if(now > last) - { - qos.print() ; - last = now ; - } - } - } - - FINALREPORT("pqiqos_test"); - return TESTRESULT() ; -} - - diff --git a/libretroshare/src/tests/pqi/testconnect.cc b/libretroshare/src/tests/pqi/testconnect.cc deleted file mode 100644 index 0dc019c18..000000000 --- a/libretroshare/src/tests/pqi/testconnect.cc +++ /dev/null @@ -1,186 +0,0 @@ -/* - * libretroshare/src/test/pqi testconnect.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pqiperson acts as the wrapper for all connection methods to a single peer. - * - * This test creates, a pqiperson and simulates connections, disconnections. - * packets passing through. - * - */ - - -#include "testconnect.h" -#include "pqi/pqibin.h" -#include -#include - -/******************************************************* - * - * Test structure - *****************/ - - -#define NUM_CONN_MAX 10 -#define NUM_CHILDREN 3 - -#define TST_STATE_CONNECT 0x0001 -#define TST_STATE_LISTEN 0x0002 - -/* static test variables */ -uint32_t testCounter = 0; -pqiconnect *testConnectPointer[NUM_CONN_MAX]; -uint32_t testConnectState[NUM_CONN_MAX]; -std::list testConnectTimes[NUM_CONN_MAX]; -std::list testConnectAddrs[NUM_CONN_MAX]; - -std::list testResetState[NUM_CONN_MAX]; -std::list testResetTimes[NUM_CONN_MAX]; - -uint32_t findWhichConnect(pqiconnect *conn) -{ - int i; - for(i = 0; i < NUM_CONN_MAX; i++) - { - if (testConnectPointer[i] == conn) - { - return i; - } - } - // error. - std::cerr << "Connect Missing" << std::endl; - exit(1); - return 0; -} - -void addTestConnect(pqiconnect *pqi) -{ - testConnectPointer[testCounter] = pqi; - testConnectState[testCounter] = 0; - testCounter++; - if (testCounter > NUM_CONN_MAX) - { - std::cerr << "Too Many Connects" << std::endl; - exit(1); - } -} - -void resetTestConnects() -{ - testCounter = 0; - int i; - for(i = 0; i < NUM_CONN_MAX; i++) - { - testConnectAddrs[i].clear(); - testConnectTimes[i].clear(); - testResetState[i].clear(); - testResetTimes[i].clear(); - } -} - - -testConnect::testConnect(RsSerialiser *rss, NetBinInterface *ni_in) - :pqiconnect(rss, ni_in) -{ - -} - -testConnect::~testConnect() -{ - return; -} - - /* dummyConnect */ -int testConnect::connect(struct sockaddr_in raddr) -{ - int cidx = findWhichConnect(this); - rstime_t now = time(NULL); - - testConnectState[cidx] |= TST_STATE_CONNECT; - testConnectTimes[cidx].push_back(now); - testConnectAddrs[cidx].push_back(raddr); - - std::cerr << "testConnect[" << cidx << "].connect() called"; - std::cerr << std::endl; - return 0; -} - -int testConnect::listen() -{ - int cidx = findWhichConnect(this); - testConnectState[cidx] |= TST_STATE_LISTEN; - std::cerr << "testConnect[" << cidx << "].listen() called"; - std::cerr << std::endl; - return 1; -} - -int testConnect::stoplistening() -{ - int cidx = findWhichConnect(this); - testConnectState[cidx] &= ~TST_STATE_LISTEN; - std::cerr << "testConnect[" << cidx << "].stoplistening() called"; - std::cerr << std::endl; - return 1; -} - -int testConnect::reset() -{ - int cidx = findWhichConnect(this); - rstime_t now = time(NULL); - - // reset everything except listening. - testResetState[cidx].push_back(testConnectState[cidx]); - testResetTimes[cidx].push_back(now); - testConnectState[cidx] &= TST_STATE_LISTEN; - - std::cerr << "testConnect[" << cidx << "].reset() called"; - std::cerr << std::endl; - return 1; -} - -// leave this as is virtual int disconnect() { return ni -> reset(); } - -bool testConnect::connect_parameter(uint32_t type, uint32_t value) -{ - int cidx = findWhichConnect(this); - //testConnectState[cidx] |= TST_STATE_LISTEN; - std::cerr << "testConnect[" << cidx << "].connect_parameter() called"; - std::cerr << std::endl; - return true; -} - -int testConnect::getConnectAddress(struct sockaddr_in &raddr) -{ - int cidx = findWhichConnect(this); - if (testConnectAddrs[cidx].size() > 0) - { - raddr = testConnectAddrs[cidx].back(); - return 1; - } - std::cerr << "testConnect[" << cidx << "].getConnectAddress() called"; - std::cerr << std::endl; - return 0; -} - diff --git a/libretroshare/src/tests/pqi/testconnect.h b/libretroshare/src/tests/pqi/testconnect.h deleted file mode 100644 index c0eda479c..000000000 --- a/libretroshare/src/tests/pqi/testconnect.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef TEST_PQICONNECT_H -#define TEST_PQICONNECT_H - -/* - * libretroshare/src/test/pqi testconnect.h - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "pqi/pqiperson.h" -//#include "pqi/pqibin.h" -#include "util/rsnet.h" - -/******************************************************* - * - * Test structure - *****************/ - - -#define NUM_CONN_MAX 10 - -#define TST_STATE_CONNECT 0x0001 -#define TST_STATE_LISTEN 0x0002 - -/* static test variables */ -extern uint32_t testCounter; -extern pqiconnect *testConnectPointer[NUM_CONN_MAX]; -extern uint32_t testConnectState[NUM_CONN_MAX]; -extern std::list testConnectTimes[NUM_CONN_MAX]; -extern std::list testConnectAddrs[NUM_CONN_MAX]; - -extern std::list testResetState[NUM_CONN_MAX]; -extern std::list testResetTimes[NUM_CONN_MAX]; - -uint32_t findWhichConnect(pqiconnect *conn); -void addTestConnect(pqiconnect *pqi); -void resetTestConnects(); - -class testConnect: public pqiconnect -{ - public: - - testConnect(RsSerialiser *rss, NetBinInterface *ni_in); - virtual ~testConnect(); - - /* dummyConnect */ - virtual int connect(struct sockaddr_in raddr); - virtual int listen(); - virtual int stoplistening(); - virtual int reset(); - virtual bool connect_parameter(uint32_t type, uint32_t value); - virtual int getConnectAddress(struct sockaddr_in &raddr); -}; // end of testConnect. - - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg); - - -#endif - diff --git a/libretroshare/src/tests/printcache/main.cpp b/libretroshare/src/tests/printcache/main.cpp deleted file mode 100644 index 66354946a..000000000 --- a/libretroshare/src/tests/printcache/main.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * main.cpp - * - * Created on: 11 Apr 2011 - * Author: greyfox - */ - -#include -#include -#include - -#include -#include "pqi/pqistreamer.h" -#include "pqi/pqibin.h" -#include "serialiser/rsdistribitems.h" -#include "pqi/pqistore.h" - -int main(int argc, char **argv) -{ - try - { - argstream as(argc,argv) ; - bool full_print = false ; - - std::string cacheFileName; - - as >> parameter('f',"file",cacheFileName,"cache file name to read",true) - >> option('F',"full",full_print,"full dump of distrib items") - >> help() ; - - as.defaultErrorHandling() ; - - std::cout << "opening file: " << cacheFileName << std::endl; - // open file - BinInterface *bio = new BinFileInterface(cacheFileName.c_str(), BIN_FLAGS_READABLE); - RsSerialiser *rsSerialiser = new RsSerialiser(); - RsSerialType *serialType = new RsDistribSerialiser(); - rsSerialiser->addSerialType(serialType); - pqistore *store = new pqistore(rsSerialiser, "", bio, BIN_FLAGS_READABLE); - RsItem* item; - - std::set already ; - int signed_msgs = 0 ; - int distrib_msgs = 0 ; - int nb_duplicated = 0 ; - - // then print out contents to screen - while(NULL != (item = store->GetItem())) - { - - if(full_print) - item->print(std::cout, 0); - else - { - { - RsDistribMsg *i = dynamic_cast(item) ; - if(i!=NULL) - { - std::cerr << "Grp=" << i->grpId << ", parent=" << i->parentId << ", msgId=" << i->msgId ; - - if(already.find(i->msgId)!=already.end()) - { - std::cerr << " *** double ***" ; - ++nb_duplicated ; - } - else - already.insert(i->msgId) ; - - std::cerr << std::endl; - ++distrib_msgs ; - } - } - { - RsDistribSignedMsg *i = dynamic_cast(item) ; - if(i!=NULL) - { - std::cerr << "Grp=" << i->grpId << ", msgId=" << i->msgId << ", type=" << i->packet.tlvtype << ", len=" << i->packet.bin_len ; - - if(already.find(i->msgId)!=already.end()) - { - std::cerr << " *** double ***" ; - ++nb_duplicated ; - } - else - already.insert(i->msgId) ; - - std::cerr << std::endl; - - ++signed_msgs ; - } - } - } - } - - std::cerr << std::endl ; - std::cerr << "Signed messages (RsDistribMsg) : " << distrib_msgs << std::endl; - std::cerr << "Signed messages (RsDistribSignedMsg): " << signed_msgs << std::endl; - std::cerr << "Duplicate messages : " << nb_duplicated << std::endl; - - return 0; - } - catch(std::exception& e) - { - std::cerr << "Unhandled exception: " << e.what() << std::endl; - return 1 ; - } -} - - - diff --git a/libretroshare/src/tests/printcache/main_extended.cpp b/libretroshare/src/tests/printcache/main_extended.cpp deleted file mode 100644 index 2cdba7d8d..000000000 --- a/libretroshare/src/tests/printcache/main_extended.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * main.cpp - * - * Created on: 11 Apr 2011 - * Author: greyfox - */ - -#include -#include -#include - -#include -#include "pqi/pqistreamer.h" -#include "pqi/pqibin.h" -#include "serialiser/rsdistribitems.h" -#include "pqi/pqistore.h" - -int storeMsg(std::map > &msgMap, std::string filename, - std::string grpId, std::string msgId); - -pqistore *BuildSerialiser(int type, std::string filename); - -int main(int argc, char **argv) -{ - - std::list fileList; - std::list::iterator fit; - - for(int i = 1; i < argc; i++) - { - fileList.push_back(argv[i]); - } - - std::map > msgMap; - std::map >::iterator mit; - - bool printInput = true; - bool printAll = true; - bool printSummary = true; - int distrib_msgs = 0; - int signed_msgs = 0; - - for(fit = fileList.begin(); fit != fileList.end(); fit++) - { - if (printInput) - { - std::cerr << "Loading File: " << *fit; - std::cerr << std::endl; - } - - /* process this file */ - pqistore *store = BuildSerialiser(0, *fit); - RsItem* item; - RsDistribMsg *distMsg; - RsDistribSignedMsg *signMsg; - - while(NULL != (item = store->GetItem())) - { - if (NULL != (distMsg = dynamic_cast(item))) - { - if (printInput) - { - std::cerr << "Grp = " << distMsg->grpId; - std::cerr << ", parent = " << distMsg->parentId; - std::cerr << ", msgId = " << distMsg->msgId; - std::cerr << std::endl; - } - storeMsg(msgMap, *fit, distMsg->grpId, distMsg->msgId); - ++distrib_msgs ; - } - if (NULL != (signMsg = dynamic_cast(item))) - { - if (printInput) - { - std::cerr << "Grp = " << signMsg->grpId; - std::cerr << ", msgId = " << signMsg->msgId; - std::cerr << ", type = " << signMsg->packet.tlvtype; - std::cerr << ", len = " << signMsg->packet.bin_len; - std::cerr << std::endl; - } - storeMsg(msgMap, *fit, signMsg->grpId, signMsg->msgId); - ++signed_msgs ; - } - } - - delete store; - } - for(mit = msgMap.begin(); mit != msgMap.end(); mit++) - { - bool print = printAll; - if (mit->second.size() > 1) - { - /* duplicates */ - print = true; - } - - if (print) - { - std::cerr << "MsgId: " << mit->first; - std::cerr << " in Files: "; - - std::list::iterator fit; - for(fit = mit->second.begin(); fit != mit->second.end(); fit++) - { - std::cerr << *fit << " "; - } - std::cerr << std::endl; - } - } - if (printSummary) - { - std::cerr << "# RsDistribMsg(s): " << distrib_msgs << std::endl; - std::cerr << "# RsDistribSignedMsg(s): " << signed_msgs << std::endl; - std::cerr << std::endl; - } -} - - -int storeMsg(std::map > &msgMap, std::string filename, - std::string grpId, std::string msgId) -{ - std::map >::iterator mit; - mit = msgMap.find(msgId); - if (mit == msgMap.end()) - { - std::list fileList; - fileList.push_back(filename); - msgMap[msgId] = fileList; - } - else - { - (mit->second).push_back(filename); - } - return 1; -} - - -pqistore *BuildSerialiser(int type, std::string filename) -{ - BinInterface *bio = new BinFileInterface(filename.c_str(), BIN_FLAGS_READABLE); - RsSerialiser *rsSerialiser = new RsSerialiser(); - RsSerialType *serialType = new RsDistribSerialiser(); - rsSerialiser->addSerialType(serialType); - - // can use type to add more serialiser types - //RsSerialType *serialType = new RsDistribSerialiser(); - //rsSerialiser->addSerialType(serialType); - - pqistore *store = new pqistore(rsSerialiser, "", bio, BIN_FLAGS_READABLE); - return store; -} - - diff --git a/libretroshare/src/tests/printcache/printcache.pro b/libretroshare/src/tests/printcache/printcache.pro deleted file mode 100644 index ed61aa4c9..000000000 --- a/libretroshare/src/tests/printcache/printcache.pro +++ /dev/null @@ -1,31 +0,0 @@ -TEMPLATE = app -CONFIG = debug - -#SOURCES = main.cpp -SOURCES = main_extended.cpp - -LIBS += ../../lib/libretroshare.a ../../../../libbitdht/src/lib/libbitdht.a ../../../../openpgpsdk/src/lib/libops.a -LIBS += -lssl -lcrypto -lupnp -lgnome-keyring -lixml -lbz2 - -INCLUDEPATH *= ../.. .. -linux { - #LIBS = -lstdc++ -lm -} -macx { - # ENABLE THIS OPTION FOR Univeral Binary BUILD. - # CONFIG += ppc x86 - # QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 - # CONFIG -= uitools - - LIBS += ../../lib/libretroshare.a - LIBS += -lssl -lcrypto -lz -lgpgme -lgpg-error -lassuan - LIBS += ../../../../../miniupnpc-1.0/libminiupnpc.a - LIBS += ../../../../libbitdht/src/lib/libbitdht.a - LIBS += -framework CoreFoundation - LIBS += -framework Security - - # LIBS += -framework CoreServices - - -} - diff --git a/libretroshare/src/tests/scripts/checks.mk b/libretroshare/src/tests/scripts/checks.mk deleted file mode 100644 index dcb19ff3f..000000000 --- a/libretroshare/src/tests/scripts/checks.mk +++ /dev/null @@ -1,25 +0,0 @@ -#Basic checks - -ifndef RS_TOP_DIR -dummy: - echo "RS_TOP_DIR is not defined in your makefile" -endif - -#ifndef SSL_DIR -#dummy: -# echo "you must define SSL_DIR before you can compile" -# -#endif - -ifneq ($(OS),Linux) - ifneq ($(OS),MacOSX) - ifndef PTHREADS_DIR -dummy: - echo "you must define PTHREADS_DIR before you can compile" - - endif - endif -endif - - - diff --git a/libretroshare/src/tests/scripts/config-cygwin.mk b/libretroshare/src/tests/scripts/config-cygwin.mk deleted file mode 100644 index ec4518f68..000000000 --- a/libretroshare/src/tests/scripts/config-cygwin.mk +++ /dev/null @@ -1,118 +0,0 @@ -ifneq ($(OS),Cygwin) -dummy: - echo "ERROR Cygwin configuration file included, but (OS != Cygwin) - -endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -PQI_USE_XPGP = 1 -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -########################################################################### - -#### DrBobs Versions.... Please Don't Delete. -### Comment out if needed. -ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW -SRC_ROOT=../../../.. - -PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads/pthreads.2 - -################### - -#ALT_SRC_ROOT=/cygdrive/c/RetroShareBuild/src -#SRC_ROOT=/cygdrive/c/RetroShareBuild/src - -#PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads-w32-2-8-0-release - -################### - -ZLIB_DIR=$(ALT_SRC_ROOT)/zlib-1.2.3 - -SSL_DIR=$(SRC_ROOT)/openssl-0.9.7g-xpgp-0.1c -UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) - -ifdef PQI_DEBUG - CFLAGS = -Wall -g $(INCLUDE) -else - CFLAGS = -Wall -O2 $(INCLUDE) -endif - -ifdef PQI_USE_XPGP - INCLUDE += -I $(SSL_DIR)/include -endif - -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -RSCFLAGS = -Wall -g $(INCLUDE) - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# Cygwin - ?same? as Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM - -######################################################################### -# OS specific Linking. -######################################################################### - -# for static pthread libs.... -WININC += -DPTW32_STATIC_LIB -WININC += -mno-cygwin -mwindows -fno-exceptions -WININC += -DWINDOWS_SYS - -WINLIB = -lws2_32 -luuid -lole32 -liphlpapi -WINLIB += -lcrypt32 -lwinmm - -CFLAGS += -I$(PTHREADS_DIR) $(WININC) -CFLAGS += -I$(ZLIB_DIR) - -LIBS = -L$(LIBDIR) -lretroshare -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) -endif - -LIBS += -lssl -lcrypto -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += -L$(ZLIB_DIR) -lz -LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d -LIBS += $(WINLIB) - -RSCFLAGS += $(WININC) - - diff --git a/libretroshare/src/tests/scripts/config-linux.mk b/libretroshare/src/tests/scripts/config-linux.mk deleted file mode 100644 index c97a3c21e..000000000 --- a/libretroshare/src/tests/scripts/config-linux.mk +++ /dev/null @@ -1,78 +0,0 @@ - -ifneq ($(OS),Linux) -dummy: - echo "ERROR Linux configuration file included, but (OS != Linux) - -endif - -############ LINUX CONFIGURATION ######################## - -#UPNPC_DIR=../../../../miniupnpc-1.0 - -# Need to define miniupnpc version because API changed a little between v1.0 and 1.2 -# put 10 for 1.0 and 12 for 1.2 -DEFINES += -D_FILE_OFFSET_BITS=64 -DSQLITE_HAS_CODEC - -include $(RS_TOP_DIR)/tests/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -BITDIR = $(DHT_TOP_DIR)/lib -OPSDIR = $(OPS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a -BITDHT = $(BITDIR)/libbitdht.a -# Unix: Linux/Cygwin -INCLUDE = -I$(RS_TOP_DIR) -I$(OPS_TOP_DIR) -I$(DHT_TOP_DIR) -CFLAGS = -Wall -g $(INCLUDE) -I.. -#CFLAGS += -fprofile-arcs -ftest-coverage -CFLAGS += ${DEFINES} - -#ifdef PQI_USE_XPGP -# INCLUDE += -I $(SSL_DIR)/include -#endif -# -#ifdef PQI_USE_XPGP -# CFLAGS += -DPQI_USE_XPGP -#endif - -RSCFLAGS = -Wall -g $(INCLUDE) -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# march=i686 causes problems while 64Bit compiling, GCC tries to generate Output for a m64 machine, but the marchi686 -# doesnt allow the instructionfs for that. -# -# gcc docu: http://gcc.gnu.org/onlinedocs/gcc-4.0.3/gcc/i386-and-x86_002d64-Options.html#i386-and-x86_002d64-Options - -# Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include ${DEFINES} -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM - -######################################################################### -# OS specific Linking. -######################################################################### - -LIBS = -L$(LIBDIR) -lretroshare -LIBS += -L$(BITDIR) -lbitdht -lgnome-keyring -LIBS += -L$(OPSDIR) -lops -LIBS += -lixml -lbz2 - -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) - endif -LIBS += -lssl -lcrypto -lpthread -#LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += $(XLIB) -ldl -lz -LIBS += -lupnp -LIBS += -lsqlcipher - -RSLIBS = $(LIBS) - - diff --git a/libretroshare/src/tests/scripts/config-macosx.mk b/libretroshare/src/tests/scripts/config-macosx.mk deleted file mode 100644 index b13a471f0..000000000 --- a/libretroshare/src/tests/scripts/config-macosx.mk +++ /dev/null @@ -1,98 +0,0 @@ - -ifneq ($(OS),MacOSX) -dummy: - echo "ERROR MacOSX configuration file included, but (OS != MacOSX) - -endif - -############ LINUX CONFIGURATION ######################## - - -# FLAGS to decide if we want i386 Build or ppc Build -# -# - -# PPC is default -# Could define both for combined compilation... -# except might not work for bio_tou.c file! -# -# MAC_I386_BUILD = 1 -# MAC_PPC_BUILD = 1 - -MAC_I386_BUILD = 1 -#MAC_PPC_BUILD = 1 - -ifndef MAC_I386_BUILD - MAC_PPC_BUILD = 1 -endif - -UPNPC_DIR=../../../../../../src/miniupnpc-1.0 - -include $(RS_TOP_DIR)/tests/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm - -RANLIB = ranlib - -# Dummy ranlib -> can't do it until afterwards with universal binaries. -# RANLIB = ls -l - -OPSDIR = $(OPS_TOP_DIR)/lib -BITDIR = $(DHT_TOP_DIR)/lib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -OPT_DIR = /opt/local -OPT_INCLUDE = $(OPT_DIR)/include -OPT_LIBS = $(OPT_DIR)/lib - -INCLUDE = -I $(RS_TOP_DIR) -I $(OPT_INCLUDE) -#CFLAGS = -Wall -O3 -CFLAGS = -Wall -g - -# Flags for architecture builds. -ifdef MAC_I386_BUILD - CFLAGS += -arch i386 -endif - -ifdef MAC_PPC_BUILD - CFLAGS += -arch ppc -endif - -CFLAGS += $(INCLUDE) - -# This Line is for Universal BUILD for 10.4 + 10.5 -# (but unlikely to work unless Qt Libraries are build properly) -#CFLAGS += -isysroot /Developer/SDKs/MacOSX10.5.sdk - -# RSCFLAGS = -Wall -O3 $(INCLUDE) - -######################################################################### -# OS Compile Options -######################################################################### - -######################################################################### -# OS specific Linking. -######################################################################### - -LIBS = -Wl,-search_paths_first - -# for Univeral BUILD -# LIBS += -arch ppc -arch i386 -#LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.5u.sdk - -LIBS = -L$(LIBDIR) -lretroshare -LIBS += -L$(BITDIR) -lbitdht -LIBS += -L$(OPSDIR) -lops -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) - endif -LIBS += -lssl -lcrypto -lpthread -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += $(XLIB) -ldl -lz - - - diff --git a/libretroshare/src/tests/scripts/config-mingw.mk b/libretroshare/src/tests/scripts/config-mingw.mk deleted file mode 100644 index c0040ac4e..000000000 --- a/libretroshare/src/tests/scripts/config-mingw.mk +++ /dev/null @@ -1,138 +0,0 @@ -#ifneq ($(OS),"Win ") -#dummy: -# echo "ERROR OS = $(OS)" -# echo "ERROR MinGW configuration file included, but (OS != Win) -# -#endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -#PQI_USE_XPGP = 1 -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -########################################################################### - -#### DrBobs Versions.... Please Don't Delete. -### Comment out if needed. -SRC_ROOT_PKG=/home/Mark/prog/retroshare/package/rs-win-v0.5.0/src -SRC_ROOT_GPG=/local - -#ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW -#SRC_ROOT=../../../.. - -PTHREADS_DIR=$(SRC_ROOT_PKG)/pthreads-w32-2-8-0/Pre-built.2 -ZLIB_DIR=$(SRC_ROOT_PKG)/zlib-1.2.3 -SSL_DIR=$(SRC_ROOT_PKG)/openssl-tmp -UPNPC_DIR=$(SRC_ROOT_PKG)/miniupnpc-1.3 - -########################################################################### - -#### Enable this section for compiling with MSYS/MINGW compile -#SRC_ROOT=/home/linux - -#SSL_DIR=$(SRC_ROOT)/OpenSSL -#GPGME_DIR=$(SRC_ROOT)/gpgme-1.1.8 -#GPG_ERROR_DIR=$(SRC_ROOT)/libgpg-error-1.7 - -#ZLIB_DIR=$(SRC_ROOT)/zlib-1.2.3 -#UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 -#PTHREADS_DIR=$(SRC_ROOT)/pthreads-w32-2-8-0-release - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ####################################### - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) - -ifdef PQI_DEBUG - CFLAGS = -Wall -g $(INCLUDE) -else - CFLAGS = -Wall -O2 $(INCLUDE) -endif - -# These aren't used anymore.... really. -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -# SSL / pthreads / Zlib -# included by default for Windows compilation. -INCLUDE += -I $(SSL_DIR)/include -INCLUDE += -I$(PTHREADS_DIR) -INCLUDE += -I$(ZLIB_DIR) - - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# Cygwin - ?same? as Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM -BIOCFLAGS += -DWINDOWS_SYS - -######################################################################### -# OS specific Linking. -######################################################################### - -# for static pthread libs.... -#WININC += -DPTW32_STATIC_LIB -#WININC += -mno-cygwin -mwindows -fno-exceptions - -WININC += -DWINDOWS_SYS - -WINLIB = -lws2_32 -luuid -lole32 -liphlpapi -WINLIB += -lcrypt32 -lwinmm - -CFLAGS += -I$(SSL_DIR)/include -CFLAGS += -I$(PTHREADS_DIR)/include -CFLAGS += -I$(ZLIB_DIR) -CFLAGS += -I$(SRC_ROOT_GPG)/include - -### Enable this for GPGME and GPG ERROR dirs -#CFLAGS += -I$(GPGME_DIR)/src -#CFLAGS += -I$(GPG_ERROR_DIR)/src - -CFLAGS += $(WININC) - - - -LIBS = -L$(LIBDIR) -lretroshare - -LIBS += -L$(SSL_DIR) - -LIBS += -lssl -lcrypto -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += -L$(ZLIB_DIR) -lz -LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d -LIBS += $(WINLIB) - -#RSCFLAGS = -Wall -g $(INCLUDE) -#RSCFLAGS += $(WININC) - - diff --git a/libretroshare/src/tests/scripts/config.mk b/libretroshare/src/tests/scripts/config.mk deleted file mode 100644 index 951eca4c6..000000000 --- a/libretroshare/src/tests/scripts/config.mk +++ /dev/null @@ -1,27 +0,0 @@ - -# determine which operating system -# -########################################################################### -#Define OS. -# -OS = Linux -#OS = MacOSX -#OS = Cygwin -#OS = Win # MinGw. -########################################################################### - -ifeq ($(OS),Linux) - include $(RS_TOP_DIR)/tests/scripts/config-linux.mk -else - ifeq ($(OS),MacOSX) - include $(RS_TOP_DIR)/tests/scripts/config-macosx.mk - else - ifeq ($(OS),Cygwin) - include $(RS_TOP_DIR)/tests/scripts/config-cygwin.mk - else - include $(RS_TOP_DIR)/tests/scripts/config-mingw.mk - endif - endif -endif - -########################################################################### diff --git a/libretroshare/src/tests/scripts/regress.mk b/libretroshare/src/tests/scripts/regress.mk deleted file mode 100644 index 7d69df664..000000000 --- a/libretroshare/src/tests/scripts/regress.mk +++ /dev/null @@ -1,25 +0,0 @@ - -testoutputfiles = $(foreach tt,$(1),$(tt).tstout) - -%.tstout : %.sh % - -sh ./$< > $@ 2>&1 - -%.tstout : % - -./$< > $@ 2>&1 - -TESTOUT = $(call testoutputfiles,$(TESTS)) - -.phony : tests regress retest clobber - -tests: $(TESTS) - -regress: $(TESTOUT) - @-echo "--------------- SUCCESS (count):" - @-grep -c SUCCESS $(TESTOUT) - @-echo "--------------- FAILURE REPORTS:" - @-grep FAILURE $(TESTOUT) || echo no failures - @-echo "--------------- end" - -retest: - -/bin/rm $(TESTOUT) - diff --git a/libretroshare/src/tests/scripts/rules.mk b/libretroshare/src/tests/scripts/rules.mk deleted file mode 100644 index 3df30a488..000000000 --- a/libretroshare/src/tests/scripts/rules.mk +++ /dev/null @@ -1,24 +0,0 @@ - -# defines required / used. -# -# CFLAGS -# -# - -librs: $(RSOBJ) - $(AR) r $(LIBRS) $(RSOBJ) - $(RANLIB) $(LIBRS) - -.cc.o: - $(CC) $(CFLAGS) -c $< - -clean: - -/bin/rm -f $(RSOBJ) $(EXECOBJ) $(TESTOBJ) *.gcno *.gcda \ - *.gcov *.tstout $(TESTS) - -clobber: clean retest - -/bin/rm $(EXEC) $(TESTS) - - -include $(RS_TOP_DIR)/tests/scripts/regress.mk - diff --git a/libretroshare/src/tests/serialiser/TestNotes.txt b/libretroshare/src/tests/serialiser/TestNotes.txt deleted file mode 100644 index 90c459120..000000000 --- a/libretroshare/src/tests/serialiser/TestNotes.txt +++ /dev/null @@ -1,56 +0,0 @@ - -Few test still need to be done. Needs to be automated - -used support(.h/.cc) file for testing RsItems - -Components and Tests. -============================================================ ------------------------------------------------------------- -Basic Items ------------------------------------------------------------- -rsbaseitems.cc : needed -rsbaseserial.cc : needed -rsconfigitems.cc : needed -rsserial.cc : needed - - - - ------------------------------------------------------------- -Compound TLV Components ------------------------------------------------------------- - -rstlvaddrs.cc : needed -rstlvbase.cc : not finished, tlvbase_test -rstlvfileitem.cc : tlvtypes_test -rstlvimage.cc : tlvtypes_test -rstlvkeys.cc : tlvtypes_test -rstlvkvwide.cc : rstlvwidetest -rstlvtypes.cc : tlvtypes_test -rstlvutil.cc : no need - ------------------------------------------------------------- -Service Components ------------------------------------------------------------- -rstunnelitems.cc : rstunnelitem_test & rsturtleitem_test -rsdistribitem.cc : distribitem_test -rsmsgitem.cc : msgitem_test -rsdiscitems.cc : needed -rsrankitems.cc : needed -rsblogitems.cc : distribitem_test -rschannelitems.cc : distribitem_test -rsforumitems.cc : distribitem_test -rsstatusitems.cc : needed -rsgameitems.cc : TBC -rsphotoitems.cc : TBC - -============================================================ -Test Specifics -============================================================ - ------------------------------------------------------------- -Basic Components ------------------------------------------------------------- - - - diff --git a/libretroshare/src/tests/serialiser/distribitem_test.cc b/libretroshare/src/tests/serialiser/distribitem_test.cc deleted file mode 100644 index 3cc551f0f..000000000 --- a/libretroshare/src/tests/serialiser/distribitem_test.cc +++ /dev/null @@ -1,365 +0,0 @@ -/* - * libretroshare/src/serialiser: distribitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include "util/rstime.h" -#include "serialiser/rsdistribitems.h" -#include "serialiser/rschannelitems.h" -#include "serialiser/rsforumitems.h" -#include "serialiser/rsblogitems.h" -#include "retroshare/rsdistrib.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" -#include "support.h" - -#include "distribitem_test.h" - -INITTEST() - -/** base rs distrib items **/ - - - - -RsSerialType* init_item(RsDistribGrp& grp) -{ - - rstime_t now = time(NULL); - - /* create Keys */ - - /* Create Group Description */ - - randString(SHORT_STR, grp.grpName); - randString(LARGE_STR, grp.grpDesc); - - grp.timestamp = now; - grp.grpFlags = (RS_DISTRIB_PRIVACY_MASK | RS_DISTRIB_AUTHEN_MASK); - grp.grpControlFlags = 0; - - init_item(grp.grpPixmap); - - /* set keys */ - - RsTlvSecurityKey publish_key; - - init_item(grp.adminKey); - init_item(publish_key); - init_item(grp.adminSignature); - - grp.publishKeys.keys[publish_key.keyId] = publish_key; - grp.publishKeys.groupId = grp.adminKey.keyId; - grp.grpId = grp.adminKey.keyId; - - init_item(grp.grpControlList); - - return new RsDistribSerialiser(); - -} - - -RsSerialType* init_item(RsDistribGrpKey& gk) -{ - - init_item(gk.key); - gk.grpId = gk.key.keyId; - - return new RsDistribSerialiser(); - -} - - -bool operator==(const RsDistribGrpKey& gk1, const RsDistribGrpKey& gk2) -{ - if(gk1.grpId != gk1.grpId) return false; - if(!(gk1.key == gk2.key)) return false; - - return true; -} - -RsSerialType* init_item(RsDistribSignedMsg& sMsg) -{ - - RsChannelMsg chMsg; - RsSerialType* ser = init_item(chMsg); - uint32_t chMsgSize = ser->size(&chMsg); - char* chMsgData = new char[chMsgSize]; - ser->serialise(&chMsg, chMsgData, &chMsgSize); - delete ser; - - sMsg.packet.setBinData(chMsgData, chMsgSize); - sMsg.flags = rand()%300; - randString(SHORT_STR, sMsg.grpId); - - return new RsDistribSerialiser(); -} - -bool operator==(const RsDistribSignedMsg& sMsg1,const RsDistribSignedMsg& sMsg2) -{ - - if(!(sMsg1.packet == sMsg2.packet)) return false; - if(sMsg1.grpId != sMsg2.grpId) return false; - if(sMsg1.flags != sMsg2.flags) return false; - - return true; -} - - -RsSerialType* init_item(RsChannelMsg& chMsg) -{ - randString(SHORT_STR, chMsg.grpId); - randString(LARGE_STR, chMsg.message); - randString(SHORT_STR, chMsg.subject); - randString(SHORT_STR, chMsg.threadId); - chMsg.timestamp = rand()%31452; - init_item(chMsg.thumbnail); - init_item(chMsg.attachment); - - return new RsChannelSerialiser(); -} - - -bool operator==(const RsChannelMsg& chMsg1,const RsChannelMsg& chMsg2) -{ - - if(chMsg1.grpId != chMsg2.grpId) return false; - if(chMsg1.message != chMsg2.message) return false; - if(!(chMsg1.attachment == chMsg2.attachment)) return false; - if(chMsg1.subject != chMsg2.subject) return false; - if(chMsg2.threadId != chMsg2.threadId) return false; - if(chMsg1.timestamp != chMsg2.timestamp) return false; - if(!(chMsg1.thumbnail.binData == chMsg2.thumbnail.binData)) return false; - if(chMsg1.thumbnail.image_type != chMsg2.thumbnail.image_type) return false; - - return true; -} - -RsSerialType* init_item(RsForumMsg& fMsg) -{ - - fMsg.timestamp = rand()%242; - randString(SHORT_STR, fMsg.grpId); - randString(LARGE_STR, fMsg.msg); - randString(SHORT_STR, fMsg.parentId); - randString(SHORT_STR, fMsg.srcId); - randString(SHORT_STR, fMsg.threadId); - randString(SHORT_STR, fMsg.title); - - return new RsForumSerialiser(); -} - - - -bool operator==(const RsForumMsg& fMsg1, const RsForumMsg& fMsg2) -{ - if(fMsg1.grpId != fMsg2.grpId) return false; - if(fMsg1.msg != fMsg2.msg) return false; - if(fMsg1.parentId != fMsg2.parentId) return false; - if(fMsg1.srcId != fMsg2.srcId) return false; - if(fMsg1.threadId != fMsg2.threadId) return false; - if(fMsg1.timestamp != fMsg2.timestamp) return false; - if(fMsg1.title != fMsg2.title) return false; - - return true; -} - -RsSerialType* init_item(RsBlogMsg& bMsg) -{ - bMsg.timestamp = rand()%223; - randString(SHORT_STR, bMsg.grpId); - randString(LARGE_STR, bMsg.message); - randString(SHORT_STR, bMsg.subject); - randString(SHORT_STR, bMsg.parentId); - randString(SHORT_STR, bMsg.threadId); - RsTlvImage image; - int nImages = rand()%5; - - for(int i=0; i < nImages; i++) - { - init_item(image); - bMsg.graphic_set.push_back(image); - } - - return new RsBlogSerialiser(); -} - - -bool operator==(const RsDistribGrp& g1, const RsDistribGrp& g2) -{ - - if(g1.grpCategory != g2.grpCategory) return false; - if(g1.grpControlFlags != g2.grpControlFlags) return false; - if(!(g1.grpControlList == g2.grpControlList)) return false; - if(g1.grpDesc != g2.grpDesc) return false; - if(g1.grpFlags != g2.grpFlags) return false; - if(g1.grpId != g2.grpId) return false; - if(g1.grpName != g2.grpName) return false; - if(g1.timestamp != g2.timestamp) return false; - - // admin key - - if(!(g1.adminKey == g2.adminKey)) return false; - if(!(g1.adminSignature == g2.adminSignature)) return false; - if(g1.grpPixmap.image_type != g2.grpPixmap.image_type) return false; - if(!(g1.grpPixmap.binData == g2.grpPixmap.binData)) return false; - - return true; -} - - - -RsSerialType* init_item(RsForumReadStatus& fRdStatus) -{ - randString(SHORT_STR, fRdStatus.forumId); - fRdStatus.save_type = rand()%42; - - std::map::iterator mit = fRdStatus.msgReadStatus.begin(); - - std::string id; - uint32_t status = 0; - - int numMaps = rand()%12; - - for(int i = 0; i < numMaps; i++) - { - randString(SHORT_STR, id); - status = rand()%23; - - fRdStatus.msgReadStatus.insert(std::pair(id, status)); - } - - return new RsForumSerialiser(); -} - -bool operator==(const RsForumReadStatus& frs1, const RsForumReadStatus& frs2) -{ - if(frs1.forumId != frs2.forumId) return false; - if(frs1.save_type != frs2.save_type) return false; - - if(frs1.msgReadStatus.size() != frs2.msgReadStatus.size()) return false; - - std::map::const_iterator mit - = frs1.msgReadStatus.begin(); - - - - for(;mit != frs1.msgReadStatus.end(); mit++) - { - if(mit->second != frs2.msgReadStatus.find(mit->first)->second) return false; - } - - return true; - -} - - - -RsSerialType* init_item(RsChannelReadStatus& fRdStatus) -{ - randString(SHORT_STR, fRdStatus.channelId); - fRdStatus.save_type = rand()%42; - - std::map::iterator mit = fRdStatus.msgReadStatus.begin(); - - std::string id; - uint32_t status = 0; - - int numMaps = rand()%12; - - for(int i = 0; i < numMaps; i++) - { - randString(SHORT_STR, id); - status = rand()%23; - - fRdStatus.msgReadStatus.insert(std::pair(id, status)); - } - - return new RsChannelSerialiser(); -} - -bool operator==(const RsChannelReadStatus& frs1, const RsChannelReadStatus& frs2) -{ - if(frs1.channelId != frs2.channelId) return false; - if(frs1.save_type != frs2.save_type) return false; - - if(frs1.msgReadStatus.size() != frs2.msgReadStatus.size()) return false; - - std::map::const_iterator mit - = frs1.msgReadStatus.begin(); - - - - for(;mit != frs1.msgReadStatus.end(); mit++) - { - if(mit->second != frs2.msgReadStatus.find(mit->first)->second) return false; - } - - return true; - -} - - -bool operator==(const RsBlogMsg& bMsg1,const RsBlogMsg& bMsg2) -{ - - if(bMsg1.timestamp != bMsg2.timestamp) return false; - if(bMsg1.grpId != bMsg2.grpId) return false; - if(bMsg1.message != bMsg2.message) return false; - if(bMsg1.subject != bMsg2.subject) return false; - if(bMsg1.threadId != bMsg2.threadId) return false; - if(bMsg1.parentId != bMsg2.parentId) return false; - - std::list::const_iterator it1 = bMsg1.graphic_set.begin(), - it2 = bMsg2.graphic_set.begin(); - - if(bMsg1.graphic_set.size() != bMsg2.graphic_set.size()) return false; - - for(; it1 != bMsg1.graphic_set.end() ; it1++, it2++) - { - if(!(*it1 == *it2)) return false; - } - - return true; -} - -int main(){ - - std::cerr << "RsDistribItem Tests" << std::endl; - - test_RsItem(); REPORT("Serialise/Deserialise RsDistribGrp"); - test_RsItem(); REPORT("Serialise/Deserialise RsDistribGrpKey"); - test_RsItem(); REPORT("Serialise/Deserialise RsDistribSignedMsg"); - test_RsItem(); REPORT("Serialise/Deserialise RsChannelMsg"); - test_RsItem(); REPORT("Serialise/Deserialise RsChannelReadStatus"); - test_RsItem(); REPORT("Serialise/Deserialise RsForumMsg"); - test_RsItem(); REPORT("Serialise/Deserialise RsForumReadStatus"); - test_RsItem(); REPORT("Serialise/Deserialise RsBlogMsg"); - - - FINALREPORT("RsDistribItem Tests"); - - return TESTRESULT(); -} - diff --git a/libretroshare/src/tests/serialiser/distribitem_test.h b/libretroshare/src/tests/serialiser/distribitem_test.h deleted file mode 100644 index 1eedfd643..000000000 --- a/libretroshare/src/tests/serialiser/distribitem_test.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef DISTRIBITEM_TEST_H_ -#define DISTRIBITEM_TEST_H_ - -/* - * libretroshare/src/serialiser: distribitem_test.h - * - * RetroShare Serialiser tests - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "serialiser/rsdistribitems.h" -#include "serialiser/rschannelitems.h" -#include "serialiser/rsforumitems.h" -#include "serialiser/rsblogitems.h" - - - -RsSerialType* init_item(RsDistribGrp&); -RsSerialType* init_item(RsDistribGrpKey&); -RsSerialType* init_item(RsDistribSignedMsg&); -RsSerialType* init_item(RsChannelMsg&); -RsSerialType* init_item(RsForumMsg&); -RsSerialType* init_item(RsForumReadStatus&); -RsSerialType* init_item(RsBlogMsg&); - -bool operator==(const RsDistribGrp& , const RsDistribGrp& ); -bool operator==(const RsDistribGrpKey& , const RsDistribGrpKey& ); -bool operator==(const RsDistribSignedMsg& , const RsDistribSignedMsg& ); -bool operator==(const RsChannelMsg& , const RsChannelMsg& ); -bool operator==(const RsForumMsg& , const RsForumMsg& ); -bool operator==(const RsForumReadStatus&, const RsForumReadStatus& ); -bool operator==(const RsBlogMsg& , const RsBlogMsg& ); - - - - -#endif /* DISTRIBITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/perform_auto_tests.sh b/libretroshare/src/tests/serialiser/perform_auto_tests.sh deleted file mode 100755 index e9857c4ec..000000000 --- a/libretroshare/src/tests/serialiser/perform_auto_tests.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh - -printresult() { - if test "$?" = "0"; then - echo ' 'PASSED - else - echo *FAILED* - fi -} - -# Warning: printresult needs to be called before anything else because it contains the -# result of the call to the test program, until the next command. - -exes="rsstatusitem_test \ - tlvbase_test \ - rsserial_test \ - tlvtypes_test \ - rsmsgitem_test \ - rstunnelitem_test \ - tlvrandom_test \ - rstlvwidetest \ - rsconfigitem_test \ - rsturtleitem_test \ - tlvitems_test \ - distribitem_test \ - tlvstack_test \ - tlvbase_test2" - -for exe in $exes; do - ./$exe > /dev/null 2>&1 ; result=`printresult`; echo "-- $exe \t test :" $result ; -done - - - diff --git a/libretroshare/src/tests/serialiser/rsbaseitem_test.cc b/libretroshare/src/tests/serialiser/rsbaseitem_test.cc deleted file mode 100644 index 4743e5248..000000000 --- a/libretroshare/src/tests/serialiser/rsbaseitem_test.cc +++ /dev/null @@ -1,191 +0,0 @@ - -/* - * libretroshare/src/serialiser: rsbaseitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - * tlvfileitem test. - * - * - */ - -#include -#include -#include "serialiser/rstlvtypes.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" - -INITTEST(); - -static int test_RsFileItem(); -static int test_RsFileData(); - -int main() -{ - std::cerr << "RsFile[Item/Data/...] Tests" << std::endl; - - test_RsFileItem(); - test_RsFileData(); - - FINALREPORT("RsTlvFile[Item/Data/...] Tests"); - - return TESTRESULT(); -} - -int test_RsTlvFileItem() -{ - - - - - RsTlvFileItem i1; - RsTlvFileItem i2; - - /* initialise */ - i1.filesize = 101010; - i1.hash = "ABCDEFEGHE"; - i1.name = "TestFile.txt"; - i1.pop = 12; - i1.age = 456; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /* check the data is the same */ - CHECK(i1.filesize == i2.filesize); - CHECK(i1.hash == i2.hash); - CHECK(i1.name == i2.name); - CHECK(i1.path == i2.path); - CHECK(i1.pop == i2.pop); - CHECK(i1.age == i2.age); - - /* do it again without optional data */ - i1.filesize = 123; - i1.name = ""; - i1.pop = 0; - i1.age = 0; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /* check the data is the same */ - CHECK(i1.filesize == i2.filesize); - CHECK(i1.hash == i2.hash); - CHECK(i1.name == i2.name); - CHECK(i1.path == i2.path); - CHECK(i1.pop == i2.pop); - CHECK(i1.age == i2.age); - - /* one more time - long file name, some optional data */ - i1.filesize = 123; - i1.name = "A Very Long File name that should fit in easily ??? with som $&%&^%* strange char (**$^%#&^$#*^%(&^ in there too!!!! ~~~!!$#(^$)$)(&%^)&\" oiyu thend"; - i1.pop = 666; - i1.age = 0; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /* check the data is the same */ - CHECK(i1.filesize == i2.filesize); - CHECK(i1.hash == i2.hash); - CHECK(i1.name == i2.name); - CHECK(i1.path == i2.path); - CHECK(i1.pop == i2.pop); - CHECK(i1.age == i2.age); - - REPORT("Serialise/Deserialise RsTlvFileItem"); - - return 1; -} - -int test_RsTlvFileSet() -{ - RsTlvFileSet s1; - RsTlvFileSet s2; - - int i = 0; - for(i = 0; i < 15; i++) - { - RsTlvFileItem fi; - fi.filesize = 16 + i * i; - fi.hash = "ABCDEF"; - std::ostringstream out; - out << "File" << i << "_inSet.txt"; - fi.name = out.str(); - if (i % 2 == 0) - { - fi.age = 10 * i; - } - else - { - fi.age = 0; - } - fi.pop = 0; - - s1.items.push_back(fi); - } - - CHECK(test_SerialiseTlvItem(std::cerr, &s1, &s2)); - - /* check the data is the same - TODO */ - - REPORT("Serialise/Deserialise RsTlvFileSet"); - - return 1; -} - - -int test_RsTlvFileData() -{ - RsTlvFileData d1; - RsTlvFileData d2; - - /* initialise */ - d1.file.filesize = 101010; - d1.file.hash = "ABCDEFEGHE"; - d1.file.name = ""; - d1.file.age = 0; - d1.file.pop = 0; - - char data[15]; - d1.binData.setBinData(data, 15); - - d1.file_offset = 222; - - CHECK(test_SerialiseTlvItem(std::cerr, &d1, &d2)); - - /* check the data is the same */ - CHECK(d1.file.filesize == d2.file.filesize); - CHECK(d1.file.hash == d2.file.hash); - CHECK(d1.file.name == d2.file.name); - CHECK(d1.file.path == d2.file.path); - CHECK(d1.file.pop == d2.file.pop); - CHECK(d1.file.age == d2.file.age); - - CHECK(d1.file_offset == d2.file_offset); - CHECK(d1.binData.bin_len == d2.binData.bin_len); - - REPORT("Serialise/Deserialise RsTlvFileData"); - - return 1; -} - - diff --git a/libretroshare/src/tests/serialiser/rsconfigitem_test.cc b/libretroshare/src/tests/serialiser/rsconfigitem_test.cc deleted file mode 100644 index 1ac41ae09..000000000 --- a/libretroshare/src/tests/serialiser/rsconfigitem_test.cc +++ /dev/null @@ -1,328 +0,0 @@ -/* - * libretroshare/src/tests/serialiser: rsconfigitemstest.cc - * - * RetroShare Serialiser tests. - * - * Copyright 2011 by Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "rsconfigitem_test.h" -#include "util/utest.h" -#include "support.h" - - - -INITTEST() - -RsSerialType* init_item(RsPeerNetItem& rpn) -{ - randString(SHORT_STR, rpn.dyndns); - randString(SHORT_STR, rpn.gpg_id); - randString(SHORT_STR, rpn.location); - randString(SHORT_STR, rpn.pid); - - rpn.lastContact = rand()%42424; - rpn.netMode = rand()%313190; - rpn.visState = rand()%63635; - - - inet_aton("10.0.0.111", &(rpn.currentlocaladdr.sin_addr)); - rpn.currentlocaladdr.sin_port = htons(1111); - - inet_aton("123.1.2.123", &(rpn.currentremoteaddr.sin_addr)); - rpn.currentremoteaddr.sin_port = htons(1234); - - RsTlvIpAddressInfo ipa1, ipa2; - - ipa1.addr = rpn.currentlocaladdr; - ipa1.seenTime = rand()%40149013; - ipa1.source = rand()%13423; - - ipa2.addr = rpn.currentremoteaddr; - ipa2.seenTime = rand()%40139013; - ipa2.source = rand()%1343443; - - rpn.extAddrList.addrs.push_back(ipa1); - rpn.extAddrList.addrs.push_back(ipa2); - - rpn.localAddrList.addrs.push_back(ipa1); - rpn.localAddrList.addrs.push_back(ipa2); - - - return new RsPeerConfigSerialiser(); -} - -RsSerialType* init_item(RsPeerOldNetItem& rpon) -{ - return new RsPeerConfigSerialiser(); -} - -RsSerialType* init_item(RsPeerGroupItem& rpgi){ - - rpgi.flag = rand()%134344; - randString(SHORT_STR, rpgi.id); - randString(SHORT_STR, rpgi.name); - std::string p1, p2, p3; - randString(SHORT_STR, p1); - randString(SHORT_STR, p2); - randString(SHORT_STR, p3); - - rpgi.peerIds.push_back(p1); - rpgi.peerIds.push_back(p2); - rpgi.peerIds.push_back(p3); - - return new RsPeerConfigSerialiser(); -} - -RsSerialType* init_item(CompressedChunkMap& map) -{ - map._map.clear() ; - for(uint32_t i=0;i<15;++i) - map._map.push_back(rand()) ; - - return new RsTurtleSerialiser(); -} - -RsSerialType* init_item(RsPeerStunItem& rpsi) -{ - std::string p1, p2, p3; - randString(SHORT_STR, p1); - randString(SHORT_STR, p2); - randString(SHORT_STR, p3); - - rpsi.stunList.ids.push_back(p1); - rpsi.stunList.ids.push_back(p2); - rpsi.stunList.ids.push_back(p3); - - rpsi.stunList.mType = TLV_TYPE_PEERSET; - - return new RsPeerConfigSerialiser(); -} -RsSerialType* init_item(RsCacheConfig& rcc) -{ - - rcc.cachesubid = rand()%2342; - rcc.cachetypeid = rand()%323; - rcc.recvd = rand()%2252243; - rcc.size = rand()%02203; - randString(SHORT_STR, rcc.hash); - randString(SHORT_STR, rcc.name); - randString(SHORT_STR, rcc.path); - randString(SHORT_STR, rcc.pid); - - return new RsCacheConfigSerialiser(); -} - -RsSerialType* init_item(RsFileTransfer& rft) -{ - - std::string p1, p2, p3; - randString(SHORT_STR, p1); - randString(SHORT_STR, p2); - randString(SHORT_STR, p3); - - rft.allPeerIds.ids.push_back(p1); - rft.allPeerIds.ids.push_back(p2); - rft.allPeerIds.ids.push_back(p3); - rft.allPeerIds.mType = TLV_TYPE_PEERSET; - -// -// rft.compressed_chunk_map._map.clear(); -// const int mapSize = 15; -// rft.compressed_chunk_map._map.resize(mapSize); -// for(int i=0; i& left, - const std::list& right) -{ - std::list::const_iterator cit1 = left.begin(), - cit2 = right.begin(); - - for(; cit1 != left.end() ; cit1++, cit2++){ - - if(*cit1 != *cit2) - return false; - } - - return true; -} - -bool operator!=(const sockaddr_in& left, const sockaddr_in& right) -{ - if(left.sin_addr.s_addr != right.sin_addr.s_addr) return true; - if(left.sin_port != right.sin_port) return true; - - return false; -} - -bool operator!=(const RsTlvIpAddressInfo& left, const RsTlvIpAddressInfo& right) -{ - - if(left.addr != right.addr) return true; - if(left.seenTime != right.seenTime) return true; - if(left.source != right.source) return true; - - return false; -} - - -bool operator==(const RsPeerOldNetItem& left, const RsPeerOldNetItem& right) -{ - return false; -} - -bool operator==(const RsPeerGroupItem& left, const RsPeerGroupItem& right) -{ - if(left.flag != right.flag) return false; - if(left.id != right.id) return false; - if(left.name != right.name) return false; - if(left.peerIds != right.peerIds) return false; - - return true; -} - -bool operator!=(const std::list& left, - const std::list& right) -{ - std::list::const_iterator cit1 = left.begin(), - cit2 = right.begin(); - - for(; cit1 != left.end(); cit1++, cit2++){ - - if(*cit1 != *cit2) - return true; - } - - return false; -} - -bool operator==(const RsPeerStunItem& left, const RsPeerStunItem& right) -{ - if(!(left.stunList == right.stunList)) return false; - - return true; -} - -//bool operator==(const RsTlvPeerIdSet& left, const RsTlvPeerIdSet& right) -//{ -// if(left.mType != right.mType) return false; -// -// std::list::iterator cit1 = left.ids.begin(), -// cit2 = right.ids.begin(); -// -// for(; cit1 != left.ids.end(); cit1++, cit2++){ -// -// if(*cit1 != *cit2) -// return false; -// } -// -// return true; -//} - -bool operator==(const RsCacheConfig& left, const RsCacheConfig& right) -{ - - if(left.cachesubid != right.cachesubid) return false; - if(left.cachetypeid != right.cachetypeid) return false; - if(left.hash != right.hash) return false; - if(left.path != right.path) return false; - if(left.pid != right.pid) return false; - if(left.recvd != right.recvd) return false; - if(left.size != right.size) return false; - - return true; -} - -bool operator==(const RsFileTransfer& left, const RsFileTransfer& right) -{ - - if(!(left.allPeerIds == right.allPeerIds)) return false; - if(left.cPeerId != right.cPeerId) return false; - if(left.chunk_strategy != right.chunk_strategy) return false; - if(left.compressed_chunk_map._map != right.compressed_chunk_map._map) return false; - if(left.crate != right.crate) return false; - if(!(left.file == right.file)) return false; - if(left.flags != right.flags) return false; - if(left.in != right.in) return false; - if(left.lrate != right.lrate) return false; - if(left.ltransfer != right.ltransfer) return false; - if(left.state != right.state) return false; - if(left.transferred != right.transferred) return false; - if(left.trate != right.trate) return false; - - return true; -} - - - -int main() -{ - - std::cerr << "RsConfigItems Tests" << std::endl; - - test_RsItem(); REPORT("Serialise/Deserialise RsPeerNetItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsPeerGroupItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsPeerStunItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsCacheConfig"); - test_RsItem(); REPORT("Serialise/Deserialise RsFileTransfer"); - - FINALREPORT("RsConfigItems Tests"); - - return TESTRESULT(); -} diff --git a/libretroshare/src/tests/serialiser/rsconfigitem_test.h b/libretroshare/src/tests/serialiser/rsconfigitem_test.h deleted file mode 100644 index 2571d5c30..000000000 --- a/libretroshare/src/tests/serialiser/rsconfigitem_test.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * libretroshare/src/serialiser: rsconfigitem_test.h - * - * RetroShare Serialiser tests. - * - * Copyright 2011 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef RSCONFIGITEM_TEST_H_ -#define RSCONFIGITEM_TEST_H_ - -#include "serialiser/rsconfigitems.h" -#include "turtle/rsturtleitem.h" - -RsSerialType* init_item(CompressedChunkMap& map); -RsSerialType* init_item(RsPeerNetItem& ); -RsSerialType* init_item(RsPeerOldNetItem& ); -RsSerialType* init_item(RsPeerGroupItem& ); -RsSerialType* init_item(RsPeerStunItem& ); -RsSerialType* init_item(RsCacheConfig& ); -RsSerialType* init_item(RsFileTransfer& ); - -bool operator==(const RsPeerNetItem&, const RsPeerNetItem& ); -bool operator==(const RsPeerOldNetItem&, const RsPeerOldNetItem& ); -bool operator==(const RsPeerGroupItem&, const RsPeerGroupItem& ); -bool operator==(const RsPeerStunItem&, const RsPeerStunItem& ); -bool operator==(const RsCacheConfig&, const RsCacheConfig& ); -bool operator==(const RsFileTransfer&, const RsFileTransfer& ); - -bool operator==(const std::list&, - const std::list&); - -bool operator!=(const sockaddr_in&, const sockaddr_in&); -bool operator!=(const RsTlvIpAddressInfo&, const RsTlvIpAddressInfo& ); -bool operator!=(const std::list& left, - const std::list& right); -//bool operator==(const RsTlvPeerIdSet& left, const RsTlvPeerIdSet& right); -bool operator==(const RsTlvFileItem&, const RsTlvFileItem& ); - - - -#endif /* RSCONFIGITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rsgrouteritem_test.cc b/libretroshare/src/tests/serialiser/rsgrouteritem_test.cc deleted file mode 100644 index 737b5155f..000000000 --- a/libretroshare/src/tests/serialiser/rsgrouteritem_test.cc +++ /dev/null @@ -1,217 +0,0 @@ -/* - * libretroshare/src/tests/serialiser: msgitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include - -#include "util/rsrandom.h" -#include "grouter/grouteritems.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" -#include "support.h" -#include "rsmsgitem_test.h" - -INITTEST(); - -RsSerialType* init_item(RsGRouterGenericDataItem& cmi) -{ - cmi.data_size = lrand48()%1000 + 1000 ; - cmi.data_bytes = (uint8_t*)malloc(cmi.data_size) ; - RSRandom::random_bytes(cmi.data_bytes,cmi.data_size) ; - cmi.routing_id = RSRandom::random_u32() ; - - Sha1CheckSum cs ; - for(int i=0;i<5;++i) cs.fourbytes[i] = RSRandom::random_u32() ; - cmi.destination_key = cs ; - - return new RsGRouterSerialiser(); -} -RsSerialType* init_item(RsGRouterACKItem& cmi) -{ - cmi.mid = RSRandom::random_u32() ; - cmi.state = RSRandom::random_u32() ; - - return new RsGRouterSerialiser(); -} -RsSerialType* init_item(RsGRouterPublishKeyItem& cmi) -{ - cmi.diffusion_id = RSRandom::random_u32() ; - cmi.service_id = RSRandom::random_u32() ; - cmi.randomized_distance = RSRandom::random_f32() ; - - Sha1CheckSum cs ; - for(int i=0;i<5;++i) cs.fourbytes[i] = RSRandom::random_u32() ; - cmi.published_key = cs ; - cmi.description_string = "test key" ; - - return new RsGRouterSerialiser(); -} -RsSerialType* init_item(RsGRouterRoutingInfoItem& cmi) -{ - cmi.origin = SSLIdType::random() ; - cmi.received_time = RSRandom::random_u64() ; - cmi.status_flags = RSRandom::random_u32() ; - - cmi.data_item = new RsGRouterGenericDataItem ; - - uint32_t n = 10+(RSRandom::random_u32()%30) ; - - for(uint32_t i=0;i 0.001) return false; - if(cmiLeft.description_string != cmiRight.description_string) return false; - - return true ; -} -bool operator ==(const RsGRouterACKItem& cmiLeft,const RsGRouterACKItem& cmiRight) -{ - if(cmiLeft.mid != cmiRight.mid) return false; - if(cmiLeft.state != cmiRight.state) return false; - - return true; -} -bool operator ==(const RsGRouterMatrixCluesItem& cmiLeft,const RsGRouterMatrixCluesItem& cmiRight) -{ - if(!(cmiLeft.destination_key == cmiRight.destination_key)) return false; - if(cmiLeft.clues.size() != cmiRight.clues.size()) return false; - - std::list::const_iterator itl = cmiLeft.clues.begin() ; - std::list::const_iterator itr = cmiRight.clues.begin() ; - - while(itl != cmiLeft.clues.end()) - { - if( (*itl).friend_id != (*itr).friend_id) return false ; - if( (*itl).time_stamp != (*itr).time_stamp) return false ; - - ++itl ; - ++itr ; - } - - return true; -} -bool operator ==(const RsGRouterMatrixFriendListItem& cmiLeft,const RsGRouterMatrixFriendListItem& cmiRight) -{ - if(cmiLeft.reverse_friend_indices.size() != cmiRight.reverse_friend_indices.size()) return false; - - for(uint32_t i=0;i::const_iterator itl(cmiLeft.tried_friends.begin()) ; - std::list::const_iterator itr(cmiRight.tried_friends.begin()) ; - - while(itl != cmiLeft.tried_friends.end()) - { - if( (*itl).friend_id != (*itr).friend_id) return false ; - if( (*itl).time_stamp != (*itr).time_stamp) return false ; - - ++itl ; - ++itr ; - } - - if(!(*cmiLeft.data_item == *cmiRight.data_item)) return false ; - - return true; -} -int main() -{ - test_RsItem(); REPORT("Serialise/Deserialise RsGRouterGenericDataItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsGRouterACKItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsGRouterPublishKeyItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsGRouterRoutingInfoItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsGRouterMatrixFriendListItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsGRouterMatrixCluesItem"); - - std::cerr << std::endl; - - FINALREPORT("RsGRouter Tests"); - - return TESTRESULT(); -} - - - - - diff --git a/libretroshare/src/tests/serialiser/rsgrouteritem_test.h b/libretroshare/src/tests/serialiser/rsgrouteritem_test.h deleted file mode 100644 index 392792fa3..000000000 --- a/libretroshare/src/tests/serialiser/rsgrouteritem_test.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef MSGITEM_TEST_H_ -#define MSGITEM_TEST_H_ - -/* - * libretroshare/src/tests/serialiser: msgitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include -#include "serialiser/rsmsgitems.h" - - -RsSerialType* init_item(RsChatMsgItem& ); -RsSerialType* init_item(RsChatStatusItem& ); -RsSerialType* init_item(RsChatAvatarItem& ); -RsSerialType* init_item(RsMsgItem& ); -RsSerialType* init_item(RsMsgTagType& ); -RsSerialType* init_item(RsMsgTags& ); -RsSerialType* init_item(RsMsgSrcId& ); - -bool operator ==(const RsChatMsgItem& ,const RsChatMsgItem& ); -bool operator ==(const RsChatStatusItem& , const RsChatStatusItem& ); -bool operator ==(const RsChatAvatarItem&, const RsChatAvatarItem& ); -bool operator ==(const RsMsgTagType&, const RsMsgTagType& ); -bool operator ==(const RsMsgTags&, const RsMsgTags& ); -bool operator ==(const RsMsgItem&, const RsMsgItem& ); -bool operator ==(const RsMsgSrcId&, const RsMsgSrcId& ); - -#endif /* MSGITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rsgxsupdateitem_test.cc b/libretroshare/src/tests/serialiser/rsgxsupdateitem_test.cc deleted file mode 100644 index aa858daf7..000000000 --- a/libretroshare/src/tests/serialiser/rsgxsupdateitem_test.cc +++ /dev/null @@ -1,110 +0,0 @@ -/* - * rsgxsupdateitem_test.cc - * - * Created on: 9 Dec 2013 - * Author: crispy - */ - -#include "support.h" -#include "rsgxsupdateitem_test.h" - -INITTEST(); - -RsSerialType* init_item(RsGxsGrpUpdateItem& i) -{ - i.clear(); - i.grpUpdateTS = rand()%2424; - randString(SHORT_STR, i.peerId); - return new RsGxsUpdateSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsGxsMsgUpdateItem& i) -{ - i.clear(); - randString(SHORT_STR, i.peerId); - int numUpdates = rand()%123; - - std::string peer; - for(int j=0; j < numUpdates; j++) - { - randString(SHORT_STR, peer); - i.msgUpdateTS.insert(std::make_pair(peer, rand()%45)); - } - - return new RsGxsUpdateSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsGxsServerGrpUpdateItem& i) -{ - i.clear(); - i.grpUpdateTS = rand()%2424; - - return new RsGxsUpdateSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsGxsServerMsgUpdateItem& i) -{ - i.clear(); - randString(SHORT_STR, i.grpId); - i.msgUpdateTS = rand()%4252; - return new RsGxsUpdateSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -bool operator ==(const RsGxsGrpUpdateItem& l, const RsGxsGrpUpdateItem& r) -{ - bool ok = l.grpUpdateTS == r.grpUpdateTS; - ok &= l.peerId == r.peerId; - - return ok; -} - -bool operator ==(const RsGxsMsgUpdateItem& l, const RsGxsMsgUpdateItem& r) -{ - bool ok = l.peerId == r.peerId; - - const std::map& lUp = l.msgUpdateTS, rUp = r.msgUpdateTS; - - ok &= lUp.size() == rUp.size(); - - std::map::const_iterator lit = lUp.begin(), rit; - - for(; lit != lUp.end(); lit++) - { - std::string key = lit->first; - if((rit = rUp.find(key)) != rUp.end()) - ok &= lit->second == rit->second; - else - return false; - } - - return ok; -} - -bool operator ==(const RsGxsServerGrpUpdateItem& l, - const RsGxsServerGrpUpdateItem& r) -{ - return l.grpUpdateTS == r.grpUpdateTS; -} - -bool operator ==(const RsGxsServerMsgUpdateItem& l, - const RsGxsServerMsgUpdateItem& r) -{ - bool ok = l.grpId == r.grpId; - ok &= l.msgUpdateTS == r.msgUpdateTS; - return ok; -} - - -int main() -{ - std::cerr << "RsGxsUpdateItem Tests" << std::endl; - - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsGxsGrpUpdateItem"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsGxsMsgUpdateItem"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsGxsServerGrpUpdateItem"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsGxsServerMsgUpdateItem"); - - FINALREPORT("RsGxsUpdateItem Tests"); - - return TESTRESULT(); -} diff --git a/libretroshare/src/tests/serialiser/rsgxsupdateitem_test.h b/libretroshare/src/tests/serialiser/rsgxsupdateitem_test.h deleted file mode 100644 index 57a686241..000000000 --- a/libretroshare/src/tests/serialiser/rsgxsupdateitem_test.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * rsgxsupdateitem_test.h - * - * Created on: 9 Dec 2013 - * Author: crispy - */ - -#ifndef RSGXSUPDATEITEM_TEST_H_ -#define RSGXSUPDATEITEM_TEST_H_ - -#include "serialiser/rsgxsupdateitems.h" -#include "support.h" - - -RsSerialType* init_item(RsGxsGrpUpdateItem& i); -RsSerialType* init_item(RsGxsMsgUpdateItem& i); -RsSerialType* init_item(RsGxsServerGrpUpdateItem& i); -RsSerialType* init_item(RsGxsServerMsgUpdateItem& i); - -bool operator==(const RsGxsGrpUpdateItem& l, const RsGxsGrpUpdateItem& r); -bool operator==(const RsGxsMsgUpdateItem& l, const RsGxsMsgUpdateItem& r); -bool operator==(const RsGxsServerGrpUpdateItem& l, const RsGxsServerGrpUpdateItem& r); -bool operator==(const RsGxsServerMsgUpdateItem& l, const RsGxsServerMsgUpdateItem& r); - -#endif /* RSGXSUPDATEITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rsmsgitem_test.cc b/libretroshare/src/tests/serialiser/rsmsgitem_test.cc deleted file mode 100644 index c964d97ba..000000000 --- a/libretroshare/src/tests/serialiser/rsmsgitem_test.cc +++ /dev/null @@ -1,366 +0,0 @@ -/* - * libretroshare/src/tests/serialiser: msgitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include - -#include "util/rsrandom.h" -#include "serialiser/rsmsgitems.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" -#include "support.h" -#include "rsmsgitem_test.h" - -INITTEST(); - -RsSerialType* init_item(RsChatMsgItem& cmi) -{ - cmi.chatFlags = rand()%34; - cmi.sendTime = rand()%422224; - randString(LARGE_STR, cmi.message); - - return new RsChatSerialiser(); -} -RsSerialType* init_item(RsChatLobbyListRequestItem& cmi) -{ - return new RsChatSerialiser(); -} -RsSerialType* init_item(RsChatLobbyListItem& cmi) -{ - int n = rand()%20 ; - - cmi.lobby_ids.resize(n) ; - cmi.lobby_names.resize(n) ; - cmi.lobby_topics.resize(n) ; - cmi.lobby_counts.resize(n) ; - - for(int i=0;i(&cmi)) ; - - cmi.msg_id = RSRandom::random_u64() ; - cmi.lobby_id = RSRandom::random_u64() ; - cmi.nick = "My nickname" ; - cmi.subpacket_id = rand()%256 ; - cmi.parent_msg_id = RSRandom::random_u64() ; - - return serial ; -} -RsSerialType *init_item(RsChatLobbyEventItem& cmi) -{ - cmi.event_type = rand()%256 ; - randString(20, cmi.string1); - - return new RsChatSerialiser(); -} - -RsSerialType* init_item(RsChatLobbyInviteItem& cmi) -{ - cmi.lobby_id = RSRandom::random_u64() ; - cmi.lobby_name = "Name of the lobby" ; - cmi.lobby_topic = "Topic of the lobby" ; - - return new RsChatSerialiser(); -} - -RsSerialType* init_item(RsPrivateChatMsgConfigItem& pcmi) -{ - randString(SHORT_STR, pcmi.configPeerId); - pcmi.chatFlags = rand()%34; - pcmi.configFlags = rand()%21; - pcmi.sendTime = rand()%422224; - randString(LARGE_STR, pcmi.message); - pcmi.recvTime = rand()%344443; - - return new RsChatSerialiser(); -} - -RsSerialType* init_item(RsChatStatusItem& csi) -{ - - randString(SHORT_STR, csi.status_string); - csi.flags = rand()%232; - - return new RsChatSerialiser(); - -} - -RsSerialType* init_item(RsChatAvatarItem& cai) -{ - std::string image_data; - randString(LARGE_STR, image_data); - cai.image_data = new unsigned char[image_data.size()]; - - memcpy(cai.image_data, image_data.c_str(), image_data.size()); - cai.image_size = image_data.size(); - - return new RsChatSerialiser(); -} - -RsSerialType* init_item(RsMsgItem& mi) -{ - init_item(mi.attachment); - init_item(mi.msgbcc); - init_item(mi.msgcc); - init_item(mi.msgto); - - randString(LARGE_STR, mi.message); - randString(SHORT_STR, mi.subject); - - mi.msgId = rand()%324232; - mi.recvTime = rand()%44252; - mi.sendTime = mi.recvTime; - mi.msgFlags = mi.recvTime; - - return new RsMsgSerialiser(true); -} - -RsSerialType* init_item(RsMsgTagType& mtt) -{ - mtt.rgb_color = rand()%5353; - mtt.tagId = rand()%24242; - randString(SHORT_STR, mtt.text); - - return new RsMsgSerialiser(); -} - - -RsSerialType* init_item(RsMsgTags& mt) -{ - mt.msgId = rand()%3334; - - int i; - for (i = 0; i < 10; i++) { - mt.tagIds.push_back(rand()%21341); - } - - return new RsMsgSerialiser(); -} - -RsSerialType* init_item(RsMsgSrcId& ms) -{ - ms.msgId = rand()%434; - randString(SHORT_STR, ms.srcId); - - return new RsMsgSerialiser(); -} - -RsSerialType* init_item(RsMsgParentId& ms) -{ - ms.msgId = rand()%354; - ms.msgParentId = rand()%476; - - return new RsMsgSerialiser(); -} - -bool operator ==(const RsChatLobbyListItem& cmiLeft,const RsChatLobbyListItem& cmiRight) -{ - if(cmiLeft.lobby_ids.size() != cmiRight.lobby_ids.size()) return false; - if(cmiLeft.lobby_names.size() != cmiRight.lobby_names.size()) return false; - if(cmiLeft.lobby_topics.size() != cmiRight.lobby_topics.size()) return false; - if(cmiLeft.lobby_counts.size() != cmiRight.lobby_counts.size()) return false; - - for(uint32_t i=0;i(); REPORT("Serialise/Deserialise RsChatMsgItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatLobbyMsgItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatLobbyInviteItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatLobbyEventItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatLobbyListRequestItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatLobbyListItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatStatusItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatAvatarItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsMsgItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsMsgTagType"); - test_RsItem(); REPORT("Serialise/Deserialise RsMsgTags"); - test_RsItem(); REPORT("Serialise/Deserialise RsMsgSrcId"); - test_RsItem(); REPORT("Serialise/Deserialise RsMsgParentId"); - - std::cerr << std::endl; - - FINALREPORT("RsMsgItem Tests"); - - return TESTRESULT(); -} - - - - - diff --git a/libretroshare/src/tests/serialiser/rsmsgitem_test.h b/libretroshare/src/tests/serialiser/rsmsgitem_test.h deleted file mode 100644 index 392792fa3..000000000 --- a/libretroshare/src/tests/serialiser/rsmsgitem_test.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef MSGITEM_TEST_H_ -#define MSGITEM_TEST_H_ - -/* - * libretroshare/src/tests/serialiser: msgitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include -#include "serialiser/rsmsgitems.h" - - -RsSerialType* init_item(RsChatMsgItem& ); -RsSerialType* init_item(RsChatStatusItem& ); -RsSerialType* init_item(RsChatAvatarItem& ); -RsSerialType* init_item(RsMsgItem& ); -RsSerialType* init_item(RsMsgTagType& ); -RsSerialType* init_item(RsMsgTags& ); -RsSerialType* init_item(RsMsgSrcId& ); - -bool operator ==(const RsChatMsgItem& ,const RsChatMsgItem& ); -bool operator ==(const RsChatStatusItem& , const RsChatStatusItem& ); -bool operator ==(const RsChatAvatarItem&, const RsChatAvatarItem& ); -bool operator ==(const RsMsgTagType&, const RsMsgTagType& ); -bool operator ==(const RsMsgTags&, const RsMsgTags& ); -bool operator ==(const RsMsgItem&, const RsMsgItem& ); -bool operator ==(const RsMsgSrcId&, const RsMsgSrcId& ); - -#endif /* MSGITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rsnxsitems_test.cc b/libretroshare/src/tests/serialiser/rsnxsitems_test.cc deleted file mode 100644 index b2dab65e9..000000000 --- a/libretroshare/src/tests/serialiser/rsnxsitems_test.cc +++ /dev/null @@ -1,187 +0,0 @@ - -#include "support.h" - -#include "rsnxsitems_test.h" - -INITTEST(); - -#define NUM_BIN_OBJECTS 5 -#define NUM_SYNC_MSGS 8 -#define NUM_SYNC_GRPS 5 - -RsSerialType* init_item(RsNxsGrp& nxg) -{ - nxg.clear(); - - randString(SHORT_STR, nxg.grpId); - nxg.transactionNumber = rand()%23; - init_item(nxg.grp); - init_item(nxg.meta); - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - - -RsSerialType* init_item(RsNxsMsg& nxm) -{ - nxm.clear(); - - randString(SHORT_STR, nxm.msgId); - randString(SHORT_STR, nxm.grpId); - init_item(nxm.msg); - init_item(nxm.meta); - nxm.transactionNumber = rand()%23; - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsNxsSyncGrp& rsg) -{ - rsg.clear(); - rsg.flag = RsNxsSyncGrp::FLAG_USE_SYNC_HASH; - rsg.createdSince = rand()%2423; - randString(3124,rsg.syncHash); - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsNxsSyncMsg& rsgm) -{ - rsgm.clear(); - - rsgm.flag = RsNxsSyncMsg::FLAG_USE_SYNC_HASH; - rsgm.createdSince = rand()%24232; - rsgm.transactionNumber = rand()%23; - randString(SHORT_STR, rsgm.grpId); - randString(SHORT_STR, rsgm.syncHash); - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsNxsSyncGrpItem& rsgl) -{ - rsgl.clear(); - - rsgl.flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - rsgl.transactionNumber = rand()%23; - rsgl.publishTs = rand()%23; - randString(SHORT_STR, rsgl.grpId); - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsNxsSyncMsgItem& rsgml) -{ - rsgml.clear(); - - rsgml.flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - rsgml.transactionNumber = rand()%23; - randString(SHORT_STR, rsgml.grpId); - randString(SHORT_STR, rsgml.msgId); - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsNxsTransac& rstx){ - - rstx.clear(); - - rstx.timestamp = rand()%14141; - rstx.transactFlag = rand()%2424; - rstx.nItems = rand()%33132; - rstx.transactionNumber = rand()%242112; - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -bool operator==(const RsNxsGrp& l, const RsNxsGrp& r){ - - if(l.grpId != r.grpId) return false; - if(!(l.grp == r.grp) ) return false; - if(!(l.meta == r.meta) ) return false; - if(l.transactionNumber != r.transactionNumber) return false; - - return true; -} - -bool operator==(const RsNxsMsg& l, const RsNxsMsg& r){ - - if(l.msgId != r.msgId) return false; - if(l.grpId != r.grpId) return false; - if(! (l.msg == r.msg) ) return false; - if(! (l.meta == r.meta) ) return false; - if(l.transactionNumber != r.transactionNumber) return false; - - return true; -} - -bool operator==(const RsNxsSyncGrp& l, const RsNxsSyncGrp& r) -{ - - if(l.syncHash != r.syncHash) return false; - if(l.flag != r.flag) return false; - if(l.createdSince != r.createdSince) return false; - if(l.transactionNumber != r.transactionNumber) return false; - - return true; -} - -bool operator==(const RsNxsSyncMsg& l, const RsNxsSyncMsg& r) -{ - - if(l.flag != r.flag) return false; - if(l.createdSince != r.createdSince) return false; - if(l.syncHash != r.syncHash) return false; - if(l.grpId != r.grpId) return false; - if(l.transactionNumber != r.transactionNumber) return false; - - return true; -} - -bool operator==(const RsNxsSyncGrpItem& l, const RsNxsSyncGrpItem& r) -{ - if(l.flag != r.flag) return false; - if(l.publishTs != r.publishTs) return false; - if(l.grpId != r.grpId) return false; - if(l.transactionNumber != r.transactionNumber) return false; - - return true; -} - -bool operator==(const RsNxsSyncMsgItem& l, const RsNxsSyncMsgItem& r) -{ - if(l.flag != r.flag) return false; - if(l.grpId != r.grpId) return false; - if(l.msgId != r.msgId) return false; - if(l.transactionNumber != r.transactionNumber) return false; - - return true; -} - -bool operator==(const RsNxsTransac& l, const RsNxsTransac& r){ - - if(l.transactFlag != r.transactFlag) return false; - if(l.transactionNumber != r.transactionNumber) return false; - if(l.timestamp != r.timestamp) return false; - if(l.nItems != r.nItems) return false; - - - return true; -} - -int main() -{ - std::cerr << "RsNxsItem Tests" << std::endl; - - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsGrpResp"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsGrpMsgResp"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsNxsSyncGrp"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsNxsSyncMsg"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsNxsSyncGrpItem"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsNxsSyncMsgItem"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsNxsTransac"); - - FINALREPORT("RsNxsItem Tests"); - - return TESTRESULT(); -} diff --git a/libretroshare/src/tests/serialiser/rsnxsitems_test.h b/libretroshare/src/tests/serialiser/rsnxsitems_test.h deleted file mode 100644 index 31dae24b7..000000000 --- a/libretroshare/src/tests/serialiser/rsnxsitems_test.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef RSNXSITEMS_TEST_H -#define RSNXSITEMS_TEST_H - -#include "serialiser/rsnxsitems.h" - - -RsSerialType* init_item(RsNxsGrp&); -RsSerialType* init_item(RsNxsMsg&); -RsSerialType* init_item(RsNxsSyncGrp&); -RsSerialType* init_item(RsNxsSyncMsg&); -RsSerialType* init_item(RsNxsSyncGrpItem&); -RsSerialType* init_item(RsNxsSyncMsgItem&); -RsSerialType* init_item(RsNxsTransac& ); - -bool operator==(const RsNxsGrp&, const RsNxsGrp&); -bool operator==(const RsNxsMsg&, const RsNxsMsg&); -bool operator==(const RsNxsSyncGrp&, const RsNxsSyncGrp&); -bool operator==(const RsNxsSyncMsg&, const RsNxsSyncMsg&); -bool operator==(const RsNxsSyncGrpItem&, const RsNxsSyncGrpItem&); -bool operator==(const RsNxsSyncMsgItem&, const RsNxsSyncMsgItem&); -bool operator==(const RsNxsTransac&, const RsNxsTransac& ); - - -#endif // RSNXSITEMS_TEST_H diff --git a/libretroshare/src/tests/serialiser/rsphotoitem_test.cc b/libretroshare/src/tests/serialiser/rsphotoitem_test.cc deleted file mode 100644 index fafd1650d..000000000 --- a/libretroshare/src/tests/serialiser/rsphotoitem_test.cc +++ /dev/null @@ -1,139 +0,0 @@ -/* - * libretroshare/src/test rsphotoitem_test.cc - * - * Test for photo item serialisation - * - * Copyright 2012-2012 by Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include "rsphotoitem_test.h" - - -RsSerialType* init_item(RsGxsPhotoAlbumItem &album) -{ - RsPhotoAlbum& a = album.album; - - randString(SHORT_STR, a.mCaption); - randString(SHORT_STR, a.mCategory); - randString(SHORT_STR, a.mDescription); - randString(SHORT_STR, a.mHashTags); - randString(SHORT_STR, a.mOther); - randString(SHORT_STR, a.mPhotoPath); - randString(SHORT_STR, a.mPhotographer); - randString(SHORT_STR, a.mWhen); - randString(SHORT_STR, a.mWhere); - randString(SHORT_STR, a.mThumbnail.type); - std::string rStr; - randString(SHORT_STR, rStr); - - a.mThumbnail.data = new uint8_t[SHORT_STR]; - memcpy(a.mThumbnail.data, rStr.data(), SHORT_STR); - a.mThumbnail.size = SHORT_STR; - - return new RsGxsPhotoSerialiser(); -} - -RsSerialType* init_item(RsGxsPhotoPhotoItem &photo) -{ - - RsPhotoPhoto& p = photo.photo; - - randString(SHORT_STR, p.mCaption); - randString(SHORT_STR, p.mCategory); - randString(SHORT_STR, p.mDescription); - randString(SHORT_STR, p.mHashTags); - randString(SHORT_STR, p.mOther); - randString(SHORT_STR, p.mPhotographer); - randString(SHORT_STR, p.mWhen); - randString(SHORT_STR, p.mWhere); - randString(SHORT_STR, p.mThumbnail.type); - std::string rStr; - randString(SHORT_STR, rStr); - - p.mThumbnail.data = new uint8_t[SHORT_STR]; - memcpy(p.mThumbnail.data, rStr.data(), SHORT_STR); - p.mThumbnail.size = SHORT_STR; - - return new RsGxsPhotoSerialiser(); -} - - -bool operator == (RsGxsPhotoAlbumItem& l, RsGxsPhotoAlbumItem& r) -{ - RsPhotoAlbum& la = l.album; - RsPhotoAlbum& ra = r.album; - - if(la.mCaption != ra.mCaption) return false; - if(la.mCategory != ra.mCategory) return false; - if(la.mDescription != ra.mDescription) return false; - if(la.mHashTags != ra.mHashTags) return false; - if(la.mOther != ra.mOther) return false; - if(la.mPhotographer!= ra.mPhotographer) return false; - if(la.mPhotoPath != ra.mPhotoPath) return false; - if(la.mWhere != ra.mWhere) return false; - if(la.mWhen != ra.mWhen) return false; - if(!(la.mThumbnail == ra.mThumbnail)) return false; - - return true; -} - - - -bool operator == (RsGxsPhotoPhotoItem& l, RsGxsPhotoPhotoItem& r) -{ - RsPhotoPhoto& la = l.photo; - RsPhotoPhoto& ra = r.photo; - - if(la.mCaption != ra.mCaption) return false; - if(la.mCategory != ra.mCategory) return false; - if(la.mDescription != ra.mDescription) return false; - if(la.mHashTags != ra.mHashTags) return false; - if(la.mOther != ra.mOther) return false; - if(la.mPhotographer!= ra.mPhotographer) return false; - if(la.mWhere != ra.mWhere) return false; - if(la.mWhen != ra.mWhen) return false; - if(!(la.mThumbnail == ra.mThumbnail)) return false; - - return true; -} - -bool operator == (RsPhotoThumbnail& l, RsPhotoThumbnail& r) -{ - if(l.size != r.size) return false; - if(l.type != r.type) return false; - if(memcmp(l.data, r.data,l.size) != 0) return false; - - return true; -} - -INITTEST() - -int main() -{ - std::cerr << "RsPhotoItem Tests" << std::endl; - - test_RsItem(); REPORT("Serialise/Deserialise RsGxsPhotoAlbumItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsGxsPhotoPhotoItem"); - - FINALREPORT("RsPhotoItem Tests"); - - return TESTRESULT(); -} diff --git a/libretroshare/src/tests/serialiser/rsphotoitem_test.h b/libretroshare/src/tests/serialiser/rsphotoitem_test.h deleted file mode 100644 index cd726198e..000000000 --- a/libretroshare/src/tests/serialiser/rsphotoitem_test.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * libretroshare/src/test rsphotoitem_test.h - * - * Test for photo item serialisation - * - * Copyright 2012-2012 by Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef RSPHOTOITEM_TEST_H_ -#define RSPHOTOITEM_TEST_H_ - -#include "serialiser/rsphotov2items.h" -#include "support.h" - - - -RsSerialType* init_item(RsGxsPhotoAlbumItem& album); -RsSerialType* init_item(RsGxsPhotoPhotoItem& photo); - -bool operator == (RsGxsPhotoAlbumItem& l, RsGxsPhotoAlbumItem& r); -bool operator == (RsGxsPhotoPhotoItem& l, RsGxsPhotoPhotoItem& r); -bool operator == (RsPhotoThumbnail& l, RsPhotoThumbnail& r); - -#endif /* RSPHOTOITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rsserial_test.cc b/libretroshare/src/tests/serialiser/rsserial_test.cc deleted file mode 100644 index e9193fee0..000000000 --- a/libretroshare/src/tests/serialiser/rsserial_test.cc +++ /dev/null @@ -1,136 +0,0 @@ - -/* - * libretroshare/src/serialiser: rsserial_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - * tlvfileitem test. - * - * - */ - -#include -#include -#include "serialiser/rsserial.h" -#include "serialiser/rsbaseitems.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" - -INITTEST(); - -static int test_RsFileItem(); -static int test_RsFileData(); - -int main() -{ - std::cerr << "RsFile[Item/Data/...] Tests" << std::endl; - - - test_RsFileItem(); - //test_RsFileData(); - - FINALREPORT("RsTlvFile[Item/Data/...] Tests"); - - return TESTRESULT(); -} - -int test_RsFileItem() -{ - /* make a serialisable FileItem */ - - RsSerialiser srl; - RsFileRequest rsfi; - - /* initialise */ - rsfi.file.filesize = 101010; - rsfi.file.hash = "ABCDEFEGHE"; - rsfi.file.name = "TestFile.txt"; - rsfi.file.pop = 12; - rsfi.file.age = 456; - - /* attempt to serialise it before we add it to the serialiser */ - - CHECK(0 == srl.size(&rsfi)); - -#define MAX_BUFSIZE 16000 - - char buffer[MAX_BUFSIZE]; - uint32_t sersize = MAX_BUFSIZE; - - CHECK(false == srl.serialise(&rsfi, (void *) buffer, &sersize)); - - - /* now add to serialiser */ - - RsFileItemSerialiser *rsfis = new RsFileItemSerialiser(); - srl.addSerialType(rsfis); - - uint32_t size = srl.size(&rsfi); - bool done = srl.serialise(&rsfi, (void *) buffer, &sersize); - - std::cerr << "test_RsFileItem() size: " << size << std::endl; - std::cerr << "test_RsFileItem() done: " << done << std::endl; - std::cerr << "test_RsFileItem() sersize: " << sersize << std::endl; - - std::cerr << "test_RsFileItem() serialised:" << std::endl; - displayRawPacket(std::cerr, (void *) buffer, sersize); - - CHECK(done == true); - - uint32_t sersize2 = sersize; - RsItem *output = srl.deserialise((void *) buffer, &sersize2); - - CHECK(output != NULL); - CHECK(sersize2 == sersize); - - RsFileRequest *outfi = dynamic_cast(output); - - CHECK(outfi != NULL); - - if (outfi) - { - /* check the data is the same */ - CHECK(rsfi.file.filesize == outfi->file.filesize); - CHECK(rsfi.file.hash == outfi->file.hash); - CHECK(rsfi.file.name == outfi->file.name); - CHECK(rsfi.file.path == outfi->file.path); - CHECK(rsfi.file.pop == outfi->file.pop); - CHECK(rsfi.file.age == outfi->file.age); - } - - sersize2 = MAX_BUFSIZE; - bool done2 = srl.serialise(outfi, (void *) &(buffer[16*8]), &sersize2); - - CHECK(sersize2 == sersize); - - displayRawPacket(std::cerr, (void *) buffer, 16 * 8 + sersize2); - - - REPORT("Serialise/Deserialise RsFileRequest"); - - return 1; -} - - - diff --git a/libretroshare/src/tests/serialiser/rsstatusitem_test.cc b/libretroshare/src/tests/serialiser/rsstatusitem_test.cc deleted file mode 100644 index db6d5c181..000000000 --- a/libretroshare/src/tests/serialiser/rsstatusitem_test.cc +++ /dev/null @@ -1,60 +0,0 @@ -/* - * libretroshare/src/tests/serialiser: rsstatusitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include "support.h" -#include "rsstatusitem_test.h" - -INITTEST(); - -RsSerialType* init_item(RsStatusItem& rsi) -{ - - rsi.sendTime = rand()%5353; - rsi.status = rand()%2032; - return new RsStatusSerialiser(); -} - -bool operator ==(RsStatusItem& rsi1, RsStatusItem& rsi2) -{ - // note: recv time is not serialised - - if(rsi1.sendTime != rsi2.sendTime) return false; - if(rsi1.status != rsi2.status) return false; - - return true; -} - - -int main() -{ - - std::cerr << "RsStatusItem Tests" << std::endl; - - test_RsItem(); REPORT("Serialise/Deserialise RsStatusItem"); - FINALREPORT("RsStatusItem Tests"); - - return TESTRESULT(); -} diff --git a/libretroshare/src/tests/serialiser/rsstatusitem_test.h b/libretroshare/src/tests/serialiser/rsstatusitem_test.h deleted file mode 100644 index cf25c5429..000000000 --- a/libretroshare/src/tests/serialiser/rsstatusitem_test.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef RSSTATUS_TEST_H_ -#define RSSTATUS_TEST_H_ - -/* - * libretroshare/src/tests/serialiser: rsstatusitem_test.h - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "serialiser/rsstatusitems.h" - -RsSerialType* init_item(RsStatusItem& ); - -bool operator ==(RsStatusItem& , RsStatusItem& ); - -#endif /* RSSTATUS_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rstlvutil.cc b/libretroshare/src/tests/serialiser/rstlvutil.cc deleted file mode 100644 index 51d1fe1c5..000000000 --- a/libretroshare/src/tests/serialiser/rstlvutil.cc +++ /dev/null @@ -1,187 +0,0 @@ - -/* - * libretroshare/src/serialiser: rstlvutil.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -/* some utility functions mainly for debugging - * - * - * - */ - -#include "serialiser/rstlvutil.h" - -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvitem.h" -#include "util/rsstring.h" -#include "util/utest.h" - -#include -#include - -#if 0 -/* print out a packet */ -#include -#include - - -#endif - -void displayRawPacket(std::ostream &out, void *data, uint32_t size) -{ - uint32_t i; - std::string sout; - rs_sprintf(sout, "DisplayRawPacket: Size: %ld", size); - - for(i = 0; i < size; i++) - { - if (i % 16 == 0) - { - sout += "\n"; - } - rs_sprintf_append(sout, "%02x:", (int) (((unsigned char *) data)[i])); - } - - out << sout << std::endl; -} - - -#define WHOLE_64K_SIZE 65536 - -int test_SerialiseTlvItem(std::ostream &str, RsTlvItem *in, RsTlvItem *out) -{ - uint16_t initsize = in->TlvSize(); - uint32_t serialOffset = 0; - uint32_t deserialOffset = 0; - - str << "test_SerialiseTlvItem() Testing ... Print/Serialise/Deserialise"; - str << std::endl; - - - /* some space to serialise into */ - unsigned char serbuffer[WHOLE_64K_SIZE]; - - CHECK(in->SetTlv(serbuffer, WHOLE_64K_SIZE, &serialOffset)); - - CHECK(serialOffset == initsize); /* check that the offset matches the size */ - CHECK(in->TlvSize() == initsize); /* check size hasn't changed */ - - REPORT("Serialise RsTlvItem"); - - /* now we try to read it back in! */ - CHECK(out->GetTlv(serbuffer, serialOffset, &deserialOffset)); - - /* again check sizes */ - CHECK(serialOffset == deserialOffset); - CHECK(deserialOffset == initsize); - CHECK(out->TlvSize() == initsize); - - str << "Class In/Serialised/Out!" << std::endl; - in->print(str, 0); - displayRawPacket(str, serbuffer, serialOffset); - out->print(str, 0); - - /* Can't check the actual data -> should add function */ - REPORT("DeSerialise RsTlvFileItem"); - - /* print it out */ - - - return 1; -} - -/* This function checks the TLV header, and steps on to the next one - */ - -bool test_StepThroughTlvStack(std::ostream &str, void *data, int size) -{ - uint32_t offset = 0; - uint32_t index = 0; - while (offset + 4 <= size) - { - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[offset]) ); - uint16_t tlvsize = GetTlvSize( &(((uint8_t *) data)[offset]) ); - str << "Tlv Entry[" << index << "] => Offset: " << offset; - str << " Type: " << tlvtype; - str << " Size: " << tlvsize; - str << std::endl; - - offset += tlvsize; - } - CHECK(offset == size); /* we match up exactly */ - - REPORT("Step Through RsTlvStack"); - return 1; -} - - -int test_CreateTlvStack(std::ostream &str, - std::vector items, void *data, uint32_t *totalsize) -{ - /* (1) select a random item - * (2) check size -> if okay serialise onto the end - * (3) loop!. - */ - uint32_t offset = 0; - uint32_t count = 0; - - while(1) - { - int idx = (int) (items.size() * (rand() / (RAND_MAX + 1.0))); - uint32_t tlvsize = items[idx] -> TlvSize(); - - if (offset + tlvsize > *totalsize) - { - *totalsize = offset; - return count; - } - - str << "Stack[" << count << "]"; - str << " Offset: " << offset; - str << " TlvSize: " << tlvsize; - str << std::endl; - - /* serialise it */ - items[idx] -> SetTlv(data, *totalsize, &offset); - items[idx] -> print(str, 10); - count++; - } - *totalsize = offset; - return 0; -} - -int test_TlvSet(std::vector items, int maxsize) -{ - int totalsize = maxsize; - void *data = malloc(totalsize); - uint32_t size = totalsize; - - test_CreateTlvStack(std::cerr, items, data, &size); - test_StepThroughTlvStack(std::cerr, data, size); - - return 1; -} - - diff --git a/libretroshare/src/tests/serialiser/rstlvutil.h b/libretroshare/src/tests/serialiser/rstlvutil.h deleted file mode 100644 index 910c494d3..000000000 --- a/libretroshare/src/tests/serialiser/rstlvutil.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef RS_TLV_UTIL_H -#define RS_TLV_UTIL_H - -/* - * libretroshare/src/serialiser: rstlvutil.h - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* some utility functions mainly for debugging - */ - -#include -#include -#include - -class RsTlvItem; - -/* print out a packet */ -void displayRawPacket(std::ostream &out, void *data, uint32_t size); -int test_SerialiseTlvItem(std::ostream &str, RsTlvItem *in, RsTlvItem *out); - - -bool test_StepThroughTlvStack(std::ostream &str, void *data, int size); -int test_CreateTlvStack(std::ostream &str, - std::vector items, void *data, int totalsize); -int test_TlvSet(std::vector items, int maxsize); - -#endif diff --git a/libretroshare/src/tests/serialiser/rstlvwidetest.cc b/libretroshare/src/tests/serialiser/rstlvwidetest.cc deleted file mode 100644 index 91f663387..000000000 --- a/libretroshare/src/tests/serialiser/rstlvwidetest.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* - * libretroshare/src/serialiser: rstlvkvwidetest.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Chris Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include -#include -#include -#include "serialiser/rstlvkvwide.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" - - -INITTEST(); - - /* define utility functions to test out with */ - - //static int testRstlvWide(); -static int testRsTlvWideSet(); - -int main() -{ - std::cerr << "RsTlvWideTest[Item/Data/...] Tests" << std::endl; - - testRsTlvWideSet(); - - FINALREPORT("RsTlvWideTest[Item/Data/...] Tests"); - - return TESTRESULT(); -} - -int testRsTlvWideSet() -{ - RsTlvKeyValueWideSet i1, i2; // one to set and other to get - RsTlvKeyValueWide i_pair; // input pair - RsTlvFileItem hello; - - std::string randString("it should work now."); - int j, k; - - std::cerr << "entering loop now" << std::endl; - /* store a 15 random pairs */ - - for(int i = 0; i < 15 ; i++) - { - j = rand() % 4; - k = rand() % 4; - std::cerr << "j: " << j << " k: " << k << std::endl; - i_pair.wKey.assign(randString.begin(), randString.end()); - std::cerr << "loop count:" << i << std::endl; - i_pair.wValue.assign(randString.begin(), randString.end()); - std::cerr << "loop count:" << i << std::endl; - i1.wPairs.push_back(i_pair); - - i_pair.TlvClear(); - } - - std::cerr << "out of loop now" << std::endl; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /*check that the data is the same*/ - - REPORT("Serialize/Deserialize RsTlvKeyValueWideSet"); - - return 1; -} diff --git a/libretroshare/src/tests/serialiser/rstunnelitem_test.cc b/libretroshare/src/tests/serialiser/rstunnelitem_test.cc deleted file mode 100644 index 88de02517..000000000 --- a/libretroshare/src/tests/serialiser/rstunnelitem_test.cc +++ /dev/null @@ -1,108 +0,0 @@ - -/* - * libretroshare/src/serialiser: rstunnelitems_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - */ - -#include -#include -#include -#include -#include "util/utest.h" -#include "support.h" - - - -RsTunnelSerialiser* init_item(RsTunnelDataItem& item) -{ - uint32_t S = rand()%20000 ; - item.encoded_data = malloc(S) ; - item.encoded_data_len = S ; - for(uint32_t i=0;i(); REPORT("Serialise/Deserialise RsTunnelDataItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsTunnelHandshakeItem"); - } - - FINALREPORT("RstunnelItem Tests"); - - return TESTRESULT(); -} - - diff --git a/libretroshare/src/tests/serialiser/rsturtleitem_test.cc b/libretroshare/src/tests/serialiser/rsturtleitem_test.cc deleted file mode 100644 index e7030818f..000000000 --- a/libretroshare/src/tests/serialiser/rsturtleitem_test.cc +++ /dev/null @@ -1,255 +0,0 @@ - -/* - * libretroshare/src/serialiser: rsturtleitems_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - */ - -#include -#include -#include "turtle/rsturtleitem.h" -#include "ft/ftturtlefiletransferitem.h" -#include -#include "support.h" -#include "util/utest.h" - -INITTEST(); - -RsSerialType* init_item(CompressedChunkMap& map) -{ - map._map.clear() ; - for(uint32_t i=0;i<15;++i) - map._map.push_back(rand()) ; - - return new RsTurtleSerialiser(); -} -bool operator==(const CompressedChunkMap& m1,const CompressedChunkMap& m2) -{ - if(m1._map.size() != m2._map.size()) return false ; - - for(uint32_t i=0;i::const_iterator i1(it1.result.begin()) ; - std::list::const_iterator i2(it2.result.begin()) ; - - for(;i1!=it1.result.end() && i2!=it2.result.end();++i1,++i2) - if( !(*i1 == *i2)) - return false ; - - return true ; -} - -int main() -{ - std::cerr << "RsTurtleItem Tests" << std::endl; - - for(uint32_t i=0;i<20;++i) - { - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleFileMapRequestItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleFileMapItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleFileDataItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleFileRequestItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleTunnelOkItem "); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleOpenTunnelItem "); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleSearchResultItem "); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleStringSearchRequestItem "); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleRegExpSearchRequestItem "); - } - - FINALREPORT("RsturtleItem Tests"); - - return TESTRESULT(); -} - - diff --git a/libretroshare/src/tests/serialiser/support.cc b/libretroshare/src/tests/serialiser/support.cc deleted file mode 100644 index 9fbda2e1f..000000000 --- a/libretroshare/src/tests/serialiser/support.cc +++ /dev/null @@ -1,294 +0,0 @@ -/* - * libretroshare/src/serialiser: t_support.h.cc - * - * RetroShare Serialiser tests. - * - * Copyright 2007-2008 by Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include - -#include "support.h" -#include "serialiser/rstlvbase.h" - -void randString(const uint32_t length, std::string& outStr) -{ - char alpha = 'a'; - char* stringData = NULL; - - stringData = new char[length]; - - for(uint32_t i=0; i != length; i++) - stringData[i] = alpha + (rand() % 26); - - outStr.assign(stringData, length); - delete[] stringData; - - return; -} - -void randString(const uint32_t length, std::wstring& outStr) -{ - wchar_t alpha = L'a'; - wchar_t* stringData = NULL; - - stringData = new wchar_t[length]; - - for(uint32_t i=0; i != length; i++) - stringData[i] = (alpha + (rand() % 26)); - - outStr.assign(stringData, length); - delete[] stringData; - - return; -} - -bool operator==(const RsTlvSecurityKey& sk1, const RsTlvSecurityKey& sk2) -{ - - if(sk1.startTS != sk2.startTS) return false; - if(sk1.endTS != sk2.endTS) return false; - if(sk1.keyFlags != sk2.keyFlags) return false; - if(sk1.keyId != sk2.keyId) return false; - if(!(sk1.keyData == sk1.keyData)) return false; - - return true; -} - -bool operator==(const RsTlvKeySignature& ks1, const RsTlvKeySignature& ks2) -{ - - if(ks1.keyId != ks2.keyId) return false; - if(!(ks1.signData == ks2.signData)) return false; - - return true; -} - -bool operator==(const RsTlvKeySignatureSet& kss1, const RsTlvKeySignatureSet& kss2) -{ - const std::map& set1 = kss1.keySignSet, - &set2 = kss2.keySignSet; - - if(set1.size() != set2.size()) return false; - - std::map::const_iterator it1 = set1.begin(), it2; - - for(; it1 != set1.end(); it1++) - { - SignType st1 = it1->first; - - if( (it2 =set2.find(st1)) == set2.end()) - return false; - - if(!(it1->second == it2->second)) - return false; - - } - - return true; -} - -bool operator==(const RsTlvPeerIdSet& pids1, const RsTlvPeerIdSet& pids2) -{ - std::list::const_iterator it1 = pids1.ids.begin(), - it2 = pids2.ids.begin(); - - - for(; ((it1 != pids1.ids.end()) && (it2 != pids2.ids.end())); it1++, it2++) - { - if(*it1 != *it2) return false; - } - - return true; - -} - - -void init_item(RsTlvImage& im) -{ - std::string imageData; - randString(LARGE_STR, imageData); - im.binData.setBinData(imageData.c_str(), imageData.size()); - im.image_type = RSTLV_IMAGE_TYPE_PNG; - - return; -} - -bool operator==(const RsTlvBinaryData& bd1, const RsTlvBinaryData& bd2) -{ - if(bd1.tlvtype != bd2.tlvtype) return false; - if(bd1.bin_len != bd2.bin_len) return false; - - unsigned char *bin1 = (unsigned char*)(bd1.bin_data), - *bin2 = (unsigned char*)(bd2.bin_data); - - for(uint32_t i=0; i < bd1.bin_len; bin1++, bin2++, i++) - { - if(*bin1 != *bin2) - return false; - } - - return true; -} - - -void init_item(RsTlvSecurityKey& sk) -{ - int randnum = rand()%313131; - - sk.endTS = randnum; - sk.keyFlags = randnum; - sk.startTS = randnum; - randString(SHORT_STR, sk.keyId); - - std::string randomStr; - randString(LARGE_STR, randomStr); - - sk.keyData.setBinData(randomStr.c_str(), randomStr.size()); - - return; -} - -void init_item(RsTlvKeySignature& ks) -{ - randString(SHORT_STR, ks.keyId); - - std::string signData; - randString(LARGE_STR, signData); - - ks.signData.setBinData(signData.c_str(), signData.size()); - - return; -} -void init_item(RsTlvKeySignatureSet &kss) -{ - int numSign = rand()%21; - - for(int i=0; i < numSign; i++) - { - RsTlvKeySignature sign; - SignType sType = rand()%2452; - init_item(sign); - kss.keySignSet.insert(std::make_pair(sType, sign)); - } -} - - -bool operator==(const RsTlvImage& img1, const RsTlvImage& img2) -{ - if(img1.image_type != img2.image_type) return false; - if(!(img1.binData == img2.binData)) return false; - - return true; - -} - -/** channels, forums and blogs **/ - -void init_item(RsTlvHashSet& hs) -{ - for(int i=0; i < 10; i++) - hs.ids.push_back(RsFileHash::random()); - - return; -} - -void init_item(RsTlvPeerIdSet& ps) -{ - for(int i=0; i < 10; i++) - ps.ids.push_back(RsPeerId::random()); - - return; -} - -bool operator==(const RsTlvHashSet& hs1,const RsTlvHashSet& hs2) -{ - std::list::const_iterator it1 = hs1.ids.begin(), - it2 = hs2.ids.begin(); - - for(; ((it1 != hs1.ids.end()) && (it2 != hs2.ids.end())); it1++, it2++) - { - if(*it1 != *it2) return false; - } - - return true; -} - -void init_item(RsTlvFileItem& fi) -{ - fi.age = rand()%200; - fi.filesize = rand()%34030313; - fi.hash = RsFileHash::random(); - randString(SHORT_STR, fi.name); - randString(SHORT_STR, fi.path); - fi.piecesize = rand()%232; - fi.pop = rand()%2354; - init_item(fi.hashset); - - return; -} - -void init_item(RsTlvBinaryData& bd){ - bd.TlvClear(); - std::string data; - randString(LARGE_STR, data); - bd.setBinData(data.data(), data.length()); -} - -void init_item(RsTlvFileSet& fSet){ - - randString(LARGE_STR, fSet.comment); - randString(SHORT_STR, fSet.title); - RsTlvFileItem fi1, fi2; - init_item(fi1); - init_item(fi2); - fSet.items.push_back(fi1); - fSet.items.push_back(fi2); - - return; -} - -bool operator==(const RsTlvFileSet& fs1,const RsTlvFileSet& fs2) -{ - if(fs1.comment != fs2.comment) return false; - if(fs1.title != fs2.title) return false; - - std::list::const_iterator it1 = fs1.items.begin(), - it2 = fs2.items.begin(); - - for(; ((it1 != fs1.items.end()) && (it2 != fs2.items.end())); it1++, it2++) - if(!(*it1 == *it2)) return false; - - return true; -} - -bool operator==(const RsTlvFileItem& fi1,const RsTlvFileItem& fi2) -{ - if(fi1.age != fi2.age) return false; - if(fi1.filesize != fi2.filesize) return false; - if(fi1.hash != fi2.hash) return false; - if(!(fi1.hashset == fi2.hashset)) return false; - if(fi1.name != fi2.name) return false; - if(fi1.path != fi2.path) return false; - if(fi1.piecesize != fi2.piecesize) return false; - if(fi1.pop != fi2.pop) return false; - - return true; -} diff --git a/libretroshare/src/tests/serialiser/support.h b/libretroshare/src/tests/serialiser/support.h deleted file mode 100644 index c9b5eea77..000000000 --- a/libretroshare/src/tests/serialiser/support.h +++ /dev/null @@ -1,234 +0,0 @@ -#ifndef SUPPORT_H_ -#define SUPPORT_H_ - -/* - * libretroshare/src/tests/serialiser: - * - * RetroShare Serialiser tests. - * - * Copyright 2007-2008 by Christopher Evi-Parker, Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include -#include - -#include "util/utest.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvutil.h" -#include "serialiser/rstlvkeys.h" -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvimage.h" - - - -/** - * This contains functions that may be useful for testing throughout the - * retroshare's serialiser - * package, if you find a function you keep using everywhere, might be a good idea to add it here - */ - - -#define SHORT_STR 100 -#define LARGE_STR 1000 - -void randString(const uint32_t, std::string&); -void randString(const uint32_t, std::wstring&); - - -/* for testing compound tlv items */ - -void init_item(RsTlvSecurityKey&); -void init_item(RsTlvKeySignature&); -void init_item(RsTlvKeySignatureSet&); -void init_item(RsTlvBinaryData&); -void init_item(RsTlvFileItem&); -void init_item(RsTlvFileSet&); -void init_item(RsTlvHashSet&); -void init_item(RsTlvPeerIdSet&); -void init_item(RsTlvImage&); -void init_item(RsTlvPeerIdSet&); - -bool operator==(const RsTlvSecurityKey&, const RsTlvSecurityKey& ); -bool operator==(const RsTlvKeySignature&, const RsTlvKeySignature& ); -bool operator==(const RsTlvBinaryData&, const RsTlvBinaryData&); -bool operator==(const RsTlvFileItem&, const RsTlvFileItem&); -bool operator==(const RsTlvFileSet&, const RsTlvFileSet& ); -bool operator==(const RsTlvHashSet&, const RsTlvHashSet&); -bool operator==(const RsTlvImage&, const RsTlvImage& ); -bool operator==(const RsTlvPeerIdSet& , const RsTlvPeerIdSet& ); -bool operator==(const RsTlvKeySignatureSet& , const RsTlvKeySignatureSet& ); - - - -/*! - * This templated test function which allows you to test - * retroshare serialiser items (except compound tlv items) - * you the function must implement a function - * - * 'RsSerialType* init_item(YourRsItem& rs_item)' - * which returns valid serialiser that - * can serialiser rs_item. You also need to implement an operator - * - * Also need to implement a function - * 'bool operator =(YourRsItem& rs_itemL, YourRsItem& rs_temR)' - * which allows this function to test for equality between both parameters. - * rs_temR is the result of deserialising the left operand (1st parameter). - * not YourRsItem in specifier in about functions should be a derived type from RsItem - * - * @param T the item you want to test - */ - -template int test_RsItem() -{ - /* make a serialisable RsTurtleItem */ - - RsSerialiser srl; - - /* initialise */ - T rsfi ; - RsSerialType *rsfis = init_item(rsfi) ; - - /* attempt to serialise it before we add it to the serialiser */ - - CHECK(0 == srl.size(&rsfi)); - - static const uint32_t MAX_BUFSIZE = 22000 ; - - char *buffer = new char[MAX_BUFSIZE]; - uint32_t sersize = MAX_BUFSIZE; - - CHECK(false == srl.serialise(&rsfi, (void *) buffer, &sersize)); - - /* now add to serialiser */ - - srl.addSerialType(rsfis); - - uint32_t size = srl.size(&rsfi); - bool done = srl.serialise(&rsfi, (void *) buffer, &sersize); - - std::cerr << "test_Item() size: " << size << std::endl; - std::cerr << "test_Item() done: " << done << std::endl; - std::cerr << "test_Item() sersize: " << sersize << std::endl; - - std::cerr << "test_Item() serialised:" << std::endl; - //displayRawPacket(std::cerr, (void *) buffer, sersize); - - CHECK(done == true); - - uint32_t sersize2 = sersize; - RsItem *output = srl.deserialise((void *) buffer, &sersize2); - - CHECK(output != NULL); - CHECK(sersize2 == sersize); - - T *outfi = dynamic_cast(output); - - CHECK(outfi != NULL); - - if(!(*outfi == rsfi)) - { - std::cerr << "Items differ: "<< std::endl; - outfi->print(std::cerr,0) ; - rsfi.print(std::cerr,0) ; - } - if (outfi) - CHECK(*outfi == rsfi) ; - - - sersize2 = MAX_BUFSIZE; - bool done2 = srl.serialise(outfi, (void *) &(buffer[16*8]), &sersize2); - - CHECK(done2) ; - CHECK(sersize2 == sersize); - -// displayRawPacket(std::cerr, (void *) buffer, 16 * 8 + sersize2); - - delete[] buffer ; - //delete rsfis; - - return 1; -} - -template int test_RsItem(uint16_t servtype) -{ - /* make a serialisable RsTurtleItem */ - - RsSerialiser srl; - - /* initialise */ - T rsfi(servtype) ; - RsSerialType *rsfis = init_item(rsfi) ; // deleted on destruction of srl - - /* attempt to serialise it before we add it to the serialiser */ - - CHECK(0 == srl.size(&rsfi)); - - static const uint32_t MAX_BUFSIZE = 22000 ; - - char *buffer = new char[MAX_BUFSIZE]; - uint32_t sersize = MAX_BUFSIZE; - - CHECK(false == srl.serialise(&rsfi, (void *) buffer, &sersize)); - - /* now add to serialiser */ - - srl.addSerialType(rsfis); - - uint32_t size = srl.size(&rsfi); - bool done = srl.serialise(&rsfi, (void *) buffer, &sersize); - - std::cerr << "test_Item() size: " << size << std::endl; - std::cerr << "test_Item() done: " << done << std::endl; - std::cerr << "test_Item() sersize: " << sersize << std::endl; - - std::cerr << "test_Item() serialised:" << std::endl; - //displayRawPacket(std::cerr, (void *) buffer, sersize); - - CHECK(done == true); - - uint32_t sersize2 = sersize; - RsItem *output = srl.deserialise((void *) buffer, &sersize2); - - CHECK(output != NULL); - CHECK(sersize2 == sersize); - - T *outfi = dynamic_cast(output); - - CHECK(outfi != NULL); - - if (outfi) - CHECK(*outfi == rsfi) ; - - sersize2 = MAX_BUFSIZE; - bool done2 = srl.serialise(outfi, (void *) &(buffer[16*8]), &sersize2); - - CHECK(done2) ; - CHECK(sersize2 == sersize); - -// displayRawPacket(std::cerr, (void *) buffer, 16 * 8 + sersize2); - - delete[] buffer ; - - return 1; -} -#endif /* SUPPORT_H_ */ diff --git a/libretroshare/src/tests/serialiser/tlvbase_test.cc b/libretroshare/src/tests/serialiser/tlvbase_test.cc deleted file mode 100644 index 1f0e92def..000000000 --- a/libretroshare/src/tests/serialiser/tlvbase_test.cc +++ /dev/null @@ -1,195 +0,0 @@ - -/* - * libretroshare/src/serialiser: tlvbase_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Horatio. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include -#include -#include -#include - -#include "serialiser/rstlvbase.h" -#include "util/utest.h" -#include "util/rsnet.h" - -INITTEST(); - -static int test_RsTlvBase(); -int main() -{ - std::cerr << " RsTlvBase Tests" < -//#include "serialiser/rstlvtypes.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" -#include "util/rsnet.h" - -INITTEST(); - -static int test_RsTlvString(); -static int test_RsTlvUInt32(); -static int test_RsTlvIPAddr(); - -int main() -{ - std::cerr << "RsTlvBase Tests" << std::endl; - - test_RsTlvString(); - test_RsTlvUInt32(); - test_RsTlvIPAddr(); - - FINALREPORT("RsTlvBase Tests"); - - return TESTRESULT(); -} - -int test_RsTlvUInt32() -{ - return 1; -} - -int test_OneString(std::string input, uint16_t type); - -int test_RsTlvString() -{ - std::string nullString; - std::string oneString = "1"; - std::string shortString = "ab cd"; - std::string longString = "abcd efgh ijkl mnop qrst uvw"; - - std::cerr << "test_RsTlvString() Testing" << std::endl; - test_OneString(nullString, 1234); - test_OneString(oneString, 12); - test_OneString(shortString, 79); - test_OneString(longString, 7654); - - REPORT("Serialise RsTlvFileItem"); - - return 1; -} - - -int test_OneString(std::string input, uint16_t type) -{ - /* an array to work from */ - char tlvdata[2048]; - std::string OutString; - - std::cerr << "test_OneString() Testing ... Print/Serialise/Deserialise"; - std::cerr << std::endl; - /* start with SetTlvString() */ - - uint16_t initsize = GetTlvStringSize(input); - uint32_t outOffset = 0; - uint32_t inOffset = 0; - - std::cerr << "Serialising: " << input << std::endl; - CHECK(SetTlvString((void*)tlvdata, 2048, &outOffset, type, input)); - std::cerr << "Init Size: " << initsize << std::endl; - std::cerr << "Serialised Size: " << outOffset << std::endl; - displayRawPacket(std::cerr, tlvdata, outOffset); - - CHECK(outOffset == initsize); /* check that the offset matches the size */ - - std::cerr << "DeSerialising" << std::endl; - - /* fails if type is wrong! */ - CHECK(0 == GetTlvString((void*)tlvdata, outOffset, &inOffset, type-1, OutString)); - CHECK(GetTlvString((void*)tlvdata, outOffset, &inOffset, type, OutString)); - - CHECK(initsize == inOffset); /* check that the offset matches the size */ - CHECK(input == OutString); /* check that strings match */ - std::cerr << "Deserialised: Size: " << inOffset << std::endl; - std::cerr << "Deserialised: String: " << OutString << std::endl; - - REPORT("Serialise OneString"); - - return 1; -} - -int test_IpAddr(struct sockaddr_in *addr, uint16_t type); - -static int test_RsTlvIPAddr() -{ - struct sockaddr_in addr; - - inet_aton("10.0.0.111", &(addr.sin_addr)); - addr.sin_port = htons(1111); - - test_IpAddr(&addr, 1234); - - inet_aton("255.255.255.1", &(addr.sin_addr)); - addr.sin_port = htons(9999); - - test_IpAddr(&addr, 1234); - - inet_aton("128.255.255.1", &(addr.sin_addr)); - addr.sin_port = htons(1); - - test_IpAddr(&addr, 1234); - - return 1; -} - -int test_IpAddr(struct sockaddr_in *addr, uint16_t type) -{ - /* an array to work from */ - char tlvdata[2048]; - struct sockaddr_in outaddr; - - std::cerr << "test_IpAddr() Testing ... Print/Serialise/Deserialise"; - std::cerr << std::endl; - /* start with SetTlvString() */ - - uint16_t initsize = GetTlvIpAddrPortV4Size(); - uint32_t outOffset = 0; - uint32_t inOffset = 0; - - std::cerr << "Serialising IPAddr: " << inet_ntoa(addr->sin_addr) << std::endl; - std::cerr << " Port : " << ntohs(addr->sin_port) << std::endl; - - CHECK(SetTlvIpAddrPortV4((void*)tlvdata, 2048, &outOffset, type, addr)); - std::cerr << "Init Size: " << initsize << std::endl; - std::cerr << "Serialised Size: " << outOffset << std::endl; - displayRawPacket(std::cerr, tlvdata, outOffset); - - CHECK(outOffset == initsize); /* check that the offset matches the size */ - - std::cerr << "DeSerialising" << std::endl; - - /* fails if type is wrong! */ - CHECK(0 == GetTlvIpAddrPortV4((void*)tlvdata, outOffset, &inOffset, type-1, &outaddr)); - CHECK(GetTlvIpAddrPortV4((void*)tlvdata, outOffset, &inOffset, type, &outaddr)); - - CHECK(initsize == inOffset); /* check that the offset matches the size */ - CHECK(addr->sin_addr.s_addr == outaddr.sin_addr.s_addr); /* check that IP match */ - CHECK(addr->sin_port == outaddr.sin_port); /* check that Port match */ - std::cerr << "Deserialised: Size: " << inOffset << std::endl; - std::cerr << "Deserialised IPAddr: " << inet_ntoa(outaddr.sin_addr) << std::endl; - std::cerr << " Port : " << ntohs(outaddr.sin_port) << std::endl; - - REPORT("Serialise OneIP/Port"); - - return 1; -} - - - diff --git a/libretroshare/src/tests/serialiser/tlvitems_test.cc b/libretroshare/src/tests/serialiser/tlvitems_test.cc deleted file mode 100644 index 5d88338bb..000000000 --- a/libretroshare/src/tests/serialiser/tlvitems_test.cc +++ /dev/null @@ -1,89 +0,0 @@ - -/* - * libretroshare/src/serialiser: tlvitems_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - * tlvfileitem test. - * - * - */ - -#include -#include -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" - -INITTEST(); - -static int test_RsTlvBinData(); -static int test_RsTlvStepping(); - -int main() -{ - std::cerr << "RsTlvItems Tests" << std::endl; - - test_RsTlvBinData(); - - FINALREPORT("RsTlvItems Tests"); - - return TESTRESULT(); -} - -#define BIN_LEN 65536 /* bigger than 64k */ - -int test_RsTlvBinData() -{ - RsTlvBinaryData d1(1023); - RsTlvBinaryData d2(1023); - - char data[BIN_LEN] = {0}; - int i, j; - for(i = 0; i < BIN_LEN; i++) - { - data[i] = i%13; - } - - for(j = 1; j < BIN_LEN; j *= 2) - { - d1.setBinData(data, j); - CHECK(test_SerialiseTlvItem(std::cerr, &d1, &d2)); - - CHECK(d1.bin_len == d2.bin_len); - CHECK(0 == memcmp(d1.bin_data, d2.bin_data, d1.bin_len)); - } - - REPORT("Serialise/Deserialise RsTlvBinData"); - - return 1; -} - -int test_RsTlvStepping() -{ - - - return 1; -} - diff --git a/libretroshare/src/tests/serialiser/tlvkey_test.cc b/libretroshare/src/tests/serialiser/tlvkey_test.cc deleted file mode 100644 index 23c87a715..000000000 --- a/libretroshare/src/tests/serialiser/tlvkey_test.cc +++ /dev/null @@ -1,36 +0,0 @@ - - -#include "support.h" -#include "serialiser/rstlvkeys.h" - -INITTEST(); - -bool test_RsTlvKeySignatureSet(); - -int main() -{ - test_RsTlvKeySignatureSet(); REPORT("test_RsTlvKeySignatureSet()"); - - FINALREPORT("RsTlvKey Test"); -} - - - -bool test_RsTlvKeySignatureSet() -{ - RsTlvKeySignatureSet set; - - init_item(set); - - char data[set.TlvSize()]; - uint32_t offset = 0; - set.SetTlv(data, set.TlvSize(), &offset); - - RsTlvKeySignatureSet setConfirm; - - offset = 0; - setConfirm.GetTlv(data, set.TlvSize(), &offset); - - CHECK(setConfirm == set); - -} diff --git a/libretroshare/src/tests/serialiser/tlvrandom_test.cc b/libretroshare/src/tests/serialiser/tlvrandom_test.cc deleted file mode 100644 index bed1525f7..000000000 --- a/libretroshare/src/tests/serialiser/tlvrandom_test.cc +++ /dev/null @@ -1,194 +0,0 @@ - -/* - * libretroshare/src/serialiser: tlvrandom_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2009 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - * tlvrandom_test. - * - * This test is designed to attempt to break the TLV serialiser. - * - * To do this we throw random data at the serialisers and try to decode it. - * As the serialiser will only attempt to deserialise if the tlvtype matches - * we cheat a little, and make this match - to increase to actual deserialise - * attempts. - * - * This test runs for 30 seconds and attempts to do as - * many deserialisation as possible. - */ - -#include "util/rstime.h" -#include -#include -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvkeys.h" -#include "serialiser/rstlvutil.h" -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rstlvkeyvalue.h" -#include "serialiser/rstlvimage.h" - -#include "util/utest.h" - -INITTEST(); - -#define TEST_LENGTH 10 - -static int test_TlvRandom(void *data, uint32_t len, uint32_t offset); - -int main() -{ - std::cerr << "TlvRandom Tests" << std::endl; - - /* random data array to work through */ - uint32_t dsize = 10000000; - uint32_t i; - uint8_t *data = (uint8_t *) malloc(dsize); - - if (!data) - { - std::cerr << "Failed to allocate array"; - std::cerr << std::endl; - exit(1); - } - - rstime_t startTs = time(NULL); - rstime_t endTs = startTs + TEST_LENGTH; - - srand(startTs); - for(i = 0; i < dsize; i++) - { - data[i] = rand() % 256; - } - - std::cerr << "TlvRandom Tests: setup data." << std::endl; - - int count = 0; - for(i = 0; endTs > time(NULL); i += 2) - { - uint32_t len = dsize - i; - count += test_TlvRandom(&(data[i]), len, i); - - std::cerr << "Run: " << count << " tests"; - std::cerr << std::endl; - } - - FINALREPORT("RsTlvItems Tests"); - - return TESTRESULT(); -} - -#define BIN_LEN 523456 /* bigger than 64k */ - -bool test_TlvItem(RsTlvItem *item, void *data, uint32_t size, uint32_t offset); -bool test_SetTlvItem(RsTlvItem *item, uint16_t type, void *data, uint32_t size, uint32_t offset); - - -int test_TlvRandom(void *data, uint32_t len, uint32_t offset) -{ - uint32_t tmpoffset = 0; - - /* List of all the TLV types it could be! */ - RsTlvSecurityKey skey; - RsTlvSecurityKeySet skeyset; - RsTlvKeySignature keysign; - - RsTlvBinaryData bindata(TLV_TYPE_IMAGE); - - RsTlvFileItem fileitem; - RsTlvFileSet fileset; - RsTlvFileData filedata; - - RsTlvPeerIdSet peerset; - RsTlvServiceIdSet servset; - - RsTlvKeyValue kv; - RsTlvKeyValueSet kvset; - - RsTlvImage image; - - /* try to decode - with all types first */ - std::cerr << "test_TlvRandom:: Testing Files " << std::endl; - CHECK(test_TlvItem(&bindata, data, len, offset)); - CHECK(test_TlvItem(&fileitem, data, len, offset)); - CHECK(test_TlvItem(&fileset, data, len, offset)); - CHECK(test_TlvItem(&filedata, data, len, offset)); - std::cerr << "test_TlvRandom:: Testing Sets " << std::endl; - CHECK(test_TlvItem(&peerset, data, len, offset)); - CHECK(test_TlvItem(&servset, data, len, offset)); - CHECK(test_TlvItem(&kv, data, len, offset)); - CHECK(test_TlvItem(&kvset, data, len, offset)); - std::cerr << "test_TlvRandom:: Testing Keys " << std::endl; - CHECK(test_TlvItem(&skey, data, len, offset)); - CHECK(test_TlvItem(&skeyset, data, len, offset)); - CHECK(test_TlvItem(&keysign, data, len, offset)); - - /* now set the type correctly before decoding */ - std::cerr << "test_TlvRandom:: Testing Files (TYPESET)" << std::endl; - CHECK(test_SetTlvItem(&bindata, TLV_TYPE_IMAGE, data, len, offset)); - CHECK(test_SetTlvItem(&fileitem,TLV_TYPE_FILEITEM, data, len, offset)); - CHECK(test_SetTlvItem(&fileset, TLV_TYPE_FILESET, data, len, offset)); - CHECK(test_SetTlvItem(&filedata, TLV_TYPE_FILEDATA, data, len, offset)); - std::cerr << "test_TlvRandom:: Testing Sets (TYPESET)" << std::endl; - CHECK(test_SetTlvItem(&peerset, TLV_TYPE_PEERSET, data, len, offset)); - CHECK(test_SetTlvItem(&servset, TLV_TYPE_SERVICESET, data, len, offset)); - CHECK(test_SetTlvItem(&kv, TLV_TYPE_KEYVALUE, data, len, offset)); - CHECK(test_SetTlvItem(&kvset, TLV_TYPE_KEYVALUESET, data, len, offset)); - std::cerr << "test_TlvRandom:: Testing Keys (TYPESET)" << std::endl; - CHECK(test_SetTlvItem(&skey, TLV_TYPE_SECURITYKEY, data, len, offset)); - CHECK(test_SetTlvItem(&skeyset, TLV_TYPE_SECURITYKEYSET, data, len, offset)); - CHECK(test_SetTlvItem(&keysign, TLV_TYPE_KEYSIGNATURE, data, len, offset)); - - return 26; /* number of tests */ -} - -bool test_TlvItem(RsTlvItem *item, void *data, uint32_t size, uint32_t offset) -{ - uint32_t tmp_offset = offset; - if (item->GetTlv(data, size, &tmp_offset)) - { - std::cerr << "TLV decoded Random!"; - std::cerr << std::endl; - item->print(std::cerr, 20); - return false; - } - else - { - std::cerr << "TLV failed to decode"; - std::cerr << std::endl; - return true; - } -} - -bool test_SetTlvItem(RsTlvItem *item, uint16_t type, void *data, uint32_t size, uint32_t offset) -{ - /* set TLV type first! */ - void *typedata = (((uint8_t *) data) + offset); - SetTlvType(typedata, size - offset, type); - - return test_TlvItem(item, data, size, offset); -} - - diff --git a/libretroshare/src/tests/serialiser/tlvstack_test.cc b/libretroshare/src/tests/serialiser/tlvstack_test.cc deleted file mode 100644 index 36527ef8a..000000000 --- a/libretroshare/src/tests/serialiser/tlvstack_test.cc +++ /dev/null @@ -1,105 +0,0 @@ - -/* - * libretroshare/src/serialiser: tlvstack_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - * tlvfileitem test. - * - * - */ - -#include -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" - -INITTEST(); - -static int test_RsTlvStack(); - -int main() -{ - std::cerr << "RsTlvItem Stack Tests" << std::endl; - - test_RsTlvStack(); - - FINALREPORT("RsTlvItem Stack Tests"); - - return TESTRESULT(); -} - - -#define BIN_LEN 53 - -int test_RsTlvStack() -{ - - /* now create a set of TLV items for the random generator */ - - RsTlvBinaryData *bd1 = new RsTlvBinaryData(123); - RsTlvBinaryData *bd2 = new RsTlvBinaryData(125); - - char data[BIN_LEN] = {0}; - int i; - for(i = 0; i < BIN_LEN; i++) - { - data[i] = i%13; - } - - bd1->setBinData(data, 5); - bd2->setBinData(data, 21); - - RsTlvFileItem *fi1 = new RsTlvFileItem(); - RsTlvFileItem *fi2 = new RsTlvFileItem(); - - /* initialise */ - fi1->filesize = 101010; - fi1->hash = "ABCDEFEGHE"; - fi1->name = "TestFile.txt"; - fi1->pop = 12; - fi1->age = 456; - - fi2->filesize = 101010; - fi2->hash = "ABCDEFEGHE"; - fi2->name = "TestFile.txt"; - fi2->pop = 0; - fi2->age = 0;; - - std::vector items; - items.resize(4); - items[0] = bd1; - items[1] = bd2; - items[2] = fi1; - items[3] = fi2; - - test_TlvSet(items, 1024); - - REPORT("Serialise/Deserialise RsTlvBinData"); - - return 1; -} - - diff --git a/libretroshare/src/tests/serialiser/tlvtypes_test.cc b/libretroshare/src/tests/serialiser/tlvtypes_test.cc deleted file mode 100644 index e32dfe0fc..000000000 --- a/libretroshare/src/tests/serialiser/tlvtypes_test.cc +++ /dev/null @@ -1,386 +0,0 @@ -/* - * libretroshare/src/serialiser: tlvfileitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie, Chris Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include -#include -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rstlvstring.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvkeyvalue.h" -#include "serialiser/rstlvimage.h" -#include "serialiser/rstlvutil.h" -#include "serialiser/rstlvbase.h" -#include "util/utest.h" - -INITTEST(); - -#define RAND_SEED 1352534 - -static int test_RsTlvBinData(); -static int test_RsTlvFileItem(); -static int test_RsTlvFileSet(); -static int test_RsTlvFileData(); -static int test_RsTlvStringSet(); -static int test_RsTlvPeerIdSet(); -static int test_RsTlvServiceIdSet(); -static int test_RsTlvKeyValue(); -static int test_RsTlvKeyValueSet(); -static int test_RsTlvHashSet(); -static int test_RsTlvImage(); - - - -int main() -{ - std::cerr << "RsTlvTypes[Item/Data/...] Tests" << std::endl; - - srand(RAND_SEED); - - test_RsTlvFileItem(); - test_RsTlvFileData(); - test_RsTlvFileSet(); - test_RsTlvPeerIdSet(); - test_RsTlvServiceIdSet(); - test_RsTlvKeyValue(); - test_RsTlvKeyValueSet(); - test_RsTlvBinData(); - test_RsTlvImage(); - test_RsTlvHashSet(); - - FINALREPORT("RsTlvTypes[Item/Data/...] Tests"); - - return TESTRESULT(); -} - -int test_RsTlvFileItem() -{ - RsTlvFileItem i1; - RsTlvFileItem i2; - - /* initialise */ - i1.filesize = 101010; - i1.hash = "ABCDEFEGHE"; - i1.name = "TestFile.txt"; - i1.pop = 12; - i1.age = 456; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /* check the data is the same */ - CHECK(i1.filesize == i2.filesize); - CHECK(i1.hash == i2.hash); - CHECK(i1.name == i2.name); - CHECK(i1.path == i2.path); - CHECK(i1.pop == i2.pop); - CHECK(i1.age == i2.age); - - /* do it again without optional data */ - i1.filesize = 123; - i1.name = ""; - i1.pop = 0; - i1.age = 0; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /* check the data is the same */ - CHECK(i1.filesize == i2.filesize); - CHECK(i1.hash == i2.hash); - CHECK(i1.name == i2.name); - CHECK(i1.path == i2.path); - CHECK(i1.pop == i2.pop); - CHECK(i1.age == i2.age); - - /* one more time - long file name, some optional data */ - i1.filesize = 123; - i1.name = "A Very Long File name that should fit in easily ??? with som $&%&^%* strange char (**$^%#&^$#*^%(&^ in there too!!!! ~~~!!$#(^$)$)(&%^)&\" oiyu thend"; - i1.pop = 666; - i1.age = 0; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /* check the data is the same */ - CHECK(i1.filesize == i2.filesize); - CHECK(i1.hash == i2.hash); - CHECK(i1.name == i2.name); - CHECK(i1.path == i2.path); - CHECK(i1.pop == i2.pop); - CHECK(i1.age == i2.age); - - REPORT("Serialise/Deserialise RsTlvFileItem"); - - return 1; -} - -int test_RsTlvFileSet() -{ - RsTlvFileSet s1; - RsTlvFileSet s2; - - int i = 0; - for(i = 0; i < 15; i++) - { - RsTlvFileItem fi; - fi.filesize = 16 + i * i; - fi.hash = "ABCDEF"; - std::ostringstream out; - out << "File" << i << "_inSet.txt"; - fi.name = out.str(); - if (i % 2 == 0) - { - fi.age = 10 * i; - } - else - { - fi.age = 0; - } - fi.pop = 0; - - s1.items.push_back(fi); - } - - CHECK(test_SerialiseTlvItem(std::cerr, &s1, &s2)); - - /* check the data is the same - TODO */ - - REPORT("Serialise/Deserialise RsTlvFileSet"); - - return 1; -} - - -int test_RsTlvFileData() -{ - RsTlvFileData d1; - RsTlvFileData d2; - - /* initialise */ - d1.file.filesize = 101010; - d1.file.hash = "ABCDEFEGHE"; - d1.file.name = ""; - d1.file.age = 0; - d1.file.pop = 0; - - char data[15]; - d1.binData.setBinData(data, 15); - - d1.file_offset = 222; - - CHECK(test_SerialiseTlvItem(std::cerr, &d1, &d2)); - - /* check the data is the same */ - CHECK(d1.file.filesize == d2.file.filesize); - CHECK(d1.file.hash == d2.file.hash); - CHECK(d1.file.name == d2.file.name); - CHECK(d1.file.path == d2.file.path); - CHECK(d1.file.pop == d2.file.pop); - CHECK(d1.file.age == d2.file.age); - - CHECK(d1.file_offset == d2.file_offset); - CHECK(d1.binData.bin_len == d2.binData.bin_len); - - REPORT("Serialise/Deserialise RsTlvFileData"); - - return 1; -} - - -int test_RsTlvPeerIdSet() -{ - - RsTlvPeerIdSet i1, i2; // one to set and other to get - - RsPeerId testId; - - std::string randString[5]; - randString[0] = "e$424!�!�"; - randString[1] = "e~:@L{L{KHKG"; - randString[2] = "e{@O**/*/*"; - randString[3] = "e?<HG�!�%$"; - randString[4] = "e>HG�!�%$"; - randString[4] = "e>addFriend(fakePeer); -} - -ServiceTest::~ServiceTest() -{ - // release resources - delete mConnMgr; - delete mPersonGrp; - delete mPeers; -} - - - - - - diff --git a/libretroshare/src/tests/services/servicetest.h b/libretroshare/src/tests/services/servicetest.h deleted file mode 100644 index ca24e9f0e..000000000 --- a/libretroshare/src/tests/services/servicetest.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * libretroshare/src/tests/services Service_Test.h - * - * RetroShare Service Testing - * - * Copyright 2010 by Chris Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#ifndef SERVICE_TEST_H_ -#define SERVICE_TEST_H_ - -#include "pqi/p3connmgr.h" -#include "rsserver/p3peers.h" -#include "dbase/cachestrapper.h" -#include "pqi/pqipersongrp.h" - - - - -/*! - * A convenience class from which tests derive from - * This enables user to test in shallow manner the public methods - * of a service - */ -class ServiceTest { - -public: - ServiceTest(); - virtual ~ServiceTest(); - - /*! - * all tests of service should be implemented here - */ - virtual void runTests() = 0; - - /*! - * use this to populate the service with messages - */ - void sendItem(RsItem* item); - -protected: - - - p3ConnectMgr* mConnMgr; - CacheStrapper *mCs; - CacheTransfer *mCt; - p3Peers* mPeers; - pqipersongrp* mPersonGrp; - - std::string fakePeer; // ssl id of fake receiving peer - -}; - - - -#endif /* SERVICE_TEST_H_ */ diff --git a/libretroshare/src/tests/tcponudp/bidir_tou.cc b/libretroshare/src/tests/tcponudp/bidir_tou.cc deleted file mode 100644 index 5075130d9..000000000 --- a/libretroshare/src/tests/tcponudp/bidir_tou.cc +++ /dev/null @@ -1,402 +0,0 @@ -/* - * "$Id: pair_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include -#include - -// for printing sockaddr -#include "udp/udpstack.h" - -#include "tcponudp/tou.h" -#include "tcponudp/udppeer.h" -#include "tcponudp/udprelay.h" - -#include "util/bdnet.h" - -#include "util/rsrandom.h" - -#include -#include -#include - - -/* - * This test creates the same stacks as are used in RS. - * This additionally tests the "checkFns" for the other UdpReceivers, which could potentially be modifying the data. - * obviously they shouldn't! - * - */ - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - - int totalwbytes = 0; - int totalmbytes = 0; - int totalrbytes = 0; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - laddr.sin_port = htons(atoi(argv[optind+1])); - raddr.sin_port = htons(atoi(argv[optind+3])); - - std::cerr << "Local Address: " << laddr << std::endl; - std::cerr << "Remote Address: " << raddr << std::endl; - - std::cerr << "Creating with Lossy Udp Layers for further testing"; - std::cerr << std::endl; - - UdpStack *udpStack1 = new UdpStack(UDP_TEST_LOSSY_LAYER,laddr); - UdpStack *udpStack2 = new UdpStack(UDP_TEST_LOSSY_LAYER,raddr); - - UdpSubReceiver *udpReceivers[4]; - int udpTypes[4]; - - // NOTE DHT is too hard to add at the moment. - - UdpRelayReceiver *mRelay1 = new UdpRelayReceiver(udpStack1); - udpReceivers[1] = mRelay1; - udpTypes[1] = TOU_RECEIVER_TYPE_UDPRELAY; - udpStack1->addReceiver(udpReceivers[1]); - - udpReceivers[0] = new UdpPeerReceiver(udpStack1); - udpTypes[0] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack1->addReceiver(udpReceivers[0]); - - // STACK 2. - UdpRelayReceiver *mRelay2 = new UdpRelayReceiver(udpStack2); - udpReceivers[3] = mRelay2; - udpTypes[3] = TOU_RECEIVER_TYPE_UDPRELAY; - udpStack2->addReceiver(udpReceivers[3]); - - udpReceivers[2] = new UdpPeerReceiver(udpStack2); - udpTypes[2] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack2->addReceiver(udpReceivers[2]); - - tou_init((void **) udpReceivers, udpTypes, 4); - - - int sockfd = tou_socket(0, TOU_RECEIVER_TYPE_UDPPEER, 0); - int sockfd2 = tou_socket(2, TOU_RECEIVER_TYPE_UDPPEER, 0); - if ((sockfd <= 0) || (sockfd2 <= 0)) - { - std::cerr << "Failed to open socket!: "; - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - std::cerr << "Socket Error:" << tou_errno(sockfd2) << std::endl; - return -1; - } - std::cerr << "Sockets Created: " << sockfd << " & " << sockfd2 << std::endl; - - std::cerr << "Socket Non-Blocking" << std::endl; - - std::cerr << "Socket1 Bound to: " << laddr << std::endl; - std::cerr << "Socket2 Bound to: " << raddr << std::endl; - - int err = 0; - - // listening. - if (1) // socket2. - { - std::cerr << "Socket2 Listening " << std::endl; - /* listen */ - err = tou_listenfor(sockfd2, - (struct sockaddr *) &laddr, sizeof(laddr)); - } - - - if (1) // only one program. - { - std::cerr << "Socket1 Connecting to: " << raddr << std::endl; - err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30); - if (err < 0) - { - errno = tou_errno(sockfd); - if (errno != EINPROGRESS) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - } - } - - bool sock1Connected = false; - bool sock2Connected = false; - - while((!sock1Connected) || (!sock2Connected)) - { - usleep(1000); - - - /* sock1 */ - if((!sock1Connected) && (0 == (err = tou_connected(sockfd)))) - { - std::cerr << "Waiting for Connect (Sock1)!" << std::endl; - } - if ((!sock1Connected) && (err < 0)) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - else if (!sock1Connected) - { - // else connected! - sock1Connected = true; - } - - /* accept - sock2 */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock = -1; - - if ((!sock2Connected) && (0 > (nsock = tou_accept(sockfd2, - (struct sockaddr *) &inaddr, &addrlen)))) - { - errno = tou_errno(sockfd2); - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - else - { - std::cerr << "Waiting for Connect (Sock2)!" << std::endl; - } - } - else if (nsock > 0) - { - /* connected */ - sock2Connected = true; - sockfd2 = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - } - - std::cerr << "Socket Connected" << std::endl; - -#define MAX_READ 20000 - - /* send data */ - int bufsize = MAX_READ; - char buffer[MAX_READ]; - char middata[MAX_READ]; - char data[MAX_READ]; - int readsize = 0; - int midsize = 0; - - bdnet_fcntl(0, F_SETFL, O_NONBLOCK); - bdnet_fcntl(1,F_SETFL,O_NONBLOCK); - - rstime_t lastRead = time(NULL); - bool doneWrite = false; - bool doneRead = false; - bool blockread = false; - bool blockmid = false; - - while((!doneWrite) || (!doneRead)) - { - /* read -> write_socket... */ - usleep(10); - - if (blockread != true) - { - int readbuf = 1 + RSRandom::random_u32() % (MAX_READ - 1); - readsize = read(0, buffer, readbuf); - if (readsize) - { - //std::cerr << "read " << readsize << " / " << readbuf; - //std::cerr << std::endl; - } - } - if ((readsize == 0) && (!doneWrite)) - { - /* eof */ - doneWrite = true; - std::cerr << "Write Done Total: " << totalwbytes; - std::cerr << std::endl; - } - /* now we write */ - if ((readsize > 0) && (-1 == tou_write(sockfd, buffer, readsize))) - { - //std::cerr << "Blocked Write "; - //std::cerr << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; - blockread = true; - } - else - { - blockread = false; - totalwbytes += readsize; - - if (readsize) - { - std::cerr << "Written: " << readsize << ", Total: " << totalwbytes; - std::cerr << " Total In Transit: " << totalwbytes - totalrbytes; - std::cerr << std::endl; - } - } - - /*************** Here we read it in, and send it back out... - * so the data is flowing both ways through the UDP connection - * - *****/ - - - if (!blockmid) - { - /* read from socket 2, and write back to socket 2 */ - - int readmidbuf = 1 + RSRandom::random_u32() % (MAX_READ - 1); - if (0 < (midsize = tou_read(sockfd2, middata, readmidbuf))) - { - //std::cerr << "MidRead: " << mid << " Total: " << totalrbytes; - //std::cerr << " In Transit: " << totalwbytes - totalrbytes; - //std::cerr << std::endl; - } - } - - /* now we write */ - if ((midsize > 0) && (-1 == tou_write(sockfd2, middata, midsize))) - { - //std::cerr << "Blocked Write "; - //std::cerr << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; - blockmid = true; - } - else - { - blockmid = false; - - if (midsize > 0) - { - totalmbytes += midsize; - - std::cerr << "MidRead: " << midsize << ", Total: " << totalmbytes; - std::cerr << " => Transit => : " << totalwbytes - totalmbytes; - std::cerr << " <= Transit <= : " << totalmbytes - totalrbytes; - std::cerr << std::endl; - } - } - - /***** READ FROM FIRST SOCKET *****/ - - int ret = 0; - int readbuf2 = 1 + RSRandom::random_u32() % (MAX_READ - 1); - if (0 < (ret = tou_read(sockfd, data, readbuf2))) - { - //std::cerr << "TF(" << ret << ")" << std::endl; - write(1, data, ret); - totalrbytes += ret; - - std::cerr << "Read: " << ret << " Total: " << totalrbytes; - std::cerr << " Total In Transit: " << totalwbytes - totalrbytes; - std::cerr << std::endl; - - lastRead = time(NULL); - } - else if ((ret == 0) && (!doneRead)) - { - doneRead = true; - std::cerr << "Read Done Total: " << totalrbytes; - std::cerr << std::endl; - } - else - { - //std::cerr << "Blocked Read: " << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; -#define TIMEOUT 15 - if ((!doneRead) && (time(NULL) - lastRead > TIMEOUT)) - { - doneRead = true; - std::cerr << "TIMEOUT: Read Done Total: " << totalrbytes; - std::cerr << std::endl; - } - } - - - } - - /* this is blocking??? */ - tou_close(sockfd); - tou_close(sockfd2); - - std::cerr << "Transfer Complete: " << totalwbytes << " bytes"; - std::cerr << std::endl; - return 1; -} - diff --git a/libretroshare/src/tests/tcponudp/bidir_tou.sh b/libretroshare/src/tests/tcponudp/bidir_tou.sh deleted file mode 100755 index 048dd67b4..000000000 --- a/libretroshare/src/tests/tcponudp/bidir_tou.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -# Script to Test the udp_server code. - -EXEC=./bidir_tou -DATAFILE=../../lib/libretroshare.a - -TMPOUTPUT=tmpoutput$$ -EXPECTEDPERIOD=10 - -$EXEC 127.0.0.1 4401 127.0.0.1 4032 < $DATAFILE > $TMPOUTPUT - -if diff -s $DATAFILE $TMPOUTPUT -then - echo "SUCCESS" -else - echo "FAILURE to accurately transfer DATA" -fi - -rm $TMPOUTPUT - diff --git a/libretroshare/src/tests/tcponudp/internal_tou.cc b/libretroshare/src/tests/tcponudp/internal_tou.cc deleted file mode 100644 index 353fecedc..000000000 --- a/libretroshare/src/tests/tcponudp/internal_tou.cc +++ /dev/null @@ -1,632 +0,0 @@ -/* - * "$Id: internal_tou.cc,v 1.2 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -/********************************************************** - * There appears (was) to be an elusive bug in the tou internals. - * most likely to be in the packing and unpacking of the - * data queues. - * - * This test is designed to load the queues up and then - * transfer the data, repeatly with different size packets. - * - * to do this effectively we need to access the TcpStream - * objects, instead of the tou.h interface. - * - */ - -#include - -// for printing sockaddr -#include "udplayer.h" -#include "tcpstream.h" - -#include "tou.h" -#include "tou_net.h" - -#include -#include -#include - - -/* This is a simple test to ensure that the tou behaviour - * is almost identical to a standard tcp socket. - * - * In this version we open 2 sockets, and attempt to - * communicate with ourselves.... - * - */ - -int setup_socket(struct sockaddr_in addr); -int connect_socket_pair(int fd1, int fd2, - struct sockaddr_in addr1, struct sockaddr_in addr2); -int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size); - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - int i,j; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - // tounet_init(); - - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - unsigned short laddr_port = atoi(argv[optind+1]); - unsigned short raddr_port = atoi(argv[optind+3]); - - laddr.sin_port = htons(laddr_port); - raddr.sin_port = htons(raddr_port); - - /* so create the Udp/Tcp components */ - //UdpLayer udp1(laddr); - //UdpLayer udp2(raddr); - LossyUdpLayer udp1(laddr, 0.10); - LossyUdpLayer udp2(raddr, 0.10); - - /* check that they are okay */ - if ((!udp1.okay()) || (!udp2.okay())) - { - std::cerr << "Trouble opening udp ports!"; - std::cerr << std::endl; - return 1; - } - - TcpStream tcp1(&udp1); - TcpStream tcp2(&udp2); - - udp1.setRemoteAddr(raddr); - udp2.setRemoteAddr(laddr); - tcp1.connect(); // start the connection. - - /* now connect them */ - while ((!tcp1.isConnected()) || (!tcp2.isConnected())) - { - usleep(10000); /* 10 ms */ - tcp1.tick(); - tcp2.tick(); - } - - std::cerr << "Connection Established!" << std::endl; - - for(i = 0; i < 10; i++) - { - - int size = 1024000; - char rnddata1[size]; - char rnddata2[size]; - - for(j = 0; j < size; j++) - { - rnddata1[j] = (unsigned char) (255.0 * - rand() / (RAND_MAX + 1.0)); - - rnddata2[j] = (unsigned char) (255.0 * - rand() / (RAND_MAX + 1.0)); - } - - /* for each iteration, we want to - * (1) fill up the outgoing buffers with stuff - */ - - int sent1 = 0; - int sent2 = 0; - int fill1, fill2; - int MaxSend = 1000000; - - while((fill1 = tcp1.write_allowed()) && (sent1 < MaxSend)) - { - /* fill with a random little bit more */ - int psize = (int) ((i + 1.0) * 255.0 * - rand() / (RAND_MAX + 1.0)); - - /* don't overload */ - if (psize > fill1) - { - std::cerr << "LAST FILL1" << std::endl; - psize = fill1; - } - - int ret = tcp1.write(&(rnddata1[sent1]), psize); - - if (ret) - { - sent1 += ret; - std::cerr << "Filled tcp1 with " << ret << " more bytes, total:"; - std::cerr << sent1 << " was allowed: " << fill1; - std::cerr << std::endl; - } - - //tcp1.status(std::cerr); - - } - std::cerr << "Tcp1 full with " << sent1 << " bytes "; - std::cerr << std::endl; - - while((fill2 = tcp2.write_allowed()) && (sent2 < MaxSend)) - { - /* fill with a random little bit more */ - /* slightly larger sizes */ - int psize = (int) ((i + 1.0) * 1255.0 * - rand() / (RAND_MAX + 1.0)); - - /* don't overload */ - if (psize > fill2) - { - std::cerr << "LAST FILL2" << std::endl; - psize = fill2; - } - - int ret = tcp2.write(&(rnddata2[sent2]), psize); - - if (ret) - { - sent2 += ret; - std::cerr << "Filled tcp2 with " << ret << " more bytes, total:"; - std::cerr << sent2 << " was allowed: " << fill2; - std::cerr << std::endl; - } - - //tcp2.status(std::cerr); - - } - std::cerr << "Tcp2 full with " << sent2 << " bytes "; - std::cerr << std::endl; - - /* for every second iteration, fill up the read buffer before starting */ - if (i % 2 == 0) - { - for(j = 0; j < 100; j++) - { - tcp1.tick(); - tcp2.tick(); - } - } - - /* now we read/tick and empty */ - int read1 = 0; - int read2 = 0; - - while(read1 < sent2) - { - tcp1.tick(); - tcp2.tick(); - - /* fill with a random little bit more */ - /* This one has a small read, while tcp2 has a large read */ - int psize = (int) ((i + 1.0) * 100.0 * - rand() / (RAND_MAX + 1.0)); - - /* limit to what we have! */ - if (psize > sent2 - read1) - { - std::cerr << "LAST READ1" << std::endl; - psize = sent2 - read1; - } - - char rbuf[psize]; - int rsize = psize; - - int ret = tcp1.read(rbuf, rsize); - if (0 < ret) - { - /* check the data */ - for(j = 0; j < ret; j++) - { - if (rnddata2[read1 + j] != rbuf[j]) - { - std::cerr << "Error Data Mismatch @ read1:" << read1; - std::cerr << " + j:" << j << " rsize: " << rsize; - std::cerr << " Index: " << read1 + j; - std::cerr << std::endl; - - int badoffset = read1 + j; - for(int k = -10; k < 10; k++) - { - printf("Orig: %02x, Trans: %02x\n", - (unsigned char) rnddata2[badoffset+k], - (unsigned char) rbuf[j + k]); - } - - - exit(1); - } - } - read1 += ret; - } - else - { - std::cerr << "Read Error: " << ret << std::endl; - } - std::cerr << "Requested " << psize << ", got " << ret << " bytes" << std::endl; - std::cerr << "Read " << read1 << " of " << sent2 << " bytes" << std::endl; - } - - sleep(2); - - - while(read2 < sent1) - { - tcp1.tick(); - tcp2.tick(); - - /* fill with a random little bit more */ - int psize = (int) ((i + 1.0) * 10000.0 * - rand() / (RAND_MAX + 1.0)); - - /* limit to what we have! */ - if (psize > sent1 - read2) - { - std::cerr << "LAST READ2" << std::endl; - psize = sent1 - read2; - } - - char rbuf[psize]; - int rsize = psize; - - int ret = tcp2.read(rbuf, rsize); - if (0 < ret) - { - /* check the data */ - for(j = 0; j < ret; j++) - { - if (rnddata1[read2 + j] != rbuf[j]) - { - std::cerr << "Error Data Mismatch @ read2:" << read2; - std::cerr << " + j:" << j << " rsize: " << rsize; - std::cerr << " Index: " << read2 + j; - std::cerr << std::endl; - exit(1); - } - } - read2 += ret; - } - else - { - std::cerr << "Read Error: " << ret << std::endl; - } - std::cerr << "Requested " << psize << ", got " << ret << " bytes" << std::endl; - std::cerr << "Read " << read2 << " of " << sent1 << " bytes" << std::endl; - } - - std::cerr << "Iteration " << i + 1 << " finished correctly!" << std::endl; - sleep(5); - - } - return 1; -} - -int setup_socket(struct sockaddr_in addr) -{ - int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0); - - if (sockfd <= 0) - { - std::cerr << "Failed to open socket!: "; - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - return -1; - } - - std::cerr << "Socket Created: " << sockfd << std::endl; - - int err = tou_bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)); - - if (err < 0) - { - std::cerr << "Error: Cannot bind socket: "; - std::cerr << err << std::endl; - return -1; - } - - std::cerr << "Socket1 Bound to: " << addr << std::endl; - return sockfd; -} - -int connect_socket_pair(int fd1, int fd2, - struct sockaddr_in addr1, struct sockaddr_in addr2) -{ - std::cerr << "Socket2 Listening " << std::endl; - /* listen */ - int err = tou_listenfor(fd2, (struct sockaddr *) &addr1, sizeof(addr1)); - int err_num; - - if (err < 0) - { - err_num = tou_errno(fd2); - if (err_num != EINPROGRESS) - { - std::cerr << "Cannot Listen!: " << err_num << std::endl; - return -1; - } - } - - - std::cerr << "Socket1 Connecting to: " << addr2 << std::endl; - err = tou_connect(fd1, (struct sockaddr *) &addr2, sizeof(addr2)); - if (err < 0) - { - err_num = tou_errno(fd1); - if (err_num != EINPROGRESS) - { - std::cerr << "Cannot Connect!: " << err_num << std::endl; - return -1; - } - } - - bool sock1Connected = false; - bool sock2Connected = false; - - while((!sock1Connected) || (!sock2Connected)) - { - sleep(1); - - /* sock1 */ - if((!sock1Connected) && (0 == (err = tou_connected(fd1)))) - { - std::cerr << "Waiting for Connect (Sock1)!" << std::endl; - } - - if ((!sock1Connected) && (err < 0)) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - else if (!sock1Connected) - { - // else connected! - sock1Connected = true; - } - - /* accept - sock2 */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock = -1; - - if ((!sock2Connected) && (0 > (nsock = tou_accept(fd2, - (struct sockaddr *) &inaddr, &addrlen)))) - { - errno = tou_errno(fd2); - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - else - { - std::cerr << "Waiting for Connect (Sock2)!" << std::endl; - } - } - else if (nsock > 0) - { - /* connected */ - sock2Connected = true; - fd2 = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - } - - std::cerr << "Socket Connected" << std::endl; - - return 1; -} - - -/* This transmits into sockfd1, and check to see that we recv - * it back from sockfd2 - */ - -int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size) -{ - /* what we recvd */ - char *recvd = (char *) malloc(size * 2); - int recvdsize = 0; - int sent = 0; - int sendsize = 0; - - int ts_start = time(NULL); - - int minsends = 100; /* min of 100 sends to complete all data */ - /* ensure we don't end up sending nothing */ - if (minsends * 10 > size) - { - minsends = size / 10; - } - - bool doneWrite = false; - bool doneRead = false; - while((!doneWrite) || (!doneRead)) - { - /* have a little break */ - //usleep(10000); /* 0.01 sec */ - //usleep(250000); /* 0.25 sec */ - usleep(500000); /* 0.50 sec */ - /* decide how much to send */ - sendsize = (int) (((float) (size / minsends)) * - (rand() / (RAND_MAX + 1.0))); - - /* limit send */ - if (sent + sendsize > size) - { - sendsize = size - sent; - } - /* if we've finished */ - if (sent == size) - { - /* eof */ - std::cerr << "Write Done!" << std::endl; - doneWrite = true; - sendsize = 0; - } - - /* now we write */ - if ((sendsize > 0)&&(-1==tou_write(sockfd1,&(data[sent]),sendsize))) - { - std::cerr << "Write Error: " << tou_errno(sockfd1) << std::endl; - if (tou_errno(sockfd1) != EAGAIN) - { - std::cerr << "FATAL ERROR ending transfer" << std::endl; - doneRead = true; - doneWrite = true; - } - - } - else - { - sent += sendsize; - } - - int ret = 0; - int readsize = (int) (((float) (size / minsends)) * - (rand() / (RAND_MAX + 1.0))); - - if (readsize > size - recvdsize) - readsize = size - recvdsize; - - if (0 < (ret = tou_read(sockfd2, &(recvd[recvdsize]), readsize))) - { - std::cerr << "TF(" << ret << ")" << std::endl; - recvdsize += ret; - } - else if (ret == 0) - { - doneRead = true; - std::cerr << "Read Done! (ret:0)" << std::endl; - } - else - { - std::cerr << "Read Error: " << tou_errno(sockfd2) << std::endl; - std::cerr << "Read " << recvdsize << "/" << size; - std::cerr << " attempted: " << readsize << std::endl; - if (tou_errno(sockfd2) != EAGAIN) - { - std::cerr << "FATAL ERROR ending transfer" << std::endl; - doneRead = true; - doneWrite = true; - } - - } - - if (recvdsize == size) - { - doneRead = true; - std::cerr << "Read Done!" << std::endl; - } - - } - - /* we have transmitted it all, so - * check the data - */ - - int i; - int diffCount = 0; - for(i = 0; i < size; i++) - { - if (recvd[i] != data[i]) - { - diffCount++; - if (diffCount < 10) - { - std::cerr << "Error Byte:" << i << " is different"; - std::cerr << std::endl; - } - } - } - if (diffCount) - { - std::cerr << "Errors (" << diffCount << "/" << size << ") in tranmission ... Exiting!"; - std::cerr << std::endl; - exit(1); - } - - int ts_end = time(NULL); - double rough_rate = size / (double) (ts_end - ts_start); - - std::cerr << "Successful Data Tranmission: " << size << " in " << ts_end-ts_start << " secs"; - std::cerr << std::endl; - std::cerr << "Approximate Rate: " << rough_rate / 1000.0 << " kbytes/sec"; - std::cerr << std::endl; - - return 1; -} - - - - - - - - diff --git a/libretroshare/src/tests/tcponudp/largefile_tou.cc b/libretroshare/src/tests/tcponudp/largefile_tou.cc deleted file mode 100644 index 1bf0bebca..000000000 --- a/libretroshare/src/tests/tcponudp/largefile_tou.cc +++ /dev/null @@ -1,502 +0,0 @@ -/* - * "$Id: largefile_tou.cc,v 1.2 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -/********************************************************** - * This test is designed to test large data blocks/files - * running to tou. Currently we see occasional errors - * every 1/2 -> 1 MB of transfer.... - * - * This test will continually fill the output buffer, - * and then empty the receive one. To ensure the - * whole system gets a good workout. - * - */ - -#include - -// for printing sockaddr -#include "udplayer.h" - -#include "tou.h" -#include "tou_net.h" - -#include -#include -#include - -int setup_socket(struct sockaddr_in addr); -int connect_socket_pair(int fd1, int fd2, - struct sockaddr_in addr1, struct sockaddr_in addr2); -int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size); - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - int i,j; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - tounet_init(); - - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - unsigned short laddr_port = atoi(argv[optind+1]); - unsigned short raddr_port = atoi(argv[optind+3]); - - for(i = 0; i < 10; i++) - { - laddr.sin_port = htons(laddr_port); - raddr.sin_port = htons(raddr_port); - //laddr.sin_port = htons(laddr_port + i); - //raddr.sin_port = htons(raddr_port + i); - - std::cerr << "Interation: " << i << std::endl; - - - /* setup the sockets */ - int sockfd1 = setup_socket(laddr); - int sockfd2 = setup_socket(raddr); - - if ((sockfd1 < 0) || (sockfd2 < 0)) - { - std::cerr << "Failed to setup sockets!"; - std::cerr << std::endl; - return -1; - } - - std::cerr << "Local Address: " << laddr; - std::cerr << " fd: " << sockfd1 << std::endl; - std::cerr << "Remote Address: " << raddr; - std::cerr << " fd: " << sockfd2 << std::endl; - - /* connect */ - int err = connect_socket_pair(sockfd1, sockfd2, laddr, raddr); - if (err < 0) - { - std::cerr << "Failed to connect sockets!"; - std::cerr << std::endl; - return -1; - } - - /* send the data */ - int size = 3093237; - char rnddata[size]; - - int data_loops = (i+1) * (i+1); - for(int k = 0; k < data_loops; k++) - { - std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl; - for(j = 0; j < size; j++) - { - rnddata[j] = (unsigned char) (255.0 * - rand() / (RAND_MAX + 1.0)); - } - send_data_via_pair(sockfd1, sockfd2, rnddata, size); - std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl; - sleep(2); - } - - std::cerr << "Completed Successful transfer of " << size * data_loops << " bytes"; - std::cerr << std::endl; - - sleep(10); - std::cerr << "closing sockfd1: " << sockfd1 << std::endl; - tou_close(sockfd1); - - std::cerr << "closing sockfd2: " << sockfd2 << std::endl; - tou_close(sockfd2); - - - } - return 1; -} - -int setup_socket(struct sockaddr_in addr) -{ - int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0); - - if (sockfd <= 0) - { - std::cerr << "Failed to open socket!: "; - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - return -1; - } - - std::cerr << "Socket Created: " << sockfd << std::endl; - - int err = tou_bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)); - - if (err < 0) - { - std::cerr << "Error: Cannot bind socket: "; - std::cerr << err << std::endl; - return -1; - } - - std::cerr << "Socket1 Bound to: " << addr << std::endl; - return sockfd; -} - -int connect_socket_pair(int fd1, int fd2, - struct sockaddr_in addr1, struct sockaddr_in addr2) -{ - std::cerr << "Socket2 Listening " << std::endl; - /* listen */ - int err = tou_listenfor(fd2, (struct sockaddr *) &addr1, sizeof(addr1)); - int err_num; - - if (err < 0) - { - err_num = tou_errno(fd2); - if (err_num != EINPROGRESS) - { - std::cerr << "Cannot Listen!: " << err_num << std::endl; - return -1; - } - } - - - std::cerr << "Socket1 Connecting to: " << addr2 << std::endl; - err = tou_connect(fd1, (struct sockaddr *) &addr2, sizeof(addr2), 30); - if (err < 0) - { - err_num = tou_errno(fd1); - if (err_num != EINPROGRESS) - { - std::cerr << "Cannot Connect!: " << err_num << std::endl; - return -1; - } - } - - bool sock1Connected = false; - bool sock2Connected = false; - - while((!sock1Connected) || (!sock2Connected)) - { - sleep(1); - - /* sock1 */ - if((!sock1Connected) && (0 == (err = tou_connected(fd1)))) - { - std::cerr << "Waiting for Connect (Sock1)!" << std::endl; - } - - if ((!sock1Connected) && (err < 0)) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - else if (!sock1Connected) - { - // else connected! - sock1Connected = true; - } - - /* accept - sock2 */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock = -1; - - if ((!sock2Connected) && (0 > (nsock = tou_accept(fd2, - (struct sockaddr *) &inaddr, &addrlen)))) - { - errno = tou_errno(fd2); - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - else - { - std::cerr << "Waiting for Connect (Sock2)!" << std::endl; - } - } - else if (nsock > 0) - { - /* connected */ - sock2Connected = true; - fd2 = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - } - - std::cerr << "Socket Connected" << std::endl; - - return 1; -} - - -/* This transmits into sockfd1, and check to see that we recv - * it back from sockfd2 - */ - -int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size) -{ - /* what we recvd */ - char *recvd = (char *) malloc(size * 2); - int recvdsize = 0; - int sent = 0; - int sendsize = 0; - - int ts_start = time(NULL); - - int minsends = 100; /* min of 100 sends to complete all data */ - /* ensure we don't end up sending nothing */ - if (minsends * 10 > size) - { - minsends = size / 10; - } - - bool doneWrite = false; - bool doneRead = false; - - int maxtransfer = (int) (size / minsends) + (int) (((float) (size / minsends)) * - (rand() / (RAND_MAX + 1.0))); - /* allow the transfer ratio read/write to vary between 0.4->1,5. */ - double tf_ratio = 0.4 + 1.1 * (rand() / (RAND_MAX + 1.0)); - - while((!doneWrite) || (!doneRead)) - { - /* have a little break */ - //usleep(10000); /* 0.01 sec */ - usleep(20000); /* 0.02 sec */ - //usleep(250000); /* 0.25 sec */ - //usleep(500000); /* 0.50 sec */ - /* decide how much to send */ - sendsize = (int) (((float) (maxtransfer)) * - (rand() / (RAND_MAX + 1.0))); - - /* limit send */ - if (sent + sendsize > size) - { - std::cerr << "Last WRITE!" << std::endl; - sendsize = size - sent; - } - /* if we've finished */ - if (sent == size) - { - /* eof */ - std::cerr << "Write Done!" << std::endl; - doneWrite = true; - sendsize = 0; - } - - /* now we write */ - if ((sendsize > 0)&&(-1==tou_write(sockfd1,&(data[sent]),sendsize))) - { - std::cerr << "Write Error: " << tou_errno(sockfd1) << std::endl; - if (tou_errno(sockfd1) != EAGAIN) - { - std::cerr << "FATAL ERROR ending transfer" << std::endl; - doneRead = true; - doneWrite = true; - } - - } - else - { - sent += sendsize; - } - - int ret = 0; - - // read size about 1/4 of write to exercise the buffers. - int readsize = (int) (((float) (maxtransfer)) * tf_ratio * - (rand() / (RAND_MAX + 1.0))); - - if (readsize > size - recvdsize) - { - std::cerr << "Last READ!" << std::endl; - readsize = size - recvdsize; - } - - if (0 < (ret = tou_read(sockfd2, &(recvd[recvdsize]), readsize))) - { - std::cerr << "TF(" << ret << ")" << std::endl; - - /* check the data at this point */ - - int i; - int diffCount = 0; - int init_err = 0; - for(i = 0; i < ret; i++) - { - if (recvd[recvdsize + i] != data[recvdsize + i]) - { - if (!diffCount) - { - init_err = i; - } - diffCount++; - if (diffCount < 10) - { - std::cerr << "Error Byte:" << recvdsize + i << " is different"; - std::cerr << std::endl; - } - } - } - if (diffCount) - { - std::cerr << "Errors (" << diffCount << "/" << ret << ") in read, "; - std::cerr << std::endl; - std::cerr << " At Blk Start: " << recvdsize << " offset: " << init_err; - std::cerr << " ==> At index: " << recvdsize + init_err << "... Exiting!"; - std::cerr << std::endl; - exit(1); - } - else - { - std::cerr << "Checked (" << recvdsize << "+ 0 => " << ret << ") Okay" << std::endl; - } - - recvdsize += ret; - } - else if (ret == 0) - { - //doneRead = true; - std::cerr << "Read Done? (ret:0)" << std::endl; - } - else - { - std::cerr << "Read Error: " << tou_errno(sockfd2) << std::endl; - std::cerr << "Read " << recvdsize << "/" << size; - std::cerr << " attempted: " << readsize << std::endl; - if (tou_errno(sockfd2) != EAGAIN) - { - std::cerr << "FATAL ERROR ending transfer" << std::endl; - doneRead = true; - doneWrite = true; - } - - } - - if (recvdsize == size) - { - doneRead = true; - std::cerr << "Read Done!" << std::endl; - } - - } - - /* we have transmitted it all, so - * check the data - */ - - int i; - int diffCount = 0; - for(i = 0; i < size; i++) - { - if (recvd[i] != data[i]) - { - diffCount++; - if (diffCount < 10) - { - std::cerr << "Error Byte:" << i << " is different"; - std::cerr << std::endl; - } - } - } - if (diffCount) - { - std::cerr << "Errors (" << diffCount << "/" << size << ") in tranmission ... Exiting!"; - std::cerr << std::endl; - exit(1); - } - - int ts_end = time(NULL); - double rough_rate = size / (double) (ts_end - ts_start); - - std::cerr << "Successful Data Tranmission: " << size << " in " << ts_end-ts_start << " secs"; - std::cerr << std::endl; - std::cerr << "Approximate Rate: " << rough_rate / 1000.0 << " kbytes/sec"; - std::cerr << std::endl; - std::cerr << "Transfer Ratio: " << tf_ratio; - std::cerr << std::endl; - - free(recvd); - - return 1; -} - - - - - - - - diff --git a/libretroshare/src/tests/tcponudp/pair_tou.cc b/libretroshare/src/tests/tcponudp/pair_tou.cc deleted file mode 100644 index 945c6ac31..000000000 --- a/libretroshare/src/tests/tcponudp/pair_tou.cc +++ /dev/null @@ -1,508 +0,0 @@ -/* - * "$Id: pair_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include -#include - -//#define USE_TCP_SOCKET - -// for printing sockaddr -#include "udp/udpstack.h" - -#ifndef USE_TCP_SOCKET - #include "tcponudp/tou.h" - #include "tcponudp/udppeer.h" -#endif - -#include "util/bdnet.h" - -#include -#include -#include - - -/* This is a simple test to ensure that the tou behaviour - * is almost identical to a standard tcp socket. - * - * In this version we open 2 sockets, and attempt to - * communicate with ourselves.... - * - */ - -int Check_Socket(int fd); - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - - int totalwbytes = 0; - int totalrbytes = 0; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - laddr.sin_port = htons(atoi(argv[optind+1])); - raddr.sin_port = htons(atoi(argv[optind+3])); - - std::cerr << "Local Address: " << laddr << std::endl; - std::cerr << "Remote Address: " << raddr << std::endl; - - UdpStack *udpStack1 = new UdpStack(laddr); - UdpStack *udpStack2 = new UdpStack(raddr); - - UdpSubReceiver *udpReceivers[2]; - int udpTypes[2]; - - udpReceivers[0] = new UdpPeerReceiver(udpStack1); - udpTypes[0] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack1->addReceiver(udpReceivers[0]); - - udpReceivers[1] = new UdpPeerReceiver(udpStack2); - udpTypes[1] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack2->addReceiver(udpReceivers[1]); - - tou_init((void **) udpReceivers, udpTypes, 2); - - -#ifdef USE_TCP_SOCKET - int sockfd = socket(PF_INET, SOCK_STREAM, 0); - int sockfd2 = socket(PF_INET, SOCK_STREAM, 0); -#else - int sockfd = tou_socket(0, TOU_RECEIVER_TYPE_UDPPEER, 0); - int sockfd2 = tou_socket(1, TOU_RECEIVER_TYPE_UDPPEER, 0); -#endif - if ((sockfd <= 0) || (sockfd2 <= 0)) - { - std::cerr << "Failed to open socket!: "; -#ifdef USE_TCP_SOCKET - std::cerr << "Socket Error:" << errno << std::endl; -#else - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - std::cerr << "Socket Error:" << tou_errno(sockfd2) << std::endl; -#endif - return -1; - } - std::cerr << "Sockets Created: " << sockfd << " & " << sockfd2 << std::endl; - - - /* make nonblocking */ -#ifdef USE_TCP_SOCKET - int err = fcntl(sockfd,F_SETFD,O_NONBLOCK); - int err2 = fcntl(sockfd2,F_SETFD,O_NONBLOCK); -#else - int err = 0; - int err2 = 0; -#endif - if ((err < 0) || (err2 < 0)) - { - std::cerr << "Error: Cannot make socket NON-Blocking: "; - std::cerr << err << std::endl; - return -1; - } - - std::cerr << "Socket Non-Blocking" << std::endl; - -#ifdef USE_TCP_SOCKET - err = bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr)); - err2 = bind(sockfd2, (struct sockaddr *) &raddr, sizeof(raddr)); - if ((err < 0) || (err2 < 0)) - { - std::cerr << "Error: Cannot bind socket: "; - std::cerr << err << std::endl; - return -1; - } -#else - // No more Bind in tou. - //err = tou_bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr)); - //err2 = tou_bind(sockfd2, (struct sockaddr *) &raddr, sizeof(raddr)); -#endif - - std::cerr << "Socket1 Bound to: " << laddr << std::endl; - std::cerr << "Socket2 Bound to: " << raddr << std::endl; - - // listening. - if (1) // socket2. - { - std::cerr << "Socket2 Listening " << std::endl; - /* listen */ -#ifdef USE_TCP_SOCKET - err = listen(sockfd2, 1); -#else - err = tou_listenfor(sockfd2, - (struct sockaddr *) &laddr, sizeof(laddr)); -#endif - } - - - if (1) // only one program. - { - std::cerr << "Socket1 Connecting to: " << raddr << std::endl; -#ifdef USE_TCP_SOCKET - err = connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr)); -#else - err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30); -#endif - if (err < 0) - { -#ifndef USE_TCP_SOCKET - errno = tou_errno(sockfd); -#endif - if (errno != EINPROGRESS) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - } - } - - bool sock1Connected = false; - bool sock2Connected = false; - - while((!sock1Connected) || (!sock2Connected)) - { - sleep(1); - - - /* sock1 */ -#ifdef USE_TCP_SOCKET - if((!sock1Connected) && (0 == (err = Check_Socket(sockfd)))) -#else - if((!sock1Connected) && (0 == (err = tou_connected(sockfd)))) -#endif - { - std::cerr << "Waiting for Connect (Sock1)!" << std::endl; - } - if ((!sock1Connected) && (err < 0)) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - else if (!sock1Connected) - { - // else connected! - sock1Connected = true; - } - - /* accept - sock2 */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock = -1; - -#ifdef USE_TCP_SOCKET - if ((!sock2Connected) && (0 > (nsock = accept(sockfd2, - (struct sockaddr *) &inaddr, &addrlen)))) -#else - if ((!sock2Connected) && (0 > (nsock = tou_accept(sockfd2, - (struct sockaddr *) &inaddr, &addrlen)))) -#endif - { -#ifndef USE_TCP_SOCKET - errno = tou_errno(sockfd2); -#endif - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - else - { - std::cerr << "Waiting for Connect (Sock2)!" << std::endl; - } - } - else if (nsock > 0) - { - /* connected */ - sock2Connected = true; - sockfd2 = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - } - - std::cerr << "Socket Connected" << std::endl; - - /* send data */ - int bufsize = 1511; - char buffer[bufsize]; - char data[bufsize]; - int readsize = 0; - - bdnet_fcntl(0, F_SETFL, O_NONBLOCK); - bdnet_fcntl(1,F_SETFL,O_NONBLOCK); - - bool doneWrite = false; - bool doneRead = false; - bool blockread = false; - while((!doneWrite) || (!doneRead)) - { - /* read -> write_socket... */ - sleep(1); - if (blockread != true) - { - readsize = read(0, buffer, bufsize); - } - if (readsize == 0) - { - /* eof */ - doneWrite = true; - } - /* now we write */ -#ifdef USE_TCP_SOCKET - if ((readsize > 0) && (-1 == write(sockfd, buffer, readsize))) -#else - if ((readsize > 0) && (-1 == tou_write(sockfd, buffer, readsize))) -#endif - { - //std::cerr << "Blocked Write!" << std::endl; -#ifndef USE_TCP_SOCKET - //std::cerr << "Error: " << tou_errno(sockfd) << std::endl; -#endif - blockread = true; - } - else - { - blockread = false; - totalwbytes += readsize; - } - - int ret = 0; -#ifdef USE_TCP_SOCKET - if (0 < (ret = read(sockfd2, data, bufsize))) -#else - if (0 < (ret = tou_read(sockfd2, data, bufsize))) -#endif - - { - std::cerr << "TF(" << ret << ")" << std::endl; - write(1, data, ret); - totalrbytes += ret; - } - else if (ret == 0) - { - doneRead = true; - } - else - { - //std::cerr << "Blocked Read!" << std::endl; -#ifndef USE_TCP_SOCKET - //std::cerr << "Error: " << tou_errno(sockfd) << std::endl; -#endif - } - - - } - -#ifdef USE_TCP_SOCKET - close(sockfd); - close(sockfd2); -#else - /* this is blocking??? */ - tou_close(sockfd); - tou_close(sockfd2); -#endif - - std::cerr << "Transfer Complete: " << totalwbytes << " bytes"; - std::cerr << std::endl; - return 1; -} - -#ifdef USE_TCP_SOCKET - - -int Check_Socket(int fd) -{ - std::cerr << "Check_Socket()" << std::endl; - - std::cerr << "1) Checking with Select()" << std::endl; - - fd_set ReadFDs, WriteFDs, ExceptFDs; - FD_ZERO(&ReadFDs); - FD_ZERO(&WriteFDs); - FD_ZERO(&ExceptFDs); - - FD_SET(fd, &ReadFDs); - FD_SET(fd, &WriteFDs); - FD_SET(fd, &ExceptFDs); - - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - int sr = 0; - if (0 > (sr = select(fd + 1, - &ReadFDs, &WriteFDs, &ExceptFDs, &timeout))) - { - std::cerr << "Check_Socket() Select ERROR: " << sr << std::endl; - return -1; - } - - if (FD_ISSET(fd, &ExceptFDs)) - { - std::cerr << "Check_Socket() Exception on socket!" << std::endl; - return -1; - } - - if (FD_ISSET(fd, &WriteFDs)) - { - std::cerr << "Check_Socket() Can Write!" << std::endl; - } - else - { - // not ready return 0; - std::cerr << "Check_Socket() Cannot Write!" << std::endl; - std::cerr << "Check_Socket() Socket Not Ready!" << std::endl; - return 0; - } - - if (FD_ISSET(fd, &ReadFDs)) - { - std::cerr << "Check_Socket() Can Read!" << std::endl; - } - else - { - std::cerr << "Check_Socket() Cannot Read!" << std::endl; - std::cerr << "Check_Socket() Socket Not Ready!" << std::endl; - return 0; - } - - std::cerr << "Select() Tests indicate Socket Good!" << std::endl; - std::cerr << "2) Checking with getsockopt()" << std::endl; - - int err = 1; - socklen_t optlen = 4; - if (0==getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen)) - { - std::cerr << "Check_Socket() getsockopt returned :" << err; - std::cerr << ", optlen:" << optlen; - std::cerr << std::endl; - - if (err == 0) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection Complete:"; - std::cerr << std::endl; - return 1; - } - else if (err == EINPROGRESS) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection INPROGRESS"; - std::cerr << std::endl; - return 0; - } - else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT"; - std::cerr << std::endl; - return -1; - } - else if ((err == EHOSTUNREACH) || (err == EHOSTDOWN)) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT"; - std::cerr << std::endl; - return -1; - } - else - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates Other Error: " << err; - std::cerr << std::endl; - return -1; - } - - - } - else - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " FAILED "; - std::cerr << std::endl; - return -1; - } -} - - -#else - -int Check_Socket(int fd) -{ - return 0; -} - -#endif diff --git a/libretroshare/src/tests/tcponudp/reset_tou.cc b/libretroshare/src/tests/tcponudp/reset_tou.cc deleted file mode 100644 index 3faa8851c..000000000 --- a/libretroshare/src/tests/tcponudp/reset_tou.cc +++ /dev/null @@ -1,453 +0,0 @@ -/* - * "$Id: reset_tou.cc,v 1.4 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -/********************************************************** - * This test is designed to ensure that tou networking - * can be reset, and restarted. - * - */ - -#include - -// for printing sockaddr -#include "udplayer.h" - -#include "tou.h" -#include "tou_net.h" - -#include -#include -#include - - -/* This is a simple test to ensure that the tou behaviour - * is almost identical to a standard tcp socket. - * - * In this version we open 2 sockets, and attempt to - * communicate with ourselves.... - * - */ - -int setup_socket(struct sockaddr_in addr); -int connect_socket_pair(int fd1, int fd2, - struct sockaddr_in addr1, struct sockaddr_in addr2); -int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size); - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - int i,j; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - tounet_init(); - - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - unsigned short laddr_port = atoi(argv[optind+1]); - unsigned short raddr_port = atoi(argv[optind+3]); - - for(i = 0; i < 10; i++) - { - laddr.sin_port = htons(laddr_port); - raddr.sin_port = htons(raddr_port); - //laddr.sin_port = htons(laddr_port + i); - //raddr.sin_port = htons(raddr_port + i); - - std::cerr << "Interation: " << i << std::endl; - - - /* setup the sockets */ - int sockfd1 = setup_socket(laddr); - int sockfd2 = setup_socket(raddr); - - if ((sockfd1 < 0) || (sockfd2 < 0)) - { - std::cerr << "Failed to setup sockets!"; - std::cerr << std::endl; - return -1; - } - - std::cerr << "Local Address: " << laddr; - std::cerr << " fd: " << sockfd1 << std::endl; - std::cerr << "Remote Address: " << raddr; - std::cerr << " fd: " << sockfd2 << std::endl; - - /* connect */ - int err = connect_socket_pair(sockfd1, sockfd2, laddr, raddr); - if (err < 0) - { - std::cerr << "Failed to connect sockets!"; - std::cerr << std::endl; - return -1; - } - - /* send the data */ - int size = 102400; - char rnddata[size]; - - int data_loops = (i+1) * (i+1); - for(int k = 0; k < data_loops; k++) - { - std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl; - for(j = 0; j < size; j++) - { - rnddata[j] = (unsigned char) (255.0 * - rand() / (RAND_MAX + 1.0)); - } - send_data_via_pair(sockfd1, sockfd2, rnddata, size); - std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl; - sleep(2); - } - - std::cerr << "Completed Successful transfer of " << size * data_loops << " bytes"; - std::cerr << std::endl; - - sleep(10); - std::cerr << "closing sockfd1: " << sockfd1 << std::endl; - tou_close(sockfd1); - - std::cerr << "closing sockfd2: " << sockfd2 << std::endl; - tou_close(sockfd2); - - - } - return 1; -} - -int setup_socket(struct sockaddr_in addr) -{ - int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0); - - if (sockfd <= 0) - { - std::cerr << "Failed to open socket!: "; - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - return -1; - } - - std::cerr << "Socket Created: " << sockfd << std::endl; - - int err = tou_bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)); - - if (err < 0) - { - std::cerr << "Error: Cannot bind socket: "; - std::cerr << err << std::endl; - return -1; - } - - std::cerr << "Socket1 Bound to: " << addr << std::endl; - return sockfd; -} - -int connect_socket_pair(int fd1, int fd2, - struct sockaddr_in addr1, struct sockaddr_in addr2) -{ - std::cerr << "Socket2 Listening " << std::endl; - /* listen */ - int err = tou_listenfor(fd2, (struct sockaddr *) &addr1, sizeof(addr1)); - int err_num; - - if (err < 0) - { - err_num = tou_errno(fd2); - if (err_num != EINPROGRESS) - { - std::cerr << "Cannot Listen!: " << err_num << std::endl; - return -1; - } - } - - - std::cerr << "Socket1 Connecting to: " << addr2 << std::endl; - err = tou_connect(fd1, (struct sockaddr *) &addr2, sizeof(addr2), 30); - if (err < 0) - { - err_num = tou_errno(fd1); - if (err_num != EINPROGRESS) - { - std::cerr << "Cannot Connect!: " << err_num << std::endl; - return -1; - } - } - - bool sock1Connected = false; - bool sock2Connected = false; - - while((!sock1Connected) || (!sock2Connected)) - { - sleep(1); - - /* sock1 */ - if((!sock1Connected) && (0 == (err = tou_connected(fd1)))) - { - std::cerr << "Waiting for Connect (Sock1)!" << std::endl; - } - - if ((!sock1Connected) && (err < 0)) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - else if (!sock1Connected) - { - // else connected! - sock1Connected = true; - } - - /* accept - sock2 */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock = -1; - - if ((!sock2Connected) && (0 > (nsock = tou_accept(fd2, - (struct sockaddr *) &inaddr, &addrlen)))) - { - errno = tou_errno(fd2); - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - else - { - std::cerr << "Waiting for Connect (Sock2)!" << std::endl; - } - } - else if (nsock > 0) - { - /* connected */ - sock2Connected = true; - fd2 = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - } - - std::cerr << "Socket Connected" << std::endl; - - return 1; -} - - -/* This transmits into sockfd1, and check to see that we recv - * it back from sockfd2 - */ - -int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size) -{ - /* what we recvd */ - char *recvd = (char *) malloc(size * 2); - int recvdsize = 0; - int sent = 0; - int sendsize = 0; - - int ts_start = time(NULL); - - int minsends = 100; /* min of 100 sends to complete all data */ - /* ensure we don't end up sending nothing */ - if (minsends * 10 > size) - { - minsends = size / 10; - } - - bool doneWrite = false; - bool doneRead = false; - while((!doneWrite) || (!doneRead)) - { - /* have a little break */ - //usleep(10000); /* 0.01 sec */ - //usleep(250000); /* 0.25 sec */ - usleep(500000); /* 0.50 sec */ - /* decide how much to send */ - sendsize = (int) (((float) (size / minsends)) * - (rand() / (RAND_MAX + 1.0))); - - /* limit send */ - if (sent + sendsize > size) - { - sendsize = size - sent; - } - /* if we've finished */ - if (sent == size) - { - /* eof */ - std::cerr << "Write Done!" << std::endl; - doneWrite = true; - sendsize = 0; - } - - /* now we write */ - if ((sendsize > 0)&&(-1==tou_write(sockfd1,&(data[sent]),sendsize))) - { - std::cerr << "Write Error: " << tou_errno(sockfd1) << std::endl; - if (tou_errno(sockfd1) != EAGAIN) - { - std::cerr << "FATAL ERROR ending transfer" << std::endl; - doneRead = true; - doneWrite = true; - } - - } - else - { - sent += sendsize; - } - - int ret = 0; - int readsize = (int) (((float) (size / minsends)) * - (rand() / (RAND_MAX + 1.0))); - - if (readsize > size - recvdsize) - readsize = size - recvdsize; - - if (0 < (ret = tou_read(sockfd2, &(recvd[recvdsize]), readsize))) - { - std::cerr << "TF(" << ret << ")" << std::endl; - recvdsize += ret; - } - else if (ret == 0) - { - doneRead = true; - std::cerr << "Read Done! (ret:0)" << std::endl; - } - else - { - std::cerr << "Read Error: " << tou_errno(sockfd2) << std::endl; - std::cerr << "Read " << recvdsize << "/" << size; - std::cerr << " attempted: " << readsize << std::endl; - if (tou_errno(sockfd2) != EAGAIN) - { - std::cerr << "FATAL ERROR ending transfer" << std::endl; - doneRead = true; - doneWrite = true; - } - - } - - if (recvdsize == size) - { - doneRead = true; - std::cerr << "Read Done!" << std::endl; - } - - } - - /* we have transmitted it all, so - * check the data - */ - - int i; - int diffCount = 0; - for(i = 0; i < size; i++) - { - if (recvd[i] != data[i]) - { - diffCount++; - if (diffCount < 10) - { - std::cerr << "Error Byte:" << i << " is different"; - std::cerr << std::endl; - } - } - } - if (diffCount) - { - std::cerr << "Errors (" << diffCount << "/" << size << ") in tranmission ... Exiting!"; - std::cerr << std::endl; - exit(1); - } - - int ts_end = time(NULL); - double rough_rate = size / (double) (ts_end - ts_start); - - std::cerr << "Successful Data Tranmission: " << size << " in " << ts_end-ts_start << " secs"; - std::cerr << std::endl; - std::cerr << "Approximate Rate: " << rough_rate / 1000.0 << " kbytes/sec"; - std::cerr << std::endl; - - return 1; -} - - - - - - - - diff --git a/libretroshare/src/tests/tcponudp/stacks_tou.cc b/libretroshare/src/tests/tcponudp/stacks_tou.cc deleted file mode 100644 index ece3915b4..000000000 --- a/libretroshare/src/tests/tcponudp/stacks_tou.cc +++ /dev/null @@ -1,354 +0,0 @@ -/* - * "$Id: pair_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include -#include - -// for printing sockaddr -#include "udp/udpstack.h" - -#include "tcponudp/tou.h" -#include "tcponudp/udppeer.h" -#include "tcponudp/udprelay.h" - -#include "util/bdnet.h" - -#include "util/rsrandom.h" - -#include -#include -#include - - -/* - * This test creates the same stacks as are used in RS. - * This additionally tests the "checkFns" for the other UdpReceivers, which could potentially be modifying the data. - * obviously they shouldn't! - * - */ - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - - int totalwbytes = 0; - int totalrbytes = 0; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - laddr.sin_port = htons(atoi(argv[optind+1])); - raddr.sin_port = htons(atoi(argv[optind+3])); - - std::cerr << "Local Address: " << laddr << std::endl; - std::cerr << "Remote Address: " << raddr << std::endl; - - std::cerr << "Creating with Lossy Udp Layers for further testing"; - std::cerr << std::endl; - - UdpStack *udpStack1 = new UdpStack(UDP_TEST_LOSSY_LAYER,laddr); - UdpStack *udpStack2 = new UdpStack(UDP_TEST_LOSSY_LAYER,raddr); - - UdpSubReceiver *udpReceivers[4]; - int udpTypes[4]; - - // NOTE DHT is too hard to add at the moment. - - UdpRelayReceiver *mRelay1 = new UdpRelayReceiver(udpStack1); - udpReceivers[1] = mRelay1; - udpTypes[1] = TOU_RECEIVER_TYPE_UDPRELAY; - udpStack1->addReceiver(udpReceivers[1]); - - udpReceivers[0] = new UdpPeerReceiver(udpStack1); - udpTypes[0] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack1->addReceiver(udpReceivers[0]); - - // STACK 2. - UdpRelayReceiver *mRelay2 = new UdpRelayReceiver(udpStack2); - udpReceivers[3] = mRelay2; - udpTypes[3] = TOU_RECEIVER_TYPE_UDPRELAY; - udpStack2->addReceiver(udpReceivers[3]); - - udpReceivers[2] = new UdpPeerReceiver(udpStack2); - udpTypes[2] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack2->addReceiver(udpReceivers[2]); - - tou_init((void **) udpReceivers, udpTypes, 4); - - - int sockfd = tou_socket(0, TOU_RECEIVER_TYPE_UDPPEER, 0); - int sockfd2 = tou_socket(2, TOU_RECEIVER_TYPE_UDPPEER, 0); - if ((sockfd <= 0) || (sockfd2 <= 0)) - { - std::cerr << "Failed to open socket!: "; - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - std::cerr << "Socket Error:" << tou_errno(sockfd2) << std::endl; - return -1; - } - std::cerr << "Sockets Created: " << sockfd << " & " << sockfd2 << std::endl; - - std::cerr << "Socket Non-Blocking" << std::endl; - - std::cerr << "Socket1 Bound to: " << laddr << std::endl; - std::cerr << "Socket2 Bound to: " << raddr << std::endl; - - int err = 0; - - // listening. - if (1) // socket2. - { - std::cerr << "Socket2 Listening " << std::endl; - /* listen */ - err = tou_listenfor(sockfd2, - (struct sockaddr *) &laddr, sizeof(laddr)); - } - - - if (1) // only one program. - { - std::cerr << "Socket1 Connecting to: " << raddr << std::endl; - err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30); - if (err < 0) - { - errno = tou_errno(sockfd); - if (errno != EINPROGRESS) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - } - } - - bool sock1Connected = false; - bool sock2Connected = false; - - while((!sock1Connected) || (!sock2Connected)) - { - usleep(1000); - - - /* sock1 */ - if((!sock1Connected) && (0 == (err = tou_connected(sockfd)))) - { - std::cerr << "Waiting for Connect (Sock1)!" << std::endl; - } - if ((!sock1Connected) && (err < 0)) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - else if (!sock1Connected) - { - // else connected! - sock1Connected = true; - } - - /* accept - sock2 */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock = -1; - - if ((!sock2Connected) && (0 > (nsock = tou_accept(sockfd2, - (struct sockaddr *) &inaddr, &addrlen)))) - { - errno = tou_errno(sockfd2); - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - else - { - std::cerr << "Waiting for Connect (Sock2)!" << std::endl; - } - } - else if (nsock > 0) - { - /* connected */ - sock2Connected = true; - sockfd2 = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - } - - std::cerr << "Socket Connected" << std::endl; - -#define MAX_READ 20000 - - /* send data */ - int bufsize = MAX_READ; - char buffer[MAX_READ]; - char data[MAX_READ]; - int readsize = 0; - - bdnet_fcntl(0, F_SETFL, O_NONBLOCK); - bdnet_fcntl(1,F_SETFL,O_NONBLOCK); - - rstime_t lastRead = time(NULL); - bool doneWrite = false; - bool doneRead = false; - bool blockread = false; - - while((!doneWrite) || (!doneRead)) - { - /* read -> write_socket... */ - usleep(10); - - if (blockread != true) - { - int readbuf = 1 + RSRandom::random_u32() % (MAX_READ - 1); - readsize = read(0, buffer, readbuf); - if (readsize) - { - //std::cerr << "read " << readsize << " / " << readbuf; - //std::cerr << std::endl; - } - } - if ((readsize == 0) && (!doneWrite)) - { - /* eof */ - doneWrite = true; - std::cerr << "Write Done Total: " << totalwbytes; - std::cerr << std::endl; - } - /* now we write */ - if ((readsize > 0) && (-1 == tou_write(sockfd, buffer, readsize))) - { - //std::cerr << "Blocked Write "; - //std::cerr << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; - blockread = true; - } - else - { - blockread = false; - totalwbytes += readsize; - - if (readsize) - { - std::cerr << "Written: " << readsize << ", Total: " << totalwbytes; - std::cerr << " In Transit: " << totalwbytes - totalrbytes; - std::cerr << std::endl; - } - } - - int ret = 0; - int readbuf2 = 1 + RSRandom::random_u32() % (MAX_READ - 1); - if (0 < (ret = tou_read(sockfd2, data, readbuf2))) - { - //std::cerr << "TF(" << ret << ")" << std::endl; - write(1, data, ret); - totalrbytes += ret; - - std::cerr << "Read: " << ret << " Total: " << totalrbytes; - std::cerr << " In Transit: " << totalwbytes - totalrbytes; - std::cerr << std::endl; - - lastRead = time(NULL); - } - else if ((ret == 0) && (!doneRead)) - { - doneRead = true; - std::cerr << "Read Done Total: " << totalrbytes; - std::cerr << std::endl; - } - else - { - //std::cerr << "Blocked Read: " << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; -#define TIMEOUT 15 - if ((!doneRead) && (time(NULL) - lastRead > TIMEOUT)) - { - doneRead = true; - std::cerr << "TIMEOUT: Read Done Total: " << totalrbytes; - std::cerr << std::endl; - } - } - - - } - - /* this is blocking??? */ - tou_close(sockfd); - tou_close(sockfd2); - - std::cerr << "Transfer Complete: " << totalwbytes << " bytes"; - std::cerr << std::endl; - return 1; -} - diff --git a/libretroshare/src/tests/tcponudp/stacks_tou.sh b/libretroshare/src/tests/tcponudp/stacks_tou.sh deleted file mode 100755 index 7715e769d..000000000 --- a/libretroshare/src/tests/tcponudp/stacks_tou.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -# Script to Test the udp_server code. - -EXEC=./stacks_tou -DATAFILE=./stacks_tou - -TMPOUTPUT=tmpoutput$$ -EXPECTEDPERIOD=10 - -$EXEC 127.0.0.1 4401 127.0.0.1 4032 < $DATAFILE > $TMPOUTPUT - -if diff -s $DATAFILE $TMPOUTPUT -then - echo "SUCCESS" -else - echo "FAILURE to accurately transfer DATA" -fi - -rm $TMPOUTPUT - diff --git a/libretroshare/src/tests/tcponudp/test_tou.cc b/libretroshare/src/tests/tcponudp/test_tou.cc deleted file mode 100644 index 17035f631..000000000 --- a/libretroshare/src/tests/tcponudp/test_tou.cc +++ /dev/null @@ -1,531 +0,0 @@ -/* - * "$Id: test_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include -#include - -//#define USE_TCP_SOCKET 1 - -// for printing sockaddr -#include "udp/udpstack.h" - -#ifndef USE_TCP_SOCKET - #include "tcponudp/tou.h" - #include "tcponudp/udppeer.h" -#endif - -/* shouldn't do this - but for convenience - * using tou_net.h for universal fns - * generally this should be only internal to libtou.h - * - * This includes the whole networking interface - */ - -#include "util/bdnet.h" - -/* These three includes appear to work in both W & L. - * and they shouldn't!!!! maybe cygwin is allowing it... - * will only use them for tou test fns. - * - * they appear to provide getopt + read/write in windows. - */ - -#include -#include -#include - -/* This is a simple test to ensure that the tou behaviour - * is almost identical to a standard tcp socket. - * - */ - -int Check_Socket(int fd); - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - - int totalwbytes = 0; - int totalrbytes = 0; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - laddr.sin_port = htons(atoi(argv[optind+1])); - raddr.sin_port = htons(atoi(argv[optind+3])); - - std::cerr << "Local Address: " << laddr << std::endl; - std::cerr << "Remote Address: " << raddr << std::endl; - - - - -#ifdef USE_TCP_SOCKET - int sockfd = socket(PF_INET, SOCK_STREAM, 0); -#else - - UdpStack udps(laddr); - - UdpSubReceiver *udpReceivers[1]; - int udpTypes[1]; - - udpReceivers[0] = new UdpPeerReceiver(&udps); - udpTypes[0] = TOU_RECEIVER_TYPE_UDPPEER; - udps.addReceiver(udpReceivers[0]); - - tou_init((void **) udpReceivers, udpTypes, 1); - - int sockfd = tou_socket(0, TOU_RECEIVER_TYPE_UDPPEER, 0); -#endif - if (sockfd < 0) - { - std::cerr << "Failed to open socket!: "; -#ifdef USE_TCP_SOCKET - std::cerr << "Socket Error:" << errno << std::endl; -#else - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; -#endif - return -1; - } - std::cerr << "Socket Created" << std::endl; - - - /* make nonblocking */ -#ifdef USE_TCP_SOCKET - int err = bdnet_fcntl(sockfd,F_SETFL,O_NONBLOCK); -#else - int err = 0; -#endif - if (err < 0) - { - std::cerr << "Error: Cannot make socket NON-Blocking: "; - std::cerr << err << std::endl; - return -1; - } - - std::cerr << "Socket Non-Blocking" << std::endl; - -#ifdef USE_TCP_SOCKET - err = bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr)); - if (err < 0) - { - std::cerr << "Error: Cannot bind socket: "; - std::cerr << err << std::endl; - return -1; - } - std::cerr << "Socket Bound to: " << laddr << std::endl; -#else - err = tou_bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr)); - if (err < 0) - { - std::cerr << "As expected, cannot bind a tou socket"; - std::cerr << err << std::endl; - //return -1; - } -#endif - - - if (toConnect) - { - std::cerr << "Socket Connecting to: " << raddr << std::endl; -#ifdef USE_TCP_SOCKET - err = connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr)); -#else - err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30); -#endif - if (err < 0) - { -#ifndef USE_TCP_SOCKET - errno = tou_errno(sockfd); -#endif - if (errno != EINPROGRESS) - { - std::cerr << "Cannot Connect!" << std::endl; - return 1; - } -#ifdef USE_TCP_SOCKET - while(0 == (err = Check_Socket(sockfd))) -#else - while(0 == (err = tou_connected(sockfd))) -#endif - { - std::cerr << "Waiting for Connect!" << std::endl; - sleep(1); - } - if (err < 0) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - // else connected! - } - } - else - { - std::cerr << "Socket Listening " << std::endl; - /* listen */ -#ifdef USE_TCP_SOCKET - err = listen(sockfd, 1); -#else - //err = tou_listen(sockfd, 1); - err = tou_listenfor(sockfd, - (struct sockaddr *) &raddr, sizeof(raddr)); -#endif - - /* accept */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock; - -#ifdef USE_TCP_SOCKET - while(0 > (nsock = accept(sockfd, - (struct sockaddr *) &inaddr, &addrlen))) -#else - while(0 > (nsock = tou_accept(sockfd, - (struct sockaddr *) &inaddr, &addrlen))) -#endif - { -#ifndef USE_TCP_SOCKET - errno = tou_errno(sockfd); -#endif - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!" << std::endl; - return 1; - } - sleep(1); - } - /* changed sockfd */ - sockfd = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - - std::cerr << "Socket Connected" << std::endl; - - if (toConnect) - { - /* send data */ - int bufsize = 15011; - char buffer[bufsize]; - int readsize = 0; - - bdnet_fcntl(0, F_SETFL, O_NONBLOCK); - - bool done = false; - bool blockread = false; - while(!done) - { - //sleep(1); - //usleep(10000); - usleep(100); - if (blockread != true) - { - readsize = read(0, buffer, bufsize); - } - if (readsize == 0) - { - /* eof */ - done = true; - } - else if ((readsize == -1) && ( EAGAIN == errno )) - { - continue; - } - - - /* now we write */ -#ifdef USE_TCP_SOCKET - if (-1 == write(sockfd, buffer, readsize)) -#else - if (-1 == tou_write(sockfd, buffer, readsize)) -#endif - { - //std::cerr << "Blocked Write!" << std::endl; -#ifndef USE_TCP_SOCKET - //std::cerr << "Error: " << tou_errno(sockfd) << std::endl; -#endif - blockread = true; - } - else - { - blockread = false; - totalwbytes += readsize; - } - } - -#ifdef USE_TCP_SOCKET - close(sockfd); -#else - /* this is blocking??? */ - tou_close(sockfd); -#endif - - std::cerr << "Transfer Complete: " << totalwbytes << " bytes"; - std::cerr << std::endl; - - // ACTUALLY tou_close() is not blocking... - // and kills the connection instantly. - // The transfer will fail if there is any data left in the send queue (which there is in most cases). - // Interestingly.. if we slow the transmit and speed up the recv, - // Then it can succeed. - // - // The settings are done to make this fail. - - return 1; - } - - /* recv data */ - int bufsize = 1523; - char data[bufsize]; - bdnet_fcntl(1,F_SETFL,O_NONBLOCK); - while(1) - { - //sleep(1); - //usleep(10000); - //usleep(1000); - usleep(100); - int writesize = bufsize; - int ret; - -#ifdef USE_TCP_SOCKET - if (0 < (ret = read(sockfd, data, writesize))) -#else - if (0 < (ret = tou_read(sockfd, data, writesize))) -#endif - - { - std::cerr << "TF(" << ret << ")" << std::endl; - write(1, data, ret); - totalrbytes += ret; - } - else if (ret == 0) - { - break; - } - else - { - //std::cerr << "Blocked Read!" << std::endl; -#ifndef USE_TCP_SOCKET - //std::cerr << "Error: " << tou_errno(sockfd) << std::endl; -#endif - - } - } - -#ifdef USE_TCP_SOCKET - close(sockfd); -#else - tou_close(sockfd); -#endif - - std::cerr << "Transfer complete :" << totalrbytes; - std::cerr << " bytes" << std::endl; - close(1); - - return 1; -} - - - -#ifdef USE_TCP_SOCKET - - -int Check_Socket(int fd) -{ - std::cerr << "Check_Socket()" << std::endl; - - std::cerr << "1) Checking with Select()" << std::endl; - - fd_set ReadFDs, WriteFDs, ExceptFDs; - FD_ZERO(&ReadFDs); - FD_ZERO(&WriteFDs); - FD_ZERO(&ExceptFDs); - - FD_SET(fd, &ReadFDs); - FD_SET(fd, &WriteFDs); - FD_SET(fd, &ExceptFDs); - - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - int sr = 0; - if (0 > (sr = select(fd + 1, - &ReadFDs, &WriteFDs, &ExceptFDs, &timeout))) - { - std::cerr << "Check_Socket() Select ERROR: " << sr << std::endl; - return -1; - } - - if (FD_ISSET(fd, &ExceptFDs)) - { - std::cerr << "Check_Socket() Exception on socket!" << std::endl; - return -1; - } - - if (FD_ISSET(fd, &WriteFDs)) - { - std::cerr << "Check_Socket() Can Write!" << std::endl; - } - else - { - // not ready return 0; - std::cerr << "Check_Socket() Cannot Write!" << std::endl; - std::cerr << "Check_Socket() Socket Not Ready!" << std::endl; - return 0; - } - - if (FD_ISSET(fd, &ReadFDs)) - { - std::cerr << "Check_Socket() Can Read!" << std::endl; - } - else - { - std::cerr << "Check_Socket() Cannot Read!" << std::endl; - std::cerr << "Check_Socket() Socket Not Ready!" << std::endl; - return 0; - } - - std::cerr << "Select() Tests indicate Socket Good!" << std::endl; - std::cerr << "2) Checking with getsockopt()" << std::endl; - - int err = 1; - socklen_t optlen = 4; - if (0==getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen)) - { - std::cerr << "Check_Socket() getsockopt returned :" << err; - std::cerr << ", optlen:" << optlen; - std::cerr << std::endl; - - if (err == 0) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection Complete:"; - std::cerr << std::endl; - return 1; - } - else if (err == EINPROGRESS) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection INPROGRESS"; - std::cerr << std::endl; - return 0; - } - else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT"; - std::cerr << std::endl; - return -1; - } - else if ((err == EHOSTUNREACH) || (err == EHOSTDOWN)) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT"; - std::cerr << std::endl; - return -1; - } - else - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates Other Error: " << err; - std::cerr << std::endl; - return -1; - } - - - } - else - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " FAILED "; - std::cerr << std::endl; - return -1; - } -} - - -#else - -int Check_Socket(int fd) -{ - return 0; -} - -#endif diff --git a/libretroshare/src/tests/tcponudp/test_tou.sh b/libretroshare/src/tests/tcponudp/test_tou.sh deleted file mode 100755 index 3ae4f0896..000000000 --- a/libretroshare/src/tests/tcponudp/test_tou.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# Script to Test the udp_server code. - -EXEC=./test_tou -TMPOUTPUT=tmpoutput$$ -EXPECTEDPERIOD=10 -# launches one instance in server mode. -$EXEC 127.0.0.1 4001 127.0.0.1 4002 > $TMPOUTPUT & -#2> udp_server1.cerr & - -# launch a second in connect mode. -$EXEC -c 127.0.0.1 4002 127.0.0.1 4001 < $EXEC -# 2> udp_server2.cerr -# pipe a bunch of data through. -# make sure the data is the same. - -# print success / failure. -sleep $EXPECTEDPERIOD -killall $EXEC - -if diff -s $EXEC $TMPOUTPUT -then - echo "SUCCESS" -else - echo "FAILURE to accurately transfer DATA" -fi - -#rm udp_server1.cerr -#rm udp_server2.cerr -rm $TMPOUTPUT - - diff --git a/libretroshare/src/tests/tcponudp/timed_tou.cc b/libretroshare/src/tests/tcponudp/timed_tou.cc deleted file mode 100644 index 5c89d88e9..000000000 --- a/libretroshare/src/tests/tcponudp/timed_tou.cc +++ /dev/null @@ -1,338 +0,0 @@ -/* - * "$Id: pair_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include -#include - -// for printing sockaddr -#include "udp/udpstack.h" - -#include "tcponudp/tou.h" -#include "tcponudp/udppeer.h" -#include "tcponudp/udprelay.h" - -#include "util/bdnet.h" - -#include "util/rsrandom.h" - -#include -#include -#include - - -/* - * This test creates the same stacks as are used in RS. - * This additionally tests the "checkFns" for the other UdpReceivers, which could potentially be modifying the data. - * obviously they shouldn't! - * - */ - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - - int totalwbytes = 0; - int totalmbytes = 0; - int totalrbytes = 0; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - laddr.sin_port = htons(atoi(argv[optind+1])); - raddr.sin_port = htons(atoi(argv[optind+3])); - - std::cerr << "Local Address: " << laddr << std::endl; - std::cerr << "Remote Address: " << raddr << std::endl; - - std::cerr << "Creating with Lossy Udp Layers for further testing"; - std::cerr << std::endl; - - UdpStack *udpStack1 = new UdpStack(UDP_TEST_TIMED_LAYER,laddr); - sleep(1); - UdpStack *udpStack2 = new UdpStack(UDP_TEST_TIMED_LAYER,raddr); - - UdpSubReceiver *udpReceivers[4]; - int udpTypes[4]; - - // NOTE DHT is too hard to add at the moment. - - UdpRelayReceiver *mRelay1 = new UdpRelayReceiver(udpStack1); - udpReceivers[1] = mRelay1; - udpTypes[1] = TOU_RECEIVER_TYPE_UDPRELAY; - udpStack1->addReceiver(udpReceivers[1]); - - udpReceivers[0] = new UdpPeerReceiver(udpStack1); - udpTypes[0] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack1->addReceiver(udpReceivers[0]); - - // STACK 2. - UdpRelayReceiver *mRelay2 = new UdpRelayReceiver(udpStack2); - udpReceivers[3] = mRelay2; - udpTypes[3] = TOU_RECEIVER_TYPE_UDPRELAY; - udpStack2->addReceiver(udpReceivers[3]); - - udpReceivers[2] = new UdpPeerReceiver(udpStack2); - udpTypes[2] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack2->addReceiver(udpReceivers[2]); - - tou_init((void **) udpReceivers, udpTypes, 4); - - - int sockfd = tou_socket(0, TOU_RECEIVER_TYPE_UDPPEER, 0); - int sockfd2 = tou_socket(2, TOU_RECEIVER_TYPE_UDPPEER, 0); - if ((sockfd <= 0) || (sockfd2 <= 0)) - { - std::cerr << "Failed to open socket!: "; - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - std::cerr << "Socket Error:" << tou_errno(sockfd2) << std::endl; - return -1; - } - std::cerr << "Sockets Created: " << sockfd << " & " << sockfd2 << std::endl; - - std::cerr << "Socket Non-Blocking" << std::endl; - - std::cerr << "Socket1 Bound to: " << laddr << std::endl; - std::cerr << "Socket2 Bound to: " << raddr << std::endl; - - int err = 0; - - std::cerr << "Socket1 Connecting to: " << raddr << std::endl; - err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30); - - std::cerr << "Socket2 Connecting to: " << raddr << std::endl; - err = tou_connect(sockfd2, (struct sockaddr *) &laddr, sizeof(laddr), 30); - - while((!tou_connected(sockfd)) && (!tou_connected(sockfd2))) - { - usleep(100000); - std::cerr << "."; - } - - std::cerr << "Socket Connected" << std::endl; - -#define MAX_READ 20000 - - /* send data */ - int bufsize = MAX_READ; - char buffer[MAX_READ]; - char middata[MAX_READ]; - char data[MAX_READ]; - int readsize = 0; - int midsize = 0; - - bdnet_fcntl(0, F_SETFL, O_NONBLOCK); - bdnet_fcntl(1,F_SETFL,O_NONBLOCK); - - rstime_t lastRead = time(NULL); - bool doneWrite = false; - bool doneRead = false; - bool blockread = false; - bool blockmid = false; - - while((!doneWrite) || (!doneRead)) - { - /* read -> write_socket... */ - usleep(10); - - if (blockread != true) - { - int readbuf = 1 + RSRandom::random_u32() % (MAX_READ - 1); - readsize = read(0, buffer, readbuf); - if (readsize) - { - //std::cerr << "read " << readsize << " / " << readbuf; - //std::cerr << std::endl; - } - } - if ((readsize == 0) && (!doneWrite)) - { - /* eof */ - doneWrite = true; - std::cerr << "Write Done Total: " << totalwbytes; - std::cerr << std::endl; - } - /* now we write */ - if ((readsize > 0) && (-1 == tou_write(sockfd, buffer, readsize))) - { - //std::cerr << "Blocked Write "; - //std::cerr << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; - blockread = true; - } - else - { - blockread = false; - totalwbytes += readsize; - - if (readsize) - { - std::cerr << "Written: " << readsize << ", Total: " << totalwbytes; - std::cerr << " Total In Transit: " << totalwbytes - totalrbytes; - std::cerr << std::endl; - } - } - - /*************** Here we read it in, and send it back out... - * so the data is flowing both ways through the UDP connection - * - *****/ - - - if (!blockmid) - { - /* read from socket 2, and write back to socket 2 */ - - int readmidbuf = 1 + RSRandom::random_u32() % (MAX_READ - 1); - if (0 < (midsize = tou_read(sockfd2, middata, readmidbuf))) - { - //std::cerr << "MidRead: " << mid << " Total: " << totalrbytes; - //std::cerr << " In Transit: " << totalwbytes - totalrbytes; - //std::cerr << std::endl; - } - } - - /* now we write */ - if ((midsize > 0) && (-1 == tou_write(sockfd2, middata, midsize))) - { - //std::cerr << "Blocked Write "; - //std::cerr << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; - blockmid = true; - } - else - { - blockmid = false; - - if (midsize > 0) - { - totalmbytes += midsize; - - std::cerr << "MidRead: " << midsize << ", Total: " << totalmbytes; - std::cerr << " => Transit => : " << totalwbytes - totalmbytes; - std::cerr << " <= Transit <= : " << totalmbytes - totalrbytes; - std::cerr << std::endl; - } - } - - /***** READ FROM FIRST SOCKET *****/ - - int ret = 0; - int readbuf2 = 1 + RSRandom::random_u32() % (MAX_READ - 1); - if (0 < (ret = tou_read(sockfd, data, readbuf2))) - { - //std::cerr << "TF(" << ret << ")" << std::endl; - write(1, data, ret); - totalrbytes += ret; - - std::cerr << "Read: " << ret << " Total: " << totalrbytes; - std::cerr << " Total In Transit: " << totalwbytes - totalrbytes; - std::cerr << std::endl; - - lastRead = time(NULL); - } - else if ((ret == 0) && (!doneRead)) - { - doneRead = true; - std::cerr << "Read Done Total: " << totalrbytes; - std::cerr << std::endl; - } - else - { - //std::cerr << "Blocked Read: " << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; -#define TIMEOUT 15 - if ((!doneRead) && (time(NULL) - lastRead > TIMEOUT)) - { - doneRead = true; - std::cerr << "TIMEOUT: Read Done Total: " << totalrbytes; - std::cerr << std::endl; - } - } - - - } - - /* this is blocking??? */ - tou_close(sockfd); - tou_close(sockfd2); - - std::cerr << "Transfer Complete: " << totalwbytes << " bytes"; - std::cerr << std::endl; - return 1; -} - diff --git a/libretroshare/src/tests/tcponudp/timed_tou.sh b/libretroshare/src/tests/tcponudp/timed_tou.sh deleted file mode 100755 index 4d2f7816c..000000000 --- a/libretroshare/src/tests/tcponudp/timed_tou.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -# Script to Test the udp_server code. - -EXEC=./timed_tou -DATAFILE=./timed_tou - -TMPOUTPUT=tmpoutput$$ -EXPECTEDPERIOD=10 - -$EXEC 127.0.0.1 4401 127.0.0.1 4032 < $DATAFILE > $TMPOUTPUT - -if diff -s $DATAFILE $TMPOUTPUT -then - echo "SUCCESS" -else - echo "FAILURE to accurately transfer DATA" -fi - -rm $TMPOUTPUT - diff --git a/libretroshare/src/tests/tcponudp/udp_server.cc b/libretroshare/src/tests/tcponudp/udp_server.cc deleted file mode 100644 index 1f720561a..000000000 --- a/libretroshare/src/tests/tcponudp/udp_server.cc +++ /dev/null @@ -1,285 +0,0 @@ -/* - * "$Id: udp_server.cc,v 1.4 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include "udp/udpstack.h" -#include "tcponudp/udppeer.h" -#include "tcponudp/tcpstream.h" -#include "tcponudp/tou.h" - -#include - -#include -#include -#include - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - - while(-1 != (c = getopt(argc, argv, "f:pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - case 'f': - /* this can only work when the define below exists in tcpstream */ -#ifdef DEBUG_TCP_STREAM_EXTRA - setupBinaryCheck(std::string(optarg)); -#else - std::cerr << "Binary Check no Enabled!" << std::endl; -#endif - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - /* setup the local/remote addresses. - */ - - - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - laddr.sin_port = htons(atoi(argv[optind+1])); - raddr.sin_port = htons(atoi(argv[optind+3])); - - std::cerr << "Local Address: " << laddr << std::endl; - std::cerr << "Remote Address: " << raddr << std::endl; - - UdpStack udps(laddr); - UdpPeerReceiver *upr = new UdpPeerReceiver(&udps); - udps.addReceiver(upr); - - if (!udps.okay()) - { - std::cerr << "UdpSorter not Okay (Cannot Open Local Address): " << laddr << std::endl; - exit(1); - } - - TcpStream tcp(upr); - upr->addUdpPeer(&tcp, raddr); - - if (toConnect) - { - tcp.connect(raddr, 30); - } - else - { - tcp.listenfor(raddr); - } - - while(!tcp.isConnected()) - { - sleep(1); - std::cerr << "Waiting for TCP to Connect!" << std::endl; - udps.status(std::cerr); - tcp.status(std::cerr); - tcp.tick(); - } - std::cerr << "TCP Connected***************************" << std::endl; - udps.status(std::cerr); - tcp.status(std::cerr); - std::cerr << "TCP Connected***************************" << std::endl; - - int count = 1; - - if (toConnect) - { - /* send data */ - int bufsize = 51; - char buffer[bufsize]; - int readsize = 0; - - bdnet_fcntl(0, F_SETFL, O_NONBLOCK); - - bool done = false; - bool blockread = false; - while(!done) - { - //sleep(1); - //usleep(100000); - usleep(1000); - if (blockread != true) - { - readsize = read(0, buffer, bufsize); - } - if (readsize == 0) - { - /* eof */ - done = true; - } - else if ((readsize == -1) && ( EAGAIN == errno )) - { - continue; - } - - /* now we write */ - if (-1 == tcp.write(buffer, readsize)) - blockread = true; - else - blockread = false; - - - tcp.tick(); - if (count++ % 10 == 0) - { - std::cerr << "******************************************" << std::endl; - tcp.status(std::cerr); - } - } - - tcp.closeWrite(); - - while(!tcp.widle()) - { - //sleep(1); - usleep(100000); - //usleep(1000); - tcp.tick(); - if (count++ % 10 == 0) - { - std::cerr << "Waiting for Idle()" << std::endl; - std::cerr << "******************************************" << std::endl; - tcp.status(std::cerr); - } - } - - std::cerr << "Transfer Complete: " << tcp.wbytes() << " bytes"; - std::cerr << std::endl; - return 1; - } - - /* recv data */ - int bufsize = 1523; - char data[bufsize]; - bdnet_fcntl(1,F_SETFL,O_NONBLOCK); - while(1) - { - //sleep(1); - usleep(100000); - //usleep(1000); - //int writesize = bufsize; - int ret; - if (0 < (ret = tcp.read(data, bufsize))) - { - std::cerr << "TF(" << ret << ")" << std::endl; - write(1, data, ret); - } - else if (ret == 0) - { - /* completed transfer */ - std::cerr << "Transfer complete :" << tcp.rbytes(); - std::cerr << " bytes" << std::endl; - break; - } - - tcp.tick(); - if (count++ % 10 == 0) - { - std::cerr << "******************************************" << std::endl; - tcp.status(std::cerr); - } - if ((!stayOpen) && tcp.ridle()) - { - std::cerr << "Transfer Idle after " << tcp.rbytes(); - std::cerr << " bytes" << std::endl; - close(1); - break; - } - } - - tcp.closeWrite(); - - /* tick for a bit */ - while((stayOpen) || (!tcp.ridle())) - { - tcp.tick(); - //sleep(1); - usleep(100000); - //usleep(1000); - if (count++ % 10 == 0) - { - std::cerr << "Waiting for Idle()" << std::endl; - std::cerr << "******************************************" << std::endl; - tcp.status(std::cerr); - } - } - - - if ((!stayOpen) && tcp.ridle()) - { - //std::cerr << "Transfer complete :" << tcp.rbytes(); - //std::cerr << " bytes" << std::endl; - close(1); - return 1; - } - - return 1; -} - - - - diff --git a/libretroshare/src/tests/tcponudp/udp_server.sh b/libretroshare/src/tests/tcponudp/udp_server.sh deleted file mode 100755 index 8bbd55887..000000000 --- a/libretroshare/src/tests/tcponudp/udp_server.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# Script to Test the udp_server code. - -EXEC=./udp_server -TMPOUTPUT=tmpoutput$$ -EXPECTEDPERIOD=10 -# launches one instance in server mode. -$EXEC 127.0.0.1 4001 127.0.0.1 4002 > $TMPOUTPUT & -#2> udp_server1.cerr & - -# launch a second in connect mode. -$EXEC -c 127.0.0.1 4002 127.0.0.1 4001 < $EXEC -# 2> udp_server2.cerr -# pipe a bunch of data through. -# make sure the data is the same. - -# print success / failure. -sleep $EXPECTEDPERIOD -killall $EXEC - -if diff -s $EXEC $TMPOUTPUT -then - echo "SUCCESS" -else - echo "FAILURE to accurately transfer DATA" -fi - -#rm udp_server1.cerr -#rm udp_server2.cerr -rm $TMPOUTPUT - - diff --git a/libretroshare/src/tests/tcponudp/udpsock_test.cc b/libretroshare/src/tests/tcponudp/udpsock_test.cc deleted file mode 100644 index bc9aeaf86..000000000 --- a/libretroshare/src/tests/tcponudp/udpsock_test.cc +++ /dev/null @@ -1,92 +0,0 @@ -/* - * libretroshare/src/tcponudp: udpsock_test.cc - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "udptestfn.h" -#include "udp/udplayer.h" -#include - -#define MAX_PEERS 16 - -int main(int argc, char **argv) -{ - /* get local and remote addresses */ - struct sockaddr_in local; - struct sockaddr_in peers[MAX_PEERS]; - int numpeers = 0; - int i,j; - - local.sin_family = AF_INET; - inet_aton("127.0.0.1", &(local.sin_addr)); - local.sin_port = htons(8767); - - for(i = 0; i < MAX_PEERS; i++) - { - peers[i].sin_family = AF_INET; - inet_aton("127.0.0.1", &(peers[i].sin_addr)); - peers[i].sin_port = htons(8768); - } - - if (argc < 3) - { - std::cerr << "Usage: " << argv[0] << " [ udp_server1.cerr & - -$EXEC 6002 6001 6003 6004 6005 & -$EXEC 6003 6002 6001 6004 6005 & -$EXEC 6004 6002 6003 6001 6005 & -$EXEC 6005 6002 6003 6004 6001 & - -## print success / failure. -sleep $EXPECTEDPERIOD -killall $EXEC - -# -#if diff -s $EXEC $TMPOUTPUT -#then -# echo "SUCCESS" -#else -# echo "FAILURE to accurately transfer DATA" -#fi -# -##rm udp_server1.cerr -##rm udp_server2.cerr -#rm $TMPOUTPUT -## -### diff --git a/libretroshare/src/tests/tcponudp/udpsort_test.cc b/libretroshare/src/tests/tcponudp/udpsort_test.cc deleted file mode 100644 index a4d025a2a..000000000 --- a/libretroshare/src/tests/tcponudp/udpsort_test.cc +++ /dev/null @@ -1,94 +0,0 @@ -/* - * libretroshare/src/tcponudp: udpsort_test.cc - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "udptestfn.h" -#include "udp/udpstack.h" -#include "tcponudp/udppeer.h" - -#define MAX_PEERS 16 - -int main(int argc, char **argv) -{ - /* get local and remote addresses */ - struct sockaddr_in local; - struct sockaddr_in peers[MAX_PEERS]; - int numpeers = 0; - int i,j; - - local.sin_family = AF_INET; - inet_aton("127.0.0.1", &(local.sin_addr)); - local.sin_port = htons(8767); - - for(i = 0; i < MAX_PEERS; i++) - { - peers[i].sin_family = AF_INET; - inet_aton("127.0.0.1", &(peers[i].sin_addr)); - peers[i].sin_port = htons(8768); - } - - if (argc < 3) - { - std::cerr << "Usage: " << argv[0] << " [addUdpPeer(pt, peers[i-2]); - } - - int size = 12; - void *data = malloc(size); - int ttl = 64; - - /* push packets to the peer */ - for(i = 0; i < 60; i++) - { - sleep(1); - for(j = 0; j < numpeers; j++) - { - udps.sendPkt(data, size, peers[j], ttl); - } - } - return 1; -} - - - diff --git a/libretroshare/src/tests/tcponudp/udpsort_test.sh b/libretroshare/src/tests/tcponudp/udpsort_test.sh deleted file mode 100755 index c6023e93b..000000000 --- a/libretroshare/src/tests/tcponudp/udpsort_test.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -# Script to Test the udp_server code. - -EXEC=./udpsort_test -TMPOUTPUT=tmpoutput$$ -EXPECTEDPERIOD=10 -$EXEC 6001 6002 6003 6004 6005 & -#2> udp_server1.cerr & - -$EXEC 6002 6001 6003 6004 6005 & -$EXEC 6003 6002 6001 6004 6005 & -$EXEC 6004 6002 6003 6001 6005 & -$EXEC 6005 6002 6003 6004 6001 & - -## print success / failure. -sleep $EXPECTEDPERIOD -killall $EXEC - -# -#if diff -s $EXEC $TMPOUTPUT -#then -# echo "SUCCESS" -#else -# echo "FAILURE to accurately transfer DATA" -#fi -# -##rm udp_server1.cerr -##rm udp_server2.cerr -#rm $TMPOUTPUT -## -### diff --git a/libretroshare/src/tests/tcponudp/udptestfn.cc b/libretroshare/src/tests/tcponudp/udptestfn.cc deleted file mode 100644 index 12c7bd264..000000000 --- a/libretroshare/src/tests/tcponudp/udptestfn.cc +++ /dev/null @@ -1,49 +0,0 @@ -/* - * libretroshare/src/tcponudp: udptestfn.cc - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "udptestfn.h" - -int UdpRecvTest::recvPkt(void *data, int size, struct sockaddr_in &from) -{ - /* print packet information */ - std::cerr << "UdpRecvTest::recvPkt(" << size << ") from: " << from; - std::cerr << std::endl; - return -1; -} - -UdpPeerTest::UdpPeerTest(struct sockaddr_in &addr) - :raddr(addr) -{ - return; -} - -void UdpPeerTest::recvPkt(void *data, int size) -{ - /* print packet information */ - std::cerr << "UdpPeerTest::recvPkt(" << size << ") from: " << raddr; - std::cerr << std::endl; -} - - diff --git a/libretroshare/src/tests/tcponudp/udptestfn.h b/libretroshare/src/tests/tcponudp/udptestfn.h deleted file mode 100644 index d25a23223..000000000 --- a/libretroshare/src/tests/tcponudp/udptestfn.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * libretroshare/src/tcponudp: udptestfn.h - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "udp/udplayer.h" -#include "udp/udpstack.h" -#include "tcponudp/udppeer.h" - -//#include "udpsorter.h" - -#ifndef TOU_UDP_TEST_FN_H -#define TOU_UDP_TEST_FN_H - -class UdpRecvTest: public UdpReceiver -{ - public: -virtual int recvPkt(void *data, int size, struct sockaddr_in &from); -virtual int status(std::ostream&) { return 0; } -}; - - -class UdpPeerTest: public UdpPeer -{ - public: - UdpPeerTest(struct sockaddr_in &addr); -virtual void recvPkt(void *data, int size); - - struct sockaddr_in raddr; -}; - - -#endif diff --git a/libretroshare/src/tests/upnp/upnpforward.cc b/libretroshare/src/tests/upnp/upnpforward.cc deleted file mode 100644 index 50394d3f1..000000000 --- a/libretroshare/src/tests/upnp/upnpforward.cc +++ /dev/null @@ -1,114 +0,0 @@ -/* - * libretroshare/src/upnp: upnpforward.cc - * - * Upnp Manual Test for RetroShare. - * - * Copyright 2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * A Upnp utility to forward a port, specified on the commandline. - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include "util/utest.h" -#include "upnp/upnphandler_linux.h" - -INITTEST() ; - -#include - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-i ] [-e ]"; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint16_t internalPort = 7812; - uint16_t externalPort = 7812; - -#ifdef PTW32_STATIC_LIB - pthread_win32_process_attach_np(); -#endif - -#ifdef WIN32 - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif - - - while(-1 != (c = getopt(argc, argv, "i:e:"))) - { - switch (c) - { - case 'i': - internalPort = atoi(optarg); - break; - case 'e': - externalPort = atoi(optarg); - break; - default: - usage(argv[0]); - break; - } - } - - - /* create a upnphandler object */ - //pqiNetAssistFirewall *upnp; - upnphandler *upnp; - - upnp = new upnphandler(); - - /* setup */ - upnp->setInternalPort(internalPort); - upnp->setExternalPort(externalPort); - - /* launch thread */ - upnp->enable(true); - - /* give it a chance to work its magic. */ - sleep(30); - - FINALREPORT("upnpforward") ; - return TESTRESULT(); -} - - - diff --git a/libretroshare/src/tests/util/aes_test.cc b/libretroshare/src/tests/util/aes_test.cc deleted file mode 100644 index cb0d00447..000000000 --- a/libretroshare/src/tests/util/aes_test.cc +++ /dev/null @@ -1,115 +0,0 @@ - -/* - * "$Id: dirtest.cc,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" - * - * RetroShare C++ Interface. - * - * Copyright 2012-2012 by Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - -#include "util/rsaes.h" -#include "util/utest.h" -#include - -#include -#include -#include -#include - -void printHelp(int argc,char *argv[]) -{ - std::cerr << argv[0] << ": tests AES encryption/decryption functions." << std::endl; - std::cerr << "Usage: " << argv[0] << std::endl ; -} - -void printHex(unsigned char *data,uint32_t length) -{ - static const char outh[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ; - static const char outl[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' } ; - - for(uint32_t j = 0; j < length; j++) - { - std::cerr << outh[ (data[j]>>4) ] ; - std::cerr << outh[ data[j] & 0xf ] ; - } -} - - -INITTEST() ; - -int main(int argc,char *argv[]) -{ - std::string inputfile ; - argstream as(argc,argv) ; - - as >> help() ; - - as.defaultErrorHandling() ; - - std::cerr << "Testing AES crypt" << std::endl; - - std::string source_string = "This is a very secret string, but ultimately it will always be decyphered" ; - std::cerr << "Input string: length=" << source_string.length() << ", s=\"" << source_string << "\"" << std::endl; - - unsigned char key_data[16] ; - unsigned char salt[8] ; - - for(int i=0;i<16;++i) - key_data[i] = lrand48() & 0xff ; - - std::cerr << "Key: " ; printHex(key_data,16); - std::cerr << std::endl; - - for(int i=5;i - -#include -#include "util/rscompress.h" -#include "util/rsdir.h" -#include "util/utest.h" -#include "util/argstream.h" - -#include -#include -#include -#include - -void printHelp(int argc,char *argv[]) -{ - std::cerr << argv[0] << ": tests AES encryption/decryption functions." << std::endl; - std::cerr << "Usage: " << argv[0] << std::endl ; -} - -bool compareStrings(const std::string& s1,const std::string& s2) -{ - uint32_t L = std::min(s1.length(),s2.length()) ; - - for(int i=0;i>4) ] ; - std::cerr << outh[ data[j] & 0xf ] ; - } -} - -INITTEST() ; - -int main(int argc,char *argv[]) -{ - std::string inputfile ; - argstream as(argc,argv) ; - - as >> help() ; - - as.defaultErrorHandling() ; - - std::cerr << "Testing RsCompress" << std::endl; - - std::string source_string = "This is a very secret string, but ultimately it will always be decyphered \ - ar cqs libretroshare.a temp/linux-g++-64/obj/p3bitdht.o \ - temp/linux-g++-64/obj/p3bitdht_interface.o \ - temp/linux-g++-64/obj/p3bitdht_peers.o \ - temp/linux-g++-64/obj/p3bitdht_peernet.o \ - temp/linux-g++-64/obj/p3bitdht_relay.o \ - temp/linux-g++-64/obj/connectstatebox.o temp/linux-g++-64/obj/udppeer.o \ - temp/linux-g++-64/obj/tcppacket.o temp/linux-g++-64/obj/tcpstream.o \ - temp/linux-g++-64/obj/tou.o temp/linux-g++-64/obj/bss_tou.o \ - temp/linux-g++-64/obj/udpstunner.o temp/linux-g++-64/obj/udprelay.o \ - temp/linux-g++-64/obj/cachestrapper.o temp/linux-g++-64/obj/fimonitor.o \ - temp/linux-g++-64/obj/findex.o temp/linux-g++-64/obj/fistore.o \ - temp/linux-g++-64/obj/rsexpr.o temp/linux-g++-64/obj/ftchunkmap.o \ - temp/linux-g++-64/obj/ftcontroller.o \ - temp/linux-g++-64/obj/ftdatamultiplex.o temp/linux-g++-64/obj/ftdbase.o \ - temp/linux-g++-64/obj/ftextralist.o temp/linux-g++-64/obj/ftfilecreator.o \ - temp/linux-g++-64/obj/ftfileprovider.o \ - temp/linux-g++-64/obj/ftfilesearch.o temp/linux-g++-64/obj/ftserver.o \ - temp/linux-g++-64/obj/fttransfermodule.o \ - temp/linux-g++-64/obj/ftturtlefiletransferitem.o \ - temp/linux-g++-64/obj/authgpg.o temp/linux-g++-64/obj/authssl.o \ - temp/linux-g++-64/obj/pgphandler.o temp/linux-g++-64/obj/pgpkeyutil.o \ - temp/linux-g++-64/obj/rscertificate.o temp/linux-g++-64/obj/p3cfgmgr.o \ - temp/linux-g++-64/obj/p3peermgr.o temp/linux-g++-64/obj/p3linkmgr.o \ - temp/linux-g++-64/obj/p3netmgr.o temp/linux-g++-64/obj/p3notify.o \ - temp/linux-g++-64/obj/pqiqos.o temp/linux-g++-64/obj/pqiarchive.o \ - temp/linux-g++-64/obj/pqibin.o temp/linux-g++-64/obj/pqihandler.o \ - temp/linux-g++-64/obj/p3historymgr.o temp/linux-g++-64/obj/pqiipset.o \ - temp/linux-g++-64/obj/pqiloopback.o temp/linux-g++-64/obj/pqimonitor.o \ - temp/linux-g++-64/obj/pqinetwork.o temp/linux-g++-64/obj/pqiperson.o \ - temp/linux-g++-64/obj/pqipersongrp.o temp/linux-g++-64/obj/pqisecurity.o \ - temp/linux-g++-64/obj/pqiservice.o temp/linux-g++-64/obj/pqissl.o \ - temp/linux-g++-64/obj/pqissllistener.o \ - temp/linux-g++-64/obj/pqisslpersongrp.o temp/linux-g++-64/obj/pqissludp.o \ - temp/linux-g++-64/obj/pqisslproxy.o temp/linux-g++-64/obj/pqistore.o \ - temp/linux-g++-64/obj/pqistreamer.o \ - temp/linux-g++-64/obj/pqithreadstreamer.o \ - temp/linux-g++-64/obj/pqiqosstreamer.o temp/linux-g++-64/obj/sslfns.o \ - temp/linux-g++-64/obj/pqinetstatebox.o \ - temp/linux-g++-64/obj/p3face-config.o temp/linux-g++-64/obj/p3face-msgs.o \ - temp/linux-g++-64/obj/p3face-server.o temp/linux-g++-64/obj/p3history.o \ - temp/linux-g++-64/obj/p3msgs.o temp/linux-g++-64/obj/p3peers.o \ - temp/linux-g++-64/obj/p3status.o temp/linux-g++-64/obj/rsinit.o \ - temp/linux-g++-64/obj/rsloginhandler.o temp/linux-g++-64/obj/rstypes.o \ - temp/linux-g++-64/obj/p3serverconfig.o \ - temp/linux-g++-64/obj/pluginmanager.o temp/linux-g++-64/obj/dlfcn_win32.o \ - temp/linux-g++-64/obj/rspluginitems.o \ - temp/linux-g++-64/obj/rsbaseserial.o \ - temp/linux-g++-64/obj/rsfiletransferitems.o \ - temp/linux-g++-64/obj/rsserviceserialiser.o \ - temp/linux-g++-64/obj/rsconfigitems.o \ - temp/linux-g++-64/obj/rshistoryitems.o temp/linux-g++-64/obj/rsmsgitems.o \ - temp/linux-g++-64/obj/rsserial.o temp/linux-g++-64/obj/rsstatusitems.o \ - temp/linux-g++-64/obj/rstlvaddrs.o temp/linux-g++-64/obj/rstlvbase.o \ - temp/linux-g++-64/obj/rstlvfileitem.o temp/linux-g++-64/obj/rstlvimage.o \ - temp/linux-g++-64/obj/rstlvkeys.o temp/linux-g++-64/obj/rstlvkvwide.o \ - temp/linux-g++-64/obj/rstlvtypes.o temp/linux-g++-64/obj/rstlvutil.o \ - temp/linux-g++-64/obj/rstlvdsdv.o temp/linux-g++-64/obj/rsdsdvitems.o \ - temp/linux-g++-64/obj/rstlvbanlist.o \ - temp/linux-g++-64/obj/rsbanlistitems.o \ - temp/linux-g++-64/obj/rsbwctrlitems.o \ - temp/linux-g++-64/obj/rsdiscovery2items.o \ - temp/linux-g++-64/obj/rsheartbeatitems.o \ - temp/linux-g++-64/obj/rsrttitems.o temp/linux-g++-64/obj/p3chatservice.o \ - temp/linux-g++-64/obj/p3msgservice.o temp/linux-g++-64/obj/p3service.o \ - temp/linux-g++-64/obj/p3statusservice.o temp/linux-g++-64/obj/p3dsdv.o \ - temp/linux-g++-64/obj/p3banlist.o temp/linux-g++-64/obj/p3bwctrl.o \ - temp/linux-g++-64/obj/p3discovery2.o temp/linux-g++-64/obj/p3heartbeat.o \ - temp/linux-g++-64/obj/p3rtt.o temp/linux-g++-64/obj/p3turtle.o \ - temp/linux-g++-64/obj/rsturtleitem.o \ - temp/linux-g++-64/obj/folderiterator.o temp/linux-g++-64/obj/rsdebug.o \ - temp/linux-g++-64/obj/rscompress.o temp/linux-g++-64/obj/smallobject.o \ - temp/linux-g++-64/obj/rsdir.o temp/linux-g++-64/obj/rsdiscspace.o \ - temp/linux-g++-64/obj/rsnet.o temp/linux-g++-64/obj/rsnet_ss.o \ - temp/linux-g++-64/obj/extaddrfinder.o temp/linux-g++-64/obj/dnsresolver.o \ - temp/linux-g++-64/obj/rsprint.o temp/linux-g++-64/obj/rsstring.o \ - temp/linux-g++-64/obj/rsthreads.o temp/linux-g++-64/obj/rsversion.o \ - temp/linux-g++-64/obj/rswin.o temp/linux-g++-64/obj/rsaes.o \ - temp/linux-g++-64/obj/rsrandom.o temp/linux-g++-64/obj/rstickevent.o \ - temp/linux-g++-64/obj/UPnPBase.o \ - temp/linux-g++-64/obj/upnphandler_linux.o \ - temp/linux-g++-64/obj/rsnxsitems.o temp/linux-g++-64/obj/rsdataservice.o \ - temp/linux-g++-64/obj/rsgenexchange.o \ - temp/linux-g++-64/obj/rsgxsnetservice.o temp/linux-g++-64/obj/rsgxsdata.o \ - temp/linux-g++-64/obj/rsgxsitems.o \ - temp/linux-g++-64/obj/rsgxsdataaccess.o temp/linux-g++-64/obj/retrodb.o \ - temp/linux-g++-64/obj/contentvalue.o temp/linux-g++-64/obj/rsdbbind.o \ - temp/linux-g++-64/obj/gxssecurity.o temp/linux-g++-64/obj/gxstokenqueue.o \ - temp/linux-g++-64/obj/rsgxsnetutils.o temp/linux-g++-64/obj/rsgxsutil.o \ - temp/linux-g++-64/obj/p3idservice.o temp/linux-g++-64/obj/rsgxsiditems.o \ - temp/linux-g++-64/obj/p3gxscircles.o \ - temp/linux-g++-64/obj/rsgxscircleitems.o \ - temp/linux-g++-64/obj/p3gxsforums.o \ - temp/linux-g++-64/obj/rsgxsforumitems.o \ - temp/linux-g++-64/obj/p3gxschannels.o temp/linux-g++-64/obj/p3gxscommon.o \ - temp/linux-g++-64/obj/rsgxscommentitems.o \ - temp/linux-g++-64/obj/rsgxschannelitems.o temp/linux-g++-64/obj/p3wiki.o \ - temp/linux-g++-64/obj/rswikiitems.o temp/linux-g++-64/obj/p3wire.o \ - temp/linux-g++-64/obj/rswireitems.o temp/linux-g++-64/obj/p3posted.o \ - temp/linux-g++-64/obj/rsposteditems.o \ - temp/linux-g++-64/obj/p3photoservice.o \ - temp/linux-g++-64/obj/rsphotoitems.o" ; - - for(int i=0;i<5;++i) - source_string = source_string+source_string ; - - source_string = source_string.substr(0,550000) ; - - for(int i=0;i - -int processpath(std::string path); - -int main() -{ - - std::string path1 = "/home/tst1//test2///test3/"; - std::string path2 = "home2/tst4//test5///test6"; - std::string path3 = "//home3"; - std::string path4 = "//"; - std::string path5 = "/a/b/c/d/"; - std::string path6 = "a//b/c//d"; - - processpath(path1); - processpath(path2); - processpath(path3); - processpath(path4); - processpath(path5); - processpath(path6); - - return 1; -} - - -int processpath(std::string path) -{ - std::string pathtogo = path; - while(pathtogo != "") - { - std::string basedir = RsDirUtil::getRootDir(pathtogo); - std::string rempath = RsDirUtil::removeRootDir(pathtogo); - std::string topdir = RsDirUtil::getTopDir(pathtogo); - std::string remtoppath = RsDirUtil::removeTopDir(pathtogo); - - std::cerr << "Processing: \"" << pathtogo << "\"" << std::endl; - std::cerr << "\tRootDir : \"" << basedir << "\"" << std::endl; - std::cerr << "\tRemaining: \"" << rempath << "\"" << std::endl; - std::cerr << "\tTopDir : \"" << topdir << "\"" << std::endl; - std::cerr << "\tRemaining(Top): \"" << remtoppath << "\"" << std::endl; - std::cerr << std::endl; - - pathtogo = rempath; - } - return 1; -} - - - - - diff --git a/libretroshare/src/tests/util/dirtest.cc b/libretroshare/src/tests/util/dirtest.cc deleted file mode 100644 index 862a77913..000000000 --- a/libretroshare/src/tests/util/dirtest.cc +++ /dev/null @@ -1,107 +0,0 @@ - -/* - * "$Id: dirtest.cc,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" - * - * RetroShare C++ Interface. - * - * Copyright 2004-2007 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - -#include "util/rsdir.h" -#include "util/utest.h" - -#include -#include -#include - -bool testRsDirUtils(std::string path); - -INITTEST() ; - -int main() -{ - - std::list dirs; - std::list::iterator it; - dirs.push_back("/incoming/htuyr/file.txt"); - dirs.push_back("/incoming/htuyr/file.txt "); - dirs.push_back("/incoming/htuyr/file.txt/"); - dirs.push_back("/incoming/htuyr/file.txt//"); - dirs.push_back("/incoming/htuyr//file.txt//"); - dirs.push_back("/incoming/htuyr//file .txt"); - dirs.push_back("/incoming/htuyr/Q"); - dirs.push_back("/incoming/htuyr/Q//"); - dirs.push_back("/incoming/htuyr/Q/"); - dirs.push_back("/incoming/htuyr/Q/text"); - dirs.push_back("/home/tst1//test2///test3/"); - dirs.push_back("home2/tst4//test5///test6"); - dirs.push_back("//home3"); - dirs.push_back("//"); - dirs.push_back("A"); - dirs.push_back("ABC"); - dirs.push_back("////ABC////"); - dirs.push_back("A/B/C"); - - for(it = dirs.begin(); it != dirs.end(); it++) - { - testRsDirUtils(*it); - } - - FINALREPORT("dirtest"); - - return TESTRESULT() ; -} - -bool testRsDirUtils(std::string path) -{ - - std::cerr << "RsUtilTest input: [" << path << "]"; - std::cerr << std::endl; - - std::string top = RsDirUtil::getTopDir(path); - std::string root = RsDirUtil::getRootDir(path); - std::string topdirs = RsDirUtil::removeRootDir(path); - std::string topdirs2 = RsDirUtil::removeRootDirs(path, root); - std::string restdirs ; - RsDirUtil::removeTopDir(path,restdirs); - std::list split; - std::list::iterator it; - RsDirUtil::breakupDirList(path, split); - - std::cerr << "\tTop: [" << top << "]"; - std::cerr << std::endl; - std::cerr << "\tRest: [" << restdirs << "]"; - std::cerr << std::endl; - - std::cerr << "\tRoot: [" << root << "]"; - std::cerr << std::endl; - std::cerr << "\tRemoveRoot: [" << topdirs << "]"; - std::cerr << std::endl; - std::cerr << "\tSplit Up "; - for(it = split.begin(); it != split.end(); it++) - { - std::cerr << ":" << (*it); - } - std::cerr << std::endl; - std::cerr << std::endl; - return true; -} diff --git a/libretroshare/src/tests/util/sha1_test.cc b/libretroshare/src/tests/util/sha1_test.cc deleted file mode 100644 index 84481aec5..000000000 --- a/libretroshare/src/tests/util/sha1_test.cc +++ /dev/null @@ -1,104 +0,0 @@ - -/* - * "$Id: dirtest.cc,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" - * - * RetroShare C++ Interface. - * - * Copyright 2012-2012 by Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - -#include "util/rsdir.h" -#include "util/utest.h" -#include - -#include -#include -#include -#include - -void printHelp(int argc,char *argv[]) -{ - std::cerr << argv[0] << ": test RS sha1sum class implementation." << std::endl; - std::cerr << "Usage: " << argv[0] << " [test file]" << std::endl ; -} - -INITTEST() ; - -int main(int argc,char *argv[]) -{ - std::string inputfile ; - argstream as(argc,argv) ; - - as >> parameter('i',"input",inputfile,"input file name to hash",false) - >> help() ; - - as.defaultErrorHandling() ; - - if(inputfile.empty()) - inputfile = argv[0] ; - - FILE *f = RsDirUtil::rs_fopen(inputfile.c_str(),"r") ; - - CHECK(f != NULL) ; - - std::cerr << "Testing sha1" << std::endl; - uint32_t SIZE = 1024*1024 ; - unsigned char *buf = new unsigned char[SIZE] ; - int len = fread(buf,1,SIZE,f) ; - - std::cerr << "Read " << len << " bytes" << std::endl; - - Sha1CheckSum sum = RsDirUtil::sha1sum(buf,len) ; - { - std::cerr << std::hex << sum.fourbytes[0] << std::endl; - std::cerr << "New method : " << sum.toStdString() << std::endl; - } - - std::string hash ; - uint64_t size ; - RsDirUtil::getFileHash(inputfile.c_str(),hash,size) ; - - std::cerr << "Old method : " << hash << std::endl; - CHECK(hash == sum.toStdString()) ; - - Sha1CheckSum H(hash) ; - std::cerr << "Hashed transformed: " << H.toStdString() << std::endl; - CHECK(hash == H.toStdString()) ; - - std::cerr << "Computing all chunk hashes:" << std::endl; - - fseek(f,0,SEEK_SET) ; - int n=0 ; - - while(len = fread(buf,1,SIZE,f)) - { - Sha1CheckSum sum = RsDirUtil::sha1sum(buf,len) ; - std::cerr << "Chunk " << n << ": " << sum.toStdString() << std::endl; - n++; - } - - fclose(f) ; - - FINALREPORT("Sha1Test") ; - return TESTRESULT() ; -} - diff --git a/libretroshare/src/tests/util/test_fifo.cpp b/libretroshare/src/tests/util/test_fifo.cpp deleted file mode 100644 index 822117e5d..000000000 --- a/libretroshare/src/tests/util/test_fifo.cpp +++ /dev/null @@ -1,138 +0,0 @@ -// COMPILE_LINE: g++ test_fifo.cpp -o test_fifo -lstdc++ -I.. -// -// This is a test program for fifo previewing of files. -// Usage: -// test_fifo -i [movie file] -// -// The program creates a named pipe /tmp/fifo.avi on Linux, \\.\pipe\fifo.avi on Windows to be played with e.g. mplayer -// On Windows the mplayer needs the argument -noidx, because the pipe is not seekable -// -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#endif - -#ifdef WIN32 -#define myFIFO TEXT("\\\\.\\pipe\\fifo.avi") -#else -#define myFIFO "/tmp/fifo.avi" -#endif - -int main(int argc,char *argv[]) -{ - try - { - std::string movie_name ; - - argstream as(argc,argv) ; - - as >> parameter('i',"input",movie_name,"file name of the movie to preview",true) - >> help() ; - - as.defaultErrorHandling() ; - - -#ifdef WIN32 - HANDLE fifo = CreateNamedPipe(myFIFO, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE | PIPE_WAIT , 2, 1024, 1024, 2000, NULL); -#else - int status, num, fifo; - umask(0); - if (mkfifo(myFIFO, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) - throw std::runtime_error("Cannot create fifo") ; - - fifo = open(myFIFO, O_WRONLY); - - std::cerr << "Opening fifo = " << fifo << " with file name " << myFIFO << std::endl; -#endif - -#ifdef WIN32 - if(fifo == INVALID_HANDLE_VALUE) -#else - if(fifo < 0) -#endif - { - printf("\nCan't open fifo: %s \n", strerror(errno)); - return 0; - } - -#ifdef WIN32 - printf("pipe=%p\n", fifo); - - printf("connect...\n"); - bool connected = ConnectNamedPipe(fifo, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); - if (!connected) { - printf("ConnectNamedPipe failed. error=%ld\n", GetLastError()); - return -1; - } - printf("...connected\n"); -#endif - - static const int SIZE = 1024*1024 ; // 1 MB - - void *membuf = malloc(SIZE) ; - FILE *f = fopen(movie_name.c_str(),"rb") ; - int chunk = 0; - - if(f == NULL) - throw std::runtime_error("Cannot open movie to stream into fifo") ; - - while(true) - { - int n = fread(membuf, 1, SIZE, f) ; - - if(n == 0) - break ; - -#ifdef WIN32 - DWORD dwNumberOfBytesWritten; - if (!WriteFile(fifo, membuf, n, &dwNumberOfBytesWritten, NULL) || dwNumberOfBytesWritten != (DWORD) n) { - printf("WriteFile failed. error=%ld\n", GetLastError()); -#else - if(write(fifo,membuf,SIZE) != n) { -#endif - throw std::runtime_error("Could not write chunk to fifo") ; - } - - std::cerr << "Streamed chunk " << chunk << std::endl; - if(n < SIZE) - break ; - - chunk++ ; - } - - fclose(f) ; - free(membuf) ; - -#ifdef WIN32 -// FlushFileBuffers(fifo); - DisconnectNamedPipe(fifo); -#endif - - std::cerr << "Sleeping 60 sec." << std::endl; -#ifdef WIN32 - Sleep(60000) ; - CloseHandle(fifo); -#else - sleep(60) ; - close(fifo) ; -#endif - - return 0 ; - } - catch(std::exception& e) - { - std::cerr << "Exception caught: " << e.what() << std::endl; - } -} - - diff --git a/libretroshare/src/tests/util/testcontentvalue.cpp b/libretroshare/src/tests/util/testcontentvalue.cpp deleted file mode 100644 index 17993aaab..000000000 --- a/libretroshare/src/tests/util/testcontentvalue.cpp +++ /dev/null @@ -1,374 +0,0 @@ - -#include - -#include "retrodb.h" -#include "utest.h" - -bool operator==(const ContentValue& lCV, ContentValue& rCV){ - - std::map leftKtMap, rightKtMap; - lCV.getKeyTypeMap(leftKtMap); - rCV.getKeyTypeMap(rightKtMap); - - return (leftKtMap == rightKtMap); -} - - -/*! - * Test content value ability to take a set of data and ability to get it out - * For all data types - */ -void testEnterAndRetrieve(); - -/*! - * Check to see if copy constructor intialises - * 'this' correctly - */ -void testCopyConstructor(); - -/*! - * check that key type map returned is consistent - * with data contained in ContentValue - */ -void testGetKeyTypeMap(); - -/*! - * Test the clearing functionality - */ -void testClear(); - -/*! - * check errors are meaningful - */ -void testErrors(); - -/*! - * enter the same key twice and ensure previous data gets overwritten - * - */ -void testSameKey(); - - -INITTEST(); - -int main(){ - - testEnterAndRetrieve(); - testCopyConstructor(); - testClear(); - testSameKey(); - testGetKeyTypeMap(); - testErrors(); - - FINALREPORT("TEST_CONTENT_VALUE"); -} - - -void testSameKey(){ - - - ContentValue cv; - - // test data - - std::string src = "adalkjalfalfalfkal"; - const char* data = src.data(); - uint32_t data_len = src.length(); - std::string data_key = "private_key"; - cv.put(data_key, data_len, data); - - std::string other_src = "daldko5202402224"; - data_len = other_src.length(); - data = other_src.data(); - - cv.put(data_key, data_len, data); - - uint32_t val_len; - char* val; - cv.getAsData(data_key, val_len, val); - std::string str_val(val, val_len); - - - CHECK(str_val == other_src); - - // now check string - - std::string key = "peer"; - cv.put(key, std::string("sexy_girl")); - cv.put(key, std::string("manly man")); - - std::string val_str; - cv.getAsString(key, val_str); - - CHECK(val_str == "manly man"); - - // and double - - cv.put(key, 4.); - cv.put(key, 32.); - double val_d; - cv.getAsDouble(key, val_d); - CHECK(val_d == 32.); - - // and int64 - int64_t large(20420492040123); - cv.put(key, large); - cv.put(key, large+34); - int64_t val_i64; - cv.getAsInt64(key, val_i64); - - CHECK(val_i64 == large+34); - - // and bool - - cv.put(key, false); - cv.put(key, true); - bool bool_val = false; - cv.getAsBool(key, bool_val); - - CHECK(bool_val == true); - - // and int32 - - int32_t medium = 20432123; - cv.put(key, medium); - cv.put(key, medium+34); - int32_t val_i32; - cv.getAsInt32(key, val_i32); - - CHECK(val_i32 == medium+34); - - REPORT("testSameKey()"); -} - - -void testErrors(){ - - - ContentValue cv; - int32_t val_32; - int64_t val_64; - char* data; - uint32_t data_len; - std::string val_str; - bool val_bool; - double val_d; - CHECK(!cv.getAsInt32("dda", val_32)); - CHECK(!cv.getAsInt64("dda", val_64)); - CHECK(!cv.getAsData("ds", data_len, data)); - CHECK(!cv.getAsString("d3536356336356356s", val_str)); - CHECK(!cv.getAsBool("d424s", val_bool)); - CHECK(!cv.getAsDouble("daads", val_d)); - - REPORT("testErrors()"); -} - -void testEnterAndRetrieve(){ - - // INT 32 - int32_t value32 = 1, retval32; - std::string key = "one"; - - ContentValue cv; - cv.put(key, value32); - - cv.getAsInt32(key, retval32); - CHECK(value32 == retval32); - - // INT 64 - int64_t value64 = 423425242, retval64; - key = "int64"; - cv.put(key, value64); - cv.getAsInt64(key, retval64); - CHECK(value64 == retval64); - - - // Double - double dvalue = 3.5, retvaldbl; - key = "double"; - cv.put(key, dvalue); - cv.getAsDouble(key, retvaldbl); - CHECK(dvalue == retvaldbl ); - - // BLOB - uint32_t data_len = 45, get_len = 0; - - char* src = new char[data_len]; - char* get_src = NULL; - memset(src, '$', data_len); - key = "data"; - cv.put(key, data_len, src); - - cv.getAsData(key, get_len, get_src); - - bool fine = true; - - CHECK(get_len = data_len); - - if(data_len == get_len){ - - for(int i=0; i < data_len; i++){ - - if(src[i] != get_src[i]) - fine &= false; - - } - } - - delete[] src; - CHECK(fine); - - // STRING - std::string strVal = "whoo", getVal(""); - key = "string"; - cv.put(key, strVal); - cv.getAsString(key, getVal); - - CHECK(getVal == strVal); - - - // BOOL - bool mefalse = false, retvalBool; - key = "bool"; - cv.put(key, mefalse); - cv.getAsBool(key, retvalBool); - CHECK(mefalse == retvalBool); - - cv.clear(); - - REPORT("testEnterAndRetrieve()"); -} - -void testGetKeyTypeMap(){ - - ContentValue cv; - std::string key1="key1", key2="key2", key3="key3", key4="key4"; - std::string key1_val; - int32_t key2_val = 42; - double key3_val = 23; - int64_t key4_val = 42052094224; - - cv.put(key1, key1_val); - cv.put(key2, key2_val); - cv.put(key3, key3_val); - cv.put(key4, key4_val); - - std::map kvMap; - - cv.getKeyTypeMap(kvMap); - - CHECK(kvMap.size() == 4); - CHECK(kvMap[key1] == ContentValue::STRING_TYPE); - CHECK(kvMap[key2] == ContentValue::INT32_TYPE); - CHECK(kvMap[key3] == ContentValue::DOUBLE_TYPE); - CHECK(kvMap[key4] == ContentValue::INT64_TYPE); - - REPORT("testGetKeyTypeMap()"); -} - -void testCopyConstructor(){ - - ContentValue cv1; - - // INT 32 - int value32 = 1; - std::string key = "one"; - - cv1.put(key, value32); - - // INT 64 - int64_t value64 = 423425242; - key = "int64"; - cv1.put(key, value64); - - // Double - double dvalue = 3.5; - key = "double"; - cv1.put(key, dvalue); - - // BLOB - uint32_t data_len = 45; - char* src = new char[data_len]; - - memset(src, '$', data_len); - key = "data"; - cv1.put(key, data_len, src); - - - delete[] src; - - // STRING - std::string strVal = "whoo"; - key = "string"; - cv1.put(key, strVal); - - // BOOL - bool mefalse = false; - key = "bool"; - cv1.put(key, mefalse); - - ContentValue cv2(cv1); - - CHECK(cv1 == cv2); - - cv1.clear(); - cv2.clear(); - - REPORT("testCopyConstructor()"); -} - - -void testClear(){ - - ContentValue cv1; - - // INT 32 - int value32 = 1; - std::string key = "one"; - - cv1.put(key, value32); - - // INT 64 - int64_t value64 = 423425242; - key = "int64"; - cv1.put(key, value64); - - // Double - double dvalue = 3.5; - key = "double"; - cv1.put(key, dvalue); - - // BLOB - uint32_t data_len = 45; - char* src = new char[data_len]; - - memset(src, '$', data_len); - key = "data"; - cv1.put(key, data_len, src); - - - delete[] src; - - // STRING - std::string strVal = "whoo"; - key = "string"; - cv1.put(key, strVal); - - // BOOL - bool mefalse = false; - key = "bool"; - cv1.put(key, mefalse); - - std::map ktMap; - - cv1.getKeyTypeMap(ktMap); - CHECK(ktMap.size() > 0); - - cv1.clear(); - - cv1.getKeyTypeMap(ktMap); - CHECK(ktMap.size() == 0); - - REPORT("testClear()"); - -} diff --git a/libretroshare/src/tests/util/testretrocursor.cpp b/libretroshare/src/tests/util/testretrocursor.cpp deleted file mode 100644 index 78d77e483..000000000 --- a/libretroshare/src/tests/util/testretrocursor.cpp +++ /dev/null @@ -1,127 +0,0 @@ - -#include -#include -#include -#include "util/rstime.h" - -#include "retrodb.h" -#include "utest.h" - - -#define INT32_KEY "day" -#define INT64_KEY "pub_key" -#define DATA_KEY "data" -#define DOUBLE_KEY "a_double" -#define STRING_KEY "a_string" -#define BOOL_KEY "a_bool" - -#define DB_FILE_NAME "RetroDb" - -static RetroDb* mDb = NULL; - -void createRetroDb(); -void destroyRetroDb(); - -INITTEST(); -// mainly test ability to move up and down result set - - -void testTraverseResult(); - - -int main() { - - testTraverseResult(); - - FINALREPORT("RETRO CURSOR TEST"); - return 0; -} - - - -void createRetroDb(){ - - if(mDb) - destroyRetroDb(); - - - remove(DB_FILE_NAME); // account for interrupted tests - mDb = new RetroDb(DB_FILE_NAME, RetroDb::OPEN_READWRITE_CREATE); -} - -void destroyRetroDb(){ - if(mDb == NULL) - return; - - mDb->closeDb(); - delete mDb; - mDb = NULL; - int rc = remove(DB_FILE_NAME); - std::cerr << "remove code: " << rc << std::endl; - - if(rc !=0){ - perror("Could not delete db: "); - - } -} - - -void testTraverseResult(){ - - - createRetroDb(); - - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(day INTEGER PRIMARY KEY ASC, pub_key INT, data BLOB, a_double REAL, a_string VARCHAR(255), a_bool INT);"); - CHECK(statementExecuted); - - ContentValue cv; - - cv.put(INT32_KEY, (int32_t)20); - int64_t large_num = 32432242344423; - cv.put(INT64_KEY, large_num); - std::string str = "3dajaojaljfacjlaf£%£^%\"%\"%$"; - const char* data = str.data(); - int size = str.size(); - cv.put(DATA_KEY, size, data); - cv.put(DOUBLE_KEY, 3.14); - cv.put(STRING_KEY, "hello precious"); - cv.put(BOOL_KEY, false); - - bool insertExecuted = mDb->sqlInsert("retroDB", "", cv); - cv.put(INT32_KEY, (int32_t)21); - insertExecuted &= mDb->sqlInsert("retroDB", "", cv); - cv.put(INT32_KEY, (int32_t)2); - insertExecuted &= mDb->sqlInsert("retroDB", "", cv); - cv.put(INT32_KEY, (int32_t)204); - insertExecuted &= mDb->sqlInsert("retroDB", "", cv); - cv.put(INT32_KEY, (int32_t)22); - insertExecuted &= mDb->sqlInsert("retroDB", "", cv); - - CHECK(insertExecuted); - - std::list columns; - columns.push_back(INT32_KEY); columns.push_back(INT64_KEY); columns.push_back(DOUBLE_KEY); - columns.push_back(DATA_KEY); columns.push_back(BOOL_KEY); columns.push_back(STRING_KEY); - std::string orderBy = std::string(INT32_KEY) + " ASC"; - RetroCursor* cursor = mDb->sqlQuery("retroDB", columns, "", orderBy); - - CHECK(cursor->getResultCount() == 5); - cursor->moveToFirst(); - CHECK(cursor->getPosition() == 0); - - cursor->moveToLast(); - CHECK(cursor->getPosition() == cursor->getResultCount()); - - cursor->moveToFirst(); - - CHECK(cursor->getInt32(0) == 2); - cursor->moveToNext(); - cursor->moveToNext(); - - CHECK(cursor->getInt32(0) == 21); - - delete cursor; - - REPORT("testTraverseResult()"); - destroyRetroDb(); -} diff --git a/libretroshare/src/tests/util/testretrodb.cpp b/libretroshare/src/tests/util/testretrodb.cpp deleted file mode 100644 index 37b9d7d84..000000000 --- a/libretroshare/src/tests/util/testretrodb.cpp +++ /dev/null @@ -1,352 +0,0 @@ - -#include -#include -#include -#include "util/rstime.h" - -#include "retrodb.h" -#include "utest.h" - - -#define DAY_KEY "day" -#define PUB_KEY "pub_key" -#define DATA_KEY "data" -#define DOUBLE_KEY "a_double" - -#define DB_FILE_NAME "RetroDb" - -static RetroDb* mDb = NULL; - -void createRetroDb(); -void destroyRetroDb(); - -void testSqlExec(); -void testSqlUpdate(); -void testSqlInsert(); -void testSqlDelete(); -void testSqlQuery(); -void testBinaryInsertion(); - -INITTEST(); - -int main(){ - - testSqlExec(); - testBinaryInsertion(); - testSqlInsert(); - testSqlUpdate(); - testSqlDelete(); - testSqlQuery(); - - FINALREPORT("RETRO DB TEST"); - return 0; -} - -void createRetroDb(){ - - if(mDb) - destroyRetroDb(); - - - remove(DB_FILE_NAME); // account for interrupted tests - mDb = new RetroDb(DB_FILE_NAME, RetroDb::OPEN_READWRITE_CREATE); -} - -void destroyRetroDb(){ - if(mDb == NULL) - return; - - mDb->closeDb(); - delete mDb; - mDb = NULL; - int rc = remove(DB_FILE_NAME); - std::cerr << "remove code: " << rc << std::endl; - - if(rc !=0){ - perror("Could not delete db: "); - - } -} - -void testSqlExec(){ - - createRetroDb(); - - // create simple table - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(day INTEGER PRIMARY KEY ASC, pub_key, data);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(day, pub_key, data) VALUES(1,2,3);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(day, pub_key, data) VALUES(3,4525624,4524);"); - - CHECK(statementExecuted); - - // now check if you can retrieve records - std::list columns; - columns.push_back("day"); - columns.push_back("pub_key"); - columns.push_back("data"); - - std::string selection, orderBy; - RetroCursor* c = mDb->sqlQuery("retroDB", columns, selection, orderBy); - - - CHECK(c->getResultCount() == 2); - - // got to first record - c->moveToFirst(); - int32_t first =c->getInt32(0), second = c->getInt32(1), - third = c->getInt32(2); - - - CHECK(first == 1); - CHECK(second == 2); - CHECK(third == 3); - - // get 2nd record - c->moveToNext(); - - first =c->getInt32(0), second = c->getInt32(1), - third = c->getInt32(2); - - CHECK(first == 3); - CHECK(second == 4525624); - CHECK(third == 4524); - - delete c; - - REPORT("testSqlExec()"); - destroyRetroDb(); -} - -void testBinaryInsertion(){ - - createRetroDb(); - // create simple table - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(day INTEGER PRIMARY KEY ASC, data BLOB);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(day, data) VALUES(1, 'dafadfad%$%^%%\"$R\"$\"$\"');"); - - // now check if you can retrieve records - std::list columns; - columns.push_back("day"); - columns.push_back("data"); - - std::string selection, orderBy; - RetroCursor* c = mDb->sqlQuery("retroDB", columns, selection, orderBy); - - c->moveToFirst(); - int first = c->getInt32(0); - uint32_t size; - const char* data = (const char*)c->getData(1, size); - std::string str = "dafadfad%$%^%%\"$R\"$\"$\""; - const char* data_comp = str.data(); - bool binCompare = ok; - - for(int i=0; i < 24 ; i++) - binCompare &= data[i] == data_comp[i]; - - CHECK(first == 1); - CHECK(binCompare); - - delete c; - REPORT("testBinaryInsertion()"); - destroyRetroDb(); -} - - - - -void testSqlUpdate(){ - - createRetroDb(); - - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(day INTEGER PRIMARY KEY ASC, data BLOB, peerId VARCHAR(255), time INT);"); - CHECK(statementExecuted); - - std::string data = "dadJOOodaodaoro20r2-0r20002ri02fgi3t0***"; - ContentValue cv; - - cv.put("day", (int32_t)20); - std::string peerid = "TheRetroSquad"; - cv.put("peerId", peerid); - cv.put("data", data.size(), data.data()); - int64_t now = time(NULL); - cv.put("time", now); - bool insertExecuted = mDb->sqlInsert("retroDB", "", cv); - - CHECK(insertExecuted); - - // now check entry is fine - - std::list columns; - columns.push_back("day"); columns.push_back("peerId"); columns.push_back("data"); columns.push_back("time"); - - RetroCursor* c = mDb->sqlQuery("retroDB", columns, "", ""); - - CHECK(c->getResultCount() == 1); - std::string result; - c->moveToFirst(); - c->getString(1, result); - - CHECK(result == peerid); - - delete c; - c = NULL; - - // now make an update and see if this is reflected - - int64_t now_plus = now+203; - cv.put("time", now_plus); - bool update = mDb->sqlUpdate("retroDB", "", cv); - CHECK(update); - c = mDb->sqlQuery("retroDB", columns, "", ""); - c->moveToFirst(); - int64_t now_plus_compare = c->getDouble(3); - - CHECK(now_plus_compare == now_plus); - - // now attempt an update which should find no valid record - - - delete c; - - REPORT("testSqlUpdate()"); - destroyRetroDb(); -} - -void testSqlInsert(){ - - createRetroDb(); - - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(day INTEGER PRIMARY KEY ASC, a_double DOUBLE, data BLOB);"); - CHECK(statementExecuted); - - ContentValue cv; - - cv.put("day", (int32_t)20); - std::string str = "3dajaojaljfacjlaf%^%\"%\"%$"; - const char* data = str.data(); - int size = 27; - cv.put(DATA_KEY, size, data); - cv.put(DOUBLE_KEY, 3.14); - bool insertExecuted = mDb->sqlInsert("retroDB", "", cv); - - std::list columns; - columns.push_back("day"); columns.push_back("a_double"); columns.push_back("data"); - RetroCursor* cursor = mDb->sqlQuery("retroDB", columns, "", ""); - - CHECK(cursor != NULL); - - cursor->moveToFirst(); - - CHECK(20 == cursor->getInt32(0)); - CHECK(3.14 == cursor->getDouble(1)); - - CHECK(insertExecuted); - - delete cursor; - FINALREPORT("testSqlInsert()"); - destroyRetroDb(); -} - -void testSqlQuery(){ - // test ordering of data and selection clause - - - createRetroDb(); - - // create simple table - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(priority INTEGER PRIMARY KEY ASC, name VARCHAR(255), friends, games INTEGER);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(priority, name, friends, games) VALUES(4,'sammy',2,30);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(priority, name, friends, games) VALUES(2,'davy',6,9);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(priority, name, friends, games) VALUES(6,'pammy',2,4);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(priority, name, friends, games) VALUES(5,'tommy',3,4534);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(priority, name, friends, games) VALUES(9,'jonny',3,44);"); - - CHECK(statementExecuted); - - std::list columns; - columns.push_back("name"); - std::string selection = "games <= 31"; - std::string orderBy = "priority DESC"; - - - // output should be by name: pammy, sammy and davy - RetroCursor* cursor = mDb->sqlQuery("retroDB", columns,selection, orderBy); - - cursor->moveToFirst(); - std::string name; - cursor->getString(0,name); - CHECK(name == "pammy"); - - cursor->moveToNext(); - cursor->getString(0,name); - CHECK(name == "sammy"); - - cursor->moveToNext(); - cursor->getString(0,name); - CHECK(name == "davy"); - - - delete cursor; - FINALREPORT("testSqlQuery()"); - destroyRetroDb(); - return; -} - -void testSqlDelete(){ - - createRetroDb(); - - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(day INTEGER PRIMARY KEY ASC, a_double DOUBLE, data BLOB);"); - CHECK(statementExecuted); - - ContentValue cv; - - cv.put("day", (int32_t)20); - std::string str = "3dajaojaljfacjlaf%^%\"%\"%$"; - const char* data = str.data(); - uint32_t size = str.size(); - cv.put(DATA_KEY, size, data); - cv.put(DOUBLE_KEY, 3.14); - - // insert to records - bool insertExecuted = mDb->sqlInsert("retroDB", "", cv); - cv.put("day", (int32_t(5))); - CHECK(insertExecuted); - mDb->sqlInsert("retroDB", "", cv); - - - // now check that their are two records in the db - std::list columns; - columns.push_back("day"); columns.push_back("a_double"); columns.push_back("data"); - RetroCursor* cursor = mDb->sqlQuery("retroDB", columns, "", ""); - CHECK(cursor->getResultCount() == 2); - delete cursor; - // now remove a record and search for the removed record, query should return no records - mDb->sqlDelete("retroDB", "day=5", ""); - - - cursor = mDb->sqlQuery("retroDB", columns, "day=5", ""); - CHECK(cursor->getResultCount() == 0); - delete cursor; - - // now check for the remaining record - cursor = mDb->sqlQuery("retroDB", columns, "day=20", ""); - CHECK(cursor->getResultCount() == 1); - cursor->moveToFirst(); - - // verify there is no data corruption - const char* data_comp1 = (const char*)cursor->getData(2, size); - const char* data_comp2 = str.data(); - - bool binCompare = true; - - for(int i=0; i < str.size() ; i++) - binCompare &= data_comp1[i] == data_comp2[i]; - - CHECK(binCompare); - - delete cursor; - - FINALREPORT("testSqlDelete()"); - destroyRetroDb(); -} diff --git a/libretroshare/src/turtle/p3turtle.cc b/libretroshare/src/turtle/p3turtle.cc deleted file mode 100644 index 10069056a..000000000 --- a/libretroshare/src/turtle/p3turtle.cc +++ /dev/null @@ -1,2516 +0,0 @@ -/******************************************************************************* - * libretroshare/src/turtle: p3turtle.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2018 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -//#define P3TURTLE_DEBUG - -#include -#include -#include -#include - -#include "rsserver/p3face.h" -#include "crypto/rscrypto.h" - -#include "pqi/authssl.h" -#include "pqi/p3linkmgr.h" -#include "retroshare/rspeers.h" - -#include "ft/ftserver.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftcontroller.h" - -#include "p3turtle.h" - -#include -#include -#include - -#include - -#include "util/rsdebug.h" -#include "util/rsprint.h" -#include "util/rsrandom.h" -#include "pqi/pqinetwork.h" - -#ifdef TUNNEL_STATISTICS -static std::vector TS_tunnel_length(8,0) ; -static std::map > > TS_request_time_stamps ; -static std::map > TS_request_bounces ; -void TS_dumpState() ; -#endif - -#define TURTLE_DEBUG() std::cerr << time(NULL) << " : TURTLE : " << __FUNCTION__ << " : " -#define TURTLE_ERROR() std::cerr << "(EE) TURTLE ERROR : " - -// These number may be quite important. I setup them with sensible values, but -// an in-depth test would be better to get an idea of what the ideal values -// could ever be. -// -// update of 14-03-11: -// - I raised the cache time for tunnel requests. This avoids inconsistencies such as: -// * tunnel requests bouncing back while the original request is not in the cache anymore -// * special case of this for own file transfer: an outgoing tunnel is built with no end. -// - changed tunnel speed estimate time lapse to 5 secs. Too small a value favors high variations. -// - the max number of tunnel requests per second is now enforced. It was before defaulting to -// QUEUE_LENGTH*0.1, meaning 0.5. I set it to 0.1. -// -// update of 19-04-12: -// - The total number of TR per second emmited from self will be MAX_TUNNEL_REQS_PER_SECOND / TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS = 0.5 -// - I updated forward probabilities to higher values, and min them to 1/nb_connected_friends to prevent blocking tunnels. -// -static const rstime_t TUNNEL_REQUESTS_LIFE_TIME = 600 ; /// life time for tunnel requests in the cache. -static const rstime_t TUNNEL_REQUESTS_RESULT_TIME = 20 ; /// maximum time during which we process/forward results for known tunnel requests -static const rstime_t SEARCH_REQUESTS_LIFE_TIME = 600 ; /// life time for search requests in the cache -static const rstime_t SEARCH_REQUESTS_RESULT_TIME = 20 ; /// maximum time during which we process/forward results for known search requests -static const rstime_t REGULAR_TUNNEL_DIGGING_TIME = 300 ; /// maximum interval between two tunnel digging campaigns. -static const rstime_t MAXIMUM_TUNNEL_IDLE_TIME = 60 ; /// maximum life time of an unused tunnel. -static const rstime_t EMPTY_TUNNELS_DIGGING_TIME = 50 ; /// look into tunnels regularly every 50 sec. -static const rstime_t TUNNEL_SPEED_ESTIMATE_LAPSE = 5 ; /// estimate tunnel speed every 5 seconds -static const rstime_t TUNNEL_CLEANING_LAPS_TIME = 10 ; /// clean tunnels every 10 secs -static const rstime_t TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS = 2 ; /// Tunnel management calls every 2 secs. -static const uint32_t MAX_TUNNEL_REQS_PER_SECOND = 1 ; /// maximum number of tunnel requests issued per second. Was 0.5 before -static const uint32_t MAX_ALLOWED_SR_IN_CACHE = 120 ; /// maximum number of search requests allowed in cache. That makes 2 per sec. -static const uint32_t TURTLE_SEARCH_RESULT_MAX_HITS_FILES =5000 ; /// maximum number of search results forwarded back to the source. -static const uint32_t TURTLE_SEARCH_RESULT_MAX_HITS_DEFAULT = 100 ; /// default maximum number of search results forwarded back source. - -static const float depth_peer_probability[7] = { 1.0f,0.99f,0.9f,0.7f,0.6f,0.5,0.4f } ; - -static const int TUNNEL_REQUEST_PACKET_SIZE = 50 ; -static const int MAX_TR_FORWARD_PER_SEC = 20 ; -static const int MAX_TR_FORWARD_PER_SEC_UPPER_LIMIT = 30 ; -static const int MAX_TR_FORWARD_PER_SEC_LOWER_LIMIT = 10 ; -static const int DISTANCE_SQUEEZING_POWER = 8 ; - -#define HEX_PRINT(a) std::hex << a << std::dec - -p3turtle::p3turtle(p3ServiceControl *sc,p3LinkMgr *lm) - :p3Service(), p3Config(), mServiceControl(sc), mLinkMgr(lm), mTurtleMtx("p3turtle") -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - _own_id = sc->getOwnId() ; - - if(_own_id.isNull()) - { - std::cerr << "OwnId is null, as returned by the p3ServiceControl object in turtle router. Can't go on!" << std::endl; - exit(-1) ; - } - _turtle_routing_enabled = true ; - _turtle_routing_session_enabled = true; - - _random_bias = RSRandom::random_u32() ; - _serialiser = new RsTurtleSerialiser() ; - - addSerialType(_serialiser); - - _last_clean_time = 0 ; - _last_tunnel_management_time = 0 ; - _last_tunnel_campaign_time = 0 ; - _last_tunnel_speed_estimate_time = 0 ; - - _traffic_info.reset() ; - _max_tr_up_rate = MAX_TR_FORWARD_PER_SEC ; - _service_type = getServiceInfo().mServiceType ; -} - -const std::string TURTLE_APP_NAME = "turtle"; -const uint16_t TURTLE_APP_MAJOR_VERSION = 1; -const uint16_t TURTLE_APP_MINOR_VERSION = 0; -const uint16_t TURTLE_MIN_MAJOR_VERSION = 1; -const uint16_t TURTLE_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3turtle::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_TURTLE, - TURTLE_APP_NAME, - TURTLE_APP_MAJOR_VERSION, - TURTLE_APP_MINOR_VERSION, - TURTLE_MIN_MAJOR_VERSION, - TURTLE_MIN_MINOR_VERSION); -} - -void p3turtle::getItemNames(std::map& names) const -{ - names.clear(); - - names[RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST ] = "Filename substring search request"; - names[RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST ] = "Generic search request"; - names[RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT ] = "File search result"; - names[RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT ] = "Generic search result"; - names[RS_TURTLE_SUBTYPE_OPEN_TUNNEL ] = "Tunnel request"; - names[RS_TURTLE_SUBTYPE_TUNNEL_OK ] = "Tunnel response"; - names[RS_TURTLE_SUBTYPE_FILE_REQUEST ] = "Data request"; - names[RS_TURTLE_SUBTYPE_FILE_DATA ] = "Data chunk"; - names[RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST ] = "Filename RegExp search request"; - names[RS_TURTLE_SUBTYPE_GENERIC_DATA ] = "Generic data"; - names[RS_TURTLE_SUBTYPE_FILE_MAP ] = "Chunk map"; - names[RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST ] = "Chunk map request"; - names[RS_TURTLE_SUBTYPE_CHUNK_CRC ] = "Chunk CRC"; - names[RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST ] = "Chunk CRC request"; -} - -void p3turtle::setEnabled(bool b) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _turtle_routing_enabled = b; - - if(b) - std::cerr << "Enabling turtle routing" << std::endl; - else - std::cerr << "Disabling turtle routing" << std::endl; - - IndicateConfigChanged() ; -} -bool p3turtle::enabled() const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - return _turtle_routing_enabled ; -} - - -void p3turtle::setSessionEnabled(bool b) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _turtle_routing_session_enabled = b; - - if(b) - std::cerr << "Enabling turtle routing for this Session" << std::endl; - else - std::cerr << "Disabling turtle routing for this Session" << std::endl; -} - -bool p3turtle::sessionEnabled() const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - return _turtle_routing_session_enabled ; -} - - -int p3turtle::tick() -{ - // Handle tunnel trafic - // - handleIncoming(); // handle incoming packets - - rstime_t now = time(NULL) ; - -#ifdef TUNNEL_STATISTICS - static rstime_t last_now = now ; - if(now - last_now > 2) - std::cerr << "******************* WARNING: now - last_now = " << now - last_now << std::endl; - last_now = now ; -#endif - - bool should_autowash,should_estimatespeed ; - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - should_autowash = now > TUNNEL_CLEANING_LAPS_TIME+_last_clean_time ; - should_estimatespeed = now >= TUNNEL_SPEED_ESTIMATE_LAPSE + _last_tunnel_speed_estimate_time ; - } - - // Tunnel management: - // - we digg new tunnels at least every 5 min (300 sec). - // - we digg new tunnels each time a new peer connects - // - we digg new tunnels each time a new hash is asked for - // - if(now >= _last_tunnel_management_time+TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS) // call every second - { -#ifdef P3TURTLE_DEBUG - std::cerr << "Calling tunnel management." << std::endl ; -#endif - if(_turtle_routing_enabled && _turtle_routing_session_enabled) - manageTunnels() ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _last_tunnel_management_time = now ; - - // Update traffic statistics. The constants are important: they allow a smooth variation of the - // traffic speed, which is used to moderate tunnel requests statistics. - // - _traffic_info = _traffic_info*0.9 + _traffic_info_buffer* (0.1 / (float)TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS) ; - _traffic_info_buffer.reset() ; - } - } - - // Clean every 10 sec. - // - if(should_autowash) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "Calling autowash." << std::endl ; -#endif - autoWash() ; // clean old/unused tunnels and file hashes, as well as search and tunnel requests. - - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _last_clean_time = now ; - } - - if(should_estimatespeed) - { - estimateTunnelSpeeds() ; - - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _last_tunnel_speed_estimate_time = now ; - } - -#ifdef TUNNEL_STATISTICS - // Dump state for debugging, every 20 sec. - // - static rstime_t TS_last_dump = time(NULL) ; - - if(now > 20+TS_last_dump) - { - TS_last_dump = now ; - TS_dumpState() ; - } -#endif - -#ifdef P3TURTLE_DEBUG - // Dump state for debugging, every 20 sec. - // - static rstime_t last_dump = time(NULL) ; - - if(now > 20+last_dump) - { - last_dump = now ; - dumpState() ; - } -#endif - return 0 ; -} - -// -----------------------------------------------------------------------------------// -// ------------------------------ Tunnel maintenance. ------------------------------ // -// -----------------------------------------------------------------------------------// -// - -// adds a virtual peer to the list that is communicated ot ftController. -// -void p3turtle::locked_addDistantPeer(const TurtleFileHash&,TurtleTunnelId tid) -{ - unsigned char tmp[RsPeerId::SIZE_IN_BYTES] ; - memset(tmp,0,RsPeerId::SIZE_IN_BYTES) ; - - assert(sizeof(tid) == 4) ; - - for(int i=0;i<4;++i) - tmp[i] = uint8_t( (tid >> ((3-i)*8)) & 0xff ) ; - - RsPeerId virtual_peer_id(tmp) ; - - _virtual_peers[virtual_peer_id] = tid ; -#ifdef P3TURTLE_DEBUG - assert(_local_tunnels.find(tid)!=_local_tunnels.end()) ; -#endif - _local_tunnels[tid].vpid = virtual_peer_id ; -} - -void p3turtle::getSourceVirtualPeersList(const TurtleFileHash& hash,std::list& list) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - list.clear() ; - - std::map::const_iterator it = _incoming_file_hashes.find(hash) ; - - if(it != _incoming_file_hashes.end()) - for(uint32_t i=0;isecond.tunnels.size();++i) - { - std::map::const_iterator it2 = _local_tunnels.find( it->second.tunnels[i] ) ; - - if(it2 != _local_tunnels.end()) - { - pqipeer vp ; - vp.id = it2->second.vpid ; - vp.name = "Virtual (distant) peer" ; - vp.state = RS_PEER_S_CONNECTED ; - vp.actions = RS_PEER_CONNECTED ; - list.push_back(vp) ; - } - else - std::cerr << "(EE) getSourceVirtualPeersList(): no tunnels for incoming file hash " << hash << ": weird!"<< std::endl; - } -} - -// This method handles digging new tunnels as needed. -// New tunnels are dug when: -// - new peers have connected. The resulting tunnels should be checked against doubling. -// - new hashes are submitted for handling. -// -class hashPairComparator -{ - public: - virtual bool operator()(const std::pair& p1,const std::pair& p2) const - { - return p1.second < p2.second ; - } -}; -void p3turtle::manageTunnels() -{ - // Collect hashes for which tunnel digging is necessary / recommended. Hashes get in the list for two reasons: - // - the hash has no tunnel -> tunnel digging every EMPTY_TUNNELS_DIGGING_TIME seconds - // - the hash hasn't been tunneled for more than REGULAR_TUNNEL_DIGGING_TIME seconds, even if downloading. - // - // Candidate hashes are sorted, by olderness. The older gets tunneled first. At most MAX_TUNNEL_REQS_PER_SECOND are - // treated at once, as this method is called every second. - // Note: Because REGULAR_TUNNEL_DIGGING_TIME is larger than EMPTY_TUNNELS_DIGGING_TIME, files being downloaded get - // re-tunneled in priority. As this happens less, they don't obliterate tunneling for files that have no tunnels yet. - - std::vector > hashes_to_digg ; - rstime_t now = time(NULL) ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // digg new tunnels if no tunnels are available and force digg new tunnels at regular (large) interval - // - for(std::map::const_iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) - { - // get total tunnel speed. - // - uint32_t total_speed = 0 ; - for(uint32_t i=0;isecond.tunnels.size();++i) - total_speed += _local_tunnels[it->second.tunnels[i]].speed_Bps ; - - static const float grow_speed = 1.0f ; // speed at which the time increases. - - float tunnel_keeping_factor = (std::max(1.0f,(float)total_speed/(float)(50*1024)) - 1.0f)*grow_speed + 1.0f ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "Total speed = " << total_speed << ", tunel factor = " << tunnel_keeping_factor << " new time = " << rstime_t(REGULAR_TUNNEL_DIGGING_TIME*tunnel_keeping_factor) << std::endl; -#endif - - if( (it->second.tunnels.empty() && now >= it->second.last_digg_time+EMPTY_TUNNELS_DIGGING_TIME) - || (it->second.use_aggressive_mode && now >= it->second.last_digg_time + rstime_t(REGULAR_TUNNEL_DIGGING_TIME*tunnel_keeping_factor))) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "pushed hash " << it->first << ", for digging. Old = " << now - it->second.last_digg_time << std::endl; -#endif - hashes_to_digg.push_back(std::pair(it->first,it->second.last_digg_time)) ; - } - } - } -#ifdef TUNNEL_STATISTICS - std::cerr << hashes_to_digg.size() << " hashes candidate for tunnel digging." << std::endl; -#endif - - std::sort(hashes_to_digg.begin(),hashes_to_digg.end(),hashPairComparator()) ; - - for(unsigned int i=0;i::iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it) - { - TurtleTunnel& tunnel(it->second) ; - - float speed_estimate = tunnel.transfered_bytes / float(TUNNEL_SPEED_ESTIMATE_LAPSE) ; - tunnel.speed_Bps = 0.75*tunnel.speed_Bps + 0.25*speed_estimate ; - tunnel.transfered_bytes = 0 ; - } -} - -void p3turtle::autoWash() -{ -#ifdef P3TURTLE_DEBUG - std::cerr << " In autowash." << std::endl ; -#endif - // Remove hashes that are marked as such. - // - - std::vector > > services_vpids_to_remove ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - for(std::set::const_iterator hit(_hashes_to_remove.begin());hit!=_hashes_to_remove.end();++hit) - { - std::map::iterator it(_incoming_file_hashes.find(*hit)) ; - - if(it == _incoming_file_hashes.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: asked to stop monitoring file hash " << *hit << ", but this hash is actually not handled by the turtle router." << std::endl ; -#endif - continue ; - } - - // copy the list of tunnels to remove. -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: stopping monitoring for file hash " << *hit << ", and closing " << it->second.tunnels.size() << " tunnels (" ; -#endif - std::vector tunnels_to_remove ; - - for(std::vector::const_iterator it2(it->second.tunnels.begin());it2!=it->second.tunnels.end();++it2) - { -#ifdef P3TURTLE_DEBUG - std::cerr << HEX_PRINT(*it2) << "," ; -#endif - tunnels_to_remove.push_back(*it2) ; - } -#ifdef P3TURTLE_DEBUG - std::cerr << ")" << std::endl ; -#endif - for(unsigned int k=0;k::iterator it(_search_requests_origins.begin());it!=_search_requests_origins.end();) - if(now > (rstime_t)(it->second.time_stamp + SEARCH_REQUESTS_LIFE_TIME)) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " removed search request " << HEX_PRINT(it->first) << ", timeout." << std::endl ; -#endif - std::map::iterator tmp(it) ; - ++tmp ; - _search_requests_origins.erase(it) ; - it = tmp ; - } - else - ++it; - } - - // Tunnel requests - // - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - for(std::map::iterator it(_tunnel_requests_origins.begin());it!=_tunnel_requests_origins.end();) - if(now > (rstime_t)(it->second.time_stamp + TUNNEL_REQUESTS_LIFE_TIME)) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " removed tunnel request " << HEX_PRINT(it->first) << ", timeout." << std::endl ; -#endif - std::map::iterator tmp(it) ; - ++tmp ; - _tunnel_requests_origins.erase(it) ; - it = tmp ; - } - else - ++it ; - } - - // Tunnels. - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - std::vector tunnels_to_close ; - - for(std::map::iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it) - if(now > (rstime_t)(it->second.time_stamp + MAXIMUM_TUNNEL_IDLE_TIME)) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " removing tunnel " << HEX_PRINT(it->first) << ": timeout." << std::endl ; -#endif - tunnels_to_close.push_back(it->first) ; - } - - for(unsigned int i=0;iremoveVirtualPeer(services_vpids_to_remove[i].second.first,services_vpids_to_remove[i].second.second) ; - } -} - -void p3turtle::forceReDiggTunnels(const TurtleFileHash& hash) -{ - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - if( _incoming_file_hashes.find(hash) == _incoming_file_hashes.end()) - { - std::cerr << "(EE) p3turtle::forceReDiggTunnels(): hash " << hash << " is not currently handled by turtle." << std::endl; - return ; - } - } - - diggTunnel(hash) ; -} - -void p3turtle::locked_closeTunnel(TurtleTunnelId tid,std::vector > >& sources_to_remove) -{ - // This is closing a given tunnel, removing it from file sources, and from the list of tunnels of its - // corresponding file hash. In the original turtle4privacy paradigm, they also send back and forward - // tunnel closing commands. In our case, this is not necessary, because if a tunnel is closed somewhere, its - // source is not going to be used and the tunnel will eventually disappear. - // - std::map::iterator it(_local_tunnels.find(tid)) ; - - if(it == _local_tunnels.end()) - { - std::cerr << "p3turtle: was asked to close tunnel " << reinterpret_cast(tid) << ", which actually doesn't exist." << std::endl ; - return ; - } -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: Closing tunnel " << HEX_PRINT(tid) << std::endl ; -#endif - - if(it->second.local_src == _own_id) // this is a starting tunnel. We thus remove - // - the virtual peer from the vpid list - // - the tunnel id from the file hash - // - the virtual peer from the file sources in the file transfer controller. - { - TurtleTunnelId tid = it->first ; - TurtleVirtualPeerId vpid = it->second.vpid ; - TurtleFileHash hash = it->second.hash ; - -#ifdef P3TURTLE_DEBUG - std::cerr << " Tunnel is a starting point. Also removing:" << std::endl ; - std::cerr << " Virtual Peer Id " << vpid << std::endl ; - std::cerr << " Associated file source." << std::endl ; -#endif - std::pair hash_vpid(hash,vpid) ; - - // Let's be cautious. Normally we should never be here without consistent information, - // but still, this happens, rarely. - // - if(_virtual_peers.find(vpid) != _virtual_peers.end()) - _virtual_peers.erase(_virtual_peers.find(vpid)) ; - - std::map::iterator it(_incoming_file_hashes.find(hash)) ; - - if(it != _incoming_file_hashes.end()) - { - std::vector& tunnels(it->second.tunnels) ; - - // Remove tunnel id from it's corresponding hash. For security we - // go through the whole tab, although the tunnel id should only be listed once - // in this tab. - // - for(unsigned int i=0;i >(it->second.service,hash_vpid)) ; - } - } - else if(it->second.local_dst == _own_id) // This is a ending tunnel. We also remove the virtual peer id - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Tunnel is a ending point. Also removing associated outgoing hash." ; -#endif - std::map::iterator itHash = _outgoing_tunnel_client_services.find(tid); - - if(itHash != _outgoing_tunnel_client_services.end()) - { - TurtleVirtualPeerId vpid = it->second.vpid ; - TurtleFileHash hash = it->second.hash ; - - std::pair hash_vpid(hash,vpid) ; - - sources_to_remove.push_back(std::pair >(itHash->second,hash_vpid)) ; - - _outgoing_tunnel_client_services.erase(itHash) ; - - // Also remove the associated virtual peer - // - if(_virtual_peers.find(vpid) != _virtual_peers.end()) - _virtual_peers.erase(_virtual_peers.find(vpid)) ; - } - } - - _local_tunnels.erase(it) ; -} - -void p3turtle::stopMonitoringTunnels(const RsFileHash& hash) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: Marking hash " << hash << " to be removed during autowash." << std::endl ; -#endif - // We don't do the deletion in this process, because it can cause a race with tunnel management. - _hashes_to_remove.insert(hash) ; -} - -// -----------------------------------------------------------------------------------// -// -------------------------------- Config functions ------------------------------ // -// -----------------------------------------------------------------------------------// -// -RsSerialiser *p3turtle::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsTurtleSerialiser) ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss ; -} - -bool p3turtle::saveList(bool& cleanup, std::list& lst) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: saving list..." << std::endl ; -#endif - cleanup = true ; - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - kv.key = "TURTLE_CONFIG_MAX_TR_RATE" ; - rs_sprintf(kv.value, "%g", _max_tr_up_rate); - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "TURTLE_ENABLED" ; - kv.value = _turtle_routing_enabled?"TRUE":"FALSE" ; - - vitem->tlvkvs.pairs.push_back(kv) ; - - lst.push_back(vitem) ; - - return true ; -} - -bool p3turtle::loadList(std::list& load) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: loading list..." << std::endl ; -#endif - for(std::list::const_iterator it(load.begin());it!=load.end();++it) - { - RsConfigKeyValueSet *vitem = dynamic_cast(*it) ; - - if(vitem != NULL) - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if(kit->key == "TURTLE_CONFIG_MAX_TR_RATE") - { - int val ; - if (sscanf(kit->value.c_str(), "%d", &val) == 1) - { - setMaxTRForwardRate(val) ; - std::cerr << "Setting max TR forward rate to " << val << std::endl ; - } - } - if(kit->key == "TURTLE_ENABLED") - { - _turtle_routing_enabled = (kit->value == "TRUE") ; - - if(!_turtle_routing_enabled) - std::cerr << "WARNING: turtle routing has been disabled. You can enable it again in config->server->turtle router." << std::endl; - } - } - - delete *it ; - } - load.clear() ; - return true ; -} -int p3turtle::getMaxTRForwardRate() const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - return _max_tr_up_rate ; -} - - -void p3turtle::setMaxTRForwardRate(int val) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - if(val > MAX_TR_FORWARD_PER_SEC_UPPER_LIMIT || val < MAX_TR_FORWARD_PER_SEC_LOWER_LIMIT) - std::cerr << "Warning: MAX_TR_FORWARD_PER_SEC value " << val << " read in config file is off limits [" << MAX_TR_FORWARD_PER_SEC_LOWER_LIMIT << "..." << MAX_TR_FORWARD_PER_SEC_UPPER_LIMIT << "]. Ignoring!" << std::endl; - else - { - _max_tr_up_rate = val ; - std::cerr << "p3turtle: Set max tr up rate to " << val << std::endl; - } - IndicateConfigChanged() ; -} - - -// -----------------------------------------------------------------------------------// -// -------------------------------- Helper functions ------------------------------ // -// -----------------------------------------------------------------------------------// -// -uint32_t p3turtle::generateRandomRequestId() -{ - return RSRandom::random_u32() ; -} - -uint32_t p3turtle::generatePersonalFilePrint(const TurtleFileHash& hash,uint32_t seed,bool b) -{ - // whatever cooking from the file hash and OwnId that cannot be recovered. - // The only important thing is that the saem couple (hash,SSL id) produces the same tunnel - // id. The result uses a boolean to allow generating non symmetric tunnel ids. - - std::string buff(hash.toStdString() + _own_id.toStdString()) ; - uint32_t res = seed ; - uint32_t decal = 0 ; - - for(int i=0;i<(int)buff.length();++i) - { - res += 7*buff[i] + decal ; - - if(b) - decal = decal*44497+15641+(res%86243) ; - else - decal = decal*86243+15649+(res%44497) ; - } - - return res ; -} -// -----------------------------------------------------------------------------------// -// -------------------------------- Global routing. -------------------------------- // -// -----------------------------------------------------------------------------------// -// -int p3turtle::handleIncoming() -{ - int nhandled = 0; - // While messages read - // - RsItem *item = NULL; - - while(NULL != (item = recvItem())) - { - nhandled++; - - if(!(_turtle_routing_enabled && _turtle_routing_session_enabled)) - delete item ; - else - { - RsTurtleGenericTunnelItem *gti = dynamic_cast(item) ; - - if(gti != NULL) - routeGenericTunnelItem(gti) ; /// Generic packets, that travel through established tunnels. - else /// These packets should be destroyed by the client. - { - /// Special packets that require specific treatment, because tunnels do not exist for these packets. - /// These packets are destroyed here, after treatment. - // - switch(item->PacketSubType()) - { - case RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST: - case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST: - case RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST: handleSearchRequest(dynamic_cast(item)) ; - break ; - - case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT : - case RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT : handleSearchResult(dynamic_cast(item)) ; - break ; - - case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : handleTunnelRequest(dynamic_cast(item)) ; - break ; - - case RS_TURTLE_SUBTYPE_TUNNEL_OK : handleTunnelResult(dynamic_cast(item)) ; - break ; - - default: - std::cerr << "p3turtle::handleIncoming: Unknown packet subtype " << item->PacketSubType() << std::endl ; - } - delete item; - } - } - } - - return nhandled; -} - -// -----------------------------------------------------------------------------------// -// -------------------------------- Search handling. ------------------------------- // -// -----------------------------------------------------------------------------------// -// -void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item) -{ - Dbg3() << __PRETTY_FUNCTION__ << " " << *item << std::endl; - - // take a look at the item and test against inconsistent values - // - If the item destimation is - -#ifdef P3TURTLE_DEBUG - std::cerr << "Received search request from peer " << item->PeerId() << ": " << std::endl ; - item->print(std::cerr,0) ; -#endif - - uint32_t item_size = RsTurtleSerialiser().size(item); - - if(item_size > TURTLE_MAX_SEARCH_REQ_ACCEPTED_SERIAL_SIZE) - { - RsWarn() << __PRETTY_FUNCTION__ - << " Got a turtle search item with arbitrary large size from " - << item->PeerId() << " of size " << item_size << " and depth " - << item->depth << ". This is not allowed => dropping." - << std::endl; - return; - } - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - if(_search_requests_origins.size() > MAX_ALLOWED_SR_IN_CACHE) - { - RsWarn() << __PRETTY_FUNCTION__ << " More than " - << MAX_ALLOWED_SR_IN_CACHE << " search request in cache. " - << "A peer is probably trying to flood your network See " - "the depth charts to find him." << std::endl; - return; - } - - if( _search_requests_origins.find(item->request_id) != - _search_requests_origins.end() ) - { - /* If the item contains an already handled search request, give up. - * This happens when the same search request gets relayed by - * different peers */ - return; - } - } - - // Perform local search off-mutex,because this might call some services that are above turtle in the mutex chain. - - uint32_t search_result_count = 0; - uint32_t max_allowed_hits = TURTLE_SEARCH_RESULT_MAX_HITS_DEFAULT; - - if(item->PeerId() != _own_id) // is the request not coming from us? - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Request not from us. Performing local search" << std::endl ; -#endif - std::list search_results ; - - performLocalSearch(item,search_result_count,search_results,max_allowed_hits) ; - - for(auto it(search_results.begin());it!=search_results.end();++it) - { - (*it)->request_id = item->request_id ; - (*it)->PeerId(item->PeerId()) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << " sending back search result for request " << item->request_id << " to back to peer " << item->PeerId() << std::endl ; -#endif - sendItem(*it) ; - } - } - - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // This is a new request. Let's add it to the request map, and forward it to - // open peers. - - TurtleSearchRequestInfo& req( _search_requests_origins[item->request_id] ) ; - req.origin = item->PeerId() ; - req.time_stamp = time(NULL) ; - req.depth = item->depth ; - req.result_count = search_result_count; - req.keywords = item->GetKeywords() ; - req.service_id = item->serviceId() ; - req.max_allowed_hits = max_allowed_hits; - - // if enough has been sent back already, do not sarch further - -#ifdef P3TURTLE_DEBUG - std::cerr << " result count = " << req.result_count << std::endl; -#endif - if(req.result_count >= max_allowed_hits) - return ; - - // If search depth not too large, also forward this search request to all other peers. - // - // We use a random factor on the depth test that is biased by a mix between the session id and the partial tunnel id - // to scramble a possible search-by-depth attack. - // - bool random_bypass = (item->depth >= TURTLE_MAX_SEARCH_DEPTH && (((_random_bias ^ item->request_id)&0x7)==2)) ; - bool random_dshift = (item->depth == 1 && (((_random_bias ^ item->request_id)&0x7)==6)) ; - - if(item->depth < TURTLE_MAX_SEARCH_DEPTH || random_bypass) - { - std::set onlineIds ; - mServiceControl->getPeersConnected(_service_type, onlineIds); -#ifdef P3TURTLE_DEBUG - std::cerr << " Looking for online peers" << std::endl ; -#endif - - for(std::set::const_iterator it(onlineIds.begin());it!=onlineIds.end();++it) - { -// if(!mServiceControl->isPeerConnected(RS_SERVICE_TYPE_TURTLE,*it)) -// continue ; - - uint32_t linkType = mLinkMgr->getLinkType(*it); - - if ((linkType & RS_NET_CONN_SPEED_TRICKLE) || (linkType & RS_NET_CONN_SPEED_LOW)) // don't forward searches to slow link types (e.g relay peers)! - continue ; - - if(*it != item->PeerId()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding request to peer = " << *it << std::endl ; -#endif - // Copy current item and modify it. - RsTurtleSearchRequestItem *fwd_item = item->clone() ; - - // increase search depth, except in some rare cases, to prevent correlation between - // TR sniffing and friend names. The strategy is to not increase depth if the depth - // is 1: - // If B receives a TR of depth 1 from A, B cannot deduice that A is downloading the - // file, since A might have shifted the depth. - // - if(!random_dshift) - ++(fwd_item->depth) ; - - fwd_item->PeerId(*it) ; - - sendItem(fwd_item) ; - } - } - } -#ifdef P3TURTLE_DEBUG - else - std::cout << " Dropping this item, as search depth is " << item->depth << std::endl ; -#endif -} - -// This function should be removed in the future, when file search will also use generic search items. - -void p3turtle::performLocalSearch( - RsTurtleSearchRequestItem *item, uint32_t& req_result_count, - std::list& search_results, - uint32_t& max_allowed_hits ) -{ - Dbg3() << __PRETTY_FUNCTION__ << " " << item << std::endl; - - RsTurtleFileSearchRequestItem* ftsearch = - dynamic_cast(item); - - if(ftsearch != NULL) - { - performLocalSearch_files( - ftsearch, req_result_count, search_results, - max_allowed_hits ); - return ; - } - - RsTurtleGenericSearchRequestItem *gnsearch = dynamic_cast(item) ; - - if(gnsearch != NULL) - { - performLocalSearch_generic(gnsearch,req_result_count,search_results,max_allowed_hits) ; - return ; - } -} - -void p3turtle::performLocalSearch_generic(RsTurtleGenericSearchRequestItem *item, uint32_t& req_result_count, std::list& result,uint32_t& max_allowed_hits) -{ - unsigned char *search_result_data = NULL ; - uint32_t search_result_data_len = 0 ; - - RsTurtleClientService *client = NULL ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - auto it = _registered_services.find(item->service_id) ; - - if(it == _registered_services.end()) - return ; - - client = it->second ; - } - - if(client->receiveSearchRequest(item->search_data,item->search_data_len,search_result_data,search_result_data_len,max_allowed_hits)) - { - RsTurtleGenericSearchResultItem *result_item = new RsTurtleGenericSearchResultItem ; - - result_item->result_data = search_result_data ; - result_item->result_data_len = search_result_data_len ; - - result.push_back(result_item) ; - } -} - -void p3turtle::performLocalSearch_files( - RsTurtleFileSearchRequestItem *item, uint32_t& req_result_count, - std::list& result, - uint32_t& max_allowed_hits ) -{ - Dbg3() << __PRETTY_FUNCTION__ << " " << *item << std::endl; - - std::list initialResults ; - item->search(initialResults) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << initialResults.size() << " matches found." << std::endl ; -#endif - result.clear() ; - RsTurtleFTSearchResultItem *res_item = NULL ; - uint32_t item_size = 0 ; - - static const uint32_t RSTURTLE_MAX_SEARCH_RESPONSE_SIZE = 10000 ; - max_allowed_hits = TURTLE_SEARCH_RESULT_MAX_HITS_FILES; - - for(auto it(initialResults.begin());it!=initialResults.end();++it) - { - if(res_item == NULL) - { - res_item = new RsTurtleFTSearchResultItem ; - item_size = 0 ; - - result.push_back(res_item) ; - } - res_item->result.push_back(*it); - - // Let's chop search results items into several chunks of finite size to avoid exceeding streamer's capacity. - // - ++req_result_count ; // increase hit number for this particular search request. - - item_size += 8 /* size */ + it->hash.serial_size() + it->name.size() ; - - if(item_size > RSTURTLE_MAX_SEARCH_RESPONSE_SIZE || req_result_count >= max_allowed_hits) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Sending back chunk of size " << item_size << ", for " << res_item->result.size() << " elements." << std::endl ; -#endif - res_item = NULL ; // forces creation of a new item. - } - } - - Dbg3() << __PRETTY_FUNCTION__ << " found " << req_result_count << " results" - << std::endl; -} - -void p3turtle::handleSearchResult(RsTurtleSearchResultItem *item) -{ - // Filter out banned hashes from the result. - - RsTurtleFTSearchResultItem *ftsr_tmp = dynamic_cast(item) ; - - if(ftsr_tmp != NULL) - { - for(auto it(ftsr_tmp->result.begin());it!=ftsr_tmp->result.end();) - if( rsFiles->isHashBanned((*it).hash) ) - { - std::cerr << "(II) filtering out banned hash " << (*it).hash << " from turtle result " << std::hex << item->request_id << std::dec << std::endl; - it = ftsr_tmp->result.erase(it); - } - else - ++it; - - if(ftsr_tmp->result.empty()) - return ; - } - - // Then handle the result - - std::list > results_to_notify_off_mutex ; - - { - RS_STACK_MUTEX(mTurtleMtx); - // Find who actually sent the corresponding request. - // - std::map::iterator it = _search_requests_origins.find(item->request_id) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "Received search result:" << std::endl ; - item->print(std::cerr,0) ; -#endif - if(it == _search_requests_origins.end()) - { - // This is an error: how could we receive a search result corresponding to a search item we - // have forwarded but that it not in the list ?? - - std::cerr << __PRETTY_FUNCTION__ << ": search result for request " << std::hex << item->request_id << std::dec << " has no peer direction!" << std::endl ; - return ; - } - - // Is this result too old? - // Search Requests younger than SEARCH_REQUESTS_LIFE_TIME are kept in the cache, so that they are not duplicated if they bounce in the network - // Nevertheless results received for Search Requests older than SEARCH_REQUESTS_RESULT_TIME are considered obsolete and discarded - if (time(NULL) > it->second.time_stamp + SEARCH_REQUESTS_RESULT_TIME) - { -#ifdef P3TURTLE_DEBUG - RsDbg() << "TURTLE p3turtle::handleSearchResult Search Request is known, but result arrives too late, dropping"; -#endif - return; - } - - // Is this result's target actually ours ? - - if(it->second.origin == _own_id) - { - it->second.result_count += item->count() ; - - auto it2 = _registered_services.find(it->second.service_id) ; - - if(it2 != _registered_services.end()) - results_to_notify_off_mutex.push_back(std::make_pair(item,it2->second)) ; - else - std::cerr << "(EE) cannot find client service for ID " << std::hex << it->second.service_id << std::dec << ": search result item will be dropped." << std::endl; - } - else - { // Nope, so forward it back. -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding result back to " << it->second.origin << std::endl; -#endif - // We update the total count forwarded back, and chop it to TURTLE_SEARCH_RESULT_MAX_HITS. - - uint32_t n = item->count(); // not so good! - - if(it->second.result_count >= it->second.max_allowed_hits) - { - std::cerr << "(WW) exceeded turtle search result to forward. Req=" << std::hex << item->request_id << std::dec - << " already forwarded: " << it->second.result_count << ", max_allowed: " << it->second.max_allowed_hits << ": dropping item with " << n << " elements." << std::endl; - return ; - } - - if(it->second.result_count + n > it->second.max_allowed_hits) - { - for(uint32_t i=it->second.result_count + n; i>it->second.max_allowed_hits;--i) - item->pop() ; - - it->second.result_count = it->second.max_allowed_hits ; - } - else - it->second.result_count += n ; - - RsTurtleSearchResultItem *fwd_item = item->duplicate(); - - // Normally here, we should setup the forward adress, so that the owner's - // of the files found can be further reached by a tunnel. - - fwd_item->PeerId(it->second.origin) ; - - sendItem(fwd_item) ; - } - } // mTurtleMtx end - - // now we notify clients off-mutex. - - for(auto it(results_to_notify_off_mutex.begin());it!=results_to_notify_off_mutex.end();++it) - { - // Hack to use the old search result handling in ftServer. Normally ftServer should use the new method with serialized result. - -#warning make sure memory is correctly deleted here - RsTurtleFTSearchResultItem *ftsr = dynamic_cast(it->first) ; - - if(ftsr!=NULL) - { - ftServer *client = dynamic_cast((*it).second) ; - - if(!client) - { - std::cerr << "(EE) received turtle FT search result but the service is not a ftServer!!" << std::endl; - continue; - } - //RsServer::notify()->notifyTurtleSearchResult(ftsr->request_id,ftsr->result) ; - - client->ftReceiveSearchResult(ftsr); - continue ; - } - - RsTurtleGenericSearchResultItem *gnsr = dynamic_cast(it->first) ; - - if(gnsr!=NULL) - (*it).second->receiveSearchResult(gnsr->request_id,gnsr->result_data,gnsr->result_data_len) ; - } -} - -// -----------------------------------------------------------------------------------// -// --------------------------------- File Transfer. -------------------------------- // -// -----------------------------------------------------------------------------------// - -// Routing of turtle tunnel items in a generic manner. Most tunnel packets will -// use this function, except packets designed for contructing the tunnels and -// searching, namely TurtleSearchRequests/Results and OpenTunnel/TunnelOkItems -// -// Only packets coming from handleIncoming() end up here, so this function is -// able to catch the transiting traffic. -// -void p3turtle::routeGenericTunnelItem(RsTurtleGenericTunnelItem *item) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3Turtle: treating generic tunnel item:" << std::endl ; - item->print(std::cerr,1) ; -#endif - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // look for the tunnel id. - // - std::map::iterator it(_local_tunnels.find(item->tunnelId())) ; - - if(it == _local_tunnels.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: got file map with unknown tunnel id " << HEX_PRINT(item->tunnelId()) << std::endl ; -#endif - delete item; - return ; - } - - TurtleTunnel& tunnel(it->second) ; - - // Only file data transfer updates tunnels time_stamp field, to avoid maintaining tunnel that are incomplete. - if(item->shouldStampTunnel()) - tunnel.time_stamp = time(NULL) ; - - tunnel.transfered_bytes += RsTurtleSerialiser().size(item); - - if(item->PeerId() == tunnel.local_dst) - item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; - else if(item->PeerId() == tunnel.local_src) - item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_SERVER) ; - else - { - std::cerr << "(EE) p3turtle::routeGenericTunnelItem(): item mismatches tunnel src/dst ids." << std::endl; - std::cerr << "(EE) tunnel.local_src = " << tunnel.local_src << std::endl; - std::cerr << "(EE) tunnel.local_dst = " << tunnel.local_dst << std::endl; - std::cerr << "(EE) item->PeerId() = " << item->PeerId() << std::endl; - std::cerr << "(EE) This item is probably lost while tunnel route got redefined. Deleting this item." << std::endl ; - delete item ; - return ; - } - - // Let's figure out whether this packet is for us or not. - - if(item->PeerId() == tunnel.local_dst && tunnel.local_src != _own_id) //direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT && - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding generic item to peer " << tunnel.local_src << std::endl ; -#endif - item->PeerId(tunnel.local_src) ; - - _traffic_info_buffer.unknown_updn_Bps += RsTurtleSerialiser().size(item) ; - - // This has been disabled for compilation reasons. Not sure we actually need it. - // - //if(dynamic_cast(item) != NULL) - // item->setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FORWARD_FILE_DATA) ; - - sendItem(item) ; - return ; - } - - if(item->PeerId() == tunnel.local_src && tunnel.local_dst != _own_id) //direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER && - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding generic item to peer " << tunnel.local_dst << std::endl ; -#endif - item->PeerId(tunnel.local_dst) ; - - _traffic_info_buffer.unknown_updn_Bps += RsTurtleSerialiser().size(item); - - sendItem(item) ; - return ; - } - - // item is for us. Use the locked region to record the data. - - _traffic_info_buffer.data_dn_Bps += RsTurtleSerialiser().size(item); - } - - // The packet was not forwarded, so it is for us. Let's treat it. - // This is done off-mutex, to avoid various deadlocks - // - - handleRecvGenericTunnelItem(item) ; - - delete item ; -} - -void p3turtle::handleRecvGenericTunnelItem(RsTurtleGenericTunnelItem *item) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3Turtle: received Generic tunnel item:" << std::endl ; - item->print(std::cerr,1) ; -#endif - RsFileHash hash ; - RsPeerId vpid ; - RsTurtleClientService *service ; - - if(!getTunnelServiceInfo(item->tunnelId(),vpid,hash,service)) - return ; - - service->receiveTurtleData(item,hash,vpid,item->travelingDirection()) ; -} - -bool p3turtle::getTunnelServiceInfo(TurtleTunnelId tunnel_id,RsPeerId& vpid,RsFileHash& hash,RsTurtleClientService *& service) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it2(_local_tunnels.find(tunnel_id)) ; - - if(it2 == _local_tunnels.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: unknown tunnel id " << std::hex << tunnel_id << std::dec << std::endl ; -#endif - return false; - } - - TurtleTunnel& tunnel(it2->second) ; - -#ifdef P3TURTLE_DEBUG - assert(!tunnel.hash.isNull()) ; - - std::cerr << " This is an endpoint for this file map." << std::endl ; - std::cerr << " Forwarding data to the multiplexer." << std::endl ; - std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; -#endif - // We should check that there is no backward call to the turtle router! - // - vpid = tunnel.vpid ; - hash = tunnel.hash ; - - // Now sort out the case of client vs. server side items. - // - if(tunnel.local_src == _own_id) - { - std::map::const_iterator it = _incoming_file_hashes.find(hash) ; - - if(it == _incoming_file_hashes.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::handleRecvGenericTunnelItem(): hash " << hash << " for client side tunnel endpoint " << std::hex << tunnel_id << std::dec << " has been removed (probably a late response)! Dropping the item. " << std::endl; -#endif - return false; - } - - service = it->second.service ; - } - else if(tunnel.local_dst == _own_id) - { - std::map::const_iterator it = _outgoing_tunnel_client_services.find(tunnel_id) ; - - if(it == _outgoing_tunnel_client_services.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::handleRecvGenericTunnelItem(): hash " << tunnel.hash << " for server side tunnel endpoint " << std::hex << tunnel_id << std::dec << " has been removed (probably a late response)! Dropping the item. " << std::endl; -#endif - return false; - } - - service = it->second; - } - else - { - std::cerr << "p3turtle::handleRecvGenericTunnelItem(): hash " << hash << " for tunnel " << std::hex << it2->first << std::dec << ". Tunnel is not a end-point or a starting tunnel!! This is a serious consistency error." << std::endl; - return false ; - } - - return true ; -} -// Send a data request into the correct tunnel for the given file hash -// -void p3turtle::sendTurtleData(const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem *item) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // get the proper tunnel for this file hash and peer id. - std::map::const_iterator it(_virtual_peers.find(virtual_peer_id)) ; - - if(it == _virtual_peers.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::senddataRequest: cannot find virtual peer " << virtual_peer_id << " in VP list." << std::endl ; -#endif - delete item ; - return ; - } - TurtleTunnelId tunnel_id = it->second ; - std::map::iterator it2( _local_tunnels.find(tunnel_id) ) ; - - if(it2 == _local_tunnels.end()) - { - std::cerr << "p3turtle::client asked to send a packet through tunnel that has previously been deleted. Not a big issue unless it happens in masses." << std::endl; - delete item ; - return ; - } - TurtleTunnel& tunnel(it2->second) ; - - item->tunnel_id = tunnel_id ; // we should randomly select a tunnel, or something more clever. - - uint32_t ss = RsTurtleSerialiser().size(item); - - if(item->shouldStampTunnel()) - tunnel.time_stamp = time(NULL) ; - - tunnel.transfered_bytes += ss ; - - if(tunnel.local_src == _own_id) - { - item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_SERVER) ; - item->PeerId(tunnel.local_dst) ; - _traffic_info_buffer.data_dn_Bps += ss ; - } - else if(tunnel.local_dst == _own_id) - { - item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; - item->PeerId(tunnel.local_src) ; - _traffic_info_buffer.data_up_Bps += ss ; - } - else - { - std::cerr << "p3Turtle::sendTurtleData(): asked to send a packet into a tunnel that is not registered. Dropping packet." << std::endl ; - delete item ; - return ; - } - -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: sending service packet to virtual peer id " << virtual_peer_id << ", hash=0x" << tunnel.hash << ", tunnel = " << HEX_PRINT(item->tunnel_id) << ", next peer=" << tunnel.local_dst << std::endl ; -#endif - sendItem(item) ; -} - -bool p3turtle::isTurtlePeer(const RsPeerId& peer_id) const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - return _virtual_peers.find(peer_id) != _virtual_peers.end() ; -} - -RsPeerId p3turtle::getTurtlePeerId(TurtleTunnelId tid) const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - std::map::const_iterator it( _local_tunnels.find(tid) ) ; - -#ifdef P3TURTLE_DEBUG - assert(it!=_local_tunnels.end()) ; - assert(!it->second.vpid.isNull()) ; -#endif - - return it->second.vpid ; -} - -bool p3turtle::isOnline(const RsPeerId& peer_id) const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // we could do something mre clever here... - // - return _virtual_peers.find(peer_id) != _virtual_peers.end() ; -} - - -// -----------------------------------------------------------------------------------// -// -------------------------------- Tunnel handling. ------------------------------- // -// -----------------------------------------------------------------------------------// -// - -TurtleRequestId p3turtle::diggTunnel(const TurtleFileHash& hash) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "DiggTunnel: performing tunnel request. OwnId = " << _own_id << " for hash=" << hash << std::endl ; -#endif - TurtleRequestId id = generateRandomRequestId() ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - // Store the request id, so that we can find the hash back when we get the response. - // - _incoming_file_hashes[hash].last_request = id ; - _incoming_file_hashes[hash].last_digg_time = time(NULL) ; - } - - // Form a tunnel request packet that simulates a request from us. - // - RsTurtleOpenTunnelItem *item = new RsTurtleOpenTunnelItem ; - - item->PeerId(_own_id) ; - item->file_hash = hash ; - item->request_id = id ; - item->partial_tunnel_id = generatePersonalFilePrint(hash,_random_bias,true) ; - item->depth = 0 ; - - // send it - -#ifdef TUNNEL_STATISTICS - TS_request_bounces[item->request_id].clear() ; // forces initialization -#endif - handleTunnelRequest(item) ; - delete item ; - - return id ; -} - -void p3turtle::handleTunnelRequest(RsTurtleOpenTunnelItem *item) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "Received tunnel request from peer " << item->PeerId() << ": " << std::endl ; - item->print(std::cerr,0) ; -#endif - - // check first if the hash is in the ban list. If so, drop the request. - - if(rsFiles->isHashBanned(item->file_hash)) - { - std::cerr << "(II) Rejecting tunnel request to ban hash " << item->file_hash << std::endl; - return ; - } - -#ifdef TUNNEL_STATISTICS - if(TS_request_bounces.find(item->request_id) != TS_request_bounces.end()) - TS_request_bounces[item->request_id].push_back(time(NULL)) ; -#endif - // TR forwarding. We must pay attention not to flood the network. The policy is to force a statistical behavior - // according to the followin grules: - // - below a number of tunnel request forwards per second MAX_TR_FORWARD_PER_SEC, we keep the traffic - // - if we get close to that limit, we drop long tunnels first with a probability that is larger for long tunnels - // - // Variables involved: - // distance_to_maximum : in [0,inf] is the proportion of the current up TR speed with respect to the maximum allowed speed. This is estimated - // as an average between the average number of TR over the 60 last seconds and the current TR up speed. - // corrected_distance : in [0,inf] is a squeezed version of distance: small values become very small and large values become very large. - // depth_peer_probability : basic probability of forwarding when the speed limit is reached. - // forward_probability : final probability of forwarding the packet, per peer. - // - // When the number of peers increases, the speed limit is reached faster, but the behavior per peer is the same. - // - - float forward_probability ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _traffic_info_buffer.tr_dn_Bps += RsTurtleSerialiser().size(item); - - float distance_to_maximum = std::min(100.0f,_traffic_info.tr_up_Bps/(float)(TUNNEL_REQUEST_PACKET_SIZE*_max_tr_up_rate)) ; - float corrected_distance = pow(distance_to_maximum,DISTANCE_SQUEEZING_POWER) ; - forward_probability = pow(depth_peer_probability[std::min((uint16_t)6,item->depth)],corrected_distance) ; -#ifdef P3TURTLE_DEBUG - std::cerr << "Forwarding probability: depth=" << item->depth << ", distance to max speed=" << distance_to_maximum << ", corrected=" << corrected_distance << ", prob.=" << forward_probability << std::endl; -#endif - } - - // If the item contains an already handled tunnel request, give up. This - // happens when the same tunnel request gets relayed by different peers. We - // have to be very careful here, not to call ftController while mTurtleMtx is - // locked. - // - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _tunnel_requests_origins.find(item->request_id) ; - - if(it != _tunnel_requests_origins.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " This is a bouncing request. Ignoring and deleting item." << std::endl ; -#endif - return ; - } - // This is a new request. Let's add it to the request map, and forward - // it to open peers, while the mutex is locked, so no-one can trigger the - // lock before the data is consistent. - - TurtleTunnelRequestInfo& req( _tunnel_requests_origins[item->request_id] ) ; - req.origin = item->PeerId() ; - req.time_stamp = time(NULL) ; - req.depth = item->depth ; - -#ifdef TUNNEL_STATISTICS - std::cerr << "storing tunnel request " << (void*)(item->request_id) << std::endl ; - - ++TS_tunnel_length[item->depth] ; - TS_request_time_stamps[item->file_hash].push_back(std::pair(time(NULL),item->request_id)) ; -#endif - } - - // If it's not for us, perform a local search. If something found, forward the search result back. - // We're off-mutex here. - - bool found = false ; - //std::string info ; - RsTurtleClientService *service = NULL ; - - if(item->PeerId() != _own_id) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Request not from us. Performing local search" << std::endl ; -#endif - found = performLocalHashSearch(item->file_hash,item->PeerId(),service) ; - } - - { - if(found) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Local hash found. Sending tunnel ok to origin (" << item->PeerId() << ")." << std::endl ; -#endif - // Send back tunnel ok to the same guy - // - RsTurtleTunnelOkItem *res_item = new RsTurtleTunnelOkItem ; - TurtleVirtualPeerId vpid ; - - res_item->request_id = item->request_id ; - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - res_item->tunnel_id = item->partial_tunnel_id ^ generatePersonalFilePrint(item->file_hash,_random_bias,false) ; - - res_item->PeerId(item->PeerId()) ; - - TurtleTunnelId t_id = res_item->tunnel_id ; // save it because sendItem deletes the item - - sendItem(res_item) ; - - // Note in the tunnels list that we have an ending tunnel here. - TurtleTunnel tt ; - tt.local_src = item->PeerId() ; - tt.hash = item->file_hash ; - tt.local_dst = _own_id ; // this means us - tt.time_stamp = time(NULL) ; - tt.transfered_bytes = 0 ; - tt.speed_Bps = 0.0f ; - - _local_tunnels[t_id] = tt ; - - // We add a virtual peer for that tunnel+hash combination. - // - locked_addDistantPeer(item->file_hash,t_id) ; - - // Store some info string about the tunnel. - // - _outgoing_tunnel_client_services[t_id] = service ; - - vpid = _local_tunnels[t_id].vpid; - } - - // Notify the client service that there's a new virtual peer id available as a client. - // - service->addVirtualPeer(item->file_hash,vpid,RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; - - // We return straight, because when something is found, there's no need to digg a tunnel further. - // - - return ; - } -#ifdef P3TURTLE_DEBUG - else - std::cerr << " No hash found locally, or local file not allowed for distant peers. Forwarding. " << std::endl ; -#endif - } - - // If search depth not too large, also forward this search request to all other peers. - // - bool random_bypass = (item->depth >= TURTLE_MAX_SEARCH_DEPTH && (((_random_bias ^ item->partial_tunnel_id)&0x7)==2)) ; - bool random_dshift = (item->depth == 1 && (((_random_bias ^ item->partial_tunnel_id)&0x7)==6)) ; - - // Multi-tunneling trick: consistently perturbate the half-tunnel id: - // - the tunnel id will now be unique for a given route - // - allows a better balance of bandwidth for a given transfer - // - avoid the waste of items that get lost when re-routing a tunnel - -#ifdef P3TURTLE_DEBUG - std::cerr << "Perturbating partial tunnel id. Original=" << std::hex << item->partial_tunnel_id ; -#endif - item->partial_tunnel_id = generatePersonalFilePrint(item->file_hash,item->partial_tunnel_id ^ _random_bias,true) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << " new=" << item->partial_tunnel_id << std::dec << std::endl; -#endif - - if(item->depth < TURTLE_MAX_SEARCH_DEPTH || random_bypass) - { - std::set onlineIds ; - mServiceControl->getPeersConnected(_service_type, onlineIds); - -// for(std::set::iterator it(onlineIds.begin());it!=onlineIds.end();) -// if(!mServiceControl->isPeerConnected(RS_SERVICE_PERM_TURTLE,*it)) -// { -// std::set::iterator tmp = it++ ; -// onlineIds.erase(tmp) ; -// } -// else -// ++it ; - - int nb_online_ids = onlineIds.size() ; - - if(forward_probability * nb_online_ids < 1.0f && nb_online_ids > 0) - { - forward_probability = 1.0f / nb_online_ids ; - - // Setting forward_probability to 1/nb_online_ids forces at most one TR up per TR dn. But if we are overflooded by - // TR dn, we still need to control them to avoid flooding the pqiHandler outqueue. So we additionally moderate the - // forward probability so as to reduct the output rate accordingly. - // - if(_traffic_info.tr_dn_Bps / (float)TUNNEL_REQUEST_PACKET_SIZE > _max_tr_up_rate) - forward_probability *= _max_tr_up_rate*TUNNEL_REQUEST_PACKET_SIZE / (float)_traffic_info.tr_dn_Bps ; - } - -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding tunnel request: Looking for online peers" << std::endl ; -#endif - - for(std::set::const_iterator it(onlineIds.begin());it!=onlineIds.end();++it) - { - uint32_t linkType = mLinkMgr->getLinkType(*it); - - if ((linkType & RS_NET_CONN_SPEED_TRICKLE) || (linkType & RS_NET_CONN_SPEED_LOW)) // don't forward tunnel requests to slow link types (e.g relay peers)! - continue ; - - if(*it != item->PeerId() && RSRandom::random_f32() <= forward_probability) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding request to peer = " << *it << std::endl ; -#endif - // Copy current item and modify it. - RsTurtleOpenTunnelItem *fwd_item = new RsTurtleOpenTunnelItem(*item) ; - - // increase search depth, except in some rare cases, to prevent correlation between - // TR sniffing and friend names. The strategy is to not increase depth if the depth - // is 1: - // If B receives a TR of depth 1 from A, B cannot deduice that A is downloading the - // file, since A might have shifted the depth. - // - if(!random_dshift) - ++(fwd_item->depth) ; // increase tunnel depth - - fwd_item->PeerId(*it) ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _traffic_info_buffer.tr_up_Bps += RsTurtleSerialiser().size(fwd_item); - } - - sendItem(fwd_item) ; - } - } - } -#ifdef P3TURTLE_DEBUG - else - std::cout << " Dropping this item, as tunnel depth is " << item->depth << std::endl ; -#endif -} - -void p3turtle::handleTunnelResult(RsTurtleTunnelOkItem *item) -{ - bool new_tunnel = false ; - TurtleFileHash new_hash ; - RsPeerId new_vpid ; - RsTurtleClientService *service = NULL ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // Find who actually sent the corresponding turtle tunnel request. - // - std::map::iterator it = _tunnel_requests_origins.find(item->request_id) ; -#ifdef P3TURTLE_DEBUG - std::cerr << "Received tunnel result:" << std::endl ; - item->print(std::cerr,0) ; -#endif - - if(it == _tunnel_requests_origins.end()) - { - // This is an error: how could we receive a tunnel result corresponding to a tunnel item we - // have forwarded but that it not in the list ?? Actually that happens, when tunnel requests - // get too old, before the tunnelOk item gets back. But this is quite unusual. - -#ifdef P3TURTLE_DEBUG - std::cerr << __PRETTY_FUNCTION__ << ": tunnel result has no peer direction!" << std::endl ; -#endif - return ; - } - if(it->second.responses.find(item->tunnel_id) != it->second.responses.end()) - { - std::cerr << "p3turtle: ERROR: received a tunnel response twice. That should not happen." << std::endl; - return ; - } - else - it->second.responses.insert(item->tunnel_id) ; - - // store tunnel info. - bool found = (_local_tunnels.find(item->tunnel_id) != _local_tunnels.end()) ; - TurtleTunnel& tunnel(_local_tunnels[item->tunnel_id]) ; - - if(found) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "Tunnel id " << HEX_PRINT(item->tunnel_id) << " is already there. Not storing." << std::endl ; -#endif - } - else - { - tunnel.local_src = it->second.origin ; - tunnel.local_dst = item->PeerId() ; - tunnel.hash.clear() ; - tunnel.time_stamp = time(NULL) ; - tunnel.transfered_bytes = 0 ; - tunnel.speed_Bps = 0.0f ; - -#ifdef P3TURTLE_DEBUG - std::cerr << " storing tunnel info. src=" << tunnel.local_src << ", dst=" << tunnel.local_dst << ", id=" << item->tunnel_id << std::endl ; -#endif - } - - // Is this result too old? - // Tunnel Requests younger than TUNNEL_REQUESTS_LIFE_TIME are kept in the cache, so that they are not duplicated if they bounce in the network - // Nevertheless results received for Tunnel Requests older than TUNNEL_REQUESTS_RESULT_TIME are considered obsolete and discarded - if (time(NULL) > it->second.time_stamp + TUNNEL_REQUESTS_RESULT_TIME) - { -#ifdef P3TURTLE_DEBUG - RsDbg() << "TURTLE p3turtle::handleTunnelResult Tunnel Request is known, but result arrives too late, dropping"; -#endif - return; - } - - // Is this result's target actually ours ? - - if(it->second.origin == _own_id) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Tunnel starting point. Storing id=" << HEX_PRINT(item->tunnel_id) << " for hash (unknown) and tunnel request id " << it->second.origin << std::endl; -#endif - // Tunnel is ending here. Add it to the list of tunnels for the given hash. - - // 1 - find which file hash issued this request. This is not costly, - // because there is not too much file hashes to be active at a time, - // and this mostly prevents from sending the hash back in the tunnel. - -#ifdef P3TURTLE_DEBUG - bool ext_found = false ; -#endif - for(std::map::iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) - if(it->second.last_request == item->request_id) - { -#ifdef P3TURTLE_DEBUG - ext_found = true ; -#endif - - { - // add the tunnel uniquely - bool found = false ; - - for(unsigned int j=0;jsecond.tunnels.size();++j) - if(it->second.tunnels[j] == item->tunnel_id) - found = true ; - - if(!found) - it->second.tunnels.push_back(item->tunnel_id) ; - - tunnel.hash = it->first ; // because it's a local tunnel - - // Adds a virtual peer to the list of online peers. - // We do this later, because of the mutex protection. - // - new_tunnel = true ; - new_hash = it->first ; - service = it->second.service ; - - locked_addDistantPeer(new_hash,item->tunnel_id) ; - new_vpid = _local_tunnels[item->tunnel_id].vpid ; // save it for off-mutex usage. - } - } -#ifdef P3TURTLE_DEBUG - if(!ext_found) - std::cerr << "p3turtle: error. Could not find hash that emmitted tunnel request " << reinterpret_cast(item->tunnel_id) << std::endl ; -#endif - } - else - { // Nope, forward it back. -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding result back to " << it->second.origin << std::endl; -#endif - RsTurtleTunnelOkItem *fwd_item = new RsTurtleTunnelOkItem(*item) ; // copy the item - fwd_item->PeerId(it->second.origin) ; - - sendItem(fwd_item) ; - } - } - - // A new tunnel has been created. Add the corresponding virtual peer to the list, and - // notify the file transfer controller for the new file source. This should be done off-mutex - // so we deported this code here. - // - if(new_tunnel && service != NULL) - service->addVirtualPeer(new_hash,new_vpid,RsTurtleGenericTunnelItem::DIRECTION_SERVER) ; -} - -// -----------------------------------------------------------------------------------// -// ------------------------------ IO with libretroshare ----------------------------// -// -----------------------------------------------------------------------------------// -// - - -void RsTurtleStringSearchRequestItem::search(std::list& result) const -{ - /* call to core */ - std::list initialResults; - std::list words ; - - // to do: split search string into words. - words.push_back(match_string) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "Performing rsFiles->search()" << std::endl ; -#endif - // now, search! - rsFiles->SearchKeywords(words, initialResults,RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_SEARCHABLE,PeerId()); - -#ifdef P3TURTLE_DEBUG - std::cerr << initialResults.size() << " matches found." << std::endl ; -#endif - result.clear() ; - - for(std::list::const_iterator it(initialResults.begin());it!=initialResults.end();++it) - { - // retain only file type - if (it->type == DIR_TYPE_DIR) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Skipping directory " << it->name << std::endl ; -#endif - continue; - } - - TurtleFileInfo i ; - i.hash = it->hash ; - i.size = it->size ; - i.name = it->name ; - - result.push_back(i) ; - } -} -void RsTurtleRegExpSearchRequestItem::search(std::list& result) const -{ - /* call to core */ - std::list initialResults; - - // to do: split search string into words. - RsRegularExpression::Expression *exp = RsRegularExpression::LinearizedExpression::toExpr(expr) ; - - if(exp == NULL) - return ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "Local search on exp: " << exp->toStdString() << std::endl; -#endif - - // now, search! - rsFiles->SearchBoolExp(exp,initialResults,RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_SEARCHABLE,PeerId()); - - result.clear() ; - - for(std::list::const_iterator it(initialResults.begin());it!=initialResults.end();++it) - { - // retain only file type - if (it->type == DIR_TYPE_DIR) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Skipping directory " << it->name << std::endl ; -#endif - continue; - } - TurtleFileInfo i ; - i.hash = it->hash ; - i.size = it->size ; - i.name = it->name ; - - result.push_back(i) ; - } - delete exp ; -} - -TurtleRequestId p3turtle::turtleSearch(const std::string& string_to_match) -{ - // generate a new search id. - - TurtleRequestId id = generateRandomRequestId() ; - - // Form a request packet that simulates a request from us. - // - RsTurtleStringSearchRequestItem *item = new RsTurtleStringSearchRequestItem ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "performing search. OwnId = " << _own_id << std::endl ; -#endif - - item->PeerId(_own_id) ; - item->match_string = string_to_match ; - item->request_id = id ; - item->depth = 0 ; - - // send it - - handleSearchRequest(item) ; - - delete item ; - - return id ; -} -TurtleRequestId p3turtle::turtleSearch(const RsRegularExpression::LinearizedExpression& expr) -{ - // generate a new search id. - - TurtleRequestId id = generateRandomRequestId() ; - - // Form a request packet that simulates a request from us. - // - RsTurtleRegExpSearchRequestItem *item = new RsTurtleRegExpSearchRequestItem ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "performing search. OwnId = " << _own_id << std::endl ; -#endif - - item->PeerId(_own_id) ; - item->expr = expr ; - item->request_id = id ; - item->depth = 0 ; - - // send it - - handleSearchRequest(item) ; - - delete item ; - - return id ; -} - -TurtleRequestId p3turtle::turtleSearch(unsigned char *search_bin_data,uint32_t search_bin_data_len,RsTurtleClientService *client_service) -{ - // generate a new search id. - - TurtleRequestId id = generateRandomRequestId() ; - - // Form a request packet that simulates a request from us. - // - RsTurtleGenericSearchRequestItem item ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "performing search. OwnId = " << _own_id << std::endl ; -#endif - - item.PeerId(_own_id) ; - item.service_id = client_service->serviceId(); - item.search_data = search_bin_data ; - item.search_data_len = search_bin_data_len ; - item.request_id = id ; - item.depth = 0 ; - - // send it - - handleSearchRequest(&item) ; - - return id ; -} - -void p3turtle::monitorTunnels(const RsFileHash& hash,RsTurtleClientService *client_service,bool allow_multi_tunnels) -{ - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // First, check if the hash is tagged for removal (there's a delay) - - if(_hashes_to_remove.erase(hash) > 0) - { -#ifdef P3TURTLE_DEBUG - TURTLE_DEBUG() << "p3turtle: File hash " << hash << " Was scheduled for removal. Canceling the removal." << std::endl ; -#endif - } - - // Then, check if the hash is already there - // - if(_incoming_file_hashes.find(hash) != _incoming_file_hashes.end()) // download already asked. - { -#ifdef P3TURTLE_DEBUG - TURTLE_DEBUG() << "p3turtle: File hash " << hash << " already in pool. Returning." << std::endl ; -#endif - return ; - } -#ifdef P3TURTLE_DEBUG - TURTLE_DEBUG() << "p3turtle: Received order for turtle download fo hash " << hash << std::endl ; -#endif - - // No tunnels at start, but this triggers digging new tunnels. - // - _incoming_file_hashes[hash].tunnels.clear(); - _incoming_file_hashes[hash].use_aggressive_mode = allow_multi_tunnels ; - - // also should send associated request to the file transfer module. - _incoming_file_hashes[hash].last_digg_time = RSRandom::random_u32()%10 ; - _incoming_file_hashes[hash].service = client_service ; - } -} - - -// RsTurtleGxsSearchResultGroupSummaryItem *gxs_sr_gs = dynamic_cast(item) ; -// -// if(gxs_sr_gs != NULL) -// { -// RsServer::notify()->notifyTurtleSearchResult(gxs_sr_gs->request_id,gxs_sr_gs->result) ; -// return ; -// } -// RsTurtleGxsSearchResultGroupDataItem *gxs_sr_gd = dynamic_cast(item) ; -// -// if(gxs_sr_gd != NULL) -// { -//#warning MISSING CODE HERE TO HANDLE ENCRYPTED INCOMING GROUP DATA. -// //RsServer::notify()->notifyTurtleSearchResult(gxs_sr_gd->request_id,gxs_sr_gd->encrypted_nxs_group) ; -// return ; -// } - -/// Warning: this function should never be called while the turtle mutex is locked. -/// Otherwize this is a possible source of cross-lock with the File mutex. -// -bool p3turtle::performLocalHashSearch(const TurtleFileHash& hash,const RsPeerId& peer_id,RsTurtleClientService *& service) -{ - std::map client_map ; - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - if(_registered_services.empty()) - { - std::cerr << "Turtle router has no services registered. Tunnel requests cannot be handled." << std::endl; - return false ; - } - - client_map = _registered_services ; - } - - for(auto it(client_map.begin());it!=client_map.end();++it) - if( (*it).second->handleTunnelRequest(hash,peer_id)) - { - service = it->second ; - return true ; - } - - return false ; -} - - -void p3turtle::registerTunnelService(RsTurtleClientService *service) -{ - std::cerr << "p3turtle: registered new tunnel service with ID=" << std::hex << service->serviceId() << std::dec << " and pointer " << (void*)service << std::endl; - - _registered_services[service->serviceId()] = service ; - _serialiser->registerClientService(service) ; -} - -static std::string printFloatNumber(float num,bool friendly=false) -{ - if(friendly) - { - char tmp[100] ; - std::string units[4] = { "B/s","KB/s","MB/s","GB/s" } ; - - int k=0 ; - while(num >= 800.0f && k<4) - num /= 1024.0f,++k; - - sprintf(tmp,"%3.2f %s",num,units[k].c_str()) ; - return std::string(tmp) ; - } - else - { - std::string out ; - rs_sprintf(out, "%g", num) ; - return out ; - } -} -static std::string printNumber(uint64_t num,bool hex=false) -{ - if(hex) - { - char tmp[100] ; - - if(num < (((uint64_t)1)<<32)) - sprintf(tmp,"%08x", uint32_t(num)) ; - else - sprintf(tmp,"%08x%08x", uint32_t(num >> 32),uint32_t(num & ( (((uint64_t)1)<<32)-1 ))) ; - return std::string(tmp) ; - } - else - { - std::string out ; - rs_sprintf(out, "%lld", num) ; - return out ; - } -} - -void p3turtle::getTrafficStatistics(TurtleTrafficStatisticsInfo& info) const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - info = _traffic_info ; - - float distance_to_maximum = std::min(100.0f,info.tr_up_Bps/(float)(TUNNEL_REQUEST_PACKET_SIZE*_max_tr_up_rate)) ; - info.forward_probabilities.clear() ; - - std::set onlineIds ; - mServiceControl->getPeersConnected(_service_type, onlineIds); - - int nb_online_ids = onlineIds.size() ; - - for(int i=0;i<=6;++i) - { - float corrected_distance = pow(distance_to_maximum,DISTANCE_SQUEEZING_POWER) ; - float forward_probability = pow(depth_peer_probability[i],corrected_distance) ; - - if(forward_probability * nb_online_ids < 1.0f && nb_online_ids > 0) - { - forward_probability = 1.0f / nb_online_ids ; - - if(_traffic_info.tr_dn_Bps / (float)TUNNEL_REQUEST_PACKET_SIZE > _max_tr_up_rate) - forward_probability *= _max_tr_up_rate*TUNNEL_REQUEST_PACKET_SIZE / (float)_traffic_info.tr_dn_Bps ; - } - - info.forward_probabilities.push_back(forward_probability) ; - } -} - -std::string p3turtle::getPeerNameForVirtualPeerId(const RsPeerId& virtual_peer_id) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - std::string name = "unknown"; - std::map::const_iterator it(_virtual_peers.find(virtual_peer_id)) ; - if(it != _virtual_peers.end()) - { - std::map::iterator it2( _local_tunnels.find(it->second) ) ; - if(it2 != _local_tunnels.end()) - { - if(it2->second.local_src == _own_id) - mLinkMgr->getPeerName(it2->second.local_dst,name); - else - mLinkMgr->getPeerName(it2->second.local_src,name); - } - } - return name; -} - -bool p3turtle::encryptData(const unsigned char *clear_data,uint32_t clear_data_size,uint8_t *encryption_master_key,RsTurtleGenericDataItem *& encrypted_item) -{ - unsigned char *encrypted_data = NULL ; - uint32_t encrypted_data_len = 0 ; - - if(!librs::crypto::encryptAuthenticateData(clear_data,clear_data_size,encryption_master_key,encrypted_data,encrypted_data_len)) - { - delete encrypted_item ; - return false ; - } - encrypted_item = new RsTurtleGenericDataItem ; - - encrypted_item->data_bytes = encrypted_data ; - encrypted_item->data_size = encrypted_data_len ; - return true; -} - -bool p3turtle::decryptItem(const RsTurtleGenericDataItem* encrypted_item, uint8_t *encryption_master_key, unsigned char *& decrypted_data, uint32_t& decrypted_data_size) -{ - return librs::crypto::decryptAuthenticateData((unsigned char*)encrypted_item->data_bytes,encrypted_item->data_size,encryption_master_key,decrypted_data,decrypted_data_size); -} - -void p3turtle::getInfo( std::vector >& hashes_info, - std::vector >& tunnels_info, - std::vector& search_reqs_info, - std::vector& tunnel_reqs_info) const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - rstime_t now = time(NULL) ; - - hashes_info.clear() ; - - for(std::map::const_iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) - { - hashes_info.push_back(std::vector()) ; - - std::vector& hashes(hashes_info.back()) ; - - hashes.push_back(it->first.toStdString()) ; - //hashes.push_back(it->second.name) ; - hashes.push_back("Name not available") ; - hashes.push_back(printNumber(it->second.tunnels.size())) ; - //hashes.push_back(printNumber(now - it->second.time_stamp)+" secs ago") ; - } - - tunnels_info.clear(); - - for(std::map::const_iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it) - { - tunnels_info.push_back(std::vector()) ; - std::vector& tunnel(tunnels_info.back()) ; - - tunnel.push_back(printNumber(it->first,true)) ; - - std::string name; - if(mLinkMgr->getPeerName(it->second.local_src,name)) - tunnel.push_back(name) ; - else - tunnel.push_back(it->second.local_src.toStdString()) ; - - if(mLinkMgr->getPeerName(it->second.local_dst,name)) - tunnel.push_back(name) ; - else - tunnel.push_back(it->second.local_dst.toStdString()); - - tunnel.push_back(it->second.hash.toStdString()) ; - tunnel.push_back(printNumber(now-it->second.time_stamp) + " secs ago") ; - tunnel.push_back(printFloatNumber(it->second.speed_Bps,false)) ; // - } - - search_reqs_info.clear(); - - for(std::map::const_iterator it(_search_requests_origins.begin());it!=_search_requests_origins.end();++it) - { - TurtleSearchRequestDisplayInfo info ; - - info.request_id = it->first ; - info.source_peer_id = it->second.origin ; - info.age = now - it->second.time_stamp ; - info.depth = it->second.depth ; - info.keywords = it->second.keywords ; - info.hits = it->second.result_count ; - - search_reqs_info.push_back(info) ; - } - - tunnel_reqs_info.clear(); - - for(std::map::const_iterator it(_tunnel_requests_origins.begin());it!=_tunnel_requests_origins.end();++it) - { - TurtleTunnelRequestDisplayInfo info ; - - info.request_id = it->first ; - info.source_peer_id = it->second.origin ; - info.age = now - it->second.time_stamp ; - info.depth = it->second.depth ; - - tunnel_reqs_info.push_back(info) ; - } -} - -#ifdef P3TURTLE_DEBUG -void p3turtle::dumpState() -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - rstime_t now = time(NULL) ; - - std::cerr << std::endl ; - std::cerr << "********************** Turtle router dump ******************" << std::endl ; - std::cerr << " Active incoming file hashes: " << _incoming_file_hashes.size() << std::endl ; - for(std::map::const_iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) - { - std::cerr << " hash=0x" << it->first << ", tunnel ids =" ; - for(std::vector::const_iterator it2(it->second.tunnels.begin());it2!=it->second.tunnels.end();++it2) - std::cerr << " " << HEX_PRINT(*it2) ; - //std::cerr << ", last_req=" << (void*)it->second.last_request << ", time_stamp = " << it->second.time_stamp << "(" << now-it->second.time_stamp << " secs ago)" << std::endl ; - } - std::cerr << " Active outgoing file hashes: " << _outgoing_tunnel_client_services.size() << std::endl ; - for(std::map::const_iterator it(_outgoing_tunnel_client_services.begin());it!=_outgoing_tunnel_client_services.end();++it) - std::cerr << " TID=0x" << it->first << std::endl ; - - std::cerr << " Local tunnels:" << std::endl ; - for(std::map::const_iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it) - std::cerr << " " << HEX_PRINT(it->first) << ": from=" - << it->second.local_src << ", to=" << it->second.local_dst - << ", hash=0x" << it->second.hash << ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp << " secs ago)" - << ", peer id =" << it->second.vpid << std::endl ; - - std::cerr << " buffered request origins: " << std::endl ; - std::cerr << " Search requests: " << _search_requests_origins.size() << std::endl ; - - for(std::map::const_iterator it(_search_requests_origins.begin());it!=_search_requests_origins.end();++it) - std::cerr << " " << HEX_PRINT(it->first) << ": from=" << it->second.origin - << ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp - << " secs ago)" - << it->second.result_count << " hits" << std::endl ; - - std::cerr << " Tunnel requests: " << _tunnel_requests_origins.size() << std::endl ; - for(std::map::const_iterator it(_tunnel_requests_origins.begin());it!=_tunnel_requests_origins.end();++it) - std::cerr << " " << HEX_PRINT(it->first) << ": from=" << it->second.origin - << ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp - << " secs ago)" << std::endl ; - - std::cerr << " Virtual peers:" << std::endl ; - for(std::map::const_iterator it(_virtual_peers.begin());it!=_virtual_peers.end();++it) - std::cerr << " id=" << it->first << ", tunnel=" << HEX_PRINT(it->second) << std::endl ; - std::cerr << " Online peers: " << std::endl ; -// for(std::list::const_iterator it(_online_peers.begin());it!=_online_peers.end();++it) -// std::cerr << " id=" << it->id << ", name=" << it->name << ", state=" << it->state << ", actions=" << it->actions << std::endl ; -} -#endif - -#ifdef TUNNEL_STATISTICS -void p3turtle::TS_dumpState() -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - rstime_t now = time(NULL) ; - std::cerr << "Dumping tunnel statistics:" << std::endl; - - std::cerr << "TR Bounces: " << TS_request_bounces.size() << std::endl; - for(std::map >::const_iterator it(TS_request_bounces.begin());it!=TS_request_bounces.end();++it) - { - std::cerr << (void*)it->first << ": " ; - for(uint32_t i=0;isecond.size();++i) - std::cerr << it->second[i] - it->second[0] << " " ; - std::cerr << std::endl; - } - std::cerr << "TR in cache: " << _tunnel_requests_origins.size() << std::endl; - std::cerr << "TR by size: " ; - for(int i=0;i<8;++i) - std::cerr << "N(" << i << ")=" << TS_tunnel_length[i] << ", " ; - std::cerr << std::endl; - - std::cerr << "Total different requested files: " << TS_request_time_stamps.size() << std::endl; - for(std::map > >::const_iterator it(TS_request_time_stamps.begin());it!=TS_request_time_stamps.end();++it) - { - std::cerr << "hash = " << it->first << ": seconds ago: " ; - float average = 0 ; - for(uint32_t i=std::max(0,(int)it->second.size()-25);isecond.size();++i) - { - std::cerr << now - it->second[i].first << " (" << (void*)it->second[i].second << ") " ; - - if(i>0) - average += it->second[i].first - it->second[i-1].first ; - } - - if(it->second.size()>1) - std::cerr << ", average delay=" << average/(float)(it->second.size()-1) << std::endl; - else - std::cerr << std::endl; - } -} -#endif diff --git a/libretroshare/src/turtle/p3turtle.h b/libretroshare/src/turtle/p3turtle.h deleted file mode 100644 index 6c0b0012d..000000000 --- a/libretroshare/src/turtle/p3turtle.h +++ /dev/null @@ -1,473 +0,0 @@ -/******************************************************************************* - * libretroshare/src/turtle: p3turtle.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2018 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -//====================================== General setup of the router ===================================// -// -// This class implements the turtle hopping router. It basically serves as -// - a cache of turtle tunnels which are the communicating ways between distant peers. -// - turtle tunnels are either end-point tunnels, or transitory points, in which case items are just -// re-serialized and passed on along the tunnel. -// - turtle tunnels are dug on request when calling diggTurtleTunnel(const std::string& hash) -// this command lets a trace in each peer along the tunnel of where -// packets come from and where they should go. Doing so, once a tunnel is -// dug, packets are directly forwarded to the correct peer. -// - an entry point for search request from the interface -// - search results, as they come back, are forwarded upwards with some additional info: -// - depth // depth of the file. setup to 1 for immediate friends and 2 for long distance friends. -// - hash // hash of the file found -// - name // name of the file found -// - search request id. // -// -// - when downloading: -// - for a given hash, a set of starting tunnels is maintained. Transitory -// tunnels are also maintained for other hashes as requested by distant -// peers. -// -//============================================= Operations =============================================// -// -// A download session works as follows: -// Initiation: -// 1 - the user searches for files (turtle search), and selects one and clicks download. -// 2 - In parallel: -// - the ft module gets a request, and searches for peers to provide this using its search modules. -// - the turtle router is informed that a turtle download will happen with the given hash, so -// it initiates tunnels for this hash. -// In a loop: -// 3 - the ft module asks the hash to the turtle searchModule, and sends file requests to the pqi -// interface of this module. -// 4 - the turtle pqi interface forwards these requests to the turtle router, which sends them to -// the correct peers, selecting randomly among all the possible tunnels for this hash. -// 5 - when a file data packet gets back, the turtle router forwards it back to the file transfer module. -// -//================================ connection to the file transfer module ===============================// -// -// The turtle router should provide the ft module with the necessary interface for asking files, and -// retreiving data: -// - a search module that responds with a given fake peer id for hash request for which it has tunnels. -// - a pqi interface to ask for file data -// - p3turtle sends back file data packets to the file transfer module -// -//========================================== Tunnel usage rules ========================================// -// -// Tunnels should be used according to their capacity. This is an unsolved problem as for now. -// -//======================================= Tunnel maintenance rules =====================================// -// -// P3turtle should derive from pqihandler, just as p3disc, so that newly connected peers should trigger -// asking for new tunnels, and disconnecting peers should produce a close tunnel packet. To simplify this, -// I maintain a time stamp in tunnels, that is updated each time a file data packet travels in the tunnel. -// Doing so, if a tunnel is not used for some time, it just disapears. Additional rules apply: -// -// - when a peer A connects: -// - initiate new tunnels for all active file hashes (go through the list of hashes) by -// asking to A, for the same hash and the same source. Only report tunnels for which the destination -// endpoint is different, which should not happen in fact, because of bouncing gards. -// -// - when a peer A disconnects. -// - do nothing. -// -// - when receive open tunnel from A -// - check whether it's a bouncing request. If yes, give up. -// - check hash against local files. -// if > 0 -// return tunnel ok item. No need to go forward, as sub tunnels are not useful. -// else -// forward request to peers, notting source and hashes. -// -// - when receive tunnel ok from A -// - no need to check whether we already have this tunnel, as bouncing gards prevent this. -// - leave a trace for the tunnel, and send (forward) backward. -// -// Ids management: -// - tunnel ids should be identical for requests between 2 same peers for the same file hash. -// - tunnel ids should be asymetric -// - tunnel requests should never be identical, to allow searching multiple times for the same string. -// So: -// - when issuing an open tunnel order, -// - a random request id is generated and used for packet routing -// - a partial tunnel id is build, which is unique to the pair (source,file hash) -// - when tunnel_ok is sent back, the tunnel id is completed so that it is unique to the -// triplet (source, destination, file hash). -// -// For these needs, tunnels are represented by: -// - their file hash. Each tunnel is only designed for transferring a single and same file. -// - their local endpoints id. These are the ids of the peers in direction to the source and destination. -// - the tunnel id, which is unique to the triple hash+global source+global destination. -// - there is a difference between source and destination in tunnels. The source is the file asker, the -// destination is the file provider. This helps sorting tunnels. -// - a timestamp, used for cleaning unused tunnels. -// -// The turtle router has: -// - a list of search requests and where to bounce them back. -// - a list of tunnel digging requests and where to bounce them, back. -// - a list of active file hashes, for which is should constantly maintain tunnels. -// - a list of active tunnels, some being transitory, some being endpoints. -// -// Turtle router entries: -// - a function for performing turtle search -// - a function for handling tunnels for a given file hash. -// -// Questions: -// - should tunnels be re-used ? nope. The only useful case would be when two peers are exchanging files, which happens quite rarely. -// - -#include -#include -#include - -#include "pqi/pqinetwork.h" -#include "pqi/pqi.h" -#include "pqi/pqimonitor.h" -#include "ft/ftcontroller.h" -#include "pqi/p3cfgmgr.h" -#include "services/p3service.h" -#include "ft/ftsearch.h" -#include "retroshare/rsturtle.h" -#include "rsturtleitem.h" -#include "turtleclientservice.h" -#include "turtlestatistics.h" - -//#define TUNNEL_STATISTICS - -class ftServer ; -class p3LinkMgr; -class ftDataMultiplex; -class RsSerialiser; - -static const int TURTLE_MAX_SEARCH_DEPTH = 6 ; -static const int TURTLE_MAX_SEARCH_REQ_ACCEPTED_SERIAL_SIZE = 200 ; - -// This classes are used to keep trace of requests (searches and tunnels). -// -class TurtleSearchRequestInfo -{ - public: - TurtlePeerId origin ; // where the request came from. - uint32_t time_stamp ; // last time the tunnel was actually used. Used for cleaning old tunnels. - int depth ; // depth of the request. Used to optimize tunnel length. - uint32_t result_count; // responses to this request. Useful to avoid spamming tunnel responses. - std::string keywords; - uint16_t service_id; // ID of the client service who issues the request. This is null if the request does not have a local origin. - uint32_t max_allowed_hits;// Max number of hits allowed for this search. This actually depends on the type of search (files, GXS groups, GXS group data, etc) -}; -class TurtleTunnelRequestInfo -{ - public: - TurtlePeerId origin ; // where the request came from. - uint32_t time_stamp ; // last time the tunnel was actually used. Used for cleaning old tunnels. - int depth ; // depth of the request. Used to optimize tunnel length. - std::set responses; // responses to this request. Useful to avoid spamming tunnel responses. -}; - -class TurtleTunnel -{ - public: - /* For all tunnels */ - - TurtlePeerId local_src ; // where packets come from. Direction to the source. - TurtlePeerId local_dst ; // where packets should go. Direction to the destination. - uint32_t time_stamp ; // last time the tunnel was actually used. Used for cleaning old tunnels. - uint32_t transfered_bytes ; // total bytes transferred in this tunnel. - float speed_Bps ; // speed of the traffic through the tunnel - - /* For ending/starting tunnels only. */ - - TurtleFileHash hash; // Hash of the file for this tunnel - TurtleVirtualPeerId vpid; // Virtual peer id for this tunnel. -}; - -// This class keeps trace of the activity for the file hashes the turtle router is asked to monitor. -// - -class TurtleHashInfo -{ - public: - std::vector tunnels ; // list of active tunnel ids for this file hash - TurtleRequestId last_request ; // last request for the tunnels of this hash - rstime_t last_digg_time ; // last time the tunnel digging happenned. - RsTurtleClientService *service ; // client service to which items should be sent. Never NULL. - bool use_aggressive_mode ; // allow to re-digg tunnels even when some are already available -}; - -// Subclassing: -// -// Class | Brings what | Usage -// -----------+------------------+------------------------------------------------------ -// p3Service | sendItem() | handle packet sending/receiving to/from friend peers. -// pqiMonitor | configChanged() | handle who's connecting/disconnecting to dig new tunnels -// RsTurtle | start/stop file()| brings interface for turtle service -// ftSearch | search() | used to allow searching for monitored files. -// p3Config | ConfigChanged() | used to load/save .cfg file for turtle variales. -// -----------+------------------+------------------------------------------------------ -// -class p3turtle: public p3Service, public RsTurtle, public p3Config -{ - public: - p3turtle(p3ServiceControl *sc,p3LinkMgr *lm) ; - virtual RsServiceInfo getServiceInfo(); - - // Enables/disable the service. Still ticks, but does nothing. Default is true. - // - virtual void setEnabled(bool) ; - virtual bool enabled() const ; - - // This is temporary, used by Operating Mode. - // Turtle operates when both enabled() && sessionEnabled() are true. - virtual void setSessionEnabled(bool); - virtual bool sessionEnabled() const; - - // Lauches a search request through the pipes, and immediately returns - // the request id, which will be further used by the gui to store results - // as they come back. - // - // The first two methods are old style search requests for FT, while the 3rd one is using a generic search data type, that is only to - // be deserialized by the service. The memory ownership is kept by the calling function. Similarly, the search response will be a - // generic data type that is to be deserialized by the client service. - // - // Eventually, search requests will use the generic system - // even for FT. We need to keep the old method for a while for backward compatibility. - // - virtual TurtleRequestId turtleSearch(const RsRegularExpression::LinearizedExpression& expr) ; - virtual TurtleRequestId turtleSearch(const std::string& string_to_match) ; - virtual TurtleRequestId turtleSearch(unsigned char *search_bin_data,uint32_t search_bin_data_len,RsTurtleClientService *client_service) ; - - // Initiates tunnel handling for the given file hash. tunnels. Launches - // an exception if an error occurs during the initialization process. The - // turtle router itself does not initiate downloads, it only maintains - // tunnels for the given hash. The download should be driven by the file - // transfer module. Maybe this function can do the whole thing: - // - initiate tunnel handling - // - send the file request to the file transfer module - // - populate the file transfer module with the adequate pqi interface and search module. - // - // This function should be called in addition to ftServer::FileRequest() so that the turtle router - // automatically provide tunnels for the file to download. - // - virtual void monitorTunnels(const RsFileHash& file_hash,RsTurtleClientService *client_service, bool allow_multi_tunnels) ; - - /// This should be called when canceling a file download, so that the turtle router stops - /// handling tunnels for this file. - /// - virtual void stopMonitoringTunnels(const RsFileHash& file_hash) ; - - /// This is provided to turtle clients to force the TR to ask tunnels again. To be used wisely: - /// too many tunnel requests will kill the network. This might be useful to speed-up the re-establishment - /// of tunnels that have become irresponsive. - - virtual void forceReDiggTunnels(const TurtleFileHash& hash) ; - - /// Adds a client tunnel service. This means that the service will be added - /// to the list of services that might respond to tunnel requests. - /// Example tunnel services include: - /// - /// p3ChatService: tunnels correspond to private distant chatting - /// ftServer : tunnels correspond to file data transfer - /// - virtual void registerTunnelService(RsTurtleClientService *service) ; - - virtual std::string getPeerNameForVirtualPeerId(const RsPeerId& virtual_peer_id); - - /// get info about tunnels - virtual void getInfo(std::vector >&, - std::vector >&, - std::vector&, - std::vector&) const ; - - virtual void getTrafficStatistics(TurtleTrafficStatisticsInfo& info) const ; - - /************* from p3service *******************/ - - /// This function does many things: - /// - It handles incoming and outgoing packets - /// - it sorts search requests and forwards search results upward. - /// - it cleans unused (tunnel+search) requests. - /// - it maintains the pool of tunnels, for each request file hash. - /// - virtual int tick(); - - virtual void getItemNames(std::map& names) const; - - /************* from p3Config *******************/ - virtual RsSerialiser *setupSerialiser() ; - virtual bool saveList(bool& cleanup, std::list&) ; - virtual bool loadList(std::list& /*load*/) ; - - /************* Communication with clients *******************/ - /// Does the turtle router manages tunnels to this peer ? (this is not a - /// real id, but a fake one, that the turtle router is capable of connecting with a tunnel id). - virtual bool isTurtlePeer(const RsPeerId& peer_id) const ; - - /// sets/gets the max number of forwarded tunnel requests per second. - virtual void setMaxTRForwardRate(int max_tr_up_rate) ; - virtual int getMaxTRForwardRate() const ; - - /// Examines the peer id, finds the turtle tunnel in it, and respond yes if the tunnel is ok and operational. - bool isOnline(const RsPeerId& peer_id) const ; - - /// Returns a unique peer id, corresponding to the given tunnel. - RsPeerId getTurtlePeerId(TurtleTunnelId tid) const ; - - /// returns the list of virtual peers for all tunnels. - void getSourceVirtualPeersList(const TurtleFileHash& hash,std::list& list) ; - - /// Send a data request into the correct tunnel for the given file hash - void sendTurtleData(const RsPeerId& virtual_peer_id, RsTurtleGenericTunnelItem *item) ; - - /// Encrypts/decrypts an item, using a autenticated construction + chacha20, based on the given 32 bytes master key. - /// Input values are not touched (memory is not released). Memory ownership of outputs is left to the client. - /// - static bool encryptData(const unsigned char *clear_data,uint32_t clear_data_size,uint8_t *encryption_master_key,RsTurtleGenericDataItem *& encrypted_item); - static bool decryptItem(const RsTurtleGenericDataItem *item, uint8_t* encryption_master_key, unsigned char *& decrypted_data,uint32_t& decrypted_data_size); - - private: - //--------------------------- Admin/Helper functions -------------------------// - - /// Generates a cyphered combination of ownId() and file hash - uint32_t generatePersonalFilePrint(const TurtleFileHash&,uint32_t seed,bool) ; - - /// Generates a random uint32_t number. - uint32_t generateRandomRequestId() ; - - /// Auto cleaning of unused tunnels, search requests and tunnel requests. - void autoWash() ; - - //------------------------------ Tunnel handling -----------------------------// - - /// initiates tunnels from here to any peers having the given file hash - TurtleRequestId diggTunnel(const TurtleFileHash& hash) ; - - /// adds info related to a new virtual peer. - void locked_addDistantPeer(const TurtleFileHash&, TurtleTunnelId) ; - - /// estimates the speed of the traffic into tunnels. - void estimateTunnelSpeeds() ; - - //----------------------------- Routing functions ----------------------------// - - /// Handle tunnel digging for current file hashes - void manageTunnels() ; - - /// Closes a given tunnel. Should be called with mutex set. - /// The hashes and peers to remove (by calling - /// ftController::removeFileSource() are happended to the supplied vector - /// so that they can be removed off the turtle mutex. - void locked_closeTunnel(TurtleTunnelId tid,std::vector > >& peers_to_remove) ; - - /// Main routing function - int handleIncoming(); - - /// Generic routing function for all tunnel packets that derive from RsTurtleGenericTunnelItem - void routeGenericTunnelItem(RsTurtleGenericTunnelItem *item) ; - - /// specific routing functions for handling particular packets. - void handleRecvGenericTunnelItem(RsTurtleGenericTunnelItem *item); - bool getTunnelServiceInfo(TurtleTunnelId, RsPeerId& virtual_peer_id, RsFileHash& hash, RsTurtleClientService*&) ; - - // following functions should go to ftServer - void handleSearchRequest(RsTurtleSearchRequestItem *item); - void handleSearchResult(RsTurtleSearchResultItem *item); - void handleTunnelRequest(RsTurtleOpenTunnelItem *item); - void handleTunnelResult(RsTurtleTunnelOkItem *item); - - //------ Functions connecting the turtle router to other components.----------// - - /// Performs a search calling local cache and search structure. - void performLocalSearch (RsTurtleSearchRequestItem *item, uint32_t& req_result_count,std::list& result,uint32_t& max_allowed_hits) ; - void performLocalSearch_files (RsTurtleFileSearchRequestItem *item, uint32_t& req_result_count, std::list& result, uint32_t &max_allowed_hits) ; - void performLocalSearch_generic(RsTurtleGenericSearchRequestItem *item, uint32_t& req_result_count, std::list& result, uint32_t &max_allowed_hits) ; - - /// Returns true if the file with given hash is hosted locally, and accessible in anonymous mode the supplied peer. - virtual bool performLocalHashSearch(const TurtleFileHash& hash,const RsPeerId& client_peer_id,RsTurtleClientService *& service); - - //--------------------------- Local variables --------------------------------// - - /* data */ - p3ServiceControl *mServiceControl; - p3LinkMgr *mLinkMgr; - RsTurtleSerialiser *_serialiser ; - RsPeerId _own_id ; - - mutable RsMutex mTurtleMtx; - - /// keeps trace of who emmitted a given search request - std::map _search_requests_origins ; - - /// keeps trace of who emmitted a tunnel request - std::map _tunnel_requests_origins ; - - /// stores adequate tunnels for each file hash locally managed - std::map _incoming_file_hashes ; - - /// stores file info for each file we provide. - std::map _outgoing_tunnel_client_services ; - - /// local tunnels, stored by ids (Either transiting or ending). - std::map _local_tunnels ; - - /// Peers corresponding to each tunnel. - std::map _virtual_peers ; - - /// Hashes marked to be deleted. - std::set _hashes_to_remove ; - - /// List of client services that have regitered. - std::map _registered_services ; - - rstime_t _last_clean_time ; - rstime_t _last_tunnel_management_time ; - rstime_t _last_tunnel_campaign_time ; - rstime_t _last_tunnel_speed_estimate_time ; - - std::list _online_peers; - - /// used to force digging new tunnels - //bool _force_digg_new_tunnels ; - - /// used as a bias to introduce randomness in a consistent way, for - /// altering tunnel request depths, and tunnel re-routing actions. - /// - uint32_t _random_bias ; - - // Used to collect statistics on turtle traffic. - // - TurtleTrafficStatisticsInfoOp _traffic_info ; // used for recording speed - TurtleTrafficStatisticsInfoOp _traffic_info_buffer ; // used as a buffer to collect bytes - - float _max_tr_up_rate ; - bool _turtle_routing_enabled ; - bool _turtle_routing_session_enabled ; - - // p3ServiceControl service type - - uint32_t _service_type ; - - RS_SET_CONTEXT_DEBUG_LEVEL(1) - -#ifdef P3TURTLE_DEBUG - // debug function - void dumpState() ; -#endif -#ifdef TUNNEL_STATISTICS - void TS_dumpState(); -#endif -}; diff --git a/libretroshare/src/turtle/rsturtleitem.cc b/libretroshare/src/turtle/rsturtleitem.cc deleted file mode 100644 index f0128d04a..000000000 --- a/libretroshare/src/turtle/rsturtleitem.cc +++ /dev/null @@ -1,256 +0,0 @@ -/******************************************************************************* - * libretroshare/src/turtle: rsturtleitem.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2018 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef WINDOWS_SYS -#include -#endif -#include -#include "turtletypes.h" -#include "rsturtleitem.h" -#include "turtleclientservice.h" - -#include "serialiser/rstypeserializer.h" - -//#define P3TURTLE_DEBUG -// -----------------------------------------------------------------------------------// -// -------------------------------- Serialization. --------------------------------- // -// -----------------------------------------------------------------------------------// -// - -RsItem *RsTurtleSerialiser::create_item(uint16_t service,uint8_t item_subtype) const -{ - if (RS_SERVICE_TYPE_TURTLE != service) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Wrong type !!" << std::endl ; -#endif - return NULL; /* wrong type */ - } - - switch(getRsItemSubType(item_subtype)) - { - case RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST : return new RsTurtleStringSearchRequestItem(); - case RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST : return new RsTurtleRegExpSearchRequestItem(); - case RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT : return new RsTurtleFTSearchResultItem(); - case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : return new RsTurtleOpenTunnelItem(); - case RS_TURTLE_SUBTYPE_TUNNEL_OK : return new RsTurtleTunnelOkItem(); - case RS_TURTLE_SUBTYPE_GENERIC_DATA : return new RsTurtleGenericDataItem(); - case RS_TURTLE_SUBTYPE_GENERIC_FAST_DATA : return new RsTurtleGenericFastDataItem(); - case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST : return new RsTurtleGenericSearchRequestItem(); - case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT : return new RsTurtleGenericSearchResultItem(); - - default: - break ; - } - // now try all client services - // - RsItem *item = NULL ; - - for(uint32_t i=0;i<_client_services.size();++i) - if((_client_services[i]->serializer() != NULL) && (item = _client_services[i]->serializer()->create_item(service,item_subtype)) != NULL) - return item ; - - std::cerr << "Unknown packet type in RsTurtle (not even handled by client services)!" << std::endl ; - return NULL ; -} - -std::string RsTurtleGenericSearchRequestItem::GetKeywords() -{ - return std::string("Generic search : " + RsUtil::BinToHex(search_data,search_data_len,10)); -} - -void RsTurtleStringSearchRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_VALUE,match_string,"match_string") ; - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; - RsTypeSerializer::serial_process(j,ctx,depth ,"depth") ; -} -void RsTurtleRegExpSearchRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; - RsTypeSerializer::serial_process(j,ctx,depth,"depth") ; - RsTypeSerializer::serial_process(j,ctx,expr,"expr") ; -} -void RsTurtleGenericSearchRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; - RsTypeSerializer::serial_process(j,ctx,depth,"depth") ; - RsTypeSerializer::serial_process(j,ctx,service_id,"service_id") ; - RsTypeSerializer::serial_process(j,ctx,request_type,"request_type") ; - - RsTypeSerializer::TlvMemBlock_proxy prox(search_data,search_data_len) ; - RsTypeSerializer::serial_process(j,ctx,prox,"search_data") ; -} -RsTurtleSearchRequestItem *RsTurtleGenericSearchRequestItem::clone() const -{ - return new RsTurtleGenericSearchRequestItem(*this) ; -} - -RsTurtleGenericSearchRequestItem::RsTurtleGenericSearchRequestItem(const RsTurtleGenericSearchRequestItem& it) - : RsTurtleSearchRequestItem(it) -{ - search_data_len = it.search_data_len ; - search_data = (unsigned char*)rs_malloc(it.search_data_len) ; - service_id = it.service_id ; - request_type = it.request_type ; - - memcpy(search_data,it.search_data,it.search_data_len) ; -} - -template<> uint32_t RsTypeSerializer::serial_size(const RsRegularExpression::LinearizedExpression& r) -{ - uint32_t s = 0 ; - - s += 4 ; // number of strings - - for(unsigned int i=0;i bool RsTypeSerializer::deserialize(const uint8_t data[],uint32_t size,uint32_t& offset,RsRegularExpression::LinearizedExpression& expr) -{ - uint32_t saved_offset = offset ; - - uint32_t n =0 ; - bool ok = true ; - - ok &= getRawUInt32(data,size,&offset,&n) ; - - if(ok) expr._tokens.resize(n) ; - - for(uint32_t i=0;i bool RsTypeSerializer::serialize(uint8_t data[],uint32_t size,uint32_t& offset,const RsRegularExpression::LinearizedExpression& expr) -{ - uint32_t saved_offset = offset ; - - bool ok = true ; - - ok &= setRawUInt32(data,size,&offset,expr._tokens.size()) ; - - for(unsigned int i=0;i void RsTypeSerializer::print_data(const std::string& n, const RsRegularExpression::LinearizedExpression& expr) -{ - std::cerr << " [RegExpr ] " << n << ", tokens=" << expr._tokens.size() << " ints=" << expr._ints.size() << " strings=" << expr._strings.size() << std::endl; -} - -RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(RsRegularExpression::LinearizedExpression) -RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(RsRegularExpression::LinearizedExpression) - -void RsTurtleFTSearchResultItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; - - // This depth was previously a member of SearchResult parent class that was set to be always 0. It's removed, but we have to stay backward compatible. - uint16_t depth_retrocompat_unused_placeholder = 0 ; - RsTypeSerializer::serial_process(j,ctx,depth_retrocompat_unused_placeholder,"depth") ; - - RsTypeSerializer::serial_process (j,ctx,result ,"result") ; -} -void RsTurtleGenericSearchResultItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; - - // This depth was previously a member of SearchResult parent class that was set to be always 0. It's removed, but we have to stay backward compatible. - uint16_t depth_retrocompat_unused_placeholder = 0 ; - RsTypeSerializer::serial_process(j,ctx,depth_retrocompat_unused_placeholder,"depth") ; - - RsTypeSerializer::TlvMemBlock_proxy prox(result_data,result_data_len) ; - RsTypeSerializer::serial_process(j,ctx,prox,"search_data") ; -} -RsTurtleSearchResultItem *RsTurtleGenericSearchResultItem::duplicate() const -{ - RsTurtleGenericSearchResultItem *sr = new RsTurtleGenericSearchResultItem ; - - sr->result_data = (unsigned char*)rs_malloc(result_data_len) ; - memcpy(sr->result_data,result_data,result_data_len) ; - sr->result_data_len = result_data_len ; - sr->request_id = request_id ; - return sr ; -} - -void RsTurtleOpenTunnelItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,file_hash ,"file_hash") ; - RsTypeSerializer::serial_process(j,ctx,request_id ,"request_id") ; - RsTypeSerializer::serial_process(j,ctx,partial_tunnel_id,"partial_tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,depth ,"depth") ; -} - -void RsTurtleTunnelOkItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id ,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; -} - -void RsTurtleGenericDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id ,"tunnel_id") ; - RsTypeSerializer::TlvMemBlock_proxy prox(data_bytes,data_size) ; - RsTypeSerializer::serial_process(j,ctx,prox,"data bytes") ; -} -void RsTurtleGenericFastDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id ,"tunnel_id") ; - RsTypeSerializer::TlvMemBlock_proxy prox(data_bytes,data_size) ; - RsTypeSerializer::serial_process(j,ctx,prox,"data bytes") ; -} diff --git a/libretroshare/src/turtle/rsturtleitem.h b/libretroshare/src/turtle/rsturtleitem.h deleted file mode 100644 index db029cc64..000000000 --- a/libretroshare/src/turtle/rsturtleitem.h +++ /dev/null @@ -1,387 +0,0 @@ -/******************************************************************************* - * libretroshare/src/turtle: rsturtleitem.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2018 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" - -#include "retroshare/rsturtle.h" -#include "retroshare/rsexpr.h" -#include "retroshare/rstypes.h" -#include "turtle/turtletypes.h" - -#include "serialiser/rsserializer.h" - -const uint8_t RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST = 0x01 ; -const uint8_t RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT = 0x02 ; -const uint8_t RS_TURTLE_SUBTYPE_OPEN_TUNNEL = 0x03 ; -const uint8_t RS_TURTLE_SUBTYPE_TUNNEL_OK = 0x04 ; -const uint8_t RS_TURTLE_SUBTYPE_FILE_REQUEST = 0x07 ; -const uint8_t RS_TURTLE_SUBTYPE_FILE_DATA = 0x08 ; -const uint8_t RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST = 0x09 ; -const uint8_t RS_TURTLE_SUBTYPE_GENERIC_DATA = 0x0a ; -const uint8_t RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST = 0x0b ; -const uint8_t RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT = 0x0c ; -const uint8_t RS_TURTLE_SUBTYPE_FILE_MAP = 0x10 ; -const uint8_t RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST = 0x11 ; -// const uint8_t RS_TURTLE_SUBTYPE_FILE_CRC = 0x12 ; // unused -// const uint8_t RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST = 0x13 ; -const uint8_t RS_TURTLE_SUBTYPE_CHUNK_CRC = 0x14 ; -const uint8_t RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST = 0x15 ; -const uint8_t RS_TURTLE_SUBTYPE_GENERIC_FAST_DATA = 0x16 ; - - -class TurtleSearchRequestInfo ; - -/***********************************************************************************/ -/* Basic Turtle Item Class */ -/***********************************************************************************/ - -class RsTurtleItem: public RsItem -{ - public: - RsTurtleItem(uint8_t turtle_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_TURTLE,turtle_subtype) {} -}; - -/***********************************************************************************/ -/* Turtle Search Item classes */ -/* Specific packets */ -/***********************************************************************************/ - -// Class hierarchy is -// -// RsTurtleItem -// | -// +---- RsTurtleSearchRequestItem -// | | -// | +---- RsTurtleFileSearchRequestItem -// | | | -// | | +---- RsTurtleStringSearchRequestItem -// | | | -// | | +---- RsTurtleReqExpSearchRequestItem -// | | -// | +---- RsTurtleGenericSearchRequestItem -// | -// +---- RsTurtleSearchResultItem -// | -// +---- RsTurtleFTSearchResultItem -// | -// +---- RsTurtleGenericSearchResultItem -// - -class RsTurtleSearchResultItem ; - -class RsTurtleSearchRequestItem: public RsTurtleItem -{ - public: - RsTurtleSearchRequestItem(uint32_t subtype) : RsTurtleItem(subtype), request_id(0), depth(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_SEARCH_REQUEST) ;} - virtual ~RsTurtleSearchRequestItem() {} - - virtual RsTurtleSearchRequestItem *clone() const = 0 ; // used for cloning in routing methods - - virtual std::string GetKeywords() = 0; - virtual uint16_t serviceId() const= 0 ; - - uint32_t request_id ; // randomly generated request id. - uint16_t depth ; // Used for limiting search depth. -}; - -class RsTurtleFileSearchRequestItem: public RsTurtleSearchRequestItem -{ - public: - RsTurtleFileSearchRequestItem(uint32_t subtype) : RsTurtleSearchRequestItem(subtype) {} - virtual ~RsTurtleFileSearchRequestItem() {} - - virtual uint16_t serviceId() const { return RS_SERVICE_TYPE_FILE_TRANSFER ; } - virtual void search(std::list &) const =0; -}; - -class RsTurtleStringSearchRequestItem: public RsTurtleFileSearchRequestItem -{ - public: - RsTurtleStringSearchRequestItem() : RsTurtleFileSearchRequestItem(RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST) {} - virtual ~RsTurtleStringSearchRequestItem() {} - - virtual void search(std::list &) const ; - - std::string match_string ; // string to match - std::string GetKeywords() { return match_string; } - - virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleStringSearchRequestItem(*this) ; } - - void clear() { match_string.clear() ; } - - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleRegExpSearchRequestItem: public RsTurtleFileSearchRequestItem -{ - public: - RsTurtleRegExpSearchRequestItem() : RsTurtleFileSearchRequestItem(RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST) {} - virtual ~RsTurtleRegExpSearchRequestItem() {} - - RsRegularExpression::LinearizedExpression expr ; // Reg Exp in linearised mode - - std::string GetKeywords() - { - RsRegularExpression::Expression *ex = RsRegularExpression::LinearizedExpression::toExpr(expr); - std::string exs = ex->toStdString(); - delete ex; - return exs; - } - - virtual void search(std::list &) const ; - - virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleRegExpSearchRequestItem(*this) ; } - void clear() { expr = RsRegularExpression::LinearizedExpression(); } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleGenericSearchRequestItem: public RsTurtleSearchRequestItem -{ - public: - RsTurtleGenericSearchRequestItem() - : RsTurtleSearchRequestItem(RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST), - service_id(0), - search_data_len(0), - request_type(0), - search_data(nullptr) - {} - virtual ~RsTurtleGenericSearchRequestItem() { clear(); } - - uint16_t service_id ; // service to search - uint32_t search_data_len ; - uint8_t request_type ; // type of request. This is used to limit the number of responses. - unsigned char *search_data ; - - std::string GetKeywords() ; - virtual uint16_t serviceId() const { return service_id ; } - - virtual RsTurtleSearchRequestItem *clone() const ; - virtual uint32_t requestType() const { return request_type; } - - void clear() { free(search_data); search_data=NULL; search_data_len=0; } - - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - private: - RsTurtleGenericSearchRequestItem(const RsTurtleGenericSearchRequestItem&); // make the object non copi-able. - RsTurtleGenericSearchRequestItem& operator=(const RsTurtleGenericSearchRequestItem&) { return *this;} -}; -class RsTurtleSearchResultItem: public RsTurtleItem -{ - public: - RsTurtleSearchResultItem(uint8_t subtype) : RsTurtleItem(subtype), request_id(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_SEARCH_RESULT) ;} - - TurtleSearchRequestId request_id ; // Randomly generated request id. - - virtual uint32_t count() const =0; - virtual void pop() =0; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)=0; - virtual RsTurtleSearchResultItem *duplicate() const =0; -}; - -class RsTurtleFTSearchResultItem: public RsTurtleSearchResultItem -{ - public: - RsTurtleFTSearchResultItem() : RsTurtleSearchResultItem(RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT){} - - std::list result ; - - void clear() { result.clear() ; } - uint32_t count() const { return result.size() ; } - virtual void pop() { result.pop_back() ;} - virtual RsTurtleSearchResultItem *duplicate() const { return new RsTurtleFTSearchResultItem(*this) ; } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleGenericSearchResultItem: public RsTurtleSearchResultItem -{ - public: - RsTurtleGenericSearchResultItem() - : RsTurtleSearchResultItem(RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT), - result_data(nullptr), - result_data_len(0) - {} - virtual ~RsTurtleGenericSearchResultItem() {} - - uint32_t count() const { return result_data_len/50 ; } // This is a blind size estimate. We should probably use the actual size to limit search results. - virtual void pop() {} - - unsigned char *result_data ; - uint32_t result_data_len ; - - virtual RsTurtleSearchResultItem *duplicate() const ; - void clear() { free(result_data); result_data=NULL; result_data_len=0; } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -/***********************************************************************************/ -/* Turtle Tunnel Item classes */ -/***********************************************************************************/ - -class RsTurtleOpenTunnelItem: public RsTurtleItem -{ - public: - RsTurtleOpenTunnelItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_OPEN_TUNNEL), request_id(0), partial_tunnel_id(0), depth(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_OPEN_TUNNEL) ;} - - TurtleFileHash file_hash ; // hash to match - uint32_t request_id ; // randomly generated request id. - uint32_t partial_tunnel_id ; // uncomplete tunnel id. Will be completed at destination. - uint16_t depth ; // Used for limiting search depth. - - void clear() { file_hash.clear() ;} - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleTunnelOkItem: public RsTurtleItem -{ - public: - RsTurtleTunnelOkItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_TUNNEL_OK), tunnel_id(0), request_id(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_TUNNEL_OK) ;} - - uint32_t tunnel_id ; // id of the tunnel. Should be identical for a tunnel between two same peers for the same hash. - uint32_t request_id ; // randomly generated request id corresponding to the intial request. - - void clear() {} - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -/***********************************************************************************/ -/* Generic turtle packets for tunnels */ -/***********************************************************************************/ - -class RsTurtleGenericTunnelItem: public RsTurtleItem -{ - public: - RsTurtleGenericTunnelItem(uint8_t sub_packet_id) : RsTurtleItem(sub_packet_id), direction(0), tunnel_id(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_ITEM);} - virtual ~RsTurtleGenericTunnelItem() {} - - typedef uint32_t Direction ; - static const Direction DIRECTION_CLIENT = 0x001 ; - static const Direction DIRECTION_SERVER = 0x002 ; - - /// Does this packet stamps tunnels when it passes through ? - /// This is used for keeping trace weither tunnels are active or not. - - virtual bool shouldStampTunnel() const = 0 ; - - /// All tunnels derived from RsTurtleGenericTunnelItem should have a tunnel id to - /// indicate which tunnel they are travelling through. - - virtual TurtleTunnelId tunnelId() const { return tunnel_id ; } - - /// Indicate weither the packet is a client packet (goign back to the - /// client) or a server packet (going to the server. Typically file - /// requests are server packets, whereas file data are client packets. - - virtual Direction travelingDirection() const { return direction ; } - virtual void setTravelingDirection(Direction d) { direction = d; } - - Direction direction ; // This does not need to be serialised. It's only used by the client services, optionnally, - // and is set by the turtle router according to which direction the item travels. - - uint32_t tunnel_id ; // Id of the tunnel to travel through -}; - -/***********************************************************************************/ -/* Specific Turtle Transfer items */ -/***********************************************************************************/ - -// This item can be used by any service to pass-on arbitrary data into a tunnel. -// -class RsTurtleGenericDataItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleGenericDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_GENERIC_DATA), data_size(0), data_bytes(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_DATA);} - virtual ~RsTurtleGenericDataItem() { if(data_bytes != NULL) free(data_bytes) ; } - - virtual bool shouldStampTunnel() const { return true ; } - - uint32_t data_size ; - void *data_bytes ; - - void clear() - { - free(data_bytes) ; - data_bytes = NULL ; - data_size = 0; - } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -// Same, but with a fact priority. Can rather be used for e.g. distant chat. -// -class RsTurtleGenericFastDataItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleGenericFastDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_GENERIC_FAST_DATA), data_size(0), data_bytes(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_FAST_DATA);} - virtual ~RsTurtleGenericFastDataItem() { if(data_bytes != NULL) free(data_bytes) ; } - - virtual bool shouldStampTunnel() const { return true ; } - - uint32_t data_size ; - void *data_bytes ; - - void clear() - { - free(data_bytes) ; - data_bytes = NULL ; - data_size = 0; - } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; -/***********************************************************************************/ -/* Turtle Serialiser class */ -/***********************************************************************************/ - -class RsTurtleSerialiser: public RsServiceSerializer -{ - public: - RsTurtleSerialiser() : RsServiceSerializer(RS_SERVICE_TYPE_TURTLE) {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const; - - // This is used by the turtle router to add services to its serialiser. - // Client services are only used for deserialising, since the serialisation is - // performed using the overloaded virtual functions above. - // - void registerClientService(RsTurtleClientService *service) { _client_services.push_back(service) ; } - - private: - std::vector _client_services ; -}; - diff --git a/libretroshare/src/turtle/turtleclientservice.h b/libretroshare/src/turtle/turtleclientservice.h deleted file mode 100644 index 9cbe5763f..000000000 --- a/libretroshare/src/turtle/turtleclientservice.h +++ /dev/null @@ -1,164 +0,0 @@ -/******************************************************************************* - * libretroshare/src/turtle: rsturtleclientservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2018 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -// This class is the parent class for any service that will use the turtle router to distribute its packets. -// Typical representative clients include: -// -// p3ChatService: opens tunnels to distant peers for chatting -// ftServer: searches and open tunnels to distant sources for file transfer -// -#pragma once - -#include -#include -#include -#include - -struct RsItem; -class p3turtle ; - -class RsTurtleClientService -{ - public: - /*! - * \brief serviceId - * Returns the ID of the client service. This is used to pass the ID to search requests, from the client services - * \return - * The service ID. - */ - - virtual uint16_t serviceId() const - { - std::cerr << "!!!!!! Received request for service ID in turtle router client, but the client service is not handling it !!!!!!!" << std::endl ; - return 0 ; - } - - /*! - * \brief handleTunnelRequest - Handling of tunnel request for the given hash. To be derived by the service in order to tell the turtle router - whether the service handles this hash or not. Most of the time, it's a search in a predefined list. - - * \return true if the service - */ - virtual bool handleTunnelRequest(const RsFileHash& /*hash*/,const RsPeerId& /*peer_id*/) { return false ; } - - /*! - * \brief receiveTurtleData - * This method is called by the turtle router to send data that comes out of a turtle tunnel, and should - * be overloaded by the client service. - * The turtle router stays responsible for the memory management of data. Most of the time the - * data chunk is a serialized item to be de-serialized by the client service. - * - * Parameters: - * virtual_peer_id : name of the tunnel that sent the data - * data : memory chunk for the data - * size : size of data - * item->direction : direction of travel: - * RsTurtleGenericTunnelItem::DIRECTION_CLIENT: the service is acting as a client - * RsTurtleGenericTunnelItem::DIRECTION_CLIENT: the service is acting as a server - * - * Most of the time this parameter is not used by services, except when some info (such as chunk maps, chat items, etc) go - * both ways, and their nature cannot suffice to determine where they should be handled. - * - * By default (if not overloaded), the method will just free the data, as any subclass should do as well. - * Note: p3turtle stays owner of the item, so the client should not delete it! - */ - virtual void receiveTurtleData(const RsTurtleGenericTunnelItem * /* item */,const RsFileHash& /*hash*/,const RsPeerId& /*virtual_peer_id*/,RsTurtleGenericTunnelItem::Direction /*direction*/) - { - std::cerr << "!!!!!! Received Data from turtle router, but the client service is not handling it !!!!!!!!!!" << std::endl ; - } - - /*! - * \brief receiveSearchRequest - * This method is called by the turtle router to notify the client of a search request in the form generic data. The returned - * result contains the serialised generic result returned by the client. - * - * The turtle router keeps the memory ownership over search_request_data - * - * \param search_request_data generic serialized search data - * \param search_request_data_len length of the serialized search data - * \param search_result_data generic serialized search result data - * \param search_result_data_len length of the serialized search result data - * \param max_allowed_hits max number of hits allowed to be sent back and forwarded - * - * \return true if the search is successful. - */ - virtual bool receiveSearchRequest(unsigned char */*search_request_data*/, - uint32_t /*search_request_data_len*/, - unsigned char *& /*search_result_data*/, - uint32_t& /*search_result_data_len*/, - uint32_t& /* max_allows_hits */) - { - std::cerr << "!!!!!! Received search result from turtle router, but the client service who requested it is not handling it !!!!!!!!!!" << std::endl ; - return false; - } - - /*! - * \brief receiveSearchResult - * This method is called by the turtle router to notify the client of a search result. The result is serialized for the current class to read. - * - * \param search_result_data result data. Memory ownership is owned by the turtle router. So do not delete! - * \param search_result_data length of result data - */ - virtual void receiveSearchResult(TurtleSearchRequestId /* request_id */,unsigned char * /*search_result_data*/,uint32_t /*search_result_data_len*/) - { - std::cerr << "!!!!!! Received search result from turtle router, but the client service who requested it is not handling it !!!!!!!!!!" << std::endl ; - } - - /*! - * \brief serializer - * Method for creating specific items of the client service. The - * method has a default behavior of not doing anything, since most client - * services might only use the generic item already provided by the turtle - * router: RsTurtleGenericDataItem - * - * \return the client's serializer is returned - */ - virtual RsServiceSerializer *serializer() { return NULL ; } - - /*! - * \brief addVirtualPeer - * These methods are called by the turtle router to notify the client in order to add/remove virtual peers when tunnels are created/deleted - * These methods must be overloaded, because a service which does not care about tunel being openned or closed is not supposed to need tunnels. - * - * \param hash hash that the tunnel responds to - * \param virtual_peer_id virtual peer id provided by turtle to allow the client to send data into this tunnel. This peer is related to the tunnel itself - * rather than to its destination. As such, multiple peer ids may actually send data to the same computer because multiple tunnels - * arrive at the same location. - * \param dir dir indicates which side the cient will be talking to: CLIENT means that the client is the server. SERVER means that the client acts - * as a client (and therefore actually requested the tunnel). - */ - virtual void addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) = 0 ; - virtual void removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) = 0 ; - - /*! - * \brief connectToTurtleRouter - * This function must be overloaded by the client. It should do two things: - * 1 - keep a pointer to the turtle router, so as to be able to send data (e.g. store pt into a local variable) - * 2 - call pt->registerTunnelService(this), so that the TR knows that service and can send back information to it. - * - * \param pt A pointer to the turtle router. - */ - virtual void connectToTurtleRouter(p3turtle *pt) = 0 ; -}; - - diff --git a/libretroshare/src/turtle/turtlestatistics.h b/libretroshare/src/turtle/turtlestatistics.h deleted file mode 100644 index 5aaeda676..000000000 --- a/libretroshare/src/turtle/turtlestatistics.h +++ /dev/null @@ -1,51 +0,0 @@ -#include - -class TurtleTrafficStatisticsInfoOp: public TurtleTrafficStatisticsInfo -{ - public: - TurtleTrafficStatisticsInfoOp() - { - reset() ; - } - - void reset() - { - unknown_updn_Bps = 0.0f ; - data_up_Bps = 0.0f ; - data_dn_Bps = 0.0f ; - tr_up_Bps = 0.0f ; - tr_dn_Bps = 0.0f ; - total_up_Bps = 0.0f ; - total_dn_Bps = 0.0f ; - } - - TurtleTrafficStatisticsInfoOp operator*(float f) const - { - TurtleTrafficStatisticsInfoOp i(*this) ; - - i.unknown_updn_Bps *= f ; - i.data_up_Bps *= f ; - i.data_dn_Bps *= f ; - i.tr_up_Bps *= f ; - i.tr_dn_Bps *= f ; - i.total_up_Bps *= f ; - i.total_dn_Bps *= f ; - - return i ; - } - TurtleTrafficStatisticsInfoOp operator+(const TurtleTrafficStatisticsInfoOp& j) const - { - TurtleTrafficStatisticsInfoOp i(*this) ; - - i.unknown_updn_Bps += j.unknown_updn_Bps ; - i.data_up_Bps += j.data_up_Bps ; - i.data_dn_Bps += j.data_dn_Bps ; - i.tr_up_Bps += j.tr_up_Bps ; - i.tr_dn_Bps += j.tr_dn_Bps ; - i.total_up_Bps += j.total_up_Bps ; - i.total_dn_Bps += j.total_dn_Bps ; - - return i ; - } -}; - diff --git a/libretroshare/src/turtle/turtletypes.h b/libretroshare/src/turtle/turtletypes.h deleted file mode 100644 index 56fd78f8b..000000000 --- a/libretroshare/src/turtle/turtletypes.h +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * libretroshare/src/turtle: rsturtletypes.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2018 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsturtle.h" - -typedef RsPeerId TurtlePeerId ; -typedef RsPeerId TurtleVirtualPeerId ; -typedef RsFileHash TurtleFileHash ; -typedef std::string TurtleFileName ; - -typedef TurtleRequestId TurtleSearchRequestId ; - -typedef uint32_t TurtleTunnelRequestId ; -typedef uint32_t TurtleTunnelId ; - - diff --git a/libretroshare/src/unfinished/db_acadeeb.h b/libretroshare/src/unfinished/db_acadeeb.h deleted file mode 100644 index 806422a30..000000000 --- a/libretroshare/src/unfinished/db_acadeeb.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * libretroshare/src/gxp: gxp_apps.h - * - * General Exchange Protocol interface for RetroShare. - * - * Copyright 2011-2011 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef RS_ACADEE_H -#define RS_ACADEE_H - -/******* - * Stores a Bibliography of Academic Articles, with links to allow you to access the actual article. - * The data fields, should contain enough information to - * - extract full biblio (bibtex or ris formats). - * - read abstract. - * - review / rating of the article - * - references to similar papers, and bibliography. - * - keywords, and the like. - * - * It will be possible to have multiple identical / similar / different descriptions of the same article. - * The class will have to handle this: sorting and matching as best it can. - * - ****/ - -class gxp::Paper -{ - /* fields from ris */ - std::string reftype; - std::string journal; - std::string title; - std::string issuetitle; - uint32_t volume; - uint32_t issue; - std::string publisher; - std::string serialnumber; - std::string url; - std::list authors; - rstime_t date; - uint32_t startpage; - uint32_t endpage; - std::string language; - - std::string abstract; - - // KeyWords <- go into hashtags (parent class) - //References & Similar Papers <- go into links (parent class) -}; - - -class rsAcadee: public rsGmxp -{ - public: - - /* we want to access the */ - - - - -}; - - -#endif /* RS_GXP_H */ - - diff --git a/libretroshare/src/unfinished/db_wire.h b/libretroshare/src/unfinished/db_wire.h deleted file mode 100644 index cac3f2747..000000000 --- a/libretroshare/src/unfinished/db_wire.h +++ /dev/null @@ -1,50 +0,0 @@ - -#include "gxp_service.h" - -class db_wire -{ - /* external interface for accessing the info */ - - /** Note this could get very busy with a large number of tweeters. - * need some other method of getting data - */ - - getTweeters(std::list &tweeterIds); - { - getGroups(); - } - - getTweetRange(GxpTimeStamp, GxpTimeStamp, std::list &tweetIds); - { - getTimeRange(); - } - - getTweetRangeSource(GxpTimeStamp, GxpTimeStamp, std::string tweeterId, std::list &tweetIds); - { - getGroupTimeRange(); - } - - getTweet(std::string id, TweetData &tweet); - { - StackLock(); - - RsGxpItem *getMsg_locked(id); - - // translate message into TweetData. - - } - - // Default - getProfile(std::string id, TweetData &tweet); - - /* returns a search code, which is used to id later delivery */ - int searchTweets(GxpSearchCondition cond, std::list); - - /* returns a search code, which is used to id later delivery */ - int fetchPendingSearchResults(int searchId, std::list); - - int cancelSearch(int searchId, std::list); - -}; - - diff --git a/libretroshare/src/unfinished/mail/directmailservice.cc b/libretroshare/src/unfinished/mail/directmailservice.cc deleted file mode 100644 index aa28a7cca..000000000 --- a/libretroshare/src/unfinished/mail/directmailservice.cc +++ /dev/null @@ -1,254 +0,0 @@ -/* - * libretroshare/src/services directmailservice.cc - * - * Services for RetroShare. - * - * Copyright 2014 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include "services/mail/directmailservice.h" - -#include "util/rsdebug.h" - -//#define MSG_DEBUG 1 - -const int directmailzone = 54319; - -using namespace Rs::Mail; - - -DirectMailService::DirectMailService(p3ServiceControl *sc) - :MailTransport(DEFAULT_MAX_MESSAGE_SIZE, RS_SERVICE_TYPE_DIRECT_MAIL), - p3Service(), mServiceCtrl(sc), mMsgMtx("DirectMailService") -{ - mSerialiser = new RsMailTransportSerialiser(RS_SERVICE_TYPE_DIRECT_MAIL); - addSerialType(mSerialiser); -} - -const std::string MSGDIRECT_APP_NAME = "msgdirect"; -const uint16_t MSGDIRECT_APP_MAJOR_VERSION = 1; -const uint16_t MSGDIRECT_APP_MINOR_VERSION = 0; -const uint16_t MSGDIRECT_MIN_MAJOR_VERSION = 1; -const uint16_t MSGDIRECT_MIN_MINOR_VERSION = 0; - -RsServiceInfo DirectMailService::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_DIRECT_MAIL, - MSGDIRECT_APP_NAME, - MSGDIRECT_APP_MAJOR_VERSION, - MSGDIRECT_APP_MINOR_VERSION, - MSGDIRECT_MIN_MAJOR_VERSION, - MSGDIRECT_MIN_MINOR_VERSION); -} - - -bool DirectMailService::CanSend(const RsTlvMailAddress &addr) -{ - /* we can send if MessageAddress is a peerID, - * and the peer ID is a friend. - */ - if (addr.mAddressType == ADDRESS_TYPE_PEER_ID) - { - return true; - } - return false; -} - -bool DirectMailService::sendMail(RsMailChunkItem *item) -{ - // set the right serviceId. - item->setPacketService(RS_SERVICE_TYPE_DIRECT_MAIL); - if (!attemptToSend(item)) - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - mOutgoingMsgs.push_back(item); - } - return true; -} - -RsMailChunkItem *DirectMailService::recvMail() -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - if (!mIncomingMsgs.empty()) - { - RsMailChunkItem *item = mIncomingMsgs.front(); - mIncomingMsgs.pop_front(); - return item; - } - return NULL; -} - -RsPeerId convertAddressToPeerId(RsMailAckItem *item) -{ - RsPeerId id; - return id; -} - -bool DirectMailService::sendMailAck(RsMailAckItem *item) -{ - // set the right serviceId. - item->setPacketService(RS_SERVICE_TYPE_DIRECT_MAIL); - item->PeerId(convertAddressToPeerId(item)); - if (!attemptToSend(item)) - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - mOutgoingMsgs.push_back(item); - } - return true; -} - -RsMailAckItem *DirectMailService::recvMailAck() -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - if (!mIncomingAckMsgs.empty()) - { - RsMailAckItem *item = mIncomingAckMsgs.front(); - mIncomingMsgs.pop_front(); - - return item; - } - return NULL; -} - - -int DirectMailService::tick() -{ - rslog(RSL_DEBUG_BASIC, directmailzone, - "DirectMailService::tick()"); - - incomingMsgs(); - return 0; -} - - -int DirectMailService::status() -{ - rslog(RSL_DEBUG_BASIC, directmailzone, - "DirectMailService::status()"); - - return 1; -} - -void DirectMailService::statusChange(const std::list &plist) -{ - /* should do it properly! */ - /* only do this when a new peer is connected */ - bool newPeers = false; - std::list::const_iterator it; - for(it = plist.begin(); it != plist.end(); it++) - { - if (it->actions & RS_SERVICE_PEER_CONNECTED) - { - newPeers = true; - } - } - - if (newPeers) - { - checkOutgoingMessages(); - } -} - - -int DirectMailService::incomingMsgs() -{ - RsItem *item; - int i = 0; - - while((item = recvItem()) != NULL) - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - RsMailChunkItem *mi = dynamic_cast(item); - RsMailAckItem *mai = dynamic_cast(item); - if (mi) - { - mIncomingMsgs.push_back(mi); - } - else if (mai) - { - mIncomingAckMsgs.push_back(mai); - } - else - { - std::cerr << "DirectMailService::incomingMsgs() Unknown incoming Msg"; - std::cerr << std::endl; - delete item; - } - ++i; - } - return i; -} - -// This is a Local copy of an Outgoing message - either SentBox or Draft. -bool DirectMailService::attemptToSend(RsItem *mi) -{ - RsPeerId pid = mi->PeerId(); - if (mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, pid)) - { - sendItem(mi); - return true; - } - - return false; -} - -void DirectMailService::checkOutgoingMessages() -{ - /* iterate through the outgoing queue and attempt to send. - */ - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::list::iterator mit; - for(mit = mOutgoingMsgs.begin(); mit != mOutgoingMsgs.end(); mit++) - { - if (attemptToSend(*mit)) - { - /* actually sent the message */ - mit = mOutgoingMsgs.erase(mit); - } - else - { - mit++; - } - } -} - -bool DirectMailService::haveIncomingMail() -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - if (!mIncomingMsgs.empty()) - { - return true; - } - - if (!mIncomingAckMsgs.empty()) - { - return true; - } - return false; -} - - diff --git a/libretroshare/src/unfinished/mail/directmailservice.h b/libretroshare/src/unfinished/mail/directmailservice.h deleted file mode 100644 index 7d6ce0d19..000000000 --- a/libretroshare/src/unfinished/mail/directmailservice.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * libretroshare/src/services/mail directmailservice.h - * - * Services for RetroShare. - * - * Copyright 2014 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#ifndef DIRECT_MAIL_SERVICE_HEADER -#define DIRECT_MAIL_SERVICE_HEADER - -#include "services/mail/mailtransport.h" -#include "services/p3service.h" - -#include "pqi/pqiservicemonitor.h" - -#include "util/rsthreads.h" - - -namespace Rs -{ -namespace Mail -{ - -class DirectMailService: public MailTransport, public p3Service, public pqiServiceMonitor -{ - -public: - DirectMailService(p3ServiceControl *sc); - virtual RsServiceInfo getServiceInfo(); - - /******* MailTransport Interface ********************************************************/ - - virtual bool CanSend(const RsTlvMailAddress &addr); - virtual bool haveIncomingMail(); - - virtual bool sendMail(RsMailChunkItem *msg); - virtual RsMailChunkItem *recvMail(); - virtual bool sendMailAck(RsMailAckItem *ack); - virtual RsMailAckItem *recvMailAck(); - - /******* MsgTransport Interface ********************************************************/ - - int tick(); - int status(); - - /*** Overloaded from pqiMonitor ***/ - virtual void statusChange(const std::list &plist); - /*** Overloaded from pqiMonitor ***/ - -private: - - int incomingMsgs(); - void checkOutgoingMessages(); - bool attemptToSend(RsItem *item); - - p3ServiceControl *mServiceCtrl; - - /* Mutex Required for stuff below */ - RsMutex mMsgMtx; - RsMailTransportSerialiser *mSerialiser ; - - /* outgoing messages */ - std::list mOutgoingMsgs; - - /* incoming msgs */ - std::list mIncomingMsgs; - std::list mIncomingAckMsgs; -}; - -} // namspace Msg -} // namspace Rs - -#endif // DIRECT_MESSAGE_SERVICE_HEADER diff --git a/libretroshare/src/unfinished/mail/mailtransport.cc b/libretroshare/src/unfinished/mail/mailtransport.cc deleted file mode 100644 index f342c9fd3..000000000 --- a/libretroshare/src/unfinished/mail/mailtransport.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* - * libretroshare/src/services/mail mailtransport.cc - * - * Services for RetroShare. - * - * Copyright 2014 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "services/mail/mailtransport.h" - -using namespace Rs::Mail; - -MailTransport::MailTransport(uint32_t max_size, uint16_t transport_type) -:mEnabled(true), mMaxSize(max_size), mTransportType(transport_type) -{ - return; -} - -bool MailTransport::isEnabled() -{ - return mEnabled; -} - -void MailTransport::setEnabled(bool enabled) -{ - mEnabled = enabled; -} - -uint32_t MailTransport::getMaxSize() -{ - return mMaxSize; -} - -uint16_t MailTransport::getTransportType() -{ - return mTransportType; -} - - diff --git a/libretroshare/src/unfinished/mail/mailtransport.h b/libretroshare/src/unfinished/mail/mailtransport.h deleted file mode 100644 index 0c6abac08..000000000 --- a/libretroshare/src/unfinished/mail/mailtransport.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once -#ifndef RS_MAIL_TRANSPORT_HEADER -#define RS_MAIL_TRANSPORT_HEADER -/* - * libretroshare/src/services/mail mailtransport.h - * - * Services for RetroShare. - * - * Copyright 2014 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include "serialiser/rsmailtransportitems.h" - - -namespace Rs -{ -namespace Mail -{ - -const uint32_t DEFAULT_MAX_MESSAGE_SIZE = (64 * 1024); - -// To decide how this will work! -const uint32_t ADDRESS_TYPE_PEER_ID = 0x001; -const uint32_t ADDRESS_TYPE_GXS_ID = 0x002; -const uint32_t ADDRESS_TYPE_EMAIL_ID = 0x003; - - -class MailTransport -{ -public: - MailTransport(uint32_t max_size, uint16_t transport_type); - virtual ~MailTransport(); - - virtual bool CanSend(const RsTlvMailAddress &addr) = 0; - virtual bool haveIncomingMail() = 0; - - virtual bool sendMail(RsMailChunkItem *msg) = 0; - virtual RsMailChunkItem *recvMail() = 0; - virtual bool sendMailAck(RsMailAckItem *ack) = 0; - virtual RsMailAckItem *recvMailAck() = 0; - - virtual bool isEnabled(); - virtual void setEnabled(bool enabled); - - uint32_t getMaxSize(); - uint16_t getTransportType(); - -private: - - bool mEnabled; - uint32_t mMaxSize; - uint16_t mTransportType; -}; - - -} // namespace Mail -} // namespace Rs - -#endif diff --git a/libretroshare/src/unfinished/p3portservice.cc b/libretroshare/src/unfinished/p3portservice.cc deleted file mode 100644 index af4b24a73..000000000 --- a/libretroshare/src/unfinished/p3portservice.cc +++ /dev/null @@ -1,123 +0,0 @@ -/* - * "$Id: p3PortService.cc,v 1.24 2007-05-05 16:10:06 rmf24 Exp $" - * - * Other Bits for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include "services/p3portservice.h" -#include "serialiser/rsserviceids.h" - -p3PortService::p3PortService(p3ConnectMgr *cm) - :p3Service(RS_SERVICE_TYPE_PORT), mConnMgr(cm), mEnabled(false) -{ - /* For Version 1, we'll just use the very simple RsRawItem packets - * which are handled in the RsServiceSerialiser - */ - addSerialType(new RsServiceSerialiser()); -} - -int p3PortService::tick() -{ -#ifdef PORT_DEBUG - std::cerr << "p3PortService::tick()"; - std::cerr << std::endl; -#endif - - /* discard data if not enabled */ - if (!mEnabled) - { - RsItem *i; - while(NULL != (i = recvItem())) - { - delete i; - } - } - - /* Rough list of what might happen (once the sockets are opened!) */ - - - /* check for data on sockets */ - //int sockfd; - RsRawItem *item; - - //while(0 < (len = recv(sockfd, ....))) ... etc. - { - - /* example of how to package data up - * We use RsRawItem as it'll handle a single binary chunk. - * This is enough for version 1.... but versions 2 + 3 will - * need their own serialiser. - * - * */ - - /* input data TODO! */ - void *data=NULL; - uint32_t len=0; - - uint32_t packetId = (((uint32_t) RS_PKT_VERSION_SERVICE) << 24) + - (((uint32_t) RS_SERVICE_TYPE_PORT) << 8); - - /* create Packet for RS Transport */ - RsRawItem *item = new RsRawItem(packetId, len); - void *item_data = item->getRawData(); - memcpy(item_data, data, len); - - /* set the correct peer destination. */ - item->PeerId(mPeerId); - - /* send data */ - sendItem(item); - - /* no delete -> packet cleaned up by RS internals */ - } - - - /* get any incoming data */ - while(NULL != (item = (RsRawItem*) recvItem())) - { - /* unpackage data */ - std::string src = item->PeerId(); -// void *item_data = item->getRawData(); -// uint32_t item_len = item->getRawLength(); - - /* push out to the socket .... */ - // send(sockfd, item_len, item_data....) - - /* cleanup packet */ - delete item; - } - - return 0; -} - -bool p3PortService::enablePortForwarding(uint32_t port, std::string peerId) -{ - mPort = port; - mPeerId = peerId; - mEnabled = true; - - return true; -} - - - diff --git a/libretroshare/src/unfinished/p3portservice.h b/libretroshare/src/unfinished/p3portservice.h deleted file mode 100644 index b1ef089f9..000000000 --- a/libretroshare/src/unfinished/p3portservice.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * libretroshare/src/services: p3portservice.h - * - * Services for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#ifndef SERVICE_PORT_FORWARD_HEADER -#define SERVICE_PORT_FORWARD_HEADER - -/* - * The start of a port forwarding service. - * - * This is just a very rough example of what might be required for version 1. - * - * FIRST VERSION: - * - * listen to a single port and send data with a single RS peer. - * - * - * SECOND VERSION: - * - * enable multiple port forwardings. - * - * each forwarding consists of a 'port, peerId & Connection Id'. - * - * THIRD VERSION: - * - * add broadcast/multicast forwardings. - * i.e. data gets sent to multiple peers. - * - * each forwarding with then consist of 'port, connectionId + list of peerIds' - * NOTE: version 3 needs some thought - might require a master host - * which distributes to all others.... or other more complicated systems. - * - */ - -#include -#include - -#include "serialiser/rsbaseitems.h" -#include "services/p3service.h" -#include "pqi/p3connmgr.h" - - -class p3PortService: public p3Service -{ - public: - p3PortService(p3ConnectMgr *cm); - - /* example setup functions */ -bool enablePortForwarding(uint32_t port, std::string peerId); - - /* overloaded */ -virtual int tick(); - - private: - - p3ConnectMgr *mConnMgr; - - bool mEnabled; - bool mPeerOnline; - - uint32_t mPort; - std::string mPeerId; - -}; - -#endif // SERVICE_PORT_FORWARD_HEADER diff --git a/libretroshare/src/unfinished/p3tunnel.cc b/libretroshare/src/unfinished/p3tunnel.cc deleted file mode 100644 index 50a10b56e..000000000 --- a/libretroshare/src/unfinished/p3tunnel.cc +++ /dev/null @@ -1,347 +0,0 @@ -/* - * libretroshare/src/services: p3tunnel.cc - * - * Services for RetroShare. - * - * Copyright 2004-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -//#include "retroshare/rsiface.h" -//#include "retroshare/rsinit.h" /* for PGPSSL flag */ -//#include "retroshare/rspeers.h" -#include "services/p3tunnel.h" -#include "pqi/pqissltunnel.h" - -#include "pqi/authssl.h" -#include "pqi/p3connmgr.h" - -#include - -#include "util/rsdebug.h" -#include "util/rsprint.h" -#include "util/rsversion.h" - -#define TUNNEL_HANDSHAKE_INIT 1 -#define TUNNEL_HANDSHAKE_ACK 2 -#define TUNNEL_HANDSHAKE_REFUSE 0 - - p3tunnel::p3tunnel(p3ConnectMgr *cm, pqipersongrp *perGrp) -:p3Service(RS_SERVICE_TYPE_TUNNEL), mConnMgr(cm), mPqiPersonGrp(perGrp) -{ - RsStackMutex stack(mTunnelMtx); /********** STACK LOCKED MTX ******/ - - ownId = mConnMgr->getOwnId(); - std::cerr << "ownId : " << mConnMgr->getOwnId() << std::endl; - addSerialType(new RsTunnelSerialiser()); - - return; -} - -void p3tunnel::statusChange(const std::list &plist) { -} - -int p3tunnel::tick() -{ - return handleIncoming(); -} - -int p3tunnel::handleIncoming() -{ - RsItem *item = NULL; - -#ifdef P3TUNNEL_DEBUG - //std::cerr << "p3tunnel::handleIncoming() called." << std::endl; -#endif - - int nhandled = 0; - // While messages read - while(NULL != (item = recvItem())) - { - if (!mConnMgr->getTunnelConnection()) { - //no tunnel allowed, just drop the packet - continue; - } - - RsTunnelDataItem *tdi = NULL; - RsTunnelHandshakeItem *thi = NULL; - - { -#ifdef P3TUNNEL_DEBUG - std::string out = "p3tunnel::handleIncoming() Received Message!\n"; - item -> print_string(out); - std::cerr << out; -#endif - } - - if (NULL != (tdi = dynamic_cast (item))) { - recvTunnelData(tdi); - nhandled++; - } else if (NULL != (thi = dynamic_cast (item))) { - recvTunnelHandshake(thi); - nhandled++; - } - delete item; - } - return nhandled; -} - -/*************************************************************************************/ -/* Output Network Msgs */ -/*************************************************************************************/ -void p3tunnel::sendTunnelData(std::string destPeerId, std::string relayPeerId, void *data, int data_length) { - sendTunnelDataPrivate(relayPeerId, ownId,relayPeerId, destPeerId, data, data_length); -} - - -void p3tunnel::sendTunnelDataPrivate(std::string to, std::string sourcePeerId, std::string relayPeerId, std::string destPeerId, void *data, int data_length) { - if (!mConnMgr->getTunnelConnection()) { - //no tunnel allowed, just drop the request - return; - } - - RsStackMutex stack(mTunnelMtx); /********** STACK LOCKED MTX ******/ - - // Then send message. - { -#ifdef P3TUNNEL_DEBUG - std::string out = "p3tunnel::sendTunnelDataPrivate() Constructing a RsTunnelItem Message!\n"; - out += "Sending to: " + to; - std::cerr << out << std::endl; -#endif - } - - // Construct a message - RsTunnelDataItem *rdi = new RsTunnelDataItem(); - rdi->destPeerId = destPeerId; - rdi->sourcePeerId = sourcePeerId; - rdi->relayPeerId = relayPeerId; - rdi->encoded_data_len = data_length; - - if(data_length > 0) - { - rdi->encoded_data = (void*)malloc(data_length); - memcpy(rdi->encoded_data, data, data_length); - } - - rdi->PeerId(to); - -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::sendTunnelDataPrivate() data_length : "<< data_length << std::endl; -#endif - /* send msg */ - sendItem(rdi); -} - -void p3tunnel::pingTunnelConnection(std::string relayPeerId, std::string destPeerId) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::pingTunnelConnection() sending ping with relay id : " << relayPeerId << std::endl; - std::cerr << "ownId : " << ownId << std::endl; - std::cerr << "destPeerId : " << destPeerId << std::endl; -#endif - this->sendTunnelDataPrivate(relayPeerId, ownId, relayPeerId, destPeerId, NULL, 0); -} - -void p3tunnel::initiateHandshake(std::string relayPeerId, std::string destPeerId) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::initiateHandshake() initiating handshake with relay id : " << relayPeerId << std::endl; - std::cerr << "ownId : " << ownId << std::endl; - std::cerr << "destPeerId : " << destPeerId << std::endl; -#endif - // Construct a message - RsTunnelHandshakeItem *rhi = new RsTunnelHandshakeItem(); - rhi->destPeerId = destPeerId; - rhi->sourcePeerId = ownId; - rhi->relayPeerId = relayPeerId; - rhi->connection_accepted = TUNNEL_HANDSHAKE_INIT; - rhi->sslCertPEM = AuthSSL::getAuthSSL()->SaveOwnCertificateToString(); - - rhi->PeerId(relayPeerId); - - /* send msg */ - sendItem(rhi); -} - -/*************************************************************************************/ -/* Input Network Msgs */ -/*************************************************************************************/ -void p3tunnel::recvTunnelHandshake(RsTunnelHandshakeItem *item) -{ -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() From: " << item->PeerId() << std::endl; -#endif - - RsPeerDetails pd; - if (!AuthSSL::getAuthSSL()->LoadDetailsFromStringCert(item->sslCertPEM, pd)) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() cert is not valid. This might be a intrusion attempt." << std::endl; -#endif - return; - } - - if (item->sourcePeerId != pd.id) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() cert is not issued from the source id of the tunnel. This might be a intrusion attempt." << std::endl; -#endif - return; - } - - //compare the peer id from the item sender to the ids in the item. - if (item->PeerId() == item->sourcePeerId && ownId == item->relayPeerId) { - if (mConnMgr->isOnline(item->destPeerId)) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() relaying packet." << std::endl; -#endif - //relaying the handshake - RsTunnelHandshakeItem* forwardItem = new RsTunnelHandshakeItem(); - forwardItem->sourcePeerId = item->sourcePeerId; - forwardItem->relayPeerId = item->relayPeerId; - forwardItem->destPeerId = item->destPeerId; - forwardItem->connection_accepted = item->connection_accepted; - forwardItem->sslCertPEM = item->sslCertPEM; - forwardItem->PeerId(item->destPeerId); - sendItem(forwardItem); - } else { - //sending back refuse - //not implemented -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() not relaying packet because destination is offline." << std::endl; -#endif - } - } else if (item->PeerId() == item->relayPeerId && ownId == item->destPeerId) { - if (item->connection_accepted == TUNNEL_HANDSHAKE_INIT || item->connection_accepted == TUNNEL_HANDSHAKE_ACK) { - //check if we accept connection - if (!mConnMgr->isFriend(pd.id)) { - //send back a refuse - // not implemented - } else { - if (item->connection_accepted == TUNNEL_HANDSHAKE_INIT) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() sending back acknowledgement to " << item->sourcePeerId << std::endl; -#endif - //send back acknowledgement - RsTunnelHandshakeItem* ack = new RsTunnelHandshakeItem(); - ack->sourcePeerId = ownId; - ack->relayPeerId = item->relayPeerId; - ack->destPeerId = item->sourcePeerId; - ack->connection_accepted = TUNNEL_HANDSHAKE_ACK; - ack->sslCertPEM = AuthSSL::getAuthSSL()->SaveOwnCertificateToString(); - ack->PeerId(item->relayPeerId); - sendItem(ack); - } - - //open the local tunnel connection -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() opening localy the tunnel connection emulation." << std::endl; -#endif - pqiperson *pers = mPqiPersonGrp->getPeer(item->sourcePeerId); - pqissltunnel *pqicon = (pqissltunnel *)(((pqiconnect *) pers->getKid(PQI_CONNECT_TUNNEL))->ni); - pqicon->IncommingHanshakePacket(item->relayPeerId); - } - } - } -} - - -void p3tunnel::recvTunnelData(RsTunnelDataItem *item) -{ -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvPeerConnectRequest() From: " << item->PeerId() << std::endl; -#endif - - //compare the peer id from the item sender to the ids in the item. - if (item->PeerId() == item->sourcePeerId && ownId == item->relayPeerId) { - privateRecvTunnelDataRelaying(item); - } else if (item->PeerId() == item->relayPeerId && ownId == item->destPeerId) { - privateRecvTunnelDataDestination(item); - } -} - -void p3tunnel::privateRecvTunnelDataRelaying(RsTunnelDataItem *item) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataRelaying() I am relaying, let's see if it's possible to send the packet to destination." << std::endl; -#endif - if (!mConnMgr->isFriend(item->sourcePeerId) || !mConnMgr->isFriend(item->destPeerId)) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() not trusting relay or dest peer. Aborting." << std::endl; -#endif - return; - } - if (mConnMgr->isOnline(item->destPeerId)) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataRelaying() I am relaying, relay the packet to destination." << std::endl; -#endif - sendTunnelDataPrivate(item->destPeerId, item->sourcePeerId, ownId, item->destPeerId, item->encoded_data, item->encoded_data_len); - return; - } -} - -void p3tunnel::privateRecvTunnelDataDestination(RsTunnelDataItem *item) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() I am the destination Id, let's make some checks and read the packet." << std::endl; -#endif - - if (!mConnMgr->isFriend(item->sourcePeerId) || !mConnMgr->isFriend(item->relayPeerId)) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() not trusting relay or source peer. Aborting." << std::endl; -#endif - return; - } - - if (!mConnMgr->isOnline(item->relayPeerId)) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() relay peer is not connected, connection impossible. Aborting." << std::endl; -#endif - return; - } - - pqiperson *pers = mPqiPersonGrp->getPeer(item->sourcePeerId); - if (pers == NULL) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() tunnel connection not found. Aborting." << std::endl; -#endif - return; - } - - pqissltunnel *pqicon = (pqissltunnel *)(((pqiconnect *) pers->getKid(PQI_CONNECT_TUNNEL))->ni); - if (pqicon == NULL || !pqicon->isactive()) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() tunnel connection not found. Aborting." << std::endl; -#endif - return; - } - - //send the packet to the net emulation layer - if (item->encoded_data_len == 0) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() receiving a ping packet, activating connection and sending back acknowlegment." << std::endl; -#endif - pqissltunnel *pqicon = (pqissltunnel *)(((pqiconnect *) pers->getKid(PQI_CONNECT_TUNNEL))->ni); - pqicon->IncommingPingPacket(); - } else { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() receiving a data packet, transfer it to the pqissltunnel connection." << std::endl; - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() getRsItemSize(item->encoded_data) : " << getRsItemSize(item->encoded_data) << std::endl; -#endif - pqissltunnel *pqicon = (pqissltunnel *)(((pqiconnect *) pers->getKid(PQI_CONNECT_TUNNEL))->ni); - pqicon->addIncomingPacket(item->encoded_data, item->encoded_data_len); - } - return; -} diff --git a/libretroshare/src/unfinished/p3tunnel.h b/libretroshare/src/unfinished/p3tunnel.h deleted file mode 100644 index ec5a03896..000000000 --- a/libretroshare/src/unfinished/p3tunnel.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * libretroshare/src/services: p3tunnel.h - * - * Services for RetroShare. - * - * Copyright 2004-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef MRK_PQI_TUNNEL_H -#define MRK_PQI_TUNNEL_H - -// The AutoDiscovery Class - -#include "pqi/pqipersongrp.h" - -// system specific network headers -#include "pqi/pqi.h" - -class p3ConnectMgr; - -#include "pqi/pqimonitor.h" -#include "services/p3service.h" -#include "serialiser/rstunnelitems.h" -#include "pqi/authssl.h" - -class p3tunnel: public p3Service, public pqiMonitor -{ - public: - -virtual void statusChange(const std::list &plist); - - p3tunnel(p3ConnectMgr *cm, pqipersongrp *persGrp); - -int tick(); - -void sendTunnelData(std::string destPeerId, std::string relayPeerId, void *data, int data_length); - -void pingTunnelConnection(std::string relayPeerId, std::string destPeerId); -void initiateHandshake(std::string relayPeerId, std::string destPeerId); - - private: - -void sendTunnelDataPrivate(std::string to, std::string sourcePeerId, std::string relayPeerId, std::string destPeerId, void *data, int data_length); - -void privateRecvTunnelDataRelaying(RsTunnelDataItem *item); //invoked when I am relaying -void privateRecvTunnelDataDestination(RsTunnelDataItem *item); //invoked when I am the destination of the tunnel - - /* Network Input */ -int handleIncoming(); -void recvTunnelData(RsTunnelDataItem *item); -void recvTunnelHandshake(RsTunnelHandshakeItem *item); - - - private: - - p3ConnectMgr *mConnMgr; - pqipersongrp *mPqiPersonGrp; - std::string ownId; - - - /* data */ - RsMutex mTunnelMtx; -}; - -#endif // MRK_PQI_TUNNEL_H diff --git a/libretroshare/src/unfinished/rstlvdsdv.cc b/libretroshare/src/unfinished/rstlvdsdv.cc deleted file mode 100644 index da3abe8c5..000000000 --- a/libretroshare/src/unfinished/rstlvdsdv.cc +++ /dev/null @@ -1,419 +0,0 @@ - -/* - * libretroshare/src/serialiser: rstlvtypes.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie, Chris Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "rstlvdsdv.h" -#include "rsbaseserial.h" - - -/************************************* RsTlvDsdvEndPoint ************************************/ - -RsTlvDsdvEndPoint::RsTlvDsdvEndPoint() - :RsTlvItem(), idType(0) -{ - return; -} - -void RsTlvDsdvEndPoint::TlvClear() -{ - idType = 0; - anonChunk.clear(); - serviceId.clear(); -} - -uint32_t RsTlvDsdvEndPoint::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header + 4 + str + str */ - - s += 4; // idType; - s += GetTlvStringSize(anonChunk); - s += GetTlvStringSize(serviceId); - - return s; - -} - -bool RsTlvDsdvEndPoint::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_DSDV_ENDPOINT, tlvsize); - - ok &= setRawUInt32(data, tlvend, offset, idType); - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, anonChunk); - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_HASH_SHA1, serviceId); - return ok; - -} - - -bool RsTlvDsdvEndPoint::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_DSDV_ENDPOINT) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - ok &= getRawUInt32(data, tlvend, offset, &(idType)); - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, anonChunk); - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_HASH_SHA1, serviceId); - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvDsdvEndPoint::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - -std::ostream &RsTlvDsdvEndPoint::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvDsdvEndPoint", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "idType:" << idType; - out << std::endl; - - printIndent(out, int_Indent); - out << "AnonChunk:" << anonChunk; - out << std::endl; - - printIndent(out, int_Indent); - out << "ServiceId:" << serviceId; - out << std::endl; - - printEnd(out, "RsTlvDsdvEndPoint", indent); - return out; -} - - -/************************************* RsTlvDsdvEntry ************************************/ - -RsTlvDsdvEntry::RsTlvDsdvEntry() - :RsTlvItem(), sequence(0), distance(0) -{ - return; -} - -void RsTlvDsdvEntry::TlvClear() -{ - endPoint.TlvClear(); - sequence = 0; - distance = 0; -} - -uint32_t RsTlvDsdvEntry::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header + EndPoint.Size + 4 + 4 */ - - s += endPoint.TlvSize(); - s += 4; // sequence; - s += 4; // distance; - - return s; - -} - -bool RsTlvDsdvEntry::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_DSDV_ENTRY, tlvsize); - - ok &= endPoint.SetTlv(data, size, offset); - ok &= setRawUInt32(data, tlvend, offset, sequence); - ok &= setRawUInt32(data, tlvend, offset, distance); - - return ok; - -} - - -bool RsTlvDsdvEntry::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_DSDV_ENTRY) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - ok &= endPoint.GetTlv(data, size, offset); - ok &= getRawUInt32(data, tlvend, offset, &(sequence)); - ok &= getRawUInt32(data, tlvend, offset, &(distance)); - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvDsdvEntry::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - -std::ostream &RsTlvDsdvEntry::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvDsdvEntry", indent); - uint16_t int_Indent = indent + 2; - - endPoint.print(out, int_Indent); - - printIndent(out, int_Indent); - out << "Sequence:" << sequence; - out << std::endl; - - printIndent(out, int_Indent); - out << "Distance:" << distance; - out << std::endl; - - printEnd(out, "RsTlvDsdvEntry", indent); - return out; -} - - -/************************************* RsTlvDsdvEntrySet ************************************/ - -#if 0 -RsTlvDsdvEntrySet::RsTlvDsdvEntrySet() -{ - -} - -void RsTlvDsdvEntrySet::TlvClear() -{ - entries.clear(); -} - -uint32_t RsTlvDsdvEntrySet::TlvSize() -{ - - uint32_t s = TLV_HEADER_SIZE; /* header */ - - std::list::iterator it; - - - if(!entries.empty()) - { - - for(it = entries.begin(); it != entries.end() ; ++it) - s += it->TlvSize(); - - } - - return s; -} - -bool RsTlvDsdvEntrySet::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_DSDV_ENTRY_SET , tlvsize); - - if(!entries.empty()) - { - std::list::iterator it; - - for(it = entries.begin(); it != entries.end() ; ++it) - ok &= it->SetTlv(data, size, offset); - } - - - return ok; - -} - - -bool RsTlvDsdvEntrySet::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_DSDV_ENTRY_SET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - switch(tlvsubtype) - { - case TLV_TYPE_DSDV_ENTRY: - { - RsTlvDsdvEntry entry; - ok &= entry.GetTlv(data, size, offset); - if (ok) - { - entries.push_back(entry); - } - } - break; - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - - } - - if (!ok) - break; - } - - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvDsdvEntrySet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -// prints out contents of RsTlvDsdvEntrySet -std::ostream &RsTlvDsdvEntrySet::print(std::ostream &out, uint16_t indent) -{ - printBase(out, "RsTlvDsdvEntrySet", indent); - uint16_t int_Indent = indent + 2; - - std::list::iterator it; - for(it = entries.begin(); it != entries.end() ; ++it) - it->print(out, int_Indent); - - printEnd(out, "RsTlvDsdvEntrySet", indent); - return out; -} - - -#endif - - diff --git a/libretroshare/src/unfinished/rstlvdsdv.h b/libretroshare/src/unfinished/rstlvdsdv.h deleted file mode 100644 index b815bb4ed..000000000 --- a/libretroshare/src/unfinished/rstlvdsdv.h +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once - -/* - * libretroshare/src/serialiser: rstlvdsdv.h - * - * RetroShare Serialiser. - * - * Copyright 2011 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvlist.h" - -#define RSDSDV_MAX_ROUTE_TABLE 1000 - -class RsTlvDsdvEndPoint: public RsTlvItem -{ - public: - RsTlvDsdvEndPoint(); -virtual ~RsTlvDsdvEndPoint() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint32_t idType; - std::string anonChunk; - std::string serviceId; -}; - -class RsTlvDsdvEntry: public RsTlvItem -{ - public: - RsTlvDsdvEntry(); -virtual ~RsTlvDsdvEntry() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - RsTlvDsdvEndPoint endPoint; - uint32_t sequence; - uint32_t distance; -}; - -typedef t_RsTlvList RsTlvDsdvEntrySet; - -#if 0 -class RsTlvDsdvEntrySet: public RsTlvItem -{ - public: - RsTlvDsdvEntrySet(); -virtual ~RsTlvDsdvEntrySet() { return; } -virtual uint32_t TlvSize(); -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ -virtual std::ostream &print(std::ostream &out, uint16_t indent); - - std::list entries; -}; - -#endif - diff --git a/libretroshare/src/unused/p3dsdv.cc b/libretroshare/src/unused/p3dsdv.cc deleted file mode 100644 index 53880111b..000000000 --- a/libretroshare/src/unused/p3dsdv.cc +++ /dev/null @@ -1,910 +0,0 @@ -/******************************************************************************* - * libretroshare/src/unused: p3dsdv.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include -#include "util/rstime.h" - -//#include "serialiser/rsdsdvitems.h" -#include "services/p3dsdv.h" -#include "pqi/p3linkmgr.h" -#include "util/rsrandom.h" - -#include - -/**** - * #define DEBUG_DSDV 1 - ****/ -#define DEBUG_DSDV 1 - -/* DEFINE INTERFACE POINTER! */ -RsDsdv *rsDsdv = NULL; - -/***** - * Routing Services are provided for any service or peer that wants to access / receive info - * over the internal network. - * - * This is going to be based loosely on Ben's Algorithm... - * Each Service / Peer is identified by a HASH. - * This HASH is disguised by a temporary ANON-CHUNK. - * DSDVID = Sha1(ANONCHUNK + HASH). - * - * Each peer can advertise as many Services as they want. - * The Anon-chunk should be rotated regularly to hide it well. - * period to be defined. - * - * - * Once this Routing table has been established, Routes can be created - in a similar manner to turtle paths. - * (Send Path request (Path Id + Origin + Destination))... path is established. - * - * Then we can do Onion Routing etc, on top of this. - * - ****/ - -p3Dsdv::p3Dsdv(p3ServiceControl *sc) - :p3Service(), /* p3Config(CONFIG_TYPE_DSDV), */ mDsdvMtx("p3Dsdv"), mServiceCtrl(sc) -{ - addSerialType(new RsDsdvSerialiser()); - - mSentTablesTime = 0; - mSentIncrementTime = 0; -} - -const std::string DSDV_APP_NAME = "dsdv"; -const uint16_t DSDV_APP_MAJOR_VERSION = 1; -const uint16_t DSDV_APP_MINOR_VERSION = 0; -const uint16_t DSDV_MIN_MAJOR_VERSION = 1; -const uint16_t DSDV_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3Dsdv::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_DSDV, - DSDV_APP_NAME, - DSDV_APP_MAJOR_VERSION, - DSDV_APP_MINOR_VERSION, - DSDV_MIN_MAJOR_VERSION, - DSDV_MIN_MINOR_VERSION); -} - - - -int p3Dsdv::tick() -{ - processIncoming(); - sendTables(); - - return 0; -} - -int p3Dsdv::status() -{ - return 1; -} - -#define DSDV_BROADCAST_PERIOD (60*10) // 10 Minutes. -#define DSDV_MIN_INCREMENT_PERIOD 5 -#define DSDV_DISCARD_PERIOD (DSDV_BROADCAST_PERIOD * 2) - -int p3Dsdv::sendTables() -{ - rstime_t now = time(NULL); - rstime_t tt, it; - bool updateRequired = false; - { - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - tt = mSentTablesTime; - it = mSentIncrementTime; - updateRequired = mSignificantChanges; - } - - if (now - tt > DSDV_BROADCAST_PERIOD) - { - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::sendTables() Broadcast Time"; - std::cerr << std::endl; -#endif - selectStableRoutes(); - clearOldRoutes(); - - generateRoutingTables(false); - - printDsdvTable(std::cerr); - - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - mSentTablesTime = now; - mSentIncrementTime = now; - - return true ; - } - - /* otherwise send incremental changes */ - if ((updateRequired) && (now - it > DSDV_MIN_INCREMENT_PERIOD)) - { - selectStableRoutes(); - - generateRoutingTables(true); - - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - mSentIncrementTime = now; - } - - return true; -} - -#define RSDSDV_SEQ_INCREMENT 2 - -void p3Dsdv::advanceLocalSequenceNumbers() -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - rstime_t now = time(NULL); - - std::map::iterator it; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - RsDsdvTableEntry &v = (it->second); - if (v.mOwnSource) - { - v.mStableRoute.mSequence += RSDSDV_SEQ_INCREMENT; - v.mStableRoute.mReceived = now; - } - } -} - -void p3Dsdv::clearSignificantChangesFlags() -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator it; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - RsDsdvTableEntry &v = (it->second); - if (v.mFlags & RSDSDV_FLAGS_SIGNIFICANT_CHANGE) - { - v.mFlags &= ~RSDSDV_FLAGS_SIGNIFICANT_CHANGE; - } - } - mSignificantChanges = false; -} - - -int p3Dsdv::generateRoutingTables(bool incremental) -{ - /* we ping our peers */ - /* who is online? */ - std::set idList; - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, idList); - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::generateRoutingTables(" << incremental << ")"; - std::cerr << std::endl; -#endif - - if (!incremental) - { - /* now clear significant flag */ - advanceLocalSequenceNumbers(); - } - - /* prepare packets */ - std::set::iterator it; - for(it = idList.begin(); it != idList.end(); ++it) - { -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::generateRoutingTables() For: " << *it; - std::cerr << std::endl; -#endif - - generateRoutingTable(*it, incremental); - } - - - /* now clear significant flag */ - clearSignificantChangesFlags(); - return 1; -} - - -int p3Dsdv::generateRoutingTable(const RsPeerId &peerId, bool incremental) -{ - RsDsdvRouteItem *dsdv = new RsDsdvRouteItem(); - dsdv->PeerId(peerId); - - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator it; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - RsDsdvTableEntry &v = (it->second); - - /* discard/ignore criterion */ - if (!v.mIsStable) - { - continue; - } - - if (v.mStableRoute.mDistance >= RSDSDV_MAX_DISTANCE) - { - continue; - } - - if (incremental) - { - if (v.mFlags & RSDSDV_FLAGS_SIGNIFICANT_CHANGE) - { - // Done elsewhere. - //v.mFlags &= ~SIGNIFICANT_CHANGE; - } - else - { - /* ignore non-significant changes */ - continue; - } - } - - RsTlvDsdvEntry entry; - - entry.endPoint.idType = v.mDest.mIdType; - entry.endPoint.anonChunk = v.mDest.mAnonChunk; - entry.endPoint.serviceId = v.mDest.mHash; - entry.sequence = v.mStableRoute.mSequence; - entry.distance = v.mStableRoute.mDistance; - - //dsdv->routes.entries.push_back(entry); - dsdv->routes.mList.push_back(entry); - - //if (dsdv->routes.entries.size() > RSDSDV_MAX_ROUTE_TABLE) - if (dsdv->routes.mList.size() > RSDSDV_MAX_ROUTE_TABLE) - { - sendItem(dsdv); - dsdv = new RsDsdvRouteItem(); - dsdv->PeerId(peerId); - } - } - sendItem(dsdv); - return 1; -} - - -/**************************************************************************** - ****************************************************************************/ - -int p3Dsdv::processIncoming() -{ - /* for each packet - pass to specific handler */ - RsItem *item = NULL; - while(NULL != (item = recvItem())) - { - switch(item->PacketSubType()) - { - default: - break; - case RS_PKT_SUBTYPE_DSDV_ROUTE: - { - handleDSDV((RsDsdvRouteItem *) item); - } - break; - } - - /* clean up */ - delete item; - } - return true ; -} - - -int p3Dsdv::handleDSDV(RsDsdvRouteItem *dsdv) -{ - /* iterate over the entries */ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - rstime_t now = time(NULL); - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::handleDSDV() Received Pkt from: " << dsdv->PeerId(); - std::cerr << std::endl; - //dsdv->print(std::cerr); - //std::cerr << std::endl; -#endif - - std::list::iterator it; - //for(it = dsdv->routes.entries.begin(); it != dsdv->routes.entries.end(); ++it) - for(it = dsdv->routes.mList.begin(); it != dsdv->routes.mList.end(); ++it) - { - /* check for existing */ - RsTlvDsdvEntry &entry = *it; - uint32_t realDistance = entry.distance + 1; // metric. - - - /* find the entry */ - std::map::iterator tit; - tit = mTable.find(entry.endPoint.serviceId); - if (tit == mTable.end()) - { -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::handleDSDV() Adding Entry for New ServiceId: "; - std::cerr << entry.endPoint.serviceId; - std::cerr << std::endl; -#endif - /* new entry! */ - RsDsdvTableEntry v; - v.mDest.mIdType = entry.endPoint.idType; - v.mDest.mAnonChunk = entry.endPoint.anonChunk; - v.mDest.mHash = entry.endPoint.serviceId; - - /* add as a possible route */ - RsDsdvRoute newRoute; - - newRoute.mNextHop = dsdv->PeerId(); - newRoute.mReceived = now; - newRoute.mSequence = entry.sequence; - newRoute.mDistance = realDistance; - newRoute.mValidSince = now; - - v.mAllRoutes[dsdv->PeerId()] = newRoute; - v.mIsStable = false; - - v.mFlags = RSDSDV_FLAGS_NEW_ROUTE; - v.mOwnSource = false; - v.mMatched = false; - - // store in table. - mTable[v.mDest.mHash] = v; - } - else - { - RsDsdvTableEntry &v = tit->second; - if (v.mOwnSource) - { -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::handleDSDV() Ignoring OwnSource Entry:"; - std::cerr << entry.endPoint.serviceId; - std::cerr << std::endl; -#endif - continue; // Ignore if we are source. - } - - /* look for this in mAllRoutes */ - std::map::iterator rit; - rit = v.mAllRoutes.find(dsdv->PeerId()); - if (rit == v.mAllRoutes.end()) - { - /* add a new entry in */ - RsDsdvRoute newRoute; - - newRoute.mNextHop = dsdv->PeerId(); - newRoute.mReceived = now; - newRoute.mSequence = entry.sequence; - newRoute.mDistance = realDistance; - newRoute.mValidSince = now; - - v.mAllRoutes[dsdv->PeerId()] = newRoute; - - /* if we've just added it in - can't be stable one */ -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::handleDSDV() Adding NewRoute Entry:"; - std::cerr << entry.endPoint.serviceId; - std::cerr << std::endl; -#endif - } - else - { - if (rit->second.mSequence >= entry.sequence) - { -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::handleDSDV() Ignoring OLDSEQ Entry:"; - std::cerr << entry.endPoint.serviceId; - std::cerr << std::endl; -#endif - /* ignore same/old sequence number??? */ - continue; - } -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::handleDSDV() Updating Entry:"; - std::cerr << entry.endPoint.serviceId; - std::cerr << std::endl; -#endif - - /* update seq,dist,etc */ - if (rit->second.mSequence + 2 < entry.sequence) - { - /* skipped a sequence number - reset timer */ - rit->second.mValidSince = now; - } - - //rit->second.mNextHop; // unchanged. - rit->second.mReceived = now; - rit->second.mSequence = entry.sequence; - rit->second.mDistance = realDistance; - - /* if consistent route... maintain */ - if ((v.mIsStable) && - (rit->second.mNextHop == v.mStableRoute.mNextHop)) - { - v.mStableRoute = rit->second; - } - else - { - /* otherwise we need to wait - see if we get new update */ - } - } - } - } - return 1; -} - - -int p3Dsdv::selectStableRoutes() -{ - /* iterate over the entries */ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - rstime_t now = time(NULL); - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::selectStableRoutes()"; - std::cerr << std::endl; -#endif - - /* find the entry */ - std::map::iterator tit; - for(tit = mTable.begin(); tit != mTable.end(); ++tit) - { - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::selectStableRoutes() For Entry: "; - std::cerr << tit->second; - std::cerr << std::endl; -#endif - if (tit->second.mOwnSource) - { -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::selectStableRoutes() OwnSource... Ignoring"; - std::cerr << std::endl; -#endif - continue; // Ignore if we are source. - } - - std::map::iterator rit; - uint32_t newest = 0; - RsPeerId newestId; - uint32_t closest = RSDSDV_MAX_DISTANCE + 1; - RsPeerId closestId; - rstime_t closestAge = 0; - - /* find newest sequence number */ - for(rit = tit->second.mAllRoutes.begin(); - rit != tit->second.mAllRoutes.end(); ++rit) - { - if ((now - rit->second.mReceived <= DSDV_DISCARD_PERIOD) && - (rit->second.mSequence >= newest)) - { - newest = rit->second.mSequence; - newestId = rit->first; - - /* also becomes default for closest (later) */ - closest = rit->second.mDistance; - closestId = rit->first; - closestAge = now - rit->second.mValidSince; - } - } - - if (closest >= RSDSDV_MAX_DISTANCE + 1) - { -#ifdef DEBUG_DSDV - std::cerr << "\tNo Suitable Route"; - std::cerr << std::endl; -#endif - tit->second.mIsStable = false; - continue; - } - - uint32_t currseq = newest - (newest % 2); // remove 'kill'=ODD Seq. - -#ifdef DEBUG_DSDV - std::cerr << "\t Newest Seq: " << newest << " from: " << newestId; - std::cerr << std::endl; -#endif - - /* find closest distance - with valid seq & max valid time */ - for(rit = tit->second.mAllRoutes.begin(); - rit != tit->second.mAllRoutes.end(); ++rit) - { - /* Maximum difference in Sequence number is 2*DISTANCE - * Otherwise it must be old. - */ - if (rit->second.mSequence + rit->second.mDistance * 2 < currseq) - { -#ifdef DEBUG_DSDV - std::cerr << "\t\tIgnoring OLD SEQ Entry: " << rit->first; - std::cerr << std::endl; -#endif - - continue; // ignore. - } - - /* if we haven't received an update in ages - old */ - if (now - rit->second.mReceived > DSDV_DISCARD_PERIOD) - { -#ifdef DEBUG_DSDV - std::cerr << "\t\tIgnoring OLD TIME Entry: " << rit->first; - std::cerr << std::endl; -#endif - - continue; // ignore. - } - - if (rit->second.mDistance < closest) - { - closest = rit->second.mDistance; - closestId = rit->first; - closestAge = now - rit->second.mValidSince; -#ifdef DEBUG_DSDV - std::cerr << "\t\tUpdating to Closer Entry: " << rit->first; - std::cerr << std::endl; -#endif - } - else if ((rit->second.mDistance == closest) && - (closestAge < now - rit->second.mValidSince)) - { - /* have a more stable (older) one */ - closest = rit->second.mDistance; - closestId = rit->first; - closestAge = now - rit->second.mValidSince; -#ifdef DEBUG_DSDV - std::cerr << "\t\tUpdating to Stabler Entry: " << rit->first; - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_DSDV - std::cerr << "\t\tIgnoring Distant Entry: " << rit->first; - std::cerr << std::endl; -#endif - } - - } - - tit->second.mIsStable = true; - rit = tit->second.mAllRoutes.find(closestId); - tit->second.mStableRoute = rit->second; - tit->second.mFlags &= ~RSDSDV_FLAGS_NEW_ROUTE; - -#ifdef DEBUG_DSDV - std::cerr << "\tStable Route: " << tit->second.mStableRoute; - std::cerr << std::endl; -#endif - } - return 1; -} - - - - -int p3Dsdv::clearOldRoutes() -{ - /* iterate over the entries */ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::clearOldRoutes()"; - std::cerr << std::endl; -#endif - - /* find the entry */ - std::map::iterator it, it2; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - if (it->second.mOwnSource) - { - continue; - } - - if (it->second.mIsStable) - { - continue; - } - - if (it->second.mFlags & RSDSDV_FLAGS_NEW_ROUTE) - { - continue; - } - - /* backstep iterator for loop, and delete original */ - it2 = it; - it--; - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::clearOldRoutes() Deleting OLD ServiceId: " << it2->first; - std::cerr << std::endl; -#endif - mTable.erase(it2); - } - return 1; -} - - -/*************** pqiMonitor callback ***********************/ -void p3Dsdv::statusChange(const std::list &plist) -{ - std::list::const_iterator it; - for(it = plist.begin(); it != plist.end(); ++it) - { - /* only care about disconnected / not friends cases */ - if ( 1 ) - { - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - - - - - } - } -} - -int p3Dsdv::addTestService() -{ - RsDsdvId testId; - - int rndhash1[SHA_DIGEST_LENGTH / 4]; - int rndhash2[SHA_DIGEST_LENGTH / 4]; - std::string realHash; - std::string seedHash; - - for(int i = 0; i < SHA_DIGEST_LENGTH / 4; i++) - { - rndhash1[i] = RSRandom::random_u32(); - rndhash2[i] = RSRandom::random_u32(); - } - - for(int i = 0; i < SHA_DIGEST_LENGTH; i++) - { - rs_sprintf_append(realHash, "%02x", (uint32_t) ((uint8_t *) rndhash1)[i]); - rs_sprintf_append(seedHash, "%02x", (uint32_t) ((uint8_t *) rndhash2)[i]); - } - - - uint8_t sha_hash[SHA_DIGEST_LENGTH]; - memset(sha_hash,0,SHA_DIGEST_LENGTH*sizeof(uint8_t)) ; - SHA_CTX *sha_ctx = new SHA_CTX; - SHA1_Init(sha_ctx); - - SHA1_Update(sha_ctx, realHash.c_str(), realHash.length()); - SHA1_Update(sha_ctx, seedHash.c_str(), seedHash.length()); - SHA1_Final(sha_hash, sha_ctx); - delete sha_ctx; - - for(int i = 0; i < SHA_DIGEST_LENGTH; i++) - { - rs_sprintf_append(testId.mHash, "%02x", (uint32_t) (sha_hash)[i]); - } - - testId.mIdType = RSDSDV_IDTYPE_TEST; - testId.mAnonChunk = seedHash; - - addDsdvId(&testId, realHash); - return 1; -} - - -int p3Dsdv::addDsdvId(RsDsdvId *id, std::string realHash) -{ - - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::addDsdvId() ID: " << *id << " RealHash: " << realHash; - std::cerr << std::endl; -#endif - - rstime_t now = time(NULL); - - /* check for duplicate */ - std::map::iterator it; - it = mTable.find(id->mHash); - if (it != mTable.end()) - { - /* error */ - std::cerr << "p3Dsdv::addDsdvId() ERROR Duplicate ID"; - std::cerr << std::endl; - - return 0; - } - - /* new entry! */ - RsDsdvTableEntry v; - v.mDest = *id; - - v.mStableRoute.mNextHop = mServiceCtrl->getOwnId(); - v.mStableRoute.mReceived = now; - v.mStableRoute.mValidSince = now; - v.mStableRoute.mSequence = 0; - v.mStableRoute.mDistance = 0; - v.mIsStable = true; - - v.mFlags = RSDSDV_FLAGS_OWN_SERVICE; - v.mOwnSource = true; - v.mMatched = true; - v.mMatchedHash = realHash; - - // store in table. - mTable[v.mDest.mHash] = v; - - return 1; -} - - - - -int p3Dsdv::dropDsdvId(RsDsdvId *id) -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::dropDsdvId() ID: " << *id; - std::cerr << std::endl; -#endif - - /* This should send out an infinity packet... and flag for deletion */ - - std::map::iterator it; - it = mTable.find(id->mHash); - if (it == mTable.end()) - { - /* error */ - std::cerr << "p3Dsdv::addDsdvId() ERROR Unknown ID"; - std::cerr << std::endl; - - return 0; - } - - mTable.erase(it); - - return 1; -} - - -int p3Dsdv::printDsdvTable(std::ostream &out) -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - /* iterate over the entries */ - std::map::iterator it; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - RsDsdvTableEntry &v = it->second; - out << v; - out << std::endl; - } - return 1; -} - -/*****************************************/ - -uint32_t p3Dsdv::getLocalServices(std::list &hashes) -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - /* iterate over the entries */ - std::map::iterator it; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - if (it->second.mOwnSource) - { - hashes.push_back(it->first); - } - } - return 1; -} - - -uint32_t p3Dsdv::getAllServices(std::list &hashes) -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - /* iterate over the entries */ - std::map::iterator it; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - hashes.push_back(it->first); - } - return 1; -} - - -int p3Dsdv::getDsdvEntry(const std::string &hash, RsDsdvTableEntry &entry) -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - /* iterate over the entries */ - std::map::iterator it; - it = mTable.find(hash); - if (it == mTable.end()) - { - return 0; - } - - entry = it->second; - - return 1; -} - -std::ostream &operator<<(std::ostream &out, const RsDsdvId &id) -{ - out << "[Type: " << id.mIdType << " AMZ: " << id.mAnonChunk << " THASH: " << id.mHash; - out << "]"; - - return out; -} - - -std::ostream &operator<<(std::ostream &out, const RsDsdvRoute &route) -{ - rstime_t now = time(NULL); - out << "< Seq: " << route.mSequence << " Dist: " << route.mDistance; - out << " NextHop: " << route.mNextHop; - out << " recvd: " << now-route.mReceived; - out << " validSince: " << now-route.mValidSince; - out << " >"; - - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsDsdvTableEntry &entry) -{ - out << "DSDV Route for: " << entry.mDest << std::endl; - if (entry.mIsStable) - { - out << "\tStable: " << entry.mStableRoute << std::endl; - } - else - { - out << "\tNo Stable Route" << std::endl; - } - - out << "\tOwnSource: " << entry.mOwnSource; - out << " Flags: " << entry.mFlags; - if (entry.mMatched) - { - out << " Matched: " << entry.mMatchedHash; - } - else - { - out << " Non Matched"; - } - out << std::endl; - if (entry.mAllRoutes.size() > 0) - { - out << "\tAll Routes:" << std::endl; - } - - std::map::const_iterator it; - for(it = entry.mAllRoutes.begin(); it != entry.mAllRoutes.end(); ++it) - { - out << "\t\t" << it->second << std::endl; - } - return out; -} - - diff --git a/libretroshare/src/unused/p3dsdv.h b/libretroshare/src/unused/p3dsdv.h deleted file mode 100644 index 049ed8695..000000000 --- a/libretroshare/src/unused/p3dsdv.h +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - * libretroshare/src/unused: p3dsdv.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef SERVICE_RSDSDV_HEADER -#define SERVICE_RSDSDV_HEADER - -#include -#include - -#include "serialiser/rsdsdvitems.h" -#include "services/p3service.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/pqimonitor.h" - -#include "retroshare/rsdsdv.h" - -class p3ServiceControl; - - -#define RSDSDV_MAX_DISTANCE 3 -#define RSDSDV_MAX_SEND_TABLE 100 - -//!The RS DSDV service. - /** - * - * Finds RS wide paths to Services and Peers. - */ - -class p3Dsdv: public RsDsdv, public p3Service /* , public p3Config */, public pqiServiceMonitor -{ - public: - p3Dsdv(p3ServiceControl *cm); -virtual RsServiceInfo getServiceInfo(); - - /*** internal librs interface ****/ - -int addDsdvId(RsDsdvId *id, std::string realHash); -int dropDsdvId(RsDsdvId *id); -int printDsdvTable(std::ostream &out); - -int addTestService(); - - private: - -int sendTables(); -void advanceLocalSequenceNumbers(); -void clearSignificantChangesFlags(); - - -int generateRoutingTables(bool incremental); -int generateRoutingTable(const RsPeerId &peerId, bool incremental); - -int processIncoming(); - -int handleDSDV(RsDsdvRouteItem *dsdv); - -int selectStableRoutes(); -int clearOldRoutes(); - - public: - - /***** overloaded from rsDsdv *****/ - -virtual uint32_t getLocalServices(std::list &hashes); -virtual uint32_t getAllServices(std::list &hashes); -virtual int getDsdvEntry(const std::string &hash, RsDsdvTableEntry &entry); - - /***** overloaded from p3Service *****/ - /*! - * Process stuff. - */ - - virtual int tick(); - virtual int status(); - - /*************** pqiMonitor callback ***********************/ - virtual void statusChange(const std::list &plist); - - /************* from p3Config *******************/ - //virtual RsSerialiser *setupSerialiser() ; - //virtual bool saveList(bool& cleanup, std::list&) ; - //virtual void saveDone(); - //virtual bool loadList(std::list& load) ; - - private: - RsMutex mDsdvMtx; - - std::map mTable; - - rstime_t mSentTablesTime; - rstime_t mSentIncrementTime; - - bool mSignificantChanges; - - p3ServiceControl *mServiceCtrl; - -}; - -#endif // SERVICE_RSDSDV_HEADER - diff --git a/libretroshare/src/unused/pqiarchive.cc b/libretroshare/src/unused/pqiarchive.cc deleted file mode 100644 index df7c57f02..000000000 --- a/libretroshare/src/unused/pqiarchive.cc +++ /dev/null @@ -1,419 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiarchive.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -/* This is dependent on the sslroot at the moment. - * -> as we need to create/restore references to the Person. - * -> and store the signatures to do this. - */ - -/******************************************************************* - * pqiarchive provides an archive stream. - * This stores RsItem + Person Reference + Timestamp, - * - * and allows Objects to be replayed or restored, - * independently of the rest of the pqi system. - * - */ - -#ifdef SUSPENDED_UNUSED_CODE - -#include "pqi/pqiarchive.h" -#include "serialiser/rsserial.h" -#include -#include - -#include "util/rsdebug.h" -#include "util/rsstring.h" -#include "util/rstime.h" - -const int pqiarchivezone = 9326; - -struct pqiarchive_header -{ - uint32_t type; - uint32_t length; - uint32_t ts; - uint8_t personSig[PQI_PEERID_LENGTH]; -}; - -const int PQIARCHIVE_TYPE_PQITEM = 0x0001; - -/* PeerId of PQInterface is not important ... as we are archiving - * packets from other people... - */ - -pqiarchive::pqiarchive(RsSerialiser *rss, BinInterface *bio_in, int bio_flags_in) - :PQInterface(""), rsSerialiser(rss), bio(bio_in), bio_flags(bio_flags_in), - nextPkt(NULL), nextPktTS(0), firstPktTS(0), initTS(0),realTime(false) -{ - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::pqiarchive() Initialisation!\n"); - - if (!bio_in) - { - pqioutput(PQL_ALERT, pqiarchivezone, "pqiarchive::pqiarchive() NULL bio, FATAL ERROR!\n"); - exit(1); - } - - return; -} - -pqiarchive::~pqiarchive() -{ - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::~pqiarchive() Destruction!\n"); - - if (bio_flags & BIN_FLAGS_NO_CLOSE) - { - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::~pqiarchive() Not Closing BinInterface!\n"); - } - else if (bio) - { - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::~pqiarchive() Deleting BinInterface!\n"); - - delete bio; - } - - if (rsSerialiser) - delete rsSerialiser; - - if (nextPkt) - { - delete nextPkt; - } - return; -} - - -// Get/Send Items. -int pqiarchive::SendItem(RsItem *si) -{ - { - std::string out = "pqiarchive::SendItem()\n"; - si -> print_string(out); - pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, out); - } - - // check if this is a writing bio. - - if (!(bio_flags & BIN_FLAGS_WRITEABLE)) - { - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete si; - return -1; - } - -// std::cerr << "SendItem: si->PeerId()=" << si->PeerId() << std::endl ; - - int ret = writePkt(si); - return ret; /* 0 - failure, 1 - success*/ -} - -RsItem *pqiarchive::GetItem() -{ - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::GetItem()"); - - // check if this is a reading bio. - if (!(bio_flags & BIN_FLAGS_READABLE)) - { - pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, "pqiarchive::GetItem() Error Not Readable"); - return NULL; - } - - // load if we dont have a packet. - if (!nextPkt) - { - if (!readPkt(&nextPkt, &nextPktTS)) - { - pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, "pqiarchive::GetItem() Failed to ReadPkt"); - return NULL; - } - } - - if (!nextPkt) return NULL; - - - /* if realtime - check delta */ - bool rtnPkt = true; - if ((realTime) && (initTS)) - { - int delta = time(NULL) - initTS; - int delta2 = nextPktTS - firstPktTS; - if (delta >= delta2) - { - rtnPkt = true; - } - else - { - rtnPkt = false; - } - } - - if (rtnPkt) - { - if (!initTS) - { - /* first read! */ - initTS = time(NULL); - firstPktTS = nextPktTS; - } - RsItem *outPkt = nextPkt; - nextPkt = NULL; - - if (outPkt != NULL) - { - std::string out = "pqiarchive::GetItem() Returning:\n"; - outPkt -> print_string(out); - pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, out); - } - return outPkt; - } - return NULL; -} - -// // PQInterface -int pqiarchive::tick() -{ - return 0; -} - -int pqiarchive::status() -{ - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::status()"); - return 0; -} - -// -/**************** HANDLE OUTGOING TRANSLATION + TRANSMISSION ******/ - -int pqiarchive::writePkt(RsItem *pqi) -{ -// std::cerr << "writePkt, pqi->peerId()=" << pqi->PeerId() << std::endl ; - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::writePkt()"); - - uint32_t pktsize = rsSerialiser->size(pqi); - void *ptr = malloc(pktsize); - if (!(rsSerialiser->serialise(pqi, ptr, &pktsize))) - { - std::string out = "pqiarchive::writePkt() Null Pkt generated!\nCaused By:\n"; - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - return 0; - } - - /* extract the extra details */ - uint32_t len = getRsItemSize(ptr); - if (len != pktsize) - { - std::string out; - rs_sprintf(out, "pqiarchive::writePkt() Length MisMatch: len: %lu != pktsize: %lu\nCaused By:\n", len, pktsize); - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - return 0; - } - - - if (!(bio->cansend(0))) - { - std::string out = "pqiarchive::writePkt() BIO cannot write!\nDiscarding:\n"; - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 0; - } - - // using the peerid from the item. - if (pqi->PeerId().length() != PQI_PEERID_LENGTH) - { - std::string out = "pqiarchive::writePkt() Invalid peerId Length!\n"; - rs_sprintf_append(out, "Found %ld instead of %ld\n", pqi->PeerId().length(), PQI_PEERID_LENGTH); - out += "pqi->PeerId() = " + pqi->PeerId() + "\nCaused By:\n"; - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - return 0; - } - - std::string out = "Writing Pkt Header\n"; - struct pqiarchive_header hdr; - hdr.type = PQIARCHIVE_TYPE_PQITEM; - hdr.length = len; - hdr.ts = time(NULL); - memcpy(hdr.personSig, pqi->PeerId().c_str(), PQI_PEERID_LENGTH); - - // write packet header. - if (sizeof(hdr) != bio->senddata(&hdr, sizeof(hdr))) - { - out += "Trouble writing header!\n"; - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 0; - } - - out += "Writing Pkt Body\n"; - - // write packet. - if ((int) len != bio->senddata(ptr, len)) - { - out += "Problems with Send Data!\n"; - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 0; - } - - out += " Success!"; - pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 1; -} - -/* Reads a single packet from the input stream - * gets the timestamp as well. - * - */ - -int pqiarchive::readPkt(RsItem **item_out, long *ts_out) -{ - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::readPkt()"); - - if ((!(bio->isactive())) || (!(bio->moretoread(0)))) - { - return 0; - } - - // header - struct pqiarchive_header hdr; - - // enough space to read any packet. - int maxlen = getRsPktMaxSize(); - void *block = malloc(maxlen); - - // initial read size: basic packet. - int blen = getRsPktBaseSize(); - - int tmplen; - - /* read in the header */ - if (sizeof(hdr) != bio->readdata(&hdr, sizeof(hdr))) - { - /* error */ - pqioutput(PQL_WARNING, pqiarchivezone, - "pqiarchive::readPkt() bad read(1)"); - - free(block); - return 0; - } - - /* we have the header */ - - // read the basic block (minimum packet size) - if (blen != (tmplen = bio->readdata(block, blen))) - { - pqioutput(PQL_WARNING, pqiarchivezone, - "pqiarchive::readPkt() bad read(2)"); - - free(block); - return 0; - } - - // workout how much more to read. - int extralen = getRsItemSize(block) - blen; - if (extralen > 0) - { - void *extradata = (void *) (((char *) block) + blen); - if (extralen != (tmplen = bio->readdata(extradata, extralen))) - { - - std::string out; - rs_sprintf(out, "pqiarchive::readPkt() Error Completing Read (read %d/%d)\n", tmplen, extralen); - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(block); - return 0; - } - } - - // create packet, based on header. - //std::cerr << "Read Data Block -> Incoming Pkt("; - //std::cerr << blen + extralen << ")" << std::endl; - uint32_t readbytes = extralen + blen; - - RsItem *item = rsSerialiser->deserialise(block, &readbytes); - free(block); - - if (item == NULL) - { - pqioutput(PQL_ALERT, pqiarchivezone, - "pqiarchive::readPkt() Failed to create Item from archive!"); - return 0; - } - - /* Cannot detect bad ids here anymore.... - * but removed dependancy on the sslroot! - */ - - std::string peerId = ""; - for(int i = 0; i < PQI_PEERID_LENGTH; i++) - { - peerId += hdr.personSig[i]; - } - item->PeerId(peerId); - - *item_out = item; - *ts_out = hdr.ts; - - return 1; -} - -/**** Hashing Functions ****/ -std::string pqiarchive::gethash() -{ - return bio->gethash(); -} -#endif - - diff --git a/libretroshare/src/unused/pqiarchive.h b/libretroshare/src/unused/pqiarchive.h deleted file mode 100644 index 4c2a82a96..000000000 --- a/libretroshare/src/unused/pqiarchive.h +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiarchive.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifdef SUSPENDED_UNUSED_CODE - -#ifndef MRK_PQI_ARCHIVE_STREAMER_HEADER -#define MRK_PQI_ARCHIVE_STREAMER_HEADER - -#include "pqi/pqi.h" - -#include - -/******************************************************************* - * pqiarchive provides an archive stream. - * This stores RsItem + Person Reference + Timestamp, - * - * and allows Objects to be replayed or restored, - * independently of the rest of the pqi system. - * - */ - -class pqiarchive: public PQInterface -{ -public: - pqiarchive(RsSerialiser *rss, BinInterface *bio_in, int bio_flagsin); -virtual ~pqiarchive(); - -// PQInterface -virtual int SendItem(RsItem *); -virtual RsItem *GetItem(); - -virtual int tick(); -virtual int status(); - -virtual void setRealTime(bool r) { realTime = r; } - -std::string gethash(); - - private: -int writePkt(RsItem *item); -int readPkt(RsItem **item_out, long *ts); - - // Serialiser - RsSerialiser *rsSerialiser; - // Binary Interface for IO, initialisated at startup. - BinInterface *bio; - unsigned int bio_flags; // only BIN_NO_CLOSE at the moment. - - // Temp Storage for transient data..... - RsItem *nextPkt; - long nextPktTS; /* timestamp associated with nextPkt */ - long firstPktTS; /* timestamp associated with first read Pkt */ - long initTS; /* clock timestamp at first read */ - - bool realTime; -}; - - -#endif //MRK_PQI_ARCHIVE_STREAMER_HEADER -#endif //SUSPENDED_UNUSED_CODE diff --git a/libretroshare/src/unused/rscompress.cc b/libretroshare/src/unused/rscompress.cc deleted file mode 100644 index e3aa0f849..000000000 --- a/libretroshare/src/unused/rscompress.cc +++ /dev/null @@ -1,196 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rscompress.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include -#include -#include -#include -#include "rscompress.h" -#include "zlib.h" -#include "util/rsmemory.h" - -// 16K buffer size. -// -static const unsigned int CHUNK = 16384u ; - -bool RsCompress::compress_memory_chunk(const uint8_t *input_mem,const uint32_t input_size,uint8_t *& output_mem,uint32_t& output_size) -{ - - uint32_t remaining_input = input_size ; - uint32_t output_offset = 0 ; - uint32_t input_offset = 0 ; - output_size = 1024 ; - output_mem = (uint8_t*)rs_malloc(output_size) ; - - if(!output_mem) - return false ; - - int ret, flush; - unsigned have; - int level = 9 ; - z_stream strm; - unsigned char in[CHUNK]; - unsigned char out[CHUNK]; - /* allocate deflate state */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - - ret = deflateInit(&strm, level); - if (ret != Z_OK) - return false; - - /* compress until end of file */ - do - { - uint32_t available_in = std::min(CHUNK,remaining_input) ; - memcpy(in,input_mem+input_offset,available_in) ; - strm.avail_in = available_in ; - remaining_input -= available_in ; - input_offset += available_in ; - - flush = /*feof(source)*/ remaining_input ? Z_NO_FLUSH: Z_FINISH ; - strm.next_in = in; - - /* run deflate() on input until output buffer not full, finish - compression if all of source has been read in */ - do - { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = deflate(&strm, flush); /* no bad return value */ - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - have = CHUNK - strm.avail_out; - - if(output_size < have+output_offset) - { - //std::cerr << "Growing outputbuffer from " << output_size << " to " << have+output_offset << std::endl; - output_mem = (uint8_t*)realloc(output_mem,have+output_offset) ; - output_size = have+output_offset ; - } - - memcpy(output_mem+output_offset,out,have) ; - output_offset += have ; - - //std::cerr << "Copying " << have << " bytes to output. New offset=" << output_offset << std::endl; - } while (strm.avail_out == 0); - assert(strm.avail_in == 0); /* all input will be used */ - - /* done when last data in file processed */ - } while (flush != Z_FINISH); - assert(ret == Z_STREAM_END); /* stream will be complete */ - - /* clean up and return */ - (void)deflateEnd(&strm); - - output_size = output_offset ; - - return true ; -} - -bool RsCompress::uncompress_memory_chunk(const uint8_t *input_mem,const uint32_t input_size,uint8_t *& output_mem,uint32_t& output_size) -{ - uint32_t remaining_input = input_size ; - output_size = input_size ; - uint32_t output_offset = 0 ; - uint32_t input_offset = 0 ; - output_mem = (uint8_t*)rs_malloc(output_size) ; - - if(!output_mem) - return false ; - - int ret; - unsigned have; - z_stream strm; - unsigned char in[CHUNK]; - unsigned char out[CHUNK]; - - /* allocate inflate state */ - memset(&strm,0,sizeof(strm)) ; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.next_in = Z_NULL; - strm.next_out = Z_NULL; - - ret = inflateInit(&strm); - if (ret != Z_OK) - return ret; - - /* decompress until deflate stream ends or end of file */ - do - { - uint32_t available_in = std::min(CHUNK,remaining_input) ; - memcpy(in,input_mem+input_offset,available_in) ; - strm.avail_in = available_in ; - remaining_input -= available_in ; - input_offset += available_in ; - - if (strm.avail_in == 0) - break; - - strm.next_in = in; - /* run inflate() on input until output buffer not full */ - do { - strm.avail_out = CHUNK; - strm.next_out = out; - - ret = inflate(&strm, Z_NO_FLUSH); - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - switch (ret) { - case Z_NEED_DICT: - ret = Z_DATA_ERROR; /* and fall through */ - /* fallthrough */ - case Z_DATA_ERROR: - case Z_MEM_ERROR: - (void)inflateEnd(&strm); - return ret; - } - - - have = CHUNK - strm.avail_out; - - if(output_size < have+output_offset) - { - output_mem = (uint8_t*)realloc(output_mem,have+output_offset) ; - output_size = have+output_offset ; - } - - memcpy(output_mem+output_offset,out,have) ; - output_offset += have ; - - } while (strm.avail_out == 0); - /* done when inflate() says it's done */ - } while (ret != Z_STREAM_END); - - /* clean up and return */ - (void)inflateEnd(&strm); - - output_size = output_offset ; - return ret == Z_STREAM_END ; -} - - - - - - diff --git a/libretroshare/src/unused/rscompress.h b/libretroshare/src/unused/rscompress.h deleted file mode 100644 index 96b9e2092..000000000 --- a/libretroshare/src/unused/rscompress.h +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rscompress.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -class RsCompress -{ - public: - static bool compress_memory_chunk(const uint8_t *input_mem,const uint32_t input_size,uint8_t *& output_mem,uint32_t& output_size) ; - static bool uncompress_memory_chunk(const uint8_t *input_mem,const uint32_t input_size,uint8_t *& output_mem,uint32_t& output_size) ; -}; - diff --git a/libretroshare/src/unused/rsdsdv.h b/libretroshare/src/unused/rsdsdv.h deleted file mode 100644 index 308a1c779..000000000 --- a/libretroshare/src/unused/rsdsdv.h +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************* - * libretroshare/src/unused: rsdsdv.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_DSDV_INTERFACE_H -#define RETROSHARE_DSDV_INTERFACE_H - -#include -#include -#include - -/* The Main Interface Class - for information about your Peers */ -class RsDsdv; -extern RsDsdv *rsDsdv; - - -#define RSDSDV_IDTYPE_PEER 0x0001 -#define RSDSDV_IDTYPE_SERVICE 0x0002 -#define RSDSDV_IDTYPE_TEST 0x0100 - -#define RSDSDV_FLAGS_SIGNIFICANT_CHANGE 0x0001 -#define RSDSDV_FLAGS_STABLE_ROUTE 0x0002 -#define RSDSDV_FLAGS_NEW_ROUTE 0x0004 -#define RSDSDV_FLAGS_OWN_SERVICE 0x0008 - - -class RsDsdvId -{ - public: - - uint32_t mIdType; - std::string mAnonChunk; - std::string mHash; -}; - -class RsDsdvRoute -{ - public: - - RsPeerId mNextHop; - uint32_t mSequence; - uint32_t mDistance; - rstime_t mReceived; - rstime_t mValidSince; - -}; - -class RsDsdvTableEntry -{ - public: - - RsDsdvId mDest; - bool mIsStable; - RsDsdvRoute mStableRoute; - //RsDsdvRoute mFreshestRoute; - - std::map mAllRoutes; - - uint32_t mFlags; - - /* if we've matched it to someone */ - std::string mMatchedHash; - bool mMatched; - bool mOwnSource; -}; - -std::ostream &operator<<(std::ostream &out, const RsDsdvId &id); -std::ostream &operator<<(std::ostream &out, const RsDsdvRoute &route); -std::ostream &operator<<(std::ostream &out, const RsDsdvTableEntry &entry); - - -class RsDsdv -{ - public: - - RsDsdv() { return; } -virtual ~RsDsdv() { return; } - -virtual uint32_t getLocalServices(std::list &hashes) = 0; -virtual uint32_t getAllServices(std::list &hashes) = 0; -virtual int getDsdvEntry(const std::string &hash, RsDsdvTableEntry &entry) = 0; - -}; - -#endif - diff --git a/libretroshare/src/unused/rsdsdvitems.cc b/libretroshare/src/unused/rsdsdvitems.cc deleted file mode 100644 index 073ebe669..000000000 --- a/libretroshare/src/unused/rsdsdvitems.cc +++ /dev/null @@ -1,349 +0,0 @@ -/******************************************************************************* - * libretroshare/src/unused: rsdsdvitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "serialiser/rsbaseserial.h" -#include "serialiser/rsdsdvitems.h" -#include "serialiser/rstlvdsdv.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -/*************************************************************************/ - -RsDsdvRouteItem::~RsDsdvRouteItem() -{ - return; -} - -void RsDsdvRouteItem::clear() -{ - routes.TlvClear(); -} - -std::ostream &RsDsdvRouteItem::print(std::ostream &out, uint16_t indent) -{ - printRsItemBase(out, "RsDsdvRouteItem", indent); - uint16_t int_Indent = indent + 2; - routes.print(out, int_Indent); - - printRsItemEnd(out, "RsDsdvRouteItem", indent); - return out; -} - - -uint32_t RsDsdvSerialiser::sizeRoute(RsDsdvRouteItem *item) -{ - uint32_t s = 8; /* header */ - s += item->routes.TlvSize(); - - return s; -} - -/* serialise the data to the buffer */ -bool RsDsdvSerialiser::serialiseRoute(RsDsdvRouteItem *item, void *data, uint32_t *pktsize) -{ - uint32_t tlvsize = sizeRoute(item); - uint32_t offset = 0; - - if (*pktsize < tlvsize) - return false; /* not enough space */ - - *pktsize = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsDsdvSerialiser::serialiseRoute() Header: " << ok << std::endl; - std::cerr << "RsDsdvSerialiser::serialiseRoute() Size: " << tlvsize << std::endl; -#endif - - /* skip the header */ - offset += 8; - - /* add mandatory parts first */ - ok &= item->routes.SetTlv(data, tlvsize, &offset); - - if (offset != tlvsize) - { - ok = false; -#ifdef RSSERIAL_DEBUG - std::cerr << "RsDsdvSerialiser::serialiseRoute() Size Error! " << std::endl; -#endif - } - - return ok; -} - -RsDsdvRouteItem *RsDsdvSerialiser::deserialiseRoute(void *data, uint32_t *pktsize) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t tlvsize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_DSDV != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_DSDV_ROUTE != getRsItemSubType(rstype))) - { - return NULL; /* wrong type */ - } - - if (*pktsize < tlvsize) /* check size */ - return NULL; /* not enough data */ - - /* set the packet length */ - *pktsize = tlvsize; - - bool ok = true; - - /* ready to load */ - RsDsdvRouteItem *item = new RsDsdvRouteItem(); - item->clear(); - - /* skip the header */ - offset += 8; - - /* add mandatory parts first */ - ok &= item->routes.GetTlv(data, tlvsize, &offset); - - if (offset != tlvsize) - { - /* error */ - delete item; - return NULL; - } - - if (!ok) - { - delete item; - return NULL; - } - - return item; -} - -/*************************************************************************/ - -RsDsdvDataItem::~RsDsdvDataItem() -{ - return; -} - -void RsDsdvDataItem::clear() -{ - src.TlvClear(); - dest.TlvClear(); - ttl = 0; - data.TlvClear(); -} - -std::ostream &RsDsdvDataItem::print(std::ostream &out, uint16_t indent) -{ - printRsItemBase(out, "RsDsdvDataItem", indent); - uint16_t int_Indent = indent + 2; - src.print(out, int_Indent); - dest.print(out, int_Indent); - - printIndent(out, int_Indent); - out << "TTL: " << ttl << std::endl; - - data.print(out, int_Indent); - - printRsItemEnd(out, "RsDsdvDataItem", indent); - return out; -} - - -uint32_t RsDsdvSerialiser::sizeData(RsDsdvDataItem *item) -{ - uint32_t s = 8; /* header */ - s += item->src.TlvSize(); - s += item->dest.TlvSize(); - s += 4; - s += item->data.TlvSize(); - - return s; -} - -/* serialise the data to the buffer */ -bool RsDsdvSerialiser::serialiseData(RsDsdvDataItem *item, void *data, uint32_t *pktsize) -{ - uint32_t tlvsize = sizeData(item); - uint32_t offset = 0; - - if (*pktsize < tlvsize) - return false; /* not enough space */ - - *pktsize = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsDsdvSerialiser::serialiseData() Header: " << ok << std::endl; - std::cerr << "RsDsdvSerialiser::serialiseData() Size: " << tlvsize << std::endl; -#endif - - /* skip the header */ - offset += 8; - - /* add mandatory parts first */ - ok &= item->src.SetTlv(data, tlvsize, &offset); - ok &= item->dest.SetTlv(data, tlvsize, &offset); - ok &= setRawUInt32(data, tlvsize, &offset, item->ttl); - ok &= item->data.SetTlv(data, tlvsize, &offset); - - if (offset != tlvsize) - { - ok = false; -#ifdef RSSERIAL_DEBUG - std::cerr << "RsDsdvSerialiser::serialiseData() Size Error! " << std::endl; -#endif - } - - return ok; -} - -RsDsdvDataItem *RsDsdvSerialiser::deserialiseData(void *data, uint32_t *pktsize) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t tlvsize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_DSDV != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_DSDV_DATA != getRsItemSubType(rstype))) - { - return NULL; /* wrong type */ - } - - if (*pktsize < tlvsize) /* check size */ - return NULL; /* not enough data */ - - /* set the packet length */ - *pktsize = tlvsize; - - bool ok = true; - - /* ready to load */ - RsDsdvDataItem *item = new RsDsdvDataItem(); - item->clear(); - - /* skip the header */ - offset += 8; - - /* add mandatory parts first */ - ok &= item->src.GetTlv(data, tlvsize, &offset); - ok &= item->dest.GetTlv(data, tlvsize, &offset); - ok &= getRawUInt32(data, tlvsize, &offset, &(item->ttl)); - ok &= item->data.GetTlv(data, tlvsize, &offset); - - if (offset != tlvsize) - { - /* error */ - delete item; - return NULL; - } - - if (!ok) - { - delete item; - return NULL; - } - - return item; -} - -/*************************************************************************/ - -uint32_t RsDsdvSerialiser::size(RsItem *i) -{ - RsDsdvRouteItem *dri; - RsDsdvDataItem *ddi; - - if (NULL != (dri = dynamic_cast(i))) - { - return sizeRoute(dri); - } - if (NULL != (ddi = dynamic_cast(i))) - { - return sizeData(ddi); - } - return 0; -} - -bool RsDsdvSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) -{ - RsDsdvRouteItem *dri; - RsDsdvDataItem *ddi; - - if (NULL != (dri = dynamic_cast(i))) - { - return serialiseRoute(dri, data, pktsize); - } - if (NULL != (ddi = dynamic_cast(i))) - { - return serialiseData(ddi, data, pktsize); - } - return false; -} - -RsItem *RsDsdvSerialiser::deserialise(void *data, uint32_t *pktsize) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_DSDV != getRsItemService(rstype))) - { - return NULL; /* wrong type */ - } - - switch(getRsItemSubType(rstype)) - { - case RS_PKT_SUBTYPE_DSDV_ROUTE: - return deserialiseRoute(data, pktsize); - break; - case RS_PKT_SUBTYPE_DSDV_DATA: - return deserialiseData(data, pktsize); - break; - default: - return NULL; - break; - } -} - -/*************************************************************************/ - - - diff --git a/libretroshare/src/unused/rsdsdvitems.h b/libretroshare/src/unused/rsdsdvitems.h deleted file mode 100644 index 856a06b92..000000000 --- a/libretroshare/src/unused/rsdsdvitems.h +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * libretroshare/src/unused: rsdsdvitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_DSDV_ITEMS_H -#define RS_DSDV_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvdsdv.h" - -/**************************************************************************/ - -#define RS_PKT_SUBTYPE_DSDV_ROUTE 0x01 -#define RS_PKT_SUBTYPE_DSDV_DATA 0x02 - -class RsDsdvRouteItem: public RsItem -{ - public: - RsDsdvRouteItem() - :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DSDV, - RS_PKT_SUBTYPE_DSDV_ROUTE) - { - setPriorityLevel(QOS_PRIORITY_RS_DSDV_ROUTE); - return; - } -virtual ~RsDsdvRouteItem(); -virtual void clear(); -std::ostream &print(std::ostream &out, uint16_t indent = 0); - - RsTlvDsdvEntrySet routes; -}; - -class RsDsdvDataItem: public RsItem -{ - public: - RsDsdvDataItem() - :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DSDV, - RS_PKT_SUBTYPE_DSDV_DATA), data(TLV_TYPE_BIN_GENERIC) - { - setPriorityLevel(QOS_PRIORITY_RS_DSDV_DATA); - return; - } -virtual ~RsDsdvDataItem(); -virtual void clear(); -std::ostream &print(std::ostream &out, uint16_t indent = 0); - - RsTlvDsdvEndPoint src; - RsTlvDsdvEndPoint dest; - uint32_t ttl; - RsTlvBinaryData data; -}; - -class RsDsdvSerialiser: public RsSerialType -{ - public: - RsDsdvSerialiser() - :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DSDV) - { return; } -virtual ~RsDsdvSerialiser() - { return; } - -virtual uint32_t size(RsItem *); -virtual bool serialise (RsItem *item, void *data, uint32_t *size); -virtual RsItem * deserialise(void *data, uint32_t *size); - - private: - -virtual uint32_t sizeRoute(RsDsdvRouteItem *); -virtual bool serialiseRoute(RsDsdvRouteItem *item, void *data, uint32_t *size); -virtual RsDsdvRouteItem *deserialiseRoute(void *data, uint32_t *size); - -virtual uint32_t sizeData(RsDsdvDataItem *); -virtual bool serialiseData(RsDsdvDataItem *item, void *data, uint32_t *size); -virtual RsDsdvDataItem *deserialiseData(void *data, uint32_t *size); - - -}; - -/**************************************************************************/ - -#endif /* RS_DSDV_ITEMS_H */ - - diff --git a/libretroshare/src/use_libretroshare.pri b/libretroshare/src/use_libretroshare.pri deleted file mode 100644 index b76c4a5da..000000000 --- a/libretroshare/src/use_libretroshare.pri +++ /dev/null @@ -1,115 +0,0 @@ -# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team -# SPDX-License-Identifier: CC0-1.0 - -RS_SRC_PATH=$$clean_path($${PWD}/../../) -RS_BUILD_PATH=$$clean_path($${OUT_PWD}/../../) - -DEPENDPATH *= $$clean_path($${RS_SRC_PATH}/libretroshare/src/) -INCLUDEPATH *= $$clean_path($${RS_SRC_PATH}/libretroshare/src) - -equals(TARGET, retroshare):equals(TEMPLATE, lib){ -} else { - LIBS *= -L$$clean_path($${RS_BUILD_PATH}/libretroshare/src/lib/) -lretroshare - win32-g++|win32-clang-g++:!isEmpty(QMAKE_SH):libretroshare_shared { - # Windows msys2 - LIBRETROSHARE_TARGET=libretroshare.dll.a - } else { - LIBRETROSHARE_TARGET=libretroshare.a - } - PRE_TARGETDEPS *= $$clean_path($${RS_BUILD_PATH}/libretroshare/src/lib/$${LIBRETROSHARE_TARGET}) -} - -!include("../../openpgpsdk/src/use_openpgpsdk.pri"):error("Including") - -bitdht { - !include("../../libbitdht/src/use_libbitdht.pri"):error("Including") -} - -# when rapidjson is mainstream on all distribs, we will not need the sources -# anymore in the meantime, they are part of the RS directory so that it is -# always possible to find them -RAPIDJSON_AVAILABLE = $$system(pkg-config --atleast-version 1.1 RapidJSON && echo yes) -isEmpty(RAPIDJSON_AVAILABLE) { - message("using rapidjson from submodule") - INCLUDEPATH *= $$clean_path($${PWD}/../../supportlibs/rapidjson/include) -} else { - message("using system rapidjson") -} - - -sLibs = -mLibs = $$RS_SQL_LIB ssl crypto $$RS_THREAD_LIB $$RS_UPNP_LIB -dLibs = - -rs_jsonapi { - no_rs_cross_compiling { - RESTBED_SRC_PATH=$$clean_path($${RS_SRC_PATH}/supportlibs/restbed) - RESTBED_BUILD_PATH=$$clean_path($${RS_BUILD_PATH}/supportlibs/restbed) - INCLUDEPATH *= $$clean_path($${RESTBED_BUILD_PATH}/include/) - DEPENDPATH *= $$clean_path($${RESTBED_BUILD_PATH}/include/) - QMAKE_LIBDIR *= $$clean_path($${RESTBED_BUILD_PATH}/) - # Using sLibs would fail as librestbed.a is generated at compile-time - LIBS *= -L$$clean_path($${RESTBED_BUILD_PATH}/) -lrestbed - } else:sLibs *= restbed - - win32-g++|win32-clang-g++:dLibs *= wsock32 -} - -linux-* { - mLibs += dl -} - -rs_deep_channels_index | rs_deep_files_index { - mLibs += xapian - win32-g++|win32-clang-g++:mLibs += rpcrt4 -} - -rs_deep_files_index_ogg { - mLibs += vorbisfile -} - -rs_deep_files_index_flac { - mLibs += FLAC++ -} - -rs_deep_files_index_taglib { - mLibs += tag -} - -rs_broadcast_discovery { - no_rs_cross_compiling { - UDP_DISCOVERY_SRC_PATH=$$clean_path($${RS_SRC_PATH}/supportlibs/udp-discovery-cpp/) - UDP_DISCOVERY_BUILD_PATH=$$clean_path($${RS_BUILD_PATH}/supportlibs/udp-discovery-cpp/) - INCLUDEPATH *= $$clean_path($${UDP_DISCOVERY_SRC_PATH}) - DEPENDPATH *= $$clean_path($${UDP_DISCOVERY_BUILD_PATH}) - QMAKE_LIBDIR *= $$clean_path($${UDP_DISCOVERY_BUILD_PATH}) - # Using sLibs would fail as libudp-discovery.a is generated at compile-time - LIBS *= -L$$clean_path($${UDP_DISCOVERY_BUILD_PATH}) -ludp-discovery - } else:sLibs *= udp-discovery - - win32-g++|win32-clang-g++:dLibs *= wsock32 -} - -static { - sLibs *= $$mLibs -} else { - dLibs *= $$mLibs -} - -LIBS += $$linkStaticLibs(sLibs) -PRE_TARGETDEPS += $$pretargetStaticLibs(sLibs) - -LIBS += $$linkDynamicLibs(dLibs) - -android-* { -## ifaddrs is missing on Android to add them don't use the one from -## https://github.com/morristech/android-ifaddrs -## because it crash, use QNetworkInterface from Qt instead - CONFIG *= qt - QT *= network -} - -################################### Pkg-Config Stuff ############################# -!isEmpty(PKGCONFIG) { - LIBS *= $$system(pkg-config --libs $$PKGCONFIG) -} diff --git a/libretroshare/src/util/androiddebug.h b/libretroshare/src/util/androiddebug.h deleted file mode 100644 index c358be553..000000000 --- a/libretroshare/src/util/androiddebug.h +++ /dev/null @@ -1,121 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: androiddebug.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -// Inspired by: https://codelab.wordpress.com/2014/11/03/how-to-use-standard-output-streams-for-logging-in-android-apps/ - -#include -#include -#include -#include // for O_NONBLOCK -#include -#include -#include - -/** - * On Android stdout and stderr of native code is discarded, instancing this - * class at the beginning of the main of your program to get them (stdout and - * stderr) on logcat output. - */ -class AndroidStdIOCatcher -{ -public: - AndroidStdIOCatcher(const std::string& dTag = "RetroShare", - android_LogPriority stdout_pri = ANDROID_LOG_INFO, - android_LogPriority stderr_pri = ANDROID_LOG_ERROR) : - tag(dTag), cout_pri(stdout_pri), cerr_pri(stderr_pri), should_stop(false) - { - // make stdout line-buffered - //setvbuf(stdout, 0, _IOLBF, 0); - - // make stdout and stderr unbuffered - setvbuf(stdout, 0, _IONBF, 0); - setvbuf(stderr, 0, _IONBF, 0); - - // create the pipes and redirect stdout and stderr - pipe2(pout_fd, O_NONBLOCK); - dup2(pout_fd[1], STDOUT_FILENO); - - pipe2(perr_fd, O_NONBLOCK); - dup2(perr_fd[1], STDERR_FILENO); - - // spawn the logging thread - pthread_create(&thr, 0, thread_func, this); - pthread_detach(thr); - } - - ~AndroidStdIOCatcher() - { - should_stop = true; - pthread_join(thr, NULL); - } - -private: - const std::string tag; - const android_LogPriority cout_pri; - const android_LogPriority cerr_pri; - - int pout_fd[2]; - int perr_fd[2]; - pthread_t thr; - std::atomic should_stop; - - static void *thread_func(void* instance) - { - __android_log_write(ANDROID_LOG_INFO, "RetroShare", "Android debugging start"); - - AndroidStdIOCatcher &i = *static_cast(instance); - - std::string out_buf; - std::string err_buf; - - while (!i.should_stop) - { - for(char c; read(i.pout_fd[0], &c, 1) == 1;) - { - out_buf += c; - if(c == '\n') - { - __android_log_write(i.cout_pri, i.tag.c_str(), out_buf.c_str()); - out_buf.clear(); - } - } - - for(char c; read(i.perr_fd[0], &c, 1) == 1;) - { - err_buf += c; - if(c == '\n') - { - __android_log_write(i.cerr_pri, i.tag.c_str(), err_buf.c_str()); - err_buf.clear(); - } - } - - usleep(10000); - } - - __android_log_write(ANDROID_LOG_INFO, "RetroShare", "Android debugging stop"); - - return NULL; - } -}; - diff --git a/libretroshare/src/util/argstream.h b/libretroshare/src/util/argstream.h deleted file mode 100644 index ede11ec2e..000000000 --- a/libretroshare/src/util/argstream.h +++ /dev/null @@ -1,847 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: argstream.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004 Xavier Decoret * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef ARGSTREAM_H -#define ARGSTREAM_H - - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace -{ - class argstream; - - template - class ValueHolder; - - template - argstream& operator>> (argstream&, const ValueHolder&); - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // Interface of ValueHolder - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - template - class ValueHolder - { - public: - ValueHolder(char s, - const char* l, - T& b, - const char *valueName, - const char* desc, - bool mandatory); - ValueHolder(const char* l, - T& b, - const char *valueName, - const char* desc, - bool mandatory); - ValueHolder(char s, - T& b, - const char *valueName, - const char* desc, - bool mandatory); - friend argstream& operator>><>(argstream& s,const ValueHolder& v); - std::string name() const; - std::string description() const; - private: - std::string shortName_; - std::string longName_; - T* value_; - std::string valueName_; - T initialValue_; - std::string description_; - bool mandatory_; - }; - template - inline ValueHolder - parameter(char s, - const char* l, - T& b, - const char* desc="", - bool mandatory = true) - { - return ValueHolder(s,l,b,"value",desc,mandatory); - } - template - inline ValueHolder - parameter(char s, - const char* l, - T& b, - const char* valueName="value", - const char* desc="", - bool mandatory = true) - { - return ValueHolder(s,l,b,valueName,desc,mandatory); - } - template - inline ValueHolder - parameter(char s, - T& b, - const char* valueName="value", - const char* desc="", - bool mandatory = true) - { - return ValueHolder(s,b,valueName,desc,mandatory); - } - template - inline ValueHolder - parameter(const char* l, - T& b, - const char* valueName="value", - const char* desc="", - bool mandatory = true) - { - return ValueHolder(l,b,valueName,desc,mandatory); - } - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // Interface of OptionHolder - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - class OptionHolder - { - public: - inline OptionHolder(char s, - const char* l, - bool& b, - const char* desc); - inline OptionHolder(const char* l, - bool& b, - const char* desc); - inline OptionHolder(char s, - bool& b, - const char* desc); - friend argstream& operator>>(argstream& s,const OptionHolder& v); - inline std::string name() const; - inline std::string description() const; - protected: - inline OptionHolder(char s, - const char* l, - const char* desc); - friend OptionHolder help(char s, - const char* l, - const char* desc); - - private: - std::string shortName_; - std::string longName_; - bool* value_; - std::string description_; - }; - inline OptionHolder - option(char s, - const char* l, - bool& b, - const char* desc="") - { - return OptionHolder(s,l,b,desc); - } - inline OptionHolder - option(char s, - bool& b, - const char* desc="") - { - return OptionHolder(s,b,desc); - } - inline OptionHolder - option(const char* l, - bool& b, - const char* desc="") - { - return OptionHolder(l,b,desc); - } - inline OptionHolder - help(char s, - const char* l, - const char* desc) - { - return OptionHolder(s,l,desc); - } - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // Interface of ValuesHolder - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - template - class ValuesHolder - { - public: - ValuesHolder(const O& o, - const char* desc, - int len); - template friend argstream& operator>>(argstream& s,const ValuesHolder& v); - std::string name() const; - std::string description() const; - typedef T value_type; - private: - mutable O value_; - std::string description_; - int len_; - char letter_; - }; - template - inline ValuesHolder - values(const O& o, - const char* desc="", - int len=-1) - { - return ValuesHolder(o,desc,len); - } - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // Interface of ValueParser - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - template - class ValueParser - { - public: - inline T operator()(const std::string& s) const - { - std::istringstream is(s); - T t; - is>>t; - return t; - } - }; - // We need to specialize for string otherwise parsing of a value that - // contains space (for example a string with space passed in quotes on the - // command line) would parse only the first element of the value!!! - template <> - class ValueParser - { - public: - inline std::string operator()(const std::string& s) const - { - return s; - } - }; - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // Interface of argstream - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - class argstream - { - public: - inline argstream(int argc,char** argv); - inline argstream(const char* c); - template - friend argstream& operator>>(argstream& s,const ValueHolder& v); - friend inline argstream& operator>>(argstream& s,const OptionHolder& v); - template - friend argstream& operator>>(argstream& s,const ValuesHolder& v); - - inline bool helpRequested() const; - inline bool isOk() const; - inline std::string errorLog() const; - inline std::string usage(bool skipCommandLine = false) const; - inline bool defaultErrorHandling(bool ignoreUnused=false,bool skipCommandLine=false) const; - static inline char uniqueLetter(); - protected: - void parse(int argc,char** argv); - private: - typedef std::list::iterator value_iterator; - typedef std::pair help_entry; - std::string progName_; - std::map options_; - std::list values_; - bool minusActive_; - bool isOk_; - std::deque argHelps_; - std::string cmdLine_; - std::deque errors_; - bool helpRequested_; - }; - //************************************************************ - // Implementation of ValueHolder - //************************************************************ - template - ValueHolder::ValueHolder(char s, - const char* l, - T& v, - const char* valueName, - const char* desc, - bool mandatory) - : shortName_(1,s), - longName_(l), - value_(&v), - valueName_(valueName), - initialValue_(v), - description_(desc), - mandatory_(mandatory) - { - } - template - ValueHolder::ValueHolder(const char* l, - T& v, - const char* valueName, - const char* desc, - bool mandatory) - : longName_(l), - value_(&v), - valueName_(valueName), - initialValue_(v), - description_(desc), - mandatory_(mandatory) - { - } - template - ValueHolder::ValueHolder(char s, - T& v, - const char* valueName, - const char* desc, - bool mandatory) - : shortName_(1,s), - value_(&v), - valueName_(valueName), - initialValue_(v), - description_(desc), - mandatory_(mandatory) - { - } - template - std::string - ValueHolder::name() const - { - std::ostringstream os; - if (!shortName_.empty()) os<<'-'< - std::string - ValueHolder::description() const - { - std::ostringstream os; - os< - //************************************************************ - template - ValuesHolder::ValuesHolder(const O& o, - const char* desc, - int len) - : value_(o), - description_(desc), - len_(len) - { - letter_ = argstream::uniqueLetter(); - } - template - std::string - ValuesHolder::name() const - { - std::ostringstream os; - os< - std::string - ValuesHolder::description() const - { - return description_; - } - //************************************************************ - // Implementation of argstream - //************************************************************ - inline - argstream::argstream(int argc,char** argv) - : progName_(argv[0]), - minusActive_(true), - isOk_(true), - helpRequested_(false) - { - parse(argc,argv); - } - inline - argstream::argstream(const char* c) - : progName_(""), - minusActive_(true), - isOk_(true) - { - std::string s(c); - // Build argc, argv from s. We must add a dummy first element for - // progName because parse() expects it!! - std::deque args; - args.push_back(""); - std::istringstream is(s); - while (is.good()) - { - std::string t; - is>>t; - args.push_back(t); - } - char* pargs[args.size()]; - char** p = pargs; - for (std::deque::const_iterator - iter = args.begin(); - iter != args.end();++iter) - { - *p++ = const_cast(iter->c_str()); - } - parse(args.size(),pargs); - } - inline void - argstream::parse(int argc,char** argv) - { - // Run thru all arguments. - // * it has -- in front : it is a long name option, if remainder is empty, - // it is an error - // * it has - in front : it is a sequence of short name options, if - // remainder is empty, deactivates option (- will - // now be considered a char). - // * if any other char, or if option was deactivated - // : it is a value. Values are split in parameters - // (immediately follow an option) and pure values. - // Each time a value is parsed, if the previously parsed argument was an - // option, then the option is linked to the value in case of it is a - // option with parameter. The subtle point is that when several options - // are given with short names (ex: -abc equivalent to -a -b -c), the last - // parsed option is -c). - // Since we use map for option, any successive call overides the previous - // one: foo -a -b -a hello is equivalent to foo -b -a hello - // For values it is not true since we might have several times the same - // value. - value_iterator* lastOption = NULL; - for (char** a = argv,**astop=a+argc;++a!=astop;) - { - std::string s(*a); - if (minusActive_ && s[0] == '-') - { - if (s.size() > 1 && s[1] == '-') - { - if (s.size() == 2) - { - minusActive_ = false; - continue; - } - lastOption = &(options_[s.substr(2)] = values_.end()); - } - else - { - if (s.size() > 1) - { - // Parse all chars, if it is a minus we have an error - for (std::string::const_iterator cter = s.begin(); - ++cter != s.end();) - { - if (*cter == '-') - { - isOk_ = false; - std::ostringstream os; - os<<"- in the middle of a switch "<::const_iterator - iter = options_.begin();iter != options_.end();++iter) - { - std::cout<<"DEBUG: option "<first; - if (iter->second != values_.end()) - { - std::cout<<" -> "<<*(iter->second); - } - std::cout<::const_iterator - iter = values_.begin();iter != values_.end();++iter) - { - std::cout<<"DEBUG: value "<<*iter<::const_iterator - iter = argHelps_.begin();iter != argHelps_.end();++iter) - { - if (lmaxfirst.size()) lmax = iter->first.size(); - } - for (std::deque::const_iterator - iter = argHelps_.begin();iter != argHelps_.end();++iter) - { - os<<'\t'<first<first.size(),' ') - <<" : "<second<<'\n'; - } - return os.str(); - } - inline std::string - argstream::errorLog() const - { - std::string s; - for(std::deque::const_iterator iter = errors_.begin(); - iter != errors_.end();++iter) - { - s += *iter; - s += '\n'; - } - return s; - } - inline char - argstream::uniqueLetter() - { - static unsigned int c = 'a'; - return c++; - } - template - argstream& - operator>>(argstream& s,const ValueHolder& v) - { - // Search in the options if there is any such option defined either with a - // short name or a long name. If both are found, only the last one is - // used. -#ifdef ARGSTREAM_DEBUG - std::cout<<"DEBUG: searching "<::iterator iter = - s.options_.find(v.shortName_); - if (iter == s.options_.end()) - { - iter = s.options_.find(v.longName_); - } - if (iter != s.options_.end()) - { - // If we find counterpart for value holder on command line, either it - // has an associated value in which case we assign it, or it has not, in - // which case we have an error. - if (iter->second != s.values_.end()) - { -#ifdef ARGSTREAM_DEBUG - std::cout<<"DEBUG: found value "<<*(iter->second)< p; - *(v.value_) = p(*(iter->second)); - // The option and its associated value are removed, the subtle thing - // is that someother options might have this associated value too, - // which we must invalidate. - s.values_.erase(iter->second); - for (std::map::iterator - jter = s.options_.begin();jter != s.options_.end();++jter) - { - if (jter->second == iter->second) - { - jter->second = s.values_.end(); - } - } - s.options_.erase(iter); - } - else - { - s.isOk_ = false; - std::ostringstream os; - os<<"No value following switch "<first - <<" on command line"; - s.errors_.push_back(os.str()); - } - } - else - { - if (v.mandatory_) - { - s.isOk_ = false; - std::ostringstream os; - os<<"Mandatory parameter "; - if (!v.shortName_.empty()) os<<'-'<>(argstream& s,const OptionHolder& v) - { - // Search in the options if there is any such option defined either with a - // short name or a long name. If both are found, only the last one is - // used. -#ifdef ARGSTREAM_DEBUG - std::cout<<"DEBUG: searching "<::iterator iter = - s.options_.find(v.shortName_); - if (iter == s.options_.end()) - { - iter = s.options_.find(v.longName_); - } - if (iter != s.options_.end()) - { - // If we find counterpart for value holder on command line then the - // option is true and if an associated value was found, it is ignored - if (v.value_ != NULL) - { - *(v.value_) = true; - } - else - { - s.helpRequested_ = true; - } - // The option only is removed - s.options_.erase(iter); - } - else - { - if (v.value_ != NULL) - { - *(v.value_) = false; - } - else - { - s.helpRequested_ = false; - } - } - return s; - } - template - argstream& - operator>>(argstream& s,const ValuesHolder& v) - { - s.argHelps_.push_back(argstream::help_entry(v.name(),v.description())); - { - std::ostringstream os; - os<<' '<::iterator first = s.values_.begin(); - // We add to the iterator as much values as we can, limited to the length - // specified (if different of -1) - int n = v.len_ != -1?v.len_:s.values_.size(); - while (first != s.values_.end() && n-->0) - { - // Read the value from the string *first - ValueParser p; - *(v.value_++) = p(*first ); - s.argHelps_.push_back(argstream::help_entry(v.name(),v.description())); - // The value we just removed was maybe "remembered" by an option so we - // remove it now. - for (std::map::iterator - jter = s.options_.begin();jter != s.options_.end();++jter) - { - if (jter->second == first) - { - jter->second = s.values_.end(); - } - } - ++first; - } - // Check if we have enough values - if (n != 0) - { - s.isOk_ = false; - std::ostringstream os; - os<<"Expecting "< * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include - -#include "contentvalue.h" - - - - -const uint8_t ContentValue::BOOL_TYPE = 1; -const uint8_t ContentValue::DATA_TYPE = 2; -const uint8_t ContentValue::STRING_TYPE = 3; -const uint8_t ContentValue::DOUBLE_TYPE = 4; -const uint8_t ContentValue::INT32_TYPE = 5; -const uint8_t ContentValue::INT64_TYPE = 6; - - -/**************** content value implementation ******************/ - -typedef std::pair KeyTypePair; - -ContentValue::ContentValue(){ - -} - -ContentValue::~ContentValue(){ - // release resources held in data - clearData(); -} - -ContentValue::ContentValue(const ContentValue &from){ - - std::map keyTypeMap; - from.getKeyTypeMap(keyTypeMap); - std::map::const_iterator cit = - keyTypeMap.begin(); - - uint8_t type = 0; - std::string currKey; - std::string val = ""; - char *src = NULL; - uint32_t data_len = 0; - - for(; cit != keyTypeMap.end(); ++cit){ - - type = cit->second; - currKey = cit->first; - - switch(type){ - - case INT32_TYPE: - { - int32_t value = 0; - if (from.getAsInt32(currKey, value)) - put(currKey, value); - break; - } - case INT64_TYPE: - { - int64_t value = 0; - if (from.getAsInt64(currKey, value)) - put(currKey, value); - break; - } - case STRING_TYPE: - { - if (from.getAsString(currKey, val)) - put(currKey, val); - break; - } - case BOOL_TYPE: - { - bool value = false; - if (from.getAsBool(currKey, value)) - put(currKey, value); - break; - } - case DATA_TYPE: - { - if (from.getAsData(currKey, data_len, src)) - put(currKey, data_len, src); - break; - } - case DOUBLE_TYPE: - { - double value = 0; - if (from.getAsDouble(currKey, value)) - put(currKey, value); - break; - } - default: - std::cerr << "ContentValue::ContentValue(ContentValue &from):" - << "Error! Unrecognised data type!" << std::endl; - break; - } - } -} - -void ContentValue::put(const std::string &key, bool value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, BOOL_TYPE)); - mKvBool.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, const std::string &value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, STRING_TYPE)); - mKvString.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, double value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key,DOUBLE_TYPE)); - mKvDouble.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, int32_t value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, INT32_TYPE)); - mKvInt32.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, int64_t value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, INT64_TYPE)); - mKvInt64.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, uint32_t len, const char* value){ - - - // release memory from old key value if key - // exists - if(mKvSet.find(key) != mKvSet.end()) { - removeKeyValue(key); - } - - mKvSet.insert(KeyTypePair(key, DATA_TYPE)); - char* dest = NULL; - - // len is zero then just put a NULL entry - if(len != 0){ - dest = new char[len]; - memcpy(dest, value, len); - } - - mKvData.insert(std::pair > - (key, std::pair(len, dest))); - //delete[] dest; //Deleted by clearData() - // cppcheck-suppress memleak -} - -bool ContentValue::getAsBool(const std::string &key, bool& value) const{ - - std::map::const_iterator it; - if((it = mKvBool.find(key)) == mKvBool.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsInt32(const std::string &key, int32_t& value) const{ - - std::map::const_iterator it; - if((it = mKvInt32.find(key)) == mKvInt32.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsInt64(const std::string &key, int64_t& value) const{ - - std::map::const_iterator it; - if((it = mKvInt64.find(key)) == mKvInt64.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsString(const std::string &key, std::string &value) const{ - - std::map::const_iterator it; - if((it = mKvString.find(key)) == mKvString.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsData(const std::string& key, uint32_t &len, char*& value) const{ - - std::map >::const_iterator it; - if((it = mKvData.find(key)) == mKvData.end()) - return false; - - const std::pair &kvRef = it->second; - - len = kvRef.first; - value = kvRef.second; - return true; -} - -bool ContentValue::getAsDouble(const std::string &key, double& value) const{ - - std::map::const_iterator it; - if((it = mKvDouble.find(key)) == mKvDouble.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::removeKeyValue(const std::string &key){ - - std::map::iterator mit; - - if((mit = mKvSet.find(key)) == mKvSet.end()) - return false; - - if(mit->second == BOOL_TYPE) - mKvBool.erase(key); - - if(mit->second == INT64_TYPE) - mKvInt64.erase(key); - - if(mit->second == DATA_TYPE){ - delete[] (mKvData[key].second); - mKvData.erase(key); - } - - if(mit->second == DOUBLE_TYPE) - mKvDouble.erase(key); - - if(mit->second == STRING_TYPE) - mKvString.erase(key); - - if(mit->second == INT32_TYPE) - mKvInt32.erase(key); - - - mKvSet.erase(key); - return true; -} - - -void ContentValue::getKeyTypeMap(std::map &keySet) const { - keySet = mKvSet; -} - -void ContentValue::clear(){ - mKvSet.clear(); - mKvBool.clear(); - mKvDouble.clear(); - mKvString.clear(); - mKvInt32.clear(); - mKvInt64.clear(); - clearData(); -} - -bool ContentValue::empty() const{ - return mKvSet.empty(); -} - -void ContentValue::clearData(){ - - std::map >::iterator - mit = mKvData.begin(); - - for(; mit != mKvData.end(); ++mit){ - - if(mit->second.first != 0) - delete[] (mit->second.second); - } - - mKvData.clear(); -} - - - diff --git a/libretroshare/src/util/contentvalue.h b/libretroshare/src/util/contentvalue.h deleted file mode 100644 index 23ee55eca..000000000 --- a/libretroshare/src/util/contentvalue.h +++ /dev/null @@ -1,187 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: contentvalue.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef CONTENTVALUE_H -#define CONTENTVALUE_H - -#include -#include -#include - -/*! - * @brief Convenience container for making additions to databases - * This class provides a means of holding column values to insert into a database - */ -class ContentValue { - -public: - - static const uint8_t INT32_TYPE; - static const uint8_t INT64_TYPE; - static const uint8_t DOUBLE_TYPE; - static const uint8_t STRING_TYPE; - static const uint8_t DATA_TYPE; - static const uint8_t BOOL_TYPE; - - ContentValue(); - - /*! - * copy constructor that copys the key value set from another \n - * ContentValue object to this one - * makes a deep copy of raw data - * @param from ContentValue instance to copy key value set from - */ - ContentValue(const ContentValue& from);//const damit die äußere klasse einen konstruktor com compielr bekommt - - /*! - * - * - * - */ - ~ContentValue(); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - * @warning cast string literals explicitly as string, observed string literal \n - * being casted to bool instead e.g. string("hello") rather than "hello" - */ - void put(const std::string& key, const std::string& value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, bool value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, int64_t value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, int32_t value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, double value); - - /*! - * Adds a value to the set - * Takes a private copy of data - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, uint32_t len, const char* value); - - - /*! - * get value as 32 bit signed integer - * @param key the value to get - */ - bool getAsInt32(const std::string& key, int32_t& value) const; - - /*! - * get value as 64 bit signed integer - * @param key the value to get - */ - bool getAsInt64(const std::string& key, int64_t& value) const; - - /*! - * get value as bool - * @param key the value to get - */ - bool getAsBool(const std::string& key, bool& value) const; - - /*! - * get as value double - * @param key the value to get - */ - bool getAsDouble(const std::string& key, double& value) const; - - /*! - * get as value as string - * @param key the value to get - * @param value the data retrieved - */ - bool getAsString(const std::string& key, std::string& value) const; - - /*! - * get as value as raw data - * @warning Deep copy of data reference should be made, if this instance ContentValue \n - * is destroyed pointer returned (value) is pointing to invalid memory - * @param key the value to get - */ - bool getAsData(const std::string&, uint32_t& len, char*& value) const; - - /*! - * @param keySet the is set with key to type pairs contained in the ContentValue instance - */ - void getKeyTypeMap(std::map& keySet) const; - - /*! - * @param key the key of the key value pair to remove - * @return true if key was found and removed, false otherwise - */ - bool removeKeyValue(const std::string& key); - - /*! - * clears this data structure of all its key value pairs held - */ - void clear(); - - /*! - * checks if internal kv map is empty - */ - bool empty() const; - -private: - - /*! - * release memory resource associated with mKvData - */ - void clearData(); - -private: - - std::map mKvInt32; - std::map mKvInt64; - std::map mKvDouble; - std::map mKvString; - std::map > mKvData; - std::map mKvBool; - - std::map mKvSet; - -}; - -#endif // CONTENTVALUE_H diff --git a/libretroshare/src/util/cxx11retrocompat.h b/libretroshare/src/util/cxx11retrocompat.h deleted file mode 100644 index f210cf87b..000000000 --- a/libretroshare/src/util/cxx11retrocompat.h +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: cxx11retrocompat.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#if defined(__GNUC__) && !defined(__clang__) -# define GCC_VERSION (__GNUC__*10000+__GNUC_MINOR__*100+__GNUC_PATCHLEVEL__) -# if GCC_VERSION < 40700 -# define override -# define final -# endif // GCC version < 40700 -# if GCC_VERSION < 40600 -# define nullptr NULL -# endif // GCC_VERSION < 40600 -#endif // defined(__GNUC__) && !defined(__clang__) diff --git a/libretroshare/src/util/cxx14retrocompat.h b/libretroshare/src/util/cxx14retrocompat.h deleted file mode 100644 index e7e7d9e99..000000000 --- a/libretroshare/src/util/cxx14retrocompat.h +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * * - * libretroshare < C++14 retro-compatibility helpers * - * * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#if __cplusplus < 201402L - -#include - -namespace std -{ -template using decay_t = typename decay::type; - -template -using enable_if_t = typename enable_if::type; - -template -using remove_const_t = typename remove_const::type; -} -#endif // __cplusplus < 201402L diff --git a/libretroshare/src/util/cxx17retrocompat.h b/libretroshare/src/util/cxx17retrocompat.h deleted file mode 100644 index 58cdfe84c..000000000 --- a/libretroshare/src/util/cxx17retrocompat.h +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: cxx17retrocompat.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#if __cplusplus < 201703L - -#include - -namespace std -{ -using namespace std; -template constexpr typename add_const::type& as_const(T& t) noexcept -{ return t; } -template void as_const(const T&&) = delete; -} -#endif // __cplusplus < 201703L diff --git a/libretroshare/src/util/dnsresolver.cc b/libretroshare/src/util/dnsresolver.cc deleted file mode 100644 index 3b68a052e..000000000 --- a/libretroshare/src/util/dnsresolver.cc +++ /dev/null @@ -1,204 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: dnsresolver.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#include "dnsresolver.h" - -#include "pqi/pqinetwork.h" -#include "util/rsnet.h" - - -#ifndef WIN32 -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include "util/rstime.h" - -const rstime_t MAX_TIME_BEFORE_RETRY = 300 ; /* seconds before retrying an ip address */ -const rstime_t MAX_KEEP_DNS_ENTRY = 3600 ; /* seconds during which a DNS entry is considered valid */ - -static const std::string ADDR_AGENT = "Mozilla/5.0"; - -void *solveDNSEntries(void *p) -{ - bool more_to_go = true ; - DNSResolver *dnsr = (DNSResolver*)p ; - - while(more_to_go) - { - // get an address request - rstime_t now = time(NULL) ; - more_to_go = false ; - - std::string next_call = "" ; - - { - RsStackMutex mut(dnsr->_rdnsMtx) ; - - if(dnsr->_addr_map != NULL) - for(std::map::iterator it(dnsr->_addr_map->begin());it!=dnsr->_addr_map->end() && next_call.empty();++it) - { - switch(it->second.state) - { - case DNSResolver::DNS_SEARCHING: - case DNSResolver::DNS_HAVE: break ; - - case DNSResolver::DNS_LOOKUP_ERROR: if(it->second.last_lookup_time + MAX_TIME_BEFORE_RETRY > now) - continue ; - /* fallthrough */ //Not really, but to suppress warning. - case DNSResolver::DNS_DONT_HAVE: next_call = it->first ; - it->second.state = DNSResolver::DNS_SEARCHING ; - it->second.last_lookup_time = now ; - more_to_go = true ; - break ; - } - } - else - return NULL; // the thread has been deleted. Return. - } - - if(!next_call.empty()) - { - in_addr in ; - - bool succeed = rsGetHostByName(next_call.c_str(),in); - - { - RsStackMutex mut(dnsr->_rdnsMtx) ; - - DNSResolver::AddrInfo &info = (*dnsr->_addr_map)[next_call]; - - if(succeed) - { - info.state = DNSResolver::DNS_HAVE ; - // IPv4 for the moment. - struct sockaddr_in *addrv4p = (struct sockaddr_in *) &(info.addr); - addrv4p->sin_family = AF_INET; - addrv4p->sin_addr= in ; - addrv4p->sin_port = htons(0); - - std::cerr << "LOOKUP succeeded: " << next_call.c_str() << " => " << rs_inet_ntoa(addrv4p->sin_addr) << std::endl; - } - else - { - info.state = DNSResolver::DNS_LOOKUP_ERROR ; - - std::cerr << "DNSResolver: lookup error for address \"" << next_call.c_str() << "\"" << std::endl; - } - } - } - } - - { - RsStackMutex mut(dnsr->_rdnsMtx) ; - *(dnsr->_thread_running) = false ; - } - return NULL ; -} - -void DNSResolver::start_request() -{ - { - RsStackMutex mut(_rdnsMtx) ; - *_thread_running = true ; - } - - void *data = (void *)this; - pthread_t tid ; - - if(! pthread_create(&tid, 0, &solveDNSEntries, data)) - pthread_detach(tid); /* so memory is reclaimed in linux */ - else - std::cerr << "(EE) Could not start DNS resolver thread!" << std::endl; -} - -void DNSResolver::reset() -{ - RsStackMutex mut(_rdnsMtx) ; - - *_thread_running = false ; - _addr_map->clear(); -} - -bool DNSResolver::getIPAddressFromString(const std::string& server_name,struct sockaddr_storage &addr) -{ - sockaddr_storage_clear(addr); - bool running = false; - { - RsStackMutex mut(_rdnsMtx) ; - - std::map::iterator it(_addr_map->find(server_name)) ; - rstime_t now = time(NULL) ; - AddrInfo *addr_info ; - - if(it != _addr_map->end()) - { - // check that the address record is not too old - - if(it->second.last_lookup_time + MAX_KEEP_DNS_ENTRY > now && it->second.state == DNSResolver::DNS_HAVE) - { - addr = it->second.addr ; - return true ; - } - else - addr_info = &it->second ; - } - else - addr_info = &(*_addr_map)[server_name] ; - - // We don't have it. Let's push it into the names to lookup for, except if we're already into it. - - if(addr_info->state != DNSResolver::DNS_SEARCHING) - addr_info->state = DNSResolver::DNS_DONT_HAVE ; - - running = *_thread_running ; - } - - if(!running) - start_request(); - - return false ; -} - -DNSResolver::~DNSResolver() -{ - RsStackMutex mut(_rdnsMtx) ; - - delete _addr_map ; - _addr_map = NULL ; - delete _thread_running ; -} - -DNSResolver::DNSResolver() : _rdnsMtx("DNSResolver") -{ - RsStackMutex mut(_rdnsMtx) ; - - _addr_map = new std::map() ; - _thread_running = new bool ; - *_thread_running = false ; -} - diff --git a/libretroshare/src/util/dnsresolver.h b/libretroshare/src/util/dnsresolver.h deleted file mode 100644 index 042654f4e..000000000 --- a/libretroshare/src/util/dnsresolver.h +++ /dev/null @@ -1,63 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: dnsresolver.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "pqi/pqinetwork.h" - -#ifndef WIN32 -#include -#endif - -#include -#include - -#include "util/rsthreads.h" -#include "util/rstime.h" - -struct sockaddr ; - -class DNSResolver -{ - public: - DNSResolver() ; - ~DNSResolver() ; - - bool getIPAddressFromString(const std::string& server_name,struct sockaddr_storage &addr) ; - - void start_request() ; - void reset() ; - - private: - enum { DNS_DONT_HAVE,DNS_SEARCHING, DNS_HAVE, DNS_LOOKUP_ERROR } ; - - struct AddrInfo - { - uint32_t state ; // state: Looked-up, not found, have - rstime_t last_lookup_time ; // last lookup time - struct sockaddr_storage addr ; - }; - friend void *solveDNSEntries(void *p) ; - - RsMutex _rdnsMtx ; - bool *_thread_running ; - std::map *_addr_map ; -}; diff --git a/libretroshare/src/util/exampletst.c b/libretroshare/src/util/exampletst.c deleted file mode 100644 index e96cd037e..000000000 --- a/libretroshare/src/util/exampletst.c +++ /dev/null @@ -1,40 +0,0 @@ - -#include "utest.h" - -#include - -/* must define the global variables */ -INITTEST(); - -int main(int argc, char **argv) -{ - int a = 2; - int b = 3; - int c = 2; - - CHECK( a == c ); - - REPORT( "Initial Tests"); - - CHECK( (0 == strcmp("123", "123")) ); - - REPORT( "Successful Tests"); - - CHECK( a == b ); - CHECK( (0 == strcmp("123", "12345")) ); - - REPORT( "Failed Tests" ); - - CHECK( 1 ); - CHECK( a == c ); - - REPORT( "Later Successful Tests"); - - - FINALREPORT( "Example Tests" ); - - return TESTRESULT(); -} - - - diff --git a/libretroshare/src/util/extaddrfinder.cc b/libretroshare/src/util/extaddrfinder.cc deleted file mode 100644 index b214dc779..000000000 --- a/libretroshare/src/util/extaddrfinder.cc +++ /dev/null @@ -1,323 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: extaddrfinder.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#include "extaddrfinder.h" - -#include "pqi/pqinetwork.h" -#include "util/rsstring.h" -#include "util/rsmemory.h" - -#ifndef WIN32 -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include "util/rstime.h" - -const uint32_t MAX_IP_STORE = 300; /* seconds ip address timeout */ - -//#define EXTADDRSEARCH_DEBUG - -static const std::string ADDR_AGENT = "Mozilla/5.0"; - -static std::string scan_ip(const std::string& text) -{ - std::set digits ; - digits.insert('0') ; digits.insert('3') ; digits.insert('6') ; - digits.insert('1') ; digits.insert('4') ; digits.insert('7') ; - digits.insert('2') ; digits.insert('5') ; digits.insert('8') ; - digits.insert('9') ; - - for(int i=0;i<(int)text.size();++i) - { - while(i < (int)text.size() && digits.find(text[i])==digits.end()) ++i ; - - if(i>=(int)text.size()) - return "" ; - - unsigned int a,b,c,d ; - - if(sscanf(text.c_str()+i,"%u.%u.%u.%u",&a,&b,&c,&d) != 4) - continue ; - - if(a < 256 && b<256 && c<256 && d<256) - { - std::string s ; - rs_sprintf(s, "%u.%u.%u.%u", a, b, c, d) ; - return s; - } - } - return "" ; -} - -static void getPage(const std::string& server_name,std::string& page) -{ - page = "" ; - int sockfd,n=0; // socket descriptor - struct sockaddr_in serveur; // server's parameters - memset(&serveur.sin_zero, 0, sizeof(serveur.sin_zero)); - - char buf[1024]; - char request[1024]; -#ifdef EXTADDRSEARCH_DEBUG - std::cout << "ExtAddrFinder: connecting to " << server_name << std::endl ; -#endif - // socket creation - - sockfd = unix_socket(PF_INET,SOCK_STREAM,0); - if (sockfd < 0) - { - std::cerr << "ExtAddrFinder: Failed to create socket" << std::endl; - return ; - } - - serveur.sin_family = AF_INET; - - // get server's ipv4 adress - - in_addr in ; - - if(!rsGetHostByName(server_name.c_str(),in)) /* l'hôte n'existe pas */ - { - std::cerr << "ExtAddrFinder: Unknown host " << server_name << std::endl; - unix_close(sockfd); - return ; - } - serveur.sin_addr = in ; - serveur.sin_port = htons(80); - -#ifdef EXTADDRSEARCH_DEBUG - printf("Connection attempt\n"); -#endif - std::cerr << "ExtAddrFinder: resolved hostname " << server_name << " to " << rs_inet_ntoa(in) << std::endl; - - sockaddr_storage server; - sockaddr_storage_setipv4(server, &serveur); - sockaddr_storage_setport(server, 80); - if(unix_connect(sockfd, server) == -1) - { - std::cerr << "ExtAddrFinder: Connection error to " << server_name << std::endl ; - unix_close(sockfd); - return ; - } -#ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Connection established to " << server_name << std::endl ; -#endif - - // envoi - if(snprintf( request, - 1024, - "GET / HTTP/1.0\r\n" - "Host: %s:%d\r\n" - "Connection: Close\r\n" - "\r\n", - server_name.c_str(), 80) > 1020) - { - std::cerr << "ExtAddrFinder: buffer overrun. The server name \"" << server_name << "\" is too long. This is quite unexpected." << std::endl; - unix_close(sockfd); - return ; - } - - if(send(sockfd,request,strlen(request),0)== -1) - { - std::cerr << "ExtAddrFinder: Could not send request to " << server_name << std::endl ; - unix_close(sockfd); - return ; - } - // recéption - - while((n = recv(sockfd, buf, sizeof buf - 1, 0)) > 0) - { - buf[n] = '\0'; - page += std::string(buf,n) ; - } - // fermeture de la socket - - unix_close(sockfd); -#ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Got full page from " << server_name << std::endl ; -#endif -} - - -void* doExtAddrSearch(void *p) -{ - - std::vector res ; - - ExtAddrFinder *af = (ExtAddrFinder*)p ; - - for(std::list::const_iterator it(af->_ip_servers.begin());it!=af->_ip_servers.end();++it) - { - std::string page ; - - getPage(*it,page) ; - std::string ip = scan_ip(page) ; - - if(ip != "") - res.push_back(ip) ; -#ifdef EXTADDRSEARCH_DEBUG - std::cout << "ip found through " << *it << ": \"" << ip << "\"" << std::endl ; -#endif - } - - if(res.empty()) - { - // thread safe copy results. - // - { - RsStackMutex mtx(af->mAddrMtx) ; - - af->mFound = false ; - af->mFoundTS = time(NULL) ; - af->mSearching = false ; - } - return NULL ; - } - - sort(res.begin(),res.end()) ; // eliminates outliers. - - - - if(!sockaddr_storage_ipv4_aton(af->mAddr, res[res.size()/2].c_str())) - { - std::cerr << "ExtAddrFinder: Could not convert " << res[res.size()/2] << " into an address." << std::endl ; - { - RsStackMutex mtx(af->mAddrMtx) ; - af->mFound = false ; - af->mFoundTS = time(NULL) ; - af->mSearching = false ; - } - return NULL ; - } - - { - RsStackMutex mtx(af->mAddrMtx) ; - af->mFound = true ; - af->mFoundTS = time(NULL) ; - af->mSearching = false ; - } - - return NULL ; -} - - -void ExtAddrFinder::start_request() -{ - void *data = (void *)this; - pthread_t tid ; - - if(! pthread_create(&tid, 0, &doExtAddrSearch, data)) - pthread_detach(tid); /* so memory is reclaimed in linux */ - else - std::cerr << "(EE) Could not start ExtAddrFinder thread." << std::endl; -} - -bool ExtAddrFinder::hasValidIP(struct sockaddr_storage &addr) -{ -#ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Getting ip." << std::endl ; -#endif - - { - RsStackMutex mut(mAddrMtx) ; - if(mFound) - { -#ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Has stored ip: responding with this ip." << std::endl ; -#endif - sockaddr_storage_copyip(addr,mAddr); // just copy the IP so we dont erase the port. - } - } - rstime_t delta; - { - RsStackMutex mut(mAddrMtx) ; - //timeout the current ip - delta = time(NULL) - mFoundTS; - } - if((uint32_t)delta > MAX_IP_STORE) {//launch a research - if( mAddrMtx.trylock()) - { - if(!mSearching) - { -#ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: No stored ip: Initiating new search." << std::endl ; -#endif - mSearching = true ; - start_request() ; - } -#ifdef EXTADDRSEARCH_DEBUG - else - std::cerr << "ExtAddrFinder: Already searching." << std::endl ; -#endif - mAddrMtx.unlock(); - } -#ifdef EXTADDRSEARCH_DEBUG - else - std::cerr << "ExtAddrFinder: (Note) Could not acquire lock. Busy." << std::endl ; -#endif - } - - RsStackMutex mut(mAddrMtx) ; - return mFound ; -} - -void ExtAddrFinder::reset() -{ - RsStackMutex mut(mAddrMtx) ; - - mFound = false ; - mSearching = false ; - mFoundTS = time(NULL) - MAX_IP_STORE; -} - -ExtAddrFinder::~ExtAddrFinder() -{ -#ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Deleting ExtAddrFinder." << std::endl ; -#endif - -} - -ExtAddrFinder::ExtAddrFinder() : mAddrMtx("ExtAddrFinder") -{ -#ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Creating new ExtAddrFinder." << std::endl ; -#endif - RsStackMutex mut(mAddrMtx) ; - - mFound = false; - mSearching = false; - mFoundTS = time(NULL) - MAX_IP_STORE; - sockaddr_storage_clear(mAddr); - - _ip_servers.push_back(std::string( "checkip.dyndns.org" )) ; - _ip_servers.push_back(std::string( "www.myip.dk" )) ; - _ip_servers.push_back(std::string( "showip.net" )) ; - _ip_servers.push_back(std::string( "www.displaymyip.com")) ; -} - diff --git a/libretroshare/src/util/extaddrfinder.h b/libretroshare/src/util/extaddrfinder.h deleted file mode 100644 index 22a9a5689..000000000 --- a/libretroshare/src/util/extaddrfinder.h +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: extaddrfinder.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "util/rsthreads.h" -#include "util/rsnet.h" -#include "util/rstime.h" - -struct sockaddr ; - -class ExtAddrFinder -{ - public: - ExtAddrFinder() ; - ~ExtAddrFinder() ; - - bool hasValidIP(struct sockaddr_storage &addr) ; - void getIPServersList(std::list& ip_servers) { ip_servers = _ip_servers ; } - - void start_request() ; - - void reset() ; - - private: - friend void* doExtAddrSearch(void *p) ; - - RsMutex mAddrMtx ; - rstime_t mFoundTS; - struct sockaddr_storage mAddr; - bool mFound ; - bool mSearching ; - std::list _ip_servers ; -}; diff --git a/libretroshare/src/util/folderiterator.cc b/libretroshare/src/util/folderiterator.cc deleted file mode 100644 index c67204fc6..000000000 --- a/libretroshare/src/util/folderiterator.cc +++ /dev/null @@ -1,257 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: folderiterator.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include -#include -#include -#include -#include "util/rstime.h" - -#ifdef WINDOWS_SYS -#include "util/rswin.h" -#endif - -#include "folderiterator.h" -#include "rsstring.h" - -//#define DEBUG_FOLDER_ITERATOR 1 - -namespace librs { namespace util { - - -FolderIterator::FolderIterator(const std::string& folderName, bool allow_symlinks, bool allow_files_from_the_future) - : mFolderName(folderName),mAllowSymLinks(allow_symlinks),mAllowFilesFromTheFuture(allow_files_from_the_future) -{ - is_open = false ; - validity = false ; - mFileModTime = 0; - mFolderModTime = 0; - mFileSize = 0; - mType = TYPE_UNKNOWN; - - // Grab the last modification time for the directory - - struct stat64 buf ; - -#ifdef WINDOWS_SYS - std::wstring wfullname; - librs::util::ConvertUtf8ToUtf16(folderName, wfullname); - if ( 0 == _wstati64(wfullname.c_str(), &buf)) -#else - if ( 0 == stat64(folderName.c_str(), &buf)) -#endif - { - mFolderModTime = buf.st_mtime ; - } - - // Now open directory content and read the first entry - -#ifdef WINDOWS_SYS - std::wstring utf16Name; - if(! ConvertUtf8ToUtf16(folderName, utf16Name)) { - validity = false; - return; - } - - utf16Name += L"/*.*"; - - // FindFirstFileW does the "next" operation, so after calling it, we need to read the information - // for the current entry. - - handle = FindFirstFileW(utf16Name.c_str(), &fileInfo); - is_open = validity = handle != INVALID_HANDLE_VALUE; - - bool should_skip ; - validity = validity && updateFileInfo(should_skip); - - if(validity && should_skip) - next(); -#else - // On linux, we need to call "next()" once the dir is openned. next() will call updateFileInfo() itself. - - handle = opendir(folderName.c_str()); - is_open = validity = handle != NULL; - next(); -#endif -} - -FolderIterator::~FolderIterator() -{ - closedir(); -} - -void FolderIterator::next() -{ - bool should_skip = false ; - - while(readdir()) - if(updateFileInfo(should_skip) && !should_skip) - return ; - - #ifdef DEBUG_FOLDER_ITERATOR - std::cerr << "End of directory." << std::endl; -#endif - - mType = TYPE_UNKNOWN ; - mFileSize = 0 ; - mFileModTime = 0; - validity = false ; -} - -bool FolderIterator::updateFileInfo(bool& should_skip) -{ - should_skip = false; -#ifdef WINDOWS_SYS - ConvertUtf16ToUtf8(fileInfo.cFileName, mFileName) ; -#else - mFileName = ent->d_name ; -#endif - - if(mFileName == "." || mFileName == "..") - { - should_skip = true ; - return true ; - } - - mFullPath = mFolderName + "/" + mFileName ; - -#warning cyril soler: should we take care of symbolic links on windows? -#ifndef WINDOWS_SYS - if( ent->d_type == DT_LNK) - { - if(!mAllowSymLinks) - { - std::cerr << "(II) Skipping symbolic link " << mFullPath << std::endl; - should_skip = true ; - return true ; - } - } - else if( ent->d_type != DT_DIR && ent->d_type != DT_REG && ent->d_type != DT_UNKNOWN) // DT_UNKNOWN is reported by mounted dirs, by services such as sshfs. - { - std::cerr << "(II) Skipping file of unknown type " << std::dec << (int)ent->d_type << std::dec << ": " << mFullPath << std::endl; - should_skip = true ; - return true ; - } -#endif - - struct stat64 buf ; - -#ifdef DEBUG_FOLDER_ITERATOR - std::cerr << "FolderIterator: next. Looking into file " << mFileName ; -#endif - -#ifdef WINDOWS_SYS - std::wstring wfullname; - librs::util::ConvertUtf8ToUtf16(mFullPath, wfullname); - if ( 0 == _wstati64(wfullname.c_str(), &buf)) -#else - if ( 0 == stat64(mFullPath.c_str(), &buf)) -#endif - { - mFileModTime = buf.st_mtime ; - - if(buf.st_mtime > time(NULL) && !mAllowFilesFromTheFuture) - { - std::cerr << "(II) skipping file with modification time in the future: " << mFullPath << std::endl; - should_skip = true ; - return true ; - } - - if (S_ISDIR(buf.st_mode)) - { -#ifdef DEBUG_FOLDER_ITERATOR - std::cerr << ": is a directory" << std::endl; -#endif - - mType = TYPE_DIR ; - mFileSize = 0 ; - mFileModTime = buf.st_mtime; - - return true; - } - - if (S_ISREG(buf.st_mode)) - { -#ifdef DEBUG_FOLDER_ITERATOR - std::cerr << ": is a file" << std::endl; -#endif - - mType = TYPE_FILE ; - mFileSize = buf.st_size; - mFileModTime = buf.st_mtime; - - return true; - } - } - -#ifdef DEBUG_FOLDER_ITERATOR - std::cerr << ": is unknown skipping" << std::endl; -#endif - - mType = TYPE_UNKNOWN ; - mFileSize = 0 ; - mFileModTime = 0; - - return false; -} - -bool FolderIterator::readdir() -{ - if(!validity) - return false; - -#ifdef WINDOWS_SYS - return FindNextFileW(handle, &fileInfo) != 0; -#else - ent = ::readdir(handle); - return ent != NULL; -#endif -} - -rstime_t FolderIterator::dir_modtime() const { return mFolderModTime ; } - -const std::string& FolderIterator::file_fullpath() { return mFullPath ; } -const std::string& FolderIterator::file_name() { return mFileName ; } -uint64_t FolderIterator::file_size() { return mFileSize ; } -rstime_t FolderIterator::file_modtime() { return mFileModTime ; } -uint8_t FolderIterator::file_type() { return mType ; } - -bool FolderIterator::closedir() -{ - validity = false; - - if(!is_open) - return true ; - - is_open = false ; - -#ifdef WINDOWS_SYS - return FindClose(handle) != 0; -#else - return ::closedir(handle) == 0; -#endif -} - - - - -} } // librs::util diff --git a/libretroshare/src/util/folderiterator.h b/libretroshare/src/util/folderiterator.h deleted file mode 100644 index 19cbb8e9c..000000000 --- a/libretroshare/src/util/folderiterator.h +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: folderiterator.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef FOLDERITERATOR_H -#define FOLDERITERATOR_H - - -#include -#include -#include - -#ifdef WINDOWS_SYS - #include - #include - #include - #include -#else - #include -#endif - -#include "util/rstime.h" - -namespace librs { namespace util { - - -class FolderIterator -{ -public: - FolderIterator(const std::string& folderName,bool allow_symlinks,bool allow_files_from_the_future = true); - ~FolderIterator(); - - enum { TYPE_UNKNOWN = 0x00, - TYPE_FILE = 0x01, - TYPE_DIR = 0x02 - }; - - // info about current parent directory - rstime_t dir_modtime() const ; - - // info about directory content - - bool isValid() const { return validity; } - bool readdir(); - void next(); - - bool closedir(); - - const std::string& file_name() ; - const std::string& file_fullpath() ; - uint64_t file_size() ; - uint8_t file_type() ; - rstime_t file_modtime() ; - -private: - bool is_open; - bool validity; - -#ifdef WINDOWS_SYS - HANDLE handle; - bool isFirstCall; - _WIN32_FIND_DATAW fileInfo; -#else - DIR* handle; - struct dirent* ent; -#endif - bool updateFileInfo(bool &should_skip) ; - - rstime_t mFileModTime ; - rstime_t mFolderModTime ; - uint64_t mFileSize ; - uint8_t mType ; - std::string mFileName ; - std::string mFullPath ; - std::string mFolderName ; - bool mAllowSymLinks; - bool mAllowFilesFromTheFuture; -}; - - -} } // librs::util - - -#endif // FOLDERITERATOR_H diff --git a/libretroshare/src/util/i2pcommon.cpp b/libretroshare/src/util/i2pcommon.cpp deleted file mode 100644 index ec2ebfd6b..000000000 --- a/libretroshare/src/util/i2pcommon.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include "i2pcommon.h" - -#include "util/rsbase64.h" -#include "util/rsdebug.h" - -namespace i2p { - -std::string keyToBase32Addr(const std::string &key) -{ - std::string copy(key); - - // replace I2P specific chars - std::replace(copy.begin(), copy.end(), '~', '/'); - // replacing the - with a + is not necessary, as RsBase64 can handle base64url encoding, too - // std::replace(copy.begin(), copy.end(), '-', '+'); - - // decode - std::vector bin; - RsBase64::decode(copy, bin); - - // hash - std::vector sha256 = RsUtil::BinToSha256(bin); - // encode - std::string out = Radix32::encode(sha256); - - // i2p uses lowercase - std::transform(out.begin(), out.end(), out.begin(), ::tolower); - out.append(".b32.i2p"); - - return out; -} - -const std::string makeOption(const std::string &lhs, const int8_t &rhs) { - return lhs + "=" + std::to_string(rhs); -} - -uint16_t readTwoBytesBE(std::vector::const_iterator &p) -{ - uint16_t val = 0; - val += *p++; - val <<= 8; - val += *p++; - return val; -} - -std::string publicKeyFromPrivate(std::string const &priv) -{ - /* - * https://geti2p.net/spec/common-structures#destination - * https://geti2p.net/spec/common-structures#keysandcert - * https://geti2p.net/spec/common-structures#certificate - */ - if (priv.length() < 884) // base64 ( = 663 bytes = KeyCert + priv Keys) - return std::string(); - - // creat a copy to work on, need to convert it to standard base64 - auto priv_copy(priv); - std::replace(priv_copy.begin(), priv_copy.end(), '~', '/'); - // replacing the - with a + is not necessary, as RsBase64 can handle base64url encoding, too - // std::replace(copy.begin(), copy.end(), '-', '+'); - - // get raw data - std::vector dataPriv; - RsBase64::decode(priv_copy, dataPriv); - - auto p = dataPriv.cbegin(); - RS_DBG("dataPriv.size ", dataPriv.size()); - - size_t publicKeyLen = 256 + 128; // default length (bytes) - uint8_t certType = 0; - uint16_t len = 0; - uint16_t signingKeyType = 0; - uint16_t cryptKey = 0; - - // only used for easy break - do { - try { - // jump to certificate - p += publicKeyLen; - // try to read type and length - certType = *p++; - len = readTwoBytesBE(p); - - // only 0 and 5 are used / valid at this point - // check for == 0 - if (certType == static_cast::type>(CertType::Null)) { - /* - * CertType.Null - * type null is followed by 0x00 0x00 - * so has to be 0! - */ - RS_DBG("cert is CertType.Null"); - publicKeyLen += 3; // add 0x00 0x00 0x00 - - if (len != 0) - // weird - RS_DBG("cert is CertType.Null but len != 0"); - - break; - } - - // check for != 5 - if (certType != static_cast::type>(CertType::Key)) { - // unsupported - RS_DBG("cert type ", certType, " is unsupported"); - return std::string(); - } - - RS_DBG("cert is CertType.Key"); - publicKeyLen += 7; // = 1 + 2 + 2 + 2 = 7 bytes - - /* - * "Key certificates were introduced in release 0.9.12. Prior to that release, all PublicKeys were 256-byte ElGamal keys, and all SigningPublicKeys were 128-byte DSA-SHA1 keys." - * --> there is space for 256+128 bytes, longer keys are splitted and appended to the certificate - * We don't need to bother with the splitting here as only the lenght is important! - */ - - // Signing Public Key - // likely 7 - signingKeyType = readTwoBytesBE(p); - - RS_DBG("signing pubkey type ", certType); - if (signingKeyType >= 3 && signingKeyType <= 6) { - RS_DBG("signing pubkey type ", certType, " has oversize"); - // calculate oversize - - if (signingKeyType >= signingKeyLengths.size()) { - // just in case - RS_DBG("signing pubkey type ", certType, " cannot be found in size data!"); - return std::string(); - } - - auto values = signingKeyLengths[signingKeyType]; - if (values.first <= 128) { - // just in case, it's supposed to be larger! - RS_DBG("signing pubkey type ", certType, " is oversize but size calculation would underflow!"); - return std::string(); - } - - publicKeyLen += values.first - 128; // 128 = default DSA key length = the space than can be used before the key must be splitted - } - - // Crypto Public Key - // likely 0 - cryptKey = readTwoBytesBE(p); - RS_DBG("crypto pubkey type ", cryptKey); - // info: these are all smaller than the default 256 bytes, so no oversize calculation is needed - - break; - } catch (const std::out_of_range &e) { - RS_DBG("hit exception! ", e.what()); - return std::string(); - } - } while(false); - - std::string pub; - auto data2 = std::vector(dataPriv.cbegin(), dataPriv.cbegin() + publicKeyLen); - RsBase64::encode(data2.data(), data2.size(), pub, false, false); - - return pub; -} - -} // namespace i2p diff --git a/libretroshare/src/util/i2pcommon.h b/libretroshare/src/util/i2pcommon.h deleted file mode 100644 index 1fd152079..000000000 --- a/libretroshare/src/util/i2pcommon.h +++ /dev/null @@ -1,213 +0,0 @@ -#ifndef I2PCOMMON_H -#define I2PCOMMON_H - -#include -#include -#include -#include - -#include "util/rsrandom.h" -#include "util/radix32.h" -#include "util/rsbase64.h" -#include "util/rsprint.h" -#include "util/rsdebug.h" - -/* - * This header provides common code for i2p related code, namely BOB and SAM3 support. - */ - -namespace i2p { - -static constexpr int8_t kDefaultLength = 3; // i2p default -static constexpr int8_t kDefaultQuantity = 3; // i2p default + 1 -static constexpr int8_t kDefaultVariance = 0; -static constexpr int8_t kDefaultBackupQuantity = 0; - -/** - * @brief The address struct - * This structure is a container for any i2p address/key. The public key is used for addressing and can be (optionally) hashed to generate the .b32.i2p address. - */ -struct address { - std::string base32; - std::string publicKey; - std::string privateKey; - - void clear() { - base32.clear(); - publicKey.clear(); - privateKey.clear(); - } -}; - -/** - * @brief The settings struct - * Common structure with all settings that are shared between any i2p backends - */ -struct settings { - bool enable; - struct address address; - - // connection parameter - int8_t inLength; - int8_t inQuantity; - int8_t inVariance; - int8_t inBackupQuantity; - - int8_t outLength; - int8_t outQuantity; - int8_t outVariance; - int8_t outBackupQuantity; - - void initDefault() { - enable = false; - address.clear(); - - inLength = kDefaultLength; - inQuantity = kDefaultQuantity; - inVariance = kDefaultVariance; - inBackupQuantity = kDefaultBackupQuantity; - - outLength = kDefaultLength; - outQuantity = kDefaultQuantity; - outVariance = kDefaultVariance; - outBackupQuantity = kDefaultBackupQuantity; - } -}; - -/* - Type Type Code Payload Length Total Length Notes - Null 0 0 3 - HashCash 1 varies varies Experimental, unused. Payload contains an ASCII colon-separated hashcash string. - Hidden 2 0 3 Experimental, unused. Hidden routers generally do not announce that they are hidden. - Signed 3 40 or 72 43 or 75 Experimental, unused. Payload contains a 40-byte DSA signature, optionally followed by the 32-byte Hash of the signing Destination. - Multiple 4 varies varies Experimental, unused. Payload contains multiple certificates. - Key 5 4+ 7+ Since 0.9.12. See below for details. -*/ -enum class CertType : uint8_t { - Null = 0, - HashCash = 1, - Hidden = 2, - Signed = 3, - Multiple = 4, - Key = 5 -}; - -/* - * public - Type Type Code Total Public Key Length Since Usage - DSA_SHA1 0 128 0.9.12 Legacy Router Identities and Destinations, never explicitly set - ECDSA_SHA256_P256 1 64 0.9.12 Older Destinations - ECDSA_SHA384_P384 2 96 0.9.12 Rarely if ever used for Destinations - ECDSA_SHA512_P521 3 132 0.9.12 Rarely if ever used for Destinations - RSA_SHA256_2048 4 256 0.9.12 Offline only; never used in Key Certificates for Router Identities or Destinations - RSA_SHA384_3072 5 384 0.9.12 Offline only; never used in Key Certificates for Router Identities or Destinations - RSA_SHA512_4096 6 512 0.9.12 Offline only; never used in Key Certificates for Router Identities or Destinations - EdDSA_SHA512_Ed25519 7 32 0.9.15 Recent Router Identities and Destinations - EdDSA_SHA512_Ed25519ph 8 32 0.9.25 Offline only; never used in Key Certificates for Router Identities or Destinations - reserved (GOST) 9 64 Reserved, see proposal 134 - reserved (GOST) 10 128 Reserved, see proposal 134 - RedDSA_SHA512_Ed25519 11 32 0.9.39 For Destinations and encrypted leasesets only; never used for Router Identities - reserved 65280-65534 Reserved for experimental use - reserved 65535 Reserved for future expansion - - * private - Type Length (bytes) Since Usage - DSA_SHA1 20 Legacy Router Identities and Destinations - ECDSA_SHA256_P256 32 0.9.12 Recent Destinations - ECDSA_SHA384_P384 48 0.9.12 Rarely used for Destinations - ECDSA_SHA512_P521 66 0.9.12 Rarely used for Destinations - RSA_SHA256_2048 512 0.9.12 Offline signing, never used for Router Identities or Destinations - RSA_SHA384_3072 768 0.9.12 Offline signing, never used for Router Identities or Destinations - RSA_SHA512_4096 1024 0.9.12 Offline signing, never used for Router Identities or Destinations - EdDSA_SHA512_Ed25519 32 0.9.15 Recent Router Identities and Destinations - EdDSA_SHA512_Ed25519ph 32 0.9.25 Offline signing, never used for Router Identities or Destinations - RedDSA_SHA512_Ed25519 32 0.9.39 For Destinations and encrypted leasesets only, never used for Router Identities - */ -enum class SigningKeyType : uint16_t { - DSA_SHA1 = 0, - ECDSA_SHA256_P256 = 1, - ECDSA_SHA384_P384 = 2, - ECDSA_SHA512_P521 = 3, - RSA_SHA256_2048 = 4, - RSA_SHA384_3072 = 5, - RSA_SHA512_4096 = 6, - EdDSA_SHA512_Ed25519 = 7, - EdDSA_SHA512_Ed25519ph = 8, - RedDSA_SHA512_Ed25519 = 11 -}; - -/* - * public - Type Type Code Total Public Key Length Usage - ElGamal 0 256 All Router Identities and Destinations - P256 1 64 Reserved, see proposal 145 - P384 2 96 Reserved, see proposal 145 - P521 3 132 Reserved, see proposal 145 - X25519 4 32 Not for use in key certs. See proposal 144 - reserved 65280-65534 Reserved for experimental use - reserved 65535 Reserved for future expansion - - * private - Type Length (bytes) Since Usage - ElGamal 256 All Router Identities and Destinations - P256 32 TBD Reserved, see proposal 145 - P384 48 TBD Reserved, see proposal 145 - P521 66 TBD Reserved, see proposal 145 - X25519 32 0.9.38 Little-endian. See proposal 144 -*/ -enum class CryptoKeyType : uint16_t { - ElGamal = 0, - P256 = 1, - P384 = 2, - P521 = 3, - X25519 = 4 -}; - -static const std::array, 5> cryptoKeyLengths { - /*CryptoKeyType::ElGamal*/ std::make_pair(256, 256), - /*CryptoKeyType::P256, */ std::make_pair( 64, 32), - /*CryptoKeyType::P384, */ std::make_pair( 96, 48), - /*CryptoKeyType::P521, */ std::make_pair(132, 66), - /*CryptoKeyType::X25519,*/ std::make_pair( 32, 32), -}; - -static const std::array, 12> signingKeyLengths { - /*SigningKeyType::DSA_SHA1, */ std::make_pair(128, 128), - /*SigningKeyType::ECDSA_SHA256_P256, */ std::make_pair( 64, 32), - /*SigningKeyType::ECDSA_SHA384_P384, */ std::make_pair( 96, 48), - /*SigningKeyType::ECDSA_SHA512_P521, */ std::make_pair(132, 66), - /*SigningKeyType::RSA_SHA256_2048, */ std::make_pair(256, 512), - /*SigningKeyType::RSA_SHA384_3072, */ std::make_pair(384, 768), - /*SigningKeyType::RSA_SHA512_4096, */ std::make_pair(512,1024), - /*SigningKeyType::EdDSA_SHA512_Ed25519 */ std::make_pair( 32, 32), - /*SigningKeyType::EdDSA_SHA512_Ed25519ph */ std::make_pair( 32, 32), - /*reserved (GOST) */ std::make_pair( 64, 0), - /*reserved (GOST) */ std::make_pair(128, 0), - /*SigningKeyType::RedDSA_SHA512_Ed25519 */ std::make_pair( 32, 32), -}; - -/** - * @brief makeOption Creates the string "lhs=rhs" used by BOB and SAM. Converts rhs - * @param lhs option to set - * @param rhs value to set - * @return concatenated string - */ -const std::string makeOption(const std::string &lhs, const int8_t &rhs); - -/** - * @brief keyToBase32Addr generated a base32 address (.b32.i2p) from a given public key - * @param key public key - * @return generated base32 address - */ -std::string keyToBase32Addr(const std::string &key); - -/** - * @brief publicKeyFromPrivate parses the private key and calculates the lenght of the public key - * @param priv private key (which includes the public key) to read - * @return public key used for addressing - */ -std::string publicKeyFromPrivate(const std::string &priv); - -} // namespace i2p - -#endif // I2PCOMMON_H diff --git a/libretroshare/src/util/radix32.h b/libretroshare/src/util/radix32.h deleted file mode 100644 index 46219da17..000000000 --- a/libretroshare/src/util/radix32.h +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: radix32.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RADIX32_H -#define RADIX32_H - -#include -#include -#include -#include - -class Radix32 -{ -public: - static std::string encode(const std::vector &in) { - return encode(in.data(), in.size()); - } - - static std::string encode(const uint8_t *data, size_t len) { - std::string out = ""; - - size_t pos = 1; - uint8_t bits = 8, index; - uint16_t tmp = data[0]; // need min. 16 bits here - while (bits > 0 || pos < len) { - if (bits < 5) { - if (pos < len) { - tmp <<= 8; - tmp |= data[pos++] & 0xFF; - bits += 8; - } else { // last byte - tmp <<= (5 - bits); - bits = 5; - } - } - - bits -= 5; - index = (tmp >> bits) & 0x1F; - out.push_back(bintoasc()[index]); - } - - // append padding - while(out.length() % 4 != 0) - out.push_back('='); - - return out; - } - -private: - static const inline char *bintoasc() { static const char bta[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; return bta ; } -}; - -#endif // RADIX32_H diff --git a/libretroshare/src/util/radix64.h b/libretroshare/src/util/radix64.h deleted file mode 100644 index 53dd7c256..000000000 --- a/libretroshare/src/util/radix64.h +++ /dev/null @@ -1,200 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: radix64.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "util/rsdeprecate.h" - -/** @deprecated use RsBase64 instead which supports also URL safe encoding */ -class RS_DEPRECATED_FOR(RsBase64) Radix64 -{ -public: - static std::vector decode(const std::string& buffer) - { - char val; - int c = 0, c2;/* init c because gcc is not clever - enough for the continue */ - int idx; - size_t buffer_pos = 0; - - radix64_init(); - - std::vector buf ; - idx = 0; - val = 0; - - for (buffer_pos = 0; buffer_pos < buffer.length(); buffer_pos++) - { - c = buffer[buffer_pos]; - -again: - if (c == '\n' || c == ' ' || c == '\r' || c == '\t') - continue; - else if (c == '=') - { - /* pad character: stop */ - /* some mailers leave quoted-printable - * encoded characters so we try to - * workaround this */ - if (buffer_pos + 2 < buffer.length()) - { - int cc1, cc2, cc3; - cc1 = buffer[buffer_pos]; - cc2 = buffer[buffer_pos + 1]; - cc3 = buffer[buffer_pos + 2]; - - if (isxdigit((unsigned char)cc1) && isxdigit((unsigned char)cc2) && strchr("=\n\r\t ", cc3)) - { - /* well it seems to be the case - - * adjust */ - c = - isdigit((unsigned char)cc1) ? (cc1 - - '0') - : (toupper((unsigned char)cc1) - 'A' + 10); - c <<= 4; - c |= - isdigit((unsigned char)cc2) ? (cc2 - - '0') - : (toupper((unsigned char)cc2) - 'A' + 10); - buffer_pos += 2; - goto again; - } - } - - if (idx == 1) - buf.push_back(val) ;// buf[n++] = val; - break; - } - else if ((c = asctobin()[(c2 = c)]) == 255) - { - /* invalid radix64 character %02x skipped\n", c2; */ - continue; - } - - switch (idx) - { - case 0: - val = c << 2; - break; - case 1: - val |= (c >> 4) & 3; - buf.push_back(val);//buf[n++] = val; - val = (c << 4) & 0xf0; - break; - case 2: - val |= (c >> 2) & 15; - buf.push_back(val);//buf[n++] = val; - val = (c << 6) & 0xc0; - break; - case 3: - val |= c & 0x3f; - buf.push_back(val);//buf[n++] = val; - break; - } - idx = (idx + 1) % 4; - } - - //idx = idx; - - return buf ; - } - - /**************** - * create a radix64 encoded string. - */ - static void encode( - const unsigned char* data, size_t len, std::string& out_string ) - { - char *buffer, *p; - - radix64_init(); - - size_t size = (len + 2) / 3 * 4 +1; - buffer = p = new char[size] ; - - for (; len >= 3; len -= 3, data += 3) - { - *p++ = bintoasc()[(data[0] >> 2) & 077]; - *p++ = - bintoasc()[ - (((data[0] << 4) & 060) | - ((data[1] >> 4) & 017)) & 077]; - *p++ = - bintoasc()[ - (((data[1] << 2) & 074) | - ((data[2] >> 6) & 03)) & 077]; - *p++ = bintoasc()[data[2] & 077]; - } - if (len == 2) - { - *p++ = bintoasc()[(data[0] >> 2) & 077]; - *p++ = - bintoasc()[ - (((data[0] << 4) & 060) | - ((data[1] >> 4) & 017)) & 077]; - *p++ = bintoasc()[((data[1] << 2) & 074)]; - *p++ = '=' ; - } - else if (len == 1) - { - *p++ = bintoasc()[(data[0] >> 2) & 077]; - *p++ = bintoasc()[(data[0] << 4) & 060]; - *p++ = '=' ; - *p++ = '=' ; - } - //*p = 0; - out_string = std::string(buffer,p-buffer) ; - delete[] buffer ; - } - - private: - static inline char *bintoasc() { static char bta[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; return bta ; } - static inline uint8_t *asctobin() { static uint8_t s[256]; return s ; } /* runtime radix64_initd */ - static int& is_radix64_initd() { static int is_inited = false ; return is_inited ; } - - /* hey, guess what: this is a read-only table. - * we don't _care_ if multiple threads get to initialise it - * at the same time, _except_ that is_radix64_initd=1 _must_ - * be done at the end... - */ - static bool radix64_init() - { - if (is_radix64_initd()) - return true; - - int i; - char *s; - - /* build the helpapr_table_t for radix64 to bin conversion */ - for (i = 0; i < 256; i++) - asctobin()[i] = 255; /* used to detect invalid characters */ - for (s = bintoasc(), i = 0; *s; s++, i++) - asctobin()[(int)*s] = i; - - is_radix64_initd() = 1; - return true ; - } -}; diff --git a/libretroshare/src/util/retrodb.cc b/libretroshare/src/util/retrodb.cc deleted file mode 100644 index 122f3e6a1..000000000 --- a/libretroshare/src/util/retrodb.cc +++ /dev/null @@ -1,866 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: retrodb.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Christopher Evi-Parker * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#include -#include -#include -#include -#include - -#include "util/rstime.h" -#include "util/retrodb.h" -#include "util/rsdbbind.h" -#include "util/stacktrace.h" -#include "util/rsdir.h" - -//#define RETRODB_DEBUG - -const int RetroDb::OPEN_READONLY = SQLITE_OPEN_READONLY; -const int RetroDb::OPEN_READWRITE = SQLITE_OPEN_READWRITE; -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(nullptr), mKey(key) -{ - bool alreadyExists = RsDirUtil::fileExists(dbPath); - - int rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, nullptr); - if(rc) - { - RsErr() << __PRETTY_FUNCTION__ << " Can't open database, Error: " - << rc << " " << sqlite3_errmsg(mDb) << std::endl; - closeDb(); - print_stacktrace(); - return; - } - - if(alreadyExists) - { - /* If the database has been created by a RetroShare compiled without - * SQLCipher, open it as a plain SQLite database instead of failing - * miserably. If RetroShare has been compiled without SQLCipher but the - * database seems encrypted print a meaningful error message instead of - * crashing miserably. - * At some point we could implement a migration SQLite <-> SQLCipher - * mecanism and suggest it to the user, or give the option to the user - * to choice between plain SQLite or SQLCipher database, is some cases - * such as encrypted FS it might make sense to keep SQLite even if - * SQLCipher is availble for performance, as encryption is already - * provided at FS level. */ - - rc = sqlite3_exec( mDb, "PRAGMA schema_version;", - nullptr, nullptr, nullptr ); - if( rc == SQLITE_OK ) - { -#ifndef NO_SQLCIPHER - RsWarn() << __PRETTY_FUNCTION__ << " The database is not encrypted: " - << dbPath << std::endl; -#endif // ndef NO_SQLCIPHER - - return; - } - else - { -#ifdef NO_SQLCIPHER - RsErr() << __PRETTY_FUNCTION__ << " Error quering schema version." - << " Are you trying to open an encrypted database without " - << "compiling SQLCipher support?" << std::endl << std::endl; - print_stacktrace(); - closeDb(); -#else // def NO_SQLCIPHER - RsInfo() << __PRETTY_FUNCTION__ << " The database seems encrypted: " - << dbPath << std::endl; -#endif // def NO_SQLCIPHER - } - } - -#ifndef NO_SQLCIPHER - if(!mKey.empty()) - { - rc = sqlite3_key(mDb, mKey.c_str(), static_cast(mKey.size())); - - if(rc) - { - RsErr() << __PRETTY_FUNCTION__ << " Can't key database: " << rc - << " " << sqlite3_errmsg(mDb) << std::endl; - closeDb(); - return; - } - } - - 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(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() { closeDb(); } - -void RetroDb::closeDb() -{ - // no-op if mDb is nullptr (https://www.sqlite.org/c3ref/close.html) - int rc = sqlite3_close(mDb); - mDb = nullptr; - - Dbg2() << __PRETTY_FUNCTION__ << " sqlite3_close return: " << rc - << std::endl; -} - -#define TIME_LIMIT 3 - -bool RetroDb::execSQL(const std::string &query){ - - // prepare statement - sqlite3_stmt* stm = NULL; - -#ifdef RETRODB_DEBUG - std::cerr << "Query: " << query << std::endl; -#endif - - int rc = sqlite3_prepare_v2(mDb, query.c_str(), query.length(), &stm, NULL); - - // check if there are any errors - if(rc != SQLITE_OK){ - std::cerr << "RetroDb::execSQL(): Error preparing statement\n"; - std::cerr << "Error code: " << sqlite3_errmsg(mDb) - << std::endl; - return false; - } - - - uint32_t delta = 3; - rstime_t stamp = time(NULL); - bool timeOut = false, ok = false; - - while(!timeOut){ - - rc = sqlite3_step(stm); - - if(rc == SQLITE_DONE){ - ok = true; - break; - } - - if(rc != SQLITE_BUSY){ - ok = false; - break; - } - - if(time(NULL) > stamp + TIME_LIMIT) - { - ok = false; - timeOut = true; - } - // TODO add sleep so not to waste - // precious cycles - } - - if(!ok){ - - if(rc == SQLITE_BUSY){ - std::cerr << "RetroDb::execSQL()\n" ; - std::cerr << "SQL timed out!" << std::endl; - }else{ - std::cerr << "RetroDb::execSQL(): Error executing statement (code: " << rc << ")\n"; - std::cerr << "Sqlite Error msg: " << sqlite3_errmsg(mDb) - << std::endl; - std::cerr << "RetroDb::execSQL() Query: " << query << std::endl; - } - } - - // finalise statement or else db cannot be closed - sqlite3_finalize(stm); - return ok; -} - -RetroCursor* RetroDb::sqlQuery(const std::string& tableName, const std::list& columns, - const std::string& selection, const std::string& orderBy){ - - if(tableName.empty() || columns.empty()){ - std::cerr << "RetroDb::sqlQuery(): No table or columns given" << std::endl; - return NULL; - } - - std::string columnSelection; // the column names to return - sqlite3_stmt* stmt = NULL; - std::list::const_iterator it = columns.begin(); - - for(; it != columns.end(); ++it){ - if (it != columns.begin()) { - columnSelection += ","; - } - - columnSelection += *it; - } - - // construct query - // SELECT columnSelection FROM tableName WHERE selection - std::string sqlQuery = "SELECT " + columnSelection + " FROM " + - tableName; - - // add selection clause if present - if(!selection.empty()) - sqlQuery += " WHERE " + selection; - - - // add 'order by' clause if present - if(!orderBy.empty()) - sqlQuery += " ORDER BY " + orderBy + ";"; - else - sqlQuery += ";"; - -#ifdef RETRODB_DEBUG - std::cerr << "RetroDb::sqlQuery(): " << sqlQuery << std::endl; -#endif - - sqlite3_prepare_v2(mDb, sqlQuery.c_str(), sqlQuery.length(), &stmt, NULL); - return (new RetroCursor(stmt)); -} - -bool RetroDb::isOpen() const { - return (mDb==NULL ? false : true); -} - -bool RetroDb::sqlInsert(const std::string &table, const std::string& /* nullColumnHack */, const ContentValue &cv){ - - std::map keyTypeMap; - cv.getKeyTypeMap(keyTypeMap); - std::map::iterator mit = keyTypeMap.begin(); - - // build columns part of insertion - std::string qColumns = table + "("; - - for(; mit != keyTypeMap.end(); ++mit){ - - qColumns += mit->first; - - ++mit; - - // add comma if more columns left - if(mit == keyTypeMap.end()) - qColumns += ")"; // close bracket if at end - else - qColumns += ","; - - --mit; - } - - // build values part of insertion - std::string qValues; - std::list paramBindings; - buildInsertQueryValue(keyTypeMap, cv, qValues, paramBindings); - - // complete insertion query - std::string sqlQuery = "INSERT INTO " + qColumns + " " + qValues; - - bool ok = execSQL_bind(sqlQuery, paramBindings); - -#ifdef RETRODB_DEBUG - std::cerr << "RetroDb::sqlInsert(): " << sqlQuery << std::endl; -#endif - - return ok; -} - -std::string RetroDb::getKey() const -{ - return mKey; -} - -bool RetroDb::beginTransaction() -{ - if (!isOpen()) { - return false; - } - - return execSQL("BEGIN;"); -} - -bool RetroDb::commitTransaction() -{ - if (!isOpen()) { - return false; - } - - return execSQL("COMMIT;"); -} -bool RetroDb::rollbackTransaction() -{ - if (!isOpen()) { - return false; - } - - return execSQL("ROLLBACK;"); -} - -bool RetroDb::execSQL_bind(const std::string &query, std::list ¶mBindings){ - - // prepare statement - sqlite3_stmt* stm = NULL; - -#ifdef RETRODB_DEBUG - std::cerr << "Query: " << query << std::endl; -#endif - - int rc = sqlite3_prepare_v2(mDb, query.c_str(), query.length(), &stm, NULL); - - // check if there are any errors - if(rc != SQLITE_OK){ - std::cerr << "RetroDb::execSQL_bind(): Error preparing statement\n"; - std::cerr << "Error code: " << sqlite3_errmsg(mDb) - << std::endl; - return false; - } - - std::list::iterator lit = paramBindings.begin(); - - for(; lit != paramBindings.end(); ++lit){ - RetroBind* rb = *lit; - - if(!rb->bind(stm)) - { - std::cerr << "\nBind failed for index: " << rb->getIndex() - << std::endl; - } - - delete rb; - rb = NULL; - } - - uint32_t delta = 3; - rstime_t stamp = time(NULL), now = 0; - bool timeOut = false, ok = false; - - while(!timeOut){ - - rc = sqlite3_step(stm); - - if(rc == SQLITE_DONE){ - ok = true; - break; - } - - if(rc != SQLITE_BUSY){ - ok = false; - break; - } - - now = time(NULL); - delta = stamp - now; - - if(delta > TIME_LIMIT){ - ok = false; - timeOut = true; - } - // TODO add sleep so not to waste - // precious cycles - } - - if(!ok){ - - if(rc == SQLITE_BUSY){ - std::cerr << "RetroDb::execSQL_bind()\n" ; - std::cerr << "SQL timed out!" << std::endl; - }else{ - std::cerr << "RetroDb::execSQL_bind(): Error executing statement (code: " << rc << ")\n"; - std::cerr << "Sqlite Error msg: " << sqlite3_errmsg(mDb) - << std::endl; - std::cerr << "RetroDb::execSQL_bind() Query: " << query << std::endl; - } - } - - // finalise statement or else db cannot be closed - sqlite3_finalize(stm); - return ok; -} - -void RetroDb::buildInsertQueryValue(const std::map keyTypeMap, - const ContentValue& cv, std::string& parameter, - std::list& paramBindings) -{ - std::map::const_iterator mit = keyTypeMap.begin(); - - parameter = "VALUES("; - int index = 0; - for(mit=keyTypeMap.begin(); mit!=keyTypeMap.end(); ++mit) - { - - uint8_t type = mit->second; - std::string key = mit->first; - - RetroBind* rb = NULL; - if(ContentValue::BOOL_TYPE == type) - { - bool value; - cv.getAsBool(key, value); - rb = new RsBoolBind(value, ++index); - } - else if( ContentValue::DOUBLE_TYPE == type) - { - double value; - cv.getAsDouble(key, value); - rb = new RsDoubleBind(value, ++index); - } - else if( ContentValue::DATA_TYPE == type) - { - char* value; - uint32_t len; - cv.getAsData(key, len, value); - rb = new RsBlobBind(value, len, ++index); - } - else if ( ContentValue::STRING_TYPE == type) - { - std::string value; - cv.getAsString(key, value); - rb = new RsStringBind(value, ++index); - } - else if ( ContentValue::INT32_TYPE == type) - { - int32_t value = 0; - cv.getAsInt32(key, value); - rb = new RsInt32Bind(value, ++index); - } - else if( ContentValue::INT64_TYPE == type) - { - int64_t value = 0; - cv.getAsInt64(key, value); - rb = new RsInt64bind(value, ++index); - } - - if(rb) - { - paramBindings.push_back(rb); - - ++mit; - - if(mit == keyTypeMap.end()) - parameter += "?"; - else - parameter += "?,"; - - --mit; - } - } - - parameter += ")"; - - -} - -void RetroDb::buildUpdateQueryValue(const std::map keyTypeMap, - const ContentValue& cv, std::string& parameter, - std::list& paramBindings) -{ - std::map::const_iterator mit = keyTypeMap.begin(); - - int index = 0; - for(mit=keyTypeMap.begin(); mit!=keyTypeMap.end(); ++mit) - { - - uint8_t type = mit->second; - std::string key = mit->first; - - RetroBind* rb = NULL; - if(ContentValue::BOOL_TYPE == type) - { - bool value; - cv.getAsBool(key, value); - rb = new RsBoolBind(value, ++index); - } - else if( ContentValue::DOUBLE_TYPE == type) - { - double value; - cv.getAsDouble(key, value); - rb = new RsDoubleBind(value, ++index); - } - else if( ContentValue::DATA_TYPE == type) - { - char* value; - uint32_t len; - cv.getAsData(key, len, value); - rb = new RsBlobBind(value, len, ++index); - } - else if ( ContentValue::STRING_TYPE == type) - { - std::string value; - cv.getAsString(key, value); - rb = new RsStringBind(value, ++index); - } - else if ( ContentValue::INT32_TYPE == type) - { - int32_t value = 0; - cv.getAsInt32(key, value); - rb = new RsInt32Bind(value, ++index); - } - else if( ContentValue::INT64_TYPE == type) - { - int64_t value = 0; - cv.getAsInt64(key, value); - rb = new RsInt64bind(value, ++index); - } - - if(rb) - { - paramBindings.push_back(rb); - - ++mit; - - if(mit == keyTypeMap.end()) - parameter += key + "=?"; - else - parameter += key + "=?,"; - - --mit; - } - } - -} - -bool RetroDb::sqlDelete(const std::string &tableName, const std::string &whereClause, const std::string &/*whereArgs*/){ - - std::string sqlQuery = "DELETE FROM " + tableName; - - if(!whereClause.empty()){ - sqlQuery += " WHERE " + whereClause + ";"; - }else - sqlQuery += ";"; - - return execSQL(sqlQuery); -} - - -bool RetroDb::sqlUpdate(const std::string &tableName, std::string whereClause, const ContentValue& cv){ - - std::string sqlQuery = "UPDATE " + tableName + " SET "; - - - std::map keyTypeMap; - std::map::iterator mit; - cv.getKeyTypeMap(keyTypeMap); - - // build SET part of update - std::string qValues; - std::list paramBindings; - buildUpdateQueryValue(keyTypeMap, cv, qValues, paramBindings); - - if(qValues.empty()) - return false; - else - sqlQuery += qValues; - - // complete update - if(!whereClause.empty()){ - sqlQuery += " WHERE " + whereClause + ";"; - } - else{ - sqlQuery += ";"; - } - - // execute query - return execSQL_bind(sqlQuery, paramBindings); -} - -bool RetroDb::tableExists(const std::string &tableName) -{ - if (!isOpen()) { - return false; - } - - std::string sqlQuery = "PRAGMA table_info(" + tableName + ");"; - - bool result = false; - sqlite3_stmt* stmt = NULL; - - int rc = sqlite3_prepare_v2(mDb, sqlQuery.c_str(), sqlQuery.length(), &stmt, NULL); - if (rc == SQLITE_OK) { - rc = sqlite3_step(stmt); - switch (rc) { - case SQLITE_ROW: - result = true; - break; - case SQLITE_DONE: - break; - default: - std::cerr << "RetroDb::tableExists(): Error executing statement (code: " << rc << ")" - << std::endl; - return false; - } - } else { - std::cerr << "RetroDb::tableExists(): Error preparing statement\n"; - std::cerr << "Error code: " << sqlite3_errmsg(mDb) - << std::endl; - } - - if (stmt) { - sqlite3_finalize(stmt); - } - - return result; -} - -/********************** RetroCursor ************************/ - -RetroCursor::RetroCursor(sqlite3_stmt *stmt) - : mStmt(NULL) { - - open(stmt); -} - -RetroCursor::~RetroCursor(){ - - // finalise statement - if(mStmt){ - sqlite3_finalize(mStmt); - } -} - -bool RetroCursor::moveToFirst(){ - -#ifdef RETRODB_DEBUG - std::cerr << "RetroCursor::moveToFirst()\n"; -#endif - - if(!isOpen()) - return false; - - // reset statement - int rc = sqlite3_reset(mStmt); - - if(rc != SQLITE_OK){ - -#ifdef RETRODB_DEBUG - std::cerr << "Error code: " << rc << std::endl; -#endif - - return false; - } - - rc = sqlite3_step(mStmt); - - if(rc == SQLITE_ROW){ - return true; - } - -#ifdef RETRODB_DEBUG - std::cerr << "Error code: " << rc << std::endl; -#endif - - return false; -} - -bool RetroCursor::moveToLast(){ - -#ifdef RETRODB_DEBUG - std::cerr << "RetroCursor::moveToLast()\n"; -#endif - - if(!isOpen()) - return -1; - - // go to begining - int rc = sqlite3_reset(mStmt); - - if(rc != SQLITE_OK) - return false; - - rc = sqlite3_step(mStmt); - - while(rc == SQLITE_ROW){ - rc = sqlite3_step(mStmt); - } - - if(rc != SQLITE_DONE){ - std::cerr << "Error executing statement (code: " << rc << ")\n" - << std::endl; - return false; - - }else{ - return true; - } -} - -int RetroCursor::columnCount() const { - - if(isOpen()) - return sqlite3_data_count(mStmt); - else - return -1; -} - -bool RetroCursor::isOpen() const { - return !(mStmt == NULL); -} - -bool RetroCursor::close(){ - - if(!isOpen()) - return false; - - - int rc = sqlite3_finalize(mStmt); - mStmt = NULL; - - return (rc == SQLITE_OK); -} - -bool RetroCursor::open(sqlite3_stmt *stm){ - -#ifdef RETRODB_DEBUG - std::cerr << "RetroCursor::open() \n"; -#endif - - if(isOpen()) - close(); - - mStmt = stm; - - // ensure statement is valid - int rc = sqlite3_reset(mStmt); - - if(rc == SQLITE_OK){ - return true; - } - else{ - std::cerr << "Error Opening cursor (code: " << rc << ")\n"; - close(); - return false; - } - -} - -bool RetroCursor::moveToNext(){ - -#ifdef RETRODB_DEBUG - std::cerr << "RetroCursor::moveToNext()\n"; -#endif - - if(!isOpen()) - return false; - - int rc = sqlite3_step(mStmt); - - if(rc == SQLITE_ROW){ - return true; - - }else if(rc == SQLITE_DONE){ // no more results - return false; - } - else if(rc == SQLITE_BUSY){ // should not enter here - std::cerr << "RetroDb::moveToNext()\n" ; - std::cerr << "Busy!, possible multiple accesses to Db" << std::endl - << "serious error"; - - return false; - - }else{ - std::cerr << "Error executing statement (code: " << rc << ")\n"; - return false; - } -} - -int32_t RetroCursor::getInt32(int columnIndex){ - return sqlite3_column_int(mStmt, columnIndex); -} - -int64_t RetroCursor::getInt64(int columnIndex){ - return sqlite3_column_int64(mStmt, columnIndex); -} - -bool RetroCursor::getBool(int columnIndex){ - return sqlite3_column_int(mStmt, columnIndex); -} - -double RetroCursor::getDouble(int columnIndex){ - return sqlite3_column_double(mStmt, columnIndex); -} - -void RetroCursor::getString(int columnIndex, std::string &str){ - str.clear(); - char* raw_str = (char*)sqlite3_column_text(mStmt, columnIndex); - if(raw_str != NULL) - { - str.assign(raw_str); -#ifdef RADIX_STRING - char* buffer = NULL; - size_t buffLen; - Radix64::decode(str, buffer, buffLen); - str.clear(); - if(buffLen != 0) - { - str.assign(buffer, buffLen); - delete[] buffer; - } - else - str.clear(); -#endif - } - else - { - str.clear(); - } -} - -const void* RetroCursor::getData(int columnIndex, uint32_t &datSize){ - - const void* val = sqlite3_column_blob(mStmt, columnIndex); - datSize = sqlite3_column_bytes(mStmt, columnIndex); - - return val; -} - diff --git a/libretroshare/src/util/retrodb.h b/libretroshare/src/util/retrodb.h deleted file mode 100644 index b48415152..000000000 --- a/libretroshare/src/util/retrodb.h +++ /dev/null @@ -1,322 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: retrodb.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#ifdef NO_SQLCIPHER -#include -#else -#include -#endif - -#include -#include -#include -#include - -#include "util/rsdebug.h" -#include "util/rsdbbind.h" -#include "util/contentvalue.h" - -class RetroCursor; - -/*! - * RetroDb provide a means for Retroshare's core and \n - * services to maintain an easy to use random access file via a database \n - * It models itself after android's sqlite functionality \n - * This is essentially unashamedly a clone of Android's SQLiteDatabase interface - */ -class RetroDb -{ -public: - - /*! - * @param dbPath path to data base file - * @param flags determine where to open read only or read/write - */ - RetroDb(const std::string& dbPath, int flags, const std::string& key = ""); - - /*! - * closes db if it is not already closed - */ - ~RetroDb(); - - /*! - * @return key used to encrypt database - */ - std::string getKey() const; - - /*! - * opens sqlite data base - * @param dbPath - * @param flags - * @return false if failed to open, true otherwise - */ - bool openDb(const std::string& dbPath, int flags = OPEN_READONLY); - - /*! - * close the database - */ - void closeDb(); - - /*! - * - * @return false if database is not open, true otherwise - */ - bool isOpen() const; - - /* modifying db */ -public: - - /*! - * Start transaction - * @return true/false - */ - bool beginTransaction(); - - /*! - * Commit transaction - * @return true/false - */ - bool commitTransaction(); - - /*! - * Rollback transaction - * @return true/false - */ - bool rollbackTransaction(); - - /*! - * To a make query which do not return a result \n - * below are the type of queries this method should be used for \n - * ALTER TABLE \n - * CREATE or DROP table / trigger / view / index / virtual table \n - * REINDEX \n - * RELEASE \n - * SAVEPOINT \n - * PRAGMA that returns no data \n - * @param query SQL query - * @return false if there was an sqlite error, true otherwise - */ - bool execSQL(const std::string& query); - - /*! - * inserts a row in a database table - * @param table table you want to insert content values into - * @param nullColumnHack SQL doesn't allow inserting a completely \n - * empty row without naming at least one column name - * @param cv hold entries to insert - * @return true if insertion successful, false otherwise - */ - bool sqlInsert(const std::string& table,const std::string& nullColumnHack, const ContentValue& cv); - - /*! - * update row in a database table - * @param tableName the table on which to apply the UPDATE - * @param whereClause formatted as where statement without 'WHERE' itself - * @param cv Values used to replace current values in accessed record - * @return true if update was successful, false otherwise - */ - bool sqlUpdate(const std::string& tableName, const std::string whereClause, const ContentValue& cv); - - /*! - * Query the given table, returning a Cursor over the result set - * @param tableName the table name - * @param columns list columns that should be returned and their order (the list's order) - * @param selection A filter declaring which rows to return, formatted as \n - * an SQL WHERE clause (excluding the WHERE itself). Passing null will \n - * return all rows for the given table. - * @param order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself) - * @return cursor over result set, this allocated resource should be free'd after use \n - * column order is in list order. - */ - RetroCursor* sqlQuery(const std::string& tableName, const std::list& columns, - const std::string& selection, const std::string& orderBy); - - /*! - * delete row in an sql table - * @param tableName the table on which to apply the DELETE - * @param whereClause formatted as where statement without 'WHERE' itself - * @return false - */ - bool sqlDelete(const std::string& tableName, const std::string& whereClause, const std::string& whereArgs); - - /*! - * TODO - * defragment database, should be done on databases if many modifications have occured - */ - void vacuum(); - - /*! - * Check if table exist in database - * @param tableName table to check - * @return true/false - */ - bool tableExists(const std::string& tableName); - -public: - - static const int OPEN_READONLY; - static const int OPEN_READWRITE; - static const int OPEN_READWRITE_CREATE; - -private: - - bool execSQL_bind(const std::string &query, std::list& blobs); - - /*! - * Build the "VALUE" part of an insertiong sql query - * @param parameter contains place holder query - * @param paramBindings - */ - void buildInsertQueryValue(const std::map keyMap, const ContentValue& cv, - std::string& parameter, std::list& paramBindings); - - /*! - * Build the "VALUE" part of an insertiong sql query - * @param parameter contains place holder query - * @param paramBindings - */ - void buildUpdateQueryValue(const std::map keyMap, const ContentValue& cv, - std::string& parameter, std::list& paramBindings); - -private: - - sqlite3* mDb; - const std::string mKey; - - RS_SET_CONTEXT_DEBUG_LEVEL(3) -}; - -/*! - * Exposes result set from retrodb query - */ -class RetroCursor { - -public: - - /*! - * Initialises a null cursor - * @warning cursor takes ownership of statement passed to it - */ - RetroCursor(sqlite3_stmt*); - - ~RetroCursor(); - - /*! - * move to first row of results - * @return false if no results - */ - bool moveToFirst(); - - /*! - * move to next row of results - * @return false if no further results - */ - bool moveToNext(); - - /*! - * move to last row of results - * @return false if no result, true otherwise - */ - bool moveToLast(); - - /* data retrieval */ - - /*! - * @return true if cursor is open and active, false otherwise - */ - bool isOpen() const; - - /*! - * cursor is closed, statement used to open cursor is deleted - * @return false if error on close (was already closed, error occured) - */ - bool close(); - - /*! - * - * @return -1 if cursor is in error, otherwise number of columns in result - */ - int32_t columnCount() const ; - - /*! - * Current statement is closed and discarded (finalised) - * before actual opening occurs - * @param stm statement to open cursor on - * @return true if cursor is successfully opened - */ - bool open(sqlite3_stmt* stm); - -public: - /*! - * Returns the value of the requested column as a String. - * @param columnIndex the zero-based index of the target column. - * @return the value of the column as 32 bit integer - */ - int32_t getInt32(int columnIndex); - - /*! - * Returns the value of the requested column as a String. - * @param columnIndex the zero-based index of the target column. - * @return the value of the column as 64 bit integer - */ - int64_t getInt64(int columnIndex); - - /*! - * Returns the value of the requested column as a String. - * @param columnIndex the zero-based index of the target column. - * @return the value of the column as 64 bit float - */ - double getDouble(int columnIndex); - - /*! - * Returns the value of the requested column as a String. - * @param columnIndex the zero-based index of the target column. - * @return the value of the column as bool - */ - bool getBool(int columnIndex); - - /*! - * Returns the value of the requested column as a String. - * @param columnIndex the zero-based index of the target column. - * @return the value of the column as a string - */ - void getString(int columnIndex, std::string& str); - - /*! - * Returns the value of the requested column as a String. - * data returned must be copied, as it is freed after RetroDb - * is closed or destroyed - * @param columnIndex the zero-based index of the target column. - * @return the value of the column as pointer to raw data - */ - const void* getData(int columnIndex, uint32_t& datSize); - - template - inline void getStringT(int columnIndex, T &str){ - std::string temp; - getString(columnIndex, temp); - str = T(temp); - } -private: - sqlite3_stmt* mStmt; -}; diff --git a/libretroshare/src/util/rsbase64.cc b/libretroshare/src/util/rsbase64.cc deleted file mode 100644 index f62c40cef..000000000 --- a/libretroshare/src/util/rsbase64.cc +++ /dev/null @@ -1,198 +0,0 @@ -/******************************************************************************* - * * - * libretroshare base64 encoding utilities * - * * - * Copyright (C) 2015 Retroshare Team * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "util/rsbase64.h" -#include "util/rsdebug.h" - -#if __cplusplus < 201703L -/* Solve weird undefined reference error with C++ < 17 see: - * https://stackoverflow.com/questions/8016780/undefined-reference-to-static-constexpr-char - */ -/*static*/ decltype(RsBase64::bDict) constexpr RsBase64::bDict; -/*static*/ decltype(RsBase64::uDict) constexpr RsBase64::uDict; -/*static*/ decltype(RsBase64::rDict) constexpr RsBase64::rDict; -/*static*/ decltype(RsBase64::sPad) constexpr RsBase64::sPad; -#endif - -/*static*/ void RsBase64::encode( - rs_view_ptr data, size_t len, std::string& outString, - bool padding, bool urlSafe ) -{ - if(!data || !len) - { - outString.clear(); - return; - } - - const char* sDict = urlSafe ? uDict : bDict; - - // Workaround if input and output are the same buffer. - bool inplace = (outString.data() == reinterpret_cast(data)); - std::string tBuff; - std::string& outStr = inplace ? tBuff : outString; - - auto encSize = encodedSize(len, padding); - outStr.resize(encSize); - char* p = &outStr[0]; - - for (; len >= 3; len -= 3, data += 3) - { - *p++ = sDict[ (data[0] >> 2) & 077 ]; - *p++ = sDict[ - (((data[0] << 4) & 060) | ((data[1] >> 4) & 017)) & 077 ]; - *p++ = sDict[ - (((data[1] << 2) & 074) | ((data[2] >> 6) & 03)) & 077 ]; - *p++ = sDict[ data[2] & 077 ]; - } - if (len == 2) - { - *p++ = sDict[ (data[0] >> 2) & 077 ]; - *p++ = sDict[ - (((data[0] << 4) & 060) | ((data[1] >> 4) & 017)) & 077 ]; - *p++ = sDict[ ((data[1] << 2) & 074) ]; - if(padding) *p++ = sPad; - } - else if (len == 1) - { - *p++ = sDict[ (data[0] >> 2) & 077 ]; - *p++ = sDict[ (data[0] << 4) & 060 ]; - if(padding) { *p++ = sPad; *p++ = sPad; } - } - - if(inplace) outString = tBuff; -} - -/*static*/ std::error_condition RsBase64::decode( - const std::string& encoded, std::vector& decoded ) -{ - size_t decSize; std::error_condition ec; - std::tie(decSize, ec) = decodedSize(encoded); - if(!decSize || ec) return ec; - - size_t encSize = encoded.size(); - decoded.resize(decSize); - - for (size_t i = 0, o = 0; i < encSize; i += 4, o += 3) - { - char input0 = encoded[i + 0]; - char input1 = encoded[i + 1]; - - /* At the end of the string, missing bytes 2 and 3 are considered - * padding '=' */ - char input2 = i + 2 < encoded.size() ? encoded[i + 2] : sPad; - char input3 = i + 3 < encSize ? encoded[i + 3] : sPad; - - // If any unknown characters appear, it's an error. - if(!( isBase64Char(input0) && isBase64Char(input1) && - isBase64Char(input2) && isBase64Char(input3) )) - return std::errc::argument_out_of_domain; - - /* If padding appears anywhere but the last 1 or 2 characters, or if - * it appears but encoded.size() % 4 != 0, it's an error. */ - bool at_end = (i + 4 >= encSize); - if ( (input0 == sPad) || (input1 == sPad) || - ( input2 == sPad && !at_end ) || - ( input2 == sPad && input3 != sPad ) || - ( input3 == sPad && !at_end) ) - return std::errc::illegal_byte_sequence; - - uint32_t b0 = rDict[static_cast(input0)] & 0x3f; - uint32_t b1 = rDict[static_cast(input1)] & 0x3f; - uint32_t b2 = rDict[static_cast(input2)] & 0x3f; - uint32_t b3 = rDict[static_cast(input3)] & 0x3f; - - uint32_t stream = (b0 << 18) | (b1 << 12) | (b2 << 6) | b3; - decoded[o + 0] = (stream >> 16) & 0xFF; - if (input2 != sPad) decoded[o + 1] = (stream >> 8) & 0xFF; - /* If there are any stale bits in this from input1, the text is - * malformed. */ - else if (((stream >> 8) & 0xFF) != 0) - return std::errc::invalid_argument; - - if (input3 != sPad) decoded[o + 2] = (stream >> 0) & 0xFF; - /* If there are any stale bits in this from input2, the text is - * malformed. */ - else if (((stream >> 0) & 0xFF) != 0) - return std::errc::invalid_argument; - } - - return std::error_condition(); -} - -/*static*/ size_t RsBase64::encodedSize(size_t decodedSize, bool padding) -{ - if(!decodedSize) return 0; - - // Thanks https://stackoverflow.com/a/45401395 - if(padding) return ceilDivision(decodedSize, 3) * 4; - return ceilDivision(decodedSize * 8, 6); -} - -/*static*/ std::tuple RsBase64::decodedSize( - const std::string& input ) -{ - const auto success = [](size_t val) - { return std::make_tuple(val, std::error_condition()); }; - - if(input.empty()) return success(0); - - auto mod = input.size() % 4; - if(mod == 1) std::make_tuple(0, std::errc::invalid_argument); - - size_t padded_size = ((input.size() + 3) / 4) * 3; - if (mod >= 2 || (mod == 0 && input[input.size() - 1] == sPad)) - { - /* If the last byte is '=', or the input size % 4 is 2 or 3 (thus - * there are implied '='s), then the actual size is 1-2 bytes - * smaller. */ - if ( mod == 2 || (mod == 0 && input[input.size() - 2] == sPad) ) - { - /* If the second-to-last byte is also '=', or the input - * size % 4 is 2 (implying a second '='), then the actual size - * is 2 bytes smaller. */ - return success(padded_size - 2); - } - else - { - /* Otherwise it's just the last character and the actual size is - * 1 byte smaller. */ - return success(padded_size - 1); - } - } - return success(padded_size); -} - -/*static*/ size_t RsBase64::stripInvalid( - const std::string& in, std::string& out ) -{ - size_t strippedCnt = 0; - auto inSize = in.size(); - out.resize(inSize); - for(size_t i = 0; i < inSize; ++i) - { - if(isBase64Char(in[i])) out[i-strippedCnt] = in[i]; - else ++strippedCnt; - } - out.resize(inSize-strippedCnt); - return strippedCnt; -} diff --git a/libretroshare/src/util/rsbase64.h b/libretroshare/src/util/rsbase64.h deleted file mode 100644 index 819870089..000000000 --- a/libretroshare/src/util/rsbase64.h +++ /dev/null @@ -1,144 +0,0 @@ -/******************************************************************************* - * * - * libretroshare base64 encoding utilities * - * * - * Copyright (C) 2015 Retroshare Team * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include - -#include "util/rsmemory.h" - -/** - * Implement methods to encode e decode to base64 format as per RFC 4648 - * This implementation support also the file name and URL safe base64url format - * @see https://tools.ietf.org/html/rfc4648#section-5 - */ -class RsBase64 -{ -public: - /// Enable base64url by default - static constexpr bool DEFAULT_URL_SAFE = true; - - /// Disable padding by default - static constexpr bool DEFAULT_PADDING = false; - - /** - * @brief Encode arbitrary data to base64 - * @param[in] data pointer to the input data buffer - * @param[in] len lenght of the input buffer - * @param[out] outString storage for the resulting base64 encoded string - * @param[in] padding set to true to enable padding to 32 bits - * @param[in] urlSafe pass true for base64url format, false for base64 format - */ - static void encode( - rs_view_ptr data, size_t len, - std::string& outString, - bool padding = DEFAULT_PADDING, bool urlSafe = DEFAULT_URL_SAFE ); - - /** - * @brief Decode data from a base64 encoded string - * @param[in] encoded encoded string - * @param[out] decoded storage for decoded data - * @return success or error details - */ - static std::error_condition decode( - const std::string& encoded, std::vector& decoded ); - - /** - * Remove invalid characters from base64 encoded string. - * Often when copy and pasting from one progam to another long base64 - * strings, new lines, spaces or other characters end up polluting the - * original text. This function is useful to cleanup the pollution before - * attempting to decode the message. - * @param in input string - * @param out storage for cleaned string. In-place operation in supported so - * the same input string may be passed. - * @return count of stripped invalid characters - */ - static size_t stripInvalid(const std::string& in, std::string& out); - - /** - * Calculate how much bytes are needed to store the base64 encoded version - * of some data. - * @param decodedSize size of the original decoded data - * @param padding true to enable base64 padding - * @return how much bytes would take to store the encoded version - */ - static size_t encodedSize( - size_t decodedSize, bool padding = DEFAULT_PADDING ); - - /** - * @brief Calculate how much space is needed to store the decoded version of - * a base64 encoded string - * @param input encoded string - * @return decoded size, plus error information on failure - */ - static std::tuple decodedSize( - const std::string& input ); - -private: - /// base64 conversion table - static constexpr char bDict[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - /// base64url conversion table - static constexpr char uDict[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - - /// This reverse table supports both base64 and base64url - static constexpr int8_t rDict[256] = { - /* index +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 */ - /* 0 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 16 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 32 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, - /* 48 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, - /* 64 */ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - /* 80 */ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, - /* 96 */ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - /* 112 */ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, - /* 128 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 144 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 160 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 176 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 192 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 208 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 224 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 240 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - }; - - /// base64 padding character - static constexpr char sPad = '='; - - /** Check if given character is valid either for base64 or for base64url - * @param c character to check - * @return true if valid false otherwise - */ - static inline bool isBase64Char(char c) - { return rDict[static_cast(c)] >= 0; } - - /** Perform ceil division without floating point operations */ - static inline size_t ceilDivision(size_t dividend, size_t divisor) - { return (dividend + divisor - 1) / divisor; } -}; diff --git a/libretroshare/src/util/rsdbbind.cc b/libretroshare/src/util/rsdbbind.cc deleted file mode 100644 index db5233ba8..000000000 --- a/libretroshare/src/util/rsdbbind.cc +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsbdbind.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#include "rsdbbind.h" - -RsDoubleBind::RsDoubleBind(double value, int index) - : RetroBind(DOUBLE, index), mValue(value) {} - -RsStringBind::RsStringBind(const std::string& value, int index) - : RetroBind(STRING, index), mValue(value) {} - -RsInt32Bind::RsInt32Bind(int32_t value, int index) - : RetroBind(INT32, index), mValue(value) {} - -RsInt64bind::RsInt64bind(int64_t value, int index) - : RetroBind(INT64, index), mValue(value) {} - -RsBoolBind::RsBoolBind(bool value, int index) - : RetroBind(BOOL, index), mValue(value) {} - -RsBlobBind::RsBlobBind(char* data, uint32_t dataLen, int index) - : RetroBind(BLOB, index), mData(data), mDataLen(dataLen) {} - -bool RsDoubleBind::bind(sqlite3_stmt* const stm) const -{ - return (SQLITE_OK == sqlite3_bind_double(stm, getIndex(), mValue)); -} - -bool RsStringBind::bind(sqlite3_stmt* const stm) const -{ - return (SQLITE_OK == sqlite3_bind_text(stm, getIndex(), mValue.c_str(), mValue.size(), SQLITE_TRANSIENT)); -} - -bool RsInt32Bind::bind(sqlite3_stmt* const stm) const -{ - return (SQLITE_OK == sqlite3_bind_int(stm, getIndex(), mValue)); -} - -bool RsInt64bind::bind(sqlite3_stmt* const stm) const -{ - return (SQLITE_OK == sqlite3_bind_int64(stm, getIndex(), mValue)); -} - -bool RsBoolBind::bind(sqlite3_stmt* const stm) const -{ - return (SQLITE_OK == sqlite3_bind_int(stm, getIndex(), mValue ? 1 : 0)); -} - -bool RsBlobBind::bind(sqlite3_stmt* const stm) const -{ - return (SQLITE_OK == sqlite3_bind_blob(stm, getIndex(), mData, mDataLen, SQLITE_TRANSIENT)); -} - diff --git a/libretroshare/src/util/rsdbbind.h b/libretroshare/src/util/rsdbbind.h deleted file mode 100644 index aa41e5b3e..000000000 --- a/libretroshare/src/util/rsdbbind.h +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsbdbind.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 Christopher Evi-Parker * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSDBBIND_H_ -#define RSDBBIND_H_ - -#include -#include - -#ifdef NO_SQLCIPHER -#include -#else -#include -#endif - -class RetroBind -{ -public: - - enum BindType { BLOB=1, STRING, INT32, INT64, DOUBLE, BOOL } ; - RetroBind(const BindType& type, int index) : mIndex(index), mType(type) {} - - virtual bool bind(sqlite3_stmt* const stm) const = 0; - BindType getType() const { return mType; } - inline int getIndex() const { return mIndex;} - virtual ~RetroBind() {} - -private: - int mIndex; - BindType mType; -}; - -class RsDoubleBind : public RetroBind -{ -public: - RsDoubleBind(double value, int index); - bool bind(sqlite3_stmt* const stm) const; - double mValue; -}; - -class RsStringBind : public RetroBind -{ -public: - RsStringBind(const std::string& value, int index); - bool bind(sqlite3_stmt* const stm) const ; - std::string mValue; -}; - -class RsInt32Bind : public RetroBind -{ -public: - RsInt32Bind(int32_t value, int index); - bool bind(sqlite3_stmt* const stm) const ; - int32_t mValue; -}; - -class RsInt64bind : public RetroBind -{ -public: - RsInt64bind(int64_t value, int index); - bool bind(sqlite3_stmt* const stm) const ; - int64_t mValue; -}; - -class RsBoolBind : public RetroBind -{ -public: - RsBoolBind(bool value, int index); - bool bind(sqlite3_stmt* const stm) const ; - bool mValue; -}; - -class RsBlobBind : public RetroBind -{ -public: - RsBlobBind(char* data, uint32_t dataLen, int index); - bool bind(sqlite3_stmt* const stm) const; - char* mData; - uint32_t mDataLen; -}; - - -#endif /* RSDBBIND_H_ */ diff --git a/libretroshare/src/util/rsdebug.cc b/libretroshare/src/util/rsdebug.cc deleted file mode 100644 index 0a4777ab0..000000000 --- a/libretroshare/src/util/rsdebug.cc +++ /dev/null @@ -1,210 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsdebug.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 by Robert Fernie * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "util/rsdebug.h" - -std::ostream &operator<<(std::ostream& out, const std::error_condition& err) -{ - return out << " error: " << err.value() << " " << err.message() - << " category: " << err.category().name(); -} - -std::string rsErrorNotInCategory(int errNum, const std::string& categoryName) -{ - return "Error message for error: " + std::to_string(errNum) + - " not available in category: " + categoryName; -} - - -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -/// All the following lines are DEPRECATED!! - -#include -#include - -#include "util/rsthreads.h" -#include "util/rsdir.h" -#include "util/rstime.h" - -const int RS_DEBUG_STDERR = 1; /* stuff goes to stderr */ -const int RS_DEBUG_LOGFILE = 2; /* stuff goes to logfile */ -const int RS_DEBUG_LOGCRASH = 3; /* minimal logfile stored after crashes */ -const int RS_DEBUG_LOGC_MAX = 100000; /* max length of crashfile log */ -const int RS_DEBUG_LOGC_MIN_SAVE = 100; /* min length of crashfile log */ - -static RsLog::logLvl defaultLevel = RsLog::Warning; -static FILE *ofd = stderr; - -static int debugMode = RS_DEBUG_STDERR; -static int lineCount = 0; -static std::string crashfile; -static int debugTS = 0; - -static RsMutex logMtx("logMtx"); - -int locked_setDebugFile(const char *fname); - -int setDebugCrashMode(const char *cfile) -{ - RsStackMutex stack(logMtx); /******** LOCKED ****************/ - crashfile = cfile; - /* if the file exists - then we crashed, save it */ - FILE *tmpin = RsDirUtil::rs_fopen(crashfile.c_str(), "r"); - if (tmpin) - { - /* see how long it is */ - fseek(tmpin, 0, SEEK_END); - if (ftell(tmpin) > RS_DEBUG_LOGC_MIN_SAVE) - { - std::string crashfile_save = crashfile + "-save"; - fprintf(stderr, "Detected Old Crash File: %s\n", crashfile.c_str()); - fprintf(stderr, "Copying to: %s\n", crashfile_save.c_str()); - - /* go back to the start */ - fseek(tmpin, 0, SEEK_SET); - - FILE *tmpout = RsDirUtil::rs_fopen(crashfile_save.c_str(), "w"); - int da_size = 10240; - char dataarray[da_size]; /* 10k */ - unsigned int da_read = 0; - - if (!tmpout) - { - fprintf(stderr, "Failed to open CrashSave\n"); - fclose(tmpin); - return -1; - } - while(0 != (da_read = fread(dataarray, 1, da_size, tmpin))) - { - if (da_read != fwrite(dataarray, 1, da_read, tmpout)) - { - fprintf(stderr, "Failed writing to CrashSave\n"); - fclose(tmpout); - fclose(tmpin); - return -1; - } - } - fclose(tmpout); - fclose(tmpin); - } - else - { - fprintf(stderr, "Negligable Old CrashLog, ignoring\n"); - fclose(tmpin); - } - } - - if (0 < locked_setDebugFile(crashfile.c_str())) - { - fprintf(stderr, "Switching To CrashLog Mode!\n"); - debugMode = RS_DEBUG_LOGCRASH; - lineCount = 0; - debugTS = time(NULL); - } - return 1; -} - -int setDebugFile(const char *fname) -{ - RsStackMutex stack(logMtx); /******** LOCKED ****************/ - return locked_setDebugFile(fname); -} - -int locked_setDebugFile(const char *fname) -{ - if (NULL != (ofd = RsDirUtil::rs_fopen(fname, "w"))) - { - fprintf(stderr, "Logging redirected to %s\n", fname); - debugMode = RS_DEBUG_LOGFILE; - return 1; - } - else - { - ofd = stderr; - debugMode = RS_DEBUG_STDERR; - fprintf(stderr, "Logging redirect to %s FAILED\n", fname); - return -1; - } -} - -int setOutputLevel(RsLog::logLvl lvl) -{ - RsStackMutex stack(logMtx); /******** LOCKED ****************/ - return defaultLevel = lvl; -} - -void rslog(const RsLog::logLvl lvl, RsLog::logInfo *info, const std::string &msg) -{ - // skipp when log level is set to 'None' - // NB: when default is set to 'None' the later check will always fail -> no need to check it here - if(info->lvl == RsLog::None) - return; - - bool process = info->lvl == RsLog::Default ? (lvl <= defaultLevel) : lvl <= info->lvl; - if(!process) - return; - - { - RS_STACK_MUTEX(logMtx); - time_t t = time(NULL); // Don't use rstime_t here or ctime break on windows - - if (debugMode == RS_DEBUG_LOGCRASH) - { - if (lineCount > RS_DEBUG_LOGC_MAX) - { - /* restarting logging */ - fprintf(stderr, "Rolling over the CrashLog\n"); - fclose(ofd); - ofd = NULL; - if (0 < locked_setDebugFile(crashfile.c_str())) - { - fprintf(ofd, "Debug CrashLog:"); - fprintf(ofd, " retroShare uptime %ld secs\n", - t-debugTS); - - debugMode = RS_DEBUG_LOGCRASH; - lineCount = 0; - } - else - { - fprintf(stderr, "Rollover Failed!\n"); - } - } - } - - std::string timestr = ctime(&t); - std::string timestr2 = timestr.substr(0,timestr.length()-1); - /* remove the endl */ - fprintf(ofd, "(%s Z: %s, lvl: %u): %s \n", - timestr2.c_str(), info->name.c_str(), (unsigned int)info->lvl, msg.c_str()); - fflush(ofd); - - fprintf(stdout, "(%s Z: %s, lvl: %u): %s \n", - timestr2.c_str(), info->name.c_str(), (unsigned int)info->lvl, msg.c_str()); - lineCount++; - } -} diff --git a/libretroshare/src/util/rsdebug.h b/libretroshare/src/util/rsdebug.h deleted file mode 100644 index 6409e9492..000000000 --- a/libretroshare/src/util/rsdebug.h +++ /dev/null @@ -1,314 +0,0 @@ -/******************************************************************************* - * RetroShare debugging utilities * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2019-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#ifdef __ANDROID__ -# include -#else // def __ANDROID__ -# include -# include -# include -#endif // def __ANDROID__ - - -#include "util/rsjson.h" - - -#ifdef __ANDROID__ -enum class RsLoggerCategories -{ - DEBUG = ANDROID_LOG_DEBUG, - INFO = ANDROID_LOG_INFO, - WARNING = ANDROID_LOG_WARN, - ERROR = ANDROID_LOG_ERROR, - FATAL = ANDROID_LOG_FATAL -}; -#else // def __ANDROID__ -enum class RsLoggerCategories -{ - DEBUG = 'D', - INFO = 'I', - WARNING = 'W', - ERROR = 'E', - FATAL = 'F' -}; -#endif // def __ANDROID__ - - -/** Stream helper for std::error_condition */ -std::ostream &operator<<(std::ostream& out, const std::error_condition& err); - -/** Provide unkown error message for all error categories to avoid duplicating - * the message around */ -std::string rsErrorNotInCategory(int errNum, const std::string& categoryName); - - -template -struct t_RsLogger : std::ostringstream -{ - t_RsLogger() { setPrefix(); } - ~t_RsLogger() { flush(); } - - /** Offer variadic style, this doesn't supports things like std::endl as - * paramether but when used toghether with conditional debugging macros - * reduces binary size as paramethers of suppressed calls are not evaluated - * and literally disappear in preprocessing fase @see RsDbg */ - template - explicit inline t_RsLogger(Args&&... args) - { - setPrefix(); - - /* Combine initializer list and comma operator so the compiler unpack - * template arguments and feed our own stream without recursion - * see https://stackoverflow.com/a/27375675 */ - using expander = int[]; - (void) expander {0, (void((*this) << std::forward(args)), 0)...}; - } - - /** Dump buffer stream to log */ - void flush() - { -#ifdef __ANDROID__ - __android_log_write( - static_cast(CATEGORY), - "RetroShare", str().c_str() ); -#else // def __ANDROID__ - (*this) << std::endl; - std::cerr << str(); -#endif // def __ANDROID__ - str() = ""; - } - -private: -#ifdef __ANDROID__ - inline void setPrefix() {} -#else // def __ANDROID__ - void setPrefix() - { - using namespace std::chrono; - const auto now = system_clock::now(); - const auto sec = time_point_cast(now); - const auto msec = duration_cast(now - sec); - (*this) << static_cast(CATEGORY) << " " - << sec.time_since_epoch().count() << "." - << std::setfill('0') << std::setw(3) << msec.count() << " "; - } -#endif // def __ANDROID__ -}; - - -/** - * Comfortable debug message logging, supports both variadic style and chaining - * style like std::cerr. - * Can be easly and selectively disabled at compile time. - * To reduce generated binary size and performance impact when debugging is - * disabled without too many \#ifdef around the code combining the variadic - * style with the leveled debugging macros is the way to go. - * - * To selectively debug your file you just need to include the header of desired - * debugging level (0 to 4) -@code{.cpp} -#include "util/rsdebuglevel2.h" -@endcode - * Then where you want to print debug messages use -@code{.cpp} -RS_DBG0("Hello 0 ", "my debug ", my_variable) << " message " << variable2; -RS_DBG1("Hello 1 ", "my debug ", my_variable) << " message " << variable2; -RS_DBG2("Hello 2 ", "my debug ", my_variable) << " message " << variable2; -RS_DBG3("Hello 3 ", "my debug ", my_variable) << " message " << variable2; -RS_DBG4("Hello 4 ", "my debug ", my_variable) << " message " << variable2; -@endcode - * To change the debugging level just include a different level header like - * `util/rsdebuglevel1.h`, debug messages with lower or equal level then the - * included header will be printed, the others will not. - * Remember then on messages with debug level higher then the included the - * paramethers you pass as macro arguments (variadic style) will disappear in - * the preprocessing phase, so their evaluation will not be included in the - * final binary and not executed at runtime, instead the paramether passed with - * `<<` (chaining style) will be in the compiled binary and evaluated at runtime - * even if are not printed, due to how C++ is made it is not possible to avoid - * this, so we suggest to use variadic style for debug messages. - */ -using RsDbg = t_RsLogger; -#define RS_DBG(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -/** - * Comfortable log information reporting helper, supports chaining like - * std::cerr. - * To report an information message you can just write: -@code{.cpp} -RsInfo() << __PRETTY_FUNCTION__ << "My information message" << std::cerr; -@endcode - */ -using RsInfo = t_RsLogger; -#define RS_INFO(...) RsInfo(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -/// Similar to @see RsInfo but for warning messages -using RsWarn = t_RsLogger; -#define RS_WARN(...) RsWarn(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -/// Similar to @see RsInfo but for error messages -using RsErr = t_RsLogger; -#define RS_ERR(...) RsErr(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -/** Similar to @see RsInfo but for fatal errors (the ones which cause RetroShare - * to terminate) messages */ -using RsFatal = t_RsLogger; -#define RS_FATAL(...) RsFatal(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - - -/** - * Keeps compatible syntax with RsDbg but explicitely do nothing in a way that - * any modern compiler should be smart enough to optimize out all the function - * calls. - */ -struct RsNoDbg -{ - inline RsNoDbg() = default; - template inline explicit RsNoDbg(Args...) {} - - /** This match most of the types, but might be not enough for templated - * types */ - template - inline RsNoDbg& operator<<(const T&) { return *this; } - - /// needed for manipulators and things like std::endl - inline RsNoDbg& operator<<(std::ostream& (*/*pf*/)(std::ostream&)) - { return *this; } - - /** Do nothing. Just for code compatibility with other logging classes */ - inline void flush() {} -}; - - - -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -/// All the following lines are DEPRECATED!! - -#include "util/rsdeprecate.h" - -/** - * Concatenate preprocessor tokens A and B without expanding macro definitions - * (however, if invoked from a macro, macro arguments are expanded). - */ -#define RS_CONCAT_MACRO_NX(A, B) A ## B - -/// Concatenate preprocessor tokens A and B after macro-expanding them. -#define RS_CONCAT_MACRO(A, B) RS_CONCAT_MACRO_NX(A, B) - -/** - * Set local context debug level. - * Avoid copy pasting boilerplate code around @see RsDbg for usage details - */ -#define RS_SET_CONTEXT_DEBUG_LEVEL(level) \ - RS_CONCAT_MACRO(RS_SET_CONTEXT_DEBUG_LEVEL, level) - -// A bunch of boilerplate, but just in one place -#define RS_SET_CONTEXT_DEBUG_LEVEL0 \ - using Dbg1 RS_DEPRECATED_FOR(RS_DBG1) = RsNoDbg; \ - using Dbg2 RS_DEPRECATED_FOR(RS_DBG2) = RsNoDbg; \ - using Dbg3 RS_DEPRECATED_FOR(RS_DBG3) = RsNoDbg; \ - using Dbg4 RS_DEPRECATED_FOR(RS_DBG4) = RsNoDbg; -#define RS_SET_CONTEXT_DEBUG_LEVEL1 \ - using Dbg1 RS_DEPRECATED_FOR(RS_DBG1) = RsDbg; \ - using Dbg2 RS_DEPRECATED_FOR(RS_DBG2) = RsNoDbg; \ - using Dbg3 RS_DEPRECATED_FOR(RS_DBG3) = RsNoDbg; \ - using Dbg4 RS_DEPRECATED_FOR(RS_DBG4) = RsNoDbg; -#define RS_SET_CONTEXT_DEBUG_LEVEL2 \ - using Dbg1 RS_DEPRECATED_FOR(RS_DBG1) = RsDbg; \ - using Dbg2 RS_DEPRECATED_FOR(RS_DBG2) = RsDbg; \ - using Dbg3 RS_DEPRECATED_FOR(RS_DBG3) = RsNoDbg; \ - using Dbg4 RS_DEPRECATED_FOR(RS_DBG4) = RsNoDbg; -#define RS_SET_CONTEXT_DEBUG_LEVEL3 \ - using Dbg1 RS_DEPRECATED_FOR(RS_DBG1) = RsDbg; \ - using Dbg2 RS_DEPRECATED_FOR(RS_DBG2) = RsDbg; \ - using Dbg3 RS_DEPRECATED_FOR(RS_DBG3) = RsDbg; \ - using Dbg4 RS_DEPRECATED_FOR(RS_DBG4) = RsNoDbg; -#define RS_SET_CONTEXT_DEBUG_LEVEL4 \ - using Dbg1 RS_DEPRECATED_FOR(RS_DBG1) = RsDbg; \ - using Dbg2 RS_DEPRECATED_FOR(RS_DBG2) = RsDbg; \ - using Dbg3 RS_DEPRECATED_FOR(RS_DBG3) = RsDbg; \ - using Dbg4 RS_DEPRECATED_FOR(RS_DBG4) = RsDbg; - -namespace RsLog { - enum RS_DEPRECATED_FOR("RsErr, RsDbg, RsNoDbg") logLvl { - None = -1, - Default = 0, - Alert = 1, - Error = 3, - Warning = 5, - Debug_Alert = 6, - Debug_Basic = 8, - Debug_All = 10 - }; - - // this struct must be provided by the caller (to rslog()) - struct RS_DEPRECATED_FOR("RsErr, RsDbg, RsNoDbg") logInfo { - // module specific log lvl - logLvl lvl; - // module name (displayed in log) - const std::string name; - }; -} - -RS_DEPRECATED_FOR("RsErr, RsDbg, RsNoDbg") -int setDebugCrashMode(const char *cfile); - -RS_DEPRECATED_FOR("RsErr, RsDbg, RsNoDbg") -int setDebugFile(const char *fname); - -RS_DEPRECATED_FOR("RsErr, RsDbg, RsNoDbg") -int setOutputLevel(RsLog::logLvl lvl); - -RS_DEPRECATED_FOR("RsErr, RsDbg, RsNoDbg") -void rslog(const RsLog::logLvl lvl, RsLog::logInfo *info, const std::string &msg); - - -/* - * retaining old #DEFINES and functions for backward compatibility. - */ - -#define RSL_NONE RsLog::None -#define RSL_ALERT RsLog::Alert -#define RSL_ERROR RsLog::Error -#define RSL_WARNING RsLog::Warning -#define RSL_DEBUG_ALERT RsLog::Debug_Alert -#define RSL_DEBUG_BASIC RsLog::Debug_Basic -#define RSL_DEBUG_ALL RsLog::Debug_Basic - -//int pqioutput(unsigned int lvl, int zone, std::string msg); -#define pqioutput rslog - -#define PQL_NONE RSL_NONE -#define PQL_ALERT RSL_ALERT -#define PQL_ERROR RSL_ERROR -#define PQL_WARNING RSL_WARNING -#define PQL_DEBUG_ALERT RSL_DEBUG_ALERT -#define PQL_DEBUG_BASIC RSL_DEBUG_BASIC -#define PQL_DEBUG_ALL RSL_DEBUG_ALL diff --git a/libretroshare/src/util/rsdebuglevel0.h b/libretroshare/src/util/rsdebuglevel0.h deleted file mode 100644 index 5c68ec0be..000000000 --- a/libretroshare/src/util/rsdebuglevel0.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * RetroShare debugging level * - * * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ - -// #pragma once // This is commented out on purpose! - -#include - -#undef RS_DEBUG_LEVEL -#define RS_DEBUG_LEVEL 0 - -#undef RS_DBG0 -#define RS_DBG0(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG1 -#define RS_DBG1(...) RsNoDbg("") - -#undef RS_DBG2 -#define RS_DBG2(...) RsNoDbg("") - -#undef RS_DBG3 -#define RS_DBG3(...) RsNoDbg("") - -#undef RS_DBG4 -#define RS_DBG4(...) RsNoDbg("") diff --git a/libretroshare/src/util/rsdebuglevel1.h b/libretroshare/src/util/rsdebuglevel1.h deleted file mode 100644 index 7e968e402..000000000 --- a/libretroshare/src/util/rsdebuglevel1.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * RetroShare debugging level * - * * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ - -// #pragma once // This is commented out on purpose! - -#include - -#undef RS_DEBUG_LEVEL -#define RS_DEBUG_LEVEL 1 - -#undef RS_DBG0 -#define RS_DBG0(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG1 -#define RS_DBG1(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG2 -#define RS_DBG2(...) RsNoDbg() - -#undef RS_DBG3 -#define RS_DBG3(...) RsNoDbg() - -#undef RS_DBG4 -#define RS_DBG4(...) RsNoDbg() diff --git a/libretroshare/src/util/rsdebuglevel2.h b/libretroshare/src/util/rsdebuglevel2.h deleted file mode 100644 index 2cbf1a224..000000000 --- a/libretroshare/src/util/rsdebuglevel2.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * RetroShare debugging level * - * * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ - -// #pragma once // This is commented out on purpose! - -#include - -#undef RS_DEBUG_LEVEL -#define RS_DEBUG_LEVEL 2 - -#undef RS_DBG0 -#define RS_DBG0(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG1 -#define RS_DBG1(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG2 -#define RS_DBG2(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG3 -#define RS_DBG3(...) RsNoDbg() - -#undef RS_DBG4 -#define RS_DBG4(...) RsNoDbg() diff --git a/libretroshare/src/util/rsdebuglevel3.h b/libretroshare/src/util/rsdebuglevel3.h deleted file mode 100644 index 53bcbfe9f..000000000 --- a/libretroshare/src/util/rsdebuglevel3.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * RetroShare debugging level * - * * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ - -// #pragma once // This is commented out on purpose! - -#include - -#undef RS_DEBUG_LEVEL -#define RS_DEBUG_LEVEL 3 - -#undef RS_DBG0 -#define RS_DBG0(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG1 -#define RS_DBG1(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG2 -#define RS_DBG2(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG3 -#define RS_DBG3(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG4 -#define RS_DBG4(...) RsNoDbg() diff --git a/libretroshare/src/util/rsdebuglevel4.h b/libretroshare/src/util/rsdebuglevel4.h deleted file mode 100644 index f8697cad8..000000000 --- a/libretroshare/src/util/rsdebuglevel4.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * RetroShare debugging level * - * * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ - -// #pragma once // This is commented out on purpose! - -#include - -#undef RS_DEBUG_LEVEL -#define RS_DEBUG_LEVEL 4 - -#undef RS_DBG0 -#define RS_DBG0(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG1 -#define RS_DBG1(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG2 -#define RS_DBG2(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG3 -#define RS_DBG3(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG4 -#define RS_DBG4(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) diff --git a/libretroshare/src/util/rsdeprecate.h b/libretroshare/src/util/rsdeprecate.h deleted file mode 100644 index 560f91c44..000000000 --- a/libretroshare/src/util/rsdeprecate.h +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsdebug.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) -# define RS_DEPRECATED __attribute__((__deprecated__)) -#elif defined(_MSC_VER) && (_MSC_VER >= 1300) -# define RS_DEPRECATED __declspec(deprecated) -#else -# define RS_DEPRECATED -#endif - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) -# define RS_DEPRECATED_FOR(f) __attribute__((__deprecated__("Use '" #f "' instead"))) -#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320) -# define RS_DEPRECATED_FOR(f) __declspec(deprecated("is deprecated. Use '" #f "' instead")) -#else -# define RS_DEPRECATED_FOR(f) RS_DEPRECATED -#endif diff --git a/libretroshare/src/util/rsdir.cc b/libretroshare/src/util/rsdir.cc deleted file mode 100644 index 8556b8198..000000000 --- a/libretroshare/src/util/rsdir.cc +++ /dev/null @@ -1,1372 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsdir.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2007 Robert Fernie * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ - -// Includes for directory creation. -#include -#include -#include -#include - -#include "util/rsdir.h" -#include "util/rsstring.h" -#include "util/rsrandom.h" -#include "util/rstime.h" -#include "util/rsmemory.h" -#include "util/folderiterator.h" -#include "retroshare/rstypes.h" -#include "retroshare/rsnotify.h" -#include "rsthreads.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#if defined(WIN32) || defined(__CYGWIN__) -#include "util/rsstring.h" -#include "wtypes.h" -#include -#else -#include -#endif - -#ifndef __GLIBC__ -#define canonicalize_file_name(p) realpath(p, NULL) -#endif - -/**** - * #define RSDIR_DEBUG 1 - ****/ - -std::string RsDirUtil::getTopDir(const std::string& dir) -{ - std::string top; - - /* find the subdir: [/][dir1.../][/] - */ - int i,j; - int len = dir.length(); - for(j = len - 1; (j > 0) && (dir[j] == '/'); j--) ; - for(i = j; (i > 0) && (dir[i] != '/'); i--) ; - - if (dir[i] == '/') - i++; - - for(; i <= j; i++) - { - top += dir[i]; - } - - return top; -} - -const char *RsDirUtil::scanf_string_for_uint(int bytes) -{ - const char *strgs[3] = { "%u","%lu","%llu" } ; - - //std::cerr << "RsDirUtil::scanf_string_for_uint(): returning for bytes=" << bytes << std::endl; - - if(sizeof(unsigned int) == bytes) - return strgs[0] ; - if(sizeof(long unsigned int) == bytes) - return strgs[1] ; - if(sizeof(long long unsigned int) == bytes) - return strgs[2] ; - - std::cerr << "RsDirUtil::scanf_string_for_uint(): no corresponding scan string for "<< bytes << " bytes. This will probably cause inconsistencies." << std::endl; - return strgs[0] ; -} - -bool RsDirUtil::splitDirFromFile(const std::string& full_path,std::string& dir, std::string& file) -{ - int i = full_path.rfind('/', full_path.size()-1); - - if(i == full_path.size()-1) // '/' not found! - { - file = full_path ; - dir = "." ; - return true ; - } - - dir.assign(full_path,0,i+1) ; - file.assign(full_path,i+1,full_path.size()) ; - - return true ; -} - -void RsDirUtil::removeTopDir(const std::string& dir, std::string& path) -{ - path.clear(); - - /* remove the subdir: [/][dir1.../][/] - */ - int j = dir.find_last_not_of('/'); - int i = dir.rfind('/', j); - - /* remove any more slashes */ - if (i > 0) - { - i = dir.find_last_not_of('/', i); - } - - if (i > 0) - { - path.assign(dir, 0, i + 1); - } -} - -std::string RsDirUtil::getRootDir(const std::string& dir) -{ - std::string root; - - /* find the subdir: [/]root[/...] - */ - int i,j; - int len = dir.length(); - for(i = 0; (i < len) && (dir[i] == '/'); i++) ; - for(j = i; (j < len) && (dir[j] != '/'); j++) ; - if (i == j) - return root; /* empty */ - for(; i < j; i++) - { - root += dir[i]; - } - return root; -} - -std::string RsDirUtil::removeRootDir(const std::string& path) -{ - unsigned int i, j; - unsigned int len = path.length(); - std::string output; - - /* chew leading '/'s */ - for(i = 0; (i < len) && (path[i] == '/'); i++) ; - if (i == len) - return output; /* empty string */ - - for(j = i; (j < len) && (path[j] != '/'); j++) ; /* run to next '/' */ - for(; (j < len) && (path[j] == '/'); j++) ; /* chew leading '/'s */ - - for(; j < len; j++) - { - output += path[j]; - } - - return output; -} - -std::string RsDirUtil::removeRootDirs(const std::string& path, const std::string& root) -{ - /* too tired */ - std::string notroot; - - unsigned int i = 0, j = 0; - - /* catch empty data */ - if ((root.length() < 1) || (path.length() < 1)) - return notroot; - - if ((path[0] == '/') && (root[0] != '/')) - { - i++; - } - - for(; (i < path.length()) && (j < root.length()) && (path[i] == root[j]); i++, j++) ; - - /* should have consumed root. */ - if (j == root.length()) - { - //std::cerr << "matched root!" << std::endl; - } - else - { - //std::cerr << "failed i: " << i << ", j: " << j << std::endl; - //std::cerr << "root: " << root << " path: " << path << std::endl; - return notroot; - } - - if (path[i] == '/') - { - i++; - } - - for(; i < path.length(); i++) - { - notroot += path[i]; - } - - //std::cerr << "Found NotRoot: " << notroot << std::endl; - - return notroot; -} - - - -int RsDirUtil::breakupDirList(const std::string& path, - std::list &subdirs) -{ - int start = 0; - unsigned int i; - for(i = 0; i < path.length(); i++) - { - if (path[i] == '/') - { - if (i - start > 0) - { - subdirs.push_back(path.substr(start, i-start)); - } - start = i+1; - } - } - // get the final one. - if (i - start > 0) - { - subdirs.push_back(path.substr(start, i-start)); - } - return 1; -} - -/**** Copied and Tweaked from ftcontroller ***/ -bool RsDirUtil::fileExists(const std::string& filename) -{ -#ifdef WINDOWS_SYS - std::wstring wfilename; - librs::util::ConvertUtf8ToUtf16(filename, wfilename); - return ( _waccess( wfilename.c_str(), F_OK ) != -1 ); -#else - return ( access( filename.c_str(), F_OK ) != -1 ); -#endif -} - -bool RsDirUtil::moveFile(const std::string& source,const std::string& dest) -{ - Dbg3() << __PRETTY_FUNCTION__<< " source: " << source - << " dest: " << dest << std::endl; - - std::string dest_dir ; - std::string dest_file ; - - splitDirFromFile(dest, dest_dir, dest_file); - - if(!checkDirectory(dest_dir)) - { - if(!std::filesystem::create_directories(dest_dir)) - { - RsErr() << __PRETTY_FUNCTION__ << " failure creating directory: " - << dest_dir << std::endl; - return false; - } - } - - // First try a rename - if(renameFile(source,dest)) - { - Dbg3() << __PRETTY_FUNCTION__ << " plain rename worked" << std::endl; - return true; - } - - /* If not, try to copy. The src and dest probably belong to different file - * systems */ - if(!copyFile(source,dest)) - { - RsErr() << __PRETTY_FUNCTION__ << " failure copying file" << std::endl; - return false; - } - - // delete the original - if(!removeFile(source)) - { - RsErr() << __PRETTY_FUNCTION__ << " failure deleting original file" - << std::endl; - return false; - } - - return true; -} - -bool RsDirUtil::removeFile(const std::string& filename) -{ -#ifdef CONTROL_DEBUG - std::cerr << "deleting original file " << source << std::endl ; -#endif - -#ifdef WINDOWS_SYS - std::wstring filenameW; - librs::util::ConvertUtf8ToUtf16(filename,filenameW); - - if(0 != DeleteFileW(filenameW.c_str())) -#else - if(0 == remove(filename.c_str())) -#endif - return true ; - else - { - std::cerr << "(EE) File erase error while removing file " << filename << ". Read-only file system ?" << std::endl; - return false ; - } -} - -/**** Copied and Tweaked from ftcontroller ***/ -bool RsDirUtil::copyFile(const std::string& source,const std::string& dest) -{ -#ifdef WINDOWS_SYS - std::wstring sourceW; - std::wstring destW; - librs::util::ConvertUtf8ToUtf16(source,sourceW); - librs::util::ConvertUtf8ToUtf16(dest,destW); - - return (CopyFileW(sourceW.c_str(), destW.c_str(), FALSE) != 0); - -#else - FILE *in = fopen64(source.c_str(),"rb") ; - - if(in == NULL) - { - return false ; - } - - FILE *out = fopen64(dest.c_str(),"wb") ; - - if(out == NULL) - { - fclose (in); - return false ; - } - - size_t s=0; - size_t T=0; - - static const int BUFF_SIZE = 10485760 ; // 10 MB buffer to speed things up. - RsTemporaryMemory buffer(BUFF_SIZE) ; - - if(!buffer) - { - fclose(in) ; - fclose(out) ; - return false ; - } - - bool bRet = true; - - while( (s = fread(buffer,1,BUFF_SIZE,in)) > 0) - { - size_t t = fwrite(buffer,1,s,out) ; - T += t ; - - if(t != s) - { - bRet = false ; - break; - } - } - - fclose(in) ; - fclose(out) ; - - return bRet ; - -#endif - -} - - -bool RsDirUtil::checkFile(const std::string& filename,uint64_t& file_size,bool disallow_empty_file) -{ - int val; - mode_t st_mode; -#ifdef WINDOWS_SYS - std::wstring wfilename; - librs::util::ConvertUtf8ToUtf16(filename, wfilename); - struct _stat buf; - val = _wstat(wfilename.c_str(), &buf); - st_mode = buf.st_mode; -#else - struct stat64 buf; - val = stat64(filename.c_str(), &buf); - st_mode = buf.st_mode; -#endif - if (val == -1) - { -#ifdef RSDIR_DEBUG - std::cerr << "RsDirUtil::checkFile() "; - std::cerr << filename << " doesn't exist" << std::endl; -#endif - return false; - } - else if (!S_ISREG(st_mode)) - { - // Some other type - error. -#ifdef RSDIR_DEBUG - std::cerr << "RsDirUtil::checkFile() "; - std::cerr << filename << " is not a Regular File" << std::endl; -#endif - return false; - } - - file_size = buf.st_size ; - - if(disallow_empty_file && buf.st_size == 0) - return false ; - - return true; -} - - -bool RsDirUtil::checkDirectory(const std::string& dir) -{ - int val; - mode_t st_mode; -#ifdef WINDOWS_SYS - std::wstring wdir; - librs::util::ConvertUtf8ToUtf16(dir, wdir); - struct _stat buf; - val = _wstat(wdir.c_str(), &buf); - st_mode = buf.st_mode; -#else - struct stat buf; - val = stat(dir.c_str(), &buf); - st_mode = buf.st_mode; -#endif - if (val == -1) - { -#ifdef RSDIR_DEBUG - std::cerr << "RsDirUtil::checkDirectory() "; - std::cerr << dir << " doesn't exist" << std::endl; -#endif - return false; - } - else if (!S_ISDIR(st_mode)) - { - // Some other type - error. -#ifdef RSDIR_DEBUG - std::cerr << "RsDirUtil::checkDirectory() "; - std::cerr << dir << " is not Directory" << std::endl; -#endif - return false; - } - return true; -} - - -bool RsDirUtil::checkCreateDirectory(const std::string& dir) -{ - Dbg3() << __PRETTY_FUNCTION__ << " " << dir << std::endl; - -#ifdef WINDOWS_SYS - std::wstring wdir; - librs::util::ConvertUtf8ToUtf16(dir, wdir); - _WDIR *direc = _wopendir(wdir.c_str()); - if (!direc) -#else - DIR *direc = opendir(dir.c_str()); - if (!direc) -#endif - { - // directory don't exist. create. -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // UNIX - if (-1 == mkdir(dir.c_str(), 0777)) -#else // WIN - if (-1 == _wmkdir(wdir.c_str())) -#endif -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - { -#ifdef RSDIR_DEBUG - std::cerr << "check_create_directory() Fatal Error et oui--"; - std::cerr < &keepFiles) -{ - for(librs::util::FolderIterator it(cleandir,false);it.isValid();it.next()) - if(it.file_type() == librs::util::FolderIterator::TYPE_FILE && (keepFiles.end() == std::find(keepFiles.begin(), keepFiles.end(), it.file_name()))) - remove( (cleandir + "/" + it.file_name()).c_str() ) ; - - return true; -} - -/* slightly nicer helper function */ -bool RsDirUtil::hashFile(const std::string& filepath, - std::string &name, RsFileHash &hash, uint64_t &size) -{ - if (getFileHash(filepath, hash, size)) - { - /* extract file name */ - name = RsDirUtil::getTopDir(filepath); - return true; - } - return false; -} - - -#include -#include - -/* Function to hash, and get details of a file */ -bool RsDirUtil::getFileHash(const std::string& filepath, RsFileHash &hash, uint64_t &size, RsThread *thread /*= NULL*/) -{ - FILE *fd; - - if (NULL == (fd = RsDirUtil::rs_fopen(filepath.c_str(), "rb"))) - return false; - - int len; - SHA_CTX *sha_ctx = new SHA_CTX; - unsigned char sha_buf[SHA_DIGEST_LENGTH]; - - static const uint32_t HASH_BUFFER_SIZE = 1024*1024*10 ;// allocate a 10MB buffer. Too small a buffer will cause multiple HD hits and slow down the hashing process. - RsTemporaryMemory gblBuf(HASH_BUFFER_SIZE) ; - //unsigned char gblBuf[512]; - - /* determine size */ - fseeko64(fd, 0, SEEK_END); - size = ftello64(fd); - fseeko64(fd, 0, SEEK_SET); - - /* check if thread is running */ - bool isRunning = thread ? thread->isRunning() : true; - int runningCheckCount = 0; - - SHA1_Init(sha_ctx); - while(isRunning && (len = fread(gblBuf,1, HASH_BUFFER_SIZE, fd)) > 0) - { - SHA1_Update(sha_ctx, gblBuf, len); - - if (thread && ++runningCheckCount > (10 * 1024)) { - /* check all 50MB if thread is running */ - isRunning = thread->isRunning(); - runningCheckCount = 0; - } - } - - /* Thread has ended */ - if (isRunning == false) - { - delete sha_ctx; - fclose(fd); - return false; - } - - /* reading failed for some reason */ - if (ferror(fd)) - { - delete sha_ctx; - fclose(fd); - return false; - } - - SHA1_Final(&sha_buf[0], sha_ctx); - - hash = Sha1CheckSum(sha_buf); - - delete sha_ctx; - fclose(fd); - return true; -} - -/* Function to hash, and get details of a file */ -Sha1CheckSum RsDirUtil::sha1sum(const unsigned char *data, uint32_t size) -{ - SHA_CTX sha_ctx ; - - if(SHA_DIGEST_LENGTH != 20) - throw std::runtime_error("Warning: can't compute Sha1Sum with sum size != 20") ; - - SHA1_Init(&sha_ctx); - while(size > 512) - { - SHA1_Update(&sha_ctx, data, 512); - data = &data[512] ; - size -= 512 ; - } - SHA1_Update(&sha_ctx, data, size); - - unsigned char sha_buf[SHA_DIGEST_LENGTH]; - SHA1_Final(&sha_buf[0], &sha_ctx); - - return Sha1CheckSum(sha_buf) ; -} - -Sha256CheckSum RsDirUtil::sha256sum(const unsigned char *data, uint32_t size) -{ - SHA256_CTX sha_ctx ; - - if(SHA256_DIGEST_LENGTH != 32) - throw std::runtime_error("Warning: can't compute Sha2561Sum with sum size != 32") ; - - SHA256_Init(&sha_ctx); - while(size > 512) - { - SHA256_Update(&sha_ctx, data, 512); - data = &data[512] ; - size -= 512 ; - } - SHA256_Update(&sha_ctx, data, size); - - unsigned char sha_buf[SHA256_DIGEST_LENGTH]; - SHA256_Final(&sha_buf[0], &sha_ctx); - - return Sha256CheckSum(sha_buf) ; -} -bool RsDirUtil::saveStringToFile(const std::string &file, const std::string &str) -{ - std::ofstream out(file.c_str(), std::ios_base::out | std::ios_base::binary); - if(!out.is_open()) - { - std::cerr << "RsDirUtil::saveStringToFile() ERROR: can't open file " << file << std::endl; - return false; - } - out << str; - return true; -} - -bool RsDirUtil::loadStringFromFile(const std::string &file, std::string &str) -{ - std::ifstream in(file.c_str(), std::ios_base::in | std::ios_base::binary); - if(!in.is_open()) - { - std::cerr << "RsDirUtil::loadStringFromFile() ERROR: can't open file " << file << std::endl; - return false; - } - std::stringstream buffer; - buffer << in.rdbuf(); - str = buffer.str(); - return true; -} - -bool RsDirUtil::renameFile(const std::string& from, const std::string& to) -{ - int loops = 0; - -#ifdef WINDOWS_SYS - std::wstring f; - librs::util::ConvertUtf8ToUtf16(from, f); - std::wstring t; - librs::util::ConvertUtf8ToUtf16(to, t); - - while (!MoveFileEx(f.c_str(), t.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) -#else - std::string f(from),t(to) ; - - while (rename(from.c_str(), to.c_str()) < 0) -#endif - { -#ifdef WIN32 - if (GetLastError() != ERROR_ACCESS_DENIED) -#else - if (errno != EACCES) -#endif - /* set errno? */ - return false ; - rstime::rs_usleep(100 * 1000); // 100 msec - - if (loops >= 30) - return false ; - - loops++; - } - - return true ; -} - -#ifdef UNUSED_CODE -// not used -bool RsDirUtil::createBackup (const std::string& sFilename, unsigned int nCount) -{ -#ifdef WINDOWS_SYS - if (GetFileAttributesA (sFilename.c_str ()) == -1) { - // file doesn't exist - return true; - } - - // search last backup - int nLast; - for (nLast = nCount; nLast >= 1; nLast--) { - std::ostringstream sStream; // please do not use std::ostringstream - sStream << sFilename << nLast << ".bak"; - - if (GetFileAttributesA (sStream.str ().c_str ()) != -1) { - break; - } - } - - // delete max backup - if (nLast == nCount) { - std::ostringstream sStream; // please do not use std::ostringstream - sStream << sFilename << nCount << ".bak"; - if (DeleteFileA (sStream.str ().c_str ()) == FALSE) { - getPqiNotify()->AddSysMessage (0, RS_SYS_WARNING, "File delete error", "Error while deleting file " + sStream.str ()); - return false; - } - nLast--; - } - - // rename backups - for (int nIndex = nLast; nIndex >= 1; nIndex--) { - std::ostringstream sStream; // please do not use std::ostringstream - sStream << sFilename << nIndex << ".bak"; - std::ostringstream sStream1; // please do not use std::ostringstream - sStream1 << sFilename << nIndex + 1 << ".bak"; - - if (renameFile (sStream.str (), sStream1.str ()) == false) { - getPqiNotify()->AddSysMessage (0, RS_SYS_WARNING, "File rename error", "Error while renaming file " + sStream.str () + " to " + sStream1.str ()); - return false; - } - } - - // copy backup - std::ostringstream sStream; // please do not use std::ostringstream - sStream << sFilename << 1 << ".bak"; - if (CopyFileA (sFilename.c_str (), sStream.str ().c_str (), FALSE) == FALSE) { - getPqiNotify()->AddSysMessage (0, RS_SYS_WARNING, "File rename error", "Error while renaming file " + sFilename + " to " + sStream.str ()); - return false; - } -#else - /* remove unused parameter warnings */ - (void) sFilename; - (void) nCount; -#endif - return true; -} -#endif - -FILE *RsDirUtil::rs_fopen(const char* filename, const char* mode) -{ -#ifdef WINDOWS_SYS - std::wstring wfilename; - librs::util::ConvertUtf8ToUtf16(filename, wfilename); - std::wstring wmode; - librs::util::ConvertUtf8ToUtf16(mode, wmode); - - return _wfopen(wfilename.c_str(), wmode.c_str()); -#else - return fopen64(filename, mode); -#endif -} - -std::string RsDirUtil::convertPathToUnix(std::string path) -{ - for (unsigned int i = 0; i < path.length(); i++) - { - if (path[i] == '\\') - path[i] = '/'; - } - return path; -} - -std::string RsDirUtil::makePath(const std::string &path1, const std::string &path2) -{ - std::string path = path1; - - if (path.empty() == false && *path.rbegin() != '/') { - path += "/"; - } - path += path2; - - return path; -} - -int RsDirUtil::createLockFile(const std::string& lock_file_path, rs_lock_handle_t &lock_handle) -{ - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS -// Suspended. The user should make sure he's not already using the file descriptor. -// if(lock_handle != -1) -// close(lock_handle); - - // open the file in write mode, create it if necessary, truncate it (it should be empty) - lock_handle = open(lock_file_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - - if(lock_handle == -1) - { - std::cerr << "Could not open lock file " << lock_file_path.c_str() << std::flush; - perror(NULL); - return 2; - } - - // see "man fcntl" for the details, in short: non blocking lock creation on the whole file contents - struct flock lockDetails; - lockDetails.l_type = F_WRLCK; - lockDetails.l_whence = SEEK_SET; - lockDetails.l_start = 0; - lockDetails.l_len = 0; - - if(fcntl(lock_handle, F_SETLK, &lockDetails) == -1) - { - int fcntlErr = errno; - std::cerr << "Could not request lock on file " << lock_file_path.c_str() << std::flush; - perror(NULL); - - // there's no lock so let's release the file handle immediately - close(lock_handle); - lock_handle = -1; - - if(fcntlErr == EACCES || fcntlErr == EAGAIN) - return 1; - else - return 2; - } - - // Write to lock file our pid - std::string ourPID = std::to_string(::getpid()); - write(lock_handle, ourPID.c_str(), sizeof(char)*ourPID.size() ); - - return 0; -#else -// Suspended. The user should make sure he's not already using the file descriptor. -// -// if (lock_handle) { -// CloseHandle(lock_handle); -// } - - std::wstring wlockFile; - librs::util::ConvertUtf8ToUtf16(lock_file_path, wlockFile); - - // open the file in write mode, create it if necessary - lock_handle = CreateFile(wlockFile.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); - - if (lock_handle == INVALID_HANDLE_VALUE) - { - DWORD lasterror = GetLastError(); - - std::cerr << "Could not open lock file " << lock_file_path.c_str() << std::endl; - std::cerr << "Last error: " << lasterror << std::endl << std::flush; - perror(NULL); - - if (lasterror == ERROR_SHARING_VIOLATION || lasterror == ERROR_ACCESS_DENIED) - return 1; - - return 2; - } - - return 0; -#endif - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -} - -void RsDirUtil::releaseLockFile(rs_lock_handle_t lockHandle) -{ - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - if(lockHandle != -1) - { - close(lockHandle); - lockHandle = -1; - } -#else - if(lockHandle) - { - CloseHandle(lockHandle); - lockHandle = 0; - } -#endif - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -} - -RsStackFileLock::RsStackFileLock(const std::string& file_path) -{ - while(RsDirUtil::createLockFile(file_path,_file_handle)) - { - std::cerr << "Cannot acquire file lock " << file_path << ", waiting 1 sec." << std::endl; - rstime::rs_usleep(1 * 1000 * 1000) ; // 1 sec - } -#ifdef RSDIR_DEBUG - std::cerr << "Acquired file handle " << _file_handle << ", lock file:" << file_path << std::endl; -#endif -} -RsStackFileLock::~RsStackFileLock() -{ - RsDirUtil::releaseLockFile(_file_handle) ; -#ifdef RSDIR_DEBUG - std::cerr << "Released file lock with handle " << _file_handle << std::endl; -#endif -} - -#if 0 // NOT ENABLED YET! -/************************* WIDE STRING ***************************/ -/************************* WIDE STRING ***************************/ -/************************* WIDE STRING ***************************/ - -std::wstring RsDirUtil::getWideTopDir(std::wstring dir) -{ - std::wstring top; - - /* find the subdir: [/][dir1.../][/] - */ - int i,j; - int len = dir.length(); - for(j = len - 1; (j > 0) && (dir[j] == '/'); j--); - for(i = j; (i > 0) && (dir[i] != '/'); i--); - - if (dir[i] == '/') - i++; - - for(; i <= j; i++) - { - top += dir[i]; - } - - return top; -} - -std::wstring RsDirUtil::removeWideTopDir(std::wstring dir) -{ - std::wstring rest; - - /* remove the subdir: [/][dir1.../][/] - */ - int i,j; - int len = dir.length(); - for(j = len - 1; (j > 0) && (dir[j] == '/'); j--); - for(i = j; (i >= 0) && (dir[i] != '/'); i--); - - /* remove any more slashes */ - for(; (i >= 0) && (dir[i] == '/'); i--); - - for(j = 0; j <= i; j++) - { - rest += dir[j]; - } - - return rest; -} - -std::wstring RsDirUtil::getWideRootDir(std::wstring dir) -{ - std::wstring root; - - /* find the subdir: [/]root[/...] - */ - int i,j; - int len = dir.length(); - for(i = 0; (i < len) && (dir[i] == '/'); i++); - for(j = i; (j < len) && (dir[j] != '/'); j++); - if (i == j) - return root; /* empty */ - for(; i < j; i++) - { - root += dir[i]; - } - return root; -} - -std::wstring RsDirUtil::removeWideRootDir(std::wstring path) -{ - unsigned int i, j; - unsigned int len = path.length(); - std::wstring output; - - /* chew leading '/'s */ - for(i = 0; (i < len) && (path[i] == '/'); i++); - if (i == len) - return output; /* empty string */ - - for(j = i; (j < len) && (path[j] != '/'); j++); /* run to next '/' */ - for(; (j < len) && (path[j] == '/'); j++); /* chew leading '/'s */ - - for(; j < len; j++) - { - output += path[j]; - } - - return output; -} - -std::wstring RsDirUtil::removeWideRootDirs(std::wstring path, std::wstring root) -{ - /* too tired */ - std::wstring notroot; - - unsigned int i = 0, j = 0; - - /* catch empty data */ - if ((root.length() < 1) || (path.length() < 1)) - return notroot; - - if ((path[0] == '/') && (root[0] != '/')) - { - i++; - } - - for(; (i < path.length()) && (j < root.length()) && (path[i] == root[j]); i++, j++); - - /* should have consumed root. */ - if (j == root.length()) - { - //std::cerr << "matched root!" << std::endl; - } - else - { - //std::cerr << "failed i: " << i << ", j: " << j << std::endl; - //std::cerr << "root: " << root << " path: " << path << std::endl; - return notroot; - } - - if (path[i] == '/') - { - i++; - } - - for(; i < path.length(); i++) - { - notroot += path[i]; - } - - //std::cerr << "Found NotRoot: " << notroot << std::endl; - - return notroot; -} - - - -int RsDirUtil::breakupWideDirList(std::wstring path, - std::list &subdirs) -{ - int start = 0; - unsigned int i; - for(i = 0; i < path.length(); i++) - { - if (path[i] == '/') - { - if (i - start > 0) - { - subdirs.push_back(path.substr(start, i-start)); - } - start = i+1; - } - } - // get the final one. - if (i - start > 0) - { - subdirs.push_back(path.substr(start, i-start)); - } - return 1; -} - - - -bool RsDirUtil::checkWideDirectory(std::wstring dir) -{ - struct stat buf; - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - std::string d(dir.begin(), dir.end()); - int val = stat(d.c_str(), &buf); - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - if (val == -1) - { -#ifdef RSDIR_DEBUG - std::cerr << "RsDirUtil::checkDirectory() "; - std::cerr << d << " doesn't exist" << std::endl; -#endif - return false; - } - else if (!S_ISDIR(buf.st_mode)) - { - // Some other type - error. -#ifdef RSDIR_DEBUG - std::cerr << "RsDirUtil::checkDirectory() "; - std::cerr << d << " is not Directory" << std::endl; -#endif - return false; - } - return true; -} - - -bool RsDirUtil::checkWideCreateDirectory(std::wstring dir) -{ - struct stat buf; - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - std::string d(dir.begin(), dir.end()); - int val = stat(d.c_str(), &buf); - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - if (val == -1) - { - // directory don't exist. create. -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // UNIX - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - if (-1 == mkdir(d.c_str(), 0777)) - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ -#else // WIN - if (-1 == mkdir(d.c_str())) -#endif -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - { -#ifdef RSDIR_DEBUG - std::cerr << "check_create_directory() Fatal Error --"; - std::cerr < - -bool RsDirUtil::cleanupWideDirectory(std::wstring cleandir, std::list keepFiles) -{ - - /* check for the dir existance */ - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - std::string cd(cleandir.begin(), cleandir.end()); - DIR *dir = opendir(cd.c_str()); - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - std::list::const_iterator it; - - if (!dir) - { - return false; - } - - struct dirent *dent; - struct stat buf; - - while(NULL != (dent = readdir(dir))) - { - /* check entry type */ - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - std::string fname(dent -> d_name); - std::wstring wfname(fname.begin(), fname.end()); - std::string fullname = cd + "/" + fname; - - if (-1 != stat(fullname.c_str(), &buf)) - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - { - /* only worry about files */ - if (S_ISREG(buf.st_mode)) - { - /* check if we should keep it */ - if (keepFiles.end() == (it = std::find(keepFiles.begin(), keepFiles.end(), wfname))) - { - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - /* can remove */ - remove(fullname.c_str()); - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - } - } - } - } - /* close directory */ - closedir(dir); - - return true; -} - -/* slightly nicer helper function */ -bool RsDirUtil::hashWideFile(std::wstring filepath, - std::wstring &name, std::string &hash, uint64_t &size) -{ - if (getWideFileHash(filepath, hash, size)) - { - /* extract file name */ - name = RsDirUtil::getWideTopDir(filepath); - return true; - } - return false; -} - - -#include -#include -#include - -/* Function to hash, and get details of a file */ -bool RsDirUtil::getWideFileHash(std::wstring filepath, - std::string &hash, uint64_t &size) -{ - FILE *fd; - int len; - SHA_CTX *sha_ctx = new SHA_CTX; - unsigned char sha_buf[SHA_DIGEST_LENGTH]; - unsigned char gblBuf[512]; - - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - std::string fp(filepath.begin(), filepath.end()); - - if (NULL == (fd = fopen64(fp.c_str(), "rb"))) - return false; - - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - - /* determine size */ - fseeko64(fd, 0, SEEK_END); - size = ftello64(fd); - fseeko64(fd, 0, SEEK_SET); - - SHA1_Init(sha_ctx); - while((len = fread(gblBuf,1, 512, fd)) > 0) - { - SHA1_Update(sha_ctx, gblBuf, len); - } - - /* reading failed for some reason */ - if (ferror(fd)) - { - delete sha_ctx; - fclose(fd); - return false; - } - - SHA1_Final(&sha_buf[0], sha_ctx); - - std::ostringstream tmpout; // please do not use std::ostringstream - for(int i = 0; i < SHA_DIGEST_LENGTH; i++) - { - tmpout << std::setw(2) << std::setfill('0') << std::hex << (unsigned int) (sha_buf[i]); - } - hash = tmpout.str(); - - delete sha_ctx; - fclose(fd); - return true; -} - -bool RsDirUtil::renameWideFile(const std::wstring& from, const std::wstring& to) -{ - int loops = 0; - -#if defined(WIN32) || defined(MINGW) || defined(__CYGWIN__) -#ifdef WIN_CROSS_UBUNTU - std::wstring f,t ; - for(int i=0;i= 30) - return false ; - - loops++; - } - - return true ; -} - - -#endif // WIDE STUFF NOT ENABLED YET! diff --git a/libretroshare/src/util/rsdir.h b/libretroshare/src/util/rsdir.h deleted file mode 100644 index 50e636541..000000000 --- a/libretroshare/src/util/rsdir.h +++ /dev/null @@ -1,164 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsdir.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2007 Robert Fernie * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ - -#pragma once - -#include -#include -#include -#include - -class RsThread; - -#include - -#ifndef WINDOWS_SYS -typedef int rs_lock_handle_t; -#else -typedef /*HANDLE*/ void *rs_lock_handle_t; -#endif - -// This is a scope guard on a given file. Works like a mutex. Is blocking. -// We could do that in another way: derive RsMutex into RsLockFileMutex, and -// use RsStackMutex on it transparently. Only issue: this will cost little more -// because of the multiple inheritance. -// -class RsStackFileLock -{ - public: - RsStackFileLock(const std::string& file_path) ; - ~RsStackFileLock() ; - - private: - rs_lock_handle_t _file_handle ; -}; - -namespace RsDirUtil { - -std::string getTopDir(const std::string&); -std::string getRootDir(const std::string&); -std::string removeRootDir(const std::string& path); -void removeTopDir(const std::string& dir, std::string &path); -std::string removeRootDirs(const std::string& path, const std::string& root); - -// Renames file from to file to. Files should be on the same file system. -// returns true if succeed, false otherwise. -bool renameFile(const std::string& from,const std::string& to) ; -//bool createBackup (const std::string& sFilename, unsigned int nCount = 5); - -// returns the CRC32 of the data of length len -// -uint32_t rs_CRC32(const unsigned char *data,uint32_t len) ; - -// Returns %u, %lu, or %llu, depending on the size of unsigned int, unsigned long and unsigned long long on the current system. -// Use as; -// sscanf(string, RsDirUtil::scanf_string_for_uint( sizeof(X) ), &X) ; -// -const char *scanf_string_for_uint(int bytes) ; - -int breakupDirList(const std::string& path, std::list &subdirs); - -// Splits the path into parent directory and file. File can be empty if full_path is a dir ending with '/' -// if full_path does not contain a directory, then dir will be "." and file will be full_path. - -bool splitDirFromFile(const std::string& full_path,std::string& dir, std::string& file); - -bool copyFile(const std::string& source,const std::string& dest); - -/** Move file. If destination directory doesn't exists create it. */ -bool moveFile(const std::string& source, const std::string& dest); - -bool removeFile(const std::string& file); -bool fileExists(const std::string& file); -bool checkFile(const std::string& filename,uint64_t& file_size,bool disallow_empty_file = false); -bool checkDirectory(const std::string& dir); -bool checkCreateDirectory(const std::string& dir); - -// Removes all symbolic links along the path and computes the actual location of the file/dir passed as argument. - -std::string removeSymLinks(const std::string& path) ; - -bool cleanupDirectory(const std::string& dir, const std::set &keepFiles); -bool cleanupDirectoryFaster(const std::string& dir, const std::set &keepFiles); - -bool hashFile(const std::string& filepath, std::string &name, RsFileHash &hash, uint64_t &size); -bool getFileHash(const std::string& filepath,RsFileHash &hash, uint64_t &size, RsThread *thread = NULL); - -Sha1CheckSum sha1sum(const uint8_t *data,uint32_t size) ; -Sha256CheckSum sha256sum(const uint8_t *data,uint32_t size) ; - -bool saveStringToFile(const std::string& file, const std::string& str); -bool loadStringFromFile(const std::string& file, std::string& str); - -// Creates a lock file with given path, and returns the lock handle -// returns: -// 0: Success -// 1: Another instance already has the lock -// 2 : Unexpected error -int createLockFile(const std::string& lock_file_path, rs_lock_handle_t& lock_handle) ; - -// Removes the lock file with specified handle. -void releaseLockFile(rs_lock_handle_t lockHandle) ; - -std::wstring getWideTopDir(std::wstring); -std::wstring getWideRootDir(std::wstring); -std::wstring removeWideRootDir(std::wstring path); -std::wstring removeWideTopDir(std::wstring dir); -std::wstring removeWideRootDirs(std::wstring path, std::wstring root); - -// Renames file from to file to. Files should be on the same file system. -// returns true if succeed, false otherwise. -bool renameWideFile(const std::wstring& from,const std::wstring& to) ; - -int breakupWideDirList(std::wstring path, - std::list &subdirs); - -bool checkWideDirectory(std::wstring dir); -bool checkWideCreateDirectory(std::wstring dir); -bool cleanupWideDirectory(std::wstring dir, std::list keepFiles); - -bool hashWideFile(std::wstring filepath,std::wstring &name, RsFileHash &hash, uint64_t &size); - -bool getWideFileHash(std::wstring filepath, RsFileHash &hash, uint64_t &size); - -FILE *rs_fopen(const char* filename, const char* mode); - -std::string convertPathToUnix(std::string path); - -/** Concatenate two path pieces putting '/' separator between them only if - * needed */ -std::string makePath(const std::string &path1, const std::string &path2); - -RS_SET_CONTEXT_DEBUG_LEVEL(1); -} - -#if __cplusplus < 201703L -namespace std -{ -namespace filesystem -{ -bool create_directories(const std::string& path); -} -} -#endif // __cplusplus < 201703L diff --git a/libretroshare/src/util/rsdiscspace.cc b/libretroshare/src/util/rsdiscspace.cc deleted file mode 100644 index a394cd4e5..000000000 --- a/libretroshare/src/util/rsdiscspace.cc +++ /dev/null @@ -1,223 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsdiscspace.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include -#include "util/rstime.h" -#include "rsserver/p3face.h" -#include "retroshare/rsfiles.h" -#include "retroshare/rsiface.h" -#include "retroshare/rsinit.h" -#include "rsdiscspace.h" -#include - -#ifdef __ANDROID__ -# include -#endif - -#ifdef WIN32 -# include -#elif defined(__ANDROID__) && (__ANDROID_API__ < 21) -# include -# define statvfs64 statfs -# warning statvfs64 is not supported with android platform < 21 falling back to statfs that is untested (may misbehave) -#else -# include -#endif - -#define DELAY_BETWEEN_CHECKS 2 - -/* - * #define DEBUG_RSDISCSPACE - */ - -rstime_t RsDiscSpace::_last_check[RS_DIRECTORY_COUNT] = { 0,0,0,0 } ; -uint32_t RsDiscSpace::_size_limit_mb = 100 ; -uint32_t RsDiscSpace::_current_size[RS_DIRECTORY_COUNT] = { 10000,10000,10000,10000 } ; -bool RsDiscSpace::_last_res[RS_DIRECTORY_COUNT] = { true,true,true,true }; -RsMutex RsDiscSpace::_mtx("RsDiscSpace") ; -std::string RsDiscSpace::_partials_path = "" ; -std::string RsDiscSpace::_download_path = "" ; - -bool RsDiscSpace::crossSystemDiskStats(const char *file, uint64_t& free_blocks, uint64_t& block_size) -{ -#if defined(WIN32) || defined(MINGW) || defined(__CYGWIN__) - - DWORD dwFreeClusters; - DWORD dwBytesPerSector; - DWORD dwSectorPerCluster; - DWORD dwTotalClusters; - -#ifdef WIN_CROSS_UBUNTU - wchar_t szDrive[4]; - szDrive[0] = file[0] ; - szDrive[1] = file[1] ; - szDrive[2] = file[2] ; -#else - char szDrive[4] = ""; - - char *pszFullPath = _fullpath (NULL, file, 0); - if (pszFullPath == 0) { - std::cerr << "Size estimate failed for drive (_fullpath) " << std::endl ; - return false; - } - _splitpath (pszFullPath, szDrive, NULL, NULL, NULL); - free (pszFullPath); -#endif - szDrive[3] = 0; - - if (!GetDiskFreeSpaceA (szDrive, &dwSectorPerCluster, &dwBytesPerSector, &dwFreeClusters, &dwTotalClusters)) - { - std::cerr << "Size estimate failed for drive " << szDrive << std::endl ; - return false; - } - - free_blocks = dwFreeClusters ; - block_size = dwSectorPerCluster * dwBytesPerSector ; -#else -#ifdef __APPLE__ - struct statvfs buf; - - if (0 != statvfs (file, &buf)) - { - std::cerr << "Size estimate failed for file " << file << std::endl ; - return false; - } - - - free_blocks = buf.f_bavail; - block_size = buf.f_frsize ; -#else - struct statvfs64 buf; - - if (0 != statvfs64 (file, &buf)) - { - std::cerr << "Size estimate failed for file " << file << std::endl ; - return false; - } - - - free_blocks = buf.f_bavail; - block_size = buf.f_bsize ; -#endif - -#endif - return true ; -} - -void RsDiscSpace::setDownloadPath(const std::string& path) -{ - RsStackMutex m(_mtx) ; // Locked - _download_path = path ; -} - -void RsDiscSpace::setPartialsPath(const std::string& path) -{ - RsStackMutex m(_mtx) ; // Locked - _partials_path = path ; -} - -bool RsDiscSpace::checkForDiscSpace(RsDiscSpace::DiscLocation loc) -{ - RsStackMutex m(_mtx) ; // Locked - - if( (_partials_path == "" && loc == RS_PARTIALS_DIRECTORY) || (_download_path == "" && loc == RS_DOWNLOAD_DIRECTORY)) - throw std::runtime_error("Download path and partial path not properly set in RsDiscSpace. Please call RsDiscSpace::setPartialsPath() and RsDiscSpace::setDownloadPath()") ; - - rstime_t now = time(NULL) ; - - if(_last_check[loc]+DELAY_BETWEEN_CHECKS < now) - { - uint64_t free_blocks,block_size ; - int rs = false; - -#ifdef DEBUG_RSDISCSPACE - std::cerr << "Size determination:" << std::endl ; -#endif - switch(loc) - { - case RS_DOWNLOAD_DIRECTORY: rs = crossSystemDiskStats(_download_path.c_str(),free_blocks,block_size) ; -#ifdef DEBUG_RSDISCSPACE - std::cerr << " path = " << _download_path << std::endl ; -#endif - break ; - - case RS_PARTIALS_DIRECTORY: rs = crossSystemDiskStats(_partials_path.c_str(),free_blocks,block_size) ; -#ifdef DEBUG_RSDISCSPACE - std::cerr << " path = " << _partials_path << std::endl ; -#endif - break ; - - case RS_CONFIG_DIRECTORY: rs = crossSystemDiskStats(RsAccounts::AccountDirectory().c_str(),free_blocks,block_size) ; -#ifdef DEBUG_RSDISCSPACE - std::cerr << " path = " << RsInit::RsConfigDirectory() << std::endl ; -#endif - break ; - - case RS_PGP_DIRECTORY: rs = crossSystemDiskStats(RsAccounts::PGPDirectory().c_str(),free_blocks,block_size) ; -#ifdef DEBUG_RSDISCSPACE - std::cerr << " path = " << RsInit::RsPGPDirectory() << std::endl ; -#endif - break ; - } - - if(!rs) - { - std::cerr << "Determination of free disc space failed ! Be careful !" << std::endl ; - return true ; - } - _last_check[loc] = now ; - - // Now compute the size in megabytes - // - _current_size[loc] = uint32_t(block_size * free_blocks / (uint64_t)(1024*1024)) ; // on purpose integer division - -#ifdef DEBUG_RSDISCSPACE - std::cerr << " blocks available = " << free_blocks << std::endl ; - std::cerr << " blocks size = " << block_size << std::endl ; - std::cerr << " free MBs = " << _current_size[loc] << std::endl ; -#endif - } - - bool res = _current_size[loc] > _size_limit_mb ; - - if(_last_res[loc] && !res) - RsServer::notify()->notifyDiskFull(loc,_size_limit_mb) ; - - _last_res[loc] = res ; - - return res ; -} - -void RsDiscSpace::setFreeSpaceLimit(uint32_t size_in_mb) -{ - RsStackMutex m(_mtx) ; // Locked - - _size_limit_mb = size_in_mb ; -} - -uint32_t RsDiscSpace::freeSpaceLimit() -{ - RsStackMutex m(_mtx) ; // Locked - - return _size_limit_mb ; -} - diff --git a/libretroshare/src/util/rsdiscspace.h b/libretroshare/src/util/rsdiscspace.h deleted file mode 100644 index 834561e6a..000000000 --- a/libretroshare/src/util/rsdiscspace.h +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsdiscspace.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -class RsDiscSpace -{ - public: - typedef uint32_t DiscLocation ; - - // Returns false is the disc space is lower than the given size limit, true otherwise. - // When the size limit is reached, this class calls notify to warn the user (possibly - // with a popup window). - // - static bool checkForDiscSpace(DiscLocation loc) ; - - // Allow the user to specify his own size limit. Should not be too low, especially not 0 MB ;-) - // 10MB to 100MB are sensible values. - // - static void setFreeSpaceLimit(uint32_t mega_bytes) ; - static uint32_t freeSpaceLimit() ; - - static void setPartialsPath(const std::string& path) ; - static void setDownloadPath(const std::string& path) ; - private: - static bool crossSystemDiskStats(const char *file, uint64_t& free_blocks, uint64_t& block_size) ; - - static RsMutex _mtx ; - - static rstime_t _last_check[RS_DIRECTORY_COUNT] ; - static uint32_t _size_limit_mb ; - static uint32_t _current_size[RS_DIRECTORY_COUNT] ; - static bool _last_res[RS_DIRECTORY_COUNT] ; - - static std::string _partials_path ; - static std::string _download_path ; -}; - diff --git a/libretroshare/src/util/rsendian.h b/libretroshare/src/util/rsendian.h deleted file mode 100644 index d27c374ff..000000000 --- a/libretroshare/src/util/rsendian.h +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * * - * libretroshare endiannes utilities * - * * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -/** - * @file - * This file provide convenient integer endiannes conversion utilities. - * Instead of providing them with different names for each type (a la C htonl, - * htons, ntohl, ntohs ), which make them uncomfortable to use, expose a - * templated function `rs_endian_fix` to reorder integers bytes representation - * when sending or receiving from the network. */ - -/* enforce LITTLE_ENDIAN on Windows */ -#ifdef WINDOWS_SYS -# define BYTE_ORDER 1234 -# define LITTLE_ENDIAN 1234 -# define BIG_ENDIAN 4321 -#else -#include -#endif - -template inline INTTYPE rs_endian_fix(INTTYPE val) -{ -#if BYTE_ORDER == LITTLE_ENDIAN - INTTYPE swapped = 0; - for (size_t i = 0; i < sizeof(INTTYPE); ++i) - swapped |= (val >> (8*(sizeof(INTTYPE)-i-1)) & 0xFF) << (8*i); - return swapped; -#else - return val; -#endif -}; - -#ifndef BYTE_ORDER -# error "ENDIAN determination Failed (BYTE_ORDER not defined)" -#endif - -#if !(BYTE_ORDER == BIG_ENDIAN || BYTE_ORDER == LITTLE_ENDIAN) -# error "ENDIAN determination Failed (unkown BYTE_ORDER value)" -#endif diff --git a/libretroshare/src/util/rserrno.cc b/libretroshare/src/util/rserrno.cc deleted file mode 100644 index b62394d69..000000000 --- a/libretroshare/src/util/rserrno.cc +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rserrno.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#include - -#define RS_INTERNAL_ERRNO_CASE(e) case e: return #e - -const char* rsErrnoName(int err) -{ - switch (err) - { - RS_INTERNAL_ERRNO_CASE(EINVAL); - RS_INTERNAL_ERRNO_CASE(EBUSY); - RS_INTERNAL_ERRNO_CASE(EAGAIN); - RS_INTERNAL_ERRNO_CASE(EDEADLK); - RS_INTERNAL_ERRNO_CASE(EPERM); - RS_INTERNAL_ERRNO_CASE(EBADF); - RS_INTERNAL_ERRNO_CASE(EFAULT); - RS_INTERNAL_ERRNO_CASE(ENOTSOCK); - RS_INTERNAL_ERRNO_CASE(EISCONN); - RS_INTERNAL_ERRNO_CASE(ECONNREFUSED); - RS_INTERNAL_ERRNO_CASE(ETIMEDOUT); - RS_INTERNAL_ERRNO_CASE(ENETUNREACH); - RS_INTERNAL_ERRNO_CASE(EADDRINUSE); - RS_INTERNAL_ERRNO_CASE(EINPROGRESS); - RS_INTERNAL_ERRNO_CASE(EALREADY); - RS_INTERNAL_ERRNO_CASE(ENOTCONN); - RS_INTERNAL_ERRNO_CASE(EPIPE); - RS_INTERNAL_ERRNO_CASE(ECONNRESET); - RS_INTERNAL_ERRNO_CASE(EHOSTUNREACH); - RS_INTERNAL_ERRNO_CASE(EADDRNOTAVAIL); - } - - return "rsErrnoName UNKNOWN ERROR CODE"; -} diff --git a/libretroshare/src/util/rserrno.h b/libretroshare/src/util/rserrno.h deleted file mode 100644 index 526a4890a..000000000 --- a/libretroshare/src/util/rserrno.h +++ /dev/null @@ -1,24 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rserrno.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -const char* rsErrnoName(int err); diff --git a/libretroshare/src/util/rsexpr.cc b/libretroshare/src/util/rsexpr.cc deleted file mode 100644 index dff5a5fa5..000000000 --- a/libretroshare/src/util/rsexpr.cc +++ /dev/null @@ -1,320 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsexpr.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Kashif Kaleem * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "retroshare/rsexpr.h" -#include "retroshare/rstypes.h" -#include -#include - -/****************************************************************************************** -eval functions of relational expressions. - -******************************************************************************************/ - -namespace RsRegularExpression -{ -template<> -void RelExpression::linearize(LinearizedExpression& e) const -{ - e._ints.push_back(Op) ; - e._ints.push_back(LowerValue) ; - e._ints.push_back(HigherValue) ; -} - - -bool DateExpression::eval(const ExpFileEntry& file) -{ - return evalRel(file.file_modtime()); -} - -bool SizeExpressionMB::eval(const ExpFileEntry& file) -{ - return evalRel((int)(file.file_size()/(uint64_t)(1024*1024))); -} - -bool SizeExpression::eval(const ExpFileEntry& file) -{ - return evalRel(file.file_size()); -} - -bool PopExpression::eval(const ExpFileEntry& file) -{ - return evalRel(file.file_popularity()); -} - -/****************************************************************************************** -Code for evaluating string expressions - -******************************************************************************************/ - -bool NameExpression::eval(const ExpFileEntry& file) -{ - return evalStr(file.file_name()); -} - -bool PathExpression::eval(const ExpFileEntry& file) -{ - return evalStr(file.file_parent_path()); -} - -bool ExtExpression::eval(const ExpFileEntry& file) -{ - std::string ext; - /*Get the part of the string after the last instance of . in the filename */ - size_t index = file.file_name().find_last_of('.'); - if (index != std::string::npos) { - ext = file.file_name().substr(index+1); - if (ext != "" ){ - return evalStr(ext); - } - } - return false; -} - -bool HashExpression::eval(const ExpFileEntry& file){ - return evalStr(file.file_hash().toStdString()); -} - -/*Check whether two strings are 'equal' to each other*/ -static bool StrEquals(const std::string & str1, const std::string & str2, - bool IgnoreCase ){ - if ( str1.size() != str2.size() ){ - return false; - } else if (IgnoreCase) { - std::equal( str1.begin(), str1.end(), - str2.begin(), CompareCharIC() ); - } - return std::equal( str1.begin(), str1.end(), - str2.begin()); -} - -/*Check whether one string contains the other*/ -static bool StrContains( const std::string & str1, const std::string & str2, - bool IgnoreCase){ - - std::string::const_iterator iter ; - if (IgnoreCase) { - iter = std::search( str1.begin(), str1.end(), - str2.begin(), str2.end(), CompareCharIC() ); - } else { - iter = std::search( str1.begin(), str1.end(), - str2.begin(), str2.end()); - } - - return ( iter != str1.end() ); -} - - -std::string StringExpression::toStdStringWithParam(const std::string& varstr) const -{ - std::string strlist ; - for (auto iter = terms.begin(); iter != terms.end(); ++iter ) - strlist += *iter + " "; - - if(!strlist.empty()) - strlist.resize(strlist.size()-1); //strlist.pop_back(); // pops the last ",". c++11 is needed for pop_back() - - switch(Op) - { - case ContainsAllStrings: return varstr + " CONTAINS ALL "+strlist ; - case ContainsAnyStrings: if(terms.size() == 1) - return varstr + " CONTAINS "+strlist ; - else - return varstr + " CONTAINS ONE OF "+strlist ; - case EqualsString: if(terms.size() == 1) - return varstr + " IS "+strlist ; - else - return varstr + " IS ONE OF "+strlist ; - - default: - return "" ; - } -} - -bool StringExpression :: evalStr ( const std::string &str ){ - std::list::iterator iter; - switch (Op) { - case ContainsAllStrings: - for ( iter = terms.begin(); iter != terms.end(); ++iter ) { - if ( StrContains (str, *iter, IgnoreCase) == false ){ - return false; - } - } - return true; - break; - case ContainsAnyStrings: - for ( iter = terms.begin(); iter != terms.end(); ++iter ) { - if ( StrContains (str,*iter, IgnoreCase) == true ) { - return true; - } - } - break; - case EqualsString: - for ( iter = terms.begin(); iter != terms.end(); ++iter ) { - if ( StrEquals (str,*iter, IgnoreCase) == true ) { - return true; - } - } - break; - default: - return false; - } - return false; -} - -/************************************************************************* - * linearization code - *************************************************************************/ - -void CompoundExpression::linearize(LinearizedExpression& e) const -{ - e._tokens.push_back(LinearizedExpression::EXPR_COMP) ; - e._ints.push_back(Op) ; - - Lexp->linearize(e) ; - Rexp->linearize(e) ; -} - -void StringExpression::linearize(LinearizedExpression& e) const -{ - e._ints.push_back(Op) ; - e._ints.push_back(IgnoreCase) ; - e._ints.push_back(terms.size()) ; - - for(std::list::const_iterator it(terms.begin());it!=terms.end();++it) - e._strings.push_back(*it) ; -} - -Expression *LinearizedExpression::toExpr(const LinearizedExpression& e) -{ - int i=0,j=0,k=0 ; - return toExpr(e,i,j,k) ; -} - -void LinearizedExpression::readStringExpr(const LinearizedExpression& e,int& n_ints,int& n_strings,std::list& strings,bool& b,StringOperator& op) -{ - op = static_cast(e._ints[n_ints++]) ; - b = e._ints[n_ints++] ; - int n = e._ints[n_ints++] ; - - strings.clear() ; - for(int i=0;i::const_iterator i = this->_strings.begin(); i != this->_strings.end(); ++i) - { - str += *i; - str += " "; - } - return str; -} - -Expression *LinearizedExpression::toExpr(const LinearizedExpression& e,int& n_tok,int& n_ints,int& n_strings) -{ - LinearizedExpression::token tok = static_cast(e._tokens[n_tok++]) ; - - switch(tok) - { - case EXPR_DATE: { - RelOperator op = static_cast(e._ints[n_ints++]) ; - int lv = e._ints[n_ints++] ; - int hv = e._ints[n_ints++] ; - - return new DateExpression(op,lv,hv) ; - } - - case EXPR_POP: { - RelOperator op = static_cast(e._ints[n_ints++]) ; - int lv = e._ints[n_ints++] ; - int hv = e._ints[n_ints++] ; - - return new PopExpression(op,lv,hv) ; - } - case EXPR_SIZE: { - RelOperator op = static_cast(e._ints[n_ints++]) ; - int lv = e._ints[n_ints++] ; - int hv = e._ints[n_ints++] ; - - return new SizeExpression(op,lv,hv) ; - } - case EXPR_HASH: { - std::list strings ; - StringOperator op ; - bool b ; - - readStringExpr(e,n_ints,n_strings,strings,b,op) ; - return new HashExpression(op,strings) ; - } - case EXPR_NAME: { - std::list strings ; - StringOperator op ; - bool b ; - - readStringExpr(e,n_ints,n_strings,strings,b,op) ; - - return new NameExpression(op,strings,b) ; - } - case EXPR_PATH: { - std::list strings ; - StringOperator op ; - bool b ; - - readStringExpr(e,n_ints,n_strings,strings,b,op) ; - - return new ExtExpression(op,strings,b) ; - } - case EXPR_EXT: { - std::list strings ; - StringOperator op ; - bool b ; - - readStringExpr(e,n_ints,n_strings,strings,b,op) ; - - return new ExtExpression(op,strings,b) ; - } - case EXPR_COMP: { - LogicalOperator op = static_cast(e._ints[n_ints++]) ; - - Expression *e1 = toExpr(e,n_tok,n_ints,n_strings) ; - Expression *e2 = toExpr(e,n_tok,n_ints,n_strings) ; - - return new CompoundExpression(op,e1,e2) ; - } - case EXPR_SIZE_MB: { - RelOperator op = static_cast(e._ints[n_ints++]) ; - int lv = e._ints[n_ints++] ; - int hv = e._ints[n_ints++] ; - - return new SizeExpressionMB(op,lv,hv) ; - } - default: - std::cerr << "No expression match the current value " << tok << std::endl ; - return NULL ; - } -} - - -} diff --git a/libretroshare/src/util/rsinitedptr.h b/libretroshare/src/util/rsinitedptr.h deleted file mode 100644 index 09aaa871a..000000000 --- a/libretroshare/src/util/rsinitedptr.h +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsinitedptr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ - -#pragma once -/** -helper class to store a pointer -it is usefull because it initialises itself to NULL - -usage: -replace - type* ptr; -with - inited_ptr ptr; - -this class can -- get assigned a pointer -- be dereferenced -- be converted back to a pointer -*/ -namespace RsUtil{ -template class inited_ptr{ -public: - inited_ptr(): _ptr(NULL){} - inited_ptr(const inited_ptr& other): _ptr(other._ptr){} - inited_ptr& operator= (const inited_ptr& other){ _ptr = other._ptr; return *this;} - inited_ptr& operator= (T* ptr){ _ptr = ptr; return *this;} - operator T* () const { return _ptr;} - T* operator ->() const { return _ptr;} - T& operator *() const { return *_ptr;} -private: - T* _ptr; -}; -}//namespace RsUtil diff --git a/libretroshare/src/util/rsjson.cc b/libretroshare/src/util/rsjson.cc deleted file mode 100644 index 8af1cf942..000000000 --- a/libretroshare/src/util/rsjson.cc +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#include -#include -#include - -#include "util/rsjson.h" - -inline int getJsonManipulatorStatePosition() -{ - static int p = std::ios_base::xalloc(); - return p; -} - -std::ostream& compactJSON(std::ostream &out) -{ - out.iword(getJsonManipulatorStatePosition()) = 1; - return out; -} - -std::ostream& prettyJSON(std::ostream &out) -{ - out.iword(getJsonManipulatorStatePosition()) = 0; - return out; -} - -std::ostream& operator<<(std::ostream &out, const RsJson &jDoc) -{ - rapidjson::StringBuffer buffer; buffer.Clear(); - if(out.iword(getJsonManipulatorStatePosition())) - { - rapidjson::Writer writer(buffer); - jDoc.Accept(writer); - } - else - { - rapidjson::PrettyWriter writer(buffer); - jDoc.Accept(writer); - } - - return out << buffer.GetString(); -} diff --git a/libretroshare/src/util/rsjson.h b/libretroshare/src/util/rsjson.h deleted file mode 100644 index 13073f3b2..000000000 --- a/libretroshare/src/util/rsjson.h +++ /dev/null @@ -1,51 +0,0 @@ -/******************************************************************************* - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -/** - * Use this type for JSON documents representations in RetroShare code - */ -typedef rapidjson::Document RsJson; - -/** - * Print out RsJson to a stream, use std::ostringstream to get the string - * @param[out] out output stream - * @param[in] jDoc JSON document to print - * @return same output stream passed as out parameter - */ -std::ostream& operator<<(std::ostream &out, const RsJson &jDoc); - -/** - * Stream manipulator to print RsJson in compact format - * @param[out] out output stream - * @return same output stream passed as out parameter - */ -std::ostream& compactJSON(std::ostream &out); - -/** - * Stream manipulator to print RsJson in human readable format - * @param[out] out output stream - * @return same output stream passed as out parameter - */ -std::ostream& prettyJSON(std::ostream &out); diff --git a/libretroshare/src/util/rskbdinput.cc b/libretroshare/src/util/rskbdinput.cc deleted file mode 100644 index 38b0307a2..000000000 --- a/libretroshare/src/util/rskbdinput.cc +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare/util/rskbdinput.cc * - * * - * Copyright (C) 2019 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef __ANDROID__ - -#include -#include - -#ifdef WINDOWS_SYS -#include -#include - -#define PASS_MAX 512 - -namespace RsUtil { -std::string rs_getpass(const std::string& prompt,bool no_echo) -{ - static char getpassbuf [PASS_MAX + 1]; - size_t i = 0; - int c; - - if (!prompt.empty()) { - std::cerr << prompt ; - std::cerr.flush(); - } - - for (;;) { - c = _getch (); - if (c == '\r') { - getpassbuf [i] = '\0'; - break; - } - else if (i < PASS_MAX) { - getpassbuf[i++] = c; - } - - if (i >= PASS_MAX) { - getpassbuf [i] = '\0'; - break; - } - } - - if (!prompt.empty()) { - std::cerr << "\r\n" ; - std::cerr.flush(); - } - - return std::string(getpassbuf); -} -} -#else - -#include -#include -#include -#include -#include - -static int getch() -{ - int ch; - struct termios t_old, t_new; - - tcgetattr(STDIN_FILENO, &t_old); - t_new = t_old; - t_new.c_lflag &= ~(ICANON | ECHO); - tcsetattr(STDIN_FILENO, TCSANOW, &t_new); - - ch = getchar(); - - tcsetattr(STDIN_FILENO, TCSANOW, &t_old); - return ch; -} - -namespace RsUtil { - -std::string rs_getpass(const std::string& prompt, bool no_echo) -{ - const char BACKSPACE=127; - const char RETURN=10; - - std::string password; - unsigned char ch=0; - - std::cout < * - * * - * 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 . * - * * - *******************************************************************************/ - -#include - -namespace RsUtil { - - std::string rs_getpass(const std::string& prompt,bool no_echo=true) ; - -} diff --git a/libretroshare/src/util/rsmemcache.h b/libretroshare/src/util/rsmemcache.h deleted file mode 100644 index 53d5efa27..000000000 --- a/libretroshare/src/util/rsmemcache.h +++ /dev/null @@ -1,492 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsmemcache.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_UTIL_MEM_CACHE -#define RS_UTIL_MEM_CACHE - -#include -#include "util/rstime.h" -#include -#include -#include - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -/* Generic Memoory Cache - * - * This is probably crude and crap to start with. - * Want Least Recently Used (LRU) discard policy, without having to search whole cache. - * Use two maps: - * - mDataMap[key] => data. - * - mLruMap[AccessTS] => key (multimap) - */ - -/*** - * #define DEBUG_RSMEMCACHE 1 - ***/ - -#define DEFAULT_MEM_CACHE_SIZE 100 - -template class RsMemCache -{ -public: - - RsMemCache(uint32_t max_size = DEFAULT_MEM_CACHE_SIZE, std::string name = "UnknownMemCache") - :mDataCount(0), mMaxSize(max_size), mName(name) - { - clearStats(); - return; - } - - bool is_cached(const Key &key) const; - bool fetch(const Key &key, Value &data); - - // Like map[] installs empty one if non-existent. - - Value& ref(const Key &key); - Value& operator[](const Key& key) { return ref(key); } - - bool store(const Key &key, const Value &data); - bool erase(const Key &key); // clean up cache. - - bool resize(); // should be called periodically to cleanup old entries. - - // Apply a method of a given class ClientClass to all cached data. Can be useful... - - template bool applyToAllCachedEntries(ClientClass& c,bool (ClientClass::*method)(Value&)); - - uint32_t size() const { return mDataMap.size() ; } - void printStats(std::ostream& out); -private: - - bool update_lrumap(const Key &key, rstime_t old_ts, rstime_t new_ts); - bool discard_LRU(int count_to_clear); - - // internal class. - class cache_data - { - public: - cache_data() { return; } - cache_data(Key in_key, Value in_data, rstime_t in_ts) - :key(in_key), data(in_data), ts(in_ts) { return; } - Key key; - Value data; - rstime_t ts; - }; - - - std::map mDataMap; - std::multimap mLruMap; - uint32_t mDataCount; - uint32_t mMaxSize; - std::string mName; - - // some statistics. - void clearStats(); - - mutable uint32_t mStats_inserted; - mutable uint32_t mStats_dropped; - mutable uint32_t mStats_iscached; - mutable uint32_t mStats_cachemiss; - mutable uint32_t mStats_access; - mutable uint32_t mStats_accessmiss; -}; - - -template bool RsMemCache::is_cached(const Key &key) const -{ - typename std::map::const_iterator it; - it = mDataMap.find(key); - if (it == mDataMap.end()) - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::is_cached(" << key << ") false"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - mStats_cachemiss++; - return false; - } -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::is_cached(" << key << ") false"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - mStats_iscached++; - return true; - -} - -template template bool RsMemCache::applyToAllCachedEntries(ClientClass& c, bool (ClientClass::*method)(Value&)) -{ - bool res = true ; - - for(typename std::map::iterator it(mDataMap.begin());it!=mDataMap.end();++it) - res = res && ((c.*method)(it->second.data)) ; - - return res ; -} - -template bool RsMemCache::fetch(const Key &key, Value& data) -{ -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::fetch()"; - std::cerr << std::endl; - printStats(std::cerr); -#endif // DEBUG_RSMEMCACHE - - typename std::map::iterator it; - it = mDataMap.find(key); - if (it == mDataMap.end()) - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::fetch(" << key << ") false"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - mStats_accessmiss++; - return false; - } - -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::fetch(" << key << ") OK"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - data = it->second.data; - - /* update ts on data */ - rstime_t old_ts = it->second.ts; - rstime_t new_ts = time(NULL); - it->second.ts = new_ts; - - update_lrumap(key, old_ts, new_ts); - - mStats_access++; - return true; -} - - -template bool RsMemCache::erase(const Key &key) -{ -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::erase()"; - std::cerr << std::endl; - printStats(std::cerr); -#endif // DEBUG_RSMEMCACHE - - typename std::map::iterator it; - it = mDataMap.find(key); - if (it == mDataMap.end()) - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::erase(" << key << ") false"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - mStats_accessmiss++; - return false; - } - -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::erase(" << key << ") OK"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - - /* get timestamps */ - rstime_t old_ts = it->second.ts; - rstime_t new_ts = 0; - - // remove from lru. - mDataMap.erase(it); - update_lrumap(key, old_ts, new_ts); - mDataCount--; - - mStats_access++; - return true; -} - - - -template Value &RsMemCache::ref(const Key &key) -{ -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::ref()"; - std::cerr << std::endl; - printStats(std::cerr); -#endif // DEBUG_RSMEMCACHE - - typename std::map::iterator it; - it = mDataMap.find(key); - if (it == mDataMap.end()) - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::ref(" << key << ") ERROR missing Key inserting Empty Data in LRU slot"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - // insert operation. - rstime_t new_ts = 0; - Value data; - mDataMap[key] = cache_data(key, data, new_ts); - mDataCount++; - - update_lrumap(key, 0, new_ts); - it = mDataMap.find(key); - - mStats_accessmiss++; - } - else - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::ref(" << key << ") OK"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - /* update ts on data */ - rstime_t old_ts = it->second.ts; - rstime_t new_ts = time(NULL); - it->second.ts = new_ts; - - update_lrumap(key, old_ts, new_ts); - - mStats_access++; - } - return it->second.data; -} - -template bool RsMemCache::store(const Key &key, const Value &data) -{ -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::store()"; - std::cerr << std::endl; - printStats(std::cerr); -#endif // DEBUG_RSMEMCACHE - - /* update lrumap entry */ - rstime_t old_ts = 0; - rstime_t new_ts = time(NULL); - - // For consistency - typename std::map::const_iterator it; - it = mDataMap.find(key); - if (it != mDataMap.end()) - { - // ERROR. -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::store() WARNING overriding existing entry"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - old_ts = it->second.ts; - } - else - { - mDataCount++; - } - - mDataMap[key] = cache_data(key, data, new_ts); - - update_lrumap(key, old_ts, new_ts); - - mStats_inserted++; - return true; -} - - -template bool RsMemCache::update_lrumap(const Key &key, rstime_t old_ts, rstime_t new_ts) -{ - if (old_ts == 0) - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") just insert!"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - /* new insertion */ - mLruMap.insert(std::make_pair(new_ts, key)); - return true; - } - - /* find old entry */ - typename std::multimap::iterator mit; - typename std::multimap::iterator sit = mLruMap.lower_bound(old_ts); - typename std::multimap::iterator eit = mLruMap.upper_bound(old_ts); - - for(mit = sit; mit != eit; ++mit) - { - if (mit->second == key) - { - mLruMap.erase(mit); -#ifdef DEBUG_RSMEMCACHE - std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") rm old"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - if (new_ts != 0) // == 0, means remove. - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") added new_ts"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - mLruMap.insert(std::make_pair(new_ts, key)); - } - return true; - } - } -#ifdef DEBUG_RSMEMCACHE - std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") ERROR"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - return false; -} - -template bool RsMemCache::resize() -{ -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::resize()"; - std::cerr << std::endl; - printStats(std::cerr); -#endif // DEBUG_RSMEMCACHE - - int count_to_clear = 0; - { - // consistency check. - if ((mDataMap.size() != mDataCount) || - (mLruMap.size() != mDataCount)) - { - // ERROR. - std::cerr << "RsMemCache::resize() CONSISTENCY ERROR"; - std::cerr << std::endl; - std::cerr << "\tmDataMap.size() = " << mDataMap.size(); - std::cerr << std::endl; - std::cerr << "\tmLruMap.size() = " << mLruMap.size(); - std::cerr << std::endl; - std::cerr << "\tmDataCount = " << mDataCount; - std::cerr << std::endl; - } - - if (mDataCount > mMaxSize) - { - count_to_clear = mDataCount - mMaxSize; -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::resize() to_clear: " << count_to_clear; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - } - } - - if (count_to_clear > 0) - { - discard_LRU(count_to_clear); - } - return true; -} - - - -template bool RsMemCache::discard_LRU(int count_to_clear) -{ - while(count_to_clear > 0) - { - typename std::multimap::iterator mit = mLruMap.begin(); - if (mit != mLruMap.end()) - { - Key key = mit->second; - mLruMap.erase(mit); - - /* now clear from real cache */ - //std::map >::iterator it; - typename std::map::iterator it; - it = mDataMap.find(key); - if (it == mDataMap.end()) - { - // ERROR - std::cerr << "RsMemCache::discard_LRU(): ERROR Missing key: " << key; - std::cerr << std::endl; - return false; - } - else - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::discard_LRU() removing: " << key; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - mDataMap.erase(it); - mDataCount--; - mStats_dropped++; - } - } - else - { - // No More Data, ERROR. -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::discard_LRU(): INFO more more cache data"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - return true; - } - count_to_clear--; - } - return true; -} - -// These aren't templated functions. -template void RsMemCache::printStats(std::ostream &out) -{ - typename std::multimap::iterator mit = mLruMap.begin(); - rstime_t age = 0; - if (mit != mLruMap.end()) - { - age = time(NULL) - mit->first; - } - - out << "RsMemCache<" << mName << ">::printStats() Size: " << mDataCount << " Size2: " << mDataMap.size() << " Size3: " << mLruMap.size() << " MaxSize: " << mMaxSize << " LRU Age: " << age; - out << std::endl; - - out << "\tInsertions: " << mStats_inserted << " Drops: " << mStats_dropped; - out << std::endl; - - out << "\tCache Hits: " << mStats_iscached << " Misses: " << mStats_cachemiss; - out << std::endl; - - out << "\tAccess Hits: " << mStats_access << " Misses: " << mStats_accessmiss; - out << std::endl; -} - -template void RsMemCache::clearStats() -{ - mStats_inserted = 0; - mStats_dropped = 0; - mStats_iscached = 0; - mStats_cachemiss = 0; - mStats_access = 0; - mStats_accessmiss = 0; -} - - - - -#endif // RS_UTIL_MEM_CACHE diff --git a/libretroshare/src/util/rsmemory.cc b/libretroshare/src/util/rsmemory.cc deleted file mode 100644 index 2b162c77d..000000000 --- a/libretroshare/src/util/rsmemory.cc +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsmemory.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include "util/rsmemory.h" - -void *rs_malloc(size_t size) -{ - static const size_t SAFE_MEMALLOC_THRESHOLD = 1024*1024*1024 ; // 1Gb should be enough for everything! - - if(size == 0) - { - std::cerr << "(EE) Memory allocation error. A chunk of size 0 was requested. Callstack:" << std::endl; - print_stacktrace() ; - return NULL ; - } - - if(size > SAFE_MEMALLOC_THRESHOLD) - { - std::cerr << "(EE) Memory allocation error. A chunk of size larger than " << SAFE_MEMALLOC_THRESHOLD << " was requested. Callstack:" << std::endl; - print_stacktrace() ; - return NULL ; - } - - void *mem = malloc(size) ; - - if(mem == NULL) - { - std::cerr << "(EE) Memory allocation error for a chunk of " << size << " bytes. Callstack:" << std::endl; - print_stacktrace() ; - return NULL ; - } - - return mem ; -} - diff --git a/libretroshare/src/util/rsmemory.h b/libretroshare/src/util/rsmemory.h deleted file mode 100644 index eb2889a6f..000000000 --- a/libretroshare/src/util/rsmemory.h +++ /dev/null @@ -1,157 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsmemory.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Cyril Soler * - * Copyright 2019-2020 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "util/stacktrace.h" - -/** - * @brief Shorthand macro to declare optional functions output parameters - * To define an optional output paramether use the following syntax - * -\code{.cpp} -bool myFunnyFunction( - int mandatoryParamether, - BigType& myOptionalOutput = RS_DEFAULT_STORAGE_PARAM(BigType) ) -\endcode - * - * The function caller then can call myFunnyFunction either passing - * myOptionalOutput parameter or not. - * @see RsGxsChannels methods for real usage examples. - * - * @details - * When const references are used to pass function parameters it is easy do make - * those params optional by defining a default value in the function - * declaration, because a temp is accepted as default parameter in those cases. - * It is not as simple when one want to make optional a non-const reference - * parameter that is usually used as output, in that case as a temp is in theory - * not acceptable. - * Yet it is possible to overcome that limitation with the following trick: - * If not passed as parameter the storage for the output parameter can be - * dinamically allocated directly by the function call, to avoid leaking memory - * on each function call the pointer to that storage is made unique so once the - * function returns it goes out of scope and is automatically deleted. - * About performance overhead: std::unique_ptr have very good performance and - * modern compilers may be even able to avoid the dynamic allocation in this - * case, any way the allocation would only happen if the parameter is not - * passed, so any effect on performace would happen only in case where the - * function is called without the parameter. - */ -#define RS_DEFAULT_STORAGE_PARAM(Type,...) *std::unique_ptr(new Type(__VA_ARGS__)) - -/** @brief Safely dynamic cast between std::unique_ptr of different types - * std::unique_ptr semantic rely on the invariant that only one instance own - * the object, when casting between differents types one would be tempted to do - * it in a one liner that easly end up breaking that condition ending up in a - * double delete and crash or in a silent memleak. - * With this function one can do that with same comfort of a plain dynamic_cast, - * plus the std::unique_ptr safety. - * @param[inout] src reference to source pointer. If the cast is successfull it - * is released, otherwise it is left untouched. - * @param[out] dst reference to destination pointer. If the cast is successful - * it get reseated to the object address, otherwise it is left untouched. - * @return true on success, false otherwise - */ -template -bool rs_unique_cast( - std::unique_ptr& src, std::unique_ptr& dst ) -{ - T_DST* dstPtr = dynamic_cast(src.get()); - if(dstPtr) - { - src.release(); - dst.reset(dstPtr); - return true; - } - return false; -} - -/** Mark a pointer as non-owned aka it must not be deleted/freed in that context. - * If a function take an `rs_view_ptr` as paramether it means that she will not - * own (aka free/delete) the passed memory, instead the caller is in charge of - * managing it. If a function return an `rs_view_ptr` it means the memory is - * managed internally and the caller should not call free/delete on it. - * @see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1408r0.pdf */ -template using rs_view_ptr = T*; - -/** Mark a pointer as owned aka the receiving context is in charge of dealing - * with it by free/delete once finished. - * If a function take an `rs_owner_ptr` as paramether it means that she will own - * (aka free/delete when finished using it) the passed memory, instead the - * caller is NOT in charge of managing it. - * If a function return an `rs_owner_ptr` it means the memory is NOT managed - * internally and the caller should call free/delete on it once finished using - * it. - * @see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1408r0.pdf */ -template using rs_owner_ptr = T*; - -void *rs_malloc(size_t size) ; - -/** @deprecated use std::unique_ptr instead -// This is a scope guard to release the memory block when going of of the current scope. -// Can be very useful to auto-delete some memory on quit without the need to call free each time. -// -// Usage: -// -// { -// TemporaryMemoryHolder mem(size) ; -// -// if(mem != NULL) -// [ do something ] ; -// -// memcopy(mem, some_other_memory, size) ; -// -// [do something] -// -// } // mem gets freed automatically -*/ -class RsTemporaryMemory -{ -public: - explicit RsTemporaryMemory(size_t s) - { - _mem = (unsigned char *)rs_malloc(s) ; - - if(_mem) - _size = s ; - else - _size = 0 ; - } - - operator unsigned char *() { return _mem ; } - - size_t size() const { return _size ; } - - ~RsTemporaryMemory() { free(_mem); } - -private: - unsigned char *_mem ; - size_t _size ; - - // make it noncopyable - RsTemporaryMemory& operator=(const RsTemporaryMemory&) { return *this ;} - RsTemporaryMemory(const RsTemporaryMemory&) {} -}; diff --git a/libretroshare/src/util/rsnet.cc b/libretroshare/src/util/rsnet.cc deleted file mode 100644 index 1e5f79181..000000000 --- a/libretroshare/src/util/rsnet.cc +++ /dev/null @@ -1,176 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsnet.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 Robert Fernie * - * Copyright 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#include "util/rsnet.h" -#include "util/rsthreads.h" -#include "util/rsstring.h" -#include "util/rsmemory.h" - -#ifdef WINDOWS_SYS -#else -#include -#endif - -#include - -/* enforce LITTLE_ENDIAN on Windows */ -#ifdef WINDOWS_SYS - #define BYTE_ORDER 1234 - #define LITTLE_ENDIAN 1234 - #define BIG_ENDIAN 4321 -#endif - -#ifndef ntohll -uint64_t ntohll(uint64_t x) -{ -#ifdef BYTE_ORDER - #if BYTE_ORDER == BIG_ENDIAN - return x; - #elif BYTE_ORDER == LITTLE_ENDIAN - - uint32_t top = (uint32_t) (x >> 32); - uint32_t bot = (uint32_t) (0x00000000ffffffffULL & x); - - uint64_t rev = ((uint64_t) ntohl(top)) | (((uint64_t) ntohl(bot)) << 32); - - return rev; - #else - #error "ENDIAN determination Failed" - #endif -#else - #error "ENDIAN determination Failed (BYTE_ORDER not defined)" -#endif - -} -#endif -#ifndef htonll -uint64_t htonll(uint64_t x) -{ - return ntohll(x); -} -#endif - -void sockaddr_clear(struct sockaddr_in *addr) -{ - memset(addr, 0, sizeof(struct sockaddr_in)); - addr->sin_family = AF_INET; -} - -bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr) -{ - addrinfo hint; memset(&hint, 0, sizeof(hint)); - hint.ai_family = AF_INET; - addrinfo* info = nullptr; - int res = getaddrinfo(hostname.c_str(), nullptr, &hint, &info); - - bool ok = true; - if(res > 0 || !info || !info->ai_addr) - { - std::cerr << __PRETTY_FUNCTION__ << "(EE) getaddrinfo returned error " - << res << " on string \"" << hostname << "\"" << std::endl; - returned_addr.s_addr = 0; - ok = false; - } - else - returned_addr.s_addr = ((sockaddr_in*)info->ai_addr)->sin_addr.s_addr; - - if(info) freeaddrinfo(info); - - return ok; -} - -bool isValidNet(const struct in_addr *addr) -{ - // invalid address. - if((*addr).s_addr == INADDR_NONE) - return false; - if((*addr).s_addr == 0) - return false; - // should do more tests. - return true; -} - - -bool isLoopbackNet(const struct in_addr *addr) -{ - in_addr_t taddr = ntohl(addr->s_addr); - return (taddr == (127 << 24 | 1)); -} - -bool isPrivateNet(const struct in_addr *addr) -{ - in_addr_t taddr = ntohl(addr->s_addr); - - if ( (taddr>>24 == 10) || // 10.0.0.0/8 - (taddr>>20 == (172<<4 | 16>>4)) || // 172.16.0.0/12 - (taddr>>16 == (192<<8 | 168)) || // 192.168.0.0/16 - (taddr>>16 == (169<<8 | 254)) ) // 169.254.0.0/16 - return true; - - return false; -} - -bool isLinkLocalNet(const struct in_addr *addr) -{ - in_addr_t taddr = ntohl(addr->s_addr); - if ( taddr>>16 == (169<<8 | 254) ) return true; // 169.254.0.0/16 - - return false; -} - -bool isExternalNet(const struct in_addr *addr) -{ - if (!isValidNet(addr)) - { - return false; - } - if (isLoopbackNet(addr)) - { - return false; - } - if (isPrivateNet(addr)) - { - return false; - } - return true; -} - -std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr) -{ - out << "[" << rs_inet_ntoa(addr.sin_addr) << ":"; - out << htons(addr.sin_port) << "]"; - return out; -} - -std::ostream& operator<<(std::ostream& o, const sockaddr_storage& addr) -{ return o << sockaddr_storage_tostring(addr); } - -/* thread-safe version of inet_ntoa */ - -std::string rs_inet_ntoa(struct in_addr in) -{ - std::string str; - uint8_t *bytes = (uint8_t *) &(in.s_addr); - rs_sprintf(str, "%u.%u.%u.%u", (int) bytes[0], (int) bytes[1], (int) bytes[2], (int) bytes[3]); - return str; -} diff --git a/libretroshare/src/util/rsnet.h b/libretroshare/src/util/rsnet.h deleted file mode 100644 index cad2c116a..000000000 --- a/libretroshare/src/util/rsnet.h +++ /dev/null @@ -1,162 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsnet.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 Robert Fernie * - * Copyright 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_UNIVERSAL_NETWORK_HEADER -#define RS_UNIVERSAL_NETWORK_HEADER - -#include -#include /* Included because GCC4.4 wants it */ -#include /* Included because GCC4.4 wants it */ -#include - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - -#include -#include -#include -#include - -#include -#include - -#else - -#include -typedef uint32_t in_addr_t; - -int inet_aton(const char *name, struct in_addr *addr); - -// Missing defines in MinGW -#ifndef MSG_WAITALL -#define MSG_WAITALL 8 -#endif - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - -/** - * Workaround for binary compatibility between Windows XP (which miss - * IPV6_V6ONLY define), and newer Windows that has it. - * @see http://lua-users.org/lists/lua-l/2013-04/msg00191.html - */ -#ifndef IPV6_V6ONLY -# define IPV6_V6ONLY 27 -#endif - -/* 64 bit conversions */ -#ifndef ntohll -uint64_t ntohll(uint64_t x); -#endif -#ifndef htonll -uint64_t htonll(uint64_t x); -#endif - -/* blank a network address */ -void sockaddr_clear(struct sockaddr_in *addr); - -/* determine network type (moved from pqi/pqinetwork.cc) */ -bool isValidNet(const struct in_addr *addr); -bool isLoopbackNet(const struct in_addr *addr); -bool isPrivateNet(const struct in_addr *addr); -bool isLinkLocalNet(const struct in_addr *addr); -bool isExternalNet(const struct in_addr *addr); - -// uses a re-entrant version of gethostbyname -bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr) ; - -std::ostream& operator<<(std::ostream& o, const sockaddr_in&); -std::ostream& operator<<(std::ostream& o, const sockaddr_storage&); - -/* thread-safe version of inet_ntoa */ -std::string rs_inet_ntoa(struct in_addr in); - - -/***************************/ -// sockaddr_storage fns. - -int rs_bind(int fd, const sockaddr_storage& addr); - -void sockaddr_storage_clear(struct sockaddr_storage &addr); - -// mods. -bool sockaddr_storage_zeroip(struct sockaddr_storage &addr); - -/** - * @brief Use this function to copy sockaddr_storage. - * - * POSIX does not require that objects of type sockaddr_storage can be copied - * as aggregates thus it is unsafe to aggregate copy ( operator = ) - * sockaddr_storage and unexpected behaviors may happens due to padding - * and alignment. - * - * @see https://sourceware.org/bugzilla/show_bug.cgi?id=20111 - * @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71120 - */ -bool sockaddr_storage_copy(const sockaddr_storage& src, sockaddr_storage& dst); - -bool sockaddr_storage_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src); -uint16_t sockaddr_storage_port(const struct sockaddr_storage &addr); -bool sockaddr_storage_setport(struct sockaddr_storage &addr, uint16_t port); - -bool sockaddr_storage_setipv4(struct sockaddr_storage &addr, const sockaddr_in *addr_ipv4); -bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6 *addr_ipv6); - -bool sockaddr_storage_inet_pton( sockaddr_storage &addr, - const std::string& ipStr ); -bool sockaddr_storage_ipv4_aton(struct sockaddr_storage &addr, const char *name); - -bool sockaddr_storage_ipv4_setport(struct sockaddr_storage &addr, const uint16_t port); - -bool sockaddr_storage_ipv4_to_ipv6(sockaddr_storage &addr); -bool sockaddr_storage_ipv6_to_ipv4(sockaddr_storage &addr); - -// comparisons. -bool operator<(const struct sockaddr_storage &a, const struct sockaddr_storage &b); - -bool sockaddr_storage_same(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); -bool sockaddr_storage_samefamily(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); -bool sockaddr_storage_sameip(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); - -// string, -std::string sockaddr_storage_tostring(const struct sockaddr_storage &addr); -bool sockaddr_storage_fromString(const std::string& str, sockaddr_storage &addr); -std::string sockaddr_storage_familytostring(const struct sockaddr_storage &addr); -std::string sockaddr_storage_iptostring(const struct sockaddr_storage &addr); -std::string sockaddr_storage_porttostring(const struct sockaddr_storage &addr); -void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputString = NULL); - -// net checks. -bool sockaddr_storage_isnull(const struct sockaddr_storage &addr); -bool sockaddr_storage_isValidNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_isLoopbackNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_isPrivateNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_isLinkLocalNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_isLinkLocalNet(const sockaddr_storage &addr); -bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr); - -bool sockaddr_storage_inet_ntop(const sockaddr_storage &addr, std::string &dst); - -int rs_setsockopt( int sockfd, int level, int optname, - const uint8_t *optval, uint32_t optlen ); - -#endif /* RS_UNIVERSAL_NETWORK_HEADER */ diff --git a/libretroshare/src/util/rsnet_ss.cc b/libretroshare/src/util/rsnet_ss.cc deleted file mode 100644 index c084f516e..000000000 --- a/libretroshare/src/util/rsnet_ss.cc +++ /dev/null @@ -1,1282 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsnet_ss.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 Robert Fernie * - * Copyright 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * 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 . * - * * - *******************************************************************************/ - -#include "util/rsurl.h" - -#include -#include -#include - -#ifdef WINDOWS_SYS -# include -/** Provides Linux like accessor for in6_addr.s6_addr16 for Windows. - * Yet Windows doesn't provide 32 bits accessors so there is no way to use - * in6_addr.s6_addr32 crossplatform. - */ -# define s6_addr16 u.Word -#else -# include -# include -# include -# ifdef __APPLE__ -/// Provides Linux like accessor for in6_addr.s6_addr16 for Mac. -# define s6_addr16 __u6_addr.__u6_addr16 -#endif // __APPLE__ -#endif // WINDOWS_SYS - -#include "util/rsnet.h" -#include "util/rsstring.h" -#include "pqi/pqinetwork.h" -#include "util/stacktrace.h" - -/***************************** Internal Helper Fns ******************************/ - -/******************************** Casting **************************************/ -struct sockaddr_in *to_ipv4_ptr(struct sockaddr_storage &addr); -struct sockaddr_in6 *to_ipv6_ptr(struct sockaddr_storage &addr); - -const struct sockaddr_in *to_const_ipv4_ptr(const struct sockaddr_storage &addr); -const struct sockaddr_in6 *to_const_ipv6_ptr(const struct sockaddr_storage &addr); - - -/******************************** Set / Clear ***********************************/ - -bool sockaddr_storage_ipv4_zeroip(struct sockaddr_storage &addr); -bool sockaddr_storage_ipv4_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src); - -uint16_t sockaddr_storage_ipv4_port(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv4_setport(struct sockaddr_storage &addr, uint16_t port); - -bool sockaddr_storage_ipv6_zeroip(struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src); - -uint16_t sockaddr_storage_ipv6_port(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_setport(struct sockaddr_storage &addr, uint16_t port); - -/******************************** Comparisions **********************************/ - -bool sockaddr_storage_ipv4_lessthan(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); -bool sockaddr_storage_ipv4_same(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); -bool sockaddr_storage_ipv4_sameip(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); - -bool sockaddr_storage_ipv6_lessthan(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); -bool sockaddr_storage_ipv6_same(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); -bool sockaddr_storage_ipv6_sameip(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); - - -/********************************* Output ***********************************/ -std::string sockaddr_storage_ipv4_iptostring(const struct sockaddr_storage &addr); -std::string sockaddr_storage_ipv6_iptostring(const struct sockaddr_storage &addr); - -/********************************* Net Checks ***********************************/ -bool sockaddr_storage_ipv4_isnull(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv4_isValidNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv4_isLoopbackNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv4_isPrivateNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv4_isExternalNet(const struct sockaddr_storage &addr); - -bool sockaddr_storage_ipv6_isnull(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_isValidNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_isLoopbackNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_isPrivateNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_isExternalNet(const struct sockaddr_storage &addr); - - -/***************************/ - -/******************************** Socket Fns ***********************************/ -// Standard bind, on OSX anyway will not accept a longer socklen for IPv4. -// so hidding details behind function. -int rs_bind(int fd, const sockaddr_storage& addr) -{ -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - socklen_t len = 0; - switch (addr.ss_family) - { - case AF_INET: - len = sizeof(struct sockaddr_in); - break; - case AF_INET6: - len = sizeof(struct sockaddr_in6); - break; - } - - return bind(fd, reinterpret_cast(&addr), len); -} - - - - -/******************************** Set / Clear ***********************************/ - -void sockaddr_storage_clear(struct sockaddr_storage &addr) -{ - memset(&addr, 0, sizeof(addr)); -} - -// mods. -bool sockaddr_storage_zeroip(struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_zeroip()"; - std::cerr << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_zeroip(addr); - break; - case AF_INET6: - return sockaddr_storage_ipv6_zeroip(addr); - break; - default: - std::cerr << "sockaddr_storage_zeroip() invalid addr.ss_family clearing whole address"; - std::cerr << std::endl; - sockaddr_storage_clear(addr); - break; - } - return false; -} - -bool sockaddr_storage_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_copyip()" << std::endl; -#endif - - switch(src.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_copyip(dst, src); - break; - case AF_INET6: - return sockaddr_storage_ipv6_copyip(dst, src); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_copyip() Unknown ss_family: " << src.ss_family << std::endl; -#endif - break; - } - return false; -} - - -uint16_t sockaddr_storage_port(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_port()" << std::endl; -#endif - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_port(addr); - case AF_INET6: - return sockaddr_storage_ipv6_port(addr); - default: - std::cerr << "sockaddr_storage_port() invalid addr.ss_family" << std::endl; -#ifdef SS_DEBUG - sockaddr_storage_dump(addr); - print_stacktrace(); -#endif - break; - } - return 0; -} - -bool sockaddr_storage_setport(struct sockaddr_storage &addr, uint16_t port) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_setport()" << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_setport(addr, port); - break; - case AF_INET6: - return sockaddr_storage_ipv6_setport(addr, port); - break; - default: - std::cerr << "sockaddr_storage_setport() invalid addr.ss_family" << std::endl; - break; - } - return false; -} - - -bool sockaddr_storage_setipv4(struct sockaddr_storage &addr, const sockaddr_in *addr_ipv4) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_setipv4()"; - std::cerr << std::endl; -#endif - - sockaddr_storage_clear(addr); - struct sockaddr_in *ipv4_ptr = to_ipv4_ptr(addr); - - ipv4_ptr->sin_family = AF_INET; - ipv4_ptr->sin_addr = addr_ipv4->sin_addr; - ipv4_ptr->sin_port = addr_ipv4->sin_port; - - return true; -} - -bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6 *addr_ipv6) -{ - std::cerr << "sockaddr_storage_setipv6()" << std::endl; - - sockaddr_storage_clear(addr); - struct sockaddr_in6 *ipv6_ptr = to_ipv6_ptr(addr); - - ipv6_ptr->sin6_family = AF_INET6; - ipv6_ptr->sin6_addr = addr_ipv6->sin6_addr; - ipv6_ptr->sin6_port = addr_ipv6->sin6_port; - - return true; -} - -#ifdef WINDOWS_SYS -int inet_pton(int af, const char *src, void *dst) -{ - sockaddr_storage ss; - int size = sizeof(ss); - char src_copy[INET6_ADDRSTRLEN+1]; - - ZeroMemory(&ss, sizeof(ss)); - /* stupid non-const API */ - strncpy (src_copy, src, INET6_ADDRSTRLEN+1); - src_copy[INET6_ADDRSTRLEN] = 0; - - if (WSAStringToAddressA(src_copy, af, NULL, (sockaddr *)&ss, &size) == 0) - { - switch(af) - { - case AF_INET: - *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr; - return 1; - case AF_INET6: - *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr; - return 1; - } - } - return 0; -} -#endif - -bool sockaddr_storage_inet_pton( sockaddr_storage &addr, - const std::string& ipStr ) -{ -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - struct sockaddr_in6 * addrv6p = (struct sockaddr_in6 *) &addr; - struct sockaddr_in * addrv4p = (struct sockaddr_in *) &addr; - - if ( 1 == inet_pton(AF_INET6, ipStr.c_str(), &(addrv6p->sin6_addr)) ) - { - addr.ss_family = AF_INET6; - return true; - } - else if ( 1 == inet_pton(AF_INET, ipStr.c_str(), &(addrv4p->sin_addr)) ) - { - addr.ss_family = AF_INET; - return sockaddr_storage_ipv4_to_ipv6(addr); - } - - return false; -} - - -bool sockaddr_storage_ipv4_aton(struct sockaddr_storage &addr, const char *name) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_aton()"; - std::cerr << std::endl; -#endif - - struct sockaddr_in *ipv4_ptr = to_ipv4_ptr(addr); - ipv4_ptr->sin_family = AF_INET; - return (1 == inet_aton(name, &(ipv4_ptr->sin_addr))); -} - -bool sockaddr_storage_ipv4_to_ipv6(sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - if ( addr.ss_family == AF_INET6 ) return true; - - if ( addr.ss_family == AF_INET ) - { - sockaddr_in & addr_ipv4 = (sockaddr_in &) addr; - sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr; - - uint32_t ip = addr_ipv4.sin_addr.s_addr; - uint16_t port = addr_ipv4.sin_port; - - sockaddr_storage_clear(addr); - addr_ipv6.sin6_family = AF_INET6; - addr_ipv6.sin6_port = port; - addr_ipv6.sin6_addr.s6_addr16[5] = htons(0xffff); - memmove( reinterpret_cast(&(addr_ipv6.sin6_addr.s6_addr16[6])), - reinterpret_cast(&ip), 4 ); - return true; - } - - return false; -} - -bool sockaddr_storage_ipv6_to_ipv4(sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - if ( addr.ss_family == AF_INET ) return true; - - if ( addr.ss_family == AF_INET6 ) - { - sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr; - bool ipv4m = addr_ipv6.sin6_addr.s6_addr16[5] == htons(0xffff); - for ( int i = 0; ipv4m && i < 5 ; ++i ) - ipv4m &= addr_ipv6.sin6_addr.s6_addr16[i] == htons(0x0000); - - if(ipv4m) - { - uint32_t ip; - memmove( reinterpret_cast(&ip), - reinterpret_cast(&(addr_ipv6.sin6_addr.s6_addr16[6])), - 4 ); - uint16_t port = addr_ipv6.sin6_port; - - sockaddr_in & addr_ipv4 = (sockaddr_in &) addr; - - sockaddr_storage_clear(addr); - addr_ipv4.sin_family = AF_INET; - addr_ipv4.sin_port = port; - addr_ipv4.sin_addr.s_addr = ip; - - return true; - } - } - - return false; -} - - -/******************************** Comparisions **********************************/ - -bool operator<(const struct sockaddr_storage &a, const struct sockaddr_storage &b) -{ - if (!sockaddr_storage_samefamily(a, b)) - { - return (a.ss_family < b.ss_family); - } - - switch(a.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_lessthan(a, b); - break; - case AF_INET6: - return sockaddr_storage_ipv6_lessthan(a, b); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_operator<() INVALID Family - error"; - std::cerr << std::endl; -#endif - break; - } - return false; -} - - -bool sockaddr_storage_same(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_same()"; - std::cerr << std::endl; -#endif - - if (!sockaddr_storage_samefamily(addr, addr2)) - return false; - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_same(addr, addr2); - break; - case AF_INET6: - return sockaddr_storage_ipv6_same(addr, addr2); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_same() INVALID Family - error"; - std::cerr << std::endl; -#endif - break; - } - return false; -} - - -bool sockaddr_storage_samefamily(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_samefamily()"; - std::cerr << std::endl; -#endif - - return (addr.ss_family == addr2.ss_family); -} - -bool sockaddr_storage_sameip(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_sameip()"; - std::cerr << std::endl; -#endif - - if (!sockaddr_storage_samefamily(addr, addr2)) - return false; - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_sameip(addr, addr2); - break; - case AF_INET6: - return sockaddr_storage_ipv6_sameip(addr, addr2); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_sameip() INVALID Family - error"; - std::cerr << std::endl; -#endif - break; - } - return false; -} - -/********************************* Output ***********************************/ - -std::string sockaddr_storage_tostring(const struct sockaddr_storage &addr) -{ - RsUrl url; - - switch(addr.ss_family) - { - case AF_INET: - url.setScheme("ipv4"); - break; - case AF_INET6: - url.setScheme("ipv6"); - break; - default: - return "AF_INVALID"; - } - - url.setHost(sockaddr_storage_iptostring(addr)) - .setPort(sockaddr_storage_port(addr)); - - return url.toString(); -} - -bool sockaddr_storage_fromString(const std::string& str, sockaddr_storage &addr) -{ - RsUrl url(str); - bool valid = sockaddr_storage_inet_pton(addr, url.host()); - if(url.hasPort()) sockaddr_storage_setport(addr, url.port()); - return valid; -} - -void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputString) -{ - // This function must not rely on others sockaddr_storage_* - - std::stringstream output; - output << "sockaddr_storage_dump(addr) "; - - switch (addr.ss_family) - { - case AF_INET: - { - const sockaddr_in * in = (const sockaddr_in *) & addr; - output << "addr.ss_family = AF_INET"; - output << " in->sin_addr = "; - output << inet_ntoa(in->sin_addr); - output << " in->sin_port = "; - output << in->sin_port; - break; - } - case AF_INET6: - { - const sockaddr_in6 * in6 = (const sockaddr_in6 *) & addr; - std::string addrStr = "INVALID_IPV6"; - sockaddr_storage_inet_ntop(addr, addrStr); - output << "addr.ss_family = AF_INET6"; - output << " in6->sin6_addr = "; - output << addrStr; - output << " in6->sin6_scope_id = "; - output << in6->sin6_scope_id; - output << " in6->sin6_port = "; - output << in6->sin6_port; - break; - } - default: - { - output << "unknown addr.ss_family "; - const uint8_t * buf = reinterpret_cast(&addr); - for( uint32_t i = 0; i < sizeof(addr); ++i ) - output << std::setw(2) << std::setfill('0') << std::hex << +buf[i]; - /* The unary +buf[i] operation forces a no-op type conversion to an int - * with the correct sign */ - } - } - - if(outputString) - { - outputString->append(output.str() + "\n"); -#ifdef SS_DEBUG - std::cerr << output.str() << std::endl; -#endif - } - else - std::cerr << output.str() << std::endl; -} - -std::string sockaddr_storage_familytostring(const struct sockaddr_storage &addr) -{ - std::string output; - switch(addr.ss_family) - { - case AF_INET: - output = "IPv4"; - break; - case AF_INET6: - output = "IPv6"; - break; - default: - output = "AF_INVALID"; -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " Got invalid address!" - << std::endl; - sockaddr_storage_dump(addr); - print_stacktrace(); -#endif - break; - } - return output; -} - -std::string sockaddr_storage_iptostring(const struct sockaddr_storage &addr) -{ - std::string output; - switch(addr.ss_family) - { - case AF_INET: - output = sockaddr_storage_ipv4_iptostring(addr); - break; - case AF_INET6: - output = sockaddr_storage_ipv6_iptostring(addr); - break; - default: - output = "INVALID_IP"; - std::cerr << __PRETTY_FUNCTION__ << " Got invalid IP!" << std::endl; -#ifdef SS_DEBUG - sockaddr_storage_dump(addr); - print_stacktrace(); -#endif - break; - } - return output; -} - -std::string sockaddr_storage_porttostring(const struct sockaddr_storage &addr) -{ - std::string output; - uint16_t port = sockaddr_storage_port(addr); - rs_sprintf(output, "%u", port); - return output; -} - - -/********************************* Net Checks ***********************************/ -bool sockaddr_storage_isnull(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isnull()"; - std::cerr << std::endl; -#endif - - if (addr.ss_family == 0) - return true; - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_isnull(addr); - break; - case AF_INET6: - return sockaddr_storage_ipv6_isnull(addr); - break; - default: - return true; - break; - } - return true; -} - -bool sockaddr_storage_isValidNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isValidNet()" << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_isValidNet(addr); - case AF_INET6: - return sockaddr_storage_ipv6_isValidNet(addr); - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isValidNet() INVALID Family" << std::endl; - sockaddr_storage_dump(addr); -#endif - break; - } - return false; -} - -bool sockaddr_storage_isLoopbackNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isLoopbackNet()"; - std::cerr << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_isLoopbackNet(addr); - break; - case AF_INET6: - return sockaddr_storage_ipv6_isLoopbackNet(addr); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isLoopbackNet() INVALID Family - error: " << sockaddr_storage_iptostring(addr); - std::cerr << std::endl; -#endif - break; - } - return false; -} - - -bool sockaddr_storage_isPrivateNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isPrivateNet()"; - std::cerr << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_isPrivateNet(addr); - break; - case AF_INET6: - return sockaddr_storage_ipv6_isPrivateNet(addr); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isPrivateNet() INVALID Family - error: " << sockaddr_storage_iptostring(addr); - std::cerr << std::endl; -#endif - break; - } - return false; -} - -bool sockaddr_storage_isLinkLocalNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return isLinkLocalNet(&(to_const_ipv4_ptr(addr)->sin_addr)); - case AF_INET6: - return sockaddr_storage_ipv6_isLinkLocalNet(addr); - default: -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ <<" INVALID Family:" << std::endl; - sockaddr_storage_dump(addr); -#endif - break; - } - - return false; -} - -bool sockaddr_storage_ipv6_isLinkLocalNet(const sockaddr_storage &addr) -{ - if(addr.ss_family != AF_INET6) return false; - - const sockaddr_in6 * addr6 = (const sockaddr_in6 *) &addr; - uint16_t mask = htons(0xffc0); - uint16_t llPrefix = htons(0xfe80); - return ((addr6->sin6_addr.s6_addr16[0] & mask ) == llPrefix); -} - - -bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isExternalNet()"; - std::cerr << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_isExternalNet(addr); - break; - case AF_INET6: - return sockaddr_storage_ipv6_isExternalNet(addr); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isExternalNet() INVALID Family - error"; - std::cerr << std::endl; -#endif - break; - } - return false; -} - - - - - -/***************************** Internal Helper Fns ******************************/ - - -/******************************** Casting **************************************/ - -struct sockaddr_in *to_ipv4_ptr(struct sockaddr_storage &addr) -{ - struct sockaddr_in *ipv4_ptr = (struct sockaddr_in *) &addr; - return ipv4_ptr; -} - -struct sockaddr_in6 *to_ipv6_ptr(struct sockaddr_storage &addr) -{ - struct sockaddr_in6 *ipv6_ptr = (struct sockaddr_in6 *) &addr; - return ipv6_ptr; -} - -const struct sockaddr_in *to_const_ipv4_ptr(const struct sockaddr_storage &addr) -{ - const struct sockaddr_in *ipv4_ptr = (const struct sockaddr_in *) &addr; - return ipv4_ptr; -} - -const struct sockaddr_in6 *to_const_ipv6_ptr(const struct sockaddr_storage &addr) -{ - const struct sockaddr_in6 *ipv6_ptr = (const struct sockaddr_in6 *) &addr; - return ipv6_ptr; -} - - -/******************************** Set / Clear ***********************************/ - -bool sockaddr_storage_copy(const sockaddr_storage& src, sockaddr_storage& dst) -{ - if(&src == &dst) return true; - - switch(src.ss_family) - { - case AF_INET: - { - sockaddr_storage_clear(dst); - const sockaddr_in& ins(reinterpret_cast(src)); - sockaddr_in& ind(reinterpret_cast(dst)); - - ind.sin_family = AF_INET; - ind.sin_addr.s_addr = ins.sin_addr.s_addr; - ind.sin_port = ins.sin_port; - - return true; - } - case AF_INET6: - { - sockaddr_storage_clear(dst); - const sockaddr_in6& ins6(reinterpret_cast(src)); - sockaddr_in6& ind6(reinterpret_cast(dst)); - - ind6.sin6_family = AF_INET6; - for(int i=0; i<8; ++i) - ind6.sin6_addr.s6_addr16[i] = ins6.sin6_addr.s6_addr16[i]; - ind6.sin6_flowinfo = ins6.sin6_flowinfo; - ind6.sin6_port = ins6.sin6_port; - ind6.sin6_scope_id = ins6.sin6_scope_id; - - return true; - } - default: -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " Attempt to copy unknown family! " - << src.ss_family << " defaulting to memmove!" << std::endl; - sockaddr_storage_dump(src); - print_stacktrace(); -#endif // SS_DEBUG - memmove(&dst, &src, sizeof(sockaddr_storage)); - return true; - } -} - -bool sockaddr_storage_ipv4_zeroip(struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_zeroip()"; - std::cerr << std::endl; -#endif - - struct sockaddr_in *ipv4_ptr = to_ipv4_ptr(addr); - memset(&(ipv4_ptr->sin_addr), 0, sizeof(ipv4_ptr->sin_addr)); - return true; -} - - -bool sockaddr_storage_ipv4_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_copyip()"; - std::cerr << std::endl; -#endif - - struct sockaddr_in *dst_ptr = to_ipv4_ptr(dst); - const struct sockaddr_in *src_ptr = to_const_ipv4_ptr(src); - - dst_ptr->sin_family = AF_INET; - memcpy(&(dst_ptr->sin_addr), &(src_ptr->sin_addr), sizeof(src_ptr->sin_addr)); - return true; -} - -uint16_t sockaddr_storage_ipv4_port(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_port()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ipv4_ptr = to_const_ipv4_ptr(addr); - uint16_t port = ntohs(ipv4_ptr->sin_port); - return port; -} - -bool sockaddr_storage_ipv4_setport(struct sockaddr_storage &addr, uint16_t port) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_setport()"; - std::cerr << std::endl; -#endif - - struct sockaddr_in *ipv4_ptr = to_ipv4_ptr(addr); - ipv4_ptr->sin_port = htons(port); - return true; -} - -bool sockaddr_storage_ipv6_zeroip(struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_zeroip()"; - std::cerr << std::endl; -#endif - - struct sockaddr_in6 *ipv6_ptr = to_ipv6_ptr(addr); - memset(&(ipv6_ptr->sin6_addr), 0, sizeof(ipv6_ptr->sin6_addr)); - return true; -} - -bool sockaddr_storage_ipv6_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_copyip()" << std::endl; -#endif - - struct sockaddr_in6 *dst_ptr = to_ipv6_ptr(dst); - const struct sockaddr_in6 *src_ptr = to_const_ipv6_ptr(src); - - dst_ptr->sin6_family = AF_INET6; - memcpy(&(dst_ptr->sin6_addr), &(src_ptr->sin6_addr), sizeof(src_ptr->sin6_addr)); - return true; -} - -uint16_t sockaddr_storage_ipv6_port(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_port()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in6 *ipv6_ptr = to_const_ipv6_ptr(addr); - uint16_t port = ntohs(ipv6_ptr->sin6_port); - return port; -} - -bool sockaddr_storage_ipv6_setport(struct sockaddr_storage &addr, uint16_t port) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_setport()"; - std::cerr << std::endl; -#endif - - struct sockaddr_in6 *ipv6_ptr = to_ipv6_ptr(addr); - ipv6_ptr->sin6_port = htons(port); - return true; -} - - -/******************************** Comparisions **********************************/ - -bool sockaddr_storage_ipv4_lessthan(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_lessthan()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - const struct sockaddr_in *ptr2 = to_const_ipv4_ptr(addr2); - - if (ptr1->sin_addr.s_addr == ptr2->sin_addr.s_addr) - { - return ptr1->sin_port < ptr2->sin_port; - } - return (ptr1->sin_addr.s_addr < ptr2->sin_addr.s_addr); -} - -bool sockaddr_storage_ipv4_same(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_same()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - const struct sockaddr_in *ptr2 = to_const_ipv4_ptr(addr2); - - return (ptr1->sin_addr.s_addr == ptr2->sin_addr.s_addr) && - (ptr1->sin_port == ptr2->sin_port); -} - -bool sockaddr_storage_ipv4_sameip(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_sameip()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - const struct sockaddr_in *ptr2 = to_const_ipv4_ptr(addr2); - - return (ptr1->sin_addr.s_addr == ptr2->sin_addr.s_addr); -} - -// IPV6 -bool sockaddr_storage_ipv6_lessthan(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_lessthan()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in6 *ptr1 = to_const_ipv6_ptr(addr); - const struct sockaddr_in6 *ptr2 = to_const_ipv6_ptr(addr2); - - uint32_t *ip6addr1 = (uint32_t *) ptr1->sin6_addr.s6_addr; - uint32_t *ip6addr2 = (uint32_t *) ptr2->sin6_addr.s6_addr; - for(int i = 0; i < 4; i++) - { - if (ip6addr1[i] == ip6addr2[i]) - { - continue; - } - - return (ip6addr1[i] < ip6addr2[i]); - } - - return (ptr1->sin6_port < ptr2->sin6_port); -} - -bool sockaddr_storage_ipv6_same(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_same()"; - std::cerr << std::endl; -#endif - const struct sockaddr_in6 *ptr1 = to_const_ipv6_ptr(addr); - const struct sockaddr_in6 *ptr2 = to_const_ipv6_ptr(addr2); - - return sockaddr_storage_ipv6_sameip(addr, addr2) && (ptr1->sin6_port == ptr2->sin6_port); -} - -bool sockaddr_storage_ipv6_sameip(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_sameip()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in6 *ptr1 = to_const_ipv6_ptr(addr); - const struct sockaddr_in6 *ptr2 = to_const_ipv6_ptr(addr2); - - uint32_t *ip6addr1 = (uint32_t *) ptr1->sin6_addr.s6_addr; - uint32_t *ip6addr2 = (uint32_t *) ptr2->sin6_addr.s6_addr; - - for(int i = 0; i < 4; i++) - { - if (ip6addr1[i] != ip6addr2[i]) - { - return false; - } - } - return true; -} - -/********************************* Output ***********************************/ -std::string sockaddr_storage_ipv4_iptostring(const struct sockaddr_storage &addr) -{ - const struct sockaddr_in *ptr = to_const_ipv4_ptr(addr); - std::string output; - output = rs_inet_ntoa(ptr->sin_addr); - return output; -} - -std::string sockaddr_storage_ipv6_iptostring(const struct sockaddr_storage & addr) -{ - std::string addrStr; - sockaddr_storage_inet_ntop(addr, addrStr); - return addrStr; -} - - -/********************************* Net Checks ***********************************/ -bool sockaddr_storage_ipv4_isnull(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_isnull()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - if (ptr1->sin_family != AF_INET) - { - return true; - } - if ((ptr1->sin_addr.s_addr == 0) || (ptr1->sin_addr.s_addr == 1)) - { - return true; - } - return false; -} - -bool sockaddr_storage_ipv4_isValidNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_isValidNet()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - if (ptr1->sin_family != AF_INET) - { - return false; - } - return isValidNet(&(ptr1->sin_addr)); -} - - -bool sockaddr_storage_ipv4_isLoopbackNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_isLoopbackNet()"; - std::cerr << std::endl; -#endif - - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - if (ptr1->sin_family != AF_INET) - { - return false; - } - return isLoopbackNet(&(ptr1->sin_addr)); -} - -bool sockaddr_storage_ipv4_isPrivateNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_isPrivateNet()"; - std::cerr << std::endl; -#endif - - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - if (ptr1->sin_family != AF_INET) - { - return false; - } - return isPrivateNet(&(ptr1->sin_addr)); -} - -bool sockaddr_storage_ipv4_isExternalNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_isExternalNet()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - if (ptr1->sin_family != AF_INET) - { - return false; - } - return isExternalNet(&(ptr1->sin_addr)); -} - - -bool sockaddr_storage_ipv6_isnull(const struct sockaddr_storage& addr) -{ - const sockaddr_in6& addr6 = reinterpret_cast(addr); - - uint16_t nZero = htons(0); // anyway 0 should be the same in host and net - bool isZero = (addr6.sin6_addr.s6_addr16[7] == nZero); - for (int i=0; isZero && i<7; ++i) - isZero &= (addr6.sin6_addr.s6_addr16[i] == nZero); - - return nZero; -} - -bool sockaddr_storage_ipv6_isValidNet(const struct sockaddr_storage& addr) -{ - return !sockaddr_storage_ipv6_isnull(addr); -} - -bool sockaddr_storage_ipv6_isLoopbackNet(const struct sockaddr_storage& addr) -{ - const sockaddr_in6& addr6 = reinterpret_cast(addr); - bool isLoopBack = (addr6.sin6_addr.s6_addr16[7] == htons(0x0001)); - uint16_t nZero = htons(0); // anyway 0 should be the same in host and net - for (int i=0; isLoopBack && i<7; ++i) - isLoopBack &= (addr6.sin6_addr.s6_addr16[i] == nZero); - -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " " << sockaddr_storage_tostring(addr) - << " " << isLoopBack << std::endl; -#endif - - return isLoopBack; -} - -bool sockaddr_storage_ipv6_isPrivateNet(const struct sockaddr_storage &/*addr*/) -{ - /* It is unlikely that we end up connecting to an IPv6 address behind NAT - * W.R.T. RS it is probably better to consider all IPv6 as internal/local - * addresses as direct connection should be always possible. */ - - return true; -} - -bool sockaddr_storage_ipv6_isExternalNet(const struct sockaddr_storage &/*addr*/) -{ - /* It is unlikely that we end up connecting to an IPv6 address behind NAT - * W.R.T. RS it is probably better to consider all IPv6 as internal/local - * addresses as direct connection should be always possible. */ - - return false; -} - -bool sockaddr_storage_inet_ntop (const sockaddr_storage &addr, std::string &dst) -{ - bool success = false; - char ipStr[255]; - -#ifdef WINDOWS_SYS - // Use WSAAddressToString instead of InetNtop because the latter is missing - // on XP and is present only on Vista and newers - wchar_t wIpStr[255]; - long unsigned int len = 255; - sockaddr_storage tmp; - sockaddr_storage_clear(tmp); - sockaddr_storage_copyip(tmp, addr); - sockaddr * sptr = (sockaddr *) &tmp; - success = (0 == WSAAddressToString( sptr, sizeof(sockaddr_storage), NULL, wIpStr, &len )); - wcstombs(ipStr, wIpStr, len); -#else // WINDOWS_SYS - switch(addr.ss_family) - { - case AF_INET: - { - const struct sockaddr_in * addrv4p = (const struct sockaddr_in *) &addr; - success = inet_ntop( addr.ss_family, (const void *) &(addrv4p->sin_addr), ipStr, INET_ADDRSTRLEN ); - } - break; - case AF_INET6: - { - const struct sockaddr_in6 * addrv6p = (const struct sockaddr_in6 *) &addr; - success = inet_ntop( addr.ss_family, (const void *) &(addrv6p->sin6_addr), ipStr, INET6_ADDRSTRLEN ); - } - break; - } -#endif // WINDOWS_SYS - - dst = ipStr; - return success; -} - -int rs_setsockopt( int sockfd, int level, int optname, - const uint8_t *optval, uint32_t optlen ) -{ -#ifdef WINDOWS_SYS - return setsockopt( sockfd, level, optname, - reinterpret_cast(optval), optlen ); -#else - return setsockopt( sockfd, level, optname, - reinterpret_cast(optval), optlen ); -#endif // WINDOWS_SYS -} diff --git a/libretroshare/src/util/rsprint.cc b/libretroshare/src/util/rsprint.cc deleted file mode 100644 index 4e547736a..000000000 --- a/libretroshare/src/util/rsprint.cc +++ /dev/null @@ -1,175 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsprint.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2008 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "util/rsprint.h" -#include "util/rsstring.h" -#include -#include -#include -#include - -#ifdef WINDOWS_SYS -#include "util/rstime.h" -#include -#endif - -std::string RsUtil::NumberToString(uint64_t n,bool hex) -{ - std::ostringstream os ; - - if(hex) - os << std::hex ; - - os << n ; - os.flush() ; - - return os.str(); -} - -std::string RsUtil::BinToHex(const std::string &bin) -{ - return BinToHex(bin.c_str(), bin.length()); -} - -std::string RsUtil::BinToHex(const unsigned char *arr, const uint32_t len,uint32_t max_len) -{ - if(max_len > 0) - return BinToHex((char*)arr,std::min(max_len,len)) + ((len > max_len)?"...":"") ; - else - return BinToHex((char*)arr,len) ; -} -std::string RsUtil::BinToHex(const char *arr, const uint32_t len) -{ - std::string out; - - for(uint32_t j = 0; j < len; j++) - { - rs_sprintf_append(out, "%02x", (int32_t) (((const uint8_t *) arr)[j])); - } - - return out; -} - -std::string RsUtil::HashId(const std::string &id, bool reverse) -{ - std::string hash; - std::string tohash; - if (reverse) - { - std::string::const_reverse_iterator rit; - for(rit = id.rbegin(); rit != id.rend(); ++rit) - { - tohash += (*rit); - } - } - else - { - tohash = id; - } - - SHA_CTX *sha_ctx = new SHA_CTX; - uint8_t sha_hash[SHA_DIGEST_LENGTH]; - - SHA1_Init(sha_ctx); - SHA1_Update(sha_ctx, tohash.c_str(), tohash.length()); - SHA1_Final(sha_hash, sha_ctx); - - for(uint16_t i = 0; i < SHA_DIGEST_LENGTH; i++) - { - hash += sha_hash[i]; - } - - /* cleanup */ - delete sha_ctx; - - return hash; -} - -static int toHalfByte(char u,bool& ok) -{ - if(u >= 'a' && u <= 'f') return u-'a' + 0xa; - if(u >= 'A' && u <= 'F') return u-'A' + 0xa; - if(u >= '0' && u <= '9') return u-'0' + 0x0; - - ok = false ; - - return 0; -} - -bool RsUtil::HexToBin(const std::string& input,unsigned char *data, const uint32_t len) -{ - if(input.size() & 1) - return false ; - - if(len != input.size()/2) - return false ; - - bool ok = true ; - - for(uint32_t i=0;(i RsUtil::BinToSha256(const std::vector &in) -{ - std::vector out; - - SHA256_CTX *sha_ctx = new SHA256_CTX; - uint8_t sha_hash[SHA256_DIGEST_LENGTH] = {0}; - - SHA256_Init(sha_ctx); - SHA256_Update(sha_ctx, in.data(), in.size()); - SHA256_Final(sha_hash, sha_ctx); - - for(uint16_t i = 0; i < SHA256_DIGEST_LENGTH; i++) - { - out.push_back(sha_hash[i]); - } - - /* cleanup */ - delete sha_ctx; - return out; -} diff --git a/libretroshare/src/util/rsprint.h b/libretroshare/src/util/rsprint.h deleted file mode 100644 index dcaab6311..000000000 --- a/libretroshare/src/util/rsprint.h +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsprint.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2008 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSUTIL_PRINTFNS_H -#define RSUTIL_PRINTFNS_H - -#include -#include -#include - -namespace RsUtil { - -std::string BinToHex(const std::string &bin); -std::string BinToHex(const char *arr, const uint32_t len); - -// proxy function. When max_len>0 and len>max_len, only the first "max_len" bytes are writen to the string and "..." is happened. - -std::string BinToHex(const unsigned char *arr, const uint32_t len, uint32_t max_len=0); -bool HexToBin(const std::string& input,unsigned char *data, const uint32_t len); -std::string NumberToString(uint64_t n, bool hex=false); -std::string HashId(const std::string &id, bool reverse = false); -std::vector BinToSha256(const std::vector &in); - -//std::string AccurateTimeString(); - -} - -#endif diff --git a/libretroshare/src/util/rsrandom.cc b/libretroshare/src/util/rsrandom.cc deleted file mode 100644 index dc7d9ac67..000000000 --- a/libretroshare/src/util/rsrandom.cc +++ /dev/null @@ -1,146 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsrandom.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2010 Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "rsrandom.h" - -#include -#include -#include -#include - -uint32_t RsRandom::index = RsRandom::N; -std::vector RsRandom::MT(RsRandom::N,0u); -RsMutex RsRandom::rndMtx("RsRandom"); - -/* According to our tests (cyril+thunder), on both Windows and Linux does - * RAND_bytes init itself automatically at first call, from system-based - * unpredictable values, so that seeding is not even needed. - * This call still adds some randomness (not much actually, but it's always good - * to have anyway) */ -#ifdef WINDOWS_SYS -# include "util/rstime.h" -# ifdef WIN_PTHREADS_H -static bool auto_seed = RsRandom::seed( - (time(nullptr) + - static_cast(pthread_self()) *0x1293fe)^0x18e34a12 ); -# else // def WIN_PTHREADS_H -static bool auto_seed = RsRandom::seed( - (time(nullptr) + - static_cast(pthread_self().p)*0x1293fe)^0x18e34a12 ); -# endif // def WIN_PTHREADS_H -#endif - -bool RsRandom::seed(uint32_t s) -{ - RS_STACK_MUTEX(rndMtx); - - MT.resize(N,0) ; // because MT might not be already resized - - uint32_t j ; - MT[0]= s & 0xffffffffUL; - for (j=1; j> 30)) + j) & 0xffffffffUL ; - - // This *does not* replace the internal seed state of RAND_bytes(), but only *adds* entropy to the random pool - // So calling this method with the same value twice does not guarranty that the output of the random bytes - // will be the same. - - RAND_seed((unsigned char *)&MT[0],N*sizeof(uint32_t)) ; - locked_next_state() ; - - return true ; -} - -void RsRandom::random_bytes(unsigned char *data,uint32_t size) -{ - RAND_bytes(data,size) ; -} -void RsRandom::locked_next_state() -{ - RAND_bytes((unsigned char *)&MT[0],N*sizeof(uint32_t)) ; - index = 0 ; -} - -uint32_t RsRandom::random_u32() -{ - uint32_t y; - - { - RS_STACK_MUTEX(rndMtx); - - index++ ; - - if(index >= N) - locked_next_state(); - - y = MT[index] ; - } - -#ifdef UNNECESSARY_CODE - // Tempering - y ^= (y >> 11); - y ^= (y << 7 ) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); -#endif - - return y; -} - -uint64_t RsRandom::random_u64() -{ - return ((uint64_t)random_u32() << 32ul) + random_u32() ; -} - -float RsRandom::random_f32() -{ - return random_u32() / (float)(~(uint32_t)0) ; -} - -double RsRandom::random_f64() -{ - return random_u64() / (double)(~(uint64_t)0) ; -} - -/*static*/ std::string RsRandom::alphaNumeric(uint32_t length) -{ - std::string s; - while(s.size() < length) - { - uint8_t rChar; random_bytes(&rChar, 1); rChar = rChar % 123; - /* if(isalnum(val)) isalnum result may vary depend on locale!! */ - if( (rChar >= 48 && rChar <= 57) /* 0-9 */ || - (rChar >= 65 && rChar <= 90) /* A-Z */ || - (rChar >= 97 && rChar <= 122) /* a-z */ ) - s += static_cast(rChar); - } - - return s; -} - -/*static*/ std::string RsRandom::printable(uint32_t length) -{ - std::string ret(length, 0); - random_bytes(reinterpret_cast(&ret[0]), length); - for(uint32_t i=0; i * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - - -#include -#include - -#include "util/rsthreads.h" -#include "util/rsdeprecate.h" - -/** - * RsRandom provide a random number generator that is - * - thread safe - * - platform independent - * - fast - * - CRYPTOGRAPHICALLY SAFE, because it is based on openssl random number - * generator - */ -class RsRandom -{ -public: - static uint32_t random_u32(); - static uint64_t random_u64(); - static float random_f32(); - static double random_f64(); - - static bool seed(uint32_t s); - - static void random_bytes(uint8_t* data, uint32_t length); - - /// Return a random alphanumeric *[0-9,A-Z,a-z] string of the given lenght - static std::string alphaNumeric(uint32_t length); - - /** Return a random printable string of the given lenght */ - static std::string printable(uint32_t length); - - /** This return a printable string not an alphanumeric one @deprecated */ - RS_DEPRECATED_FOR("RsRandom::printable") - static inline std::string random_alphaNumericString(uint32_t length) - { return printable(length); } - -private: - static RsMutex rndMtx; - - static const uint32_t N = 1024; - - static void locked_next_state(); - static uint32_t index; - static std::vector MT; -}; - -/// @deprecated this alias is provided only for code retro-compatibility -using RSRandom RS_DEPRECATED_FOR(RsRandom) = RsRandom; diff --git a/libretroshare/src/util/rsrecogn.cc b/libretroshare/src/util/rsrecogn.cc deleted file mode 100644 index 5cc0a5e09..000000000 --- a/libretroshare/src/util/rsrecogn.cc +++ /dev/null @@ -1,656 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsrandom.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2013 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "pqi/pqi_base.h" - -#include "util/rsrecogn.h" -#include "util/radix64.h" -#include "util/rsstring.h" -#include "util/rsdir.h" - -#include "gxs/gxssecurity.h" - -#include -#include - -/*** - * #define DEBUG_RECOGN 1 - ***/ - -#define DEBUG_RECOGN 1 - -static std::string RecognKey = "MIICCgKCAgEA4/i2fy+zR27/H8fzphM8mR/Nz+yXjMJTtqKlCvEMQlyk7lKzDbKifNjGSiAXjSv3b9TRgMtje7hfEhs3//Oeu4KsCf6sz17aj2StBF579IdJTSUPDwq6jCsZ6NDEYpG8xz3FVV+Ac8q5Vpr/+jdg23ta09zq4aV8VIdIsroVOmZQqjwPcmQK57iWHd538i/XBtc2rnzbYq5bprnmtAKdx55gXVXDfALa0s6yR0HYvCaWguMEJhMIKWfi/9PEgLgwF9OmRwywc2TU/EdvYJo8fYHLfGk0PnYBuL1oSnn3cwAAef02W2JyCzQ84g30tLSUk+hC1LLi+iYj3x7IRR4q7Rlf/FYv/Q5fvjRtPT9eqM6fKyJ9ZO4NjlrSPFGydNbgABzP6WMhBzFjUkEKS27bGmr8Qxdj3Zp0TvR2IkyM6oM+6YknuM4RndUEgC1ZxtoIhugMjm6HdMQmoaHNK3kXewgQB90HHqzKA/J1gok3NcqL8Yls5g0LHepVHsU4cuaIqQr5yr665ZTLU2oqn1HIdkgydBYYUt6G3eWJKXYRbDhWPthGo/HK+W+iw6cTGWxzlCZS40EU9efxz4mDuhow67jOe704lBP3kiYXu05Y5uspaYnuvrvIwaRWBYapyR9UmKktnY8xJYrZvrcZgCovAbiodTzWeYg37xjFfGgYNI8CAwEAAQ=="; - -#define NUM_RECOGN_SIGN_KEYS 3 -static std::string RecognSigningKeys[NUM_RECOGN_SIGN_KEYS] = -{ - "AvMxAwAAA5YQMAAAABAANAAAAAoAAAABEEAAAAFMAKQAAAAmYjI2ZTUyNGFlZjczYmY3Y2MyMzUwNTc0ZTMyMjcxZWEAAAAAUl8ogFRAXAABEAAAARQwggEKAoIBAQCyblJK73O/fMI1BXTjInHqIWma62Z2r3K7/giT6Xm3k+lyNokvpR+I45XdEvPRmFVZmTU7XT2n3YiPDLe7y2r9fnYiLvBCdu+FBaVv5UQG8nvFGMLKbhdyRpOSBgDc+Y+8plMPn8jqgfNhLROMowmvDJQkJQjlm80d/9wj+VZ+tLiPPo8uOlghqNhdXDGK7HnfeLrJyD8kLEW7+4huaxR8IsLgjzuK8rovGLYCBcnx4TXvtbEeafJBBBt8S/GPeUaB1rxWpVV6fi+oBU6cvjbEqPzSalIrwNPyqlj+1SbL1jGEGEr1XIMzDa96SVsJ0F93lS3H9c8HdvByAifgzbPZAgMBAAEQUAAAAjIApAAAACZlM2Y4YjY3ZjJmYjM0NzZlZmYxZmM3ZjNhNjEzM2M5OQEgAAACBp1w449QGjchVotgHvGWRh18zpsDUHRv8PlRX1vXy8FMstTrnRjaDofFitmpJm8K6F1t/9jviCdB+BCvRzAS4SxER49YCBp04xZfX7c03xdq/e27jYRds2w6YHTiEgNi5v1cyWhrwDcCdefXRnHTH1UOw3jOoWnlnmM6jEsL39XI5fvsog9z8GxcG54APKA7JgiqhgMcrKRwNk74XJAzcjB6FS8xaV2gzpZZLNZ1TU+tJoLSiRqTU8UiAGbAR85lYLT5Ozdd2C+bTQ9f6vltz8bpzicJzxGCIsYtSL44InQsO/Oar9IgZu8QE4pTuunGJhVqEZru7ZN+oV+wXt51n+24SS0sNgNKVUFS74RfvsFi67CrXSWTOI8bVS0Lvv3EMWMdSF9dHGbdCFnp2/wqbW/4Qz7XYF4lcu9gLe4UtIrZ6TkAvBtnSfvTTdXj7kD6oHDjrUCjHPxdhz3BLRbj1wENZsoS3QDl22Ts7dbO8wHjutsS3/zx4DLlADoFlU8p7HJaCdrsq20P4WCeQJb6JbbLpGRAccKAidAPHMxQ4fr3b+GtjxpLJtXaytr4CPSXsCt4TloE9g5yCE6n/2UxQACp8Guh9l2MXmrD7qEGexhYqFB/OG84u3vL+gskmsKXTEqi2SiSmhvzta2p2hGCLCKRQeYbn+4TsIQfgWtYNQvC", - "AvMxAwAAA5YQMAAAABAANAAAAAoAAAACEEAAAAFMAKQAAAAmYjY0OTJkODMzNTI5ZjMxMGM1MmRjMDc3ZjBmZDgyMjcAAAAAUl8ogFRAXAABEAAAARQwggEKAoIBAQC2SS2DNSnzEMUtwHfw/YInm/XLXEUMktyZTmyMWACBbEfmU6aztT3vxz6UHoCBYtKkzKrfDZLvXe0a5TRLMmK+yfl5IzIVUPdqTg6FF3Bx/GXdj4v/ZP6lAuqY5YeI4wPcKldrrIJ9DTUdhZhgdtgDtxGvrXZ8eFjcl9zM+QEykYKMwfnTCixzVOPCCo3q1lJO13NmlhVQDO+f9vvTZsYDCcZHMqlKZWcCEyY1ZpQiCqlsL8wN6tKxMuSQO8EGdH/tNzsGHwCoZq6EEL7SX/pmc2ABjpDQTLixgXwJtCpw8Fwj1xiavsFFbqSLu3SjUCcrMz9f8U5p2ROyv//lWxsXAgMBAAEQUAAAAjIApAAAACZlM2Y4YjY3ZjJmYjM0NzZlZmYxZmM3ZjNhNjEzM2M5OQEgAAACBksDPQ93PdZBGCEnKXcQsdB4yBA9NpImVR81JZdPmWlTwZGAXGJwt4EkBcz+xdey84JDujVtHJUzIL9Ws/Jq5MuXHr0tP5ebah1GCQF2/Ov7sctUk3UPBxeroon7gZQhuzaIJVhl0rzwWriFUbTu7H7g9eaTHMvyfUg+S0Z2p+e0+PdL5rfGOJJZ6+NJCXxxbQ//cF4s0PAzkjAuwDmC+OiUiU5V6fY4XtRMCEI7w+UCj+wQn2Wu1Wc7xVM9uow13rGaLPYkWZ/9v+wNhg0KCsVfKGhkAGGzGyKI9LAppFVTu52pBlRu9Ung7VkhF0JC2aadYKKFl99wCbsGqUYN/gtfgHYCV24LNVah2dAy8CI9UmHdWk1kIwWazbPTYKLfpYCTFxqEqXqo3ijLf0YPsfhIvCQpc5VHAvLJlDm0RFKwzK6N9Zu9s9IvJHzIpaAAHCQJPtYxPwWMdt83njGo9wu1+aVkl5Sb5X8N16AybbnQ7fCBqJruGBM0LHtWVbHEiEygD7OStzyhT5rXKZSQYMA9I2CvK1t7qfDXDM40k8SVQ5CrS9R8x1wqQbe+DqNJ9tMfbUmN0xrO/w2pTl/4edKW30TShW/fr3vCWpVq8gcm3CVFSZUaC4T9wqH96K6KgIPbmg1Hk158pxXYXopEv6ZxR7UTPxKB0O22aIHB6UQ5", - "AvMxAwAAA5YQMAAAABAANAAAAAoAAAABEEAAAAFMAKQAAAAmOTdhNTJkMThjMDBjYWE3YmZlYmQ4NTg0MDJkMzBhY2QAAAAAUl8ogFRAXAABEAAAARQwggEKAoIBAQCXpS0YwAyqe/69hYQC0wrNz7eUHAmJfR5EV7NVFQeOxtTlFwbdvRMK8ZpfqEoRhIPXAYCc9Dv3F7WcmcFer8d50EWhlK7rCQScaRdwL1UmF1dUY8bR8QxhJOUgwmrlzeKOHi2DJ3/9AXm7NJR8XMJgHEQQwi3z/aQsWrwCUA0mk68C8a3vjLtcMj5XBuNXRtGZ9zFjiI9Xt19y0iIKdYpfzOnJTKVETcjH7XPBBbJETWkrEyToHXPjcfhESAbJDOoyfQQbxHMQNE7no7owN08LoWX2kOSGtl2m6JbE2OEdJig83a6U3PDYfYM5LCfsAJEIroYhB3qZJDE98zGC8jihAgMBAAEQUAAAAjIApAAAACZlM2Y4YjY3ZjJmYjM0NzZlZmYxZmM3ZjNhNjEzM2M5OQEgAAACBiwl7oRPJzLlwDd8AzVolFQH1ZS+MWLA4B1eHCjCXSMn+zS0Su6CrpC6/vLwECaKSfNZ8y7T2fNDPJHMLmc1F6jJkdNZq3TZGNRgJx24OF3G5MU6mAH7DBsz7muFto+URTJl9CdJviIyQAn5E+R4Gp531RJdKlbqJl/gWuQMVem+eo3elpVEn8Ckg0yvFaFdhGFTOPyrXOZ6fI0pdCX0SH2q/vAIxGDRzaSYmsR0Y+oYZs0AeRnZD9iEh1v17xnVEdSoLZmZbjlLXXgqhbdXGik6ZoXQg3bTfl5D1j8Tk/d/CXqf0SUKBnIafaNgUeQSMY95M3k3vjPQN7vHdXmg19GnqQmBnGq45qdKI7+0Erfhl4po1z6yVvx9JfIMIDOsKwO3U/As5zbO2BYso0pUP4+gndissfDfqlPRni3orA0tlV6NuLmXi1wkHCu8HQ8WOqEUlWDJNLNpHW5OmgjMFqlIPt7hX5jlc9eXd4oMyaqXm1Tg8Cgbh5DYaT9A7He47+QhqYlPygqK9Fm0ZnH3Yz51cm3p2tRB1JU7qH9h5UqLLKJMBuIx7e9L5ieTfzKmTw6tqpIpHpiR/8bSQlKkw2LxikFy3OXL5obY1t9sWk35BNZQqcqflI6mkPrvGQKwN+co8GjUon5/Y1HSM6ursaJtkD8dz+oXVyWAokkuD7QZ", - - -}; - - - -EVP_PKEY *RsRecogn::loadMasterKey() -{ - /* load master signing key */ - std::vector decoded = Radix64::decode(RecognKey); - - const unsigned char *keyptr2 = decoded.data(); - long keylen2 = decoded.size(); - - RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr2), keylen2); - - if (!rsakey) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::loadMasterKeys() failed rsakey load"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return NULL; - } - - - EVP_PKEY *signKey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(signKey, rsakey); - - return signKey; -} - - -bool RsRecogn::loadSigningKeys(std::map &signMap) -{ - - EVP_PKEY *signKey = loadMasterKey(); - RsGxsRecognSerialiser recognSerialiser; - - if (!signKey) - { - std::cerr << "RsRecogn::loadSigningKeys() missing Master Key"; - return false; - } - - - rstime_t now = time(NULL); - - for(int i = 0; i < NUM_RECOGN_SIGN_KEYS; i++) - { - std::vector signerbuf = Radix64::decode(RecognSigningKeys[i]); - - uint32_t pktsize = signerbuf.size(); - RsItem *pktitem = recognSerialiser.deserialise(signerbuf.data(), &pktsize); - RsGxsRecognSignerItem *item = dynamic_cast(pktitem); - - if (!item) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::loadSigningKeys() failed to deserialise SignerItem from string \"" << RecognSigningKeys[i] << "\""; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - continue; - } - -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::loadSigningKeys() SignerItem: "; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - - /* check dates */ - if ((item->key.startTS > (unsigned) now) || (item->key.endTS < (unsigned) now)) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::loadSigningKeys() failed timestamp"; - std::cerr << std::endl; - std::cerr << "RsRecogn::loadSigningKeys() key.startTS: " << item->key.startTS; - std::cerr << std::endl; - std::cerr << "RsRecogn::loadSigningKeys() now: " << now; - std::cerr << std::endl; - std::cerr << "RsRecogn::loadSigningKeys() key.endTS: " << item->key.endTS; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - delete item; - continue; - } - - /* check signature */ - RsTlvKeySignature signature = item->sign; - item->sign.TlvShallowClear(); - - unsigned int siglen = signature.signData.bin_len; - unsigned char *sigbuf = (unsigned char *) signature.signData.bin_data; - - /* store in */ - uint32_t datalen = recognSerialiser.size(item); - - RsTemporaryMemory data(datalen) ; - - if(!data) - return false ; - - uint32_t pktlen = datalen; - int signOk = 0; - - if (recognSerialiser.serialise(item, data, &pktlen)) - { - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - EVP_VerifyInit(mdctx, EVP_sha1()); - EVP_VerifyUpdate(mdctx, data, pktlen); - signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey); - - EVP_MD_CTX_destroy(mdctx); - - item->sign = signature; - signature.TlvShallowClear(); - - if (signOk) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::loadSigningKeys() signature ok"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - RsGxsId signerId = item->key.keyId; - signMap[signerId] = item; - } - } - - if (!signOk) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::loadSigningKeys() signature failed"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - delete item; - } - } - - /* clean up */ - EVP_PKEY_free(signKey); - return true; -} - - - -bool RsRecogn::validateTagSignature(RsGxsRecognSignerItem *signer, RsGxsRecognTagItem *item) -{ - if (item->sign.keyId != signer->key.keyId) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::validateTagSignature() keyId mismatch"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - const unsigned char *keyptr = (const unsigned char *) signer->key.keyData.bin_data; - long keylen = signer->key.keyData.bin_len; - - /* extract admin key */ - RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen); - if (!rsakey) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::validateTagSignature() failed extract signkey"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - /* check signature */ - RsTlvKeySignature signature = item->sign; - item->sign.TlvShallowClear(); - - unsigned int siglen = signature.signData.bin_len; - unsigned char *sigbuf = (unsigned char *) signature.signData.bin_data; - - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - EVP_PKEY *signKey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(signKey, rsakey); - - - /* store in */ - RsGxsRecognSerialiser serialiser; - - uint32_t datalen = serialiser.size(item); - - RsTemporaryMemory data(datalen) ; - - if(!data) - return false ; - - int signOk = 0; - - uint32_t pktlen = datalen; - if (serialiser.serialise(item, data, &pktlen)) - { - - EVP_VerifyInit(mdctx, EVP_sha1()); - EVP_VerifyUpdate(mdctx, data, pktlen); - signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey); -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::validateTagSignature() sign_result: " << signOk; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - } - else - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::validateTagSignature() failed to serialise"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - } - - // Clean up. - item->sign = signature; - signature.TlvShallowClear(); - - EVP_MD_CTX_destroy(mdctx); - EVP_PKEY_free(signKey); - - return (signOk == 1); -} - - -bool rsa_sanity_check(RSA *rsa) -{ - std::cerr << "rsa_sanity_check()"; - std::cerr << std::endl; - - if (!rsa) - { - std::cerr << "rsa_sanity_check() RSA == NULL"; - std::cerr << std::endl; - return false; - } - - RSA *pubkey = RSAPublicKey_dup(rsa); - - std::string signId = RsRecogn::getRsaKeyId(rsa); - std::string signId2 = RsRecogn::getRsaKeyId(pubkey); - - bool ok = true; - if (signId != signId2) - { - std::cerr << "rsa_sanity_check() ERROR SignId Failure"; - std::cerr << std::endl; - ok = false; - } - - if (1 != RSA_check_key(rsa)) - { - std::cerr << "rsa_sanity_check() ERROR RSA key is not private"; - std::cerr << std::endl; - ok = false; - } - -#if 0 - if (1 == RSA_check_key(pubkey)) - { - std::cerr << "rsa_sanity_check() ERROR RSA dup key is private"; - std::cerr << std::endl; - ok = false; - } -#endif - - RSA_free(pubkey); - - if (!ok) - { - exit(1); - } - - return true; -} - - -#warning csoler: this code should be using GxsSecurity signature code. Not some own made signature call. - -bool RsRecogn::signTag(EVP_PKEY *signKey, RsGxsRecognTagItem *item) -{ - RsGxsRecognSerialiser serialiser; - - RSA *rsa = EVP_PKEY_get1_RSA(signKey); - std::string signId = getRsaKeyId(rsa); - rsa_sanity_check(rsa); - RSA_free(rsa); - - item->sign.TlvClear(); - - /* write out the item for signing */ - uint32_t len = serialiser.size(item); - char *buf = new char[len]; - if (!serialiser.serialise(item, buf, &len)) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::signTag() Failed serialise TagItem:"; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - delete []buf; - return false; - } - - /* calc and check signature */ - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - EVP_SignInit(mdctx, EVP_sha1()); - EVP_SignUpdate(mdctx, buf, len); - - unsigned int siglen = EVP_PKEY_size(signKey); - unsigned char sigbuf[siglen]; - EVP_SignFinal(mdctx, sigbuf, &siglen, signKey); - - /* save signature */ - item->sign.signData.setBinData(sigbuf, siglen); - item->sign.keyId = RsGxsId(signId); - - /* clean up */ - EVP_MD_CTX_destroy(mdctx); - delete []buf; - - return true; -} - -#warning csoler: this code should be using GxsSecurity signature code. Not some own made signature call. - -bool RsRecogn::signSigner(EVP_PKEY *signKey, RsGxsRecognSignerItem *item) -{ - std::cerr << "RsRecogn::signSigner()"; - std::cerr << std::endl; - - RsGxsRecognSerialiser serialiser; - - std::cerr << "RsRecogn::signSigner() Checking Key"; - std::cerr << std::endl; - - RSA *rsa = EVP_PKEY_get1_RSA(signKey); - std::string signId = getRsaKeyId(rsa); - rsa_sanity_check(rsa); - RSA_free(rsa); - - std::cerr << "RsRecogn::signSigner() Key Okay"; - std::cerr << std::endl; - - item->sign.TlvClear(); - - /* write out the item for signing */ - uint32_t len = serialiser.size(item); - char *buf = new char[len]; - if (!serialiser.serialise(item, buf, &len)) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::signSigner() Failed serialise SignerItem:"; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - delete []buf; - return false; - } - - /* calc and check signature */ - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - EVP_SignInit(mdctx, EVP_sha1()); - EVP_SignUpdate(mdctx, buf, len); - - unsigned int siglen = EVP_PKEY_size(signKey); - unsigned char sigbuf[siglen]; - EVP_SignFinal(mdctx, sigbuf, &siglen, signKey); - - /* save signature */ - item->sign.signData.setBinData(sigbuf, siglen); - item->sign.keyId = RsGxsId(signId); - - /* clean up */ - EVP_MD_CTX_destroy(mdctx); - delete []buf; - - return true; -} - -#warning csoler: this code should be using GxsSecurity signature code. Not some own made signature call. - -bool RsRecogn::signTagRequest(EVP_PKEY *signKey, RsGxsRecognReqItem *item) -{ - std::cerr << "RsRecogn::signTagRequest()"; - std::cerr << std::endl; - - RsGxsRecognSerialiser serialiser; - - RSA *rsa = EVP_PKEY_get1_RSA(signKey); - std::string signId = getRsaKeyId(rsa); - rsa_sanity_check(rsa); - RSA_free(rsa); - - item->sign.TlvClear(); - - /* write out the item for signing */ - uint32_t len = serialiser.size(item); - char *buf = new char[len]; - if (!serialiser.serialise(item, buf, &len)) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::signTagRequest() Failed serialise Tag Request:"; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - delete []buf; - return false; - } - - /* calc and check signature */ - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - EVP_SignInit(mdctx, EVP_sha1()); - EVP_SignUpdate(mdctx, buf, len); - - unsigned int siglen = EVP_PKEY_size(signKey); - unsigned char sigbuf[siglen]; - EVP_SignFinal(mdctx, sigbuf, &siglen, signKey); - - /* save signature */ - item->sign.signData.setBinData(sigbuf, siglen); - item->sign.keyId = RsGxsId(signId); - - /* clean up */ - EVP_MD_CTX_destroy(mdctx); - delete []buf; - - return true; -} - - -bool RsRecogn::itemToRadix64(RsItem *item, std::string &radstr) -{ - RsGxsRecognSerialiser serialiser; - - /* write out the item for signing */ - uint32_t len = serialiser.size(item); - - RsTemporaryMemory buf(len) ; - - if (!serialiser.serialise(item, buf, &len)) - { - return false; - } - - radstr.clear(); - Radix64::encode(buf, len, radstr); - - return true; -} - - -std::string RsRecogn::getRsaKeyId(RSA *pubkey) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - int len = BN_num_bytes(pubkey -> n); - unsigned char tmp[len]; - BN_bn2bin(pubkey -> n, tmp); -#else - const BIGNUM *nn=NULL ; - RSA_get0_key(pubkey,&nn,NULL,NULL) ; - - int len = BN_num_bytes(nn); - unsigned char tmp[len]; - BN_bn2bin(nn, tmp); -#endif - - return RsDirUtil::sha1sum(tmp,len).toStdString(); - -#ifdef OLD_VERSION_REMOVED - // (cyril) I removed this because this is cryptographically insane, as it allows to easily forge a RSA key with the same ID. - - // copy first CERTSIGNLEN bytes... - if (len > CERTSIGNLEN) - { - len = CERTSIGNLEN; - } - - std::string id; - for(uint32_t i = 0; i < CERTSIGNLEN; i++) - { - rs_sprintf_append(id, "%02x", (uint16_t) (((uint8_t *) (tmp))[i])); - } - - return id; -#endif -} - - - -RsGxsRecognTagItem *RsRecogn::extractTag(const std::string &encoded) -{ - // Decode from Radix64 encoded Packet. - uint32_t pktsize; - - std::vector buffer = Radix64::decode(encoded); - pktsize = buffer.size(); - - if( buffer.empty() ) - return NULL; - - RsGxsRecognSerialiser serialiser; - RsItem *item = serialiser.deserialise(buffer.data(), &pktsize); - - if (!item) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::extractTag() ERROR Deserialise failed"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return NULL; - } - - RsGxsRecognTagItem *tagitem = dynamic_cast(item); - - if (!tagitem) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::extractTag() ERROR Not TagItem, is: "; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - delete item; - } - - return tagitem; -} - - -bool RsRecogn::createTagRequest(const RsTlvPrivateRSAKey &key, const RsGxsId &id, const std::string &nickname, uint16_t tag_class, uint16_t tag_type, const std::string &comment, std::string &tag) -{ - EVP_PKEY *signKey = EVP_PKEY_new(); - RSA *rsakey = d2i_RSAPrivateKey(NULL, (const unsigned char **)&key.keyData.bin_data, key.keyData.bin_len); - - if (!rsakey) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::createTagRequest() Failed to extract key"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - if (!EVP_PKEY_assign_RSA(signKey, rsakey)) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::createTagRequest() Failed to assign key"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - RsGxsRecognReqItem *item = new RsGxsRecognReqItem(); - - item->issued_at = time(NULL); - item->period = 365 * 24 * 3600; - item->tag_class = tag_class; - item->tag_type = tag_type; - - item->nickname = nickname; - item->identity = id; - item->comment = comment; - - bool signOk = RsRecogn::signTagRequest(signKey,item); - EVP_PKEY_free(signKey); - - if (!signOk) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::createTagRequest() Failed to sign Tag Request:"; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - delete item; - return false; - } - - /* write out the item for signing */ - RsGxsRecognSerialiser serialiser; - uint32_t len = serialiser.size(item); - RsTemporaryMemory buf(len) ; - bool serOk = serialiser.serialise(item, buf, &len); - - if (serOk) - { - Radix64::encode(buf, len, tag); - } - - if (!serOk) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::createTagRequest() Failed serialise Tag Request:"; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - delete item; - return false; - } - - delete item; - return serOk; -} - - diff --git a/libretroshare/src/util/rsrecogn.h b/libretroshare/src/util/rsrecogn.h deleted file mode 100644 index 7cc33ec76..000000000 --- a/libretroshare/src/util/rsrecogn.h +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsrandom.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2013 Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef RSUTIL_RECOGN_H -#define RSUTIL_RECOGN_H - -#include -#include -#include -#include - -#include "rsitems/rsgxsrecognitems.h" -#include "retroshare/rsgxsifacetypes.h" - -namespace RsRecogn { - -EVP_PKEY * loadMasterKey(); -bool loadSigningKeys(std::map &signMap); -bool validateTagSignature(RsGxsRecognSignerItem *signer, RsGxsRecognTagItem *item); - -bool signTag(EVP_PKEY *signKey, RsGxsRecognTagItem *item); -bool signSigner(EVP_PKEY *signKey, RsGxsRecognSignerItem *item); -bool signTagRequest(EVP_PKEY *signKey, RsGxsRecognReqItem *item); - -bool itemToRadix64(RsItem *item, std::string &radstr); - -std::string getRsaKeyId(RSA *pubkey); - -RsGxsRecognTagItem *extractTag(const std::string &encoded); - -bool createTagRequest(const RsTlvPrivateRSAKey &key, - const RsGxsId &id, const std::string &nickname, - uint16_t tag_class, uint16_t tag_type, - const std::string &comment, std::string &tag); - -} - -#endif diff --git a/libretroshare/src/util/rssharedptr.h b/libretroshare/src/util/rssharedptr.h deleted file mode 100644 index ca54f85b2..000000000 --- a/libretroshare/src/util/rssharedptr.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * rssharedptr.h - * - * Created on: 16 Apr 2014 - * Author: crispy - */ - -#ifndef RSSHAREDPTR_H_ -#define RSSHAREDPTR_H_ - -#include - -/*! - * Not thread safe!! - * And also has a memory leak. Do not use (csoler, 24 Jul 2017). - */ -template -class RsSharedPtr -{ -public: - - RsSharedPtr() : mShared(NULL), mCount(NULL), mSharedPtrMutex(NULL){} - - RsSharedPtr(T* shared) - : mShared(shared), mCount(new int(0)), mSharedPtrMutex(new RsMutex("SharedMutex")) - { - mCount++; - } - - RsSharedPtr(const RsSharedPtr& rsp) - { - rsp.lock(); - mShared = rsp.mShared; - mCount = rsp.mCount; - mCount++; - mSharedPtrMutex = rsp.mSharedPtrMutex; - rsp.unlock(); - - } - - void operator=(const RsSharedPtr& rsp) - { - rsp.lock(); - mSharedPtrMutex = rsp.mSharedPtrMutex; - DecrementAndDeleteIfLast(); - mShared = rsp.mShared; - RepointAndIncrement(rsp.mCount); - - mSharedPtrMutex->unlock(); - } - - T* release() { - - lock(); - - mCount--; T* temp = mShared; mShared = NULL; - - unlock(); - - return temp; - } - T* get() { return mShared; } - - T& operator*(){ return *mShared; } - T* operator->(){ return mShared; } - - ~RsSharedPtr() - { - lock(); - DecrementAndDeleteIfLast(); - unlock(); - } -private: - - void DecrementAndDeleteIfLast() - { - mCount--; - if(mCount == 0 && mShared != NULL) - { - delete mShared; - delete mCount; - } - - mShared = NULL; - mCount = NULL; - } - - void RepointAndIncrement(int* count) - { - mCount = count; - mCount++; - - } - - void lock() const { mSharedPtrMutex->lock(); } - void unlock() const { mSharedPtrMutex->unlock(); } - -private: - - T* mShared; - int* mCount; - RsMutex* mSharedPtrMutex; - -}; - -template -RsSharedPtr rs_make_shared(T* ptr){ return RsSharedPtr(ptr); } - -#endif /* RSSHAREDPTR_H_ */ diff --git a/libretroshare/src/util/rsstd.h b/libretroshare/src/util/rsstd.h deleted file mode 100644 index 2cf3ae31d..000000000 --- a/libretroshare/src/util/rsstd.h +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsstd.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSSTD_H_ -#define RSSTD_H_ - -namespace rsstd { - -template -void delete_all(_IIter iter_begin, _IIter iter_end) -{ - for (_IIter it = iter_begin; it != iter_end; ++it) { - delete(*it); - } -} - -} - -#endif // RSSTD_H_ diff --git a/libretroshare/src/util/rsstring.cc b/libretroshare/src/util/rsstring.cc deleted file mode 100644 index 6dcb8bd21..000000000 --- a/libretroshare/src/util/rsstring.cc +++ /dev/null @@ -1,334 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsstd.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2010, Thomas Kister * - * * - * 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 . * - * * - *******************************************************************************/ -#include "rsstring.h" - -#ifdef WINDOWS_SYS -#include -#include -#else -#include -#include -#include -#endif -#include -#include - -namespace librs { namespace util { - -bool ConvertUtf8ToUtf16(const std::string& source, std::wstring& dest) -{ - if (source.empty()) { - dest.clear(); - return true; - } - -#ifdef WINDOWS_SYS - int nbChars = MultiByteToWideChar(CP_UTF8, 0, source.c_str(), -1, 0, 0); - if(nbChars == 0) { - return false; - } - - wchar_t* utf16Name = new wchar_t[nbChars]; - if( MultiByteToWideChar(CP_UTF8, 0, source.c_str(), -1, utf16Name, nbChars) == 0) { - delete[] utf16Name; - return false; - } - - dest = utf16Name; - delete[] utf16Name; -#else - std::vector res; - std::string::size_type len = source.length(); - - unsigned int i = 0; - unsigned long temp; - - while (i < len) { - char src = source[i]; - if ((src & 0x80) == 0) { // ASCII : 0000 0000-0000 007F 0xxxxxxx - temp = src; - ++i; - } else if ((src & 0xE0) == 0xC0) { // 0000 0080-0000 07FF 110xxxxx 10xxxxxx - temp = (src & 0x1F); - temp <<= 6; - temp += (source[i + 1] & 0x3F); - i += 2; - } else if ((src & 0xF0) == 0xE0) { // 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx - temp = (src & 0x0F); - temp <<= 6; - temp += (source[i + 1] & 0x3F); - temp <<= 6; - temp += (source[i + 2] & 0x3F); - i += 3; - } else if ((src & 0xF8) == 0xF0) { // 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - temp = (src & 0x07); - temp <<= 6; - temp += (source[i + 1] & 0x3F); - temp <<= 6; - temp += (source[i + 2] & 0x3F); - temp <<= 6; - temp += (source[i + 3] & 0x3F); - i += 4; - } else if ((src & 0xFC) == 0xF8) { // 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - temp = (src & 0x03); - temp <<= 6; - temp += (source[i + 1] & 0x3F); - temp <<= 6; - temp += (source[i + 2] & 0x3F); - temp <<= 6; - temp += (source[i + 3] & 0x3F); - temp <<= 6; - temp += (source[i + 4] & 0x3F); - i += 5; - } else if ((src & 0xFE) == 0xFC) { // 0400 0000-7FFF FFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - temp = (src & 0x01); - temp <<= 6; - temp += (source[i + 1] & 0x3F); - temp <<= 6; - temp += (source[i + 2] & 0x3F); - temp <<= 6; - temp += (source[i + 3] & 0x3F); - temp <<= 6; - temp += (source[i + 4] & 0x3F); - temp <<= 6; - temp += (source[i + 5] & 0x3F); - i += 6; - } else { - temp = '?'; - } - // Need to transform to UTF-16 > handle surrogates - if (temp > 0xFFFF) { - // First high surrogate - res.push_back(0xD800 + wchar_t(temp >> 10)); - // Now low surrogate - res.push_back(0xDC00 + wchar_t(temp & 0x3FF)); - } else { - res.push_back(wchar_t(temp)); - } - } - // Check whether first wchar_t is the BOM 0xFEFF - if (res[0] == 0xFEFF) { - dest.append(&res[1], res.size() - 1); - } else { - dest.append(&res[0], res.size()); - } -#endif - - return true; -} - -bool ConvertUtf16ToUtf8(const std::wstring& source, std::string& dest) -{ -#ifdef WINDOWS_SYS - int nbChars = WideCharToMultiByte(CP_UTF8, 0, source.c_str(), -1, 0, 0, 0, 0); - if(nbChars == 0) { - return false; - } - - char* utf8Name = new char[nbChars]; - if( WideCharToMultiByte(CP_UTF8, 0, source.c_str(), -1, utf8Name, nbChars, 0, 0) == 0) { - delete[] utf8Name; - return false; - } - - dest = utf8Name; - delete[] utf8Name; -#else - std::vector res; - - std::wstring::size_type len = source.length(); - unsigned int i = 0; - unsigned long temp; - - while (i < len) { - if ((source[i] & 0xD800) == 0xD800) { // surrogate - temp = (source[i] - 0xD800); - temp <<= 10; - temp += (source[i + 1] - 0xDC00); - i += 2; - } else { - temp = source[i]; - ++i; - } - if (temp < 0x00000080) { // ASCII : 0000 0000-0000 007F 0xxxxxxx - res.push_back(char(temp)); - } else if (temp < 0x00000800) { // 0000 0080-0000 07FF 110xxxxx 10xxxxxx - res.push_back(char(0xC0 | (temp >> 6))); - res.push_back(char(0x80 | (temp & 0x3F))); - } else if (temp < 0x00010000) { // 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx - res.push_back(char(0xE0 | (temp >> 12))); - res.push_back(char(0x80 | ((temp >> 6) & 0x3F))); - res.push_back(char(0x80 | (temp & 0x3F))); - } else if (temp < 0x00200000) { // 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - res.push_back(char(0xF0 | (temp >> 18))); - res.push_back(char(0x80 | ((temp >> 12) & 0x3F))); - res.push_back(char(0x80 | ((temp >> 6) & 0x3F))); - res.push_back(char(0x80 | (temp & 0x3F))); - } else if (temp < 0x04000000) { // 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - res.push_back(char(0xF8 | (temp >> 24))); - res.push_back(char(0x80 | ((temp >> 18) & 0x3F))); - res.push_back(char(0x80 | ((temp >> 12) & 0x3F))); - res.push_back(char(0x80 | ((temp >> 6) & 0x3F))); - res.push_back(char(0x80 | (temp & 0x3F))); - } else if (temp < 0x80000000) { // 0400 0000-7FFF FFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - res.push_back(char(0xFC | (temp >> 30))); - res.push_back(char(0x80 | ((temp >> 24) & 0x3F))); - res.push_back(char(0x80 | ((temp >> 18) & 0x3F))); - res.push_back(char(0x80 | ((temp >> 12) & 0x3F))); - res.push_back(char(0x80 | ((temp >> 6) & 0x3F))); - res.push_back(char(0x80 | (temp & 0x3F))); - } - } - - dest.append(&res[0], res.size()); -#endif - - return true; -} - -#if 0 -bool is_alphanumeric(char c) -{ - return (c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z'); -} - -bool is_alphanumeric(const std::string& s) -{ - for( uint32_t i=0; i < s.size(); ++i) - if(!is_alphanumeric(s[i])) return false; - return true; -} -#endif - -} } // librs::util - -#ifdef WINDOWS_SYS -// asprintf() and vasprintf() are missing in Win32 -static int vasprintf(char **sptr, const char *fmt, va_list argv) -{ - int wanted = __mingw_vsnprintf(*sptr = NULL, 0, fmt, argv); - if ((wanted > 0) && ((*sptr = (char*) malloc(wanted + 1)) != NULL)) { - return __mingw_vsprintf(*sptr, fmt, argv); - } - - return wanted; -} - -//static int asprintf(char **sptr, const char *fmt, ...) -//{ -// int retval; -// va_list argv; -// va_start( argv, fmt ); -// retval = vasprintf(sptr, fmt, argv); -// va_end(argv); -// return retval; -//} -#endif - -int rs_sprintf_args(std::string &str, const char *fmt, va_list ap) -{ - char *buffer = NULL; - - int retval = vasprintf(&buffer, fmt, ap); - - if (retval >= 0) { - if (buffer) { - str = buffer; - free(buffer); - } else { - str.clear(); - } - } else { - str.clear(); - } - - return retval; -} - -int rs_sprintf(std::string &str, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - int retval = rs_sprintf_args(str, fmt, ap); - va_end(ap); - - return retval; -} - -int rs_sprintf_append_args(std::string &str, const char *fmt, va_list ap) -{ - char *buffer = NULL; - - int retval = vasprintf(&buffer, fmt, ap); - - if (retval >= 0) { - if (buffer) { - str.append(buffer); - free(buffer); - } - } - - return retval; -} - -int rs_sprintf_append(std::string &str, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - int retval = rs_sprintf_append_args(str, fmt, ap); - va_end(ap); - - return retval; -} - -void stringToUpperCase(const std::string& s, std::string &upper) -{ - upper = s ; - - for(uint32_t i=0;i 96 && upper[i] < 123) - upper[i] -= 97-65 ; -} - -void stringToLowerCase(const std::string& s, std::string &lower) -{ - lower = s ; - - for(uint32_t i=0;i 64 && lower[i] < 91) - lower[i] += 97-65 ; -} - - - -bool isHexaString(const std::string& s) -{ - for(uint32_t i=0;i= 'A' && s[i] <= 'F') || (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f'))) - return false ; - - return true ; -} - - diff --git a/libretroshare/src/util/rsstring.h b/libretroshare/src/util/rsstring.h deleted file mode 100644 index b3fd2553c..000000000 --- a/libretroshare/src/util/rsstring.h +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsstd.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2010, Thomas Kister * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RSSTRING_H_ -#define RSSTRING_H_ - -#include -#include - -namespace librs { - namespace util { - - bool ConvertUtf8ToUtf16(const std::string& source, std::wstring& dest); - bool ConvertUtf16ToUtf8(const std::wstring& source, std::string& dest); -#if 0 - bool is_alphanumeric(char c) ; - bool is_alphanumeric(const std::string& s); -#endif -} } // librs::util - -#ifdef WIN32 -#define INT64FMT "%I64d" -#define UINT64FMT "%I64u" -#else -#define INT64FMT "%lld" -#define UINT64FMT "%llu" -#endif - -int rs_sprintf_args(std::string &str, const char *fmt, va_list ap); -int rs_sprintf(std::string &str, const char *fmt, ...); -int rs_sprintf_append_args(std::string &str, const char *fmt, va_list ap); -int rs_sprintf_append(std::string &str, const char *fmt, ...); - -void stringToUpperCase(const std::string& s, std::string &upper); -void stringToLowerCase(const std::string& s, std::string &lower); - -bool isHexaString(const std::string& s); - -#endif // RSSTRING_H_ diff --git a/libretroshare/src/util/rsthreads.cc b/libretroshare/src/util/rsthreads.cc deleted file mode 100644 index 035ad214a..000000000 --- a/libretroshare/src/util/rsthreads.cc +++ /dev/null @@ -1,332 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsthreads.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2007 Robert Fernie * - * Copyright (C) 2016-2020 Gioacchino Mazzurco * - * Copyright (C) 2019-2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ - -#include "rsthreads.h" - -#include "util/rsdebug.h" -#include "util/rserrno.h" - -#include -#include -#include -#include - -#ifdef RS_MUTEX_DEBUG -#include -#include -#endif - -#ifdef __APPLE__ -int __attribute__((weak)) pthread_setname_np(const char *__buf) ; -int RS_pthread_setname_np(pthread_t /*__target_thread*/, const char *__buf) { - return pthread_setname_np(__buf); -} -#else -#ifndef __WIN64__ -int __attribute__((weak)) pthread_setname_np(pthread_t __target_thread, const char *__buf) ; -#endif //__WIN64__ -int RS_pthread_setname_np(pthread_t __target_thread, const char *__buf) { - return pthread_setname_np(__target_thread, __buf); -} -#endif //__APPLE__ - - -/******* - * #define DEBUG_THREADS 1 - * #define RSMUTEX_ABORT 1 // Catch wrong pthreads mode. - *******/ -#define THREAD_DEBUG RsDbg() << "[this=" << static_cast(this) \ - << ", caller thread ID: " << std::hex << pthread_self() << ", thread ID: " \ - << mTid << std::dec << "] " - -#ifdef RSMUTEX_ABORT - #include -#endif - -#ifdef DEBUG_THREADS - #include -#endif - -/*static*/ void* RsThread::rsthread_init(void* p) -{ - RsThread* thread = reinterpret_cast(p); - if(!thread) return nullptr; - - /* Using pthread_detach(...) the thread resources will be automatically - * freed when this function return, so there is no need for pthread_join() - * later. */ - pthread_detach(pthread_self()); - -#ifdef DEBUG_THREADS - std::cerr << "[Thread ID:" << std::hex << pthread_self() << std::dec - << "] thread is started. Calling wrapRun()..." << std::endl; -#endif - - thread->wrapRun(); - return nullptr; -} - -void RsThread::resetTid() -{ -#ifdef WINDOWS_SYS - memset (&mTid, 0, sizeof(mTid)); -#else - mTid = 0; -#endif -} - -RsThread::RsThread() : mHasStopped(true), mShouldStop(false), mLastTid() -#ifdef RS_THREAD_FORCE_STOP - , mStopTimeout(0) -#endif -{ resetTid(); } - -bool RsThread::isRunning() { return !mHasStopped; } - -bool RsThread::shouldStop() { return mShouldStop; } - -void RsThread::askForStop() -{ - /* Call onStopRequested() only once even if askForStop() is called multiple - * times */ - if(!mShouldStop.exchange(true)) onStopRequested(); -} - -void RsThread::wrapRun() -{ - run(); - resetTid(); - mHasStopped = true; -} - -void RsThread::fullstop() -{ -#ifdef RS_THREAD_FORCE_STOP - const rstime_t stopRequTS = time(nullptr); -#endif - - askForStop(); - - const pthread_t callerTid = pthread_self(); - if(pthread_equal(mTid, callerTid)) - { - RsErr() << __PRETTY_FUNCTION__ << " called by same thread. This should " - << "never happen! this: " << static_cast(this) - << std::hex << ", callerTid: " << callerTid - << ", mTid: " << mTid << std::dec - << ", mFullName: " << mFullName << std::endl; - print_stacktrace(); - return; - } - - // Wait for the thread being stopped - auto i = 1; - while(!mHasStopped) - { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - ++i; - if(!(i%5)) - RsDbg() << __PRETTY_FUNCTION__ << " " << i*0.2 << " seconds passed" - << " waiting for thread: " << std::hex << mLastTid - << std::dec << " " << mFullName << " to stop" << std::endl; - -#ifdef RS_THREAD_FORCE_STOP - if(mStopTimeout && time(nullptr) > stopRequTS + mStopTimeout) - { - RsErr() << __PRETTY_FUNCTION__ << " thread mLastTid: " << std::hex - << mLastTid << " mTid: " << mTid << std::dec << " " - << mFullName - << " ignored our nice stop request for more then " - << mStopTimeout - << " seconds, will be forcefully stopped. " - << "Please submit a report to RetroShare developers" - << std::endl; - - const auto terr = pthread_cancel(mTid); - if(terr == 0) mHasStopped = true; - else - { - RsErr() << __PRETTY_FUNCTION__ << " pthread_cancel(" - << std::hex << mTid << std::dec <<") returned " - << terr << " " << rsErrnoName(terr) << std::endl; - print_stacktrace(); - } - - break; - } -#endif // def RS_THREAD_FORCE_STOP - } -} - -bool RsThread::start(const std::string& threadName) -{ - // Atomically check if the thread was already started and set it as running - if(mHasStopped.exchange(false)) - { - mShouldStop = false; - int pError = pthread_create( - &mTid, nullptr, &rsthread_init, static_cast(this) ); - if(pError) - { - RsErr() << __PRETTY_FUNCTION__ << " pthread_create could not create" - << " new thread: " << threadName << " pError: " << pError - << std::endl; - mHasStopped = true; - print_stacktrace(); - return false; - } - if(!mTid) - { - RsErr() << __PRETTY_FUNCTION__ << " pthread_create could not create" - << " new thread: " << threadName << " mTid: " << mTid - << std::endl; - mHasStopped = true; - print_stacktrace(); - return false; - } - - /* Store an extra copy of thread id for debugging */ - mLastTid = mTid; - - /* Store thread full name as PThread is not able to keep it entirely */ - mFullName = threadName; - - /* Set PThread thread name which is restricted to 16 characters - * including the terminating null byte */ - if(pthread_setname_np && !threadName.empty()) - RS_pthread_setname_np(mTid, threadName.substr(0, 15).c_str()); - - return true; - } - - RsErr() << __PRETTY_FUNCTION__ << " attempt to start already running thread" - << std::endl; - print_stacktrace(); - return false; -} - -RsQueueThread::RsQueueThread(uint32_t min, uint32_t max, double relaxFactor ) - :mMinSleep(min), mMaxSleep(max), mRelaxFactor(relaxFactor) -{ - mLastSleep = (uint32_t)mMinSleep ; - mLastWork = time(NULL) ; -} - -void RsQueueThread::threadTick() -{ - bool doneWork = false; - while(workQueued() && doWork()) - { - doneWork = true; - } - time_t now = time(NULL); - if (doneWork) - { - mLastWork = now; - mLastSleep = (uint32_t) (mMinSleep + (mLastSleep - mMinSleep) / 2.0); -#ifdef DEBUG_TICKING - THREAD_DEBUG << "RsQueueThread::data_tick() done work: sleeping for: " << mLastSleep << " ms" << std::endl; -#endif - - } - else - { - uint32_t deltaT = now - mLastWork; - double frac = deltaT / mRelaxFactor; - - mLastSleep += (uint32_t) - ((mMaxSleep-mMinSleep) * (frac + 0.05)); - if (mLastSleep > mMaxSleep) - { - mLastSleep = mMaxSleep; - } -#ifdef DEBUG_TICKING - THREAD_DEBUG << "RsQueueThread::data_tick() no work: sleeping for: " << mLastSleep << " ms" << std::endl; -#endif - } - - std::this_thread::sleep_for(std::chrono::milliseconds(mLastSleep)); -} - -void RsMutex::unlock() -{ - _thread_id = 0; - pthread_mutex_unlock(&realMutex); -} - -void RsMutex::lock() -{ - int err = pthread_mutex_lock(&realMutex); - if( err != 0) - { - RsErr() << __PRETTY_FUNCTION__ << "pthread_mutex_lock returned: " - << rsErrnoName(err) -#ifdef RS_MUTEX_DEBUG - << " name: " << name() -#endif - << std::endl; - - print_stacktrace(); - -#ifdef RSMUTEX_ABORT - abort(); -#endif - } - - _thread_id = pthread_self(); -} - -#ifdef RS_MUTEX_DEBUG -double RsStackMutex::getCurrentTS() -{ - -#ifndef WINDOWS_SYS - struct timeval cts_tmp; - gettimeofday(&cts_tmp, NULL); - double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; -#else - struct _timeb timebuf; - _ftime( &timebuf); - double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; -#endif - return cts; -} -#endif - - -RsThread::~RsThread() -{ - if(!mHasStopped) - { - RsErr() << __PRETTY_FUNCTION__ << " deleting thread: " << mLastTid - << " " << mFullName << " that is still " - << "running! Something seems very wrong here and RetroShare is " - << "likely to crash because of this." << std::endl; - print_stacktrace(); - - fullstop(); - } -} - -RsQueueThread::~RsQueueThread() = default; diff --git a/libretroshare/src/util/rsthreads.h b/libretroshare/src/util/rsthreads.h deleted file mode 100644 index 82221ebbb..000000000 --- a/libretroshare/src/util/rsthreads.h +++ /dev/null @@ -1,336 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsthreads.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2016-2020 Gioacchino Mazzurco * - * Copyright (C) 2019-2020 Asociación Civil Altermundi * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util/rsmemory.h" -#include "util/rsdeprecate.h" - -#ifdef RS_THREAD_FORCE_STOP -# include "util/rstime.h" -#endif - -/** - * @brief Provide mutexes that keep track of the owner. Based on pthread mutex. - */ -class RsMutex -{ -public: - - RsMutex(const std::string& name) : _thread_id(0) -#ifdef RS_MUTEX_DEBUG - , _name(name) -#endif - { - pthread_mutex_init(&realMutex, nullptr); - -#ifndef RS_MUTEX_DEBUG - (void) name; // remove unused parameter warnings -#endif - } - - ~RsMutex() { pthread_mutex_destroy(&realMutex); } - - inline const pthread_t& owner() const { return _thread_id; } - - void lock(); - void unlock(); - bool trylock() { return (0 == pthread_mutex_trylock(&realMutex)); } - -#ifdef RS_MUTEX_DEBUG - const std::string& name() const { return _name ; } -#endif - -private: - pthread_mutex_t realMutex; - pthread_t _thread_id; - -#ifdef RS_MUTEX_DEBUG - std::string _name; -#endif -}; - -/** - * @def RS_STACK_MUTEX(m) - * This macro allows you to trace which mutex in the code is locked and for how - * much time. You can use this as follows: - * @code - * { - * RS_STACK_MUTEX(myMutex); - * do_something(); - * } - * @endcode - */ -#define RS_STACK_MUTEX(m) \ - RsStackMutex __local_retroshare_stack_mutex_##m( \ - m, __PRETTY_FUNCTION__, __FILE__, __LINE__ ) - -/** - * Provide mutexes that automatically lock/unlock on creation/destruction and - * have powerfull debugging facilities (if RS_MUTEX_DEBUG is defined at - * compiletime). - * In most of the cases you should not use this directly instead - * @see RS_STACK_MUTEX(m) - */ -class RsStackMutex -{ -public: - - RsStackMutex(RsMutex &mtx) : mMtx(mtx) - { - mMtx.lock(); -#ifdef RS_MUTEX_DEBUG - double ts = getCurrentTS(); - _time_stamp = ts; - _lineno = 0; - _info = "[no info]"; -#endif - } - - RsStackMutex(RsMutex &mtx, const char *function_name, const char *file_name, - int lineno) : mMtx(mtx) -#ifdef RS_MUTEX_DEBUG - , _info(std::string(function_name)+" in file "+file_name), _lineno(lineno) -#endif - { -#ifdef RS_MUTEX_DEBUG - double ts = getCurrentTS(); - _time_stamp = ts; - pthread_t owner = mMtx.owner(); -#else - // remove unused parameter warnings - (void) function_name; (void) file_name; (void) lineno; -#endif - - mMtx.lock(); - -#ifdef RS_MUTEX_DEBUG - ts = getCurrentTS(); - - if(ts - _time_stamp > 1.0) - std::cerr << "Mutex " << (void*)&mMtx << " \"" << mtx.name() << "\"" - << " waited for " << ts - _time_stamp - << " seconds in thread " << pthread_self() - << " for locked thread " << owner << ". in " << _info - << ":" << _lineno << std::endl; - _time_stamp = ts ; // This is to re-init the locking time without accounting for how much we waited. -#endif - } - - ~RsStackMutex() - { - mMtx.unlock(); - -#ifdef RS_MUTEX_DEBUG - double ts = getCurrentTS(); - - if(ts - _time_stamp > 1.0) - std::cerr << "Mutex " << (void*)&mMtx << " \"" << mMtx.name() - << "\"" << " locked for " << ts - _time_stamp - << " seconds in thread " << pthread_self() - << ". in " << _info << ":" << _lineno << std::endl; -#endif - } - -private: - RsMutex &mMtx; - -#ifdef RS_MUTEX_DEBUG - static double getCurrentTS(); - double _time_stamp; - std::string _info; - int _lineno; -#endif -}; - - - -/// @brief Offer basic threading functionalities. -class RsThread -{ -public: - RsThread(); - virtual ~RsThread(); - - /** - * @brief start the thread and call run() on it. - * @param threadName string containing the name of the thread used for - * debugging purposes, @note inside PThread it is - * truncated to 16 characters including \0 at the end of - * the string. - * @return false on error, true otherwise - */ - bool start(const std::string& threadName = ""); - - /** - * @brief Check if thread is running. - * @return true if the thread is still running, false otherwise. - */ - bool isRunning(); - - /** - * @brief Check if the thread should stop. - * Expecially useful for subclasses which implement a @see run() method - * which may take lot of time before returning when not asked, to check if - * stop has been requested and therefore interrupting the execution ASAP - * returning in a coherent state. - * @return true if the thread received a stopping order. - */ - bool shouldStop(); - - /** - * @brief Asyncronously ask the thread to stop. - * The real stop will happen when the @see run() method finish. - */ - void askForStop(); - - /** - * Call @see askForStop() then wait it has really stopped before returning. - * It must not be called in the same thread, as it would not wait for the - * effective stop to occur as it would cause a deadlock. - */ - void fullstop(); - - /** - * Execute given function on a detached thread without blocking the caller - * execution. - * This can be generalized with variadic template, ATM it is enough to wrap - * any kind of function call or job into a lambda which get no paramethers - * and return nothing but can capture - * This can be easly optimized later by using a thread pool - */ - static void async(const std::function& fn) - { std::thread(fn).detach(); } - - /** @return RsThread full name */ - const std::string& threadName() { return mFullName; } - -protected: - /** - * This method must be implemented by sublasses, will be called once the - * thread is started. Should return on request, use @see shouldStop() to - * check if stop has been requested. - */ - virtual void run() = 0; - - /** - * This method is meant to be overridden by subclasses with long running - * @see run() method and is executed asyncronously when @see askForStop() - * is called, any task necessary to stop the thread (aka inducing @see run() - * to return in a coherent state) should be done in the overridden version - * of this method, @see JsonApiServer for an usage example. */ - virtual void onStopRequested() {} - -#ifdef RS_THREAD_FORCE_STOP - /** Set last resort timeout to forcefully kill thread if it didn't stop - * nicely, one should never use this, still we needed to introduce this - * to investigate some bugs in external libraries */ - void setStopTimeout(rstime_t timeout) { mStopTimeout = timeout; } -#endif - -private: - /** Call @see run() setting the appropriate flags around it*/ - void wrapRun(); - - /// True if thread is stopped, false otherwise - std::atomic mHasStopped; - - /// True if stop has been requested - std::atomic mShouldStop; - - /// Passed as argument for pthread_create(), call start() - static void *rsthread_init(void*); - - /// Store the id of the corresponding pthread - pthread_t mTid; - void resetTid(); - - /** Store thread full name for debugging because PThread is limited to 15 - * char thread names */ - std::string mFullName; - - /** Store a copy of thread id which is never reset to 0 after initialization - * due to RsThread functioning. After RsThread initialization this member is - * only re-written with a new tread id in start(...). - * This is useful for debugging because mTid is reset at the end of wrapRun - * and that might happens concurrently (or just before) a debug message - * being printed, thus causing the debug message to print a mangled value.*/ - pthread_t mLastTid; - -#ifdef RS_THREAD_FORCE_STOP - /// @see setStopTimeout - rstime_t mStopTimeout; -#endif -}; - -/** - * Provide a detached execution loop that continuously call data_tick() once the - * thread is started - */ -class RsTickingThread: public RsThread -{ -public: - - /** - * Subclasses must implement this method, it will be called in a loop once - * the thread is started, so repetitive work (like checking if data is - * available on a socket) should be done here, at the end of this method - * sleep_for(...) or similar function should be called or the CPU will - * be used as much as possible also if there is nothing to do. - */ - virtual void threadTick() = 0; - -private: - /// Implement the run loop and continuously call threadTick() in it - void run() override { while(!shouldStop()) threadTick(); } -}; - -// TODO: Used just one time, is this really an useful abstraction? -class RsQueueThread: public RsTickingThread -{ -public: - RsQueueThread(uint32_t min, uint32_t max, double relaxFactor); - ~RsQueueThread() override; - -protected: - virtual bool workQueued() = 0; - virtual bool doWork() = 0; - - void threadTick() override; /// @see RsTickingThread - -private: - uint32_t mMinSleep; /* ms */ - uint32_t mMaxSleep; /* ms */ - uint32_t mLastSleep; /* ms */ - time_t mLastWork; /* secs */ - float mRelaxFactor; -}; diff --git a/libretroshare/src/util/rstickevent.cc b/libretroshare/src/util/rstickevent.cc deleted file mode 100644 index d596d417c..000000000 --- a/libretroshare/src/util/rstickevent.cc +++ /dev/null @@ -1,199 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rstickevent.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#include "util/rstickevent.h" - -#include -#include - -//#define DEBUG_EVENTS 1 - -void RsTickEvent::tick_events() -{ -#ifdef DEBUG_EVENTS - std::cerr << "RsTickEvent::tick_events() Event List:"; - std::cerr << std::endl; -#endif - - rstime_t now = time(NULL); - { - RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_EVENTS - if (!mEvents.empty()) - { - std::multimap::iterator it; - - for(it = mEvents.begin(); it != mEvents.end(); ++it) - { - std::cerr << "\tEvent type: "; - std::cerr << it->second << " in " << it->first - now << " secs"; - std::cerr << std::endl; - } - } -#endif - - if (mEvents.empty()) - { - return; - } - - /* all events in the future */ - if (mEvents.begin()->first > now) - { - return; - } - } - - std::list toProcess; - std::list::iterator it; - - { - RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ - while((!mEvents.empty()) && (mEvents.begin()->first <= now)) - { - std::multimap::iterator it = mEvents.begin(); - uint32_t event_type = it->second.mEventType; - toProcess.push_back(it->second); - mEvents.erase(it); - - count_adjust_locked(event_type, -1); - note_event_locked(event_type); - } - } - - for(it = toProcess.begin(); it != toProcess.end(); ++it) - { -#ifdef DEBUG_EVENTS - std::cerr << "RsTickEvent::tick_events() calling handle_event("; - std::cerr << it->mEventType << ", " << it->mEventLabel << ")"; - std::cerr << std::endl; -#endif // DEBUG_EVENTS - handle_event(it->mEventType, it->mEventLabel); - } -} - -void RsTickEvent::schedule_now(uint32_t event_type) -{ - std::string elabel; - RsTickEvent::schedule_in(event_type, 0, elabel); -} - - -void RsTickEvent::schedule_now(uint32_t event_type, const std::string &elabel) -{ - RsTickEvent::schedule_in(event_type, 0, elabel); -} - -void RsTickEvent::schedule_event(uint32_t event_type, rstime_t when, const std::string &elabel) -{ - RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ - mEvents.insert(std::make_pair(when, EventData(event_type, elabel))); - - count_adjust_locked(event_type, 1); -} - -void RsTickEvent::schedule_in(uint32_t event_type, uint32_t in_secs) -{ - std::string elabel; - RsTickEvent::schedule_in(event_type, in_secs, elabel); -} - - -void RsTickEvent::schedule_in(uint32_t event_type, uint32_t in_secs, const std::string &elabel) -{ -#ifdef DEBUG_EVENTS - std::cerr << "RsTickEvent::schedule_in(" << event_type << ", " << elabel << ") in " << in_secs << " secs"; - std::cerr << std::endl; -#endif // DEBUG_EVENTS - - rstime_t event_time = time(NULL) + in_secs; - RsTickEvent::schedule_event(event_type, event_time, elabel); -} - - -void RsTickEvent::handle_event(uint32_t event_type, const std::string &elabel) -{ - std::cerr << "RsTickEvent::handle_event(" << event_type << ", " << elabel; - std::cerr << ") ERROR Not Handled"; - std::cerr << std::endl; -} - - -int32_t RsTickEvent::event_count(uint32_t event_type) -{ - RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it; - - it = mEventCount.find(event_type); - if (it == mEventCount.end()) - { - return 0; - } - - return it->second; -} - - -bool RsTickEvent::prev_event_ago(uint32_t event_type, int32_t &age) -{ - RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it; - - it = mPreviousEvent.find(event_type); - if (it == mPreviousEvent.end()) - { - return false; - } - - age = time(NULL) - it->second; - return true; -} - - -void RsTickEvent::count_adjust_locked(uint32_t event_type, int32_t change) -{ - std::map::iterator it; - - it = mEventCount.find(event_type); - if (it == mEventCount.end()) - { - mEventCount[event_type] = 0; - it = mEventCount.find(event_type); - } - - it->second += change; - if (it->second < 0) - { - std::cerr << "RsTickEvent::count_adjust() ERROR: COUNT < 0"; - std::cerr << std::endl; - - it->second = 0; - } -} - - -void RsTickEvent::note_event_locked(uint32_t event_type) -{ - mPreviousEvent[event_type] = time(NULL); -} - - diff --git a/libretroshare/src/util/rstickevent.h b/libretroshare/src/util/rstickevent.h deleted file mode 100644 index 7f2c9188c..000000000 --- a/libretroshare/src/util/rstickevent.h +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rstickevent.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * 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 . * - * * - *******************************************************************************/ -#ifndef RS_UTIL_TICK_EVENT -#define RS_UTIL_TICK_EVENT - - -/* - * - * A simple event queue... to avoid having to continually write separate one. - */ - -#include -#include "util/rstime.h" - -#include "util/rsthreads.h" - -class RsTickEvent -{ - public: - RsTickEvent():mEventMtx("TickEventMtx") { return; } - -void tick_events(); - -void schedule_now(uint32_t event_type); -void schedule_now(uint32_t event_type, const std::string &elabel); - -void schedule_event(uint32_t event_type, rstime_t when, const std::string &elabel); - -void schedule_in(uint32_t event_type, uint32_t in_secs); -void schedule_in(uint32_t event_type, uint32_t in_secs, const std::string &elabel); - -int32_t event_count(uint32_t event_type); -bool prev_event_ago(uint32_t event_type, int32_t &age); - - protected: - - // Overloaded to handle the events. -virtual void handle_event(uint32_t event_type, const std::string &event_label); - - private: - - class EventData - { - public: - EventData() :mEventType(0) { return; } - EventData(uint32_t etype) :mEventType(etype) { return; } - EventData(uint32_t etype, std::string elabel) :mEventLabel(elabel), mEventType(etype) { return; } - - std::string mEventLabel; - uint32_t mEventType; - }; - -void count_adjust_locked(uint32_t event_type, int32_t change); -void note_event_locked(uint32_t event_type); - - RsMutex mEventMtx; - std::map mEventCount; - std::map mPreviousEvent; - std::multimap mEvents; -}; - -#endif // RS_UTIL_TICK_EVENT diff --git a/libretroshare/src/util/rstime.cc b/libretroshare/src/util/rstime.cc deleted file mode 100644 index d2180775e..000000000 --- a/libretroshare/src/util/rstime.cc +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rstime.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include -#include -#include - -#include "rstime.h" - -namespace rstime { - -int rs_usleep(uint32_t micro_seconds) -{ - while(micro_seconds >= 1000000) - { - // usleep cannot be called with 1000000 or more. - - usleep(500000) ; - usleep(500000) ; - - micro_seconds -= 1000000 ; - } - usleep(micro_seconds) ; - - return 0 ; -} - -RsScopeTimer::RsScopeTimer(const std::string& name) -{ - _name = name ; - start(); -} - -RsScopeTimer::~RsScopeTimer() -{ - if (!_name.empty()) - { - std::cerr << "Time for \"" << _name << "\": " << duration() << std::endl; - } -} - -double RsScopeTimer::currentTime() -{ - timeval tv ; - gettimeofday(&tv,NULL) ; - return (tv.tv_sec % 10000) + tv.tv_usec/1000000.0f ; // the %1000 is here to allow double precision to cover the decimals. -} - -void RsScopeTimer::start() -{ - _seconds = currentTime(); -} - -double RsScopeTimer::duration() -{ - return currentTime() - _seconds; -} - -} diff --git a/libretroshare/src/util/rstime.h b/libretroshare/src/util/rstime.h deleted file mode 100644 index 6cc01e486..000000000 --- a/libretroshare/src/util/rstime.h +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rstime.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2013 by Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#ifdef WINDOWS_SYS -#include -#else -#include -#endif -#include // Added for comfort of users of this util header -#include "util/rsdeprecate.h" - -/** - * Safer alternative to time_t. - * As time_t have not same lenght accross platforms, even though representation - * is not guaranted to be the same but we found it being number of seconds since - * the epoch for time points in all platforms we could test, or plain seconds - * for intervals. - * Still in some platforms it's 32bit long and in other 64bit long. - * To avoid uncompatibility due to different serialzation format use this - * reasonably safe alternative instead. - */ -typedef int64_t rstime_t; - -// Do we really need this? Our names have rs prefix to avoid pollution already! -namespace rstime { - -/** - * @deprecated { std::this_thread::sleep_for or - * std::this_thread::sleep_until instead } - * @brief This is a cross-system definition of usleep, which accepts any - * 32 bits number of micro-seconds. - */ -RS_DEPRECATED_FOR("std::this_thread::sleep_for") -int rs_usleep(uint32_t micro_seconds); - - /* Use this class to measure and display time duration of a given environment: - - { - RsScopeTimer timer("callToMeasure()") ; - - callToMeasure() ; - } - - */ - - class RsScopeTimer - { - public: - RsScopeTimer(const std::string& name); - ~RsScopeTimer(); - - void start(); - double duration(); - - static double currentTime(); - - private: - std::string _name ; - double _seconds ; - }; - -} diff --git a/libretroshare/src/util/rsurl.cc b/libretroshare/src/util/rsurl.cc deleted file mode 100644 index 5da7bbaf4..000000000 --- a/libretroshare/src/util/rsurl.cc +++ /dev/null @@ -1,304 +0,0 @@ -/* - * RetroShare - * Copyright (C) 2018-2019 Gioacchino Mazzurco - * - * 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 . - */ - - -#include -#include -#include -#include -#include - -#include "rsurl.h" -#include "serialiser/rstypeserializer.h" -#include "util/rsnet.h" - -using namespace std; - -RsUrl::RsUrl() : mPort(0), mHasPort(false) {} - -RsUrl::RsUrl(const std::string& urlStr) : mPort(0), mHasPort(false) -{ fromString(urlStr); } - -RsUrl::RsUrl(const sockaddr_storage& addr): mPort(0), mHasPort(false) -{ - switch(addr.ss_family) - { - case AF_INET: setScheme("ipv4"); break; - case AF_INET6: setScheme("ipv6"); break; - default: - { - std::string addrDump; - sockaddr_storage_dump(addr, &addrDump); - RsErr() << __PRETTY_FUNCTION__ << " got invalid addr: " << addrDump - << std::endl; - return; - } - } - - setHost(sockaddr_storage_iptostring(addr)); - setPort(sockaddr_storage_port(addr)); -} - -RsUrl& RsUrl::fromString(const std::string& urlStr) -{ - size_t endI = urlStr.size()-1; - - size_t schemeEndI = urlStr.find(schemeSeparator); - if(schemeEndI >= endI) - { - mScheme = urlStr; - return *this; - } - - mScheme = urlStr.substr(0, schemeEndI); - - size_t hostBeginI = schemeEndI + 3; - if(hostBeginI >= endI) return *this; - - bool hasSquareBr = (urlStr[hostBeginI] == ipv6WrapOpen[0]); - size_t hostEndI; - if(hasSquareBr) - { - if(++hostBeginI >= endI) return *this; - hostEndI = urlStr.find(ipv6WrapClose, hostBeginI); - mHost = urlStr.substr(hostBeginI, hostEndI - hostBeginI); - ++hostEndI; - } - else - { - hostEndI = urlStr.find(pathSeparator, hostBeginI); - hostEndI = min(hostEndI, urlStr.find(portSeparator, hostBeginI)); - hostEndI = min(hostEndI, urlStr.find(querySeparator, hostBeginI)); - hostEndI = min(hostEndI, urlStr.find(fragmentSeparator, hostBeginI)); - - mHost = urlStr.substr(hostBeginI, hostEndI - hostBeginI); - } - - if( hostEndI >= endI ) return *this; - - mHasPort = (sscanf(&urlStr[hostEndI], ":%hu", &mPort) == 1); - - size_t pathBeginI = urlStr.find(pathSeparator, hostBeginI); - size_t pathEndI = string::npos; - if(pathBeginI < endI) - { - pathEndI = urlStr.find(querySeparator, pathBeginI); - pathEndI = min(pathEndI, urlStr.find(fragmentSeparator, pathBeginI)); - mPath = UrlDecode(urlStr.substr(pathBeginI, pathEndI - pathBeginI)); - if(pathEndI >= endI) return *this; - } - - size_t queryBeginI = urlStr.find(querySeparator, hostBeginI); - size_t queryEndI = urlStr.find(fragmentSeparator, hostBeginI); - if(queryBeginI < endI) - { - string qStr = urlStr.substr(queryBeginI+1, queryEndI-queryBeginI-1); - - size_t kPos = 0; - size_t assPos = qStr.find(queryAssign); - do - { - size_t vEndPos = qStr.find(queryFieldSep, assPos); - mQuery.insert( std::make_pair( qStr.substr(kPos, assPos-kPos), - UrlDecode(qStr.substr(assPos+1, vEndPos-assPos-1)) - ) ); - kPos = vEndPos+1; - assPos = qStr.find(queryAssign, vEndPos); - } - while(assPos < endI); - - if(queryEndI >= endI) return *this; - } - - size_t fragmentBeginI = urlStr.find(fragmentSeparator, hostBeginI); - if(fragmentBeginI < endI) - mFragment = UrlDecode(urlStr.substr(++fragmentBeginI)); - - return *this; -} - -std::string RsUrl::toString() const -{ - std::string urlStr(mScheme); - urlStr += schemeSeparator; - - if(!mHost.empty()) - { - if(mHost.find(ipv6Separator) != string::npos && - mHost[0] != ipv6WrapOpen[0] ) - urlStr += ipv6WrapOpen + mHost + ipv6WrapClose; - else urlStr += mHost; - } - - if(mHasPort) urlStr += portSeparator + std::to_string(mPort); - - urlStr += UrlEncode(mPath, pathSeparator); - - bool hasQuery = !mQuery.empty(); - if(hasQuery) urlStr += querySeparator; - for(auto&& kv : mQuery) - { - urlStr += kv.first; - urlStr += queryAssign; - urlStr += UrlEncode(kv.second); - urlStr += queryFieldSep; - } - if(hasQuery) urlStr.pop_back(); - - if(!mFragment.empty()) urlStr += fragmentSeparator + UrlEncode(mFragment); - - return urlStr; -} - -const std::string& RsUrl::scheme() const { return mScheme; } -RsUrl& RsUrl::setScheme(const std::string& scheme) -{ - mScheme = scheme; - return *this; -} - -const std::string& RsUrl::host() const { return mHost; } -RsUrl& RsUrl::setHost(const std::string& host) -{ - mHost = host; - return *this; -} - -bool RsUrl::hasPort() const { return mHasPort; } -uint16_t RsUrl::port(uint16_t def) const -{ - if(mHasPort) return mPort; - return def; -} -RsUrl& RsUrl::setPort(uint16_t port) -{ - mPort = port; - mHasPort = true; - return *this; -} -RsUrl& RsUrl::unsetPort() -{ - mPort = 0; - mHasPort = false; - return *this; -} - -const std::string& RsUrl::path() const { return mPath; } -RsUrl& RsUrl::setPath(const std::string& path) -{ - mPath = path; - return *this; -} - -const std::map& RsUrl::query() const -{ return mQuery; } -RsUrl& RsUrl::setQuery(const std::map& query) -{ - mQuery = query; - return *this; -} -RsUrl& RsUrl::setQueryKV(const std::string& key, const std::string& value) -{ - mQuery.insert(std::make_pair(key, value)); - return *this; -} -RsUrl& RsUrl::delQueryK(const std::string& key) -{ - mQuery.erase(key); - return *this; -} -bool RsUrl::hasQueryK(const std::string& key) -{ return (mQuery.find(key) != mQuery.end()); } -rs_view_ptr RsUrl::getQueryV(const std::string& key) -{ - if(hasQueryK(key)) return &(mQuery.find(key)->second); - return nullptr; -} - -const std::string& RsUrl::fragment() const { return mFragment; } -RsUrl& RsUrl::setFragment(const std::string& fragment) -{ - mFragment = fragment; - return *this; -} - -/*static*/ std::string RsUrl::UrlEncode( const std::string& str, - const std::string& ignore ) -{ - ostringstream escaped; - escaped.fill('0'); - escaped << hex; - - for (string::value_type c : str) - { - // Keep alphanumeric and other accepted characters intact - if ( isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~' - || ignore.find(c) != string::npos ) - { - escaped << c; - continue; - } - - // Any other characters are percent-encoded - escaped << uppercase; - escaped << '%' << setw(2) << int((unsigned char) c); - escaped << nouppercase; - } - - return escaped.str(); -} - -/*static*/ std::string RsUrl::UrlDecode(const std::string& str) -{ - ostringstream decoded; - - size_t len = str.size(); - size_t boundary = len-2; // % Encoded char must be at least 2 hex char - for (size_t i = 0; i < len; ++i) - { - if(str[i] == '%' && i < boundary) - { - decoded << static_cast(std::stoi( - str.substr(++i, 2), nullptr, 16 )); - ++i; - } - else decoded << str[i]; - } - - return decoded.str(); -} - -void RsUrl::serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - std::string urlString = toString(); - RS_SERIAL_PROCESS(urlString); - fromString(urlString); -} - -/*static*/ const std::string RsUrl::schemeSeparator("://"); -/*static*/ const std::string RsUrl::ipv6WrapOpen("["); -/*static*/ const std::string RsUrl::ipv6Separator(":"); -/*static*/ const std::string RsUrl::ipv6WrapClose("]"); -/*static*/ const std::string RsUrl::portSeparator(":"); -/*static*/ const std::string RsUrl::pathSeparator("/"); -/*static*/ const std::string RsUrl::querySeparator("?"); -/*static*/ const std::string RsUrl::queryAssign("="); -/*static*/ const std::string RsUrl::queryFieldSep("&"); -/*static*/ const std::string RsUrl::fragmentSeparator("#"); - diff --git a/libretroshare/src/util/rsurl.h b/libretroshare/src/util/rsurl.h deleted file mode 100644 index 6e6d124c3..000000000 --- a/libretroshare/src/util/rsurl.h +++ /dev/null @@ -1,114 +0,0 @@ -#pragma once -/* - * RetroShare - * Copyright (C) 2018 Gioacchino Mazzurco - * - * 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 . - */ - -#include -#include - -#include "util/rsmemory.h" -#include "serialiser/rsserializable.h" - -struct sockaddr_storage; - -/** - * Very simplistic and minimal URL helper class for RetroShare, after looking - * for a small and self-contained C/C++ URL parsing and manipulation library, - * haven't found nothing satisfactory except for implementation like QUrl that - * rely on bigger library. - * ATM this implementation is not standard compliant and doesn't aim to be. - * Improvements to this are welcome. - * - * Anyway this should support most common URLs of the form - * scheme://host[:port][/path][?query][#fragment] - */ -struct RsUrl : RsSerializable -{ - RsUrl(); - explicit RsUrl(const std::string& urlStr); - explicit RsUrl(const sockaddr_storage& ssas); - - RsUrl& fromString(const std::string& urlStr); - std::string toString() const; - - const std::string& scheme() const; - RsUrl& setScheme(const std::string& scheme); - - const std::string& host() const; - RsUrl& setHost(const std::string& host); - - bool hasPort() const; - uint16_t port(uint16_t def = 0) const; - RsUrl& setPort(uint16_t port); - RsUrl& unsetPort(); - - const std::string& path() const; - RsUrl& setPath(const std::string& path); - - const std::map& query() const; - RsUrl& setQuery(const std::map& query); - RsUrl& setQueryKV(const std::string& key, const std::string& value); - RsUrl& delQueryK(const std::string& key); - bool hasQueryK(const std::string& key); - rs_view_ptr getQueryV(const std::string& key); - - const std::string& fragment() const; - RsUrl& setFragment(const std::string& fragment); - - static std::string UrlEncode(const std::string& str, - const std::string& ignoreChars = ""); - static std::string UrlDecode(const std::string& str); - - inline bool operator<(const RsUrl& rhs) const - { return toString() < rhs.toString(); } - inline bool operator>(const RsUrl& rhs) const - { return toString() > rhs.toString(); } - inline bool operator<=(const RsUrl& rhs) const - { return toString() <= rhs.toString(); } - inline bool operator>=(const RsUrl& rhs) const - { return toString() >= rhs.toString(); } - inline bool operator==(const RsUrl& rhs) const - { return toString() == rhs.toString(); } - inline bool operator!=(const RsUrl& rhs) const - { return toString() != rhs.toString(); } - - /// @see RsSerializable - virtual void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx); - - static const std::string schemeSeparator; - static const std::string ipv6WrapOpen; - static const std::string ipv6Separator; - static const std::string ipv6WrapClose; - static const std::string portSeparator; - static const std::string pathSeparator; - static const std::string querySeparator; - static const std::string queryAssign; - static const std::string queryFieldSep; - static const std::string fragmentSeparator; - -private: - - std::string mScheme; - std::string mHost; - uint16_t mPort; - bool mHasPort; - std::string mPath; - std::map mQuery; - std::string mFragment; -}; - diff --git a/libretroshare/src/util/rswin.h b/libretroshare/src/util/rswin.h deleted file mode 100644 index 22e2ead96..000000000 --- a/libretroshare/src/util/rswin.h +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rswin.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2010, Thomas Kister * - * * - * 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 . * - * * - *******************************************************************************/ - -/** - * This file provides helper functions for the windows environment - */ - - -#ifndef RSWIN_H_ -#define RSWIN_H_ - -#ifdef WINDOWS_SYS - -#include -#include - -// For win32 systems (tested on MingW+Ubuntu) -#define stat64 _stati64 - -// Should be in Iphlpapi.h, but mingw doesn't seem to have these -// Values copied directly from: -// http://msdn.microsoft.com/en-us/library/aa366845(v=vs.85).aspx -// (Title: MIB_IPADDRROW structure) - -#ifndef MIB_IPADDR_DISCONNECTED -#define MIB_IPADDR_DISCONNECTED 0x0008 // Address is on disconnected interface -#endif - -#ifndef MIB_IPADDR_DELETED -#define MIB_IPADDR_DELETED 0x0040 // Address is being deleted -#endif - -#endif // WINDOWS_SYS - -#endif // RSWIN_H_ diff --git a/libretroshare/src/util/smallobject.cc b/libretroshare/src/util/smallobject.cc deleted file mode 100644 index 5559e2af6..000000000 --- a/libretroshare/src/util/smallobject.cc +++ /dev/null @@ -1,349 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: smallobject.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2011, Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#include -#include "smallobject.h" -#include "util/rsthreads.h" -#include "util/rsmemory.h" - -using namespace RsMemoryManagement ; - -RsMutex SmallObject::_mtx("SmallObject") ; -SmallObjectAllocator SmallObject::_allocator(RsMemoryManagement::MAX_SMALL_OBJECT_SIZE) ; - -void Chunk::init(size_t blockSize,unsigned char blocks) -{ - _data = new unsigned char[blockSize*blocks] ; - _firstAvailableBlock = 0 ; - _blocksAvailable = blocks ; - - // Inits the first byte of each block to point to the next available block - // - unsigned char *p = _data ; - - for(unsigned char i=0;i= 2) ; - - unsigned char *result = _data + _firstAvailableBlock*blockSize ; - - // Grab id of next available block from the block being allocated. - - // Always the case because the first available block is the first, so the next - // available block is given by *result. - // - _firstAvailableBlock = *result ; - --_blocksAvailable ; - - return result ; -} - -void Chunk::deallocate(void *p,size_t blockSize) -{ - assert(p >= _data) ; - - unsigned char *toRelease = static_cast(p) ; - - // alignment check - - assert( (toRelease - _data) % blockSize == 0 ) ; - - *toRelease = _firstAvailableBlock ; - _firstAvailableBlock = static_cast( (toRelease - _data)/blockSize) ; - - // truncation check - - assert(_firstAvailableBlock == (toRelease - _data)/blockSize); - - ++_blocksAvailable ; -} - -void Chunk::printStatistics(int blockSize) const -{ - std::cerr << " blocksAvailable : " << (int)_blocksAvailable << std::endl; - std::cerr << " firstBlockAvailable: " << (int)_firstAvailableBlock << std::endl; - std::cerr << " blocks : " << (void*)_data << " to " << (void*)(_data+BLOCKS_PER_CHUNK*blockSize) << std::endl; -} - -FixedAllocator::FixedAllocator(size_t bytes) -{ - _blockSize = bytes ; - _numBlocks = BLOCKS_PER_CHUNK ; - _allocChunk = -1 ; - _deallocChunk = -1 ; -} -FixedAllocator::~FixedAllocator() -{ - for(uint32_t i=0;i<_chunks.size();++i) - { - _chunks[i]->free() ; - delete _chunks[i] ; - } -} - -void *FixedAllocator::allocate() -{ - if(_allocChunk < 0 || _chunks[_allocChunk]->_blocksAvailable == 0) - { - // find availabel memory in this chunk - // - uint32_t i ; - _allocChunk = -1 ; - for(i=0;i<_chunks.size();++i) - if(_chunks[i]->_blocksAvailable > 0) // found a chunk - { - _allocChunk = i ; - break ; - } - if( _allocChunk < 0 ) - { - _chunks.reserve(_chunks.size()+1) ; - Chunk *newChunk = new Chunk; - - if(newChunk == NULL) - { - std::cerr << "RsMemoryManagement: ran out of memory !" << std::endl; - exit(-1) ; - } - newChunk->init(_blockSize,_numBlocks) ; - _chunks.push_back(newChunk) ; - - _allocChunk = _chunks.size()-1 ; - _deallocChunk = _chunks.size()-1 ; - } - - } - assert(_chunks[_allocChunk] != NULL) ; - assert(_chunks[_allocChunk]->_blocksAvailable > 0) ; - - return _chunks[_allocChunk]->allocate(_blockSize) ; -} -void FixedAllocator::deallocate(void *p) -{ - if(_deallocChunk < 0 || !chunkOwnsPointer(*_chunks[_deallocChunk],p)) - { - // find the chunk that contains this pointer. Perform a linear search. - - _deallocChunk = -1 ; - - for(uint32_t i=0;i<_chunks.size();++i) - if(chunkOwnsPointer(*_chunks[i],p)) - { - _deallocChunk = i ; - break ; - } - } - assert(_chunks[_deallocChunk] != NULL) ; - - _chunks[_deallocChunk]->deallocate(p,_blockSize) ; - - if(_chunks[_deallocChunk]->_blocksAvailable == BLOCKS_PER_CHUNK) - { - _chunks[_deallocChunk]->free() ; - delete _chunks[_deallocChunk] ; - - _chunks[_deallocChunk] = _chunks.back() ; - if(_allocChunk == _deallocChunk) _allocChunk = -1 ; - if(_allocChunk == ((int)_chunks.size())-1) _allocChunk = _deallocChunk ; - _deallocChunk = -1 ; - _chunks.pop_back(); - } -} -uint32_t FixedAllocator::currentSize() const -{ - uint32_t res = 0 ; - - for(uint32_t i=0;i<_chunks.size();++i) - res += (_numBlocks - _chunks[i]->_blocksAvailable) * _blockSize ; - - return res ; -} -void FixedAllocator::printStatistics() const -{ - std::cerr << " numBLocks=" << (int)_numBlocks << std::endl; - std::cerr << " blockSize=" << (int)_blockSize << std::endl; - std::cerr << " Number of chunks: " << _chunks.size() << std::endl; - for(uint32_t i=0;i<_chunks.size();++i) - _chunks[i]->printStatistics(_blockSize) ; -} - -SmallObjectAllocator::SmallObjectAllocator(size_t maxObjectSize) - : _maxObjectSize(maxObjectSize) -{ - RsStackMutex m(SmallObject::_mtx) ; - - _lastAlloc = NULL ; - _lastDealloc = NULL ; - _active = true ; -} - -SmallObjectAllocator::~SmallObjectAllocator() -{ - RsStackMutex m(SmallObject::_mtx) ; - - //std::cerr << __PRETTY_FUNCTION__ << " not deleting. Leaving it to the system." << std::endl; - - _active = false ; - - uint32_t still_allocated = 0 ; - - for(std::map::const_iterator it(_pool.begin());it!=_pool.end();++it) - still_allocated += it->second->currentSize() ; - //delete it->second ; - - std::cerr << "Memory still in use at end of program: " << still_allocated << " bytes." << std::endl; -} - -void *SmallObjectAllocator::allocate(size_t bytes) -{ - if(bytes > _maxObjectSize) - return rs_malloc(bytes) ; - else if(_lastAlloc != NULL && _lastAlloc->blockSize() == bytes) - return _lastAlloc->allocate() ; - else - { - std::map::iterator it(_pool.find(bytes)) ; - - if(it == _pool.end()) - { - _pool[bytes] = new FixedAllocator(bytes) ; - it = _pool.find(bytes) ; - } - _lastAlloc = it->second ; - - return it->second->allocate() ; - } -} - -void SmallObjectAllocator::deallocate(void *p,size_t bytes) -{ - if(bytes > _maxObjectSize) - free(p) ; - else if(_lastDealloc != NULL && _lastDealloc->blockSize() == bytes) - _lastDealloc->deallocate(p) ; - else - { - std::map::iterator it(_pool.find(bytes)) ; - - if(it == _pool.end()) - { - _pool[bytes] = new FixedAllocator(bytes) ; - it = _pool.find(bytes) ; - } - it->second->deallocate(p) ; - _lastDealloc = it->second ; - } -} - -void SmallObjectAllocator::printStatistics() const -{ - std::cerr << "RsMemoryManagement Statistics:" << std::endl; - std::cerr << " Total Fixed-size allocators: " << _pool.size() << std::endl; - std::cerr << "Pool" << std::endl; - - for(std::map::const_iterator it(_pool.begin());it!=_pool.end();++it) - { - std::cerr << " Allocator for size " << it->first << " : " << std::endl; - std::cerr << " Last Alloc: " << _lastAlloc << std::endl; - std::cerr << " Last Dealloc: " << _lastDealloc << std::endl; - it->second->printStatistics() ; - } -} - -void *SmallObject::operator new(size_t size) -{ -#ifdef DEBUG_MEMORY - bool print=false ; - { - RsStackMutex m(_mtx) ; - static rstime_t last_time = 0 ; - rstime_t now = time(NULL) ; - if(now > last_time + 20) - { - last_time = now ; - print=true ; - } - } - if(print) - printStatistics() ; -#endif - - RsStackMutex m(_mtx) ; - - // This should normally not happen. But that prevents a crash when quitting, since we cannot prevent the constructor - // of an object to call operator new(), nor to handle the case where it returns NULL. - // The memory will therefore not be deleted if that happens. We thus print a warning. - - if(_allocator._active) - return _allocator.allocate(size) ; - else - { - std::cerr << "(EE) allocating " << size << " bytes of memory that cannot be deleted. This is a bug, except if it happens when closing Retroshare" << std::endl; - return malloc(size) ; - } - -#ifdef DEBUG_MEMORY - std::cerr << "new RsItem: " << p << ", size=" << size << std::endl; -#endif -} - -void SmallObject::operator delete(void *p,size_t size) -{ - RsStackMutex m(_mtx) ; - - if(!_allocator._active) - return ; - - _allocator.deallocate(p,size) ; -#ifdef DEBUG_MEMORY - std::cerr << "del RsItem: " << p << ", size=" << size << std::endl; -#endif -} - -void SmallObject::printStatistics() -{ - RsStackMutex m(_mtx) ; - - if(!_allocator._active) - return ; - - _allocator.printStatistics() ; -} - -void RsMemoryManagement::printStatistics() -{ - SmallObject::printStatistics(); -} - - diff --git a/libretroshare/src/util/smallobject.h b/libretroshare/src/util/smallobject.h deleted file mode 100644 index 452037ac6..000000000 --- a/libretroshare/src/util/smallobject.h +++ /dev/null @@ -1,116 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: smallobject.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2011, Cyril Soler * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include -#include - -#include - -namespace RsMemoryManagement -{ - static const int MAX_SMALL_OBJECT_SIZE = 128 ; - static const unsigned char BLOCKS_PER_CHUNK = 255 ; - - struct Chunk - { - void init(size_t blockSize,unsigned char blocks); - void free() ; - - void *allocate(size_t); - void deallocate(void *p,size_t blockSize); - - unsigned char *_data ; - unsigned char _firstAvailableBlock ; - unsigned char _blocksAvailable ; - - void printStatistics(int blockSize) const ; - }; - - class FixedAllocator - { - public: - FixedAllocator(size_t bytes) ; - virtual ~FixedAllocator() ; - - void *allocate(); - void deallocate(void *p) ; - inline size_t blockSize() const { return _blockSize ; } - - inline bool chunkOwnsPointer(const Chunk& c,void *p) const - { - return intptr_t(p) >= intptr_t(c._data) && (intptr_t(static_cast(p))-intptr_t(c._data))/intptr_t(_blockSize)< intptr_t( _numBlocks ); - } - - void printStatistics() const ; - uint32_t currentSize() const; - private: - size_t _blockSize ; - unsigned char _numBlocks ; - std::vector _chunks ; - int _allocChunk ; // last chunk that provided allocation. -1 if not inited - int _deallocChunk ; // last chunk that provided de-allocation. -1 if not inited - }; - - class SmallObjectAllocator - { - public: - SmallObjectAllocator(size_t maxObjectSize) ; - virtual ~SmallObjectAllocator() ; - - void *allocate(size_t numBytes) ; - void deallocate(void *p,size_t size) ; - - void printStatistics() const ; - - bool _active ; - private: - std::map _pool ; - FixedAllocator *_lastAlloc ; - FixedAllocator *_lastDealloc ; - size_t _maxObjectSize ; - }; - - class SmallObject - { - public: - static void *operator new(size_t size) ; - static void operator delete(void *p,size_t size) ; - - static void printStatistics() ; - - virtual ~SmallObject() {} - - private: - static SmallObjectAllocator _allocator ; - static RsMutex _mtx; - - friend class SmallObjectAllocator ; - }; - - extern void printStatistics() ; -} - - diff --git a/libretroshare/src/util/stacktrace.h b/libretroshare/src/util/stacktrace.h deleted file mode 100644 index cb7dc4e71..000000000 --- a/libretroshare/src/util/stacktrace.h +++ /dev/null @@ -1,312 +0,0 @@ -/******************************************************************************* - * libretroshare * - * * - * Copyright (C) 2016-2018 Gioacchino Mazzurco * - * Copyright (C) 2008 Timo Bingmann http://idlebox.net/ * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#ifdef __ANDROID__ -# include "util/rsdebug.h" -#endif - -/** - * @brief Print a backtrace to FILE* out. - * @param[in] demangle true to demangle C++ symbols requires malloc working, in - * some patological cases like a SIGSEGV received during a malloc this would - * cause deadlock so pass false if you may be in such situation (like in a - * SIGSEGV handler ) - * @param[in] out output file - * @param[in] maxFrames maximum number of stack frames you want to bu printed - */ -static inline void print_stacktrace( - bool demangle = true, FILE *out = stderr, unsigned int maxFrames = 63 ); - - -#if defined(__linux__) && defined(__GLIBC__) - -#include -#include - -static inline void print_stacktrace( - bool demangle, FILE* out, unsigned int maxFrames ) -{ - if(!out) - { - fprintf(stderr, "print_stacktrace invalid output file!\n"); - return; - } - - fprintf(out, "stack trace:\n"); - - // storage array for stack trace address data - void* addrlist[maxFrames+1]; - - // retrieve current stack addresses - int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*)); - - if (addrlen == 0) - { - fprintf(out, " \n"); - return; - } - - if(!demangle) - { - int outFd = fileno(out); - if(outFd < 0) - { - fprintf(stderr, "print_stacktrace invalid output file descriptor!\n"); - return; - } - - backtrace_symbols_fd(addrlist, addrlen, outFd); - return; - } - - // resolve addresses into strings containing "filename(function+address)", - // this array must be free()-ed - char** symbollist = backtrace_symbols(addrlist, addrlen); - - // allocate string which will be filled with the demangled function name - size_t funcnamesize = 256; - char* funcname = (char*)malloc(funcnamesize); - - // iterate over the returned symbol lines. skip the first, it is the - // address of this function. - for (int i = 1; i < addrlen; i++) - { - char *begin_name = 0, *begin_offset = 0, *end_offset = 0; - - /* find parentheses and +address offset surrounding the mangled - * name: ./module(function+0x15c) [0x8048a6d] */ - for (char *p = symbollist[i]; *p; ++p) - { - if (*p == '(') begin_name = p; - else if (*p == '+') begin_offset = p; - else if (*p == ')' && begin_offset) - { - end_offset = p; - break; - } - } - - if ( begin_name && begin_offset && end_offset - && begin_name < begin_offset ) - { - *begin_name++ = '\0'; - *begin_offset++ = '\0'; - *end_offset = '\0'; - - // mangled name is now in [begin_name, begin_offset) and caller - // offset in [begin_offset, end_offset). now apply - // __cxa_demangle(): - - int status; - char* ret = abi::__cxa_demangle( - begin_name, funcname, &funcnamesize, &status ); - if (status == 0) - { - funcname = ret; // use possibly realloc()-ed string - fprintf( out, " %s : %s+%s\n", - symbollist[i], funcname, begin_offset ); - } - else - { - // demangling failed. Output function name as a C function with - // no arguments. - fprintf( out, " %s : %s()+%s\n", - symbollist[i], begin_name, begin_offset ); - } - } - else - { - // couldn't parse the line? print the whole line. - fprintf(out, " %s\n", symbollist[i]); - } - } - - free(funcname); - 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 -#include -#include - -struct RsAndroidBacktraceState -{ - void** current; - void** end; -}; - -static inline _Unwind_Reason_Code android_unwind_callback( - struct _Unwind_Context* context, void* arg ) -{ - RsAndroidBacktraceState* state = static_cast(arg); - uintptr_t pc = _Unwind_GetIP(context); - if(pc) - { - if (state->current == state->end) return _URC_END_OF_STACK; - - *state->current++ = reinterpret_cast(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(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__) - -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__) - -/** - * @brief CrashStackTrace catch crash signals and print stack trace - * Inspired too https://oroboro.com/stack-trace-on-crash/ - */ -struct CrashStackTrace -{ - CrashStackTrace() - { - signal(SIGABRT, &CrashStackTrace::abortHandler); - signal(SIGSEGV, &CrashStackTrace::abortHandler); - signal(SIGILL, &CrashStackTrace::abortHandler); - signal(SIGFPE, &CrashStackTrace::abortHandler); -#ifdef SIGBUS - signal(SIGBUS, &CrashStackTrace::abortHandler); -#endif - } - - [[ noreturn ]] - static void abortHandler(int signum) - { - // associate each signal with a signal name string. - const char* name = nullptr; - switch(signum) - { - case SIGABRT: name = "SIGABRT"; break; - case SIGSEGV: name = "SIGSEGV"; break; - case SIGILL: name = "SIGILL"; break; - case SIGFPE: name = "SIGFPE"; break; -#ifdef SIGBUS - case SIGBUS: name = "SIGBUS"; break; -#endif - } - -#ifndef __ANDROID__ - /** 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. */ - if(name) - fprintf(stderr, "Caught signal %d (%s)\n", signum, name); - else - 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); - - exit(-signum); - } -}; - diff --git a/libretroshare/src/util/utest.h b/libretroshare/src/util/utest.h deleted file mode 100644 index 1ebd9875a..000000000 --- a/libretroshare/src/util/utest.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _UNIT_TEST_MACROS_H__ -#define _UNIT_TEST_MACROS_H__ - -#include - -#define TFAILURE( s ) printf( "FAILURE: " __FILE__ ":%-4d %s\n", __LINE__, s ) -#define TSUCCESS( s ) printf( "SUCCESS: " __FILE__ ":%-4d %s\n", __LINE__, s ) - -/* careful with this line (no protection) */ -#define INITTEST() int ok = 1; int gok = 1; - -/* declare the variables */ -extern int ok; -extern int gok; - -#define CHECK( b ) do { if ( ! (b) ) { ok = 0; TFAILURE( #b ); } } while(0) -#define FAILED( s ) do { ok = 0; TFAILURE( s ); } while(0) -#define REPORT( s ) do { if ( ! (ok) ) { ok = 0; TFAILURE( s ); } else { TSUCCESS( s );} gok &= ok; ok = 1; } while(0) -#define REPORT2( b, s ) do { if ( ! (b) ) { ok = 0; TFAILURE( s ); } else { TSUCCESS( s );} gok &= ok; ok = 1; } while(0) -#define FINALREPORT( s ) do { gok &= ok; ok = 1; if ( ! (gok) ) { TFAILURE( s ); } else { TSUCCESS( s );} } while(0) -#define TESTRESULT() (!gok) - -#endif diff --git a/openpgpsdk b/openpgpsdk new file mode 160000 index 000000000..178aa8ebc --- /dev/null +++ b/openpgpsdk @@ -0,0 +1 @@ +Subproject commit 178aa8ebcef47e3271d5a5ca5c07e45d3b71c81d diff --git a/openpgpsdk/src/openpgpsdk.pro b/openpgpsdk/src/openpgpsdk.pro deleted file mode 100644 index 66341d0a3..000000000 --- a/openpgpsdk/src/openpgpsdk.pro +++ /dev/null @@ -1,144 +0,0 @@ -# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team -# SPDX-License-Identifier: CC0-1.0 - -!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri") - -TEMPLATE = lib -CONFIG += staticlib - -DEFINES *= OPENSSL_NO_IDEA - -QMAKE_CXXFLAGS *= -Wall -Werror -W - -TARGET = ops -DESTDIR = lib - -!include(use_openpgpsdk.pri):error("Including") - -#################################### Windows ##################################### - -linux-* { - OBJECTS_DIR = temp/linux/obj -} - -win32-g++|win32-clang-g++ { - - HEADERS += openpgpsdk/opsstring.h - SOURCES += openpgpsdk/opsstring.c - - DEFINES *= WIN32_LEAN_AND_MEAN - - # Switch off optimization for release version - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -O0 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE += -O0 - - mLibs = bz2 z ssl crypto - static { - LIBS += $$linkStaticLibs(mLibs) - PRE_TARGETDEPS += $$pretargetStaticLibs(mLibs) - } else { - LIBS += $$linkDynamicLibs(mLibs) - } -} - - -macx { - for(lib, LIB_DIR):LIBS += -L"$$lib" - for(bin, BIN_DIR):LIBS += -L"$$bin" - DEFINES += OPENSSL_NO_CAMELLIA -} - -# Input -HEADERS += openpgpsdk/writer.h \ - openpgpsdk/writer_armoured.h \ - openpgpsdk/version.h \ - openpgpsdk/validate.h \ - openpgpsdk/util.h \ - openpgpsdk/types.h \ - openpgpsdk/streamwriter.h \ - openpgpsdk/std_print.h \ - openpgpsdk/signature.h \ - openpgpsdk/readerwriter.h \ - openpgpsdk/random.h \ - openpgpsdk/partial.h \ - openpgpsdk/packet-show.h \ - openpgpsdk/packet-show-cast.h \ - openpgpsdk/packet-parse.h \ - openpgpsdk/packet.h \ - openpgpsdk/memory.h \ - openpgpsdk/literal.h \ - openpgpsdk/lists.h \ - openpgpsdk/keyring.h \ - openpgpsdk/hash.h \ - openpgpsdk/final.h \ - openpgpsdk/defs.h \ - openpgpsdk/errors.h \ - openpgpsdk/crypto.h \ - openpgpsdk/create.h \ - openpgpsdk/configure.h \ - openpgpsdk/compress.h \ - openpgpsdk/callback.h \ - openpgpsdk/accumulate.h \ - openpgpsdk/armour.h \ - openpgpsdk/parse_local.h \ - openpgpsdk/keyring_local.h \ - openpgpsdk/opsdir.h - -SOURCES += openpgpsdk/accumulate.c \ - openpgpsdk/compress.c \ - openpgpsdk/create.c \ - openpgpsdk/crypto.c \ - openpgpsdk/errors.c \ - openpgpsdk/fingerprint.c \ - openpgpsdk/hash.c \ - openpgpsdk/keyring.c \ - openpgpsdk/lists.c \ - openpgpsdk/memory.c \ - openpgpsdk/openssl_crypto.c \ - openpgpsdk/packet-parse.c \ - openpgpsdk/packet-print.c \ - openpgpsdk/packet-show.c \ - openpgpsdk/random.c \ - openpgpsdk/reader.c \ - openpgpsdk/reader_armoured.c \ - openpgpsdk/reader_encrypted_se.c \ - openpgpsdk/reader_encrypted_seip.c \ - openpgpsdk/reader_fd.c \ - openpgpsdk/reader_hashed.c \ - openpgpsdk/reader_mem.c \ - openpgpsdk/readerwriter.c \ - openpgpsdk/signature.c \ - openpgpsdk/symmetric.c \ - openpgpsdk/util.c \ - openpgpsdk/validate.c \ - openpgpsdk/writer.c \ - openpgpsdk/writer_armour.c \ - openpgpsdk/writer_partial.c \ - openpgpsdk/writer_literal.c \ - openpgpsdk/writer_encrypt.c \ - openpgpsdk/writer_encrypt_se_ip.c \ - openpgpsdk/writer_fd.c \ - openpgpsdk/writer_memory.c \ - openpgpsdk/writer_skey_checksum.c \ - openpgpsdk/writer_stream_encrypt_se_ip.c \ - openpgpsdk/opsdir.c - - -################################# Android ##################################### - -android-* { - -## Add this here because static library are very sensible to order in -## command line - LIBS += -L$$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/lib/ -lssl - INCLUDEPATH += $$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/include - DEPENDPATH += $$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/include - PRE_TARGETDEPS += $$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/lib/libssl.a - - LIBS += -L$$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/lib/ -lcrypto - INCLUDEPATH += $$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/include - DEPENDPATH += $$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/include - PRE_TARGETDEPS += $$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/lib/libcrypto.a -} diff --git a/openpgpsdk/src/openpgpsdk/accumulate.c b/openpgpsdk/src/openpgpsdk/accumulate.c deleted file mode 100644 index 025e08e74..000000000 --- a/openpgpsdk/src/openpgpsdk/accumulate.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include "keyring_local.h" -#include "parse_local.h" -#include -#include -#include - -#include - -typedef struct - { - ops_keyring_t *keyring; - } accumulate_arg_t; - -/** - * \ingroup Core_Callbacks - */ -static ops_parse_cb_return_t accumulate_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) -{ - accumulate_arg_t *arg=ops_parse_cb_get_arg(cbinfo); - const ops_parser_content_union_t *content=&content_->content; - ops_keyring_t *keyring=arg->keyring; - ops_keydata_t *cur=NULL; - const ops_public_key_t *pkey; - - if(keyring->nkeys >= 0) - cur=&keyring->keys[keyring->nkeys]; - - switch(content_->tag) - { - case OPS_PTAG_CT_PUBLIC_KEY: - case OPS_PTAG_CT_SECRET_KEY: - case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: - // printf("New key\n"); - ++keyring->nkeys; - EXPAND_ARRAY(keyring,keys); - - if(content_->tag == OPS_PTAG_CT_PUBLIC_KEY) - pkey=&content->public_key; - else - pkey=&content->secret_key.public_key; - - memset(&keyring->keys[keyring->nkeys],'\0', sizeof keyring->keys[keyring->nkeys]); - - ops_keyid(keyring->keys[keyring->nkeys].key_id,pkey); - ops_fingerprint(&keyring->keys[keyring->nkeys].fingerprint,pkey); - - keyring->keys[keyring->nkeys].type=content_->tag; - - if(content_->tag == OPS_PTAG_CT_PUBLIC_KEY) - keyring->keys[keyring->nkeys].key.pkey=*pkey; - else - keyring->keys[keyring->nkeys].key.skey=content->secret_key; - return OPS_KEEP_MEMORY; - - case OPS_PTAG_CT_USER_ID: - // printf("User ID: %s\n",content->user_id.user_id); - if (!cur) - { - OPS_ERROR(cbinfo->errors,OPS_E_P_NO_USERID, "No user id found"); - return OPS_KEEP_MEMORY; - } - ops_add_userid_to_keydata(cur, &content->user_id); - free(content->user_id.user_id); - return OPS_KEEP_MEMORY; - - case OPS_PARSER_PACKET_END: - if(!cur) - return OPS_RELEASE_MEMORY; - ops_add_packet_to_keydata(cur, &content->packet); - free(content->packet.raw); - return OPS_KEEP_MEMORY; - - case OPS_PARSER_ERROR: - fprintf(stderr,"Error: %s\n",content->error.error); - break; - - case OPS_PARSER_ERRCODE: - switch(content->errcode.errcode) - { - default: - fprintf(stderr,"parse error: %s\n", ops_errcode(content->errcode.errcode)); - } - break; - - default: - break; - } - - // XXX: we now exclude so many things, we should either drop this or - // do something to pass on copies of the stuff we keep - return ops_parse_stacked_cb(content_,cbinfo); -} - -/** - * \ingroup Core_Parse - * - * Parse packets from an input stream until EOF or error. - * - * Key data found in the parsed data is added to #keyring. - * - * \param keyring Pointer to an existing keyring - * \param parse_info Options to use when parsing -*/ - -int ops_parse_and_accumulate(ops_keyring_t *keyring, - ops_parse_info_t *parse_info) - { - int rtn; - - accumulate_arg_t arg; - - if(parse_info->rinfo.accumulate) - { - fprintf(stderr,"Structural error: parse_info->rinfo.accumulate should be ops_false" ) ; - return 0 ; // error - } - //assert(!parse_info->rinfo.accumulate); - - memset(&arg,'\0',sizeof arg); - - arg.keyring=keyring; - /* Kinda weird, but to do with counting, and we put it back after */ - --keyring->nkeys; - - ops_parse_cb_push(parse_info,accumulate_cb,&arg); - - parse_info->rinfo.accumulate=ops_true; - - rtn=ops_parse(parse_info,ops_false); - ++keyring->nkeys; - - return rtn; - } - -static void dump_one_keydata(const ops_keydata_t *key) - { - unsigned n; - - printf("Key ID: "); - hexdump(key->key_id,8); - - printf("\nFingerpint: "); - hexdump(key->fingerprint.fingerprint,key->fingerprint.length); - - printf("\n\nUIDs\n====\n\n"); - for(n=0 ; n < key->nuids ; ++n) - printf("%s\n",key->uids[n].user_id); - - printf("\nPackets\n=======\n"); - for(n=0 ; n < key->npackets ; ++n) - { - printf("\n%03d: ",n); - hexdump(key->packets[n].raw,key->packets[n].length); - } - printf("\n\n"); - } - -// XXX: not a maintained part of the API - use ops_keyring_list() -/** ops_dump_keyring -*/ -void ops_dump_keyring(const ops_keyring_t *keyring) - { - int n; - - for(n=0 ; n < keyring->nkeys ; ++n) - dump_one_keydata(&keyring->keys[n]); - } diff --git a/openpgpsdk/src/openpgpsdk/accumulate.h b/openpgpsdk/src/openpgpsdk/accumulate.h deleted file mode 100644 index eeadb4011..000000000 --- a/openpgpsdk/src/openpgpsdk/accumulate.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_ACCUMULATE_H -#define OPS_ACCUMULATE_H -#endif - -#include "keyring.h" -#include "packet-parse.h" - -int ops_parse_and_accumulate(ops_keyring_t *keyring, - ops_parse_info_t *parse_info); diff --git a/openpgpsdk/src/openpgpsdk/armour.h b/openpgpsdk/src/openpgpsdk/armour.h deleted file mode 100644 index b2f3a8d69..000000000 --- a/openpgpsdk/src/openpgpsdk/armour.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __OPS_ARMOUR_H__ -#define __OPS_ARMOUR_H__ - -#include "packet-parse.h" -#include "signature.h" - -unsigned ops_crc24(unsigned checksum,unsigned char c); - -void ops_reader_push_dearmour(ops_parse_info_t *parse_info); - -void ops_reader_pop_dearmour(ops_parse_info_t *parse_info); -ops_boolean_t ops_writer_push_clearsigned(ops_create_info_t *info, - ops_create_signature_t *sig); -void ops_writer_push_armoured_message(ops_create_info_t *info); -ops_boolean_t ops_writer_switch_to_armoured_signature(ops_create_info_t *info); - -typedef enum - { - OPS_PGP_MESSAGE=1, - OPS_PGP_PUBLIC_KEY_BLOCK, - OPS_PGP_PRIVATE_KEY_BLOCK, - OPS_PGP_MULTIPART_MESSAGE_PART_X_OF_Y, - OPS_PGP_MULTIPART_MESSAGE_PART_X, - OPS_PGP_SIGNATURE - } ops_armor_type_t; - -void ops_writer_push_armoured(ops_create_info_t *info, ops_armor_type_t type); - -#define CRC24_INIT 0xb704ceL - -#endif /* __OPS_ARMOUR_H__ */ - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/callback.h b/openpgpsdk/src/openpgpsdk/callback.h deleted file mode 100644 index 399c3d118..000000000 --- a/openpgpsdk/src/openpgpsdk/callback.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __OPS_CALLBACK_H__ -#define __OPS_CALLBACK_H__ - -#define CB(cbinfo,t,pc) do { (pc)->tag=(t); if(ops_parse_cb((pc),(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0) -/*#define CB(cbinfo,t,pc) do { (pc)->tag=(t); if((cbinfo)->cb(pc,(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0)*/ -//#define CB(cbinfo,t,pc) do { (pc)->tag=(t); if((cbinfo)->cb(pc,(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0) - -#define CBP(info,t,pc) CB(&(info)->cbinfo,t,pc) - -#define ERR(cbinfo,err,code) do { content.content.error.error=err; content.tag=OPS_PARSER_ERROR; ops_parse_cb(&content,(cbinfo)); OPS_ERROR(errors,code,err); return -1; } while(0) - /*#define ERR(err) do { content.content.error.error=err; content.tag=OPS_PARSER_ERROR; ops_parse_cb(&content,cbinfo); return -1; } while(0)*/ - -#define ERRP(info,err) do { C.error.error=err; CBP(info,OPS_PARSER_ERROR,&content); return ops_false; } while(0) - - -#endif /*__OPS_CALLBACK_H__*/ diff --git a/openpgpsdk/src/openpgpsdk/compress.c b/openpgpsdk/src/openpgpsdk/compress.c deleted file mode 100644 index afe3db6ac..000000000 --- a/openpgpsdk/src/openpgpsdk/compress.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Copyright (c) 2005-2009 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh. - * The Contributors have asserted their moral rights under the - * UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include - -#include -#include -#include -#include -#include "parse_local.h" -#include -#include - -static const int debug = 0; - -#define DECOMPRESS_BUFFER 1024 -#define COMPRESS_BUFFER 32768 - -typedef struct - { - ops_compression_type_t type; - ops_region_t *region; - unsigned char in[DECOMPRESS_BUFFER]; - unsigned char out[DECOMPRESS_BUFFER]; - z_stream zstream; // ZIP and ZLIB - size_t offset; - int inflate_ret; - } z_decompress_arg_t; - -typedef struct - { - ops_compression_type_t type; - ops_region_t *region; - char in[DECOMPRESS_BUFFER]; - char out[DECOMPRESS_BUFFER]; - bz_stream bzstream; // BZIP2 - size_t offset; - int inflate_ret; - } bz_decompress_arg_t; - -typedef struct - { - z_stream stream; - unsigned char *src; - unsigned char *dst; - size_t bytes_in; - size_t bytes_out; - } compress_arg_t; - -// \todo remove code duplication between this and bzip2_compressed_data_reader -static int zlib_compressed_data_reader(void *dest,size_t length, - ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - z_decompress_arg_t *arg=ops_reader_get_arg(rinfo); - - if(! (arg->type==OPS_C_ZIP || arg->type==OPS_C_ZLIB) ) // ASSERT(arg->type==OPS_C_ZIP || arg->type==OPS_C_ZLIB); - { - fprintf(stderr,"zlib_compressed_data_reader: unexpected compress format %d\n",arg->type) ; - return -1 ; - } - - //ops_parser_content_t content; - int saved=length; - - if(/*arg->region->indeterminate && */ arg->inflate_ret == Z_STREAM_END - && arg->zstream.next_out == &arg->out[arg->offset]) - return 0; - - if(arg->region->length_read == arg->region->length) - { - if(arg->inflate_ret != Z_STREAM_END) - OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR, - "Compressed data didn't end when region ended."); - /* - else - return 0; - www.zlib.org - */ - } - - while(length > 0) - { - unsigned len; - - if(&arg->out[arg->offset] == arg->zstream.next_out) - { - int ret; - - arg->zstream.next_out=arg->out; - arg->zstream.avail_out=sizeof arg->out; - arg->offset=0; - if(arg->zstream.avail_in == 0) - { - unsigned n=arg->region->length; - - if(!arg->region->indeterminate) - { - n-=arg->region->length_read; - if(n > sizeof arg->in) - n=sizeof arg->in; - } - else - n=sizeof arg->in; - - if(!ops_stacked_limited_read(arg->in,n,arg->region, - errors,rinfo,cbinfo)) - return -1; - - arg->zstream.next_in=arg->in; - arg->zstream.avail_in=arg->region->indeterminate - ? arg->region->last_read : n; - } - - ret=inflate(&arg->zstream,Z_SYNC_FLUSH); - if(ret == Z_STREAM_END) - { - if(!arg->region->indeterminate - && arg->region->length_read != arg->region->length) - OPS_ERROR(cbinfo->errors,OPS_E_P_DECOMPRESSION_ERROR, - "Compressed stream ended before packet end."); - } - else if(ret != Z_OK) - { - fprintf(stderr,"ret=%d\n",ret); - OPS_ERROR(cbinfo->errors,OPS_E_P_DECOMPRESSION_ERROR, arg->zstream.msg); - } - arg->inflate_ret=ret; - } - - if(!(arg->zstream.next_out > &arg->out[arg->offset])) // ASSERT(arg->zstream.next_out > &arg->out[arg->offset]); - { - fprintf(stderr,"decompression error: next packet is too large.\n"); - return -1 ; - } - len=arg->zstream.next_out-&arg->out[arg->offset]; - if(len > length) - len=length; - memcpy(dest,&arg->out[arg->offset],len); - arg->offset+=len; - length-=len; - } - - return saved; -} - -// \todo remove code duplication between this and zlib_compressed_data_reader -static int bzip2_compressed_data_reader(void *dest,size_t length, - ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - bz_decompress_arg_t *arg=ops_reader_get_arg(rinfo); - - if(!(arg->type==OPS_C_BZIP2)) // ASSERT(arg->type==OPS_C_BZIP2); - { - fprintf(stderr,"bzip2_compressed_data_reader: unexpected compress format %d\n",arg->type) ; - return -1 ; - } - - //ops_parser_content_t content; - int saved=length; - - if(arg->inflate_ret == BZ_STREAM_END - && arg->bzstream.next_out == &arg->out[arg->offset]) - return 0; - - if(arg->region->length_read == arg->region->length) - { - if(arg->inflate_ret != BZ_STREAM_END) - OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR, - "Compressed data didn't end when region ended."); - } - - while(length > 0) - { - unsigned len; - - if(&arg->out[arg->offset] == arg->bzstream.next_out) - { - int ret; - - arg->bzstream.next_out=(char *) arg->out; - arg->bzstream.avail_out=sizeof arg->out; - arg->offset=0; - if(arg->bzstream.avail_in == 0) - { - unsigned n=arg->region->length; - - if(!arg->region->indeterminate) - { - n-=arg->region->length_read; - if(n > sizeof arg->in) - n=sizeof arg->in; - } - else - n=sizeof arg->in; - - if(!ops_stacked_limited_read(arg->in, n, arg->region, errors, - rinfo, cbinfo)) - return -1; - - arg->bzstream.next_in=arg->in; - arg->bzstream.avail_in=arg->region->indeterminate - ? arg->region->last_read : n; - } - - ret=BZ2_bzDecompress(&arg->bzstream); - if(ret == BZ_STREAM_END) - { - if(!arg->region->indeterminate - && arg->region->length_read != arg->region->length) - OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR, - "Compressed stream ended before packet end."); - } - else if(ret != BZ_OK) - { - OPS_ERROR_1(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR, - "Invalid return %d from BZ2_bzDecompress", ret); - } - arg->inflate_ret=ret; - } - if(!(arg->bzstream.next_out > &arg->out[arg->offset])) // ASSERT(arg->bzstream.next_out > &arg->out[arg->offset]); - { - fprintf(stderr,"bzip2_compressed_data_reader: unexpected size in compressed packet.\n") ; - return -1 ; - } - len=arg->bzstream.next_out-&arg->out[arg->offset]; - if(len > length) - len=length; - memcpy(dest,&arg->out[arg->offset],len); - arg->offset+=len; - length-=len; - } - - return saved; -} - -/** - * \ingroup Core_Compress - * - * \param *region Pointer to a region - * \param *parse_info How to parse - * \param type Which compression type to expect -*/ - -int ops_decompress(ops_region_t *region,ops_parse_info_t *parse_info, - ops_compression_type_t type) - { - z_decompress_arg_t z_arg; - bz_decompress_arg_t bz_arg; - int ret; - - switch (type) - { - case OPS_C_ZIP: - case OPS_C_ZLIB: - memset(&z_arg,'\0',sizeof z_arg); - - z_arg.region=region; - z_arg.offset=0; - z_arg.type=type; - - z_arg.zstream.next_in=Z_NULL; - z_arg.zstream.avail_in=0; - z_arg.zstream.next_out=z_arg.out; - z_arg.zstream.zalloc=Z_NULL; - z_arg.zstream.zfree=Z_NULL; - z_arg.zstream.opaque=Z_NULL; - break; - - case OPS_C_BZIP2: - memset(&bz_arg,'\0',sizeof bz_arg); - - bz_arg.region=region; - bz_arg.offset=0; - bz_arg.type=type; - - bz_arg.bzstream.next_in=NULL; - bz_arg.bzstream.avail_in=0; - bz_arg.bzstream.next_out=bz_arg.out; - bz_arg.bzstream.bzalloc=NULL; - bz_arg.bzstream.bzfree=NULL; - bz_arg.bzstream.opaque=NULL; - break; - - default: - OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, - "Compression algorithm %d is not yet supported", type); - return 0; - } - - switch(type) - { - case OPS_C_ZIP: - ret=inflateInit2(&z_arg.zstream,-15); - break; - - case OPS_C_ZLIB: - ret=inflateInit(&z_arg.zstream); - break; - - case OPS_C_BZIP2: - /* - OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, "Compression algorithm %s is not yet supported", "BZIP2"); - return 0; - */ - ret=BZ2_bzDecompressInit(&bz_arg.bzstream, 1, 0); - break; - - default: - OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, - "Compression algorithm %d is not yet supported", type); - return 0; - } - - switch (type) - { - case OPS_C_ZIP: - case OPS_C_ZLIB: - if(ret != Z_OK) - { - OPS_ERROR_1(&parse_info->errors, OPS_E_P_DECOMPRESSION_ERROR, - "Cannot initialise ZIP or ZLIB stream " - "for decompression: error=%d", ret); - return 0; - } - ops_reader_push(parse_info,zlib_compressed_data_reader,NULL,&z_arg); - break; - - case OPS_C_BZIP2: - if (ret != BZ_OK) - { - OPS_ERROR_1(&parse_info->errors, OPS_E_P_DECOMPRESSION_ERROR, - "Cannot initialise BZIP2 stream " - "for decompression: error=%d", ret); - return 0; - } - ops_reader_push(parse_info,bzip2_compressed_data_reader,NULL,&bz_arg); - break; - - default: - OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, - "Compression algorithm %d is not yet supported", type); - return 0; - } - - ret=ops_parse(parse_info,ops_true); - - ops_reader_pop(parse_info); - - return ret; - } - -/** -\ingroup Core_WritePackets -\brief Writes Compressed packet -\param data Data to write out -\param len Length of data -\param cinfo Write settings -\return ops_true if OK; else ops_false -*/ - -ops_boolean_t ops_write_compressed(const unsigned char *data, - const unsigned int len, - ops_create_info_t *cinfo) -{ - int r=0; - int sz_in=0; - int sz_out=0; - compress_arg_t* compress=ops_mallocz(sizeof *compress); - - // compress the data - const int level=Z_DEFAULT_COMPRESSION; // \todo allow varying levels - compress->stream.zalloc=Z_NULL; - compress->stream.zfree=Z_NULL; - compress->stream.opaque=NULL; - - // all other fields set to zero by use of ops_mallocz - - if (deflateInit(&compress->stream,level) != Z_OK) - { - // can't initialise - - fprintf(stderr,"ops_write_compressed: can't initialise compression engine\n") ; - return ops_false ; - } - - // do necessary transformation - // copy input to maintain const'ness of src - - if(!(compress->src==NULL)) // ASSERT(compress->src==NULL); - { - fprintf(stderr,"ops_write_compressed: compress->src should be NULL\n") ; - return ops_false ; - } - if(!(compress->dst==NULL)) // ASSERT(compress->dst==NULL); - { - fprintf(stderr,"ops_write_compressed: compress->dst should be NULL\n") ; - return ops_false ; - } - - sz_in=len * sizeof (unsigned char); - sz_out= (sz_in * 1.01) + 12; // from zlib webpage - compress->src=ops_mallocz(sz_in); - compress->dst=ops_mallocz(sz_out); - memcpy(compress->src,data,len); - - // setup stream - compress->stream.next_in=compress->src; - compress->stream.avail_in=sz_in; - compress->stream.total_in=0; - - compress->stream.next_out=compress->dst; - compress->stream.avail_out=sz_out; - compress->stream.total_out=0; - - r=deflate(&compress->stream, Z_FINISH); - - if(!(r==Z_STREAM_END)) // ASSERT(r==Z_STREAM_END); // need to loop if not - { - fprintf(stderr,"ops_write_compressed: compression failed.\n") ; - return ops_false ; - } - - // write it out - return (ops_write_ptag(OPS_PTAG_CT_COMPRESSED, cinfo) - && ops_write_length(1+compress->stream.total_out, cinfo) - && ops_write_scalar(OPS_C_ZLIB,1,cinfo) - && ops_write(compress->dst, compress->stream.total_out,cinfo)); -} - - -// Writes out the header for the compressed packet. Invoked by the -// partial stream writer. Note that writing the packet tag and the -// packet length is handled by the partial stream writer. -static ops_boolean_t write_compressed_header(ops_create_info_t *info, - void *header_data) - { - OPS_USED(header_data); - // Write the compression type. Currently we just use ZLIB - ops_write_scalar(OPS_C_ZLIB, 1, info); - return ops_true; - } - -static void zlib_error(ops_error_t **errors, z_stream *stream, int error) - { - OPS_ERROR_2(errors,OPS_E_FAIL, - "Error from compression stream %d (%s)", error, - stream->msg == NULL ? "Unknown" : stream->msg); - } - -static ops_boolean_t stream_compress_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - // ZLib doesn't like being asked to compress nothing, so return if - // we are given no input. - if (length == 0) - return ops_true; - if (debug) - fprintf(stderr, "Compressing %u bytes\n", length); - compress_arg_t* compress = ops_writer_get_arg(winfo); - compress->bytes_in += length; - compress->stream.next_in = (void*) src; - compress->stream.avail_in = length; - ops_boolean_t result = ops_true; - do - { - compress->stream.next_out = compress->dst; - compress->stream.avail_out = COMPRESS_BUFFER; - int retcode = deflate(&compress->stream, Z_NO_FLUSH); - if (retcode != Z_OK) - { - zlib_error(errors, &compress->stream, retcode); - deflateEnd(&compress->stream); - return ops_false; - } - unsigned bytes_to_write = COMPRESS_BUFFER - compress->stream.avail_out; - if (debug) - fprintf(stderr, "bytes_to_write = %u\n", bytes_to_write); - compress->bytes_out += bytes_to_write; - result = ops_stacked_write(compress->dst, bytes_to_write, errors, - winfo); - } - while (result && compress->stream.avail_out == 0); - - return result; - } - -static ops_boolean_t stream_compress_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - compress_arg_t* compress = ops_writer_get_arg(winfo); - compress->stream.next_in = NULL; - compress->stream.avail_in = 0; - int retcode = Z_OK; - int output_size = COMPRESS_BUFFER; - ops_boolean_t result = ops_true; - do - { - compress->stream.next_out = compress->dst; - compress->stream.avail_out = output_size; - retcode = deflate(&compress->stream, Z_FINISH); - if (retcode != Z_STREAM_END && retcode != Z_OK) - { - zlib_error(errors, &compress->stream, retcode); - deflateEnd(&compress->stream); - return ops_false; - } - int bytes_to_write = output_size - compress->stream.avail_out; - if (debug) - fprintf(stderr, "At end, bytes_to_write = %u\n", bytes_to_write); - compress->bytes_out += bytes_to_write; - result = ops_stacked_write(compress->dst, bytes_to_write, errors, - winfo); - - // If deflate returns Z_OK after we have asked to flush, it means - // that there was not enough space in the output buffer. Increase - // the buffer size and try again. - if (retcode != Z_STREAM_END) - { - if (debug) - fprintf(stderr, "Reallocating %u\n", output_size * 2); - output_size *= 2; - compress->dst = realloc(compress->dst, output_size); - } - } - while (result && retcode != Z_STREAM_END); - - int error = deflateEnd(&compress->stream); - if (error != Z_OK) - { - zlib_error(errors, &compress->stream, error); - return ops_false; - } - return result; - } - -static void stream_compress_destroyer(ops_writer_info_t *winfo) - { - compress_arg_t* compress = ops_writer_get_arg(winfo); - if (debug) - fprintf(stderr, "Compressed %zu to %zu\n", compress->bytes_in, - compress->bytes_out); - free(compress->dst); - free(compress); - } - -/** -\ingroup Core_WritePackets -\brief Pushes a compressed writer onto the stack. Data written - will be encoded as a compressed packet. -\param cinfo Write settings -*/ -ops_boolean_t ops_writer_push_compressed(ops_create_info_t *cinfo) -{ - // This is a streaming writer, so we don't know the length in - // advance. Use a partial writer to handle the partial body - // packet lengths. - ops_writer_push_partial(COMPRESS_BUFFER, - cinfo, OPS_PTAG_CT_COMPRESSED, - write_compressed_header, NULL); - - // Create arg to be used with this writer - // Remember to free this in the destroyer - compress_arg_t *compress = ops_mallocz(sizeof *compress); - - compress->dst = malloc(COMPRESS_BUFFER); - const int level=Z_DEFAULT_COMPRESSION; // \todo allow varying levels - compress->stream.zalloc=Z_NULL; - compress->stream.zfree=Z_NULL; - compress->stream.opaque=NULL; - compress->stream.avail_out = COMPRESS_BUFFER; - // all other fields set to zero by use of ops_mallocz - - if (deflateInit(&compress->stream, level) != Z_OK) - // can't initialise. Is there a better way to handle this? - return ops_false ; - - // And push writer on stack - ops_writer_push(cinfo, stream_compress_writer, stream_compress_finaliser, - stream_compress_destroyer, compress); - - return ops_true ; -} - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/compress.h b/openpgpsdk/src/openpgpsdk/compress.h deleted file mode 100644 index 04d124e41..000000000 --- a/openpgpsdk/src/openpgpsdk/compress.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include "packet-parse.h" - -int ops_decompress(ops_region_t *region,ops_parse_info_t *parse_info, - ops_compression_type_t type); - -ops_boolean_t ops_write_compressed(const unsigned char* data, - const unsigned int len, - ops_create_info_t *cinfo); - -ops_boolean_t ops_writer_push_compressed(ops_create_info_t *cinfo); diff --git a/openpgpsdk/src/openpgpsdk/configure.h b/openpgpsdk/src/openpgpsdk/configure.h deleted file mode 100644 index 63051b316..000000000 --- a/openpgpsdk/src/openpgpsdk/configure.h +++ /dev/null @@ -1,15 +0,0 @@ -/* generated by configure from include/openpgpsdk/configure.h.template. Don't edit. */ - -#define HAVE_ALLOCA_H 0 -#define TIME_T_FMT "%ld" - -/* for silencing unused parameter warnings */ -#define OPS_USED(x) (x)=(x) - -/* for tests, flag to tell gpg not to use blocking randomness */ -#define GNUPG_QUICK_RANDOM "--quick-random" - -/* Avoid a bunch of #ifs */ -#ifndef O_BINARY -# define O_BINARY 0 -#endif diff --git a/openpgpsdk/src/openpgpsdk/create.c b/openpgpsdk/src/openpgpsdk/create.c deleted file mode 100644 index b4fe548a7..000000000 --- a/openpgpsdk/src/openpgpsdk/create.c +++ /dev/null @@ -1,1396 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include - -#include -#include -#include -#include -#include -#include -#include "keyring_local.h" -#include -#include -#include -#include -#include -#include -#ifndef WIN32 -#include -#endif -#include - -#include -#include - -static int debug=0; - -/** - * \ingroup Core_Create - * \param length - * \param type - * \param info - * \return ops_true if OK, otherwise ops_false - */ - -ops_boolean_t ops_write_ss_header(unsigned length,ops_content_tag_t type, - ops_create_info_t *info) - { - return ops_write_length(length,info) - && ops_write_scalar(type-OPS_PTAG_SIGNATURE_SUBPACKET_BASE,1,info); - } - -/* XXX: the general idea of _fast_ is that it doesn't copy stuff - * the safe (i.e. non _fast_) version will, and so will also need to - * be freed. */ - -/** - * \ingroup Core_Create - * - * ops_fast_create_user_id() sets id->user_id to the given user_id. - * This is fast because it is only copying a char*. However, if user_id - * is changed or freed in the future, this could have injurious results. - * \param id - * \param user_id - */ - -void ops_fast_create_user_id(ops_user_id_t *id,unsigned char *user_id) - { - id->user_id=user_id; - } - -/** - * \ingroup Core_WritePackets - * \brief Writes a User Id packet - * \param id - * \param info - * \return ops_true if OK, otherwise ops_false - */ -ops_boolean_t ops_write_struct_user_id(ops_user_id_t *id, - ops_create_info_t *info) - { - return ops_write_ptag(OPS_PTAG_CT_USER_ID,info) - && ops_write_length(strlen((char *)id->user_id),info) - && ops_write(id->user_id,strlen((char *)id->user_id),info); - } - -/** - * \ingroup Core_WritePackets - * \brief Write a User Id packet. - * \param user_id - * \param info - * - * \return return value from ops_write_struct_user_id() - */ -ops_boolean_t ops_write_user_id(const unsigned char *user_id, - ops_create_info_t *info) - { - ops_user_id_t id; - - id.user_id=(unsigned char *)user_id; - return ops_write_struct_user_id(&id,info); - } - -/** -\ingroup Core_MPI -*/ -static unsigned mpi_length(const BIGNUM *bn) -{ - return 2+(BN_num_bits(bn)+7)/8; -} - -static unsigned public_key_length(const ops_public_key_t *key) -{ - switch(key->algorithm) - { - case OPS_PKA_RSA: return mpi_length(key->key.rsa.n) - +mpi_length(key->key.rsa.e); - - case OPS_PKA_DSA: return mpi_length(key->key.dsa.p) - +mpi_length(key->key.dsa.q) - +mpi_length(key->key.dsa.g) - +mpi_length(key->key.dsa.y); - case OPS_PKA_ELGAMAL: - return mpi_length(key->key.elgamal.p) - +mpi_length(key->key.elgamal.g) - +mpi_length(key->key.elgamal.y) ; - - default: - fprintf(stderr,"Bad algorithm type in key: %d\n",key->algorithm) ; - assert(!"unknown key algorithm"); - } - /* not reached */ - return 0; -} - -static unsigned secret_key_length(const ops_secret_key_t *key) -{ - int l; - - switch(key->public_key.algorithm) - { - case OPS_PKA_RSA: l=mpi_length(key->key.rsa.d) - +mpi_length(key->key.rsa.p) - +mpi_length(key->key.rsa.q) - +mpi_length(key->key.rsa.u); - break ; - - case OPS_PKA_DSA: l=mpi_length(key->key.dsa.x); - break; - - default: - assert(!"unknown key algorithm"); - } - - return l+public_key_length(&key->public_key); -} - -/** - * \ingroup Core_Create - * \param key - * \param time - * \param n - * \param e -*/ -void ops_fast_create_rsa_public_key(ops_public_key_t *key,time_t time, - BIGNUM *n,BIGNUM *e) - { - key->version=4; - key->creation_time=time; - key->algorithm=OPS_PKA_RSA; - key->key.rsa.n=n; - key->key.rsa.e=e; - } - -/* Note that we support v3 keys here because they're needed for - * for verification - the writer doesn't allow them, though */ -static ops_boolean_t write_public_key_body(const ops_public_key_t *key, - ops_create_info_t *info) -{ - if(!(ops_write_scalar(key->version,1,info) && ops_write_scalar(key->creation_time,4,info))) - return ops_false; - - if(key->version != 4 && !ops_write_scalar(key->days_valid,2,info)) - return ops_false; - - if(!ops_write_scalar(key->algorithm,1,info)) - return ops_false; - - switch(key->algorithm) - { - case OPS_PKA_DSA: - return ops_write_mpi(key->key.dsa.p,info) - && ops_write_mpi(key->key.dsa.q,info) - && ops_write_mpi(key->key.dsa.g,info) - && ops_write_mpi(key->key.dsa.y,info); - - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - return ops_write_mpi(key->key.rsa.n,info) - && ops_write_mpi(key->key.rsa.e,info); - - case OPS_PKA_ELGAMAL: - return ops_write_mpi(key->key.elgamal.p,info) - && ops_write_mpi(key->key.elgamal.g,info) - && ops_write_mpi(key->key.elgamal.y,info); - - default: - fprintf(stderr, "Unknown algorithm %d\n", key->algorithm); - assert(0); - break; - } - - /* not reached */ - return ops_false; -} - -/* Note that we support v3 keys here because they're needed for - * for verification - the writer doesn't allow them, though */ -static ops_boolean_t write_secret_key_body(const ops_secret_key_t *key, - const unsigned char* passphrase, - const size_t pplen, - ops_create_info_t *info) -{ - /* RFC4880 Section 5.5.3 Secret-Key Packet Formats */ - - ops_crypt_t crypt; - ops_hash_t hash; - unsigned char hashed[OPS_SHA1_HASH_SIZE]; - unsigned char session_key[CAST_KEY_LENGTH]; - unsigned int done=0; - unsigned int i=0; - - if(!write_public_key_body(&key->public_key,info)) - return ops_false; - - assert(key->s2k_usage==OPS_S2KU_ENCRYPTED_AND_HASHED); /* = 254 */ - if(!ops_write_scalar(key->s2k_usage,1,info)) - return ops_false; - - assert(key->algorithm==OPS_SA_CAST5); - if (!ops_write_scalar(key->algorithm,1,info)) - return ops_false; - - assert(key->s2k_specifier==OPS_S2KS_SIMPLE - || key->s2k_specifier==OPS_S2KS_SALTED); // = 1 \todo could also be iterated-and-salted - if (!ops_write_scalar(key->s2k_specifier,1,info)) - return ops_false; - - assert(key->hash_algorithm==OPS_HASH_SHA1); - if (!ops_write_scalar(key->hash_algorithm,1,info)) - return ops_false; - - switch(key->s2k_specifier) - { - case OPS_S2KS_SIMPLE: - // nothing more to do - break; - - case OPS_S2KS_SALTED: - // 8-octet salt value - ops_random((void *)&key->salt[0],OPS_SALT_SIZE); - if (!ops_write(key->salt, OPS_SALT_SIZE, info)) - return ops_false; - break; - - /* \todo - case OPS_S2KS_ITERATED_AND_SALTED: - // 8-octet salt value - // 1-octet count - break; - */ - - default: - fprintf(stderr,"invalid/unsupported s2k specifier %d\n", - key->s2k_specifier); - assert(0); - } - - if (!ops_write(&key->iv[0],ops_block_size(key->algorithm),info)) - return ops_false; - - /* create the session key for encrypting the algorithm-specific fields */ - - switch(key->s2k_specifier) - { - case OPS_S2KS_SIMPLE: - case OPS_S2KS_SALTED: - // RFC4880: section 3.7.1.1 and 3.7.1.2 - - done=0; - for (i=0; donehash_algorithm); - hash.init(&hash); - - // preload if iterating - for (j=0; js2k_specifier==OPS_S2KS_SALTED) - { hash.add(&hash, key->salt, OPS_SALT_SIZE); } - - hash.add(&hash, passphrase, pplen); - hash.finish(&hash, hashed); - - // if more in hash than is needed by session key, use the - // leftmost octets - memcpy(session_key+(i*SHA_DIGEST_LENGTH), hashed, use); - done += use; - assert(done<=CAST_KEY_LENGTH); - } - - break; - - /* \todo - case OPS_S2KS_ITERATED_AND_SALTED: - // 8-octet salt value - // 1-octet count - break; - */ - - default: - fprintf(stderr,"invalid/unsupported s2k specifier %d\n", - key->s2k_specifier); - assert(0); - } - - /* use this session key to encrypt */ - - ops_crypt_any(&crypt,key->algorithm); - crypt.set_iv(&crypt, key->iv); - crypt.set_key(&crypt, session_key); - ops_encrypt_init(&crypt); - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"\nWRITING:\niv="); - for (i=0; ialgorithm); i++) - { - fprintf(stderr, "%02x ", key->iv[i]); - } - fprintf(stderr,"\n"); - - fprintf(stderr,"key="); - for (i=0; ipublic_key.algorithm) - { - case OPS_PKA_DSA: - return ops_write_mpi(key->key.dsa.x,info); - - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - - if(!ops_write_mpi(key->key.rsa.d,info) - || !ops_write_mpi(key->key.rsa.p,info) - || !ops_write_mpi(key->key.rsa.q,info) - || !ops_write_mpi(key->key.rsa.u,info)) - { - if (debug) - { fprintf(stderr,"4 x mpi not written - problem\n"); } - return ops_false; - } - - break; - - // case OPS_PKA_ELGAMAL: - // return ops_write_mpi(key->key.elgamal.x,info); - - default: - assert(0); - break; - } - - if(!ops_write(key->checkhash, OPS_CHECKHASH_SIZE, info)) - return ops_false; - - ops_writer_pop(info); - - free(crypt.encrypt_key) ; - free(crypt.decrypt_key) ; - - return ops_true; -} - - -/** - \ingroup HighLevel_KeyWrite - - \brief Writes a transferable PGP public key to the given output stream. - - \param keydata Key to be written - \param armoured Flag is set for armoured output - \param info Output stream - - Example code: - \code - void example(const ops_keydata_t* keydata) - { - ops_boolean_t armoured=ops_true; - char* filename="/tmp/testkey.asc"; - - int fd; - ops_boolean_t overwrite=ops_true; - ops_create_info_t* cinfo; - - fd=ops_setup_file_write(&cinfo, filename, overwrite); - ops_write_transferable_public_key(keydata,armoured,cinfo); - ops_teardown_file_write(cinfo,fd); - } - \endcode -*/ - -ops_boolean_t ops_write_transferable_public_key(const ops_keydata_t *keydata, - ops_boolean_t armoured, - ops_create_info_t *info) -{ - ops_boolean_t rtn; - unsigned int i=0,j=0; - - if (armoured) - { ops_writer_push_armoured(info, OPS_PGP_PUBLIC_KEY_BLOCK); } - - // public key - rtn=ops_write_struct_public_key(&keydata->key.skey.public_key,info); - if (rtn!=ops_true) - return rtn; - - // TODO: revocation signatures go here - - // user ids and corresponding signatures - for (i=0; inuids; i++) - { - ops_user_id_t* uid=&keydata->uids[i]; - - rtn=ops_write_struct_user_id(uid, info); - - if (!rtn) - return rtn; - - // find signature for this packet if it exists - for (j=0; jnsigs; j++) - { - sigpacket_t* sig=&keydata->sigs[i]; - if (!strcmp((char *)sig->userid->user_id, (char *)uid->user_id)) - { - rtn=ops_write(sig->packet->raw, sig->packet->length, info); - if (!rtn) - return !rtn; - } - } - } - - // TODO: user attributes and corresponding signatures - - // subkey packets and corresponding signatures and optional revocation - - if (armoured) - { - writer_info_finalise(&info->errors, &info->winfo); - ops_writer_pop(info); - } - - return rtn; -} - -ops_boolean_t ops_write_transferable_public_key_from_packet_data(const ops_keydata_t *keydata, - ops_boolean_t armoured, - ops_create_info_t *info) -{ - ops_boolean_t rtn = ops_true; - unsigned int i=0; - - if (armoured) - { ops_writer_push_armoured(info, OPS_PGP_PUBLIC_KEY_BLOCK); } - - for(i=0;inpackets;++i) - if(!ops_write(keydata->packets[i].raw, keydata->packets[i].length, info)) - return ops_false ; - - if (armoured) - { - writer_info_finalise(&info->errors, &info->winfo); - ops_writer_pop(info); - } - - return rtn; -} - -ops_boolean_t ops_write_transferable_secret_key_from_packet_data(const ops_keydata_t *keydata, - ops_boolean_t armoured, - ops_create_info_t *info) -{ - ops_boolean_t rtn = ops_true; - unsigned int i=0; - - if(keydata->type != OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) - { - fprintf(stderr,"Can only output encrypted secret keys from raw packet data. Current type is %d\n",keydata->type) ; - return ops_false ; - } - if (armoured) - { ops_writer_push_armoured(info, OPS_PGP_PRIVATE_KEY_BLOCK); } - - for(i=0;inpackets;++i) - if(!ops_write(keydata->packets[i].raw, keydata->packets[i].length, info)) - return ops_false ; - - if (armoured) - { - writer_info_finalise(&info->errors, &info->winfo); - ops_writer_pop(info); - } - - return rtn; -} -/** - \ingroup HighLevel_KeyWrite - - \brief Writes a transferable PGP secret key to the given output stream. - - \param keydata Key to be written - \param passphrase - \param pplen - \param armoured Flag is set for armoured output - \param info Output stream - - Example code: - \code - void example(const ops_keydata_t* keydata) - { - const unsigned char* passphrase=NULL; - const size_t passphraselen=0; - ops_boolean_t armoured=ops_true; - - int fd; - char* filename="/tmp/testkey.asc"; - ops_boolean_t overwrite=ops_true; - ops_create_info_t* cinfo; - - fd=ops_setup_file_write(&cinfo, filename, overwrite); - ops_write_transferable_secret_key(keydata,passphrase,pplen,armoured,cinfo); - ops_teardown_file_write(cinfo,fd); - } - \endcode -*/ - -ops_boolean_t ops_write_transferable_secret_key(const ops_keydata_t *keydata, const unsigned char* passphrase, const size_t pplen, ops_boolean_t armoured, ops_create_info_t *info) - { - ops_boolean_t rtn; - unsigned int i=0,j=0; - - if (armoured) - { ops_writer_push_armoured(info,OPS_PGP_PRIVATE_KEY_BLOCK); } - - // public key - rtn=ops_write_struct_secret_key(&keydata->key.skey,passphrase,pplen,info); - if (rtn!=ops_true) - return rtn; - - // TODO: revocation signatures go here - - // user ids and corresponding signatures - for (i=0; inuids; i++) - { - ops_user_id_t* uid=&keydata->uids[i]; - - rtn=ops_write_struct_user_id(uid, info); - - if (!rtn) - return rtn; - - // find signature for this packet if it exists - for (j=0; jnsigs; j++) - { - sigpacket_t* sig=&keydata->sigs[i]; - if (!strcmp((char *)sig->userid->user_id, (char *)uid->user_id)) - { - rtn=ops_write(sig->packet->raw, sig->packet->length, info); - if (!rtn) - return !rtn; - } - } - } - - // TODO: user attributes and corresponding signatures - - // subkey packets and corresponding signatures and optional revocation - - if (armoured) - { - writer_info_finalise(&info->errors, &info->winfo); - ops_writer_pop(info); - } - - return rtn; - } - -/** - * \ingroup Core_WritePackets - * \brief Writes a Public Key packet - * \param key - * \param info - * \return ops_true if OK, otherwise ops_false - */ -ops_boolean_t ops_write_struct_public_key(const ops_public_key_t *key, - ops_create_info_t *info) -{ - assert(key->version == 4); - - if(key->algorithm != OPS_PKA_RSA) - { - fprintf(stderr,"\nUnhandled key algorithm %d\n",key->algorithm); - return ops_false ; - } - - return ops_write_ptag(OPS_PTAG_CT_PUBLIC_KEY,info) - && ops_write_length(1+4+1+public_key_length(key),info) - && write_public_key_body(key,info); -} - -/** - * \ingroup Core_WritePackets - * \brief Writes one RSA public key packet. - * \param time Creation time - * \param n RSA public modulus - * \param e RSA public encryption exponent - * \param info Writer settings - * - * \return ops_true if OK, otherwise ops_false - */ - -ops_boolean_t ops_write_rsa_public_key(time_t time,const BIGNUM *n, - const BIGNUM *e, - ops_create_info_t *info) - { - ops_public_key_t key; - - ops_fast_create_rsa_public_key(&key,time,DECONST(BIGNUM,n), - DECONST(BIGNUM,e)); - return ops_write_struct_public_key(&key,info); - } - -/** - * \ingroup Core_Create - * \param out - * \param key - * \param make_packet - */ - -void ops_build_public_key(ops_memory_t *out,const ops_public_key_t *key, - ops_boolean_t make_packet) - { - ops_create_info_t *info; - - info=ops_create_info_new(); - - ops_memory_init(out,128); - ops_writer_set_memory(info,out); - - write_public_key_body(key,info); - - if(make_packet) - ops_memory_make_packet(out,OPS_PTAG_CT_PUBLIC_KEY); - - ops_create_info_delete(info); - } - -/** - * \ingroup Core_Create - * - * Create an RSA secret key structure. If a parameter is marked as - * [OPTIONAL], then it can be omitted and will be calculated from - * other parameters - or, in the case of e, will default to 0x10001. - * - * Parameters are _not_ copied, so will be freed if the structure is - * freed. - * - * \param key The key structure to be initialised. - * \param time - * \param d The RSA parameter d (=e^-1 mod (p-1)(q-1)) [OPTIONAL] - * \param p The RSA parameter p - * \param q The RSA parameter q (q > p) - * \param u The RSA parameter u (=p^-1 mod q) [OPTIONAL] - * \param n The RSA public parameter n (=p*q) [OPTIONAL] - * \param e The RSA public parameter e */ - -void ops_fast_create_rsa_secret_key(ops_secret_key_t *key,time_t time, - BIGNUM *d,BIGNUM *p,BIGNUM *q,BIGNUM *u, - BIGNUM *n,BIGNUM *e) - { - ops_fast_create_rsa_public_key(&key->public_key,time,n,e); - - // XXX: calculate optionals - key->key.rsa.d=d; - key->key.rsa.p=p; - key->key.rsa.q=q; - key->key.rsa.u=u; - - key->s2k_usage=OPS_S2KU_NONE; - - // XXX: sanity check and add errors... - } - -/** - * \ingroup Core_WritePackets - * \brief Writes a Secret Key packet. - * \param key The secret key - * \param passphrase The passphrase - * \param pplen Length of passphrase - * \param info - * \return ops_true if OK; else ops_false - */ -ops_boolean_t ops_write_struct_secret_key(const ops_secret_key_t *key, - const unsigned char* passphrase, - const size_t pplen, - ops_create_info_t *info) - { - int length=0; - - assert(key->public_key.version == 4); - - // Ref: RFC4880 Section 5.5.3 - - // public_key, excluding MPIs - length += 1+4+1+1; - - // s2k usage - length+=1; - - switch (key->s2k_usage) - { - case OPS_S2KU_NONE: - // nothing to add - break; - - case OPS_S2KU_ENCRYPTED_AND_HASHED: // 254 - case OPS_S2KU_ENCRYPTED: // 255 - - // Ref: RFC4880 Section 3.7 - length+=1; // s2k_specifier - - switch(key->s2k_specifier) - { - case OPS_S2KS_SIMPLE: - length+=1; // hash algorithm - break; - - case OPS_S2KS_SALTED: - length+=1+8; // hash algorithm + salt - break; - - case OPS_S2KS_ITERATED_AND_SALTED: - length+=1+8+1; // hash algorithm, salt + count - break; - - default: - assert(0); - } - break; - - default: - assert(0); - } - - // IV - if (key->s2k_usage != 0) - { - length += ops_block_size(key->algorithm); - } - - // checksum or hash - switch (key->s2k_usage) - { - case 0: - case 255: - length += 2; - break; - - case 254: - length += 20; - break; - - default: - assert(0); - } - - // secret key and public key MPIs - length += secret_key_length(key); - - return ops_write_ptag(OPS_PTAG_CT_SECRET_KEY,info) - // && ops_write_length(1+4+1+1+secret_key_length(key)+2,info) - && ops_write_length(length,info) - && write_secret_key_body(key,passphrase,pplen,info); - } - -/** - * \ingroup InternalAPI - * - * \brief Initialise a temporary info structure that can be used for - * writing to a writer's parent. - * - * This is used by writers who want to use the various ops_write functions - * in order to write to the parent writer. - * Example code: - * \code - * ops_boolean_t writer(const unsigned char *src, - * unsigned length, - * ops_error_t **errors, - * ops_writer_info_t *winfo) { - * ops_create_info_t parent; - * ops_prepare_parent_info(&parent, winfo, errors); - * - * // The ptag will be written to the parent writer - * ops_write_ptag(OPS_PTAG_CT_LITERAL_DATA, &parent); - * - * // The data is written to the parent. This line is - // equivalent to: - * // ops_stacked_write(src, length, errors, winfo); - * ops_boolean_t result = ops_write(src, length, info); - * ops_move_errors(&parent_info, errors); - * return result; - * \endcode - * - * \note It is the responsiblity of the caller to assign space for the parent - * structure, typically on the stack. IOn order to report errors correctly, - * use ops_move_errors() after the write operation. - * - * \see ops_move_errors - */ -void ops_prepare_parent_info(ops_create_info_t *parent_info, - ops_writer_info_t *winfo) - { - parent_info->winfo = *winfo->next; - parent_info->errors = NULL; - } - -/** - * \ingroup Core_Create - * - * \brief Create a new ops_create_info_t structure. - * - * \return the new structure. - * \note It is the responsiblity of the caller to call ops_create_info_delete(). - * \sa ops_create_info_delete() - */ -ops_create_info_t *ops_create_info_new(void) - { return ops_mallocz(sizeof(ops_create_info_t)); } - -/** - * \ingroup Core_Create - * \brief Delete an ops_create_info_t strucut and associated resources. - * - * Delete an ops_create_info_t structure. If a writer is active, then - * that is also deleted. - * - * \param info the structure to be deleted. - */ -void ops_create_info_delete(ops_create_info_t *info) - { - writer_info_delete(&info->winfo); - free(info); - } - -/** - \ingroup Core_Create - \brief Calculate the checksum for a session key - \param session_key Session Key to use - \param cs Checksum to be written - \return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_calc_session_key_checksum(ops_pk_session_key_t *session_key, - unsigned char cs[2]) - { - unsigned int i=0; - unsigned long checksum=0; - - if (!ops_is_sa_supported(session_key->symmetric_algorithm)) - return ops_false; - - for (i=0; isymmetric_algorithm); i++) - { - checksum+=session_key->key[i]; - } - checksum = checksum % 65536; - - cs[0]=checksum >> 8; - cs[1]=checksum & 0xFF; - - return ops_true; - // fprintf(stderr,"\nm buf checksum: "); - // fprintf(stderr," %2x",cs[0]); - // fprintf(stderr," %2x\n",cs[1]); - } - -static ops_boolean_t create_unencoded_m_buf(ops_pk_session_key_t *session_key, - unsigned char *m_buf) - { - int i=0; - // unsigned long checksum=0; - - // m_buf is the buffer which will be encoded in PKCS#1 block - // encoding to form the "m" value used in the - // Public Key Encrypted Session Key Packet - // as defined in RFC Section 5.1 "Public-Key Encrypted Session Key Packet" - - m_buf[0]=session_key->symmetric_algorithm; - - assert(session_key->symmetric_algorithm == OPS_SA_CAST5); - for (i=0; ikey[i]; - } - - return(ops_calc_session_key_checksum(session_key, m_buf+1+CAST_KEY_LENGTH)); - } - -/** -\ingroup Core_Create -\brief implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC -\param M -\param mLen -\param pkey -\param EM -\return ops_true if OK; else ops_false -*/ -ops_boolean_t encode_m_buf(const unsigned char *M, size_t mLen, - const ops_public_key_t *pkey, - unsigned char* EM -) - { - unsigned int k; - unsigned i; - - // implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC - - if(pkey->algorithm != OPS_PKA_RSA) - { - fprintf(stderr,"\nUnhandled key algorithm %d\n",pkey->algorithm); - return ops_false ; - } - - k=BN_num_bytes(pkey->key.rsa.n); - assert(mLen <= k-11); - if (mLen > k-11) - { - fprintf(stderr,"message too long\n"); - return ops_false; - } - - // these two bytes defined by RFC - EM[0]=0x00; - EM[1]=0x02; - - // add non-zero random bytes of length k - mLen -3 - for(i=2 ; i < k-mLen-1 ; ++i) - do - ops_random(EM+i, 1); - while(EM[i] == 0); - - assert (i >= 8+2); - - EM[i++]=0; - - memcpy(EM+i, M, mLen); - - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"Encoded Message: \n"); - for (i=0; ikey.rsa.n); - unsigned char* encoded_m_buf = ops_mallocz(sz_encoded_m_buf); - - ops_pk_session_key_t *session_key=ops_mallocz(sizeof *session_key); - - assert(key->type == OPS_PTAG_CT_PUBLIC_KEY); - session_key->version=OPS_PKSK_V3; - memcpy(session_key->key_id, key->key_id, sizeof session_key->key_id); - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"Encrypting for RSA key id : "); - for (i=0; ikey_id; i++) - fprintf(stderr,"%2x ", key->key_id[i]); - fprintf(stderr,"\n"); - } - - assert(key->key.pkey.algorithm == OPS_PKA_RSA); - session_key->algorithm=key->key.pkey.algorithm; - - // \todo allow user to specify other algorithm - session_key->symmetric_algorithm=OPS_SA_CAST5; - ops_random(session_key->key, CAST_KEY_LENGTH); - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"CAST5 session key created (len=%d):\n ", - CAST_KEY_LENGTH); - for (i=0; ikey[i]); - fprintf(stderr,"\n"); - } - - if (create_unencoded_m_buf(session_key, &unencoded_m_buf[0])==ops_false) - { - free(encoded_m_buf); - return NULL; - } - - if (debug) - { - unsigned int i=0; - printf("unencoded m buf:\n"); - for (i=0; iparameters)) - { - free (encoded_m_buf); - return NULL; - } - - free(encoded_m_buf); - return session_key; - } - -/** -\ingroup Core_WritePackets -\brief Writes Public Key Session Key packet -\param info Write settings -\param pksk Public Key Session Key to write out -\return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_write_pk_session_key(ops_create_info_t *info, - ops_pk_session_key_t *pksk) - { - assert(pksk); - assert(pksk->algorithm == OPS_PKA_RSA); - - return ops_write_ptag(OPS_PTAG_CT_PK_SESSION_KEY, info) - && ops_write_length(1 + 8 + 1 - + BN_num_bytes(pksk->parameters.rsa.encrypted_m) - + 2, info) - && ops_write_scalar(pksk->version, 1, info) - && ops_write(pksk->key_id, 8, info) - && ops_write_scalar(pksk->algorithm, 1, info) - && ops_write_mpi(pksk->parameters.rsa.encrypted_m, info) - //?? && ops_write_scalar(0, 2, info); - ; - } - -/** -\ingroup Core_WritePackets -\brief Writes MDC packet -\param hashed Hash for MDC -\param info Write settings -\return ops_true if OK; else ops_false -*/ - -ops_boolean_t ops_write_mdc(const unsigned char *hashed, - ops_create_info_t* info) - { - // write it out - return ops_write_ptag(OPS_PTAG_CT_MDC, info) - && ops_write_length(OPS_SHA1_HASH_SIZE,info) - && ops_write(hashed, OPS_SHA1_HASH_SIZE, info); - } - -/** -\ingroup Core_WritePackets -\brief Writes Literal Data packet from buffer -\param data Buffer to write out -\param maxlen Max length of buffer -\param type Literal Data Type -\param info Write settings -\return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_write_literal_data_from_buf(const unsigned char *data, - const int maxlen, - const ops_literal_data_type_t type, - ops_create_info_t *info) - { - /* - * RFC4880 does not specify a meaning for filename or date. - * It is implementation-dependent. - * We will not implement them. - */ - // \todo do we need to check text data for line endings ? - return ops_write_ptag(OPS_PTAG_CT_LITERAL_DATA, info) - && ops_write_length(1+1+4+maxlen,info) - && ops_write_scalar(type, 1, info) - && ops_write_scalar(0, 1, info) - && ops_write_scalar(0, 4, info) - && ops_write(data, maxlen, info); - } - -/** -\ingroup Core_WritePackets -\brief Writes Literal Data packet from contents of file -\param filename Name of file to read from -\param type Literal Data Type -\param info Write settings -\return ops_true if OK; else ops_false -*/ - -ops_boolean_t -ops_write_literal_data_from_file(const char *filename, - const ops_literal_data_type_t type, - ops_create_info_t *info) - { - size_t initial_size=1024; - int fd=0; - ops_boolean_t rtn; - unsigned char buf[1024]; - ops_memory_t* mem=NULL; - size_t len=0; - - fd=ops_open(filename,O_RDONLY | O_BINARY, 0); - - if (fd < 0) - return ops_false; - - mem=ops_memory_new(); - ops_memory_init(mem,initial_size); - for (;;) - { - ssize_t n=0; - n=read(fd,buf,1024); - if (!n) - break; - if (n == -1) - { - close(fd); - ops_memory_free(mem); - return ops_false; - } - ops_memory_add(mem, &buf[0], n); - } - close(fd); - - // \todo do we need to check text data for line endings ? - len=ops_memory_get_length(mem); - rtn=ops_write_ptag(OPS_PTAG_CT_LITERAL_DATA, info) - && ops_write_length(1+1+4+len,info) - && ops_write_scalar(type, 1, info) - && ops_write_scalar(0, 1, info) // filename - && ops_write_scalar(0, 4, info) // date - && ops_write(ops_memory_get_data(mem), len, info); - - ops_memory_free(mem); - return rtn; - } - -/** - \ingroup HighLevel_General - - \brief Reads contents of file into new ops_memory_t struct. - - \param filename Filename to read from - \param errnum Pointer to error - \return new ops_memory_t pointer containing the contents of the file - - \note If there was an error opening the file or reading from it, - errnum is set to the cause - - \note It is the caller's responsibility to call ops_memory_free(mem) -*/ - -ops_memory_t* ops_write_mem_from_file(const char *filename, int* errnum) - { - size_t initial_size=1024; - int fd=0; - unsigned char buf[1024]; - ops_memory_t* mem=NULL; - - *errnum=0; - - fd=ops_open(filename,O_RDONLY | O_BINARY, 0); - - if (fd < 0) - { - *errnum=errno; - return ops_false; - } - - mem=ops_memory_new(); - ops_memory_init(mem,initial_size); - for (;;) - { - ssize_t n=0; - n=read(fd,buf,1024); - if (n<0) - { - *errnum=errno; - break; - } - if (!n) - break; - ops_memory_add(mem, &buf[0], n); - } - close(fd); - return mem; - } - -/** - \ingroup HighLevel_General - - \brief Reads contents of buffer into file - - \param filename Filename to write to - \param buf Buffer to write to file - \param len Size of buffer - \param overwrite Flag to set whether to overwrite an existing file - \return 1 if OK; 0 if error -*/ - -int ops_write_file_from_buf(const char *filename, const char* buf, - const size_t len, const ops_boolean_t overwrite) - { - int fd=0; - size_t n=0; - int flags=0; - - flags=O_WRONLY | O_CREAT; - if (overwrite==ops_true) - flags |= O_TRUNC; - else - flags |= O_EXCL; - - flags |= O_BINARY; - - fd=ops_open(filename,flags, 0600); - if (fd < 0) - { - perror(NULL); - return 0; - } - - n=write(fd,buf,len); - if (n!=len) - return 0; - - if(!close(fd)) - return 1; - - return 0; - } - -/** -\ingroup Core_WritePackets -\brief Write Symmetrically Encrypted packet -\param data Data to encrypt -\param len Length of data -\param info Write settings -\return ops_true if OK; else ops_false -\note Hard-coded to use AES256 -*/ -ops_boolean_t ops_write_symmetrically_encrypted_data(const unsigned char *data, - const int len, - ops_create_info_t *info) - { - int done=0; - ops_crypt_t crypt_info; - int encrypted_sz=0;// size of encrypted data - unsigned char *encrypted=NULL; // buffer to write encrypted data to - - // \todo assume AES256 for now - ops_crypt_any(&crypt_info, OPS_SA_AES_256); - ops_encrypt_init(&crypt_info); - - encrypted_sz=len+crypt_info.blocksize+2; - encrypted=ops_mallocz(encrypted_sz); - - done=ops_encrypt_se(&crypt_info, encrypted, data, len); - assert(done==len); - // printf("len=%d, done: %d\n", len, done); - - return ops_write_ptag(OPS_PTAG_CT_SE_DATA, info) - && ops_write_length(1+encrypted_sz,info) - && ops_write(data, len, info); - } - -/** -\ingroup Core_WritePackets -\brief Write a One Pass Signature packet -\param skey Secret Key to use -\param hash_alg Hash Algorithm to use -\param sig_type Signature type -\param info Write settings -\return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_write_one_pass_sig(const ops_secret_key_t* skey, - const ops_hash_algorithm_t hash_alg, - const ops_sig_type_t sig_type, - ops_create_info_t* info) - { - unsigned char keyid[OPS_KEY_ID_SIZE]; - if (debug) - fprintf(stderr, "calling ops_keyid in write_one_pass_sig: " - "this calls sha1_init\n"); - ops_keyid(keyid,&skey->public_key); - - return ops_write_ptag(OPS_PTAG_CT_ONE_PASS_SIGNATURE, info) - && ops_write_length(1+1+1+1+8+1, info) - && ops_write_scalar (3, 1, info) // version - && ops_write_scalar (sig_type, 1, info) - && ops_write_scalar (hash_alg, 1, info) - && ops_write_scalar (skey->public_key.algorithm, 1, info) - && ops_write(keyid, 8, info) - && ops_write_scalar (1, 1, info); - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/create.h b/openpgpsdk/src/openpgpsdk/create.h deleted file mode 100644 index aaeec0d51..000000000 --- a/openpgpsdk/src/openpgpsdk/create.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_CREATE_H -#define OPS_CREATE_H - -#include -#include -#include -#include -#include -#include -#include - -/** - * \ingroup Create - * This struct contains the required information about how to write this stream - */ -struct ops_create_info - { - ops_writer_info_t winfo; - ops_error_t *errors; /*!< an error stack */ - }; - -void ops_prepare_parent_info(ops_create_info_t *parent_info, - ops_writer_info_t *winfo); -ops_create_info_t *ops_create_info_new(void); -void ops_create_info_delete(ops_create_info_t *info); - -ops_memory_t* ops_write_mem_from_file(const char *filename, int* errnum); -int ops_write_file_from_buf(const char *filename, const char* buf, const size_t len, const ops_boolean_t overwrite); - -ops_boolean_t ops_calc_session_key_checksum(ops_pk_session_key_t *session_key, unsigned char *cs); -void ops_build_public_key(ops_memory_t *out,const ops_public_key_t *key, - ops_boolean_t make_packet); -ops_boolean_t ops_write_struct_user_id(ops_user_id_t *id, - ops_create_info_t *info); -ops_boolean_t ops_write_struct_public_key(const ops_public_key_t *key, - ops_create_info_t *info); - -ops_boolean_t ops_write_ss_header(unsigned length,ops_content_tag_t type, - ops_create_info_t *info); -ops_boolean_t ops_write_struct_secret_key(const ops_secret_key_t *key, - const unsigned char* passphrase, - const size_t pplen, - ops_create_info_t *info); -ops_boolean_t ops_write_one_pass_sig(const ops_secret_key_t* skey, - const ops_hash_algorithm_t hash_alg, - const ops_sig_type_t sig_type, - ops_create_info_t* info); -ops_boolean_t ops_write_literal_data_from_buf(const unsigned char *data, - const int maxlen, - const ops_literal_data_type_t type, - ops_create_info_t *info); -ops_pk_session_key_t *ops_create_pk_session_key(const ops_keydata_t *key); -ops_boolean_t ops_write_pk_session_key(ops_create_info_t *info, - ops_pk_session_key_t *pksk); -ops_boolean_t ops_write_transferable_public_key(const ops_keydata_t *key, ops_boolean_t armoured, ops_create_info_t *info); -ops_boolean_t ops_write_transferable_secret_key(const ops_keydata_t *key, const unsigned char* passphrase, const size_t pplen, ops_boolean_t armoured, ops_create_info_t *info); -ops_boolean_t ops_write_transferable_public_key_from_packet_data(const ops_keydata_t *keydata, ops_boolean_t armoured, ops_create_info_t *info); -ops_boolean_t ops_write_transferable_secret_key_from_packet_data(const ops_keydata_t *keydata, ops_boolean_t armoured, ops_create_info_t *info); - - -#endif /*OPS_CREATE_H*/ - -// eof diff --git a/openpgpsdk/src/openpgpsdk/crypto.c b/openpgpsdk/src/openpgpsdk/crypto.c deleted file mode 100644 index 86acebaca..000000000 --- a/openpgpsdk/src/openpgpsdk/crypto.c +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "parse_local.h" - -#include -#include -#include - -#include -#include - -/** -\ingroup Core_MPI -\brief Decrypt and unencode MPI -\param buf Buffer in which to write decrypted unencoded MPI -\param buflen Length of buffer -\param encmpi -\param skey -\return length of MPI -\note only RSA at present -*/ -int ops_decrypt_and_unencode_mpi(unsigned char *buf, unsigned buflen, - const BIGNUM *encmpi, - const ops_secret_key_t *skey) - { - unsigned char encmpibuf[8192]; - unsigned char mpibuf[8192]; - unsigned mpisize; - int n; - int i; - - mpisize=BN_num_bytes(encmpi); - /* MPI can't be more than 65,536 */ - - if(!(mpisize <= sizeof encmpibuf)) // ASSERT(mpisize <= sizeof encmpibuf); - { - fprintf(stderr,"ops_decrypt_and_unencode_mpi: number size too large (%d bytes!).\n",mpisize) ; - return -1 ; - } - - BN_bn2bin(encmpi, encmpibuf); - - if(!(skey->public_key.algorithm == OPS_PKA_RSA)) // ASSERT(skey->public_key.algorithm == OPS_PKA_RSA); - { - fprintf(stderr,"ops_decrypt_and_unencode_mpi: encryption algorithm %02x is not supported. Sorry.\n",skey->public_key.algorithm) ; - return -1 ; - } - - /* - fprintf(stderr,"\nDECRYPTING\n"); - fprintf(stderr,"encrypted data : "); - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", encmpibuf[i]); - fprintf(stderr,"\n"); - */ - - n=ops_rsa_private_decrypt(mpibuf, encmpibuf, (BN_num_bits(encmpi)+7)/8, - &skey->key.rsa, &skey->public_key.key.rsa); - -// if(n == -1) // assert(n != -1); -// return ops_false ; - - /* - fprintf(stderr,"decrypted encoded m buf : "); - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", mpibuf[i]); - fprintf(stderr,"\n"); - */ - - if(n <= 0) - return -1; - - /* - printf(" decrypted=%d ",n); - hexdump(mpibuf,n); - printf("\n"); - */ - - // Decode EME-PKCS1_V1_5 (RFC 2437). - - if(mpibuf[0] != 0 || mpibuf[1] != 2) - return ops_false; - - // Skip the random bytes. - for(i=2 ; i < n && mpibuf[i] ; ++i) - ; - - if(i == n || i < 10) - return ops_false; - - // Skip the zero - ++i; - - // this is the unencoded m buf - if((unsigned)(n-i) <= buflen) - memcpy(buf, mpibuf+i, n-i); - - /* - printf("decoded m buf:\n"); - int j; - for (j=0; jkey.rsa.n))) // ASSERT(sz_encoded_m_buf==(size_t) BN_num_bytes(pkey->key.rsa.n)); - return ops_false ; - - unsigned char encmpibuf[8192]; - int n=0; - - n=ops_rsa_public_encrypt(encmpibuf, encoded_m_buf, sz_encoded_m_buf, &pkey->key.rsa); - - //if(!(n!=-1)) // ASSERT(n!=-1); - // return ops_false ; - - if(n <= 0) - return ops_false; - - skp->rsa.encrypted_m=BN_bin2bn(encmpibuf, n, NULL); - - /* - fprintf(stderr,"encrypted mpi buf : "); - int i; - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", encmpibuf[i]); - fprintf(stderr,"\n"); - */ - - return ops_true; -} - -#define MAXBUF 1024 - -static ops_parse_cb_return_t -callback_write_parsed(const ops_parser_content_t *content_, - ops_parse_cb_info_t *cbinfo); - -/** -\ingroup HighLevel_Crypto -Encrypt a file -\param input_filename Name of file to be encrypted -\param output_filename Name of file to write to. If NULL, name is constructed from input_filename -\param pub_key Public Key to encrypt file for -\param use_armour Write armoured text, if set -\param allow_overwrite Allow output file to be overwrwritten if it exists -\return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_encrypt_file(const char* input_filename, - const char* output_filename, - const ops_keydata_t *pub_key, - const ops_boolean_t use_armour, - const ops_boolean_t allow_overwrite) - { - int fd_in=0; - int fd_out=0; - - ops_create_info_t *cinfo; -#ifdef WIN32 - fd_in=ops_open(input_filename, O_RDONLY | O_BINARY, 0); -#else - fd_in=ops_open(input_filename, O_RDONLY, 0); -#endif - if(fd_in < 0) - { - perror(input_filename); - return ops_false; - } - - fd_out=ops_setup_file_write(&cinfo, output_filename, allow_overwrite); - if (fd_out < 0) - return ops_false; - - // set armoured/not armoured here - if (use_armour) - ops_writer_push_armoured_message(cinfo); - - // Push the encrypted writer - ops_writer_push_stream_encrypt_se_ip(cinfo, pub_key); - ops_writer_push_literal(cinfo); - - // Do the writing - - unsigned buffer[10240]; - for (;;) - { - int n=0; - - n=read(fd_in, buffer, sizeof buffer); - if (!n) - break; - - if(n < 0) - return ops_false ; - - // FIXME: apparently writing can't fail. - ops_write(buffer, n, cinfo); - } - - - // tidy up - close(fd_in); - ops_teardown_file_write(cinfo, fd_out); - - return ops_true; - } - -/** - \ingroup HighLevel_Crypto - Encrypt a compressed, signed stream. - \param cinfo the structure describing where the output will be written. - \param public_key the key used to encrypt the data - \param secret_key the key used to sign the data. If NULL, the data - will not be signed - \param compress If true, compress the stream before encrypting - \param use_armour Write armoured text, if set - \see ops_setup_file_write - - Example Code: - \code - const char* filename = "armour_nocompress_sign.asc"; - ops_create_info_t *info; - int fd = ops_setup_file_write(&info, filename, ops_true); - if (fd < 0) { - fprintf(stderr, "Cannot write to %s\n", filename); - return -1; - } - ops_encrypt_stream(info, public_key, secret_key, ops_false, ops_true); - ops_write(cleartext, strlen(cleartext), info); - ops_writer_close(info); - ops_create_info_delete(info); - \endcode -*/ -extern ops_boolean_t ops_encrypt_stream(ops_create_info_t* cinfo, - const ops_keydata_t* public_key, - const ops_secret_key_t* secret_key, - const ops_boolean_t compress, - const ops_boolean_t use_armour) -{ - if (use_armour) - ops_writer_push_armoured_message(cinfo); - - ops_writer_push_stream_encrypt_se_ip(cinfo, public_key); - - if(compress) - if(!ops_writer_push_compressed(cinfo)) - return ops_false ; - - if (secret_key != NULL) - ops_writer_push_signed(cinfo, OPS_SIG_BINARY, secret_key); - else - ops_writer_push_literal(cinfo); - - return ops_true ; -} - -/** - \ingroup HighLevel_Crypto - \brief Decrypt a chunk of memory, containing a encrypted stream. - \param input_filename Name of file to be decrypted - \param output_filename Name of file to write to. If NULL, the filename is constructed from the input filename, following GPG conventions. - \param keyring Keyring to use - \param use_armour Expect armoured text, if set - \param allow_overwrite Allow output file to overwritten, if set. - \param cb_get_passphrase Callback to use to get passphrase -*/ - -ops_boolean_t ops_decrypt_memory(const unsigned char *encrypted_memory,int em_length, - unsigned char **decrypted_memory,int *out_length, - ops_keyring_t* keyring, - const ops_boolean_t use_armour, - ops_parse_cb_t* cb_get_passphrase) -{ - ops_parse_info_t *pinfo=NULL; - - // setup for reading from given input file - - ops_memory_t *input_mem = ops_memory_new() ; - ops_memory_add(input_mem,encrypted_memory,em_length) ; - - ops_setup_memory_read(&pinfo, input_mem, NULL, callback_write_parsed, ops_false); - - if (pinfo == NULL) - { - perror("cannot create memory read"); - return ops_false; - } - - // setup memory chunk - - ops_memory_t *output_mem; - - ops_setup_memory_write(&pinfo->cbinfo.cinfo, &output_mem,0) ; - - if (output_mem == NULL) - { - perror("Cannot create output memory"); - ops_teardown_memory_read(pinfo, input_mem); - return ops_false; - } - - // \todo check for suffix matching armour param - - // setup keyring and passphrase callback - pinfo->cbinfo.cryptinfo.keyring=keyring; - pinfo->cbinfo.cryptinfo.cb_get_passphrase=cb_get_passphrase; - - // Set up armour/passphrase options - - if (use_armour) - ops_reader_push_dearmour(pinfo); - - // Do it - - ops_boolean_t res = ops_parse_and_print_errors(pinfo); - - // Unsetup - - if (use_armour) - ops_reader_pop_dearmour(pinfo); - - // copy output memory to supplied buffer. - // - *out_length = ops_memory_get_length(output_mem) ; - *decrypted_memory = ops_mallocz(*out_length) ; - memcpy(*decrypted_memory,ops_memory_get_data(output_mem),*out_length) ; - - ops_teardown_memory_write(pinfo->cbinfo.cinfo, output_mem); - ops_teardown_memory_read(pinfo, input_mem); - - return res ; -} - -/** - \ingroup HighLevel_Crypto - \brief Decrypt a file. - \param input_filename Name of file to be decrypted - \param output_filename Name of file to write to. If NULL, the filename is constructed from the input filename, following GPG conventions. - \param keyring Keyring to use - \param use_armour Expect armoured text, if set - \param allow_overwrite Allow output file to overwritten, if set. - \param cb_get_passphrase Callback to use to get passphrase -*/ - -ops_boolean_t ops_decrypt_file(const char* input_filename, - const char* output_filename, - ops_keyring_t* keyring, - const ops_boolean_t use_armour, - const ops_boolean_t allow_overwrite, - ops_parse_cb_t* cb_get_passphrase) -{ - int fd_in=0; - int fd_out=0; - char* myfilename=NULL; - - // - ops_parse_info_t *pinfo=NULL; - - // setup for reading from given input file - fd_in=ops_setup_file_read(&pinfo, input_filename, - NULL, - callback_write_parsed, - ops_false); - if (fd_in < 0) - { - perror(input_filename); - return ops_false; - } - - // setup output filename - - if (output_filename) - { - fd_out=ops_setup_file_write(&pinfo->cbinfo.cinfo, output_filename, - allow_overwrite); - - if (fd_out < 0) - { - perror(output_filename); - ops_teardown_file_read(pinfo, fd_in); - return ops_false; - } - } - else - { - int suffixlen=4; - char *defaultsuffix=".decrypted"; - const char *suffix=input_filename+strlen(input_filename)-suffixlen; - if (!strcmp(suffix, ".gpg") || !strcmp(suffix, ".asc")) - { - myfilename=ops_mallocz(strlen(input_filename)-suffixlen+1); - strncpy(myfilename, input_filename, - strlen(input_filename)-suffixlen); - } - else - { - unsigned filenamelen=strlen(input_filename)+strlen(defaultsuffix)+1; - myfilename=ops_mallocz(filenamelen); - snprintf(myfilename, filenamelen, "%s%s", input_filename, - defaultsuffix); - } - - fd_out=ops_setup_file_write(&pinfo->cbinfo.cinfo, myfilename, - allow_overwrite); - - if (fd_out < 0) - { - perror(myfilename); - free(myfilename); - ops_teardown_file_read(pinfo, fd_in); - return ops_false; - } - - free (myfilename); - } - - // \todo check for suffix matching armour param - - // setup for writing decrypted contents to given output file - - // setup keyring and passphrase callback - pinfo->cbinfo.cryptinfo.keyring=keyring; - pinfo->cbinfo.cryptinfo.cb_get_passphrase=cb_get_passphrase; - - // Set up armour/passphrase options - - if (use_armour) - ops_reader_push_dearmour(pinfo); - - // Do it - - ops_boolean_t res = ops_parse_and_print_errors(pinfo); - - // Unsetup - - if (use_armour) - ops_reader_pop_dearmour(pinfo); - - ops_teardown_file_write(pinfo->cbinfo.cinfo, fd_out); - ops_teardown_file_read(pinfo, fd_in); - // \todo cleardown crypt - - return res; -} -static ops_parse_cb_return_t -callback_write_parsed(const ops_parser_content_t *content_, - ops_parse_cb_info_t *cbinfo) -{ - ops_parser_content_union_t* content - =(ops_parser_content_union_t *)&content_->content; - static ops_boolean_t skipping; - // ops_boolean_t write=ops_true; - - OPS_USED(cbinfo); - - // ops_print_packet(content_); - - if(content_->tag != OPS_PTAG_CT_UNARMOURED_TEXT && skipping) - { - puts("...end of skip"); - skipping=ops_false; - } - - switch(content_->tag) - { - case OPS_PTAG_CT_UNARMOURED_TEXT: - printf("OPS_PTAG_CT_UNARMOURED_TEXT\n"); - if(!skipping) - { - puts("Skipping..."); - skipping=ops_true; - } - fwrite(content->unarmoured_text.data, 1, - content->unarmoured_text.length, stdout); - break; - - case OPS_PTAG_CT_PK_SESSION_KEY: - return callback_pk_session_key(content_, cbinfo); - break; - - case OPS_PARSER_CMD_GET_SECRET_KEY: - return callback_cmd_get_secret_key(content_, cbinfo); - break; - - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - case OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD: - // return callback_cmd_get_secret_key_passphrase(content_,cbinfo); - return cbinfo->cryptinfo.cb_get_passphrase(content_, cbinfo); - break; - - case OPS_PTAG_CT_LITERAL_DATA_BODY: - return callback_literal_data(content_, cbinfo); - break; - - case OPS_PTAG_CT_ARMOUR_HEADER: - case OPS_PTAG_CT_ARMOUR_TRAILER: - case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: - case OPS_PTAG_CT_COMPRESSED: - case OPS_PTAG_CT_LITERAL_DATA_HEADER: - case OPS_PTAG_CT_SE_IP_DATA_BODY: - case OPS_PTAG_CT_SE_IP_DATA_HEADER: - case OPS_PTAG_CT_SE_DATA_BODY: - case OPS_PTAG_CT_SE_DATA_HEADER: - - // Ignore these packets - // They're handled in ops_parse_one_packet() - // and nothing else needs to be done - break; - - default: - // return callback_general(content_,cbinfo); - break; - // fprintf(stderr,"Unexpected packet tag=%d (0x%x)\n",content_->tag, - // content_->tag); - } - - return OPS_RELEASE_MEMORY; -} - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/crypto.h b/openpgpsdk/src/openpgpsdk/crypto.h deleted file mode 100644 index 25bffa073..000000000 --- a/openpgpsdk/src/openpgpsdk/crypto.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_CRYPTO_H -#define OPS_CRYPTO_H - -#include "keyring.h" -#include "util.h" -#include "packet.h" -#include "packet-parse.h" -#include -#include -#include - -#if OPENSSL_VERSION_NUMBER < 0x00908030L -# define OPENSSL_NO_CAMELLIA -#endif - -#define OPS_MIN_HASH_SIZE 16 - -typedef void ops_hash_init_t(ops_hash_t *hash); -typedef void ops_hash_add_t(ops_hash_t *hash,const unsigned char *data, - unsigned length); -typedef unsigned ops_hash_finish_t(ops_hash_t *hash,unsigned char *out); - -/** _ops_hash_t */ -struct _ops_hash_t - { - ops_hash_algorithm_t algorithm; - size_t size; - const char *name; - ops_hash_init_t *init; - ops_hash_add_t *add; - ops_hash_finish_t *finish; - void *data; - }; - -typedef void ops_crypt_set_iv_t(ops_crypt_t *crypt, - const unsigned char *iv); -typedef void ops_crypt_set_key_t(ops_crypt_t *crypt, - const unsigned char *key); -typedef void ops_crypt_init_t(ops_crypt_t *crypt); -typedef void ops_crypt_resync_t(ops_crypt_t *crypt); -typedef void ops_crypt_block_encrypt_t(ops_crypt_t *crypt,void *out, - const void *in); -typedef void ops_crypt_block_decrypt_t(ops_crypt_t *crypt,void *out, - const void *in); -typedef void ops_crypt_cfb_encrypt_t(ops_crypt_t *crypt,void *out, - const void *in, size_t count); -typedef void ops_crypt_cfb_decrypt_t(ops_crypt_t *crypt,void *out, - const void *in, size_t count); -typedef void ops_crypt_finish_t(ops_crypt_t *crypt); - -/** _ops_crypt_t */ -struct _ops_crypt_t - { - ops_symmetric_algorithm_t algorithm; - size_t blocksize; - size_t keysize; - ops_crypt_set_iv_t *set_iv; /* Call this before decrypt init! */ - ops_crypt_set_key_t *set_key; /* Call this before init! */ - ops_crypt_init_t *base_init; - ops_crypt_resync_t *decrypt_resync; - // encrypt/decrypt one block - ops_crypt_block_encrypt_t *block_encrypt; - ops_crypt_block_decrypt_t *block_decrypt; - - // Standard CFB encrypt/decrypt (as used by Sym Enc Int Prot packets) - ops_crypt_cfb_encrypt_t *cfb_encrypt; - ops_crypt_cfb_decrypt_t *cfb_decrypt; - - ops_crypt_finish_t *decrypt_finish; - unsigned char iv[OPS_MAX_BLOCK_SIZE]; - unsigned char civ[OPS_MAX_BLOCK_SIZE]; - unsigned char siv[OPS_MAX_BLOCK_SIZE]; /* Needed for weird v3 resync */ - unsigned char key[OPS_MAX_KEY_SIZE]; - size_t num; /* Offset - see openssl _encrypt doco */ - void *encrypt_key; - void *decrypt_key; - }; - -void ops_crypto_init(void); -void ops_crypto_finish(void); -void ops_hash_md5(ops_hash_t *hash); -void ops_hash_sha1(ops_hash_t *hash); -void ops_hash_sha256(ops_hash_t *hash); -void ops_hash_sha512(ops_hash_t *hash); -void ops_hash_sha384(ops_hash_t *hash); -void ops_hash_sha224(ops_hash_t *hash); -void ops_hash_any(ops_hash_t *hash,ops_hash_algorithm_t alg); -ops_hash_algorithm_t ops_hash_algorithm_from_text(const char *hash); -const char *ops_text_from_hash(ops_hash_t *hash); -unsigned ops_hash_size(ops_hash_algorithm_t alg); -unsigned ops_hash(unsigned char *out,ops_hash_algorithm_t alg,const void *in, - size_t length); - -void ops_hash_add_int(ops_hash_t *hash,unsigned n,unsigned length); - -ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length, - const ops_dsa_signature_t *sig, - const ops_dsa_public_key_t *dsa); -int ops_rsa_public_decrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_public_key_t *rsa); -int ops_rsa_public_encrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_public_key_t *rsa); -int ops_rsa_private_encrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_secret_key_t *srsa, - const ops_rsa_public_key_t *rsa); -int ops_rsa_private_decrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_secret_key_t *srsa, - const ops_rsa_public_key_t *rsa); - -unsigned ops_block_size(ops_symmetric_algorithm_t alg); -unsigned ops_key_size(ops_symmetric_algorithm_t alg); - -int ops_decrypt_data(ops_content_tag_t tag,ops_region_t *region, - ops_parse_info_t *parse_info); - -int ops_crypt_any(ops_crypt_t *decrypt,ops_symmetric_algorithm_t alg); -void ops_decrypt_init(ops_crypt_t *decrypt); -void ops_encrypt_init(ops_crypt_t *encrypt); -size_t ops_decrypt_se(ops_crypt_t *decrypt,void *out,const void *in, - size_t count); -size_t ops_encrypt_se(ops_crypt_t *encrypt,void *out,const void *in, - size_t count); -size_t ops_decrypt_se_ip(ops_crypt_t *decrypt,void *out,const void *in, - size_t count); -size_t ops_encrypt_se_ip(ops_crypt_t *encrypt,void *out,const void *in, - size_t count); -ops_boolean_t ops_is_sa_supported(ops_symmetric_algorithm_t alg); - -void ops_reader_push_decrypt(ops_parse_info_t *pinfo,ops_crypt_t *decrypt, - ops_region_t *region); -void ops_reader_pop_decrypt(ops_parse_info_t *pinfo); - -// Hash everything that's read -void ops_reader_push_hash(ops_parse_info_t *pinfo,ops_hash_t *hash); -void ops_reader_pop_hash(ops_parse_info_t *pinfo); - -int ops_decrypt_and_unencode_mpi(unsigned char *buf,unsigned buflen,const BIGNUM *encmpi, - const ops_secret_key_t *skey); -ops_boolean_t ops_rsa_encrypt_mpi(const unsigned char *buf, const size_t buflen, - const ops_public_key_t *pkey, - ops_pk_session_key_parameters_t *spk); - - -// Encrypt everything that's written -struct ops_key_data; -void ops_writer_push_encrypt(ops_create_info_t *info, - const struct ops_key_data *key); - -ops_boolean_t ops_encrypt_file(const char* input_filename, const char* output_filename, const ops_keydata_t *pub_key, const ops_boolean_t use_armour, const ops_boolean_t allow_overwrite); -ops_boolean_t ops_decrypt_file(const char* input_filename, const char* output_filename, ops_keyring_t *keyring, const ops_boolean_t use_armour, const ops_boolean_t allow_overwrite,ops_parse_cb_t* cb_get_passphrase); -extern ops_boolean_t ops_encrypt_stream(ops_create_info_t* cinfo, const ops_keydata_t* public_key, const ops_secret_key_t* secret_key, const ops_boolean_t compress, const ops_boolean_t use_armour); -ops_boolean_t ops_decrypt_memory(const unsigned char *encrypted_memory,int em_length, unsigned char **decrypted_memory,int *out_length, ops_keyring_t* keyring, const ops_boolean_t use_armour, ops_parse_cb_t* cb_get_passphrase) ; -// Keys -ops_boolean_t ops_rsa_generate_keypair(const int numbits, const unsigned long e, ops_keydata_t* keydata); -ops_keydata_t* ops_rsa_create_selfsigned_keypair(const int numbits, const unsigned long e, ops_user_id_t * userid); - -int ops_dsa_size(const ops_dsa_public_key_t *dsa); -DSA_SIG* ops_dsa_sign(unsigned char* hashbuf, unsigned hashsize, const ops_dsa_secret_key_t *sdsa, const ops_dsa_public_key_t *dsa); -#endif diff --git a/openpgpsdk/src/openpgpsdk/defs.h b/openpgpsdk/src/openpgpsdk/defs.h deleted file mode 100644 index e4f8b48ba..000000000 --- a/openpgpsdk/src/openpgpsdk/defs.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_DEFS_H -#define OPS_DEFS_H - -#define OPS_ARMOURED ops_true -#define OPS_UNARMOURED ops_false - -#define OPS_OVERWRITE_YES ops_true -#define OPS_OVERWRITE_NO ops_false - -#define OPS_ACCUMULATE_YES ops_true -#define OPS_ACCUMULATE_NO ops_false - -#endif /* OPS_DEFS_H */ diff --git a/openpgpsdk/src/openpgpsdk/errors.c b/openpgpsdk/src/openpgpsdk/errors.c deleted file mode 100644 index 2de42341b..000000000 --- a/openpgpsdk/src/openpgpsdk/errors.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * \brief Error Handling - */ - -#include -#include - -#include -#include -#include -#include - -#ifdef WIN32 -#define vsnprintf _vsnprintf -#endif - -#include -#include - -#define ERRNAME(code) { code, #code } - -static ops_errcode_name_map_t errcode_name_map[] = - { - ERRNAME(OPS_E_OK), - ERRNAME(OPS_E_FAIL), - ERRNAME(OPS_E_SYSTEM_ERROR), - ERRNAME(OPS_E_UNIMPLEMENTED), - - ERRNAME(OPS_E_R), - ERRNAME(OPS_E_R_READ_FAILED), - ERRNAME(OPS_E_R_EARLY_EOF), - ERRNAME(OPS_E_R_BAD_FORMAT), - ERRNAME(OPS_E_R_UNCONSUMED_DATA), - - ERRNAME(OPS_E_W), - ERRNAME(OPS_E_W_WRITE_FAILED), - ERRNAME(OPS_E_W_WRITE_TOO_SHORT), - - ERRNAME(OPS_E_P), - ERRNAME(OPS_E_P_NOT_ENOUGH_DATA), - ERRNAME(OPS_E_P_UNKNOWN_TAG), - ERRNAME(OPS_E_P_PACKET_CONSUMED), - ERRNAME(OPS_E_P_MPI_FORMAT_ERROR), - - ERRNAME(OPS_E_C), - - ERRNAME(OPS_E_V), - ERRNAME(OPS_E_V_BAD_SIGNATURE), - ERRNAME(OPS_E_V_NO_SIGNATURE), - ERRNAME(OPS_E_V_UNKNOWN_SIGNER), - - ERRNAME(OPS_E_ALG), - ERRNAME(OPS_E_ALG_UNSUPPORTED_SYMMETRIC_ALG), - ERRNAME(OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG), - ERRNAME(OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG), - ERRNAME(OPS_E_ALG_UNSUPPORTED_HASH_ALG), - - ERRNAME(OPS_E_PROTO), - ERRNAME(OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT), - ERRNAME(OPS_E_PROTO_UNKNOWN_SS), - ERRNAME(OPS_E_PROTO_CRITICAL_SS_IGNORED), - ERRNAME(OPS_E_PROTO_BAD_PUBLIC_KEY_VRSN), - ERRNAME(OPS_E_PROTO_BAD_SIGNATURE_VRSN), - ERRNAME(OPS_E_PROTO_BAD_ONE_PASS_SIG_VRSN), - ERRNAME(OPS_E_PROTO_BAD_PKSK_VRSN), - ERRNAME(OPS_E_PROTO_DECRYPTED_MSG_WRONG_LEN), - ERRNAME(OPS_E_PROTO_BAD_SK_CHECKSUM), - - { 0x00, NULL }, /* this is the end-of-array marker */ - }; - -/** - * \ingroup Core_Errors - * \brief returns error code name - * \param errcode - * \return error code name or "Unknown" - */ -char *ops_errcode(const ops_errcode_t errcode) - { - return(ops_str_from_map((int) errcode, (ops_map_t *) errcode_name_map)); - } - -/** - * \ingroup Core_Errors - * \brief Pushes the given error on the given errorstack - * \param errstack Error stack to use - * \param errcode Code of error to push - * \param sys_errno System errno (used if errcode=OPS_E_SYSTEM_ERROR) - * \param file Source filename where error occurred - * \param line Line in source file where error occurred - * \param fmt Comment - * - */ - -void ops_push_error(ops_error_t **errstack,ops_errcode_t errcode,int sys_errno, - const char *file,int line,const char *fmt,...) - { - // first get the varargs and generate the comment - char *comment; - int maxbuf=128; - va_list args; - ops_error_t *err; - - comment=malloc(maxbuf+1); - assert(comment); - - va_start(args, fmt); - vsnprintf(comment,maxbuf+1,fmt,args); - va_end(args); - - // alloc a new error and add it to the top of the stack - - err=malloc(sizeof(ops_error_t)); - assert(err); - - err->next=*errstack; - *errstack=err; - - // fill in the details - err->errcode=errcode; - err->sys_errno=sys_errno; - err->file=file; - err->line=line; - - err->comment=comment; - } - -/** -\ingroup Core_Errors -\brief print this error -\param err Error to print -*/ -void ops_print_error(ops_error_t *err) - { - printf("%s:%d: ",err->file,err->line); - if(err->errcode==OPS_E_SYSTEM_ERROR) - printf("system error %d returned from %s()\n",err->sys_errno, - err->comment); - else - printf("%s, %s\n",ops_errcode(err->errcode),err->comment); - } - -/** -\ingroup Core_Errors -\brief Print all errors on stack -\param errstack Error stack to print -*/ -void ops_print_errors(ops_error_t *errstack) - { - ops_error_t *err; - - for(err=errstack ; err!=NULL ; err=err->next) - ops_print_error(err); - } - -/** -\ingroup Core_Errors -\brief Return true if given error is present anywhere on stack -\param errstack Error stack to check -\param errcode Error code to look for -\return 1 if found; else 0 -*/ -int ops_has_error(ops_error_t *errstack, ops_errcode_t errcode) - { - ops_error_t *err; - for (err=errstack; err!=NULL; err=err->next) - { - if (err->errcode==errcode) - return 1; - } - return 0; - } - -/** -\ingroup Core_Errors -\brief Frees all errors on stack -\param errstack Error stack to free -*/ -void ops_free_errors(ops_error_t *errstack) -{ - ops_error_t *next; - while(errstack!=NULL) { - next=errstack->next; - free(errstack->comment); - free(errstack); - errstack=next; - } -} - -/** -\ingroup InternalAPI -\brief Moves errors from a create info structure to another error stack. - -The error stack wil be moved from the source structure to the destination -stack. If the destination already has errors defined, the errors will -be appended. -*/ -void ops_move_errors(ops_create_info_t *source, ops_error_t **dest) - { - if (*dest == NULL) - *dest = source->errors; - else - { - ops_error_t *last = *dest; - while(last->next != NULL) - last = last->next; - last->next = source->errors; - } - source->errors = NULL; - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/errors.h b/openpgpsdk/src/openpgpsdk/errors.h deleted file mode 100644 index 6ff958c2d..000000000 --- a/openpgpsdk/src/openpgpsdk/errors.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_ERRORS -#define OPS_ERRORS - -#include "openpgpsdk/types.h" -#include - -/** error codes */ -// Remember to add names to map in errors.c -typedef enum - { - OPS_E_OK=0x0000, /* no error */ - OPS_E_FAIL=0x0001, /* general error */ - OPS_E_SYSTEM_ERROR=0x0002, /* system error, look at errno for details */ - OPS_E_UNIMPLEMENTED=0x0003, /* feature not yet implemented */ - - /* reader errors */ - OPS_E_R=0x1000, /* general reader error */ - OPS_E_R_READ_FAILED =OPS_E_R+1, - OPS_E_R_EARLY_EOF =OPS_E_R+2, - OPS_E_R_BAD_FORMAT =OPS_E_R+3, // For example, malformed armour - OPS_E_R_UNSUPPORTED =OPS_E_R+4, - OPS_E_R_UNCONSUMED_DATA =OPS_E_R+5, - - /* writer errors */ - OPS_E_W=0x2000, /* general writer error */ - OPS_E_W_WRITE_FAILED = OPS_E_W+1, - OPS_E_W_WRITE_TOO_SHORT = OPS_E_W+2, - - /* parser errors */ - OPS_E_P=0x3000, /* general parser error */ - OPS_E_P_NOT_ENOUGH_DATA =OPS_E_P+1, - OPS_E_P_UNKNOWN_TAG =OPS_E_P+2, - OPS_E_P_PACKET_CONSUMED =OPS_E_P+3, - OPS_E_P_MPI_FORMAT_ERROR =OPS_E_P+4, - OPS_E_P_PACKET_NOT_CONSUMED =OPS_E_P+5, - OPS_E_P_DECOMPRESSION_ERROR =OPS_E_P+6, - OPS_E_P_NO_USERID =OPS_E_P+7, - - /* creator errors */ - OPS_E_C=0x4000, /* general creator error */ - - /* validation errors */ - OPS_E_V=0x5000, /* general validation error */ - OPS_E_V_BAD_SIGNATURE =OPS_E_V+1, - OPS_E_V_NO_SIGNATURE =OPS_E_V+2, - OPS_E_V_UNKNOWN_SIGNER =OPS_E_V+3, - OPS_E_V_BAD_HASH =OPS_E_V+4, - - /* Algorithm support errors */ - OPS_E_ALG=0x6000, /* general algorithm error */ - OPS_E_ALG_UNSUPPORTED_SYMMETRIC_ALG =OPS_E_ALG+1, - OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG =OPS_E_ALG+2, - OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG =OPS_E_ALG+3, - OPS_E_ALG_UNSUPPORTED_HASH_ALG =OPS_E_ALG+4, - OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG =OPS_E_ALG+5, - - /* Protocol errors */ - OPS_E_PROTO=0x7000, /* general protocol error */ - OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT =OPS_E_PROTO+2, - OPS_E_PROTO_UNKNOWN_SS =OPS_E_PROTO+3, - OPS_E_PROTO_CRITICAL_SS_IGNORED =OPS_E_PROTO+4, - OPS_E_PROTO_BAD_PUBLIC_KEY_VRSN =OPS_E_PROTO+5, - OPS_E_PROTO_BAD_SIGNATURE_VRSN =OPS_E_PROTO+6, - OPS_E_PROTO_BAD_ONE_PASS_SIG_VRSN =OPS_E_PROTO+7, - OPS_E_PROTO_BAD_PKSK_VRSN =OPS_E_PROTO+8, - OPS_E_PROTO_DECRYPTED_MSG_WRONG_LEN =OPS_E_PROTO+9, - OPS_E_PROTO_BAD_SK_CHECKSUM =OPS_E_PROTO+10, - } ops_errcode_t; - -/** ops_errcode_name_map_t */ -typedef ops_map_t ops_errcode_name_map_t; - -/** one entry in a linked list of errors */ -typedef struct ops_error - { - ops_errcode_t errcode; - int sys_errno; /*!< irrelevent unless errcode == OPS_E_SYSTEM_ERROR */ - char *comment; - const char *file; - int line; - struct ops_error *next; - } ops_error_t; - -char *ops_errcode(const ops_errcode_t errcode); - -void ops_push_error(ops_error_t **errstack,ops_errcode_t errcode,int sys_errno, - const char *file,int line,const char *comment,...); -void ops_print_error(ops_error_t *err); -void ops_print_errors(ops_error_t *errstack); -void ops_free_errors(ops_error_t *errstack); -int ops_has_error(ops_error_t *errstack, ops_errcode_t errcode); -void ops_move_errors(ops_create_info_t *source, ops_error_t **errstack); - -#define OPS_SYSTEM_ERROR_1(err,code,syscall,fmt,arg) do { ops_push_error(err,OPS_E_SYSTEM_ERROR,errno,__FILE__,__LINE__,syscall); ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg); } while(0) -#define OPS_MEMORY_ERROR(err) {fprintf(stderr, "Memory error\n");} // \todo placeholder for better error handling -#define OPS_ERROR(err,code,fmt) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt); } while(0) -#define OPS_ERROR_1(err,code,fmt,arg) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg); } while(0) -#define OPS_ERROR_2(err,code,fmt,arg,arg2) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg,arg2); } while(0) -#define OPS_ERROR_3(err,code,fmt,arg,arg2,arg3) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg,arg2,arg3); } while(0) -#define OPS_ERROR_4(err,code,fmt,arg,arg2,arg3,arg4) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg,arg2,arg3,arg4); } while(0) - -#endif /* OPS_ERRORS */ diff --git a/openpgpsdk/src/openpgpsdk/final.h b/openpgpsdk/src/openpgpsdk/final.h deleted file mode 100644 index 404391d2f..000000000 --- a/openpgpsdk/src/openpgpsdk/final.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* A header that is always included last, for things that need to come last */ - -#ifdef DMALLOC -# include -#endif - diff --git a/openpgpsdk/src/openpgpsdk/fingerprint.c b/openpgpsdk/src/openpgpsdk/fingerprint.c deleted file mode 100644 index 61702f292..000000000 --- a/openpgpsdk/src/openpgpsdk/fingerprint.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include - -#include -#if HAVE_ALLOCA_H -# include -#endif - -#ifdef WIN32 -#define alloca _alloca -#endif - -#include - -static int debug=0; - -/** - * \ingroup Core_Keys - * \brief Calculate a public key fingerprint. - * \param fp Where to put the calculated fingerprint - * \param key The key for which the fingerprint is calculated - */ - -void ops_fingerprint(ops_fingerprint_t *fp,const ops_public_key_t *key) - { - if(key->version == 2 || key->version == 3) - { - unsigned char *bn; - int n; - ops_hash_t md5; - - assert(key->algorithm == OPS_PKA_RSA - || key->algorithm == OPS_PKA_RSA_ENCRYPT_ONLY - || key->algorithm == OPS_PKA_RSA_SIGN_ONLY ); - - ops_hash_md5(&md5); - md5.init(&md5); - - n=BN_num_bytes(key->key.rsa.n); - bn=alloca(n); - BN_bn2bin(key->key.rsa.n,bn); - md5.add(&md5,bn,n); - - n=BN_num_bytes(key->key.rsa.e); - bn=alloca(n); - BN_bn2bin(key->key.rsa.e,bn); - md5.add(&md5,bn,n); - - md5.finish(&md5,fp->fingerprint); - fp->length=16; - } - else - { - ops_memory_t *mem=ops_memory_new(); - ops_hash_t sha1; - size_t l; - - ops_build_public_key(mem,key,ops_false); - - if (debug) - { fprintf(stderr,"--- creating key fingerprint\n"); } - - ops_hash_sha1(&sha1); - sha1.init(&sha1); - - l=ops_memory_get_length(mem); - - ops_hash_add_int(&sha1,0x99,1); - ops_hash_add_int(&sha1,l,2); - sha1.add(&sha1,ops_memory_get_data(mem),l); - sha1.finish(&sha1,fp->fingerprint); - - if (debug) - { fprintf(stderr,"--- finished creating key fingerprint\n"); } - - fp->length=20; - - ops_memory_free(mem); - } - } - -/** - * \ingroup Core_Keys - * \brief Calculate the Key ID from the public key. - * \param keyid Space for the calculated ID to be stored - * \param key The key for which the ID is calculated - */ - -void ops_keyid(unsigned char keyid[8],const ops_public_key_t *key) - { - if(key->version == 2 || key->version == 3) - { - unsigned char bn[8192]; - unsigned n=BN_num_bytes(key->key.rsa.n); - - assert(n <= sizeof bn); - assert(key->algorithm == OPS_PKA_RSA - || key->algorithm == OPS_PKA_RSA_ENCRYPT_ONLY - || key->algorithm == OPS_PKA_RSA_SIGN_ONLY ); - BN_bn2bin(key->key.rsa.n,bn); - memcpy(keyid,bn+n-8,8); - } - else - { - ops_fingerprint_t fingerprint; - - ops_fingerprint(&fingerprint,key); - memcpy(keyid,fingerprint.fingerprint+fingerprint.length-8,8); - } - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/hash.c b/openpgpsdk/src/openpgpsdk/hash.c deleted file mode 100644 index 5154f46ac..000000000 --- a/openpgpsdk/src/openpgpsdk/hash.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include - -#include - -static int debug=0; - -/** -\ingroup Core_Hashes -\brief Add to the hash -\param hash Hash to add to -\param n Int to add -\param length Length of int in bytes -*/ -void ops_hash_add_int(ops_hash_t *hash,unsigned n,unsigned length) - { - while(length--) - { - unsigned char c[1]; - - c[0]=n >> (length*8); - hash->add(hash,c,1); - } - } - -/** -\ingroup Core_Hashes -\brief Setup hash for given hash algorithm -\param hash Hash to set up -\param alg Hash algorithm to use -*/ -void ops_hash_any(ops_hash_t *hash,ops_hash_algorithm_t alg) - { - switch(alg) - { - case OPS_HASH_MD5: - ops_hash_md5(hash); - break; - - case OPS_HASH_SHA1: - ops_hash_sha1(hash); - break; - - case OPS_HASH_SHA256: - ops_hash_sha256(hash); - break; - - case OPS_HASH_SHA384: - ops_hash_sha384(hash); - break; - - case OPS_HASH_SHA512: - ops_hash_sha512(hash); - break; - - case OPS_HASH_SHA224: - ops_hash_sha224(hash); - break; - - default: - assert(0); - } - } - -/** -\ingroup Core_Hashes -\brief Returns size of hash for given hash algorithm -\param alg Hash algorithm to use -\return Size of hash algorithm in bytes -*/ -unsigned ops_hash_size(ops_hash_algorithm_t alg) - { - switch(alg) - { - case OPS_HASH_MD5: - return 16; - - case OPS_HASH_SHA1: - return 20; - - case OPS_HASH_SHA256: - return 32; - - case OPS_HASH_SHA224: - return 28; - - case OPS_HASH_SHA512: - return 64; - - case OPS_HASH_SHA384: - return 48; - - default: - assert(0); - } - - return 0; - } - -/** -\ingroup Core_Hashes -\brief Returns hash enum corresponding to given string -\param hash Text name of hash algorithm i.e. "SHA1" -\returns Corresponding enum i.e. OPS_HASH_SHA1 -*/ -ops_hash_algorithm_t ops_hash_algorithm_from_text(const char *hash) - { - if(!strcmp(hash,"SHA1")) - return OPS_HASH_SHA1; - else if(!strcmp(hash,"MD5")) - return OPS_HASH_MD5; - else if (!strcmp(hash,"SHA256")) - return OPS_HASH_SHA256; - /* - else if (!strcmp(hash,"SHA224")) - return OPS_HASH_SHA224; - */ - else if (!strcmp(hash,"SHA512")) - return OPS_HASH_SHA512; - else if (!strcmp(hash,"SHA384")) - return OPS_HASH_SHA384; - - return OPS_HASH_UNKNOWN; - } - -/** -\ingroup Core_Hashes -\brief Hash given data -\param out Where to write the hash -\param alg Hash algorithm to use -\param in Data to hash -\param length Length of data -\return Size of hash created -*/ -unsigned ops_hash(unsigned char *out,ops_hash_algorithm_t alg,const void *in, - size_t length) - { - ops_hash_t hash; - - ops_hash_any(&hash,alg); - hash.init(&hash); - hash.add(&hash,in,length); - return hash.finish(&hash,out); - } - -/** -\ingroup Core_Hashes -\brief Calculate hash for MDC packet -\param preamble Preamble to hash -\param sz_preamble Size of preamble -\param plaintext Plaintext to hash -\param sz_plaintext Size of plaintext -\param hashed Resulting hash -*/ -void ops_calc_mdc_hash(const unsigned char* preamble, const size_t sz_preamble, const unsigned char* plaintext, const unsigned int sz_plaintext, unsigned char *hashed) - { - ops_hash_t hash; - unsigned char c[1]; - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"ops_calc_mdc_hash():\n"); - - fprintf(stderr,"\npreamble: "); - for (i=0; i -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "keyring_local.h" -#include "parse_local.h" - -#include -#include -#ifndef WIN32 -#include -#include -#endif -#include -#include - -#include -#include - -/** - \ingroup HighLevel_Keyring - - \brief Creates a new ops_keydata_t struct - - \return A new ops_keydata_t struct, initialised to zero. - - \note The returned ops_keydata_t struct must be freed after use with ops_keydata_free. -*/ - -ops_keydata_t *ops_keydata_new(void) - { return ops_mallocz(sizeof(ops_keydata_t)); } - - -// Frees the content of a keydata structure, but not the keydata itself. -static void keydata_internal_free(ops_keydata_t *keydata) - { - unsigned n; - - for(n=0 ; n < keydata->nuids ; ++n) - ops_user_id_free(&keydata->uids[n]); - free(keydata->uids); - keydata->uids=NULL; - keydata->nuids=0; - - for(n=0 ; n < keydata->npackets ; ++n) - ops_packet_free(&keydata->packets[n]); - free(keydata->packets); - keydata->packets=NULL; - keydata->npackets=0; - -/* for(n=0;nnsigs;++n) - { - ops_user_id_free(keydata->sigs[n].userid) ; - ops_packet_free(keydata->sigs[n].packet) ; - }*/ - free(keydata->sigs) ; - - if(keydata->type == OPS_PTAG_CT_PUBLIC_KEY) - ops_public_key_free(&keydata->key.pkey); - else - ops_secret_key_free(&keydata->key.skey); - - } - -/** - \ingroup HighLevel_Keyring - - \brief Frees keydata and its memory - - \param keydata Key to be freed. - - \note This frees the keydata itself, as well as any other memory - alloc-ed by it. -*/ -void ops_keydata_free(ops_keydata_t *keydata) - { - keydata_internal_free(keydata); - free(keydata); - } - -// \todo check where userid pointers are copied -/** -\ingroup Core_Keys -\brief Copy user id, including contents -\param dst Destination User ID -\param src Source User ID -\note If dst already has a user_id, it will be freed. -*/ -void ops_copy_userid(ops_user_id_t* dst, const ops_user_id_t* src) - { - int len=strlen((char *)src->user_id); - if (dst->user_id) - free(dst->user_id); - dst->user_id=ops_mallocz(len+1); - - memcpy(dst->user_id, src->user_id, len); - } -// \todo check where pkt pointers are copied -/** -\ingroup Core_Keys -\brief Copy packet, including contents -\param dst Destination packet -\param src Source packet -\note If dst already has a packet, it will be freed. -*/ -void ops_copy_packet(ops_packet_t* dst, const ops_packet_t* src) - { - if (dst->raw) - free(dst->raw); - dst->raw=ops_mallocz(src->length); - - dst->length=src->length; - memcpy(dst->raw, src->raw, src->length); - } - - - -/** -\ingroup Core_Keys -\brief Copies entire key data -\param dst Destination key where to copy -\param src Source key to copy -*/ -void ops_keydata_copy(ops_keydata_t *dst,const ops_keydata_t *src) -{ - unsigned n; - - keydata_internal_free(dst) ; - memset(dst,0,sizeof(ops_keydata_t)) ; - - dst->uids = (ops_user_id_t*)ops_mallocz(src->nuids * sizeof(ops_user_id_t)) ; - dst->nuids = src->nuids ; - dst->nuids_allocated = src->nuids ; - - for(n=0 ; n < src->nuids ; ++n) - ops_copy_userid(&dst->uids[n],&src->uids[n]) ; - - dst->packets = (ops_packet_t*)ops_mallocz(src->npackets * sizeof(ops_packet_t)) ; - dst->npackets = src->npackets ; - dst->npackets_allocated = src->npackets ; - - for(n=0 ; n < src->npackets ; ++n) - ops_copy_packet(&(dst->packets[n]),&(src->packets[n])); - - dst->nsigs = src->nsigs ; - dst->sigs = (sigpacket_t*)ops_mallocz(src->nsigs * sizeof(sigpacket_t)) ; - dst->nsigs_allocated = src->nsigs ; - - for(n=0 ; n < src->nsigs ; ++n) - { - dst->sigs[n].userid = (ops_user_id_t*)ops_mallocz(sizeof(ops_user_id_t)) ; - dst->sigs[n].packet = (ops_packet_t*)ops_mallocz(sizeof(ops_packet_t)) ; - - ops_copy_userid(dst->sigs[n].userid,src->sigs[n].userid) ; - ops_copy_packet(dst->sigs[n].packet,src->sigs[n].packet) ; - } - - dst->key_id[0] = src->key_id[0] ; - dst->key_id[1] = src->key_id[1] ; - dst->key_id[2] = src->key_id[2] ; - dst->key_id[3] = src->key_id[3] ; - dst->key_id[4] = src->key_id[4] ; - dst->key_id[5] = src->key_id[5] ; - dst->key_id[6] = src->key_id[6] ; - dst->key_id[7] = src->key_id[7] ; - dst->type = src->type ; - dst->key = src->key ; - dst->fingerprint = src->fingerprint ; - - if(src->type == OPS_PTAG_CT_PUBLIC_KEY) - ops_public_key_copy(&dst->key.pkey,&src->key.pkey); - else - ops_secret_key_copy(&dst->key.skey,&src->key.skey); -} - - -/** - \ingroup HighLevel_KeyGeneral - - \brief Returns the public key in the given keydata. - \param keydata - - \return Pointer to public key - - \note This is not a copy, do not free it after use. -*/ - -const ops_public_key_t * -ops_get_public_key_from_data(const ops_keydata_t *keydata) - { - if(keydata->type == OPS_PTAG_CT_PUBLIC_KEY) - return &keydata->key.pkey; - return &keydata->key.skey.public_key; - } - -/** -\ingroup HighLevel_KeyGeneral - -\brief Check whether this is a secret key or not. -*/ - -ops_boolean_t ops_is_key_secret(const ops_keydata_t *data) - { return data->type != OPS_PTAG_CT_PUBLIC_KEY; } - -/** - \ingroup HighLevel_KeyGeneral - - \brief Returns the secret key in the given keydata. - - \note This is not a copy, do not free it after use. - - \note This returns a const. If you need to be able to write to this pointer, use ops_get_writable_secret_key_from_data -*/ - -const ops_secret_key_t * -ops_get_secret_key_from_data(const ops_keydata_t *data) - { - if(data->type != OPS_PTAG_CT_SECRET_KEY) - return NULL; - - return &data->key.skey; - } - -/** - \ingroup HighLevel_KeyGeneral - - \brief Returns the secret key in the given keydata. - - \note This is not a copy, do not free it after use. - - \note If you do not need to be able to modify this key, there is an equivalent read-only function ops_get_secret_key_from_data. -*/ - -ops_secret_key_t * -ops_get_writable_secret_key_from_data(ops_keydata_t *data) - { - if (data->type != OPS_PTAG_CT_SECRET_KEY) - return NULL; - - return &data->key.skey; - } - -typedef struct - { - const ops_keydata_t *key; - char *pphrase; - ops_secret_key_t *skey; - } decrypt_arg_t; - -static ops_parse_cb_return_t decrypt_cb(const ops_parser_content_t *content_, - ops_parse_cb_info_t *cbinfo) - { - const ops_parser_content_union_t *content=&content_->content; - decrypt_arg_t *arg=ops_parse_cb_get_arg(cbinfo); - - OPS_USED(cbinfo); - - switch(content_->tag) - { - case OPS_PARSER_PTAG: - case OPS_PTAG_CT_USER_ID: - case OPS_PTAG_CT_SIGNATURE: - case OPS_PTAG_CT_SIGNATURE_HEADER: - case OPS_PTAG_CT_SIGNATURE_FOOTER: - case OPS_PTAG_CT_TRUST: - break; - - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - *content->secret_key_passphrase.passphrase=arg->pphrase; - return OPS_KEEP_MEMORY; - - case OPS_PARSER_ERRCODE: - switch(content->errcode.errcode) - { - case OPS_E_P_MPI_FORMAT_ERROR: - /* Generally this means a bad passphrase */ - fprintf(stderr,"Bad passphrase!\n"); - goto done; - - case OPS_E_P_PACKET_CONSUMED: - /* And this is because of an error we've accepted */ - goto done; - - default: - fprintf(stderr,"parse error: %s\n", - ops_errcode(content->errcode.errcode)); - assert(0); - break; - } - - break; - - case OPS_PARSER_ERROR: - printf("parse error: %s\n",content->error.error); - assert(0); - break; - - case OPS_PTAG_CT_SECRET_KEY: - arg->skey=malloc(sizeof *arg->skey); - *arg->skey=content->secret_key; - return OPS_KEEP_MEMORY; - - case OPS_PARSER_PACKET_END: - // nothing to do - break; - - default: - fprintf(stderr,"Unexpected tag %d (0x%x)\n",content_->tag, - content_->tag); - assert(0); - } - - done: - return OPS_RELEASE_MEMORY; - } - -/** -\ingroup Core_Keys -\brief Decrypts secret key from given keydata with given passphrase -\param key Key from which to get secret key -\param pphrase Passphrase to use to decrypt secret key -\return secret key -*/ -ops_secret_key_t *ops_decrypt_secret_key_from_data(const ops_keydata_t *key, - const char *pphrase) - { - ops_parse_info_t *pinfo; - decrypt_arg_t arg; - - memset(&arg,'\0',sizeof arg); - arg.key=key; - arg.pphrase=strdup(pphrase); - - pinfo=ops_parse_info_new(); - - ops_keydata_reader_set(pinfo,key); - ops_parse_cb_set(pinfo,decrypt_cb,&arg); - pinfo->rinfo.accumulate=ops_true; - - ops_parse(pinfo,ops_false); - - ops_parse_info_delete(pinfo); - - return arg.skey; - } - -/** -\ingroup Core_Keys -\brief Set secret key in content -\param content Content to be set -\param key Keydata to get secret key from -*/ -void ops_set_secret_key(ops_parser_content_union_t* content,const ops_keydata_t *key) - { - *content->get_secret_key.secret_key=&key->key.skey; - } - -/** -\ingroup Core_Keys -\brief Get Key ID from keydata -\param key Keydata to get Key ID from -\return Pointer to Key ID inside keydata -*/ -const unsigned char* ops_get_key_id(const ops_keydata_t *key) - { - return key->key_id; - } - -/** -\ingroup Core_Keys -\brief How many User IDs in this key? -\param key Keydata to check -\return Num of user ids -*/ -unsigned ops_get_user_id_count(const ops_keydata_t *key) - { - return key->nuids; - } - -/** -\ingroup Core_Keys -\brief Get indexed user id from key -\param key Key to get user id from -\param index Which key to get -\return Pointer to requested user id -*/ -const unsigned char* ops_get_user_id(const ops_keydata_t *key, unsigned index) - { - return key->uids[index].user_id; - } - -/** - \ingroup HighLevel_Supported - \brief Checks whether key's algorithm and type are supported by OpenPGP::SDK - \param keydata Key to be checked - \return ops_true if key algorithm and type are supported by OpenPGP::SDK; ops_false if not -*/ - -ops_boolean_t ops_is_key_supported(const ops_keydata_t *keydata) -{ - if(keydata->type == OPS_PTAG_CT_PUBLIC_KEY) - { - if(keydata->key.pkey.algorithm == OPS_PKA_RSA) - return ops_true; - } - return ops_false; -} - - -/** - \ingroup HighLevel_KeyringFind - - \brief Returns key inside a keyring, chosen by index - - \param keyring Pointer to existing keyring - \param index Index of required key - - \note Index starts at 0 - - \note This returns a pointer to the original key, not a copy. You do not need to free the key after use. - - \return Pointer to the required key; or NULL if index too large. - - Example code: - \code - void example(const ops_keyring_t* keyring) - { - ops_keydata_t* keydata=NULL; - keydata=ops_keyring_get_key_by_index(keyring, 0); - ... - } - \endcode -*/ - -const ops_keydata_t* ops_keyring_get_key_by_index(const ops_keyring_t *keyring, int index) - { - if (index >= keyring->nkeys) - return NULL; - return &keyring->keys[index]; - } - -/** -\ingroup Core_Keys -\brief Add User ID to keydata -\param keydata Key to which to add User ID -\param userid User ID to add -\return Pointer to new User ID -*/ -ops_user_id_t* ops_add_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* userid) - { - ops_user_id_t* new_uid=NULL; - - EXPAND_ARRAY(keydata, uids); - - // initialise new entry in array - new_uid=&keydata->uids[keydata->nuids]; - - new_uid->user_id=NULL; - - // now copy it - ops_copy_userid(new_uid,userid); - keydata->nuids++; - - return new_uid; - } - -/** -\ingroup Core_Keys -\brief Add packet to key -\param keydata Key to which to add packet -\param packet Packet to add -\return Pointer to new packet -*/ -ops_packet_t* ops_add_packet_to_keydata(ops_keydata_t* keydata, const ops_packet_t* packet) - { - ops_packet_t* new_pkt=NULL; - - EXPAND_ARRAY(keydata, packets); - - // initialise new entry in array - new_pkt=&keydata->packets[keydata->npackets]; - new_pkt->length=0; - new_pkt->raw=NULL; - - // now copy it - ops_copy_packet(new_pkt, packet); - keydata->npackets++; - - return new_pkt; - } - -/** -\ingroup Core_Keys -\brief Add signed User ID to key -\param keydata Key to which to add signed User ID -\param user_id User ID to add -\param sigpacket Packet to add -*/ -void ops_add_signed_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* user_id, const ops_packet_t* sigpacket) - { - //int i=0; - ops_user_id_t * uid=NULL; - ops_packet_t * pkt=NULL; - - uid=ops_add_userid_to_keydata(keydata, user_id); - pkt=ops_add_packet_to_keydata(keydata, sigpacket); - - /* - * add entry in sigs array to link the userid and sigpacket - */ - - // and add ptr to it from the sigs array - EXPAND_ARRAY(keydata, sigs); - - // setup new entry in array - - keydata->sigs[keydata->nsigs].userid=uid; - keydata->sigs[keydata->nsigs].packet=pkt; - - keydata->nsigs++; - } - -/** -\ingroup Core_Keys -\brief Add selfsigned User ID to key -\param keydata Key to which to add user ID -\param userid Self-signed User ID to add -\return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_add_selfsigned_userid_to_keydata(ops_keydata_t* keydata, ops_user_id_t* userid) - { - ops_packet_t sigpacket; - - ops_memory_t* mem_userid=NULL; - ops_create_info_t* cinfo_userid=NULL; - - ops_memory_t* mem_sig=NULL; - ops_create_info_t* cinfo_sig=NULL; - - ops_create_signature_t *sig=NULL; - - /* - * create signature packet for this userid - */ - - // create userid pkt - ops_setup_memory_write(&cinfo_userid, &mem_userid, 128); - ops_write_struct_user_id(userid, cinfo_userid); - - // create sig for this pkt - - sig=ops_create_signature_new(); - ops_signature_start_key_signature(sig, &keydata->key.skey.public_key, userid, OPS_CERT_POSITIVE); - ops_signature_add_creation_time(sig,time(NULL)); - ops_signature_add_issuer_key_id(sig,keydata->key_id); - ops_signature_add_primary_user_id(sig, ops_true); - ops_signature_hashed_subpackets_end(sig); - - ops_setup_memory_write(&cinfo_sig, &mem_sig, 128); - ops_write_signature(sig,&keydata->key.skey.public_key,&keydata->key.skey, cinfo_sig); - - // add this packet to keydata - - sigpacket.length=ops_memory_get_length(mem_sig); - sigpacket.raw=ops_memory_get_data(mem_sig); - - // add userid to keydata - ops_add_signed_userid_to_keydata(keydata, userid, &sigpacket); - - // cleanup - ops_create_signature_delete(sig); - ops_create_info_delete(cinfo_userid); - ops_create_info_delete(cinfo_sig); - ops_memory_free(mem_userid); - ops_memory_free(mem_sig); - - return ops_true; - } - -/** -\ingroup Core_Keys -\brief Add signature to given key -\return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_sign_key(ops_keydata_t* keydata, const unsigned char *signers_key_id,ops_secret_key_t *signers_key) -{ -/* ops_memory_t* mem_userid=NULL; */ - ops_memory_t* mem_sig=NULL; - ops_create_info_t* cinfo_sig=NULL; - - ops_create_signature_t *sig=NULL; - - /* - * create signature packet for this userid - */ - - // create sig for this pkt - - sig=ops_create_signature_new(); - ops_signature_start_key_signature(sig, &keydata->key.skey.public_key, &keydata->uids[0], OPS_CERT_GENERIC); - ops_signature_add_creation_time(sig,time(NULL)); - ops_signature_add_issuer_key_id(sig,signers_key_id); - ops_signature_hashed_subpackets_end(sig); - - ops_setup_memory_write(&cinfo_sig, &mem_sig, 128); - ops_write_signature(sig,&signers_key->public_key,signers_key, cinfo_sig); - - // add this packet to keydata - - ops_packet_t sigpacket; - sigpacket.length=ops_memory_get_length(mem_sig); - sigpacket.raw=ops_memory_get_data(mem_sig); - - // add userid to keydata - ops_add_packet_to_keydata(keydata, &sigpacket); - - // cleanup - ops_create_signature_delete(sig); - ops_create_info_delete(cinfo_sig); - ops_memory_free(mem_sig); - - return ops_true; -} -/** -\ingroup Core_Keys -\brief Initialise ops_keydata_t -\param keydata Keydata to initialise -\param type OPS_PTAG_CT_PUBLIC_KEY or OPS_PTAG_CT_SECRET_KEY -*/ -void ops_keydata_init(ops_keydata_t* keydata, const ops_content_tag_t type) - { - assert(keydata->type==OPS_PTAG_CT_RESERVED); - assert(type==OPS_PTAG_CT_PUBLIC_KEY || type==OPS_PTAG_CT_SECRET_KEY); - - keydata->type=type; - } - -/** - Example Usage: - \code - - // definition of variables - ops_keyring_t keyring; - char* filename="~/.gnupg/pubring.gpg"; - - // Read keyring from file - ops_keyring_read_from_file(&keyring,filename); - - // do actions using keyring - ... - - // Free memory alloc-ed in ops_keyring_read_from_file() - ops_keyring_free(keyring); - \endcode -*/ - -static ops_parse_cb_return_t -cb_keyring_read(const ops_parser_content_t *content_, - ops_parse_cb_info_t *cbinfo); - -/** - \ingroup HighLevel_KeyringRead - - \brief Reads a keyring from a file - - \param keyring Pointer to an existing ops_keyring_t struct - \param armour ops_true if file is armoured; else ops_false - \param filename Filename of keyring to be read - - \return ops true if OK; ops_false on error - - \note Keyring struct must already exist. - - \note Can be used with either a public or secret keyring. - - \note You must call ops_keyring_free() after usage to free alloc-ed memory. - - \note If you call this twice on the same keyring struct, without calling - ops_keyring_free() between these calls, you will introduce a memory leak. - - \sa ops_keyring_read_from_mem() - \sa ops_keyring_free() - - Example code: - \code - ops_keyring_t* keyring=ops_mallocz(sizeof *keyring); - ops_boolean_t armoured=ops_false; - ops_keyring_read_from_file(keyring, armoured, "~/.gnupg/pubring.gpg"); - ... - ops_keyring_free(keyring); - free (keyring); - - \endcode -*/ - -ops_boolean_t ops_keyring_read_from_file(ops_keyring_t *keyring, const ops_boolean_t armour, const char *filename) - { - ops_parse_info_t *pinfo; - int fd; - ops_boolean_t res = ops_true; - - pinfo=ops_parse_info_new(); - - // add this for the moment, - // \todo need to fix the problems with reading signature subpackets later - - // ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_RAW); - ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_PARSED); - - fd=ops_open(filename,O_RDONLY | O_BINARY, 0); - - if(fd < 0) - { - ops_parse_info_delete(pinfo); - perror(filename); - return ops_false; - } - - ops_reader_set_fd(pinfo,fd); - - ops_parse_cb_set(pinfo,cb_keyring_read,NULL); - - if (armour) - { ops_reader_push_dearmour(pinfo); } - - if ( ops_parse_and_accumulate(keyring,pinfo) == 0 ) { - res = ops_false; - } - else - { - res = ops_true; - } - ops_print_errors(ops_parse_info_get_errors(pinfo)); - - if (armour) - ops_reader_pop_dearmour(pinfo); - - close(fd); - - ops_parse_info_delete(pinfo); - - return res; - } - -/** - \ingroup HighLevel_KeyringRead - - \brief Reads a keyring from memory - - \param keyring Pointer to existing ops_keyring_t struct - \param armour ops_true if file is armoured; else ops_false - \param mem Pointer to a ops_memory_t struct containing keyring to be read - - \return ops true if OK; ops_false on error - - \note Keyring struct must already exist. - - \note Can be used with either a public or secret keyring. - - \note You must call ops_keyring_free() after usage to free alloc-ed memory. - - \note If you call this twice on the same keyring struct, without calling - ops_keyring_free() between these calls, you will introduce a memory leak. - - \sa ops_keyring_read_from_file - \sa ops_keyring_free - - Example code: - \code - ops_memory_t* mem; // Filled with keyring packets - ops_keyring_t* keyring=ops_mallocz(sizeof *keyring); - ops_boolean_t armoured=ops_false; - ops_keyring_read_from_mem(keyring, armoured, mem); - ... - ops_keyring_free(keyring); - free (keyring); - \endcode -*/ -ops_boolean_t ops_keyring_read_from_mem(ops_keyring_t *keyring, const ops_boolean_t armour, ops_memory_t* mem) - { - ops_parse_info_t *pinfo=NULL; - ops_boolean_t res = ops_true; - - ops_setup_memory_read(&pinfo, mem, NULL, cb_keyring_read, - OPS_ACCUMULATE_NO); - ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_PARSED); - - if (armour) - { ops_reader_push_dearmour(pinfo); } - - if ( ops_parse_and_accumulate(keyring,pinfo) == 0 ) - { - res = ops_false; - } - else - { - res = ops_true; - } - ops_print_errors(ops_parse_info_get_errors(pinfo)); - - if (armour) - ops_reader_pop_dearmour(pinfo); - - // don't call teardown_memory_read because memory was passed - // in. But we need to free the parse_info object allocated by - // ops_setup_memory_read(). - ops_parse_info_delete(pinfo); - - return res; - } - -/** - \ingroup HighLevel_KeyringRead - - \brief Frees keyring's contents (but not keyring itself) - - \param keyring Keyring whose data is to be freed - - \note This does not free keyring itself, just the memory alloc-ed in it. - */ -void ops_keyring_free(ops_keyring_t *keyring) - { - int i; - - for (i = 0; i < keyring->nkeys; i++) - keydata_internal_free(&keyring->keys[i]); - - free(keyring->keys); - keyring->keys=NULL; - keyring->nkeys=0; - keyring->nkeys_allocated=0; - } - -void ops_keyring_remove_key(ops_keyring_t *keyring,int index) -{ - if(index > keyring->nkeys-1) - { - fprintf(stderr,"ops_keyring_remove_key: ERROR: cannot remove key with index %d > %d.",index,keyring->nkeys-1) ; - return ; - } - - if(index < keyring->nkeys-1) - ops_keydata_copy(&keyring->keys[index],&keyring->keys[keyring->nkeys-1]) ; - - keydata_internal_free(&keyring->keys[keyring->nkeys-1]) ; - keyring->nkeys-- ; - - // keyring->nkeys_allocated is left untouched intentionnaly. -} - -/** - \ingroup HighLevel_KeyringFind - - \brief Finds key in keyring from its Key ID - - \param keyring Keyring to be searched - \param keyid ID of required key - - \return Pointer to key, if found; NULL, if not found - - \note This returns a pointer to the key inside the given keyring, not a copy. Do not free it after use. - - Example code: - \code - void example(ops_keyring_t* keyring) - { - ops_keydata_t* keydata=NULL; - unsigned char keyid[OPS_KEY_ID_SIZE]; // value set elsewhere - keydata=ops_keyring_find_key_by_id(keyring,keyid); - ... - } - \endcode -*/ -const ops_keydata_t * -ops_keyring_find_key_by_id(const ops_keyring_t *keyring, - const unsigned char keyid[OPS_KEY_ID_SIZE]) - { - int n; - - if (!keyring) - return NULL; - - for(n=0 ; n < keyring->nkeys ; ++n) - { - if(!memcmp(keyring->keys[n].key_id,keyid,OPS_KEY_ID_SIZE)) - return &keyring->keys[n]; - } - - return NULL; - } - -/** - \ingroup HighLevel_KeyringFind - - \brief Finds key from its User ID - - \param keyring Keyring to be searched - \param userid User ID of required key - - \return Pointer to Key, if found; NULL, if not found - - \note This returns a pointer to the key inside the keyring, not a copy. Do not free it. - - Example code: - \code - void example(ops_keyring_t* keyring) - { - ops_keydata_t* keydata=NULL; - keydata=ops_keyring_find_key_by_userid(keyring,"user@domain.com"); - ... - } - \endcode -*/ -const ops_keydata_t * -ops_keyring_find_key_by_userid(const ops_keyring_t *keyring, - const char *userid) - { - int n=0; - unsigned int i=0; - - if (!keyring) - return NULL; - - for(n=0 ; n < keyring->nkeys ; ++n) - { - for(i=0; ikeys[n].nuids; i++) - { - //printf("[%d][%d] userid %s\n",n,i,keyring->keys[n].uids[i].user_id); - if(!strncmp((char *)keyring->keys[n].uids[i].user_id,userid,strlen(userid))) - return &keyring->keys[n]; - } - } - - //printf("end: n=%d,i=%d\n",n,i); - return NULL; - } - -/** - \ingroup HighLevel_KeyringList - - \brief Prints all keys in keyring to stdout. - - \param keyring Keyring to use - - \return none - - Example code: - \code - void example() - { - ops_keyring_t* keyring=ops_mallocz(sizeof *keyring); - ops_boolean_t armoured=ops_false; - ops_keyring_read_from_file(keyring, armoured, "~/.gnupg/pubring.gpg"); - - ops_keyring_list(keyring); - - ops_keyring_free(keyring); - free (keyring); - } - \endcode -*/ - -void -ops_keyring_list(const ops_keyring_t* keyring) - { - int n; - unsigned int i; - ops_keydata_t* key; - - printf ("%d keys\n", keyring->nkeys); - for(n=0,key=&keyring->keys[n] ; n < keyring->nkeys ; ++n,++key) - { - for(i=0; inuids; i++) - { - if (ops_is_key_secret(key)) - ops_print_secret_keydata(key); - else - ops_print_public_keydata(key); - } - - } - } - -/* Static functions */ - -static ops_parse_cb_return_t -cb_keyring_read(const ops_parser_content_t *content_, - ops_parse_cb_info_t *cbinfo) -{ - OPS_USED(cbinfo); - - switch(content_->tag) - { - case OPS_PARSER_PTAG: - case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: // we get these because we didn't prompt - case OPS_PTAG_CT_SIGNATURE_HEADER: - case OPS_PTAG_CT_SIGNATURE_FOOTER: - case OPS_PTAG_CT_SIGNATURE: - case OPS_PTAG_CT_TRUST: - case OPS_PARSER_ERRCODE: - break; - - default: - ; - } - - return OPS_RELEASE_MEMORY; -} - -/** - \ingroup HighLevel_KeyringList - - \brief Saves keyring to specified file - - \param keyring Keyring to save - \param armoured Save in ascii armoured format - \param output filename - - \return ops_true is anything when ok -*/ - -ops_boolean_t ops_write_keyring_to_file(const ops_keyring_t *keyring,ops_boolean_t armoured,const char *filename,ops_boolean_t write_all_packets) -{ - ops_create_info_t *info; - int fd = ops_setup_file_write(&info, filename, ops_true); - - if (fd < 0) - { - fprintf(stderr,"ops_write_keyring(): ERROR: Cannot write to %s\n",filename ) ; - return ops_false ; - } - - int i; - for(i=0;inkeys;++i) -// if(keyring->keys[i].key.pkey.algorithm == OPS_PKA_RSA) - if(write_all_packets) - ops_write_transferable_public_key_from_packet_data(&keyring->keys[i],armoured,info) ; - else - ops_write_transferable_public_key(&keyring->keys[i],armoured,info) ; -// else -// { -// fprintf(stdout, "ops_write_keyring: not writing key. Algorithm not handled: ") ; -// ops_print_public_keydata(&keyring->keys[i]); -// fprintf(stdout, "\n") ; -// } - - ops_teardown_file_write(info, fd); - - return ops_true ; -} - -/*\@}*/ - -// eof diff --git a/openpgpsdk/src/openpgpsdk/keyring.h b/openpgpsdk/src/openpgpsdk/keyring.h deleted file mode 100644 index 028416cec..000000000 --- a/openpgpsdk/src/openpgpsdk/keyring.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_KEYRING_H -#define OPS_KEYRING_H - -#include "packet.h" -#include "memory.h" - -typedef struct ops_keydata ops_keydata_t; - -/** \struct ops_keyring_t - * A keyring - */ - -typedef struct - { - int nkeys; // while we are constructing a key, this is the offset - int nkeys_allocated; - ops_keydata_t *keys; - } ops_keyring_t; - -const ops_keydata_t * -ops_keyring_find_key_by_id(const ops_keyring_t *keyring, - const unsigned char keyid[OPS_KEY_ID_SIZE]); -const ops_keydata_t * -ops_keyring_find_key_by_userid(const ops_keyring_t *keyring, - const char* userid); -void ops_keydata_free(ops_keydata_t *key); -void ops_keydata_copy(ops_keydata_t *dst,const ops_keydata_t *src); -void ops_keyring_free(ops_keyring_t *keyring); -void ops_dump_keyring(const ops_keyring_t *keyring); -const ops_public_key_t * -ops_get_public_key_from_data(const ops_keydata_t *data); -ops_boolean_t ops_is_key_secret(const ops_keydata_t *data); -const ops_secret_key_t * -ops_get_secret_key_from_data(const ops_keydata_t *data); -ops_secret_key_t * -ops_get_writable_secret_key_from_data(ops_keydata_t *data); -ops_secret_key_t *ops_decrypt_secret_key_from_data(const ops_keydata_t *key, - const char *pphrase); - -ops_boolean_t ops_keyring_read_from_file(ops_keyring_t *keyring, const ops_boolean_t armour, const char *filename); -ops_boolean_t ops_keyring_read_from_mem(ops_keyring_t *keyring, const ops_boolean_t armour, ops_memory_t *mem); -ops_boolean_t ops_write_keyring_to_file(const ops_keyring_t *keyring,ops_boolean_t armoured,const char *filename,ops_boolean_t write_all_packets); - -char *ops_malloc_passphrase(char *passphrase); -char *ops_get_passphrase(void); - -void ops_keyring_list(const ops_keyring_t* keyring); - -void ops_set_secret_key(ops_parser_content_union_t* content,const ops_keydata_t *key); - -const unsigned char* ops_get_key_id(const ops_keydata_t *key); -unsigned ops_get_user_id_count(const ops_keydata_t *key); -const unsigned char* ops_get_user_id(const ops_keydata_t *key, unsigned index); -ops_boolean_t ops_is_key_supported(const ops_keydata_t *key); -const ops_keydata_t* ops_keyring_get_key_by_index(const ops_keyring_t *keyring, int index); -void ops_keyring_remove_key(ops_keyring_t *keyring,int index) ; - -ops_user_id_t* ops_add_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* userid); -ops_packet_t* ops_add_packet_to_keydata(ops_keydata_t* keydata, const ops_packet_t* packet); -void ops_add_signed_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* userid, const ops_packet_t* packet); - -ops_boolean_t ops_add_selfsigned_userid_to_keydata(ops_keydata_t* keydata, ops_user_id_t* userid); -ops_boolean_t ops_sign_key(ops_keydata_t* keydata_to_sign, const unsigned char *signers_key_id,ops_secret_key_t *signers_decrypted_private_key); - -ops_keydata_t *ops_keydata_new(void); -void ops_keydata_init(ops_keydata_t* keydata, const ops_content_tag_t type); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/keyring_local.h b/openpgpsdk/src/openpgpsdk/keyring_local.h deleted file mode 100644 index 5c3860f35..000000000 --- a/openpgpsdk/src/openpgpsdk/keyring_local.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include - -#define DECLARE_ARRAY(type,arr) unsigned n##arr; unsigned n##arr##_allocated; type *arr -#define EXPAND_ARRAY(str,arr) do if(str->n##arr == str->n##arr##_allocated) \ - { \ - str->n##arr##_allocated=str->n##arr##_allocated*2+10; \ - str->arr=realloc(str->arr,str->n##arr##_allocated*sizeof *str->arr); \ - } while(0) - -/** ops_keydata_key_t - */ -typedef union - { - ops_public_key_t pkey; - ops_secret_key_t skey; - } ops_keydata_key_t; - - -/** sigpacket_t */ -typedef struct - { - ops_user_id_t* userid; - ops_packet_t* packet; - } sigpacket_t; - -// XXX: gonna have to expand this to hold onto subkeys, too... -/** \struct ops_keydata - * \todo expand to hold onto subkeys - */ -struct ops_keydata - { - DECLARE_ARRAY(ops_user_id_t,uids); - DECLARE_ARRAY(ops_packet_t,packets); - DECLARE_ARRAY(sigpacket_t, sigs); - unsigned char key_id[8]; - ops_fingerprint_t fingerprint; - ops_content_tag_t type; - ops_keydata_key_t key; - }; diff --git a/openpgpsdk/src/openpgpsdk/lists.c b/openpgpsdk/src/openpgpsdk/lists.c deleted file mode 100644 index 5be1e2e2c..000000000 --- a/openpgpsdk/src/openpgpsdk/lists.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * \file - * - * Set of functions to manage a dynamic list - */ - -#include - -#include - -#include - -/** - * \ingroup Core_Lists - * \brief Initialises ulong list - * \param *list Pointer to existing list structure - */ -void ops_ulong_list_init(ops_ulong_list_t *list) - { - list->size=0; - list->used=0; - list->ulongs=NULL; - } - -/** - * \ingroup Core_Lists - * \brief Frees allocated memory in ulong list. Does not free *list itself. - * \param *list - */ -void ops_ulong_list_free(ops_ulong_list_t *list) - { - if (list->ulongs) - free(list->ulongs); - ops_ulong_list_init(list); - } - -/** - * \ingroup Core_Lists - * \brief Resizes ulong list. - * - * We only resize in one direction - upwards. - * Algorithm used : double the current size then add 1 - * - * \param *list Pointer to list - * \return 1 if success, else 0 - */ - -static unsigned int ops_ulong_list_resize(ops_ulong_list_t *list) - { - - int newsize=0; - - newsize=list->size*2 + 1; - list->ulongs=realloc(list->ulongs,newsize*sizeof *list->ulongs); - if (list->ulongs) - { - list->size=newsize; - return 1; - } - else - { - /* xxx - realloc failed. error message? - rachel */ - return 0; - } - } - -/** - * \ingroup Core_Lists - * Adds entry to ulong list - * - * \param *list - * \param *ulong - * - * \return 1 if success, else 0 - */ -unsigned int ops_ulong_list_add(ops_ulong_list_t *list, unsigned long *ulong) - { - if (list->size==list->used) - if (!ops_ulong_list_resize(list)) - return 0; - - list->ulongs[list->used]=*ulong; - list->used++; - return 1; - } - diff --git a/openpgpsdk/src/openpgpsdk/lists.h b/openpgpsdk/src/openpgpsdk/lists.h deleted file mode 100644 index 520b1d432..000000000 --- a/openpgpsdk/src/openpgpsdk/lists.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_LISTS_H -#define OPS_LISTS_H - -/** ops_ulong_list_t */ -typedef struct - { - unsigned int size;/* num of array slots allocated */ - unsigned int used; /* num of array slots currently used */ - unsigned long *ulongs; - } ops_ulong_list_t; - -void ops_ulong_list_init(ops_ulong_list_t *list); -void ops_ulong_list_free(ops_ulong_list_t *list); -unsigned int ops_ulong_list_add(ops_ulong_list_t *list, unsigned long *ulong); - -#endif /* OPS_LISTS_H */ diff --git a/openpgpsdk/src/openpgpsdk/literal.h b/openpgpsdk/src/openpgpsdk/literal.h deleted file mode 100644 index 8b1c30e6b..000000000 --- a/openpgpsdk/src/openpgpsdk/literal.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2005-2009 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __OPS_LITERAL_H__ -#define __OPS_LITERAL_H__ - - -ops_boolean_t write_literal_header(ops_create_info_t *info, - void *header_data); - -void ops_writer_push_literal(ops_create_info_t *info); -void ops_writer_push_literal_with_opts(ops_create_info_t *info, - unsigned int buf_size); - -#endif /* __OPS_LITERAL_H__ */ - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/memory.c b/openpgpsdk/src/openpgpsdk/memory.c deleted file mode 100644 index 4093e5657..000000000 --- a/openpgpsdk/src/openpgpsdk/memory.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include - -#include - -struct ops_memory - { - unsigned char *buf; - size_t length; - size_t allocated; - }; - -/** -\ingroup HighLevel_Memory -\brief Memory to initialise -\param mem memory to initialise -\param initial_size Size to initialise to -*/ -void ops_memory_init(ops_memory_t *mem,size_t initial_size) - { - mem->length=0; - if(mem->buf) - { - if(mem->allocated < initial_size) - { - mem->buf=realloc(mem->buf,initial_size); - mem->allocated=initial_size; - } - return; - } - mem->buf=malloc(initial_size); - mem->allocated=initial_size; - } - -/** -\ingroup HighLevel_Memory -\brief Pad memory to required length -\param mem Memory to use -\param length New size -*/ -void ops_memory_pad(ops_memory_t *mem,size_t length) - { - assert(mem->allocated >= mem->length); - if(mem->allocated < mem->length+length) - { - mem->allocated=mem->allocated*2+length; - mem->buf=realloc(mem->buf,mem->allocated); - } - assert(mem->allocated >= mem->length+length); - } - -/** -\ingroup HighLevel_Memory -\brief Add data to memory -\param mem Memory to which to add -\param src Data to add -\param length Length of data to add -*/ -void ops_memory_add(ops_memory_t *mem,const unsigned char *src,size_t length) - { - ops_memory_pad(mem,length); - memcpy(mem->buf+mem->length,src,length); - mem->length+=length; - } - -// XXX: this could be refactored via the writer, but an awful lot of -// hoops to jump through for 2 lines of code! -void ops_memory_place_int(ops_memory_t *mem,unsigned offset,unsigned n, - size_t length) - { - assert(mem->allocated >= offset+length); - - while(length--) - mem->buf[offset++]=n >> (length*8); - } - -/** - * \ingroup HighLevel_Memory - * \brief Retains allocated memory and set length of stored data to zero. - * \param mem Memory to clear - * \sa ops_memory_release() - * \sa ops_memory_free() - */ -void ops_memory_clear(ops_memory_t *mem) - { mem->length=0; } - -/** -\ingroup HighLevel_Memory -\brief Free memory and associated data -\param mem Memory to free -\note This does not free mem itself -\sa ops_memory_clear() -\sa ops_memory_free() -*/ -void ops_memory_release(ops_memory_t *mem) - { - free(mem->buf); - mem->buf=NULL; - mem->length=0; - } - -void ops_memory_make_packet(ops_memory_t *out,ops_content_tag_t tag) - { - size_t extra; - - if(out->length < 192) - extra=1; - else if(out->length < 8384) - extra=2; - else - extra=5; - - ops_memory_pad(out,extra+1); - memmove(out->buf+extra+1,out->buf,out->length); - - out->buf[0]=OPS_PTAG_ALWAYS_SET|OPS_PTAG_NEW_FORMAT|tag; - - if(out->length < 192) - out->buf[1]=out->length; - else if(out->length < 8384) - { - out->buf[1]=((out->length-192) >> 8)+192; - out->buf[2]=out->length-192; - } - else - { - out->buf[1]=0xff; - out->buf[2]=out->length >> 24; - out->buf[3]=out->length >> 16; - out->buf[4]=out->length >> 8; - out->buf[5]=out->length; - } - - out->length+=extra+1; - } - -/** - \ingroup HighLevel_Memory - \brief Create a new zeroed ops_memory_t - \return Pointer to new ops_memory_t - \note Free using ops_memory_free() after use. - \sa ops_memory_free() -*/ - -ops_memory_t *ops_memory_new() - { return ops_mallocz(sizeof(ops_memory_t)); } - -/** - \ingroup HighLevel_Memory - \brief Free memory ptr and associated memory - \param mem Memory to be freed - \sa ops_memory_release() - \sa ops_memory_clear() -*/ - -void ops_memory_free(ops_memory_t *mem) - { - ops_memory_release(mem); - free(mem); - } - -/** - \ingroup HighLevel_Memory - \brief Get length of data stored in ops_memory_t struct - \return Number of bytes in data -*/ -size_t ops_memory_get_length(const ops_memory_t *mem) - { return mem->length; } - -/** - \ingroup HighLevel_Memory - \brief Get data stored in ops_memory_t struct - \return Pointer to data -*/ -void *ops_memory_get_data(ops_memory_t *mem) - { return mem->buf; } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/memory.h b/openpgpsdk/src/openpgpsdk/memory.h deleted file mode 100644 index 3fa098026..000000000 --- a/openpgpsdk/src/openpgpsdk/memory.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include "packet.h" - -#ifndef OPS_MEMORY_H -#define OPS_MEMORY_H - -/** ops_memory_t - */ -typedef struct ops_memory ops_memory_t; - -ops_memory_t *ops_memory_new(void); -void ops_memory_free(ops_memory_t *mem); -void ops_memory_init(ops_memory_t *mem,size_t initial_size); -void ops_memory_pad(ops_memory_t *mem,size_t length); -void ops_memory_add(ops_memory_t *mem,const unsigned char *src,size_t length); -void ops_memory_place_int(ops_memory_t *mem,unsigned offset,unsigned n, - size_t length); -void ops_memory_make_packet(ops_memory_t *out,ops_content_tag_t tag); -void ops_memory_clear(ops_memory_t *mem); -void ops_memory_release(ops_memory_t *mem); - -void ops_writer_set_memory(ops_create_info_t *info,ops_memory_t *mem); - -size_t ops_memory_get_length(const ops_memory_t *mem); -void *ops_memory_get_data(ops_memory_t *mem); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/openssl_crypto.c b/openpgpsdk/src/openpgpsdk/openssl_crypto.c deleted file mode 100644 index 086dad77a..000000000 --- a/openpgpsdk/src/openpgpsdk/openssl_crypto.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "keyring_local.h" -#include - -#include - -static int debug=0; - -void test_secret_key(const ops_secret_key_t *skey) - { - RSA* test=RSA_new(); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - test->n=BN_dup(skey->public_key.key.rsa.n); - test->e=BN_dup(skey->public_key.key.rsa.e); - test->d=BN_dup(skey->key.rsa.d); - - test->p=BN_dup(skey->key.rsa.p); - test->q=BN_dup(skey->key.rsa.q); -#else - RSA_set0_key(test, - BN_dup(skey->public_key.key.rsa.n), - BN_dup(skey->public_key.key.rsa.e), - BN_dup(skey->key.rsa.d)); - - RSA_set0_factors(test, BN_dup(skey->key.rsa.p), BN_dup(skey->key.rsa.q)); -#endif - - assert(RSA_check_key(test)==1); - RSA_free(test); - } - -static void md5_init(ops_hash_t *hash) - { - assert(!hash->data); - hash->data=malloc(sizeof(MD5_CTX)); - MD5_Init(hash->data); - } - -static void md5_add(ops_hash_t *hash,const unsigned char *data,unsigned length) - { - MD5_Update(hash->data,data,length); - } - -static unsigned md5_finish(ops_hash_t *hash,unsigned char *out) - { - MD5_Final(out,hash->data); - free(hash->data); - hash->data=NULL; - return 16; - } - -static ops_hash_t md5={OPS_HASH_MD5,MD5_DIGEST_LENGTH,"MD5",md5_init,md5_add, - md5_finish,NULL}; - -/** - \ingroup Core_Crypto - \brief Initialise to MD5 - \param hash Hash to initialise -*/ -void ops_hash_md5(ops_hash_t *hash) - { - *hash=md5; - } - -static void sha1_init(ops_hash_t *hash) - { - if (debug) - { - fprintf(stderr,"***\n***\nsha1_init\n***\n"); - } - assert(!hash->data); - hash->data=malloc(sizeof(SHA_CTX)); - SHA1_Init(hash->data); - } - -static void sha1_add(ops_hash_t *hash,const unsigned char *data, - unsigned length) - { - if (debug) - { - unsigned int i=0; - fprintf(stderr,"adding %d to hash:\n ", length); - for (i=0; idata,data,length); - } - -static unsigned sha1_finish(ops_hash_t *hash,unsigned char *out) - { - SHA1_Final(out,hash->data); - if (debug) - { - unsigned i=0; - fprintf(stderr,"***\n***\nsha1_finish\n***\n"); - for (i=0; idata); - hash->data=NULL; - return SHA_DIGEST_LENGTH; - } - -static ops_hash_t sha1={OPS_HASH_SHA1,SHA_DIGEST_LENGTH,"SHA1",sha1_init, - sha1_add,sha1_finish,NULL}; - -/** - \ingroup Core_Crypto - \brief Initialise to SHA1 - \param hash Hash to initialise -*/ -void ops_hash_sha1(ops_hash_t *hash) - { - *hash=sha1; - } - -static void sha256_init(ops_hash_t *hash) - { - if (debug) - { - fprintf(stderr,"***\n***\nsha256_init\n***\n"); - } - assert(!hash->data); - hash->data=malloc(sizeof(SHA256_CTX)); - SHA256_Init(hash->data); - } - -static void sha256_add(ops_hash_t *hash,const unsigned char *data, - unsigned length) - { - if (debug) - { - unsigned int i=0; - fprintf(stderr,"adding %d to hash:\n ", length); - for (i=0; idata,data,length); - } - -static unsigned sha256_finish(ops_hash_t *hash,unsigned char *out) - { - SHA256_Final(out,hash->data); - if (debug) - { - unsigned i=0; - fprintf(stderr,"***\n***\nsha1_finish\n***\n"); - for (i=0; idata); - hash->data=NULL; - return SHA256_DIGEST_LENGTH; - } - -static ops_hash_t sha256={OPS_HASH_SHA256,SHA256_DIGEST_LENGTH,"SHA256",sha256_init, - sha256_add,sha256_finish,NULL}; - -void ops_hash_sha256(ops_hash_t *hash) - { - *hash=sha256; - } - -/* - * SHA384 - */ - -static void sha384_init(ops_hash_t *hash) - { - if (debug) - { - fprintf(stderr,"***\n***\nsha384_init\n***\n"); - } - assert(!hash->data); - hash->data=malloc(sizeof(SHA512_CTX)); - SHA384_Init(hash->data); - } - -static void sha384_add(ops_hash_t *hash,const unsigned char *data, - unsigned length) - { - if (debug) - { - unsigned int i=0; - fprintf(stderr,"adding %d to hash:\n ", length); - for (i=0; idata,data,length); - } - -static unsigned sha384_finish(ops_hash_t *hash,unsigned char *out) - { - SHA384_Final(out,hash->data); - if (debug) - { - unsigned i=0; - fprintf(stderr,"***\n***\nsha1_finish\n***\n"); - for (i=0; idata); - hash->data=NULL; - return SHA384_DIGEST_LENGTH; - } - -static ops_hash_t sha384={OPS_HASH_SHA384,SHA384_DIGEST_LENGTH,"SHA384",sha384_init, - sha384_add,sha384_finish,NULL}; - -void ops_hash_sha384(ops_hash_t *hash) - { - *hash=sha384; - } - -/* - * SHA512 - */ - -static void sha512_init(ops_hash_t *hash) - { - if (debug) - { - fprintf(stderr,"***\n***\nsha512_init\n***\n"); - } - assert(!hash->data); - hash->data=malloc(sizeof(SHA512_CTX)); - SHA512_Init(hash->data); - } - -static void sha512_add(ops_hash_t *hash,const unsigned char *data, - unsigned length) - { - if (debug) - { - unsigned int i=0; - fprintf(stderr,"adding %d to hash:\n ", length); - for (i=0; idata,data,length); - } - -static unsigned sha512_finish(ops_hash_t *hash,unsigned char *out) - { - SHA512_Final(out,hash->data); - if (debug) - { - unsigned i=0; - fprintf(stderr,"***\n***\nsha1_finish\n***\n"); - for (i=0; idata); - hash->data=NULL; - return SHA512_DIGEST_LENGTH; - } - -static ops_hash_t sha512={OPS_HASH_SHA512,SHA512_DIGEST_LENGTH,"SHA512",sha512_init, - sha512_add,sha512_finish,NULL}; - -void ops_hash_sha512(ops_hash_t *hash) - { - *hash=sha512; - } - -/* - * SHA224 - */ - -static void sha224_init(ops_hash_t *hash) - { - if (debug) - { - fprintf(stderr,"***\n***\nsha1_init\n***\n"); - } - assert(!hash->data); - hash->data=malloc(sizeof(SHA256_CTX)); - SHA224_Init(hash->data); - } - -static void sha224_add(ops_hash_t *hash,const unsigned char *data, - unsigned length) - { - if (debug) - { - unsigned int i=0; - fprintf(stderr,"adding %d to hash:\n ", length); - for (i=0; idata,data,length); - } - -static unsigned sha224_finish(ops_hash_t *hash,unsigned char *out) - { - SHA224_Final(out,hash->data); - if (debug) - { - unsigned i=0; - fprintf(stderr,"***\n***\nsha1_finish\n***\n"); - for (i=0; idata); - hash->data=NULL; - return SHA224_DIGEST_LENGTH; - } - -static ops_hash_t sha224={OPS_HASH_SHA224,SHA224_DIGEST_LENGTH,"SHA224",sha224_init, - sha224_add,sha224_finish,NULL}; - -void ops_hash_sha224(ops_hash_t *hash) - { - *hash=sha224; - } - -ops_boolean_t already_said = ops_false ; - -ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length, - const ops_dsa_signature_t *sig, - const ops_dsa_public_key_t *dsa) - { - DSA_SIG *osig; - DSA *odsa; - int ret; - - osig=DSA_SIG_new(); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - osig->r=sig->r; - osig->s=sig->s; -#else - DSA_SIG_set0(osig,BN_dup(sig->r),BN_dup(sig->s)) ; -#endif - - if(BN_num_bits(dsa->q) != 160) - { - if(!already_said) - { - fprintf(stderr,"(WW) ops_dsa_verify: openssl does only supports 'q' of 160 bits. Current is %d bits.\n",BN_num_bits(dsa->q)) ; - already_said=ops_true ; - } - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - osig->r=NULL; // in this case, the values are not copied. - osig->s=NULL; -#endif - - DSA_SIG_free(osig); - return ops_false ; - } - - odsa=DSA_new(); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - odsa->p=dsa->p; - odsa->q=dsa->q; - odsa->g=dsa->g; - - odsa->pub_key=dsa->y; -#else - DSA_set0_pqg(odsa,BN_dup(dsa->p),BN_dup(dsa->q),BN_dup(dsa->g)); - DSA_set0_key(odsa,BN_dup(dsa->y),NULL) ; -#endif - - if (debug) - { - fprintf(stderr,"hash passed in:\n"); - unsigned i; - for (i=0; iq)); - unsigned int qlen=BN_num_bytes(dsa->q); - - if (qlen < hash_length) - hash_length=qlen; - // ret=DSA_do_verify(hash,hash_length,osig,odsa); - ret=DSA_do_verify(hash,hash_length,osig,odsa); - if (debug) - { - fprintf(stderr,"ret=%d\n",ret); - } - - if(ret < 0) - { - ERR_load_crypto_strings() ; - unsigned long err = 0 ; - while((err = ERR_get_error()) > 0) - fprintf(stderr,"DSA_do_verify(): ERR = %ld. lib error:\"%s\", func_error:\"%s\", reason:\"%s\"\n",err,ERR_lib_error_string(err),ERR_func_error_string(err),ERR_reason_error_string(err)) ; - //assert(ret >= 0); - return ops_false ; - } - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - osig->r=NULL; - osig->s=NULL; - - odsa->p=NULL; - odsa->q=NULL; - odsa->g=NULL; - odsa->pub_key=NULL; -#endif - - DSA_free(odsa); - DSA_SIG_free(osig); - - return ret != 0; - } - -/** - \ingroup Core_Crypto - \brief Recovers message digest from the signature - \param out Where to write decrypted data to - \param in Encrypted data - \param length Length of encrypted data - \param rsa RSA public key - \return size of recovered message digest -*/ -int ops_rsa_public_decrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_public_key_t *rsa) - { - RSA *orsa; - int n; - - orsa=RSA_new(); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=rsa->n; - orsa->e=rsa->e; -#else - RSA_set0_key(orsa,BN_dup(rsa->n),BN_dup(rsa->e),NULL) ; -#endif - - n=RSA_public_decrypt(length,in,out,orsa,RSA_NO_PADDING); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=orsa->e=NULL; -#endif - RSA_free(orsa); - - return n; - } - -/** - \ingroup Core_Crypto - \brief Signs data with RSA - \param out Where to write signature - \param in Data to sign - \param length Length of data - \param srsa RSA secret key - \param rsa RSA public key - \return number of bytes decrypted -*/ -int ops_rsa_private_encrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_secret_key_t *srsa, - const ops_rsa_public_key_t *rsa) - { - RSA *orsa; - int n; - - orsa=RSA_new(); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=rsa->n; // XXX: do we need n? - orsa->d=srsa->d; - orsa->p=srsa->q; - orsa->q=srsa->p; - - /* debug */ - orsa->e=rsa->e; - - // If this isn't set, it's very likely that the programmer hasn't - // decrypted the secret key. RSA_check_key segfaults in that case. - // Use ops_decrypt_secret_key_from_data() to do that. - assert(orsa->d); -#else - RSA_set0_key(orsa,BN_dup(rsa->n),BN_dup(rsa->e),BN_dup(srsa->d)) ; - RSA_set0_factors(orsa,BN_dup(srsa->p),BN_dup(srsa->q)); -#endif - - assert(RSA_check_key(orsa) == 1); - /* end debug */ - - // WARNING: this function should *never* be called for direct encryption, because of the padding. - // It's actually only called in the signature function now, where an adapted padding is placed. - - n=RSA_private_encrypt(length,in,out,orsa,RSA_NO_PADDING); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=orsa->d=orsa->p=orsa->q=NULL; - orsa->e=NULL; -#endif - RSA_free(orsa); - - return n; - } - -/** -\ingroup Core_Crypto -\brief Decrypts RSA-encrypted data -\param out Where to write the plaintext -\param in Encrypted data -\param length Length of encrypted data -\param srsa RSA secret key -\param rsa RSA public key -\return size of recovered plaintext -*/ -int ops_rsa_private_decrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_secret_key_t *srsa, - const ops_rsa_public_key_t *rsa) - { - RSA *orsa; - int n; - char errbuf[1024]; - - orsa=RSA_new(); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=rsa->n; // XXX: do we need n? - orsa->d=srsa->d; - orsa->p=srsa->q; - orsa->q=srsa->p; - orsa->e=rsa->e; -#else - RSA_set0_key(orsa,BN_dup(rsa->n),BN_dup(rsa->e),BN_dup(srsa->d)) ; - RSA_set0_factors(orsa,BN_dup(srsa->p),BN_dup(srsa->q)); -#endif - - /* debug */ - assert(RSA_check_key(orsa) == 1); - /* end debug */ - - n=RSA_private_decrypt(length,in,out,orsa,RSA_NO_PADDING); - - // printf("ops_rsa_private_decrypt: n=%d\n",n); - - errbuf[0]='\0'; - if (n==-1) - { - unsigned long err=ERR_get_error(); - ERR_error_string(err,&errbuf[0]); - fprintf(stderr,"openssl error : %s\n",errbuf); - } -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=orsa->d=orsa->p=orsa->q=NULL; - orsa->e=NULL; -#endif - RSA_free(orsa); - - return n; - } - -/** - \ingroup Core_Crypto - \brief RSA-encrypts data - \param out Where to write the encrypted data - \param in Plaintext - \param length Size of plaintext - \param rsa RSA Public Key -*/ -int ops_rsa_public_encrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_public_key_t *rsa) - { - RSA *orsa; - int n; - - // printf("ops_rsa_public_encrypt: length=%ld\n", length); - - orsa=RSA_new(); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=rsa->n; - orsa->e=rsa->e; -#else - RSA_set0_key(orsa,BN_dup(rsa->n),BN_dup(rsa->e),NULL); -#endif - - // printf("len: %ld\n", length); - // ops_print_bn("n: ", orsa->n); - // ops_print_bn("e: ", orsa->e); - n=RSA_public_encrypt(length,in,out,orsa,RSA_NO_PADDING); - - if (n==-1) - { - BIO *fd_out; - fd_out=BIO_new_fd(fileno(stderr), BIO_NOCLOSE); - ERR_print_errors(fd_out); - BIO_free(fd_out) ; - } - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=orsa->e=NULL; -#endif - RSA_free(orsa); - - return n; - } - -/** - \ingroup Core_Crypto - \brief initialises openssl - \note Would usually call ops_init() instead - \sa ops_init() -*/ -void ops_crypto_init() - { -#ifdef DMALLOC - CRYPTO_malloc_debug_init(); - CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL); - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); -#endif - } - -/** - \ingroup Core_Crypto - \brief Finalise openssl - \note Would usually call ops_finish() instead - \sa ops_finish() -*/ -void ops_crypto_finish() - { - CRYPTO_cleanup_all_ex_data(); - // FIXME: what should we do instead (function is deprecated)? - // ERR_remove_state(0); -#ifdef DMALLOC - CRYPTO_mem_leaks_fp(stderr); -#endif - } - -/** - \ingroup Core_Hashes - \brief Get Hash name - \param hash Hash struct - \return Hash name -*/ -const char *ops_text_from_hash(ops_hash_t *hash) - { return hash->name; } - -/** - \ingroup HighLevel_KeyGenerate - \brief Generates an RSA keypair - \param numbits Modulus size - \param e Public Exponent - \param keydata Pointer to keydata struct to hold new key - \return ops_true if key generated successfully; otherwise ops_false - \note It is the caller's responsibility to call ops_keydata_free(keydata) -*/ -ops_boolean_t ops_rsa_generate_keypair(const int numbits, const unsigned long e, - ops_keydata_t* keydata) - { - ops_secret_key_t *skey=NULL; - RSA *rsa=RSA_new(); - BN_CTX *ctx=BN_CTX_new(); - BIGNUM *ebn=BN_new(); - - ops_keydata_init(keydata,OPS_PTAG_CT_SECRET_KEY); - skey=ops_get_writable_secret_key_from_data(keydata); - - // generate the key pair - - BN_set_word(ebn,e); - RSA_generate_key_ex(rsa,numbits,ebn,NULL); - - // populate ops key from ssl key - - skey->public_key.version=4; - skey->public_key.creation_time=time(NULL); - skey->public_key.days_valid=0; - skey->public_key.algorithm= OPS_PKA_RSA; - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - skey->public_key.key.rsa.n=BN_dup(rsa->n); - skey->public_key.key.rsa.e=BN_dup(rsa->e); - skey->key.rsa.d=BN_dup(rsa->d); -#else - const BIGNUM *nn=NULL,*ee=NULL,*dd=NULL ; - - RSA_get0_key(rsa,&nn,&ee,&dd) ; - - skey->public_key.key.rsa.n=BN_dup(nn) ; - skey->public_key.key.rsa.e=BN_dup(ee) ; - skey->key.rsa.d=BN_dup(dd) ; -#endif - - skey->s2k_usage=OPS_S2KU_ENCRYPTED_AND_HASHED; - skey->s2k_specifier=OPS_S2KS_SALTED; - //skey->s2k_specifier=OPS_S2KS_SIMPLE; - skey->algorithm=OPS_SA_CAST5; // \todo make param - skey->hash_algorithm=OPS_HASH_SHA1; // \todo make param - skey->octet_count=0; - skey->checksum=0; - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - skey->key.rsa.p=BN_dup(rsa->p); - skey->key.rsa.q=BN_dup(rsa->q); - skey->key.rsa.u=BN_mod_inverse(NULL,rsa->p, rsa->q, ctx); -#else - const BIGNUM *pp=NULL,*qq=NULL ; - - RSA_get0_factors(rsa,&pp,&qq) ; - - skey->key.rsa.p=BN_dup(pp); - skey->key.rsa.q=BN_dup(qq); - - skey->key.rsa.u=BN_mod_inverse(NULL,pp,qq, ctx); -#endif - assert(skey->key.rsa.u); - BN_CTX_free(ctx); - - RSA_free(rsa); - - ops_keyid(keydata->key_id, &keydata->key.skey.public_key); - ops_fingerprint(&keydata->fingerprint, &keydata->key.skey.public_key); - - // Generate checksum - - ops_create_info_t *cinfo=NULL; - ops_memory_t *mem=NULL; - - ops_setup_memory_write(&cinfo, &mem, 128); - - ops_push_skey_checksum_writer(cinfo, skey); - - switch(skey->public_key.algorithm) - { - // case OPS_PKA_DSA: - // return ops_write_mpi(key->key.dsa.x,info); - - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - if(!ops_write_mpi(skey->key.rsa.d,cinfo) - || !ops_write_mpi(skey->key.rsa.p,cinfo) - || !ops_write_mpi(skey->key.rsa.q,cinfo) - || !ops_write_mpi(skey->key.rsa.u,cinfo)) - return ops_false; - break; - - // case OPS_PKA_ELGAMAL: - // return ops_write_mpi(key->key.elgamal.x,info); - - default: - assert(0); - break; - } - - // close rather than pop, since its the only one on the stack - ops_writer_close(cinfo); - ops_teardown_memory_write(cinfo, mem); - - // should now have checksum in skey struct - - // test - if (debug) - test_secret_key(skey); - - return ops_true; - } - -/** - \ingroup HighLevel_KeyGenerate - \brief Creates a self-signed RSA keypair - \param numbits Modulus size - \param e Public Exponent - \param userid User ID - \return The new keypair or NULL - - \note It is the caller's responsibility to call ops_keydata_free(keydata) - \sa ops_rsa_generate_keypair() - \sa ops_keydata_free() -*/ -ops_keydata_t* ops_rsa_create_selfsigned_keypair(const int numbits, const unsigned long e, ops_user_id_t * userid) - { - ops_keydata_t *keydata=NULL; - - keydata=ops_keydata_new(); - - if (ops_rsa_generate_keypair(numbits, e, keydata) != ops_true - || ops_add_selfsigned_userid_to_keydata(keydata, userid) != ops_true) - { - ops_keydata_free(keydata); - return NULL; - } - - return keydata; - } - -/* -int ops_dsa_size(const ops_dsa_public_key_t *dsa) - { - int size; - DSA *odsa; - odsa=DSA_new(); - odsa->p=dsa->p; - odsa->q=dsa->q; - odsa->g=dsa->g; - odsa->pub_key=dsa->y; - - DSAparams_print_fp(stderr, odsa); - size=DSA_size(odsa); - - odsa->p=odsa->q=odsa->g=odsa->pub_key=odsa->priv_key=NULL; - DSA_free(odsa); - - return size; - } -*/ - -DSA_SIG* ops_dsa_sign(unsigned char* hashbuf, unsigned hashsize, const ops_dsa_secret_key_t *sdsa, const ops_dsa_public_key_t *dsa) - { - DSA *odsa; - DSA_SIG *dsasig; - - odsa=DSA_new(); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - odsa->p=dsa->p; - odsa->q=dsa->q; - odsa->g=dsa->g; - odsa->pub_key=dsa->y; - odsa->priv_key=sdsa->x; -#else - DSA_set0_pqg(odsa,BN_dup(dsa->p),BN_dup(dsa->q),BN_dup(dsa->g)); - DSA_set0_key(odsa,BN_dup(dsa->y),BN_dup(sdsa->x)); -#endif - - dsasig=DSA_do_sign(hashbuf,hashsize,odsa); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - odsa->p=odsa->q=odsa->g=odsa->pub_key=odsa->priv_key=NULL; -#endif - DSA_free(odsa); - - return dsasig; - } - -// eof diff --git a/openpgpsdk/src/openpgpsdk/opsdir.c b/openpgpsdk/src/openpgpsdk/opsdir.c deleted file mode 100644 index b966f090f..000000000 --- a/openpgpsdk/src/openpgpsdk/opsdir.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "opsdir.h" -#ifdef WIN32 -#include "opsstring.h" -#endif -#include - -int ops_open(const char* filename, int flag, int pmode) -{ -#ifdef WIN32 - wchar_t *wfilename = ConvertUtf8ToUtf16(filename); - if (!wfilename) - { - return -1; - } - - int result = _wopen(wfilename, flag, pmode); - free(wfilename); - - return result; -#else - return open(filename, flag, pmode); -#endif -} diff --git a/openpgpsdk/src/openpgpsdk/opsdir.h b/openpgpsdk/src/openpgpsdk/opsdir.h deleted file mode 100644 index 78f7ad8e8..000000000 --- a/openpgpsdk/src/openpgpsdk/opsdir.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef OPUTIL_H -#define OPUTIL_H - -int ops_open(const char* filename, int flag, int pmode); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/opsstring.c b/openpgpsdk/src/openpgpsdk/opsstring.c deleted file mode 100644 index 6a0e2b072..000000000 --- a/openpgpsdk/src/openpgpsdk/opsstring.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "opsstring.h" - -#ifdef WIN32 -wchar_t *ConvertUtf8ToUtf16(const char* source) -{ - if (!source) { - return NULL; - } - -#ifdef WIN32 - int nbChars = MultiByteToWideChar(CP_UTF8, 0, source, -1, 0, 0); - if (nbChars == 0) { - return NULL; - } - - wchar_t* utf16Name = (wchar_t*) malloc(nbChars * sizeof(wchar_t)); - if (MultiByteToWideChar(CP_UTF8, 0, source, -1, utf16Name, nbChars) == 0) { - free(utf16Name); - return NULL; - } - - return utf16Name; -#else - // currently only for WIN32 - // convert code from rsstring.cc - return NULL; -#endif -} - -char* ConvertUtf16ToUtf8(const wchar_t *source) -{ - if (!source) { - return NULL; - } - -#ifdef WIN32 - int nbChars = WideCharToMultiByte(CP_UTF8, 0, source, -1, 0, 0, 0, 0); - if (nbChars == 0) { - return NULL; - } - - char* utf8Name = (char*) malloc(nbChars * sizeof(char)); - if (WideCharToMultiByte(CP_UTF8, 0, source, -1, utf8Name, nbChars, 0, 0) == 0) { - free(utf8Name); - return NULL; - } - - return utf8Name; -#else - // currently only for WIN32 - // convert code from rsstring.cc - return NULL; -#endif -} -#endif diff --git a/openpgpsdk/src/openpgpsdk/opsstring.h b/openpgpsdk/src/openpgpsdk/opsstring.h deleted file mode 100644 index 3bbaed494..000000000 --- a/openpgpsdk/src/openpgpsdk/opsstring.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef OPSSTRING_H -#define OPSSTRING_H - -#ifdef WIN32 -#include -#endif - -#ifdef WIN32 -// currently only for WIN32 - -// Convert strings between UTF8 and UTF16 -// Don't forget to free the returned string. -wchar_t* ConvertUtf8ToUtf16(const char *source); -char* ConvertUtf16ToUtf8(const wchar_t* source); -#endif - -#endif // OPSSTRING_H diff --git a/openpgpsdk/src/openpgpsdk/packet-parse.c b/openpgpsdk/src/openpgpsdk/packet-parse.c deleted file mode 100644 index e641eae41..000000000 --- a/openpgpsdk/src/openpgpsdk/packet-parse.c +++ /dev/null @@ -1,3477 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * \brief Parser for OpenPGP packets - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "parse_local.h" - -#include -#include -#include -#ifndef WIN32 -#include -#endif -#include -#include - -#include - -static int debug=0; -static const size_t MAX_RECURSIVE_COMPRESSION_DEPTH = 32 ; - -/** - * limited_read_data reads the specified amount of the subregion's data - * into a data_t structure - * - * \param data Empty structure which will be filled with data - * \param len Number of octets to read - * \param subregion - * \param pinfo How to parse - * - * \return 1 on success, 0 on failure - */ -static int limited_read_data(ops_data_t *data,unsigned int len, - ops_region_t *subregion,ops_parse_info_t *pinfo) -{ - data->len = len; - - if(!(subregion->length-subregion->length_read >= len)) // ASSERT(subregion->length-subregion->length_read >= len); - { - fprintf(stderr,"Data length error: announced size %d larger than expected size %d. Giving up.",len,subregion->length-subregion->length_read) ; - return 0 ; - } - - data->contents=malloc(data->len); - if (!data->contents) - return 0; - - if (!ops_limited_read(data->contents, data->len,subregion,&pinfo->errors, - &pinfo->rinfo,&pinfo->cbinfo)) - return 0; - - return 1; -} - -/** - * read_data reads the remainder of the subregion's data - * into a data_t structure - * - * \param data - * \param subregion - * \param pinfo - * - * \return 1 on success, 0 on failure - */ -static int read_data(ops_data_t *data,ops_region_t *subregion, - ops_parse_info_t *pinfo) - { - int len; - - len=subregion->length-subregion->length_read; - - if ( len >= 0 ) { - return(limited_read_data(data,len,subregion,pinfo)); - } - return 0; - } - -/** - * Reads the remainder of the subregion as a string. - * It is the user's responsibility to free the memory allocated here. - */ - -static int read_unsigned_string(unsigned char **str,ops_region_t *subregion, - ops_parse_info_t *pinfo) - { - int len=0; - - len=subregion->length-subregion->length_read; - - *str=malloc(len+1); - if(!(*str)) - return 0; - - if(len && !ops_limited_read(*str,len,subregion,&pinfo->errors, - &pinfo->rinfo,&pinfo->cbinfo)) - return 0; - - /*! ensure the string is NULL-terminated */ - - (*str)[len]='\0'; - - return 1; - } - -static int read_string(char **str, ops_region_t *subregion, ops_parse_info_t *pinfo) - { - return (read_unsigned_string((unsigned char **)str, subregion, pinfo)); - } - -void ops_init_subregion(ops_region_t *subregion,ops_region_t *region) - { - memset(subregion,'\0',sizeof *subregion); - subregion->parent=region; - } - -/*! macro to save typing */ -#define C content.content - -/* XXX: replace ops_ptag_t with something more appropriate for limiting - reads */ - -/** - * low-level function to read data from reader function - * - * Use this function, rather than calling the reader directly. - * - * If the accumulate flag is set in *pinfo, the function - * adds the read data to the accumulated data, and updates - * the accumulated length. This is useful if, for example, - * the application wants access to the raw data as well as the - * parsed data. - * - * This function will also try to read the entire amount asked for, but not - * if it is over INT_MAX. Obviously many callers will know that they - * never ask for that much and so can avoid the extra complexity of - * dealing with return codes and filled-in lengths. - * - * \param *dest - * \param *plength - * \param flags - * \param *pinfo - * - * \return OPS_R_OK - * \return OPS_R_PARTIAL_READ - * \return OPS_R_EOF - * \return OPS_R_EARLY_EOF - * - * \sa #ops_reader_ret_t for details of return codes - */ - -static int sub_base_read(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) -{ - size_t n; - - /* reading more than this would look like an error */ - if(length > INT_MAX) - length=INT_MAX; - - for(n=0 ; n < length ; ) - { - int r=rinfo->reader((char*)dest+n,length-n,errors,rinfo,cbinfo); - - if(!(r <= (int)(length-n))) // ASSERT(r <= (int)(length-n)) - { - fprintf(stderr,"sub_base_read: error in length. Read %d, remaining length is %d",r,(int)(length-n)) ; - return -1 ; - } - - // XXX: should we save the error and return what was read so far? - // - if(r < 0) - return r; - - if(r == 0) - break; - - n+=r; - } - - if(n == 0) - return 0; - - if(rinfo->accumulate) - { - if(!(rinfo->asize >= rinfo->alength)) // ASSERT(rinfo->asize >= rinfo->alength) - { - fprintf(stderr,"sub_base_read: error in accumulated length.") ; - return -1 ; - } - - if(rinfo->alength+n > rinfo->asize) - { - rinfo->asize=rinfo->asize*2+n; - rinfo->accumulated=realloc(rinfo->accumulated,rinfo->asize); - } - if(!(rinfo->asize >= rinfo->alength+n)) // ASSERT(rinfo->asize >= rinfo->alength+n) - { - fprintf(stderr,"sub_base_read: error in accumulated length.") ; - return -1 ; - } - - memcpy(rinfo->accumulated+rinfo->alength,dest,n); - } - // we track length anyway, because it is used for packet offsets - rinfo->alength+=n; - // and also the position - rinfo->position+=n; - - return n; -} - -int ops_stacked_read(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) - { return sub_base_read(dest,length,errors,rinfo->next,cbinfo); } - -/* This will do a full read so long as length < MAX_INT */ -static int base_read(unsigned char *dest,size_t length, - ops_parse_info_t *pinfo) - { - return sub_base_read(dest,length,&pinfo->errors,&pinfo->rinfo, - &pinfo->cbinfo); - } - -/* Read a full size_t's worth. If the return is < than length, then - * *last_read tells you why - < 0 for an error, == 0 for EOF */ - -static size_t full_read(unsigned char *dest,size_t length,int *last_read, - ops_error_t **errors,ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) - { - size_t t; - int r=0; /* preset in case some loon calls with length == 0 */ - - for(t=0 ; t < length ; ) - { - r=sub_base_read(dest+t,length-t,errors,rinfo,cbinfo); - - if(r <= 0) - { - *last_read=r; - return t; - } - - t+=r; - } - - *last_read=r; - - return t; - } - - - -/** Read a scalar value of selected length from reader. - * - * Read an unsigned scalar value from reader in Big Endian representation. - * - * This function does not know or care about packet boundaries. It - * also assumes that an EOF is an error. - * - * \param *result The scalar value is stored here - * \param *reader Our reader - * \param length How many bytes to read - * \return ops_true on success, ops_false on failure - */ -static ops_boolean_t _read_scalar(unsigned *result,unsigned length, - ops_parse_info_t *pinfo) - { - unsigned t=0; - - if(! (length <= sizeof(*result))) // ASSERT(length <= sizeof(*result)) - { - fprintf(stderr,"_read_scalar: length to read is larger than buffer size.") ; - return ops_false ; - } - - while(length--) - { - unsigned char c[1]; - int r; - - r=base_read(c,1,pinfo); - if(r != 1) - return ops_false; - t=(t << 8)+c[0]; - } - - *result=t; - return ops_true; - } - -/** - * \ingroup Core_ReadPackets - * \brief Read bytes from a region within the packet. - * - * Read length bytes into the buffer pointed to by *dest. - * Make sure we do not read over the packet boundary. - * Updates the Packet Tag's ops_ptag_t::length_read. - * - * If length would make us read over the packet boundary, or if - * reading fails, we call the callback with an error. - * - * Note that if the region is indeterminate, this can return a short - * read - check region->last_read for the length. EOF is indicated by - * a success return and region->last_read == 0 in this case (for a - * region of known length, EOF is an error). - * - * This function makes sure to respect packet boundaries. - * - * \param dest The destination buffer - * \param length How many bytes to read - * \param region Pointer to packet region - * \param errors Error stack - * \param rinfo Reader info - * \param cbinfo Callback info - * \return ops_true on success, ops_false on error - */ -ops_boolean_t ops_limited_read(unsigned char *dest,size_t length, - ops_region_t *region,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - size_t r; - int lr; - - if(!region->indeterminate && region->length_read+length > region->length) - { - OPS_ERROR(errors,OPS_E_P_NOT_ENOUGH_DATA,"Not enough data"); - return ops_false; - } - - r=full_read(dest,length,&lr,errors,rinfo,cbinfo); - - if(lr < 0) - { - OPS_ERROR(errors,OPS_E_R_READ_FAILED,"Read failed"); - return ops_false; - } - - if(!region->indeterminate && r != length) - { - OPS_ERROR(errors,OPS_E_R_READ_FAILED,"Read failed"); - return ops_false; - } - - region->last_read=r; - do - { - region->length_read+=r; - - if(!(!region->parent || region->length <= region->parent->length)) // ASSERT(!region->parent || region->length <= region->parent->length) - { - OPS_ERROR(errors,OPS_E_R_READ_FAILED,"Read failed"); - return ops_false; - } - } - while((region=region->parent)); - - return ops_true; -} - -/** - \ingroup Core_ReadPackets - \brief Call ops_limited_read on next in stack -*/ -ops_boolean_t ops_stacked_limited_read(void *dest, unsigned length, - ops_region_t *region, - ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) - { - return ops_limited_read(dest, length, region, errors, rinfo->next, cbinfo); - } - -static ops_boolean_t limited_read(unsigned char *dest,unsigned length, - ops_region_t *region,ops_parse_info_t *info) - { - return ops_limited_read(dest,length,region,&info->errors, - &info->rinfo,&info->cbinfo); - } - -static ops_boolean_t exact_limited_read(unsigned char *dest,unsigned length, - ops_region_t *region, - ops_parse_info_t *pinfo) - { - ops_boolean_t ret; - - pinfo->exact_read=ops_true; - ret=limited_read(dest,length,region,pinfo); - pinfo->exact_read=ops_false; - - return ret; - } - -/** Skip over length bytes of this packet. - * - * Calls limited_read() to skip over some data. - * - * This function makes sure to respect packet boundaries. - * - * \param length How many bytes to skip - * \param *region Pointer to packet region - * \param *pinfo How to parse - * \return 1 on success, 0 on error (calls the cb with OPS_PARSER_ERROR in limited_read()). - */ -static int limited_skip(unsigned length,ops_region_t *region, - ops_parse_info_t *pinfo) - { - unsigned char buf[8192]; - - while(length) - { - int n=length%8192; - if(!limited_read(buf,n,region,pinfo)) - return 0; - length-=n; - } - return 1; - } - -/** Read a scalar. - * - * Read a big-endian scalar of length bytes, respecting packet - * boundaries (by calling limited_read() to read the raw data). - * - * This function makes sure to respect packet boundaries. - * - * \param *dest The scalar value is stored here - * \param length How many bytes make up this scalar (at most 4) - * \param *region Pointer to current packet region - * \param *pinfo How to parse - * \param *cb The callback - * \return 1 on success, 0 on error (calls the cb with OPS_PARSER_ERROR in limited_read()). - * - * \see RFC4880 3.1 - */ -static int limited_read_scalar(unsigned *dest,unsigned length, - ops_region_t *region, - ops_parse_info_t *pinfo) -{ - unsigned char c[4]=""; - unsigned t; - unsigned n; - - if(!(length <= 4)) // ASSERT(length <= 4) - { - fprintf(stderr,"limited_read_scalar: wrong size for scalar %d\n",length) ; - return ops_false ; - } - if(!(sizeof(*dest) >= 4)) // ASSERT(sizeof(*dest) >= 4) - { - fprintf(stderr,"limited_read_scalar: wrong size for dest %lu\n",sizeof(*dest)) ; - return ops_false ; - } - if(!limited_read(c,length,region,pinfo)) - return 0; - - for(t=0,n=0 ; n < length ; ++n) - t=(t << 8)+c[n]; - *dest=t; - - return 1; -} - -/** Read a scalar. - * - * Read a big-endian scalar of length bytes, respecting packet - * boundaries (by calling limited_read() to read the raw data). - * - * The value read is stored in a size_t, which is a different size - * from an unsigned on some platforms. - * - * This function makes sure to respect packet boundaries. - * - * \param *dest The scalar value is stored here - * \param length How many bytes make up this scalar (at most 4) - * \param *region Pointer to current packet region - * \param *pinfo How to parse - * \param *cb The callback - * \return 1 on success, 0 on error (calls the cb with OPS_PARSER_ERROR in limited_read()). - * - * \see RFC4880 3.1 - */ -static int limited_read_size_t_scalar(size_t *dest,unsigned length, - ops_region_t *region, - ops_parse_info_t *pinfo) -{ - unsigned tmp; - - if(!(sizeof(*dest) >= 4)) // ASSERT(sizeof(*dest) >= 4) - { - fprintf(stderr,"limited_read_scalar: wrong dest size for scalar %lu\n",sizeof(*dest)) ; - return ops_false ; - } - - /* Note that because the scalar is at most 4 bytes, we don't care - if size_t is bigger than usigned */ - if(!limited_read_scalar(&tmp,length,region,pinfo)) - return 0; - - *dest=tmp; - return 1; -} - -/** Read a timestamp. - * - * Timestamps in OpenPGP are unix time, i.e. seconds since The Epoch (1.1.1970). They are stored in an unsigned scalar - * of 4 bytes. - * - * This function reads the timestamp using limited_read_scalar(). - * - * This function makes sure to respect packet boundaries. - * - * \param *dest The timestamp is stored here - * \param *ptag Pointer to current packet's Packet Tag. - * \param *reader Our reader - * \param *cb The callback - * \return see limited_read_scalar() - * - * \see RFC4880 3.5 - */ -static int limited_read_time(time_t *dest,ops_region_t *region, - ops_parse_info_t *pinfo) -{ - /* - * Cannot assume that time_t is 4 octets long - - * there is at least one architecture (SunOS 5.10) where it is 8. - */ - if (sizeof(*dest)==4) - { - return limited_read_scalar((unsigned *)dest,4,region,pinfo); - } - else - { - time_t mytime=0; - int i=0; - unsigned char c[1]; - for (i=0; i<4; i++) - { - if (!limited_read(c,1,region,pinfo)) - return 0; - mytime=(mytime << 8) + c[0]; - } - *dest=mytime; - return 1; - } -} - -/** - * \ingroup Core_MPI - * Read a multiprecision integer. - * - * Large numbers (multiprecision integers, MPI) are stored in OpenPGP in two parts. First there is a 2 byte scalar - * indicating the length of the following MPI in Bits. Then follow the bits that make up the actual number, most - * significant bits first (Big Endian). The most significant bit in the MPI is supposed to be 1 (unless the MPI is - * encrypted - then it may be different as the bit count refers to the plain text but the bits are encrypted). - * - * Unused bits (i.e. those filling up the most significant byte from the left to the first bits that counts) are - * supposed to be cleared - I guess. XXX - does anything actually say so? - * - * This function makes sure to respect packet boundaries. - * - * \param **pgn return the integer there - the BIGNUM is created by BN_bin2bn() and probably needs to be freed - * by the caller XXX right ben? - * \param *ptag Pointer to current packet's Packet Tag. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error (by limited_read_scalar() or limited_read() or if the MPI is not properly formed (XXX - * see comment below - the callback is called with a OPS_PARSER_ERROR in case of an error) - * - * \see RFC4880 3.2 - */ -static int limited_read_mpi(BIGNUM **pbn,ops_region_t *region, - ops_parse_info_t *pinfo) - { - unsigned length; - unsigned nonzero; - unsigned char buf[8192]=""; /* an MPI has a 2 byte length part. Length - is given in bits, so the largest we should - ever need for the buffer is 8192 bytes. */ - ops_boolean_t ret; - - pinfo->reading_mpi_length=ops_true; - ret=limited_read_scalar(&length,2,region,pinfo); - - pinfo->reading_mpi_length=ops_false; - if(!ret) - return 0; - - nonzero=length&7; /* there should be this many zero bits in the MS byte */ - if(!nonzero) - nonzero=8; - length=(length+7)/8; - - if(!(length <= 8192)) // ASSERT(length <= 8192) - { - fprintf(stderr,"limited_read_mpi: wrong size to read %d > 8192",length) ; - return 0 ; - } - - if(!limited_read(buf,length,region,pinfo)) - return 0; - - if((buf[0] >> nonzero) != 0 || !(buf[0]&(1 << (nonzero-1)))) - { - OPS_ERROR(&pinfo->errors,OPS_E_P_MPI_FORMAT_ERROR,"MPI Format error"); /* XXX: Ben, one part of this constraint does not apply to encrypted MPIs the draft says. -- peter */ - return 0; - } - - *pbn=BN_bin2bn(buf,length,NULL); - return 1; - } - -/** Read some data with a New-Format length from reader. - * - * \sa Internet-Draft RFC4880.txt Section 4.2.2 - * - * \param *length Where the decoded length will be put - * \param *pinfo How to parse - * \return ops_true if OK, else ops_false - * - */ - -static ops_boolean_t read_new_length(unsigned *length,ops_parse_info_t *pinfo) - { - unsigned char c[1]; - - if(base_read(c,1,pinfo) != 1) - return ops_false; - if(c[0] < 192) - { - // 1. One-octet packet - *length=c[0]; - return ops_true; - } - - else if (c[0]>=192 && c[0]<=223) - { - // 2. Two-octet packet - unsigned t=(c[0]-192) << 8; - - if(base_read(c,1,pinfo) != 1) - return ops_false; - *length=t+c[0]+192; - return ops_true; - } - - else if (c[0]==255) - { - // 3. Five-Octet packet - return _read_scalar(length,4,pinfo); - } - - else if (c[0]>=224 && c[0]<255) - { - // 4. Partial Body Length - OPS_ERROR(&pinfo->errors,OPS_E_UNIMPLEMENTED, - "New format Partial Body Length fields not yet implemented"); - return ops_false; - } - return ops_false; - } - -/** Read the length information for a new format Packet Tag. - * - * New style Packet Tags encode the length in one to five octets. This function reads the right amount of bytes and - * decodes it to the proper length information. - * - * This function makes sure to respect packet boundaries. - * - * \param *length return the length here - * \param *ptag Pointer to current packet's Packet Tag. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error (by limited_read_scalar() or limited_read() or if the MPI is not properly formed (XXX - * see comment below) - * - * \see RFC4880 4.2.2 - * \see ops_ptag_t - */ -static int limited_read_new_length(unsigned *length,ops_region_t *region, - ops_parse_info_t *pinfo) - { - unsigned char c[1]=""; - - if(!limited_read(c,1,region,pinfo)) - return 0; - if(c[0] < 192) - { - *length=c[0]; - return 1; - } - if(c[0] < 255) - { - unsigned t=(c[0]-192) << 8; - - if(!limited_read(c,1,region,pinfo)) - return 0; - *length=t+c[0]+192; - return 1; - } - return limited_read_scalar(length,4,region,pinfo); - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -static void data_free(ops_data_t *data) - { - free(data->contents); - data->contents=NULL; - data->len=0; - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -static void string_free(char **str) - { - free(*str); - *str=NULL; - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free packet memory, set pointer to NULL */ -void ops_packet_free(ops_packet_t *packet) - { - free(packet->raw); - packet->raw=NULL; - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -void ops_headers_free(ops_headers_t *headers) - { - unsigned n; - - for(n=0 ; n < headers->nheaders ; ++n) - { - free(headers->headers[n].key); - free(headers->headers[n].value); - } - free(headers->headers); - headers->headers=NULL; - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -void ops_signed_cleartext_trailer_free(ops_signed_cleartext_trailer_t *trailer) - { - free(trailer->hash); - trailer->hash=NULL; - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -void ops_cmd_get_passphrase_free(ops_secret_key_passphrase_t *skp) - { - if (skp->passphrase && *skp->passphrase) - { - free(*skp->passphrase); - *skp->passphrase=NULL; - } - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free any memory allocated when parsing the packet content */ -void ops_parser_content_free(ops_parser_content_t *c) -{ - switch(c->tag) - { - case OPS_PARSER_PTAG: - case OPS_PTAG_CT_COMPRESSED: - case OPS_PTAG_SS_CREATION_TIME: - case OPS_PTAG_SS_EXPIRATION_TIME: - case OPS_PTAG_SS_KEY_EXPIRATION_TIME: - case OPS_PTAG_SS_TRUST: - case OPS_PTAG_SS_ISSUER_KEY_ID: - case OPS_PTAG_CT_ONE_PASS_SIGNATURE: - case OPS_PTAG_SS_PRIMARY_USER_ID: - case OPS_PTAG_SS_REVOCABLE: - case OPS_PTAG_SS_REVOCATION_KEY: - case OPS_PTAG_CT_LITERAL_DATA_HEADER: - case OPS_PTAG_CT_LITERAL_DATA_BODY: - case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY: - case OPS_PTAG_CT_UNARMOURED_TEXT: - case OPS_PTAG_CT_ARMOUR_TRAILER: - case OPS_PTAG_CT_SIGNATURE_HEADER: - case OPS_PTAG_CT_SE_DATA_HEADER: - case OPS_PTAG_CT_SE_IP_DATA_HEADER: - case OPS_PTAG_CT_SE_IP_DATA_BODY: - case OPS_PTAG_CT_MDC: - case OPS_PARSER_CMD_GET_SECRET_KEY: - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER: - ops_headers_free(&c->content.signed_cleartext_header.headers); - break; - - case OPS_PTAG_CT_ARMOUR_HEADER: - ops_headers_free(&c->content.armour_header.headers); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: - ops_signed_cleartext_trailer_free(&c->content.signed_cleartext_trailer); - break; - - case OPS_PTAG_CT_TRUST: - ops_trust_free(&c->content.trust); - break; - - case OPS_PTAG_CT_SIGNATURE: - case OPS_PTAG_CT_SIGNATURE_FOOTER: - ops_signature_free(&c->content.signature); - break; - - case OPS_PTAG_CT_PUBLIC_KEY: - case OPS_PTAG_CT_PUBLIC_SUBKEY: - ops_public_key_free(&c->content.public_key); - break; - - case OPS_PTAG_CT_USER_ID: - ops_user_id_free(&c->content.user_id); - break; - - case OPS_PTAG_SS_SIGNERS_USER_ID: - ops_user_id_free(&c->content.ss_signers_user_id); - break; - - case OPS_PTAG_CT_USER_ATTRIBUTE: - ops_user_attribute_free(&c->content.user_attribute); - break; - - case OPS_PTAG_SS_PREFERRED_SKA: - ops_ss_preferred_ska_free(&c->content.ss_preferred_ska); - break; - - case OPS_PTAG_SS_PREFERRED_HASH: - ops_ss_preferred_hash_free(&c->content.ss_preferred_hash); - break; - - case OPS_PTAG_SS_PREFERRED_COMPRESSION: - ops_ss_preferred_compression_free(&c->content.ss_preferred_compression); - break; - - case OPS_PTAG_SS_KEY_FLAGS: - ops_ss_key_flags_free(&c->content.ss_key_flags); - break; - - case OPS_PTAG_SS_KEY_SERVER_PREFS: - ops_ss_key_server_prefs_free(&c->content.ss_key_server_prefs); - break; - - case OPS_PTAG_SS_FEATURES: - ops_ss_features_free(&c->content.ss_features); - break; - - case OPS_PTAG_SS_NOTATION_DATA: - ops_ss_notation_data_free(&c->content.ss_notation_data); - break; - - case OPS_PTAG_SS_REGEXP: - ops_ss_regexp_free(&c->content.ss_regexp); - break; - - case OPS_PTAG_SS_POLICY_URI: - ops_ss_policy_url_free(&c->content.ss_policy_url); - break; - - case OPS_PTAG_SS_PREFERRED_KEY_SERVER: - ops_ss_preferred_key_server_free(&c->content.ss_preferred_key_server); - break; - - case OPS_PTAG_SS_USERDEFINED00: - case OPS_PTAG_SS_USERDEFINED01: - case OPS_PTAG_SS_USERDEFINED02: - case OPS_PTAG_SS_USERDEFINED03: - case OPS_PTAG_SS_USERDEFINED04: - case OPS_PTAG_SS_USERDEFINED05: - case OPS_PTAG_SS_USERDEFINED06: - case OPS_PTAG_SS_USERDEFINED07: - case OPS_PTAG_SS_USERDEFINED08: - case OPS_PTAG_SS_USERDEFINED09: - case OPS_PTAG_SS_USERDEFINED10: - ops_ss_userdefined_free(&c->content.ss_userdefined); - break; - - case OPS_PTAG_SS_RESERVED: - ops_ss_reserved_free(&c->content.ss_unknown); - break; - - case OPS_PTAG_SS_REVOCATION_REASON: - ops_ss_revocation_reason_free(&c->content.ss_revocation_reason); - break; - - case OPS_PTAG_SS_EMBEDDED_SIGNATURE: - ops_ss_embedded_signature_free(&c->content.ss_embedded_signature); - break; - - case OPS_PARSER_PACKET_END: - ops_packet_free(&c->content.packet); - break; - - case OPS_PARSER_ERROR: - case OPS_PARSER_ERRCODE: - break; - - case OPS_PTAG_CT_SECRET_KEY: - case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: - ops_secret_key_free(&c->content.secret_key); - break; - - case OPS_PTAG_CT_PK_SESSION_KEY: - case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: - ops_pk_session_key_free(&c->content.pk_session_key); - break; - - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - case OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD: - ops_cmd_get_passphrase_free(&c->content.secret_key_passphrase); - break; - - default: - fprintf(stderr,"Can't free %d (0x%x)\n",c->tag,c->tag); - //ASSERT(0); - } -} - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -static void free_BN(BIGNUM **pp) - { - BN_free(*pp); - *pp=NULL; - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -void ops_pk_session_key_free(ops_pk_session_key_t *sk) -{ - switch(sk->algorithm) - { - case OPS_PKA_RSA: - free_BN(&sk->parameters.rsa.encrypted_m); - break; - - case OPS_PKA_ELGAMAL: - free_BN(&sk->parameters.elgamal.g_to_k); - free_BN(&sk->parameters.elgamal.encrypted_m); - break; - - default: - fprintf(stderr,"ops_pk_session_key_free: Unknown algorithm: %d \n",sk->algorithm); - //ASSERT(0); - } -} - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free the memory used when parsing a public key */ -void ops_public_key_free(ops_public_key_t *p) -{ - switch(p->algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - free_BN(&p->key.rsa.n); - free_BN(&p->key.rsa.e); - break; - - case OPS_PKA_DSA: - free_BN(&p->key.dsa.p); - free_BN(&p->key.dsa.q); - free_BN(&p->key.dsa.g); - free_BN(&p->key.dsa.y); - break; - - case OPS_PKA_ELGAMAL: - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - free_BN(&p->key.elgamal.p); - free_BN(&p->key.elgamal.g); - free_BN(&p->key.elgamal.y); - break; - - default: - fprintf(stderr,"ops_public_key_free: Unknown algorithm: %d \n",p->algorithm); - //ASSERT(0); - } -} - -void ops_public_key_copy(ops_public_key_t *dst,const ops_public_key_t *src) -{ - *dst = *src ; - - switch(src->algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - dst->key.rsa.n = BN_dup(src->key.rsa.n); - dst->key.rsa.e = BN_dup(src->key.rsa.e); - break; - - case OPS_PKA_DSA: - dst->key.dsa.p = BN_dup(src->key.dsa.p); - dst->key.dsa.q = BN_dup(src->key.dsa.q); - dst->key.dsa.g = BN_dup(src->key.dsa.g); - dst->key.dsa.y = BN_dup(src->key.dsa.y); - break; - - case OPS_PKA_ELGAMAL: - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - dst->key.elgamal.p = BN_dup(src->key.elgamal.p); - dst->key.elgamal.g = BN_dup(src->key.elgamal.g); - dst->key.elgamal.y = BN_dup(src->key.elgamal.y); - break; - - //case 0: - // nothing to free - // break; - - default: - fprintf(stderr,"ops_public_key_copy: Unknown algorithm: %d \n",src->algorithm); - //ASSERT(0); - } -} -/** - \ingroup Core_ReadPackets -*/ -static int parse_public_key_data(ops_public_key_t *key,ops_region_t *region, - ops_parse_info_t *pinfo) -{ - unsigned char c[1]=""; - - if(!(region->length_read == 0)) // ASSERT(region->length_read == 0) /* We should not have read anything so far */ - { - fprintf(stderr,"parse_public_key_data: read length error\n") ; - return 0 ; - } - - if(!limited_read(c,1,region,pinfo)) - return 0; - key->version=c[0]; - if(key->version < 2 || key->version > 4) - { - OPS_ERROR_1(&pinfo->errors,OPS_E_PROTO_BAD_PUBLIC_KEY_VRSN, - "Bad public key version (0x%02x)",key->version); - return 0; - } - - if(!limited_read_time(&key->creation_time,region,pinfo)) - return 0; - - key->days_valid=0; - if((key->version == 2 || key->version == 3) - && !limited_read_scalar(&key->days_valid,2,region,pinfo)) - return 0; - - if(!limited_read(c,1,region,pinfo)) - return 0; - - key->algorithm=c[0]; - - switch(key->algorithm) - { - case OPS_PKA_DSA: - if(!limited_read_mpi(&key->key.dsa.p,region,pinfo) - || !limited_read_mpi(&key->key.dsa.q,region,pinfo) - || !limited_read_mpi(&key->key.dsa.g,region,pinfo) - || !limited_read_mpi(&key->key.dsa.y,region,pinfo)) - return 0; - break; - - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - if(!limited_read_mpi(&key->key.rsa.n,region,pinfo) - || !limited_read_mpi(&key->key.rsa.e,region,pinfo)) - return 0; - break; - - case OPS_PKA_ELGAMAL: - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - if(!limited_read_mpi(&key->key.elgamal.p,region,pinfo) - || !limited_read_mpi(&key->key.elgamal.g,region,pinfo) - || !limited_read_mpi(&key->key.elgamal.y,region,pinfo)) - return 0; - break; - - default: - OPS_ERROR_1(&pinfo->errors,OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG,"Unsupported Public Key algorithm (%s)",ops_show_pka(key->algorithm)); - return 0; - } - - return 1; -} - - -/** - * \ingroup Core_ReadPackets - * \brief Parse a public key packet. - * - * This function parses an entire v3 (== v2) or v4 public key packet for RSA, ElGamal, and DSA keys. - * - * Once the key has been parsed successfully, it is passed to the callback. - * - * \param *ptag Pointer to the current Packet Tag. This function should consume the entire packet. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - * - * \see RFC4880 5.5.2 - */ -static int parse_public_key(ops_content_tag_t tag,ops_region_t *region, - ops_parse_info_t *pinfo) - { - ops_parser_content_t content; - - if(!parse_public_key_data(&C.public_key,region,pinfo)) - return 0; - - // XXX: this test should be done for all packets, surely? - if(region->length_read != region->length) - { - OPS_ERROR_1(&pinfo->errors,OPS_E_R_UNCONSUMED_DATA, - "Unconsumed data (%d)", region->length-region->length_read); - return 0; - } - - CBP(pinfo,tag,&content); - - return 1; - } - - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free the memory used when parsing this signature sub-packet type */ -void ops_ss_regexp_free(ops_ss_regexp_t *regexp) - { - string_free(®exp->text); - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free the memory used when parsing this signature sub-packet type */ -void ops_ss_policy_url_free(ops_ss_policy_url_t *policy_url) - { - string_free(&policy_url->text); - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free the memory used when parsing this signature sub-packet type */ -void ops_ss_preferred_key_server_free(ops_ss_preferred_key_server_t *preferred_key_server) - { - string_free(&preferred_key_server->text); - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free the memory used when parsing this packet type */ -void ops_user_attribute_free(ops_user_attribute_t *user_att) - { - data_free(&user_att->data); - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse one user attribute packet. - * - * User attribute packets contain one or more attribute subpackets. - * For now, handle the whole packet as raw data. - */ - -static int parse_user_attribute(ops_region_t *region, ops_parse_info_t *pinfo) -{ - - ops_parser_content_t content; - - /* xxx- treat as raw data for now. Could break down further - into attribute sub-packets later - rachel */ - - if(!(region->length_read == 0)) // ASSERT(region->length_read == 0) /* We should not have read anything so far */ - { - fprintf(stderr,"parse_user_attribute: read length error\n") ; - return 0 ; - } - - if(!read_data(&C.user_attribute.data,region,pinfo)) - return 0; - - CBP(pinfo,OPS_PTAG_CT_USER_ATTRIBUTE,&content); - - return 1; -} - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free the memory used when parsing this packet type */ -void ops_user_id_free(ops_user_id_t *id) - { - free(id->user_id); - id->user_id=NULL; - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse a user id. - * - * This function parses an user id packet, which is basically just a char array the size of the packet. - * - * The char array is to be treated as an UTF-8 string. - * - * The userid gets null terminated by this function. Freeing it is the responsibility of the caller. - * - * Once the userid has been parsed successfully, it is passed to the callback. - * - * \param *ptag Pointer to the Packet Tag. This function should consume the entire packet. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - * - * \see RFC4880 5.11 - */ -static int parse_user_id(ops_region_t *region,ops_parse_info_t *pinfo) -{ - ops_parser_content_t content; - - if(!(region->length_read == 0)) // ASSERT(region->length_read == 0) /* We should not have read anything so far */ - { - fprintf(stderr,"parse_user_id: region read size should be 0. Corrupted data ?\n") ; - return 0 ; - } - - /* From gnupg parse-packet.c: - Cap the size of a user ID at 2k: a value absurdly large enough - that there is no sane user ID string (which is printable text - as of RFC2440bis) that won't fit in it, but yet small enough to - avoid allocation problems. */ - - if(region->length > 2048) - { - fprintf(stderr,"parse_user_id(): invalid region length (%u)\n",region->length); - return 0; - } - C.user_id.user_id=malloc(region->length +1); /* XXX should we not like check malloc's return value? */ - - if(C.user_id.user_id==NULL) - { - fprintf(stderr,"malloc failed in parse_user_id\n") ; - return 0 ; - } - - if(region->length && !limited_read(C.user_id.user_id,region->length,region, - pinfo)) - return 0; - - C.user_id.user_id[region->length]='\0'; /* terminate the string */ - - CBP(pinfo,OPS_PTAG_CT_USER_ID,&content); - - return 1; -} - -/** - * \ingroup Core_Create - * \brief Free the memory used when parsing a private/experimental PKA signature - * \param unknown_sig - */ -void free_unknown_sig_pka(ops_unknown_signature_t *unknown_sig) - { - data_free(&unknown_sig->data); - } - -/** - * \ingroup Core_Create - * \brief Free the memory used when parsing a signature - * \param sig - */ -void ops_signature_free(ops_signature_t *sig) - { - switch(sig->info.key_algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_SIGN_ONLY: - free_BN(&sig->info.signature.rsa.sig); - break; - - case OPS_PKA_DSA: - free_BN(&sig->info.signature.dsa.r); - free_BN(&sig->info.signature.dsa.s); - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - free_BN(&sig->info.signature.elgamal.r); - free_BN(&sig->info.signature.elgamal.s); - break; - - case OPS_PKA_PRIVATE00: - case OPS_PKA_PRIVATE01: - case OPS_PKA_PRIVATE02: - case OPS_PKA_PRIVATE03: - case OPS_PKA_PRIVATE04: - case OPS_PKA_PRIVATE05: - case OPS_PKA_PRIVATE06: - case OPS_PKA_PRIVATE07: - case OPS_PKA_PRIVATE08: - case OPS_PKA_PRIVATE09: - case OPS_PKA_PRIVATE10: - free_unknown_sig_pka(&sig->info.signature.unknown); - break; - - default: - fprintf(stderr,"ops_signature_free: Unknown algorithm: %d \n",sig->info.key_algorithm); - //ASSERT(0); - } - free(sig->info.v4_hashed_data); - } - -/** - * \ingroup Core_Parse - * \brief Parse a version 3 signature. - * - * This function parses an version 3 signature packet, handling RSA and DSA signatures. - * - * Once the signature has been parsed successfully, it is passed to the callback. - * - * \param *ptag Pointer to the Packet Tag. This function should consume the entire packet. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - * - * \see RFC4880 5.2.2 - */ -static int parse_v3_signature(ops_region_t *region, - ops_parse_info_t *pinfo) - { - unsigned char c[1]=""; - ops_parser_content_t content; - - // clear signature - memset(&C.signature,'\0',sizeof C.signature); - - C.signature.info.version=OPS_V3; - - /* hash info length */ - if(!limited_read(c,1,region,pinfo)) - return 0; - if(c[0] != 5) - ERRP(pinfo,"bad hash info length"); - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.signature.info.type=c[0]; - /* XXX: check signature type */ - - if(!limited_read_time(&C.signature.info.creation_time,region,pinfo)) - return 0; - C.signature.info.creation_time_set=ops_true; - - if(!limited_read(C.signature.info.signer_id,OPS_KEY_ID_SIZE,region,pinfo)) - return 0; - C.signature.info.signer_id_set=ops_true; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.signature.info.key_algorithm=c[0]; - /* XXX: check algorithm */ - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.signature.info.hash_algorithm=c[0]; - /* XXX: check algorithm */ - - if(!limited_read(C.signature.hash2,2,region,pinfo)) - return 0; - - switch(C.signature.info.key_algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_SIGN_ONLY: - if(!limited_read_mpi(&C.signature.info.signature.rsa.sig,region,pinfo)) - return 0; - break; - - case OPS_PKA_DSA: - if(!limited_read_mpi(&C.signature.info.signature.dsa.r,region,pinfo) - || !limited_read_mpi(&C.signature.info.signature.dsa.s,region,pinfo)) - return 0; - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - if(!limited_read_mpi(&C.signature.info.signature.elgamal.r,region,pinfo) - || !limited_read_mpi(&C.signature.info.signature.elgamal.s,region,pinfo)) - return 0; - break; - - default: - OPS_ERROR_1(&pinfo->errors,OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG, - "Unsupported signature key algorithm (%s)", - ops_show_pka(C.signature.info.key_algorithm)); - return 0; - } - - if(region->length_read != region->length) - { - OPS_ERROR_1(&pinfo->errors,OPS_E_R_UNCONSUMED_DATA,"Unconsumed data (%d)",region->length-region->length_read); - return 0; - } - - if(C.signature.info.signer_id_set) - C.signature.hash=ops_parse_hash_find(pinfo,C.signature.info.signer_id); - - CBP(pinfo,OPS_PTAG_CT_SIGNATURE,&content); - - return 1; - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse one signature sub-packet. - * - * Version 4 signatures can have an arbitrary amount of (hashed and unhashed) subpackets. Subpackets are used to hold - * optional attributes of subpackets. - * - * This function parses one such signature subpacket. - * - * Once the subpacket has been parsed successfully, it is passed to the callback. - * - * \param *ptag Pointer to the Packet Tag. This function should consume the entire subpacket. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - * - * \see RFC4880 5.2.3 - */ -static int parse_one_signature_subpacket(ops_signature_t *sig, - ops_region_t *region, - ops_parse_info_t *pinfo) - { - ops_region_t subregion; - unsigned char c[1]=""; - ops_parser_content_t content; - unsigned t8,t7; - ops_boolean_t read=ops_true; - unsigned char bool[1]=""; - - ops_init_subregion(&subregion,region); - if(!limited_read_new_length(&subregion.length,region,pinfo)) - return 0; - - if(subregion.length > region->length) - ERRP(pinfo,"Subpacket too long"); - - if(!limited_read(c,1,&subregion,pinfo)) - return 0; - - t8=(c[0]&0x7f)/8; - t7=1 << (c[0]&7); - - content.critical=c[0] >> 7; - content.tag=OPS_PTAG_SIGNATURE_SUBPACKET_BASE+(c[0]&0x7f); - - /* Application wants it delivered raw */ - if(pinfo->ss_raw[t8]&t7) - { - C.ss_raw.tag=content.tag; - C.ss_raw.length=subregion.length-1; - C.ss_raw.raw=malloc(C.ss_raw.length); - - if(C.ss_raw.raw==NULL) - { - fprintf(stderr,"malloc failed in parse_signature_subpackets") ; - return 0 ; - } - if(!limited_read(C.ss_raw.raw,C.ss_raw.length,&subregion,pinfo)) - return 0; - CBP(pinfo,OPS_PTAG_RAW_SS,&content); - return 1; - } - - switch(content.tag) - { - case OPS_PTAG_SS_CREATION_TIME: - case OPS_PTAG_SS_EXPIRATION_TIME: - case OPS_PTAG_SS_KEY_EXPIRATION_TIME: - if(!limited_read_time(&C.ss_time.time,&subregion,pinfo)) - return 0; - if(content.tag == OPS_PTAG_SS_CREATION_TIME) - { - sig->info.creation_time=C.ss_time.time; - sig->info.creation_time_set=ops_true; - } - break; - - case OPS_PTAG_SS_TRUST: - if(!limited_read(&C.ss_trust.level,1,&subregion,pinfo) - || !limited_read(&C.ss_trust.amount,1,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_REVOCABLE: - if(!limited_read(bool,1,&subregion,pinfo)) - return 0; - C.ss_revocable.revocable=!!bool[0]; - break; - - case OPS_PTAG_SS_ISSUER_KEY_ID: - if(!limited_read(C.ss_issuer_key_id.key_id,OPS_KEY_ID_SIZE, - &subregion,pinfo)) - return 0; - memcpy(sig->info.signer_id,C.ss_issuer_key_id.key_id,OPS_KEY_ID_SIZE); - sig->info.signer_id_set=ops_true; - break; - - case OPS_PTAG_SS_PREFERRED_SKA: - if(!read_data(&C.ss_preferred_ska.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_PREFERRED_HASH: - if(!read_data(&C.ss_preferred_hash.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_PREFERRED_COMPRESSION: - if(!read_data(&C.ss_preferred_compression.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_PRIMARY_USER_ID: - if(!limited_read (bool,1,&subregion,pinfo)) - return 0; - C.ss_primary_user_id.primary_user_id = !!bool[0]; - break; - - case OPS_PTAG_SS_KEY_FLAGS: - if(!read_data(&C.ss_key_flags.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_KEY_SERVER_PREFS: - if(!read_data(&C.ss_key_server_prefs.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_FEATURES: - if(!read_data(&C.ss_features.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_SIGNERS_USER_ID: - if(!read_unsigned_string(&C.ss_signers_user_id.user_id,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_EMBEDDED_SIGNATURE: - // \todo should do something with this sig? - if (!read_data(&C.ss_embedded_signature.sig,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_NOTATION_DATA: - if(!limited_read_data(&C.ss_notation_data.flags,4,&subregion,pinfo)) - return 0; - if(!limited_read_size_t_scalar(&C.ss_notation_data.name.len,2, - &subregion,pinfo)) - return 0; - if(!limited_read_size_t_scalar(&C.ss_notation_data.value.len,2, - &subregion,pinfo)) - return 0; - if(!limited_read_data(&C.ss_notation_data.name, - C.ss_notation_data.name.len,&subregion,pinfo)) - return 0; - if(!limited_read_data(&C.ss_notation_data.value, - C.ss_notation_data.value.len,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_POLICY_URI: - if(!read_string(&C.ss_policy_url.text,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_REGEXP: - if(!read_string(&C.ss_regexp.text,&subregion, pinfo)) - return 0; - break; - - case OPS_PTAG_SS_PREFERRED_KEY_SERVER: - if(!read_string(&C.ss_preferred_key_server.text,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_USERDEFINED00: - case OPS_PTAG_SS_USERDEFINED01: - case OPS_PTAG_SS_USERDEFINED02: - case OPS_PTAG_SS_USERDEFINED03: - case OPS_PTAG_SS_USERDEFINED04: - case OPS_PTAG_SS_USERDEFINED05: - case OPS_PTAG_SS_USERDEFINED06: - case OPS_PTAG_SS_USERDEFINED07: - case OPS_PTAG_SS_USERDEFINED08: - case OPS_PTAG_SS_USERDEFINED09: - case OPS_PTAG_SS_USERDEFINED10: - if(!read_data(&C.ss_userdefined.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_RESERVED: - if(!read_data(&C.ss_unknown.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_REVOCATION_REASON: - /* first byte is the machine-readable code */ - if(!limited_read(&C.ss_revocation_reason.code,1,&subregion,pinfo)) - return 0; - - /* the rest is a human-readable UTF-8 string */ - if(!read_string(&C.ss_revocation_reason.text,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_REVOCATION_KEY: - /* octet 0 = clss. Bit 0x80 must be set */ - if(!limited_read (&C.ss_revocation_key.clss,1,&subregion,pinfo)) - return 0; - if(!(C.ss_revocation_key.clss&0x80)) - { - printf("Warning: OPS_PTAG_SS_REVOCATION_KEY class: " - "Bit 0x80 should be set\n"); - return 0; - } - - /* octet 1 = algid */ - if(!limited_read(&C.ss_revocation_key.algid,1,&subregion,pinfo)) - return 0; - - /* octets 2-21 = fingerprint */ - if(!limited_read(&C.ss_revocation_key.fingerprint[0],20,&subregion, - pinfo)) - return 0; - break; - - default: - if(pinfo->ss_parsed[t8]&t7) - OPS_ERROR_1(&pinfo->errors, OPS_E_PROTO_UNKNOWN_SS, - "Unknown signature subpacket type (%d)", c[0]&0x7f); - read=ops_false; - break; - } - - /* Application doesn't want it delivered parsed */ - if(!(pinfo->ss_parsed[t8]&t7)) - { - if(content.critical) - OPS_ERROR_1(&pinfo->errors,OPS_E_PROTO_CRITICAL_SS_IGNORED, - "Critical signature subpacket ignored (%d)", - c[0]&0x7f); - if(!read && !limited_skip(subregion.length-1,&subregion,pinfo)) - return 0; - // printf("skipped %d length %d\n",c[0]&0x7f,subregion.length); - if(read) - ops_parser_content_free(&content); - return 1; - } - - if(read && subregion.length_read != subregion.length) - { - OPS_ERROR_1(&pinfo->errors,OPS_E_R_UNCONSUMED_DATA, - "Unconsumed data (%d)", - subregion.length-subregion.length_read); - return 0; - } - - CBP(pinfo,content.tag,&content); - - return 1; - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type - \param ss_preferred_ska -*/ -void ops_ss_preferred_ska_free(ops_ss_preferred_ska_t *ss_preferred_ska) - { - data_free(&ss_preferred_ska->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type - \param ss_preferred_hash -*/ -void ops_ss_preferred_hash_free(ops_ss_preferred_hash_t *ss_preferred_hash) - { - data_free(&ss_preferred_hash->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_preferred_compression_free(ops_ss_preferred_compression_t *ss_preferred_compression) - { - data_free(&ss_preferred_compression->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_key_flags_free(ops_ss_key_flags_t *ss_key_flags) - { - data_free(&ss_key_flags->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_features_free(ops_ss_features_t *ss_features) - { - data_free(&ss_features->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_key_server_prefs_free(ops_ss_key_server_prefs_t *ss_key_server_prefs) - { - data_free(&ss_key_server_prefs->data); - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse several signature subpackets. - * - * Hashed and unhashed subpacket sets are preceded by an octet count that specifies the length of the complete set. - * This function parses this length and then calls parse_one_signature_subpacket() for each subpacket until the - * entire set is consumed. - * - * This function does not call the callback directly, parse_one_signature_subpacket() does for each subpacket. - * - * \param *ptag Pointer to the Packet Tag. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - * - * \see RFC4880 5.2.3 - */ -static int parse_signature_subpackets(ops_signature_t *sig, - ops_region_t *region, - ops_parse_info_t *pinfo) - { - ops_region_t subregion; - ops_parser_content_t content; - - ops_init_subregion(&subregion,region); - if(!limited_read_scalar(&subregion.length,2,region,pinfo)) - return 0; - - if(subregion.length > region->length) - ERRP(pinfo,"Subpacket set too long"); - - while(subregion.length_read < subregion.length) - if(!parse_one_signature_subpacket(sig,&subregion,pinfo)) - return 0; - - if(subregion.length_read != subregion.length) - { - if(!limited_skip(subregion.length-subregion.length_read,&subregion, - pinfo)) - ERRP(pinfo,"Read failed while recovering from subpacket length mismatch"); - ERRP(pinfo,"Subpacket length mismatch"); - } - - return 1; - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse a version 4 signature. - * - * This function parses a version 4 signature including all its hashed and unhashed subpackets. - * - * Once the signature packet has been parsed successfully, it is passed to the callback. - * - * \param *ptag Pointer to the Packet Tag. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - * - * \see RFC4880 5.2.3 - */ -static int parse_v4_signature(ops_region_t *region,ops_parse_info_t *pinfo) - { - unsigned char c[1]=""; - ops_parser_content_t content; - - //debug=1; - if (debug) - { fprintf(stderr, "\nparse_v4_signature\n"); } - - // clear signature - memset(&C.signature,'\0',sizeof C.signature); - - /* We need to hash the packet data from version through the hashed subpacket data */ - - C.signature.v4_hashed_data_start=pinfo->rinfo.alength-1; - - /* Set version,type,algorithms */ - - C.signature.info.version=OPS_V4; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.signature.info.type=c[0]; - if (debug) - { fprintf(stderr, "signature type=%d\n", C.signature.info.type); } - - /* XXX: check signature type */ - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.signature.info.key_algorithm=c[0]; - /* XXX: check algorithm */ - if (debug) - { fprintf(stderr, "key_algorithm=%d\n", C.signature.info.key_algorithm); } - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.signature.info.hash_algorithm=c[0]; - /* XXX: check algorithm */ - if (debug) - { fprintf(stderr, "hash_algorithm=%d %s\n", C.signature.info.hash_algorithm, ops_show_hash_algorithm(C.signature.info.hash_algorithm)); } - - CBP(pinfo,OPS_PTAG_CT_SIGNATURE_HEADER,&content); - - if(!parse_signature_subpackets(&C.signature,region,pinfo)) - return 0; - - C.signature.info.v4_hashed_data_length=pinfo->rinfo.alength - -C.signature.v4_hashed_data_start; - - // copy hashed subpackets - if (C.signature.info.v4_hashed_data) - free(C.signature.info.v4_hashed_data); - C.signature.info.v4_hashed_data=ops_mallocz(C.signature.info.v4_hashed_data_length); - - if (!pinfo->rinfo.accumulate) - { - /* We must accumulate, else we can't check the signature */ - fprintf(stderr,"*** ERROR: must set accumulate to true\n"); - return 0 ; //ASSERT(0); - } - - memcpy(C.signature.info.v4_hashed_data, - pinfo->rinfo.accumulated+C.signature.v4_hashed_data_start, - C.signature.info.v4_hashed_data_length); - - if(!parse_signature_subpackets(&C.signature,region,pinfo)) - return 0; - - if(!limited_read(C.signature.hash2,2,region,pinfo)) - return 0; - - switch(C.signature.info.key_algorithm) - { - case OPS_PKA_RSA: - if(!limited_read_mpi(&C.signature.info.signature.rsa.sig,region,pinfo)) - return 0; - break; - - case OPS_PKA_DSA: - if(!limited_read_mpi(&C.signature.info.signature.dsa.r,region,pinfo)) - ERRP(pinfo,"Error reading DSA r field in signature"); - if (!limited_read_mpi(&C.signature.info.signature.dsa.s,region,pinfo)) - ERRP(pinfo,"Error reading DSA s field in signature"); - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - if(!limited_read_mpi(&C.signature.info.signature.elgamal.r,region,pinfo) - || !limited_read_mpi(&C.signature.info.signature.elgamal.s,region,pinfo)) - return 0; - break; - - case OPS_PKA_PRIVATE00: - case OPS_PKA_PRIVATE01: - case OPS_PKA_PRIVATE02: - case OPS_PKA_PRIVATE03: - case OPS_PKA_PRIVATE04: - case OPS_PKA_PRIVATE05: - case OPS_PKA_PRIVATE06: - case OPS_PKA_PRIVATE07: - case OPS_PKA_PRIVATE08: - case OPS_PKA_PRIVATE09: - case OPS_PKA_PRIVATE10: - if (!read_data(&C.signature.info.signature.unknown.data,region,pinfo)) - return 0; - break; - - default: - OPS_ERROR_1(&pinfo->errors,OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG, - "Bad v4 signature key algorithm (%s)", - ops_show_pka(C.signature.info.key_algorithm)); - return 0; - } - - if(region->length_read != region->length) - { - OPS_ERROR_1(&pinfo->errors,OPS_E_R_UNCONSUMED_DATA, - "Unconsumed data (%d)", - region->length-region->length_read); - return 0; - } - - CBP(pinfo,OPS_PTAG_CT_SIGNATURE_FOOTER,&content); - - return 1; - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse a signature subpacket. - * - * This function calls the appropriate function to handle v3 or v4 signatures. - * - * Once the signature packet has been parsed successfully, it is passed to the callback. - * - * \param *ptag Pointer to the Packet Tag. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - */ -static int parse_signature(ops_region_t *region,ops_parse_info_t *pinfo) -{ - unsigned char c[1]=""; - ops_parser_content_t content; - - if(!(region->length_read == 0)) // ASSERT(region->length_read == 0) /* We should not have read anything so far */ - { - fprintf(stderr,"parse_signature: region read is not empty! Data is corrupted?") ; - return 0 ; - } - - memset(&content,'\0',sizeof content); - - if(!limited_read(c,1,region,pinfo)) - return 0; - - if(c[0] == 2 || c[0] == 3) - return parse_v3_signature(region,pinfo); - else if(c[0] == 4) - return parse_v4_signature(region,pinfo); - - OPS_ERROR_1(&pinfo->errors,OPS_E_PROTO_BAD_SIGNATURE_VRSN, - "Bad signature version (%d)",c[0]); - return 0; -} - -/** - \ingroup Core_ReadPackets - \brief Parse Compressed packet -*/ -static int parse_compressed(ops_region_t *region,ops_parse_info_t *pinfo) - { - unsigned char c[1]=""; - ops_parser_content_t content; - - if(pinfo->recursive_compression_depth > MAX_RECURSIVE_COMPRESSION_DEPTH) - { - fprintf(stderr,"Recursive compression down to depth 32. This is weird. Probably a packet crafted to crash PGP. Will be dropped!\n") ; - return 0 ; - } - - if(!limited_read(c,1,region,pinfo)) - return 0; - -pinfo->recursive_compression_depth++ ; - - C.compressed.type=c[0]; - - CBP(pinfo,OPS_PTAG_CT_COMPRESSED,&content); - - /* The content of a compressed data packet is more OpenPGP packets - once decompressed, so recursively handle them */ - - int res = ops_decompress(region,pinfo,C.compressed.type); - -pinfo->recursive_compression_depth-- ; - - return res ; - } - -/** - \ingroup Core_ReadPackets - \brief Parse a One Pass Signature packet -*/ -static int parse_one_pass(ops_region_t *region,ops_parse_info_t *pinfo) - { - unsigned char c[1]=""; - ops_parser_content_t content; - - if(!limited_read(&C.one_pass_signature.version,1,region,pinfo)) - return 0; - if(C.one_pass_signature.version != 3) - { - OPS_ERROR_1(&pinfo->errors,OPS_E_PROTO_BAD_ONE_PASS_SIG_VRSN, - "Bad one-pass signature version (%d)", - C.one_pass_signature.version); - return 0; - } - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.one_pass_signature.sig_type=c[0]; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.one_pass_signature.hash_algorithm=c[0]; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.one_pass_signature.key_algorithm=c[0]; - - if(!limited_read(C.one_pass_signature.keyid, - sizeof C.one_pass_signature.keyid,region,pinfo)) - return 0; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.one_pass_signature.nested=!!c[0]; - - CBP(pinfo,OPS_PTAG_CT_ONE_PASS_SIGNATURE,&content); - - // XXX: we should, perhaps, let the app choose whether to hash or not - ops_parse_hash_init(pinfo,C.one_pass_signature.hash_algorithm, - C.one_pass_signature.keyid); - - return 1; - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_userdefined_free(ops_ss_userdefined_t *ss_userdefined) - { - data_free(&ss_userdefined->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_reserved_free(ops_ss_unknown_t *ss_unknown) - { - data_free(&ss_unknown->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_notation_data_free(ops_ss_notation_data_t *ss_notation_data) - { - data_free(&ss_notation_data->name); - data_free(&ss_notation_data->value); - } - -void ops_ss_embedded_signature_free(ops_ss_embedded_signature_t *ss_embedded_signature) - { - data_free(&ss_embedded_signature->sig); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_revocation_reason_free(ops_ss_revocation_reason_t *ss_revocation_reason) - { - string_free(&ss_revocation_reason->text); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this packet type -*/ -void ops_trust_free(ops_trust_t *trust) - { - data_free(&trust->data); - } - -/** - \ingroup Core_ReadPackets - \brief Parse a Trust packet -*/ -static int -parse_trust (ops_region_t *region, ops_parse_info_t *pinfo) - { - ops_parser_content_t content; - - if(!read_data(&C.trust.data,region,pinfo)) - return 0; - - CBP(pinfo,OPS_PTAG_CT_TRUST, &content); - - return 1; - } - -/** - \ingroup Core_ReadPackets - \brief Parse a Literal Data packet -*/ -static int parse_literal_data(ops_region_t *region,ops_parse_info_t *pinfo) - { - ops_parser_content_t content; - unsigned char c[1]=""; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.literal_data_header.format=c[0]; - - if(!limited_read(c,1,region,pinfo)) - return 0; - if(!limited_read((unsigned char *)C.literal_data_header.filename,c[0], - region,pinfo)) - return 0; - C.literal_data_header.filename[c[0]]='\0'; - - if(!limited_read_time(&C.literal_data_header.modification_time,region,pinfo)) - return 0; - - CBP(pinfo,OPS_PTAG_CT_LITERAL_DATA_HEADER,&content); - - while(region->length_read < region->length) - { - unsigned l=region->length-region->length_read; - - C.literal_data_body.data = (unsigned char *)malloc(l) ; - - if(C.literal_data_body.data == NULL) - { - fprintf(stderr,"parse_literal_data(): cannot malloc for requested size %d.\n",l) ; - return 0 ; - } - - if(!limited_read(C.literal_data_body.data,l,region,pinfo)) - { - free(C.literal_data_body.data); - return 0; - } - - C.literal_data_body.length=l; - - ops_parse_hash_data(pinfo,C.literal_data_body.data,l); - - CBP(pinfo,OPS_PTAG_CT_LITERAL_DATA_BODY,&content); - free(C.literal_data_body.data); - } - - return 1; - } - -/** - * \ingroup Core_Create - * - * ops_secret_key_free() frees the memory associated with "key". Note that - * the key itself is not freed. - * - * \param key - */ - -void ops_secret_key_free(ops_secret_key_t *key) - { - switch(key->public_key.algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - free_BN(&key->key.rsa.d); - free_BN(&key->key.rsa.p); - free_BN(&key->key.rsa.q); - free_BN(&key->key.rsa.u); - break; - - case OPS_PKA_DSA: - free_BN(&key->key.dsa.x); - break; - - default: - fprintf(stderr,"ops_secret_key_free: Unknown algorithm: %d (%s)\n",key->public_key.algorithm, ops_show_pka(key->public_key.algorithm)); - //ASSERT(0); - } - - ops_public_key_free(&key->public_key); - } - -void ops_secret_key_copy(ops_secret_key_t *dst,const ops_secret_key_t *src) -{ - *dst = *src ; - ops_public_key_copy(&dst->public_key,&src->public_key); - - switch(src->public_key.algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - dst->key.rsa.d = BN_dup(src->key.rsa.d) ; - dst->key.rsa.p = BN_dup(src->key.rsa.p) ; - dst->key.rsa.q = BN_dup(src->key.rsa.q) ; - dst->key.rsa.u = BN_dup(src->key.rsa.u) ; - break; - - case OPS_PKA_DSA: - dst->key.dsa.x = BN_dup(src->key.dsa.x) ; - break; - - default: - fprintf(stderr,"ops_secret_key_copy: Unknown algorithm: %d (%s)\n",src->public_key.algorithm, ops_show_pka(src->public_key.algorithm)); - //ASSERT(0); - } -} -static int consume_packet(ops_region_t *region,ops_parse_info_t *pinfo, - ops_boolean_t warn) - { - ops_data_t remainder; - ops_parser_content_t content; - - if(region->indeterminate) - ERRP(pinfo,"Can't consume indeterminate packets"); - - if(read_data(&remainder,region,pinfo)) - { - /* now throw it away */ - data_free(&remainder); - if(warn) - OPS_ERROR(&pinfo->errors,OPS_E_P_PACKET_CONSUMED,"Warning: packet consumer"); - } - else if(warn) - OPS_ERROR(&pinfo->errors,OPS_E_P_PACKET_NOT_CONSUMED,"Warning: Packet was not consumed"); - else - { - OPS_ERROR(&pinfo->errors,OPS_E_P_PACKET_NOT_CONSUMED,"Packet was not consumed"); - return 0; - } - - return 1; - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse a secret key - */ -static int parse_secret_key(ops_region_t *region,ops_parse_info_t *pinfo) -{ - ops_parser_content_t content; - unsigned char c[1]=""; - ops_crypt_t decrypt; - int ret=1; - ops_region_t encregion; - ops_region_t *saved_region=NULL; - ops_hash_t checkhash; - int blocksize; - ops_boolean_t crypted; - - if (debug) - { fprintf(stderr,"\n---------\nparse_secret_key:\n"); - fprintf(stderr,"region length=%d, length_read=%d, remainder=%d\n", region->length, region->length_read, region->length-region->length_read); - } - - memset(&content,'\0',sizeof content); - if(!parse_public_key_data(&C.secret_key.public_key,region,pinfo)) - return 0; - - if (debug) - { - fprintf(stderr,"parse_secret_key: public key parsed\n"); - ops_print_public_key(&C.secret_key.public_key); - } - - pinfo->reading_v3_secret=C.secret_key.public_key.version != OPS_V4; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.secret_key.s2k_usage=c[0]; - - if(C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED - || C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED) - { - if(!limited_read(c,1,region,pinfo)) - return 0; - C.secret_key.algorithm=c[0]; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.secret_key.s2k_specifier=c[0]; - - if(!(C.secret_key.s2k_specifier == OPS_S2KS_SIMPLE || C.secret_key.s2k_specifier == OPS_S2KS_SALTED || C.secret_key.s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED)) // ASSERT(C.secret_key.s2k_specifier == OPS_S2KS_SIMPLE || C.secret_key.s2k_specifier == OPS_S2KS_SALTED || C.secret_key.s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED) - { - fprintf(stderr,"parse_secret_key: error in secret key format. Bad flags combination.\n") ; - return 0; - } - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.secret_key.hash_algorithm=c[0]; - - if(C.secret_key.s2k_specifier != OPS_S2KS_SIMPLE - && !limited_read(C.secret_key.salt,8,region,pinfo)) - { - return 0; - } - - if(C.secret_key.s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED) - { - if(!limited_read(c,1,region,pinfo)) - return 0; - C.secret_key.octet_count=(16+(c[0]&15)) << ((c[0] >> 4)+6); - } - } - else if(C.secret_key.s2k_usage != OPS_S2KU_NONE) - { - // this is V3 style, looks just like a V4 simple hash - C.secret_key.algorithm=(ops_symmetric_algorithm_t)C.secret_key.s2k_usage; - C.secret_key.s2k_usage=OPS_S2KU_ENCRYPTED; - C.secret_key.s2k_specifier=OPS_S2KS_SIMPLE; - C.secret_key.hash_algorithm=OPS_HASH_MD5; - } - - crypted=C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED - || C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED; - - if(crypted) - { - int n; - ops_parser_content_t pc; - char *passphrase; - unsigned char key[OPS_MAX_KEY_SIZE+OPS_MAX_HASH_SIZE]; - ops_hash_t hashes[(OPS_MAX_KEY_SIZE+OPS_MIN_HASH_SIZE-1)/OPS_MIN_HASH_SIZE]; - int keysize; - int hashsize; - size_t l; - - blocksize=ops_block_size(C.secret_key.algorithm); - if(!(blocksize > 0 && blocksize <= OPS_MAX_BLOCK_SIZE)) // ASSERT(blocksize > 0 && blocksize <= OPS_MAX_BLOCK_SIZE); - { - fprintf(stderr,"parse_secret_key: block size error. Data seems corrupted.") ; - return 0; - } - - if(!limited_read(C.secret_key.iv,blocksize,region,pinfo)) - return 0; - - memset(&pc,'\0',sizeof pc); - passphrase=NULL; - pc.content.secret_key_passphrase.passphrase=&passphrase; - pc.content.secret_key_passphrase.secret_key=&C.secret_key; - CBP(pinfo,OPS_PARSER_CMD_GET_SK_PASSPHRASE,&pc); - if(!passphrase) - { - if (debug) - { - // \todo make into proper error - fprintf(stderr,"parse_secret_key: can't get passphrase\n"); - } - - if(!consume_packet(region,pinfo,ops_false)) - return 0; - - CBP(pinfo,OPS_PTAG_CT_ENCRYPTED_SECRET_KEY,&content); - - return 1; - } - - keysize=ops_key_size(C.secret_key.algorithm); - if(!(keysize > 0 && keysize <= OPS_MAX_KEY_SIZE)) // ASSERT(keysize > 0 && keysize <= OPS_MAX_KEY_SIZE); - { - fprintf(stderr,"parse_secret_key: keysize %d exceeds maximum allowed size %d\n",keysize,OPS_MAX_KEY_SIZE); - return 0 ; - } - - hashsize=ops_hash_size(C.secret_key.hash_algorithm); - if(!(hashsize > 0 && hashsize <= OPS_MAX_HASH_SIZE)) // ASSERT(hashsize > 0 && hashsize <= OPS_MAX_HASH_SIZE); - { - fprintf(stderr,"parse_secret_key: hashsize %d exceeds maximum allowed size %d\n",keysize,OPS_MAX_HASH_SIZE); - return 0 ; - } - - for(n=0 ; n*hashsize < keysize ; ++n) - { - int i; - - ops_hash_any(&hashes[n],C.secret_key.hash_algorithm); - hashes[n].init(&hashes[n]); - // preload hashes with zeroes... - for(i=0 ; i < n ; ++i) - hashes[n].add(&hashes[n],(unsigned char *)"",1); - } - - l=strlen(passphrase); - - for(n=0 ; n*hashsize < keysize ; ++n) - { - unsigned i; - - switch(C.secret_key.s2k_specifier) - { - case OPS_S2KS_SALTED: - hashes[n].add(&hashes[n],C.secret_key.salt,OPS_SALT_SIZE); - /* fallthrough */ - case OPS_S2KS_SIMPLE: - hashes[n].add(&hashes[n],(unsigned char*)passphrase,l); - break; - - case OPS_S2KS_ITERATED_AND_SALTED: - for(i=0 ; i < C.secret_key.octet_count ; i+=l+OPS_SALT_SIZE) - { - int j=l+OPS_SALT_SIZE; - - if(i+j > C.secret_key.octet_count && i != 0) - j=C.secret_key.octet_count-i; - - hashes[n].add(&hashes[n],C.secret_key.salt, - j > OPS_SALT_SIZE ? OPS_SALT_SIZE : j); - if(j > OPS_SALT_SIZE) - hashes[n].add(&hashes[n],(unsigned char *)passphrase,j-OPS_SALT_SIZE); - } - - } - } - - for(n=0 ; n*hashsize < keysize ; ++n) - { - int r=hashes[n].finish(&hashes[n],key+n*hashsize); - if(!(r == hashsize)) // ASSERT(r == hashsize); - { - fprintf(stderr,"parse_secret_key: read error. Data probably corrupted.") ; - return 0 ; - } - } - - free(passphrase); - - ops_crypt_any(&decrypt,C.secret_key.algorithm); - if (debug) - { - unsigned int i=0; - fprintf(stderr,"\nREADING:\niv="); - for (i=0; ilength-region->length_read; - if(C.secret_key.public_key.version != OPS_V4) - { - encregion.length-=2; - } - saved_region=region; - region=&encregion; - } - - if(C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED) - { - ops_hash_sha1(&checkhash); - ops_reader_push_hash(pinfo,&checkhash); - } - else - { - ops_reader_push_sum16(pinfo); - } - - switch(C.secret_key.public_key.algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - if(!limited_read_mpi(&C.secret_key.key.rsa.d,region,pinfo) - || !limited_read_mpi(&C.secret_key.key.rsa.p,region,pinfo) - || !limited_read_mpi(&C.secret_key.key.rsa.q,region,pinfo) - || !limited_read_mpi(&C.secret_key.key.rsa.u,region,pinfo)) - ret=0; - - break; - - case OPS_PKA_DSA: - - if(!limited_read_mpi(&C.secret_key.key.dsa.x,region,pinfo)) - ret=0; - break; - - default: - OPS_ERROR_2(&pinfo->errors,OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG,"Unsupported Public Key algorithm %d (%s)",C.secret_key.public_key.algorithm,ops_show_pka(C.secret_key.public_key.algorithm)); - ret=0; - // ASSERT(0); - } - - if (debug) - { - fprintf(stderr,"4 MPIs read\n"); - // ops_print_secret_key_verbose(OPS_PTAG_CT_SECRET_KEY, &C.secret_key); - } - - pinfo->reading_v3_secret=ops_false; - - if(C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED) - { - unsigned char hash[20]; - - ops_reader_pop_hash(pinfo); - checkhash.finish(&checkhash,hash); - - if(crypted && C.secret_key.public_key.version != OPS_V4) - { - ops_reader_pop_decrypt(pinfo); - region=saved_region; - } - - if(ret) - { - if(!limited_read(C.secret_key.checkhash,20,region,pinfo)) - return 0; - - if(memcmp(hash,C.secret_key.checkhash,20)) - ERRP(pinfo,"Hash mismatch in secret key"); - } - } - else - { - unsigned short sum; - - sum=ops_reader_pop_sum16(pinfo); - - if(crypted && C.secret_key.public_key.version != OPS_V4) - { - ops_reader_pop_decrypt(pinfo); - region=saved_region; - } - - if(ret) - { - if(!limited_read_scalar(&C.secret_key.checksum,2,region, - pinfo)) - return 0; - - if(sum != C.secret_key.checksum) - ERRP(pinfo,"Checksum mismatch in secret key"); - } - } - - if(crypted && C.secret_key.public_key.version == OPS_V4) - { - ops_reader_pop_decrypt(pinfo); - } - - if(!(!ret || region->length_read == region->length)) // ASSERT(!ret || region->length_read == region->length) - { - fprintf(stderr,"parse_secret_key: read error. data probably corrupted.") ; - return 0 ; - } - - if(!ret) - return 0; - - CBP(pinfo,OPS_PTAG_CT_SECRET_KEY,&content); - - if (debug) - { fprintf(stderr, "--- end of parse_secret_key\n\n"); } - - return 1; -} - -/** - \ingroup Core_ReadPackets - \brief Parse a Public Key Session Key packet -*/ -static int parse_pk_session_key(ops_region_t *region, - ops_parse_info_t *pinfo) - { - unsigned char c[1]=""; - ops_parser_content_t content; - ops_parser_content_t pc; - - int n; - BIGNUM *enc_m; - unsigned k; - const ops_secret_key_t *secret; - unsigned char cs[2]; - unsigned char* iv; - - // Can't rely on it being CAST5 - // \todo FIXME RW - // const size_t sz_unencoded_m_buf=CAST_KEY_LENGTH+1+2; - const size_t sz_unencoded_m_buf=1024; - unsigned char unencoded_m_buf[sz_unencoded_m_buf]; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.pk_session_key.version=c[0]; - if(C.pk_session_key.version != OPS_PKSK_V3) - { - OPS_ERROR_1(&pinfo->errors, OPS_E_PROTO_BAD_PKSK_VRSN, - "Bad public-key encrypted session key version (%d)", - C.pk_session_key.version); - return 0; - } - - if(!limited_read(C.pk_session_key.key_id, - sizeof C.pk_session_key.key_id,region,pinfo)) - return 0; - - if (debug) - { - int i; - int x=sizeof C.pk_session_key.key_id; - printf("session key: public key id: x=%d\n",x); - for (i=0; ierrors, OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG, - "Unknown public key algorithm in session key (%s)", - ops_show_pka(C.pk_session_key.algorithm)); - return 0; - } - - memset(&pc,'\0',sizeof pc); - secret=NULL; - pc.content.get_secret_key.secret_key=&secret; - pc.content.get_secret_key.pk_session_key=&C.pk_session_key; - - CBP(pinfo,OPS_PARSER_CMD_GET_SECRET_KEY,&pc); - - if(!secret) - { - CBP(pinfo,OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY,&content); - - return 1; - } - - // n=ops_decrypt_mpi(buf,sizeof buf,enc_m,secret); - n=ops_decrypt_and_unencode_mpi(unencoded_m_buf,sizeof unencoded_m_buf,enc_m,secret); - - if(n < 1) - { - ERRP(pinfo,"decrypted message too short"); - return 0; - } - - // PKA - C.pk_session_key.symmetric_algorithm=unencoded_m_buf[0]; - - if (!ops_is_sa_supported(C.pk_session_key.symmetric_algorithm)) - { - // ERR1P - OPS_ERROR_1(&pinfo->errors,OPS_E_ALG_UNSUPPORTED_SYMMETRIC_ALG, - "Symmetric algorithm %s not supported", - ops_show_symmetric_algorithm(C.pk_session_key.symmetric_algorithm)); - return 0; - } - - k=ops_key_size(C.pk_session_key.symmetric_algorithm); - - if((unsigned)n != k+3) - { - OPS_ERROR_2(&pinfo->errors,OPS_E_PROTO_DECRYPTED_MSG_WRONG_LEN, - "decrypted message wrong length (got %d expected %d)", - n,k+3); - return 0; - } - - if(!(k <= sizeof C.pk_session_key.key)) // ASSERT(k <= sizeof C.pk_session_key.key); - { - fprintf(stderr,"ops_decrypt_se_data: error in session key size. Corrupted data?") ; - return 0 ; - } - - memcpy(C.pk_session_key.key,unencoded_m_buf+1,k); - - if (debug) - { - printf("session key recovered (len=%d):\n",k); - unsigned int j; - for(j=0; jerrors, OPS_E_PROTO_BAD_SK_CHECKSUM, - "Session key checksum wrong: expected %2x %2x, got %2x %2x", - cs[0], cs[1], unencoded_m_buf[k+1], unencoded_m_buf[k+2]); - return 0; - } - - // all is well - CBP(pinfo,OPS_PTAG_CT_PK_SESSION_KEY,&content); - - ops_crypt_any(&pinfo->decrypt,C.pk_session_key.symmetric_algorithm); - iv=ops_mallocz(pinfo->decrypt.blocksize); - pinfo->decrypt.set_iv(&pinfo->decrypt, iv); - pinfo->decrypt.set_key(&pinfo->decrypt,C.pk_session_key.key); - ops_encrypt_init(&pinfo->decrypt); - return 1; - } - -// XXX: make this static? -int ops_decrypt_se_data(ops_content_tag_t tag,ops_region_t *region, ops_parse_info_t *pinfo) -{ - int r=1; - ops_crypt_t *decrypt=ops_parse_get_decrypt(pinfo); - - if(decrypt) - { - unsigned char buf[OPS_MAX_BLOCK_SIZE+2]=""; - size_t b=decrypt->blocksize; - // ops_parser_content_t content; - ops_region_t encregion; - - - ops_reader_push_decrypt(pinfo,decrypt,region); - - ops_init_subregion(&encregion,NULL); - encregion.length=b+2; - - if(!exact_limited_read(buf,b+2,&encregion,pinfo)) - return 0; - - if(buf[b-2] != buf[b] || buf[b-1] != buf[b+1]) - { - ops_reader_pop_decrypt(pinfo); - OPS_ERROR_4(&pinfo->errors, OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT, - "Bad symmetric decrypt (%02x%02x vs %02x%02x)", - buf[b-2],buf[b-1],buf[b],buf[b+1]); - return 0; - } - - if(tag == OPS_PTAG_CT_SE_DATA_BODY) - { - decrypt->decrypt_resync(decrypt); - decrypt->block_encrypt(decrypt,decrypt->civ,decrypt->civ); - } - - - r=ops_parse(pinfo,ops_false); - - ops_reader_pop_decrypt(pinfo); - } - else - { - ops_parser_content_t content; - - while(region->length_read < region->length) - { - unsigned l=region->length-region->length_read; - - if(l > sizeof C.se_data_body.data) - l=sizeof C.se_data_body.data; - - if(!limited_read(C.se_data_body.data,l,region,pinfo)) - return 0; - - C.se_data_body.length=l; - - CBP(pinfo,tag,&content); - } - } - - return r; -} - -int ops_decrypt_se_ip_data(ops_content_tag_t tag,ops_region_t *region, - ops_parse_info_t *pinfo) -{ - int r=1; - ops_crypt_t *decrypt=ops_parse_get_decrypt(pinfo); - - if(decrypt) - { - ops_reader_push_decrypt(pinfo,decrypt,region); - ops_reader_push_se_ip_data(pinfo,decrypt,region); - - r=ops_parse(pinfo,ops_false); - - ops_reader_pop_se_ip_data(pinfo); - ops_reader_pop_decrypt(pinfo); - } - else - { - ops_parser_content_t content; - - while(region->length_read < region->length) - { - unsigned l=region->length-region->length_read; - - if(l > sizeof C.se_data_body.data) - l=sizeof C.se_data_body.data; - - if(!limited_read(C.se_data_body.data,l,region,pinfo)) - return 0; - - C.se_data_body.length=l; - - CBP(pinfo,tag,&content); - } - } - - return r; -} - -/** - \ingroup Core_ReadPackets - \brief Read a Symmetrically Encrypted packet -*/ -static int parse_se_data(ops_region_t *region,ops_parse_info_t *pinfo) - { - ops_parser_content_t content; - - /* there's no info to go with this, so just announce it */ - CBP(pinfo,OPS_PTAG_CT_SE_DATA_HEADER,&content); - - /* The content of an encrypted data packet is more OpenPGP packets - once decrypted, so recursively handle them */ - return ops_decrypt_se_data(OPS_PTAG_CT_SE_DATA_BODY,region,pinfo); - } - -/** - \ingroup Core_ReadPackets - \brief Read a Symmetrically Encrypted Integrity Protected packet -*/ -static int parse_se_ip_data(ops_region_t *region,ops_parse_info_t *pinfo) -{ - unsigned char c[1]=""; - ops_parser_content_t content; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.se_ip_data_header.version=c[0]; - - if(!(C.se_ip_data_header.version == OPS_SE_IP_V1)) // ASSERT(C.se_ip_data_header.version == OPS_SE_IP_V1); - { - fprintf(stderr,"parse_se_ip_data: packet header version should be %d, it is %d. Packet dropped.",OPS_SE_IP_V1,C.se_ip_data_header.version) ; - return 0 ; - } - - /* The content of an encrypted data packet is more OpenPGP packets - once decrypted, so recursively handle them */ - return ops_decrypt_se_ip_data(OPS_PTAG_CT_SE_IP_DATA_BODY,region,pinfo); -} - -/** - \ingroup Core_ReadPackets - \brief Read a MDC packet -*/ -static int parse_mdc(ops_region_t *region, ops_parse_info_t *pinfo) - { - ops_parser_content_t content; - - if (!limited_read((unsigned char *)&C.mdc,OPS_SHA1_HASH_SIZE,region,pinfo)) - return 0; - - CBP(pinfo,OPS_PTAG_CT_MDC,&content); - - return 1; - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse one packet. - * - * This function parses the packet tag. It computes the value of the - * content tag and then calls the appropriate function to handle the - * content. - * - * \param *pinfo How to parse - * \param *pktlen On return, will contain number of bytes in packet - * \return 1 on success, 0 on error, -1 on EOF */ -static int ops_parse_one_packet(ops_parse_info_t *pinfo, - unsigned long *pktlen) - { - unsigned char ptag[1]; - ops_parser_content_t content; - int r; - ops_region_t region; - ops_boolean_t indeterminate=ops_false; - - C.ptag.position=pinfo->rinfo.position; - - r=base_read(ptag,1,pinfo); - - // errors in the base read are effectively EOF. - if(r <= 0) - return -1; - - *pktlen=0; - - if(!(*ptag&OPS_PTAG_ALWAYS_SET)) - { - C.error.error="Format error (ptag bit not set)"; - CBP(pinfo,OPS_PARSER_ERROR,&content); - OPS_ERROR(&pinfo->errors, OPS_E_P_UNKNOWN_TAG, C.error.error); - return 0; - } - C.ptag.new_format=!!(*ptag&OPS_PTAG_NEW_FORMAT); - if(C.ptag.new_format) - { - C.ptag.content_tag=*ptag&OPS_PTAG_NF_CONTENT_TAG_MASK; - C.ptag.length_type=0; - if(!read_new_length(&C.ptag.length,pinfo)) - return 0; - - } - else - { - ops_boolean_t rb = ops_false; - - C.ptag.content_tag=(*ptag&OPS_PTAG_OF_CONTENT_TAG_MASK) - >> OPS_PTAG_OF_CONTENT_TAG_SHIFT; - C.ptag.length_type=*ptag&OPS_PTAG_OF_LENGTH_TYPE_MASK; - switch(C.ptag.length_type) - { - case OPS_PTAG_OF_LT_ONE_BYTE: - rb=_read_scalar(&C.ptag.length,1,pinfo); - break; - - case OPS_PTAG_OF_LT_TWO_BYTE: - rb=_read_scalar(&C.ptag.length,2,pinfo); - break; - - case OPS_PTAG_OF_LT_FOUR_BYTE: - rb=_read_scalar(&C.ptag.length,4,pinfo); - break; - - case OPS_PTAG_OF_LT_INDETERMINATE: - C.ptag.length=0; - indeterminate=ops_true; - rb=ops_true; - break; - } - if(!rb) - { - OPS_ERROR(&pinfo->errors, OPS_E_P, "Cannot read tag length"); - return 0; - } - } - - CBP(pinfo,OPS_PARSER_PTAG,&content); - - ops_init_subregion(®ion,NULL); - region.length=C.ptag.length; - region.indeterminate=indeterminate; - switch(C.ptag.content_tag) - { - case OPS_PTAG_CT_SIGNATURE: - r=parse_signature(®ion,pinfo); - break; - - case OPS_PTAG_CT_PUBLIC_KEY: - case OPS_PTAG_CT_PUBLIC_SUBKEY: - r=parse_public_key(C.ptag.content_tag,®ion,pinfo); - break; - - case OPS_PTAG_CT_TRUST: - r=parse_trust(®ion, pinfo); - break; - - case OPS_PTAG_CT_USER_ID: - r=parse_user_id(®ion,pinfo); - break; - - case OPS_PTAG_CT_COMPRESSED: - r=parse_compressed(®ion,pinfo); - break; - - case OPS_PTAG_CT_ONE_PASS_SIGNATURE: - r=parse_one_pass(®ion,pinfo); - break; - - case OPS_PTAG_CT_LITERAL_DATA: - r=parse_literal_data(®ion,pinfo); - break; - - case OPS_PTAG_CT_USER_ATTRIBUTE: - r=parse_user_attribute(®ion,pinfo); - break; - - case OPS_PTAG_CT_SECRET_KEY: - r=parse_secret_key(®ion,pinfo); - break; - - case OPS_PTAG_CT_SECRET_SUBKEY: - r=parse_secret_key(®ion,pinfo); - break; - - case OPS_PTAG_CT_PK_SESSION_KEY: - r=parse_pk_session_key(®ion,pinfo); - break; - - case OPS_PTAG_CT_SE_DATA: - r=parse_se_data(®ion,pinfo); - break; - - case OPS_PTAG_CT_SE_IP_DATA: - r=parse_se_ip_data(®ion,pinfo); - break; - - case OPS_PTAG_CT_MDC: - r=parse_mdc(®ion, pinfo); - break; - - default: - OPS_ERROR_1(&pinfo->errors,OPS_E_P_UNKNOWN_TAG, - "Unknown content tag 0x%x", C.ptag.content_tag); - r=0; - } - - /* Ensure that the entire packet has been consumed */ - - if(region.length != region.length_read && !region.indeterminate) - if(!consume_packet(®ion,pinfo,ops_false)) - r=-1; - - // also consume it if there's been an error? - // \todo decide what to do about an error on an - // indeterminate packet - if (r==0) - { - if (!consume_packet(®ion,pinfo,ops_false)) - r=-1; - } - - /* set pktlen */ - - *pktlen=pinfo->rinfo.alength; - - /* do callback on entire packet, if desired and there was no error */ - - if(r > 0 && pinfo->rinfo.accumulate) - { - C.packet.length=pinfo->rinfo.alength; - C.packet.raw=pinfo->rinfo.accumulated; - - CBP(pinfo,OPS_PARSER_PACKET_END,&content); - //free(pinfo->rinfo.accumulated); - pinfo->rinfo.accumulated=NULL; - pinfo->rinfo.asize=0; - } - else - C.packet.raw = NULL ; - - pinfo->rinfo.alength=0; - - if(r < 0) - return -1; - - return r ? 1 : 0; - } - -/** - * \ingroup Core_ReadPackets - * - * \brief Parse packets from an input stream until EOF or error. - * - * \details Setup the necessary parsing configuration in "pinfo" before calling ops_parse(). - * - * That information includes : - * - * - a "reader" function to be used to get the data to be parsed - * - * - a "callback" function to be called when this library has identified - * a parseable object within the data - * - * - whether the calling function wants the signature subpackets returned raw, parsed or not at all. - * - * After returning, pinfo->errors holds any errors encountered while parsing. - * - * \param pinfo Parsing configuration - * \return 1 on success in all packets, 0 on error in any packet - * - * \sa CoreAPI Overview - * - * \sa ops_print_errors(), ops_parse_and_print_errors() - * - * Example code - * \code -ops_parse_cb_t* example_callback(); -void example() - { - int fd=0; - ops_parse_info_t *pinfo=NULL; - char *filename="pubring.gpg"; - - // setup pinfo to read from file with example callback - fd=ops_setup_file_read(&pinfo, filename, NULL, example_callback, ops_false); - - // specify how we handle signature subpackets - ops_parse_options(pinfo, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED); - - if (!ops_parse(pinfo)) - ops_print_errors(pinfo->errors); - - ops_teardown_file_read(pinfo,fd); - } - * \endcode - */ - -int ops_parse(ops_parse_info_t *pinfo,ops_boolean_t limit_packets) -{ - int r; - unsigned long pktlen; - int n_packets = 0 ; - - do - // Parse until we get a return code of 0 (error) or -1 (EOF) - { - r=ops_parse_one_packet(pinfo,&pktlen); - - if(++n_packets > 500 && limit_packets) - { - fprintf(stderr,"More than 500 packets parsed in a row. This is likely to be a buggy certificate.") ; - return 0 ; - } - } while (r > 0); - - return pinfo->errors ? 0 : 1; - //return r == -1 ? 0 : 1; -} - -/** -\ingroup Core_ReadPackets -\brief Parse packets and print any errors - * \param pinfo Parsing configuration - * \return 1 on success in all packets, 0 on error in any packet - * \sa CoreAPI Overview - * \sa ops_parse() -*/ - -int ops_parse_and_print_errors(ops_parse_info_t *pinfo) -{ - ops_parse(pinfo,ops_false); - ops_print_errors(pinfo->errors); - return pinfo->errors ? 0 : 1; -} - -/** - * \ingroup Core_ReadPackets - * - * \brief Specifies whether one or more signature - * subpacket types should be returned parsed; or raw; or ignored. - * - * \param pinfo Pointer to previously allocated structure - * \param tag Packet tag. OPS_PTAG_SS_ALL for all SS tags; or one individual signature subpacket tag - * \param type Parse type - * \todo Make all packet types optional, not just subpackets */ -void ops_parse_options(ops_parse_info_t *pinfo, - ops_content_tag_t tag, - ops_parse_type_t type) -{ - int t8,t7; - - if(tag == OPS_PTAG_SS_ALL) - { - int n; - - for(n=0 ; n < 256 ; ++n) - ops_parse_options(pinfo,OPS_PTAG_SIGNATURE_SUBPACKET_BASE+n, - type); - return; - } - - if(!(tag >= OPS_PTAG_SIGNATURE_SUBPACKET_BASE && tag <= OPS_PTAG_SIGNATURE_SUBPACKET_BASE+NTAGS-1)) // ASSERT(tag >= OPS_PTAG_SIGNATURE_SUBPACKET_BASE && tag <= OPS_PTAG_SIGNATURE_SUBPACKET_BASE+NTAGS-1) - { - fprintf(stderr,"ops_parse_options: format error in options. Will not be parsed. Correct your code!\n") ; - return ; - } - - t8=(tag-OPS_PTAG_SIGNATURE_SUBPACKET_BASE)/8; - t7=1 << ((tag-OPS_PTAG_SIGNATURE_SUBPACKET_BASE)&7); - switch(type) - { - case OPS_PARSE_RAW: - pinfo->ss_raw[t8] |= t7; - pinfo->ss_parsed[t8] &= ~t7; - break; - - case OPS_PARSE_PARSED: - pinfo->ss_raw[t8] &= ~t7; - pinfo->ss_parsed[t8] |= t7; - break; - - case OPS_PARSE_IGNORE: - pinfo->ss_raw[t8] &= ~t7; - pinfo->ss_parsed[t8] &= ~t7; - break; - } -} - -/** -\ingroup Core_ReadPackets -\brief Creates a new zero-ed ops_parse_info_t struct -\sa ops_parse_info_delete() -*/ -ops_parse_info_t *ops_parse_info_new(void) - { return ops_mallocz(sizeof(ops_parse_info_t)); } - -/** -\ingroup Core_ReadPackets -\brief Free ops_parse_info_t struct and its contents -\sa ops_parse_info_new() -*/ -void ops_parse_info_delete(ops_parse_info_t *pinfo) - { - ops_parse_cb_info_t *cbinfo,*next; - - for(cbinfo=pinfo->cbinfo.next ; cbinfo ; cbinfo=next) - { - next=cbinfo->next; - free(cbinfo); - } - if(pinfo->rinfo.destroyer) - pinfo->rinfo.destroyer(&pinfo->rinfo); - ops_free_errors(pinfo->errors); - if(pinfo->rinfo.accumulated) - free(pinfo->rinfo.accumulated); - free(pinfo); - } - -/** -\ingroup Core_ReadPackets -\brief Returns the parse_info's reader_info -\return Pointer to the reader_info inside the parse_info -*/ -ops_reader_info_t *ops_parse_get_rinfo(ops_parse_info_t *pinfo) - { return &pinfo->rinfo; } - -/** -\ingroup Core_ReadPackets -\brief Sets the parse_info's callback -This is used when adding the first callback in a stack of callbacks. -\sa ops_parse_cb_push() -*/ - -void ops_parse_cb_set(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg) - { - pinfo->cbinfo.cb=cb; - pinfo->cbinfo.arg=arg; - pinfo->cbinfo.errors=&pinfo->errors; - } - -/** -\ingroup Core_ReadPackets -\brief Adds a further callback to a stack of callbacks -\sa ops_parse_cb_set() -*/ -void ops_parse_cb_push(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg) - { - ops_parse_cb_info_t *cbinfo=malloc(sizeof *cbinfo); - - *cbinfo=pinfo->cbinfo; - pinfo->cbinfo.next=cbinfo; - ops_parse_cb_set(pinfo,cb,arg); - } - -/** -\ingroup Core_ReadPackets -\brief Returns callback's arg -*/ -void *ops_parse_cb_get_arg(ops_parse_cb_info_t *cbinfo) - { return cbinfo->arg; } - -/** -\ingroup Core_ReadPackets -\brief Returns callback's errors -*/ -void *ops_parse_cb_get_errors(ops_parse_cb_info_t *cbinfo) - { return cbinfo->errors; } - -/** -\ingroup Core_ReadPackets -\brief Calls the parse_cb_info's callback if present -\return Return value from callback, if present; else OPS_FINISHED -*/ -ops_parse_cb_return_t ops_parse_cb(const ops_parser_content_t *content, - ops_parse_cb_info_t *cbinfo) - { - if(cbinfo->cb) - return cbinfo->cb(content,cbinfo); - else - return OPS_FINISHED; - } - -/** -\ingroup Core_ReadPackets -\brief Calls the next callback in the stack -\return Return value from callback -*/ -ops_parse_cb_return_t ops_parse_stacked_cb(const ops_parser_content_t *content, - ops_parse_cb_info_t *cbinfo) - { return ops_parse_cb(content,cbinfo->next); } - -/** -\ingroup Core_ReadPackets -\brief Returns the parse_info's errors -\return parse_info's errors -*/ -ops_error_t *ops_parse_info_get_errors(ops_parse_info_t *pinfo) - { return pinfo->errors; } - -ops_crypt_t *ops_parse_get_decrypt(ops_parse_info_t *pinfo) - { - if(pinfo->decrypt.algorithm) - return &pinfo->decrypt; - return NULL; - } - -// XXX: this could be improved by sharing all hashes that are the -// same, then duping them just before checking the signature. -void ops_parse_hash_init(ops_parse_info_t *pinfo,ops_hash_algorithm_t type, - const unsigned char *keyid) - { - ops_parse_hash_info_t *hash; - - pinfo->hashes=realloc(pinfo->hashes, - (pinfo->nhashes+1)*sizeof *pinfo->hashes); - hash=&pinfo->hashes[pinfo->nhashes++]; - - ops_hash_any(&hash->hash,type); - hash->hash.init(&hash->hash); - memcpy(hash->keyid,keyid,sizeof hash->keyid); - } - -void ops_parse_hash_data(ops_parse_info_t *pinfo,const void *data, - size_t length) - { - size_t n; - - for(n=0 ; n < pinfo->nhashes ; ++n) - pinfo->hashes[n].hash.add(&pinfo->hashes[n].hash,data,length); - } - -ops_hash_t *ops_parse_hash_find(ops_parse_info_t *pinfo, - const unsigned char keyid[OPS_KEY_ID_SIZE]) - { - size_t n; - - for(n=0 ; n < pinfo->nhashes ; ++n) - if(!memcmp(pinfo->hashes[n].keyid,keyid,OPS_KEY_ID_SIZE)) - return &pinfo->hashes[n].hash; - return NULL; - } - -/* vim:set textwidth=120: */ -/* vim:set ts=8: */ diff --git a/openpgpsdk/src/openpgpsdk/packet-parse.h b/openpgpsdk/src/openpgpsdk/packet-parse.h deleted file mode 100644 index fe65060c0..000000000 --- a/openpgpsdk/src/openpgpsdk/packet-parse.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * Parser for OpenPGP packets - headers. - */ - -#ifndef OPS_PACKET_PARSE_H -#define OPS_PACKET_PARSE_H - -#include "types.h" -#include "packet.h" -#include "lists.h" - -/** ops_region_t */ -typedef struct ops_region - { - struct ops_region *parent; - unsigned length; - unsigned length_read; - unsigned last_read; /*!< length of last read, only valid in deepest child */ - ops_boolean_t indeterminate:1; - } ops_region_t; - -void ops_init_subregion(ops_region_t *subregion,ops_region_t *region); - -#if 0 -/** Return values for reader functions e.g. ops_packet_reader_t() */ -enum ops_reader_ret_t - { - OPS_R_OK =0, /*!< success */ - OPS_R_EOF =1, /*!< reached end of file, no data has been returned */ - OPS_R_EARLY_EOF =2, /*!< could not read the requested - number of bytes and either - OPS_RETURN_LENGTH was not set and at - least 1 byte was read, or there was - an abnormal end to the file (or - armoured block) */ - OPS_R_PARTIAL_READ =3, /*!< if OPS_RETURN_LENGTH is set and - the buffer was not filled */ - OPS_R_ERROR =4, /*!< if there was an error reading */ - }; -#endif - -/** ops_parse_callback_return_t */ -typedef enum - { - OPS_RELEASE_MEMORY, - OPS_KEEP_MEMORY, - OPS_FINISHED - } ops_parse_cb_return_t; - -typedef struct ops_parse_cb_info ops_parse_cb_info_t; - -typedef ops_parse_cb_return_t -ops_parse_cb_t(const ops_parser_content_t *content, - ops_parse_cb_info_t *cbinfo); - -typedef struct ops_parse_info ops_parse_info_t; -typedef struct ops_reader_info ops_reader_info_t; -typedef struct ops_crypt_info ops_crypt_info_t; - -/* - A reader MUST read at least one byte if it can, and should read up - to the number asked for. Whether it reads more for efficiency is - its own decision, but if it is a stacked reader it should never - read more than the length of the region it operates in (which it - would have to be given when it is stacked). - - If a read is short because of EOF, then it should return the short - read (obviously this will be zero on the second attempt, if not the - first). Because a reader is not obliged to do a full read, only a - zero return can be taken as an indication of EOF. - - If there is an error, then the callback should be notified, the - error stacked, and -1 should be returned. - - Note that although length is a size_t, a reader will never be asked - to read more than INT_MAX in one go. - - */ - -typedef int ops_reader_t(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo); - -typedef void ops_reader_destroyer_t(ops_reader_info_t *rinfo); - -ops_parse_info_t *ops_parse_info_new(void); -void ops_parse_info_delete(ops_parse_info_t *pinfo); -ops_error_t *ops_parse_info_get_errors(ops_parse_info_t *pinfo); -ops_crypt_t *ops_parse_get_decrypt(ops_parse_info_t *pinfo); - -void ops_parse_cb_set(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg); -void ops_parse_cb_push(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg); -void *ops_parse_cb_get_arg(ops_parse_cb_info_t *cbinfo); -void *ops_parse_cb_get_errors(ops_parse_cb_info_t *cbinfo); -void ops_reader_set(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg); -void ops_reader_push(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg); -void ops_reader_pop(ops_parse_info_t *pinfo); -void *ops_reader_get_arg_from_pinfo(ops_parse_info_t *pinfo); - -void *ops_reader_get_arg(ops_reader_info_t *rinfo); - -ops_parse_cb_return_t ops_parse_cb(const ops_parser_content_t *content, - ops_parse_cb_info_t *cbinfo); -ops_parse_cb_return_t ops_parse_stacked_cb(const ops_parser_content_t *content, - ops_parse_cb_info_t *cbinfo); -ops_reader_info_t *ops_parse_get_rinfo(ops_parse_info_t *pinfo); - -int ops_parse(ops_parse_info_t *parse_info,ops_boolean_t limit_packets); -int ops_parse_and_print_errors(ops_parse_info_t *parse_info); -int ops_parse_and_save_errs(ops_parse_info_t *parse_info,ops_ulong_list_t *errs); -int ops_parse_errs(ops_parse_info_t *parse_info,ops_ulong_list_t *errs); - -void ops_parse_and_validate(ops_parse_info_t *parse_info); - -void ops_parse_options(ops_parse_info_t *pinfo,ops_content_tag_t tag, - ops_parse_type_t type); - -ops_boolean_t ops_limited_read(unsigned char *dest,size_t length, - ops_region_t *region,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo); -ops_boolean_t ops_stacked_limited_read(void *dest,unsigned length, - ops_region_t *region, - ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo); -void ops_parse_hash_init(ops_parse_info_t *pinfo,ops_hash_algorithm_t type, - const unsigned char *keyid); -void ops_parse_hash_data(ops_parse_info_t *pinfo,const void *data, - size_t length); -void ops_parse_hash_finish(ops_parse_info_t *pinfo); -ops_hash_t *ops_parse_hash_find(ops_parse_info_t *pinfo, - const unsigned char keyid[OPS_KEY_ID_SIZE]); - -ops_reader_t ops_stacked_read; - -/* vim:set textwidth=120: */ -/* vim:set ts=8: */ - - -#endif diff --git a/openpgpsdk/src/openpgpsdk/packet-print.c b/openpgpsdk/src/openpgpsdk/packet-print.c deleted file mode 100644 index 012531aab..000000000 --- a/openpgpsdk/src/openpgpsdk/packet-print.c +++ /dev/null @@ -1,1836 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/*! \file - \brief Standard API print functions -*/ - -#include -#include -#include "openpgpsdk/crypto.h" -#include "openpgpsdk/keyring.h" -#include "keyring_local.h" -#include "parse_local.h" -#include "openpgpsdk/packet-show.h" -#include "openpgpsdk/util.h" -#include "openpgpsdk/std_print.h" -#include "openpgpsdk/readerwriter.h" -#include "openpgpsdk/armour.h" - -static int indent=0; - -void print_bn( const char *name, - const BIGNUM *bn); -static void print_hex(const unsigned char *src, - size_t length); -static void print_hexdump(const char *name, - const unsigned char *data, - unsigned int len); -static void print_hexdump_data(const char *name, - const unsigned char *data, - unsigned int len); -static void print_indent(); -static void print_name(const char *name); -static void print_string_and_value(char *name, - const char *str, - unsigned char value); -static void print_tagname(const char *str); -static void print_time( char *name, - time_t time); -static void print_time_short(time_t time); -static void print_unsigned_int(char *name, - unsigned int val); -static void showtime(const char *name,time_t t); -static void showtime_short(time_t t); - -/** - \ingroup Core_Print - - Prints a public key in succinct detail - - \param key Ptr to public key -*/ - -void -ops_print_public_keydata(const ops_keydata_t *key) - { - printf("pub "); - - ops_show_pka(key->key.pkey.algorithm); - printf(" "); - - hexdump(key->key_id, OPS_KEY_ID_SIZE); - printf(" "); - - print_time_short(key->key.pkey.creation_time); - printf(" "); - - if (key->nuids==1) - { - // print on same line as other info - printf ("%s\n", key->uids[0].user_id); - } - else - { - // print all uids on separate line - unsigned int i; - printf("\n"); - for (i=0; inuids; i++) - { - printf("uid %s\n",key->uids[i].user_id); - } - } - } - -/** -\ingroup Core_Print -\param pkey -*/ -void -ops_print_public_key(const ops_public_key_t *pkey) - { - printf("------- PUBLIC KEY ------\n"); - print_unsigned_int("Version",pkey->version); - print_time("Creation Time", pkey->creation_time); - if(pkey->version == OPS_V3) - print_unsigned_int("Days Valid",pkey->days_valid); - - print_string_and_value("Algorithm",ops_show_pka(pkey->algorithm), - pkey->algorithm); - - switch(pkey->algorithm) - { - case OPS_PKA_DSA: - print_bn("p",pkey->key.dsa.p); - print_bn("q",pkey->key.dsa.q); - print_bn("g",pkey->key.dsa.g); - print_bn("y",pkey->key.dsa.y); - break; - - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - print_bn("n",pkey->key.rsa.n); - print_bn("e",pkey->key.rsa.e); - break; - - case OPS_PKA_ELGAMAL: - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - print_bn("p",pkey->key.elgamal.p); - print_bn("g",pkey->key.elgamal.g); - print_bn("y",pkey->key.elgamal.y); - break; - - default: - assert(0); - } - - printf("------- end of PUBLIC KEY ------\n"); - } - -/** - \ingroup Core_Print - - Prints a public key in full detail - - \param key Ptr to public key -*/ - -void -ops_print_public_keydata_verbose(const ops_keydata_t *key) - { - const ops_public_key_t* pkey=&key->key.pkey; - - ops_print_public_key(pkey); - } - -/** - \ingroup Core_Print - - Prints a secret key - - \param key Ptr to public key -*/ - -void -ops_print_secret_keydata(const ops_keydata_t *key) - { - printf("sec "); - ops_show_pka(key->key.pkey.algorithm); - printf(" "); - - hexdump(key->key_id, OPS_KEY_ID_SIZE); - printf(" "); - - print_time_short(key->key.pkey.creation_time); - printf(" "); - - if (key->nuids==1) - { - // print on same line as other info - printf ("%s\n", key->uids[0].user_id); - } - else - { - // print all uids on separate line - unsigned int i; - printf("\n"); - for (i=0; inuids; i++) - { - printf("uid %s\n",key->uids[i].user_id); - } - } - } - -/* -void -ops_print_secret_key_verbose(const ops_secret_key_t* skey) - { - if(key->type == OPS_PTAG_CT_SECRET_KEY) - print_tagname("SECRET_KEY"); - else - print_tagname("ENCRYPTED_SECRET_KEY"); - ops_print_secret_key(key->type,skey); - } -*/ - -/** -\ingroup Core_Print -\param type -\param skey -*/ -void -ops_print_secret_key_verbose(const ops_content_tag_t type, const ops_secret_key_t* skey) - { - printf("------- SECRET KEY or ENCRYPTED SECRET KEY ------\n"); - if(type == OPS_PTAG_CT_SECRET_KEY) - print_tagname("SECRET_KEY"); - else - print_tagname("ENCRYPTED_SECRET_KEY"); - // ops_print_public_key(key); - printf("S2K Usage: %d\n",skey->s2k_usage); - if(skey->s2k_usage != OPS_S2KU_NONE) - { - printf("S2K Specifier: %d\n",skey->s2k_specifier); - printf("Symmetric algorithm: %d (%s)\n",skey->algorithm, - ops_show_symmetric_algorithm(skey->algorithm)); - printf("Hash algorithm: %d (%s)\n",skey->hash_algorithm, - ops_show_hash_algorithm(skey->hash_algorithm)); - if(skey->s2k_specifier != OPS_S2KS_SIMPLE) - print_hexdump("Salt",skey->salt,sizeof skey->salt); - if(skey->s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED) - printf("Octet count: %d\n",skey->octet_count); - print_hexdump("IV",skey->iv,ops_block_size(skey->algorithm)); - } - - /* no more set if encrypted */ - if(type == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) - return; - - switch(skey->public_key.algorithm) - { - case OPS_PKA_RSA: - print_bn("d",skey->key.rsa.d); - print_bn("p",skey->key.rsa.p); - print_bn("q",skey->key.rsa.q); - print_bn("u",skey->key.rsa.u); - break; - - case OPS_PKA_DSA: - print_bn("x",skey->key.dsa.x); - break; - - default: - assert(0); - } - - if(skey->s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED) - print_hexdump("Checkhash",skey->checkhash,OPS_CHECKHASH_SIZE); - else - printf("Checksum: %04x\n",skey->checksum); - - printf("------- end of SECRET KEY or ENCRYPTED SECRET KEY ------\n"); - } - -/** -\ingroup Core_Print -\param key -*/ -void -ops_print_secret_keydata_verbose(const ops_keydata_t *key) - { - const ops_secret_key_t* skey=&key->key.skey; - ops_print_public_keydata(key); - ops_print_secret_key_verbose(key->type,skey); - } - -// static functions - -static void print_unsigned_int(char *name, unsigned int val) - { - print_name(name); - printf("%d\n", val); - } - -static void print_time( char *name, time_t time) - { - print_indent(); - printf("%s: ",name); - showtime("time",time); - printf("\n"); - } - -static void print_time_short(time_t time) - { - showtime_short(time); - } - -static void print_string_and_value(char *name,const char *str, - unsigned char value) - { - print_name(name); - - printf("%s", str); - printf(" (0x%x)", value); - printf("\n"); - } - -void print_bn( const char *name, const BIGNUM *bn) - { - print_indent(); - printf("%s=",name); - if(bn) - { - BN_print_fp(stdout,bn); - putchar('\n'); - } - else - puts("(unset)"); - } - -static void print_tagname(const char *str) - { - print_indent(); - printf("%s packet\n", str); - } - -static void print_hexdump(const char *name, - const unsigned char *data, - unsigned int len) - { - print_name(name); - - printf("len=%d, data=0x", len); - print_hex(data,len); - printf("\n"); - } - -static void print_hexdump_data(const char *name, - const unsigned char *data, - unsigned int len) - { - print_name(name); - - printf("0x"); - print_hex(data,len); - printf("\n"); - } - -static void print_data(const char *name,const ops_data_t *data) - { - print_hexdump(name,data->contents,data->len); - } - - -static void print_name(const char *name) - { - print_indent(); - if(name) - printf("%s: ",name); - } - -static void print_indent() - { - int i=0; - - for(i=0 ; i < indent ; i++) - printf(" "); - } - -/* printhex is now print_hex for consistency */ -static void print_hex(const unsigned char *src,size_t length) - { - while(length--) - printf("%02X",*src++); - } - -static void showtime(const char *name,time_t t) - { - printf("%s=" TIME_T_FMT " (%.24s)",name,t,ctime(&t)); - } -static void showtime_short(time_t t) - { - struct tm* tm; - /* - const int maxbuf=512; - char buf[maxbuf+1]; - buf[maxbuf]='\0'; - // this needs to be tm struct - strftime(buf,maxbuf,"%F",&t); - printf(buf); - */ - tm=gmtime(&t); - printf ("%04d-%02d-%02d", tm->tm_year+1900, tm->tm_mon, tm->tm_mday); - } - - -static void print_packet_hex(const ops_packet_t *packet) - { - unsigned char *cur; - int i; - int rem; - int blksz=4; - - printf("\nhexdump of packet contents follows:\n"); - - - for (i=1,cur=packet->raw; cur<(packet->raw+packet->length); cur+=blksz,i++) - { - rem = packet->raw+packet->length-cur; - hexdump(cur,rem<=blksz ? rem : blksz); - printf(" "); - if (!(i%8)) - printf("\n"); - - } - - printf("\n"); - } - -static void print_escaped(const unsigned char *data,size_t length) - { - while(length-- > 0) - { - if((*data >= 0x20 && *data < 0x7f && *data != '%') || *data == '\n') - putchar(*data); - else - printf("%%%02x",*data); - ++data; - } - } - -static void print_string(const char *name,const char *str) - { - print_name(name); - print_escaped((unsigned char *)str,strlen(str)); - putchar('\n'); - } - -static void print_utf8_string(const char *name,const unsigned char *str) - { - // \todo Do this better for non-English character sets - print_string(name,(const char *)str); - } - -static void print_duration(char *name, time_t time) - { - int mins, hours, days, years; - - print_indent(); - printf("%s: ",name); - printf("duration " TIME_T_FMT " seconds",time); - - mins=time/60; - hours=mins/60; - days=hours/24; - years=days/365; - - printf(" (approx. "); - if (years) - printf("%d %s",years,years==1?"year":"years"); - else if (days) - printf("%d %s",days,days==1?"day":"days"); - else if (hours) - printf("%d %s", hours, hours==1?"hour":"hours"); - - printf(")"); - printf("\n"); - } - -static void print_boolean(const char *name, unsigned char bool) - { - print_name(name); - - if(bool) - printf("Yes"); - else - printf("No"); - printf("\n"); - } - -static void print_text_breakdown( ops_text_t *text) - { - unsigned i; - char *prefix=".. "; - - /* these were recognised */ - - for(i=0 ; iknown.used ; i++) - { - print_indent(); - fputs(prefix,stdout); - printf("%s\n",text->known.strings[i]); - } - - /* these were not recognised. the strings will contain the hex value - of the unrecognised value in string format - see process_octet_str() - */ - - if(text->unknown.used) - { - printf("\n"); - print_indent(); - printf("Not Recognised: "); - } - for( i=0; i < text->unknown.used; i++) - { - print_indent(); - fputs(prefix,stdout); - printf("%s\n",text->unknown.strings[i]); - } - - } - -static void print_headers(const ops_headers_t *headers) - { - unsigned n; - - for(n=0 ; n < headers->nheaders ; ++n) - printf("%s=%s\n",headers->headers[n].key,headers->headers[n].value); - } - -static void print_block(const char *name,const unsigned char *str, - size_t length) - { - int o=length; - - print_indent(); - printf(">>>>> %s >>>>>\n",name); - - print_indent(); - for( ; length > 0 ; --length) - { - if(*str >= 0x20 && *str < 0x7f && *str != '%') - putchar(*str); - else if(*str == '\n') - { - putchar(*str); - print_indent(); - } - else - printf("%%%02x",*str); - ++str; - } - if(o && str[-1] != '\n') - { - putchar('\n'); - print_indent(); - fputs("[no newline]",stdout); - } - else - print_indent(); - printf("<<<<< %s <<<<<\n",name); - } - -/** -\ingroup Core_Print -\param tag -\param key -*/ -void ops_print_pk_session_key(ops_content_tag_t tag, - const ops_pk_session_key_t *key) - { - if(tag == OPS_PTAG_CT_PK_SESSION_KEY) - print_tagname("PUBLIC KEY SESSION KEY"); - else - print_tagname("ENCRYPTED PUBLIC KEY SESSION KEY"); - - printf("Version: %d\n",key->version); - print_hexdump("Key ID",key->key_id,sizeof key->key_id); - printf("Algorithm: %d (%s)\n",key->algorithm, - ops_show_pka(key->algorithm)); - switch(key->algorithm) - { - case OPS_PKA_RSA: - print_bn("encrypted_m",key->parameters.rsa.encrypted_m); - break; - - case OPS_PKA_ELGAMAL: - print_bn("g_to_k",key->parameters.elgamal.g_to_k); - print_bn("encrypted_m",key->parameters.elgamal.encrypted_m); - break; - - default: - assert(0); - } - - if(tag != OPS_PTAG_CT_PK_SESSION_KEY) - return; - - printf("Symmetric algorithm: %d (%s)\n",key->symmetric_algorithm, - ops_show_symmetric_algorithm(key->symmetric_algorithm)); - print_hexdump("Key",key->key,ops_key_size(key->symmetric_algorithm)); - printf("Checksum: %04x\n",key->checksum); - } - -static void start_subpacket(unsigned type) - { - indent++; - print_indent(); - printf("-- %s (type 0x%02x)\n", - ops_show_ss_type(type), - type-OPS_PTAG_SIGNATURE_SUBPACKET_BASE); - } - -static void end_subpacket() - { - indent--; - } - -/** -\ingroup Core_Print -\param content_ -*/ -int ops_print_packet(const ops_parser_content_t *content_) - { - const ops_parser_content_union_t *content=&content_->content; - ops_text_t *text; - const char *str; - static ops_boolean_t unarmoured; - - if(unarmoured && content_->tag != OPS_PTAG_CT_UNARMOURED_TEXT) - { - unarmoured=ops_false; - puts("UNARMOURED TEXT ends"); - } - - if (content_->tag==OPS_PARSER_PTAG) - { - printf("=> OPS_PARSER_PTAG: %s\n", ops_show_packet_tag(content->ptag.content_tag)); - } - else - { - printf("=> %s\n", ops_show_packet_tag(content_->tag)); - } - - switch(content_->tag) - { - case OPS_PARSER_ERROR: - printf("parse error: %s\n",content->error.error); - break; - - case OPS_PARSER_ERRCODE: - printf("parse error: %s\n", - ops_errcode(content->errcode.errcode)); - break; - - case OPS_PARSER_PACKET_END: - print_packet_hex(&content->packet); - break; - - case OPS_PARSER_PTAG: - if(content->ptag.content_tag == OPS_PTAG_CT_PUBLIC_KEY) - { - indent=0; - printf("\n*** NEXT KEY ***\n"); - } - - printf("\n"); - print_indent(); - printf("==== ptag new_format=%d content_tag=%d length_type=%d" - " length=0x%x (%d) position=0x%x (%d)\n",content->ptag.new_format, - content->ptag.content_tag,content->ptag.length_type, - content->ptag.length,content->ptag.length, - content->ptag.position,content->ptag.position); - print_tagname(ops_show_packet_tag(content->ptag.content_tag)); - break; - - case OPS_PTAG_CT_SE_DATA_HEADER: - print_tagname("SYMMETRIC ENCRYPTED DATA"); - break; - - case OPS_PTAG_CT_SE_IP_DATA_HEADER: - print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER"); - printf("Version: %d\n",content->se_ip_data_header.version); - break; - - case OPS_PTAG_CT_SE_IP_DATA_BODY: - print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY"); - printf(" data body length=%d\n", - content->se_data_body.length); - printf(" data="); - hexdump(content->se_data_body.data, - content->se_data_body.length); - printf("\n"); - break; - - case OPS_PTAG_CT_PUBLIC_KEY: - case OPS_PTAG_CT_PUBLIC_SUBKEY: - if (content_->tag == OPS_PTAG_CT_PUBLIC_KEY) - print_tagname("PUBLIC KEY"); - else - print_tagname("PUBLIC SUBKEY"); - ops_print_public_key(&content->public_key); - break; - - case OPS_PTAG_CT_TRUST: - print_tagname("TRUST"); - print_data("Trust",&content->trust.data); - break; - - case OPS_PTAG_CT_USER_ID: - /* XXX: how do we print UTF-8? */ - print_tagname("USER ID"); - print_utf8_string("user_id",content->user_id.user_id); - break; - - case OPS_PTAG_CT_SIGNATURE: - print_tagname("SIGNATURE"); - print_indent(); - print_unsigned_int("Signature Version", - content->signature.info.version); - if (content->signature.info.creation_time_set) - print_time("Signature Creation Time", - content->signature.info.creation_time); - - print_string_and_value("Signature Type", - ops_show_sig_type(content->signature.info.type), - content->signature.info.type); - - if(content->signature.info.signer_id_set) - print_hexdump_data("Signer ID", - content->signature.info.signer_id, - sizeof content->signature.info.signer_id); - - print_string_and_value("Public Key Algorithm", - ops_show_pka(content->signature.info.key_algorithm), - content->signature.info.key_algorithm); - print_string_and_value("Hash Algorithm", - ops_show_hash_algorithm(content->signature.info.hash_algorithm), - content->signature.info.hash_algorithm); - - print_unsigned_int("Hashed data len", content->signature.info.v4_hashed_data_length); - - print_indent(); - print_hexdump_data("hash2",&content->signature.hash2[0],2); - - switch(content->signature.info.key_algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_SIGN_ONLY: - print_bn("sig",content->signature.info.signature.rsa.sig); - break; - - case OPS_PKA_DSA: - print_bn("r",content->signature.info.signature.dsa.r); - print_bn("s",content->signature.info.signature.dsa.s); - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - print_bn("r",content->signature.info.signature.elgamal.r); - print_bn("s",content->signature.info.signature.elgamal.s); - break; - - default: - assert(0); - } - - if(content->signature.hash) - printf("data hash is set\n"); - - break; - - case OPS_PTAG_CT_COMPRESSED: - print_tagname("COMPRESSED"); - print_unsigned_int("Compressed Data Type", content->compressed.type); - break; - - case OPS_PTAG_CT_ONE_PASS_SIGNATURE: - print_tagname("ONE PASS SIGNATURE"); - - print_unsigned_int("Version",content->one_pass_signature.version); - print_string_and_value("Signature Type", - ops_show_sig_type(content->one_pass_signature.sig_type), - content->one_pass_signature.sig_type); - print_string_and_value("Hash Algorithm", - ops_show_hash_algorithm(content->one_pass_signature.hash_algorithm), - content->one_pass_signature.hash_algorithm); - print_string_and_value("Public Key Algorithm", - ops_show_pka(content->one_pass_signature.key_algorithm), - content->one_pass_signature.key_algorithm); - print_hexdump_data("Signer ID", - content->one_pass_signature.keyid, - sizeof content->one_pass_signature.keyid); - - print_unsigned_int("Nested", - content->one_pass_signature.nested); - break; - - case OPS_PTAG_CT_USER_ATTRIBUTE: - print_tagname("USER ATTRIBUTE"); - print_hexdump("User Attribute", - content->user_attribute.data.contents, - content->user_attribute.data.len); - break; - - case OPS_PTAG_RAW_SS: - assert(!content_->critical); - start_subpacket(content_->tag); - print_unsigned_int("Raw Signature Subpacket: tag", - content->ss_raw.tag-OPS_PTAG_SIGNATURE_SUBPACKET_BASE); - print_hexdump("Raw Data", - content->ss_raw.raw, - content->ss_raw.length); - break; - - case OPS_PTAG_SS_CREATION_TIME: - start_subpacket(content_->tag); - print_time("Signature Creation Time",content->ss_time.time); - end_subpacket(); - break; - - case OPS_PTAG_SS_EXPIRATION_TIME: - start_subpacket(content_->tag); - print_duration("Signature Expiration Time",content->ss_time.time); - end_subpacket(); - break; - - case OPS_PTAG_SS_KEY_EXPIRATION_TIME: - start_subpacket(content_->tag); - print_duration("Key Expiration Time", content->ss_time.time); - end_subpacket(); - break; - - case OPS_PTAG_SS_TRUST: - start_subpacket(content_->tag); - print_string("Trust Signature",""); - print_unsigned_int("Level", - content->ss_trust.level); - print_unsigned_int("Amount", - content->ss_trust.amount); - end_subpacket(); - break; - - case OPS_PTAG_SS_REVOCABLE: - start_subpacket(content_->tag); - print_boolean("Revocable",content->ss_revocable.revocable); - end_subpacket(); - break; - - case OPS_PTAG_SS_REVOCATION_KEY: - start_subpacket(content_->tag); - /* not yet tested */ - printf (" revocation key: class=0x%x", - content->ss_revocation_key.clss); - if (content->ss_revocation_key.clss&0x40) - printf (" (sensitive)"); - printf (", algid=0x%x", content->ss_revocation_key.algid); - printf(", fingerprint="); - hexdump(content->ss_revocation_key.fingerprint,20); - printf("\n"); - end_subpacket(); - break; - - case OPS_PTAG_SS_ISSUER_KEY_ID: - start_subpacket(content_->tag); - print_hexdump("Issuer Key Id", &content->ss_issuer_key_id.key_id[0], - sizeof content->ss_issuer_key_id.key_id); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_SKA: - start_subpacket(content_->tag); - print_data( "Preferred Symmetric Algorithms", - &content->ss_preferred_ska.data); - - text = ops_showall_ss_preferred_ska(content->ss_preferred_ska); - print_text_breakdown(text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_PRIMARY_USER_ID: - start_subpacket(content_->tag); - print_boolean("Primary User ID", - content->ss_primary_user_id.primary_user_id); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_HASH: - start_subpacket(content_->tag); - print_data("Preferred Hash Algorithms", - &content->ss_preferred_hash.data); - - text = ops_showall_ss_preferred_hash(content->ss_preferred_hash); - print_text_breakdown(text); - ops_text_free(text); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_COMPRESSION: - start_subpacket(content_->tag); - print_data( "Preferred Compression Algorithms", - &content->ss_preferred_compression.data); - - text = ops_showall_ss_preferred_compression(content->ss_preferred_compression); - print_text_breakdown(text); - ops_text_free(text); - end_subpacket(); - break; - - case OPS_PTAG_SS_KEY_FLAGS: - start_subpacket(content_->tag); - print_data( "Key Flags", &content->ss_key_flags.data); - - text = ops_showall_ss_key_flags(content->ss_key_flags); - print_text_breakdown( text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_KEY_SERVER_PREFS: - start_subpacket(content_->tag); - print_data( "Key Server Preferences", - &content->ss_key_server_prefs.data); - - text = ops_showall_ss_key_server_prefs(content->ss_key_server_prefs); - print_text_breakdown( text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_FEATURES: - start_subpacket(content_->tag); - print_data( "Features", - &content->ss_features.data); - - text = ops_showall_ss_features(content->ss_features); - print_text_breakdown( text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_NOTATION_DATA: - start_subpacket(content_->tag); - print_indent(); - printf("Notation Data:\n"); - - indent++; - print_data( "Flags", - &content->ss_notation_data.flags); - text = ops_showall_ss_notation_data_flags(content->ss_notation_data); - print_text_breakdown( text); - ops_text_free(text); - - /* xxx - TODO: print out UTF - rachel */ - - print_data( "Name", - &content->ss_notation_data.name); - - print_data( "Value", - &content->ss_notation_data.value); - - indent--; - end_subpacket(); - break; - - case OPS_PTAG_SS_REGEXP: - start_subpacket(content_->tag); - print_hexdump("Regular Expression", - (unsigned char *)content->ss_regexp.text, - strlen(content->ss_regexp.text)); - print_string(NULL, - content->ss_regexp.text); - end_subpacket(); - break; - - case OPS_PTAG_SS_POLICY_URI: - start_subpacket(content_->tag); - print_string("Policy URL", - content->ss_policy_url.text); - end_subpacket(); - break; - - case OPS_PTAG_SS_SIGNERS_USER_ID: - start_subpacket(content_->tag); - print_utf8_string("Signer's User ID",content->ss_signers_user_id.user_id); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_KEY_SERVER: - start_subpacket(content_->tag); - print_string("Preferred Key Server", - content->ss_preferred_key_server.text); - end_subpacket(); - break; - - case OPS_PTAG_SS_EMBEDDED_SIGNATURE: - start_subpacket(content_->tag); - end_subpacket(); // \todo print out contents? - break; - - case OPS_PTAG_SS_USERDEFINED00: - case OPS_PTAG_SS_USERDEFINED01: - case OPS_PTAG_SS_USERDEFINED02: - case OPS_PTAG_SS_USERDEFINED03: - case OPS_PTAG_SS_USERDEFINED04: - case OPS_PTAG_SS_USERDEFINED05: - case OPS_PTAG_SS_USERDEFINED06: - case OPS_PTAG_SS_USERDEFINED07: - case OPS_PTAG_SS_USERDEFINED08: - case OPS_PTAG_SS_USERDEFINED09: - case OPS_PTAG_SS_USERDEFINED10: - start_subpacket(content_->tag); - print_hexdump("Internal or user-defined", - content->ss_userdefined.data.contents, - content->ss_userdefined.data.len); - end_subpacket(); - break; - - case OPS_PTAG_SS_RESERVED: - start_subpacket(content_->tag); - print_hexdump("Reserved", - content->ss_userdefined.data.contents, - content->ss_userdefined.data.len); - end_subpacket(); - break; - - case OPS_PTAG_SS_REVOCATION_REASON: - start_subpacket(content_->tag); - print_hexdump("Revocation Reason", - &content->ss_revocation_reason.code, - 1); - str=ops_show_ss_rr_code(content->ss_revocation_reason.code); - print_string(NULL,str); - /* xxx - todo : output text as UTF-8 string */ - end_subpacket(); - break; - - case OPS_PTAG_CT_LITERAL_DATA_HEADER: - print_tagname("LITERAL DATA HEADER"); - printf(" literal data header format=%c filename='%s'\n", - content->literal_data_header.format, - content->literal_data_header.filename); - showtime(" modification time", - content->literal_data_header.modification_time); - printf("\n"); - break; - - case OPS_PTAG_CT_LITERAL_DATA_BODY: - print_tagname("LITERAL DATA BODY"); - printf(" literal data body length=%d\n", - content->literal_data_body.length); - printf(" data="); - print_escaped(content->literal_data_body.data, - content->literal_data_body.length); - printf("\n"); - break; - - case OPS_PTAG_CT_SIGNATURE_HEADER: - print_tagname("SIGNATURE"); - print_indent(); - print_unsigned_int("Signature Version", - content->signature.info.version); - if(content->signature.info.creation_time_set) - print_time("Signature Creation Time", content->signature.info.creation_time); - - print_string_and_value("Signature Type", - ops_show_sig_type(content->signature.info.type), - content->signature.info.type); - - if(content->signature.info.signer_id_set) - print_hexdump_data("Signer ID", - content->signature.info.signer_id, - sizeof content->signature.info.signer_id); - - print_string_and_value("Public Key Algorithm", - ops_show_pka(content->signature.info.key_algorithm), - content->signature.info.key_algorithm); - print_string_and_value("Hash Algorithm", - ops_show_hash_algorithm(content->signature.info.hash_algorithm), - content->signature.info.hash_algorithm); - - break; - - case OPS_PTAG_CT_SIGNATURE_FOOTER: - print_indent(); - print_hexdump_data("hash2",&content->signature.hash2[0],2); - - switch(content->signature.info.key_algorithm) - { - case OPS_PKA_RSA: - print_bn("sig",content->signature.info.signature.rsa.sig); - break; - - case OPS_PKA_DSA: - print_bn("r",content->signature.info.signature.dsa.r); - print_bn("s",content->signature.info.signature.dsa.s); - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - print_bn("r",content->signature.info.signature.elgamal.r); - print_bn("s",content->signature.info.signature.elgamal.s); - break; - - case OPS_PKA_PRIVATE00: - case OPS_PKA_PRIVATE01: - case OPS_PKA_PRIVATE02: - case OPS_PKA_PRIVATE03: - case OPS_PKA_PRIVATE04: - case OPS_PKA_PRIVATE05: - case OPS_PKA_PRIVATE06: - case OPS_PKA_PRIVATE07: - case OPS_PKA_PRIVATE08: - case OPS_PKA_PRIVATE09: - case OPS_PKA_PRIVATE10: - print_data("Private/Experimental", - &content->signature.info.signature.unknown.data); - break; - - default: - assert(0); - } - break; - - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - print_tagname("OPS_PARSER_CMD_GET_SK_PASSPHRASE"); - /* - if(passphrase_prompt) - { - print_secret_key(OPS_PTAG_CT_ENCRYPTED_SECRET_KEY, - content->secret_key_passphrase.secret_key); - *content->secret_key_passphrase.passphrase=ops_get_passphrase(); - if(!**content->secret_key_passphrase.passphrase) - break; - return OPS_KEEP_MEMORY; - } - else - printf(">>> ASKED FOR PASSPHRASE <<<\n"); - */ - - break; - - case OPS_PTAG_CT_SECRET_KEY: - print_tagname("OPS_PTAG_CT_SECRET_KEY"); - ops_print_secret_key_verbose(content_->tag,&content->secret_key); - break; - - case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: - // print_secret_key(content_->tag,&content->secret_key); - print_tagname("OPS_PTAG_CT_ENCRYPTED_SECRET_KEY"); - ops_print_secret_key_verbose(content_->tag,&content->secret_key); - break; - - case OPS_PTAG_CT_ARMOUR_HEADER: - print_tagname("ARMOUR HEADER"); - print_string("type",content->armour_header.type); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER: - print_tagname("SIGNED CLEARTEXT HEADER"); - print_headers(&content->signed_cleartext_header.headers); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY: - print_tagname("SIGNED CLEARTEXT BODY"); - print_block("signed cleartext",content->signed_cleartext_body.data, - content->signed_cleartext_body.length); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: - print_tagname("SIGNED CLEARTEXT TRAILER"); - printf("hash algorithm: %d\n", - content->signed_cleartext_trailer.hash->algorithm); - printf("\n"); - break; - - case OPS_PTAG_CT_UNARMOURED_TEXT: - if(!unarmoured) - { - print_tagname("UNARMOURED TEXT"); - unarmoured=ops_true; - } - putchar('['); - print_escaped(content->unarmoured_text.data, - content->unarmoured_text.length); - putchar(']'); - break; - - case OPS_PTAG_CT_ARMOUR_TRAILER: - print_tagname("ARMOUR TRAILER"); - print_string("type",content->armour_header.type); - break; - - case OPS_PTAG_CT_PK_SESSION_KEY: - case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: - ops_print_pk_session_key(content_->tag,&content->pk_session_key); - break; - - case OPS_PARSER_CMD_GET_SECRET_KEY: - ops_print_pk_session_key(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, - content->get_secret_key.pk_session_key); - break; - - default: - print_tagname("UNKNOWN PACKET TYPE"); - fprintf(stderr,"ops_print_packet: unknown tag=%d (0x%x)\n",content_->tag, - content_->tag); - exit(1); - } - return 1; - } - -static ops_parse_cb_return_t cb_list_packets(const ops_parser_content_t * content_, ops_parse_cb_info_t *cbinfo) - { - OPS_USED(cbinfo); - - ops_print_packet(content_); -#ifdef XXX - if(unarmoured && content_->tag != OPS_PTAG_CT_UNARMOURED_TEXT) - { - unarmoured=ops_false; - puts("UNARMOURED TEXT ends"); - } - - switch(content_->tag) - { - case OPS_PARSER_ERROR: - printf("parse error: %s\n",content->error.error); - break; - - case OPS_PARSER_ERRCODE: - printf("parse error: %s\n", - ops_errcode(content->errcode.errcode)); - break; - - case OPS_PARSER_PACKET_END: - print_packet_hex(&content->packet); - break; - - case OPS_PARSER_PTAG: - if(content->ptag.content_tag == OPS_PTAG_CT_PUBLIC_KEY) - { - indent=0; - printf("\n*** NEXT KEY ***\n"); - } - - printf("\n"); - print_indent(); - printf("==== ptag new_format=%d content_tag=%d length_type=%d" - " length=0x%x (%d) position=0x%x (%d)\n",content->ptag.new_format, - content->ptag.content_tag,content->ptag.length_type, - content->ptag.length,content->ptag.length, - content->ptag.position,content->ptag.position); - print_tagname(ops_show_packet_tag(content->ptag.content_tag)); - break; - - case OPS_PTAG_CT_SE_DATA_HEADER: - print_tagname("SYMMETRIC ENCRYPTED DATA"); - break; - - case OPS_PTAG_CT_SE_IP_DATA_HEADER: - print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER"); - printf("Version: %d\n",content->se_ip_data_header.version); - break; - - case OPS_PTAG_CT_SE_IP_DATA_BODY: - print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY"); - printf(" data body length=%d\n", - content->se_data_body.length); - printf(" data="); - hexdump(content->se_data_body.data, - content->se_data_body.length); - printf("\n"); - break; - - case OPS_PTAG_CT_PUBLIC_KEY: - case OPS_PTAG_CT_PUBLIC_SUBKEY: - if (content_->tag == OPS_PTAG_CT_PUBLIC_KEY) - print_tagname("PUBLIC KEY"); - else - print_tagname("PUBLIC SUBKEY"); - - ops_print_public_key(&content->public_key); - break; - - case OPS_PTAG_CT_TRUST: - print_tagname("TRUST"); - print_data("Trust",&content->trust.data); - break; - - case OPS_PTAG_CT_USER_ID: - /* XXX: how do we print UTF-8? */ - print_tagname("USER ID"); - print_utf8_string("user_id",content->user_id.user_id); - break; - - case OPS_PTAG_CT_SIGNATURE: - print_tagname("SIGNATURE"); - print_indent(); - print_unsigned_int("Signature Version", - content->signature.info.version); - if (content->signature.info.creation_time_set) - print_time("Signature Creation Time", - content->signature.info.creation_time); - - print_string_and_value("Signature Type", - ops_show_sig_type(content->signature.info.type), - content->signature.info.type); - - if(content->signature.info.signer_id_set) - print_hexdump_data("Signer ID", - content->signature.info.signer_id, - sizeof content->signature.info.signer_id); - - print_string_and_value("Public Key Algorithm", - ops_show_pka(content->signature.info.key_algorithm), - content->signature.info.key_algorithm); - print_string_and_value("Hash Algorithm", - ops_show_hash_algorithm(content->signature.info.hash_algorithm), - content->signature.info.hash_algorithm); - print_unsigned_int("Hashed data len", content->signature.info.v4_hashed_data_length); - - print_indent(); - print_hexdump_data("hash2",&content->signature.hash2[0],2); - - switch(content->signature.info.key_algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_SIGN_ONLY: - print_bn("sig",content->signature.info.signature.rsa.sig); - break; - - case OPS_PKA_DSA: - print_bn("r",content->signature.info.signature.dsa.r); - print_bn("s",content->signature.info.signature.dsa.s); - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - print_bn("r",content->signature.info.signature.elgamal.r); - print_bn("s",content->signature.info.signature.elgamal.s); - break; - - default: - assert(0); - } - - if(content->signature.hash) - printf("data hash is set\n"); - - break; - - case OPS_PTAG_CT_COMPRESSED: - print_tagname("COMPRESSED"); - print_unsigned_int("Compressed Data Type", content->compressed.type); - break; - - case OPS_PTAG_CT_ONE_PASS_SIGNATURE: - print_tagname("ONE PASS SIGNATURE"); - - print_unsigned_int("Version",content->one_pass_signature.version); - print_string_and_value("Signature Type", - ops_show_sig_type(content->one_pass_signature.sig_type), - content->one_pass_signature.sig_type); - print_string_and_value("Hash Algorithm", - ops_show_hash_algorithm(content->one_pass_signature.hash_algorithm), - content->one_pass_signature.hash_algorithm); - print_string_and_value("Public Key Algorithm", - ops_show_pka(content->one_pass_signature.key_algorithm), - content->one_pass_signature.key_algorithm); - print_hexdump_data("Signer ID", - content->one_pass_signature.keyid, - sizeof content->one_pass_signature.keyid); - - print_unsigned_int("Nested", - content->one_pass_signature.nested); - break; - - case OPS_PTAG_CT_USER_ATTRIBUTE: - print_tagname("USER ATTRIBUTE"); - print_hexdump("User Attribute", - content->user_attribute.data.contents, - content->user_attribute.data.len); - break; - - case OPS_PTAG_RAW_SS: - assert(!content_->critical); - start_subpacket(content_->tag); - print_unsigned_int("Raw Signature Subpacket: tag", - content->ss_raw.tag-OPS_PTAG_SIGNATURE_SUBPACKET_BASE); - print_hexdump("Raw Data", - content->ss_raw.raw, - content->ss_raw.length); - break; - - case OPS_PTAG_SS_CREATION_TIME: - start_subpacket(content_->tag); - print_time("Signature Creation Time",content->ss_time.time); - end_subpacket(); - break; - - case OPS_PTAG_SS_EXPIRATION_TIME: - start_subpacket(content_->tag); - print_duration("Signature Expiration Time",content->ss_time.time); - end_subpacket(); - break; - - case OPS_PTAG_SS_KEY_EXPIRATION_TIME: - start_subpacket(content_->tag); - print_duration("Key Expiration Time", content->ss_time.time); - end_subpacket(); - break; - - case OPS_PTAG_SS_TRUST: - start_subpacket(content_->tag); - print_string("Trust Signature",""); - print_unsigned_int("Level", - content->ss_trust.level); - print_unsigned_int("Amount", - content->ss_trust.amount); - end_subpacket(); - break; - - case OPS_PTAG_SS_REVOCABLE: - start_subpacket(content_->tag); - print_boolean("Revocable",content->ss_revocable.revocable); - end_subpacket(); - break; - - case OPS_PTAG_SS_REVOCATION_KEY: - start_subpacket(content_->tag); - /* not yet tested */ - printf (" revocation key: class=0x%x", - content->ss_revocation_key.clss); - if (content->ss_revocation_key.clss&0x40) - printf (" (sensitive)"); - printf (", algid=0x%x", content->ss_revocation_key.algid); - printf(", fingerprint="); - hexdump(content->ss_revocation_key.fingerprint,20); - printf("\n"); - end_subpacket(); - break; - - case OPS_PTAG_SS_ISSUER_KEY_ID: - start_subpacket(content_->tag); - print_hexdump("Issuer Key Id", - &content->ss_issuer_key_id.key_id[0], - sizeof content->ss_issuer_key_id.key_id); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_SKA: - start_subpacket(content_->tag); - print_data( "Preferred Symmetric Algorithms", - &content->ss_preferred_ska.data); - - text = ops_showall_ss_preferred_ska(content->ss_preferred_ska); - print_text_breakdown(text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_PRIMARY_USER_ID: - start_subpacket(content_->tag); - print_boolean("Primary User ID", - content->ss_primary_user_id.primary_user_id); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_HASH: - start_subpacket(content_->tag); - print_data("Preferred Hash Algorithms", - &content->ss_preferred_hash.data); - - text = ops_showall_ss_preferred_hash(content->ss_preferred_hash); - print_text_breakdown(text); - ops_text_free(text); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_COMPRESSION: - start_subpacket(content_->tag); - print_data( "Preferred Compression Algorithms", - &content->ss_preferred_compression.data); - - text = ops_showall_ss_preferred_compression(content->ss_preferred_compression); - print_text_breakdown(text); - ops_text_free(text); - end_subpacket(); - break; - - case OPS_PTAG_SS_KEY_FLAGS: - start_subpacket(content_->tag); - print_data( "Key Flags", &content->ss_key_flags.data); - - text = ops_showall_ss_key_flags(content->ss_key_flags); - print_text_breakdown( text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_KEY_SERVER_PREFS: - start_subpacket(content_->tag); - print_data( "Key Server Preferences", - &content->ss_key_server_prefs.data); - - text = ops_showall_ss_key_server_prefs(content->ss_key_server_prefs); - print_text_breakdown( text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_FEATURES: - start_subpacket(content_->tag); - print_data( "Features", - &content->ss_features.data); - - text = ops_showall_ss_features(content->ss_features); - print_text_breakdown( text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_NOTATION_DATA: - start_subpacket(content_->tag); - print_indent(); - printf("Notation Data:\n"); - - indent++; - print_data( "Flags", - &content->ss_notation_data.flags); - text = ops_showall_ss_notation_data_flags(content->ss_notation_data); - print_text_breakdown( text); - ops_text_free(text); - - /* xxx - TODO: print out UTF - rachel */ - - print_data( "Name", - &content->ss_notation_data.name); - - print_data( "Value", - &content->ss_notation_data.value); - - indent--; - end_subpacket(); - break; - - case OPS_PTAG_SS_REGEXP: - start_subpacket(content_->tag); - print_hexdump("Regular Expression", - (unsigned char *)content->ss_regexp.text, - strlen(content->ss_regexp.text)); - print_string(NULL, - content->ss_regexp.text); - end_subpacket(); - break; - - case OPS_PTAG_SS_POLICY_URL: - start_subpacket(content_->tag); - print_string("Policy URL", - content->ss_policy_url.text); - end_subpacket(); - break; - - case OPS_PTAG_SS_SIGNERS_USER_ID: - start_subpacket(content_->tag); - print_utf8_string("Signer's User ID",content->ss_signers_user_id.user_id); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_KEY_SERVER: - start_subpacket(content_->tag); - print_string("Preferred Key Server", - content->ss_preferred_key_server.text); - end_subpacket(); - break; - - case OPS_PTAG_SS_USERDEFINED00: - case OPS_PTAG_SS_USERDEFINED01: - case OPS_PTAG_SS_USERDEFINED02: - case OPS_PTAG_SS_USERDEFINED03: - case OPS_PTAG_SS_USERDEFINED04: - case OPS_PTAG_SS_USERDEFINED05: - case OPS_PTAG_SS_USERDEFINED06: - case OPS_PTAG_SS_USERDEFINED07: - case OPS_PTAG_SS_USERDEFINED08: - case OPS_PTAG_SS_USERDEFINED09: - case OPS_PTAG_SS_USERDEFINED10: - start_subpacket(content_->tag); - print_hexdump("Internal or user-defined", - content->ss_userdefined.data.contents, - content->ss_userdefined.data.len); - end_subpacket(); - break; - - case OPS_PTAG_SS_RESERVED: - start_subpacket(content_->tag); - print_hexdump("Reserved", - content->ss_userdefined.data.contents, - content->ss_userdefined.data.len); - end_subpacket(); - break; - - case OPS_PTAG_SS_REVOCATION_REASON: - start_subpacket(content_->tag); - print_hexdump("Revocation Reason", - &content->ss_revocation_reason.code, - 1); - str=ops_show_ss_rr_code(content->ss_revocation_reason.code); - print_string(NULL,str); - /* xxx - todo : output text as UTF-8 string */ - end_subpacket(); - break; - - case OPS_PTAG_CT_LITERAL_DATA_HEADER: - print_tagname("LITERAL DATA HEADER"); - printf(" literal data header format=%c filename='%s'\n", - content->literal_data_header.format, - content->literal_data_header.filename); - print_time(" modification time", - content->literal_data_header.modification_time); - printf("\n"); - break; - - case OPS_PTAG_CT_LITERAL_DATA_BODY: - print_tagname("LITERAL DATA BODY"); - printf(" literal data body length=%d\n", - content->literal_data_body.length); - printf(" data="); - print_escaped(content->literal_data_body.data, - content->literal_data_body.length); - printf("\n"); - break; - - case OPS_PTAG_CT_SIGNATURE_HEADER: - print_tagname("SIGNATURE"); - print_indent(); - print_unsigned_int("Signature Version", - content->signature.info.version); - if(content->signature.info.creation_time_set) - print_time("Signature Creation Time", content->signature.info.creation_time); - - print_string_and_value("Signature Type", - ops_show_sig_type(content->signature.info.type), - content->signature.info.type); - - if(content->signature.info.signer_id_set) - print_hexdump_data("Signer ID", - content->signature.info.signer_id, - sizeof content->signature.info.signer_id); - - print_string_and_value("Public Key Algorithm", - ops_show_pka(content->signature.info.key_algorithm), - content->signature.info.key_algorithm); - print_string_and_value("Hash Algorithm", - ops_show_hash_algorithm(content->signature.info.hash_algorithm), - content->signature.info.hash_algorithm); - - break; - - case OPS_PTAG_CT_SIGNATURE_FOOTER: - print_indent(); - print_hexdump_data("hash2",&content->signature.hash2[0],2); - - switch(content->signature.info.key_algorithm) - { - case OPS_PKA_RSA: - print_bn("sig",content->signature.info.signature.rsa.sig); - break; - - case OPS_PKA_DSA: - print_bn("r",content->signature.info.signature.dsa.r); - print_bn("s",content->signature.info.signature.dsa.s); - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - print_bn("r",content->signature.info.signature.elgamal.r); - print_bn("s",content->signature.info.signature.elgamal.s); - break; - - case OPS_PKA_PRIVATE00: - case OPS_PKA_PRIVATE01: - case OPS_PKA_PRIVATE02: - case OPS_PKA_PRIVATE03: - case OPS_PKA_PRIVATE04: - case OPS_PKA_PRIVATE05: - case OPS_PKA_PRIVATE06: - case OPS_PKA_PRIVATE07: - case OPS_PKA_PRIVATE08: - case OPS_PKA_PRIVATE09: - case OPS_PKA_PRIVATE10: - print_data("Private/Experimental", - &content->signature.info.signature.unknown.data); - break; - - default: - assert(0); - } - break; - - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: -#ifdef XXX - if(passphrase_prompt) - { - ops_print_secret_key(OPS_PTAG_CT_ENCRYPTED_SECRET_KEY, - content->secret_key_passphrase.secret_key); - *content->secret_key_passphrase.passphrase=ops_get_passphrase(); - if(!**content->secret_key_passphrase.passphrase) - break; - return OPS_KEEP_MEMORY; - } - else - printf(">>> ASKED FOR PASSPHRASE <<<\n"); -#else - if (cbinfo->cryptinfo.cb_get_passphrase) - return cbinfo->cryptinfo.cb_get_passphrase(content_,cbinfo); -#endif /*XXX*/ - break; - - case OPS_PTAG_CT_SECRET_KEY: - case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: - ops_print_secret_key_verbose(content_->tag,&content->secret_key); - break; - - case OPS_PTAG_CT_ARMOUR_HEADER: - print_tagname("ARMOUR HEADER"); - print_string("type",content->armour_header.type); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER: - print_tagname("SIGNED CLEARTEXT HEADER"); - print_headers(&content->signed_cleartext_header.headers); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY: - print_tagname("SIGNED CLEARTEXT BODY"); - print_block("signed cleartext",content->signed_cleartext_body.data, - content->signed_cleartext_body.length); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: - print_tagname("SIGNED CLEARTEXT TRAILER"); - printf("hash algorithm: %d\n", - content->signed_cleartext_trailer.hash->algorithm); - printf("\n"); - break; - - case OPS_PTAG_CT_UNARMOURED_TEXT: - if(!unarmoured) - { - print_tagname("UNARMOURED TEXT"); - unarmoured=ops_true; - } - putchar('['); - print_escaped(content->unarmoured_text.data, - content->unarmoured_text.length); - putchar(']'); - break; - - case OPS_PTAG_CT_ARMOUR_TRAILER: - print_tagname("ARMOUR TRAILER"); - print_string("type",content->armour_header.type); - break; - - case OPS_PTAG_CT_PK_SESSION_KEY: - case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: - ops_print_pk_session_key(content_->tag,&content->pk_session_key); - break; - - case OPS_PARSER_CMD_GET_SECRET_KEY: - ops_print_pk_session_key(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, - content->get_secret_key.pk_session_key); - -#ifdef XXX - decrypter=ops_keyring_find_key_by_id(&keyring, - content->get_secret_key.pk_session_key->key_id); - if(!decrypter || !ops_key_is_secret(decrypter)) - break; - - puts("[Decryption key found in keyring]"); - - secret=ops_get_secret_key_from_data(decrypter); - while(!secret) - { - /* then it must be encrypted */ - char *phrase=ops_get_passphrase(); - secret=ops_decrypt_secret_key_from_data(decrypter,phrase); - free(phrase); - } - - *content->get_secret_key.secret_key=secret; -#else - return callback_cmd_get_secret_key(content_,cbinfo); -#endif /*XXX*/ - break; - - default: - print_tagname("UNKNOWN PACKET TYPE"); - fprintf(stderr,"packet-dump: unknown tag=%d (0x%x)\n",content_->tag, - content_->tag); - exit(1); - } -#endif /*XXX*/ - return OPS_RELEASE_MEMORY; - } - -/** -\ingroup Core_Print -\param filename -\param armour -\param keyring -\param cb_get_passphrase -*/ -void ops_list_packets(char* filename, ops_boolean_t armour, ops_keyring_t* keyring, ops_parse_cb_t* cb_get_passphrase) - { - int fd=0; - ops_parse_info_t *pinfo=NULL; - const ops_boolean_t accumulate=ops_true; - - fd=ops_setup_file_read(&pinfo, filename, NULL, cb_list_packets, accumulate); - ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_PARSED); - pinfo->cryptinfo.keyring=keyring; - pinfo->cryptinfo.cb_get_passphrase=cb_get_passphrase; - - if(armour) - ops_reader_push_dearmour(pinfo); - - ops_parse_and_print_errors(pinfo); - - ops_teardown_file_read(pinfo,fd); - } diff --git a/openpgpsdk/src/openpgpsdk/packet-show-cast.h b/openpgpsdk/src/openpgpsdk/packet-show-cast.h deleted file mode 100644 index b5c8b0ab4..000000000 --- a/openpgpsdk/src/openpgpsdk/packet-show-cast.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Generated from packet-show.cast by ../../util/caster.pl, do not edit. */ - -#include "types.h" - -/* (line 4) char *show_packet_tag(ops_packet_tag_t packet_tag, packet_tag_map_t *packet_tag_map) -> char *ops_str_from_map(int packet_tag, ops_map_t *packet_tag_map) */ -char *ops_str_from_map(int packet_tag, ops_map_t *packet_tag_map); -#define show_packet_tag(packet_tag,packet_tag_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_packet_tag_t , packet_tag),CHECKED_INSTANCE_OF( packet_tag_map_t *, packet_tag_map)) -typedef char * show_packet_tag_t(ops_packet_tag_t , packet_tag_map_t *); - -/* (line 5) char *show_sig_type(ops_sig_type_t sig_type, sig_type_map_t *sig_type_map) -> char *ops_str_from_map(int sig_type, ops_map_t *sig_type_map) */ -char *ops_str_from_map(int sig_type, ops_map_t *sig_type_map); -#define show_sig_type(sig_type,sig_type_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_sig_type_t , sig_type),CHECKED_INSTANCE_OF( sig_type_map_t *, sig_type_map)) -typedef char * show_sig_type_t(ops_sig_type_t , sig_type_map_t *); - -/* (line 6) char *show_pka(ops_public_key_algorithm_t pka, public_key_algorithm_map_t *pka_map) -> char *ops_str_from_map(int pka, ops_map_t *pka_map) */ -char *ops_str_from_map(int pka, ops_map_t *pka_map); -#define show_pka(pka,pka_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_public_key_algorithm_t , pka),CHECKED_INSTANCE_OF( public_key_algorithm_map_t *, pka_map)) -typedef char * show_pka_t(ops_public_key_algorithm_t , public_key_algorithm_map_t *); - -/* (line 7) char *show_ss_type(ops_ss_type_t ss_type, ss_type_map_t *ss_type_map) -> char *ops_str_from_map(int ss_type, ops_map_t *ss_type_map) */ -char *ops_str_from_map(int ss_type, ops_map_t *ss_type_map); -#define show_ss_type(ss_type,ss_type_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_ss_type_t , ss_type),CHECKED_INSTANCE_OF( ss_type_map_t *, ss_type_map)) -typedef char * show_ss_type_t(ops_ss_type_t , ss_type_map_t *); - -/* (line 8) char *show_ss_rr_code(ops_ss_rr_code_t ss_rr_code, ss_rr_code_map_t *ss_rr_code_map) -> char *ops_str_from_map(int ss_rr_code, ops_map_t *ss_rr_code_map) */ -char *ops_str_from_map(int ss_rr_code, ops_map_t *ss_rr_code_map); -#define show_ss_rr_code(ss_rr_code,ss_rr_code_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_ss_rr_code_t , ss_rr_code),CHECKED_INSTANCE_OF( ss_rr_code_map_t *, ss_rr_code_map)) -typedef char * show_ss_rr_code_t(ops_ss_rr_code_t , ss_rr_code_map_t *); - -/* (line 9) char *show_hash_algorithm(unsigned char hash,+ops_map_t *hash_algorithm_map) -> char *ops_str_from_map(int hash,ops_map_t *hash_algorithm_map) */ -char *ops_str_from_map(int hash,ops_map_t *hash_algorithm_map); -#define show_hash_algorithm(hash) ops_str_from_map(CHECKED_INSTANCE_OF(unsigned char , hash),CHECKED_INSTANCE_OF(ops_map_t *, hash_algorithm_map)) -typedef char * show_hash_algorithm_t(unsigned char ); - -/* (line 10) char *show_symmetric_algorithm(unsigned char hash,+ops_map_t *symmetric_algorithm_map) -> char *ops_str_from_map(int hash,ops_map_t *symmetric_algorithm_map) */ -char *ops_str_from_map(int hash,ops_map_t *symmetric_algorithm_map); -#define show_symmetric_algorithm(hash) ops_str_from_map(CHECKED_INSTANCE_OF(unsigned char , hash),CHECKED_INSTANCE_OF(ops_map_t *, symmetric_algorithm_map)) -typedef char * show_symmetric_algorithm_t(unsigned char ); diff --git a/openpgpsdk/src/openpgpsdk/packet-show.c b/openpgpsdk/src/openpgpsdk/packet-show.c deleted file mode 100644 index 8be6c7563..000000000 --- a/openpgpsdk/src/openpgpsdk/packet-show.c +++ /dev/null @@ -1,857 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * - * Creates printable text strings from packet contents - * - */ - -#include - -#include -#include - -#include -#include - -#include - -/* - * Arrays of value->text maps - */ - -static ops_map_t packet_tag_map[] = - { - { OPS_PTAG_CT_RESERVED, "Reserved" }, - { OPS_PTAG_CT_PK_SESSION_KEY, "Public-Key Encrypted Session Key" }, - { OPS_PTAG_CT_SIGNATURE, "Signature" }, - { OPS_PTAG_CT_SK_SESSION_KEY, "Symmetric-Key Encrypted Session Key" }, - { OPS_PTAG_CT_ONE_PASS_SIGNATURE, "One-Pass Signature" }, - { OPS_PTAG_CT_SECRET_KEY, "Secret Key" }, - { OPS_PTAG_CT_PUBLIC_KEY, "Public Key" }, - { OPS_PTAG_CT_SECRET_SUBKEY, "Secret Subkey" }, - { OPS_PTAG_CT_COMPRESSED, "Compressed Data" }, - { OPS_PTAG_CT_SE_DATA, "Symmetrically Encrypted Data" }, - { OPS_PTAG_CT_MARKER, "Marker" }, - { OPS_PTAG_CT_LITERAL_DATA, "Literal Data" }, - { OPS_PTAG_CT_TRUST, "Trust" }, - { OPS_PTAG_CT_USER_ID, "User ID" }, - { OPS_PTAG_CT_PUBLIC_SUBKEY, "Public Subkey" }, - { OPS_PTAG_CT_RESERVED2, "reserved" }, - { OPS_PTAG_CT_RESERVED3, "reserved" }, - { OPS_PTAG_CT_USER_ATTRIBUTE, "User Attribute" }, - { OPS_PTAG_CT_SE_IP_DATA, "Sym. Encrypted and Integrity Protected Data" }, - { OPS_PTAG_CT_MDC, "Modification Detection Code" }, - { OPS_PARSER_PTAG, "OPS_PARSER_PTAG" }, - { OPS_PTAG_RAW_SS, "OPS_PTAG_RAW_SS" }, - { OPS_PTAG_SS_ALL, "OPS_PTAG_SS_ALL" }, - { OPS_PARSER_PACKET_END, "OPS_PARSER_PACKET_END" }, - { OPS_PTAG_SIGNATURE_SUBPACKET_BASE, "OPS_PTAG_SIGNATURE_SUBPACKET_BASE" }, - - { OPS_PTAG_SS_CREATION_TIME, "SS: Signature Creation Time" }, - { OPS_PTAG_SS_EXPIRATION_TIME, "SS: Signature Expiration Time" }, - { OPS_PTAG_SS_EXPORTABLE_CERTIFICATION, "SS: Exportable Certification" }, - { OPS_PTAG_SS_TRUST, "SS: Trust Signature" }, - { OPS_PTAG_SS_REGEXP, "SS: Regular Expression" }, - { OPS_PTAG_SS_REVOCABLE, "SS: Revocable" }, - { OPS_PTAG_SS_KEY_EXPIRATION_TIME, "SS: Key Expiration Time" }, - { OPS_PTAG_SS_RESERVED, "SS: Reserved" }, - { OPS_PTAG_SS_PREFERRED_SKA, "SS: Preferred Secret Key Algorithm" }, - { OPS_PTAG_SS_REVOCATION_KEY, "SS: Revocation Key" }, - { OPS_PTAG_SS_ISSUER_KEY_ID, "SS: Issuer Key Id" }, - { OPS_PTAG_SS_NOTATION_DATA, "SS: Notation Data" }, - { OPS_PTAG_SS_PREFERRED_HASH, "SS: Preferred Hash Algorithm" }, - { OPS_PTAG_SS_PREFERRED_COMPRESSION,"SS: Preferred Compression Algorithm" }, - { OPS_PTAG_SS_KEY_SERVER_PREFS, "SS: Key Server Preferences" }, - { OPS_PTAG_SS_PREFERRED_COMPRESSION,"SS: Preferred Key Server" }, - { OPS_PTAG_SS_PRIMARY_USER_ID, "SS: Primary User ID" }, - { OPS_PTAG_SS_POLICY_URI, "SS: Policy URI" }, - { OPS_PTAG_SS_KEY_FLAGS, "SS: Key Flags" }, - { OPS_PTAG_SS_SIGNERS_USER_ID, "SS: Signer's User ID" }, - { OPS_PTAG_SS_REVOCATION_REASON, "SS: Reason for Revocation" }, - { OPS_PTAG_SS_FEATURES, "SS: Features" }, - { OPS_PTAG_SS_SIGNATURE_TARGET, "SS: Signature Target" }, - { OPS_PTAG_SS_EMBEDDED_SIGNATURE, "SS: Embedded Signature" }, - - { OPS_PTAG_CT_LITERAL_DATA_HEADER, "CT: Literal Data Header" }, - { OPS_PTAG_CT_LITERAL_DATA_BODY, "CT: Literal Data Body" }, - { OPS_PTAG_CT_SIGNATURE_HEADER, "CT: Signature Header" }, - { OPS_PTAG_CT_SIGNATURE_FOOTER, "CT: Signature Footer" }, - { OPS_PTAG_CT_ARMOUR_HEADER, "CT: Armour Header" }, - { OPS_PTAG_CT_ARMOUR_TRAILER, "CT: Armour Trailer" }, - { OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER, "CT: Signed Cleartext Header" }, - { OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY, "CT: Signed Cleartext Body" }, - { OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER, "CT: Signed Cleartext Trailer" }, - { OPS_PTAG_CT_UNARMOURED_TEXT, "CT: Unarmoured Text" }, - { OPS_PTAG_CT_ENCRYPTED_SECRET_KEY, "CT: Encrypted Secret Key" }, - { OPS_PTAG_CT_SE_DATA_HEADER, "CT: Sym Encrypted Data Header" }, - { OPS_PTAG_CT_SE_DATA_BODY, "CT: Sym Encrypted Data Body" }, - { OPS_PTAG_CT_SE_IP_DATA_HEADER, "CT: Sym Encrypted IP Data Header" }, - { OPS_PTAG_CT_SE_IP_DATA_BODY, "CT: Sym Encrypted IP Data Body" }, - { OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, "CT: Encrypted PK Session Key" }, - { OPS_PARSER_CMD_GET_SK_PASSPHRASE, "CMD: Get Secret Key Passphrase" }, - { OPS_PARSER_CMD_GET_SECRET_KEY, "CMD: Get Secret Key" }, - { OPS_PARSER_ERROR, "OPS_PARSER_ERROR" }, - { OPS_PARSER_ERRCODE, "OPS_PARSER_ERRCODE" }, - - { 0x00, NULL }, /* this is the end-of-array marker */ - }; -typedef ops_map_t packet_tag_map_t; - -static ops_map_t ss_type_map[] = - { - { OPS_PTAG_SS_CREATION_TIME, "Signature Creation Time" }, - { OPS_PTAG_SS_EXPIRATION_TIME, "Signature Expiration Time" }, - { OPS_PTAG_SS_TRUST, "Trust Signature" }, - { OPS_PTAG_SS_REGEXP, "Regular Expression" }, - { OPS_PTAG_SS_REVOCABLE, "Revocable" }, - { OPS_PTAG_SS_KEY_EXPIRATION_TIME, "Key Expiration Time" }, - { OPS_PTAG_SS_PREFERRED_SKA, "Preferred Symmetric Algorithms" }, - { OPS_PTAG_SS_REVOCATION_KEY, "Revocation Key" }, - { OPS_PTAG_SS_ISSUER_KEY_ID, "Issuer key ID" }, - { OPS_PTAG_SS_NOTATION_DATA, "Notation Data" }, - { OPS_PTAG_SS_PREFERRED_HASH, "Preferred Hash Algorithms" }, - { OPS_PTAG_SS_PREFERRED_COMPRESSION,"Preferred Compression Algorithms" }, - { OPS_PTAG_SS_KEY_SERVER_PREFS, "Key Server Preferences" }, - { OPS_PTAG_SS_PREFERRED_KEY_SERVER, "Preferred Key Server" }, - { OPS_PTAG_SS_PRIMARY_USER_ID, "Primary User ID" }, - { OPS_PTAG_SS_POLICY_URI, "Policy URI" }, - { OPS_PTAG_SS_KEY_FLAGS, "Key Flags" }, - { OPS_PTAG_SS_REVOCATION_REASON, "Reason for Revocation" }, - { OPS_PTAG_SS_FEATURES, "Features" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; -typedef ops_map_t ss_type_map_t; - - -static ops_map_t ss_rr_code_map[] = - { - { 0x00, "No reason specified" }, - { 0x01, "Key is superseded" }, - { 0x02, "Key material has been compromised" }, - { 0x03, "Key is retired and no longer used" }, - { 0x20, "User ID information is no longer valid" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; -typedef ops_map_t ss_rr_code_map_t; - -static ops_map_t sig_type_map[] = - { - { OPS_SIG_BINARY, "Signature of a binary document" }, - { OPS_SIG_TEXT, "Signature of a canonical text document" }, - { OPS_SIG_STANDALONE, "Standalone signature" }, - { OPS_CERT_GENERIC, "Generic certification of a User ID and Public Key packet" }, - { OPS_CERT_PERSONA, "Persona certification of a User ID and Public Key packet" }, - { OPS_CERT_CASUAL, "Casual certification of a User ID and Public Key packet" }, - { OPS_CERT_POSITIVE, "Positive certification of a User ID and Public Key packet" }, - { OPS_SIG_SUBKEY, "Subkey Binding Signature" }, - { OPS_SIG_PRIMARY, "Primary Key Binding Signature" }, - { OPS_SIG_DIRECT, "Signature directly on a key" }, - { OPS_SIG_REV_KEY, "Key revocation signature" }, - { OPS_SIG_REV_SUBKEY, "Subkey revocation signature" }, - { OPS_SIG_REV_CERT, "Certification revocation signature" }, - { OPS_SIG_TIMESTAMP, "Timestamp signature" }, - { OPS_SIG_3RD_PARTY, "Third-Party Confirmation signature" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; -typedef ops_map_t sig_type_map_t; - -static ops_map_t public_key_algorithm_map[] = - { - { OPS_PKA_RSA, "RSA (Encrypt or Sign)" }, - { OPS_PKA_RSA_ENCRYPT_ONLY, "RSA Encrypt-Only" }, - { OPS_PKA_RSA_SIGN_ONLY, "RSA Sign-Only" }, - { OPS_PKA_ELGAMAL, "Elgamal (Encrypt-Only)" }, - { OPS_PKA_DSA, "DSA" }, - { OPS_PKA_RESERVED_ELLIPTIC_CURVE, "Reserved for Elliptic Curve" }, - { OPS_PKA_RESERVED_ECDSA, "Reserved for ECDSA" }, - { OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN, "Reserved (formerly Elgamal Encrypt or Sign" }, - { OPS_PKA_RESERVED_DH, "Reserved for Diffie-Hellman (X9.42)" }, - { OPS_PKA_PRIVATE00, "Private/Experimental" }, - { OPS_PKA_PRIVATE01, "Private/Experimental" }, - { OPS_PKA_PRIVATE02, "Private/Experimental" }, - { OPS_PKA_PRIVATE03, "Private/Experimental" }, - { OPS_PKA_PRIVATE04, "Private/Experimental" }, - { OPS_PKA_PRIVATE05, "Private/Experimental" }, - { OPS_PKA_PRIVATE06, "Private/Experimental" }, - { OPS_PKA_PRIVATE07, "Private/Experimental" }, - { OPS_PKA_PRIVATE08, "Private/Experimental" }, - { OPS_PKA_PRIVATE09, "Private/Experimental" }, - { OPS_PKA_PRIVATE10, "Private/Experimental" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; -typedef ops_map_t public_key_algorithm_map_t; - -static ops_map_t symmetric_algorithm_map[] = - { - { OPS_SA_PLAINTEXT, "Plaintext or unencrypted data" }, - { OPS_SA_IDEA, "IDEA" }, - { OPS_SA_TRIPLEDES, "TripleDES" }, - { OPS_SA_CAST5, "CAST5" }, - { OPS_SA_BLOWFISH, "Blowfish" }, - { OPS_SA_AES_128, "AES (128-bit key)" }, - { OPS_SA_AES_192, "AES (192-bit key)" }, - { OPS_SA_AES_256, "AES (256-bit key)" }, - { OPS_SA_TWOFISH, "Twofish(256-bit key)" }, - { OPS_SA_CAMELLIA_128, "Camellia (128-bit key)" }, - { OPS_SA_CAMELLIA_192, "Camellia (192-bit key)" }, - { OPS_SA_CAMELLIA_256, "Camellia (256-bit key)" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; - -static ops_map_t hash_algorithm_map[] = - { - { OPS_HASH_MD5, "MD5" }, - { OPS_HASH_SHA1, "SHA1" }, - { OPS_HASH_RIPEMD, "RIPEMD160" }, - { OPS_HASH_SHA256, "SHA256" }, - { OPS_HASH_SHA384, "SHA384" }, - { OPS_HASH_SHA512, "SHA512" }, - { OPS_HASH_SHA224, "SHA224" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; - -static ops_map_t compression_algorithm_map[] = - { - { OPS_C_NONE, "Uncompressed" }, - { OPS_C_ZIP, "ZIP(RFC1951)" }, - { OPS_C_ZLIB, "ZLIB(RFC1950)" }, - { OPS_C_BZIP2, "Bzip2(BZ2)" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; - -static ops_bit_map_t ss_notation_data_map_byte0[] = - { - { 0x80, "Human-readable" }, - { 0x00, NULL }, - }; - -static ops_bit_map_t *ss_notation_data_map[] = - { - ss_notation_data_map_byte0, - }; - -static ops_bit_map_t ss_feature_map_byte0[] = - { - { 0x01, "Modification Detection" }, - { 0x00, NULL }, - }; - -static ops_bit_map_t *ss_feature_map[] = - { - ss_feature_map_byte0, - }; - -static ops_bit_map_t ss_key_flags_map[] = - { - { 0x01, "May be used to certify other keys" }, - { 0x02, "May be used to sign data" }, - { 0x04, "May be used to encrypt communications" }, - { 0x08, "May be used to encrypt storage" }, - { 0x10, "Private component may have been split by a secret-sharing mechanism"}, - { 0x80, "Private component may be in possession of more than one person"}, - { 0x00, NULL }, - }; - -static ops_bit_map_t ss_key_server_prefs_map[] = - { - { 0x80, "Key holder requests that this key only be modified or updated by the key holder or an administrator of the key server" }, - { 0x00, NULL }, - }; - -#include - -/* - * Private functions - */ - -static void list_init(ops_list_t *list) - { - list->size=0; - list->used=0; - list->strings=NULL; - } - -static void list_free_strings(ops_list_t *list) - { - unsigned i; - - for(i=0; i < list->used ; i++) - { - free(list->strings[i]); - list->strings[i]=NULL; - } - } - -static void list_free(ops_list_t *list) - { - if (list->strings) - free(list->strings); - list_init(list); - } - -static unsigned int list_resize(ops_list_t *list) - { - /* We only resize in one direction - upwards. - Algorithm used : double the current size then add 1 - */ - - int newsize=0; - - newsize=list->size*2 + 1; - list->strings=realloc(list->strings,newsize*sizeof(char *)); - if (list->strings) - { - list->size=newsize; - return 1; - } - else - { - /* xxx - realloc failed. error message? - rachel */ - return 0; - } - } - -static unsigned int add_str(ops_list_t *list,char *str) - { - if (list->size==list->used) - if (!list_resize(list)) - return 0; - - list->strings[list->used]=str; - list->used++; - return 1; - } - -static char *str_from_bitfield_or_null(unsigned char octet, ops_bit_map_t *map) - { - ops_bit_map_t *row; - - for ( row=map; row->string != NULL; row++ ) - if (row->mask == octet) - return row->string; - - return NULL; - } - -static char *str_from_bitfield(unsigned char octet, ops_bit_map_t *map) - { - char *str; - str=str_from_bitfield_or_null(octet,map); - if (str) - return str; - else - return "Unknown"; - } - -/*! generic function to initialise ops_text_t structure */ -void ops_text_init(ops_text_t *text) - { - list_init(&text->known); - list_init(&text->unknown); - } - -/** - * \ingroup Core_Print - * - * ops_text_free() frees the memory used by an ops_text_t structure - * - * \param text Pointer to a previously allocated structure. This structure and its contents will be freed. - */ -void ops_text_free(ops_text_t *text) - { - /* Strings in "known" array will be constants, so don't free them */ - list_free(&text->known); - - /* Strings in "unknown" array will be dynamically allocated, so do free them */ - list_free_strings(&text->unknown); - list_free(&text->unknown); - - /* finally, free the text structure itself */ - free(text); - } - -// XXX: should this (and many others) be ops_boolean_t? -/*! generic function which adds text derived from single octet map to text */ -static unsigned int add_str_from_octet_map(ops_text_t *text,char *str, - unsigned char octet) - { - if (str && !add_str(&text->known,str)) - { - /* value recognised, but there was a problem adding it to the list */ - /* XXX - should print out error msg here, Ben? - rachel */ - return 0; - } - else if (!str) - { - /* value not recognised and there was a problem adding it to the unknown list */ - unsigned len=2+2+1; /* 2 for "0x", 2 for single octet in hex format, 1 for NULL */ - str=malloc(len); - snprintf(str,len,"0x%x",octet); - if (!add_str(&text->unknown,str)) - return 0; - } - return 1; - } - -/*! generic function which adds text derived from single bit map to text */ -static unsigned int add_str_from_bit_map(ops_text_t *text, char *str, unsigned char bit) - { - char *fmt_unknown="Unknown bit(0x%x)"; - - if (str && !add_str(&text->known,str)) - { - /* value recognised, but there was a problem adding it to the list */ - /* XXX - should print out error msg here, Ben? - rachel */ - return 0; - } - else if (!str) - { - /* value not recognised and there was a problem adding it to the unknown list */ - /* 2 chars of the string are the format definition, - this will be replaced in the output by 2 chars of hex, - so the length will be correct */ - unsigned len=strlen(fmt_unknown)+1; - str=malloc(len); - - snprintf(str,len,fmt_unknown,bit); - if (!add_str(&text->unknown,str)) - return 0; - } - return 1; - } - -/** - * Produce a structure containing human-readable textstrings - * representing the recognised and unrecognised contents - * of this byte array. text_fn() will be called on each octet in turn. - * Each octet will generate one string representing the whole byte. - * - */ - -static ops_text_t *text_from_bytemapped_octets(ops_data_t *data, - const char *(*text_fn)(unsigned char octet)) - { - - ops_text_t *text=NULL; - const char *str; - unsigned i; - - /*! allocate and initialise ops_text_t structure to store derived strings */ - text=malloc(sizeof(ops_text_t)); - if (!text) - return NULL; - - ops_text_init(text); - - /*! for each octet in field ... */ - for(i=0 ; i < data->len ; i++) - { - /*! derive string from octet */ - str=(*text_fn)(data->contents[i]); - - /*! and add to text */ - if (!add_str_from_octet_map(text,strdup(str),data->contents[i])) - { - ops_text_free(text); - return NULL; - } - - } - /*! All values have been added to either the known or the unknown list */ - /*! Return text */ - return text; - } - -/** - * Produce a structure containing human-readable textstrings - * representing the recognised and unrecognised contents - * of this byte array, derived from each bit of each octet. - * - */ -static ops_text_t *showall_octets_bits(ops_data_t *data,ops_bit_map_t **map, - size_t nmap) - { - ops_text_t *text=NULL; - char *str; - unsigned i; - int j=0; - unsigned char mask, bit; - - /*! allocate and initialise ops_text_t structure to store derived strings */ - text=malloc(sizeof(ops_text_t)); - if (!text) - return NULL; - - ops_text_init(text); - - /*! for each octet in field ... */ - for(i=0 ; i < data->len ; i++) - { - /*! for each bit in octet ... */ - for (j=0, mask=0x80; j<8; j++, mask = mask>>1 ) - { - bit = data->contents[i]&mask; - if (bit) - { - if(i >= nmap) - str="Unknown"; - else - str=str_from_bitfield ( bit, map[i] ); - if (!add_str_from_bit_map( text, str, bit)) - { - ops_text_free(text); - return NULL; - } - } - } - } - return text; - } - -/* - * Public Functions - */ - -/** - * \ingroup Core_Print - * returns description of the Packet Tag - * \param packet_tag - * \return string or "Unknown" -*/ -const char *ops_show_packet_tag(ops_packet_tag_t packet_tag) - { - char *rtn=NULL; - rtn=show_packet_tag(packet_tag,packet_tag_map); - - if (!rtn) - rtn="Unknown Tag"; - - return rtn; - } - -/** - * \ingroup Core_Print - * - * returns description of the Signature Sub-Packet type - * \param ss_type Signature Sub-Packet type - * \return string or "Unknown" - */ -const char *ops_show_ss_type(ops_ss_type_t ss_type) - { - return show_ss_type(ss_type,ss_type_map); - } - -/** - * \ingroup Core_Print - * - * returns description of the Revocation Reason code - * \param ss_rr_code Revocation Reason code - * \return string or "Unknown" - */ -const char *ops_show_ss_rr_code(ops_ss_rr_code_t ss_rr_code) - { - return show_ss_rr_code(ss_rr_code,ss_rr_code_map); - } - -/** - * \ingroup Core_Print - * - * returns description of the given Signature type - * \param sig_type Signature type - * \return string or "Unknown" - */ -const char *ops_show_sig_type(ops_sig_type_t sig_type) - { - return show_sig_type(sig_type, sig_type_map); - } - -/** - * \ingroup Core_Print - * - * returns description of the given Public Key Algorithm - * \param pka Public Key Algorithm type - * \return string or "Unknown" - */ -const char *ops_show_pka(ops_public_key_algorithm_t pka) - { - return show_pka(pka, public_key_algorithm_map); - } - -/** - * \ingroup Core_Print - * returns description of the Preferred Compression - * \param octet Preferred Compression - * \return string or "Unknown" -*/ -const char *ops_show_ss_preferred_compression(unsigned char octet) - { - return ops_str_from_map(octet,compression_algorithm_map); - } - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given Preferred Compression Algorithms - * \param ss_preferred_compression Array of Preferred Compression Algorithms - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -ops_text_t *ops_showall_ss_preferred_compression(ops_ss_preferred_compression_t ss_preferred_compression) - { - return text_from_bytemapped_octets(&ss_preferred_compression.data, - &ops_show_ss_preferred_compression); - } - - -/** - * \ingroup Core_Print - * - * returns description of the Hash Algorithm type - * \param hash Hash Algorithm type - * \return string or "Unknown" - */ -const char *ops_show_hash_algorithm(unsigned char hash) - { - return show_hash_algorithm(hash); - } - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given Preferred Hash Algorithms - * \param ss_preferred_hash Array of Preferred Hash Algorithms - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -ops_text_t *ops_showall_ss_preferred_hash(ops_ss_preferred_hash_t ss_preferred_hash) - { - return text_from_bytemapped_octets(&ss_preferred_hash.data, - &ops_show_hash_algorithm); - } - -const char *ops_show_symmetric_algorithm(unsigned char hash) - { - return show_symmetric_algorithm(hash); - } - -/** - * \ingroup Core_Print - * returns description of the given Preferred Symmetric Key Algorithm - * \param octet - * \return string or "Unknown" -*/ -const char *ops_show_ss_preferred_ska(unsigned char octet) - { - return ops_str_from_map(octet,symmetric_algorithm_map); - } - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given Preferred Symmetric Key Algorithms - * \param ss_preferred_ska Array of Preferred Symmetric Key Algorithms - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -ops_text_t *ops_showall_ss_preferred_ska(ops_ss_preferred_ska_t ss_preferred_ska) - { - return text_from_bytemapped_octets(&ss_preferred_ska.data, - &ops_show_ss_preferred_ska); - } - -/** - * \ingroup Core_Print - * returns description of one SS Feature - * \param octet - * \return string or "Unknown" -*/ -static char *ops_show_ss_feature(unsigned char octet,unsigned offset) - { - if(offset >= OPS_ARRAY_SIZE(ss_feature_map)) - return "Unknown"; - return str_from_bitfield(octet,ss_feature_map[offset]); - } - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given SS Features - * \param ss_features Signature Sub-Packet Features - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -/* XXX: shouldn't this use show_all_octets_bits? */ -ops_text_t *ops_showall_ss_features(ops_ss_features_t ss_features) - { - ops_text_t *text=NULL; - char *str; - unsigned i; - int j=0; - unsigned char mask, bit; - - text=malloc(sizeof(ops_text_t)); - if (!text) - return NULL; - - ops_text_init(text); - - for(i=0 ; i < ss_features.data.len ; i++) - { - for (j=0, mask=0x80; j<8; j++, mask = mask>>1 ) - { - bit = ss_features.data.contents[i]&mask; - if (bit) - { - str=ops_show_ss_feature ( bit, i ); - if (!add_str_from_bit_map( text, str, bit)) - { - ops_text_free(text); - return NULL; - } - } - } - } - return text; - } - -/** - * \ingroup Core_Print - * returns description of SS Key Flag - * \param octet - * \param map - * \return -*/ -const char *ops_show_ss_key_flag(unsigned char octet, ops_bit_map_t *map) - { - return str_from_bitfield(octet,map); - } - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given Preferred Key Flags - * \param ss_key_flags Array of Key Flags - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -ops_text_t *ops_showall_ss_key_flags(ops_ss_key_flags_t ss_key_flags) - { - ops_text_t *text=NULL; - const char *str; - int i=0; - unsigned char mask, bit; - - text=malloc(sizeof(ops_text_t)); - if (!text) - return NULL; - - ops_text_init(text); - - /* xxx - TBD: extend to handle multiple octets of bits - rachel */ - - for (i=0,mask=0x80 ; i < 8 ; i++,mask=mask >> 1) - { - bit=ss_key_flags.data.contents[0]&mask; - if(bit) - { - str=ops_show_ss_key_flag(bit,&ss_key_flags_map[0]); - if(!add_str_from_bit_map(text,strdup(str),bit)) - { - ops_text_free(text); - return NULL; - } - } - } -/* xxx - must add error text if more than one octet. Only one currently specified -- rachel */ - return text; - } - -/** - * \ingroup Core_Print - * - * returns description of one given Key Server Preference - * - * \param prefs Byte containing bitfield of preferences - * \param map - * \return string or "Unknown" - */ -const char *ops_show_ss_key_server_prefs(unsigned char prefs, - ops_bit_map_t *map) - { - return str_from_bitfield(prefs,map); - } - -/** - * \ingroup Core_Print - * returns set of descriptions of given Key Server Preferences - * \param ss_key_server_prefs - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - * -*/ -ops_text_t *ops_showall_ss_key_server_prefs(ops_ss_key_server_prefs_t ss_key_server_prefs) - { - ops_text_t *text=NULL; - const char *str; - int i=0; - unsigned char mask, bit; - - text=malloc(sizeof(ops_text_t)); - if (!text) - return NULL; - - ops_text_init(text); - - /* xxx - TBD: extend to handle multiple octets of bits - rachel */ - - for (i=0,mask=0x80 ; i < 8 ; i++,mask=mask >> 1) - { - bit=ss_key_server_prefs.data.contents[0]&mask; - if (bit) - { - str=ops_show_ss_key_server_prefs(bit, - &ss_key_server_prefs_map[0]); - if(!add_str_from_bit_map( text, strdup(str), bit)) - { - ops_text_free(text); - return NULL; - } - } - } -/* xxx - must add error text if more than one octet. Only one currently specified -- rachel */ - return text; - } - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given SS Notation Data Flags - * \param ss_notation_data Signature Sub-Packet Notation Data - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -ops_text_t *ops_showall_ss_notation_data_flags(ops_ss_notation_data_t ss_notation_data) - { - return showall_octets_bits(&ss_notation_data.flags,ss_notation_data_map, - OPS_ARRAY_SIZE(ss_notation_data_map)); - } diff --git a/openpgpsdk/src/openpgpsdk/packet-show.h b/openpgpsdk/src/openpgpsdk/packet-show.h deleted file mode 100644 index f8dc4050f..000000000 --- a/openpgpsdk/src/openpgpsdk/packet-show.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_PACKET_TO_TEXT_H -#define OPS_PACKET_TO_TEXT_H - -#ifndef OPS_PACKET_H -#include "packet.h" -#endif - -/** ops_list_t - */ -typedef struct - { - unsigned int size;/* num of array slots allocated */ - unsigned int used; /* num of array slots currently used */ - char **strings; - } ops_list_t; - -/** ops_text_t - */ -typedef struct - { - ops_list_t known; - ops_list_t unknown; - } ops_text_t; - -/** ops_bit_map_t - */ -typedef struct - { - unsigned char mask; - char *string; - } ops_bit_map_t; - -void ops_text_init(ops_text_t *text); -void ops_text_free(ops_text_t *text); - -const char *ops_show_packet_tag(ops_packet_tag_t packet_tag); -const char *ops_show_ss_type(ops_ss_type_t ss_type); - -const char *ops_show_sig_type(ops_sig_type_t sig_type); -const char *ops_show_pka(ops_public_key_algorithm_t pka); - -ops_text_t *ops_showall_ss_preferred_compression(ops_ss_preferred_compression_t ss_preferred_compression); -const char *ops_show_ss_preferred_compression(unsigned char octet); - -ops_text_t *ops_showall_ss_preferred_hash(ops_ss_preferred_hash_t ss_preferred_hash); -const char *ops_show_hash_algorithm(unsigned char octet); -const char *ops_show_symmetric_algorithm(unsigned char hash); - -ops_text_t *ops_showall_ss_preferred_ska(ops_ss_preferred_ska_t ss_preferred_ska); -const char *ops_show_ss_preferred_ska(unsigned char octet); - -const char *ops_show_ss_rr_code(ops_ss_rr_code_t ss_rr_code); - -ops_text_t *ops_showall_ss_features(ops_ss_features_t ss_features); - -ops_text_t *ops_showall_ss_key_flags(ops_ss_key_flags_t ss_key_flags); -const char *ops_show_ss_key_flag(unsigned char octet, ops_bit_map_t *map); - -ops_text_t *ops_showall_ss_key_server_prefs(ops_ss_key_server_prefs_t ss_key_server_prefs); -const char *ops_show_ss_key_server_prefs(unsigned char octet, - ops_bit_map_t *map); - -ops_text_t *ops_showall_ss_notation_data_flags(ops_ss_notation_data_t ss_notation_data); - -char *ops_str_from_map(int code, ops_map_t *map); - -/* vim:set textwidth=120: */ -/* vim:set ts=8: */ - -#endif /* OPS_PACKET_TO_TEXT_H */ diff --git a/openpgpsdk/src/openpgpsdk/packet.h b/openpgpsdk/src/openpgpsdk/packet.h deleted file mode 100644 index 49e59a556..000000000 --- a/openpgpsdk/src/openpgpsdk/packet.h +++ /dev/null @@ -1,951 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * packet related headers. - */ - -#ifndef OPS_PACKET_H -#define OPS_PACKET_H - -#include "configure.h" - -#include -#include -#include -#include "types.h" -#include "errors.h" - -/** General-use structure for variable-length data - */ - -typedef struct - { - size_t len; - unsigned char *contents; - } ops_data_t; - -/************************************/ -/* Packet Tags - RFC4880, 4.2 */ -/************************************/ - -/** Packet Tag - Bit 7 Mask (this bit is always set). - * The first byte of a packet is the "Packet Tag". It always - * has bit 7 set. This is the mask for it. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_ALWAYS_SET 0x80 - -/** Packet Tag - New Format Flag. - * Bit 6 of the Packet Tag is the packet format indicator. - * If it is set, the new format is used, if cleared the - * old format is used. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_NEW_FORMAT 0x40 - - -/** Old Packet Format: Mask for content tag. - * In the old packet format bits 5 to 2 (including) - * are the content tag. This is the mask to apply - * to the packet tag. Note that you need to - * shift by #OPS_PTAG_OF_CONTENT_TAG_SHIFT bits. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_OF_CONTENT_TAG_MASK 0x3c -/** Old Packet Format: Offset for the content tag. - * As described at #OPS_PTAG_OF_CONTENT_TAG_MASK the - * content tag needs to be shifted after being masked - * out from the Packet Tag. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_OF_CONTENT_TAG_SHIFT 2 -/** Old Packet Format: Mask for length type. - * Bits 1 and 0 of the packet tag are the length type - * in the old packet format. - * - * See #ops_ptag_of_lt_t for the meaning of the values. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_OF_LENGTH_TYPE_MASK 0x03 - - -/** Old Packet Format Lengths. - * Defines the meanings of the 2 bits for length type in the - * old packet format. - * - * \see RFC4880 4.2.1 - */ -typedef enum - { - OPS_PTAG_OF_LT_ONE_BYTE =0x00, /*!< Packet has a 1 byte length - header is 2 bytes long. */ - OPS_PTAG_OF_LT_TWO_BYTE =0x01, /*!< Packet has a 2 byte length - header is 3 bytes long. */ - OPS_PTAG_OF_LT_FOUR_BYTE =0x02, /*!< Packet has a 4 byte length - header is 5 bytes long. */ - OPS_PTAG_OF_LT_INDETERMINATE =0x03 /*!< Packet has a indeterminate length. */ - } ops_ptag_of_lt_t; - - -/** New Packet Format: Mask for content tag. - * In the new packet format the 6 rightmost bits - * are the content tag. This is the mask to apply - * to the packet tag. Note that you need to - * shift by #OPS_PTAG_NF_CONTENT_TAG_SHIFT bits. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_NF_CONTENT_TAG_MASK 0x3f -/** New Packet Format: Offset for the content tag. - * As described at #OPS_PTAG_NF_CONTENT_TAG_MASK the - * content tag needs to be shifted after being masked - * out from the Packet Tag. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_NF_CONTENT_TAG_SHIFT 0 - - -/** Structure to hold one parse error string. */ -typedef struct - { - const char *error; /*!< error message. */ - } ops_parser_error_t; - -/** Structure to hold one error code */ -typedef struct - { - ops_errcode_t errcode; - } ops_parser_errcode_t; - -/** Structure to hold one packet tag. - * \see RFC4880 4.2 - */ -typedef struct - { - unsigned new_format; /*!< Whether this packet tag is new (true) or old format (false) */ - unsigned content_tag; /*!< content_tag value - See #ops_content_tag_t for meanings */ - ops_ptag_of_lt_t length_type; /*!< Length type (#ops_ptag_of_lt_t) - only if this packet tag is old format. Set to 0 if new format. */ - unsigned length; /*!< The length of the packet. This value is set when we read and compute the - length information, not at the same moment we create the packet tag structure. - Only defined if #length_read is set. */ /* XXX: Ben, is this correct? */ - unsigned position; /*!< The position (within the current reader) of the packet */ - } ops_ptag_t; - -/** Public Key Algorithm Numbers. - * OpenPGP assigns a unique Algorithm Number to each algorithm that is part of OpenPGP. - * - * This lists algorithm numbers for public key algorithms. - * - * \see RFC4880 9.1 - */ -typedef enum - { - OPS_PKA_RSA =1, /*!< RSA (Encrypt or Sign) */ - OPS_PKA_RSA_ENCRYPT_ONLY =2, /*!< RSA Encrypt-Only (deprecated - \see RFC4880 13.5) */ - OPS_PKA_RSA_SIGN_ONLY =3, /*!< RSA Sign-Only (deprecated - \see RFC4880 13.5) */ - OPS_PKA_ELGAMAL =16, /*!< Elgamal (Encrypt-Only) */ - OPS_PKA_DSA =17, /*!< DSA (Digital Signature Algorithm) */ - OPS_PKA_RESERVED_ELLIPTIC_CURVE =18, /*!< Reserved for Elliptic Curve */ - OPS_PKA_RESERVED_ECDSA =19, /*!< Reserved for ECDSA */ - OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN =20, /*!< Deprecated. */ - OPS_PKA_RESERVED_DH =21, /*!< Reserved for Diffie-Hellman (X9.42, as defined for IETF-S/MIME) */ - OPS_PKA_PRIVATE00 =100, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE01 =101, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE02 =102, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE03 =103, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE04 =104, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE05 =105, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE06 =106, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE07 =107, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE08 =108, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE09 =109, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE10 =110, /*!< Private/Experimental Algorithm */ - } ops_public_key_algorithm_t; - -/** Structure to hold one DSA public key parameters. - * - * \see RFC4880 5.5.2 - */ -typedef struct - { - BIGNUM *p; /*!< DSA prime p */ - BIGNUM *q; /*!< DSA group order q */ - BIGNUM *g; /*!< DSA group generator g */ - BIGNUM *y; /*!< DSA public key value y (= g^x mod p with x being the secret) */ - } ops_dsa_public_key_t; - -/** Structure to hold on RSA public key. - * - * \see RFC4880 5.5.2 - */ -typedef struct - { - BIGNUM *n; /*!< RSA public modulus n */ - BIGNUM *e; /*!< RSA public encryptiong exponent e */ - } ops_rsa_public_key_t; - -/** Structure to hold on ElGamal public key parameters. - * - * \see RFC4880 5.5.2 - */ -typedef struct - { - BIGNUM *p; /*!< ElGamal prime p */ - BIGNUM *g; /*!< ElGamal group generator g */ - BIGNUM *y; /*!< ElGamal public key value y (= g^x mod p with x being the secret) */ - } ops_elgamal_public_key_t; - -/** Union to hold public key parameters of any algorithm */ -typedef union - { - ops_dsa_public_key_t dsa; /*!< A DSA public key */ - ops_rsa_public_key_t rsa; /*!< An RSA public key */ - ops_elgamal_public_key_t elgamal; /*!< An ElGamal public key */ - } ops_public_key_union_t; - -/** Version. - * OpenPGP has two different protocol versions: version 3 and version 4. - * - * \see RFC4880 5.2 - */ -typedef enum - { - OPS_V2=2, /*contents to be a null-terminated list */ - } ops_ss_preferred_ska_t; - -/** Signature Subpacket : Preferrred Hash Algorithm */ -typedef struct - { - ops_data_t data; - } ops_ss_preferred_hash_t; - -/** Signature Subpacket : Preferred Compression */ -typedef struct - { - ops_data_t data; - } ops_ss_preferred_compression_t; - -/** Signature Subpacket : Key Flags */ -typedef struct - { - ops_data_t data; - } ops_ss_key_flags_t; - -/** Signature Subpacket : Key Server Preferences */ -typedef struct - { - ops_data_t data; - } ops_ss_key_server_prefs_t; - -/** Signature Subpacket : Features */ -typedef struct - { - ops_data_t data; - } ops_ss_features_t; - -/** Signature Subpacket : Signature Target */ -typedef struct - { - ops_public_key_algorithm_t pka_alg; - ops_hash_algorithm_t hash_alg; - ops_data_t hash; - } ops_ss_signature_target_t; - -/** Signature Subpacket : Embedded Signature */ -typedef struct - { - ops_data_t sig; - } ops_ss_embedded_signature_t; - -/** ops_packet_t */ - -typedef struct - { - size_t length; - unsigned char *raw; - } ops_packet_t; - -/** Types of Compression */ -typedef enum - { - OPS_C_NONE=0, - OPS_C_ZIP=1, - OPS_C_ZLIB=2, - OPS_C_BZIP2=3, - } ops_compression_type_t; - -/* unlike most structures, this will feed its data as a stream - * to the application instead of directly including it */ -/** ops_compressed_t */ -typedef struct - { - ops_compression_type_t type; - } ops_compressed_t; - -/** ops_one_pass_signature_t */ -typedef struct - { - unsigned char version; - ops_sig_type_t sig_type; - ops_hash_algorithm_t hash_algorithm; - ops_public_key_algorithm_t key_algorithm; - unsigned char keyid[OPS_KEY_ID_SIZE]; - ops_boolean_t nested; - } ops_one_pass_signature_t; - -/** Signature Subpacket : Primary User ID */ -typedef struct - { - ops_boolean_t primary_user_id; - } ops_ss_primary_user_id_t; - -/** Signature Subpacket : Regexp */ -typedef struct - { - char *text; - } ops_ss_regexp_t; - -/** Signature Subpacket : Policy URL */ -typedef struct - { - char *text; - } ops_ss_policy_url_t; - -/** Signature Subpacket : Preferred Key Server */ -typedef struct - { - char *text; - } ops_ss_preferred_key_server_t; - -/** Signature Subpacket : Revocation Key */ -typedef struct - { - unsigned char clss; /* class - name changed for C++ */ - unsigned char algid; - unsigned char fingerprint[20]; - } ops_ss_revocation_key_t; - -/** Signature Subpacket : Revocation Reason */ -typedef struct - { - unsigned char code; - char *text; - } ops_ss_revocation_reason_t; - -/** literal_data_type_t */ -typedef enum - { - OPS_LDT_BINARY='b', - OPS_LDT_TEXT='t', - OPS_LDT_UTF8='u', - OPS_LDT_LOCAL='l', - OPS_LDT_LOCAL2='1' - } ops_literal_data_type_t; - -/** ops_literal_data_header_t */ -typedef struct - { - ops_literal_data_type_t format; - char filename[256]; - time_t modification_time; - } ops_literal_data_header_t; - -/** ops_literal_data_body_t */ -typedef struct - { - unsigned length; - unsigned char *data;//[8192]; - } ops_literal_data_body_t; - -/** ops_mdc_t */ -typedef struct - { - unsigned char data[20]; // size of SHA1 hash - } ops_mdc_t; - -/** ops_armoured_header_value_t */ -typedef struct - { - char *key; - char *value; - } ops_armoured_header_value_t; - -/** ops_headers_t */ -typedef struct - { - ops_armoured_header_value_t *headers; - unsigned nheaders; - } ops_headers_t; - -/** ops_armour_header_t */ -typedef struct - { - const char *type; - ops_headers_t headers; - } ops_armour_header_t; - -/** ops_armour_trailer_t */ -typedef struct - { - const char *type; - } ops_armour_trailer_t; - -/** ops_signed_cleartext_header_t */ -typedef struct - { - ops_headers_t headers; - } ops_signed_cleartext_header_t; - -/** ops_signed_cleartext_body_t */ -typedef struct - { - unsigned length; - unsigned char *data; // \todo fix hard-coded value? - } ops_signed_cleartext_body_t; - -/** ops_signed_cleartext_trailer_t */ -typedef struct - { - struct _ops_hash_t *hash; /*!< This will not have been finalised, but will have seen all the cleartext data in canonical form */ - } ops_signed_cleartext_trailer_t; - -/** ops_unarmoured_text_t */ -typedef struct - { - unsigned length; - unsigned char *data; - } ops_unarmoured_text_t; - -typedef enum - { - SE_IP_DATA_VERSION=1 - } ops_se_ip_data_version_t; - -typedef enum - { - OPS_PKSK_V3=3 - } ops_pk_session_key_version_t; - -/** ops_pk_session_key_parameters_rsa_t */ -typedef struct - { - BIGNUM *encrypted_m; - BIGNUM *m; - } ops_pk_session_key_parameters_rsa_t; - -/** ops_pk_session_key_parameters_elgamal_t */ -typedef struct - { - BIGNUM *g_to_k; - BIGNUM *encrypted_m; - } ops_pk_session_key_parameters_elgamal_t; - -/** ops_pk_session_key_parameters_t */ -typedef union - { - ops_pk_session_key_parameters_rsa_t rsa; - ops_pk_session_key_parameters_elgamal_t elgamal; - } ops_pk_session_key_parameters_t; - -/** ops_pk_session_key_t */ -typedef struct - { - ops_pk_session_key_version_t version; - unsigned char key_id[OPS_KEY_ID_SIZE]; - ops_public_key_algorithm_t algorithm; - ops_pk_session_key_parameters_t parameters; - ops_symmetric_algorithm_t symmetric_algorithm; - unsigned char key[OPS_MAX_KEY_SIZE]; - unsigned short checksum; - } ops_pk_session_key_t; - -/** ops_secret_key_passphrase_t */ -typedef struct - { - const ops_secret_key_t *secret_key; - char **passphrase; /* point somewhere that gets filled in to work around constness of content */ - } ops_secret_key_passphrase_t; - -typedef enum - { - OPS_SE_IP_V1=1 - } ops_se_ip_version_t; - -/** ops_se_ip_data_header_t */ -typedef struct - { - ops_se_ip_version_t version; - } ops_se_ip_data_header_t; - -/** ops_se_ip_data_body_t */ -typedef struct - { - unsigned length; - unsigned char* data; // \todo remember to free this - } ops_se_ip_data_body_t; - -/** ops_se_data_body_t */ -typedef struct - { - unsigned length; - unsigned char data[8192]; // \todo parameterise this! - } ops_se_data_body_t; - -/** ops_get_secret_key_t */ -typedef struct - { - const ops_secret_key_t **secret_key; - const ops_pk_session_key_t *pk_session_key; - } ops_get_secret_key_t; - -/** ops_parser_union_content_t */ -typedef union - { - ops_parser_error_t error; - ops_parser_errcode_t errcode; - ops_ptag_t ptag; - ops_public_key_t public_key; - ops_trust_t trust; - ops_user_id_t user_id; - ops_user_attribute_t user_attribute; - ops_signature_t signature; - ops_ss_raw_t ss_raw; - ops_ss_trust_t ss_trust; - ops_ss_revocable_t ss_revocable; - ops_ss_time_t ss_time; - ops_ss_key_id_t ss_issuer_key_id; - ops_ss_notation_data_t ss_notation_data; - ops_packet_t packet; - ops_compressed_t compressed; - ops_one_pass_signature_t one_pass_signature; - ops_ss_preferred_ska_t ss_preferred_ska; - ops_ss_preferred_hash_t ss_preferred_hash; - ops_ss_preferred_compression_t ss_preferred_compression; - ops_ss_key_flags_t ss_key_flags; - ops_ss_key_server_prefs_t ss_key_server_prefs; - ops_ss_primary_user_id_t ss_primary_user_id; - ops_ss_regexp_t ss_regexp; - ops_ss_policy_url_t ss_policy_url; - ops_ss_preferred_key_server_t ss_preferred_key_server; - ops_ss_revocation_key_t ss_revocation_key; - ops_ss_userdefined_t ss_userdefined; - ops_ss_unknown_t ss_unknown; - ops_literal_data_header_t literal_data_header; - ops_literal_data_body_t literal_data_body; - ops_mdc_t mdc; - ops_ss_features_t ss_features; - ops_ss_signature_target_t ss_signature_target; - ops_ss_embedded_signature_t ss_embedded_signature; - ops_ss_revocation_reason_t ss_revocation_reason; - ops_secret_key_t secret_key; - ops_user_id_t ss_signers_user_id; - ops_armour_header_t armour_header; - ops_armour_trailer_t armour_trailer; - ops_signed_cleartext_header_t signed_cleartext_header; - ops_signed_cleartext_body_t signed_cleartext_body; - ops_signed_cleartext_trailer_t signed_cleartext_trailer; - ops_unarmoured_text_t unarmoured_text; - ops_pk_session_key_t pk_session_key; - ops_secret_key_passphrase_t secret_key_passphrase; - ops_se_ip_data_header_t se_ip_data_header; - ops_se_ip_data_body_t se_ip_data_body; - ops_se_data_body_t se_data_body; - ops_get_secret_key_t get_secret_key; - } ops_parser_content_union_t; - -/** ops_parser_content_t */ -struct ops_parser_content_t - { - ops_content_tag_t tag; - unsigned char critical; /* for signature subpackets */ - ops_parser_content_union_t content; - }; - -/** ops_fingerprint_t */ -typedef struct - { - unsigned char fingerprint[20]; - unsigned length; - } ops_fingerprint_t; - -void ops_init(void); -void ops_finish(void); -void ops_keyid(unsigned char keyid[OPS_KEY_ID_SIZE], - const ops_public_key_t *key); -void ops_fingerprint(ops_fingerprint_t *fp,const ops_public_key_t *key); -void ops_public_key_free(ops_public_key_t *key); -void ops_public_key_copy(ops_public_key_t *dst,const ops_public_key_t *src); -void ops_user_id_free(ops_user_id_t *id); -void ops_user_attribute_free(ops_user_attribute_t *att); -void ops_signature_free(ops_signature_t *sig); -void ops_trust_free(ops_trust_t *trust); -void ops_ss_preferred_ska_free(ops_ss_preferred_ska_t *ss_preferred_ska); -void ops_ss_preferred_hash_free(ops_ss_preferred_hash_t *ss_preferred_hash); -void ops_ss_preferred_compression_free(ops_ss_preferred_compression_t *ss_preferred_compression); -void ops_ss_key_flags_free(ops_ss_key_flags_t *ss_key_flags); -void ops_ss_key_server_prefs_free(ops_ss_key_server_prefs_t *ss_key_server_prefs); -void ops_ss_features_free(ops_ss_features_t *ss_features); -void ops_ss_notation_data_free(ops_ss_notation_data_t *ss_notation_data); -void ops_ss_policy_url_free(ops_ss_policy_url_t *ss_policy_url); -void ops_ss_preferred_key_server_free(ops_ss_preferred_key_server_t *ss_preferred_key_server); -void ops_ss_regexp_free(ops_ss_regexp_t *ss_regexp); -void ops_ss_userdefined_free(ops_ss_userdefined_t *ss_userdefined); -void ops_ss_reserved_free(ops_ss_unknown_t *ss_unknown); -void ops_ss_revocation_reason_free(ops_ss_revocation_reason_t *ss_revocation_reason); -void ops_ss_signature_target_free(ops_ss_signature_target_t *ss_signature_target); -void ops_ss_embedded_signature_free(ops_ss_embedded_signature_t *ss_embedded_signature); - -void ops_packet_free(ops_packet_t *packet); -void ops_parser_content_free(ops_parser_content_t *c); -void ops_secret_key_free(ops_secret_key_t *key); -void ops_secret_key_copy(ops_secret_key_t *dst,const ops_secret_key_t *src); -void ops_pk_session_key_free(ops_pk_session_key_t *sk); - -/* vim:set textwidth=120: */ -/* vim:set ts=8: */ - -#endif diff --git a/openpgpsdk/src/openpgpsdk/parse_local.h b/openpgpsdk/src/openpgpsdk/parse_local.h deleted file mode 100644 index 64fd013b6..000000000 --- a/openpgpsdk/src/openpgpsdk/parse_local.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file */ - -#include -#include - -/** ops_reader_info */ -struct ops_reader_info - { - ops_reader_t *reader; /*!< the reader function to use to get the - data to be parsed */ - ops_reader_destroyer_t *destroyer; - void *arg; /*!< the args to pass to the reader function */ - - ops_boolean_t accumulate:1; /*!< set to accumulate packet data */ - unsigned char *accumulated; /*!< the accumulated data */ - unsigned asize; /*!< size of the buffer */ - unsigned alength; /*!< used buffer */ - /* XXX: what do we do about offsets into compressed packets? */ - unsigned position; /*!< the offset from the beginning (with this reader) */ - - ops_reader_info_t *next; - ops_parse_info_t *pinfo; /*!< A pointer back to the parent parse_info structure */ - }; - - -/** ops_crypt_info - Encrypt/decrypt settings -*/ -struct ops_crypt_info - { - char *passphrase; /* - -#include - -void ops_random(void *dest,size_t length) - { - RAND_bytes(dest,length); - } diff --git a/openpgpsdk/src/openpgpsdk/random.h b/openpgpsdk/src/openpgpsdk/random.h deleted file mode 100644 index 833094353..000000000 --- a/openpgpsdk/src/openpgpsdk/random.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifdef WIN32 -#include -#else -#include -#endif - -void ops_random(void *dest,size_t length); diff --git a/openpgpsdk/src/openpgpsdk/reader.c b/openpgpsdk/src/openpgpsdk/reader.c deleted file mode 100644 index 24fc8a041..000000000 --- a/openpgpsdk/src/openpgpsdk/reader.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#ifndef WIN32 -#include -#else -#include -#endif -#include -#include -#include - -#include -#include - -#include "parse_local.h" - - -/** - * \ingroup Internal_Readers_Generic - * \brief Starts reader stack - * \param pinfo Parse settings - * \param reader Reader to use - * \param destroyer Destroyer to use - * \param arg Reader-specific arg - */ -void ops_reader_set(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg) - { - pinfo->rinfo.reader=reader; - pinfo->rinfo.destroyer=destroyer; - pinfo->rinfo.arg=arg; - } - -/** - * \ingroup Internal_Readers_Generic - * \brief Adds to reader stack - * \param pinfo Parse settings - * \param reader Reader to use - * \param destroyer Reader's destroyer - * \param arg Reader-specific arg - */ -void ops_reader_push(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg) - { - ops_reader_info_t *rinfo=malloc(sizeof *rinfo); - - *rinfo=pinfo->rinfo; - memset(&pinfo->rinfo,'\0',sizeof pinfo->rinfo); - pinfo->rinfo.next=rinfo; - pinfo->rinfo.pinfo=pinfo; - - // should copy accumulate flags from other reader? RW - pinfo->rinfo.accumulate=rinfo->accumulate; - - ops_reader_set(pinfo,reader,destroyer,arg); - } - -/** - * \ingroup Internal_Readers_Generic - * \brief Removes from reader stack - * \param pinfo Parse settings - */ -void ops_reader_pop(ops_parse_info_t *pinfo) - { - ops_reader_info_t *next=pinfo->rinfo.next; - // We are about to overwrite pinfo->rinfo, so free any data in the - // old rinfo structure first. - free(pinfo->rinfo.accumulated); - pinfo->rinfo=*next; - free(next); - } - -/** - * \ingroup Internal_Readers_Generic - * \brief Gets arg from reader - * \param rinfo Reader info - * \return Pointer to reader info's arg - */ -void *ops_reader_get_arg(ops_reader_info_t *rinfo) - { return rinfo->arg; } - -/** - * \ingroup Internal_Readers_Generic - * \brief Gets reader's arg from parse_info - * \param pinfo - * \return Pointer to parse_info's reader_info's arg - */ -void *ops_reader_get_arg_from_pinfo(ops_parse_info_t *pinfo) - { return pinfo->rinfo.arg; } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/reader_armoured.c b/openpgpsdk/src/openpgpsdk/reader_armoured.c deleted file mode 100644 index 44ed56592..000000000 --- a/openpgpsdk/src/openpgpsdk/reader_armoured.c +++ /dev/null @@ -1,1101 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * \brief Code for dealing with ASCII-armoured packets - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "parse_local.h" - -#include - -#include - -static int debug=0; - -#define CRC24_POLY 0x1864cfbL - -/** - * \struct dearmour_arg_t - */ -typedef struct - { - enum - { - OUTSIDE_BLOCK=0, - BASE64, - AT_TRAILER_NAME, - } state; - - enum - { - NONE=0, - BEGIN_PGP_MESSAGE, - BEGIN_PGP_PUBLIC_KEY_BLOCK, - BEGIN_PGP_PRIVATE_KEY_BLOCK, - BEGIN_PGP_MULTI, - BEGIN_PGP_SIGNATURE, - - END_PGP_MESSAGE, - END_PGP_PUBLIC_KEY_BLOCK, - END_PGP_PRIVATE_KEY_BLOCK, - END_PGP_MULTI, - END_PGP_SIGNATURE, - - BEGIN_PGP_SIGNED_MESSAGE - } lastseen; - - ops_parse_info_t *parse_info; - ops_boolean_t seen_nl:1; - ops_boolean_t prev_nl:1; - ops_boolean_t allow_headers_without_gap:1; /*!< allow headers in - armoured data that - are not separated - from the data by a - blank line */ - ops_boolean_t allow_no_gap:1; /*!< allow no blank line at the - start of armoured data */ - ops_boolean_t allow_trailing_whitespace:1; /*!< allow armoured - stuff to have - trailing whitespace - where we wouldn't - strictly expect it */ - - // it is an error to get a cleartext message without a sig - ops_boolean_t expect_sig:1; - ops_boolean_t got_sig:1; - - // base64 stuff - unsigned buffered; - unsigned char buffer[3]; - ops_boolean_t eof64; - unsigned long checksum; - unsigned long read_checksum; - // unarmoured text blocks - unsigned char unarmoured[8192]; - size_t num_unarmoured; - // pushed back data (stored backwards) - unsigned char *pushed_back; - unsigned npushed_back; - // armoured block headers - ops_headers_t headers; - } dearmour_arg_t; - -static void push_back(dearmour_arg_t *arg,const unsigned char *buf, unsigned length) -{ - unsigned n; - - //ASSERT(!arg->pushed_back); // in the least, there will be a memory leak. Not a big issue. - arg->pushed_back=malloc(length); - for(n=0 ; n < length ; ++n) - arg->pushed_back[n]=buf[length-n-1]; - arg->npushed_back=length; -} - -static int set_lastseen_headerline(dearmour_arg_t* arg, char* buf, ops_error_t **errors) - { - char* begin_msg="BEGIN PGP MESSAGE"; - char* begin_public="BEGIN PGP PUBLIC KEY BLOCK"; - char* begin_private="BEGIN PGP PRIVATE KEY BLOCK"; - char* begin_multi="BEGIN PGP MESSAGE, PART "; - char* begin_sig="BEGIN PGP SIGNATURE"; - - char* end_msg="END PGP MESSAGE"; - char* end_public="END PGP PUBLIC KEY BLOCK"; - char* end_private="END PGP PRIVATE KEY BLOCK"; - char* end_multi="END PGP MESSAGE, PART "; - char* end_sig="END PGP SIGNATURE"; - - char* begin_signed_msg="BEGIN PGP SIGNED MESSAGE"; - - int prev=arg->lastseen; - - if (!strncmp(buf,begin_msg,strlen(begin_msg))) - arg->lastseen=BEGIN_PGP_MESSAGE; - else if (!strncmp(buf,begin_public,strlen(begin_public))) - arg->lastseen=BEGIN_PGP_PUBLIC_KEY_BLOCK; - else if (!strncmp(buf,begin_private,strlen(begin_private))) - arg->lastseen=BEGIN_PGP_PRIVATE_KEY_BLOCK; - else if (!strncmp(buf,begin_multi,strlen(begin_multi))) - arg->lastseen=BEGIN_PGP_MULTI; - else if (!strncmp(buf,begin_sig,strlen(begin_sig))) - arg->lastseen=BEGIN_PGP_SIGNATURE; - - else if (!strncmp(buf,end_msg,strlen(end_msg))) - arg->lastseen=END_PGP_MESSAGE; - else if (!strncmp(buf,end_public,strlen(end_public))) - arg->lastseen=END_PGP_PUBLIC_KEY_BLOCK; - else if (!strncmp(buf,end_private,strlen(end_private))) - arg->lastseen=END_PGP_PRIVATE_KEY_BLOCK; - else if (!strncmp(buf,end_multi,strlen(end_multi))) - arg->lastseen=END_PGP_MULTI; - else if (!strncmp(buf,end_sig,strlen(end_sig))) - arg->lastseen=END_PGP_SIGNATURE; - - else if (!strncmp(buf,begin_signed_msg,strlen(begin_signed_msg))) - arg->lastseen=BEGIN_PGP_SIGNED_MESSAGE; - - else - { - OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unrecognised Header Line %s", buf); - return 0; - } - - if (debug) - printf("set header: buf=%s, arg->lastseen=%d, prev=%d\n", buf, arg->lastseen, prev); - - switch (arg->lastseen) - { - case NONE: - OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unrecognised last seen Header Line %s", buf); - break; - - case END_PGP_MESSAGE: - if (prev!=BEGIN_PGP_MESSAGE) - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Got END PGP MESSAGE, but not after BEGIN"); - break; - - case END_PGP_PUBLIC_KEY_BLOCK: - if (prev!=BEGIN_PGP_PUBLIC_KEY_BLOCK) - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Got END PGP PUBLIC KEY BLOCK, but not after BEGIN"); - break; - - case END_PGP_PRIVATE_KEY_BLOCK: - if (prev!=BEGIN_PGP_PRIVATE_KEY_BLOCK) - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Got END PGP PRIVATE KEY BLOCK, but not after BEGIN"); - break; - - case BEGIN_PGP_MULTI: - case END_PGP_MULTI: - OPS_ERROR(errors,OPS_E_R_UNSUPPORTED,"Multi-part messages are not yet supported"); - break; - - case END_PGP_SIGNATURE: - if (prev!=BEGIN_PGP_SIGNATURE) - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Got END PGP SIGNATURE, but not after BEGIN"); - break; - - case BEGIN_PGP_MESSAGE: - case BEGIN_PGP_PUBLIC_KEY_BLOCK: - case BEGIN_PGP_PRIVATE_KEY_BLOCK: - case BEGIN_PGP_SIGNATURE: - case BEGIN_PGP_SIGNED_MESSAGE: - break; - } - - return 1; - } - -static int read_char(dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo, - ops_boolean_t skip) - { - unsigned char c[1]; - - do - { - if(arg->npushed_back) - { - c[0]=arg->pushed_back[--arg->npushed_back]; - if(!arg->npushed_back) - { - free(arg->pushed_back); - arg->pushed_back=NULL; - } - } - /* XXX: should ops_stacked_read exist? Shouldn't this be a limited_read? */ - else if(ops_stacked_read(c,1,errors,rinfo,cbinfo) != 1) - return -1; - } - while(skip && c[0] == '\r'); - - arg->prev_nl=arg->seen_nl; - arg->seen_nl=c[0] == '\n'; - - return c[0]; - } - -static int eat_whitespace(int first, - dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo, - ops_boolean_t skip) - { - int c=first; - - while(c == ' ' || c == '\t') - c=read_char(arg,errors,rinfo,cbinfo,skip); - - return c; - } - -static int read_and_eat_whitespace(dearmour_arg_t *arg, - ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo, - ops_boolean_t skip) - { - int c; - - do - c=read_char(arg,errors,rinfo,cbinfo,skip); - while(c == ' ' || c == '\t'); - - return c; - } - -static void flush(dearmour_arg_t *arg,ops_parse_cb_info_t *cbinfo) - { - ops_parser_content_t content; - - if(arg->num_unarmoured == 0) - return; - - content.content.unarmoured_text.data=arg->unarmoured; - content.content.unarmoured_text.length=arg->num_unarmoured; - CB(cbinfo,OPS_PTAG_CT_UNARMOURED_TEXT,&content); - arg->num_unarmoured=0; - } - -static int unarmoured_read_char(dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo, - ops_boolean_t skip) - { - int c; - - do - { - c=read_char(arg,errors,rinfo,cbinfo,ops_false); - if(c < 0) - return c; - arg->unarmoured[arg->num_unarmoured++]=c; - if(arg->num_unarmoured == sizeof arg->unarmoured) - flush(arg,cbinfo); - } - while(skip && c == '\r'); - - return c; - } - -/** - * \param headers - * \param key - * - * \return header value if found, otherwise NULL - */ -const char *ops_find_header(ops_headers_t *headers,const char *key) - { - unsigned n; - - for(n=0 ; n < headers->nheaders ; ++n) - if(!strcmp(headers->headers[n].key,key)) - return headers->headers[n].value; - return NULL; - } - -/** - * \param dest - * \param src - */ -void ops_dup_headers(ops_headers_t *dest,const ops_headers_t *src) - { - unsigned n; - - dest->headers=malloc(src->nheaders*sizeof *dest->headers); - dest->nheaders=src->nheaders; - - for(n=0 ; n < src->nheaders ; ++n) - { - dest->headers[n].key=strdup(src->headers[n].key); - dest->headers[n].value=strdup(src->headers[n].value); - } - } - -/* Note that this skips CRs so implementations always see just - straight LFs as line terminators */ -static int process_dash_escaped(dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - ops_parser_content_t content; - ops_parser_content_t content2; - ops_signed_cleartext_body_t *body=&content.content.signed_cleartext_body; - ops_signed_cleartext_trailer_t *trailer - =&content2.content.signed_cleartext_trailer; - const char *hashstr; - ops_hash_t *hash; - int total; - - hash=malloc(sizeof *hash); - hashstr=ops_find_header(&arg->headers,"Hash"); - if(hashstr) - { - ops_hash_algorithm_t alg; - - alg=ops_hash_algorithm_from_text(hashstr); - - if(!ops_is_hash_alg_supported(&alg)) - { - free(hash); - OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unsupported hash algorithm '%s'",hashstr); - return -1; - } - if(alg == OPS_HASH_UNKNOWN) - { - free(hash); - OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unknown hash algorithm '%s'",hashstr); - return -1; - } - ops_hash_any(hash,alg); - } - else - ops_hash_md5(hash); - - hash->init(hash); - - body->length=0; - total=0; - for( ; ; ) - { - int c; - unsigned count; - - if((c=read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0) - return -1; - if(arg->prev_nl && c == '-') - { - if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return -1; - if(c != ' ') - { - /* then this had better be a trailer! */ - if(c != '-') - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad dash-escaping"); - for(count=2 ; count < 5 ; ++count) - { - if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return -1; - if(c != '-') - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad dash-escaping (2)"); - } - arg->state=AT_TRAILER_NAME; - break; - } - /* otherwise we read the next character */ - if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return -1; - } - if(c == '\n' && body->length) - { - if(!(memchr(body->data+1,'\n',body->length-1) == NULL)) // ASSERT(memchr(body->data+1,'\n',body->length-1) == NULL); - { - fprintf(stderr,"no \\n in armoured file.") ; - return -1 ; - } - if(body->data[0] == '\n') - hash->add(hash,(unsigned char *)"\r",1); - hash->add(hash,body->data,body->length); - if (debug) - { fprintf(stderr,"Got body:\n%s\n",body->data); } - CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY,&content); - body->length=0; - } - - body->data[body->length++]=c; - ++total; - if(body->length == sizeof body->data) - { - if (debug) - { fprintf(stderr,"Got body (2):\n%s\n",body->data); } - CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY,&content); - body->length=0; - } - } - - if(!(body->data[0] == '\n')) // ASSERT(body->data[0] == '\n'); - { - fprintf(stderr,"Body should end with \\n\n"); - return -1 ; - } - if(!(body->length == 1)) // ASSERT(body->length == 1); - { - fprintf(stderr,"Body length error\n"); - return -1 ; - } - /* don't send that one character, because its part of the trailer. */ - - trailer->hash=hash; - CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER,&content2); - - return total; -} - -static int add_header(dearmour_arg_t *arg,const char *key,const char - *value) - { - /* - * Check that the header is valid - */ - if ( !strcmp(key,"Version") || !strcmp(key,"Comment") - || !strcmp(key,"MessageID") || !strcmp(key,"Hash") - || !strcmp(key,"Charset")) - { - arg->headers.headers=realloc(arg->headers.headers, - (arg->headers.nheaders+1) - *sizeof *arg->headers.headers); - arg->headers.headers[arg->headers.nheaders].key=strdup(key); - arg->headers.headers[arg->headers.nheaders].value=strdup(value); - ++arg->headers.nheaders; - return 1; - } - else - { - return 0; - } - } - -/* \todo what does a return value of 0 indicate? 1 is good, -1 is bad */ -static int parse_headers(dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) -{ - int rtn=1; - char *buf; - unsigned nbuf; - unsigned size; - ops_boolean_t first=ops_true; - //ops_parser_content_t content; - - buf=NULL; - nbuf=size=0; - - for( ; ; ) - { - int c; - - if((c=read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0) - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Unexpected EOF"); - rtn=-1; - break; - } - - if(c == '\n') - { - char *s; - - if(nbuf == 0) - break; - - if(!(nbuf < size)) // ASSERT(nbuf < size); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Size error in armour header"); - return -1 ; - } - buf[nbuf]='\0'; - - s=strchr(buf,':'); - if(!s) - if(!first && !arg->allow_headers_without_gap) - { - // then we have seriously malformed armour - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"No colon in armour header"); - rtn=-1; - break; - } - else - { - if(first && - !(arg->allow_headers_without_gap || arg->allow_no_gap)) - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"No colon in armour header (2)"); - // then we have a nasty armoured block with no - // headers, not even a blank line. - buf[nbuf]='\n'; - push_back(arg,(unsigned char *)buf,nbuf+1); - rtn=-1; - break; - } - } - else - { - *s='\0'; - if(s[1] != ' ') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"No space in armour header"); - rtn=-1; - goto end; - } - if (!add_header(arg,buf,s+2)) - { - OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Invalid header %s", buf); - rtn=-1; - goto end; - } - nbuf=0; - } - first=ops_false; - } - else - { - if(size <= nbuf+1) - { - size+=size+80; - char *nbuf; - nbuf=realloc(buf,size); - if (nbuf == NULL) - { - free(buf); - buf = NULL ; - rtn=-1; - goto end; - } - buf = nbuf; - } - buf[nbuf++]=c; - } - } - -end: - free(buf); - - return rtn; -} - -static int read4(dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo, - int *pc,unsigned *pn,unsigned long *pl) - { - int n,c; - unsigned long l=0; - - for(n=0 ; n < 4 ; ++n) - { - c=read_char(arg,errors,rinfo,cbinfo,ops_true); - if(c < 0) - { - arg->eof64=ops_true; - return -1; - } - if(c == '-') - break; - if(c == '=') - break; - l <<= 6; - if(c >= 'A' && c <= 'Z') - l+=c-'A'; - else if(c >= 'a' && c <= 'z') - l+=c-'a'+26; - else if(c >= '0' && c <= '9') - l+=c-'0'+52; - else if(c == '+') - l+=62; - else if(c == '/') - l+=63; - else - { - --n; - l >>= 6; - } - } - - *pc=c; - *pn=n; - *pl=l; - - return 4; - } - -unsigned ops_crc24(unsigned checksum,unsigned char c) - { - unsigned i; - - checksum ^= c << 16; - for(i=0 ; i < 8 ; i++) - { - checksum <<= 1; - if(checksum & 0x1000000) - checksum ^= CRC24_POLY; - } - return checksum&0xffffffL; - } - -static int decode64(dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) -{ - unsigned n; - int n2; - unsigned long l; - int c; - int ret; - - if(!(arg->buffered == 0)) // ASSERT(arg->buffered == 0); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly formed base64"); - return 0; - } - - ret=read4(arg,errors,rinfo,cbinfo,&c,&n,&l); - if(ret < 0) - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly formed base64"); - return 0; - } - - if(n == 3) - { - if(c != '=') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated base64 (2)"); - return 0; - } - arg->buffered=2; - arg->eof64=ops_true; - l >>= 2; - } - else if(n == 2) - { - if(c != '=') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated base64 (3)"); - return 0; - } - arg->buffered=1; - arg->eof64=ops_true; - l >>= 4; - c=read_char(arg,errors,rinfo,cbinfo,ops_false); - if(c != '=') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated base64"); - return 0; - } - } - else if(n == 0) - { - if(!arg->prev_nl || c != '=') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated base64 (4)"); - return 0; - } - arg->buffered=0; - } - else - { - if(n != 4) // ASSERT(n == 4); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"n should be 4"); - return 0; - } - arg->buffered=3; - - if(!(c != '-' && c != '=')) // ASSERT(c != '-' && c != '='); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated Base64 chunk"); - return 0; - } - } - - if(arg->buffered < 3 && arg->buffered > 0) - { - // then we saw padding - if(!(c == '=')) // ASSERT(c == '='); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated Base64 chunk"); - return 0; - } - c=read_and_eat_whitespace(arg,errors,rinfo,cbinfo,ops_true); - if(c != '\n') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"No newline at base64 end"); - return 0; - } - c=read_char(arg,errors,rinfo,cbinfo,ops_false); - if(c != '=') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"No checksum at base64 end"); - return 0; - } - } - - if(c == '=') - { - // now we are at the checksum - ret=read4(arg,errors,rinfo,cbinfo,&c,&n,&arg->read_checksum); - if(ret < 0 || n != 4) - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Error in checksum"); - return 0; - } - c=read_char(arg,errors,rinfo,cbinfo,ops_true); - if(arg->allow_trailing_whitespace) - c=eat_whitespace(c,arg,errors,rinfo,cbinfo,ops_true); - if(c != '\n') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated checksum"); - return 0; - } - c=read_char(arg,errors,rinfo,cbinfo,ops_false); - if(c != '-') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad base64 trailer (2)"); - return 0; - } - } - - if(c == '-') - { - for(n=0 ; n < 4 ; ++n) - if(read_char(arg,errors,rinfo,cbinfo,ops_false) != '-') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad base64 trailer"); - return 0; - } - arg->eof64=ops_true; - } - else if(!(arg->buffered)) // ASSERT(arg->buffered); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Buffer error"); - return 0; - } - - for(n=0 ; n < arg->buffered ; ++n) - { - arg->buffer[n]=l; - l >>= 8; - } - - for(n2=arg->buffered-1 ; n2 >= 0 ; --n2) - arg->checksum=ops_crc24(arg->checksum,arg->buffer[n2]); - - if(arg->eof64 && arg->read_checksum != arg->checksum) - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Checksum mismatch"); - return 0; - } - - return 1; -} - -static void base64(dearmour_arg_t *arg) - { - arg->state=BASE64; - arg->checksum=CRC24_INIT; - arg->eof64=ops_false; - arg->buffered=0; - } - -// This reader is rather strange in that it can generate callbacks for -// content - this is because plaintext is not encapsulated in PGP -// packets... it also calls back for the text between the blocks. - -static int armoured_data_reader(void *dest_,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - dearmour_arg_t *arg=ops_reader_get_arg(rinfo); - ops_parser_content_t content; - int ret; - ops_boolean_t first; - unsigned char *dest=dest_; - int saved=length; - - if(arg->eof64 && !arg->buffered) - if(!(arg->state == OUTSIDE_BLOCK || arg->state == AT_TRAILER_NAME)) // ASSERT(arg->state == OUTSIDE_BLOCK || arg->state == AT_TRAILER_NAME); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Outside block or trailer name expected"); - return -1 ; - } - - while(length > 0) - { - unsigned count; - unsigned n; - char buf[1024]; - int c; - - flush(arg,cbinfo); - switch(arg->state) - { - case OUTSIDE_BLOCK: - /* This code returns EOF rather than EARLY_EOF because if - we don't see a header line at all, then it is just an - EOF (and not a BLOCK_END) */ - while(!arg->seen_nl) - if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0) - return 0; - - /* flush at this point so we definitely have room for the - header, and so we can easily erase it from the buffer */ - flush(arg,cbinfo); - /* Find and consume the 5 leading '-' */ - for(count=0 ; count < 5 ; ++count) - { - if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return 0; - if(c != '-') - goto reloop; - } - - /* Now find the block type */ - for(n=0 ; n < sizeof buf-1 ; ) - { - if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return 0; - if(c == '-') - goto got_minus; - buf[n++]=c; - } - /* then I guess this wasn't a proper header */ - break; - -got_minus: - buf[n]='\0'; - - /* Consume trailing '-' */ - for(count=1 ; count < 5 ; ++count) - { - if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return 0; - if(c != '-') - /* wasn't a header after all */ - goto reloop; - } - - /* Consume final NL */ - if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0) - return 0; - if(arg->allow_trailing_whitespace) - if((c=eat_whitespace(c,arg,errors,rinfo,cbinfo, - ops_true)) < 0) - return 0; - if(c != '\n') - /* wasn't a header line after all */ - break; - - /* Now we've seen the header, scrub it from the buffer */ - arg->num_unarmoured=0; - - /* But now we've seen a header line, then errors are - EARLY_EOF */ - if((ret=parse_headers(arg,errors,rinfo,cbinfo)) <= 0) - return -1; - - if (!set_lastseen_headerline(arg,buf,errors)) - return -1; - - if(!strcmp(buf,"BEGIN PGP SIGNED MESSAGE")) - { - ops_dup_headers(&content.content.signed_cleartext_header.headers,&arg->headers); - CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER,&content); - ret=process_dash_escaped(arg,errors,rinfo,cbinfo); - if(ret <= 0) - return ret; - } - else - { - content.content.armour_header.type=buf; - content.content.armour_header.headers=arg->headers; - memset(&arg->headers,'\0',sizeof arg->headers); - CB(cbinfo,OPS_PTAG_CT_ARMOUR_HEADER,&content); - base64(arg); - } - break; - - case BASE64: - first=ops_true; - while(length > 0) - { - if(!arg->buffered) - { - if(!arg->eof64) - { - ret=decode64(arg,errors,rinfo,cbinfo); - if(ret <= 0) - return ret; - } - if(!arg->buffered) - { - if(!(arg->eof64)) // ASSERT(arg->eof64); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Format error"); - return -1 ; - } - if(first) - { - arg->state=AT_TRAILER_NAME; - goto reloop; - } - return -1; - } - } - - if(!(arg->buffered)) // ASSERT(arg->buffered); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Format error"); - return -1 ; - } - *dest=arg->buffer[--arg->buffered]; - ++dest; - --length; - first=ops_false; - } - if(arg->eof64 && !arg->buffered) - arg->state=AT_TRAILER_NAME; - break; - - case AT_TRAILER_NAME: - for(n=0 ; n < sizeof buf-1 ; ) - { - if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return -1; - if(c == '-') - goto got_minus2; - buf[n++]=c; - } - /* then I guess this wasn't a proper trailer */ - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad ASCII armour trailer"); - break; - -got_minus2: - buf[n]='\0'; - - if (!set_lastseen_headerline(arg,buf,errors)) - return -1; - - /* Consume trailing '-' */ - for(count=1 ; count < 5 ; ++count) - { - if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return -1; - if(c != '-') - /* wasn't a trailer after all */ - OPS_ERROR(errors, OPS_E_R_BAD_FORMAT,"Bad ASCII armour trailer (2)"); - } - - /* Consume final NL */ - if((c=read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0) - return -1; - if(arg->allow_trailing_whitespace) - if((c=eat_whitespace(c,arg,errors,rinfo,cbinfo, - ops_true)) < 0) - return 0; - if(c != '\n') - /* wasn't a trailer line after all */ - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad ASCII armour trailer (3)"); - - if(!strncmp(buf,"BEGIN ",6)) - { - if (!set_lastseen_headerline(arg,buf,errors)) - return -1; - if((ret=parse_headers(arg,errors,rinfo,cbinfo)) <= 0) - return ret; - content.content.armour_header.type=buf; - content.content.armour_header.headers=arg->headers; - memset(&arg->headers,'\0',sizeof arg->headers); - CB(cbinfo,OPS_PTAG_CT_ARMOUR_HEADER,&content); - base64(arg); - } - else - { - content.content.armour_trailer.type=buf; - CB(cbinfo,OPS_PTAG_CT_ARMOUR_TRAILER,&content); - arg->state=OUTSIDE_BLOCK; - } - break; - } -reloop: - continue; - } - - return saved; -} - -static void armoured_data_destroyer(ops_reader_info_t *rinfo) - { free(ops_reader_get_arg(rinfo)); } - -/** - * \ingroup Core_Readers_Armour - * \brief Pushes dearmouring reader onto stack - * \param parse_info Usual structure containing information about to how to do the parse - * \sa ops_reader_pop_dearmour() - */ -void ops_reader_push_dearmour(ops_parse_info_t *parse_info) - /* - This function originally had these parameters to cater for - packets which didn't strictly match the RFC. - The initial 0.5 release is only going to support - strict checking. - If it becomes desirable to support loose checking of armoured packets - and these params are reinstated, parse_headers() must be fixed - so that these flags work correctly. - - // Allow headers in armoured data that are not separated from the data by a blank line - ops_boolean_t without_gap, - - // Allow no blank line at the start of armoured data - ops_boolean_t no_gap, - - //Allow armoured data to have trailing whitespace where we strictly would not expect it - ops_boolean_t trailing_whitespace - */ - { - dearmour_arg_t *arg; - - arg=ops_mallocz(sizeof *arg); - arg->seen_nl=ops_true; -/* - arg->allow_headers_without_gap=without_gap; - arg->allow_no_gap=no_gap; - arg->allow_trailing_whitespace=trailing_whitespace; -*/ - arg->expect_sig=ops_false; - arg->got_sig=ops_false; - - ops_reader_push(parse_info,armoured_data_reader,armoured_data_destroyer,arg); - } - -/** - * \ingroup Core_Readers_Armour - * \brief Pops dearmour reader from stock - * \param pinfo - * \sa ops_reader_push_dearmour() - */ -void ops_reader_pop_dearmour(ops_parse_info_t *pinfo) - { - dearmour_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo)); - free(arg); - ops_reader_pop(pinfo); - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/reader_encrypted_se.c b/openpgpsdk/src/openpgpsdk/reader_encrypted_se.c deleted file mode 100644 index d45fa8108..000000000 --- a/openpgpsdk/src/openpgpsdk/reader_encrypted_se.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#ifndef OPENSSL_NO_IDEA -#include -#endif -#include -#include -#include "parse_local.h" - -#include -#include - -static int debug=0; - -#ifndef ATTRIBUTE_UNUSED - -#ifndef WIN32 -#define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -#else -#define ATTRIBUTE_UNUSED -#endif // #ifndef WIN32 - -#endif /* ATTRIBUTE_UNUSED */ - - -// \todo there's also a encrypted_arg_t in adv_create.c -// which is used for *encrypting* whereas this is used -// for *decrypting* - -typedef struct - { - unsigned char decrypted[1024]; - size_t decrypted_count; - size_t decrypted_offset; - ops_crypt_t *decrypt; - ops_region_t *region; - ops_boolean_t prev_read_was_plain:1; - } encrypted_arg_t; - -static int encrypted_data_reader(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - encrypted_arg_t *arg=ops_reader_get_arg(rinfo); - int saved=length; - - // V3 MPIs have the count plain and the cipher is reset after each count - if(arg->prev_read_was_plain && !rinfo->pinfo->reading_mpi_length) - { - if(!(rinfo->pinfo->reading_v3_secret)) // ASSERT(rinfo->pinfo->reading_v3_secret); - { - fprintf(stderr,"encrypted_data_reader: Expected non null value for rinfo->pinfo->reading_v3_secret") ; - return -1 ; - } - arg->decrypt->decrypt_resync(arg->decrypt); - arg->prev_read_was_plain=ops_false; - } - else if(rinfo->pinfo->reading_v3_secret - && rinfo->pinfo->reading_mpi_length) - { - arg->prev_read_was_plain=ops_true; - } - - while(length > 0) - { - if(arg->decrypted_count) - { - - unsigned n; - - // if we are reading v3 we should never read more than - // we're asked for - if(!(length >= arg->decrypted_count || (!rinfo->pinfo->reading_v3_secret && !rinfo->pinfo->exact_read))) // ASSERT(length >= arg->decrypted_count || (!rinfo->pinfo->reading_v3_secret && !rinfo->pinfo->exact_read)); - { - fprintf(stderr,"encrypted_data_reader: inconsistency in packet sizes") ; - return -1 ; - } - - if(length > arg->decrypted_count) - n=arg->decrypted_count; - else - n=length; - - memcpy(dest,arg->decrypted+arg->decrypted_offset,n); - arg->decrypted_count-=n; - arg->decrypted_offset+=n; - length-=n; - dest+=n; - } - else - { - unsigned n=arg->region->length; - unsigned char buffer[1024]; - - if(!n) - { - return -1; - } - - if(!arg->region->indeterminate) - { - n-=arg->region->length_read; - if(n == 0) - return saved-length; - if(n > sizeof buffer) - n=sizeof buffer; - } - else - { - n=sizeof buffer; - } - - // we can only read as much as we're asked for in v3 keys - // because they're partially unencrypted! - if((rinfo->pinfo->reading_v3_secret || rinfo->pinfo->exact_read) - && n > length) - n=length; - - if(!ops_stacked_limited_read(buffer,n,arg->region,errors,rinfo, - cbinfo)) - { - return -1; - } - - if(!rinfo->pinfo->reading_v3_secret - || !rinfo->pinfo->reading_mpi_length) - { - arg->decrypted_count=ops_decrypt_se_ip(arg->decrypt, - arg->decrypted, - buffer,n); - - if (debug) - { - fprintf(stderr,"READING:\nencrypted: "); - int i=0; - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", buffer[i]); - fprintf(stderr,"\n"); - fprintf(stderr,"decrypted: "); - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", arg->decrypted[i]); - fprintf(stderr,"\n"); - } - } - else - { - memcpy(arg->decrypted,buffer,n); - arg->decrypted_count=n; - } - - if(!(arg->decrypted_count > 0)) // ASSERT(arg->decrypted_count > 0); - { - fprintf(stderr,"encrypted_data_reader: inconsistency in decrypted count") ; - return -1 ; - } - - arg->decrypted_offset=0; - } - } - - return saved; -} - -static void encrypted_data_destroyer(ops_reader_info_t *rinfo) - { free(ops_reader_get_arg(rinfo)); } - -/** - * \ingroup Core_Readers_SE - * \brief Pushes decryption reader onto stack - * \sa ops_reader_pop_decrypt() - */ -void ops_reader_push_decrypt(ops_parse_info_t *pinfo,ops_crypt_t *decrypt, - ops_region_t *region) - { - encrypted_arg_t *arg=ops_mallocz(sizeof *arg); - - arg->decrypt=decrypt; - arg->region=region; - - ops_decrypt_init(arg->decrypt); - - ops_reader_push(pinfo,encrypted_data_reader,encrypted_data_destroyer,arg); - } - -/** - * \ingroup Core_Readers_Encrypted - * \brief Pops decryption reader from stack - * \sa ops_reader_push_decrypt() - */ -void ops_reader_pop_decrypt(ops_parse_info_t *pinfo) - { - encrypted_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo)); - - arg->decrypt->decrypt_finish(arg->decrypt); - free(arg); - - ops_reader_pop(pinfo); - } - -// eof diff --git a/openpgpsdk/src/openpgpsdk/reader_encrypted_seip.c b/openpgpsdk/src/openpgpsdk/reader_encrypted_seip.c deleted file mode 100644 index 4e5251648..000000000 --- a/openpgpsdk/src/openpgpsdk/reader_encrypted_seip.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * \brief Parser for OpenPGP packets - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "parse_local.h" - -#include -#include -#include -#ifndef WIN32 -#include -#endif -#include -#include - -#include - -static int debug=0; - -typedef struct - { - // boolean: false once we've done the preamble/MDC checks - // and are reading from the plaintext - int passed_checks; - unsigned char *plaintext; - size_t plaintext_available; - size_t plaintext_offset; - ops_region_t *region; - ops_crypt_t *decrypt; - } decrypt_se_ip_arg_t; - -static int se_ip_data_reader(void *dest_, size_t len, ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) - { - - /* - Gets entire SE_IP data packet. - Verifies leading preamble - Verifies trailing MDC packet - Then passes up plaintext as requested - */ - - unsigned int n=0; - - ops_region_t decrypted_region; - - decrypt_se_ip_arg_t *arg=ops_reader_get_arg(rinfo); - - if (!arg->passed_checks) - { - unsigned char*buf=NULL; - - ops_hash_t hash; - unsigned char hashed[SHA_DIGEST_LENGTH]; - - size_t b; - size_t sz_preamble; - size_t sz_mdc_hash; - size_t sz_mdc; - size_t sz_plaintext; - - unsigned char* preamble; - unsigned char* plaintext; - unsigned char* mdc; - unsigned char* mdc_hash; - - ops_hash_any(&hash,OPS_HASH_SHA1); - hash.init(&hash); - - ops_init_subregion(&decrypted_region,NULL); - decrypted_region.length = arg->region->length - arg->region->length_read; - buf=ops_mallocz(decrypted_region.length); - - // read entire SE IP packet - - if (!ops_stacked_limited_read(buf,decrypted_region.length, &decrypted_region,errors,rinfo,cbinfo)) - { - free (buf); - return -1; - } - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"\n\nentire SE IP packet (len=%d):\n",decrypted_region.length); - for (i=0; idecrypt->blocksize+2;i++) - fprintf(stderr," 0x%02x", buf[i]); - fprintf(stderr,"\n"); - } - - b=arg->decrypt->blocksize; - if(buf[b-2] != buf[b] || buf[b-1] != buf[b+1]) - { - fprintf(stderr,"Bad symmetric decrypt (%02x%02x vs %02x%02x)\n", - buf[b-2],buf[b-1],buf[b],buf[b+1]); - OPS_ERROR(errors, OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT,"Bad symmetric decrypt when parsing SE IP packet"); - free(buf); - return -1; - } - - // Verify trailing MDC hash - - sz_preamble=arg->decrypt->blocksize+2; - sz_mdc_hash=OPS_SHA1_HASH_SIZE; - sz_mdc=1+1+sz_mdc_hash; - sz_plaintext=decrypted_region.length-sz_preamble-sz_mdc; - - preamble=buf; - plaintext=buf+sz_preamble; - mdc=plaintext+sz_plaintext; - mdc_hash=mdc+2; - -#ifdef DEBUG - if (debug) - { - unsigned int i=0; - - fprintf(stderr,"\nplaintext (len=%ld): ",sz_plaintext); - for (i=0; iplaintext) // ASSERT(!arg->plaintext); - { - fprintf(stderr,"se_ip_data_reader: consistency error\n"); - return -1 ; - } - arg->plaintext=ops_mallocz(sz_plaintext); - memcpy(arg->plaintext, plaintext, sz_plaintext); - arg->plaintext_available=sz_plaintext; - - arg->passed_checks=1; - - free(buf); - } - - n=len; - if (n > arg->plaintext_available) - n=arg->plaintext_available; - - memcpy(dest_, arg->plaintext+arg->plaintext_offset, n); - arg->plaintext_available-=n; - arg->plaintext_offset+=n; - len-=n; - - return n; - } - -static void se_ip_data_destroyer(ops_reader_info_t *rinfo) - { - decrypt_se_ip_arg_t* arg=ops_reader_get_arg(rinfo); - free (arg->plaintext); - free (arg); - // free(ops_reader_get_arg(rinfo)); - } - -/** - \ingroup Internal_Readers_SEIP -*/ -void ops_reader_push_se_ip_data(ops_parse_info_t *pinfo, ops_crypt_t *decrypt, - ops_region_t *region) - { - decrypt_se_ip_arg_t *arg=ops_mallocz(sizeof *arg); - arg->region=region; - arg->decrypt=decrypt; - - ops_reader_push(pinfo, se_ip_data_reader, se_ip_data_destroyer,arg); - } - -/** - \ingroup Internal_Readers_SEIP - */ -void ops_reader_pop_se_ip_data(ops_parse_info_t* pinfo) - { - // decrypt_se_ip_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo)); - // free(arg); - ops_reader_pop(pinfo); - } - -// eof diff --git a/openpgpsdk/src/openpgpsdk/reader_fd.c b/openpgpsdk/src/openpgpsdk/reader_fd.c deleted file mode 100644 index 8681c65d7..000000000 --- a/openpgpsdk/src/openpgpsdk/reader_fd.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include -#include -#include - -#ifndef WIN32 -#include -#endif - -#include - -#include - -/** Arguments for reader_fd - */ -typedef struct - { - int fd; /*!< file descriptor */ - } reader_fd_arg_t; - -/** - * \ingroup Core_Readers - * - * ops_reader_fd() attempts to read up to "plength" bytes from the file - * descriptor in "parse_info" into the buffer starting at "dest" using the - * rules contained in "flags" - * - * \param dest Pointer to previously allocated buffer - * \param plength Number of bytes to try to read - * \param flags Rules about reading to use - * \param parse_info Gets cast to ops_reader_fd_arg_t - * - * \return OPS_R_EOF if no bytes were read - * \return OPS_R_PARTIAL_READ if not enough bytes were read, and OPS_RETURN_LENGTH is set in "flags" - * \return OPS_R_EARLY_EOF if not enough bytes were read, and OPS_RETURN_LENGTH was not set in "flags" - * \return OPS_R_OK if expected length was read - * \return OPS_R_ERROR if cannot read - * - * OPS_R_EARLY_EOF and OPS_R_ERROR push errors on the stack - * - * \sa enum opt_reader_ret_t - * - * \todo change arg_ to typesafe? - */ -static int fd_reader(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) - { - reader_fd_arg_t *arg=ops_reader_get_arg(rinfo); - int n=read(arg->fd,dest,length); - - OPS_USED(cbinfo); - - if(n == 0) - return 0; - - if(n < 0) - { - OPS_SYSTEM_ERROR_1(errors,OPS_E_R_READ_FAILED,"read", - "file descriptor %d",arg->fd); - return -1; - } - - return n; - } - -static void fd_destroyer(ops_reader_info_t *rinfo) - { free(ops_reader_get_arg(rinfo)); } - -/** - \ingroup Core_Readers_First - \brief Starts stack with file reader -*/ - -void ops_reader_set_fd(ops_parse_info_t *pinfo,int fd) - { - reader_fd_arg_t *arg=malloc(sizeof *arg); - - arg->fd=fd; - ops_reader_set(pinfo,fd_reader,fd_destroyer,arg); - } - -// eof diff --git a/openpgpsdk/src/openpgpsdk/reader_hashed.c b/openpgpsdk/src/openpgpsdk/reader_hashed.c deleted file mode 100644 index 3cc6d2bc2..000000000 --- a/openpgpsdk/src/openpgpsdk/reader_hashed.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include - -#include - -static int hash_reader(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) - { - ops_hash_t *hash=ops_reader_get_arg(rinfo); - int r=ops_stacked_read(dest,length,errors,rinfo,cbinfo); - - if(r <= 0) - return r; - - hash->add(hash,dest,r); - - return r; - } - -/** - \ingroup Internal_Readers_Hash - \brief Push hashed data reader on stack -*/ -void ops_reader_push_hash(ops_parse_info_t *pinfo,ops_hash_t *hash) - { - hash->init(hash); - ops_reader_push(pinfo,hash_reader,NULL,hash); - } - -/** - \ingroup Internal_Readers_Hash - \brief Pop hashed data reader from stack -*/ -void ops_reader_pop_hash(ops_parse_info_t *pinfo) - { ops_reader_pop(pinfo); } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/reader_mem.c b/openpgpsdk/src/openpgpsdk/reader_mem.c deleted file mode 100644 index 2802673c8..000000000 --- a/openpgpsdk/src/openpgpsdk/reader_mem.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include -#include -#include - -#ifndef WIN32 -#include -#endif - -#include - -#include - -typedef struct - { - const unsigned char *buffer; - size_t length; - size_t offset; - } reader_mem_arg_t; - -static int mem_reader(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) - { - reader_mem_arg_t *arg=ops_reader_get_arg(rinfo); - unsigned n; - - OPS_USED(cbinfo); - OPS_USED(errors); - - if(arg->offset+length > arg->length) - n=arg->length-arg->offset; - else - n=length; - - if(n == 0) - return 0; - - memcpy(dest,arg->buffer+arg->offset,n); - arg->offset+=n; - - return n; - } - -static void mem_destroyer(ops_reader_info_t *rinfo) - { free(ops_reader_get_arg(rinfo)); } - -/** - \ingroup Core_Readers_First - \brief Starts stack with memory reader -*/ - -void ops_reader_set_memory(ops_parse_info_t *pinfo,const void *buffer, - size_t length) - { - reader_mem_arg_t *arg=malloc(sizeof *arg); - - arg->buffer=buffer; - arg->length=length; - arg->offset=0; - ops_reader_set(pinfo,mem_reader,mem_destroyer,arg); - } - -/* eof */ diff --git a/openpgpsdk/src/openpgpsdk/readerwriter.c b/openpgpsdk/src/openpgpsdk/readerwriter.c deleted file mode 100644 index 78b45e28c..000000000 --- a/openpgpsdk/src/openpgpsdk/readerwriter.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#ifndef WIN32 -#include -#include -#else -#include -#endif -#include -#include - -#include -#include -#include - -#include "parse_local.h" - -#ifdef WIN32 -#include -#include - -#define PASS_MAX 512 - -char *getpass (const char *prompt) -{ - static char getpassbuf [PASS_MAX + 1]; - size_t i = 0; - int c; - - if (prompt) { - fputs (prompt, stderr); - fflush (stderr); - } - - for (;;) { - c = _getch (); - if (c == '\r') { - getpassbuf [i] = '\0'; - break; - } - else if (i < PASS_MAX) { - getpassbuf[i++] = c; - } - - if (i >= PASS_MAX) { - getpassbuf [i] = '\0'; - break; - } - } - - if (prompt) { - fputs ("\r\n", stderr); - fflush (stderr); - } - - return getpassbuf; -} -#endif - -/** - \ingroup Core_Writers - \brief Create and initialise cinfo and mem; Set for writing to mem - \param cinfo Address where new cinfo pointer will be set - \param mem Address when new mem pointer will be set - \param bufsz Initial buffer size (will automatically be increased when necessary) - \note It is the caller's responsiblity to free cinfo and mem. - \sa ops_teardown_memory_write() -*/ -void ops_setup_memory_write(ops_create_info_t **cinfo, ops_memory_t **mem, size_t bufsz) - { - /* - * initialise needed structures for writing to memory - */ - - *cinfo=ops_create_info_new(); - *mem=ops_memory_new(); - - ops_memory_init(*mem,bufsz); - - ops_writer_set_memory(*cinfo,*mem); - } - -/** - \ingroup Core_Writers - \brief Closes writer and frees cinfo and mem - \param cinfo - \param mem - \sa ops_setup_memory_write() -*/ -void ops_teardown_memory_write(ops_create_info_t *cinfo, ops_memory_t *mem) - { - ops_writer_close(cinfo); // new - ops_create_info_delete(cinfo); - ops_memory_free(mem); - } - -/** - \ingroup Core_Readers - \brief Create parse_info and sets to read from memory - \param pinfo Address where new parse_info will be set - \param mem Memory to read from - \param arg Reader-specific arg - \param callback Callback to use with reader - \param accumulate Set if we need to accumulate as we read. (Usually false unless doing signature verification) - \note It is the caller's responsiblity to free parse_info - \sa ops_teardown_memory_read() -*/ -void ops_setup_memory_read(ops_parse_info_t **pinfo, ops_memory_t *mem, - void* arg, - ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *), - ops_boolean_t accumulate) - { - /* - * initialise needed uctures for reading - */ - - *pinfo=ops_parse_info_new(); - ops_parse_cb_set(*pinfo,callback,arg); - ops_reader_set_memory(*pinfo, - ops_memory_get_data(mem), - ops_memory_get_length(mem)); - - if (accumulate) - (*pinfo)->rinfo.accumulate=ops_true; - } - -/** - \ingroup Core_Readers - \brief Frees pinfo and mem - \param pinfo - \param mem - \sa ops_setup_memory_read() -*/ -void ops_teardown_memory_read(ops_parse_info_t *pinfo, ops_memory_t *mem) - { - ops_parse_info_delete(pinfo); - ops_memory_free(mem); - } - -/** - \ingroup Core_Writers - \brief Create and initialise cinfo and mem; Set for writing to file - \param cinfo Address where new cinfo pointer will be set - \param filename File to write to - \param allow_overwrite Allows file to be overwritten, if set. - \return Newly-opened file descriptor - \note It is the caller's responsiblity to free cinfo and to close fd. - \sa ops_teardown_file_write() -*/ -int ops_setup_file_write(ops_create_info_t **cinfo, const char* filename, ops_boolean_t allow_overwrite) - { - int fd=0; - int flags=0; - - /* - * initialise needed structures for writing to file - */ - - flags=O_WRONLY | O_CREAT; - if (allow_overwrite==ops_true) - flags |= O_TRUNC; - else - flags |= O_EXCL; - flags |= O_BINARY; - - fd=ops_open(filename, flags, 0600); - if(fd < 0) - { - perror(filename); - return fd; - } - - *cinfo=ops_create_info_new(); - - ops_writer_set_fd(*cinfo,fd); - - return fd; - } - -/** - \ingroup Core_Writers - \brief Closes writer, frees info, closes fd - \param cinfo - \param fd -*/ -void ops_teardown_file_write(ops_create_info_t *cinfo, int fd) - { - ops_writer_close(cinfo); - close(fd); - ops_create_info_delete(cinfo); - } - -/** - \ingroup Core_Writers - \brief As ops_setup_file_write, but appends to file -*/ -int ops_setup_file_append(ops_create_info_t **cinfo, const char* filename) - { - int fd; - /* - * initialise needed structures for writing to file - */ - - fd=ops_open(filename,O_WRONLY | O_APPEND | O_BINARY | O_CREAT, 0600); - - if(fd < 0) - { - perror(filename); - return fd; - } - - *cinfo=ops_create_info_new(); - - ops_writer_set_fd(*cinfo,fd); - - return fd; - } - -/** - \ingroup Core_Writers - \brief As ops_teardown_file_write() -*/ -void ops_teardown_file_append(ops_create_info_t *cinfo, int fd) - { - ops_teardown_file_write(cinfo,fd); - } - -/** - \ingroup Core_Readers - \brief Creates parse_info, opens file, and sets to read from file - \param pinfo Address where new parse_info will be set - \param filename Name of file to read - \param arg Reader-specific arg - \param callback Callback to use when reading - \param accumulate Set if we need to accumulate as we read. (Usually false unless doing signature verification) - \note It is the caller's responsiblity to free parse_info and to close fd - \sa ops_teardown_file_read() -*/ - -int ops_setup_file_read(ops_parse_info_t **pinfo, const char *filename, - void* arg, - ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *), - ops_boolean_t accumulate) - { - int fd=0; - /* - * initialise needed structures for reading - */ - - fd=ops_open(filename,O_RDONLY | O_BINARY, 0); - - if (fd < 0) - { - perror(filename); - return fd; - } - - *pinfo=ops_parse_info_new(); - ops_parse_cb_set(*pinfo,callback,arg); - ops_reader_set_fd(*pinfo,fd); - - if (accumulate) - (*pinfo)->rinfo.accumulate=ops_true; - - return fd; - } - -/** - \ingroup Core_Readers - \brief Frees pinfo and closes fd - \param pinfo - \param fd - \sa ops_setup_file_read() -*/ -void ops_teardown_file_read(ops_parse_info_t *pinfo, int fd) - { - close(fd); - ops_parse_info_delete(pinfo); - } - -ops_parse_cb_return_t -callback_literal_data(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) - { - ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content; - - OPS_USED(cbinfo); - - // ops_print_packet(content_); - - // Read data from packet into static buffer - switch(content_->tag) - { - case OPS_PTAG_CT_LITERAL_DATA_BODY: - // if writer enabled, use it - if (cbinfo->cinfo) - { - ops_write(content->literal_data_body.data, - content->literal_data_body.length, - cbinfo->cinfo); - } - /* - ops_memory_add(mem_literal_data, - content->literal_data_body.data, - content->literal_data_body.length); - */ - break; - - case OPS_PTAG_CT_LITERAL_DATA_HEADER: - // ignore - break; - - default: - // return callback_general(content_,cbinfo); - break; - } - - return OPS_RELEASE_MEMORY; - } - -ops_parse_cb_return_t -callback_pk_session_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) - { - ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content; - - OPS_USED(cbinfo); - - // ops_print_packet(content_); - - // Read data from packet into static buffer - switch(content_->tag) - { - case OPS_PTAG_CT_PK_SESSION_KEY: - // printf ("OPS_PTAG_CT_PK_SESSION_KEY\n"); - if(!(cbinfo->cryptinfo.keyring)) // ASSERT(cbinfo->cryptinfo.keyring); - { - fprintf(stderr,"No keyring supplied!") ; - return 0 ; - } - cbinfo->cryptinfo.keydata=ops_keyring_find_key_by_id(cbinfo->cryptinfo.keyring, - content->pk_session_key.key_id); - if(!cbinfo->cryptinfo.keydata) - break; - break; - - default: - // return callback_general(content_,cbinfo); - break; - } - - return OPS_RELEASE_MEMORY; - } - -/** - \ingroup Core_Callbacks - -\brief Callback to get secret key, decrypting if necessary. - -@verbatim - This callback does the following: - * finds the session key in the keyring - * gets a passphrase if required - * decrypts the secret key, if necessary - * sets the secret_key in the content struct -@endverbatim -*/ - -ops_parse_cb_return_t -callback_cmd_get_secret_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) -{ - ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content; - const ops_secret_key_t *secret; - ops_parser_content_t pc; - - OPS_USED(cbinfo); - - // ops_print_packet(content_); - - switch(content_->tag) - { - case OPS_PARSER_CMD_GET_SECRET_KEY: - cbinfo->cryptinfo.keydata=ops_keyring_find_key_by_id(cbinfo->cryptinfo.keyring,content->get_secret_key.pk_session_key->key_id); - if (!cbinfo->cryptinfo.keydata || !ops_is_key_secret(cbinfo->cryptinfo.keydata)) - return 0; - - /* now get the key from the data */ - secret=ops_get_secret_key_from_data(cbinfo->cryptinfo.keydata); - int tag_to_use = OPS_PARSER_CMD_GET_SK_PASSPHRASE ; - int nbtries = 0 ; - - while( (!secret) && nbtries++ < 3) - { - if (!cbinfo->cryptinfo.passphrase) - { - cbinfo->arg = malloc(sizeof(unsigned char)) ; - *(unsigned char *)cbinfo->arg = 0 ; - - memset(&pc,'\0',sizeof pc); - pc.content.secret_key_passphrase.passphrase=&cbinfo->cryptinfo.passphrase; - CB(cbinfo,tag_to_use,&pc); - - if(*(unsigned char*)(cbinfo->arg) == 1) - { - fprintf(stderr,"passphrase cancelled\n"); - free(cbinfo->arg) ; - cbinfo->arg=NULL ; - return 0 ; // ASSERT(0); - } - if (!cbinfo->cryptinfo.passphrase) - { - free(cbinfo->arg) ; - cbinfo->arg=NULL ; - fprintf(stderr,"can't get passphrase\n"); - return 0 ; // ASSERT(0); - } - free(cbinfo->arg) ; - cbinfo->arg=NULL ; - } - /* then it must be encrypted */ - secret=ops_decrypt_secret_key_from_data(cbinfo->cryptinfo.keydata,cbinfo->cryptinfo.passphrase); - - free(cbinfo->cryptinfo.passphrase) ; - cbinfo->cryptinfo.passphrase = NULL ; - - tag_to_use = OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD ; - } - - if(!secret) - return 0 ; - - *content->get_secret_key.secret_key=secret; - break; - - default: - // return callback_general(content_,cbinfo); - break; - } - - return OPS_RELEASE_MEMORY; -} - -char *ops_get_passphrase(void) - { -#ifndef __ANDROID__ - return ops_malloc_passphrase(getpass("Passphrase: ")); -#else // __ANDROID - // We should never get here on Android, getpass not supported. - abort(); -#endif // __ANDROID__ - } - -char *ops_malloc_passphrase(char *pp) - { - char *passphrase; - size_t n; - - n=strlen(pp); - passphrase=malloc(n+1); - strncpy(passphrase,pp,n+1); - - return passphrase; - } - -/** - \ingroup HighLevel_Callbacks - \brief Callback to use when you need to prompt user for passphrase - \param content_ - \param cbinfo -*/ -ops_parse_cb_return_t -callback_cmd_get_passphrase_from_cmdline(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) - { - ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content; - - OPS_USED(cbinfo); - -// ops_print_packet(content_); - - switch(content_->tag) - { - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - *(content->secret_key_passphrase.passphrase)=ops_get_passphrase(); - return OPS_KEEP_MEMORY; - break; - - default: - // return callback_general(content_,cbinfo); - break; - } - - return OPS_RELEASE_MEMORY; - } - -ops_boolean_t ops_reader_set_accumulate(ops_parse_info_t* pinfo, ops_boolean_t state) - { - pinfo->rinfo.accumulate=state; - return state; - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/readerwriter.h b/openpgpsdk/src/openpgpsdk/readerwriter.h deleted file mode 100644 index 6961bafef..000000000 --- a/openpgpsdk/src/openpgpsdk/readerwriter.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __OPS_READERWRITER_H__ -#define __OPS_READERWRITER_H__ - -#include -#include - - -void ops_reader_set_fd(ops_parse_info_t *pinfo,int fd); -void ops_reader_set_memory(ops_parse_info_t *pinfo,const void *buffer, - size_t length); - -// Do a sum mod 65536 of all bytes read (as needed for secret keys) -void ops_reader_push_sum16(ops_parse_info_t *pinfo); -unsigned short ops_reader_pop_sum16(ops_parse_info_t *pinfo); - -void ops_reader_push_se_ip_data(ops_parse_info_t *pinfo, ops_crypt_t *decrypt, - ops_region_t *region); -void ops_reader_pop_se_ip_data(ops_parse_info_t* pinfo); - -// -ops_boolean_t ops_write_mdc(const unsigned char *hashed, - ops_create_info_t* info); -ops_boolean_t ops_write_se_ip_pktset(const unsigned char *data, - const unsigned int len, - ops_crypt_t *crypt, - ops_create_info_t *info); -void ops_writer_push_encrypt_crypt(ops_create_info_t *cinfo, - ops_crypt_t *crypt); -void ops_writer_push_encrypt_se_ip(ops_create_info_t *cinfo, - const ops_keydata_t *pub_key); -// Secret Key checksum - -void ops_push_skey_checksum_writer(ops_create_info_t *cinfo, ops_secret_key_t *skey); -ops_boolean_t ops_pop_skey_checksum_writer(ops_create_info_t *cinfo); - - -// memory writing -void ops_setup_memory_write(ops_create_info_t **cinfo, ops_memory_t **mem, size_t bufsz); -void ops_teardown_memory_write(ops_create_info_t *cinfo, ops_memory_t *mem); - -// memory reading -void ops_setup_memory_read(ops_parse_info_t **pinfo, ops_memory_t *mem, - void* arg, - ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *),ops_boolean_t accumulate); -void ops_teardown_memory_read(ops_parse_info_t *pinfo, ops_memory_t *mem); - -// file writing -int ops_setup_file_write(ops_create_info_t **cinfo, const char* filename, ops_boolean_t allow_overwrite); -void ops_teardown_file_write(ops_create_info_t *cinfo, int fd); - -// file appending -int ops_setup_file_append(ops_create_info_t **cinfo, const char* filename); -void ops_teardown_file_append(ops_create_info_t *cinfo, int fd); - -// file reading -int ops_setup_file_read(ops_parse_info_t **pinfo, const char *filename, void* arg, - ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *), ops_boolean_t accumulate); -void ops_teardown_file_read(ops_parse_info_t *pinfo, int fd); - -ops_boolean_t ops_reader_set_accumulate(ops_parse_info_t* pinfo, ops_boolean_t state); - -// useful callbacks -ops_parse_cb_return_t -callback_literal_data(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo); -ops_parse_cb_return_t -callback_pk_session_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo); -ops_parse_cb_return_t -callback_cmd_get_secret_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo); -ops_parse_cb_return_t -callback_cmd_get_passphrase_from_cmdline(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo); - -#endif /*OPS_READERWRITER_H__*/ diff --git a/openpgpsdk/src/openpgpsdk/signature.c b/openpgpsdk/src/openpgpsdk/signature.c deleted file mode 100644 index b62ebdb9f..000000000 --- a/openpgpsdk/src/openpgpsdk/signature.c +++ /dev/null @@ -1,1602 +0,0 @@ -/* - * Copyright (c) 2005-2009 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh. - * The Contributors have asserted their moral rights under the - * UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -static int debug=0; -#define MAXBUF 1024 /*info); - sig->info=NULL; - free(sig); - } - -static unsigned char prefix_md5[]={ 0x30,0x20,0x30,0x0C,0x06,0x08,0x2A,0x86, - 0x48,0x86,0xF7,0x0D,0x02,0x05,0x05,0x00, - 0x04,0x10 }; - -static unsigned char prefix_sha1[]={ 0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0E, - 0x03,0x02,0x1A,0x05,0x00,0x04,0x14 }; - -static unsigned char prefix_sha224[]={ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, - 0x00, 0x04, 0x1C }; - -static unsigned char prefix_sha256[]={ 0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86, - 0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05, - 0x00,0x04,0x20 }; - -static unsigned char prefix_sha384[]={ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, - 0x00, 0x04, 0x30 }; - -static unsigned char prefix_sha512[]={ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, - 0x00, 0x04, 0x40 }; - -static unsigned char prefix_ripemd[]={ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, - 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; -/** - \ingroup Core_Create - implementation of EMSA-PKCS1-v1_5, as defined in OpenPGP RFC - \param M - \param mLen - \param hash_alg Hash algorithm to use - \param EM - \return ops_true if OK; else ops_false -*/ -ops_boolean_t encode_hash_buf(const unsigned char *M, size_t mLen, - const ops_hash_algorithm_t hash_alg, - unsigned char* EM) -{ - // implementation of EMSA-PKCS1-v1_5, as defined in OpenPGP RFC - - unsigned i; - int n; - ops_hash_t hash; - int hash_sz=0; - // int encoded_hash_sz=0; - int prefix_sz=0; - unsigned padding_sz=0; - unsigned encoded_msg_sz=0; - unsigned char* prefix=NULL; - - if(hash_alg != OPS_HASH_SHA1) - { - fprintf(stderr,"encode_hash_buf: unsupported hash algorithm %x. Sorry.",hash_alg) ; - return ops_false ; - } - - // 1. Apply hash function to M - - ops_hash_any(&hash, hash_alg); - hash.init(&hash); - hash.add(&hash, M, mLen); - - // \todo combine with rsa_sign - - // 2. Get hash prefix - - switch(hash_alg) - { - case OPS_HASH_SHA1: - prefix=prefix_sha1; - prefix_sz=sizeof prefix_sha1; - hash_sz=OPS_SHA1_HASH_SIZE; - // encoded_hash_sz=hash_sz+prefix_sz; - // \todo why is Ben using a PS size of 90 in rsa_sign? - // (keysize-hashsize-1-2) - padding_sz=90; - break; - - default: - return ops_false ; // according to the test at start, this should never happen, so no error handling is necessary. - } - - // \todo 3. Test for len being too short - - // 4 and 5. Generate PS and EM - - EM[0]=0x00; - EM[1]=0x01; - - for (i=0; ialgorithm) - { - case OPS_HASH_SHA1: hashsize=OPS_SHA1_HASH_SIZE+sizeof prefix_sha1; - hash_length=OPS_SHA1_HASH_SIZE ; - prefix = prefix_sha1; - plen = sizeof prefix_sha1 ; - break ; - - case OPS_HASH_SHA224: hashsize=OPS_SHA224_HASH_SIZE+sizeof prefix_sha224; - hash_length=OPS_SHA224_HASH_SIZE ; - prefix = prefix_sha224; - plen = sizeof prefix_sha224 ; - break ; - - case OPS_HASH_SHA256: hashsize=OPS_SHA256_HASH_SIZE+sizeof prefix_sha256; - hash_length=OPS_SHA256_HASH_SIZE ; - prefix = prefix_sha256; - plen = sizeof prefix_sha256 ; - break ; - - case OPS_HASH_SHA384: hashsize=OPS_SHA384_HASH_SIZE+sizeof prefix_sha384; - hash_length=OPS_SHA384_HASH_SIZE ; - prefix = prefix_sha384; - plen = sizeof prefix_sha384 ; - break ; - - case OPS_HASH_SHA512: hashsize=OPS_SHA512_HASH_SIZE+sizeof prefix_sha512; - hash_length=OPS_SHA512_HASH_SIZE ; - prefix = prefix_sha512; - plen = sizeof prefix_sha512 ; - break ; - - case OPS_HASH_MD5: fprintf(stderr,"(insecure) MD5+RSA signatures not supported in RSA sign") ; - return ops_false ; - - default: fprintf(stderr,"Hash algorithm %d not supported in RSA sign",hash->algorithm) ; - return ops_false ; - } - // XXX: we assume hash is sha-1 for now - - keysize=BN_num_bytes(rsa->n); - - if(keysize > sizeof hashbuf) - { - fprintf(stderr,"Keysize too large. limit is %lu, size was %u",sizeof(hashbuf), keysize) ; - return ops_false ; - } - if(10+hashsize > keysize) - { - fprintf(stderr,"10+hashsize > keysize. Can't sign!") ; - return ops_false ; - } - - hashbuf[0]=0; - hashbuf[1]=1; - if (debug) - printf("rsa_sign: PS is %d\n", keysize-hashsize-1-2); - for(n=2 ; n < keysize-hashsize-1 ; ++n) - hashbuf[n]=0xff; - hashbuf[n++]=0; - - memcpy(&hashbuf[n], prefix, plen); - n+=plen; - - t=hash->finish(hash, &hashbuf[n]); - - if(t != hash_length) - { - fprintf(stderr,"Wrong hash size. Should be 20! can't sign.") ; - return ops_false ; - } - - ops_write(&hashbuf[n], 2, opt); - - n+=t; - - if(n != keysize) - { - fprintf(stderr,"Size error in hashed data. can't sign.") ; - return ops_false ; - } - - t=ops_rsa_private_encrypt(sigbuf, hashbuf, keysize, srsa, rsa); - bn=BN_bin2bn(sigbuf, t, NULL); - ops_write_mpi(bn, opt); - BN_free(bn); - - return ops_true ; -} - -static ops_boolean_t dsa_sign(ops_hash_t *hash, const ops_dsa_public_key_t *dsa, - const ops_dsa_secret_key_t *sdsa, ops_create_info_t *cinfo) -{ - unsigned char hashbuf[8192]; - unsigned hashsize; - unsigned t; - - // hashsize must be "equal in size to the number of bits of q, - // the group generated by the DSA key's generator value - // 160/8 = 20 - - hashsize=20; - - // finalise hash - t=hash->finish(hash, &hashbuf[0]); - - if(t != 20) - { - fprintf(stderr,"Wrong hash size. Should be 20! can't sign.") ; - return ops_false ; - } - - ops_write(&hashbuf[0], 2, cinfo); - - // write signature to buf - DSA_SIG* dsasig; - dsasig=ops_dsa_sign(hashbuf, hashsize, sdsa, dsa); - - // convert and write the sig out to memory -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - ops_write_mpi(dsasig->r, cinfo); - ops_write_mpi(dsasig->s, cinfo); -#else - const BIGNUM *rr=NULL,*ss=NULL ; - - DSA_SIG_get0(dsasig,&rr,&ss) ; - - ops_write_mpi(rr, cinfo); - ops_write_mpi(ss, cinfo); -#endif - - DSA_SIG_free(dsasig); - - return ops_true ; -} - -static ops_boolean_t rsa_verify(ops_hash_algorithm_t type, - const unsigned char *hash, size_t hash_length, - const ops_rsa_signature_t *sig, - const ops_rsa_public_key_t *rsa) -{ - unsigned char sigbuf[8192]; - unsigned char hashbuf_from_sig[8192]; - unsigned n; - unsigned keysize; - unsigned char *prefix; - int plen; - - keysize=BN_num_bytes(rsa->n); - /* RSA key can't be bigger than 65535 bits, so... */ - - if(keysize > sizeof hashbuf_from_sig) - { - fprintf(stderr,"Can't verify signature: keysize too big.") ; - return ops_false ; - } - if((unsigned)BN_num_bits(sig->sig) > 8*sizeof sigbuf) - { - fprintf(stderr,"Can't verify signature: signature too big.") ; - return ops_false ; - } - BN_bn2bin(sig->sig, sigbuf); - - n=ops_rsa_public_decrypt(hashbuf_from_sig, sigbuf, BN_num_bytes(sig->sig), rsa); - int debug_len_decrypted=n; - - if(n != keysize) // obviously, this includes error returns - return ops_false; - - // XXX: why is there a leading 0? The first byte should be 1... - // XXX: because the decrypt should use keysize and not sigsize? - if(hashbuf_from_sig[0] != 0 || hashbuf_from_sig[1] != 1) - return ops_false; - - switch(type) - { - case OPS_HASH_MD5 : prefix=prefix_md5 ; plen=sizeof prefix_md5; break; - case OPS_HASH_SHA1 : prefix=prefix_sha1 ; plen=sizeof prefix_sha1; break; - case OPS_HASH_SHA224 : prefix=prefix_sha224 ; plen=sizeof prefix_sha224; break; - case OPS_HASH_SHA256 : prefix=prefix_sha256 ; plen=sizeof prefix_sha256; break; - case OPS_HASH_SHA384 : prefix=prefix_sha384 ; plen=sizeof prefix_sha384; break; - case OPS_HASH_SHA512 : prefix=prefix_sha512 ; plen=sizeof prefix_sha512; break; - case OPS_HASH_RIPEMD : prefix=prefix_ripemd ; plen=sizeof prefix_ripemd; break; - - default: - fprintf(stderr,"Warning: unhandled hash type in signature verification code: %d\n",type) ; - return ops_false ; - } - - if(keysize-plen-hash_length < 10) - return ops_false; - - for(n=2 ; n < keysize-plen-hash_length-1 ; ++n) - if(hashbuf_from_sig[n] != 0xff) - return ops_false; - - if(hashbuf_from_sig[n++] != 0) - return ops_false; - - if (debug) - { - int zz; - - printf("\n"); - printf("hashbuf_from_sig\n"); - for (zz=0; zzadd(hash, ops_memory_get_data(mem), l); - - ops_memory_free(mem); - } - -static void initialise_hash(ops_hash_t *hash, const ops_signature_t *sig) - { - ops_hash_any(hash, sig->info.hash_algorithm); - hash->init(hash); - } - -static void init_key_signature(ops_hash_t *hash, const ops_signature_t *sig, - const ops_public_key_t *key) - { - initialise_hash(hash, sig); - hash_add_key(hash, key); - } - -static void hash_add_trailer(ops_hash_t *hash, const ops_signature_t *sig, - const unsigned char *raw_packet) - { - if(sig->info.version == OPS_V4) - { - if(raw_packet) - hash->add(hash, raw_packet+sig->v4_hashed_data_start, - sig->info.v4_hashed_data_length); - ops_hash_add_int(hash, sig->info.version, 1); - ops_hash_add_int(hash, 0xff, 1); - ops_hash_add_int(hash, sig->info.v4_hashed_data_length, 4); - } - else - { - ops_hash_add_int(hash, sig->info.type, 1); - ops_hash_add_int(hash, sig->info.creation_time, 4); - } - } - -/** - \ingroup Core_Signature - \brief Checks a signature - \param hash Signature Hash to be checked - \param length Signature Length - \param sig The Signature to be checked - \param signer The signer's public key - \return ops_true if good; else ops_false -*/ -ops_boolean_t ops_check_signature(const unsigned char *hash, unsigned length, - const ops_signature_t *sig, - const ops_public_key_t *signer) -{ - ops_boolean_t ret; - - /* - printf(" hash="); - // hashout[0]=0; - hexdump(hash,length); - */ - - switch(sig->info.key_algorithm) - { - case OPS_PKA_DSA: - ret=ops_dsa_verify(hash, length, &sig->info.signature.dsa, - &signer->key.dsa); - /* fprintf(stderr,"Cannot verify DSA signature. skipping.\n") ; - ret = ops_false ; */ - break; - - case OPS_PKA_RSA: - ret=rsa_verify(sig->info.hash_algorithm, hash, length, - &sig->info.signature.rsa, &signer->key.rsa); - break; - - default: - fprintf(stderr,"Cannot verify signature. Unknown key signing algorithm %d. skipping.\n",sig->info.key_algorithm) ; - ret = ops_false ; - - } - - return ret; -} - -static ops_boolean_t hash_and_check_signature(ops_hash_t *hash, - const ops_signature_t *sig, - const ops_public_key_t *signer) - { - int n; - unsigned char hashout[OPS_MAX_HASH_SIZE]; - - n=hash->finish(hash, hashout); - - return ops_check_signature(hashout, n, sig, signer); - } - -static ops_boolean_t finalise_signature(ops_hash_t *hash, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet) - { - hash_add_trailer(hash, sig, raw_packet); - return hash_and_check_signature(hash, sig, signer); - } - -/** - * \ingroup Core_Signature - * - * \brief Verify a certification signature. - * - * \param key The public key that was signed. - * \param id The user ID that was signed - * \param sig The signature. - * \param signer The public key of the signer. - * \param raw_packet The raw signature packet. - * \return ops_true if OK; else ops_false - */ -ops_boolean_t -ops_check_user_id_certification_signature(const ops_public_key_t *key, - const ops_user_id_t *id, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet) - { - ops_hash_t hash; - size_t user_id_len=strlen((char *)id->user_id); - - init_key_signature(&hash, sig, key); - - if(sig->info.version == OPS_V4) - { - ops_hash_add_int(&hash, 0xb4, 1); - ops_hash_add_int(&hash, user_id_len, 4); - } - hash.add(&hash, id->user_id, user_id_len); - - return finalise_signature(&hash, sig, signer, raw_packet); - } - -/** - * \ingroup Core_Signature - * - * Verify a certification signature. - * - * \param key The public key that was signed. - * \param attribute The user attribute that was signed - * \param sig The signature. - * \param signer The public key of the signer. - * \param raw_packet The raw signature packet. - * \return ops_true if OK; else ops_false - */ -ops_boolean_t -ops_check_user_attribute_certification_signature(const ops_public_key_t *key, - const ops_user_attribute_t *attribute, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet) - { - ops_hash_t hash; - - init_key_signature(&hash, sig, key); - - if(sig->info.version == OPS_V4) - { - ops_hash_add_int(&hash, 0xd1, 1); - ops_hash_add_int(&hash, attribute->data.len, 4); - } - hash.add(&hash, attribute->data.contents, attribute->data.len); - - return finalise_signature(&hash, sig, signer, raw_packet); - } - -/** - * \ingroup Core_Signature - * - * Verify a subkey signature. - * - * \param key The public key whose subkey was signed. - * \param subkey The subkey of the public key that was signed. - * \param sig The signature. - * \param signer The public key of the signer. - * \param raw_packet The raw signature packet. - * \return ops_true if OK; else ops_false - */ -ops_boolean_t -ops_check_subkey_signature(const ops_public_key_t *key, - const ops_public_key_t *subkey, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet) - { - ops_hash_t hash; - - init_key_signature(&hash, sig, key); - hash_add_key(&hash, subkey); - - return finalise_signature(&hash, sig, signer, raw_packet); - } - -/** - * \ingroup Core_Signature - * - * Verify a direct signature. - * - * \param key The public key which was signed. - * \param sig The signature. - * \param signer The public key of the signer. - * \param raw_packet The raw signature packet. - * \return ops_true if OK; else ops_false - */ -ops_boolean_t -ops_check_direct_signature(const ops_public_key_t *key, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet) - { - ops_hash_t hash; - - init_key_signature(&hash, sig, key); - return finalise_signature(&hash, sig, signer, raw_packet); - } - -/** - * \ingroup Core_Signature - * - * Verify a signature on a hash (the hash will have already been fed - * the material that was being signed, for example signed cleartext). - * - * \param hash A hash structure of appropriate type that has been fed - * the material to be signed. This MUST NOT have been finalised. - * \param sig The signature to be verified. - * \param signer The public key of the signer. - * \return ops_true if OK; else ops_false - */ -ops_boolean_t -ops_check_hash_signature(ops_hash_t *hash, const ops_signature_t *sig, - const ops_public_key_t *signer) - { - if(sig->info.hash_algorithm != hash->algorithm) - return ops_false; - - return finalise_signature(hash, sig, signer, NULL); - } - -static void start_signature_in_mem(ops_create_signature_t *sig) - { - // since this has subpackets and stuff, we have to buffer the whole - // thing to get counts before writing. - sig->mem=ops_memory_new(); - ops_memory_init(sig->mem, 100); - ops_writer_set_memory(sig->info, sig->mem); - - // write nearly up to the first subpacket - ops_write_scalar(sig->sig.info.version, 1, sig->info); - ops_write_scalar(sig->sig.info.type, 1, sig->info); - ops_write_scalar(sig->sig.info.key_algorithm, 1, sig->info); - ops_write_scalar(sig->sig.info.hash_algorithm, 1, sig->info); - - // dummy hashed subpacket count - sig->hashed_count_offset=ops_memory_get_length(sig->mem); - ops_write_scalar(0, 2, sig->info); - } - -/** - * \ingroup Core_Signature - * - * ops_signature_start() creates a V4 public key signature with a SHA1 hash. - * - * \param sig The signature structure to initialise - * \param key The public key to be signed - * \param id The user ID being bound to the key - * \param type Signature type - */ -void ops_signature_start_key_signature(ops_create_signature_t *sig, - const ops_public_key_t *key, - const ops_user_id_t *id, - ops_sig_type_t type) - { - sig->info=ops_create_info_new(); - - // XXX: refactor with check (in several ways - check should probably - // use the buffered writer to construct packets (done), and also should - // share code for hash calculation) - sig->sig.info.version=OPS_V4; - sig->sig.info.hash_algorithm=OPS_HASH_SHA1; - sig->sig.info.key_algorithm=key->algorithm; - sig->sig.info.type=type; - - sig->hashed_data_length=-1; - - init_key_signature(&sig->hash, &sig->sig, key); - - ops_hash_add_int(&sig->hash, 0xb4, 1); - ops_hash_add_int(&sig->hash, strlen((char *)id->user_id), 4); - sig->hash.add(&sig->hash, id->user_id, strlen((char *)id->user_id)); - - start_signature_in_mem(sig); - } - -/** - * \ingroup Core_Signature - * - * Create a V4 public key signature over some cleartext. - * - * \param sig The signature structure to initialise - * \param id - * \param type - * \todo Expand description. Allow other hashes. - */ - -static void ops_signature_start_signature(ops_create_signature_t *sig, - const ops_secret_key_t *key, - const ops_hash_algorithm_t hash, - const ops_sig_type_t type) - { - sig->info=ops_create_info_new(); - - // XXX: refactor with check (in several ways - check should probably - // use the buffered writer to construct packets (done), and also should - // share code for hash calculation) - sig->sig.info.version=OPS_V4; - sig->sig.info.key_algorithm=key->public_key.algorithm; - sig->sig.info.hash_algorithm=hash; - sig->sig.info.type=type; - - sig->hashed_data_length=-1; - - if (debug) - { fprintf(stderr, "initialising hash for sig in mem\n"); } - initialise_hash(&sig->hash, &sig->sig); - start_signature_in_mem(sig); - } - -/** - * \ingroup Core_Signature - * \brief Setup to start a cleartext's signature - */ -void ops_signature_start_cleartext_signature(ops_create_signature_t *sig, - const ops_secret_key_t *key, - const ops_hash_algorithm_t hash, - const ops_sig_type_t type) - { - ops_signature_start_signature(sig, key, hash, type); - } - -/** - * \ingroup Core_Signature - * \brief Setup to start a message's signature - */ -void ops_signature_start_message_signature(ops_create_signature_t *sig, - const ops_secret_key_t *key, - const ops_hash_algorithm_t hash, - const ops_sig_type_t type) - { - ops_signature_start_signature(sig, key, hash, type); - } - -/** - * \ingroup Core_Signature - * - * Add plaintext data to a signature-to-be. - * - * \param sig The signature-to-be. - * \param buf The plaintext data. - * \param length The amount of plaintext data. - */ -void ops_signature_add_data(ops_create_signature_t *sig, const void *buf, - size_t length) - { - if (debug) - { fprintf(stderr, "ops_signature_add_data adds to hash\n"); } - sig->hash.add(&sig->hash, buf, length); - } - -/** - * \ingroup Core_Signature - * - * Mark the end of the hashed subpackets in the signature - * - * \param sig - */ - -ops_boolean_t ops_signature_hashed_subpackets_end(ops_create_signature_t *sig) - { - sig->hashed_data_length=ops_memory_get_length(sig->mem) - -sig->hashed_count_offset-2; - ops_memory_place_int(sig->mem, sig->hashed_count_offset, - sig->hashed_data_length, 2); - // dummy unhashed subpacket count - sig->unhashed_count_offset=ops_memory_get_length(sig->mem); - return ops_write_scalar(0, 2, sig->info); - } - -/** - * \ingroup Core_Signature - * - * Write out a signature - * - * \param sig - * \param key - * \param skey - * \param info - * - */ - -ops_boolean_t ops_write_signature(ops_create_signature_t *sig, - const ops_public_key_t *key, - const ops_secret_key_t *skey, - ops_create_info_t *info) -{ - ops_boolean_t rtn=ops_false; - size_t l=ops_memory_get_length(sig->mem); - - // check key not decrypted - switch (skey->public_key.algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - if(skey->key.rsa.d == NULL) - { - fprintf(stderr, "Malformed secret key when signing (rsa.d = 0). Can't sign.\n") ; - return ops_false ; - } - break; - - case OPS_PKA_DSA: - if(skey->key.dsa.x == NULL) - { - fprintf(stderr, "Malformed secret key when signing (dsa.x = 0). Can't sign.\n") ; - return ops_false ; - } - break; - - default: - fprintf(stderr, "Unsupported algorithm %d when signing. Sorry.\n", skey->public_key.algorithm); - return ops_false ; - } - - if(sig->hashed_data_length == (unsigned)-1) - { - fprintf(stderr, "Hashed data not initialized properly when signing. Sorry.\n") ; - return ops_false ; - } - - ops_memory_place_int(sig->mem, sig->unhashed_count_offset, - l-sig->unhashed_count_offset-2, 2); - - // add the packet from version number to end of hashed subpackets - - if (debug) - { fprintf(stderr, "--- Adding packet to hash from version number to" - " hashed subpkts\n"); } - - sig->hash.add(&sig->hash, ops_memory_get_data(sig->mem), - sig->unhashed_count_offset); - - // add final trailer - ops_hash_add_int(&sig->hash, sig->sig.info.version, 1); - ops_hash_add_int(&sig->hash, 0xff, 1); - // +6 for version, type, pk alg, hash alg, hashed subpacket length - ops_hash_add_int(&sig->hash, sig->hashed_data_length+6, 4); - - if (debug) - { fprintf(stderr, "--- Finished adding packet to hash from version" - " number to hashed subpkts\n"); } - - // XXX: technically, we could figure out how big the signature is - // and write it directly to the output instead of via memory. - switch(skey->public_key.algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - if(!rsa_sign(&sig->hash, &key->key.rsa, &skey->key.rsa, sig->info)) - { - fprintf(stderr, "error in rsa_sign. Can't produce signature\n") ; - return ops_false; - } - break; - - case OPS_PKA_DSA: - if(!dsa_sign(&sig->hash, &key->key.dsa, &skey->key.dsa, sig->info)) - { - fprintf(stderr, "error in dsa_sign. Can't produce signature\n") ; - return ops_false; - } - break; - - default: - fprintf(stderr, "Unsupported algorithm %d in signature\n", skey->public_key.algorithm); - return ops_false ; - } - - rtn=ops_write_ptag(OPS_PTAG_CT_SIGNATURE, info); - if (rtn) - { - l=ops_memory_get_length(sig->mem); - rtn = ops_write_length(l, info) - && ops_write(ops_memory_get_data(sig->mem), l, info); - } - - ops_memory_free(sig->mem); - - if (!rtn) - OPS_ERROR(&info->errors, OPS_E_W, "Cannot write signature"); - return rtn; -} - -/** - * \ingroup Core_Signature - * - * ops_signature_add_creation_time() adds a creation time to the signature. - * - * \param sig - * \param when - */ -ops_boolean_t ops_signature_add_creation_time(ops_create_signature_t *sig, - time_t when) - { - return ops_write_ss_header(5, OPS_PTAG_SS_CREATION_TIME, sig->info) - && ops_write_scalar(when, 4, sig->info); - } - -/** - * \ingroup Core_Signature - * - * Adds issuer's key ID to the signature - * - * \param sig - * \param keyid - */ - -ops_boolean_t -ops_signature_add_issuer_key_id(ops_create_signature_t *sig, - const unsigned char keyid[OPS_KEY_ID_SIZE]) - { - return ops_write_ss_header(OPS_KEY_ID_SIZE+1, OPS_PTAG_SS_ISSUER_KEY_ID, - sig->info) - && ops_write(keyid, OPS_KEY_ID_SIZE, sig->info); - } - -/** - * \ingroup Core_Signature - * - * Adds primary user ID to the signature - * - * \param sig - * \param primary - */ -void ops_signature_add_primary_user_id(ops_create_signature_t *sig, - ops_boolean_t primary) - { - ops_write_ss_header(2, OPS_PTAG_SS_PRIMARY_USER_ID, sig->info); - ops_write_scalar(primary, 1, sig->info); - } - -/** - * \ingroup Core_Signature - * - * Get the hash structure in use for the signature. - * - * \param sig The signature structure. - * \return The hash structure. - */ -ops_hash_t *ops_signature_get_hash(ops_create_signature_t *sig) - { return &sig->hash; } - -static int open_output_file(ops_create_info_t **cinfo, - const char* input_filename, - const char* output_filename, - const ops_boolean_t use_armour, - const ops_boolean_t overwrite) - { - int fd_out; - - // setup output file - - if (output_filename) - fd_out=ops_setup_file_write(cinfo, output_filename, overwrite); - else - { - char *myfilename=NULL; - unsigned filenamelen=strlen(input_filename)+4+1; - myfilename=ops_mallocz(filenamelen); - if (use_armour) - snprintf(myfilename, filenamelen, "%s.asc", input_filename); - else - snprintf(myfilename, filenamelen, "%s.gpg", input_filename); - fd_out=ops_setup_file_write(cinfo, myfilename, overwrite); - free(myfilename); - } - - return fd_out; - } - -/** - \ingroup HighLevel_Sign - \brief Sign a file with a Cleartext Signature - \param input_filename Name of file to be signed - \param output_filename Filename to be created. If NULL, filename will be constructed from the input_filename. - \param skey Secret Key to sign with - \param overwrite Allow output file to be overwritten, if set - \return ops_true if OK, else ops_false - - Example code: - \code - void example(const ops_secret_key_t *skey, ops_boolean_t overwrite) - { - if (ops_sign_file_as_cleartext("mytestfile.txt",NULL,skey,overwrite)==ops_true) - printf("OK"); - else - printf("ERR"); - } - \endcode -*/ -ops_boolean_t ops_sign_file_as_cleartext(const char* input_filename, - const char* output_filename, - const ops_secret_key_t *skey, - const ops_boolean_t overwrite) -{ - // \todo allow choice of hash algorithams - // enforce use of SHA1 for now - - unsigned char keyid[OPS_KEY_ID_SIZE]; - ops_create_signature_t *sig=NULL; - - int fd_in=0; - int fd_out=0; - ops_create_info_t *cinfo=NULL; - unsigned char buf[MAXBUF]; - //int flags=0; - ops_boolean_t rtn=ops_false; - ops_boolean_t use_armour=ops_true; - - // open file to sign - - fd_in=ops_open(input_filename, O_RDONLY | O_BINARY, 0); - - if(fd_in < 0) - { - return ops_false; - } - - // set up output file - - fd_out=open_output_file(&cinfo, input_filename, output_filename, use_armour, - overwrite); - - if (fd_out < 0) - { - close(fd_in); - return ops_false; - } - - // set up signature - sig=ops_create_signature_new(); - if (!sig) - { - close (fd_in); - ops_teardown_file_write(cinfo, fd_out); - return ops_false; - } - - // \todo could add more error detection here - ops_signature_start_cleartext_signature(sig, skey, OPS_HASH_SHA1, OPS_SIG_BINARY); - - if (!ops_writer_push_clearsigned(cinfo, sig)) - return ops_false; - - // Do the signing - - for (;;) - { - int n=0; - - n=read(fd_in, buf, sizeof(buf)); - if (!n) - break; - - if(n < 0) - { - fprintf(stderr, "Read error in ops_sign_file_as_cleartext\n"); - close(fd_in) ; - ops_teardown_file_write(cinfo, fd_out); - return ops_false ; - } - ops_write(buf, n, cinfo); - } - close(fd_in); - - // add signature with subpackets: - // - creation time - // - key id - rtn = ops_writer_switch_to_armoured_signature(cinfo) - && ops_signature_add_creation_time(sig, time(NULL)); - - if (!rtn) - { - ops_teardown_file_write(cinfo, fd_out); - return ops_false; - } - - ops_keyid(keyid, &skey->public_key); - - rtn = ops_signature_add_issuer_key_id(sig, keyid) - && ops_signature_hashed_subpackets_end(sig) - && ops_write_signature(sig, &skey->public_key, skey, cinfo); - - if (!rtn) - OPS_ERROR(&cinfo->errors, OPS_E_W, "Cannot sign file as cleartext"); - - // we can't get errors in cinfo->errors while closing - // because ops_teardown_file_write frees everything - // it seems that writer finalisers do not report errors anyway - // and ops_teardown_file_write does not have an return value, so we could not bubble something up - ops_teardown_file_write(cinfo, fd_out); - - return rtn; -} - - -/** - * \ingroup HighLevel_Sign - * \brief Sign a buffer with a Cleartext signature - * \param cleartext Text to be signed - * \param len Length of text - * \param signed_cleartext ops_memory_t struct in which to write the signed cleartext - * \param skey Secret key with which to sign the cleartext - * \return ops_true if OK; else ops_false - - * \note It is the calling function's responsibility to free signed_cleartext - * \note signed_cleartext should be a NULL pointer when passed in - - Example code: - \code - void example(const ops_secret_key_t *skey) - { - ops_memory_t* mem=NULL; - const char* buf="Some example text"; - size_t len=strlen(buf); - if (ops_sign_buf_as_cleartext(buf,len, &mem, skey)==ops_true) - printf("OK"); - else - printf("ERR"); - // free signed cleartext after use - ops_memory_free(mem); - } - \endcode - */ -ops_boolean_t ops_sign_buf_as_cleartext(const char* cleartext, const size_t len, - ops_memory_t** signed_cleartext, - const ops_secret_key_t *skey) -{ - ops_boolean_t rtn=ops_false; - - // \todo allow choice of hash algorithams - // enforce use of SHA1 for now - - unsigned char keyid[OPS_KEY_ID_SIZE]; - ops_create_signature_t *sig=NULL; - - ops_create_info_t *cinfo=NULL; - - if(*signed_cleartext != NULL) - { - fprintf(stderr,"ops_sign_buf_as_cleartext: error. Variable signed_cleartext should point to NULL.\n") ; - return ops_false ; - } - - // set up signature - sig=ops_create_signature_new(); - if (!sig) - return ops_false; - - // \todo could add more error detection here - ops_signature_start_cleartext_signature(sig, skey, OPS_HASH_SHA1, OPS_SIG_BINARY); - - // set up output file - ops_setup_memory_write(&cinfo, signed_cleartext, len); - - // Do the signing - // add signature with subpackets: - // - creation time - // - key id - rtn = ops_writer_push_clearsigned(cinfo, sig) - && ops_write(cleartext, len, cinfo) - && ops_writer_switch_to_armoured_signature(cinfo) - && ops_signature_add_creation_time(sig, time(NULL)); - - if (!rtn) - return ops_false; - - ops_keyid(keyid, &skey->public_key); - - rtn = ops_signature_add_issuer_key_id(sig, keyid) - && ops_signature_hashed_subpackets_end(sig) - && ops_write_signature(sig, &skey->public_key, skey, cinfo) - && ops_writer_close(cinfo); - - // Note: the calling function must free signed_cleartext - ops_create_info_delete(cinfo); - - return rtn; -} - -/** -\ingroup HighLevel_Sign -\brief Sign a file -\param input_filename Input filename -\param output_filename Output filename. If NULL, a name is constructed from the input filename. -\param skey Secret Key to use for signing -\param use_armour Write armoured text, if set. -\param overwrite May overwrite existing file, if set. -\return ops_true if OK; else ops_false; - -Example code: -\code -void example(const ops_secret_key_t *skey) -{ - const char* filename="mytestfile"; - const ops_boolean_t use_armour=ops_false; - const ops_boolean_t overwrite=ops_false; - if (ops_sign_file(filename, NULL, skey, use_armour, overwrite)==ops_true) - printf("OK"); - else - printf("ERR"); -} -\endcode -*/ -ops_boolean_t ops_sign_file(const char* input_filename, - const char* output_filename, - const ops_secret_key_t *skey, - const ops_boolean_t use_armour, - const ops_boolean_t overwrite) - { - // \todo allow choice of hash algorithams - // enforce use of SHA1 for now - - unsigned char keyid[OPS_KEY_ID_SIZE]; - ops_create_signature_t *sig=NULL; - - int fd_out=0; - ops_create_info_t *cinfo=NULL; - - ops_hash_algorithm_t hash_alg=OPS_HASH_SHA1; - ops_sig_type_t sig_type=OPS_SIG_BINARY; - - ops_memory_t* mem_buf=NULL; - ops_hash_t* hash=NULL; - - // read input file into buf - - int errnum; - mem_buf=ops_write_mem_from_file(input_filename, &errnum); - if (errnum) - return ops_false; - - // setup output file - - fd_out=open_output_file(&cinfo, input_filename, output_filename, use_armour, - overwrite); - - if (fd_out < 0) - { - ops_memory_free(mem_buf); - return ops_false; - } - - // set up signature - sig=ops_create_signature_new(); - ops_signature_start_message_signature(sig, skey, hash_alg, sig_type); - - // set armoured/not armoured here - if (use_armour) - ops_writer_push_armoured_message(cinfo); - - if (debug) - { fprintf(stderr, "** Writing out one pass sig\n"); } - - // write one_pass_sig - ops_write_one_pass_sig(skey, hash_alg, sig_type, cinfo); - - // hash file contents - hash=ops_signature_get_hash(sig); - hash->add(hash, ops_memory_get_data(mem_buf), - ops_memory_get_length(mem_buf)); - - // output file contents as Literal Data packet - - if (debug) - fprintf(stderr,"** Writing out data now\n"); - - ops_write_literal_data_from_buf(ops_memory_get_data(mem_buf), - ops_memory_get_length(mem_buf), - OPS_LDT_BINARY, cinfo); - - if (debug) - fprintf(stderr, "** After Writing out data now\n"); - - // add subpackets to signature - // - creation time - // - key id - - ops_signature_add_creation_time(sig, time(NULL)); - - ops_keyid(keyid, &skey->public_key); - ops_signature_add_issuer_key_id(sig, keyid); - - ops_signature_hashed_subpackets_end(sig); - - // write out sig - ops_write_signature(sig, &skey->public_key, skey, cinfo); - - ops_teardown_file_write(cinfo, fd_out); - - // tidy up - ops_create_signature_delete(sig); - ops_memory_free(mem_buf); - - return ops_true; - } - -/** -\ingroup HighLevel_Sign -\brief Signs a buffer -\param input Input text to be signed -\param input_len Length of input text -\param sig_type Signature type -\param skey Secret Key -\param use_armour Write armoured text, if set -\param include_data Includes the signed data in the output message. If not, creates a detached signature. -\return New ops_memory_t struct containing signed text -\note It is the caller's responsibility to call ops_memory_free(me) - -Example Code: -\code -void example(const ops_secret_key_t *skey) -{ - const char* buf="Some example text"; - const size_t len=strlen(buf); - const ops_boolean_t use_armour=ops_true; - - ops_memory_t* mem=NULL; - - mem=ops_sign_buf(buf,len,OPS_SIG_BINARY,skey,use_armour); - if (mem) - { - printf ("OK"); - ops_memory_free(mem); - } - else - { - printf("ERR"); - } -} -\endcode -*/ -ops_memory_t* ops_sign_buf(const void* input, const size_t input_len, - const ops_sig_type_t sig_type, - const ops_hash_algorithm_t hash_algorithm, - const ops_secret_key_t *skey, - const ops_boolean_t use_armour, - ops_boolean_t include_data, - ops_boolean_t include_creation_time, - ops_boolean_t include_key_id) - { - // \todo allow choice of hash algorithams - // enforce use of SHA1 for now - - unsigned char keyid[OPS_KEY_ID_SIZE]; - ops_create_signature_t *sig=NULL; - - ops_create_info_t *cinfo=NULL; - ops_memory_t *mem=ops_memory_new(); - - ops_hash_algorithm_t hash_alg=hash_algorithm ; - ops_literal_data_type_t ld_type; - ops_hash_t* hash=NULL; - - // setup literal data packet type - if (sig_type == OPS_SIG_BINARY) - ld_type=OPS_LDT_BINARY; - else - ld_type=OPS_LDT_TEXT; - - // set up signature - sig=ops_create_signature_new(); - ops_signature_start_message_signature(sig, skey, hash_alg, sig_type); - - // setup writer - ops_setup_memory_write(&cinfo, &mem, input_len); - - // set armoured/not armoured here - if (use_armour) - ops_writer_push_armoured_message(cinfo); - - if (debug) - fprintf(stderr, "** Writing out one pass sig\n"); - - // write one_pass_sig - if(include_data) - ops_write_one_pass_sig(skey, hash_alg, sig_type, cinfo); - - // hash file contents - hash=ops_signature_get_hash(sig); - hash->add(hash, input, input_len); - - // output file contents as Literal Data packet - - if (debug) - fprintf(stderr,"** Writing out data now\n"); - - if(include_data) - ops_write_literal_data_from_buf(input, input_len, ld_type, cinfo); - - if (debug) - fprintf(stderr,"** After Writing out data now\n"); - - // add subpackets to signature - // - creation time - // - key id - - if(include_creation_time) - ops_signature_add_creation_time(sig, time(NULL)); - - if(include_key_id) - { - ops_keyid(keyid, &skey->public_key); - ops_signature_add_issuer_key_id(sig, keyid); - } - - ops_signature_hashed_subpackets_end(sig); - - // write out sig - ops_write_signature(sig, &skey->public_key, skey, cinfo); - - // tidy up - ops_writer_close(cinfo); - free(cinfo) ; - ops_create_signature_delete(sig); - - return mem; - } - -typedef struct { - ops_create_signature_t *signature; - const ops_secret_key_t *skey; - ops_hash_algorithm_t hash_alg; - ops_sig_type_t sig_type; -} signature_arg_t; - -static ops_boolean_t stream_signature_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - signature_arg_t* arg = ops_writer_get_arg(winfo); - // Add the input data to the hash. At the end, we will use the hash - // to generate a signature packet. - ops_hash_t* hash = ops_signature_get_hash(arg->signature); - hash->add(hash, src, length); - - return ops_stacked_write(src, length, errors, winfo); - } - -static ops_boolean_t stream_signature_write_trailer(ops_create_info_t *cinfo, - void *data) - { - signature_arg_t* arg = data; - unsigned char keyid[OPS_KEY_ID_SIZE]; - - // add subpackets to signature - // - creation time - // - key id - ops_signature_add_creation_time(arg->signature,time(NULL)); - ops_keyid(keyid, &arg->skey->public_key); - ops_signature_add_issuer_key_id(arg->signature, keyid); - ops_signature_hashed_subpackets_end(arg->signature); - - // write out signature - return ops_write_signature(arg->signature, &arg->skey->public_key, - arg->skey, cinfo); - } - -static void stream_signature_destroyer(ops_writer_info_t *winfo) - { - signature_arg_t* arg = ops_writer_get_arg(winfo); - ops_create_signature_delete(arg->signature); - free(arg); - } - -/** -\ingroup Core_WritePackets -\brief Pushes a signed writer onto the stack. - -Data written will be encoded as a onepass signature packet, followed -by a literal packet, followed by a signature packet. Once this writer -has been added to the stack, cleartext can be written straight to the -output, and it will be encoded as a literal packet and signed. - -\param cinfo Write settings -\param sig_type the type of input to be signed (text or binary) -\param skey the key used to sign the stream. -\return false if the initial onepass packet could not be created. -*/ -ops_boolean_t ops_writer_push_signed(ops_create_info_t *cinfo, - const ops_sig_type_t sig_type, - const ops_secret_key_t *skey) - { - // \todo allow choice of hash algorithams - // enforce use of SHA1 for now - - // Create arg to be used with this writer - // Remember to free this in the destroyer - signature_arg_t *signature_arg = ops_mallocz(sizeof *signature_arg); - signature_arg->signature = ops_create_signature_new(); - signature_arg->hash_alg = OPS_HASH_SHA1; - signature_arg->skey = skey; - signature_arg->sig_type = sig_type; - ops_signature_start_message_signature(signature_arg->signature, - signature_arg->skey, - signature_arg->hash_alg, - signature_arg->sig_type); - - if (!ops_write_one_pass_sig(signature_arg->skey, - signature_arg->hash_alg, - signature_arg->sig_type, - cinfo)) - return ops_false; - - ops_writer_push_partial_with_trailer(0, cinfo, OPS_PTAG_CT_LITERAL_DATA, - write_literal_header, NULL, - stream_signature_write_trailer, - signature_arg); - // And push writer on stack - ops_writer_push(cinfo, stream_signature_writer, NULL, - stream_signature_destroyer,signature_arg); - return ops_true; - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/signature.h b/openpgpsdk/src/openpgpsdk/signature.h deleted file mode 100644 index eb87d0ee5..000000000 --- a/openpgpsdk/src/openpgpsdk/signature.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_SIGNATURE_H -#define OPS_SIGNATURE_H - -#include "packet.h" -#include "util.h" -#include "create.h" - -typedef struct ops_create_signature ops_create_signature_t; - -ops_create_signature_t *ops_create_signature_new(void); -void ops_create_signature_delete(ops_create_signature_t *sig); - -ops_boolean_t -ops_check_user_id_certification_signature(const ops_public_key_t *key, - const ops_user_id_t *id, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet); -ops_boolean_t -ops_check_user_attribute_certification_signature(const ops_public_key_t *key, - const ops_user_attribute_t *attribute, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet); -ops_boolean_t -ops_check_subkey_signature(const ops_public_key_t *key, - const ops_public_key_t *subkey, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet); -ops_boolean_t -ops_check_direct_signature(const ops_public_key_t *key, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet); -ops_boolean_t -ops_check_hash_signature(ops_hash_t *hash, - const ops_signature_t *sig, - const ops_public_key_t *signer); -void ops_signature_start_key_signature(ops_create_signature_t *sig, - const ops_public_key_t *key, - const ops_user_id_t *id, - ops_sig_type_t type); -void ops_signature_start_cleartext_signature(ops_create_signature_t *sig, - const ops_secret_key_t *key, - const ops_hash_algorithm_t hash, - const ops_sig_type_t type); -void ops_signature_start_message_signature(ops_create_signature_t *sig, - const ops_secret_key_t *key, - const ops_hash_algorithm_t hash, - const ops_sig_type_t type); - -void ops_signature_add_data(ops_create_signature_t *sig,const void *buf, - size_t length); -ops_hash_t *ops_signature_get_hash(ops_create_signature_t *sig); -ops_boolean_t ops_signature_hashed_subpackets_end(ops_create_signature_t *sig); -ops_boolean_t ops_write_signature(ops_create_signature_t *sig,const ops_public_key_t *key, - const ops_secret_key_t *skey, ops_create_info_t *opt); -ops_boolean_t ops_signature_add_creation_time(ops_create_signature_t *sig,time_t when); -ops_boolean_t ops_signature_add_issuer_key_id(ops_create_signature_t *sig, - const unsigned char keyid[OPS_KEY_ID_SIZE]); -void ops_signature_add_primary_user_id(ops_create_signature_t *sig, - ops_boolean_t primary); - -// Standard Interface -ops_boolean_t ops_sign_file_as_cleartext(const char* input_filename, const char* output_filename, const ops_secret_key_t *skey, const ops_boolean_t overwrite); -ops_boolean_t ops_sign_buf_as_cleartext(const char* input, const size_t len, ops_memory_t** output, const ops_secret_key_t *skey); -ops_boolean_t ops_sign_file(const char* input_filename, const char* output_filename, const ops_secret_key_t *skey, const ops_boolean_t use_armour, const ops_boolean_t overwrite); -ops_memory_t * ops_sign_buf(const void* input, const size_t input_len, const ops_sig_type_t sig_type, const ops_hash_algorithm_t hash_algorithm, const ops_secret_key_t *skey, const ops_boolean_t use_armour, ops_boolean_t include_data, ops_boolean_t include_creation_time, ops_boolean_t include_key_id); -ops_boolean_t ops_writer_push_signed(ops_create_info_t *cinfo, const ops_sig_type_t sig_type, const ops_secret_key_t *skey); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/std_print.h b/openpgpsdk/src/openpgpsdk/std_print.h deleted file mode 100644 index f6ae7dba1..000000000 --- a/openpgpsdk/src/openpgpsdk/std_print.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_STD_PRINT_H -#define OPS_STD_PRINT_H - -#include "openpgpsdk/packet.h" -#include "openpgpsdk/packet-parse.h" -#include "openpgpsdk/keyring.h" - -void print_bn( const char *name, - const BIGNUM *bn); -void ops_print_pk_session_key(ops_content_tag_t tag, - const ops_pk_session_key_t *key); -void ops_print_public_keydata(const ops_keydata_t *key); - -void ops_print_public_keydata_verbose(const ops_keydata_t *key); -void ops_print_public_key(const ops_public_key_t *pkey); - -void ops_print_secret_keydata(const ops_keydata_t *key); -void ops_print_secret_keydata_verbose(const ops_keydata_t *key); -//void ops_print_secret_key(const ops_content_tag_t type, const ops_secret_key_t* skey); -int ops_print_packet(const ops_parser_content_t *content_); -void ops_list_packets(char *filename, ops_boolean_t armour, ops_keyring_t* pubring, ops_parse_cb_t* cb_get_passphrase); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/streamwriter.h b/openpgpsdk/src/openpgpsdk/streamwriter.h deleted file mode 100644 index 70f77990d..000000000 --- a/openpgpsdk/src/openpgpsdk/streamwriter.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __OPS_STREAMWRITER_H__ -#define __OPS_STREAMWRITER_H__ - -#include - -void ops_writer_push_stream_encrypt_se_ip(ops_create_info_t *cinfo, - const ops_keydata_t *pub_key); - -#endif /*__OPS_STREAMWRITER_H__*/ diff --git a/openpgpsdk/src/openpgpsdk/symmetric.c b/openpgpsdk/src/openpgpsdk/symmetric.c deleted file mode 100644 index 30dc0b74b..000000000 --- a/openpgpsdk/src/openpgpsdk/symmetric.c +++ /dev/null @@ -1,683 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#ifndef OPENSSL_NO_IDEA -# include -#endif -#include -#ifndef OPENSSL_NO_CAMELLIA -# include -#endif -#include -#include "parse_local.h" - -#include -#include - -//static int debug=0; - -#ifndef ATTRIBUTE_UNUSED - -#ifndef WIN32 -#define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -#else -#define ATTRIBUTE_UNUSED -#endif // #ifndef WIN32 - -#endif /* ATTRIBUTE_UNUSED */ - -static void std_set_iv(ops_crypt_t *crypt,const unsigned char *iv) - { - memcpy(crypt->iv,iv,crypt->blocksize); - crypt->num=0; - } - -static void std_set_key(ops_crypt_t *crypt,const unsigned char *key) - { memcpy(crypt->key,key,crypt->keysize); } - -static void std_resync(ops_crypt_t *decrypt) - { - if(decrypt->num == decrypt->blocksize) - return; - - memmove(decrypt->civ+decrypt->blocksize-decrypt->num,decrypt->civ, - decrypt->num); - memcpy(decrypt->civ,decrypt->siv+decrypt->num, - decrypt->blocksize-decrypt->num); - decrypt->num=0; - } - -static void std_finish(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - { - free(crypt->encrypt_key); - crypt->encrypt_key=NULL; - } - if (crypt->decrypt_key) - { - free(crypt->decrypt_key); - crypt->decrypt_key=NULL; - } - } - -static void cast5_init(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(CAST_KEY)); - CAST_set_key(crypt->encrypt_key,crypt->keysize,crypt->key); - crypt->decrypt_key=malloc(sizeof(CAST_KEY)); - CAST_set_key(crypt->decrypt_key,crypt->keysize,crypt->key); - } - -static void cast5_block_encrypt(ops_crypt_t *crypt,void *out,const void *in) - { CAST_ecb_encrypt(in,out,crypt->encrypt_key,CAST_ENCRYPT); } - -static void cast5_block_decrypt(ops_crypt_t *crypt,void *out,const void *in) - { CAST_ecb_encrypt(in,out,crypt->encrypt_key,CAST_DECRYPT); } - -static void cast5_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - CAST_cfb64_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - CAST_ENCRYPT); - } - -static void cast5_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - CAST_cfb64_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - CAST_DECRYPT); - } - -#define TRAILER "","","","",0,NULL,NULL - -static ops_crypt_t cast5= - { - OPS_SA_CAST5, - CAST_BLOCK, - CAST_KEY_LENGTH, - std_set_iv, - std_set_key, - cast5_init, - std_resync, - cast5_block_encrypt, - cast5_block_decrypt, - cast5_cfb_encrypt, - cast5_cfb_decrypt, - std_finish, - TRAILER - }; - -#ifndef OPENSSL_NO_IDEA -static void idea_init(ops_crypt_t *crypt) - { - assert(crypt->keysize == IDEA_KEY_LENGTH); - - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(IDEA_KEY_SCHEDULE)); - - // note that we don't invert the key when decrypting for CFB mode - idea_set_encrypt_key(crypt->key,crypt->encrypt_key); - - if (crypt->decrypt_key) - free(crypt->decrypt_key); - crypt->decrypt_key=malloc(sizeof(IDEA_KEY_SCHEDULE)); - - idea_set_decrypt_key(crypt->encrypt_key,crypt->decrypt_key); - } - -static void idea_block_encrypt(ops_crypt_t *crypt,void *out,const void *in) - { idea_ecb_encrypt(in,out,crypt->encrypt_key); } - -static void idea_block_decrypt(ops_crypt_t *crypt,void *out,const void *in) - { idea_ecb_encrypt(in,out,crypt->decrypt_key); } - -static void idea_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - idea_cfb64_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - CAST_ENCRYPT); - } - -static void idea_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - idea_cfb64_encrypt(in,out,count, - crypt->decrypt_key, crypt->iv, (int *)&crypt->num, - CAST_DECRYPT); - } - -static const ops_crypt_t idea= - { - OPS_SA_IDEA, - IDEA_BLOCK, - IDEA_KEY_LENGTH, - std_set_iv, - std_set_key, - idea_init, - std_resync, - idea_block_encrypt, - idea_block_decrypt, - idea_cfb_encrypt, - idea_cfb_decrypt, - std_finish, - TRAILER - }; -#endif /* OPENSSL_NO_IDEA */ - -// AES with 128-bit key (AES) - -#define KEYBITS_AES128 128 - -static void aes128_init(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(AES_KEY)); - if (AES_set_encrypt_key(crypt->key,KEYBITS_AES128,crypt->encrypt_key)) - fprintf(stderr,"aes128_init: Error setting encrypt_key\n"); - - if (crypt->decrypt_key) - free(crypt->decrypt_key); - crypt->decrypt_key=malloc(sizeof(AES_KEY)); - if (AES_set_decrypt_key(crypt->key,KEYBITS_AES128,crypt->decrypt_key)) - fprintf(stderr,"aes128_init: Error setting decrypt_key\n"); - } - -static void aes_block_encrypt(ops_crypt_t *crypt,void *out,const void *in) - { AES_encrypt(in,out,crypt->encrypt_key); } - -static void aes_block_decrypt(ops_crypt_t *crypt,void *out,const void *in) - { AES_decrypt(in,out,crypt->decrypt_key); } - -static void aes_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - AES_cfb128_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - AES_ENCRYPT); - } - -static void aes_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - AES_cfb128_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - AES_DECRYPT); - } - -static const ops_crypt_t aes128= - { - OPS_SA_AES_128, - AES_BLOCK_SIZE, - KEYBITS_AES128/8, - std_set_iv, - std_set_key, - aes128_init, - std_resync, - aes_block_encrypt, - aes_block_decrypt, - aes_cfb_encrypt, - aes_cfb_decrypt, - std_finish, - TRAILER - }; - -// AES with 256-bit key - -#define KEYBITS_AES256 256 - -static void aes256_init(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(AES_KEY)); - if (AES_set_encrypt_key(crypt->key,KEYBITS_AES256,crypt->encrypt_key)) - fprintf(stderr,"aes256_init: Error setting encrypt_key\n"); - - if (crypt->decrypt_key) - free(crypt->decrypt_key); - crypt->decrypt_key=malloc(sizeof(AES_KEY)); - if (AES_set_decrypt_key(crypt->key,KEYBITS_AES256,crypt->decrypt_key)) - fprintf(stderr,"aes256_init: Error setting decrypt_key\n"); - } - -static const ops_crypt_t aes256= - { - OPS_SA_AES_256, - AES_BLOCK_SIZE, - KEYBITS_AES256/8, - std_set_iv, - std_set_key, - aes256_init, - std_resync, - aes_block_encrypt, - aes_block_decrypt, - aes_cfb_encrypt, - aes_cfb_decrypt, - std_finish, - TRAILER - }; - -#ifndef OPENSSL_NO_CAMELLIA - -// CAMELLIA with 128-bit key - -#define KEYBITS_CAMELLIA128 128 - -static void camellia128_init(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(CAMELLIA_KEY)); - if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA128,crypt->encrypt_key)) - fprintf(stderr,"camellia128_init: Error setting encrypt_key\n"); - - if (crypt->decrypt_key) - free(crypt->decrypt_key); - crypt->decrypt_key=malloc(sizeof(CAMELLIA_KEY)); - if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA128,crypt->decrypt_key)) - fprintf(stderr,"camellia128_init: Error setting decrypt_key\n"); - } - -static void camellia_block_encrypt(ops_crypt_t *crypt,void *out,const void *in) - { Camellia_encrypt(in,out,crypt->encrypt_key); } - -static void camellia_block_decrypt(ops_crypt_t *crypt,void *out,const void *in) - { Camellia_decrypt(in,out,crypt->decrypt_key); } - -static void camellia_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - Camellia_cfb128_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - CAMELLIA_ENCRYPT); - } - -static void camellia_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - Camellia_cfb128_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - CAMELLIA_DECRYPT); - } - -static const ops_crypt_t camellia128= - { - OPS_SA_CAMELLIA_128, - CAMELLIA_BLOCK_SIZE, - KEYBITS_CAMELLIA128/8, - std_set_iv, - std_set_key, - camellia128_init, - std_resync, - camellia_block_encrypt, - camellia_block_decrypt, - camellia_cfb_encrypt, - camellia_cfb_decrypt, - std_finish, - TRAILER - }; - -// CAMELLIA with 192-bit key - -#define KEYBITS_CAMELLIA192 192 - -static void camellia192_init(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(CAMELLIA_KEY)); - if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA192,crypt->encrypt_key)) - fprintf(stderr,"camellia192_init: Error setting encrypt_key\n"); - - if (crypt->decrypt_key) - free(crypt->decrypt_key); - crypt->decrypt_key=malloc(sizeof(CAMELLIA_KEY)); - if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA192,crypt->decrypt_key)) - fprintf(stderr,"camellia192_init: Error setting decrypt_key\n"); - } - -static const ops_crypt_t camellia192= - { - OPS_SA_CAMELLIA_192, - CAMELLIA_BLOCK_SIZE, - KEYBITS_CAMELLIA192/8, - std_set_iv, - std_set_key, - camellia192_init, - std_resync, - camellia_block_encrypt, - camellia_block_decrypt, - camellia_cfb_encrypt, - camellia_cfb_decrypt, - std_finish, - TRAILER - }; - -// CAMELLIA with 256-bit key - -#define KEYBITS_CAMELLIA256 256 - -static void camellia256_init(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(CAMELLIA_KEY)); - if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA256,crypt->encrypt_key)) - fprintf(stderr,"camellia256_init: Error setting encrypt_key\n"); - - if (crypt->decrypt_key) - free(crypt->decrypt_key); - crypt->decrypt_key=malloc(sizeof(CAMELLIA_KEY)); - if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA256,crypt->decrypt_key)) - fprintf(stderr,"camellia256_init: Error setting decrypt_key\n"); - } - -static const ops_crypt_t camellia256= - { - OPS_SA_CAMELLIA_256, - CAMELLIA_BLOCK_SIZE, - KEYBITS_CAMELLIA256/8, - std_set_iv, - std_set_key, - camellia256_init, - std_resync, - camellia_block_encrypt, - camellia_block_decrypt, - camellia_cfb_encrypt, - camellia_cfb_decrypt, - std_finish, - TRAILER - }; - -#endif // ndef OPENSSL_NO_CAMELLIA - -// Triple DES - -static void tripledes_init(ops_crypt_t *crypt) - { - DES_key_schedule *keys; - int n; - - if (crypt->encrypt_key) - free(crypt->encrypt_key); - keys=crypt->encrypt_key=malloc(3*sizeof(DES_key_schedule)); - - for(n=0 ; n < 3 ; ++n) - DES_set_key((DES_cblock *)(crypt->key+n*8),&keys[n]); - } - -static void tripledes_block_encrypt(ops_crypt_t *crypt,void *out, - const void *in) - { - DES_key_schedule *keys=crypt->encrypt_key; - - DES_ecb3_encrypt((void *)in,out,&keys[0],&keys[1],&keys[2],DES_ENCRYPT); - } - -static void tripledes_block_decrypt(ops_crypt_t *crypt,void *out, - const void *in) - { - DES_key_schedule *keys=crypt->encrypt_key; - - DES_ecb3_encrypt((void *)in,out,&keys[0],&keys[1],&keys[2],DES_DECRYPT); - } - -static void tripledes_cfb_encrypt(ops_crypt_t *crypt ATTRIBUTE_UNUSED, - void *out ATTRIBUTE_UNUSED, - const void *in ATTRIBUTE_UNUSED, - size_t count ATTRIBUTE_UNUSED) - { - DES_key_schedule *keys=crypt->encrypt_key; - DES_ede3_cfb64_encrypt(in,out,count, - &keys[0],&keys[1],&keys[2], - (DES_cblock *)crypt->iv, (int *)&crypt->num, - DES_ENCRYPT); - } - -static void tripledes_cfb_decrypt(ops_crypt_t *crypt ATTRIBUTE_UNUSED, - void *out ATTRIBUTE_UNUSED, - const void *in ATTRIBUTE_UNUSED, - size_t count ATTRIBUTE_UNUSED) - { - DES_key_schedule *keys=crypt->encrypt_key; - DES_ede3_cfb64_encrypt(in,out,count, - &keys[0],&keys[1],&keys[2], - (DES_cblock *)crypt->iv, (int *)&crypt->num, - DES_DECRYPT); - } - -static const ops_crypt_t tripledes= - { - OPS_SA_TRIPLEDES, - 8, - 24, - std_set_iv, - std_set_key, - tripledes_init, - std_resync, - tripledes_block_encrypt, - tripledes_block_decrypt, - tripledes_cfb_encrypt, - tripledes_cfb_decrypt, - std_finish, - TRAILER - }; - -static const ops_crypt_t *get_proto(ops_symmetric_algorithm_t alg) - { - switch(alg) - { - case OPS_SA_CAST5: - return &cast5; - -#ifndef OPENSSL_NO_IDEA - case OPS_SA_IDEA: - return &idea; -#endif /* OPENSSL_NO_IDEA */ - - case OPS_SA_AES_128: - return &aes128; - - case OPS_SA_AES_256: - return &aes256; - -#ifndef OPENSSL_NO_CAMELLIA - case OPS_SA_CAMELLIA_128: - return &camellia128; - - case OPS_SA_CAMELLIA_192: - return &camellia192; - - case OPS_SA_CAMELLIA_256: - return &camellia256; -#endif // ndef OPENSSL_NO_CAMELLIA - - case OPS_SA_TRIPLEDES: - return &tripledes; - - default: - fprintf(stderr,"Unknown algorithm: %d (%s)\n",alg, - ops_show_symmetric_algorithm(alg)); - // assert(0); - } - - return NULL; - } - -int ops_crypt_any(ops_crypt_t *crypt,ops_symmetric_algorithm_t alg) - { - const ops_crypt_t *ptr=get_proto(alg); - if (ptr) - { - *crypt=*ptr; - return 1; - } - else - { - memset(crypt,'\0',sizeof *crypt); - return 0; - } - } - -unsigned ops_block_size(ops_symmetric_algorithm_t alg) - { - const ops_crypt_t *p=get_proto(alg); - - if(!p) - return 0; - - return p->blocksize; - } - -unsigned ops_key_size(ops_symmetric_algorithm_t alg) - { - const ops_crypt_t *p=get_proto(alg); - - if(!p) - return 0; - - return p->keysize; - } - -void ops_encrypt_init(ops_crypt_t * encrypt) - { - // \todo should there be a separate ops_encrypt_init? - ops_decrypt_init(encrypt); - } - -void ops_decrypt_init(ops_crypt_t *decrypt) - { - decrypt->base_init(decrypt); - decrypt->block_encrypt(decrypt,decrypt->siv,decrypt->iv); - memcpy(decrypt->civ,decrypt->siv,decrypt->blocksize); - decrypt->num=0; - } - -size_t ops_decrypt_se -(ops_crypt_t *decrypt,void *out_,const void *in_, - size_t count) - { - unsigned char *out=out_; - const unsigned char *in=in_; - int saved=count; - - /* in order to support v3's weird resyncing we have to implement CFB mode - ourselves */ - while(count-- > 0) - { - unsigned char t; - - if(decrypt->num == decrypt->blocksize) - { - memcpy(decrypt->siv,decrypt->civ,decrypt->blocksize); - decrypt->block_decrypt(decrypt,decrypt->civ,decrypt->civ); - decrypt->num=0; - } - t=decrypt->civ[decrypt->num]; - *out++=t^(decrypt->civ[decrypt->num++]=*in++); - } - - return saved; - } - -size_t ops_encrypt_se(ops_crypt_t *encrypt,void *out_,const void *in_, - size_t count) - { - unsigned char *out=out_; - const unsigned char *in=in_; - int saved=count; - - /* in order to support v3's weird resyncing we have to implement CFB mode - ourselves */ - while(count-- > 0) - { - if(encrypt->num == encrypt->blocksize) - { - memcpy(encrypt->siv,encrypt->civ,encrypt->blocksize); - encrypt->block_encrypt(encrypt,encrypt->civ,encrypt->civ); - encrypt->num=0; - } - encrypt->civ[encrypt->num]=*out++=encrypt->civ[encrypt->num]^*in++; - ++encrypt->num; - } - - return saved; - } - -/** -\ingroup HighLevel_Supported -\brief Is this Symmetric Algorithm supported? -\param alg Symmetric Algorithm to check -\return ops_true if supported; else ops_false -*/ -ops_boolean_t ops_is_sa_supported(ops_symmetric_algorithm_t alg) - { - switch (alg) - { - case OPS_SA_AES_128: - case OPS_SA_AES_256: - case OPS_SA_CAMELLIA_128: - case OPS_SA_CAMELLIA_192: - case OPS_SA_CAMELLIA_256: - case OPS_SA_CAST5: - case OPS_SA_TRIPLEDES: -#ifndef OPENSSL_NO_IDEA - case OPS_SA_IDEA: -#endif - return ops_true; - break; - - default: - fprintf(stderr,"\nWarning: %s not supported\n", - ops_show_symmetric_algorithm(alg)); - return ops_false; - } - } - -size_t ops_encrypt_se_ip(ops_crypt_t *crypt,void *out_,const void *in_, - size_t count) - { - if (!ops_is_sa_supported(crypt->algorithm)) - return -1; - - crypt->cfb_encrypt(crypt, out_, in_, count); - - // \todo test this number was encrypted - return count; - } - -size_t ops_decrypt_se_ip(ops_crypt_t *crypt,void *out_,const void *in_, - size_t count) - { - if (!ops_is_sa_supported(crypt->algorithm)) - return -1; - - crypt->cfb_decrypt(crypt, out_, in_, count); - - // \todo check this number was in fact decrypted - return count; - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/types.h b/openpgpsdk/src/openpgpsdk/types.h deleted file mode 100644 index 50d4107a0..000000000 --- a/openpgpsdk/src/openpgpsdk/types.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_TYPES_H -#define OPS_TYPES_H - -/** Special type for intermediate function casting, avoids warnings on - some platforms -*/ -typedef void (*ops_void_fptr)(void); -#define ops_fcast(f) ((ops_void_fptr)f) - -/** ops_map_t - */ -typedef struct - { - int type; - char *string; - } ops_map_t; - -/** Boolean type */ -typedef unsigned ops_boolean_t; - -/** ops_content_tag_t */ - -/* PTag Content Tags */ -/***************************/ - -/** Package Tags (aka Content Tags) and signature subpacket types. - * This enumerates all rfc-defined packet tag values and the - * signature subpacket type values that we understand. - * - * \see RFC4880 4.3 - * \see RFC4880 5.2.3.1 - */ - -#ifndef __cplusplus -typedef enum ops_content_tag_t ops_content_tag_t ; -#endif - -enum ops_content_tag_t - { - OPS_PTAG_CT_RESERVED = 0, /*!< Reserved - a packet tag must not have this value */ - OPS_PTAG_CT_PK_SESSION_KEY = 1, /*!< Public-Key Encrypted Session Key Packet */ - OPS_PTAG_CT_SIGNATURE = 2, /*!< Signature Packet */ - OPS_PTAG_CT_SK_SESSION_KEY = 3, /*!< Symmetric-Key Encrypted Session Key Packet */ - OPS_PTAG_CT_ONE_PASS_SIGNATURE = 4, /*!< One-Pass Signature Packet */ - OPS_PTAG_CT_SECRET_KEY = 5, /*!< Secret Key Packet */ - OPS_PTAG_CT_PUBLIC_KEY = 6, /*!< Public Key Packet */ - OPS_PTAG_CT_SECRET_SUBKEY = 7, /*!< Secret Subkey Packet */ - OPS_PTAG_CT_COMPRESSED = 8, /*!< Compressed Data Packet */ - OPS_PTAG_CT_SE_DATA = 9, /*!< Symmetrically Encrypted Data Packet */ - OPS_PTAG_CT_MARKER =10, /*!< Marker Packet */ - OPS_PTAG_CT_LITERAL_DATA =11, /*!< Literal Data Packet */ - OPS_PTAG_CT_TRUST =12, /*!< Trust Packet */ - OPS_PTAG_CT_USER_ID =13, /*!< User ID Packet */ - OPS_PTAG_CT_PUBLIC_SUBKEY =14, /*!< Public Subkey Packet */ - OPS_PTAG_CT_RESERVED2 =15, /*!< reserved */ - OPS_PTAG_CT_RESERVED3 =16, /*!< reserved */ - OPS_PTAG_CT_USER_ATTRIBUTE =17, /*!< User Attribute Packet */ - OPS_PTAG_CT_SE_IP_DATA =18, /*!< Sym. Encrypted and Integrity Protected Data Packet */ - OPS_PTAG_CT_MDC =19, /*!< Modification Detection Code Packet */ - - OPS_PARSER_PTAG =0x100, /*!< Internal Use: The packet is the "Packet Tag" itself - used when - callback sends back the PTag. */ - OPS_PTAG_RAW_SS =0x101, /*!< Internal Use: content is raw sig subtag */ - OPS_PTAG_SS_ALL =0x102, /*!< Internal Use: select all subtags */ - OPS_PARSER_PACKET_END =0x103, - - /* signature subpackets (0x200-2ff) (type+0x200) */ - /* only those we can parse are listed here */ - OPS_PTAG_SIGNATURE_SUBPACKET_BASE =0x200, /*!< Base for signature subpacket types - All signature type - values are relative to this value. */ - OPS_PTAG_SS_CREATION_TIME =0x200+2, /*!< signature creation time */ - OPS_PTAG_SS_EXPIRATION_TIME =0x200+3, /*!< signature expiration time */ - - OPS_PTAG_SS_EXPORTABLE_CERTIFICATION =0x200+4, /*!< exportable certification */ - OPS_PTAG_SS_TRUST =0x200+5, /*!< trust signature */ - OPS_PTAG_SS_REGEXP =0x200+6, /*!< regular expression */ - OPS_PTAG_SS_REVOCABLE =0x200+7, /*!< revocable */ - OPS_PTAG_SS_KEY_EXPIRATION_TIME =0x200+9, /*!< key expiration time */ - OPS_PTAG_SS_RESERVED =0x200+10, /*!< reserved */ - OPS_PTAG_SS_PREFERRED_SKA =0x200+11, /*!< preferred symmetric algorithms */ - OPS_PTAG_SS_REVOCATION_KEY =0x200+12, /*!< revocation key */ - OPS_PTAG_SS_ISSUER_KEY_ID =0x200+16, /*!< issuer key ID */ - OPS_PTAG_SS_NOTATION_DATA =0x200+20, /*!< notation data */ - OPS_PTAG_SS_PREFERRED_HASH =0x200+21, /*!< preferred hash algorithms */ - OPS_PTAG_SS_PREFERRED_COMPRESSION =0x200+22, /*!< preferred compression algorithms */ - OPS_PTAG_SS_KEY_SERVER_PREFS =0x200+23, /*!< key server preferences */ - OPS_PTAG_SS_PREFERRED_KEY_SERVER =0x200+24, /*!< Preferred Key Server */ - OPS_PTAG_SS_PRIMARY_USER_ID =0x200+25, /*!< primary User ID */ - OPS_PTAG_SS_POLICY_URI =0x200+26, /*!< Policy URI */ - OPS_PTAG_SS_KEY_FLAGS =0x200+27, /*!< key flags */ - OPS_PTAG_SS_SIGNERS_USER_ID =0x200+28, /*!< Signer's User ID */ - OPS_PTAG_SS_REVOCATION_REASON =0x200+29, /*!< reason for revocation */ - OPS_PTAG_SS_FEATURES =0x200+30, /*!< features */ - OPS_PTAG_SS_SIGNATURE_TARGET =0x200+31, /*!< signature target */ - OPS_PTAG_SS_EMBEDDED_SIGNATURE=0x200+32, /*!< embedded signature */ - - OPS_PTAG_SS_USERDEFINED00 =0x200+100, /*!< internal or user-defined */ - OPS_PTAG_SS_USERDEFINED01 =0x200+101, - OPS_PTAG_SS_USERDEFINED02 =0x200+102, - OPS_PTAG_SS_USERDEFINED03 =0x200+103, - OPS_PTAG_SS_USERDEFINED04 =0x200+104, - OPS_PTAG_SS_USERDEFINED05 =0x200+105, - OPS_PTAG_SS_USERDEFINED06 =0x200+106, - OPS_PTAG_SS_USERDEFINED07 =0x200+107, - OPS_PTAG_SS_USERDEFINED08 =0x200+108, - OPS_PTAG_SS_USERDEFINED09 =0x200+109, - OPS_PTAG_SS_USERDEFINED10 =0x200+110, - - - /* pseudo content types */ - OPS_PTAG_CT_LITERAL_DATA_HEADER =0x300, - OPS_PTAG_CT_LITERAL_DATA_BODY =0x300+1, - OPS_PTAG_CT_SIGNATURE_HEADER =0x300+2, - OPS_PTAG_CT_SIGNATURE_FOOTER =0x300+3, - OPS_PTAG_CT_ARMOUR_HEADER =0x300+4, - OPS_PTAG_CT_ARMOUR_TRAILER =0x300+5, - OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER =0x300+6, - OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY =0x300+7, - OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER=0x300+8, - OPS_PTAG_CT_UNARMOURED_TEXT =0x300+9, - OPS_PTAG_CT_ENCRYPTED_SECRET_KEY =0x300+10, // In this case the algorithm specific fields will not be initialised - OPS_PTAG_CT_SE_DATA_HEADER =0x300+11, - OPS_PTAG_CT_SE_DATA_BODY =0x300+12, - OPS_PTAG_CT_SE_IP_DATA_HEADER =0x300+13, - OPS_PTAG_CT_SE_IP_DATA_BODY =0x300+14, - OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY=0x300+15, - - /* commands to the callback */ - OPS_PARSER_CMD_GET_SK_PASSPHRASE =0x400, - OPS_PARSER_CMD_GET_SECRET_KEY =0x400+1, - OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD =0x400+2, - - /* Errors */ - OPS_PARSER_ERROR =0x500, /*!< Internal Use: Parser Error */ - OPS_PARSER_ERRCODE =0x500+1, /*! < Internal Use: Parser Error with errcode returned */ - }; - -/** Used to specify whether subpackets should be returned raw, parsed or ignored. - */ - -enum ops_parse_type_t - { - OPS_PARSE_RAW, /*!< Callback Raw */ - OPS_PARSE_PARSED, /*!< Callback Parsed */ - OPS_PARSE_IGNORE, /*!< Don't callback */ - }; - -typedef struct _ops_crypt_t ops_crypt_t; - -/** ops_hash_t */ -typedef struct _ops_hash_t ops_hash_t; - -/** - keep both ops_content_tag_t and ops_packet_tag_t because we might - want to introduce some bounds checking i.e. is this really a valid value - for a packet tag? -*/ -typedef enum ops_content_tag_t ops_packet_tag_t; -/** SS types are a subset of all content types. -*/ -typedef enum ops_content_tag_t ops_ss_type_t; -/* typedef enum ops_sig_type_t ops_sig_type_t; */ - -/** Revocation Reason type */ -typedef unsigned char ops_ss_rr_code_t; - -/** ops_parse_type_t */ - -/** Used to specify whether subpackets should be returned raw, parsed or ignored. - */ - -typedef enum ops_parse_type_t ops_parse_type_t; - -/** ops_parser_content_t */ -typedef struct ops_parser_content_t ops_parser_content_t; - -/** Reader Flags */ -/* -typedef enum - { - OPS_RETURN_LENGTH=1, - } ops_reader_flags_t; -typedef enum ops_reader_ret_t ops_reader_ret_t; -*/ - -/** Writer flags */ -typedef enum - { - OPS_WF_DUMMY, - } ops_writer_flags_t; - -/** - * \ingroup Create - * Contains the required information about how to write - */ -typedef struct ops_create_info ops_create_info_t; - -#endif diff --git a/openpgpsdk/src/openpgpsdk/util.c b/openpgpsdk/src/openpgpsdk/util.c deleted file mode 100644 index 2dced1ff0..000000000 --- a/openpgpsdk/src/openpgpsdk/util.c +++ /dev/null @@ -1,179 +0,0 @@ - /* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include -#include -#include - -#ifndef WIN32 -#include -#endif - -#include - -#include - -/** - * Searches the given map for the given type. - * Returns a human-readable descriptive string if found, - * returns NULL if not found - * - * It is the responsibility of the calling function to handle the - * error case sensibly (i.e. don't just print out the return string. - * - */ -static char *str_from_map_or_null(int type, ops_map_t *map) - { - ops_map_t *row; - - for ( row=map; row->string != NULL; row++ ) - if (row->type == type) - return row->string; - return NULL; - } - -/** - * \ingroup Core_Print - * - * Searches the given map for the given type. - * Returns a readable string if found, "Unknown" if not. - */ - -char *ops_str_from_map(int type, ops_map_t *map) - { - char *str; - str=str_from_map_or_null(type,map); - if (str) - return(str); - else - return("Unknown"); - } - -void hexdump(const unsigned char *src,size_t length) - { - while(length--) - printf("%02X",*src++); - } - -/** - * \ingroup HighLevel_Functions - * \brief Initialises OpenPGP::SDK. To be called before any other OPS function. - * - * Initialises OpenPGP::SDK and the underlying openssl library. - */ - -void ops_init(void) - { - ops_crypto_init(); - } - -/** - * \ingroup HighLevel_Functions - * \brief Closes down OpenPGP::SDK. - * - * Close down OpenPGP:SDK, release any resources under the control of - * the library. No OpenPGP:SDK function other than ops_init() should - * be called after this function. - */ - -void ops_finish(void) - { - ops_crypto_finish(); - } - -/** - \ingroup HighLevel_Misc - \brief mallocs and zeros memory - \param n Number of bytes to be alloc-ed. - \return Pointer to new memory. - \note Should be freed after use with free(). -*/ -void *ops_mallocz(size_t n) -{ - void *m=malloc(n); - - if(m == NULL) - fprintf(stderr,"(EE) Cannot allocate %lu bytes of memory in %s\n",n,__PRETTY_FUNCTION__) ; - else - memset(m,'\0',n); - - return m; -} - -typedef struct - { - unsigned short sum; - } sum16_arg_t; - -static int sum16_reader(void *dest_,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) - { - const unsigned char *dest=dest_; - sum16_arg_t *arg=ops_reader_get_arg(rinfo); - int r=ops_stacked_read(dest_,length,errors,rinfo,cbinfo); - int n; - - if(r < 0) - return r; - - for(n=0 ; n < r ; ++n) - arg->sum=(arg->sum+dest[n])&0xffff; - - return r; - } - -static void sum16_destroyer(ops_reader_info_t *rinfo) - { free(ops_reader_get_arg(rinfo)); } - -/** - \ingroup Internal_Readers_Sum16 - \param pinfo Parse settings -*/ - -void ops_reader_push_sum16(ops_parse_info_t *pinfo) - { - sum16_arg_t *arg=ops_mallocz(sizeof *arg); - - ops_reader_push(pinfo,sum16_reader,sum16_destroyer,arg); - } - -/** - \ingroup Internal_Readers_Sum16 - \param pinfo Parse settings - \return sum -*/ -unsigned short ops_reader_pop_sum16(ops_parse_info_t *pinfo) - { - sum16_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo)); - unsigned short sum=arg->sum; - - ops_reader_pop(pinfo); - free(arg); - - return sum; - } diff --git a/openpgpsdk/src/openpgpsdk/util.h b/openpgpsdk/src/openpgpsdk/util.h deleted file mode 100644 index 88d7b10a8..000000000 --- a/openpgpsdk/src/openpgpsdk/util.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_UTIL_H -#define OPS_UTIL_H - -#include "openpgpsdk/types.h" -#include "openpgpsdk/create.h" -#include "openpgpsdk/packet-parse.h" -#include - -#define ops_false 0 -#define ops_true 1 - -void hexdump(const unsigned char *src,size_t length); - -/* - * These macros code ensures that you are casting what you intend to cast. - * It works because in "a ? b : c", b and c must have the same type. - * This is a copy of the macro defined in openssl/asn1.h. - */ -#ifndef CHECKED_PTR_OF -#define CHECKED_PTR_OF(type, p) ((void*) (1 ? p : (type *)0)) -#endif -#define CHECKED_INSTANCE_OF(type, p) (1 ? p : (type)0) -#define DECONST(type,p) ((type *)CHECKED_PTR_OF(const type, p)) - -/* number of elements in an array */ -#define OPS_ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) - -void *ops_mallocz(size_t n); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/validate.c b/openpgpsdk/src/openpgpsdk/validate.c deleted file mode 100644 index d42d6becd..000000000 --- a/openpgpsdk/src/openpgpsdk/validate.c +++ /dev/null @@ -1,844 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include "keyring_local.h" -#include "parse_local.h" -#include -#include -#include -#include -#include -#include -#include - -#include - -static int debug=0; - -static ops_boolean_t check_binary_signature(const unsigned len, - const unsigned char *data, - const ops_signature_t *sig, - const ops_public_key_t *signer __attribute__((unused))) -{ - // Does the signed hash match the given hash? - - int n=0; - ops_hash_t hash; - unsigned char hashout[OPS_MAX_HASH_SIZE]; - unsigned char trailer[6]; - unsigned int hashedlen; - - //common_init_signature(&hash,sig); - ops_hash_any(&hash,sig->info.hash_algorithm); - hash.init(&hash); - hash.add(&hash,data,len); - switch (sig->info.version) - { - case OPS_V3: - trailer[0]=sig->info.type; - trailer[1]=sig->info.creation_time >> 24; - trailer[2]=sig->info.creation_time >> 16; - trailer[3]=sig->info.creation_time >> 8; - trailer[4]=sig->info.creation_time; - hash.add(&hash,&trailer[0],5); - break; - - case OPS_V4: - hash.add(&hash,sig->info.v4_hashed_data,sig->info.v4_hashed_data_length); - - trailer[0]=0x04; // version - trailer[1]=0xFF; - hashedlen=sig->info.v4_hashed_data_length; - trailer[2]=hashedlen >> 24; - trailer[3]=hashedlen >> 16; - trailer[4]=hashedlen >> 8; - trailer[5]=hashedlen; - hash.add(&hash,&trailer[0],6); - - break; - - default: - fprintf(stderr,"Invalid signature version %d\n", sig->info.version); - return ops_false; - } - - n=hash.finish(&hash,hashout); - - // return ops_false; - return ops_check_signature(hashout,n,sig,signer); -} - -static int keydata_reader(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - validate_reader_arg_t *arg=ops_reader_get_arg(rinfo); - - OPS_USED(errors); - OPS_USED(cbinfo); - if(arg->offset == arg->key->packets[arg->packet].length) - { - ++arg->packet; - arg->offset=0; - } - - if(arg->packet == arg->key->npackets) - return 0; - - // we should never be asked to cross a packet boundary in a single read - // - if(arg->key->packets[arg->packet].length >= arg->offset+length) - { - memcpy(dest,&arg->key->packets[arg->packet].raw[arg->offset],length); - arg->offset+=length; - - return length; - } - else - { - // If that happens, we set the offet to the total length and return 0. - // - fprintf(stderr,"WARNING: keydata_reader: packet length %lu goes beyond actual data size %lu. Consistency error!",arg->offset+length,arg->key->packets[arg->packet].length) ; - - arg->offset = arg->key->packets[arg->packet].length ; - return 0 ; - } -} - -static void free_signature_info(ops_signature_info_t *sig,int n) -{ - int i ; - for(i=0;iv4_hashed_data=ops_mallocz(src->v4_hashed_data_length); - memcpy(dst->v4_hashed_data,src->v4_hashed_data,src->v4_hashed_data_length); -} - -static void add_sig_to_valid_list(ops_validate_result_t * result, const ops_signature_info_t* sig) -{ - size_t newsize; - - // increment count - ++result->valid_count; - - // increase size of array - newsize=(sizeof *sig) * result->valid_count; - if (!result->valid_sigs) - result->valid_sigs=malloc(newsize); - else - result->valid_sigs=realloc(result->valid_sigs, newsize); - - // copy key ptr to array - copy_signature_info(&result->valid_sigs[result->valid_count-1],sig); -} - -static void add_sig_to_invalid_list(ops_validate_result_t * result, const ops_signature_info_t *sig) -{ - size_t newsize; - - // increment count - ++result->invalid_count; - - // increase size of array - newsize=(sizeof *sig) * result->invalid_count; - if (!result->invalid_sigs) - result->invalid_sigs=malloc(newsize); - else - result->invalid_sigs=realloc(result->invalid_sigs, newsize); - - // copy key ptr to array - copy_signature_info(&result->invalid_sigs[result->invalid_count-1],sig); -} - -static void add_sig_to_unknown_list(ops_validate_result_t * result, const ops_signature_info_t *sig) -{ - size_t newsize; - - // increment count - ++result->unknown_signer_count; - - // increase size of array - newsize=(sizeof *sig) * result->unknown_signer_count; - if (!result->unknown_sigs) - result->unknown_sigs=malloc(newsize); - else - result->unknown_sigs=realloc(result->unknown_sigs, newsize); - - // copy key id to array - copy_signature_info(&result->unknown_sigs[result->unknown_signer_count-1],sig); -} - - ops_parse_cb_return_t -ops_validate_key_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) -{ - const ops_parser_content_union_t *content=&content_->content; - validate_key_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo); - ops_error_t **errors=ops_parse_cb_get_errors(cbinfo); - const ops_keydata_t *signer; - ops_boolean_t valid=ops_false; - - if (debug) - printf("%s\n",ops_show_packet_tag(content_->tag)); - - switch(content_->tag) - { - case OPS_PTAG_CT_PUBLIC_KEY: - if(arg->pkey.version != 0) - { - fprintf(stderr,"arg->pkey.version should be 0! It's %d. Giving up.",arg->pkey.version) ; - return OPS_RELEASE_MEMORY ; - } - arg->pkey=content->public_key; - return OPS_KEEP_MEMORY; - - case OPS_PTAG_CT_PUBLIC_SUBKEY: - if(arg->subkey.version) - ops_public_key_free(&arg->subkey); - arg->subkey=content->public_key; - return OPS_KEEP_MEMORY; - - case OPS_PTAG_CT_SECRET_KEY: - arg->skey=content->secret_key; - arg->pkey=arg->skey.public_key; - return OPS_KEEP_MEMORY; - - case OPS_PTAG_CT_USER_ID: - if(arg->user_id.user_id) - ops_user_id_free(&arg->user_id); - arg->user_id=content->user_id; - arg->last_seen=ID; - return OPS_KEEP_MEMORY; - - case OPS_PTAG_CT_USER_ATTRIBUTE: - if(!content->user_attribute.data.len) - { - fprintf(stderr,"User attribute length is 0. Not possible! Giving up.") ; - return OPS_RELEASE_MEMORY ; - } - printf("user attribute, length=%d\n",(int)content->user_attribute.data.len); - if(arg->user_attribute.data.len) - ops_user_attribute_free(&arg->user_attribute); - arg->user_attribute=content->user_attribute; - arg->last_seen=ATTRIBUTE; - return OPS_KEEP_MEMORY; - - case OPS_PTAG_CT_SIGNATURE: // V3 sigs - case OPS_PTAG_CT_SIGNATURE_FOOTER: // V4 sigs - - if(debug) - { - printf(" type=%02x signer_id=",content->signature.info.type); - hexdump(content->signature.info.signer_id, - sizeof content->signature.info.signer_id); - printf("\n"); - } - - signer=ops_keyring_find_key_by_id(arg->keyring, - content->signature.info.signer_id); - if(!signer) - { - add_sig_to_unknown_list(arg->result, &content->signature.info); - break; - } - - switch(content->signature.info.type) - { - case OPS_CERT_GENERIC: - case OPS_CERT_PERSONA: - case OPS_CERT_CASUAL: - case OPS_CERT_POSITIVE: - case OPS_SIG_REV_CERT: - if(arg->last_seen == ID) - valid=ops_check_user_id_certification_signature(&arg->pkey, - &arg->user_id, - &content->signature, - ops_get_public_key_from_data(signer), - arg->rarg->key->packets[arg->rarg->packet].raw); - else - valid=ops_check_user_attribute_certification_signature(&arg->pkey, - &arg->user_attribute, - &content->signature, - ops_get_public_key_from_data(signer), - arg->rarg->key->packets[arg->rarg->packet].raw); - - break; - - case OPS_SIG_SUBKEY: - // XXX: we should also check that the signer is the key we are validating, I think. - valid=ops_check_subkey_signature(&arg->pkey,&arg->subkey, - &content->signature, - ops_get_public_key_from_data(signer), - arg->rarg->key->packets[arg->rarg->packet].raw); - break; - - case OPS_SIG_DIRECT: - valid=ops_check_direct_signature(&arg->pkey,&content->signature, - ops_get_public_key_from_data(signer), - arg->rarg->key->packets[arg->rarg->packet].raw); - break; - - case OPS_SIG_STANDALONE: - case OPS_SIG_PRIMARY: - case OPS_SIG_REV_KEY: - case OPS_SIG_REV_SUBKEY: - case OPS_SIG_TIMESTAMP: - case OPS_SIG_3RD_PARTY: - OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED, - "Verification of signature type 0x%02x not yet implemented\n", content->signature.info.type); - break; - - default: - OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED, - "Unexpected signature type 0x%02x\n", content->signature.info.type); - } - - if(valid) - { - // printf(" validated\n"); - //++arg->result->valid_count; - add_sig_to_valid_list(arg->result, &content->signature.info); - } - else - { - OPS_ERROR(errors,OPS_E_V_BAD_SIGNATURE,"Bad Signature"); - // printf(" BAD SIGNATURE\n"); - // ++arg->result->invalid_count; - add_sig_to_invalid_list(arg->result, &content->signature.info); - } - break; - - // ignore these - case OPS_PARSER_PTAG: - case OPS_PTAG_CT_SIGNATURE_HEADER: - case OPS_PARSER_PACKET_END: - case OPS_PTAG_CT_TRUST: - break; - - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - if (arg->cb_get_passphrase) - { - return arg->cb_get_passphrase(content_,cbinfo); - } - break; - - default: - fprintf(stderr,"unexpected tag=0x%x\n",content_->tag); - //assert(0); - OPS_ERROR_1(errors, OPS_E_V_NO_SIGNATURE, "Unknown PTAG 0x%02x in validation packet\n",content_->tag); - break; - } - return OPS_RELEASE_MEMORY; -} - - ops_parse_cb_return_t -validate_data_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) -{ - const ops_parser_content_union_t *content=&content_->content; - validate_data_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo); - ops_error_t **errors=ops_parse_cb_get_errors(cbinfo); - const ops_keydata_t *signer; - ops_boolean_t valid=ops_false; - ops_memory_t* mem=NULL; - - if (debug) - printf("%s\n",ops_show_packet_tag(content_->tag)); - - switch(content_->tag) - { - case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER: - // ignore - this gives us the "Armor Header" line "Hash: SHA1" or similar - break; - - case OPS_PTAG_CT_LITERAL_DATA_HEADER: - // ignore - break; - - case OPS_PTAG_CT_LITERAL_DATA_BODY: - arg->literal_data_body=content->literal_data_body; - arg->use=LITERAL_DATA; - return OPS_KEEP_MEMORY; - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY: - arg->signed_cleartext_body=content->signed_cleartext_body; - arg->use=SIGNED_CLEARTEXT; - return OPS_KEEP_MEMORY; - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: - // this gives us an ops_hash_t struct - break; - - case OPS_PTAG_CT_SIGNATURE: // V3 sigs - case OPS_PTAG_CT_SIGNATURE_FOOTER: // V4 sigs - - if (debug) - { - printf("\n*** hashed data:\n"); - unsigned int zzz=0; - for (zzz=0; zzzsignature.info.v4_hashed_data_length; zzz++) - printf("0x%02x ", content->signature.info.v4_hashed_data[zzz]); - printf("\n"); - printf(" type=%02x signer_id=",content->signature.info.type); - hexdump(content->signature.info.signer_id, - sizeof content->signature.info.signer_id); - } - - signer=ops_keyring_find_key_by_id(arg->keyring, - content->signature.info.signer_id); - if(!signer) - { - OPS_ERROR(errors,OPS_E_V_UNKNOWN_SIGNER,"Unknown Signer"); - add_sig_to_unknown_list(arg->result, &content->signature.info); - break; - } - - mem=ops_memory_new(); - ops_memory_init(mem,128); - - switch(content->signature.info.type) - { - case OPS_SIG_BINARY: - case OPS_SIG_TEXT: - switch(arg->use) - { - case LITERAL_DATA: - ops_memory_add(mem, - arg->literal_data_body.data, - arg->literal_data_body.length); - break; - - case SIGNED_CLEARTEXT: - ops_memory_add(mem, - arg->signed_cleartext_body.data, - arg->signed_cleartext_body.length); - break; - - default: - OPS_ERROR_1(errors,OPS_E_UNIMPLEMENTED,"Unimplemented Sig Use %d", arg->use); - printf(" Unimplemented Sig Use %d\n", arg->use); - break; - } - - valid=check_binary_signature(ops_memory_get_length(mem), - ops_memory_get_data(mem), - &content->signature, - ops_get_public_key_from_data(signer)); - break; - - default: - OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED, - "Verification of signature type 0x%02x not yet implemented\n", content->signature.info.type); - break; - - } - ops_memory_free(mem); - - if(valid) - { - add_sig_to_valid_list(arg->result, &content->signature.info); - } - else - { - OPS_ERROR(errors,OPS_E_V_BAD_SIGNATURE,"Bad Signature"); - add_sig_to_invalid_list(arg->result, &content->signature.info); - } - break; - - // ignore these - case OPS_PARSER_PTAG: - case OPS_PTAG_CT_SIGNATURE_HEADER: - case OPS_PTAG_CT_ARMOUR_HEADER: - case OPS_PTAG_CT_ARMOUR_TRAILER: - case OPS_PTAG_CT_ONE_PASS_SIGNATURE: - case OPS_PARSER_PACKET_END: - break; - - default: - fprintf(stderr,"unexpected tag=0x%x\n",content_->tag); - //assert(0); - OPS_ERROR_1(errors, OPS_E_V_NO_SIGNATURE, "Unknown PTAG 0x%02x in validation packet\n",content_->tag); - break; - } - return OPS_RELEASE_MEMORY; -} - -static void keydata_destroyer(ops_reader_info_t *rinfo) -{ free(ops_reader_get_arg(rinfo)); } - -void ops_keydata_reader_set(ops_parse_info_t *pinfo,const ops_keydata_t *key) -{ - validate_reader_arg_t *arg=malloc(sizeof *arg); - - memset(arg,'\0',sizeof *arg); - - arg->key=key; - arg->packet=0; - arg->offset=0; - - ops_reader_set(pinfo,keydata_reader,keydata_destroyer,arg); -} - -/** - * \ingroup HighLevel_Verify - * \brief Indicicates whether any errors were found - * \param result Validation result to check - * \return ops_false if any invalid signatures or unknown signers or no valid signatures; else ops_true - */ -ops_boolean_t validate_result_status(ops_validate_result_t* result) -{ - if (result->invalid_count || result->unknown_signer_count || !result->valid_count) - return ops_false; - else - return ops_true; -} - -/** - * \ingroup HighLevel_Verify - * \brief Validate all signatures on a single key against the given keyring - * \param result Where to put the result - * \param key Key to validate - * \param keyring Keyring to use for validation - * \param cb_get_passphrase Callback to use to get passphrase - * \return ops_true if all signatures OK; else ops_false - * \note It is the caller's responsiblity to free result after use. - * \sa ops_validate_result_free() - - Example Code: - \code - void example(const ops_keydata_t* key, const ops_keyring_t *keyring) - { - ops_validate_result_t *result=NULL; - if (ops_validate_key_signatures(result, key, keyring, callback_cmd_get_passphrase_from_cmdline)==ops_true) - printf("OK"); - else - printf("ERR"); - printf("valid=%d, invalid=%d, unknown=%d\n", - result->valid_count, - result->invalid_count, - result->unknown_signer_count); - ops_validate_result_free(result); - } - - \endcode - */ -ops_boolean_t ops_validate_key_signatures(ops_validate_result_t *result,const ops_keydata_t *key, - const ops_keyring_t *keyring, - ops_parse_cb_return_t cb_get_passphrase (const ops_parser_content_t *, ops_parse_cb_info_t *) - ) -{ - ops_parse_info_t *pinfo; - validate_key_cb_arg_t carg; - - memset(&carg,'\0',sizeof carg); - carg.result=result; - carg.cb_get_passphrase=cb_get_passphrase; - - pinfo=ops_parse_info_new(); - // ops_parse_options(&opt,OPS_PTAG_CT_SIGNATURE,OPS_PARSE_PARSED); - - carg.keyring=keyring; - - ops_parse_cb_set(pinfo,ops_validate_key_cb,&carg); - pinfo->rinfo.accumulate=ops_true; - ops_keydata_reader_set(pinfo,key); - - // Note: Coverity incorrectly reports an error that carg.rarg - // is never used. - carg.rarg=ops_reader_get_arg_from_pinfo(pinfo); - - ops_parse(pinfo,ops_true); - - ops_public_key_free(&carg.pkey); - if(carg.subkey.version) - ops_public_key_free(&carg.subkey); - ops_user_id_free(&carg.user_id); - ops_user_attribute_free(&carg.user_attribute); - - ops_parse_info_delete(pinfo); - -/* if(carg.literal_data_body.data != NULL) - free(carg.literal_data_body.data) ; */ - - if (result->invalid_count || result->unknown_signer_count || !result->valid_count) - return ops_false; - else - return ops_true; -} - -/** - \ingroup HighLevel_Verify - \param result Where to put the result - \param ring Keyring to use - \param cb_get_passphrase Callback to use to get passphrase - \note It is the caller's responsibility to free result after use. - \sa ops_validate_result_free() - */ -ops_boolean_t ops_validate_all_signatures(ops_validate_result_t *result, - const ops_keyring_t *ring, - ops_parse_cb_return_t cb_get_passphrase (const ops_parser_content_t *, ops_parse_cb_info_t *) - ) -{ - int n; - - memset(result,'\0',sizeof *result); - for(n=0 ; n < ring->nkeys ; ++n) - ops_validate_key_signatures(result,&ring->keys[n],ring, cb_get_passphrase); - return validate_result_status(result); -} - -/** - \ingroup HighLevel_Verify - \brief Frees validation result and associated memory - \param result Struct to be freed - \note Must be called after validation functions - */ -void ops_validate_result_free(ops_validate_result_t *result) -{ - if (!result) - return; - - if (result->valid_sigs) - free_signature_info(result->valid_sigs,result->valid_count); - if (result->invalid_sigs) - free_signature_info(result->invalid_sigs,result->invalid_count); - if (result->unknown_sigs) - free_signature_info(result->unknown_sigs,result->unknown_signer_count); - - free(result); - result=NULL; -} - -/** - \ingroup HighLevel_Verify - \brief Verifies the signatures in a signed file - \param result Where to put the result - \param filename Name of file to be validated - \param armoured Treat file as armoured, if set - \param keyring Keyring to use - \return ops_true if signatures validate successfully; ops_false if signatures fail or there are no signatures - \note After verification, result holds the details of all keys which - have passed, failed and not been recognised. - \note It is the caller's responsiblity to call ops_validate_result_free(result) after use. - - Example code: - \code - void example(const char* filename, const int armoured, const ops_keyring_t* keyring) - { - ops_validate_result_t* result=ops_mallocz(sizeof *result); - - if (ops_validate_file(result, filename, armoured, keyring)==ops_true) - { - printf("OK"); -// look at result for details of keys with good signatures -} -else -{ -printf("ERR"); -// look at result for details of failed signatures or unknown signers -} - -ops_validate_result_free(result); -} -\endcode - */ -ops_boolean_t ops_validate_file(ops_validate_result_t *result, const char* filename, const int armoured, const ops_keyring_t* keyring) -{ - ops_parse_info_t *pinfo=NULL; - validate_data_cb_arg_t validate_arg; - - int fd=0; - - // - fd=ops_setup_file_read(&pinfo, filename, &validate_arg, validate_data_cb, ops_true); - if (fd < 0) - return ops_false; - - // Set verification reader and handling options - - memset(&validate_arg,'\0',sizeof validate_arg); - validate_arg.result=result; - validate_arg.keyring=keyring; - // Note: Coverity incorrectly reports an error that carg.rarg - // is never used. - validate_arg.rarg=ops_reader_get_arg_from_pinfo(pinfo); - - if (armoured) - ops_reader_push_dearmour(pinfo); - - // Do the verification - - ops_parse(pinfo,ops_true); - - if (debug) - { - printf("valid=%d, invalid=%d, unknown=%d\n", - result->valid_count, - result->invalid_count, - result->unknown_signer_count); - } - - // Tidy up - if (armoured) - ops_reader_pop_dearmour(pinfo); - ops_teardown_file_read(pinfo, fd); - - if(validate_arg.literal_data_body.data != NULL) free(validate_arg.literal_data_body.data) ; - - return validate_result_status(result); -} - -/** - \ingroup HighLevel_Verify - \brief Verifies the signatures in a ops_memory_t struct - \param result Where to put the result - \param mem Memory to be validated - \param armoured Treat data as armoured, if set - \param keyring Keyring to use - \return ops_true if signature validates successfully; ops_false if not - \note After verification, result holds the details of all keys which - have passed, failed and not been recognised. - \note It is the caller's responsiblity to call ops_validate_result_free(result) after use. - */ - -ops_boolean_t ops_validate_mem(ops_validate_result_t *result, ops_memory_t* mem, const int armoured, const ops_keyring_t* keyring) -{ - ops_parse_info_t *pinfo=NULL; - validate_data_cb_arg_t validate_arg; - - // - ops_setup_memory_read(&pinfo, mem, &validate_arg, validate_data_cb, ops_true); - - // Set verification reader and handling options - - memset(&validate_arg,'\0',sizeof validate_arg); - validate_arg.result=result; - validate_arg.keyring=keyring; - // Note: Coverity incorrectly reports an error that carg.rarg - // is never used. - validate_arg.rarg=ops_reader_get_arg_from_pinfo(pinfo); - - if (armoured) - ops_reader_push_dearmour(pinfo); - - // Do the verification - - ops_parse(pinfo,ops_true); - - if (debug) - { - printf("valid=%d, invalid=%d, unknown=%d\n", - result->valid_count, - result->invalid_count, - result->unknown_signer_count); - } - - // Tidy up - if (armoured) - ops_reader_pop_dearmour(pinfo); - ops_teardown_memory_read(pinfo, mem); - - if(validate_arg.literal_data_body.data != NULL) free(validate_arg.literal_data_body.data) ; - if(validate_arg.signed_cleartext_body.data != NULL) free(validate_arg.signed_cleartext_body.data) ; - - return validate_result_status(result); -} - -/** - \ingroup HighLevel_Verify - \brief Verifies the signature in a detached signature data packet, given the literal data - \param literal_data Literal data that is signed - \param literal_data_length length of the literal data that is signed - \param signature_packet signature packet in binary PGP format - \param signature_packet_length length of the signature packet - \param signers_key Public key of the signer to check the signature for. - \return ops_true if signature validates successfully; ops_false if not - */ - -ops_boolean_t ops_validate_detached_signature(const void *literal_data, unsigned int literal_data_length, const unsigned char *signature_packet, unsigned int signature_packet_length,const ops_keydata_t *signers_key) -{ - ops_validate_result_t *result = (ops_validate_result_t*)ops_mallocz(sizeof(ops_validate_result_t)); - - ops_memory_t *mem = ops_memory_new() ; - ops_memory_add(mem,signature_packet,signature_packet_length) ; - - ops_parse_info_t *pinfo=NULL; - validate_data_cb_arg_t validate_arg; - - ops_setup_memory_read(&pinfo, mem, &validate_arg, validate_data_cb, ops_true); - - // Set verification reader and handling options - - ops_keyring_t tmp_keyring ; - tmp_keyring.nkeys = 1 ; - tmp_keyring.nkeys_allocated = 1 ; - tmp_keyring.keys = (ops_keydata_t *)signers_key ; // this is a const_cast, somehow - - memset(&validate_arg,'\0',sizeof validate_arg); - - validate_arg.result=result; - validate_arg.keyring=&tmp_keyring; - - int length = literal_data_length ; - - validate_arg.literal_data_body.data = (unsigned char *)malloc(length) ; - memcpy(validate_arg.literal_data_body.data, literal_data, length) ; - validate_arg.literal_data_body.length = length ; - - // Note: Coverity incorrectly reports an error that carg.rarg - // is never used. - validate_arg.rarg=ops_reader_get_arg_from_pinfo(pinfo); - - //if (armoured) - // ops_reader_push_dearmour(pinfo); - - // Do the verification - - ops_parse(pinfo,ops_true); - - if(debug) - printf("valid=%d, invalid=%d, unknown=%d\n", result->valid_count, result->invalid_count, result->unknown_signer_count); - - // Tidy up - //if (armoured) - // ops_reader_pop_dearmour(pinfo); - - ops_teardown_memory_read(pinfo, mem); - - ops_boolean_t res = validate_result_status(result); - ops_validate_result_free(result) ; - - if(validate_arg.literal_data_body.data != NULL) free(validate_arg.literal_data_body.data) ; - if(validate_arg.signed_cleartext_body.data != NULL) free(validate_arg.signed_cleartext_body.data) ; - - return res ; -} - -// eof diff --git a/openpgpsdk/src/openpgpsdk/validate.h b/openpgpsdk/src/openpgpsdk/validate.h deleted file mode 100644 index a078b7916..000000000 --- a/openpgpsdk/src/openpgpsdk/validate.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -typedef struct - { - unsigned int valid_count; - ops_signature_info_t * valid_sigs; - unsigned int invalid_count; - ops_signature_info_t * invalid_sigs; - unsigned int unknown_signer_count; - ops_signature_info_t * unknown_sigs; - } ops_validate_result_t; - -void ops_validate_result_free(ops_validate_result_t *result); - -ops_boolean_t ops_validate_key_signatures(ops_validate_result_t *result, - const ops_keydata_t* keydata, - const ops_keyring_t *ring, - ops_parse_cb_return_t cb (const ops_parser_content_t *, ops_parse_cb_info_t *)); -ops_boolean_t ops_validate_all_signatures(ops_validate_result_t *result, - const ops_keyring_t *ring, - ops_parse_cb_return_t (const ops_parser_content_t *, ops_parse_cb_info_t *)); - -void ops_keydata_reader_set(ops_parse_info_t *pinfo, - const ops_keydata_t *key); - -typedef struct - { - const ops_keydata_t *key; - unsigned packet; - unsigned offset; - } validate_reader_arg_t; - -/** Struct used with the validate_key_cb callback */ -typedef struct - { - ops_public_key_t pkey; - ops_public_key_t subkey; - ops_secret_key_t skey; - enum - { - ATTRIBUTE=1, - ID, - } last_seen; - ops_user_id_t user_id; - ops_user_attribute_t user_attribute; - unsigned char hash[OPS_MAX_HASH_SIZE]; - const ops_keyring_t *keyring; - validate_reader_arg_t *rarg; - ops_validate_result_t *result; - ops_parse_cb_return_t (*cb_get_passphrase) (const ops_parser_content_t *, ops_parse_cb_info_t *); - } validate_key_cb_arg_t; - -/** Struct use with the validate_data_cb callback */ -typedef struct validate_data_cb_arg - { - enum - { - LITERAL_DATA, - SIGNED_CLEARTEXT - } use; /* - -#include -#include -#include -#include -#include -#include -#include "keyring_local.h" -#include -#include -#include -#include -#include -#include -#ifndef WIN32 -#include -#endif - -#include - -//static int debug=0; - -/* - * return true if OK, otherwise false - */ -static ops_boolean_t base_write(const void *src,unsigned length, - ops_create_info_t *info) - { - return info->winfo.writer(src,length,&info->errors,&info->winfo); - } - -/** - * \ingroup Core_WritePackets - * - * \param src - * \param length - * \param info - * \return 1 if OK, otherwise 0 - */ - -ops_boolean_t ops_write(const void *src,unsigned length, - ops_create_info_t *info) - { - return base_write(src,length,info); - } - -/** - * \ingroup Core_WritePackets - * \param n - * \param length - * \param info - * \return ops_true if OK, otherwise ops_false - */ - -ops_boolean_t ops_write_scalar(unsigned n,unsigned length, - ops_create_info_t *info) - { - while(length-- > 0) - { - unsigned char c[1]; - - c[0]=n >> (length*8); - if(!base_write(c,1,info)) - return ops_false; - } - return ops_true; - } - -/** - * \ingroup Core_WritePackets - * \param bn - * \param info - * \return 1 if OK, otherwise 0 - */ - -ops_boolean_t ops_write_mpi(const BIGNUM *bn,ops_create_info_t *info) - { - unsigned char buf[8192]; - int bits=BN_num_bits(bn); - - assert(bits <= 65535); - BN_bn2bin(bn,buf); - return ops_write_scalar(bits,2,info) - && ops_write(buf,(bits+7)/8,info); - } - -/** - * \ingroup Core_WritePackets - * \param tag - * \param info - * \return 1 if OK, otherwise 0 - */ - -ops_boolean_t ops_write_ptag(ops_content_tag_t tag,ops_create_info_t *info) - { - unsigned char c[1]; - - c[0]=tag|OPS_PTAG_ALWAYS_SET|OPS_PTAG_NEW_FORMAT; - - return base_write(c,1,info); - } - -/** - * \ingroup Core_WritePackets - * \param length - * \param info - * \return 1 if OK, otherwise 0 - */ - -ops_boolean_t ops_write_length(unsigned length,ops_create_info_t *info) - { - unsigned char c[2]; - - if(length < 192) - { - c[0]=length; - return base_write(c,1,info); - } - else if(length < 8384) - { - c[0]=((length-192) >> 8)+192; - c[1]=(length-192)%256; - return base_write(c,2,info); - } - return ops_write_scalar(0xff,1,info) && ops_write_scalar(length,4,info); - } - -/* Note that we finalise from the top down, so we don't use writers below - * that have already been finalised - */ -ops_boolean_t writer_info_finalise(ops_error_t **errors, - ops_writer_info_t *winfo) - { - ops_boolean_t ret=ops_true; - - if(winfo->finaliser) - { - ret=winfo->finaliser(errors,winfo); - winfo->finaliser=NULL; - } - if(winfo->next && !writer_info_finalise(errors,winfo->next)) - { - winfo->finaliser=NULL; - return ops_false; - } - return ret; - } - -void writer_info_delete(ops_writer_info_t *winfo) - { - // we should have finalised before deleting - assert(!winfo->finaliser); - if(winfo->next) - { - writer_info_delete(winfo->next); - free(winfo->next); - winfo->next=NULL; - } - if(winfo->destroyer) - { - winfo->destroyer(winfo); - winfo->destroyer=NULL; - } - winfo->writer=NULL; - } - -/** - * \ingroup Core_Writers - * - * Set a writer in info. There should not be another writer set. - * - * \param info The info structure - * \param writer - * \param finaliser - * \param destroyer - * \param arg The argument for the writer and destroyer - */ -void ops_writer_set(ops_create_info_t *info, - ops_writer_t *writer, - ops_writer_finaliser_t *finaliser, - ops_writer_destroyer_t *destroyer, - void *arg) - { - assert(!info->winfo.writer); - info->winfo.writer=writer; - info->winfo.finaliser=finaliser; - info->winfo.destroyer=destroyer; - info->winfo.arg=arg; - } - -/** - * \ingroup Core_Writers - * - * Push a writer in info. There must already be another writer set. - * - * \param info The info structure - * \param writer - * \param finaliser - * \param destroyer - * \param arg The argument for the writer and destroyer - */ -void ops_writer_push(ops_create_info_t *info, - ops_writer_t *writer, - ops_writer_finaliser_t *finaliser, - ops_writer_destroyer_t *destroyer, - void *arg) - { - ops_writer_info_t *copy=ops_mallocz(sizeof *copy); - - assert(info->winfo.writer); - *copy=info->winfo; - info->winfo.next=copy; - - info->winfo.writer=writer; - info->winfo.finaliser=finaliser; - info->winfo.destroyer=destroyer; - info->winfo.arg=arg; - } - -void ops_writer_pop(ops_create_info_t *info) - { - ops_writer_info_t *next; - - // Make sure the finaliser has been called. - assert(!info->winfo.finaliser); - // Make sure this is a stacked writer - assert(info->winfo.next); - if(info->winfo.destroyer) - info->winfo.destroyer(&info->winfo); - - next=info->winfo.next; - info->winfo=*next; - - free(next); - } - -/** - * \ingroup Core_Writers - * - * Close the writer currently set in info. - * - * \param info The info structure - */ -ops_boolean_t ops_writer_close(ops_create_info_t *info) - { - ops_boolean_t ret=writer_info_finalise(&info->errors,&info->winfo); - - writer_info_delete(&info->winfo); - - return ret; - } - -/** - * \ingroup Core_Writers - * - * Get the arg supplied to ops_create_info_set_writer(). - * - * \param winfo The writer_info structure - * \return The arg - */ -void *ops_writer_get_arg(ops_writer_info_t *winfo) - { return winfo->arg; } - -/** - * \ingroup Core_Writers - * - * Write to the next writer down in the stack. - * - * \param src The data to write. - * \param length The length of src. - * \param errors A place to store errors. - * \param winfo The writer_info structure. - * \return Success - if ops_false, then errors should contain the error. - */ -ops_boolean_t ops_stacked_write(const void *src,unsigned length, - ops_error_t **errors,ops_writer_info_t *winfo) - { - return winfo->next->writer(src,length,errors,winfo->next); - } - -/** - * \ingroup Core_Writers - * - * Free the arg. Many writers just have a malloc()ed lump of storage, this - * function releases it. - * - * \param winfo the info structure. - */ -void ops_writer_generic_destroyer(ops_writer_info_t *winfo) - { free(ops_writer_get_arg(winfo)); } - -/** - * \ingroup Core_Writers - * - * A writer that just writes to the next one down. Useful for when you - * want to insert just a finaliser into the stack. - */ -ops_boolean_t ops_writer_passthrough(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { return ops_stacked_write(src,length,errors,winfo); } - - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer.h b/openpgpsdk/src/openpgpsdk/writer.h deleted file mode 100644 index 2b15c8206..000000000 --- a/openpgpsdk/src/openpgpsdk/writer.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_WRITER_H -#define OPS_WRITER_H - -#include "types.h" -#include "packet.h" -#include "crypto.h" -#include "memory.h" -#include "errors.h" -#include "keyring.h" - -/** - * \ingroup Create - * This struct contains the required information about one writer - */ -/** - * \ingroup Writer - * the writer function prototype - */ - -typedef struct ops_writer_info ops_writer_info_t; -typedef ops_boolean_t ops_writer_t(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo); -typedef ops_boolean_t ops_writer_finaliser_t(ops_error_t **errors, - ops_writer_info_t *winfo); -typedef void ops_writer_destroyer_t(ops_writer_info_t *winfo); -/** Writer settings */ -struct ops_writer_info - { - ops_writer_t *writer; /*!< the writer itself */ - ops_writer_finaliser_t *finaliser; /*!< the writer's finaliser */ - ops_writer_destroyer_t *destroyer; /*!< the writer's destroyer */ - void *arg; /* writer-specific argument */ - ops_writer_info_t *next; /*!< next writer in the stack */ - }; - - -void *ops_writer_get_arg(ops_writer_info_t *winfo); -ops_boolean_t ops_stacked_write(const void *src,unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo); - -void ops_writer_set(ops_create_info_t *info, - ops_writer_t *writer, - ops_writer_finaliser_t *finaliser, - ops_writer_destroyer_t *destroyer, - void *arg); -void ops_writer_push(ops_create_info_t *info, - ops_writer_t *writer, - ops_writer_finaliser_t *finaliser, - ops_writer_destroyer_t *destroyer, - void *arg); -void ops_writer_pop(ops_create_info_t *info); -void ops_writer_generic_destroyer(ops_writer_info_t *winfo); -ops_boolean_t ops_writer_passthrough(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo); - -void ops_writer_set_fd(ops_create_info_t *info,int fd); -ops_boolean_t ops_writer_close(ops_create_info_t *info); - -ops_boolean_t ops_write(const void *src,unsigned length, - ops_create_info_t *opt); -ops_boolean_t ops_write_length(unsigned length,ops_create_info_t *opt); -ops_boolean_t ops_write_ptag(ops_content_tag_t tag,ops_create_info_t *opt); -ops_boolean_t ops_write_scalar(unsigned n,unsigned length, - ops_create_info_t *opt); -ops_boolean_t ops_write_mpi(const BIGNUM *bn,ops_create_info_t *opt); -ops_boolean_t ops_write_encrypted_mpi(const BIGNUM *bn, ops_crypt_t* crypt, ops_create_info_t *info); - -void writer_info_delete(ops_writer_info_t *winfo); -ops_boolean_t writer_info_finalise(ops_error_t **errors, ops_writer_info_t *winfo); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/writer_armour.c b/openpgpsdk/src/openpgpsdk/writer_armour.c deleted file mode 100644 index cd828e6a6..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_armour.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include - -#include -#include -#include -#include - -#include - -static int debug=0; - -#define LINE_LENGTH 64 - -static const char newline[] = "\r\n"; - -/** - * \struct dash_escaped_arg_t - */ -typedef struct - { - ops_boolean_t seen_nl:1; - ops_boolean_t seen_cr:1; - ops_create_signature_t *sig; - ops_memory_t *trailing; - } dash_escaped_arg_t; - -static ops_boolean_t dash_escaped_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - dash_escaped_arg_t *arg=ops_writer_get_arg(winfo); - unsigned n; - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"dash_escaped_writer writing %d:\n", length); - for (i=0; iseen_nl) - { - if(src[n] == '-' && !ops_stacked_write("- ",2,errors,winfo)) - return ops_false; - arg->seen_nl=ops_false; - } - - arg->seen_nl=src[n] == '\n'; - - if(arg->seen_nl && !arg->seen_cr) - { - if(!ops_stacked_write("\r",1,errors,winfo)) - return ops_false; - ops_signature_add_data(arg->sig,"\r",1); - } - - arg->seen_cr=src[n] == '\r'; - - if(!ops_stacked_write(&src[n],1,errors,winfo)) - return ops_false; - - /* trailing whitespace isn't included in the signature */ - if(src[n] == ' ' || src[n] == '\t') - ops_memory_add(arg->trailing,&src[n],1); - else - { - if((l=ops_memory_get_length(arg->trailing))) - { - if(!arg->seen_nl && !arg->seen_cr) - ops_signature_add_data(arg->sig, - ops_memory_get_data(arg->trailing), - l); - ops_memory_clear(arg->trailing); - } - ops_signature_add_data(arg->sig,&src[n],1); - } - } - - return ops_true; - } - -/** - * \param winfo - */ -static void dash_escaped_destroyer(ops_writer_info_t *winfo) - { - dash_escaped_arg_t *arg=ops_writer_get_arg(winfo); - - ops_memory_free(arg->trailing); - free(arg); - } - -/** - * \ingroup Core_WritersNext - * \brief Push Clearsigned Writer onto stack - * \param info - * \param sig - */ -ops_boolean_t ops_writer_push_clearsigned(ops_create_info_t *info, - ops_create_signature_t *sig) - { - static char header[]="-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: "; - const char *hash=ops_text_from_hash(ops_signature_get_hash(sig)); - dash_escaped_arg_t *arg=ops_mallocz(sizeof *arg); - - ops_boolean_t rtn; - - rtn= ( ops_write(header,sizeof header-1,info) - && ops_write(hash,strlen(hash),info) - && ops_write("\r\n\r\n",4,info)); - - if (rtn==ops_false) - { - OPS_ERROR(&info->errors, OPS_E_W, "Error pushing clearsigned header"); - free(arg); - return rtn; - } - - arg->seen_nl=ops_true; - arg->sig=sig; - arg->trailing=ops_memory_new(); - ops_writer_push(info,dash_escaped_writer,NULL,dash_escaped_destroyer,arg); - return rtn; - } - - -/** - * \struct base64_arg_t - */ -typedef struct - { - size_t chars_written; - ops_boolean_t writing_trailer; - unsigned pos; - unsigned char t; - unsigned checksum; - } base64_arg_t; - -static char b64map[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" -"0123456789+/"; - -static ops_boolean_t check_newline(base64_arg_t* arg, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - arg->chars_written++; - if (!arg->writing_trailer && arg->chars_written % LINE_LENGTH == 0) - if (!ops_stacked_write(newline, strlen(newline), errors, winfo)) - return ops_false; - return ops_true; - } - -static ops_boolean_t base64_writer(const unsigned char *src, - unsigned length,ops_error_t **errors, - ops_writer_info_t *winfo) - { - base64_arg_t *arg=ops_writer_get_arg(winfo); - unsigned n; - - for(n=0 ; n < length ; ) - { - arg->checksum=ops_crc24(arg->checksum,src[n]); - if(arg->pos == 0) - { - /* XXXXXX00 00000000 00000000 */ - if(!ops_stacked_write(&b64map[src[n] >> 2],1,errors,winfo)) - return ops_false; - - /* 000000XX xxxx0000 00000000 */ - arg->t=(src[n++]&3) << 4; - arg->pos=1; - } - else if(arg->pos == 1) - { - /* 000000xx XXXX0000 00000000 */ - arg->t+=src[n] >> 4; - if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo)) - return ops_false; - - /* 00000000 0000XXXX xx000000 */ - arg->t=(src[n++]&0xf) << 2; - arg->pos=2; - } - else if(arg->pos == 2) - { - /* 00000000 0000xxxx XX000000 */ - arg->t+=src[n] >> 6; - if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo)) - return ops_false; - if(!check_newline(arg, errors, winfo)) - return ops_false; - - /* 00000000 00000000 00XXXXXX */ - if(!ops_stacked_write(&b64map[src[n++]&0x3f],1,errors,winfo)) - return ops_false; - - arg->pos=0; - } - if (!check_newline(arg, errors, winfo)) - return ops_false; - } - return ops_true; - } - -static ops_boolean_t signature_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - base64_arg_t *arg=ops_writer_get_arg(winfo); - static char trailer[]="\r\n-----END PGP SIGNATURE-----\r\n"; - unsigned char c[3]; - - if(arg->pos) - { - if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo)) - return ops_false; - if(arg->pos == 1 && !ops_stacked_write("==",2,errors,winfo)) - return ops_false; - if(arg->pos == 2 && !ops_stacked_write("=",1,errors,winfo)) - return ops_false; - } - /* Ready for the checksum */ - if(!ops_stacked_write("\r\n=",3,errors,winfo)) - return ops_false; - - arg->pos=0; /* get ready to write the checksum */ - - c[0]=arg->checksum >> 16; - c[1]=arg->checksum >> 8; - c[2]=arg->checksum; - /* push the checksum through our own writer. Turn off the - writing_body flag so we don't put a newline in the trailer. - */ - arg->writing_trailer = ops_true; - if(!base64_writer(c,3,errors,winfo)) - return ops_false; - - return ops_stacked_write(trailer,sizeof trailer-1,errors,winfo); - } - -/** - * \struct linebreak_arg_t - */ -typedef struct - { - unsigned pos; - } linebreak_arg_t; - -#define BREAKPOS 65 - -static ops_boolean_t linebreak_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - linebreak_arg_t *arg=ops_writer_get_arg(winfo); - unsigned n; - - for(n=0 ; n < length ; ++n,++arg->pos) - { - if(src[n] == '\r' || src[n] == '\n') - arg->pos=0; - - if(arg->pos == BREAKPOS) - { - if(!ops_stacked_write(newline,strlen(newline),errors,winfo)) - return ops_false; - arg->pos=0; - } - if(!ops_stacked_write(&src[n],1,errors,winfo)) - return ops_false; - } - - return ops_true; - } - -/** - * \ingroup Core_WritersNext - * \brief Push armoured signature on stack - * \param info - */ -ops_boolean_t ops_writer_switch_to_armoured_signature(ops_create_info_t *info) - { - static char header[]="\r\n-----BEGIN PGP SIGNATURE-----\r\nVersion: " - OPS_VERSION_STRING "\r\n\r\n"; - base64_arg_t *base64; - - ops_writer_pop(info); - if (ops_write(header,sizeof header-1,info)==ops_false) - { - OPS_ERROR(&info->errors, OPS_E_W, "Error switching to armoured signature"); - return ops_false; - } - - ops_writer_push(info,linebreak_writer,NULL,ops_writer_generic_destroyer, - ops_mallocz(sizeof(linebreak_arg_t))); - - base64=ops_mallocz(sizeof *base64); - if (!base64) - { - OPS_MEMORY_ERROR(&info->errors); - return ops_false; - } - base64->checksum=CRC24_INIT; - ops_writer_push(info,base64_writer,signature_finaliser, - ops_writer_generic_destroyer,base64); - return ops_true; - } - -static ops_boolean_t armoured_message_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - // TODO: This is same as signature_finaliser apart from trailer. - base64_arg_t *arg=ops_writer_get_arg(winfo); - static char trailer[]="\r\n-----END PGP MESSAGE-----\r\n"; - unsigned char c[3]; - - if(arg->pos) - { - if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo)) - return ops_false; - if(arg->pos == 1 && !ops_stacked_write("==",2,errors,winfo)) - return ops_false; - if(arg->pos == 2 && !ops_stacked_write("=",1,errors,winfo)) - return ops_false; - } - /* Ready for the checksum */ - if(!ops_stacked_write("\r\n=",3,errors,winfo)) - return ops_false; - - arg->pos=0; /* get ready to write the checksum */ - - c[0]=arg->checksum >> 16; - c[1]=arg->checksum >> 8; - c[2]=arg->checksum; - /* push the checksum through our own writer. Turn off the - writing_body flag so we don't put a newline in the trailer. - */ - arg->writing_trailer = ops_true; - if(!base64_writer(c,3,errors,winfo)) - return ops_false; - - return ops_stacked_write(trailer,sizeof trailer-1,errors,winfo); - } - -/** - \ingroup Core_WritersNext - \brief Write a PGP MESSAGE - \todo replace with generic function -*/ -void ops_writer_push_armoured_message(ops_create_info_t *info) -// ops_create_signature_t *sig) - { - static char header[]="-----BEGIN PGP MESSAGE-----\r\n"; - - base64_arg_t *base64; - - ops_write(header,sizeof header-1,info); - ops_write(newline,strlen(newline),info); - base64=ops_mallocz(sizeof *base64); - base64->checksum=CRC24_INIT; - ops_writer_push(info,base64_writer,armoured_message_finaliser,ops_writer_generic_destroyer,base64); - } - -static ops_boolean_t armoured_finaliser(ops_armor_type_t type, ops_error_t **errors, - ops_writer_info_t *winfo) - { - static char tail_public_key[]="\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n"; - static char tail_private_key[]="\r\n-----END PGP PRIVATE KEY BLOCK-----\r\n"; - - char* tail=NULL; - unsigned int sz_tail=0; - - switch(type) - { - case OPS_PGP_PUBLIC_KEY_BLOCK: - tail=tail_public_key; - sz_tail=sizeof tail_public_key-1; - break; - - case OPS_PGP_PRIVATE_KEY_BLOCK: - tail=tail_private_key; - sz_tail=sizeof tail_private_key-1; - break; - - default: - assert(0); - } - - base64_arg_t *arg=ops_writer_get_arg(winfo); - unsigned char c[3]; - - if(arg->pos) - { - if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo)) - return ops_false; - if(arg->pos == 1 && !ops_stacked_write("==",2,errors,winfo)) - return ops_false; - if(arg->pos == 2 && !ops_stacked_write("=",1,errors,winfo)) - return ops_false; - } - - /* Ready for the checksum */ - if(!ops_stacked_write("\r\n=",3,errors,winfo)) - return ops_false; - - arg->pos=0; /* get ready to write the checksum */ - - c[0]=arg->checksum >> 16; - c[1]=arg->checksum >> 8; - c[2]=arg->checksum; - /* push the checksum through our own writer. Turn off the - writing_body flag so we don't put a newline in the trailer. - */ - arg->writing_trailer = ops_true; - if(!base64_writer(c,3,errors,winfo)) - return ops_false; - - return ops_stacked_write(tail,sz_tail,errors,winfo); - } - -static ops_boolean_t armoured_public_key_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - return armoured_finaliser(OPS_PGP_PUBLIC_KEY_BLOCK,errors,winfo); - } - -static ops_boolean_t armoured_private_key_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - return armoured_finaliser(OPS_PGP_PRIVATE_KEY_BLOCK,errors,winfo); - } - -// \todo use this for other armoured types -/** - \ingroup Core_WritersNext - \brief Push Armoured Writer on stack (generic) -*/ -void ops_writer_push_armoured(ops_create_info_t *info, ops_armor_type_t type) - { - static char hdr_public_key[]="-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: " - OPS_VERSION_STRING "\r\n\r\n"; - static char hdr_private_key[]="-----BEGIN PGP PRIVATE KEY BLOCK-----\r\nVersion: " - OPS_VERSION_STRING "\r\n\r\n"; - - char* header=NULL; - unsigned int sz_hdr=0; - ops_boolean_t (* finaliser)(ops_error_t **errors, ops_writer_info_t *winfo); - - switch(type) - { - case OPS_PGP_PUBLIC_KEY_BLOCK: - header=hdr_public_key; - sz_hdr=sizeof hdr_public_key-1; - finaliser=armoured_public_key_finaliser; - break; - - case OPS_PGP_PRIVATE_KEY_BLOCK: - header=hdr_private_key; - sz_hdr=sizeof hdr_private_key-1; - finaliser=armoured_private_key_finaliser; - break; - - default: - assert(0); - } - - ops_write(header,sz_hdr,info); - - ops_writer_push(info,linebreak_writer,NULL,ops_writer_generic_destroyer, - ops_mallocz(sizeof(linebreak_arg_t))); - - base64_arg_t *arg=ops_mallocz(sizeof *arg); - arg->checksum=CRC24_INIT; - ops_writer_push(info,base64_writer,finaliser,ops_writer_generic_destroyer,arg); - } - - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_armoured.h b/openpgpsdk/src/openpgpsdk/writer_armoured.h deleted file mode 100644 index bf81141b8..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_armoured.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -ops_boolean_t ops_writer_push_clearsigned(ops_create_info_t *info, - ops_create_signature_t *sig); -void ops_writer_push_armoured_message(ops_create_info_t *info); -ops_boolean_t ops_writer_switch_to_armoured_signature(ops_create_info_t *info); - -void ops_writer_push_armoured(ops_create_info_t *info, ops_armor_type_t type); - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_encrypt.c b/openpgpsdk/src/openpgpsdk/writer_encrypt.c deleted file mode 100644 index 4224fca42..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_encrypt.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include - -static int debug=0; - -typedef struct - { - ops_crypt_t* crypt; - int free_crypt; - } crypt_arg_t; - -/* - * This writer simply takes plaintext as input, - * encrypts it with the given key - * and outputs the resulting encrypted text - */ -static ops_boolean_t encrypt_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - -#define BUFSZ 1024 // arbitrary number - unsigned char encbuf[BUFSZ]; - unsigned remaining=length; - unsigned done=0; - - crypt_arg_t *arg=(crypt_arg_t *)ops_writer_get_arg(winfo); - - if (!ops_is_sa_supported(arg->crypt->algorithm)) - assert(0); // \todo proper error handling - - while (remaining) - { - unsigned len = remaining < BUFSZ ? remaining : BUFSZ; - // memcpy(buf,src,len); // \todo copy needed here? - - arg->crypt->cfb_encrypt(arg->crypt, encbuf, src+done, len); - - if (debug) - { - int i=0; - fprintf(stderr,"WRITING:\nunencrypted: "); - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", src[done+i]); - fprintf(stderr,"\n"); - fprintf(stderr,"encrypted: "); - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", encbuf[i]); - fprintf(stderr,"\n"); - } - - if (!ops_stacked_write(encbuf,len,errors,winfo)) - { - if (debug) - { fprintf(stderr, "encrypted_writer got error from stacked write, returning\n"); } - return ops_false; - } - remaining-=len; - done+=len; - } - - return ops_true; - } - -static void encrypt_destroyer (ops_writer_info_t *winfo) - - { - crypt_arg_t *arg=(crypt_arg_t *)ops_writer_get_arg(winfo); - if (arg->free_crypt) - free(arg->crypt); - free (arg); - } - -/** -\ingroup Core_WritersNext -\brief Push Encrypted Writer onto stack (create SE packets) -*/ -void ops_writer_push_encrypt_crypt(ops_create_info_t *cinfo, - ops_crypt_t *crypt) - { - // Create arg to be used with this writer - // Remember to free this in the destroyer - - crypt_arg_t *arg=ops_mallocz(sizeof *arg); - - // Setup the arg - - arg->crypt=crypt; - arg->free_crypt=0; - - // And push writer on stack - ops_writer_push(cinfo,encrypt_writer,NULL,encrypt_destroyer,arg); - - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_encrypt_se_ip.c b/openpgpsdk/src/openpgpsdk/writer_encrypt_se_ip.c deleted file mode 100644 index 0c1b2c78d..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_encrypt_se_ip.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include - -#ifndef WIN32 - #include -#endif - -#include - -#include "keyring_local.h" -#include -#include -#include -#include -#include -#include - -static int debug=0; - -typedef struct - { - ops_crypt_t* crypt; - } encrypt_se_ip_arg_t; - -static ops_boolean_t encrypt_se_ip_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo); -static void encrypt_se_ip_destroyer(ops_writer_info_t *winfo); - -// - -/** -\ingroup Core_WritersNext -\brief Push Encrypted SE IP Writer onto stack -*/ -void ops_writer_push_encrypt_se_ip(ops_create_info_t *cinfo, - const ops_keydata_t *pub_key) - { - ops_crypt_t *encrypt; - unsigned char *iv=NULL; - - // Create arg to be used with this writer - // Remember to free this in the destroyer - encrypt_se_ip_arg_t *arg=ops_mallocz(sizeof *arg); - - // Create and write encrypted PK session key - ops_pk_session_key_t *encrypted_pk_session_key; - encrypted_pk_session_key=ops_create_pk_session_key(pub_key); - ops_write_pk_session_key(cinfo, encrypted_pk_session_key); - - // Setup the arg - encrypt=ops_mallocz(sizeof *encrypt); - ops_crypt_any(encrypt, encrypted_pk_session_key->symmetric_algorithm); - iv=ops_mallocz(encrypt->blocksize); - encrypt->set_iv(encrypt, iv); - encrypt->set_key(encrypt, &encrypted_pk_session_key->key[0]); - ops_encrypt_init(encrypt); - - arg->crypt=encrypt; - - // And push writer on stack - ops_writer_push(cinfo, encrypt_se_ip_writer, NULL, encrypt_se_ip_destroyer, - arg); - // tidy up - ops_pk_session_key_free(encrypted_pk_session_key); - free(encrypted_pk_session_key); - free(iv); - } - -static ops_boolean_t encrypt_se_ip_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo); - - ops_boolean_t rtn=ops_true; - - ops_memory_t *mem_literal; - ops_create_info_t *cinfo_literal; - - ops_memory_t *mem_compressed; - ops_create_info_t *cinfo_compressed; - - ops_memory_t *my_mem; - ops_create_info_t *my_cinfo; - - const unsigned int bufsz=128; // initial value; gets expanded as necessary - ops_setup_memory_write(&cinfo_literal, &mem_literal, bufsz); - ops_setup_memory_write(&cinfo_compressed, &mem_compressed, bufsz); - ops_setup_memory_write(&my_cinfo, &my_mem, bufsz); - - // create literal data packet from source data - ops_write_literal_data_from_buf(src, length, OPS_LDT_BINARY, cinfo_literal); - assert(ops_memory_get_length(mem_literal) > length); - - // create compressed packet from literal data packet - ops_write_compressed(ops_memory_get_data(mem_literal), - ops_memory_get_length(mem_literal), - cinfo_compressed); - - // create SE IP packet set from this compressed literal data - ops_write_se_ip_pktset(ops_memory_get_data(mem_compressed), - ops_memory_get_length(mem_compressed), - arg->crypt, my_cinfo); - assert(ops_memory_get_length(my_mem) - > ops_memory_get_length(mem_compressed)); - - // now write memory to next writer - rtn=ops_stacked_write(ops_memory_get_data(my_mem), - ops_memory_get_length(my_mem), - errors, winfo); - - ops_memory_free(my_mem); - ops_memory_free(mem_compressed); - ops_memory_free(mem_literal); - - return rtn; - } - -static void encrypt_se_ip_destroyer (ops_writer_info_t *winfo) - - { - encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo); - - free(arg->crypt); - free(arg); - } - -ops_boolean_t ops_write_se_ip_pktset(const unsigned char *data, - const unsigned int len, - ops_crypt_t *crypt, - ops_create_info_t *cinfo) - { - unsigned char hashed[SHA_DIGEST_LENGTH]; - const size_t sz_mdc=1+1+SHA_DIGEST_LENGTH; - - size_t sz_preamble=crypt->blocksize+2; - unsigned char* preamble=ops_mallocz(sz_preamble); - - size_t sz_buf=sz_preamble+len+sz_mdc; - - ops_memory_t *mem_mdc; - ops_create_info_t *cinfo_mdc; - - if (!ops_write_ptag(OPS_PTAG_CT_SE_IP_DATA, cinfo) - || !ops_write_length(1+sz_buf, cinfo) - || !ops_write_scalar(SE_IP_DATA_VERSION, 1, cinfo)) - { - free (preamble); - return 0; - } - - ops_random(preamble, crypt->blocksize); - preamble[crypt->blocksize]=preamble[crypt->blocksize-2]; - preamble[crypt->blocksize+1]=preamble[crypt->blocksize-1]; - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"\npreamble: "); - for (i=0; i -#include -#include -#endif - -#include - -#include - -typedef struct - { - int fd; - } writer_fd_arg_t; - -static ops_boolean_t fd_writer(const unsigned char *src,unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - writer_fd_arg_t *arg=ops_writer_get_arg(winfo); - int n=write(arg->fd,src,length); - - if(n == -1) - { - OPS_SYSTEM_ERROR_1(errors,OPS_E_W_WRITE_FAILED,"write", - "file descriptor %d",arg->fd); - return ops_false; - } - - if((unsigned)n != length) - { - OPS_ERROR_1(errors,OPS_E_W_WRITE_TOO_SHORT, - "file descriptor %d",arg->fd); - return ops_false; - } - - return ops_true; - } - -static void fd_destroyer(ops_writer_info_t *winfo) - { - free(ops_writer_get_arg(winfo)); - } - -/** - * \ingroup Core_WritersFirst - * \brief Write to a File - * - * Set the writer in info to be a stock writer that writes to a file - * descriptor. If another writer has already been set, then that is - * first destroyed. - * - * \param info The info structure - * \param fd The file descriptor - * - */ - -void ops_writer_set_fd(ops_create_info_t *info,int fd) - { - writer_fd_arg_t *arg=malloc(sizeof *arg); - - arg->fd=fd; - ops_writer_set(info,fd_writer,NULL,fd_destroyer,arg); - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_literal.c b/openpgpsdk/src/openpgpsdk/writer_literal.c deleted file mode 100644 index 64b3f650c..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_literal.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2005-2009 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh. - * The Contributors have asserted their moral rights under the - * UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** Writes a literal data packet, using the partial data length encoding. - */ - -#include -#include - -#ifndef WIN32 -#include -#endif - -#include -#include -#include - -//#define MIN_PARTIAL_DATA_LENGTH 512 // now defined in partial.h -#define MAX_PARTIAL_DATA_LENGTH 1073741824 - - -ops_boolean_t write_literal_header(ops_create_info_t *info, - void *header_data) - { - OPS_USED(header_data); - // \todo add the literal type as a header_data argument - // \todo add filename - // \todo add date - // \todo do we need to check text data for line endings ? - - ops_write_scalar(OPS_LDT_BINARY, 1, info); // data type - ops_write_scalar(0, 1, info); // Filename (length = 0) - ops_write_scalar(0, 4, info); // Date (unspecified) - return ops_true; - } - -/** - * \ingroup InternalAPI - * \brief Pushes a literal writer onto the stack. - * \param cinfo the writer info - * \param buf_size the size of the internal buffer. For best - * throughput, write data in multiples of buf_size - */ -void ops_writer_push_literal_with_opts(ops_create_info_t *cinfo, - unsigned int buf_size) - { - // The literal writer doesn't need to transform the data, so we just - // push a partial packet writer onto the stack. This will handle - // the packet length encoding. All we need to provide is a function - // to write the header. - ops_writer_push_partial(buf_size, cinfo, OPS_PTAG_CT_LITERAL_DATA, - write_literal_header, NULL); - -} - -/** - * \ingroup InternalAPI - * \brief Pushes a literal writer onto the stack. - * \param cinfo the writer info - */ -void ops_writer_push_literal(ops_create_info_t *cinfo) - { - ops_writer_push_literal_with_opts(cinfo, 0); - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_memory.c b/openpgpsdk/src/openpgpsdk/writer_memory.c deleted file mode 100644 index 0c8fa57c4..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_memory.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include - -#include - -static ops_boolean_t memory_writer(const unsigned char *src,unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - ops_memory_t *mem=ops_writer_get_arg(winfo); - - OPS_USED(errors); - ops_memory_add(mem,src,length); - return ops_true; - } - -/** - * \ingroup Core_WritersFirst - * \brief Write to memory - * - * Set a memory writer. - * - * \param info The info structure - * \param mem The memory structure - * \note It is the caller's responsiblity to call ops_memory_free(mem) - * \sa ops_memory_free() - */ - -void ops_writer_set_memory(ops_create_info_t *info,ops_memory_t *mem) - { - ops_writer_set(info,memory_writer,NULL,NULL,mem); - } - - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_partial.c b/openpgpsdk/src/openpgpsdk/writer_partial.c deleted file mode 100644 index 9c59c27f9..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_partial.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (c) 2005-2009 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh. - * The Contributors have asserted their moral rights under the - * UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** Writes data using a series of partial body length headers. - * (See RFC 4880 4.2.2.4). This is normally used in conjunction - * with a streaming writer of some kind that needs to write out - * data packets of unknown length. - */ - -#include -#include - -#ifndef WIN32 -#include -#endif - -#include -#include -#include -#include - -static const int debug = 0; - -#define MAX_PARTIAL_DATA_LENGTH 1073741824 - -typedef struct - { - size_t packet_size; // size of packets - ops_memory_t *buffer; // Data is buffered here until written - ops_content_tag_t tag; // Packet tag - ops_memory_t *header; // Header is written here - ops_boolean_t written_first; // Has the first packet been written? - ops_write_partial_trailer_t *trailer_fn; // Custom end-of-packet fn - void *trailer_data; // data for end-of-packet fn - } stream_partial_arg_t; - - - -static unsigned int ops_calc_partial_data_length(unsigned int len) - { - int i; - unsigned int mask = MAX_PARTIAL_DATA_LENGTH; - assert( len > 0 ); - - if (len > MAX_PARTIAL_DATA_LENGTH) - return MAX_PARTIAL_DATA_LENGTH; - - for (i = 0 ; i <= 30 ; i++) - { - if (mask & len) - break; - mask >>= 1; - } - - return mask; - } - -static ops_boolean_t ops_write_partial_data_length(unsigned int len, - ops_create_info_t *info) - { - // len must be a power of 2 from 0 to 30 - unsigned i; - unsigned char c[1]; - - for (i = 0 ; i <= 30 ; i++) - if ((len >> i) & 1) - break; - - assert((1u << i) == len); - - c[0] = 224 + i; - - return ops_write(c, 1, info); - } - -static ops_boolean_t write_partial_data(const unsigned char *data, - size_t len, - ops_create_info_t *info) - { - if (debug) - fprintf(stderr, "Writing %zu bytes\n", len); - while (len > 0) - { - size_t pdlen = ops_calc_partial_data_length(len); - ops_write_partial_data_length(pdlen, info); - ops_write(data, pdlen, info); - data += pdlen; - len -= pdlen; - } - return ops_true; - } - -static ops_boolean_t write_partial_data_first(stream_partial_arg_t *arg, - const unsigned char *data, - unsigned int len, - ops_create_info_t *info) - { - size_t header_len = ops_memory_get_length(arg->header); - - size_t sz_towrite = len + header_len; - size_t sz_pd = ops_calc_partial_data_length(sz_towrite); - size_t first_data_len = (sz_pd - header_len); - assert(sz_pd >= MIN_PARTIAL_DATA_LENGTH); - - if (debug) - fprintf(stderr, "Writing first packet of len %zu (%zu + %u)\n", - sz_towrite, header_len, len); - - // Write the packet tag, the partial size and the header, followed - // by the first chunk of data and then the remainder of the data. - // (We have to do this in two chunks, as the partial length may not - // match the number of bytes to write.) - return ops_write_ptag(arg->tag, info) && - ops_write_partial_data_length(sz_pd, info) && - ops_write(ops_memory_get_data(arg->header), header_len, info) && - ops_write(data, first_data_len, info) && - write_partial_data(data + first_data_len, len - first_data_len, info); - } - -/* - * Writes out the last packet. The length is encoded as a fixed-length - * packet. Note that even if there is no data accumulated in the - * buffer, we stil lneed to write out a packet, as the final packet in - * a partially-encoded stream must be a fixed-lngth packet. - */ -static ops_boolean_t write_partial_data_last(stream_partial_arg_t *arg, - ops_create_info_t *info) - { - size_t buffer_length = ops_memory_get_length(arg->buffer); - if (debug) - fprintf(stderr, "writing final packet of %zu bytes\n", buffer_length); - return ops_write_length(buffer_length, info) && - ops_write(ops_memory_get_data(arg->buffer), buffer_length, info); - } - -/* - * Writes out the data accumulated in the in-memory buffer. - */ -static ops_boolean_t flush_buffer(stream_partial_arg_t *arg, - ops_create_info_t *info) - { - ops_boolean_t result = ops_true; - size_t buffer_length = ops_memory_get_length(arg->buffer); - if (buffer_length > 0) - { - if (debug) - fprintf(stderr, "Flushing %zu bytes\n", buffer_length); - - result = write_partial_data(ops_memory_get_data(arg->buffer), - buffer_length, - info); - ops_memory_clear(arg->buffer); - } - return result; - } - -static ops_boolean_t stream_partial_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - stream_partial_arg_t *arg = ops_writer_get_arg(winfo); - - // For the first write operation, we need to write out the header - // plus the data. The total size that we write out must be at least - // MIN_PARTIAL_DATA_LENGTH bytes. (See RFC 4880, sec 4.2.2.4, - // Partial Body Lengths.) If we are given less than this, - // then we need to store the data in the buffer until we have the - // minumum - if (!arg->written_first) - { - ops_memory_add(arg->buffer, src, length); - size_t buffer_length = ops_memory_get_length(arg->buffer); - size_t header_length = ops_memory_get_length(arg->header); - if (header_length + buffer_length < MIN_PARTIAL_DATA_LENGTH) - { - if (debug) - fprintf(stderr, "Storing %zu (%zu + %zu) bytes\n", - header_length + buffer_length, header_length, - buffer_length); - return ops_true; // will wait for more data or end of stream - } - arg->written_first = ops_true; - - // Create a writer that will write to the parent stream. Allows - // useage of ops_write_ptag, etc. - ops_create_info_t parent_info; - ops_prepare_parent_info(&parent_info, winfo); - ops_boolean_t result = - write_partial_data_first(arg, ops_memory_get_data(arg->buffer), - buffer_length, &parent_info); - ops_memory_clear(arg->buffer); - ops_move_errors(&parent_info, errors); - return result; - } - else - { - size_t buffer_length = ops_memory_get_length(arg->buffer); - if (buffer_length + length < arg->packet_size) - { - ops_memory_add(arg->buffer, src, length); - if (debug) - fprintf(stderr, "Storing %u bytes (total %zu)\n", - length, buffer_length); - return ops_true; - } - else - { - ops_create_info_t parent_info; - parent_info.winfo = *winfo->next; - parent_info.errors = *errors; - return flush_buffer(arg, &parent_info) && - write_partial_data(src, length, &parent_info); - } - } - return ops_true; - } - -/* - * Invoked when the total packet size is less than - * MIN_PARTIAL_DATA_LENGTH. In that case, we write out the whole - * packet in a single operation, without using partial body length - * packets. - */ -static ops_boolean_t write_complete_packet(stream_partial_arg_t *arg, - ops_create_info_t *info) - { - size_t data_len = ops_memory_get_length(arg->buffer); - size_t header_len = ops_memory_get_length(arg->header); - - // Write the header tag, the length of the packet, and the - // packet. Note that the packet includes the header - // bytes. - size_t total = data_len + header_len; - if (debug) - fprintf(stderr, "writing entire packet with length %zu (%zu + %zu)\n", - total, data_len, header_len); - return ops_write_ptag(arg->tag, info) && - ops_write_length(total, info) && - ops_write(ops_memory_get_data(arg->header), header_len, info) && - ops_write(ops_memory_get_data(arg->buffer), data_len, info); - } - -static ops_boolean_t stream_partial_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - stream_partial_arg_t *arg = ops_writer_get_arg(winfo); - // write last chunk of data - - // Create a writer that will write to the parent stream. Allows - // useage of ops_write_ptag, etc. - ops_create_info_t parent_info; - ops_prepare_parent_info(&parent_info, winfo); - ops_boolean_t result; - if (!arg->written_first) - result = write_complete_packet(arg, &parent_info); - else - // finish writing - result = write_partial_data_last(arg, &parent_info); - if (result && arg->trailer_fn != NULL) - result = arg->trailer_fn(&parent_info, arg->trailer_data); - ops_move_errors(&parent_info, errors); - return result; - } - -static void stream_partial_destroyer(ops_writer_info_t *winfo) - { - stream_partial_arg_t *arg = ops_writer_get_arg(winfo); - ops_memory_free(arg->buffer); - ops_memory_free(arg->header); - free(arg); - } - -/** - * \ingroup InternalAPI - * \brief Pushes a partial packet writer onto the stack. - * - * This writer is used in conjunction with another writer that - * generates streaming data of unknown length. The partial writer - * handles the various partial body length packets. When writing the - * initial packet header, the partial writer will write out the given - * tag, write out an initial length, and then invoke the 'header' - * function to write the remainder of the header. Note that the header - * function should not write a packet tag or a length. - * - * \param packet_size the expected size of the incoming packets. Must - * be >= 512 bytes. Must be a power of 2. The partial writer - * will buffer incoming writes into packets of this size. Note - * that writes will be most efficient if done in chunks of - * packet_size. If the packet size is unknown, specify 0, and - * the default size will be used. - * \param cinfo the writer info - * \param tag the packet tag - * \param header_writer a function that writes the packet header. - * \param header_data passed into header_writer - */ -void ops_writer_push_partial(size_t packet_size, - ops_create_info_t *cinfo, - ops_content_tag_t tag, - ops_write_partial_header_t *header_writer, - void *header_data) - { - ops_writer_push_partial_with_trailer(packet_size, cinfo, tag, header_writer, - header_data, NULL, NULL); - } - -/** - * \ingroup InternalAPI - * \brief Pushes a partial packet writer onto the stack. Adds a trailer - * function that will be invoked after writing out the partial - * packet. - * - * This writer is primarily used by the signature writer, which needs - * to append a signature packet after the literal data packet. - * - * \param trailer_writer a function that writes the trailer - * \param trailer_data passed into trailer_data - * \see ops_writer_push_partial - * \see ops_writer_push_signed - */ -void ops_writer_push_partial_with_trailer( - size_t packet_size, - ops_create_info_t *cinfo, - ops_content_tag_t tag, - ops_write_partial_header_t *header_writer, - void *header_data, - ops_write_partial_trailer_t *trailer_writer, - void *trailer_data) - { - if (packet_size == 0) - packet_size = MIN_PARTIAL_DATA_LENGTH; - assert(packet_size >= MIN_PARTIAL_DATA_LENGTH); - // Verify that the packet size is a valid power of 2. - assert(ops_calc_partial_data_length(packet_size) == packet_size); - - // Create arg to be used with this writer - // Remember to free this in the destroyer - stream_partial_arg_t *arg = ops_mallocz(sizeof *arg); - arg->tag = tag; - arg->written_first = ops_false; - arg->packet_size = packet_size; - arg->buffer = ops_memory_new(); - ops_memory_init(arg->buffer, arg->packet_size); - arg->trailer_fn = trailer_writer; - arg->trailer_data = trailer_data; - - // Write out the header into the memory buffer. Later we will write - // this buffer to the underlying output stream. - ops_create_info_t *header_info; - ops_setup_memory_write(&header_info, &arg->header, 128); - header_writer(header_info, header_data); - ops_writer_close(header_info); - ops_create_info_delete(header_info); - - // And push writer on stack - ops_writer_push(cinfo, stream_partial_writer, stream_partial_finaliser, - stream_partial_destroyer, arg); - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_skey_checksum.c b/openpgpsdk/src/openpgpsdk/writer_skey_checksum.c deleted file mode 100644 index 6b8a480de..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_skey_checksum.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include - -#include - -//static int debug=0; - -typedef struct - { - ops_hash_algorithm_t hash_algorithm; - ops_hash_t hash; - unsigned char *hashed; - } skey_checksum_arg_t; - -static ops_boolean_t skey_checksum_writer(const unsigned char *src, const unsigned length, ops_error_t **errors, ops_writer_info_t *winfo) - { - skey_checksum_arg_t *arg=ops_writer_get_arg(winfo); - ops_boolean_t rtn=ops_true; - - // add contents to hash - arg->hash.add(&arg->hash, src, length); - - // write to next stacked writer - rtn=ops_stacked_write(src,length,errors,winfo); - - // tidy up and return - return rtn; - } - -static ops_boolean_t skey_checksum_finaliser(ops_error_t **errors __attribute__((unused)), ops_writer_info_t *winfo) - { - skey_checksum_arg_t *arg=ops_writer_get_arg(winfo); - arg->hash.finish(&arg->hash, arg->hashed); - return ops_true; - } - -static void skey_checksum_destroyer(ops_writer_info_t* winfo) - { - skey_checksum_arg_t *arg=ops_writer_get_arg(winfo); - free(arg); - } - -/** -\ingroup Core_WritersNext -\param cinfo -\param skey -*/ -void ops_push_skey_checksum_writer(ops_create_info_t *cinfo, ops_secret_key_t *skey) - { - // OPS_USED(info); - // XXX: push a SHA-1 checksum writer (and change s2k to 254). - skey_checksum_arg_t *arg=ops_mallocz(sizeof *arg); - - // configure the arg - arg->hash_algorithm=skey->hash_algorithm; - arg->hashed=&skey->checkhash[0]; - - // init the hash - ops_hash_any(&arg->hash, arg->hash_algorithm); - arg->hash.init(&arg->hash); - - ops_writer_push(cinfo, skey_checksum_writer, skey_checksum_finaliser, skey_checksum_destroyer, arg); - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_stream_encrypt_se_ip.c b/openpgpsdk/src/openpgpsdk/writer_stream_encrypt_se_ip.c deleted file mode 100644 index d882e9022..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_stream_encrypt_se_ip.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2005-2009 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh. - * The Contributors have asserted their moral rights under the - * UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include - -#ifndef WIN32 -#include -#endif - -#include - -#include "keyring_local.h" -#include -#include -#include -#include -#include - -typedef struct - { - ops_crypt_t*crypt; - ops_memory_t *mem_se_ip; - ops_create_info_t *cinfo_se_ip; - ops_hash_t hash; - } stream_encrypt_se_ip_arg_t; - -static ops_boolean_t write_encrypt_se_ip_header(ops_create_info_t *info, - void *header_data); - - -static ops_boolean_t stream_encrypt_se_ip_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo); - -static ops_boolean_t stream_encrypt_se_ip_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo); - -static void stream_encrypt_se_ip_destroyer (ops_writer_info_t *winfo); - - -/** -\ingroup Core_WritersNext -\brief Pushes a streaming encryption writer onto the stack. - -Data written to the stream will be encoded in a Symmetrically -Encrypted Integrity Protected packet. Note that this writer must be -used in conjunction with a literal writer or a signed writer. - -\param cinfo -\param pub_key -Example Code: -\code - ops_writer_push_stream_encrypt_se_ip(cinfo, public_key); - if (compress) - ops_writer_push_compressed(cinfo); - if (sign) - ops_writer_push_signed(cinfo, OPS_SIG_BINARY, secret_key); - else - ops_writer_push_literal(cinfo); -\endcode -*/ - -void ops_writer_push_stream_encrypt_se_ip(ops_create_info_t *cinfo, - const ops_keydata_t *pub_key) - { - ops_crypt_t *encrypt; - unsigned char *iv=NULL; - const unsigned int bufsz=1024; // initial value; gets expanded as necessary - - // Create arg to be used with this writer - // Remember to free this in the destroyer - stream_encrypt_se_ip_arg_t *arg=ops_mallocz(sizeof *arg); - - // Create and write encrypted PK session key - ops_pk_session_key_t *encrypted_pk_session_key; - encrypted_pk_session_key=ops_create_pk_session_key(pub_key); - ops_write_pk_session_key(cinfo, encrypted_pk_session_key); - - // Setup the arg - encrypt=ops_mallocz(sizeof *encrypt); - ops_crypt_any(encrypt, encrypted_pk_session_key->symmetric_algorithm); - iv=ops_mallocz(encrypt->blocksize); - encrypt->set_iv(encrypt, iv); - encrypt->set_key(encrypt, &encrypted_pk_session_key->key[0]); - ops_encrypt_init(encrypt); - - arg->crypt=encrypt; - - ops_setup_memory_write(&arg->cinfo_se_ip, &arg->mem_se_ip, bufsz); - - ops_hash_any(&arg->hash, OPS_HASH_SHA1); - arg->hash.init(&arg->hash); - - // This is a streaming writer, so we don't know the length in - // advance. Use a partial writer to handle the partial body - // packet lengths. - ops_writer_push_partial(PARTIAL_PACKET_SIZE, cinfo, OPS_PTAG_CT_SE_IP_DATA, - write_encrypt_se_ip_header, arg); - - // And push encryption writer on stack - ops_writer_push(cinfo, - stream_encrypt_se_ip_writer, - stream_encrypt_se_ip_finaliser, - stream_encrypt_se_ip_destroyer, arg); - // tidy up - ops_pk_session_key_free(encrypted_pk_session_key); - free(encrypted_pk_session_key); - free(iv); - } - -static ops_boolean_t ops_stream_write_se_ip(const unsigned char *data, - unsigned int len, - stream_encrypt_se_ip_arg_t *arg, - ops_create_info_t *cinfo) - { - ops_writer_push_encrypt_crypt(cinfo, arg->crypt); - ops_write(data, len, cinfo); - ops_writer_pop(cinfo); - arg->hash.add(&arg->hash, data, len); - return ops_true; - } - -// Writes out the header for the encrypted packet. Invoked by the -// partial stream writer. Note that writing the packet tag and the -// packet length is handled by the partial stream writer. -static ops_boolean_t write_encrypt_se_ip_header(ops_create_info_t *cinfo, - void *data) - { - stream_encrypt_se_ip_arg_t *arg = data; - size_t sz_preamble = arg->crypt->blocksize + 2; - unsigned char* preamble = ops_mallocz(sz_preamble); - - ops_write_scalar(SE_IP_DATA_VERSION, 1, cinfo); - - ops_writer_push_encrypt_crypt(cinfo, arg->crypt); - - ops_random(preamble, arg->crypt->blocksize); - preamble[arg->crypt->blocksize]=preamble[arg->crypt->blocksize-2]; - preamble[arg->crypt->blocksize+1]=preamble[arg->crypt->blocksize-1]; - - ops_write(preamble, sz_preamble, cinfo); - arg->hash.add(&arg->hash, preamble, sz_preamble); - ops_writer_pop(cinfo); - free(preamble); - - return ops_true; - } - -static ops_boolean_t -ops_stream_write_se_ip_last(stream_encrypt_se_ip_arg_t *arg, - ops_create_info_t *cinfo) - { - unsigned char c[1]; - unsigned char hashed[SHA_DIGEST_LENGTH]; - const size_t sz_mdc = 1 + 1 + SHA_DIGEST_LENGTH; - - ops_memory_t *mem_mdc; - ops_create_info_t *cinfo_mdc; - - // MDC packet tag - c[0]=0xD3; - arg->hash.add(&arg->hash, &c[0], 1); - - // MDC packet len - c[0]=0x14; - arg->hash.add(&arg->hash, &c[0], 1); - - //finish - arg->hash.finish(&arg->hash, hashed); - - ops_setup_memory_write(&cinfo_mdc, &mem_mdc, sz_mdc); - ops_write_mdc(hashed, cinfo_mdc); - - // encode everthing - ops_writer_push_encrypt_crypt(cinfo, arg->crypt); - - ops_write(ops_memory_get_data(mem_mdc), ops_memory_get_length(mem_mdc), - cinfo); - - ops_writer_pop(cinfo); - - ops_teardown_memory_write(cinfo_mdc, mem_mdc); - - return ops_true; - } - -static ops_boolean_t stream_encrypt_se_ip_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - stream_encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo); - - ops_boolean_t rtn=ops_true; - - ops_stream_write_se_ip(src, length, - arg, arg->cinfo_se_ip); - // now write memory to next writer - rtn=ops_stacked_write(ops_memory_get_data(arg->mem_se_ip), - ops_memory_get_length(arg->mem_se_ip), - errors, winfo); - - ops_memory_clear(arg->mem_se_ip); - - return rtn; - } - -static ops_boolean_t stream_encrypt_se_ip_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - stream_encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo); - // write trailer - ops_stream_write_se_ip_last(arg, arg->cinfo_se_ip); - // now write memory to next writer - return ops_stacked_write(ops_memory_get_data(arg->mem_se_ip), - ops_memory_get_length(arg->mem_se_ip), - errors, winfo); - } - -static void stream_encrypt_se_ip_destroyer(ops_writer_info_t *winfo) - - { - stream_encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo); - - ops_teardown_memory_write(arg->cinfo_se_ip, arg->mem_se_ip); - arg->crypt->decrypt_finish(arg->crypt); - - free(arg->crypt); - free(arg); - } - -// EOF diff --git a/openpgpsdk/src/use_openpgpsdk.pri b/openpgpsdk/src/use_openpgpsdk.pri deleted file mode 100644 index ba82100d8..000000000 --- a/openpgpsdk/src/use_openpgpsdk.pri +++ /dev/null @@ -1,23 +0,0 @@ -# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team -# SPDX-License-Identifier: CC0-1.0 - -DEPENDPATH *= $$system_path($$clean_path($${PWD}/../../openpgpsdk/src)) -INCLUDEPATH *= $$system_path($$clean_path($${PWD}/../../openpgpsdk/src)) -LIBS *= -L$$system_path($$clean_path($${OUT_PWD}/../../openpgpsdk/src/lib/)) -lops - -!equals(TARGET, ops):PRE_TARGETDEPS *= $$system_path($$clean_path($${OUT_PWD}/../../openpgpsdk/src/lib/libops.a)) - -sLibs = -mLibs = ssl crypto z bz2 -dLibs = - -static { - sLibs *= $$mLibs -} else { - dLibs *= $$mLibs -} - -LIBS += $$linkStaticLibs(sLibs) -PRE_TARGETDEPS += $$pretargetStaticLibs(sLibs) - -LIBS += $$linkDynamicLibs(dLibs) diff --git a/plugins/Common/retroshare_plugin.pri b/plugins/Common/retroshare_plugin.pri index 5159aa9b1..a3a6c5d8d 100644 --- a/plugins/Common/retroshare_plugin.pri +++ b/plugins/Common/retroshare_plugin.pri @@ -53,10 +53,6 @@ win32 { LIBS += -L"$$OUT_PWD/../../libretroshare/src/lib" -lretroshare } - # Switch on extra warnings - QMAKE_CFLAGS += -Wextra - QMAKE_CXXFLAGS += -Wextra - CONFIG(debug, debug|release) { } else { # Tell linker to use ASLR protection @@ -103,7 +99,8 @@ win32 { for(bin, BIN_DIR):LIBS += -L"$$bin" LIBS += -lpthread - QMAKE_LFLAGS += -Wl,--end-group + # Do not add for MinGW + !isEmpty(QMAKE_SH): QMAKE_LFLAGS += -Wl,--end-group } macx { diff --git a/plugins/FeedReader/FeedReader.pro b/plugins/FeedReader/FeedReader.pro index b78dda911..97137c2b2 100644 --- a/plugins/FeedReader/FeedReader.pro +++ b/plugins/FeedReader/FeedReader.pro @@ -44,6 +44,8 @@ SOURCES = FeedReaderPlugin.cpp \ gui/FeedReaderFeedNotify.cpp \ gui/FeedReaderUserNotify.cpp \ gui/FeedReaderFeedItem.cpp \ + gui/FeedTreeWidget.cpp \ + gui/ProxyWidget.cpp \ util/CURLWrapper.cpp \ util/XMLWrapper.cpp \ util/HTMLWrapper.cpp \ @@ -64,6 +66,8 @@ HEADERS = FeedReaderPlugin.h \ gui/FeedReaderFeedNotify.h \ gui/FeedReaderUserNotify.h \ gui/FeedReaderFeedItem.h \ + gui/FeedTreeWidget.h \ + gui/ProxyWidget.h \ util/CURLWrapper.h \ util/XMLWrapper.h \ util/HTMLWrapper.h \ @@ -74,7 +78,8 @@ FORMS = gui/FeedReaderDialog.ui \ gui/AddFeedDialog.ui \ gui/PreviewFeedDialog.ui \ gui/FeedReaderConfig.ui \ - gui/FeedReaderFeedItem.ui + gui/FeedReaderFeedItem.ui \ + gui/ProxyWidget.ui TARGET = FeedReader @@ -121,6 +126,11 @@ win32 { #Have to reorder libs, else got /libs/lib/libcrypto.a(bio_lib.o):bio_lib.c:(.text+0x0): multiple definition of `BIO_new' LIBS = -lcurl -lxml2 -lz -lxslt -lws2_32 -lwldap32 -lssl -lcrypto -lgdi32 $${LIBS} + isEmpty(QMAKE_SH) { + # MinGW + LIBS += -lcrypt32 -lbcrypt + } + # Check for msys2 !isEmpty(PREFIX_MSYS2) { message(Use msys2 xml2.) diff --git a/plugins/FeedReader/FeedReaderPlugin.cpp b/plugins/FeedReader/FeedReaderPlugin.cpp index 24b602f9c..bc44a3036 100644 --- a/plugins/FeedReader/FeedReaderPlugin.cpp +++ b/plugins/FeedReader/FeedReaderPlugin.cpp @@ -92,7 +92,7 @@ void FeedReaderPlugin::setInterfaces(RsPlugInInterfaces &interfaces) { mInterfaces = interfaces; - mFeedReader = new p3FeedReader(mPlugInHandler, mInterfaces.mGxsForums); + mFeedReader = new p3FeedReader(mPlugInHandler, mInterfaces.mGxsForums, mInterfaces.mPosted); rsFeedReader = mFeedReader; mNotify = new FeedReaderNotify(); diff --git a/plugins/FeedReader/gui/AddFeedDialog.cpp b/plugins/FeedReader/gui/AddFeedDialog.cpp index 19d02d968..b6e781c4b 100644 --- a/plugins/FeedReader/gui/AddFeedDialog.cpp +++ b/plugins/FeedReader/gui/AddFeedDialog.cpp @@ -30,9 +30,11 @@ #include "gui/common/UIStateHelper.h" #include +#include #include -#define TOKEN_TYPE_FORUM_GROUPS 1 +#define TOKEN_TYPE_FORUM_GROUPS 1 +#define TOKEN_TYPE_POSTED_GROUPS 2 AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, QWidget *parent) : QDialog(parent, Qt::Window), mFeedReader(feedReader), mNotify(notify), ui(new Ui::AddFeedDialog) @@ -47,9 +49,12 @@ AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, mStateHelper->addWidget(TOKEN_TYPE_FORUM_GROUPS, ui->forumComboBox, UISTATE_LOADING_DISABLED); mStateHelper->addWidget(TOKEN_TYPE_FORUM_GROUPS, ui->buttonBox->button(QDialogButtonBox::Ok), UISTATE_LOADING_DISABLED); + mStateHelper->addWidget(TOKEN_TYPE_POSTED_GROUPS, ui->postedComboBox, UISTATE_LOADING_DISABLED); + mStateHelper->addWidget(TOKEN_TYPE_POSTED_GROUPS, ui->buttonBox->button(QDialogButtonBox::Ok), UISTATE_LOADING_DISABLED); /* Setup TokenQueue */ - mTokenQueue = new TokenQueue(rsGxsForums->getTokenService(), this); + mForumTokenQueue = new TokenQueue(rsGxsForums->getTokenService(), this); + mPostedTokenQueue = new TokenQueue(rsPosted->getTokenService(), this); /* Connect signals */ connect(ui->buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(createFeed())); @@ -59,18 +64,23 @@ AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, connect(ui->useStandardStorageTimeCheckBox, SIGNAL(toggled(bool)), this, SLOT(useStandardStorageTimeToggled())); connect(ui->useStandardUpdateInterval, SIGNAL(toggled(bool)), this, SLOT(useStandardUpdateIntervalToggled())); connect(ui->useStandardProxyCheckBox, SIGNAL(toggled(bool)), this, SLOT(useStandardProxyToggled())); - connect(ui->typeForumRadio, SIGNAL(toggled(bool)), this, SLOT(typeForumToggled())); + connect(ui->typeForumCheckBox, SIGNAL(toggled(bool)), this, SLOT(typeForumToggled())); + connect(ui->typePostedCheckBox, SIGNAL(toggled(bool)), this, SLOT(typePostedToggled())); + connect(ui->typeLocalCheckBox, SIGNAL(toggled(bool)), this, SLOT(typeLocalToggled())); + connect(ui->postedFirstImageCheckBox, SIGNAL(toggled(bool)), this, SLOT(postedFirstImageToggled())); connect(ui->previewButton, SIGNAL(clicked()), this, SLOT(preview())); /* currently only for local feeds */ - connect(ui->saveCompletePageCheckBox, SIGNAL(toggled(bool)), this, SLOT(denyForumToggled())); + connect(ui->saveCompletePageCheckBox, SIGNAL(toggled(bool)), this, SLOT(denyForumAndPostedToggled())); connect(ui->urlLineEdit, SIGNAL(textChanged(QString)), this, SLOT(validate())); connect(ui->nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(validate())); connect(ui->useInfoFromFeedCheckBox, SIGNAL(toggled(bool)), this, SLOT(validate())); - connect(ui->typeLocalRadio, SIGNAL(toggled(bool)), this, SLOT(validate())); - connect(ui->typeForumRadio, SIGNAL(toggled(bool)), this, SLOT(validate())); + connect(ui->typeLocalCheckBox, SIGNAL(toggled(bool)), this, SLOT(validate())); + connect(ui->typeForumCheckBox, SIGNAL(toggled(bool)), this, SLOT(validate())); connect(ui->forumComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(validate())); + connect(ui->typePostedCheckBox, SIGNAL(toggled(bool)), this, SLOT(validate())); + connect(ui->postedComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(validate())); connect(ui->clearCachePushButton, SIGNAL(clicked()), this, SLOT(clearMessageCache())); @@ -79,13 +89,24 @@ AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, ui->activatedCheckBox->setChecked(true); mStateHelper->setWidgetEnabled(ui->forumComboBox, false); + mStateHelper->setWidgetEnabled(ui->postedComboBox, false); ui->useInfoFromFeedCheckBox->setChecked(true); ui->updateForumInfoCheckBox->setEnabled(false); ui->updateForumInfoCheckBox->setChecked(true); + ui->updatePostedInfoCheckBox->setEnabled(false); + ui->updatePostedInfoCheckBox->setChecked(true); + ui->postedFirstImageCheckBox->setEnabled(false); + ui->postedFirstImageCheckBox->setChecked(false); + ui->postedOnlyImageCheckBox->setEnabled(false); + ui->postedOnlyImageCheckBox->setChecked(false); + ui->postedShinkImageCheckBox->setEnabled(false); + ui->postedShinkImageCheckBox->setChecked(true); ui->useAuthenticationCheckBox->setChecked(false); ui->useStandardStorageTimeCheckBox->setChecked(true); ui->useStandardUpdateInterval->setChecked(true); ui->useStandardProxyCheckBox->setChecked(true); + ui->embedImagesCheckBox->setChecked(true); + ui->saveCompletePageCheckBox->setEnabled(false); /* not yet supported */ ui->authenticationGroupBox->setEnabled(false); @@ -98,6 +119,9 @@ AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, /* fill own forums */ requestForumGroups(); + /* fill own posted */ + requestPostedGroups(); + validate(); ui->urlLineEdit->setFocus(); @@ -112,7 +136,8 @@ AddFeedDialog::~AddFeedDialog() processSettings(false); delete(ui); - delete(mTokenQueue); + delete(mForumTokenQueue); + delete(mPostedTokenQueue); } void AddFeedDialog::processSettings(bool load) @@ -155,24 +180,71 @@ void AddFeedDialog::useStandardUpdateIntervalToggled() void AddFeedDialog::useStandardProxyToggled() { bool checked = ui->useStandardProxyCheckBox->isChecked(); - ui->proxyAddressLineEdit->setEnabled(!checked); - ui->proxyPortSpinBox->setEnabled(!checked); + ui->proxyWidget->setEnabled(!checked); } void AddFeedDialog::typeForumToggled() { - bool checked = ui->typeForumRadio->isChecked(); + bool checked = ui->typeForumCheckBox->isChecked(); mStateHelper->setWidgetEnabled(ui->forumComboBox, checked); ui->updateForumInfoCheckBox->setEnabled(checked); + + if (checked) { + ui->typeLocalCheckBox->setChecked(false); + } } -void AddFeedDialog::denyForumToggled() +void AddFeedDialog::postedFirstImageToggled() +{ + bool checked = ui->postedFirstImageCheckBox->isChecked(); + ui->postedOnlyImageCheckBox->setEnabled(checked); + + if (!checked) { + ui->postedOnlyImageCheckBox->setChecked(false); + } +} + +void AddFeedDialog::typePostedToggled() +{ + bool checked = ui->typePostedCheckBox->isChecked(); + mStateHelper->setWidgetEnabled(ui->postedComboBox, checked); + ui->updatePostedInfoCheckBox->setEnabled(checked); + ui->postedFirstImageCheckBox->setEnabled(checked); + ui->postedShinkImageCheckBox->setEnabled(checked); + + if (checked) { + ui->typeLocalCheckBox->setChecked(false); + }else { + ui->postedFirstImageCheckBox->setChecked(false); + } +} + +void AddFeedDialog::typeLocalToggled() +{ + bool checked = ui->typeLocalCheckBox->isChecked(); + if (checked) { + mStateHelper->setWidgetEnabled(ui->forumComboBox, false); + mStateHelper->setWidgetEnabled(ui->postedComboBox, false); + ui->typeForumCheckBox->setChecked(false); + ui->typePostedCheckBox->setChecked(false); + ui->saveCompletePageCheckBox->setEnabled(true); + } else { + ui->saveCompletePageCheckBox->setEnabled(false); + ui->saveCompletePageCheckBox->setChecked(false); + } +} + +void AddFeedDialog::denyForumAndPostedToggled() { if (ui->saveCompletePageCheckBox->isChecked()) { - ui->typeForumRadio->setEnabled(false); - ui->typeLocalRadio->setChecked(true); + ui->typeForumCheckBox->setEnabled(false); + ui->typeForumCheckBox->setChecked(false); + ui->typePostedCheckBox->setEnabled(false); + ui->typePostedCheckBox->setChecked(false); + ui->typeLocalCheckBox->setChecked(true); } else { - ui->typeForumRadio->setEnabled(true); + ui->typeForumCheckBox->setEnabled(true); + ui->typePostedCheckBox->setEnabled(true); } } @@ -189,11 +261,15 @@ void AddFeedDialog::validate() ui->previewButton->setEnabled(ok); - if (!ui->typeLocalRadio->isChecked() && !ui->typeForumRadio->isChecked()) { + if (!ui->typeLocalCheckBox->isChecked() && !ui->typeForumCheckBox->isChecked() && !ui->typePostedCheckBox->isChecked()) { ok = false; } - if (ui->typeForumRadio->isChecked() && ui->forumComboBox->itemData(ui->forumComboBox->currentIndex()).toString().isEmpty()) { + if (ui->typeForumCheckBox->isChecked() && ui->forumComboBox->itemData(ui->forumComboBox->currentIndex()).toString().isEmpty()) { + ok = false; + } + + if (ui->typePostedCheckBox->isChecked() && ui->postedComboBox->itemData(ui->postedComboBox->currentIndex()).toString().isEmpty()) { ok = false; } @@ -224,20 +300,32 @@ bool AddFeedDialog::fillFeed(uint32_t feedId) ui->urlLineEdit->setText(QString::fromUtf8(feedInfo.url.c_str())); ui->useInfoFromFeedCheckBox->setChecked(feedInfo.flag.infoFromFeed); ui->updateForumInfoCheckBox->setChecked(feedInfo.flag.updateForumInfo); + ui->updatePostedInfoCheckBox->setChecked(feedInfo.flag.updatePostedInfo); + ui->postedFirstImageCheckBox->setChecked(feedInfo.flag.postedFirstImage); + ui->postedOnlyImageCheckBox->setChecked(feedInfo.flag.postedOnlyImage); + ui->postedShinkImageCheckBox->setChecked(feedInfo.flag.postedShrinkImage); ui->activatedCheckBox->setChecked(!feedInfo.flag.deactivated); ui->embedImagesCheckBox->setChecked(feedInfo.flag.embedImages); ui->saveCompletePageCheckBox->setChecked(feedInfo.flag.saveCompletePage); ui->descriptionPlainTextEdit->setPlainText(QString::fromUtf8(feedInfo.description.c_str())); - if (feedInfo.flag.forum) { - mStateHelper->setWidgetEnabled(ui->forumComboBox, true); - ui->typeForumRadio->setChecked(true); - ui->saveCompletePageCheckBox->setEnabled(false); + if (feedInfo.flag.forum || feedInfo.flag.posted) { + if (feedInfo.flag.forum) { + mStateHelper->setWidgetEnabled(ui->forumComboBox, true); + ui->typeForumCheckBox->setChecked(true); - setActiveForumId(feedInfo.forumId); + setActiveForumId(feedInfo.forumId); + } + if (feedInfo.flag.posted) { + mStateHelper->setWidgetEnabled(ui->postedComboBox, true); + ui->typePostedCheckBox->setChecked(true); + + setActivePostedId(feedInfo.postedId); + } + ui->saveCompletePageCheckBox->setEnabled(false); } else { - ui->typeLocalRadio->setChecked(true); + ui->typeLocalCheckBox->setChecked(true); mStateHelper->setWidgetEnabled(ui->forumComboBox, false); } @@ -246,8 +334,8 @@ bool AddFeedDialog::fillFeed(uint32_t feedId) ui->passwordLineEdit->setText(QString::fromUtf8(feedInfo.password.c_str())); ui->useStandardProxyCheckBox->setChecked(feedInfo.flag.standardProxy); - ui->proxyAddressLineEdit->setText(QString::fromUtf8(feedInfo.proxyAddress.c_str())); - ui->proxyPortSpinBox->setValue(feedInfo.proxyPort); + ui->proxyWidget->setAddress(QString::fromUtf8(feedInfo.proxyAddress.c_str())); + ui->proxyWidget->setPort(feedInfo.proxyPort); ui->useStandardUpdateInterval->setChecked(feedInfo.flag.standardUpdateInterval); ui->updateIntervalSpinBox->setValue(feedInfo.updateInterval / 60); @@ -286,6 +374,21 @@ void AddFeedDialog::setActiveForumId(const std::string &forumId) } } +void AddFeedDialog::setActivePostedId(const std::string &postedId) +{ + if (mStateHelper->isLoading(TOKEN_TYPE_POSTED_GROUPS)) { + mFillPostedId = postedId; + return; + } + + int index = ui->postedComboBox->findData(QString::fromStdString(postedId)); + if (index >= 0) { + ui->postedComboBox->setCurrentIndex(index); + } else { + ui->postedComboBox->setCurrentIndex(0); + } +} + void AddFeedDialog::getFeedInfo(FeedInfo &feedInfo) { feedInfo.parentId = mParentId; @@ -294,25 +397,35 @@ void AddFeedDialog::getFeedInfo(FeedInfo &feedInfo) feedInfo.url = ui->urlLineEdit->text().toUtf8().constData(); feedInfo.flag.infoFromFeed = ui->useInfoFromFeedCheckBox->isChecked(); feedInfo.flag.updateForumInfo = ui->updateForumInfoCheckBox->isChecked() && ui->updateForumInfoCheckBox->isEnabled(); + feedInfo.flag.updatePostedInfo = ui->updatePostedInfoCheckBox->isChecked() && ui->updatePostedInfoCheckBox->isEnabled(); + feedInfo.flag.postedFirstImage = ui->postedFirstImageCheckBox->isChecked() && ui->postedFirstImageCheckBox->isEnabled(); + feedInfo.flag.postedOnlyImage = ui->postedOnlyImageCheckBox->isChecked() && ui->postedOnlyImageCheckBox->isEnabled(); + feedInfo.flag.postedShrinkImage = ui->postedShinkImageCheckBox->isChecked() && ui->postedShinkImageCheckBox->isEnabled(); feedInfo.flag.deactivated = !ui->activatedCheckBox->isChecked(); feedInfo.flag.embedImages = ui->embedImagesCheckBox->isChecked(); feedInfo.flag.saveCompletePage = ui->saveCompletePageCheckBox->isChecked(); feedInfo.description = ui->descriptionPlainTextEdit->toPlainText().toUtf8().constData(); - feedInfo.flag.forum = ui->typeForumRadio->isChecked(); + feedInfo.flag.forum = ui->typeForumCheckBox->isChecked(); if (feedInfo.flag.forum) { feedInfo.forumId = ui->forumComboBox->itemData(ui->forumComboBox->currentIndex()).toString().toStdString(); } + feedInfo.flag.posted = ui->typePostedCheckBox->isChecked(); + + if (feedInfo.flag.posted) { + feedInfo.postedId = ui->postedComboBox->itemData(ui->postedComboBox->currentIndex()).toString().toStdString(); + } + feedInfo.flag.authentication = ui->useAuthenticationCheckBox->isChecked(); feedInfo.user = ui->userLineEdit->text().toUtf8().constData(); feedInfo.password = ui->passwordLineEdit->text().toUtf8().constData(); feedInfo.flag.standardProxy = ui->useStandardProxyCheckBox->isChecked(); - feedInfo.proxyAddress = ui->proxyAddressLineEdit->text().toUtf8().constData(); - feedInfo.proxyPort = ui->proxyPortSpinBox->value(); + feedInfo.proxyAddress = ui->proxyWidget->address().toUtf8().constData(); + feedInfo.proxyPort = ui->proxyWidget->port(); feedInfo.flag.standardUpdateInterval = ui->useStandardUpdateInterval->isChecked(); feedInfo.updateInterval = ui->updateIntervalSpinBox->value() * 60; @@ -340,12 +453,12 @@ void AddFeedDialog::createFeed() if (mFeedId == 0) { /* add new feed */ - RsFeedAddResult result = mFeedReader->addFeed(feedInfo, mFeedId); + RsFeedResult result = mFeedReader->addFeed(feedInfo, mFeedId); if (FeedReaderStringDefs::showError(this, result, tr("Create feed"), tr("Cannot create feed."))) { return; } } else { - RsFeedAddResult result = mFeedReader->setFeed(mFeedId, feedInfo); + RsFeedResult result = mFeedReader->setFeed(mFeedId, feedInfo); if (FeedReaderStringDefs::showError(this, result, tr("Edit feed"), tr("Cannot change feed."))) { return; } @@ -382,10 +495,10 @@ void AddFeedDialog::requestForumGroups() RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - mTokenQueue->cancelActiveRequestTokens(TOKEN_TYPE_FORUM_GROUPS); + mForumTokenQueue->cancelActiveRequestTokens(TOKEN_TYPE_FORUM_GROUPS); uint32_t token; - mTokenQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, TOKEN_TYPE_FORUM_GROUPS); + mForumTokenQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, TOKEN_TYPE_FORUM_GROUPS); } void AddFeedDialog::loadForumGroups(const uint32_t &token) @@ -416,9 +529,50 @@ void AddFeedDialog::loadForumGroups(const uint32_t &token) } } +void AddFeedDialog::requestPostedGroups() +{ + mStateHelper->setLoading(TOKEN_TYPE_POSTED_GROUPS, true); + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + mPostedTokenQueue->cancelActiveRequestTokens(TOKEN_TYPE_POSTED_GROUPS); + + uint32_t token; + mPostedTokenQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, TOKEN_TYPE_POSTED_GROUPS); +} + +void AddFeedDialog::loadPostedGroups(const uint32_t &token) +{ + std::vector groups; + rsPosted->getGroupData(token, groups); + + ui->postedComboBox->clear(); + + for (std::vector::iterator it = groups.begin(); it != groups.end(); ++it) { + const RsPostedGroup &group = *it; + + /* show only own posted */ + if (IS_GROUP_PUBLISHER(group.mMeta.mSubscribeFlags) && IS_GROUP_ADMIN(group.mMeta.mSubscribeFlags) && !group.mMeta.mAuthorId.isNull()) { + ui->postedComboBox->addItem(QString::fromUtf8(group.mMeta.mGroupName.c_str()), QString::fromStdString(group.mMeta.mGroupId.toStdString())); + } + } + + /* insert empty item */ + ui->postedComboBox->insertItem(0, "", ""); + ui->postedComboBox->setCurrentIndex(0); + + mStateHelper->setLoading(TOKEN_TYPE_POSTED_GROUPS, false); + + if (!mFillPostedId.empty()) { + setActivePostedId(mFillPostedId); + mFillPostedId.clear(); + } +} + void AddFeedDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) { - if (queue == mTokenQueue) + if (queue == mForumTokenQueue) { /* now switch on req */ switch(req.mUserType) @@ -433,4 +587,20 @@ void AddFeedDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req } } + + if (queue == mPostedTokenQueue) + { + /* now switch on req */ + switch(req.mUserType) + { + case TOKEN_TYPE_POSTED_GROUPS: + loadPostedGroups(req.mToken); + break; + + default: + std::cerr << "AddFeedDialog::loadRequest() ERROR: INVALID TYPE"; + std::cerr << std::endl; + + } + } } diff --git a/plugins/FeedReader/gui/AddFeedDialog.h b/plugins/FeedReader/gui/AddFeedDialog.h index 111238d33..e557580e1 100644 --- a/plugins/FeedReader/gui/AddFeedDialog.h +++ b/plugins/FeedReader/gui/AddFeedDialog.h @@ -53,7 +53,10 @@ private slots: void useStandardUpdateIntervalToggled(); void useStandardProxyToggled(); void typeForumToggled(); - void denyForumToggled(); + void postedFirstImageToggled(); + void typePostedToggled(); + void typeLocalToggled(); + void denyForumAndPostedToggled(); void validate(); void createFeed(); void preview(); @@ -63,9 +66,12 @@ private: void processSettings(bool load); void getFeedInfo(FeedInfo &feedInfo); void setActiveForumId(const std::string &forumId); + void setActivePostedId(const std::string &postedId); void requestForumGroups(); void loadForumGroups(const uint32_t &token); + void requestPostedGroups(); + void loadPostedGroups(const uint32_t &token); private: RsFeedReader *mFeedReader; @@ -73,13 +79,15 @@ private: uint32_t mFeedId; uint32_t mParentId; std::string mFillForumId; + std::string mFillPostedId; RsFeedTransformationType mTransformationType; std::list mXPathsToUse; std::list mXPathsToRemove; std::string mXslt; - TokenQueue *mTokenQueue; + TokenQueue *mForumTokenQueue; + TokenQueue *mPostedTokenQueue; UIStateHelper *mStateHelper; Ui::AddFeedDialog *ui; diff --git a/plugins/FeedReader/gui/AddFeedDialog.ui b/plugins/FeedReader/gui/AddFeedDialog.ui index ff657b6ff..569578473 100644 --- a/plugins/FeedReader/gui/AddFeedDialog.ui +++ b/plugins/FeedReader/gui/AddFeedDialog.ui @@ -6,8 +6,8 @@ 0 0 - 715 - 605 + 739 + 653 @@ -37,56 +37,14 @@ - + QFrame::NoFrame QFrame::Raised - - - - - Type - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - - - Forum - - - - - - - - - - - - Local Feed - - - - - - + @@ -175,37 +133,16 @@ Proxy - - + + Use standard proxy - - - - Server - - - - - - - - - - : - - - - - - - 65535 - - + + @@ -306,6 +243,13 @@ + + + 11 + true + true + + Name: @@ -316,7 +260,44 @@ - + + + + Misc + + + + + + Activated + + + + + + + Use name and description from feed + + + + + + + Embed images + + + + + + + Save complete web page (experimental for local feeds) + + + + + + + Transformation @@ -349,46 +330,99 @@ - - + + - Misc + Type - - - + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + 0 + 0 + + - Activated + Forum - - + + + + + - Use name and description from feed + Local Feed - - + + + + + + Update forum information + + + + + + + + + + - Update forum information + Board - - - - Embed images - - - - - - - Save complete web page (experimental for local feeds) - - + + + + + + Update board information + + + + + + + Only image + + + + + + + Use first image as board image + + + + + + + Shrink image + + + + @@ -405,27 +439,47 @@
gui/common/HeaderFrame.h
1 + + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
+ + ProxyWidget + QWidget +
gui/ProxyWidget.h
+ 1 +
urlLineEdit nameLineEdit descriptionPlainTextEdit - typeForumRadio + typeForumCheckBox forumComboBox + updateForumInfoCheckBox + typePostedCheckBox + postedComboBox + updatePostedInfoCheckBox + postedShinkImageCheckBox + postedFirstImageCheckBox + postedOnlyImageCheckBox + typeLocalCheckBox activatedCheckBox useInfoFromFeedCheckBox - updateForumInfoCheckBox + embedImagesCheckBox + saveCompletePageCheckBox + previewButton useAuthenticationCheckBox userLineEdit passwordLineEdit useStandardStorageTimeCheckBox + clearCachePushButton storageTimeSpinBox useStandardUpdateInterval updateIntervalSpinBox useStandardProxyCheckBox - proxyAddressLineEdit - proxyPortSpinBox - buttonBox + proxyWidget diff --git a/plugins/FeedReader/gui/FeedReaderConfig.cpp b/plugins/FeedReader/gui/FeedReaderConfig.cpp index 89456e3da..91b24f394 100644 --- a/plugins/FeedReader/gui/FeedReaderConfig.cpp +++ b/plugins/FeedReader/gui/FeedReaderConfig.cpp @@ -31,8 +31,7 @@ FeedReaderConfig::FeedReaderConfig(QWidget *parent, Qt::WindowFlags flags) /* Invoke the Qt Designer generated object setup routine */ ui->setupUi(this); - ui->proxyAddressLineEdit->setEnabled(false); - ui->proxyPortSpinBox->setEnabled(false); + ui->proxyWidget->setEnabled(false); /* Connect signals */ connect(ui->updateIntervalSpinBox, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this]() { @@ -51,8 +50,7 @@ FeedReaderConfig::FeedReaderConfig(QWidget *parent, Qt::WindowFlags flags) Settings->setValueToGroup("FeedReaderDialog", "OpenAllInNewTab", ui->openAllInNewTabCheckBox->isChecked()); }); connect(ui->useProxyCheckBox, &QCheckBox::toggled, this, &FeedReaderConfig::updateProxy); - connect(ui->proxyAddressLineEdit, &QLineEdit::textChanged, this, &FeedReaderConfig::updateProxy); - connect(ui->proxyPortSpinBox, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, &FeedReaderConfig::updateProxy); + connect(ui->proxyWidget, &ProxyWidget::changed, this, &FeedReaderConfig::updateProxy); connect(ui->useProxyCheckBox, SIGNAL(toggled(bool)), this, SLOT(useProxyToggled())); } @@ -75,8 +73,8 @@ void FeedReaderConfig::load() std::string proxyAddress; uint16_t proxyPort; whileBlocking(ui->useProxyCheckBox)->setChecked(rsFeedReader->getStandardProxy(proxyAddress, proxyPort)); - whileBlocking(ui->proxyAddressLineEdit)->setText(QString::fromUtf8(proxyAddress.c_str())); - whileBlocking(ui->proxyPortSpinBox)->setValue(proxyPort); + whileBlocking(ui->proxyWidget)->setAddress(QString::fromUtf8(proxyAddress.c_str())); + whileBlocking(ui->proxyWidget)->setPort(proxyPort); loaded = true; @@ -87,11 +85,10 @@ void FeedReaderConfig::useProxyToggled() { bool enabled = ui->useProxyCheckBox->isChecked(); - ui->proxyAddressLineEdit->setEnabled(enabled); - ui->proxyPortSpinBox->setEnabled(enabled); + ui->proxyWidget->setEnabled(enabled); } void FeedReaderConfig::updateProxy() { - rsFeedReader->setStandardProxy(ui->useProxyCheckBox->isChecked(), ui->proxyAddressLineEdit->text().toUtf8().constData(), ui->proxyPortSpinBox->value()); + rsFeedReader->setStandardProxy(ui->useProxyCheckBox->isChecked(), ui->proxyWidget->address().toUtf8().constData(), ui->proxyWidget->port()); } diff --git a/plugins/FeedReader/gui/FeedReaderConfig.ui b/plugins/FeedReader/gui/FeedReaderConfig.ui index 8928dc85e..18fa29a42 100644 --- a/plugins/FeedReader/gui/FeedReaderConfig.ui +++ b/plugins/FeedReader/gui/FeedReaderConfig.ui @@ -77,37 +77,16 @@ Proxy - - + + Use proxy - - - - Server - - - - - - - - - - 65535 - - - - - - - : - - + +
@@ -157,12 +136,19 @@
+ + + ProxyWidget + QWidget +
gui/ProxyWidget.h
+ 1 +
+
updateIntervalSpinBox storageTimeSpinBox useProxyCheckBox - proxyAddressLineEdit - proxyPortSpinBox + proxyWidget saveInBackgroundCheckBox setMsgToReadOnActivate openAllInNewTabCheckBox diff --git a/plugins/FeedReader/gui/FeedReaderDialog.cpp b/plugins/FeedReader/gui/FeedReaderDialog.cpp index abc2f1aa5..87db9cf9c 100644 --- a/plugins/FeedReader/gui/FeedReaderDialog.cpp +++ b/plugins/FeedReader/gui/FeedReaderDialog.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "FeedReaderDialog.h" #include "FeedReaderMessageWidget.h" @@ -35,6 +36,8 @@ #include "gui/settings/rsharesettings.h" #include "gui/notifyqt.h" #include "FeedReaderUserNotify.h" +#include "gui/Posted/PostedCreatePostDialog.h" +#include "util/imageutil.h" #include "interface/rsFeedReader.h" #include "retroshare/rsiface.h" @@ -55,6 +58,8 @@ #define ROLE_FEED_ERROR Qt::UserRole + 9 #define ROLE_FEED_DEACTIVATED Qt::UserRole + 10 +const int MAXMESSAGESIZE = RsSerialiser::MAX_SERIAL_SIZE - 70000; + FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, QWidget *parent) : MainPage(parent), mFeedReader(feedReader), mNotify(notify), ui(new Ui::FeedReaderDialog) { @@ -66,6 +71,7 @@ FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, FeedReaderNotify *n mMessageWidget = NULL; connect(mNotify, &FeedReaderNotify::feedChanged, this, &FeedReaderDialog::feedChanged, Qt::QueuedConnection); + connect(mNotify, &FeedReaderNotify::optimizeImage, this, &FeedReaderDialog::optimizeImage, Qt::QueuedConnection); connect(NotifyQt::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); @@ -84,9 +90,16 @@ FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, FeedReaderNotify *n connect(ui->feedAddButton, SIGNAL(clicked()), this, SLOT(newFeed())); connect(ui->feedProcessButton, SIGNAL(clicked()), this, SLOT(processFeed())); + connect(ui->feedTreeWidget, SIGNAL(feedReparent(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(feedTreeReparent(QTreeWidgetItem*,QTreeWidgetItem*))); + mFeedCompareRole = new RSTreeWidgetItemCompareRole; mFeedCompareRole->setRole(COLUMN_FEED_NAME, ROLE_FEED_SORT); + /* enable drag and drop */ + ui->feedTreeWidget->setAcceptDrops(true); + ui->feedTreeWidget->setDragEnabled(true); + ui->feedTreeWidget->setDragDropMode(QAbstractItemView::InternalMove); + /* initialize root item */ mRootItem = new QTreeWidgetItem(ui->feedTreeWidget); QString name = tr("Message Folders"); @@ -116,6 +129,8 @@ FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, FeedReaderNotify *n settingsChanged(); feedTreeItemActivated(NULL); + + mFontSizeHandler.registerFontSize(ui->feedTreeWidget); } FeedReaderDialog::~FeedReaderDialog() @@ -395,6 +410,9 @@ void FeedReaderDialog::updateFeeds(uint32_t parentId, QTreeWidgetItem *parentIte mOpenFeedIds->removeAt(index); } } + } else { + /* disable drop */ + item->setFlags(item->flags() & ~Qt::ItemIsDropEnabled); } } @@ -594,6 +612,55 @@ void FeedReaderDialog::feedChanged(uint32_t feedId, int type) calculateFeedItems(); } +void FeedReaderDialog::optimizeImage() +{ + while (true) { + FeedReaderOptimizeImageTask *optimizeImageTask = mFeedReader->getOptimizeImageTask(); + + if (!optimizeImageTask) { + return; + } + + optimizeImageTask->mResult = false; + + QImage image; + if (image.loadFromData(optimizeImageTask->mImage.data(), optimizeImageTask->mImage.size())) { + QByteArray optimizedImageData; + std::string optimizedImageMimeType; + QImage imageOptDummy; + + switch (optimizeImageTask->mType) { + case FeedReaderOptimizeImageTask::POSTED: + if (PostedCreatePostDialog::optimizeImage(image, optimizedImageData, imageOptDummy)) { + optimizedImageMimeType = "image/jpeg"; + optimizeImageTask->mResult = true; + } + break; + case FeedReaderOptimizeImageTask::SIZE: + if (ImageUtil::optimizeSizeBytes(optimizedImageData, image, imageOptDummy, "JPG", 0, MAXMESSAGESIZE)) { + optimizedImageMimeType = "image/jpg"; + optimizeImageTask->mResult = true; + } + break; + } + + if (optimizeImageTask->mResult) { + if (optimizedImageData.size() < (ssize_t) optimizeImageTask->mImage.size()) { + /* use optimized image */ + optimizeImageTask->mImageResult.assign(optimizedImageData.begin(), optimizedImageData.end()); + optimizeImageTask->mMimeTypeResult = optimizedImageMimeType; + } else { + /* use original image */ + optimizeImageTask->mImageResult = optimizeImageTask->mImage; + optimizeImageTask->mMimeTypeResult = optimizeImageTask->mMimeType; + } + } + } + + mFeedReader->setOptimizeImageTaskResult(optimizeImageTask); + } +} + FeedReaderMessageWidget *FeedReaderDialog::feedMessageWidget(uint32_t id) { int tabCount = ui->messageTabWidget->count(); @@ -738,7 +805,7 @@ void FeedReaderDialog::newFolder() if (dialog.exec() == QDialog::Accepted && !dialog.textValue().isEmpty()) { uint32_t feedId; - RsFeedAddResult result = mFeedReader->addFolder(currentFeedId(), dialog.textValue().toUtf8().constData(), feedId); + RsFeedResult result = mFeedReader->addFolder(currentFeedId(), dialog.textValue().toUtf8().constData(), feedId); FeedReaderStringDefs::showError(this, result, tr("Create folder"), tr("Cannot create folder.")); } } @@ -791,7 +858,7 @@ void FeedReaderDialog::editFeed() dialog.setTextValue(item->data(COLUMN_FEED_DATA, ROLE_FEED_NAME).toString()); if (dialog.exec() == QDialog::Accepted && !dialog.textValue().isEmpty()) { - RsFeedAddResult result = mFeedReader->setFolder(feedId, dialog.textValue().toUtf8().constData()); + RsFeedResult result = mFeedReader->setFolder(feedId, dialog.textValue().toUtf8().constData()); FeedReaderStringDefs::showError(this, result, tr("Create folder"), tr("Cannot create folder.")); } } else { @@ -832,3 +899,30 @@ void FeedReaderDialog::processFeed() mFeedReader->processFeed(feedId); } + +void FeedReaderDialog::feedTreeReparent(QTreeWidgetItem *item, QTreeWidgetItem *newParent) +{ + if (!item || ! newParent) { + return; + } + + uint32_t feedId = item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt(); + uint32_t parentId = newParent->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt(); + + if (feedId == 0) { + return; + } + + RsFeedResult result = mFeedReader->setParent(feedId, parentId); + if (FeedReaderStringDefs::showError(this, result, tr("Move feed"), tr("Cannot move feed."))) { + return; + } + + bool expanded = item->isExpanded(); + item->parent()->removeChild(item); + newParent->addChild(item); + item->setExpanded(expanded); + newParent->setExpanded(true); + + calculateFeedItems(); +} diff --git a/plugins/FeedReader/gui/FeedReaderDialog.h b/plugins/FeedReader/gui/FeedReaderDialog.h index a221cfe64..a9672bc76 100644 --- a/plugins/FeedReader/gui/FeedReaderDialog.h +++ b/plugins/FeedReader/gui/FeedReaderDialog.h @@ -23,6 +23,7 @@ #include #include "interface/rsFeedReader.h" +#include "util/FontSizeHandler.h" namespace Ui { class FeedReaderDialog; @@ -61,6 +62,7 @@ private slots: void editFeed(); void activateFeed(); void processFeed(); + void feedTreeReparent(QTreeWidgetItem *item, QTreeWidgetItem *newParent); void messageTabCloseRequested(int index); void messageTabChanged(int index); @@ -68,6 +70,7 @@ private slots: /* FeedReaderNotify */ void feedChanged(uint32_t feedId, int type); + void optimizeImage(); private: uint32_t currentFeedId(); @@ -96,6 +99,8 @@ private: RsFeedReader *mFeedReader; FeedReaderNotify *mNotify; + FontSizeHandler mFontSizeHandler; + /** Qt Designer generated object */ Ui::FeedReaderDialog *ui; }; diff --git a/plugins/FeedReader/gui/FeedReaderDialog.ui b/plugins/FeedReader/gui/FeedReaderDialog.ui index 7c77717bb..440bb7736 100644 --- a/plugins/FeedReader/gui/FeedReaderDialog.ui +++ b/plugins/FeedReader/gui/FeedReaderDialog.ui @@ -57,10 +57,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -86,7 +86,14 @@ - + + + + 12 + 75 + true + + Feeds @@ -143,7 +150,7 @@ - + Qt::CustomContextMenu @@ -179,14 +186,9 @@ - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
- - RSTreeWidget + FeedTreeWidget QTreeWidget -
gui/common/RSTreeWidget.h
+
gui/FeedTreeWidget.h
RSTabWidget diff --git a/plugins/FeedReader/gui/FeedReaderFeedItem.ui b/plugins/FeedReader/gui/FeedReaderFeedItem.ui index 37c2df915..47d56f441 100644 --- a/plugins/FeedReader/gui/FeedReaderFeedItem.ui +++ b/plugins/FeedReader/gui/FeedReaderFeedItem.ui @@ -10,7 +10,7 @@ 123
- + 1 @@ -30,7 +30,7 @@ 1 - + 0 @@ -46,9 +46,9 @@ QFrame::Sunken - + - + @@ -66,9 +66,9 @@ - + - + @@ -92,7 +92,7 @@ - + 0 @@ -101,7 +101,9 @@ + 11 75 + true true @@ -127,7 +129,7 @@ - + 8 @@ -195,7 +197,7 @@ p, li { white-space: pre-wrap; } Expand - + :/icons/png/down-arrow.png:/icons/png/down-arrow.png @@ -221,7 +223,7 @@ p, li { white-space: pre-wrap; } Set as read and remove item - + :/icons/png/correct.png:/icons/png/correct.png @@ -247,7 +249,7 @@ p, li { white-space: pre-wrap; } Remove Item - + :/icons/png/exit2.png:/icons/png/exit2.png @@ -260,7 +262,7 @@ p, li { white-space: pre-wrap; } - + 0 @@ -287,7 +289,7 @@ p, li { white-space: pre-wrap; } QFrame::Sunken - + 5 @@ -336,16 +338,8 @@ p, li { white-space: pre-wrap; } - - - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
-
- diff --git a/plugins/FeedReader/gui/FeedReaderFeedNotify.cpp b/plugins/FeedReader/gui/FeedReaderFeedNotify.cpp index 16a3099e6..23d95f50e 100644 --- a/plugins/FeedReader/gui/FeedReaderFeedNotify.cpp +++ b/plugins/FeedReader/gui/FeedReaderFeedNotify.cpp @@ -90,7 +90,7 @@ void FeedReaderFeedNotify::msgChanged(uint32_t feedId, const QString &msgId, int mMutex->unlock(); } -FeedItem *FeedReaderFeedNotify::feedItem(FeedHolder *parent) +FeedItem *FeedReaderFeedNotify::feedItem(FeedHolder */*parent*/) { bool msgPending = false; FeedInfo feedInfo; @@ -119,7 +119,7 @@ FeedItem *FeedReaderFeedNotify::feedItem(FeedHolder *parent) return new FeedReaderFeedItem(mFeedReader, mNotify, feedInfo, msgInfo); } -FeedItem *FeedReaderFeedNotify::testFeedItem(FeedHolder *parent) +FeedItem *FeedReaderFeedNotify::testFeedItem(FeedHolder */*parent*/) { FeedInfo feedInfo; feedInfo.name = tr("Test").toUtf8().constData(); diff --git a/plugins/FeedReader/gui/FeedReaderMessageWidget.cpp b/plugins/FeedReader/gui/FeedReaderMessageWidget.cpp index 1550bc636..ec0e3d0e2 100644 --- a/plugins/FeedReader/gui/FeedReaderMessageWidget.cpp +++ b/plugins/FeedReader/gui/FeedReaderMessageWidget.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "FeedReaderMessageWidget.h" #include "ui_FeedReaderMessageWidget.h" @@ -36,8 +37,14 @@ #include "gui/settings/rsharesettings.h" #include "util/HandleRichText.h" #include "util/QtVersion.h" +#include "gui/Posted/PostedCreatePostDialog.h" +#include "gui/gxsforums/CreateGxsForumMsg.h" +#include "gui/common/FilesDefs.h" +#include "util/imageutil.h" #include "retroshare/rsiface.h" +#include "retroshare/rsgxsforums.h" +#include "retroshare/rsposted.h" #define COLUMN_MSG_COUNT 4 #define COLUMN_MSG_TITLE 0 @@ -83,6 +90,12 @@ FeedReaderMessageWidget::FeedReaderMessageWidget(uint32_t feedId, RsFeedReader * connect(ui->msgRemoveButton, SIGNAL(clicked()), this, SLOT(removeMsg())); connect(ui->feedProcessButton, SIGNAL(clicked()), this, SLOT(processFeed())); + /* Set initial size the splitter */ + QList sizes; + sizes << 250 << width(); // Qt calculates the right sizes + ui->pictureSplitter->setSizes(sizes); + ui->pictureSplitter->hide(); + // create timer for navigation mTimer = new QTimer(this); mTimer->setInterval(300); @@ -115,6 +128,10 @@ FeedReaderMessageWidget::FeedReaderMessageWidget(uint32_t feedId, RsFeedReader * ui->filterLineEdit->addFilter(QIcon(), tr("Author"), COLUMN_MSG_AUTHOR, tr("Search Author")); ui->filterLineEdit->setCurrentFilter(COLUMN_MSG_TITLE); + /* add image actions */ + ui->attachmentLabel->addContextMenuAction(ui->actionAttachmentCopyLinkLocation); + connect(ui->actionAttachmentCopyLinkLocation, &QAction::triggered, this, &FeedReaderMessageWidget::attachmentCopyLinkLocation); + /* load settings */ processSettings(true); @@ -137,6 +154,8 @@ FeedReaderMessageWidget::FeedReaderMessageWidget(uint32_t feedId, RsFeedReader * ui->msgTreeWidget->installEventFilter(this); setFeedId(feedId); + + mFontSizeHandler.registerFontSize(ui->msgTreeWidget); } FeedReaderMessageWidget::~FeedReaderMessageWidget() @@ -175,6 +194,7 @@ void FeedReaderMessageWidget::processSettings(bool load) // state of splitter ui->msgSplitter->restoreState(Settings->value("msgSplitter").toByteArray()); + ui->pictureSplitter->restoreState(Settings->value("pictureSplitter").toByteArray()); } else { // save settings @@ -183,6 +203,7 @@ void FeedReaderMessageWidget::processSettings(bool load) // state of splitter Settings->setValue("msgSplitter", ui->msgSplitter->saveState()); + Settings->setValue("pictureSplitter", ui->pictureSplitter->saveState()); } Settings->endGroup(); @@ -245,9 +266,19 @@ void FeedReaderMessageWidget::setFeedId(uint32_t feedId) ui->msgReadAllButton->setEnabled(false); ui->msgTreeWidget->setPlaceholderText(""); } else { - if (mFeedInfo.flag.forum) { + if (mFeedInfo.flag.forum || mFeedInfo.flag.posted) { ui->msgReadAllButton->setEnabled(false); - ui->msgTreeWidget->setPlaceholderText(tr("The messages will be added to the forum")); + + if (mFeedInfo.flag.forum && mFeedInfo.flag.posted) { + ui->msgTreeWidget->setPlaceholderText(tr("The messages will be added to the forum and the board")); + } else { + if (mFeedInfo.flag.forum) { + ui->msgTreeWidget->setPlaceholderText(tr("The messages will be added to the forum")); + } + if (mFeedInfo.flag.posted) { + ui->msgTreeWidget->setPlaceholderText(tr("The messages will be added to the board")); + } + } } else { ui->msgReadAllButton->setEnabled(true); ui->msgTreeWidget->setPlaceholderText(""); @@ -340,6 +371,20 @@ void FeedReaderMessageWidget::msgTreeCustomPopupMenu(QPoint /*point*/) action = contextMnu.addAction(QIcon(""), tr("Remove"), this, SLOT(removeMsg())); action->setEnabled(!selectedItems.empty()); + if (selectedItems.size() == 1 && (mFeedReader->forums() || mFeedReader->posted())) { + contextMnu.addSeparator(); + + if (mFeedReader->forums()) { + QMenu *menu = contextMnu.addMenu(tr("Add to forum")); + connect(menu, SIGNAL(aboutToShow()), this, SLOT(fillForumMenu())); + } + + if (mFeedReader->posted()) { + QMenu *menu = contextMnu.addMenu(tr("Add to board")); + connect(menu, SIGNAL(aboutToShow()), this, SLOT(fillPostedMenu())); + } + } + contextMnu.addSeparator(); action = contextMnu.addAction(QIcon(""), tr("Retransform"), this, SLOT(retransformMsg())); @@ -571,6 +616,21 @@ void FeedReaderMessageWidget::msgItemChanged() mTimer->start(); } +void FeedReaderMessageWidget::clearMessage() +{ + ui->msgTitle->clear(); +// ui->msgLink->clear(); + ui->msgText->clear(); + ui->msgTextSplitter->clear(); + ui->attachmentLabel->clear(); + ui->linkButton->setEnabled(false); + ui->msgText->show(); + ui->pictureSplitter->hide(); + + ui->actionAttachmentCopyLinkLocation->setData(QVariant()); + ui->actionAttachmentCopyLinkLocation->setEnabled(false); +} + void FeedReaderMessageWidget::updateCurrentMessage() { mTimer->stop(); @@ -580,10 +640,7 @@ void FeedReaderMessageWidget::updateCurrentMessage() std::string msgId = currentMsgId(); if (mFeedId == 0 || msgId.empty()) { - ui->msgTitle->clear(); -// ui->msgLink->clear(); - ui->msgText->clear(); - ui->linkButton->setEnabled(false); + clearMessage(); ui->msgReadButton->setEnabled(false); ui->msgUnreadButton->setEnabled(false); @@ -594,10 +651,7 @@ void FeedReaderMessageWidget::updateCurrentMessage() QTreeWidgetItem *item = ui->msgTreeWidget->currentItem(); if (!item) { /* there is something wrong */ - ui->msgTitle->clear(); -// ui->msgLink->clear(); - ui->msgText->clear(); - ui->linkButton->setEnabled(false); + clearMessage(); ui->msgReadButton->setEnabled(false); ui->msgUnreadButton->setEnabled(false); @@ -612,10 +666,7 @@ void FeedReaderMessageWidget::updateCurrentMessage() /* get msg */ FeedMsgInfo msgInfo; if (!mFeedReader->getMsgInfo(mFeedId, msgId, msgInfo)) { - ui->msgTitle->clear(); -// ui->msgLink->clear(); - ui->msgText->clear(); - ui->linkButton->setEnabled(false); + clearMessage(); return; } @@ -635,9 +686,41 @@ void FeedReaderMessageWidget::updateCurrentMessage() setMsgAsReadUnread(row, setToReadOnActive); } + ui->actionAttachmentCopyLinkLocation->setData(QVariant()); + ui->actionAttachmentCopyLinkLocation->setEnabled(false); + + if (!msgInfo.attachment.empty()) { + QByteArray imageData((char*) msgInfo.attachment.data(), msgInfo.attachment.size()); + QPixmap pixmap; + if (pixmap.loadFromData(imageData)) { + ui->attachmentLabel->setPixmap(pixmap); + ui->pictureSplitter->show(); + ui->msgText->hide(); + } else { + ui->pictureSplitter->hide(); + ui->msgText->show(); + } + + if (!msgInfo.attachmentLink.empty()) { + ui->actionAttachmentCopyLinkLocation->setData(QString::fromUtf8(msgInfo.attachmentLink.c_str())); + ui->actionAttachmentCopyLinkLocation->setEnabled(true); + } + } else { + ui->pictureSplitter->hide(); + ui->msgText->show(); + } + QString msgTxt = RsHtml().formatText(ui->msgText->document(), QString::fromUtf8((msgInfo.descriptionTransformed.empty() ? msgInfo.description : msgInfo.descriptionTransformed).c_str()), RSHTML_FORMATTEXT_EMBED_LINKS); - ui->msgText->setHtml(msgTxt); + if (ui->pictureSplitter->isVisible()) { + ui->msgTextSplitter->setHtml(msgTxt); + ui->msgText->clear(); + } else { + ui->msgText->setHtml(msgTxt); + ui->msgTextSplitter->clear(); + ui->attachmentLabel->clear(); + } + ui->msgTitle->setText(QString::fromUtf8(msgInfo.title.c_str())); ui->linkButton->setEnabled(!msgInfo.link.empty()); @@ -714,11 +797,11 @@ void FeedReaderMessageWidget::toggleMsgText() void FeedReaderMessageWidget::toggleMsgText_internal() { if (ui->expandButton->isChecked()) { - ui->msgText->setVisible(true); + ui->horizontalLayoutWidget->setVisible(true); ui->expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); ui->expandButton->setToolTip(tr("Hide")); } else { - ui->msgText->setVisible(false); + ui->horizontalLayoutWidget->setVisible(false); ui->expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); ui->expandButton->setToolTip(tr("Expand")); } @@ -840,3 +923,123 @@ void FeedReaderMessageWidget::openLinkMsg() QDesktopServices::openUrl(QUrl(link)); } + +void FeedReaderMessageWidget::fillForumMenu() +{ + QMenu *menu = dynamic_cast(sender()) ; + if (!menu) { + return; + } + + disconnect(menu, SIGNAL(aboutToShow()), this, SLOT(fillForumMenu())); + + std::vector groups; + if (mFeedReader->getForumGroups(groups, true)) { + for (std::vector::iterator it = groups.begin(); it != groups.end(); ++it) { + const RsGxsForumGroup &group = *it; + QAction *action = menu->addAction(QString::fromUtf8(group.mMeta.mGroupName.c_str()), this, SLOT(addToForum())); + action->setData(QString::fromUtf8(group.mMeta.mGroupId.toStdString().c_str())); + } + } +} + +void FeedReaderMessageWidget::fillPostedMenu() +{ + QMenu *menu = dynamic_cast(sender()) ; + if (!menu) { + return; + } + + disconnect(menu, SIGNAL(aboutToShow()), this, SLOT(fillPostedMenu())); + + std::vector groups; + if (mFeedReader->getPostedGroups(groups, true)) { + for (std::vector::iterator it = groups.begin(); it != groups.end(); ++it) { + const RsPostedGroup &group = *it; + QAction *action = menu->addAction(QString::fromUtf8(group.mMeta.mGroupName.c_str()), this, SLOT(addToPosted())); + action->setData(QString::fromUtf8(group.mMeta.mGroupId.toStdString().c_str())); + } + } +} + +void FeedReaderMessageWidget::addToForum() +{ + QAction *action = dynamic_cast(sender()) ; + if (!action) { + return; + } + + QString id = action->data().toString(); + if (id.isEmpty()) { + return; + } + + QList selectedItems = ui->msgTreeWidget->selectedItems(); + if (selectedItems.size() != 1) { + return; + } + + std::string msgId = selectedItems[0]->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString(); + FeedMsgInfo msgInfo; + if (!mFeedReader->getMsgInfo(mFeedId, msgId, msgInfo)) { + return; + } + + RsGxsGroupId forumId(id.toStdString()); + + CreateGxsForumMsg *msgDialog = new CreateGxsForumMsg(forumId, RsGxsMessageId(), RsGxsMessageId(), RsGxsId()) ; + msgDialog->setSubject(QString::fromUtf8(msgInfo.title.c_str())); + msgDialog->insertPastedText(QString::fromUtf8(msgInfo.description.c_str())); + msgDialog->show(); +} + +void FeedReaderMessageWidget::addToPosted() +{ + QAction *action = dynamic_cast(sender()) ; + if (!action) { + return; + } + + QString id = action->data().toString(); + if (id.isEmpty()) { + return; + } + + QList selectedItems = ui->msgTreeWidget->selectedItems(); + if (selectedItems.size() != 1) { + return; + } + + std::string msgId = selectedItems[0]->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString(); + FeedMsgInfo msgInfo; + if (!mFeedReader->getMsgInfo(mFeedId, msgId, msgInfo)) { + return; + } + + RsGxsGroupId postedId(id.toStdString()); + + PostedCreatePostDialog *msgDialog = new PostedCreatePostDialog(mFeedReader->posted(), postedId); + msgDialog->setTitle(QString::fromUtf8(msgInfo.title.c_str())); + msgDialog->setNotes(QString::fromUtf8(msgInfo.description.c_str())); + msgDialog->setLink(QString::fromUtf8(msgInfo.link.c_str())); + msgDialog->show(); +} + +void FeedReaderMessageWidget::attachmentCopyLinkLocation() +{ + QAction *action = dynamic_cast(sender()) ; + if (!action) { + return; + } + + QVariant data = action->data(); + if (!data.isValid()) { + return; + } + + if (data.type() != QVariant::String) { + return; + } + + QApplication::clipboard()->setText(data.toString()); +} diff --git a/plugins/FeedReader/gui/FeedReaderMessageWidget.h b/plugins/FeedReader/gui/FeedReaderMessageWidget.h index 452c407ad..40f16e29f 100644 --- a/plugins/FeedReader/gui/FeedReaderMessageWidget.h +++ b/plugins/FeedReader/gui/FeedReaderMessageWidget.h @@ -24,6 +24,7 @@ #include #include "interface/rsFeedReader.h" +#include "util/FontSizeHandler.h" namespace Ui { class FeedReaderMessageWidget; @@ -73,6 +74,11 @@ private slots: void openLinkMsg(); void copyLinkMsg(); void retransformMsg(); + void fillForumMenu(); + void fillPostedMenu(); + void addToForum(); + void addToPosted(); + void attachmentCopyLinkLocation(); /* FeedReaderNotify */ void feedChanged(uint32_t feedId, int type); @@ -88,6 +94,7 @@ private: void filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn); void filterItem(QTreeWidgetItem *item); void toggleMsgText_internal(); + void clearMessage(); bool mProcessSettings; RSTreeWidgetItemCompareRole *mMsgCompareRole; @@ -101,6 +108,8 @@ private: RsFeedReader *mFeedReader; FeedReaderNotify *mNotify; + FontSizeHandler mFontSizeHandler; + Ui::FeedReaderMessageWidget *ui; }; diff --git a/plugins/FeedReader/gui/FeedReaderMessageWidget.ui b/plugins/FeedReader/gui/FeedReaderMessageWidget.ui index 3542c5375..fada5279e 100644 --- a/plugins/FeedReader/gui/FeedReaderMessageWidget.ui +++ b/plugins/FeedReader/gui/FeedReaderMessageWidget.ui @@ -182,7 +182,7 @@ - + :/images/message-state-header.png:/images/message-state-header.png @@ -245,7 +245,7 @@ - + :/images/edit_remove24.png:/images/edit_remove24.png @@ -260,20 +260,63 @@
- - - - 0 - 10 - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - + + + + + + + 0 + 10 + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Qt::Horizontal + + + + + + + pictureLabel + + + Qt::AlignCenter + + + + + + + + + 0 + 10 + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + Copy Link Location + + @@ -297,10 +340,14 @@
gui/common/ElidedLabel.h
1
+ + AspectRatioPixmapLabel + QLabel +
util/AspectRatioPixmapLabel.h
+
- diff --git a/plugins/FeedReader/gui/FeedReaderNotify.cpp b/plugins/FeedReader/gui/FeedReaderNotify.cpp index f2aa7ad1d..95728b225 100644 --- a/plugins/FeedReader/gui/FeedReaderNotify.cpp +++ b/plugins/FeedReader/gui/FeedReaderNotify.cpp @@ -33,3 +33,8 @@ void FeedReaderNotify::notifyMsgChanged(uint32_t feedId, const std::string &msgI { emit msgChanged(feedId, QString::fromStdString(msgId), type); } + +void FeedReaderNotify::notifyOptimizeImage() +{ + emit optimizeImage(); +} diff --git a/plugins/FeedReader/gui/FeedReaderNotify.h b/plugins/FeedReader/gui/FeedReaderNotify.h index 5a8ad712a..5913f1985 100644 --- a/plugins/FeedReader/gui/FeedReaderNotify.h +++ b/plugins/FeedReader/gui/FeedReaderNotify.h @@ -34,10 +34,12 @@ public: /* RsFeedReaderNotify */ virtual void notifyFeedChanged(uint32_t feedId, int type); virtual void notifyMsgChanged(uint32_t feedId, const std::string &msgId, int type); + virtual void notifyOptimizeImage(); signals: void feedChanged(uint32_t feedId, int type); void msgChanged(uint32_t feedId, const QString &msgId, int type); + void optimizeImage(); }; #endif diff --git a/plugins/FeedReader/gui/FeedReaderStringDefs.cpp b/plugins/FeedReader/gui/FeedReaderStringDefs.cpp index 99c537498..53a62e669 100644 --- a/plugins/FeedReader/gui/FeedReaderStringDefs.cpp +++ b/plugins/FeedReader/gui/FeedReaderStringDefs.cpp @@ -23,27 +23,27 @@ #include "FeedReaderStringDefs.h" -bool FeedReaderStringDefs::showError(QWidget *parent, RsFeedAddResult result, const QString &title, const QString &text) +bool FeedReaderStringDefs::showError(QWidget *parent, RsFeedResult result, const QString &title, const QString &text) { QString error; switch (result) { - case RS_FEED_ADD_RESULT_SUCCESS: + case RS_FEED_RESULT_SUCCESS: /* no error */ return false; - case RS_FEED_ADD_RESULT_FEED_NOT_FOUND: + case RS_FEED_RESULT_FEED_NOT_FOUND: error = QApplication::translate("FeedReaderStringDefs", "Feed not found."); break; - case RS_FEED_ADD_RESULT_PARENT_NOT_FOUND: + case RS_FEED_RESULT_PARENT_NOT_FOUND: error = QApplication::translate("FeedReaderStringDefs", "Parent not found."); break; - case RS_FEED_ADD_RESULT_PARENT_IS_NO_FOLDER: + case RS_FEED_RESULT_PARENT_IS_NO_FOLDER: error = QApplication::translate("FeedReaderStringDefs", "Parent is no folder."); break; - case RS_FEED_ADD_RESULT_FEED_IS_FOLDER: + case RS_FEED_RESULT_FEED_IS_FOLDER: error = QApplication::translate("FeedReaderStringDefs", "Feed is a folder."); break; - case RS_FEED_ADD_RESULT_FEED_IS_NO_FOLDER: + case RS_FEED_RESULT_FEED_IS_NO_FOLDER: error = QApplication::translate("FeedReaderStringDefs", "Feed is no folder."); break; default: @@ -101,6 +101,9 @@ QString FeedReaderStringDefs::errorString(RsFeedReaderErrorState errorState, con case RS_FEED_ERRORSTATE_DOWNLOAD_UNKOWN_RESPONSE_CODE: errorText = QApplication::translate("FeedReaderStringDefs", "Unknown response code"); break; + case RS_FEED_ERRORSTATE_DOWNLOAD_BLOCKED: + errorText = QApplication::translate("FeedReaderStringDefs", "Download blocked"); + break; /* process */ case RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR: @@ -109,9 +112,9 @@ QString FeedReaderStringDefs::errorString(RsFeedReaderErrorState errorState, con case RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT: errorText = QApplication::translate("FeedReaderStringDefs", "Unknown XML format"); break; - case RS_FEED_ERRORSTATE_PROCESS_FORUM_CREATE: - errorText = QApplication::translate("FeedReaderStringDefs", "Can't create forum"); - break; +// case RS_FEED_ERRORSTATE_PROCESS_FORUM_CREATE: +// errorText = QApplication::translate("FeedReaderStringDefs", "Can't create forum"); +// break; case RS_FEED_ERRORSTATE_PROCESS_FORUM_NOT_FOUND: errorText = QApplication::translate("FeedReaderStringDefs", "Forum not found"); break; @@ -121,6 +124,21 @@ QString FeedReaderStringDefs::errorString(RsFeedReaderErrorState errorState, con case RS_FEED_ERRORSTATE_PROCESS_FORUM_NO_AUTHOR: errorText = QApplication::translate("FeedReaderStringDefs", "Forum has no author"); break; +// case RS_FEED_ERRORSTATE_PROCESS_POSTED_CREATE: +// errorText = QApplication::translate("FeedReaderStringDefs", "Can't create board"); +// break; + case RS_FEED_ERRORSTATE_PROCESS_POSTED_NOT_FOUND: + errorText = QApplication::translate("FeedReaderStringDefs", "Board not found"); + break; + case RS_FEED_ERRORSTATE_PROCESS_POSTED_NO_ADMIN: + errorText = QApplication::translate("FeedReaderStringDefs", "You are not admin of the board"); + break; + case RS_FEED_ERRORSTATE_PROCESS_POSTED_NO_AUTHOR: + errorText = QApplication::translate("FeedReaderStringDefs", "Board has no author"); + break; + case RS_FEED_ERRORSTATE_PROCESS_POST: + errorText = QApplication::translate("FeedReaderStringDefs", "Some posts could not be created"); + break; case RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR: errorText = QApplication::translate("FeedReaderStringDefs", "Can't read html"); diff --git a/plugins/FeedReader/gui/FeedReaderStringDefs.h b/plugins/FeedReader/gui/FeedReaderStringDefs.h index f4b384c8f..587621e7d 100644 --- a/plugins/FeedReader/gui/FeedReaderStringDefs.h +++ b/plugins/FeedReader/gui/FeedReaderStringDefs.h @@ -30,7 +30,7 @@ class QWidget; class FeedReaderStringDefs { public: - static bool showError(QWidget *parent, RsFeedAddResult result, const QString &title, const QString &text); + static bool showError(QWidget *parent, RsFeedResult result, const QString &title, const QString &text); static QString workState(FeedInfo::WorkState state); static QString errorString(const FeedInfo &feedInfo); static QString errorString(RsFeedReaderErrorState errorState, const std::string &errorString); diff --git a/plugins/FeedReader/gui/FeedTreeWidget.cpp b/plugins/FeedReader/gui/FeedTreeWidget.cpp new file mode 100644 index 000000000..37baaf235 --- /dev/null +++ b/plugins/FeedReader/gui/FeedTreeWidget.cpp @@ -0,0 +1,119 @@ +/******************************************************************************* + * plugins/FeedReader/gui/FeedTreeWidget.cpp * + * * + * Copyright (C) 2012 RetroShare Team * + * * + * 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 . * + * * + *******************************************************************************/ + +#include +#include "FeedTreeWidget.h" + +FeedTreeWidget::FeedTreeWidget(QWidget *parent) : RSTreeWidget(parent) +{ + mDraggedItem = NULL; +} + +void FeedTreeWidget::dragEnterEvent(QDragEnterEvent *event) +{ + mDraggedItem = currentItem(); + RSTreeWidget::dragEnterEvent(event); +} + +void FeedTreeWidget::dragLeaveEvent(QDragLeaveEvent *event) +{ + RSTreeWidget::dragLeaveEvent(event); + mDraggedItem = NULL; +} + +bool FeedTreeWidget::canDrop(QDropEvent *event, QTreeWidgetItem **dropItem) +{ + if (dropItem) { + *dropItem = NULL; + } + + if (!mDraggedItem) { + /* no drag item */ + return false; + } + + QModelIndex droppedIndex = indexAt(event->pos()); + if (!droppedIndex.isValid()) { + /* no drop target */ + return false; + } + + QTreeWidgetItem *dropItemIntern = itemFromIndex(droppedIndex); + if (!dropItemIntern) { + /* no drop item */ + return false; + } + + if ((dropItemIntern->flags() & Qt::ItemIsDropEnabled) == 0) { + /* drop is disabled */ + return false; + } + + if (dropItemIntern == mDraggedItem->parent()) { + /* drag item parent */ + return false; + } + + if (dropItem) { + *dropItem = dropItemIntern; + } + + return true; +} + +void FeedTreeWidget::dragMoveEvent(QDragMoveEvent *event) +{ + if (!canDrop(event)) { + event->ignore(); + return; + } + + RSTreeWidget::dragMoveEvent(event); +} + +void FeedTreeWidget::dropEvent(QDropEvent *event) +{ + QTreeWidgetItem *dropItem; + if (!canDrop(event, &dropItem)) { + event->ignore(); + return; + } + + if (!mDraggedItem) { + /* no drag item */ + event->ignore(); + return; + } + + QTreeWidgetItem *draggedParent = mDraggedItem->parent(); + if (!draggedParent) { + /* no drag item parent */ + event->ignore(); + return; + } + + if (!dropItem) { + /* no drop item */ + event->ignore(); + return; + } + + emit feedReparent(mDraggedItem, dropItem); +} diff --git a/retroshare-gui/src/gui/common/StyledLabel.h b/plugins/FeedReader/gui/FeedTreeWidget.h similarity index 66% rename from retroshare-gui/src/gui/common/StyledLabel.h rename to plugins/FeedReader/gui/FeedTreeWidget.h index faf0654da..e9eb197a9 100644 --- a/retroshare-gui/src/gui/common/StyledLabel.h +++ b/plugins/FeedReader/gui/FeedTreeWidget.h @@ -1,7 +1,7 @@ /******************************************************************************* - * gui/common/StyledLabel.h * + * plugins/FeedReader/gui/FeedTreeWidget.h * * * - * Copyright (c) 2014, RetroShare Team * + * Copyright (C) 2012 by Retroshare Team * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Affero General Public License as * @@ -18,25 +18,33 @@ * * *******************************************************************************/ -#ifndef _STYLEDLABEL_H -#define _STYLEDLABEL_H +#ifndef _FEEDTREEWIDGET_H +#define _FEEDTREEWIDGET_H -#include +#include "gui/common/RSTreeWidget.h" -class StyledLabel : public QLabel +/* Subclassing RSTreeWidget */ +class FeedTreeWidget : public RSTreeWidget { Q_OBJECT - Q_PROPERTY(int fontSizeFactor READ fontSizeFactor WRITE setFontSizeFactor) public: - StyledLabel(QWidget *parent = NULL); - StyledLabel(const QString &text, QWidget *parent = NULL); + FeedTreeWidget(QWidget *parent = 0); - int fontSizeFactor(); - void setFontSizeFactor(int factor); +Q_SIGNALS: + void feedReparent(QTreeWidgetItem *item, QTreeWidgetItem *newParent); + +protected: + void dragEnterEvent(QDragEnterEvent *event); + void dragLeaveEvent(QDragLeaveEvent *event); + void dragMoveEvent(QDragMoveEvent *event); + void dropEvent(QDropEvent *event); private: - int mFontSizeFactor; + bool canDrop(QDropEvent *event, QTreeWidgetItem **dropItem = NULL); + +private: + QTreeWidgetItem *mDraggedItem; }; #endif diff --git a/plugins/FeedReader/gui/PreviewFeedDialog.ui b/plugins/FeedReader/gui/PreviewFeedDialog.ui index 14868c082..41cebc153 100644 --- a/plugins/FeedReader/gui/PreviewFeedDialog.ui +++ b/plugins/FeedReader/gui/PreviewFeedDialog.ui @@ -7,7 +7,7 @@ 0 0 800 - 521 + 564 @@ -16,7 +16,7 @@ true - + 0 @@ -28,7 +28,7 @@ 0 - + 0 @@ -57,6 +57,14 @@ 0 + + + 11 + 75 + true + true + + Name: @@ -284,7 +292,7 @@ - + @@ -324,6 +332,14 @@ 0 + + + 11 + 75 + true + true + + Title: @@ -365,7 +381,7 @@ false - + 0 @@ -387,7 +403,7 @@ - + 0 @@ -451,7 +467,7 @@ QFrame::Raised - + 0 @@ -472,7 +488,7 @@ QFrame::Raised - + 0 @@ -499,7 +515,7 @@ QFrame::Raised - + 0 @@ -513,7 +529,7 @@ 0 - + @@ -572,11 +588,13 @@ - titleFrame - splitter - buttonBox + + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
RSPlainTextEdit QPlainTextEdit diff --git a/plugins/FeedReader/gui/ProxyWidget.cpp b/plugins/FeedReader/gui/ProxyWidget.cpp new file mode 100644 index 000000000..eeb0c5256 --- /dev/null +++ b/plugins/FeedReader/gui/ProxyWidget.cpp @@ -0,0 +1,142 @@ +#include "ProxyWidget.h" +#include "ui_ProxyWidget.h" + +ProxyWidget::ProxyWidget(QWidget *parent) + : QWidget(parent) + , ui(new Ui::ProxyWidget) +{ + ui->setupUi(this); + + /* Connect signals */ + connectUi(true); + connect(ui->portSpinBox, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, &ProxyWidget::changed); + + /* Initialize types */ + ui->schemeComboBox->addItem("", ""); + ui->schemeComboBox->addItem("HTTP", "http://"); + ui->schemeComboBox->setItemData(ui->schemeComboBox->count() - 1, tr("HTTP Proxy."), Qt::ToolTipRole); + ui->schemeComboBox->addItem("HTTPS", "https://"); + ui->schemeComboBox->setItemData(ui->schemeComboBox->count() - 1, tr("HTTPS Proxy."), Qt::ToolTipRole); + ui->schemeComboBox->addItem("SOCKS4", "socks4://"); + ui->schemeComboBox->setItemData(ui->schemeComboBox->count() - 1, tr("SOCKS4 Proxy."), Qt::ToolTipRole); + ui->schemeComboBox->addItem("SOCKS4a", "socks4a://"); + ui->schemeComboBox->setItemData(ui->schemeComboBox->count() - 1, tr("SOCKS4a Proxy. Proxy resolves URL hostname."), Qt::ToolTipRole); + ui->schemeComboBox->addItem("SOCKS5", "socks5://"); + ui->schemeComboBox->setItemData(ui->schemeComboBox->count() - 1, tr("SOCKS5 Proxy."), Qt::ToolTipRole); + ui->schemeComboBox->addItem("SOCKS5h", "socks5h://"); + ui->schemeComboBox->setItemData(ui->schemeComboBox->count() - 1, tr("SOCKS5 Proxy. Proxy resolves URL hostname."), Qt::ToolTipRole); +} + +ProxyWidget::~ProxyWidget() +{ + delete ui; +} + +void ProxyWidget::connectUi(bool doConnect) +{ + if (doConnect) { + if (!mAddressConnection) { + mAddressConnection = connect(ui->addressLineEdit, &QLineEdit::textChanged, this, &ProxyWidget::addressChanged); + } + if (!mSchemeConnection) { + mSchemeConnection = connect(ui->schemeComboBox, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, &ProxyWidget::changed); + } + } else { + if (mAddressConnection) { + disconnect(mAddressConnection); + } + if (mSchemeConnection) { + disconnect(mSchemeConnection); + } + } +} + +QString ProxyWidget::address() +{ + QString host = ui->addressLineEdit->text(); + if (host.isEmpty()) { + return ""; + } + + QString value; + + QString scheme = ui->schemeComboBox->currentData().toString(); + if (!scheme.isEmpty()) { + value = scheme; + } + + value += ui->addressLineEdit->text(); + + return value; +} + +void ProxyWidget::setAddress(const QString &value) +{ + int schemeIndex; + QString host; + + splitAddress(value, schemeIndex, host); + + connectUi(false); + ui->schemeComboBox->setCurrentIndex(schemeIndex); + ui->addressLineEdit->setText(host); + connectUi(true); +} + +int ProxyWidget::port() +{ + return ui->portSpinBox->value(); +} + +void ProxyWidget::setPort(int value) +{ + ui->portSpinBox->setValue(value); +} + +void ProxyWidget::addressChanged(const QString &value) +{ + int schemeIndex; + QString host; + + splitAddress(value, schemeIndex, host); + + connectUi(false); + ui->schemeComboBox->setCurrentIndex(schemeIndex); + if (host != ui->addressLineEdit->text()) { + ui->addressLineEdit->setText(host); + } + connectUi(true); + + emit changed(); +} + +void ProxyWidget::splitAddress(const QString &value, int &schemeIndex, QString &host) +{ + if (value.isEmpty()) { + schemeIndex = ui->schemeComboBox->currentIndex(); + host = value; + return; + } + + QString scheme; + int index = value.indexOf("://"); + if (index >= 0) { + scheme = value.left(index + 3); + host = value.mid(index + 3); + } else { + if (ui->schemeComboBox->currentIndex() == 0) { + // Default to HTTP + scheme = "http://"; + } else { + scheme = ui->schemeComboBox->currentData().toString(); + } + host = value; + } + + schemeIndex = ui->schemeComboBox->findData(scheme); + if (schemeIndex < 0) { + /* Unknown scheme */ + schemeIndex = 0; + host = value; + } +} diff --git a/plugins/FeedReader/gui/ProxyWidget.h b/plugins/FeedReader/gui/ProxyWidget.h new file mode 100644 index 000000000..d1fdac315 --- /dev/null +++ b/plugins/FeedReader/gui/ProxyWidget.h @@ -0,0 +1,40 @@ +#ifndef PROXYWIDGET_H +#define PROXYWIDGET_H + +#include + +namespace Ui { +class ProxyWidget; +} + +class ProxyWidget : public QWidget +{ + Q_OBJECT + +public: + explicit ProxyWidget(QWidget *parent = nullptr); + ~ProxyWidget(); + + QString address(); + void setAddress(const QString &value); + + int port(); + void setPort(int value); + +Q_SIGNALS: + void changed(); + +private Q_SLOTS: + void addressChanged(const QString &value); + +private: + void connectUi(bool doConnect); + void splitAddress(const QString &value, int &schemeIndex, QString &host); + +private: + Ui::ProxyWidget *ui; + QMetaObject::Connection mAddressConnection; + QMetaObject::Connection mSchemeConnection; +}; + +#endif // PROXYWIDGET_H diff --git a/plugins/FeedReader/gui/ProxyWidget.ui b/plugins/FeedReader/gui/ProxyWidget.ui new file mode 100644 index 000000000..0671cebc3 --- /dev/null +++ b/plugins/FeedReader/gui/ProxyWidget.ui @@ -0,0 +1,53 @@ + + + ProxyWidget + + + + 0 + 0 + 400 + 22 + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + : + + + + + + + 65535 + + + + + + + + diff --git a/plugins/FeedReader/interface/rsFeedReader.h b/plugins/FeedReader/interface/rsFeedReader.h index bf524ad0c..326d3e022 100644 --- a/plugins/FeedReader/interface/rsFeedReader.h +++ b/plugins/FeedReader/interface/rsFeedReader.h @@ -25,8 +25,13 @@ #include #include #include +#include class RsFeedReader; +class RsGxsForums; +class RsPosted; +class RsGxsForumGroup; +class RsPostedGroup; extern RsFeedReader *rsFeedReader; enum RsFeedReaderErrorState { @@ -38,14 +43,20 @@ enum RsFeedReaderErrorState { RS_FEED_ERRORSTATE_DOWNLOAD_UNKNOWN_CONTENT_TYPE = 3, RS_FEED_ERRORSTATE_DOWNLOAD_NOT_FOUND = 4, RS_FEED_ERRORSTATE_DOWNLOAD_UNKOWN_RESPONSE_CODE = 5, + RS_FEED_ERRORSTATE_DOWNLOAD_BLOCKED = 6, /* process */ RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR = 50, RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT = 51, - RS_FEED_ERRORSTATE_PROCESS_FORUM_CREATE = 100, +// RS_FEED_ERRORSTATE_PROCESS_FORUM_CREATE = 100, RS_FEED_ERRORSTATE_PROCESS_FORUM_NOT_FOUND = 101, RS_FEED_ERRORSTATE_PROCESS_FORUM_NO_ADMIN = 102, RS_FEED_ERRORSTATE_PROCESS_FORUM_NO_AUTHOR = 103, +// RS_FEED_ERRORSTATE_PROCESS_POSTED_CREATE = 104, + RS_FEED_ERRORSTATE_PROCESS_POSTED_NOT_FOUND = 105, + RS_FEED_ERRORSTATE_PROCESS_POSTED_NO_ADMIN = 106, + RS_FEED_ERRORSTATE_PROCESS_POSTED_NO_AUTHOR = 107, + RS_FEED_ERRORSTATE_PROCESS_POST = 108, RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR = 150, RS_FEED_ERRORSTATE_PROCESS_XPATH_INTERNAL_ERROR = 151, @@ -56,14 +67,14 @@ enum RsFeedReaderErrorState { RS_FEED_ERRORSTATE_PROCESS_XSLT_NO_RESULT = 156 }; -enum RsFeedAddResult +enum RsFeedResult { - RS_FEED_ADD_RESULT_SUCCESS, - RS_FEED_ADD_RESULT_FEED_NOT_FOUND, - RS_FEED_ADD_RESULT_PARENT_NOT_FOUND, - RS_FEED_ADD_RESULT_PARENT_IS_NO_FOLDER, - RS_FEED_ADD_RESULT_FEED_IS_FOLDER, - RS_FEED_ADD_RESULT_FEED_IS_NO_FOLDER + RS_FEED_RESULT_SUCCESS, + RS_FEED_RESULT_FEED_NOT_FOUND, + RS_FEED_RESULT_PARENT_NOT_FOUND, + RS_FEED_RESULT_PARENT_IS_NO_FOLDER, + RS_FEED_RESULT_FEED_IS_FOLDER, + RS_FEED_RESULT_FEED_IS_NO_FOLDER }; enum RsFeedTransformationType @@ -102,6 +113,8 @@ public: flag.deactivated = false; flag.forum = false; flag.updateForumInfo = false; + flag.posted = false; + flag.updatePostedInfo = false; flag.embedImages = false; flag.saveCompletePage = false; flag.preview = false; @@ -122,6 +135,7 @@ public: time_t lastUpdate; uint32_t storageTime; std::string forumId; + std::string postedId; WorkState workstate; RsFeedReaderErrorState errorState; std::string errorString; @@ -141,6 +155,11 @@ public: bool deactivated : 1; bool forum : 1; bool updateForumInfo : 1; + bool posted : 1; + bool updatePostedInfo : 1; + bool postedFirstImage : 1; + bool postedOnlyImage : 1; + bool postedShrinkImage : 1; bool embedImages : 1; bool saveCompletePage : 1; bool preview : 1; @@ -166,6 +185,9 @@ public: std::string description; std::string descriptionTransformed; time_t pubDate; + std::string attachmentLink; + std::vector attachment; + std::string attachmentMimeType; struct { bool isnew : 1; @@ -174,6 +196,32 @@ public: } flag; }; +class FeedReaderOptimizeImageTask +{ +public: + enum Type { + POSTED, + SIZE + }; + +public: + Type mType; + std::vector mImage; + std::string mMimeType; + std::vector mImageResult; + std::string mMimeTypeResult; + bool mResult; + +public: + FeedReaderOptimizeImageTask(Type type, const std::vector &image, const std::string &mimeType) + { + mType = type; + mImage = image; + mMimeType = mimeType; + mResult = false; + } +}; + class RsFeedReaderNotify { public: @@ -181,6 +229,7 @@ public: virtual void notifyFeedChanged(uint32_t /*feedId*/, int /*type*/) {} virtual void notifyMsgChanged(uint32_t /*feedId*/, const std::string &/*msgId*/, int /*type*/) {} + virtual void notifyOptimizeImage() {} }; class RsFeedReader @@ -201,24 +250,33 @@ public: virtual bool getSaveInBackground() = 0; virtual void setSaveInBackground(bool saveInBackground) = 0; - virtual RsFeedAddResult addFolder(uint32_t parentId, const std::string &name, uint32_t &feedId) = 0; - virtual RsFeedAddResult setFolder(uint32_t feedId, const std::string &name) = 0; - virtual RsFeedAddResult addFeed(const FeedInfo &feedInfo, uint32_t &feedId) = 0; - virtual RsFeedAddResult setFeed(uint32_t feedId, const FeedInfo &feedInfo) = 0; - virtual bool removeFeed(uint32_t feedId) = 0; - virtual bool addPreviewFeed(const FeedInfo &feedInfo, uint32_t &feedId) = 0; - virtual void getFeedList(uint32_t parentId, std::list &feedInfos) = 0; - virtual bool getFeedInfo(uint32_t feedId, FeedInfo &feedInfo) = 0; - virtual bool getMsgInfo(uint32_t feedId, const std::string &msgId, FeedMsgInfo &msgInfo) = 0; - virtual bool removeMsg(uint32_t feedId, const std::string &msgId) = 0; - virtual bool removeMsgs(uint32_t feedId, const std::list &msgIds) = 0; - virtual bool getMessageCount(uint32_t feedId, uint32_t *msgCount, uint32_t *newCount, uint32_t *unreadCount) = 0; - virtual bool getFeedMsgList(uint32_t feedId, std::list &msgInfos) = 0; - virtual bool getFeedMsgIdList(uint32_t feedId, std::list &msgIds) = 0; - virtual bool processFeed(uint32_t feedId) = 0; - virtual bool setMessageRead(uint32_t feedId, const std::string &msgId, bool read) = 0; - virtual bool retransformMsg(uint32_t feedId, const std::string &msgId) = 0; - virtual bool clearMessageCache(uint32_t feedId) = 0; + virtual RsFeedResult addFolder(uint32_t parentId, const std::string &name, uint32_t &feedId) = 0; + virtual RsFeedResult setFolder(uint32_t feedId, const std::string &name) = 0; + virtual RsFeedResult addFeed(const FeedInfo &feedInfo, uint32_t &feedId) = 0; + virtual RsFeedResult setFeed(uint32_t feedId, const FeedInfo &feedInfo) = 0; + virtual RsFeedResult setParent(uint32_t feedId, uint32_t parentId) = 0; + virtual bool removeFeed(uint32_t feedId) = 0; + virtual bool addPreviewFeed(const FeedInfo &feedInfo, uint32_t &feedId) = 0; + virtual void getFeedList(uint32_t parentId, std::list &feedInfos) = 0; + virtual bool getFeedInfo(uint32_t feedId, FeedInfo &feedInfo) = 0; + virtual bool getMsgInfo(uint32_t feedId, const std::string &msgId, FeedMsgInfo &msgInfo) = 0; + virtual bool removeMsg(uint32_t feedId, const std::string &msgId) = 0; + virtual bool removeMsgs(uint32_t feedId, const std::list &msgIds) = 0; + virtual bool getMessageCount(uint32_t feedId, uint32_t *msgCount, uint32_t *newCount, uint32_t *unreadCount) = 0; + virtual bool getFeedMsgList(uint32_t feedId, std::list &msgInfos) = 0; + virtual bool getFeedMsgIdList(uint32_t feedId, std::list &msgIds) = 0; + virtual bool processFeed(uint32_t feedId) = 0; + virtual bool setMessageRead(uint32_t feedId, const std::string &msgId, bool read) = 0; + virtual bool retransformMsg(uint32_t feedId, const std::string &msgId) = 0; + virtual bool clearMessageCache(uint32_t feedId) = 0; + + virtual RsGxsForums* forums() = 0; + virtual RsPosted* posted() = 0; + virtual bool getForumGroups(std::vector &groups, bool onlyOwn) = 0; + virtual bool getPostedGroups(std::vector &groups, bool onlyOwn) = 0; + + virtual FeedReaderOptimizeImageTask *getOptimizeImageTask() = 0; + virtual void setOptimizeImageTaskResult(FeedReaderOptimizeImageTask *optimizeImageTask) = 0; virtual RsFeedReaderErrorState processXPath(const std::list &xpathsToUse, const std::list &xpathsToRemove, std::string &description, std::string &errorString) = 0; virtual RsFeedReaderErrorState processXslt(const std::string &xslt, std::string &description, std::string &errorString) = 0; diff --git a/plugins/FeedReader/lang/FeedReader_en.ts b/plugins/FeedReader/lang/FeedReader_en.ts index 89cde2fe0..2fea9589e 100644 --- a/plugins/FeedReader/lang/FeedReader_en.ts +++ b/plugins/FeedReader/lang/FeedReader_en.ts @@ -9,7 +9,32 @@ - + + Board + + + + + Update board information + + + + + Only image + + + + + Use first image as board image + + + + + Shrink image + + + + Authentication (not yet supported) @@ -34,7 +59,7 @@ - + Update interval @@ -59,12 +84,12 @@ - + Embed images - + Storage time @@ -89,32 +114,22 @@ - - Server - - - - - : - - - - + Type - + Forum - + Local Feed - + Transformation @@ -129,7 +144,7 @@ - + Misc @@ -144,17 +159,17 @@ - + Update forum information - + Save complete web page (experimental for local feeds) - + Description: @@ -164,18 +179,18 @@ - + Name: - + Feed Details - - + + Edit feed @@ -239,17 +254,7 @@ - - Server - - - - - : - - - - + Misc @@ -277,7 +282,7 @@ FeedReaderDialog - + Feeds @@ -292,12 +297,12 @@ - + Message Folders - + New @@ -342,12 +347,12 @@ - + No name - + Add new folder @@ -398,11 +403,21 @@ Please enter a new name for the folder + + + Move feed + + + + + Cannot move feed. + + FeedReaderFeedItem - + Expand @@ -500,7 +515,7 @@ - + Title @@ -516,6 +531,11 @@ Author + + + Copy Link Location + + Search Title @@ -532,7 +552,7 @@ - + Open link in browser @@ -542,12 +562,22 @@ - + The messages will be added to the forum - + + The messages will be added to the forum and the board + + + + + The messages will be added to the board + + + + No name @@ -576,13 +606,23 @@ Remove + + + Add to forum + + + Add to board + + + + Retransform - + Hide @@ -659,12 +699,12 @@ - + Unknown - + Internal download error @@ -688,6 +728,11 @@ Unknown response code + + + Download blocked + + Internal process error @@ -699,12 +744,7 @@ - - Can't create forum - - - - + Forum not found @@ -718,6 +758,26 @@ Forum has no author + + + Board not found + + + + + You are not admin of the board + + + + + Board has no author + + + + + Some posts could not be created + + Can't read html @@ -790,7 +850,7 @@ - + Name: @@ -825,7 +885,7 @@ - + Title: @@ -882,4 +942,37 @@ + + ProxyWidget + + + HTTP Proxy. + + + + + HTTPS Proxy. + + + + + SOCKS4 Proxy. + + + + + SOCKS4a Proxy. Proxy resolves URL hostname. + + + + + SOCKS5 Proxy. + + + + + SOCKS5 Proxy. Proxy resolves URL hostname. + + + diff --git a/plugins/VOIP/qss/VOIP_qss.default b/plugins/FeedReader/qss/FeedReader_default.qss similarity index 52% rename from plugins/VOIP/qss/VOIP_qss.default rename to plugins/FeedReader/qss/FeedReader_default.qss index abe80ad93..9b964468c 100644 --- a/plugins/VOIP/qss/VOIP_qss.default +++ b/plugins/FeedReader/qss/FeedReader_default.qss @@ -1,9 +1,3 @@ /* Default stylesheet This file is used as default for all stylesheets and can be overloaded */ -/* Font */ - -VOIPToasterItem QLabel#textLabel -{ - qproperty-fontSizeFactor: 115; -} diff --git a/plugins/FeedReader/qss/FeedReader_qss.qrc b/plugins/FeedReader/qss/FeedReader_qss.qrc index 437503d74..adefd6b1b 100644 --- a/plugins/FeedReader/qss/FeedReader_qss.qrc +++ b/plugins/FeedReader/qss/FeedReader_qss.qrc @@ -1,6 +1,6 @@ - FeedReader_qss.default + FeedReader_default.qss FeedReader_Standard.qss diff --git a/plugins/FeedReader/services/p3FeedReader.cc b/plugins/FeedReader/services/p3FeedReader.cc index d70591c36..3e46a027c 100644 --- a/plugins/FeedReader/services/p3FeedReader.cc +++ b/plugins/FeedReader/services/p3FeedReader.cc @@ -24,6 +24,7 @@ #include "rsitems/rsconfigitems.h" #include "retroshare/rsiface.h" #include "retroshare/rsgxsforums.h" +#include "retroshare/rsposted.h" #include "util/rsstring.h" #include "util/rstime.h" #include "gxs/rsgenexchange.h" @@ -34,6 +35,7 @@ RsFeedReader *rsFeedReader = NULL; #define FEEDREADER_CLEAN_INTERVAL 1 * 60 * 60 // check every hour #define FEEDREADER_FORUM_PREFIX "RSS: " +#define FEEDREADER_POSTED_PREFIX "RSS: " #define MAX_REQUEST_AGE 30 // 30 seconds @@ -41,9 +43,9 @@ RsFeedReader *rsFeedReader = NULL; * #define FEEDREADER_DEBUG *********/ -p3FeedReader::p3FeedReader(RsPluginHandler* pgHandler, RsGxsForums *forums) +p3FeedReader::p3FeedReader(RsPluginHandler* pgHandler, RsGxsForums *forums, RsPosted *posted) : RsPQIService(RS_SERVICE_TYPE_PLUGIN_FEEDREADER, 5, pgHandler), - mFeedReaderMtx("p3FeedReader"), mDownloadMutex("p3FeedReaderDownload"), mProcessMutex("p3FeedReaderProcess"), mPreviewMutex("p3FeedReaderPreview") + mFeedReaderMtx("p3FeedReader"), mDownloadMutex("p3FeedReaderDownload"), mProcessMutex("p3FeedReaderProcess"), mImageMutex("p3FeedReaderImage"), mPreviewMutex("p3FeedReaderPreview") { mNextFeedId = 1; mNextMsgId = 1; @@ -55,6 +57,7 @@ p3FeedReader::p3FeedReader(RsPluginHandler* pgHandler, RsGxsForums *forums) mStandardProxyPort = 0; mLastClean = 0; mForums = forums; + mPosted = posted; mNotify = NULL; mSaveInBackground = false; mStopped = false; @@ -92,6 +95,7 @@ static void feedToInfo(const RsFeedReaderFeed *feed, FeedInfo &info) info.updateInterval = feed->updateInterval; info.lastUpdate = feed->lastUpdate; info.forumId = feed->forumId; + info.postedId = feed->postedId; info.storageTime = feed->storageTime; info.errorState = feed->errorState; info.errorString = feed->errorString; @@ -110,6 +114,11 @@ static void feedToInfo(const RsFeedReaderFeed *feed, FeedInfo &info) info.flag.deactivated = (feed->flag & RS_FEED_FLAG_DEACTIVATED); info.flag.forum = (feed->flag & RS_FEED_FLAG_FORUM); info.flag.updateForumInfo = (feed->flag & RS_FEED_FLAG_UPDATE_FORUM_INFO); + info.flag.posted = (feed->flag & RS_FEED_FLAG_POSTED); + info.flag.updatePostedInfo = (feed->flag & RS_FEED_FLAG_UPDATE_POSTED_INFO); + info.flag.postedFirstImage = (feed->flag & RS_FEED_FLAG_POSTED_FIRST_IMAGE); + info.flag.postedOnlyImage = (feed->flag & RS_FEED_FLAG_POSTED_ONLY_IMAGE); + info.flag.postedShrinkImage = (feed->flag & RS_FEED_FLAG_POSTED_SHRINK_IMAGE); info.flag.embedImages = (feed->flag & RS_FEED_FLAG_EMBED_IMAGES); info.flag.saveCompletePage = (feed->flag & RS_FEED_FLAG_SAVE_COMPLETE_PAGE); @@ -151,6 +160,7 @@ static void infoToFeed(const FeedInfo &info, RsFeedReaderFeed *feed) feed->storageTime = info.storageTime; feed->forumId = info.forumId; + feed->postedId = info.postedId; feed->transformationType = info.transformationType; feed->xpathsToUse.ids = info.xpathsToUse; @@ -193,6 +203,24 @@ static void infoToFeed(const FeedInfo &info, RsFeedReaderFeed *feed) if (info.flag.updateForumInfo) { feed->flag |= RS_FEED_FLAG_UPDATE_FORUM_INFO; } + if (info.flag.posted) { + feed->flag |= RS_FEED_FLAG_POSTED; + } + if (info.flag.updatePostedInfo) { + feed->flag |= RS_FEED_FLAG_UPDATE_POSTED_INFO; + } + if (info.flag.updatePostedInfo) { + feed->flag |= RS_FEED_FLAG_UPDATE_POSTED_INFO; + } + if (info.flag.postedFirstImage) { + feed->flag |= RS_FEED_FLAG_POSTED_FIRST_IMAGE; + } + if (info.flag.postedOnlyImage) { + feed->flag |= RS_FEED_FLAG_POSTED_ONLY_IMAGE; + } + if (info.flag.postedShrinkImage) { + feed->flag |= RS_FEED_FLAG_POSTED_SHRINK_IMAGE; + } } static void feedMsgToInfo(const RsFeedReaderMsg *msg, FeedMsgInfo &info) @@ -205,6 +233,13 @@ static void feedMsgToInfo(const RsFeedReaderMsg *msg, FeedMsgInfo &info) info.description = msg->description; info.descriptionTransformed = msg->descriptionTransformed; info.pubDate = msg->pubDate; + info.attachmentLink = msg->attachmentLink; + if (!msg->attachment.empty()) { + p3FeedReaderThread::fromBase64(msg->attachment, info.attachment); + } else { + info.attachment.clear(); + } + info.attachmentMimeType = msg->attachmentMimeType; info.flag.isnew = (msg->flag & RS_FEEDMSG_FLAG_NEW); info.flag.read = (msg->flag & RS_FEEDMSG_FLAG_READ); @@ -245,7 +280,7 @@ void p3FeedReader::setStandardStorageTime(uint32_t storageTime) if (mStandardStorageTime != storageTime) { mStandardStorageTime = storageTime; - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); } } @@ -262,7 +297,7 @@ void p3FeedReader::setStandardUpdateInterval(uint32_t updateInterval) if (mStandardUpdateInterval != updateInterval) { mStandardUpdateInterval = updateInterval; - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); } } @@ -284,7 +319,7 @@ void p3FeedReader::setStandardProxy(bool useProxy, const std::string &proxyAddre mStandardProxyAddress = proxyAddress; mStandardProxyPort = proxyPort; mStandardUseProxy = useProxy; - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); } } @@ -301,7 +336,7 @@ void p3FeedReader::setSaveInBackground(bool saveInBackground) if (saveInBackground != mSaveInBackground) { mSaveInBackground = saveInBackground; - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); } } @@ -342,7 +377,7 @@ void p3FeedReader::stopPreviewThreads_locked() } } -RsFeedAddResult p3FeedReader::addFolder(uint32_t parentId, const std::string &name, uint32_t &feedId) +RsFeedResult p3FeedReader::addFolder(uint32_t parentId, const std::string &name, uint32_t &feedId) { feedId = 0; @@ -356,14 +391,14 @@ RsFeedAddResult p3FeedReader::addFolder(uint32_t parentId, const std::string &na #ifdef FEEDREADER_DEBUG std::cerr << "p3FeedReader::addFolder - parent id " << parentId << " not found" << std::endl; #endif - return RS_FEED_ADD_RESULT_PARENT_NOT_FOUND; + return RS_FEED_RESULT_PARENT_NOT_FOUND; } if ((parentIt->second->flag & RS_FEED_FLAG_FOLDER) == 0) { #ifdef FEEDREADER_DEBUG std::cerr << "p3FeedReader::addFolder - parent " << parentIt->second->name << " is no folder" << std::endl; #endif - return RS_FEED_ADD_RESULT_PARENT_IS_NO_FOLDER; + return RS_FEED_RESULT_PARENT_IS_NO_FOLDER; } } @@ -377,16 +412,16 @@ RsFeedAddResult p3FeedReader::addFolder(uint32_t parentId, const std::string &na feedId = fi->feedId; } - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); if (mNotify) { mNotify->notifyFeedChanged(feedId, NOTIFY_TYPE_ADD); } - return RS_FEED_ADD_RESULT_SUCCESS; + return RS_FEED_RESULT_SUCCESS; } -RsFeedAddResult p3FeedReader::setFolder(uint32_t feedId, const std::string &name) +RsFeedResult p3FeedReader::setFolder(uint32_t feedId, const std::string &name) { { RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ @@ -400,33 +435,33 @@ RsFeedAddResult p3FeedReader::setFolder(uint32_t feedId, const std::string &name #ifdef FEEDREADER_DEBUG std::cerr << "p3FeedReader::setFolder - feed id " << feedId << " not found" << std::endl; #endif - return RS_FEED_ADD_RESULT_FEED_NOT_FOUND; + return RS_FEED_RESULT_FEED_NOT_FOUND; } if ((feedIt->second->flag & RS_FEED_FLAG_FOLDER) == 0) { #ifdef FEEDREADER_DEBUG std::cerr << "p3FeedReader::setFolder - feed " << feedIt->second->name << " is no folder" << std::endl; #endif - return RS_FEED_ADD_RESULT_FEED_IS_NO_FOLDER; + return RS_FEED_RESULT_FEED_IS_NO_FOLDER; } RsFeedReaderFeed *fi = feedIt->second; if (fi->name == name) { - return RS_FEED_ADD_RESULT_SUCCESS; + return RS_FEED_RESULT_SUCCESS; } fi->name = name; } - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); if (mNotify) { mNotify->notifyFeedChanged(feedId, NOTIFY_TYPE_MOD); } - return RS_FEED_ADD_RESULT_SUCCESS; + return RS_FEED_RESULT_SUCCESS; } -RsFeedAddResult p3FeedReader::addFeed(const FeedInfo &feedInfo, uint32_t &feedId) +RsFeedResult p3FeedReader::addFeed(const FeedInfo &feedInfo, uint32_t &feedId) { feedId = 0; @@ -444,14 +479,14 @@ RsFeedAddResult p3FeedReader::addFeed(const FeedInfo &feedInfo, uint32_t &feedId #ifdef FEEDREADER_DEBUG std::cerr << "p3FeedReader::addFeed - parent id " << feedInfo.parentId << " not found" << std::endl; #endif - return RS_FEED_ADD_RESULT_PARENT_NOT_FOUND; + return RS_FEED_RESULT_PARENT_NOT_FOUND; } if ((parentIt->second->flag & RS_FEED_FLAG_FOLDER) == 0) { #ifdef FEEDREADER_DEBUG std::cerr << "p3FeedReader::addFeed - parent " << parentIt->second->name << " is no folder" << std::endl; #endif - return RS_FEED_ADD_RESULT_PARENT_IS_NO_FOLDER; + return RS_FEED_RESULT_PARENT_IS_NO_FOLDER; } } @@ -464,20 +499,23 @@ RsFeedAddResult p3FeedReader::addFeed(const FeedInfo &feedInfo, uint32_t &feedId feedId = fi->feedId; } - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); if (mNotify) { mNotify->notifyFeedChanged(feedId, NOTIFY_TYPE_ADD); } - return RS_FEED_ADD_RESULT_SUCCESS; + return RS_FEED_RESULT_SUCCESS; } -RsFeedAddResult p3FeedReader::setFeed(uint32_t feedId, const FeedInfo &feedInfo) +RsFeedResult p3FeedReader::setFeed(uint32_t feedId, const FeedInfo &feedInfo) { std::string forumId; std::string forumName; std::string forumDescription; + std::string postedId; + std::string postedName; + std::string postedDescription; { RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ @@ -491,14 +529,14 @@ RsFeedAddResult p3FeedReader::setFeed(uint32_t feedId, const FeedInfo &feedInfo) #ifdef FEEDREADER_DEBUG std::cerr << "p3FeedReader::setFeed - feed id " << feedId << " not found" << std::endl; #endif - return RS_FEED_ADD_RESULT_FEED_NOT_FOUND; + return RS_FEED_RESULT_FEED_NOT_FOUND; } if (feedIt->second->flag & RS_FEED_FLAG_FOLDER) { #ifdef FEEDREADER_DEBUG std::cerr << "p3FeedReader::setFeed - feed " << feedIt->second->name << " is a folder" << std::endl; #endif - return RS_FEED_ADD_RESULT_FEED_IS_FOLDER; + return RS_FEED_RESULT_FEED_IS_FOLDER; } if (feedInfo.parentId) { @@ -508,19 +546,20 @@ RsFeedAddResult p3FeedReader::setFeed(uint32_t feedId, const FeedInfo &feedInfo) #ifdef FEEDREADER_DEBUG std::cerr << "p3FeedReader::setFeed - parent id " << feedInfo.parentId << " not found" << std::endl; #endif - return RS_FEED_ADD_RESULT_PARENT_NOT_FOUND; + return RS_FEED_RESULT_PARENT_NOT_FOUND; } if ((parentIt->second->flag & RS_FEED_FLAG_FOLDER) == 0) { #ifdef FEEDREADER_DEBUG std::cerr << "p3FeedReader::setFeed - parent " << parentIt->second->name << " is no folder" << std::endl; #endif - return RS_FEED_ADD_RESULT_PARENT_IS_NO_FOLDER; + return RS_FEED_RESULT_PARENT_IS_NO_FOLDER; } } RsFeedReaderFeed *fi = feedIt->second; std::string oldForumId = fi->forumId; + std::string oldPostedId = fi->postedId; std::string oldName = fi->name; std::string oldDescription = fi->description; @@ -534,9 +573,18 @@ RsFeedAddResult p3FeedReader::setFeed(uint32_t feedId, const FeedInfo &feedInfo) forumDescription = fi->description; forumName.insert(0, FEEDREADER_FORUM_PREFIX); } + + if ((fi->flag & RS_FEED_FLAG_POSTED) && (fi->flag & RS_FEED_FLAG_UPDATE_POSTED_INFO) && !fi->postedId.empty() && + (fi->postedId != oldPostedId || fi->name != oldName || fi->description != oldDescription)) { + /* name or description changed, update posted */ + postedId = fi->postedId; + postedName = fi->name; + postedDescription = fi->description; + postedName.insert(0, FEEDREADER_POSTED_PREFIX); + } } - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); if (mNotify) { mNotify->notifyFeedChanged(feedId, NOTIFY_TYPE_MOD); @@ -550,7 +598,71 @@ RsFeedAddResult p3FeedReader::setFeed(uint32_t feedId, const FeedInfo &feedInfo) //TODO: error } - return RS_FEED_ADD_RESULT_SUCCESS; + if (!postedId.empty()) { + RsPostedGroup postedGroup; + if (getPostedGroup(RsGxsGroupId(postedId), postedGroup)) { + updatePostedGroup(postedGroup, postedName, postedDescription); + } + //TODO: error + } + + return RS_FEED_RESULT_SUCCESS; +} + +RsFeedResult p3FeedReader::setParent(uint32_t feedId, uint32_t parentId) +{ + bool changed = false; + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setParent - set parent " << parentId << std::endl; +#endif + + std::map::iterator feedIt = mFeeds.find(feedId); + if (feedIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setParent - feed id " << feedId << " not found" << std::endl; +#endif + return RS_FEED_RESULT_FEED_NOT_FOUND; + } + + if (parentId) { + /* check parent id */ + std::map::iterator parentIt = mFeeds.find(parentId); + if (parentIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setParent - parent id " << parentId << " not found" << std::endl; +#endif + return RS_FEED_RESULT_PARENT_NOT_FOUND; + } + + if ((parentIt->second->flag & RS_FEED_FLAG_FOLDER) == 0) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setParent - parent " << parentIt->second->name << " is no folder" << std::endl; +#endif + return RS_FEED_RESULT_PARENT_IS_NO_FOLDER; + } + } + + RsFeedReaderFeed *fi = feedIt->second; + + if (fi->parentId != parentId) { + fi->parentId = parentId; + changed = true; + } + } + + if (changed) { + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); + + if (mNotify) { + mNotify->notifyFeedChanged(feedId, NOTIFY_TYPE_MOD); + } + } + + return RS_FEED_RESULT_SUCCESS; } void p3FeedReader::deleteAllMsgs_locked(RsFeedReaderFeed *fi) @@ -628,7 +740,7 @@ bool p3FeedReader::removeFeed(uint32_t feedId) } if (changed) { - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); } if (preview) { @@ -682,6 +794,7 @@ bool p3FeedReader::addPreviewFeed(const FeedInfo &feedInfo, uint32_t &feedId) fi->updateInterval = 0; fi->lastUpdate = 0; fi->forumId.clear(); + fi->postedId.clear(); fi->storageTime = 0; mFeeds[fi->feedId] = fi; @@ -808,7 +921,7 @@ bool p3FeedReader::removeMsg(uint32_t feedId, const std::string &msgId) } if (changed) { - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); } if (mNotify) { @@ -860,7 +973,7 @@ bool p3FeedReader::removeMsgs(uint32_t feedId, const std::list &msg } if (changed) { - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); } if (mNotify && !removedMsgs.empty()) { @@ -1158,7 +1271,7 @@ bool p3FeedReader::setMessageRead(uint32_t feedId, const std::string &msgId, boo } if (changed) { - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_OFTEN); if (mNotify) { mNotify->notifyFeedChanged(feedId, NOTIFY_TYPE_MOD); mNotify->notifyMsgChanged(feedId, msgId, NOTIFY_TYPE_MOD); @@ -1212,7 +1325,7 @@ bool p3FeedReader::retransformMsg(uint32_t feedId, const std::string &msgId) } if (feedChanged || msgChanged) { - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); if (mNotify) { if (feedChanged) { mNotify->notifyFeedChanged(feedId, NOTIFY_TYPE_MOD); @@ -1266,7 +1379,7 @@ bool p3FeedReader::clearMessageCache(uint32_t feedId) } } - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); return true; } @@ -1343,10 +1456,21 @@ int p3FeedReader::tick() } } + // check images + bool imageToOptimze = false; + { + RsStackMutex stack(mImageMutex); /******* LOCK STACK MUTEX *********/ + + imageToOptimze = !mImages.empty(); + } + if (mNotify) { for (it = notifyIds.begin(); it != notifyIds.end(); ++it) { mNotify->notifyFeedChanged(*it, NOTIFY_TYPE_MOD); } + if (imageToOptimze) { + mNotify->notifyOptimizeImage(); + } } return 0; @@ -1397,7 +1521,7 @@ void p3FeedReader::cleanFeeds() mLastClean = currentTime; if (removedMsgIds.size()) { - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); if (mNotify) { std::list >::iterator it; @@ -1709,7 +1833,7 @@ void p3FeedReader::onDownloadSuccess(uint32_t feedId, const std::string &content fi->icon = icon; if (!preview) { - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); } } @@ -1760,7 +1884,7 @@ void p3FeedReader::onDownloadError(uint32_t feedId, RsFeedReaderErrorState resul #endif if (!fi->preview) { - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); } } @@ -1872,21 +1996,26 @@ void p3FeedReader::onProcessSuccess_filterMsg(uint32_t feedId, std::listerrorString.clear(); if (!fi->preview) { - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); } } } -void p3FeedReader::onProcessSuccess_addMsgs(uint32_t feedId, std::list &msgs, bool single) +void p3FeedReader::onProcessSuccess_addMsgs(uint32_t feedId, std::list &msgs) { #ifdef FEEDREADER_DEBUG std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - feed " << feedId << " got " << msgs.size() << " messages" << std::endl; #endif + RsFeedReaderErrorState errorState = RS_FEED_ERRORSTATE_OK; std::list addedMsgs; std::string forumId; - RsGxsId authorId; + RsGxsId forumAuthorId; std::list forumMsgs; + std::string postedId; + RsGxsId postedAuthorId; + std::list postedMsgs; + uint32_t feedFlag = 0; { RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ @@ -1903,7 +2032,8 @@ void p3FeedReader::onProcessSuccess_addMsgs(uint32_t feedId, std::listsecond; bool forum = (fi->flag & RS_FEED_FLAG_FORUM) && !fi->preview; - RsFeedReaderErrorState errorState = RS_FEED_ERRORSTATE_OK; + bool posted = (fi->flag & RS_FEED_FLAG_POSTED) && !fi->preview; + feedFlag = fi->flag; if (forum && !msgs.empty()) { if (mForums) { @@ -1913,9 +2043,9 @@ void p3FeedReader::onProcessSuccess_addMsgs(uint32_t feedId, std::listforumId), forumGroup)) { if (IS_GROUP_PUBLISHER(forumGroup.mMeta.mSubscribeFlags) && IS_GROUP_ADMIN(forumGroup.mMeta.mSubscribeFlags)) { forumId = fi->forumId; - authorId = forumGroup.mMeta.mAuthorId; + forumAuthorId = forumGroup.mMeta.mAuthorId; - if (authorId.isNull()) { + if (forumAuthorId.isNull()) { errorState = RS_FEED_ERRORSTATE_PROCESS_FORUM_NO_AUTHOR; } } else { @@ -1933,6 +2063,34 @@ void p3FeedReader::onProcessSuccess_addMsgs(uint32_t feedId, std::listpostedId.empty()) { + /* check posted */ + RsPostedGroup postedGroup; + if (getPostedGroup(RsGxsGroupId(fi->postedId), postedGroup)) { + if (IS_GROUP_PUBLISHER(postedGroup.mMeta.mSubscribeFlags) && IS_GROUP_ADMIN(postedGroup.mMeta.mSubscribeFlags)) { + postedId = fi->postedId; + postedAuthorId = postedGroup.mMeta.mAuthorId; + + if (postedAuthorId.isNull()) { + errorState = RS_FEED_ERRORSTATE_PROCESS_POSTED_NO_AUTHOR; + } + } else { + errorState = RS_FEED_ERRORSTATE_PROCESS_POSTED_NO_ADMIN; + } + } else { + errorState = RS_FEED_ERRORSTATE_PROCESS_POSTED_NOT_FOUND; + } + } else { + std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - posted id is empty (" << fi->name << ")" << std::endl; + errorState = RS_FEED_ERRORSTATE_PROCESS_POSTED_NOT_FOUND; + } + } else { + std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - can't process posted, member mPosted is not set" << std::endl; + } + } + /* process msgs */ if (errorState == RS_FEED_ERRORSTATE_OK) { /* process msgs */ @@ -1949,11 +2107,19 @@ void p3FeedReader::onProcessSuccess_addMsgs(uint32_t feedId, std::listmsgId, "%lu", mNextMsgId++); } - if (forum) { + if (forum || posted) { miNew->flag = RS_FEEDMSG_FLAG_DELETED; - forumMsgs.push_back(*miNew); + if (forum) { + forumMsgs.push_back(*miNew); + } + if (posted) { + postedMsgs.push_back(*miNew); + } miNew->description.clear(); miNew->descriptionTransformed.clear(); + miNew->attachmentLink.clear(); + miNew->attachment.clear(); + miNew->attachmentMimeType.clear(); } else { miNew->flag = RS_FEEDMSG_FLAG_NEW; addedMsgs.push_back(miNew->msgId); @@ -1969,60 +2135,190 @@ void p3FeedReader::onProcessSuccess_addMsgs(uint32_t feedId, std::listfeedId << " (" << fi->name << ") added " << newMsgs << "/" << msgs.size() << " messages" << std::endl; #endif } + } - if (!single) { - fi->workstate = RsFeedReaderFeed::WAITING; - fi->content.clear(); - fi->errorState = errorState; - fi->lastUpdate = time(NULL); + bool postError = false; + + if (errorState == RS_FEED_ERRORSTATE_OK) { + if (!forumId.empty() && !forumMsgs.empty()) { + if (mForums) { + /* a bit tricky */ + RsGenExchange *genExchange = dynamic_cast(mForums); + if (genExchange) { + /* add messages as forum messages */ + std::list::iterator msgIt; + for (msgIt = forumMsgs.begin(); msgIt != forumMsgs.end(); ++msgIt) { + RsFeedReaderMsg &mi = *msgIt; + + /* convert to forum messages */ + RsGxsForumMsg forumMsg; + forumMsg.mMeta.mGroupId = RsGxsGroupId(forumId); + forumMsg.mMeta.mMsgName = mi.title; + forumMsg.mMeta.mAuthorId = forumAuthorId; + + std::string description = mi.descriptionTransformed.empty() ? mi.description : mi.descriptionTransformed; + /* add link */ + if (!mi.link.empty()) { + description += "
" + mi.link + ""; + } + + if (!mi.attachmentBinary.empty()) { + if (p3FeedReaderThread::isContentType(mi.attachmentMimeType, "image/")) { + /* add attachement to description */ + + // optimize image + std::vector optimizedImage; + std::string optimizedMimeType; + if (optimizeImage(FeedReaderOptimizeImageTask::SIZE, mi.attachmentBinary, mi.attachmentBinaryMimeType, optimizedImage, optimizedMimeType)) { + std::string base64; + if (p3FeedReaderThread::toBase64(optimizedImage, base64)) { + std::string imageBase64; + rs_sprintf(imageBase64, "data:%s;base64,%s", optimizedMimeType.c_str(), base64.c_str()); + description += "
"; + } + } + } + } + + forumMsg.mMsg = description; + + uint32_t token; + if (mForums->createMsg(token, forumMsg) && waitForToken(mForums, token)) { + RsGxsGrpMsgIdPair msgPair; + if (mForums->acknowledgeMsg(token, msgPair)) { + /* set to new */ + genExchange->setMsgStatusFlags(token, msgPair, GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD, GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD); + } + } else { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - can't add forum message " << mi.title << " for feed " << forumId << std::endl; +#endif + postError = true; + } + } + } else { + std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - can't process forum, member mForums is not derived from RsGenExchange" << std::endl; + } + } else { + std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - can't process forum, member mForums is not set" << std::endl; + } } - if (!fi->preview) { - IndicateConfigChanged(); + if (!postedId.empty() && !postedMsgs.empty()) { + if (mPosted) { + /* a bit tricky */ + RsGenExchange *genExchange = dynamic_cast(mPosted); + if (genExchange) { + /* add messages as posted messages */ + std::list::iterator msgIt; + for (msgIt = postedMsgs.begin(); msgIt != postedMsgs.end(); ++msgIt) { + RsFeedReaderMsg &mi = *msgIt; + + /* convert to posted messages */ + RsPostedPost postedPost; + postedPost.mMeta.mGroupId = RsGxsGroupId(postedId); + postedPost.mMeta.mMsgName = mi.title; + postedPost.mMeta.mAuthorId = postedAuthorId; + postedPost.mLink = mi.link; + + std::string description; + if (feedFlag & RS_FEED_FLAG_POSTED_FIRST_IMAGE) { + if (!mi.postedFirstImage.empty()) { + /* use first image as image for posted and description without image as notes */ + if (feedFlag & RS_FEED_FLAG_POSTED_SHRINK_IMAGE) { + // optimize image + std::vector optimizedImage; + std::string optimizedMimeType; + if (optimizeImage(FeedReaderOptimizeImageTask::POSTED, mi.postedFirstImage, mi.postedFirstImageMimeType, optimizedImage, optimizedMimeType)) { + postedPost.mImage.copy(optimizedImage.data(), optimizedImage.size()); + } + } else { + postedPost.mImage.copy(mi.postedFirstImage.data(), mi.postedFirstImage.size()); + } + if (feedFlag & RS_FEED_FLAG_POSTED_ONLY_IMAGE) { + /* ignore description */ + } else { + description = mi.postedDescriptionWithoutFirstImage; + } + } else { + if (feedFlag & RS_FEED_FLAG_POSTED_ONLY_IMAGE) { + /* ignore messages without image */ + continue; + } + description = mi.descriptionTransformed.empty() ? mi.description : mi.descriptionTransformed; + } + } else { + description = mi.descriptionTransformed.empty() ? mi.description : mi.descriptionTransformed; + + if (!mi.attachmentBinary.empty()) { + if (p3FeedReaderThread::isContentType(mi.attachmentMimeType, "image/")) { + /* use attachement as image */ + + if (feedFlag & RS_FEED_FLAG_POSTED_SHRINK_IMAGE) { + // optimize image + std::vector optimizedImage; + std::string optimizedMimeType; + if (optimizeImage(FeedReaderOptimizeImageTask::POSTED, mi.attachmentBinary, mi.attachmentBinaryMimeType, optimizedImage, optimizedMimeType)) { + postedPost.mImage.copy(optimizedImage.data(), optimizedImage.size()); + } + } else { + postedPost.mImage.copy(mi.attachmentBinary.data(), mi.attachmentBinary.size()); + } + } + } + } + + postedPost.mNotes = description; + + uint32_t token; + if (mPosted->createPost(token, postedPost) && waitForToken(mPosted, token)) { + RsGxsGrpMsgIdPair msgPair; + if (mPosted->acknowledgeMsg(token, msgPair)) { + /* set to new */ + genExchange->setMsgStatusFlags(token, msgPair, GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD, GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD); + } + } else { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - can't add posted message " << mi.title << " for feed " << postedId << std::endl; +#endif + postError = true; + } + } + } else { + std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - can't process posted, member mPosted is not derived from RsGenExchange" << std::endl; + } + } else { + std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - can't process posted, member mPosted is not set" << std::endl; + } } } - if (!forumId.empty() && !forumMsgs.empty()) { - if (mForums) { - /* a bit tricky */ - RsGenExchange *genExchange = dynamic_cast(mForums); - if (genExchange) { - /* add messages as forum messages */ - std::list::iterator msgIt; - for (msgIt = forumMsgs.begin(); msgIt != forumMsgs.end(); ++msgIt) { - RsFeedReaderMsg &mi = *msgIt; + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ - /* convert to forum messages */ - RsGxsForumMsg forumMsg; - forumMsg.mMeta.mGroupId = RsGxsGroupId(forumId); - forumMsg.mMeta.mMsgName = mi.title; - forumMsg.mMeta.mAuthorId = authorId; - - std::string description = mi.descriptionTransformed.empty() ? mi.description : mi.descriptionTransformed; - /* add link */ - if (!mi.link.empty()) { - description += "
" + mi.link + ""; - } - forumMsg.mMsg = description; - - uint32_t token; - if (mForums->createMsg(token, forumMsg) && waitForToken(token)) { - RsGxsGrpMsgIdPair msgPair; - if (mForums->acknowledgeMsg(token, msgPair)) { - /* set to new */ - genExchange->setMsgStatusFlags(token, msgPair, GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD, GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD); - } - } else { + /* find feed */ + std::map::iterator it = mFeeds.find(feedId); + if (it == mFeeds.end()) { + /* feed not found */ #ifdef FEEDREADER_DEBUG - std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - can't add forum message " << mi.title << " for feed " << forumId << std::endl; + std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - feed " << feedId << " not found" << std::endl; #endif - } - } - } else { - std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - can't process forum, member mForums is not derived from RsGenExchange" << std::endl; + return; + } + + RsFeedReaderFeed *fi = it->second; + + if (!fi->preview) { + fi->workstate = RsFeedReaderFeed::WAITING; + fi->content.clear(); + if (errorState == RS_FEED_ERRORSTATE_OK && postError) { + // post error occured + errorState = RS_FEED_ERRORSTATE_PROCESS_POST; } - } else { - std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - can't process forum, member mForums is not set" << std::endl; + fi->errorState = errorState; + fi->lastUpdate = time(NULL); + + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); } } @@ -2064,7 +2360,7 @@ void p3FeedReader::onProcessError(uint32_t feedId, RsFeedReaderErrorState result #endif if (!fi->preview) { - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); } } @@ -2080,6 +2376,9 @@ void p3FeedReader::setFeedInfo(uint32_t feedId, const std::string &name, const s std::string forumId; std::string forumName; std::string forumDescription; + std::string postedId; + std::string postedName; + std::string postedDescription; { RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ @@ -2118,11 +2417,19 @@ void p3FeedReader::setFeedInfo(uint32_t feedId, const std::string &name, const s forumDescription = fi->description; forumName.insert(0, FEEDREADER_FORUM_PREFIX); } + + if ((fi->flag & RS_FEED_FLAG_POSTED) && (fi->flag & RS_FEED_FLAG_UPDATE_POSTED_INFO) && !fi->postedId.empty() && !preview) { + /* change posted too */ + postedId = fi->postedId; + postedName = fi->name; + postedDescription = fi->description; + postedName.insert(0, FEEDREADER_POSTED_PREFIX); + } } if (changed) { if (!preview) { - IndicateConfigChanged(); + IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); } if (mNotify) { @@ -2137,6 +2444,14 @@ void p3FeedReader::setFeedInfo(uint32_t feedId, const std::string &name, const s } //TODO: error } + + if (!postedId.empty()) { + RsPostedGroup postedGroup; + if (getPostedGroup(RsGxsGroupId(postedId), postedGroup)) { + updatePostedGroup(postedGroup, postedName, postedDescription); + } + //TODO: error + } } bool p3FeedReader::getForumGroup(const RsGxsGroupId &groupId, RsGxsForumGroup &forumGroup) @@ -2159,7 +2474,7 @@ bool p3FeedReader::getForumGroup(const RsGxsGroupId &groupId, RsGxsForumGroup &f uint32_t token; mForums->getTokenService()->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, grpIds); - if (!waitForToken(token)) { + if (!waitForToken(mForums, token)) { std::cerr << "p3FeedReader::getForumGroup - waitForToken for request failed" << std::endl; return false; } @@ -2202,7 +2517,7 @@ bool p3FeedReader::updateForumGroup(const RsGxsForumGroup &forumGroup, const std return false; } - if (!waitForToken(token)) { + if (!waitForToken(mForums, token)) { std::cerr << "p3FeedReader::updateForumGroup - waitForToken for update failed" << std::endl; return false; } @@ -2211,13 +2526,85 @@ bool p3FeedReader::updateForumGroup(const RsGxsForumGroup &forumGroup, const std return true; } -bool p3FeedReader::waitForToken(uint32_t token) +bool p3FeedReader::getPostedGroup(const RsGxsGroupId &groupId, RsPostedGroup &postedGroup) { - if (!mForums) { + if (!mPosted) { + std::cerr << "p3FeedReader::getPostedGroup - can't get posted group " << groupId.toStdString() << ", member mPosted is not set" << std::endl; return false; } - RsTokenService *service = mForums->getTokenService(); + if (groupId.isNull()) { + std::cerr << "p3FeedReader::getPostedGroup - group id is not valid" << std::endl; + return false; + } + + std::list grpIds; + grpIds.push_back(groupId); + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + uint32_t token; + mPosted->getTokenService()->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, grpIds); + + if (!waitForToken(mPosted, token)) { + std::cerr << "p3FeedReader::getPostedGroup - waitForToken for request failed" << std::endl; + return false; + } + + std::vector groups; + if (!mPosted->getGroupData(token, groups)) { + std::cerr << "p3FeedReader::getPostedGroup - Error getting data" << std::endl; + return false; + } + + if (groups.size() != 1) { + std::cerr << "p3FeedReader::getPostedGroup - Wrong number of items" << std::endl; + return false; + } + + postedGroup = groups[0]; + + return true; +} + +bool p3FeedReader::updatePostedGroup(const RsPostedGroup &postedGroup, const std::string &groupName, const std::string &groupDescription) +{ + if (!mPosted) { + std::cerr << "p3FeedReader::updatePostedGroup - can't change posted " << postedGroup.mMeta.mGroupId.toStdString() << ", member mPosted is not set" << std::endl; + return false; + } + + if (postedGroup.mMeta.mGroupName == groupName && postedGroup.mDescription == groupDescription) { + /* No change */ + return true; + } + + RsPostedGroup newPostedGroup = postedGroup; + newPostedGroup.mMeta.mGroupName = groupName; + newPostedGroup.mDescription = groupDescription; + + uint32_t token; + if (!mPosted->updateGroup(token, newPostedGroup)) { + std::cerr << "p3FeedReader::updatePostedGroup - can't change posted " << newPostedGroup.mMeta.mGroupId.toStdString() << std::endl; + return false; + } + + if (!waitForToken(mPosted, token)) { + std::cerr << "p3FeedReader::updatePostedGroup - waitForToken for update failed" << std::endl; + return false; + } + + /* Posted updated */ + return true; +} + +bool p3FeedReader::waitForToken(RsGxsIfaceHelper *interface, uint32_t token) +{ + if (!interface) { + return false; + } + + RsTokenService *service = interface->getTokenService(); int count = MAX_REQUEST_AGE * 2; while (!mStopped) { @@ -2239,3 +2626,169 @@ bool p3FeedReader::waitForToken(uint32_t token) return false; } + +bool p3FeedReader::getForumGroups(std::vector &groups, bool onlyOwn) +{ + if (!mForums) { + std::cerr << "p3FeedReader::getForumGroups - can't get groups, member mForums is not set" << std::endl; + return false; + } + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + uint32_t token; + if (!mForums->requestGroupInfo(token, opts)) { + std::cerr << "p3FeedReader::getForumGroups - can't get group list" << std::endl; + return false; + } + + if (!waitForToken(mForums, token)) { + std::cerr << "p3FeedReader::getForumGroups - waitForToken for list failed" << std::endl; + return false; + } + + if (!mForums->getGroupData(token, groups)) { + std::cerr << "p3FeedReader::getForumGroups - getGroupData failed" << std::endl; + return false; + } + + if (onlyOwn) { + // filter groups + for (std::vector::iterator it = groups.begin(); it != groups.end(); ) { + const RsGxsForumGroup &group = *it; + if (IS_GROUP_PUBLISHER(group.mMeta.mSubscribeFlags) && IS_GROUP_ADMIN(group.mMeta.mSubscribeFlags)) { + ++it; + } else { + it = groups.erase(it); + } + } + } + + return true; +} + +bool p3FeedReader::getPostedGroups(std::vector &groups, bool onlyOwn) +{ + if (!mPosted) { + std::cerr << "p3FeedReader::getPostedGroups - can't get groups, member mPosted is not set" << std::endl; + return false; + } + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + uint32_t token; + if (!mPosted->requestGroupInfo(token, opts)) { + std::cerr << "p3FeedReader::getPostedGroups - can't get group list" << std::endl; + return false; + } + + if (!waitForToken(mPosted, token)) { + std::cerr << "p3FeedReader::getPostedGroups - waitForToken for list failed" << std::endl; + return false; + } + + if (!mPosted->getGroupData(token, groups)) { + std::cerr << "p3FeedReader::getForumGroups - getGroupData failed" << std::endl; + return false; + } + + if (onlyOwn) { + // filter groups + for (std::vector::iterator it = groups.begin(); it != groups.end(); ) { + const RsPostedGroup &group = *it; + if (IS_GROUP_PUBLISHER(group.mMeta.mSubscribeFlags) && IS_GROUP_ADMIN(group.mMeta.mSubscribeFlags)) { + ++it; + } else { + it = groups.erase(it); + } + } + } + + return true; +} + +bool p3FeedReader::optimizeImage(FeedReaderOptimizeImageTask::Type type, const std::vector &image, const std::string &mimeType, std::vector &resultImage, std::string &resultMimeType) +{ + if (!mNotify) { + return false; + } + + FeedReaderOptimizeImageTask *optimizeImageTask = new FeedReaderOptimizeImageTask(type, image, mimeType); + { + RsStackMutex stack(mImageMutex); /******* LOCK STACK MUTEX *********/ + + mImages.push_back(optimizeImageTask); + } + + /* Wait until task is complete */ + int nSeconds = 0; + while (true) { + if (mStopped) { + return false; + } + + rstime::rs_usleep(1000 * 1000); // 1 second + + if (++nSeconds >= 30) { + // timeout + std::list::iterator it = std::find(mImages.begin(), mImages.end(), optimizeImageTask); + if (it != mImages.end()) { + mImages.erase(it); + + delete(optimizeImageTask); + + return false; + } + + // not found in mImages? + } + + { + RsStackMutex stack(mImageMutex); /******* LOCK STACK MUTEX *********/ + + std::list::iterator it = std::find(mResultImages.begin(), mResultImages.end(), optimizeImageTask); + if (it != mResultImages.end()) { + mResultImages.erase(it); + + bool result = optimizeImageTask->mResult; + if (result) { + resultImage = optimizeImageTask->mImageResult; + resultMimeType = optimizeImageTask->mMimeTypeResult; + } + + delete(optimizeImageTask); + + return result; + } + } + } + + return false; +} + +FeedReaderOptimizeImageTask *p3FeedReader::getOptimizeImageTask() +{ + RsStackMutex stack(mImageMutex); /******* LOCK STACK MUTEX *********/ + + if (mImages.empty()) { + return NULL; + } + + FeedReaderOptimizeImageTask *imageResize = mImages.front(); + mImages.pop_front(); + + return imageResize; +} + +void p3FeedReader::setOptimizeImageTaskResult(FeedReaderOptimizeImageTask *optimizeImageTask) +{ + if (!optimizeImageTask) { + return; + } + + RsStackMutex stack(mImageMutex); /******* LOCK STACK MUTEX *********/ + + mResultImages.push_back(optimizeImageTask); +} diff --git a/plugins/FeedReader/services/p3FeedReader.h b/plugins/FeedReader/services/p3FeedReader.h index 08fa3619b..0df9bf79e 100644 --- a/plugins/FeedReader/services/p3FeedReader.h +++ b/plugins/FeedReader/services/p3FeedReader.h @@ -33,11 +33,14 @@ class p3FeedReaderThread; class RsGxsForums; struct RsGxsForumGroup; +class RsPosted; +struct RsPostedGroup; +class RsGxsIfaceHelper; class p3FeedReader : public RsPQIService, public RsFeedReader { public: - p3FeedReader(RsPluginHandler *pgHandler, RsGxsForums *forums); + p3FeedReader(RsPluginHandler *pgHandler, RsGxsForums *forums, RsPosted *posted); /****************** FeedReader Interface *************/ virtual void stop(); @@ -52,24 +55,33 @@ public: virtual bool getSaveInBackground(); virtual void setSaveInBackground(bool saveInBackground); - virtual RsFeedAddResult addFolder(uint32_t parentId, const std::string &name, uint32_t &feedId); - virtual RsFeedAddResult setFolder(uint32_t feedId, const std::string &name); - virtual RsFeedAddResult addFeed(const FeedInfo &feedInfo, uint32_t &feedId); - virtual RsFeedAddResult setFeed(uint32_t feedId, const FeedInfo &feedInfo); - virtual bool removeFeed(uint32_t feedId); - virtual bool addPreviewFeed(const FeedInfo &feedInfo, uint32_t &feedId); - virtual void getFeedList(uint32_t parentId, std::list &feedInfos); - virtual bool getFeedInfo(uint32_t feedId, FeedInfo &feedInfo); - virtual bool getMsgInfo(uint32_t feedId, const std::string &msgId, FeedMsgInfo &msgInfo); - virtual bool removeMsg(uint32_t feedId, const std::string &msgId); - virtual bool removeMsgs(uint32_t feedId, const std::list &msgIds); - virtual bool getMessageCount(uint32_t feedId, uint32_t *msgCount, uint32_t *newCount, uint32_t *unreadCount); - virtual bool getFeedMsgList(uint32_t feedId, std::list &msgInfos); - virtual bool getFeedMsgIdList(uint32_t feedId, std::list &msgIds); - virtual bool processFeed(uint32_t feedId); - virtual bool setMessageRead(uint32_t feedId, const std::string &msgId, bool read); - virtual bool retransformMsg(uint32_t feedId, const std::string &msgId); - virtual bool clearMessageCache(uint32_t feedId); + virtual RsFeedResult addFolder(uint32_t parentId, const std::string &name, uint32_t &feedId); + virtual RsFeedResult setFolder(uint32_t feedId, const std::string &name); + virtual RsFeedResult addFeed(const FeedInfo &feedInfo, uint32_t &feedId); + virtual RsFeedResult setFeed(uint32_t feedId, const FeedInfo &feedInfo); + virtual RsFeedResult setParent(uint32_t feedId, uint32_t parentId); + virtual bool removeFeed(uint32_t feedId); + virtual bool addPreviewFeed(const FeedInfo &feedInfo, uint32_t &feedId); + virtual void getFeedList(uint32_t parentId, std::list &feedInfos); + virtual bool getFeedInfo(uint32_t feedId, FeedInfo &feedInfo); + virtual bool getMsgInfo(uint32_t feedId, const std::string &msgId, FeedMsgInfo &msgInfo); + virtual bool removeMsg(uint32_t feedId, const std::string &msgId); + virtual bool removeMsgs(uint32_t feedId, const std::list &msgIds); + virtual bool getMessageCount(uint32_t feedId, uint32_t *msgCount, uint32_t *newCount, uint32_t *unreadCount); + virtual bool getFeedMsgList(uint32_t feedId, std::list &msgInfos); + virtual bool getFeedMsgIdList(uint32_t feedId, std::list &msgIds); + virtual bool processFeed(uint32_t feedId); + virtual bool setMessageRead(uint32_t feedId, const std::string &msgId, bool read); + virtual bool retransformMsg(uint32_t feedId, const std::string &msgId); + virtual bool clearMessageCache(uint32_t feedId); + + virtual RsGxsForums* forums() { return mForums; } + virtual RsPosted* posted() { return mPosted; } + virtual bool getForumGroups(std::vector &groups, bool onlyOwn); + virtual bool getPostedGroups(std::vector &groups, bool onlyOwn); + + virtual FeedReaderOptimizeImageTask *getOptimizeImageTask(); + virtual void setOptimizeImageTaskResult(FeedReaderOptimizeImageTask *optimizeImageTask); virtual RsFeedReaderErrorState processXPath(const std::list &xpathsToUse, const std::list &xpathsToRemove, std::string &description, std::string &errorString); virtual RsFeedReaderErrorState processXslt(const std::string &xslt, std::string &description, std::string &errorString); @@ -83,7 +95,7 @@ public: void onDownloadSuccess(uint32_t feedId, const std::string &content, std::string &icon); void onDownloadError(uint32_t feedId, RsFeedReaderErrorState result, const std::string &errorString); void onProcessSuccess_filterMsg(uint32_t feedId, std::list &msgs); - void onProcessSuccess_addMsgs(uint32_t feedId, std::list &msgs, bool single); + void onProcessSuccess_addMsgs(uint32_t feedId, std::list &msgs); void onProcessError(uint32_t feedId, RsFeedReaderErrorState result, const std::string &errorString); bool getFeedToProcess(RsFeedReaderFeed &feed, uint32_t neededFeedId); @@ -92,7 +104,10 @@ public: bool getForumGroup(const RsGxsGroupId &groupId, RsGxsForumGroup &forumGroup); bool updateForumGroup(const RsGxsForumGroup &forumGroup, const std::string &groupName, const std::string &groupDescription); - bool waitForToken(uint32_t token); + bool getPostedGroup(const RsGxsGroupId &groupId, RsPostedGroup &postedGroup); + bool updatePostedGroup(const RsPostedGroup &postedGroup, const std::string &groupName, const std::string &groupDescription); + bool waitForToken(RsGxsIfaceHelper *interface, uint32_t token); + bool optimizeImage(FeedReaderOptimizeImageTask::Type type, const std::vector &image, const std::string &mimeType, std::vector &resultImage, std::string &resultMimeType); protected: /****************** p3Config STUFF *******************/ @@ -109,6 +124,7 @@ private: private: time_t mLastClean; RsGxsForums *mForums; + RsPosted *mPosted; RsFeedReaderNotify *mNotify; volatile bool mStopped; @@ -133,6 +149,10 @@ private: RsMutex mProcessMutex; std::list mProcessFeeds; + RsMutex mImageMutex; + std::list mImages; + std::list mResultImages; + RsMutex mPreviewMutex; p3FeedReaderThread *mPreviewDownloadThread; p3FeedReaderThread *mPreviewProcessThread; diff --git a/plugins/FeedReader/services/p3FeedReaderThread.cc b/plugins/FeedReader/services/p3FeedReaderThread.cc index 38f966663..110d051cf 100644 --- a/plugins/FeedReader/services/p3FeedReaderThread.cc +++ b/plugins/FeedReader/services/p3FeedReaderThread.cc @@ -89,7 +89,7 @@ void p3FeedReaderThread::threadTick() /* first, filter the messages */ mFeedReader->onProcessSuccess_filterMsg(feed.feedId, msgs); if (isRunning()) { - /* second, process the descriptions */ + /* second, process the descriptions and attachment */ for (it = msgs.begin(); it != msgs.end(); ) { if (!isRunning()) { break; @@ -107,7 +107,7 @@ void p3FeedReaderThread::threadTick() std::list msgSingle; msgSingle.push_back(mi); - mFeedReader->onProcessSuccess_addMsgs(feed.feedId, msgSingle, true); + mFeedReader->onProcessSuccess_addMsgs(feed.feedId, msgSingle); /* delete not accepted message */ std::list::iterator it1; @@ -122,12 +122,15 @@ void p3FeedReaderThread::threadTick() ++it; } } - if (isRunning()) { - if (result == RS_FEED_ERRORSTATE_OK) { - /* third, add messages */ - mFeedReader->onProcessSuccess_addMsgs(feed.feedId, msgs, false); - } else { - mFeedReader->onProcessError(feed.feedId, result, errorString); + + if (!feed.preview) { + if (isRunning()) { + if (result == RS_FEED_ERRORSTATE_OK) { + /* third, add messages */ + mFeedReader->onProcessSuccess_addMsgs(feed.feedId, msgs); + } else { + mFeedReader->onProcessError(feed.feedId, result, errorString); + } } } } @@ -150,12 +153,12 @@ void p3FeedReaderThread::threadTick() /****************************** Download ***********************************/ /***************************************************************************/ -static bool isContentType(const std::string &contentType, const char *type) +bool p3FeedReaderThread::isContentType(const std::string &contentType, const char *type) { return (strncasecmp(contentType.c_str(), type, strlen(type)) == 0); } -static bool toBase64(const std::vector &data, std::string &base64) +bool p3FeedReaderThread::toBase64(const std::vector &data, std::string &base64) { bool result = false; @@ -184,6 +187,28 @@ static bool toBase64(const std::vector &data, std::string &base64 return result; } +bool p3FeedReaderThread::fromBase64(const std::string &base64, std::vector &data) +{ + bool result = false; + + BIO *b64 = BIO_new(BIO_f_base64()); + if (b64) { + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + BIO *source = BIO_new_mem_buf(base64.c_str(), -1); // read-only source + if (source) { + BIO_push(b64, source); + const int maxlen = base64.length() / 4 * 3 + 1; + data.resize(maxlen); + const int len = BIO_read(b64, data.data(), maxlen); + data.resize(len); + result = true; + } + BIO_free_all(b64); + } + + return result; +} + static std::string getBaseLink(std::string link) { size_t found = link.rfind('/'); @@ -196,7 +221,7 @@ static std::string getBaseLink(std::string link) static std::string calculateLink(const std::string &baseLink, const std::string &link) { - if (link.substr(0, 7) == "http://") { + if (link.substr(0, 7) == "http://" || link.substr(0, 8) == "https://") { /* absolute link */ return link; } @@ -204,8 +229,14 @@ static std::string calculateLink(const std::string &baseLink, const std::string /* calculate link of base link */ std::string resultLink = baseLink; - /* link should begin with "http://" */ - if (resultLink.substr(0, 7) != "http://") { + int hostStart = 0; + /* link should begin with "http://" or "https://" */ + if (resultLink.substr(0, 7) == "http://") { + hostStart = 7; + } else if (resultLink.substr(0, 8) == "https://") { + hostStart = 8; + } else { + hostStart = 7; resultLink.insert(0, "http://"); } @@ -216,7 +247,7 @@ static std::string calculateLink(const std::string &baseLink, const std::string if (*link.begin() == '/') { /* link begins with "/" */ - size_t found = resultLink.find('/', 7); + size_t found = resultLink.find('/', hostStart); if (found != std::string::npos) { resultLink.erase(found); } @@ -245,12 +276,12 @@ static bool getFavicon(CURLWrapper &CURL, const std::string &url, std::string &i if (code == CURLE_OK) { if (CURL.responseCode() == 200) { std::string contentType = CURL.contentType(); - if (isContentType(contentType, "image/x-icon") || - isContentType(contentType, "application/octet-stream") || - isContentType(contentType, "text/plain")) { + if (p3FeedReaderThread::isContentType(contentType, "image/") || + p3FeedReaderThread::isContentType(contentType, "application/octet-stream") || + p3FeedReaderThread::isContentType(contentType, "text/plain")) { if (!vicon.empty()) { #warning p3FeedReaderThread.cc TODO thunder2: check it - result = toBase64(vicon, icon); + result = p3FeedReaderThread::toBase64(vicon, icon); } } } @@ -296,6 +327,9 @@ RsFeedReaderErrorState p3FeedReaderThread::download(const RsFeedReaderFeed &feed } } break; + case 403: + result = RS_FEED_ERRORSTATE_DOWNLOAD_BLOCKED; + break; case 404: result = RS_FEED_ERRORSTATE_DOWNLOAD_NOT_FOUND; break; @@ -814,6 +848,22 @@ RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed, RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK; + time_t minimumPubDate = 0; + if (feed.lastUpdate == 0) { + // Get all items on first scan + } else { + // Get storage time + uint32_t storageTime = 0; + if (feed.flag & RS_FEED_FLAG_STANDARD_STORAGE_TIME) { + storageTime = mFeedReader->getStandardStorageTime(); + } else { + storageTime = feed.storageTime; + } + if (storageTime > 0) { + minimumPubDate = time(NULL) - storageTime; + } + } + XMLWrapper xml; if (xml.readXML(feed.content.c_str())) { xmlNodePtr root = xml.getRootElement(); @@ -959,6 +1009,26 @@ RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed, item->pubDate = time(NULL); } + if (feedFormat == FORMAT_RSS) { + /* */ + xmlNodePtr enclosure = xml.findNode(node->children, "enclosure", false); + if (enclosure) { + std::string enclosureMimeType = xml.getAttr(enclosure, "type"); + std::string enclosureUrl = xml.getAttr(enclosure, "url"); + if (!enclosureUrl.empty()) { + item->attachmentLink = enclosureUrl; + item->attachmentMimeType = enclosureMimeType; + } + } + } + + if (minimumPubDate) { + if (item->pubDate < minimumPubDate) { + // pubDate is less than storage time, don't add as new item + continue; + } + } + entries.push_back(item); } } else { @@ -1013,10 +1083,44 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK; std::string proxy = getProxyForFeed(feed); + /* attachment */ + if (!msg->attachmentLink.empty()) { + if (isContentType(msg->attachmentMimeType, "image/")) { + CURLWrapper CURL(proxy); + CURLcode code = CURL.downloadBinary(msg->attachmentLink, msg->attachmentBinary); + if (code == CURLE_OK && CURL.responseCode() == 200) { + std::string contentType = CURL.contentType(); + if (isContentType(contentType, "image/")) { + msg->attachmentBinaryMimeType = contentType; + + bool forum = (feed.flag & RS_FEED_FLAG_FORUM) && !feed.preview; + bool posted = (feed.flag & RS_FEED_FLAG_POSTED) && !feed.preview; + + if (!forum && ! posted) { + /* no need to optimize image */ + std::vector optimizedBinary; + std::string optimizedMimeType; + if (mFeedReader->optimizeImage(FeedReaderOptimizeImageTask::SIZE, msg->attachmentBinary, msg->attachmentBinaryMimeType, optimizedBinary, optimizedMimeType)) { + if (toBase64(optimizedBinary, msg->attachment)) { + msg->attachmentMimeType = optimizedMimeType; + } else { + msg->attachment.clear(); + } + } + } + } else { + msg->attachmentBinary.clear(); + } + } else { + msg->attachmentBinary.clear(); + } + } + } + std::string url; if (feed.flag & RS_FEED_FLAG_SAVE_COMPLETE_PAGE) { #ifdef FEEDREADER_DEBUG - std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") download page " << msg->link << std::endl; + std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") download page " << msg->link << std::endl; #endif std::string content; CURLWrapper CURL(proxy); @@ -1053,7 +1157,7 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe if (result != RS_FEED_ERRORSTATE_OK) { #ifdef FEEDREADER_DEBUG - std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot download page, CURLCode = " << code << ", error = " << errorString << std::endl; + std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") cannot download page, CURLCode = " << code << ", error = " << errorString << std::endl; #endif return result; } @@ -1070,12 +1174,19 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe if (isRunning()) { /* process description */ + bool processPostedFirstImage = (feed.flag & RS_FEED_FLAG_POSTED_FIRST_IMAGE) ? true : false; + if (!msg->attachmentBinary.empty()) { + /* use attachment as image */ + processPostedFirstImage = false; + } + //long todo; // encoding HTMLWrapper html; if (html.readHTML(msg->description.c_str(), url.c_str())) { xmlNodePtr root = html.getRootElement(); if (root) { std::list nodesToDelete; + xmlNodePtr postedFirstImageNode = NULL; /* process all children */ std::list nodes; @@ -1192,7 +1303,7 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe if (!src.empty()) { /* download image */ #ifdef FEEDREADER_DEBUG - std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") download image " << src << std::endl; + std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") download image " << src << std::endl; #endif std::vector data; CURLWrapper CURL(proxy); @@ -1200,14 +1311,24 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe if (code == CURLE_OK && CURL.responseCode() == 200) { std::string contentType = CURL.contentType(); if (isContentType(contentType, "image/")) { - std::string base64; - if (toBase64(data, base64)) { - std::string imageBase64; - rs_sprintf(imageBase64, "data:%s;base64,%s", contentType.c_str(), base64.c_str()); - if (html.setAttr(node, "src", imageBase64.c_str())) { - removeImage = false; + std::vector optimizedData; + std::string optimizedMimeType; + if (mFeedReader->optimizeImage(FeedReaderOptimizeImageTask::SIZE, data, contentType, optimizedData, optimizedMimeType)) { + std::string base64; + if (toBase64(optimizedData, base64)) { + std::string imageBase64; + rs_sprintf(imageBase64, "data:%s;base64,%s", optimizedMimeType.c_str(), base64.c_str()); + if (html.setAttr(node, "src", imageBase64.c_str())) { + removeImage = false; + } } } + if (processPostedFirstImage && postedFirstImageNode == NULL) { + /* set first image */ + msg->postedFirstImage = data; + msg->postedFirstImageMimeType = contentType; + postedFirstImageNode = node; + } } } } @@ -1241,10 +1362,25 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe if (result == RS_FEED_ERRORSTATE_OK) { if (isRunning()) { - if (!html.saveHTML(msg->description)) { + if (html.saveHTML(msg->description)) { + if (postedFirstImageNode) { + /* Remove first image and create description without the image */ + xmlUnlinkNode(postedFirstImageNode); + xmlFreeNode(postedFirstImageNode); + + if (!html.saveHTML(msg->postedDescriptionWithoutFirstImage)) { + errorString = html.lastError(); +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl; + std::cerr << " Error: " << errorString << std::endl; +#endif + result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR; + } + } + } else { errorString = html.lastError(); #ifdef FEEDREADER_DEBUG - std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl; + std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl; std::cerr << " Error: " << errorString << std::endl; #endif result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR; @@ -1253,14 +1389,14 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe } } else { #ifdef FEEDREADER_DEBUG - std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") no root element" << std::endl; + std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") no root element" << std::endl; #endif result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR; } } else { errorString = html.lastError(); #ifdef FEEDREADER_DEBUG - std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot read html" << std::endl; + std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") cannot read html" << std::endl; std::cerr << " Error: " << errorString << std::endl; #endif result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR; diff --git a/plugins/FeedReader/services/p3FeedReaderThread.h b/plugins/FeedReader/services/p3FeedReaderThread.h index 48d920dd6..a9be84010 100644 --- a/plugins/FeedReader/services/p3FeedReaderThread.h +++ b/plugins/FeedReader/services/p3FeedReaderThread.h @@ -54,6 +54,11 @@ public: static RsFeedReaderErrorState processXslt(const std::string &xslt, HTMLWrapper &html, std::string &errorString); static RsFeedReaderErrorState processTransformation(const RsFeedReaderFeed &feed, RsFeedReaderMsg *msg, std::string &errorString); + + static bool isContentType(const std::string &contentType, const char *type); + static bool toBase64(const std::vector &data, std::string &base64); + static bool fromBase64(const std::string &base64, std::vector &data); + private: virtual void threadTick() override; /// @see RsTickingThread diff --git a/plugins/FeedReader/services/rsFeedReaderItems.cc b/plugins/FeedReader/services/rsFeedReaderItems.cc index 04a6c8f1e..0d5b1f60b 100644 --- a/plugins/FeedReader/services/rsFeedReaderItems.cc +++ b/plugins/FeedReader/services/rsFeedReaderItems.cc @@ -46,6 +46,7 @@ void RsFeedReaderFeed::clear() storageTime = 0; flag = 0; forumId.clear(); + postedId.clear(); description.clear(); icon.clear(); errorState = RS_FEED_ERRORSTATE_OK; @@ -85,6 +86,7 @@ uint32_t RsFeedReaderSerialiser::sizeFeed(RsFeedReaderFeed *item) s += item->xpathsToUse.TlvSize(); s += item->xpathsToRemove.TlvSize(); s += GetTlvStringSize(item->xslt); + s += GetTlvStringSize(item->postedId); return s; } @@ -108,7 +110,7 @@ bool RsFeedReaderSerialiser::serialiseFeed(RsFeedReaderFeed *item, void *data, u offset += 8; /* add values */ - ok &= setRawUInt16(data, tlvsize, &offset, 2); /* version */ + ok &= setRawUInt16(data, tlvsize, &offset, 3); /* version */ ok &= setRawUInt32(data, tlvsize, &offset, item->feedId); ok &= setRawUInt32(data, tlvsize, &offset, item->parentId); ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LINK, item->url); @@ -124,6 +126,7 @@ bool RsFeedReaderSerialiser::serialiseFeed(RsFeedReaderFeed *item, void *data, u ok &= setRawUInt32(data, tlvsize, &offset, item->storageTime); ok &= setRawUInt32(data, tlvsize, &offset, item->flag); ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->forumId); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->postedId); ok &= setRawUInt32(data, tlvsize, &offset, item->errorState); ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->errorString); ok &= setRawUInt32(data, tlvsize, &offset, item->transformationType); @@ -208,6 +211,9 @@ RsFeedReaderFeed *RsFeedReaderSerialiser::deserialiseFeed(void *data, uint32_t * ok &= getRawUInt32(data, rssize, &offset, &(item->storageTime)); ok &= getRawUInt32(data, rssize, &offset, &(item->flag)); ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->forumId); + if (version >= 3) { + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->postedId); + } uint32_t errorState = 0; ok &= getRawUInt32(data, rssize, &offset, &errorState); item->errorState = (RsFeedReaderErrorState) errorState; @@ -268,6 +274,9 @@ void RsFeedReaderMsg::clear() descriptionTransformed.clear(); pubDate = 0; flag = 0; + attachmentLink.clear(); + attachment.clear(); + attachmentMimeType.clear(); } std::ostream &RsFeedReaderMsg::print(std::ostream &out, uint16_t /*indent*/) @@ -288,6 +297,9 @@ uint32_t RsFeedReaderSerialiser::sizeMsg(RsFeedReaderMsg *item) s += GetTlvStringSize(item->descriptionTransformed); s += sizeof(uint32_t); /* pubDate */ s += sizeof(uint32_t); /* flag */ + s += GetTlvStringSize(item->attachmentLink); + s += GetTlvStringSize(item->attachment); + s += GetTlvStringSize(item->attachmentMimeType); return s; } @@ -311,7 +323,7 @@ bool RsFeedReaderSerialiser::serialiseMsg(RsFeedReaderMsg *item, void *data, uin offset += 8; /* add values */ - ok &= setRawUInt16(data, tlvsize, &offset, 2); /* version */ + ok &= setRawUInt16(data, tlvsize, &offset, 3); /* version */ ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->msgId); ok &= setRawUInt32(data, tlvsize, &offset, item->feedId); ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_NAME, item->title); @@ -321,6 +333,9 @@ bool RsFeedReaderSerialiser::serialiseMsg(RsFeedReaderMsg *item, void *data, uin ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_COMMENT, item->descriptionTransformed); ok &= setRawUInt32(data, tlvsize, &offset, item->pubDate); ok &= setRawUInt32(data, tlvsize, &offset, item->flag); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LOCATION, item->attachmentLink); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PIC_AUTH, item->attachment); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PIC_TYPE, item->attachmentMimeType); if (offset != tlvsize) { @@ -384,6 +399,11 @@ RsFeedReaderMsg *RsFeedReaderSerialiser::deserialiseMsg(void *data, uint32_t *pk } ok &= getRawUInt32(data, rssize, &offset, (uint32_t*) &(item->pubDate)); ok &= getRawUInt32(data, rssize, &offset, &(item->flag)); + if (version >= 3) { + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_LOCATION, item->attachmentLink); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PIC_AUTH, item->attachment); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PIC_TYPE, item->attachmentMimeType); + } if (offset != rssize) { diff --git a/plugins/FeedReader/services/rsFeedReaderItems.h b/plugins/FeedReader/services/rsFeedReaderItems.h index a8cce7084..4e343be75 100644 --- a/plugins/FeedReader/services/rsFeedReaderItems.h +++ b/plugins/FeedReader/services/rsFeedReaderItems.h @@ -34,17 +34,22 @@ const uint8_t RS_PKT_SUBTYPE_FEEDREADER_MSG = 0x03; /**************************************************************************/ -#define RS_FEED_FLAG_FOLDER 0x001 -#define RS_FEED_FLAG_INFO_FROM_FEED 0x002 -#define RS_FEED_FLAG_STANDARD_STORAGE_TIME 0x004 -#define RS_FEED_FLAG_STANDARD_UPDATE_INTERVAL 0x008 -#define RS_FEED_FLAG_STANDARD_PROXY 0x010 -#define RS_FEED_FLAG_AUTHENTICATION 0x020 -#define RS_FEED_FLAG_DEACTIVATED 0x040 -#define RS_FEED_FLAG_FORUM 0x080 -#define RS_FEED_FLAG_UPDATE_FORUM_INFO 0x100 -#define RS_FEED_FLAG_EMBED_IMAGES 0x200 -#define RS_FEED_FLAG_SAVE_COMPLETE_PAGE 0x400 +#define RS_FEED_FLAG_FOLDER 0x0001 +#define RS_FEED_FLAG_INFO_FROM_FEED 0x0002 +#define RS_FEED_FLAG_STANDARD_STORAGE_TIME 0x0004 +#define RS_FEED_FLAG_STANDARD_UPDATE_INTERVAL 0x0008 +#define RS_FEED_FLAG_STANDARD_PROXY 0x0010 +#define RS_FEED_FLAG_AUTHENTICATION 0x0020 +#define RS_FEED_FLAG_DEACTIVATED 0x0040 +#define RS_FEED_FLAG_FORUM 0x0080 +#define RS_FEED_FLAG_UPDATE_FORUM_INFO 0x0100 +#define RS_FEED_FLAG_EMBED_IMAGES 0x0200 +#define RS_FEED_FLAG_SAVE_COMPLETE_PAGE 0x0400 +#define RS_FEED_FLAG_POSTED 0x0800 +#define RS_FEED_FLAG_UPDATE_POSTED_INFO 0x1000 +#define RS_FEED_FLAG_POSTED_FIRST_IMAGE 0x2000 +#define RS_FEED_FLAG_POSTED_ONLY_IMAGE 0x4000 +#define RS_FEED_FLAG_POSTED_SHRINK_IMAGE 0x8000 class RsFeedReaderFeed : public RsItem { @@ -62,6 +67,7 @@ public: virtual ~RsFeedReaderFeed() {} virtual void clear(); + virtual void serial_process(RsGenericSerializer::SerializeJob, RsGenericSerializer::SerializeContext&) {} uint32_t feedId; uint32_t parentId; @@ -75,6 +81,7 @@ public: time_t lastUpdate; uint32_t flag; // RS_FEED_FLAG_... std::string forumId; + std::string postedId; uint32_t storageTime; std::string description; std::string icon; @@ -105,6 +112,7 @@ public: virtual ~RsFeedReaderMsg() {} virtual void clear(); + virtual void serial_process(RsGenericSerializer::SerializeJob, RsGenericSerializer::SerializeContext&) {} virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); std::string msgId; @@ -116,6 +124,16 @@ public: std::string descriptionTransformed; time_t pubDate; uint32_t flag; // RS_FEEDMSG_FLAG_... + std::string attachmentLink; + std::string attachment; // binary as base64 + std::string attachmentMimeType; + + // Only in memory when receiving messages + std::vector attachmentBinary; + std::string attachmentBinaryMimeType; + std::vector postedFirstImage; + std::string postedFirstImageMimeType; + std::string postedDescriptionWithoutFirstImage; }; class RsFeedReaderSerialiser: public RsSerialType diff --git a/plugins/FeedReader/util/CURLWrapper.cpp b/plugins/FeedReader/util/CURLWrapper.cpp index 4e8c5c9bb..94ae7beaa 100644 --- a/plugins/FeedReader/util/CURLWrapper.cpp +++ b/plugins/FeedReader/util/CURLWrapper.cpp @@ -21,6 +21,8 @@ #include "CURLWrapper.h" #include +#define USERAGENT "Mozilla/5.0 (rv:109.0) Gecko/20100101 Firefox/112.0" + CURLWrapper::CURLWrapper(const std::string &proxy) { mCurl = curl_easy_init(); @@ -65,6 +67,7 @@ CURLcode CURLWrapper::downloadText(const std::string &link, std::string &data) curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, writeFunctionString); curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, &data); curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, false); + curl_easy_setopt(mCurl, CURLOPT_USERAGENT, USERAGENT); return curl_easy_perform(mCurl); } @@ -94,6 +97,8 @@ CURLcode CURLWrapper::downloadBinary(const std::string &link, std::vector #include #define IMAGE_VOIP ":/images/talking_on.svg" @@ -113,7 +112,7 @@ ConfigPage *VOIPPlugin::qt_config_page() const // The config pages are deleted when config is closed, so it's important not to static the // created object. // - return new AudioInputConfig() ; + return new VOIPConfigPanel() ; } QDialog *VOIPPlugin::qt_about_page() const @@ -188,8 +187,6 @@ std::string VOIPPlugin::getPluginName() const void VOIPPlugin::getLibraries(std::list &libraries) { - libraries.push_back(RsLibraryInfo("OpenCV", CV_VERSION)); - const char *speexVersion = NULL; if (speex_lib_ctl(SPEEX_LIB_GET_VERSION_STRING, &speexVersion) == 0 && speexVersion) { libraries.push_back(RsLibraryInfo("Speex", speexVersion)); diff --git a/plugins/VOIP/gui/AudioInputConfig.cpp b/plugins/VOIP/gui/AudioInputConfig.cpp deleted file mode 100644 index b063d5e48..000000000 --- a/plugins/VOIP/gui/AudioInputConfig.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/******************************************************************************* - * plugins/VOIP/gui/AudioInputConfig.h * - * * - * Copyright (C) 2008, Andreas Messer * - * Copyright (C) 2005-2010 Thorvald Natvig * - * Copyright (C) 2012 by Retroshare Team * - * * - * 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 . * - * * - *******************************************************************************/ -#pragma once - -#include "AudioStats.h" -#include "AudioInputConfig.h" -#include "audiodevicehelper.h" -#include "AudioWizard.h" -#include "gui/VideoProcessor.h" -#include "gui/common/RSGraphWidget.h" -#include "util/RsProtectedTimer.h" - -#include - -#define iroundf(x) ( static_cast(x) ) - -class voipGraphSource: public RSGraphSource -{ -public: - voipGraphSource() : video_input(NULL) {} - - void setVideoInput(const QVideoInputDevice *vid) { video_input = vid ; } - - virtual QString displayName(int) const { return tr("Required bandwidth") ;} - - virtual QString displayValue(float v) const - { - if(v < 1000) - return QString::number(v,10,2) + " B/s" ; - else if(v < 1000*1024) - return QString::number(v/1024,10,2) + " KB/s" ; - else - return QString::number(v/(1024*1024),10,2) + " MB/s" ; - } - - virtual void getValues(std::map& vals) const - { - vals.clear() ; - - if(video_input) - vals[std::string("bw")] = video_input->currentBandwidth() ; - } - -private: - const QVideoInputDevice *video_input ; -}; - -void voipGraph::setVoipSource(voipGraphSource *gs) -{ -_src = gs ; -RSGraphWidget::setSource(gs) ; -} - -voipGraph::voipGraph(QWidget *parent) - : RSGraphWidget(parent) -{ - setFlags(RSGraphWidget::RSGRAPH_FLAGS_SHOW_LEGEND) ; - setFlags(RSGraphWidget::RSGRAPH_FLAGS_PAINT_STYLE_PLAIN) ; - - _src = NULL ; -} - -/** Constructor */ -AudioInputConfig::AudioInputConfig(QWidget * parent, Qt::WindowFlags flags) - : ConfigPage(parent, flags) -{ - std::cerr << "Creating audioInputConfig object" << std::endl; - - /* Invoke the Qt Designer generated object setup routine */ - ui.setupUi(this); - - loaded = false; - - inputAudioProcessor = NULL; - inputAudioDevice = NULL; - abSpeech = NULL; - qtTick = NULL; - - // Create the video pipeline. - // - videoInput = new QVideoInputDevice(this) ; - videoInput->setEchoVideoTarget(ui.videoDisplay) ; - - videoProcessor = new VideoProcessor() ; - videoProcessor->setDisplayTarget(NULL) ; - - videoProcessor->setMaximumBandwidth(ui.availableBW_SB->value()) ; - - videoInput->setVideoProcessor(videoProcessor) ; - - graph_source = new voipGraphSource ; - ui.voipBwGraph->setSource(graph_source); - - graph_source->setVideoInput(videoInput) ; - graph_source->setCollectionTimeLimit(1000*300) ; - graph_source->start() ; - - QObject::connect(ui.showEncoded_CB,SIGNAL(toggled(bool)),this,SLOT(togglePreview(bool))) ; - QObject::connect(ui.availableBW_SB,SIGNAL(valueChanged(double)),this,SLOT(updateAvailableBW(double))) ; -} - -void AudioInputConfig::updateAvailableBW(double r) -{ - std::cerr << "Setting max bandwidth to " << r << " KB/s" << std::endl; - videoProcessor->setMaximumBandwidth((uint32_t)(r*1024)) ; -} - -void AudioInputConfig::togglePreview(bool b) -{ - if(b) - { - videoInput->setEchoVideoTarget(NULL) ; - videoProcessor->setDisplayTarget(ui.videoDisplay) ; - } - else - { - videoProcessor->setDisplayTarget(NULL) ; - videoInput->setEchoVideoTarget(ui.videoDisplay) ; - } -} - -AudioInputConfig::~AudioInputConfig() -{ - disconnect( qtTick, SIGNAL( timeout ( ) ), this, SLOT( on_Tick_timeout() ) ); - - graph_source->stop() ; - graph_source->setVideoInput(NULL) ; - - std::cerr << "Deleting audioInputConfig object" << std::endl; - if(videoInput != NULL) - { - videoInput->stop() ; - delete videoInput ; - } - - if (inputAudioDevice) { - inputAudioDevice->stop(); - delete inputAudioDevice ; - inputAudioDevice = NULL ; - } - - if(inputAudioProcessor) - { - delete inputAudioProcessor ; - inputAudioProcessor = NULL ; - } -} - -/** Loads the settings for this page */ -void AudioInputConfig::load() -{ - //connect( ui.allowIpDeterminationCB, SIGNAL( toggled( bool ) ), this, SLOT( toggleIpDetermination(bool) ) ); - //connect( ui.allowTunnelConnectionCB, SIGNAL( toggled( bool ) ), this, SLOT( toggleTunnelConnection(bool) ) ); - - qtTick = new RsProtectedTimer(this); - connect( qtTick, SIGNAL( timeout ( ) ), this, SLOT( on_Tick_timeout() ) ); - qtTick->start(20); - /*if (AudioInputRegistrar::qmNew) { - QList keys = AudioInputRegistrar::qmNew->keys(); - foreach(QString key, keys) { - qcbSystem->addItem(key); - } - } - qcbSystem->setEnabled(qcbSystem->count() > 1);*/ - - ui.qcbTransmit->addItem(tr("Continuous"), RsVOIP::AudioTransmitContinous); - ui.qcbTransmit->addItem(tr("Voice Activity"), RsVOIP::AudioTransmitVAD); - ui.qcbTransmit->addItem(tr("Push To Talk"), RsVOIP::AudioTransmitPushToTalk); - - abSpeech = new AudioBar(); - abSpeech->qcBelow = Qt::red; - abSpeech->qcInside = Qt::yellow; - abSpeech->qcAbove = Qt::green; - //abSpeech->setGeometry(9,20,50,10); - ui.qwVadLayout_2->addWidget(abSpeech,0,0,1,0); - - //on_qcbPushClick_clicked(g.s.bPushClick); - //ui.on_Tick_timeout(); - loadSettings(); -} - - -void AudioInputConfig::loadSettings() { - /*QList keys; - - if (AudioInputRegistrar::qmNew) - keys=AudioInputRegistrar::qmNew->keys(); - else - keys.clear(); - i=keys.indexOf(AudioInputRegistrar::current); - if (i >= 0) - loadComboBox(qcbSystem, i); - - loadCheckBox(qcbExclusive, r.bExclusiveInput);*/ - - //qlePushClickPathOn->setText(r.qsPushClickOn); - //qlePushClickPathOff->setText(r.qsPushClickOff); - - /*loadComboBox(qcbTransmit, r.atTransmit); - loadSlider(qsTransmitHold, r.iVoiceHold); - loadSlider(qsTransmitMin, iroundf(r.fVADmin * 32767.0f + 0.5f)); - loadSlider(qsTransmitMax, iroundf(r.fVADmax * 32767.0f + 0.5f)); - loadSlider(qsFrames, (r.iFramesPerPacket == 1) ? 1 : (r.iFramesPerPacket/2 + 1)); - loadSlider(qsDoublePush, iroundf(static_cast(r.uiDoublePush) / 1000.f + 0.5f));*/ - ui.qcbTransmit->setCurrentIndex(rsVOIP->getVoipATransmit()); - on_qcbTransmit_currentIndexChanged(rsVOIP->getVoipATransmit()); - ui.qsTransmitHold->setValue(rsVOIP->getVoipVoiceHold()); - on_qsTransmitHold_valueChanged(rsVOIP->getVoipVoiceHold()); - ui.qsTransmitMin->setValue(rsVOIP->getVoipfVADmin()); - ui.qsTransmitMax->setValue(rsVOIP->getVoipfVADmax()); - ui.qcbEchoCancel->setChecked(rsVOIP->getVoipEchoCancel()); - //ui.qsDoublePush->setValue(iroundf(static_cast(r.uiDoublePush) / 1000.f + 0.5f)); - - //loadCheckBox(qcbPushClick, r.bPushClick); - //loadSlider(qsQuality, r.iQuality); - if (rsVOIP->getVoipiNoiseSuppress() != 0) - ui.qsNoise->setValue(-rsVOIP->getVoipiNoiseSuppress()); - else - ui.qsNoise->setValue(14); - - on_qsNoise_valueChanged(-rsVOIP->getVoipiNoiseSuppress()); - - ui.qsAmp->setValue(20000 - rsVOIP->getVoipiMinLoudness()); - on_qsAmp_valueChanged(20000 - rsVOIP->getVoipiMinLoudness()); - //loadSlider(qsIdle, r.iIdleTime); - - /*int echo = 0; - if (r.bEcho) - echo = r.bEchoMulti ? 2 : 1; - - loadComboBox(qcbEcho, echo);*/ - connect( ui.qsTransmitHold, SIGNAL( valueChanged ( int ) ), this, SLOT( on_qsTransmitHold_valueChanged(int) ) ); - connect( ui.qsNoise, SIGNAL( valueChanged ( int ) ), this, SLOT( on_qsNoise_valueChanged(int) ) ); - connect( ui.qsAmp, SIGNAL( valueChanged ( int ) ), this, SLOT( on_qsAmp_valueChanged(int) ) ); - connect( ui.qcbTransmit, SIGNAL( currentIndexChanged ( int ) ), this, SLOT( on_qcbTransmit_currentIndexChanged(int) ) ); - loaded = true; - - std::cerr << "AudioInputConfig:: starting video." << std::endl; - videoInput->start() ; -} - -bool AudioInputConfig::save(QString &/*errmsg*/) {//mainly useless beacause saving occurs in realtime - //s.iQuality = qsQuality->value(); - rsVOIP->setVoipiNoiseSuppress((ui.qsNoise->value() == 14) ? 0 : - ui.qsNoise->value()); - rsVOIP->setVoipiMinLoudness(20000 - ui.qsAmp->value()); - rsVOIP->setVoipVoiceHold(ui.qsTransmitHold->value()); - rsVOIP->setVoipfVADmin(ui.qsTransmitMin->value()); - rsVOIP->setVoipfVADmax(ui.qsTransmitMax->value()); - /*s.uiDoublePush = qsDoublePush->value() * 1000;*/ - rsVOIP->setVoipATransmit(static_cast(ui.qcbTransmit->currentIndex() )); - rsVOIP->setVoipEchoCancel(ui.qcbEchoCancel->isChecked()); - - return true; -} - -void AudioInputConfig::on_qsTransmitHold_valueChanged(int v) { - float val = static_cast(v * FRAME_SIZE); - val = val / SAMPLING_RATE; - ui.qlTransmitHold->setText(tr("%1 s").arg(val, 0, 'f', 2)); - rsVOIP->setVoipVoiceHold(v); -} - -void AudioInputConfig::on_qsNoise_valueChanged(int v) { - QPalette pal; - - if (v < 15) { - ui.qlNoise->setText(tr("Off")); - pal.setColor(ui.qlNoise->foregroundRole(), Qt::red); - } else { - ui.qlNoise->setText(tr("-%1 dB").arg(v)); - } - ui.qlNoise->setPalette(pal); - rsVOIP->setVoipiNoiseSuppress(- ui.qsNoise->value()); -} - -void AudioInputConfig::on_qsAmp_valueChanged(int v) { - v = 20000 - v; - float d = 20000.0f/static_cast(v); - ui.qlAmp->setText(QString::fromLatin1("%1").arg(d, 0, 'f', 2)); - rsVOIP->setVoipiMinLoudness(20000 - ui.qsAmp->value()); -} - -void AudioInputConfig::on_qcbEchoCancel_clicked() { - rsVOIP->setVoipEchoCancel(ui.qcbEchoCancel->isChecked()); -} - - -void AudioInputConfig::on_qcbTransmit_currentIndexChanged(int v) { - switch (v) { - case 0: - ui.qswTransmit->setCurrentWidget(ui.qwContinuous); - break; - case 1: - ui.qswTransmit->setCurrentWidget(ui.qwVAD); - break; - case 2: - ui.qswTransmit->setCurrentWidget(ui.qwPTT); - break; - } - if (loaded) - rsVOIP->setVoipATransmit(static_cast(ui.qcbTransmit->currentIndex() )); -} - - -void AudioInputConfig::on_Tick_timeout() -{ - if (!inputAudioProcessor) - { - inputAudioProcessor = new QtSpeex::SpeexInputProcessor(); - inputAudioProcessor->open(QIODevice::WriteOnly | QIODevice::Unbuffered); - - if (!inputAudioDevice) { - inputAudioDevice = AudioDeviceHelper::getPreferedInputDevice(); - } - inputAudioDevice->start(inputAudioProcessor); - connect(inputAudioProcessor, SIGNAL(networkPacketReady()), this, SLOT(emptyBuffer())); - } - - abSpeech->iBelow = ui.qsTransmitMin->value(); - abSpeech->iAbove = ui.qsTransmitMax->value(); - if (loaded) { - rsVOIP->setVoipfVADmin(ui.qsTransmitMin->value()); - rsVOIP->setVoipfVADmax(ui.qsTransmitMax->value()); - } - - abSpeech->iValue = iroundf(inputAudioProcessor->dVoiceAcivityLevel * 32767.0f + 0.5f); - - abSpeech->update(); - - // also transmit encoded video - RsVOIPDataChunk chunk ; - - while((!videoInput->stopped()) && videoInput->getNextEncodedPacket(chunk)) - { - videoProcessor->receiveEncodedData(chunk) ; - chunk.clear() ; - } -} - -void AudioInputConfig::emptyBuffer() { - while(inputAudioProcessor->hasPendingPackets()) { - inputAudioProcessor->getNetworkPacket(); //that will purge the buffer - } -} - -void AudioInputConfig::on_qpbAudioWizard_clicked() { - AudioWizard aw(this); - aw.exec(); - loadSettings(); -} diff --git a/plugins/VOIP/gui/AudioStats.cpp b/plugins/VOIP/gui/AudioStats.cpp index 536cf0a1d..96ea93b83 100644 --- a/plugins/VOIP/gui/AudioStats.cpp +++ b/plugins/VOIP/gui/AudioStats.cpp @@ -25,7 +25,7 @@ #include #include "AudioStats.h" -#include "AudioInputConfig.h" +#include "VOIPConfigPanel.h" //#include "Global.h" //#include "smallft.h" diff --git a/plugins/VOIP/gui/AudioWizard.cpp b/plugins/VOIP/gui/AudioWizard.cpp index cbf24d9b4..8c0841d1f 100644 --- a/plugins/VOIP/gui/AudioWizard.cpp +++ b/plugins/VOIP/gui/AudioWizard.cpp @@ -104,8 +104,8 @@ AudioWizard::AudioWizard(QWidget *p) : QWizard(p) { iMaxPeak = 0; iTicks = 0; - qpTalkingOn = QPixmap::fromImage(QImage(QLatin1String("skin:talking_on.svg")).scaled(64,64)); - qpTalkingOff = QPixmap::fromImage(QImage(QLatin1String("skin:talking_off.svg")).scaled(64,64)); + qpTalkingOn = QPixmap::fromImage(QImage(QLatin1String(":/images/talking_on.svg")).scaled(64,64)); + qpTalkingOff = QPixmap::fromImage(QImage(QLatin1String(":/images/talking_off.svg")).scaled(64,64)); bInit = false; diff --git a/plugins/VOIP/gui/AudioWizard.ui b/plugins/VOIP/gui/AudioWizard.ui index dfe9578f6..22d848fc4 100644 --- a/plugins/VOIP/gui/AudioWizard.ui +++ b/plugins/VOIP/gui/AudioWizard.ui @@ -202,7 +202,16 @@ - + + 0 + + + 0 + + + 0 + + 0 diff --git a/plugins/VOIP/gui/QVideoDevice.cpp b/plugins/VOIP/gui/QVideoDevice.cpp index 1a3d084db..fb81b84e2 100644 --- a/plugins/VOIP/gui/QVideoDevice.cpp +++ b/plugins/VOIP/gui/QVideoDevice.cpp @@ -18,15 +18,18 @@ * * *******************************************************************************/ -#include -#include -#include - #include #include +#include +#include +#include +#include +#include #include "QVideoDevice.h" #include "VideoProcessor.h" +// #define DEBUG_QVIDEODEVICE 1 + QVideoInputDevice::QVideoInputDevice(QWidget *parent) :QObject(parent) { @@ -34,18 +37,31 @@ QVideoInputDevice::QVideoInputDevice(QWidget *parent) _capture_device = NULL ; _video_processor = NULL ; _echo_output_device = NULL ; + _image_capture = NULL; } -bool QVideoInputDevice::stopped() +QVideoInputDevice::~QVideoInputDevice() +{ + stop() ; + _video_processor = NULL ; + + delete _image_capture; + delete _capture_device; + delete _timer; +} + +bool QVideoInputDevice::stopped() const { return _timer == NULL ; } void QVideoInputDevice::stop() { + _capture_device_info = QCameraInfo(); + if(_timer != NULL) { - QObject::disconnect(_timer,SIGNAL(timeout()),this,SLOT(grabFrame())) ; + _capture_device->stop(); _timer->stop() ; delete _timer ; _timer = NULL ; @@ -53,57 +69,122 @@ void QVideoInputDevice::stop() if(_capture_device != NULL) { // the camera will be deinitialized automatically in VideoCapture destructor - _capture_device->release(); - delete _capture_device ; + delete _image_capture ; + delete _capture_device ; + _capture_device = NULL ; - } + _image_capture = NULL ; + } + if(_echo_output_device != NULL) + _echo_output_device->showFrameOff() ; } -void QVideoInputDevice::start() +void QVideoInputDevice::getAvailableDevices(QList& device_desc) +{ + device_desc.clear(); + + QList dev_list = QCameraInfo::availableCameras(); + + for(auto& cam:dev_list) + device_desc.push_back(cam.deviceName()); +} + +void QVideoInputDevice::start(const QString& description) { // make sure everything is re-initialised // stop() ; - // Initialise la capture - static const int cam_id = 0 ; - _capture_device = new cv::VideoCapture(cam_id); + QCameraInfo caminfo ; - if(!_capture_device->isOpened()) - { - std::cerr << "Cannot initialise camera. Something's wrong." << std::endl; - return ; - } + if(description.isNull()) + caminfo = QCameraInfo::defaultCamera(); + else + { + auto cam_list = QCameraInfo::availableCameras(); - _timer = new QTimer ; - QObject::connect(_timer,SIGNAL(timeout()),this,SLOT(grabFrame())) ; + for(auto& s:cam_list) + if(s.deviceName() == description) + caminfo = s; + } - _timer->start(50) ; // 10 images per second. + if(caminfo.isNull()) + { + std::cerr << "No video camera available in this system!" << std::endl; + return ; + } + _capture_device_info = caminfo; + _capture_device = new QCamera(caminfo); + + if(_capture_device->error() != QCamera::NoError) + { + emit cameraCaptureInfo(CANNOT_INITIALIZE_CAMERA,_capture_device->error()); + std::cerr << "Cannot initialise camera. Something's wrong." << std::endl; + return; + } + _capture_device->setCaptureMode(QCamera::CaptureStillImage); + + if(_capture_device->error() == QCamera::NoError) + emit cameraCaptureInfo(CAMERA_IS_READY,QCamera::NoError); + + _image_capture = new QCameraImageCapture(_capture_device); + + if(!_image_capture->isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer)) + { + emit cameraCaptureInfo(CAMERA_IS_READY,QCamera::NoError); + + delete _capture_device; + delete _image_capture; + return; + } + + _image_capture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer); + + QObject::connect(_image_capture,SIGNAL(imageAvailable(int,QVideoFrame)),this,SLOT(grabFrame(int,QVideoFrame))); + QObject::connect(this,SIGNAL(cameraCaptureInfo(CameraStatus,QCamera::Error)),this,SLOT(errorHandling(CameraStatus,QCamera::Error))); + + _timer = new QTimer ; + QObject::connect(_timer,SIGNAL(timeout()),_image_capture,SLOT(capture())) ; + + _timer->start(50) ; // 10 images per second. + + _capture_device->start(); } -void QVideoInputDevice::grabFrame() +void QVideoInputDevice::errorHandling(CameraStatus status,QCamera::Error error) { - if(!_timer) - return ; - - cv::Mat frame; - if(!_capture_device->read(frame)) +#ifdef DEBUG_QVIDEODEVICE + std::cerr << "Received msg from camera capture: status=" << (int)status << " error=" << (int)error << std::endl; +#else + Q_UNUSED(error); +#endif + if(status == CANNOT_INITIALIZE_CAMERA) { - std::cerr << "(EE) Cannot capture image from camera. Something's wrong." << std::endl; - return ; + std::cerr << "Cannot initialize camera. Make sure to install package libqt5multimedia5-plugins, as this is a common cause for camera not being found." << std::endl; + } +} + +void QVideoInputDevice::grabFrame(int id,QVideoFrame frame) +{ + if(frame.size().isEmpty()) + { + std::cerr << "Empty frame!" ; + return; } - // get the image data + frame.map(QAbstractVideoBuffer::ReadOnly); + QByteArray data((const char *)frame.bits(), frame.mappedBytes()); + QBuffer buffer; + buffer.setData(data); + buffer.open(QIODevice::ReadOnly); + QImageReader reader(&buffer, "JPG"); + reader.setScaledSize(QSize(640,480)); + QImage image(reader.read()); - if(frame.channels() != 3) - { - std::cerr << "(EE) expected 3 channels. Got " << frame.channels() << std::endl; - return ; - } - - // convert to RGB and copy to new buffer, because cvQueryFrame tells us to not modify the buffer - cv::Mat img_rgb; - cv::cvtColor(frame, img_rgb, CV_BGR2RGB); - QImage image = QImage(img_rgb.data,img_rgb.cols,img_rgb.rows,QImage::Format_RGB888); +#ifdef DEBUG_QVIDEODEVICE + std::cerr << "Frame " << id << ". Pixel format: " << frame.pixelFormat() << ". Size: " << image.size().width() << " x " << image.size().height() << std::endl; // if(frame.pixelFormat() != QVideoFrame::Format_Jpeg) +#else + Q_UNUSED(id); +#endif if(_video_processor != NULL) { @@ -128,16 +209,12 @@ bool QVideoInputDevice::getNextEncodedPacket(RsVOIPDataChunk& chunk) uint32_t QVideoInputDevice::currentBandwidth() const { - return _video_processor->currentBandwidthOut() ; + if(stopped()) + return 0; + else + return _video_processor->currentBandwidthOut() ; } -QVideoInputDevice::~QVideoInputDevice() -{ - stop() ; - _video_processor = NULL ; -} - - QVideoOutputDevice::QVideoOutputDevice(QWidget *parent) : QLabel(parent) { @@ -152,7 +229,9 @@ void QVideoOutputDevice::showFrameOff() void QVideoOutputDevice::showFrame(const QImage& img) { +#ifdef DEBUG_QVIDEODEVICE std::cerr << "img.size = " << img.width() << " x " << img.height() << std::endl; +#endif setPixmap(QPixmap::fromImage(img).scaled( QSize(height()*4/3,height()),Qt::IgnoreAspectRatio,Qt::SmoothTransformation)) ; } diff --git a/plugins/VOIP/gui/QVideoDevice.h b/plugins/VOIP/gui/QVideoDevice.h index e0c21778e..63d83b4e1 100644 --- a/plugins/VOIP/gui/QVideoDevice.h +++ b/plugins/VOIP/gui/QVideoDevice.h @@ -21,13 +21,14 @@ #pragma once #include +#include +#include #include "interface/rsVOIP.h" -#include "opencv2/opencv.hpp" - #include "gui/VideoProcessor.h" class VideoEncoder ; +class QCameraImageCapture; // Responsible from displaying the video. The source of the video is // a VideoDecoder object, which uses a codec. @@ -49,7 +50,7 @@ class QVideoInputDevice: public QObject Q_OBJECT public: - QVideoInputDevice(QWidget *parent = 0) ; + QVideoInputDevice(QWidget *parent = 0) ; ~QVideoInputDevice() ; // Captured images are sent to this encoder. Can be NULL. @@ -71,19 +72,35 @@ class QVideoInputDevice: public QObject // control - void start() ; + void start(const QString &description = QString()) ; void stop() ; - bool stopped(); + bool stopped() const; + + enum CameraStatus { + CAMERA_IS_READY = 0x00, + CANNOT_INITIALIZE_CAMERA = 0x01, + CAMERA_CANNOT_GRAB_FRAMES = 0x02 + }; + + // Gets the list of available devices. The id string for each device can be used when creating a QVideoDevice + + static void getAvailableDevices(QList& device_desc); + + QString currentCameraDescriptionString() const { return _capture_device_info.deviceName(); } protected slots: - void grabFrame() ; + void grabFrame(int id, QVideoFrame f) ; + void errorHandling(CameraStatus status,QCamera::Error error); signals: void networkPacketReady() ; + void cameraCaptureInfo(CameraStatus status,QCamera::Error qt_cam_err_code); private: VideoProcessor *_video_processor ; QTimer *_timer ; - cv::VideoCapture *_capture_device ; + QCamera *_capture_device; + QCameraImageCapture *_image_capture; + QCameraInfo _capture_device_info; QVideoOutputDevice *_echo_output_device ; diff --git a/plugins/VOIP/gui/VOIPConfigPanel.cpp b/plugins/VOIP/gui/VOIPConfigPanel.cpp new file mode 100644 index 000000000..a9912af8b --- /dev/null +++ b/plugins/VOIP/gui/VOIPConfigPanel.cpp @@ -0,0 +1,473 @@ +/******************************************************************************* + * plugins/VOIP/gui/AudioInputConfig.h * + * * + * Copyright (C) 2008, Andreas Messer * + * Copyright (C) 2005-2010 Thorvald Natvig * + * Copyright (C) 2012 by Retroshare Team * + * * + * 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 . * + * * + *******************************************************************************/ + +#include "AudioStats.h" +#include "VOIPConfigPanel.h" +#include "audiodevicehelper.h" +#include "AudioWizard.h" +#include "gui/VideoProcessor.h" +#include "gui/VideoProcessor.h" +#include "util/misc.h" +#include "util/RsProtectedTimer.h" + +#include + +#define iroundf(x) ( static_cast(x) ) + +class voipGraphSource: public RSGraphSource +{ +public: + voipGraphSource() : video_input(NULL) {} + + void setVideoInput(const QVideoInputDevice *vid) { video_input = vid ; } + + virtual QString displayName(int) const { return tr("Required bandwidth") ;} + + virtual QString displayValue(float v) const + { + if(v < 1000) + return QString::number(v,10,2) + " B/s" ; + else if(v < 1000*1024) + return QString::number(v/1024,10,2) + " KB/s" ; + else + return QString::number(v/(1024*1024),10,2) + " MB/s" ; + } + + virtual void getValues(std::map& vals) const + { + vals.clear() ; + + if(video_input) + vals[std::string("bw")] = video_input->currentBandwidth() ; + } + +private: + const QVideoInputDevice *video_input ; +}; + +void voipGraph::setVoipSource(voipGraphSource *gs) +{ +_src = gs ; +RSGraphWidget::setSource(gs) ; +} + +voipGraph::voipGraph(QWidget *parent) + : RSGraphWidget(parent) +{ + setFlags(RSGraphWidget::RSGRAPH_FLAGS_SHOW_LEGEND) ; + setFlags(RSGraphWidget::RSGRAPH_FLAGS_PAINT_STYLE_PLAIN) ; + + _src = NULL ; +} + +/** Constructor */ +VOIPConfigPanel::VOIPConfigPanel(QWidget * parent, Qt::WindowFlags flags) + : ConfigPage(parent, flags) +{ + std::cerr << "Creating audioInputConfig object" << std::endl; + + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + loaded = false; + + inputAudioProcessor = NULL; + inputAudioDevice = NULL; + graph_source = nullptr; + videoInput = nullptr; + videoProcessor = nullptr; + qtTick = NULL; + + ui.qcbTransmit->addItem(tr("Continuous"), RsVOIP::AudioTransmitContinous); + ui.qcbTransmit->addItem(tr("Voice Activity"), RsVOIP::AudioTransmitVAD); + ui.qcbTransmit->addItem(tr("Push To Talk"), RsVOIP::AudioTransmitPushToTalk); + + ui.abSpeech->qcBelow = Qt::red; + ui.abSpeech->qcInside = Qt::yellow; + ui.abSpeech->qcAbove = Qt::green; + + QList input_devices; + QVideoInputDevice::getAvailableDevices(input_devices); + ui.inputDevice_CB->clear(); + ui.inputDevice_CB->addItem(tr("[No video]"),QString("")); + for(auto& s:input_devices) + ui.inputDevice_CB->addItem(s,QVariant(s)); + + if(!input_devices.empty()) + whileBlocking(ui.inputDevice_CB)->setCurrentIndex(1); // select default cam + + connect( ui.qsTransmitHold, SIGNAL( valueChanged ( int ) ), this, SLOT( on_qsTransmitHold_valueChanged(int) ) ); + connect( ui.qsNoise, SIGNAL( valueChanged ( int ) ), this, SLOT( on_qsNoise_valueChanged(int) ) ); + connect( ui.qsAmp, SIGNAL( valueChanged ( int ) ), this, SLOT( on_qsAmp_valueChanged(int) ) ); + connect( ui.qcbTransmit, SIGNAL( currentIndexChanged ( int ) ), this, SLOT( on_qcbTransmit_currentIndexChanged(int) ) ); + connect( ui.inputDevice_CB, SIGNAL( currentIndexChanged ( int ) ), this, SLOT( on_changedCurrentInputDevice(int) ) ); +} + +void VOIPConfigPanel::showEvent(QShowEvent *) +{ + std::cerr << "Creating the audio pipeline" << std::endl; + + inputAudioProcessor = new QtSpeex::SpeexInputProcessor(); + inputAudioProcessor->open(QIODevice::WriteOnly | QIODevice::Unbuffered); + + inputAudioDevice = AudioDeviceHelper::getPreferedInputDevice(); + inputAudioDevice->start(inputAudioProcessor); + + connect(inputAudioProcessor, SIGNAL(networkPacketReady()), this, SLOT(emptyBuffer())); + + std::cerr << "Creating the video pipeline" << std::endl; + + // Create the video pipeline. + // + + videoInput = new QVideoInputDevice(this) ; + + videoProcessor = new VideoProcessor() ; + videoProcessor->setDisplayTarget(NULL) ; + + videoProcessor->setMaximumBandwidth(ui.availableBW_SB->value()) ; + + videoInput->setVideoProcessor(videoProcessor) ; + + graph_source = new voipGraphSource ; + ui.voipBwGraph->setSource(graph_source); + + graph_source->setVideoInput(videoInput) ; + graph_source->setCollectionTimeLimit(1000*300) ; + graph_source->start() ; + + if(ui.showEncoded_CB->isChecked()) + { + videoInput->setEchoVideoTarget(nullptr) ; + videoProcessor->setDisplayTarget(ui.videoDisplay) ; + } + else + { + videoInput->setEchoVideoTarget(ui.videoDisplay) ; + videoProcessor->setDisplayTarget(nullptr); + } + + QObject::connect(ui.showEncoded_CB,SIGNAL(toggled(bool)),this,SLOT(togglePreview(bool))) ; + QObject::connect(ui.availableBW_SB,SIGNAL(valueChanged(double)),this,SLOT(updateAvailableBW(double))) ; + + loadSettings(); + + qtTick = new RsProtectedTimer(this); + connect( qtTick, SIGNAL( timeout ( ) ), this, SLOT( on_Tick_timeout() ) ); + qtTick->start(20); + + videoInput->start(); +} + +void VOIPConfigPanel::hideEvent(QHideEvent *) +{ + std::cerr << "Deleting the video pipeline" << std::endl; + + clearPipeline(); +} + +void VOIPConfigPanel::updateAvailableBW(double r) +{ + std::cerr << "Setting max bandwidth to " << r << " KB/s" << std::endl; + videoProcessor->setMaximumBandwidth((uint32_t)(r*1024)) ; +} + +void VOIPConfigPanel::togglePreview(bool b) +{ + if(b) + { + videoInput->setEchoVideoTarget(NULL) ; + videoProcessor->setDisplayTarget(ui.videoDisplay) ; + } + else + { + videoProcessor->setDisplayTarget(NULL) ; + videoInput->setEchoVideoTarget(ui.videoDisplay) ; + } +} + +VOIPConfigPanel::~VOIPConfigPanel() +{ + clearPipeline(); +} + +void VOIPConfigPanel::clearPipeline() +{ + if (qtTick) { + delete qtTick; + qtTick = nullptr; + } + + if (graph_source) { + graph_source->stop() ; + graph_source->setVideoInput(NULL) ; + graph_source=nullptr; // is deleted by setSource below. This is a bad design. + } + + ui.voipBwGraph->setSource(nullptr); + + std::cerr << "Deleting audioInputConfig object" << std::endl; + if(videoInput != NULL) + { + videoInput->stop() ; + delete videoInput ; + + videoInput = nullptr; + } + if (videoProcessor) { + delete videoProcessor; + videoProcessor = nullptr; + } + + if (inputAudioDevice) { + inputAudioDevice->stop(); + delete inputAudioDevice ; + inputAudioDevice = nullptr ; + } + + if(inputAudioProcessor) + { + delete inputAudioProcessor ; + inputAudioProcessor = nullptr ; + } +} + +void VOIPConfigPanel::load() +{ +} + +/** Loads the settings for this page */ + +void VOIPConfigPanel::loadSettings() +{ + ui.qcbTransmit->setCurrentIndex(rsVOIP->getVoipATransmit()); + on_qcbTransmit_currentIndexChanged(rsVOIP->getVoipATransmit()); + ui.qsTransmitHold->setValue(rsVOIP->getVoipVoiceHold()); + on_qsTransmitHold_valueChanged(rsVOIP->getVoipVoiceHold()); + ui.qsTransmitMin->setValue(rsVOIP->getVoipfVADmin()); + ui.qsTransmitMax->setValue(rsVOIP->getVoipfVADmax()); + ui.qcbEchoCancel->setChecked(rsVOIP->getVoipEchoCancel()); + + if (rsVOIP->getVoipiNoiseSuppress() != 0) + ui.qsNoise->setValue(-rsVOIP->getVoipiNoiseSuppress()); + else + ui.qsNoise->setValue(14); + + on_qsNoise_valueChanged(-rsVOIP->getVoipiNoiseSuppress()); + + ui.qsAmp->setValue(20000 - rsVOIP->getVoipiMinLoudness()); + on_qsAmp_valueChanged(20000 - rsVOIP->getVoipiMinLoudness()); + + loaded = true; +} + +bool VOIPConfigPanel::save(QString &/*errmsg*/) +{ + //mainly useless beacause saving occurs in realtime + //s.iQuality = qsQuality->value(); + rsVOIP->setVoipiNoiseSuppress((ui.qsNoise->value() == 14) ? 0 : - ui.qsNoise->value()); + rsVOIP->setVoipiMinLoudness(20000 - ui.qsAmp->value()); + rsVOIP->setVoipVoiceHold(ui.qsTransmitHold->value()); + rsVOIP->setVoipfVADmin(ui.qsTransmitMin->value()); + rsVOIP->setVoipfVADmax(ui.qsTransmitMax->value()); + /*s.uiDoublePush = qsDoublePush->value() * 1000;*/ + rsVOIP->setVoipATransmit(static_cast(ui.qcbTransmit->currentIndex() )); + rsVOIP->setVoipEchoCancel(ui.qcbEchoCancel->isChecked()); + + return true; +} + +void VOIPConfigPanel::on_qsTransmitHold_valueChanged(int v) { + float val = static_cast(v * FRAME_SIZE); + val = val / SAMPLING_RATE; + ui.qlTransmitHold->setText(tr("%1 s").arg(val, 0, 'f', 2)); + rsVOIP->setVoipVoiceHold(v); +} + +void VOIPConfigPanel::on_qsNoise_valueChanged(int v) { + QPalette pal; + + if (v < 15) { + ui.qlNoise->setText(tr("Off")); + pal.setColor(ui.qlNoise->foregroundRole(), Qt::red); + } else { + ui.qlNoise->setText(tr("-%1 dB").arg(v)); + } + ui.qlNoise->setPalette(pal); + rsVOIP->setVoipiNoiseSuppress(- ui.qsNoise->value()); +} + +void VOIPConfigPanel::on_qsAmp_valueChanged(int v) { + v = 20000 - v; + float d = 20000.0f/static_cast(v); + ui.qlAmp->setText(QString::fromLatin1("%1").arg(d, 0, 'f', 2)); + rsVOIP->setVoipiMinLoudness(20000 - ui.qsAmp->value()); +} + +void VOIPConfigPanel::on_qcbEchoCancel_clicked() { + rsVOIP->setVoipEchoCancel(ui.qcbEchoCancel->isChecked()); +} + + +void VOIPConfigPanel::on_qcbTransmit_currentIndexChanged(int v) { + switch (v) { + case 0: + ui.qswTransmit->setCurrentWidget(ui.qwContinuous); + break; + case 1: + ui.qswTransmit->setCurrentWidget(ui.qwVAD); + break; + case 2: + ui.qswTransmit->setCurrentWidget(ui.qwPTT); + break; + } + if (loaded) + rsVOIP->setVoipATransmit(static_cast(ui.qcbTransmit->currentIndex() )); +} + + +void VOIPConfigPanel::on_Tick_timeout() +{ + // update the sound capture bar + + ui.abSpeech->iBelow = ui.qsTransmitMin->value(); + ui.abSpeech->iAbove = ui.qsTransmitMax->value(); + + if (loaded) { + rsVOIP->setVoipfVADmin(ui.qsTransmitMin->value()); + rsVOIP->setVoipfVADmax(ui.qsTransmitMax->value()); + } + + ui.abSpeech->iValue = iroundf(inputAudioProcessor->dVoiceAcivityLevel * 32767.0f + 0.5f); + ui.abSpeech->update(); + + // also transmit encoded video + + RsVOIPDataChunk chunk ; + + while((!videoInput->stopped()) && videoInput->getNextEncodedPacket(chunk)) + { + videoProcessor->receiveEncodedData(chunk) ; + chunk.clear() ; + } +} + +void VOIPConfigPanel::emptyBuffer() { + while(inputAudioProcessor->hasPendingPackets()) { + inputAudioProcessor->getNetworkPacket(); //that will purge the buffer + } +} + +void VOIPConfigPanel::on_qpbAudioWizard_clicked() { + AudioWizard aw(this); + aw.exec(); + loadSettings(); +} + +void VOIPConfigPanel::on_changedCurrentInputDevice(int i) +{ + QString s = dynamic_cast(sender())->itemData(i).toString(); + + videoInput->stop(); + + // check that the camera still exists + + QList input_devices; + QVideoInputDevice::getAvailableDevices(input_devices); + + for(const QString& cams:input_devices) + if(s == cams) + { + std::cerr << "Switching to camera \"" << s.toStdString() << "\"" << std::endl; + + videoInput->start(s); + + return; + } + + // if not, re-create the ComboBox + + checkAvailableCameras(); +} + +void VOIPConfigPanel::checkAvailableCameras() +{ + // save current camera + QString current_cam = videoInput->currentCameraDescriptionString(); + + // Check that the list of cams we had previously is the same than the list of available camera. + + QList input_devices; + QVideoInputDevice::getAvailableDevices(input_devices); + + bool same = true; + if(input_devices.size() != ui.inputDevice_CB->count()) + same = false; + + if(same) + { + int n=0; + for(auto& s:input_devices) + { + if(ui.inputDevice_CB->itemData(n).toString() != s) + { + same = false; + break; + } + n++; + } + } + + // If not, re-add them to the comboBox and make sure to re-select the same camera. + + if(!same) + { + whileBlocking(ui.inputDevice_CB)->clear(); // remove existing entries + whileBlocking(ui.inputDevice_CB)->addItem(tr("[No video]"),QString("")); + int n=0; + int found_index = -1; + + for(auto& s:input_devices) + { + whileBlocking(ui.inputDevice_CB)->addItem(s,QVariant(s)); + + if(s == current_cam) + found_index = n; + + n++; + } + + if(found_index >= 0) + ui.inputDevice_CB->setCurrentIndex(found_index); + else + ui.inputDevice_CB->setCurrentIndex(0); // no video + } +} + + + + + + + + + diff --git a/plugins/VOIP/gui/AudioInputConfig.h b/plugins/VOIP/gui/VOIPConfigPanel.h similarity index 77% rename from plugins/VOIP/gui/AudioInputConfig.h rename to plugins/VOIP/gui/VOIPConfigPanel.h index 3dd2cecae..dcfc0323b 100644 --- a/plugins/VOIP/gui/AudioInputConfig.h +++ b/plugins/VOIP/gui/VOIPConfigPanel.h @@ -19,7 +19,6 @@ * * *******************************************************************************/ #pragma once -#pragma once #include #include @@ -46,9 +45,9 @@ private: voipGraphSource *_src ; }; -#include "ui_AudioInputConfig.h" +#include "ui_VOIPConfigPanel.h" -class AudioInputConfig : public ConfigPage +class VOIPConfigPanel : public ConfigPage { Q_OBJECT @@ -60,33 +59,37 @@ class AudioInputConfig : public ConfigPage //VideoDecoder *videoDecoder ; //VideoEncoder *videoEncoder ; QVideoInputDevice *videoInput ; - VideoProcessor *videoProcessor ; + VideoProcessor *videoProcessor ; bool loaded; + QString currentCameraDescription; voipGraphSource *graph_source ; protected: QTimer *qtTick; - /*void hideEvent(QHideEvent *event); - void showEvent(QShowEvent *event);*/ + void clearPipeline(); public: /** Default Constructor */ - AudioInputConfig(QWidget * parent = 0, Qt::WindowFlags flags = 0); + VOIPConfigPanel(QWidget * parent = 0, Qt::WindowFlags flags = 0); /** Default Destructor */ - ~AudioInputConfig(); + ~VOIPConfigPanel(); /** Saves the changes on this page */ - virtual bool save(QString &errmsg); + virtual bool save(QString &errmsg)override ; /** Loads the settings for this page */ - virtual void load(); + virtual void load()override ; - virtual QPixmap iconPixmap() const { return QPixmap(":/images/talking_on.svg") ; } - virtual QString pageName() const { return tr("VOIP") ; } - virtual QString helpText() const { return ""; } + virtual QPixmap iconPixmap() const override { return QPixmap(":/images/talking_on.svg") ; } + virtual QString pageName() const override { return tr("VOIP") ; } + virtual QString helpText() const override { return ""; } + virtual void showEvent(QShowEvent *) override; + virtual void hideEvent(QHideEvent *event) override; private slots: - void updateAvailableBW(double r); + void on_changedCurrentInputDevice(int i); + void checkAvailableCameras(); + void updateAvailableBW(double r); void loadSettings(); void emptyBuffer(); void togglePreview(bool) ; diff --git a/plugins/VOIP/gui/AudioInputConfig.ui b/plugins/VOIP/gui/VOIPConfigPanel.ui similarity index 55% rename from plugins/VOIP/gui/AudioInputConfig.ui rename to plugins/VOIP/gui/VOIPConfigPanel.ui index 62e8c98a6..9fbb9008c 100644 --- a/plugins/VOIP/gui/AudioInputConfig.ui +++ b/plugins/VOIP/gui/VOIPConfigPanel.ui @@ -10,50 +10,289 @@ 832 - + - - - Audio Wizard + + + Video + + + + + + + + 170 + 128 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + Input device: + + + + + + + + + + + 0 + 0 + + + + Available bandwidth: + + + + + + + <html><head/><body><p>Use this field to simulate the maximum bandwidth available so as to preview what the encoded video will look like with the corresponding compression rate.</p></body></html> + + + KB/s + + + 1 + + + 2.000000000000000 + + + 200.000000000000000 + + + 30.000000000000000 + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Display encoded (and then decoded) frame, to check the codec's quality. If not selected, the image above only shows the frame that is grabbed from your camera.</p></body></html> + + + preview + + + + + + - - - - 0 - 0 - - + - Transmission + Audio - - - - - &Transmit + + + + + + 30 + 0 + - - qcbTransmit + + - - + + + + true + - When to transmit your speech + Noise suppression - <b>This sets when speech should be transmitted.</b><br /><i>Continuous</i> - All the time<br /><i>Voice Activity</i> - When you are speaking clearly.<br /><i>Push To Talk</i> - When you hold down the hotkey set under <i>Shortcuts</i>. + <b>This sets the amount of noise suppression to apply.</b><br />The higher this value, the more aggressively stationary noise will be suppressed. + + + 14 + + + 60 + + + 5 + + + Qt::Horizontal - + + + + Noise Suppression + + + qsNoise + + + + + + + + 30 + 0 + + + + + + + + + + + Maximum amplification of input sound + + + <b>Maximum amplification of input.</b><br />RetroShare normalizes the input volume before compressing, and this sets how much it's allowed to amplify.<br />The actual level is continually updated based on your current speech pattern, but it will never go above the level specified here.<br />If the <i>Microphone loudness</i> level of the audio statistics hover around 100%, you probably want to set this to 2.0 or so, but if, like most people, you are unable to reach 100%, set this to something much higher.<br />Ideally, set it so <i>Microphone Loudness * Amplification Factor >= 100</i>, even when you're speaking really soft.<br /><br />Note that there is no harm in setting this to maximum, but RetroShare will start picking up other conversations if you leave it to auto-tune to that level. + + + 19500 + + + 500 + + + 2000 + + + Qt::Horizontal + + + + + + + Amplification + + + qsAmp + + + + + + + + + + 0 + 0 + + + + Echo Cancellation Processing + + + false + + + + + + + + + + 0 + 0 + + + + &Transmit: + + + qcbTransmit + + + + + + + When to transmit your speech + + + <b>This sets when speech should be transmitted.</b><br /><i>Continuous</i> - All the time<br /><i>Voice Activity</i> - When you are speaking clearly.<br /><i>Push To Talk</i> - When you hold down the hotkey set under <i>Shortcuts</i>. + + + + + + + + + + 0 + 0 + + + + Audio Wizard + + + + + + + + + 0 + 0 + + - 2 + 1 @@ -231,218 +470,21 @@ - - - - - - - - - Audio Processing - - - - - - Noise Suppression - - - qsNoise - - - - - - - true - - - Noise suppression - - - <b>This sets the amount of noise suppression to apply.</b><br />The higher this value, the more aggressively stationary noise will be suppressed. - - - 14 - - - 60 - - - 5 - - - Qt::Horizontal - - - - - - - - 30 - 0 - - - - - - - - - - - Amplification - - - qsAmp - - - - - - - Maximum amplification of input sound - - - <b>Maximum amplification of input.</b><br />RetroShare normalizes the input volume before compressing, and this sets how much it's allowed to amplify.<br />The actual level is continually updated based on your current speech pattern, but it will never go above the level specified here.<br />If the <i>Microphone loudness</i> level of the audio statistics hover around 100%, you probably want to set this to 2.0 or so, but if, like most people, you are unable to reach 100%, set this to something much higher.<br />Ideally, set it so <i>Microphone Loudness * Amplification Factor >= 100</i>, even when you're speaking really soft.<br /><br />Note that there is no harm in setting this to maximum, but RetroShare will start picking up other conversations if you leave it to auto-tune to that level. - - - 19500 - - - 500 - - - 2000 - - - Qt::Horizontal - - - - - - - - 30 - 0 - - - - - - - - - - - Echo Cancellation Processing - - - false - - - - - - - - - - - - Video Processing - - - - - - 170 - 128 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - + - - - - - Available bandwidth: - - - - - - - <html><head/><body><p>Use this field to simulate the maximum bandwidth available so as to preview what the encoded video will look like with the corresponding compression rate.</p></body></html> - - - KB/s - - - 1 - - - 2.000000000000000 - - - 200.000000000000000 - - - 30.000000000000000 - - - - - - - - - <html><head/><body><p>Display encoded (and then decoded) frame, to check the codec's quality. If not selected, the image above only shows the frame that is grabbed from your camera.</p></body></html> - - - preview - - - - - + Qt::Vertical - 1 - 151 + 20 + 40 @@ -459,12 +501,22 @@ voipGraph QFrame -
gui/AudioInputConfig.h
+
gui/VOIPConfigPanel.h
1
+ + AudioBar + QWidget +
gui/AudioStats.h
+ 1 +
+ + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
- qcbTransmit qsDoublePush qsTransmitHold qsTransmitMin diff --git a/plugins/VOIP/gui/VOIPToasterItem.ui b/plugins/VOIP/gui/VOIPToasterItem.ui index ef1a3e402..676e787e2 100644 --- a/plugins/VOIP/gui/VOIPToasterItem.ui +++ b/plugins/VOIP/gui/VOIPToasterItem.ui @@ -22,7 +22,7 @@ 102 - + 0 @@ -39,14 +39,14 @@ 0 - + QFrame::WinPanel QFrame::Raised - + 2 @@ -63,7 +63,7 @@ 2 - + 6 @@ -97,13 +97,20 @@ + + + 12 + 75 + true + + RetroShare - + Qt::Horizontal @@ -141,7 +148,7 @@ - + 6 @@ -240,7 +247,7 @@ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 0.67, - + 0 @@ -255,6 +262,7 @@ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 0.67, + 12 75 true @@ -272,11 +280,6 @@ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 0.67, - - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
AvatarWidget QLabel diff --git a/plugins/VOIP/qss/VOIP_Standard.qss b/plugins/VOIP/qss/VOIP_Standard.qss index ee40c6344..851f9af4f 100644 --- a/plugins/VOIP/qss/VOIP_Standard.qss +++ b/plugins/VOIP/qss/VOIP_Standard.qss @@ -1 +1 @@ -/* Standard stylesheet for FeedReader */ +/* Standard stylesheet for VOIP */ diff --git a/plugins/FeedReader/qss/FeedReader_qss.default b/plugins/VOIP/qss/VOIP_default.qss similarity index 51% rename from plugins/FeedReader/qss/FeedReader_qss.default rename to plugins/VOIP/qss/VOIP_default.qss index 27ca35f0c..9b964468c 100644 --- a/plugins/FeedReader/qss/FeedReader_qss.default +++ b/plugins/VOIP/qss/VOIP_default.qss @@ -1,9 +1,3 @@ /* Default stylesheet This file is used as default for all stylesheets and can be overloaded */ -/* Font */ - -FeedReaderFeedItem QLabel#titleLabel -{ - qproperty-fontSizeFactor: 135; -} diff --git a/plugins/VOIP/qss/VOIP_qss.qrc b/plugins/VOIP/qss/VOIP_qss.qrc index f82c259d4..81df6f74d 100644 --- a/plugins/VOIP/qss/VOIP_qss.qrc +++ b/plugins/VOIP/qss/VOIP_qss.qrc @@ -1,6 +1,6 @@ - VOIP_qss.default + VOIP_default.qss VOIP_Standard.qss diff --git a/plugins/plugins.pro b/plugins/plugins.pro index 209b82898..7ecbc32c7 100644 --- a/plugins/plugins.pro +++ b/plugins/plugins.pro @@ -19,5 +19,5 @@ TEMPLATE = subdirs SUBDIRS += \ - VOIP \ + VOIP \ FeedReader diff --git a/retroshare-friendserver/src/friendserver.cc b/retroshare-friendserver/src/friendserver.cc new file mode 100644 index 000000000..3c80bba83 --- /dev/null +++ b/retroshare-friendserver/src/friendserver.cc @@ -0,0 +1,569 @@ +#include "util/rsdebug.h" +#include "util/rsprint.h" +#include "util/rsdir.h" +#include "util/rsbase64.h" +#include "util/radix64.h" + +#include "crypto/hashstream.h" + +#include "pgp/pgpkeyutil.h" +#include "pgp/rscertificate.h" +#ifdef USE_OPENPGPSDK +#include "pgp/openpgpsdkhandler.h" +#else +#include "pgp/rnppgphandler.h" +#endif + +#include "friendserver.h" +#include "friend_server/fsitem.h" + +static const rstime_t MAXIMUM_PEER_INACTIVE_DELAY = 600; +static const rstime_t DELAY_BETWEEN_TWO_AUTOWASH = 60; +static const rstime_t DELAY_BETWEEN_TWO_DEBUG_PRINT = 10; +static const uint32_t MAXIMUM_PEERS_TO_REQUEST = 10; + +void FriendServer::threadTick() +{ + // Listen to the network interface, capture incoming data etc. + + RsItem *item; + + while(nullptr != (item = mni->GetItem())) + { + RsFriendServerItem *fsitem = dynamic_cast(item); + + if(!fsitem) + { + RsErr() << "Received an item of the wrong type!" ; + + continue; + } + std::cerr << "Received item: " << std::endl << *fsitem << std::endl; + + switch(fsitem->PacketSubType()) + { + case RS_PKT_SUBTYPE_FS_CLIENT_PUBLISH: handleClientPublish(dynamic_cast(fsitem)); + break; + case RS_PKT_SUBTYPE_FS_CLIENT_REMOVE: handleClientRemove(dynamic_cast(fsitem)); + break; + default: ; + } + delete item; + } + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + + static rstime_t last_autowash_TS = time(nullptr); + rstime_t now = time(nullptr); + + if(last_autowash_TS + DELAY_BETWEEN_TWO_AUTOWASH < now) + { + last_autowash_TS = now; + autoWash(); + } + + static rstime_t last_debugprint_TS = time(nullptr); + + if(last_debugprint_TS + DELAY_BETWEEN_TWO_DEBUG_PRINT < now) + { + last_debugprint_TS = now; + debugPrint(false); + } +} + +void FriendServer::handleClientPublish(const RsFriendServerClientPublishItem *item) +{ + // We always respond with exactly one item, be it an error item or a list of friends to connect to. + + try + { + RsDbg() << "Received a client publish item from " << item->PeerId() << ":"; + RsDbg() << *item ; + + // First of all, read PGP key and short invites, parse them, and check that they contain the same information + + RsPeerId pid; + + if(!handleIncomingClientData(item->pgp_public_key_b64,item->short_invite,pid)) + { + RsErr() << "Client data is dropped because of error." ; + return ; + } + + // All good. + + auto pi(mCurrentClientPeers.find(pid)); + + // Update the list of closest peers for other peers, based on which known friends it reports, and of current peer depending + // on friendship levels of other peers. + + updateClosestPeers(pi->first,pi->second.pgp_fingerprint,item->already_received_peers); + + RsDbg() << "Sending response item to " << item->PeerId() ; + + RsFriendServerServerResponseItem sr_item; + + std::set friends; + sr_item.unique_identifier = pi->second.last_identifier; + sr_item.friend_invites = computeListOfFriendInvites(pi->first,item->n_requested_friends,item->already_received_peers,friends); + sr_item.PeerId(item->PeerId()); + + RsDbg() << " Got " << sr_item.friend_invites.size() << " closest peers not in the list." ; + RsDbg() << " Updating local information for destination peer." ; + + // Update friendship levels of the peer that will receive the new list + + for(auto fr:friends) + { + auto& p(pi->second.friendship_levels[fr]); + + RsDbg() << " Already a friend: " << fr << ", with local status " << static_cast(p) ; + + if(static_cast(p) < static_cast(RsFriendServer::PeerFriendshipLevel::HAS_KEY)) + { + p = RsFriendServer::PeerFriendshipLevel::HAS_KEY; + RsDbg() << " --> updating status to HAS_KEY" ; + } + } + + // Now encrypt the item with the public PGP key of the destination. This prevents the wrong person to request for + // someone else's data. + + RsDbg() << " Encrypting item..." ; + + RsFriendServerEncryptedServerResponseItem *encrypted_response_item = new RsFriendServerEncryptedServerResponseItem; + uint32_t serialized_clear_size = FsSerializer().size(&sr_item); + RsTemporaryMemory serialized_clear_mem(serialized_clear_size); + FsSerializer().serialise(&sr_item,serialized_clear_mem,&serialized_clear_size); + + uint32_t encrypted_mem_size = serialized_clear_size+1000; // leave some extra space + RsTemporaryMemory encrypted_mem(encrypted_mem_size); + + if(!mPgpHandler->encryptDataBin(PGPHandler::pgpIdFromFingerprint(pi->second.pgp_fingerprint), + serialized_clear_mem,serialized_clear_size, + encrypted_mem,&encrypted_mem_size)) + { + RsErr() << "Cannot encrypt item for PGP Id/FPR " << pi->second.pgp_fingerprint << ". Something went wrong." ; + return; + } + encrypted_response_item->PeerId(item->PeerId()); + encrypted_response_item->bin_len = encrypted_mem_size; + encrypted_response_item->bin_data = malloc(encrypted_mem_size); + + memcpy(encrypted_response_item->bin_data,encrypted_mem,encrypted_mem_size); + + // Send the item. + + RsDbg() << " Sending item..." ; + mni->SendItem(encrypted_response_item); + } + catch(std::exception& e) + { + RsErr() << "ERROR: " << e.what() ; + + RsFriendServerStatusItem *status_item = new RsFriendServerStatusItem; + status_item->status = RsFriendServerStatusItem::END_OF_TRANSMISSION; + status_item->PeerId(item->PeerId()); + mni->SendItem(status_item); + return; + } +} + +std::map FriendServer::computeListOfFriendInvites(const RsPeerId &pid, uint32_t nb_reqs_invites, + const std::map& already_known_peers, + std::set& chosen_peers) const +{ + // Strategy: we want to return the same set of friends for a given PGP profile key. + // Still, using some closest distance strategy, the n-closest peers for profile A is not the + // same set than the n-closest peers for profile B, so some peers will not be in both sets. + // We have multiple options: + // + // Option 1: + // + // (1) for each profile, keep the list of n-closest peers updated (when a new peer if added/removed all lists are updated) + // + // When a peer asks for k friends, read from (1), until the number of collected peers + // reaches the requested value. Then when a peer receives a connection request, ask the friend server if the + // peer has been sent your own cert. + // + // Option 2: + // + // (1) for each profile, keep the list of n-closest peers updated (when a new peer if added/removed all lists are updated) + // (2) for each profile, keep the list of which peers have been sent this profile already + // + // When a peer asks for k friends, read from (2) first, then (1), until the number of collected peers + // reaches the requested value. + // + // So we choose Option 2. + + std::map res; + chosen_peers.clear(); + auto pinfo_it(mCurrentClientPeers.find(pid)); + + if(pinfo_it == mCurrentClientPeers.end()) + { + RsErr() << "inconsistency in computeListOfFriendInvites. Something's wrong in the code." ; + return res; + } + auto pinfo(pinfo_it->second); + + for(const auto& pit:pinfo.closest_peers) + { + if(already_known_peers.find(pit.second) == already_known_peers.end()) + { + RsDbg() << " peer " << pit.second << ": not in supplied list => adding it."; + + const auto p = mCurrentClientPeers.find(pit.second); + + if(p == mCurrentClientPeers.end()) // should not happen, but just an extra security. + continue; + + auto pp = p->second.friendship_levels.find(pid); + + auto peer_friendship_level = (pp==p->second.friendship_levels.end())?(RsFriendServer::PeerFriendshipLevel::UNKNOWN):(pp->second); + + res[p->second.short_certificate] = peer_friendship_level; + chosen_peers.insert(p->first); + + if(res.size() + already_known_peers.size() >= nb_reqs_invites) + break; + } + else + { + auto p = already_known_peers.find(pit.second); + RsDbg() << " peer " << pit.second << ": already in supplied list, with status " << static_cast(p->second) << ". Not adding it."; + } + } + + return res; +} + +bool FriendServer::handleIncomingClientData(const std::string& pgp_public_key_b64,const std::string& short_invite_b64,RsPeerId& pid) +{ + // 1 - Check that the incoming data is sound. + + try + { + RsDbg() << " Checking item data..."; + + std::string error_string; + std::vector key_binary_data ; + + if(RsBase64::decode(pgp_public_key_b64,key_binary_data)) + throw std::runtime_error(" Cannot decode client pgp public key: \"" + pgp_public_key_b64 + "\". Wrong format??"); + + RsDbg() << " Parsing public key:" ; + + PGPKeyInfo received_key_info; + + if(!PGPKeyManagement::parsePGPPublicKey(key_binary_data.data(),key_binary_data.size(),received_key_info)) + throw std::runtime_error("Cannot parse received pgp public key.") ; + + RsDbg() << " Issuer : \"" << received_key_info.user_id << "\"" ; + RsDbg() << " Fingerprint: " << RsPgpFingerprint::fromBufferUnsafe(received_key_info.fingerprint) ; + + RsDbg() << " Parsing short invite:" ; + + RsPeerDetails shortInviteDetails; + uint32_t errorCode = 0; + + if(short_invite_b64.empty() || !RsCertificate::decodeRadix64ShortInvite(short_invite_b64, shortInviteDetails,errorCode )) + throw std::runtime_error("Could not parse short certificate. Error = " + RsUtil::NumberToString(errorCode)); + + RsDbg() << " Fingerprint: " << shortInviteDetails.fpr ; + RsDbg() << " Peer ID: " << shortInviteDetails.id ; + + if(shortInviteDetails.fpr != RsPgpFingerprint::fromBufferUnsafe(received_key_info.fingerprint)) + throw std::runtime_error("Fingerpring from short invite and public key are different! Very unexpected! Message will be ignored."); + + // 3 - if the key is not already here, add it to keyring. + + { + RsPgpFingerprint fpr_test; + if(mPgpHandler->isPgpPubKeyAvailable(RsPgpId::fromBufferUnsafe(received_key_info.fingerprint+12))) + RsDbg() << " PGP Key is already into keyring."; + else + { + RsPgpId pgp_id; + if(!mPgpHandler->LoadCertificateFromBinaryData(key_binary_data.data(),key_binary_data.size(), pgp_id, error_string)) + throw std::runtime_error("Cannot load client's pgp public key into keyring: " + error_string) ; + + RsDbg() << " Public key added to keyring."; + RsDbg() << " Sync-ing the PGP keyring on disk"; + + mPgpHandler->syncDatabase(); + } + } + // Store/update the peer info + + auto& pi(mCurrentClientPeers[shortInviteDetails.id]); + + pi.short_certificate = short_invite_b64; + pi.last_connection_TS = time(nullptr); + pi.pgp_fingerprint = shortInviteDetails.fpr; + + while(pi.last_identifier == 0) // reuse the same identifier (so it's not really a nonce, but it's kept secret whatsoever). + pi.last_identifier = RsRandom::random_u64(); + + pid = shortInviteDetails.id; + return true; + } + catch (std::exception& e) + { + RsErr() << "Exception while adding client data: " << e.what() ; + return false; + } +} + +void FriendServer::handleClientRemove(const RsFriendServerClientRemoveItem *item) +{ + RsDbg() << "Received a client remove item:" << *item ; + + auto it = mCurrentClientPeers.find(item->peer_id); + + if(it == mCurrentClientPeers.end()) + { + RsErr() << " ERROR: Client " << item->peer_id << " is not known to the server." ; + return; + } + + if(it->second.last_identifier != item->unique_identifier) + { + RsErr() << " ERROR: Client supplied a nonce " << std::hex << item->unique_identifier << std::dec << " that is not correct (expected " + << std::hex << it->second.last_identifier << std::dec << ")"; + return; + } + + RsDbg() << " Nonce is correct: " << std::hex << item->unique_identifier << std::dec << ". Removing peer " << item->peer_id ; + + removePeer(item->peer_id); +} + +void FriendServer::removePeer(const RsPeerId& peer_id) +{ + auto it = mCurrentClientPeers.find(peer_id); + + if(it != mCurrentClientPeers.end()) + mCurrentClientPeers.erase(it); + + for(auto& it:mCurrentClientPeers) + { + // Also remove that peer from all n-closest lists + + for(auto pit(it.second.closest_peers.begin());pit!=it.second.closest_peers.end();) + if(pit->second == peer_id) + { + RsDbg() << " Removing from n-closest peers of peer " << it.first ; + + auto tmp(pit); + ++tmp; + it.second.closest_peers.erase(pit); + pit=tmp; + } + else + ++pit; + + // Also remove that peer from friendship levels of that particular peer. + + auto fit = it.second.friendship_levels.find(peer_id); + + if(fit != it.second.friendship_levels.end()) + { + RsDbg() << " Removing from have_added_as_friend peers of peer " << it.first ; + it.second.friendship_levels.erase(fit); + } + } +} + +PeerInfo::PeerDistance FriendServer::computePeerDistance(const RsPgpFingerprint& p1,const RsPgpFingerprint& p2) +{ + auto res = (p1 ^ p2)^mRandomPeerBias; + auto res2 = RsDirUtil::sha1sum(res.toByteArray(),res.SIZE_IN_BYTES); // sha1sum prevents reverse finding the random bias + + std::cerr << "Computing peer distance: p1=" << p1 << " p2=" << p2 << " p1^p2=" << (p1^p2) << " distance=" << res2 << std::endl; + + return res2; +} +FriendServer::FriendServer(const std::string& base_dir,const std::string& listening_address,uint16_t listening_port) + : mListeningAddress(listening_address),mListeningPort(listening_port) +{ + RsDbg() << "Creating friend server." ; + mBaseDirectory = base_dir; + + // Create a PGP Handler + + std::string pgp_public_keyring_path = RsDirUtil::makePath(base_dir,"pgp_public_keyring") ; + std::string pgp_lock_path = RsDirUtil::makePath(base_dir,"pgp_lock") ; + + std::string pgp_private_keyring_path = RsDirUtil::makePath(base_dir,"pgp_private_keyring") ; // not used. + std::string pgp_trustdb_path = RsDirUtil::makePath(base_dir,"pgp_trustdb") ; // not used. + +#ifdef USE_OPENPGPSDK + mPgpHandler = new OpenPGPSDKHandler(pgp_public_keyring_path,pgp_private_keyring_path,pgp_trustdb_path,pgp_lock_path); +#else + mPgpHandler = new RNPPGPHandler(pgp_public_keyring_path,pgp_private_keyring_path,pgp_trustdb_path,pgp_lock_path); +#endif + + // Random bias. Should be cryptographically safe. + + mRandomPeerBias = RsPgpFingerprint::random(); +} + +void FriendServer::run() +{ + // 1 - create network interface. + + mni = new FsNetworkInterface(mListeningAddress,mListeningPort); + mni->start(); + + while(!shouldStop()) { threadTick() ; } +} + +void FriendServer::autoWash() +{ + rstime_t now = time(nullptr); + std::list to_remove; + + for(std::map::iterator it(mCurrentClientPeers.begin());it!=mCurrentClientPeers.end();++it) + if(it->second.last_connection_TS + MAXIMUM_PEER_INACTIVE_DELAY < now) + { + RsDbg() << "Removing client peer " << it->first << " because it's inactive for more than " << MAXIMUM_PEER_INACTIVE_DELAY << " seconds." ; + to_remove.push_back(it->first); + } + + for(auto peer_id:to_remove) + removePeer(peer_id); +} + +void FriendServer::updateClosestPeers(const RsPeerId& pid,const RsPgpFingerprint& fpr,const std::map& friended_peers) +{ + auto find_multi = [](PeerInfo::PeerDistance dist,std::map< std::pair,RsPeerId >& mp) + -> std::map< std::pair,RsPeerId >::iterator + { + auto it = mp.find(std::make_pair(RsFriendServer::PeerFriendshipLevel::UNKNOWN,dist)) ; + + if(it == mp.end()) it = mp.find(std::make_pair(RsFriendServer::PeerFriendshipLevel::NO_KEY ,dist)); + if(it == mp.end()) it = mp.find(std::make_pair(RsFriendServer::PeerFriendshipLevel::HAS_KEY ,dist)); + if(it == mp.end()) it = mp.find(std::make_pair(RsFriendServer::PeerFriendshipLevel::HAS_ACCEPTED_KEY,dist)); + + return it; + }; + auto remove_from_map = [find_multi](PeerInfo::PeerDistance dist, + std::map< std::pair,RsPeerId>& mp) -> bool + { + auto mpit = find_multi(dist,mp); + + if(mpit != mp.end()) + { + mp.erase(mpit); + return true; + } + else + return false; + }; + + auto& pit(mCurrentClientPeers[pid]); + + for(auto& it:mCurrentClientPeers) + if(it.first != pid) + { + // 1 - for all existing peers, update the level at which the given peer has added the peer as friend. + + auto peer_iterator = friended_peers.find(it.first); + auto peer_friendship_level = (peer_iterator==friended_peers.end())? (RsFriendServer::PeerFriendshipLevel::UNKNOWN):(peer_iterator->second); + + PeerInfo::PeerDistance d = computePeerDistance(fpr,it.second.pgp_fingerprint); + + // Remove the peer from the map. This is costly. I need to find something better. If the peer is already + // in the list, it has a map key with the same distance. + + remove_from_map(d,it.second.closest_peers); + + it.second.closest_peers[std::make_pair(peer_friendship_level,d)] = pid; + + while(it.second.closest_peers.size() > MAXIMUM_PEERS_TO_REQUEST) + it.second.closest_peers.erase(std::prev(it.second.closest_peers.end())); + + // 2 - for the current peer, update the list of closest peers + + auto pit2 = it.second.friendship_levels.find(pid); + peer_friendship_level = (pit2==it.second.friendship_levels.end())? (RsFriendServer::PeerFriendshipLevel::UNKNOWN):(pit2->second); + + remove_from_map(d,pit.closest_peers); + + pit.closest_peers[std::make_pair(peer_friendship_level,d)] = it.first; + + while(pit.closest_peers.size() > MAXIMUM_PEERS_TO_REQUEST) + pit.closest_peers.erase(std::prev(pit.closest_peers.end())); + } + + // Also update the friendship levels for the current peer, of all friends from the list. + + for(auto it:friended_peers) + pit.friendship_levels[it.first] = it.second; +} + +Sha1CheckSum FriendServer::computeDataHash() +{ + librs::crypto::HashStream s(librs::crypto::HashStream::SHA1); + + for(auto p(mCurrentClientPeers.begin());p!=mCurrentClientPeers.end();++p) + { + s << p->first; + + const auto& inf(p->second); + + s << inf.pgp_fingerprint; + s << inf.short_certificate; + s << (uint64_t)inf.last_connection_TS; + s << inf.last_identifier; + + for(auto d(inf.closest_peers.begin());d!=inf.closest_peers.end();++d) + { + s << static_cast(d->first.first) ; + s << d->first.second ; + s << d->second; + } + for(auto d:inf.friendship_levels) + { + s << d.first ; + s << static_cast(d.second); + } + } + return s.hash(); +} +void FriendServer::debugPrint(bool force) +{ + auto h = computeDataHash(); + + if((h != mCurrentDataHash) || force) + { + RsDbg() << "========== FriendServer statistics ============"; + RsDbg() << " Base directory: "<< mBaseDirectory; + RsDbg() << " Random peer bias: "<< mRandomPeerBias; + RsDbg() << " Current hash: "<< h; + RsDbg() << " Network interface: "; + RsDbg() << " Max peers in n-closest list: " << MAXIMUM_PEERS_TO_REQUEST; + RsDbg() << " Current active peers: " << mCurrentClientPeers.size() ; + + rstime_t now = time(nullptr); + + for(const auto& it:mCurrentClientPeers) + { + RsDbg() << " " << it.first << ": identifier=" << std::hex << it.second.last_identifier << std::dec << " fpr: " << it.second.pgp_fingerprint << ", last contact: " << now - it.second.last_connection_TS << " secs ago."; + RsDbg() << " Closest peers:" ; + + for(auto pit:it.second.closest_peers) + RsDbg() << " " << pit.second << " distance=" << pit.first.second << " Peer reciprocal status:" << static_cast(pit.first.first); + } + + RsDbg() << "==============================================="; + + mCurrentDataHash = h; + } + +} + + + + diff --git a/retroshare-friendserver/src/friendserver.h b/retroshare-friendserver/src/friendserver.h new file mode 100644 index 000000000..259b0e5ba --- /dev/null +++ b/retroshare-friendserver/src/friendserver.h @@ -0,0 +1,181 @@ +/* + * RetroShare Friend Server + * Copyright (C) 2021-2021 retroshare team + * + * 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 . + * + * SPDX-FileCopyrightText: Retroshare Team + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#pragma once + +#include "util/rsthreads.h" +#include "pqi/pqistreamer.h" +#include "pgp/pgphandler.h" +#include "retroshare/rsfriendserver.h" + +#include "network.h" + +class RsFriendServerClientRemoveItem; +class RsFriendServerClientPublishItem; + +// +================================================================+ +// | o---o o | +// | \ / - Retroshare Friend Server - / \ | +// | o o---o | +// +================================================================+ +// +// The friend server facilitates a group of RS Tor-nodes to make friends. It maintains a pool of +// participants (RS nodes currently susbscribing to the friend server) and advertise them to each other +// as possible friends. Its goal is to allow new RS users to quickly experiment with the software without +// compromising their anonymity. +// +// Implementation +// ============== +// +// The implementation is entirely client-based: clients make a request, and get a response. No connection is maintained +// beyond this interaction. Consequently, the friend server returns a random ID to each client that the client can use to +// e.g. signal its departure from the friend server and the release of its data. +// +// Both client and server use a binary interface linked to a proxy-connected socket to stream RS items, everything +// happenning on top of Tor connections. +// +// Algorithms +// ========== +// +// * Protocol +// +// Retroshare Client Server (Friend Server) +// +// ------------ Tor connection --------> no action +// Server online MSG <-------------- Tor ACK ------------ +// +// +// Friend Req. loop ------------ Friend Request --------> Friend list calculation / update +// <---------- Friend list + ID -------- +// +// +// FS disabled ------------ FS Close + ID ---------> Data cleaning, peer removal. +// +// +// * Friend selection +// +// In order to reduce the ease to retrieve the list of all participants to a friend server, the +// friend server always returns the same list of friends to a given peer. To do so, participants are sorted +// for each peer, using a XOR distance such as: +// +// d(P1,P2) = P1 (XOR) P2 (XOR) R +// +// ...where R is a random bias. +// +// Since being in the n closest peers is not a reflexive relationship (P1 may be within the n closest peers +// to P2 but P2 may not be in the n closest peers to P1), selected friends for peer A are picked from both +// the closest peers of A, and the peers that received the RS certificate of A. +// +// Another important effect of the stability of retrieved friends is to maintain a network that is not +// fully connected and stable over time, which corresponds to the mesh model of the RS network. +// +// * Peer friendship level +// +// For display purposes, the friend server also stores the "friendship level" for each pair of peers, +// that means whether the peer has added the other peer as friend, or only reveived his key, etc. +// +// Peers send to the friend server the list of peers they already have, with their own friendship +// level with that peer. The FS needs to send back a list of peers, with the friendship level to the current peer. +// In the list of closest peers, the reverse friendship levels are stored: for a peer A the reverse friendship +// level to peer B is whether B has added A as friend or not.In the list of friends for a peer, the forward FL +// is stored. The forward FL of a peer A to a peer B is whether A has added B as friend or not. +// +// * Security +// +// Obviously the friend server knows who is possibly connected to whom. Since the connections to the +// friend server are anonymous, this information is difficult to protect, although the implementation +// currently makes it difficult to retrieve. +// +// The friend server is only available to Tor nodes, since it allows RS nodes to connect to random peers. +// This allows trying the software without compromizing one's privacy. + +struct PeerInfo +{ + typedef Sha1CheckSum PeerDistance; + + RsPgpFingerprint pgp_fingerprint; + std::string short_certificate; + rstime_t last_connection_TS; + uint64_t last_identifier; + + // The following map contains the list of closest peers. The sorting is based + // on a combination of the peer XOR distance and the friendship level, so that + // peers which already have added a peer are considered first as potential receivers of his key. + // The friendship level here is a reverse FL, e.g. whether each closest peer has added the current peer as friend. + + std::map,RsPeerId > closest_peers; // limited in size. + + // Which peers have received the key for that particular peer, along with the direct friendship level: whether current peer has added each peer. + + std::map friendship_levels; // unlimited in size, but no distance sorting. +}; + +class FriendServer : public RsTickingThread +{ +public: + FriendServer(const std::string& base_directory,const std::string& listening_address,uint16_t listening_port); + +private: + // overloads RsTickingThread + + virtual void threadTick() override; + virtual void run() override; + + // Own algorithmics + + void handleClientRemove(const RsFriendServerClientRemoveItem *item); + void handleClientPublish(const RsFriendServerClientPublishItem *item); + + // Updates for each peer in the database, the list of closest peers w.r.t. some arbitrary distance. + void updateClosestPeers(const RsPeerId& pid, const RsPgpFingerprint& fpr, const std::map &friended_peers); + + // removes a single peer from all lists. + void removePeer(const RsPeerId& peer_id); + + // Adds the incoming peer data to the list of current clients and returns the + bool handleIncomingClientData(const std::string& pgp_public_key_b64, const std::string& short_invite_b64, RsPeerId &pid); + + // Computes the appropriate list of short invites to send to a given peer. + std::map computeListOfFriendInvites(const RsPeerId &pid, uint32_t nb_reqs_invites, + const std::map& already_known_peers, + std::set& chosen_peers) const; + + // Compute the distance between peers using the random bias (It's not really a distance though. I'm not sure about the triangular inequality). + PeerInfo::PeerDistance computePeerDistance(const RsPgpFingerprint &p1, const RsPgpFingerprint &p2); + + void autoWash(); + void debugPrint(bool force); + Sha1CheckSum computeDataHash(); + + // Local members + + FsNetworkInterface *mni; + PGPHandler *mPgpHandler; + + std::string mBaseDirectory; + RsPgpFingerprint mRandomPeerBias; + + std::map mCurrentClientPeers; + std::string mListeningAddress; + uint16_t mListeningPort; + + Sha1CheckSum mCurrentDataHash; +}; diff --git a/retroshare-friendserver/src/network.cc b/retroshare-friendserver/src/network.cc new file mode 100644 index 000000000..f28a38de0 --- /dev/null +++ b/retroshare-friendserver/src/network.cc @@ -0,0 +1,324 @@ +/* + * RetroShare Friend Server + * Copyright (C) 2021-2021 retroshare team + * + * 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 . + * + * SPDX-FileCopyrightText: Retroshare Team + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef WINDOWS_SYS +#include +#include +#include +#else +#include +#endif + +#include "util/rsnet.h" +#include "util/rsprint.h" +#include "util/rsdebug.h" + +#include "pqi/pqithreadstreamer.h" +#include "pqi/pqifdbin.h" + +#include "network.h" +#include "friend_server/fsitem.h" + +FsNetworkInterface::FsNetworkInterface(const std::string& listening_address,uint16_t listening_port) + : PQInterface(RsPeerId()),mFsNiMtx(std::string("FsNetworkInterface")),mListeningAddress(listening_address),mListeningPort(listening_port) +{ + RS_STACK_MUTEX(mFsNiMtx); + + mClintListn = 0; + mClintListn = socket(AF_INET, SOCK_STREAM, 0); // creating socket + + int flags=1; + setsockopt(mClintListn,SOL_SOCKET,TCP_NODELAY,(char*)&flags,sizeof(flags)); + + unix_fcntl_nonblock(mClintListn); + + struct sockaddr_in ipOfServer; + memset(&ipOfServer, '0', sizeof(ipOfServer)); + + assert(mListeningPort > 1024); + + ipOfServer.sin_family = AF_INET; + ipOfServer.sin_port = htons(mListeningPort); // this is the port number of running server + + int addr[4]; + if(sscanf(listening_address.c_str(),"%d.%d.%d.%d",&addr[0],&addr[1],&addr[2],&addr[3]) != 4) + throw std::runtime_error("Cannot parse a proper IPv4 address in \""+listening_address+"\""); + + for(int i=0;i<4;++i) + if(addr[i] < 0 || addr[i] > 255) + throw std::runtime_error("Cannot parse a proper IPv4 address in \""+listening_address+"\""); + + ipOfServer.sin_addr.s_addr = htonl( (addr[0] << 24) + (addr[1] << 16) + (addr[2] << 8) + addr[3] ); + + if(bind(mClintListn, (struct sockaddr*)&ipOfServer , sizeof(ipOfServer)) < 0) + { + RsErr() << "Error while binding: errno=" << errno ; + return; + } + + if(listen(mClintListn , 40) < 0) + { + RsErr() << "Error while calling listen: errno=" << errno ; + return; + } + + RsDbg() << "Network interface now listening for TCP on " << sockaddr_storage_tostring( *(sockaddr_storage*)&ipOfServer) ; +} + +FsNetworkInterface::~FsNetworkInterface() +{ + RS_STACK_MUTEX(mFsNiMtx); + for(auto& it:mConnections) + { + delete it.second.pqi_thread; + std::cerr << "Releasing socket " << it.second.socket << std::endl; + close(it.second.socket); + } + std::cerr << "Releasing listening socket " << mClintListn << std::endl; + close(mClintListn); +} +void FsNetworkInterface::threadTick() +{ + // 1 - check for new connections + + checkForNewConnections(); + + // 2 - tick all streamers + + std::list to_close; + + { + RS_STACK_MUTEX(mFsNiMtx); + for(auto& it:mConnections) + { + it.second.pqi_thread->tick(); + + if(!it.second.bio->isactive() && !it.second.bio->moretoread(0)) + to_close.push_back(it.first); + } + + for(const auto& pid:to_close) + locked_closeConnection(pid); + } + + std::this_thread::sleep_for(std::chrono::milliseconds(200)); +} + +static RsPeerId makePeerId(int t) +{ + unsigned char s[RsPeerId::SIZE_IN_BYTES]; + memset(s,0,sizeof(s)); + + *reinterpret_cast(&s) = t; + return RsPeerId::fromBufferUnsafe(s); +} +bool FsNetworkInterface::checkForNewConnections() +{ + // look for incoming data + + struct sockaddr addr; + socklen_t addr_len = sizeof(sockaddr); + + int clintConnt = accept(mClintListn, &addr, &addr_len); // accept is a blocking call! + + if(clintConnt < 0) + { + int err = rs_socket_error(); + + if(err == EWOULDBLOCK || err == EAGAIN) + ;//RsErr()<< "Incoming connection with nothing to read!" << std::endl; + else + RsErr()<< "Error when accepting connection." << std::endl; + + return false; + } + RsDbg() << "Got incoming connection from " << sockaddr_storage_tostring( *(sockaddr_storage*)&addr); + + // Make the socket non blocking so that we can read from it and return if nothing comes + + int flags=1; + setsockopt(clintConnt,SOL_SOCKET,TCP_NODELAY,(char*)&flags,sizeof(flags)); + + unix_fcntl_nonblock(clintConnt); + + // Create connection info + + RsDbg() << " Creating connection data." ; + + ConnectionData c; + c.socket = clintConnt; + c.client_address = addr; + RsPeerId pid = makePeerId(clintConnt); + + RsDbg() << " socket: " << clintConnt; + RsDbg() << " client address: " << sockaddr_storage_tostring(*(sockaddr_storage*)&addr); + RsDbg() << " peer id: " << pid ; + + // Setup a pqistreamer to deserialize whatever comes from this connection + + RsSerialiser *rss = new RsSerialiser ; + rss->addSerialType(new FsSerializer) ; + + RsFdBinInterface *bio = new RsFdBinInterface(clintConnt,true); + + auto pqi = new pqithreadstreamer(this,rss, pid, bio,BIN_FLAGS_READABLE | BIN_FLAGS_WRITEABLE); + + c.pqi_thread = pqi; + c.bio = bio; + + { + RS_STACK_MUTEX(mFsNiMtx); + mConnections[pid] = c; + + pqi->start(); + } + + RsDbg() << " streamer has properly started." ; + return true; +} + +bool FsNetworkInterface::RecvItem(RsItem *item) +{ + RS_STACK_MUTEX(mFsNiMtx); + + RsDbg() << "FsNetworkInterface: received item " << (void*)item; + + auto it = mConnections.find(item->PeerId()); + + if(it == mConnections.end()) + { + RsErr() << "Receiving an item for peer ID " << item->PeerId() << " but no connection is known for that peer." << std::endl; + delete item; + return false; + } + + it->second.incoming_items.push_back(item); + return true; +} + +RsItem *FsNetworkInterface::GetItem() +{ + RS_STACK_MUTEX(mFsNiMtx); + + for(auto& it:mConnections) + { + if(!it.second.incoming_items.empty()) + { + RsItem *item = it.second.incoming_items.front(); + it.second.incoming_items.pop_front(); + + RsDbg() << "FsNetworkInterface: returning item " << (void*)item << " to caller."; + return item; + } + } + return nullptr; +} + +int FsNetworkInterface::SendItem(RsItem *item) +{ + RS_STACK_MUTEX(mFsNiMtx); + + const auto& it = mConnections.find(item->PeerId()); + + if(it == mConnections.end()) + { + RsErr() << "Cannot send item to peer " << item->PeerId() << ": no pending sockets available." ; + delete item; + return 0; + } + + uint32_t ss; + return it->second.pqi_thread->SendItem(item,ss); +} + +void FsNetworkInterface::closeConnection(const RsPeerId& peer_id) +{ + RS_STACK_MUTEX(mFsNiMtx); + + locked_closeConnection(peer_id); +} +void FsNetworkInterface::locked_closeConnection(const RsPeerId& peer_id) +{ + RsDbg() << "Closing connection to virtual peer " << peer_id ; + + const auto& it = mConnections.find(peer_id); + + if(it == mConnections.end()) + { + RsErr() << " Cannot close connection to peer " << peer_id << ": no pending sockets available." ; + return; + } + + if(!it->second.incoming_items.empty()) + { + RsErr() << " Trying to close an incoming connection with incoming items still pending! The items will be lost:" << std::endl; + + for(auto& item:it->second.incoming_items) + { + RsErr() << *item; + delete item; + } + + it->second.incoming_items.clear(); + } + // Close the socket and delete everything. + + close(it->second.socket); + it->second.pqi_thread->fullstop(); + it->second.bio->close(); + + delete it->second.pqi_thread; + + mConnections.erase(it); +} + +void FsNetworkInterface::debugPrint() +{ + RsDbg() << " " << mClintListn ; // listening socket + RsDbg() << " Connections: " << mConnections.size() ; + + for(auto& it:mConnections) + RsDbg() << " " << it.first << ": from \"" << sockaddr_storage_tostring(*(sockaddr_storage*)(&it.second.client_address)) << "\", socket=" << it.second.socket ; + + std::map mConnections; +} + + + + + + + + + + + + + + diff --git a/retroshare-friendserver/src/network.h b/retroshare-friendserver/src/network.h new file mode 100644 index 000000000..fcec0648b --- /dev/null +++ b/retroshare-friendserver/src/network.h @@ -0,0 +1,86 @@ +/* + * RetroShare Friend Server + * Copyright (C) 2021-2021 retroshare team + * + * 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 . + * + * SPDX-FileCopyrightText: Retroshare Team + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#pragma once + +#include "util/rsthreads.h" +#include "pqi/pqi_base.h" +#include "retroshare/rspeers.h" + +class pqithreadstreamer; +class RsFdBinInterface; + +struct ConnectionData +{ + sockaddr client_address; + int socket; + pqithreadstreamer *pqi_thread; + RsFdBinInterface *bio; + + std::list incoming_items; +}; + +// This class handles multiple connections to the server and supplies RsItem elements + +class FsNetworkInterface: public RsTickingThread, public PQInterface +{ +public: + FsNetworkInterface(const std::string& listening_address,uint16_t listening_port) ; + virtual ~FsNetworkInterface() ; + + // basic functionality + + void debugPrint(); + + // Implements PQInterface + + bool RecvItem(RsItem *item) override; + int SendItem(RsItem *item) override; + RsItem *GetItem() override; + + void closeConnection(const RsPeerId& peer_id); + + // Implements RsTickingThread + + void threadTick() override; + +protected: + bool checkForNewConnections(); + void locked_closeConnection(const RsPeerId& peer_id); + +private: + RsMutex mFsNiMtx; + + void initListening(); + void stopListening(); + + int mClintListn ; // listening socket + std::map mConnections; + + std::string mListeningAddress; + uint16_t mListeningPort; +}; + + + + + + diff --git a/retroshare-friendserver/src/retroshare-friendserver.cc b/retroshare-friendserver/src/retroshare-friendserver.cc new file mode 100644 index 000000000..fabe3889d --- /dev/null +++ b/retroshare-friendserver/src/retroshare-friendserver.cc @@ -0,0 +1,140 @@ +/* + * RetroShare Service + * Copyright (C) 2021-2021 retroshare team + * + * 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 . + * + * SPDX-FileCopyrightText: Retroshare Team + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include "util/stacktrace.h" +#include "util/rsdir.h" +#include "util/argstream.h" +#include "util/rstime.h" +#include "util/rsdebug.h" + +#include "retroshare/rstor.h" +#include "retroshare/rsinit.h" +#include "pqi/authgpg.h" + +#include "friendserver.h" + +// debug +#include "friend_server/fsitem.h" +#include "friend_server/fsclient.h" + +int main(int argc, char* argv[]) +{ + RsInfo() << "\n" << + "+================================================================+\n" + "| o---o o |\n" + "| \\ / - Retroshare Friend Server - / \\ |\n" + "| o o---o |\n" + "+================================================================+" + << std::endl << std::endl; + + //RsControl::earlyInitNotificationSystem(); + + std::string base_directory = "FSData"; + std::string tor_executable_path ; + bool verbose = false; + + argstream as(argc,argv); + + as >> parameter( 'c',"base-dir", base_directory, "set base directory to store data files (keys, etc)", false ) + >> parameter( 't',"tor-executable", tor_executable_path, "set absolute path for tor executable", false ) + >> option( 'v',"verbose", verbose, "display additional debug information") + >> help( 'h', "help", "Display this Help" ); + + as.defaultErrorHandling(true, true); + + RsConfigOptions conf; + conf.optBaseDir = base_directory; + conf.main_executable_path = argv[0]; + + if(!tor_executable_path.empty()) + RsTor::setTorExecutablePath(tor_executable_path); + + RsTor::setVerbose(verbose); + + RsInit::InitRsConfig(); + RsInit::InitRetroShare(conf); + + AuthPGP::exit(); // This allows to release the keyring created by libretroshare, since it's not useful, as TorManager has its own. + + // Create the base directory if needed + + if(!RsDirUtil::checkCreateDirectory(base_directory)) + { + RsErr() << "Cannot create base directory \"" << base_directory << "\". Check permissions, paths, etc." ; + return 1; + } + + // Check the existance of the Tor executable path + + auto tor_path = RsTor::torExecutablePath(); + + if (!RsDirUtil::fileExists(tor_path)) + { + RsErr() << "Tor executable \"" << tor_path << "\" not found. Try supplying the correct full path for a tor executable with the -t option."; + return 1; + } + else + RsDbg() << "Using Tor executable: \"" << tor_path << "\""; + + // Create/start TorManager + + RsTor::setTorDataDirectory(RsDirUtil::makePath(base_directory,"tor")); + RsTor::setHiddenServiceDirectory(RsDirUtil::makePath(base_directory,"hidden_service")); + + if(! RsTor::start() || RsTor::hasError()) + { + RsErr() << "Tor cannot be started on your system: " << RsTor::errorMessage() ; + return 1 ; + } + + std::string service_id; + + while(RsTor::torStatus() != RsTorStatus::READY || RsTor::getHiddenServiceStatus(service_id) != RsTorHiddenServiceStatus::ONLINE) + std::this_thread::sleep_for(std::chrono::seconds(1)); + + std::string onion_address,service_target_address; + uint16_t service_port,target_port; + + RsTor::getHiddenServiceInfo(service_id,onion_address,service_port,service_target_address,target_port) ; + + RsInfo() << "Tor properly started: " ; + RsInfo() << " Hidden service address: " << onion_address << ":" << service_port; + RsInfo() << " Target address : " << service_target_address << ":" << target_port; + + // Now start the real thing. + + FriendServer fs(base_directory,service_target_address,target_port); + fs.start(); + + RsInfo() << ""; + RsInfo() << "================== Retroshare Friend Server has properly started =====================" ; + RsInfo() << "= ="; + RsInfo() << "= Address:Port " << onion_address << ":" << service_port << ((service_port<10000)?" ":"") << " ="; + RsInfo() << "= ="; + RsInfo() << "======================================================================================" ; + RsInfo() << ""; + + while(fs.isRunning()) + std::this_thread::sleep_for(std::chrono::seconds(2)); + + return 0; +} + diff --git a/retroshare-friendserver/src/retroshare-friendserver.pro b/retroshare-friendserver/src/retroshare-friendserver.pro new file mode 100644 index 000000000..eda1f35cb --- /dev/null +++ b/retroshare-friendserver/src/retroshare-friendserver.pro @@ -0,0 +1,50 @@ +# RetroShare service qmake build script +# +# Copyright (C) 2021-2021, retroshare team +# +# 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 . +# +# SPDX-FileCopyrightText: Retroshare Team +# SPDX-License-Identifier: AGPL-3.0-or-later + +!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri") + +TARGET = retroshare-friendserver + +!include("../../libretroshare/src/use_libretroshare.pri"):error("Including") + +SOURCES += retroshare-friendserver.cc \ + friendserver.cc \ + network.cc + +HEADERS += friendserver.h \ + network.h + +################################# Linux ########################################## + +unix { + target.path = "$${RS_BIN_DIR}" + INSTALLS += target +} + +################################# Windows ########################################## + +win32-g++|win32-clang-g++ { + dLib = ws2_32 iphlpapi crypt32 + LIBS *= $$linkDynamicLibs(dLib) + CONFIG += console +} + +################################### COMMON stuff ################################## + diff --git a/retroshare-gui/CMakeLists.txt b/retroshare-gui/CMakeLists.txt new file mode 100644 index 000000000..314edf1ab --- /dev/null +++ b/retroshare-gui/CMakeLists.txt @@ -0,0 +1,492 @@ +################################################################################ +# retroshare-gui/CMakeLists.txt # +# Copyright (C) 2022, Retroshare team # +# # +# 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 . # +################################################################################ + +cmake_minimum_required (VERSION 3.18.0) +project(retroshare-gui VERSION 0.6.6 LANGUAGES CXX) + +include(CMakeDependentOption) + +set( + RS_BIN_INSTALL_DIR + "${CMAKE_INSTALL_PREFIX}/bin" + CACHE PATH + "Path where to install retroshare-service compiled binary" ) + +option( + RS_DEVELOPMENT_BUILD + "Disable optimization to speed up build, enable verbose build log. \ + just for development purposes, not suitable for library usage" + ON ) + +option( + RS_JSON_API + "Use restbed to expose libretroshare as JSON API via HTTP" + OFF ) + +option( + RS_SERVICE_DESKTOP + "Install icons and shortcuts for desktop environements" + OFF ) + +option( + RS_SERVICE_TERMINAL_LOGIN + "Enable RetroShare login via terminal" + ON ) + +option( RS_GXSGUI "Enable GXS services in GUI" ON ) +option( RS_GXSCHANNELS "Enable GXS channels in GUI" ON ) +option( RS_GXSFORUMS "Enable GXS forums in GUI" ON ) +option( RS_GXSPOSTED "Enable GXS posted in GUI" ON ) +option( RS_GXSCIRCLES "Enable GXS circles in GUI" ON ) + +cmake_dependent_option( + RS_SERVICE_TERMINAL_WEBUI_PASSWORD + "Enable settin Web UI password via terminal in retroshare-service" + OFF + "RS_WEBUI" + ON ) + +cmake_dependent_option( + RS_WEBUI + "Install RetroShare Web UI" + OFF + "RS_JSON_API" + ON ) + +################################ QT FILES ####################################### + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +find_package( Qt5 COMPONENTS Core REQUIRED) +find_package( Qt5 COMPONENTS Widgets REQUIRED) +find_package( Qt5 COMPONENTS Xml REQUIRED) +find_package( Qt5 COMPONENTS Network REQUIRED) +find_package( Qt5 COMPONENTS Multimedia REQUIRED) +find_package( Qt5 COMPONENTS PrintSupport REQUIRED) + +list( APPEND RS_LINK_LIBRARIES Qt5::Multimedia Qt5::Widgets Qt5::Xml Qt5::Network Qt5::PrintSupport) + +################################################################################ + +set(FETCHCONTENT_QUIET OFF) +include(FetchContent) + +find_package(Git REQUIRED) + +################################################################################ + +if(RS_DEVELOPMENT_BUILD) + set(CMAKE_VERBOSE_MAKEFILE ON) + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +endif(RS_DEVELOPMENT_BUILD) + +################################################################################ + +include(src/CMakeLists.txt) + +qt5_wrap_ui(RS_UI_HEADERS ${RS_GUI_FORMS}) + +add_executable(${PROJECT_NAME} ${RS_GUI_SOURCES} ${RS_UI_HEADERS} ${RS_GUI_QTRESOURCES}) +install(TARGETS ${PROJECT_NAME} DESTINATION ${RS_BIN_INSTALL_DIR}) + +include_directories( ${CMAKE_BINARY_DIR} ) + +################################################################################ + +if(RS_DEVELOPMENT_BUILD) + target_compile_options(${PROJECT_NAME} PRIVATE "-O0") +endif(RS_DEVELOPMENT_BUILD) + +################################################################################ + +set(LIBRETROSHARE_DEVEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../libretroshare/") +if(EXISTS "${LIBRETROSHARE_DEVEL_DIR}/.git" ) + message( + STATUS + "libretroshare submodule found at ${LIBRETROSHARE_DEVEL_DIR} using it" ) + add_subdirectory( + "${LIBRETROSHARE_DEVEL_DIR}" "${CMAKE_BINARY_DIR}/libretroshare" ) +else() + FetchContent_Declare( + libretroshare + GIT_REPOSITORY "https://gitlab.com/RetroShare/libretroshare.git" + GIT_TAG "origin/master" + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE + TIMEOUT 10 + ) + FetchContent_MakeAvailable(libretroshare) +endif() + +target_include_directories(${PROJECT_NAME} PRIVATE ${LIBRETROSHARE_DEVEL_DIR}/src/) + +################################################################################ + +if(RS_SERVICE_DESKTOP) + if(UNIX AND NOT APPLE) + install( + FILES data/retroshare.svg + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/ ) + + install( + FILES data/retroshare.xpm + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps/ ) + + install( + FILES data/24x24/apps/retroshare.png + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/24x24/apps/retroshare.png ) + + install( + FILES data/48x48/apps/retroshare.png + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps/retroshare.png ) + + install( + FILES data/64x64/apps/retroshare.png + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/64x64/apps/retroshare.png ) + + install( + FILES data/128x128/apps/retroshare.png + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/128x128/apps/retroshare.png ) + + install( + FILES data/retroshare.desktop + DESTINATION ${CMAKE_INSTALL_PREFIX}/data/retroshare.desktop ) + + install( + FILES gui/qss/chat/Bubble gui/qss/chat/Bubble_Compact + DESTINATION ${CMAKE_INSTALL_PREFIX}/data/stylesheets/ ) + + install( + FILES src/sounds/ src/qss/ + DESTINATION ${CMAKE_INSTALL_PREFIX}/ ) + endif(UNIX AND NOT APPLE) +endif(RS_SERVICE_DESKTOP) + +################################################################################ + +if(RS_JSON_API) + target_compile_definitions(${PROJECT_NAME} PUBLIC RS_JSONAPI) +endif(RS_JSON_API) + +################################# CMark ######################################## + +if(RS_GUI_CMARK) + set(CMARK_DEVEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../supportlibs/cmark/") + if(EXISTS "${LIBRETROSHARE_DEVEL_DIR}/.git" ) + message( STATUS "cmark submodule found at ${LIBRETROSHARE_DEVEL_DIR} using it" ) + add_subdirectory( "${LIBRETROSHARE_DEVEL_DIR}" "${CMAKE_BINARY_DIR}/cmark" ) + else() + FetchContent_Declare( + cmark + GIT_REPOSITORY "https://github.com/commonmark/cmark.git" + GIT_TAG "origin/master" + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE + TIMEOUT 10 + ) + FetchContent_MakeAvailable(cmark) + endif() +endif(RS_GUI_CMARK) + +################################# LibSam v3 #################################### + +set(SAM3_DEVEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../supportlibs/libsam3/") +if(EXISTS "${SAM3_DEVEL_DIR}/.git" ) + message( STATUS "libsam3 submodule found at ${SAM3_DEVEL_DIR} using it" ) + add_subdirectory( "${SAM3_DEVEL_DIR}" "${CMAKE_BINARY_DIR}/libsam3" ) +else() + FetchContent_Declare( + libsam3 + GIT_REPOSITORY "https://github.com/i2p/libsam3.git" + GIT_TAG "origin/master" + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE + TIMEOUT 10 + ) + FetchContent_MakeAvailable(libsam3) +endif() + +################################################################################ +# TODO # +################################################################################ + +# # Auto detect installed version of cmark +# rs_gui_cmark { +# DEFINES *= USE_CMARK +# no_rs_cross_compiling { +# message("Using compiled cmark") +# CMARK_SRC_PATH=$$clean_path($${RS_SRC_PATH}/supportlibs/cmark) +# CMARK_BUILD_PATH=$$clean_path($${RS_BUILD_PATH}/supportlibs/cmark/build) +# INCLUDEPATH *= $$clean_path($${CMARK_SRC_PATH}/src/) +# DEPENDPATH *= $$clean_path($${CMARK_SRC_PATH}/src/) +# QMAKE_LIBDIR *= $$clean_path($${CMARK_BUILD_PATH}/) +# # Using sLibs would fail as libcmark.a is generated at compile-time +# LIBS *= -L$$clean_path($${CMARK_BUILD_PATH}/src/) -lcmark +# +# DUMMYCMARKINPUT = FORCE +# CMAKE_GENERATOR_OVERRIDE="" +# win32-g++|win32-clang-g++:CMAKE_GENERATOR_OVERRIDE="-G \"MSYS Makefiles\"" +# gencmarklib.name = Generating libcmark. +# gencmarklib.input = DUMMYCMARKINPUT +# gencmarklib.output = $$clean_path($${CMARK_BUILD_PATH}/src/libcmark.a) +# gencmarklib.CONFIG += target_predeps combine +# gencmarklib.variable_out = PRE_TARGETDEPS +# gencmarklib.commands = \ +# cd $${RS_SRC_PATH} && ( \ +# git submodule update --init supportlibs/cmark ; \ +# cd $${CMARK_SRC_PATH} ; \ +# true ) && \ +# mkdir -p $${CMARK_BUILD_PATH} && cd $${CMARK_BUILD_PATH} && \ +# cmake \ +# -DCMAKE_CXX_COMPILER=$$QMAKE_CXX \ +# \"-DCMAKE_CXX_FLAGS=$${QMAKE_CXXFLAGS}\" \ +# $${CMAKE_GENERATOR_OVERRIDE} \ +# -DCMAKE_INSTALL_PREFIX=. \ +# -B. \ +# -H$$shell_path($${CMARK_SRC_PATH}) && \ +# $(MAKE) +# QMAKE_EXTRA_COMPILERS += gencmarklib +# } else { +# message("Using systems cmark") +# sLibs *= libcmark +# } +# } + +################################# Linux ########################################## +# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib + +if(UNIX) + find_package(PkgConfig REQUIRED) + + pkg_check_modules(X11 REQUIRED x11) + pkg_check_modules(XSCRNSAVER REQUIRED xscrnsaver) + + list( APPEND RS_LINK_LIBRARIES ${X11_LIBRARIES} ) + list( APPEND RS_LINK_LIBRARIES ${XSCRNSAVER_LIBRARIES} ) + + target_include_directories(${PROJECT_NAME} PRIVATE ${X11_INCLUDE_DIRS}) + target_compile_options(${PROJECT_NAME} PRIVATE ${X11_CFLAGS_OTHER}) + + target_include_directories(retroshare-gui PRIVATE ${XSCRNSAVER_INCLUDE_DIRS}) + target_compile_options(retroshare-gui PRIVATE ${XSCRNSAVER_CFLAGS_OTHER}) + + target_compile_definitions(${PROJECT_NAME} PRIVATE HAVE_XSS) + target_compile_definitions(${PROJECT_NAME} PRIVATE _FILE_OFFSET_BITS=64) + target_link_options(${PROJECT_NAME} PRIVATE LINKER:-rdynamic) +endif(UNIX) + +if(RS_SANITIZE) + list( APPEND RS_LINK_LIBRARIES asan ) + list( APPEND RS_LINK_LIBRARIES ubsan ) +endif(RS_SANITIZE) + +# #################### Cross compilation for windows under Linux ################### +# +# win32-x-g++ { +# OBJECTS_DIR = temp/win32-x-g++/obj +# +# LIBS += ../../../../lib/win32-x-g++-v0.5/libssl.a +# LIBS += ../../../../lib/win32-x-g++-v0.5/libcrypto.a +# LIBS += ../../../../lib/win32-x-g++-v0.5/libgpgme.dll.a +# LIBS += ../../../../lib/win32-x-g++-v0.5/libminiupnpc.a +# LIBS += ../../../../lib/win32-x-g++-v0.5/libz.a +# LIBS += -L${HOME}/.wine/drive_c/pthreads/lib -lpthreadGCE2 +# LIBS += -lQtUiTools +# LIBS += -lws2_32 -luuid -lole32 -liphlpapi -lcrypt32 -gdi32 +# LIBS += -lole32 -lwinmm +# +# DEFINES *= WINDOWS_SYS WIN32 WIN32_CROSS_UBUNTU +# +# INCLUDEPATH += ../../../../gpgme-1.1.8/src/ +# INCLUDEPATH += ../../../../libgpg-error-1.7/src/ +# +# RC_FILE = gui/images/retroshare_win.rc +# } +# +# #################################### Windows ##################################### +# +# win32-g++|win32-clang-g++ { +# CONFIG(debug, debug|release) { +# # show console output +# CONFIG += console +# } else { +# CONFIG -= console +# } +# +# CONFIG(debug, debug|release) { +# } else { +# # Tell linker to use ASLR protection +# QMAKE_LFLAGS += -Wl,-dynamicbase +# # Tell linker to use DEP protection +# QMAKE_LFLAGS += -Wl,-nxcompat +# } +# +# # Fix linking error (ld.exe: Error: export ordinal too large) due to too +# # many exported symbols. +# !libretroshare_shared:QMAKE_LFLAGS+=-Wl,--exclude-libs,ALL +# +# # Switch off optimization for release version +# QMAKE_CXXFLAGS_RELEASE -= -O2 +# QMAKE_CXXFLAGS_RELEASE += -O0 +# QMAKE_CFLAGS_RELEASE -= -O2 +# QMAKE_CFLAGS_RELEASE += -O0 +# +# # Switch on optimization for debug version +# #QMAKE_CXXFLAGS_DEBUG += -O2 +# #QMAKE_CFLAGS_DEBUG += -O2 +# +# OBJECTS_DIR = temp/obj +# +# dLib = ws2_32 gdi32 uuid ole32 iphlpapi crypt32 winmm +# LIBS *= $$linkDynamicLibs(dLib) +# +# RC_FILE = gui/images/retroshare_win.rc +# +# # export symbols for the plugins +# LIBS += -Wl,--export-all-symbols,--out-implib,lib/libretroshare-gui.a +# +# # create lib directory +# isEmpty(QMAKE_SH) { +# QMAKE_PRE_LINK = $(CHK_DIR_EXISTS) lib $(MKDIR) lib +# } else { +# QMAKE_PRE_LINK = $(CHK_DIR_EXISTS) lib || $(MKDIR) lib +# } +# +# greaterThan(QT_MAJOR_VERSION, 4) { +# # Qt 5 +# RC_INCLUDEPATH += $$_PRO_FILE_PWD_/../../libretroshare/src +# } else { +# # Qt 4 +# QMAKE_RC += --include-dir=$$_PRO_FILE_PWD_/../../libretroshare/src +# } +# } +# +# ##################################### MacOS ###################################### +# +# macx { +# # ENABLE THIS OPTION FOR Univeral Binary BUILD. +# #CONFIG += ppc x86 +# #QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 +# QMAKE_INFO_PLIST = Info.plist +# mac_icon.files = $$files($$PWD/rsMacIcon.icns) +# mac_icon.path = Contents/Resources +# QMAKE_BUNDLE_DATA += mac_icon +# dplQSS.files = $$PWD/qss +# dplQSS.path = Contents/Resources +# QMAKE_BUNDLE_DATA += dplQSS +# dplChatStyles.files = \ +# $$PWD/gui/qss/chat/Bubble \ +# $$PWD/gui/qss/chat/Bubble_Compact +# dplChatStyles.path = Contents/Resources/stylesheets +# QMAKE_BUNDLE_DATA += dplChatStyles +# # mac_webui.files = $$files($$PWD/../../libresapi/src/webui) +# # mac_webui.path = Contents/Resources +# # QMAKE_BUNDLE_DATA += mac_webui +# +# OBJECTS_DIR = temp/obj +# +# CONFIG += version_detail_bash_script +# LIBS += -lssl -lcrypto -lz +# for(lib, LIB_DIR):exists($$lib/libminiupnpc.a){ LIBS += $$lib/libminiupnpc.a} +# LIBS += -framework CoreFoundation +# LIBS += -framework Security +# LIBS += -framework Carbon +# +# for(lib, LIB_DIR):LIBS += -L"$$lib" +# for(bin, BIN_DIR):LIBS += -L"$$bin" +# +# DEPENDPATH += . $$INC_DIR +# INCLUDEPATH += . $$INC_DIR +# +# #DEFINES *= MAC_IDLE # for idle feature +# CONFIG -= uitools +# } +# +# ##################################### FreeBSD ###################################### +# +# freebsd-* { +# INCLUDEPATH *= /usr/local/include/gpgme +# LIBS *= -lssl +# LIBS *= -lgpgme +# LIBS *= -lupnp +# LIBS *= -lgnome-keyring +# +# LIBS += -lsqlite3 +# } +# +# ##################################### Haiku ###################################### +# +# haiku-* { +# PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a +# PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a +# +# LIBS *= ../../libretroshare/src/lib/libretroshare.a +# LIBS *= ../../openpgpsdk/src/lib/libops.a -lbz2 -lbsd +# LIBS *= -lssl -lcrypto -lnetwork +# LIBS *= -lgpgme +# LIBS *= -lupnp +# LIBS *= -lz +# LIBS *= -lixml +# +# LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a +# LIBS += -lsqlite3 +# } +# +# ##################################### OpenBSD ###################################### +# +# openbsd-* { +# INCLUDEPATH *= /usr/local/include +# +# LIBS *= -lssl -lcrypto +# LIBS *= -lgpgme +# LIBS *= -lupnp +# LIBS *= -lgnome-keyring +# LIBS += -lsqlite3 +# LIBS *= -rdynamic +# } +# +# ################################### COMMON stuff ################################## +# +# wikipoos { +# PRE_TARGETDEPS *= $$OUT_PWD/../../supportlibs/pegmarkdown/lib/libpegmarkdown.a +# LIBS *= $$OUT_PWD/../../supportlibs/pegmarkdown/lib/libpegmarkdown.a +# LIBS *= -lglib-2.0 +# } + +################################ GENERAL ####################################### + +target_link_libraries(${PROJECT_NAME} PRIVATE ${RS_LINK_LIBRARIES}) + +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/) + +set( CMAKE_CXX_FLAGS "-Wno-deprecated-declarations" ) +target_compile_definitions(${PROJECT_NAME} PUBLIC RS_NO_WARN_DEPRECATED ) +target_compile_definitions(${PROJECT_NAME} PRIVATE RS_RELEASE_VERSION ) +target_compile_definitions(${PROJECT_NAME} PRIVATE TARGET=\"retroshare\") + +if(RS_GXS_CIRCLES) + target_compile_definitions(${PROJECT_NAME} PRIVATE RS_USE_CIRCLES ) +endif(RS_GXS_CIRCLES) + +#add_dependencies(${PROJECT_NAME} libretroshare) + diff --git a/retroshare-gui/src/CMakeLists.txt b/retroshare-gui/src/CMakeLists.txt new file mode 100644 index 000000000..b936552ed --- /dev/null +++ b/retroshare-gui/src/CMakeLists.txt @@ -0,0 +1,1279 @@ +################################################################################ +# uselibresapi.pri # +# Copyright (C) 2018, Retroshare team # +# # +# 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 . # +################################################################################ + +list( + APPEND RS_GUI_SOURCES + src/TorControl/TorControlWindow.cpp + + src/main.cpp + src/rshare.cpp + + src/gui/notifyqt.cpp + src/gui/AboutDialog.cpp + src/gui/AboutWidget.cpp + src/gui/QuickStartWizard.cpp + src/gui/StartDialog.cpp + src/gui/HomePage.cpp + src/gui/ChatLobbyWidget.cpp + src/gui/GetStartedDialog.cpp + src/gui/GenCertDialog.cpp + src/gui/NetworkDialog.cpp + src/gui/mainpagestack.cpp + src/gui/MainWindow.cpp + src/gui/NetworkView.cpp + src/gui/FriendsDialog.cpp + src/gui/ServicePermissionDialog.cpp + src/gui/RemoteDirModel.cpp + src/gui/RsAutoUpdatePage.cpp + src/gui/RetroShareLink.cpp + src/gui/SearchTreeWidget.cpp + src/gui/ShareManager.cpp + # src/gui/ShareDialog.cpp + src/gui/NewsFeed.cpp + src/gui/MainPage.cpp + src/gui/HelpDialog.cpp + src/gui/LogoBar.cpp + src/gui/SoundManager.cpp + + src/gui/im_history/ImHistoryBrowser.cpp + src/gui/im_history/IMHistoryItemDelegate.cpp + src/gui/im_history/IMHistoryItemPainter.cpp + + src/gui/help/browser/helpbrowser.cpp + src/gui/help/browser/helptextbrowser.cpp + + src/gui/FileTransfer/SearchDialog.cpp + src/gui/FileTransfer/SharedFilesDialog.cpp + src/gui/FileTransfer/TransfersDialog.cpp + src/gui/FileTransfer/FileTransferInfoWidget.cpp + src/gui/FileTransfer/DLListDelegate.cpp + src/gui/FileTransfer/ULListDelegate.cpp + src/gui/FileTransfer/xprogressbar.cpp + src/gui/FileTransfer/DetailsDialog.cpp + src/gui/FileTransfer/TransferUserNotify.cpp + src/gui/FileTransfer/BannedFilesDialog.cpp + + src/lang/languagesupport.cpp + + src/util/RsProtectedTimer.cpp + src/util/stringutil.cpp + src/util/RsNetUtil.cpp + src/util/DateTime.cpp + src/util/RetroStyleLabel.cpp + src/util/WidgetBackgroundImage.cpp + src/util/PixmapMerging.cpp + src/util/MouseEventFilter.cpp + src/util/EventFilter.cpp + src/util/Widget.cpp + src/util/RsAction.cpp + src/util/printpreview.cpp + src/util/log.cpp + src/util/misc.cpp + src/util/HandleRichText.cpp + src/util/ObjectPainter.cpp + src/util/RsFile.cpp + src/util/RichTextEdit.cpp + src/util/ClickableLabel.cpp + src/util/AspectRatioPixmapLabel.cpp + + src/gui/profile/ProfileWidget.cpp + src/gui/profile/StatusMessage.cpp + src/gui/profile/ProfileManager.cpp + + src/gui/chat/PopupChatWindow.cpp + src/gui/chat/PopupChatDialog.cpp + src/gui/chat/PopupDistantChatDialog.cpp + src/gui/chat/ChatTabWidget.cpp + src/gui/chat/ChatWidget.cpp + src/gui/chat/ChatDialog.cpp + src/gui/chat/ChatLobbyDialog.cpp + src/gui/chat/CreateLobbyDialog.cpp + src/gui/chat/ChatStyle.cpp + src/gui/chat/ChatUserNotify.cpp + src/gui/chat/ChatLobbyUserNotify.cpp + + src/gui/connect/ConfCertDialog.cpp + src/gui/connect/PGPKeyDialog.cpp + src/gui/connect/ConnectFriendWizard.cpp + src/gui/connect/ConnectProgressDialog.cpp + src/gui/connect/FriendRecommendDialog.cpp + + src/gui/msgs/MessagesDialog.cpp + src/gui/msgs/MessageComposer.cpp + src/gui/msgs/MessageWidget.cpp + src/gui/msgs/MessageWindow.cpp + src/gui/msgs/MessageModel.cpp + src/gui/msgs/TagsMenu.cpp + src/gui/msgs/MessageUserNotify.cpp + + src/gui/common/RsButtonOnText.cpp + src/gui/common/RSGraphWidget.cpp + src/gui/common/ElidedLabel.cpp + src/gui/common/vmessagebox.cpp + src/gui/common/RsCollectionDialog.cpp + src/gui/common/RsCollection.cpp + src/gui/common/RsUrlHandler.cpp + src/gui/common/rwindow.cpp + src/gui/common/rshtml.cpp + src/gui/common/AvatarDefs.cpp + src/gui/common/AvatarDialog.cpp + src/gui/common/GroupFlagsWidget.cpp + src/gui/common/GroupSelectionBox.cpp + src/gui/common/GroupChooser.cpp + src/gui/common/StatusDefs.cpp + src/gui/common/TagDefs.cpp + src/gui/common/GroupDefs.cpp + src/gui/common/Emoticons.cpp + src/gui/common/RSComboBox.cpp + src/gui/common/RSListWidgetItem.cpp + src/gui/common/RSTextEdit.cpp + src/gui/common/RSPlainTextEdit.cpp + src/gui/common/RSTreeWidget.cpp + src/gui/common/RSTreeWidgetItem.cpp + src/gui/common/RSFeedWidget.cpp + src/gui/common/RSTabWidget.cpp + src/gui/common/RSElidedItemDelegate.cpp + src/gui/common/RSItemDelegate.cpp + src/gui/common/PeerDefs.cpp + src/gui/common/FilesDefs.cpp + src/gui/common/PopularityDefs.cpp + src/gui/common/RsBanListDefs.cpp + src/gui/common/GroupTreeWidget.cpp + src/gui/common/RSTreeView.cpp + src/gui/common/AvatarWidget.cpp + src/gui/common/FriendListModel.cpp + src/gui/common/NewFriendList.cpp + src/gui/common/FriendSelectionWidget.cpp + src/gui/common/FriendSelectionDialog.cpp + src/gui/common/HashBox.cpp + src/gui/common/LineEditClear.cpp + src/gui/common/DropLineEdit.cpp + src/gui/common/RSTextBrowser.cpp + src/gui/common/RSImageBlockWidget.cpp + src/gui/common/FeedNotify.cpp + src/gui/common/UserNotify.cpp + src/gui/common/HeaderFrame.cpp + src/gui/common/MimeTextEdit.cpp + src/gui/common/UIStateHelper.cpp + src/gui/common/FloatingHelpBrowser.cpp + src/gui/common/SubscribeToolButton.cpp + src/gui/common/RsBanListToolButton.cpp + src/gui/common/FlowLayout.cpp + src/gui/common/PictureFlow.cpp + src/gui/common/ToasterNotify.cpp + + src/gui/style/RSStyle.cpp + src/gui/style/StyleDialog.cpp + + src/gui/settings/RSPermissionMatrixWidget.cpp + src/gui/settings/rsharesettings.cpp + src/gui/settings/RsharePeerSettings.cpp + src/gui/settings/rsettings.cpp + src/gui/settings/rsettingswin.cpp + src/gui/settings/GeneralPage.cpp + src/gui/settings/AboutPage.cpp + src/gui/settings/ServerPage.cpp + src/gui/settings/NotifyPage.cpp + src/gui/settings/CryptoPage.cpp + src/gui/settings/PeoplePage.cpp + src/gui/settings/MessagePage.cpp + src/gui/settings/NewTag.cpp + src/gui/settings/ForumPage.cpp + src/gui/settings/PluginsPage.cpp + src/gui/settings/PluginItem.cpp + src/gui/settings/AppearancePage.cpp + src/gui/settings/FileAssociationsPage.cpp + src/gui/settings/SoundPage.cpp + src/gui/settings/TransferPage.cpp + src/gui/settings/ChatPage.cpp + src/gui/settings/ChannelPage.cpp + src/gui/settings/PostedPage.cpp + src/gui/settings/ServicePermissionsPage.cpp + src/gui/settings/AddFileAssociationDialog.cpp + src/gui/settings/GroupFrameSettingsWidget.cpp + + src/gui/statusbar/peerstatus.cpp + src/gui/statusbar/natstatus.cpp + src/gui/statusbar/dhtstatus.cpp + src/gui/statusbar/torstatus.cpp + src/gui/statusbar/ratesstatus.cpp + src/gui/statusbar/hashingstatus.cpp + src/gui/statusbar/discstatus.cpp + src/gui/statusbar/SoundStatus.cpp + src/gui/statusbar/OpModeStatus.cpp + src/gui/statusbar/ToasterDisable.cpp + src/gui/statusbar/SysTrayStatus.cpp + + src/gui/toaster/ToasterItem.cpp + src/gui/toaster/MessageToaster.cpp + src/gui/toaster/DownloadToaster.cpp + src/gui/toaster/OnlineToaster.cpp + src/gui/toaster/ChatToaster.cpp + src/gui/toaster/GroupChatToaster.cpp + src/gui/toaster/ChatLobbyToaster.cpp + src/gui/toaster/FriendRequestToaster.cpp + + src/gui/advsearch/advancedsearchdialog.cpp + src/gui/advsearch/expressionwidget.cpp + src/gui/advsearch/guiexprelement.cpp + + src/gui/elastic/graphwidget.cpp + src/gui/elastic/edge.cpp + src/gui/elastic/arrow.cpp + src/gui/elastic/elnode.cpp + + src/gui/feeds/BoardsCommentsItem.cpp + src/gui/feeds/FeedItem.cpp + src/gui/feeds/FeedHolder.cpp + src/gui/feeds/GxsCircleItem.cpp + src/gui/feeds/ChannelsCommentsItem.cpp + src/gui/feeds/PeerItem.cpp + src/gui/feeds/MsgItem.cpp + src/gui/feeds/ChatMsgItem.cpp + src/gui/feeds/SubFileItem.cpp + src/gui/feeds/AttachFileItem.cpp + src/gui/feeds/SecurityItem.cpp + src/gui/feeds/SecurityIpItem.cpp + src/gui/feeds/NewsFeedUserNotify.cpp + + src/gui/groups/CreateGroup.cpp + + src/gui/statistics/BandwidthGraphWindow.cpp + src/gui/statistics/BandwidthStatsWidget.cpp + src/gui/statistics/DhtWindow.cpp + src/gui/statistics/Histogram.cpp + src/gui/statistics/TurtleRouterDialog.cpp + src/gui/statistics/TurtleRouterStatistics.cpp + src/gui/statistics/GxsIdStatistics.cpp + src/gui/statistics/GlobalRouterStatistics.cpp + src/gui/statistics/GxsTransportStatistics.cpp + src/gui/statistics/StatisticsWindow.cpp + src/gui/statistics/BwCtrlWindow.cpp + src/gui/statistics/RttStatistics.cpp + src/gui/statistics/BWGraph.cpp + + src/util/RsSyntaxHighlighter.cpp + src/util/imageutil.cpp + src/util/retroshareWin32.cpp + + src/gui/NetworkDialog/pgpid_item_model.cpp + src/gui/NetworkDialog/pgpid_item_proxy.cpp + ) + +list( + APPEND RS_GUI_FORMS + src/TorControl/TorControlWindow.ui + + src/gui/StartDialog.ui + src/gui/HomePage.ui + src/gui/GetStartedDialog.ui + src/gui/GenCertDialog.ui + src/gui/AboutDialog.ui + src/gui/AboutWidget.ui + src/gui/QuickStartWizard.ui + src/gui/NetworkDialog.ui + src/gui/common/AvatarDialog.ui + src/gui/MainWindow.ui + src/gui/NetworkView.ui + src/gui/FriendsDialog.ui + src/gui/NewsFeed.ui + src/gui/ShareManager.ui + src/gui/help/browser/helpbrowser.ui + src/gui/HelpDialog.ui + src/gui/ServicePermissionDialog.ui + src/gui/ChatLobbyWidget.ui + + src/gui/FileTransfer/TransfersDialog.ui + src/gui/FileTransfer/DetailsDialog.ui + src/gui/FileTransfer/SearchDialog.ui + src/gui/FileTransfer/SharedFilesDialog.ui + src/gui/FileTransfer/BannedFilesDialog.ui + + src/gui/profile/ProfileWidget.ui + src/gui/profile/StatusMessage.ui + src/gui/profile/ProfileManager.ui + + src/gui/chat/PopupChatWindow.ui + src/gui/chat/PopupChatDialog.ui + src/gui/chat/ChatTabWidget.ui + src/gui/chat/ChatWidget.ui + src/gui/chat/ChatLobbyDialog.ui + src/gui/chat/CreateLobbyDialog.ui + + src/gui/connect/ConfCertDialog.ui + src/gui/connect/PGPKeyDialog.ui + src/gui/connect/ConnectFriendWizard.ui + src/gui/connect/ConnectProgressDialog.ui + src/gui/connect/FriendRecommendDialog.ui + + src/gui/msgs/MessagesDialog.ui + src/gui/msgs/MessageComposer.ui + src/gui/msgs/MessageWindow.ui + src/gui/msgs/MessageWidget.ui + + src/gui/settings/settingsw.ui + src/gui/settings/GeneralPage.ui + src/gui/settings/ServerPage.ui + src/gui/settings/NotifyPage.ui + src/gui/settings/PeoplePage.ui + src/gui/settings/CryptoPage.ui + src/gui/settings/MessagePage.ui + src/gui/settings/NewTag.ui + src/gui/settings/ForumPage.ui + src/gui/settings/AboutPage.ui + src/gui/settings/PluginsPage.ui + src/gui/settings/AppearancePage.ui + src/gui/settings/TransferPage.ui + src/gui/settings/SoundPage.ui + src/gui/settings/ChatPage.ui + src/gui/settings/ChannelPage.ui + src/gui/settings/PostedPage.ui + src/gui/settings/ServicePermissionsPage.ui + src/gui/settings/PluginItem.ui + src/gui/settings/GroupFrameSettingsWidget.ui + + src/gui/toaster/MessageToaster.ui + src/gui/toaster/OnlineToaster.ui + src/gui/toaster/DownloadToaster.ui + src/gui/toaster/ChatToaster.ui + src/gui/toaster/GroupChatToaster.ui + src/gui/toaster/ChatLobbyToaster.ui + src/gui/toaster/FriendRequestToaster.ui + + src/gui/advsearch/AdvancedSearchDialog.ui + src/gui/advsearch/expressionwidget.ui + + src/gui/feeds/BoardsCommentsItem.ui + src/gui/feeds/GxsCircleItem.ui + src/gui/feeds/ChannelsCommentsItem.ui + src/gui/feeds/PeerItem.ui + src/gui/feeds/MsgItem.ui + src/gui/feeds/ChatMsgItem.ui + src/gui/feeds/SubFileItem.ui + src/gui/feeds/AttachFileItem.ui + src/gui/feeds/SecurityItem.ui + src/gui/feeds/SecurityIpItem.ui + + src/gui/im_history/ImHistoryBrowser.ui + + src/gui/groups/CreateGroup.ui + + src/gui/common/GroupTreeWidget.ui + src/gui/common/AvatarWidget.ui + src/gui/common/NewFriendList.ui + src/gui/common/FriendSelectionWidget.ui + src/gui/common/HashBox.ui + src/gui/common/RSImageBlockWidget.ui + src/gui/common/RsCollectionDialog.ui + src/gui/common/HeaderFrame.ui + src/gui/common/RSFeedWidget.ui + + src/gui/style/StyleDialog.ui + + src/gui/statistics/BandwidthGraphWindow.ui + src/gui/statistics/BandwidthStatsWidget.ui + src/gui/statistics/DhtWindow.ui + src/gui/statistics/TurtleRouterDialog.ui + src/gui/statistics/TurtleRouterStatistics.ui + src/gui/statistics/GxsIdStatistics.ui + src/gui/statistics/GlobalRouterStatistics.ui + src/gui/statistics/GxsTransportStatistics.ui + src/gui/statistics/StatisticsWindow.ui + src/gui/statistics/BwCtrlWindow.ui + src/gui/statistics/RttStatistics.ui + + src/util/RichTextEdit.ui + ) + +list( + APPEND RS_IMPLEMENTATION_HEADERS + + src/TorControl/TorControlWindow.h + + src/chat/distantchat.h + src/chat/distributedchat.h + src/chat/p3chatservice.h + src/chat/rschatitems.h + + src/rshare.h + src/retroshare-gui/configpage.h + src/retroshare-gui/RsAutoUpdatePage.h + src/retroshare-gui/mainpage.h + + src/control/bandwidthevent.h + src/control/eventtype.h + + src/gui/QuickStartWizard.h + src/gui/notifyqt.h + src/gui/GetStartedDialog.h + src/gui/StartDialog.h + src/gui/HomePage.h + src/gui/NetworkDialog.h + src/gui/GenCertDialog.h + src/gui/linetypes.h + src/gui/mainpagestack.h + src/gui/MainWindow.h + src/gui/RSHumanReadableDelegate.h + src/gui/AboutDialog.h + src/gui/AboutWidget.h + src/gui/NetworkView.h + src/gui/FriendsDialog.h + src/gui/ServicePermissionDialog.h + src/gui/RemoteDirModel.h + src/gui/RetroShareLink.h + src/gui/SearchTreeWidget.h + src/gui/ShareManager.h + src/gui/NewsFeed.h + src/gui/ShareDialog.h + src/gui/SFListDelegate.h + src/gui/SoundManager.h + src/gui/HelpDialog.h + src/gui/LogoBar.h + + src/gui/common/AvatarDialog.h + + src/gui/NetworkDialog/pgpid_item_model.h + src/gui/NetworkDialog/pgpid_item_proxy.h + + src/gui/FileTransfer/SearchDialog.h + src/gui/FileTransfer/SharedFilesDialog.h + src/gui/FileTransfer/xprogressbar.h + src/gui/FileTransfer/DetailsDialog.h + src/gui/FileTransfer/FileTransferInfoWidget.h + src/gui/FileTransfer/DLListDelegate.h + src/gui/FileTransfer/ULListDelegate.h + src/gui/FileTransfer/TransfersDialog.h + src/gui/FileTransfer/BannedFilesDialog.h + src/gui/FileTransfer/TransferUserNotify.h + + src/gui/statistics/TurtleRouterDialog.h + src/gui/statistics/TurtleRouterStatistics.h + src/gui/statistics/GxsIdStatistics.h + src/gui/statistics/dhtgraph.h + src/gui/statistics/Histogram.h + src/gui/statistics/BandwidthGraphWindow.h + src/gui/statistics/turtlegraph.h + src/gui/statistics/BandwidthStatsWidget.h + src/gui/statistics/DhtWindow.h + src/gui/statistics/GlobalRouterStatistics.h + src/gui/statistics/GxsTransportStatistics.h + src/gui/statistics/StatisticsWindow.h + src/gui/statistics/BwCtrlWindow.h + src/gui/statistics/BWGraph.h + src/gui/statistics/RttStatistics.h + + src/gui/plugins/PluginInterface.h + + src/gui/im_history/ImHistoryBrowser.h + src/gui/im_history/IMHistoryItemDelegate.h + src/gui/im_history/IMHistoryItemPainter.h + + src/lang/languagesupport.h + + src/util/RsSyntaxHighlighter.h + src/util/imageutil.h + src/util/RichTextEdit.h + src/util/retroshareWin32.h + src/util/RsProtectedTimer.h + src/util/stringutil.h + src/util/RsNetUtil.h + src/util/DateTime.h + src/util/RetroStyleLabel.h + src/util/dllexport.h + src/util/NonCopyable.h + src/util/rsutildll.h + src/util/dllexport.h + src/util/global.h + src/util/rsqtutildll.h + src/util/Interface.h + src/util/PixmapMerging.h + src/util/MouseEventFilter.h + src/util/EventFilter.h + src/util/Widget.h + src/util/RsAction.h + src/util/RsUserdata.h + src/util/printpreview.h + src/util/log.h + src/util/misc.h + src/util/HandleRichText.h + src/util/ObjectPainter.h + src/util/QtVersion.h + src/util/RsFile.h + src/util/qtthreadsutils.h + src/util/ClickableLabel.h + src/util/AspectRatioPixmapLabel.h + + src/gui/profile/ProfileWidget.h + src/gui/profile/ProfileManager.h + src/gui/profile/StatusMessage.h + + src/gui/chat/PopupChatWindow.h + src/gui/chat/PopupChatDialog.h + src/gui/chat/PopupDistantChatDialog.h + src/gui/chat/ChatTabWidget.h + src/gui/chat/ChatWidget.h + src/gui/chat/ChatDialog.h + src/gui/ChatLobbyWidget.h + src/gui/chat/ChatLobbyDialog.h + src/gui/chat/CreateLobbyDialog.h + src/gui/chat/ChatStyle.h + src/gui/chat/ChatUserNotify.h + src/gui/chat/ChatLobbyUserNotify.h + + src/gui/connect/ConfCertDialog.h + src/gui/connect/PGPKeyDialog.h + src/gui/connect/FriendRecommendDialog.h + + src/gui/msgs/MessagesDialog.h + src/gui/msgs/MessageInterface.h + src/gui/msgs/MessageComposer.h + src/gui/msgs/MessageWindow.h + src/gui/msgs/MessageWidget.h + src/gui/msgs/MessageModel.h + src/gui/msgs/TagsMenu.h + src/gui/msgs/textformat.h + src/gui/msgs/MessageUserNotify.h + + src/gui/images/retroshare_win.rc.h + + src/gui/settings/RSPermissionMatrixWidget.h + src/gui/settings/rsharesettings.h + src/gui/settings/RsharePeerSettings.h + src/gui/settings/rsettings.h + src/gui/settings/rsettingswin.h + src/gui/settings/GeneralPage.h + src/gui/settings/PeoplePage.h + src/gui/settings/AboutPage.h + src/gui/settings/ServerPage.h + src/gui/settings/NotifyPage.h + src/gui/settings/CryptoPage.h + src/gui/settings/MessagePage.h + src/gui/settings/NewTag.h + src/gui/settings/ForumPage.h + src/gui/settings/PluginsPage.h + src/gui/settings/PluginItem.h + src/gui/settings/AppearancePage.h + src/gui/settings/FileAssociationsPage.h + src/gui/settings/SoundPage.h + src/gui/settings/TransferPage.h + src/gui/settings/ChatPage.h + src/gui/settings/ChannelPage.h + src/gui/settings/PostedPage.h + src/gui/settings/ServicePermissionsPage.h + src/gui/settings/AddFileAssociationDialog.h + src/gui/settings/GroupFrameSettingsWidget.h + + src/gui/toaster/ToasterItem.h + src/gui/toaster/MessageToaster.h + src/gui/toaster/OnlineToaster.h + src/gui/toaster/DownloadToaster.h + src/gui/toaster/ChatToaster.h + src/gui/toaster/GroupChatToaster.h + src/gui/toaster/ChatLobbyToaster.h + src/gui/toaster/FriendRequestToaster.h + + src/gui/common/RsButtonOnText.h + src/gui/common/RsCollection.h + src/gui/common/RSGraphWidget.h + src/gui/common/ElidedLabel.h + src/gui/common/vmessagebox.h + src/gui/common/RsUrlHandler.h + src/gui/common/RsCollectionDialog.h + src/gui/common/rwindow.h + src/gui/common/rshtml.h + src/gui/common/AvatarDefs.h + src/gui/common/GroupFlagsWidget.h + src/gui/common/GroupSelectionBox.h + src/gui/common/GroupChooser.h + src/gui/common/StatusDefs.h + src/gui/common/TagDefs.h + src/gui/common/GroupDefs.h + src/gui/common/Emoticons.h + src/gui/common/RSComboBox.h + src/gui/common/RSListWidgetItem.h + src/gui/common/RSTextEdit.h + src/gui/common/RSPlainTextEdit.h + src/gui/common/RSTreeWidget.h + src/gui/common/RSTreeWidgetItem.h + src/gui/common/RSFeedWidget.h + src/gui/common/RSTabWidget.h + src/gui/common/RSElidedItemDelegate.h + src/gui/common/RSItemDelegate.h + src/gui/common/PeerDefs.h + src/gui/common/FilesDefs.h + src/gui/common/PopularityDefs.h + src/gui/common/RsBanListDefs.h + src/gui/common/GroupTreeWidget.h + src/gui/common/RSTreeView.h + src/gui/common/AvatarWidget.h + src/gui/common/FriendListModel.h + src/gui/common/NewFriendList.h + src/gui/common/FriendSelectionWidget.h + src/gui/common/FriendSelectionDialog.h + src/gui/common/HashBox.h + src/gui/common/LineEditClear.h + src/gui/common/DropLineEdit.h + src/gui/common/RSTextBrowser.h + src/gui/common/RSImageBlockWidget.h + src/gui/common/FeedNotify.h + src/gui/common/UserNotify.h + src/gui/common/HeaderFrame.h + src/gui/common/MimeTextEdit.h + src/gui/common/UIStateHelper.h + src/gui/common/FloatingHelpBrowser.h + src/gui/common/SubscribeToolButton.h + src/gui/common/RsBanListToolButton.h + src/gui/common/FlowLayout.h + src/gui/common/PictureFlow.h + src/gui/common/ToasterNotify.h + + src/gui/style/RSStyle.h + src/gui/style/StyleDialog.h + + src/gui/help/browser/helpbrowser.h + src/gui/help/browser/helptextbrowser.h + + src/gui/statusbar/peerstatus.h + src/gui/statusbar/natstatus.h + src/gui/statusbar/dhtstatus.h + src/gui/statusbar/torstatus.h + src/gui/statusbar/ratesstatus.h + src/gui/statusbar/hashingstatus.h + src/gui/statusbar/discstatus.h + src/gui/statusbar/SoundStatus.h + src/gui/statusbar/OpModeStatus.h + src/gui/statusbar/ToasterDisable.h + src/gui/statusbar/SysTrayStatus.h + + src/gui/advsearch/advancedsearchdialog.h + src/gui/advsearch/expressionwidget.h + src/gui/advsearch/guiexprelement.h + + src/gui/elastic/graphwidget.h + src/gui/elastic/edge.h + src/gui/elastic/arrow.h + src/gui/elastic/elnode.h + + src/gui/feeds/BoardsCommentsItem.h + src/gui/feeds/FeedItem.h + src/gui/feeds/FeedHolder.h + src/gui/feeds/GxsCircleItem.h + src/gui/feeds/ChannelsCommentsItem.h + src/gui/feeds/PeerItem.h + src/gui/feeds/MsgItem.h + src/gui/feeds/ChatMsgItem.h + src/gui/feeds/SubFileItem.h + src/gui/feeds/AttachFileItem.h + src/gui/feeds/SecurityItem.h + src/gui/feeds/SecurityIpItem.h + src/gui/feeds/NewsFeedUserNotify.h + + src/gui/connect/ConnectFriendWizard.h + src/gui/connect/ConnectProgressDialog.h + + src/gui/groups/CreateGroup.h + ) + +if(RS_JSON_API) + list( + APPEND RS_GUI_SOURCES + src/gui/settings/JsonApiPage.cc + ) + + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/gui/settings/JsonApiPage.h + ) + + list( + APPEND RS_GUI_FORMS + src/gui/settings/JsonApiPage.ui + ) +endif(RS_JSON_API) + +if(RS_WEBUI) + list( + APPEND RS_GUI_SOURCES + src/gui/settings/WebuiPage.cpp + ) + + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/jsonapi/p3webui.h + src/gui/settings/WebuiPage.h + ) + + list( + APPEND RS_GUI_FORMS + src/gui/settings/WebuiPage.ui + ) +endif(RS_WEBUI) + +list( + APPEND RS_GUI_QTRESOURCES + src/gui/images.qrc + src/gui/icons.qrc + src/lang/lang.qrc + src/gui/help/content/content.qrc + src/gui/emojione.qrc + src/gui/qss/stylesheet/qdarkstyle/dark/Standard_Dark.qrc + src/gui/qss/stylesheet/qdarkstyle/light/Standard_Light.qrc + ) + +list( + APPEND RS_TRANSLATIONS + src/lang/retroshare_ca_ES.ts + src/lang/retroshare_cs.ts + src/lang/retroshare_da.ts + src/lang/retroshare_de.ts + src/lang/retroshare_el.ts + src/lang/retroshare_en.ts + src/lang/retroshare_es.ts + src/lang/retroshare_fi.ts + src/lang/retroshare_fr.ts + src/lang/retroshare_hu.ts + src/lang/retroshare_it.ts + src/lang/retroshare_ja_JP.ts + src/lang/retroshare_nl.ts + src/lang/retroshare_ko.ts + src/lang/retroshare_pl.ts + src/lang/retroshare_ru.ts + src/lang/retroshare_sv.ts + src/lang/retroshare_tr.ts + src/lang/retroshare_zh_CN.ts + ) + +if(RS_UNFINISHED_TRANSLATIONS) + list( + APPEND RS_TRANSLATIONS + src/lang/retroshare_bg.ts + src/lang/retroshare_af.ts + src/lang/retroshare_pt.ts + src/lang/retroshare_sl.ts + src/lang/retroshare_sr.ts + src/lang/retroshare_zh_TW.ts + ) +endif(RS_UNFINISHED_TRANSLATIONS) + +if(RS_MESSENGER) + + target_compile_definitions( ${PROJECT_NAME} PUBLIC MESSENGER_WINDOW ) + + list( + APPEND RS_GUI_SOURCES + src/gui/MessengerWindow.cpp + src/gui/common/FriendList.cpp + ) + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/gui/MessengerWindow.h + src/gui/common/FriendList.h + ) + list( + APPEND RS_GUI_FORMS + src/gui/MessengerWindow.ui + src/gui/common/FriendList.ui + ) +endif(RS_MESSENGER) + +if(RS_IDLE) + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/idle/idle.h + ) + list( + APPEND RS_GUI_SOURCES + src/idle/idle.cpp + src/idle/idle_platform.cpp + ) +endif(RS_IDLE) + +if(RS_FRAMECATCHER) + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/util/framecatcher.h + ) + list( + APPEND RS_GUI_SOURCES + src/util/framecatcher.cpp + ) + + # TODO: LIBS += -lxine + + target_compile_definitions( + ${PROJECT_NAME} PUBLIC CHANNELS_FRAME_CATCHER + ) +endif(RS_FRAMECATCHER) + +# Embedded Friend Server + +if(RS_EFS) + target_compile_definitions( + ${PROJECT_NAME} PUBLIC RS_EMBEDED_FRIEND_SERVER + ) + list( + APPEND RS_GUI_SOURCES + src/gui/FriendServerControl.cpp + ) + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/gui/FriendServerControl.h + ) + list( + APPEND RS_GUI_FORMS + src/gui/FriendServerControl.ui + ) +endif(RS_EFS) + +# BELOW IS GXS Unfinished Services. + +if(RS_UNFINISHED) + + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/gui/unfinished/ApplicationWindow.h + + # gui/unfinished/CalDialog.h + # gui/unfinished/ExampleDialog.h + # gui/unfinished/GamesDialog.h + # gui/unfinished/profile/ProfileView.h + # gui/unfinished/profile/ProfileEdit.h + # gui/unfinished/StatisticDialog.h + # gui/unfinished/PhotoDialog.h + # gui/unfinished/PhotoShow.h + ) + + list( + APPEND RS_GUI_FORMS + src/gui/unfinished/ApplicationWindow.ui + + # gui/unfinished/CalDialog.ui + # gui/unfinished/ExampleDialog.ui + # gui/unfinished/GamesDialog.ui + # gui/unfinished/profile/ProfileView.ui + # gui/unfinished/profile/ProfileEdit.ui + # gui/unfinished/StatisticDialog.ui + # gui/unfinished/PhotoDialog.ui + # gui/unfinished/PhotoShow.ui + ) + + list( + APPEND RS_GUI_SOURCES + src/gui/unfinished/ApplicationWindow.cpp + + # gui/unfinished/CalDialog.cpp + # gui/unfinished/ExampleDialog.cpp + # gui/unfinished/GamesDialog.cpp + # gui/unfinished/profile/ProfileView.cpp + # gui/unfinished/profile/ProfileEdit.cpp + # gui/unfinished/StatisticDialog.cpp + # gui/unfinished/PhotoDialog.cpp + # gui/unfinished/PhotoShow.cpp + ) + + target_compile_definitions( + ${PROJECT_NAME} PUBLIC UNFINISHED + ) +endif(RS_UNFINISHED) + +if(RS_GXSPHOTOSHARE) + target_compile_definitions( + ${PROJECT_NAME} PUBLIC RS_USE_PHOTO + ) + + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/gui/PhotoShare/AlbumGroupDialog.h + src/gui/PhotoShare/AlbumExtra.h + src/gui/PhotoShare/PhotoDrop.h + src/gui/PhotoShare/AlbumItem.h + src/gui/PhotoShare/AlbumDialog.h + src/gui/PhotoShare/PhotoItem.h + src/gui/PhotoShare/PhotoShareItemHolder.h + src/gui/PhotoShare/PhotoShare.h + src/gui/PhotoShare/PhotoSlideShow.h + src/gui/PhotoShare/PhotoDialog.h + ) + list( + APPEND RS_GUI_FORMS + src/gui/PhotoShare/AlbumExtra.ui + src/gui/PhotoShare/PhotoItem.ui + src/gui/PhotoShare/PhotoDialog.ui + src/gui/PhotoShare/AlbumItem.ui + src/gui/PhotoShare/AlbumDialog.ui + src/gui/PhotoShare/PhotoShare.ui + src/gui/PhotoShare/PhotoSlideShow.ui + ) + + list( + APPEND RS_GUI_SOURCES + src/gui/PhotoShare/AlbumGroupDialog.cpp + src/gui/PhotoShare/AlbumExtra.cpp + src/gui/PhotoShare/PhotoItem.cpp + src/gui/PhotoShare/PhotoDialog.cpp + src/gui/PhotoShare/PhotoDrop.cpp + src/gui/PhotoShare/AlbumItem.cpp + src/gui/PhotoShare/AlbumDialog.cpp + src/gui/PhotoShare/PhotoShareItemHolder.cpp + src/gui/PhotoShare/PhotoShare.cpp + src/gui/PhotoShare/PhotoSlideShow.cpp + ) + + list( + APPEND RS_GUI_QTRESOURCES + src/gui/PhotoShare/Photo_images.qrc + ) +endif(RS_GXSPHOTOSHARE) + +if(RS_GXSWIKIPOS) + target_compile_definitions( + ${PROJECT_NAME} PUBLIC RS_USE_WIKI + ) + + target_include_directories(${PROJECT_NAME} PUBLIC ../../supportlibs/pegmarkdown) + + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/gui/WikiPoos/WikiDialog.h + src/gui/WikiPoos/WikiAddDialog.h + src/gui/WikiPoos/WikiEditDialog.h + src/gui/gxs/WikiGroupDialog.h + src/gui/gxs/RsGxsUpdateBroadcastBase.h + src/gui/gxs/RsGxsUpdateBroadcastWidget.h + src/gui/gxs/RsGxsUpdateBroadcastPage.h + ) + + list( + APPEND RS_GUI_FORMS + src/gui/WikiPoos/WikiDialog.ui + src/gui/WikiPoos/WikiAddDialog.ui + src/gui/WikiPoos/WikiEditDialog.ui + ) + + list( + APPEND RS_GUI_SOURCES + src/gui/WikiPoos/WikiDialog.cpp + src/gui/WikiPoos/WikiAddDialog.cpp + src/gui/WikiPoos/WikiEditDialog.cpp + src/gui/gxs/WikiGroupDialog.cpp + src/gui/gxs/RsGxsUpdateBroadcastBase.cpp + src/gui/gxs/RsGxsUpdateBroadcastWidget.cpp + src/gui/gxs/RsGxsUpdateBroadcastPage.cpp + ) + + list( + APPEND RS_GUI_QTRESOURCES + src/gui/WikiPoos/Wiki_images.qrc + ) +endif(RS_GXSWIKIPOS) + +if(RS_GXSTHEWIRE) + target_compile_definitions( + ${PROJECT_NAME} PUBLIC RS_USE_WIRE + ) + + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/gui/TheWire/WireDialog.h + src/gui/TheWire/WireGroupItem.h + src/gui/TheWire/WireGroupDialog.h + src/gui/TheWire/WireGroupExtra.h + src/gui/TheWire/PulseAddDialog.h + src/gui/TheWire/PulseViewItem.h + src/gui/TheWire/PulseTopLevel.h + src/gui/TheWire/PulseViewGroup.h + src/gui/TheWire/PulseReply.h + src/gui/TheWire/PulseReplySeperator.h + src/gui/TheWire/PulseMessage.h + ) + + list( + APPEND RS_GUI_FORMS + src/gui/TheWire/WireDialog.ui + src/gui/TheWire/WireGroupItem.ui + src/gui/TheWire/WireGroupExtra.ui + src/gui/TheWire/PulseAddDialog.ui + src/gui/TheWire/PulseTopLevel.ui + src/gui/TheWire/PulseViewGroup.ui + src/gui/TheWire/PulseReply.ui + src/gui/TheWire/PulseReplySeperator.ui + src/gui/TheWire/PulseMessage.ui + ) + + list( + APPEND RS_GUI_SOURCES + src/gui/TheWire/WireDialog.cpp + src/gui/TheWire/WireGroupItem.cpp + src/gui/TheWire/WireGroupDialog.cpp + src/gui/TheWire/WireGroupExtra.cpp + src/gui/TheWire/PulseAddDialog.cpp + src/gui/TheWire/PulseViewItem.cpp + src/gui/TheWire/PulseTopLevel.cpp + src/gui/TheWire/PulseViewGroup.cpp + src/gui/TheWire/PulseReply.cpp + src/gui/TheWire/PulseReplySeperator.cpp + src/gui/TheWire/PulseMessage.cpp + ) + + list( + APPEND RS_GUI_QTRESOURCES + RESOURCES += src/gui/TheWire/TheWire_images.qrc + ) +endif(RS_GXSTHEWIRE) + +if(RS_GXSIDENTITIES) + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/gui/Identity/IdDialog.h + src/gui/Identity/IdEditDialog.h + src/gui/Identity/IdDetailsDialog.h + ) + + list( + APPEND RS_GUI_FORMS + src/gui/Identity/IdDialog.ui + src/gui/Identity/IdEditDialog.ui + src/gui/Identity/IdDetailsDialog.ui + ) + + list( + APPEND RS_GUI_SOURCES + src/gui/Identity/IdDialog.cpp + src/gui/Identity/IdEditDialog.cpp + src/gui/Identity/IdDetailsDialog.cpp + ) +endif(RS_GXSIDENTITIES) + +if(RS_GXSCIRCLES) + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/gui/Circles/CirclesDialog.h + src/gui/Circles/CreateCircleDialog.h + src/gui/People/PeopleDialog.h + src/gui/People/CircleWidget.h + src/gui/People/IdentityWidget.h + ) + + list( + APPEND RS_GUI_FORMS + src/gui/Circles/CirclesDialog.ui + src/gui/Circles/CreateCircleDialog.ui + src/gui/People/PeopleDialog.ui + src/gui/People/CircleWidget.ui + src/gui/People/IdentityWidget.ui + ) + + list( + APPEND RS_GUI_SOURCES + src/gui/Circles/CirclesDialog.cpp + src/gui/Circles/CreateCircleDialog.cpp + src/gui/People/PeopleDialog.cpp + src/gui/People/CircleWidget.cpp + src/gui/People/IdentityWidget.cpp + ) +endif(RS_GXSCIRCLES) + +if(RS_GXSGUI) + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/gui/gxs/GxsGroupDialog.h + src/gui/gxs/GxsIdDetails.h + src/gui/gxs/GxsIdChooser.h + src/gui/gxs/GxsIdLabel.h + src/gui/gxs/GxsCircleChooser.h + src/gui/gxs/GxsCircleLabel.h + src/gui/gxs/GxsIdTreeWidgetItem.h + src/gui/gxs/GxsCommentTreeWidget.h + src/gui/gxs/GxsCommentContainer.h + src/gui/gxs/GxsCommentDialog.h + src/gui/gxs/GxsCreateCommentDialog.h + src/gui/gxs/GxsGroupFrameDialog.h + src/gui/gxs/GxsMessageFrameWidget.h + src/gui/gxs/GxsMessageFramePostWidget.h + src/gui/gxs/GxsGroupFeedItem.h + src/gui/gxs/GxsFeedItem.h + src/gui/gxs/GxsGroupShareKey.h + src/gui/gxs/GxsUserNotify.h + src/gui/gxs/GxsFeedWidget.h + src/util/TokenQueue.h + src/util/RsGxsUpdateBroadcast.h + ) + + list( + APPEND RS_GUI_FORMS + src/gui/gxs/GxsGroupDialog.ui + src/gui/gxs/GxsCommentContainer.ui + src/gui/gxs/GxsCommentDialog.ui + src/gui/gxs/GxsCreateCommentDialog.ui + src/gui/gxs/GxsGroupFrameDialog.ui + src/gui/gxs/GxsGroupShareKey.ui + ) + + list( + APPEND RS_GUI_SOURCES + src/gui/gxs/GxsGroupDialog.cpp + src/gui/gxs/GxsIdDetails.cpp + src/gui/gxs/GxsIdChooser.cpp + src/gui/gxs/GxsIdLabel.cpp + src/gui/gxs/GxsCircleChooser.cpp + src/gui/gxs/GxsGroupShareKey.cpp + src/gui/gxs/GxsCircleLabel.cpp + src/gui/gxs/GxsIdTreeWidgetItem.cpp + src/gui/gxs/GxsCommentTreeWidget.cpp + src/gui/gxs/GxsCommentContainer.cpp + src/gui/gxs/GxsCommentDialog.cpp + src/gui/gxs/GxsCreateCommentDialog.cpp + src/gui/gxs/GxsGroupFrameDialog.cpp + src/gui/gxs/GxsMessageFrameWidget.cpp + src/gui/gxs/GxsMessageFramePostWidget.cpp + src/gui/gxs/GxsGroupFeedItem.cpp + src/gui/gxs/GxsFeedItem.cpp + src/gui/gxs/GxsUserNotify.cpp + src/gui/gxs/GxsFeedWidget.cpp + src/util/TokenQueue.cpp + src/util/RsGxsUpdateBroadcast.cpp + ) +endif(RS_GXSGUI) + +if(RS_GXSFORUMS) + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/gui/gxsforums/GxsForumsDialog.h + src/gui/gxsforums/GxsForumGroupDialog.h + src/gui/gxsforums/CreateGxsForumMsg.h + src/gui/gxsforums/GxsForumThreadWidget.h + src/gui/gxsforums/GxsForumModel.h + src/gui/gxsforums/GxsForumUserNotify.h + src/gui/feeds/GxsForumGroupItem.h + src/gui/feeds/GxsForumMsgItem.h + ) + + list( + APPEND RS_GUI_FORMS + src/gui/gxsforums/CreateGxsForumMsg.ui + src/gui/gxsforums/GxsForumThreadWidget.ui + src/gui/feeds/GxsForumGroupItem.ui + src/gui/feeds/GxsForumMsgItem.ui + ) + + list( + APPEND RS_GUI_SOURCES + src/gui/gxsforums/GxsForumsDialog.cpp + src/gui/gxsforums/GxsForumGroupDialog.cpp + src/gui/gxsforums/CreateGxsForumMsg.cpp + src/gui/gxsforums/GxsForumThreadWidget.cpp + src/gui/gxsforums/GxsForumModel.cpp + src/gui/gxsforums/GxsForumUserNotify.cpp + src/gui/feeds/GxsForumGroupItem.cpp + src/gui/feeds/GxsForumMsgItem.cpp + ) +endif(RS_GXSFORUMS) + + +if(RS_GXSCHANNELS) + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/gui/gxschannels/GxsChannelDialog.h + src/gui/gxschannels/GxsChannelGroupDialog.h + src/gui/gxschannels/CreateGxsChannelMsg.h + src/gui/gxschannels/GxsChannelPostsWidgetWithModel.h + src/gui/gxschannels/GxsChannelPostsModel.h + src/gui/gxschannels/GxsChannelPostFilesModel.h + src/gui/gxschannels/GxsChannelPostThumbnail.h + src/gui/gxschannels/GxsChannelFilesStatusWidget.h + src/gui/feeds/GxsChannelGroupItem.h + src/gui/feeds/GxsChannelPostItem.h + src/gui/gxschannels/GxsChannelUserNotify.h + ) + + list( + APPEND RS_GUI_FORMS + src/gui/gxschannels/GxsChannelPostsWidgetWithModel.ui + src/gui/gxschannels/GxsChannelFilesStatusWidget.ui + src/gui/gxschannels/CreateGxsChannelMsg.ui + src/gui/feeds/GxsChannelGroupItem.ui + src/gui/feeds/GxsChannelPostItem.ui + ) + + list( + APPEND RS_GUI_SOURCES + src/gui/gxschannels/GxsChannelDialog.cpp + src/gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp + src/gui/gxschannels/GxsChannelPostsModel.cpp + src/gui/gxschannels/GxsChannelPostFilesModel.cpp + src/gui/gxschannels/GxsChannelFilesStatusWidget.cpp + src/gui/gxschannels/GxsChannelPostThumbnail.cpp + src/gui/gxschannels/GxsChannelGroupDialog.cpp + src/gui/gxschannels/CreateGxsChannelMsg.cpp + src/gui/feeds/GxsChannelGroupItem.cpp + src/gui/feeds/GxsChannelPostItem.cpp + src/gui/gxschannels/GxsChannelUserNotify.cpp + ) +endif(RS_GXSCHANNELS) + +if(RS_GXSPOSTED) + list( + APPEND RS_IMPLEMENTATION_HEADERS + src/gui/Posted/PostedDialog.h + src/gui/Posted/PostedListWidgetWithModel.h + src/gui/Posted/PostedPostsModel.h + src/gui/Posted/BoardPostDisplayWidget.h + src/gui/Posted/PostedItem.h + src/gui/Posted/PostedCardView.h + src/gui/Posted/PostedGroupDialog.h + src/gui/feeds/PostedGroupItem.h + src/gui/Posted/PostedCreatePostDialog.h + src/gui/Posted/PhotoView.h + src/gui/Posted/PostedUserNotify.h + ) + + list( + APPEND RS_GUI_FORMS + src/gui/Posted/PostedListWidgetWithModel.ui + src/gui/feeds/PostedGroupItem.ui + src/gui/Posted/BoardPostDisplayWidget_compact.ui + src/gui/Posted/BoardPostDisplayWidget_card.ui + src/gui/Posted/PostedItem.ui + src/gui/Posted/PostedCardView.ui + src/gui/Posted/PostedCreatePostDialog.ui + src/gui/Posted/PhotoView.ui + ) + + list( + APPEND RS_GUI_SOURCES + src/gui/Posted/PostedDialog.cpp + src/gui/Posted/PostedListWidgetWithModel.cpp + src/gui/Posted/BoardPostDisplayWidget.cpp + src/gui/Posted/PostedPostsModel.cpp + src/gui/feeds/PostedGroupItem.cpp + src/gui/Posted/PostedItem.cpp + src/gui/Posted/PostedCardView.cpp + src/gui/Posted/PostedGroupDialog.cpp + src/gui/Posted/PostedCreatePostDialog.cpp + src/gui/Posted/PhotoView.cpp + src/gui/Posted/PostedUserNotify.cpp + ) + + list( + APPEND RS_GUI_QTRESOURCES + src/gui/Posted/Posted_images.qrc + ) +endif(RS_GXSPOSTED) + + + diff --git a/retroshare-gui/src/README.txt b/retroshare-gui/src/README.txt index 7f7f35c8e..231d16b23 100644 --- a/retroshare-gui/src/README.txt +++ b/retroshare-gui/src/README.txt @@ -2,17 +2,14 @@ README for RetroShare ======================================================================================= -RetroShare web site . . . . http://retroshare.net/index.html +RetroShare web site . . . . https://retroshare.cc/ Developer's blog . . . . . https://retroshareteam.wordpress.com -Documentation . . . . . . . https://retroshare.readthedocs.io/en/latest/ -Support . . . . . . . . . . http://retroshare.net/support.html -Forums . . . . . . . . . . http://retroshare.sourceforge.net/forum/ +Documentation . . . . . . . https://retrosharedocs.readthedocs.io/en/latest/ Wiki . . . . . . . . . . . https://github.com/RetroShare/documentation/wiki -Old developers site . . . . http://retroshare.sourceforge.net/wiki/index.php/Developers_Corner Project site . . . . . . . https://github.com/RetroShare/RetroShare -Relted projects/plugins . . https://github.com/RetroShare +Related projects/plugins . .https://github.com/RetroShare -Contact: . . . . . . . . . retroshare@lunamutt.com ,defnax@users.sourceforge.net +Contact: . . . . . . . . . retroshare.project@gmail.com ========================================================================================= Compiling RetroShare @@ -22,9 +19,9 @@ Build Scripts are avaible on GIT: https://github.com/RetroShare/RetroShare/tree/master/build_scripts You can find here instructions howto compile RetroShare: -https://retroshare.readthedocs.io/en/latest/developer/compilation/ +https://retrosharedocs.readthedocs.io/en/latest/developer/compilation/ -You can go on over to our forum or chat lobby when you have trouble with compiling: +You can go on over to our forum or chat room when you have trouble with compiling: retroshare://forum?name=Developers%20Discussions&id=8fd22bd8f99754461e7ba1ca8a727995 retroshare://chat_room?name=Retroshare%20Devel%20%28signed%29&id=L68DB0A1E09BDA3A5 -http://retroshare.sourceforge.net/forum/ + diff --git a/retroshare-gui/src/TorControl/AddOnionCommand.cpp b/retroshare-gui/src/TorControl/AddOnionCommand.cpp deleted file mode 100644 index fb2047dc7..000000000 --- a/retroshare-gui/src/TorControl/AddOnionCommand.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2016, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "AddOnionCommand.h" -#include "HiddenService.h" -#include "CryptoKey.h" -#include "StrUtil.h" - -using namespace Tor; - -AddOnionCommand::AddOnionCommand(HiddenService *service) - : m_service(service) -{ - Q_ASSERT(m_service); -} - -bool AddOnionCommand::isSuccessful() const -{ - return statusCode() == 250 && m_errorMessage.isEmpty(); -} - -QByteArray AddOnionCommand::build() -{ - QByteArray out("ADD_ONION"); - - if (m_service->privateKey().isLoaded()) { - out += " "; - out += m_service->privateKey().bytes(); - } else { - //out += " NEW:RSA1024"; // this is v2. For v3, use NEW:BEST, or NEW:ED25519-V3 - //out += " NEW:ED25519-V3"; // this is v3. - out += " NEW:BEST"; // this is v3, but without control of key type. Generates a RSA1024 key on older Tor versions. - } - - foreach (const HiddenService::Target &target, m_service->targets()) { - out += " Port="; - out += QByteArray::number(target.servicePort); - out += ","; - out += target.targetAddress.toString().toLatin1(); - out += ":"; - out += QByteArray::number(target.targetPort); - } - - out.append("\r\n"); - return out; -} - -void AddOnionCommand::onReply(int statusCode, const QByteArray &data) -{ - TorControlCommand::onReply(statusCode, data); - if (statusCode != 250) { - m_errorMessage = QString::fromLatin1(data); - return; - } - - const QByteArray keyPrefix("PrivateKey="); - const QByteArray sidPrefix("ServiceID="); - - if(data.startsWith("ServiceID=")){ - QByteArray service_id = data.mid(sidPrefix.size()); - m_service->setServiceId(service_id); - } - - if (data.startsWith(keyPrefix)) { - - QByteArray keyData(data.mid(keyPrefix.size())); - CryptoKey key; - - if (!key.loadFromTorMessage(keyData)) { - m_errorMessage = QStringLiteral("Key structure check failed"); - return; - } - - m_service->setPrivateKey(key); - } -} - -void AddOnionCommand::onFinished(int statusCode) -{ - TorControlCommand::onFinished(statusCode); - if (isSuccessful()) - emit succeeded(); - else - emit failed(statusCode); -} - - diff --git a/retroshare-gui/src/TorControl/AddOnionCommand.h b/retroshare-gui/src/TorControl/AddOnionCommand.h deleted file mode 100644 index 7c0afaf5e..000000000 --- a/retroshare-gui/src/TorControl/AddOnionCommand.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2016, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ADDONIONCOMMAND_H -#define ADDONIONCOMMAND_H - -#include "TorControlCommand.h" -#include -#include -#include - -namespace Tor -{ - -class HiddenService; - -class AddOnionCommand : public TorControlCommand -{ - Q_OBJECT - Q_DISABLE_COPY(AddOnionCommand) - - Q_PROPERTY(QString errorMessage READ errorMessage CONSTANT) - Q_PROPERTY(bool successful READ isSuccessful CONSTANT) - -public: - AddOnionCommand(HiddenService *service); - - QByteArray build(); - - QString errorMessage() const { return m_errorMessage; } - bool isSuccessful() const; - -signals: - void succeeded(); - void failed(int code); - -protected: - HiddenService *m_service; - QString m_errorMessage; - - virtual void onReply(int statusCode, const QByteArray &data); - virtual void onFinished(int statusCode); -}; - -} - -#endif // ADDONIONCOMMAND_H - diff --git a/retroshare-gui/src/TorControl/AuthenticateCommand.cpp b/retroshare-gui/src/TorControl/AuthenticateCommand.cpp deleted file mode 100644 index 497c28f89..000000000 --- a/retroshare-gui/src/TorControl/AuthenticateCommand.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "AuthenticateCommand.h" - -using namespace Tor; - -AuthenticateCommand::AuthenticateCommand() -{ -} - -QByteArray AuthenticateCommand::build(const QByteArray &data) -{ - if (data.isNull()) - return QByteArray("AUTHENTICATE\r\n"); - - return QByteArray("AUTHENTICATE ") + data.toHex() + "\r\n"; -} - -void AuthenticateCommand::onReply(int statusCode, const QByteArray &data) -{ - TorControlCommand::onReply(statusCode, data); - m_statusMessage = QString::fromLatin1(data); -} - -void AuthenticateCommand::onFinished(int statusCode) -{ - if (statusCode == 515) { - m_statusMessage = QStringLiteral("Authentication failed - incorrect password"); - } else if (statusCode != 250) { - if (m_statusMessage.isEmpty()) - m_statusMessage = QStringLiteral("Authentication failed (error %1").arg(statusCode); - } - TorControlCommand::onFinished(statusCode); -} diff --git a/retroshare-gui/src/TorControl/AuthenticateCommand.h b/retroshare-gui/src/TorControl/AuthenticateCommand.h deleted file mode 100644 index 79c901d98..000000000 --- a/retroshare-gui/src/TorControl/AuthenticateCommand.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef AUTHENTICATECOMMAND_H -#define AUTHENTICATECOMMAND_H - -#include "TorControlCommand.h" - -namespace Tor -{ - -class AuthenticateCommand : public TorControlCommand -{ - Q_OBJECT - -public: - AuthenticateCommand(); - - QByteArray build(const QByteArray &data = QByteArray()); - - bool isSuccessful() const { return statusCode() == 250; } - QString errorMessage() const { return m_statusMessage; } - -protected: - virtual void onReply(int statusCode, const QByteArray &data); - virtual void onFinished(int statusCode); - -private: - QString m_statusMessage; -}; - -} - -#endif // AUTHENTICATECOMMAND_H diff --git a/retroshare-gui/src/TorControl/CryptoKey.cpp b/retroshare-gui/src/TorControl/CryptoKey.cpp deleted file mode 100644 index 9be9a6699..000000000 --- a/retroshare-gui/src/TorControl/CryptoKey.cpp +++ /dev/null @@ -1,527 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "CryptoKey.h" -#include "SecureRNG.h" -#include "Useful.h" -#include -#include -#include -#include -#include -#include - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) -void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) -{ - *p = r->p; - *q = r->q; -} -#define RSA_bits(o) (BN_num_bits((o)->n)) -#endif - -#ifdef TO_REMOVE -void base32_encode(char *dest, unsigned destlen, const char *src, unsigned srclen); -bool base32_decode(char *dest, unsigned destlen, const char *src, unsigned srclen); -#endif - -CryptoKey::CryptoKey() -{ -} - -CryptoKey::~CryptoKey() -{ - clear(); -} - -#ifdef TO_REMOVE -CryptoKey::Data::~Data() -{ - if (key) - { - RSA_free(key); - key = 0; - } -} -#endif - -void CryptoKey::clear() -{ - key_data.clear(); -} - -#ifdef TO_REMOVE -bool CryptoKey::loadFromData(const QByteArray &data, KeyType type, KeyFormat format) -{ - RSA *key = NULL; - clear(); - - if (data.isEmpty()) - return false; - - if (format == PEM) { - BIO *b = BIO_new_mem_buf((void*)data.constData(), -1); - - if (type == PrivateKey) - key = PEM_read_bio_RSAPrivateKey(b, NULL, NULL, NULL); - else - key = PEM_read_bio_RSAPublicKey(b, NULL, NULL, NULL); - - BIO_free(b); - } else if (format == DER) { - const uchar *dp = reinterpret_cast(data.constData()); - - if (type == PrivateKey) - key = d2i_RSAPrivateKey(NULL, &dp, data.size()); - else - key = d2i_RSAPublicKey(NULL, &dp, data.size()); - } else { - Q_UNREACHABLE(); - } - - if (!key) { - qWarning() << "Failed to parse" << (type == PrivateKey ? "private" : "public") << "key from data"; - return false; - } - - d = new Data(key); - return true; -} -#endif - -bool CryptoKey::loadFromFile(const QString& path) -{ - QFile file(path); - if (!file.open(QIODevice::ReadOnly)) - { - qWarning() << "Failed to open Tor key file " << path << ": " << file.errorString(); - return false; - } - - QByteArray data = file.readAll(); - file.close(); - - if(data.contains("-----BEGIN RSA PRIVATE KEY-----")) - { - std::cerr << "Note: Reading/converting Tor v2 key format." << std::endl; - - // This to be compliant with old format. New format is oblivious to the type of key so we dont need a header - data = data.replace("-----BEGIN RSA PRIVATE KEY-----",nullptr); - data = data.replace("-----END RSA PRIVATE KEY-----",nullptr); - data = data.replace("\n",nullptr); - data = data.replace("\t",nullptr); - - data = "RSA1024:"+data; - } - - std::cerr << "Have read the following key: " << std::endl; - std::cerr << QString(data).toStdString() << std::endl; - - key_data = data; - - return true; -} - -bool CryptoKey::loadFromTorMessage(const QByteArray& b) -{ - // note: We should probably check the structure a bit more, for security. - - std::cerr << "Loading new key:" << std::endl; - - if(b.startsWith("RSA1024")) - std::cerr << " type: RSA-1024 (Tor v2)" << std::endl; - else if(b.startsWith("ED25519-V3")) - std::cerr << " type: ED25519-V3 (Tor v3)" << std::endl; - else if(b.indexOf(':')) - { - std::cerr << " unknown type, or bad syntax in key: \"" << b.left(b.indexOf(':')).toStdString() << "\". Not accepted." << std::endl; - return false; - } - - key_data = b; - return true; -} - -/* Cryptographic hash of a password as expected by Tor's HashedControlPassword */ -QByteArray torControlHashedPassword(const QByteArray &password) -{ - QByteArray salt = SecureRNG::random(8); - if (salt.isNull()) - return QByteArray(); - - int count = ((quint32)16 + (96 & 15)) << ((96 >> 4) + 6); - - SHA_CTX hash; - SHA1_Init(&hash); - - QByteArray tmp = salt + password; - while (count) - { - int c = qMin(count, tmp.size()); - SHA1_Update(&hash, reinterpret_cast(tmp.constData()), c); - count -= c; - } - - unsigned char md[20]; - SHA1_Final(md, &hash); - - /* 60 is the hex-encoded value of 96, which is a constant used by Tor's algorithm. */ - return QByteArray("16:") + salt.toHex().toUpper() + QByteArray("60") + - QByteArray::fromRawData(reinterpret_cast(md), 20).toHex().toUpper(); -} - - -#ifdef TO_REMOVE -bool CryptoKey::isPrivate() const -{ - if (!isLoaded()) { - return false; - } else { - const BIGNUM *p, *q; - RSA_get0_factors(d->key, &p, &q); - return (p != 0); - } -} - -int CryptoKey::bits() const -{ - return isLoaded() ? RSA_bits(d->key) : 0; -} - -QByteArray CryptoKey::publicKeyDigest() const -{ - if (!isLoaded()) - return QByteArray(); - - QByteArray buf = encodedPublicKey(DER); - - QByteArray re(20, 0); - bool ok = SHA1(reinterpret_cast(buf.constData()), buf.size(), - reinterpret_cast(re.data())) != NULL; - - if (!ok) - { - qWarning() << "Failed to hash public key data for digest"; - return QByteArray(); - } - - return re; -} - -QByteArray CryptoKey::encodedPublicKey(KeyFormat format) const -{ - if (!isLoaded()) - return QByteArray(); - - if (format == PEM) { - BIO *b = BIO_new(BIO_s_mem()); - - if (!PEM_write_bio_RSAPublicKey(b, d->key)) { - BUG() << "Failed to encode public key in PEM format"; - BIO_free(b); - return QByteArray(); - } - - BUF_MEM *buf; - BIO_get_mem_ptr(b, &buf); - - /* Close BIO, but don't free buf. */ - (void)BIO_set_close(b, BIO_NOCLOSE); - BIO_free(b); - - QByteArray re((const char *)buf->data, (int)buf->length); - BUF_MEM_free(buf); - return re; - } else if (format == DER) { - uchar *buf = NULL; - int len = i2d_RSAPublicKey(d->key, &buf); - if (len <= 0 || !buf) { - BUG() << "Failed to encode public key in DER format"; - return QByteArray(); - } - - QByteArray re((const char*)buf, len); - OPENSSL_free(buf); - return re; - } else { - Q_UNREACHABLE(); - } - - return QByteArray(); -} - -QByteArray CryptoKey::encodedPrivateKey(KeyFormat format) const -{ - if (!isLoaded() || !isPrivate()) - return QByteArray(); - - if (format == PEM) { - BIO *b = BIO_new(BIO_s_mem()); - - if (!PEM_write_bio_RSAPrivateKey(b, d->key, NULL, NULL, 0, NULL, NULL)) { - BUG() << "Failed to encode private key in PEM format"; - BIO_free(b); - return QByteArray(); - } - - BUF_MEM *buf; - BIO_get_mem_ptr(b, &buf); - - /* Close BIO, but don't free buf. */ - (void)BIO_set_close(b, BIO_NOCLOSE); - BIO_free(b); - - QByteArray re((const char *)buf->data, (int)buf->length); - BUF_MEM_free(buf); - return re; - } else if (format == DER) { - uchar *buf = NULL; - int len = i2d_RSAPrivateKey(d->key, &buf); - if (len <= 0 || !buf) { - BUG() << "Failed to encode private key in DER format"; - return QByteArray(); - } - - QByteArray re((const char*)buf, len); - OPENSSL_free(buf); - return re; - } else { - Q_UNREACHABLE(); - } - - return QByteArray(); -} - -QString CryptoKey::torServiceID() const -{ - if (!isLoaded()) - return QString(); - - QByteArray digest = publicKeyDigest(); - if (digest.isNull()) - return QString(); - - static const int hostnameDigestSize = 10; - static const int hostnameEncodedSize = 16; - - QByteArray re(hostnameEncodedSize+1, 0); - base32_encode(re.data(), re.size(), digest.constData(), hostnameDigestSize); - - // Chop extra null byte - re.chop(1); - - return QString::fromLatin1(re); -} - -QByteArray CryptoKey::signData(const QByteArray &data) const -{ - QByteArray digest(32, 0); - bool ok = SHA256(reinterpret_cast(data.constData()), data.size(), - reinterpret_cast(digest.data())) != NULL; - if (!ok) { - qWarning() << "Digest for RSA signature failed"; - return QByteArray(); - } - - return signSHA256(digest); -} - -QByteArray CryptoKey::signSHA256(const QByteArray &digest) const -{ - if (!isPrivate()) - return QByteArray(); - - QByteArray re(RSA_size(d->key), 0); - unsigned sigsize = 0; - int r = RSA_sign(NID_sha256, reinterpret_cast(digest.constData()), digest.size(), - reinterpret_cast(re.data()), &sigsize, d->key); - - if (r != 1) { - qWarning() << "RSA encryption failed when generating signature"; - return QByteArray(); - } - - re.truncate(sigsize); - return re; -} - -bool CryptoKey::verifyData(const QByteArray &data, QByteArray signature) const -{ - QByteArray digest(32, 0); - bool ok = SHA256(reinterpret_cast(data.constData()), data.size(), - reinterpret_cast(digest.data())) != NULL; - - if (!ok) { - qWarning() << "Digest for RSA verify failed"; - return false; - } - - return verifySHA256(digest, signature); -} - -bool CryptoKey::verifySHA256(const QByteArray &digest, QByteArray signature) const -{ - if (!isLoaded()) - return false; - - int r = RSA_verify(NID_sha256, reinterpret_cast(digest.constData()), digest.size(), - reinterpret_cast(signature.data()), signature.size(), d->key); - if (r != 1) - return false; - return true; -} - -/* Copyright (c) 2001-2004, Roger Dingledine - * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson - * Copyright (c) 2007-2010, The Tor Project, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define BASE32_CHARS "abcdefghijklmnopqrstuvwxyz234567" - -/* Implements base32 encoding as in rfc3548. Requires that srclen*8 is a multiple of 5. */ -void base32_encode(char *dest, unsigned destlen, const char *src, unsigned srclen) -{ - unsigned i, bit, v, u; - unsigned nbits = srclen * 8; - - /* We need an even multiple of 5 bits, and enough space */ - if ((nbits%5) != 0 || destlen > (nbits/5)+1) { - Q_ASSERT(false); - memset(dest, 0, destlen); - return; - } - - for (i = 0, bit = 0; bit < nbits; ++i, bit += 5) - { - /* set v to the 16-bit value starting at src[bits/8], 0-padded. */ - v = ((quint8) src[bit / 8]) << 8; - if (bit + 5 < nbits) - v += (quint8) src[(bit/8)+1]; - - /* set u to the 5-bit value at the bit'th bit of src. */ - u = (v >> (11 - (bit % 8))) & 0x1F; - dest[i] = BASE32_CHARS[u]; - } - - dest[i] = '\0'; -} - -/* Implements base32 decoding as in rfc3548. Requires that srclen*5 is a multiple of 8. */ -bool base32_decode(char *dest, unsigned destlen, const char *src, unsigned srclen) -{ - unsigned int i, j, bit; - unsigned nbits = srclen * 5; - - /* We need an even multiple of 8 bits, and enough space */ - if ((nbits%8) != 0 || (nbits/8)+1 > destlen) { - Q_ASSERT(false); - return false; - } - - char *tmp = new char[srclen]; - - /* Convert base32 encoded chars to the 5-bit values that they represent. */ - for (j = 0; j < srclen; ++j) - { - if (src[j] > 0x60 && src[j] < 0x7B) - tmp[j] = src[j] - 0x61; - else if (src[j] > 0x31 && src[j] < 0x38) - tmp[j] = src[j] - 0x18; - else if (src[j] > 0x40 && src[j] < 0x5B) - tmp[j] = src[j] - 0x41; - else - { - delete[] tmp; - return false; - } - } - - /* Assemble result byte-wise by applying five possible cases. */ - for (i = 0, bit = 0; bit < nbits; ++i, bit += 8) - { - switch (bit % 40) - { - case 0: - dest[i] = (((quint8)tmp[(bit/5)]) << 3) + (((quint8)tmp[(bit/5)+1]) >> 2); - break; - case 8: - dest[i] = (((quint8)tmp[(bit/5)]) << 6) + (((quint8)tmp[(bit/5)+1]) << 1) - + (((quint8)tmp[(bit/5)+2]) >> 4); - break; - case 16: - dest[i] = (((quint8)tmp[(bit/5)]) << 4) + (((quint8)tmp[(bit/5)+1]) >> 1); - break; - case 24: - dest[i] = (((quint8)tmp[(bit/5)]) << 7) + (((quint8)tmp[(bit/5)+1]) << 2) - + (((quint8)tmp[(bit/5)+2]) >> 3); - break; - case 32: - dest[i] = (((quint8)tmp[(bit/5)]) << 5) + ((quint8)tmp[(bit/5)+1]); - break; - } - } - - delete[] tmp; - return true; -} - -#endif diff --git a/retroshare-gui/src/TorControl/CryptoKey.h b/retroshare-gui/src/TorControl/CryptoKey.h deleted file mode 100644 index c99703444..000000000 --- a/retroshare-gui/src/TorControl/CryptoKey.h +++ /dev/null @@ -1,106 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CRYPTOKEY_H -#define CRYPTOKEY_H - -#include -#include -#include - -class CryptoKey -{ -public: - enum KeyType { - PrivateKey, - PublicKey - }; - - enum KeyFormat { - PEM, - DER - }; - - CryptoKey(); - ~CryptoKey(); - -#ifdef TO_REMOVE - bool loadFromData(const QByteArray &data, KeyType type, KeyFormat format = PEM); - bool loadFromFile(const QString &path, KeyType type, KeyFormat format = PEM); -#endif - bool loadFromFile(const QString &path); - void clear(); - - const QByteArray bytes() const { return key_data; } - bool loadFromTorMessage(const QByteArray& b); - bool isLoaded() const { return !key_data.isNull(); } -#ifdef TO_REMOVE - bool isPrivate() const; - - QByteArray publicKeyDigest() const; - QByteArray encodedPublicKey(KeyFormat format) const; - QByteArray encodedPrivateKey(KeyFormat format) const; - QString torServiceID() const; - int bits() const; - - // Calculate and sign SHA-256 digest of data using this key and PKCS #1 v2.0 padding - QByteArray signData(const QByteArray &data) const; - // Verify a signature as per signData - bool verifyData(const QByteArray &data, QByteArray signature) const; - - // Sign the input SHA-256 digest using this key and PKCS #1 v2.0 padding - QByteArray signSHA256(const QByteArray &digest) const; - // Verify a signature as per signSHA256 - bool verifySHA256(const QByteArray &digest, QByteArray signature) const; -#endif - -private: -#ifdef TO_REMOVE - struct Data : public QSharedData - { - typedef struct rsa_st RSA; - RSA *key; - - Data(RSA *k = 0) : key(k) { } - ~Data(); - }; -#endif - - QByteArray key_data; -#ifdef TO_REMOVE - QExplicitlySharedDataPointer d; -#endif -}; - -QByteArray torControlHashedPassword(const QByteArray &password); - -#endif // CRYPTOKEY_H diff --git a/retroshare-gui/src/TorControl/GetConfCommand.cpp b/retroshare-gui/src/TorControl/GetConfCommand.cpp deleted file mode 100644 index 933def562..000000000 --- a/retroshare-gui/src/TorControl/GetConfCommand.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "GetConfCommand.h" -#include "StrUtil.h" -#include - -using namespace Tor; - -GetConfCommand::GetConfCommand(Type t) - : type(t) -{ -} - -QByteArray GetConfCommand::build(const QByteArray &key) -{ - return build(QList() << key); -} - -QByteArray GetConfCommand::build(const QList &keys) -{ - QByteArray out; - if (type == GetConf) { - out = "GETCONF"; - } else if (type == GetInfo) { - out = "GETINFO"; - } else { - Q_ASSERT(false); - return out; - } - - foreach (const QByteArray &key, keys) { - out.append(' '); - out.append(key); - } - - out.append("\r\n"); - return out; -} - -void GetConfCommand::onReply(int statusCode, const QByteArray &data) -{ - TorControlCommand::onReply(statusCode, data); - if (statusCode != 250) - return; - - int kep = data.indexOf('='); - QString key = QString::fromLatin1(data.mid(0, kep)); - QVariant value; - if (kep >= 0) - value = QString::fromLatin1(unquotedString(data.mid(kep + 1))); - - m_lastKey = key; - QVariantMap::iterator it = m_results.find(key); - if (it != m_results.end()) { - // Make a list of values - QVariantList results = it->toList(); - if (results.isEmpty()) - results.append(*it); - results.append(value); - *it = QVariant(results); - } else { - m_results.insert(key, value); - } -} - -void GetConfCommand::onDataLine(const QByteArray &data) -{ - if (m_lastKey.isEmpty()) { - qWarning() << "torctrl: Unexpected data line in GetConf command"; - return; - } - - QVariantMap::iterator it = m_results.find(m_lastKey); - if (it != m_results.end()) { - QVariantList results = it->toList(); - if (results.isEmpty() && !it->toByteArray().isEmpty()) - results.append(*it); - results.append(data); - *it = QVariant(results); - } else { - m_results.insert(m_lastKey, QVariantList() << data); - } -} - -void GetConfCommand::onDataFinished() -{ - m_lastKey.clear(); -} - -QVariant GetConfCommand::get(const QByteArray &key) const -{ - return m_results.value(QString::fromLatin1(key)); -} - diff --git a/retroshare-gui/src/TorControl/GetConfCommand.h b/retroshare-gui/src/TorControl/GetConfCommand.h deleted file mode 100644 index 0de97d1b7..000000000 --- a/retroshare-gui/src/TorControl/GetConfCommand.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GETCONFCOMMAND_H -#define GETCONFCOMMAND_H - -#include "TorControlCommand.h" -#include -#include - -namespace Tor -{ - -class GetConfCommand : public TorControlCommand -{ - Q_OBJECT - Q_DISABLE_COPY(GetConfCommand) - - Q_PROPERTY(QVariantMap results READ results CONSTANT) - -public: - enum Type { - GetConf, - GetInfo - }; - const Type type; - - GetConfCommand(Type type); - - QByteArray build(const QByteArray &key); - QByteArray build(const QList &keys); - - const QVariantMap &results() const { return m_results; } - QVariant get(const QByteArray &key) const; - -protected: - virtual void onReply(int statusCode, const QByteArray &data); - virtual void onDataLine(const QByteArray &data); - virtual void onDataFinished(); - -private: - QVariantMap m_results; - QString m_lastKey; -}; - -} - -#endif // GETCONFCOMMAND_H diff --git a/retroshare-gui/src/TorControl/HiddenService.cpp b/retroshare-gui/src/TorControl/HiddenService.cpp deleted file mode 100644 index b2b58626a..000000000 --- a/retroshare-gui/src/TorControl/HiddenService.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "HiddenService.h" -#include "TorControl.h" -#include "TorSocket.h" -#include "CryptoKey.h" -#include "Useful.h" -#include -#include -#include -#include - -using namespace Tor; - -HiddenService::HiddenService(QObject *parent) - : QObject(parent), m_status(NotCreated) -{ -} - -HiddenService::HiddenService(const QString &path, QObject *parent) - : QObject(parent), m_dataPath(path), m_status(NotCreated) -{ - /* Set the initial status and, if possible, load the hostname */ - if (QDir(m_dataPath).exists(QLatin1String("private_key"))) { - loadPrivateKey(); - if (!m_hostname.isEmpty()) - m_status = Offline; - } -} - -HiddenService::HiddenService(const CryptoKey &privateKey, const QString &path, QObject *parent) - : QObject(parent), m_dataPath(path), m_status(NotCreated) -{ - setPrivateKey(privateKey); - m_status = Offline; -} - -void HiddenService::setStatus(Status newStatus) -{ - if (m_status == newStatus) - return; - - Status old = m_status; - m_status = newStatus; - - emit statusChanged(m_status, old); - - if (m_status == Online) - emit serviceOnline(); -} - -void HiddenService::addTarget(const Target &target) -{ - m_targets.append(target); -} - -void HiddenService::addTarget(quint16 servicePort, QHostAddress targetAddress, quint16 targetPort) -{ - Target t = { targetAddress, servicePort, targetPort }; - m_targets.append(t); -} - -void HiddenService::setServiceId(const QByteArray& sid) -{ - m_service_id = sid; - m_hostname = sid + ".onion"; - - emit hostnameChanged(); -} -void HiddenService::setPrivateKey(const CryptoKey &key) -{ - if (m_privateKey.isLoaded()) { - BUG() << "Cannot change the private key on an existing HiddenService"; - return; - } - -#ifdef TO_REMOVE - if (!key.isPrivate()) { - BUG() << "Cannot create a hidden service with a public key"; - return; - } -#endif - - m_privateKey = key; - - emit privateKeyChanged(); -} - -void HiddenService::loadPrivateKey() -{ - if (m_privateKey.isLoaded() || m_dataPath.isEmpty()) - return; - - bool ok = m_privateKey.loadFromFile(m_dataPath + QLatin1String("/private_key")); - - if (!ok) { - qWarning() << "Failed to load hidden service key"; - return; - } - - emit privateKeyChanged(); -} - -void HiddenService::servicePublished() -{ - loadPrivateKey(); - - if (m_hostname.isEmpty()) { - std::cerr << "Failed to read hidden service hostname" << std::endl; - return; - } - - std::cerr << "Hidden service published successfully" << std::endl; - setStatus(Online); -} - diff --git a/retroshare-gui/src/TorControl/HiddenService.h b/retroshare-gui/src/TorControl/HiddenService.h deleted file mode 100644 index 20fa1d851..000000000 --- a/retroshare-gui/src/TorControl/HiddenService.h +++ /dev/null @@ -1,108 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HIDDENSERVICE_H -#define HIDDENSERVICE_H - -#include -#include -#include -#include "CryptoKey.h" - -namespace Tor -{ - -class TorSocket; - -class HiddenService : public QObject -{ - Q_OBJECT - Q_DISABLE_COPY(HiddenService) - - friend class TorControlPrivate; - -public: - struct Target - { - QHostAddress targetAddress; - quint16 servicePort, targetPort; - }; - - enum Status - { - NotCreated = -1, /* Service has not been created yet */ - Offline = 0, /* Data exists, but service is not published */ - Online /* Published */ - }; - - HiddenService(QObject *parent = 0); - HiddenService(const QString &dataPath, QObject *parent = 0); - HiddenService(const CryptoKey &privateKey, const QString &dataPath = QString(), QObject *parent = 0); - - Status status() const { return m_status; } - - const QString& hostname() const { return m_hostname; } - const QString serviceId() const { return QString(m_service_id); } - const QString& dataPath() const { return m_dataPath; } - - CryptoKey privateKey() { return m_privateKey; } - void setPrivateKey(const CryptoKey &privateKey); - void setServiceId(const QByteArray& sid); - - const QList &targets() const { return m_targets; } - void addTarget(const Target &target); - void addTarget(quint16 servicePort, QHostAddress targetAddress, quint16 targetPort); - -signals: - void statusChanged(int newStatus, int oldStatus); - void serviceOnline(); - void privateKeyChanged(); - void hostnameChanged(); - -private slots: - void servicePublished(); - -private: - QString m_dataPath; - QList m_targets; - QString m_hostname; - Status m_status; - CryptoKey m_privateKey; - QByteArray m_service_id; - - void loadPrivateKey(); - void setStatus(Status newStatus); -}; - -} - -#endif // HIDDENSERVICE_H diff --git a/retroshare-gui/src/TorControl/PendingOperation.cpp b/retroshare-gui/src/TorControl/PendingOperation.cpp deleted file mode 100644 index 4a11f3e75..000000000 --- a/retroshare-gui/src/TorControl/PendingOperation.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "PendingOperation.h" - -PendingOperation::PendingOperation(QObject *parent) - : QObject(parent), m_finished(false) -{ -} - -bool PendingOperation::isFinished() const -{ - return m_finished; -} - -bool PendingOperation::isSuccess() const -{ - return m_finished && m_errorMessage.isNull(); -} - -bool PendingOperation::isError() const -{ - return m_finished && !m_errorMessage.isNull(); -} - -QString PendingOperation::errorMessage() const -{ - return m_errorMessage; -} - -void PendingOperation::finishWithError(const QString &message) -{ - if (message.isEmpty()) - m_errorMessage = QStringLiteral("Unknown Error"); - m_errorMessage = message; - - if (!m_finished) { - m_finished = true; - emit finished(); - emit error(m_errorMessage); - } -} - -void PendingOperation::finishWithSuccess() -{ - Q_ASSERT(m_errorMessage.isNull()); - - if (!m_finished) { - m_finished = true; - emit finished(); - if (isSuccess()) - emit success(); - } -} - diff --git a/retroshare-gui/src/TorControl/PendingOperation.h b/retroshare-gui/src/TorControl/PendingOperation.h deleted file mode 100644 index 8f776a8d7..000000000 --- a/retroshare-gui/src/TorControl/PendingOperation.h +++ /dev/null @@ -1,87 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PENDINGOPERATION_H -#define PENDINGOPERATION_H - -#include - -/* Represents an asynchronous operation for reporting status - * - * This class is used for asynchronous operations that report a - * status and errors when finished, particularly for exposing them - * to QML. - * - * Subclass PendingOperation to implement your operation's logic. - * You also need to handle the object's lifetime, for example by - * calling deleteLater() when finished() is emitted. - * - * PendingOperation will emit finished() and one of success() or - * error() when completed. - */ -class PendingOperation : public QObject -{ - Q_OBJECT - - Q_PROPERTY(bool isFinished READ isFinished NOTIFY finished FINAL) - Q_PROPERTY(bool isSuccess READ isSuccess NOTIFY success FINAL) - Q_PROPERTY(bool isError READ isError NOTIFY error FINAL) - Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY finished FINAL) - -public: - PendingOperation(QObject *parent = 0); - - bool isFinished() const; - bool isSuccess() const; - bool isError() const; - QString errorMessage() const; - -signals: - // Always emitted once when finished, regardless of status - void finished(); - - // One of error() or success() is emitted once - void error(const QString &errorMessage); - void success(); - -protected slots: - void finishWithError(const QString &errorMessage); - void finishWithSuccess(); - -private: - bool m_finished; - QString m_errorMessage; -}; - -Q_DECLARE_METATYPE(PendingOperation*) - -#endif diff --git a/retroshare-gui/src/TorControl/ProtocolInfoCommand.cpp b/retroshare-gui/src/TorControl/ProtocolInfoCommand.cpp deleted file mode 100644 index a365a5c4d..000000000 --- a/retroshare-gui/src/TorControl/ProtocolInfoCommand.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ProtocolInfoCommand.h" -#include "TorControl.h" -#include "StrUtil.h" -#include - -using namespace Tor; - -ProtocolInfoCommand::ProtocolInfoCommand(TorControl *m) - : manager(m) -{ -} - -QByteArray ProtocolInfoCommand::build() -{ - return QByteArray("PROTOCOLINFO 1\r\n"); -} - -void ProtocolInfoCommand::onReply(int statusCode, const QByteArray &data) -{ - TorControlCommand::onReply(statusCode, data); - if (statusCode != 250) - return; - - if (data.startsWith("AUTH ")) - { - QList tokens = splitQuotedStrings(data.mid(5), ' '); - - foreach (QByteArray token, tokens) - { - if (token.startsWith("METHODS=")) - { - QList textMethods = unquotedString(token.mid(8)).split(','); - for (QList::Iterator it = textMethods.begin(); it != textMethods.end(); ++it) - { - if (*it == "NULL") - m_authMethods |= AuthNull; - else if (*it == "HASHEDPASSWORD") - m_authMethods |= AuthHashedPassword; - else if (*it == "COOKIE") - m_authMethods |= AuthCookie; - } - } - else if (token.startsWith("COOKIEFILE=")) - { - m_cookieFile = QString::fromLatin1(unquotedString(token.mid(11))); - } - } - } - else if (data.startsWith("VERSION Tor=")) - { - m_torVersion = QString::fromLatin1(unquotedString(data.mid(12, data.indexOf(' ', 12)))); - } -} diff --git a/retroshare-gui/src/TorControl/ProtocolInfoCommand.h b/retroshare-gui/src/TorControl/ProtocolInfoCommand.h deleted file mode 100644 index 7789cfefd..000000000 --- a/retroshare-gui/src/TorControl/ProtocolInfoCommand.h +++ /dev/null @@ -1,78 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PROTOCOLINFOCOMMAND_H -#define PROTOCOLINFOCOMMAND_H - -#include "TorControlCommand.h" -#include - -namespace Tor -{ - -class TorControl; - -class ProtocolInfoCommand : public TorControlCommand -{ - Q_OBJECT - Q_DISABLE_COPY(ProtocolInfoCommand) - -public: - enum AuthMethod - { - AuthUnknown = 0, - AuthNull = 0x1, - AuthHashedPassword = 0x2, - AuthCookie = 0x4 - }; - Q_DECLARE_FLAGS(AuthMethods, AuthMethod) - - ProtocolInfoCommand(TorControl *manager); - QByteArray build(); - - AuthMethods authMethods() const { return m_authMethods; } - QString torVersion() const { return m_torVersion; } - QString cookieFile() const { return m_cookieFile; } - -protected: - virtual void onReply(int statusCode, const QByteArray &data); - -private: - TorControl *manager; - AuthMethods m_authMethods; - QString m_torVersion; - QString m_cookieFile; -}; - -} - -#endif // PROTOCOLINFOCOMMAND_H diff --git a/retroshare-gui/src/TorControl/SecureRNG.cpp b/retroshare-gui/src/TorControl/SecureRNG.cpp deleted file mode 100644 index 60cf3c048..000000000 --- a/retroshare-gui/src/TorControl/SecureRNG.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "SecureRNG.h" -#include -#include -#include -#include - -#ifdef Q_OS_WIN -#include -#include -#endif - -#if QT_VERSION >= 0x040700 -#include -#endif - -bool SecureRNG::seed() -{ -#if QT_VERSION >= 0x040700 - QElapsedTimer timer; - timer.start(); -#endif - -#ifdef Q_OS_WIN - /* RAND_poll is very unreliable on windows; with older versions of OpenSSL, - * it can take up to several minutes to run and has been known to crash. - * Even newer versions seem to take around 400ms, which is far too long for - * interactive startup. Random data from the windows CSP is used as a seed - * instead, as it should be very high quality random and fast. */ - HCRYPTPROV provider = 0; - if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) - { - qWarning() << "Failed to acquire CSP context for RNG seed:" << hex << GetLastError(); - return false; - } - - /* Same amount of entropy OpenSSL uses, apparently. */ - char buf[32]; - - if (!CryptGenRandom(provider, sizeof(buf), reinterpret_cast(buf))) - { - qWarning() << "Failed to get entropy from CSP for RNG seed: " << hex << GetLastError(); - CryptReleaseContext(provider, 0); - return false; - } - - CryptReleaseContext(provider, 0); - - RAND_seed(buf, sizeof(buf)); - memset(buf, 0, sizeof(buf)); -#else - if (!RAND_poll()) - { - qWarning() << "OpenSSL RNG seed failed:" << ERR_get_error(); - return false; - } -#endif - -#if QT_VERSION >= 0x040700 - qDebug() << "RNG seed took" << timer.elapsed() << "ms"; -#endif - - return true; -} - -void SecureRNG::random(char *buf, int size) -{ - int r = RAND_bytes(reinterpret_cast(buf), size); - if (r <= 0) - qFatal("RNG failed: %lu", ERR_get_error()); -} - -QByteArray SecureRNG::random(int size) -{ - QByteArray re(size, 0); - random(re.data(), size); - return re; -} - -QByteArray SecureRNG::randomPrintable(int length) -{ - QByteArray re(length, 0); - for (int i = 0; i < re.size(); i++) - re[i] = randomInt(95) + 32; - return re; -} - -unsigned SecureRNG::randomInt(unsigned max) -{ - unsigned cutoff = UINT_MAX - (UINT_MAX % max); - unsigned value = 0; - - for (;;) - { - random(reinterpret_cast(&value), sizeof(value)); - if (value < cutoff) - return value % max; - } -} - -#ifndef UINT64_MAX -#define UINT64_MAX ((quint64)-1) -#endif - -quint64 SecureRNG::randomInt64(quint64 max) -{ - quint64 cutoff = UINT64_MAX - (UINT64_MAX % max); - quint64 value = 0; - - for (;;) - { - random(reinterpret_cast(value), sizeof(value)); - if (value < cutoff) - return value % max; - } -} diff --git a/retroshare-gui/src/TorControl/SecureRNG.h b/retroshare-gui/src/TorControl/SecureRNG.h deleted file mode 100644 index f3b2a4b64..000000000 --- a/retroshare-gui/src/TorControl/SecureRNG.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SECURERNG_H -#define SECURERNG_H - -#include - -class SecureRNG -{ -public: - static bool seed(); - - static void random(char *buf, int size); - static QByteArray random(int size); - - static QByteArray randomPrintable(int length); - static unsigned randomInt(unsigned max); - static quint64 randomInt64(quint64 max); -}; - -#endif // SECURERNG_H diff --git a/retroshare-gui/src/TorControl/SetConfCommand.cpp b/retroshare-gui/src/TorControl/SetConfCommand.cpp deleted file mode 100644 index f13a9fdef..000000000 --- a/retroshare-gui/src/TorControl/SetConfCommand.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "SetConfCommand.h" -#include "StrUtil.h" - -using namespace Tor; - -SetConfCommand::SetConfCommand() - : m_resetMode(false) -{ -} - -void SetConfCommand::setResetMode(bool enabled) -{ - m_resetMode = enabled; -} - -bool SetConfCommand::isSuccessful() const -{ - return statusCode() == 250; -} - -QByteArray SetConfCommand::build(const QByteArray &key, const QByteArray &value) -{ - return build(QList >() << qMakePair(key, value)); -} - -QByteArray SetConfCommand::build(const QVariantMap &data) -{ - QList > out; - - for (QVariantMap::ConstIterator it = data.begin(); it != data.end(); it++) { - QByteArray key = it.key().toLatin1(); - - if (static_cast(it.value().type()) == QMetaType::QVariantList) { - QVariantList values = it.value().value(); - foreach (const QVariant &value, values) - out.append(qMakePair(key, value.toString().toLatin1())); - } else { - out.append(qMakePair(key, it.value().toString().toLatin1())); - } - } - - return build(out); -} - -QByteArray SetConfCommand::build(const QList > &data) -{ - QByteArray out(m_resetMode ? "RESETCONF" : "SETCONF"); - - for (int i = 0; i < data.size(); i++) { - out += " " + data[i].first; - if (!data[i].second.isEmpty()) - out += "=" + quotedString(data[i].second); - } - - out.append("\r\n"); - return out; -} - -void SetConfCommand::onReply(int statusCode, const QByteArray &data) -{ - TorControlCommand::onReply(statusCode, data); - if (statusCode != 250) - m_errorMessage = QString::fromLatin1(data); -} - -void SetConfCommand::onFinished(int statusCode) -{ - TorControlCommand::onFinished(statusCode); - if (isSuccessful()) - emit setConfSucceeded(); - else - emit setConfFailed(statusCode); -} - diff --git a/retroshare-gui/src/TorControl/SetConfCommand.h b/retroshare-gui/src/TorControl/SetConfCommand.h deleted file mode 100644 index 5bdcb9329..000000000 --- a/retroshare-gui/src/TorControl/SetConfCommand.h +++ /dev/null @@ -1,78 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SETCONFCOMMAND_H -#define SETCONFCOMMAND_H - -#include "TorControlCommand.h" -#include -#include -#include - -namespace Tor -{ - -class SetConfCommand : public TorControlCommand -{ - Q_OBJECT - Q_DISABLE_COPY(SetConfCommand) - - Q_PROPERTY(QString errorMessage READ errorMessage CONSTANT) - Q_PROPERTY(bool successful READ isSuccessful CONSTANT) - -public: - SetConfCommand(); - - void setResetMode(bool resetMode); - - QByteArray build(const QByteArray &key, const QByteArray &value); - QByteArray build(const QVariantMap &data); - QByteArray build(const QList > &data); - - QString errorMessage() const { return m_errorMessage; } - bool isSuccessful() const; - -signals: - void setConfSucceeded(); - void setConfFailed(int code); - -protected: - QString m_errorMessage; - bool m_resetMode; - - virtual void onReply(int statusCode, const QByteArray &data); - virtual void onFinished(int statusCode); -}; - -} - -#endif // SETCONFCOMMAND_H diff --git a/retroshare-gui/src/TorControl/Settings.cpp b/retroshare-gui/src/TorControl/Settings.cpp deleted file mode 100644 index b20d330b7..000000000 --- a/retroshare-gui/src/TorControl/Settings.cpp +++ /dev/null @@ -1,553 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "Settings.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class SettingsFilePrivate : public QObject -{ - Q_OBJECT - -public: - SettingsFile *q; - QString filePath; - QString errorMessage; - QTimer syncTimer; - QJsonObject jsonRoot; - SettingsObject *rootObject; - - SettingsFilePrivate(SettingsFile *qp); - virtual ~SettingsFilePrivate(); - - void reset(); - void setError(const QString &message); - bool checkDirPermissions(const QString &path); - bool readFile(); - bool writeFile(); - - static QStringList splitPath(const QString &input, bool &ok); - QJsonValue read(const QJsonObject &base, const QStringList &path); - bool write(const QStringList &path, const QJsonValue &value); - -signals: - void modified(const QStringList &path, const QJsonValue &value); - -private slots: - void sync(); -}; - -SettingsFile::SettingsFile(QObject *parent) - : QObject(parent), d(new SettingsFilePrivate(this)) -{ - d->rootObject = new SettingsObject(this, QString()); -} - -SettingsFile::~SettingsFile() -{ -} - -SettingsFilePrivate::SettingsFilePrivate(SettingsFile *qp) - : QObject(qp) - , q(qp) - , rootObject(0) -{ - syncTimer.setInterval(0); - syncTimer.setSingleShot(true); - connect(&syncTimer, &QTimer::timeout, this, &SettingsFilePrivate::sync); -} - -SettingsFilePrivate::~SettingsFilePrivate() -{ - if (syncTimer.isActive()) - sync(); - delete rootObject; -} - -void SettingsFilePrivate::reset() -{ - filePath.clear(); - errorMessage.clear(); - - jsonRoot = QJsonObject(); - emit modified(QStringList(), jsonRoot); -} - -QString SettingsFile::filePath() const -{ - return d->filePath; -} - -bool SettingsFile::setFilePath(const QString &filePath) -{ - if (d->filePath == filePath) - return hasError(); - - d->reset(); - d->filePath = filePath; - - QFileInfo fileInfo(filePath); - QDir dir(fileInfo.path()); - if (!dir.exists() && !dir.mkpath(QStringLiteral("."))) { - d->setError(QStringLiteral("Cannot create directory: %1").arg(dir.path())); - return false; - } - d->checkDirPermissions(fileInfo.path()); - - if (!d->readFile()) - return false; - - return true; -} - -QString SettingsFile::errorMessage() const -{ - return d->errorMessage; -} - -bool SettingsFile::hasError() const -{ - return !d->errorMessage.isEmpty(); -} - -void SettingsFilePrivate::setError(const QString &message) -{ - errorMessage = message; - emit q->error(); -} - -bool SettingsFilePrivate::checkDirPermissions(const QString &path) -{ - static QFile::Permissions desired = QFileDevice::ReadUser | QFileDevice::WriteUser | QFileDevice::ExeUser; - static QFile::Permissions ignored = QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner; - - QFile file(path); - if ((file.permissions() & ~ignored) != desired) { - qDebug() << "Correcting permissions on configuration directory"; - if (!file.setPermissions(desired)) { - qWarning() << "Correcting permissions on configuration directory failed"; - return false; - } - } - - return true; -} - -SettingsObject *SettingsFile::root() -{ - return d->rootObject; -} - -const SettingsObject *SettingsFile::root() const -{ - return d->rootObject; -} - -void SettingsFilePrivate::sync() -{ - if (filePath.isEmpty()) - return; - - syncTimer.stop(); - writeFile(); -} - -bool SettingsFilePrivate::readFile() -{ - QFile file(filePath); - if (!file.open(QIODevice::ReadWrite)) { - setError(file.errorString()); - return false; - } - - QByteArray data = file.readAll(); - if (data.isEmpty() && (file.error() != QFileDevice::NoError || file.size() > 0)) { - setError(file.errorString()); - return false; - } - - if (data.isEmpty()) { - jsonRoot = QJsonObject(); - return true; - } - - QJsonParseError parseError; - QJsonDocument document = QJsonDocument::fromJson(data, &parseError); - if (document.isNull()) { - setError(parseError.errorString()); - return false; - } - - if (!document.isObject()) { - setError(QStringLiteral("Invalid configuration file (expected object)")); - return false; - } - - jsonRoot = document.object(); - - emit modified(QStringList(), jsonRoot); - return true; -} - -bool SettingsFilePrivate::writeFile() -{ - QSaveFile file(filePath); - if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - setError(file.errorString()); - return false; - } - - QJsonDocument document(jsonRoot); - QByteArray data = document.toJson(); - if (data.isEmpty() && !document.isEmpty()) { - setError(QStringLiteral("Encoding failure")); - return false; - } - - if (file.write(data) < data.size() || !file.commit()) { - setError(file.errorString()); - return false; - } - - return true; -} - -QStringList SettingsFilePrivate::splitPath(const QString &input, bool &ok) -{ - QStringList components = input.split(QLatin1Char('.')); - - // Allow a leading '.' to simplify concatenation - if (!components.isEmpty() && components.first().isEmpty()) - components.takeFirst(); - - // No other empty components, including a trailing . - foreach (const QString &word, components) { - if (word.isEmpty()) { - ok = false; - return QStringList(); - } - } - - ok = true; - return components; -} - -QJsonValue SettingsFilePrivate::read(const QJsonObject &base, const QStringList &path) -{ - QJsonValue current = base; - - foreach (const QString &key, path) { - QJsonObject object = current.toObject(); - if (object.isEmpty() || (current = object.value(key)).isUndefined()) - return QJsonValue::Undefined; - } - - return current; -} - -// Compare two QJsonValue to find keys that have changed, -// recursing into objects and building paths as necessary. -typedef QList > ModifiedList; -static void findModifiedRecursive(ModifiedList &modified, const QStringList &path, const QJsonValue &oldValue, const QJsonValue &newValue) -{ - if (oldValue.isObject() || newValue.isObject()) { - // If either is a non-object type, this returns an empty object - QJsonObject oldObject = oldValue.toObject(); - QJsonObject newObject = newValue.toObject(); - - // Iterate keys of the original object and compare to new - for (QJsonObject::iterator it = oldObject.begin(); it != oldObject.end(); it++) { - QJsonValue newSubValue = newObject.value(it.key()); - if (*it == newSubValue) - continue; - - if ((*it).isObject() || newSubValue.isObject()) - findModifiedRecursive(modified, QStringList() << path << it.key(), *it, newSubValue); - else - modified.append(qMakePair(QStringList() << path << it.key(), newSubValue)); - } - - // Iterate keys of the new object that may not be in original - for (QJsonObject::iterator it = newObject.begin(); it != newObject.end(); it++) { - if (oldObject.contains(it.key())) - continue; - - if ((*it).isObject()) - findModifiedRecursive(modified, QStringList() << path << it.key(), QJsonValue::Undefined, it.value()); - else - modified.append(qMakePair(QStringList() << path << it.key(), it.value())); - } - } else - modified.append(qMakePair(path, newValue)); -} - -bool SettingsFilePrivate::write(const QStringList &path, const QJsonValue &value) -{ - typedef QVarLengthArray > ObjectStack; - ObjectStack stack; - QJsonValue current = jsonRoot; - QJsonValue originalValue; - QString currentKey; - - foreach (const QString &key, path) { - const QJsonObject &parent = current.toObject(); - stack.append(qMakePair(currentKey, parent)); - current = parent.value(key); - currentKey = key; - } - - // Stack now contains parent objects starting with the root, and current - // is the old value. Write back changes in reverse. - if (current == value) - return false; - originalValue = current; - current = value; - - ObjectStack::const_iterator it = stack.end(), begin = stack.begin(); - while (it != begin) { - --it; - QJsonObject update = it->second; - update.insert(currentKey, current); - current = update; - currentKey = it->first; - } - - // current is now the updated jsonRoot - jsonRoot = current.toObject(); - syncTimer.start(); - - ModifiedList modified; - findModifiedRecursive(modified, path, originalValue, value); - - for (ModifiedList::iterator it = modified.begin(); it != modified.end(); it++) - emit this->modified(it->first, it->second); - - return true; -} - -class SettingsObjectPrivate : public QObject -{ - Q_OBJECT - -public: - explicit SettingsObjectPrivate(SettingsObject *q); - - SettingsObject *q; - SettingsFile *file; - QStringList path; - QJsonObject object; - bool invalid; - - void setFile(SettingsFile *file); - -public slots: - void modified(const QStringList &absolutePath, const QJsonValue &value); -}; - -SettingsObject::SettingsObject(QObject *parent) - : QObject(parent) - , d(new SettingsObjectPrivate(this)) -{ - d->setFile(defaultFile()); - if (d->file) - setPath(QString()); -} - -SettingsObject::SettingsObject(const QString &path, QObject *parent) - : QObject(parent) - , d(new SettingsObjectPrivate(this)) -{ - d->setFile(defaultFile()); - setPath(path); -} - -SettingsObject::SettingsObject(SettingsFile *file, const QString &path, QObject *parent) - : QObject(parent) - , d(new SettingsObjectPrivate(this)) -{ - d->setFile(file); - setPath(path); -} - -SettingsObject::SettingsObject(SettingsObject *base, const QString &path, QObject *parent) - : QObject(parent) - , d(new SettingsObjectPrivate(this)) -{ - d->setFile(base->d->file); - setPath(base->path() + QLatin1Char('.') + path); -} - -SettingsObjectPrivate::SettingsObjectPrivate(SettingsObject *qp) - : QObject(qp) - , q(qp) - , file(0) - , invalid(true) -{ -} - -void SettingsObjectPrivate::setFile(SettingsFile *value) -{ - if (file == value) - return; - - if (file) - disconnect(file, 0, this, 0); - file = value; - if (file) - connect(file->d, &SettingsFilePrivate::modified, this, &SettingsObjectPrivate::modified); -} - -// Emit SettingsObject::modified with a relative path if path is matched -void SettingsObjectPrivate::modified(const QStringList &key, const QJsonValue &value) -{ - if (key.size() < path.size()) - return; - - for (int i = 0; i < path.size(); i++) { - if (path[i] != key[i]) - return; - } - - object = file->d->read(file->d->jsonRoot, path).toObject(); - emit q->modified(QStringList(key.mid(path.size())).join(QLatin1Char('.')), value); - emit q->dataChanged(); -} - -static QPointer defaultObjectFile; - -SettingsFile *SettingsObject::defaultFile() -{ - return defaultObjectFile; -} - -void SettingsObject::setDefaultFile(SettingsFile *file) -{ - defaultObjectFile = file; -} - -QString SettingsObject::path() const -{ - return d->path.join(QLatin1Char('.')); -} - -void SettingsObject::setPath(const QString &input) -{ - bool ok = false; - QStringList newPath = SettingsFilePrivate::splitPath(input, ok); - if (!ok) { - d->invalid = true; - d->path.clear(); - d->object = QJsonObject(); - - emit pathChanged(); - emit dataChanged(); - return; - } - - if (!d->invalid && d->path == newPath) - return; - - d->path = newPath; - if (d->file) { - d->invalid = false; - d->object = d->file->d->read(d->file->d->jsonRoot, d->path).toObject(); - emit dataChanged(); - } - - emit pathChanged(); -} - -QJsonObject SettingsObject::data() const -{ - return d->object; -} - -void SettingsObject::setData(const QJsonObject &input) -{ - if (d->invalid || d->object == input) - return; - - d->object = input; - d->file->d->write(d->path, d->object); -} - -QJsonValue SettingsObject::read(const QString &key, const QJsonValue &defaultValue) const -{ - bool ok = false; - QStringList splitKey = SettingsFilePrivate::splitPath(key, ok); - if (d->invalid || !ok || splitKey.isEmpty()) { - qDebug() << "Invalid settings read of path" << key; - return defaultValue; - } - - QJsonValue ret = d->file->d->read(d->object, splitKey); - if (ret.isUndefined()) - ret = defaultValue; - return ret; -} - -void SettingsObject::write(const QString &key, const QJsonValue &value) -{ - bool ok = false; - QStringList splitKey = SettingsFilePrivate::splitPath(key, ok); - if (d->invalid || !ok || splitKey.isEmpty()) { - qDebug() << "Invalid settings write of path" << key; - return; - } - - splitKey = d->path + splitKey; - d->file->d->write(splitKey, value); -} - -void SettingsObject::unset(const QString &key) -{ - write(key, QJsonValue()); -} - -void SettingsObject::undefine() -{ - if (d->invalid) - return; - - d->object = QJsonObject(); - d->file->d->write(d->path, QJsonValue::Undefined); -} - -#include "Settings.moc" diff --git a/retroshare-gui/src/TorControl/Settings.h b/retroshare-gui/src/TorControl/Settings.h deleted file mode 100644 index 79ad032d1..000000000 --- a/retroshare-gui/src/TorControl/Settings.h +++ /dev/null @@ -1,257 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SETTINGS_H -#define SETTINGS_H - -#include -#include -#include -#include -#include -#include - -class SettingsObject; -class SettingsFilePrivate; -class SettingsObjectPrivate; - -/* SettingsFile represents a JSON-encoded configuration file. - * - * SettingsFile is an API for reading, writing, and change notification - * on JSON-encoded settings files. - * - * Data is accessed via SettingsObject, either using the root property - * or by creating a SettingsObject, optionally using a base path. - */ -class SettingsFile : public QObject -{ - Q_OBJECT - Q_DISABLE_COPY(SettingsFile) - - Q_PROPERTY(SettingsObject *root READ root CONSTANT) - Q_PROPERTY(QString filePath READ filePath WRITE setFilePath NOTIFY filePathChanged) - Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY error) - Q_PROPERTY(bool hasError READ hasError NOTIFY error) - -public: - explicit SettingsFile(QObject *parent = 0); - virtual ~SettingsFile(); - - QString filePath() const; - bool setFilePath(const QString &filePath); - - QString errorMessage() const; - bool hasError() const; - - SettingsObject *root(); - const SettingsObject *root() const; - -signals: - void filePathChanged(); - void error(); - -private: - SettingsFilePrivate *d; - - friend class SettingsObject; - friend class SettingsObjectPrivate; -}; - -/* SettingsObject reads and writes data within a SettingsFile - * - * A SettingsObject is associated with a SettingsFile and represents an object - * tree within that file. It refers to the JSON object tree using a path - * notation with keys separated by '.'. For example: - * - * { - * "one": { - * "two": { - * "three": "value" - * } - * } - * } - * - * With this data, a SettingsObject with an empty path can read with the path - * "one.two.three", and a SettingsObject with a path of "one.two" can simply - * read or write on "three". - * - * Multiple SettingsObjects may be created for the same path, and will be kept - * synchronized with changes. The modified signal is emitted for all changes - * affecting keys within a path, including writes of object trees and from other - * instances. - */ -class SettingsObject : public QObject -{ - Q_OBJECT - Q_DISABLE_COPY(SettingsObject) - - Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) - Q_PROPERTY(QJsonObject data READ data WRITE setData NOTIFY dataChanged) - -public: - explicit SettingsObject(QObject *parent = 0); - explicit SettingsObject(const QString &path, QObject *parent = 0); - explicit SettingsObject(SettingsFile *file, const QString &path, QObject *parent = 0); - explicit SettingsObject(SettingsObject *base, const QString &path, QObject *parent = 0); - - /* Specify a SettingsFile to use by default on SettingsObject instances. - * - * After calling setDefaultFile, a SettingsObject created without any file, e.g.: - * - * SettingsObject settings; - * SettingsObject animals(QStringLiteral("animals")); - * - * Will use the specified SettingsFile instance by default. This is a convenience - * over passing around instances of SettingsFile in application use cases, and is - * particularly useful for QML. - */ - static SettingsFile *defaultFile(); - static void setDefaultFile(SettingsFile *file); - - QString path() const; - void setPath(const QString &path); - - QJsonObject data() const; - void setData(const QJsonObject &data); - - Q_INVOKABLE QJsonValue read(const QString &key, const QJsonValue &defaultValue = QJsonValue::Undefined) const; - template T read(const QString &key) const; - Q_INVOKABLE void write(const QString &key, const QJsonValue &value); - template void write(const QString &key, const T &value); - Q_INVOKABLE void unset(const QString &key); - - // const char* key overloads - QJsonValue read(const char *key, const QJsonValue &defaultValue = QJsonValue::Undefined) const - { - return read(QString::fromLatin1(key), defaultValue); - } - template T read(const char *key) const - { - return read(QString::fromLatin1(key)); - } - void write(const char *key, const QJsonValue &value) - { - write(QString::fromLatin1(key), value); - } - template void write(const char *key, const T &value) - { - write(QString::fromLatin1(key), value); - } - void unset(const char *key) - { - unset(QString::fromLatin1(key)); - } - - Q_INVOKABLE void undefine(); - -signals: - void pathChanged(); - void dataChanged(); - - void modified(const QString &path, const QJsonValue &value); - -private: - SettingsObjectPrivate *d; -}; - -template inline void SettingsObject::write(const QString &key, const T &value) -{ - write(key, QJsonValue(value)); -} - -template<> inline QString SettingsObject::read(const QString &key) const -{ - return read(key).toString(); -} - -template<> inline QJsonArray SettingsObject::read(const QString &key) const -{ - return read(key).toArray(); -} - -template<> inline QJsonObject SettingsObject::read(const QString &key) const -{ - return read(key).toObject(); -} - -template<> inline double SettingsObject::read(const QString &key) const -{ - return read(key).toDouble(); -} - -template<> inline int SettingsObject::read(const QString &key) const -{ - return read(key).toInt(); -} - -template<> inline bool SettingsObject::read(const QString &key) const -{ - return read(key).toBool(); -} - -template<> inline QDateTime SettingsObject::read(const QString &key) const -{ - QString value = read(key).toString(); - if (value.isEmpty()) - return QDateTime(); - return QDateTime::fromString(value, Qt::ISODate).toLocalTime(); -} - -template<> inline void SettingsObject::write(const QString &key, const QDateTime &value) -{ - write(key, QJsonValue(value.toUTC().toString(Qt::ISODate))); -} - -// Explicitly store value encoded as base64. Decodes and casts implicitly to QByteArray for reads. -class Base64Encode -{ -public: - explicit Base64Encode(const QByteArray &value) : d(value) { } - operator QByteArray() { return d; } - QByteArray encoded() const { return d.toBase64(); } - -private: - QByteArray d; -}; - -template<> inline Base64Encode SettingsObject::read(const QString &key) const -{ - return Base64Encode(QByteArray::fromBase64(read(key).toString().toLatin1())); -} - -template<> inline void SettingsObject::write(const QString &key, const Base64Encode &value) -{ - write(key, QJsonValue(QString::fromLatin1(value.encoded()))); -} - -#endif - diff --git a/retroshare-gui/src/TorControl/StrUtil.cpp b/retroshare-gui/src/TorControl/StrUtil.cpp deleted file mode 100644 index 81de151b0..000000000 --- a/retroshare-gui/src/TorControl/StrUtil.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "StrUtil.h" - -QByteArray quotedString(const QByteArray &string) -{ - QByteArray out; - out.reserve(string.size() * 2); - - out.append('"'); - - for (int i = 0; i < string.size(); ++i) - { - switch (string[i]) - { - case '"': - out.append("\\\""); - break; - case '\\': - out.append("\\\\"); - break; - default: - out.append(string[i]); - break; - } - } - - out.append('"'); - return out; -} - -QByteArray unquotedString(const QByteArray &string) -{ - if (string.size() < 2 || string[0] != '"') - return string; - - QByteArray out; - out.reserve(string.size() - 2); - - for (int i = 1; i < string.size(); ++i) - { - switch (string[i]) - { - case '\\': - if (++i < string.size()) - out.append(string[i]); - break; - case '"': - return out; - default: - out.append(string[i]); - } - } - - return out; -} - -QList splitQuotedStrings(const QByteArray &input, char separator) -{ - QList out; - bool inquote = false; - int start = 0; - - for (int i = 0; i < input.size(); ++i) - { - switch (input[i]) - { - case '"': - inquote = !inquote; - break; - case '\\': - if (inquote) - ++i; - break; - } - - if (!inquote && input[i] == separator) - { - out.append(input.mid(start, i - start)); - start = i+1; - } - } - - if (start < input.size()) - out.append(input.mid(start)); - - return out; -} diff --git a/retroshare-gui/src/TorControl/StrUtil.h b/retroshare-gui/src/TorControl/StrUtil.h deleted file mode 100644 index c86d2c6ec..000000000 --- a/retroshare-gui/src/TorControl/StrUtil.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef STRINGUTIL_H -#define STRINGUTIL_H - -#include -#include - -QByteArray quotedString(const QByteArray &string); - -/* Return the unquoted contents of a string, either until an end quote or an unescaped separator character. */ -QByteArray unquotedString(const QByteArray &string); - -QList splitQuotedStrings(const QByteArray &input, char separator); - -#endif // STRINGUTIL_H diff --git a/retroshare-gui/src/TorControl/TorControl.cpp b/retroshare-gui/src/TorControl/TorControl.cpp deleted file mode 100644 index 29979e2b3..000000000 --- a/retroshare-gui/src/TorControl/TorControl.cpp +++ /dev/null @@ -1,788 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "TorControl.h" -#include "TorControlSocket.h" -#include "HiddenService.h" -#include "ProtocolInfoCommand.h" -#include "AuthenticateCommand.h" -#include "SetConfCommand.h" -#include "GetConfCommand.h" -#include "AddOnionCommand.h" -#include "StrUtil.h" -#include "Settings.h" -#include "PendingOperation.h" -#include -#include -#include -//#include -#include -#include -#include -#include - -Tor::TorControl *torControl = 0; - -class nullstream: public std::ostream {}; - -static std::ostream& torctrldebug() -{ - static nullstream null ; - - if(true) - return std::cerr << time(NULL) << ":TOR CONTROL: " ; - else - return null ; -} - -#define torCtrlDebug torctrldebug - - -using namespace Tor; - -namespace Tor { - -class TorControlPrivate : public QObject -{ - Q_OBJECT - -public: - TorControl *q; - - TorControlSocket *socket; - QHostAddress torAddress; - QString errorMessage; - QString torVersion; - QByteArray authPassword; - QHostAddress socksAddress; - QList services; - quint16 controlPort, socksPort; - TorControl::Status status; - TorControl::TorStatus torStatus; - QVariantMap bootstrapStatus; - bool hasOwnership; - - TorControlPrivate(TorControl *parent); - - void setStatus(TorControl::Status status); - void setTorStatus(TorControl::TorStatus status); - - void getTorInfo(); - void publishServices(); - -public slots: - void socketConnected(); - void socketDisconnected(); - void socketError(); - - void authenticateReply(); - void protocolInfoReply(); - void getTorInfoReply(); - void setError(const QString &message); - - void statusEvent(int code, const QByteArray &data); - void updateBootstrap(const QList &data); -}; - -} - -TorControl::TorControl(QObject *parent) - : QObject(parent), d(new TorControlPrivate(this)) -{ -} - -TorControlPrivate::TorControlPrivate(TorControl *parent) - : QObject(parent), q(parent), controlPort(0), socksPort(0), - status(TorControl::NotConnected), torStatus(TorControl::TorUnknown), - hasOwnership(false) -{ - socket = new TorControlSocket(this); - QObject::connect(socket, SIGNAL(connected()), this, SLOT(socketConnected())); - QObject::connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); - QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError())); - QObject::connect(socket, SIGNAL(error(QString)), this, SLOT(setError(QString))); -} - -QNetworkProxy TorControl::connectionProxy() -{ - return QNetworkProxy(QNetworkProxy::Socks5Proxy, d->socksAddress.toString(), d->socksPort); -} - -void TorControlPrivate::setStatus(TorControl::Status n) -{ - if (n == status) - return; - - TorControl::Status old = status; - status = n; - - if (old == TorControl::Error) - errorMessage.clear(); - - emit q->statusChanged(status, old); - - if (status == TorControl::Connected && old < TorControl::Connected) - emit q->connected(); - else if (status < TorControl::Connected && old >= TorControl::Connected) - emit q->disconnected(); -} - -void TorControlPrivate::setTorStatus(TorControl::TorStatus n) -{ - if (n == torStatus) - return; - - TorControl::TorStatus old = torStatus; - torStatus = n; - emit q->torStatusChanged(torStatus, old); - emit q->connectivityChanged(); - - if (torStatus == TorControl::TorReady && socksAddress.isNull()) { - // Request info again to read the SOCKS port - getTorInfo(); - } -} - -void TorControlPrivate::setError(const QString &message) -{ - errorMessage = message; - setStatus(TorControl::Error); - - qWarning() << "torctrl: Error:" << errorMessage; - - socket->abort(); - - QTimer::singleShot(15000, q, SLOT(reconnect())); -} - -TorControl::Status TorControl::status() const -{ - return d->status; -} - -TorControl::TorStatus TorControl::torStatus() const -{ - return d->torStatus; -} - -QString TorControl::torVersion() const -{ - return d->torVersion; -} - -QString TorControl::errorMessage() const -{ - return d->errorMessage; -} - -bool TorControl::hasConnectivity() const -{ - return torStatus() == TorReady && !d->socksAddress.isNull(); -} - -QHostAddress TorControl::socksAddress() const -{ - return d->socksAddress; -} - -quint16 TorControl::socksPort() const -{ - return d->socksPort; -} - -QList TorControl::hiddenServices() const -{ - return d->services; -} - -QVariantMap TorControl::bootstrapStatus() const -{ - return d->bootstrapStatus; -} - -void TorControl::setAuthPassword(const QByteArray &password) -{ - d->authPassword = password; -} - -void TorControl::connect(const QHostAddress &address, quint16 port) -{ - if (status() > Connecting) - { - torCtrlDebug() << "Ignoring TorControl::connect due to existing connection" << std::endl; - return; - } - - d->torAddress = address; - d->controlPort = port; - d->setTorStatus(TorUnknown); - - bool b = d->socket->blockSignals(true); - d->socket->abort(); - d->socket->blockSignals(b); - - d->setStatus(Connecting); - d->socket->connectToHost(address, port); -} - -void TorControl::reconnect() -{ - Q_ASSERT(!d->torAddress.isNull() && d->controlPort); - if (d->torAddress.isNull() || !d->controlPort || status() >= Connecting) - return; - - d->setStatus(Connecting); - d->socket->connectToHost(d->torAddress, d->controlPort); -} - -void TorControlPrivate::authenticateReply() -{ - AuthenticateCommand *command = qobject_cast(sender()); - Q_ASSERT(command); - Q_ASSERT(status == TorControl::Authenticating); - if (!command) - return; - - if (!command->isSuccessful()) { - setError(command->errorMessage()); - return; - } - - torCtrlDebug() << "torctrl: Authentication successful" << std::endl; - setStatus(TorControl::Connected); - - setTorStatus(TorControl::TorUnknown); - - TorControlCommand *clientEvents = new TorControlCommand; - connect(clientEvents, &TorControlCommand::replyLine, this, &TorControlPrivate::statusEvent); - socket->registerEvent("STATUS_CLIENT", clientEvents); - - getTorInfo(); - publishServices(); - - // XXX Fix old configurations that would store unwanted options in torrc. - // This can be removed some suitable amount of time after 1.0.4. - if (hasOwnership) - q->saveConfiguration(); -} - - -void TorControlPrivate::socketConnected() -{ - Q_ASSERT(status == TorControl::Connecting); - - torCtrlDebug() << "torctrl: Connected socket; querying information" << std::endl; - setStatus(TorControl::Authenticating); - - ProtocolInfoCommand *command = new ProtocolInfoCommand(q); - connect(command, &TorControlCommand::finished, this, &TorControlPrivate::protocolInfoReply); - socket->sendCommand(command, command->build()); -} - -void TorControlPrivate::socketDisconnected() -{ - /* Clear some internal state */ - torVersion.clear(); - socksAddress.clear(); - socksPort = 0; - setTorStatus(TorControl::TorUnknown); - - /* This emits the disconnected() signal as well */ - setStatus(TorControl::NotConnected); -} - -void TorControlPrivate::socketError() -{ - setError(QStringLiteral("Connection failed: %1").arg(socket->errorString())); -} - -void TorControlPrivate::protocolInfoReply() -{ - ProtocolInfoCommand *info = qobject_cast(sender()); - if (!info) - return; - - torVersion = info->torVersion(); - - if (status == TorControl::Authenticating) - { - AuthenticateCommand *auth = new AuthenticateCommand; - connect(auth, &TorControlCommand::finished, this, &TorControlPrivate::authenticateReply); - - QByteArray data; - ProtocolInfoCommand::AuthMethods methods = info->authMethods(); - - if (methods.testFlag(ProtocolInfoCommand::AuthNull)) - { - torCtrlDebug() << "torctrl: Using null authentication" << std::endl; - data = auth->build(); - } - else if (methods.testFlag(ProtocolInfoCommand::AuthCookie) && !info->cookieFile().isEmpty()) - { - QString cookieFile = info->cookieFile(); - QString cookieError; - torCtrlDebug() << "torctrl: Using cookie authentication with file" << cookieFile.toStdString() << std::endl; - - QFile file(cookieFile); - if (file.open(QIODevice::ReadOnly)) - { - QByteArray cookie = file.readAll(); - file.close(); - - /* Simple test to avoid a vulnerability where any process listening on what we think is - * the control port could trick us into sending the contents of an arbitrary file */ - if (cookie.size() == 32) - data = auth->build(cookie); - else - cookieError = QStringLiteral("Unexpected file size"); - } - else - cookieError = file.errorString(); - - if (!cookieError.isNull() || data.isNull()) - { - /* If we know a password and password authentication is allowed, try using that instead. - * This is a strange corner case that will likely never happen in a normal configuration, - * but it has happened. */ - if (methods.testFlag(ProtocolInfoCommand::AuthHashedPassword) && !authPassword.isEmpty()) - { - torCtrlDebug() << "torctrl: Unable to read authentication cookie file:" << cookieError.toStdString() << std::endl; - goto usePasswordAuth; - } - - setError(QStringLiteral("Unable to read authentication cookie file: %1").arg(cookieError)); - delete auth; - return; - } - } - else if (methods.testFlag(ProtocolInfoCommand::AuthHashedPassword) && !authPassword.isEmpty()) - { - usePasswordAuth: - torCtrlDebug() << "torctrl: Using hashed password authentication" << std::endl; - data = auth->build(authPassword); - } - else - { - if (methods.testFlag(ProtocolInfoCommand::AuthHashedPassword)) - setError(QStringLiteral("Tor requires a control password to connect, but no password is configured.")); - else - setError(QStringLiteral("Tor is not configured to accept any supported authentication methods.")); - delete auth; - return; - } - - socket->sendCommand(auth, data); - } -} - -void TorControlPrivate::getTorInfo() -{ - Q_ASSERT(q->isConnected()); - - GetConfCommand *command = new GetConfCommand(GetConfCommand::GetInfo); - connect(command, &TorControlCommand::finished, this, &TorControlPrivate::getTorInfoReply); - - QList keys; - keys << QByteArray("status/circuit-established") << QByteArray("status/bootstrap-phase"); - - /* If these are set in the config, they override the automatic behavior. */ - SettingsObject settings(QStringLiteral("tor")); - QHostAddress forceAddress(settings.read("socksAddress").toString()); - quint16 port = (quint16)settings.read("socksPort").toInt(); - - if (!forceAddress.isNull() && port) { - torCtrlDebug() << "torctrl: Using manually specified SOCKS connection settings"; - socksAddress = forceAddress; - socksPort = port; - emit q->connectivityChanged(); - } else - keys << QByteArray("net/listeners/socks"); - - socket->sendCommand(command, command->build(keys)); -} - -void TorControlPrivate::getTorInfoReply() -{ - GetConfCommand *command = qobject_cast(sender()); - if (!command || !q->isConnected()) - return; - - QList listenAddresses = splitQuotedStrings(command->get(QByteArray("net/listeners/socks")).toString().toLatin1(), ' '); - for (QList::Iterator it = listenAddresses.begin(); it != listenAddresses.end(); ++it) { - QByteArray value = unquotedString(*it); - int sepp = value.indexOf(':'); - QHostAddress address(QString::fromLatin1(value.mid(0, sepp))); - quint16 port = (quint16)value.mid(sepp+1).toUInt(); - - /* Use the first address that matches the one used for this control connection. If none do, - * just use the first address and rely on the user to reconfigure if necessary (not a problem; - * their setup is already very customized) */ - if (socksAddress.isNull() || address == socket->peerAddress()) { - socksAddress = address; - socksPort = port; - if (address == socket->peerAddress()) - break; - } - } - - /* It is not immediately an error to have no SOCKS address; when DisableNetwork is set there won't be a - * listener yet. To handle that situation, we'll try to read the socks address again when TorReady state - * is reached. */ - if (!socksAddress.isNull()) { - torCtrlDebug() << "torctrl: SOCKS address is " << socksAddress.toString().toStdString() << ":" << socksPort << std::endl; - emit q->connectivityChanged(); - } - - if (command->get(QByteArray("status/circuit-established")).toInt() == 1) { - torCtrlDebug() << "torctrl: Tor indicates that circuits have been established; state is TorReady" << std::endl; - setTorStatus(TorControl::TorReady); - } else { - setTorStatus(TorControl::TorOffline); - } - - QByteArray bootstrap = command->get(QByteArray("status/bootstrap-phase")).toString().toLatin1(); - if (!bootstrap.isEmpty()) - updateBootstrap(splitQuotedStrings(bootstrap, ' ')); -} - -void TorControl::addHiddenService(HiddenService *service) -{ - if (d->services.contains(service)) - return; - - d->services.append(service); -} - -void TorControlPrivate::publishServices() -{ - torCtrlDebug() << "Publish Services... " ; - - Q_ASSERT(q->isConnected()); - if (services.isEmpty()) - { - std::cerr << "No service regstered!" << std::endl; - return; - } - std::cerr << std::endl; - - SettingsObject settings(QStringLiteral("tor")); - if (settings.read("neverPublishServices").toBool()) - { - torCtrlDebug() << "torctrl: Skipping service publication because neverPublishService is enabled" << std::endl; - - /* Call servicePublished under the assumption that they're published externally. */ - for (QList::Iterator it = services.begin(); it != services.end(); ++it) - (*it)->servicePublished(); - - return; - } - - if (q->torVersionAsNewAs(QStringLiteral("0.2.7"))) { - foreach (HiddenService *service, services) { - if (service->hostname().isEmpty()) - torCtrlDebug() << "torctrl: Creating a new hidden service" << std::endl; - else - torCtrlDebug() << "torctrl: Publishing hidden service: " << service->hostname().toStdString() << std::endl; - AddOnionCommand *onionCommand = new AddOnionCommand(service); - QObject::connect(onionCommand, &AddOnionCommand::succeeded, service, &HiddenService::servicePublished); - socket->sendCommand(onionCommand, onionCommand->build()); - } - } else { - torCtrlDebug() << "torctrl: Using legacy SETCONF hidden service configuration for tor" << torVersion.toStdString() << std::endl; - SetConfCommand *command = new SetConfCommand; - QList > torConfig; - - foreach (HiddenService *service, services) - { - if (service->dataPath().isEmpty()) - continue; - - if (service->privateKey().isLoaded() && !QFile::exists(service->dataPath() + QStringLiteral("/private_key"))) { - // This case can happen if tor is downgraded after the profile is created - qWarning() << "Cannot publish ephemeral hidden services with this version of tor; skipping"; - continue; - } - - torCtrlDebug() << "torctrl: Configuring hidden service at" << service->dataPath().toStdString() << std::endl; - - QDir dir(service->dataPath()); - torConfig.append(qMakePair(QByteArray("HiddenServiceDir"), dir.absolutePath().toLocal8Bit())); - - const QList &targets = service->targets(); - for (QList::ConstIterator tit = targets.begin(); tit != targets.end(); ++tit) - { - QString target = QString::fromLatin1("%1 %2:%3").arg(tit->servicePort) - .arg(tit->targetAddress.toString()) - .arg(tit->targetPort); - torConfig.append(qMakePair(QByteArray("HiddenServicePort"), target.toLatin1())); - } - - QObject::connect(command, &SetConfCommand::setConfSucceeded, service, &HiddenService::servicePublished); - } - - if (!torConfig.isEmpty()) - socket->sendCommand(command, command->build(torConfig)); - } -} - -void TorControl::shutdown() -{ - if (!hasOwnership()) { - qWarning() << "torctrl: Ignoring shutdown command for a tor instance I don't own"; - return; - } - - d->socket->sendCommand("SIGNAL SHUTDOWN\r\n"); -} - -void TorControl::shutdownSync() -{ - if (!hasOwnership()) { - qWarning() << "torctrl: Ignoring shutdown command for a tor instance I don't own"; - return; - } - - shutdown(); - while (d->socket->bytesToWrite()) - { - if (!d->socket->waitForBytesWritten(5000)) - return; - } -} - -void TorControlPrivate::statusEvent(int code, const QByteArray &data) -{ - Q_UNUSED(code); - - QList tokens = splitQuotedStrings(data.trimmed(), ' '); - if (tokens.size() < 3) - return; - - torCtrlDebug() << "torctrl: status event:" << QString(data.trimmed()).toStdString() << std::endl; - - if (tokens[2] == "CIRCUIT_ESTABLISHED") { - setTorStatus(TorControl::TorReady); - } else if (tokens[2] == "CIRCUIT_NOT_ESTABLISHED") { - setTorStatus(TorControl::TorOffline); - } else if (tokens[2] == "BOOTSTRAP") { - tokens.takeFirst(); - updateBootstrap(tokens); - } -} - -void TorControlPrivate::updateBootstrap(const QList &data) -{ - bootstrapStatus.clear(); - // WARN or NOTICE - bootstrapStatus[QStringLiteral("severity")] = data.value(0); - for (int i = 1; i < data.size(); i++) { - int equals = data[i].indexOf('='); - QString key = QString::fromLatin1(data[i].mid(0, equals)); - QString value; - if (equals >= 0) - value = QString::fromLatin1(unquotedString(data[i].mid(equals + 1))); - bootstrapStatus[key.toLower()] = value; - } - - //torCtrlDebug() << bootstrapStatus << std::endl; - - emit q->bootstrapStatusChanged(); -} - -QObject *TorControl::getConfiguration(const QString &options) -{ - GetConfCommand *command = new GetConfCommand(GetConfCommand::GetConf); - d->socket->sendCommand(command, command->build(options.toLatin1())); - - //QQmlEngine::setObjectOwnership(command, QQmlEngine::CppOwnership); - return command; -} - -QObject *TorControl::setConfiguration(const QVariantMap &options) -{ - SetConfCommand *command = new SetConfCommand; - command->setResetMode(true); - d->socket->sendCommand(command, command->build(options)); - - //QQmlEngine::setObjectOwnership(command, QQmlEngine::CppOwnership); - return command; -} - -namespace Tor { - -class SaveConfigOperation : public PendingOperation -{ - Q_OBJECT - -public: - SaveConfigOperation(QObject *parent) - : PendingOperation(parent), command(0) - { - } - - void start(TorControlSocket *socket) - { - Q_ASSERT(!command); - command = new GetConfCommand(GetConfCommand::GetInfo); - QObject::connect(command, &TorControlCommand::finished, this, &SaveConfigOperation::configTextReply); - socket->sendCommand(command, command->build(QList() << "config-text" << "config-file")); - } - -private slots: - void configTextReply() - { - Q_ASSERT(command); - if (!command) - return; - - QString path = QFile::decodeName(command->get("config-file").toByteArray()); - if (path.isEmpty()) { - finishWithError(QStringLiteral("Cannot write torrc without knowing its path")); - return; - } - - // Out of paranoia, refuse to write any file not named 'torrc', or if the - // file doesn't exist - QFileInfo fileInfo(path); - if (fileInfo.fileName() != QStringLiteral("torrc") || !fileInfo.exists()) { - finishWithError(QStringLiteral("Refusing to write torrc to unacceptable path %1").arg(path)); - return; - } - - QSaveFile file(path); - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - finishWithError(QStringLiteral("Failed opening torrc file for writing: %1").arg(file.errorString())); - return; - } - - // Remove these keys when writing torrc; they are set at runtime and contain - // absolute paths or port numbers - static const char *bannedKeys[] = { - "ControlPortWriteToFile", - "DataDirectory", - "HiddenServiceDir", - "HiddenServicePort", - 0 - }; - - QVariantList configText = command->get("config-text").toList(); - foreach (const QVariant &value, configText) { - QByteArray line = value.toByteArray(); - - bool skip = false; - for (const char **key = bannedKeys; *key; key++) { - if (line.startsWith(*key)) { - skip = true; - break; - } - } - if (skip) - continue; - - file.write(line); - file.write("\n"); - } - - if (!file.commit()) { - finishWithError(QStringLiteral("Failed writing torrc: %1").arg(file.errorString())); - return; - } - - torCtrlDebug() << "torctrl: Wrote torrc file" << std::endl; - finishWithSuccess(); - } - -private: - GetConfCommand *command; -}; - -} - -PendingOperation *TorControl::saveConfiguration() -{ - if (!hasOwnership()) { - qWarning() << "torctrl: Ignoring save configuration command for a tor instance I don't own"; - return 0; - } - - SaveConfigOperation *operation = new SaveConfigOperation(this); - QObject::connect(operation, &PendingOperation::finished, operation, &QObject::deleteLater); - operation->start(d->socket); - - //QQmlEngine::setObjectOwnership(operation, QQmlEngine::CppOwnership); - return operation; -} - -bool TorControl::hasOwnership() const -{ - return d->hasOwnership; -} - -void TorControl::takeOwnership() -{ - d->hasOwnership = true; - d->socket->sendCommand("TAKEOWNERSHIP\r\n"); - - // Reset PID-based polling - QVariantMap options; - options[QStringLiteral("__OwningControllerProcess")] = QVariant(); - setConfiguration(options); -} - -bool TorControl::torVersionAsNewAs(const QString &match) const -{ - QRegularExpression r(QStringLiteral("[.-]")); - QStringList split = torVersion().split(r); - QStringList matchSplit = match.split(r); - - for (int i = 0; i < matchSplit.size(); i++) { - if (i >= split.size()) - return false; - bool ok1 = false, ok2 = false; - int currentVal = split[i].toInt(&ok1); - int matchVal = matchSplit[i].toInt(&ok2); - if (!ok1 || !ok2) - return false; - if (currentVal > matchVal) - return true; - if (currentVal < matchVal) - return false; - } - - // Versions are equal, up to the length of match - return true; -} - -#include "TorControl.moc" - diff --git a/retroshare-gui/src/TorControl/TorControl.h b/retroshare-gui/src/TorControl/TorControl.h deleted file mode 100644 index 5d208656e..000000000 --- a/retroshare-gui/src/TorControl/TorControl.h +++ /dev/null @@ -1,144 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TORCONTROL_H -#define TORCONTROL_H - -#include - -#include -#include -#include "PendingOperation.h" - -class QNetworkProxy; - -namespace Tor -{ - -class HiddenService; -class TorControlPrivate; - -class TorControl : public QObject -{ - Q_OBJECT - Q_ENUMS(Status TorStatus) - - // Status of the control connection - Q_PROPERTY(Status status READ status NOTIFY statusChanged) - // Status of Tor (and whether it believes it can connect) - Q_PROPERTY(TorStatus torStatus READ torStatus NOTIFY torStatusChanged) - // Whether it's possible to make a SOCKS connection and connect - Q_PROPERTY(bool hasConnectivity READ hasConnectivity NOTIFY connectivityChanged) - Q_PROPERTY(QString torVersion READ torVersion NOTIFY connected) - Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY statusChanged) - Q_PROPERTY(QVariantMap bootstrapStatus READ bootstrapStatus NOTIFY bootstrapStatusChanged) - Q_PROPERTY(bool hasOwnership READ hasOwnership NOTIFY hasOwnershipChanged) - -public: - enum Status - { - Error = -1, - NotConnected = 0x00, - Connecting = 0x01, - Authenticating = 0x02, - Connected = 0x03 - }; - - enum TorStatus - { - TorUnknown = 0x00, - TorOffline = 0x01, - TorReady = 0x02 - }; - - - explicit TorControl(QObject *parent = 0); - - /* Information */ - Status status() const; - TorStatus torStatus() const; - QString torVersion() const; - bool torVersionAsNewAs(const QString &version) const; - QString errorMessage() const; - - bool hasConnectivity() const; - QHostAddress socksAddress() const; - quint16 socksPort() const; - QNetworkProxy connectionProxy(); - - /* Authentication */ - void setAuthPassword(const QByteArray &password); - - /* Connection */ - bool isConnected() const { return status() == Connected; } - void connect(const QHostAddress &address, quint16 port); - - /* Ownership means that tor is managed by this socket, and we - * can shut it down, own its configuration, etc. */ - bool hasOwnership() const; - void takeOwnership(); - - /* Hidden Services */ - QList hiddenServices() const; - void addHiddenService(HiddenService *service); - - QVariantMap bootstrapStatus() const; - Q_INVOKABLE QObject *getConfiguration(const QString &options); - Q_INVOKABLE QObject *setConfiguration(const QVariantMap &options); - Q_INVOKABLE PendingOperation *saveConfiguration(); - -signals: - void statusChanged(int newStatus, int oldStatus); - void torStatusChanged(int newStatus, int oldStatus); - void connected(); - void disconnected(); - void connectivityChanged(); - void bootstrapStatusChanged(); - void hasOwnershipChanged(); - -public slots: - /* Instruct Tor to shutdown */ - void shutdown(); - /* Call shutdown(), and wait synchronously for the command to be written */ - void shutdownSync(); - - void reconnect(); - -private: - TorControlPrivate *d; -}; - -} - -extern Tor::TorControl *torControl; - -#endif // TORCONTROLMANAGER_H diff --git a/retroshare-gui/src/TorControl/TorControlCommand.cpp b/retroshare-gui/src/TorControl/TorControlCommand.cpp deleted file mode 100644 index 48d4aab8b..000000000 --- a/retroshare-gui/src/TorControl/TorControlCommand.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "TorControlCommand.h" -#include - -using namespace Tor; - -TorControlCommand::TorControlCommand() - : m_finalStatus(0) -{ -} - -void TorControlCommand::onReply(int statusCode, const QByteArray &data) -{ - emit replyLine(statusCode, data); -} - -void TorControlCommand::onFinished(int statusCode) -{ - m_finalStatus = statusCode; - emit finished(); -} - -void TorControlCommand::onDataLine(const QByteArray &data) -{ - Q_UNUSED(data); -} - -void TorControlCommand::onDataFinished() -{ - qWarning() << "torctrl: Unexpected data response for command"; -} - diff --git a/retroshare-gui/src/TorControl/TorControlCommand.h b/retroshare-gui/src/TorControl/TorControlCommand.h deleted file mode 100644 index 894381054..000000000 --- a/retroshare-gui/src/TorControl/TorControlCommand.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TORCONTROLCOMMAND_H -#define TORCONTROLCOMMAND_H - -#include -#include - -namespace Tor -{ - -class TorControlCommand : public QObject -{ - Q_OBJECT - Q_DISABLE_COPY(TorControlCommand) - - friend class TorControlSocket; - -public: - TorControlCommand(); - - int statusCode() const { return m_finalStatus; } - -signals: - void replyLine(int statusCode, const QByteArray &data); - void finished(); - -protected: - virtual void onReply(int statusCode, const QByteArray &data); - virtual void onFinished(int statusCode); - virtual void onDataLine(const QByteArray &data); - virtual void onDataFinished(); - -private: - int m_finalStatus; -}; - -} - -#endif // TORCONTROLCOMMAND_H diff --git a/retroshare-gui/src/TorControl/TorControlSocket.cpp b/retroshare-gui/src/TorControl/TorControlSocket.cpp deleted file mode 100644 index c6b1eb707..000000000 --- a/retroshare-gui/src/TorControl/TorControlSocket.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "TorControlSocket.h" -#include "TorControlCommand.h" -#include - -using namespace Tor; - -TorControlSocket::TorControlSocket(QObject *parent) - : QTcpSocket(parent), currentCommand(0), inDataReply(false) -{ - connect(this, SIGNAL(readyRead()), this, SLOT(process())); - connect(this, SIGNAL(disconnected()), this, SLOT(clear())); -} - -TorControlSocket::~TorControlSocket() -{ - clear(); -} - -void TorControlSocket::sendCommand(TorControlCommand *command, const QByteArray &data) -{ - Q_ASSERT(data.endsWith("\r\n")); - - commandQueue.append(command); - write(data); - - std::cerr << "[TOR CTRL] Sent: \"" << QString(data.trimmed()).toStdString() << "\"" << std::endl; -} - -void TorControlSocket::registerEvent(const QByteArray &event, TorControlCommand *command) -{ - eventCommands.insert(event, command); - - QByteArray data("SETEVENTS"); - foreach (const QByteArray &key, eventCommands.keys()) { - data += ' '; - data += key; - } - data += "\r\n"; - - sendCommand(data); -} - -void TorControlSocket::clear() -{ - qDeleteAll(commandQueue); - commandQueue.clear(); - qDeleteAll(eventCommands); - eventCommands.clear(); - inDataReply = false; - currentCommand = 0; -} - -void TorControlSocket::setError(const QString &message) -{ - m_errorMessage = message; - emit error(message); - abort(); -} - -void TorControlSocket::process() -{ - for (;;) { - if (!canReadLine()) - return; - - QByteArray line = readLine(5120); - if (!line.endsWith("\r\n")) { - setError(QStringLiteral("Invalid control message syntax")); - return; - } - line.chop(2); - - if (inDataReply) { - if (line == ".") { - inDataReply = false; - if (currentCommand) - currentCommand->onDataFinished(); - currentCommand = 0; - } else { - if (currentCommand) - currentCommand->onDataLine(line); - } - continue; - } - - if (line.size() < 4) { - setError(QStringLiteral("Invalid control message syntax")); - return; - } - - int statusCode = line.left(3).toInt(); - char type = line[3]; - bool isFinalReply = (type == ' '); - inDataReply = (type == '+'); - - // Trim down to just data - line = line.mid(4); - - if (!isFinalReply && !inDataReply && type != '-') { - setError(QStringLiteral("Invalid control message syntax")); - return; - } - - // 6xx replies are asynchronous responses - if (statusCode >= 600 && statusCode < 700) { - if (!currentCommand) { - int space = line.indexOf(' '); - if (space > 0) - currentCommand = eventCommands.value(line.mid(0, space)); - - if (!currentCommand) { - qWarning() << "torctrl: Ignoring unknown event"; - continue; - } - } - - currentCommand->onReply(statusCode, line); - if (isFinalReply) { - currentCommand->onFinished(statusCode); - currentCommand = 0; - } - continue; - } - - if (commandQueue.isEmpty()) { - qWarning() << "torctrl: Received unexpected data"; - continue; - } - - TorControlCommand *command = commandQueue.first(); - if (command) - command->onReply(statusCode, line); - - if (inDataReply) { - currentCommand = command; - } else if (isFinalReply) { - commandQueue.takeFirst(); - if (command) { - command->onFinished(statusCode); - command->deleteLater(); - } - } - } -} diff --git a/retroshare-gui/src/TorControl/TorControlSocket.h b/retroshare-gui/src/TorControl/TorControlSocket.h deleted file mode 100644 index 2db911503..000000000 --- a/retroshare-gui/src/TorControl/TorControlSocket.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TORCONTROLSOCKET_H -#define TORCONTROLSOCKET_H - -#include -#include - -namespace Tor -{ - -class TorControlCommand; - -class TorControlSocket : public QTcpSocket -{ -Q_OBJECT -public: - explicit TorControlSocket(QObject *parent = 0); - virtual ~TorControlSocket(); - - QString errorMessage() const { return m_errorMessage; } - - void registerEvent(const QByteArray &event, TorControlCommand *handler); - - void sendCommand(const QByteArray &data) { sendCommand(0, data); } - void sendCommand(TorControlCommand *command, const QByteArray &data); - -signals: - void error(const QString &message); - -private slots: - void process(); - void clear(); - -private: - QQueue commandQueue; - QHash eventCommands; - QString m_errorMessage; - TorControlCommand *currentCommand; - bool inDataReply; - - void setError(const QString &message); -}; - -} - -#endif // TORCONTROLSOCKET_H diff --git a/retroshare-gui/src/TorControl/TorControlWindow.cpp b/retroshare-gui/src/TorControl/TorControlWindow.cpp index 6da6b8d7a..ddab3f281 100644 --- a/retroshare-gui/src/TorControl/TorControlWindow.cpp +++ b/retroshare-gui/src/TorControl/TorControlWindow.cpp @@ -9,42 +9,59 @@ #include #include "util/rstime.h" +#include "retroshare/rstor.h" +#include "retroshare/rsevents.h" + #include "TorControlWindow.h" -#include "TorManager.h" -#include "TorControl.h" -#include "HiddenService.h" +#include "util/qtthreadsutils.h" -TorControlDialog::TorControlDialog(Tor::TorManager *tm,QWidget *parent) - : mTorManager(tm) +TorControlDialog::TorControlDialog(QWidget *) { - setupUi(this) ; + setupUi(this) ; - QObject::connect(tm->control(),SIGNAL(statusChanged(int,int)),this,SLOT(statusChanged())) ; - QObject::connect(tm->control(),SIGNAL(connected()),this,SLOT(statusChanged())); - QObject::connect(tm->control(),SIGNAL(disconnected()),this,SLOT(statusChanged())); - QObject::connect(tm->control(),SIGNAL(bootstrapStatusChanged()),this,SLOT(statusChanged())); - QObject::connect(tm->control(),SIGNAL(connectivityChanged()),this,SLOT(statusChanged())); - QObject::connect(tm ,SIGNAL(errorChanged()),this,SLOT(statusChanged())); + mEventHandlerId = 0; // very important! - //QTimer::singleShot(2000,this,SLOT(checkForHiddenService())) ; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) + { + RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); + }, mEventHandlerId, RsEventType::TOR_MANAGER ); - mIncomingServer = new QTcpServer(this) ; - mHiddenService = NULL ; - mHiddenServiceStatus = HIDDEN_SERVICE_STATUS_UNKNOWN; - //mBootstrapPhaseFinished = false ; + mIncomingServer = new QTcpServer(this) ; - connect(mIncomingServer, SIGNAL(QTcpServer::newConnection()), this, SLOT(onIncomingConnection())); + connect(mIncomingServer, SIGNAL(QTcpServer::newConnection()), this, SLOT(onIncomingConnection())); - QTimer *timer = new QTimer ; + QTimer *timer = new QTimer ; - QObject::connect(timer,SIGNAL(timeout()),this,SLOT(showLog())) ; - timer->start(500) ; + QObject::connect(timer,SIGNAL(timeout()),this,SLOT(showLog())) ; + timer->start(300) ; - // Hide some debug output for the released version + // Hide some debug output for the released version - setWindowFlags( Qt::Dialog | Qt::FramelessWindowHint ); + setWindowFlags( Qt::Dialog | Qt::FramelessWindowHint ); - adjustSize(); + adjustSize(); +} + +TorControlDialog::~TorControlDialog() +{ + rsEvents->unregisterEventsHandler(mEventHandlerId); +} + +void TorControlDialog::handleEvent_main_thread(std::shared_ptr event) +{ + if(event->mType != RsEventType::TOR_MANAGER) return; + + const RsTorManagerEvent *fe = dynamic_cast(event.get()); + if(!fe) + return; + + switch(fe->mTorManagerEventType) + { + case RsTorManagerEventCode::TOR_STATUS_CHANGED: + case RsTorManagerEventCode::TOR_CONNECTIVITY_CHANGED: statusChanged(fe->mTorStatus,fe->mTorConnectivityStatus); + break; + default: ; + } } void TorControlDialog::onIncomingConnection() @@ -52,67 +69,66 @@ void TorControlDialog::onIncomingConnection() std::cerr << "Incoming connection !!" << std::endl; } -void TorControlDialog::statusChanged() +void TorControlDialog::statusChanged(RsTorStatus torstatus, RsTorConnectivityStatus tor_control_status) { - int tor_control_status = mTorManager->control()->status(); - int torstatus = mTorManager->control()->torStatus(); - QString tor_control_status_str,torstatus_str ; - if(mTorManager->hasError()) - mErrorMsg = mTorManager->errorMessage() ; + if(RsTor::hasError()) + mErrorMsg = QString::fromStdString(RsTor::errorMessage()) ; switch(tor_control_status) { default: - case Tor::TorControl::Error : tor_control_status_str = "Error" ; break ; - case Tor::TorControl::NotConnected: tor_control_status_str = "Not connected" ; break ; - case Tor::TorControl::Connecting: tor_control_status_str = "Connecting" ; break ; - case Tor::TorControl::Authenticating: tor_control_status_str = "Authenticating" ; break ; - case Tor::TorControl::Connected: tor_control_status_str = "Connected" ; break ; - } + case RsTorConnectivityStatus::ERROR: tor_control_status_str = tr("Error") ; break ; + case RsTorConnectivityStatus::NOT_CONNECTED: tor_control_status_str = tr("Not connected") ; break ; + case RsTorConnectivityStatus::CONNECTING: tor_control_status_str = tr("Connecting") ; break ; + case RsTorConnectivityStatus::SOCKET_CONNECTED: tor_control_status_str = tr("Socket connected") ; break ; + case RsTorConnectivityStatus::AUTHENTICATING: tor_control_status_str = tr("Authenticating") ; break ; + case RsTorConnectivityStatus::AUTHENTICATED: tor_control_status_str = tr("Authenticated") ; break ; + case RsTorConnectivityStatus::HIDDEN_SERVICE_READY: tor_control_status_str = tr("Hidden service ready") ; break ; + case RsTorConnectivityStatus::UNKNOWN: tor_control_status_str = tr("Unknown") ; break ; + } switch(torstatus) { default: - case Tor::TorControl::TorUnknown: torstatus_str = "Unknown" ; break ; - case Tor::TorControl::TorOffline: torstatus_str = "Tor offline" ; break ; - case Tor::TorControl::TorReady: torstatus_str = "Tor ready" ; break ; + case RsTorStatus::UNKNOWN: torstatus_str = tr("Unknown") ; break ; + case RsTorStatus::OFFLINE: torstatus_str = tr("Tor offline") ; break ; + case RsTorStatus::READY: torstatus_str = tr("Tor ready") ; break ; } torStatus_LB->setText(torstatus_str) ; - if(torstatus == Tor::TorControl::TorUnknown) + if(torstatus == RsTorStatus::UNKNOWN) torStatus_LB->setToolTip(tr("Check that Tor is accessible in your executable path")) ; else torStatus_LB->setToolTip("") ; - QVariantMap qvm = mTorManager->control()->bootstrapStatus(); + std::map qvm = RsTor::bootstrapStatus(); QString bootstrapstatus_str ; std::cerr << "Tor control status: " << tor_control_status_str.toStdString() << std::endl; std::cerr << "Tor status: " << torstatus_str.toStdString() << std::endl; - std::cerr << "Bootstrap status map: " << std::endl; for(auto it(qvm.begin());it!=qvm.end();++it) - std::cerr << " " << it.key().toStdString() << " : " << it.value().toString().toStdString() << std::endl; + std::cerr << " " << it->first << " : " << it->second << std::endl; - if(!qvm["progress"].toString().isNull()) - torBootstrapStatus_LB->setText(qvm["progress"].toString() + " % (" + qvm["summary"].toString() + ")") ; + if(!qvm["progress"].empty()) + torBootstrapStatus_LB->setText(QString::fromStdString(qvm["progress"]) + " % (" + QString::fromStdString(qvm["summary"]) + ")") ; else torBootstrapStatus_LB->setText(tr("[Waiting for Tor...]")) ; - QString service_id ; - QString onion_address ; - QHostAddress service_target_address ; + std::string service_id ; + std::string onion_address ; + std::string service_target_address ; uint16_t service_port ; uint16_t target_port ; - if(mTorManager->getHiddenServiceInfo(service_id,onion_address,service_port, service_target_address,target_port)) + if(RsTor::getHiddenServiceInfo(service_id,onion_address,service_port, service_target_address,target_port)) { - hiddenServiceAddress_LB->setText(QString::number(service_port) + ":" + service_target_address.toString() + ":" + QString::number(target_port)); - onionAddress_LB->setText(onion_address); + hiddenServiceAddress_LB->setText(QString::number(service_port) + ":" + QString::fromStdString(service_target_address) + ":" + QString::number(target_port)); + onionAddress_LB->setText(QString::fromStdString(onion_address)); } else { @@ -123,34 +139,39 @@ void TorControlDialog::statusChanged() showLog(); adjustSize(); - QCoreApplication::processEvents(); // forces update + QCoreApplication::processEvents(); // forces update } void TorControlDialog::showLog() { - static std::set already_seen ; + static std::set already_seen ; - QString s ; - QStringList logmsgs = mTorManager->logMessages() ; - bool can_print = false ; + std::string s ; + std::list logmsgs = RsTor::logMessages() ; + bool can_print = false ; - for(QStringList::const_iterator it(logmsgs.begin());it!=logmsgs.end();++it) - { + for(auto it(logmsgs.begin());it!=logmsgs.end();++it) + { s += *it + "\n" ; - if(already_seen.find(*it) == already_seen.end()) - { - can_print = true ; - already_seen.insert(*it); - } + if(already_seen.find(*it) == already_seen.end()) + { + can_print = true ; + already_seen.insert(*it); + } - if(can_print) - std::cerr << "[TOR DEBUG LOG] " << (*it).toStdString() << std::endl; - } + if(can_print) + { + std::cerr << "[TOR DEBUG LOG] " << *it << std::endl; -// torLog_TB->setText(s) ;: + QString s = QString::fromStdString(*it); + int n = s.indexOf(QString("Bootstrapped")); - std::cerr << "Connexion Proxy: " << mTorManager->control()->socksAddress().toString().toStdString() << ":" << mTorManager->control()->socksPort() << std::endl; + if(n >= 0) + torBootstrapStatus_LB->setText(s.mid(n+QString("Bootstrapped").length())); + } + } + //std::cerr << "Connexion Proxy: " << RsTor::socksAddress() << ":" << QString::number(RsTor::socksPort()).toStdString() << std::endl; } TorControlDialog::TorStatus TorControlDialog::checkForTor(QString& error_msg) @@ -161,9 +182,9 @@ TorControlDialog::TorStatus TorControlDialog::checkForTor(QString& error_msg) return TorControlDialog::TOR_STATUS_FAIL ; } - switch(mTorManager->control()->torStatus()) + switch(RsTor::torStatus()) { - case Tor::TorControl::TorReady: rstime::rs_usleep(1*1000*1000);return TOR_STATUS_OK ; + case RsTorStatus::READY: rstime::rs_usleep(1*1000*1000);return TOR_STATUS_OK ; default: return TOR_STATUS_UNKNOWN ; } @@ -171,60 +192,35 @@ TorControlDialog::TorStatus TorControlDialog::checkForTor(QString& error_msg) TorControlDialog::HiddenServiceStatus TorControlDialog::checkForHiddenService() { - std::cerr << "Checking for hidden services:" ; + std::cerr << "Checking for hidden services:" ; - switch(mHiddenServiceStatus) - { - default: - case HIDDEN_SERVICE_STATUS_UNKNOWN: { + std::string service_id; - std::cerr << " trying to setup. " ; + RsTorHiddenServiceStatus service_status = RsTor::getHiddenServiceStatus(service_id); - if(!mTorManager->setupHiddenService()) - { - mHiddenServiceStatus = HIDDEN_SERVICE_STATUS_FAIL ; - std::cerr << "Failed." << std::endl; - return mHiddenServiceStatus ; - } - std::cerr << "Done." << std::endl; - mHiddenServiceStatus = HIDDEN_SERVICE_STATUS_REQUESTED ; - return mHiddenServiceStatus ; - } + if(service_id.empty()) + { + std::cerr << "Not ready yet." << std::endl; + return HIDDEN_SERVICE_STATUS_REQUESTED ; + } + else + { + if(mHiddenService.empty()) + mHiddenService = service_id ; - case HIDDEN_SERVICE_STATUS_REQUESTED: { - QList hidden_services = mTorManager->control()->hiddenServices(); + std::cerr << "New service acquired. Status is " << (int)service_status ; - if(hidden_services.empty()) - { - std::cerr << "Not ready yet." << std::endl; - return mHiddenServiceStatus ; - } - else - { - if(mHiddenService == NULL) - mHiddenService = *(hidden_services.begin()) ; + if(service_status == RsTorHiddenServiceStatus::ONLINE) + { + std::cerr << ": published and running!" << std::endl; - Tor::HiddenService::Status hss = mHiddenService->status(); - - std::cerr << "New service acquired. Status is " << hss ; - - if(hss == Tor::HiddenService::Online) - { - mHiddenServiceStatus = HIDDEN_SERVICE_STATUS_OK ; - std::cerr << ": published and running!" << std::endl; - - return mHiddenServiceStatus ; - } - else - { - std::cerr << ": not ready yet." << std::endl; - return mHiddenServiceStatus ; - } - } - } - case HIDDEN_SERVICE_STATUS_OK : - std::cerr << "New service acquired." << std::endl; - return mHiddenServiceStatus ; - } + return HIDDEN_SERVICE_STATUS_OK ; + } + else + { + std::cerr << ": not ready yet." << std::endl; + return HIDDEN_SERVICE_STATUS_REQUESTED ; + } + } } diff --git a/retroshare-gui/src/TorControl/TorControlWindow.h b/retroshare-gui/src/TorControl/TorControlWindow.h index c4e8ce522..412c08ed5 100644 --- a/retroshare-gui/src/TorControl/TorControlWindow.h +++ b/retroshare-gui/src/TorControl/TorControlWindow.h @@ -1,3 +1,5 @@ +#include "retroshare/rsevents.h" +#include "retroshare/rstor.h" #include "ui_TorControlWindow.h" class QTcpServer ; @@ -12,7 +14,8 @@ class TorControlDialog: public QWidget, public Ui::TorControlDialog Q_OBJECT public: - TorControlDialog(Tor::TorManager *tm,QWidget *parent =NULL); + TorControlDialog(QWidget *parent =NULL); + virtual ~TorControlDialog(); enum TorStatus { TOR_STATUS_UNKNOWN = 0x00, @@ -34,15 +37,14 @@ public: protected slots: void showLog(); - void statusChanged(); - void onIncomingConnection(); + void statusChanged(RsTorStatus torstatus,RsTorConnectivityStatus tor_control_status); + void onIncomingConnection(); + void handleEvent_main_thread(std::shared_ptr event); private: QString mErrorMsg ; - HiddenServiceStatus mHiddenServiceStatus ; - - Tor::TorManager *mTorManager ; - Tor::HiddenService *mHiddenService ; + std::string mHiddenService; QTcpServer *mIncomingServer ; + RsEventsHandlerId_t mEventHandlerId; }; diff --git a/retroshare-gui/src/TorControl/TorControlWindow.ui b/retroshare-gui/src/TorControl/TorControlWindow.ui index 602146641..6077485e5 100644 --- a/retroshare-gui/src/TorControl/TorControlWindow.ui +++ b/retroshare-gui/src/TorControl/TorControlWindow.ui @@ -40,6 +40,12 @@ + + + 0 + 0 + + @@ -55,6 +61,12 @@ + + + 0 + 0 + + Tor status: @@ -79,8 +91,14 @@ + + + 0 + 0 + + - Hidden service address: + Hidden address: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -89,8 +107,14 @@ + + + 0 + 0 + + - Tor bootstrap status: + Tor status: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -106,6 +130,12 @@ + + + 0 + 0 + + Onion address: diff --git a/retroshare-gui/src/TorControl/TorManager.cpp b/retroshare-gui/src/TorControl/TorManager.cpp deleted file mode 100644 index 221a55935..000000000 --- a/retroshare-gui/src/TorControl/TorManager.cpp +++ /dev/null @@ -1,526 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "TorManager.h" -#include "TorProcess.h" -#include "TorControl.h" -#include "CryptoKey.h" -#include "HiddenService.h" -#include "GetConfCommand.h" -#include "Settings.h" -#include -#include -#include -#include -#include - -using namespace Tor; - -namespace Tor -{ - -class TorManagerPrivate : public QObject -{ - Q_OBJECT - -public: - TorManager *q; - TorProcess *process; - TorControl *control; - QString dataDir; - QString hiddenServiceDir; - QStringList logMessages; - QString errorMessage; - bool configNeeded; - - HiddenService *hiddenService ; - - explicit TorManagerPrivate(TorManager *parent = 0); - - QString torExecutablePath() const; - bool createDataDir(const QString &path); - bool createDefaultTorrc(const QString &path); - - void setError(const QString &errorMessage); - -public slots: - void processStateChanged(int state); - void processErrorChanged(const QString &errorMessage); - void processLogMessage(const QString &message); - void controlStatusChanged(int status); - void getConfFinished(); -}; - -} - -TorManager::TorManager(QObject *parent) - : QObject(parent), d(new TorManagerPrivate(this)) -{ -} - -TorManagerPrivate::TorManagerPrivate(TorManager *parent) - : QObject(parent) - , q(parent) - , process(0) - , control(new TorControl(this)) - , configNeeded(false) - , hiddenService(NULL) -{ - connect(control, SIGNAL(statusChanged(int,int)), SLOT(controlStatusChanged(int))); -} - -TorManager *TorManager::instance() -{ - static TorManager *p = 0; - if (!p) - p = new TorManager(qApp); - return p; -} - -TorControl *TorManager::control() -{ - return d->control; -} - -TorProcess *TorManager::process() -{ - return d->process; -} - -bool TorManager::isTorAvailable() -{ - return !instance()->d->torExecutablePath().isNull(); -} - -QString TorManager::torDataDirectory() const -{ - return d->dataDir; -} - -void TorManager::setTorDataDirectory(const QString &path) -{ - d->dataDir = QDir::fromNativeSeparators(path); - - if (!d->dataDir.isEmpty() && !d->dataDir.endsWith(QLatin1Char('/'))) - d->dataDir.append(QLatin1Char('/')); -} - -QString TorManager::hiddenServiceDirectory() const -{ - return d->hiddenServiceDir; -} -void TorManager::setHiddenServiceDirectory(const QString &path) -{ - d->hiddenServiceDir = QDir::fromNativeSeparators(path); - - if (!d->hiddenServiceDir.isEmpty() && !d->hiddenServiceDir.endsWith(QLatin1Char('/'))) - d->hiddenServiceDir.append(QLatin1Char('/')); -} - -bool TorManager::setupHiddenService() -{ - if(d->hiddenService != NULL) - { - std::cerr << "TorManager: setupHiddenService() called twice! Not doing anything this time." << std::endl; - return true ; - } - - QString keyData ;//= m_settings->read("serviceKey").toString(); - QString legacyDir = d->hiddenServiceDir; - - std::cerr << "TorManager: setting up hidden service." << std::endl; - - if(legacyDir.isNull()) - { - std::cerr << "legacy dir not set! Cannot proceed." << std::endl; - return false ; - } - - std::cerr << "Using legacy dir: " << legacyDir.toStdString() << std::endl; - - if (!legacyDir.isEmpty() && QFile::exists(legacyDir + QLatin1String("/private_key"))) - { - std::cerr << "Attempting to load key from legacy filesystem format in " << legacyDir.toStdString() << std::endl; - - CryptoKey key; - if (!key.loadFromFile(legacyDir + QLatin1String("/private_key"))) - { - qWarning() << "Cannot load legacy format key from" << legacyDir << "for conversion"; - return false; - } - - d->hiddenService = new Tor::HiddenService(key, legacyDir, this); - - std::cerr << "Got key from legacy dir: " << std::endl; - std::cerr << key.bytes().toStdString() << std::endl; - } - else - { - d->hiddenService = new Tor::HiddenService(legacyDir, this); - - std::cerr << "Creating new hidden service." << std::endl; - - connect(d->hiddenService, SIGNAL(privateKeyChanged()), this, SLOT(hiddenServicePrivateKeyChanged())) ; - connect(d->hiddenService, SIGNAL(hostnameChanged()), this, SLOT(hiddenServiceHostnameChanged())) ; - } - - Q_ASSERT(d->hiddenService); - connect(d->hiddenService, SIGNAL(statusChanged(int,int)), this, SLOT(hiddenServiceStatusChanged(int,int))); - - // Generally, these are not used, and we bind to localhost and port 0 - // for an automatic (and portable) selection. - - QHostAddress address = QHostAddress::LocalHost; // we only listen from localhost - - quint16 port = 7934;//(quint16)m_settings->read("localListenPort").toInt(); - - std::cerr << "Testing host address: " << address.toString().toStdString() << ":" << port ; - - if (!QTcpServer().listen(address, port)) - { - // XXX error case - std::cerr << " Failed to open incoming socket" << std::endl; - return false; - } - - std::cerr << " OK - Adding hidden service to TorControl." << std::endl; - - //d->hiddenService->addTarget(9878, mIncomingServer->serverAddress(), mIncomingServer->serverPort()); - d->hiddenService->addTarget(9878, QHostAddress::LocalHost,7934); - control()->addHiddenService(d->hiddenService); - - return true ; -} - -void TorManager::hiddenServiceStatusChanged(int old_status,int new_status) -{ - std::cerr << "Hidden service status changed from " << old_status << " to " << new_status << std::endl; -} - -void TorManager::hiddenServicePrivateKeyChanged() -{ - QString key = QString::fromLatin1(d->hiddenService->privateKey().bytes()); - - QFile outfile(d->hiddenServiceDir + QLatin1String("/private_key")) ; - outfile.open( QIODevice::WriteOnly | QIODevice::Text ); - QTextStream s(&outfile); - -#ifdef TO_REMOVE - s << "-----BEGIN RSA PRIVATE KEY-----" << endl; - - for(int i=0;ihiddenServiceDir + QLatin1String("/hostname")) ; - outfile2.open( QIODevice::WriteOnly | QIODevice::Text ); - QTextStream t(&outfile2); - - QString hostname(d->hiddenService->hostname()); - - t << hostname << endl; - outfile2.close(); - - std::cerr << "Hidden service hostname changed: " << hostname.toStdString() << std::endl; -} - -bool TorManager::configurationNeeded() const -{ - return d->configNeeded; -} - -QStringList TorManager::logMessages() const -{ - return d->logMessages; -} - -bool TorManager::hasError() const -{ - return !d->errorMessage.isEmpty(); -} - -QString TorManager::errorMessage() const -{ - return d->errorMessage; -} - -bool TorManager::start() -{ - if (!d->errorMessage.isEmpty()) { - d->errorMessage.clear(); - emit errorChanged(); - } - - SettingsObject settings(QStringLiteral("tor")); - - // If a control port is defined by config or environment, skip launching tor - if (!settings.read("controlPort").isUndefined() || - !qEnvironmentVariableIsEmpty("TOR_CONTROL_PORT")) - { - QHostAddress address(settings.read("controlAddress").toString()); - quint16 port = (quint16)settings.read("controlPort").toInt(); - QByteArray password = settings.read("controlPassword").toString().toLatin1(); - - if (!qEnvironmentVariableIsEmpty("TOR_CONTROL_HOST")) - address = QHostAddress(QString::fromLatin1(qgetenv("TOR_CONTROL_HOST"))); - - if (!qEnvironmentVariableIsEmpty("TOR_CONTROL_PORT")) { - bool ok = false; - port = qgetenv("TOR_CONTROL_PORT").toUShort(&ok); - if (!ok) - port = 0; - } - - if (!qEnvironmentVariableIsEmpty("TOR_CONTROL_PASSWD")) - password = qgetenv("TOR_CONTROL_PASSWD"); - - if (!port) { - d->setError(QStringLiteral("Invalid control port settings from environment or configuration")); - return false; - } - - if (address.isNull()) - address = QHostAddress::LocalHost; - - d->control->setAuthPassword(password); - d->control->connect(address, port); - } else { - // Launch a bundled Tor instance - QString executable = d->torExecutablePath(); - - std::cerr << "Executable path: " << executable.toStdString() << std::endl; - - if (executable.isEmpty()) { - d->setError(QStringLiteral("Cannot find tor executable")); - return false; - } - - if (!d->process) { - d->process = new TorProcess(this); - connect(d->process, SIGNAL(stateChanged(int)), d, SLOT(processStateChanged(int))); - connect(d->process, SIGNAL(errorMessageChanged(QString)), d, - SLOT(processErrorChanged(QString))); - connect(d->process, SIGNAL(logMessage(QString)), d, SLOT(processLogMessage(QString))); - } - - if (!QFile::exists(d->dataDir) && !d->createDataDir(d->dataDir)) { - d->setError(QStringLiteral("Cannot write data location: %1").arg(d->dataDir)); - return false; - } - - QString defaultTorrc = d->dataDir + QStringLiteral("default_torrc"); - if (!QFile::exists(defaultTorrc) && !d->createDefaultTorrc(defaultTorrc)) { - d->setError(QStringLiteral("Cannot write data files: %1").arg(defaultTorrc)); - return false; - } - - QFile torrc(d->dataDir + QStringLiteral("torrc")); - if (!torrc.exists() || torrc.size() == 0) { - d->configNeeded = true; - emit configurationNeededChanged(); - } - - d->process->setExecutable(executable); - d->process->setDataDir(d->dataDir); - d->process->setDefaultTorrc(defaultTorrc); - d->process->start(); - } - return true ; -} - -bool TorManager::getProxyServerInfo(QHostAddress& proxy_server_adress,uint16_t& proxy_server_port) -{ - proxy_server_adress = control()->socksAddress(); - proxy_server_port = control()->socksPort(); - - return proxy_server_port > 1023 ; -} - -bool TorManager::getHiddenServiceInfo(QString& service_id,QString& service_onion_address,uint16_t& service_port, QHostAddress& service_target_address,uint16_t& target_port) -{ - QList hidden_services = control()->hiddenServices(); - - if(hidden_services.empty()) - return false ; - - // Only return the first one. - - for(auto it(hidden_services.begin());it!=hidden_services.end();++it) - { - service_onion_address = (*it)->hostname(); - service_id = (*it)->serviceId(); - - for(auto it2((*it)->targets().begin());it2!=(*it)->targets().end();++it2) - { - service_port = (*it2).servicePort ; - service_target_address = (*it2).targetAddress ; - target_port = (*it2).targetPort; - break ; - } - break ; - } - return true ; -} - -void TorManagerPrivate::processStateChanged(int state) -{ - std::cerr << Q_FUNC_INFO << "state: " << state << " passwd=\"" << QString(process->controlPassword()).toStdString() << "\" " << process->controlHost().toString().toStdString() - << ":" << process->controlPort() << std::endl; - if (state == TorProcess::Ready) { - control->setAuthPassword(process->controlPassword()); - control->connect(process->controlHost(), process->controlPort()); - } -} - -void TorManagerPrivate::processErrorChanged(const QString &errorMessage) -{ - std::cerr << "tor error:" << errorMessage.toStdString() << std::endl; - setError(errorMessage); -} - -void TorManagerPrivate::processLogMessage(const QString &message) -{ - std::cerr << "tor:" << message.toStdString() << std::endl; - if (logMessages.size() >= 50) - logMessages.takeFirst(); - logMessages.append(message); -} - -void TorManagerPrivate::controlStatusChanged(int status) -{ - if (status == TorControl::Connected) { - if (!configNeeded) { - // If DisableNetwork is 1, trigger configurationNeeded - connect(control->getConfiguration(QStringLiteral("DisableNetwork")), - SIGNAL(finished()), SLOT(getConfFinished())); - } - - if (process) { - // Take ownership via this control socket - control->takeOwnership(); - } - } -} - -void TorManagerPrivate::getConfFinished() -{ - GetConfCommand *command = qobject_cast(sender()); - if (!command) - return; - - if (command->get("DisableNetwork").toInt() == 1 && !configNeeded) { - configNeeded = true; - emit q->configurationNeededChanged(); - } -} - -QString TorManagerPrivate::torExecutablePath() const -{ - SettingsObject settings(QStringLiteral("tor")); - QString path = settings.read("executablePath").toString(); - - if (!path.isEmpty() && QFile::exists(path)) - return path; - -#ifdef Q_OS_WIN - QString filename(QStringLiteral("/tor.exe")); -#else - QString filename(QStringLiteral("/tor")); -#endif - - path = qApp->applicationDirPath(); - - if (QFile::exists(path + filename)) - return path + filename; - -#ifdef BUNDLED_TOR_PATH - path = QStringLiteral(BUNDLED_TOR_PATH); - if (QFile::exists(path + filename)) - return path + filename; -#endif - -#ifdef __APPLE__ - // on MacOS, try traditional brew installation path - - path = QStringLiteral("/usr/local/opt/tor/bin") ; - - if (QFile::exists(path + filename)) - return path + filename; -#endif - - // Try $PATH - return filename.mid(1); -} - -bool TorManagerPrivate::createDataDir(const QString &path) -{ - QDir dir(path); - return dir.mkpath(QStringLiteral(".")); -} - -bool TorManagerPrivate::createDefaultTorrc(const QString &path) -{ - static const char defaultTorrcContent[] = - "SocksPort auto\n" - "AvoidDiskWrites 1\n" -// "DisableNetwork 1\n" // (cyril) I removed this because it prevents Tor to bootstrap. - "__ReloadTorrcOnSIGHUP 0\n"; - - QFile file(path); - if (!file.open(QIODevice::WriteOnly)) - return false; - if (file.write(defaultTorrcContent) < 0) - return false; - return true; -} - -void TorManagerPrivate::setError(const QString &message) -{ - errorMessage = message; - emit q->errorChanged(); -} - -#include "TorManager.moc" - diff --git a/retroshare-gui/src/TorControl/TorManager.h b/retroshare-gui/src/TorControl/TorManager.h deleted file mode 100644 index e9acc1208..000000000 --- a/retroshare-gui/src/TorControl/TorManager.h +++ /dev/null @@ -1,111 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// This code has been further modified to fit Retroshare context. - -#ifndef TORMANAGER_H -#define TORMANAGER_H - -#include -#include -#include - -namespace Tor -{ - -class TorProcess; -class TorControl; -class TorManagerPrivate; - -/* Run/connect to an instance of Tor according to configuration, and manage - * UI interaction, first time configuration, etc. */ -class TorManager : public QObject -{ - Q_OBJECT - - Q_PROPERTY(bool configurationNeeded READ configurationNeeded NOTIFY configurationNeededChanged) - Q_PROPERTY(QStringList logMessages READ logMessages CONSTANT) - Q_PROPERTY(Tor::TorProcess* process READ process CONSTANT) - Q_PROPERTY(Tor::TorControl* control READ control CONSTANT) - Q_PROPERTY(bool hasError READ hasError NOTIFY errorChanged) - Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorChanged) - Q_PROPERTY(QString torDataDirectory READ torDataDirectory WRITE setTorDataDirectory) - -public: - static bool isTorAvailable() ; - static TorManager *instance(); - - TorProcess *process(); - TorControl *control(); - - - QString torDataDirectory() const; - void setTorDataDirectory(const QString &path); - - QString hiddenServiceDirectory() const; - void setHiddenServiceDirectory(const QString &path); - - // Starts a hidden service, loading it from the config directory that has been set earlier. - bool setupHiddenService() ; - - // True on first run or when the Tor configuration wizard needs to be shown - bool configurationNeeded() const; - - QStringList logMessages() const; - - bool hasError() const; - QString errorMessage() const; - - bool getHiddenServiceInfo(QString& service_id,QString& service_onion_address,uint16_t& service_port, QHostAddress& service_target_address,uint16_t& target_port); - bool getProxyServerInfo(QHostAddress& proxy_server_adress,uint16_t& proxy_server_port); - -public slots: - bool start(); - -private slots: - void hiddenServicePrivateKeyChanged(); - void hiddenServiceHostnameChanged(); - void hiddenServiceStatusChanged(int old_status,int new_status); - -signals: - void configurationNeededChanged(); - void errorChanged(); - -private: - explicit TorManager(QObject *parent = 0); - TorManagerPrivate *d; -}; - -} - -#endif -# diff --git a/retroshare-gui/src/TorControl/TorProcess.cpp b/retroshare-gui/src/TorControl/TorProcess.cpp deleted file mode 100644 index ca1aecfe5..000000000 --- a/retroshare-gui/src/TorControl/TorProcess.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "TorProcess_p.h" -#include "CryptoKey.h" -#include "SecureRNG.h" -#include -#include -#include - -using namespace Tor; - -TorProcess::TorProcess(QObject *parent) - : QObject(parent), d(new TorProcessPrivate(this)) -{ -} - -TorProcess::~TorProcess() -{ - if (state() > NotStarted) - stop(); -} - -TorProcessPrivate::TorProcessPrivate(TorProcess *q) - : QObject(q), q(q), state(TorProcess::NotStarted), controlPort(0), controlPortAttempts(0) -{ - connect(&process, &QProcess::started, this, &TorProcessPrivate::processStarted); - connect(&process, (void (QProcess::*)(int, QProcess::ExitStatus))&QProcess::finished, - this, &TorProcessPrivate::processFinished); - connect(&process, (void (QProcess::*)(QProcess::ProcessError))&QProcess::error, - this, &TorProcessPrivate::processError); - connect(&process, &QProcess::readyRead, this, &TorProcessPrivate::processReadable); - - controlPortTimer.setInterval(500); - connect(&controlPortTimer, &QTimer::timeout, this, &TorProcessPrivate::tryReadControlPort); -} - -QString TorProcess::executable() const -{ - return d->executable; -} - -void TorProcess::setExecutable(const QString &path) -{ - d->executable = path; -} - -QString TorProcess::dataDir() const -{ - return d->dataDir; -} - -void TorProcess::setDataDir(const QString &path) -{ - d->dataDir = path; -} - -QString TorProcess::defaultTorrc() const -{ - return d->defaultTorrc; -} - -void TorProcess::setDefaultTorrc(const QString &path) -{ - d->defaultTorrc = path; -} - -QStringList TorProcess::extraSettings() const -{ - return d->extraSettings; -} - -void TorProcess::setExtraSettings(const QStringList &settings) -{ - d->extraSettings = settings; -} - -TorProcess::State TorProcess::state() const -{ - return d->state; -} - -QString TorProcess::errorMessage() const -{ - return d->errorMessage; -} - -void TorProcess::start() -{ - if (state() > NotStarted) - return; - - d->errorMessage.clear(); - - if (d->executable.isEmpty() || d->dataDir.isEmpty()) { - d->errorMessage = QStringLiteral("Tor executable and data directory not specified"); - d->state = Failed; - emit errorMessageChanged(d->errorMessage); - emit stateChanged(d->state); - return; - } - - if (!d->ensureFilesExist()) { - d->state = Failed; - emit errorMessageChanged(d->errorMessage); - emit stateChanged(d->state); - return; - } - - QByteArray password = controlPassword(); - QByteArray hashedPassword = torControlHashedPassword(password); - if (password.isEmpty() || hashedPassword.isEmpty()) { - d->errorMessage = QStringLiteral("Random password generation failed"); - d->state = Failed; - emit errorMessageChanged(d->errorMessage); - emit stateChanged(d->state); - } - - QStringList args; - if (!d->defaultTorrc.isEmpty()) - args << QStringLiteral("--defaults-torrc") << d->defaultTorrc; - args << QStringLiteral("-f") << d->torrcPath(); - args << QStringLiteral("DataDirectory") << d->dataDir; - args << QStringLiteral("HashedControlPassword") << QString::fromLatin1(hashedPassword); - args << QStringLiteral("ControlPort") << QStringLiteral("auto"); - args << QStringLiteral("ControlPortWriteToFile") << d->controlPortFilePath(); - args << QStringLiteral("__OwningControllerProcess") << QString::number(qApp->applicationPid()); - args << d->extraSettings; - - d->state = Starting; - emit stateChanged(d->state); - - if (QFile::exists(d->controlPortFilePath())) - QFile::remove(d->controlPortFilePath()); - d->controlPort = 0; - d->controlHost.clear(); - - d->process.setProcessChannelMode(QProcess::MergedChannels); - d->process.start(d->executable, args, QIODevice::ReadOnly); -} - -void TorProcess::stop() -{ - if (state() < Starting) - return; - - d->controlPortTimer.stop(); - - if (d->process.state() == QProcess::Starting) - d->process.waitForStarted(2000); - - d->state = NotStarted; - - // Windows can't terminate the process well, but Tor will clean itself up -#ifndef Q_OS_WIN - if (d->process.state() == QProcess::Running) { - d->process.terminate(); - if (!d->process.waitForFinished(5000)) { - qWarning() << "Tor process" << d->process.pid() << "did not respond to terminate, killing..."; - d->process.kill(); - if (!d->process.waitForFinished(2000)) { - qCritical() << "Tor process" << d->process.pid() << "did not respond to kill!"; - } - } - } -#endif - - emit stateChanged(d->state); -} - -QByteArray TorProcess::controlPassword() -{ - if (d->controlPassword.isEmpty()) - d->controlPassword = SecureRNG::randomPrintable(16); - return d->controlPassword; -} - -QHostAddress TorProcess::controlHost() -{ - return d->controlHost; -} - -quint16 TorProcess::controlPort() -{ - return d->controlPort; -} - -bool TorProcessPrivate::ensureFilesExist() -{ - QFile torrc(torrcPath()); - if (!torrc.exists()) { - QDir dir(dataDir); - if (!dir.exists() && !dir.mkpath(QStringLiteral("."))) { - errorMessage = QStringLiteral("Cannot create Tor data directory: %1").arg(dataDir); - return false; - } - - if (!torrc.open(QIODevice::ReadWrite)) { - errorMessage = QStringLiteral("Cannot create Tor configuration file: %1").arg(torrcPath()); - return false; - } - } - - return true; -} - -QString TorProcessPrivate::torrcPath() const -{ - return QDir::toNativeSeparators(dataDir) + QDir::separator() + QStringLiteral("torrc"); -} - -QString TorProcessPrivate::controlPortFilePath() const -{ - return QDir::toNativeSeparators(dataDir) + QDir::separator() + QStringLiteral("control-port"); -} - -void TorProcessPrivate::processStarted() -{ - state = TorProcess::Connecting; - emit q->stateChanged(state); - - controlPortAttempts = 0; - controlPortTimer.start(); -} - -void TorProcessPrivate::processFinished() -{ - if (state < TorProcess::Starting) - return; - - controlPortTimer.stop(); - errorMessage = process.errorString(); - if (errorMessage.isEmpty()) - errorMessage = QStringLiteral("Process exited unexpectedly (code %1)").arg(process.exitCode()); - state = TorProcess::Failed; - emit q->errorMessageChanged(errorMessage); - emit q->stateChanged(state); -} - -void TorProcessPrivate::processError(QProcess::ProcessError error) -{ - if (error == QProcess::FailedToStart || error == QProcess::Crashed) - processFinished(); -} - -void TorProcessPrivate::processReadable() -{ - while (process.bytesAvailable() > 0) { - QByteArray line = process.readLine(2048).trimmed(); - if (!line.isEmpty()) - emit q->logMessage(QString::fromLatin1(line)); - } -} - -void TorProcessPrivate::tryReadControlPort() -{ - QFile file(controlPortFilePath()); - if (file.open(QIODevice::ReadOnly)) { - QByteArray data = file.readLine().trimmed(); - - int p; - if (data.startsWith("PORT=") && (p = data.lastIndexOf(':')) > 0) { - controlHost = QHostAddress(QString::fromLatin1(data.mid(5, p - 5))); - controlPort = data.mid(p+1).toUShort(); - - if (!controlHost.isNull() && controlPort > 0) { - controlPortTimer.stop(); - state = TorProcess::Ready; - emit q->stateChanged(state); - return; - } - } - } - - if (++controlPortAttempts * controlPortTimer.interval() > 10000) { - errorMessage = QStringLiteral("No control port available after launching process"); - state = TorProcess::Failed; - emit q->errorMessageChanged(errorMessage); - emit q->stateChanged(state); - } -} - diff --git a/retroshare-gui/src/TorControl/TorProcess.h b/retroshare-gui/src/TorControl/TorProcess.h deleted file mode 100644 index ad489dc43..000000000 --- a/retroshare-gui/src/TorControl/TorProcess.h +++ /dev/null @@ -1,100 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TORPROCESS_H -#define TORPROCESS_H - -#include -#include - -namespace Tor -{ - -class TorProcessPrivate; - -/* Launches and controls a Tor instance with behavior suitable for bundling - * an instance with the application. */ -class TorProcess : public QObject -{ - Q_OBJECT - Q_ENUMS(State) - - Q_PROPERTY(State state READ state NOTIFY stateChanged) - Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged) - -public: - enum State { - Failed = -1, - NotStarted, - Starting, - Connecting, - Ready - }; - - explicit TorProcess(QObject *parent = 0); - virtual ~TorProcess(); - - QString executable() const; - void setExecutable(const QString &path); - - QString dataDir() const; - void setDataDir(const QString &path); - - QString defaultTorrc() const; - void setDefaultTorrc(const QString &path); - - QStringList extraSettings() const; - void setExtraSettings(const QStringList &settings); - - State state() const; - QString errorMessage() const; - QHostAddress controlHost(); - quint16 controlPort(); - QByteArray controlPassword(); - -public slots: - void start(); - void stop(); - -signals: - void stateChanged(int newState); - void errorMessageChanged(const QString &errorMessage); - void logMessage(const QString &message); - -private: - TorProcessPrivate *d; -}; - -} - -#endif - diff --git a/retroshare-gui/src/TorControl/TorProcess_p.h b/retroshare-gui/src/TorControl/TorProcess_p.h deleted file mode 100644 index 9aa2585e3..000000000 --- a/retroshare-gui/src/TorControl/TorProcess_p.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TORPROCESS_P_H -#define TORPROCESS_P_H - -#include "TorProcess.h" -#include -#include - -namespace Tor { - -class TorProcessPrivate : public QObject -{ - Q_OBJECT - -public: - TorProcess *q; - QProcess process; - QString executable; - QString dataDir; - QString defaultTorrc; - QStringList extraSettings; - TorProcess::State state; - QString errorMessage; - QHostAddress controlHost; - quint16 controlPort; - QByteArray controlPassword; - - QTimer controlPortTimer; - int controlPortAttempts; - - TorProcessPrivate(TorProcess *q); - - QString torrcPath() const; - QString controlPortFilePath() const; - bool ensureFilesExist(); - -public slots: - void processStarted(); - void processFinished(); - void processError(QProcess::ProcessError error); - void processReadable(); - void tryReadControlPort(); -}; - -} - -#endif - diff --git a/retroshare-gui/src/TorControl/TorSocket.cpp b/retroshare-gui/src/TorControl/TorSocket.cpp deleted file mode 100644 index fb9c07b26..000000000 --- a/retroshare-gui/src/TorControl/TorSocket.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "TorSocket.h" -#include "TorControl.h" -#include - -using namespace Tor; - -TorSocket::TorSocket(QObject *parent) - : QTcpSocket(parent) - , m_port(0) - , m_reconnectEnabled(true) - , m_maxInterval(900) - , m_connectAttempts(0) -{ - connect(torControl, SIGNAL(connectivityChanged()), SLOT(connectivityChanged())); - connect(&m_connectTimer, SIGNAL(timeout()), SLOT(reconnect())); - connect(this, SIGNAL(disconnected()), SLOT(onFailed())); - connect(this, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(onFailed())); - - m_connectTimer.setSingleShot(true); - connectivityChanged(); -} - -TorSocket::~TorSocket() -{ -} - -void TorSocket::setReconnectEnabled(bool enabled) -{ - if (enabled == m_reconnectEnabled) - return; - - m_reconnectEnabled = enabled; - if (m_reconnectEnabled) { - m_connectAttempts = 0; - reconnect(); - } else { - m_connectTimer.stop(); - } -} - -void TorSocket::setMaxAttemptInterval(int interval) -{ - m_maxInterval = interval; -} - -void TorSocket::resetAttempts() -{ - m_connectAttempts = 0; - if (m_connectTimer.isActive()) { - m_connectTimer.stop(); - m_connectTimer.start(reconnectInterval() * 1000); - } -} - -int TorSocket::reconnectInterval() -{ - int delay = 0; - if (m_connectAttempts <= 4) - delay = 30; - else if (m_connectAttempts <= 6) - delay = 120; - else - delay = m_maxInterval; - - return qMin(delay, m_maxInterval); -} - -void TorSocket::reconnect() -{ - if (!torControl->hasConnectivity() || !reconnectEnabled()) - return; - - m_connectTimer.stop(); - if (!m_host.isEmpty() && m_port) { - std::cerr << "Attempting reconnection of socket to" << m_host.toStdString() << ":" << m_port << std::endl; - connectToHost(m_host, m_port); - } -} - -void TorSocket::connectivityChanged() -{ - if (torControl->hasConnectivity()) { - setProxy(torControl->connectionProxy()); - if (state() == QAbstractSocket::UnconnectedState) - reconnect(); - } else { - m_connectTimer.stop(); - m_connectAttempts = 0; - } -} - -void TorSocket::connectToHost(const QString &hostName, quint16 port, OpenMode openMode, - NetworkLayerProtocol protocol) -{ - m_host = hostName; - m_port = port; - - if (!torControl->hasConnectivity()) - return; - - if (proxy() != torControl->connectionProxy()) - setProxy(torControl->connectionProxy()); - - QAbstractSocket::connectToHost(hostName, port, openMode, protocol); -} - -void TorSocket::connectToHost(const QHostAddress &address, quint16 port, OpenMode openMode) -{ - TorSocket::connectToHost(address.toString(), port, openMode); -} - -void TorSocket::onFailed() -{ - // Make sure the internal connection to the SOCKS proxy is closed - // Otherwise reconnect attempts will fail (#295) - close(); - - if (reconnectEnabled() && !m_connectTimer.isActive()) { - m_connectAttempts++; - m_connectTimer.start(reconnectInterval() * 1000); - std::cerr << "Reconnecting socket to" << m_host.toStdString() << ":" << m_port << "in" << m_connectTimer.interval() / 1000 << "seconds" << std::endl; - } -} diff --git a/retroshare-gui/src/TorControl/TorSocket.h b/retroshare-gui/src/TorControl/TorSocket.h deleted file mode 100644 index 0c68f7854..000000000 --- a/retroshare-gui/src/TorControl/TorSocket.h +++ /dev/null @@ -1,97 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TORSOCKET_H -#define TORSOCKET_H - -#include -#include - -namespace Tor { - -/* Specialized QTcpSocket which makes connections over the SOCKS proxy - * from a TorControl instance, automatically attempts reconnections, and - * reacts to Tor's connectivity state. - * - * Use normal QTcpSocket/QAbstractSocket API. When a connection fails, it - * will be retried automatically after the correct interval and when - * connectivity is available. - * - * To fully disconnect, destroy the object, or call - * setReconnectEnabled(false) and disconnect the socket with - * disconnectFromHost or abort. - * - * The caller is responsible for resetting the attempt counter if a - * connection was successful and reconnection will be used again. - */ -class TorSocket : public QTcpSocket -{ - Q_OBJECT - -public: - explicit TorSocket(QObject *parent = 0); - virtual ~TorSocket(); - - bool reconnectEnabled() const { return m_reconnectEnabled; } - void setReconnectEnabled(bool enabled); - int maxAttemptInterval() { return m_maxInterval; } - void setMaxAttemptInterval(int interval); - void resetAttempts(); - - virtual void connectToHost(const QString &hostName, quint16 port, OpenMode openMode = ReadWrite, NetworkLayerProtocol protocol = AnyIPProtocol); - virtual void connectToHost(const QHostAddress &address, quint16 port, OpenMode openMode = ReadWrite); - - QString hostName() const { return m_host; } - quint16 port() const { return m_port; } - -protected: - virtual int reconnectInterval(); - -private slots: - void reconnect(); - void connectivityChanged(); - void onFailed(); - -private: - QString m_host; - quint16 m_port; - QTimer m_connectTimer; - bool m_reconnectEnabled; - int m_maxInterval; - int m_connectAttempts; - - using QAbstractSocket::connectToHost; -}; - -} - -#endif diff --git a/retroshare-gui/src/TorControl/Useful.h b/retroshare-gui/src/TorControl/Useful.h deleted file mode 100644 index 6bb6e44c1..000000000 --- a/retroshare-gui/src/TorControl/Useful.h +++ /dev/null @@ -1,71 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef UTILS_USEFUL_H -#define UTILS_USEFUL_H - -#include -#include - -/* Print a warning for bug conditions, and assert on a debug build. - * - * This should be used in place of Q_ASSERT for bug conditions, along - * with a proper error case for release-mode builds. For example: - * - * if (!connection || !user) { - * BUG() << "Request" << request << "should have a connection and user"; - * return false; - * } - * - * Do not confuse bugs with actual error cases; BUG() should never be - * triggered unless the code or logic is wrong. - */ -#if !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS) -# define BUG() Explode(__FILE__,__LINE__), qWarning() << "BUG:" -namespace { -class Explode -{ -public: - const char *file; - int line; - Explode(const char *file, int line) : file(file), line(line) { } - ~Explode() { - qt_assert("something broke!", file, line); - } -}; -} -#else -# define BUG() qWarning() << "BUG:" -#endif - -#endif - diff --git a/retroshare-gui/src/changelog.txt b/retroshare-gui/src/changelog.txt index 3da31f03c..24c784d1a 100644 --- a/retroshare-gui/src/changelog.txt +++ b/retroshare-gui/src/changelog.txt @@ -439,7 +439,7 @@ Changes for 0.5.4e - Enabled embedded images in private chat and messages (only for QT version 4.7.0 and higher) - added tooltips to GroupFlagsWidget when buttons are unchecked (Patch from Anonym) - when an unknow user attempt to connect, show the name in the security item (Patch from Anonym) - - Load new stylesheets for locale depended things. Loading order: qss.default (internal), qss. (internal e.g. qss.de_DE) + - Load new stylesheets for locale depended things. Loading order: default.qss (internal), .qss (internal e.g. de_DE.qss) stylesheet.qss (internal or external), stylesheet_.lqss (parallel to stylesheet) - Added api for news feeds to the plugin interface. Added news feeds to the FeedReader plugin. - Removed toaster for muted participant of a chat lobby. @@ -586,7 +586,7 @@ Changes for 0.5.4c - GUI * patch from AC to perform html optimization of forum posts using the canonical function optimizeHtml() * fixed bug preventing share manager to modify more than one directory at once - * Moved most of the hardcoded colors of lists and trees to the file qss.default (with help from braindead). + * Moved most of the hardcoded colors of lists and trees to the file default.qss (with help from braindead). Now the stylesheet can redefine these colors. * Added multiselective mute/unmute to chat lobby. Added mute/unmute with double click on icon. * Added flag for hungarian language. @@ -790,10 +790,10 @@ Changes for 0.5.4a * Set the built-in stylesheet "Standard" as default for new profiles. * Removed some unnecessary style sheets. * Added two internal stylesheets: - - qss.default - This file is used as default for all stylesheets (e.g. the frames of + - default.qss - This file is used as default for all stylesheets (e.g. the frames of the AvatarWidget) and can be overloaded from the selected stylesheet - Standard.qss - The standard stylesheet for the current look of RetroShare. More internal stylesheets can be added. - The plan is to move nearly all internal stylesheets to the files Standard.qss/qss.default. + The plan is to move nearly all internal stylesheets to the files Standard.qss/default.qss. After that the "empty" stylesheet should represent the system theme of the os. - Added clear chat history to the context menu of the message text browser @@ -3121,4 +3121,4 @@ We have available for those interested in retroshare: (2) deb installation files for debian/etch and kubuntu/feisty (3) Language pack for those interested in translating. - \ No newline at end of file + diff --git a/retroshare-gui/src/gui/AboutWidget.cpp b/retroshare-gui/src/gui/AboutWidget.cpp index aa239650e..1c4ae6827 100644 --- a/retroshare-gui/src/gui/AboutWidget.cpp +++ b/retroshare-gui/src/gui/AboutWidget.cpp @@ -21,7 +21,7 @@ #include "AboutDialog.h" #include "HelpDialog.h" -#include "qmake_info.h" +#include "include/qmake_info.h" #include "rshare.h" #ifdef RS_JSONAPI @@ -52,8 +52,8 @@ AboutWidget::AboutWidget(QWidget* parent) l->setMargin(0); l->addStretch(1); l->addStretch(1); - frame->setContentsMargins(0, 0, 0, 0); - frame->setLayout(l); + specialFrame->setContentsMargins(0, 0, 0, 0); + specialFrame->setLayout(l); tWidget = NULL; aWidget = NULL; installAWidget(); @@ -67,7 +67,7 @@ AboutWidget::AboutWidget(QWidget* parent) void AboutWidget::installAWidget() { assert(tWidget == NULL); aWidget = new AWidget(); - QVBoxLayout* l = (QVBoxLayout*)frame->layout(); + QVBoxLayout* l = (QVBoxLayout*)specialFrame->layout(); l->insertWidget(0, aWidget); l->setStretchFactor(aWidget, 100); aWidget->setFocus(); @@ -96,10 +96,10 @@ void AboutWidget::installTWidget() { vl->addWidget(levelLabel); vl->addStretch(); - QHBoxLayout* l = (QHBoxLayout*)frame->layout(); + QHBoxLayout* l = (QHBoxLayout*)specialFrame->layout(); l->insertWidget(0, pan); l->insertWidget(0, tWidget); - QRect cRect = frame->contentsRect(); + QRect cRect = specialFrame->contentsRect(); int height = tWidget->heightForWidth(cRect.width()); tWidget->setFixedSize(cRect.width() * cRect.height() / height, cRect.height()); npLabel->setFixedSize(tWidget->squareWidth()*4, tWidget->squareHeight()*5); @@ -117,7 +117,7 @@ void AboutWidget::installTWidget() { void AboutWidget::switchPages() { QLayoutItem* li = NULL; - QLayout* l = frame->layout(); + QLayout* l = specialFrame->layout(); while ((li = l->takeAt(0)) && li->widget()) { li->widget()->deleteLater(); } @@ -142,7 +142,7 @@ void AboutWidget::updateTitle() { if (tWidget == NULL) { - setWindowTitle(QString("%1 %2").arg(tr("About RetroShare"), Rshare::retroshareVersion(true))); + setWindowTitle(QString("%1 %2").arg(tr("About RetroShare"), RsApplication::retroshareVersion(true))); } else { @@ -158,9 +158,9 @@ void AboutWidget::updateTitle() void AboutWidget::mousePressEvent(QMouseEvent *e) { QPoint globalPos = mapToGlobal(e->pos()); - QPoint framePos = frame->mapFromGlobal(globalPos); + QPoint framePos = specialFrame->mapFromGlobal(globalPos); - if (frame->contentsRect().contains(framePos)) { + if (specialFrame->contentsRect().contains(framePos)) { { if(e->modifiers() & Qt::ControlModifier) switchPages(); @@ -228,7 +228,7 @@ void AWidget::initImages() #ifdef RS_ONLYHIDDENNODE p.drawText(QPointF(10, 50), QString("%1 : %2 (With embedded Tor)").arg(tr("Retroshare version"), Rshare::retroshareVersion(true))); #else - p.drawText(QPointF(10, 50), QString("%1 : %2").arg(tr("Retroshare version"), Rshare::retroshareVersion(true))); + p.drawText(QPointF(10, 50), QString("%1 : %2").arg(tr("Retroshare version"), RsApplication::retroshareVersion(true))); #endif /* Draw Qt's version number */ @@ -936,7 +936,7 @@ void AboutWidget::on_copy_button_clicked() { QString verInfo; QString rsVerString = "RetroShare Version: "; - rsVerString+=Rshare::retroshareVersion(true); + rsVerString+=RsApplication::retroshareVersion(true); verInfo+=rsVerString; #ifdef RS_ONLYHIDDENNODE verInfo+=" " + tr("Only Hidden Node"); diff --git a/retroshare-gui/src/gui/AboutWidget.ui b/retroshare-gui/src/gui/AboutWidget.ui index 99b638388..548d6fd9a 100644 --- a/retroshare-gui/src/gui/AboutWidget.ui +++ b/retroshare-gui/src/gui/AboutWidget.ui @@ -57,7 +57,7 @@ - + QFrame::StyledPanel diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.cpp b/retroshare-gui/src/gui/ChatLobbyWidget.cpp index 475495674..60ed255a8 100644 --- a/retroshare-gui/src/gui/ChatLobbyWidget.cpp +++ b/retroshare-gui/src/gui/ChatLobbyWidget.cpp @@ -22,19 +22,20 @@ #include "ChatLobbyWidget.h" #include "notifyqt.h" +#include "RetroShareLink.h" #include "chat/ChatLobbyDialog.h" #include "chat/ChatLobbyUserNotify.h" #include "chat/ChatTabWidget.h" #include "chat/CreateLobbyDialog.h" +#include "common/FilesDefs.h" #include "common/RSTreeWidgetItem.h" #include "common/RSElidedItemDelegate.h" -#include "gui/RetroShareLink.h" -#include "gui/gxs/GxsIdDetails.h" -#include "gui/Identity/IdEditDialog.h" -#include "gui/settings/rsharesettings.h" +#include "gxs/GxsIdDetails.h" +#include "Identity/IdEditDialog.h" +#include "settings/rsharesettings.h" #include "util/HandleRichText.h" +#include "util/misc.h" #include "util/QtVersion.h" -#include "gui/common/FilesDefs.h" #include "retroshare/rsmsgs.h" #include "retroshare/rspeers.h" @@ -59,6 +60,10 @@ #define COLUMN_COUNT 3 #define COLUMN_DATA 0 +#define COLUMN_NAME_NB_CHAR 30 +#define COLUMN_USER_COUNT_NB_CHAR 4 +#define COLUMN_TOPIC_NB_CHAR 25 + #define ROLE_SORT Qt::UserRole #define ROLE_ID Qt::UserRole + 1 #define ROLE_SUBSCRIBED Qt::UserRole + 2 @@ -88,26 +93,37 @@ ChatLobbyWidget::ChatLobbyWidget(QWidget *parent, Qt::WindowFlags flags) { ui.setupUi(this); + int H = QFontMetricsF(ui.lobbyTreeWidget->font()).height(); +#if QT_VERSION < QT_VERSION_CHECK(5,11,0) + int W = QFontMetricsF(ui.lobbyTreeWidget->font()).width("_"); +#else + int W = QFontMetricsF(ui.lobbyTreeWidget->font()).horizontalAdvance("_"); +#endif + m_bProcessSettings = false; myChatLobbyUserNotify = NULL; myInviteYesButton = NULL; myInviteIdChooser = NULL; QObject::connect( NotifyQt::getInstance(), SIGNAL(lobbyListChanged()), SLOT(lobbyChanged())); - QObject::connect( NotifyQt::getInstance(), SIGNAL(chatLobbyEvent(qulonglong,int,const RsGxsId&,const QString&)), this, SLOT(displayChatLobbyEvent(qulonglong,int,const RsGxsId&,const QString&))); + QObject::connect( NotifyQt::getInstance(), SIGNAL(chatLobbyEvent(qulonglong,int,RsGxsId,QString)), this, SLOT(displayChatLobbyEvent(qulonglong,int,RsGxsId,QString))); QObject::connect( NotifyQt::getInstance(), SIGNAL(chatLobbyInviteReceived()), this, SLOT(readChatLobbyInvites())); QObject::connect( ui.lobbyTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(lobbyTreeWidgetCustomPopupMenu(QPoint))); QObject::connect( ui.lobbyTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem*,int))); QObject::connect( ui.lobbyTreeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(updateCurrentLobby())); - QObject::connect( ui.filterLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterItems(QString))); + QObject::connect( ui.filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString))); QObject::connect( ui.filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterColumnChanged(int))); QObject::connect( ui.createLobbyToolButton, SIGNAL(clicked()), this, SLOT(createChatLobby())); compareRole = new RSTreeWidgetItemCompareRole; compareRole->setRole(COLUMN_NAME, ROLE_SORT); + RSElidedItemDelegate *itemDelegate = new RSElidedItemDelegate(this); + itemDelegate->setSpacing(QSize(W/2, H/4)); + ui.lobbyTreeWidget->setItemDelegate(itemDelegate); + ui.lobbyTreeWidget->setColumnCount(COLUMN_COUNT); ui.lobbyTreeWidget->sortItems(COLUMN_NAME, Qt::AscendingOrder); @@ -127,28 +143,28 @@ ChatLobbyWidget::ChatLobbyWidget(QWidget *parent, Qt::WindowFlags flags) QHeaderView_setSectionResizeModeColumn(header, COLUMN_TOPIC, QHeaderView::Interactive); privateSubLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER); - privateSubLobbyItem->setText(COLUMN_NAME, tr("Private Subscribed chat rooms")); + privateSubLobbyItem->setText(COLUMN_NAME, tr("Private Subscribed")); privateSubLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "1"); // privateLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PRIVATE)); privateSubLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE); ui.lobbyTreeWidget->insertTopLevelItem(0, privateSubLobbyItem); publicSubLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER); - publicSubLobbyItem->setText(COLUMN_NAME, tr("Public Subscribed chat rooms")); + publicSubLobbyItem->setText(COLUMN_NAME, tr("Public Subscribed")); publicSubLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "2"); // publicLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PUBLIC)); publicSubLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC); ui.lobbyTreeWidget->insertTopLevelItem(1, publicSubLobbyItem); privateLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER); - privateLobbyItem->setText(COLUMN_NAME, tr("Private chat rooms")); + privateLobbyItem->setText(COLUMN_NAME, tr("Private")); privateLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "3"); // privateLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PRIVATE)); privateLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE); ui.lobbyTreeWidget->insertTopLevelItem(2, privateLobbyItem); publicLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER); - publicLobbyItem->setText(COLUMN_NAME, tr("Public chat rooms")); + publicLobbyItem->setText(COLUMN_NAME, tr("Public")); publicLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "4"); // publicLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PUBLIC)); publicLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC); @@ -159,14 +175,11 @@ ChatLobbyWidget::ChatLobbyWidget(QWidget *parent, Qt::WindowFlags flags) ui.lobbyTreeWidget->setColumnHidden(COLUMN_USER_COUNT,true) ; ui.lobbyTreeWidget->setColumnHidden(COLUMN_TOPIC,true) ; ui.lobbyTreeWidget->setSortingEnabled(true) ; - ui.lobbyTreeWidget->setItemDelegateForColumn(COLUMN_NAME, new RSElidedItemDelegate()); - float fact = QFontMetricsF(font()).height()/14.0f; - ui.lobbyTreeWidget->adjustSize(); - ui.lobbyTreeWidget->setColumnWidth(COLUMN_NAME,100*fact); - ui.lobbyTreeWidget->setColumnWidth(COLUMN_USER_COUNT, 50*fact); - ui.lobbyTreeWidget->setColumnWidth(COLUMN_TOPIC, 50*fact); + ui.lobbyTreeWidget->setColumnWidth(COLUMN_NAME,COLUMN_NAME_NB_CHAR*W); + ui.lobbyTreeWidget->setColumnWidth(COLUMN_USER_COUNT, COLUMN_USER_COUNT_NB_CHAR*W); + ui.lobbyTreeWidget->setColumnWidth(COLUMN_TOPIC, COLUMN_TOPIC_NB_CHAR*W); /** Setup the actions for the header context menu */ showUserCountAct= new QAction(headerItem->text(COLUMN_USER_COUNT),this); @@ -181,7 +194,7 @@ ChatLobbyWidget::ChatLobbyWidget(QWidget *parent, Qt::WindowFlags flags) ui.splitter->setStretchFactor(1, 1); QList sizes; - sizes << 200*fact << width(); // Qt calculates the right sizes + sizes << ui.lobbyTreeWidget->columnWidth(COLUMN_NAME) << width(); // Qt calculates the right sizes ui.splitter->setSizes(sizes); lobbyChanged(); @@ -194,29 +207,31 @@ ChatLobbyWidget::ChatLobbyWidget(QWidget *parent, Qt::WindowFlags flags) // load settings processSettings(true); - int S = QFontMetricsF(font()).height(); - QString help_str = tr("\ -

  Chat Rooms

\ -

Chat rooms work pretty much like IRC. \ - They allow you to talk anonymously with tons of people without the need to make friends.

\ -

A chat room can be public (your friends see it) or private (your friends can't see it, unless you \ - invite them with ). \ - Once you have been invited to a private room, you will be able to see it when your friends \ - are using it.

\ -

The list at left shows \ - chat lobbies your friends are participating in. You can either \ -

    \ -
  • Right click to create a new chat room
  • \ -
  • Double click a chat room to enter, chat, and show it to your friends
  • \ -
\ - Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!\ -

\ - " - ).arg(QString::number(2*S)).arg(QString::number(S)) ; + int hbH = misc::getFontSizeFactor("HelpButton").height(); + QString help_str = tr( + "

  Chat Rooms

" + "

Chat rooms work pretty much like IRC." + " They allow you to talk anonymously with tons of people without the need to make friends.

" + "

A chat room can be public (your friends see it) or private (your friends can't see it, unless you" + " invite them with )." + " Once you have been invited to a private room, you will be able to see it when your friends" + " are using it.

" + "

The list at left shows" + " chat lobbies your friends are participating in. You can either" + "

    " + "
  • Right click to create a new chat room
  • " + "
  • Double click a chat room to enter, chat, and show it to your friends
  • " + "
" + " Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!" + "

" + ).arg(QString::number(2*hbH), QString::number(hbH)) ; - registerHelpButton(ui.helpButton,help_str,"ChatLobbyDialog") ; - - ui.lobbyTreeWidget->setIconSize(QSize(S*1.5,S*1.5)); + registerHelpButton(ui.helpButton,help_str,"ChatLobbyDialog") ; + + int ltwH = misc::getFontSizeFactor("LobbyTreeWidget", 1.5).height(); + ui.lobbyTreeWidget->setIconSize(QSize(ltwH,ltwH)); + + mFontSizeHandler.registerFontSize(ui.lobbyTreeWidget); } ChatLobbyWidget::~ChatLobbyWidget() @@ -232,7 +247,7 @@ ChatLobbyWidget::~ChatLobbyWidget() UserNotify *ChatLobbyWidget::createUserNotify(QObject *parent) { myChatLobbyUserNotify = new ChatLobbyUserNotify(parent); - connect(myChatLobbyUserNotify, SIGNAL(countChanged(ChatLobbyId, unsigned int)), this, SLOT(updateNotify(ChatLobbyId, unsigned int))); + connect(myChatLobbyUserNotify, SIGNAL(countChanged(ChatLobbyId,uint)), this, SLOT(updateNotify(ChatLobbyId,uint))); return myChatLobbyUserNotify; } @@ -282,87 +297,84 @@ void ChatLobbyWidget::lobbyTreeWidgetCustomPopupMenu(QPoint) QMenu contextMnu(this); if (item && item->type() == TYPE_FOLDER) { - QAction *action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_CREATE), tr("Create chat room"), this, SLOT(createChatLobby())); + QAction *action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_CREATE), tr("Create chat room"), this, SLOT(createChatLobby())); action->setData(item->data(COLUMN_DATA, ROLE_PRIVACYLEVEL).toInt()); } - if (item && item->type() == TYPE_LOBBY) - { - std::list own_identities ; - rsIdentity->getOwnIds(own_identities) ; + if (item && item->type() == TYPE_LOBBY) + { + std::list own_identities ; + rsIdentity->getOwnIds(own_identities) ; - if (item->data(COLUMN_DATA, ROLE_SUBSCRIBED).toBool()) - contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_UNSUBSCRIBE), tr("Leave this room"), this, SLOT(unsubscribeItem())); - else - { - QTreeWidgetItem *item = ui.lobbyTreeWidget->currentItem(); + if (item->data(COLUMN_DATA, ROLE_SUBSCRIBED).toBool()) + contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_UNSUBSCRIBE), tr("Leave this room"), this, SLOT(unsubscribeItem())); + else + { + ChatLobbyFlags flags(item->data(COLUMN_DATA, ROLE_FLAGS).toUInt()); - //ChatLobbyId id = item->data(COLUMN_DATA, ROLE_ID).toULongLong(); - ChatLobbyFlags flags(item->data(COLUMN_DATA, ROLE_FLAGS).toUInt()); + bool removed = false ; + if(flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED) + removed = trimAnonIds(own_identities) ; - bool removed = false ; - if(flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED) - removed = trimAnonIds(own_identities) ; - - if(own_identities.empty()) - { - if(removed) - contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_SUBSCRIBE), tr("Create a non anonymous identity and enter this room"), this, SLOT(createIdentityAndSubscribe())); - else - contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_SUBSCRIBE), tr("Create an identity and enter this chat room"), this, SLOT(createIdentityAndSubscribe())); - } - else if(own_identities.size() == 1) - { - QAction *action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_SUBSCRIBE), tr("Enter this chat room"), this, SLOT(subscribeChatLobbyAs())); - action->setData(QString::fromStdString((own_identities.front()).toStdString())) ; - } - else - { - QMenu *mnu = contextMnu.addMenu(FilesDefs::getIconFromQtResourcePath(IMAGE_SUBSCRIBE),tr("Enter this chat room as...")) ; + if(own_identities.empty()) + { + if(removed) + contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_SUBSCRIBE), tr("Create a non anonymous identity and enter this room"), this, SLOT(createIdentityAndSubscribe())); + else + contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_SUBSCRIBE), tr("Create an identity and enter this chat room"), this, SLOT(createIdentityAndSubscribe())); + } + else if(own_identities.size() == 1) + { + QAction *action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_SUBSCRIBE), tr("Enter this chat room"), this, SLOT(subscribeChatLobbyAs())); + action->setData(QString::fromStdString((own_identities.front()).toStdString())) ; + } + else + { + QMenu *mnu = contextMnu.addMenu(FilesDefs::getIconFromQtResourcePath(IMAGE_SUBSCRIBE),tr("Enter this chat room as...")) ; - for(std::list::const_iterator it=own_identities.begin();it!=own_identities.end();++it) - { - RsIdentityDetails idd ; - rsIdentity->getIdDetails(*it,idd) ; + for(std::list::const_iterator it=own_identities.begin();it!=own_identities.end();++it) + { + RsIdentityDetails idd ; + rsIdentity->getIdDetails(*it,idd) ; - QPixmap pixmap ; + QPixmap pixmap ; - if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap, GxsIdDetails::SMALL)) - pixmap = GxsIdDetails::makeDefaultIcon(*it,GxsIdDetails::SMALL) ; + if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap, GxsIdDetails::SMALL)) + 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())); - action->setData(QString::fromStdString((*it).toStdString())) ; - } - } - } + 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())) ; + } + } + } #ifdef TO_BE_REMOVED - // This code is not needed anymore because AutoSubscribe is now automatically handled with chat room subscription. + // This code is not needed anymore because AutoSubscribe is now automatically handled with chat room subscription. - if (item->data(COLUMN_DATA, ROLE_AUTOSUBSCRIBE).toBool()) - contextMnu.addAction(QIcon(IMAGE_AUTOSUBSCRIBE), tr("Remove Auto Subscribe"), this, SLOT(autoSubscribeItem())); - else if(!own_identities.empty()) - contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Add Auto Subscribe"), this, SLOT(autoSubscribeItem())); + if (item->data(COLUMN_DATA, ROLE_AUTOSUBSCRIBE).toBool()) + contextMnu.addAction(QIcon(IMAGE_AUTOSUBSCRIBE), tr("Remove Auto Subscribe"), this, SLOT(autoSubscribeItem())); + else if(!own_identities.empty()) + contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Add Auto Subscribe"), this, SLOT(autoSubscribeItem())); #endif - contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_COPYRSLINK), tr("Copy RetroShare Link"), this, SLOT(copyItemLink())); - } + contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_COPYRSLINK), tr("Copy RetroShare Link"), this, SLOT(copyItemLink())); + } - contextMnu.addSeparator();//------------------------------------------------------------------- + contextMnu.addSeparator();//------------------------------------------------------------------- - showUserCountAct->setChecked(!ui.lobbyTreeWidget->isColumnHidden(COLUMN_USER_COUNT)); - showTopicAct->setChecked(!ui.lobbyTreeWidget->isColumnHidden(COLUMN_TOPIC)); + showUserCountAct->setChecked(!ui.lobbyTreeWidget->isColumnHidden(COLUMN_USER_COUNT)); + showTopicAct->setChecked(!ui.lobbyTreeWidget->isColumnHidden(COLUMN_TOPIC)); - QMenu *menu = contextMnu.addMenu(tr("Columns")); - menu->addAction(showUserCountAct); - menu->addAction(showTopicAct); + QMenu *menu = contextMnu.addMenu(tr("Columns")); + menu->addAction(showUserCountAct); + menu->addAction(showTopicAct); - contextMnu.exec(QCursor::pos()); + contextMnu.exec(QCursor::pos()); } void ChatLobbyWidget::lobbyChanged() { - updateDisplay(); + ChatLobbyWidget::updateDisplay(); } static void updateItem(QTreeWidget *treeWidget, QTreeWidgetItem *item, ChatLobbyId id, const std::string &name, const std::string &topic, int count, bool subscribed, bool autoSubscribe,ChatLobbyFlags lobby_flags) @@ -410,7 +422,7 @@ static void updateItem(QTreeWidget *treeWidget, QTreeWidgetItem *item, ChatLobby if(lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED) { tooltipstr += QObject::tr("\nSecurity: no anonymous IDs") ; - QColor foreground = QColor(0, 128, 0); // green + QColor foreground = QColor(16, 157, 0); // green for (int column = 0; column < COLUMN_COUNT; ++column) item->setData(column, Qt::ForegroundRole, foreground); } @@ -596,7 +608,7 @@ void ChatLobbyWidget::updateDisplay() QTreeWidgetItem *itemLoop = lobby_other_item->child(childIndex); if (itemLoop->type() == TYPE_LOBBY && itemLoop->data(COLUMN_DATA, ROLE_ID).toULongLong() == lobby.lobby_id) { delete(lobby_other_item->takeChild(lobby_other_item->indexOfChild(itemLoop))); - childCnt = lobby_other_item->childCount(); + //childCnt = lobby_other_item->childCount(); break; } } @@ -711,9 +723,9 @@ void ChatLobbyWidget::updateDisplay() } } 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")+ QString(" (") + QString::number(publicSubLobbyItem->childCount())+QString(")")); privateSubLobbyItem->setHidden(privateSubLobbyItem->childCount()==0); - publicLobbyItem->setText(COLUMN_NAME, tr("Public chat rooms")+ " (" + QString::number(publicLobbyItem->childCount())+QString(")")); + publicLobbyItem->setText(COLUMN_NAME, tr("Public")+ " (" + QString::number(publicLobbyItem->childCount())+QString(")")); } void ChatLobbyWidget::createChatLobby() @@ -920,7 +932,7 @@ void ChatLobbyWidget::showBlankPage(ChatLobbyId id, bool subscribed /*= false*/) } } - ui.lobbyInfoLabel->setText(text); + ui.info_Label_Lobby->setText(text); return ; } @@ -932,7 +944,7 @@ void ChatLobbyWidget::showBlankPage(ChatLobbyId id, bool subscribed /*= false*/) ui.lobbysec_lineEdit->clear(); QString text = tr("No chat room selected. \nSelect chat rooms at left to show details.\nDouble click a chat room to enter and chat.") ; - ui.lobbyInfoLabel->setText(text) ; + ui.info_Label_Lobby->setText(text) ; } void ChatLobbyWidget::subscribeItem() @@ -1116,6 +1128,7 @@ void ChatLobbyWidget::updateCurrentLobby() filterItems(ui.filterLineEdit->text()); } } + void ChatLobbyWidget::updateMessageChanged(bool incoming, ChatLobbyId id, QDateTime time, QString senderName, QString msg) { QTreeWidgetItem *current_item = ui.lobbyTreeWidget->currentItem(); @@ -1174,9 +1187,11 @@ void ChatLobbyWidget::readChatLobbyInvites() if(found) continue ; - QMessageBox mb(QObject::tr("Join chat room"), - tr("%1 invites you to chat room named %2").arg(QString::fromUtf8(rsPeers->getPeerName((*it).peer_id).c_str())).arg(RsHtml::plainText(it->lobby_name)), - QMessageBox::Question, QMessageBox::Yes,QMessageBox::No, 0); + QMessageBox mb(QObject::tr("Join chat room") + , tr("%1 invites you to chat room named %2") + .arg(QString::fromUtf8(rsPeers->getPeerName((*it).peer_id).c_str()) + , RsHtml::plainText(it->lobby_name)) + , QMessageBox::Question, QMessageBox::Yes,QMessageBox::No, 0); QLabel *label; diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.h b/retroshare-gui/src/gui/ChatLobbyWidget.h index a9bb01895..424780dac 100644 --- a/retroshare-gui/src/gui/ChatLobbyWidget.h +++ b/retroshare-gui/src/gui/ChatLobbyWidget.h @@ -25,6 +25,7 @@ #include "chat/ChatLobbyUserNotify.h" #include "gui/gxs/GxsIdChooser.h" +#include "util/FontSizeHandler.h" #include @@ -56,18 +57,18 @@ class ChatLobbyWidget : public RsAutoUpdatePage public: /** Default constructor */ - ChatLobbyWidget(QWidget *parent = 0, Qt::WindowFlags flags = 0); + ChatLobbyWidget(QWidget *parent = 0, Qt::WindowFlags flags = Qt::WindowFlags()); /** Default destructor */ ~ChatLobbyWidget(); - virtual QIcon iconPixmap() const { return QIcon(IMAGE_CHATLOBBY) ; } //MainPage - virtual QString pageName() const { return tr("Chats") ; } //MainPage - virtual QString helpText() const { return ""; } //MainPage + virtual QIcon iconPixmap() const override { return QIcon(IMAGE_CHATLOBBY) ; } //MainPage + virtual QString pageName() const override { return tr("Chats") ; } //MainPage + virtual QString helpText() const override { return ""; } //MainPage virtual UserNotify *createUserNotify(QObject *parent) override; //MainPage - virtual void updateDisplay(); + virtual void updateDisplay() override; //RsAutoUpdatePage void setCurrentChatPage(ChatLobbyDialog *) ; // used by ChatLobbyDialog to raise. void addChatPage(ChatLobbyDialog *) ; @@ -146,6 +147,8 @@ private: QAbstractButton* myInviteYesButton; GxsIdChooser* myInviteIdChooser; + FontSizeHandler mFontSizeHandler; + /* UI - from Designer */ Ui::ChatLobbyWidget ui; }; diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.ui b/retroshare-gui/src/gui/ChatLobbyWidget.ui index 4a4f863ef..b2f711b72 100644 --- a/retroshare-gui/src/gui/ChatLobbyWidget.ui +++ b/retroshare-gui/src/gui/ChatLobbyWidget.ui @@ -70,7 +70,14 @@
- + + + + 12 + 75 + true + + Chat rooms @@ -95,7 +102,7 @@ Qt::NoFocus - + :/icons/help_64.png:/icons/help_64.png @@ -183,7 +190,7 @@ - + 16 @@ -228,6 +235,13 @@ + + + 12 + 75 + true + + @@ -244,6 +258,7 @@ + 12 75 true @@ -261,6 +276,13 @@ 0 + + + 16 + 75 + true + + TextLabel @@ -270,6 +292,7 @@ + 12 75 true @@ -296,6 +319,7 @@ + 12 75 true @@ -325,6 +349,7 @@ + 12 75 true @@ -351,6 +376,7 @@ + 12 75 true @@ -371,6 +397,7 @@ + 12 75 true @@ -396,7 +423,7 @@
- + TextLabel @@ -432,16 +459,15 @@ LineEditClear QLineEdit -
gui/common/LineEditClear.h
+
gui/common/LineEditClear.h
- StyledLabel - QLabel -
gui/common/StyledLabel.h
+ RSTreeWidget + QTreeWidget +
gui/common/RSTreeWidget.h
- diff --git a/retroshare-gui/src/gui/Circles/CirclesDialog.cpp b/retroshare-gui/src/gui/Circles/CirclesDialog.cpp index 41fd4e9f2..a05ff2f20 100644 --- a/retroshare-gui/src/gui/Circles/CirclesDialog.cpp +++ b/retroshare-gui/src/gui/Circles/CirclesDialog.cpp @@ -25,6 +25,7 @@ #include "gui/Circles/CirclesDialog.h" #include "gui/Circles/CreateCircleDialog.h" #include "gui/common/UIStateHelper.h" +#include "util/qtthreadsutils.h" #include #include @@ -72,9 +73,6 @@ CirclesDialog::CirclesDialog(QWidget *parent) connect(ui.treeWidget_membership, SIGNAL(itemSelectionChanged()), this, SLOT(circle_selected())); - /* Setup TokenQueue */ - mCircleQueue = new TokenQueue(rsGxsCircles->getTokenService(), this); - /* Set header resize modes and initial section sizes */ QHeaderView * membership_header = ui.treeWidget_membership->header () ; membership_header->resizeSection ( CIRCLEGROUP_CIRCLE_COL_GROUPNAME, 200 ); @@ -82,7 +80,6 @@ CirclesDialog::CirclesDialog(QWidget *parent) CirclesDialog::~CirclesDialog() { - delete mCircleQueue; } void CirclesDialog::todo() @@ -564,38 +561,36 @@ void CirclesDialog::requestGroupMeta() { mStateHelper->setLoading(CIRCLESDIALOG_GROUPMETA, true); - std::cerr << "CirclesDialog::requestGroupMeta()"; - std::cerr << std::endl; + RsThread::async([this]() + { + std::list circles; - mCircleQueue->cancelActiveRequestTokens(CIRCLESDIALOG_GROUPMETA); + if(!rsGxsCircles->getCirclesSummaries(circles)) + { + std::cerr << __PRETTY_FUNCTION__ << " failed to get circles summaries " << std::endl; + return; + } - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + RsQThreadUtils::postToObject( [this,circles]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete, note that + * Qt::QueuedConnection is important! + */ - uint32_t token; - mCircleQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, CIRCLESDIALOG_GROUPMETA); + loadGroupMeta(circles); + + }, this ); + }); } -void CirclesDialog::loadGroupMeta(const uint32_t &token) +void CirclesDialog::loadGroupMeta(const std::list& groupInfo) { mStateHelper->setLoading(CIRCLESDIALOG_GROUPMETA, false); - std::cerr << "CirclesDialog::loadGroupMeta()"; - std::cerr << std::endl; - ui.treeWidget_membership->clear(); - std::list groupInfo; - std::list::iterator vit; - - if (!rsGxsCircles->getGroupSummary(token,groupInfo)) - { - std::cerr << "CirclesDialog::loadGroupMeta() Error getting GroupMeta"; - std::cerr << std::endl; - mStateHelper->setActive(CIRCLESDIALOG_GROUPMETA, false); - return; - } - mStateHelper->setActive(CIRCLESDIALOG_GROUPMETA, true); /* add the top level item */ @@ -615,7 +610,7 @@ void CirclesDialog::loadGroupMeta(const uint32_t &token) externalOtherCirclesItem->setText(0, tr("External Circles (Other)")); ui.treeWidget_membership->addTopLevelItem(externalOtherCirclesItem); - for(vit = groupInfo.begin(); vit != groupInfo.end(); ++vit) + for(auto vit = groupInfo.begin(); vit != groupInfo.end(); ++vit) { /* Add Widget, and request Pages */ std::cerr << "CirclesDialog::loadGroupMeta() GroupId: " << vit->mGroupId; @@ -647,25 +642,3 @@ void CirclesDialog::loadGroupMeta(const uint32_t &token) } } } - -void CirclesDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) -{ - std::cerr << "CirclesDialog::loadRequest() UserType: " << req.mUserType; - std::cerr << std::endl; - - if (queue == mCircleQueue) - { - /* now switch on req */ - switch(req.mUserType) - { - case CIRCLESDIALOG_GROUPMETA: - loadGroupMeta(req.mToken); - break; - - default: - std::cerr << "CirclesDialog::loadRequest() ERROR: INVALID TYPE"; - std::cerr << std::endl; - break; - } - } -} diff --git a/retroshare-gui/src/gui/Circles/CirclesDialog.h b/retroshare-gui/src/gui/Circles/CirclesDialog.h index ac87f9f61..56011dc61 100644 --- a/retroshare-gui/src/gui/Circles/CirclesDialog.h +++ b/retroshare-gui/src/gui/Circles/CirclesDialog.h @@ -24,14 +24,13 @@ #define MRK_CIRCLE_DIALOG_H #include "gui/gxs/RsGxsUpdateBroadcastPage.h" -#include "util/TokenQueue.h" #include "ui_CirclesDialog.h" #define IMAGE_CIRCLES ":/icons/png/circles.png" class UIStateHelper; -class CirclesDialog : public MainPage, public TokenResponse +class CirclesDialog : public MainPage { Q_OBJECT @@ -43,8 +42,6 @@ public: virtual QString pageName() const { return tr("Circles") ; } //MainPage virtual QString helpText() const { return ""; } //MainPage - void loadRequest(const TokenQueue *queue, const TokenRequest &req); - protected: virtual void updateDisplay(bool complete); @@ -62,9 +59,8 @@ private: void reloadAll(); void requestGroupMeta(); - void loadGroupMeta(const uint32_t &token); + void loadGroupMeta(const std::list& groupInfo); - TokenQueue *mCircleQueue; UIStateHelper *mStateHelper; /* UI - from Designer */ diff --git a/retroshare-gui/src/gui/Circles/CirclesDialog.ui b/retroshare-gui/src/gui/Circles/CirclesDialog.ui index da9da0b8b..05b89146b 100644 --- a/retroshare-gui/src/gui/Circles/CirclesDialog.ui +++ b/retroshare-gui/src/gui/Circles/CirclesDialog.ui @@ -49,7 +49,14 @@
- + + + + 12 + 75 + true + + Circles @@ -247,13 +254,6 @@
- - - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
-
diff --git a/retroshare-gui/src/gui/Circles/CreateCircleDialog.cpp b/retroshare-gui/src/gui/Circles/CreateCircleDialog.cpp index 2b9d3b804..92003e0a6 100644 --- a/retroshare-gui/src/gui/Circles/CreateCircleDialog.cpp +++ b/retroshare-gui/src/gui/Circles/CreateCircleDialog.cpp @@ -98,7 +98,7 @@ CreateCircleDialog::CreateCircleDialog() connect(ui.addButton, SIGNAL(clicked()), this, SLOT(addMember())); connect(ui.removeButton, SIGNAL(clicked()), this, SLOT(removeMember())); - connect(ui.createButton, SIGNAL(clicked()), this, SLOT(createCircle())); + connect(ui.postButton, SIGNAL(clicked()), this, SLOT(createCircle())); connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(close())); connect(ui.treeWidget_membership, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(selectedMember(QTreeWidgetItem*, QTreeWidgetItem*))); @@ -187,14 +187,14 @@ void CreateCircleDialog::editExistingId(const RsGxsGroupId &circleId, const bool ui.idChooser->setVisible(true) ; } - ui.createButton->setText(tr("Update")); + ui.postButton->setText(tr("Update")); ui.addButton->setEnabled(!readonly) ; ui.removeButton->setEnabled(!readonly) ; if(readonly) { - ui.createButton->hide() ; + ui.postButton->hide() ; ui.cancelButton->setText(tr("Close")); ui.peersSelection_GB->hide() ; ui.addButton->hide() ; @@ -216,7 +216,7 @@ void CreateCircleDialog::editNewId(bool isExternal) { setupForExternalCircle(); ui.headerFrame->setHeaderText(tr("Create New Circle")); - ui.createButton->setText(tr("Create")); + ui.postButton->setText(tr("Create")); } else { @@ -357,8 +357,8 @@ void CreateCircleDialog::addMember(const QString& keyId, const QString& idtype, member->setText(RSCIRCLEID_COL_IDTYPE, idtype); tree->addTopLevelItem(member); - - ui.members_groupBox->setTitle( tr("Invited Members") + " (" + QString::number(ui.treeWidget_membership->topLevelItemCount()) + ")" ); + + updateMembership(); } /** Maybe we can use RsGxsCircleGroup instead of RsGxsCircleDetails ??? (TODO)**/ @@ -413,6 +413,8 @@ void CreateCircleDialog::removeMember() // does this just work? (TODO) delete(item); + + updateMembership(); } void CreateCircleDialog::createCircle() @@ -422,7 +424,7 @@ void CreateCircleDialog::createCircle() close() ; return ; } - + #ifdef DEBUG_CREATE_CIRCLE_DIALOG std::cerr << "CreateCircleDialog::createCircle()"; std::cerr << std::endl; @@ -431,10 +433,10 @@ void CreateCircleDialog::createCircle() QString name = ui.circleName->text(); if(name.isEmpty()) { - /* error message */ - QMessageBox::warning(this, tr("RetroShare"),tr("Please set a name for your Circle"), QMessageBox::Ok, QMessageBox::Ok); + /* error message */ + QMessageBox::warning(this, tr("RetroShare"),tr("Please set a name for your Circle"), QMessageBox::Ok, QMessageBox::Ok); - return; //Don't add a empty Subject!! + return; //Don't add a empty Subject!! } RsGxsCircleGroup circle = mCircleGroup; // init with loaded group @@ -448,23 +450,23 @@ void CreateCircleDialog::createCircle() { case GxsIdChooser::KnowId: case GxsIdChooser::UnKnowId: - circle.mMeta.mAuthorId = authorId; + circle.mMeta.mAuthorId = authorId; circle.mMeta.mAuthenFlags = GXS_SERV::GRP_OPTION_AUTHEN_AUTHOR_SIGN; #ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::createCircle() AuthorId: " << authorId; - std::cerr << std::endl; + std::cerr << "CreateCircleDialog::createCircle() AuthorId: " << authorId; + std::cerr << std::endl; #endif - break; + break; case GxsIdChooser::NoId: case GxsIdChooser::None: circle.mMeta.mAuthorId.clear(); circle.mMeta.mAuthenFlags = 0; default: ; #ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::createCircle() No AuthorId Chosen!"; - std::cerr << std::endl; + std::cerr << "CreateCircleDialog::createCircle() No AuthorId Chosen!"; + std::cerr << std::endl; #endif } @@ -472,144 +474,164 @@ void CreateCircleDialog::createCircle() /* copy Ids from GUI */ QTreeWidget *tree = ui.treeWidget_membership; int count = tree->topLevelItemCount(); - for(int i = 0; i < count; ++i) + for(int i = 0; i < count; ++i) { - QTreeWidgetItem *item = tree->topLevelItem(i); - QString keyId = item->text(RSCIRCLEID_COL_KEYID); + QTreeWidgetItem *item = tree->topLevelItem(i); + QString keyId = item->text(RSCIRCLEID_COL_KEYID); - /* insert into circle */ - if (mIsExternalCircle) - { - RsGxsId key_id_gxs(keyId.toStdString()) ; + /* insert into circle */ + if (mIsExternalCircle) + { + RsGxsId key_id_gxs(keyId.toStdString()) ; - if(key_id_gxs.isNull()) - { - std::cerr << "Error: Not a proper keyID: " << keyId.toStdString() << std::endl; - continue ; - } + if(key_id_gxs.isNull()) + { + std::cerr << "Error: Not a proper keyID: " << keyId.toStdString() << std::endl; + continue ; + } - circle.mInvitedMembers.insert(key_id_gxs) ; + circle.mInvitedMembers.insert(key_id_gxs) ; #ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::createCircle() Inserting Member: " << keyId.toStdString(); - std::cerr << std::endl; + std::cerr << "CreateCircleDialog::createCircle() Inserting Member: " << keyId.toStdString(); + std::cerr << std::endl; #endif - } - else - { - RsPgpId key_id_pgp(keyId.toStdString()) ; + } + else + { + RsPgpId key_id_pgp(keyId.toStdString()) ; - if(key_id_pgp.isNull()) - { - std::cerr << "Error: Not a proper PGP keyID: " << keyId.toStdString() << std::endl; - continue ; - } + if(key_id_pgp.isNull()) + { + std::cerr << "Error: Not a proper PGP keyID: " << keyId.toStdString() << std::endl; + continue ; + } - circle.mLocalFriends.insert(key_id_pgp) ; + circle.mLocalFriends.insert(key_id_pgp) ; #ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::createCircle() Inserting Friend: " << keyId.toStdString(); - std::cerr << std::endl; + std::cerr << "CreateCircleDialog::createCircle() Inserting Friend: " << keyId.toStdString(); + std::cerr << std::endl; #endif - } + } } - if (mIsExternalCircle) + if (mIsExternalCircle) { #ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::createCircle() External Circle"; - std::cerr << std::endl; + std::cerr << "CreateCircleDialog::createCircle() External Circle"; + std::cerr << std::endl; #endif - // set distribution from GUI. - circle.mMeta.mCircleId.clear() ; + // set distribution from GUI. + circle.mMeta.mCircleId.clear() ; circle.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; - if (ui.radioButton_Public->isChecked()) { + if (ui.radioButton_Public->isChecked()) { #ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::createCircle() Public Circle"; - std::cerr << std::endl; + std::cerr << "CreateCircleDialog::createCircle() Public Circle"; + std::cerr << std::endl; #endif - circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC; + circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC; - } else if (ui.radioButton_Self->isChecked()) { + } else if (ui.radioButton_Self->isChecked()) { #ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::createCircle() ExtSelfRef Circle"; - std::cerr << std::endl; + std::cerr << "CreateCircleDialog::createCircle() ExtSelfRef Circle"; + std::cerr << std::endl; #endif - circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_EXT_SELF; - } else if (ui.radioButton_Restricted->isChecked()) { + circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_EXT_SELF; + } else if (ui.radioButton_Restricted->isChecked()) { #ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::createCircle() External (Other) Circle"; - std::cerr << std::endl; + std::cerr << "CreateCircleDialog::createCircle() External (Other) Circle"; + std::cerr << std::endl; #endif - circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_EXTERNAL; + circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_EXTERNAL; - /* grab circle ID from chooser */ - RsGxsCircleId chosenId; - if (ui.circleComboBox->getChosenCircle(chosenId)) { + /* grab circle ID from chooser */ + RsGxsCircleId chosenId; + if (ui.circleComboBox->getChosenCircle(chosenId)) { #ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::createCircle() ChosenId: " << chosenId; - std::cerr << std::endl; + std::cerr << "CreateCircleDialog::createCircle() ChosenId: " << chosenId; + std::cerr << std::endl; #endif - circle.mMeta.mCircleId = chosenId; - } else {//if (ui.circleComboBox->getChosenCircle(chosenId)) + circle.mMeta.mCircleId = chosenId; + } else {//if (ui.circleComboBox->getChosenCircle(chosenId)) #ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::createCircle() Error no Id Chosen"; - std::cerr << std::endl; + std::cerr << "CreateCircleDialog::createCircle() Error no Id Chosen"; + std::cerr << std::endl; #endif - QMessageBox::warning(this, tr("RetroShare"),tr("No Restriction Circle Selected"), QMessageBox::Ok, QMessageBox::Ok); - return; - }//else (ui.circleComboBox->getChosenCircle(chosenId)) - } - else - { - QMessageBox::warning(this, tr("RetroShare"),tr("No Circle Limitations Selected"), QMessageBox::Ok, QMessageBox::Ok); - return; - } - } - else - { -#ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::createCircle() Personal Circle"; - std::cerr << std::endl; -#endif - - // set personal distribution - circle.mMeta.mCircleId.clear() ; - circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_LOCAL; - } - - uint32_t token; - - if(mIsExistingCircle) - { -#ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::updateCircle() : mCircleType: " << circle.mMeta.mCircleType << std::endl; - std::cerr << "CreateCircleDialog::updateCircle() : mCircleId: " << circle.mMeta.mCircleId << std::endl; - std::cerr << "CreateCircleDialog::updateCircle() : mGroupId: " << circle.mMeta.mGroupId << std::endl; - - std::cerr << "CreateCircleDialog::updateCircle() Checks and Balances Okay - calling service proper.."<< std::endl; -#endif - - rsGxsCircles->updateGroup(token, circle); + QMessageBox::warning(this, tr("RetroShare"),tr("No Restriction Circle Selected"), QMessageBox::Ok, QMessageBox::Ok); + return; + }//else (ui.circleComboBox->getChosenCircle(chosenId)) + } + else + { + QMessageBox::warning(this, tr("RetroShare"),tr("No Circle Limitations Selected"), QMessageBox::Ok, QMessageBox::Ok); + return; + } } else - { + { #ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::createCircle() : mCircleType: " << circle.mMeta.mCircleType << std::endl; - std::cerr << "CreateCircleDialog::createCircle() : mCircleId: " << circle.mMeta.mCircleId << std::endl; - - std::cerr << "CreateCircleDialog::createCircle() Checks and Balances Okay - calling service proper.."<< std::endl; + std::cerr << "CreateCircleDialog::createCircle() Personal Circle"; + std::cerr << std::endl; #endif - rsGxsCircles->createGroup(token, circle); + // set personal distribution + circle.mMeta.mCircleId.clear() ; + circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_LOCAL; } + bool is_existing_circle(mIsExistingCircle); + + RsThread::async([circle,is_existing_circle]() + { + RsGxsCircleId circleId; + + if(is_existing_circle) + { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::updateCircle() : mCircleType: " << circle.mMeta.mCircleType << std::endl; + std::cerr << "CreateCircleDialog::updateCircle() : mCircleId: " << circle.mMeta.mCircleId << std::endl; + std::cerr << "CreateCircleDialog::updateCircle() : mGroupId: " << circle.mMeta.mGroupId << std::endl; + + std::cerr << "CreateCircleDialog::updateCircle() Checks and Balances Okay - calling service proper.."<< std::endl; +#endif + rsGxsCircles->editCircle(*const_cast(&circle)); // const_cast: Not nice, but simpler. + + circleId = RsGxsCircleId(circle.mMeta.mGroupId); + } + else + { +#ifdef DEBUG_CREATE_CIRCLE_DIALOG + std::cerr << "CreateCircleDialog::createCircle() : mCircleType: " << circle.mMeta.mCircleType << std::endl; + std::cerr << "CreateCircleDialog::createCircle() : mCircleId: " << circle.mMeta.mCircleId << std::endl; + + std::cerr << "CreateCircleDialog::createCircle() Checks and Balances Okay - calling service proper.."<< std::endl; +#endif + rsGxsCircles->createCircle(circle.mMeta.mGroupName, + static_cast(circle.mMeta.mCircleType), + circleId, + circle.mMeta.mCircleId, + circle.mMeta.mAuthorId, + circle.mInvitedMembers, + circle.mLocalFriends); + } + + if(!is_existing_circle) + RsQThreadUtils::postToObject( [circle,circleId]() + { + QMessageBox::information(nullptr,tr("Circle created"), + tr("Your new circle has been created:\n Name: %1\n Id: %2.") + .arg(QString::fromUtf8(circle.mMeta.mGroupName.c_str())) + .arg(QString::fromStdString(circleId.toStdString()))); + }); + }); + close(); } @@ -810,11 +832,6 @@ void CreateCircleDialog::loadIdentities() void CreateCircleDialog::fillIdentitiesList(const std::vector& id_groups) { -#ifdef DEBUG_CREATE_CIRCLE_DIALOG - std::cerr << "CreateCircleDialog::loadIdentities(" << token << ")"; - std::cerr << std::endl; -#endif - QTreeWidget *tree = ui.treeWidget_IdList; tree->clear(); @@ -830,7 +847,6 @@ void CreateCircleDialog::fillIdentitiesList(const std::vector& id_ bool isSignedByFriendNode = isSigned && rsPeers->isPgpFriend(idGroup.mPgpId); /* do filtering */ - bool ok = false; if(!(acceptAll ||(acceptOnlySignedIdentities && isSigned) ||(acceptOnlyIdentitiesSignedByFriend && isSignedByFriendNode))) { @@ -938,3 +954,8 @@ void CreateCircleDialog::MembershipListCustomPopupMenu( QPoint ) contextMnu.exec(QCursor::pos()); } +void CreateCircleDialog::updateMembership() +{ + ui.members_groupBox->setTitle( tr("Invited Members") + " (" + QString::number(ui.treeWidget_membership->topLevelItemCount()) + ")" ); +} + diff --git a/retroshare-gui/src/gui/Circles/CreateCircleDialog.h b/retroshare-gui/src/gui/Circles/CreateCircleDialog.h index fbbaacb2c..5e713b9c3 100644 --- a/retroshare-gui/src/gui/Circles/CreateCircleDialog.h +++ b/retroshare-gui/src/gui/Circles/CreateCircleDialog.h @@ -56,6 +56,7 @@ private slots: void filterChanged(const QString &text); void createNewGxsId(); void idTypeChanged(); + void updateMembership(); /** Create the context popup menu and it's submenus */ void IdListCustomPopupMenu( QPoint point ); diff --git a/retroshare-gui/src/gui/Circles/CreateCircleDialog.ui b/retroshare-gui/src/gui/Circles/CreateCircleDialog.ui index 54e1fe80f..62390e56a 100644 --- a/retroshare-gui/src/gui/Circles/CreateCircleDialog.ui +++ b/retroshare-gui/src/gui/Circles/CreateCircleDialog.ui @@ -13,7 +13,7 @@ - + 0 @@ -40,226 +40,225 @@ - + QFrame::StyledPanel QFrame::Raised - + Circle Details - + + + 11 + - - - - - - 75 - true - - - - Qt::LeftToRight - - - Name: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> - - - - - - - - 75 - true - - - - Contact author: - - - - - - - - 0 - 0 - - - - <html><head/><body><p>The creator of a circle is purely optional. It is however useful for public circles so that people know with whom to discuss membership aspects.</p></body></html> - - - - - - - [Circle Admin] - - - - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 40 - 20 - - - - - - - - - 75 - true - - - - Distribution: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 2 + + + + 75 + true + + + + Qt::LeftToRight + + + Name: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> + + + + + + + + 75 + true + + + + Contact author: + + + + + + + + 0 + 0 + + + + <html><head/><body><p>The creator of a circle is purely optional. It is however useful for public circles so that people know with whom to discuss membership aspects.</p></body></html> + + + + + + + [Circle Admin] + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 40 + 20 + + + + + + + + + 75 + true + + + + Distribution: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 2 + + + 2 + + + 2 + + + + + <html><head/><body><p>Publicly distributed circles are visible to your friends, which will get to know the circle data (Creator, members, etc)</p></body></html> - - 2 + + Public - - 2 + + + :/icons/png/network-puplic.png:/icons/png/network-puplic.png - - 2 + + + 24 + 24 + - - - - <html><head/><body><p>Publicly distributed circles are visible to your friends, which will get to know the circle data (Creator, members, etc)</p></body></html> - - - Public - - - - :/icons/png/network-puplic.png:/icons/png/network-puplic.png - - - - 24 - 24 - - - - - - - - <html><head/><body><p>Private (a.k.a. self-restricted) circles are only visible to the invited members of these circles. In practice the circle uses its own list of invited members to limit its own distribution. </p></body></html> - - - Private - - - - :/icons/png/person.png:/icons/png/person.png - - - - 24 - 24 - - - - - - - - <html><head/><body><p>Circles can be restricted to the members of another circle. Only the members of that second circle will be allowed to see the new circle and its content (list of members, etc).</p></body></html> - - - Only &visible to members of: - - - - :/icons/png/circles.png:/icons/png/circles.png - - - - 24 - 24 - - - - - - - - - - - Qt::Horizontal - - - - 147 - 20 - - - - - - - - + + + + + + <html><head/><body><p>Private (a.k.a. self-restricted) circles are only visible to the invited members of these circles. In practice the circle uses its own list of invited members to limit its own distribution. </p></body></html> + + + Private + + + + :/icons/png/person.png:/icons/png/person.png + + + + 24 + 24 + + + + + + + + <html><head/><body><p>Circles can be restricted to the members of another circle. Only the members of that second circle will be allowed to see the new circle and its content (list of members, etc).</p></body></html> + + + Only &visible to members of: + + + + :/icons/png/circles.png:/icons/png/circles.png + + + + 24 + 24 + + + + + + + + + + + Qt::Horizontal + + + + 147 + 20 + + + + + + - + Invited Members - + @@ -287,9 +286,9 @@ - + - + Qt::Vertical @@ -330,7 +329,7 @@ - + Qt::Vertical @@ -378,7 +377,7 @@ QFrame::Raised - + 0 @@ -419,9 +418,9 @@ - + - + Filter @@ -438,7 +437,7 @@ - + Qt::Horizontal @@ -451,7 +450,14 @@ - + + + + 12 + 75 + true + + Create @@ -503,7 +509,6 @@ - diff --git a/retroshare-gui/src/gui/FileTransfer/DLListDelegate.cpp b/retroshare-gui/src/gui/FileTransfer/DLListDelegate.cpp old mode 100644 new mode 100755 index 4385af476..319c284d5 --- a/retroshare-gui/src/gui/FileTransfer/DLListDelegate.cpp +++ b/retroshare-gui/src/gui/FileTransfer/DLListDelegate.cpp @@ -32,6 +32,8 @@ Q_DECLARE_METATYPE(FileProgressInfo) +#define MAX_CHAR_TMP 128 + DLListDelegate::DLListDelegate(QObject *parent) : QAbstractItemDelegate(parent) { } @@ -100,7 +102,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti multi *= 1024.0; } } - painter->drawText(option.rect, Qt::AlignRight, temp); + painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); break; case COLUMN_REMAINING: remaining = index.data().toLongLong(); @@ -119,7 +121,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti multi *= 1024.0; } } - painter->drawText(option.rect, Qt::AlignRight, temp); + painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); break; case COLUMN_COMPLETED: completed = index.data().toLongLong(); @@ -138,7 +140,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti multi *= 1024.0; } } - painter->drawText(option.rect, Qt::AlignRight, temp); + painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); break; case COLUMN_DLSPEED: dlspeed = index.data().toDouble(); @@ -149,7 +151,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti temp.sprintf("%.2f", dlspeed/1024.); temp += " KB/s"; } - painter->drawText(option.rect, Qt::AlignRight, temp); + painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); break; case COLUMN_PROGRESS: { @@ -180,7 +182,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti } painter->drawText(option.rect, Qt::AlignCenter, newopt.text); break; - case COLUMN_SOURCES: + case COLUMN_SOURCES: { double dblValue = index.data().toDouble(); @@ -188,7 +190,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti painter->drawText(option.rect, Qt::AlignCenter, temp); } break; - case COLUMN_PRIORITY: + case COLUMN_PRIORITY: { double dblValue = index.data().toDouble(); if (dblValue == PRIORITY_NULL) @@ -205,7 +207,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti painter->drawText(option.rect, Qt::AlignCenter, temp); } break; - case COLUMN_DOWNLOADTIME: + case COLUMN_DOWNLOADTIME: downloadtime = index.data().toLongLong(); minutes = downloadtime / 60; seconds = downloadtime % 60; @@ -225,7 +227,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti temp = "" ; painter->drawText(option.rect, Qt::AlignCenter, temp); break; - case COLUMN_NAME: + case COLUMN_NAME: { // decoration int pixOffset = 0; @@ -234,7 +236,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti pixmap = qvariant_cast(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off); pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize)); if (pixmapRect.isValid()){ - QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft(); + QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft | Qt::AlignVCenter, pixmap.size(), option.rect).topLeft(); p.setX( p.x() + pixOffset); painter->drawPixmap(p, pixmap); temp = " " + temp; @@ -245,13 +247,13 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti pixmap = qvariant_cast(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off); pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize)); if (pixmapRect.isValid()){ - QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft(); + QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft | Qt::AlignVCenter, pixmap.size(), option.rect).topLeft(); p.setX( p.x() + pixOffset); painter->drawPixmap(p, pixmap); temp = " " + temp; pixOffset += pixmap.size().width(); } - painter->drawText(option.rect.translated(pixOffset, 0), Qt::AlignLeft, temp); + painter->drawText(option.rect.translated(pixOffset, 0), Qt::AlignLeft | Qt::AlignVCenter, temp); } break; case COLUMN_LASTDL: @@ -277,7 +279,7 @@ QSize DLListDelegate::sizeHint(const QStyleOptionViewItem & option, const QModel { float w = QFontMetricsF(option.font).width(index.data(Qt::DisplayRole).toString()); - int S = QFontMetricsF(option.font).height() ; + int S = QFontMetricsF(option.font).height()*1.5 ; return QSize(w,S); } diff --git a/retroshare-gui/src/gui/FileTransfer/DLListDelegate.h b/retroshare-gui/src/gui/FileTransfer/DLListDelegate.h index 3b67934fe..19b9306a5 100644 --- a/retroshare-gui/src/gui/FileTransfer/DLListDelegate.h +++ b/retroshare-gui/src/gui/FileTransfer/DLListDelegate.h @@ -18,55 +18,40 @@ * * *******************************************************************************/ -#ifndef DLLISTDELEGATE_H -#define DLLISTDELEGATE_H +#pragma once #include #include "xprogressbar.h" - -// Defines for download list list columns -#define COLUMN_NAME 0 -#define COLUMN_SIZE 1 -#define COLUMN_COMPLETED 2 -#define COLUMN_DLSPEED 3 -#define COLUMN_PROGRESS 4 -#define COLUMN_SOURCES 5 -#define COLUMN_STATUS 6 -#define COLUMN_PRIORITY 7 -#define COLUMN_REMAINING 8 -#define COLUMN_DOWNLOADTIME 9 -#define COLUMN_ID 10 -#define COLUMN_LASTDL 11 -#define COLUMN_PATH 12 -#define COLUMN_COUNT 13 - -#define PRIORITY_NULL 0.0 -#define PRIORITY_FASTER 0.1 -#define PRIORITY_AVERAGE 0.2 -#define PRIORITY_SLOWER 0.3 - -#define MAX_CHAR_TMP 128 - class QModelIndex; class QPainter; +class DLListDelegate: public QAbstractItemDelegate +{ +public: + DLListDelegate(QObject *parent=0); + virtual ~DLListDelegate(){} + void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; + QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const; -class DLListDelegate: public QAbstractItemDelegate { + static constexpr int COLUMN_NAME = 0; + static constexpr int COLUMN_SIZE = 1; + static constexpr int COLUMN_COMPLETED = 2; + static constexpr int COLUMN_DLSPEED = 3; + static constexpr int COLUMN_PROGRESS = 4; + static constexpr int COLUMN_SOURCES = 5; + static constexpr int COLUMN_STATUS = 6; + static constexpr int COLUMN_PRIORITY = 7; + static constexpr int COLUMN_REMAINING = 8; + static constexpr int COLUMN_DOWNLOADTIME= 9; + static constexpr int COLUMN_ID = 10; + static constexpr int COLUMN_LASTDL = 11; + static constexpr int COLUMN_PATH = 12; + static constexpr int COLUMN_COUNT = 13; - Q_OBJECT - - public: - DLListDelegate(QObject *parent=0); - virtual ~DLListDelegate(){} - void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; - QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const; - - private: - - public slots: - - signals: + static constexpr float PRIORITY_NULL = 0.0; + static constexpr float PRIORITY_FASTER = 0.1; + static constexpr float PRIORITY_AVERAGE = 0.2; + static constexpr float PRIORITY_SLOWER = 0.3; }; -#endif diff --git a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp index 9c3703032..0af441dd5 100644 --- a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp @@ -30,13 +30,15 @@ #include "gui/RetroShareLink.h" #include "retroshare-gui/RsAutoUpdatePage.h" #include "gui/msgs/MessageComposer.h" -#include "gui/common/RsCollection.h" +#include "gui/common/RsCollectionDialog.h" #include "gui/common/FilesDefs.h" #include "gui/common/RsUrlHandler.h" #include "gui/settings/rsharesettings.h" #include "gui/advsearch/advancedsearchdialog.h" #include "gui/common/RSTreeWidgetItem.h" #include "util/QtVersion.h" +#include "util/qtthreadsutils.h" +#include "util/misc.h" #include #include @@ -85,6 +87,18 @@ const int SearchDialog::FILETYPE_IDX_DIRECTORY = 8; QMap * SearchDialog::FileTypeExtensionMap = new QMap(); bool SearchDialog::initialised = false; +struct SearchDialog::FileDetail +{ +public: + RsPeerId id; + std::string name; + RsFileHash hash; + std::string path; + uint64_t size; + uint32_t mtime; + uint32_t rank; +}; + /** Constructor */ SearchDialog::SearchDialog(QWidget *parent) : MainPage(parent), @@ -121,10 +135,10 @@ SearchDialog::SearchDialog(QWidget *parent) connect( ui.searchSummaryWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( searchSummaryWidgetCustomPopupMenu( QPoint ) ) ); connect( ui.showBannedFiles_TB, SIGNAL( clicked() ), this, SLOT( openBannedFiles() ) ); - connect( ui.lineEdit, SIGNAL( returnPressed ( void ) ), this, SLOT( searchKeywords( void ) ) ); + connect( ui.lineEdit, SIGNAL( returnPressed () ), this, SLOT( searchKeywords() ) ); connect( ui.lineEdit, SIGNAL( textChanged ( const QString& ) ), this, SLOT( checkText( const QString& ) ) ); - connect( ui.pushButtonSearch, SIGNAL( released ( void ) ), this, SLOT( searchKeywords( void ) ) ); - connect( ui.pushButtonDownload, SIGNAL( released ( void ) ), this, SLOT( download( void ) ) ); + connect( ui.searchButton, SIGNAL( released () ), this, SLOT( searchKeywords() ) ); + connect( ui.pushButtonDownload, SIGNAL( released () ), this, SLOT( download() ) ); connect( ui.cloaseallsearchresultsButton, SIGNAL(clicked()), this, SLOT(searchRemoveAll())); connect( ui.searchResultWidget, SIGNAL( itemDoubleClicked ( QTreeWidgetItem *, int)), this, SLOT(download())); @@ -186,11 +200,6 @@ SearchDialog::SearchDialog(QWidget *parent) _smheader->resizeSection ( SR_AGE_COL, 90*f ); _smheader->resizeSection ( SR_HASH_COL, 240*f ); - // set header text aligment - QTreeWidgetItem * headerItem = ui.searchResultWidget->headerItem(); - headerItem->setTextAlignment(SR_NAME_COL, Qt::AlignRight | Qt::AlignRight); - headerItem->setTextAlignment(SR_SIZE_COL, Qt::AlignRight | Qt::AlignRight); - ui.searchResultWidget->sortItems(SR_NAME_COL, Qt::AscendingOrder); /* Set initial size the splitter */ @@ -218,6 +227,17 @@ SearchDialog::SearchDialog(QWidget *parent) checkText(ui.lineEdit->text()); + // add an event handler to get search results (previously available through notifyQt) + + mEventHandlerId = 0; + + rsEvents->registerEventsHandler( [this](std::shared_ptr event) + { + RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); + }, mEventHandlerId, RsEventType::FILE_TRANSFER ); + + mFontSizeHandler.registerFontSize(ui.searchSummaryWidget); + mFontSizeHandler.registerFontSize(ui.searchResultWidget, 1.4f); } SearchDialog::~SearchDialog() @@ -236,6 +256,31 @@ SearchDialog::~SearchDialog() ui.searchResultWidget->setItemDelegateForColumn(SR_SIZE_COL, nullptr); ui.searchResultWidget->setItemDelegateForColumn(SR_AGE_COL, nullptr); + + rsEvents->unregisterEventsHandler(mEventHandlerId); +} + +void SearchDialog::handleEvent_main_thread(std::shared_ptr event) +{ + if(event->mType != RsEventType::FILE_TRANSFER) + return; + + auto fe = dynamic_cast(event.get()); + + if(!fe || fe->mFileTransferEventCode!=RsFileTransferEventCode::NEW_DISTANT_SEARCH_RESULTS) + return; + + for(uint32_t i=0;imResults.size();++i) + { + FileDetail f; + f.hash = fe->mResults[i].fHash; + f.name = fe->mResults[i].fName; + f.size = fe->mResults[i].fSize; + f.mtime = 0; // zero what's not available, otherwise we'll get some random values displayed. + f.rank = 0; + + updateFiles(fe->mRequestId,f); + } } void SearchDialog::processSettings(bool bLoad) @@ -276,31 +321,10 @@ void SearchDialog::processSettings(bool bLoad) void SearchDialog::checkText(const QString& txt) { - bool valid; - QColor color; - - if(txt.length() < 3) - { - std::cout << "setting palette 1" << std::endl ; - valid = false; - color = QApplication::palette().color(QPalette::Disabled, QPalette::Base); - } - else - { - std::cout << "setting palette 2" << std::endl ; - valid = true; - color = QApplication::palette().color(QPalette::Active, QPalette::Base); - } - - /* unpolish widget to clear the stylesheet's palette cache */ + ui.searchButton->setDisabled(txt.length() < 3); + ui.searchLineFrame->setProperty("valid", (txt.length() >= 3)); ui.searchLineFrame->style()->unpolish(ui.searchLineFrame); - - QPalette palette = ui.lineEdit->palette(); - palette.setColor(ui.lineEdit->backgroundRole(), color); - ui.lineEdit->setPalette(palette); - - ui.searchLineFrame->setProperty("valid", valid); - Rshare::refreshStyleSheet(ui.searchLineFrame, false); + RsApplication::refreshStyleSheet(ui.searchLineFrame, false); } void SearchDialog::initialiseFileTypeMappings() @@ -308,7 +332,7 @@ void SearchDialog::initialiseFileTypeMappings() /* edit these strings to change the range of extensions recognised by the search */ SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_ANY, ""); SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_AUDIO, - "aac aif flac iff m3u m4a mid midi mp3 mpa ogg ra ram wav wma"); + "aac aif flac iff m3u m4a mid midi mp3 mpa ogg ra ram wav wma weba"); SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_ARCHIVE, "7z bz2 gz pkg rar sea sit sitx tar zip tgz"); SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_CDIMAGE, @@ -317,11 +341,11 @@ void SearchDialog::initialiseFileTypeMappings() "doc odt ott rtf pdf ps txt log msg wpd wps ods xls epub" ); SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_PICTURE, "3dm 3dmf ai bmp drw dxf eps gif ico indd jpe jpeg jpg mng pcx pcc pct pgm " - "pix png psd psp qxd qxprgb sgi svg tga tif tiff xbm xcf"); + "pix png psd psp qxd qxprgb sgi svg tga tif tiff xbm xcf webp"); SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_PROGRAM, "app bat cgi com bin exe js pif py pl sh vb ws bash"); SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_VIDEO, - "3gp asf asx avi mov mp4 mkv flv mpeg mpg qt rm swf vob wmv"); + "3gp asf asx avi mov mp4 mkv flv mpeg mpg qt rm swf vob wmv webm"); SearchDialog::initialised = true; } @@ -393,11 +417,10 @@ void SearchDialog::download() /* should also be able to handle multi-selection */ QList itemsForDownload = ui.searchResultWidget->selectedItems() ; int numdls = itemsForDownload.size() ; - QTreeWidgetItem * item ; bool attemptDownloadLocal = false ; for (int i = 0; i < numdls; ++i) { - item = itemsForDownload.at(i) ; + QTreeWidgetItem *item = itemsForDownload.at(i) ; // call the download // * if (item->text(SR_HASH_COL).isEmpty()) { // we have a folder @@ -421,8 +444,8 @@ void SearchDialog::download() std::cout << *it << "-" << std::endl; QColor foreground = textColorDownloading(); - for (int i = 0; i < item->columnCount(); ++i) - item->setData(i, Qt::ForegroundRole, foreground ); + for (int j = 0; j < item->columnCount(); ++j) + item->setData(j, Qt::ForegroundRole, foreground ); } } } @@ -473,25 +496,23 @@ void SearchDialog::collCreate() int selectedCount = selectedItems.size() ; QTreeWidgetItem * item ; - for (int i = 0; i < selectedCount; ++i) { + RsFileTree tree; + + for (int i = 0; i < selectedCount; ++i) + { item = selectedItems.at(i) ; - if (!item->text(SR_HASH_COL).isEmpty()) { + if (!item->text(SR_HASH_COL).isEmpty()) + { std::string name = item->text(SR_NAME_COL).toUtf8().constData(); RsFileHash hash( item->text(SR_HASH_COL).toStdString() ); uint64_t count = item->text(SR_SIZE_COL).toULongLong(); - DirDetails details; - details.name = name; - details.hash = hash; - details.size = count; - details.type = DIR_TYPE_FILE; - - dirVec.push_back(details); + tree.addFile(tree.root(),name,hash,count); } } - RsCollection(dirVec,RS_FILE_HINTS_LOCAL).openNewColl(this); + RsCollectionDialog::openNewCollection(tree); } void SearchDialog::collModif() @@ -518,12 +539,8 @@ void SearchDialog::collModif() /* open file with a suitable application */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - collection.openColl(qinfo.absoluteFilePath()); - }//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) - }//if (qinfo.exists()) + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath()); } void SearchDialog::collView() @@ -550,12 +567,8 @@ void SearchDialog::collView() /* open file with a suitable application */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - collection.openColl(qinfo.absoluteFilePath(), true); - }//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) - }//if (qinfo.exists()) + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(), true); } void SearchDialog::collOpen() @@ -573,32 +586,35 @@ void SearchDialog::collOpen() if (rsFiles->FileDetails(hash, RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_NETWORK_WIDE - | RS_FILE_HINTS_SPEC_ONLY, info)) { - + | RS_FILE_HINTS_SPEC_ONLY, info)) + { /* make path for downloaded files */ std::string path; path = info.path; /* open file with a suitable application */ QFileInfo qinfo; + RsCollection::RsCollectionErrorCode err; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - if (collection.load(qinfo.absoluteFilePath())) { - collection.downloadFiles(); - return; - } - } - } + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::downloadFiles(RsCollection(qinfo.absoluteFilePath(),err)); } } } - RsCollection collection; - if (collection.load(this)) { - collection.downloadFiles(); - }//if (collection.load(this)) + QString fileName; + if (!misc::getOpenFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName)) + return ; + + std::cerr << "Got file name: " << fileName.toStdString() << std::endl; + + RsCollection::RsCollectionErrorCode err; + RsCollection collection(fileName, err); + + if(err == RsCollection::RsCollectionErrorCode::COLLECTION_NO_ERROR) + RsCollectionDialog::downloadFiles(collection); + else + QMessageBox::information(nullptr,tr("Error open RsCollection file"),RsCollection::errorString(err)); } void SearchDialog::downloadDirectory(const QTreeWidgetItem *item, const QString &base) @@ -828,28 +844,29 @@ void SearchDialog::advancedSearch(RsRegularExpression::Expression* expression) { advSearchDialog->hide(); - /* call to core */ - std::list results; - // send a turtle search request RsRegularExpression::LinearizedExpression e ; expression->linearize(e) ; - TurtleRequestId req_id = rsFiles->turtleSearch(e) ; + TurtleRequestId req_id ; - // This will act before turtle results come to the interface, thanks to the signals scheduling policy. - initSearchResult(QString::fromStdString(e.GetStrings()),req_id, ui.FileTypeComboBox->currentIndex(), true) ; + if(ui._anonF2Fsearch_CB->isChecked()) + req_id = rsFiles->turtleSearch(e) ; + else + req_id = RSRandom::random_u32() ; // generate a random 32 bits request id - rsFiles -> SearchBoolExp(expression, results, RS_FILE_HINTS_REMOTE);// | DIR_FLAGS_NETWORK_WIDE | DIR_FLAGS_BROWSABLE); + initSearchResult(QString::fromStdString(e.GetStrings()),req_id, ui.FileTypeComboBox->currentIndex(), true) ; + + std::list results; + + FileSearchFlags flags(0); + if(ui._ownFiles_CB->isChecked()) flags |= RS_FILE_HINTS_LOCAL; + if(ui._friendListsearch_SB->isChecked()) flags |= RS_FILE_HINTS_REMOTE; + + rsFiles -> SearchBoolExp(expression, results, flags); /* abstraction to allow reusee of tree rendering code */ - resultsToTree(advSearchDialog->getSearchAsString(),req_id, results); - -// // debug stuff -// Expression *expression2 = LinearizedExpression::toExpr(e) ; -// results.clear() ; -// rsFiles -> SearchBoolExp(expression2, results, DIR_FLAGS_REMOTE | DIR_FLAGS_NETWORK_WIDE | DIR_FLAGS_BROWSABLE); -// resultsToTree((advSearchDialog->getSearchAsString()).toStdString(),req_id+1, results); + resultsToTree(advSearchDialog->getSearchAsString(),req_id, results); } void SearchDialog::searchKeywords() @@ -881,7 +898,7 @@ void SearchDialog::searchKeywords(const QString& keywords) if (keywords.length() < 3) return ; - QStringList qWords = keywords.split(" ", QString::SkipEmptyParts); + QStringList qWords = keywords.split(" ", QtSkipEmptyParts); std::list words; QStringListIterator qWordsIter(qWords); while (qWordsIter.hasNext()) @@ -955,7 +972,7 @@ void SearchDialog::searchKeywords(const QString& keywords) } } -void SearchDialog::updateFiles(qulonglong search_id,FileDetail file) +void SearchDialog::updateFiles(qulonglong search_id,const FileDetail& file) { searchResultsQueue.push_back(std::pair(search_id,file)) ; @@ -983,7 +1000,7 @@ void SearchDialog::processResultQueue() while(!searchResultsQueue.empty() && nb_treated_elements++ < 250) { qulonglong search_id = searchResultsQueue.back().first ; - FileDetail& file = searchResultsQueue.back().second ; + const FileDetail& file = searchResultsQueue.back().second ; #ifdef DEBUG std::cout << "Updating file detail:" << std::endl ; @@ -1023,7 +1040,7 @@ void SearchDialog::insertDirectory(const QString &txt, qulonglong searchId, cons child->setText(SR_SOURCES_COL, QString::number(1)); child->setData(SR_SOURCES_COL, ROLE_SORT, 1); - child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight ); + child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight | Qt::AlignVCenter ); child->setText(SR_SEARCH_ID_COL, sid_hexa); setIconAndType(child, QString::fromUtf8(dir.name.c_str())); @@ -1048,7 +1065,7 @@ void SearchDialog::insertDirectory(const QString &txt, qulonglong searchId, cons child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); child->setText(SR_SOURCES_COL, QString::number(1)); child->setData(SR_SOURCES_COL, ROLE_SORT, 1); - child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight ); + child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight | Qt::AlignVCenter ); child->setText(SR_SEARCH_ID_COL, sid_hexa); child->setText(SR_TYPE_COL, tr("Folder")); @@ -1117,7 +1134,7 @@ void SearchDialog::insertDirectory(const QString &txt, qulonglong searchId, cons child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); child->setText(SR_SOURCES_COL, QString::number(1)); child->setData(SR_SOURCES_COL, ROLE_SORT, 1); - child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight ); + child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight | Qt::AlignVCenter ); child->setText(SR_SEARCH_ID_COL, sid_hexa); child->setText(SR_TYPE_COL, tr("Folder")); @@ -1209,18 +1226,17 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s // bool found = false ; bool altname = false ; - int sources; - int friendSource = 0; - int anonymousSource = 0; QString modifiedResult; - QList itms = ui.searchResultWidget->findItems(QString::fromStdString(file.hash.toStdString()),Qt::MatchExactly,SR_HASH_COL) ; + QList itms = ui.searchResultWidget->findItems(QString::fromStdString(file.hash.toStdString()),Qt::MatchExactly,SR_HASH_COL) ; - for(QList::const_iterator it(itms.begin());it!=itms.end();++it) - if((*it)->text(SR_SEARCH_ID_COL) == sid_hexa) + for(auto &it : itms) + if(it->text(SR_SEARCH_ID_COL) == sid_hexa) { - QString resultCount = (*it)->text(SR_SOURCES_COL); - QStringList modifiedResultCount = resultCount.split("/", QString::SkipEmptyParts); + int friendSource = 0; + int anonymousSource = 0; + QString resultCount = it->text(SR_SOURCES_COL); + QStringList modifiedResultCount = resultCount.split("/", QtSkipEmptyParts); if(searchType == FRIEND_SEARCH) { friendSource = modifiedResultCount.at(0).toInt() + 1; @@ -1233,13 +1249,13 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s } modifiedResult = QString::number(friendSource) + "/" + QString::number(anonymousSource); float fltRes = friendSource + (float)anonymousSource/1000; - (*it)->setText(SR_SOURCES_COL,modifiedResult); - (*it)->setData(SR_SOURCES_COL, ROLE_SORT, fltRes); - QTreeWidgetItem *item = (*it); + it->setText(SR_SOURCES_COL,modifiedResult); + it->setData(SR_SOURCES_COL, ROLE_SORT, fltRes); + QTreeWidgetItem *item = it; found = true ; - if(QString::compare((*it)->text(SR_NAME_COL), QString::fromUtf8(file.name.c_str()), Qt::CaseSensitive)!=0) + if(QString::compare(it->text(SR_NAME_COL), QString::fromUtf8(file.name.c_str()), Qt::CaseSensitive)!=0) altname = true; if (!item->data(SR_DATA_COL, SR_ROLE_LOCAL).toBool()) { @@ -1280,19 +1296,18 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s } } - if(altname) - { - QTreeWidgetItem *item = new RSTreeWidgetItem(compareResultRole); - item->setText(SR_NAME_COL, QString::fromUtf8(file.name.c_str())); - item->setText(SR_HASH_COL, QString::fromStdString(file.hash.toStdString())); - setIconAndType(item, QString::fromUtf8(file.name.c_str())); - item->setText(SR_SIZE_COL, QString::number(file.size)); - setIconAndType(item, QString::fromUtf8(file.name.c_str())); - (*it)->addChild(item); + if(altname) + { + QTreeWidgetItem *altItem = new RSTreeWidgetItem(compareResultRole); + altItem->setText(SR_NAME_COL, QString::fromUtf8(file.name.c_str())); + altItem->setText(SR_HASH_COL, QString::fromStdString(file.hash.toStdString())); + setIconAndType(altItem, QString::fromUtf8(file.name.c_str())); + altItem->setText(SR_SIZE_COL, QString::number(file.size)); + setIconAndType(altItem, QString::fromUtf8(file.name.c_str())); + it->addChild(altItem); + } } - } - if(!found) { ++nb_results[searchId] ; @@ -1301,7 +1316,7 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s QTreeWidgetItem *item = new RSTreeWidgetItem(compareResultRole); item->setText(SR_NAME_COL, QString::fromUtf8(file.name.c_str())); - item->setText(SR_HASH_COL, QString::fromStdString(file.hash.toStdString())); + item->setText(SR_HASH_COL, QString::fromStdString(file.hash.toStdString())); setIconAndType(item, QString::fromUtf8(file.name.c_str())); @@ -1311,9 +1326,13 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s item->setText(SR_SIZE_COL, QString::number(file.size)); item->setData(SR_SIZE_COL, ROLE_SORT, (qulonglong) file.size); - item->setText(SR_AGE_COL, QString::number(file.age)); - item->setData(SR_AGE_COL, ROLE_SORT, file.age); + item->setText(SR_AGE_COL, QString::number(file.mtime)); + item->setData(SR_AGE_COL, ROLE_SORT, file.mtime); item->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); + item->setTextAlignment( SR_AGE_COL, Qt::AlignCenter ); + + int friendSource = 0; + int anonymousSource = 0; if(searchType == FRIEND_SEARCH) { friendSource = 1; @@ -1330,7 +1349,7 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s item->setText(SR_SOURCES_COL,modifiedResult); item->setToolTip(SR_SOURCES_COL, tr("Obtained via ")+QString::fromStdString(rsPeers->getPeerName(file.id)) ); item->setData(SR_SOURCES_COL, ROLE_SORT, fltRes); - item->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight ); + item->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight | Qt::AlignVCenter ); item->setText(SR_SEARCH_ID_COL, sid_hexa); QColor foreground; @@ -1344,7 +1363,7 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s } else { item->setData(SR_DATA_COL, SR_ROLE_LOCAL, false); - sources = item->text(SR_SOURCES_COL).toInt(); + int sources = item->text(SR_SOURCES_COL).toInt(); if (sources == 1) { foreground = ui.searchResultWidget->palette().color(QPalette::Text); @@ -1369,11 +1388,8 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s /* hide/show this search result */ hideOrShowSearchResult(item); - } - /* update the summary as well */ - if(!found) // only increment result when it's a new item. - { + // only increment result when it's a new item. int s = ui.searchSummaryWidget->topLevelItem(summaryItemIndex)->text(SS_RESULTS_COL).toInt() ; ui.searchSummaryWidget->topLevelItem(summaryItemIndex)->setText(SS_RESULTS_COL, QString::number(s+1)); ui.searchSummaryWidget->topLevelItem(summaryItemIndex)->setData(SS_RESULTS_COL, ROLE_SORT, s+1); @@ -1388,21 +1404,21 @@ void SearchDialog::resultsToTree(const QString& txt,qulonglong searchId, const s std::list::const_iterator it; for(it = results.begin(); it != results.end(); ++it) - if (it->type == DIR_TYPE_FILE) { + if (it->type == DIR_TYPE_FILE) + { FileDetail fd; fd.id = it->id; fd.name = it->name; fd.hash = it->hash; fd.path = it->path; fd.size = it->size; - fd.age = it->mtime; + fd.mtime= it->mtime; fd.rank = 0; insertFile(searchId,fd, FRIEND_SEARCH); - } else if (it->type == DIR_TYPE_DIR) { -// insertDirectory(txt, searchId, *it, NULL); + } + else if (it->type == DIR_TYPE_DIR) insertDirectory(txt, searchId, *it); - } ui.searchResultWidget->setSortingEnabled(true); } @@ -1481,33 +1497,38 @@ void SearchDialog::copyResultLink() { /* should also be able to handle multi-selection */ QList itemsForCopy = ui.searchResultWidget->selectedItems(); - int numdls = itemsForCopy.size(); - QTreeWidgetItem * item; - QList urls ; + std::set already_seen_hashes; + QList urls ; - for (int i = 0; i < numdls; ++i) - { - item = itemsForCopy.at(i); - // call copy + for (auto item:itemsForCopy) + { + // call copy - if (!item->childCount()) - { - std::cerr << "SearchDialog::copyResultLink() Calling set retroshare link"; - std::cerr << std::endl; + QString fhash = item->text(SR_HASH_COL); + RsFileHash hash(fhash.toStdString()); - QString fhash = item->text(SR_HASH_COL); - qulonglong fsize = item->text(SR_SIZE_COL).toULongLong(); - QString fname = item->text(SR_NAME_COL); + if(!hash.isNull() && (already_seen_hashes.end() == already_seen_hashes.find(hash))) + { + std::cerr << "SearchDialog::copyResultLink() Calling set retroshare link"; + std::cerr << std::endl; - RetroShareLink link = RetroShareLink::createFile(fname, fsize, fhash); - if (link.valid()) { - std::cerr << "new link added to clipboard: " << link.toString().toStdString() << std::endl ; - urls.push_back(link) ; - } - } - } - RSLinkClipboard::copyLinks(urls) ; + qulonglong fsize = item->text(SR_SIZE_COL).toULongLong(); + QString fname = item->text(SR_NAME_COL); + + RetroShareLink link = RetroShareLink::createFile(fname, fsize, fhash); + + if (link.valid()) + { + std::cerr << "new link added to clipboard: " << link.toString().toStdString() << std::endl ; + urls.push_back(link); + already_seen_hashes.insert(hash); + } + } + } + + if(!urls.empty()) + RSLinkClipboard::copyLinks(urls) ; } void SearchDialog::sendLinkTo( ) diff --git a/retroshare-gui/src/gui/FileTransfer/SearchDialog.h b/retroshare-gui/src/gui/FileTransfer/SearchDialog.h index 83eb3b1b2..0af53662b 100644 --- a/retroshare-gui/src/gui/FileTransfer/SearchDialog.h +++ b/retroshare-gui/src/gui/FileTransfer/SearchDialog.h @@ -21,9 +21,11 @@ #ifndef _SEARCHDIALOG_H #define _SEARCHDIALOG_H -#include +#include "retroshare/rstypes.h" +#include "retroshare/rsevents.h" #include "ui_SearchDialog.h" -#include +#include "retroshare-gui/mainpage.h" +#include "util/FontSizeHandler.h" class AdvancedSearchDialog; class RSTreeWidgetItemCompareRole; @@ -42,6 +44,7 @@ class SearchDialog : public MainPage Q_PROPERTY(QColor textColorLowSources READ textColorLowSources WRITE setTextColorLowSources) Q_PROPERTY(QColor textColorHighSources READ textColorHighSources WRITE setTextColorHighSources) + struct FileDetail; // useful structure to store search results. public: /** Default Constructor */ SearchDialog(QWidget *parent = 0); @@ -62,8 +65,7 @@ public: void setTextColorLowSources(QColor color) { mTextColorLowSources = color; } void setTextColorHighSources(QColor color) { mTextColorHighSources = color; } -public slots: - void updateFiles(qulonglong request_id,FileDetail file) ; + void updateFiles(qulonglong request_id, const FileDetail& file) ; private slots: @@ -125,6 +127,7 @@ private: void setIconAndType(QTreeWidgetItem *item, const QString& filename); void downloadDirectory(const QTreeWidgetItem *item, const QString &base); void getSourceFriendsForHash(const RsFileHash &hash,std::list &srcIds); + void handleEvent_main_thread(std::shared_ptr event); /** the advanced search dialog instance */ AdvancedSearchDialog * advSearchDialog; @@ -159,7 +162,7 @@ private: QAbstractItemDelegate *mAgeColumnDelegate; QAbstractItemDelegate *mSizeColumnDelegate; - /* Color definitions (for standard see qss.default) */ + /* Color definitions (for standard see default.qss) */ QColor mTextColorLocal; QColor mTextColorDownloading; QColor mTextColorNoSources; @@ -171,11 +174,15 @@ private: QAction *collViewAct; QAction *collOpenAct; + FontSizeHandler mFontSizeHandler; + /** Qt Designer generated object */ Ui::SearchDialog ui; bool _queueIsAlreadyTakenCareOf ; std::vector > searchResultsQueue ; + + RsEventsHandlerId_t mEventHandlerId ; }; #endif diff --git a/retroshare-gui/src/gui/FileTransfer/SearchDialog.ui b/retroshare-gui/src/gui/FileTransfer/SearchDialog.ui index ad8c61068..f121c16c1 100644 --- a/retroshare-gui/src/gui/FileTransfer/SearchDialog.ui +++ b/retroshare-gui/src/gui/FileTransfer/SearchDialog.ui @@ -16,7 +16,7 @@ 1 - + @@ -31,7 +31,7 @@ QFrame::Plain - + 3 @@ -45,43 +45,28 @@ 3 - + 2 - - - 0 - 22 - - - - - 16777215 - 22 - - - + - 0 + 2 - 0 + 2 - 0 + 2 - 0 + 2 - + 0 - - 1 - @@ -93,7 +78,14 @@ - + + + + 12 + 75 + true + + Qt::NoFocus @@ -223,6 +215,9 @@ true + + false + KeyWords @@ -261,6 +256,9 @@ true + + false + Filename @@ -336,14 +334,14 @@ - + Any - - :/images/FileTypeAny.png:/images/FileTypeAny.png + + :/icons/filetype/any.svg:/icons/filetype/any.svg @@ -351,8 +349,8 @@ Archive - - :/images/FileTypeArchive.png:/images/FileTypeArchive.png + + :/icons/filetype/archive.svg:/icons/filetype/archive.svg @@ -360,8 +358,8 @@ Audio - - :/images/FileTypeAudio.png:/images/FileTypeAudio.png + + :/icons/filetype/audio.svg:/icons/filetype/audio.svg @@ -369,8 +367,8 @@ CD-Image - - :/images/FileTypeCDImage.png:/images/FileTypeCDImage.png + + :/icons/filetype/img.svg:/icons/filetype/img.svg @@ -378,8 +376,8 @@ Document - - :/images/FileTypeDocument.png:/images/FileTypeDocument.png + + :/icons/filetype/document.svg:/icons/filetype/document.svg @@ -387,8 +385,8 @@ Picture - - :/images/FileTypePicture.png:/images/FileTypePicture.png + + :/icons/filetype/picture.svg:/icons/filetype/picture.svg @@ -396,8 +394,8 @@ Program - - :/images/FileTypeProgram.png:/images/FileTypeProgram.png + + :/icons/filetype/program.svg:/icons/filetype/program.svg @@ -405,8 +403,8 @@ Video - - :/images/FileTypeVideo.png:/images/FileTypeVideo.png + + :/icons/filetype/video.svg:/icons/filetype/video.svg @@ -414,8 +412,8 @@ Directory - - :/images/foldermail.png:/images/foldermail.png + + :/icons/folder.png:/icons/folder.png @@ -460,6 +458,11 @@ QLineEdit
gui/common/LineEditClear.h
+ + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
SearchTreeWidget QTreeWidget @@ -467,8 +470,8 @@ - + diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp index 20de4b9e9..2a8a6b58f 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp @@ -27,7 +27,7 @@ #include "gui/RetroShareLink.h" #include "gui/ShareManager.h" #include "gui/common/PeerDefs.h" -#include "gui/common/RsCollection.h" +#include "gui/common/RsCollectionDialog.h" #include "gui/msgs/MessageComposer.h" #include "gui/gxschannels/GxsChannelDialog.h" #include "gui/gxsforums/GxsForumsDialog.h" @@ -55,6 +55,16 @@ #include +#define SHARED_FILES_DIALOG_COLUMN_NAME 0 +#define SHARED_FILES_DIALOG_COLUMN_FILENB 1 +#define SHARED_FILES_DIALOG_COLUMN_SIZE 2 +#define SHARED_FILES_DIALOG_COLUMN_AGE 3 +#define SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS 4 +#define SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR 5 +#define SHARED_FILES_DIALOG_COLUMN_COUNT 6 + +#define SHARED_FILES_DIALOG_FILTER_STRING "filtered" + /* Images for context menu icons */ #define IMAGE_DOWNLOAD ":/icons/png/download.png" #define IMAGE_PLAY ":/images/start.png" @@ -75,7 +85,7 @@ #define IMAGE_COLLOPEN ":/icons/collections.png" #define IMAGE_EDITSHARE ":/icons/png/pencil-edit-button.png" #define IMAGE_MYFILES ":/icons/svg/folders1.svg" -#define IMAGE_UNSHAREEXTRA ":/images/button_cancel.png" +#define IMAGE_UNSHAREEXTRA ":/icons/cancel.svg" /*define viewType_CB value */ #define VIEW_TYPE_TREE 0 @@ -91,7 +101,7 @@ //#define DEBUG_SHARED_FILES_DIALOG 1 -const QString Image_AddNewAssotiationForFile = ":/images/kcmsystem24.png"; +const QString Image_AddNewAssotiationForFile = ":/icons/svg/options.svg"; class SFDSortFilterProxyModel : public QSortFilterProxyModel { @@ -187,17 +197,17 @@ SharedFilesDialog::SharedFilesDialog(bool remote_mode, QWidget *parent) tree_proxyModel->setSourceModel(tree_model); tree_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); tree_proxyModel->setSortRole(RetroshareDirModel::SortRole); - tree_proxyModel->sort(COLUMN_NAME); + tree_proxyModel->sort(SHARED_FILES_DIALOG_COLUMN_NAME); tree_proxyModel->setFilterRole(RetroshareDirModel::FilterRole); - tree_proxyModel->setFilterRegExp(QRegExp(QString(RETROSHARE_DIR_MODEL_FILTER_STRING))) ; + tree_proxyModel->setFilterRegExp(QRegExp(QString(SHARED_FILES_DIALOG_FILTER_STRING))) ; flat_proxyModel = new SFDSortFilterProxyModel(flat_model, this); flat_proxyModel->setSourceModel(flat_model); flat_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); flat_proxyModel->setSortRole(RetroshareDirModel::SortRole); - flat_proxyModel->sort(COLUMN_NAME); + flat_proxyModel->sort(SHARED_FILES_DIALOG_COLUMN_NAME); flat_proxyModel->setFilterRole(RetroshareDirModel::FilterRole); - flat_proxyModel->setFilterRegExp(QRegExp(QString(RETROSHARE_DIR_MODEL_FILTER_STRING))) ; + flat_proxyModel->setFilterRegExp(QRegExp(QString(SHARED_FILES_DIALOG_FILTER_STRING))) ; connect(ui.filterClearButton, SIGNAL(clicked()), this, SLOT(clearFilter())); connect(ui.filterStartButton, SIGNAL(clicked()), this, SLOT(startFilter())); @@ -213,15 +223,20 @@ SharedFilesDialog::SharedFilesDialog(bool remote_mode, QWidget *parent) /* Set header resize modes and initial section sizes */ QHeaderView * header = ui.dirTreeView->header () ; +#if QT_VERSION < QT_VERSION_CHECK(5,11,0) + int charWidth = ui.dirTreeView->fontMetrics().width("_"); +#else + int charWidth = ui.dirTreeView->fontMetrics().horizontalAdvance("_"); +#endif - header->resizeSection ( COLUMN_NAME, 490 ); - header->resizeSection ( COLUMN_FILENB, 70 ); - header->resizeSection ( COLUMN_SIZE, 70 ); - header->resizeSection ( COLUMN_AGE, 100 ); - header->resizeSection ( COLUMN_FRIEND_ACCESS,100); - header->resizeSection ( COLUMN_WN_VISU_DIR, 100 ); + header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_NAME , charWidth*100 ); + header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_FILENB , charWidth*15 ); + header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_SIZE , charWidth*10 ); + header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_AGE , charWidth*6 ); + header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS, charWidth*10 ); + header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR , charWidth*20 ); - header->setStretchLastSection(false); + header->setStretchLastSection(true); /* Set Multi Selection */ ui.dirTreeView->setSelectionMode(QAbstractItemView::ExtendedSelection); @@ -251,7 +266,7 @@ LocalSharedFilesDialog::LocalSharedFilesDialog(QWidget *parent) : SharedFilesDialog(false,parent) { // Hide columns after loading the settings - ui.dirTreeView->setColumnHidden(COLUMN_WN_VISU_DIR, false) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR, false) ; ui.downloadButton->hide() ; // load settings @@ -270,14 +285,14 @@ LocalSharedFilesDialog::LocalSharedFilesDialog(QWidget *parent) ui.titleBarPixmap->setPixmap(FilesDefs::getPixmapFromQtResourcePath(IMAGE_MYFILES)) ; - ui.dirTreeView->setItemDelegateForColumn(COLUMN_FRIEND_ACCESS,new ShareFlagsItemDelegate()) ; + ui.dirTreeView->setItemDelegateForColumn(SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS,new ShareFlagsItemDelegate()) ; } RemoteSharedFilesDialog::RemoteSharedFilesDialog(QWidget *parent) : SharedFilesDialog(true,parent) { - ui.dirTreeView->setColumnHidden(COLUMN_FRIEND_ACCESS, false) ; - ui.dirTreeView->setColumnHidden(COLUMN_WN_VISU_DIR, true) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS, false) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR, true) ; ui.checkButton->hide() ; connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(downloadRemoteSelected())); @@ -304,7 +319,7 @@ void SharedFilesDialog::hideEvent(QHideEvent *) model->setVisible(false) ; } -void SharedFilesDialog::showEvent(QShowEvent *) +void SharedFilesDialog::showEvent(QShowEvent *event) { if(model!=NULL) { @@ -317,6 +332,10 @@ void SharedFilesDialog::showEvent(QShowEvent *) restoreExpandedPathsAndSelection(expanded_indexes,hidden_indexes,selected_indexes); } + + if (!event->spontaneous()) { + updateFontSize(); + } } RemoteSharedFilesDialog::~RemoteSharedFilesDialog() { @@ -431,9 +450,9 @@ void SharedFilesDialog::changeCurrentViewModel(int viewTypeIndex) restoreExpandedPathsAndSelection(expanded_indexes,hidden_indexes,selected_indexes); QHeaderView * header = ui.dirTreeView->header () ; - QHeaderView_setSectionResizeModeColumn(header, COLUMN_NAME, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(header, SHARED_FILES_DIALOG_COLUMN_NAME, QHeaderView::Interactive); - ui.dirTreeView->header()->headerDataChanged(Qt::Horizontal, COLUMN_NAME, COLUMN_WN_VISU_DIR) ; + ui.dirTreeView->header()->headerDataChanged(Qt::Horizontal, SHARED_FILES_DIALOG_COLUMN_NAME, SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR) ; // recursRestoreExpandedItems(ui.dirTreeView->rootIndex(),expanded_indexes); FilterItems(); @@ -443,9 +462,9 @@ void LocalSharedFilesDialog::showProperColumns() { if(model == tree_model) { - ui.dirTreeView->setColumnHidden(COLUMN_FILENB, false) ; - ui.dirTreeView->setColumnHidden(COLUMN_FRIEND_ACCESS, false) ; - ui.dirTreeView->setColumnHidden(COLUMN_WN_VISU_DIR, false) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FILENB, false) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS, false) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR, false) ; #ifdef DONT_USE_SEARCH_IN_TREE_VIEW ui.filterLabel->hide(); ui.filterPatternLineEdit->hide(); @@ -455,9 +474,9 @@ void LocalSharedFilesDialog::showProperColumns() } else { - ui.dirTreeView->setColumnHidden(COLUMN_FILENB, true) ; - ui.dirTreeView->setColumnHidden(COLUMN_FRIEND_ACCESS, true) ; - ui.dirTreeView->setColumnHidden(COLUMN_WN_VISU_DIR, false) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FILENB, true) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS, true) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR, false) ; #ifdef DONT_USE_SEARCH_IN_TREE_VIEW ui.filterLabel->show(); ui.filterPatternLineEdit->show(); @@ -468,9 +487,9 @@ void RemoteSharedFilesDialog::showProperColumns() { if(model == tree_model) { - ui.dirTreeView->setColumnHidden(COLUMN_FILENB, false) ; - ui.dirTreeView->setColumnHidden(COLUMN_FRIEND_ACCESS, true) ; - ui.dirTreeView->setColumnHidden(COLUMN_WN_VISU_DIR, true) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FILENB, false) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS, true) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR, true) ; #ifdef DONT_USE_SEARCH_IN_TREE_VIEW ui.filterLabel->hide(); ui.filterPatternLineEdit->hide(); @@ -480,9 +499,9 @@ void RemoteSharedFilesDialog::showProperColumns() } else { - ui.dirTreeView->setColumnHidden(COLUMN_FILENB, true) ; - ui.dirTreeView->setColumnHidden(COLUMN_FRIEND_ACCESS, false) ; - ui.dirTreeView->setColumnHidden(COLUMN_WN_VISU_DIR, false) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FILENB, true) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS, false) ; + ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR, false) ; #ifdef DONT_USE_SEARCH_IN_TREE_VIEW ui.filterLabel->show(); ui.filterPatternLineEdit->show(); @@ -510,7 +529,6 @@ void LocalSharedFilesDialog::checkUpdate() void LocalSharedFilesDialog::forceCheck() { rsFiles->ForceDirectoryCheck(); - return; } void RemoteSharedFilesDialog::spawnCustomPopupMenu( QPoint point ) @@ -634,7 +652,7 @@ void SharedFilesDialog::copyLinks(const QModelIndexList& lst, bool remote,QList< QString dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName(); - RetroShareLink link = RetroShareLink::createFileTree(dir_name,ft->mTotalSize,ft->mTotalFiles,QString::fromStdString(ft->toRadix64())) ; + RetroShareLink link = RetroShareLink::createFileTree(dir_name,ft->totalFileSize(),ft->numFiles(),QString::fromStdString(ft->toRadix64())) ; if(link.valid()) urls.push_back(link) ; @@ -716,7 +734,32 @@ void SharedFilesDialog::sendLinkTo() void SharedFilesDialog::collCreate() { QModelIndexList lst = getSelected(); - model->createCollectionFile(this, lst); + + std::vector dirVec; + model->getDirDetailsFromSelect(lst, dirVec); + + auto RemoteMode = isRemote(); + FileSearchFlags f = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ; + + QString dir_name; + + if(!RemoteMode) + { + if(!dirVec.empty()) + { + const DirDetails& details = dirVec[0]; + dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName(); + } + } + + RsFileTree tree; + + for(uint32_t i=0;isetEnabled(bIsRsColl); collOpenAct->setEnabled(true); - QMenu collectionMenu(tr("Collection"), this); + QMenu collectionMenu(tr("Retroshare Collection"), this); collectionMenu.setIcon(QIcon(IMAGE_LIBRARY)); collectionMenu.addAction(collCreateAct); - collectionMenu.addAction(collModifAct); - collectionMenu.addAction(collViewAct); - collectionMenu.addAction(collOpenAct); + + if(bIsRsColl) + collectionMenu.addAction(collModifAct); + //collectionMenu.addAction(collViewAct); + //collectionMenu.addAction(collOpenAct); switch (type) { case DIR_TYPE_DIR : @@ -1328,9 +1369,9 @@ void SharedFilesDialog::indicatorChanged(int index) ui.dirTreeView->update(ui.dirTreeView->rootIndex()); if (correct_indicator[index] != IND_ALWAYS) - ui.dirTreeView->sortByColumn(COLUMN_AGE, Qt::AscendingOrder); + ui.dirTreeView->sortByColumn(SHARED_FILES_DIALOG_COLUMN_AGE, Qt::AscendingOrder); else - ui.dirTreeView->sortByColumn(COLUMN_NAME, Qt::AscendingOrder); + ui.dirTreeView->sortByColumn(SHARED_FILES_DIALOG_COLUMN_NAME, Qt::AscendingOrder); updateDisplay() ; } @@ -1578,7 +1619,7 @@ void SharedFilesDialog::FilterItems() return ; //FileSearchFlags flags = isRemote()?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL; - QStringList lst = text.split(" ",QString::SkipEmptyParts) ; + QStringList lst = text.split(" ",QtSkipEmptyParts) ; std::list keywords ; for(auto it(lst.begin());it!=lst.end();++it) @@ -1667,3 +1708,20 @@ bool SharedFilesDialog::tree_FilterItem(const QModelIndex &index, const QString return (visible || visibleChildCount); } #endif + +void SharedFilesDialog::updateFontSize() +{ +#if defined(Q_OS_DARWIN) + int customFontSize = Settings->valueFromGroup("File", "MinimumFontSize", 13).toInt(); +#else + int customFontSize = Settings->valueFromGroup("File", "MinimumFontSize", 11).toInt(); +#endif + QFont newFont = ui.dirTreeView->font(); + if (newFont.pointSize() != customFontSize) { + newFont.setPointSize(customFontSize); + QFontMetricsF fontMetrics(newFont); + int iconHeight = fontMetrics.height()*1.5; + ui.dirTreeView->setFont(newFont); + ui.dirTreeView->setIconSize(QSize(iconHeight, iconHeight)); + } +} diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.h b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.h index c406821c9..7524d5035 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.h +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.h @@ -117,6 +117,8 @@ protected: QModelIndexList getSelected(); + void updateFontSize(); + /** Defines the actions for the context menu for QTreeWidget */ QAction* copylinkAct; QAction* sendlinkAct; diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.ui b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.ui index b1f4ceb9b..4c8f8c38b 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.ui +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.ui @@ -23,10 +23,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -61,7 +61,14 @@
- + + + + 12 + 75 + true + + Files @@ -216,7 +223,7 @@ border-image: url(:/images/closepressed.png)
- + Tree view @@ -230,14 +237,14 @@ border-image: url(:/images/closepressed.png) - + All - - :/images/view_calendar_list.png:/images/view_calendar_list.png + + :/icons/svg/calendar-blank.svg:/icons/svg/calendar-blank.svg @@ -245,8 +252,8 @@ border-image: url(:/images/closepressed.png) One day old - - :/images/view_calendar_day.png:/images/view_calendar_day.png + + :/icons/svg/calendar-today.svg:/icons/svg/calendar-today.svg @@ -254,8 +261,8 @@ border-image: url(:/images/closepressed.png) One Week old - - :/images/view_calendar_week.png:/images/view_calendar_week.png + + :/icons/svg/calendar-week.svg:/icons/svg/calendar-week.svg @@ -263,8 +270,8 @@ border-image: url(:/images/closepressed.png) One month old - - :/images/view_calendar_month.png:/images/view_calendar_month.png + + :/icons/svg/calendar-month.svg:/icons/svg/calendar-month.svg @@ -278,9 +285,16 @@ border-image: url(:/images/closepressed.png) + + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + check files + + + :/icons/svg/refresh.svg:/icons/svg/refresh.svg + @@ -304,8 +318,8 @@ border-image: url(:/images/closepressed.png) Download - - :/images/download16.png:/images/download16.png + + :/icons/png/download.png:/icons/png/download.png @@ -366,9 +380,9 @@ border-image: url(:/images/closepressed.png) true - + false - +
@@ -379,9 +393,9 @@ border-image: url(:/images/closepressed.png) - StyledLabel - QLabel -
gui/common/StyledLabel.h
+ RSComboBox + QComboBox +
gui/common/RSComboBox.h
diff --git a/retroshare-gui/src/gui/FileTransfer/TransferUserNotify.cpp b/retroshare-gui/src/gui/FileTransfer/TransferUserNotify.cpp index b424d922b..fa0c33046 100644 --- a/retroshare-gui/src/gui/FileTransfer/TransferUserNotify.cpp +++ b/retroshare-gui/src/gui/FileTransfer/TransferUserNotify.cpp @@ -27,8 +27,6 @@ TransferUserNotify::TransferUserNotify(QObject *parent) : UserNotify(parent) { newTransferCount = 0; - -// connect(NotifyQt::getInstance(), SIGNAL(downloadCompleteCountChanged(int)), this, SLOT(downloadCountChanged(int))); } bool TransferUserNotify::hasSetting(QString *name, QString *group) diff --git a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp index 9fa03f3fd..3ee120162 100644 --- a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp @@ -21,9 +21,10 @@ #include "TransfersDialog.h" #include "gui/notifyqt.h" +#include "gui/SoundManager.h" #include "gui/RetroShareLink.h" #include "gui/common/FilesDefs.h" -#include "gui/common/RsCollection.h" +#include "gui/common/RsCollectionDialog.h" #include "gui/common/RSTreeView.h" #include "gui/common/RsUrlHandler.h" #include "gui/FileTransfer/DetailsDialog.h" @@ -144,7 +145,7 @@ public: } int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { - return COLUMN_COUNT ; + return DLListDelegate::COLUMN_COUNT ; } bool hasChildren(const QModelIndex &parent = QModelIndex()) const { @@ -176,7 +177,7 @@ public: QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const { - if(row < 0 || column < 0 || column >= COLUMN_COUNT) + if(row < 0 || column < 0 || column >= DLListDelegate::COLUMN_COUNT) return QModelIndex(); void *parent_ref = (parent.isValid())?parent.internalPointer():NULL ; @@ -258,19 +259,19 @@ public: switch(section) { default: - case COLUMN_NAME: return tr("Name", "i.e: file name"); - case COLUMN_SIZE: return tr("Size", "i.e: file size"); - case COLUMN_COMPLETED: return tr("Completed", ""); - case COLUMN_DLSPEED: return tr("Speed", "i.e: Download speed"); - case COLUMN_PROGRESS: return tr("Progress / Availability", "i.e: % downloaded"); - case COLUMN_SOURCES: return tr("Sources", "i.e: Sources"); - case COLUMN_STATUS: return tr("Status"); - case COLUMN_PRIORITY: return tr("Speed / Queue position"); - case COLUMN_REMAINING: return tr("Remaining"); - case COLUMN_DOWNLOADTIME: return tr("Download time", "i.e: Estimated Time of Arrival / Time left"); - case COLUMN_ID: return tr("Hash"); - case COLUMN_LASTDL: return tr("Last Time Seen", "i.e: Last Time Receiced Data"); - case COLUMN_PATH: return tr("Path", "i.e: Where file is saved"); + case DLListDelegate::COLUMN_NAME: return tr("Name", "i.e: file name"); + case DLListDelegate::COLUMN_SIZE: return tr("Size", "i.e: file size"); + case DLListDelegate::COLUMN_COMPLETED: return tr("Completed", ""); + case DLListDelegate::COLUMN_DLSPEED: return tr("Speed", "i.e: Download speed"); + case DLListDelegate::COLUMN_PROGRESS: return tr("Progress / Availability", "i.e: % downloaded"); + case DLListDelegate::COLUMN_SOURCES: return tr("Sources", "i.e: Sources"); + case DLListDelegate::COLUMN_STATUS: return tr("Status"); + case DLListDelegate::COLUMN_PRIORITY: return tr("Speed / Queue position"); + case DLListDelegate::COLUMN_REMAINING: return tr("Remaining"); + case DLListDelegate::COLUMN_DOWNLOADTIME: return tr("Download time", "i.e: Estimated Time of Arrival / Time left"); + case DLListDelegate::COLUMN_ID: return tr("Hash"); + case DLListDelegate::COLUMN_LASTDL: return tr("Last Time Seen", "i.e: Last Time Receiced Data"); + case DLListDelegate::COLUMN_PATH: return tr("Path", "i.e: Where file is saved"); } } @@ -352,19 +353,19 @@ public: switch(col) { default: - case COLUMN_NAME: return QVariant( QSize(factor * 170, factor*14.0f )); - case COLUMN_SIZE: return QVariant( QSize(factor * 70 , factor*14.0f )); - case COLUMN_COMPLETED: return QVariant( QSize(factor * 75 , factor*14.0f )); - case COLUMN_DLSPEED: return QVariant( QSize(factor * 75 , factor*14.0f )); - case COLUMN_PROGRESS: return QVariant( QSize(factor * 170, factor*14.0f )); - case COLUMN_SOURCES: return QVariant( QSize(factor * 90 , factor*14.0f )); - case COLUMN_STATUS: return QVariant( QSize(factor * 100, factor*14.0f )); - case COLUMN_PRIORITY: return QVariant( QSize(factor * 100, factor*14.0f )); - case COLUMN_REMAINING: return QVariant( QSize(factor * 100, factor*14.0f )); - case COLUMN_DOWNLOADTIME: return QVariant( QSize(factor * 100, factor*14.0f )); - case COLUMN_ID: return QVariant( QSize(factor * 100, factor*14.0f )); - case COLUMN_LASTDL: return QVariant( QSize(factor * 100, factor*14.0f )); - case COLUMN_PATH: return QVariant( QSize(factor * 100, factor*14.0f )); + case DLListDelegate::COLUMN_NAME: return QVariant( QSize(factor * 170, factor*14.0f )); + case DLListDelegate::COLUMN_SIZE: return QVariant( QSize(factor * 70 , factor*14.0f )); + case DLListDelegate::COLUMN_COMPLETED: return QVariant( QSize(factor * 75 , factor*14.0f )); + case DLListDelegate::COLUMN_DLSPEED: return QVariant( QSize(factor * 75 , factor*14.0f )); + case DLListDelegate::COLUMN_PROGRESS: return QVariant( QSize(factor * 170, factor*14.0f )); + case DLListDelegate::COLUMN_SOURCES: return QVariant( QSize(factor * 90 , factor*14.0f )); + case DLListDelegate::COLUMN_STATUS: return QVariant( QSize(factor * 100, factor*14.0f )); + case DLListDelegate::COLUMN_PRIORITY: return QVariant( QSize(factor * 100, factor*14.0f )); + case DLListDelegate::COLUMN_REMAINING: return QVariant( QSize(factor * 100, factor*14.0f )); + case DLListDelegate::COLUMN_DOWNLOADTIME: return QVariant( QSize(factor * 100, factor*14.0f )); + case DLListDelegate::COLUMN_ID: return QVariant( QSize(factor * 100, factor*14.0f )); + case DLListDelegate::COLUMN_LASTDL: return QVariant( QSize(factor * 100, factor*14.0f )); + case DLListDelegate::COLUMN_PATH: return QVariant( QSize(factor * 100, factor*14.0f )); } } @@ -374,11 +375,11 @@ public: if(source_id == -1) // toplevel switch(col) { - case COLUMN_NAME: return QVariant(QString::fromUtf8(fileInfo.fname.c_str())); - case COLUMN_COMPLETED: return QVariant((qlonglong)fileInfo.transfered); - case COLUMN_DLSPEED: return QVariant((double)((fileInfo.downloadStatus == FT_STATE_DOWNLOADING) ? (fileInfo.tfRate * 1024.0) : 0.0)); - case COLUMN_PROGRESS: return QVariant((float)((fileInfo.size == 0) ? 0 : (fileInfo.transfered * 100.0 / (float)fileInfo.size))); - case COLUMN_STATUS: + case DLListDelegate::COLUMN_NAME: return QVariant(QString::fromUtf8(fileInfo.fname.c_str())); + case DLListDelegate::COLUMN_COMPLETED: return QVariant((qlonglong)fileInfo.transfered); + case DLListDelegate::COLUMN_DLSPEED: return QVariant((double)((fileInfo.downloadStatus == FT_STATE_DOWNLOADING) ? (fileInfo.tfRate * 1024.0) : 0.0)); + case DLListDelegate::COLUMN_PROGRESS: return QVariant((float)((fileInfo.size == 0) ? 0 : (fileInfo.transfered * 100.0 / (float)fileInfo.size))); + case DLListDelegate::COLUMN_STATUS: { QString status; switch (fileInfo.downloadStatus) @@ -396,9 +397,9 @@ public: return QVariant(status); } - case COLUMN_PRIORITY: + case DLListDelegate::COLUMN_PRIORITY: { - double priority = PRIORITY_NULL; + double priority = DLListDelegate::PRIORITY_NULL; if (fileInfo.downloadStatus == FT_STATE_QUEUED) priority = fileInfo.queue_position; @@ -407,18 +408,18 @@ public: else switch (fileInfo.priority) { - case SPEED_LOW: priority = PRIORITY_SLOWER; break; - case SPEED_NORMAL: priority = PRIORITY_AVERAGE; break; - case SPEED_HIGH: priority = PRIORITY_FASTER; break; - default: priority = PRIORITY_AVERAGE; break; + case SPEED_LOW: priority = DLListDelegate::PRIORITY_SLOWER; break; + case SPEED_NORMAL: priority = DLListDelegate::PRIORITY_AVERAGE; break; + case SPEED_HIGH: priority = DLListDelegate::PRIORITY_FASTER; break; + default: priority = DLListDelegate::PRIORITY_AVERAGE; break; } return QVariant(priority); } - case COLUMN_REMAINING: return QVariant((qlonglong)(fileInfo.size - fileInfo.transfered)); - case COLUMN_DOWNLOADTIME: return QVariant((qlonglong)(fileInfo.tfRate > 0)?( (fileInfo.size - fileInfo.transfered) / (fileInfo.tfRate * 1024.0) ) : 0); - case COLUMN_LASTDL: + case DLListDelegate::COLUMN_REMAINING: return QVariant((qlonglong)(fileInfo.size - fileInfo.transfered)); + case DLListDelegate::COLUMN_DOWNLOADTIME: return QVariant((qlonglong)(fileInfo.tfRate > 0)?( (fileInfo.size - fileInfo.transfered) / (fileInfo.tfRate * 1024.0) ) : 0); + case DLListDelegate::COLUMN_LASTDL: { qint64 qi64LastDL = fileInfo.lastTS ; @@ -437,19 +438,19 @@ public: } return QVariant(qi64LastDL) ; } - case COLUMN_PATH: + case DLListDelegate::COLUMN_PATH: { QString strPath = QString::fromUtf8(fileInfo.path.c_str()); QString strPathAfterDL = strPath; - strPathAfterDL.replace(QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()),""); + strPathAfterDL.replace(QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()),"[Download Dir]"); return QVariant(strPathAfterDL); } - case COLUMN_SOURCES: + case DLListDelegate::COLUMN_SOURCES: { int active = 0; - QString fileHash = QString::fromStdString(fileInfo.hash.toStdString()); + //QString fileHash = QString::fromStdString(fileInfo.hash.toStdString()); if (fileInfo.downloadStatus != FT_STATE_COMPLETE) for (std::vector::const_iterator pit = fileInfo.peers.begin() ; pit != fileInfo.peers.end(); ++pit) @@ -478,9 +479,9 @@ public: } - case COLUMN_SIZE: return QVariant((qlonglong) fileInfo.size); + case DLListDelegate::COLUMN_SIZE: return QVariant((qlonglong) fileInfo.size); - case COLUMN_ID: return QVariant(QString::fromStdString(fileInfo.hash.toStdString())); + case DLListDelegate::COLUMN_ID: return QVariant(QString::fromStdString(fileInfo.hash.toStdString())); default: return QVariant("[ TODO ]"); @@ -492,16 +493,16 @@ public: switch(col) { default: - case COLUMN_SOURCES: - case COLUMN_COMPLETED: - case COLUMN_REMAINING: - case COLUMN_LASTDL: - case COLUMN_ID: - case COLUMN_PATH: - case COLUMN_DOWNLOADTIME: - case COLUMN_SIZE: return QVariant(); - case COLUMN_PROGRESS: return QVariant( (fileInfo.size>0)?((fileInfo.peers[source_id].transfered % chunk_size)*100.0/fileInfo.size):0.0) ; - case COLUMN_DLSPEED: + case DLListDelegate::COLUMN_SOURCES: + case DLListDelegate::COLUMN_COMPLETED: + case DLListDelegate::COLUMN_REMAINING: + case DLListDelegate::COLUMN_LASTDL: + case DLListDelegate::COLUMN_ID: + case DLListDelegate::COLUMN_PATH: + case DLListDelegate::COLUMN_DOWNLOADTIME: + case DLListDelegate::COLUMN_SIZE: return QVariant(); + case DLListDelegate::COLUMN_PROGRESS: return QVariant( (fileInfo.size>0)?((fileInfo.peers[source_id].transfered % chunk_size)*100.0/fileInfo.size):0.0) ; + case DLListDelegate::COLUMN_DLSPEED: { double peerDlspeed = 0; if((uint32_t)fileInfo.peers[source_id].status == FT_STATE_DOWNLOADING && fileInfo.downloadStatus != FT_STATE_PAUSED && fileInfo.downloadStatus != FT_STATE_COMPLETE) @@ -509,13 +510,13 @@ public: return QVariant((double)peerDlspeed) ; } - case COLUMN_NAME: + case DLListDelegate::COLUMN_NAME: { QString iconName,tooltip; return QVariant(TransfersDialog::getPeerName(fileInfo.peers[source_id].peerId, iconName, tooltip)); } - case COLUMN_PRIORITY: return QVariant((double)PRIORITY_NULL); + case DLListDelegate::COLUMN_PRIORITY: return QVariant((double)DLListDelegate::PRIORITY_NULL); } } @@ -527,7 +528,7 @@ public: if(source_id == -1) switch(col) { - case COLUMN_PROGRESS: + case DLListDelegate::COLUMN_PROGRESS: { FileChunksInfo fcinfo; if (!rsFiles->FileDownloadChunksDetails(fileInfo.hash, fcinfo)) @@ -554,7 +555,7 @@ public: return QVariant::fromValue(pinfo); } - case COLUMN_ID: return QVariant(QString::fromStdString(fileInfo.hash.toStdString())); + case DLListDelegate::COLUMN_ID: return QVariant(QString::fromStdString(fileInfo.hash.toStdString())); default: @@ -563,7 +564,7 @@ public: else switch(col) { - case COLUMN_PROGRESS: + case DLListDelegate::COLUMN_PROGRESS: { FileChunksInfo fcinfo; if (!rsFiles->FileDownloadChunksDetails(fileInfo.hash, fcinfo)) @@ -582,7 +583,7 @@ public: return QVariant::fromValue(pinfo); } - case COLUMN_ID: return QVariant(QString::fromStdString(fileInfo.hash.toStdString()) + QString::fromStdString(fileInfo.peers[source_id].peerId.toStdString())); + case DLListDelegate::COLUMN_ID: return QVariant(QString::fromStdString(fileInfo.hash.toStdString()) + QString::fromStdString(fileInfo.peers[source_id].peerId.toStdString())); default: return QVariant(); @@ -592,7 +593,7 @@ public: QVariant decorationRole(const FileInfo& fileInfo,int source_id,int col) const { - if(col == COLUMN_NAME) + if(col == DLListDelegate::COLUMN_NAME) { if(source_id == -1) return QVariant(FilesDefs::getIconFromFileType(QString::fromUtf8(fileInfo.fname.c_str()))); @@ -635,27 +636,27 @@ public: for(auto it(downHashes.begin());it!=downHashes.end();++it,++i) { FileInfo fileInfo(mDownloads[i]); // we dont update the data itself but only a copy of it.... - int old_size = fileInfo.peers.size() ; + int old_peers_size = fileInfo.peers.size() ; rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, fileInfo); int new_size = fileInfo.peers.size() ; - if(old_size < new_size) + if(old_peers_size < new_size) { - beginInsertRows(index(i,0), old_size, new_size-1); - insertRows(old_size, new_size - old_size,index(i,0)); + beginInsertRows(index(i,0), old_peers_size, new_size-1); + insertRows(old_peers_size, new_size - old_peers_size,index(i,0)); #ifdef DEBUG_DOWNLOADLIST - std::cerr << "called insert rows ( " << old_size << ", " << new_size - old_size << ",index(" << index(i,0)<< "))" << std::endl; + std::cerr << "called insert rows ( " << old_peers_size << ", " << new_size - old_peers_size << ",index(" << index(i,0)<< "))" << std::endl; #endif endInsertRows(); } - else if(new_size < old_size) + else if(new_size < old_peers_size) { - beginRemoveRows(index(i,0), new_size, old_size-1); - removeRows(new_size, old_size - new_size,index(i,0)); + beginRemoveRows(index(i,0), new_size, old_peers_size-1); + removeRows(new_size, old_peers_size - new_size,index(i,0)); #ifdef DEBUG_DOWNLOADLIST - std::cerr << "called remove rows ( " << old_size << ", " << old_size - new_size << ",index(" << index(i,0)<< "))" << std::endl; + std::cerr << "called remove rows ( " << old_peers_size << ", " << old_peers_size - new_size << ",index(" << index(i,0)<< "))" << std::endl; #endif endRemoveRows(); } @@ -666,7 +667,7 @@ public: if(fileInfo.downloadStatus == FT_STATE_DOWNLOADING || old_status != fileInfo.downloadStatus) { - QModelIndex topLeft = createIndex(i,0), bottomRight = createIndex(i, COLUMN_COUNT-1); + QModelIndex topLeft = createIndex(i,0), bottomRight = createIndex(i, DLListDelegate::COLUMN_COUNT-1); emit dataChanged(topLeft, bottomRight); } @@ -674,7 +675,7 @@ public: // // if(!mDownloads.empty()) // { - // QModelIndex topLeft = createIndex(0,0), bottomRight = createIndex(mDownloads.size()-1, COLUMN_COUNT-1); + // QModelIndex topLeft = createIndex(0,0), bottomRight = createIndex(mDownloads.size()-1, DLListDelegate::COLUMN_COUNT-1); // emit dataChanged(topLeft, bottomRight); // mDownloads[i] = fileInfo ; // } @@ -742,7 +743,7 @@ private: class SortByNameItem : public QStandardItem { public: - SortByNameItem(QHeaderView *header) : QStandardItem() + explicit SortByNameItem(QHeaderView *header) : QStandardItem() { this->header = header; } @@ -761,8 +762,8 @@ public: return QStandardItem::operator<(other); } - QStandardItem *myName = myParent->child(index().row(), COLUMN_NAME); - QStandardItem *otherName = otherParent->child(other.index().row(), COLUMN_NAME); + QStandardItem *myName = myParent->child(index().row(), DLListDelegate::COLUMN_NAME); + QStandardItem *otherName = otherParent->child(other.index().row(), DLListDelegate::COLUMN_NAME); if (header == NULL || header->sortIndicatorOrder() == Qt::AscendingOrder) { /* Ascending */ @@ -780,9 +781,9 @@ private: class ProgressItem : public SortByNameItem { public: - ProgressItem(QHeaderView *header) : SortByNameItem(header) {} + explicit ProgressItem(QHeaderView *header) : SortByNameItem(header) {} - virtual bool operator<(const QStandardItem &other) const + virtual bool operator<(const QStandardItem &other) const override { const int role = model() ? model()->sortRole() : Qt::DisplayRole; @@ -847,41 +848,41 @@ TransfersDialog::TransfersDialog(QWidget *parent) // /* Set header resize modes and initial section sizes Downloads TreeView*/ QHeaderView * dlheader = ui.downloadList->header () ; - QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_NAME, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_SIZE, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_COMPLETED, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_DLSPEED, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_PROGRESS, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_SOURCES, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_STATUS, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_PRIORITY, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_REMAINING, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_DOWNLOADTIME, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_ID, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_LASTDL, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_PATH, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(dlheader, DLListDelegate::COLUMN_NAME, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(dlheader, DLListDelegate::COLUMN_SIZE, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(dlheader, DLListDelegate::COLUMN_COMPLETED, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(dlheader, DLListDelegate::COLUMN_DLSPEED, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(dlheader, DLListDelegate::COLUMN_PROGRESS, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(dlheader, DLListDelegate::COLUMN_SOURCES, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(dlheader, DLListDelegate::COLUMN_STATUS, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(dlheader, DLListDelegate::COLUMN_PRIORITY, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(dlheader, DLListDelegate::COLUMN_REMAINING, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(dlheader, DLListDelegate::COLUMN_DOWNLOADTIME, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(dlheader, DLListDelegate::COLUMN_ID, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(dlheader, DLListDelegate::COLUMN_LASTDL, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(dlheader, DLListDelegate::COLUMN_PATH, QHeaderView::Interactive); // set default column and sort order for download - ui.downloadList->sortByColumn(COLUMN_NAME, Qt::AscendingOrder); + ui.downloadList->sortByColumn(DLListDelegate::COLUMN_NAME, Qt::AscendingOrder); connect(ui.filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); /* Add filter actions */ - QString headerName = DLListModel->headerData(COLUMN_NAME, Qt::Horizontal).toString(); - ui.filterLineEdit->addFilter(QIcon(), headerName, COLUMN_NAME , QString("%1 %2").arg(tr("Search"), headerName)); - QString headerID = DLListModel->headerData(COLUMN_ID, Qt::Horizontal).toString(); - ui.filterLineEdit->addFilter(QIcon(), headerID, COLUMN_ID , QString("%1 %2").arg(tr("Search"), headerID)); + QString headerName = DLListModel->headerData(DLListDelegate::COLUMN_NAME, Qt::Horizontal).toString(); + ui.filterLineEdit->addFilter(QIcon(), headerName, DLListDelegate::COLUMN_NAME , QString("%1 %2").arg(tr("Search"), headerName)); + QString headerID = DLListModel->headerData(DLListDelegate::COLUMN_ID, Qt::Horizontal).toString(); + ui.filterLineEdit->addFilter(QIcon(), headerID, DLListDelegate::COLUMN_ID , QString("%1 %2").arg(tr("Search"), headerID)); connect( ui.uploadsList, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( uploadsListCustomPopupMenu( QPoint ) ) ); // Set Upload list model - ULListModel = new QStandardItemModel(0,COLUMN_UCOUNT); - ULListModel->setHeaderData(COLUMN_UNAME, Qt::Horizontal, tr("Name", "i.e: file name")); - ULListModel->setHeaderData(COLUMN_UPEER, Qt::Horizontal, tr("Peer", "i.e: user name / tunnel id")); - ULListModel->setHeaderData(COLUMN_USIZE, Qt::Horizontal, tr("Size", "i.e: file size")); - ULListModel->setHeaderData(COLUMN_UTRANSFERRED, Qt::Horizontal, tr("Transferred", "")); - ULListModel->setHeaderData(COLUMN_ULSPEED, Qt::Horizontal, tr("Speed", "i.e: upload speed")); - ULListModel->setHeaderData(COLUMN_UPROGRESS, Qt::Horizontal, tr("Progress", "i.e: % uploaded")); - ULListModel->setHeaderData(COLUMN_UHASH, Qt::Horizontal, tr("Hash", "")); + ULListModel = new QStandardItemModel(0,ULListDelegate::COLUMN_UCOUNT); + ULListModel->setHeaderData(ULListDelegate::COLUMN_UNAME, Qt::Horizontal, tr("Name", "i.e: file name")); + ULListModel->setHeaderData(ULListDelegate::COLUMN_UPEER, Qt::Horizontal, tr("Peer", "i.e: user name / tunnel id")); + ULListModel->setHeaderData(ULListDelegate::COLUMN_USIZE, Qt::Horizontal, tr("Size", "i.e: file size")); + ULListModel->setHeaderData(ULListDelegate::COLUMN_UTRANSFERRED, Qt::Horizontal, tr("Transferred", "")); + ULListModel->setHeaderData(ULListDelegate::COLUMN_ULSPEED, Qt::Horizontal, tr("Speed", "i.e: upload speed")); + ULListModel->setHeaderData(ULListDelegate::COLUMN_UPROGRESS, Qt::Horizontal, tr("Progress", "i.e: % uploaded")); + ULListModel->setHeaderData(ULListDelegate::COLUMN_UHASH, Qt::Horizontal, tr("Hash", "")); ui.uploadsList->setModel(ULListModel); @@ -901,22 +902,22 @@ TransfersDialog::TransfersDialog(QWidget *parent) /* Set header resize modes and initial section sizes Uploads TreeView*/ QHeaderView * upheader = ui.uploadsList->header () ; - QHeaderView_setSectionResizeModeColumn(upheader, COLUMN_UNAME, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(upheader, COLUMN_UPEER, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(upheader, COLUMN_USIZE, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(upheader, COLUMN_UTRANSFERRED, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(upheader, COLUMN_ULSPEED, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(upheader, COLUMN_UPROGRESS, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(upheader, ULListDelegate::COLUMN_UNAME, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(upheader, ULListDelegate::COLUMN_UPEER, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(upheader, ULListDelegate::COLUMN_USIZE, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(upheader, ULListDelegate::COLUMN_UTRANSFERRED, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(upheader, ULListDelegate::COLUMN_ULSPEED, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(upheader, ULListDelegate::COLUMN_UPROGRESS, QHeaderView::Interactive); - upheader->resizeSection ( COLUMN_UNAME, 260 ); - upheader->resizeSection ( COLUMN_UPEER, 120 ); - upheader->resizeSection ( COLUMN_USIZE, 70 ); - upheader->resizeSection ( COLUMN_UTRANSFERRED, 75 ); - upheader->resizeSection ( COLUMN_ULSPEED, 75 ); - upheader->resizeSection ( COLUMN_UPROGRESS, 170 ); + upheader->resizeSection ( ULListDelegate::COLUMN_UNAME, 260 ); + upheader->resizeSection ( ULListDelegate::COLUMN_UPEER, 120 ); + upheader->resizeSection ( ULListDelegate::COLUMN_USIZE, 70 ); + upheader->resizeSection ( ULListDelegate::COLUMN_UTRANSFERRED, 75 ); + upheader->resizeSection ( ULListDelegate::COLUMN_ULSPEED, 75 ); + upheader->resizeSection ( ULListDelegate::COLUMN_UPROGRESS, 170 ); // set default column and sort order for upload - ui.uploadsList->sortByColumn(COLUMN_UNAME, Qt::AscendingOrder); + ui.uploadsList->sortByColumn(ULListDelegate::COLUMN_UNAME, Qt::AscendingOrder); QObject::connect(ui.downloadList->selectionModel(),SIGNAL(selectionChanged (const QItemSelection&, const QItemSelection&)),this,SLOT(showFileDetails())) ; @@ -1077,24 +1078,23 @@ TransfersDialog::TransfersDialog(QWidget *parent) // load settings processSettings(true); - int S = static_cast(QFontMetricsF(font()).height()); + int H = misc::getFontSizeFactor("HelpButton").height(); QString help_str = tr( - "

  " - "File Transfer

" - "

Retroshare brings two ways of transferring files: direct " - "transfers from your friends, and distant anonymous tunnelled " - "transfers. In addition, file transfer is multi-source and " - "allows swarming (you can be a source while downloading)

" - "

You can share files using the " - "" - " icon from the left side bar. These files will be listed in " - "the My Files tab. You can decide for each friend group whether" - " they can or not see these files in their Friends Files tab

" - "

The search tab reports files from your friends' file lists," - " and distant files that can be reached anonymously using the " - "multi-hop tunnelling system.

") - .arg(QString::number(2*S)).arg(QString::number(S)) ; - + "

  " + " File Transfer

" + "

Retroshare brings two ways of transferring files: direct " + " transfers from your friends, and distant anonymous tunnelled " + " transfers. In addition, file transfer is multi-source and " + " allows swarming (you can be a source while downloading)

" + "

You can share files using the " + " " + " icon from the left side bar. These files will be listed in " + " the My Files tab. You can decide for each friend group whether" + " they can or not see these files in their Friends Files tab

" + "

The search tab reports files from your friends' file lists," + " and distant files that can be reached anonymously using the " + " multi-hop tunnelling system.

" + ).arg(QString::number(2*H), QString::number(H)) ; registerHelpButton(ui.helpButton,help_str,"TransfersDialog") ; @@ -1114,6 +1114,16 @@ void TransfersDialog::handleEvent_main_thread(std::shared_ptr eve switch (fe->mFileTransferEventCode) { case RsFileTransferEventCode::DOWNLOAD_COMPLETE: + { + FileInfo nfo ; + if(!rsFiles->FileDetails(fe->mHash, RS_FILE_HINTS_DOWNLOAD, nfo)) + break; + + SoundManager::play(SOUND_DOWNLOAD_COMPLETE); + NotifyQt::getInstance()->addToaster(RS_POPUP_DOWNLOAD, fe->mHash.toStdString(), nfo.fname.c_str(),""); + } + [[fallthrough]]; + case RsFileTransferEventCode::COMPLETED_FILES_REMOVED: getUserNotify()->updateIcon(); @@ -1175,18 +1185,18 @@ void TransfersDialog::processSettings(bool bLoad) // state of splitter ui.splitter->restoreState(Settings->value("Splitter").toByteArray()); - setShowDLSizeColumn(Settings->value("showDLSizeColumn", !ui.downloadList->isColumnHidden(COLUMN_SIZE)).toBool()); - setShowDLCompleteColumn(Settings->value("showDLCompleteColumn", !ui.downloadList->isColumnHidden(COLUMN_COMPLETED)).toBool()); - setShowDLDLSpeedColumn(Settings->value("showDLDLSpeedColumn", !ui.downloadList->isColumnHidden(COLUMN_DLSPEED)).toBool()); - setShowDLProgressColumn(Settings->value("showDLProgressColumn", !ui.downloadList->isColumnHidden(COLUMN_PROGRESS)).toBool()); - setShowDLSourcesColumn(Settings->value("showDLSourcesColumn", !ui.downloadList->isColumnHidden(COLUMN_SOURCES)).toBool()); - setShowDLStatusColumn(Settings->value("showDLStatusColumn", !ui.downloadList->isColumnHidden(COLUMN_STATUS)).toBool()); - setShowDLPriorityColumn(Settings->value("showDLPriorityColumn", !ui.downloadList->isColumnHidden(COLUMN_PRIORITY)).toBool()); - setShowDLRemainingColumn(Settings->value("showDLRemainingColumn", !ui.downloadList->isColumnHidden(COLUMN_REMAINING)).toBool()); - setShowDLDownloadTimeColumn(Settings->value("showDLDownloadTimeColumn", !ui.downloadList->isColumnHidden(COLUMN_DOWNLOADTIME)).toBool()); - setShowDLIDColumn(Settings->value("showDLIDColumn", !ui.downloadList->isColumnHidden(COLUMN_ID)).toBool()); - setShowDLLastDLColumn(Settings->value("showDLLastDLColumn", !ui.downloadList->isColumnHidden(COLUMN_LASTDL)).toBool()); - setShowDLPath(Settings->value("showDLPath", !ui.downloadList->isColumnHidden(COLUMN_PATH)).toBool()); + setShowDLSizeColumn(Settings->value("showDLSizeColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_SIZE)).toBool()); + setShowDLCompleteColumn(Settings->value("showDLCompleteColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_COMPLETED)).toBool()); + setShowDLDLSpeedColumn(Settings->value("showDLDLSpeedColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_DLSPEED)).toBool()); + setShowDLProgressColumn(Settings->value("showDLProgressColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_PROGRESS)).toBool()); + setShowDLSourcesColumn(Settings->value("showDLSourcesColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_SOURCES)).toBool()); + setShowDLStatusColumn(Settings->value("showDLStatusColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_STATUS)).toBool()); + setShowDLPriorityColumn(Settings->value("showDLPriorityColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_PRIORITY)).toBool()); + setShowDLRemainingColumn(Settings->value("showDLRemainingColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_REMAINING)).toBool()); + setShowDLDownloadTimeColumn(Settings->value("showDLDownloadTimeColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_DOWNLOADTIME)).toBool()); + setShowDLIDColumn(Settings->value("showDLIDColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_ID)).toBool()); + setShowDLLastDLColumn(Settings->value("showDLLastDLColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_LASTDL)).toBool()); + setShowDLPath(Settings->value("showDLPath", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_PATH)).toBool()); // selected tab ui.tabWidget->setCurrentIndex(Settings->value("selectedTab").toInt()); @@ -1200,18 +1210,18 @@ void TransfersDialog::processSettings(bool bLoad) // state of splitter Settings->setValue("Splitter", ui.splitter->saveState()); - Settings->setValue("showDLSizeColumn", !ui.downloadList->isColumnHidden(COLUMN_SIZE)); - Settings->setValue("showDLCompleteColumn", !ui.downloadList->isColumnHidden(COLUMN_COMPLETED)); - Settings->setValue("showDLDLSpeedColumn", !ui.downloadList->isColumnHidden(COLUMN_DLSPEED)); - Settings->setValue("showDLProgressColumn", !ui.downloadList->isColumnHidden(COLUMN_PROGRESS)); - Settings->setValue("showDLSourcesColumn", !ui.downloadList->isColumnHidden(COLUMN_SOURCES)); - Settings->setValue("showDLStatusColumn", !ui.downloadList->isColumnHidden(COLUMN_STATUS)); - Settings->setValue("showDLPriorityColumn", !ui.downloadList->isColumnHidden(COLUMN_PRIORITY)); - Settings->setValue("showDLRemainingColumn", !ui.downloadList->isColumnHidden(COLUMN_REMAINING)); - Settings->setValue("showDLDownloadTimeColumn", !ui.downloadList->isColumnHidden(COLUMN_DOWNLOADTIME)); - Settings->setValue("showDLIDColumn", !ui.downloadList->isColumnHidden(COLUMN_ID)); - Settings->setValue("showDLLastDLColumn", !ui.downloadList->isColumnHidden(COLUMN_LASTDL)); - Settings->setValue("showDLPath", !ui.downloadList->isColumnHidden(COLUMN_PATH)); + Settings->setValue("showDLSizeColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_SIZE)); + Settings->setValue("showDLCompleteColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_COMPLETED)); + Settings->setValue("showDLDLSpeedColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_DLSPEED)); + Settings->setValue("showDLProgressColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_PROGRESS)); + Settings->setValue("showDLSourcesColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_SOURCES)); + Settings->setValue("showDLStatusColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_STATUS)); + Settings->setValue("showDLPriorityColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_PRIORITY)); + Settings->setValue("showDLRemainingColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_REMAINING)); + Settings->setValue("showDLDownloadTimeColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_DOWNLOADTIME)); + Settings->setValue("showDLIDColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_ID)); + Settings->setValue("showDLLastDLColumn", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_LASTDL)); + Settings->setValue("showDLPath", !ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_PATH)); // selected tab Settings->setValue("selectedTab", ui.tabWidget->currentIndex()); @@ -1424,18 +1434,18 @@ void TransfersDialog::downloadListHeaderCustomPopupMenu( QPoint /*point*/ ) std::cerr << "TransfersDialog::downloadListHeaderCustomPopupMenu()" << std::endl; QMenu contextMnu( this ); - showDLSizeAct->setChecked(!ui.downloadList->isColumnHidden(COLUMN_SIZE)); - showDLCompleteAct->setChecked(!ui.downloadList->isColumnHidden(COLUMN_COMPLETED)); - showDLDLSpeedAct->setChecked(!ui.downloadList->isColumnHidden(COLUMN_DLSPEED)); - showDLProgressAct->setChecked(!ui.downloadList->isColumnHidden(COLUMN_PROGRESS)); - showDLSourcesAct->setChecked(!ui.downloadList->isColumnHidden(COLUMN_SOURCES)); - showDLStatusAct->setChecked(!ui.downloadList->isColumnHidden(COLUMN_STATUS)); - showDLPriorityAct->setChecked(!ui.downloadList->isColumnHidden(COLUMN_PRIORITY)); - showDLRemainingAct->setChecked(!ui.downloadList->isColumnHidden(COLUMN_REMAINING)); - showDLDownloadTimeAct->setChecked(!ui.downloadList->isColumnHidden(COLUMN_DOWNLOADTIME)); - showDLIDAct->setChecked(!ui.downloadList->isColumnHidden(COLUMN_ID)); - showDLLastDLAct->setChecked(!ui.downloadList->isColumnHidden(COLUMN_LASTDL)); - showDLPath->setChecked(!ui.downloadList->isColumnHidden(COLUMN_PATH)); + showDLSizeAct->setChecked(!ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_SIZE)); + showDLCompleteAct->setChecked(!ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_COMPLETED)); + showDLDLSpeedAct->setChecked(!ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_DLSPEED)); + showDLProgressAct->setChecked(!ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_PROGRESS)); + showDLSourcesAct->setChecked(!ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_SOURCES)); + showDLStatusAct->setChecked(!ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_STATUS)); + showDLPriorityAct->setChecked(!ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_PRIORITY)); + showDLRemainingAct->setChecked(!ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_REMAINING)); + showDLDownloadTimeAct->setChecked(!ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_DOWNLOADTIME)); + showDLIDAct->setChecked(!ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_ID)); + showDLLastDLAct->setChecked(!ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_LASTDL)); + showDLPath->setChecked(!ui.downloadList->isColumnHidden(DLListDelegate::COLUMN_PATH)); QMenu *menu = contextMnu.addMenu(tr("Columns")); menu->addAction(showDLSizeAct); @@ -1487,12 +1497,12 @@ void TransfersDialog::uploadsListHeaderCustomPopupMenu( QPoint /*point*/ ) std::cerr << "TransfersDialog::uploadsListHeaderCustomPopupMenu()" << std::endl; QMenu contextMnu( this ); - showULPeerAct->setChecked(!ui.uploadsList->isColumnHidden(COLUMN_UPEER)); - showULSizeAct->setChecked(!ui.uploadsList->isColumnHidden(COLUMN_USIZE)); - showULTransferredAct->setChecked(!ui.uploadsList->isColumnHidden(COLUMN_UTRANSFERRED)); - showULSpeedAct->setChecked(!ui.uploadsList->isColumnHidden(COLUMN_ULSPEED)); - showULProgressAct->setChecked(!ui.uploadsList->isColumnHidden(COLUMN_UPROGRESS)); - showULHashAct->setChecked(!ui.uploadsList->isColumnHidden(COLUMN_UHASH)); + showULPeerAct->setChecked(!ui.uploadsList->isColumnHidden(ULListDelegate::COLUMN_UPEER)); + showULSizeAct->setChecked(!ui.uploadsList->isColumnHidden(ULListDelegate::COLUMN_USIZE)); + showULTransferredAct->setChecked(!ui.uploadsList->isColumnHidden(ULListDelegate::COLUMN_UTRANSFERRED)); + showULSpeedAct->setChecked(!ui.uploadsList->isColumnHidden(ULListDelegate::COLUMN_ULSPEED)); + showULProgressAct->setChecked(!ui.uploadsList->isColumnHidden(ULListDelegate::COLUMN_UPROGRESS)); + showULHashAct->setChecked(!ui.uploadsList->isColumnHidden(ULListDelegate::COLUMN_UHASH)); QMenu *menu = contextMnu.addMenu(tr("Columns")); menu->addAction(showULPeerAct); @@ -1555,20 +1565,20 @@ int TransfersDialog::addULItem(int row, const FileInfo &fileInfo) // change progress column to own class for sorting //ULListModel->setItem(row, COLUMN_UPROGRESS, new ProgressItem(NULL)); - ULListModel->setData(ULListModel->index(row, COLUMN_UNAME), fileName); - ULListModel->setData(ULListModel->index(row, COLUMN_UNAME), FilesDefs::getIconFromFileType(fileName), Qt::DecorationRole); - ULListModel->setData(ULListModel->index(row, COLUMN_UHASH), fileHash); - ULListModel->setData(ULListModel->index(row, COLUMN_UHASH), fileHash, Qt::UserRole); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UNAME), fileName); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UNAME), FilesDefs::getIconFromFileType(fileName), Qt::DecorationRole); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UHASH), fileHash); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UHASH), fileHash, Qt::UserRole); } - ULListModel->setData(ULListModel->index(row, COLUMN_USIZE), QVariant((qlonglong)fileSize)); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_USIZE), QVariant((qlonglong)fileSize)); //Reset Parent info if child present - ULListModel->setData(ULListModel->index(row, COLUMN_UPEER), QVariant(QString(tr("%1 tunnels").arg(fileInfo.peers.size()))) ); - ULListModel->setData(ULListModel->index(row, COLUMN_UPEER), QIcon(), Qt::DecorationRole); - ULListModel->setData(ULListModel->index(row, COLUMN_UPEER), QVariant(), Qt::ToolTipRole); - ULListModel->setData(ULListModel->index(row, COLUMN_UTRANSFERRED), QVariant()); - ULListModel->setData(ULListModel->index(row, COLUMN_UPROGRESS), QVariant()); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UPEER), QVariant(QString(tr("%1 tunnels").arg(fileInfo.peers.size()))) ); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UPEER), QIcon(), Qt::DecorationRole); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UPEER), QVariant(), Qt::ToolTipRole); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UTRANSFERRED), QVariant()); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UPROGRESS), QVariant()); QStandardItem *ulItem = ULListModel->item(row); std::set used_rows ; @@ -1584,7 +1594,6 @@ int TransfersDialog::addULItem(int row, const FileInfo &fileInfo) //unique combination: fileHash + peerId, variant: hash + peerName (too long) QString hashFileAndPeerId = fileHash + QString::fromStdString(transferInfo.peerId.toStdString()); - qlonglong completed = transferInfo.transfered; double peerULSpeed = transferInfo.tfRate * 1024.0; @@ -1602,6 +1611,7 @@ int TransfersDialog::addULItem(int row, const FileInfo &fileInfo) peerpinfo.type = FileProgressInfo::UPLOAD_LINE ; peerpinfo.nb_chunks = peerpinfo.cmap._map.empty()?0:nb_chunks ; + qlonglong completed = 0; if(filled_chunks > 0 && nb_chunks > 0) { completed = peerpinfo.cmap.computeProgress(fileInfo.size,chunk_size) ; @@ -1618,11 +1628,11 @@ int TransfersDialog::addULItem(int row, const FileInfo &fileInfo) //Only one peer so update parent QString iconName; QString tooltip; - ULListModel->setData(ULListModel->index(row, COLUMN_UPEER), QVariant(getPeerName(transferInfo.peerId, iconName, tooltip))); - ULListModel->setData(ULListModel->index(row, COLUMN_UPEER), QIcon(iconName), Qt::DecorationRole); - ULListModel->setData(ULListModel->index(row, COLUMN_UPEER), QVariant(tooltip), Qt::ToolTipRole); - ULListModel->setData(ULListModel->index(row, COLUMN_UTRANSFERRED), QVariant(completed)); - ULListModel->setData(ULListModel->index(row, COLUMN_UPROGRESS), QVariant::fromValue(peerpinfo)); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UPEER), QVariant(getPeerName(transferInfo.peerId, iconName, tooltip))); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UPEER), QIcon(iconName), Qt::DecorationRole); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UPEER), QVariant(tooltip), Qt::ToolTipRole); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UTRANSFERRED), QVariant(completed)); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_UPROGRESS), QVariant::fromValue(peerpinfo)); } else { int row_id = addPeerToULItem(ulItem, transferInfo.peerId, hashFileAndPeerId, completed, peerULSpeed, peerpinfo); @@ -1633,7 +1643,7 @@ int TransfersDialog::addULItem(int row, const FileInfo &fileInfo) } // Update Parent UpLoad Speed - ULListModel->setData(ULListModel->index(row, COLUMN_ULSPEED), QVariant((double)peerULSpeedTotal)); + ULListModel->setData(ULListModel->index(row, ULListDelegate::COLUMN_ULSPEED), QVariant((double)peerULSpeedTotal)); // This is not optimal, but we deal with a small number of elements. The reverse order is really important, @@ -1654,7 +1664,7 @@ int TransfersDialog::addPeerToULItem(QStandardItem *ulItem, const RsPeerId& peer int childRow = -1; QStandardItem *childId = NULL; - for (int count = 0; (childId = ulItem->child(count, COLUMN_UHASH)) != NULL; ++count) { + for (int count = 0; (childId = ulItem->child(count, ULListDelegate::COLUMN_UHASH)) != NULL; ++count) { if (childId->data(Qt::UserRole).toString() == coreID) { childRow = count; break; @@ -1701,9 +1711,9 @@ int TransfersDialog::addPeerToULItem(QStandardItem *ulItem, const RsPeerId& peer childRow = ulItem->rowCount() - 1; } else { // just update the child (peer) - ulItem->child(childRow, COLUMN_ULSPEED)->setData(QVariant((double)ulspeed), Qt::DisplayRole); - ulItem->child(childRow, COLUMN_UTRANSFERRED)->setData(QVariant((qlonglong)completed), Qt::DisplayRole); - ulItem->child(childRow, COLUMN_UPROGRESS)->setData(QVariant::fromValue(peerInfo), Qt::DisplayRole); + ulItem->child(childRow, ULListDelegate::COLUMN_ULSPEED)->setData(QVariant((double)ulspeed), Qt::DisplayRole); + ulItem->child(childRow, ULListDelegate::COLUMN_UTRANSFERRED)->setData(QVariant((qlonglong)completed), Qt::DisplayRole); + ulItem->child(childRow, ULListDelegate::COLUMN_UPROGRESS)->setData(QVariant::fromValue(peerInfo), Qt::DisplayRole); } return childRow; @@ -1720,9 +1730,6 @@ void TransfersDialog::insertTransfers() { // Since downloads use an AstractItemModel, we just need to update it, while saving the selected and expanded items. - std::set expanded_hashes ; - std::set selected_hashes ; - DLListModel->update_transfers(); // Now show upload hashes. Here we use the "old" way, since the number of uploads is generally not so large. @@ -1747,7 +1754,7 @@ void TransfersDialog::insertTransfers() int rowCount = ULListModel->rowCount(); for (int row = 0; row < rowCount; ) { - RsFileHash hash ( ULListModel->item(row, COLUMN_UHASH)->data(Qt::UserRole).toString().toStdString()); + RsFileHash hash ( ULListModel->item(row, ULListDelegate::COLUMN_UHASH)->data(Qt::UserRole).toString().toStdString()); std::set::iterator hashIt = hashs.find(hash); if (hashIt == hashs.end()) { @@ -1957,18 +1964,18 @@ void TransfersDialog::pasteLink() RsCollection col ; RSLinkClipboard::pasteLinks(links,RetroShareLink::TYPE_FILE_TREE); - for(QList::const_iterator it(links.begin());it!=links.end();++it) + for(auto &it: links) { - auto ft = RsFileTree::fromRadix64((*it).radix().toStdString()); + auto ft = RsFileTree::fromRadix64(it.radix().toStdString()); col.merge_in(*ft); } links.clear(); RSLinkClipboard::pasteLinks(links,RetroShareLink::TYPE_FILE); - for(QList::const_iterator it(links.begin());it!=links.end();++it) - col.merge_in((*it).name(),(*it).size(),RsFileHash((*it).hash().toStdString())) ; + for(auto &it : links) + col.merge_in(it.name(),it.size(),RsFileHash(it.hash().toStdString())) ; - col.downloadFiles(); + RsCollectionDialog::downloadFiles(col); } void TransfersDialog::getDLSelectedItems(std::set *ids, std::set *rows) @@ -1980,13 +1987,13 @@ void TransfersDialog::getDLSelectedItems(std::set *ids, std::setclear(); if (rows) rows->clear(); - QModelIndexList selectedRows = selection->selectedRows(COLUMN_ID); + QModelIndexList selectedRows = selection->selectedRows(DLListDelegate::COLUMN_ID); int i, imax = selectedRows.count(); for (i = 0; i < imax; ++i) { QModelIndex index = selectedRows.at(i); - if (index.parent().isValid()) - index = index.model()->index(index.parent().row(), COLUMN_ID); + if (index.parent().isValid() && index.model()) + index = index.model()->index(index.parent().row(), DLListDelegate::COLUMN_ID); if (ids) { ids->insert(RsFileHash(index.data(Qt::DisplayRole).toString().toStdString())); @@ -2014,7 +2021,7 @@ void TransfersDialog::getULSelectedItems(std::set *ids, std::setitem(index.row(), COLUMN_UHASH); + QStandardItem *id = ULListModel->item(index.row(), ULListDelegate::COLUMN_UHASH); ids->insert(RsFileHash(id->data(Qt::DisplayRole).toString().toStdString())); } if (rows) { @@ -2067,22 +2074,23 @@ void TransfersDialog::dlOpenFolder() break; } + openFolder(info); +} + +void TransfersDialog::openFolder(const FileInfo& info) +{ /* make path for downloaded or downloading files */ - QFileInfo qinfo; - std::string path; - if (info.downloadStatus == FT_STATE_COMPLETE) { - path = info.path; - } else { - path = rsFiles->getPartialsDirectory(); - } + QDir directory; + + if (info.downloadStatus == FT_STATE_COMPLETE) + directory = QFileInfo(QString::fromStdString(info.path)).absoluteDir().path(); + else + directory = QDir(QString::fromStdString(rsFiles->getPartialsDirectory())); /* open folder with a suitable application */ - qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists() && qinfo.isDir()) { - if (!RsUrlHandler::openUrl(QUrl::fromLocalFile(qinfo.absoluteFilePath()))) { - std::cerr << "dlOpenFolder(): can't open folder " << path << std::endl; - } - } + + if (directory.exists() && !RsUrlHandler::openUrl(QUrl::fromLocalFile(directory.path()))) + std::cerr << "dlOpenFolder(): can't open folder " << directory.path().toStdString() << std::endl; } void TransfersDialog::ulOpenFolder() @@ -2097,19 +2105,7 @@ void TransfersDialog::ulOpenFolder() break; } - /* make path for uploading files */ - QFileInfo qinfo; - std::string path; - path = info.path.substr(0,info.path.length()-info.fname.length()); - - /* open folder with a suitable application */ - qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists() && qinfo.isDir()) { - if (!RsUrlHandler::openUrl(QUrl::fromLocalFile(qinfo.absoluteFilePath()))) { - std::cerr << "ulOpenFolder(): can't open folder " << path << std::endl; - } - } - + openFolder(info); } void TransfersDialog::dlPreviewFile() @@ -2132,7 +2128,7 @@ void TransfersDialog::dlPreviewFile() /* make path for downloaded or downloading files */ QFileInfo fileInfo; if (info.downloadStatus == FT_STATE_COMPLETE) { - fileInfo = QFileInfo(QString::fromUtf8(info.path.c_str()), QString::fromUtf8(info.fname.c_str())); + fileInfo = QFileInfo(QString::fromUtf8(info.path.c_str())); } else { fileInfo = QFileInfo(QString::fromUtf8(rsFiles->getPartialsDirectory().c_str()), QString::fromUtf8(info.hash.toStdString().c_str())); @@ -2197,7 +2193,7 @@ void TransfersDialog::dlOpenFile() /* make path for downloaded or downloading files */ std::string path; if (info.downloadStatus == FT_STATE_COMPLETE) { - path = info.path + "/" + info.fname; + path = info.path ; /* open file with a suitable application */ QFileInfo qinfo; @@ -2237,6 +2233,10 @@ void TransfersDialog::chunkStreaming() } void TransfersDialog::chunkRandom() { +#ifdef WINDOWS_SYS + if(QMessageBox::Yes != QMessageBox::warning(nullptr,tr("Warning"),tr("On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway?"),QMessageBox::Yes,QMessageBox::No)) + return; +#endif setChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; } void TransfersDialog::chunkProgressive() @@ -2387,72 +2387,72 @@ return 0.0 ; double TransfersDialog::getSpeed(int row, QStandardItemModel *model) { - return model->data(model->index(row, COLUMN_DLSPEED), Qt::DisplayRole).toDouble(); + return model->data(model->index(row, DLListDelegate::COLUMN_DLSPEED), Qt::DisplayRole).toDouble(); } QString TransfersDialog::getFileName(int row, QStandardItemModel *model) { - return model->data(model->index(row, COLUMN_NAME), Qt::DisplayRole).toString(); + return model->data(model->index(row, DLListDelegate::COLUMN_NAME), Qt::DisplayRole).toString(); } QString TransfersDialog::getStatus(int row, QStandardItemModel *model) { - return model->data(model->index(row, COLUMN_STATUS), Qt::DisplayRole).toString(); + return model->data(model->index(row, DLListDelegate::COLUMN_STATUS), Qt::DisplayRole).toString(); } QString TransfersDialog::getID(int row, QStandardItemModel *model) { - return model->data(model->index(row, COLUMN_ID), Qt::UserRole).toString().left(40); // gets only the "hash" part of the name + return model->data(model->index(row, DLListDelegate::COLUMN_ID), Qt::UserRole).toString().left(40); // gets only the "hash" part of the name } QString TransfersDialog::getID(int row, QSortFilterProxyModel *filter) { - QModelIndex index = filter->mapToSource(filter->index(row, COLUMN_ID)); + QModelIndex index = filter->mapToSource(filter->index(row, DLListDelegate::COLUMN_ID)); return filter->sourceModel()->data(index, Qt::UserRole).toString().left(40); // gets only the "hash" part of the name } QString TransfersDialog::getPriority(int row, QStandardItemModel *model) { - return model->data(model->index(row, COLUMN_PRIORITY), Qt::DisplayRole).toString(); + return model->data(model->index(row, DLListDelegate::COLUMN_PRIORITY), Qt::DisplayRole).toString(); } qlonglong TransfersDialog::getFileSize(int row, QStandardItemModel *model) { bool ok = false; - return model->data(model->index(row, COLUMN_SIZE), Qt::DisplayRole).toULongLong(&ok); + return model->data(model->index(row, DLListDelegate::COLUMN_SIZE), Qt::DisplayRole).toULongLong(&ok); } qlonglong TransfersDialog::getTransfered(int row, QStandardItemModel *model) { bool ok = false; - return model->data(model->index(row, COLUMN_COMPLETED), Qt::DisplayRole).toULongLong(&ok); + return model->data(model->index(row, DLListDelegate::COLUMN_COMPLETED), Qt::DisplayRole).toULongLong(&ok); } qlonglong TransfersDialog::getRemainingTime(int row, QStandardItemModel *model) { bool ok = false; - return model->data(model->index(row, COLUMN_REMAINING), Qt::DisplayRole).toULongLong(&ok); + return model->data(model->index(row, DLListDelegate::COLUMN_REMAINING), Qt::DisplayRole).toULongLong(&ok); } qlonglong TransfersDialog::getDownloadTime(int row, QStandardItemModel *model) { - return model->data(model->index(row, COLUMN_DOWNLOADTIME), Qt::DisplayRole).toULongLong(); + return model->data(model->index(row, DLListDelegate::COLUMN_DOWNLOADTIME), Qt::DisplayRole).toULongLong(); } qlonglong TransfersDialog::getLastDL(int row, QStandardItemModel *model) { - return model->data(model->index(row, COLUMN_LASTDL), Qt::DisplayRole).toULongLong(); + return model->data(model->index(row, DLListDelegate::COLUMN_LASTDL), Qt::DisplayRole).toULongLong(); } qlonglong TransfersDialog::getPath(int row, QStandardItemModel *model) { - return model->data(model->index(row, COLUMN_PATH), Qt::DisplayRole).toULongLong(); + return model->data(model->index(row, DLListDelegate::COLUMN_PATH), Qt::DisplayRole).toULongLong(); } QString TransfersDialog::getSources(int row, QStandardItemModel *model) { - double dblValue = model->data(model->index(row, COLUMN_SOURCES), Qt::DisplayRole).toDouble(); + double dblValue = model->data(model->index(row, DLListDelegate::COLUMN_SOURCES), Qt::DisplayRole).toDouble(); QString temp = QString("%1 (%2)").arg((int)dblValue).arg((int)((fmod(dblValue,1)*1000)+0.5)); return temp; @@ -2466,21 +2466,17 @@ void TransfersDialog::collCreate() std::set::iterator it ; getDLSelectedItems(&items, NULL); + RsFileTree tree; + for (it = items.begin(); it != items.end(); ++it) { FileInfo info; if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, info)) continue; - DirDetails details; - details.name = info.fname; - details.hash = info.hash; - details.size = info.size; - details.type = DIR_TYPE_FILE; - - dirVec.push_back(details); + tree.addFile(tree.root(),info.fname,info.hash,info.size); } - RsCollection(dirVec,RS_FILE_HINTS_LOCAL).openNewColl(this); + RsCollectionDialog::openNewCollection(tree); } void TransfersDialog::collModif() @@ -2504,12 +2500,8 @@ void TransfersDialog::collModif() /* open collection */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - collection.openColl(qinfo.absoluteFilePath()); - } - } + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath()); } } @@ -2534,12 +2526,8 @@ void TransfersDialog::collView() /* open collection */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - collection.openColl(qinfo.absoluteFilePath(), true); - } - } + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(), true); } } @@ -2564,23 +2552,29 @@ void TransfersDialog::collOpen() /* open file with a suitable application */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - if (collection.load(qinfo.absoluteFilePath())) { - collection.downloadFiles(); - return; - } - } - } + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + { + RsCollection::RsCollectionErrorCode code; + RsCollectionDialog::downloadFiles(RsCollection(qinfo.absoluteFilePath(),code)); + return; + } } } } - RsCollection collection; - if (collection.load(this)) { - collection.downloadFiles(); - } + QString fileName; + if (!misc::getOpenFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName)) + return ; + + std::cerr << "Got file name: " << fileName.toStdString() << std::endl; + + RsCollection::RsCollectionErrorCode code; + RsCollection collection(fileName,code); + + if(code == RsCollection::RsCollectionErrorCode::COLLECTION_NO_ERROR) + RsCollectionDialog::downloadFiles(collection); + else + QMessageBox::information(nullptr,tr("Error openning collection file"),RsCollection::errorString(code)); } void TransfersDialog::collAutoOpen(const QString &fileHash) @@ -2592,45 +2586,42 @@ void TransfersDialog::collAutoOpen(const QString &fileHash) if (rsFiles->FileDetails(hash, RS_FILE_HINTS_DOWNLOAD, info)) { /* make path for downloaded files */ - if (info.downloadStatus == FT_STATE_COMPLETE) { + if (info.downloadStatus == FT_STATE_COMPLETE) + { std::string path; path = info.path + "/" + info.fname; /* open file with a suitable application */ QFileInfo qinfo; qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - if (collection.load(qinfo.absoluteFilePath(), false)) { - collection.autoDownloadFiles(); - } - } - } + RsCollection::RsCollectionErrorCode err; + + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::downloadFiles(RsCollection(qinfo.absoluteFilePath(),err)); } } } } -void TransfersDialog::setShowDLSizeColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_SIZE, !show); } -void TransfersDialog::setShowDLCompleteColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_COMPLETED, !show); } -void TransfersDialog::setShowDLDLSpeedColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_DLSPEED, !show); } -void TransfersDialog::setShowDLProgressColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_PROGRESS, !show); } -void TransfersDialog::setShowDLSourcesColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_SOURCES, !show); } -void TransfersDialog::setShowDLStatusColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_STATUS, !show); } -void TransfersDialog::setShowDLPriorityColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_PRIORITY, !show); } -void TransfersDialog::setShowDLRemainingColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_REMAINING, !show); } -void TransfersDialog::setShowDLDownloadTimeColumn(bool show) { ui.downloadList->setColumnHidden(COLUMN_DOWNLOADTIME, !show); } -void TransfersDialog::setShowDLIDColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_ID, !show); } -void TransfersDialog::setShowDLLastDLColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_LASTDL, !show); } -void TransfersDialog::setShowDLPath (bool show) { ui.downloadList->setColumnHidden(COLUMN_PATH, !show); } +void TransfersDialog::setShowDLSizeColumn (bool show) { ui.downloadList->setColumnHidden(DLListDelegate::COLUMN_SIZE, !show); } +void TransfersDialog::setShowDLCompleteColumn (bool show) { ui.downloadList->setColumnHidden(DLListDelegate::COLUMN_COMPLETED, !show); } +void TransfersDialog::setShowDLDLSpeedColumn (bool show) { ui.downloadList->setColumnHidden(DLListDelegate::COLUMN_DLSPEED, !show); } +void TransfersDialog::setShowDLProgressColumn (bool show) { ui.downloadList->setColumnHidden(DLListDelegate::COLUMN_PROGRESS, !show); } +void TransfersDialog::setShowDLSourcesColumn (bool show) { ui.downloadList->setColumnHidden(DLListDelegate::COLUMN_SOURCES, !show); } +void TransfersDialog::setShowDLStatusColumn (bool show) { ui.downloadList->setColumnHidden(DLListDelegate::COLUMN_STATUS, !show); } +void TransfersDialog::setShowDLPriorityColumn (bool show) { ui.downloadList->setColumnHidden(DLListDelegate::COLUMN_PRIORITY, !show); } +void TransfersDialog::setShowDLRemainingColumn (bool show) { ui.downloadList->setColumnHidden(DLListDelegate::COLUMN_REMAINING, !show); } +void TransfersDialog::setShowDLDownloadTimeColumn(bool show) { ui.downloadList->setColumnHidden(DLListDelegate::COLUMN_DOWNLOADTIME, !show); } +void TransfersDialog::setShowDLIDColumn (bool show) { ui.downloadList->setColumnHidden(DLListDelegate::COLUMN_ID, !show); } +void TransfersDialog::setShowDLLastDLColumn (bool show) { ui.downloadList->setColumnHidden(DLListDelegate::COLUMN_LASTDL, !show); } +void TransfersDialog::setShowDLPath (bool show) { ui.downloadList->setColumnHidden(DLListDelegate::COLUMN_PATH, !show); } -void TransfersDialog::setShowULPeerColumn (bool show) { ui.uploadsList->setColumnHidden(COLUMN_UPEER, !show); } -void TransfersDialog::setShowULSizeColumn (bool show) { ui.uploadsList->setColumnHidden(COLUMN_USIZE, !show); } -void TransfersDialog::setShowULTransferredColumn(bool show) { ui.uploadsList->setColumnHidden(COLUMN_UTRANSFERRED, !show); } -void TransfersDialog::setShowULSpeedColumn (bool show) { ui.uploadsList->setColumnHidden(COLUMN_ULSPEED, !show); } -void TransfersDialog::setShowULProgressColumn (bool show) { ui.uploadsList->setColumnHidden(COLUMN_UPROGRESS, !show); } -void TransfersDialog::setShowULHashColumn (bool show) { ui.uploadsList->setColumnHidden(COLUMN_UHASH, !show); } +void TransfersDialog::setShowULPeerColumn (bool show) { ui.uploadsList->setColumnHidden(ULListDelegate::COLUMN_UPEER, !show); } +void TransfersDialog::setShowULSizeColumn (bool show) { ui.uploadsList->setColumnHidden(ULListDelegate::COLUMN_USIZE, !show); } +void TransfersDialog::setShowULTransferredColumn(bool show) { ui.uploadsList->setColumnHidden(ULListDelegate::COLUMN_UTRANSFERRED, !show); } +void TransfersDialog::setShowULSpeedColumn (bool show) { ui.uploadsList->setColumnHidden(ULListDelegate::COLUMN_ULSPEED, !show); } +void TransfersDialog::setShowULProgressColumn (bool show) { ui.uploadsList->setColumnHidden(ULListDelegate::COLUMN_UPROGRESS, !show); } +void TransfersDialog::setShowULHashColumn (bool show) { ui.uploadsList->setColumnHidden(ULListDelegate::COLUMN_UHASH, !show); } void TransfersDialog::expandAllDL() { diff --git a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.h b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.h index 87396fc81..19e2df363 100644 --- a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.h +++ b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.h @@ -173,6 +173,7 @@ signals: void playFiles(QStringList files); private: + void openFolder(const FileInfo& info); RsDownloadListModel *DLListModel; QSortFilterProxyModel *DLLFilterModel; diff --git a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.ui b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.ui index d2e7a9ab6..f329509b1 100644 --- a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.ui +++ b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.ui @@ -70,7 +70,14 @@ - + + + + 12 + 75 + true + + File Transfers @@ -213,6 +220,9 @@ true + + false + false @@ -280,6 +290,9 @@ true + + false +
@@ -294,11 +307,6 @@ - - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
LineEditClear QLineEdit diff --git a/retroshare-gui/src/gui/FileTransfer/ULListDelegate.cpp b/retroshare-gui/src/gui/FileTransfer/ULListDelegate.cpp old mode 100644 new mode 100755 index c4c9bb90d..8bddc5017 --- a/retroshare-gui/src/gui/FileTransfer/ULListDelegate.cpp +++ b/retroshare-gui/src/gui/FileTransfer/ULListDelegate.cpp @@ -25,14 +25,14 @@ Q_DECLARE_METATYPE(FileProgressInfo) +#define MAX_CHAR_TMP 128 + ULListDelegate::ULListDelegate(QObject *parent) : QAbstractItemDelegate(parent) { - ; } ULListDelegate::~ULListDelegate(void) { - ; } void ULListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const @@ -65,7 +65,7 @@ void ULListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti // draw the background color bool bDrawBackground = true; - if(index.column() == COLUMN_UPROGRESS) { + if(index.column() == COLUMN_UPROGRESS) { FileProgressInfo pinfo = index.data().value() ; bDrawBackground = (pinfo.type == FileProgressInfo::UNINIT); } @@ -101,7 +101,7 @@ void ULListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti multi *= 1024.0; } } - painter->drawText(option.rect, Qt::AlignRight, temp); + painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); break; case COLUMN_UTRANSFERRED: transferred = index.data().toLongLong(); @@ -120,7 +120,7 @@ void ULListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti multi *= 1024.0; } } - painter->drawText(option.rect, Qt::AlignRight, temp); + painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); break; case COLUMN_ULSPEED: ulspeed = index.data().toDouble(); @@ -131,9 +131,9 @@ void ULListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti temp.sprintf("%.2f", ulspeed/1024.); temp += " KB/s"; } - painter->drawText(option.rect, Qt::AlignRight, temp); + painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); break; - case COLUMN_UPROGRESS: + case COLUMN_UPROGRESS: { FileProgressInfo pinfo = index.data().value() ; if (pinfo.type == FileProgressInfo::UNINIT) @@ -143,7 +143,7 @@ void ULListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti painter->save() ; xProgressBar progressBar(pinfo,option.rect,painter,0);// the 3rd param is the color schema (0 is the default value) - QString ext = QFileInfo(QString::fromStdString(index.sibling(index.row(), COLUMN_UNAME).data().toString().toStdString())).suffix();; + QString ext = QFileInfo(QString::fromStdString(index.sibling(index.row(), COLUMN_UNAME).data().toString().toStdString())).suffix();; if (ext == "rsfc" || ext == "rsrl" || ext == "dist" || ext == "rsfb") progressBar.setColorSchema( 9); else @@ -157,17 +157,17 @@ void ULListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti } painter->drawText(option.rect, Qt::AlignCenter, newopt.text); break; - case COLUMN_UNAME: - case COLUMN_UPEER: + case COLUMN_UNAME: + case COLUMN_UPEER: // decoration value = index.data(Qt::DecorationRole); pixmap = qvariant_cast(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off); pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize)); if (pixmapRect.isValid()){ - QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft(); + QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft | Qt::AlignVCenter, pixmap.size(), option.rect).topLeft(); painter->drawPixmap(p, pixmap); } - painter->drawText(option.rect.translated(pixmap.size().width(), 0), Qt::AlignLeft, index.data().toString()); + painter->drawText(option.rect.translated(pixmap.size().width(), 0), Qt::AlignLeft | Qt::AlignVCenter, index.data().toString()); break; default: painter->drawText(option.rect, Qt::AlignCenter, index.data().toString()); @@ -181,7 +181,7 @@ QSize ULListDelegate::sizeHint(const QStyleOptionViewItem & option, const QModel { float w = QFontMetricsF(option.font).width(index.data(Qt::DisplayRole).toString()); - int S = QFontMetricsF(option.font).height() ; + int S = QFontMetricsF(option.font).height()*1.5 ; return QSize(w,S); } diff --git a/retroshare-gui/src/gui/FileTransfer/ULListDelegate.h b/retroshare-gui/src/gui/FileTransfer/ULListDelegate.h index 24a7d66d1..fc65c3a8f 100644 --- a/retroshare-gui/src/gui/FileTransfer/ULListDelegate.h +++ b/retroshare-gui/src/gui/FileTransfer/ULListDelegate.h @@ -18,43 +18,27 @@ * * *******************************************************************************/ -#ifndef ULLISTDELEGATE_H -#define ULLISTDELEGATE_H +#pragma once #include -// Defines for upload list list columns -#define COLUMN_UNAME 0 -#define COLUMN_UPEER 1 -#define COLUMN_USIZE 2 -#define COLUMN_UTRANSFERRED 3 -#define COLUMN_ULSPEED 4 -#define COLUMN_UPROGRESS 5 -#define COLUMN_UHASH 6 -#define COLUMN_UCOUNT 7 - - -#define MAX_CHAR_TMP 128 - class QModelIndex; class QPainter; +class ULListDelegate: public QAbstractItemDelegate +{ +public: + ULListDelegate(QObject *parent=0); + ~ULListDelegate(); + void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; + QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const; -class ULListDelegate: public QAbstractItemDelegate { - - Q_OBJECT - - public: - ULListDelegate(QObject *parent=0); - ~ULListDelegate(); - void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; - QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const; - - private: - - public slots: - - signals: + static constexpr int COLUMN_UNAME = 0; + static constexpr int COLUMN_UPEER = 1; + static constexpr int COLUMN_USIZE = 2; + static constexpr int COLUMN_UTRANSFERRED = 3; + static constexpr int COLUMN_ULSPEED = 4; + static constexpr int COLUMN_UPROGRESS = 5; + static constexpr int COLUMN_UHASH = 6; + static constexpr int COLUMN_UCOUNT = 7; }; -#endif - diff --git a/retroshare-gui/src/gui/FriendServerControl.cpp b/retroshare-gui/src/gui/FriendServerControl.cpp new file mode 100644 index 000000000..7b031e7e2 --- /dev/null +++ b/retroshare-gui/src/gui/FriendServerControl.cpp @@ -0,0 +1,362 @@ +/******************************************************************************* + * gui/FriendServer.cpp * + * * + * Copyright (c) 2021 Retroshare Team * + * * + * 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 . * + * * + *******************************************************************************/ + +#include +#include +#include +#include +#include + +#include "retroshare/rsfriendserver.h" +#include "retroshare/rstor.h" + +#include "util/qtthreadsutils.h" +#include "util/misc.h" +#include "gui/common/FilesDefs.h" + +#include "FriendServerControl.h" + +#include + +#define ICON_STATUS_UNKNOWN ":/images/ledoff1.png" +#define ICON_STATUS_OK ":/images/ledon1.png" + +#define NAME_COLUMN 0 +#define NODE_COLUMN 1 +#define ADDR_COLUMN 2 +#define STAT_COLUMN 3 + +/** Constructor */ +FriendServerControl::FriendServerControl(QWidget *parent) + : MainPage(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + friendServerOnOff_CB->setEnabled(false); // until FS is connected. + mCurrentlyCheckingServerAddress = false; + + if(!rsFriendServer) + { + setEnabled(false); + return; + } + + int H = QFontMetricsF(torServerAddress_LE->font()).height(); + + QString help_str = tr("\ +

  Friend Server

\ +

This configuration panel allows you to specify the onion address of a \ + friend server. Retroshare will talk to that server anonymously through Tor \ + and use it to acquire a fixed number of friends.

\ +

The friend server will continue supplying new friends until that number is reached \ + in particular if you add your own friends manually, the friend server may become useless \ + and you will save bandwidth disabling it. When disabling it, you will keep existing friends.

\ +

The friend server only knows your peer ID and profile public key. It doesn't know your IP address.

\ + " + ).arg(QString::number(2*H), QString::number(2*H)) ; + + registerHelpButton(helpButton,help_str,"Friend Server") ; + + mConnectionCheckTimer = new QTimer; + + whileBlocking(autoAccept_CB)->setChecked(rsFriendServer->autoAddFriends()); + + // Init values + + whileBlocking(torServerFriendsToRequest_SB)->setValue(rsFriendServer->friendsToRequest()); + + // Connect slignals/slots + + QObject::connect(friendServerOnOff_CB,SIGNAL(toggled(bool)),this,SLOT(onOnOffClick(bool))); + QObject::connect(torServerFriendsToRequest_SB,SIGNAL(valueChanged(int)),this,SLOT(onFriendsToRequestChanged(int))); + QObject::connect(torServerAddress_LE,SIGNAL(textEdited(const QString&)),this,SLOT(onOnionAddressEdit(const QString&))); + QObject::connect(torServerPort_SB,SIGNAL(valueChanged(int)),this,SLOT(onOnionPortEdit(int))); + QObject::connect(autoAccept_CB,SIGNAL(toggled(bool)),this,SLOT(onAutoAddFriends(bool))); + + QObject::connect(mConnectionCheckTimer,SIGNAL(timeout()),this,SLOT(checkServerAddress())); + QObject::connect(status_TW, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(launchStatusContextMenu(QPoint))); + + mCheckingServerMovie = new QMovie(":/images/loader/circleball-16.gif"); + + // Do not block signal for these two, since we want to trigger a test to initialise the online status. + torServerAddress_LE->setText(QString::fromStdString(rsFriendServer->friendsServerAddress().c_str())); + torServerPort_SB->setValue(rsFriendServer->friendsServerPort()); + + updateFriendServerStatusIcon(false); + + makeFriend_ACT = new QAction(tr("Make friend")); // makes SSL-only friend with the peer + + QObject::connect(makeFriend_ACT,SIGNAL(triggered()),this,SLOT(makeFriend())); + + mEventHandlerId_fs = 0; + + rsEvents->registerEventsHandler( [this](std::shared_ptr event) + { + RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); + }, mEventHandlerId_fs, RsEventType::FRIEND_SERVER ); + + mEventHandlerId_peer = 0; + + rsEvents->registerEventsHandler( [this](std::shared_ptr event) + { + RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); + }, mEventHandlerId_peer, RsEventType::PEER_CONNECTION ); +} + +void FriendServerControl::onAutoAddFriends(bool b) +{ + rsFriendServer->setAutoAddFriends(b); +} +void FriendServerControl::handleEvent_main_thread(std::shared_ptr event) +{ + { + const RsFriendServerEvent *fe = dynamic_cast(event.get()); + + if(fe) + switch(fe->mFriendServerEventType) + { + case RsFriendServerEventCode::PEER_INFO_CHANGED: updateContactsStatus(); + break; + + case RsFriendServerEventCode::FRIEND_SERVER_STATUS_CHANGED: updateFriendServerStatusIcon(fe->mFriendServerStatus == RsFriendServerStatus::ONLINE); + break; + + default: + case RsFriendServerEventCode::UNKNOWN: break; + } + } + + { + const RsConnectionEvent *pe = dynamic_cast(event.get()); + + if(pe) + switch(pe->mConnectionInfoCode) + { + case RsConnectionEventCode::PEER_ADDED: + case RsConnectionEventCode::PEER_REMOVED: + case RsConnectionEventCode::PEER_CONNECTED: updateContactsStatus(); + break; + + default: ; + } + } +} + +FriendServerControl::~FriendServerControl() +{ + delete mCheckingServerMovie; + delete mConnectionCheckTimer; + + rsEvents->unregisterEventsHandler(mEventHandlerId_fs); + rsEvents->unregisterEventsHandler(mEventHandlerId_peer); +} + +void FriendServerControl::launchStatusContextMenu(QPoint p) +{ + RsPeerId peer_id = getCurrentPeer(); + + RsPeerDetails det; + if(rsPeers->getPeerDetails(peer_id,det) && det.accept_connection) + return; + + QMenu contextMnu(this); + contextMnu.addAction(makeFriend_ACT); + + contextMnu.exec(QCursor::pos()); +} +void FriendServerControl::onOnOffClick(bool b) +{ + if(b) + { + if(passphrase_LE->text().isNull()) + { + QMessageBox::critical(nullptr,tr("Missing profile passphrase."),tr("Your profile passphrase is missing. Please enter is in the field below before enabling the friend server.")); + whileBlocking(friendServerOnOff_CB)->setCheckState(Qt::Unchecked); + return; + } + rsFriendServer->setProfilePassphrase(passphrase_LE->text().toStdString()); + rsFriendServer->startServer(); + } + else + rsFriendServer->stopServer(); +} +void FriendServerControl::onOnionPortEdit(int) +{ + // Setup timer to auto-check the friend server address + + mConnectionCheckTimer->stop(); + mConnectionCheckTimer->setSingleShot(true); + mConnectionCheckTimer->setInterval(5000); // check in 5 secs unless something is changed in the mean time. + + mConnectionCheckTimer->start(); + + if(mCheckingServerMovie->fileName() != QString(":/images/loader/circleball-16.gif" )) + { + mCheckingServerMovie->setFileName(":/images/loader/circleball-16.gif"); + mCheckingServerMovie->start(); + } +} + +void FriendServerControl::onOnionAddressEdit(const QString&) +{ + while(mCurrentlyCheckingServerAddress) + { + std::cerr << " waiting for free slot" << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(500)); // wait for ongoing check to finish. + } + + std::cerr << "Resetting connection proxy timer" << std::endl; + + // Setup timer to auto-check the friend server address + mConnectionCheckTimer->setSingleShot(true); + mConnectionCheckTimer->setInterval(5000); // check in 5 secs unless something is changed in the mean time. + mConnectionCheckTimer->start(); +} + +void FriendServerControl::checkServerAddress() +{ + std::cerr << "In checkServerAddress() ..." << std::endl; + + mCurrentlyCheckingServerAddress = true; + + serverStatusCheckResult_LB->setMovie(mCheckingServerMovie); + serverStatusCheckResult_LB->setToolTip(tr("Trying to contact friend server\nThis may take up to 1 min.")) ; + mCheckingServerMovie->setFileName(":/images/loader/circleball-16.gif"); + mCheckingServerMovie->start(); + + RsThread::async( [this]() + { + auto port = torServerPort_SB->value(); + auto addr = torServerAddress_LE->text().toStdString(); + + std::cerr << "calling sync test..." << std::endl; + bool succeed = rsFriendServer->checkServerAddress(addr,port,5000); + std::cerr << "result is " << succeed << std::endl; + + RsQThreadUtils::postToObject( [addr,port,succeed,this]() + { + if(succeed) + rsFriendServer->setServerAddress(addr,port); + + mCheckingServerMovie->stop(); + updateFriendServerStatusIcon(succeed); + mCurrentlyCheckingServerAddress = false; + + },this); + }); +} + +void FriendServerControl::onNbFriendsToRequestsChanged(int n) +{ + rsFriendServer->setFriendsToRequest(n); +} + +void FriendServerControl::updateFriendServerStatusIcon(bool ok) +{ + std::cerr << "updating proxy status icon" << std::endl; + + if(ok) + { + serverStatusCheckResult_LB->setToolTip(tr("Friend server is currently reachable.")) ; + serverStatusCheckResult_LB->setPixmap(QPixmap(ICON_STATUS_OK)); + friendServerOnOff_CB->setEnabled(true); + status_TW->setEnabled(true); + } + else + { + rsFriendServer->stopServer(); + serverStatusCheckResult_LB->setToolTip(tr("The proxy is not enabled or broken.\nAre all services up and running fine??\nAlso check your ports!")) ; + serverStatusCheckResult_LB->setPixmap(QPixmap(ICON_STATUS_UNKNOWN)); + friendServerOnOff_CB->setChecked(false); + friendServerOnOff_CB->setEnabled(false); + status_TW->setEnabled(false); + } +} + +void FriendServerControl::updateContactsStatus() +{ + std::map pinfo = rsFriendServer->getPeersInfo(); + + status_TW->clear(); + int row = 0; + status_TW->setRowCount(pinfo.size()); + status_TW->setColumnCount(4); + + status_TW->setHorizontalHeaderItem(NAME_COLUMN,new QTableWidgetItem(QObject::tr("Name"))); + status_TW->setHorizontalHeaderItem(NODE_COLUMN,new QTableWidgetItem(QObject::tr("Node"))); + status_TW->setHorizontalHeaderItem(ADDR_COLUMN,new QTableWidgetItem(QObject::tr("Address"))); + status_TW->setHorizontalHeaderItem(STAT_COLUMN,new QTableWidgetItem(QObject::tr("Status"))); + + for(auto it:pinfo) + { + uint32_t err_code=0; + RsPeerDetails details; + + rsPeers->parseShortInvite(it.second.mInvite,details,err_code); + + status_TW->setItem(row,NAME_COLUMN,new QTableWidgetItem(QString::fromStdString(details.name))); + status_TW->setItem(row,NODE_COLUMN,new QTableWidgetItem(QString::fromStdString(details.id.toStdString()))); + status_TW->setItem(row,ADDR_COLUMN,new QTableWidgetItem(QString::fromStdString(details.hiddenNodeAddress)+":"+QString::number(details.hiddenNodePort))); + + QString status_string; + if(details.accept_connection) + status_string += QString("Friend"); + else + status_string += QString("Not friend"); + + status_string += QString(" / "); + + switch(it.second.mPeerLevel) + { + case RsFriendServer::PeerFriendshipLevel::NO_KEY: status_string += "Doesn't have my key" ; break; + case RsFriendServer::PeerFriendshipLevel::HAS_KEY: status_string += "Has my key" ; break; + case RsFriendServer::PeerFriendshipLevel::HAS_ACCEPTED_KEY: status_string += "Has friended me" ; break; + default: + case RsFriendServer::PeerFriendshipLevel::UNKNOWN: status_string += "Unkn" ; break; + } + + status_TW->setItem(row,STAT_COLUMN,new QTableWidgetItem(status_string)); + + row++; + } +} + +RsPeerId FriendServerControl::getCurrentPeer() +{ + QTableWidgetItem *item = status_TW->currentItem(); + + if(!item) + return RsPeerId(); + + return RsPeerId(status_TW->item(item->row(),NODE_COLUMN)->text().toStdString()); +} +void FriendServerControl::makeFriend() +{ + RsPeerId peer_id = getCurrentPeer(); + + rsFriendServer->allowPeer(peer_id); +} + + + + + + diff --git a/retroshare-gui/src/gui/common/StyledElidedLabel.cpp b/retroshare-gui/src/gui/FriendServerControl.h similarity index 52% rename from retroshare-gui/src/gui/common/StyledElidedLabel.cpp rename to retroshare-gui/src/gui/FriendServerControl.h index 43fc85220..ddc66ee8a 100644 --- a/retroshare-gui/src/gui/common/StyledElidedLabel.cpp +++ b/retroshare-gui/src/gui/FriendServerControl.h @@ -1,7 +1,7 @@ /******************************************************************************* - * gui/common/StyleElidedLabel.cpp * + * gui/NetworkView.h * * * - * Copyright (c) 2014, RetroShare Team * + * Copyright (c) 2008 Robert Fernie * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Affero General Public License as * @@ -18,29 +18,48 @@ * * *******************************************************************************/ -#include -#include "StyledElidedLabel.h" +#pragma once -/** Constructor */ -StyledElidedLabel::StyledElidedLabel(QWidget *parent) - : ElidedLabel(parent), _lastFactor(-1) -{ -} +#include -StyledElidedLabel::StyledElidedLabel(const QString &text, QWidget *parent) - : ElidedLabel(text, parent), _lastFactor(-1) -{ -} +#include "retroshare/rsevents.h" -void StyledElidedLabel::setFontSizeFactor(int factor) +#include "retroshare-gui/mainpage.h" +#include "ui_FriendServerControl.h" + +class FriendServerControl : public MainPage, public Ui::FriendServerControl { - int newFactor = factor; - if (factor > 0) { - if (_lastFactor > 0) newFactor = 100 + factor - _lastFactor; - _lastFactor = factor; - QFont f = font(); - qreal fontSize = newFactor * f.pointSizeF() / 100; - f.setPointSizeF(fontSize); - setFont(f); - } -} + Q_OBJECT + +public: + FriendServerControl(QWidget *parent = 0); + virtual ~FriendServerControl(); + +protected slots: + void onOnOffClick(bool b); + void onOnionAddressEdit(const QString &); + void onOnionPortEdit(int); + void onNbFriendsToRequestsChanged(int n); + void checkServerAddress(); + void onAutoAddFriends(bool b); + void launchStatusContextMenu(QPoint p); + void makeFriend(); + +private: + RsPeerId getCurrentPeer(); + void updateContactsStatus(); + void updateFriendServerStatusIcon(bool ok); + void handleEvent_main_thread(std::shared_ptr event); + + QTimer *mConnectionCheckTimer; + QMovie *mCheckingServerMovie; + bool mCurrentlyCheckingServerAddress; + + RsEventsHandlerId_t mEventHandlerId_fs; + RsEventsHandlerId_t mEventHandlerId_peer; + + QAction *makeFriend_ACT; + QAction *unmakeFriend_ACT; + QAction *removePeer_ACT; + QAction *removePeerPermanently_ACT; +}; diff --git a/retroshare-gui/src/gui/FriendServerControl.ui b/retroshare-gui/src/gui/FriendServerControl.ui new file mode 100644 index 000000000..e3faac36b --- /dev/null +++ b/retroshare-gui/src/gui/FriendServerControl.ui @@ -0,0 +1,241 @@ + + + FriendServerControl + + + + 0 + 0 + 620 + 499 + + + + + + + + + Server onion address: + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + Onion address of the friend server + + + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + 1025 + + + 65536 + + + 2017 + + + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Maximum + + + + 40 + 20 + + + + + + + + Qt::NoFocus + + + + :/icons/help_64.png:/icons/help_64.png + + + true + + + false + + + true + + + + + + + + + + + + + + Retroshare passphrase: + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + QLineEdit::Password + + + Your retroshare passphrase + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + On/Off + + + + + + + Qt::Horizontal + + + + 302 + 26 + + + + + + + + Friends to request: + + + + + + + 1 + + + 15 + + + 5 + + + + + + + Auto accept received certificates as friends + + + Auto-accept + + + + + + + + + + Qt::CustomContextMenu + + + + Name + + + + + Node ID + + + + + Address + + + + + Status + + + + + + + + Qt::Vertical + + + + 20 + 380 + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/FriendsDialog.cpp b/retroshare-gui/src/gui/FriendsDialog.cpp index 660f13fa7..532a87f4a 100644 --- a/retroshare-gui/src/gui/FriendsDialog.cpp +++ b/retroshare-gui/src/gui/FriendsDialog.cpp @@ -27,6 +27,7 @@ #include #include +#include #include "chat/ChatUserNotify.h" #include "connect/ConnectFriendWizard.h" @@ -44,6 +45,9 @@ #include "NetworkView.h" #include "NetworkDialog.h" #include "gui/common/NewFriendList.h" +#ifdef RS_EMBEDED_FRIEND_SERVER +#include "gui/FriendServerControl.h" +#endif #include "gui/Identity/IdDialog.h" /* Images for Newsfeed icons */ //#define IMAGE_NEWSFEED "" @@ -88,6 +92,10 @@ FriendsDialog::FriendsDialog(QWidget *parent) : MainPage(parent) ui.avatar->setFrameType(AvatarWidget::STATUS_FRAME); ui.tabWidget->setTabPosition(QTabWidget::North); +#ifdef RS_EMBEDED_FRIEND_SERVER + if(RsAccounts::isTorAuto()) + ui.tabWidget->addTab(friendServerControl = new FriendServerControl(),QIcon(IMAGE_PEERS), tr("Friend Server")); +#endif ui.tabWidget->addTab(networkView = new NetworkView(),QIcon(IMAGE_NETWORK2), tr("Network graph")); ui.tabWidget->addTab(networkDialog = new NetworkDialog(),QIcon(IMAGE_PEERS), tr("Keyring")); @@ -117,25 +125,24 @@ FriendsDialog::FriendsDialog(QWidget *parent) : MainPage(parent) // add self nick and Avatar to Friends. RsPeerDetails pd ; - if (rsPeers->getPeerDetails(rsPeers->getOwnId(),pd)) { + if (rsPeers->getPeerDetails(rsPeers->getOwnId(),pd)) ui.nicknameLabel->setText(QString::fromUtf8(pd.name.c_str()) + " (" + QString::fromUtf8(pd.location.c_str())+")"); - } - QString hlp_str = tr( - "

  Network

\ -

The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. \ -

\ -

You can group nodes together to allow a finer level of information access, for instance to only allow \ - some nodes to see some of your files.

\ -

On the right, you will find 3 useful tabs: \ -

    \ -
  • Broadcast sends messages to all connected nodes at once
  • \ -
  • Local network graph shows the network around you, based on discovery information
  • \ -
  • Keyring contains node keys you collected, mostly forwarded to you by your friend nodes
  • \ -

\ - ") ; + int H = misc::getFontSizeFactor("HelpButton").height(); + QString hlp_str = tr( + "

  Network

" + "

The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.

" + "

You can group nodes together to allow a finer level of information access, for instance to only allow" + " some nodes to see some of your files.

" + "

On the right, you will find 3 useful tabs:" + "

    " + "
  • Broadcast sends messages to all connected nodes at once
  • " + "
  • Local network graph shows the network around you, based on discovery information
  • " + "
  • Keyring contains node keys you collected, mostly forwarded to you by your friend nodes
  • " + "

" + ).arg(QString::number(2*H)); - registerHelpButton(ui.helpButton, hlp_str,"FriendsDialog") ; + registerHelpButton(ui.helpButton, hlp_str,"FriendsDialog") ; } FriendsDialog::~FriendsDialog () @@ -252,13 +259,9 @@ void FriendsDialog::loadmypersonalstatus() QString statustring = QString::fromUtf8(rsMsgs->getCustomStateString().c_str()); if (statustring.isEmpty()) - { ui.mypersonalstatusLabel->setText(tr("Set your status message here.")); - } else - { ui.mypersonalstatusLabel->setText(statustring); - } } void FriendsDialog::clearChatNotify() @@ -275,13 +278,11 @@ void FriendsDialog::statusmessage() /*static*/ bool FriendsDialog::isGroupChatActive() { FriendsDialog *friendsDialog = dynamic_cast(MainWindow::getPage(MainWindow::Friends)); - if (!friendsDialog) { + if (!friendsDialog) return false; - } - if (friendsDialog->ui.tabWidget->currentWidget() == friendsDialog->ui.groupChatTab) { + if (friendsDialog->ui.tabWidget->currentWidget() == friendsDialog->ui.groupChatTab) return true; - } return false; } diff --git a/retroshare-gui/src/gui/FriendsDialog.h b/retroshare-gui/src/gui/FriendsDialog.h index bd8979224..7e86669b8 100644 --- a/retroshare-gui/src/gui/FriendsDialog.h +++ b/retroshare-gui/src/gui/FriendsDialog.h @@ -30,6 +30,7 @@ class NetworkDialog; class NetworkView; class IdDialog; class CirclesDialog; +class FriendServerControl; class FriendsDialog : public MainPage { @@ -64,7 +65,8 @@ public: NetworkDialog *networkDialog ; NetworkView *networkView ; - + FriendServerControl *friendServerControl ; + IdDialog *idDialog; private slots: diff --git a/retroshare-gui/src/gui/FriendsDialog.ui b/retroshare-gui/src/gui/FriendsDialog.ui index b32c71465..a8e8217fc 100644 --- a/retroshare-gui/src/gui/FriendsDialog.ui +++ b/retroshare-gui/src/gui/FriendsDialog.ui @@ -10,7 +10,7 @@ 491 - + 0 @@ -37,7 +37,7 @@ QFrame::Sunken - + 2 @@ -70,14 +70,21 @@ - + + + + 12 + 75 + true + + Network - + Qt::Horizontal @@ -95,7 +102,7 @@ Qt::NoFocus - + :/icons/help_64.png:/icons/help_64.png @@ -115,22 +122,22 @@ Qt::Horizontal - + 1 - + - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + 1 @@ -192,7 +199,14 @@ - + + + + 20 + 75 + true + + Nickname (Location) @@ -240,7 +254,7 @@ Broadcast - + @@ -362,11 +376,6 @@
gui/common/AvatarWidget.h
1
- - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
ChatWidget QWidget @@ -380,9 +389,9 @@ 1 - StyledElidedLabel + ElidedLabel QLabel -
gui/common/StyledElidedLabel.h
+
gui/common/ElidedLabel.h
NewFriendList @@ -392,8 +401,8 @@
- + diff --git a/retroshare-gui/src/gui/GenCertDialog.cpp b/retroshare-gui/src/gui/GenCertDialog.cpp index e106146fb..0f318049d 100644 --- a/retroshare-gui/src/gui/GenCertDialog.cpp +++ b/retroshare-gui/src/gui/GenCertDialog.cpp @@ -33,27 +33,27 @@ #include #include "gui/settings/rsharesettings.h" -#include "TorControl/TorManager.h" #include "util/misc.h" #include "gui/common/FilesDefs.h" -#include -#include -#include -#include -#include +#include "retroshare/rstor.h" +#include "retroshare/rsidentity.h" +#include "retroshare/rsinit.h" +#include "retroshare/rsnotify.h" +#include "rsserver/rsaccounts.h" +#include "util/rsrandom.h" #include #include #include #define IMAGE_GOOD ":/images/accepted16.png" -#define IMAGE_BAD ":/images/cancel.png" +#define IMAGE_BAD ":/icons/cancel.svg" class EntropyCollectorWidget: public QTextBrowser { public: - EntropyCollectorWidget(QProgressBar *pr,QWidget *p = NULL) + explicit EntropyCollectorWidget(QProgressBar *pr,QWidget *p = NULL) : QTextBrowser(p) { progress = pr ; @@ -150,7 +150,7 @@ GenCertDialog::GenCertDialog(bool onlyGenerateIdentity, QWidget *parent) connect(ui.node_input, SIGNAL(textChanged(QString)), this, SLOT(updateCheckLabels())); connect(ui.reuse_existing_node_CB, SIGNAL(toggled(bool)), this, SLOT(updateCheckLabels())); - connect(ui.cbUseBob, SIGNAL(clicked(bool)), this, SLOT(useBobChecked(bool)));; + connect(ui.cbUseBob, SIGNAL(clicked(bool)), this, SLOT(useI2pChecked(bool)));; entropy_timer = new QTimer ; entropy_timer->start(20) ; @@ -251,7 +251,7 @@ void GenCertDialog::initKeyList() void GenCertDialog::mouseMoveEvent(QMouseEvent *e) { - std::cerr << "Mouse : " << e->x() << ", " << e->y() << std::endl; + //std::cerr << "Mouse : " << e->x() << ", " << e->y() << std::endl; QDialog::mouseMoveEvent(e) ; } @@ -288,8 +288,6 @@ void GenCertDialog::setupState() break; } - //ui.no_node_label->setVisible(false); - setWindowTitle(generate_new?tr("Create new profile and new Retroshare node"):tr("Create new Retroshare node")); //ui.headerFrame->setHeaderText(generate_new?tr("Create a new profile and node"):tr("Create a new node")); @@ -300,15 +298,9 @@ void GenCertDialog::setupState() ui.genPGPuser->setVisible(adv_state && haveGPGKeys && !generate_new) ; - //ui.genprofileinfo_label->setVisible(false); - //ui.no_gpg_key_label->setText(tr("Welcome to Retroshare. Before you can proceed you need to create a profile and associate a node with it. To do so please fill out this form.\nAlternatively you can import a (previously exported) profile. Just uncheck \"Create a new profile\"")); - //no_gpg_key_label->setVisible(false); - ui.name_label->setVisible(true); ui.name_input->setVisible(generate_new); - //ui.header_label->setVisible(false) ; - ui.nickname_label->setVisible(adv_state && !mOnlyGenerateIdentity); ui.nickname_input->setVisible(adv_state && !mOnlyGenerateIdentity); @@ -341,9 +333,9 @@ void GenCertDialog::setupState() ui.hiddenport_spinBox->setVisible(hidden_state && !tor_auto); ui.cbUseBob->setVisible(hidden_state && !tor_auto); -#ifndef RS_USE_I2P_BOB +#ifndef RS_USE_I2P_SAM3 ui.cbUseBob->setDisabled(true); - ui.cbUseBob->setToolTip(tr("BOB support is not available")); + ui.cbUseBob->setToolTip(tr("SAMv3 support is not available")); #endif if(!mAllFieldsOk) @@ -352,8 +344,8 @@ void GenCertDialog::setupState() ui.genButton->setVisible(false) ; ui.generate_label->setVisible(false) ; - ui.info_label->setText("Please choose a profile name and password...") ; - ui.info_label->setVisible(true) ; + ui.info_Label->setText("Please choose a profile name and password...") ; + ui.info_Label->setVisible(true) ; } else if(!mEntropyOk) { @@ -361,8 +353,8 @@ void GenCertDialog::setupState() ui.genButton->setVisible(false) ; ui.generate_label->setVisible(false) ; - ui.info_label->setText("Please move your mouse randomly to generate enough random data to create your profile.") ; - ui.info_label->setVisible(true) ; + ui.info_Label->setText("Please move your mouse randomly to generate enough random data to create your profile.") ; + ui.info_Label->setVisible(true) ; } else { @@ -371,7 +363,7 @@ void GenCertDialog::setupState() ui.genButton->setToolTip(tr("Click to create your node and/or profile")) ; ui.genButton->setVisible(true) ; ui.generate_label->setVisible(false) ; - ui.info_label->setVisible(false) ; + ui.info_Label->setVisible(false) ; } } @@ -407,7 +399,7 @@ void GenCertDialog::updateCheckLabels() ui.node_name_check_LB ->setPixmap(bad) ; } - if(!generate_new || ui.name_input->text().length() >= 3) + if(!generate_new || ui.name_input->text().trimmed().length() >= 3) ui.profile_name_check_LB ->setPixmap(good) ; else { @@ -440,10 +432,10 @@ void GenCertDialog::updateCheckLabels() setupState(); } -void GenCertDialog::useBobChecked(bool checked) +void GenCertDialog::useI2pChecked(bool checked) { if (checked) { - ui.hiddenaddr_input->setPlaceholderText(tr("I2P instance address with BOB enabled")); + ui.hiddenaddr_input->setPlaceholderText(tr("I2P instance address with SAMv3 enabled")); ui.hiddenaddr_label->setText(tr("I2P instance address")); ui.hiddenport_spinBox->setEnabled(false); @@ -528,7 +520,7 @@ void GenCertDialog::genPerson() bool isHiddenLoc = (ui.nodeType_CB->currentIndex()>0); bool isAutoTor = (ui.nodeType_CB->currentIndex()==1); - if(isAutoTor && !Tor::TorManager::isTorAvailable()) + if(isAutoTor && !RsTor::isTorAvailable()) { QMessageBox::critical(this,tr("Tor is not available"),tr("No Tor executable has been found on your system. You need to install Tor before creating a hidden identity.")) ; return ; @@ -539,12 +531,12 @@ void GenCertDialog::genPerson() std::string hl = ui.hiddenaddr_input->text().toStdString(); uint16_t port = ui.hiddenport_spinBox->value(); - bool useBob = ui.cbUseBob->isChecked(); + bool useI2p = ui.cbUseBob->isChecked(); - if (useBob && hl.empty()) + if (useI2p && hl.empty()) hl = "127.0.0.1"; - RsInit::SetHiddenLocation(hl, port, useBob); /* parses it */ + RsInit::SetHiddenLocation(hl, port, useI2p); /* parses it */ } @@ -591,7 +583,6 @@ void GenCertDialog::genPerson() //generate a new gpg key std::string err_string; //_key_label->setText(tr("Generating new node key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. \n\nFill in your password when asked, to sign your new key.")); - //ui.no_gpg_key_label->show(); //ui.reuse_existing_node_CB->hide(); ui.name_label->hide(); ui.name_input->hide(); @@ -609,7 +600,6 @@ void GenCertDialog::genPerson() ui.node_input->hide(); ui.genButton->hide(); ui.importIdentity_PB->hide(); - //ui.genprofileinfo_label->hide(); ui.nodeType_CB->hide(); //ui.adv_checkbox->hide(); ui.keylength_label->hide(); @@ -619,7 +609,9 @@ void GenCertDialog::genPerson() QCoreApplication::processEvents(); QAbstractEventDispatcher* ed = QAbstractEventDispatcher::instance(); - std::cout << "Waiting ed->processEvents()" << std::endl; +#ifdef DEBUG_GENCERTDIALOG + std::cout << "Waiting ed->processEvents()" << std::endl; +#endif time_t waitEnd = time(NULL) + 10;//Wait no more than 10 sec to processEvents if (ed->hasPendingEvents()) while(ed->processEvents(QEventLoop::AllEvents) && (time(NULL) < waitEnd)); @@ -657,7 +649,7 @@ void GenCertDialog::genPerson() { /* complete the process */ RsInit::LoadPassword(sslPasswd); - if (Rshare::loadCertificate(sslId, false)) { + if (RsApplication::loadCertificate(sslId, false)) { // Normally we should clear the cached passphrase as soon as possible. However,some other GUI components may still need it at start. // (csoler) This is really bad: we have to guess that 30 secs will be enough. I have no better way to do this. diff --git a/retroshare-gui/src/gui/GenCertDialog.h b/retroshare-gui/src/gui/GenCertDialog.h index afd82e5f0..6d9d3610a 100644 --- a/retroshare-gui/src/gui/GenCertDialog.h +++ b/retroshare-gui/src/gui/GenCertDialog.h @@ -31,7 +31,7 @@ class GenCertDialog : public QDialog public: /** Default constructor */ - GenCertDialog(bool onlyGenerateIdentity, QWidget *parent = 0); + explicit GenCertDialog(bool onlyGenerateIdentity, QWidget *parent = 0); virtual ~GenCertDialog() ; virtual void mouseMoveEvent(QMouseEvent *e) ; @@ -44,7 +44,7 @@ private slots: void switchReuseExistingNode(); void grabMouse(); void updateCheckLabels(); - void useBobChecked(bool checked); + void useI2pChecked(bool checked); private: void initKeyList(); diff --git a/retroshare-gui/src/gui/GenCertDialog.ui b/retroshare-gui/src/gui/GenCertDialog.ui index 96f09cae2..a747709d3 100644 --- a/retroshare-gui/src/gui/GenCertDialog.ui +++ b/retroshare-gui/src/gui/GenCertDialog.ui @@ -111,7 +111,7 @@ - + 0 @@ -187,7 +187,7 @@ - + 0 @@ -245,6 +245,12 @@ 0 + + + 75 + true + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> @@ -303,6 +309,12 @@ 0 + + + 75 + true + + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> @@ -340,6 +352,12 @@ 32 + + + 75 + true + + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> @@ -352,13 +370,19 @@ - + 0 0 + + + 75 + true + + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. @@ -417,6 +441,12 @@ 0 + + + 75 + true + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> @@ -456,6 +486,12 @@ 32 + + + 75 + true + + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> @@ -479,6 +515,12 @@ 0 + + + 75 + true + + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -496,7 +538,7 @@ - Use BOB + Use I2P @@ -510,6 +552,12 @@ 0 + + + 75 + true + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> @@ -532,6 +580,8 @@ 12 + 75 + true @@ -721,7 +771,12 @@ - + + + + 12 + + TextLabel @@ -751,6 +806,13 @@ + + + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
+
name_input node_input @@ -764,8 +826,8 @@ importIdentity_PB - + diff --git a/retroshare-gui/src/gui/GetStartedDialog.cpp b/retroshare-gui/src/gui/GetStartedDialog.cpp index d525808b6..399cc36d7 100644 --- a/retroshare-gui/src/gui/GetStartedDialog.cpp +++ b/retroshare-gui/src/gui/GetStartedDialog.cpp @@ -53,19 +53,19 @@ GetStartedDialog::GetStartedDialog(QWidget *parent) mFirstShow = true; - connect(ui.inviteCheckBox, SIGNAL(stateChanged( int )), this, SLOT(tickInviteChanged())); - connect(ui.addCheckBox, SIGNAL(stateChanged( int )), this, SLOT(tickAddChanged())); - connect(ui.connectCheckBox, SIGNAL(stateChanged( int )), this, SLOT(tickConnectChanged())); - connect(ui.firewallCheckBox, SIGNAL(stateChanged( int )), this, SLOT(tickFirewallChanged())); + connect(ui.inviteCheckBox, SIGNAL(stateChanged(int)), this, SLOT(tickInviteChanged())); + connect(ui.addCheckBox, SIGNAL(stateChanged(int)), this, SLOT(tickAddChanged())); + connect(ui.connectCheckBox, SIGNAL(stateChanged(int)), this, SLOT(tickConnectChanged())); + connect(ui.firewallCheckBox, SIGNAL(stateChanged(int)), this, SLOT(tickFirewallChanged())); - connect(ui.pushButton_InviteFriends, SIGNAL(clicked( bool )), this, SLOT(inviteFriends())); - connect(ui.pushButton_AddFriend, SIGNAL(clicked( bool )), this, SLOT(addFriends())); + connect(ui.pushButton_InviteFriends, SIGNAL(clicked(bool)), this, SLOT(inviteFriends())); + connect(ui.pushButton_AddFriend, SIGNAL(clicked(bool)), this, SLOT(addFriends())); - connect(ui.pushButton_FAQ, SIGNAL(clicked( bool )), this, SLOT(OpenFAQ())); - connect(ui.pushButton_Forums, SIGNAL(clicked( bool )), this, SLOT(OpenForums())); - connect(ui.pushButton_Website, SIGNAL(clicked( bool )), this, SLOT(OpenWebsite())); - connect(ui.pushButton_EmailFeedback, SIGNAL(clicked( bool )), this, SLOT(emailFeedback())); - connect(ui.pushButton_EmailSupport, SIGNAL(clicked( bool )), this, SLOT(emailSupport())); + connect(ui.pushButton_FAQ, SIGNAL(clicked(bool)), this, SLOT(OpenFAQ())); + connect(ui.pushButton_Forums, SIGNAL(clicked(bool)), this, SLOT(OpenForums())); + connect(ui.pushButton_Website, SIGNAL(clicked(bool)), this, SLOT(OpenWebsite())); + connect(ui.pushButton_EmailFeedback, SIGNAL(clicked(bool)), this, SLOT(emailFeedback())); + connect(ui.pushButton_EmailSupport, SIGNAL(clicked(bool)), this, SLOT(emailSupport())); } GetStartedDialog::~GetStartedDialog() @@ -105,8 +105,7 @@ void GetStartedDialog::showEvent ( QShowEvent * /*event*/ ) void GetStartedDialog::updateFromUserLevel() { - RsConfigUserLvl userLevel = RsConfigUserLvl::NEW; - userLevel = rsConfig->getUserLevel(); + RsConfigUserLvl userLevel = rsConfig->getUserLevel(); ui.inviteCheckBox->setChecked(false); ui.addCheckBox->setChecked(false); @@ -185,17 +184,12 @@ void GetStartedDialog::tickFirewallChanged() } } -static void sendMail(const QString &address, const QString &subject, QString body) +static void sendMail(const QString &address, const QString &subject, const QString &body) { - /* Only under windows do we need to do this! */ -#ifdef Q_OS_WIN - /* search and replace the end of lines with: "%0D%0A" */ - body.replace("\n", "%0D%0A"); -#endif QString mailstr = "mailto:" + address; - mailstr += "?subject=" + subject; - mailstr += "&body=" + body; + mailstr += "?subject=" + QUrl::toPercentEncoding(subject); + mailstr += "&body=" + QUrl::toPercentEncoding(body); std::cerr << "MAIL STRING:" << mailstr.toStdString() << std::endl; @@ -235,12 +229,12 @@ void GetStartedDialog::inviteFriends() { RsAutoUpdatePage::lockAllEvents(); - cert = rsPeers->GetRetroshareInvite(RsPeerId(),RetroshareInviteFlags::DNS | RetroshareInviteFlags::CURRENT_IP | RetroshareInviteFlags::FULL_IP_HISTORY); + cert = rsPeers->GetRetroshareInvite(RsPeerId(),RsPeers::defaultCertificateFlags | RetroshareInviteFlags::FULL_IP_HISTORY); RsAutoUpdatePage::unlockAllEvents() ; } - QString text = QString("%1\n%2\n\n%3\n").arg(GetInviteText()).arg(GetCutBelowText()).arg(QString::fromUtf8(cert.c_str())); + QString text = QString("%1\n%2\n\n%3\n").arg(GetInviteText(), GetCutBelowText(), QString::fromUtf8(cert.c_str())); sendMail("", tr("RetroShare Invitation"), text); } @@ -427,8 +421,10 @@ void GetStartedDialog::emailSupport() sysVersion = "Linux"; #endif #endif - text += QString("My RetroShare Configuration is: (%1, %2, %3)").arg(Rshare::retroshareVersion(true)).arg(sysVersion).arg(static_cast::type>(userLevel)) + "\n"; - text += "\n"; + text += QString("My RetroShare Configuration is: (%1, %2, %3)").arg(RsApplication::retroshareVersion(true) + , sysVersion + ).arg(static_cast::type>(userLevel)) + "\n"; + text += "\n"; text += QString("I am having trouble with RetroShare."); text += QString(" Can you help me with....") + "\n"; diff --git a/retroshare-gui/src/gui/GetStartedDialog.ui b/retroshare-gui/src/gui/GetStartedDialog.ui index 13698c204..5c0a78e6b 100644 --- a/retroshare-gui/src/gui/GetStartedDialog.ui +++ b/retroshare-gui/src/gui/GetStartedDialog.ui @@ -10,7 +10,7 @@ 582 - + 0 @@ -32,11 +32,20 @@ Getting Started - + 0 - + + 0 + + + 0 + + + 0 + + 0 @@ -53,12 +62,12 @@ 732 - + 0 - + @@ -121,20 +130,20 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html>
- + @@ -197,17 +206,17 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html>
- + 0 @@ -282,25 +291,25 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html>
- + @@ -366,23 +375,23 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html>
- + Qt::Vertical @@ -407,31 +416,31 @@ p, li { white-space: pre-wrap; } Further Help and Support - + - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html>
- + @@ -454,7 +463,7 @@ p, li { white-space: pre-wrap; } - + Qt::Vertical @@ -481,7 +490,7 @@ p, li { white-space: pre-wrap; } - + Qt::Vertical @@ -494,7 +503,7 @@ p, li { white-space: pre-wrap; } - + Qt::Vertical diff --git a/retroshare-gui/src/gui/HelpDialog.cpp b/retroshare-gui/src/gui/HelpDialog.cpp index cc3f1d407..ddaf925d4 100644 --- a/retroshare-gui/src/gui/HelpDialog.cpp +++ b/retroshare-gui/src/gui/HelpDialog.cpp @@ -80,7 +80,7 @@ HelpDialog::HelpDialog(QWidget *parent) : ui->thanks->setHtml(in.readAll()); } - ui->version->setText(Rshare::retroshareVersion(true)); + ui->version->setText(RsApplication::retroshareVersion(true)); /* Add version numbers of libretroshare */ std::list libraries; diff --git a/retroshare-gui/src/gui/HelpDialog.ui b/retroshare-gui/src/gui/HelpDialog.ui index 66884029f..3d40a8a90 100644 --- a/retroshare-gui/src/gui/HelpDialog.ui +++ b/retroshare-gui/src/gui/HelpDialog.ui @@ -56,7 +56,7 @@ 6 - + @@ -72,13 +72,13 @@ - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -97,16 +97,6 @@ p, li { white-space: pre-wrap; } - - - - QFrame::StyledPanel - - - QFrame::Raised - - - @@ -223,7 +213,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> diff --git a/retroshare-gui/src/gui/HomePage.cpp b/retroshare-gui/src/gui/HomePage.cpp index 3caba0ca1..9b8213646 100644 --- a/retroshare-gui/src/gui/HomePage.cpp +++ b/retroshare-gui/src/gui/HomePage.cpp @@ -24,13 +24,16 @@ #include "retroshare/rsinit.h" #include "util/qtthreadsutils.h" +#include "util/misc.h" #include "gui/notifyqt.h" +#include "gui/common/FilesDefs.h" #include "gui/msgs/MessageComposer.h" #include "gui/connect/ConnectFriendWizard.h" #include "gui/connect/ConfCertDialog.h" #include #include "gui/connect/FriendRecommendDialog.h" +#include "settings/rsharesettings.h" #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) #include @@ -49,14 +52,10 @@ HomePage::HomePage(QWidget *parent) : MainPage(parent), - ui(new Ui::HomePage), - mIncludeAllIPs(false), - mUseShortFormat(true) + ui(new Ui::HomePage) { ui->setupUi(this); - updateCertificate(); - connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addFriend())); connect(ui->copyIDButton, SIGNAL(clicked()), this, SLOT(copyId())); @@ -66,58 +65,84 @@ HomePage::HomePage(QWidget *parent) : QAction *RecAction = new QAction(QIcon(),tr("Recommend friends to each others"), this); connect(RecAction, SIGNAL(triggered()), this, SLOT(recommendFriends())); + QAction *SaveAction = new QAction(QIcon(),tr("Save to File"), this); + connect(SaveAction, SIGNAL(triggered()), this, SLOT(saveCert())); + QAction *SendAction = new QAction(QIcon(),tr("Send via Email"), this); connect(SendAction, SIGNAL(triggered()), this, SLOT(runEmailClient())); QAction *CopyIdAction = new QAction(QIcon(),tr("Copy your Retroshare ID to Clipboard"), this); connect(CopyIdAction, SIGNAL(triggered()), this, SLOT(copyId())); - QMenu *menu = new QMenu(); + QMenu *menu = new QMenu(); menu->addAction(CopyIdAction); - if(!RsAccounts::isHiddenNode()) - { - QAction *includeIPsAct = new QAction(QIcon(), tr("Include all your known IPs"),this); - connect(includeIPsAct, SIGNAL(triggered()), this, SLOT(toggleIncludeAllIPs())); - includeIPsAct->setCheckable(true); - includeIPsAct->setChecked(mIncludeAllIPs); - - menu->addAction(includeIPsAct); - } - QAction *useOldFormatAct = new QAction(QIcon(), tr("Use old certificate format"),this); - useOldFormatAct->setToolTip(tr("Displays the certificate format used up to version 0.6.5\nOld Retroshare nodes will not understand the\nnew short format")); - connect(useOldFormatAct, SIGNAL(triggered()), this, SLOT(toggleUseOldFormat())); - useOldFormatAct->setCheckable(true); - useOldFormatAct->setChecked(!mUseShortFormat); - menu->addAction(useOldFormatAct); - menu->addSeparator(); + menu->addAction(SaveAction); menu->addAction(SendAction); menu->addAction(WebMailAction); menu->addAction(RecAction); + menu->addSeparator(); + + mUseOldFormatact = new QAction(QIcon(), tr("Use old certificate format"),this); + mUseOldFormatact->setToolTip(tr("Displays the certificate format used up to version 0.6.5\nOld Retroshare nodes will not understand the\nnew short format")); + connect(mUseOldFormatact, SIGNAL(triggered()), this, SLOT(updateOwnCert())); + mUseOldFormatact->setCheckable(true); + mUseOldFormatact->setChecked(false); + menu->addAction(mUseOldFormatact); + + if(!RsAccounts::isHiddenNode()) + { + mIncludeLocIPact = new QAction(QIcon(), tr("Include current local IP"),this); + connect(mIncludeLocIPact, SIGNAL(triggered()), this, SLOT(updateOwnCert())); + mIncludeLocIPact->setCheckable(true); + mIncludeLocIPact->setChecked(true); + menu->addAction(mIncludeLocIPact); + + mIncludeExtIPact = new QAction(QIcon(), tr("Include current external IP"),this); + connect(mIncludeExtIPact, SIGNAL(triggered()), this, SLOT(updateOwnCert())); + mIncludeExtIPact->setCheckable(true); + mIncludeExtIPact->setChecked(true); + menu->addAction(mIncludeExtIPact); + + mIncludeDNSact = new QAction(QIcon(), tr("Include my DNS"),this); + connect(mIncludeDNSact, SIGNAL(triggered()), this, SLOT(updateOwnCert())); + mIncludeDNSact->setCheckable(true); + mIncludeDNSact->setChecked(true); + menu->addAction(mIncludeDNSact); + + mIncludeIPHistoryact = new QAction(QIcon(), tr("Include all IPs history"),this); + connect(mIncludeIPHistoryact, SIGNAL(triggered()), this, SLOT(updateOwnCert())); + mIncludeIPHistoryact->setCheckable(true); + mIncludeIPHistoryact->setChecked(false); + menu->addAction(mIncludeIPHistoryact); + } ui->shareButton->setMenu(menu); connect(ui->openwebhelp,SIGNAL(clicked()), this,SLOT(openWebHelp())) ; - int S = QFontMetricsF(font()).height(); - QString help_str = tr( - "

  Welcome to Retroshare!

\ -

You need to make friends! After you create a network of friends or join an existing network,\ - you'll be able to exchange files, chat, talk in forums, etc.

\ -
\ - \ -
\ -

To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.

\ -

Another option is to search the internet for \"Retroshare chat servers\" (independently administrated). These servers allow you to exchange \ - Retroshare ID with a dedicated Retroshare node, through which\ - you will be able to anonymously meet other people.

").arg(QString::number(2*S)).arg(width()*0.5); - registerHelpButton(ui->helpButton,help_str,"HomePage") ; + int H = misc::getFontSizeFactor("HelpButton").height(); + QString help_str = tr( + "

  Welcome to Retroshare!

" + "

You need to make friends! After you create a network of friends or join an existing network," + " you'll be able to exchange files, chat, talk in forums, etc.

" + "
" + "

To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.

" + "

Another option is to search the internet for \"Retroshare chat servers\" (independently administrated). These servers allow you to exchange" + " Retroshare ID with a dedicated Retroshare node, through which" + " you will be able to anonymously meet other people.

" + ).arg(QString::number(2*H), QString::number(width()*0.5), QString::number(width()*0.5*(337.0/800.0)));// needs height and width defined. + registerHelpButton(ui->helpButton,help_str,"HomePage") ; - // register a event handler to catch IP updates + // register a event handler to catch IP updates mEventHandlerId = 0; rsEvents->registerEventsHandler( [this](std::shared_ptr event) { handleEvent(event); }, mEventHandlerId, RsEventType::NETWORK ); + + updateOwnCert(); + + updateHomeLogo(); } void HomePage::handleEvent(std::shared_ptr e) @@ -136,16 +161,19 @@ void HomePage::handleEvent(std::shared_ptr e) { case RsNetworkEventCode::LOCAL_IP_UPDATED: // [fallthrough] case RsNetworkEventCode::EXTERNAL_IP_UPDATED: // [fallthrough] + case RsNetworkEventCode::DNS_UPDATED: // [fallthrough] RsQThreadUtils::postToObject( [=]() { - updateCertificate(); + updateOwnCert(); },this); break; default: break; } } -void HomePage::certContextMenu(QPoint point) + +#ifdef DEAD_CODE +void HomePage::certContextMenu(QPoint /*point*/) { QMenu menu(this) ; @@ -177,17 +205,7 @@ void HomePage::certContextMenu(QPoint point) menu.exec(QCursor::pos()); } - -void HomePage::toggleUseShortFormat() -{ - mUseShortFormat = !mUseShortFormat; - updateCertificate(); -} -void HomePage::toggleIncludeAllIPs() -{ - mIncludeAllIPs = !mIncludeAllIPs; - updateCertificate(); -} +#endif HomePage::~HomePage() { @@ -195,15 +213,29 @@ HomePage::~HomePage() delete ui; } -void HomePage::updateCertificate() +RetroshareInviteFlags HomePage::currentInviteFlags() const { - updateOwnCert(); + RetroshareInviteFlags invite_flags = RetroshareInviteFlags::NOTHING; + + if(!RsAccounts::isHiddenNode()) + { + if(mIncludeLocIPact->isChecked()) + invite_flags |= RetroshareInviteFlags::CURRENT_LOCAL_IP; + + if(mIncludeExtIPact->isChecked()) + invite_flags |= RetroshareInviteFlags::CURRENT_EXTERNAL_IP; + + if(mIncludeDNSact->isChecked()) + invite_flags |= RetroshareInviteFlags::DNS; + + if(mIncludeIPHistoryact->isChecked()) + invite_flags |= RetroshareInviteFlags::FULL_IP_HISTORY; + } + + return invite_flags; } - -void HomePage::updateOwnCert() +void HomePage::getOwnCert(QString& invite,QString& description) const { - bool include_extra_locators = mIncludeAllIPs; - RsPeerDetails detail; if (!rsPeers->getPeerDetails(rsPeers->getOwnId(), detail)) @@ -211,24 +243,36 @@ void HomePage::updateOwnCert() std::cerr << "(EE) Cannot retrieve information about own certificate. That is a real problem!!" << std::endl; return ; } + auto invite_flags = currentInviteFlags(); - QString invite ; - RetroshareInviteFlags invite_flags = RetroshareInviteFlags::CURRENT_IP; + invite_flags |= RetroshareInviteFlags::SLICE_TO_80_CHARS; - if(mIncludeAllIPs) - invite_flags |= RetroshareInviteFlags::FULL_IP_HISTORY; - - if(mUseShortFormat) + if(!mUseOldFormatact->isChecked()) { std::string short_invite; rsPeers->getShortInvite(short_invite,rsPeers->getOwnId(),invite_flags | RetroshareInviteFlags::RADIX_FORMAT); + invite = QString::fromStdString(short_invite); + } + else + invite = QString::fromStdString(rsPeers->GetRetroshareInvite(detail.id,invite_flags)); + description = ConfCertDialog::getCertificateDescription(detail,false,!mUseOldFormatact->isChecked(),invite_flags); +} + +void HomePage::updateOwnCert() +{ + QString certificate, description; + + getOwnCert(certificate,description); + + if(!mUseOldFormatact->isChecked()) // in this case we have to split the cert for a better display + { QString S; QString txt; - for(uint32_t i=0;iGetRetroshareInvite(detail.id,invite_flags)); - - ui->retroshareid->setText("\n"+invite+"\n"); - - QString description = ConfCertDialog::getCertificateDescription(detail,false,mUseShortFormat,include_extra_locators); + ui->retroshareid->setText("\n"+certificate+"\n"); ui->retroshareid->setToolTip(description); } -static void sendMail(QString sAddress, QString sSubject, QString sBody) +static void sendMail(const QString &sAddress, const QString &sSubject, const QString &sBody) { -#ifdef Q_OS_WIN - /* search and replace the end of lines with: "%0D%0A" */ - sBody.replace("\n", "%0D%0A"); -#endif - QUrl url = QUrl("mailto:" + sAddress); #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) @@ -265,7 +298,12 @@ static void sendMail(QString sAddress, QString sSubject, QString sBody) #endif urlQuery.addQueryItem("subject", sSubject); +#ifdef Q_OS_WIN + /* search and replace the end of lines with: "%0D%0A" */ + urlQuery.addQueryItem("body", QString(sBody).replace("\n", "%0D%0A")); +#else urlQuery.addQueryItem("body", sBody); +#endif #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) url.setQuery(urlQuery); @@ -348,8 +386,17 @@ void HomePage::openWebHelp() QDesktopServices::openUrl(QUrl(QString("https://retrosharedocs.readthedocs.io/en/latest/"))); } -void HomePage::toggleUseOldFormat() +void HomePage::showEvent(QShowEvent *event) { - mUseShortFormat = !mUseShortFormat; - updateCertificate(); + if (!event->spontaneous()) { + updateHomeLogo(); + } +} + +void HomePage::updateHomeLogo() +{ + if (Settings->getSheetName() == ":Standard_Dark") + ui->label->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":images/logo/logo_web_nobackground_black.png")); + else + ui->label->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":images/logo/logo_web_nobackground.png")); } diff --git a/retroshare-gui/src/gui/HomePage.h b/retroshare-gui/src/gui/HomePage.h index 2b9e28c18..2dfc62f82 100644 --- a/retroshare-gui/src/gui/HomePage.h +++ b/retroshare-gui/src/gui/HomePage.h @@ -46,28 +46,36 @@ public: virtual QString pageName() const { return tr("Home") ; } //MainPage virtual QString helpText() const { return ""; } //MainPage + // Returns the certificate along with its description using current options. + + void getOwnCert(QString& invite,QString& description) const; + RetroshareInviteFlags currentInviteFlags() const ; + + virtual void showEvent(QShowEvent *) override; + private slots: - void certContextMenu(QPoint); +#ifdef DEAD_CODE + void certContextMenu(QPoint); +#endif void updateOwnCert(); - void updateCertificate(); void runEmailClient(); void copyCert(); void copyId(); void saveCert(); void addFriend(); void webMail(); - //void loadCert(); void openWebHelp() ; - void toggleUseOldFormat() ; - void recommendFriends(); - void toggleIncludeAllIPs(); - void toggleUseShortFormat(); + void recommendFriends(); + void updateHomeLogo(); private: Ui::HomePage *ui; - bool mIncludeAllIPs; - bool mUseShortFormat; + QAction *mIncludeDNSact; + QAction *mIncludeIPHistoryact; + QAction *mIncludeExtIPact; + QAction *mIncludeLocIPact; + QAction *mUseOldFormatact; RsEventsHandlerId_t mEventHandlerId; diff --git a/retroshare-gui/src/gui/HomePage.ui b/retroshare-gui/src/gui/HomePage.ui index 60743b3c1..e716577b8 100644 --- a/retroshare-gui/src/gui/HomePage.ui +++ b/retroshare-gui/src/gui/HomePage.ui @@ -43,7 +43,6 @@ Courier New - 10 75 true @@ -88,7 +87,8 @@ - 11 + 75 + true @@ -231,11 +231,6 @@
- - - 12 - - Open Source cross-platform, private and secure decentralized communication platform. @@ -289,6 +284,13 @@ private and secure decentralized communication platform. + + + 15 + 75 + true + + Add friend @@ -308,11 +310,6 @@ private and secure decentralized communication platform. - - - 11 - - @@ -396,11 +393,6 @@ private and secure decentralized communication platform. - - - 11 - - Do you need help with Retroshare? diff --git a/retroshare-gui/src/gui/Identity/IdDetailsDialog.h b/retroshare-gui/src/gui/Identity/IdDetailsDialog.h index ba53b2bba..abefaf872 100644 --- a/retroshare-gui/src/gui/Identity/IdDetailsDialog.h +++ b/retroshare-gui/src/gui/Identity/IdDetailsDialog.h @@ -23,7 +23,6 @@ #include -#include "util/TokenQueue.h" #include namespace Ui { diff --git a/retroshare-gui/src/gui/Identity/IdDetailsDialog.ui b/retroshare-gui/src/gui/Identity/IdDetailsDialog.ui index 6a681f142..f54a19b8c 100644 --- a/retroshare-gui/src/gui/Identity/IdDetailsDialog.ui +++ b/retroshare-gui/src/gui/Identity/IdDetailsDialog.ui @@ -355,7 +355,7 @@ - + 0 @@ -493,12 +493,16 @@ p, li { white-space: pre-wrap; } - - HeaderFrame - QFrame -
gui/common/HeaderFrame.h
- 1 + + HeaderFrame + QFrame +
gui/common/HeaderFrame.h
+ 1
-
- + + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
+ diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp index e8c39e75d..a2d588d3e 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp @@ -31,6 +31,8 @@ #include "IdDialog.h" #include "ui_IdDialog.h" #include "IdEditDialog.h" +#include "IdentityListModel.h" + #include "gui/RetroShareLink.h" #include "gui/chat/ChatDialog.h" #include "gui/Circles/CreateCircleDialog.h" @@ -50,7 +52,7 @@ #include "util/rsdebug.h" #include "retroshare/rsgxsflags.h" -#include "retroshare/rsmsgs.h" +#include "retroshare/rsmsgs.h" #include "retroshare/rspeers.h" #include "retroshare/rsservicecontrol.h" @@ -92,11 +94,6 @@ /**************************************************************** */ -#define RSID_COL_NICKNAME 0 -#define RSID_COL_KEYID 1 -#define RSID_COL_IDTYPE 2 -#define RSID_COL_VOTES 3 - #define RSIDREP_COL_NAME 0 #define RSIDREP_COL_OPINION 1 #define RSIDREP_COL_COMMENT 2 @@ -123,6 +120,7 @@ static const uint32_t SortRole = Qt::UserRole+1 ; +#ifdef TO_REMOVE // quick solution for RSID_COL_VOTES sorting class TreeWidgetItem : public QTreeWidgetItem { @@ -146,6 +144,60 @@ class TreeWidgetItem : public QTreeWidgetItem return data(column,Qt::DisplayRole).toString().toUpper() < other.data(column,Qt::DisplayRole).toString().toUpper(); } }; +#endif + +std::ostream& operator<<(std::ostream& o, const QModelIndex& i);// defined elsewhere + +class IdListSortFilterProxyModel: public QSortFilterProxyModel +{ +public: + explicit IdListSortFilterProxyModel(const QHeaderView *header,QObject *parent = NULL) + : QSortFilterProxyModel(parent) + , m_header(header) + , m_sortingEnabled(false), m_sortByState(false) + { + setDynamicSortFilter(false); // causes crashes when true. + } + + bool lessThan(const QModelIndex& left, const QModelIndex& right) const override + { +// bool online1 = (left .data(RsFriendListModel::OnlineRole).toInt() != RS_STATUS_OFFLINE); +// bool online2 = (right.data(RsFriendListModel::OnlineRole).toInt() != RS_STATUS_OFFLINE); +// +// if((online1 != online2) && m_sortByState) +// return (m_header->sortIndicatorOrder()==Qt::AscendingOrder)?online1:online2 ; // always put online nodes first + +#ifdef DEBUG_NEW_FRIEND_LIST + std::cerr << "Comparing index " << left << " with index " << right << std::endl; +#endif + return QSortFilterProxyModel::lessThan(left,right); + } + + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override + { + // do not show empty groups + + QModelIndex index = sourceModel()->index(source_row,0,source_parent); + + return index.data(RsIdentityListModel::FilterRole).toString() == RsIdentityListModel::FilterString ; + } + + void sort( int column, Qt::SortOrder order = Qt::AscendingOrder ) override + { + if(m_sortingEnabled) + return QSortFilterProxyModel::sort(column,order) ; + } + + void setSortingEnabled(bool b) { m_sortingEnabled = b ; } + void setSortByState(bool b) { m_sortByState = b ; } + bool sortByState() const { return m_sortByState ; } + +private: + const QHeaderView *m_header ; + bool m_sortingEnabled; + bool m_sortByState; +}; + /** Constructor */ IdDialog::IdDialog(QWidget *parent) @@ -153,6 +205,8 @@ IdDialog::IdDialog(QWidget *parent) , mExternalBelongingCircleItem(NULL) , mExternalOtherCircleItem(NULL ) , mMyCircleItem(NULL) + , mLastSortColumn(RsIdentityListModel::COLUMN_THREAD_NAME) + , mLastSortOrder(Qt::SortOrder::AscendingOrder) , needUpdateIdsOnNextShow(true), needUpdateCirclesOnNextShow(true) // Update Ids and Circles on first show , ui(new Ui::IdDialog) { @@ -167,35 +221,29 @@ IdDialog::IdDialog(QWidget *parent) // This is used to grab the broadcast of changes from p3GxsCircles, which is discarded by the current dialog, since it expects data for p3Identity only. //mCirclesBroadcastBase = new RsGxsUpdateBroadcastBase(rsGxsCircles, this); //connect(mCirclesBroadcastBase, SIGNAL(fillDisplay(bool)), this, SLOT(updateCirclesDisplay(bool))); - - ownItem = new QTreeWidgetItem(); - ownItem->setText(0, tr("My own identities")); - ownItem->setData(RSID_COL_VOTES, Qt::DecorationRole,0xff); // this is in order to prevent displaying a reputaiton icon next to these items. - allItem = new QTreeWidgetItem(); - allItem->setText(0, tr("All")); - allItem->setData(RSID_COL_VOTES, Qt::DecorationRole,0xff); + mIdListModel = new RsIdentityListModel(this); - contactsItem = new QTreeWidgetItem(); - contactsItem->setText(0, tr("My contacts")); - contactsItem->setData(RSID_COL_VOTES, Qt::DecorationRole,0xff); + mProxyModel = new IdListSortFilterProxyModel(ui->idTreeWidget->header(),this); + mProxyModel->setSourceModel(mIdListModel); + mProxyModel->setSortRole(RsIdentityListModel::SortRole); + mProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + mProxyModel->setFilterRole(RsIdentityListModel::FilterRole); + mProxyModel->setFilterRegExp(QRegExp(RsIdentityListModel::FilterString)); - ui->idTreeWidget->insertTopLevelItem(0, ownItem); - ui->idTreeWidget->insertTopLevelItem(0, allItem); - ui->idTreeWidget->insertTopLevelItem(0, contactsItem ); + ui->idTreeWidget->setModel(mProxyModel); + //ui->idTreeWidget->setSelectionModel(new QItemSelectionModel(mProxyModel));// useless in Qt5. ui->treeWidget_membership->clear(); ui->treeWidget_membership->setItemDelegateForColumn(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,new GxsIdTreeItemDelegate()); - /* Setup UI helper */ mStateHelper = new UIStateHelper(this); -// mStateHelper->addWidget(IDDIALOG_IDLIST, ui->idTreeWidget); - mStateHelper->addLoadPlaceholder(IDDIALOG_IDLIST, ui->idTreeWidget, false); - mStateHelper->addClear(IDDIALOG_IDLIST, ui->idTreeWidget); - mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); + connect(ui->idTreeWidget,SIGNAL(expanded(const QModelIndex&)),this,SLOT(trace_expanded(const QModelIndex&)),Qt::DirectConnection); + connect(ui->idTreeWidget,SIGNAL(collapsed(const QModelIndex&)),this,SLOT(trace_collapsed(const QModelIndex&)),Qt::DirectConnection); + mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_PublishTS); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_KeyId); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_Type); @@ -211,7 +259,7 @@ IdDialog::IdDialog(QWidget *parent) mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->label_positive); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->label_negative); - mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); + //mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_PublishTS); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_KeyId); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_Type); @@ -222,7 +270,7 @@ IdDialog::IdDialog(QWidget *parent) mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->overallOpinion_TF); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->usageStatistics_TB); - mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); + //mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_PublishTS); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_KeyId); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_Type); @@ -245,33 +293,37 @@ IdDialog::IdDialog(QWidget *parent) connect(ui->editIdentity, SIGNAL(triggered()), this, SLOT(editIdentity())); connect(ui->chatIdentity, SIGNAL(triggered()), this, SLOT(chatIdentity())); - connect(ui->idTreeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(updateSelection())); - connect(ui->idTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(IdListCustomPopupMenu(QPoint))); + connect(ui->idTreeWidget->selectionModel(),SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),this,SLOT(updateSelection(const QItemSelection&,const QItemSelection&))); + connect(ui->idTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(IdListCustomPopupMenu(QPoint))); + + ui->idTreeWidget->header()->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->idTreeWidget->header(), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(headerContextMenuRequested(QPoint))); connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); - connect(ui->ownOpinion_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(modifyReputation())); - + connect(ui->ownOpinion_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(modifyReputation())); + connect(ui->inviteButton, SIGNAL(clicked()), this, SLOT(sendInvite())); connect(ui->editButton, SIGNAL(clicked()), this, SLOT(editIdentity())); - connect( ui->idTreeWidget, &RSTreeWidget::itemDoubleClicked, - this, &IdDialog::chatIdentityItem ); + connect(ui->idTreeWidget, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(chatIdentityItem(QModelIndex&)) ); + connect(ui->idTreeWidget->header(),SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(sortColumn(int,Qt::SortOrder))); ui->editButton->hide(); - ui->avlabel_Circles->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/circles.png")); + ui->avLabel_Circles->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/circles.png")); ui->headerTextLabel_Circles->setText(tr("Circles")); /* Initialize splitter */ ui->mainSplitter->setStretchFactor(0, 0); ui->mainSplitter->setStretchFactor(1, 1); - + clearPerson(); +#ifdef TODO /* Add filter types */ - QMenu *idTWHMenu = new QMenu(tr("Show Items"), this); - ui->idTreeWidget->addContextMenuMenu(idTWHMenu); + QMenu *idTWHMenu = new QMenu(tr("Show Items"), this); + ui->idTreeWidget->addContextMenuMenu(idTWHMenu); QActionGroup *idTWHActionGroup = new QActionGroup(this); QAction *idTWHAction = new QAction(QIcon(),tr("All"), this); @@ -324,77 +376,65 @@ IdDialog::IdDialog(QWidget *parent) idTWHAction->setData(RSID_FILTER_BANNED); connect(idTWHAction, SIGNAL(toggled(bool)), this, SLOT(filterToggled(bool))); idTWHMenu->addAction(idTWHAction); - +#endif + QAction *CreateIDAction = new QAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/person.png"),tr("Create new Identity"), this); connect(CreateIDAction, SIGNAL(triggered()), this, SLOT(addIdentity())); - + QAction *CreateCircleAction = new QAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/circles.png"),tr("Create new circle"), this); connect(CreateCircleAction, SIGNAL(triggered()), this, SLOT(createExternalCircle())); - + QMenu *menu = new QMenu(); menu->addAction(CreateIDAction); menu->addAction(CreateCircleAction); ui->toolButton_New->setMenu(menu); - - /* Add filter actions */ - QTreeWidgetItem *headerItem = ui->idTreeWidget->headerItem(); - QString headerText = headerItem->text(RSID_COL_NICKNAME); - ui->filterLineEdit->addFilter(QIcon(), headerText, RSID_COL_NICKNAME, QString("%1 %2").arg(tr("Search"), headerText)); - headerItem->setData(RSID_COL_VOTES,Qt::UserRole,tr("Reputation")); + QFontMetricsF fm(ui->idTreeWidget->font()) ; /* Set initial section sizes */ - QHeaderView * circlesheader = ui->treeWidget_membership->header () ; - circlesheader->resizeSection (CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QFontMetricsF(ui->idTreeWidget->font()).width("Circle name")*1.5) ; - ui->treeWidget_membership->setColumnWidth(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, 270); - - ui->filterLineEdit->addFilter(QIcon(), tr("ID"), RSID_COL_KEYID, tr("Search ID")); + QHeaderView * circlesheader = ui->treeWidget_membership->header () ; + circlesheader->resizeSection (CIRCLEGROUP_CIRCLE_COL_GROUPNAME, fm.width("Circle name")*1.5) ; + ui->treeWidget_membership->setColumnWidth(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, 270); /* Setup tree */ - ui->idTreeWidget->sortByColumn(RSID_COL_NICKNAME, Qt::AscendingOrder); + //ui->idTreeWidget->sortByColumn(RsIdentityListModel::COLUMN_THREAD_NAME, Qt::AscendingOrder); - ui->idTreeWidget->enableColumnCustomize(true); - ui->idTreeWidget->setColumnCustomizable(RSID_COL_NICKNAME, false); + ui->idTreeWidget->setColumnHidden(RsIdentityListModel::COLUMN_THREAD_OWNER_ID, true); + ui->idTreeWidget->setColumnHidden(RsIdentityListModel::COLUMN_THREAD_OWNER_NAME, true); + ui->idTreeWidget->setColumnHidden(RsIdentityListModel::COLUMN_THREAD_ID, true); - ui->idTreeWidget->setColumnHidden(RSID_COL_IDTYPE, true); - ui->idTreeWidget->setColumnHidden(RSID_COL_KEYID, true); - - /* Set initial column width */ - int fontWidth = QFontMetricsF(ui->idTreeWidget->font()).width("W"); - ui->idTreeWidget->setColumnWidth(RSID_COL_NICKNAME, 14 * fontWidth); - ui->idTreeWidget->setColumnWidth(RSID_COL_KEYID, 20 * fontWidth); - ui->idTreeWidget->setColumnWidth(RSID_COL_IDTYPE, 18 * fontWidth); - ui->idTreeWidget->setColumnWidth(RSID_COL_VOTES, 2 * fontWidth); - - ui->idTreeWidget->setItemDelegateForColumn( - RSID_COL_NICKNAME, - new GxsIdTreeItemDelegate()); - ui->idTreeWidget->setItemDelegateForColumn( - RSID_COL_VOTES, - new ReputationItemDelegate(RsReputationLevel(0xff))); + ui->idTreeWidget->setItemDelegate(new RSElidedItemDelegate()); + ui->idTreeWidget->setItemDelegateForColumn( RsIdentityListModel::COLUMN_THREAD_REPUTATION, new ReputationItemDelegate(RsReputationLevel(0xff))); /* Set header resize modes and initial section sizes */ QHeaderView * idheader = ui->idTreeWidget->header(); - QHeaderView_setSectionResizeModeColumn(idheader, RSID_COL_VOTES, QHeaderView::ResizeToContents); - idheader->setStretchLastSection(true); + QHeaderView_setSectionResizeModeColumn(idheader, RsIdentityListModel::COLUMN_THREAD_NAME, QHeaderView::Stretch); + QHeaderView_setSectionResizeModeColumn(idheader, RsIdentityListModel::COLUMN_THREAD_ID, QHeaderView::Stretch); + QHeaderView_setSectionResizeModeColumn(idheader, RsIdentityListModel::COLUMN_THREAD_OWNER_ID, QHeaderView::Stretch); + QHeaderView_setSectionResizeModeColumn(idheader, RsIdentityListModel::COLUMN_THREAD_OWNER_NAME, QHeaderView::Stretch); + QHeaderView_setSectionResizeModeColumn(idheader, RsIdentityListModel::COLUMN_THREAD_REPUTATION, QHeaderView::Fixed); + ui->idTreeWidget->setColumnWidth(RsIdentityListModel::COLUMN_THREAD_REPUTATION,fm.height()); + idheader->setStretchLastSection(false); - mStateHelper->setActive(IDDIALOG_IDDETAILS, false); + mStateHelper->setActive(IDDIALOG_IDDETAILS, false); mStateHelper->setActive(IDDIALOG_REPLIST, false); - QString hlp_str = tr( - "

  Identities

\ -

In this tab you can create/edit pseudo-anonymous identities, and circles.

\ -

Identities are used to securely identify your data: sign messages in chat lobbies, forum and channel posts,\ - receive feedback using the Retroshare built-in email system, post comments \ - after channel posts, chat using secured tunnels, etc.

\ -

Identities can optionally be signed by your Retroshare node's certificate. \ - Signed identities are easier to trust but are easily linked to your node's IP address.

\ -

Anonymous identities allow you to anonymously interact with other users. They cannot be \ - spoofed, but noone can prove who really owns a given identity.

\ -

Circles are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be \ - used to restrict the visibility to forums, channels, etc.

\ -

An circle can be restricted to another circle, thereby limiting its visibility to members of that circle \ - or even self-restricted, meaning that it is only visible to invited members.

") ; + int H = misc::getFontSizeFactor("HelpButton").height(); + QString hlp_str = tr( + "

  Identities

" + "

In this tab you can create/edit pseudo-anonymous identities, and circles.

" + "

Identities are used to securely identify your data: sign messages in chat lobbies, forum and channel posts," + " receive feedback using the Retroshare built-in email system, post comments" + " after channel posts, chat using secured tunnels, etc.

" + "

Identities can optionally be signed by your Retroshare node's certificate." + " Signed identities are easier to trust but are easily linked to your node's IP address.

" + "

Anonymous identities allow you to anonymously interact with other users. They cannot be" + " spoofed, but noone can prove who really owns a given identity.

" + "

Circles are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be" + " used to restrict the visibility to forums, channels, etc.

" + "

An circle can be restricted to another circle, thereby limiting its visibility to members of that circle" + " or even self-restricted, meaning that it is only visible to invited members.

" + ).arg(QString::number(2*H)); registerHelpButton(ui->helpButton, hlp_str,"PeopleDialog") ; @@ -402,13 +442,42 @@ IdDialog::IdDialog(QWidget *parent) processSettings(true); // circles stuff - + //connect(ui->treeWidget_membership, SIGNAL(itemSelectionChanged()), this, SLOT(circle_selected())); connect(ui->treeWidget_membership, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(CircleListCustomPopupMenu(QPoint))); connect(ui->autoBanIdentities_CB, SIGNAL(toggled(bool)), this, SLOT(toggleAutoBanIdentities(bool))); - updateIdTimer.setSingleShot(true); + updateIdTimer.setSingleShot(true); connect(&updateIdTimer, SIGNAL(timeout()), this, SLOT(updateIdList())); + + mFontSizeHandler.registerFontSize(ui->idTreeWidget, 0, [this] (QAbstractItemView*, int fontSize) { + // Set new font size on all items + + mIdListModel->setFontSize(fontSize); + }); + + mFontSizeHandler.registerFontSize(ui->treeWidget_membership, 0, [this] (QAbstractItemView*, int fontSize) { + // Set new font size on all items + QTreeWidgetItemIterator it(ui->treeWidget_membership); + while (*it) { + QTreeWidgetItem *item = *it; +#ifdef CIRCLE_MEMBERSHIP_CATEGORIES + if (item->parent()) + { +#endif + QFont font = item->font(CIRCLEGROUP_CIRCLE_COL_GROUPNAME); + font.setPointSize(fontSize); + + item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, font); + item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPID, font); + item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, font); + +#ifdef CIRCLE_MEMBERSHIP_CATEGORIES + } +#endif + ++it; + } + }); } void IdDialog::handleEvent_main_thread(std::shared_ptr event) @@ -423,17 +492,19 @@ void IdDialog::handleEvent_main_thread(std::shared_ptr event) switch(e->mIdentityEventCode) { case RsGxsIdentityEventCode::DELETED_IDENTITY: - case RsGxsIdentityEventCode::NEW_IDENTITY: + if(mId == e->mIdentityId) + { + mId.clear(); + updateIdentity(); + } + updateIdListRequest(); + break; + + case RsGxsIdentityEventCode::NEW_IDENTITY: case RsGxsIdentityEventCode::UPDATED_IDENTITY: if (isVisible()) - { - if(rsIdentity->isOwnId(RsGxsId(e->mIdentityId))) - updateIdList(); - else - updateIdTimer.start(3000); // use a timer for events not generated by local changes - } - else - needUpdateIdsOnNextShow = true; + updateIdListRequest(); // use a timer for events not generated by local changes which generally + // come in large herds. Allows to group multiple changes into a single UI update. if(!mId.isNull() && mId == e->mIdentityId) updateIdentity(); @@ -473,13 +544,13 @@ void IdDialog::handleEvent_main_thread(std::shared_ptr event) void IdDialog::clearPerson() { - QFontMetricsF f(ui->avLabel_Person->font()) ; + //QFontMetricsF f(ui->avLabel_Person->font()) ; - ui->avLabel_Person->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/people.png").scaled(f.height()*4,f.height()*4,Qt::IgnoreAspectRatio,Qt::SmoothTransformation)); ui->headerTextLabel_Person->setText(tr("People")); - ui->inviteFrame->hide(); + ui->info_Frame_Invite->hide(); ui->avatarLabel->clear(); + ui->avatarLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/people.png")); whileBlocking(ui->ownOpinion_CB)->setCurrentIndex(1); whileBlocking(ui->autoBanIdentities_CB)->setChecked(false); @@ -493,7 +564,7 @@ void IdDialog::toggleAutoBanIdentities(bool b) if(!id.isNull()) { rsReputations->banNode(id,b) ; - updateIdList(); + updateIdListRequest(); } } @@ -501,10 +572,10 @@ void IdDialog::updateCirclesDisplay() { if(RsAutoUpdatePage::eventsLocked()) return ; - + if(!isVisible()) return ; - + #ifdef ID_DEBUG std::cerr << "!!Updating circles display!" << std::endl; #endif @@ -648,15 +719,14 @@ void IdDialog::loadCircles(const std::list& groupInfo) if(!mExternalOtherCircleItem) { mExternalOtherCircleItem = new QTreeWidgetItem(); - mExternalOtherCircleItem->setText(0, tr("Other circles")); - + mExternalOtherCircleItem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, tr("Other circles")); ui->treeWidget_membership->addTopLevelItem(mExternalOtherCircleItem); } if(!mExternalBelongingCircleItem ) { mExternalBelongingCircleItem = new QTreeWidgetItem(); - mExternalBelongingCircleItem->setText(0, tr("Circles I belong to")); + mExternalBelongingCircleItem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, tr("Circles I belong to")); ui->treeWidget_membership->addTopLevelItem(mExternalBelongingCircleItem); } #endif @@ -732,14 +802,11 @@ void IdDialog::loadCircles(const std::list& groupInfo) item->setToolTip(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,tooltip); - if (am_I_admin) - { - QFont font = item->font(CIRCLEGROUP_CIRCLE_COL_GROUPNAME) ; - font.setBold(true) ; - item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,font) ; - item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPID,font) ; - item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS,font) ; - } + QFont font = ui->treeWidget_membership->font() ; + font.setBold(am_I_admin) ; + item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,font) ; + item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPID,font) ; + item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS,font) ; // now determine for this circle wether we have pending invites // we add a sub-item to the circle (to show the invite system info) in the following two cases: @@ -854,12 +921,10 @@ void IdDialog::loadCircles(const std::list& groupInfo) subitem->setData(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole, QVariant(it->second)) ; subitem->setData(CIRCLEGROUP_CIRCLE_COL_GROUPID, Qt::UserRole, QString::fromStdString(it->first.toStdString())) ; - //subitem->setIcon(RSID_COL_NICKNAME, QIcon(pixmap)); - - new_sub_items.push_back(subitem); + new_sub_items.push_back(subitem); } - else - subitem = item->child(subitem_index); + else + subitem = item->child(subitem_index); if(invited && !subscrb) { @@ -878,15 +943,12 @@ void IdDialog::loadCircles(const std::list& groupInfo) if(invited && subscrb) subitem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPID, tr("Member")) ; - if (is_own_id) - { - QFont font = subitem->font(CIRCLEGROUP_CIRCLE_COL_GROUPNAME) ; - font.setBold(true) ; - subitem->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,font) ; - subitem->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPID,font) ; - subitem->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS,font) ; - } - } + QFont font = ui->treeWidget_membership->font() ; + font.setBold(is_own_id) ; + subitem->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,font) ; + subitem->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPID,font) ; + subitem->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS,font) ; + } // add all items item->addChildren(new_sub_items); @@ -921,16 +983,16 @@ void IdDialog::loadCircles(const std::list& groupInfo) bool IdDialog::getItemCircleId(QTreeWidgetItem *item,RsGxsCircleId& id) { -#ifdef CIRCLE_MEMBERSHIP_CATEGORIES +#ifdef CIRCLE_MEMBERSHIP_CATEGORIES if ((!item) || (!item->parent())) return false; - + QString coltext = (item->parent()->parent())? (item->parent()->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString()) : (item->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString()); id = RsGxsCircleId( coltext.toStdString()) ; #else if(!item) return false; - + QString coltext = (item->parent())? (item->parent()->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString()) : (item->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString()); id = RsGxsCircleId( coltext.toStdString()) ; #endif @@ -940,7 +1002,7 @@ bool IdDialog::getItemCircleId(QTreeWidgetItem *item,RsGxsCircleId& id) void IdDialog::showEvent(QShowEvent *s) { if (needUpdateIdsOnNextShow) - updateIdList(); + updateIdListRequest(); if (needUpdateCirclesOnNextShow) updateCircles(); @@ -959,19 +1021,19 @@ void IdDialog::createExternalCircle() void IdDialog::showEditExistingCircle() { RsGxsCircleId id ; - + if(!getItemCircleId(ui->treeWidget_membership->currentItem(),id)) return ; - + uint32_t subscribe_flags = ui->treeWidget_membership->currentItem()->data(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole).toUInt(); - + CreateCircleDialog dlg; - + dlg.editExistingId(RsGxsGroupId(id),true,!(subscribe_flags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) ; dlg.exec(); } -void IdDialog::grantCircleMembership() +void IdDialog::grantCircleMembership() { RsGxsCircleId circle_id ; @@ -988,7 +1050,7 @@ void IdDialog::grantCircleMembership() }); } -void IdDialog::revokeCircleMembership() +void IdDialog::revokeCircleMembership() { RsGxsCircleId circle_id ; @@ -1017,22 +1079,22 @@ void IdDialog::revokeCircleMembership() }); } -void IdDialog::acceptCircleSubscription() +void IdDialog::acceptCircleSubscription() { RsGxsCircleId circle_id ; - + if(!getItemCircleId(ui->treeWidget_membership->currentItem(),circle_id)) return; RsGxsId own_id(qobject_cast(sender())->data().toString().toStdString()); - + rsGxsCircles->requestCircleMembership(own_id,circle_id) ; } -void IdDialog::cancelCircleSubscription() -{ +void IdDialog::cancelCircleSubscription() +{ RsGxsCircleId circle_id ; - + if(!getItemCircleId(ui->treeWidget_membership->currentItem(),circle_id)) return; @@ -1040,14 +1102,14 @@ void IdDialog::cancelCircleSubscription() rsGxsCircles->cancelCircleMembership(own_id,circle_id) ; } - + void IdDialog::CircleListCustomPopupMenu( QPoint ) { QMenu contextMnu( this ); RsGxsCircleId circle_id ; QTreeWidgetItem *item = ui->treeWidget_membership->currentItem(); - + if(!getItemCircleId(item,circle_id)) return ; @@ -1055,7 +1117,7 @@ void IdDialog::CircleListCustomPopupMenu( QPoint ) RsGxsId item_id(item->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString().toStdString()); bool is_circle ; bool am_I_circle_admin = false ; - + if(item_id == RsGxsId(circle_id)) // is it a circle? { uint32_t group_flags = item->data(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole).toUInt(); @@ -1074,7 +1136,7 @@ void IdDialog::CircleListCustomPopupMenu( QPoint ) #ifdef CIRCLE_MEMBERSHIP_CATEGORIES } #endif - + #ifdef ID_DEBUG std::cerr << " Item is a circle item. Adding Edit/Details menu entry." << std::endl; #endif @@ -1082,7 +1144,7 @@ void IdDialog::CircleListCustomPopupMenu( QPoint ) contextMnu.addSeparator() ; } - else + else { current_gxs_id = RsGxsId(item_id); is_circle =false ; @@ -1097,9 +1159,9 @@ void IdDialog::CircleListCustomPopupMenu( QPoint ) std::cerr << " Item is a GxsId item. Requesting flags/group id from parent: " << circle_id << std::endl; #endif } - + RsGxsCircleDetails details ; - + if(!rsGxsCircles->getCircleDetails(circle_id,details))// grab real circle ID from parent. Make sure circle id is used correctly afterwards! { std::cerr << " (EE) cannot get circle info for ID " << circle_id << ". Not in cache?" << std::endl; @@ -1112,7 +1174,7 @@ void IdDialog::CircleListCustomPopupMenu( QPoint ) static const int CANCEL = 3 ; // Admin list: no Subscription request: yes const QString menu_titles[4] = { tr("Request subscription"), tr("Accept circle invitation"), tr("Quit this circle"),tr("Cancel subscribe request")} ; - const QString image_names[4] = { ":/images/edit_add24.png",":/images/accepted16.png",":/icons/png/enter.png",":/images/cancel.png" } ; + const QString image_names[4] = { ":/images/edit_add24.png",":/images/accepted16.png",":/icons/png/enter.png",":/icons/cancel.svg" } ; std::vector< std::vector > ids(4) ; @@ -1136,7 +1198,7 @@ void IdDialog::CircleListCustomPopupMenu( QPoint ) ids[REMOVE].push_back(*it) ; else ids[CANCEL].push_back(*it) ; - else + else if(subscribe_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) ids[ACCEPT].push_back(*it) ; else @@ -1197,17 +1259,17 @@ void IdDialog::CircleListCustomPopupMenu( QPoint ) contextMnu.addMenu(menu) ; } } - + if(!is_circle && am_I_circle_admin) // I am circle admin. I can therefore revoke/accept membership { std::map::const_iterator it = details.mSubscriptionFlags.find(current_gxs_id) ; - + if(!current_gxs_id.isNull() && it != details.mSubscriptionFlags.end()) { contextMnu.addSeparator() ; if(it->second & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) - { + { QAction *action = new QAction(tr("Revoke this member"),this) ; action->setData(QString::fromStdString(current_gxs_id.toStdString())); QObject::connect(action,SIGNAL(triggered()), this, SLOT(revokeCircleMembership())); @@ -1235,6 +1297,8 @@ IdDialog::~IdDialog() // save settings processSettings(false); + delete mIdListModel; + delete mProxyModel; delete(ui); } @@ -1252,46 +1316,65 @@ static QString getHumanReadableDuration(uint32_t seconds) return QString(QObject::tr("%1 hours ago")).arg(seconds/3600) ; else if(seconds < 2*24*3600) return QString(QObject::tr("%1 day ago")).arg(seconds/86400) ; - else + else return QString(QObject::tr("%1 days ago")).arg(seconds/86400) ; } void IdDialog::processSettings(bool load) { - Settings->beginGroup("IdDialog"); + Settings->beginGroup("IdDialog"); - // state of peer tree - ui->idTreeWidget->processSettings(load); + if (load) { + // load settings - if (load) { - // load settings + ui->idTreeWidget->header()->restoreState(Settings->value(objectName()).toByteArray()); + ui->idTreeWidget->header()->setHidden(Settings->value(objectName()+"HiddenHeader", false).toBool()); - // filterColumn - ui->filterLineEdit->setCurrentFilter(Settings->value("filterColumn", RSID_COL_NICKNAME).toInt()); + // filterColumn + //ui->filterLineEdit->setCurrentFilter(Settings->value("filterColumn", RsIdentityListModel::COLUMN_THREAD_NAME).toInt()); - // state of splitter - ui->mainSplitter->restoreState(Settings->value("splitter").toByteArray()); + // state of splitter + ui->mainSplitter->restoreState(Settings->value("splitter").toByteArray()); - //Restore expanding - allItem->setExpanded(Settings->value("ExpandAll", QVariant(true)).toBool()); - ownItem->setExpanded(Settings->value("ExpandOwn", QVariant(true)).toBool()); - contactsItem->setExpanded(Settings->value("ExpandContacts", QVariant(true)).toBool()); - } else { - // save settings + //Restore expanding + ui->idTreeWidget->setExpanded(mProxyModel->mapFromSource(mIdListModel->getIndexOfCategory(RsIdentityListModel::CATEGORY_ALL)),Settings->value("ExpandAll", QVariant(true)).toBool()); + ui->idTreeWidget->setExpanded(mProxyModel->mapFromSource(mIdListModel->getIndexOfCategory(RsIdentityListModel::CATEGORY_OWN)),Settings->value("ExpandOwn", QVariant(true)).toBool()); + ui->idTreeWidget->setExpanded(mProxyModel->mapFromSource(mIdListModel->getIndexOfCategory(RsIdentityListModel::CATEGORY_CTS)),Settings->value("ExpandContacts", QVariant(true)).toBool()); - // filterColumn - Settings->setValue("filterColumn", ui->filterLineEdit->currentFilter()); + // visible columns - // state of splitter - Settings->setValue("splitter", ui->mainSplitter->saveState()); - - //save expanding - Settings->setValue("ExpandAll", allItem->isExpanded()); - Settings->setValue("ExpandContacts", contactsItem->isExpanded()); - Settings->setValue("ExpandOwn", ownItem->isExpanded()); - } + int v = Settings->value("columnVisibility",(1 << RsIdentityListModel::COLUMN_THREAD_NAME)+(1 << RsIdentityListModel::COLUMN_THREAD_REPUTATION)).toInt(); - Settings->endGroup(); + for(int i=0;icolumnCount();++i) + ui->idTreeWidget->setColumnHidden(i,!(v & (1<setValue(objectName(), ui->idTreeWidget->header()->saveState()); + Settings->setValue(objectName()+"HiddenHeader", ui->idTreeWidget->header()->isHidden()); + + // filterColumn + //Settings->setValue("filterColumn", ui->filterLineEdit->currentFilter()); + + // state of splitter + Settings->setValue("splitter", ui->mainSplitter->saveState()); + + //save expanding + Settings->setValue("ExpandAll", ui->idTreeWidget->isExpanded(mProxyModel->mapFromSource(mIdListModel->getIndexOfCategory(RsIdentityListModel::CATEGORY_ALL)))); + Settings->setValue("ExpandContacts", ui->idTreeWidget->isExpanded(mProxyModel->mapFromSource(mIdListModel->getIndexOfCategory(RsIdentityListModel::CATEGORY_CTS)))); + Settings->setValue("ExpandOwn", ui->idTreeWidget->isExpanded(mProxyModel->mapFromSource(mIdListModel->getIndexOfCategory(RsIdentityListModel::CATEGORY_OWN)))); + + int v = 0; + for(int i=0;icolumnCount();++i) + if(!ui->idTreeWidget->isColumnHidden(i)) + v += (1 << i); + + Settings->setValue("columnVisibility",v); + } + + Settings->endGroup(); } void IdDialog::filterChanged(const QString& /*text*/) @@ -1305,79 +1388,79 @@ void IdDialog::filterToggled(const bool &value) QAction *source = qobject_cast(QObject::sender()); if (source) { filter = source->data().toInt(); - updateIdList(); + updateIdListRequest(); } } } -void IdDialog::updateSelection() +void IdDialog::updateSelection(const QItemSelection& /* new_sel */,const QItemSelection& /* old_sel */) { - QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); - RsGxsGroupId id; +#ifdef DEBUG_ID_DIALOG + std::cerr << "Got selectionChanged signal. Old selection is: " << std::endl; + for(auto i:old_sel.indexes()) std::cerr << " " << i << std::endl; + std::cerr << "Got selectionChanged signal. New selection is: " << std::endl; + for(auto i:new_sel.indexes()) std::cerr << " " << i << std::endl; +#endif - if (item) { - id = RsGxsGroupId(item->text(RSID_COL_KEYID).toStdString()); - } + auto id = RsGxsGroupId(getSelectedIdentity()); - if (id != mId) { +#ifdef DEBUG_ID_DIALOG + std::cerr << "updating selection to id " << id << std::endl; +#endif + if(id != mId) + { mId = id; updateIdentity(); - //updateRepList(); } } - +void IdDialog::updateIdListRequest() +{ + if(updateIdTimer.isActive()) + { + std::cerr << "updateIdListRequest(): restarting timer"<< std::endl; + updateIdTimer.stop(); + updateIdTimer.start(1000); + } + else + { + std::cerr << "updateIdListRequest(): starting timer"<< std::endl; + updateIdTimer.start(1000); + } +} void IdDialog::updateIdList() { - //int accept = filter; + //print_stacktrace(); - RsThread::async([this]() - { - // 1 - get message data from p3GxsForums + RsThread::async([this]() + { + std::list *ids = new std::list(); -#ifdef DEBUG_FORUMS - std::cerr << "Retrieving post data for post " << mThreadId << std::endl; -#endif + if(!rsIdentity->getIdentitiesSummaries(*ids)) + { + std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve identity metadata." << std::endl; + return; + } - std::list identity_metas ; + RsQThreadUtils::postToObject( [ids,this]() + { - if (!rsIdentity->getIdentitiesSummaries(identity_metas)) - { - std::cerr << "IdDialog::insertIdList() Error getting GroupData" << std::endl; - return; - } + std::cerr << "Updating identity list in widget." << std::endl; - std::set ids; - for(auto it(identity_metas.begin());it!=identity_metas.end();++it) - ids.insert(RsGxsId((*it).mGroupId)); - - std::vector groups; - - if(!rsIdentity->getIdentitiesInfo(ids,groups)) - { - std::cerr << "IdDialog::insertIdList() Error getting identities info" << std::endl; - return; - } - - auto ids_set = new std::map(); - - for(auto it(groups.begin()); it!=groups.end(); ++it) - (*ids_set)[(*it).mMeta.mGroupId] = *it; - - RsQThreadUtils::postToObject( [ids_set, this] () - { - /* Here it goes any code you want to be executed on the Qt Gui - * thread, for example to update the data model with new information - * after a blocking call to RetroShare API complete */ - loadIdentities(*ids_set); - delete ids_set; - - }, this ); + applyWhileKeepingTree( [ids,this]() + { + std::cerr << "setting new identity in model." << std::endl; + mIdListModel->setIdentities(*ids) ; + delete ids; + ui->label_count->setText("("+QString::number(mIdListModel->count())+")"); + }); + }); }); } +#ifdef TO_REMOVE bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, const RsPgpId &ownPgpId, int accept) { bool isLinkedToOwnNode = (data.mPgpKnown && (data.mPgpId == ownPgpId)) ; @@ -1389,73 +1472,42 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, uint32_t item_flags = 0; /* do filtering */ - bool ok = false; if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility) - { - if (isLinkedToOwnNode && (accept & RSID_FILTER_YOURSELF)) - { - ok = true; - item_flags |= RSID_FILTER_YOURSELF ; - } + { + if (isLinkedToOwnNode && (accept & RSID_FILTER_YOURSELF)) + item_flags |= RSID_FILTER_YOURSELF ; - if (data.mPgpKnown && (accept & RSID_FILTER_FRIENDS)) - { - ok = true; - item_flags |= RSID_FILTER_FRIENDS ; - } + if (data.mPgpKnown && (accept & RSID_FILTER_FRIENDS)) + item_flags |= RSID_FILTER_FRIENDS ; - if (accept & RSID_FILTER_OTHERS) - { - ok = true; - item_flags |= RSID_FILTER_OTHERS ; - } - } - else if (accept & RSID_FILTER_PSEUDONYMS) - { - ok = true; - item_flags |= RSID_FILTER_PSEUDONYMS ; - } + if (accept & RSID_FILTER_OTHERS) + item_flags |= RSID_FILTER_OTHERS ; + } + else if (accept & RSID_FILTER_PSEUDONYMS) + item_flags |= RSID_FILTER_PSEUDONYMS ; - if (isOwnId && (accept & RSID_FILTER_OWNED_BY_YOU)) - { - ok = true; - item_flags |= RSID_FILTER_OWNED_BY_YOU ; - } + if (isOwnId && (accept & RSID_FILTER_OWNED_BY_YOU)) + item_flags |= RSID_FILTER_OWNED_BY_YOU ; if (isBanned && (accept & RSID_FILTER_BANNED)) - { - ok = true; item_flags |= RSID_FILTER_BANNED ; - } - if (!ok) + if (item_flags == 0) return false; if (!item) - { - item = new TreeWidgetItem(); - } - + item = new TreeWidgetItem(); + item->setText(RSID_COL_NICKNAME, QString::fromUtf8(data.mMeta.mGroupName.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE)); item->setData(RSID_COL_NICKNAME, Qt::UserRole, QString::fromStdString(data.mMeta.mGroupId.toStdString())); item->setText(RSID_COL_KEYID, QString::fromStdString(data.mMeta.mGroupId.toStdString())); - if(isBanned) - { - //TODO (Phenom): Add qproperty for these text colors in stylesheets - item->setData(RSID_COL_NICKNAME, Qt::ForegroundRole, QColor(Qt::red)); - item->setData(RSID_COL_KEYID , Qt::ForegroundRole, QColor(Qt::red)); - item->setData(RSID_COL_IDTYPE , Qt::ForegroundRole, QColor(Qt::red)); - item->setData(RSID_COL_VOTES , Qt::ForegroundRole, QColor(Qt::red)); - } - else - { - item->setData(RSID_COL_NICKNAME, Qt::ForegroundRole, QVariant()); - item->setData(RSID_COL_KEYID , Qt::ForegroundRole, QVariant()); - item->setData(RSID_COL_IDTYPE , Qt::ForegroundRole, QVariant()); - item->setData(RSID_COL_VOTES , Qt::ForegroundRole, QVariant()); - } + //TODO (Phenom): Add qproperty for these text colors in stylesheets + item->setData(RSID_COL_NICKNAME, Qt::ForegroundRole, isBanned ? QColor(Qt::red) : QVariant() ); + item->setData(RSID_COL_KEYID , Qt::ForegroundRole, isBanned ? QColor(Qt::red) : QVariant() ); + item->setData(RSID_COL_IDTYPE , Qt::ForegroundRole, isBanned ? QColor(Qt::red) : QVariant() ); + item->setData(RSID_COL_VOTES , Qt::ForegroundRole, isBanned ? QColor(Qt::red) : QVariant() ); item->setData(RSID_COL_KEYID, Qt::UserRole,QVariant(item_flags)) ; item->setTextAlignment(RSID_COL_VOTES, Qt::AlignRight | Qt::AlignVCenter); @@ -1466,16 +1518,9 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, RSID_COL_VOTES,SortRole, static_cast(idd.mReputation.mOverallReputationLevel)); - if(isOwnId) - { - QFont font = item->font(RSID_COL_NICKNAME) ; - - font.setBold(true) ; - item->setFont(RSID_COL_NICKNAME,font) ; - item->setFont(RSID_COL_IDTYPE,font) ; - item->setFont(RSID_COL_KEYID,font) ; - - QString tooltip = tr("This identity is owned by you"); + if(isOwnId) + { + QString tooltip = tr("This identity is owned by you"); if(idd.mFlags & RS_IDENTITY_FLAGS_IS_DEPRECATED) { @@ -1487,10 +1532,16 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, tooltip += tr("\nThis identity has a unsecure fingerprint (It's probably quite old).\nYou should get rid of it now and use a new one.\nThese identities will soon be not supported anymore.") ; } - item->setToolTip(RSID_COL_NICKNAME, tooltip) ; - item->setToolTip(RSID_COL_KEYID, tooltip) ; - item->setToolTip(RSID_COL_IDTYPE, tooltip) ; - } + item->setToolTip(RSID_COL_NICKNAME, tooltip) ; + item->setToolTip(RSID_COL_KEYID, tooltip) ; + item->setToolTip(RSID_COL_IDTYPE, tooltip) ; + } + QFont font = ui->idTreeWidget->font() ; + font.setBold(isOwnId) ; + item->setFont(RSID_COL_NICKNAME,font) ; + item->setFont(RSID_COL_IDTYPE,font) ; + item->setFont(RSID_COL_KEYID,font) ; + //QPixmap pixmap ; // @@ -1501,8 +1552,6 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, // Icon Place Holder item->setIcon(RSID_COL_NICKNAME,FilesDefs::getIconFromQtResourcePath(":/icons/png/anonymous.png")); - QString tooltip; - if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility) { if (data.mPgpKnown) @@ -1511,27 +1560,27 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, rsPeers->getGPGDetails(data.mPgpId, details); item->setText(RSID_COL_IDTYPE, QString::fromUtf8(details.name.c_str())); item->setToolTip(RSID_COL_IDTYPE,"Verified signature from node "+QString::fromStdString(data.mPgpId.toStdString())) ; - - - tooltip += tr("Node name:")+" " + QString::fromUtf8(details.name.c_str()) + "\n"; - tooltip += tr("Node Id :")+" " + QString::fromStdString(data.mPgpId.toStdString()) ; + + + QString tooltip = tr("Node name:")+" " + QString::fromUtf8(details.name.c_str()) + "\n"; + tooltip += tr("Node Id :")+" " + QString::fromStdString(data.mPgpId.toStdString()) ; item->setToolTip(RSID_COL_KEYID,tooltip) ; } - else + else { - QString txt = tr("[Unknown node]"); + QString txt = tr("[Unknown node]"); item->setText(RSID_COL_IDTYPE, txt); - - if(!data.mPgpId.isNull()) - { - item->setToolTip(RSID_COL_IDTYPE,tr("Unverified signature from node ")+QString::fromStdString(data.mPgpId.toStdString())) ; - item->setToolTip(RSID_COL_KEYID,tr("Unverified signature from node ")+QString::fromStdString(data.mPgpId.toStdString())) ; - } - else - { - item->setToolTip(RSID_COL_IDTYPE,tr("Unchecked signature")) ; - item->setToolTip(RSID_COL_KEYID,tr("Unchecked signature")) ; - } + + if(!data.mPgpId.isNull()) + { + item->setToolTip(RSID_COL_IDTYPE,tr("Unverified signature from node ")+QString::fromStdString(data.mPgpId.toStdString())) ; + item->setToolTip(RSID_COL_KEYID,tr("Unverified signature from node ")+QString::fromStdString(data.mPgpId.toStdString())) ; + } + else + { + item->setToolTip(RSID_COL_IDTYPE,tr("Unchecked signature")) ; + item->setToolTip(RSID_COL_KEYID,tr("Unchecked signature")) ; + } } } else @@ -1543,112 +1592,7 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, return true; } -void IdDialog::loadIdentities(const std::map& ids_set_const) -{ - auto ids_set(ids_set_const); - - //First: Get current item to restore after - RsGxsGroupId oldCurrentId = mIdToNavigate; - { - QTreeWidgetItem *oldCurrent = ui->idTreeWidget->currentItem(); - if (oldCurrent) { - oldCurrentId = RsGxsGroupId(oldCurrent->text(RSID_COL_KEYID).toStdString()); - } - } - - //Save expanding - Settings->beginGroup("IdDialog"); - Settings->setValue("ExpandAll", allItem->isExpanded()); - Settings->setValue("ExpandContacts", contactsItem->isExpanded()); - Settings->setValue("ExpandOwn", ownItem->isExpanded()); - Settings->endGroup(); - - - int accept = filter; - - mStateHelper->setActive(IDDIALOG_IDLIST, true); - - RsPgpId ownPgpId = rsPeers->getGPGOwnId(); - - // Update existing and remove not existing items - // Also remove items that do not have the correct parent - - QTreeWidgetItemIterator itemIterator(ui->idTreeWidget); - QTreeWidgetItem *item = NULL; - - while ((item = *itemIterator) != NULL) - { - ++itemIterator; - auto it = ids_set.find(RsGxsGroupId(item->text(RSID_COL_KEYID).toStdString())) ; - - if(it == ids_set.end()) - { - if(item != allItem && item != contactsItem && item != ownItem) - delete(item); - - continue ; - } - - QTreeWidgetItem *parent_item = item->parent() ; - -// if(it->second.mMeta.mPublishTs > time(NULL) - 20 || it->second.mMeta.mGroupId == RsGxsGroupId("3de2172503675206b3a23c997e5ee688")) -// std::cerr << "Captured ID " <second.mMeta.mGroupId << std::endl; - - if( (parent_item == allItem && it->second.mIsAContact) || (parent_item == contactsItem && !it->second.mIsAContact)) - { - delete item ; // do not remove from the list, so that it is added again in the correct place. - continue ; - } - - if (!fillIdListItem(it->second, item, ownPgpId, accept)) - delete(item); - - ids_set.erase(it); // erase, so it is not considered to be a new item - } - - /* Insert new items */ - for (std::map::const_iterator vit = ids_set.begin(); vit != ids_set.end(); ++vit) - { - RsGxsIdGroup data = vit->second ; - - item = NULL; - - if (fillIdListItem(data, item, ownPgpId, accept)) - { - if(data.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) - ownItem->addChild(item); - else if(data.mIsAContact) - contactsItem->addChild(item); - else - allItem->addChild(item); - - } - } - - /* count items */ - int itemCount = contactsItem->childCount() + allItem->childCount() + ownItem->childCount(); - ui->label_count->setText( "(" + QString::number( itemCount ) + ")" ); - - int contactsCount = contactsItem->childCount() ; - int allCount = allItem->childCount() ; - int ownCount = ownItem->childCount(); - - contactsItem->setText(0, tr("My contacts") + " (" + QString::number( contactsCount ) + ")" ); - allItem->setText(0, tr("All") + " (" + QString::number( allCount ) + ")" ); - ownItem->setText(0, tr("My own identities") + " (" + QString::number( ownCount ) + ")" ); - - - //Restore expanding - Settings->beginGroup("IdDialog"); - allItem->setExpanded(Settings->value("ExpandAll", QVariant(true)).toBool()); - ownItem->setExpanded(Settings->value("ExpandOwn", QVariant(true)).toBool()); - contactsItem->setExpanded(Settings->value("ExpandContacts", QVariant(true)).toBool()); - Settings->endGroup(); - - navigate(RsGxsId(oldCurrentId)); - filterIds(); - updateSelection(); -} +#endif void IdDialog::updateIdentity() { @@ -1694,7 +1638,7 @@ void IdDialog::updateIdentity() loadIdentity(group); - }, this ); + }, this ); }); } @@ -1710,7 +1654,7 @@ void IdDialog::loadIdentity(RsGxsIdGroup data) RsPgpId ownPgpId = rsPeers->getGPGOwnId(); ui->lineEdit_PublishTS->setText(QDateTime::fromMSecsSinceEpoch(qint64(1000)*data.mMeta.mPublishTs).toString(Qt::SystemLocaleShortDate)); - ui->lineEdit_Nickname->setText(QString::fromUtf8(data.mMeta.mGroupName.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE)); + //ui->lineEdit_Nickname->setText(QString::fromUtf8(data.mMeta.mGroupName.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE)); ui->lineEdit_KeyId->setText(QString::fromStdString(data.mMeta.mGroupId.toStdString())); //ui->lineEdit_GpgHash->setText(QString::fromStdString(data.mPgpIdHash.toStdString())); if(data.mPgpKnown) @@ -1736,8 +1680,8 @@ void IdDialog::loadIdentity(RsGxsIdGroup data) //ui->avLabel_Person->setPixmap(pixmap); //ui->avatarLabel->setPixmap(pixmap); - QFontMetricsF f(ui->avLabel_Person->font()) ; - ui->avLabel_Person->setPixmap(pixmap.scaled(f.height()*4,f.height()*4,Qt::KeepAspectRatio,Qt::SmoothTransformation)); + //QFontMetricsF f(ui->avLabel_Person->font()) ; + //ui->avLabel_Person->setPixmap(pixmap.scaled(f.height()*4,f.height()*4,Qt::KeepAspectRatio,Qt::SmoothTransformation)); ui->avatarLabel->setPixmap(pixmap.scaled(ui->inviteButton->width(),ui->inviteButton->width(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation)); ui->avatarLabel->setScaledContents(true); @@ -1766,7 +1710,7 @@ void IdDialog::loadIdentity(RsGxsIdGroup data) ui->lineEdit_GpgId->show() ; ui->label_GpgId->show() ; } - + if(data.mPgpKnown) { ui->lineEdit_GpgName->show() ; @@ -1806,7 +1750,6 @@ void IdDialog::loadIdentity(RsGxsIdGroup data) if (isOwnId) { - mStateHelper->setWidgetEnabled(ui->ownOpinion_CB, false); mStateHelper->setWidgetEnabled(ui->autoBanIdentities_CB, false); // ui->editIdentity->setEnabled(true); // ui->removeIdentity->setEnabled(true); @@ -1816,8 +1759,6 @@ void IdDialog::loadIdentity(RsGxsIdGroup data) } else { - // No Reputation yet! - mStateHelper->setWidgetEnabled(ui->ownOpinion_CB, true); mStateHelper->setWidgetEnabled(ui->autoBanIdentities_CB, true); // ui->editIdentity->setEnabled(false); // ui->removeIdentity->setEnabled(false); @@ -1861,7 +1802,7 @@ void IdDialog::loadIdentity(RsGxsIdGroup data) frep_string = tr("No votes from friends") ; ui->neighborNodesOpinion_TF->setText(frep_string) ; - + ui->label_positive->setText(QString::number(info.mFriendsPositiveVotes)); ui->label_negative->setText(QString::number(info.mFriendsNegativeVotes)); @@ -1884,9 +1825,9 @@ void IdDialog::loadIdentity(RsGxsIdGroup data) switch(info.mOwnOpinion) { - case RsOpinion::NEGATIVE: ui->ownOpinion_CB->setCurrentIndex(0); break; - case RsOpinion::NEUTRAL : ui->ownOpinion_CB->setCurrentIndex(1); break; - case RsOpinion::POSITIVE: ui->ownOpinion_CB->setCurrentIndex(2); break; + case RsOpinion::NEGATIVE: whileBlocking(ui->ownOpinion_CB)->setCurrentIndex(0); break; + case RsOpinion::NEUTRAL : whileBlocking(ui->ownOpinion_CB)->setCurrentIndex(1); break; + case RsOpinion::POSITIVE: whileBlocking(ui->ownOpinion_CB)->setCurrentIndex(2); break; default: std::cerr << "Unexpected value in own opinion: " << static_cast(info.mOwnOpinion) << std::endl; @@ -2058,33 +1999,62 @@ void IdDialog::modifyReputation() // trigger refresh when finished. // basic / anstype are not needed. - updateIdentity(); - updateIdList(); + //updateIdentity(); + //updateIdList(); return; } - + void IdDialog::navigate(const RsGxsId& gxs_id) { -#ifdef ID_DEBUG + mIdListModel->debug_dump(); +#ifndef ID_DEBUG std::cerr << "IdDialog::navigate to " << gxs_id.toStdString() << std::endl; #endif + if(gxs_id.isNull()) + return; + + auto indx = mIdListModel->getIndexOfIdentity(gxs_id); + + if(!indx.isValid()) + { + RsErr() << "Invalid index found for identity " << gxs_id << std::endl; + return; + } + std::cerr << "Obtained index " << indx << ": id of that index is " << mIdListModel->getIdentity(indx) << std::endl; + + QModelIndex proxy_indx = mProxyModel->mapFromSource(indx); + + std::cerr << "Obtained proxy index " << proxy_indx << std::endl; + // in order to do this, we just select the correct ID in the ID list - if (!gxs_id.isNull()) - { - QList select = ui->idTreeWidget->findItems(QString::fromStdString(gxs_id.toStdString()),Qt::MatchExactly | Qt::MatchRecursive | Qt::MatchWrap,RSID_COL_KEYID) ; + Q_ASSERT(ui->idTreeWidget->model() == mProxyModel); - if(select.empty()) - { - mIdToNavigate = RsGxsGroupId(gxs_id); - std::cerr << "Cannot find item with ID " << gxs_id << " in ID list." << std::endl; - return; - } - ui->idTreeWidget->setCurrentItem(*select.begin(),true); - } + if(!proxy_indx.isValid()) + { + std::cerr << "Cannot find item with ID " << gxs_id << " in ID list." << std::endl; + return; + } + std::cerr << "Row hidden? " << ui->idTreeWidget->isRowHidden(proxy_indx.row(),proxy_indx.parent()) << std::endl; - mIdToNavigate = RsGxsGroupId(); + { + auto ii = mProxyModel->mapToSource(proxy_indx); + std::cerr << "Remapping index to source: " << ii << std::endl; + } + ui->idTreeWidget->selectionModel()->select(proxy_indx,QItemSelectionModel::Current|QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + { + auto lst = ui->idTreeWidget->selectionModel()->selectedIndexes(); + std::cerr << "Just after calling select(), the selected index list has size " << lst.size() << std::endl; + } + ui->idTreeWidget->scrollTo(proxy_indx);//May change if model reloaded + ui->idTreeWidget->setFocus(); + + // This has to be done manually because for some reason the proxy model doesn't work with the selection model + // No signal is emitted when calling setCurrentIndex() above. + + //mId = RsGxsGroupId(gxs_id); + //updateIdentity(); } void IdDialog::updateDisplay(bool complete) @@ -2102,6 +2072,49 @@ void IdDialog::updateDisplay(bool complete) } } +std::list IdDialog::getSelectedIdentities() const +{ + QModelIndexList selectedIndexes_proxy = ui->idTreeWidget->selectionModel()->selectedIndexes(); + std::list res; + +#ifdef DEBUG_ID_DIALOG + std::cerr << "Parsing selected index list: " << std::endl; +#endif + for(auto indx_proxy:selectedIndexes_proxy) + { + RsGxsId id; + + if(indx_proxy.column() == RsIdentityListModel::COLUMN_THREAD_ID) // this removes duplicates + { + auto indx = mProxyModel->mapToSource(indx_proxy); + auto id = mIdListModel->getIdentity(indx); + +#ifdef DEBUG_ID_DIALOG + std::cerr << " indx: " << indx_proxy << " original indx: " << indx << " identity: " << id << std::endl; +#endif + + if( !id.isNull() ) + res.push_back(id); + } + } + + return res; +} + +RsGxsId IdDialog::getSelectedIdentity() const +{ + auto lst = getSelectedIdentities(); + +#ifdef DEBUG_ID_DIALOG + std::cerr << "Selected identities has size " << lst.size() << std::endl; +#endif + + if(lst.size() != 1) + return RsGxsId(); + else + return lst.front(); +} + void IdDialog::addIdentity() { IdEditDialog dlg(this); @@ -2111,237 +2124,248 @@ void IdDialog::addIdentity() void IdDialog::removeIdentity() { - QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); - if (!item) - { -#ifdef ID_DEBUG - std::cerr << "IdDialog::editIdentity() Invalid item"; - std::cerr << std::endl; -#endif - return; - } + RsGxsId id = getSelectedIdentity(); - if ((QMessageBox::question(this, tr("Really delete?"), tr("Do you really want to delete this identity?"), QMessageBox::Yes|QMessageBox::No, QMessageBox::No))== QMessageBox::Yes) - { - std::string keyId = item->text(RSID_COL_KEYID).toStdString(); + if(id.isNull()) + return; - uint32_t dummyToken = 0; - RsGxsIdGroup group; - group.mMeta.mGroupId=RsGxsGroupId(keyId); - rsIdentity->deleteIdentity(dummyToken, group); - } + if ((QMessageBox::question(this, tr("Really delete?"), tr("Do you really want to delete this identity?\nThis cannot be undone."), QMessageBox::Yes|QMessageBox::No, QMessageBox::No))== QMessageBox::Yes) + rsIdentity->deleteIdentity(id); } void IdDialog::editIdentity() { - QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); - if (!item) - { -#ifdef ID_DEBUG - std::cerr << "IdDialog::editIdentity() Invalid item"; - std::cerr << std::endl; -#endif - return; - } + RsGxsId id = getSelectedIdentity(); - RsGxsGroupId keyId = RsGxsGroupId(item->text(RSID_COL_KEYID).toStdString()); - if (keyId.isNull()) { - return; - } + if(id.isNull()) + return; - IdEditDialog dlg(this); - dlg.setupExistingId(keyId); - dlg.exec(); + IdEditDialog dlg(this); + dlg.setupExistingId(RsGxsGroupId(id)); + dlg.exec(); } void IdDialog::filterIds() { - int filterColumn = ui->filterLineEdit->currentFilter(); QString text = ui->filterLineEdit->text(); - ui->idTreeWidget->filterItems(filterColumn, text); + int8_t ft=0; + + if(!ui->idTreeWidget->isColumnHidden(RsIdentityListModel::COLUMN_THREAD_ID)) ft |= RsIdentityListModel::FILTER_TYPE_ID; + if(!ui->idTreeWidget->isColumnHidden(RsIdentityListModel::COLUMN_THREAD_NAME)) ft |= RsIdentityListModel::FILTER_TYPE_NAME; + if(!ui->idTreeWidget->isColumnHidden(RsIdentityListModel::COLUMN_THREAD_OWNER_NAME)) ft |= RsIdentityListModel::FILTER_TYPE_OWNER_NAME; + if(!ui->idTreeWidget->isColumnHidden(RsIdentityListModel::COLUMN_THREAD_OWNER_ID)) ft |= RsIdentityListModel::FILTER_TYPE_OWNER_ID; + + mIdListModel->setFilter(ft,{ text }); } +void IdDialog::headerContextMenuRequested(QPoint) +{ + QMenu displayMenu(this); + + // create menu header + //QHBoxLayout *hbox = new QHBoxLayout(widget); + //hbox->setMargin(0); + //hbox->setSpacing(6); + + auto addEntry = [&](const QString& name,RsIdentityListModel::Columns col) + { + QAction *action = displayMenu.addAction(QIcon(), name, this, SLOT(toggleColumnVisible())); + action->setCheckable(true); + action->setData(static_cast(col)); + action->setChecked(!ui->idTreeWidget->header()->isSectionHidden(col)); + }; + + addEntry(tr("Id"),RsIdentityListModel::COLUMN_THREAD_ID); + addEntry(tr("Owner Id"),RsIdentityListModel::COLUMN_THREAD_OWNER_ID); + addEntry(tr("Owner Name"),RsIdentityListModel::COLUMN_THREAD_OWNER_NAME); + addEntry(tr("Reputation"),RsIdentityListModel::COLUMN_THREAD_REPUTATION); + + //addEntry(tr("Name"),RsIdentityListModel::COLUMN_THREAD_NAME); + + displayMenu.exec(QCursor::pos()); +} + +void IdDialog::toggleColumnVisible() +{ + QAction *action = dynamic_cast(sender()); + + std::cerr << "Aciton = " << (void*)action << std::endl; + if (!action) + return; + + int column = action->data().toInt(); + bool visible = action->isChecked(); + + ui->idTreeWidget->setColumnHidden(column, !visible); +} void IdDialog::IdListCustomPopupMenu( QPoint ) { - QMenu *contextMenu = new QMenu(this); + QMenu contextMenu(this); + std::list own_identities; + rsIdentity->getOwnIds(own_identities); - std::list own_identities; - rsIdentity->getOwnIds(own_identities); + // make some stats about what's selected. If the same value is used for all selected items, it can be switched. - // make some stats about what's selected. If the same value is used for all selected items, it can be switched. + auto lst = getSelectedIdentities(); - QList selected_items = ui->idTreeWidget->selectedItems(); + if(lst.empty()) + return ; - bool root_node_present = false ; - bool one_item_owned_by_you = false ; - uint32_t n_positive_reputations = 0 ; - uint32_t n_negative_reputations = 0 ; - uint32_t n_neutral_reputations = 0 ; - uint32_t n_is_a_contact = 0 ; - uint32_t n_is_not_a_contact = 0 ; - uint32_t n_selected_items =0 ; + //bool root_node_present = false ; + bool one_item_owned_by_you = false ; + uint32_t n_positive_reputations = 0 ; + uint32_t n_negative_reputations = 0 ; + uint32_t n_neutral_reputations = 0 ; + uint32_t n_is_a_contact = 0 ; + uint32_t n_is_not_a_contact = 0 ; + uint32_t n_selected_items =0 ; - for(auto& it :selected_items) - { - if(it == allItem || it == contactsItem || it == ownItem) - { - root_node_present = true ; - continue ; - } + for(auto& keyId :lst) + { + //if(it == allItem || it == contactsItem || it == ownItem) + //{ + // root_node_present = true ; + // continue ; + //} - uint32_t item_flags = it->data(RSID_COL_KEYID,Qt::UserRole).toUInt() ; + //uint32_t item_flags = mIdListModel->data(RSID_COL_KEYID,Qt::UserRole).toUInt() ; - if(item_flags & RSID_FILTER_OWNED_BY_YOU) - one_item_owned_by_you = true ; + if(rsIdentity->isOwnId(keyId)) + one_item_owned_by_you = true ; #ifdef ID_DEBUG - std::cerr << " item flags = " << item_flags << std::endl; + std::cerr << " item flags = " << item_flags << std::endl; #endif - RsGxsId keyId(it->text(RSID_COL_KEYID).toStdString()); + RsIdentityDetails det ; + rsIdentity->getIdDetails(keyId,det) ; - RsIdentityDetails det ; - rsIdentity->getIdDetails(keyId,det) ; + switch(det.mReputation.mOwnOpinion) + { + case RsOpinion::NEGATIVE: ++n_negative_reputations; break; + case RsOpinion::POSITIVE: ++n_positive_reputations; break; + case RsOpinion::NEUTRAL: ++n_neutral_reputations; break; + } - switch(det.mReputation.mOwnOpinion) - { - case RsOpinion::NEGATIVE: ++n_negative_reputations; break; - case RsOpinion::POSITIVE: ++n_positive_reputations; break; - case RsOpinion::NEUTRAL: ++n_neutral_reputations; break; - } + ++n_selected_items; - ++n_selected_items; + if(rsIdentity->isARegularContact(keyId)) + ++n_is_a_contact ; + else + ++n_is_not_a_contact ; + } - if(rsIdentity->isARegularContact(keyId)) - ++n_is_a_contact ; - else - ++n_is_not_a_contact ; - } + if(!one_item_owned_by_you) + { + QFrame *widget = new QFrame(&contextMenu); + widget->setObjectName("gradFrame"); //Use qss + //widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); - if(!root_node_present) // don't show menu if some of the root nodes are present - { + // create menu header + QHBoxLayout *hbox = new QHBoxLayout(widget); + hbox->setMargin(0); + hbox->setSpacing(6); - if(!one_item_owned_by_you) - { - QWidget *widget = new QWidget(contextMenu); - widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); + QLabel *iconLabel = new QLabel(widget); + iconLabel->setObjectName("trans_Icon"); + QPixmap pix = FilesDefs::getPixmapFromQtResourcePath(":/images/user/friends24.png").scaledToHeight(QFontMetricsF(iconLabel->font()).height()*1.5); + iconLabel->setPixmap(pix); + iconLabel->setMaximumSize(iconLabel->frameSize().height() + pix.height(), pix.width()); + hbox->addWidget(iconLabel); - // create menu header - QHBoxLayout *hbox = new QHBoxLayout(widget); - hbox->setMargin(0); - hbox->setSpacing(6); + QLabel *textLabel = new QLabel("" + ui->titleBarLabel->text() + "", widget); + textLabel->setObjectName("trans_Text"); + hbox->addWidget(textLabel); - QLabel *iconLabel = new QLabel(widget); - QPixmap pix = FilesDefs::getPixmapFromQtResourcePath(":/images/user/friends24.png").scaledToHeight(QFontMetricsF(iconLabel->font()).height()*1.5); - iconLabel->setPixmap(pix); - iconLabel->setMaximumSize(iconLabel->frameSize().height() + pix.height(), pix.width()); - hbox->addWidget(iconLabel); + QSpacerItem *spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + hbox->addItem(spacerItem); - QLabel *textLabel = new QLabel("" + ui->titleBarLabel->text() + "", widget); - hbox->addWidget(textLabel); + widget->setLayout(hbox); - QSpacerItem *spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - hbox->addItem(spacerItem); + QWidgetAction *widgetAction = new QWidgetAction(this); + widgetAction->setDefaultWidget(widget); + contextMenu.addAction(widgetAction); - widget->setLayout(hbox); + if(n_selected_items == 1) // if only one item is selected, allow to chat with this item + { + if(own_identities.size() <= 1) + { + QAction *action = contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/chats.png"), tr("Chat with this person"), this, SLOT(chatIdentity())); - QWidgetAction *widgetAction = new QWidgetAction(this); - widgetAction->setDefaultWidget(widget); - contextMenu->addAction(widgetAction); + if(own_identities.empty()) + action->setEnabled(false) ; + else + action->setData(QString::fromStdString((own_identities.front()).toStdString())) ; + } + else + { + QMenu *mnu = contextMenu.addMenu(FilesDefs::getIconFromQtResourcePath(":/icons/png/chats.png"),tr("Chat with this person as...")) ; - if(n_selected_items == 1) // if only one item is selected, allow to chat with this item - { - if(own_identities.size() <= 1) - { - QAction *action = contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/chats.png"), tr("Chat with this person"), this, SLOT(chatIdentity())); + for(std::list::const_iterator it=own_identities.begin();it!=own_identities.end();++it) + { + RsIdentityDetails idd ; + rsIdentity->getIdDetails(*it,idd) ; - if(own_identities.empty()) - action->setEnabled(false) ; - else - action->setData(QString::fromStdString((own_identities.front()).toStdString())) ; - } - else - { - QMenu *mnu = contextMenu->addMenu(FilesDefs::getIconFromQtResourcePath(":/icons/png/chats.png"),tr("Chat with this person as...")) ; + QPixmap pixmap ; - for(std::list::const_iterator it=own_identities.begin();it!=own_identities.end();++it) - { - RsIdentityDetails idd ; - rsIdentity->getIdDetails(*it,idd) ; + if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap,GxsIdDetails::SMALL)) + pixmap = GxsIdDetails::makeDefaultIcon(*it,GxsIdDetails::SMALL) ; - QPixmap pixmap ; + 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())) ; + } + } + } + // always allow to send messages + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/mail/write-mail.png"), tr("Send message"), this, SLOT(sendMsg())); - if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap,GxsIdDetails::SMALL)) - pixmap = GxsIdDetails::makeDefaultIcon(*it,GxsIdDetails::SMALL) ; + contextMenu.addSeparator(); - 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())) ; - } - } - } - // always allow to send messages - contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/icons/mail/write-mail.png"), tr("Send message"), this, SLOT(sendMsg())); + if(n_is_a_contact == 0) + contextMenu.addAction(QIcon(), tr("Add to Contacts"), this, SLOT(addtoContacts())); - contextMenu->addSeparator(); + if(n_is_not_a_contact == 0) + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/cancel.svg"), tr("Remove from Contacts"), this, SLOT(removefromContacts())); + } + if (n_selected_items==1) + contextMenu.addAction(QIcon(""),tr("Copy identity to clipboard"),this,SLOT(copyRetroshareLink())) ; - if(n_is_a_contact == 0) - contextMenu->addAction(QIcon(), tr("Add to Contacts"), this, SLOT(addtoContacts())); + contextMenu.addSeparator(); - if (n_selected_items==1) - contextMenu->addAction(QIcon(""),tr("Copy identity to clipboard"),this,SLOT(copyRetroshareLink())) ; + if(n_positive_reputations == 0) // only unban when all items are banned + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-up.png"), tr("Set positive opinion"), this, SLOT(positivePerson())); - if(n_is_not_a_contact == 0) - contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/images/cancel.png"), tr("Remove from Contacts"), this, SLOT(removefromContacts())); + if(n_neutral_reputations == 0) // only unban when all items are banned + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-neutral.png"), tr("Set neutral opinion"), this, SLOT(neutralPerson())); - contextMenu->addSeparator(); + if(n_negative_reputations == 0) + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-down.png"), tr("Set negative opinion"), this, SLOT(negativePerson())); - if(n_positive_reputations == 0) // only unban when all items are banned - contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-up.png"), tr("Set positive opinion"), this, SLOT(positivePerson())); + if(one_item_owned_by_you && n_selected_items==1) + { + contextMenu.addSeparator(); - if(n_neutral_reputations == 0) // only unban when all items are banned - contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-neutral.png"), tr("Set neutral opinion"), this, SLOT(neutralPerson())); + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_EDIT),tr("Edit identity"),this,SLOT(editIdentity())) ; + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/cancel.svg"),tr("Delete identity"),this,SLOT(removeIdentity())) ; + } - if(n_negative_reputations == 0) - contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-down.png"), tr("Set negative opinion"), this, SLOT(negativePerson())); - } + //contextMenu = ui->idTreeWidget->createStandardContextMenu(contextMenu); - if(one_item_owned_by_you && n_selected_items==1) - { - contextMenu->addSeparator(); - - contextMenu->addAction(QIcon(""),tr("Copy identity to clipboard"),this,SLOT(copyRetroshareLink())) ; - contextMenu->addAction(ui->editIdentity); - contextMenu->addAction(ui->removeIdentity); - } - - } - - contextMenu = ui->idTreeWidget->createStandardContextMenu(contextMenu); - - contextMenu->exec(QCursor::pos()); - delete contextMenu; + contextMenu.exec(QCursor::pos()); } void IdDialog::copyRetroshareLink() { - QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); + auto gxs_id = getSelectedIdentity(); - if (!item) + if (gxs_id.isNull()) { std::cerr << "IdDialog::editIdentity() Invalid item"; std::cerr << std::endl; return; } - RsGxsId gxs_id(item->text(RSID_COL_KEYID).toStdString()); - - if(gxs_id.isNull()) - { - std::cerr << "Null GXS id. Something went wrong." << std::endl; - return ; - } - RsIdentityDetails details ; if(! rsIdentity->getIdDetails(gxs_id,details)) @@ -2379,35 +2403,33 @@ void IdDialog::copyRetroshareLink() }); } -void IdDialog::chatIdentity() +void IdDialog::chatIdentityItem(const QModelIndex& indx) { - QTreeWidgetItem* item = ui->idTreeWidget->currentItem(); - if (!item) - { - std::cerr << __PRETTY_FUNCTION__ << " Error. Invalid item!" << std::endl; - return; - } + auto toGxsId = mIdListModel->getIdentity(indx); - chatIdentityItem(item); -} - -void IdDialog::chatIdentityItem(QTreeWidgetItem* item) -{ - if(!item) + if(toGxsId.isNull()) { std::cerr << __PRETTY_FUNCTION__ << " Error. Invalid item." << std::endl; return; } + chatIdentity(toGxsId); +} - std::string&& toIdString(item->text(RSID_COL_KEYID).toStdString()); - RsGxsId toGxsId(toIdString); - if(toGxsId.isNull()) - { - std::cerr << __PRETTY_FUNCTION__ << " Error. Invalid destination id: " - << toIdString << std::endl; - return; - } +void IdDialog::chatIdentity() +{ + auto id = getSelectedIdentity(); + if(id.isNull()) + { + std::cerr << __PRETTY_FUNCTION__ << " Error. Invalid item!" << std::endl; + return; + } + + chatIdentity(id); +} + +void IdDialog::chatIdentity(const RsGxsId& toGxsId) +{ RsGxsId fromGxsId; QAction* action = qobject_cast(QObject::sender()); if(!action) @@ -2426,8 +2448,7 @@ void IdDialog::chatIdentityItem(QTreeWidgetItem* item) if(fromGxsId.isNull()) { - std::cerr << __PRETTY_FUNCTION__ << " Error. Could not determine sender" - << " identity to open chat toward: " << toIdString << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " Error. Could not determine sender identity to open chat toward: " << toGxsId << std::endl; return; } @@ -2444,12 +2465,12 @@ void IdDialog::chatIdentityItem(QTreeWidgetItem* item) void IdDialog::sendMsg() { - QList selected_items = ui->idTreeWidget->selectedItems(); + auto lst = getSelectedIdentities(); - if(selected_items.empty()) + if(lst.empty()) return ; - if(selected_items.size() > 20) + if(lst.size() > 20) if(QMessageBox::warning(nullptr,tr("Too many identities"),tr("

It is not recommended to send a message to more than 20 persons at once. Large scale diffusion of data (including friend invitations) are much more efficiently handled by forums. Click ok to proceed anyway.

"),QMessageBox::Ok|QMessageBox::Cancel,QMessageBox::Cancel)==QMessageBox::Cancel) return; @@ -2457,15 +2478,10 @@ void IdDialog::sendMsg() if (nMsgDialog == NULL) return; - for(auto& it : selected_items) - { - QTreeWidgetItem *item = it ; + for(const auto& id : lst) + nMsgDialog->addRecipient(MessageComposer::TO, id); - std::string keyId = item->text(RSID_COL_KEYID).toStdString(); - - nMsgDialog->addRecipient(MessageComposer::TO, RsGxsId(keyId)); - } - nMsgDialog->show(); + nMsgDialog->show(); nMsgDialog->activateWindow(); /* window will destroy itself! */ @@ -2478,103 +2494,77 @@ QString IdDialog::inviteMessage() void IdDialog::sendInvite() { - QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); - if (!item) - { - return; - } + auto id = getSelectedIdentity(); + + if(id.isNull()) + return; - RsGxsId id(ui->lineEdit_KeyId->text().toStdString()); - //if ((QMessageBox::question(this, tr("Send invite?"),tr("Do you really want send a invite with your Certificate?"),QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes))== QMessageBox::Yes) { MessageComposer::sendInvite(id,false); - ui->inviteFrame->show(); + ui->info_Frame_Invite->show(); ui->inviteButton->setEnabled(false); } - + } void IdDialog::negativePerson() { - QList selected_items = ui->idTreeWidget->selectedItems(); - for(auto& it : selected_items) - { - QTreeWidgetItem *item = it ; + auto lst = getSelectedIdentities(); - std::string Id = item->text(RSID_COL_KEYID).toStdString(); + for(const auto& id : lst) + rsReputations->setOwnOpinion(id, RsOpinion::NEGATIVE); - rsReputations->setOwnOpinion(RsGxsId(Id), RsOpinion::NEGATIVE); - } - - updateIdentity(); - updateIdList(); + updateIdentity(); + updateIdListRequest(); } void IdDialog::neutralPerson() { - QList selected_items = ui->idTreeWidget->selectedItems(); - for(auto& it : selected_items) - { - QTreeWidgetItem *item = it ; + auto lst = getSelectedIdentities(); - std::string Id = item->text(RSID_COL_KEYID).toStdString(); + for(const auto& id : lst) + rsReputations->setOwnOpinion(id, RsOpinion::NEUTRAL); - rsReputations->setOwnOpinion(RsGxsId(Id), RsOpinion::NEUTRAL); - } - - updateIdentity(); - updateIdList(); + updateIdentity(); + updateIdListRequest(); } void IdDialog::positivePerson() { - QList selected_items = ui->idTreeWidget->selectedItems(); - for(auto& it : selected_items) - { - QTreeWidgetItem *item = it ; + auto lst = getSelectedIdentities(); - std::string Id = item->text(RSID_COL_KEYID).toStdString(); + for(const auto& id : lst) + rsReputations->setOwnOpinion(id, RsOpinion::POSITIVE); - rsReputations->setOwnOpinion(RsGxsId(Id), RsOpinion::POSITIVE); - } - - updateIdentity(); - updateIdList(); + updateIdentity(); + updateIdListRequest(); } void IdDialog::addtoContacts() { - QList selected_items = ui->idTreeWidget->selectedItems(); - for(auto& it : selected_items) - { - QTreeWidgetItem *item = it ; - std::string Id = item->text(RSID_COL_KEYID).toStdString(); + auto lst = getSelectedIdentities(); - rsIdentity->setAsRegularContact(RsGxsId(Id),true); - } + for(const auto& id : lst) + rsIdentity->setAsRegularContact(id,true); - updateIdList(); + updateIdListRequest(); } void IdDialog::removefromContacts() { - QList selected_items = ui->idTreeWidget->selectedItems(); - for(auto& it : selected_items) - { - QTreeWidgetItem *item = it ; - std::string Id = item->text(RSID_COL_KEYID).toStdString(); + auto lst = getSelectedIdentities(); - rsIdentity->setAsRegularContact(RsGxsId(Id),false); - } + for(const auto& id : lst) + rsIdentity->setAsRegularContact(id,false); - updateIdList(); + updateIdListRequest(); } -void IdDialog::on_closeInfoFrameButton_clicked() +void IdDialog::on_closeInfoFrameButton_Invite_clicked() { - ui->inviteFrame->setVisible(false); + ui->info_Frame_Invite->setVisible(false); } // We need to use indexes here because saving items is not possible since they can be re-created. @@ -2625,3 +2615,174 @@ void IdDialog::restoreExpandedCircleItems(const std::vector& expanded_root restoreTopLevel(mMyCircleItem,2); } +void IdDialog::applyWhileKeepingTree(std::function predicate) +{ + std::set expanded,selected; + + saveExpandedPathsAndSelection_idTreeView(expanded, selected); +#ifdef DEBUG_NEW_FRIEND_LIST + std::cerr << "After collecting selection, selected paths is: \"" << selected.toStdString() << "\", " ; + std::cerr << "expanded paths are: " << std::endl; + for(auto path:expanded) + std::cerr << " \"" << path.toStdString() << "\"" << std::endl; + std::cerr << "Current sort column is: " << mLastSortColumn << " and order is " << mLastSortOrder << std::endl; +#endif + + // This is a hack to avoid crashes on windows while calling endInsertRows(). I'm not sure wether these crashes are + // due to a Qt bug, or a misuse of the proxy model on my side. Anyway, this solves them for good. + // As a side effect we need to save/restore hidden columns because setSourceModel() resets this setting. + + // save hidden columns and sizes + std::vector col_visible(RsIdentityListModel::COLUMN_THREAD_NB_COLUMNS); + std::vector col_sizes(RsIdentityListModel::COLUMN_THREAD_NB_COLUMNS); + + for(int i=0;iidTreeWidget->isColumnHidden(i); + col_sizes[i] = ui->idTreeWidget->columnWidth(i); + } + +#ifdef SUSPENDED +#ifdef DEBUG_NEW_FRIEND_LIST + std::cerr << "Applying predicate..." << std::endl; +#endif +#endif + mProxyModel->setSourceModel(nullptr); + predicate(); + mProxyModel->setSourceModel(mIdListModel); + + restoreExpandedPathsAndSelection_idTreeView(expanded,selected); + // restore hidden columns + for(uint32_t i=0;iidTreeWidget->setColumnHidden(i,!col_visible[i]); + ui->idTreeWidget->setColumnWidth(i,col_sizes[i]); + } + + mProxyModel->setSortingEnabled(true); + mProxyModel->sort(mLastSortColumn,mLastSortOrder); + mProxyModel->setSortingEnabled(false); +#ifdef SUSPENDED + // restore sorting + // sortColumn(mLastSortColumn,mLastSortOrder); +#ifdef DEBUG_NEW_FRIEND_LIST + std::cerr << "Sorting again with sort column: " << mLastSortColumn << " and order " << mLastSortOrder << std::endl; +#endif + +// if(selected_index.isValid()) +// ui->idTreeWidget->scrollTo(selected_index); +#endif +} + +void IdDialog::saveExpandedPathsAndSelection_idTreeView(std::set& expanded, std::set& selected) +{ +#ifdef DEBUG_ID_DIALOG + std::cerr << "Saving expended paths and selection..." << std::endl; +#endif + + for(int row = 0; row < mProxyModel->rowCount(); ++row) + recursSaveExpandedItems_idTreeView(mProxyModel->index(row,0),QStringList(),expanded,selected); +} + +void IdDialog::restoreExpandedPathsAndSelection_idTreeView(const std::set& expanded, const std::set& selected) +{ +#ifdef DEBUG_ID_DIALOG + std::cerr << "Restoring expanded paths and selection..." << std::endl; + std::cerr << " expanded: " << expanded.size() << " items" << std::endl; + std::cerr << " selected: " << selected.size() << " items" << std::endl; +#endif + ui->idTreeWidget->blockSignals(true) ; + ui->idTreeWidget->selectionModel()->blockSignals(true) ; + + ui->idTreeWidget->clearSelection(); + + for(int row = 0; row < mProxyModel->rowCount(); ++row) + recursRestoreExpandedItems_idTreeView(mProxyModel->index(row,0),QStringList(),expanded,selected); + + ui->idTreeWidget->selectionModel()->blockSignals(false) ; + ui->idTreeWidget->blockSignals(false) ; +} + +void IdDialog::recursSaveExpandedItems_idTreeView(const QModelIndex& proxy_index,const QStringList& parent_path,std::set& expanded,std::set& selected) +{ + QStringList local_path = parent_path; + + local_path.push_back(mIdListModel->indexIdentifier(mProxyModel->mapToSource(proxy_index))); + + if(ui->idTreeWidget->isExpanded(proxy_index)) + { +#ifdef DEBUG_ID_DIALOG + std::cerr << "Adding expanded path "; + for(auto L:local_path) std::cerr << "\"" << L.toStdString() << "\" " ; std::cerr << std::endl; +#endif + if(proxy_index.isValid()) + expanded.insert(local_path) ; + + for(int row=0;rowrowCount(proxy_index);++row) + recursSaveExpandedItems_idTreeView(proxy_index.child(row,0),local_path,expanded,selected) ; + } + + if(ui->idTreeWidget->selectionModel()->isSelected(proxy_index)) + { +#ifdef DEBUG_ID_DIALOG + std::cerr << "Adding selected path "; + for(auto L:local_path) std::cerr << "\"" << L.toStdString() << "\" " ; std::cerr << std::endl; +#endif + selected.insert(local_path); + } +} + +void IdDialog::recursRestoreExpandedItems_idTreeView(const QModelIndex& proxy_index,const QStringList& parent_path,const std::set& expanded,const std::set& selected) +{ + QStringList local_path = parent_path; + local_path.push_back(mIdListModel->indexIdentifier(mProxyModel->mapToSource(proxy_index))); + +#ifdef DEBUG_ID_DIALOG + std::cerr << "Local path = " ; for(auto L:local_path) std::cerr << "\"" << L.toStdString() << "\" " ; std::cerr << std::endl; +#endif + + if(expanded.find(local_path) != expanded.end()) + { +#ifdef DEBUG_ID_DIALOG + std::cerr << " re expanding " ; + for(auto L:local_path) std::cerr << "\"" << L.toStdString() << "\" " ; std::cerr << std::endl; +#endif + + ui->idTreeWidget->setExpanded(proxy_index,true) ; + + for(int row=0;rowrowCount(proxy_index);++row) + recursRestoreExpandedItems_idTreeView(proxy_index.child(row,0),local_path,expanded,selected) ; + } + + if(selected.find(local_path) != selected.end()) + { +#ifdef DEBUG_ID_DIALOG + std::cerr << "Restoring selected path "; + for(auto L:local_path) std::cerr << "\"" << L.toStdString() << "\" " ; std::cerr << std::endl; +#endif + ui->idTreeWidget->selectionModel()->select(proxy_index, QItemSelectionModel::Current|QItemSelectionModel::Select | QItemSelectionModel::Rows); + } +} + +void IdDialog::sortColumn(int col,Qt::SortOrder so) +{ +#ifdef DEBUG_NEW_FRIEND_LIST + std::cerr << "Sorting with column=" << col << " and order=" << so << std::endl; +#endif + std::set expanded_indexes,selected_indexes; + + saveExpandedPathsAndSelection_idTreeView(expanded_indexes, selected_indexes); + whileBlocking(ui->idTreeWidget)->clearSelection(); + + mProxyModel->setSortingEnabled(true); + mProxyModel->sort(col,so); + mProxyModel->setSortingEnabled(false); + + restoreExpandedPathsAndSelection_idTreeView(expanded_indexes,selected_indexes); + + //if(selected_index.isValid()) + // ui->peerTreeWidget->scrollTo(selected_index); + + mLastSortColumn = col; + mLastSortOrder = so; +} diff --git a/retroshare-gui/src/gui/Identity/IdDialog.h b/retroshare-gui/src/gui/Identity/IdDialog.h index 4e465fc5d..d4629a5af 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.h +++ b/retroshare-gui/src/gui/Identity/IdDialog.h @@ -22,8 +22,10 @@ #define IDENTITYDIALOG_H #include "gui/gxs/RsGxsUpdateBroadcastPage.h" +#include "util/FontSizeHandler.h" -#include +#include "retroshare/rsidentity.h" +#include "IdentityListModel.h" #include @@ -34,7 +36,11 @@ class IdDialog; } class UIStateHelper; +class QStyledItemDelegate; class QTreeWidgetItem; +class RsIdentityListModel; +class IdListSortFilterProxyModel; +class QItemSelection; class IdDialog : public MainPage { @@ -58,6 +64,7 @@ protected: void loadIdentity(RsGxsIdGroup id_data); void loadCircles(const std::list& circle_metas); + void updateIdListRequest(); //void requestCircleGroupData(const RsGxsCircleId& circle_id); bool getItemCircleId(QTreeWidgetItem *item,RsGxsCircleId& id) ; @@ -66,13 +73,13 @@ protected: private slots: - void updateIdList(); - void updateCircles(); - - void createExternalCircle(); + void updateIdList(); + void updateCircles(); + void createExternalCircle(); void showEditExistingCircle(); void updateCirclesDisplay(); void toggleAutoBanIdentities(bool b); + void sortColumn(int col,Qt::SortOrder so); void acceptCircleSubscription() ; void cancelCircleSubscription() ; @@ -86,17 +93,20 @@ private slots: void removeIdentity(); void editIdentity(); void chatIdentity(); - void chatIdentityItem(QTreeWidgetItem* item); - void sendMsg(); + void chatIdentityItem(const QModelIndex &indx); + void chatIdentity(const RsGxsId& toGxsId); + void sendMsg(); void copyRetroshareLink(); - void on_closeInfoFrameButton_clicked(); + void on_closeInfoFrameButton_Invite_clicked(); - void updateSelection(); + void updateSelection(const QItemSelection &new_sel, const QItemSelection &old_sel); void modifyReputation(); /** Create the context popup menu and it's submenus */ void IdListCustomPopupMenu( QPoint point ); + void headerContextMenuRequested(QPoint); + void toggleColumnVisible(); void CircleListCustomPopupMenu(QPoint point) ; #ifdef SUSPENDED @@ -117,7 +127,12 @@ private: void processSettings(bool load); QString createUsageString(const RsIdentityUsage& u) const; - void requestIdData(std::list &ids); + void saveExpandedPathsAndSelection_idTreeView(std::set &expanded, std::set &selected); + void restoreExpandedPathsAndSelection_idTreeView(const std::set& expanded, const std::set& selelected); + void recursSaveExpandedItems_idTreeView(const QModelIndex& index, const QStringList& parent_path, std::set& expanded, std::set& selected); + void recursRestoreExpandedItems_idTreeView(const QModelIndex& index,const QStringList& parent_path,const std::set& expanded,const std::set& selected); + + void requestIdData(std::list &ids); bool fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, const RsPgpId &ownPgpId, int accept); void insertIdList(uint32_t token); void filterIds(); @@ -134,20 +149,32 @@ private: private: UIStateHelper *mStateHelper; - QTreeWidgetItem *contactsItem; - QTreeWidgetItem *allItem; - QTreeWidgetItem *ownItem; QTreeWidgetItem *mExternalBelongingCircleItem; QTreeWidgetItem *mExternalOtherCircleItem; QTreeWidgetItem *mMyCircleItem; RsGxsUpdateBroadcastBase *mCirclesBroadcastBase ; - void saveExpandedCircleItems(std::vector &expanded_root_items, std::set& expanded_circle_items) const; + int mLastSortColumn; + Qt::SortOrder mLastSortOrder; + + void saveExpandedCircleItems(std::vector &expanded_root_items, std::set& expanded_circle_items) const; void restoreExpandedCircleItems(const std::vector& expanded_root_items,const std::set& expanded_circle_items); - RsGxsGroupId mId; + void applyWhileKeepingTree(std::function predicate); + + RsGxsId getSelectedIdentity() const; + std::list getSelectedIdentities() const; + + RsGxsGroupId mId; RsGxsGroupId mIdToNavigate; int filter; + bool mColumnSizeAlreadySet; // remembers if we already did some size set. If not, automatically stretch to content. + + QStyledItemDelegate *mElidedLabelDelegate; + QStyledItemDelegate *mReputationDelegate; + + RsIdentityListModel *mIdListModel; + IdListSortFilterProxyModel *mProxyModel; void handleEvent_main_thread(std::shared_ptr event); RsEventsHandlerId_t mEventHandlerId_identity; @@ -157,6 +184,8 @@ private: bool needUpdateIdsOnNextShow; bool needUpdateCirclesOnNextShow; + FontSizeHandler mFontSizeHandler; + /* UI - Designer */ Ui::IdDialog *ui; }; diff --git a/retroshare-gui/src/gui/Identity/IdDialog.ui b/retroshare-gui/src/gui/Identity/IdDialog.ui index 256849509..37522524e 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.ui +++ b/retroshare-gui/src/gui/Identity/IdDialog.ui @@ -6,7 +6,7 @@ 0 0 - 800 + 878 584 @@ -88,7 +88,14 @@
- + + + + 12 + 75 + true + + People @@ -120,7 +127,7 @@ Qt::NoFocus - + :/icons/help_64.png:/icons/help_64.png @@ -147,10 +154,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -166,7 +173,11 @@ 1 - + + + Search... + + @@ -204,7 +215,7 @@ - + 0 @@ -229,39 +240,9 @@ true - - false + + true - - - Persons - - - - - Identity ID - - - - - Owned by - - - - - - - - Votes - - - AlignLeading|AlignVCenter - - - - :/icons/flag-green.png:/icons/flag-green.png - - @@ -287,242 +268,208 @@ - -155 + 0 0 - 634 - 523 + 535 + 784 - - - + + + + + 3 + + + + + + + + 0 + 0 + + + + + 128 + 128 + + + + + 128 + 128 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + Your Avatar + + + true + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + Edit Identity + + + + + + + + 0 + 0 + + + + Send Invite + + + + + + + + + 6 + + + 2 + + + + + + 34 + 34 + + + + + + + :/icons/png/thumbs-up.png + + + true + + + + + + + + 16 + + + + Positive votes + + + 0 + + + + + + + Qt::Vertical + + + + + + + + 34 + 34 + + + + + + + :/icons/png/thumbs-down.png + + + true + + + + + + + + 16 + + + + Negative votes + + + 0 + + + + + + + + + Qt::Vertical + + + + 118 + 17 + + + + + + + + + + + 22 + + + + People + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + - + 0 0 - - QFrame::StyledPanel - - - QFrame::Raised - - - - 12 - - - - - - - People - - - - - - - Qt::Vertical - - - - 518 - 17 - - - - - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 178 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 178 - - - - - - - - - 255 - 255 - 178 - - - - - - - 255 - 255 - 178 - - - - - - - - true - - - - - - QFrame::Box - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - - 16 - 16 - - - - - - - :/images/info16.png - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - Invite messages stay into your Outbox until an acknowledgement of receipt has been received. - - - - - - - - 16 - 16 - - - - Qt::NoFocus - - - Close - - - QToolButton -{ - border-image: url(:/images/closenormal.png) -} - -QToolButton:hover -{ -border-image: url(:/images/closehover.png) -} - -QToolButton:pressed { -border-image: url(:/images/closepressed.png) -} - - - true - - - - - - - - - - - - - 0 - 0 - - - - - 64 - 64 - - - - - 1000 - 1000 - - - - - - - - - - true - - - - - - - - 0 @@ -530,262 +477,23 @@ border-image: url(:/images/closepressed.png) - Identity info + - - - - Owner node ID : - - - - - + + 9 + + + - <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - - - true - - - - - - - true - - - true - - - - - - - 0 - - - - - - 0 - 0 - - - - - 128 - 128 - - - - - 128 - 128 - - - - QFrame::Box - - - QFrame::Sunken - - - Your Avatar - - - true - - - Qt::AlignCenter - - - - - - - Send Invite - - - - - - - Edit Identity - - - - - - - 6 - - - 2 - - - - - - 34 - 34 - - - - - - - :/icons/png/thumbs-up.png - - - true - - - - - - - - 16 - - - - Positive votes - - - 0 - - - - - - - Qt::Vertical - - - - - - - - 34 - 34 - - - - - - - :/icons/png/thumbs-down.png - - - true - - - - - - - - 16 - - - - Negative votes - - - 0 - - - - - - - - - Qt::Vertical - - - - 118 - 17 - - - - - - - - - - true - - - - - - - Type: - - - - - - - - 75 - true - + Auto-Ban all identities signed by the same node - Overall: + Auto-Ban profile - - - - Last used: - - - - - - - Identity ID : - - - - - - - Created on : - - - - - - - Owner node name : - - - - - - - Ban-option: - - - - - - - Your opinion: - - - - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> @@ -795,15 +503,121 @@ border-image: url(:/images/closepressed.png) - + + + + Ban-option: + + + + + + + true + + + + true - - + + + + Identity ID : + + + + + + + Last used: + + + + + + + Qt::Horizontal + + + + + + + Owner node ID : + + + + + + + Created on : + + + + + + + Friend votes: + + + true + + + + + + + Type: + + + + + + + true + + + true + + + + + + + Your opinion: + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + true + + + true + + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> @@ -842,21 +656,24 @@ border-image: url(:/images/closepressed.png) - - - - Identity name : - - - - - - Auto-Ban all identities signed by the same node + + + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> + + + true - + + + + Owner node name : + + + + true @@ -866,43 +683,209 @@ border-image: url(:/images/closepressed.png) - + true - - + + + + + 75 + true + + - Friend votes: + Overall: - - - - true + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 178 + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 178 + + + + + + + + + 154 + 154 + 154 + + + + + + + 255 + 255 + 178 + + + + + + + 255 + 255 + 178 + + + + + + + + true + + + + + + QFrame::Box + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + 16 + 16 + - + + + + + :/images/info16.png + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Invite messages stay into your Outbox until an acknowledgement of receipt has been received. + + true - - - - Qt::Horizontal + + + + + 16 + 16 + - - - - - - true + + Qt::NoFocus - + + Close + + + QToolButton +{ + border-image: url(:/images/closenormal.png) +} + +QToolButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QToolButton:pressed { +border-image: url(:/images/closepressed.png) +} + + true @@ -910,7 +893,7 @@ border-image: url(:/images/closepressed.png) - + Usage statistics @@ -922,7 +905,7 @@ border-image: url(:/images/closepressed.png) - + Qt::Vertical @@ -936,9 +919,6 @@ border-image: url(:/images/closepressed.png) - detailsGroupBox - usageStatisticsGBox - headerFramePerson @@ -954,19 +934,19 @@ border-image: url(:/images/closepressed.png) - + QFrame::StyledPanel QFrame::Raised - + 12 - + 64 @@ -991,7 +971,12 @@ border-image: url(:/images/closepressed.png) - + + + + 22 + + Circles @@ -1037,10 +1022,6 @@ border-image: url(:/images/closepressed.png) - - - :/images/edit_16.png:/images/edit_16.png - Edit identity @@ -1049,19 +1030,11 @@ border-image: url(:/images/closepressed.png) - - - :/images/delete.png:/images/delete.png - Delete identity - - - :/images/toaster/chat.png:/images/toaster/chat.png - Chat with this peer @@ -1077,19 +1050,15 @@ border-image: url(:/images/closepressed.png)
gui/common/LineEditClear.h
- RSTreeWidget - QTreeWidget -
gui/common/RSTreeWidget.h
+ RSComboBox + QComboBox +
gui/common/RSComboBox.h
- StyledElidedLabel + ElidedLabel QLabel -
gui/common/StyledElidedLabel.h
-
- - StyledLabel - QLabel -
gui/common/StyledLabel.h
+
gui/common/ElidedLabel.h
+ 1
RSTextBrowser @@ -1101,8 +1070,8 @@ border-image: url(:/images/closepressed.png) idTreeWidget - + diff --git a/retroshare-gui/src/gui/Identity/IdEditDialog.cpp b/retroshare-gui/src/gui/Identity/IdEditDialog.cpp index 7f9f179cb..add0de131 100644 --- a/retroshare-gui/src/gui/Identity/IdEditDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdEditDialog.cpp @@ -31,9 +31,10 @@ #include "util/misc.h" #include "gui/notifyqt.h" -#include -#include +#include "retroshare/rsidentity.h" +#include "retroshare/rspeers.h" #include "gui/common/FilesDefs.h" +#include "util/imageutil.h" #include @@ -46,6 +47,7 @@ IdEditDialog::IdEditDialog(QWidget *parent) : ui(new(Ui::IdEditDialog)) { mIsNew = true; + mAvatarIsSet = false; ui->setupUi(this); @@ -76,7 +78,7 @@ IdEditDialog::IdEditDialog(QWidget *parent) : /* Connect signals */ connect(ui->radioButton_GpgId, SIGNAL(toggled(bool)), this, SLOT(idTypeToggled(bool))); connect(ui->radioButton_Pseudo, SIGNAL(toggled(bool)), this, SLOT(idTypeToggled(bool))); - connect(ui->createButton, SIGNAL(clicked()), this, SLOT(submit())); + connect(ui->postButton, SIGNAL(clicked()), this, SLOT(submit())); connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(reject())); connect(ui->plainTextEdit_Tag, SIGNAL(textChanged()), this, SLOT(checkNewTag())); @@ -87,6 +89,12 @@ IdEditDialog::IdEditDialog(QWidget *parent) : connect(ui->toolButton_Tag4, SIGNAL(clicked(bool)), this, SLOT(rmTag4())); connect(ui->toolButton_Tag5, SIGNAL(clicked(bool)), this, SLOT(rmTag5())); connect(ui->avatarButton, SIGNAL(clicked(bool)), this, SLOT(changeAvatar())); + connect(ui->removeButton, SIGNAL(clicked(bool)), this, SLOT(removeAvatar())); + + connect(ui->avatarLabel,SIGNAL(cleared()),this,SLOT(avatarCleared())); + + ui->avatarLabel->setEnableClear(true); + ui->avatarLabel->setToolTip(tr("No Avatar chosen. A default image will be automatically displayed from your new identity.")); /* Initialize ui */ ui->lineEdit_Nickname->setMaxLength(RSID_MAXIMUM_NICKNAME_SIZE); @@ -96,6 +104,8 @@ IdEditDialog::IdEditDialog(QWidget *parent) : ui->plainTextEdit_Tag->hide(); ui->label_TagCheck->hide(); ui->frame_Tags->setHidden(true); + + updateInterface(); } IdEditDialog::~IdEditDialog() {} @@ -125,10 +135,13 @@ void IdEditDialog::changeAvatar() ui->avatarLabel->setPicture(QPixmap::fromImage(img)); ui->avatarLabel->setEnableZoom(true); - ui->avatarLabel->setToolTip(tr("Use the mouse to zoom and adjust the image for your avatar.")); + ui->avatarLabel->setToolTip(tr("Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it.")); + mAvatarIsSet = true; // shows the tooltip for a while QToolTip::showText( ui->avatarLabel->mapToGlobal( QPoint( 0, 0 ) ), ui->avatarLabel->toolTip() ); + + updateInterface(); } void IdEditDialog::setupNewId(bool pseudo,bool enable_anon) @@ -205,16 +218,25 @@ void IdEditDialog::updateIdType(bool pseudo) } } +void IdEditDialog::avatarCleared() +{ + setAvatar(QPixmap()); +} + void IdEditDialog::setAvatar(const QPixmap &avatar) { mAvatar = avatar; if (!mAvatar.isNull()) { ui->avatarLabel->setPicture(avatar); + mAvatarIsSet = true; + ui->avatarLabel->setToolTip(tr("Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it.")); } else { // we need to use the default pixmap here, generated from the ID - ui->avatarLabel->setPicture(GxsIdDetails::makeDefaultIcon(RsGxsId(mEditGroup.mMeta.mGroupId))); - } + ui->avatarLabel->setText(tr("No avatar chosen")); // This clears up the image + mAvatarIsSet = false; + ui->avatarLabel->setToolTip(tr("No Avatar chosen. A default image will be automatically displayed from your new identity.")); + } } void IdEditDialog::setupExistingId(const RsGxsGroupId& keyId) @@ -222,7 +244,7 @@ void IdEditDialog::setupExistingId(const RsGxsGroupId& keyId) setWindowTitle(tr("Edit identity")); ui->headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/person.png")); ui->headerFrame->setHeaderText(tr("Edit identity")); - ui->createButton->setText(tr("Update")); + ui->postButton->setText(tr("Update")); mStateHelper->setLoading(IDEDITDIALOG_LOADID, true); @@ -337,6 +359,7 @@ void IdEditDialog::loadExistingId(const RsGxsIdGroup& id_group) ui->frame_Tags->setHidden(true); loadRecognTags(); + updateInterface(); } #define MAX_RECOGN_TAGS 5 @@ -517,13 +540,9 @@ void IdEditDialog::loadRecognTags() void IdEditDialog::submit() { if (mIsNew) - { createId(); - } else - { updateId(); - } } void IdEditDialog::createId() @@ -551,15 +570,17 @@ void IdEditDialog::createId() params.nickname = groupname.toUtf8().constData(); params.isPgpLinked = (ui->radioButton_GpgId->isChecked()); - mAvatar = ui->avatarLabel->extractCroppedScaledPicture(); - - if (!mAvatar.isNull()) + if(mAvatarIsSet) { + mAvatar = ui->avatarLabel->extractCroppedScaledPicture(); + QByteArray ba; QBuffer buffer(&ba); + bool has_transparency = ImageUtil::hasAlphaContent(mAvatar.toImage()); + buffer.open(QIODevice::WriteOnly); - mAvatar.save(&buffer, "PNG"); // writes image into ba in PNG format + mAvatar.save(&buffer, has_transparency?"PNG":"JPG"); // writes image into ba in PNG format params.mImage.copy((uint8_t *) ba.data(), ba.size()); } @@ -589,7 +610,7 @@ void IdEditDialog::createId() if(rsIdentity->createIdentity(keyId,params.nickname,params.mImage,!params.isPgpLinked,gpg_password)) { - ui->createButton->setEnabled(false); + ui->postButton->setEnabled(false); if(!keyId.isNull()) { @@ -630,8 +651,10 @@ void IdEditDialog::updateId() QByteArray ba; QBuffer buffer(&ba); - buffer.open(QIODevice::WriteOnly); - mAvatar.save(&buffer, "PNG"); // writes image into ba in PNG format + bool has_transparency = ImageUtil::hasAlphaContent(mAvatar.toImage()); + + buffer.open(QIODevice::WriteOnly); + mAvatar.save(&buffer, has_transparency?"PNG":"JPG"); // writes image into ba in PNG format mEditGroup.mImage.copy((uint8_t *) ba.data(), ba.size()); } @@ -667,3 +690,22 @@ void IdEditDialog::updateId() accept(); } +void IdEditDialog::removeAvatar() +{ + ui->avatarLabel->setPicture(QPixmap()); + mEditGroup.mImage.clear(); + + updateInterface(); +} + +void IdEditDialog::updateInterface() +{ + QPixmap pixmap = ui->avatarLabel->pixmap(Qt::ReturnByValue); + if (!pixmap.isNull()) { + ui->removeButton->setEnabled(true); + } else if (mEditGroup.mImage.mSize > 0) { + ui->removeButton->setEnabled(true); + } else { + ui->removeButton->setEnabled(false); + } +} diff --git a/retroshare-gui/src/gui/Identity/IdEditDialog.h b/retroshare-gui/src/gui/Identity/IdEditDialog.h index 36eed2891..714a79256 100644 --- a/retroshare-gui/src/gui/Identity/IdEditDialog.h +++ b/retroshare-gui/src/gui/Identity/IdEditDialog.h @@ -23,7 +23,6 @@ #include -#include "util/TokenQueue.h" #include #include #include @@ -51,8 +50,11 @@ public: private slots: void idTypeToggled(bool checked); void submit(); + void avatarCleared(); void changeAvatar(); + void removeAvatar(); + void updateInterface(); void addRecognTag(); void checkNewTag(); @@ -68,7 +70,6 @@ private: void updateIdType(bool pseudo); void loadExistingId(const RsGxsIdGroup& id_group); void setAvatar(const QPixmap &avatar); - void idCreated(uint32_t token); void loadRecognTags(); // extract details. @@ -84,6 +85,7 @@ protected: RsGxsGroupId mGroupId; QPixmap mAvatar; // Avatar from identity (not calculated) + bool mAvatarIsSet; }; #endif diff --git a/retroshare-gui/src/gui/Identity/IdEditDialog.ui b/retroshare-gui/src/gui/Identity/IdEditDialog.ui index fee114a9d..d0a625c00 100644 --- a/retroshare-gui/src/gui/Identity/IdEditDialog.ui +++ b/retroshare-gui/src/gui/Identity/IdEditDialog.ui @@ -55,10 +55,19 @@ - + + + + + 0 + 0 + 0 + + + @@ -79,6 +88,15 @@ + + + + 0 + 0 + 0 + + + @@ -99,6 +117,15 @@ + + + + 154 + 154 + 154 + + + @@ -120,6 +147,11 @@ + + + 12 + + true @@ -310,6 +342,9 @@ 128 + + Qt::StrongFocus + QFrame::Box @@ -334,6 +369,13 @@ + + + + Remove + + + @@ -362,7 +404,7 @@ QFrame::Raised - + @@ -474,7 +516,7 @@ - + 9 @@ -504,7 +546,14 @@ - + + + + 12 + 75 + true + + Create diff --git a/retroshare-gui/src/gui/Identity/IdentityListModel.cpp b/retroshare-gui/src/gui/Identity/IdentityListModel.cpp new file mode 100644 index 000000000..b55d9c160 --- /dev/null +++ b/retroshare-gui/src/gui/Identity/IdentityListModel.cpp @@ -0,0 +1,968 @@ +/******************************************************************************* + * retroshare-gui/src/gui/msgs/RsFriendListModel.cpp * + * * + * Copyright 2019 by Cyril Soler * + * * + * 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 . * + * * + *******************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "gui/common/AvatarDefs.h" +#include "util/qtthreadsutils.h" +#include "util/HandleRichText.h" +#include "util/DateTime.h" +#include "gui/gxs/GxsIdDetails.h" +#include "retroshare/rsexpr.h" + +#include "IdentityListModel.h" + +//#define DEBUG_MODEL +//#define DEBUG_MODEL_INDEX + +std::ostream& operator<<(std::ostream& o, const QModelIndex& i);// defined elsewhere + +const QString RsIdentityListModel::FilterString("filtered"); + +const uint32_t MAX_INTERNAL_DATA_UPDATE_DELAY = 300 ; // re-update the internal data every 5 mins. Should properly cover sleep/wake-up changes. +const uint32_t MAX_NODE_UPDATE_DELAY = 10 ; // re-update the internal data every 5 mins. Should properly cover sleep/wake-up changes. + +static const uint32_t ID_DETAILS_UPDATE_DELAY = 5; // update each node every 5 secs. + +RsIdentityListModel::RsIdentityListModel(QObject *parent) + : QAbstractItemModel(parent) + , mLastInternalDataUpdate(0), mLastNodeUpdate(0) +{ + mFontSize = QApplication::font().pointSize(); + + mFilterStrings.clear(); + mIdentityUpdateTimer = new QTimer(); + connect(mIdentityUpdateTimer,SIGNAL(timeout()),this,SLOT(timerUpdate())); +} + +void RsIdentityListModel::timerUpdate() +{ + emit dataChanged(index(0,0,QModelIndex()),index(2,0,QModelIndex())); +} +RsIdentityListModel::EntryIndex::EntryIndex() + : type(ENTRY_TYPE_INVALID),category_index(0),identity_index(0) +{ +} + +// The index encodes the whole hierarchy of parents. This allows to very efficiently compute indices of the parent of an index. +// +// On 32 bits and 64 bits architectures the format is the following: +// +// 0x [2 bits] 00000 [24 bits] [2 bits] +// | | | +// | | +-------------- type (0=top level, 1=category, 2=identity) +// | +----------------------- identity index +// +-------------------------------------- category index +// + +bool RsIdentityListModel::convertIndexToInternalId(const EntryIndex& e,quintptr& id) +{ + // the internal id is set to the place in the table of items. We simply shift to allow 0 to mean something special. + + if(e.type == ENTRY_TYPE_INVALID) + { + RsErr() << "ERROR: asked for the internal id of an invalid EntryIndex" ; + id = 0; + return true; + } + if(bool(e.identity_index >> 24)) + { + RsErr() << "Cannot encode more than 2^24 identities. Somthing's wrong. e.identity_index = " << std::hex << e.identity_index << std::dec ; + id = 0; + return false; + } + + id = ((0x3 & (uint32_t)e.category_index) << 30) + ((uint32_t)e.identity_index << 2) + (0x3 & (uint32_t)e.type); + + return true; +} +bool RsIdentityListModel::convertInternalIdToIndex(quintptr ref,EntryIndex& e) +{ + // Compatible with ref=0 since it will cause type=TOP_LEVEL + + e.type = static_cast((ref >> 0) & 0x3) ;// 2 bits + e.identity_index = (ref >> 2) & 0xffffff;// 24 bits + e.category_index = (ref >> 30) & 0x3 ;// 2 bits + + return true; +} + +static QIcon createAvatar(const QPixmap &avatar, const QPixmap &overlay) +{ + int avatarWidth = avatar.width(); + int avatarHeight = avatar.height(); + + QPixmap pixmap(avatar); + + int overlaySize = (avatarWidth > avatarHeight) ? (avatarWidth/2.5) : (avatarHeight/2.5); + int overlayX = avatarWidth - overlaySize; + int overlayY = avatarHeight - overlaySize; + + QPainter painter(&pixmap); + painter.drawPixmap(overlayX, overlayY, overlaySize, overlaySize, overlay); + + QIcon icon; + icon.addPixmap(pixmap); + return icon; +} + +void RsIdentityListModel::preMods() +{ + emit layoutAboutToBeChanged(); +} +void RsIdentityListModel::postMods() +{ + emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(rowCount()-1,columnCount()-1,(void*)NULL)); + emit layoutChanged(); +} + +int RsIdentityListModel::rowCount(const QModelIndex& parent) const +{ + if(parent.column() >= COLUMN_THREAD_NB_COLUMNS) + return 0; + + EntryIndex index; + + if(!parent.isValid() || !convertInternalIdToIndex(parent.internalId(),index)) + return mCategories.size(); + + switch(index.type) + { + case ENTRY_TYPE_CATEGORY: return mCategories[index.category_index].child_identity_indices.size(); + case ENTRY_TYPE_TOP_LEVEL: return mCategories.size(); + default: + return 0; + } +} + +int RsIdentityListModel::columnCount(const QModelIndex &/*parent*/) const +{ + return COLUMN_THREAD_NB_COLUMNS ; +} + +bool RsIdentityListModel::hasChildren(const QModelIndex &parent) const +{ + if(!parent.isValid()) + return true; + + EntryIndex parent_index ; + convertInternalIdToIndex(parent.internalId(),parent_index); + + if(parent_index.type == ENTRY_TYPE_TOP_LEVEL) + return true; + + if(parent_index.type == ENTRY_TYPE_IDENTITY) + return false; + + if(parent_index.type == ENTRY_TYPE_CATEGORY) + return !mCategories[parent_index.category_index].child_identity_indices.empty(); + + return false; +} + +RsIdentityListModel::EntryIndex RsIdentityListModel::EntryIndex::parent() const +{ + EntryIndex i(*this); + + switch(type) + { + case ENTRY_TYPE_CATEGORY: i.type = ENTRY_TYPE_TOP_LEVEL; + i.category_index = 0; + i.identity_index = 0; + break; + + case ENTRY_TYPE_IDENTITY: i.type = ENTRY_TYPE_CATEGORY; + i.identity_index = 0; + break; + case ENTRY_TYPE_TOP_LEVEL: + std::cerr << "ERROR: calling parent() on entryindex with no parent!" << std::endl; + + default: + //Can be when request root index. + break; + } + + return i; +} + +RsIdentityListModel::EntryIndex RsIdentityListModel::EntryIndex::child(int row) const +{ + EntryIndex i; + + switch(type) + { + case ENTRY_TYPE_TOP_LEVEL: + i.type = ENTRY_TYPE_CATEGORY; + i.category_index = row; + i.identity_index = 0; + + break; + + case ENTRY_TYPE_CATEGORY: i.type = ENTRY_TYPE_IDENTITY; + i.category_index = category_index; + i.identity_index = row; + break; + + case ENTRY_TYPE_IDENTITY: i = EntryIndex(); + std::cerr << "ERROR: calling child() on entryindex with no children!" << std::endl; + default: + break; + } + + return i; + +} +uint32_t RsIdentityListModel::EntryIndex::parentRow() const +{ + switch(type) + { + default: + case ENTRY_TYPE_TOP_LEVEL: return -1; + case ENTRY_TYPE_CATEGORY : return -1; + case ENTRY_TYPE_IDENTITY : return category_index; + } +} + +QModelIndex RsIdentityListModel::index(int row, int column, const QModelIndex& parent) const +{ + if(row < 0 || column < 0 || column >= columnCount(parent) || row >= rowCount(parent)) + return QModelIndex(); + + EntryIndex parent_index ; + convertInternalIdToIndex(parent.internalId(),parent_index); +#ifdef DEBUG_MODEL_INDEX + RsDbg() << "Index row=" << row << " col=" << column << " parent=" << parent << std::endl; +#endif + + quintptr ref; + EntryIndex new_index = parent_index.child(row); + convertIndexToInternalId(new_index,ref); + +#ifdef DEBUG_MODEL_INDEX + RsDbg() << " returning " << createIndex(row,column,ref) << std::endl; +#endif + + return createIndex(row,column,ref); +} + +QModelIndex RsIdentityListModel::parent(const QModelIndex& index) const +{ + if(!index.isValid()) + return QModelIndex(); + + EntryIndex I ; + convertInternalIdToIndex(index.internalId(),I); + + EntryIndex p = I.parent(); + + if(p.type == ENTRY_TYPE_TOP_LEVEL) + return QModelIndex(); + + quintptr i; + convertIndexToInternalId(p,i); + + return createIndex(I.parentRow(),0,i); +} + +Qt::ItemFlags RsIdentityListModel::flags(const QModelIndex& index) const +{ + if (!index.isValid()) + return Qt::ItemFlags(); + + return QAbstractItemModel::flags(index); +} + +QVariant RsIdentityListModel::headerData(int section, Qt::Orientation /*orientation*/, int role) const +{ + if(role == Qt::DisplayRole) + switch(section) + { + case COLUMN_THREAD_NAME: return tr("Name"); + case COLUMN_THREAD_ID: return tr("Id"); + case COLUMN_THREAD_REPUTATION: return QVariant(); + case COLUMN_THREAD_OWNER_ID: return tr("Owner Id"); + case COLUMN_THREAD_OWNER_NAME: return tr("Owner"); + default: + return QVariant(); + } + if(role == Qt::DecorationRole && section == COLUMN_THREAD_REPUTATION) + return QIcon(":/icons/flag-green.png"); + + return QVariant(); +} + +QVariant RsIdentityListModel::data(const QModelIndex &index, int role) const +{ +#ifdef DEBUG_MESSAGE_MODEL + std::cerr << "calling data(" << index << ") role=" << role << std::endl; +#endif + + if(!index.isValid()) + return QVariant(); + + quintptr ref = (index.isValid())?index.internalId():0 ; + +#ifdef DEBUG_MESSAGE_MODEL + std::cerr << "data(" << index << ")" ; +#endif + + if(!ref) + { +#ifdef DEBUG_MESSAGE_MODEL + std::cerr << " [empty]" << std::endl; +#endif + return QVariant() ; + } + + EntryIndex entry; + + if(!convertInternalIdToIndex(ref,entry)) + { +#ifdef DEBUG_MESSAGE_MODEL + std::cerr << "Bad pointer: " << (void*)ref << std::endl; +#endif + return QVariant() ; + } + + switch(role) + { + case Qt::SizeHintRole: return sizeHintRole(entry,index.column()) ; + case Qt::DisplayRole: return displayRole(entry,index.column()) ; + case Qt::FontRole: return fontRole(entry,index.column()) ; + case Qt::ForegroundRole: return foregroundRole(entry,index.column()) ; + case Qt::DecorationRole: return decorationRole(entry,index.column()) ; + + case FilterRole: return filterRole(entry,index.column()) ; + case SortRole: return sortRole(entry,index.column()) ; + case TreePathRole: return treePathRole(entry,index.column()) ; + + default: + return QVariant(); + } +} + +bool RsIdentityListModel::passesFilter(const EntryIndex& e,int /*column*/) const +{ + QString s ; + + if(mFilterStrings.empty() || e.type != ENTRY_TYPE_IDENTITY) + return true; + + auto passes_strings = [&](const QString& s) -> bool { + bool res = true; + + for(auto iter(mFilterStrings.begin()); iter != mFilterStrings.end(); ++iter) + res = res && s.contains(*iter,Qt::CaseInsensitive); + + return res; + }; + + if((mFilterType & FilterType::FILTER_TYPE_ID) && passes_strings(displayRole(e,COLUMN_THREAD_ID ).toString())) return true; + if((mFilterType & FilterType::FILTER_TYPE_NAME) && passes_strings(displayRole(e,COLUMN_THREAD_NAME ).toString())) return true; + if((mFilterType & FilterType::FILTER_TYPE_OWNER_ID) && passes_strings(displayRole(e,COLUMN_THREAD_OWNER_ID ).toString())) return true; + if((mFilterType & FilterType::FILTER_TYPE_OWNER_NAME) && passes_strings(displayRole(e,COLUMN_THREAD_OWNER_NAME).toString())) return true; + + return false; +} + +QVariant RsIdentityListModel::filterRole(const EntryIndex& e,int column) const +{ + if(passesFilter(e,column)) + return QVariant(FilterString); + + return QVariant(QString()); +} + +uint32_t RsIdentityListModel::updateFilterStatus(ForumModelIndex /*i*/,int /*column*/,const QStringList& /*strings*/) +{ + return 0; +} + + +void RsIdentityListModel::setFilter(uint8_t filter_type, const QStringList& strings) +{ +#ifdef DEBUG_MODEL + std::cerr << "Setting filter to filter_type=" << int(filter_type) << " and strings to " ; + foreach(const QString& str,strings) + std::cerr << "\"" << str.toStdString() << "\" " ; + std::cerr << std::endl; +#endif + + preMods(); + + mFilterType = filter_type; + mFilterStrings = strings; + + postMods(); +} + +QVariant RsIdentityListModel::toolTipRole(const EntryIndex& fmpe,int /*column*/) const +{ + switch(fmpe.type) + { + case ENTRY_TYPE_IDENTITY: + { + auto id_info = getIdentityInfo(fmpe); + + if(!id_info) + return QVariant(); + + if(id_info->flags & RS_IDENTITY_FLAGS_IS_DEPRECATED) + return QVariant( tr("\nThis identity has a insecure fingerprint (It's probably quite old).\nYou should get rid of it now and use a new one.\nThese identities are not supported anymore.") ) ; + + if(rsIdentity->isOwnId(id_info->id)) + return QVariant(tr("This identity is owned by you")); + + if(id_info->owner.isNull()) + return QVariant("Anonymous identity"); + else + { + RsPeerDetails dd; + if(rsPeers->getGPGDetails(id_info->owner,dd)) + return QVariant(tr("Identity owned by profile")+" \""+ QString::fromUtf8(dd.name.c_str()) +"\" ("+QString::fromStdString(id_info->owner.toStdString())); + else + return QVariant(tr("Identity possibly owned by unknown profile")+" \""+ QString::fromUtf8(dd.name.c_str()) +"\" ("+QString::fromStdString(id_info->owner.toStdString())); + } + } + + break; + case ENTRY_TYPE_CATEGORY: ; // fallthrough + default: + return QVariant(); + } +} + +QVariant RsIdentityListModel::sizeHintRole(const EntryIndex& e,int col) const +{ + float x_factor = QFontMetricsF(QApplication::font()).height()/14.0f ; + float y_factor = QFontMetricsF(QApplication::font()).height()/14.0f ; + + if(e.type == ENTRY_TYPE_IDENTITY) + y_factor *= 1.0; + + if(e.type == ENTRY_TYPE_CATEGORY) + y_factor *= 1.5; + + std::cerr << "sizeHintRole()" << std::endl; + switch(col) + { + default: + case COLUMN_THREAD_REPUTATION: return QVariant( QSize(x_factor * 14 , y_factor*14*1.1f )); + + case COLUMN_THREAD_NAME: + case COLUMN_THREAD_ID: + case COLUMN_THREAD_OWNER_NAME: + case COLUMN_THREAD_OWNER_ID: return QFontMetricsF(QApplication::font()).boundingRect(displayRole(e,col).toString()).size(); + } +} + +QString RsIdentityListModel::indexIdentifier(QModelIndex index) +{ + quintptr ref = (index.isValid())?index.internalId():0 ; + +#ifdef DEBUG_MESSAGE_MODEL + std::cerr << "data(" << index << ")" ; +#endif + + if(!ref) + { +#ifdef DEBUG_MESSAGE_MODEL + std::cerr << " [empty]" << std::endl; +#endif + return QString(); + } + + EntryIndex entry; + if(!convertInternalIdToIndex(ref,entry)) + return QString(); + + return treePathRole(entry,0).toString(); +} +QVariant RsIdentityListModel::treePathRole(const EntryIndex& entry,int /*column*/) const +{ + if(entry.type == ENTRY_TYPE_CATEGORY) + return QString::number((int)entry.category_index); + else + return QString::fromStdString(mIdentities[mCategories[entry.category_index].child_identity_indices[entry.identity_index]].id.toStdString()); +} +QVariant RsIdentityListModel::sortRole(const EntryIndex& entry,int column) const +{ + switch(column) + { + case COLUMN_THREAD_REPUTATION: return decorationRole(entry,column); + + case COLUMN_THREAD_ID: + case COLUMN_THREAD_OWNER_ID: + case COLUMN_THREAD_OWNER_NAME: + case COLUMN_THREAD_NAME: [[__fallthrough__]]; + default: + return displayRole(entry,column); + } +} + +QModelIndex RsIdentityListModel::getIndexOfIdentity(const RsGxsId& id) const +{ + for(uint i=0;iflags & RS_IDENTITY_FLAGS_IS_DEPRECATED) + return QVariant(QColor(Qt::red)); + + return QVariant(); +} +QVariant RsIdentityListModel::fontRole(const EntryIndex& e, int /*col*/) const +{ + QFont f; + f.setPointSize(mFontSize); + + auto it = getIdentityInfo(e); + + if(it) + { + RsGxsId id(it->id); + + if(rsIdentity->isOwnId(id)) + f.setBold(true); + } + + return QVariant(f); +} +void RsIdentityListModel::setFontSize(int s) +{ + if(s != mFontSize) + { + mFontSize = s; + emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(mCategories.size()-1,columnCount()-1,(void*)NULL)); + } +} + +#ifdef DEBUG_MODEL_INDEX + std::cerr << " font role " << e.type << ", (" << (int)e.group_index << ","<< (int)e.profile_index << ","<< (int)e.node_index << ") col="<< col<<": " << std::endl; +#endif + +#ifdef TODO + int status = onlineRole(e,col).toInt(); + + switch (status) + { + case RS_STATUS_INACTIVE: + { + QFont font ; + QTreeView* myParent = dynamic_cast(QAbstractItemModel::parent()); + if (myParent) + font = myParent->font(); + + font.setBold(true); + + return QVariant(font); + } + default: + return QVariant(); + } +#endif + +QVariant RsIdentityListModel::displayRole(const EntryIndex& e, int col) const +{ +#ifdef DEBUG_MODEL_INDEX + std::cerr << " Display role " << e.type << ", (" << (int)e.group_index << ","<< (int)e.profile_index << ","<< (int)e.node_index << ") col="<< col<<": "; +#endif + + switch(e.type) + { + case ENTRY_TYPE_CATEGORY: + { + const HierarchicalCategoryInformation *cat = getCategoryInfo(e); + + if(!cat) + return QVariant(); + + switch(col) + { + case COLUMN_THREAD_NAME: +#ifdef DEBUG_MODEL_INDEX + std::cerr << group->group_info.name.c_str() ; +#endif + + if(!cat->child_identity_indices.empty()) + return QVariant(cat->category_name+" (" + QString::number(cat->child_identity_indices.size()) + ")"); + else + return QVariant(cat->category_name); + + default: + return QVariant(); + } + } + break; + + case ENTRY_TYPE_IDENTITY: + { + const HierarchicalIdentityInformation *idinfo = getIdentityInfo(e); + const QString loading_string = "["+tr("Loading...")+"]"; + +#ifdef DEBUG_MODEL_INDEX + std::cerr << profile->profile_info.name.c_str() ; +#endif + if(col == COLUMN_THREAD_ID) return QVariant(QString::fromStdString(idinfo->id.toStdString()) ); + if(col == COLUMN_THREAD_REPUTATION) return QVariant(); + + if(idinfo->nickname.empty()) + return loading_string; + + switch(col) + { + case COLUMN_THREAD_NAME: return QVariant(QString::fromUtf8(idinfo->nickname.c_str())); + case COLUMN_THREAD_OWNER_NAME: if(idinfo->owner.isNull()) + return QVariant(); + else + return QVariant(QString::fromStdString(rsPeers->getGPGName(idinfo->owner)) ); + + case COLUMN_THREAD_OWNER_ID: if(idinfo->owner.isNull()) + return QVariant(); + else + return QVariant(QString::fromStdString(idinfo->owner.toStdString()) ); + default: + return QVariant(); + } + } + break; + + default: //ENTRY_TYPE + return QVariant(); + } +} + +// This function makes sure that the internal data gets updated. They are situations where the notification system cannot +// send the information about changes, such as when the computer is put on sleep. + +void RsIdentityListModel::checkInternalData(bool force) +{ + rstime_t now = time(NULL); + + if( (mLastInternalDataUpdate + MAX_INTERNAL_DATA_UPDATE_DELAY < now) || force) + updateIdentityList(); +} + +const RsIdentityListModel::HierarchicalCategoryInformation *RsIdentityListModel::getCategoryInfo(const EntryIndex& e) const +{ + if(e.category_index >= mCategories.size()) + return NULL ; + else + return &mCategories[e.category_index]; +} + +const RsIdentityListModel::HierarchicalIdentityInformation *RsIdentityListModel::getIdentityInfo(const EntryIndex& e) const +{ + // First look into the relevant group, then for the correct profile in this group. + + if(e.type != ENTRY_TYPE_IDENTITY) + return nullptr ; + + if(e.category_index >= mCategories.size()) + return nullptr ; + + if(e.identity_index < mCategories[e.category_index].child_identity_indices.size()) + { + auto& it(mIdentities[mCategories[e.category_index].child_identity_indices[e.identity_index]]); + rstime_t now = time(nullptr); + + if(now > it.last_update_TS + ID_DETAILS_UPDATE_DELAY) + { + RsIdentityDetails det; + if(rsIdentity->getIdDetails(it.id,det)) + { + it.nickname = det.mNickname; + it.owner = det.mPgpId; + it.flags = det.mFlags; + it.last_update_TS = now; + } + } + return ⁢ + } + else + { + RsErr() << "Inconsistent identity index!" ; + return nullptr; + } +} + +QVariant RsIdentityListModel::decorationRole(const EntryIndex& entry,int col) const +{ + switch(entry.type) + { + case ENTRY_TYPE_CATEGORY: + return QVariant(); + + case ENTRY_TYPE_IDENTITY: + { + const HierarchicalIdentityInformation *hn = getIdentityInfo(entry); + + if(!hn) + return QVariant(); + + if(col == COLUMN_THREAD_REPUTATION) + return QVariant( static_cast(rsReputations->overallReputationLevel(hn->id)) ); + else if(col == COLUMN_THREAD_NAME) + { + QPixmap sslAvatar; + RsIdentityDetails details ; + + if(!rsIdentity->getIdDetails(hn->id, details)) + { + mIdentityUpdateTimer->stop(); + mIdentityUpdateTimer->setSingleShot(true); + mIdentityUpdateTimer->start(500); + return QVariant(); + } + else if(details.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(details.mAvatar.mData, details.mAvatar.mSize, sslAvatar,GxsIdDetails::LARGE)) + return QVariant(QIcon(GxsIdDetails::makeDefaultIcon(hn->id,GxsIdDetails::SMALL))); + else + return QVariant(QIcon(sslAvatar)); + } + else + return QVariant(); + } + break; + + default: + return QVariant(); + } +} + +void RsIdentityListModel::clear() +{ + preMods(); + + mIdentities.clear(); + mCategories.clear(); + + mCategories.resize(3); + mCategories[0].category_name = tr("My own identities"); + mCategories[1].category_name = tr("My contacts"); + mCategories[2].category_name = tr("All"); + + postMods(); + + emit friendListChanged(); +} + + +void RsIdentityListModel::debug_dump() const +{ + std::cerr << "==== IdentityListModel Debug dump ====" << std::endl; + + std::cerr << "Invalid index : " << QModelIndex() << std::endl; + + EntryIndex top_level; + top_level.type = ENTRY_TYPE_TOP_LEVEL; + quintptr id; + convertIndexToInternalId(top_level,id); + + std::cerr << "Top level index: " << createIndex(0,0,id) << std::endl; + EntryIndex tei; + convertInternalIdToIndex(0,tei); + std::cerr << "Top level entry index: " << tei << std::endl; + + for(uint32_t j=0;jid; + else + return RsGxsId(); +} + +RsIdentityListModel::EntryType RsIdentityListModel::getType(const QModelIndex& i) const +{ + if(!i.isValid()) + return ENTRY_TYPE_TOP_LEVEL; + + EntryIndex e; + if(!convertInternalIdToIndex(i.internalId(),e)) + return ENTRY_TYPE_TOP_LEVEL; + + return e.type; +} + +int RsIdentityListModel::getCategory(const QModelIndex& i) const +{ + if(!i.isValid()) + return CATEGORY_ALL; + + EntryIndex e; + if(!convertInternalIdToIndex(i.internalId(),e)) + return CATEGORY_ALL; + + return e.category_index; +} +void RsIdentityListModel::setIdentities(const std::list& identities_meta) +{ + preMods(); + beginResetModel(); + clear(); + + for(auto id:identities_meta) + { + HierarchicalIdentityInformation idinfo; + idinfo.id = RsGxsId(id.mGroupId); + idinfo.last_update_TS = 0;// forces update + + if(rsIdentity->isOwnId(idinfo.id)) + mCategories[CATEGORY_OWN].child_identity_indices.push_back(mIdentities.size()); + else if(rsIdentity->isARegularContact(RsGxsId(id.mGroupId))) + mCategories[CATEGORY_CTS].child_identity_indices.push_back(mIdentities.size()); + else + mCategories[CATEGORY_ALL].child_identity_indices.push_back(mIdentities.size()); + + mIdentities.push_back(idinfo); + } + + if (mCategories.size()>0) + { + beginInsertRows(QModelIndex(),0,mCategories.size()-1); + endInsertRows(); + } + + endResetModel(); + postMods(); + + mLastInternalDataUpdate = time(NULL); + +} + +void RsIdentityListModel::updateIdentityList() +{ + std::cerr << "Updating identity list" << std::endl; + + std::list ids ; + + if(!rsIdentity->getIdentitiesSummaries(ids)) + { + std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve identity metadata." << std::endl; + return; + } + + setIdentities(ids) ; + + debug_dump(); +} + + + +void RsIdentityListModel::collapseItem(const QModelIndex& index) +{ + if(getType(index) != ENTRY_TYPE_CATEGORY) + return; + + EntryIndex entry; + + if(!convertInternalIdToIndex(index.internalId(),entry)) + return; + + mExpandedCategories[entry.category_index] = false; + + // apparently we cannot be subtle here. + emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(mCategories.size()-1,columnCount()-1,(void*)NULL)); +} + +void RsIdentityListModel::expandItem(const QModelIndex& index) +{ + if(getType(index) != ENTRY_TYPE_CATEGORY) + return; + + EntryIndex entry; + + if(!convertInternalIdToIndex(index.internalId(),entry)) + return; + + mExpandedCategories[entry.category_index] = true; + + // apparently we cannot be subtle here. + emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(mCategories.size()-1,columnCount()-1,(void*)NULL)); +} + + + diff --git a/retroshare-gui/src/gui/Identity/IdentityListModel.h b/retroshare-gui/src/gui/Identity/IdentityListModel.h new file mode 100644 index 000000000..4c3cb43e2 --- /dev/null +++ b/retroshare-gui/src/gui/Identity/IdentityListModel.h @@ -0,0 +1,252 @@ +/******************************************************************************* + * retroshare-gui/src/gui/msgs/RsFriendListModel.h * + * * + * Copyright 2019 by Cyril Soler * + * * + * 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 . * + * * + *******************************************************************************/ + +#pragma once + +#include +#include + +#include "retroshare/rsstatus.h" +#include "retroshare/rsmsgs.h" +#include "retroshare/rspeers.h" +#include "retroshare/rsidentity.h" + +typedef uint32_t ForumModelIndex; + +// This class is the item model used by Qt to display the information + +class QTimer; + +class RsIdentityListModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit RsIdentityListModel(QObject *parent = NULL); + ~RsIdentityListModel(){} + + enum Columns { + COLUMN_THREAD_NAME = 0x00, + COLUMN_THREAD_ID = 0x01, + COLUMN_THREAD_OWNER_NAME = 0x02, + COLUMN_THREAD_OWNER_ID = 0x03, + COLUMN_THREAD_REPUTATION = 0x04, + COLUMN_THREAD_NB_COLUMNS = 0x05 + }; + + enum Roles{ SortRole = Qt::UserRole+1, + StatusRole = Qt::UserRole+2, + UnreadRole = Qt::UserRole+3, + FilterRole = Qt::UserRole+4, + TreePathRole = Qt::UserRole+5, + }; + + enum FilterType{ FILTER_TYPE_NONE = 0x00, + FILTER_TYPE_ID = 0x01, + FILTER_TYPE_NAME = 0x02, + FILTER_TYPE_OWNER_NAME = 0x04, + FILTER_TYPE_OWNER_ID = 0x08 + }; + + enum EntryType{ ENTRY_TYPE_TOP_LEVEL = 0x00, + ENTRY_TYPE_CATEGORY = 0x01, + ENTRY_TYPE_IDENTITY = 0x02, + ENTRY_TYPE_INVALID = 0x03 + }; + + enum Category{ CATEGORY_OWN = 0x00, + CATEGORY_CTS = 0x01, + CATEGORY_ALL = 0x02 + }; + + struct HierarchicalCategoryInformation + { + QString category_name; + std::vector child_identity_indices; // index in the array of hierarchical profiles + }; + + // This stores all the info that is useful avoiding a call to the more expensive getIdDetails() + // + struct HierarchicalIdentityInformation + { + rstime_t last_update_TS; + RsGxsId id; + RsPgpId owner; + uint32_t flags; + std::string nickname; + }; + + // 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) + + friend std::ostream& operator<<(std::ostream& o, const EntryIndex& e) + { + o << "[" ; + switch(e.type) + { + case RsIdentityListModel::ENTRY_TYPE_INVALID: o << "Invalid," ; break; + case RsIdentityListModel::ENTRY_TYPE_CATEGORY: o << "Category," ; break; + case RsIdentityListModel::ENTRY_TYPE_IDENTITY: o << "Identity," ; break; + case RsIdentityListModel::ENTRY_TYPE_TOP_LEVEL: o << "Toplevel," ; break; + } + o << " CI: " << e.category_index << ", "; + o << " II: " << e.identity_index << "]"; + return o; + } + + // 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 category_index; // index of the category in the mCategory array + uint16_t identity_index; // index of the identity in its own category + + EntryIndex parent() const; + EntryIndex child(int row) const; + uint32_t parentRow() const; + }; + + QModelIndex root() const{ return createIndex(0,0,(void*)NULL) ;} + QModelIndex getIndexOfIdentity(const RsGxsId& id) const; + QModelIndex getIndexOfCategory(Category id) const; + + void updateIdentityList(); + + int count() const { return mIdentities.size() ; } // total number of identities + + static const QString FilterString ; + + // This method will asynchroneously update the data + + EntryType getType(const QModelIndex&) const; + RsGxsId getIdentity(const QModelIndex&) const; + int getCategory(const QModelIndex&) const; + void setFontSize(int s); + + void setFilter(uint8_t 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() ; + QString indexIdentifier(QModelIndex i); + + /* Color definitions (for standard see default.qss) */ + QColor mTextColorGroup; + QColor mTextColorStatus[RS_STATUS_COUNT]; + + void setIdentities(const std::list& identities_meta); + +private: + const HierarchicalCategoryInformation *getCategoryInfo (const EntryIndex&) const; + const HierarchicalIdentityInformation *getIdentityInfo(const EntryIndex&) const; + + void checkIdentity(HierarchicalIdentityInformation& node); + + 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 foregroundRole(const EntryIndex& e, int col) const; + QVariant textColorRole (const EntryIndex& e, int col) const; + QVariant filterRole (const EntryIndex& e, int col) const; + QVariant treePathRole (const EntryIndex& entry,int column) 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; + void timerUpdate(); + +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: + 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; + + static bool convertIndexToInternalId(const EntryIndex& e,quintptr& ref); + static bool convertInternalIdToIndex(quintptr ref, EntryIndex& e); + + uint32_t updateFilterStatus(ForumModelIndex i,int column,const QStringList& strings); + + QStringList mFilterStrings; + uint8_t mFilterType; + int mFontSize; + + 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 mCategories; + mutable std::vector mIdentities; + + // 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 mTopLevel; + + // keeps track of expanded/collapsed items, so as to only show icon for collapsed profiles + + std::vector mExpandedCategories; + + // List of identities for which getIdDetails() failed, to be requested again. + mutable QTimer *mIdentityUpdateTimer; +}; + + diff --git a/retroshare-gui/src/gui/MainPage.cpp b/retroshare-gui/src/gui/MainPage.cpp index 545f1270e..6136343d7 100644 --- a/retroshare-gui/src/gui/MainPage.cpp +++ b/retroshare-gui/src/gui/MainPage.cpp @@ -18,12 +18,14 @@ * * *******************************************************************************/ -#include -#include - #include + #include "common/FloatingHelpBrowser.h" #include "gui/settings/rsharesettings.h" +#include "util/misc.h" + +#include +#include MainPage::MainPage(QWidget *parent , Qt::WindowFlags flags ) : QWidget(parent, flags) { @@ -44,13 +46,13 @@ UserNotify *MainPage::getUserNotify() void MainPage::registerHelpButton(QToolButton *button, const QString& help_html_text, const QString &code_name) { - mHelpCodeName = code_name ; + mHelpCodeName = code_name ; - if (mHelpBrowser == NULL) + if (mHelpBrowser == nullptr) mHelpBrowser = new FloatingHelpBrowser(this, button) ; - float S = QFontMetricsF(button->font()).height() ; - button->setIconSize(QSize(S,S)) ; + int H = misc::getFontSizeFactor("HelpButton").height(); + button->setIconSize(QSize(H, H)) ;//Square Icon mHelpBrowser->setHelpText(help_html_text) ; } diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index 8ba6a0a90..5ba8f1ddd 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -21,15 +21,23 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include #include #include +#include + +#if defined(Q_OS_DARWIN) +#include "gui/common/MacDockIconHandler.h" +#endif #ifdef MESSENGER_WINDOW #include "MessengerWindow.h" @@ -113,7 +121,7 @@ #include "gui/statistics/StatisticsWindow.h" #include "gui/connect/ConnectFriendWizard.h" -#include "gui/common/RsCollection.h" +#include "gui/common/RsCollectionDialog.h" #include "settings/rsettingswin.h" #include "settings/rsharesettings.h" #include "common/StatusDefs.h" @@ -140,12 +148,10 @@ #define IMAGE_OVERLAY ":/icons/star_overlay_128.png" #define IMAGE_BWGRAPH ":/icons/png/bandwidth.png" -#define IMAGE_MESSENGER ":/images/rsmessenger48.png" #define IMAGE_COLOR ":/images/highlight.png" #define IMAGE_NEWRSCOLLECTION ":/images/library.png" #define IMAGE_ADDSHARE ":/images/directoryadd_24x24_shadow.png" #define IMAGE_OPTIONS ":/images/settings.png" -#define IMAGE_UNFINISHED ":/images/underconstruction.png" #define IMAGE_MINIMIZE ":/icons/fullscreen.png" #define IMAGE_MAXIMIZE ":/icons/fullscreen-exit.png" @@ -207,7 +213,7 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags) hiddenmode = true; } - setWindowTitle(tr("RetroShare %1 a secure decentralized communication platform").arg(Rshare::retroshareVersion(true)) + " - " + nameAndLocation); + setWindowTitle(tr("RetroShare %1 a secure decentralized communication platform").arg(RsApplication::retroshareVersion(true)) + " - " + nameAndLocation); connect(rApp, SIGNAL(newArgsReceived(QStringList)), this, SLOT(receiveNewArgs(QStringList))); /* add url handler for RetroShare links */ @@ -247,12 +253,13 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags) statusBar()->setVisible(Settings->valueFromGroup("StatusBar", "ShowStatusBar", QVariant(true)).toBool()); /* initialize combobox in status bar */ - statusComboBox = new QComboBox(statusBar()); + statusComboBox = new RSComboBox(statusBar()); statusComboBox->setVisible(Settings->valueFromGroup("StatusBar", "ShowStatus", QVariant(true)).toBool()); statusComboBox->setFocusPolicy(Qt::ClickFocus); initializeStatusObject(statusComboBox, true); QWidget *widget = new QWidget(); + widget->setObjectName("trans_statusComboBoxFrame"); QHBoxLayout *hbox = new QHBoxLayout(); hbox->setMargin(0); hbox->setSpacing(6); @@ -354,6 +361,8 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags) connect(NotifyQt::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); settingsChanged(); + + mFontSizeHandler.registerFontSize(ui->listWidget, 1.5f); } /** Destructor. */ @@ -377,6 +386,11 @@ MainWindow::~MainWindow() delete sysTrayStatus; delete trayIcon; delete trayMenu; +#if defined(Q_OS_DARWIN) + delete menuBar; + delete dockMenu; + MacDockIconHandler::cleanup(); +#endif // delete notifyMenu; // already deleted by the deletion of trayMenu StatisticsWindow::releaseInstance(); @@ -466,10 +480,8 @@ void MainWindow::initStackedPage() } #ifndef RS_RELEASE_VERSION -#ifdef PLUGINMGR addPage(pluginsPage = new gui::PluginsPage(ui->stackPages), grp, NULL); #endif -#endif #undef GETSTARTED_GUI #ifdef GETSTARTED_GUI @@ -487,11 +499,11 @@ void MainWindow::initStackedPage() addPage(newsFeed = new NewsFeed(ui->stackPages), grp, ¬ify); //List All notify before Setting was created - QList > >::iterator notifyIt; - for (notifyIt = notify.begin(); notifyIt != notify.end(); ++notifyIt) { - UserNotify *userNotify = notifyIt->first->getUserNotify(); + for (auto notifyIt:notify) + { + UserNotify *userNotify = notifyIt.first->getUserNotify(); if (userNotify) { - userNotify->initialize(ui->toolBarPage, notifyIt->second.first, notifyIt->second.second); + userNotify->initialize(ui->toolBarPage, notifyIt.second.first, notifyIt.second.second); connect(userNotify, SIGNAL(countChanged()), this, SLOT(updateTrayCombine())); userNotifyList.push_back(userNotify); } @@ -505,7 +517,7 @@ void MainWindow::initStackedPage() #ifdef UNFINISHED - addAction(new QAction(QIcon(IMAGE_UNFINISHED), tr("Unfinished"), ui->toolBar), &MainWindow::showApplWindow, SLOT(showApplWindow())); + addAction(new QAction(QIcon(), tr("Unfinished"), ui->toolBar), &MainWindow::showApplWindow, SLOT(showApplWindow())); ui->toolBarAction->addSeparator(); notify += applicationWindow->getNotify(); #endif @@ -555,6 +567,11 @@ void MainWindow::addPage(MainPage *page, QActionGroup *grp, QListiconPixmap()),page->pageName()) ; ui->listWidget->addItem(item) ; +#if defined(Q_OS_DARWIN) + QFont f = ui->toolBarPage->font(); + action->setFont(f); +#endif + if (notify) { QPair pair = QPair( action, item); @@ -623,7 +640,7 @@ void MainWindow::createTrayIcon() trayMenu->addSeparator(); #ifdef MESSENGER_WINDOW - trayMenu->addAction(QIcon(IMAGE_MESSENGER), tr("Open Messenger"), this, SLOT(showMessengerWindow())); + trayMenu->addAction(QIcon(), tr("Open Messenger"), this, SLOT(showMessengerWindow())); #endif trayMenu->addAction(QIcon(IMAGE_MESSAGES), tr("Open Messages"), this, SLOT(showMess())); #ifdef RS_JSONAPI @@ -636,7 +653,7 @@ void MainWindow::createTrayIcon() #ifdef UNFINISHED - trayMenu->addAction(QIcon(IMAGE_UNFINISHED), tr("Applications"), this, SLOT(showApplWindow())); + trayMenu->addAction(QIcon(), tr("Applications"), this, SLOT(showApplWindow())); #endif trayMenu->addAction(QIcon(IMAGE_PREFERENCES), tr("Options"), this, SLOT(showSettings())); trayMenu->addAction(QIcon(IMG_HELP), tr("Help"), this, SLOT(showHelpDialog())); @@ -653,10 +670,75 @@ void MainWindow::createTrayIcon() trayIcon->setContextMenu(trayMenu); trayIcon->setIcon(QIcon(IMAGE_NOONLINE)); +#if defined(Q_OS_DARWIN) + // Note: On macOS, the Dock icon is used to provide the tray's functionality. + MacDockIconHandler* dockIconHandler = MacDockIconHandler::instance(); + connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, [this] { + show(); + activateWindow(); + }); +#endif + +#if defined(Q_OS_DARWIN) + createMenuBar(); +#endif + connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleVisibility(QSystemTrayIcon::ActivationReason))); trayIcon->show(); } +#if defined(Q_OS_DARWIN) +/** Creates a new menubar for macOS */ +void MainWindow::createMenuBar() +{ + /* Mac users sure like their shortcuts. */ + actionMinimize = new QAction(tr("Minimize"),this); + actionMinimize->setShortcutContext(Qt::ApplicationShortcut); + actionMinimize->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M)); + actionMinimize->setShortcutVisibleInContextMenu(true); + connect(actionMinimize,SIGNAL(triggered()),this,SLOT(minimizeWindow())) ; + + actionCloseWindow = new QAction(tr("Close window"),this); + actionCloseWindow->setShortcutContext(Qt::ApplicationShortcut); + actionCloseWindow->setShortcut(QKeySequence::Close); + actionCloseWindow->setShortcutVisibleInContextMenu(true); + connect(actionCloseWindow,SIGNAL(triggered()),this,SLOT(closeWindow())) ; + + menuBar = new QMenuBar(this); + QMenu *fileMenu = menuBar->addMenu(""); + fileMenu->addAction(actionMinimize); + fileMenu->addAction(actionCloseWindow); + + dockMenu = new QMenu(this); + dockMenu->setAsDockMenu(); + dockMenu->addAction(tr("Open Messages"), this, SLOT(showMess())); + dockMenu->addAction(tr("Bandwidth Graph"), this, SLOT(showBandwidthGraph())); + dockMenu->addAction(tr("Statistics"), this, SLOT(showStatisticsWindow())); + dockMenu->addAction(tr("Options"), this, SLOT(showSettings())); + dockMenu->addAction(tr("Help"), this, SLOT(showHelpDialog())); + + dockMenu->addSeparator(); + QMenu *statusMenu = dockMenu->addMenu(tr("Status")); + initializeStatusObject(statusMenu, true); + +} +#endif + +#if defined(Q_OS_DARWIN) +void MainWindow::minimizeWindow() +{ + setWindowState(windowState() | Qt::WindowMinimized); +} +#endif + +#if defined(Q_OS_DARWIN) +void MainWindow::closeWindow() +{ + // On macOS window close is basically equivalent to window hide. + close(); +} +#endif + void MainWindow::showBandwidthGraph() { if(_bandwidthGraph == NULL) @@ -948,6 +1030,7 @@ void SetForegroundWindowInternal(HWND hWnd) /* Show the dialog. */ raiseWindow(); + /* Set the focus to the specified page. */ _instance->ui->stackPages->setCurrentPage(page); } @@ -1081,7 +1164,9 @@ void SetForegroundWindowInternal(HWND hWnd) return _instance->gxsforumDialog; case Posted: return _instance->postedDialog; - } + case Home: + return _instance->homePage; + } return NULL; } @@ -1178,10 +1263,91 @@ void MainWindow::doQuit() rApp->quit(); } +// This method parses arguments passed by the operating system. All arguments +// except -r, -f, -o and lists of rscollection files and rslinks are discarded. +// void MainWindow::receiveNewArgs(QStringList args) { - Rshare::parseArguments(args, false); - processLastArgs(); + RsInfo() << "Received new arguments from operating system call."; + + std::string argstring = RsApplication::applicationFilePath().toStdString() ; + + for(auto l:args) + argstring += " " + l.toStdString(); + + // This class does all the job at once: validate arguments, and parses them. + + std::vector links_and_files; + + argstream as(argstring.c_str()); + + QString omValues = QString(";full;noturtle;gaming;minimal;"); + std::string opModeStr; + std::string retroshare_link_url; + std::string rscollection_file; + + as >> parameter('r',"rslink",retroshare_link_url,"Retroshare:// link","Retroshare link to open in Downloads " ,false) + >> parameter('f',"rsfile",rscollection_file,"file","File to open " ,false) + >> parameter('o',"opmode",opModeStr,"opmode","Set mode (Full, NoTurtle, Gaming, Minimal) " ,false) + >> values(back_inserter(links_and_files),"links and files"); + + if(!as.isOk()) + { + RsErr() << "Error while parsing arguments:" ; + RsErr() << as.errorLog() ; + return; + } + if(!opModeStr.empty() && omValues.contains(";"+QString::fromStdString(opModeStr).toLower()+";")) + { + QString opmode = QString::fromStdString(opModeStr).toLower(); + //RsApplication::setOpMode(opModeStr.toLower()); // Do we need this?? + + RsInfo() << "Setting new operating mode to \"" << opmode.toStdString() << "\""; + + if (opmode == "noturtle") + opModeStatus->setCurrentIndex(static_cast::type>(RsOpMode::NOTURTLE) - 1); + else if (opmode == "gaming") + opModeStatus->setCurrentIndex(static_cast::type>(RsOpMode::GAMING) - 1); + else if (opmode == "minimal") + opModeStatus->setCurrentIndex(static_cast::type>(RsOpMode::MINIMAL) - 1); + else if (opmode != "") + opModeStatus->setCurrentIndex(static_cast::type>(RsOpMode::FULL) - 1); + + opModeStatus->setOpMode(); + } + + // Sort all collected arguments into rscollection files and retroshare links, accordingly + + QStringList rscollection_files; + QList rslinks; + + auto sort = [&](const QString s) { + + if(QFile(s).exists() && s.endsWith(".rscollection")) + rscollection_files.append(QString::fromUtf8(rscollection_file.c_str())); + else if(s.startsWith("retroshare://")) + { + RetroShareLink link(s); + + if(link.valid()) + rslinks.push_back(link); + } + }; + + sort(QString::fromUtf8(rscollection_file.c_str())); + sort(QString::fromUtf8(retroshare_link_url.c_str())); + + for(auto s:links_and_files) + sort(QString::fromUtf8(s.c_str())); + + // Now handle links and rscollection files. + + for(auto file:rscollection_files) + if(file.endsWith(".rscollection")) + openRsCollection(file); + + for(auto link:rslinks) + retroshareLinkActivated(link.toUrl()); } void MainWindow::displayErrorMessage(int /*a*/,int /*b*/,const QString& error_msg) @@ -1220,7 +1386,11 @@ void MainWindow::updateMenu() void MainWindow::toggleVisibility(QSystemTrayIcon::ActivationReason e) { +#if defined(Q_OS_DARWIN) + if (e == QSystemTrayIcon::DoubleClick) { +#else if (e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick) { +#endif if (isHidden() || isMinimized()) { show(); if (isMinimized()) { @@ -1300,7 +1470,7 @@ static void setStatusObject(QObject *pObject, int nStatus) } return; } - QComboBox *pComboBox = dynamic_cast(pObject); + RSComboBox *pComboBox = dynamic_cast(pObject); if (pComboBox) { /* set index of combobox */ int nIndex = pComboBox->findData(nStatus, Qt::UserRole); @@ -1389,7 +1559,7 @@ void MainWindow::initializeStatusObject(QObject *pObject, bool bConnect) } } else { /* initialize combobox */ - QComboBox *pComboBox = dynamic_cast(pObject); + RSComboBox *pComboBox = dynamic_cast(pObject); if (pComboBox) { pComboBox->addItem(QIcon(StatusDefs::imageStatus(RS_STATUS_ONLINE)), StatusDefs::name(RS_STATUS_ONLINE), RS_STATUS_ONLINE); pComboBox->addItem(QIcon(StatusDefs::imageStatus(RS_STATUS_BUSY)), StatusDefs::name(RS_STATUS_BUSY), RS_STATUS_BUSY); @@ -1544,45 +1714,9 @@ void MainWindow::retroshareLinkActivated(const QUrl &url) void MainWindow::openRsCollection(const QString &filename) { QFileInfo qinfo(filename); - if (qinfo.exists()) { - if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { - RsCollection collection; - collection.openColl(qinfo.absoluteFilePath()); - } - } -} - -void MainWindow::processLastArgs() -{ - while (!Rshare::links()->isEmpty()) { - std::cerr << "MainWindow::processLastArgs() : " << Rshare::links()->count() << std::endl; - /* Now use links from the command line, because no RetroShare was running */ - RetroShareLink link(Rshare::links()->takeFirst()); - if (link.valid()) { - retroshareLinkActivated(link.toUrl()); - } - } - while (!Rshare::files()->isEmpty()) { - /* Now use files from the command line, because no RetroShare was running */ - openRsCollection(Rshare::files()->takeFirst()); - } - /* Handle the -opmode options. */ - if (opModeStatus) { - QString opmode = Rshare::opmode().toLower(); - if (opmode == "noturtle") { - opModeStatus->setCurrentIndex(static_cast::type>(RsOpMode::NOTURTLE) - 1); - } else if (opmode == "gaming") { - opModeStatus->setCurrentIndex(static_cast::type>(RsOpMode::GAMING) - 1); - } else if (opmode == "minimal") { - opModeStatus->setCurrentIndex(static_cast::type>(RsOpMode::MINIMAL) - 1); - } else if (opmode != "") { - opModeStatus->setCurrentIndex(static_cast::type>(RsOpMode::FULL) - 1); - } - opModeStatus->setOpMode(); - } else { - std::cerr << "ERR: MainWindow::processLastArgs opModeStatus is not initialized."; - } + if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) + RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath()); } void MainWindow::switchVisibilityStatus(StatusElement e,bool b) @@ -1613,7 +1747,7 @@ void MainWindow::switchVisibilityStatus(StatusElement e,bool b) //{ // ServicePermissionDialog::showYourself(); //} -QComboBox *MainWindow::statusComboBoxInstance() +RSComboBox *MainWindow::statusComboBoxInstance() { return statusComboBox; } @@ -1628,6 +1762,11 @@ NATStatus *MainWindow::natstatusInstance() return natstatus; } +void MainWindow::torstatusReset() +{ + if(torstatus != nullptr) + torstatus->reset(); +} DHTStatus *MainWindow::dhtstatusInstance() { return dhtstatus; @@ -1688,3 +1827,19 @@ void MainWindow::setCompactStatusMode(bool compact) ratesstatus->setCompactMode(compact); //opModeStatus: TODO Show only ??? } + +Gui_InputDialogReturn MainWindow::guiInputDialog(const QString& windowTitle, const QString& labelText, QLineEdit::EchoMode textEchoMode, bool modal) +{ + + QInputDialog dialog(this); + dialog.setWindowTitle(windowTitle); + dialog.setLabelText(labelText); + dialog.setTextEchoMode(textEchoMode); + dialog.setModal(modal); + + Gui_InputDialogReturn ret; + ret.execReturn = dialog.exec(); + ret.textValue = dialog.textValue(); + + return ret; +} diff --git a/retroshare-gui/src/gui/MainWindow.h b/retroshare-gui/src/gui/MainWindow.h index be459d295..b435524f0 100644 --- a/retroshare-gui/src/gui/MainWindow.h +++ b/retroshare-gui/src/gui/MainWindow.h @@ -21,16 +21,18 @@ #ifndef _MainWindow_H #define _MainWindow_H +#include #include #include #include "gui/common/rwindow.h" +#include "gui/common/RSComboBox.h" +#include "util/FontSizeHandler.h" namespace Ui { class MainWindow; } -class QComboBox; class QLabel; class QActionGroup; class QListWidgetItem; @@ -74,6 +76,14 @@ class MessengerWindow; class ApplicationWindow; #endif + +struct Gui_InputDialogReturn +{ + int execReturn; + QString textValue; +}; +Q_DECLARE_METATYPE(Gui_InputDialogReturn); + class MainWindow : public RWindow { Q_OBJECT @@ -91,9 +101,10 @@ public: Channels = 6, /** Channels page. */ Forums = 7, /** Forums page. */ Search = 8, /** Search page. */ - Posted = 11, /** Posted links */ - People = 12, /** People page. */ - Options = 13 /** People page. */ + Posted = 11, /** Posted links */ + People = 12, /** People page. */ + Options = 13, /** People page. */ + Home = 14 /** Home page. */ }; @@ -174,9 +185,10 @@ public: void removeStatusObject(QObject *pObject); void setStatus(QObject *pObject, int nStatus); - QComboBox *statusComboBoxInstance(); + RSComboBox *statusComboBoxInstance(); PeerStatus *peerstatusInstance(); NATStatus *natstatusInstance(); + void torstatusReset(); DHTStatus *dhtstatusInstance(); HashingStatus *hashingstatusInstance(); DiscStatus *discstatusInstance(); @@ -192,7 +204,7 @@ public: } static bool hiddenmode; - + public slots: void receiveNewArgs(QStringList args); void displayErrorMessage(int,int,const QString&) ; @@ -203,16 +215,41 @@ public slots: void externalLinkActivated(const QUrl &url); void retroshareLinkActivated(const QUrl &url); void openRsCollection(const QString &filename); - void processLastArgs(); //! Go to a specific part of the control panel. void setNewPage(int page); void setCompactStatusMode(bool compact); void showBandwidthGraph(); void toggleStatusToolTip(bool toggle); + + /** + * @brief Create a QInputDialog. This must be called in MainWindow thread because Widgets must be created in the GUI thread. + * Here an exemple how to call it: + * + * bool sameThread = QThread::currentThread() == qApp->thread(); + * Gui_InputDialogReturn ret; + * qRegisterMetaType("Gui_InputDialogReturn"); + * QMetaObject::invokeMethod( MainWindow::getInstance() + * , "guiInputDialog" + * , sameThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection + * , Q_RETURN_ARG(Gui_InputDialogReturn, ret) + * , Q_ARG(QString, windowTitle) + * , Q_ARG(QString, labelText) + * , Q_ARG(QLineEdit::EchoMode, textEchoMode) + * , Q_ARG(bool, modal) + * ); + * + * @param windowTitle: the window title (caption). + * @param labelText: label's text which describes what needs to be input. + * @param textEchoMode: the echo mode for the text value. + * @param modal: pop up the dialog as modal or modeless. + * @return Gui_InputDialogReturn ( Accepted(1)|Rejected(0), text value for the input dialog) + */ + Gui_InputDialogReturn guiInputDialog(const QString& windowTitle, const QString& labelText, QLineEdit::EchoMode textEchoMode, bool modal); + protected: /** Default Constructor */ - MainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0); + MainWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags()); void closeEvent(QCloseEvent *); @@ -228,6 +265,11 @@ private slots: void toggleVisibility(QSystemTrayIcon::ActivationReason e); void toggleVisibilitycontextmenu(); +#if defined(Q_OS_DARWIN) + void minimizeWindow(); + void closeWindow(); +#endif + /** Toolbar fns. */ void addFriend(); //void newRsCollection(); @@ -271,6 +313,10 @@ private: void initStackedPage(); void addPage(MainPage *page, QActionGroup *grp, QList > > *notify); void createTrayIcon(); +#if defined(Q_OS_DARWIN) + /** Creates a default menubar on Mac */ + void createMenuBar(); +#endif void createNotifyIcons(); static MainWindow *_instance; @@ -287,6 +333,14 @@ private: QString nameAndLocation; +#if defined(Q_OS_DARWIN) + /** The menubar (Mac OS X only). */ + QMenuBar *menuBar; + QMenu *dockMenu; + QAction* actionMinimize; + QAction* actionCloseWindow; +#endif + QSystemTrayIcon *trayIcon; QMenu *notifyMenu; QMenu *trayMenu; @@ -294,7 +348,7 @@ private: QAction *toggleVisibilityAction, *toolAct; QList userNotifyList; - QComboBox *statusComboBox; + RSComboBox *statusComboBox; PeerStatus *peerstatus; NATStatus *natstatus; DHTStatus *dhtstatus; @@ -318,6 +372,8 @@ private: void setIdle(bool Idle); bool isIdle; + FontSizeHandler mFontSizeHandler; + Ui::MainWindow *ui ; }; diff --git a/retroshare-gui/src/gui/MainWindow.ui b/retroshare-gui/src/gui/MainWindow.ui index d1dc1c2f7..796593dfd 100644 --- a/retroshare-gui/src/gui/MainWindow.ui +++ b/retroshare-gui/src/gui/MainWindow.ui @@ -143,7 +143,7 @@
- + :/images/add-share24.png:/images/add-share24.png @@ -152,7 +152,7 @@ - + :/images/kcmsystem24.png:/images/kcmsystem24.png @@ -161,7 +161,7 @@ - + :/images/messenger.png:/images/messenger.png @@ -187,7 +187,7 @@ - + :/images/exit_24x24.png:/images/exit_24x24.png diff --git a/retroshare-gui/src/gui/MessengerWindow.ui b/retroshare-gui/src/gui/MessengerWindow.ui index 7e952e86b..cc81303b8 100644 --- a/retroshare-gui/src/gui/MessengerWindow.ui +++ b/retroshare-gui/src/gui/MessengerWindow.ui @@ -74,7 +74,7 @@ - + true @@ -124,7 +124,7 @@ - + 0 @@ -175,7 +175,7 @@ 0 0 258 - 21 + 27 @@ -199,6 +199,11 @@
gui/LogoBar.h
1 + + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
diff --git a/retroshare-gui/src/gui/NetworkDialog.cpp b/retroshare-gui/src/gui/NetworkDialog.cpp index 1b02cbc7c..7c2b3fd14 100644 --- a/retroshare-gui/src/gui/NetworkDialog.cpp +++ b/retroshare-gui/src/gui/NetworkDialog.cpp @@ -73,7 +73,7 @@ NetworkDialog::NetworkDialog(QWidget */*parent*/) PGPIdItemProxy = new pgpid_item_proxy(this); connect(ui.onlyTrustedKeys, SIGNAL(toggled(bool)), PGPIdItemProxy, SLOT(use_only_trusted_keys(bool))); PGPIdItemProxy->setSourceModel(PGPIdItemModel); - PGPIdItemProxy->setFilterKeyColumn(COLUMN_PEERNAME); + PGPIdItemProxy->setFilterKeyColumn(pgpid_item_model::PGP_ITEM_MODEL_COLUMN_PEERNAME); PGPIdItemProxy->setFilterCaseSensitivity(Qt::CaseInsensitive); PGPIdItemProxy->setSortRole(Qt::EditRole); //use edit role to get raw data since we do not have edit for this model. ui.connectTreeWidget->setModel(PGPIdItemProxy); @@ -83,16 +83,16 @@ NetworkDialog::NetworkDialog(QWidget */*parent*/) ui.connectTreeWidget->setUpdatesEnabled(true); ui.connectTreeWidget->setSortingEnabled(true); ui.connectTreeWidget->setSelectionBehavior(QAbstractItemView::SelectRows); - ui.connectTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection); + ui.connectTreeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); connect(ui.connectTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( connectTreeWidgetCostumPopupMenu( QPoint ) ) ); connect(ui.connectTreeWidget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(peerdetails())); ui.onlyTrustedKeys->setMinimumWidth(20*f); /* add filter actions */ - ui.filterLineEdit->addFilter(QIcon(), tr("Name"), COLUMN_PEERNAME, tr("Search name")); - ui.filterLineEdit->addFilter(QIcon(), tr("Peer ID"), COLUMN_PEERID, tr("Search peer ID")); - ui.filterLineEdit->setCurrentFilter(COLUMN_PEERNAME); + ui.filterLineEdit->addFilter(QIcon(), tr("Name"), pgpid_item_model::PGP_ITEM_MODEL_COLUMN_PEERNAME, tr("Search name")); + ui.filterLineEdit->addFilter(QIcon(), tr("Peer ID"), pgpid_item_model::PGP_ITEM_MODEL_COLUMN_PEERID, tr("Search peer ID")); + ui.filterLineEdit->setCurrentFilter(pgpid_item_model::PGP_ITEM_MODEL_COLUMN_PEERNAME); connect(ui.filterLineEdit, SIGNAL(textChanged(QString)), PGPIdItemProxy, SLOT(setFilterWildcard(QString))); } @@ -117,24 +117,12 @@ void NetworkDialog::connectTreeWidgetCostumPopupMenu( QPoint /*point*/ ) { return; } - QMenu *contextMnu = new QMenu; - RsPgpId peer_id(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()) ; - - // That's what context menus are made for - RsPeerDetails detail; - if(!rsPeers->getGPGDetails(peer_id, detail)) // that is not suppose to fail. - return ; - - if(peer_id == rsPeers->getGPGOwnId()) - contextMnu->addAction(QIcon(), tr("Export/create a new node"), this, SLOT(on_actionExportKey_activated())); - contextMnu->addAction(QIcon(IMAGE_PEERDETAILS), tr("Profile details..."), this, SLOT(peerdetails())); contextMnu->addSeparator() ; contextMnu->addAction(QIcon(), tr("Remove unused keys..."), this, SLOT(removeUnusedKeys())); contextMnu->addAction(QIcon(), tr("Remove this key"), this, SLOT(removeSelectedKeys())); - contextMnu->exec(QCursor::pos()); } @@ -177,11 +165,34 @@ void NetworkDialog::removeSelectedKeys() QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); if(l.empty()) return; - std::set selected; - selected.insert(RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString())); - removeKeys(selected); + std::set friends; + for (int i = 0; i < l.size(); i++) + { + RsPgpId peer_id = RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l[i].row(), pgpid_item_model::PGP_ITEM_MODEL_COLUMN_PEERID)).toString().toStdString()); + RsPeerDetails details ; + if(rsPeers->getGPGDetails(peer_id,details)) + { + if(details.accept_connection) + friends.insert(peer_id); + else + selected.insert(peer_id); + } + } + if(!friends.empty()) + { + if ((QMessageBox::question(this, "RetroShare", tr("You have selected %1 accepted peers among others,\n Are you sure you want to un-friend them?").arg(friends.size()), QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes)) == QMessageBox::Yes) + { + for(std::set::const_iterator it(friends.begin());it!=friends.end();++it) + rsPeers->removeFriend(*it); + selected.insert(friends.begin(),friends.end()); + } + } + if(!selected.empty()) + removeKeys(selected); + + updateDisplay(); } void NetworkDialog::removeKeys(std::set selected) @@ -228,7 +239,7 @@ void NetworkDialog::denyFriend() if(l.empty()) return; - RsPgpId peer_id(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()); + RsPgpId peer_id(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), pgpid_item_model::PGP_ITEM_MODEL_COLUMN_PEERID)).toString().toStdString()); rsPeers->removeFriend(peer_id) ; securedUpdateDisplay(); @@ -241,7 +252,7 @@ void NetworkDialog::makeFriend() if(l.empty()) return; - PGPKeyDialog::showIt(RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()), PGPKeyDialog::PageDetails); + PGPKeyDialog::showIt(RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), pgpid_item_model::PGP_ITEM_MODEL_COLUMN_PEERID)).toString().toStdString()), PGPKeyDialog::PageDetails); } /** Shows Peer Information/Auth Dialog */ @@ -251,7 +262,7 @@ void NetworkDialog::peerdetails() if(l.empty()) return; - PGPKeyDialog::showIt(RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()), PGPKeyDialog::PageDetails); + PGPKeyDialog::showIt(RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), pgpid_item_model::PGP_ITEM_MODEL_COLUMN_PEERID)).toString().toStdString()), PGPKeyDialog::PageDetails); } void NetworkDialog::copyLink() @@ -261,7 +272,7 @@ void NetworkDialog::copyLink() return; - RsPgpId peer_id (ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()) ; + RsPgpId peer_id (ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), pgpid_item_model::PGP_ITEM_MODEL_COLUMN_PEERID)).toString().toStdString()) ; QList urls; RetroShareLink link = RetroShareLink::createPerson(peer_id); diff --git a/retroshare-gui/src/gui/NetworkDialog.h b/retroshare-gui/src/gui/NetworkDialog.h index 6a5b1c367..216cd8cc5 100644 --- a/retroshare-gui/src/gui/NetworkDialog.h +++ b/retroshare-gui/src/gui/NetworkDialog.h @@ -43,6 +43,7 @@ class NetworkDialog : public RsAutoUpdatePage Q_PROPERTY(QColor backgroundColorAcceptConnection READ backgroundColorAcceptConnection WRITE setBackgroundColorAcceptConnection) Q_PROPERTY(QColor backgroundColorHasSignedMe READ backgroundColorHasSignedMe WRITE setBackgroundColorHasSignedMe) Q_PROPERTY(QColor backgroundColorDenied READ backgroundColorDenied WRITE setBackgroundColorDenied) + Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor) public: /** Default Constructor */ @@ -55,12 +56,14 @@ public: QColor backgroundColorAcceptConnection() const { return mBackgroundColorAcceptConnection; } QColor backgroundColorHasSignedMe() const { return mBackgroundColorHasSignedMe; } QColor backgroundColorDenied() const { return mBackgroundColorDenied; } + QColor textColor() const { return mTextColor; } void setBackgroundColorSelf(QColor color) { PGPIdItemModel->setBackgroundColorSelf(color); mBackgroundColorSelf = color; } void setBackgroundColorOwnSign(QColor color) { PGPIdItemModel->setBackgroundColorOwnSign(color); mBackgroundColorOwnSign = color; } void setBackgroundColorAcceptConnection(QColor color) { PGPIdItemModel->setBackgroundColorAcceptConnection(color); mBackgroundColorAcceptConnection = color; } void setBackgroundColorHasSignedMe(QColor color) { PGPIdItemModel->setBackgroundColorHasSignedMe(color); mBackgroundColorHasSignedMe = color; } void setBackgroundColorDenied(QColor color) { PGPIdItemModel->setBackgroundColorDenied(color); mBackgroundColorDenied = color; } + void setTextColor(QColor color) { PGPIdItemModel->setTextColor(color); mTextColor = color; } protected: void changeEvent(QEvent *e); @@ -89,12 +92,13 @@ private: void removeKeys(std::set selected) ; - /* Color definitions (for standard see qss.default) */ + /* Color definitions (for standard see default.qss) */ QColor mBackgroundColorSelf; QColor mBackgroundColorOwnSign; QColor mBackgroundColorAcceptConnection; QColor mBackgroundColorHasSignedMe; QColor mBackgroundColorDenied; + QColor mTextColor; RSTreeWidgetItemCompareRole *compareNetworkRole ; diff --git a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.cpp b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.cpp index 96ab24e92..016692092 100644 --- a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.cpp +++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.cpp @@ -24,6 +24,9 @@ #include #include +#define IMAGE_AUTHED ":/images/accepted16.png" +#define IMAGE_DENIED ":/images/denied16.png" +#define IMAGE_TRUSTED ":/images/rs-2.png" /*TODO: * using list here for internal data storage is not best option @@ -41,22 +44,22 @@ QVariant pgpid_item_model::headerData(int section, Qt::Orientation orientation, { switch(section) { - case COLUMN_CHECK: + case PGP_ITEM_MODEL_COLUMN_CHECK: return QString(tr(" Do you accept connections signed by this profile?")); break; - case COLUMN_PEERNAME: + case PGP_ITEM_MODEL_COLUMN_PEERNAME: return QString(tr("Name of the profile")); break; - case COLUMN_I_AUTH_PEER: + case PGP_ITEM_MODEL_COLUMN_I_AUTH_PEER: return QString(tr("This column indicates the trust level you indicated and whether you signed the profile PGP key")); break; - case COLUMN_PEER_AUTH_ME: + case PGP_ITEM_MODEL_COLUMN_PEER_AUTH_ME: return QString(tr("Did that peer sign your own profile PGP key")); break; - case COLUMN_PEERID: + case PGP_ITEM_MODEL_COLUMN_PEERID: return QString(tr("PGP Key Id of that profile")); break; - case COLUMN_LAST_USED: + case PGP_ITEM_MODEL_COLUMN_LAST_USED: return QString(tr("Last time this key was used (received time, or to check connection)")); break; } @@ -65,22 +68,22 @@ QVariant pgpid_item_model::headerData(int section, Qt::Orientation orientation, { switch(section) { - case COLUMN_CHECK: + case PGP_ITEM_MODEL_COLUMN_CHECK: return QString(tr("Connections")); break; - case COLUMN_PEERNAME: + case PGP_ITEM_MODEL_COLUMN_PEERNAME: return QString(tr("Profile")); break; - case COLUMN_I_AUTH_PEER: + case PGP_ITEM_MODEL_COLUMN_I_AUTH_PEER: return QString(tr("Trust level")); break; - case COLUMN_PEER_AUTH_ME: + case PGP_ITEM_MODEL_COLUMN_PEER_AUTH_ME: return QString(tr("Has signed your key?")); break; - case COLUMN_PEERID: + case PGP_ITEM_MODEL_COLUMN_PEERID: return QString(tr("Id")); break; - case COLUMN_LAST_USED: + case PGP_ITEM_MODEL_COLUMN_LAST_USED: return QString(tr("Last used")); break; } @@ -98,13 +101,13 @@ QVariant pgpid_item_model::headerData(int section, Qt::Orientation orientation, { switch(section) { - case COLUMN_CHECK: + case PGP_ITEM_MODEL_COLUMN_CHECK: return 25*font_height; break; - case COLUMN_PEERNAME: case COLUMN_I_AUTH_PEER: case COLUMN_PEER_AUTH_ME: + case PGP_ITEM_MODEL_COLUMN_PEERNAME: case PGP_ITEM_MODEL_COLUMN_I_AUTH_PEER: case PGP_ITEM_MODEL_COLUMN_PEER_AUTH_ME: return 200*font_height; break; - case COLUMN_LAST_USED: + case PGP_ITEM_MODEL_COLUMN_LAST_USED: return 75*font_height; break; } @@ -122,7 +125,7 @@ int pgpid_item_model::rowCount(const QModelIndex &/*parent*/) const int pgpid_item_model::columnCount(const QModelIndex &/*parent*/) const { - return COLUMN_COUNT; + return PGP_ITEM_MODEL_COLUMN_COUNT; } @@ -148,20 +151,20 @@ QVariant pgpid_item_model::data(const QModelIndex &index, int role) const { switch(index.column()) { - case COLUMN_LAST_USED: + case PGP_ITEM_MODEL_COLUMN_LAST_USED: return detail.lastUsed; break; - case COLUMN_I_AUTH_PEER: + case PGP_ITEM_MODEL_COLUMN_I_AUTH_PEER: { if (detail.ownsign) return RS_TRUST_LVL_ULTIMATE; return detail.trustLvl; } break; - case COLUMN_PEER_AUTH_ME: + case PGP_ITEM_MODEL_COLUMN_PEER_AUTH_ME: return detail.hasSignedMe; break; - case COLUMN_CHECK: + case PGP_ITEM_MODEL_COLUMN_CHECK: return detail.accept_connection; break; default: @@ -174,13 +177,13 @@ QVariant pgpid_item_model::data(const QModelIndex &index, int role) const { switch(index.column()) { - case COLUMN_PEERNAME: + case PGP_ITEM_MODEL_COLUMN_PEERNAME: return QString::fromUtf8(detail.name.c_str()); break; - case COLUMN_PEERID: + case PGP_ITEM_MODEL_COLUMN_PEERID: return QString::fromStdString(detail.gpg_id.toStdString()); break; - case COLUMN_I_AUTH_PEER: + case PGP_ITEM_MODEL_COLUMN_I_AUTH_PEER: { if (detail.ownsign) return tr("Personal signature"); @@ -199,7 +202,7 @@ QVariant pgpid_item_model::data(const QModelIndex &index, int role) const } } break; - case COLUMN_PEER_AUTH_ME: + case PGP_ITEM_MODEL_COLUMN_PEER_AUTH_ME: { if (detail.hasSignedMe) return tr("Yes"); @@ -207,7 +210,7 @@ QVariant pgpid_item_model::data(const QModelIndex &index, int role) const return tr("No"); } break; - case COLUMN_LAST_USED: + case PGP_ITEM_MODEL_COLUMN_LAST_USED: { time_t now = time(NULL); uint64_t last_time_used = now - detail.lastUsed ; @@ -226,7 +229,7 @@ QVariant pgpid_item_model::data(const QModelIndex &index, int role) const return lst_used_str; } break; - case COLUMN_CHECK: + case PGP_ITEM_MODEL_COLUMN_CHECK: { if (detail.accept_connection || rsPeers->getGPGOwnId() == detail.gpg_id) return tr("Accepted"); @@ -242,7 +245,7 @@ QVariant pgpid_item_model::data(const QModelIndex &index, int role) const { switch(index.column()) { - case COLUMN_I_AUTH_PEER: + case PGP_ITEM_MODEL_COLUMN_I_AUTH_PEER: { if (detail.ownsign) return tr("PGP key signed by you"); @@ -263,7 +266,7 @@ QVariant pgpid_item_model::data(const QModelIndex &index, int role) const { switch(index.column()) { - case COLUMN_CHECK: + case PGP_ITEM_MODEL_COLUMN_CHECK: { if (detail.accept_connection) return QIcon(IMAGE_AUTHED); @@ -299,6 +302,10 @@ QVariant pgpid_item_model::data(const QModelIndex &index, int role) const } } } + else if(role == Qt::ForegroundRole) + { + return QBrush(mTextColor); + } return QVariant(); } @@ -341,14 +348,14 @@ void pgpid_item_model::data_updated(std::list &new_neighs) break; if(*i1 != *i2) { - QModelIndex topLeft = createIndex(ii1,0), bottomRight = createIndex(ii1, COLUMN_COUNT-1); + QModelIndex topLeft = createIndex(ii1,0), bottomRight = createIndex(ii1, PGP_ITEM_MODEL_COLUMN_COUNT-1); emit dataChanged(topLeft, bottomRight); } } } if(new_size > old_size) { - QModelIndex topLeft = createIndex(old_size ? old_size -1 : 0 ,0), bottomRight = createIndex(new_size -1, COLUMN_COUNT-1); + QModelIndex topLeft = createIndex(old_size ? old_size -1 : 0 ,0), bottomRight = createIndex(new_size -1, PGP_ITEM_MODEL_COLUMN_COUNT-1); emit dataChanged(topLeft, bottomRight); } //dirty solution for initial data fetch diff --git a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.h b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.h index 1e38e0461..7a17f48cb 100644 --- a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.h +++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.h @@ -25,20 +25,6 @@ #include #include -#define IMAGE_AUTHED ":/images/accepted16.png" -#define IMAGE_DENIED ":/images/denied16.png" -#define IMAGE_TRUSTED ":/images/rs-2.png" - - -#define COLUMN_CHECK 0 -#define COLUMN_PEERNAME 1 -#define COLUMN_I_AUTH_PEER 2 -#define COLUMN_PEER_AUTH_ME 3 -#define COLUMN_PEERID 4 -#define COLUMN_LAST_USED 5 -#define COLUMN_COUNT 6 - - class pgpid_item_model : public QAbstractTableModel { Q_OBJECT @@ -60,7 +46,15 @@ public: void setBackgroundColorAcceptConnection(QColor color) { mBackgroundColorAcceptConnection = color; } void setBackgroundColorHasSignedMe(QColor color) { mBackgroundColorHasSignedMe = color; } void setBackgroundColorDenied(QColor color) { mBackgroundColorDenied = color; } + void setTextColor(QColor color) { mTextColor = color; } + static constexpr int PGP_ITEM_MODEL_COLUMN_CHECK = 0; + static constexpr int PGP_ITEM_MODEL_COLUMN_PEERNAME = 1; + static constexpr int PGP_ITEM_MODEL_COLUMN_I_AUTH_PEER = 2; + static constexpr int PGP_ITEM_MODEL_COLUMN_PEER_AUTH_ME = 3; + static constexpr int PGP_ITEM_MODEL_COLUMN_PEERID = 4; + static constexpr int PGP_ITEM_MODEL_COLUMN_LAST_USED = 5; + static constexpr int PGP_ITEM_MODEL_COLUMN_COUNT = 6; public slots: void data_updated(std::list &new_neighs); @@ -73,6 +67,7 @@ private: QColor mBackgroundColorAcceptConnection; QColor mBackgroundColorHasSignedMe; QColor mBackgroundColorDenied; + QColor mTextColor; }; #endif // KEY_ITEM_MODEL_H diff --git a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.cpp b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.cpp index 29acee273..e7b81ef2b 100644 --- a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.cpp +++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.cpp @@ -26,17 +26,13 @@ #include #include - -//TODO: set this defines in one place -// Defines for key list columns -#define COLUMN_CHECK 0 -#define COLUMN_PEERNAME 1 -#define COLUMN_I_AUTH_PEER 2 -#define COLUMN_PEER_AUTH_ME 3 -#define COLUMN_PEERID 4 -#define COLUMN_LAST_USED 5 -#define COLUMN_COUNT 6 - +bool pgpid_item_proxy::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + if(left.column() == pgpid_item_model::PGP_ITEM_MODEL_COLUMN_LAST_USED) + return left.data(Qt::EditRole).toUInt() < right.data(Qt::EditRole).toUInt(); + else + return left.data(Qt::DisplayRole).toString().toUpper() < right.data(Qt::DisplayRole).toString().toUpper(); +} pgpid_item_proxy::pgpid_item_proxy(QObject *parent) : @@ -57,7 +53,7 @@ bool pgpid_item_proxy::filterAcceptsRow(int sourceRow, const QModelIndex &source { if(!rsPeers) return false; - RsPgpId peer_id (sourceModel()->data(sourceModel()->index(sourceRow, COLUMN_PEERID, sourceParent)).toString().toStdString()); + RsPgpId peer_id (sourceModel()->data(sourceModel()->index(sourceRow, pgpid_item_model::PGP_ITEM_MODEL_COLUMN_PEERID, sourceParent)).toString().toStdString()); RsPeerDetails details; if(!rsPeers->getGPGDetails(peer_id, details)) return false; diff --git a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.h b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.h index 0260b815d..5608862a2 100644 --- a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.h +++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.h @@ -34,14 +34,7 @@ class pgpid_item_proxy : public: pgpid_item_proxy(QObject *parent = nullptr); bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; - - bool lessThan(const QModelIndex &left, const QModelIndex &right) const override - { - if(left.column() == COLUMN_LAST_USED) - return left.data(Qt::EditRole).toUInt() < right.data(Qt::EditRole).toUInt(); - else - return left.data(Qt::DisplayRole).toString().toUpper() < right.data(Qt::DisplayRole).toString().toUpper(); - } + bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; public slots: void use_only_trusted_keys(bool val); diff --git a/retroshare-gui/src/gui/NewsFeed.cpp b/retroshare-gui/src/gui/NewsFeed.cpp index 4d552735e..dc0834e71 100644 --- a/retroshare-gui/src/gui/NewsFeed.cpp +++ b/retroshare-gui/src/gui/NewsFeed.cpp @@ -32,6 +32,7 @@ #include #include +#include "util/misc.h" #include "util/qtthreadsutils.h" #include "feeds/BoardsCommentsItem.h" #include "feeds/ChatMsgItem.h" @@ -83,7 +84,10 @@ NewsFeed::NewsFeed(QWidget *parent) : MainPage(parent), ui(new Ui::NewsFeed), RsEventType::MAIL_STATUS }) { - for(uint32_t i=0;isetupUi(this); + + for(uint32_t i=0;iregisterEventsHandler( @@ -91,9 +95,6 @@ NewsFeed::NewsFeed(QWidget *parent) : MainPage(parent), ui(new Ui::NewsFeed), mEventHandlerIds.back(), mEventTypes[i] ); } - /* Invoke the Qt Designer generated object setup routine */ - ui->setupUi(this); - if (!instance) { instance = this; } @@ -111,22 +112,23 @@ NewsFeed::NewsFeed(QWidget *parent) : MainPage(parent), ui(new Ui::NewsFeed), connect(ui->feedOptionsButton, SIGNAL(clicked()), this, SLOT(feedoptions())); ui->feedOptionsButton->hide(); // (csoler) Hidden until we repare the system to display a specific settings page. -QString hlp_str = tr( - "

  Activity Feed

\ -

The Activity Feed displays the last events on your network, sorted by the time you received them. \ - This gives you a summary of the activity of your friends. \ - You can configure which events to show by pressing on Options.

\ -

The various events shown are: \ -

    \ -
  • Connection attempts (useful to make friends with new people and control who's trying to reach you)
  • \ -
  • Channel, Forum and Board posts
  • \ -
  • Circle membership requests and invites
  • \ -
  • New Channels, Forums and Boards you can subscribe to
  • \ -
  • Channel and Board comments
  • \ -
  • New Mail messages
  • \ -
  • Private messages from your friends
  • \ -

\ - ") ; + int H = misc::getFontSizeFactor("HelpButton").height(); + QString hlp_str = tr( + "

  Activity Feed

" + "

The Activity Feed displays the last events on your network, sorted by the time you received them." + " This gives you a summary of the activity of your friends." + " You can configure which events to show by pressing on Options.

" + "

The various events shown are:" + "

    " + "
  • Connection attempts (useful to make friends with new people and control who's trying to reach you)
  • " + "
  • Channel, Forum and Board posts
  • " + "
  • Circle membership requests and invites
  • " + "
  • New Channels, Forums and Boards you can subscribe to
  • " + "
  • Channel and Board comments
  • " + "
  • New Mail messages
  • " + "
  • Private messages from your friends
  • " + "

" + ).arg(QString::number(2*H)); registerHelpButton(ui->helpButton,hlp_str,"NewFeed") ; @@ -270,7 +272,10 @@ void NewsFeed::handleForumEvent(std::shared_ptr event) case RsForumEventCode::UPDATED_MESSAGE: case RsForumEventCode::NEW_MESSAGE: - addFeedItem(new GxsForumMsgItem(this, NEWSFEED_NEW_FORUM, pe->mForumGroupId, pe->mForumMsgId, false, true)); + addFeedItem(new GxsForumMsgItem( + this, NEWSFEED_NEW_FORUM, + pe->mForumGroupId, pe->mForumMsgId, + false, true )); break; default: break; @@ -294,7 +299,7 @@ void NewsFeed::handleChannelEvent(std::shared_ptr event) addFeedItem(new GxsChannelPostItem(this, NEWSFEED_CHANNELNEWLIST, pe->mChannelGroupId, pe->mChannelMsgId, false, true)); break; case RsChannelEventCode::NEW_COMMENT: - addFeedItem(new ChannelsCommentsItem(this, NEWSFEED_CHANNELNEWLIST, pe->mChannelGroupId, pe->mChannelMsgId, false, true)); + addFeedItem(new ChannelsCommentsItem(this, NEWSFEED_CHANNELNEWLIST, pe->mChannelGroupId, pe->mChannelMsgId,pe->mChannelThreadId, false, true)); break; case RsChannelEventCode::RECEIVED_PUBLISH_KEY: addFeedItem(new GxsChannelGroupItem(this, NEWSFEED_CHANNELPUBKEYLIST, pe->mChannelGroupId, false, true)); @@ -436,6 +441,7 @@ void NewsFeed::handleConnectionEvent(std::shared_ptr event) { case RsConnectionEventCode::PEER_CONNECTED: addFeedItemIfUnique(new PeerItem(this, NEWSFEED_PEERLIST, e.mSslId, PEER_TYPE_CONNECT, false), true); + NotifyQt::getInstance()->addToaster(RS_POPUP_CONNECT, e.mSslId.toStdString().c_str(), "", ""); break; case RsConnectionEventCode::PEER_DISCONNECTED: // not handled yet break; @@ -471,6 +477,7 @@ void NewsFeed::handleSecurityEvent(std::shared_ptr event) addFeedItemIfUnique(new PeerItem(this, NEWSFEED_PEERLIST, e.mSslId, PEER_TYPE_HELLO, false), true ); return; } + uint32_t FeedItemType=0; @@ -499,9 +506,11 @@ void NewsFeed::handleSecurityEvent(std::shared_ptr event) if (Settings->getMessageFlags() & RS_MESSAGE_CONNECT_ATTEMPT) MessageComposer::addConnectAttemptMsg(e.mPgpId, e.mSslId, QString::fromStdString(det.name + "(" + det.location + ")")); + + NotifyQt::getInstance()->addToaster(RS_POPUP_CONNECT_ATTEMPT, e.mPgpId.toStdString().c_str(), det.location, e.mSslId.toStdString().c_str()); } -void NewsFeed::testFeeds(uint notifyFlags) +void NewsFeed::testFeeds(uint /*notifyFlags*/) { #ifdef TO_REMOVE if (!instance) { diff --git a/retroshare-gui/src/gui/NewsFeed.h b/retroshare-gui/src/gui/NewsFeed.h index 2e3d7e5ed..2b246fb4c 100644 --- a/retroshare-gui/src/gui/NewsFeed.h +++ b/retroshare-gui/src/gui/NewsFeed.h @@ -24,7 +24,6 @@ #include #include "gui/feeds/FeedHolder.h" -#include "util/TokenQueue.h" #include #define IMAGE_NEWSFEED ":/icons/png/newsfeed.png" diff --git a/retroshare-gui/src/gui/NewsFeed.ui b/retroshare-gui/src/gui/NewsFeed.ui index 1314c60c7..ff8c17f5e 100644 --- a/retroshare-gui/src/gui/NewsFeed.ui +++ b/retroshare-gui/src/gui/NewsFeed.ui @@ -67,7 +67,14 @@
- + + + + 12 + 75 + true + + Activity Stream @@ -87,7 +94,7 @@ - + @@ -143,9 +150,9 @@ - StyledLabel - QLabel -
gui/common/StyledLabel.h
+ RSComboBox + QComboBox +
gui/common/RSComboBox.h
RSFeedWidget diff --git a/retroshare-gui/src/gui/PhotoShare/AlbumDialog.ui b/retroshare-gui/src/gui/PhotoShare/AlbumDialog.ui index 2d1e7de4e..ef39eac4a 100644 --- a/retroshare-gui/src/gui/PhotoShare/AlbumDialog.ui +++ b/retroshare-gui/src/gui/PhotoShare/AlbumDialog.ui @@ -138,14 +138,14 @@
- + 0 1 - + 0 @@ -185,8 +185,8 @@ p, li { white-space: pre-wrap; } 0 0 - 757 - 395 + 741 + 316
diff --git a/retroshare-gui/src/gui/PhotoShare/AlbumExtra.ui b/retroshare-gui/src/gui/PhotoShare/AlbumExtra.ui index 23b0a462f..ee8c173fc 100644 --- a/retroshare-gui/src/gui/PhotoShare/AlbumExtra.ui +++ b/retroshare-gui/src/gui/PhotoShare/AlbumExtra.ui @@ -28,7 +28,7 @@
- + 0 @@ -111,6 +111,13 @@ + + + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
+
diff --git a/retroshare-gui/src/gui/PhotoShare/AlbumItem.cpp b/retroshare-gui/src/gui/PhotoShare/AlbumItem.cpp index a28b500e5..fea04adbc 100644 --- a/retroshare-gui/src/gui/PhotoShare/AlbumItem.cpp +++ b/retroshare-gui/src/gui/PhotoShare/AlbumItem.cpp @@ -47,7 +47,7 @@ void AlbumItem::setUp() if(mAlbum.mThumbnail.mSize != 0) { QPixmap qtn; - qtn.loadFromData(mAlbum.mThumbnail.mData, mAlbum.mThumbnail.mSize, "PNG"); + qtn.loadFromData(mAlbum.mThumbnail.mData, mAlbum.mThumbnail.mSize, "JPG"); ui->label_Thumbnail->setPixmap(qtn); } else diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoDialog.ui b/retroshare-gui/src/gui/PhotoShare/PhotoDialog.ui index cf809286c..7be276b77 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoDialog.ui +++ b/retroshare-gui/src/gui/PhotoShare/PhotoDialog.ui @@ -153,7 +153,7 @@ - + 50 % @@ -302,6 +302,13 @@ + + + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
+
diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoShare.ui b/retroshare-gui/src/gui/PhotoShare/PhotoShare.ui index 19230a67f..e5476486f 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoShare.ui +++ b/retroshare-gui/src/gui/PhotoShare/PhotoShare.ui @@ -61,7 +61,7 @@ Edit Album Details - + :/images/edit_16.png:/images/edit_16.png @@ -186,6 +186,11 @@ + + + 12 + + My Albums @@ -212,6 +217,11 @@ + + + 12 + + Subscribed Albums @@ -238,6 +248,11 @@ + + + 12 + + Shared Albums @@ -286,7 +301,7 @@ 0 0 804 - 208 + 205 @@ -322,7 +337,7 @@ 0 0 804 - 208 + 205 diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.ui b/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.ui index b8509703e..03c5093ad 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.ui +++ b/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.ui @@ -24,6 +24,11 @@ 0 + + + 12 + + Album Name @@ -155,8 +160,6 @@ - - diff --git a/retroshare-gui/src/gui/PluginManager.cpp b/retroshare-gui/src/gui/PluginManager.cpp index 2b6fa01a6..e5ac7f7d5 100644 --- a/retroshare-gui/src/gui/PluginManager.cpp +++ b/retroshare-gui/src/gui/PluginManager.cpp @@ -41,7 +41,7 @@ PluginManager::PluginManager() { baseFolder = //qApp->applicationDirPath()+"///plugins" ; -Rshare::dataDirectory() + "/plugins" ; +RsApplication::dataDirectory() + "/plugins" ; lastError = "No error."; viewWidget = 0; diff --git a/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget.cpp b/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget.cpp index 7dc90eb82..541cecac0 100644 --- a/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget.cpp +++ b/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "rshare.h" #include "BoardPostDisplayWidget.h" @@ -43,6 +44,7 @@ #define LINK_IMAGE ":/images/thumb-link.png" + // #ifdef DEBUG_BOARDPOSTDISPLAYWIDGET 1 /** Constructor */ @@ -58,6 +60,7 @@ BoardPostDisplayWidgetBase::BoardPostDisplayWidgetBase(const RsPostedPost& post, { } + void BoardPostDisplayWidgetBase::setCommentsSize(int comNb) { QString sComButText = tr("Comment"); @@ -108,28 +111,28 @@ void BoardPostDisplayWidgetBase::makeUpVote() void BoardPostDisplayWidgetBase::setReadStatus(bool isNew, bool isUnread) { if (isUnread) - readButton()->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); + readButton()->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); else - readButton()->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-read.png")); + readButton()->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-read.png")); - newLabel()->setVisible(isNew); + newLabel()->setVisible(isNew); - mainFrame()->setProperty("new", isNew); - mainFrame()->style()->unpolish(mainFrame()); - mainFrame()->style()->polish(mainFrame()); + feedFrame()->setProperty("new", isNew); + feedFrame()->style()->unpolish(feedFrame()); + feedFrame()->style()->polish( feedFrame()); } void BoardPostDisplayWidget_compact::doExpand(bool e) { #ifdef DEBUG_BOARDPOSTDISPLAYWIDGET - std::cerr << "Expanding" << std::endl; + std::cerr << "Expanding" << std::endl; #endif - if(e) - ui->frame_notes->show(); - else - ui->frame_notes->hide(); + if(e) + ui->frame_notes->show(); + else + ui->frame_notes->hide(); - emit expand(mPost.mMeta.mMsgId,e); + emit expand(mPost.mMeta.mMsgId,e); } void BoardPostDisplayWidgetBase::loadComments(bool e) @@ -144,7 +147,7 @@ void BoardPostDisplayWidgetBase::readToggled() emit changeReadStatusRequested(mPost.mMeta.mMsgId,s); } -void BoardPostDisplayWidgetBase::setup() +void BoardPostDisplayWidgetBase::baseSetup() { // show/hide things based on the view type @@ -166,16 +169,17 @@ void BoardPostDisplayWidgetBase::setup() QAction *CopyLinkAction = new QAction(QIcon(""),tr("Copy RetroShare Link"), this); connect(CopyLinkAction, SIGNAL(triggered()), this, SLOT(handleCopyLinkClicked())); - int S = QFontMetricsF(font()).height() ; - readButton()->setChecked(false); +#ifdef TO_REMOVE QMenu *menu = new QMenu(); menu->addAction(CopyLinkAction); menu->addSeparator(); shareButton()->setMenu(menu); + shareButton()->setPopupMode(QToolButton::InstantPopup); - connect(shareButton(),SIGNAL(pressed()),this,SLOT(handleShareButtonClicked())); + connect(menu,SIGNAL(aboutToShow()),this,SLOT(handleShareButtonClicked())); +#endif RsReputationLevel overall_reputation = rsReputations->overallReputationLevel(mPost.mMeta.mAuthorId); bool redacted = (overall_reputation == RsReputationLevel::LOCALLY_NEGATIVE); @@ -183,6 +187,9 @@ void BoardPostDisplayWidgetBase::setup() if(redacted) { commentButton()->setDisabled(true); +#ifdef TO_REMOVE + shareButton()->setDisabled(true); +#endif voteUpButton()->setDisabled(true); voteDownButton()->setDisabled(true); fromLabel()->setId(mPost.mMeta.mAuthorId); @@ -195,8 +202,6 @@ void BoardPostDisplayWidgetBase::setup() } else { - QPixmap sqpixmap2 = FilesDefs::getPixmapFromQtResourcePath(":/images/thumb-default.png"); - QDateTime qtime; qtime.setTime_t(mPost.mMeta.mPublishTs); QString timestamp = qtime.toString("hh:mm dd-MMM-yyyy"); @@ -210,8 +215,6 @@ void BoardPostDisplayWidgetBase::setup() // The only combination that seems to work: load as EncodedUrl, extract toEncoded(). QByteArray urlarray(mPost.mLink.c_str()); QUrl url = QUrl::fromEncoded(urlarray.trimmed()); - QString urlstr = "Invalid Link"; - QString sitestr = "Invalid Link"; bool urlOkay = url.isValid(); if (urlOkay) @@ -223,25 +226,24 @@ void BoardPostDisplayWidgetBase::setup() && (scheme != "retroshare")) { urlOkay = false; - sitestr = "Invalid Link Scheme"; } } + ElidedLabel *label = titleLabel(); + label->setText( QString::fromUtf8(mPost.mMeta.mMsgName.c_str()) ); + if (urlOkay) { - urlstr = QString(" "); - urlstr += QString::fromUtf8(mPost.mMeta.mMsgName.c_str()); - urlstr += QString(" "); - QString siteurl = url.toEncoded(); - titleLabel()->setText(urlstr); - titleLabel()->setToolTip(siteurl); + label->setStyleSheet("text-decoration: underline; color:#2255AA;"); + label->setCursor(QCursor(Qt::PointingHandCursor)); + label->setToolTip(siteurl); + + connect(label, &ElidedLabel::clicked, this, [url] () { + QDesktopServices::openUrl(url); + }, Qt::QueuedConnection); } - else - titleLabel()->setText( QString::fromUtf8(mPost.mMeta.mMsgName.c_str()) ); } //QString score = "Hot" + QString::number(post.mHotScore); @@ -277,6 +279,7 @@ void BoardPostDisplayWidgetBase::setup() emit sizeChanged(this); #endif } +#ifdef TO_REMOVE void BoardPostDisplayWidgetBase::handleShareButtonClicked() { emit shareButtonClicked(); @@ -286,6 +289,8 @@ void BoardPostDisplayWidgetBase::handleCopyLinkClicked() { emit copylinkClicked(); } +#endif + //=================================================================================================================================== //== class BoardPostDisplayWidget == //=================================================================================================================================== @@ -293,17 +298,9 @@ void BoardPostDisplayWidgetBase::handleCopyLinkClicked() BoardPostDisplayWidget_compact::BoardPostDisplayWidget_compact(const RsPostedPost& post, uint8_t display_flags,QWidget *parent=nullptr) : BoardPostDisplayWidgetBase(post,display_flags,parent), ui(new Ui::BoardPostDisplayWidget_compact()) { - ui->setupUi(this); - setup(); - - ui->verticalLayout->addStretch(); - ui->verticalLayout->setAlignment(Qt::AlignTop); - ui->topLayout->setAlignment(Qt::AlignTop); - ui->arrowsLayout->addStretch(); - ui->arrowsLayout->setAlignment(Qt::AlignTop); - ui->verticalLayout_2->addStretch(); - - adjustSize(); + ui->setupUi(this); + ui->shareButton->hide(); + BoardPostDisplayWidget_compact::setup(); } BoardPostDisplayWidget_compact::~BoardPostDisplayWidget_compact() @@ -313,7 +310,7 @@ BoardPostDisplayWidget_compact::~BoardPostDisplayWidget_compact() void BoardPostDisplayWidget_compact::setup() { - BoardPostDisplayWidgetBase::setup(); + baseSetup(); // show/hide things based on the view type @@ -341,7 +338,7 @@ void BoardPostDisplayWidget_compact::setup() #ifdef DEBUG_BOARDPOSTDISPLAYWIDGET std::cerr << "Got pixmap of size " << pixmap.width() << " x " << pixmap.height() << std::endl; std::cerr << "Saving to pix.png" << std::endl; - pixmap.save("pix.png","PNG"); + pixmap.save("pix.png","JPG"); #endif ui->pictureLabel->setPicture(pixmap); @@ -355,7 +352,7 @@ void BoardPostDisplayWidget_compact::setup() QObject::connect(ui->expandButton, SIGNAL(toggled(bool)), this, SLOT(doExpand(bool))); QTextDocument doc; - doc.setHtml(notes()->text()); + doc.setHtml(BoardPostDisplayWidget_compact::notes()->text()); if(mDisplayFlags & SHOW_NOTES) { @@ -411,12 +408,12 @@ QLabel *BoardPostDisplayWidget_compact::newLabel() { return ui->ne QToolButton *BoardPostDisplayWidget_compact::readButton() { return ui->readButton; } GxsIdLabel *BoardPostDisplayWidget_compact::fromLabel() { return ui->fromLabel; } QLabel *BoardPostDisplayWidget_compact::dateLabel() { return ui->dateLabel; } -QLabel *BoardPostDisplayWidget_compact::titleLabel() { return ui->titleLabel; } +ElidedLabel *BoardPostDisplayWidget_compact::titleLabel() { return ui->titleLabel; } QLabel *BoardPostDisplayWidget_compact::scoreLabel() { return ui->scoreLabel; } QLabel *BoardPostDisplayWidget_compact::notes() { return ui->notes; } -QPushButton *BoardPostDisplayWidget_compact::shareButton() { return ui->shareButton; } +//QToolButton *BoardPostDisplayWidget_compact::shareButton() { return ui->shareButton; } QLabel *BoardPostDisplayWidget_compact::pictureLabel() { return ui->pictureLabel; } -QFrame *BoardPostDisplayWidget_compact::mainFrame() { return ui->mainFrame; } +QFrame *BoardPostDisplayWidget_compact::feedFrame() { return ui->feedFrame; } //=================================================================================================================================== //== class BoardPostDisplayWidget_card == @@ -425,17 +422,9 @@ QFrame *BoardPostDisplayWidget_compact::mainFrame() { return ui->ma BoardPostDisplayWidget_card::BoardPostDisplayWidget_card(const RsPostedPost& post, uint8_t display_flags, QWidget *parent) : BoardPostDisplayWidgetBase(post,display_flags,parent), ui(new Ui::BoardPostDisplayWidget_card()) { - ui->setupUi(this); - setup(); - - ui->verticalLayout->addStretch(); - ui->verticalLayout->setAlignment(Qt::AlignTop); - ui->topLayout->setAlignment(Qt::AlignTop); - ui->arrowsLayout->addStretch(); - ui->arrowsLayout->setAlignment(Qt::AlignTop); - ui->verticalLayout_2->addStretch(); - - adjustSize(); + ui->setupUi(this); + ui->shareButton->hide(); + BoardPostDisplayWidget_card::setup(); } BoardPostDisplayWidget_card::~BoardPostDisplayWidget_card() @@ -445,7 +434,7 @@ BoardPostDisplayWidget_card::~BoardPostDisplayWidget_card() void BoardPostDisplayWidget_card::setup() { - BoardPostDisplayWidgetBase::setup(); + baseSetup(); RsReputationLevel overall_reputation = rsReputations->overallReputationLevel(mPost.mMeta.mAuthorId); bool redacted = (overall_reputation == RsReputationLevel::LOCALLY_NEGATIVE); @@ -462,7 +451,6 @@ void BoardPostDisplayWidget_card::setup() GxsIdDetails::loadPixmapFromData(mPost.mImage.mData, mPost.mImage.mSize, pixmap,GxsIdDetails::ORIGINAL); // Wiping data - as its been passed to thumbnail. - QPixmap scaledpixmap; if(pixmap.width() > 800){ QPixmap scaledpixmap = pixmap.scaledToWidth(800, Qt::SmoothTransformation); ui->pictureLabel->setPixmap(scaledpixmap); @@ -477,10 +465,10 @@ void BoardPostDisplayWidget_card::setup() } QTextDocument doc; - doc.setHtml(notes()->text()); + doc.setHtml(BoardPostDisplayWidget_card::notes()->text()); if(doc.toPlainText().trimmed().isEmpty()) - notes()->hide(); + BoardPostDisplayWidget_card::notes()->hide(); } QToolButton *BoardPostDisplayWidget_card::voteUpButton() { return ui->voteUpButton; } @@ -490,10 +478,10 @@ QLabel *BoardPostDisplayWidget_card::newLabel() { return ui->newLa QToolButton *BoardPostDisplayWidget_card::readButton() { return ui->readButton; } GxsIdLabel *BoardPostDisplayWidget_card::fromLabel() { return ui->fromLabel; } QLabel *BoardPostDisplayWidget_card::dateLabel() { return ui->dateLabel; } -QLabel *BoardPostDisplayWidget_card::titleLabel() { return ui->titleLabel; } +ElidedLabel *BoardPostDisplayWidget_card::titleLabel() { return ui->titleLabel; } QLabel *BoardPostDisplayWidget_card::scoreLabel() { return ui->scoreLabel; } QLabel *BoardPostDisplayWidget_card::notes() { return ui->notes; } -QPushButton *BoardPostDisplayWidget_card::shareButton() { return ui->shareButton; } +//QToolButton *BoardPostDisplayWidget_card::shareButton() { return ui->shareButton; } QLabel *BoardPostDisplayWidget_card::pictureLabel() { return ui->pictureLabel; } -QFrame *BoardPostDisplayWidget_card::mainFrame() { return ui->mainFrame; } +QFrame *BoardPostDisplayWidget_card::feedFrame() { return ui->feedFrame; } diff --git a/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget.h b/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget.h index 32ce60a2a..731ddc9da 100644 --- a/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget.h +++ b/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget.h @@ -37,6 +37,7 @@ class QToolButton; class QTextEdit; class ClickableLabel; class GxsIdLabel; +class ElidedLabel; struct RsPostedPost; @@ -62,34 +63,37 @@ public: static const char *DEFAULT_BOARD_IMAGE; -protected slots: +protected: /* GxsGroupFeedItem */ - virtual void setup(); // to be overloaded by the different views + void baseSetup(); + virtual void setup() =0; // to be overloaded by the different views virtual QToolButton *voteUpButton() =0; virtual QToolButton *commentButton() =0; virtual QToolButton *voteDownButton() =0; virtual QLabel *newLabel() =0; - virtual QLabel *titleLabel()=0; + virtual ElidedLabel *titleLabel()=0; virtual GxsIdLabel *fromLabel()=0; virtual QLabel *dateLabel()=0; virtual QLabel *scoreLabel() =0; virtual QLabel *notes() =0; virtual QLabel *pictureLabel()=0; virtual QToolButton *readButton() =0; - virtual QPushButton *shareButton() =0; - virtual QFrame *mainFrame() =0; +// virtual QToolButton *shareButton() =0; + virtual QFrame *feedFrame() =0; +protected slots: void loadComments(bool e); void readToggled(); void setReadStatus(bool isNew, bool isUnread) ; void makeUpVote() ; void makeDownVote() ; void setCommentsSize(int comNb) ; +#ifdef TO_REMOVE void handleShareButtonClicked() ; void handleCopyLinkClicked() ; - +#endif signals: void changeReadStatusRequested(const RsGxsMessageId&,bool); @@ -97,8 +101,8 @@ signals: void expand(RsGxsMessageId,bool); void commentsRequested(const RsGxsMessageId&,bool); void thumbnailOpenned(); - void shareButtonClicked(); - void copylinkClicked(); +// void shareButtonClicked(); +// void copylinkClicked(); protected: RsPostedPost mPost; @@ -121,13 +125,15 @@ public: QLabel *newLabel() override; GxsIdLabel *fromLabel() override; QLabel *dateLabel() override; - QLabel *titleLabel() override; + ElidedLabel *titleLabel() override; QLabel *scoreLabel() override; QLabel *notes() override; QLabel *pictureLabel() override; QToolButton *readButton() override; - QPushButton *shareButton() override; - QFrame *mainFrame() override; +#ifdef TO_REMOVE + QToolButton *shareButton() override; +#endif + QFrame *feedFrame() override; public slots: void viewPicture() ; @@ -160,13 +166,13 @@ public: QLabel *newLabel() override; GxsIdLabel *fromLabel() override; QLabel *dateLabel() override; - QLabel *titleLabel() override; + ElidedLabel *titleLabel() override; QLabel *scoreLabel() override; QLabel *notes() override; QToolButton *readButton() override; - QPushButton *shareButton() override; +// QToolButton *shareButton() override; QLabel *pictureLabel() override; - QFrame *mainFrame() override; + QFrame *feedFrame() override; protected slots: /* GxsGroupFeedItem */ diff --git a/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget_card.ui b/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget_card.ui index 42dc90f44..553577fb8 100644 --- a/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget_card.ui +++ b/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget_card.ui @@ -22,7 +22,7 @@ - + 0 @@ -42,7 +42,7 @@ 2 - + 0 @@ -55,7 +55,7 @@ QFrame::Raised - + 2 @@ -90,7 +90,10 @@ - + + + 0 + 0 @@ -127,10 +130,10 @@ - + - 9 + 14 @@ -173,13 +176,20 @@ + + + + Qt::Vertical + + +
- + - + 5 @@ -199,8 +209,8 @@ - 50 - false + 75 + true @@ -277,7 +287,7 @@ - + Qt::Horizontal @@ -295,7 +305,7 @@ - + 0 @@ -304,9 +314,9 @@ - Arial - 10 + 12 75 + true true @@ -340,7 +350,7 @@ - + Qt::Horizontal @@ -371,7 +381,7 @@ - + @@ -393,7 +403,7 @@ - + Share @@ -401,13 +411,16 @@ :/images/share.png:/images/share.png - + + Qt::ToolButtonTextBesideIcon + + true - + Qt::Horizontal @@ -421,30 +434,51 @@ + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + Qt::Vertical + + + + + ElidedLabel + QLabel +
gui/common/ElidedLabel.h
+ 1 +
GxsIdLabel QLabel
gui/gxs/GxsIdLabel.h
- - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
- + diff --git a/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget_compact.ui b/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget_compact.ui index 411d4583e..5e920cfed 100644 --- a/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget_compact.ui +++ b/retroshare-gui/src/gui/Posted/BoardPostDisplayWidget_compact.ui @@ -7,7 +7,7 @@ 0 0 542 - 150 + 151 @@ -22,7 +22,7 @@ - + 0 @@ -42,7 +42,7 @@ 2 - + 0 @@ -55,7 +55,7 @@ QFrame::Raised - + 2 @@ -89,78 +89,102 @@ 2 - - - - - - 0 - 0 - - - - Vote up - - - - - - - :/images/up-arrow.png:/images/up-arrow.png - - - true - - - - - - - - 9 - - - - 0 - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Vote down - - - - - - \/ - - - - :/images/down-arrow.png:/images/down-arrow.png - - - true - - - - + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Vote up + + + + + + + :/images/up-arrow.png:/images/up-arrow.png + + + true + + + + + + + + 14 + + + + 0 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Vote down + + + + + + \/ + + + + :/images/down-arrow.png:/images/down-arrow.png + + + true + + + + + + + Qt::Vertical + + + + + @@ -182,12 +206,12 @@ - + 3 - + 0 @@ -196,9 +220,9 @@ - Arial - 10 + 12 75 + true true @@ -220,7 +244,7 @@ - + 6 @@ -243,8 +267,8 @@ - 50 - false + 75 + true @@ -285,7 +309,7 @@ - + Qt::Horizontal @@ -303,7 +327,7 @@ - + @@ -345,7 +369,7 @@ - + Share @@ -353,7 +377,10 @@ :/images/share.png:/images/share.png - + + Qt::ToolButtonTextBesideIcon + + true @@ -395,7 +422,7 @@ - + Qt::Horizontal @@ -409,6 +436,13 @@ + + + + Qt::Vertical + + + @@ -421,7 +455,7 @@ QFrame::Raised - + 2 @@ -468,6 +502,13 @@ + + + + Qt::Vertical + + + @@ -475,9 +516,10 @@ - StyledLabel + ElidedLabel QLabel -
gui/common/StyledLabel.h
+
gui/common/ElidedLabel.h
+ 1
GxsIdLabel diff --git a/retroshare-gui/src/gui/Posted/PhotoView.ui b/retroshare-gui/src/gui/Posted/PhotoView.ui index e0d4dce64..31db767c9 100644 --- a/retroshare-gui/src/gui/Posted/PhotoView.ui +++ b/retroshare-gui/src/gui/Posted/PhotoView.ui @@ -22,8 +22,8 @@ MS Sans Serif - 11 75 + true true @@ -36,14 +36,14 @@ - + 0 0 - + 0 @@ -102,7 +102,6 @@ MS Sans Serif - 9 50 false @@ -113,7 +112,7 @@ - + 24 @@ -133,7 +132,9 @@ MS Sans Serif - 9 + 75 + true + true @@ -146,7 +147,6 @@ MS Sans Serif - 9 @@ -159,7 +159,6 @@ MS Sans Serif - 9 @@ -205,17 +204,17 @@ + + AvatarWidget + QLabel +
gui/common/AvatarWidget.h
+ 1 +
GxsIdLabel QLabel
gui/gxs/GxsIdLabel.h
- - AvatarWidget - QWidget -
gui/common/AvatarWidget.h
- 1 -
AspectRatioPixmapLabel QLabel diff --git a/retroshare-gui/src/gui/Posted/PostedCardView.cpp b/retroshare-gui/src/gui/Posted/PostedCardView.cpp index b7ead3c0b..9824cfda2 100644 --- a/retroshare-gui/src/gui/Posted/PostedCardView.cpp +++ b/retroshare-gui/src/gui/Posted/PostedCardView.cpp @@ -104,12 +104,12 @@ void PostedCardView::setReadStatus(bool isNew, bool isUnread) ui->newLabel->setVisible(isNew); - ui->mainFrame->setProperty("new", isNew); - ui->mainFrame->style()->unpolish(ui->mainFrame); - ui->mainFrame->style()->polish( ui->mainFrame); + ui->feedFrame->setProperty("new", isNew); + ui->feedFrame->style()->unpolish(ui->feedFrame); + ui->feedFrame->style()->polish( ui->feedFrame); } -void PostedCardView::setComment(const RsGxsComment& cmt) {} +void PostedCardView::setComment(const RsGxsComment& /*cmt*/) {} PostedCardView::~PostedCardView() { @@ -192,11 +192,11 @@ void PostedCardView::fill() ui->dateLabel->setText(timestamp); } else { - QPixmap sqpixmap2 = FilesDefs::getPixmapFromQtResourcePath(":/images/thumb-default.png"); + //QPixmap sqpixmap2 = FilesDefs::getPixmapFromQtResourcePath(":/images/thumb-default.png"); mInFill = true; - int desired_height = 1.5*(ui->voteDownButton->height() + ui->voteUpButton->height() + ui->scoreLabel->height()); - int desired_width = sqpixmap2.width()*desired_height/(float)sqpixmap2.height(); + //int desired_height = 1.5*(ui->voteDownButton->height() + ui->voteUpButton->height() + ui->scoreLabel->height()); + //int desired_width = sqpixmap2.width()*desired_height/(float)sqpixmap2.height(); QDateTime qtime; qtime.setTime_t(mPost.mMeta.mPublishTs); @@ -211,7 +211,6 @@ void PostedCardView::fill() // The only combination that seems to work: load as EncodedUrl, extract toEncoded(). QByteArray urlarray(mPost.mLink.c_str()); QUrl url = QUrl::fromEncoded(urlarray.trimmed()); - QString urlstr = "Invalid Link"; QString sitestr = "Invalid Link"; bool urlOkay = url.isValid(); @@ -230,7 +229,7 @@ void PostedCardView::fill() if (urlOkay) { - urlstr = QString(" "); urlstr += messageName(); @@ -259,7 +258,6 @@ void PostedCardView::fill() GxsIdDetails::loadPixmapFromData(mPost.mImage.mData, mPost.mImage.mSize, pixmap,GxsIdDetails::ORIGINAL); // Wiping data - as its been passed to thumbnail. - QPixmap scaledpixmap; if(pixmap.width() > 800){ QPixmap scaledpixmap = pixmap.scaledToWidth(800, Qt::SmoothTransformation); ui->pictureLabel->setPixmap(scaledpixmap); @@ -267,14 +265,14 @@ void PostedCardView::fill() ui->pictureLabel->setPixmap(pixmap); } } - else if (mPost.mImage.mData == NULL) + else //if (mPost.mImage.mData == NULL) { ui->picture_frame->hide(); } - else - { - ui->picture_frame->show(); - } + //else + //{ + // ui->picture_frame->show(); + //} } //QString score = "Hot" + QString::number(post.mHotScore); diff --git a/retroshare-gui/src/gui/Posted/PostedCardView.ui b/retroshare-gui/src/gui/Posted/PostedCardView.ui index 8cbbd4d56..dba517263 100644 --- a/retroshare-gui/src/gui/Posted/PostedCardView.ui +++ b/retroshare-gui/src/gui/Posted/PostedCardView.ui @@ -7,7 +7,7 @@ 0 0 614 - 182 + 198 @@ -16,7 +16,7 @@ - + 0 @@ -33,7 +33,7 @@ 0 - + 0 @@ -49,7 +49,7 @@ QFrame::Sunken - + 0 @@ -69,7 +69,7 @@ 6 - + 0 @@ -78,9 +78,9 @@ - Arial - 10 + 11 75 + true true @@ -118,7 +118,7 @@ - + 5 @@ -216,7 +216,7 @@ - + Qt::Horizontal @@ -241,30 +241,27 @@ 0 - - - QFrame::NoFrame QFrame::Plain - + 0 - 3 + 0 - 3 + 0 - 3 + 0 - 3 + 0 @@ -290,10 +287,10 @@ - + - 9 + 14 @@ -337,26 +334,20 @@ - + Qt::Vertical QSizePolicy::Expanding - - - 20 - 5 - -
- + @@ -389,7 +380,7 @@ - + Qt::Horizontal @@ -461,7 +452,7 @@ - + 0 @@ -485,7 +476,7 @@ - + Qt::Horizontal @@ -506,11 +497,6 @@ - - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
GxsIdLabel QLabel @@ -519,8 +505,8 @@
- + diff --git a/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.cpp b/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.cpp index 6bbfa3e37..bfccd3fc7 100644 --- a/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.cpp +++ b/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.cpp @@ -19,6 +19,7 @@ *******************************************************************************/ #include +#include #include #include #include @@ -28,6 +29,7 @@ #include "ui_PostedCreatePostDialog.h" #include "util/misc.h" +#include "util/qtthreadsutils.h" #include "util/RichTextEdit.h" #include "gui/feeds/SubFileItem.h" #include "util/rsdir.h" @@ -41,9 +43,14 @@ #include "gui/common/FilesDefs.h" /* View Page */ -#define VIEW_POST 1 -#define VIEW_IMAGE 2 -#define VIEW_LINK 3 +#define VIEW_POST 0 +#define VIEW_IMAGE 1 +#define VIEW_LINK 2 +/* View Image */ +#define IMG_ATTACH 0 +#define IMG_PICTURE 1 + +const int MAXMESSAGESIZE = 199000; PostedCreatePostDialog::PostedCreatePostDialog(RsPosted *posted, const RsGxsGroupId& grpId, const RsGxsId& default_author, QWidget *parent): QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint), @@ -53,10 +60,10 @@ PostedCreatePostDialog::PostedCreatePostDialog(RsPosted *posted, const RsGxsGrou ui->setupUi(this); Settings->loadWidgetInformation(this); - connect(ui->submitButton, SIGNAL(clicked()), this, SLOT(createPost())); - connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(ui->postButton, SIGNAL(clicked()), this, SLOT(createPost())); connect(ui->addPicButton, SIGNAL(clicked() ), this , SLOT(addPicture())); - connect(ui->RichTextEditWidget, SIGNAL(textSizeOk(bool)),ui->submitButton, SLOT(setEnabled(bool))); + connect(ui->pasteButton, SIGNAL(clicked() ), this , SLOT(pastePicture())); + connect(ui->RichTextEditWidget, SIGNAL(textSizeOk(bool)),ui->postButton, SLOT(setEnabled(bool))); ui->headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/postedlinks.png")); ui->headerFrame->setHeaderText(tr("Create a new Post")); @@ -74,16 +81,17 @@ PostedCreatePostDialog::PostedCreatePostDialog(RsPosted *posted, const RsGxsGrou ui->idChooser->loadIds(IDCHOOSER_ID_REQUIRED, default_author); QSignalMapper *signalMapper = new QSignalMapper(this); - connect(ui->postButton, SIGNAL(clicked()), signalMapper, SLOT(map())); - connect(ui->imageButton, SIGNAL(clicked()), signalMapper, SLOT(map())); - connect(ui->linkButton, SIGNAL(clicked()), signalMapper, SLOT(map())); + connect(ui->viewPostButton, SIGNAL(clicked()), signalMapper, SLOT(map())); + connect(ui->viewImageButton, SIGNAL(clicked()), signalMapper, SLOT(map())); + connect(ui->viewLinkButton, SIGNAL(clicked()), signalMapper, SLOT(map())); - signalMapper->setMapping(ui->postButton, VIEW_POST); - signalMapper->setMapping(ui->imageButton, VIEW_IMAGE); - signalMapper->setMapping(ui->linkButton, VIEW_LINK); + signalMapper->setMapping(ui->viewPostButton, VIEW_POST); + signalMapper->setMapping(ui->viewImageButton, VIEW_IMAGE); + signalMapper->setMapping(ui->viewLinkButton, VIEW_LINK); connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(setPage(int))); ui->removeButton->hide(); + ui->stackedWidgetPicture->setCurrentIndex(IMG_ATTACH); /* load settings */ processSettings(true); @@ -175,10 +183,20 @@ void PostedCreatePostDialog::createPost() return; } - uint32_t token; - mPosted->createPost(token, post); + RsThread::async([this,post]() + { + RsGxsMessageId post_id; - accept(); + bool res = rsPosted->createPost(post,post_id); + + RsQThreadUtils::postToObject( [res,this]() + { + if(!res) + QMessageBox::information(nullptr,tr("Error while creating post"),tr("An error occurred while creating the post.")); + + accept(); + }, this ); + }); } void PostedCreatePostDialog::fileHashingFinished(QList hashedFiles) @@ -189,7 +207,7 @@ void PostedCreatePostDialog::fileHashingFinished(QList hashedFiles) link = RetroShareLink::createFile(hashedFile.filename, hashedFile.size, QString::fromStdString(hashedFile.hash.toStdString())); ui->linkEdit->setText(link.toString()); } - ui->submitButton->setEnabled(true); + ui->postButton->setEnabled(true); ui->addPicButton->setEnabled(true); } @@ -202,7 +220,6 @@ void PostedCreatePostDialog::addPicture() // select a picture file if (misc::getOpenFileName(window(), RshareSettings::LASTDIR_IMAGES, tr("Load Picture File"), "Pictures (*.png *.xpm *.jpg *.jpeg *.gif *.webp )", imagefilename)) { - QString encodedImage; QImage image; if (image.load(imagefilename) == false) { fprintf (stderr, "RsHtml::makeEmbeddedImage() - image \"%s\" can't be load\n", imagefilename.toLatin1().constData()); @@ -211,9 +228,9 @@ void PostedCreatePostDialog::addPicture() } QImage opt; - if(ImageUtil::optimizeSizeBytes(imagebytes, image, opt, 640*480, MAXMESSAGESIZE - 2000)) { //Leave space for other stuff + if (optimizeImage(image, imagebytes, opt)) { ui->imageLabel->setPixmap(QPixmap::fromImage(opt)); - ui->stackedWidgetPicture->setCurrentIndex(1); + ui->stackedWidgetPicture->setCurrentIndex(IMG_PICTURE); ui->removeButton->show(); } else { imagefilename = ""; @@ -233,7 +250,7 @@ void PostedCreatePostDialog::addPicture() //If still yes then link it if(answer == QMessageBox::Yes) { - ui->submitButton->setEnabled(false); + ui->postButton->setEnabled(false); ui->addPicButton->setEnabled(false); QStringList files; files.append(imagefilename); @@ -243,13 +260,48 @@ void PostedCreatePostDialog::addPicture() } +void PostedCreatePostDialog::pastePicture() +{ + imagefilename = ""; + imagebytes.clear(); + QPixmap empty; + ui->imageLabel->setPixmap(empty); + + // paste picture from clipboard + const QClipboard *clipboard = QApplication::clipboard(); + const QMimeData *mimeData = clipboard->mimeData(); + + QImage image; + if (mimeData->hasImage()) { + image = (qvariant_cast(mimeData->imageData())); + + QImage opt; + if (optimizeImage(image, imagebytes, opt)) { + ui->imageLabel->setPixmap(QPixmap::fromImage(opt)); + ui->stackedWidgetPicture->setCurrentIndex(IMG_PICTURE); + ui->removeButton->show(); + } + } else { + QMessageBox::information(nullptr,tr("No clipboard image found."),tr("There is no image data in the clipboard to paste")); + imagefilename = ""; + imagebytes.clear(); + return; + } +} + +bool PostedCreatePostDialog::optimizeImage(const QImage &image, QByteArray &imagebytes, QImage &imageOpt) +{ + // Leave space for other stuff + return ImageUtil::optimizeSizeBytes(imagebytes, image, imageOpt, "JPG", 640*480, MAXMESSAGESIZE - 2000); +} + int PostedCreatePostDialog::viewMode() { - if (ui->postButton->isChecked()) { + if (ui->viewPostButton->isChecked()) { return VIEW_POST; - } else if (ui->imageButton->isChecked()) { + } else if (ui->viewImageButton->isChecked()) { return VIEW_IMAGE; - } else if (ui->linkButton->isChecked()) { + } else if (ui->viewLinkButton->isChecked()) { return VIEW_LINK; } @@ -259,45 +311,24 @@ int PostedCreatePostDialog::viewMode() void PostedCreatePostDialog::setPage(int viewMode) { - switch (viewMode) { - case VIEW_POST: - ui->stackedWidget->setCurrentIndex(0); + if( (viewMode < 0) || (viewMode > ui->stackedWidget->count()-1) ) + viewMode = VIEW_POST; - ui->postButton->setChecked(true); - ui->imageButton->setChecked(false); - ui->linkButton->setChecked(false); + ui->stackedWidget->setCurrentIndex(viewMode); - break; - case VIEW_IMAGE: - ui->stackedWidget->setCurrentIndex(1); + ui->viewPostButton ->setChecked(viewMode==VIEW_POST); + ui->viewImageButton->setChecked(viewMode==VIEW_IMAGE); + ui->viewLinkButton ->setChecked(viewMode==VIEW_LINK); - ui->imageButton->setChecked(true); - ui->postButton->setChecked(false); - ui->linkButton->setChecked(false); - - break; - case VIEW_LINK: - ui->stackedWidget->setCurrentIndex(2); - - ui->linkButton->setChecked(true); - ui->postButton->setChecked(false); - ui->imageButton->setChecked(false); - - break; - default: - setPage(VIEW_POST); - return; - } } void PostedCreatePostDialog::on_removeButton_clicked() { imagefilename = ""; imagebytes.clear(); - QPixmap empty; - ui->imageLabel->setPixmap(empty); + ui->imageLabel->setPixmap(QPixmap()); ui->removeButton->hide(); - ui->stackedWidgetPicture->setCurrentIndex(0); + ui->stackedWidgetPicture->setCurrentIndex(IMG_ATTACH); } void PostedCreatePostDialog::reject() @@ -307,3 +338,18 @@ void PostedCreatePostDialog::reject() QDialog::reject(); } + +void PostedCreatePostDialog::setTitle(const QString& title) +{ + ui->titleEdit->setText(title); +} + +void PostedCreatePostDialog::setNotes(const QString& notes) +{ + ui->RichTextEditWidget->setText(notes); +} + +void PostedCreatePostDialog::setLink(const QString& link) +{ + ui->linkEdit->setText(link); +} diff --git a/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.h b/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.h index a62fe46c6..5ac2c2e7d 100644 --- a/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.h +++ b/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.h @@ -24,7 +24,6 @@ #include #include #include "retroshare/rsposted.h" -#include "util/RichTextEdit.h" namespace Ui { class PostedCreatePostDialog; @@ -42,17 +41,23 @@ public: explicit PostedCreatePostDialog(RsPosted* posted, const RsGxsGroupId& grpId, const RsGxsId& default_author=RsGxsId(),QWidget *parent = 0); ~PostedCreatePostDialog(); + void setTitle(const QString& title); + void setNotes(const QString& notes); + void setLink(const QString& link); + + static bool optimizeImage(const QImage &image, QByteArray &imagebytes, QImage &imageOpt); + private: QString imagefilename; QByteArray imagebytes; - const int MAXMESSAGESIZE = 199000; private slots: void createPost(); void addPicture(); + void pastePicture(); void on_removeButton_clicked(); void fileHashingFinished(QList hashedFiles); - void reject(); + void reject() override; //QDialog void setPage(int viewMode); private: diff --git a/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.ui b/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.ui index bd44c4d0a..2a19f02d8 100644 --- a/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.ui +++ b/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.ui @@ -7,7 +7,7 @@ 0 0 575 - 518 + 468 @@ -40,21 +40,21 @@
- + QFrame::StyledPanel QFrame::Raised - + 0 - + 0 @@ -73,7 +73,7 @@ - + 0 @@ -104,7 +104,7 @@ Preview - + 0 @@ -115,7 +115,7 @@ 0 - + Qt::Horizontal @@ -128,7 +128,7 @@ - + Qt::Horizontal @@ -146,14 +146,14 @@ 0 - + - + 9 - - + + Qt::Horizontal @@ -182,15 +182,8 @@ - - - - Post size is limited to 32 KB, pictures will be downscaled. - - - - - + + Qt::Horizontal @@ -203,7 +196,14 @@ - + + + Post size is limited to 32 KB, pictures will be downscaled. + + + + + Qt::Vertical @@ -215,17 +215,37 @@ + + + + Paste image from clipboard + + + Paste Picture + + + + :/icons/svg/paste_image.svg:/icons/svg/paste_image.svg + + + + 32 + 32 + + + + - + Qt::Horizontal 267 - 138 + 20 @@ -233,7 +253,7 @@ - + 2 @@ -267,7 +287,7 @@ - + Qt::Horizontal @@ -305,7 +325,7 @@ - + 0 @@ -323,7 +343,7 @@ - + Qt::Vertical @@ -340,7 +360,7 @@ - + @@ -367,13 +387,20 @@ - + 0 0 + + + 12 + 75 + true + + @@ -399,12 +426,12 @@ - + 2 - + Post @@ -424,7 +451,7 @@ - + Image @@ -450,7 +477,7 @@ - + Link @@ -473,7 +500,7 @@ - + Qt::Horizontal @@ -488,10 +515,19 @@ - + + + + + 0 + 0 + 0 + + + @@ -512,6 +548,15 @@ + + + + 0 + 0 + 0 + + + @@ -532,6 +577,15 @@ + + + + 154 + 154 + 154 + + + @@ -553,6 +607,11 @@ + + + 12 + + true @@ -584,7 +643,7 @@ - + 6 @@ -613,15 +672,9 @@ - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
- - HashBox - QScrollArea -
gui/common/HashBox.h
- 1 + GxsIdChooser + QComboBox +
gui/gxs/GxsIdChooser.h
HeaderFrame @@ -629,21 +682,22 @@
gui/common/HeaderFrame.h
1
- - GxsIdChooser - QComboBox -
gui/gxs/GxsIdChooser.h
-
RichTextEdit QWidget
util/RichTextEdit.h
1
+ + HashBox + QScrollArea +
gui/common/HashBox.h
+ 1 +
- + diff --git a/retroshare-gui/src/gui/Posted/PostedDialog.cpp b/retroshare-gui/src/gui/Posted/PostedDialog.cpp index f1837da3b..733878810 100644 --- a/retroshare-gui/src/gui/Posted/PostedDialog.cpp +++ b/retroshare-gui/src/gui/Posted/PostedDialog.cpp @@ -26,6 +26,7 @@ #include "gui/gxs/GxsGroupShareKey.h" #include "gui/settings/rsharesettings.h" #include "gui/common/GroupTreeWidget.h" +#include "util/misc.h" #include "util/qtthreadsutils.h" #include @@ -42,7 +43,7 @@ public: /** Constructor */ PostedDialog::PostedDialog(QWidget *parent): - GxsGroupFrameDialog(rsPosted, parent), mEventHandlerId(0) + GxsGroupFrameDialog(rsPosted, settingsGroupName(),parent), mEventHandlerId(0) { // Needs to be asynced because this function is likely to be called by another thread! rsEvents->registerEventsHandler( @@ -95,14 +96,19 @@ UserNotify *PostedDialog::createUserNotify(QObject *parent) QString PostedDialog::getHelpString() const { - QString hlp_str = tr("

  Boards

\ -

The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and \ - channels

\ -

Posts can be commented by subscribed users. A promotion system also gives the opportunity to \ - enlight important links.

\ -

There is no restriction on which links are shared. Be careful when clicking on them.

\ -

Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.

\ - ").arg(QString::number(rsPosted->getDefaultStoragePeriod()/86400)).arg(QString::number(rsPosted->getDefaultSyncPeriod()/86400)); + int H = misc::getFontSizeFactor("HelpButton").height(); + + QString hlp_str = tr( + "

  Boards

" + "

The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and" + " channels

" + "

Posts can be commented by subscribed users. A promotion system also gives the opportunity to" + " enlight important links.

" + "

There is no restriction on which links are shared. Be careful when clicking on them.

" + "

Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.

" + ).arg( QString::number(2*H) + , QString::number(rsPosted->getDefaultStoragePeriod()/86400) + , QString::number(rsPosted->getDefaultSyncPeriod()/86400)); return hlp_str ; } @@ -211,34 +217,6 @@ QWidget *PostedDialog::createCommentHeaderWidget(const RsGxsGroupId &grpId, cons return new PostedItem(NULL, 0, grpId, msgId, true, false); } -#ifdef TO_REMOVE -void PostedDialog::loadGroupSummaryToken(const uint32_t &token, std::list &groupInfo, RsUserdata *&userdata) -{ - std::vector groups; - rsPosted->getGroupData(token, groups); - - /* Save groups to fill description */ - PostedGroupInfoData *postedData = new PostedGroupInfoData; - userdata = postedData; - - std::vector::iterator groupIt; - for (groupIt = groups.begin(); groupIt != groups.end(); ++groupIt) { - RsPostedGroup &group = *groupIt; - groupInfo.push_back(group.mMeta); - - if (group.mGroupImage.mData != NULL) { - QPixmap image; - GxsIdDetails::loadPixmapFromData(group.mGroupImage.mData, group.mGroupImage.mSize, image,GxsIdDetails::ORIGINAL); - postedData->mIcon[group.mMeta.mGroupId] = image; - } - - if (!group.mDescription.empty()) { - postedData->mDescription[group.mMeta.mGroupId] = QString::fromUtf8(group.mDescription.c_str()); - } - } -} -#endif - void PostedDialog::groupInfoToGroupItemInfo(const RsGxsGenericGroupData *groupData, GroupItemInfo &groupItemInfo) { GxsGroupFrameDialog::groupInfoToGroupItemInfo(groupData, groupItemInfo); diff --git a/retroshare-gui/src/gui/Posted/PostedGroupDialog.cpp b/retroshare-gui/src/gui/Posted/PostedGroupDialog.cpp index c516f7520..f2b011adb 100644 --- a/retroshare-gui/src/gui/Posted/PostedGroupDialog.cpp +++ b/retroshare-gui/src/gui/Posted/PostedGroupDialog.cpp @@ -22,8 +22,9 @@ #include "PostedGroupDialog.h" #include "gui/gxs/GxsIdDetails.h" #include "gui/common/FilesDefs.h" +#include "util/imageutil.h" -#include +#include "retroshare/rswiki.h" #include const uint32_t PostedCreateEnabledFlags = ( @@ -104,8 +105,10 @@ void PostedGroupDialog::preparePostedGroup(RsPostedGroup &group, const RsGroupMe QByteArray ba; QBuffer buffer(&ba); - buffer.open(QIODevice::WriteOnly); - pixmap.save(&buffer, "PNG"); // writes image into ba in PNG format + bool has_transparency = ImageUtil::hasAlphaContent(pixmap.toImage()); + + buffer.open(QIODevice::WriteOnly); + pixmap.save(&buffer, has_transparency?"PNG":"JPG"); // writes image into ba in PNG format group.mGroupImage.copy((uint8_t *) ba.data(), ba.size()); } else { @@ -136,7 +139,7 @@ bool PostedGroupDialog::service_updateGroup(const RsGroupMetaData& editedMeta) return rsPosted->editBoard(grp); } -bool PostedGroupDialog::service_loadGroup(const RsGxsGenericGroupData *data, Mode mode, QString& description) +bool PostedGroupDialog::service_loadGroup(const RsGxsGenericGroupData *data, Mode /*mode*/, QString& description) { const RsPostedGroup *pgroup = dynamic_cast(data); diff --git a/retroshare-gui/src/gui/Posted/PostedItem.cpp b/retroshare-gui/src/gui/Posted/PostedItem.cpp index fa79b9d70..8f1cddf7d 100644 --- a/retroshare-gui/src/gui/Posted/PostedItem.cpp +++ b/retroshare-gui/src/gui/Posted/PostedItem.cpp @@ -74,7 +74,7 @@ BasePostedItem::BasePostedItem( FeedHolder *feedHolder, uint32_t feedId BasePostedItem::~BasePostedItem() { - auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(200); + auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(200); while( (mIsLoadingGroup || mIsLoadingMessage || mIsLoadingComment) && std::chrono::steady_clock::now() < timeout) { @@ -279,16 +279,16 @@ void BasePostedItem::loadComments() } void BasePostedItem::readToggled(bool checked) { - if (mInFill) { - return; - } + if (mInFill) { + return; + } + setReadStatus(false, checked); - RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); - - uint32_t token; - rsPosted->setMessageReadStatus(token, msgPair, !checked); - - setReadStatus(false, checked); + RsThread::async([this,checked]() + { + RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); + rsPosted->setPostReadStatus(msgPair, !checked); + }); } void BasePostedItem::readAndClearItem() @@ -495,7 +495,7 @@ void PostedItem::fill() ui->voteUpButton->setDisabled(true); ui->voteDownButton->setDisabled(true); - ui->thumbnailLabel->setPixmap( FilesDefs::getPixmapFromQtResourcePath(":/images/thumb-default.png")); + ui->thumbnailLabel->setPicture( FilesDefs::getPixmapFromQtResourcePath(":/images/thumb-default.png")); ui->fromLabel->setId(mPost.mMeta.mAuthorId); ui->titleLabel->setText(tr( "

The author of this message (with ID %1) is banned.").arg(QString::fromStdString(mPost.mMeta.mAuthorId.toStdString()))) ; QDateTime qtime; @@ -509,8 +509,10 @@ void PostedItem::fill() QPixmap sqpixmap2 = FilesDefs::getPixmapFromQtResourcePath(":/images/thumb-default.png"); mInFill = true; - int desired_height = 1.5*(ui->voteDownButton->height() + ui->voteUpButton->height() + ui->scoreLabel->height()); - int desired_width = sqpixmap2.width()*desired_height/(float)sqpixmap2.height(); + int desired_height = ui->voteDownButton->height() + ui->voteUpButton->height() + ui->scoreLabel->height(); + int desired_width = 16/9.0 * desired_height; //sqpixmap2.width()*desired_height/(float)sqpixmap2.height(); + + ui->thumbnailLabel->setFixedSize(desired_width,desired_height); QDateTime qtime; qtime.setTime_t(mPost.mMeta.mPublishTs); @@ -573,17 +575,17 @@ void PostedItem::fill() GxsIdDetails::loadPixmapFromData(mPost.mImage.mData, mPost.mImage.mSize, pixmap,GxsIdDetails::ORIGINAL); // Wiping data - as its been passed to thumbnail. - QPixmap sqpixmap = pixmap.scaled(desired_width,desired_height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); - ui->thumbnailLabel->setPixmap(sqpixmap); +// QPixmap sqpixmap = pixmap.scaled(desired_width,desired_height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); + ui->thumbnailLabel->setPicture(pixmap); ui->thumbnailLabel->setToolTip(tr("Click to view Picture")); + ui->thumbnailLabel->setEnableZoom(false); - QPixmap scaledpixmap; - if(pixmap.width() > 800){ - QPixmap scaledpixmap = pixmap.scaledToWidth(800, Qt::SmoothTransformation); - ui->pictureLabel->setPixmap(scaledpixmap); - }else{ - ui->pictureLabel->setPixmap(pixmap); - } + QPixmap scaledpixmap; + if(pixmap.width() > 800){ + QPixmap scaledpixmap = pixmap.scaledToWidth(800, Qt::SmoothTransformation); + ui->pictureLabel->setPixmap(scaledpixmap); + }else + ui->pictureLabel->setPixmap(pixmap); } else if (urlOkay && (mPost.mImage.mData == NULL)) { @@ -705,9 +707,9 @@ void PostedItem::setReadStatus(bool isNew, bool isUnread) //ui->newLabel->setVisible(isNew); - ui->mainFrame->setProperty("new", isNew); - ui->mainFrame->style()->unpolish(ui->mainFrame); - ui->mainFrame->style()->polish( ui->mainFrame); + ui->feedFrame->setProperty("new", isNew); + ui->feedFrame->style()->unpolish(ui->feedFrame); + ui->feedFrame->style()->polish( ui->feedFrame); } diff --git a/retroshare-gui/src/gui/Posted/PostedItem.h b/retroshare-gui/src/gui/Posted/PostedItem.h index d726cf830..a2f432dc0 100644 --- a/retroshare-gui/src/gui/Posted/PostedItem.h +++ b/retroshare-gui/src/gui/Posted/PostedItem.h @@ -112,11 +112,11 @@ protected: void setCommentsSize(int comNb) override; private slots: - void doExpand(bool open); - void toggle(); - void makeUpVote(); - void makeDownVote(); - void toggleNotes() ; + void doExpand(bool open) override; + void toggle() override; + void makeUpVote() override; + void makeDownVote() override; + void toggleNotes() override; private: /** Qt Designer generated object */ diff --git a/retroshare-gui/src/gui/Posted/PostedItem.ui b/retroshare-gui/src/gui/Posted/PostedItem.ui index f16c7b100..ad37a936c 100644 --- a/retroshare-gui/src/gui/Posted/PostedItem.ui +++ b/retroshare-gui/src/gui/Posted/PostedItem.ui @@ -16,7 +16,7 @@ - + 1 @@ -33,7 +33,7 @@ 0 - + 0 @@ -44,12 +44,12 @@ false - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + 0 @@ -82,21 +82,21 @@ QFrame::Plain - + 0 - 3 + 0 - 3 + 0 - 3 + 0 - 3 + 0 @@ -125,7 +125,12 @@ - + + + + 14 + + 0 @@ -164,7 +169,7 @@ - + Qt::Vertical @@ -173,8 +178,8 @@ - 20 - 5 + 0 + 0 @@ -183,7 +188,7 @@ - + 9 @@ -191,7 +196,7 @@ 6 - + 0 @@ -228,7 +233,7 @@ - + Qt::Vertical @@ -243,12 +248,12 @@ - + 6 - + 0 @@ -258,6 +263,7 @@ 75 + true true @@ -279,7 +285,7 @@ - + 0 @@ -305,7 +311,7 @@ - + 0 @@ -313,7 +319,7 @@ QLayout::SetDefaultConstraint - + 5 @@ -327,6 +333,7 @@ + 11 75 true true @@ -408,7 +415,7 @@ - + Qt::Horizontal @@ -426,7 +433,7 @@ - + 6 @@ -559,7 +566,7 @@ - + Qt::Horizontal @@ -623,9 +630,9 @@ QFrame::Raised - + - + Qt::Horizontal @@ -651,7 +658,7 @@ - + Qt::Horizontal @@ -677,7 +684,7 @@ QFrame::Sunken - + 3 @@ -718,31 +725,26 @@ - - StyledLabel - QLabel -

gui/common/StyledLabel.h
-
- - ElidedLabel - QLabel -
gui/common/ElidedLabel.h
- 1 -
GxsIdLabel QLabel
gui/gxs/GxsIdLabel.h
- ClickableLabel + ElidedLabel QLabel -
util/ClickableLabel.h
+
gui/common/ElidedLabel.h
+ 1 +
+ + ZoomableLabel + QLabel +
gui/gxschannels/GxsChannelPostThumbnail.h
- + diff --git a/retroshare-gui/src/gui/Posted/PostedListWidget.cpp b/retroshare-gui/src/gui/Posted/PostedListWidget.cpp index a88a1d6b5..c5f95aa24 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidget.cpp +++ b/retroshare-gui/src/gui/Posted/PostedListWidget.cpp @@ -102,7 +102,7 @@ PostedListWidget::PostedListWidget(const RsGxsGroupId &postedId, QWidget *parent available posts from your subscribed friends, and make the \ links visible to all other friends.

Afterwards you can unsubscribe from the context menu of the links list at left.

")); - ui->infoframe->hide(); + ui->infoFrame->hide(); /* load settings */ processSettings(true); @@ -417,7 +417,7 @@ void PostedListWidget::insertPostedDetails(const RsPostedGroup &group) if (IS_GROUP_SUBSCRIBED(group.mMeta.mSubscribeFlags)) { - ui->infoframe->hide(); + ui->infoFrame->hide(); } else { @@ -472,7 +472,7 @@ void PostedListWidget::insertPostedDetails(const RsPostedGroup &group) ui->infoDistribution->setText(distrib_string); - ui->infoframe->show(); + ui->infoFrame->show(); } } @@ -771,7 +771,7 @@ void PostedListWidget::applyRanking() void PostedListWidget::blank() { clearPosts(); - ui->infoframe->hide(); + ui->infoFrame->hide(); } void PostedListWidget::clearPosts() { diff --git a/retroshare-gui/src/gui/Posted/PostedListWidget.ui b/retroshare-gui/src/gui/Posted/PostedListWidget.ui index f59ee76ee..22f1761ca 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidget.ui +++ b/retroshare-gui/src/gui/Posted/PostedListWidget.ui @@ -30,7 +30,7 @@ 0 - + QFrame::Box @@ -106,7 +106,7 @@ - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -260,7 +260,7 @@ - + QFrame::StyledPanel @@ -323,7 +323,7 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Description</span></p></body></html> @@ -515,7 +515,10 @@ p, li { white-space: pre-wrap; } - 14 + 11 + 75 + true + true @@ -658,16 +661,21 @@ p, li { white-space: pre-wrap; } QLabel
gui/gxs/GxsIdLabel.h
- - SubscribeToolButton - QToolButton -
gui/common/SubscribeToolButton.h
-
GxsIdChooser QComboBox
gui/gxs/GxsIdChooser.h
+ + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
+ + SubscribeToolButton + QToolButton +
gui/common/SubscribeToolButton.h
+
diff --git a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.cpp b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.cpp index 8ff178af6..ebc0aca2b 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.cpp +++ b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "retroshare/rsgxscircles.h" @@ -44,6 +45,7 @@ #include "util/DateTime.h" #include "util/qtthreadsutils.h" #include "gui/common/FilesDefs.h" +#include "util/QtVersion.h" #include "gui/MainWindow.h" @@ -58,9 +60,7 @@ // number of posts to show at once. #define POSTS_CHUNK_SIZE 25 -/**** - * #define DEBUG_POSTED - ***/ +//#define DEBUG_POSTED static const int POSTED_TABS_POSTS = 1; @@ -74,6 +74,7 @@ static const int POSTED_TABS_POSTS = 1; // #define IMAGE_COPYLINK ":/images/copyrslink.png" #define IMAGE_AUTHOR ":/images/user/personal64.png" +#define IMAGE_COPYHTTP ":/images/emblem-web.png" Q_DECLARE_METATYPE(RsPostedPost); @@ -87,8 +88,12 @@ std::ostream& operator<<(std::ostream& o,const QSize& s) { return o << s.width() void PostedPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { +#ifdef DEBUG_POSTED + if(option.state & QStyle::State_Selected) RS_DBG("Selected"); +#endif + if((option.state & QStyle::State_Selected)) // Avoids double display. The selected widget is never exactly the size of the rendered one, - return; // so when selected, we only draw the selected one. + return; // so when selected, we only draw the selected one. // prepare painter->save(); @@ -98,7 +103,7 @@ void PostedPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem & painter->save(); - painter->fillRect( option.rect, option.palette.background()); + painter->fillRect( option.rect, option.palette.window()); painter->restore(); QPixmap pixmap(option.rect.size()); @@ -109,9 +114,9 @@ void PostedPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem & BoardPostDisplayWidget_compact w(post,displayFlags(post.mMeta.mMsgId),nullptr); w.setFixedSize(option.rect.size()); - w.updateGeometry(); w.adjustSize(); + w.render(&pixmap,QPoint(0,0),QRegion(),QWidget::DrawChildren );// draw the widgets, not the background } else @@ -121,6 +126,7 @@ void PostedPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem & w.setFixedSize(option.rect.size()); w.updateGeometry(); w.adjustSize(); + w.render(&pixmap,QPoint(0,0),QRegion(),QWidget::DrawChildren );// draw the widgets, not the background } @@ -145,6 +151,10 @@ void PostedPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem & painter->save(); painter->drawPixmap(option.rect.topLeft(), pixmap /*,.scaled(option.rect.width(),option.rect.width()*w.height()/(float)w.width(),Qt::KeepAspectRatio,Qt::SmoothTransformation)*/); +#ifdef DEBUG_POSTED + painter->drawText(option.rect.bottomLeft(),QString::number(time(nullptr))); + RS_DBG("DisplayMode=", mDisplayMode == BoardPostDisplayWidget_compact::DISPLAY_MODE_COMPACT? "Compact":"Card", " Title:", post.mMeta.mMsgName.c_str()); +#endif painter->restore(); } @@ -193,40 +203,45 @@ uint8_t PostedPostDelegate::displayFlags(const RsGxsMessageId &id) const QWidget *PostedPostDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex& index) const { - RsPostedPost post = index.data(Qt::UserRole).value() ; - if(index.column() == RsPostedPostsModel::COLUMN_POSTS) - { - QWidget *w ; + if (!index.isValid()) + return nullptr; - if(mDisplayMode==BoardPostDisplayWidget_compact::DISPLAY_MODE_COMPACT) - w = new BoardPostDisplayWidget_compact(post,displayFlags(post.mMeta.mMsgId),parent); - else - w = new BoardPostDisplayWidget_card(post,displayFlags(post.mMeta.mMsgId),parent); + if(index.column() != RsPostedPostsModel::COLUMN_POSTS) + return nullptr; - QObject::connect(w,SIGNAL(vote(RsGxsGrpMsgIdPair,bool)),mPostListWidget,SLOT(voteMsg(RsGxsGrpMsgIdPair,bool))); - QObject::connect(w,SIGNAL(expand(RsGxsMessageId,bool)),this,SLOT(expandItem(RsGxsMessageId,bool))); - QObject::connect(w,SIGNAL(commentsRequested(const RsGxsMessageId&,bool)),mPostListWidget,SLOT(openComments(const RsGxsMessageId&))); - QObject::connect(w,SIGNAL(changeReadStatusRequested(const RsGxsMessageId&,bool)),mPostListWidget,SLOT(changeReadStatus(const RsGxsMessageId&,bool))); + QWidget *w ; + RsPostedPost post = index.data(Qt::UserRole).value() ; - // All other interactions with the widget should cause the msg to be set as read. - QObject::connect(w,SIGNAL(thumbnailOpenned()),mPostListWidget,SLOT(markCurrentPostAsRead())); - QObject::connect(w,SIGNAL(vote(RsGxsGrpMsgIdPair,bool)),mPostListWidget,SLOT(markCurrentPostAsRead())); - QObject::connect(w,SIGNAL(expand(RsGxsMessageId,bool)),this,SLOT(markCurrentPostAsRead())); - QObject::connect(w,SIGNAL(commentsRequested(const RsGxsMessageId&,bool)),mPostListWidget,SLOT(markCurrentPostAsRead())); - QObject::connect(w,SIGNAL(shareButtonClicked()),mPostListWidget,SLOT(markCurrentPostAsRead())); - QObject::connect(w,SIGNAL(copylinkClicked()),mPostListWidget,SLOT(copyMessageLink())); +#ifdef DEBUG_POSTED + RS_DBG("Title:", post.mMeta.mMsgName.c_str()); +#endif - w->setFixedSize(option.rect.size()); - w->adjustSize(); - w->updateGeometry(); - w->adjustSize(); + if(mDisplayMode==BoardPostDisplayWidget_compact::DISPLAY_MODE_COMPACT) + w = new BoardPostDisplayWidget_compact(post,displayFlags(post.mMeta.mMsgId),parent); + else + w = new BoardPostDisplayWidget_card(post,displayFlags(post.mMeta.mMsgId),parent); - return w; - } - else - return NULL; + QObject::connect(w,SIGNAL(vote(RsGxsGrpMsgIdPair,bool)),mPostListWidget,SLOT(voteMsg(RsGxsGrpMsgIdPair,bool))); + QObject::connect(w,SIGNAL(expand(RsGxsMessageId,bool)),this,SLOT(expandItem(RsGxsMessageId,bool))); + QObject::connect(w,SIGNAL(commentsRequested(RsGxsMessageId,bool)),mPostListWidget,SLOT(openComments(RsGxsMessageId))); + QObject::connect(w,SIGNAL(changeReadStatusRequested(RsGxsMessageId,bool)),mPostListWidget,SLOT(changeReadStatus(RsGxsMessageId,bool))); + + // All other interactions with the widget should cause the msg to be set as read. + QObject::connect(w,SIGNAL(thumbnailOpenned()),mPostListWidget,SLOT(markCurrentPostAsRead())); + QObject::connect(w,SIGNAL(vote(RsGxsGrpMsgIdPair,bool)),mPostListWidget,SLOT(markCurrentPostAsRead())); + QObject::connect(w,SIGNAL(expand(RsGxsMessageId,bool)),this,SLOT(markCurrentPostAsRead())); + QObject::connect(w,SIGNAL(commentsRequested(RsGxsMessageId,bool)),mPostListWidget,SLOT(markCurrentPostAsRead())); + QObject::connect(w,SIGNAL(shareButtonClicked()),mPostListWidget,SLOT(markCurrentPostAsRead())); + + w->setGeometry(option.rect); + w->adjustSize(); + w->updateGeometry(); + w->adjustSize(); + + return w; } + void PostedPostDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const { editor->setGeometry(option.rect); @@ -264,13 +279,10 @@ PostedListWidgetWithModel::PostedListWidgetWithModel(const RsGxsGroupId& postedI connect(ui->nextButton,SIGNAL(clicked()),this,SLOT(nextPosts())); connect(ui->prevButton,SIGNAL(clicked()),this,SLOT(prevPosts())); - connect(ui->postsTree,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(postContextMenu(const QPoint&))); connect(ui->viewModeButton,SIGNAL(clicked()),this,SLOT(switchDisplayMode())); connect(mPostedPostsModel,SIGNAL(boardPostsLoaded()),this,SLOT(postPostLoad())); - QFontMetricsF fm(font()); - /* Setup UI helper */ /* Connect signals */ @@ -285,7 +297,11 @@ PostedListWidgetWithModel::PostedListWidgetWithModel(const RsGxsGroupId& postedI connect(ui->postsTree,SIGNAL(sizeChanged(QSize)),this,SLOT(handlePostsTreeSizeChange(QSize))); - /* load settings */ + ui->postsTree->setContextMenuPolicy(Qt::CustomContextMenu); + //QObject::connect(this,SIGNAL(copylinkClicked()),this,SLOT(copyMessageLink())); + connect(ui->postsTree,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(postContextMenu(const QPoint&))); + + /* load settings */ processSettings(true); /* Initialize subscribe button */ @@ -314,6 +330,43 @@ PostedListWidgetWithModel::PostedListWidgetWithModel(const RsGxsGroupId& postedI }, mEventHandlerId, RsEventType::GXS_POSTED ); } +void PostedListWidgetWithModel::postContextMenu(const QPoint& point) +{ + QMenu menu(this); + + // 1 - check that we are clicking on a post + + QModelIndex index = ui->postsTree->indexAt(point); + + if(!index.isValid()) + return; + + // 2 - generate the menu for that post. + + RsPostedPost post = index.data(Qt::UserRole).value() ; + + menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyMessageLink()))->setData(index); + + QByteArray urlarray(post.mLink.c_str()); + QUrl url = QUrl::fromEncoded(urlarray.trimmed()); + + std::cerr << "Using link: \"" << post.mLink << "\"" << std::endl; + + if(url.scheme()=="http" || url.scheme()=="https") + menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_COPYHTTP), tr("Copy http Link"), this, SLOT(copyHttpLink()))->setData(index); + + menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_AUTHOR), tr("Show author in People tab"), this, SLOT(showAuthorInPeople()))->setData(index); + +#ifdef TODO + // This feature is not implemented yet in libretroshare. + + if(IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) + menu.addAction(FilesDefs::getIconFromQtResourcePath(":/images/edit_16.png"), tr("Edit"), this, SLOT(editPost())); +#endif + + menu.exec(QCursor::pos()); +} + void PostedListWidgetWithModel::switchDisplayMode() { if(mPostedPostsDelegate->getDisplayMode() == BoardPostDisplayWidget_compact::DISPLAY_MODE_CARD) @@ -365,7 +418,7 @@ void PostedListWidgetWithModel::updateShowLabel() void PostedListWidgetWithModel::filterItems(QString text) { - QStringList lst = text.split(" ",QString::SkipEmptyParts) ; + QStringList lst = text.split(" ",QtSkipEmptyParts) ; uint32_t count; mPostedPostsModel->setFilter(lst,count) ; @@ -374,28 +427,25 @@ void PostedListWidgetWithModel::filterItems(QString text) void PostedListWidgetWithModel::nextPosts() { - ui->postsTree->selectionModel()->clear(); - if(mPostedPostsModel->displayedStartPostIndex() + POSTS_CHUNK_SIZE < mPostedPostsModel->filteredPostsCount()) - { - mPostedPostsModel->setPostsInterval(POSTS_CHUNK_SIZE+mPostedPostsModel->displayedStartPostIndex(),POSTS_CHUNK_SIZE); + if(mPostedPostsModel->displayedStartPostIndex() + POSTS_CHUNK_SIZE < mPostedPostsModel->filteredPostsCount()) + { + mPostedPostsModel->setPostsInterval(POSTS_CHUNK_SIZE+mPostedPostsModel->displayedStartPostIndex(),POSTS_CHUNK_SIZE); updateShowLabel(); - } + } } void PostedListWidgetWithModel::prevPosts() { - ui->postsTree->selectionModel()->clear(); - - if((int)mPostedPostsModel->displayedStartPostIndex() > 0) - { - mPostedPostsModel->setPostsInterval((int)mPostedPostsModel->displayedStartPostIndex()-POSTS_CHUNK_SIZE,POSTS_CHUNK_SIZE); - updateShowLabel(); - } + if((int)mPostedPostsModel->displayedStartPostIndex() > 0) + { + mPostedPostsModel->setPostsInterval((int)mPostedPostsModel->displayedStartPostIndex()-POSTS_CHUNK_SIZE,POSTS_CHUNK_SIZE); + updateShowLabel(); + } } void PostedListWidgetWithModel::showAuthorInPeople() { - QModelIndex index = ui->postsTree->selectionModel()->currentIndex(); + QModelIndex index = qobject_cast(QObject::sender())->data().toModelIndex(); if(!index.isValid()) throw std::runtime_error("No post under mouse!"); @@ -420,23 +470,31 @@ void PostedListWidgetWithModel::showAuthorInPeople() MainWindow::showWindow(MainWindow::People); idDialog->navigate(RsGxsId(post.mMeta.mAuthorId)); } -void PostedListWidgetWithModel::postContextMenu(const QPoint&) +void PostedListWidgetWithModel::copyHttpLink() { - QMenu menu(this); + try + { + if (groupId().isNull()) + throw std::runtime_error("No channel currently selected!"); - menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyMessageLink())); - menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_AUTHOR), tr("Show author in People tab"), this, SLOT(showAuthorInPeople())); + QModelIndex index = qobject_cast(QObject::sender())->data().toModelIndex(); -#ifdef TODO - // This feature is not implemented yet in libretroshare. + if(!index.isValid()) + throw std::runtime_error("No post under mouse!"); - if(IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) - menu.addAction(FilesDefs::getIconFromQtResourcePath(":/images/edit_16.png"), tr("Edit"), this, SLOT(editPost())); -#endif + RsPostedPost post = index.data(Qt::UserRole).value() ; - menu.exec(QCursor::pos()); + if(post.mMeta.mMsgId.isNull()) + throw std::runtime_error("Post has empty MsgId!"); + + QApplication::clipboard()->setText(QString::fromStdString(post.mLink)) ; + QMessageBox::information(NULL,tr("information"),tr("The Retrohare link was copied to your clipboard.")) ; + } + catch(std::exception& e) + { + QMessageBox::critical(NULL,tr("Link creation error"),tr("Link could not be created: ")+e.what()); + } } - void PostedListWidgetWithModel::copyMessageLink() { try @@ -444,7 +502,7 @@ void PostedListWidgetWithModel::copyMessageLink() if (groupId().isNull()) throw std::runtime_error("No channel currently selected!"); - QModelIndex index = ui->postsTree->selectionModel()->currentIndex(); + QModelIndex index = qobject_cast(QObject::sender())->data().toModelIndex(); if(!index.isValid()) throw std::runtime_error("No post under mouse!"); @@ -490,116 +548,36 @@ void PostedListWidgetWithModel::handleEvent_main_thread(std::shared_ptrmPostedEventCode) { - case RsPostedEventCode::NEW_COMMENT: // [[fallthrough]]; - case RsPostedEventCode::NEW_VOTE: // [[fallthrough]]; - { - // special treatment here because the message might be a comment, so we need to refresh the comment tab if openned + case RsPostedEventCode::NEW_COMMENT: [[fallthrough]]; + case RsPostedEventCode::NEW_VOTE: + { + // special treatment here because the message might be a comment, so we need to refresh the comment tab if openned - for(int i=2;itabWidget->count();++i) - { - auto *t = dynamic_cast(ui->tabWidget->widget(i)); + for(int i=2;itabWidget->count();++i) + { + auto *t = dynamic_cast(ui->tabWidget->widget(i)); - if(t->groupId() == e->mPostedGroupId) - t->refresh(); - } - } - case RsPostedEventCode::NEW_MESSAGE: // [[fallthrough]]; - case RsPostedEventCode::NEW_POSTED_GROUP: // [[fallthrough]]; - case RsPostedEventCode::UPDATED_POSTED_GROUP: // [[fallthrough]]; - case RsPostedEventCode::UPDATED_MESSAGE: - case RsPostedEventCode::BOARD_DELETED: - case RsPostedEventCode::SYNC_PARAMETERS_UPDATED: - { + if(t->groupId() == e->mPostedGroupId) + t->refresh(); + } + } + [[clang::fallthrough]]; + case RsPostedEventCode::NEW_MESSAGE: [[fallthrough]]; + case RsPostedEventCode::NEW_POSTED_GROUP: [[fallthrough]]; + case RsPostedEventCode::UPDATED_POSTED_GROUP: [[fallthrough]]; + case RsPostedEventCode::UPDATED_MESSAGE: [[fallthrough]]; + case RsPostedEventCode::BOARD_DELETED: [[fallthrough]]; + case RsPostedEventCode::SYNC_PARAMETERS_UPDATED: + { if(e->mPostedGroupId == groupId()) updateDisplay(true); - } + } default: break; } } -#ifdef TO_REMOVE -void PostedListWidgetWithModel::showPostDetails() -{ - QModelIndex index = ui->postsTree->selectionModel()->currentIndex(); - RsPostedPost post = index.data(Qt::UserRole).value() ; - - QTextDocument doc; - doc.setHtml(post.mMsg.c_str()); - - if(post.mMeta.mPublishTs == 0) - { - ui->postDetails_TE->clear(); - ui->postLogo_LB->hide(); - ui->postName_LB->hide(); - ui->postTime_LB->hide(); - mChannelPostFilesModel->clear(); - - return; - } - - ui->postLogo_LB->show(); - ui->postName_LB->show(); - ui->postTime_LB->show(); - - if(index.row()==0 && index.column()==0) - std::cerr << "here" << std::endl; - - std::cerr << "showPostDetails: setting mLastSelectedPosts[groupId()] to current post Id " << post.mMeta.mMsgId << ". Previous value: " << mLastSelectedPosts[groupId()] << std::endl; - mLastSelectedPosts[groupId()] = post.mMeta.mMsgId; - - std::list files; - for(auto& file:post.mFiles) - files.push_back(ChannelPostFileInfo(file,post.mMeta.mPublishTs)); - - mChannelPostFilesModel->setFiles(files); - - auto all_msgs_versions(post.mOlderVersions); - all_msgs_versions.insert(post.mMeta.mMsgId); - - ui->commentsDialog->commentLoad(post.mMeta.mGroupId, all_msgs_versions, post.mMeta.mMsgId); - - std::cerr << "Showing details about selected index : "<< index.row() << "," << index.column() << std::endl; - - ui->postDetails_TE->setText(RsHtml().formatText(NULL, QString::fromUtf8(post.mMsg.c_str()), /* RSHTML_FORMATTEXT_EMBED_SMILEYS |*/ RSHTML_FORMATTEXT_EMBED_LINKS)); - - QPixmap postImage; - - if (post.mThumbnail.mData != NULL) - GxsIdDetails::loadPixmapFromData(post.mThumbnail.mData, post.mThumbnail.mSize, postImage,GxsIdDetails::ORIGINAL); - else - postImage = FilesDefs::getPixmapFromQtResourcePath(ChannelPostThumbnailView::CHAN_DEFAULT_IMAGE); - - int W = QFontMetricsF(font()).height() * 8; - - // Using fixed width so that the post will not displace the text when we browse. - - ui->postLogo_LB->setPixmap(postImage); - ui->postLogo_LB->setFixedSize(W,postImage.height()/(float)postImage.width()*W); - - ui->postName_LB->setText(QString::fromUtf8(post.mMeta.mMsgName.c_str())); - ui->postName_LB->setFixedWidth(W); - ui->postTime_LB->setText(QDateTime::fromMSecsSinceEpoch(post.mMeta.mPublishTs*1000).toString("MM/dd/yyyy, hh:mm")); - ui->postTime_LB->setFixedWidth(W); - - //ui->channelPostFiles_TV->resizeColumnToContents(RsGxsChannelPostFilesModel::COLUMN_FILES_FILE); - //ui->channelPostFiles_TV->resizeColumnToContents(RsGxsChannelPostFilesModel::COLUMN_FILES_SIZE); - ui->channelPostFiles_TV->setAutoSelect(true); - - // Now also set the post as read - - if(IS_MSG_UNREAD(post.mMeta.mMsgStatus) || IS_MSG_NEW(post.mMeta.mMsgStatus)) - { - RsGxsGrpMsgIdPair postId; - postId.second = post.mMeta.mMsgId; - postId.first = post.mMeta.mGroupId; - - RsThread::async([postId]() { rsGxsChannels->markRead(postId, true) ; } ); - } -} -#endif - void PostedListWidgetWithModel::updateGroupData() { if(groupId().isNull()) @@ -642,12 +620,13 @@ void PostedListWidgetWithModel::updateGroupData() void PostedListWidgetWithModel::postPostLoad() { +#ifdef DEBUG_POSTED std::cerr << "Post channel load..." << std::endl; +#endif whileBlocking(ui->filter_LE)->setText(QString()); //Clear it before navigate, as it will update it. if (!mNavigatePendingMsgId.isNull()) navigate(mNavigatePendingMsgId); - #ifdef TO_REMOVE else if( (mLastSelectedPosts.count(groupId()) > 0) && !mLastSelectedPosts[groupId()].isNull()) @@ -662,8 +641,10 @@ void PostedListWidgetWithModel::postPostLoad() ui->postsTree->setFocus(); } #endif +#ifdef DEBUG_POSTED else std::cerr << "No pre-selected channel post." << std::endl; +#endif updateShowLabel(); } @@ -764,7 +745,7 @@ QIcon PostedListWidgetWithModel::groupIcon() return QIcon(postedImage); } -void PostedListWidgetWithModel::setAllMessagesReadDo(bool read, uint32_t &/*token*/) +void PostedListWidgetWithModel::setAllMessagesReadDo(bool read) { if (groupId().isNull() || !IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags)) return; @@ -786,7 +767,7 @@ void PostedListWidgetWithModel::openComments(const RsGxsMessageId& msgId) ui->idChooser->getChosenId(current_author); RsPostedPost post = index.data(Qt::UserRole).value() ; - auto *commentDialog = new GxsCommentDialog(this,current_author,rsPosted->getTokenService(),rsPosted); + auto *commentDialog = new GxsCommentDialog(this,current_author,rsPosted); std::set msg_versions({post.mMeta.mMsgId}); commentDialog->commentLoad(post.mMeta.mGroupId, msg_versions, post.mMeta.mMsgId); @@ -884,6 +865,7 @@ void PostedListWidgetWithModel::insertBoardDetails(const RsPostedGroup& group) ui->subscribeToolButton->setText(tr("Subscribe")); ui->infoPosts->setText(QString::number(group.mMeta.mVisibleMsgCount)); + ui->poplabel->setText(QString::number(group.mMeta.mPop)); if(group.mMeta.mLastPost==0) ui->infoLastPost->setText(tr("Never")); @@ -923,7 +905,7 @@ void PostedListWidgetWithModel::insertBoardDetails(const RsPostedGroup& group) formatDescription = RsHtml().formatText(NULL, formatDescription, formatFlag); - ui->infoDescription->setText(formatDescription); + ui->trans_Description->setText(formatDescription); ui->infoAdministrator->setId(group.mMeta.mAuthorId) ; link = RetroShareLink::createMessage(group.mMeta.mAuthorId, ""); @@ -1181,8 +1163,7 @@ void PostedListWidgetWithModel::subscribeGroup(bool subscribe) RsThread::async([=]() { - uint32_t token; - rsPosted->subscribeToGroup(token,grpId, subscribe); + rsPosted->subscribeToBoard(grpId, subscribe); } ); } @@ -1195,51 +1176,13 @@ void PostedListWidgetWithModel::voteMsg(RsGxsGrpMsgIdPair msg,bool up_or_down) return; } - rsPosted->voteForPost(up_or_down,msg.first,msg.second,voter_id); + RsGxsVoteType tvote = up_or_down?(RsGxsVoteType::UP):(RsGxsVoteType::DOWN); + + std::string error_str; + RsGxsMessageId vote_id; + if(!rsPosted->voteForPost(msg.first,msg.second,voter_id,tvote,vote_id,error_str)) + QMessageBox::critical(nullptr,tr("Could not vote"), tr("Error occured while voting: ")+QString::fromStdString(error_str)); + else + updateDisplay(true); } -#ifdef TODO -class PostedPostsReadData -{ -public: - PostedPostsReadData(bool read) - { - mRead = read; - mLastToken = 0; - } - -public: - bool mRead; - uint32_t mLastToken; -}; - -static void setAllMessagesReadCallback(FeedItem *feedItem, void *data) -{ - GxsChannelPostItem *channelPostItem = dynamic_cast(feedItem); - if (!channelPostItem) { - return; - } - - GxsChannelPostsReadData *readData = (GxsChannelPostsReadData*) data; - bool isRead = !channelPostItem->isUnread() ; - - if(channelPostItem->isLoaded() && (isRead == readData->mRead)) - return ; - - RsGxsGrpMsgIdPair msgPair = std::make_pair(channelPostItem->groupId(), channelPostItem->messageId()); - rsGxsChannels->setMessageReadStatus(readData->mLastToken, msgPair, readData->mRead); -} - -void PostedListWidgetWithModel::setAllMessagesReadDo(bool read, uint32_t &token) -{ - if (groupId().isNull() || !IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags)) { - return; - } - - GxsChannelPostsReadData data(read); - //ui->feedWidget->withAll(setAllMessagesReadCallback, &data); - - token = data.mLastToken; -} - -#endif diff --git a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.h b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.h index a38e0d036..cb7dcfd39 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.h +++ b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.h @@ -130,12 +130,13 @@ protected: #endif /* GxsMessageFrameWidget */ - virtual void setAllMessagesReadDo(bool read, uint32_t &token) override; + virtual void setAllMessagesReadDo(bool read) override; private slots: #ifdef TO_REMOVE void showPostDetails(); #endif + void postContextMenu(const QPoint&); void showAuthorInPeople(); void tabCloseRequested(int index); void updateSorting(int); @@ -145,8 +146,8 @@ private slots: void subscribeGroup(bool subscribe); void settingsChanged(); void postPostLoad(); - void postContextMenu(const QPoint&); void copyMessageLink(); + void copyHttpLink(); void nextPosts(); void prevPosts(); void filterItems(QString s); diff --git a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui index ccba99f67..734c4a233 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui +++ b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui @@ -46,7 +46,7 @@
- + @@ -54,7 +54,7 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'.AppleSystemUIFont'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Description</span></p></body></html>
@@ -84,8 +84,11 @@ p, li { white-space: pre-wrap; } true
+ + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + - Contributions: + Items (at friends): @@ -179,6 +182,9 @@ p, li { white-space: pre-wrap; } true
+ + Number of subscribed friend nodes + Popularity: @@ -251,7 +257,7 @@ p, li { white-space: pre-wrap; } Qt::Vertical - QSizePolicy::Preferred + QSizePolicy::Expanding @@ -271,9 +277,10 @@ p, li { white-space: pre-wrap; } - 50 + 15 + 75 false - false + true @@ -300,7 +307,7 @@ p, li { white-space: pre-wrap; } - + 0 @@ -309,7 +316,9 @@ p, li { white-space: pre-wrap; } + 25 75 + true true @@ -344,12 +353,12 @@ p, li { white-space: pre-wrap; } - + - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -372,6 +381,12 @@ p, li { white-space: pre-wrap; } 0 + + + 75 + true + + Create Post @@ -394,7 +409,13 @@ p, li { white-space: pre-wrap; } - + + + + 75 + true + + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -439,22 +460,6 @@ p, li { white-space: pre-wrap; } - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 40 - 20 - - - - @@ -574,17 +579,7 @@ p, li { white-space: pre-wrap; } LineEditClear QLineEdit -
gui/common/LineEditClear.h
-
- - SubscribeToolButton - QToolButton -
gui/common/SubscribeToolButton.h
-
- - GxsIdLabel - QLabel -
gui/gxs/GxsIdLabel.h
+
gui/common/LineEditClear.h
RSTreeView @@ -593,9 +588,30 @@ p, li { white-space: pre-wrap; } 1 - StyledElidedLabel + GxsIdLabel QLabel -
gui/common/StyledElidedLabel.h
+
gui/gxs/GxsIdLabel.h
+
+ + ElidedLabel + QLabel +
gui/common/ElidedLabel.h
+ 1 +
+ + SubscribeToolButton + QToolButton +
gui/common/SubscribeToolButton.h
+
+ + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
+ + GxsIdChooser + QComboBox +
gui/gxs/GxsIdChooser.h
RSTabWidget @@ -603,11 +619,6 @@ p, li { white-space: pre-wrap; }
gui/common/RSTabWidget.h
1
- - GxsIdChooser - QComboBox -
gui/gxs/GxsIdChooser.h
-
diff --git a/retroshare-gui/src/gui/QuickStartWizard.cpp b/retroshare-gui/src/gui/QuickStartWizard.cpp index f442d2f1b..ce953a32e 100644 --- a/retroshare-gui/src/gui/QuickStartWizard.cpp +++ b/retroshare-gui/src/gui/QuickStartWizard.cpp @@ -20,27 +20,30 @@ #include "QuickStartWizard.h" -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include +#include "gui/common/FilesDefs.h" +#ifdef USE_COMBOBOX +#include "gui/common/RSComboBox.h" +#endif #include "settings/rsharesettings.h" #include "util/QtVersion.h" -#include "gui/common/FilesDefs.h" + +#include "retroshare/rsfiles.h" +#include "retroshare/rsconfig.h" +#include "retroshare/rspeers.h" +#include "retroshare/rstypes.h" + +#include +#include +#include +#include +#include QuickStartWizard::QuickStartWizard(QWidget *parent) : QDialog(parent) { ui.setupUi(this); - ui.headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/images/rs_wizard.png")); + ui.headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/images/tools_wizard.png")); ui.headerFrame->setHeaderText("RetroShare"); ui.pagesWizard->setCurrentIndex(0); @@ -53,7 +56,7 @@ QuickStartWizard::QuickStartWizard(QWidget *parent) : // ui.checkBoxF2FRouting->setChecked(true) ; // ui.checkBoxF2FRouting->setEnabled(false) ; - connect( ui.netModeComboBox, SIGNAL( activated ( int ) ), this, SLOT( toggleUPnP( ) ) ); + connect( ui.netModeComboBox, SIGNAL( activated(int) ), this, SLOT( toggleUPnP() ) ); // connect( ui.checkBoxTunnelConnection, SIGNAL( toggled( bool ) ), this, SLOT( toggleTunnelConnection(bool) ) ); // bool b = rsPeers->getAllowTunnelConnection() ; @@ -299,7 +302,7 @@ void QuickStartWizard::loadShare() listWidget->insertRow(row) ; listWidget->setItem(row,0,new QTableWidgetItem(QString::fromStdString((*it).filename))); #ifdef USE_COMBOBOX - QComboBox *cb = new QComboBox ; + RSComboBox *cb = new RSComboBox ; cb->addItem(tr("Network Wide")) ; cb->addItem(tr("Browsable")) ; cb->addItem(tr("Universal")) ; @@ -494,7 +497,6 @@ void QuickStartWizard::loadNetwork() void QuickStartWizard::saveChanges() { - QString str; //bool saveAddr = false; diff --git a/retroshare-gui/src/gui/QuickStartWizard.ui b/retroshare-gui/src/gui/QuickStartWizard.ui index ede111c52..fc8832637 100644 --- a/retroshare-gui/src/gui/QuickStartWizard.ui +++ b/retroshare-gui/src/gui/QuickStartWizard.ui @@ -334,7 +334,7 @@ p, li { white-space: pre-wrap; }
- + Automatic (UPnP) @@ -360,7 +360,7 @@ p, li { white-space: pre-wrap; } - + Public: DHT & Discovery @@ -1072,6 +1072,11 @@ p, li { white-space: pre-wrap; }
gui/common/HeaderFrame.h
1 + + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
diff --git a/retroshare-gui/src/gui/RSHumanReadableDelegate.h b/retroshare-gui/src/gui/RSHumanReadableDelegate.h index 3e9a3e412..1b3995cd7 100644 --- a/retroshare-gui/src/gui/RSHumanReadableDelegate.h +++ b/retroshare-gui/src/gui/RSHumanReadableDelegate.h @@ -88,10 +88,16 @@ class RSHumanReadableAgeDelegate: public RSHumanReadableDelegate public: virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const { + painter->save(); QStyleOptionViewItem opt(option) ; setPainterOptions(painter,opt,index) ; - painter->drawText(opt.rect, Qt::AlignCenter, misc::timeRelativeToNow(index.data().toLongLong())) ; + if(index.data().toLongLong() > 0) { // no date is present. + painter->setFont(opt.font); + painter->drawText(opt.rect, opt.displayAlignment, misc::timeRelativeToNow(index.data().toLongLong())) ; + } + + painter->restore(); } }; @@ -100,10 +106,14 @@ class RSHumanReadableSizeDelegate: public RSHumanReadableDelegate public: virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const { + painter->save(); QStyleOptionViewItem opt(option) ; setPainterOptions(painter,opt,index) ; - painter->drawText(opt.rect, Qt::AlignRight, misc::friendlyUnit(index.data().toULongLong())); + painter->setFont(opt.font); + painter->drawText(opt.rect, opt.displayAlignment, misc::friendlyUnit(index.data().toULongLong())); + + painter->restore(); } }; diff --git a/retroshare-gui/src/gui/RemoteDirModel.cpp b/retroshare-gui/src/gui/RemoteDirModel.cpp index 0cfcc9772..962001a76 100644 --- a/retroshare-gui/src/gui/RemoteDirModel.cpp +++ b/retroshare-gui/src/gui/RemoteDirModel.cpp @@ -24,7 +24,7 @@ #include "gui/common/FilesDefs.h" #include "gui/common/GroupDefs.h" -#include "gui/common/RsCollection.h" +#include "gui/common/RsCollectionDialog.h" #include "gui/common/RsUrlHandler.h" #include "gui/gxs/GxsIdDetails.h" #include "retroshare/rsfiles.h" @@ -48,6 +48,15 @@ * #define RDM_SEARCH_DEBUG ****/ +#define REMOTEDIRMODEL_COLUMN_NAME 0 +#define REMOTEDIRMODEL_COLUMN_FILENB 1 +#define REMOTEDIRMODEL_COLUMN_SIZE 2 +#define REMOTEDIRMODEL_COLUMN_AGE 3 +#define REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS 4 +#define REMOTEDIRMODEL_COLUMN_WN_VISU_DIR 5 +#define REMOTEDIRMODEL_COLUMN_COUNT 6 +#define RETROSHARE_DIR_MODEL_FILTER_STRING "filtered" + static const uint32_t FLAT_VIEW_MAX_REFS_PER_SECOND = 2000 ; static const size_t FLAT_VIEW_MAX_REFS_TABLE_SIZE = 10000 ; // static const uint32_t FLAT_VIEW_MIN_DELAY_BETWEEN_UPDATES = 120 ; // dont rebuild ref list more than every 2 mins. @@ -136,7 +145,7 @@ void RetroshareDirModel::treeStyle() { categoryIcon.addPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/folder.png"), QIcon::Normal, QIcon::Off); categoryIcon.addPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/folderopen.png"), QIcon::Normal, QIcon::On); - peerIcon = FilesDefs::getIconFromQtResourcePath(":/images/user/identity16.png"); + peerIcon = FilesDefs::getIconFromQtResourcePath(":/icons/folder-account.svg"); } void TreeStyle_RDM::update() { @@ -295,11 +304,11 @@ int FlatStyle_RDM::rowCount(const QModelIndex &parent) const int TreeStyle_RDM::columnCount(const QModelIndex &/*parent*/) const { - return COLUMN_COUNT; + return REMOTEDIRMODEL_COLUMN_COUNT; } int FlatStyle_RDM::columnCount(const QModelIndex &/*parent*/) const { - return COLUMN_COUNT; + return REMOTEDIRMODEL_COLUMN_COUNT; } QString RetroshareDirModel::getFlagsString(FileStorageFlags flags) @@ -416,7 +425,7 @@ QVariant RetroshareDirModel::filterRole(const DirDetails& details, int /*coln*/) QVariant RetroshareDirModel::decorationRole(const DirDetails& details,int coln) const { - if(coln == COLUMN_FRIEND_ACCESS) + if(coln == REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS) { if(details.type == DIR_TYPE_PERSON) return QVariant() ; @@ -484,7 +493,7 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details,int coln) const { switch(coln) { - case COLUMN_NAME: { + case REMOTEDIRMODEL_COLUMN_NAME: { //SharedDirStats stats ; QString res ; @@ -497,7 +506,7 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details,int coln) const return res ; } - case COLUMN_FILENB: { + case REMOTEDIRMODEL_COLUMN_FILENB: { SharedDirStats stats ; if(RemoteMode) @@ -516,7 +525,7 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details,int coln) const } return tr("Empty"); } - case COLUMN_SIZE: { + case REMOTEDIRMODEL_COLUMN_SIZE: { SharedDirStats stats ; if(RemoteMode) @@ -531,7 +540,7 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details,int coln) const return QString(); } - case COLUMN_AGE: + case REMOTEDIRMODEL_COLUMN_AGE: if(!isNewerThanEpoque(details.max_mtime)) return QString(); else if(details.id != rsPeers->getOwnId()) @@ -547,13 +556,13 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details,int coln) const { switch(coln) { - case COLUMN_NAME: + case REMOTEDIRMODEL_COLUMN_NAME: return QString::fromUtf8(details.name.c_str()); - case COLUMN_FILENB: + case REMOTEDIRMODEL_COLUMN_FILENB: return QVariant(); - case COLUMN_SIZE: + case REMOTEDIRMODEL_COLUMN_SIZE: return misc::friendlyUnit(details.size); - case COLUMN_AGE: + case REMOTEDIRMODEL_COLUMN_AGE: { if(details.type == DIR_TYPE_FILE) return misc::timeRelativeToNow(details.max_mtime); @@ -567,9 +576,9 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details,int coln) const else return QString(); } - case COLUMN_FRIEND_ACCESS: + case REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS: return QVariant(); - case COLUMN_WN_VISU_DIR: + case REMOTEDIRMODEL_COLUMN_WN_VISU_DIR: return getGroupsString(details.flags,details.parent_groups) ; default: @@ -580,22 +589,22 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details,int coln) const { switch(coln) { - case COLUMN_NAME: + case REMOTEDIRMODEL_COLUMN_NAME: return QString::fromUtf8(details.name.c_str()); break; - case COLUMN_FILENB: + case REMOTEDIRMODEL_COLUMN_FILENB: if (details.children.size() > 1) { return QString::number(details.children.size()) + " " + tr("Files"); } return QString::number(details.children.size()) + " " + tr("File"); - case COLUMN_SIZE: + case REMOTEDIRMODEL_COLUMN_SIZE: return misc::friendlyUnit(details.size); - case COLUMN_AGE: + case REMOTEDIRMODEL_COLUMN_AGE: return misc::timeRelativeToNow(details.max_mtime); - case COLUMN_FRIEND_ACCESS: + case REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS: return QVariant(); - case COLUMN_WN_VISU_DIR: + case REMOTEDIRMODEL_COLUMN_WN_VISU_DIR: return getGroupsString(details.flags,details.parent_groups) ; default: @@ -650,12 +659,12 @@ QVariant FlatStyle_RDM::displayRole(const DirDetails& details,int coln) const if (details.type == DIR_TYPE_FILE || details.type == DIR_TYPE_EXTRA_FILE) /* File */ switch(coln) { - case COLUMN_NAME: return QString::fromUtf8(details.name.c_str()); - case COLUMN_FILENB: return QString(); - case COLUMN_SIZE: return misc::friendlyUnit(details.size); - case COLUMN_AGE: return misc::timeRelativeToNow(details.max_mtime); - case COLUMN_FRIEND_ACCESS: return QString::fromUtf8(rsPeers->getPeerName(details.id).c_str()); - case COLUMN_WN_VISU_DIR: return computeDirectoryPath(details); + case REMOTEDIRMODEL_COLUMN_NAME: return QString::fromUtf8(details.name.c_str()); + case REMOTEDIRMODEL_COLUMN_FILENB: return QString(); + case REMOTEDIRMODEL_COLUMN_SIZE: return misc::friendlyUnit(details.size); + case REMOTEDIRMODEL_COLUMN_AGE: return misc::timeRelativeToNow(details.max_mtime); + case REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS: return QString::fromUtf8(rsPeers->getPeerName(details.id).c_str()); + case REMOTEDIRMODEL_COLUMN_WN_VISU_DIR: return computeDirectoryPath(details); default: return QVariant() ; } @@ -675,9 +684,9 @@ QVariant TreeStyle_RDM::sortRole(const QModelIndex& /*index*/,const DirDetails& { switch(coln) { - case COLUMN_NAME: + case REMOTEDIRMODEL_COLUMN_NAME: return (RemoteMode)?(QString::fromUtf8(rsPeers->getPeerName(details.id).c_str())):tr("My files"); - case COLUMN_FILENB: { + case REMOTEDIRMODEL_COLUMN_FILENB: { SharedDirStats stats ; if(RemoteMode) @@ -687,7 +696,7 @@ QVariant TreeStyle_RDM::sortRole(const QModelIndex& /*index*/,const DirDetails& return (qulonglong) stats.total_number_of_files; } - case COLUMN_SIZE: { + case REMOTEDIRMODEL_COLUMN_SIZE: { SharedDirStats stats ; if(RemoteMode) @@ -697,7 +706,7 @@ QVariant TreeStyle_RDM::sortRole(const QModelIndex& /*index*/,const DirDetails& return (qulonglong) stats.total_shared_size; } - case COLUMN_AGE: + case REMOTEDIRMODEL_COLUMN_AGE: return details.max_mtime; default: return QString(); @@ -707,17 +716,17 @@ QVariant TreeStyle_RDM::sortRole(const QModelIndex& /*index*/,const DirDetails& { switch(coln) { - case COLUMN_NAME: + case REMOTEDIRMODEL_COLUMN_NAME: return QString::fromUtf8(details.name.c_str()); - case COLUMN_FILENB: + case REMOTEDIRMODEL_COLUMN_FILENB: return (qulonglong) 0; - case COLUMN_SIZE: + case REMOTEDIRMODEL_COLUMN_SIZE: return (qulonglong) details.size; - case COLUMN_AGE: + case REMOTEDIRMODEL_COLUMN_AGE: return details.max_mtime; - case COLUMN_FRIEND_ACCESS: + case REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS: return getFlagsString(details.flags); - case COLUMN_WN_VISU_DIR: + case REMOTEDIRMODEL_COLUMN_WN_VISU_DIR: { QString ind(""); if (ageIndicator != IND_ALWAYS) @@ -732,15 +741,15 @@ QVariant TreeStyle_RDM::sortRole(const QModelIndex& /*index*/,const DirDetails& { switch(coln) { - case COLUMN_NAME: + case REMOTEDIRMODEL_COLUMN_NAME: return QString::fromUtf8(details.name.c_str()); - case COLUMN_FILENB: + case REMOTEDIRMODEL_COLUMN_FILENB: return (qulonglong) details.children.size(); - case COLUMN_SIZE: + case REMOTEDIRMODEL_COLUMN_SIZE: return (qulonglong) 0; - case COLUMN_AGE: + case REMOTEDIRMODEL_COLUMN_AGE: return details.max_mtime; - case COLUMN_FRIEND_ACCESS: + case REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS: return getFlagsString(details.flags); default: return tr("DIR"); @@ -760,12 +769,12 @@ QVariant FlatStyle_RDM::sortRole(const QModelIndex& /*index*/,const DirDetails& { switch(coln) { - case COLUMN_NAME: return QString::fromUtf8(details.name.c_str()); - case COLUMN_FILENB: return (qulonglong) 0; - case COLUMN_SIZE: return (qulonglong) details.size; - case COLUMN_AGE: return details.max_mtime; - case COLUMN_FRIEND_ACCESS: return QString::fromUtf8(rsPeers->getPeerName(details.id).c_str()); - case COLUMN_WN_VISU_DIR: { + case REMOTEDIRMODEL_COLUMN_NAME: return QString::fromUtf8(details.name.c_str()); + case REMOTEDIRMODEL_COLUMN_FILENB: return (qulonglong) 0; + case REMOTEDIRMODEL_COLUMN_SIZE: return (qulonglong) details.size; + case REMOTEDIRMODEL_COLUMN_AGE: return details.max_mtime; + case REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS: return QString::fromUtf8(rsPeers->getPeerName(details.id).c_str()); + case REMOTEDIRMODEL_COLUMN_WN_VISU_DIR: { RS_STACK_MUTEX(_ref_mutex) ; return computeDirectoryPath(details); @@ -793,7 +802,7 @@ QVariant RetroshareDirModel::data(const QModelIndex &index, int role) const if (role == Qt::TextAlignmentRole) { - if((coln == COLUMN_FILENB) || (coln == COLUMN_SIZE)) + if((coln == REMOTEDIRMODEL_COLUMN_FILENB) || (coln == REMOTEDIRMODEL_COLUMN_SIZE)) return int( Qt::AlignRight | Qt::AlignVCenter); else return QVariant(); @@ -895,7 +904,7 @@ QVariant TreeStyle_RDM::headerData(int section, Qt::Orientation orientation, int int defw = QFontMetricsF(QWidget().font()).width(headerData(section,Qt::Horizontal,Qt::DisplayRole).toString()) ; int defh = QFontMetricsF(QWidget().font()).height(); - if (section < COLUMN_AGE) + if (section < REMOTEDIRMODEL_COLUMN_AGE) { defw = 200/16.0*defh; } @@ -909,7 +918,7 @@ QVariant TreeStyle_RDM::headerData(int section, Qt::Orientation orientation, int { switch(section) { - case COLUMN_NAME: + case REMOTEDIRMODEL_COLUMN_NAME: if (RemoteMode) if(mUpdating) return tr("Friends Directories [updating...]"); @@ -920,18 +929,18 @@ QVariant TreeStyle_RDM::headerData(int section, Qt::Orientation orientation, int return tr("My Directories [updating...]"); else return tr("My Directories"); - case COLUMN_FILENB: + case REMOTEDIRMODEL_COLUMN_FILENB: return tr("# Files"); - case COLUMN_SIZE: + case REMOTEDIRMODEL_COLUMN_SIZE: return tr("Size"); - case COLUMN_AGE: + case REMOTEDIRMODEL_COLUMN_AGE: return tr("Age"); - case COLUMN_FRIEND_ACCESS: + case REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS: if (RemoteMode) return tr("Friend"); else return tr("Access"); - case COLUMN_WN_VISU_DIR: + case REMOTEDIRMODEL_COLUMN_WN_VISU_DIR: if (RemoteMode) return tr("What's new"); else @@ -949,7 +958,7 @@ QVariant FlatStyle_RDM::headerData(int section, Qt::Orientation orientation, int int defw = QFontMetricsF(QWidget().font()).width(headerData(section,Qt::Horizontal,Qt::DisplayRole).toString()) ; int defh = QFontMetricsF(QWidget().font()).height(); - if (section < COLUMN_AGE) + if (section < REMOTEDIRMODEL_COLUMN_AGE) { defw = defh*200/16.0; } @@ -963,24 +972,24 @@ QVariant FlatStyle_RDM::headerData(int section, Qt::Orientation orientation, int { switch(section) { - case COLUMN_NAME: + case REMOTEDIRMODEL_COLUMN_NAME: if (RemoteMode) { return tr("Friends Directories"); } return tr("My Directories"); - case COLUMN_FILENB: + case REMOTEDIRMODEL_COLUMN_FILENB: return tr("# Files"); - case COLUMN_SIZE: + case REMOTEDIRMODEL_COLUMN_SIZE: return tr("Size"); - case COLUMN_AGE: + case REMOTEDIRMODEL_COLUMN_AGE: return tr("Age"); - case COLUMN_FRIEND_ACCESS: + case REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS: if(RemoteMode) return tr("Friend"); else return tr("Share Flags"); - case COLUMN_WN_VISU_DIR: + case REMOTEDIRMODEL_COLUMN_WN_VISU_DIR: return tr("Directory"); } return tr("Column %1").arg(section); @@ -1096,7 +1105,7 @@ QModelIndex TreeStyle_RDM::parent( const QModelIndex & index ) const std::cerr << "Creating index 3 row=" << details.prow << ", column=" << 0 << ", ref=" << (void*)details.parent << std::endl; #endif - return createIndex(details.prow, COLUMN_NAME, details.parent); + return createIndex(details.prow, REMOTEDIRMODEL_COLUMN_NAME, details.parent); } QModelIndex FlatStyle_RDM::parent( const QModelIndex & index ) const { @@ -1167,7 +1176,7 @@ void RetroshareDirModel::postMods() endResetModel(); - emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(rowCount()-1,COLUMN_COUNT-1,(void*)NULL)); + emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(rowCount()-1,REMOTEDIRMODEL_COLUMN_COUNT-1,(void*)NULL)); } void FlatStyle_RDM::postMods() @@ -1224,31 +1233,6 @@ bool RetroshareDirModel::requestDirDetails(void *ref, bool remote,DirDetails& d) return false ; } -void RetroshareDirModel::createCollectionFile(QWidget *parent, const QModelIndexList &list) -{ -/* if(RemoteMode) - { - std::cerr << "Cannot create a collection file from remote" << std::endl; - return ; - }*/ - - std::vector dirVec; - getDirDetailsFromSelect(list, dirVec); - - FileSearchFlags f = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ; - - QString dir_name; - if(!RemoteMode) - { - if(!dirVec.empty()) - { - const DirDetails& details = dirVec[0]; - dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName(); - } - } - RsCollection(dirVec,f).openNewColl(parent,dir_name); -} - void RetroshareDirModel::downloadSelected(const QModelIndexList &list,bool interactive) { if (!RemoteMode) @@ -1269,7 +1253,7 @@ void RetroshareDirModel::downloadSelected(const QModelIndexList &list,bool inter FileSearchFlags f = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ; if(interactive) - RsCollection(dirVec,f).downloadFiles() ; + RsCollectionDialog::downloadFiles(RsCollection(dirVec,f)) ; else /* Fire off requests */ for (int i = 0, n = dirVec.size(); i < n; ++i) { @@ -1340,7 +1324,7 @@ void RetroshareDirModel::getDirDetailsFromSelect (const QModelIndexList &list, s QModelIndexList::const_iterator it; for(it = list.begin(); it != list.end(); ++it) { - if(it->column()==COLUMN_FILENB) + if(it->column()==REMOTEDIRMODEL_COLUMN_FILENB) { void *ref = it -> internalPointer(); @@ -1377,7 +1361,7 @@ void RetroshareDirModel::getFileInfoFromIndexList(const QModelIndexList& list, s std::set already_in ; for(QModelIndexList::const_iterator it(list.begin()); it != list.end(); ++it) - if(it->column()==COLUMN_NAME) + if(it->column()==REMOTEDIRMODEL_COLUMN_NAME) { void *ref = it -> internalPointer(); @@ -1458,7 +1442,7 @@ void RetroshareDirModel::openSelected(const QModelIndexList &qmil, bool openDir) void RetroshareDirModel::getFilePath(const QModelIndex& index, std::string& fullpath) { - void *ref = index.sibling(index.row(),COLUMN_FILENB).internalPointer(); + void *ref = index.sibling(index.row(),REMOTEDIRMODEL_COLUMN_FILENB).internalPointer(); DirDetails details ; diff --git a/retroshare-gui/src/gui/RemoteDirModel.h b/retroshare-gui/src/gui/RemoteDirModel.h index 9d94abf32..b7811533e 100644 --- a/retroshare-gui/src/gui/RemoteDirModel.h +++ b/retroshare-gui/src/gui/RemoteDirModel.h @@ -32,15 +32,6 @@ #include #include -#define COLUMN_NAME 0 -#define COLUMN_FILENB 1 -#define COLUMN_SIZE 2 -#define COLUMN_AGE 3 -#define COLUMN_FRIEND_ACCESS 4 -#define COLUMN_WN_VISU_DIR 5 -#define COLUMN_COUNT 6 -#define RETROSHARE_DIR_MODEL_FILTER_STRING "filtered" - struct DirDetails; class DirDetailsVector : public DirDetails @@ -77,8 +68,6 @@ class RetroshareDirModel : public QAbstractItemModel /* Callback from GUI */ void downloadSelected(const QModelIndexList &list, bool interactive); - void createCollectionFile(QWidget *parent, const QModelIndexList &list); - void getDirDetailsFromSelect (const QModelIndexList &list, std::vector & dirVec); int getType ( const QModelIndex & index ) const ; diff --git a/retroshare-gui/src/gui/RetroShareLink.cpp b/retroshare-gui/src/gui/RetroShareLink.cpp index d34871104..0001cd9bc 100644 --- a/retroshare-gui/src/gui/RetroShareLink.cpp +++ b/retroshare-gui/src/gui/RetroShareLink.cpp @@ -22,9 +22,10 @@ #include "ChatLobbyWidget.h" #include "MainWindow.h" +#include "HomePage.h" #include "chat/ChatDialog.h" #include "common/PeerDefs.h" -#include "common/RsCollection.h" +#include "common/RsCollectionDialog.h" #include "common/RsUrlHandler.h" #include "connect/ConfCertDialog.h" #include "connect/ConnectFriendWizard.h" @@ -551,32 +552,45 @@ RetroShareLink RetroShareLink::createMessage(const RsGxsId& peerId, const QStrin RetroShareLink RetroShareLink::createCertificate(const RsPeerId& ssl_id) { - RetroShareLink link; - link.clear(); + RetroShareLink link; + link.clear(); #ifndef RS_NO_WARN_CPP #pragma message("csoler 2012-08-14: This is baaaaaad code") #endif - // - we should not need to parse and re-read a cert in old format. - // - RsPeerDetails detail; - if (rsPeers->getPeerDetails(ssl_id, detail) == false) { - std::cerr << "RetroShareLink::createPerson() Couldn't find peer id " << ssl_id << std::endl; - } else { + // - we should not need to parse and re-read a cert in old format. + // + RsPeerDetails detail; + if (rsPeers->getPeerDetails(ssl_id, detail) == false) + std::cerr << "RetroShareLink::createPerson() Couldn't find peer id " << ssl_id << std::endl; + else + { + link._type = TYPE_CERTIFICATE; - link._type = TYPE_CERTIFICATE; - link._radix = QString::fromUtf8(rsPeers->GetRetroshareInvite(ssl_id).c_str()); - link._name = QString::fromUtf8(detail.name.c_str()); - link._location = QString::fromUtf8(detail.location.c_str()); - link._radix.replace("\n",""); + if(rsPeers->getOwnId() == ssl_id) // in this case, use application-wide parameters set in HomePage + { + QString description; + auto invite_flags = static_cast(MainWindow::getPage(MainWindow::Home))->currentInviteFlags(); - std::cerr << "Found radix = " << link._radix.toStdString() << std::endl; - } + invite_flags &= ~RetroshareInviteFlags::SLICE_TO_80_CHARS; + invite_flags |= RetroshareInviteFlags::RADIX_FORMAT; - link.check(); + link._radix = QString::fromUtf8(rsPeers->GetRetroshareInvite(ssl_id,invite_flags).c_str()); + } + else + link._radix = QString::fromUtf8(rsPeers->GetRetroshareInvite(ssl_id).c_str()); - return link; + link._name = QString::fromUtf8(detail.name.c_str()); + link._location = QString::fromUtf8(detail.location.c_str()); + link._radix.replace("\n",""); + + std::cerr << "Found radix = " << link._radix.toStdString() << std::endl; + } + + link.check(); + + return link; } RetroShareLink RetroShareLink::createUnknownSslCertificate(const RsPeerId& sslId, const RsPgpId& gpgId) { @@ -1129,11 +1143,13 @@ QString RetroShareLink::toHtmlSize() const if (type() == TYPE_FILE && RsCollection::isCollectionFile(name())) { FileInfo finfo; - if (rsFiles->FileDetails(RsFileHash(hash().toStdString()), RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL, finfo)) { - RsCollection collection; - if (collection.load(QString::fromUtf8(finfo.path.c_str()), false)) { + if (rsFiles->FileDetails(RsFileHash(hash().toStdString()), RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL, finfo)) + { + RsCollection::RsCollectionErrorCode code; + RsCollection collection(QString::fromUtf8(finfo.path.c_str()), code) ; + + if(code == RsCollection::RsCollectionErrorCode::COLLECTION_NO_ERROR) size += QString(" [%1]").arg(misc::friendlyUnit(collection.size())); - } } } QString link = QString("
%2 %3").arg(toString()).arg(name()).arg(size); @@ -1708,10 +1724,9 @@ static void processList(const QStringList &list, const QString &textSingular, co case TYPE_FILE_TREE: { - auto ft = RsFileTree::fromRadix64( - link.radix().toStdString() ); - RsCollection(*ft).downloadFiles(); - break; + auto ft = RsFileTree::fromRadix64(link.radix().toStdString() ); + RsCollectionDialog::downloadFiles(RsCollection(*ft)); + break; } case TYPE_CHAT_ROOM: @@ -1762,7 +1777,7 @@ static void processList(const QStringList &list, const QString &textSingular, co // were single file links found? if (fileLinkFound) - col.downloadFiles(); + RsCollectionDialog::downloadFiles(col); int countProcessed = 0; int countError = 0; @@ -1905,7 +1920,9 @@ static void processList(const QStringList &list, const QString &textSingular, co void RSLinkClipboard::copyLinks(const QList& links) { QString res ; - for (int i = 0; i < links.size(); ++i) + if(links.size() == 1) + res += links[0].toString(); + else for(int i = 0; i < links.size(); ++i) res += links[i].toString() + "\n" ; QApplication::clipboard()->setText(res) ; @@ -2021,4 +2038,3 @@ void RSLinkClipboard::parseText(QString text, QList &links,Retro pos += rx.matchedLength(); } } - diff --git a/retroshare-gui/src/gui/ServicePermissionDialog.ui b/retroshare-gui/src/gui/ServicePermissionDialog.ui index 0acd51c75..7354fe9ae 100644 --- a/retroshare-gui/src/gui/ServicePermissionDialog.ui +++ b/retroshare-gui/src/gui/ServicePermissionDialog.ui @@ -16,8 +16,17 @@ true - - + + + 0 + + + 0 + + + 0 + + 0 @@ -37,14 +46,14 @@ - + QFrame::StyledPanel QFrame::Raised - + @@ -69,7 +78,7 @@ - frame + gradFrame headerFrame diff --git a/retroshare-gui/src/gui/ShareManager.cpp b/retroshare-gui/src/gui/ShareManager.cpp index 8f4e32542..6681e30c5 100644 --- a/retroshare-gui/src/gui/ShareManager.cpp +++ b/retroshare-gui/src/gui/ShareManager.cpp @@ -66,7 +66,7 @@ ShareManager::ShareManager() Settings->loadWidgetInformation(this); connect(ui.addButton, SIGNAL(clicked( bool ) ), this , SLOT( addShare() ) ); - connect(ui.closeButton, SIGNAL(clicked()), this, SLOT(applyAndClose())); + connect(ui.applyButton, SIGNAL(clicked()), this, SLOT(applyAndClose())); connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(cancel())); connect(ui.shareddirList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(shareddirListCustomPopupMenu(QPoint))); diff --git a/retroshare-gui/src/gui/ShareManager.ui b/retroshare-gui/src/gui/ShareManager.ui index e20074f9a..2799737c9 100644 --- a/retroshare-gui/src/gui/ShareManager.ui +++ b/retroshare-gui/src/gui/ShareManager.ui @@ -17,7 +17,7 @@ :/images/logo/logo_16.png:/images/logo/logo_16.png - + 0 @@ -47,14 +47,14 @@ - + QFrame::NoFrame QFrame::Raised - + 6 @@ -63,10 +63,7 @@ Shared Folder Manager - - - 2 - + @@ -97,7 +94,7 @@ false - 22 + 43 @@ -132,17 +129,12 @@ - - - 0 - 0 - - - - - 200 - 200 - + + + 12 + 75 + true + Add a Share Directory @@ -150,16 +142,10 @@ Add new - - - 24 - 24 - - - + Qt::Horizontal @@ -172,7 +158,14 @@ - + + + + 12 + 75 + true + + Apply and close @@ -186,10 +179,19 @@ - + + + + + 0 + 0 + 0 + + + @@ -210,6 +212,15 @@ + + + + 0 + 0 + 0 + + + @@ -230,6 +241,15 @@ + + + + 154 + 154 + 154 + + + @@ -251,6 +271,11 @@ + + + 12 + + true @@ -274,11 +299,6 @@ - - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
HeaderFrame QFrame diff --git a/retroshare-gui/src/gui/StartDialog.cpp b/retroshare-gui/src/gui/StartDialog.cpp index 4a07d43c8..237d1bb83 100644 --- a/retroshare-gui/src/gui/StartDialog.cpp +++ b/retroshare-gui/src/gui/StartDialog.cpp @@ -123,7 +123,7 @@ void StartDialog::loadPerson() rsNotify->cachePgpPassphrase(ui.password_input->text().toUtf8().constData()) ; rsNotify->setDisableAskPassword(true); - bool res = Rshare::loadCertificate(accountId, ui.autologin_checkbox->isChecked()) ; + bool res = RsApplication::loadCertificate(accountId, ui.autologin_checkbox->isChecked()) ; rsNotify->setDisableAskPassword(false); rsNotify->clearPgpPassphrase(); @@ -161,7 +161,7 @@ void StartDialog::notSecureWarning() QMessageBox::warning ( this, tr("Warning"), tr("The password to your SSL certificate (your node) will be stored encrypted in your Keychain. \n\n Your PGP passwd will not be stored.\n\nThis choice can be reverted in settings."), QMessageBox::Ok); #else // this handles all linux systems at once. - QMessageBox::warning ( this, tr("Warning"), tr("The password to your SSL certificate (your node) will be stored encrypted in your Gnome Keyring. \n\n Your PGP passwd will not be stored.\n\nThis choice can be reverted in settings."), QMessageBox::Ok); + QMessageBox::warning ( this, tr("Warning"), tr("The password to your SSL certificate (your node) will be stored encrypted in your desktop's keyring. \n\n Your PGP passwd will not be stored.\n\nThis choice can be reverted in settings."), QMessageBox::Ok); #endif #endif } diff --git a/retroshare-gui/src/gui/StartDialog.ui b/retroshare-gui/src/gui/StartDialog.ui index a49d51e9b..39287a797 100644 --- a/retroshare-gui/src/gui/StartDialog.ui +++ b/retroshare-gui/src/gui/StartDialog.ui @@ -252,7 +252,7 @@
- + @@ -298,6 +298,8 @@ 12 + 75 + true @@ -343,8 +345,8 @@ The current identities/locations will not be affected.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">New Profile/Node</span></a></p></body></html> +</style></head><body style=" font-family:'Sans'; font-size:13pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; text-decoration: underline; color:#366fe0;">New Profile/Node</span></a></p></body></html>
@@ -355,16 +357,21 @@ p, li { white-space: pre-wrap; } - - - - - LineEditClear QLineEdit
gui/common/LineEditClear.h
+ + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
+ + + + + diff --git a/retroshare-gui/src/gui/common/StyledLabel.cpp b/retroshare-gui/src/gui/TheWire/CustomFrame.cpp similarity index 67% rename from retroshare-gui/src/gui/common/StyledLabel.cpp rename to retroshare-gui/src/gui/TheWire/CustomFrame.cpp index 2eabc9852..4f1308df5 100644 --- a/retroshare-gui/src/gui/common/StyledLabel.cpp +++ b/retroshare-gui/src/gui/TheWire/CustomFrame.cpp @@ -1,49 +1,41 @@ -/******************************************************************************* - * gui/common/StyledLabel.cpp * - * * - * Copyright (c) 2014, RetroShare Team * - * * - * 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 . * - * * - *******************************************************************************/ - -#include - -#include "StyledLabel.h" - -/** Constructor */ -StyledLabel::StyledLabel(QWidget *parent) - : QLabel(parent) -{ -} - -StyledLabel::StyledLabel(const QString &text, QWidget *parent) - : QLabel(text, parent) -{ -} - -int StyledLabel::fontSizeFactor() -{ - return mFontSizeFactor; -} - -void StyledLabel::setFontSizeFactor(int factor) -{ - mFontSizeFactor = factor; - - QFont f = font(); - qreal fontSize = mFontSizeFactor * f.pointSizeF() / 100; - f.setPointSizeF(fontSize); - setFont(f); -} +/******************************************************************************* + * gui/TheWire/CustomFrame.cpp * + * * + * Copyright (c) 2012-2020 Robert Fernie * + * * + * 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 . * + * * + *******************************************************************************/ + +#include "CustomFrame.h" +#include + +// Constructor +CustomFrame::CustomFrame(QWidget *parent) : QFrame(parent) +{ + // Any initializations for this frame. +} + +// Overriding the inbuilt paint function +void CustomFrame::paintEvent(QPaintEvent *event) +{ + QFrame::paintEvent(event); + QPainter painter(this); + painter.drawPixmap(rect(), backgroundImage); +} + +// Function to set the member variable 'backgroundImage' +void CustomFrame::setPixmap(QPixmap pixmap){ + backgroundImage = pixmap; +} diff --git a/retroshare-gui/src/gui/common/StyledElidedLabel.h b/retroshare-gui/src/gui/TheWire/CustomFrame.h similarity index 70% rename from retroshare-gui/src/gui/common/StyledElidedLabel.h rename to retroshare-gui/src/gui/TheWire/CustomFrame.h index d6467ab1f..e75a6087a 100644 --- a/retroshare-gui/src/gui/common/StyledElidedLabel.h +++ b/retroshare-gui/src/gui/TheWire/CustomFrame.h @@ -1,42 +1,44 @@ -/******************************************************************************* - * gui/common/StyleElidedLabel.h * - * * - * Copyright (c) 2014, RetroShare Team * - * * - * 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 . * - * * - *******************************************************************************/ - -#ifndef _STYLEDELIDEDLABEL_H -#define _STYLEDELIDEDLABEL_H - -#include "ElidedLabel.h" - -class StyledElidedLabel : public ElidedLabel -{ - Q_OBJECT - Q_PROPERTY(int fontSizeFactor READ fontSizeFactor WRITE setFontSizeFactor) - -public: - StyledElidedLabel(QWidget *parent = NULL); - StyledElidedLabel(const QString &text, QWidget *parent = NULL); - - void setFontSizeFactor(int factor); - int fontSizeFactor() {return _lastFactor;} - -private: - int _lastFactor; -}; - -#endif +/******************************************************************************* + * gui/TheWire/CustomFrame.h * + * * + * Copyright (c) 2012-2020 Robert Fernie * + * * + * 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 . * + * * + *******************************************************************************/ + +#ifndef CUSTOMFRAMEH_H +#define CUSTOMFRAMEH_H + +#include +#include + +// This class is made to implement the background image in a Qframe or any widget + +class CustomFrame : public QFrame +{ + Q_OBJECT + +public: + explicit CustomFrame(QWidget *parent = nullptr); + void setPixmap(QPixmap pixmap); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + QPixmap backgroundImage; +}; + +#endif //CUSTOMFRAMEH_H diff --git a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp index ee9c562a2..d3b666a7e 100644 --- a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp @@ -24,6 +24,8 @@ #include "PulseReply.h" #include "gui/gxs/GxsIdDetails.h" #include "gui/common/FilesDefs.h" +#include "util/misc.h" +#include "util/qtthreadsutils.h" #include "PulseAddDialog.h" @@ -35,15 +37,32 @@ PulseAddDialog::PulseAddDialog(QWidget *parent) { ui.setupUi(this); - connect(ui.pushButton_Post, SIGNAL( clicked( void ) ), this, SLOT( postPulse( void ) ) ); + connect(ui.postButton, SIGNAL( clicked( void ) ), this, SLOT( postPulse( void ) ) ); connect(ui.pushButton_AddURL, SIGNAL( clicked( void ) ), this, SLOT( addURL( void ) ) ); connect(ui.pushButton_ClearDisplayAs, SIGNAL( clicked( void ) ), this, SLOT( clearDisplayAs( void ) ) ); connect(ui.pushButton_Cancel, SIGNAL( clicked( void ) ), this, SLOT( cancelPulse( void ) ) ); connect(ui.textEdit_Pulse, SIGNAL( textChanged( void ) ), this, SLOT( pulseTextChanged( void ) ) ); connect(ui.pushButton_picture, SIGNAL(clicked()), this, SLOT( toggle())); + connect(ui.pushButton_remove, SIGNAL(clicked()), this, SLOT( removePictures())); + + + // this connection is from browse push button to the slot function onBrowseButtonClicked() + connect(ui.pushButton_Browse, SIGNAL(clicked()), this, SLOT( onBrowseButtonClicked())); ui.pushButton_picture->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/photo.png"))); + ui.pushButton_Browse->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/add-image.png"))); + ui.pushButton_remove->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/mail/delete.png"))); + ui.frame_picture->hide(); + ui.pushButton_picture->hide(); + + // initially hiding the browse button as the attach image button is not pressed + //ui.frame_PictureBrowse->hide(); + + ui.label_image1->hide(); + ui.label_image2->hide(); + ui.label_image3->hide(); + ui.label_image4->hide(); setAcceptDrops(true); } @@ -80,11 +99,31 @@ void PulseAddDialog::setGroup(RsWireGroup &group) // set ReplyWith Group. void PulseAddDialog::setGroup(const RsGxsGroupId &grpId) { - /* fetch in the background */ - RsWireGroupSPtr pGroup; - rsWire->getWireGroup(grpId, pGroup); + if(grpId.isNull()){ + return; + } - setGroup(*pGroup); + RsThread::async([this,grpId](){ + + RsWireGroupSPtr pGroup; + if(!rsWire->getWireGroup(grpId,pGroup)) + { + std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve wire group info for wire id: " << grpId << std::endl; + return; + } + + RsQThreadUtils::postToObject( [pGroup,this]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete, note that + * Qt::QueuedConnection is important! + */ + + setGroup(*pGroup); + }, this ); + + }); } void PulseAddDialog::cleanup() @@ -98,10 +137,9 @@ void PulseAddDialog::cleanup() QLayout *layout = ui.widget_replyto->layout(); // completely delete layout and sublayouts QLayoutItem * item; - QWidget * widget; while ((item = layout->takeAt(0))) { - if ((widget = item->widget()) != 0) + if (QWidget *widget = item->widget()) { std::cerr << "PulseAddDialog::cleanup() removing widget"; std::cerr << std::endl; @@ -129,8 +167,8 @@ void PulseAddDialog::cleanup() ui.frame_URL->setEnabled(false); ui.frame_URL->hide(); - ui.pushButton_Post->setEnabled(false); - ui.pushButton_Post->setText(tr("Post")); + ui.postButton->setEnabled(false); + ui.postButton->setText(tr("Post")); ui.textEdit_Pulse->setPlaceholderText(tr("Whats happening?")); ui.frame_input->setVisible(true); ui.widget_sentiment->setVisible(true); @@ -154,8 +192,11 @@ void PulseAddDialog::cleanup() ui.label_image4->clear(); ui.label_image4->setText(tr("Drag and Drop Image")); - // Hide Drag & Drop Frame - ui.frame_picture->hide(); + // Hide Drag & Drop Frame and the browse frame + ui.frame_picture->hide(); + //ui.frame_PictureBrowse->hide(); + ui.pushButton_picture->hide(); + ui.pushButton_picture->setChecked(false); } @@ -163,18 +204,18 @@ void PulseAddDialog::pulseTextChanged() { std::string pulseText = ui.textEdit_Pulse->toPlainText().toStdString(); bool enable = (pulseText.size() > 0) && (pulseText.size() < PULSE_MAX_SIZE); - ui.pushButton_Post->setEnabled(enable); + ui.postButton->setEnabled(enable); } // Old Interface, deprecate / make internal. // TODO: Convert mReplyToPulse to be an SPtr, and remove &pulse parameter. -void PulseAddDialog::setReplyTo(RsWirePulse &pulse, RsWirePulseSPtr pPulse, std::string &groupName, uint32_t replyType) +void PulseAddDialog::setReplyTo(const RsWirePulse &pulse, RsWirePulseSPtr pPulse, std::string &/*groupName*/, uint32_t replyType) { mIsReply = true; mReplyToPulse = pulse; mReplyType = replyType; ui.frame_reply->setVisible(true); - ui.pushButton_picture->show(); + ui.pushButton_picture->hide(); ui.topheadshot->hide(); { @@ -191,22 +232,24 @@ void PulseAddDialog::setReplyTo(RsWirePulse &pulse, RsWirePulseSPtr pPulse, std: if (mReplyType & WIRE_PULSE_TYPE_REPLY) { - ui.pushButton_Post->setText(tr("Reply to Pulse")); + ui.postButton->setText(tr("Reply to Pulse")); ui.textEdit_Pulse->setPlaceholderText(tr("Pulse your reply")); } else { // cannot add msg for like / republish. - ui.pushButton_Post->setEnabled(true); + ui.postButton->setEnabled(true); ui.frame_input->setVisible(false); ui.widget_sentiment->setVisible(false); if (mReplyType & WIRE_PULSE_TYPE_REPUBLISH) { - ui.pushButton_Post->setText(tr("Republish Pulse")); + ui.postButton->setText(tr("Republish Pulse")); ui.pushButton_picture->hide(); + ui.pushButton_Browse->hide(); } else if (mReplyType & WIRE_PULSE_TYPE_LIKE) { - ui.pushButton_Post->setText(tr("Like Pulse")); + ui.postButton->setText(tr("Like Pulse")); ui.pushButton_picture->hide(); + ui.pushButton_Browse->hide(); } } @@ -214,30 +257,46 @@ void PulseAddDialog::setReplyTo(RsWirePulse &pulse, RsWirePulseSPtr pPulse, std: void PulseAddDialog::setReplyTo(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, uint32_t replyType) { + if(grpId.isNull()){ + return; + } /* fetch in the background */ - RsWireGroupSPtr pGroup; - if (!rsWire->getWireGroup(grpId, pGroup)) - { - std::cerr << "PulseAddDialog::setRplyTo() failed to fetch group"; - std::cerr << std::endl; - return; - } - RsWirePulseSPtr pPulse; - if (!rsWire->getWirePulse(grpId, msgId, pPulse)) - { - std::cerr << "PulseAddDialog::setRplyTo() failed to fetch pulse"; - std::cerr << std::endl; - return; - } + RsThread::async([this,grpId,msgId,replyType](){ - // update GroupPtr - // TODO - this should be handled in libretroshare if possible. - if (pPulse->mGroupPtr == NULL) { - pPulse->mGroupPtr = pGroup; - } + RsWireGroupSPtr pGroup; + RsWirePulseSPtr pPulse; + if(!rsWire->getWireGroup(grpId,pGroup)) + { + std::cerr << __PRETTY_FUNCTION__ << "PulseAddDialog::setRplyTo() failed to fetch group id: " << grpId << std::endl; + return; + } + + if (!rsWire->getWirePulse(grpId, msgId, pPulse)) + { + std::cerr << "PulseAddDialog::setRplyTo() failed to fetch pulse of group id: " << grpId << std::endl; + return; + } + + // update GroupPtr + // TODO - this should be handled in libretroshare if possible. + if (pPulse->mGroupPtr == NULL) { + pPulse->mGroupPtr = pGroup; + } + + RsQThreadUtils::postToObject( [pGroup,this,pPulse,replyType]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete, note that + * Qt::QueuedConnection is important! + */ + + setReplyTo(*pPulse, pPulse, pGroup->mMeta.mGroupName, replyType); + }, this ); + + }); - setReplyTo(*pPulse, pPulse, pGroup->mMeta.mGroupName, replyType); } void PulseAddDialog::addURL() @@ -287,26 +346,39 @@ void PulseAddDialog::postOriginalPulse() std::cerr << "PulseAddDialog::postOriginalPulse()"; std::cerr << std::endl; - RsWirePulseSPtr pPulse(new RsWirePulse()); + RsWirePulseSPtr pPulse(new RsWirePulse()); - pPulse->mSentiment = WIRE_PULSE_SENTIMENT_NO_SENTIMENT; - pPulse->mPulseText = ui.textEdit_Pulse->toPlainText().toStdString(); - // set images here too. - pPulse->mImage1 = mImage1; - pPulse->mImage2 = mImage2; - pPulse->mImage3 = mImage3; - pPulse->mImage4 = mImage4; + pPulse->mSentiment = WIRE_PULSE_SENTIMENT_NO_SENTIMENT; + pPulse->mPulseText = ui.textEdit_Pulse->toPlainText().toStdString(); + // set images here too. + pPulse->mImage1 = mImage1; + pPulse->mImage2 = mImage2; + pPulse->mImage3 = mImage3; + pPulse->mImage4 = mImage4; - // this should be in async thread, so doesn't block UI thread. - if (!rsWire->createOriginalPulse(mGroup.mMeta.mGroupId, pPulse)) - { - std::cerr << "PulseAddDialog::postOriginalPulse() FAILED"; - std::cerr << std::endl; - return; - } + RsThread::async([this,pPulse](){ + + if (!rsWire->createOriginalPulse(mGroup.mMeta.mGroupId, pPulse)) + { + std::cerr << "PulseAddDialog::postOriginalPulse() FAILED"; + std::cerr << std::endl; + return; + } + + RsQThreadUtils::postToObject( [this]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete, note that + * Qt::QueuedConnection is important! + */ + + clearDialog(); + hide(); + }, this ); + + }); - clearDialog(); - hide(); } uint32_t PulseAddDialog::toPulseSentiment(int index) @@ -336,15 +408,15 @@ void PulseAddDialog::postReplyPulse() std::cerr << "PulseAddDialog::postReplyPulse()"; std::cerr << std::endl; - RsWirePulseSPtr pPulse(new RsWirePulse()); + RsWirePulseSPtr pPulse(new RsWirePulse()); - pPulse->mSentiment = toPulseSentiment(ui.comboBox_sentiment->currentIndex()); - pPulse->mPulseText = ui.textEdit_Pulse->toPlainText().toStdString(); - // set images here too. - pPulse->mImage1 = mImage1; - pPulse->mImage2 = mImage2; - pPulse->mImage3 = mImage3; - pPulse->mImage4 = mImage4; + pPulse->mSentiment = toPulseSentiment(ui.comboBox_sentiment->currentIndex()); + pPulse->mPulseText = ui.textEdit_Pulse->toPlainText().toStdString(); + // set images here too. + pPulse->mImage1 = mImage1; + pPulse->mImage2 = mImage2; + pPulse->mImage3 = mImage3; + pPulse->mImage4 = mImage4; if (mReplyType & WIRE_PULSE_TYPE_REPUBLISH) { // Copy details from parent, and override @@ -358,20 +430,33 @@ void PulseAddDialog::postReplyPulse() pPulse->mImage4 = mReplyToPulse.mImage4; } - // this should be in async thread, so doesn't block UI thread. - if (!rsWire->createReplyPulse(mReplyToPulse.mMeta.mGroupId, - mReplyToPulse.mMeta.mOrigMsgId, - mGroup.mMeta.mGroupId, - mReplyType, - pPulse)) - { - std::cerr << "PulseAddDialog::postReplyPulse() FAILED"; - std::cerr << std::endl; - return; - } + RsThread::async([this, pPulse](){ + + if (!rsWire->createReplyPulse(mReplyToPulse.mMeta.mGroupId, + mReplyToPulse.mMeta.mOrigMsgId, + mGroup.mMeta.mGroupId, + mReplyType, + pPulse)) + { + std::cerr << "PulseAddDialog::postReplyPulse() FAILED"; + std::cerr << std::endl; + return; + } + + RsQThreadUtils::postToObject( [this]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete, note that + * Qt::QueuedConnection is important! + */ + + clearDialog(); + hide(); + }, this ); + + }); - clearDialog(); - hide(); } void PulseAddDialog::clearDialog() @@ -479,24 +564,29 @@ void PulseAddDialog::addImage(const QString &path) std::cerr << "PulseAddDialog::addImage() Installing in Image1"; std::cerr << std::endl; ui.label_image1->setPixmap(icon); + ui.label_image1->show(); + ui.frame_picture->show(); mImage1.copy((uint8_t *) ba.data(), ba.size()); std::cerr << "PulseAddDialog::addImage() Installing in Image1 Size: " << mImage1.mSize; std::cerr << std::endl; } else if (mImage2.empty()) { ui.label_image2->setPixmap(icon); + ui.label_image2->show(); mImage2.copy((uint8_t *) ba.data(), ba.size()); std::cerr << "PulseAddDialog::addImage() Installing in Image2 Size: " << mImage2.mSize; std::cerr << std::endl; } else if (mImage3.empty()) { ui.label_image3->setPixmap(icon); + ui.label_image3->show(); mImage3.copy((uint8_t *) ba.data(), ba.size()); std::cerr << "PulseAddDialog::addImage() Installing in Image3 Size: " << mImage3.mSize; std::cerr << std::endl; } else if (mImage4.empty()) { ui.label_image4->setPixmap(icon); + ui.label_image4->show(); mImage4.copy((uint8_t *) ba.data(), ba.size()); std::cerr << "PulseAddDialog::addImage() Installing in Image4 Size: " << mImage4.mSize; std::cerr << std::endl; @@ -511,12 +601,47 @@ void PulseAddDialog::toggle() { if (ui.pushButton_picture->isChecked()) { + // Show the input methods (drag and drop field and the browse button) ui.frame_picture->show(); + ui.pushButton_picture->setToolTip(tr("Hide Pictures")); } else { + // Hide the input methods (drag and drop field and the browse button) ui.frame_picture->hide(); + ui.pushButton_picture->setToolTip(tr("Add Pictures")); } } + +// Function to get the file dialog for the browse button +void PulseAddDialog::onBrowseButtonClicked() +{ + QString filePath; + misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Load Picture File"), "Pictures (*.png *.xpm *.jpg *.jpeg *.gif *.webp )", filePath); + if (!filePath.isEmpty()) { + //ui.lineEdit_FilePath->setText(filePath); + addImage(filePath); + } +} + +void PulseAddDialog::removePictures() +{ + + mImage1.clear(); + ui.label_image1->clear(); + mImage2.clear(); + ui.label_image2->clear(); + mImage3.clear(); + ui.label_image3->clear(); + mImage4.clear(); + ui.label_image4->clear(); + + ui.label_image1->hide(); + ui.label_image2->hide(); + ui.label_image3->hide(); + ui.label_image4->hide(); + + ui.frame_picture->hide(); +} diff --git a/retroshare-gui/src/gui/TheWire/PulseAddDialog.h b/retroshare-gui/src/gui/TheWire/PulseAddDialog.h index ab386df2e..b1e8eca47 100644 --- a/retroshare-gui/src/gui/TheWire/PulseAddDialog.h +++ b/retroshare-gui/src/gui/TheWire/PulseAddDialog.h @@ -53,11 +53,13 @@ private slots: void clearDialog(); void pulseTextChanged(); void toggle(); + void onBrowseButtonClicked(); + void removePictures(); private: // OLD VERSIONs, private now. void setGroup(RsWireGroup &group); - void setReplyTo(RsWirePulse &pulse, RsWirePulseSPtr pPulse, std::string &groupName, uint32_t replyType); + void setReplyTo(const RsWirePulse &pulse, RsWirePulseSPtr pPulse, std::string &groupName, uint32_t replyType); void postOriginalPulse(); void postReplyPulse(); diff --git a/retroshare-gui/src/gui/TheWire/PulseAddDialog.ui b/retroshare-gui/src/gui/TheWire/PulseAddDialog.ui index 1b8fb24cc..bdfda3cc5 100644 --- a/retroshare-gui/src/gui/TheWire/PulseAddDialog.ui +++ b/retroshare-gui/src/gui/TheWire/PulseAddDialog.ui @@ -6,22 +6,22 @@ 0 0 - 720 - 449 + 735 + 513 - - - 0 - + 6 - - + + 0 + + + 0 @@ -34,18 +34,15 @@ 16777215 - - QFrame::StyledPanel - - - QFrame::Raised - - + + + 0 + 0 - + 100 @@ -72,7 +69,7 @@ - + Qt::Horizontal @@ -86,6 +83,11 @@ + + + 12 + + GroupLabel @@ -116,15 +118,9 @@ - + - - QFrame::StyledPanel - - - QFrame::Raised - - + 0 @@ -142,9 +138,9 @@ - + - 20 + 9 0 @@ -175,7 +171,7 @@ - + Qt::Horizontal @@ -188,14 +184,14 @@ - + Response Sentiment: - + 0 @@ -236,18 +232,21 @@ - + - - QFrame::StyledPanel - - - QFrame::Raised - - + + + 0 + 0 + + 0 + + + 0 + @@ -263,10 +262,16 @@ + + + 0 + 0 + + 0 - 100 + 80 @@ -275,45 +280,13 @@ QFrame::Raised - - - - - - 80 - 80 - - - - Drag and Drop Image - - - Qt::AlignCenter - - - + - 80 - 80 - - - - Drag and Drop Image - - - Qt::AlignCenter - - - - - - - - 80 - 80 + 40 + 40 @@ -328,8 +301,8 @@ - 80 - 80 + 40 + 40 @@ -340,19 +313,60 @@ + + + + + 40 + 40 + + + + Drag and Drop Image + + + Qt::AlignCenter + + + + + + + + 40 + 40 + + + + Drag and Drop Image + + + Qt::AlignCenter + + + + + + + Remove all images + + + + + + + 24 + 24 + + + + - - - - - URL - - - + @@ -363,13 +377,6 @@ - - - - Display As - - - @@ -380,19 +387,36 @@ + + + + Display As + + + + + + + URL + + + + frame_URL + frame_picture + textEdit_Pulse - - + + 6 - + @@ -408,7 +432,23 @@ - + + + Add Picture + + + + + + + 24 + 24 + + + + + + Qt::Horizontal @@ -421,7 +461,14 @@ - + + + + 12 + 75 + true + + Post @@ -444,9 +491,12 @@ QLabel
gui/gxs/GxsIdLabel.h
+ + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
- - - + diff --git a/retroshare-gui/src/gui/TheWire/PulseMessage.cpp b/retroshare-gui/src/gui/TheWire/PulseMessage.cpp index 8f4a91873..34724282f 100644 --- a/retroshare-gui/src/gui/TheWire/PulseMessage.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseMessage.cpp @@ -29,10 +29,10 @@ PulseMessage::PulseMessage(QWidget *parent) { setupUi(this); - connect(label_image1, SIGNAL(clicked()), this, SLOT(viewPicture())); - connect(label_image2, SIGNAL(clicked()), this, SLOT(viewPicture())); - connect(label_image3, SIGNAL(clicked()), this, SLOT(viewPicture())); - connect(label_image4, SIGNAL(clicked()), this, SLOT(viewPicture())); + connect(label_image1, SIGNAL(clicked()), this, SLOT(viewPictureOne())); + connect(label_image2, SIGNAL(clicked()), this, SLOT(viewPictureTwo())); + connect(label_image3, SIGNAL(clicked()), this, SLOT(viewPictureThree())); + connect(label_image4, SIGNAL(clicked()), this, SLOT(viewPictureFour())); } void PulseMessage::setup(RsWirePulseSPtr pulse) @@ -148,7 +148,7 @@ void PulseMessage::setRefImageCount(uint32_t count) } } -void PulseMessage::viewPicture() +void PulseMessage::viewPictureOne() { PhotoView *photoView = new PhotoView(this); @@ -158,21 +158,69 @@ void PulseMessage::viewPicture() pixmap.loadFromData(mPulse->mImage1.mData, mPulse->mImage1.mSize); photoView->setPixmap(pixmap); } - + + QString timestamp = misc::timeRelativeToNow(mPulse->mRefPublishTs); + + photoView->setTitle(QString::fromStdString(mPulse->mPulseText)); + photoView->setGroupNameString(QString::fromStdString(mPulse->mRefGroupName)); + photoView->setTime(timestamp); + //photoView->setGroupId(mPulse->mRefGroupId); + + photoView->show(); + + /* window will destroy itself! */ +} + +void PulseMessage::viewPictureTwo() +{ + PhotoView *photoView = new PhotoView(this); + if (!mPulse->mImage2.empty()) { // install image. QPixmap pixmap; pixmap.loadFromData(mPulse->mImage2.mData, mPulse->mImage2.mSize); photoView->setPixmap(pixmap); } - + + QString timestamp = misc::timeRelativeToNow(mPulse->mRefPublishTs); + + photoView->setTitle(QString::fromStdString(mPulse->mPulseText)); + photoView->setGroupNameString(QString::fromStdString(mPulse->mRefGroupName)); + photoView->setTime(timestamp); + //photoView->setGroupId(mPulse->mRefGroupId); + + photoView->show(); + + /* window will destroy itself! */ +} + +void PulseMessage::viewPictureThree() +{ + PhotoView *photoView = new PhotoView(this); + if (!mPulse->mImage3.empty()) { // install image. QPixmap pixmap; pixmap.loadFromData(mPulse->mImage3.mData, mPulse->mImage3.mSize); photoView->setPixmap(pixmap); } - + + QString timestamp = misc::timeRelativeToNow(mPulse->mRefPublishTs); + + photoView->setTitle(QString::fromStdString(mPulse->mPulseText)); + photoView->setGroupNameString(QString::fromStdString(mPulse->mRefGroupName)); + photoView->setTime(timestamp); + //photoView->setGroupId(mPulse->mRefGroupId); + + photoView->show(); + + /* window will destroy itself! */ +} + +void PulseMessage::viewPictureFour() +{ + PhotoView *photoView = new PhotoView(this); + if (!mPulse->mImage4.empty()) { // install image. QPixmap pixmap; diff --git a/retroshare-gui/src/gui/TheWire/PulseMessage.h b/retroshare-gui/src/gui/TheWire/PulseMessage.h index a2372ebbf..234f0da02 100644 --- a/retroshare-gui/src/gui/TheWire/PulseMessage.h +++ b/retroshare-gui/src/gui/TheWire/PulseMessage.h @@ -37,7 +37,10 @@ public: void setRefImageCount(uint32_t count); private slots: - void viewPicture(); + void viewPictureOne(); + void viewPictureTwo(); + void viewPictureThree(); + void viewPictureFour(); private: RsWirePulseSPtr mPulse; diff --git a/retroshare-gui/src/gui/TheWire/PulseMessage.ui b/retroshare-gui/src/gui/TheWire/PulseMessage.ui index 8af226cea..46e4d8cd5 100644 --- a/retroshare-gui/src/gui/TheWire/PulseMessage.ui +++ b/retroshare-gui/src/gui/TheWire/PulseMessage.ui @@ -14,6 +14,18 @@ Form + + 0 + + + 0 + + + 0 + + + 0 + @@ -53,7 +65,7 @@ MS Sans Serif - 10 + 11 diff --git a/retroshare-gui/src/gui/TheWire/PulseReply.cpp b/retroshare-gui/src/gui/TheWire/PulseReply.cpp index 92dccabf5..5067b5f9b 100644 --- a/retroshare-gui/src/gui/TheWire/PulseReply.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseReply.cpp @@ -50,7 +50,7 @@ void PulseReply::setup() // connect(pushButton_tmpViewGroup, SIGNAL(clicked()), this, SLOT(actionViewGroup())); // connect(pushButton_tmpViewParent, SIGNAL(clicked()), this, SLOT(actionViewParent())); - connect(toolButton_follow, SIGNAL(clicked()), this, SLOT(actionFollow())); + connect(followButton, SIGNAL(clicked()), this, SLOT(actionFollow())); // connect(toolButton_rate, SIGNAL(clicked()), this, SLOT(rate())); connect(toolButton_reply, SIGNAL(clicked()), this, SLOT(actionReply())); @@ -118,7 +118,7 @@ void PulseReply::setPulseStatus(PulseStatus status) { widget_actions->setVisible(status == PulseStatus::FULL); widget_follow->setVisible(status != PulseStatus::FULL); - toolButton_follow->setEnabled(status == PulseStatus::UNSUBSCRIBED); + followButton->setEnabled(status == PulseStatus::UNSUBSCRIBED); switch(status) { diff --git a/retroshare-gui/src/gui/TheWire/PulseReply.ui b/retroshare-gui/src/gui/TheWire/PulseReply.ui index 1ffbbdf85..497d606de 100644 --- a/retroshare-gui/src/gui/TheWire/PulseReply.ui +++ b/retroshare-gui/src/gui/TheWire/PulseReply.ui @@ -25,8 +25,20 @@ + + 0 + + + 0 + + + 0 + + + 0 + - + 0 @@ -48,10 +60,13 @@ QFrame::Raised - + 0 + + 1 + @@ -149,6 +164,9 @@ + + 9 + 0 @@ -380,7 +398,14 @@ - + + + + 12 + 75 + true + + FOLLOW @@ -433,10 +458,22 @@ 0 - 40 + 0 + + 6 + + + 0 + + + 0 + + + 0 + @@ -604,13 +641,19 @@ 0 - 40 + 0 + + 6 + 0 + + 0 + 0 diff --git a/retroshare-gui/src/gui/TheWire/PulseReplySeperator.ui b/retroshare-gui/src/gui/TheWire/PulseReplySeperator.ui index 4a605a219..6564fe5e3 100644 --- a/retroshare-gui/src/gui/TheWire/PulseReplySeperator.ui +++ b/retroshare-gui/src/gui/TheWire/PulseReplySeperator.ui @@ -40,10 +40,7 @@ - QFrame#frame{border: 2px solid #CCCCCC; -background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #EEEEEE, stop: 1 #CCCCCC); -border-radius: 10px} + QFrame::StyledPanel diff --git a/retroshare-gui/src/gui/TheWire/PulseTopLevel.cpp b/retroshare-gui/src/gui/TheWire/PulseTopLevel.cpp index e8c830a0b..0948e745b 100644 --- a/retroshare-gui/src/gui/TheWire/PulseTopLevel.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseTopLevel.cpp @@ -48,7 +48,7 @@ void PulseTopLevel::setup() { connect(toolButton_viewGroup, SIGNAL(clicked()), this, SLOT(actionViewGroup())); connect(toolButton_viewParent, SIGNAL(clicked()), this, SLOT(actionViewParent())); - connect(toolButton_follow, SIGNAL(clicked()), this, SLOT(actionFollow())); + connect(followButton, SIGNAL(clicked()), this, SLOT(actionFollow())); connect(toolButton_followParent, SIGNAL(clicked()), this, SLOT(actionFollowParent())); // connect(toolButton_rate, SIGNAL(clicked()), this, SLOT(rate())); @@ -58,7 +58,7 @@ void PulseTopLevel::setup() connect(toolButton_view, SIGNAL(clicked()), this, SLOT(actionViewPulse())); } -void PulseTopLevel::setRefMessage(QString msg, uint32_t image_count) +void PulseTopLevel::setRefMessage(QString /*msg*/, uint32_t /*image_count*/) { // This should never happen. //widget_message->setRefMessage(msg, image_count); @@ -149,7 +149,7 @@ void PulseTopLevel::setReferenceString(QString ref) } } -void PulseTopLevel::mousePressEvent(QMouseEvent *event) +void PulseTopLevel::mousePressEvent(QMouseEvent */*event*/) { } diff --git a/retroshare-gui/src/gui/TheWire/PulseTopLevel.ui b/retroshare-gui/src/gui/TheWire/PulseTopLevel.ui index 35f763948..1959244d3 100644 --- a/retroshare-gui/src/gui/TheWire/PulseTopLevel.ui +++ b/retroshare-gui/src/gui/TheWire/PulseTopLevel.ui @@ -24,9 +24,9 @@ - + - + 0 @@ -48,7 +48,7 @@ QFrame::Raised - + @@ -63,7 +63,7 @@ 40 - + 0 @@ -77,7 +77,7 @@ 0 - + Qt::Horizontal @@ -171,7 +171,7 @@ - + Qt::Horizontal @@ -200,9 +200,9 @@ 60 - + - + Qt::Vertical @@ -256,7 +256,7 @@ - + Qt::Horizontal @@ -336,7 +336,7 @@ 16777215 - + @@ -345,7 +345,7 @@ - + Qt::Horizontal @@ -361,7 +361,7 @@ - + Qt::Horizontal @@ -381,9 +381,9 @@ 40 - + - + @@ -392,14 +392,14 @@ - + <html><head/><body><p><span style=" color:#2e3436;">Replies</span></p></body></html> - + Qt::Horizontal @@ -417,7 +417,7 @@ - + @@ -426,14 +426,14 @@ - + <html><head/><body><p><span style=" color:#2e3436;">Republishes</span></p></body></html> - + Qt::Horizontal @@ -451,7 +451,7 @@ - + @@ -460,14 +460,14 @@ - + <html><head/><body><p><span style=" color:#2e3436;">Likes</span></p></body></html> - + Qt::Horizontal @@ -485,7 +485,7 @@ - + Qt::Horizontal @@ -501,7 +501,7 @@ - + Qt::Horizontal @@ -521,11 +521,11 @@ 40 - + - + - + Qt::Horizontal @@ -562,7 +562,7 @@ - + Qt::Horizontal @@ -577,9 +577,9 @@ - + - + Qt::Horizontal @@ -616,7 +616,7 @@
- + Qt::Horizontal @@ -631,9 +631,9 @@
- + - + Qt::Horizontal @@ -670,7 +670,7 @@ - + Qt::Horizontal @@ -685,9 +685,9 @@ - + - + Qt::Horizontal @@ -717,7 +717,7 @@ - + Qt::Horizontal @@ -748,9 +748,9 @@ 40 - + - + Qt::Horizontal @@ -763,7 +763,13 @@ - + + + + 12 + true + + FOLLOW @@ -773,7 +779,7 @@ - + Qt::Horizontal diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp b/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp index 547fabbab..475c74034 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp @@ -24,86 +24,149 @@ #include #include "PulseViewGroup.h" +#include "CustomFrame.h" +#include "WireGroupDialog.h" #include "gui/gxs/GxsIdDetails.h" #include "gui/common/FilesDefs.h" #include "util/DateTime.h" +Q_DECLARE_METATYPE(RsWireGroup) + /** Constructor */ PulseViewGroup::PulseViewGroup(PulseViewHolder *holder, RsWireGroupSPtr group) :PulseViewItem(holder), mGroup(group) { - setupUi(this); - setAttribute ( Qt::WA_DeleteOnClose, true ); - setup(); + setupUi(this); + setAttribute ( Qt::WA_DeleteOnClose, true ); + setup(); + + connect(editButton, SIGNAL(clicked()), this, SLOT(editProfile())); + } void PulseViewGroup::setup() { - if (mGroup) { - connect(toolButton_follow, SIGNAL(clicked()), this, SLOT(actionFollow())); + if (mGroup) { + connect(followButton, SIGNAL(clicked()), this, SLOT(actionFollow())); - label_groupName->setText("@" + QString::fromStdString(mGroup->mMeta.mGroupName)); - label_authorName->setText(BoldString(QString::fromStdString(mGroup->mMeta.mAuthorId.toStdString()))); - label_date->setText(DateTime::formatDateTime(mGroup->mMeta.mPublishTs)); - label_tagline->setText(QString::fromStdString(mGroup->mTagline)); - label_location->setText(QString::fromStdString(mGroup->mLocation)); + label_groupName->setText("@" + QString::fromStdString(mGroup->mMeta.mGroupName)); + label_authorName->setText(BoldString(QString::fromStdString(mGroup->mMeta.mAuthorId.toStdString()))); + label_date->setText(DateTime::formatDateTime(mGroup->mMeta.mPublishTs)); + label_tagline->setText(QString::fromStdString(mGroup->mTagline)); + label_location->setText(QString::fromStdString(mGroup->mLocation)); - // need to draw mGroup->mMasthead, as background to headshot. - // TODO frame_headerBackground->setBackground() - if (mGroup->mHeadshot.mData) - { - QPixmap pixmap; - if (GxsIdDetails::loadPixmapFromData( - mGroup->mHeadshot.mData, - mGroup->mHeadshot.mSize, - pixmap,GxsIdDetails::ORIGINAL)) - { - pixmap = pixmap.scaled(50,50); - label_headshot->setPixmap(pixmap); - } - } - else - { + if (mGroup->mMasthead.mData) + { + QPixmap pixmap; + if (GxsIdDetails::loadPixmapFromData( + mGroup->mMasthead.mData, + mGroup->mMasthead.mSize, + pixmap, GxsIdDetails::ORIGINAL)) + { + QSize frameSize = frame_masthead->size(); + + // Scale the pixmap based on the frame size + pixmap = pixmap.scaledToWidth(frameSize.width(), Qt::SmoothTransformation); + frame_masthead->setPixmap(pixmap); + } + } +// Uncomment the below code for default background +// else +// { +// // Default pixmap +// QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/png/posted.png"); +// QSize frameSize = frame_masthead->size(); + +// // Scale the pixmap based on the frame size +// pixmap = pixmap.scaled(frameSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); +// frame_masthead->setPixmap(pixmap); +// } + + if (mGroup->mHeadshot.mData) + { + QPixmap pixmap; + if (GxsIdDetails::loadPixmapFromData( + mGroup->mHeadshot.mData, + mGroup->mHeadshot.mSize, + pixmap,GxsIdDetails::ORIGINAL)) + { + pixmap = pixmap.scaled(100,100, Qt::KeepAspectRatio, Qt::SmoothTransformation); + label_headshot->setPixmap(pixmap); + } + } + else + { // default. - QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/png/posted.png").scaled(50,50); - label_headshot->setPixmap(pixmap); - } + QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png").scaled(100,100, Qt::KeepAspectRatio, Qt::SmoothTransformation); + label_headshot->setPixmap(pixmap); + } - if (mGroup->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) - { - uint32_t pulses = mGroup->mGroupPulses + mGroup->mGroupReplies; - uint32_t replies = mGroup->mRefReplies; - uint32_t republishes = mGroup->mRefRepublishes; - uint32_t likes = mGroup->mRefLikes; + if (mGroup->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) + { + uint32_t pulses = mGroup->mGroupPulses + mGroup->mGroupReplies; + uint32_t replies = mGroup->mRefReplies; + uint32_t republishes = mGroup->mRefRepublishes; + uint32_t likes = mGroup->mRefLikes; - label_extra_pulses->setText(BoldString(ToNumberUnits(pulses))); - label_extra_replies->setText(BoldString(ToNumberUnits(replies))); - label_extra_republishes->setText(BoldString(ToNumberUnits(republishes))); - label_extra_likes->setText(BoldString(ToNumberUnits(likes))); + label_extra_pulses->setText(BoldString(ToNumberUnits(pulses))); + label_extra_replies->setText(BoldString(ToNumberUnits(replies))); + label_extra_republishes->setText(BoldString(ToNumberUnits(republishes))); + label_extra_likes->setText(BoldString(ToNumberUnits(likes))); - // hide follow. - widget_actions->setVisible(false); - } - else - { - // hide stats. - widget_replies->setVisible(false); - } + // hide follow. + widget_actions->setVisible(false); + } + else + { + // hide stats. + widget_replies->setVisible(false); + } + } + + setGroupSet(); +} + +void PulseViewGroup::setGroupSet() +{ + if (mGroup->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) { + editButton->show(); + } + else if (mGroup->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) + { + editButton->hide(); + } + else + { + editButton->hide(); } } void PulseViewGroup::actionFollow() { - RsGxsGroupId groupId = mGroup->mMeta.mGroupId; - std::cerr << "PulseViewGroup::actionFollow() following "; - std::cerr << groupId; - std::cerr << std::endl; + RsGxsGroupId groupId = mGroup->mMeta.mGroupId; + std::cerr << "PulseViewGroup::actionFollow() following "; + std::cerr << groupId; + std::cerr << std::endl; - if (mHolder) { - mHolder->PVHfollow(groupId); - } + if (mHolder) { + mHolder->PVHfollow(groupId); + } +} + +void PulseViewGroup::editProfile() +{ + RsGxsGroupId groupId = mGroup->mMeta.mGroupId; + if (groupId.isNull()) + { + std::cerr << "PulseViewGroup::editProfile() No Group selected"; + std::cerr << std::endl; + return; + } + + WireGroupDialog wireEdit(GxsGroupDialog::MODE_EDIT, groupId, this); + wireEdit.exec (); } diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.h b/retroshare-gui/src/gui/TheWire/PulseViewGroup.h index 4d00090ca..62da0a228 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.h +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.h @@ -35,10 +35,13 @@ public: private slots: void actionFollow(); + void editProfile(); protected: void setup(); +private: + void setGroupSet(); protected: RsWireGroupSPtr mGroup; diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui b/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui index 41a2bf23a..79d9964f6 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui @@ -6,7 +6,7 @@ 0 0 - 745 + 746 483 @@ -24,9 +24,9 @@ - + - + 0 @@ -50,17 +50,35 @@ - - + + + + 0 + 0 + + + + + 700 + 135 + + + + + + - + Qt::Horizontal + + QSizePolicy::Expanding + - 283 - 20 + 277 + 17 @@ -79,19 +97,22 @@ 100 + + + headshot - + Qt::Horizontal - 23 + 281 20 @@ -114,16 +135,38 @@ 60 - - - + + + + + + 0 + 0 + + + + + 0 + 20 + + + + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> + + + + + - Qt::Horizontal + Qt::Vertical + + + QSizePolicy::Minimum - 518 - 58 + 20 + 10 @@ -147,41 +190,26 @@ - - - - - 0 - 0 - - - - - 0 - 20 - - - - <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - - - - - + + - Qt::Vertical - - - QSizePolicy::Minimum + Qt::Horizontal - 20 - 10 + 518 + 58 + + + + Edit profile + + + @@ -205,42 +233,7 @@ 16777215 - - - - - - 0 - 0 - - - - - 0 - 20 - - - - <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - + @@ -260,19 +253,6 @@ - - - - Qt::Horizontal - - - - 2000 - 20 - - - - @@ -292,11 +272,59 @@ + + + + + 0 + 0 + + + + + 0 + 20 + + + + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> + + + + + + + Qt::Horizontal + + + + 2000 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + - + Qt::Horizontal @@ -316,9 +344,9 @@ 40 - + - + @@ -327,14 +355,14 @@ - + <html><head/><body><p><span style=" color:#2e3436;">Pulses</span></p></body></html> - + Qt::Horizontal @@ -352,7 +380,7 @@ - + @@ -361,14 +389,14 @@ - + <html><head/><body><p><span style=" color:#2e3436;">Replies</span></p></body></html> - + Qt::Horizontal @@ -386,7 +414,7 @@ - + @@ -395,14 +423,14 @@ - + <html><head/><body><p><span style=" color:#2e3436;">Republishes</span></p></body></html> - + Qt::Horizontal @@ -420,7 +448,7 @@ - + @@ -429,14 +457,14 @@ - + <html><head/><body><p><span style=" color:#2e3436;">Likes</span></p></body></html> - + Qt::Horizontal @@ -454,7 +482,7 @@ - + Qt::Horizontal @@ -470,7 +498,7 @@ - + Qt::Horizontal @@ -490,9 +518,9 @@ 40 - + - + Qt::Horizontal @@ -505,7 +533,14 @@ - + + + + 12 + 75 + true + + FOLLOW @@ -515,7 +550,7 @@ - + Qt::Horizontal @@ -531,12 +566,25 @@ + widget_header + widget_publish + line_1 + widget_replies + line_2 + widget_actions + frame_masthead
- - - + + + CustomFrame + QFrame +
gui/TheWire/CustomFrame.h
+ 1 +
+
+ diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.cpp b/retroshare-gui/src/gui/TheWire/WireDialog.cpp index ed2ee5edd..36a201a7f 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireDialog.cpp @@ -23,6 +23,8 @@ #include "WireGroupDialog.h" #include "WireGroupItem.h" #include "gui/settings/rsharesettings.h" +#include "gui/gxs/GxsIdDetails.h" +#include "gui/common/FilesDefs.h" #include "PulseViewGroup.h" #include "PulseReplySeperator.h" @@ -57,17 +59,14 @@ /** Constructor */ WireDialog::WireDialog(QWidget *parent) -: MainPage(parent), mGroupSet(GROUP_SET_ALL) + : MainPage(parent), mGroupSet(GROUP_SET_ALL) + , mAddDialog(nullptr), mGroupSelected(nullptr), mWireQueue(nullptr) + , mHistoryIndex(-1), mEventHandlerId(0) { ui.setupUi(this); - mAddDialog = NULL; - mGroupSelected = NULL; - mHistoryIndex = -1; - connect( ui.toolButton_createAccount, SIGNAL(clicked()), this, SLOT(createGroup())); connect( ui.toolButton_createPulse, SIGNAL(clicked()), this, SLOT(createPulse())); - connect( ui.toolButton_refresh, SIGNAL(clicked()), this, SLOT(refreshGroups())); connect(ui.comboBox_groupSet, SIGNAL(currentIndexChanged(int)), this, SLOT(selectGroupSet(int))); connect(ui.comboBox_filterTime, SIGNAL(currentIndexChanged(int)), this, SLOT(selectFilterTime(int))); @@ -91,6 +90,48 @@ WireDialog::WireDialog(QWidget *parent) // load settings processSettings(true); + + // Needs to be asynced because this function is called by another thread! + rsEvents->registerEventsHandler( + [this](std::shared_ptr event) + { RsQThreadUtils::postToObject([=]() { handleEvent_main_thread(event); }, this ); }, + mEventHandlerId, RsEventType::WIRE ); +} + +void WireDialog::handleEvent_main_thread(std::shared_ptr event) +{ + const RsWireEvent *e = dynamic_cast(event.get()); + + if(e) + { + +#ifdef GXSWIRE_DEBUG + RsDbg() << " Refreshing the feed if there is a matching event. "<< std::endl; +#endif + + // The following switch statements refresh the wire feed whenever there is a new event + switch(e->mWireEventCode) + { + case RsWireEventCode::NEW_POST: + + case RsWireEventCode::NEW_REPLY: + + case RsWireEventCode::NEW_LIKE: + + case RsWireEventCode::NEW_REPUBLISH: + + case RsWireEventCode::POST_UPDATED: + + case RsWireEventCode::NEW_WIRE: + + case RsWireEventCode::FOLLOW_STATUS_CHANGED: + + default: + refreshGroups(); + break; + + } + } } WireDialog::~WireDialog() @@ -98,7 +139,11 @@ WireDialog::~WireDialog() // save settings processSettings(false); - delete(mWireQueue); + clearTwitterView(); + std::cerr << "WireDialog::~WireDialog()" << std::endl; + delete(mWireQueue); + + rsEvents->unregisterEventsHandler(mEventHandlerId); } void WireDialog::processSettings(bool load) @@ -110,9 +155,16 @@ void WireDialog::processSettings(bool load) // state of splitter ui.splitter->restoreState(Settings->value("SplitterWire").toByteArray()); + + // state of filter combobox + int index = Settings->value("ShowGroup", 0).toInt(); + ui.comboBox_groupSet->setCurrentIndex(index); } else { // save settings + // state of filter combobox + Settings->setValue("ShowGroup", ui.comboBox_groupSet->currentIndex()); + // state of splitter Settings->setValue("SplitterWire", ui.splitter->saveState()); } @@ -127,7 +179,7 @@ void WireDialog::refreshGroups() void WireDialog::addGroup(QWidget *item) { - QLayout *alayout = ui.scrollAreaWidgetContents_groups->layout(); + QLayout *alayout = ui.groupsWidget->layout(); alayout->addWidget(item); } @@ -268,7 +320,7 @@ void WireDialog::deleteGroups() mGroupSelected = NULL; - QLayout *alayout = ui.scrollAreaWidgetContents_groups->layout(); + QLayout *alayout = ui.groupsWidget->layout(); QLayoutItem *item; int i = 0; while (i < alayout->count()) @@ -300,17 +352,28 @@ void WireDialog::updateGroups(std::vector& groups) mOwnGroups.clear(); ui.groupChooser->clear(); - std::vector::const_iterator it; - for(it = groups.begin(); it != groups.end(); it++) { + for(auto &it : groups) { // save list of all groups. - mAllGroups[it->mMeta.mGroupId] = *it; + mAllGroups[it.mMeta.mGroupId] = it; - if (it->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) + if (it.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) { // grab own groups. // setup Chooser too. - mOwnGroups.push_back(*it); - ui.groupChooser->addItem(QString::fromStdString(it->mMeta.mGroupName)); + mOwnGroups.push_back(it); + QPixmap pixmap; + if (it.mHeadshot.mData) + { + if (GxsIdDetails::loadPixmapFromData( it.mHeadshot.mData,it.mHeadshot.mSize,pixmap,GxsIdDetails::ORIGINAL)) + pixmap = pixmap.scaled(32,32); + } + else + { + // default. + pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png").scaled(32,32); + } + + ui.groupChooser->addItem(QPixmap(pixmap),QString::fromStdString(it.mMeta.mGroupName)); } } } @@ -362,16 +425,15 @@ void WireDialog::showGroups() std::list allGroupIds; /* depends on the comboBox */ - std::map::const_iterator it; - for (it = mAllGroups.begin(); it != mAllGroups.end(); it++) + for (auto &it : mAllGroups) { bool add = (mGroupSet == GROUP_SET_ALL); - if (it->second.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) { + if (it.second.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) { if (mGroupSet == GROUP_SET_OWN) { add = true; } } - else if (it->second.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) { + else if (it.second.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) { if (mGroupSet == GROUP_SET_SUBSCRIBED) { add = true; } @@ -383,11 +445,11 @@ void WireDialog::showGroups() } if (add) { - addGroup(it->second); + addGroup(it.second); // request data. std::list grpIds; - grpIds.push_back(it->second.mMeta.mGroupId); - allGroupIds.push_back(it->second.mMeta.mGroupId); + grpIds.push_back(it.second.mMeta.mGroupId); + allGroupIds.push_back(it.second.mMeta.mGroupId); } } @@ -413,13 +475,13 @@ bool WireDialog::loadGroupData(const uint32_t &token) std::cerr << "WireDialog::loadGroupData()"; std::cerr << std::endl; - std::vector groups; - rsWire->getGroupData(token, groups); + std::vector groups; + rsWire->getGroupData(token, groups); - // save list of groups. - updateGroups(groups); - showGroups(); - return true; + // save list of groups. + updateGroups(groups); + showGroups(); + return true; } rstime_t WireDialog::getFilterTimestamp() @@ -627,6 +689,7 @@ void WireDialog::PVHrate(const RsGxsId &authorId) void WireDialog::postTestTwitterView() { clearTwitterView(); + std::cerr << "WireDialog::postTestTwitterView()" << std::endl; addTwitterView(new PulseTopLevel(NULL,RsWirePulseSPtr())); addTwitterView(new PulseReply(NULL,RsWirePulseSPtr())); @@ -783,6 +846,7 @@ void WireDialog::requestPulseFocus(const RsGxsGroupId groupId, const RsGxsMessag void WireDialog::showPulseFocus(const RsGxsGroupId groupId, const RsGxsMessageId msgId) { clearTwitterView(); + std::cerr << "WireDialog::showPulseFocus()" << std::endl; // background thread for loading. RsThread::async([this, groupId, msgId]() @@ -790,20 +854,21 @@ void WireDialog::showPulseFocus(const RsGxsGroupId groupId, const RsGxsMessageId // fetch data from backend. RsWirePulseSPtr pPulse; int type = 0; - bool success = rsWire->getPulseFocus(groupId, msgId, type, pPulse); - - // sleep(2); - - /* now insert the pulse + children into the layput */ - RsQThreadUtils::postToObject([pPulse,this]() + if(rsWire->getPulseFocus(groupId, msgId, type, pPulse)) { - /* Here it goes any code you want to be executed on the Qt Gui + // sleep(2); + + /* now insert the pulse + children into the layput */ + RsQThreadUtils::postToObject([pPulse,this]() + { + /* Here it goes any code you want to be executed on the Qt Gui * thread, for example to update the data model with new information * after a blocking call to RetroShare API complete */ - postPulseFocus(pPulse); + postPulseFocus(pPulse); - }, this); + }, this); + } }); } @@ -811,6 +876,8 @@ void WireDialog::showPulseFocus(const RsGxsGroupId groupId, const RsGxsMessageId void WireDialog::postPulseFocus(RsWirePulseSPtr pPulse) { clearTwitterView(); + std::cerr << "WireDialog::postPulseFocus()" << std::endl; + if (!pPulse) { std::cerr << "WireDialog::postPulseFocus() Invalid pulse"; @@ -822,10 +889,9 @@ void WireDialog::postPulseFocus(RsWirePulseSPtr pPulse) addTwitterView(new PulseTopLevel(this, pPulse)); - std::list::iterator it; - for(it = pPulse->mReplies.begin(); it != pPulse->mReplies.end(); it++) + for(auto &it : pPulse->mReplies) { - RsWirePulseSPtr reply = *it; + RsWirePulseSPtr reply = it; PulseReply *firstReply = new PulseReply(this, reply); addTwitterView(firstReply); @@ -857,9 +923,9 @@ void WireDialog::postPulseFocus(RsWirePulseSPtr pPulse) addTwitterView(new PulseReplySeperator()); } - for(it = pPulse->mRepublishes.begin(); it != pPulse->mRepublishes.end(); it++) + for(auto &it : pPulse->mRepublishes) { - RsWirePulseSPtr repub = *it; + RsWirePulseSPtr repub = it; PulseReply *firstRepub = new PulseReply(this, repub); firstRepub->showReplyLine(false); @@ -884,7 +950,7 @@ void WireDialog::requestGroupFocus(const RsGxsGroupId groupId) void WireDialog::showGroupFocus(const RsGxsGroupId groupId) { clearTwitterView(); - + std::cerr << "WireDialog::showGroupFocus()" << std::endl; // background thread for loading. RsThread::async([this, groupId]() { @@ -928,10 +994,9 @@ void WireDialog::postGroupFocus(RsWireGroupSPtr group, std::list::iterator it; - for(it = pulses.begin(); it != pulses.end(); it++) + for(auto &it : pulses) { - RsWirePulseSPtr reply = *it; + RsWirePulseSPtr reply = it; // don't show likes if (reply->mPulseType & WIRE_PULSE_TYPE_LIKE) { @@ -949,7 +1014,7 @@ void WireDialog::postGroupFocus(RsWireGroupSPtr group, std::list groupIds) +void WireDialog::requestGroupsPulses(const std::list& groupIds) { WireViewHistory view; view.viewType = WireViewType::GROUPS; @@ -959,29 +1024,31 @@ void WireDialog::requestGroupsPulses(const std::list groupIds) showGroupsPulses(groupIds); } -void WireDialog::showGroupsPulses(const std::list groupIds) +void WireDialog::showGroupsPulses(const std::list& groupIds) { clearTwitterView(); + std::cerr << "WireDialog::showGroupPulses()" << std::endl; // background thread for loading. RsThread::async([this, groupIds]() { // fetch data from backend. std::list pulses; - bool success = rsWire->getPulsesForGroups(groupIds, pulses); - - // sleep(2); - - /* now insert the pulse + children into the layput */ - RsQThreadUtils::postToObject([pulses,this]() + if(rsWire->getPulsesForGroups(groupIds, pulses)) { - /* Here it goes any code you want to be executed on the Qt Gui + // sleep(2); + + /* now insert the pulse + children into the layput */ + RsQThreadUtils::postToObject([pulses,this]() + { + /* Here it goes any code you want to be executed on the Qt Gui * thread, for example to update the data model with new information * after a blocking call to RetroShare API complete */ - postGroupsPulses(pulses); + postGroupsPulses(pulses); - }, this); + }, this); + } }); } @@ -992,10 +1059,9 @@ void WireDialog::postGroupsPulses(std::list pulses) ui.label_viewMode->setText("Groups Pulses"); - std::list::iterator it; - for(it = pulses.begin(); it != pulses.end(); it++) + for(auto &it : pulses) { - RsWirePulseSPtr reply = *it; + RsWirePulseSPtr reply = it; // don't show likes if (reply->mPulseType & WIRE_PULSE_TYPE_LIKE) { std::cerr << "WireDialog::postGroupsPulses() Not showing LIKE"; @@ -1011,4 +1077,3 @@ void WireDialog::postGroupsPulses(std::list pulses) } } - diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.h b/retroshare-gui/src/gui/TheWire/WireDialog.h index 100cedeec..fcd33ad37 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.h +++ b/retroshare-gui/src/gui/TheWire/WireDialog.h @@ -76,9 +76,9 @@ public: WireDialog(QWidget *parent = 0); ~WireDialog(); - virtual QIcon iconPixmap() const { return QIcon(IMAGE_WIRE) ; } - virtual QString pageName() const { return tr("The Wire") ; } - virtual QString helpText() const { return ""; } + virtual QIcon iconPixmap() const override { return QIcon(IMAGE_WIRE) ; } + virtual QString pageName() const override { return tr("The Wire") ; } + virtual QString helpText() const override { return ""; } // WireGroupHolder interface. virtual void subscribe(RsGxsGroupId &groupId) override; @@ -114,8 +114,8 @@ public: void showGroupFocus(const RsGxsGroupId groupId); void postGroupFocus(RsWireGroupSPtr group, std::list pulses); - void requestGroupsPulses(const std::list groupIds); - void showGroupsPulses(const std::list groupIds); + void requestGroupsPulses(const std::list& groupIds); + void showGroupsPulses(const std::list& groupIds); void postGroupsPulses(std::list pulses); private slots: @@ -150,10 +150,10 @@ private: // Loading Data. void requestGroupData(); - bool loadGroupData(const uint32_t &token); + bool loadGroupData(const uint32_t &token); void acknowledgeGroup(const uint32_t &token, const uint32_t &userType); - virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); + virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req) override; int mGroupSet; @@ -164,6 +164,10 @@ private: std::map mAllGroups; std::vector mOwnGroups; + // This function and variable below it handle the events for the wire + void handleEvent_main_thread(std::shared_ptr event); + RsEventsHandlerId_t mEventHandlerId; + int32_t mHistoryIndex; std::vector mHistory; diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.ui b/retroshare-gui/src/gui/TheWire/WireDialog.ui index 2aeefe92f..4cdf4a174 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.ui +++ b/retroshare-gui/src/gui/TheWire/WireDialog.ui @@ -6,7 +6,7 @@ 0 0 - 804 + 809 586 @@ -33,7 +33,7 @@ 0 - + 0 @@ -46,7 +46,7 @@ QFrame::Plain - + 0 @@ -101,14 +101,7 @@ - - - Refresh - - - - - + @@ -134,7 +127,7 @@ Qt::Horizontal - + 1 @@ -159,9 +152,9 @@ QFrame::Raised - + - + All @@ -189,7 +182,6 @@ 10 - 75 true @@ -199,22 +191,22 @@ - + true - + 0 0 - 228 - 488 + 224 + 465 - + - + Qt::Vertical @@ -305,6 +297,11 @@ + + + 12 + + Most Recent @@ -337,7 +334,7 @@ - + 0 @@ -383,7 +380,7 @@ 0 0 523 - 484 + 462 @@ -429,9 +426,16 @@ + + + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
+
- + diff --git a/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp b/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp index 1be0c9a2c..e832540de 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp @@ -109,7 +109,7 @@ void WireGroupDialog::prepareWireGroup(RsWireGroup &group, const RsGroupMetaData QBuffer buffer(&ba); buffer.open(QIODevice::WriteOnly); - pixmap.save(&buffer, "PNG"); // writes image into ba in PNG format + pixmap.save(&buffer, "PNG"); // writes image into ba in PNG format group.mHeadshot.copy((uint8_t *) ba.data(), ba.size()); } else { @@ -126,7 +126,7 @@ void WireGroupDialog::prepareWireGroup(RsWireGroup &group, const RsGroupMetaData QBuffer buffer(&ba); buffer.open(QIODevice::WriteOnly); - pixmap.save(&buffer, "JPG"); + pixmap.save(&buffer, "PNG"); group.mMasthead.copy((uint8_t *) ba.data(), ba.size()); } else { @@ -152,7 +152,7 @@ bool WireGroupDialog::service_updateGroup(const RsGroupMetaData &editedMeta) std::cerr << "WireGroupDialog::service_updateGroup() submitting changes"; std::cerr << std::endl; - bool success = rsWire->updateGroup(grp); + bool success = rsWire->editWire(grp); // TODO updateGroup should refresh groupId or Data return success; } diff --git a/retroshare-gui/src/gui/TheWire/WireGroupExtra.cpp b/retroshare-gui/src/gui/TheWire/WireGroupExtra.cpp index b6a1c5440..8ed6d4d4b 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupExtra.cpp +++ b/retroshare-gui/src/gui/TheWire/WireGroupExtra.cpp @@ -34,13 +34,19 @@ WireGroupExtra::~WireGroupExtra() void WireGroupExtra::setUp() { - connect(ui.pushButton_masthead, SIGNAL(clicked() ), this , SLOT(addMasthead())); -} + connect(ui.pushButton_masthead, SIGNAL(clicked() ), this , SLOT(addMasthead())); + int desired_height = ui.pushButton_masthead->height() + ui.removeButton->height() + ui.lineEdit_Tagline->height(); + int desired_width = 3/1.0 * desired_height + ui.lineEdit_Tagline->width(); + + ui.label_masthead->setFixedSize(desired_width, desired_height); + + setMasthead(QPixmap()); +} void WireGroupExtra::addMasthead() { - QPixmap img = misc::getOpenThumbnailedPicture(this, tr("Load Masthead"), 400, 100); + QPixmap img = misc::getOpenThumbnailedPicture(this, tr("Load Masthead"), 800, 600); if (img.isNull()) return; @@ -48,7 +54,6 @@ void WireGroupExtra::addMasthead() setMasthead(img); } - void WireGroupExtra::setTagline(const std::string &str) { ui.lineEdit_Tagline->setText(QString::fromStdString(str)); @@ -61,8 +66,21 @@ void WireGroupExtra::setLocation(const std::string &str) void WireGroupExtra::setMasthead(const QPixmap &pixmap) { - mMasthead = pixmap; - ui.label_masthead->setPixmap(mMasthead); + mMasthead = pixmap; + + if (!mMasthead.isNull()) { + ui.label_masthead->setPicture(mMasthead); + ui.label_masthead->setToolTip(tr("Use the mouse to zoom and adjust the image for your background.")); + } else { + ui.label_masthead->setPicture(QPixmap()); + ui.label_masthead->setText(tr("MastHead background Image")); + } +} + +void WireGroupExtra::on_removeButton_clicked() +{ + ui.label_masthead->setPicture(QPixmap()); + ui.label_masthead->setText(tr("MastHead background Image")); } std::string WireGroupExtra::getTagline() @@ -77,7 +95,5 @@ std::string WireGroupExtra::getLocation() QPixmap WireGroupExtra::getMasthead() { - return mMasthead; + return ui.label_masthead->extractCroppedScaledPicture(); } - - diff --git a/retroshare-gui/src/gui/TheWire/WireGroupExtra.h b/retroshare-gui/src/gui/TheWire/WireGroupExtra.h index ce606feb3..429be088b 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupExtra.h +++ b/retroshare-gui/src/gui/TheWire/WireGroupExtra.h @@ -34,7 +34,6 @@ public: void setMasthead(const QPixmap &pixmap); QPixmap getMasthead(); - void setTagline(const std::string &str); void setLocation(const std::string &str); @@ -43,7 +42,7 @@ public: private slots: void addMasthead(); - + void on_removeButton_clicked(); private: void setUp(); private: diff --git a/retroshare-gui/src/gui/TheWire/WireGroupExtra.ui b/retroshare-gui/src/gui/TheWire/WireGroupExtra.ui index fb1da5e73..4c03b8fe8 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupExtra.ui +++ b/retroshare-gui/src/gui/TheWire/WireGroupExtra.ui @@ -7,7 +7,7 @@ 0 0 516 - 199 + 133
@@ -19,50 +19,127 @@ Form - + + + 0 + + + 0 + - - - Masthead - - - - - - - MastHead background Image - - + + + + + + + + Tagline: + + + + + + + + + + Remove + + + + + + + Location: + + + + + + + Qt::Vertical + + + + 20 + 10 + + + + + + + + Select Image + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + QFrame::Plain + + + 1 + + + MastHead background Image + + + Qt::PlainText + + + false + + + Qt::AlignCenter + + + + - - - Select Image + + + Qt::Vertical - - - - - - Tagline: + + + 20 + 10 + - - - - - - - - - Location: - - - - - +
+ + + ZoomableLabel + QLabel +
gui/gxschannels/GxsChannelPostThumbnail.h
+
+
diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp b/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp index 8ab62260a..1759103f6 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp @@ -65,8 +65,7 @@ WireGroupItem::WireGroupItem(WireGroupHolder *holder, const RsWireGroup &grp) setAttribute ( Qt::WA_DeleteOnClose, true ); setup(); - // disabled, still not yet functional Edit/Update - editButton->setEnabled(false); + editButton->setEnabled(true); } RsGxsGroupId &WireGroupItem::groupId() @@ -93,14 +92,14 @@ void WireGroupItem::setup() QImage circleImage = getCirclePhoto(orginalImage,orginalImage.size().width()); pixmap.convertFromImage(circleImage); - pixmap = pixmap.scaled(40,40); + pixmap = pixmap.scaled(40,40, Qt::KeepAspectRatio, Qt::SmoothTransformation); label_headshot->setPixmap(pixmap); } } else { // default. - QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png").scaled(32,32); + QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png").scaled(32,32, Qt::KeepAspectRatio, Qt::SmoothTransformation); label_headshot->setPixmap(pixmap); } @@ -124,21 +123,21 @@ void WireGroupItem::setup() void WireGroupItem::setGroupSet() { if (mGroup.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) { - toolButton_type->setText("Own"); - toolButton_subscribe->setText("N/A"); + toolButton_type->setText(tr("Own")); + toolButton_subscribe->setText(tr("N/A")); toolButton_subscribe->setEnabled(false); editButton->show(); } else if (mGroup.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) { - toolButton_type->setText("Following"); - toolButton_subscribe->setText("Unfollow"); + toolButton_type->setText(tr("Following")); + toolButton_subscribe->setText(tr("Unfollow")); editButton->hide(); } else { - toolButton_type->setText("Other"); - toolButton_subscribe->setText("Follow"); + toolButton_type->setText(tr("Other")); + toolButton_subscribe->setText(tr("Follow")); editButton->hide(); } } diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.ui b/retroshare-gui/src/gui/TheWire/WireGroupItem.ui index 2da79ddc6..a53448157 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupItem.ui +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.ui @@ -6,8 +6,8 @@ 0 0 - 276 - 114 + 292 + 115 diff --git a/retroshare-gui/src/gui/TorControl/TorControlWindow.cpp b/retroshare-gui/src/gui/TorControl/TorControlWindow.cpp new file mode 100644 index 000000000..6da6b8d7a --- /dev/null +++ b/retroshare-gui/src/gui/TorControl/TorControlWindow.cpp @@ -0,0 +1,230 @@ +#include +#include + +#include +#include +#include +#include + +#include +#include "util/rstime.h" + +#include "TorControlWindow.h" +#include "TorManager.h" +#include "TorControl.h" +#include "HiddenService.h" + +TorControlDialog::TorControlDialog(Tor::TorManager *tm,QWidget *parent) + : mTorManager(tm) +{ + setupUi(this) ; + + QObject::connect(tm->control(),SIGNAL(statusChanged(int,int)),this,SLOT(statusChanged())) ; + QObject::connect(tm->control(),SIGNAL(connected()),this,SLOT(statusChanged())); + QObject::connect(tm->control(),SIGNAL(disconnected()),this,SLOT(statusChanged())); + QObject::connect(tm->control(),SIGNAL(bootstrapStatusChanged()),this,SLOT(statusChanged())); + QObject::connect(tm->control(),SIGNAL(connectivityChanged()),this,SLOT(statusChanged())); + QObject::connect(tm ,SIGNAL(errorChanged()),this,SLOT(statusChanged())); + + //QTimer::singleShot(2000,this,SLOT(checkForHiddenService())) ; + + mIncomingServer = new QTcpServer(this) ; + mHiddenService = NULL ; + mHiddenServiceStatus = HIDDEN_SERVICE_STATUS_UNKNOWN; + //mBootstrapPhaseFinished = false ; + + connect(mIncomingServer, SIGNAL(QTcpServer::newConnection()), this, SLOT(onIncomingConnection())); + + QTimer *timer = new QTimer ; + + QObject::connect(timer,SIGNAL(timeout()),this,SLOT(showLog())) ; + timer->start(500) ; + + // Hide some debug output for the released version + + setWindowFlags( Qt::Dialog | Qt::FramelessWindowHint ); + + adjustSize(); +} + +void TorControlDialog::onIncomingConnection() +{ + std::cerr << "Incoming connection !!" << std::endl; +} + +void TorControlDialog::statusChanged() +{ + int tor_control_status = mTorManager->control()->status(); + int torstatus = mTorManager->control()->torStatus(); + + QString tor_control_status_str,torstatus_str ; + + if(mTorManager->hasError()) + mErrorMsg = mTorManager->errorMessage() ; + + switch(tor_control_status) + { + default: + case Tor::TorControl::Error : tor_control_status_str = "Error" ; break ; + case Tor::TorControl::NotConnected: tor_control_status_str = "Not connected" ; break ; + case Tor::TorControl::Connecting: tor_control_status_str = "Connecting" ; break ; + case Tor::TorControl::Authenticating: tor_control_status_str = "Authenticating" ; break ; + case Tor::TorControl::Connected: tor_control_status_str = "Connected" ; break ; + } + + switch(torstatus) + { + default: + case Tor::TorControl::TorUnknown: torstatus_str = "Unknown" ; break ; + case Tor::TorControl::TorOffline: torstatus_str = "Tor offline" ; break ; + case Tor::TorControl::TorReady: torstatus_str = "Tor ready" ; break ; + } + + torStatus_LB->setText(torstatus_str) ; + + if(torstatus == Tor::TorControl::TorUnknown) + torStatus_LB->setToolTip(tr("Check that Tor is accessible in your executable path")) ; + else + torStatus_LB->setToolTip("") ; + + QVariantMap qvm = mTorManager->control()->bootstrapStatus(); + QString bootstrapstatus_str ; + + std::cerr << "Tor control status: " << tor_control_status_str.toStdString() << std::endl; + std::cerr << "Tor status: " << torstatus_str.toStdString() << std::endl; + + std::cerr << "Bootstrap status map: " << std::endl; + + for(auto it(qvm.begin());it!=qvm.end();++it) + std::cerr << " " << it.key().toStdString() << " : " << it.value().toString().toStdString() << std::endl; + + if(!qvm["progress"].toString().isNull()) + torBootstrapStatus_LB->setText(qvm["progress"].toString() + " % (" + qvm["summary"].toString() + ")") ; + else + torBootstrapStatus_LB->setText(tr("[Waiting for Tor...]")) ; + + QString service_id ; + QString onion_address ; + QHostAddress service_target_address ; + uint16_t service_port ; + uint16_t target_port ; + + if(mTorManager->getHiddenServiceInfo(service_id,onion_address,service_port, service_target_address,target_port)) + { + hiddenServiceAddress_LB->setText(QString::number(service_port) + ":" + service_target_address.toString() + ":" + QString::number(target_port)); + onionAddress_LB->setText(onion_address); + } + else + { + hiddenServiceAddress_LB->setText(QString("[Not ready]")) ; + onionAddress_LB->setText(QString("[Not ready]")) ; + } + + showLog(); + adjustSize(); + + QCoreApplication::processEvents(); // forces update +} + +void TorControlDialog::showLog() +{ + static std::set already_seen ; + + QString s ; + QStringList logmsgs = mTorManager->logMessages() ; + bool can_print = false ; + + for(QStringList::const_iterator it(logmsgs.begin());it!=logmsgs.end();++it) + { + s += *it + "\n" ; + + if(already_seen.find(*it) == already_seen.end()) + { + can_print = true ; + already_seen.insert(*it); + } + + if(can_print) + std::cerr << "[TOR DEBUG LOG] " << (*it).toStdString() << std::endl; + } + +// torLog_TB->setText(s) ;: + + std::cerr << "Connexion Proxy: " << mTorManager->control()->socksAddress().toString().toStdString() << ":" << mTorManager->control()->socksPort() << std::endl; +} + +TorControlDialog::TorStatus TorControlDialog::checkForTor(QString& error_msg) +{ + if(!mErrorMsg.isNull()) + { + error_msg = mErrorMsg ; + return TorControlDialog::TOR_STATUS_FAIL ; + } + + switch(mTorManager->control()->torStatus()) + { + case Tor::TorControl::TorReady: rstime::rs_usleep(1*1000*1000);return TOR_STATUS_OK ; + default: + return TOR_STATUS_UNKNOWN ; + } +} + +TorControlDialog::HiddenServiceStatus TorControlDialog::checkForHiddenService() +{ + std::cerr << "Checking for hidden services:" ; + + switch(mHiddenServiceStatus) + { + default: + case HIDDEN_SERVICE_STATUS_UNKNOWN: { + + std::cerr << " trying to setup. " ; + + if(!mTorManager->setupHiddenService()) + { + mHiddenServiceStatus = HIDDEN_SERVICE_STATUS_FAIL ; + std::cerr << "Failed." << std::endl; + return mHiddenServiceStatus ; + } + std::cerr << "Done." << std::endl; + mHiddenServiceStatus = HIDDEN_SERVICE_STATUS_REQUESTED ; + return mHiddenServiceStatus ; + } + + case HIDDEN_SERVICE_STATUS_REQUESTED: { + QList hidden_services = mTorManager->control()->hiddenServices(); + + if(hidden_services.empty()) + { + std::cerr << "Not ready yet." << std::endl; + return mHiddenServiceStatus ; + } + else + { + if(mHiddenService == NULL) + mHiddenService = *(hidden_services.begin()) ; + + Tor::HiddenService::Status hss = mHiddenService->status(); + + std::cerr << "New service acquired. Status is " << hss ; + + if(hss == Tor::HiddenService::Online) + { + mHiddenServiceStatus = HIDDEN_SERVICE_STATUS_OK ; + std::cerr << ": published and running!" << std::endl; + + return mHiddenServiceStatus ; + } + else + { + std::cerr << ": not ready yet." << std::endl; + return mHiddenServiceStatus ; + } + } + } + case HIDDEN_SERVICE_STATUS_OK : + std::cerr << "New service acquired." << std::endl; + return mHiddenServiceStatus ; + } +} + diff --git a/retroshare-gui/src/gui/TorControl/TorControlWindow.h b/retroshare-gui/src/gui/TorControl/TorControlWindow.h new file mode 100644 index 000000000..c4e8ce522 --- /dev/null +++ b/retroshare-gui/src/gui/TorControl/TorControlWindow.h @@ -0,0 +1,48 @@ +#include "ui_TorControlWindow.h" + +class QTcpServer ; + +namespace Tor { + class HiddenService ; + class TorManager ; +} + +class TorControlDialog: public QWidget, public Ui::TorControlDialog +{ + Q_OBJECT + +public: + TorControlDialog(Tor::TorManager *tm,QWidget *parent =NULL); + + enum TorStatus { + TOR_STATUS_UNKNOWN = 0x00, + TOR_STATUS_OK = 0x01, + TOR_STATUS_FAIL = 0x02 + }; + + enum HiddenServiceStatus { + HIDDEN_SERVICE_STATUS_UNKNOWN = 0x00, // no information known. + HIDDEN_SERVICE_STATUS_FAIL = 0x01, // some error occurred + HIDDEN_SERVICE_STATUS_REQUESTED = 0x02, // one service at least has been requested. Still being tested. + HIDDEN_SERVICE_STATUS_OK = 0x03 // one service responds and has been tested + }; + + // Should be called multiple times in a loop until it returns something else than *_UNKNOWN + + TorStatus checkForTor(QString& error_msg) ; + HiddenServiceStatus checkForHiddenService() ; + +protected slots: + void showLog(); + void statusChanged(); + void onIncomingConnection(); + +private: + QString mErrorMsg ; + HiddenServiceStatus mHiddenServiceStatus ; + + Tor::TorManager *mTorManager ; + Tor::HiddenService *mHiddenService ; + + QTcpServer *mIncomingServer ; +}; diff --git a/retroshare-gui/src/gui/TorControl/TorControlWindow.ui b/retroshare-gui/src/gui/TorControl/TorControlWindow.ui new file mode 100644 index 000000000..602146641 --- /dev/null +++ b/retroshare-gui/src/gui/TorControl/TorControlWindow.ui @@ -0,0 +1,134 @@ + + + TorControlDialog + + + + 0 + 0 + 600 + 228 + + + + + 0 + 0 + + + + Dialog + + + + + + + 75 + true + + + + Setting up Tor... + + + Qt::AlignCenter + + + + + + + + + + + + :/icons/tor-logo.png + + + false + + + + + + + + + Tor status: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Unknown + + + + + + + Not started + + + + + + + Hidden service address: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Tor bootstrap status: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Not set + + + + + + + Onion address: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Not set + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/WikiPoos/WikiAddDialog.ui b/retroshare-gui/src/gui/WikiPoos/WikiAddDialog.ui index 9de9e6a3e..28f2e41ce 100644 --- a/retroshare-gui/src/gui/WikiPoos/WikiAddDialog.ui +++ b/retroshare-gui/src/gui/WikiPoos/WikiAddDialog.ui @@ -51,7 +51,7 @@
- + Travel @@ -110,7 +110,7 @@ - + 0 @@ -135,7 +135,7 @@ - + 0 @@ -170,7 +170,7 @@ - + 0 @@ -195,7 +195,7 @@ - + 0 @@ -266,6 +266,13 @@ + + + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
+
diff --git a/retroshare-gui/src/gui/WikiPoos/WikiDialog.ui b/retroshare-gui/src/gui/WikiPoos/WikiDialog.ui index 7a86e6488..056e0a859 100644 --- a/retroshare-gui/src/gui/WikiPoos/WikiDialog.ui +++ b/retroshare-gui/src/gui/WikiPoos/WikiDialog.ui @@ -50,7 +50,7 @@ 510 - + 0 @@ -63,33 +63,48 @@ 0 - - - - - 0 - 150 - + + + + Qt::Vertical - - - - - - - Page Name + + + + 0 + 0 + - - - - Page Id + + + 0 + 150 + - - - - Orig Id + + + + + 0 + 0 + - + + + Page Name + + + + + Page Id + + + + + Orig Id + + + diff --git a/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.cpp b/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.cpp index 077641621..8dd0404d6 100644 --- a/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.cpp +++ b/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.cpp @@ -56,18 +56,18 @@ WikiEditDialog::WikiEditDialog(QWidget *parent) { ui.setupUi(this); - connect(ui.pushButton_Cancel, SIGNAL( clicked( void ) ), this, SLOT( cancelEdit( void ) ) ); - connect(ui.pushButton_Revert, SIGNAL( clicked( void ) ), this, SLOT( revertEdit( void ) ) ); - connect(ui.pushButton_Submit, SIGNAL( clicked( void ) ), this, SLOT( submitEdit( void ) ) ); - connect(ui.pushButton_Preview, SIGNAL( clicked( void ) ), this, SLOT( previewToggle( void ) ) ); - connect(ui.pushButton_History, SIGNAL( clicked( void ) ), this, SLOT( historyToggle( void ) ) ); - connect(ui.toolButton_Show, SIGNAL( clicked( void ) ), this, SLOT( detailsToggle( void ) ) ); - connect(ui.toolButton_Hide, SIGNAL( clicked( void ) ), this, SLOT( detailsToggle( void ) ) ); - connect(ui.textEdit, SIGNAL( textChanged( void ) ), this, SLOT( textChanged( void ) ) ); - connect(ui.checkBox_OldHistory, SIGNAL( clicked( void ) ), this, SLOT( oldHistoryChanged( void ) ) ); - connect(ui.checkBox_Merge, SIGNAL( clicked( void ) ), this, SLOT( mergeModeToggle( void ) ) ); - connect(ui.pushButton_Merge, SIGNAL( clicked( void ) ), this, SLOT( generateMerge( void ) ) ); - connect(ui.treeWidget_History, SIGNAL( itemSelectionChanged( void ) ), this, SLOT( historySelected( void ) ) ); + connect(ui.pushButton_Cancel, SIGNAL( clicked() ), this, SLOT( cancelEdit() ) ); + connect(ui.pushButton_Revert, SIGNAL( clicked() ), this, SLOT( revertEdit() ) ); + connect(ui.postButton, SIGNAL( clicked() ), this, SLOT( submitEdit() ) ); + connect(ui.pushButton_Preview, SIGNAL( clicked() ), this, SLOT( previewToggle() ) ); + connect(ui.pushButton_History, SIGNAL( clicked() ), this, SLOT( historyToggle() ) ); + connect(ui.toolButton_Show, SIGNAL( clicked() ), this, SLOT( detailsToggle() ) ); + connect(ui.toolButton_Hide, SIGNAL( clicked() ), this, SLOT( detailsToggle() ) ); + connect(ui.textEdit, SIGNAL( textChanged() ), this, SLOT( textChanged() ) ); + connect(ui.checkBox_OldHistory, SIGNAL( clicked() ), this, SLOT( oldHistoryChanged() ) ); + connect(ui.checkBox_Merge, SIGNAL( clicked() ), this, SLOT( mergeModeToggle() ) ); + connect(ui.pushButton_Merge, SIGNAL( clicked() ), this, SLOT( generateMerge() ) ); + connect(ui.treeWidget_History, SIGNAL( itemSelectionChanged() ), this, SLOT( historySelected() ) ); mWikiQueue = new TokenQueue(rsWiki->getTokenService(), this); @@ -125,7 +125,7 @@ void WikiEditDialog::textChanged() mTextChanged = true; ui.pushButton_Revert->setEnabled(true); - ui.pushButton_Submit->setEnabled(true); + ui.postButton->setEnabled(true); ui.label_Status->setText("Modified"); // Disable Selection in Edit History. @@ -142,7 +142,7 @@ void WikiEditDialog::textReset() mTextChanged = false; ui.pushButton_Revert->setEnabled(false); - ui.pushButton_Submit->setEnabled(false); + ui.postButton->setEnabled(false); ui.label_Status->setText("Original"); // Enable Selection in Edit History. @@ -434,11 +434,11 @@ void WikiEditDialog::setNewPage() void WikiEditDialog::setRepublishMode(RsGxsMessageId &origMsgId) { - mRepublishMode = true; - mRepublishOrigId = origMsgId; - ui.pushButton_Submit->setText(tr("Republish")); + mRepublishMode = true; + mRepublishOrigId = origMsgId; + ui.postButton->setText(tr("Republish")); /* No need for for REQUIRED ID */ - ui.comboBox_IdChooser->loadIds(0, RsGxsId()); + ui.comboBox_IdChooser->loadIds(0, RsGxsId()); } diff --git a/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.ui b/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.ui index c971c1398..5433f4a7f 100644 --- a/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.ui +++ b/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.ui @@ -13,7 +13,7 @@ - + 0 @@ -40,14 +40,14 @@
- + QFrame::StyledPanel QFrame::Raised - + @@ -63,7 +63,7 @@ Page Edit History - + @@ -109,18 +109,18 @@ - + QFrame::StyledPanel QFrame::Raised - + - + 6 @@ -132,7 +132,7 @@ - + Qt::Vertical @@ -157,7 +157,7 @@ - + 0 @@ -177,7 +177,7 @@ Wiki Group: - frame + formFrame @@ -254,16 +254,23 @@
- + + + + 15 + 75 + true + + History - + Qt::Horizontal @@ -298,7 +305,7 @@ - + @@ -314,7 +321,7 @@ - + Qt::Horizontal @@ -327,7 +334,14 @@ - + + + + 12 + 75 + true + + Submit @@ -357,8 +371,6 @@
gui/gxs/GxsIdChooser.h
- - - + diff --git a/retroshare-gui/src/gui/advsearch/AdvancedSearchDialog.ui b/retroshare-gui/src/gui/advsearch/AdvancedSearchDialog.ui index 5926e8d94..9427358cd 100644 --- a/retroshare-gui/src/gui/advsearch/AdvancedSearchDialog.ui +++ b/retroshare-gui/src/gui/advsearch/AdvancedSearchDialog.ui @@ -6,8 +6,8 @@ 0 0 - 838 - 130 + 297 + 138 @@ -17,7 +17,7 @@ :/images/logo/logo_16.png:/images/logo/logo_16.png - + 0 @@ -31,20 +31,14 @@ 0 - - - - 0 - 130 - - + QFrame::StyledPanel QFrame::Raised - + @@ -53,12 +47,6 @@ 1 - - - 800 - 60 - - false @@ -68,59 +56,15 @@ Qt::AlignJustify|Qt::AlignTop - + 0 - - 2 - - - 2 - - - 2 - - - 2 - - - - - - 1 - 0 - - - - - 600 - 26 - - - - false - - - - - - - Qt::Vertical - - - - 20 - 9 - - - - - + 6 @@ -142,8 +86,8 @@ Add a further search criterion. - - :/images/add_24x24.png:/images/add_24x24.png + + :/icons/png/add.png:/icons/png/add.png @@ -174,16 +118,10 @@ - + Qt::Horizontal - - - 381 - 27 - - @@ -203,7 +141,7 @@
- + 0 @@ -227,6 +165,7 @@ + diff --git a/retroshare-gui/src/gui/advsearch/advancedsearchdialog.cpp b/retroshare-gui/src/gui/advsearch/advancedsearchdialog.cpp index eb9b9ce83..da3d24057 100644 --- a/retroshare-gui/src/gui/advsearch/advancedsearchdialog.cpp +++ b/retroshare-gui/src/gui/advsearch/advancedsearchdialog.cpp @@ -21,97 +21,79 @@ *******************************************************************************/ #include "advancedsearchdialog.h" + #include "gui/common/FilesDefs.h" +#include + AdvancedSearchDialog::AdvancedSearchDialog(QWidget * parent) : QDialog (parent) { - setupUi(this); - dialogLayout = this->layout(); - metrics = new QFontMetrics(this->font()); + setupUi(this); - // the list of expressions - expressions = new QList(); + QFontMetrics metrics = QFontMetrics(this->font()); + searchCriteriaBox_VL->setContentsMargins(2, metrics.height()/2, 2, 2); + addExprButton->setIconSize(QSize(metrics.height(),metrics.height())*1.5); + resetButton->setIconSize(QSize(metrics.height(),metrics.height())*1.5); - // a area for holding the objects - expressionsLayout = new QVBoxLayout(); - expressionsLayout->setSpacing(0); - expressionsLayout->setMargin(0); - expressionsLayout->setObjectName(QString::fromUtf8("expressionsLayout")); - expressionsFrame->setSizePolicy(QSizePolicy::MinimumExpanding, - QSizePolicy::MinimumExpanding); - expressionsFrame->setLayout(expressionsLayout); - - // we now add the first expression widgets to the dialog via a vertical - // layout - reset();//addNewExpression(); + // Save current default size as minimum to only add expresssions size to it. + this->adjustSize(); + this->setMinimumSize(this->size()); - connect (this->addExprButton, SIGNAL(clicked()), - this, SLOT(addNewExpression())); - connect (this->resetButton, SIGNAL(clicked()), - this, SLOT(reset())); - connect(this->executeButton, SIGNAL(clicked()), - this, SLOT(prepareSearch())); + // the list of expressions + expressions = new QList(); - addExprButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/add.png")); + // we now add the first expression widgets to the dialog + reset();//addNewExpression(); + + connect ( addExprButton, SIGNAL(clicked()) + , this, SLOT(addNewExpression())); + connect ( resetButton, SIGNAL(clicked()) + , this, SLOT(reset())); + connect ( searchButton, SIGNAL(clicked()) + , this, SLOT(prepareSearch())); } void AdvancedSearchDialog::addNewExpression() { - int sizeChange = metrics->height() + 26; + ExpressionWidget *expr = new ExpressionWidget(searchCriteriaBox, (expressions->size() == 0)); + expressions->append(expr); - ExpressionWidget *expr; - if (expressions->size() == 0) - { - //create an initial expression - expr = new ExpressionWidget(expressionsFrame, true); - } else { - expr = new ExpressionWidget(expressionsFrame); - } - - expressions->append(expr); - expressionsLayout->addWidget(expr, 1, Qt::AlignLeft); - - - connect(expr, SIGNAL(signalDelete(ExpressionWidget*)), - this, SLOT(deleteExpression(ExpressionWidget*))); - - //expressionsLayout->invalidate(); - //searchCriteriaBox->setMinimumSize(searchCriteriaBox->minimumWidth(), - // searchCriteriaBox->minimumHeight() + sizeChange); - //searchCriteriaBox->adjustSize(); - expressionsFrame->adjustSize(); - this->setMinimumSize(this->minimumWidth(), this->minimumHeight()+sizeChange); - this->adjustSize(); + searchCriteriaBox_VL->addWidget(expr); + searchCriteriaBox_VL->setAlignment(Qt::AlignTop); + expr->adjustSize(); + if (searchCriteriaBox->minimumWidth() < expr->minimumWidth()) + searchCriteriaBox->setMinimumWidth(expr->minimumWidth()); + QSize exprHeight = QSize(0,expr->height()); + + connect( expr, SIGNAL(signalDelete(ExpressionWidget*)) + , this, SLOT(deleteExpression(ExpressionWidget*)) ); + + this->setMinimumSize(this->minimumSize() + exprHeight); + int marg = gradFrame_GL->contentsMargins().left()+gradFrame_GL->contentsMargins().right(); + marg += this->contentsMargins().left()+this->contentsMargins().right(); + if (this->minimumWidth() < (searchCriteriaBox->minimumWidth()+marg)) + this->setMinimumWidth(searchCriteriaBox->minimumWidth()+marg); } void AdvancedSearchDialog::deleteExpression(ExpressionWidget* expr) { - int sizeChange = metrics->height() + 26; - - expressions->removeAll(expr); - expr->hide(); - expressionsLayout->removeWidget(expr); - delete expr; - - expressionsLayout->invalidate(); - //searchCriteriaBox->setMinimumSize(searchCriteriaBox->minimumWidth(), - // searchCriteriaBox->minimumHeight() - sizeChange); - //searchCriteriaBox->adjustSize(); - expressionsFrame->adjustSize(); - this->setMinimumSize(this->minimumWidth(), this->minimumHeight()-sizeChange); - this->adjustSize(); + QSize exprHeight = QSize(0,expr->height()); + + expressions->removeAll(expr); + expr->hide(); + searchCriteriaBox_VL->removeWidget(expr); + delete expr; + + this->setMinimumSize(this->minimumSize() - exprHeight); + this->resize(this->size() - exprHeight); } void AdvancedSearchDialog::reset() { - ExpressionWidget *expr; while (!expressions->isEmpty()) - { - expr = expressions->takeLast(); - deleteExpression(expr); - } + deleteExpression(expressions->takeLast()); // now add a new default expressions addNewExpression(); @@ -129,7 +111,6 @@ RsRegularExpression::Expression * AdvancedSearchDialog::getRsExpr() // process the special case: first expression wholeExpression = expressions->at(0)->getRsExpression(); - // iterate through the items in elements and #warning Phenom (2017-07-21): I don t know if it is a real memLeak for wholeExpression. If not remove this warning and add a comment how it is deleted. @@ -140,21 +121,20 @@ RsRegularExpression::Expression * AdvancedSearchDialog::getRsExpr() wholeExpression = new RsRegularExpression::CompoundExpression(expressions->at(i)->getOperator(), wholeExpression, expressions->at(i)->getRsExpression()); - } + } return wholeExpression; } QString AdvancedSearchDialog::getSearchAsString() { QString str = expressions->at(0)->toString(); - // iterate through the items in elements and for (int i = 1; i < expressions->size(); ++i) { // extract the expression information and compound it with the // first expression str += QString(" ") + expressions->at(i)->toString(); - } + } return str; } diff --git a/retroshare-gui/src/gui/advsearch/advancedsearchdialog.h b/retroshare-gui/src/gui/advsearch/advancedsearchdialog.h index 317809e6f..25ea74129 100644 --- a/retroshare-gui/src/gui/advsearch/advancedsearchdialog.h +++ b/retroshare-gui/src/gui/advsearch/advancedsearchdialog.h @@ -22,13 +22,10 @@ #ifndef _AdvancedSearch_h_ #define _AdvancedSearch_h_ -#include -#include -#include -#include -#include #include "ui_AdvancedSearchDialog.h" + #include "expressionwidget.h" + #include class AdvancedSearchDialog : public QDialog, public Ui::AdvancedSearchDialog @@ -49,10 +46,7 @@ private slots: void prepareSearch(); private: - QLayout * dialogLayout; - QVBoxLayout * expressionsLayout; QList * expressions; - QFontMetrics * metrics; }; #endif // _AdvancedSearch_h_ diff --git a/retroshare-gui/src/gui/advsearch/expressionwidget.cpp b/retroshare-gui/src/gui/advsearch/expressionwidget.cpp index 2b6ad3b2e..9387f951e 100644 --- a/retroshare-gui/src/gui/advsearch/expressionwidget.cpp +++ b/retroshare-gui/src/gui/advsearch/expressionwidget.cpp @@ -20,108 +20,62 @@ * * *******************************************************************************/ #include "expressionwidget.h" +#include "util/QtVersion.h" -ExpressionWidget::ExpressionWidget(QWidget * parent, bool initial) : QWidget(parent) +ExpressionWidget::ExpressionWidget(QWidget * parent, bool initial) + : QWidget(parent) + , isFirst (initial), inRangedConfig(false) + , searchType (NameSearch) // the default search type { - setupUi(this); - - inRangedConfig = false; - - // the default search type - searchType = NameSearch; - - exprLayout = this->layout(); - - exprOpFrame->setLayout (createLayout()); - exprTermFrame->setLayout (createLayout()); - exprConditionFrame->setLayout (createLayout()); - exprParamFrame->setLayout (createLayout()); - exprParamFrame->setSizePolicy(QSizePolicy::MinimumExpanding, - QSizePolicy::Fixed); - - elements = new QList(); - - exprOpElem = new ExprOpElement(); - exprOpFrame->layout()->addWidget(exprOpElem); - elements->append(exprOpElem); - - exprTermElem = new ExprTermsElement(); - exprTermFrame->layout()->addWidget(exprTermElem); - elements->append(exprTermElem); - connect (exprTermElem, SIGNAL(currentIndexChanged(int)), - this, SLOT (adjustExprForTermType(int))); - - exprCondElem = new ExprConditionElement(searchType); - exprConditionFrame->layout()->addWidget(exprCondElem); - elements->append(exprCondElem); - connect (exprCondElem, SIGNAL (currentIndexChanged(int)), - this, SLOT (adjustExprForConditionType(int))); - - exprParamElem= new ExprParamElement(searchType); - exprParamFrame->layout()->addWidget(exprParamElem); - elements->append(exprParamElem); - - // set up the default search: a search on name - adjustExprForTermType(searchType); - isFirst = initial; - deleteExprButton ->setVisible(!isFirst); - exprOpElem ->setVisible(!isFirst); - exprTermFrame ->show(); - exprConditionFrame ->show(); - exprParamFrame ->show(); - - // connect the delete button signal - connect (deleteExprButton, SIGNAL (clicked()), - this, SLOT(deleteExpression())); - - this->show(); -} + setupUi(this); -QLayout * ExpressionWidget::createLayout(QWidget * parent) -{ - QHBoxLayout * hboxLayout; - if (parent == 0) - { - hboxLayout = new QHBoxLayout(); - } else { - hboxLayout = new QHBoxLayout(parent); - } - hboxLayout->setSpacing(0); - hboxLayout->setMargin(0); - return hboxLayout; + connect (exprTermElem, SIGNAL(currentIndexChanged(int)), + this, SLOT (adjustExprForTermType(int))); + + connect (exprCondElem, SIGNAL (currentIndexChanged(int)), + this, SLOT (adjustExprForConditionType(int))); + + // set up the default search: a search on name + adjustExprForTermType(searchType); + exprOpElem ->setVisible(!isFirst); + deleteExprButton ->setVisible(!isFirst); + + // connect the delete button signal + connect (deleteExprButton, SIGNAL (clicked()), + this, SLOT(deleteExpression()) ); + + this->show(); } bool ExpressionWidget::isStringSearchExpression() { - return (searchType == NameSearch || searchType == PathSearch - || searchType == ExtSearch || searchType == HashSearch); + return ( searchType == NameSearch || searchType == PathSearch + || searchType == ExtSearch || searchType == HashSearch); } void ExpressionWidget::adjustExprForTermType(int index) { - ExprSearchType type = GuiExprElement::TermsIndexMap[index]; - searchType = type; - - // now adjust the relevant elements - // the condition combobox - exprCondElem->adjustForSearchType(type); - - // the parameter expression: can be a date, 1-2 edit fields - // or a size with units etc - exprParamElem->adjustForSearchType(type); - exprParamFrame->adjustSize(); - - exprLayout->invalidate(); - this->adjustSize(); + ExprSearchType type = GuiExprElement::TermsIndexMap[index]; + searchType = type; + + // now adjust the relevant elements + // the condition combobox + exprCondElem->adjustForSearchType(type); + + // the parameter expression: can be a date, 1-2 edit fields + // or a size with units etc + exprParamElem->adjustForSearchType(type); + + this->setMinimumWidth( exprOpElem->width()+exprTermElem->width() + + exprCondElem->width()+exprParamElem->width() + + deleteExprButton->width() ); } void ExpressionWidget::adjustExprForConditionType(int newCondition) { - // we adjust the appearance for a ranged selection - inRangedConfig = (newCondition == GuiExprElement::RANGE_INDEX); - exprParamElem->setRangedSearch(inRangedConfig); - exprParamFrame->layout()->invalidate(); - exprParamFrame->adjustSize(); + // we adjust the appearance for a ranged selection + inRangedConfig = (newCondition == GuiExprElement::RANGE_INDEX); + exprParamElem->setRangedSearch(inRangedConfig); } void ExpressionWidget::deleteExpression() @@ -156,7 +110,7 @@ RsRegularExpression::Expression* ExpressionWidget::getRsExpression() if (isStringSearchExpression()) { QString txt = exprParamElem->getStrSearchValue(); - QStringList words = txt.split(" ", QString::SkipEmptyParts); + QStringList words = txt.split(" ", QtSkipEmptyParts); for (int i = 0; i < words.size(); ++i) wordList.push_back(words.at(i).toUtf8().constData()); } else if (inRangedConfig){ @@ -165,12 +119,12 @@ RsRegularExpression::Expression* ExpressionWidget::getRsExpression() highVal = exprParamElem->getIntHighValue(); if (lowVal >highVal) { - lowVal = lowVal^highVal; // csoler: wow, that is some style! - highVal = lowVal^highVal; - lowVal = lowVal^highVal; + auto tmp=lowVal; + lowVal = highVal; + highVal = tmp; } } - + switch (searchType) { case NameSearch: @@ -193,11 +147,33 @@ RsRegularExpression::Expression* ExpressionWidget::getRsExpression() wordList); break; case DateSearch: - if (inRangedConfig) { - expr = new RsRegularExpression::DateExpression(exprCondElem->getRelOperator(), checkedConversion(lowVal), checkedConversion(highVal)); - } else { - expr = new RsRegularExpression::DateExpression(exprCondElem->getRelOperator(), checkedConversion(exprParamElem->getIntValue())); - } + switch(exprCondElem->getRelOperator()) // we need to convert expressions so that the delta is 1 day (i.e. 86400 secs) + { + // The conditions below account for 3 things: + // - the swap between variables in rsexpr.h:214 + // - the swap of variables when calling getRelOperator() (See guiexprelement.cpp:166) + // - the fact that some comparisions in the unit of days may add 86400 seconds. + + default: + case RsRegularExpression::Equals: + expr = new RsRegularExpression::DateExpression(RsRegularExpression::InRange, checkedConversion(exprParamElem->getIntValue()), checkedConversion(86400+exprParamElem->getIntValue())); + break; + case RsRegularExpression::InRange: + expr = new RsRegularExpression::DateExpression(RsRegularExpression::InRange, checkedConversion(lowVal), 86400+checkedConversion(highVal)); + break; + case RsRegularExpression::Greater: // means we expect file.date() < some day D. So file.date() < D, meaning Exp=Greater + expr = new RsRegularExpression::DateExpression(RsRegularExpression::Greater,checkedConversion(exprParamElem->getIntValue())); + break; + case RsRegularExpression::SmallerEquals: // means we expect file.date() >= some day D. So file.date() >= D, meaning Exp=SmallerEquals + expr = new RsRegularExpression::DateExpression(RsRegularExpression::SmallerEquals,checkedConversion(exprParamElem->getIntValue())); + break; + case RsRegularExpression::Smaller: // means we expect file.date() > some day D. So file.date() >= D+86400, meaning Exp=SmallerEquals + expr = new RsRegularExpression::DateExpression(RsRegularExpression::SmallerEquals, checkedConversion(86400+exprParamElem->getIntValue()-1)); + break; + case RsRegularExpression::GreaterEquals: // means we expect file.date() <= some day D. So file.date() < D+86400, meaning Exp=Greater + expr = new RsRegularExpression::DateExpression(RsRegularExpression::Greater, checkedConversion(86400+exprParamElem->getIntValue())); + break; + } break; case PopSearch: if (inRangedConfig) { @@ -208,20 +184,42 @@ RsRegularExpression::Expression* ExpressionWidget::getRsExpression() break; case SizeSearch: if (inRangedConfig) - { - if(lowVal >= (uint64_t)(1024*1024*1024) || highVal >= (uint64_t)(1024*1024*1024)) - expr = new RsRegularExpression::SizeExpressionMB(exprCondElem->getRelOperator(), (int)(lowVal / (1024*1024)), (int)(highVal / (1024*1024))); - else - expr = new RsRegularExpression::SizeExpression(exprCondElem->getRelOperator(), lowVal, highVal); - } - else - { - uint64_t s = exprParamElem->getIntValue() ; + { + if(lowVal >= (uint64_t)(1024*1024*1024) || highVal >= (uint64_t)(1024*1024*1024)) + expr = new RsRegularExpression::SizeExpressionMB(exprCondElem->getRelOperator(), (int)(lowVal / (1024*1024)), (int)(highVal / (1024*1024))); + else + expr = new RsRegularExpression::SizeExpression(exprCondElem->getRelOperator(), lowVal, highVal); + } + else + { + uint64_t s = exprParamElem->getIntValue() ; + auto cond = exprCondElem->getRelOperator(); + bool MB = false; - if(s >= (uint64_t)(1024*1024*1024)) - expr = new RsRegularExpression::SizeExpressionMB(exprCondElem->getRelOperator(), (int)(s/(1024*1024))) ; - else - expr = new RsRegularExpression::SizeExpression(exprCondElem->getRelOperator(), (int)s) ; + if(s >= (uint64_t)(1024*1024*1024)) + { + MB=true; + s >>= 20; + } + + // Specific case for Equal operator, which we convert to a range, so as to avoid matching arbitrary digits + + if(cond == RsRegularExpression::Equals) + { + // Now compute a proper interval. There is no optimal solution, so we aim for the simplest: add/remove 20% of the initial value. + + if(MB) + expr = new RsRegularExpression::SizeExpressionMB(RsRegularExpression::InRange, (int)(s*0.8) , (int)(s*1.2)); + else + expr = new RsRegularExpression::SizeExpression(RsRegularExpression::InRange, (int)(s*0.8) , (int)(s*1.2)); + } + else + { + if(MB) + expr = new RsRegularExpression::SizeExpressionMB(cond, (int)s); + else + expr = new RsRegularExpression::SizeExpression(cond, (int)s) ; + } } break; }; diff --git a/retroshare-gui/src/gui/advsearch/expressionwidget.h b/retroshare-gui/src/gui/advsearch/expressionwidget.h index 40ef3ec47..109ea2a35 100644 --- a/retroshare-gui/src/gui/advsearch/expressionwidget.h +++ b/retroshare-gui/src/gui/advsearch/expressionwidget.h @@ -21,14 +21,16 @@ *******************************************************************************/ #ifndef _ExpressionWidget_h_ #define _ExpressionWidget_h_ -#include -#include -#include -#include -#include "guiexprelement.h" #include "ui_expressionwidget.h" +#include "guiexprelement.h" + +#include + +#include + +#include /** Represents an Advanced Search GUI Expression object which acts as a container @@ -74,20 +76,10 @@ private slots: private: - QLayout * createLayout(QWidget* parent = 0); - bool isStringSearchExpression(); - - QList * elements; - QLayout * exprLayout; - ExprOpElement * exprOpElem; - ExprTermsElement * exprTermElem; - ExprConditionElement * exprCondElem; - ExprParamElement* exprParamElem; - - bool inRangedConfig; bool isFirst; + bool inRangedConfig; ExprSearchType searchType; }; diff --git a/retroshare-gui/src/gui/advsearch/expressionwidget.ui b/retroshare-gui/src/gui/advsearch/expressionwidget.ui index 9e7d2d780..5b8584f00 100644 --- a/retroshare-gui/src/gui/advsearch/expressionwidget.ui +++ b/retroshare-gui/src/gui/advsearch/expressionwidget.ui @@ -2,104 +2,33 @@ ExpressionWidget - - - 0 - 0 - 800 - 34 - - - + 0 0 - - - 800 - 30 - - - - - 16777215 - 55 - - Expression Widget - - 6 - - - 6 - - + + + + + + + + + + - + 0 0 - - - 90 - 26 - - - - - - - - - 0 - 0 - - - - - 100 - 26 - - - - - - - - - 0 - 0 - - - - - 180 - 26 - - - - - - - - - 1 - 0 - - - - - 350 - 26 - - @@ -113,21 +42,34 @@ - - - - Qt::Horizontal - - - - 0 - 30 - - - -
+ + + ExprOpElement + QFrame +
gui/advsearch/guiexprelement.h
+ 1 +
+ + ExprTermsElement + QFrame +
gui/advsearch/guiexprelement.h
+ 1 +
+ + ExprConditionElement + QFrame +
gui/advsearch/guiexprelement.h
+ 1 +
+ + ExprParamElement + QFrame +
gui/advsearch/guiexprelement.h
+ 1 +
+
diff --git a/retroshare-gui/src/gui/advsearch/guiexprelement.cpp b/retroshare-gui/src/gui/advsearch/guiexprelement.cpp index 44d1350a4..5dd138186 100644 --- a/retroshare-gui/src/gui/advsearch/guiexprelement.cpp +++ b/retroshare-gui/src/gui/advsearch/guiexprelement.cpp @@ -21,14 +21,10 @@ *******************************************************************************/ #include "guiexprelement.h" -#define STR_FIELDS_MIN_WIDTH 200 -#define SIZE_FIELDS_MIN_WIDTH 80 -#define DATE_FIELDS_MIN_WIDTH 100 -#define FIELDS_MIN_HEIGHT 26 - -#define LOGICAL_OP_CB_WIDTH 70 -#define STD_CB_WIDTH 90 -#define CONDITION_CB_WIDTH 170 +#define STR_FIELDS_MIN_WFACTOR 20.0 +#define SIZE_FIELDS_MIN_WFACTOR 8.0 +#define DATE_FIELDS_MIN_WFACTOR 10.0 +#define FIELDS_MIN_HFACTOR 1.2 const int GuiExprElement::AND_INDEX = 0; const int GuiExprElement::OR_INDEX = 1; @@ -37,10 +33,10 @@ const int GuiExprElement::XOR_INDEX = 2; const int GuiExprElement::NAME_INDEX = 0; const int GuiExprElement::PATH_INDEX = 1; const int GuiExprElement::EXT_INDEX = 2; -const int GuiExprElement::HASH_INDEX = 3; -/*const int GuiExprElement::KEYWORDS_INDEX = ???; -const int GuiExprElement::COMMENTS_INDEX = ???; -const int GuiExprElement::META_INDEX = ???;*/ +const int GuiExprElement::HASH_INDEX = 3; +//const int GuiExprElement::KEYWORDS_INDEX = ???; +//const int GuiExprElement::COMMENTS_INDEX = ???; +//const int GuiExprElement::META_INDEX = ???; const int GuiExprElement::DATE_INDEX = 4; const int GuiExprElement::SIZE_INDEX = 5; const int GuiExprElement::POP_INDEX = 6; @@ -76,14 +72,13 @@ bool GuiExprElement::initialised = false; GuiExprElement::GuiExprElement(QWidget * parent) - : QWidget(parent) + : QFrame(parent), searchType(NameSearch) { - if (!GuiExprElement::initialised) - { - initialiseOptionsLists(); - } - searchType = NameSearch; + if (!GuiExprElement::initialised) + initialiseOptionsLists(); + setObjectName("trans_InternalFrame"); + createLayout(this); } @@ -96,7 +91,7 @@ void GuiExprElement::initialiseOptionsLists() const QString NAME = tr("Name"); const QString PATH = tr("Path"); const QString EXT = tr("Extension"); - const QString HASH = tr("Hash"); + const QString HASH = tr("Hash"); //const QString KEYWORDS= tr("Keywords"); //const QString COMMENTS= tr("Comments"); //const QString META = tr("Meta"); @@ -128,7 +123,7 @@ void GuiExprElement::initialiseOptionsLists() //GuiExprElement::searchTermsOptionsList.append(META); GuiExprElement::searchTermsOptionsList.append(DATE); GuiExprElement::searchTermsOptionsList.append(SIZE); -// GuiExprElement::searchTermsOptionsList.append(POP); + //GuiExprElement::searchTermsOptionsList.append(POP); GuiExprElement::stringOptionsList.append(CONTAINS); GuiExprElement::stringOptionsList.append(CONTALL); @@ -160,18 +155,19 @@ void GuiExprElement::initialiseOptionsLists() /* W A R N I N G !!!! the cb elements correspond to their inverse rel op counterparts in rsexpr.h due to the nature of - the implementation.there + the implementation. For example consider "size greater than 100kb" selected in the GUI. The rsexpr.cc impl returns true if the CONDITION specified is greater than the file size passed as argument as rsexpr iterates through the files. So, the user wants files that are greater than 100kb but the impl returns - files where the condition is greater than the file size i.e. files whose size is less than or equal to the condition + files where the condition is greater than the file size i.e. files whose size is less than to the condition Therefore we invert the mapping of rel conditions here to match the behaviour of the impl. + Also the Equal nature of comparisons should be kept, since = is symmetric. */ - GuiExprElement::relConditionIndexMap[GuiExprElement::LT_INDEX] = RsRegularExpression::GreaterEquals; - GuiExprElement::relConditionIndexMap[GuiExprElement::LTE_INDEX] = RsRegularExpression::Greater; + GuiExprElement::relConditionIndexMap[GuiExprElement::LT_INDEX] = RsRegularExpression::Greater; + GuiExprElement::relConditionIndexMap[GuiExprElement::LTE_INDEX] = RsRegularExpression::GreaterEquals; GuiExprElement::relConditionIndexMap[GuiExprElement::EQUAL_INDEX] = RsRegularExpression::Equals; - GuiExprElement::relConditionIndexMap[GuiExprElement::GTE_INDEX] = RsRegularExpression::Smaller; - GuiExprElement::relConditionIndexMap[GuiExprElement::GT_INDEX] = RsRegularExpression::SmallerEquals; + GuiExprElement::relConditionIndexMap[GuiExprElement::GTE_INDEX] = RsRegularExpression::SmallerEquals; + GuiExprElement::relConditionIndexMap[GuiExprElement::GT_INDEX] = RsRegularExpression::Smaller; GuiExprElement::relConditionIndexMap[GuiExprElement::RANGE_INDEX] = RsRegularExpression::InRange; // the string to index map @@ -220,24 +216,29 @@ QStringList GuiExprElement::getConditionOptions(ExprSearchType t) return QStringList(); } -QHBoxLayout * GuiExprElement::createLayout(QWidget * parent) +QHBoxLayout * GuiExprElement::createLayout(QWidget * parent /*= nullptr*/) { - QHBoxLayout * hboxLayout; - if (parent == 0) - { - hboxLayout = new QHBoxLayout(); - } else { - hboxLayout = new QHBoxLayout(parent); - } + QHBoxLayout * hboxLayout = new QHBoxLayout(parent); hboxLayout->setMargin(0); hboxLayout->setSpacing(0); return hboxLayout; } +QSize GuiExprElement::getMinSize(float widthFactor/*=1*/, float heightFactor/*=1*/) +{ + QFontMetrics fm = QFontMetrics(font()); +#if QT_VERSION < QT_VERSION_CHECK(5,11,0) + QSize size = QSize(fm.width("_")*widthFactor, fm.height()*heightFactor); +#else + QSize size = QSize(fm.horizontalAdvance("_")*widthFactor, fm.height()*heightFactor); +#endif + return size; +} + bool GuiExprElement::isStringSearchExpression() { - return (searchType == NameSearch || searchType == PathSearch - || searchType == ExtSearch || searchType == HashSearch); + return (searchType == NameSearch || searchType == PathSearch + || searchType == ExtSearch || searchType == HashSearch); } @@ -245,14 +246,12 @@ bool GuiExprElement::isStringSearchExpression() /* *********** L O G I C A L O P E L E M E N T ******************/ /* ********************************************************************/ ExprOpElement::ExprOpElement(QWidget * parent) - : GuiExprElement(parent) + : GuiExprElement(parent) { - internalframe = new QFrame(this); - internalframe->setLayout(createLayout()); - cb = new QComboBox(this); - cb->setMinimumSize(LOGICAL_OP_CB_WIDTH, FIELDS_MIN_HEIGHT); - cb->addItems(GuiExprElement::exprOpsList); - internalframe->layout()->addWidget(cb); + cb = new RSComboBox(this); + cb->addItems(GuiExprElement::exprOpsList); + layout()->addWidget(cb); + setMinimumSize(cb->sizeHint()); } QString ExprOpElement::toString() @@ -271,16 +270,14 @@ RsRegularExpression::LogicalOperator ExprOpElement::getLogicalOperator() /* *********** T E R M S E L E M E N T ******************/ /* **********************************************************/ ExprTermsElement::ExprTermsElement(QWidget * parent) - : GuiExprElement(parent) + : GuiExprElement(parent) { - internalframe = new QFrame(this); - internalframe->setLayout(createLayout()); - cb = new QComboBox(this); - cb->setMinimumSize(STD_CB_WIDTH, FIELDS_MIN_HEIGHT); - connect (cb, SIGNAL(currentIndexChanged(int)), - this, SIGNAL(currentIndexChanged(int))); - cb->addItems(GuiExprElement::searchTermsOptionsList); - internalframe->layout()->addWidget(cb); + cb = new RSComboBox(this); + connect (cb, SIGNAL(currentIndexChanged(int)), + this, SIGNAL(currentIndexChanged(int))); + cb->addItems(GuiExprElement::searchTermsOptionsList); + layout()->addWidget(cb); + setMinimumSize(cb->sizeHint()); } QString ExprTermsElement::toString() { @@ -290,17 +287,15 @@ QString ExprTermsElement::toString() /* ******************************************************************/ /* *********** C O N D I T I O N E L E M E N T ******************/ /* ******************************************************************/ -ExprConditionElement::ExprConditionElement(ExprSearchType type, QWidget * parent) - : GuiExprElement(parent) +ExprConditionElement::ExprConditionElement(QWidget * parent, ExprSearchType type) + : GuiExprElement(parent) { - internalframe = new QFrame(this); - internalframe->setLayout(createLayout()); - cb = new QComboBox(this); - cb->setMinimumSize(CONDITION_CB_WIDTH, FIELDS_MIN_HEIGHT); - connect (cb, SIGNAL(currentIndexChanged(int)), - this, SIGNAL(currentIndexChanged(int))); - cb->addItems(getConditionOptions(type)); - internalframe->layout()->addWidget(cb); + cb = new RSComboBox(this); + connect (cb, SIGNAL(currentIndexChanged(int)), + this, SIGNAL(currentIndexChanged(int))); + cb->addItems(getConditionOptions(type)); + layout()->addWidget(cb); + setMinimumSize(cb->sizeHint()); } @@ -334,174 +329,189 @@ void ExprConditionElement::adjustForSearchType(ExprSearchType type) /* **********************************************************/ /* *********** P A R A M E L E M E N T ******************/ /* **********************************************************/ -ExprParamElement::ExprParamElement(ExprSearchType type, QWidget * parent) - : GuiExprElement(parent) +ExprParamElement::ExprParamElement(QWidget * parent, ExprSearchType type) + : GuiExprElement(parent), inRangedConfig(false) { - internalframe = new QFrame(this); - internalframe->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - internalframe->setLayout(createLayout()); - inRangedConfig = false; - searchType = type; - adjustForSearchType(type); + adjustForSearchType(type); } QString ExprParamElement::toString() { - QString str = ""; - if (isStringSearchExpression()) - { - str = QString("\"") + getStrSearchValue() + QString("\""); - // we don't bother with case if hash search - if (searchType != HashSearch) { - str += (ignoreCase() ? QString(" (ignore case)") - : QString(" (case sensitive)")); + QString str = ""; + if (isStringSearchExpression()) + { + str = QString("\"") + getStrSearchValue() + QString("\""); + // we don't bother with case if hash search + if (searchType != HashSearch) { + str += (ignoreCase() ? QString(" (ignore case)") + : QString(" (case sensitive)")); + } + } else + { + if (searchType == DateSearch) { + QDateEdit * dateEdit = findChild ("param1"); + str = dateEdit->text(); + if (inRangedConfig) + { + str += QString(" ") + tr("to") + QString(" "); + dateEdit = findChild ("param2"); + str += dateEdit->text(); + } + } else if (searchType == SizeSearch) + { + QLineEdit * lineEditSize = findChild("param1"); + str = ("" == lineEditSize->text()) ? "0" + : lineEditSize->text(); + RSComboBox * cb = findChild ("unitsCb1"); + str += QString(" ") + cb->itemText(cb->currentIndex()); + if (inRangedConfig) + { + str += QString(" ") + tr("to") + QString(" "); + lineEditSize = findChild("param2"); + str += ("" == lineEditSize->text()) ? "0" + : lineEditSize->text(); + cb = findChild ("unitsCb2"); + str += QString(" ") + cb->itemText(cb->currentIndex()); + } + } } - } else - { - if (searchType == DateSearch) { - QDateEdit * dateEdit = internalframe->findChild ("param1"); - str = dateEdit->text(); - if (inRangedConfig) - { - str += QString(" ") + tr("to") + QString(" "); - dateEdit = internalframe->findChild ("param2"); - str += dateEdit->text(); - } - } else if (searchType == SizeSearch) - { - QLineEdit * lineEditSize = internalframe->findChild("param1"); - str = ("" == lineEditSize->text()) ? "0" - : lineEditSize->text(); - QComboBox * cb = internalframe->findChild ("unitsCb1"); - str += QString(" ") + cb->itemText(cb->currentIndex()); - if (inRangedConfig) - { - str += QString(" ") + tr("to") + QString(" "); - lineEditSize = internalframe->findChild("param2"); - str += ("" == lineEditSize->text()) ? "0" - : lineEditSize->text(); - cb = internalframe->findChild ("unitsCb2"); - str += QString(" ") + cb->itemText(cb->currentIndex()); - } - } - } - return str; + return str; } +void clearLayout(QLayout *layout) { + if (layout == NULL) + return; + QLayoutItem *item; + while((item = layout->takeAt(0))) { + if (item->layout()) { + clearLayout(item->layout()); + delete item->layout(); + } + if (item->widget()) { + delete item->widget(); + } + delete item; + } +} void ExprParamElement::adjustForSearchType(ExprSearchType type) -{ - // record which search type is active - searchType = type; - QRegExp regExp("0|[1-9][0-9]*"); - numValidator = new QRegExpValidator(regExp, this); - QRegExp hexRegExp("[A-Fa-f0-9]*"); - hexValidator = new QRegExpValidator(hexRegExp, this); - - // remove all elements - QList children = internalframe->findChildren(); - QWidget* child; - QLayout * lay_out = internalframe->layout(); - while (!children.isEmpty()) - { - child = children.takeLast(); - child->hide(); - lay_out->removeWidget(child); - delete child; - } - delete lay_out; +{ + // record which search type is active + searchType = type; + QRegExp regExp("0|[1-9][0-9]*"); + numValidator = new QRegExpValidator(regExp, this); + QRegExp hexRegExp("[A-Fa-f0-9]*"); + hexValidator = new QRegExpValidator(hexRegExp, this); - QHBoxLayout* hbox = createLayout(); - internalframe->setLayout(hbox); - internalframe->setMinimumSize(320,26); + QHBoxLayout* hbox = static_cast(layout()); + clearLayout(hbox); + + setMinimumSize(getMinSize(STR_FIELDS_MIN_WFACTOR,FIELDS_MIN_HFACTOR) ); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + + if (isStringSearchExpression()) + { + // set up for default of a simple input field + QLineEdit* lineEdit = new QLineEdit(this); + lineEdit->setMinimumSize(getMinSize(STR_FIELDS_MIN_WFACTOR,FIELDS_MIN_HFACTOR)); + lineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + lineEdit->setObjectName("param1"); + hbox->addWidget(lineEdit); + + hbox->addSpacing(9); + + QCheckBox* icCb = new QCheckBox(tr("ignore case"), this); + icCb->setMinimumSize(getMinSize(icCb->text().length()+2,FIELDS_MIN_HFACTOR)); + icCb->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + icCb->setObjectName("ignoreCaseCB"); + icCb->setCheckState(Qt::Checked); + hbox->addWidget(icCb); + + // hex search specifics: hidden case sensitivity and hex validator + if (searchType == HashSearch) { + icCb->hide(); + lineEdit->setValidator(hexValidator); + } + setMinimumSize(lineEdit->minimumSize() + + QSize((searchType != HashSearch ? icCb->minimumWidth() : 0),0) ); + + } else if (searchType == DateSearch) + { + QDateEdit * dateEdit = new QDateEdit(QDate::currentDate(), this); + dateEdit->setMinimumSize(getMinSize(DATE_FIELDS_MIN_WFACTOR, FIELDS_MIN_HFACTOR)); + dateEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + dateEdit->setDisplayFormat(tr("yyyy-MM-dd")); + dateEdit->setObjectName("param1"); + dateEdit->setMinimumDate(QDate(1970, 1, 1)); + dateEdit->setMaximumDate(QDate(2099, 12,31)); + hbox->addWidget(dateEdit, Qt::AlignLeft); + hbox->addStretch(); + setMinimumSize(dateEdit->minimumSize()); + + } else if (searchType == SizeSearch) + { + QLineEdit * lineEdit = new QLineEdit(this); + lineEdit->setMinimumSize(getMinSize(SIZE_FIELDS_MIN_WFACTOR, FIELDS_MIN_HFACTOR)); + lineEdit->setMaximumSize(getMinSize(SIZE_FIELDS_MIN_WFACTOR, FIELDS_MIN_HFACTOR)); + lineEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + lineEdit->setObjectName("param1"); + lineEdit->setValidator(numValidator); + hbox->addWidget(lineEdit, Qt::AlignLeft); + + hbox->addSpacing(9); + + RSComboBox * cb = new RSComboBox(this); + cb->setObjectName("unitsCb1"); + cb->addItem(tr("KB"), QVariant(1024)); + cb->addItem(tr("MB"), QVariant(1024*1024)); + cb->addItem(tr("GB"), QVariant(1024*1024*1024)); + hbox->addWidget(cb); + hbox->addStretch(); + setMinimumSize(lineEdit->minimumSize() + QSize(9,0) + + QSize(cb->minimumWidth(),0) ); - if (isStringSearchExpression()) - { - // set up for default of a simple input field - QLineEdit* lineEdit = new QLineEdit(internalframe); - lineEdit->setMinimumSize(STR_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); - lineEdit->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - lineEdit->setObjectName("param1"); - hbox->addWidget(lineEdit); - hbox->addSpacing(9); - QCheckBox* icCb = new QCheckBox(tr("ignore case"), internalframe); - icCb->setObjectName("ignoreCaseCB"); - icCb->setCheckState(Qt::Checked); - // hex search specifics: hidden case sensitivity and hex validator - if (searchType == HashSearch) { - icCb->hide(); - lineEdit->setValidator(hexValidator); } - hbox->addWidget(icCb); - hbox->addStretch(); - - } else if (searchType == DateSearch) - { - QDateEdit * dateEdit = new QDateEdit(QDate::currentDate(), internalframe); - dateEdit->setMinimumSize(DATE_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); - dateEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - dateEdit->setDisplayFormat(tr("dd.MM.yyyy")); - dateEdit->setObjectName("param1"); - dateEdit->setMinimumDate(QDate(1970, 1, 1)); - dateEdit->setMaximumDate(QDate(2099, 12,31)); - hbox->addWidget(dateEdit, Qt::AlignLeft); - hbox->addStretch(); - } else if (searchType == SizeSearch) - { - QLineEdit * lineEdit = new QLineEdit(internalframe); - lineEdit->setMinimumSize(SIZE_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); - lineEdit->setMaximumSize(SIZE_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); - lineEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - lineEdit->setObjectName("param1"); - lineEdit->setValidator(numValidator); - hbox->addWidget(lineEdit, Qt::AlignLeft); - QComboBox * cb = new QComboBox(internalframe); - cb->setObjectName("unitsCb1"); - cb-> addItem(tr("KB"), QVariant(1024)); - cb->addItem(tr("MB"), QVariant(1048576)); - cb->addItem(tr("GB"), QVariant(1073741824)); - hbox->addSpacing(9); - internalframe->layout()->addWidget(cb); - hbox->addStretch(); - } - - /* POP Search not implemented - else if (searchType == PopSearch) - { - QLineEdit * lineEdit = new QLineEdit(elem); - lineEdit->setObjectName("param1"); - lineEdit->setValidator(numValidator); - elem->layout()->addWidget(lineEdit); - }*/ - hbox->invalidate(); - internalframe->adjustSize(); - internalframe->show(); - this->adjustSize(); + /* POP Search not implemented + else if (searchType == PopSearch) + { + QLineEdit * lineEdit = new QLineEdit(this); + lineEdit->setObjectName("param1"); + lineEdit->setValidator(numValidator); + hbox->addWidget(lineEdit); + hbox->addStretch(); + setMinimumSize(lineEdit->minimumSize()); + }*/ + hbox->invalidate(); + adjustSize(); + show(); } void ExprParamElement::setRangedSearch(bool ranged) -{ +{ if (inRangedConfig == ranged) return; // nothing to do here inRangedConfig = ranged; - QHBoxLayout* hbox = (dynamic_cast(internalframe->layout())); + QHBoxLayout* hbox = static_cast(layout()); // add additional or remove extra input fields depending on whether // ranged search or not if (inRangedConfig) { + + if(hbox->itemAt(hbox->count()-1)->spacerItem()) + delete hbox->takeAt(hbox->count()-1); + QLabel * toLbl = new QLabel(tr("to")); - toLbl->setMinimumSize(10, FIELDS_MIN_HEIGHT); + toLbl->setMinimumSize(getMinSize(2, FIELDS_MIN_HFACTOR)); toLbl->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); if (searchType == DateSearch) { - internalframe->setMinimumSize(250,26); - QDateEdit * dateEdit = new QDateEdit(QDate::currentDate(), internalframe); - dateEdit->setMinimumSize(DATE_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); + QDateEdit * dateEdit = new QDateEdit(QDate::currentDate(), this); + dateEdit->setMinimumSize(getMinSize(DATE_FIELDS_MIN_WFACTOR, FIELDS_MIN_HFACTOR)); dateEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + dateEdit->setDisplayFormat(tr("yyyy-MM-dd")); dateEdit->setObjectName("param2"); - dateEdit->setDisplayFormat(tr("dd.MM.yyyy")); dateEdit->setMinimumDate(QDate(1970, 1, 1)); dateEdit->setMaximumDate(QDate(2099, 12,31)); @@ -510,18 +520,21 @@ void ExprParamElement::setRangedSearch(bool ranged) hbox->addSpacing(9); hbox->addWidget(dateEdit, Qt::AlignLeft); hbox->addStretch(); + setMinimumSize(minimumSize() + QSize(9,0) + + QSize(toLbl->minimumWidth(),0) + QSize(9,0) + + QSize(dateEdit->minimumWidth(),0) ); + } else if (searchType == SizeSearch) { - internalframe->setMinimumSize(340,26); - QLineEdit * lineEdit = new QLineEdit(internalframe); - lineEdit->setMinimumSize(SIZE_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); - lineEdit->setMaximumSize(SIZE_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); + QLineEdit * lineEdit = new QLineEdit(this); + lineEdit->setMinimumSize(getMinSize(SIZE_FIELDS_MIN_WFACTOR, FIELDS_MIN_HFACTOR)); + lineEdit->setMaximumSize(getMinSize(SIZE_FIELDS_MIN_WFACTOR, FIELDS_MIN_HFACTOR)); lineEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); lineEdit->setObjectName("param2"); lineEdit->setValidator(numValidator); - QComboBox * cb = new QComboBox(internalframe); + RSComboBox * cb = new RSComboBox(this); cb->setObjectName("unitsCb2"); - cb-> addItem(tr("KB"), QVariant(1024)); + cb->addItem(tr("KB"), QVariant(1024)); cb->addItem(tr("MB"), QVariant(1048576)); cb->addItem(tr("GB"), QVariant(1073741824)); @@ -532,28 +545,39 @@ void ExprParamElement::setRangedSearch(bool ranged) hbox->addSpacing(9); hbox->addWidget(cb); hbox->addStretch(); - } -// else if (searchType == PopSearch) -// { -// elem->layout()->addWidget(new QLabel(tr("to")), Qt::AlignCenter); -// QLineEdit * lineEdit = new QLineEdit(elem); -// lineEdit->setObjectName("param2"); -// lineEdit->setValidator(numValidator); -// elem->layout()->addWidget(slineEdit); -// } + setMinimumSize(minimumSize() + QSize(9,0) + + QSize(toLbl->minimumWidth(),0) + QSize(9,0) + + QSize(lineEdit->minimumWidth(),0) + QSize(9,0) + + QSize(cb->minimumWidth(),0) ); + + } +// else if (searchType == PopSearch) +// { +// QLineEdit * lineEdit = new QLineEdit(this); +// lineEdit->setObjectName("param2"); +// lineEdit->setValidator(numValidator); + +// hbox->addSpacing(9); +// hbox->addWidget(toLbl, Qt::AlignLeft); +// hbox->addSpacing(9); +// hbox->addWidget(lineEdit, Qt::AlignLeft); +// hbox->addStretch(); +// setMinimumSize(minimumSize() + QSize(9,0) +// + QSize(toLbl->minimumWidth(),0) + QSize(9,0) +// + QSize(lineEdit->minimumWidth(),0) ); +// } hbox->invalidate(); - internalframe->adjustSize(); - internalframe->show(); - this->adjustSize(); + adjustSize(); + show(); } else { adjustForSearchType(searchType); } } bool ExprParamElement::ignoreCase() -{ +{ return (isStringSearchExpression() - && (internalframe->findChild("ignoreCaseCB")) + && (findChild("ignoreCaseCB")) ->checkState()==Qt::Checked); } @@ -561,15 +585,15 @@ QString ExprParamElement::getStrSearchValue() { if (!isStringSearchExpression()) return ""; - QLineEdit * lineEdit = internalframe->findChild("param1"); + QLineEdit * lineEdit = findChild("param1"); return lineEdit->displayText(); } uint64_t ExprParamElement::getIntValueFromField(QString fieldName, bool isToField,bool *ok) { uint64_t val = 0; - if(ok!=NULL) - *ok=true ; + if(ok!=NULL) + *ok=true ; QString suffix = (isToField) ? "2": "1" ; // NOTE qFindChild necessary for MSVC 6 compatibility!! @@ -577,25 +601,29 @@ uint64_t ExprParamElement::getIntValueFromField(QString fieldName, bool isToFiel { case DateSearch: { - QDateEdit * dateEdit = internalframe->findChild (fieldName + suffix); - QDateTime * time = new QDateTime(dateEdit->date()); - val = (uint64_t)time->toTime_t(); + QDateEdit * dateEdit = findChild (fieldName + suffix); +#if QT_VERSION < QT_VERSION_CHECK(5,15,0) + QDateTime time = QDateTime(dateEdit->date()); +#else + QDateTime time = dateEdit->date().startOfDay(); +#endif + val = (uint64_t)time.toTime_t(); break; - } + } case SizeSearch: { - QLineEdit * lineEditSize = internalframe->findChild(fieldName + suffix); + QLineEdit * lineEditSize = findChild(fieldName + suffix); bool ok2 = false; val = (lineEditSize->displayText()).toULongLong(&ok2); if (ok2) - { - QComboBox * cb = internalframe->findChild((QString("unitsCb") + suffix)); + { + RSComboBox * cb = findChild((QString("unitsCb") + suffix)); QVariant data = cb->itemData(cb->currentIndex()); val *= data.toULongLong(); - } - else - if(ok!=NULL) - *ok=false ; + } + else + if(ok!=NULL) + *ok=false ; break; } @@ -615,8 +643,8 @@ uint64_t ExprParamElement::getIntValueFromField(QString fieldName, bool isToFiel case HashSearch: default: // shouldn't be here...val stays at -1 - if(ok!=NULL) - *ok=false ; + if(ok!=NULL) + *ok=false ; } return val; diff --git a/retroshare-gui/src/gui/advsearch/guiexprelement.h b/retroshare-gui/src/gui/advsearch/guiexprelement.h index 00748f4f7..50ebeaa15 100644 --- a/retroshare-gui/src/gui/advsearch/guiexprelement.h +++ b/retroshare-gui/src/gui/advsearch/guiexprelement.h @@ -22,25 +22,18 @@ #ifndef _GuiExprElement_h_ #define _GuiExprElement_h_ -#include -#include -#include -#include -#include +#include "gui/common/RSComboBox.h" + +#include "retroshare/rsexpr.h" + #include -#include -#include #include -#include -#include -#include #include -#include +#include +#include #include -#include - enum ExprSearchType { NameSearch, @@ -53,13 +46,13 @@ enum ExprSearchType }; -class GuiExprElement: public QWidget +class GuiExprElement: public QFrame { Q_OBJECT public: GuiExprElement(QWidget * parent = 0); - virtual void adjustForSearchType(ExprSearchType) {} + void adjustForSearchType(ExprSearchType) {} virtual ~GuiExprElement(){} virtual void set(int){} virtual void set(QObject*){} @@ -103,8 +96,8 @@ protected: condition combobox */ QStringList getConditionOptions(ExprSearchType t); - QHBoxLayout* createLayout(QWidget* parent = 0); - QFrame * internalframe; + QHBoxLayout* createLayout(QWidget* parent = nullptr); + QSize getMinSize(float widthFactor = 1.0, float heightFactor = 1.0); ExprSearchType searchType; @@ -125,7 +118,6 @@ protected: static QMap strConditionStrMap; static QMap relConditionStrMap; - }; /** the Expression operator combobox element */ @@ -134,11 +126,11 @@ class ExprOpElement : public GuiExprElement Q_OBJECT public: - ExprOpElement(QWidget * parent = 0); + ExprOpElement(QWidget * parent = nullptr); RsRegularExpression::LogicalOperator getLogicalOperator(); QString toString(); private: - QComboBox * cb; + RSComboBox * cb; }; /** the Terms combobox element */ @@ -147,7 +139,7 @@ class ExprTermsElement : public GuiExprElement Q_OBJECT public: - ExprTermsElement(QWidget * parent = 0); + ExprTermsElement(QWidget * parent = nullptr); int getTermsIndex(); RsRegularExpression::RelOperator getRelOperator(); RsRegularExpression::StringOperator getStringOperator(); @@ -158,7 +150,7 @@ signals: void currentIndexChanged(int); private: - QComboBox * cb; + RSComboBox * cb; }; /** the Conditions combobox element */ @@ -167,7 +159,7 @@ class ExprConditionElement : public GuiExprElement Q_OBJECT public: - ExprConditionElement(ExprSearchType, QWidget * parent = 0); + ExprConditionElement(QWidget * parent = nullptr, ExprSearchType type = NameSearch); RsRegularExpression::RelOperator getRelOperator(); RsRegularExpression::StringOperator getStringOperator(); void adjustForSearchType(ExprSearchType); @@ -178,7 +170,7 @@ signals: void currentIndexChanged(int); private: - QComboBox * cb; + RSComboBox * cb; }; /** the Parameter element */ @@ -187,7 +179,7 @@ class ExprParamElement : public GuiExprElement Q_OBJECT public: - ExprParamElement(ExprSearchType, QWidget * parent = 0); + ExprParamElement(QWidget * parent = nullptr, ExprSearchType type = NameSearch); QVariant* getRSExprValue(); void adjustForSearchType(ExprSearchType); void setRangedSearch(bool ranged = true); diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp index 3b92883e8..fbc35d2cf 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "ChatLobbyDialog.h" @@ -208,6 +209,8 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi connect(unsubscribeButton, SIGNAL(clicked()), this , SLOT(leaveLobby())); getChatWidget()->addTitleBarWidget(unsubscribeButton) ; + + mFontSizeHandler.registerFontSize(ui.participantsList); } void ChatLobbyDialog::leaveLobby() diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.h b/retroshare-gui/src/gui/chat/ChatLobbyDialog.h index 429a5bfb4..c3572cc4b 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.h +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.h @@ -26,9 +26,10 @@ #include "gui/common/RSTreeWidgetItem.h" #include "ChatDialog.h" #include "PopupChatWindow.h" +#include "util/FontSizeHandler.h" -Q_DECLARE_METATYPE(RsGxsId) -Q_DECLARE_METATYPE(QList) +// Q_DECLARE_METATYPE(RsGxsId) +// Q_DECLARE_METATYPE(QList) class GxsIdChooser ; class QToolButton; @@ -101,7 +102,7 @@ private: void muteParticipant(const RsGxsId& id); void unMuteParticipant(const RsGxsId& id); bool isNicknameInLobby(const RsGxsId& id); - + ChatLobbyId lobbyId; QString _lobby_name ; time_t lastUpdateListTime; @@ -115,9 +116,11 @@ private: bool mWindowedSetted; PopupChatWindow* mPCWindow; + FontSizeHandler mFontSizeHandler; + /** Qt Designer generated object */ Ui::ChatLobbyDialog ui; - + /** Ignored Users in Chatlobby by nickname until we had implemented Peer Ids in ver 0.6 */ std::set mutedParticipants; diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.ui b/retroshare-gui/src/gui/chat/ChatLobbyDialog.ui index 0a1635735..e00790f83 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.ui +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.ui @@ -13,7 +13,7 @@ MainWindow - + 0 @@ -48,7 +48,7 @@
- + 0 @@ -61,7 +61,10 @@ 0 - + + + 2 + 0 @@ -77,12 +80,12 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + 2 diff --git a/retroshare-gui/src/gui/chat/ChatLobbyUserNotify.cpp b/retroshare-gui/src/gui/chat/ChatLobbyUserNotify.cpp index 4407cc73c..719ad7d2d 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyUserNotify.cpp +++ b/retroshare-gui/src/gui/chat/ChatLobbyUserNotify.cpp @@ -146,8 +146,48 @@ QString ChatLobbyUserNotify::getNotifyMessage(bool plural) void ChatLobbyUserNotify::iconClicked() { + #if defined(Q_OS_DARWIN) + std::list lobbies; + rsMsgs->getChatLobbyList(lobbies); + bool doUpdate=false; + + for (lobby_map::iterator itCL=_listMsg.begin(); itCL!=_listMsg.end();) + { + bool bFound=false; + QString strLobbyName=tr("Unknown Lobby"); + QIcon icoLobby=QIcon(); + std::list::const_iterator lobbyIt; + for (lobbyIt = lobbies.begin(); lobbyIt != lobbies.end(); ++lobbyIt) { + ChatLobbyId clId = *lobbyIt; + if (clId==itCL->first) { + ChatLobbyInfo clInfo; + if (rsMsgs->getChatLobbyInfo(clId,clInfo)) + strLobbyName=QString::fromUtf8(clInfo.lobby_name.c_str()) ; + bFound=true; + break; + } + } + + if (bFound) + { + MainWindow::showWindow(MainWindow::ChatLobby); + ChatLobbyWidget *chatLobbyWidget = dynamic_cast(MainWindow::getPage(MainWindow::ChatLobby)); + if (chatLobbyWidget) chatLobbyWidget->showLobbyAnchor(itCL->first,strLobbyName); + ++itCL ; + } + else + { + lobby_map::iterator ittmp(itCL); + ++ittmp ; + _listMsg.erase(itCL); + itCL=ittmp ; + doUpdate=true; + } + } + #else + /// Tray icon Menu /// - QMenu* trayMenu = new QMenu(MainWindow::getInstance()); + QMenu* trayMenu = createMenu(); std::list lobbies; rsMsgs->getChatLobbyList(lobbies); bool doUpdate=false; @@ -186,27 +226,25 @@ void ChatLobbyUserNotify::iconClicked() } } - if (notifyCombined()) { - QSystemTrayIcon* trayIcon=getTrayIcon(); - if (trayIcon!=NULL) trayIcon->setContextMenu(trayMenu); - } else { - QAction* action=getNotifyIcon(); - if (action!=NULL) { - action->setMenu(trayMenu); - } - } - QString strName=tr("Remove All"); QAction *pAction = new QAction( QIcon(), strName, trayMenu); ActionTag actionTag={0x0, "", true}; pAction->setData(qVariantFromValue(actionTag)); - connect(trayMenu, SIGNAL(triggered(QAction*)), this, SLOT(subMenuClicked(QAction*))); - connect(trayMenu, SIGNAL(hovered(QAction*)), this, SLOT(subMenuHovered(QAction*))); trayMenu->addAction(pAction); trayMenu->exec(QCursor::pos()); + delete(trayMenu); if (doUpdate) updateIcon(); + #endif +} + +QMenu* ChatLobbyUserNotify::createMenu() +{ + QMenu* menu = new QMenu(MainWindow::getInstance()); + connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(subMenuClicked(QAction*))); + connect(menu, SIGNAL(hovered(QAction*)), this, SLOT(subMenuHovered(QAction*))); + return menu; } void ChatLobbyUserNotify::makeSubMenu(QMenu* parentMenu, QIcon icoLobby, QString strLobbyName, ChatLobbyId id) @@ -217,11 +255,7 @@ void ChatLobbyUserNotify::makeSubMenu(QMenu* parentMenu, QIcon icoLobby, QString unsigned int msgCount=msgMap.size(); - if(!parentMenu) parentMenu = new QMenu(MainWindow::getInstance()); QMenu *lobbyMenu = parentMenu->addMenu(icoLobby, strLobbyName); - connect(lobbyMenu, SIGNAL(triggered(QAction*)), this, SLOT(subMenuClicked(QAction*))); - connect(lobbyMenu, SIGNAL(hovered(QAction*)), this, SLOT(subMenuHovered(QAction*))); - lobbyMenu->setToolTip(getNotifyMessage(msgCount>1).arg(msgCount)); for (msg_map::iterator itMsg=msgMap.begin(); itMsg!=msgMap.end(); ++itMsg) { @@ -243,7 +277,6 @@ void ChatLobbyUserNotify::makeSubMenu(QMenu* parentMenu, QIcon icoLobby, QString ActionTag actionTag={itCL->first, "", true}; pAction->setData(qVariantFromValue(actionTag)); lobbyMenu->addAction(pAction); - } void ChatLobbyUserNotify::iconHovered() @@ -251,7 +284,6 @@ void ChatLobbyUserNotify::iconHovered() iconClicked(); } - void ChatLobbyUserNotify::chatLobbyNewMessage(ChatLobbyId lobby_id, QDateTime time, QString senderName, QString msg) { diff --git a/retroshare-gui/src/gui/chat/ChatLobbyUserNotify.h b/retroshare-gui/src/gui/chat/ChatLobbyUserNotify.h index fd95511b4..2e49f450f 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyUserNotify.h +++ b/retroshare-gui/src/gui/chat/ChatLobbyUserNotify.h @@ -49,6 +49,7 @@ public: ChatLobbyUserNotify(QObject *parent = 0); virtual bool hasSetting(QString *name, QString *group); + QMenu* createMenu(); void makeSubMenu(QMenu* parentMenu, QIcon icoLobby, QString strLobbyName, ChatLobbyId id); void chatLobbyNewMessage(ChatLobbyId lobby_id, QDateTime time, QString senderName, QString msg); void chatLobbyCleared(ChatLobbyId lobby_id, QString anchor, bool onlyUnread=false); diff --git a/retroshare-gui/src/gui/chat/ChatUserNotify.cpp b/retroshare-gui/src/gui/chat/ChatUserNotify.cpp index 5f78739c3..dcafae59a 100644 --- a/retroshare-gui/src/gui/chat/ChatUserNotify.cpp +++ b/retroshare-gui/src/gui/chat/ChatUserNotify.cpp @@ -76,7 +76,7 @@ bool ChatUserNotify::hasSetting(QString *name, QString *group) QIcon ChatUserNotify::getIcon() { - return FilesDefs::getIconFromQtResourcePath(":/images/chat.png"); + return FilesDefs::getIconFromQtResourcePath(":/images/orange-bubble-64.png"); } QIcon ChatUserNotify::getMainIcon(bool hasNew) diff --git a/retroshare-gui/src/gui/chat/ChatWidget.cpp b/retroshare-gui/src/gui/chat/ChatWidget.cpp index 331aed893..abab8336a 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.cpp +++ b/retroshare-gui/src/gui/chat/ChatWidget.cpp @@ -165,7 +165,6 @@ ChatWidget::ChatWidget(QWidget *parent) connect(ui->actionResetFont, SIGNAL(triggered()), this, SLOT(resetFont())); connect(ui->actionQuote, SIGNAL(triggered()), this, SLOT(quote())); connect(ui->actionDropPlacemark, SIGNAL(triggered()), this, SLOT(dropPlacemark())); - connect(ui->actionSave_image, SIGNAL(triggered()), this, SLOT(saveImage())); connect(ui->actionImport_sticker, SIGNAL(triggered()), this, SLOT(saveSticker())); connect(ui->actionShow_Hidden_Images, SIGNAL(triggered()), ui->textBrowser, SLOT(showImages())); ui->actionShow_Hidden_Images->setIcon(ui->textBrowser->getBlockedImage()); @@ -183,7 +182,7 @@ ChatWidget::ChatWidget(QWidget *parent) connect(ui->chatTextEdit, SIGNAL(currentCharFormatChanged(QTextCharFormat)), this, SLOT(chatCharFormatChanged())); connect(ui->chatTextEdit, SIGNAL(textChanged()), this, SLOT(updateLenOfChatTextEdit())); - ui->infoFrame->setVisible(false); + ui->info_Frame->setVisible(false); ui->statusMessageLabel->hide(); setAcceptDrops(true); @@ -290,12 +289,12 @@ void ChatWidget::addChatBarWidget(QWidget *w) void ChatWidget::addTitleBarWidget(QWidget *w) { - ui->pluginTitleFrame->layout()->addWidget(w) ; + ui->trans_Frame_PluginTitle->layout()->addWidget(w) ; } void ChatWidget::addTopBarWidget(QWidget *w) { - ui->pluginTopFrame->layout()->addWidget(w) ; + ui->trans_Frame_PluginTop->layout()->addWidget(w) ; } void ChatWidget::hideChatText(bool hidden) @@ -381,7 +380,7 @@ void ChatWidget::init(const ChatId &chat_id, const QString &title) hist_chat_type = RS_HISTORY_TYPE_PUBLIC; messageCount = Settings->getPublicChatHistoryCount(); - ui->titleBarFrame->setVisible(false); + ui->headerBFrame->setVisible(false); } if (rsHistory->getEnable(hist_chat_type)) @@ -403,7 +402,7 @@ void ChatWidget::init(const ChatId &chat_id, const QString &title) continue; QString name; - if (chatId.isLobbyId() || chatId.isDistantChatId() || chatId.isPeerId()) + if (!chatId.isNotSet()) { RsIdentityDetails details; @@ -474,6 +473,7 @@ void ChatWidget::processSettings(bool load) // state of splitter ui->chatVSplitter->restoreState(Settings->value("ChatSplitter").toByteArray()); } else { + shrinkChatTextEdit(false); // save settings // state of splitter @@ -627,7 +627,7 @@ bool ChatWidget::eventFilter(QObject *obj, QEvent *event) QString toolTipText = ui->textBrowser->anchorForPosition(helpEvent->pos()); if (toolTipText.isEmpty() && !ui->textBrowser->getShowImages()){ QString imageStr; - if (ui->textBrowser->checkImage(helpEvent->pos(), imageStr)) { + if (ImageUtil::checkImage(ui->textBrowser, helpEvent->pos(), imageStr)) { toolTipText = imageStr; } } else if (toolTipText.startsWith(PERSONID)){ @@ -642,7 +642,17 @@ bool ChatWidget::eventFilter(QObject *obj, QEvent *event) } } - } else if (obj == ui->chatTextEdit) { + } else if (obj == ui->chatTextEdit) { + if (chatType() == CHATTYPE_LOBBY) { + #define EVENT_IS(q_event) (event->type() == QEvent::q_event) + if (EVENT_IS(FocusIn)) { + if (was_shrinked) { + shrinkChatTextEdit(false); + } + } + #undef EVENT_IS + } + if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(event); @@ -905,11 +915,19 @@ void ChatWidget::showEvent(QShowEvent */*event*/) QScrollBar *scrollbar = ui->textBrowser->verticalScrollBar(); bool is_scrollbar_at_end = scrollbar->value() == scrollbar->maximum(); bool is_chat_text_edit_empty = ui->chatTextEdit->toPlainText().isEmpty(); + // show event will not be called on every change of focus if (is_scrollbar_at_end || !is_chat_text_edit_empty) { + if (!firstShow) { + shrinkChatTextEdit(false); + } focusDialog(); } else { - // otherwise focus will be get even not chat itself + // otherwise, focus will not even be gotten by chat itself ui->textBrowser->setFocus(); + + if (!firstShow && !was_shrinked) { + shrinkChatTextEdit(true); + } } ChatUserNotify::clearWaitingChat(chatId); @@ -923,6 +941,11 @@ void ChatWidget::showEvent(QShowEvent */*event*/) void ChatWidget::resizeEvent(QResizeEvent */*event*/) { + // it's about resize all chat window, not about chattextedit + // just unshrink it and do not bother + if (was_shrinked) { + shrinkChatTextEdit(false); + } // Workaround: now the scroll position is correct calculated QScrollBar *scrollbar = ui->textBrowser->verticalScrollBar(); scrollbar->setValue(scrollbar->maximum()); @@ -959,11 +982,12 @@ void ChatWidget::on_notifyButton_clicked() if(!notify) return; if (chatType() != CHATTYPE_LOBBY) return; - QMenu* menu = new QMenu(MainWindow::getInstance()); + QMenu* menu = notify->createMenu(); QIcon icoLobby=(ui->notifyButton->icon()); notify->makeSubMenu(menu, icoLobby, title, chatId.toLobbyId()); menu->exec(ui->notifyButton->mapToGlobal(QPoint(0,ui->notifyButton->geometry().height()))); + delete(menu); } @@ -1070,7 +1094,7 @@ void ChatWidget::addChatMsg(bool incoming, const QString &name, const RsGxsId gx QImage image(icon.pixmap(height,height).toImage()); QByteArray byteArray; QBuffer buffer(&byteArray); - image.save(&buffer, "PNG"); // writes the image in PNG format inside the buffer + image.save(&buffer, "PNG"); // writes the image in PNG format inside the buffer QString iconBase64 = QString::fromLatin1(byteArray.toBase64().data()); strPreName = QString("\"[unsigned]\"").arg(iconBase64); } @@ -1127,10 +1151,7 @@ void ChatWidget::pasteText(const QString& S) void ChatWidget::contextMenuTextBrowser(QPoint point) { - QMatrix matrix; - matrix.translate(ui->textBrowser->horizontalScrollBar()->value(), ui->textBrowser->verticalScrollBar()->value()); - - QMenu *contextMnu = ui->textBrowser->createStandardContextMenu(matrix.map(point)); + QMenu *contextMnu = ui->textBrowser->createStandardContextMenuFromPoint(point); contextMnu->addSeparator(); contextMnu->addAction(ui->actionClearChatHistory); @@ -1138,14 +1159,12 @@ void ChatWidget::contextMenuTextBrowser(QPoint point) contextMnu->addAction(ui->actionQuote); contextMnu->addAction(ui->actionDropPlacemark); - if(ui->textBrowser->checkImage(point)) + if(ImageUtil::checkImage(ui->textBrowser, point)) { if (! ui->textBrowser->getShowImages()) contextMnu->addAction(ui->actionShow_Hidden_Images); - ui->actionSave_image->setData(point); ui->actionImport_sticker->setData(point); - contextMnu->addAction(ui->actionSave_image); contextMnu->addAction(ui->actionImport_sticker); } @@ -1286,7 +1305,7 @@ void ChatWidget::sendChat() void ChatWidget::on_closeInfoFrameButton_clicked() { - ui->infoFrame->setVisible(false); + ui->info_Frame->setVisible(false); } void ChatWidget::on_searchButton_clicked(bool bValue) @@ -1511,23 +1530,43 @@ void ChatWidget::chooseFont() //Use NULL as parent as with this QFontDialog don't take care of title nether options. QFont font = misc::getFont(&ok, currentFont, nullptr, tr("Choose your font.")); - QTextCursor cursor = ui->chatTextEdit->textCursor(); if (ok) { + QTextCursor cursor = ui->chatTextEdit->textCursor(); + if (cursor.selection().isEmpty()){ currentFont = font; setFont(); } else { - //Merge Format doesn't works for only selection so add a new block. - QString text = "

" + cursor.selectedText().toHtmlEscaped() + "

"; - cursor.insertHtml(text); + // Merge Format doesn't works for only selection. + // and charFormat() get format for last char. + QTextCursor selCurs = cursor; + QTextCursor lastCurs = cursor; + int pos = cursor.selectionStart(); + lastCurs.setPosition(pos); + do + { + // Get format block in selection iterating char one by one + selCurs.setPosition(++pos); + if (selCurs.charFormat() != lastCurs.charFormat()) + { + // New char format, format last block. + QTextCharFormat charFormat = lastCurs.charFormat(); + charFormat.setFont(font); + lastCurs.setCharFormat(charFormat); + // Last block formated, start it to current char. + lastCurs.setPosition(pos-1); + } + // Add current char. + lastCurs.setPosition(pos, QTextCursor::KeepAnchor); + } while (pos < cursor.selectionEnd()); + + // Now format last block + if (lastCurs.selectionStart() != lastCurs.selectionEnd()) + { + QTextCharFormat charFormat = lastCurs.charFormat(); + charFormat.setFont(font); + lastCurs.setCharFormat(charFormat); + } } } } @@ -1583,7 +1622,12 @@ void ChatWidget::addSmiley() smiley += QString(" "); // add preceding space when needed (not at start of text or preceding space already exists) QString plainText = ui->chatTextEdit->toPlainText(); - QChar start = plainText[ui->chatTextEdit->textCursor().position() - 1]; + + int startPosition = ui->chatTextEdit->textCursor().position(); + if (startPosition > 0) + startPosition -= 1; + + QChar start = plainText[startPosition]; if(!ui->chatTextEdit->textCursor().atStart() && start != QChar(' ')) smiley = QString(" ") + smiley; @@ -1648,7 +1692,7 @@ void ChatWidget::addExtraPicture() if (misc::getOpenFileName(window(), RshareSettings::LASTDIR_IMAGES, tr("Load Picture File"), "Pictures (*.png *.xpm *.jpg *.jpeg *.gif *.webp )", file)) { QString encodedImage; uint32_t maxMessageSize = this->maxMessageSize(); - if (RsHtml::makeEmbeddedImage(file, encodedImage, 640*480, maxMessageSize - 200)) { //-200 for the html stuff + if (RsHtml::makeEmbeddedImage(file, encodedImage, 640*480, maxMessageSize - 200)) { //-200 for the html stuff QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(encodedImage); ui->chatTextEdit->textCursor().insertFragment(fragment); } @@ -1799,27 +1843,27 @@ void ChatWidget::updateStatus(const QString &peer_id, int status) switch (status) { case RS_STATUS_OFFLINE: - ui->infoFrame->setVisible(true); + ui->info_Frame->setVisible(true); ui->infoLabel->setText(peerName + " " + tr("appears to be Offline.") +"\n" + tr("Messages you send will be delivered after Friend is again Online.")); break; case RS_STATUS_INACTIVE: - ui->infoFrame->setVisible(true); + ui->info_Frame->setVisible(true); ui->infoLabel->setText(peerName + " " + tr("is Idle and may not reply")); break; case RS_STATUS_ONLINE: - ui->infoFrame->setVisible(false); + ui->info_Frame->setVisible(false); break; case RS_STATUS_AWAY: ui->infoLabel->setText(peerName + " " + tr("is Away and may not reply")); - ui->infoFrame->setVisible(true); + ui->info_Frame->setVisible(true); break; case RS_STATUS_BUSY: ui->infoLabel->setText(peerName + " " + tr("is Busy and may not reply")); - ui->infoFrame->setVisible(true); + ui->info_Frame->setVisible(true); break; } @@ -1946,13 +1990,6 @@ void ChatWidget::dropPlacemark() // or not. } -void ChatWidget::saveImage() -{ - QPoint point = ui->actionSave_image->data().toPoint(); - QTextCursor cursor = ui->textBrowser->cursorForPosition(point); - ImageUtil::extractImage(window(), cursor); -} - void ChatWidget::saveSticker() { QPoint point = ui->actionImport_sticker->data().toPoint(); @@ -1962,3 +1999,50 @@ void ChatWidget::saveSticker() filename = Emoticons::importedStickerPath() + "/" + filename + ".png"; ImageUtil::extractImage(window(), cursor, filename); } + +void ChatWidget::shrinkChatTextEdit(bool shrink_me) +{ + // here and at eventfiltert check + if (chatType() != CHATTYPE_LOBBY) + return; + if (!Settings->getShrinkChatTextEdit()) { + if (was_shrinked) { + ui->chatVSplitter->setSizes(_chatvsplitter_saved_size); + } + _chatvsplitter_saved_size.clear(); + was_shrinked = false; + } + + if (Settings->getShrinkChatTextEdit()) { + if (shrink_me) { + if (!was_shrinked) { + _chatvsplitter_saved_size = ui->chatVSplitter->sizes(); + + QList shrinked_v_splitter_size = _chatvsplitter_saved_size; + // #define TEXT_BROWSER ui->chatVSplitter->indexOf(ui->textBrowser) + #define TEXT_BROWSER 0 + // when you will update the layout one more time change this appropriately + // #define BELOW_TEXT_BROWSER ui->chatVSplitter->indexOf(ui->chatVSplitter->widget(1)) + #define BELOW_TEXT_BROWSER 1 + int height_diff = shrinked_v_splitter_size[BELOW_TEXT_BROWSER] - ui->chatTextEdit->minimumHeight(); + shrinked_v_splitter_size[BELOW_TEXT_BROWSER] = ui->chatTextEdit->minimumHeight(); + shrinked_v_splitter_size[TEXT_BROWSER] += height_diff; + ui->chatVSplitter->setSizes( shrinked_v_splitter_size ); + #undef TEXT_BROWSER + #undef BELOW_TEXT_BROWSER + was_shrinked = true; + } + } else { // (!shrink_me) + if (was_shrinked) { + // to not shrink/unshrink at every entry into chat + // when unshrinked state is enough to a browser be scrollable, but shrinked - not + QScrollBar *scrollbar = ui->textBrowser->verticalScrollBar(); + bool is_scrollbar_at_end = scrollbar->value() == scrollbar->maximum(); + ui->chatVSplitter->setSizes(_chatvsplitter_saved_size); + if (is_scrollbar_at_end) + scrollbar->setValue(scrollbar->maximum()); + was_shrinked = false; + } + } + } +} diff --git a/retroshare-gui/src/gui/chat/ChatWidget.h b/retroshare-gui/src/gui/chat/ChatWidget.h index b9ff7086f..e42df06fe 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.h +++ b/retroshare-gui/src/gui/chat/ChatWidget.h @@ -196,7 +196,6 @@ private slots: void quote(); void dropPlacemark(); - void saveImage(); void saveSticker(); private: @@ -215,6 +214,8 @@ private: void completeNickname(bool reverse); QAbstractItemModel *modelFromPeers(); + void shrinkChatTextEdit(bool shrink_me); + ChatId chatId; QString title; QString name; @@ -264,6 +265,9 @@ private: QCompleter *completer; ImHistoryBrowser* imBrowser; + QList _chatvsplitter_saved_size; + bool was_shrinked = false; + QList mChatWidgetHolder; ChatLobbyUserNotify* notify; diff --git a/retroshare-gui/src/gui/chat/ChatWidget.ui b/retroshare-gui/src/gui/chat/ChatWidget.ui index 7ecbcfdc2..39bd84bb7 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.ui +++ b/retroshare-gui/src/gui/chat/ChatWidget.ui @@ -32,7 +32,7 @@ QLayout::SetMaximumSize - + 0 @@ -51,7 +51,7 @@ QFrame::Plain - + 2 @@ -84,10 +84,12 @@ - + + 11 75 + true true @@ -100,7 +102,14 @@ - + + + + 12 + 75 + true + + (Status) @@ -121,14 +130,14 @@ - + QFrame::NoFrame QFrame::Plain - + 3 @@ -311,14 +320,14 @@ - + QFrame::NoFrame QFrame::Plain - + 3 @@ -355,12 +364,6 @@ 0 - - QFrame::StyledPanel - - - QFrame::Raised - 0 @@ -375,10 +378,19 @@ 0 - + + + + + 0 + 0 + 0 + + + @@ -399,6 +411,15 @@ + + + + 0 + 0 + 0 + + + @@ -419,6 +440,15 @@ + + + + 154 + 154 + 154 + + + @@ -631,7 +661,7 @@ border-image: url(:/images/closepressed.png) 0 - 30 + 40 @@ -1019,15 +1049,6 @@ border-image: url(:/images/closepressed.png) Insert horizontal rule - - - - :/images/document_save.png:/images/document_save.png - - - Save image - - @@ -1089,21 +1110,6 @@ border-image: url(:/images/closepressed.png) - - LineEditClear - QLineEdit -
gui/common/LineEditClear.h
-
- - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
- - RSTextBrowser - QTextBrowser -
gui/common/RSTextBrowser.h
-
HashBox QScrollArea @@ -1115,11 +1121,20 @@ border-image: url(:/images/closepressed.png) QTextEdit
gui/common/MimeTextEdit.h
+ + LineEditClear + QLineEdit +
gui/common/LineEditClear.h
+
+ + RSTextBrowser + QTextBrowser +
gui/common/RSTextBrowser.h
+
- - + diff --git a/retroshare-gui/src/gui/chat/CreateLobbyDialog.ui b/retroshare-gui/src/gui/chat/CreateLobbyDialog.ui index 7c4d01aaa..15dab649d 100644 --- a/retroshare-gui/src/gui/chat/CreateLobbyDialog.ui +++ b/retroshare-gui/src/gui/chat/CreateLobbyDialog.ui @@ -37,10 +37,15 @@
- - + + - + + + + 15 + + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -103,7 +108,7 @@ - + Public (Visible by friends) @@ -230,6 +235,13 @@ + + + 12 + 75 + true + + Create @@ -250,17 +262,6 @@ - - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
- - HeaderFrame - QFrame -
gui/common/HeaderFrame.h
- 1 -
FriendSelectionWidget QWidget @@ -272,6 +273,17 @@ QComboBox
gui/gxs/GxsIdChooser.h
+ + HeaderFrame + QFrame +
gui/common/HeaderFrame.h
+ 1 +
+ + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
diff --git a/retroshare-gui/src/gui/chat/PopupChatWindow.cpp b/retroshare-gui/src/gui/chat/PopupChatWindow.cpp index 6c1f9128d..1f15345b1 100644 --- a/retroshare-gui/src/gui/chat/PopupChatWindow.cpp +++ b/retroshare-gui/src/gui/chat/PopupChatWindow.cpp @@ -34,6 +34,7 @@ #include "util/misc.h" #include "rshare.h" +#include #include #include @@ -88,7 +89,7 @@ PopupChatWindow::PopupChatWindow(bool tabbed, QWidget *parent, Qt::WindowFlags f // 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! + ui.headerToolBar->hide(); // no widgets left! setAttribute(Qt::WA_DeleteOnClose, true); @@ -100,6 +101,17 @@ PopupChatWindow::PopupChatWindow(bool tabbed, QWidget *parent, Qt::WindowFlags f connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); + voteNegative = new QAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-down.png"), + tr("Ban this person (Sets negative opinion)"), this); + voteNeutral = new QAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-neutral.png"), + tr("Give neutral opinion"), this); + votePositive = new QAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-up.png"), + tr("Give positive opinion"), this); + + connect(votePositive, SIGNAL(triggered()), this, SLOT(voteParticipant())); + connect(voteNeutral, SIGNAL(triggered()), this, SLOT(voteParticipant())); + connect(voteNegative, SIGNAL(triggered()), this, SLOT(voteParticipant())); + connect(ui.tabWidget, SIGNAL(tabChanged(ChatDialog*)), this, SLOT(tabChanged(ChatDialog*))); connect(ui.tabWidget, SIGNAL(tabClosed(ChatDialog*)), this, SLOT(tabClosed(ChatDialog*))); @@ -116,6 +128,37 @@ void PopupChatWindow::showContextMenu(QPoint) QMenu contextMnu(this); contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(":/images/highlight.png"),tr("Choose window color..."),this,SLOT(setStyle())); + ChatId ch_id = getCurrentDialog()->getChatId(); + if (ch_id.isDistantChatId()) { + DistantChatPeerId dc_id = ch_id.toDistantChatId(); + DistantChatPeerInfo dc_info; + if(rsMsgs->getDistantChatStatus(dc_id, dc_info)) { + RsGxsId gxs_id = dc_info.to_id; + if(!gxs_id.isNull() && !rsIdentity->isOwnId(gxs_id)) { + contextMnu.addAction(votePositive); + contextMnu.addAction(voteNeutral); + contextMnu.addAction(voteNegative); + + votePositive->setEnabled(false); + voteNeutral ->setEnabled(false); + voteNegative->setEnabled(false); + + RsOpinion rs_rep; + rsReputations->getOwnOpinion(gxs_id, rs_rep); + if (rsReputations->getOwnOpinion(gxs_id, rs_rep)) { + votePositive->setEnabled(rs_rep != RsOpinion::POSITIVE); + voteNeutral->setEnabled( ( rs_rep == RsOpinion::POSITIVE ) + || ( rs_rep == RsOpinion::NEGATIVE ) ); + voteNegative->setEnabled(rs_rep != RsOpinion::NEGATIVE); + + votePositive->setData(QVariant::fromValue(gxs_id)); + voteNeutral ->setData(QVariant::fromValue(gxs_id)); + voteNegative->setData(QVariant::fromValue(gxs_id)); + } + } + } + } + if (Settings->getChatFlags() & RS_CHAT_TABBED_WINDOW) { if(tabbedWindow) @@ -440,7 +483,7 @@ void PopupChatWindow::calculateStyle(ChatDialog *dialog) } } - ui.chattoolBar->setStyleSheet(toolSheet); + ui.headerToolBar->setStyleSheet(toolSheet); ui.chatstatusbar->setStyleSheet(statusSheet); ui.chatcentralwidget->setStyleSheet(widgetSheet); } @@ -457,3 +500,17 @@ void PopupChatWindow::blink(bool on) setWindowIcon(on ? mBlinkIcon : *mEmptyIcon); } } + +void PopupChatWindow::voteParticipant() +{ + QAction *act = dynamic_cast(sender()) ; + if (!act) { + return ; + } + + RsOpinion opinion = RsOpinion::NEUTRAL; + if (act == voteNeutral) opinion = RsOpinion::NEUTRAL; + if (act == votePositive) opinion = RsOpinion::POSITIVE; + if (act == voteNegative) opinion = RsOpinion::NEGATIVE; + rsReputations->setOwnOpinion(act->data().value(), opinion); +} diff --git a/retroshare-gui/src/gui/chat/PopupChatWindow.h b/retroshare-gui/src/gui/chat/PopupChatWindow.h index 86f8ebc80..968531ea1 100644 --- a/retroshare-gui/src/gui/chat/PopupChatWindow.h +++ b/retroshare-gui/src/gui/chat/PopupChatWindow.h @@ -27,6 +27,8 @@ #include "ui_PopupChatWindow.h" #include #include +Q_DECLARE_METATYPE(RsGxsId) +Q_DECLARE_METATYPE(QList) class ChatDialog; @@ -67,6 +69,7 @@ private slots: void setOnTop(); void blink(bool on); void showContextMenu(QPoint p); + void voteParticipant(); private: bool tabbedWindow; @@ -75,6 +78,9 @@ private: ChatDialog *chatDialog; QIcon mBlinkIcon; QIcon *mEmptyIcon; + QAction* votePositive; + QAction* voteNegative; + QAction* voteNeutral; ChatDialog *getCurrentDialog(); void saveSettings(); diff --git a/retroshare-gui/src/gui/chat/PopupChatWindow.ui b/retroshare-gui/src/gui/chat/PopupChatWindow.ui index ea6ea79af..0394a1c31 100644 --- a/retroshare-gui/src/gui/chat/PopupChatWindow.ui +++ b/retroshare-gui/src/gui/chat/PopupChatWindow.ui @@ -43,7 +43,7 @@
- + false diff --git a/retroshare-gui/src/gui/common/AvatarDefs.cpp b/retroshare-gui/src/gui/common/AvatarDefs.cpp index ccca08707..3255501aa 100644 --- a/retroshare-gui/src/gui/common/AvatarDefs.cpp +++ b/retroshare-gui/src/gui/common/AvatarDefs.cpp @@ -54,7 +54,9 @@ bool AvatarDefs::getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, cons /* get avatar */ rsMsgs->getAvatarData(RsPeerId(sslId), data, size); if (size == 0) { - avatar = FilesDefs::getPixmapFromQtResourcePath(defaultImage); + if (!defaultImage.isEmpty()) { + avatar = FilesDefs::getPixmapFromQtResourcePath(defaultImage); + } return false; } diff --git a/retroshare-gui/src/gui/common/AvatarDialog.cpp b/retroshare-gui/src/gui/common/AvatarDialog.cpp index 8eb24a184..a5e8d15d4 100644 --- a/retroshare-gui/src/gui/common/AvatarDialog.cpp +++ b/retroshare-gui/src/gui/common/AvatarDialog.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,7 @@ #include "util/misc.h" #include "gui/common/FilesDefs.h" #include "util/HandleRichText.h" +#include "util/imageutil.h" #include "retroshare/rsinit.h" #define ICONNAME "groupicon.png" @@ -105,8 +107,8 @@ void AvatarDialog::removeAvatar() void AvatarDialog::updateInterface() { - const QPixmap *pixmap = ui->avatarLabel->pixmap(); - if (pixmap && !pixmap->isNull()) { + QPixmap pixmap = ui->avatarLabel->pixmap(Qt::ReturnByValue); + if (!pixmap.isNull()) { ui->removeButton->setEnabled(true); } else { ui->removeButton->setEnabled(false); @@ -121,13 +123,7 @@ void AvatarDialog::setAvatar(const QPixmap &avatar) void AvatarDialog::getAvatar(QPixmap &avatar) { - const QPixmap *pixmap = ui->avatarLabel->pixmap(); - if (!pixmap) { - avatar = QPixmap(); - return; - } - - avatar = *pixmap; + avatar = ui->avatarLabel->pixmap(Qt::ReturnByValue); } void AvatarDialog::getAvatar(QByteArray &avatar) @@ -138,10 +134,11 @@ void AvatarDialog::getAvatar(QByteArray &avatar) return; } - QBuffer buffer(&avatar); + bool has_transparency = ImageUtil::hasAlphaContent(pixmap.toImage()); + QBuffer buffer(&avatar); buffer.open(QIODevice::WriteOnly); - pixmap.save(&buffer, "PNG"); // writes image into ba in PNG format + pixmap.save(&buffer, has_transparency?"PNG":"JPG"); // writes image into ba in PNG format } void AvatarDialog::load() @@ -166,7 +163,7 @@ void AvatarDialog::loadAvatarWidget() message += "\n RetroShare/stickers\n RetroShare/Data/stickers\n RetroShare/Data/Location/stickers"; ui->nostickersLabel->setText(message); } else { - ui->infoframe->hide(); + ui->info_Frame->hide(); } bool bOnlyOneGroup = (stickerTabs.count() == 1); @@ -272,7 +269,7 @@ void AvatarDialog::loadAvatarWidget() loadToolTips(firstpage); //Get widget's size - QSize sizeWidget = ui->avatarWidget->sizeHint(); + //QSize sizeWidget = ui->avatarWidget->sizeHint(); } diff --git a/retroshare-gui/src/gui/common/AvatarDialog.ui b/retroshare-gui/src/gui/common/AvatarDialog.ui index 9c5bc9482..a7b98cbcf 100644 --- a/retroshare-gui/src/gui/common/AvatarDialog.ui +++ b/retroshare-gui/src/gui/common/AvatarDialog.ui @@ -13,7 +13,7 @@ Change Avatar - + 0 @@ -37,14 +37,14 @@
- + QFrame::StyledPanel QFrame::Raised - + 3 @@ -52,14 +52,14 @@ 0 - + QFrame::StyledPanel QFrame::Raised - + @@ -74,7 +74,7 @@ - + @@ -121,7 +121,7 @@ - + Qt::Vertical @@ -146,7 +146,7 @@ 0 0 431 - 359 + 356 @@ -180,7 +180,7 @@ - + 9 @@ -194,7 +194,7 @@ 9 - + Qt::Horizontal @@ -219,7 +219,7 @@ - frame + gradFrame headerFrame @@ -235,9 +235,7 @@
gui/gxschannels/GxsChannelPostThumbnail.h
- - - + buttonBox diff --git a/retroshare-gui/src/gui/common/AvatarWidget.cpp b/retroshare-gui/src/gui/common/AvatarWidget.cpp index e6d6d03d9..02151730a 100644 --- a/retroshare-gui/src/gui/common/AvatarWidget.cpp +++ b/retroshare-gui/src/gui/common/AvatarWidget.cpp @@ -121,7 +121,7 @@ void AvatarWidget::setFrameType(FrameType type) //refreshAvatarImage(); refreshStatus(); - Rshare::refreshStyleSheet(this, false); + RsApplication::refreshStyleSheet(this, false); } void AvatarWidget::setId(const ChatId &id) { @@ -174,7 +174,7 @@ void AvatarWidget::refreshStatus() case NO_FRAME: case NORMAL_FRAME: { - Rshare::refreshStyleSheet(this, false); + RsApplication::refreshStyleSheet(this, false); break; } case STATUS_FRAME: @@ -252,7 +252,7 @@ void AvatarWidget::updateStatus(int status) mPeerState = status; setEnabled(((uint32_t) status == RS_STATUS_OFFLINE) ? false : true); - Rshare::refreshStyleSheet(this, false); + RsApplication::refreshStyleSheet(this, false); } void AvatarWidget::updateAvatar(const QString &peerId) diff --git a/retroshare-gui/src/gui/common/ElidedLabel.cpp b/retroshare-gui/src/gui/common/ElidedLabel.cpp index c444c8113..2486d0cae 100644 --- a/retroshare-gui/src/gui/common/ElidedLabel.cpp +++ b/retroshare-gui/src/gui/common/ElidedLabel.cpp @@ -126,7 +126,12 @@ bool ElidedLabel::paintElidedLine( QPainter* painter, QString plainText to.setWrapMode(wordWrap ? QTextOption::WrapAtWordBoundaryOrAnywhere : QTextOption::NoWrap); textLayout.setTextOption(to); - if (painter) painter->save(); + if (painter) + { + useFont.setPointSize(useFont.pointSize()); //Modify it to be copied in painter. Else painter keep defaut font size. + painter->save(); + painter->setFont(useFont); + } textLayout.beginLayout(); forever { //Get new line for text. @@ -148,7 +153,7 @@ bool ElidedLabel::paintElidedLine( QPainter* painter, QString plainText QTextLine lineEnd = textLayout.createLine(); if (!lineEnd.isValid() && (wordWrap #if QT_VERSION < QT_VERSION_CHECK(5,11,0) - || (fontMetrics.width(lastLine) < cr.width()) )) + || (fontMetrics.width(lastLine) < cr.width()) )) #else || (fontMetrics.horizontalAdvance(lastLine) < cr.width()) )) #endif @@ -220,10 +225,7 @@ bool ElidedLabel::paintElidedLine( QPainter* painter, QString plainText if(width+iTransX+cr.left() <= cr.right()) if (painter) - { - painter->setFont(useFont); painter->drawText(QPoint(iTransX + cr.left(), y + fontMetrics.ascent() + cr.top()), elidedLastLine); - } //Draw button to get ToolTip #if QT_VERSION < QT_VERSION_CHECK(5,11,0) @@ -256,7 +258,11 @@ void ElidedLabel::mousePressEvent(QMouseEvent *ev) return; // eat event } QLabel::mousePressEvent(ev); - emit clicked(ev->pos()); + + if(ev->buttons()==Qt::LeftButton) + emit clicked(ev->pos()); + else if(ev->buttons()==Qt::RightButton) + emit rightClicked(ev->pos()); } void ElidedLabel::setTextColor(const QColor &color) diff --git a/retroshare-gui/src/gui/common/ElidedLabel.h b/retroshare-gui/src/gui/common/ElidedLabel.h index 9290a61d1..2faa2f0ef 100644 --- a/retroshare-gui/src/gui/common/ElidedLabel.h +++ b/retroshare-gui/src/gui/common/ElidedLabel.h @@ -77,7 +77,8 @@ protected: signals: void elisionChanged(bool elided); - void clicked(QPoint pos); + void rightClicked(QPoint pos); + void clicked(QPoint pos); private: bool mElided; diff --git a/retroshare-gui/src/gui/common/Emoticons.cpp b/retroshare-gui/src/gui/common/Emoticons.cpp index d6bb17e4a..2341039cd 100644 --- a/retroshare-gui/src/gui/common/Emoticons.cpp +++ b/retroshare-gui/src/gui/common/Emoticons.cpp @@ -51,7 +51,7 @@ static QHash iconcache; void Emoticons::load() { loadSmiley(); - filters << "*.png" << "*.jpg" << "*.gif"; + filters << "*.png" << "*.jpg" << "*.jpeg" << "*.gif" << "*.webp"; stickerFolders << (QString::fromStdString(RsAccounts::AccountDirectory()) + "/stickers"); //under account, unique for user stickerFolders << (QString::fromStdString(RsAccounts::ConfigDirectory()) + "/stickers"); //under .retroshare, shared between users stickerFolders << (QString::fromStdString(RsAccounts::systemDataDirectory()) + "/stickers"); //exe's folder, shipped with RS @@ -205,10 +205,11 @@ void Emoticons::showSmileyWidget(QWidget *parent, QWidget *button, const char *s // (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)); + QSize size(28*fm.height()/14.0,28*fm.height()/14.0); + smTab->setIconSize(size); smTab->setMinimumWidth(400); smTab->setTabPosition(QTabWidget::South); - smTab->setStyleSheet("QTabBar::tab { height: 44px; width: 44px; }"); + smTab->setStyleSheet(QString("QTabBar::tab { height: %1px; width: %1px; padding: 0px; margin: 0px;}").arg(size.width()*1.1)); if (groupName.right(4).toLower() == ".png") smTab->addTab( tabGrpWidget, FilesDefs::getIconFromQtResourcePath(groupName), ""); diff --git a/retroshare-gui/src/gui/common/FilesDefs.cpp b/retroshare-gui/src/gui/common/FilesDefs.cpp index b7f0192a4..0048d5685 100644 --- a/retroshare-gui/src/gui/common/FilesDefs.cpp +++ b/retroshare-gui/src/gui/common/FilesDefs.cpp @@ -33,50 +33,56 @@ static QString getInfoFromFilename(const QString& filename, bool anyForUnknown, { QString ext = QFileInfo(filename).suffix().toLower(); - if (ext == "jpg" || ext == "jpeg" || ext == "tif" || ext == "tiff" || ext == "png" || ext == "gif" || ext == "bmp" || ext == "ico" || ext == "svg") { - return image ? ":/images/FileTypePicture.png" : QApplication::translate("FilesDefs", "Picture"); + if (ext == "jpg" || ext == "jpeg" || ext == "tif" || ext == "tiff" || ext == "png" || ext == "gif" || + ext == "bmp" || ext == "ico" || ext == "svg" || ext == "webp") { + return image ? ":/icons/filetype/picture.svg" : QApplication::translate("FilesDefs", "Picture"); } else if (ext == "avi" || ext == "mpg" || ext == "mpeg" || ext == "wmv" || ext == "divx" || ext == "ts" || ext == "mkv" || ext == "mp4" || ext == "flv" || ext == "mov" || ext == "asf" || ext == "xvid" || - ext == "vob" || ext == "qt" || ext == "rm" || ext == "3gp" || ext == "ogm") { - return image ? ":/images/FileTypeVideo.png" : QApplication::translate("FilesDefs", "Video"); - } else if (ext == "ogg" || ext == "mp3" || ext == "mp1" || ext == "mp2" || ext == "wav" || ext == "wma" || ext == "m4a" || ext == "flac" ||ext == "xpm") { - return image ? ":/images/FileTypeAudio.png" : QApplication::translate("FilesDefs", "Audio"); + ext == "vob" || ext == "qt" || ext == "rm" || ext == "3gp" || ext == "ogm" || ext == "webm") { + return image ? ":/icons/filetype/video.svg" : QApplication::translate("FilesDefs", "Video"); + } else if (ext == "ogg" || ext == "mp3" || ext == "mp1" || ext == "mp2" || ext == "wav" || ext == "wma" || + ext == "m4a" || ext == "flac" || ext == "xpm" || ext == "weba") { + return image ? ":/icons/filetype/audio.svg" : QApplication::translate("FilesDefs", "Audio"); } else if (ext == "tar" || ext == "bz2" || ext == "zip" || ext == "gz" || ext == "7z" || ext == "msi" || ext == "rar" || ext == "rpm" || ext == "ace" || ext == "jar" || ext == "tgz" || ext == "lha" || ext == "cab" || ext == "cbz"|| ext == "cbr" || ext == "alz" || ext == "sit" || ext == "arj" || ext == "deb") { - return image ? ":/images/FileTypeArchive.png" : QApplication::translate("FilesDefs", "Archive"); + return image ? ":/icons/filetype/archive.svg" : QApplication::translate("FilesDefs", "Archive"); } else if (ext == "app" || ext == "bat" || ext == "cgi" || ext == "com" || ext == "exe" || ext == "js" || ext == "pif" || ext == "py" || ext == "pl" || ext == "sh" || ext == "vb" || ext == "ws") { - return image ? ":/images/FileTypeProgram.png" : QApplication::translate("FilesDefs", "Program"); + return image ? ":/icons/filetype/program.svg" : QApplication::translate("FilesDefs", "Program"); } else if (ext == "iso" || ext == "nrg" || ext == "mdf" || ext == "img" || ext == "dmg" || ext == "bin" || ext == "uif") { - return image ? ":/images/FileTypeCDImage.png" : QApplication::translate("FilesDefs", "CD/DVD-Image"); + return image ? ":/icons/filetype/img.svg" : QApplication::translate("FilesDefs", "CD/DVD-Image"); } else if (ext == "txt" || ext == "ui" || ext == "doc" || ext == "rtf" || ext == "sxw" || ext == "xls" || ext == "pps" || ext == "xml" || ext == "nfo" || ext == "reg" || ext == "sxc" || ext == "odt" || ext == "ods" || ext == "dot" || ext == "ppt" || ext == "css" || ext == "crt" || ext == "html" || ext == "htm" || ext == "php") { - return image ? ":/images/FileTypeDocument.png" : QApplication::translate("FilesDefs", "Document"); + return image ? ":/icons/filetype/document.svg" : QApplication::translate("FilesDefs", "Document"); } else if (ext == "pdf") { - return image ? ":/images/mimetypes/pdf.png" : QApplication::translate("FilesDefs", "Document"); + return image ? ":/icons/filetype/pdf.svg" : QApplication::translate("FilesDefs", "Document"); } else if (ext == RsCollection::ExtensionString) { - return image ? ":/images/mimetypes/rscollection-16.png" : QApplication::translate("FilesDefs", "RetroShare collection file"); + return image ? ":/icons/filetype/collection.svg" : QApplication::translate("FilesDefs", "RetroShare collection file"); } else if (ext == "sub" || ext == "srt") { - return image ? ":/images/FileTypeAny.png" : QApplication::translate("FilesDefs", "Subtitles"); + return image ? ":/icons/filetype/any.svg" : QApplication::translate("FilesDefs", "Subtitles"); } else if (ext == "nds") { - return image ? ":/images/FileTypeAny.png" : QApplication::translate("FilesDefs", "Nintendo DS Rom"); + return image ? ":/icons/filetype/any.svg" : QApplication::translate("FilesDefs", "Nintendo DS Rom"); } else if (ext == "patch" || ext == "diff") { - return image ? ":/images/mimetypes/patch.png" : QApplication::translate("FilesDefs", "Patch"); + return image ? ":/icons/filetype/patch.svg" : QApplication::translate("FilesDefs", "Patch"); } else if (ext == "cpp") { - return image ? ":/images/mimetypes/source_cpp.png" : QApplication::translate("FilesDefs", "C++"); + return image ? ":/icons/filetype/cpp.svg" : QApplication::translate("FilesDefs", "C++"); } else if (ext == "h") { - return image ? ":/images/mimetypes/source_h.png" : QApplication::translate("FilesDefs", "Header"); + return image ? ":/icons/filetype/h.svg" : QApplication::translate("FilesDefs", "Header"); } else if (ext == "c") { - return image ? ":/images/mimetypes/source_c.png" : QApplication::translate("FilesDefs", "C "); + return image ? ":/icons/filetype/c.svg" : QApplication::translate("FilesDefs", "C "); + } else if (ext == "apk") { + return image ? ":/icons/filetype/apk.svg" : QApplication::translate("FilesDefs", "APK "); + } else if (ext == "dll") { + return image ? ":/icons/filetype/dll.svg" : QApplication::translate("FilesDefs", "DLL "); } if (anyForUnknown) { - return image ? ":/images/FileTypeAny.png" : ""; + return image ? ":/icons/filetype/any.svg" : ""; } return ""; @@ -156,7 +162,7 @@ QIcon FilesDefs::getIconFromGxsIdCache(const RsGxsId& id,const QIcon& setIcon, b if (setIcon.isNull()) { if (id.isNull()) - return getIconFromQtResourcePath(":/icons/notification.png"); + return getIconFromQtResourcePath(":/icons/notification.svg"); auto item = mIconCache.find(id); diff --git a/retroshare-gui/src/gui/common/FriendList.cpp b/retroshare-gui/src/gui/common/FriendList.cpp index 531a87f63..dd2d17875 100644 --- a/retroshare-gui/src/gui/common/FriendList.cpp +++ b/retroshare-gui/src/gui/common/FriendList.cpp @@ -55,6 +55,7 @@ #include "gui/chat/ChatUserNotify.h" #include "gui/connect/ConnectProgressDialog.h" #include "gui/common/ElidedLabel.h" +#include "gui/common/FilesDefs.h" #include "FriendList.h" #include "ui_FriendList.h" @@ -67,7 +68,7 @@ #define IMAGE_FRIENDINFO ":/images/info16.png" #define IMAGE_CHAT ":/icons/png/chats.png" #define IMAGE_MSG ":/icons/mail/write-mail.png" -#define IMAGE_CONNECT ":/images/connect_friend.png" +#define IMAGE_CONNECT ":/icons/connection.svg" #define IMAGE_COPYLINK ":/images/copyrslink.png" #define IMAGE_GROUP16 ":/images/user/group16.png" #define IMAGE_EDIT ":/icons/png/pencil-edit-button.png" @@ -297,8 +298,9 @@ void FriendList::peerTreeWidgetCustomPopupMenu() QMenu *contextMenu = new QMenu(this); - QWidget *widget = new QWidget(contextMenu); - widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); + QFrame *widget = new QFrame(contextMenu); + widget->setObjectName("gradFrame"); //Use qss + //widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); // create menu header QHBoxLayout *hbox = new QHBoxLayout(widget); @@ -306,12 +308,14 @@ void FriendList::peerTreeWidgetCustomPopupMenu() hbox->setSpacing(6); QLabel *iconLabel = new QLabel(widget); + iconLabel->setObjectName("trans_Icon"); QPixmap pix = FilesDefs::getPixmapFromQtResourcePath(":/images/user/friends24.png").scaledToHeight(QFontMetricsF(iconLabel->font()).height()*1.5); iconLabel->setPixmap(pix); iconLabel->setMaximumSize(iconLabel->frameSize().height() + pix.height(), pix.width()); hbox->addWidget(iconLabel); QLabel *textLabel = new QLabel("RetroShare", widget); + textLabel->setObjectName("trans_Text"); hbox->addWidget(textLabel); QSpacerItem *spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); diff --git a/retroshare-gui/src/gui/common/FriendList.h b/retroshare-gui/src/gui/common/FriendList.h index 3a5c15bbe..efcf034d4 100644 --- a/retroshare-gui/src/gui/common/FriendList.h +++ b/retroshare-gui/src/gui/common/FriendList.h @@ -125,7 +125,7 @@ private: std::set openGroups; std::set openPeers; - /* Color definitions (for standard see qss.default) */ + /* Color definitions (for standard see default.qss) */ QColor mTextColorGroup; QColor mTextColorStatus[RS_STATUS_COUNT]; diff --git a/retroshare-gui/src/gui/common/FriendListModel.cpp b/retroshare-gui/src/gui/common/FriendListModel.cpp index a2ae9052d..45c054698 100644 --- a/retroshare-gui/src/gui/common/FriendListModel.cpp +++ b/retroshare-gui/src/gui/common/FriendListModel.cpp @@ -42,7 +42,12 @@ #define IS_MESSAGE_UNREAD(flags) (flags & (RS_MSG_NEW | RS_MSG_UNREAD_BY_USER)) -#define IMAGE_GROUP24 ":/images/user/group24.png" +#define IMAGE_COWORKERS ":/icons/groups/green.svg" +#define IMAGE_FRIENDS ":/icons/groups/blue.svg" +#define IMAGE_FAMILY ":/icons/groups/purple.svg" +#define IMAGE_FAVORITES ":/icons/groups/yellow.svg" +#define IMAGE_OTHERCONTACTS ":/icons/groups/pink.svg" +#define IMAGE_OTHERGROUPS ":/icons/groups/red.svg" #define IMAGE_STAR_ON ":/images/star-on-16.png" #define IMAGE_STAR_OFF ":/images/star-off-16.png" @@ -60,7 +65,7 @@ static const uint32_t NODE_DETAILS_UPDATE_DELAY = 5; // update each node every 5 RsFriendListModel::RsFriendListModel(QObject *parent) : QAbstractItemModel(parent) - , mDisplayGroups(true), mDisplayStatusString(true) + , mDisplayGroups(true), mDisplayStatusString(true), mDisplayStatusIcon (false) , mLastInternalDataUpdate(0), mLastNodeUpdate(0) { mFilterStrings.clear(); @@ -136,13 +141,39 @@ template<> bool RsFriendListModel::convertInternalIdToIndex<8>(quintptr ref,Entr return true; } +static QIcon createAvatar(const QPixmap &avatar, const QPixmap &overlay) +{ + int avatarWidth = avatar.width(); + int avatarHeight = avatar.height(); + + QPixmap pixmap(avatar); + + int overlaySize = (avatarWidth > avatarHeight) ? (avatarWidth/2.5) : (avatarHeight/2.5); + int overlayX = avatarWidth - overlaySize; + int overlayY = avatarHeight - overlaySize; + + QPainter painter(&pixmap); + painter.drawPixmap(overlayX, overlayY, overlaySize, overlaySize, overlay); + + QIcon icon; + icon.addPixmap(pixmap); + return icon; +} void RsFriendListModel::setDisplayStatusString(bool b) { + preMods(); mDisplayStatusString = b; postMods(); } +void RsFriendListModel::setDisplayStatusIcon(bool b) +{ + preMods(); + mDisplayStatusIcon = b; + postMods(); +} + void RsFriendListModel::setDisplayGroups(bool b) { mDisplayGroups = b; @@ -236,7 +267,8 @@ RsFriendListModel::EntryIndex RsFriendListModel::EntryIndex::parent() const i.node_index = UNDEFINED_NODE_INDEX_VALUE; break; case ENTRY_TYPE_UNKNOWN: - RS_ERR("Unknown Entry type for parent."); + //Can be when request root index. + break; } return i; @@ -272,16 +304,16 @@ uint32_t RsFriendListModel::EntryIndex::parentRow(uint32_t nb_groups) const switch(type) { default: - case ENTRY_TYPE_UNKNOWN : return 0; - case ENTRY_TYPE_GROUP : return group_index; - case ENTRY_TYPE_PROFILE : return (group_index==UNDEFINED_GROUP_INDEX_VALUE)?(profile_index+nb_groups):profile_index; - case ENTRY_TYPE_NODE : return node_index; + case ENTRY_TYPE_UNKNOWN : return -1; + case ENTRY_TYPE_GROUP : return -1; + case ENTRY_TYPE_PROFILE : return (group_index==UNDEFINED_GROUP_INDEX_VALUE)?(-1):group_index; + case ENTRY_TYPE_NODE : return (group_index==UNDEFINED_GROUP_INDEX_VALUE)?(profile_index+nb_groups):profile_index; } } QModelIndex RsFriendListModel::index(int row, int column, const QModelIndex& parent) const { - if(row < 0 || column < 0 || column >= COLUMN_THREAD_NB_COLUMNS) + if(row < 0 || column < 0 || column >= columnCount(parent) || row >= rowCount(parent)) return QModelIndex(); if(parent.internalId() == 0) @@ -407,17 +439,28 @@ QVariant RsFriendListModel::textColorRole(const EntryIndex& fmpe,int column) con { switch(fmpe.type) { - case ENTRY_TYPE_GROUP: return QVariant(QBrush(mTextColorGroup)); - case ENTRY_TYPE_PROFILE: - case ENTRY_TYPE_NODE: return QVariant(QBrush(mTextColorStatus[onlineRole(fmpe,column).toInt()])); + case ENTRY_TYPE_GROUP: return QVariant(QBrush(mTextColorGroup)); + case ENTRY_TYPE_PROFILE: return QVariant(QBrush(mTextColorStatus[onlineRole(fmpe,column).toInt()])); + case ENTRY_TYPE_NODE: return QVariant(QBrush(mTextColorStatus[statusRole(fmpe,column).toInt()])); default: return QVariant(); } } -QVariant RsFriendListModel::statusRole(const EntryIndex& /*fmpe*/,int /*column*/) const +// statusRole returns the status (e.g. RS_STATUS_BUSY). It is used only to change the font color + +QVariant RsFriendListModel::statusRole(const EntryIndex& fmpe,int /*column*/) const { - return QVariant();//fmpe.mMsgStatus); + const HierarchicalNodeInformation *node = getNodeInfo(fmpe); + + if(node) + { + StatusInfo status; + rsStatus->getStatus(node->node_info.id, status); + + return QVariant(status.status); + } + return QVariant(); } bool RsFriendListModel::passesFilter(const EntryIndex& e,int /*column*/) const @@ -496,7 +539,7 @@ QVariant RsFriendListModel::sizeHintRole(const EntryIndex& e,int col) const y_factor *= 3.0; if(e.type == ENTRY_TYPE_GROUP) - y_factor = std::max(y_factor, 24.0f / 14.0f ); // allows to fit the 24 pixels icon for groups in the line + y_factor *= 1.5; switch(col) { @@ -542,6 +585,9 @@ QVariant RsFriendListModel::sortRole(const EntryIndex& entry,int column) const } } +// Only returns two values: RS_STATUS_ONLINE, or RS_STATUS_OFFLINE. This is used to decide on text font (bold) +// and whether profiles have children or not when offline nodes are shown. + QVariant RsFriendListModel::onlineRole(const EntryIndex& e, int /*col*/) const { switch(e.type) @@ -579,13 +625,10 @@ QVariant RsFriendListModel::onlineRole(const EntryIndex& e, int /*col*/) const { const HierarchicalNodeInformation *node = getNodeInfo(e); - if(node) - { - StatusInfo status; - rsStatus->getStatus(node->node_info.id, status); - - return QVariant(status.status); - } + if(node && bool(node->node_info.state & RS_PEER_STATE_CONNECTED)) + return QVariant(RS_STATUS_ONLINE); + else + return QVariant(RS_STATUS_OFFLINE); } } return QVariant(RS_STATUS_OFFLINE); @@ -620,12 +663,6 @@ QVariant RsFriendListModel::fontRole(const EntryIndex& e, int col) const } } -class AutoEndel -{ -public: - ~AutoEndel() { std::cerr << std::endl;} -}; - QVariant RsFriendListModel::displayRole(const EntryIndex& e, int col) const { #ifdef DEBUG_MODEL_INDEX @@ -744,7 +781,7 @@ QVariant RsFriendListModel::displayRole(const EntryIndex& e, int col) const else { return QVariant(QString::fromUtf8(node->node_info.location.c_str())+"\n" - + "(" + StatusDefs::name(onlineRole(e,col).toInt()) + ")"); + + "(" + StatusDefs::name(statusRole(e,col).toInt()) + ")"); } else return QVariant(QString::fromUtf8(node->node_info.location.c_str())); @@ -863,6 +900,69 @@ bool RsFriendListModel::getPeerOnlineStatus(const EntryIndex& e) const return (noded && (noded->node_info.state & RS_PEER_STATE_CONNECTED)); } +const RsFriendListModel::HierarchicalNodeInformation *RsFriendListModel::getBestNodeInformation(const HierarchicalProfileInformation *profileInfo, uint32_t *status) const +{ + if (status) { + *status = RS_STATUS_OFFLINE; + } + + if (!profileInfo) { + return NULL; + } + + const RsFriendListModel::HierarchicalNodeInformation *bestNodeInformation = NULL; + int bestStatusIndex = 0; + + /* Find the best status */ + for (uint32_t i = 0; i < profileInfo->child_node_indices.size(); ++i) { + const RsFriendListModel::HierarchicalNodeInformation &nodeInformation = mLocations[profileInfo->child_node_indices[i]]; + StatusInfo statusInfo; + rsStatus->getStatus(nodeInformation.node_info.id, statusInfo); + + int statusIndex = 0; + switch (statusInfo.status) { + case RS_STATUS_OFFLINE: + statusIndex = 1; + break; + + case RS_STATUS_INACTIVE: + statusIndex = 2; + break; + + case RS_STATUS_AWAY: + statusIndex = 3; + break; + + case RS_STATUS_BUSY: + statusIndex = 4; + break; + + case RS_STATUS_ONLINE: + statusIndex = 5; + break; + + default: + std::cerr << "FriendListModel: Unknown status " << statusInfo.status << std::endl; + } + + if (bestStatusIndex == 0 || statusIndex > bestStatusIndex) { + /* first status or better status */ + bestStatusIndex = statusIndex; + bestNodeInformation = &nodeInformation; + + if (status) { + *status = statusInfo.status; + } + } + } + + if (bestStatusIndex == 0) { + return NULL; + } + + return bestNodeInformation; +} + QVariant RsFriendListModel::decorationRole(const EntryIndex& entry,int col) const { if(col > 0) @@ -870,19 +970,68 @@ QVariant RsFriendListModel::decorationRole(const EntryIndex& entry,int col) cons switch(entry.type) { - case ENTRY_TYPE_GROUP: return QVariant(FilesDefs::getIconFromQtResourcePath(IMAGE_GROUP24)); + case ENTRY_TYPE_GROUP: + { + const HierarchicalGroupInformation *groupInfo = getGroupInfo(entry); + if (groupInfo->group_info.id.toStdString() == RS_GROUP_ID_FRIENDS.toStdString()) { + return QVariant(FilesDefs::getIconFromQtResourcePath(IMAGE_FRIENDS)); + } + if (groupInfo->group_info.id.toStdString() == RS_GROUP_ID_FAMILY.toStdString()) { + return QVariant(FilesDefs::getIconFromQtResourcePath(IMAGE_FAMILY)); + } + if (groupInfo->group_info.id.toStdString() == RS_GROUP_ID_COWORKERS.toStdString()) { + return QVariant(FilesDefs::getIconFromQtResourcePath(IMAGE_COWORKERS)); + } + if (groupInfo->group_info.id.toStdString() == RS_GROUP_ID_OTHERS.toStdString()) { + return QVariant(FilesDefs::getIconFromQtResourcePath(IMAGE_OTHERCONTACTS)); + } + if (groupInfo->group_info.id.toStdString() == RS_GROUP_ID_FAVORITES.toStdString()) { + return QVariant(FilesDefs::getIconFromQtResourcePath(IMAGE_FAVORITES)); + } + + return QVariant(FilesDefs::getIconFromQtResourcePath(IMAGE_OTHERGROUPS)); + } case ENTRY_TYPE_PROFILE: { if(!isProfileExpanded(entry)) { - QPixmap sslAvatar = FilesDefs::getPixmapFromQtResourcePath(AVATAR_DEFAULT_IMAGE); - + QPixmap sslAvatar; + bool foundAvatar = false; const HierarchicalProfileInformation *hn = getProfileInfo(entry); + uint32_t status = RS_STATUS_OFFLINE; + const HierarchicalNodeInformation *bestNodeInformation = NULL; - for(uint32_t i=0;ichild_node_indices.size();++i) - if(AvatarDefs::getAvatarFromSslId(RsPeerId(mLocations[hn->child_node_indices[i]].node_info.id.toStdString()), sslAvatar)) - return QVariant(QIcon(sslAvatar)); + if (mDisplayStatusIcon) { + bestNodeInformation = getBestNodeInformation(hn, &status); + if (bestNodeInformation) { + if (AvatarDefs::getAvatarFromSslId(RsPeerId(bestNodeInformation->node_info.id.toStdString()), sslAvatar, "")) { + /* Use avatar from best node */ + foundAvatar = true; + } + } + } + + if (!foundAvatar) { + /* Use first available avatar */ + for(uint32_t i=0;ichild_node_indices.size();++i) { + if(AvatarDefs::getAvatarFromSslId(RsPeerId(mLocations[hn->child_node_indices[i]].node_info.id.toStdString()), sslAvatar, "")) { + foundAvatar = true; + break; + } + } + } + + if (!foundAvatar || sslAvatar.isNull()) { + sslAvatar = FilesDefs::getPixmapFromQtResourcePath(AVATAR_DEFAULT_IMAGE); + } + + if (mDisplayStatusIcon) { + if (bestNodeInformation) { + QPixmap sslOverlayIcon = FilesDefs::getPixmapFromQtResourcePath(StatusDefs::imageStatus(status)); + return QVariant(QIcon(createAvatar(sslAvatar, sslOverlayIcon))); + } + } return QVariant(QIcon(sslAvatar)); } @@ -899,6 +1048,10 @@ QVariant RsFriendListModel::decorationRole(const EntryIndex& entry,int col) cons QPixmap sslAvatar; AvatarDefs::getAvatarFromSslId(RsPeerId(hn->node_info.id.toStdString()), sslAvatar); + if (mDisplayStatusIcon) { + QPixmap sslOverlayIcon = FilesDefs::getPixmapFromQtResourcePath(StatusDefs::imageStatus(statusRole(entry, col).toInt())); + return QVariant(QIcon(createAvatar(sslAvatar, sslOverlayIcon))); + } return QVariant(QIcon(sslAvatar)); } @@ -1051,7 +1204,12 @@ std::map::const_iterator RsFriendListModel::createInvalidatedP if(rsPeers->getGPGDetails(pgp_id,hprof.profile_info)) { - std::cerr << "(EE) asked to create an invalidated profile that already exists!" << std::endl; + std::cerr << "(EE) asked to create an invalidated profile that already exists: " << pgp_id << std::endl; + + pgp_indices[pgp_id] = mProfiles.size(); + mProfiles.push_back(hprof); + it2 = pgp_indices.find(pgp_id); + return it2; } @@ -1114,8 +1272,6 @@ void RsFriendListModel::updateInternalData() mLocations.clear(); mTopLevel.clear(); - endResetModel(); - auto TL = mTopLevel ; // This allows to fill TL without touching mTopLevel outside of [begin/end]InsertRows(). // create a map of profiles and groups @@ -1251,7 +1407,8 @@ void RsFriendListModel::updateInternalData() endInsertRows(); } - postMods(); + endResetModel(); + postMods(); mLastInternalDataUpdate = time(NULL); } diff --git a/retroshare-gui/src/gui/common/FriendListModel.h b/retroshare-gui/src/gui/common/FriendListModel.h index 871dc14b9..e19a84f04 100644 --- a/retroshare-gui/src/gui/common/FriendListModel.h +++ b/retroshare-gui/src/gui/common/FriendListModel.h @@ -129,6 +129,10 @@ public: void setDisplayStatusString(bool b); bool getDisplayStatusString() const { return mDisplayStatusString; } + void setDisplayStatusIcon(bool b); + bool getDisplayStatusIcon() const { return mDisplayStatusIcon; } + + EntryType getType(const QModelIndex&) const; @@ -156,7 +160,7 @@ public: void clear() ; - /* Color definitions (for standard see qss.default) */ + /* Color definitions (for standard see default.qss) */ QColor mTextColorGroup; QColor mTextColorStatus[RS_STATUS_COUNT]; @@ -219,11 +223,14 @@ private: uint32_t updateFilterStatus(ForumModelIndex i,int column,const QStringList& strings); + const HierarchicalNodeInformation *getBestNodeInformation(const HierarchicalProfileInformation *profileInfo, uint32_t *status = NULL) const; + QStringList mFilterStrings; FilterType mFilterType; bool mDisplayGroups ; bool mDisplayStatusString ; + bool mDisplayStatusIcon ; rstime_t mLastInternalDataUpdate; rstime_t mLastNodeUpdate;; diff --git a/retroshare-gui/src/gui/common/FriendSelectionWidget.cpp b/retroshare-gui/src/gui/common/FriendSelectionWidget.cpp index a2b355e06..d9fc4b8dc 100644 --- a/retroshare-gui/src/gui/common/FriendSelectionWidget.cpp +++ b/retroshare-gui/src/gui/common/FriendSelectionWidget.cpp @@ -51,9 +51,9 @@ #define ROLE_SORT_STANDARD_GROUP Qt::UserRole + 2 #define ROLE_SORT_NAME Qt::UserRole + 3 #define ROLE_SORT_STATE Qt::UserRole + 4 -#define ROLE_FILTER_REASON Qt::UserRole + 5 +#define ROLE_SORT_SELECTED Qt::UserRole + 5 +#define ROLE_FILTER_REASON Qt::UserRole + 6 -#define IMAGE_GROUP16 ":/images/user/group16.png" #define IMAGE_FRIENDINFO ":/images/peerdetails_16x16.png" static bool isSelected(FriendSelectionWidget::Modus modus, QTreeWidgetItem *item) @@ -127,12 +127,48 @@ FriendSelectionWidget::FriendSelectionWidget(QWidget *parent) ui->filterLineEdit->showFilterIcon(); /* Refresh style to have the correct text color */ - Rshare::refreshStyleSheet(this, false); + RsApplication::refreshStyleSheet(this, false); + + mEventHandlerId_identities = 0; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) { + RsQThreadUtils::postToObject( [this,event]() { handleEvent_main_thread(event); }) ;}, mEventHandlerId_identities, RsEventType::GXS_IDENTITY ); + mEventHandlerId_peers = 0; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) { + RsQThreadUtils::postToObject( [this,event]() { handleEvent_main_thread(event); }) ;}, mEventHandlerId_peers, RsEventType::PEER_CONNECTION ); + + mFontSizeHandler.registerFontSize(ui->friendList); } +void FriendSelectionWidget::handleEvent_main_thread(std::shared_ptr event) +{ + const RsGxsIdentityEvent *fe = dynamic_cast(event.get()); + + if(fe) + { + updateDisplay(true); + update(); // Qt flush + return; + } + const RsConnectionEvent *fp = dynamic_cast(event.get()); + + if(fp) + switch(fp->mConnectionInfoCode) + { + case RsConnectionEventCode::PEER_REMOVED: + case RsConnectionEventCode::PEER_ADDED: + updateDisplay(true); + update(); // Qt flush + break; + default: break ; + } +} + + FriendSelectionWidget::~FriendSelectionWidget() { - delete ui; + rsEvents->unregisterEventsHandler(mEventHandlerId_peers); + rsEvents->unregisterEventsHandler(mEventHandlerId_identities); + delete ui; } void FriendSelectionWidget::changeEvent(QEvent *e) @@ -382,12 +418,34 @@ void FriendSelectionWidget::secured_fillList() // Add item to the list ui->friendList->addTopLevelItem(groupItem); + QFontMetricsF fontMetrics(ui->friendList->font()); + int avatarHeight = fontMetrics.height() * 1.5; + ui->friendList->setIconSize(QSize(avatarHeight, avatarHeight)); + groupItem->setFlags(Qt::ItemIsUserCheckable | groupItem->flags()); groupItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); groupItem->setTextAlignment(COLUMN_NAME, Qt::AlignLeft | Qt::AlignVCenter); - groupItem->setIcon(COLUMN_NAME, FilesDefs::getIconFromQtResourcePath(IMAGE_GROUP16)); - groupItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(groupInfo->id.toStdString())); + if (groupInfo->id.toStdString() == RS_GROUP_ID_FRIENDS.toStdString()) { + groupItem->setIcon(COLUMN_NAME, FilesDefs::getIconFromQtResourcePath(":/icons/groups/blue.svg")); + } + else if (groupInfo->id.toStdString() == RS_GROUP_ID_FAMILY.toStdString()) { + groupItem->setIcon(COLUMN_NAME, FilesDefs::getIconFromQtResourcePath(":/icons/groups/purple.svg")); + } + else if (groupInfo->id.toStdString() == RS_GROUP_ID_COWORKERS.toStdString()) { + groupItem->setIcon(COLUMN_NAME, FilesDefs::getIconFromQtResourcePath(":/icons/groups/green.svg")); + } + else if (groupInfo->id.toStdString() == RS_GROUP_ID_OTHERS.toStdString()) { + groupItem->setIcon(COLUMN_NAME, FilesDefs::getIconFromQtResourcePath(":/icons/groups/pink.svg")); + } + else if (groupInfo->id.toStdString() == RS_GROUP_ID_FAVORITES.toStdString()) { + groupItem->setIcon(COLUMN_NAME, FilesDefs::getIconFromQtResourcePath(":/icons/groups/yellow.svg")); + } + else { + groupItem->setIcon(COLUMN_NAME, FilesDefs::getIconFromQtResourcePath(":/icons/groups/red.svg")); + } + + groupItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(groupInfo->id.toStdString())); groupItem->setExpanded(true); @@ -612,8 +670,13 @@ void FriendSelectionWidget::secured_fillList() emit itemAdded(IDTYPE_GXS, QString::fromStdString(detail.mId.toStdString()), gxsItem); if (std::find(gxsIdsSelected.begin(), gxsIdsSelected.end(), detail.mId) != gxsIdsSelected.end()) + { setSelected(mListModus, gxsItem, true); - } + gxsItem->setData(COLUMN_NAME,ROLE_SORT_SELECTED,0); + } + else + gxsItem->setData(COLUMN_NAME,ROLE_SORT_SELECTED,1); + } } if(mShowTypes & SHOW_CONTACTS) { @@ -1164,9 +1227,18 @@ std::string FriendSelectionWidget::idFromItem(QTreeWidgetItem *item) return item->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); } +void FriendSelectionWidget::sortByChecked(bool) +{ + mCompareRole->clear(); + mCompareRole->setRole(COLUMN_NAME,ROLE_SORT_SELECTED); + + ui->friendList->resort(); +} + void FriendSelectionWidget::sortByState(bool sort) { - mCompareRole->setRole(COLUMN_NAME, ROLE_SORT_GROUP); + mCompareRole->clear(); + mCompareRole->setRole(COLUMN_NAME, ROLE_SORT_GROUP); mCompareRole->addRole(COLUMN_NAME, ROLE_SORT_STANDARD_GROUP); if (sort) { diff --git a/retroshare-gui/src/gui/common/FriendSelectionWidget.h b/retroshare-gui/src/gui/common/FriendSelectionWidget.h index 7a2fb718e..425e16774 100644 --- a/retroshare-gui/src/gui/common/FriendSelectionWidget.h +++ b/retroshare-gui/src/gui/common/FriendSelectionWidget.h @@ -24,7 +24,9 @@ #include #include +#include "retroshare/rsevents.h" #include +#include "util/FontSizeHandler.h" namespace Ui { class FriendSelectionWidget; @@ -131,7 +133,8 @@ signals: public slots: void sortByState(bool sort); - void filterConnected(bool filter); + void sortByChecked(bool sort); + void filterConnected(bool filter); private slots: void groupsChanged(int type); @@ -151,6 +154,8 @@ private: void setSelectedIds_internal(IdType idType, const std::set &ids, bool add); private: + void handleEvent_main_thread(std::shared_ptr event); + bool mStarted; RSTreeWidgetItemCompareRole *mCompareRole; Modus mListModus; @@ -162,7 +167,7 @@ private: QAction *mActionSortByState; QAction *mActionFilterConnected; - /* Color definitions (for standard see qss.default) */ + /* Color definitions (for standard see default.qss) */ QColor mTextColorOnline; Ui::FriendSelectionWidget *ui; @@ -173,6 +178,11 @@ private: QList mContextMenuActions; std::set mPreSelectedIds; // because loading of GxsIds is asynchroneous we keep selected Ids from the client in a list here and use it to initialize after loading them. + + FontSizeHandler mFontSizeHandler; + + RsEventsHandlerId_t mEventHandlerId_identities; + RsEventsHandlerId_t mEventHandlerId_peers; }; Q_DECLARE_OPERATORS_FOR_FLAGS(FriendSelectionWidget::ShowTypes) diff --git a/retroshare-gui/src/gui/common/FriendSelectionWidget.ui b/retroshare-gui/src/gui/common/FriendSelectionWidget.ui index d3682f014..a9bc8b407 100644 --- a/retroshare-gui/src/gui/common/FriendSelectionWidget.ui +++ b/retroshare-gui/src/gui/common/FriendSelectionWidget.ui @@ -66,7 +66,7 @@ LineEditClear QLineEdit -
gui/common/LineEditClear.h
+
gui/common/LineEditClear.h
RSTreeWidget diff --git a/retroshare-gui/src/gui/common/GroupChooser.cpp b/retroshare-gui/src/gui/common/GroupChooser.cpp index be456f96d..8cdf2fd2d 100644 --- a/retroshare-gui/src/gui/common/GroupChooser.cpp +++ b/retroshare-gui/src/gui/common/GroupChooser.cpp @@ -20,15 +20,16 @@ #include "GroupChooser.h" +#include + +#include + #include #include -#include -#include - /** Constructor */ GroupChooser::GroupChooser(QWidget *parent) -: QComboBox(parent), mFlags(0) + : RSComboBox(parent), mFlags(0) { return; } diff --git a/retroshare-gui/src/gui/common/GroupChooser.h b/retroshare-gui/src/gui/common/GroupChooser.h index fa7e2eba7..04d821bc2 100644 --- a/retroshare-gui/src/gui/common/GroupChooser.h +++ b/retroshare-gui/src/gui/common/GroupChooser.h @@ -20,13 +20,14 @@ #pragma once -#include +#include "gui/common/RSComboBox.h" + #include -class GroupChooser : public QComboBox +class GroupChooser : public RSComboBox { public: - GroupChooser(QWidget *parent = NULL); + GroupChooser(QWidget *parent = nullptr); void loadGroups(uint32_t chooserFlags, const RsNodeGroupId& defaultId); bool getChosenGroup(RsNodeGroupId& id); diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.cpp b/retroshare-gui/src/gui/common/GroupTreeWidget.cpp index 685c54169..43861c4c6 100644 --- a/retroshare-gui/src/gui/common/GroupTreeWidget.cpp +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.cpp @@ -60,16 +60,25 @@ GroupTreeWidget::GroupTreeWidget(QWidget *parent) : connect(ui->filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterChanged())); connect(ui->treeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customContextMenuRequested(QPoint))); - connect(ui->treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); + connect(ui->treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))); connect(ui->treeWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)), this, SLOT(itemActivated(QTreeWidgetItem*,int))); if (!style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, NULL, this)) { // need signal itemClicked too connect(ui->treeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(itemActivated(QTreeWidgetItem*,int))); } + int H = QFontMetricsF(ui->treeWidget->font()).height() ; +#if QT_VERSION < QT_VERSION_CHECK(5,11,0) + int W = QFontMetricsF(ui->treeWidget->font()).width("_") ; + int D = QFontMetricsF(ui->treeWidget->font()).width("9999-99-99[]") ; +#else + int W = QFontMetricsF(ui->treeWidget->font()).horizontalAdvance("_") ; + int D = QFontMetricsF(ui->treeWidget->font()).horizontalAdvance("9999-99-99[]") ; +#endif + /* Add own item delegate */ RSElidedItemDelegate *itemDelegate = new RSElidedItemDelegate(this); - itemDelegate->setSpacing(QSize(0, 2)); + itemDelegate->setSpacing(QSize(W/2, H/4)); ui->treeWidget->setItemDelegate(itemDelegate); /* Set compare role for each column */ @@ -87,10 +96,6 @@ GroupTreeWidget::GroupTreeWidget(QWidget *parent) : ui->treeWidget->enableColumnCustomize(true); ui->treeWidget->setColumnCustomizable(GTW_COLUMN_NAME, false); - int S = QFontMetricsF(font()).height() ; - int W = QFontMetricsF(font()).width("_") ; - int D = QFontMetricsF(font()).width("9999-99-99[]") ; - QTreeWidgetItem *headerItem = ui->treeWidget->headerItem(); headerItem->setText(GTW_COLUMN_NAME, tr("Name")); headerItem->setText(GTW_COLUMN_UNREAD, ""); @@ -143,7 +148,19 @@ GroupTreeWidget::GroupTreeWidget(QWidget *parent) : connect(ui->distantSearchLineEdit,SIGNAL(returnPressed()),this,SLOT(distantSearch())) ; - ui->treeWidget->setIconSize(QSize(S*1.8,S*1.8)); + mFontSizeHandler.registerFontSize(ui->treeWidget, 1.8f, [this] (QAbstractItemView*, int fontSize) { + // Set new font size on all items + QTreeWidgetItemIterator it(ui->treeWidget); + while (*it) { + QTreeWidgetItem *item = *it; + + QFont font = item->font(GTW_COLUMN_NAME); + font.setPointSize(fontSize); + item->setFont(GTW_COLUMN_NAME, font); + + ++it; + } + }); } GroupTreeWidget::~GroupTreeWidget() @@ -205,9 +222,9 @@ void GroupTreeWidget::updateColors() int color = item->data(GTW_COLUMN_DATA, ROLE_COLOR).toInt(); if (color >= 0) { - item->setData(GTW_COLUMN_NAME, Qt::TextColorRole, mTextColor[color]); + item->setData(GTW_COLUMN_NAME, Qt::ForegroundRole, mTextColor[color]); } else { - item->setData(GTW_COLUMN_NAME, Qt::TextColorRole, QVariant()); + item->setData(GTW_COLUMN_NAME, Qt::ForegroundRole, QVariant()); } } @@ -246,24 +263,24 @@ void GroupTreeWidget::itemActivated(QTreeWidgetItem *item, int column) QTreeWidgetItem *GroupTreeWidget::addCategoryItem(const QString &name, const QIcon &icon, bool expand, int sortOrder /*= -1*/) { - QFont font; RSTreeWidgetItem *item = new RSTreeWidgetItem(); ui->treeWidget->addTopLevelItem(item); // To get StyleSheet for Items - ui->treeWidget->style()->unpolish(ui->treeWidget); - ui->treeWidget->style()->polish(ui->treeWidget); +// ui->treeWidget->style()->unpolish(ui->treeWidget); +// ui->treeWidget->style()->polish(ui->treeWidget); item->setText(GTW_COLUMN_NAME, name); item->setData(GTW_COLUMN_DATA, ROLE_NAME, name); - font = item->font(GTW_COLUMN_NAME); - font.setBold(true); - item->setFont(GTW_COLUMN_NAME, font); + QFont itFont = item->font(GTW_COLUMN_NAME); + itFont.setBold(true); + itFont.setPointSize(ui->treeWidget->font().pointSize()); //use treeWidget font size defined in ui. + item->setFont(GTW_COLUMN_NAME, itFont); item->setIcon(GTW_COLUMN_NAME, icon); - int S = QFontMetricsF(font).height(); + //int S = QFontMetricsF(itFont).height(); - item->setSizeHint(GTW_COLUMN_NAME, QSize(S*1.9, S*1.9)); - item->setData(GTW_COLUMN_NAME, Qt::TextColorRole, textColorCategory()); + //item->setSizeHint(GTW_COLUMN_NAME, QSize(S*1.9, S*1.9)); //size hint is calculated by item delegate. Use itemDelegate->setSpacing() in constructor. + item->setData(GTW_COLUMN_NAME, Qt::ForegroundRole, textColorCategory()); item->setData(GTW_COLUMN_DATA, ROLE_COLOR, GROUPTREEWIDGET_COLOR_CATEGORY); item->setExpanded(expand); @@ -385,6 +402,7 @@ void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList< if (item == NULL) { item = new RSTreeWidgetItem(compareRole); item->setData(GTW_COLUMN_DATA, ROLE_ID, itemInfo.id); + item->setFont(GTW_COLUMN_NAME, ui->treeWidget->font()); //static_cast(item)->setNoDataAsLast(true); //Uncomment this to sort data with QVariant() always at end. categoryItem->addChild(item); } @@ -506,18 +524,18 @@ void GroupTreeWidget::setUnreadCount(QTreeWidgetItem *item, int unreadCount) return; } - QFont font = item->font(GTW_COLUMN_NAME); + QFont itFont = item->font(GTW_COLUMN_NAME); if (unreadCount) { item->setText(GTW_COLUMN_UNREAD, QString::number(unreadCount)); - font.setBold(true); + itFont.setBold(true); } else { item->setText(GTW_COLUMN_UNREAD, ""); - font.setBold(false); + itFont.setBold(false); } item->setData(GTW_COLUMN_UNREAD, ROLE_SORT, unreadCount); - item->setFont(GTW_COLUMN_NAME, font); + item->setFont(GTW_COLUMN_NAME, itFont); } QTreeWidgetItem *GroupTreeWidget::getItemFromId(const QString &id) diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.h b/retroshare-gui/src/gui/common/GroupTreeWidget.h index 6125dac28..4aadb1c51 100644 --- a/retroshare-gui/src/gui/common/GroupTreeWidget.h +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.h @@ -25,6 +25,7 @@ #include #include +#include "util/FontSizeHandler.h" class QToolButton; class RshareSettings; @@ -158,11 +159,12 @@ private: private: - /* Color definitions (for standard see qss.default) */ + /* Color definitions (for standard see default.qss) */ QColor mTextColor[GROUPTREEWIDGET_COLOR_COUNT]; // Compare role used for each column RSTreeWidgetItemCompareRole *compareRole; + FontSizeHandler mFontSizeHandler; Ui::GroupTreeWidget *ui; }; diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.ui b/retroshare-gui/src/gui/common/GroupTreeWidget.ui index f925cf8ed..10b5eb48b 100644 --- a/retroshare-gui/src/gui/common/GroupTreeWidget.ui +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.ui @@ -35,10 +35,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/retroshare-gui/src/gui/common/HeaderFrame.ui b/retroshare-gui/src/gui/common/HeaderFrame.ui index 45a65943a..f9c436f68 100644 --- a/retroshare-gui/src/gui/common/HeaderFrame.ui +++ b/retroshare-gui/src/gui/common/HeaderFrame.ui @@ -16,15 +16,24 @@ 76 - + 0 - + + 0 + + + 0 + + + 0 + + 0 - + 0 @@ -37,7 +46,7 @@ 76 - + 12 @@ -67,7 +76,14 @@ - + + + + 22 + 75 + true + + Header text @@ -77,7 +93,7 @@ - + QFrame::HLine @@ -90,9 +106,9 @@ - StyledElidedLabel + ElidedLabel QLabel -
gui/common/StyledElidedLabel.h
+
gui/common/ElidedLabel.h
diff --git a/retroshare-gui/src/gui/common/LineEditClear.cpp b/retroshare-gui/src/gui/common/LineEditClear.cpp index b439aaa07..cf45bc75b 100644 --- a/retroshare-gui/src/gui/common/LineEditClear.cpp +++ b/retroshare-gui/src/gui/common/LineEditClear.cpp @@ -24,22 +24,24 @@ #include #include #include +#include //#if QT_VERSION < 0x040700 #if QT_VERSION < 0x050000//PlaceHolder text only shown when not have focus in Qt4 #include #endif -#define IMAGE_FILTER ":/images/find-16.png" +#define IMAGE_FILTER ":/images/find.png" LineEditClear::LineEditClear(QWidget *parent) - : QLineEdit(parent) + : QLineEdit(parent) { mActionGroup = NULL; mFilterButton = NULL; + QFontMetrics fm(this->font()); mClearButton = new QToolButton(this); - mClearButton->setFixedSize(16, 16); - mClearButton->setIconSize(QSize(16, 16)); + mClearButton->setFixedSize(fm.height(), fm.height()); + mClearButton->setIconSize(QSize(fm.height(), fm.height())); mClearButton->setCursor(Qt::ArrowCursor); mClearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }" "QToolButton { border-image: url(:/images/closenormal.png) }" @@ -50,7 +52,7 @@ LineEditClear::LineEditClear(QWidget *parent) mClearButton->setToolTip("Clear Filter"); connect(mClearButton, SIGNAL(clicked()), this, SLOT(clear())); - connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateClearButton(const QString&))); + connect(this, SIGNAL(textChanged(QString)), this, SLOT(updateClearButton(QString))); //#if QT_VERSION < 0x040700 #if QT_VERSION < 0x050000//PlaceHolder text only shown when not have focus in Qt4 @@ -124,15 +126,18 @@ void LineEditClear::showFilterIcon() } mFilterButton = new QToolButton(this); - mFilterButton->setFixedSize(16, 16); - mFilterButton->setIcon(FilesDefs::getIconFromQtResourcePath(IMAGE_FILTER)); - //mFilterButton->setIconSize(filterPixmap.size()); - mFilterButton->setCursor(Qt::ArrowCursor); - mFilterButton->setStyleSheet("QToolButton { border: none; padding: 0px; }" - "QToolButton[popupMode=\"2\"] { padding-right: 10px; }" - "QToolButton::menu-indicator[popupMode=\"2\"] { subcontrol-origin: padding; subcontrol-position: bottom right; top: 5px; left: -3px; width: 7px; }"); - mFilterButton->move(2, 2); + mFilterButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); mFilterButton->setFocusPolicy(Qt::NoFocus); + mFilterButton->setPopupMode(QToolButton::InstantPopup); + mFilterButton->setAutoFillBackground(true); + mFilterButton->setToolButtonStyle(Qt::ToolButtonIconOnly); + setFilterButtonIcon(QIcon()); + mFilterButton->setCursor(Qt::ArrowCursor); + mFilterButton->setStyleSheet("QToolButton { background: transparent; border: none; margin: 0px; padding: 0px; }" + "QToolButton[popupMode=\"2\"] { padding-right: 10px; }" + "QToolButton::menu-indicator[popupMode=\"2\"] { subcontrol-origin: padding; subcontrol-position: bottom right; top: 5px; left: -3px; width: 7px; }" + ); + mFilterButton->move(2, 2); reposButtons(); } @@ -155,9 +160,6 @@ void LineEditClear::addFilter(const QIcon &icon, const QString &text, int id, co showFilterIcon(); if (mActionGroup == NULL) { - mFilterButton->setFixedSize(26, 16); - mFilterButton->setPopupMode(QToolButton::InstantPopup); - mActionGroup = new QActionGroup(this); mActionGroup->setExclusive(true); @@ -222,10 +224,21 @@ void LineEditClear::activateAction(QAction *action) setPlaceholderText(*description); } - QIcon icon = action->icon(); - if (icon.isNull()) { - icon = FilesDefs::getIconFromQtResourcePath(IMAGE_FILTER); - } - - mFilterButton->setIcon(icon); + setFilterButtonIcon(action->icon()); +} + +void LineEditClear::setFilterButtonIcon(const QIcon &icon) +{ + if (icon.isNull()) + mFilterButton->setIcon(FilesDefs::getIconFromQtResourcePath(IMAGE_FILTER)); + else + mFilterButton->setIcon(icon); + + ensurePolished(); +#if !defined(Q_OS_DARWIN) + QFontMetrics fm(this->font()); + QSize size(fm.width("___"), fm.height()); + mFilterButton->setFixedSize(size); + mFilterButton->setIconSize(size); +#endif } diff --git a/retroshare-gui/src/gui/common/LineEditClear.h b/retroshare-gui/src/gui/common/LineEditClear.h index e8aea0626..ae30f6127 100644 --- a/retroshare-gui/src/gui/common/LineEditClear.h +++ b/retroshare-gui/src/gui/common/LineEditClear.h @@ -61,6 +61,7 @@ protected: #endif void reposButtons(); void activateAction(QAction *action); + void setFilterButtonIcon(const QIcon &icon); private slots: void updateClearButton(const QString &text); diff --git a/retroshare-gui/src/gui/common/MacDockIconHandler.h b/retroshare-gui/src/gui/common/MacDockIconHandler.h new file mode 100644 index 000000000..d9d4d41f5 --- /dev/null +++ b/retroshare-gui/src/gui/common/MacDockIconHandler.h @@ -0,0 +1,27 @@ +// Copyright (c) 2011-2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef MACDOCKICONHANDLER_H +#define MACDOCKICONHANDLER_H + +#include + +/** macOS-specific Dock icon handler. + */ +class MacDockIconHandler : public QObject +{ + Q_OBJECT + +public: + static MacDockIconHandler *instance(); + static void cleanup(); + +Q_SIGNALS: + void dockIconClicked(); + +private: + MacDockIconHandler(); +}; + +#endif // MACDOCKICONHANDLER_H diff --git a/retroshare-gui/src/gui/common/MacDockIconHandler.mm b/retroshare-gui/src/gui/common/MacDockIconHandler.mm new file mode 100644 index 000000000..51a26135d --- /dev/null +++ b/retroshare-gui/src/gui/common/MacDockIconHandler.mm @@ -0,0 +1,53 @@ +// Copyright (c) 2011-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "MacDockIconHandler.h" + +#include +#include + +static MacDockIconHandler *s_instance = nullptr; + +bool dockClickHandler(id self, SEL _cmd, ...) { + Q_UNUSED(self) + Q_UNUSED(_cmd) + + Q_EMIT s_instance->dockIconClicked(); + + // Return NO (false) to suppress the default macOS actions + return false; +} + +void setupDockClickHandler() { + Class delClass = (Class)[[[NSApplication sharedApplication] delegate] class]; + SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:"); + class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:"); +} + +MacDockIconHandler::MacDockIconHandler() : QObject() +{ + setupDockClickHandler(); +} + +MacDockIconHandler *MacDockIconHandler::instance() +{ + if (!s_instance) + s_instance = new MacDockIconHandler(); + return s_instance; +} + +void MacDockIconHandler::cleanup() +{ + delete s_instance; +} + +/** + * Force application activation on macOS. With Qt 5.5.1 this is required when + * an action in the Dock menu is triggered. + * TODO: Define a Qt version where it's no-longer necessary. + */ +void ForceActivation() +{ + [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; +} diff --git a/retroshare-gui/src/gui/common/MimeTextEdit.cpp b/retroshare-gui/src/gui/common/MimeTextEdit.cpp index b24a65879..3d3398b0c 100644 --- a/retroshare-gui/src/gui/common/MimeTextEdit.cpp +++ b/retroshare-gui/src/gui/common/MimeTextEdit.cpp @@ -32,6 +32,7 @@ #include "MimeTextEdit.h" #include "util/HandleRichText.h" #include "gui/RetroShareLink.h" +#include "util/imageutil.h" #include @@ -246,6 +247,18 @@ void MimeTextEdit::contextMenuEvent(QContextMenuEvent *e) QMenu *contextMenu = createStandardContextMenu(e->pos()); + if (ImageUtil::checkImage(this, e->pos())) { + contextMenu->addSeparator(); + + QAction *a = contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/images/document_save.png"), tr("Save image"), this, SLOT(saveImage())); + a->setData(e->pos()); + + a = contextMenu->addAction( tr("Copy image"), this, SLOT(copyImage())); + a->setData(e->pos()); + + contextMenu->addSeparator(); + } + /* Add actions for pasting links */ contextMenu->addAction( tr("Paste as plain text"), this, SLOT(pastePlainText())); QAction *spoilerAction = contextMenu->addAction(tr("Spoiler"), this, SLOT(spoiler())); @@ -292,3 +305,27 @@ void MimeTextEdit::spoiler() { RsHtml::insertSpoilerText(this->textCursor()); } + +void MimeTextEdit::saveImage() +{ + QAction *action = dynamic_cast(sender()) ; + if (!action) { + return; + } + + QPoint point = action->data().toPoint(); + QTextCursor cursor = cursorForPosition(point); + ImageUtil::extractImage(window(), cursor); +} + +void MimeTextEdit::copyImage() +{ + QAction *action = dynamic_cast(sender()) ; + if (!action) { + return; + } + + QPoint point = action->data().toPoint(); + QTextCursor cursor = cursorForPosition(point); + ImageUtil::copyImage(window(), cursor); +} diff --git a/retroshare-gui/src/gui/common/MimeTextEdit.h b/retroshare-gui/src/gui/common/MimeTextEdit.h index 9c47cac23..b575c1ac9 100644 --- a/retroshare-gui/src/gui/common/MimeTextEdit.h +++ b/retroshare-gui/src/gui/common/MimeTextEdit.h @@ -75,6 +75,8 @@ private slots: void pasteOwnCertificateLink(); void pastePlainText(); void spoiler(); + void saveImage(); + void copyImage(); private: QString textUnderCursor() const; diff --git a/retroshare-gui/src/gui/common/NewFriendList.cpp b/retroshare-gui/src/gui/common/NewFriendList.cpp index ba794fafe..4ed25d951 100644 --- a/retroshare-gui/src/gui/common/NewFriendList.cpp +++ b/retroshare-gui/src/gui/common/NewFriendList.cpp @@ -54,6 +54,7 @@ #include "gui/chat/ChatUserNotify.h" #include "gui/connect/ConnectProgressDialog.h" #include "gui/common/ElidedLabel.h" +#include "gui/notifyqt.h" #include "NewFriendList.h" #include "ui_NewFriendList.h" @@ -66,17 +67,17 @@ #define IMAGE_FRIENDINFO ":/images/info16.png" #define IMAGE_CHAT ":/icons/png/chats.png" #define IMAGE_MSG ":/icons/mail/write-mail.png" -#define IMAGE_CONNECT ":/images/connect_friend.png" +#define IMAGE_CONNECT ":/icons/connection.svg" #define IMAGE_COPYLINK ":/images/copyrslink.png" -#define IMAGE_GROUP16 ":/images/user/group16.png" +#define IMAGE_GROUPS ":/icons/groups/colored.svg" #define IMAGE_EDIT ":/icons/png/pencil-edit-button.png" -#define IMAGE_REMOVE ":/images/delete.png" -#define IMAGE_EXPAND ":/images/edit_add24.png" -#define IMAGE_COLLAPSE ":/images/edit_remove24.png" +#define IMAGE_EXPAND ":/icons/plus.svg" +#define IMAGE_COLLAPSE ":/icons/minus.svg" +#define IMAGE_REMOVE ":/icons/cancel.svg" +#define IMAGE_ADD ":/icons/png/add.png" /* Images for Status icons */ #define IMAGE_AVAILABLE ":/images/user/identityavaiblecyan24.png" #define IMAGE_PASTELINK ":/images/pasterslink.png" -#define IMAGE_GROUP24 ":/images/user/group24.png" #define COLUMN_DATA 0 // column for storing the userdata id @@ -184,6 +185,13 @@ NewFriendList::NewFriendList(QWidget */*parent*/) : /* RsAutoUpdatePage(5000,par { ui->setupUi(this); + int H = QFontMetricsF(ui->peerTreeWidget->font()).height(); +#if QT_VERSION < QT_VERSION_CHECK(5,11,0) + int W = QFontMetricsF(ui->peerTreeWidget->font()).width("_"); +#else + int W = QFontMetricsF(ui->peerTreeWidget->font()).horizontalAdvance("_"); +#endif + ui->filterLineEdit->setPlaceholderText(tr("Search")) ; ui->filterLineEdit->showFilterIcon(); @@ -195,6 +203,9 @@ NewFriendList::NewFriendList(QWidget */*parent*/) : /* RsAutoUpdatePage(5000,par rsEvents->registerEventsHandler( [this](std::shared_ptr e) { handleEvent(e); }, mEventHandlerId_peer, RsEventType::PEER_CONNECTION ); rsEvents->registerEventsHandler( [this](std::shared_ptr e) { handleEvent(e); }, mEventHandlerId_gssp, RsEventType::GOSSIP_DISCOVERY ); + connect(NotifyQt::getInstance(), SIGNAL(peerHasNewAvatar(QString)), this, SLOT(forceUpdateDisplay())); + connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(QString,int)), this, SLOT(forceUpdateDisplay())); + mModel = new RsFriendListModel(ui->peerTreeWidget); mProxyModel = new FriendListSortFilterProxyModel(ui->peerTreeWidget->header(),this); @@ -205,7 +216,9 @@ NewFriendList::NewFriendList(QWidget */*parent*/) : /* RsAutoUpdatePage(5000,par mProxyModel->setFilterRegExp(QRegExp(RsFriendListModel::FilterString)); ui->peerTreeWidget->setModel(mProxyModel); - ui->peerTreeWidget->setItemDelegate(new RSElidedItemDelegate()); + RSElidedItemDelegate *itemDelegate = new RSElidedItemDelegate(this); + itemDelegate->setSpacing(QSize(W/2, H/4)); + ui->peerTreeWidget->setItemDelegate(itemDelegate); ui->peerTreeWidget->setWordWrap(false); /* Add filter actions */ @@ -228,17 +241,13 @@ NewFriendList::NewFriendList(QWidget */*parent*/) : /* RsAutoUpdatePage(5000,par QShortcut *Shortcut = new QShortcut(QKeySequence(Qt::Key_Delete), ui->peerTreeWidget, 0, 0, Qt::WidgetShortcut); connect(Shortcut, SIGNAL(activated()), this, SLOT(removeItem()),Qt::QueuedConnection); - QFontMetricsF fontMetrics(ui->peerTreeWidget->font()); + /* Set initial column width */ + ui->peerTreeWidget->setColumnWidth(RsFriendListModel::COLUMN_THREAD_NAME , 22 * W); + ui->peerTreeWidget->setColumnWidth(RsFriendListModel::COLUMN_THREAD_IP , 15 * W); + ui->peerTreeWidget->setColumnWidth(RsFriendListModel::COLUMN_THREAD_ID , 32 * W); + ui->peerTreeWidget->setColumnWidth(RsFriendListModel::COLUMN_THREAD_LAST_CONTACT, 12 * W); - /* Set initial column width */ - int fontWidth = fontMetrics.width("W"); - ui->peerTreeWidget->setColumnWidth(RsFriendListModel::COLUMN_THREAD_NAME , 22 * fontWidth); - ui->peerTreeWidget->setColumnWidth(RsFriendListModel::COLUMN_THREAD_IP , 15 * fontWidth); - ui->peerTreeWidget->setColumnWidth(RsFriendListModel::COLUMN_THREAD_ID , 32 * fontWidth); - ui->peerTreeWidget->setColumnWidth(RsFriendListModel::COLUMN_THREAD_LAST_CONTACT, 12 * fontWidth); - - int avatarHeight = fontMetrics.height() * 3; - ui->peerTreeWidget->setIconSize(QSize(avatarHeight, avatarHeight)); + ui->peerTreeWidget->setIconSize(QSize(H*2, H*2)); mModel->checkInternalData(true); @@ -256,6 +265,7 @@ NewFriendList::NewFriendList(QWidget */*parent*/) : /* RsAutoUpdatePage(5000,par connect(ui->actionShowOfflineFriends, SIGNAL(triggered(bool)), this, SLOT(setShowUnconnected(bool))); connect(ui->actionShowState, SIGNAL(triggered(bool)), this, SLOT(setShowState(bool)) ); + connect(ui->actionShowStateIcon, SIGNAL(triggered(bool)), this, SLOT(setShowStateIcon(bool)) ); connect(ui->actionShowGroups, SIGNAL(triggered(bool)), this, SLOT(setShowGroups(bool)) ); connect(ui->actionExportFriendlist, SIGNAL(triggered()) , this, SLOT(exportFriendlistClicked())); connect(ui->actionImportFriendlist, SIGNAL(triggered()) , this, SLOT(importFriendlistClicked())); @@ -263,6 +273,8 @@ NewFriendList::NewFriendList(QWidget */*parent*/) : /* RsAutoUpdatePage(5000,par connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString)),Qt::QueuedConnection); connect(h, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(headerContextMenuRequested(QPoint))); + mFontSizeHandler.registerFontSize(ui->peerTreeWidget,1.5f); + // #ifdef RS_DIRECT_CHAT // connect(ui->peerTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(chatNode())); // #endif @@ -301,8 +313,9 @@ void NewFriendList::headerContextMenuRequested(QPoint /*p*/) { QMenu displayMenu(tr("Show Items"), this); - QWidget *widget = new QWidget(&displayMenu); - widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); + QFrame *widget = new QFrame(&displayMenu); + widget->setObjectName("gradFrame"); //Use qss + //widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); // create menu header QHBoxLayout *hbox = new QHBoxLayout(widget); @@ -310,12 +323,14 @@ void NewFriendList::headerContextMenuRequested(QPoint /*p*/) hbox->setSpacing(6); QLabel *iconLabel = new QLabel(widget); + iconLabel->setObjectName("trans_Icon"); QPixmap pix = FilesDefs::getPixmapFromQtResourcePath(":/images/user/friends24.png").scaledToHeight(QFontMetricsF(iconLabel->font()).height()*1.5); iconLabel->setPixmap(pix); iconLabel->setMaximumSize(iconLabel->frameSize().height() + pix.height(), pix.width()); hbox->addWidget(iconLabel); QLabel *textLabel = new QLabel("Show/hide...", widget); + textLabel->setObjectName("trans_Text"); hbox->addWidget(textLabel); QSpacerItem *spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); @@ -333,10 +348,12 @@ void NewFriendList::headerContextMenuRequested(QPoint /*p*/) displayMenu.addAction(ui->actionShowOfflineFriends); displayMenu.addAction(ui->actionShowState); + displayMenu.addAction(ui->actionShowStateIcon); displayMenu.addAction(ui->actionShowGroups); ui->actionShowOfflineFriends->setChecked(mProxyModel->showOfflineNodes()); ui->actionShowState->setChecked(mModel->getDisplayStatusString()); + ui->actionShowStateIcon->setChecked(mModel->getDisplayStatusIcon()); ui->actionShowGroups->setChecked(mModel->getDisplayGroups()); QHeaderView *header = ui->peerTreeWidget->header(); @@ -376,7 +393,7 @@ void NewFriendList::addToolButton(QToolButton *toolButton) toolButton->setIconSize(QSize(S*1.5,S*1.5)); toolButton->setFocusPolicy(Qt::NoFocus); - ui->titleBarFrame->layout()->addWidget(toolButton); + ui->toolBarFrame->layout()->addWidget(toolButton); } void NewFriendList::saveExpandedPathsAndSelection(std::set& expanded_indexes, QString& sel) @@ -497,6 +514,8 @@ void NewFriendList::processSettings(bool load) mModel->setDisplayStatusString(Settings->value("showState", mModel->getDisplayStatusString()).toBool()); mModel->setDisplayGroups(Settings->value("showGroups", mModel->getDisplayGroups()).toBool()); + mModel->setDisplayStatusIcon(Settings->value("showStateIcon", mModel->getDisplayStatusIcon()).toBool()); + setColumnVisible(RsFriendListModel::COLUMN_THREAD_IP,Settings->value("showIP", isColumnVisible(RsFriendListModel::COLUMN_THREAD_IP)).toBool()); setColumnVisible(RsFriendListModel::COLUMN_THREAD_ID,Settings->value("showID", isColumnVisible(RsFriendListModel::COLUMN_THREAD_ID)).toBool()); @@ -520,6 +539,8 @@ void NewFriendList::processSettings(bool load) Settings->setValue("hideUnconnected", !mProxyModel->showOfflineNodes()); Settings->setValue("showState", mModel->getDisplayStatusString()); Settings->setValue("showGroups", mModel->getDisplayGroups()); + Settings->setValue("showStateIcon", mModel->getDisplayStatusIcon()); + Settings->setValue("showIP",isColumnVisible(RsFriendListModel::COLUMN_THREAD_IP)); Settings->setValue("showID",isColumnVisible(RsFriendListModel::COLUMN_THREAD_ID)); @@ -564,8 +585,9 @@ void NewFriendList::peerTreeWidgetCustomPopupMenu() QMenu contextMenu(this); - QWidget *widget = new QWidget(&contextMenu); - widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); + QFrame *widget = new QFrame(); + widget->setObjectName("gradFrame"); //Use qss + //widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); // create menu header QHBoxLayout *hbox = new QHBoxLayout(widget); @@ -573,12 +595,14 @@ void NewFriendList::peerTreeWidgetCustomPopupMenu() hbox->setSpacing(6); QLabel *iconLabel = new QLabel(widget); + iconLabel->setObjectName("trans_Icon"); QPixmap pix = FilesDefs::getPixmapFromQtResourcePath(":/images/user/friends24.png").scaledToHeight(QFontMetricsF(iconLabel->font()).height()*1.5); iconLabel->setPixmap(pix); iconLabel->setMaximumSize(iconLabel->frameSize().height() + pix.height(), pix.width()); hbox->addWidget(iconLabel); QLabel *textLabel = new QLabel("Friend list", widget); + textLabel->setObjectName("trans_Text"); hbox->addWidget(textLabel); QSpacerItem *spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); @@ -676,8 +700,8 @@ void NewFriendList::peerTreeWidgetCustomPopupMenu() } } - QMenu *groupsMenu = contextMenu.addMenu(FilesDefs::getIconFromQtResourcePath(IMAGE_GROUP16), tr("Groups")); - groupsMenu->addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_EXPAND), tr("Create new group"), this, SLOT(createNewGroup())); + QMenu *groupsMenu = contextMenu.addMenu(FilesDefs::getIconFromQtResourcePath(IMAGE_GROUPS), tr("Groups")); + groupsMenu->addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_ADD), tr("Create new group"), this, SLOT(createNewGroup())); if (addToGroupMenu || moveToGroupMenu || foundGroup) { if (addToGroupMenu) { @@ -697,7 +721,7 @@ void NewFriendList::peerTreeWidgetCustomPopupMenu() mModel->getGroupData(parent,info); QAction *removeFromGroup = groupsMenu->addAction(tr("Remove from group ")+QString::fromUtf8(info.name.c_str())); - removeFromGroup->setData(parent.sibling(parent.row(),RsFriendListModel::COLUMN_THREAD_ID).data(Qt::DisplayRole)); + removeFromGroup->setData(QString::fromStdString(info.id.toStdString())); connect(removeFromGroup, SIGNAL(triggered()), this, SLOT(removeFromGroup())); } @@ -767,6 +791,7 @@ void NewFriendList::createNewGroup() { CreateGroup createGrpDialog (RsNodeGroupId(), this); createGrpDialog.exec(); + checkInternalData(true); } #ifdef NOT_USED @@ -1349,7 +1374,7 @@ bool NewFriendList::exportFriendlist(QString &fileName) if (!rsPeers->getPeerDetails(*list_iter2, detailSSL)) continue; - std::string certificate = rsPeers->GetRetroshareInvite(detailSSL.id, RetroshareInviteFlags::CURRENT_IP | RetroshareInviteFlags::DNS | RetroshareInviteFlags::RADIX_FORMAT); + std::string certificate = rsPeers->GetRetroshareInvite(detailSSL.id, RsPeers::defaultCertificateFlags | RetroshareInviteFlags::RADIX_FORMAT); // remove \n from certificate certificate.erase(std::remove(certificate.begin(), certificate.end(), '\n'), certificate.end()); @@ -1607,7 +1632,9 @@ bool NewFriendList::isColumnVisible(int col) const } void NewFriendList::setColumnVisible(int col,bool visible) { +#ifdef DEBUG_NEW_FRIEND_LIST std::cerr << "Setting column " << col << " to be visible: " << visible << std::endl; +#endif ui->peerTreeWidget->setColumnHidden(col, !visible); } void NewFriendList::toggleColumnVisible() @@ -1629,6 +1656,12 @@ void NewFriendList::setShowState(bool show) processSettings(false); } +void NewFriendList::setShowStateIcon(bool show) +{ + applyWhileKeepingTree([show,this]() { mModel->setDisplayStatusIcon(show) ; }); + processSettings(false); +} + void NewFriendList::setShowGroups(bool show) { applyWhileKeepingTree([show,this]() { mModel->setDisplayGroups(show) ; }); @@ -1640,7 +1673,7 @@ void NewFriendList::setShowGroups(bool show) */ void NewFriendList::filterItems(const QString &text) { - QStringList lst = text.split(' ',QString::SkipEmptyParts); + QStringList lst = text.split(' ',QtSkipEmptyParts); int filterColumn = ui->filterLineEdit->currentFilter(); if(filterColumn == 0) diff --git a/retroshare-gui/src/gui/common/NewFriendList.h b/retroshare-gui/src/gui/common/NewFriendList.h index cf2e892b3..cf4c68e6f 100644 --- a/retroshare-gui/src/gui/common/NewFriendList.h +++ b/retroshare-gui/src/gui/common/NewFriendList.h @@ -29,6 +29,7 @@ #include "FriendListModel.h" #include "retroshare/rsstatus.h" +#include "util/FontSizeHandler.h" namespace Ui { class NewFriendList; @@ -87,7 +88,9 @@ public slots: void setShowGroups(bool show); void setShowUnconnected(bool hidden); void setShowState(bool show); - void headerContextMenuRequested(QPoint); + void setShowStateIcon(bool show); + void headerContextMenuRequested(QPoint); + void exportFriendlistClicked(); private slots: void sortColumn(int col,Qt::SortOrder so); @@ -102,6 +105,7 @@ private: Ui::NewFriendList *ui; RsFriendListModel *mModel; QAction *mActionSortByState; + FontSizeHandler mFontSizeHandler; void applyWhileKeepingTree(std::function predicate); @@ -164,6 +168,5 @@ private slots: void editGroup(); void removeGroup(); - void exportFriendlistClicked(); void importFriendlistClicked(); }; diff --git a/retroshare-gui/src/gui/common/NewFriendList.ui b/retroshare-gui/src/gui/common/NewFriendList.ui index 3ec1c6c03..286cf4304 100644 --- a/retroshare-gui/src/gui/common/NewFriendList.ui +++ b/retroshare-gui/src/gui/common/NewFriendList.ui @@ -10,7 +10,7 @@ 292
- + 0 @@ -27,14 +27,14 @@ 0 - + - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + 3 @@ -119,12 +119,23 @@ import your friendlist including groups + + + true + + + Status icons + + + Show status icons + + LineEditClear QLineEdit -
gui/common/LineEditClear.h
+
gui/common/LineEditClear.h
diff --git a/retroshare-gui/src/gui/common/RSComboBox.cpp b/retroshare-gui/src/gui/common/RSComboBox.cpp new file mode 100644 index 000000000..e11a3c99d --- /dev/null +++ b/retroshare-gui/src/gui/common/RSComboBox.cpp @@ -0,0 +1,59 @@ +/******************************************************************************* + * gui/common/RSComboBox.cpp * + * * + * Copyright (C) 2010, Retroshare Team * + * * + * 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 . * + * * + *******************************************************************************/ + +#include "RSComboBox.h" + +#include "gui/common/RSElidedItemDelegate.h" + +#include +#include + +RSComboBox::RSComboBox(QWidget *parent /*= nullptr*/) + :QComboBox(parent) +{ + // To Fix ComboBox item delegate not respecting stylesheet. See QDarkStyleSheet issues 214 + setItemDelegate(new RSElidedItemDelegate()); + view()->installEventFilter(this); +} + +bool RSComboBox::eventFilter(QObject *obj, QEvent *event) +{ + if(QAbstractItemView* view = dynamic_cast(obj)) + { + // To Fix ComboBox item delegate not respecting stylesheet. See QDarkStyleSheet issues 214 + // With QStyleItemDelegate QComboBox::item:checked doesn't works. + // With QComboBox ::item:checked, it's applied to hover ones. + if (event->type() == QEvent::Show) + { + if(QComboBox* cmb = dynamic_cast(view->parent()->parent()) ) + { + for (int curs = 0; curs < cmb->count(); ++curs) + { + QFont font = cmb->itemData(curs, Qt::FontRole).value(); + font.setBold(curs == cmb->currentIndex()); + cmb->setItemData(curs, QVariant(font), Qt::FontRole); + + } + } + } + } + // pass the event on to the parent class + return QWidget::eventFilter(obj, event); +} diff --git a/libbitdht/src/util/bdfile.h b/retroshare-gui/src/gui/common/RSComboBox.h similarity index 76% rename from libbitdht/src/util/bdfile.h rename to retroshare-gui/src/gui/common/RSComboBox.h index 5228f986a..8ce46a649 100644 --- a/libbitdht/src/util/bdfile.h +++ b/retroshare-gui/src/gui/common/RSComboBox.h @@ -1,9 +1,7 @@ /******************************************************************************* - * util/bdfile.h * + * gui/common/RSComboBox.h * * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * + * Copyright (C) 2010, Retroshare Team * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Affero General Public License as * @@ -19,12 +17,20 @@ * along with this program. If not, see . * * * *******************************************************************************/ -#pragma once -#include +#ifndef RSCOMBOBOX_H +#define RSCOMBOBOX_H -class bdFile +#include + +class RSComboBox : public QComboBox { - public: - static bool renameFile(const std::string& from, const std::string& to) ; -} ; + Q_OBJECT +public: + explicit RSComboBox(QWidget *parent = nullptr); + +protected: + bool eventFilter(QObject *obj, QEvent *event); +}; + +#endif // RSCOMBOBOX_H diff --git a/retroshare-gui/src/gui/common/RSElidedItemDelegate.cpp b/retroshare-gui/src/gui/common/RSElidedItemDelegate.cpp index 34879b10c..f90591d8c 100644 --- a/retroshare-gui/src/gui/common/RSElidedItemDelegate.cpp +++ b/retroshare-gui/src/gui/common/RSElidedItemDelegate.cpp @@ -20,7 +20,7 @@ #include "RSElidedItemDelegate.h" -#include "gui/common/StyledElidedLabel.h" +#include "gui/common/ElidedLabel.h" #include "util/rsdebug.h" #include @@ -51,7 +51,7 @@ QTreeView::item:hover, QTreeWidget::item:hover, QListWidget::item:hover{ color: #0000EF; background-color: #FEDCBA; } -QQTreeView::item:selected:hover, TreeWidget::item:selected:hover, QListWidget::item:selected:hover{ +QTreeView::item:selected:hover, QTreeWidget::item:selected:hover, QListWidget::item:selected:hover{ color: #ABCDEF; background-color: #FE0000; } @@ -88,7 +88,12 @@ QSize RSElidedItemDelegate::sizeHint(const QStyleOptionViewItem &option, const Q QSize contSize = ownStyle->sizeFromContents( QStyle::CT_ItemViewItem,&ownOption ,QSize( checkRect.width()+iconRect.width()+textRect.width() - ,qMax(checkRect.height(),qMax(iconRect.height(),textRect.height()))),widget); + , qMax(checkRect.height(),qMax(iconRect.height(),textRect.height())) + ), widget ) ; + + contSize += QSize( 2*spacing().width() + , qMax(checkRect.height(),iconRect.height()) > textRect.height() + ? 0 : 2*spacing().height() ); return contSize; } @@ -97,7 +102,7 @@ inline QColor getImagePixelColor(QImage img, int x, int y) { #if QT_VERSION >= QT_VERSION_CHECK(5,6,0) #ifdef DEBUG_EID_PAINT -// RsDbg() << " RSEID: Found Color " << img.pixelColor(x,y).name(QColor::HexArgb).toStdString() << " at " << x << "," << y << std::endl; + //RsDbg(" RSEID: Found Color ", img.pixelColor(x,y).name(QColor::HexArgb).toStdString(), " at ", x, ",", y); #endif return img.pixelColor(x,y); #else @@ -109,7 +114,7 @@ void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem & { if(!index.isValid()) { - RsErr() << __PRETTY_FUNCTION__ << " attempt to draw an invalid index." << std::endl; + RS_ERR(" attempt to draw an invalid index."); return ; } painter->save(); @@ -120,7 +125,7 @@ void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem & ownOption.icon = option.icon; #ifdef DEBUG_EID_PAINT - RsDbg() << __PRETTY_FUNCTION__ << std::endl << " RSEID: Enter for item with text:" << ownOption.text.toStdString() << std::endl; + RS_DBG("\n RSEID: Enter for item with text:", ownOption.text.toStdString()); #endif const QWidget* widget = option.widget; @@ -138,17 +143,16 @@ void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem & ownOption.font = font; ownOption.fontMetrics = QFontMetrics(font); #ifdef DEBUG_EID_PAINT - QFontInfo info(font); - RsDbg() << " RSEID: Found font in model:" << info.family().toStdString() << std::endl; + RsDbg(" RSEID: Found font in model:", font.family().toStdString(), " size:", font.pointSize()); #endif } // Get Text color from model if one exists QColor textColor; - if (index.data(Qt::TextColorRole).isValid()) { + if (index.data(Qt::ForegroundRole).isValid()) { //textColor = QColor(index.data(Qt::TextColorRole).toString());//Needs to pass from string else loose RBG format. - textColor = index.data(Qt::TextColorRole).value(); + textColor = index.data(Qt::ForegroundRole).value(); #ifdef DEBUG_EID_PAINT - RsDbg() << " RSEID: Found text color in model:" << textColor.name().toStdString() << std::endl; + RsDbg(" RSEID: Found text color in model:", textColor.name().toStdString()); #endif } // Get Brush from model if one exists @@ -157,7 +161,7 @@ void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem & if (index.data(Qt::BackgroundRole).isValid()) { bgBrush = index.data(Qt::BackgroundRole).value(); #ifdef DEBUG_EID_PAINT - RsDbg() << " RSEID: Found bg brush in model:" << bgBrush.color().name().toStdString() << std::endl; + RsDbg(" RSEID: Found bg brush in model:", bgBrush.color().name().toStdString()); #endif } @@ -165,10 +169,10 @@ void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem & if ( (bgBrush.color().spec()==QColor::Invalid) || (textColor.spec()!=QColor::Invalid) ) { #ifdef DEBUG_EID_PAINT - RsDbg() << " RSEID:" - << ((bgBrush.color().spec()==QColor::Invalid) ? " Brush not defined" : "") - << ((textColor.spec()==QColor::Invalid) ? " Text Color not defined" : "") - << " so get it from base image." << std::endl; + RsDbg( " RSEID:" + , ((bgBrush.color().spec()==QColor::Invalid) ? " Brush not defined" : "") + , ((textColor.spec()==QColor::Invalid) ? " Text Color not defined" : "") + , " so get it from base image."); #endif // QPalette is not updated by StyleSheet all occurs in internal class. (QRenderRule) // https://code.woboq.org/qt5/qtbase/src/widgets/styles/qstylesheetstyle.cpp.html#4138 @@ -179,7 +183,7 @@ void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem & if (moSize.width() <= 20) moSize.setWidth(20); #ifdef DEBUG_EID_PAINT - RsDbg() << " RSEID: for item size = " << moSize.width() << "x" << moSize.height() << std::endl; + RsDbg(" RSEID: for item size = ", moSize.width(), "x", moSize.height()); #endif QImage moImg(moSize,QImage::Format_ARGB32); @@ -268,14 +272,14 @@ void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem & { bgBrush = QBrush(moBGColor); #ifdef DEBUG_EID_PAINT - RsDbg() << " RSEID: bg brush setted to " << moBGColor.name(QColor::HexArgb).toStdString() << std::endl; + RsDbg(" RSEID: bg brush setted to ", moBGColor.name(QColor::HexArgb).toStdString()); #endif } if (textColor.spec()==QColor::Invalid) { textColor = moColor; #ifdef DEBUG_EID_PAINT - RsDbg() << " RSEID: text color setted to " << moColor.name(QColor::HexArgb).toStdString() << std::endl; + RsDbg(" RSEID: text color setted to ", moColor.name(QColor::HexArgb).toStdString()); #endif } } @@ -378,18 +382,16 @@ void RSElidedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem & ownOption.text = ownOption.text.prepend("__"); #endif - QTextLayout textLayout(ownOption.text, painter->font()); - QTextOption to = textLayout.textOption(); - to.setWrapMode((ownOption.features & QStyleOptionViewItem::WrapText) ? QTextOption::WordWrap : QTextOption::NoWrap); + QTextOption::WrapMode wm = (ownOption.features & QStyleOptionViewItem::WrapText) ? QTextOption::WordWrap : QTextOption::NoWrap; const int textHMargin = ownStyle->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, widget) + 1; const int textVMargin = ownStyle->pixelMetric(QStyle::PM_FocusFrameVMargin, nullptr, widget) + 1; textRect = textRect.adjusted(textHMargin, textVMargin, -textHMargin, -textVMargin); // remove width padding - StyledElidedLabel::paintElidedLine(painter,ownOption.text,textRect,ownOption.font,ownOption.displayAlignment,to.wrapMode(),mPaintRoundedRect); + ElidedLabel::paintElidedLine(painter,ownOption.text,textRect,ownOption.font,ownOption.displayAlignment,wm,mPaintRoundedRect); } painter->restore(); #ifdef DEBUG_EID_PAINT - RsDbg() << " RSEID: Finished" << std::endl; + RsDbg(" RSEID: Finished"); #endif } @@ -436,7 +438,7 @@ bool RSElidedItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, //Update RSElidedItemDelegate as only one delegate for all items QRect rectElision; - bool elided = StyledElidedLabel::paintElidedLine(nullptr,text,textRect,ownOption.font,ownOption.displayAlignment,to.wrapMode(),true,&rectElision); + bool elided = ElidedLabel::paintElidedLine(nullptr,text,textRect,ownOption.font,ownOption.displayAlignment,to.wrapMode(),true,&rectElision); if (elided && (rectElision.contains(ev->pos()))){ QToolTip::showText(ev->globalPos(),QString("") + text + QString("")); return true; // eat event diff --git a/retroshare-gui/src/gui/common/RSFeedWidget.cpp b/retroshare-gui/src/gui/common/RSFeedWidget.cpp index 3293e3fae..7be4020b2 100644 --- a/retroshare-gui/src/gui/common/RSFeedWidget.cpp +++ b/retroshare-gui/src/gui/common/RSFeedWidget.cpp @@ -130,7 +130,7 @@ bool RSFeedWidget::eventFilter(QObject *object, QEvent *event) return QWidget::eventFilter(object, event); } -void RSFeedWidget::feedAdded(FeedItem *feedItem, QTreeWidgetItem *treeItem) +void RSFeedWidget::feedAdded(FeedItem */*feedItem*/, QTreeWidgetItem */*treeItem*/) { } @@ -433,7 +433,6 @@ void RSFeedWidget::feedItemDestroyed(qulonglong id) QTreeWidgetItem *RSFeedWidget::findTreeWidgetItem(const FeedItem *w) { QTreeWidgetItemIterator it(ui->treeWidget); - QTreeWidgetItem *treeItem=NULL; // this search could probably be automatised by giving the tree items the identifier as data for some specific role, then calling QTreeWidget::findItems() #warning TODO diff --git a/retroshare-gui/src/gui/common/RSImageBlockWidget.cpp b/retroshare-gui/src/gui/common/RSImageBlockWidget.cpp index e1f517f42..63dd224f1 100644 --- a/retroshare-gui/src/gui/common/RSImageBlockWidget.cpp +++ b/retroshare-gui/src/gui/common/RSImageBlockWidget.cpp @@ -31,7 +31,7 @@ RSImageBlockWidget::RSImageBlockWidget(QWidget *parent) : ui->setupUi(this); mDefaultRect = this->geometry(); - ui->infoFrame->installEventFilter(this); + ui->info_Frame->installEventFilter(this); mTimer = new RsProtectedTimer(this); mTimer->setSingleShot(true); diff --git a/retroshare-gui/src/gui/common/RSImageBlockWidget.ui b/retroshare-gui/src/gui/common/RSImageBlockWidget.ui index f483a1afd..ab40c379d 100644 --- a/retroshare-gui/src/gui/common/RSImageBlockWidget.ui +++ b/retroshare-gui/src/gui/common/RSImageBlockWidget.ui @@ -33,10 +33,19 @@ 0 - + + + + + 0 + 0 + 0 + + + @@ -57,6 +66,15 @@ + + + + 0 + 0 + 0 + + + @@ -77,6 +95,15 @@ + + + + 154 + 154 + 154 + + + @@ -104,7 +131,7 @@ QFrame::Box - + 6 diff --git a/retroshare-gui/src/gui/common/RSTextBrowser.cpp b/retroshare-gui/src/gui/common/RSTextBrowser.cpp index cd2bd988e..c11d4edef 100644 --- a/retroshare-gui/src/gui/common/RSTextBrowser.cpp +++ b/retroshare-gui/src/gui/common/RSTextBrowser.cpp @@ -22,6 +22,7 @@ #include "RSImageBlockWidget.h" #include "gui/common/FilesDefs.h" +#include "util/imageutil.h" #include //To get RsAccounts @@ -33,6 +34,7 @@ #include #include #include +#include #include @@ -232,64 +234,6 @@ void RSTextBrowser::activateLinkClick(bool active) mLinkClickActive = active; } -/** - * @brief RSTextBrowser::checkImage - * @param pos where to check if image is shown in viewport coordinate - * @param imageStr return html source of cursor - * @return True if an image is under cursor - */ -bool RSTextBrowser::checkImage(QPoint pos, QString &imageStr) -{ - //Get text cursor under pos. But if pos is under text browser end line this return last cursor. - QTextCursor cursor = cursorForPosition(pos); - //First get rect of cursor (could be at left or right of image) - QRect cursorRectStart = cursorRect(cursor); - //Second get text - cursor.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, 1);//To get character just before - QRect cursorRectLeft = cursorRect(cursor); - cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 2); - QRect cursorRectRight = cursorRect(cursor); - imageStr = cursor.selection().toHtml(); -#ifdef RSTEXTBROWSER_CHECKIMAGE_DEBUG - mCursorRectStart = cursorRectStart; - mCursorRectLeft = cursorRectLeft; - mCursorRectRight = cursorRectRight; - - std::cerr << "cursorRect LTRB :" << cursorRectStart.left() << ";" << cursorRectStart.top() << ";" << cursorRectStart.right() << ";" << cursorRectStart.bottom() << std::endl; - std::cerr << "cursorRectLeft :" << cursorRectLeft.left() << ";" << cursorRectLeft.top() << ";" << cursorRectLeft.right() << ";" << cursorRectLeft.bottom() << std::endl; - std::cerr << "cursorRectRight :" << cursorRectRight.left() << ";" << cursorRectRight.top() << ";" << cursorRectRight.right() << ";" << cursorRectRight.bottom() << std::endl; - std::cerr << "pos XY :" << pos.x() << ";" << pos.y() << std::endl; -#endif - QRect cursorRectEnd = cursorRectStart; - //Finally set left with right of precedent character. - if (cursorRectEnd.top() < cursorRectLeft.bottom()) - { - cursorRectEnd.setLeft(cursorRectLeft.right()); - } else { - //Image on new line - cursorRectEnd.setLeft(0); - } - //And set Right with left of next character. - if (cursorRectEnd.bottom() > cursorRectRight.top()) - { - cursorRectEnd.setRight(cursorRectRight.left()); - } else { - //New line after Image. - } -#ifdef RSTEXTBROWSER_CHECKIMAGE_DEBUG - mCursorRectEnd = cursorRectEnd; - - std::cerr << "final cursorRect:" << cursorRectEnd.left() << ";" << cursorRectEnd.top() << ";" << cursorRectEnd.right() << ";" << cursorRectEnd.bottom() << std::endl; - viewport()->update(); -#endif - //If pos is on text rect - if (cursorRectEnd.contains(pos)) - { - return imageStr.indexOf("base64,") != -1; - } - return false; -} - /** * @brief RSTextBrowser::anchorForPosition Replace anchorAt that doesn't works as expected. * @param pos Where to get anchor from text @@ -317,18 +261,59 @@ QString RSTextBrowser::anchorForPosition(const QPoint &pos) const return anchor; } -QMenu *RSTextBrowser::createStandardContextMenu() +void RSTextBrowser::addContextMenuAction(QAction *action) { - return createStandardContextMenu(QPoint()); + mContextMenuActions.push_back(action); } -QMenu *RSTextBrowser::createStandardContextMenu(const QPoint &position) + +void RSTextBrowser::contextMenuEvent(QContextMenuEvent *event) { - QMenu *menu = QTextBrowser::createStandardContextMenu(position); + emit calculateContextMenuActions(); + + QMenu *contextMenu = createStandardContextMenuFromPoint(event->pos()); + + QList::iterator it; + for (it = mContextMenuActions.begin(); it != mContextMenuActions.end(); ++it) { + contextMenu->addAction(*it); + } + + contextMenu->exec(QCursor::pos()); + + delete(contextMenu); +} + +QMenu *RSTextBrowser::createStandardContextMenuFromPoint(const QPoint &widgetPos) +{ + QMatrix matrix; + matrix.translate(horizontalScrollBar()->value(), verticalScrollBar()->value()); + + QMenu *menu = QTextBrowser::createStandardContextMenu(matrix.map(widgetPos)); menu->addSeparator(); QAction *a = menu->addAction(FilesDefs::getIconFromQtResourcePath("://icons/textedit/code.png"), tr("View &Source"), this, SLOT(viewSource())); a->setEnabled(!this->document()->isEmpty()); + if (ImageUtil::checkImage(this, widgetPos +#ifdef RSTEXTBROWSER_CHECKIMAGE_DEBUG + , &mCursorRectStart, &mCursorRectLeft, &mCursorRectRight, &mCursorRectEnd +#endif + )) { + a = menu->addAction(FilesDefs::getIconFromQtResourcePath(":/images/document_save.png"), tr("Save image"), this, SLOT(saveImage())); + a->setData(widgetPos); + + a = menu->addAction( tr("Copy image"), this, SLOT(copyImage())); + a->setData(widgetPos); + } + +#ifdef RSTEXTBROWSER_CHECKIMAGE_DEBUG + std::cerr << "cursorRect LTRB :" << mCursorRectStart.left() << ";" << mCursorRectStart.top() << ";" << mCursorRectStart.right() << ";" << mCursorRectStart.bottom() << std::endl; + std::cerr << "cursorRectLeft :" << mCursorRectLeft.left() << ";" << mCursorRectLeft.top() << ";" << mCursorRectLeft.right() << ";" << mCursorRectLeft.bottom() << std::endl; + std::cerr << "cursorRectRight :" << mCursorRectRight.left() << ";" << mCursorRectRight.top() << ";" << mCursorRectRight.right() << ";" << mCursorRectRight.bottom() << std::endl; + std::cerr << "pos XY :" << widgetPos.x() << ";" << widgetPos.y() << std::endl; + std::cerr << "final cursorRect:" << mCursorRectEnd.left() << ";" << mCursorRectEnd.top() << ";" << mCursorRectEnd.right() << ";" << mCursorRectEnd.bottom() << std::endl; + viewport()->update(); +#endif + return menu; } @@ -350,3 +335,27 @@ void RSTextBrowser::viewSource() delete dialog; } + +void RSTextBrowser::saveImage() +{ + QAction *action = dynamic_cast(sender()) ; + if (!action) { + return; + } + + QPoint point = action->data().toPoint(); + QTextCursor cursor = cursorForPosition(point); + ImageUtil::extractImage(window(), cursor); +} + +void RSTextBrowser::copyImage() +{ + QAction *action = dynamic_cast(sender()) ; + if (!action) { + return; + } + + QPoint point = action->data().toPoint(); + QTextCursor cursor = cursorForPosition(point); + ImageUtil::copyImage(window(), cursor); +} diff --git a/retroshare-gui/src/gui/common/RSTextBrowser.h b/retroshare-gui/src/gui/common/RSTextBrowser.h index 57f351d2b..a10a2b30a 100644 --- a/retroshare-gui/src/gui/common/RSTextBrowser.h +++ b/retroshare-gui/src/gui/common/RSTextBrowser.h @@ -45,10 +45,10 @@ public: void setImageBlockWidget(RSImageBlockWidget *widget); void resetImagesStatus(bool load); QPixmap getBlockedImage(); - bool checkImage(QPoint pos, QString &imageStr); - bool checkImage(QPoint pos) {QString imageStr; return checkImage(pos, imageStr); } QString anchorForPosition(const QPoint &pos) const; + // Add QAction to context menu (action won't be deleted) + void addContextMenuAction(QAction *action); void activateLinkClick(bool active); @@ -58,8 +58,10 @@ public: QVariant textColorQuotes() const { return highlighter->textColorQuotes();} bool getShowImages() const { return mShowImages; } - QMenu *createStandardContextMenu(); - QMenu *createStandardContextMenu(const QPoint &position); + QMenu *createStandardContextMenuFromPoint(const QPoint &widgetPos); + +Q_SIGNALS: + void calculateContextMenuActions(); public slots: void showImages(); @@ -70,9 +72,16 @@ private slots: void linkClicked(const QUrl &url); void destroyImageBlockWidget(); void viewSource(); + void saveImage(); + void copyImage(); protected: void paintEvent(QPaintEvent *event); + virtual void contextMenuEvent(QContextMenuEvent *event); + +private: + // Hide method from QTextBrowser + using QTextBrowser::createStandardContextMenu; private: QString mPlaceholderText; @@ -80,6 +89,7 @@ private: RSImageBlockWidget *mImageBlockWidget; bool mLinkClickActive; RsSyntaxHighlighter *highlighter; + QList mContextMenuActions; #ifdef RSTEXTBROWSER_CHECKIMAGE_DEBUG QRect mCursorRectStart; QRect mCursorRectLeft; diff --git a/retroshare-gui/src/gui/common/RSTreeView.cpp b/retroshare-gui/src/gui/common/RSTreeView.cpp index 624021f2f..454ab250e 100644 --- a/retroshare-gui/src/gui/common/RSTreeView.cpp +++ b/retroshare-gui/src/gui/common/RSTreeView.cpp @@ -18,42 +18,73 @@ * * *******************************************************************************/ -#include -#include #include "RSTreeView.h" -RSTreeView::RSTreeView(QWidget *parent) : QTreeView(parent) +#include "util/rsdebug.h" + +#include +#include + +//#define DEBUG_RSTREEVIEW + +RSTreeView::RSTreeView(QWidget *parent) + : QTreeView(parent), autoSelect(false) { - setMouseTracking(false); // normally the default, but who knows if it's not goign to change in the future. + setMouseTracking(false); // normally the default, but who knows if it's not going to change in the future. } void RSTreeView::wheelEvent(QWheelEvent *e) { - if(e->modifiers() == Qt::ControlModifier) - { - emit zoomRequested(e->delta() > 0); - return; - } - else - QTreeView::wheelEvent(e); + if(e->modifiers() == Qt::ControlModifier) + { + emit zoomRequested(e->angleDelta().y() > 0); + return; + } + else + QTreeView::wheelEvent(e); } void RSTreeView::mouseMoveEvent(QMouseEvent *e) { - QModelIndex idx = indexAt(e->pos()); +#ifdef DEBUG_RSTREEVIEW + RS_DBG(e->localPos().x(), ":", e->localPos().y()); +#endif + if (autoSelect) + { + QModelIndex idx = indexAt(e->pos()); - if(idx.isValid() && idx != selectionModel()->currentIndex()) - selectionModel()->setCurrentIndex(idx,QItemSelectionModel::ClearAndSelect); + if(idx.isValid() && idx != selectionModel()->currentIndex()) + { +#ifdef DEBUG_RSTREEVIEW + RS_DBG("Selection changed"); +#endif + selectionModel()->setCurrentIndex(idx,QItemSelectionModel::ClearAndSelect); + } + } - QTreeView::mouseMoveEvent(e); + QTreeView::mouseMoveEvent(e); +} + +void RSTreeView::leaveEvent(QEvent *e) +{ +#ifdef DEBUG_RSTREEVIEW + RS_DBG(""); +#endif + if (autoSelect) + { + auto fp = focusPolicy(); + setFocusPolicy(Qt::NoFocus); // To not select first index when resetting current index. + selectionModel()->setCurrentIndex(QModelIndex(),QItemSelectionModel::Clear); // Close editor + setFocusPolicy(fp); + } + + QTreeView::leaveEvent(e); } void RSTreeView::setAutoSelect(bool b) { - if(b) - setMouseTracking(true); - else - setMouseTracking(false); + autoSelect = b; // Keep this because setMouseTracking can be called outside. + setMouseTracking(b); } void RSTreeView::resizeEvent(QResizeEvent *e) diff --git a/retroshare-gui/src/gui/common/RSTreeView.h b/retroshare-gui/src/gui/common/RSTreeView.h index 116ccac31..0ccd34134 100644 --- a/retroshare-gui/src/gui/common/RSTreeView.h +++ b/retroshare-gui/src/gui/common/RSTreeView.h @@ -29,26 +29,34 @@ class RSTreeView : public QTreeView Q_OBJECT public: - RSTreeView(QWidget *parent = 0); + RSTreeView(QWidget *parent = nullptr); + /** + * @brief set Placeholder Text + * @param text + */ void setPlaceholderText(const QString &text); - // Use this to make selection automatic based on mouse position. This is useful to trigger selection and therefore editing mode - // in trees that show editing widgets using a QStyledItemDelegate - - void setAutoSelect(bool b); + /** + * @brief Use this to make selection automatic based on mouse position. + * This is useful to trigger selection and therefore editing mode in trees that show editing widgets using a QStyledItemDelegate. + * @param b + */ + void setAutoSelect(bool b); signals: - void sizeChanged(QSize); - void zoomRequested(bool zoom_or_unzoom); + void sizeChanged(QSize); + void zoomRequested(bool zoom_or_unzoom); protected: virtual void mouseMoveEvent(QMouseEvent *e) override; // overriding so as to manage auto-selection + virtual void leaveEvent(QEvent *e) override; // overriding so as to manage auto-selection clear virtual void wheelEvent(QWheelEvent *e) override; // overriding so as to manage zoom - virtual void resizeEvent(QResizeEvent *e) override; + virtual void resizeEvent(QResizeEvent *e) override; virtual void paintEvent(QPaintEvent *event) override; QString placeholderText; + bool autoSelect; }; #endif diff --git a/retroshare-gui/src/gui/common/RSTreeWidget.cpp b/retroshare-gui/src/gui/common/RSTreeWidget.cpp index 09ef481f6..8ecdfde3f 100644 --- a/retroshare-gui/src/gui/common/RSTreeWidget.cpp +++ b/retroshare-gui/src/gui/common/RSTreeWidget.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "gui/settings/rsharesettings.h" #include "gui/common/FilesDefs.h" @@ -253,8 +254,9 @@ QMenu *RSTreeWidget::createStandardContextMenu(QMenu *contextMenu) } if(!mContextMenuActions.isEmpty() || !mContextMenuMenus.isEmpty() || mEnableColumnCustomize) { - QWidget *widget = new QWidget(contextMenu); - widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); + QFrame *widget = new QFrame(contextMenu); + widget->setObjectName("gradFrame"); //Use qss + //widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); // create menu header QHBoxLayout *hbox = new QHBoxLayout(widget); @@ -262,15 +264,17 @@ QMenu *RSTreeWidget::createStandardContextMenu(QMenu *contextMenu) hbox->setSpacing(6); QLabel *iconLabel = new QLabel(widget); - QPixmap pix = FilesDefs::getPixmapFromQtResourcePath(":/images/settings.png").scaledToHeight(QFontMetricsF(iconLabel->font()).height()*1.5); + iconLabel->setObjectName("trans_Icon"); + QPixmap pix = FilesDefs::getPixmapFromQtResourcePath(":/icons/png/options2.png").scaledToHeight(QFontMetricsF(iconLabel->font()).height()*1.5); iconLabel->setPixmap(pix); iconLabel->setMaximumSize(iconLabel->frameSize().height() + pix.height(), pix.width()); hbox->addWidget(iconLabel); QLabel *textLabel = new QLabel("" + tr("Tree View Options") + "", widget); + textLabel->setObjectName("trans_Text"); hbox->addWidget(textLabel); - QSpacerItem *spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + QSpacerItem *spacerItem = new QSpacerItem(40, 24, QSizePolicy::Expanding, QSizePolicy::Minimum); hbox->addItem(spacerItem); widget->setLayout(hbox); diff --git a/retroshare-gui/src/gui/common/RSTreeWidgetItem.h b/retroshare-gui/src/gui/common/RSTreeWidgetItem.h index 14a22b97c..8e90baee6 100644 --- a/retroshare-gui/src/gui/common/RSTreeWidgetItem.h +++ b/retroshare-gui/src/gui/common/RSTreeWidgetItem.h @@ -32,6 +32,7 @@ public: RSTreeWidgetItemCompareRole(); explicit RSTreeWidgetItemCompareRole(QMap> map); + void clear() { QMap >::clear() ; } void setRole(const int column, const int role); void addRole(const int column, const int role); void findRoles(const int column, QList &roles) const; diff --git a/retroshare-gui/src/gui/common/RsButtonOnText.cpp b/retroshare-gui/src/gui/common/RsButtonOnText.cpp index 95466c9d4..8774f84bd 100644 --- a/retroshare-gui/src/gui/common/RsButtonOnText.cpp +++ b/retroshare-gui/src/gui/common/RsButtonOnText.cpp @@ -107,7 +107,7 @@ bool RSButtonOnText::eventFilter(QObject *obj, QEvent *event) } if (event->type() == QEvent::MouseButtonPress) { QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseButtonPress - ,QPoint(1,1),Qt::LeftButton,Qt::LeftButton,0); + ,QPoint(1,1),Qt::LeftButton,Qt::LeftButton,Qt::KeyboardModifier::NoModifier); QPushButton::mousePressEvent(mouseEvent); delete mouseEvent; if (guard) _pressed = true; @@ -116,7 +116,7 @@ bool RSButtonOnText::eventFilter(QObject *obj, QEvent *event) } if (event->type() == QEvent::MouseButtonRelease) { QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseButtonPress - ,QPoint(1,1),Qt::LeftButton,Qt::LeftButton,0); + ,QPoint(1,1),Qt::LeftButton,Qt::LeftButton,Qt::KeyboardModifier::NoModifier); QPushButton::mouseReleaseEvent(mouseEvent); delete mouseEvent; if (guard) _pressed = false; @@ -152,7 +152,7 @@ bool RSButtonOnText::eventFilter(QObject *obj, QEvent *event) } if (_pressed){ QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseButtonPress - ,QPoint(1,1),Qt::LeftButton,Qt::LeftButton,0); + ,QPoint(1,1),Qt::LeftButton,Qt::LeftButton,Qt::KeyboardModifier::NoModifier); QPushButton::mouseReleaseEvent(mouseEvent); delete mouseEvent; //if (guard) emit released(); diff --git a/retroshare-gui/src/gui/common/RsCollection.cpp b/retroshare-gui/src/gui/common/RsCollection.cpp index c49296503..e13452038 100644 --- a/retroshare-gui/src/gui/common/RsCollection.cpp +++ b/retroshare-gui/src/gui/common/RsCollection.cpp @@ -37,534 +37,411 @@ const QString RsCollection::ExtensionString = QString("rscollection") ; -RsCollection::RsCollection(QObject *parent) - : QObject(parent), _xml_doc("RsCollection") +RsCollection::RsCollection() { - _root = _xml_doc.createElement("RsCollection"); - _xml_doc.appendChild(_root); + mFileTree = std::unique_ptr(new RsFileTree()); +} +RsCollection::RsCollection(const RsFileTree& ft) +{ + mFileTree = std::unique_ptr(new RsFileTree(ft)); + + for(uint64_t i=0;inumFiles();++i) + mHashes.insert(std::make_pair(mFileTree->fileData(i).hash,i )); } -RsCollection::RsCollection(const RsFileTree& fr) - : _xml_doc("RsCollection") +RsCollection::RsCollection(const std::vector& file_infos,FileSearchFlags flags) + : mFileTree(new RsFileTree) { - _root = _xml_doc.createElement("RsCollection"); - _xml_doc.appendChild(_root); + if(! ( (flags & RS_FILE_HINTS_LOCAL) || (flags & RS_FILE_HINTS_REMOTE))) + { + std::cerr << "(EE) Wrong flags passed to RsCollection constructor. Please fix the code!" << std::endl; + return ; + } - recursAddElements(_xml_doc,fr,0,_root) ; -} + for(uint32_t i = 0;iroot(),file_infos[i],flags) ; -RsCollection::RsCollection(const std::vector& file_infos,FileSearchFlags flags, QObject *parent) - : QObject(parent), _xml_doc("RsCollection") -{ - _root = _xml_doc.createElement("RsCollection"); - _xml_doc.appendChild(_root); - - if(! ( (flags & RS_FILE_HINTS_LOCAL) || (flags & RS_FILE_HINTS_REMOTE))) - { - std::cerr << "(EE) Wrong flags passed to RsCollection constructor. Please fix the code!" << std::endl; - return ; - } - - for(uint32_t i = 0;inumFiles();++i) + mHashes.insert(std::make_pair(mFileTree->fileData(i).hash,i )); } RsCollection::~RsCollection() { } -void RsCollection::downloadFiles() const -{ - // print out the element names of all elements that are direct children - // of the outermost element. - QDomElement docElem = _xml_doc.documentElement(); - - std::vector colFileInfos ; - - recursCollectColFileInfos(docElem,colFileInfos,QString(),false) ; - - RsCollectionDialog(_fileName, colFileInfos, false).exec() ; -} - -void RsCollection::autoDownloadFiles() const -{ - QDomElement docElem = _xml_doc.documentElement(); - - std::vector colFileInfos; - - recursCollectColFileInfos(docElem,colFileInfos,QString(),false); - - QString dlDir = QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()); - - foreach(ColFileInfo colFileInfo, colFileInfos) - { - autoDownloadFiles(colFileInfo, dlDir); - } -} - void RsCollection::autoDownloadFiles(ColFileInfo colFileInfo, QString dlDir) const { - if (!colFileInfo.filename_has_wrong_characters) - { - QString cleanPath = dlDir + colFileInfo.path ; - std::cout << "making directory " << cleanPath.toStdString() << std::endl; + if (!colFileInfo.filename_has_wrong_characters) + { + QString cleanPath = dlDir + colFileInfo.path ; + std::cout << "making directory " << cleanPath.toStdString() << std::endl; - if(!QDir(QApplication::applicationDirPath()).mkpath(cleanPath)) - std::cerr << "Unable to make path: " + cleanPath.toStdString() << std::endl; + if(!QDir(QApplication::applicationDirPath()).mkpath(cleanPath)) + std::cerr << "Unable to make path: " + cleanPath.toStdString() << std::endl; - if (colFileInfo.type==DIR_TYPE_FILE) - rsFiles->FileRequest(colFileInfo.name.toUtf8().constData(), - RsFileHash(colFileInfo.hash.toStdString()), - colFileInfo.size, - cleanPath.toUtf8().constData(), - RS_FILE_REQ_ANONYMOUS_ROUTING, - std::list()); - } - foreach(ColFileInfo colFileInfoChild, colFileInfo.children) - { - autoDownloadFiles(colFileInfoChild, dlDir); - } + if (colFileInfo.type==DIR_TYPE_FILE) + rsFiles->FileRequest(colFileInfo.name.toUtf8().constData(), + RsFileHash(colFileInfo.hash.toStdString()), + colFileInfo.size, + cleanPath.toUtf8().constData(), + RS_FILE_REQ_ANONYMOUS_ROUTING, + std::list()); + } + foreach(ColFileInfo colFileInfoChild, colFileInfo.children) + { + autoDownloadFiles(colFileInfoChild, dlDir); + } } static QString purifyFileName(const QString& input,bool& bad) { - static const QString bad_chars = "/\\\"*:?<>|" ; - bad = false ; - QString output = input ; + static const QString bad_chars = "/\\\"*:?<>|" ; + bad = false ; + QString output = input ; - for(int i=0;iaddFile(parent_index,fname.toStdString(),hash,size); } -void RsCollection::merge_in(const RsFileTree& tree) +void RsCollection::merge_in(const RsFileTree& tree, RsFileTree::DirIndex parent_index) { - recursAddElements(_xml_doc,tree,0,_root) ; + recursMergeTree(mFileTree->root(),tree,tree.directoryData(parent_index)) ; } -void RsCollection::recursCollectColFileInfos(const QDomElement& e,std::vector& colFileInfos,const QString& current_path, bool bad_chars_in_parent) const +void RsCollection::recursMergeTree(RsFileTree::DirIndex parent,const RsFileTree& tree,const RsFileTree::DirData& dd) { - QDomNode n = e.firstChild() ; -#ifdef COLLECTION_DEBUG - std::cerr << "Parsing element " << e.tagName().toStdString() << std::endl; -#endif + for(uint32_t i=0;iaddFile(parent,fd.name,fd.hash,fd.size); + } + for(uint32_t i=0;iaddDirectory(parent,ld.name); + recursMergeTree(new_dir_index,tree,ld); + } } - -void RsCollection::recursAddElements(QDomDocument& doc,const DirDetails& details,QDomElement& e,FileSearchFlags flags) const +void RsCollection::recursAddElements(RsFileTree::DirIndex parent, const DirDetails& dd, FileSearchFlags flags) { - if (details.type == DIR_TYPE_FILE) - { - QDomElement f = doc.createElement("File") ; + if (dd.type == DIR_TYPE_FILE) + mHashes[dd.hash] = mFileTree->addFile(parent,dd.name,dd.hash,dd.size); + else if (dd.type == DIR_TYPE_DIR) + { + RsFileTree::DirIndex new_dir_index = mFileTree->addDirectory(parent,dd.name); - f.setAttribute(QString("name"),QString::fromUtf8(details.name.c_str())) ; - f.setAttribute(QString("sha1"),QString::fromStdString(details.hash.toStdString())) ; - f.setAttribute(QString("size"),QString::number(details.size)) ; + for(uint32_t i=0;iRequestDirDetails(dd.children[i].ref, subDirDetails, flags)) + continue; - for(uint32_t i=0;iRequestDirDetails(details.children[i].ref, subDirDetails, flags)) - continue; - - recursAddElements(doc,subDirDetails,d,flags) ; - } - - e.appendChild(d) ; - } + recursAddElements(new_dir_index,subDirDetails,flags) ; + } + } } -void RsCollection::recursAddElements(QDomDocument& doc,const ColFileInfo& colFileInfo,QDomElement& e) const +QString RsCollection::errorString(RsCollectionErrorCode code) { - if (colFileInfo.type == DIR_TYPE_FILE) - { - QDomElement f = doc.createElement("File") ; - - f.setAttribute(QString("name"),colFileInfo.name) ; - f.setAttribute(QString("sha1"),colFileInfo.hash) ; - f.setAttribute(QString("size"),QString::number(colFileInfo.size)) ; - - e.appendChild(f) ; - } - else if (colFileInfo.type == DIR_TYPE_DIR) - { - QDomElement d = doc.createElement("Directory") ; - - d.setAttribute(QString("name"),colFileInfo.name) ; - - for (std::vector::const_iterator it = colFileInfo.children.begin(); it != colFileInfo.children.end(); ++it) - recursAddElements(doc,(*it),d) ; - - e.appendChild(d) ; - } + switch(code) + { + default: [[fallthrough]] ; + case RsCollectionErrorCode::UNKNOWN_ERROR: return QObject::tr("Unknown error"); + case RsCollectionErrorCode::COLLECTION_NO_ERROR: return QObject::tr("No error"); + case RsCollectionErrorCode::FILE_READ_ERROR: return QObject::tr("Error while openning file"); + case RsCollectionErrorCode::FILE_CONTAINS_HARMFUL_STRINGS: return QObject::tr("Collection file contains potentially harmful code"); + case RsCollectionErrorCode::INVALID_ROOT_NODE: return QObject::tr("Invalid root node. RsCollection node was expected."); + case RsCollectionErrorCode::XML_PARSING_ERROR: return QObject::tr("XML parsing error in collection file"); + } } -void RsCollection::recursAddElements( - QDomDocument& doc, const RsFileTree& ft, uint32_t index, - QDomElement& e ) const +RsCollection::RsCollection(const RsCollection& col) + : mFileTree(new RsFileTree(*col.mFileTree)),mHashes(col.mHashes) { - std::vector subdirs; - std::vector subfiles ; - std::string name; - if(!ft.getDirectoryContent(name, subdirs, subfiles, index)) return; - - QDomElement d = doc.createElement("Directory") ; - d.setAttribute(QString("name"),QString::fromUtf8(name.c_str())) ; - e.appendChild(d) ; - - for (uint32_t i=0;i bad_strings ; + bad_strings.push_back(std::string("= 0) + { + if (!file.atEnd()) + file.getChar(&c); + else + c=0; - return ok; -} + if(c == '\t' || c == '\n' || c == '\b' || c == '\r') + continue ; - // check that the file is a valid rscollection file, and not a lol bomb or some shit like this -bool RsCollection::checkFile(const QString& fileName, bool showError) -{ - QFile file(fileName); + if (n == max_size || file.atEnd()) + for(int i=0;i bad_strings ; - bad_strings.push_back(std::string("= 'A' && c <= 'Z') c += 'a' - 'A' ; - while( !file.atEnd() || n >= 0) - { - if (!file.atEnd()) - file.getChar(&c); - else - c=0; + if(!file.atEnd()) + current[n] = c ; + else + current[n] = 0 ; - if(c == '\t' || c == '\n' || c == '\b' || c == '\r') - continue ; + //std::cerr << "n==" << n <<" Checking string " << std::string(current,n+1) << " c = " << std::hex << (int)c << std::dec << std::endl; - if (n == max_size || file.atEnd()) - for(int i=0;i= 'A' && c <= 'Z') c += 'a' - 'A' ; - - if(!file.atEnd()) - current[n] = c ; - else - current[n] = 0 ; - - //std::cerr << "n==" << n <<" Checking string " << std::string(current,n+1) << " c = " << std::hex << (int)c << std::dec << std::endl; - - for(uint i=0;idirectoryData(mFileTree->root())); - file.close(); + if(!recursExportToXml(xml_doc,root,root_data)) + return false; - return true; + xml_doc.appendChild(root); + + QTextStream stream(&file) ; + stream.setCodec("UTF-8") ; + + stream << xml_doc.toString() ; + file.close(); + + return true; } -bool RsCollection::save(QWidget *parent) const +bool RsCollection::recursParseXml(QDomDocument& doc,const QDomNode& e,const RsFileTree::DirIndex parent) { - QString fileName; - if(!misc::getSaveFileName(parent, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Create collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName)) - return false; + mHashes.clear(); + QDomNode n = e.firstChild() ; +#ifdef COLLECTION_DEBUG + std::cerr << "Parsing element " << e.tagName().toStdString() << std::endl; +#endif - if (!fileName.endsWith("." + RsCollection::ExtensionString)) - fileName += "." + RsCollection::ExtensionString ; + while(!n.isNull()) + { + QDomElement ee = n.toElement(); // try to convert the node to an element. - std::cerr << "Got file name: " << fileName.toStdString() << std::endl; +#ifdef COLLECTION_DEBUG + std::cerr << " Seeing child " << ee.tagName().toStdString() << std::endl; +#endif - return save(fileName); + if(ee.tagName() == QString("File")) + { + RsFileHash hash(ee.attribute(QString("sha1")).toStdString()) ; + + bool bad_chars_detected = false; + std::string name = purifyFileName(ee.attribute(QString("name")), bad_chars_detected).toUtf8().constData() ; + uint64_t size = ee.attribute(QString("size")).toULongLong() ; + + mHashes[hash] = mFileTree->addFile(parent,name,hash,size); + } + else if(ee.tagName() == QString("Directory")) + { + bool bad_chars_detected = false ; + std::string cleanDirName = purifyFileName(ee.attribute(QString("name")),bad_chars_detected).toUtf8().constData() ; + + RsFileTree::DirIndex new_dir_index = mFileTree->addDirectory(parent,cleanDirName); + + recursParseXml(doc,ee,new_dir_index); + } + + n = n.nextSibling() ; + } + return true; } - - -bool RsCollection::openNewColl(QWidget *parent, QString fileName) +bool RsCollection::recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFileTree::DirData& dd) const { - if(!misc::getSaveFileName(parent, RshareSettings::LASTDIR_EXTRAFILE - , QApplication::translate("RsCollectionFile", "Create collection file") - , QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")" - , fileName,0, QFileDialog::DontConfirmOverwrite)) - return false; + for(uint32_t i=0;ifileData(dd.subfiles[i])); - std::cerr << "Got file name: " << fileName.toStdString() << std::endl; + f.setAttribute(QString("name"),QString::fromUtf8(fd.name.c_str())) ; + f.setAttribute(QString("sha1"),QString::fromStdString(fd.hash.toStdString())) ; + f.setAttribute(QString("size"),QString::number(fd.size)) ; - QFile file(fileName) ; + e.appendChild(f) ; + } - if(file.exists()) - { - if (!checkFile(fileName,true)) return false; + for(uint32_t i=0;idirectoryData(dd.subdirs[i])); - QMessageBox mb; - mb.setText(tr("Save Collection File.")); - mb.setInformativeText(tr("File already exists.")+"\n"+tr("What do you want to do?")); - QAbstractButton *btnOwerWrite = mb.addButton(tr("Overwrite"), QMessageBox::YesRole); - QAbstractButton *btnMerge = mb.addButton(tr("Merge"), QMessageBox::NoRole); - QAbstractButton *btnCancel = mb.addButton(tr("Cancel"), QMessageBox::ResetRole); - mb.setIcon(QMessageBox::Question); - mb.exec(); + QDomElement d = doc.createElement("Directory") ; + d.setAttribute(QString("name"),QString::fromUtf8(di.name.c_str())) ; - if (mb.clickedButton()==btnOwerWrite) { - //Nothing to do _xml_doc already up to date - } else if (mb.clickedButton()==btnMerge) { - //Open old file to merge it with _xml_doc - QDomDocument qddOldFile("RsCollection"); - if (qddOldFile.setContent(&file)) { - QDomElement docOldElem = qddOldFile.elementsByTagName("RsCollection").at(0).toElement(); - std::vector colOldFileInfos; - recursCollectColFileInfos(docOldElem,colOldFileInfos,QString(),false); + if(!recursExportToXml(doc,d,di)) + return false; - QDomElement root = _xml_doc.elementsByTagName("RsCollection").at(0).toElement(); - for(uint32_t i = 0;i colFileInfos ; - - recursCollectColFileInfos(_xml_doc.documentElement(),colFileInfos,QString(),false) ; - - RsCollectionDialog* rcd = new RsCollectionDialog(fileName, colFileInfos,true); - connect(rcd,SIGNAL(saveColl(std::vector, QString)),this,SLOT(saveColl(std::vector, QString))) ; - _saved=false; - rcd->exec() ; - delete rcd; - - return _saved; + return true; } -bool RsCollection::openColl(const QString& fileName, bool readOnly /* = false */, bool showError /* = true*/) +qulonglong RsCollection::count() const { - if (load(fileName, showError)) { - std::vector colFileInfos ; - - recursCollectColFileInfos(_xml_doc.documentElement(),colFileInfos,QString(),false) ; - - RsCollectionDialog* rcd = new RsCollectionDialog(fileName, colFileInfos, true, readOnly); - connect(rcd,SIGNAL(saveColl(std::vector, QString)),this,SLOT(saveColl(std::vector, QString))) ; - _saved=false; - rcd->exec() ; - delete rcd; - - return _saved; - } - return false; + return mFileTree->numFiles(); } - qulonglong RsCollection::size() { - QDomElement docElem = _xml_doc.documentElement(); - - std::vector colFileInfos; - recursCollectColFileInfos(docElem, colFileInfos, QString(),false); - - uint64_t size = 0; - - for (uint32_t i = 0; i < colFileInfos.size(); ++i) { - size += colFileInfos[i].size; - } - - return size; + return mFileTree->totalFileSize(); } bool RsCollection::isCollectionFile(const QString &fileName) { - QString ext = QFileInfo(fileName).suffix().toLower(); + QString ext = QFileInfo(fileName).suffix().toLower(); - return (ext == RsCollection::ExtensionString); + return (ext == RsCollection::ExtensionString); } -void RsCollection::saveColl(std::vector colFileInfos, const QString &fileName) +void RsCollection::updateHashes(const std::map& old_to_new_hashes) { + for(auto it:old_to_new_hashes) + { + auto fit = mHashes.find(it.first); - QDomElement root = _xml_doc.elementsByTagName("RsCollection").at(0).toElement(); - while (root.childNodes().count()>0) root.removeChild(root.firstChild()); - for(uint32_t i = 0;ifileData(fit->second)); + if(fd.hash != it.first) + { + RsErr() << "Mismatch hash for file " << fd.name << " (found " << fd.hash << " instead of " << it.first << ") in RsCollection list of hashes. This is a bug." ; + return ; + } + mFileTree->updateFile(fit->second,fd.name,it.second,fd.size); + } +} + +bool RsCollection::removeFile(RsFileTree::FileIndex index_to_remove,RsFileTree::DirIndex parent_index) +{ + return mFileTree->removeFile(index_to_remove,parent_index); +} +bool RsCollection::removeDirectory(RsFileTree::DirIndex index_to_remove,RsFileTree::DirIndex parent_index) +{ + return mFileTree->removeDirectory(index_to_remove,parent_index); +} + +void RsCollection::cleanup() +{ + RsDbg() << "Cleaning up RsCollection with " << mFileTree->numDirs() << " dirs and " << mFileTree->numFiles() << " files." ; + + mFileTree = RsFileTree::fromTreeCleaned(*mFileTree); + + RsDbg() << "Simplified to " << mFileTree->numDirs() << " dirs and " << mFileTree->numFiles() << " files."; } diff --git a/retroshare-gui/src/gui/common/RsCollection.h b/retroshare-gui/src/gui/common/RsCollection.h index 492d407d8..f68423f85 100644 --- a/retroshare-gui/src/gui/common/RsCollection.h +++ b/retroshare-gui/src/gui/common/RsCollection.h @@ -26,7 +26,6 @@ #pragma once -#include #include #include #include @@ -53,66 +52,70 @@ public: }; Q_DECLARE_METATYPE(ColFileInfo) -class RsCollection : public QObject +class RsCollection { - Q_OBJECT - public: + enum class RsCollectionErrorCode:uint8_t { + COLLECTION_NO_ERROR = 0x00, + UNKNOWN_ERROR = 0x01, + FILE_READ_ERROR = 0x02, + FILE_CONTAINS_HARMFUL_STRINGS = 0x03, + INVALID_ROOT_NODE = 0x04, + XML_PARSING_ERROR = 0x05 + }; - RsCollection(QObject *parent = 0) ; - // create from list of files and directories - RsCollection(const std::vector& file_entries, FileSearchFlags flags, QObject *parent = 0) ; - RsCollection(const RsFileTree& fr); - virtual ~RsCollection() ; + RsCollection(); + RsCollection(const RsCollection&); + RsCollection(const std::vector& file_entries, FileSearchFlags flags) ; + RsCollection(const RsFileTree& ft); + RsCollection(const QString& filename,RsCollectionErrorCode& error_code); - void merge_in(const QString& fname,uint64_t size,const RsFileHash& hash) ; - void merge_in(const RsFileTree& tree) ; + static QString errorString(RsCollectionErrorCode code); + + virtual ~RsCollection() ; + + void merge_in(const QString& fname,uint64_t size,const RsFileHash& hash,RsFileTree::DirIndex parent_index=0) ; + void merge_in(const RsFileTree& tree,RsFileTree::DirIndex parent_index=0) ; + + bool removeFile(RsFileTree::FileIndex index_to_remove,RsFileTree::DirIndex parent_index); + bool removeDirectory(RsFileTree::DirIndex index_to_remove,RsFileTree::DirIndex parent_index); + + void cleanup(); // cleans up the collection, which may contain unreferenced files/dirs after lazy editing. static const QString ExtensionString ; - // Loads file from disk. - bool load(QWidget *parent); - bool load(const QString& fileName, bool showError = true); - // Save to disk - bool save(QWidget *parent) const ; bool save(const QString& fileName) const ; - // Open new collection - bool openNewColl(QWidget *parent, QString fileName = ""); - // Open existing collection - bool openColl(const QString& fileName, bool readOnly = false, bool showError = true); - - // Download the content. - void downloadFiles() const ; - // Auto Download all the content. - void autoDownloadFiles() const ; - - qulonglong size(); + // returns the file tree + const RsFileTree& fileTree() const { return *mFileTree; } + // total size of files in the collection + qulonglong size(); + // total number of files in the collection + qulonglong count() const; static bool isCollectionFile(const QString& fileName); -private slots: - void saveColl(std::vector colFileInfos, const QString& fileName); - + void updateHashes(const std::map& old_to_new_hashes); private: - void recursAddElements(QDomDocument&, const DirDetails&, QDomElement&, FileSearchFlags flags) const ; - void recursAddElements(QDomDocument&,const ColFileInfo&,QDomElement&) const; - void recursAddElements( - QDomDocument& doc, const RsFileTree& ft, uint32_t index, - QDomElement& e ) const; + bool recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFileTree::DirData& dd) const; + bool recursParseXml(QDomDocument& doc, const QDomNode &e, RsFileTree::DirIndex dd) ; + + // This function is used to populate a RsCollection from locally or remotly shared files. + void recursAddElements(RsFileTree::DirIndex parent, const DirDetails& dd, FileSearchFlags flags) ; + + // This function is used to merge an existing RsFileTree into the RsCollection + void recursMergeTree(RsFileTree::DirIndex parent, const RsFileTree& tree, const RsFileTree::DirData &dd); + + // check that the file is a valid rscollection file, and not a lol bomb or some shit like this + static bool checkFile(const QString &fileName, RsCollectionErrorCode &error); - void recursCollectColFileInfos(const QDomElement&,std::vector& colFileInfos,const QString& current_dir,bool bad_chars_in_parent) const ; - // check that the file is a valid rscollection file, and not a lol bomb or some shit like this - static bool checkFile(const QString &fileName, bool showError); // Auto Download recursively. void autoDownloadFiles(ColFileInfo colFileInfo, QString dlDir) const ; - QDomDocument _xml_doc ; - QString _fileName ; - bool _saved; - QDomElement _root ; + std::unique_ptr mFileTree; + std::map mHashes; // used to efficiently update files being hashed friend class RsCollectionDialog ; }; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 417af69bc..5eb56506d 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -23,6 +23,7 @@ #include "RsCollection.h" #include "util/misc.h" +#include "util/rsdir.h" #include #include @@ -120,80 +121,93 @@ protected: /** * @brief RsCollectionDialog::RsCollectionDialog * @param collectionFileName: Filename of RSCollection saved - * @param colFileInfos: Vector of ColFileInfo to be add in intialization * @param creation: Open dialog as RsColl Creation or RsColl DownLoad * @param readOnly: Open dialog for RsColl as ReadOnly */ -RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName - , const std::vector& colFileInfos - , const bool& creation /* = false*/ - , const bool& readOnly) - : _fileName(collectionFileName), _creationMode(creation) ,_readOnly(readOnly) +RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName, RsCollectionDialogMode mode) + : _mode(mode) +{ + RsCollection::RsCollectionErrorCode err_code; + mCollection = new RsCollection(collectionFileName,err_code); + + if(err_code != RsCollection::RsCollectionErrorCode::COLLECTION_NO_ERROR) + { + QMessageBox::information(nullptr,tr("Could not load collection file"),tr("Could not load collection file")); + close(); + } + + init(collectionFileName); +} + +RsCollectionDialog::RsCollectionDialog(const RsCollection& coll, RsCollectionDialogMode mode) + : _mode(mode) +{ + mCollection = new RsCollection(coll); + init(QString()); +} +void RsCollectionDialog::init(const QString& collectionFileName) { ui.setupUi(this) ; + ui._filename_TL->setText(collectionFileName); - uint32_t size = colFileInfos.size(); - for(uint32_t i=0;isetHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/icons/collections.png")); - if(creation) - { - ui.headerFrame->setHeaderText(tr("Collection Editor")); - ui.downloadFolder_LE->hide(); - ui.downloadFolder_LB->hide(); - ui.destinationDir_TB->hide(); - } - else + if(_mode == DOWNLOAD) { ui.headerFrame->setHeaderText(tr("Download files")); ui.downloadFolder_LE->show(); ui.downloadFolder_LB->show(); - ui.label_filename->hide(); + ui.label_filename->hide(); ui._filename_TL->hide(); ui.downloadFolder_LE->setText(QString::fromUtf8(rsFiles->getDownloadDirectory().c_str())) ; QObject::connect(ui.downloadFolder_LE,SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(openDestinationDirectoryMenu())); QObject::connect(ui.destinationDir_TB,SIGNAL(pressed()), this, SLOT(openDestinationDirectoryMenu())); - } + } + else + { + ui.headerFrame->setHeaderText(tr("Collection Editor")); + ui.downloadFolder_LE->hide(); + ui.downloadFolder_LB->hide(); + ui.destinationDir_TB->hide(); + ui.label_filename->show(); + ui._filename_TL->show(); + } + // 1 - add all elements to the list. - ui._fileEntriesTW->setColumnCount(COLUMN_COUNT) ; + mCollectionModel = new RsCollectionModel(*mCollection); + ui._fileEntriesTW->setModel(mCollectionModel); - QTreeWidgetItem *headerItem = ui._fileEntriesTW->headerItem(); - headerItem->setText(COLUMN_FILE, tr("File")); - headerItem->setText(COLUMN_FILEPATH, tr("File Path")); - headerItem->setText(COLUMN_SIZE, tr("Size")); - headerItem->setText(COLUMN_HASH, tr("Hash")); - headerItem->setText(COLUMN_FILEC, tr("File Count")); - - bool wrong_chars = !updateList(); + connect(mCollectionModel,SIGNAL(sizesChanged()),this,SLOT(updateSizes())); + updateSizes(); // forced because it's only called when the collection is changed, or when the model is created. // 2 - connect necessary signals/slots connect(ui._changeFile, SIGNAL(clicked()), this, SLOT(changeFileName())); - connect(ui._add_PB, SIGNAL(clicked()), this, SLOT(add())); - connect(ui._addRecur_PB, SIGNAL(clicked()), this, SLOT(addRecursive())); + connect(ui._add_PB, SIGNAL(clicked()), this, SLOT(addSelection())); + connect(ui._addRecur_PB, SIGNAL(clicked()), this, SLOT(addSelectionRecursive())); connect(ui._remove_PB, SIGNAL(clicked()), this, SLOT(remove())); connect(ui._makeDir_PB, SIGNAL(clicked()), this, SLOT(makeDir())); - connect(ui._removeDuplicate_CB, SIGNAL(clicked(bool)), this, SLOT(updateRemoveDuplicate(bool))); connect(ui._cancel_PB, SIGNAL(clicked()), this, SLOT(cancel())); connect(ui._save_PB, SIGNAL(clicked()), this, SLOT(save())); connect(ui._download_PB, SIGNAL(clicked()), this, SLOT(download())); connect(ui._hashBox, SIGNAL(fileHashingFinished(QList)), this, SLOT(fileHashingFinished(QList))); - connect(ui._fileEntriesTW, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(itemChanged(QTreeWidgetItem*,int))); // 3 Initialize List _dirModel = new QFileSystemModel(this); @@ -216,14 +230,12 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName processSettings(true); // 5 Activate button follow creationMode - ui._changeFile->setVisible(_creationMode && !_readOnly); - ui._makeDir_PB->setVisible(_creationMode && !_readOnly); - ui._removeDuplicate_CB->setVisible(_creationMode && !_readOnly); - ui._save_PB->setVisible(_creationMode && !_readOnly); - ui._treeViewFrame->setVisible(_creationMode && !_readOnly); - ui._download_PB->setVisible(!_creationMode && !_readOnly); + ui._changeFile->setVisible(_mode == EDIT); + ui._makeDir_PB->setVisible(_mode == EDIT); + ui._save_PB->setVisible(_mode == EDIT); + ui._treeViewFrame->setVisible(_mode == EDIT); + ui._download_PB->setVisible(_mode == DOWNLOAD); - ui._fileEntriesTW->installEventFilter(this); ui._systemFileTW->installEventFilter(this); // 6 Add HashBox @@ -231,9 +243,6 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName ui._hashBox->setDropWidget(this); ui._hashBox->setAutoHide(true); ui._hashBox->setDefaultTransferRequestFlags(RS_FILE_REQ_ANONYMOUS_ROUTING) ; - - if(wrong_chars) - QMessageBox::warning(NULL,tr("Bad filenames have been cleaned"),tr("Some filenames or directory names contained forbidden characters.\nCharacters \",|,/,\\,<,>,*,? will be replaced by '_'.\n Concerned files are listed in red.")) ; } void RsCollectionDialog::openDestinationDirectoryMenu() @@ -285,85 +294,18 @@ RsCollectionDialog::~RsCollectionDialog() processSettings(false); } -/** - * @brief RsCollectionDialog::eventFilter: Proccess event in object - * @param obj: object where event occured - * @param event: event occured - * @return If we don't have to process event in parent. - */ -bool RsCollectionDialog::eventFilter(QObject *obj, QEvent *event) -{ - if (obj == ui._fileEntriesTW) { - if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); - if (keyEvent && (keyEvent->key() == Qt::Key_Space)) { - // Space pressed - - // get state of current item - QTreeWidgetItem *item = ui._fileEntriesTW->currentItem(); - if (item) { - Qt::CheckState checkState = (item->checkState(COLUMN_FILE) == Qt::Checked) ? Qt::Unchecked : Qt::Checked; - - // set state of all selected items - QList selectedItems = ui._fileEntriesTW->selectedItems(); - QList::iterator it; - for (it = selectedItems.begin(); it != selectedItems.end(); ++it) { - if ((*it)->checkState(COLUMN_FILE) != checkState) - (*it)->setCheckState(COLUMN_FILE, checkState); - } - } - - return true; // eat event - } - - if (keyEvent && (keyEvent->key() == Qt::Key_Delete)) { - // Delete pressed - remove(); - return true; // eat event - } - - if (keyEvent && (keyEvent->key() == Qt::Key_Plus)) { - // Plus pressed - makeDir(); - return true; // eat event - } - - } - } - - if (obj == ui._systemFileTW) { - if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); - if (keyEvent && ((keyEvent->key() == Qt::Key_Enter) - || keyEvent->key() == Qt::Key_Return)) { - // Enter pressed - if (keyEvent->modifiers() == Qt::ShiftModifier) - addRecursive(); - else if(keyEvent->modifiers() == Qt::NoModifier) { - add(); - } - - return true; // eat event - } - } - } - - // pass the event on to the parent class - return QDialog::eventFilter(obj, event); -} - /** * @brief RsCollectionDialog::processSettings * @param bLoad: Load or Save dialog's settings */ void RsCollectionDialog::processSettings(bool bLoad) { - Settings->beginGroup("RsCollectionDialog"); + Settings->beginGroup("RsCollectionDialogV2"); if (bLoad) { // load settings - if(_creationMode && !_readOnly){ + if(_mode == EDIT){ // Load windows geometrie restoreGeometry(Settings->value("WindowGeometrie_CM").toByteArray()); // Load splitters state @@ -385,7 +327,7 @@ void RsCollectionDialog::processSettings(bool bLoad) ui._fileEntriesTW->header()->restoreState(Settings->value("FileEntriesHeader").toByteArray()); } } else { - if(_creationMode && !_readOnly){ + if(_mode == EDIT){ // Save windows geometrie Settings->setValue("WindowGeometrie_CM",saveGeometry()); // Save splitters state @@ -411,182 +353,6 @@ void RsCollectionDialog::processSettings(bool bLoad) Settings->endGroup(); } -/** - * @brief RsCollectionDialog::getRootItem: Create the root Item if not existing - * @return: the root item - */ -QTreeWidgetItem* RsCollectionDialog::getRootItem() -{ - return ui._fileEntriesTW->invisibleRootItem(); - -// (csoler) I removed this code because it does the job of the invisibleRootItem() method. -// -// QTreeWidgetItem* root= ui._fileEntriesTW->topLevelItem(0); -// if (!root) { -// root= new QTreeWidgetItem; -// root->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate); -// root->setText(COLUMN_FILE, "/"); -// root->setToolTip(COLUMN_FILE,tr("This is the root directory.")); -// root->setText(COLUMN_FILEPATH, "/"); -// root->setText(COLUMN_HASH, ""); -// root->setData(COLUMN_HASH, ROLE_NAME, ""); -// root->setData(COLUMN_HASH, ROLE_PATH, ""); -// root->setData(COLUMN_HASH, ROLE_TYPE, DIR_TYPE_DIR); -// root->setText(COLUMN_SIZE, misc::friendlyUnit(0)); -// root->setToolTip(COLUMN_SIZE, tr("Real Size: Waiting child...")); -// root->setData(COLUMN_SIZE, ROLE_SIZE, 0); -// root->setData(COLUMN_SIZE, ROLE_SELSIZE, 0); -// root->setText(COLUMN_FILEC, "0"); -// root->setToolTip(COLUMN_FILEC, tr("Real File Count: Waiting child...")); -// root->setData(COLUMN_FILEC, ROLE_FILEC, 0); -// root->setData(COLUMN_FILEC, ROLE_SELFILEC, 0); -// ui._fileEntriesTW->addTopLevelItem(root); -// } -// root->setExpanded(true); -// -// return root; -} - -/** - * @brief RsCollectionDialog::updateList: Update list of item in RsCollection - * @return If at least one item have a Wrong Char - */ -bool RsCollectionDialog::updateList() -{ - bool wrong_chars = false ; - wrong_chars = addChild(getRootItem(), _newColFileInfos); - - _newColFileInfos.clear(); - - ui._filename_TL->setText(_fileName) ; - for (int column = 0; column < ui._fileEntriesTW->columnCount(); ++column) { - ui._fileEntriesTW->resizeColumnToContents(column); - } - - updateSizes() ; - - return !wrong_chars; -} - -/** - * @brief RsCollectionDialog::addChild: Add Child Item in list - * @param parent: Parent Item - * @param child: Child ColFileInfo item to add - * @param total_size: Saved total size of children to save in parent - * @param total_files: Saved total file of children to save in parent - * @return If at least one item have a Wrong Char - */ -bool RsCollectionDialog::addChild(QTreeWidgetItem* parent, const std::vector& child) -{ - bool wrong_chars = false ; - - uint32_t childCount = child.size(); - for(uint32_t i=0; i founds; - QList parentsFounds; - parentsFounds = ui._fileEntriesTW->findItems(colFileInfo.path , Qt::MatchExactly | Qt::MatchRecursive, COLUMN_FILEPATH); - if (colFileInfo.type == DIR_TYPE_DIR){ - founds = ui._fileEntriesTW->findItems(colFileInfo.path + "/" +colFileInfo.name, Qt::MatchExactly | Qt::MatchRecursive, COLUMN_FILEPATH); - } else { - founds = ui._fileEntriesTW->findItems(colFileInfo.path + "/" +colFileInfo.name, Qt::MatchExactly | Qt::MatchRecursive, COLUMN_FILEPATH); - if (ui._removeDuplicate_CB->isChecked()) { - founds << ui._fileEntriesTW->findItems(colFileInfo.hash, Qt::MatchExactly | Qt::MatchRecursive, COLUMN_HASH); - } - } - if (founds.empty()) { - QTreeWidgetItem *item = new QTreeWidgetItem; - - //item->setFlags(Qt::ItemIsUserCheckable | item->flags()); - item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate); - item->setCheckState(COLUMN_FILE, Qt::Checked); - item->setText(COLUMN_FILE, colFileInfo.name); - item->setText(COLUMN_FILEPATH, colFileInfo.path + "/" + colFileInfo.name); - item->setText(COLUMN_HASH, colFileInfo.hash); - item->setData(COLUMN_HASH, ROLE_NAME, colFileInfo.name); - item->setData(COLUMN_HASH, ROLE_PATH, colFileInfo.path); - item->setData(COLUMN_HASH, ROLE_TYPE, colFileInfo.type); - QFont font = item->font(COLUMN_FILE); - if (colFileInfo.type==DIR_TYPE_DIR) { - item->setToolTip(COLUMN_FILE,tr("This is a directory. Double-click to expand it.")); - font.setBold(true); - //Size calculated after for added child after init - item->setText(COLUMN_SIZE, misc::friendlyUnit(0)); - item->setToolTip(COLUMN_SIZE,tr("Real Size: Waiting child...")); - item->setData(COLUMN_SIZE, ROLE_SIZE, 0); - item->setData(COLUMN_SIZE, ROLE_SELSIZE, 0); - - item->setText(COLUMN_FILEC, ""); - item->setToolTip(COLUMN_FILEC, tr("Real File Count: Waiting child...")); - item->setData(COLUMN_FILEC, ROLE_FILEC, 0); - item->setData(COLUMN_FILEC, ROLE_SELFILEC, 0); - } else { - font.setBold(false); - item->setText(COLUMN_SIZE, misc::friendlyUnit(colFileInfo.size)); - item->setToolTip(COLUMN_SIZE, tr("Real Size=%1").arg(misc::friendlyUnit(colFileInfo.size))); - item->setData(COLUMN_SIZE, ROLE_SIZE, colFileInfo.size); - item->setData(COLUMN_SIZE, ROLE_SELSIZE, colFileInfo.size); - - item->setText(COLUMN_FILEC, "1"); - item->setToolTip(COLUMN_FILEC, tr("Real File Count=%1").arg(1)); - item->setData(COLUMN_FILEC, ROLE_FILEC, 1); - item->setData(COLUMN_FILEC, ROLE_SELFILEC, 1); - } - item->setFont(COLUMN_FILE, font); - item->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); - - if (colFileInfo.filename_has_wrong_characters) - { - //TODO (Phenom): Add qproperty for these text colors in stylesheets - wrong_chars = true ; - item->setData(COLUMN_FILE, Qt::ForegroundRole, QColor(255,80,120)) ; - } - - if (parentsFounds.empty()) { - parent->addChild(item); - } else { - parentsFounds.at(0)->addChild(item); - } - - if (colFileInfo.type == DIR_TYPE_FILE) { - //update parents size only for file children - QTreeWidgetItem *itemParent = item->parent(); - if (itemParent) { - while (itemParent) { - qulonglong parentSize = itemParent->data(COLUMN_SIZE, ROLE_SIZE).toULongLong() + colFileInfo.size; - itemParent->setData(COLUMN_SIZE, ROLE_SIZE, parentSize); - itemParent->setToolTip(COLUMN_SIZE, tr("Real Size=%1").arg(misc::friendlyUnit(parentSize))); - qulonglong parentSelSize = itemParent->data(COLUMN_SIZE, ROLE_SELSIZE).toULongLong() + colFileInfo.size; - itemParent->setData(COLUMN_SIZE, ROLE_SELSIZE, parentSelSize); - itemParent->setText(COLUMN_SIZE, misc::friendlyUnit(parentSelSize)); - - qulonglong parentFileCount = itemParent->data(COLUMN_FILEC, ROLE_FILEC).toULongLong() + 1; - itemParent->setData(COLUMN_FILEC, ROLE_FILEC, parentFileCount); - itemParent->setToolTip(COLUMN_FILEC, tr("Real File Count=%1").arg(parentFileCount)); - qulonglong parentSelFileCount = itemParent->data(COLUMN_FILEC, ROLE_SELFILEC).toULongLong() + 1; - itemParent->setData(COLUMN_FILEC, ROLE_SELFILEC, parentSelFileCount); - itemParent->setText(COLUMN_FILEC, QString("%1").arg(parentSelFileCount)); - - itemParent = itemParent->parent(); - } - } - } - - founds.push_back(item); - } - - if (!founds.empty()) { - - if (colFileInfo.type == DIR_TYPE_DIR) { - wrong_chars |= addChild(founds.at(0), colFileInfo.children); - } - } - } - return wrong_chars; -} - /** * @brief RsCollectionDialog::directoryLoaded: called when ui._treeView have load an directory as QFileSystemModel don't load all in one time * @param dirLoaded: Name of directory just loaded @@ -596,7 +362,7 @@ void RsCollectionDialog::directoryLoaded(QString dirLoaded) if(!_dirLoaded) { - QFileInfo lastDir = Settings->getLastDir(RshareSettings::LASTDIR_EXTRAFILE); + QFileInfo lastDir = QFileInfo(Settings->getLastDir(RshareSettings::LASTDIR_EXTRAFILE)); if (lastDir.absoluteFilePath() == "") return; if (lastDir.absoluteFilePath() == dirLoaded) _dirLoaded = true; @@ -639,17 +405,8 @@ void RsCollectionDialog::directoryLoaded(QString dirLoaded) */ void RsCollectionDialog::updateSizes() { - uint64_t total_size = 0 ; - uint32_t total_count = 0 ; - - for(int i=0;itopLevelItemCount();++i) - { - total_size += ui._fileEntriesTW->topLevelItem(i)->data(COLUMN_SIZE ,ROLE_SELSIZE ).toULongLong(); - total_count += ui._fileEntriesTW->topLevelItem(i)->data(COLUMN_FILEC,ROLE_SELFILEC).toULongLong(); - } - - ui._selectedFiles_TL->setText(QString::number(total_count)); - ui._totalSize_TL->setText(misc::friendlyUnit(total_size)); + ui._selectedFiles_TL->setText(QString::number(mCollectionModel->totalSelected())); + ui._totalSize_TL->setText(misc::friendlyUnit(mCollectionModel->totalSize())); } /** @@ -658,21 +415,21 @@ void RsCollectionDialog::updateSizes() * @param bad * @return */ -static QString purifyFileName(const QString& input, bool& bad) +static bool checkFileName(const std::string& input, std::string& corrected) { - static const QString bad_chars = "/\\\"*:?<>|" ; - bad = false ; - QString output = input ; + static const std::string bad_chars ( "/\\\"*:?<>|" ); + bool ok = true ; + corrected = input ; - for(int i=0;ipreMods(); + mCollection->merge_in(qddOldFileCollection.fileTree()); + mCollectionModel->postMods(); + } + } + else if(mb.clickedButton()==btnCancel) + return; + else + return; + + } + else + { //create a new empty file to check if name if good. - if (!file.open(QFile::WriteOnly)) return; + if (!file.open(QFile::WriteOnly)) + return; file.remove(); } - _fileName = fileName; - - updateList(); + ui._filename_TL->setText(fileName); } /** * @brief RsCollectionDialog::add: */ -void RsCollectionDialog::add() +void RsCollectionDialog::addSelection() { - addRecursive(false); + addSelection(false); } /** * @brief RsCollectionDialog::addRecursive: */ -void RsCollectionDialog::addRecursive() +void RsCollectionDialog::addSelectionRecursive() { - addRecursive(true); + addSelection(true); } +static void recursBuildFileTree(const QString& path,RsFileTree& tree,RsFileTree::DirIndex dir_index,bool recursive,std::map& paths_to_hash) +{ + QFileInfo fileInfo = QFileInfo(path); + + if (fileInfo.isDir()) + { + auto di = tree.addDirectory(dir_index,fileInfo.fileName().toUtf8().constData()); + + if(recursive) + { + QDir dirParent = fileInfo.absoluteFilePath(); + dirParent.setFilter(QDir::AllEntries | QDir::NoSymLinks | QDir::NoDotAndDotDot); + QFileInfoList childrenList = dirParent.entryInfoList(); + + for(QFileInfo f:childrenList) + recursBuildFileTree(f.absoluteFilePath(),tree,di,recursive,paths_to_hash); + } + } + else + { + // Here we use a temporary hash that serves two purposes: + // 1 - identify the file in the RsFileTree of the collection so that we can update its hash when calculated + // 2 - mark the file as being processed + // The hash s is computed to be the hash of the path of the file. The collection must take care of multiple instances. + + Sha1CheckSum s = RsDirUtil::sha1sum((uint8_t*)(fileInfo.filePath().toUtf8().constData()),fileInfo.filePath().toUtf8().size()); + + tree.addFile(dir_index,fileInfo.fileName().toUtf8().constData(),s,fileInfo.size()); + + paths_to_hash.insert(std::make_pair(fileInfo.filePath(),s)); + } +} /** * @brief RsCollectionDialog::addRecursive: Add Selected item to RSCollection * -Add File seperatly if parent folder not selected @@ -757,139 +550,47 @@ void RsCollectionDialog::addRecursive() * -Get root folder the selected one * @param recursive: If true, add all selected directory childrens */ -void RsCollectionDialog::addRecursive(bool recursive) +void RsCollectionDialog::addSelection(bool recursive) { - QStringList fileToHash; QMap dirToAdd; - int count=0;//to not scan all items on list .count() - QModelIndexList milSelectionList = ui._systemFileTW->selectionModel()->selectedIndexes(); + + mCollectionModel->preMods(); + + std::map paths_to_hash; // sha1sum of the paths to hash. + foreach (QModelIndex index, milSelectionList) - { + if(index.column()==0) //Get only FileName + { + RsFileTree tree; + recursBuildFileTree(_dirModel->filePath(_tree_proxyModel->mapToSource(index)),tree,tree.root(),recursive,paths_to_hash); - if (index.column()==0){//Get only FileName - QString filePath = _dirModel->filePath(_tree_proxyModel->mapToSource(index)); - QFileInfo fileInfo = filePath; - if (fileInfo.isDir()) { - dirToAdd.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath()); - ++count; - if (recursive) { - if (!addAllChild(fileInfo, dirToAdd, fileToHash, count)) return; - } else { - continue; - } - } - if (fileInfo.isFile()){ - fileToHash.append(fileInfo.absoluteFilePath()); - ++count; - if (dirToAdd.contains(fileInfo.absolutePath())) - _listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath()); - else - _listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),""); - } + mCollection->merge_in(tree); } - } - // Process Dirs - QTreeWidgetItem *item = NULL; - if (!ui._fileEntriesTW->selectedItems().empty()) - item= ui._fileEntriesTW->selectedItems().at(0); - if (item) { - while (item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) { - item = item->parent();//Only Dir as Parent - } - } + mFilesBeingHashed.insert(paths_to_hash.begin(),paths_to_hash.end()); - int index = 0; - while (index < dirToAdd.count()) - { - ColFileInfo root; - if (item && (item != getRootItem())) { - root.name = ""; - root.path = item->text(COLUMN_FILEPATH); - } else { - root.name = ""; - root.path = ""; - } - //QMap is ordered, so we get parent before child - //Iterator is moved inside this function - processItem(dirToAdd, index, root); - } + QStringList paths; + std::list hashes; - //Update liste before attach files to be sure when file is hashed, parent directory exists. - updateList(); + for(auto it:paths_to_hash) + { + paths.push_back(it.first); + hashes.push_back(it.second); - for (QHash::Iterator it = _listOfFilesAddedInDir.begin(); it != _listOfFilesAddedInDir.end() ; ++it) - { - QString path = it.value(); - //it.value() = "";//Don't reset value, could be an older attachment not terminated. - if (dirToAdd.contains(path)){ - it.value() = dirToAdd.value(path); - } else if(item) { - if (item->data(COLUMN_HASH, ROLE_NAME) != "") { - it.value() = item->text(COLUMN_FILEPATH); - } - } - } + std::cerr << "Setting file has being hased: ID=" << it.second << " - " << it.first.toUtf8().constData() << std::endl; + } - // Process Files once all done - ui._hashBox->addAttachments(fileToHash,RS_FILE_REQ_ANONYMOUS_ROUTING /*, 0*/); -} + mCollectionModel->notifyFilesBeingHashed(hashes); + mCollectionModel->postMods(); -/** - * @brief RsCollectionDialog::addAllChild: Add children to RsCollection - * @param fileInfoParent: Parent's QFileInfo to scan - * @param dirToAdd: QMap where directories are added - * @param fileToHash: QStringList where files are added - * @return false if too many items is selected and aborted - */ -bool RsCollectionDialog::addAllChild(QFileInfo &fileInfoParent - , QMap &dirToAdd - , QStringList &fileToHash - , int &count) -{ - //Save count only first time to not scan all items on list .count() - if (count == 0) count = (dirToAdd.count() + fileToHash.count()); - QDir dirParent = fileInfoParent.absoluteFilePath(); - dirParent.setFilter(QDir::AllEntries | QDir::NoSymLinks | QDir::NoDotAndDotDot); - QFileInfoList childrenList = dirParent.entryInfoList(); - foreach (QFileInfo fileInfo, childrenList) - { - if (count == MAX_FILE_ADDED_BEFORE_ASK) - { - QMessageBox msgBox; - msgBox.setText(tr("Warning, selection contains more than %1 items.").arg(MAX_FILE_ADDED_BEFORE_ASK)); - msgBox.setInformativeText("Do you want to continue?"); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - int ret = msgBox.exec(); - switch (ret) { - case QMessageBox::Yes: - break; - case QMessageBox::No: - return false; - break; - break; - default: - // should never be reached - break; - } - } - if (fileInfo.isDir()) { - dirToAdd.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath()); - ++count; - if (!addAllChild(fileInfo, dirToAdd, fileToHash, count)) return false; - } - if (fileInfo.isFile()){ - fileToHash.append(fileInfo.absoluteFilePath()); - ++count; - if (dirToAdd.contains(fileInfo.absolutePath())) - _listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath()); - else - _listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),""); - } - } - return true; + ui._hashBox->addAttachments(paths,RS_FILE_REQ_ANONYMOUS_ROUTING /*, 0*/); + + if(!mFilesBeingHashed.empty()) + { + ui._save_PB->setToolTip(tr("Please wait for all files to be properly processed before saving.")); + ui._save_PB->setEnabled(false); + } } /** @@ -897,172 +598,26 @@ bool RsCollectionDialog::addAllChild(QFileInfo &fileInfoParent */ void RsCollectionDialog::remove() { - bool removeOnlyFile=false; - QString listDir; - // First, check if selection contains directories - for (int curs = 0; curs < ui._fileEntriesTW->selectedItems().count(); ++curs) - {// Have to call ui._fileEntriesTW->selectedItems().count() each time as selected could change - QTreeWidgetItem *item = NULL; - item= ui._fileEntriesTW->selectedItems().at(curs); + QMap dirToRemove; + int count=0;//to not scan all items on list .count() - //Uncheck child directory item if parent is checked - if (item != getRootItem()){ - if (item->data(COLUMN_HASH, ROLE_TYPE).toUInt() == DIR_TYPE_DIR) { - QString path = item->data(COLUMN_HASH, ROLE_PATH).toString(); - if (listDir.contains(path) && !path.isEmpty()) { - item->setSelected(false); - } else { - listDir += item->data(COLUMN_HASH, ROLE_NAME).toString() +"
"; - } - } - } - } + QModelIndexList milSelectionList = ui._fileEntriesTW->selectionModel()->selectedIndexes(); - //If directories, ask to remove them or not - if (!listDir.isEmpty()){ - QMessageBox* msgBox = new QMessageBox(QMessageBox::Information, "", ""); - msgBox->setText("Warning, selection contains directories."); - //msgBox->setInformativeText(); If text too long, no scroll, so I add an text edit - QGridLayout* layout = qobject_cast(msgBox->layout()); - if (layout) { - int newRow = 1; - for (int row = layout->count()-1; row >= 0; --row) { - for (int col = layout->columnCount()-1; col >= 0; --col) { - QLayoutItem *item = layout->itemAtPosition(row, col); - if (item) { - int index = layout->indexOf(item->widget()); - int r=0, c=0, rSpan=0, cSpan=0; - layout->getItemPosition(index, &r, &c, &rSpan, &cSpan); - if (r>0) { - layout->removeItem(item); - layout->addItem(item, r+3, c, rSpan, cSpan); - } else if (rSpan>1) { - newRow = rSpan + 1; - } - } - } - } - QLabel *label = new QLabel(tr("Do you want to remove them and all their children, too?")); - layout->addWidget(label,newRow, 0, 1, layout->columnCount(), Qt::AlignHCenter ); - QTextEdit *edit = new QTextEdit(listDir); - edit->setReadOnly(true); - edit->setWordWrapMode(QTextOption::NoWrap); - layout->addWidget(edit,newRow+1, 0, 1, layout->columnCount(), Qt::AlignHCenter ); - } + mCollectionModel->preMods(); - msgBox->setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - msgBox->setDefaultButton(QMessageBox::Yes); - int ret = msgBox->exec(); - switch (ret) { - case QMessageBox::Yes: - break; - case QMessageBox::No: - removeOnlyFile = true; - break; - case QMessageBox::Cancel: { - delete msgBox; - return; - } - break; - default: - // should never be reached - break; - } - delete msgBox; - } + foreach (QModelIndex index, milSelectionList) + if(index.column()==0) //Get only FileName + { + auto indx = mCollectionModel->getIndex(index); + auto parent_indx = mCollectionModel->getIndex(index.parent()); - //Remove wanted items - int leftItem = 0; - // Have to call ui._fileEntriesTW->selectedItems().count() each time as selected change - while (ui._fileEntriesTW->selectedItems().count() > leftItem) { - QTreeWidgetItem *item = ui._fileEntriesTW->selectedItems().at(leftItem); + if(indx.is_file) + mCollection->removeFile(indx.index,parent_indx.index); + else + mCollection->removeDirectory(indx.index,parent_indx.index); + } - if (item != getRootItem()){ - if (!removeItem(item, removeOnlyFile)) { - ++leftItem; - } - } else { - //Get Root change index - ++leftItem; - } - } - - updateSizes() ; - -} - -bool RsCollectionDialog::removeItem(QTreeWidgetItem *item, bool &removeOnlyFile) -{ - if (item){ - if ((item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) || !removeOnlyFile) { - int leftItem = 0; - while (item->childCount() > leftItem) { - if (!removeItem(item->child(0), removeOnlyFile)) { - ++leftItem; - } - } - if (leftItem == 0) { - //First uncheck item to update parent informations - item->setCheckState(COLUMN_FILE,Qt::Unchecked); - QTreeWidgetItem *parent = item->parent(); - if (parent) { - parent->removeChild(item); - } else { - getRootItem()->removeChild(item); - } - return true; - } else { - if (!removeOnlyFile) { - std::cerr << "(EE) RsCollectionDialog::removeItem This could never happen." << std::endl; - } - } - } - } - return false; -} - -/** Process each item to make a new RsCollection item */ -void RsCollectionDialog::processItem(QMap &dirToAdd - , int &index - , ColFileInfo &parent - ) -{ - ColFileInfo newChild; - int count = dirToAdd.count(); - if (index < count) { - QString key=dirToAdd.keys().at(index); - bool bad_chars_detected = false; - QFileInfo fileInfo=key; - QString cleanDirName = purifyFileName(fileInfo.fileName(),bad_chars_detected); - newChild.name = cleanDirName; - newChild.filename_has_wrong_characters = bad_chars_detected; - newChild.size = fileInfo.isDir()? 0: fileInfo.size(); - newChild.type = fileInfo.isDir()? DIR_TYPE_DIR: DIR_TYPE_FILE ; - if (parent.name != "") { - newChild.path = parent.path + "/" + parent.name; - } else { - newChild.path = parent.path; - } - dirToAdd[key] = newChild.path + "/" + newChild.name; - //Move to next item - ++index; - if (index < count){ - QString newKey = dirToAdd.keys().at(index); - while ((dirToAdd.value(newKey) == key) - && (index < count)) { - processItem(dirToAdd, index, newChild); - if (index < count)newKey = dirToAdd.keys().at(index); - } - } - - //Save parent when child are processed - if (parent.name != "") { - parent.children.push_back(newChild); - parent.size += newChild.size; - } else { - _newColFileInfos.push_back(newChild); - } - } + mCollectionModel->postMods(); } /** @@ -1070,119 +625,31 @@ void RsCollectionDialog::processItem(QMap &dirToAdd */ void RsCollectionDialog::makeDir() { - QString childName=""; - bool ok, badChar, nameOK = false; - // Ask for name - while (!nameOK) - { - childName = QInputDialog::getText(this, tr("New Directory") - , tr("Enter the new directory's name") - , QLineEdit::Normal, childName, &ok); - if (ok && !childName.isEmpty()) - { - childName = purifyFileName(childName, badChar); - nameOK = !badChar; - if (badChar) - { - QMessageBox msgBox; - msgBox.setText("The name contains bad characters."); - msgBox.setInformativeText("Do you want to use the corrected one?\n" + childName); - msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Retry | QMessageBox::Cancel); - msgBox.setDefaultButton(QMessageBox::Ok); - int ret = msgBox.exec(); - switch (ret) { - case QMessageBox::Ok: - nameOK = true; - break; - case QMessageBox::Retry: - break; - case QMessageBox::Cancel: - return; - break; - default: - // should never be reached - break; - } - } - } else {//if (ok && !childName.isEmpty()) - return; - } + QModelIndexList selected_indices = ui._fileEntriesTW->selectionModel()->selectedIndexes(); - } + if(selected_indices.size() > 1) + { + QMessageBox::information(nullptr,tr("Too many places selected"),tr("Please select at most one directory where to create the new folder")); + return; + } + QModelIndex place_index; - QList selected = ui._fileEntriesTW->selectedItems(); + if(!selected_indices.empty()) + place_index = selected_indices.first(); - if(selected.empty()) - { - QTreeWidgetItem *item = getRootItem(); + RsCollectionModel::EntryIndex e = mCollectionModel->getIndex(place_index); - ColFileInfo newChild; - newChild.name = childName; - newChild.filename_has_wrong_characters = false; - newChild.size = 0; - newChild.type = DIR_TYPE_DIR; - newChild.path = item->data(COLUMN_HASH, ROLE_PATH).toString() - + "/" + item->data(COLUMN_HASH, ROLE_NAME).toString(); - if (item == getRootItem()) newChild.path = ""; + if(e.is_file) + { + QMessageBox::information(nullptr,tr("Selected place cannot be a file"),tr("Please select at most one directory where to create the new folder")); + return; + } + QString childName = QInputDialog::getText(this, tr("New Directory"), tr("Enter the new directory's name"), QLineEdit::Normal); - _newColFileInfos.push_back(newChild); - } - else - for(auto it(selected.begin());it!=selected.end();++it) - { - QTreeWidgetItem *item = *it; - - while(item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) - item = item->parent();//Only Dir as Parent - - ColFileInfo newChild; - newChild.name = childName; - newChild.filename_has_wrong_characters = false; - newChild.size = 0; - newChild.type = DIR_TYPE_DIR; - - if (item == getRootItem()) - newChild.path = ""; - else - newChild.path = item->data(COLUMN_HASH, ROLE_PATH).toString() + "/" + item->data(COLUMN_HASH, ROLE_NAME).toString(); - - _newColFileInfos.push_back(newChild); - } - - -// // Process all selected items -// int count = ui._fileEntriesTW->selectedItems().count(); -// int curs = 0; -// if (count == 0) curs = -1; -// -// for (; curs < count; ++curs) -// { -// QTreeWidgetItem *item = NULL; -// if (curs >= 0) { -// item= ui._fileEntriesTW->selectedItems().at(curs); -// } else { -// item = getRootItem(); -// } -// if (item) { -// while (item->parent() != NULL && item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) { -// item = item->parent();//Only Dir as Parent -// } -// ColFileInfo newChild; -// newChild.name = childName; -// newChild.filename_has_wrong_characters = false; -// newChild.size = 0; -// newChild.type = DIR_TYPE_DIR; -// newChild.path = item->data(COLUMN_HASH, ROLE_PATH).toString() -// + "/" + item->data(COLUMN_HASH, ROLE_NAME).toString(); -// if (item == getRootItem()) newChild.path = ""; -// -// _newColFileInfos.push_back(newChild); -// } -// } - - - updateList(); + mCollectionModel->preMods(); + mCollection->merge_in(*RsFileTree::fromDirectory(childName.toUtf8().constData()),e.index); + mCollectionModel->postMods(); } /** @@ -1192,156 +659,34 @@ void RsCollectionDialog::makeDir() */ void RsCollectionDialog::fileHashingFinished(QList hashedFiles) { - std::cerr << "RsCollectionDialog::fileHashingFinished() started." << std::endl; + // build a map of old-hash to new-hash for the hashed files, so that it can be passed to the mCollection for update - QString message; + mCollectionModel->preMods(); + std::map old_to_new_hashes; - QList::iterator it; - for (it = hashedFiles.begin(); it != hashedFiles.end(); ++it) { - HashedFile& hashedFile = *it; + for(auto f:hashedFiles) + { + auto it = mFilesBeingHashed.find(f.filepath); - ColFileInfo colFileInfo; - colFileInfo.name=hashedFile.filename; - colFileInfo.path=""; - colFileInfo.size=hashedFile.size; - colFileInfo.hash=QString::fromStdString(hashedFile.hash.toStdString()); - colFileInfo.filename_has_wrong_characters=false; - colFileInfo.type=DIR_TYPE_FILE; + if(it == mFilesBeingHashed.end()) + { + RsErr() << "Could not find hash-ID correspondence for path " << f.filepath.toUtf8().constData() << ". This is a bug." << std::endl; + continue; + } + std::cerr << "Will update old hash " << it->second << " to new hash " << f.hash << std::endl; - if(_listOfFilesAddedInDir.value(hashedFile.filepath,"")!="") { - //File Added in directory, find its parent - colFileInfo.path = _listOfFilesAddedInDir.value(hashedFile.filepath,""); - _listOfFilesAddedInDir.remove(hashedFile.filepath); - } + old_to_new_hashes.insert(std::make_pair(it->second,f.hash)); + mFilesBeingHashed.erase(it); + mCollectionModel->fileHashingFinished(it->second); + } + mCollection->updateHashes(old_to_new_hashes); + mCollectionModel->postMods(); - _newColFileInfos.push_back(colFileInfo); - - } - - std::cerr << "RsCollectionDialog::fileHashingFinished message : " << message.toStdString() << std::endl; - - updateList(); -} - -void RsCollectionDialog::itemChanged(QTreeWidgetItem *item, int col) -{ - if (col != COLUMN_FILE) return; - - if (item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_FILE) return; - - //In COLUMN_FILE, normaly, only checkState could change... - qulonglong size = item->data(COLUMN_SIZE, ROLE_SIZE).toULongLong(); - bool unchecked = (item->checkState(COLUMN_FILE) == Qt::Unchecked); - item->setData(COLUMN_SIZE, ROLE_SELSIZE, unchecked?0:size); - item->setText(COLUMN_SIZE, misc::friendlyUnit(unchecked?0:size)); - item->setData(COLUMN_FILEC, ROLE_SELFILEC, unchecked?0:1); - item->setText(COLUMN_FILEC, QString("%1").arg(unchecked?0:1)); - - //update parents size - QTreeWidgetItem *itemParent = item->parent(); - while (itemParent) { - //When unchecked only remove selected size - qulonglong parentSize = itemParent->data(COLUMN_SIZE, ROLE_SELSIZE).toULongLong() + (unchecked?0-size:size); - itemParent->setData(COLUMN_SIZE, ROLE_SELSIZE, parentSize); - itemParent->setText(COLUMN_SIZE, misc::friendlyUnit(parentSize)); - - qulonglong parentFileCount = itemParent->data(COLUMN_FILEC, ROLE_SELFILEC).toULongLong() + (unchecked?0-1:1); - itemParent->setData(COLUMN_FILEC, ROLE_SELFILEC, parentFileCount); - itemParent->setText(COLUMN_FILEC, QString("%1").arg(parentFileCount)); - - itemParent = itemParent->parent(); - } - - updateSizes() ; - -} - -/** - * @brief RsCollectionDialog::updateRemoveDuplicate Remove all duplicate file when checked. - * @param checked - */ -void RsCollectionDialog::updateRemoveDuplicate(bool checked) -{ - if (checked) { - bool bRemoveAll = false; - QTreeWidgetItemIterator it(ui._fileEntriesTW); - QTreeWidgetItem *item; - while ((item = *it) != NULL) { - ++it; - if (item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) { - QList founds; - founds << ui._fileEntriesTW->findItems(item->text(COLUMN_HASH), Qt::MatchExactly | Qt::MatchRecursive, COLUMN_HASH); - if (founds.count() > 1) { - bool bRemove = false; - if (!bRemoveAll) { - QMessageBox* msgBox = new QMessageBox(QMessageBox::Information, "", ""); - msgBox->setText("Warning, duplicate file found."); - //msgBox->setInformativeText(); If text too long, no scroll, so I add an text edit - msgBox->setStandardButtons(QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - msgBox->setDefaultButton(QMessageBox::Yes); - - QGridLayout* layout = qobject_cast(msgBox->layout()); - if (layout) { - int newRow = 1; - for (int row = layout->count()-1; row >= 0; --row) { - for (int col = layout->columnCount()-1; col >= 0; --col) { - QLayoutItem *item = layout->itemAtPosition(row, col); - if (item) { - int index = layout->indexOf(item->widget()); - int r=0, c=0, rSpan=0, cSpan=0; - layout->getItemPosition(index, &r, &c, &rSpan, &cSpan); - if (r>0) { - layout->removeItem(item); - layout->addItem(item, r+3, c, rSpan, cSpan); - } else if (rSpan>1) { - newRow = rSpan + 1; - } - } - } - } - QLabel *label = new QLabel(tr("Do you want to remove this file from the list?")); - layout->addWidget(label,newRow, 0, 1, layout->columnCount(), Qt::AlignHCenter ); - QTextEdit *edit = new QTextEdit(item->text(COLUMN_FILEPATH)); - edit->setReadOnly(true); - edit->setWordWrapMode(QTextOption::NoWrap); - layout->addWidget(edit,newRow+1, 0, 1, layout->columnCount(), Qt::AlignHCenter ); - } - - int ret = msgBox->exec(); - switch (ret) { - case QMessageBox::YesToAll: { - bRemoveAll = true; - } - break; - case QMessageBox::Yes: { - bRemove = true; - } - break; - case QMessageBox::No: - break; - case QMessageBox::Cancel: { - delete msgBox; - ui._removeDuplicate_CB->setChecked(false); - return; - } - break; - default: - // should never be reached - break; - } - delete msgBox; - } - - if (bRemove || bRemoveAll) { - //First uncheck item to update parent informations - item->setCheckState(COLUMN_FILE,Qt::Unchecked); - item->parent()->removeChild(item); - } - - } - } - } - } + if(mFilesBeingHashed.empty()) + { + ui._save_PB->setToolTip(tr("")); + ui._save_PB->setEnabled(true); + } } /** @@ -1359,47 +704,85 @@ void RsCollectionDialog::cancel() void RsCollectionDialog::download() { std::cerr << "Downloading!" << std::endl; + bool auto_correct = false; + bool auto_skip = false; QString dldir = ui.downloadFolder_LE->text(); std::cerr << "downloading all these files:" << std::endl; - QTreeWidgetItemIterator itemIterator(ui._fileEntriesTW); - QTreeWidgetItem *item; - while ((item = *itemIterator) != NULL) { - ++itemIterator; + std::function recursDL = [&](RsFileTree::DirIndex index,const std::string& path) + { + const auto& dirdata(mCollection->fileTree().directoryData(index)); + RsCollectionModel::EntryIndex e; - if (item->checkState(COLUMN_FILE) == Qt::Checked) { - std::cerr << item->data(COLUMN_HASH,ROLE_NAME).toString().toStdString() - << " " << item->text(COLUMN_HASH).toStdString() - << " " << item->text(COLUMN_SIZE).toStdString() - << " " << item->data(COLUMN_HASH,ROLE_PATH).toString().toStdString() << std::endl; - ColFileInfo colFileInfo; - colFileInfo.hash = item->text(COLUMN_HASH); - colFileInfo.name = item->data(COLUMN_HASH,ROLE_NAME).toString(); - colFileInfo.path = item->data(COLUMN_HASH,ROLE_PATH).toString(); - colFileInfo.type = item->data(COLUMN_HASH,ROLE_TYPE).toUInt(); - colFileInfo.size = item->data(COLUMN_SIZE,ROLE_SELSIZE).toULongLong(); + for(uint32_t i=0;iisChecked(e)) + continue; - if(!QDir(QApplication::applicationDirPath()).mkpath(cleanPath)) - QMessageBox::warning(NULL,QObject::tr("Unable to make path"),QObject::tr("Unable to make path:")+"
"+cleanPath) ; + const auto& sdd = mCollection->fileTree().directoryData(e.index); + std::string subpath = RsDirUtil::makePath(path,sdd.name); - if (colFileInfo.type==DIR_TYPE_FILE) - rsFiles->FileRequest(colFileInfo.name.toUtf8().constData(), - RsFileHash(colFileInfo.hash.toStdString()), - colFileInfo.size, - cleanPath.toUtf8().constData(), - RS_FILE_REQ_ANONYMOUS_ROUTING, - std::list()); - } else {//if (item->checkState(COLUMN_FILE) == Qt::Checked) - std::cerr<<"Skipping file : " << item->data(COLUMN_HASH,ROLE_NAME).toString().toStdString() << std::endl; - } - } + std::cerr << "Creating subdir " << sdd.name << " to directory " << path << std::endl; - close(); + if(!QDir(QApplication::applicationDirPath()).mkpath(QString::fromUtf8(subpath.c_str()))) + QMessageBox::warning(NULL,tr("Unable to make path"),tr("Unable to make path:")+"
"+QString::fromUtf8(subpath.c_str())) ; + + recursDL(dirdata.subdirs[i],subpath); + } + for(uint32_t i=0;iisChecked(e)) + continue; + + std::string subpath = RsDirUtil::makePath(path,dirdata.name); + const auto& f(mCollection->fileTree().fileData(dirdata.subfiles[i])); + + std::string corrected_name; + + if(!checkFileName(f.name,corrected_name) && !auto_correct) + { + if(auto_skip) + continue; + + QMessageBox mb; + mb.setText(tr("Incompatible filename.")); + mb.setInformativeText(tr("This filename is not usable on your system.")+"\n"+tr("Retroshare can replace every problematic chars by '_'.") + +"\n"+tr("What do you want to do?")); + QAbstractButton *btnCorrect = mb.addButton(tr("Correct filename"), QMessageBox::YesRole); + QAbstractButton *btnCorrectAll = mb.addButton(tr("Correct all"), QMessageBox::AcceptRole); + QAbstractButton *btnSkip = mb.addButton(tr("Skip this file"), QMessageBox::NoRole); + QAbstractButton *btnSkipAll = mb.addButton(tr("Skip all"), QMessageBox::RejectRole); + mb.setIcon(QMessageBox::Question); + mb.exec(); + + if(mb.clickedButton() == btnSkipAll) + { + auto_skip = true; + continue; + } + if(mb.clickedButton() == btnSkip) + continue; + + if(mb.clickedButton() == btnCorrectAll) + auto_correct = true; + } + + std::cerr << "Requesting file " << corrected_name << " to directory " << path << std::endl; + + rsFiles->FileRequest(corrected_name,f.hash,f.size,path,RS_FILE_REQ_ANONYMOUS_ROUTING,std::list()); + } + }; + + recursDL(mCollection->fileTree().root(),dldir.toUtf8().constData()); + close(); } /** @@ -1407,40 +790,66 @@ void RsCollectionDialog::download() */ void RsCollectionDialog::save() { - std::cerr << "Saving!" << std::endl; - _newColFileInfos.clear(); - QTreeWidgetItem* root = getRootItem(); - if (root) { - saveChild(root); + if(ui._filename_TL->text().isNull()) + changeFileName(); + if(ui._filename_TL->text().isNull()) + return; - emit saveColl(_newColFileInfos, _fileName); - } - close(); + mCollectionModel->preMods(); + mCollection->cleanup(); + mCollection->save(ui._filename_TL->text()); + close(); } -/** - * @brief RsCollectionDialog::saveChild: Save each child in _newColFileInfos - * @param parent - */ -void RsCollectionDialog::saveChild(QTreeWidgetItem *parentItem, ColFileInfo *parentInfo) +bool RsCollectionDialog::editExistingCollection(const QString& fileName, bool showError /* = true*/) { - ColFileInfo parent; - if (!parentInfo) parentInfo = &parent; - - parentInfo->checked = (parentItem->checkState(COLUMN_FILE)==Qt::Checked); - parentInfo->hash = parentItem->text(COLUMN_HASH); - parentInfo->name = parentItem->data(COLUMN_HASH,ROLE_NAME).toString(); - parentInfo->path = parentItem->data(COLUMN_HASH,ROLE_PATH).toString(); - parentInfo->type = parentItem->data(COLUMN_HASH,ROLE_TYPE).toUInt(); - parentInfo->size = parentItem->data(COLUMN_SIZE,ROLE_SELSIZE).toULongLong(); - - for (int i=0; ichildCount(); ++i) { - ColFileInfo child; - saveChild(parentItem->child(i), &child); - if (parentInfo->name != "") { - parentInfo->children.push_back(child); - } else { - _newColFileInfos.push_back(child); - } - } + return RsCollectionDialog(fileName,EDIT).exec(); } + +bool RsCollectionDialog::openExistingCollection(const QString& fileName, bool showError /* = true*/) +{ + return RsCollectionDialog(fileName,DOWNLOAD).exec(); +} + +bool RsCollectionDialog::downloadFiles(const RsCollection &collection) +{ + return RsCollectionDialog(collection,DOWNLOAD).exec(); +} + + +bool RsCollectionDialog::openNewCollection(const RsFileTree& tree) +{ + RsCollection collection(tree); + QString fileName; + + if(!misc::getSaveFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE + , QApplication::translate("RsCollectionFile", "Create collection file") + , QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")" + , fileName,0, QFileDialog::DontConfirmOverwrite)) + return false; + + if (!fileName.endsWith("." + RsCollection::ExtensionString)) + fileName += "." + RsCollection::ExtensionString ; + + std::cerr << "Got file name: " << fileName.toStdString() << std::endl; + + if(QFile(fileName).exists()) + { + QMessageBox mb; + mb.setText(tr("Save Collection File.")); + mb.setInformativeText(tr("File already exists.")+"\n"+tr("What do you want to do?")); + QAbstractButton *btnOwerWrite = mb.addButton(tr("Overwrite"), QMessageBox::YesRole); + QAbstractButton *btnCancel = mb.addButton(tr("Cancel"), QMessageBox::ResetRole); + mb.setIcon(QMessageBox::Question); + mb.exec(); + + if (mb.clickedButton()==btnCancel) + return false; + } + + if(!collection.save(fileName)) + return false; + + return RsCollectionDialog(fileName,EDIT).exec(); +} + diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.h b/retroshare-gui/src/gui/common/RsCollectionDialog.h index 43c7dbdd7..3c1f5c29a 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.h +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.h @@ -18,8 +18,10 @@ * * *******************************************************************************/ +#include #include "ui_RsCollectionDialog.h" #include "RsCollection.h" +#include "RsCollectionModel.h" #include #include @@ -30,33 +32,45 @@ class RsCollectionDialog: public QDialog Q_OBJECT public: - RsCollectionDialog(const QString& filename - , const std::vector &colFileInfos - , const bool& creation - , const bool& readOnly = false) ; virtual ~RsCollectionDialog(); + // Open new collection + static bool openNewCollection(const RsFileTree &tree = RsFileTree()); + + // Edit existing collection + static bool editExistingCollection(const QString& fileName, bool showError = true); + + // Open existing collection for download + static bool openExistingCollection(const QString& fileName, bool showError = true); + + // Open existing collection for download + static bool downloadFiles(const RsCollection& collection); protected: - bool eventFilter(QObject *obj, QEvent *ev); + static QString errorString(RsCollection::RsCollectionErrorCode code); + + void init(const QString& collectionFileName); + + enum RsCollectionDialogMode { + UNKNOWN = 0x00, + EDIT = 0x01, + DOWNLOAD = 0x02, + }; + + RsCollectionDialog(const QString& filename, RsCollectionDialogMode mode) ; + RsCollectionDialog(const RsCollection& coll, RsCollectionDialogMode mode) ; private slots: void directoryLoaded(QString dirLoaded); void updateSizes() ; void changeFileName() ; - void add() ; - void addRecursive() ; + void addSelection() ; + void addSelectionRecursive() ; void remove() ; void chooseDestinationDirectory(); void setDestinationDirectory(); void openDestinationDirectoryMenu(); - void processItem(QMap &dirToAdd - , int &index - , ColFileInfo &parent - ) ; void makeDir() ; void fileHashingFinished(QList hashedFiles) ; - void itemChanged(QTreeWidgetItem* item,int col) ; - void updateRemoveDuplicate(bool checked); void cancel() ; void download() ; void save() ; @@ -66,26 +80,20 @@ signals: private: void processSettings(bool bLoad) ; - QTreeWidgetItem* getRootItem(); - bool updateList(); - bool addChild(QTreeWidgetItem *parent, const std::vector &child); - bool removeItem(QTreeWidgetItem *item, bool &removeOnlyFile) ; - void addRecursive(bool recursive) ; - bool addAllChild(QFileInfo &fileInfoParent - , QMap &dirToAdd - , QStringList &fileToHash - , int &count); - void saveChild(QTreeWidgetItem *parentItem, ColFileInfo *parentInfo = NULL); + void addSelection(bool recursive) ; Ui::RsCollectionDialog ui; - QString _fileName ; - const bool _creationMode ; - const bool _readOnly; - std::vector _newColFileInfos ; + + RsCollectionDialogMode _mode; QFileSystemModel *_dirModel; QSortFilterProxyModel *_tree_proxyModel; QItemSelectionModel *_selectionProxy; bool _dirLoaded; QHash _listOfFilesAddedInDir; + + RsCollectionModel *mCollectionModel; + RsCollection *mCollection; + + std::map mFilesBeingHashed; // map of file path vs. temporary ID used for the file while hashing }; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.ui b/retroshare-gui/src/gui/common/RsCollectionDialog.ui index ceaea3b99..5ceadb647 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.ui +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.ui @@ -6,8 +6,8 @@ 0 0 - 600 - 400 + 761 + 434
@@ -17,13 +17,13 @@ Collection - + :/images/mimetypes/rscollection-16.png:/images/mimetypes/rscollection-16.png true - + 0 @@ -50,14 +50,14 @@
- + QFrame::StyledPanel QFrame::Raised - + @@ -70,7 +70,7 @@ QFrame::Plain - + @@ -88,7 +88,7 @@ 0 - + 0 @@ -157,7 +157,7 @@ - + 21 @@ -170,6 +170,10 @@ ... + + + :/icons/browsable_blue_128.png:/icons/browsable_blue_128.png + @@ -283,7 +287,7 @@ - :/images/feedback_arrow.png:/images/feedback_arrow.png + :/images/start.png:/images/start.png @@ -309,7 +313,7 @@ - :/images/update.png:/images/update.png + :/images/startall.png:/images/startall.png @@ -335,7 +339,7 @@ - :/images/deletemail24.png:/images/deletemail24.png + :/images/delete.png:/images/delete.png
@@ -382,7 +386,7 @@
- + QAbstractItemView::NoEditTriggers @@ -398,11 +402,6 @@ true - - - 1 - -
@@ -410,27 +409,7 @@
- - - - - Remove Duplicate - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - + @@ -451,6 +430,12 @@ + + + 0 + 0 + + Qt::CustomContextMenu @@ -462,6 +447,19 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -498,7 +496,7 @@ - frame + gradFrame headerFrame
@@ -517,7 +515,7 @@ - + diff --git a/retroshare-gui/src/gui/common/RsCollectionModel.cpp b/retroshare-gui/src/gui/common/RsCollectionModel.cpp new file mode 100644 index 000000000..8c7fa9283 --- /dev/null +++ b/retroshare-gui/src/gui/common/RsCollectionModel.cpp @@ -0,0 +1,616 @@ +#include +#include + +#include "RsCollectionModel.h" + +// #define DEBUG_COLLECTION_MODEL 1 + +static const int COLLECTION_MODEL_FILENAME = 0; +static const int COLLECTION_MODEL_SIZE = 1; +static const int COLLECTION_MODEL_HASH = 2; +static const int COLLECTION_MODEL_COUNT = 3; +static const int COLLECTION_MODEL_NB_COLUMN = 4; + +RsCollectionModel::RsCollectionModel(const RsCollection& col, QObject *parent) + : QAbstractItemModel(parent),mCollection(col) +{ + postMods(); +} + +static std::ostream& operator<<(std::ostream& o,const RsCollectionModel::EntryIndex& i) +{ + return o << ((i.is_file)?("File"):"Dir") << " with index " << (int)i.index ; +} +static std::ostream& operator<<(std::ostream& o,const QModelIndex& i) +{ + return o << "QModelIndex (row " << i.row() << ", ref " << i.internalId() << ")" ; +} +#ifdef DEBUG_COLLECTION_MODEL +#endif + +// Indernal Id is always a quintptr_t (basically a uint with the size of a pointer). Depending on the +// Indernal Id is always a quintptr_t (basically a uint with the size of a pointer). Depending on the +// architecture, the pointer may have 4 or 8 bytes. We use the low-level bit for type (0=dir, 1=file) and +// the remaining bits for the index (which will be accordingly understood as a FileIndex or a DirIndex) +// This way, index 0 is always the top dir. + +bool RsCollectionModel::convertIndexToInternalId(const EntryIndex& e,quintptr& ref) +{ + ref = (e.index << 1) | e.is_file; + return true; +} + +bool RsCollectionModel::convertInternalIdToIndex(quintptr ref, EntryIndex& e) +{ + e.is_file = (bool)(ref & 1); + e.index = ref >> 1; + return true; +} + +int RsCollectionModel::rowCount(const QModelIndex& parent) const +{ +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << "Asking rowCount of " << parent << std::endl; +#endif + + if(parent.column() >= COLLECTION_MODEL_NB_COLUMN) + return 0; + + if(!parent.isValid()) + { +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << " root! returning " << mCollection.fileTree().directoryData(0).subdirs.size() + + mCollection.fileTree().directoryData(0).subfiles.size() << std::endl; +#endif + + return mCollection.fileTree().directoryData(0).subdirs.size() + + mCollection.fileTree().directoryData(0).subfiles.size(); + } + + EntryIndex i; + if(!convertInternalIdToIndex(parent.internalId(),i)) + return 0; + + if(i.is_file) + { +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << " file: returning 0" << std::endl; +#endif + return 0; + } + else + { +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << " dir: returning " << mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size() + << std::endl; +#endif + return mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size(); + } +} + +bool RsCollectionModel::hasChildren(const QModelIndex & parent) const +{ + if(!parent.isValid()) + return true; + + EntryIndex i; + if(!convertInternalIdToIndex(parent.internalId(),i)) + return false; + + if(i.is_file) + return false; + else if(mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size() > 0) + return true; + else + return false; +} + +int RsCollectionModel::columnCount(const QModelIndex&) const +{ + return COLLECTION_MODEL_NB_COLUMN; +} + +QVariant RsCollectionModel::headerData(int section, Qt::Orientation,int role) const +{ + if(role == Qt::DisplayRole) + switch(section) + { + case 0: return tr("File"); + case 1: return tr("Size"); + case 2: return tr("Hash"); + case 3: return tr("Count"); + default: + return QVariant(); + } + return QVariant(); +} + +QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & parent) const +{ + if(row < 0 || column < 0 || column >= columnCount(parent) || row >= rowCount(parent)) + return QModelIndex(); + + EntryIndex parent_index; + + if(!parent.isValid()) // root + { + parent_index.is_file = false; + parent_index.index = 0; + } + else if(!convertInternalIdToIndex(parent.internalId(),parent_index)) + return QModelIndex(); + + if(parent_index.is_file || parent_index.index >= mCollection.fileTree().numDirs()) + return QModelIndex(); + + const auto& parentData(mCollection.fileTree().directoryData(parent_index.index)); + + if((size_t)row < parentData.subdirs.size()) + { + EntryIndex e; + e.is_file = false; + e.index = parentData.subdirs[row]; + + quintptr ref; + convertIndexToInternalId(e,ref); + +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << "creating index for row " << row << " of parent " << parent << ". result is " << createIndex(row,column,ref) << std::endl; +#endif + return createIndex(row,column,ref); + } + + if((size_t)row < parentData.subdirs.size() + parentData.subfiles.size()) + { + EntryIndex e; + e.is_file = true; + e.index = parentData.subfiles[row - parentData.subdirs.size()]; + + quintptr ref; + convertIndexToInternalId(e,ref); +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << "creating index for row " << row << " of parent " << parent << ". result is " << createIndex(row,column,ref) << std::endl; +#endif + return createIndex(row,column,ref); + } + + return QModelIndex(); +} + +Qt::ItemFlags RsCollectionModel::flags ( const QModelIndex & index ) const +{ + if(index.isValid() && index.column() == COLLECTION_MODEL_FILENAME) + { + EntryIndex e; + + if(!convertInternalIdToIndex(index.internalId(),e)) + return QAbstractItemModel::flags(index) ; + + if(e.is_file) + return QAbstractItemModel::flags(index) | Qt::ItemIsUserCheckable; + else + return QAbstractItemModel::flags(index) | Qt::ItemIsAutoTristate | Qt::ItemIsUserCheckable; + } + + return QAbstractItemModel::flags(index) ; +} + +QModelIndex RsCollectionModel::parent(const QModelIndex & index) const +{ + if(!index.isValid()) + return QModelIndex(); + + EntryIndex i; + if(index.internalId()==0 || !convertInternalIdToIndex(index.internalId(),i)) + return QModelIndex(); + + EntryIndex p; + p.is_file = false; // all parents are directories + int row; + + if(i.is_file) + { + p.index = mFileInfos[i.index].parent_index; + row = mFileInfos[i.index].parent_row; + } + else + { + p.index = mDirInfos[i.index].parent_index; + row = mDirInfos[i.index].parent_row; + } + + quintptr ref; + convertIndexToInternalId(p,ref); + + return createIndex(row,0,ref); +} + +QVariant RsCollectionModel::data(const QModelIndex& index, int role) const +{ + EntryIndex i; + if(!convertInternalIdToIndex(index.internalId(),i)) + return QVariant(); + +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << "Asking data of " << i << std::endl; +#endif + switch(role) + { + case Qt::DisplayRole: return displayRole(i,index.column()); + case Qt::DecorationRole: return decorationRole(i,index.column()); + case Qt::CheckStateRole: return checkStateRole(i,index.column()); + case Qt::TextColorRole: return textColorRole(i,index.column()); + default: + return QVariant(); + } +} + +bool RsCollectionModel::setData(const QModelIndex& index,const QVariant& value,int role) +{ + if(!index.isValid()) + return false; + + EntryIndex e; + + if(role==Qt::CheckStateRole && convertInternalIdToIndex(index.internalId(), e)) + { +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << "Setting check state of item " << index << " to " << value.toBool() << std::endl; +#endif + RsFileTree::DirIndex dir_index ; + + if(e.is_file) + { + mFileInfos[e.index].is_checked = value.toBool(); + dir_index = mFileInfos[e.index].parent_index; + } + else + { + std::function recursSetCheckFlag = [&](RsFileTree::DirIndex index,bool s) -> void + { + mDirInfos[index].check_state = (s)?SELECTED:UNSELECTED; + auto& dir_data(mCollection.fileTree().directoryData(index)); + + mDirInfos[index].total_size = 0; + mDirInfos[index].total_count = 0; + + for(uint32_t i=0;i& files) +{ + mFilesBeingHashed.insert(files.begin(),files.end()); +} +void RsCollectionModel::fileHashingFinished(const RsFileHash& hash) +{ + mFilesBeingHashed.erase(hash); +} + +void RsCollectionModel::preMods() +{ + mUpdating = true; + emit layoutAboutToBeChanged(); +} +void RsCollectionModel::postMods() +{ + // update all the local structures + + mDirInfos.clear(); + mFileInfos.clear(); + + mDirInfos.resize(mCollection.fileTree().numDirs()); + mFileInfos.resize(mCollection.fileTree().numFiles()); + + mDirInfos[0].parent_index = 0; + +#ifdef DEBUG_COLLECTION_MODEL + std::cerr << "Updating from tree: " << std::endl; +#endif + recursUpdateLocalStructures(mCollection.fileTree().root(),0); + + mUpdating = false; + emit layoutChanged(); + emit sizesChanged(); + +// debugDump(); +} + +void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,int depth) +{ + uint64_t total_size = 0; + uint64_t total_count = 0; + bool all_checked = true; + bool all_unchecked = false; + + const auto& dd(mCollection.fileTree().directoryData(dir_index)); + + for(uint32_t i=0;i recursDump = [&](RsFileTree::DirIndex indx,int depth) { + const auto& dir_data(mCollection.fileTree().directoryData(indx)); + + for(int i=0;i recursDump2 = [&](QModelIndex indx,int depth) { + + for(int i=0;i + +#include "RsCollection.h" + +class RsCollectionModel: public QAbstractItemModel +{ + Q_OBJECT + + public: + enum Roles{ FileNameRole = Qt::UserRole+1, SortRole = Qt::UserRole+2, FilterRole = Qt::UserRole+3 }; + + RsCollectionModel(const RsCollection& col, QObject *parent = 0); + virtual ~RsCollectionModel() = default; + + /* Callback from Core */ + void preMods(); // always call this before updating the RsCollection! + void postMods(); // always call this after updating the RsCollection! + + /* Callback from GUI */ + + void update() ; + void filterItems(const std::list& keywords, uint32_t& found) ; + + // Overloaded from QAbstractItemModel + virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex() ) const override; + virtual QModelIndex parent ( const QModelIndex & index ) const override; + + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; + virtual bool hasChildren(const QModelIndex & parent = QModelIndex()) const override; + + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + virtual bool setData(const QModelIndex& index,const QVariant& value,int role) override; + virtual Qt::ItemFlags flags ( const QModelIndex & index ) const override; +#ifdef TODO + virtual QStringList mimeTypes () const override; + virtual QMimeData * mimeData ( const QModelIndexList & indexes ) const override; +#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) + virtual Qt::DropActions supportedDragActions() const override; +#endif +#endif + + struct EntryIndex { + bool is_file; // false=dir, true=file + uint64_t index; + }; + uint64_t totalSize() const { return mDirInfos[0].total_size; } + uint64_t totalSelected() const { return mDirInfos[0].total_count; } + + void notifyFilesBeingHashed(const std::list& files); + void fileHashingFinished(const RsFileHash& hash); + bool isChecked(EntryIndex); + + EntryIndex getIndex(const QModelIndex& i) const; + signals: + void sizesChanged(); // tells that the total size of the top level dir has changed (due to selection) + + private: + static bool convertIndexToInternalId(const EntryIndex& e,quintptr& ref); + static bool convertInternalIdToIndex(quintptr ref, EntryIndex& e); + + void recursUpdateLocalStructures(RsFileTree::DirIndex dir_index, int depth); + + QVariant displayRole(const EntryIndex&,int col) const ; + QVariant sortRole(const EntryIndex&,int col) const ; + QVariant decorationRole(const EntryIndex&,int col) const ; + QVariant checkStateRole(const EntryIndex& i,int col) const; + QVariant textColorRole(const EntryIndex& i,int col) const; + //QVariant filterRole(const DirDetails& details,int coln) const; + + void debugDump(); + + bool mUpdating ; + + const RsCollection& mCollection; + + enum DirCheckState: uint8_t { + UNSELECTED = 0x00, + PARTIALLY_SELECTED = 0x01, + SELECTED = 0x02, + }; + + struct ModelDirInfo { + ModelDirInfo() :parent_index(0),parent_row(0),check_state(SELECTED),total_size(0),total_count(0){} + + RsFileTree::DirIndex parent_index; // index of the parent + RsFileTree::DirIndex parent_row; // row of that child, in this parent + DirCheckState check_state; + uint64_t total_size; + uint64_t total_count; + }; + + struct ModelFileInfo { + ModelFileInfo() :parent_index(0),parent_row(0),is_checked(true){} + + RsFileTree::DirIndex parent_index; // index of the parent + RsFileTree::DirIndex parent_row; // row of that child, in this parent + bool is_checked; + }; + + std::vector mFileInfos; + std::vector mDirInfos; + + std::set mFilesBeingHashed; + + // std::set mFilteredPointers ; +}; diff --git a/retroshare-gui/src/gui/common/RsUrlHandler.cpp b/retroshare-gui/src/gui/common/RsUrlHandler.cpp index 6ac6310ac..94ec79753 100644 --- a/retroshare-gui/src/gui/common/RsUrlHandler.cpp +++ b/retroshare-gui/src/gui/common/RsUrlHandler.cpp @@ -21,19 +21,13 @@ #include #include #include -#include "RsCollection.h" +#include "RsCollectionDialog.h" #include "RsUrlHandler.h" bool RsUrlHandler::openUrl(const QUrl& url) { if(url.scheme() == QString("file") && url.toLocalFile().endsWith("."+RsCollection::ExtensionString)) - { - RsCollection collection ; - if(collection.load(url.toLocalFile())) - { - collection.downloadFiles() ; - return true; - } - } + return RsCollectionDialog::openExistingCollection(url.toLocalFile()); + return QDesktopServices::openUrl(url) ; } diff --git a/retroshare-gui/src/gui/common/SubscribeToolButton.cpp b/retroshare-gui/src/gui/common/SubscribeToolButton.cpp index 4015e641c..165b6caa1 100644 --- a/retroshare-gui/src/gui/common/SubscribeToolButton.cpp +++ b/retroshare-gui/src/gui/common/SubscribeToolButton.cpp @@ -72,7 +72,7 @@ void SubscribeToolButton::updateUi() delete mMenu ; mMenu = new QMenu; - mMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/images/cancel.png"), tr("Unsubscribe"), this, SLOT(unsubscribePrivate())); + mMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/icons/cancel.svg"), tr("Unsubscribe"), this, SLOT(unsubscribePrivate())); if (!mSubscribedActions.empty()) { mMenu->addSeparator(); diff --git a/retroshare-gui/src/gui/connect/ConfCertDialog.cpp b/retroshare-gui/src/gui/connect/ConfCertDialog.cpp index 03f7b4205..6a407cb49 100644 --- a/retroshare-gui/src/gui/connect/ConfCertDialog.cpp +++ b/retroshare-gui/src/gui/connect/ConfCertDialog.cpp @@ -264,7 +264,7 @@ void ConfCertDialog::loadInvitePage() ui._shouldAddSignatures_CB->setEnabled(detail.gpgSigners.size() > 1) ; std::string invite ; - RetroshareInviteFlags flags = RetroshareInviteFlags::DNS | RetroshareInviteFlags::CURRENT_IP | RetroshareInviteFlags::RADIX_FORMAT; + RetroshareInviteFlags flags = RsPeers::defaultCertificateFlags | RetroshareInviteFlags::RADIX_FORMAT; if(!detail.isHiddenNode && ui._includeIPHistory_CB->isChecked()) flags |= RetroshareInviteFlags::FULL_IP_HISTORY; @@ -283,7 +283,7 @@ void ConfCertDialog::loadInvitePage() ui.stabWidget->setTabText(PageCertificate, tr("Retroshare Certificate")); } - QString infotext = getCertificateDescription(detail,ui._shouldAddSignatures_CB->isChecked(),ui._shortFormat_CB->isChecked(), ui._includeIPHistory_CB->isChecked() ); + QString infotext = getCertificateDescription(detail,ui._shouldAddSignatures_CB->isChecked(),ui._shortFormat_CB->isChecked(), flags ); ui.userCertificateText->setToolTip(infotext) ; @@ -297,19 +297,15 @@ void ConfCertDialog::loadInvitePage() ui.userCertificateText->setText(QString::fromUtf8(invite.c_str())); } -QString ConfCertDialog::getCertificateDescription(const RsPeerDetails& detail,bool signatures_included,bool use_short_format,bool include_additional_locators) +QString ConfCertDialog::getCertificateDescription(const RsPeerDetails& detail, bool signatures_included, bool use_short_format,RetroshareInviteFlags invite_flags) { //infotext += tr("

Use this certificate to make new friends. Send it by email, or give it hand to hand.

") ; QString infotext; if(use_short_format) - { infotext += tr("

This Retroshare ID contains:") ; - } else - { infotext += tr("

This certificate contains:") ; - } infotext += "

    " ; @@ -334,25 +330,36 @@ QString ConfCertDialog::getCertificateDescription(const RsPeerDetails& detail,bo if(detail.isHiddenNode) infotext += tr("
  • onion address and port") +" (" + detail.hiddenNodeAddress.c_str() + ":" + QString::number(detail.hiddenNodePort)+ ")
  • "; - else if(!include_additional_locators) + else if(!!(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY)) + for(auto it(detail.ipAddressList.begin());it!=detail.ipAddressList.end();++it) + { + infotext += "
  • " ; + infotext += tr("IP address and port: ") + QString::fromStdString(*it) ; + infotext += "
  • " ; + } + else { - if(!detail.localAddr.empty()) infotext += tr("
  • IP address and port: ") + detail.localAddr.c_str() + ":" + QString::number(detail.localPort)+ "
  • "; - if(!detail.extAddr.empty()) infotext += tr("
  • IP address and port: ") + detail.extAddr.c_str() + ":" + QString::number(detail.extPort)+ "
  • "; + if(!!(invite_flags & RetroshareInviteFlags::CURRENT_LOCAL_IP) && !detail.localAddr.empty()) + infotext += tr("
  • IP address and port: ") + detail.localAddr.c_str() + ":" + QString::number(detail.localPort)+ "
  • "; + + if(!!(invite_flags & RetroshareInviteFlags::CURRENT_EXTERNAL_IP) && !detail.extAddr.empty()) + infotext += tr("
  • IP address and port: ") + detail.extAddr.c_str() + ":" + QString::number(detail.extPort)+ "
  • "; + } + + if(!!(invite_flags & RetroshareInviteFlags::DNS) && !detail.dyndns.empty()) + { + infotext += "
  • " ; + infotext += tr("DNS: : ") + QString::fromStdString(detail.dyndns); + infotext += "
  • " ; } - else for(auto it(detail.ipAddressList.begin());it!=detail.ipAddressList.end();++it) - { - infotext += "
  • " ; - infotext += tr("IP address and port: ") + QString::fromStdString(*it) ; - infotext += "
  • " ; - } infotext += QString("

    ") ; if(rsPeers->getOwnId() == detail.id) if(use_short_format) - infotext += tr("

    You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.

    ") ; - else - infotext += tr("

    You can use this certificate to make new friends. Send it by email, or give it hand to hand.

    ") ; + infotext += tr("

    You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.

    ") ; + else + infotext += tr("

    You can use this certificate to make new friends. Send it by email, or give it hand to hand.

    ") ; return infotext; } diff --git a/retroshare-gui/src/gui/connect/ConfCertDialog.h b/retroshare-gui/src/gui/connect/ConfCertDialog.h index a883dfd17..4760835da 100644 --- a/retroshare-gui/src/gui/connect/ConfCertDialog.h +++ b/retroshare-gui/src/gui/connect/ConfCertDialog.h @@ -59,7 +59,7 @@ public: /* window will destroy itself! */ } static void loadAll(); - static QString getCertificateDescription(const RsPeerDetails& det, bool signatures_included, bool use_short_format, bool extra_locators_included); + static QString getCertificateDescription(const RsPeerDetails& det, bool signatures_included, bool use_short_format,RetroshareInviteFlags invite_flags); signals: void configChanged(); diff --git a/retroshare-gui/src/gui/connect/ConfCertDialog.ui b/retroshare-gui/src/gui/connect/ConfCertDialog.ui index a2f94bc5b..93f9a86ba 100644 --- a/retroshare-gui/src/gui/connect/ConfCertDialog.ui +++ b/retroshare-gui/src/gui/connect/ConfCertDialog.ui @@ -6,8 +6,8 @@ 0 0 - 658 - 419 + 666 + 522 @@ -47,14 +47,14 @@ - + QFrame::StyledPanel QFrame::Raised - + diff --git a/retroshare-gui/src/gui/connect/ConnectFriendWizard.cpp b/retroshare-gui/src/gui/connect/ConnectFriendWizard.cpp index 90f532fd5..7ffdcd687 100755 --- a/retroshare-gui/src/gui/connect/ConnectFriendWizard.cpp +++ b/retroshare-gui/src/gui/connect/ConnectFriendWizard.cpp @@ -34,11 +34,13 @@ #endif #include "gui/common/FilesDefs.h" +#include "gui/RetroShareLink.h" #include "gui/settings/rsharesettings.h" #include "util/misc.h" #include "ConnectFriendWizard.h" #include "ui_ConnectFriendWizard.h" #include "gui/common/PeerDefs.h" +#include "gui/connect/ConfCertDialog.h" #include "gui/notifyqt.h" #include "gui/common/GroupDefs.h" #include "gui/msgs/MessageComposer.h" @@ -79,6 +81,7 @@ ConnectFriendWizard::ConnectFriendWizard(QWidget *parent) : { ui->setupUi(this); + error = 0; mTitleFontSize = 0; // Standard mTitleFontWeight = 0; // Standard @@ -107,8 +110,8 @@ ConnectFriendWizard::ConnectFriendWizard(QWidget *parent) : //ui->foffRadioButton->hide(); //ui->rsidRadioButton->hide(); - ui->cp_Label->hide(); - ui->requestinfolabel->hide(); + ui->info_Label_FrdReq->hide(); + ui->info_Label_Request->hide(); connect(ui->acceptNoSignGPGCheckBox,SIGNAL(toggled(bool)), ui->_options_GB,SLOT(setEnabled(bool))) ; connect(ui->addKeyToKeyring_CB,SIGNAL(toggled(bool)), ui->acceptNoSignGPGCheckBox,SLOT(setChecked(bool))) ; @@ -295,8 +298,8 @@ void ConnectFriendWizard::setCertificate(const QString &certificate, bool friend setStartId(Page_Conclusion); if (friendRequest){ - ui->cp_Label->show(); - ui->requestinfolabel->show(); + ui->info_Label_FrdReq->show(); + ui->info_Label_Request->show(); setTitleText(ui->ConclusionPage, tr("Friend request")); ui->ConclusionPage->setSubTitle(tr("Details about the request")); setButtonText(QWizard::FinishButton , tr("Accept")); @@ -320,8 +323,8 @@ void ConnectFriendWizard::setCertificate(const QString &certificate, bool friend setStartId(Page_Conclusion); if (friendRequest){ - ui->cp_Label->show(); - ui->requestinfolabel->show(); + ui->info_Label_FrdReq->show(); + ui->info_Label_Request->show(); setTitleText(ui->ConclusionPage, tr("Friend request")); ui->ConclusionPage->setSubTitle(tr("Details about the request")); setButtonText(QWizard::FinishButton , tr("Accept")); @@ -358,8 +361,8 @@ void ConnectFriendWizard::setGpgId(const RsPgpId &gpgId, const RsPeerId &sslId, setStartId(Page_Conclusion); if (friendRequest){ - ui->cp_Label->show(); - ui->requestinfolabel->show(); + ui->info_Label_FrdReq->show(); + ui->info_Label_Request->show(); setTitleText(ui->ConclusionPage, tr("Friend request")); ui->ConclusionPage->setSubTitle(tr("Details about the request")); setButtonText(QWizard::FinishButton , tr("Accept")); @@ -374,8 +377,8 @@ void ConnectFriendWizard::setGpgId(const RsPgpId &gpgId, const RsPeerId &sslId, //setStartId(friendRequest ? Page_FriendRequest : Page_Conclusion); setStartId(Page_Conclusion); if (friendRequest){ - ui->cp_Label->show(); - ui->requestinfolabel->show(); + ui->info_Label_FrdReq->show(); + ui->info_Label_Request->show(); setTitleText(ui->ConclusionPage,tr("Friend request")); ui->ConclusionPage->setSubTitle(tr("Details about the request")); setButtonText(QWizard::FinishButton , tr("Accept")); @@ -447,8 +450,9 @@ void ConnectFriendWizard::initializePage(int id) } sockaddr_storage addr ; - +#ifdef DEBUG_FRIENDWIZARD std::cerr << "Cert IP = " << peerDetails.extAddr << std::endl; +#endif if(sockaddr_storage_ipv4_aton(addr,peerDetails.extAddr.c_str()) && sockaddr_storage_isValidNet(addr)) { @@ -530,7 +534,7 @@ void ConnectFriendWizard::initializePage(int id) } } - ui->cp_Label->setText(tr("You have a friend request from") + " " + QString::fromUtf8(peerDetails.name.c_str())); + ui->info_Label_FrdReq->setText(tr("You have a friend request from") + " " + QString::fromUtf8(peerDetails.name.c_str())); ui->nameEdit->setText(QString::fromUtf8(peerDetails.name.c_str())); ui->trustEdit->setText(trustString); ui->profileIdEdit->setText(QString::fromStdString(peerDetails.gpg_id.toStdString())); @@ -572,6 +576,16 @@ void ConnectFriendWizard::initializePage(int id) ui->ipEdit->setText(s); ui->signersEdit->setPlainText(ts); + ui->knownIpLabel->setHidden(peerDetails.ipAddressList.empty()); + ui->knownIpEdit->setHidden(peerDetails.ipAddressList.empty()); + { + QString ipList; + for(auto& it : peerDetails.ipAddressList) + ipList.append(QString::fromStdString(it) + "\n"); + + ui->knownIpEdit->setPlainText(ipList); + } + fillGroups(this, ui->groupComboBox, groupId); if(peerDetails.isHiddenNode) @@ -587,15 +601,16 @@ void ConnectFriendWizard::initializePage(int id) } if(mIsShortInvite) { - ui->nameEdit->setText(tr("[Unknown]")); - ui->addKeyToKeyring_CB->setChecked(false); - ui->addKeyToKeyring_CB->setEnabled(false); + if(ui->nameEdit->text().isEmpty()) + ui->nameEdit->setText(QString::fromUtf8(peerDetails.name.c_str())); + ui->addKeyToKeyring_CB->setChecked(false); + ui->addKeyToKeyring_CB->setEnabled(false); ui->signersEdit->hide(); ui->signersLabel->hide(); - ui->signGPGCheckBox->setChecked(false); - ui->signGPGCheckBox->setEnabled(false); - ui->acceptNoSignGPGCheckBox->setChecked(true); - ui->acceptNoSignGPGCheckBox->setEnabled(false); + ui->signGPGCheckBox->setChecked(false); + ui->signGPGCheckBox->setEnabled(false); + ui->acceptNoSignGPGCheckBox->setChecked(true); + ui->acceptNoSignGPGCheckBox->setEnabled(false); } ui->ipEdit->setTextInteractionFlags(Qt::TextSelectableByMouse); @@ -856,30 +871,43 @@ void ConnectFriendWizard::cleanFriendCert() { bool certValid = false; QString errorMsg ; - std::string cert = ui->friendCertEdit->toPlainText().toUtf8().constData(); + QString certDetail; + + std::string cert ; + RetroShareLink rslink(ui->friendCertEdit->toPlainText()); + + if(rslink.valid() && rslink.type() == RetroShareLink::TYPE_CERTIFICATE) + cert = rslink.radix().toStdString(); + else + cert = ui->friendCertEdit->toPlainText().toUtf8().constData(); + +#ifdef DEBUG_FRIENDWIZARD + std::cerr << "Friend cert:\"" << cert << "\"" << std::endl; +#endif if (cert.empty()) { - ui->friendCertCleanLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/delete.png")); ui->friendCertCleanLabel->setToolTip(""); - ui->friendCertCleanLabel->setStyleSheet(""); errorMsg = tr(""); } else { std::string cleanCert; uint32_t error_code; + RsPeerDetails details; - if (rsPeers->cleanCertificate(cert, cleanCert, mIsShortInvite, error_code)) - { + if (rsPeers->cleanCertificate(cert, cleanCert, mIsShortInvite, error_code, details)) + { certValid = true; if (cert != cleanCert) - { + { QTextCursor textCursor = ui->friendCertEdit->textCursor(); whileBlocking(ui->friendCertEdit)->setPlainText(QString::fromUtf8(cleanCert.c_str())); whileBlocking(ui->friendCertEdit)->setTextCursor(textCursor); - ui->friendCertCleanLabel->setStyleSheet(""); + // use dummy flags so that the content of the description is driven by what's in the "details" variable. + RetroshareInviteFlags dummy_flags = RetroshareInviteFlags::ALL; + certDetail = ConfCertDialog::getCertificateDescription(details,false,mIsShortInvite,dummy_flags); } if (mIsShortInvite) @@ -887,7 +915,7 @@ void ConnectFriendWizard::cleanFriendCert() else errorMsg = tr("Valid certificate") ; - ui->friendCertCleanLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/accepted16.png")); + ui->friendCertCleanLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/accepted16.png")); } else { if (error_code > 0) { switch (error_code) { @@ -903,16 +931,17 @@ void ConnectFriendWizard::cleanFriendCert() default: errorMsg = tr("Not a valid Retroshare certificate!") ; - ui->friendCertCleanLabel->setStyleSheet("QLabel#friendCertCleanLabel {border: 1px solid #DCDC41; border-radius: 6px; background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2);}"); } } - ui->friendCertCleanLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/delete.png")); } } - ui->friendCertCleanLabel->setPixmap(certValid ? FilesDefs::getPixmapFromQtResourcePath(":/images/accepted16.png") : FilesDefs::getPixmapFromQtResourcePath(":/images/delete.png")); - ui->friendCertCleanLabel->setToolTip(errorMsg); + ui->friendCertCleanLabel->setPixmap(certValid ? FilesDefs::getPixmapFromQtResourcePath(":/images/accepted16.png") : FilesDefs::getPixmapFromQtResourcePath(":/images/delete.png")); + ui->friendCertCleanLabel->setToolTip("

    " + errorMsg + (certValid ? "\n" + certDetail : "") + "

    "); ui->friendCertCleanLabel->setText(errorMsg); + ui->friendCertCleanLabel->setProperty("WrongValue", !certValid && !errorMsg.isEmpty()); + ui->friendCertCleanLabel->style()->unpolish(ui->friendCertCleanLabel); + ui->friendCertCleanLabel->style()->polish( ui->friendCertCleanLabel); ui->TextPage->setComplete(certValid); } @@ -920,7 +949,7 @@ void ConnectFriendWizard::cleanFriendCert() void ConnectFriendWizard::pasteCert() { QClipboard *clipboard = QApplication::clipboard(); - ui->friendCertEdit->setPlainText(clipboard->text()); + ui->friendCertEdit->setPlainText(clipboard->text()); } void ConnectFriendWizard::openCert() diff --git a/retroshare-gui/src/gui/connect/ConnectFriendWizard.ui b/retroshare-gui/src/gui/connect/ConnectFriendWizard.ui index 5e9cd7a34..65b736762 100644 --- a/retroshare-gui/src/gui/connect/ConnectFriendWizard.ui +++ b/retroshare-gui/src/gui/connect/ConnectFriendWizard.ui @@ -360,7 +360,7 @@ - + 0 @@ -370,6 +370,15 @@ + + + + 0 + 0 + 0 + + + @@ -390,6 +399,15 @@ + + + + 0 + 0 + 0 + + + @@ -410,6 +428,15 @@ + + + + 154 + 154 + 154 + + + @@ -431,6 +458,11 @@ + + + 10 + + true @@ -510,6 +542,14 @@ 0 + + + 11 + 75 + true + true + + Name: @@ -550,7 +590,7 @@
    - Email + ProfilId @@ -589,7 +629,7 @@ - Signers + Signers: @@ -635,6 +675,16 @@ + + + + Known IP: + + + + + + @@ -687,7 +737,7 @@ - + @@ -701,7 +751,7 @@ - + @@ -767,10 +817,19 @@ - + + + + + 0 + 0 + 0 + + + @@ -791,6 +850,15 @@ + + + + 0 + 0 + 0 + + + @@ -811,6 +879,15 @@ + + + + 154 + 154 + 154 + + + @@ -832,6 +909,11 @@ + + + 12 + + true @@ -863,17 +945,17 @@ - - StyledLabel - QLabel -
    gui/common/StyledLabel.h
    -
    ConnectFriendPage QWizardPage
    gui/connect/ConnectFriendWizard.h
    1
    + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    RSPlainTextEdit QPlainTextEdit @@ -881,8 +963,8 @@
    - + diff --git a/retroshare-gui/src/gui/connect/ConnectProgressDialog.cpp b/retroshare-gui/src/gui/connect/ConnectProgressDialog.cpp index ce1c843c8..e405430e5 100755 --- a/retroshare-gui/src/gui/connect/ConnectProgressDialog.cpp +++ b/retroshare-gui/src/gui/connect/ConnectProgressDialog.cpp @@ -235,38 +235,42 @@ void ConnectProgressDialog::initDialog() void ConnectProgressDialog::updateStatus() { - if (time(NULL) > mInitTS + CONNECT_TIMEOUT_PERIOD) - { - sayConnectTimeout(); - mState = CONNECT_STATE_FAILED; - } + if (time(NULL) > mInitTS + CONNECT_TIMEOUT_PERIOD) + { + sayConnectTimeout(); + mState = CONNECT_STATE_FAILED; + } - switch(mState) - { - case CONNECT_STATE_PROGRESS: + switch(mState) + { + case CONNECT_STATE_PROGRESS: - updateNetworkStatus(); - updateContactStatus(); + updateNetworkStatus(); + updateContactStatus(); + + if(!mIsPeerHiddenNode && !mAmIHiddenNode) + { #ifdef RS_USE_BITDHT - updateDhtStatus(); + updateDhtStatus(); #endif - updateLookupStatus(); - updateUdpStatus(); + updateLookupStatus(); + updateUdpStatus(); + } - return; - break; + return; + break; - default: - case CONNECT_STATE_CLOSED: - case CONNECT_STATE_FAILED: - case CONNECT_STATE_DENIED: - case CONNECT_STATE_CONNECTED: - break; - } + default: + case CONNECT_STATE_CLOSED: + case CONNECT_STATE_FAILED: + case CONNECT_STATE_DENIED: + case CONNECT_STATE_CONNECTED: + break; + } - /* shutdown actions */ - ui->progressFrame->setEnabled(false); - mTimer->stop(); + /* shutdown actions */ + ui->progressFrame->setEnabled(false); + mTimer->stop(); } @@ -282,42 +286,70 @@ void ConnectProgressDialog::stopAndClose() void ConnectProgressDialog::updateNetworkStatus() { - RsNetState netState = rsConfig->getNetState(); + QLabel *label = ui->NetResult; - QLabel *label = ui->NetResult; - switch(netState) - { - case RsNetState::BAD_UNKNOWN: - label->setText(tr("Unknown State")); - break; - case RsNetState::BAD_OFFLINE: - label->setText(tr("Offline")); - break; - case RsNetState::BAD_NATSYM: - label->setText(tr("Behind Symmetric NAT")); - break; - case RsNetState::BAD_NODHT_NAT: - label->setText(tr("Behind NAT & No DHT")); - break; - case RsNetState::WARNING_RESTART: - label->setText(tr("NET Restart")); - break; - case RsNetState::WARNING_NATTED: - label->setText(tr("Behind NAT")); - break; - case RsNetState::WARNING_NODHT: - label->setText(tr("No DHT")); - break; - case RsNetState::GOOD: - label->setText(tr("NET STATE GOOD!")); - break; - case RsNetState::ADV_FORWARD: - label->setText(tr("UNVERIFIABLE FORWARD!")); - break; - case RsNetState::ADV_DARK_FORWARD: - label->setText(tr("UNVERIFIABLE FORWARD & NO DHT")); - break; - } + if(mAmIHiddenNode || mIsPeerHiddenNode) + switch(rsConfig->getNetState()) + { + case RsNetState::BAD_UNKNOWN: + label->setText(tr("Unknown State")); + break; + case RsNetState::BAD_OFFLINE: + label->setText(tr("Offline")); + break; + case RsNetState::BAD_NATSYM: + label->setText(tr("Behind Symmetric NAT")); + break; + case RsNetState::WARNING_RESTART: + label->setText(tr("NET Restart")); + break; + case RsNetState::BAD_NODHT_NAT: + case RsNetState::WARNING_NATTED: + label->setText(tr("Behind NAT")); + break; + case RsNetState::WARNING_NODHT: + case RsNetState::GOOD: + label->setText(tr("NET STATE GOOD!")); + break; + case RsNetState::ADV_DARK_FORWARD: + case RsNetState::ADV_FORWARD: + label->setText(tr("UNVERIFIABLE FORWARD!")); + break; + } + else + switch(rsConfig->getNetState()) + { + case RsNetState::BAD_UNKNOWN: + label->setText(tr("Unknown State")); + break; + case RsNetState::BAD_OFFLINE: + label->setText(tr("Offline")); + break; + case RsNetState::BAD_NATSYM: + label->setText(tr("Behind Symmetric NAT")); + break; + case RsNetState::BAD_NODHT_NAT: + label->setText(tr("Behind NAT & No DHT")); + break; + case RsNetState::WARNING_RESTART: + label->setText(tr("NET Restart")); + break; + case RsNetState::WARNING_NATTED: + label->setText(tr("Behind NAT")); + break; + case RsNetState::WARNING_NODHT: + label->setText(tr("No DHT")); + break; + case RsNetState::GOOD: + label->setText(tr("NET STATE GOOD!")); + break; + case RsNetState::ADV_FORWARD: + label->setText(tr("UNVERIFIABLE FORWARD!")); + break; + case RsNetState::ADV_DARK_FORWARD: + label->setText(tr("UNVERIFIABLE FORWARD & NO DHT")); + break; + } } void ConnectProgressDialog::updateContactStatus() @@ -454,13 +486,9 @@ void ConnectProgressDialog::updateLookupStatus() mState = CONNECT_STATE_FAILED; if (mLookupStatus == CONNECT_LOOKUP_NODHTCONFIG) - { sayPeerNoDhtConfig(); - } else - { sayPeerOffline(); - } } case CONNECT_LOOKUP_FAIL: diff --git a/retroshare-gui/src/gui/connect/PGPKeyDialog.cpp b/retroshare-gui/src/gui/connect/PGPKeyDialog.cpp index b167ca1ed..36b6057b4 100644 --- a/retroshare-gui/src/gui/connect/PGPKeyDialog.cpp +++ b/retroshare-gui/src/gui/connect/PGPKeyDialog.cpp @@ -45,6 +45,8 @@ #include "util/DateTime.h" #include "util/misc.h" +#define FRIEND_OPTIONS_TAB_INDEX 2 + QMap PGPKeyDialog::instances_pgp; PGPKeyDialog *PGPKeyDialog::instance(const RsPgpId& pgp_id) @@ -178,6 +180,7 @@ void PGPKeyDialog::load() { ui.make_friend_button->hide(); ui.signKeyButton->hide(); + ui.label_signKey->hide(); ui.denyFriendButton->hide(); ui.label_trustlevel->hide(); @@ -199,11 +202,13 @@ void PGPKeyDialog::load() { ui.make_friend_button->hide(); ui.denyFriendButton->show(); + ui.stabWidget->setTabEnabled(FRIEND_OPTIONS_TAB_INDEX,true); } else { ui.make_friend_button->show(); ui.denyFriendButton->hide(); + ui.stabWidget->setTabEnabled(FRIEND_OPTIONS_TAB_INDEX,false); } //web of trust diff --git a/retroshare-gui/src/gui/connect/PGPKeyDialog.ui b/retroshare-gui/src/gui/connect/PGPKeyDialog.ui index 04b891fdf..eca49e965 100644 --- a/retroshare-gui/src/gui/connect/PGPKeyDialog.ui +++ b/retroshare-gui/src/gui/connect/PGPKeyDialog.ui @@ -30,14 +30,14 @@ 0 - + QFrame::StyledPanel QFrame::Raised - + 3 @@ -56,11 +56,11 @@ 0 - + Profile info - + 0 @@ -68,9 +68,9 @@ 6 - + - + @@ -103,7 +103,7 @@ - + <html><head/><body><p>The trust level is an optional and local parameter that you can set in order to remember your option about a given PGP key. It is not used whatsoever to authorize connections. </p></body></html> @@ -112,8 +112,8 @@ Unset - - :/images/security-low-off-48.png:/images/security-low-off-48.png + + :/icons/security_low_off_128.png:/icons/security_low_off_128.png @@ -121,8 +121,8 @@ Unknown - - :/images/security-low-off-48.png:/images/security-low-off-48.png + + :/icons/security_low_off_128.png:/icons/security_low_off_128.png @@ -130,8 +130,8 @@ No trust - - :/images/security-low-48.png:/images/security-low-48.png + + :/icons/security_low_128.png:/icons/security_low_128.png @@ -139,8 +139,8 @@ Marginal - - :/images/security-medium-48.png:/images/security-medium-48.png + + :/icons/security_medium_128.png:/icons/security_medium_128.png @@ -148,8 +148,8 @@ Full - - :/images/security-high-48.png:/images/security-high-48.png + + :/icons/security_high_128.png:/icons/security_high_128.png @@ -157,8 +157,8 @@ Ultimate - - :/images/security-high-48.png:/images/security-high-48.png + + :/icons/security_high_128.png:/icons/security_high_128.png @@ -350,11 +350,11 @@ p, li { white-space: pre-wrap; } - + PGP key - + @@ -391,11 +391,11 @@ p, li { white-space: pre-wrap; } - + - Options + Friend options - + @@ -518,20 +518,26 @@ p, li { white-space: pre-wrap; } - - RSTextBrowser - QTextBrowser -
    gui/common/RSTextBrowser.h
    -
    HeaderFrame QFrame
    gui/common/HeaderFrame.h
    1
    + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    + + RSTextBrowser + QTextBrowser +
    gui/common/RSTextBrowser.h
    +
    + diff --git a/retroshare-gui/src/gui/elastic/arrow.cpp b/retroshare-gui/src/gui/elastic/arrow.cpp index 6a95f2041..5698a3da6 100644 --- a/retroshare-gui/src/gui/elastic/arrow.cpp +++ b/retroshare-gui/src/gui/elastic/arrow.cpp @@ -33,7 +33,7 @@ static double TwoPi = 2.0 * Pi; Arrow::Arrow(Node *sourceNode, Node *destNode) : arrowSize(10) { - setAcceptedMouseButtons(0); + setAcceptedMouseButtons(Qt::MouseButton::NoButton); source = sourceNode; dest = destNode; #ifdef SUSP diff --git a/retroshare-gui/src/gui/feeds/AttachFileItem.ui b/retroshare-gui/src/gui/feeds/AttachFileItem.ui index d0421e864..b755fba22 100644 --- a/retroshare-gui/src/gui/feeds/AttachFileItem.ui +++ b/retroshare-gui/src/gui/feeds/AttachFileItem.ui @@ -16,15 +16,24 @@ 35 - + + + 0 + + + 0 + + + 0 + + + 0 + 0 - - 0 - - + 0 @@ -37,7 +46,7 @@ QFrame::Sunken - + 2 diff --git a/retroshare-gui/src/gui/feeds/BoardsCommentsItem.cpp b/retroshare-gui/src/gui/feeds/BoardsCommentsItem.cpp index 670567f03..57adbb39d 100644 --- a/retroshare-gui/src/gui/feeds/BoardsCommentsItem.cpp +++ b/retroshare-gui/src/gui/feeds/BoardsCommentsItem.cpp @@ -28,6 +28,7 @@ #include "gui/feeds/FeedHolder.h" #include "gui/RetroShareLink.h" #include "gui/gxs/GxsIdDetails.h" +#include "util/qtthreadsutils.h" #include "util/DateTime.h" #include "util/misc.h" #include "util/stringutil.h" @@ -185,13 +186,13 @@ void BaseBoardsCommentsItem::loadMessage() if (posts.size() == 1) { std::cerr << (void*)this << ": Obtained post, with msgId = " << posts[0].mMeta.mMsgId << std::endl; - const RsPostedPost& post(posts[0]); + RsPostedPost post(posts[0]); // no reference to temporary because it's passed to a thread! RsQThreadUtils::postToObject( [post,this]() { setPost(post,true); mIsLoadingMessage = false;}, this ); } else if(comments.size() == 1) { - const RsGxsComment& cmt = comments[0]; + RsGxsComment cmt(comments[0]); std::cerr << (void*)this << ": Obtained comment, setting messageId to threadID = " << cmt.mMeta.mThreadId << std::endl; RsQThreadUtils::postToObject( [cmt,this]() @@ -286,12 +287,14 @@ void BaseBoardsCommentsItem::readToggled(bool checked) return; } - RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); + setReadStatus(false, checked); // Can't call this inside an async call since the widget may be destroyed afterwards! + // So we do it right away. - uint32_t token; - rsPosted->setMessageReadStatus(token, msgPair, !checked); - - setReadStatus(false, checked); + RsThread::async( [this,checked]() { + RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); + + rsPosted->setCommentReadStatus(msgPair, !checked); + }); } void BaseBoardsCommentsItem::readAndClearItem() @@ -536,9 +539,9 @@ void BoardsCommentsItem::setReadStatus(bool isNew, bool isUnread) ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-read.png")); } - ui->mainFrame->setProperty("new", isNew); - ui->mainFrame->style()->unpolish(ui->mainFrame); - ui->mainFrame->style()->polish( ui->mainFrame); + ui->feedFrame->setProperty("new", isNew); + ui->feedFrame->style()->unpolish(ui->feedFrame); + ui->feedFrame->style()->polish( ui->feedFrame); } void BoardsCommentsItem::toggle() diff --git a/retroshare-gui/src/gui/feeds/BoardsCommentsItem.ui b/retroshare-gui/src/gui/feeds/BoardsCommentsItem.ui index b3e529091..53e233e0b 100644 --- a/retroshare-gui/src/gui/feeds/BoardsCommentsItem.ui +++ b/retroshare-gui/src/gui/feeds/BoardsCommentsItem.ui @@ -10,7 +10,14 @@ 157 - + + + 12 + 75 + true + + + 1 @@ -24,7 +31,7 @@ 1 - + 0 @@ -40,7 +47,7 @@ QFrame::Sunken - + 9 @@ -53,7 +60,7 @@ 8 - + @@ -68,6 +75,7 @@ + 12 75 true @@ -131,6 +139,7 @@ + 12 75 true @@ -147,6 +156,7 @@ + 12 75 true @@ -160,7 +170,7 @@ - + Qt::Horizontal @@ -242,7 +252,7 @@ - + @@ -275,7 +285,7 @@ - + Qt::Vertical @@ -291,7 +301,7 @@ - + 0 @@ -312,7 +322,7 @@ QFrame::Sunken - + 5 @@ -367,7 +377,7 @@ - + 3 @@ -384,7 +394,7 @@ 3 - + Qt::Horizontal @@ -403,6 +413,7 @@ + 12 75 true @@ -425,7 +436,9 @@ + 12 75 + true true @@ -449,6 +462,8 @@ MS Sans Serif 10 + 75 + true @@ -483,8 +498,6 @@
    gui/gxs/GxsIdLabel.h
    - - - + diff --git a/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.cpp b/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.cpp index 88b724598..5b0e0b264 100644 --- a/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.cpp +++ b/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.cpp @@ -49,46 +49,41 @@ * #define DEBUG_ITEM 1 ****/ -ChannelsCommentsItem::ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGroupMetaData& group_meta, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate,const std::set& older_versions) : - GxsFeedItem(feedHolder, feedId, group_meta.mGroupId, messageId, isHome, rsGxsChannels, autoUpdate), - mGroupMeta(group_meta) +// ChannelsCommentsItem::ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGroupMetaData& group_meta, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate,const std::set& older_versions) : +// GxsFeedItem(feedHolder, feedId, group_meta.mGroupId, messageId, isHome, rsGxsChannels, autoUpdate), +// mGroupMeta(group_meta) +// { +// mLoadingGroup = false; +// mLoadingMessage = false; +// mLoadingComment = false; +// +// mPost.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded +// mPost.mMeta.mGroupId = mGroupMeta.mGroupId; +// +// QVector v; +// //bool self = false; +// +// for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) +// v.push_back(*it) ; +// +// if(older_versions.find(messageId) == older_versions.end()) +// v.push_back(messageId); +// +// setMessageVersions(v) ; +// setup(); +// +// // no call to loadGroup() here because we have it already. +// } + +ChannelsCommentsItem::ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &commentId, const RsGxsMessageId &threadId, bool isHome, bool autoUpdate) : + GxsFeedItem(feedHolder, feedId, groupId, commentId, isHome, rsGxsChannels, autoUpdate), // this one should be in GxsFeedItem + mThreadId(threadId) { - mPost.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded - mPost.mMeta.mGroupId = mGroupMeta.mGroupId; + mLoading= false; QVector v; - //bool self = false; - for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) - v.push_back(*it) ; - - if(older_versions.find(messageId) == older_versions.end()) - v.push_back(messageId); - - setMessageVersions(v) ; setup(); - - // no call to loadGroup() here because we have it already. -} - -ChannelsCommentsItem::ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate,const std::set& older_versions) : - GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsGxsChannels, autoUpdate) // this one should be in GxsFeedItem -{ - mPost.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded - - QVector v; - //bool self = false; - - for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) - v.push_back(*it) ; - - if(older_versions.find(messageId) == older_versions.end()) - v.push_back(messageId); - - setMessageVersions(v) ; - setup(); - - loadGroup(); } void ChannelsCommentsItem::paintEvent(QPaintEvent *e) @@ -99,21 +94,22 @@ void ChannelsCommentsItem::paintEvent(QPaintEvent *e) if(!mLoaded) { mLoaded = true ; - - std::set older_versions; // not so nice. We need to use std::set everywhere - for(auto& m:messageVersions()) - older_versions.insert(m); - - fill(); - requestMessage(); - requestComment(); - } + load(); + } GxsFeedItem::paintEvent(e) ; } ChannelsCommentsItem::~ChannelsCommentsItem() { + auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(300); + + while( mLoading && std::chrono::steady_clock::now() < timeout ) + { + RsDbg() << __PRETTY_FUNCTION__ << " is Waiting for data to load " << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + delete(ui); } @@ -175,28 +171,26 @@ void ChannelsCommentsItem::setup() // hide expand button, replies is not implemented yet ui->expandButton->hide(); - ui->mainFrame->setProperty("new", false); - ui->mainFrame->style()->unpolish(ui->mainFrame); - ui->mainFrame->style()->polish( ui->mainFrame); + ui->feedFrame->setProperty("new", false); + ui->feedFrame->style()->unpolish(ui->feedFrame); + ui->feedFrame->style()->polish( ui->feedFrame); ui->expandFrame->hide(); } -bool ChannelsCommentsItem::setPost(const RsGxsChannelPost &post, bool doFill) +bool ChannelsCommentsItem::setPost(const RsGxsChannelPost& post, bool doFill) { - if (groupId() != post.mMeta.mGroupId || messageId() != post.mMeta.mMsgId) { - std::cerr << "ChannelsCommentsItem::setPost() - Wrong id, cannot set post"; - std::cerr << std::endl; - return false; - } - mPost = post; - if (doFill) { + if (doFill) fill(); - } - return true; + return true; +} +bool ChannelsCommentsItem::setMissingPost() +{ + fill(true); + return true; } QString ChannelsCommentsItem::getTitleLabel() @@ -230,167 +224,148 @@ void ChannelsCommentsItem::loadComments() void ChannelsCommentsItem::loadGroup() { -#ifdef DEBUG_ITEM - std::cerr << "GxsChannelGroupItem::loadGroup()"; - std::cerr << std::endl; -#endif - - RsThread::async([this]() - { - // 1 - get group data - - std::vector groups; - const std::list groupIds = { groupId() }; - - if(!rsGxsChannels->getChannelsInfo(groupIds,groups)) // would be better to call channel Summaries for a single group - { - RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; - return; - } - - if (groups.size() != 1) - { - std::cerr << "GxsGxsChannelGroupItem::loadGroup() Wrong number of Items"; - std::cerr << std::endl; - return; - } - RsGxsChannelGroup group(groups[0]); - - RsQThreadUtils::postToObject( [group,this]() - { - /* Here it goes any code you want to be executed on the Qt Gui - * thread, for example to update the data model with new information - * after a blocking call to RetroShare API complete */ - - mGroupMeta = group.mMeta; - - }, this ); - }); +//#ifdef DEBUG_ITEM +// std::cerr << "GxsChannelGroupItem::loadGroup()"; +// std::cerr << std::endl; +//#endif +// if(mLoading) +// return; +// +// mLoading= true; +// +// std::cerr << "Loading group" << std::endl; +// RsThread::async([this]() +// { +// // 1 - get group data +// +// std::vector groups; +// const std::list groupIds = { groupId() }; +// +// if(!rsGxsChannels->getChannelsInfo(groupIds,groups)) // would be better to call channel Summaries for a single group +// { +// RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; +// return; +// } +// +// if (groups.size() != 1) +// { +// std::cerr << "GxsGxsChannelGroupItem::loadGroup() Wrong number of Items"; +// std::cerr << std::endl; +// return; +// } +// RsGxsChannelGroup group(groups[0]); +// +// RsQThreadUtils::postToObject( [group,this]() +// { +// /* Here it goes any code you want to be executed on the Qt Gui +// * thread, for example to update the data model with new information +// * after a blocking call to RetroShare API complete */ +// +// mGroupMeta = group.mMeta; +// mLoading= false; +// +// std::cerr << "End loading group" << std::endl; +// }, this ); +// }); } -void ChannelsCommentsItem::loadMessage() +void ChannelsCommentsItem::load() { + // This function loads everything that's needed: + // - the comment text + // - the comment parent message + #ifdef DEBUG_ITEM std::cerr << "ChannelsCommentsItem::loadMessage()"; std::cerr << std::endl; #endif - RsThread::async([this]() + if(mLoading) + return; + + mLoading= true; + + RsThread::async([this]() { - // 1 - get group data + // 1 - get group meta data + + std::vector groups; + const std::list groupIds = { groupId() }; + + if(!rsGxsChannels->getChannelsInfo(groupIds,groups)) // would be better to call channel Summaries for a single group + { + RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; + return; + } + + if (groups.size() != 1) + { + std::cerr << "GxsGxsChannelGroupItem::loadGroup() Wrong number of Items" << std::endl; + return; + } + RsGxsChannelGroup group(groups[0]); + + // 2 - get message and comment data std::vector posts; std::vector comments; std::vector votes; - if(! rsGxsChannels->getChannelContent( groupId(), std::set( { messageId() } ),posts,comments,votes)) + if(! rsGxsChannels->getChannelContent( groupId(), std::set( { messageId(),mThreadId } ),posts,comments,votes)) { RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; return; } - if (posts.size() == 1) - { -#ifdef DEBUG_ITEM - std::cerr << (void*)this << ": Obtained post, with msgId = " << posts[0].mMeta.mMsgId << std::endl; -#endif - const RsGxsChannelPost& post(posts[0]); + // now that everything is in place, update the UI - RsQThreadUtils::postToObject( [post,this]() { setPost(post); }, this ); - } - else if(comments.size() == 1) - { - const RsGxsComment& cmt = comments[0]; -#ifdef DEBUG_ITEM - std::cerr << (void*)this << ": Obtained comment, setting messageId to threadID = " << cmt.mMeta.mThreadId << std::endl; -#endif + RsQThreadUtils::postToObject( [group,posts,comments,this]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete */ - RsQThreadUtils::postToObject( [cmt,this]() - { - uint32_t autorized_lines = (int)floor((ui->avatarLabel->height() - ui->buttonHLayout->sizeHint().height())/QFontMetricsF(ui->subjectLabel->font()).height()); + mGroupMeta = group.mMeta; - ui->commLabel->setText(RsHtml().formatText(NULL, RsStringUtil::CopyLines(QString::fromUtf8(cmt.mComment.c_str()), autorized_lines), RSHTML_FORMATTEXT_EMBED_LINKS)); + if(comments.size()==1) + { + RsGxsComment cmt(comments[0]); - ui->nameLabel->setId(cmt.mMeta.mAuthorId); - ui->datetimeLabel->setText(DateTime::formatLongDateTime(cmt.mMeta.mPublishTs)); + uint32_t autorized_lines = (int)floor( (ui->avatarLabel->height() - ui->button_HL->sizeHint().height()) + / QFontMetricsF(ui->subjectLabel->font()).height()); - RsIdentityDetails idDetails ; - rsIdentity->getIdDetails(cmt.mMeta.mAuthorId,idDetails); - QPixmap pixmap ; + ui->commLabel->setText(RsHtml().formatText(NULL, RsStringUtil::CopyLines(QString::fromUtf8(cmt.mComment.c_str()), autorized_lines), RSHTML_FORMATTEXT_EMBED_LINKS)); + ui->nameLabel->setId(cmt.mMeta.mAuthorId); + ui->datetimeLabel->setText(DateTime::formatLongDateTime(cmt.mMeta.mPublishTs)); - if(idDetails.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idDetails.mAvatar.mData, idDetails.mAvatar.mSize, pixmap,GxsIdDetails::SMALL)) - pixmap = GxsIdDetails::makeDefaultIcon(cmt.mMeta.mAuthorId,GxsIdDetails::LARGE); - ui->avatarLabel->setPixmap(pixmap); + RsIdentityDetails idDetails ; + rsIdentity->getIdDetails(cmt.mMeta.mAuthorId,idDetails); + QPixmap pixmap ; - //Change this item to be uploaded with thread element. - setMessageId(cmt.mMeta.mThreadId); - requestMessage(); + if(idDetails.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idDetails.mAvatar.mData, idDetails.mAvatar.mSize, pixmap,GxsIdDetails::SMALL)) + pixmap = GxsIdDetails::makeDefaultIcon(cmt.mMeta.mAuthorId,GxsIdDetails::LARGE); + ui->avatarLabel->setPixmap(pixmap); - }, this ); + //Change this item to be uploaded with thread element. This is really bad practice. + } + else + { + mLoading=false; + removeItem(); + } - } - else - { -#ifdef DEBUG_ITEM - std::cerr << "ChannelsCommentsItem::loadMessage() Wrong number of Items. Remove It."; - std::cerr << std::endl; -#endif + if (posts.size() == 1) + setPost(posts[0]); + else + setMissingPost(); - RsQThreadUtils::postToObject( [this]() { removeItem(); }, this ); - } - }); - - emit sizeChanged(this); + emit sizeChanged(this); + mLoading=false; + + }, this ); + }); } -void ChannelsCommentsItem::loadComment() +void ChannelsCommentsItem::fill(bool missing_post) { -#ifdef DEBUG_ITEM - std::cerr << "ChannelsCommentsItem::loadComment()"; - std::cerr << std::endl; -#endif - - RsThread::async([this]() - { - // 1 - get group data - - std::set msgIds; - - for(auto MsgId: messageVersions()) - msgIds.insert(MsgId); - - std::vector posts; - std::vector comments; - - if(! rsGxsChannels->getChannelComments( groupId(),msgIds,comments)) - { - RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; - return; - } - - int comNb = comments.size(); - - RsQThreadUtils::postToObject( [comNb,this]() - { - QString sComButText = tr("Comment"); - if (comNb == 1) - sComButText = sComButText.append("(1)"); - else if(comNb > 1) - sComButText = tr("Comments ").append("(%1)").arg(comNb); - - //ui->commentButton->setText(sComButText); - - }, this ); - }); -} - -void ChannelsCommentsItem::fill() -{ - /* fill in */ - -// if (isLoading()) { - // /* Wait for all requests */ - //return; -// } - #ifdef DEBUG_ITEM std::cerr << "ChannelsCommentsItem::fill()"; std::cerr << std::endl; @@ -398,9 +373,6 @@ void ChannelsCommentsItem::fill() mInFill = true; - //QString title; - //float f = QFontMetricsF(font()).height()/14.0 ; - if (!mIsHome) { if (mCloseOnRead && !IS_MSG_NEW(mPost.mMeta.mMsgStatus)) { @@ -411,19 +383,14 @@ void ChannelsCommentsItem::fill() //title += link.toHtml(); //ui->titleLabel->setText(title); - RetroShareLink msgLink = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_CHANNEL, mPost.mMeta.mGroupId, mPost.mMeta.mMsgId, messageName()); - ui->subjectLabel->setText(msgLink.toHtml()); + RetroShareLink msgLink = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_CHANNEL, mPost.mMeta.mGroupId, mPost.mMeta.mMsgId, messageName()); + + if(missing_post) + ui->subjectLabel->setText("[" + QObject::tr("Missing channel post")+"]"); + else + ui->subjectLabel->setText(msgLink.toHtml()); - if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) - { - //ui->unsubscribeButton->setEnabled(true); - } - else - { - //ui->unsubscribeButton->setEnabled(false); - } ui->readButton->hide(); - //ui->titleLabel->hide(); if (IS_MSG_NEW(mPost.mMeta.mMsgStatus)) { mCloseOnRead = true; @@ -431,18 +398,10 @@ void ChannelsCommentsItem::fill() } else { - /* subject */ - //ui->titleLabel->setText(QString::fromUtf8(mPost.mMeta.mMsgName.c_str())); - - uint32_t autorized_lines = (int)floor((ui->avatarLabel->height() - ui->buttonHLayout->sizeHint().height())/QFontMetricsF(ui->subjectLabel->font()).height()); - - // fill first 4 lines of message. (csoler) Disabled the replacement of smileys and links, because the cost is too crazy - //ui->subjectLabel->setText(RsHtml().formatText(NULL, RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), autorized_lines), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); - - ui->subjectLabel->setText(RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), 2)) ; - - //QString score = QString::number(post.mTopScore); - // scoreLabel->setText(score); + if(missing_post) + ui->subjectLabel->setText("[" + QObject::tr("Missing channel post")+"]"); + else + ui->subjectLabel->setText(RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), 2)) ; /* disable buttons: deletion facility not enabled with cache services yet */ ui->clearButton->setEnabled(false); @@ -465,50 +424,9 @@ void ChannelsCommentsItem::fill() mCloseOnRead = false; } - // differences between Feed or Top of Comment. - if (mFeedHolder) - { - //ui->commentButton->show(); - - // Not yet functional - /*if (mPost.mCommentCount) - { - QString commentText = QString::number(mPost.mCommentCount); - commentText += " "; - commentText += tr("Comments"); - ui->commentButton->setText(commentText); - } - else - { - ui->commentButton->setText(tr("Comment")); - }*/ - - } - else - { - //ui->commentButton->hide(); - } - - // disable voting buttons - if they have already voted. - /*if (post.mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) - { - voteUpButton->setEnabled(false); - voteDownButton->setEnabled(false); - }*/ - - if (wasExpanded() || ui->expandFrame->isVisible()) { - fillExpandFrame(); - } - mInFill = false; } -void ChannelsCommentsItem::fillExpandFrame() -{ - //ui->msgLabel->setText(RsHtml().formatText(NULL, QString::fromUtf8(mPost.mMsg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); - -} - QString ChannelsCommentsItem::messageName() { return QString::fromUtf8(mPost.mMeta.mMsgName.c_str()); @@ -534,9 +452,9 @@ void ChannelsCommentsItem::setReadStatus(bool isNew, bool isUnread) ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-read.png")); } - ui->mainFrame->setProperty("new", isNew); - ui->mainFrame->style()->unpolish(ui->mainFrame); - ui->mainFrame->style()->polish( ui->mainFrame); + ui->feedFrame->setProperty("new", isNew); + ui->feedFrame->style()->unpolish(ui->feedFrame); + ui->feedFrame->style()->polish( ui->feedFrame); } void ChannelsCommentsItem::doExpand(bool open) @@ -572,10 +490,6 @@ void ChannelsCommentsItem::doExpand(bool open) void ChannelsCommentsItem::expandFill(bool first) { GxsFeedItem::expandFill(first); - - if (first) { - fillExpandFrame(); - } } void ChannelsCommentsItem::toggle() @@ -615,7 +529,7 @@ void ChannelsCommentsItem::readToggled(bool /*checked*/) RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); - rsGxsChannels->markRead(msgPair, isUnread()); + rsGxsChannels->setCommentReadStatus(msgPair, isUnread()); //setReadStatus(false, checked); // Updated by events } diff --git a/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.h b/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.h index 53537d61e..c245cbca7 100644 --- a/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.h +++ b/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.h @@ -42,12 +42,17 @@ public: // It can be used for all apparences of channel posts. But in rder to merge comments from the previous versions of the post, the list of // previous posts should be supplied. It's optional. If not supplied only the comments of the new version will be displayed. - ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); + ChannelsCommentsItem(FeedHolder *feedHolder, + uint32_t feedId, + const RsGxsGroupId& groupId, + const RsGxsMessageId& commentId, + const RsGxsMessageId& threadId, + bool isHome, + bool autoUpdate); // This one is used in channel thread widget. We don't want the group data to reload at every post, so we load it in the hosting // GxsChannelsPostsWidget and pass it to created items. - - ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGroupMetaData& group, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); + // ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGroupMetaData& group, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); virtual ~ChannelsCommentsItem(); @@ -55,6 +60,7 @@ public: bool setGroup(const RsGxsChannelGroup& group, bool doFill = true); bool setPost(const RsGxsChannelPost& post, bool doFill = true); + bool setMissingPost(); QString getTitleLabel(); QString getMsgLabel(); @@ -85,8 +91,8 @@ protected: /* GxsFeedItem */ virtual QString messageName(); - virtual void loadMessage(); - virtual void loadComment(); + virtual void loadMessage() override {} + virtual void loadComment() override {} private slots: /* default stuff */ @@ -104,17 +110,20 @@ signals: void vote(const RsGxsGrpMsgIdPair& msgId, bool up); private: - void setup(); - void fill(); - void fillExpandFrame(); + void load(); + void setup(); + void fill(bool missing_post=false); private: bool mInFill; bool mCloseOnRead; bool mLoaded; + bool mLoading; + RsGroupMetaData mGroupMeta; RsGxsChannelPost mPost; + RsGxsMessageId mThreadId; /** Qt Designer generated object */ Ui::ChannelsCommentsItem *ui; diff --git a/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.ui b/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.ui index 45c55b841..db4ac6b1a 100644 --- a/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.ui +++ b/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.ui @@ -6,11 +6,11 @@ 0 0 - 755 - 157 + 836 + 160
    - + 1 @@ -24,7 +24,7 @@ 1 - + 0 @@ -35,12 +35,12 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + 9 @@ -51,12 +51,12 @@ 3 - + 8 - + @@ -134,6 +134,7 @@ + 12 75 true @@ -150,6 +151,7 @@ + 12 75 true @@ -163,7 +165,7 @@ - + Qt::Horizontal @@ -272,7 +274,7 @@ 3 - + Qt::Horizontal @@ -313,7 +315,9 @@ + 11 75 + true true @@ -360,7 +364,7 @@ - + @@ -393,7 +397,7 @@ - + Qt::Vertical @@ -409,7 +413,7 @@ - + 0 @@ -430,7 +434,7 @@ QFrame::Sunken - + 5 @@ -486,8 +490,6 @@
    gui/gxs/GxsIdLabel.h
    - - - + diff --git a/retroshare-gui/src/gui/feeds/ChatMsgItem.cpp b/retroshare-gui/src/gui/feeds/ChatMsgItem.cpp index 7f37aef8b..573c65c9d 100644 --- a/retroshare-gui/src/gui/feeds/ChatMsgItem.cpp +++ b/retroshare-gui/src/gui/feeds/ChatMsgItem.cpp @@ -229,7 +229,7 @@ void ChatMsgItem::sendMessage() mi.title = tr("Quick Message").toUtf8().constData(); mi.msg = quickmsgText->toHtml().toUtf8().constData(); - mi.rspeerid_msgto.insert(mPeerId); + mi.destinations.insert(MsgAddress(mPeerId,MsgAddress::MSG_ADDRESS_MODE_TO)); rsMail->MessageSend(mi); diff --git a/retroshare-gui/src/gui/feeds/ChatMsgItem.ui b/retroshare-gui/src/gui/feeds/ChatMsgItem.ui index 2a8725b09..64c994b6f 100644 --- a/retroshare-gui/src/gui/feeds/ChatMsgItem.ui +++ b/retroshare-gui/src/gui/feeds/ChatMsgItem.ui @@ -10,7 +10,7 @@ 209 - + 1 @@ -24,7 +24,7 @@ 1 - + 0 @@ -40,9 +40,9 @@ QFrame::Sunken - + - + @@ -60,7 +60,7 @@ - + Qt::Vertical @@ -75,7 +75,12 @@ - + + + + 17 + + Peer Name @@ -85,7 +90,7 @@ - + Qt::Horizontal @@ -149,7 +154,7 @@ - + 0 @@ -247,7 +252,7 @@ - + Qt::Horizontal @@ -307,7 +312,7 @@ - + 0 @@ -345,11 +350,6 @@
    gui/common/AvatarWidget.h
    1 - - StyledLabel - QLabel -
    gui/common/StyledLabel.h
    -
    diff --git a/retroshare-gui/src/gui/feeds/FeedItem.cpp b/retroshare-gui/src/gui/feeds/FeedItem.cpp index 83c97eb3b..e9991e6d0 100644 --- a/retroshare-gui/src/gui/feeds/FeedItem.cpp +++ b/retroshare-gui/src/gui/feeds/FeedItem.cpp @@ -23,7 +23,7 @@ #include "FeedHolder.h" /** Constructor */ -FeedItem::FeedItem(FeedHolder *fh, uint32_t feedId, QWidget *parent) : QWidget(parent), mHash(0),mFeedHolder(fh),mFeedId(feedId) +FeedItem::FeedItem(FeedHolder *fh, uint32_t feedId, QWidget *parent) : QWidget(parent),mFeedHolder(fh),mFeedId(feedId),mHash(0) { mWasExpanded = false; } diff --git a/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.cpp b/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.cpp index 41c61d896..a6213e740 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.cpp +++ b/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.cpp @@ -27,6 +27,7 @@ #include "gui/common/FilesDefs.h" #include "gui/NewsFeed.h" #include "gui/RetroShareLink.h" +#include "util/DateTime.h" /**** * #define DEBUG_ITEM 1 @@ -36,20 +37,47 @@ GxsChannelGroupItem::GxsChannelGroupItem(FeedHolder *feedHolder, uint32_t feedId GxsGroupFeedItem(feedHolder, feedId, groupId, isHome, rsGxsChannels, autoUpdate) { setup(); - requestGroup(); + addEventHandler(); } GxsChannelGroupItem::GxsChannelGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelGroup &group, bool isHome, bool autoUpdate) : GxsGroupFeedItem(feedHolder, feedId, group.mMeta.mGroupId, isHome, rsGxsChannels, autoUpdate) { - setup(); + setup(); + setGroup(group); + addEventHandler(); +} - setGroup(group); +void GxsChannelGroupItem::addEventHandler() +{ + mEventHandlerId = 0; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) + { + RsQThreadUtils::postToObject([=]() + { + const auto *e = dynamic_cast(event.get()); + + if(!e || e->mChannelGroupId != this->groupId()) + return; + + switch(e->mChannelEventCode) + { + case RsChannelEventCode::SUBSCRIBE_STATUS_CHANGED: + case RsChannelEventCode::UPDATED_CHANNEL: + case RsChannelEventCode::RECEIVED_PUBLISH_KEY: + loadGroup(); + break; + default: + break; + } + }, this ); + }, mEventHandlerId, RsEventType::GXS_CHANNELS ); } GxsChannelGroupItem::~GxsChannelGroupItem() { + rsEvents->unregisterEventsHandler(mEventHandlerId); delete(ui); } @@ -166,6 +194,11 @@ void GxsChannelGroupItem::fill() break ; } + if(mGroup.mMeta.mLastPost==0) + ui->infoLastPost->setText(tr("Never")); + else + ui->infoLastPost->setText(DateTime::formatLongDateTime(mGroup.mMeta.mLastPost)); + if (mIsHome) { /* disable buttons */ diff --git a/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.h b/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.h index cd7f6510b..b0366bc98 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.h +++ b/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.h @@ -60,12 +60,14 @@ private slots: private: void fill(); void setup(); + void addEventHandler(); private: RsGxsChannelGroup mGroup; /** Qt Designer generated object */ Ui::GxsChannelGroupItem *ui; + RsEventsHandlerId_t mEventHandlerId; }; #endif diff --git a/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.ui b/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.ui index b5c3eb9aa..43537d061 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.ui +++ b/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.ui @@ -7,10 +7,18 @@ 0 0 618 - 161 + 189
    - + + + 11 + 75 + true + true + + + 1 @@ -24,7 +32,7 @@ 1 - + 0 @@ -34,6 +42,15 @@ + + + + 0 + 0 + 0 + + + @@ -54,6 +71,15 @@ + + + + 0 + 0 + 0 + + + @@ -74,6 +100,15 @@ + + + + 154 + 154 + 154 + + + @@ -99,14 +134,14 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + - + @@ -133,7 +168,7 @@ - + @@ -144,6 +179,7 @@ + 11 75 true true @@ -158,7 +194,9 @@ + 11 75 + true true @@ -171,7 +209,7 @@ - + Qt::Horizontal @@ -183,10 +221,24 @@
    + + + + Last activity + + + + + + + TextLabel + + +
    - + @@ -199,7 +251,7 @@ Qt::NoFocus - Subscribe to Channel + Subscribe this Channel Subscribe @@ -207,7 +259,7 @@ - + Qt::Horizontal @@ -282,7 +334,7 @@ - + 0 @@ -303,7 +355,7 @@ Channel Description - + @@ -341,7 +393,6 @@ - diff --git a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp index 733e3048b..17036a15e 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp +++ b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp @@ -49,6 +49,10 @@ GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, GxsFeedItem(feedHolder, feedId, group_meta.mGroupId, messageId, isHome, rsGxsChannels, autoUpdate), mGroupMeta(group_meta) { + mLoadingGroup = false; + mLoadingMessage = false; + mLoadingComment = false; + mPost.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded mPost.mMeta.mGroupId = mGroupMeta.mGroupId; @@ -136,6 +140,19 @@ void GxsChannelPostItem::paintEvent(QPaintEvent *e) GxsChannelPostItem::~GxsChannelPostItem() { + auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(300); + + while( (mLoadingGroup || mLoadingMessage || mLoadingComment) + && std::chrono::steady_clock::now() < timeout) + { + RsDbg() << __PRETTY_FUNCTION__ << " is Waiting for " + << (mLoadingGroup ? "Group " : "") + << (mLoadingMessage ? "Message " : "") + << (mLoadingComment ? "Comment " : "") + << "loading." << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + delete(ui); } @@ -221,9 +238,9 @@ void GxsChannelPostItem::setup() //ui->subjectLabel->setMinimumWidth(100); //ui->warning_label->setMinimumWidth(100); - ui->mainFrame->setProperty("new", false); - ui->mainFrame->style()->unpolish(ui->mainFrame); - ui->mainFrame->style()->polish( ui->mainFrame); + ui->feedFrame->setProperty("new", false); + ui->feedFrame->style()->unpolish(ui->feedFrame); + ui->feedFrame->style()->polish( ui->feedFrame); ui->expandFrame->hide(); } @@ -277,6 +294,7 @@ void GxsChannelPostItem::loadGroup() std::cerr << "GxsChannelGroupItem::loadGroup()"; std::cerr << std::endl; #endif + mLoadingGroup = true; RsThread::async([this]() { @@ -306,6 +324,7 @@ void GxsChannelPostItem::loadGroup() * after a blocking call to RetroShare API complete */ mGroupMeta = group.mMeta; + mLoadingGroup = false; }, this ); }); @@ -316,6 +335,8 @@ void GxsChannelPostItem::loadMessage() std::cerr << "GxsChannelPostItem::loadMessage()"; std::cerr << std::endl; #endif + mLoadingMessage = true; + RsThread::async([this]() { // 1 - get group data @@ -337,7 +358,11 @@ void GxsChannelPostItem::loadMessage() #endif const RsGxsChannelPost& post(posts[0]); - RsQThreadUtils::postToObject( [post,this]() { setPost(post); }, this ); + RsQThreadUtils::postToObject( [post,this]() + { + setPost(post); + mLoadingMessage = false; + }, this ); } else if(comments.size() == 1) { @@ -356,7 +381,8 @@ void GxsChannelPostItem::loadMessage() setMessageId(cmt.mMeta.mThreadId); requestMessage(); - }, this ); + mLoadingMessage = false; + }, this ); } else @@ -366,7 +392,11 @@ void GxsChannelPostItem::loadMessage() std::cerr << std::endl; #endif - RsQThreadUtils::postToObject( [this]() { removeItem(); }, this ); + RsQThreadUtils::postToObject( [this]() + { + removeItem(); + mLoadingMessage = false; + }, this ); } }); } @@ -377,6 +407,7 @@ void GxsChannelPostItem::loadComment() std::cerr << "GxsChannelPostItem::loadComment()"; std::cerr << std::endl; #endif + mLoadingComment = true; RsThread::async([this]() { @@ -407,6 +438,7 @@ void GxsChannelPostItem::loadComment() sComButText = tr("Comments ").append("(%1)").arg(comNb); ui->commentButton->setText(sComButText); + mLoadingComment = false; }, this ); }); @@ -487,7 +519,7 @@ void GxsChannelPostItem::fill() /* subject */ ui->titleLabel->setText(QString::fromUtf8(mPost.mMeta.mMsgName.c_str())); - uint32_t autorized_lines = (int)floor((ui->logoLabel->height() - ui->titleLabel->height() - ui->buttonHLayout->sizeHint().height())/QFontMetricsF(ui->subjectLabel->font()).height()); + //uint32_t autorized_lines = (int)floor((ui->logoLabel->height() - ui->titleLabel->height() - ui->buttonHLayout->sizeHint().height())/QFontMetricsF(ui->subjectLabel->font()).height()); // fill first 4 lines of message. (csoler) Disabled the replacement of smileys and links, because the cost is too crazy //ui->subjectLabel->setText(RsHtml().formatText(NULL, RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), autorized_lines), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); @@ -647,9 +679,9 @@ void GxsChannelPostItem::setReadStatus(bool isNew, bool isUnread) ui->newLabel->setVisible(isNew); - ui->mainFrame->setProperty("new", isNew); - ui->mainFrame->style()->unpolish(ui->mainFrame); - ui->mainFrame->style()->polish( ui->mainFrame); + ui->feedFrame->setProperty("new", isNew); + ui->feedFrame->style()->unpolish(ui->feedFrame); + ui->feedFrame->style()->polish( ui->feedFrame); } // void GxsChannelPostItem::setFileCleanUpWarning(uint32_t time_left) @@ -850,7 +882,7 @@ void GxsChannelPostItem::readToggled(bool /*checked*/) RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); - rsGxsChannels->markRead(msgPair, isUnread()); + rsGxsChannels->setMessageReadStatus(msgPair, isUnread()); //setReadStatus(false, checked); // Updated by events } diff --git a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h index 8370b885e..b3e7843c0 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h +++ b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h @@ -119,7 +119,12 @@ private: private: bool mInFill; bool mCloseOnRead; - bool mLoaded; + bool mLoaded; + + bool mLoadingMessage; + bool mLoadingGroup; + bool mLoadingComment; + RsGroupMetaData mGroupMeta; RsGxsChannelPost mPost; diff --git a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.ui b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.ui index 3ce8c06b3..d4d41dc06 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.ui +++ b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.ui @@ -7,10 +7,10 @@ 0 0 1092 - 231 + 255 - + 1 @@ -30,7 +30,7 @@ 1 - + 0 @@ -41,16 +41,16 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + - + @@ -86,6 +86,7 @@ + 11 75 true true @@ -125,7 +126,7 @@ - + Qt::Vertical @@ -139,6 +140,14 @@ + + + 11 + 75 + false + true + + TextLabel @@ -317,7 +326,7 @@ - + Qt::Horizontal @@ -385,7 +394,7 @@ - + 0 @@ -406,7 +415,7 @@ QFrame::Sunken - + 5 @@ -451,7 +460,7 @@ - + Qt::Vertical @@ -472,7 +481,7 @@ ElidedLabel QLabel -
    gui/common/ElidedLabel.h
    +
    gui/common/ElidedLabel.h
    1
    diff --git a/retroshare-gui/src/gui/feeds/GxsCircleItem.h b/retroshare-gui/src/gui/feeds/GxsCircleItem.h index dc83dd30d..74f2cf44a 100644 --- a/retroshare-gui/src/gui/feeds/GxsCircleItem.h +++ b/retroshare-gui/src/gui/feeds/GxsCircleItem.h @@ -24,8 +24,6 @@ #include #include "FeedItem.h" -#include "util/TokenQueue.h" - namespace Ui { class GxsCircleItem; } diff --git a/retroshare-gui/src/gui/feeds/GxsCircleItem.ui b/retroshare-gui/src/gui/feeds/GxsCircleItem.ui index c295d1b57..374e8f84d 100644 --- a/retroshare-gui/src/gui/feeds/GxsCircleItem.ui +++ b/retroshare-gui/src/gui/feeds/GxsCircleItem.ui @@ -7,10 +7,10 @@ 0 0 618 - 108 + 128 - + 1 @@ -24,7 +24,7 @@ 1 - + 0 @@ -34,6 +34,15 @@ + + + + 0 + 0 + 0 + + + @@ -54,6 +63,15 @@ + + + + 0 + 0 + 0 + + + @@ -74,6 +92,15 @@ + + + + 154 + 154 + 154 + + + @@ -99,12 +126,12 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + @@ -131,9 +158,9 @@ - + - + @@ -154,8 +181,9 @@ - 10 + 11 75 + true true @@ -177,6 +205,7 @@ + 11 75 true true @@ -188,7 +217,7 @@ - + Qt::Horizontal @@ -203,9 +232,9 @@ - + - + 10 @@ -220,6 +249,14 @@ + + + 11 + 75 + true + true + + name @@ -244,7 +281,7 @@ - + @@ -280,7 +317,7 @@ Revoke - + :/images/cancel.png:/images/cancel.png @@ -306,7 +343,7 @@ - + Qt::Horizontal @@ -358,8 +395,8 @@ - + diff --git a/retroshare-gui/src/gui/feeds/GxsForumGroupItem.cpp b/retroshare-gui/src/gui/feeds/GxsForumGroupItem.cpp index 1d61bb98b..663951a6c 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumGroupItem.cpp +++ b/retroshare-gui/src/gui/feeds/GxsForumGroupItem.cpp @@ -35,8 +35,8 @@ GxsForumGroupItem::GxsForumGroupItem(FeedHolder *feedHolder, uint32_t feedId, co GxsGroupFeedItem(feedHolder, feedId, groupId, isHome, rsGxsForums, autoUpdate) { setup(); - requestGroup(); + addEventHandler(); } GxsForumGroupItem::GxsForumGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const std::list& added_moderators,const std::list& removed_moderators,bool isHome, bool autoUpdate): @@ -45,21 +45,48 @@ GxsForumGroupItem::GxsForumGroupItem(FeedHolder *feedHolder, uint32_t feedId, co mRemovedModerators(removed_moderators) { setup(); - requestGroup(); + addEventHandler(); +} + +void GxsForumGroupItem::addEventHandler() +{ + mEventHandlerId = 0; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) + { + RsQThreadUtils::postToObject([=]() + { + const auto *e = dynamic_cast(event.get()); + + if(!e || e->mForumGroupId != this->groupId()) + return; + + switch(e->mForumEventCode) + { + case RsForumEventCode::SUBSCRIBE_STATUS_CHANGED: + case RsForumEventCode::UPDATED_FORUM: + case RsForumEventCode::MODERATOR_LIST_CHANGED: + loadGroup(); + break; + default: + break; + } + }, this ); + }, mEventHandlerId, RsEventType::GXS_FORUMS ); } GxsForumGroupItem::GxsForumGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsForumGroup &group, bool isHome, bool autoUpdate) : GxsGroupFeedItem(feedHolder, feedId, group.mMeta.mGroupId, isHome, rsGxsForums, autoUpdate) { setup(); - setGroup(group); + addEventHandler(); } GxsForumGroupItem::~GxsForumGroupItem() { - delete(ui); + rsEvents->unregisterEventsHandler(mEventHandlerId); + delete(ui); } void GxsForumGroupItem::setup() @@ -125,7 +152,7 @@ void GxsForumGroupItem::loadGroup() std::cerr << std::endl; return; } - const RsGxsForumGroup& group(groups[0]); + RsGxsForumGroup group(groups[0]);// no reference to teporary accross threads! RsQThreadUtils::postToObject( [group,this]() { diff --git a/retroshare-gui/src/gui/feeds/GxsForumGroupItem.h b/retroshare-gui/src/gui/feeds/GxsForumGroupItem.h index 29b7851f2..d80671e5a 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumGroupItem.h +++ b/retroshare-gui/src/gui/feeds/GxsForumGroupItem.h @@ -22,6 +22,7 @@ #define _GXSFORUMGROUPITEM_H #include +#include #include "gui/gxs/GxsGroupFeedItem.h" namespace Ui { @@ -39,27 +40,28 @@ public: GxsForumGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, bool autoUpdate); GxsForumGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const std::list& added_moderators,const std::list& removed_moderators,bool isHome, bool autoUpdate); GxsForumGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsForumGroup &group, bool isHome, bool autoUpdate); - ~GxsForumGroupItem(); + virtual ~GxsForumGroupItem() override; bool setGroup(const RsGxsForumGroup &group); uint64_t uniqueIdentifier() const override { return hash_64bits("GxsForumGroupItem " + groupId().toStdString()) ; } protected: /* FeedItem */ - virtual void doExpand(bool open); - void toggle() override; + virtual void doExpand(bool open) override; /* GxsGroupFeedItem */ - virtual QString groupName(); + virtual QString groupName() override; virtual void loadGroup() override; - virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_FORUM; } + virtual RetroShareLink::enumType getLinkType() override { return RetroShareLink::TYPE_FORUM; } private slots: void subscribeForum(); + void toggle() override; private: void fill(); void setup(); + void addEventHandler(); private: RsGxsForumGroup mGroup; @@ -69,6 +71,8 @@ private: std::list mAddedModerators; std::list mRemovedModerators; + + RsEventsHandlerId_t mEventHandlerId; }; #endif diff --git a/retroshare-gui/src/gui/feeds/GxsForumGroupItem.ui b/retroshare-gui/src/gui/feeds/GxsForumGroupItem.ui index 88000d0cb..aee325282 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumGroupItem.ui +++ b/retroshare-gui/src/gui/feeds/GxsForumGroupItem.ui @@ -10,7 +10,7 @@ 464 - + 1 @@ -24,7 +24,7 @@ 1 - + 0 @@ -34,6 +34,15 @@ + + + + 0 + 0 + 0 + + + @@ -54,6 +63,15 @@ + + + + 0 + 0 + 0 + + + @@ -74,6 +92,15 @@ + + + + 154 + 154 + 154 + + + @@ -99,14 +126,14 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + - + @@ -133,7 +160,7 @@ - + @@ -144,6 +171,7 @@ + 11 75 true true @@ -158,7 +186,9 @@ + 11 75 + true true @@ -171,7 +201,7 @@ - + Qt::Horizontal @@ -186,7 +216,7 @@ - + @@ -207,7 +237,7 @@ - + Qt::Horizontal @@ -282,7 +312,7 @@ - + 0 @@ -303,7 +333,7 @@ Forum Description - + @@ -339,24 +369,34 @@ Moderator list - + - 0 + 6 - 0 + 9 - 0 + 9 - 0 + 9 - 0 + 9 - + + + TextLabel + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + @@ -367,7 +407,6 @@ - diff --git a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp index af80babd5..f4d091179 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp +++ b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp @@ -47,7 +47,13 @@ GxsForumMsgItem::GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const { mMessage.mMeta.mMsgId = messageId; // useful for uniqueIdentifier() before the post is actually loaded mMessage.mMeta.mGroupId = groupId; - setup(); + + mLoadingGroup = false; + mLoadingMessage = false; + mLoadingSetAsRead = false; + mLoadingParentMessage = false; + + setup(); requestGroup(); requestMessage(); @@ -83,6 +89,19 @@ GxsForumMsgItem::GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const GxsForumMsgItem::~GxsForumMsgItem() { + auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(300); + + while( (mLoadingGroup || mLoadingMessage || mLoadingSetAsRead || mLoadingParentMessage) + && std::chrono::steady_clock::now() < timeout) + { + RsDbg() << __PRETTY_FUNCTION__ << " is Waiting for " + << (mLoadingGroup ? "Group " : "") + << (mLoadingMessage ? "Message " : "") + << (mLoadingParentMessage ? "Parent message " : "") + << (mLoadingSetAsRead ? "Set as read" : "") + << "loading." << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } delete(ui); } @@ -106,7 +125,7 @@ void GxsForumMsgItem::setup() connect(ui->subjectLabel, SIGNAL(linkActivated(QString)), this, SLOT(on_linkActivated(QString))); ui->timestamplabel->clear(); ui->parentNameLabel->clear(); - ui->nameLabel->clear(); + ui->currNameLabel->clear(); /* general ones */ connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(toggle())); @@ -167,6 +186,8 @@ QString GxsForumMsgItem::groupName() void GxsForumMsgItem::loadGroup() { + mLoadingGroup = true; + RsThread::async([this]() { // 1 - get group data @@ -199,6 +220,7 @@ void GxsForumMsgItem::loadGroup() * after a blocking call to RetroShare API complete */ setGroup(group); + mLoadingGroup = false; }, this ); }); @@ -210,6 +232,7 @@ void GxsForumMsgItem::loadMessage() std::cerr << "GxsForumMsgItem::loadMessage(): messageId=" << messageId() << " groupId=" << groupId() ; std::cerr << std::endl; #endif + mLoadingMessage = true; RsThread::async([this]() { @@ -235,7 +258,7 @@ void GxsForumMsgItem::loadMessage() std::cerr << std::endl; return; } - const RsGxsForumMsg& msg(msgs[0]); + RsGxsForumMsg msg(msgs[0]); RsQThreadUtils::postToObject( [msg,this]() { @@ -244,6 +267,7 @@ void GxsForumMsgItem::loadMessage() * after a blocking call to RetroShare API complete */ setMessage(msg); + mLoadingMessage = false; }, this ); }); @@ -255,6 +279,7 @@ void GxsForumMsgItem::loadParentMessage(const RsGxsMessageId& parent_msg) std::cerr << "GxsForumMsgItem::loadParentMessage()"; std::cerr << std::endl; #endif + mLoadingParentMessage = true; RsThread::async([parent_msg,this]() { @@ -280,7 +305,7 @@ void GxsForumMsgItem::loadParentMessage(const RsGxsMessageId& parent_msg) std::cerr << std::endl; return; } - const RsGxsForumMsg& msg(msgs[0]); + RsGxsForumMsg msg(msgs[0]); RsQThreadUtils::postToObject( [msg,this]() { @@ -291,6 +316,8 @@ void GxsForumMsgItem::loadParentMessage(const RsGxsMessageId& parent_msg) mParentMessage = msg; fillParentMessage(); + mLoadingParentMessage = false; + }, this ); }); } @@ -347,12 +374,12 @@ void GxsForumMsgItem::fillMessage() if(idDetails.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idDetails.mAvatar.mData, idDetails.mAvatar.mSize, pixmap,GxsIdDetails::SMALL)) pixmap = GxsIdDetails::makeDefaultIcon(mMessage.mMeta.mAuthorId,GxsIdDetails::SMALL); - ui->avatar->setPixmap(pixmap); + ui->currAvatar->setPixmap(pixmap); - ui->nameLabel->setId(mMessage.mMeta.mAuthorId); + ui->currNameLabel->setId(mMessage.mMeta.mAuthorId); RetroShareLink msgLink = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_FORUM, mMessage.mMeta.mGroupId, mMessage.mMeta.mMsgId, messageName()); - ui->subLabel->setText(msgLink.toHtml()); + ui->currSubLabel->setText(msgLink.toHtml()); if (wasExpanded() || ui->expandFrame->isVisible()) fillExpandFrame(); @@ -386,7 +413,7 @@ void GxsForumMsgItem::fillGroup() void GxsForumMsgItem::fillExpandFrame() { - ui->msgLabel->setText(RsHtml().formatText(NULL, QString::fromUtf8(mMessage.mMsg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); + ui->currMsgLabel->setText(RsHtml().formatText(NULL, QString::fromUtf8(mMessage.mMsg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); } QString GxsForumMsgItem::messageName() @@ -411,7 +438,7 @@ void GxsForumMsgItem::doExpand(bool open) ui->parentFrame->show(); } - setAsRead(); + setAsRead(true); } else { @@ -445,9 +472,9 @@ void GxsForumMsgItem::toggle() void GxsForumMsgItem::setReadStatus(bool isNew, bool /*isUnread*/) { - ui->mainFrame->setProperty("new", isNew); - ui->mainFrame->style()->unpolish(ui->mainFrame); - ui->mainFrame->style()->polish( ui->mainFrame); + ui->feedFrame->setProperty("new", isNew); + ui->feedFrame->style()->unpolish(ui->feedFrame); + ui->feedFrame->style()->polish( ui->feedFrame); } /*********** SPECIFIC FUNCTIONS ***********************/ @@ -459,7 +486,7 @@ void GxsForumMsgItem::readAndClearItem() std::cerr << std::endl; #endif - setAsRead(); + setAsRead(false); removeItem(); } @@ -473,20 +500,27 @@ void GxsForumMsgItem::unsubscribeForum() unsubscribe(); } -void GxsForumMsgItem::setAsRead() +void GxsForumMsgItem::setAsRead(bool doUpdate) { - if (mInFill) { - return; - } + if (mInFill) { + return; + } - mCloseOnRead = false; + mCloseOnRead = false; + mLoadingSetAsRead = true; - RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); + RsThread::async( [this, doUpdate]() { + RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); - uint32_t token; - rsGxsForums->setMessageReadStatus(token, msgPair, true); + rsGxsForums->markRead(msgPair, true); - setReadStatus(false, false); + if (doUpdate) { + RsQThreadUtils::postToObject( [this]() { + setReadStatus(false, true); + mLoadingSetAsRead = false; + } ); + } + }); } void GxsForumMsgItem::on_linkActivated(QString link) diff --git a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.h b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.h index 17287ada1..ec933d96e 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.h +++ b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.h @@ -82,11 +82,15 @@ private: void fillParentMessage(); void fillExpandFrame(); void setReadStatus(bool isNew, bool isUnread); - void setAsRead(); + void setAsRead(bool doUpdate); private: bool mInFill; bool mCloseOnRead; + bool mLoadingMessage; + bool mLoadingParentMessage; + bool mLoadingGroup; + bool mLoadingSetAsRead; RsGxsForumGroup mGroup; RsGxsForumMsg mMessage; diff --git a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.ui b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.ui index 5967010b7..4a080effb 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.ui +++ b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.ui @@ -10,7 +10,7 @@ 360 - + 1 @@ -24,7 +24,7 @@ 1 - + 0 @@ -34,6 +34,15 @@ + + + + 0 + 0 + 0 + + + @@ -45,6 +54,15 @@ + + + + 0 + 0 + 0 + + + @@ -56,6 +74,15 @@ + + + + 154 + 154 + 154 + + + @@ -72,12 +99,12 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + @@ -104,7 +131,7 @@ - + @@ -115,7 +142,9 @@ + 11 75 + true true @@ -134,7 +163,7 @@ - + Qt::Horizontal @@ -165,9 +194,9 @@ - + - + 75 @@ -196,7 +225,7 @@ - + Qt::Horizontal @@ -299,7 +328,7 @@ - + 32 @@ -331,9 +360,9 @@ - + - + 0 @@ -371,7 +400,7 @@ - + Qt::Horizontal @@ -389,7 +418,7 @@ - + Qt::Vertical @@ -402,7 +431,7 @@ - + @@ -426,7 +455,7 @@ - + Qt::Horizontal @@ -454,9 +483,9 @@ QFrame::Sunken - + - + 32 @@ -472,10 +501,12 @@ - + + 11 75 + true true @@ -488,9 +519,9 @@ - + - + 0 @@ -509,7 +540,7 @@ - + 0 @@ -530,7 +561,7 @@ - + Qt::Vertical @@ -543,9 +574,9 @@ - + - + 0 @@ -587,13 +618,12 @@ AvatarWidget - QLabel + QWidget
    gui/common/AvatarWidget.h
    1
    - diff --git a/retroshare-gui/src/gui/feeds/MsgItem.cpp b/retroshare-gui/src/gui/feeds/MsgItem.cpp index 87a01bcd9..0789d98c9 100644 --- a/retroshare-gui/src/gui/feeds/MsgItem.cpp +++ b/retroshare-gui/src/gui/feeds/MsgItem.cpp @@ -31,6 +31,7 @@ #include "gui/common/AvatarDefs.h" #include "gui/common/FilesDefs.h" #include "gui/notifyqt.h" +#include "util/qtthreadsutils.h" #include #include @@ -59,20 +60,73 @@ MsgItem::MsgItem(FeedHolder *parent, uint32_t feedId, const std::string &msgId, //connect( gotoButton, SIGNAL( clicked( void ) ), this, SLOT( gotoHome ( void ) ) ); /* specific ones */ - connect(NotifyQt::getInstance(), SIGNAL(messagesChanged()), this, SLOT(checkMessageReadStatus())); connect( playButton, SIGNAL( clicked( void ) ), this, SLOT( playMedia ( void ) ) ); connect( deleteButton, SIGNAL( clicked( void ) ), this, SLOT( deleteMsg ( void ) ) ); connect( replyButton, SIGNAL( clicked( void ) ), this, SLOT( replyMsg ( void ) ) ); connect( sendinviteButton, SIGNAL( clicked( void ) ), this, SLOT( sendInvite ( void ) ) ); + mEventHandlerId = 0; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) { RsQThreadUtils::postToObject( [this,event]() { handleEvent_main_thread(event); }); }, mEventHandlerId, RsEventType::MAIL_STATUS ); expandFrame->hide(); - inviteFrame->hide(); + info_Frame_Invite->hide(); updateItemStatic(); updateItem(); } +MsgItem::~MsgItem() +{ + rsEvents->unregisterEventsHandler(mEventHandlerId); +} + +void MsgItem::handleEvent_main_thread(std::shared_ptr event) +{ + if(event->mType != RsEventType::MAIL_STATUS) { + return; + } + + const RsMailStatusEvent *fe = dynamic_cast(event.get()); + if (!fe) { + return; + } + + switch (fe->mMailStatusEventCode) { + case RsMailStatusEventCode::MESSAGE_CHANGED: + if (fe->mChangedMsgIds.find(mMsgId) != fe->mChangedMsgIds.end()) { + MessageInfo msgInfo; + + if (!rsMail->getMessage(mMsgId, msgInfo)) { + removeItem(); + break; + } + + if (!mCloseOnRead) { + break; + } + + if (msgInfo.msgflags & RS_MSG_NEW) { + /* Message status is still "new" */ + break; + } + + removeItem(); + } + break; + case RsMailStatusEventCode::MESSAGE_REMOVED: + if (fe->mChangedMsgIds.find(mMsgId) != fe->mChangedMsgIds.end()) { + removeItem(); + } + break; + case RsMailStatusEventCode::MESSAGE_SENT: + case RsMailStatusEventCode::NEW_MESSAGE: + case RsMailStatusEventCode::TAG_CHANGED: + case RsMailStatusEventCode::MESSAGE_RECEIVED_ACK: + case RsMailStatusEventCode::SIGNATURE_FAILED: + break; + } +} + void MsgItem::updateItemStatic() { /* fill in */ @@ -92,44 +146,44 @@ void MsgItem::updateItemStatic() /* get peer Id */ if (mi.msgflags & RS_MSG_DISTANT) - avatar->setGxsId(mi.rsgxsid_srcId) ; + avatar->setGxsId(mi.from.toGxsId()) ; else - avatar->setId(ChatId(mi.rspeerid_srcId)) ; + avatar->setId(ChatId(mi.from.toRsPeerId())) ; QString title; QString srcName; - if ((mi.msgflags & RS_MSG_SYSTEM) && mi.rspeerid_srcId == rsPeers->getOwnId()) + if ((mi.msgflags & RS_MSG_SYSTEM) && mi.from.toRsPeerId() == rsPeers->getOwnId()) srcName = "RetroShare"; else { if(mi.msgflags & RS_MSG_DISTANT) { RsIdentityDetails details ; - rsIdentity->getIdDetails(mi.rsgxsid_srcId, details) ; + rsIdentity->getIdDetails(mi.from.toGxsId(), details) ; srcName = QString::fromUtf8(details.mNickname.c_str()); } else - srcName = QString::fromUtf8(rsPeers->getPeerName(mi.rspeerid_srcId).c_str()); + srcName = QString::fromUtf8(rsPeers->getPeerName(mi.from.toRsPeerId()).c_str()); } if (!mIsHome) { - if ((mi.msgflags & RS_MSG_USER_REQUEST) && (!mi.rsgxsid_srcId.isNull())) + if ((mi.msgflags & RS_MSG_USER_REQUEST) && mi.from.type()==MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) // !mi.rsgxsid_srcId.isNull())) { title = QString::fromUtf8(mi.title.c_str()) + " " + tr("from") + " " + srcName; replyButton->setText(tr("Reply to invite")); subjectLabel->hide(); - inviteFrame->show(); + info_Frame_Invite->show(); } - else if ((mi.msgflags & RS_MSG_USER_REQUEST) && mi.rsgxsid_srcId.isNull()) + else if ((mi.msgflags & RS_MSG_USER_REQUEST) && mi.from.type()!=MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) // mi.rsgxsid_srcId.isNull()) { title = QString::fromUtf8(mi.title.c_str()) + " " + " " + srcName; subjectLabel->hide(); - inviteFrame->show(); - infoLabel->setText(tr("This message invites you to make friend! You may accept this request.")); + info_Frame_Invite->show(); + infoLabel_Invite->setText(tr("This message invites you to make friend! You may accept this request.")); sendinviteButton->hide(); replyButton->hide(); } @@ -137,7 +191,7 @@ void MsgItem::updateItemStatic() { title = tr("Message From") + ": " + srcName; sendinviteButton->hide(); - inviteFrame->hide(); + info_Frame_Invite->hide(); } } else @@ -179,7 +233,11 @@ void MsgItem::updateItemStatic() for(it = mi.files.begin(); it != mi.files.end(); ++it) { /* add file */ - SubFileItem *fi = new SubFileItem(it->hash, it->fname, it->path, it->size, SFI_STATE_REMOTE, mi.rspeerid_srcId); + RsPeerId srcId ; + if(mi.from.type()==MsgAddress::MSG_ADDRESS_TYPE_RSPEERID) + srcId = mi.from.toRsPeerId(); + + SubFileItem *fi = new SubFileItem(it->hash, it->fname, it->path, it->size, SFI_STATE_REMOTE, srcId); mFileItems.push_back(fi); QLayout *layout = expandFrame->layout(); @@ -246,7 +304,6 @@ void MsgItem::doExpand(bool open) mCloseOnRead = false; rsMail->MessageRead(mMsgId, false); - mCloseOnRead = true; } else { @@ -332,26 +389,6 @@ void MsgItem::toggle() expand(expandFrame->isHidden()); } -void MsgItem::checkMessageReadStatus() -{ - if (!mCloseOnRead) { - return; - } - - MessageInfo msgInfo; - if (!rsMail->getMessage(mMsgId, msgInfo)) { - std::cerr << "MsgItem::checkMessageReadStatus() Couldn't find Msg" << std::endl; - return; - } - - if (msgInfo.msgflags & RS_MSG_NEW) { - /* Message status is still "new" */ - return; - } - - removeItem(); -} - void MsgItem::sendInvite() { MessageInfo mi; @@ -362,9 +399,12 @@ void MsgItem::sendInvite() if (!rsMail->getMessage(mMsgId, mi)) return; + if(mi.from.type()!=MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) + return; + //if ((QMessageBox::question(this, tr("Send invite?"),tr("Do you really want send a invite with your Certificate?"),QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes))== QMessageBox::Yes) //{ - MessageComposer::sendInvite(mi.rsgxsid_srcId,false); + MessageComposer::sendInvite(mi.from.toGxsId(),false); //} } diff --git a/retroshare-gui/src/gui/feeds/MsgItem.h b/retroshare-gui/src/gui/feeds/MsgItem.h index 32824ca23..2cb8645ba 100644 --- a/retroshare-gui/src/gui/feeds/MsgItem.h +++ b/retroshare-gui/src/gui/feeds/MsgItem.h @@ -24,6 +24,7 @@ #include "ui_MsgItem.h" #include "FeedItem.h" #include +#include class FeedHolder; class SubFileItem; @@ -35,6 +36,7 @@ class MsgItem : public FeedItem, private Ui::MsgItem public: /** Default Constructor */ MsgItem(FeedHolder *parent, uint32_t feedId, const std::string &msgId, bool isHome); + virtual ~MsgItem(); void updateItemStatic(); @@ -46,6 +48,7 @@ protected: private: void fillExpandFrame(); + void handleEvent_main_thread(std::shared_ptr event); private slots: /* default stuff */ @@ -56,7 +59,6 @@ private slots: void deleteMsg(); void replyMsg(); void sendInvite(); - void checkMessageReadStatus(); void updateItem(); @@ -66,6 +68,7 @@ private: bool mIsHome; bool mCloseOnRead; + RsEventsHandlerId_t mEventHandlerId; std::list mFileItems; }; diff --git a/retroshare-gui/src/gui/feeds/MsgItem.ui b/retroshare-gui/src/gui/feeds/MsgItem.ui index 9075554a9..cf0a3ac08 100644 --- a/retroshare-gui/src/gui/feeds/MsgItem.ui +++ b/retroshare-gui/src/gui/feeds/MsgItem.ui @@ -6,11 +6,11 @@ 0 0 - 707 - 180 + 777 + 234
    - + 1 @@ -24,7 +24,7 @@ 1 - + 0 @@ -35,15 +35,15 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + - - + + 0 @@ -57,7 +57,7 @@ 0 - + 70 @@ -82,7 +82,7 @@ - 12 + 11 75 true true @@ -97,7 +97,7 @@ - + Qt::Horizontal @@ -142,7 +142,7 @@ - + @@ -164,7 +164,7 @@ - + Qt::Horizontal @@ -259,10 +259,19 @@ - + + + + + 0 + 0 + 0 + + + @@ -283,6 +292,15 @@ + + + + 0 + 0 + 0 + + + @@ -303,6 +321,15 @@ + + + + 154 + 154 + 154 + + + @@ -333,7 +360,7 @@ QFrame::Box - + 6 @@ -347,7 +374,7 @@ 6 - + 16 @@ -366,7 +393,7 @@ - + This message invites you to make friend! You may accept this request and send your own Certificate back @@ -380,7 +407,7 @@ - + @@ -412,7 +439,7 @@ AvatarWidget - QLabel + QWidget
    gui/common/AvatarWidget.h
    1
    diff --git a/retroshare-gui/src/gui/feeds/PeerItem.ui b/retroshare-gui/src/gui/feeds/PeerItem.ui index 230cbd7a4..2433cdf09 100644 --- a/retroshare-gui/src/gui/feeds/PeerItem.ui +++ b/retroshare-gui/src/gui/feeds/PeerItem.ui @@ -7,13 +7,13 @@ 0 0 476 - 262 + 328
    false - + 1 @@ -27,7 +27,7 @@ 1 - + 0 @@ -38,18 +38,18 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + 0 - + 0 @@ -59,8 +59,11 @@ 0 + + 0 + - + 70 @@ -75,84 +78,11 @@ - - - - - - Peer Name - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - 0 - 0 - - - - - 75 - true - true - - - - Connected - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - - - - Qt::Horizontal - - - - 190 - 13 - - - - - - - - - 0 - 0 - - - - - 75 - true - - - - TextLabel - - - Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing - - - - - - - + + + + 6 + @@ -203,7 +133,7 @@ - + Qt::Horizontal @@ -260,16 +190,97 @@ + + + + 6 + + + + + + 0 + 0 + + + + + 75 + true + + + + TextLabel + + + Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing + + + + + + + + 17 + + + + Peer Name + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Qt::Horizontal + + + + 190 + 13 + + + + + + + + + 0 + 0 + + + + + 11 + 75 + true + true + + + + Connected + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + - + - + - + @@ -397,7 +408,7 @@ - + @@ -406,6 +417,14 @@ 0 + + + 11 + 75 + true + true + + TextLabel @@ -508,18 +527,18 @@ AvatarWidget - QLabel + QWidget
    gui/common/AvatarWidget.h
    1
    - StyledLabel + ElidedLabel QLabel -
    gui/common/StyledLabel.h
    +
    gui/common/ElidedLabel.h
    + 1
    - diff --git a/retroshare-gui/src/gui/feeds/PostedGroupItem.cpp b/retroshare-gui/src/gui/feeds/PostedGroupItem.cpp index 4ed8a95c4..f4abafb08 100644 --- a/retroshare-gui/src/gui/feeds/PostedGroupItem.cpp +++ b/retroshare-gui/src/gui/feeds/PostedGroupItem.cpp @@ -26,6 +26,7 @@ #include "gui/RetroShareLink.h" #include "gui/gxs/GxsIdDetails.h" #include "gui/common/FilesDefs.h" +#include "util/DateTime.h" /**** * #define DEBUG_ITEM 1 @@ -160,6 +161,10 @@ void PostedGroupItem::fill() ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/posted.png")); } + if(mGroup.mMeta.mLastPost==0) + ui->infoLastPost->setText(tr("Never")); + else + ui->infoLastPost->setText(DateTime::formatLongDateTime(mGroup.mMeta.mLastPost)); //TODO - nice icon for subscribed group // if (IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) { diff --git a/retroshare-gui/src/gui/feeds/PostedGroupItem.ui b/retroshare-gui/src/gui/feeds/PostedGroupItem.ui index 27226fd28..6c043972f 100644 --- a/retroshare-gui/src/gui/feeds/PostedGroupItem.ui +++ b/retroshare-gui/src/gui/feeds/PostedGroupItem.ui @@ -7,10 +7,10 @@ 0 0 618 - 161 + 195 - + 1 @@ -24,7 +24,7 @@ 1 - + 0 @@ -34,6 +34,15 @@ + + + + 0 + 0 + 0 + + + @@ -54,6 +63,15 @@ + + + + 0 + 0 + 0 + + + @@ -74,6 +92,15 @@ + + + + 154 + 154 + 154 + + + @@ -99,14 +126,14 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + - + @@ -133,7 +160,7 @@ - + @@ -144,6 +171,7 @@ + 11 75 true true @@ -158,7 +186,9 @@ + 11 75 + true true @@ -171,7 +201,7 @@ - + Qt::Horizontal @@ -183,10 +213,37 @@
    + + + + + 75 + true + + + + Last activity + + + + + + + + 75 + true + true + + + + TextLabel + + +
    - + @@ -207,7 +264,7 @@ - + Qt::Horizontal @@ -282,7 +339,7 @@ - + 0 @@ -303,14 +360,14 @@ Board Description - + - :/images/contacts24.png + :/images/contacts24.png @@ -340,8 +397,6 @@ - - diff --git a/retroshare-gui/src/gui/feeds/SecurityIpItem.ui b/retroshare-gui/src/gui/feeds/SecurityIpItem.ui index a9471c6b1..53f4172b9 100644 --- a/retroshare-gui/src/gui/feeds/SecurityIpItem.ui +++ b/retroshare-gui/src/gui/feeds/SecurityIpItem.ui @@ -7,10 +7,10 @@ 0 0 763 - 185 + 205 - + 1 @@ -24,7 +24,7 @@ 1 - + 0 @@ -38,17 +38,17 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + 0 - + 0 @@ -66,7 +66,7 @@ 0 - + 70 @@ -79,13 +79,141 @@ 70 - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - + + + + 6 + + + 0 + + + + + + 11 + 75 + true + true + + + + Title + + + + + + + + 0 + 0 + + + + + 10 + + + + IP address: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + + + + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> + + + IP Address + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + but reported: + + + + + + + + 0 + 0 + + + + IP address reported + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Peer: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Name (Location) + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + + + + 75 + true + + + + TextLabel + + + Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing + + + + + - + 6 @@ -142,7 +270,7 @@ - + Qt::Horizontal @@ -196,130 +324,12 @@ - - - - - - - 75 - true - - - - TextLabel - - - Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing - - - - - - - - - 6 - - - 0 - - - - - - 0 - 0 - - - - IP address: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> - - - IP Address - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - but reported: - - - - - - - - 0 - 0 - - - - IP address reported - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Peer: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - Title - - - - - - - - 0 - 0 - - - - Name (Location) - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - -
    - + @@ -333,22 +343,6 @@ - - - - - 0 - 0 - - - - Location - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - @@ -365,19 +359,6 @@ - - - - - 75 - true - - - - Location: - - - @@ -401,6 +382,35 @@ + + + + + 75 + true + + + + Location: + + + + + + + + 0 + 0 + + + + Location + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + @@ -412,15 +422,10 @@ AvatarWidget - QLabel + QWidget
    gui/common/AvatarWidget.h
    1
    - - StyledLabel - QLabel -
    gui/common/StyledLabel.h
    -
    RsBanListToolButton QToolButton diff --git a/retroshare-gui/src/gui/feeds/SecurityItem.ui b/retroshare-gui/src/gui/feeds/SecurityItem.ui index de674a133..585c18e00 100644 --- a/retroshare-gui/src/gui/feeds/SecurityItem.ui +++ b/retroshare-gui/src/gui/feeds/SecurityItem.ui @@ -7,10 +7,10 @@ 0 0 1015 - 246 + 326 - + 1 @@ -24,7 +24,7 @@ 1 - + 0 @@ -35,18 +35,18 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + 0 - - + + 0 @@ -63,7 +63,7 @@ 0 - + 70 @@ -76,13 +76,10 @@ 70 - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - + 6 @@ -90,7 +87,12 @@ 0 - + + + + 17 + + Peer Name @@ -109,6 +111,7 @@ + 11 75 true true @@ -123,13 +126,18 @@ - + 0 0 + + + 17 + + wants to be friend with you on RetroShare @@ -144,7 +152,7 @@ - + @@ -164,7 +172,7 @@ - + 6 @@ -276,7 +284,7 @@ - + Qt::Horizontal @@ -292,7 +300,7 @@ - + Qt::Horizontal @@ -351,11 +359,11 @@ - + - + - + @@ -463,7 +471,7 @@ - + @@ -472,6 +480,14 @@ 0 + + + 11 + 75 + true + true + + TextLabel @@ -570,19 +586,14 @@ AvatarWidget - QLabel + QWidget
    gui/common/AvatarWidget.h
    1
    - - StyledLabel - QLabel -
    gui/common/StyledLabel.h
    -
    - + diff --git a/retroshare-gui/src/gui/feeds/SubFileItem.ui b/retroshare-gui/src/gui/feeds/SubFileItem.ui index 6717836b5..d869fc7b8 100644 --- a/retroshare-gui/src/gui/feeds/SubFileItem.ui +++ b/retroshare-gui/src/gui/feeds/SubFileItem.ui @@ -10,7 +10,7 @@ 128 - + 0 @@ -27,16 +27,16 @@ 0 - + - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + - + @@ -215,7 +215,7 @@ - + diff --git a/retroshare-gui/src/gui/groups/CreateGroup.cpp b/retroshare-gui/src/gui/groups/CreateGroup.cpp index 91380f98b..2a3defc9c 100644 --- a/retroshare-gui/src/gui/groups/CreateGroup.cpp +++ b/retroshare-gui/src/gui/groups/CreateGroup.cpp @@ -41,7 +41,7 @@ CreateGroup::CreateGroup(const RsNodeGroupId &groupId, QWidget *parent) mIsStandard = false; - ui.headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/images/user/add_group256.png")); + ui.headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/icons/groups/colored.svg")); mGroupId = groupId; @@ -69,7 +69,7 @@ CreateGroup::CreateGroup(const RsNodeGroupId &groupId, QWidget *parent) } setWindowTitle(tr("Edit Group")); - ui.headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/images/user/edit_group64.png")); + ui.headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/icons/groups/colored.svg")); ui.headerFrame->setHeaderText(tr("Edit Group")); ui.groupName->setDisabled(mIsStandard); diff --git a/retroshare-gui/src/gui/groups/CreateGroup.ui b/retroshare-gui/src/gui/groups/CreateGroup.ui index 7abcd5a4e..838a15ac6 100644 --- a/retroshare-gui/src/gui/groups/CreateGroup.ui +++ b/retroshare-gui/src/gui/groups/CreateGroup.ui @@ -13,27 +13,36 @@ Create a Group - + + + 0 + + + 0 + + + 0 + + + 0 + 6 0 - - 0 - - + QFrame::StyledPanel QFrame::Raised - + - + diff --git a/retroshare-gui/src/gui/gxs/GxsCircleChooser.cpp b/retroshare-gui/src/gui/gxs/GxsCircleChooser.cpp index 630a3efbe..9e56c53cd 100644 --- a/retroshare-gui/src/gui/gxs/GxsCircleChooser.cpp +++ b/retroshare-gui/src/gui/gxs/GxsCircleChooser.cpp @@ -20,15 +20,15 @@ #include "GxsCircleChooser.h" -#include #include +#include #include /** Constructor */ GxsCircleChooser::GxsCircleChooser(QWidget *parent) -: QComboBox(parent) + : RSComboBox(parent) { return; } diff --git a/retroshare-gui/src/gui/gxs/GxsCircleChooser.h b/retroshare-gui/src/gui/gxs/GxsCircleChooser.h index f78b350b8..37234b230 100644 --- a/retroshare-gui/src/gui/gxs/GxsCircleChooser.h +++ b/retroshare-gui/src/gui/gxs/GxsCircleChooser.h @@ -21,17 +21,18 @@ #ifndef _GXS_CIRCLES_CHOOSER_H #define _GXS_CIRCLES_CHOOSER_H -#include +#include "gui/common/RSComboBox.h" + #include -class GxsCircleChooser : public QComboBox +class GxsCircleChooser : public RSComboBox { - Q_OBJECT + Q_OBJECT public: - GxsCircleChooser(QWidget *parent = NULL); + GxsCircleChooser(QWidget *parent = nullptr); - void loadCircles(const RsGxsCircleId &defaultId); + void loadCircles(const RsGxsCircleId &defaultId); bool getChosenCircle(RsGxsCircleId &id); private: diff --git a/retroshare-gui/src/gui/gxs/GxsCommentContainer.cpp b/retroshare-gui/src/gui/gxs/GxsCommentContainer.cpp index b80539cea..5d899104e 100644 --- a/retroshare-gui/src/gui/gxs/GxsCommentContainer.cpp +++ b/retroshare-gui/src/gui/gxs/GxsCommentContainer.cpp @@ -60,7 +60,7 @@ void GxsCommentContainer::commentLoad(const RsGxsGroupId &grpId, const std::set< comments += "..."; } - GxsCommentDialog *commentDialog = new GxsCommentDialog(this, RsGxsId(),getTokenService(), getCommentService()); + GxsCommentDialog *commentDialog = new GxsCommentDialog(this, RsGxsId(),getCommentService()); QWidget *commentHeader = createHeaderWidget(grpId, msgId); commentDialog->setCommentHeader(commentHeader); diff --git a/retroshare-gui/src/gui/gxs/GxsCommentContainer.ui b/retroshare-gui/src/gui/gxs/GxsCommentContainer.ui index bad001d4f..72b64e4e0 100644 --- a/retroshare-gui/src/gui/gxs/GxsCommentContainer.ui +++ b/retroshare-gui/src/gui/gxs/GxsCommentContainer.ui @@ -46,7 +46,14 @@ - + + + + 12 + 75 + true + + Comment Container @@ -87,12 +94,7 @@
    gui/common/RSTabWidget.h
    1
    - - StyledLabel - QLabel -
    gui/common/StyledLabel.h
    -
    -
    + diff --git a/retroshare-gui/src/gui/gxs/GxsCommentDialog.cpp b/retroshare-gui/src/gui/gxs/GxsCommentDialog.cpp index b610f9dd3..afc676bdd 100644 --- a/retroshare-gui/src/gui/gxs/GxsCommentDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsCommentDialog.cpp @@ -29,14 +29,16 @@ #include #include +//#define DEBUG_COMMENT_DIALOG 1 + /** Constructor */ -GxsCommentDialog::GxsCommentDialog(QWidget *parent, const RsGxsId &default_author, RsTokenService *token_service, RsGxsCommentService *comment_service) +GxsCommentDialog::GxsCommentDialog(QWidget *parent, const RsGxsId &default_author, RsGxsCommentService *comment_service) : QWidget(parent), ui(new Ui::GxsCommentDialog) { /* Invoke the Qt Designer generated QObject setup routine */ ui->setupUi(this); - setTokenService(token_service,comment_service); + setGxsService(comment_service); init(default_author); } @@ -67,9 +69,9 @@ void GxsCommentDialog::init(const RsGxsId& default_author) ui->sortBox->setIconSize(QSize(S*1.5,S*1.5)); } -void GxsCommentDialog::setTokenService(RsTokenService *token_service, RsGxsCommentService *comment_service) +void GxsCommentDialog::setGxsService(RsGxsCommentService *comment_service) { - ui->treeWidget->setup(token_service, comment_service); + ui->treeWidget->setup(comment_service); } GxsCommentDialog::GxsCommentDialog(QWidget *parent,const RsGxsId &default_author) @@ -95,8 +97,11 @@ void GxsCommentDialog::commentClear() } void GxsCommentDialog::commentLoad(const RsGxsGroupId &grpId, const std::set& msg_versions,const RsGxsMessageId& most_recent_msgId,bool use_cache) { - std::cerr << "GxsCommentDialog::commentLoad(" << grpId << ", most recent msg version: " << most_recent_msgId << ")"; - std::cerr << std::endl; +#ifdef DEBUG_COMMENT_DIALOG + std::cerr << "GxsCommentDialog::commentLoad(" << grpId << ", most recent msg version: " << most_recent_msgId << ")" << std::endl; + for(const auto& mid:msg_versions) + std::cerr << " msg version: " << mid << std::endl; +#endif mGrpId = grpId; mMostRecentMsgId = most_recent_msgId; @@ -126,15 +131,19 @@ void GxsCommentDialog::idChooserReady() void GxsCommentDialog::voterSelectionChanged( int index ) { +#ifdef DEBUG_COMMENT_DIALOG std::cerr << "GxsCommentDialog::voterSelectionChanged(" << index << ")"; std::cerr << std::endl; +#endif RsGxsId voterId; switch (ui->idChooser->getChosenId(voterId)) { case GxsIdChooser::KnowId: case GxsIdChooser::UnKnowId: - std::cerr << "GxsCommentDialog::voterSelectionChanged() => " << voterId; +#ifdef DEBUG_COMMENT_DIALOG + std::cerr << "GxsCommentDialog::voterSelectionChanged() => " << voterId; std::cerr << std::endl; +#endif ui->treeWidget->setVoteId(voterId); break; @@ -155,8 +164,10 @@ void GxsCommentDialog::setCommentHeader(QWidget *header) return; } - std::cerr << "GxsCommentDialog::setCommentHeader() Adding header to ui,postFrame"; +#ifdef DEBUG_COMMENT_DIALOG + std::cerr << "GxsCommentDialog::setCommentHeader() Adding header to ui,postFrame"; std::cerr << std::endl; +#endif //header->setParent(ui->postFrame); //ui->postFrame->setVisible(true); diff --git a/retroshare-gui/src/gui/gxs/GxsCommentDialog.h b/retroshare-gui/src/gui/gxs/GxsCommentDialog.h index 4be6edede..6a3eee16c 100644 --- a/retroshare-gui/src/gui/gxs/GxsCommentDialog.h +++ b/retroshare-gui/src/gui/gxs/GxsCommentDialog.h @@ -33,10 +33,10 @@ class GxsCommentDialog: public QWidget public: GxsCommentDialog(QWidget *parent=nullptr,const RsGxsId& default_author=RsGxsId()); - GxsCommentDialog(QWidget *parent,const RsGxsId& default_author, RsTokenService *token_service, RsGxsCommentService *comment_service); + GxsCommentDialog(QWidget *parent, const RsGxsId& default_author, RsGxsCommentService *comment_service); virtual ~GxsCommentDialog(); - void setTokenService(RsTokenService *token_service, RsGxsCommentService *comment_service); + void setGxsService(RsGxsCommentService *comment_service); void setCommentHeader(QWidget *header); void commentLoad(const RsGxsGroupId &grpId, const std::set &msg_versions, const RsGxsMessageId &most_recent_msgId, bool use_cache=false); void commentClear(); diff --git a/retroshare-gui/src/gui/gxs/GxsCommentDialog.ui b/retroshare-gui/src/gui/gxs/GxsCommentDialog.ui index 734e490ca..7b50494d6 100644 --- a/retroshare-gui/src/gui/gxs/GxsCommentDialog.ui +++ b/retroshare-gui/src/gui/gxs/GxsCommentDialog.ui @@ -97,7 +97,13 @@
    - + + + + 75 + true + + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -174,15 +180,20 @@
    + + GxsCommentTreeWidget + QTreeWidget +
    gui/gxs/GxsCommentTreeWidget.h
    +
    GxsIdChooser QComboBox
    gui/gxs/GxsIdChooser.h
    - GxsCommentTreeWidget - QTreeWidget -
    gui/gxs/GxsCommentTreeWidget.h
    + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    diff --git a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp index 343f88c91..277b11e4f 100644 --- a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp +++ b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp @@ -21,16 +21,20 @@ #include "GxsCommentTreeWidget.h" #include "gui/common/FilesDefs.h" +#include "gui/Identity/IdDialog.h" +#include "gui/MainWindow.h" #include "gui/common/RSElidedItemDelegate.h" #include "gui/common/RSTreeWidgetItem.h" #include "gui/gxs/GxsCreateCommentDialog.h" #include "gui/gxs/GxsIdTreeWidgetItem.h" +#include "util/qtthreadsutils.h" #include #include #include #include #include +#include #include #include #include @@ -40,6 +44,8 @@ #include +//#define DEBUG_COMMENT_TREE_WIDGET + #define PCITEM_COLUMN_COMMENT 0 #define PCITEM_COLUMN_AUTHOR 1 #define PCITEM_COLUMN_DATE 2 @@ -71,6 +77,7 @@ std::map > GxsCommentTreeWidget::mComm QMutex GxsCommentTreeWidget::mCacheMutex; //#define USE_NEW_DELEGATE 1 +//#define DEBUG_GXSCOMMENT_TREEWIDGET 1 // This class allows to draw the item using an appropriate size @@ -247,7 +254,7 @@ void GxsCommentTreeWidget::mouseMoveEvent(QMouseEvent *e) } GxsCommentTreeWidget::GxsCommentTreeWidget(QWidget *parent) - :QTreeWidget(parent), mTokenQueue(NULL), mRsTokenService(NULL), mCommentService(NULL) + :QTreeWidget(parent), mCommentService(NULL) { setVerticalScrollMode(ScrollPerPixel); setContextMenuPolicy(Qt::CustomContextMenu); @@ -297,9 +304,6 @@ void GxsCommentTreeWidget::updateContent() } GxsCommentTreeWidget::~GxsCommentTreeWidget() { - if (mTokenQueue) { - delete(mTokenQueue); - } } void GxsCommentTreeWidget::setCurrentCommentMsgId(QTreeWidgetItem *current, QTreeWidgetItem *previous) @@ -344,6 +348,10 @@ void GxsCommentTreeWidget::customPopUpMenu(const QPoint& point) action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_VOTEDOWN), tr("Vote Down"), this, SLOT(voteDown())); action->setDisabled(!item || mCurrentCommentMsgId.isNull() || mVoterId.isNull()); + contextMnu.addSeparator(); + + action = contextMnu.addAction(tr("Show Author"), this, SLOT(showAuthor())); + action->setDisabled(!item || mCurrentCommentMsgId.isNull() || mVoterId.isNull()); if (!mCurrentCommentMsgId.isNull()) { @@ -401,35 +409,23 @@ void GxsCommentTreeWidget::setVoteId(const RsGxsId &voterId) void GxsCommentTreeWidget::vote(const RsGxsGroupId &groupId, const RsGxsMessageId &threadId, const RsGxsMessageId &parentId, const RsGxsId &authorId, bool up) { - RsGxsVote vote; + RsThread::async([this,groupId,threadId,parentId,authorId,up]() + { + std::string error_string; + RsGxsMessageId vote_id; + RsGxsVoteType tvote = up?(RsGxsVoteType::UP):(RsGxsVoteType::DOWN); - vote.mMeta.mGroupId = groupId; - vote.mMeta.mThreadId = threadId; - vote.mMeta.mParentId = parentId; - vote.mMeta.mAuthorId = authorId; + bool res = mCommentService->voteForComment(groupId, threadId, parentId, authorId,tvote,vote_id, error_string); - if (up) - { - vote.mVoteType = GXS_VOTE_UP; - } - else - { - vote.mVoteType = GXS_VOTE_DOWN; - } + RsQThreadUtils::postToObject( [this,res,error_string]() + { -#ifdef DEBUG_GXSCOMMENT_TREEWIDGET - std::cerr << "GxsCommentTreeWidget::vote()"; - std::cerr << std::endl; - - std::cerr << "GroupId : " << vote.mMeta.mGroupId << std::endl; - std::cerr << "ThreadId : " << vote.mMeta.mThreadId << std::endl; - std::cerr << "ParentId : " << vote.mMeta.mParentId << std::endl; - std::cerr << "AuthorId : " << vote.mMeta.mAuthorId << std::endl; -#endif - - uint32_t token; - mCommentService->createNewVote(token, vote); - mTokenQueue->queueRequest(token, TOKENREQ_MSGINFO, RS_TOKREQ_ANSTYPE_ACK, COMMENT_VOTE_ACK); + if(res) + service_requestComments(mGroupId,mMsgVersions); + else + QMessageBox::critical(nullptr,tr("Cannot vote"),tr("Error while voting: ")+QString::fromStdString(error_string)); + }); + }); } @@ -474,22 +470,29 @@ void GxsCommentTreeWidget::replyToComment() pcc.exec(); } + +void GxsCommentTreeWidget::showAuthor() +{ + /* window will destroy itself! */ + IdDialog *idDialog = dynamic_cast(MainWindow::getPage(MainWindow::People)); + + if (!idDialog) + return ; + + MainWindow::showWindow(MainWindow::People); + idDialog->navigate(RsGxsId(mCurrentCommentAuthorId)); +} + void GxsCommentTreeWidget::copyComment() { QString txt = dynamic_cast(sender())->data().toString(); - - QMimeData *mimeData = new QMimeData(); - mimeData->setHtml(""+txt+""); - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setMimeData(mimeData, QClipboard::Clipboard); + QApplication::clipboard()->setText(txt) ; } -void GxsCommentTreeWidget::setup(RsTokenService *token_service, RsGxsCommentService *comment_service) +void GxsCommentTreeWidget::setup(RsGxsCommentService *comment_service) { - mRsTokenService = token_service; mCommentService = comment_service; - mTokenQueue = new TokenQueue(token_service, this); - connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customPopUpMenu(QPoint))); + connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customPopUpMenu(QPoint))); connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(setCurrentCommentMsgId(QTreeWidgetItem*, QTreeWidgetItem*))); return; @@ -527,27 +530,84 @@ void GxsCommentTreeWidget::service_requestComments(const RsGxsGroupId& group_id, /* request comments */ #ifdef DEBUG_GXSCOMMENT_TREEWIDGET std::cerr << "GxsCommentTreeWidget::service_requestComments for group " << group_id << std::endl; + for(const auto& mid:msgIds) + std::cerr << " including message " << mid << std::endl; #endif - std::vector ids_to_ask; - - for(std::set::const_iterator it(msgIds.begin());it!=msgIds.end();++it) + RsThread::async([this,group_id,msgIds]() { -#ifdef DEBUG_GXSCOMMENT_TREEWIDGET - std::cerr << " asking for msg " << *it << std::endl; -#endif + std::vector comments; - ids_to_ask.push_back(std::make_pair(group_id,*it)); - } + if(!mCommentService->getRelatedComments(group_id,msgIds,comments)) + { + std::cerr << __PRETTY_FUNCTION__ << " failed to get comments" << std::endl; + return; + } - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; - opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST; + RsQThreadUtils::postToObject( [this,comments]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete, note that + * Qt::QueuedConnection is important! + */ - uint32_t token; - mTokenQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, ids_to_ask, GXSCOMMENTS_LOADTHREAD); + clearItems(); + + service_loadThread(comments); + + completeItems(); + + emit commentsLoaded(treeCount(this)); + + }, this ); + }); } +#ifdef TODO +void GxsCommentTreeWidget::async_msg_action(const CmtMethod &action) +{ + RsThread::async([this,action]() + { + // 1 - get message data from p3GxsForums + + std::set msgs_to_request ; + std::vector msgs; + + msgs_to_request.insert(mThreadId); + + if(!rsGxsForums->getForumContent(groupId(),msgs_to_request,msgs)) + { + std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve forum message info for forum " << groupId() << " and thread " << mThreadId << std::endl; + return; + } + + if(msgs.size() != 1) + { + std::cerr << __PRETTY_FUNCTION__ << " more than 1 or no msgs selected in forum " << groupId() << std::endl; + return; + } + + // 2 - sort the messages into a proper hierarchy + + RsGxsForumMsg msg = msgs[0]; + + // 3 - update the model in the UI thread. + + RsQThreadUtils::postToObject( [msg,action,this]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete */ + + (this->*action)(msg); + + }, this ); + + }); +} +#endif + /* Generic Handling */ void GxsCommentTreeWidget::clearItems() @@ -673,7 +733,7 @@ void GxsCommentTreeWidget::addItem(RsGxsMessageId itemId, RsGxsMessageId parentI } } -int treeCount(QTreeWidget *tree, QTreeWidgetItem *parent = 0) +int GxsCommentTreeWidget::treeCount(QTreeWidget *tree, QTreeWidgetItem *parent) { int count = 0; if (parent == 0) @@ -694,45 +754,11 @@ int treeCount(QTreeWidget *tree, QTreeWidgetItem *parent = 0) } return count; } -void GxsCommentTreeWidget::loadThread(const uint32_t &token) + +void GxsCommentTreeWidget::service_loadThread(const std::vector& comments) { - clearItems(); - - service_loadThread(token); - - completeItems(); - - emit commentsLoaded(treeCount(this)); -} - -void GxsCommentTreeWidget::acknowledgeComment(const uint32_t &token) -{ - RsGxsGrpMsgIdPair msgId; - mCommentService->acknowledgeComment(token, msgId); - - // simply reload data - service_requestComments(mGroupId,mMsgVersions); -} - - -void GxsCommentTreeWidget::acknowledgeVote(const uint32_t &token) -{ - RsGxsGrpMsgIdPair msgId; - if (mCommentService->acknowledgeVote(token, msgId)) - { - // reload data if vote was added. - service_requestComments(mGroupId,mMsgVersions); - } -} - - -void GxsCommentTreeWidget::service_loadThread(const uint32_t &token) -{ - std::cerr << "GxsCommentTreeWidget::service_loadThread() ERROR must be overloaded!"; - std::cerr << std::endl; - - std::vector comments; - mCommentService->getRelatedComments(token, comments); + std::cerr << "GxsCommentTreeWidget::service_loadThread() ERROR must be overloaded!"; + std::cerr << std::endl; // This is inconsistent since we cannot know here that all comments are for the same thread. However they are only // requested in requestComments() where a single MsgId is used. @@ -763,8 +789,10 @@ void GxsCommentTreeWidget::insertComments(const std::vector& comme new_comments.push_back(comment.mMeta.mMsgId); /* convert to a QTreeWidgetItem */ +#ifdef DEBUG_COMMENT_TREE_WIDGET std::cerr << "GxsCommentTreeWidget::service_loadThread() Got Comment: " << comment.mMeta.mMsgId; std::cerr << std::endl; +#endif GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(NULL,GxsIdDetails::ICON_TYPE_AVATAR) ; QString text; @@ -821,10 +849,7 @@ void GxsCommentTreeWidget::insertComments(const std::vector& comme // now set all loaded comments as not new, since they have been loaded. for(auto cid:new_comments) - { - uint32_t token=0; - mCommentService->setCommentAsRead(token,mGroupId,cid); - } + mCommentService->setCommentReadStatus(RsGxsGrpMsgIdPair(mGroupId,cid),true); } QTreeWidgetItem *GxsCommentTreeWidget::service_createMissingItem(const RsGxsMessageId& parent) @@ -852,50 +877,3 @@ QTreeWidgetItem *GxsCommentTreeWidget::service_createMissingItem(const RsGxsMess return item; } - - -void GxsCommentTreeWidget::loadRequest(const TokenQueue *queue, const TokenRequest &req) -{ -#ifdef DEBUG_GXSCOMMENT_TREEWIDGET - std::cerr << "GxsCommentTreeWidget::loadRequest() UserType: " << req.mUserType; - std::cerr << std::endl; -#endif - - if (queue != mTokenQueue) - { - std::cerr << "GxsCommentTreeWidget::loadRequest() Queue ERROR"; - std::cerr << std::endl; - return; - } - - /* now switch on req */ - switch(req.mType) - { - - case TOKENREQ_MSGINFO: - { - switch(req.mAnsType) - { - case RS_TOKREQ_ANSTYPE_ACK: - if (req.mUserType == COMMENT_VOTE_ACK) - { - acknowledgeVote(req.mToken); - } - else - { - acknowledgeComment(req.mToken); - } - break; - case RS_TOKREQ_ANSTYPE_DATA: - loadThread(req.mToken); - break; - } - } - break; - default: - std::cerr << "GxsCommentTreeWidget::loadRequest() UNKNOWN UserType "; - std::cerr << std::endl; - break; - - } -} diff --git a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.h b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.h index c4840eb46..5f52459a9 100644 --- a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.h +++ b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.h @@ -24,26 +24,24 @@ #include #include -#include "util/TokenQueue.h" #include #include class RSTreeWidgetItemCompareRole; -class GxsCommentTreeWidget : public QTreeWidget, public TokenResponse +class GxsCommentTreeWidget : public QTreeWidget { Q_OBJECT public: GxsCommentTreeWidget(QWidget *parent = 0); ~GxsCommentTreeWidget(); - void setup(RsTokenService *token_service, RsGxsCommentService *comment_service); + void setup(RsGxsCommentService *comment_service); void requestComments(const RsGxsGroupId& group, const std::set &message_versions, const RsGxsMessageId &most_recent_message); void getCurrentMsgId(RsGxsMessageId& parentId); void applyRankings(std::map& positions); - void loadRequest(const TokenQueue *queue, const TokenRequest &req); void setVoteId(const RsGxsId &voterId); void setUseCache(bool b) { mUseCache = b ;} @@ -56,20 +54,17 @@ protected: /* to be overloaded */ virtual void service_requestComments(const RsGxsGroupId &group_id, const std::set &msgIds); - virtual void service_loadThread(const uint32_t &token); + virtual void service_loadThread(const std::vector& comments); virtual QTreeWidgetItem *service_createMissingItem(const RsGxsMessageId& parent); void clearItems(); void completeItems(); - void acknowledgeComment(const uint32_t& token); - void acknowledgeVote(const uint32_t &token); - - void loadThread(const uint32_t &token); - void insertComments(const std::vector& comments); void addItem(RsGxsMessageId itemId, RsGxsMessageId parentId, QTreeWidgetItem *item); + + static int treeCount(QTreeWidget *tree, QTreeWidgetItem *parent = 0); public slots: void customPopUpMenu(const QPoint& point); void setCurrentCommentMsgId(QTreeWidgetItem* current, QTreeWidgetItem* previous); @@ -77,6 +72,7 @@ public slots: void makeComment(); void replyToComment(); + void showAuthor(); void copyComment(); @@ -112,8 +108,6 @@ protected: RSTreeWidgetItemCompareRole *commentsRole; - TokenQueue *mTokenQueue; - RsTokenService *mRsTokenService; RsGxsCommentService *mCommentService; bool mUseCache; diff --git a/retroshare-gui/src/gui/gxs/GxsCreateCommentDialog.cpp b/retroshare-gui/src/gui/gxs/GxsCreateCommentDialog.cpp index 3dacc3e6c..6585941c4 100644 --- a/retroshare-gui/src/gui/gxs/GxsCreateCommentDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsCreateCommentDialog.cpp @@ -51,8 +51,8 @@ void GxsCreateCommentDialog::loadComment(const QString &msgText, const QString & ui->avatarLabel->setGxsId(msgAuthorId); ui->avatarLabel->setFrameType(AvatarWidget::NO_FRAME); - ui->replaytolabel->setId(msgAuthorId); - ui->replaytolabel->setText( tr("Replying to") + " @" + msgAuthor); + ui->replyToLabel->setId(msgAuthorId); + ui->replyToLabel->setText( tr("Replying to") + " @" + msgAuthor); ui->commentTextEdit->setPlaceholderText( tr("Type your reply")); ui->postButton->setText("Reply"); @@ -99,7 +99,6 @@ void GxsCreateCommentDialog::createComment() return; } - uint32_t token; mCommentService->createComment(comment); close(); } @@ -116,11 +115,11 @@ void GxsCreateCommentDialog::checkLength(){ int charRemains = MAX_ALLOWED_GXS_MESSAGE_SIZE - msg.length(); if(charRemains >= 0) { text = tr("It remains %1 characters after HTML conversion.").arg(charRemains); - ui->infoLabel->setStyleSheet("QLabel#infoLabel { }"); + ui->info_Label->setStyleSheet("QLabel#info_Label { }"); }else{ text = tr("Warning: This message is too big of %1 characters after HTML conversion.").arg((0-charRemains)); - ui->infoLabel->setStyleSheet("QLabel#infoLabel {color: red; font: bold; }"); + ui->info_Label->setStyleSheet("QLabel#info_Label {color: red; font: bold; }"); } ui->postButton->setEnabled(charRemains>=0); - ui->infoLabel->setText(text); + ui->info_Label->setText(text); } diff --git a/retroshare-gui/src/gui/gxs/GxsCreateCommentDialog.h b/retroshare-gui/src/gui/gxs/GxsCreateCommentDialog.h index 1f38e2a98..4a21c6457 100644 --- a/retroshare-gui/src/gui/gxs/GxsCreateCommentDialog.h +++ b/retroshare-gui/src/gui/gxs/GxsCreateCommentDialog.h @@ -25,7 +25,6 @@ #include #include "retroshare/rsgxscommon.h" -#include "util/TokenQueue.h" namespace Ui { class GxsCreateCommentDialog; diff --git a/retroshare-gui/src/gui/gxs/GxsCreateCommentDialog.ui b/retroshare-gui/src/gui/gxs/GxsCreateCommentDialog.ui index 9a40b6f4a..aecd1b794 100644 --- a/retroshare-gui/src/gui/gxs/GxsCreateCommentDialog.ui +++ b/retroshare-gui/src/gui/gxs/GxsCreateCommentDialog.ui @@ -7,13 +7,13 @@ 0 0 505 - 367 + 406 Make Comment - + 0 @@ -30,7 +30,7 @@ 0 - + 0 @@ -58,9 +58,9 @@ QFrame::Raised - + - + 52 @@ -73,16 +73,24 @@ 52 - + - + true + + + 11 + 75 + true + true + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -121,7 +129,7 @@ p, li { white-space: pre-wrap; } - + Qt::Vertical @@ -138,12 +146,12 @@ p, li { white-space: pre-wrap; } - + 6 - + Qt::Horizontal @@ -176,14 +184,14 @@ p, li { white-space: pre-wrap; } - + TextLabel - + @@ -208,21 +216,31 @@ p, li { white-space: pre-wrap; } + + + 12 + 75 + true + + Post - + 0 0 - - + + + 75 + true + @@ -240,6 +258,12 @@ p, li { white-space: pre-wrap; } QLabel
    gui/gxs/GxsIdLabel.h
    + + AvatarWidget + QWidget +
    gui/common/AvatarWidget.h
    + 1 +
    GxsIdChooser QComboBox @@ -250,12 +274,6 @@ p, li { white-space: pre-wrap; } QTextEdit
    gui/common/MimeTextEdit.h
    - - AvatarWidget - QLabel -
    gui/common/AvatarWidget.h
    - 1 -
    diff --git a/retroshare-gui/src/gui/gxs/GxsFeedItem.h b/retroshare-gui/src/gui/gxs/GxsFeedItem.h index c7c16ea79..bc75d1837 100644 --- a/retroshare-gui/src/gui/gxs/GxsFeedItem.h +++ b/retroshare-gui/src/gui/gxs/GxsFeedItem.h @@ -52,11 +52,6 @@ protected: //virtual bool isLoading(); //virtual void fillDisplay(RsGxsUpdateBroadcastBase *updateBroadcastBase, bool complete); -#ifdef TO_REMOVE - /* TokenResponse */ - virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); -#endif - protected slots: void comments(const QString &title); void copyMessageLink(); diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp index ff1919403..5afb5414b 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp @@ -92,7 +92,7 @@ GxsGroupDialog::~GxsGroupDialog() void GxsGroupDialog::init() { // connect up the buttons. - connect(ui.createButton, SIGNAL(clicked()), this, SLOT(submitGroup())); + connect(ui.postButton, SIGNAL(clicked()), this, SLOT(submitGroup())); connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(cancelDialog())); connect(ui.pubKeyShare_cb, SIGNAL(clicked()), this, SLOT(setShareList())); connect(ui.addAdmins_cb, SIGNAL(clicked()), this, SLOT(setAdminsList())); @@ -194,7 +194,7 @@ void GxsGroupDialog::setUiText(UiType uiType, const QString &text) //ui.contactsdockWidget->setWindowTitle(text); break; case UITYPE_BUTTONBOX_OK: - ui.createButton->setText(text); + ui.postButton->setText(text); break; } } @@ -210,7 +210,7 @@ void GxsGroupDialog::setUiToolTip(UiType uiType, const QString &text) ui.addAdmins_cb->setToolTip(text); break; case UITYPE_BUTTONBOX_OK: - ui.createButton->setToolTip(text); + ui.postButton->setToolTip(text); default: break; } @@ -232,14 +232,14 @@ void GxsGroupDialog::initMode() { ui.stackedWidget->setCurrentIndex(1); mReadonlyFlags = 0xffffffff; // Force all to readonly. - ui.createButton->hide(); + ui.postButton->hide(); } break; case MODE_EDIT: { ui.stackedWidget->setCurrentIndex(0); - ui.createButton->setText(tr("Submit Group Changes")); + ui.postButton->setText(tr("Submit Group Changes")); } break; } @@ -370,7 +370,7 @@ void GxsGroupDialog::setupVisibility() ui.groupLogo->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_ICON); - ui.groupDesc->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_DESCRIPTION); + ui.groupBox->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_DESCRIPTION); ui.distribGroupBox->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_DISTRIBUTION); ui.distributionLabel->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_DISTRIBUTION); @@ -384,8 +384,8 @@ void GxsGroupDialog::setupVisibility() ui.pubKeyShare_cb->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_SHAREKEYS); ui.addAdmins_cb->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_ADDADMINS); - ui.label_8->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_ADDADMINS); ui.moderatorsLabel->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_ADDADMINS); + ui.moderatorsValueLabel->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_ADDADMINS); ui.personalGroupBox->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_PERSONALSIGN); @@ -410,11 +410,8 @@ void GxsGroupDialog::setupReadonly() { ui.publishGroupBox->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_PUBLISHSIGN)); - ui.pubKeyShare_cb->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_SHAREKEYS)); - ui.personalGroupBox->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_PERSONALSIGN)); - ui.idChooser->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_PERSONALSIGN)); //ui.distribGroupBox_2->setEnabled(!(mReadonlyFlags & GXS_GROUP_FLAGS_DISTRIBUTION)); @@ -465,12 +462,14 @@ void GxsGroupDialog::updateFromExistingMeta(const QString &description) ui.lastpostline->setText(tr("Never")); else ui.lastpostline->setText(DateTime::formatLongDateTime(mGrpMeta.mLastPost)); - ui.authorLabel->setId(mGrpMeta.mAuthorId); + ui.authorValueLabel->setId(mGrpMeta.mAuthorId); ui.createdline->setText(DateTime::formatLongDateTime(mGrpMeta.mPublishTs)); link = RetroShareLink::createMessage(mGrpMeta.mAuthorId, ""); - ui.authorLabel->setText(link.toHtml()); + + if(!mGrpMeta.mAuthorId.isNull()) + ui.authorValueLabel->setText(link.toHtml()); ui.IDline->setText(QString::fromStdString(mGrpMeta.mGroupId.toStdString())); ui.descriptiontextEdit->setPlainText(description); @@ -673,15 +672,9 @@ void GxsGroupDialog::createGroup() if (service_createGroup(meta)) { - // now update the UI #warning Missing code here! -#ifdef TODO - // - // get the Queue to handle response. What is this for? - if(mExternalTokenQueue != NULL) - mExternalTokenQueue->queueRequest(token, TOKENREQ_GROUPINFO, RS_TOKREQ_ANSTYPE_ACK, GXSGROUP_NEWGROUPID); -#endif - } + // now update the UI + } close(); } @@ -721,55 +714,57 @@ uint32_t GxsGroupDialog::getGroupSignFlags() void GxsGroupDialog::setGroupSignFlags(uint32_t signFlags) { - if (signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_ENCRYPTED) { - ui.publish_encrypt->setChecked(true); - } else if (signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_ALLSIGNED) { - ui.publish_required->setChecked(true); - } else if (signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_THREADHEAD) { - ui.publish_threads->setChecked(true); - } else if (signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ) { - ui.publish_open->setChecked(true); - } + if (signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_ENCRYPTED) + ui.publish_encrypt->setChecked(true); + else if (signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_ALLSIGNED) + ui.publish_required->setChecked(true); + else if (signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_THREADHEAD) + ui.publish_threads->setChecked(true); + else if (signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ) + ui.publish_open->setChecked(true); - if (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED) - ui.personal_required->setChecked(true); - - if (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN) - ui.personal_ifnopub->setChecked(true); - - if( (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN) && (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG)) - ui.antiSpam_perms_CB->setCurrentIndex(2) ; - else if(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) - ui.antiSpam_perms_CB->setCurrentIndex(1) ; - else - ui.antiSpam_perms_CB->setCurrentIndex(0) ; - - QString antispam_string ; - if(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) antispam_string += tr("Message tracking") ; - if(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN) antispam_string += (antispam_string.isNull()?"":" and ")+tr("PGP signature from known ID required") ; - else - if(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) antispam_string += (antispam_string.isNull()?"":" and ")+tr("PGP signature required") ; - - ui.antiSpamValueLabel->setText(antispam_string) ; - //ui.antiSpam_trackMessages_2->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) ); - //ui.antiSpam_signedIds_2 ->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) ); - //ui.SignEdIds->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) ); - //ui.trackmessagesradioButton->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) ); - - /* guess at comments */ - if ((signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_THREADHEAD) && - (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN)) - { - // (cyril) very weird piece of code. Need to clear this up. - - ui.comments_allowed->setChecked(true); - ui.commentsValueLabel->setText("Allowed") ; - } - else - { - ui.comments_no->setChecked(true); - ui.commentsValueLabel->setText("Forbidden") ; - } + + if (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED) + ui.personal_required->setChecked(true); + + if (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN) + ui.personal_ifnopub->setChecked(true); + + if( (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN) && (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG)) + ui.antiSpam_perms_CB->setCurrentIndex(2) ; + else if(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) + ui.antiSpam_perms_CB->setCurrentIndex(1) ; + else + ui.antiSpam_perms_CB->setCurrentIndex(0) ; + + QString antispam_string ; + if(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) antispam_string += tr("Message tracking") ; + if(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN) antispam_string += (antispam_string.isNull()?"":" and ")+tr("PGP signature from known ID required") ; + else if(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) antispam_string += (antispam_string.isNull()?"":" and ")+tr("PGP signature required") ; + + if(antispam_string.isNull()) + antispam_string = tr("[None]"); + + ui.antiSpamValueLabel->setText(antispam_string) ; + //ui.antiSpam_trackMessages_2->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) ); + //ui.antiSpam_signedIds_2 ->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) ); + //ui.SignEdIds->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) ); + //ui.trackmessagesradioButton->setChecked((bool)(signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) ); + + /* guess at comments */ + if ((signFlags & GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_THREADHEAD) && + (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN)) + { + // (cyril) very weird piece of code. Need to clear this up. + + ui.comments_allowed->setChecked(true); + ui.commentsValueLabel->setText("Allowed") ; + } + else + { + ui.comments_no->setChecked(true); + ui.commentsValueLabel->setText("Forbidden") ; + } } /**** Above logic is flawed, and will be removed shortly @@ -894,7 +889,7 @@ void GxsGroupDialog::setSelectedModerators(const std::set& ids) ui.adminsList->show(); ui.filtercomboBox->show(); - ui.adminsList->setSelectedIds(ids, false); + ui.adminsList->setSelectedIds(ids, true); QString moderatorsListString ; RsIdentityDetails det; @@ -915,8 +910,11 @@ void GxsGroupDialog::setSelectedModerators(const std::set& ids) moderatorsListString += link.toHtml() + " "; } - //ui.moderatorsLabel->setId(det.mId); - ui.moderatorsLabel->setText(moderatorsListString); + + if(moderatorsListString.isNull()) + moderatorsListString = tr("[None]"); + + ui.moderatorsValueLabel->setText(moderatorsListString); } /*********************************************************************************** diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.h b/retroshare-gui/src/gui/gxs/GxsGroupDialog.h index 4860f52a8..b5e9417d0 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupDialog.h +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.h @@ -23,8 +23,6 @@ #include "ui_GxsGroupDialog.h" -#include "util/TokenQueue.h" - /******** * Notes: * @@ -284,9 +282,6 @@ private: std::list mShareList; QPixmap mPicture; - RsTokenService *mTokenService; - TokenQueue *mExternalTokenQueue; - TokenQueue *mInternalTokenQueue; RsGroupMetaData mGrpMeta; Mode mMode; diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui b/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui index e6da1441e..867652e01 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui @@ -6,14 +6,14 @@ 0 0 - 701 - 529 + 746 + 533
    Create New - + 0 @@ -44,10 +44,10 @@ QFrame::Raised
    - 0 + 1 - + 0 @@ -59,7 +59,7 @@ - + 3 @@ -98,7 +98,7 @@
    - + 6 @@ -106,7 +106,7 @@ 6
    - + Name @@ -118,7 +118,7 @@
    - + Qt::Horizontal @@ -131,7 +131,7 @@ - + <html><head/><body><p>The identity here can be used to send feedback.</p></body></html> @@ -178,7 +178,7 @@ Description - + @@ -190,7 +190,7 @@ Publish Signatures - + 6 @@ -235,7 +235,7 @@ - + Qt::Horizontal @@ -255,7 +255,7 @@ Personal Signatures - + @@ -278,7 +278,7 @@ - + Qt::Horizontal @@ -298,7 +298,7 @@ Comments - + 6 @@ -329,7 +329,7 @@
    - + Qt::Horizontal @@ -349,16 +349,16 @@ Spam-protection - + - + Posts permissions: - + <html><head/><body><p>This combo box allows you to choose how posts are handled depending on the node the poster belongs to.</p><p><span style=" font-weight:600;">All allowed</span>: all posts are treated equally.</p><p><span style=" font-weight:600;">Defavor posts from unsigned IDs</span>: anonymous IDs will require a reputation of 0.4 to be received/forwarded.</p><p><span style=" font-weight:600;">Defavor posts from unsigned IDs and IDs from unknown nodes</span>: anonymous IDs and IDs signed by unknown Retroshare nodes will require a reputation of 0.4 to be received/forwarded.</p></body></html> @@ -380,7 +380,7 @@ - + Qt::Horizontal @@ -406,9 +406,9 @@
    - + - + @@ -426,7 +426,7 @@ Message Distribution - + 6 @@ -532,20 +532,7 @@ - - - Qt::Horizontal - - - - 0 - 17 - - - - - - + Qt::Horizontal @@ -563,205 +550,217 @@
    - + 0 - + Info - - - - - - - Author - - - - - - - Last Post - - - - - - - Name - - - - - - - Popularity - - - - - + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Author: + + + + + + + Last Post + + + + + + + Name + + + + + + + Popularity + + + + + + + TextLabel + + + + + + + Anti Spam: + + + + + + + true + + + + + + + TextLabel + + + true + + + + + + + Comments: + + + + + + + GxsIdLabel + + + true + + + + + + + ID + + + + + + + true + + + + + + + Posts + + + + + + + + + + true + + + + + + + TextLabel - - - - Anti Spam: - - - - - - - true - - - - - - - TextLabel - - - true - - - - - - - Comments: - - - - - - - GxsIdLabel - - - true - - - - - - - ID - - - - - - - true - - - - - - - Posts - - - - - - - - - - true - - - - - - - - - TextLabel - - - - - - - - 0 - 0 - - - - - - - - - - Distribution: - - - - - - - true - - - - - - - true - - - - - - - Moderators: - - - - - - - TextLabel - - - true - - - - - - - - - - Created + + + + + 0 + 0 + + + + + Distribution: + + + + + + + true + + + + + + + true + + + + + + + Moderators: + + + + + + + TextLabel + + + true + + + + + + + true + + + + + + + Created + + + - + Description - + @@ -777,14 +776,14 @@ - + QFrame::StyledPanel QFrame::Raised - + @@ -793,7 +792,7 @@ - + Qt::Horizontal @@ -806,7 +805,14 @@ - + + + + 12 + 75 + true + + Create @@ -824,20 +830,14 @@
    gui/gxs/GxsIdLabel.h
    - GxsIdChooser + RSComboBox QComboBox -
    gui/gxs/GxsIdChooser.h
    +
    gui/common/RSComboBox.h
    - GxsCircleChooser - QComboBox -
    gui/gxs/GxsCircleChooser.h
    -
    - - HeaderFrame - QFrame -
    gui/common/HeaderFrame.h
    - 1 + ClickableLabel + QLabel +
    util/ClickableLabel.h
    FriendSelectionWidget @@ -845,20 +845,31 @@
    gui/common/FriendSelectionWidget.h
    1
    - - MimeTextEdit - QTextEdit -
    gui/common/MimeTextEdit.h
    -
    GroupChooser QComboBox
    gui/common/GroupChooser.h
    - ClickableLabel - QLabel -
    util/ClickableLabel.h
    + GxsCircleChooser + QComboBox +
    gui/gxs/GxsCircleChooser.h
    +
    + + GxsIdChooser + QComboBox +
    gui/gxs/GxsIdChooser.h
    +
    + + HeaderFrame + QFrame +
    gui/common/HeaderFrame.h
    + 1 +
    + + MimeTextEdit + QTextEdit +
    gui/common/MimeTextEdit.h
    diff --git a/retroshare-gui/src/gui/gxs/GxsGroupFeedItem.cpp b/retroshare-gui/src/gui/gxs/GxsGroupFeedItem.cpp index fb530a3ef..b4fe2273f 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupFeedItem.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupFeedItem.cpp @@ -31,7 +31,7 @@ * #define DEBUG_ITEM 1 **/ -GxsGroupFeedItem::GxsGroupFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, RsGxsIfaceHelper *iface, bool autoUpdate) : +GxsGroupFeedItem::GxsGroupFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, RsGxsIfaceHelper *iface, bool /*autoUpdate*/) : FeedItem(feedHolder,feedId,NULL) { #ifdef DEBUG_ITEM @@ -102,7 +102,7 @@ void GxsGroupFeedItem::copyGroupLink() } } -void GxsGroupFeedItem::fillDisplaySlot(bool complete) +void GxsGroupFeedItem::fillDisplaySlot(bool /*complete*/) { requestGroup(); } diff --git a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp index 963b3a8ad..069c51b79 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp @@ -42,13 +42,11 @@ /* Images for TreeWidget */ #define IMAGE_SUBSCRIBE ":/images/edit_add24.png" -#define IMAGE_UNSUBSCRIBE ":/images/cancel.png" +#define IMAGE_UNSUBSCRIBE ":/icons/cancel.svg" #define IMAGE_INFO ":/images/info16.png" -//#define IMAGE_GROUPAUTHD ":/images/konv_message2.png" #define IMAGE_COPYLINK ":/images/copyrslink.png" #define IMAGE_EDIT ":/icons/png/pencil-edit-button.png" -#define IMAGE_SHARE ":/images/share-icon-16.png" -#define IMAGE_TABNEW ":/images/tab-new.png" +#define IMAGE_TABNEW ":/icons/newtab.svg" #define IMAGE_DELETE ":/images/delete.png" #define IMAGE_RETRIEVE ":/images/edit_add24.png" #define IMAGE_COMMENT "" @@ -72,8 +70,8 @@ static const uint32_t DELAY_BETWEEN_GROUP_STATISTICS_UPDATE = 120; // do not upd */ /** Constructor */ -GxsGroupFrameDialog::GxsGroupFrameDialog(RsGxsIfaceHelper *ifaceImpl, QWidget *parent,bool allow_dist_sync) -: MainPage(parent) +GxsGroupFrameDialog::GxsGroupFrameDialog(RsGxsIfaceHelper *ifaceImpl,const QString& settings_name, QWidget *parent,bool allow_dist_sync) +: MainPage(parent),mSettingsName(settings_name) { /* Invoke the Qt Designer generated object setup routine */ ui = new Ui::GxsGroupFrameDialog(); @@ -121,6 +119,9 @@ GxsGroupFrameDialog::GxsGroupFrameDialog(RsGxsIfaceHelper *ifaceImpl, QWidget *p sizes << 300 << width(); // Qt calculates the right sizes ui->splitter->setSizes(sizes); + // load settings + processSettings(true); + #ifndef UNFINISHED ui->todoPushButton->hide(); #endif @@ -168,7 +169,6 @@ void GxsGroupFrameDialog::initUi() } // load settings - mSettingsName = settingsGroupName(); processSettings(true); if (groupFrameSettingsType() != GroupFrameSettings::Nothing) { @@ -466,7 +466,9 @@ void GxsGroupFrameDialog::groupTreeCustomPopupMenu(QPoint point) uint32_t current_store_time = checkDelay(mInterface->getStoragePeriod(mGroupId))/86400 ; uint32_t current_sync_time = checkDelay(mInterface->getSyncPeriod(mGroupId))/86400 ; +#ifdef DEBUG_GROUPFRAMEDIALOG std::cerr << "Got sync=" << current_sync_time << ". store=" << current_store_time << std::endl; +#endif QAction *actnn = NULL; QMenu *ctxMenu2 = contextMnu.addMenu(tr("Synchronise posts of last...")) ; @@ -490,7 +492,7 @@ void GxsGroupFrameDialog::groupTreeCustomPopupMenu(QPoint point) ctxMenu2->setEnabled(isSubscribed); if (shareKeyType()) { - action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_SHARE), tr("Share publish permissions..."), this, SLOT(sharePublishKey())); + action = contextMnu.addAction(QIcon(""), tr("Share publish permissions..."), this, SLOT(sharePublishKey())); action->setEnabled(!mGroupId.isNull() && isPublisher); } @@ -726,7 +728,7 @@ void GxsGroupFrameDialog::loadComment(const RsGxsGroupId &grpId, const QVectorgetTokenService(), commentService); + commentDialog = new GxsCommentDialog(this,RsGxsId(), commentService); QWidget *commentHeader = createCommentHeaderWidget(grpId, most_recent_msgId); if (commentHeader) { @@ -1105,7 +1107,12 @@ void GxsGroupFrameDialog::updateGroupSummary() * Qt::QueuedConnection is important! */ - insertGroupsData(*groupInfo); + // Here we save the focus, and restore it afterwards: there's no need to grab the focus here and + // if we do, it may harm the navitation in forums, channels, boards, etc. + + auto w = QApplication::focusWidget(); + + insertGroupsData(*groupInfo); updateSearchResults(); mStateHelper->setLoading(TOKEN_TYPE_GROUP_SUMMARY, false); @@ -1132,7 +1139,12 @@ void GxsGroupFrameDialog::updateGroupSummary() delete groupInfo; - }, this ); + // Restore the focus. + + if(w) + w->setFocus(); + + }, this ); }); } @@ -1165,35 +1177,64 @@ void GxsGroupFrameDialog::updateGroupStatisticsReal(const RsGxsGroupId &groupId) * Qt::QueuedConnection is important! */ - QTreeWidgetItem *item = ui->groupTreeWidget->getItemFromId(QString::fromStdString(stats.mGrpId.toStdString())); - if (!item) - return; + QTreeWidgetItem *item = ui->groupTreeWidget->getItemFromId(QString::fromStdString(stats.mGrpId.toStdString())); + + if (item) + ui->groupTreeWidget->setUnreadCount(item, mCountChildMsgs ? (stats.mNumThreadMsgsUnread + stats.mNumChildMsgsUnread) : stats.mNumThreadMsgsUnread); - ui->groupTreeWidget->setUnreadCount(item, mCountChildMsgs ? (stats.mNumThreadMsgsUnread + stats.mNumChildMsgsUnread) : stats.mNumThreadMsgsUnread); mCachedGroupStats[groupId] = stats; getUserNotify()->updateIcon(); - }, this ); + }, this ); }); } void GxsGroupFrameDialog::getServiceStatistics(GxsServiceStatistic& stats) const { - stats = GxsServiceStatistic(); // clears everything + if(!mCachedGroupStats.empty()) + { + stats = GxsServiceStatistic(); // clears everything - for(auto& it: mCachedGroupStats) - { - const GxsGroupStatistic& s(it.second); + for(auto& it: mCachedGroupStats) + { + const GxsGroupStatistic& s(it.second); - stats.mNumMsgs += s.mNumMsgs; - stats.mNumGrps += 1; - stats.mSizeOfMsgs += s.mTotalSizeOfMsgs; - stats.mNumThreadMsgsNew += s.mNumThreadMsgsNew; - stats.mNumThreadMsgsUnread += s.mNumThreadMsgsUnread; - stats.mNumChildMsgsNew += s.mNumChildMsgsNew ; - stats.mNumChildMsgsUnread += s.mNumChildMsgsUnread ; - } + stats.mNumMsgs += s.mNumMsgs; + stats.mNumGrps += 1; + stats.mSizeOfMsgs += s.mTotalSizeOfMsgs; + stats.mNumThreadMsgsNew += s.mNumThreadMsgsNew; + stats.mNumThreadMsgsUnread += s.mNumThreadMsgsUnread; + stats.mNumChildMsgsNew += s.mNumChildMsgsNew ; + stats.mNumChildMsgsUnread += s.mNumChildMsgsUnread ; + } + + // Also save the service statistics in conf file, so that we can display it right away at start. + + Settings->beginGroup(mSettingsName); + Settings->setValue("NumMsgs", stats.mNumMsgs ); + Settings->setValue("NumGrps", stats.mNumGrps ); + Settings->setValue("SizeOfMessages", stats.mSizeOfMsgs ); + Settings->setValue("NumThreadMsgsNew", stats.mNumThreadMsgsNew ); + Settings->setValue("NumThreadMsgsUnread",stats.mNumThreadMsgsUnread); + Settings->setValue("NumChildMsgsNew", stats.mNumChildMsgsNew ); + Settings->setValue("NumChildMsgsUnread", stats.mNumChildMsgsUnread ); + Settings->endGroup(); + } + else // Get statistics from settings if no cache is already present: allows to display at start. + { + Settings->beginGroup(mSettingsName); + + stats.mNumMsgs = Settings->value("NumMsgs",QVariant(0)).toInt(); + stats.mNumGrps = Settings->value("NumGrps",QVariant(0)).toInt(); + stats.mSizeOfMsgs = Settings->value("SizeOfMessages",QVariant(0)).toInt(); + stats.mNumThreadMsgsNew = Settings->value("NumThreadMsgsNew",QVariant(0)).toInt(); + stats.mNumThreadMsgsUnread = Settings->value("NumThreadMsgsUnread",QVariant(0)).toInt(); + stats.mNumChildMsgsNew = Settings->value("NumChildMsgsNew",QVariant(0)).toInt(); + stats.mNumChildMsgsUnread = Settings->value("NumChildMsgsUnread",QVariant(0)).toInt(); + + Settings->endGroup(); + } } TurtleRequestId GxsGroupFrameDialog::distantSearch(const QString& search_string) // this should be overloaded in the child class diff --git a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.h b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.h index 1cbd1fc8f..81bba553d 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.h +++ b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.h @@ -71,7 +71,7 @@ public: }; public: - GxsGroupFrameDialog(RsGxsIfaceHelper *ifaceImpl, QWidget *parent = 0,bool allow_dist_sync=false); + GxsGroupFrameDialog(RsGxsIfaceHelper *ifaceImpl, const QString& settings_name,QWidget *parent = 0,bool allow_dist_sync=false); virtual ~GxsGroupFrameDialog(); bool navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msgId); diff --git a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.ui b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.ui index 0a8fa4587..8cb249020 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.ui +++ b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.ui @@ -70,7 +70,14 @@
    - + + + + 12 + 75 + true + + Name @@ -168,11 +175,6 @@
    gui/common/RSTabWidget.h
    1 - - StyledLabel - QLabel -
    gui/common/StyledLabel.h
    -
    GroupTreeWidget QWidget diff --git a/retroshare-gui/src/gui/gxs/GxsGroupShareKey.cpp b/retroshare-gui/src/gui/gxs/GxsGroupShareKey.cpp index dfcafaaf2..9197e3665 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupShareKey.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupShareKey.cpp @@ -79,14 +79,14 @@ void GroupShareKey::setTyp() ui->headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/channels.png")); ui->headerFrame->setHeaderText(tr("Share channel publish permissions")); - ui->sharekeyinfo_label->setText(tr("You can allow your friends to publish in your channel, or send the publish permissions to another Retroshare instance of yours. Select the friends which you want to be allowed to publish in this channel. Note: it is currently not possible to revoke channel publish permissions.")); + ui->info_Label_ShareKey->setText(tr("You can allow your friends to publish in your channel, or send the publish permissions to another Retroshare instance of yours. Select the friends which you want to be allowed to publish in this channel. Note: it is currently not possible to revoke channel publish permissions.")); } else if(mGrpType == FORUM_KEY_SHARE) { ui->headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/forums.png")); ui->headerFrame->setHeaderText(tr("Share forum admin permissions")); - ui->sharekeyinfo_label->setText(tr("You can let your friends know about your forum by sharing it with them. Select the friends with which you want to share your forum.")); + ui->info_Label_ShareKey->setText(tr("You can let your friends know about your forum by sharing it with them. Select the friends with which you want to share your forum.")); } else if (mGrpType == POSTED_KEY_SHARE) @@ -96,7 +96,7 @@ void GroupShareKey::setTyp() ui->headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/posted.png")); ui->headerFrame->setHeaderText(tr("Share board admin permissions")); - ui->sharekeyinfo_label->setText(tr("You can allow your friends to edit the board. Select them in the list below. Note: it is not possible to revoke Board admin permissions.")); + ui->info_Label_ShareKey->setText(tr("You can allow your friends to edit the board. Select them in the list below. Note: it is not possible to revoke Board admin permissions.")); } else diff --git a/retroshare-gui/src/gui/gxs/GxsGroupShareKey.ui b/retroshare-gui/src/gui/gxs/GxsGroupShareKey.ui index fb7db3b6e..b41aad127 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupShareKey.ui +++ b/retroshare-gui/src/gui/gxs/GxsGroupShareKey.ui @@ -17,7 +17,16 @@ 0 - + + 0 + + + 0 + + + 0 + + 0 @@ -78,7 +87,16 @@ - + + 0 + + + 0 + + + 0 + + 0 @@ -140,15 +158,12 @@
    - + 11 - - - QFrame::StyledPanel diff --git a/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp b/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp index 9321c4de4..f40182563 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp @@ -19,18 +19,20 @@ *******************************************************************************/ #include "GxsIdChooser.h" + #include "GxsIdDetails.h" #include "RsGxsUpdateBroadcastBase.h" -#include "gui/Identity/IdEditDialog.h" #include "gui/common/FilesDefs.h" +#include "gui/Identity/IdEditDialog.h" #include "util/misc.h" +#include "util/qtthreadsutils.h" #include #include #include -#include +#include #include #define ROLE_SORT Qt::UserRole + 1 // Qt::UserRole is reserved for data @@ -50,7 +52,7 @@ /** Constructor */ GxsIdChooser::GxsIdChooser(QWidget *parent) - : QComboBox(parent), mFlags(IDCHOOSER_ANON_DEFAULT) + : RSComboBox(parent), mFlags(IDCHOOSER_ANON_DEFAULT) { // mBase = new RsGxsUpdateBroadcastBase(rsIdentity, this); // connect(mBase, SIGNAL(fillDisplay(bool)), this, SLOT(fillDisplay(bool))); @@ -75,6 +77,24 @@ GxsIdChooser::GxsIdChooser(QWidget *parent) /* Connect signals */ connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(myCurrentIndexChanged(int))); connect(this, SIGNAL(activated(int)), this, SLOT(indexActivated(int))); + + // also capture identity creation/deletion events so as to update the UI accordingly + + mEventHandlerId = 0; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) { + RsQThreadUtils::postToObject( [this,event]() { handleEvent_main_thread(event); }) ;}, mEventHandlerId, RsEventType::GXS_IDENTITY ); +} + +void GxsIdChooser::handleEvent_main_thread(std::shared_ptr event) +{ + if(event->mType != RsEventType::GXS_IDENTITY) return; + + const RsGxsIdentityEvent *fe = dynamic_cast(event.get()); + if(!fe) + return; + + updateDisplay(true); + update(); // Qt flush } void GxsIdChooser::setFlags(uint32_t flags) @@ -85,6 +105,7 @@ void GxsIdChooser::setFlags(uint32_t flags) GxsIdChooser::~GxsIdChooser() { + rsEvents->unregisterEventsHandler(mEventHandlerId); } void GxsIdChooser::fillDisplay(bool complete) diff --git a/retroshare-gui/src/gui/gxs/GxsIdChooser.h b/retroshare-gui/src/gui/gxs/GxsIdChooser.h index 3cee770eb..61a610763 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdChooser.h +++ b/retroshare-gui/src/gui/gxs/GxsIdChooser.h @@ -21,14 +21,15 @@ #ifndef _GXS_ID_CHOOSER_H #define _GXS_ID_CHOOSER_H -#include -#include +#include "retroshare/rsevents.h" +#include "gui/common/RSComboBox.h" + +#include "retroshare/rsgxsifacetypes.h" // This class implement a basic RS functionality which is that ComboBox displaying Id // should update regularly. They also should update only when visible, to save CPU time. // -struct RsGxsIfaceHelper; class RsGxsUpdateBroadcastBase; #define IDCHOOSER_ID_REQUIRED 0x0001 @@ -36,13 +37,12 @@ class RsGxsUpdateBroadcastBase; #define IDCHOOSER_NO_CREATE 0x0004 #define IDCHOOSER_NON_ANONYMOUS 0x0008 -class GxsIdChooser : public QComboBox +class GxsIdChooser : public RSComboBox { Q_OBJECT public: - GxsIdChooser(RsGxsIfaceHelper* ifaceImpl, QWidget *parent = NULL); - GxsIdChooser(QWidget *parent = NULL); + GxsIdChooser(QWidget *parent = nullptr); virtual ~GxsIdChooser(); void setFlags(uint32_t flags) ; @@ -79,6 +79,7 @@ private slots: private: void loadPrivateIds(); void setDefaultItem(); + void handleEvent_main_thread(std::shared_ptr event); uint32_t mFlags; RsGxsId mDefaultId; @@ -87,6 +88,8 @@ private: std::set mConstraintIdsSet ; // leave empty if all allowed // RsGxsUpdateBroadcastBase *mBase; + + RsEventsHandlerId_t mEventHandlerId; }; #endif diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp index 51dbcf2bc..5c1c11b49 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp @@ -85,23 +85,27 @@ void ReputationItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem { Q_ASSERT(index.isValid()); - QStyleOptionViewItemV4 opt = option; + QStyleOptionViewItem opt(option); initStyleOption(&opt, index); // disable default icon opt.icon = QIcon(); // draw default item QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, 0); - const QRect r = option.rect; + const QRect r = option.rect; // get pixmap - unsigned int icon_index = qvariant_cast(index.data(Qt::DecorationRole)); + auto v = index.data(Qt::DecorationRole); + + if(!v.canConvert(QVariant::Int)) + return; + + unsigned int icon_index = qvariant_cast(v); if(icon_index > mMaxLevelToDisplay) return ; - QIcon icon = GxsIdDetails::getReputationIcon( - RsReputationLevel(icon_index), 0xff ); + QIcon icon = GxsIdDetails::getReputationIcon( RsReputationLevel(icon_index), 0xff ); QPixmap pix = icon.pixmap(r.size()); @@ -110,6 +114,12 @@ void ReputationItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem painter->drawPixmap(r.topLeft() + p, pix); } +QSize ReputationItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex & /*index*/) const +{ + int s = 1.5*QFontMetricsF(option.font).height(); + + return QSize(s,s); +} /* The global object */ GxsIdDetails *GxsIdDetails::mInstance = NULL ; @@ -1073,11 +1083,13 @@ bool GxsIdDetails::MakeIdDesc(const RsGxsId &id, bool doIcons, QString &str, QLi QString GxsIdDetails::getName(const RsIdentityDetails &details) { - if( details.mReputation.mOverallReputationLevel == - RsReputationLevel::LOCALLY_NEGATIVE ) + if( details.mReputation.mOverallReputationLevel == RsReputationLevel::LOCALLY_NEGATIVE ) return tr("[Banned]"); - QString name = QString::fromUtf8(details.mNickname.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE); + if( details.mId.isNull() ) + return tr("[Nobody]"); + + QString name = QString::fromUtf8(details.mNickname.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE); std::list::const_iterator it; for (it = details.mRecognTags.begin(); it != details.mRecognTags.end(); ++it) @@ -1104,7 +1116,7 @@ QString nickname ; nickname = QString::fromUtf8(details.mNickname.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE) ; - comment = QString("%1:%2
    %3:%4").arg(QApplication::translate("GxsIdDetails", "Identity name"), + comment = QString("%1: %2
    %3: %4").arg(QApplication::translate("GxsIdDetails", "Identity name"), nickname, QApplication::translate("GxsIdDetails", "Identity Id"), QString::fromStdString(details.mId.toStdString())); diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.h b/retroshare-gui/src/gui/gxs/GxsIdDetails.h index 05568aa3a..122b5e089 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdDetails.h +++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.h @@ -52,7 +52,8 @@ public: ReputationItemDelegate(RsReputationLevel max_level_to_display) : mMaxLevelToDisplay(static_cast(max_level_to_display)) {} - virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex & /*index*/) const override; private: uint32_t mMaxLevelToDisplay ; diff --git a/retroshare-gui/src/gui/gxs/GxsIdLabel.cpp b/retroshare-gui/src/gui/gxs/GxsIdLabel.cpp index 6cb741d14..62c15a699 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdLabel.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdLabel.cpp @@ -60,7 +60,10 @@ void GxsIdLabel::setId(const RsGxsId &id) { mId = id; - GxsIdDetails::process(mId, fillLabelCallback, this); + if(id.isNull()) + setText(tr("[Nobody]")); + else + GxsIdDetails::process(mId, fillLabelCallback, this); } bool GxsIdLabel::getId(RsGxsId &id) diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp index 0a8b9271b..053590e11 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp @@ -169,8 +169,11 @@ QVariant GxsIdRSTreeWidgetItem::data(int column, int role) const QString embeddedImage; - if ( RsHtml::makeEmbeddedImage( pix.scaled(QSize(4*S,4*S), Qt::KeepAspectRatio, Qt::SmoothTransformation ).toImage(), embeddedImage, 8*S * 8*S ) ) + if ( RsHtml::makeEmbeddedImage( pix.scaled(QSize(5*S,5*S), Qt::KeepAspectRatio, Qt::SmoothTransformation ).toImage(), embeddedImage, -1 ) ) + { + embeddedImage.insert(embeddedImage.indexOf("src="), "style=\"float:left\" "); t = "
    " + embeddedImage + "" + t + "
    "; + } return t; } @@ -190,17 +193,25 @@ void GxsIdTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem QStyleOptionViewItem ownOption (option); initStyleOption(&ownOption, index); - RsGxsId id(index.data(Qt::UserRole).toString().toStdString()); - QString cmt; + QString dt = index.data(Qt::UserRole).toString(); + RsGxsId id(index.data(Qt::UserRole).toString().toStdString()); - if(id.isNull()) + // This is a trick: UserRole in Mail generally is 0000...00000 when there is a notification, and is empty when there are multiple + // destinations at once. This is not so nice to do that this way, but it's a quick workaround to a more complex method involving an + // additional Qt role only to determine the number of destinations. + + if(dt == "") + ownOption.icon = FilesDefs::getIconFromQtResourcePath(":/icons/svg/people2.svg"); + else if(id.isNull()) + { + if (ownOption.icon.isNull()) + ownOption.icon = FilesDefs::getIconFromQtResourcePath(":/icons/notification.svg"); + } + else { - if (ownOption.icon.isNull()) - ownOption.icon = FilesDefs::getIconFromQtResourcePath(":/icons/notification.png"); - } - else - { - if(! computeNameIconAndComment(id,ownOption.text,ownOption.icon,cmt)) + QString cmt; + + if(! computeNameIconAndComment(id,ownOption.text,ownOption.icon,cmt)) { if(mReloadPeriod > 3) { diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h index 15bdfeb87..1f38ecf04 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h +++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h @@ -109,7 +109,9 @@ public: QList icons; QString comment; - if(rsPeers->isFriend(RsPeerId(id))) // horrible trick because some widgets still use locations as IDs (e.g. messages) + if(id.isNull()) + name = QObject::tr("[System]"); + else if(RsPeerId(id)==rsPeers->getOwnId() || rsPeers->isFriend(RsPeerId(id))) // horrible trick because some widgets still use locations as IDs (e.g. messages) name = QString::fromUtf8(rsPeers->getPeerName(RsPeerId(id)).c_str()) ; else if(!GxsIdDetails::MakeIdDesc(id, false, name, icons, comment,GxsIdDetails::ICON_TYPE_NONE)) return false; @@ -123,8 +125,13 @@ public: bool exist = false; - if(rsPeers->isFriend(RsPeerId(id))) // horrible trick because some widgets still use locations as IDs (e.g. messages) - { + if(id.isNull()) + { + name = QObject::tr("[System]"); + icon = QIcon(); + } + else if(RsPeerId(id)==rsPeers->getOwnId() || rsPeers->isFriend(RsPeerId(id))) // horrible trick because some widgets still use locations as IDs (e.g. messages) + { name = QString::fromUtf8(rsPeers->getPeerName(RsPeerId(id)).c_str()) ; icon = FilesDefs::getIconFromQtResourcePath(":/icons/avatar_128.png"); } diff --git a/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.cpp b/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.cpp index 1eb52356a..0f7c6dc0b 100644 --- a/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.cpp +++ b/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.cpp @@ -371,7 +371,7 @@ void GxsMessageFramePostWidget::loadPosts(const std::set& msgIds /**************************************************************/ GxsMessageFramePostThread::GxsMessageFramePostThread(const std::vector& posts,GxsMessageFramePostWidget *parent) - : mPosts(posts),QThread(parent), mParent(parent) + : QThread(parent), mPosts(posts), mParent(parent) { mStopped = false; } diff --git a/retroshare-gui/src/gui/gxs/GxsMessageFrameWidget.cpp b/retroshare-gui/src/gui/gxs/GxsMessageFrameWidget.cpp index 8d9a89a47..8a42911ac 100644 --- a/retroshare-gui/src/gui/gxs/GxsMessageFrameWidget.cpp +++ b/retroshare-gui/src/gui/gxs/GxsMessageFrameWidget.cpp @@ -28,7 +28,6 @@ GxsMessageFrameWidget::GxsMessageFrameWidget(RsGxsIfaceHelper *ifaceImpl, QWidge { mNextTokenType = 0; - mTokenQueue = new TokenQueue(ifaceImpl->getTokenService(), this); mStateHelper = new UIStateHelper(this); /* Set read status */ @@ -36,7 +35,7 @@ GxsMessageFrameWidget::GxsMessageFrameWidget(RsGxsIfaceHelper *ifaceImpl, QWidge mAcknowledgeReadStatusToken = 0; /* Add dummy entry to store waiting status */ - mStateHelper->addWidget(mTokenTypeAcknowledgeReadStatus, NULL, 0); + mStateHelper->addWidget(mTokenTypeAcknowledgeReadStatus, NULL, UIStates()); } GxsMessageFrameWidget::~GxsMessageFrameWidget() @@ -46,8 +45,6 @@ GxsMessageFrameWidget::~GxsMessageFrameWidget() emit waitingChanged(this); } - - delete(mTokenQueue); } const RsGxsGroupId &GxsMessageFrameWidget::groupId() @@ -95,34 +92,6 @@ void GxsMessageFrameWidget::setGroupId(const RsGxsGroupId &groupId) void GxsMessageFrameWidget::setAllMessagesRead(bool read) { - uint32_t token = 0; - setAllMessagesReadDo(read, token); - - if (token) { - /* Wait for acknowlegde of the token */ - mAcknowledgeReadStatusToken = token; - mTokenQueue->queueRequest(mAcknowledgeReadStatusToken, 0, 0, mTokenTypeAcknowledgeReadStatus); - mStateHelper->setLoading(mTokenTypeAcknowledgeReadStatus, true); - - emit waitingChanged(this); - } + setAllMessagesReadDo(read); } -void GxsMessageFrameWidget::loadRequest(const TokenQueue *queue, const TokenRequest &req) -{ - if (queue == mTokenQueue) - { - if (req.mUserType == mTokenTypeAcknowledgeReadStatus) { - if (mAcknowledgeReadStatusToken == req.mToken) { - /* Set read status is finished */ - mStateHelper->setLoading(mTokenTypeAcknowledgeReadStatus, false); - - emit waitingChanged(this); - } - return; - } - } - - std::cerr << "GxsMessageFrameWidget::loadRequest() ERROR: INVALID TYPE"; - std::cerr << std::endl; -} diff --git a/retroshare-gui/src/gui/gxs/GxsMessageFrameWidget.h b/retroshare-gui/src/gui/gxs/GxsMessageFrameWidget.h index 36c2f4f67..758088595 100644 --- a/retroshare-gui/src/gui/gxs/GxsMessageFrameWidget.h +++ b/retroshare-gui/src/gui/gxs/GxsMessageFrameWidget.h @@ -22,12 +22,11 @@ #define GXSMESSAGEFRAMEWIDGET_H #include "gui/gxs/RsGxsUpdateBroadcastWidget.h" -#include "util/TokenQueue.h" struct RsGxsIfaceHelper; class UIStateHelper; -class GxsMessageFrameWidget : public QWidget, public TokenResponse +class GxsMessageFrameWidget : public QWidget { Q_OBJECT @@ -49,7 +48,6 @@ public: /* GXS functions */ uint32_t nextTokenType() { return ++mNextTokenType; } - virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); signals: void groupChanged(QWidget *widget); @@ -58,10 +56,9 @@ signals: void groupDataLoaded(); protected: - virtual void setAllMessagesReadDo(bool read, uint32_t &token) = 0; + virtual void setAllMessagesReadDo(bool read) = 0; protected: - TokenQueue *mTokenQueue; UIStateHelper *mStateHelper; /* Set read status */ diff --git a/retroshare-gui/src/gui/gxs/GxsUserNotify.cpp b/retroshare-gui/src/gui/gxs/GxsUserNotify.cpp index bc1afa1c1..1784a6f8c 100644 --- a/retroshare-gui/src/gui/gxs/GxsUserNotify.cpp +++ b/retroshare-gui/src/gui/gxs/GxsUserNotify.cpp @@ -26,7 +26,7 @@ #define TOKEN_TYPE_STATISTICS 1 -GxsUserNotify::GxsUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsGroupFrameDialog *g,QObject *parent) : UserNotify(parent), mGroupFrameDialog(g) +GxsUserNotify::GxsUserNotify(RsGxsIfaceHelper */*ifaceImpl*/, const GxsGroupFrameDialog *g,QObject *parent) : UserNotify(parent), mGroupFrameDialog(g) { mNewThreadMessageCount = 0; mNewChildMessageCount = 0; diff --git a/retroshare-gui/src/gui/gxs/GxsUserNotify.h b/retroshare-gui/src/gui/gxs/GxsUserNotify.h index f9c5cd616..66890a1c3 100644 --- a/retroshare-gui/src/gui/gxs/GxsUserNotify.h +++ b/retroshare-gui/src/gui/gxs/GxsUserNotify.h @@ -24,9 +24,8 @@ #include #include "gui/common/UserNotify.h" #include "gui/gxs/GxsGroupFrameDialog.h" -#include "util/TokenQueue.h" -struct RsGxsIfaceHelper; +class RsGxsIfaceHelper; class RsGxsUpdateBroadcastBase; class GxsUserNotify : public UserNotify @@ -47,7 +46,6 @@ protected: bool mCountChildMsgs; // Count new child messages? private: - RsGxsUpdateBroadcastBase *mBase; const GxsGroupFrameDialog *mGroupFrameDialog; unsigned int mNewThreadMessageCount; diff --git a/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.cpp b/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.cpp index 3d51f0acb..bc2f5d960 100644 --- a/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.cpp +++ b/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.cpp @@ -35,6 +35,7 @@ #include "util/rsdir.h" #include "util/qtthreadsutils.h" #include "util/RichTextEdit.h" +#include "util/imageutil.h" #include @@ -74,7 +75,7 @@ CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId, RsGxsMessageId connect(addFileButton, SIGNAL(clicked() ), this , SLOT(addExtraFile())); connect(removeAllFilesButton, SIGNAL(clicked() ), this , SLOT(clearAllAttachments())); //connect(addfilepushButton, SIGNAL(clicked() ), this , SLOT(addExtraFile())); - connect(subjectEdit,SIGNAL(textChanged(const QString&)),this,SLOT(updatePreviewText(const QString&))); + connect(subjectEdit,SIGNAL(textChanged(QString)),this,SLOT(updatePreviewText(QString))); connect(expandButton, SIGNAL(clicked()), this, SLOT( toggle())); connect(addThumbnailButton, SIGNAL(clicked() ), this , SLOT(addThumbnail())); @@ -183,8 +184,8 @@ void CreateGxsChannelMsg::contextMenu(QPoint /*point*/) int n_file = 0 ; - for(QList::const_iterator it(links.begin());it!=links.end();++it) - if((*it).type() == RetroShareLink::TYPE_FILE) + for(auto &it : links) + if(it.type() == RetroShareLink::TYPE_FILE) ++n_file ; QMenu contextMnu(this) ; @@ -203,42 +204,42 @@ void CreateGxsChannelMsg::pasteLink() { std::cerr << "Pasting links: " << std::endl; - QList links; + QList links; RSLinkClipboard::pasteLinks(links) ; - for(QList::const_iterator it(links.begin());it!=links.end();++it) - if((*it).type() == RetroShareLink::TYPE_FILE) + for(auto &it : links) + if(it.type() == RetroShareLink::TYPE_FILE) { // 0 - check that we actually have the file! // - std::cerr << "Pasting " << (*it).toString().toStdString() << std::endl; + std::cerr << "Pasting " << it.toString().toStdString() << std::endl; - FileInfo info ; - RsFileHash hash( (*it).hash().toStdString()) ; + FileInfo info ; + RsFileHash hash( it.hash().toStdString()) ; #ifdef TO_REMOVE - if(rsFiles->alreadyHaveFile( hash,info ) ) + if(rsFiles->alreadyHaveFile( hash,info ) ) #endif - addAttachment(hash, (*it).name().toUtf8().constData(), (*it).size(), rsFiles->alreadyHaveFile( hash,info ), RsPeerId()) ; + addAttachment(hash, it.name().toUtf8().constData(), it.size(), rsFiles->alreadyHaveFile( hash,info ), RsPeerId()) ; #ifdef TO_REMOVE - else - not_have.push_back( *it ) ; + else + not_have.push_back( *it ) ; #endif - } + } #ifdef TO_REMOVE - if(!not_have.empty()) - { - QString msg = tr("You are about to add files you're not actually sharing. Do you still want this to happen?")+"

    " ; + if(!not_have.empty()) + { + QString msg = tr("You are about to add files you're not actually sharing. Do you still want this to happen?")+"

    " ; - for(QList::const_iterator it(not_have.begin());it!=not_have.end();++it) - msg += (*it).toString() + "
    " ; + for(QList::const_iterator it(not_have.begin());it!=not_have.end();++it) + msg += (*it).toString() + "
    " ; - if(QMessageBox::YesToAll == QMessageBox::question(NULL,tr("About to post un-owned files to a channel."),msg,QMessageBox::YesToAll | QMessageBox::No)) - for(QList::const_iterator it(not_have.begin());it!=not_have.end();++it) - addAttachment(RsFileHash((*it).hash().toStdString()), (*it).name().toUtf8().constData(), (*it).size(), false, RsPeerId()) ; - } + if(QMessageBox::YesToAll == QMessageBox::question(NULL,tr("About to post un-owned files to a channel."),msg,QMessageBox::YesToAll | QMessageBox::No)) + for(QList::const_iterator it(not_have.begin());it!=not_have.end();++it) + addAttachment(RsFileHash((*it).hash().toStdString()), (*it).name().toUtf8().constData(), (*it).size(), false, RsPeerId()) ; + } #endif } @@ -607,11 +608,13 @@ bool CreateGxsChannelMsg::setThumbNail(const std::string& path, int frame){ if(imageBuffer == NULL) return false; - QImage tNail(imageBuffer, width, height, QImage::Format_RGB32); + QImage tNail(imageBuffer, width, height, QImage::Format_RGBA32); QByteArray ba; QBuffer buffer(&ba); + bool has_transparency = ImageUtil::hasAlphaContent(tNail.toImage()); + buffer.open(QIODevice::WriteOnly); - tNail.save(&buffer, "PNG"); + tNail.save(&buffer, has_transparency?"PNG":"JPG"); QPixmap img; img.loadFromData(ba, "PNG"); img = img.scaled(thumbnail_label->width(), thumbnail_label->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation); @@ -794,54 +797,29 @@ void CreateGxsChannelMsg::sendMessage(const std::string &subject, const std::str /* rsGxsChannels */ if (rsGxsChannels) { - RsGxsChannelPost post; - - post.mMeta.mGroupId = mChannelId; - post.mMeta.mParentId.clear() ; - post.mMeta.mThreadId.clear() ; - post.mMeta.mMsgId.clear() ; - - post.mMeta.mOrigMsgId = mOrigPostId; - post.mMeta.mMsgName = subject; - post.mMsg = msg; - post.mFiles = files; - QByteArray ba; QBuffer buffer(&ba); + RsGxsImage image; + QPixmap pixmap; + pixmap = preview_W->getCroppedScaledPicture(); + QImage qimg = pixmap.toImage(); + bool has_transparency = ImageUtil::hasAlphaContent(qimg); + if(!picture.isNull()) { // send chan image buffer.open(QIODevice::WriteOnly); - preview_W->getCroppedScaledPicture().save(&buffer, "PNG"); // writes image into ba in PNG format - post.mThumbnail.copy((uint8_t *) ba.data(), ba.size()); + preview_W->getCroppedScaledPicture().save(&buffer, has_transparency?"PNG":"JPG"); // writes image into ba in PNG format + image.copy((uint8_t *) ba.data(), ba.size()); } - int generateCount = 0; + std::string error_string; + RsGxsMessageId post_id; -#ifdef ENABLE_GENERATE - if (generateCheckBox->isChecked()) { - generateCount = generateSpinBox->value(); - if (QMessageBox::question(this, tr("Generate mass data"), tr("Do you really want to generate %1 messages ?").arg(generateCount), QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::No) { - return; - } - } -#endif - - uint32_t token; - if (generateCount) { -#ifdef ENABLE_GENERATE - for (int count = 0; count < generateCount; ++count) { - RsGxsChannelPost generatePost = post; - generatePost.mMeta.mMsgName = QString("%1 %2").arg(QString::fromUtf8(post.mMeta.mMsgName.c_str())).arg(count + 1, 3, 10, QChar('0')).toUtf8().constData(); - - rsGxsChannels->createPost(token, generatePost); - } -#endif - } else { - rsGxsChannels->createPost(token, post); - } + if(!rsGxsChannels->createPostV2(mChannelId,subject,msg,files,image,mOrigPostId,post_id,error_string)) + QMessageBox::critical(nullptr,tr("Cannot publish post"),QString::fromStdString(error_string)); } accept(); @@ -966,14 +944,14 @@ void CreateGxsChannelMsg::toggle() if (expandButton->isChecked()) { thumbnailFrame->hide(); - gridLayoutTextEdit->setContentsMargins(0,9,0,0); + subject_HL->setContentsMargins(0,9,0,0); expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/down-arrow.png"))); expandButton->setToolTip(tr("Show")); } else { thumbnailFrame->show(); - gridLayoutTextEdit->setContentsMargins(0,0,0,0); + subject_HL->setContentsMargins(0,0,0,0); expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/up-arrow.png"))); expandButton->setToolTip(tr("Hide")); } diff --git a/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.ui b/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.ui index b29e9cdd8..01e58118f 100644 --- a/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.ui +++ b/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.ui @@ -20,7 +20,7 @@ :/images/logo/logo_16.png:/images/logo/logo_16.png - + 0 @@ -40,14 +40,14 @@ 0 - + QFrame::StyledPanel QFrame::Raised - + 3 @@ -77,7 +77,7 @@ - + 9 @@ -99,7 +99,7 @@
    - + Qt::Horizontal @@ -113,6 +113,13 @@ + + + 12 + 75 + true + + Post @@ -141,8 +148,8 @@ 0 - - + + 0 @@ -163,7 +170,7 @@ QFrame::Plain - + 6 @@ -184,8 +191,8 @@ p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;">Attachments:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Use Drag and Drop / Add Files button, to Hash new files.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Copy/Paste RetroShare links from your shares</span></p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:''; font-size:;"> Use Drag and Drop / Add Files button, to Hash new files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:''; font-size:;"> Copy/Paste RetroShare links from your shares</span></p></body></html> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop @@ -193,7 +200,7 @@ p, li { white-space: pre-wrap; } - + @@ -208,7 +215,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Choose aspect ratio policy. In 'Auto' mode, the most suitable aspect ratio is chosen for you.</p></body></html> @@ -254,7 +261,7 @@ p, li { white-space: pre-wrap; } - + Qt::Horizontal @@ -272,7 +279,7 @@ p, li { white-space: pre-wrap; } - + 9 @@ -317,7 +324,7 @@ p, li { white-space: pre-wrap; } - + 6 @@ -332,7 +339,7 @@ p, li { white-space: pre-wrap; }
    - + Qt::Vertical @@ -350,7 +357,7 @@ p, li { white-space: pre-wrap; }
    - + 6 @@ -388,10 +395,10 @@ p, li { white-space: pre-wrap; }
    - + - + @@ -481,7 +488,7 @@ p, li { white-space: pre-wrap; } - + Qt::Horizontal @@ -508,8 +515,8 @@ p, li { white-space: pre-wrap; } 0 0 - 63 - 24 + 98 + 30 @@ -518,7 +525,7 @@ p, li { white-space: pre-wrap; } 0 - + 3 @@ -548,7 +555,7 @@ p, li { white-space: pre-wrap; } Drag and Drop Files from Search Results - +
    @@ -579,7 +586,7 @@ p, li { white-space: pre-wrap; }
    - + Qt::Horizontal @@ -604,6 +611,17 @@ p, li { white-space: pre-wrap; }
    + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    + + ChannelPostThumbnailView + QWidget +
    gui/gxschannels/GxsChannelPostThumbnail.h
    + 1 +
    HeaderFrame QFrame @@ -616,16 +634,10 @@ p, li { white-space: pre-wrap; }
    util/RichTextEdit.h
    1
    - - ChannelPostThumbnailView - QWidget -
    gui/gxschannels/GxsChannelPostThumbnail.h
    - 1 -
    - + diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp index e18a161a3..47317c801 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp @@ -35,6 +35,7 @@ #include "gui/notifyqt.h" #include "gui/common/GroupTreeWidget.h" #include "util/qtthreadsutils.h" +#include "util/misc.h" // class GxsChannelGroupInfoData : public RsUserdata // { @@ -48,7 +49,7 @@ /** Constructor */ GxsChannelDialog::GxsChannelDialog(QWidget *parent): - GxsGroupFrameDialog(rsGxsChannels, parent, true), mEventHandlerId(0) + GxsGroupFrameDialog(rsGxsChannels, settingsGroupName(),parent, true), mEventHandlerId(0) { // Needs to be asynced because this function is called by another thread! rsEvents->registerEventsHandler( @@ -66,6 +67,7 @@ void GxsChannelDialog::handleEvent_main_thread(std::shared_ptr ev { case RsChannelEventCode::STATISTICS_CHANGED: // [[fallthrough]]; updateDisplay(true); // no breaks, on purpose! + Q_FALLTHROUGH(); case RsChannelEventCode::NEW_MESSAGE: // [[fallthrough]]; case RsChannelEventCode::UPDATED_MESSAGE: // [[fallthrough]]; @@ -89,8 +91,8 @@ void GxsChannelDialog::handleEvent_main_thread(std::shared_ptr ev const RsGxsChannelSearchResultEvent*f = dynamic_cast(event.get()); - if(nullptr != f) - for(auto it:f->mSearchResultsMap) + if(nullptr != f) + for(auto &it:f->mSearchResultsMap) updateSearchResults(it.first); } @@ -101,18 +103,23 @@ GxsChannelDialog::~GxsChannelDialog() QString GxsChannelDialog::getHelpString() const { - QString hlp_str = tr("

      Channels

    \ -

    Channels allow you to post data (e.g. movies, music) that will spread in the network

    \ -

    You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to \ - your friends. This promotes good channels in the network.

    \ -

    Only the channel's creator can post on that channel. Other peers \ - in the network can only read from it, unless the channel is private. You can however share \ - the posting rights or the reading rights with friend Retroshare nodes.

    \ -

    Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed.\ - Enable \"Allow Comments\" if you want to let users comment on your posts.

    \ -

    Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.

    \ -

    UI Tip: use Control + mouse wheel to control image size in the thumbnail view.

    \ - ").arg(QString::number(rsGxsChannels->getDefaultStoragePeriod()/86400)).arg(QString::number(rsGxsChannels->getDefaultSyncPeriod()/86400)); + int H = misc::getFontSizeFactor("HelpButton").height(); + + QString hlp_str = tr( + "

      Channels

    " + "

    Channels allow you to post data (e.g. movies, music) that will spread in the network

    " + "

    You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to" + " your friends. This promotes good channels in the network.

    " + "

    Only the channel's creator can post on that channel. Other peers" + " in the network can only read from it, unless the channel is private. You can however share" + " the posting rights or the reading rights with friend Retroshare nodes.

    " + "

    Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed." + " Enable \"Allow Comments\" if you want to let users comment on your posts.

    " + "

    Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.

    " + "

    UI Tip: use Control + mouse wheel to control image size in the thumbnail view.

    " + ).arg( QString::number(2*H) + , QString::number(rsGxsChannels->getDefaultStoragePeriod()/86400) + , QString::number(rsGxsChannels->getDefaultSyncPeriod()/86400)); return hlp_str ; } @@ -259,11 +266,13 @@ void GxsChannelDialog::groupTreeCustomActions(RsGxsGroupId grpId, int subscribeF if (isSubscribed) { - QAction *action = autoDownload ? (new QAction(FilesDefs::getIconFromQtResourcePath(":/images/redled.png"), tr("Disable Auto-Download"), this)) - : (new QAction(FilesDefs::getIconFromQtResourcePath(":/images/start.png"),tr("Enable Auto-Download"), this)); + { + QAction *action = autoDownload ? (new QAction(FilesDefs::getIconFromQtResourcePath(":/images/redled.png"), tr("Disable Auto-Download"), this)) + : (new QAction(FilesDefs::getIconFromQtResourcePath(":/images/start.png"),tr("Enable Auto-Download"), this)); - connect(action, SIGNAL(triggered()), this, SLOT(toggleAutoDownload())); - actions.append(action); + connect(action, SIGNAL(triggered()), this, SLOT(toggleAutoDownload())); + actions.append(action); + } std::string dl_directory; rsGxsChannels->getChannelDownloadDirectory(grpId,dl_directory) ; @@ -281,20 +290,20 @@ void GxsChannelDialog::groupTreeCustomActions(RsGxsGroupId grpId, int subscribeF for(std::list::const_iterator it(lst.begin());it!=lst.end();++it) { - QAction *action = NULL; + QAction *fileAction = NULL; if(dl_directory == it->filename) { - action = new QAction(FilesDefs::getIconFromQtResourcePath(":/images/start.png"),QString::fromUtf8(it->filename.c_str()),NULL) ; + fileAction = new QAction(FilesDefs::getIconFromQtResourcePath(":/images/start.png"),QString::fromUtf8(it->filename.c_str()),NULL) ; found = true ; } else - action = new QAction(QString::fromUtf8(it->filename.c_str()),NULL) ; + fileAction = new QAction(QString::fromUtf8(it->filename.c_str()),NULL) ; - connect(action,SIGNAL(triggered()),this,SLOT(setDownloadDirectory())) ; - action->setData(QString::fromUtf8(it->filename.c_str())) ; + connect(fileAction,SIGNAL(triggered()),this,SLOT(setDownloadDirectory())) ; + fileAction->setData(QString::fromUtf8(it->filename.c_str())) ; - mnu->addAction(action) ; + mnu->addAction(fileAction) ; } if(!found && !dl_directory.empty()) @@ -360,24 +369,42 @@ void GxsChannelDialog::toggleAutoDownload() bool GxsChannelDialog::getGroupStatistics(const RsGxsGroupId& groupId,GxsGroupStatistic& stat) { - return rsGxsChannels->getChannelStatistics(groupId,stat); + // What follows is a hack to replace the GXS group statistics by the actual count of unread messages in channels, + // which should take into account old post versions, discard comments and votes, etc. + + RsGxsChannelStatistics s; + bool res = rsGxsChannels->getChannelStatistics(groupId,s); + + if(!res) + return false; + + stat.mGrpId = groupId; + stat.mNumMsgs = s.mNumberOfPosts; + + stat.mTotalSizeOfMsgs = 0; // hopefuly unused. Required the loading of the full channel data, so not very convenient. + stat.mNumThreadMsgsNew = s.mNumberOfNewPosts; + stat.mNumThreadMsgsUnread = s.mNumberOfUnreadPosts; + stat.mNumChildMsgsNew = 0; + stat.mNumChildMsgsUnread = 0; + + return true; } bool GxsChannelDialog::getGroupData(std::list& groupInfo) { std::vector groups; - // request all group infos at once + // request all group infos at once - if(! rsGxsChannels->getChannelsInfo(std::list(),groups)) - return false; + if(! rsGxsChannels->getChannelsInfo(std::list(),groups)) + return false; - /* Save groups to fill icons and description */ + /* Save groups to fill icons and description */ for (auto& group: groups) - groupInfo.push_back(new RsGxsChannelGroup(group)); + groupInfo.push_back(new RsGxsChannelGroup(group)); - return true; + return true; } void GxsChannelDialog::groupInfoToGroupItemInfo(const RsGxsGenericGroupData *groupData, GroupItemInfo &groupItemInfo) diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.cpp index 365dab3f3..23f5f5b93 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.cpp @@ -33,8 +33,8 @@ #include "retroshare/rsfiles.h" -GxsChannelFilesStatusWidget::GxsChannelFilesStatusWidget(const RsGxsFile &file, QWidget *parent) : - QWidget(parent), mFile(file), ui(new Ui::GxsChannelFilesStatusWidget) +GxsChannelFilesStatusWidget::GxsChannelFilesStatusWidget(const RsGxsFile &file, QWidget *parent,bool used_as_editor) : + QWidget(parent), mFile(file), mUsedAsEditor(used_as_editor),ui(new Ui::GxsChannelFilesStatusWidget) { ui->setupUi(this); @@ -46,19 +46,16 @@ GxsChannelFilesStatusWidget::GxsChannelFilesStatusWidget(const RsGxsFile &file, connect(ui->downloadPushButton, SIGNAL(clicked()), this, SLOT(download())); connect(ui->resumeToolButton, SIGNAL(clicked()), this, SLOT(resume())); connect(ui->pauseToolButton, SIGNAL(clicked()), this, SLOT(pause())); - connect(ui->cancelToolButton, SIGNAL(clicked()), this, SLOT(cancel())); + connect(ui->cancelToolButton, SIGNAL(clicked()), this, SLOT(cancel())); connect(ui->openFilePushButton, SIGNAL(clicked()), this, SLOT(openFile())); ui->downloadPushButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/download.png")); - ui->openFolderToolButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/arrow.png")); - QAction *openfolder = new QAction(tr("Open folder"), this); - connect(openfolder, SIGNAL(triggered()), this, SLOT(openFolder())); + ui->openFolderPushButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/folderopen.png")); + ui->openFolderPushButton->setToolTip(tr("Open folder")); + + connect(ui->openFolderPushButton, SIGNAL(clicked()), this, SLOT(openFolder())); - QMenu *menu = new QMenu(); - menu->addAction(openfolder); - ui->openFolderToolButton->setMenu(menu); - check(); } @@ -90,7 +87,9 @@ void GxsChannelFilesStatusWidget::setSize(uint64_t size) void GxsChannelFilesStatusWidget::check() { FileInfo fileInfo; - if (rsFiles->alreadyHaveFile(mFile.mHash, fileInfo)) { + + if(haveFile(fileInfo)) + { mState = STATE_LOCAL; setSize(fileInfo.size); @@ -103,27 +102,25 @@ void GxsChannelFilesStatusWidget::check() ui->openFilePushButton->setText(tr("Play")); ui->openFilePushButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/play.png")); } - - } else { - FileInfo fileInfo; - bool detailsOk = rsFiles->FileDetails(mFile.mHash, RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_SPEC_ONLY, fileInfo); - - if (detailsOk) { - switch (fileInfo.downloadStatus) { + } + else + { + switch (fileInfo.downloadStatus) + { case FT_STATE_WAITING: mState = STATE_WAITING; break; case FT_STATE_DOWNLOADING: - if (fileInfo.avail == fileInfo.size) { + if (fileInfo.avail == fileInfo.size) mState = STATE_LOCAL; - } else { + else mState = STATE_DOWNLOAD; - } + setSize(fileInfo.size); ui->progressBar->setValue(fileInfo.avail / mDivisor); break; - case FT_STATE_COMPLETE: - mState = STATE_DOWNLOAD; + case FT_STATE_COMPLETE: // this should not happen, since the case is handled earlier + mState = STATE_ERROR; break; case FT_STATE_QUEUED: mState = STATE_WAITING; @@ -134,14 +131,11 @@ void GxsChannelFilesStatusWidget::check() case FT_STATE_CHECKING_HASH: mState = STATE_CHECKING; break; - case FT_STATE_FAILED: - mState = STATE_ERROR; - break; - } - } else { - mState = STATE_REMOTE; - } - } + default: + mState = STATE_REMOTE; + break; + } + } int repeat = 0; QString statusText; @@ -156,7 +150,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->hide(); ui->progressBar->hide(); ui->openFilePushButton->hide(); - ui->openFolderToolButton->hide(); + ui->openFolderPushButton->hide(); statusText = tr("Error"); @@ -171,7 +165,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->hide(); ui->progressBar->hide(); ui->openFilePushButton->hide(); - ui->openFolderToolButton->hide(); + ui->openFolderPushButton->hide(); break; @@ -184,7 +178,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->show(); ui->progressBar->show(); ui->openFilePushButton->hide(); - ui->openFolderToolButton->hide(); + ui->openFolderPushButton->hide(); break; @@ -197,7 +191,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->show(); ui->progressBar->hide(); ui->openFilePushButton->hide(); - ui->openFolderToolButton->hide(); + ui->openFolderPushButton->hide(); statusText = tr("Paused"); @@ -212,7 +206,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->show(); ui->progressBar->hide(); ui->openFilePushButton->hide(); - ui->openFolderToolButton->hide(); + ui->openFolderPushButton->hide(); statusText = tr("Waiting"); @@ -227,7 +221,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->show(); ui->progressBar->hide(); ui->openFilePushButton->hide(); - ui->openFolderToolButton->hide(); + ui->openFolderPushButton->hide(); statusText = tr("Checking"); @@ -242,7 +236,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->hide(); ui->progressBar->hide(); ui->openFilePushButton->show(); - ui->openFolderToolButton->show(); + ui->openFolderPushButton->show(); break; } @@ -306,49 +300,87 @@ void GxsChannelFilesStatusWidget::resume() void GxsChannelFilesStatusWidget::cancel() { - if ((QMessageBox::question(this, "", tr("Are you sure that you want to cancel and delete the file?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No)) == QMessageBox::No) { - return; - } + // When QMessgeBox asks for cancel confirmtion, this makes the widget lose focus => since it is an editor widget, + // it gets destroyed by the parent list widget => subsequent code after the QMessageBox runs over a deleted object => crash + // In summary: no QMessageBox here when the Status widget is used as an editor. + + if(!mUsedAsEditor) + if ((QMessageBox::question(this, "", tr("Are you sure that you want to cancel and delete the file?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No)) == QMessageBox::No) { + return; + } rsFiles->FileCancel(mFile.mHash); emit onButtonClick();// Signals the parent widget to e.g. update the downloadable file count - check(); + check(); } void GxsChannelFilesStatusWidget::openFolder() { FileInfo fileInfo; - if (!rsFiles->alreadyHaveFile(mFile.mHash, fileInfo)) { + if (!haveFile(fileInfo)) return; - } - /* open folder with a suitable application */ - QDir dir = QFileInfo(QString::fromUtf8(fileInfo.path.c_str())).absoluteDir(); - if (dir.exists()) { - if (!RsUrlHandler::openUrl(QUrl::fromLocalFile(dir.absolutePath()))) { - QMessageBox::warning(this, "", QString("%1 %2").arg(tr("Can't open folder"), dir.absolutePath())); - } - } + QFileInfo finfo; + finfo.setFile(QString::fromUtf8(fileInfo.path.c_str())); + + /* open folder with a suitable application */ + if (!RsUrlHandler::openUrl(QUrl::fromLocalFile(finfo.absolutePath()))) { + if(!mUsedAsEditor) + QMessageBox::warning(this, "", QString("%1 %2").arg(tr("Can't open folder"), finfo.absolutePath())); + else + RsErr() << "Can't open folder " << finfo.absolutePath().toStdString() ; + } +} + +bool GxsChannelFilesStatusWidget::haveFile(FileInfo& info) +{ + bool already_has_file = rsFiles->alreadyHaveFile(mFile.mHash, info); + + if(!already_has_file) + if(!(rsFiles->FileDetails(mFile.mHash, RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_SPEC_ONLY, info) && info.downloadStatus==FT_STATE_COMPLETE)) + return false; + + // We need the code below because FileDetails() returns fileInfo.path as the directory when the file in COMPLETE and + // as a full path when the file is shared. The former is inconsistent with the documentation in rstypes.h, but I'm not + // sure what are the implications of changing the code in libretroshare so that the full path is always returned. + + QFileInfo finfo; + + if(QDir(QString::fromUtf8(info.path.c_str())).exists()) + finfo.setFile(QString::fromUtf8(info.path.c_str()),QString::fromUtf8(info.fname.c_str())); + else if(QFile(QString::fromUtf8(info.path.c_str())).exists()) + finfo.setFile(QString::fromUtf8(info.path.c_str())); + else + { + RsErr() << "Cannot find file!" << std::endl; + return false; + } + + info.path = finfo.absoluteFilePath().toStdString(); + return true; } void GxsChannelFilesStatusWidget::openFile() { FileInfo fileInfo; - if (!rsFiles->alreadyHaveFile(mFile.mHash, fileInfo)) { + if(!haveFile(fileInfo)) return; - } - /* open file with a suitable application */ - QFileInfo qinfo; - qinfo.setFile(QString::fromUtf8(fileInfo.path.c_str())); - if (qinfo.exists()) { - if (!RsUrlHandler::openUrl(QUrl::fromLocalFile(qinfo.absoluteFilePath()))) { + QFileInfo finfo; + finfo.setFile(QString::fromUtf8(fileInfo.path.c_str())); + + if (finfo.exists()) { + if (!RsUrlHandler::openUrl(QUrl::fromLocalFile(finfo.absoluteFilePath()))) { std::cerr << "GxsChannelFilesStatusWidget(): can't open file " << fileInfo.path << std::endl; } }else{ - QMessageBox::information(this, tr("Play File"), - tr("File %1 does not exist at location.").arg(fileInfo.path.c_str())); - return; + if(!mUsedAsEditor) + QMessageBox::information(this, tr("Play File"), + tr("File %1 does not exist at location.").arg(fileInfo.path.c_str())); + else + RsErr() << "File " << fileInfo.path << " does not exist at location." ; + + return; } } diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.h b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.h index 8f2f7f8e4..0dbb5c072 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.h +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.h @@ -34,9 +34,10 @@ class GxsChannelFilesStatusWidget : public QWidget Q_OBJECT public: - explicit GxsChannelFilesStatusWidget(const RsGxsFile &file, QWidget *parent = 0); + explicit GxsChannelFilesStatusWidget(const RsGxsFile &file, QWidget *parent = 0,bool used_as_editor=false); ~GxsChannelFilesStatusWidget(); + bool usedAsEditor() const { return mUsedAsEditor; } signals: void onButtonClick(); @@ -52,6 +53,7 @@ private slots: private: void setSize(uint64_t size); + bool haveFile(FileInfo& info); private: enum State @@ -73,6 +75,8 @@ private: uint64_t mSize; uint64_t mDivisor; + bool mUsedAsEditor; + Ui::GxsChannelFilesStatusWidget *ui; }; diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.ui b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.ui index c1b02ab83..e8ee2d512 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.ui +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.ui @@ -6,14 +6,14 @@ 0 0 - 421 - 29 + 473 + 36 Form - + 0 @@ -27,11 +27,11 @@ 0 - + true - + 2 @@ -120,8 +120,8 @@ Qt::NoFocus - - :/images/cancel.png:/images/cancel.png + + :/icons/cancel.svg:/icons/cancel.svg @@ -139,7 +139,7 @@
    - + 0 diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelGroupDialog.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelGroupDialog.cpp index a98e9016a..0af2631c5 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelGroupDialog.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelGroupDialog.cpp @@ -21,10 +21,11 @@ #include #include "gui/gxs/GxsIdDetails.h" +#include "util/imageutil.h" #include "gui/common/FilesDefs.h" #include "GxsChannelGroupDialog.h" -#include +#include "retroshare/rsgxschannels.h" #include // To start with we only have open forums - with distribution controls. @@ -119,8 +120,10 @@ void GxsChannelGroupDialog::prepareChannelGroup(RsGxsChannelGroup &group, const QByteArray ba; QBuffer buffer(&ba); - buffer.open(QIODevice::WriteOnly); - pixmap.save(&buffer, "PNG"); // writes image into ba in PNG format + bool has_transparency = ImageUtil::hasAlphaContent(pixmap.toImage()); + + buffer.open(QIODevice::WriteOnly); + pixmap.save(&buffer, has_transparency?"PNG":"JPG"); // writes image into ba in PNG format group.mImage.copy((uint8_t *) ba.data(), ba.size()); } else { diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostFilesModel.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostFilesModel.cpp index be2f288ac..806fcaa69 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostFilesModel.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostFilesModel.cpp @@ -33,11 +33,11 @@ #include "GxsChannelPostFilesModel.h" -//#define DEBUG_CHANNEL_MODEL +//#define DEBUG_CHANNEL_FILES_MODEL Q_DECLARE_METATYPE(ChannelPostFileInfo) -#ifdef DEBUG_CHANNEL_MODEL +#ifdef DEBUG_CHANNEL_FILES_MODEL static std::ostream& operator<<(std::ostream& o, const QModelIndex& i);// defined elsewhere #endif @@ -161,8 +161,8 @@ QModelIndex RsGxsChannelPostFilesModel::index(int row, int column, const QModelI quintptr ref = getChildRef(parent.internalId(),row); -#ifdef DEBUG_CHANNEL_MODEL - std::cerr << "index-3(" << row << "," << column << " parent=" << parent << ") : " << createIndex(row,column,ref) << std::endl; +#ifdef DEBUG_CHANNEL_FILES_MODEL + RsDbg() << "index-3(" << row << "," << column << " parent=" << parent << ") : " << createIndex(row,column,ref) ; #endif return createIndex(row,column,ref) ; } @@ -242,7 +242,7 @@ QVariant RsGxsChannelPostFilesModel::headerData(int section, Qt::Orientation /*o QVariant RsGxsChannelPostFilesModel::data(const QModelIndex &index, int role) const { -#ifdef DEBUG_CHANNEL_MODEL +#ifdef DEBUG_CHANNEL_FILES_MODEL std::cerr << "calling data(" << index << ") role=" << role << std::endl; #endif @@ -259,13 +259,13 @@ QVariant RsGxsChannelPostFilesModel::data(const QModelIndex &index, int role) co quintptr ref = (index.isValid())?index.internalId():0 ; uint32_t entry = 0; -#ifdef DEBUG_CHANNEL_MODEL +#ifdef DEBUG_CHANNEL_FILES_MODEL std::cerr << "data(" << index << ")" ; #endif if(!ref) { -#ifdef DEBUG_CHANNEL_MODEL +#ifdef DEBUG_CHANNEL_FILES_MODEL std::cerr << " [empty]" << std::endl; #endif return QVariant() ; @@ -273,7 +273,7 @@ QVariant RsGxsChannelPostFilesModel::data(const QModelIndex &index, int role) co if(!convertRefPointerToTabEntry(ref,entry) || entry >= mFilteredFiles.size()) { -#ifdef DEBUG_CHANNEL_MODEL +#ifdef DEBUG_CHANNEL_FILES_MODEL std::cerr << "Bad pointer: " << (void*)ref << std::endl; #endif return QVariant() ; @@ -295,7 +295,7 @@ void RsGxsChannelPostFilesModel::setFilter(const QStringList& strings, uint32_t& { preMods(); - initEmptyHierarchy(); + mFilteredFiles.clear(); if(strings.empty()) { @@ -317,8 +317,6 @@ void RsGxsChannelPostFilesModel::setFilter(const QStringList& strings, uint32_t& } count = mFilteredFiles.size(); - std::cerr << "After filtering: " << count << " posts remain." << std::endl; - if (rowCount()>0) { beginInsertRows(QModelIndex(),0,rowCount()-1); @@ -344,10 +342,20 @@ public: case RsGxsChannelPostFilesModel::COLUMN_FILES_FILE: { FileInfo fi1,fi2; - rsFiles->FileDetails(f1.mHash,RS_FILE_HINTS_DOWNLOAD,fi1); - rsFiles->FileDetails(f2.mHash,RS_FILE_HINTS_DOWNLOAD,fi2); + bool r1 = rsFiles->FileDetails(f1.mHash,RS_FILE_HINTS_DOWNLOAD,fi1); + bool r2 = rsFiles->FileDetails(f2.mHash,RS_FILE_HINTS_DOWNLOAD,fi2); - return (ord==Qt::AscendingOrder)?(fi1.transferedfi2.transfered); + if(r1 && r2) + return (ord==Qt::AscendingOrder)?(fi1.transferedfi2.transfered); + else + { + FileInfo fitmp; + + if(!r1 && rsFiles->alreadyHaveFile(f1.mHash,fitmp)) fi1.downloadStatus = FT_STATE_COMPLETE; + if(!r2 && rsFiles->alreadyHaveFile(f2.mHash,fitmp)) fi2.downloadStatus = FT_STATE_COMPLETE; + + return (ord==Qt::AscendingOrder)?(fi1.downloadStatusfi2.downloadStatus); + } } } @@ -428,7 +436,6 @@ QVariant RsGxsChannelPostFilesModel::userRole(const ChannelPostFileInfo& fmpe,in void RsGxsChannelPostFilesModel::clear() { - initEmptyHierarchy(); emit channelLoaded(); @@ -446,7 +453,7 @@ void RsGxsChannelPostFilesModel::setFiles(const std::list & for(uint32_t i=0;i & postMods(); } + +void RsGxsChannelPostFilesModel::update_files(std::set& added_files,std::set& removed_files) +{ + // 1 - remove common files from both lists + +#ifdef DEBUG_CHANNEL_FILES_MODEL + RsDbg() << "RsGxsChannelPostsFilesModel:: updating files." ; +#endif + + for(auto afit=added_files.begin();afit!=added_files.end();) + { + auto rfit = removed_files.find(*afit); + + if(rfit != removed_files.end()) + { +#ifdef DEBUG_CHANNEL_FILES_MODEL + RsDbg() << " Eliminating common file " << rfit->mName ; +#endif + removed_files.erase(rfit); + auto tmp = afit; + ++tmp; + added_files.erase(afit); + afit = tmp; + } + else + ++afit; + } +#ifdef DEBUG_CHANNEL_FILES_MODEL + RsDbg() << " Remains: " << added_files.size() << " added files and " << removed_files.size() << " removed files" ; +#endif + + // 2 - add whatever file remains, + + for(const auto& f:removed_files) + { +#ifdef DEBUG_CHANNEL_FILES_MODEL + RsDbg() << " Removing deleted file " << f.mName ; +#endif + + for(uint32_t i=0;i& files); + void setFiles(const std::list& files); void setFilter(const QStringList &strings, uint32_t &count) ; + // This method adds/removes the given lists of files. Useful when a single post is updated + void update_files(std::set &added_files, std::set &removed_files); + #ifdef TODO - QModelIndex getIndexOfFile(const RsFileHash& hash) const; + QModelIndex getIndexOfFile(const RsFileHash& hash) const; void setSortMode(SortMode mode) ; - void setTextColorRead (QColor color) { mTextColorRead = color;} - void setTextColorUnread (QColor color) { mTextColorUnread = color;} - void setTextColorUnreadChildren(QColor color) { mTextColorUnreadChildren = color;} - void setTextColorNotSubscribed (QColor color) { mTextColorNotSubscribed = color;} - void setTextColorMissing (QColor color) { mTextColorMissing = color;} - void setAuthorOpinion(const QModelIndex& indx,RsOpinion op); + void setTextColorRead (QColor color) { mTextColorRead = color;} + void setTextColorUnread (QColor color) { mTextColorUnread = color;} + void setTextColorUnreadChildren(QColor color) { mTextColorUnreadChildren = color;} + void setTextColorNotSubscribed (QColor color) { mTextColorNotSubscribed = color;} + void setTextColorMissing (QColor color) { mTextColorMissing = color;} + void setAuthorOpinion(const QModelIndex& indx,RsOpinion op); #endif // Helper functions @@ -112,25 +115,25 @@ public: Qt::ItemFlags flags(const QModelIndex& index) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; // Custom item roles QVariant sizeHintRole (int col) const; - QVariant displayRole (const ChannelPostFileInfo& fmpe, int col) const; - QVariant toolTipRole (const ChannelPostFileInfo& fmpe, int col) const; - QVariant userRole (const ChannelPostFileInfo& fmpe, int col) const; - QVariant sortRole (const ChannelPostFileInfo& fmpe, int col) const; - QVariant filterRole (const ChannelPostFileInfo& fmpe, int col) const; + QVariant displayRole (const ChannelPostFileInfo& fmpe, int col) const; + QVariant toolTipRole (const ChannelPostFileInfo& fmpe, int col) const; + QVariant userRole (const ChannelPostFileInfo& fmpe, int col) const; + QVariant sortRole (const ChannelPostFileInfo& fmpe, int col) const; + QVariant filterRole (const ChannelPostFileInfo& fmpe, int col) const; #ifdef TODO - QVariant decorationRole(const ForumModelPostEntry& fmpe, int col) const; - QVariant pinnedRole (const ForumModelPostEntry& fmpe, int col) const; - QVariant missingRole (const ForumModelPostEntry& fmpe, int col) const; - QVariant statusRole (const ForumModelPostEntry& fmpe, int col) const; - QVariant authorRole (const ForumModelPostEntry& fmpe, int col) const; - QVariant fontRole (const ForumModelPostEntry& fmpe, int col) const; - QVariant textColorRole (const ForumModelPostEntry& fmpe, int col) const; - QVariant backgroundRole(const ForumModelPostEntry& fmpe, int col) const; + QVariant decorationRole(const ForumModelPostEntry& fmpe, int col) const; + QVariant pinnedRole (const ForumModelPostEntry& fmpe, int col) const; + QVariant missingRole (const ForumModelPostEntry& fmpe, int col) const; + QVariant statusRole (const ForumModelPostEntry& fmpe, int col) const; + QVariant authorRole (const ForumModelPostEntry& fmpe, int col) const; + QVariant fontRole (const ForumModelPostEntry& fmpe, int col) const; + QVariant textColorRole (const ForumModelPostEntry& fmpe, int col) const; + QVariant backgroundRole(const ForumModelPostEntry& fmpe, int col) const; #endif /*! @@ -151,20 +154,20 @@ private: bool mFilteringEnabled; SortMode mSortMode; #endif - void preMods() ; - void postMods() ; + void preMods() ; + void postMods() ; quintptr getParentRow(quintptr ref,int& row) const; quintptr getChildRef(quintptr ref, int index) const; int getChildrenCount(quintptr ref) const; static bool convertTabEntryToRefPointer(uint32_t entry, quintptr& ref); - static bool convertRefPointerToTabEntry(quintptr ref,uint32_t& entry); + static bool convertRefPointerToTabEntry(quintptr ref,uint32_t& entry); #ifdef TODO - static void generateMissingItem(const RsGxsMessageId &msgId,ChannelPostsModelPostEntry& entry); + static void generateMissingItem(const RsGxsMessageId &msgId,ChannelPostsModelPostEntry& entry); #endif - void initEmptyHierarchy(); + void initEmptyHierarchy(); std::vector mFilteredFiles ; // store the list of files for the post std::vector mFiles ; // store the list of files for the post diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostThumbnail.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostThumbnail.cpp index eb890b075..560c37577 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostThumbnail.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostThumbnail.cpp @@ -217,6 +217,25 @@ float ChannelPostThumbnailView::thumbnail_h() const } } +void ZoomableLabel::keyPressEvent(QKeyEvent *e) +{ + switch(e->key()) + { + case Qt::Key_Delete: + + if(mClearEnabled) + { + mFullImage = QPixmap(); + emit cleared(); + e->accept(); + updateView(); + } + break; + default: + QLabel::keyPressEvent(e); + } +} + void ZoomableLabel::reset() { mCenterX = mFullImage.width()/2.0; @@ -290,6 +309,24 @@ void ZoomableLabel::wheelEvent(QWheelEvent *me) updateView(); } +#if QT_VERSION >= QT_VERSION_CHECK (6, 0, 0) +void ZoomableLabel::enterEvent(QEnterEvent* /*event*/) +#else +void ZoomableLabel::enterEvent(QEvent* /*event*/) +#endif +{ + if (mUseStyleSheet) { + setStyleSheet("QLabel { border: 2px solid #039bd5; }"); + } +} + +void ZoomableLabel::ZoomableLabel::leaveEvent(QEvent* /*event*/) +{ + if (mUseStyleSheet) { + setStyleSheet("QLabel { border: 2px solid #CCCCCC; border-radius: 3px; }"); + } +} + QPixmap ZoomableLabel::extractCroppedScaledPicture() const { QRect rect(mCenterX - 0.5 * width()*mZoomFactor, mCenterY - 0.5 * height()*mZoomFactor, width()*mZoomFactor, height()*mZoomFactor); @@ -331,7 +368,7 @@ void ZoomableLabel::updateView() std::cerr << " Image size: " << mFullImage.width() << " x " << mFullImage.height() << ", window size: " << width() << " x " << height() << std::endl; std::cerr << " cropped image: " << rect.left() << "," << rect.top() << "+" << rect.width() << "+" << rect.height() << std::endl; std::cerr << " saving crop to pix2.png" << std::endl; - mFullImage.copy(rect).save("pix2.png","PNG"); + mFullImage.copy(rect).save("pix2.png","JPG"); #endif QLabel::setPixmap(mFullImage.copy(rect)); } diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostThumbnail.h b/retroshare-gui/src/gui/gxschannels/GxsChannelPostThumbnail.h index d89fd5eca..da30f2083 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostThumbnail.h +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostThumbnail.h @@ -40,18 +40,22 @@ class ZoomableLabel: public QLabel Q_OBJECT public: - ZoomableLabel(QWidget *parent): QLabel(parent),mUseStyleSheet(true),mZoomFactor(1.0),mCenterX(0.0),mCenterY(0.0),mZoomEnabled(true) {} + ZoomableLabel(QWidget *parent): QLabel(parent),mUseStyleSheet(true),mZoomFactor(1.0),mCenterX(0.0),mCenterY(0.0),mZoomEnabled(true),mClearEnabled(false) {} void setPicture(const QPixmap& pix); void setEnableZoom(bool b) { mZoomEnabled = b; } + void setEnableClear(bool b) { mClearEnabled = b; } void reset(); QPixmap extractCroppedScaledPicture() const; void updateView(); + virtual void keyPressEvent(QKeyEvent *ev) override; + const QPixmap& originalImage() const { return mFullImage ; } signals: void clicked(); + void cleared(); protected: void mousePressEvent(QMouseEvent *ev) override; @@ -60,8 +64,12 @@ protected: void resizeEvent(QResizeEvent *ev) override; void wheelEvent(QWheelEvent *me) override; - void enterEvent(QEvent * /* ev */ ) override { if(mUseStyleSheet) setStyleSheet("QLabel { border: 2px solid #039bd5; }");} - void leaveEvent(QEvent * /* ev */ ) override { if(mUseStyleSheet) setStyleSheet("QLabel { border: 2px solid #CCCCCC; border-radius: 3px; }");} +#if QT_VERSION >= QT_VERSION_CHECK (6, 0, 0) + void enterEvent(QEnterEvent *event) override; +#else + void enterEvent(QEvent *event) override; +#endif + void leaveEvent(QEvent *event) override; bool mUseStyleSheet; @@ -73,6 +81,7 @@ protected: int mLastX,mLastY; bool mMoving; bool mZoomEnabled; + bool mClearEnabled; }; // Class to paint the thumbnails with title @@ -102,7 +111,7 @@ public: static const int THUMBNAIL_W = 4; static const int THUMBNAIL_H = 6; - static constexpr char *CHAN_DEFAULT_IMAGE = ":images/thumb-default-video.png"; + static constexpr const char *CHAN_DEFAULT_IMAGE = ":images/thumb-default-video.png"; virtual ~ChannelPostThumbnailView(); ChannelPostThumbnailView(QWidget *parent=NULL,uint32_t flags=FLAG_ALLOW_PAN | FLAG_SHOW_TEXT | FLAG_SCALE_FONT); diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp index 31eef8242..8b5b7e707 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp @@ -27,6 +27,8 @@ #include "retroshare/rsgxschannels.h" #include "retroshare/rsexpr.h" +#include "gui/MainWindow.h" +#include "gui/mainpagestack.h" #include "gui/common/FilesDefs.h" #include "util/qtthreadsutils.h" #include "util/HandleRichText.h" @@ -35,10 +37,10 @@ #include "GxsChannelPostsModel.h" #include "GxsChannelPostFilesModel.h" +//#define DEBUG_CHANNEL_MODEL_DATA //#define DEBUG_CHANNEL_MODEL Q_DECLARE_METATYPE(RsMsgMetaData) - Q_DECLARE_METATYPE(RsGxsChannelPost) std::ostream& operator<<(std::ostream& o, const QModelIndex& i);// defined elsewhere @@ -47,14 +49,6 @@ RsGxsChannelPostsModel::RsGxsChannelPostsModel(QObject *parent) : QAbstractItemModel(parent), mTreeMode(RsGxsChannelPostsModel::TREE_MODE_GRID), mColumns(6) { initEmptyHierarchy(); - - mEventHandlerId = 0; - // Needs to be asynced because this function is called by another thread! - - rsEvents->registerEventsHandler( [this](std::shared_ptr event) - { - RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); - }, mEventHandlerId, RsEventType::GXS_CHANNELS ); } RsGxsChannelPostsModel::~RsGxsChannelPostsModel() @@ -69,137 +63,10 @@ void RsGxsChannelPostsModel::setMode(TreeMode mode) if(mode == TREE_MODE_LIST) setNumColumns(2); - triggerViewUpdate(); -} - -void updateCommentCounts( std::vector& posts, std::vector& comments) -{ - // Store posts IDs in a std::map to avoid a quadratic cost - - std::map post_indices; - - for(uint32_t i=0;isecond>=posts.size() is impossible by construction, since post_indices - // is previously filled using posts ids. - - if(it == post_indices.end()) - continue; - - ++posts[it->second].mCommentCount; - - if(IS_MSG_NEW(comments[i].mMeta.mMsgStatus)) - ++posts[it->second].mUnreadCommentCount; - } + triggerViewUpdate(true,true); } -void RsGxsChannelPostsModel::handleEvent_main_thread(std::shared_ptr event) -{ - const RsGxsChannelEvent *e = dynamic_cast(event.get()); - - if(!e) - return; - - switch(e->mChannelEventCode) - { - case RsChannelEventCode::UPDATED_MESSAGE: - case RsChannelEventCode::READ_STATUS_CHANGED: - { - // Normally we should just emit dataChanged() on the index of the data that has changed: - // We need to update the data! - - // make a copy of e, so as to avoid destruction of the shared pointer during async thread execution, since [e] doesn't actually tell - // the original shared_ptr that it is copied! So no counter is updated in event, which will be destroyed (as e will be) during or even before - // the execution of the lambda. - - RsGxsChannelEvent E(*e); - - if(E.mChannelGroupId == mChannelGroup.mMeta.mGroupId) - RsThread::async([this, E]() - { - // 1 - get message data from p3GxsChannels. No need for pointers here, because we send only a single post to postToObject() - // At this point we dont know what kind of msg id we have. It can be a vote, a comment or an actual message. - - std::vector posts; - std::vector comments; - std::vector votes; - std::set msg_ids{ E.mChannelMsgId }; - - if(!rsGxsChannels->getChannelContent(E.mChannelGroupId,msg_ids, posts,comments,votes)) - { - std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve channel message data for channel/msg " << E.mChannelGroupId << "/" << E.mChannelMsgId << std::endl; - return; - } - - // Check if what we have actually is a comment or a vote. If so we need to update the actual message they refer to - - if(posts.empty()) // means we have a comment or a vote - { - msg_ids.clear(); - - for(auto c:comments) msg_ids.insert(c.mMeta.mThreadId); - for(auto v:votes ) msg_ids.insert(v.mMeta.mThreadId); - - comments.clear(); - votes.clear(); - - if(!rsGxsChannels->getChannelContent(E.mChannelGroupId,msg_ids,posts,comments,votes)) - { - std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve channel message data for channel/msg " << E.mChannelGroupId << "/" << E.mChannelMsgId << std::endl; - return; - } - } - - // Need to call this in order to get the actuall comment count. The previous call only retrieves the message, since we supplied the message ID. - // another way to go would be to save the comment ids of the existing message and re-insert them before calling getChannelContent. - - if(!rsGxsChannels->getChannelComments(E.mChannelGroupId,msg_ids,comments)) - { - std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve message comment data for channel/msg " << E.mChannelGroupId << "/" << E.mChannelMsgId << std::endl; - return; - } - - updateCommentCounts(posts,comments); - - // 2 - update the model in the UI thread. - - RsQThreadUtils::postToObject( [posts,this]() - { - for(uint32_t i=0;i& files) @@ -241,29 +111,39 @@ void RsGxsChannelPostsModel::getFilesList(std::list& files) files.push_back(it.second); } +bool RsGxsChannelPostsModel::postPassesFilter(const RsGxsChannelPost& post,const QStringList& strings,bool only_unread) const +{ + bool passes_strings = true; + + for(auto& s:strings) + passes_strings = passes_strings && QString::fromStdString(post.mMeta.mMsgName).contains(s,Qt::CaseInsensitive); + + if(strings.empty()) + passes_strings = true; + + if(passes_strings && (!only_unread || (IS_MSG_UNREAD(post.mMeta.mMsgStatus) || IS_MSG_NEW(post.mMeta.mMsgStatus)))) + return true; + + return false; +} + void RsGxsChannelPostsModel::setFilter(const QStringList& strings,bool only_unread, uint32_t& count) +{ + mFilteredStrings = strings; + mFilterUnread = only_unread; + + updateFilter(count); +} + +void RsGxsChannelPostsModel::updateFilter(uint32_t& count) { preMods(); - beginResetModel(); - mFilteredPosts.clear(); - //mFilteredPosts.push_back(0); - endResetModel(); for(size_t i=0;i 0) + return r; + else + return columnCount(); + } + else + return columnCount(); + } + else + return 2; +} int RsGxsChannelPostsModel::columnCount(const QModelIndex &/*parent*/) const { if(mTreeMode == TREE_MODE_GRID) @@ -365,12 +264,12 @@ bool RsGxsChannelPostsModel::convertRefPointerToTabEntry(quintptr ref, uint32_t& QModelIndex RsGxsChannelPostsModel::index(int row, int column, const QModelIndex & parent) const { - if(row < 0 || column < 0 || column >= (int)mColumns) + if(row < 0 || column < 0 || row >= rowCount() || column >= columnCount(row)) return QModelIndex(); quintptr ref = getChildRef(parent.internalId(),(mTreeMode == TREE_MODE_GRID)?(column + row*mColumns):row); -#ifdef DEBUG_CHANNEL_MODEL +#ifdef DEBUG_CHANNEL_MODEL_DATA std::cerr << "index-3(" << row << "," << column << " parent=" << parent << ") : " << createIndex(row,column,ref) << std::endl; #endif return createIndex(row,column,ref) ; @@ -401,17 +300,8 @@ bool RsGxsChannelPostsModel::setNumColumns(int n) preMods(); - beginResetModel(); - endResetModel(); - mColumns = n; - if (rowCount()>0) - { - beginInsertRows(QModelIndex(),0,rowCount()-1); - endInsertRows(); - } - postMods(); return true; @@ -460,7 +350,7 @@ int RsGxsChannelPostsModel::getChildrenCount(quintptr ref) const QVariant RsGxsChannelPostsModel::data(const QModelIndex &index, int role) const { -#ifdef DEBUG_CHANNEL_MODEL +#ifdef DEBUG_CHANNEL_MODEL_DATA std::cerr << "calling data(" << index << ") role=" << role << std::endl; #endif @@ -477,13 +367,13 @@ QVariant RsGxsChannelPostsModel::data(const QModelIndex &index, int role) const quintptr ref = (index.isValid())?index.internalId():0 ; uint32_t entry = 0; -#ifdef DEBUG_CHANNEL_MODEL +#ifdef DEBUG_CHANNEL_MODEL_DATA std::cerr << "data(" << index << ")" ; #endif if(!ref) { -#ifdef DEBUG_CHANNEL_MODEL +#ifdef DEBUG_CHANNEL_MODEL_DATA std::cerr << " [empty]" << std::endl; #endif return QVariant() ; @@ -491,7 +381,7 @@ QVariant RsGxsChannelPostsModel::data(const QModelIndex &index, int role) const if(!convertRefPointerToTabEntry(ref,entry) || entry >= mFilteredPosts.size()) { -#ifdef DEBUG_CHANNEL_MODEL +#ifdef DEBUG_CHANNEL_MODEL_DATA std::cerr << "Bad pointer: " << (void*)ref << std::endl; #endif return QVariant() ; @@ -540,7 +430,6 @@ const RsGxsGroupId& RsGxsChannelPostsModel::currentGroupId() const { return mChannelGroup.mMeta.mGroupId; } - void RsGxsChannelPostsModel::updateChannel(const RsGxsGroupId& channel_group_id) { if(channel_group_id.isNull()) @@ -564,6 +453,79 @@ bool operator<(const RsGxsChannelPost& p1,const RsGxsChannelPost& p2) return p1.mMeta.mPublishTs > p2.mMeta.mPublishTs; } +void RsGxsChannelPostsModel::updateSinglePost(const RsGxsChannelPost& post,std::set& added_files,std::set& removed_files) +{ +#ifdef DEBUG_CHANNEL_MODEL + RsDbg() << "updating single post for group id=" << currentGroupId() << " and msg id=" << post.mMeta.mMsgId ; +#endif + added_files.clear(); + removed_files.clear(); + + emit layoutAboutToBeChanged(); + + // linear search. Not good at all, but normally this is just for a single post. + + bool found = false; + const auto& new_post_meta(post.mMeta); + + for(uint32_t j=0;j& posts) { preMods(); @@ -571,8 +533,9 @@ void RsGxsChannelPostsModel::setPosts(const RsGxsChannelGroup& group, std::vecto initEmptyHierarchy(); mChannelGroup = group; - createPostsArray(posts); +// createPostsArray(posts); + mPosts = posts; std::sort(mPosts.begin(),mPosts.end()); for(uint32_t i=0;isetCursor(Qt::WaitCursor) ; // Maybe we should pass that widget when calling update_posts + + RsThread::async([this, group_id]() { // 1 - get message data from p3GxsChannels @@ -616,30 +583,25 @@ void RsGxsChannelPostsModel::update_posts(const RsGxsGroupId& group_id) RsGxsChannelGroup group = groups[0]; - // We use the heap because the arrays need to be stored accross async + std::vector *posts = new std::vector(); // We use the heap because the arrays need to be stored accross async + std::vector comments ; + std::vector votes ; - std::vector *posts = new std::vector(); - std::vector *comments = new std::vector(); - std::vector *votes = new std::vector(); - - if(!rsGxsChannels->getChannelAllContent(group_id, *posts,*comments,*votes)) + if(!rsGxsChannels->getChannelAllContent(group_id, *posts,comments,votes)) { std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve channel messages for channel " << group_id << std::endl; return; } +#ifdef DEBUG_CHANNEL_MODEL std::cerr << "Got channel all content for channel " << group_id << std::endl; std::cerr << " posts : " << posts->size() << std::endl; - std::cerr << " comments: " << comments->size() << std::endl; - std::cerr << " votes : " << votes->size() << std::endl; - - // This shouldn't be needed normally. We need it until a background process computes the number of comments per - // post and stores it in the service string. Since we request all data, this process isn't costing much anyway. - - updateCommentCounts(*posts,*comments); + std::cerr << " comments: " << comments.size() << std::endl; + std::cerr << " votes : " << votes.size() << std::endl; +#endif // 2 - update the model in the UI thread. - RsQThreadUtils::postToObject( [group,posts,comments,votes,this]() + RsQThreadUtils::postToObject( [group,posts,this]() { /* Here it goes any code you want to be executed on the Qt Gui * thread, for example to update the data model with new information @@ -650,132 +612,14 @@ void RsGxsChannelPostsModel::update_posts(const RsGxsGroupId& group_id) setPosts(group,*posts) ; delete posts; - delete comments; - delete votes; - }, this ); + MainWindow::getPage(MainWindow::Channels)->setCursor(Qt::ArrowCursor) ; + + }, this ); }); } -void RsGxsChannelPostsModel::createPostsArray(std::vector& posts) -{ - // collect new versions of posts if any - -#ifdef DEBUG_CHANNEL_MODEL - std::cerr << "Inserting channel posts" << std::endl; -#endif - - std::vector new_versions ; - for (uint32_t i=0;i search_map ; - for (uint32_t i=0;i versions ; - std::map::const_iterator vit ; - - while(search_map.end() != (vit=search_map.find(posts[current_index].mMeta.mOrigMsgId))) - { -#ifdef DEBUG_CHANNEL_MODEL - std::cerr << " post at index " << current_index << " replaces a post at position " << vit->second ; -#endif - - // Now replace the post only if the new versionis more recent. It may happen indeed that the same post has been corrected multiple - // times. In this case, we only need to replace the post with the newest version - - //uint32_t prev_index = current_index ; - current_index = vit->second ; - - if(posts[current_index].mMeta.mMsgId.isNull()) // This handles the branching situation where this post has been already erased. No need to go down further. - { -#ifdef DEBUG_CHANNEL_MODEL - std::cerr << " already erased. Stopping." << std::endl; -#endif - break ; - } - - if(posts[current_index].mMeta.mPublishTs < posts[source_index].mMeta.mPublishTs) - { -#ifdef DEBUG_CHANNEL_MODEL - std::cerr << " and is more recent => following" << std::endl; -#endif - for(std::set::const_iterator itt(posts[current_index].mOlderVersions.begin());itt!=posts[current_index].mOlderVersions.end();++itt) - posts[source_index].mOlderVersions.insert(*itt); - - posts[source_index].mOlderVersions.insert(posts[current_index].mMeta.mMsgId); - posts[current_index].mMeta.mMsgId.clear(); // clear the msg Id so the post will be ignored - } -#ifdef DEBUG_CHANNEL_MODEL - else - std::cerr << " but is older -> Stopping" << std::endl; -#endif - } - } - } - -#ifdef DEBUG_CHANNEL_MODEL - std::cerr << "Now adding " << posts.size() << " posts into array structure..." << std::endl; -#endif - - mPosts.clear(); - - for (std::vector::const_reverse_iterator it = posts.rbegin(); it != posts.rend(); ++it) - { - if(!(*it).mMeta.mMsgId.isNull()) - { -#ifdef DEBUG_CHANNEL_MODEL - std::cerr << " adding post \"" << (*it).mMeta.mMsgName << "\"" << std::endl; -#endif - mPosts.push_back(*it); - } -#ifdef DEBUG_CHANNEL_MODEL - else - std::cerr << " skipped older version post \"" << (*it).mMeta.mMsgName << "\"" << std::endl; -#endif - } -} - void RsGxsChannelPostsModel::setAllMsgReadStatus(bool read_status) { // No need to call preMods()/postMods() here because we're not changing the model @@ -798,11 +642,31 @@ void RsGxsChannelPostsModel::setAllMsgReadStatus(bool read_status) for(uint32_t i=0;imarkRead(p,read_status)) + if(!rsGxsChannels->setMessageReadStatus(p,read_status)) RsErr() << "setAllMsgReadStatus: failed to change status of msg " << p.first << " in group " << p.second << " to status " << read_status << std::endl; }); + + // 3 - update the local model data, since we don't catch the READ_STATUS_CHANGED event later, to avoid re-loading the msg. + + for(uint32_t i=0;i= mFilteredPosts.size()) return ; - rsGxsChannels->markRead(RsGxsGrpMsgIdPair(mPosts[mFilteredPosts[entry]].mMeta.mGroupId,mPosts[mFilteredPosts[entry]].mMeta.mMsgId),read_status); + rsGxsChannels->setMessageReadStatus(RsGxsGrpMsgIdPair(mPosts[mFilteredPosts[entry]].mMeta.mGroupId,mPosts[mFilteredPosts[entry]].mMeta.mMsgId),read_status); + + // Quick update to the msg itself. Normally setMsgReadStatus will launch an event, + // that we can catch to update the msg, but all the information is already here. + + if(read_status) + mPosts[mFilteredPosts[entry]].mMeta.mMsgStatus &= ~(GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD | GXS_SERV::GXS_MSG_STATUS_GUI_NEW); + else + mPosts[mFilteredPosts[entry]].mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; + + mPosts[mFilteredPosts[entry]].mUnreadCommentCount = 0; + + emit dataChanged(i,i); } QModelIndex RsGxsChannelPostsModel::getIndexOfMessage(const RsGxsMessageId& mid) const diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.h b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.h index d8385d24b..c447f11a3 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.h +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.h @@ -101,9 +101,11 @@ public: SORT_MODE_CHILDREN_PUBLISH_TS = 0x01, }; #endif + static void computeCommentCounts( std::vector& posts, std::vector& comments); QModelIndex root() const{ return createIndex(0,0,(void*)NULL) ;} QModelIndex getIndexOfMessage(const RsGxsMessageId& mid) const; + int columnCount(int row) const; // columns in the row of this particular index. std::vector > getPostVersions(const RsGxsMessageId& mid) const; @@ -114,7 +116,7 @@ public: void updateChannel(const RsGxsGroupId& channel_group_id); const RsGxsGroupId& currentGroupId() const; - void triggerViewUpdate(); + void triggerViewUpdate(bool data_changed,bool layout_changed); // sets the number of columns. Returns 0 if nothing changes. bool setNumColumns(int n); @@ -138,8 +140,11 @@ public: void setMsgReadStatus(const QModelIndex &i, bool read_status); void setAllMsgReadStatus(bool read_status); + void updatePostWithNewComment(const RsGxsMessageId& msg_id); void setFilter(const QStringList &strings, bool only_unread,uint32_t &count) ; + bool postPassesFilter(const RsGxsChannelPost &post, const QStringList &strings, bool only_unread) const; + void updateFilter(uint32_t& count); #ifdef TODO void setAuthorOpinion(const QModelIndex& indx,RsOpinion op); @@ -215,6 +220,8 @@ private: void update_posts(const RsGxsGroupId& group_id); +private: + #ifdef TODO void setForumMessageSummary(const std::vector& messages); #endif @@ -229,10 +236,16 @@ private: //static void convertMsgToPostEntry(const RsGxsChannelGroup &mChannelGroup, const RsMsgMetaData &msg, bool useChildTS, ChannelModelPostEntry& fentry); //void computeMessagesHierarchy(const RsGxsChannelGroup& forum_group, const std::vector &msgs_array, std::vector &posts, std::map > > &mPostVersions); - void createPostsArray(std::vector &posts); - void setPosts(const RsGxsChannelGroup& group, std::vector &posts); - void initEmptyHierarchy(); - void handleEvent_main_thread(std::shared_ptr event); + void old_createPostsArray(std::vector &posts); + void createPostsArray(std::vector& posts); + void setPosts(const RsGxsChannelGroup& group, std::vector &posts); +public: + void updateSinglePost(const RsGxsChannelPost& post, std::set& added_files, std::set& removed_files); +private: + void initEmptyHierarchy(); + + QStringList mFilteredStrings; + bool mFilterUnread; std::vector mFilteredPosts; // stores the list of displayes indices due to filtering. std::vector mPosts ; // store the list of posts updated from rsForums. diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp index d3c4070b0..c041e4369 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp @@ -41,6 +41,7 @@ #include "util/DateTime.h" #include "util/qtthreadsutils.h" #include "gui/common/FilesDefs.h" +#include "util/QtVersion.h" #include "GxsChannelPostsWidgetWithModel.h" #include "GxsChannelPostsModel.h" @@ -56,8 +57,6 @@ * #define DEBUG_CHANNEL ***/ -//static const int mTokenTypeGroupData = 1; - static const int CHANNEL_TABS_DETAILS= 0; static const int CHANNEL_TABS_POSTS = 1; static const int CHANNEL_TABS_FILES = 2; @@ -75,12 +74,13 @@ QColor SelectedColor = QRgb(0xff308dc7); #define COLUMN_SIZE_FONT_FACTOR_W 6 #define COLUMN_SIZE_FONT_FACTOR_H 10 -#define STAR_OVERLAY_IMAGE ":icons/star_overlay_128.png" -#define COMMENT_OVERLAY_IMAGE ":images/white-bubble-64.png" -#define IMAGE_COPYLINK ":icons/png/copy.png" -#define IMAGE_GRID_VIEW ":icons/png/menu.png" -#define IMAGE_DOWNLOAD ":icons/png/download.png" -#define IMAGE_UNREAD ":icons/png/message.png" +#define STAR_OVERLAY_IMAGE ":icons/star_overlay_128.png" +#define COMMENT_OVERLAY_IMAGE ":images/white-bubble-64.png" +#define UNREAD_COMMENT_OVERLAY_IMAGE ":images/orange-bubble-64.png" +#define IMAGE_COPYLINK ":icons/png/copy.png" +#define IMAGE_GRID_VIEW ":icons/png/menu.png" +#define IMAGE_DOWNLOAD ":icons/png/download.png" +#define IMAGE_UNREAD ":icons/png/message.png" Q_DECLARE_METATYPE(ChannelPostFileInfo) @@ -93,17 +93,17 @@ Q_DECLARE_METATYPE(ChannelPostFileInfo) int ChannelPostDelegate::cellSize(int col,const QFont& font,uint32_t parent_width) const { if(mUseGrid || col==0) - return mZoom*COLUMN_SIZE_FONT_FACTOR_W*QFontMetricsF(font).height(); + return (int)floor(mZoom*COLUMN_SIZE_FONT_FACTOR_W*QFontMetricsF(font).height()); else - return 0.8*parent_width - mZoom*COLUMN_SIZE_FONT_FACTOR_W*QFontMetricsF(font).height(); + return (int)floor(0.8*parent_width - mZoom*COLUMN_SIZE_FONT_FACTOR_W*QFontMetricsF(font).height()); } void ChannelPostDelegate::zoom(bool zoom_or_unzoom) { if(zoom_or_unzoom) - mZoom *= 1.02; + mZoom *= 1.02; else - mZoom /= 1.02; + mZoom /= 1.02; if(mZoom < 0.5) mZoom = 0.5; @@ -123,11 +123,7 @@ void ChannelPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem & RsGxsChannelPost post = index.data(Qt::UserRole).value() ; - // if(index.row() & 0x01) - // painter->fillRect( option.rect, option.palette.alternateBase().color()); - // else - painter->fillRect( option.rect, option.palette.base().color()); - + painter->fillRect( option.rect, option.palette.base().color()); painter->restore(); if(mUseGrid || index.column()==0) @@ -146,14 +142,7 @@ void ChannelPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem & if((option.state & QStyle::State_Selected) && post.mMeta.mPublishTs > 0) // check if post is selected and is not empty (end of last row) pixmap.fill(SelectedColor); // I dont know how to grab the backgroud color for selected objects automatically. else - { - // we need to do the alternate color manually - - //if(index.row() & 0x01) - // pixmap.fill(option.palette.alternateBase().color()); - //else - pixmap.fill(option.palette.base().color()); - } + pixmap.fill(option.palette.base().color()); w.render(&pixmap,QPoint(),QRegion(),QWidget::DrawChildren );// draw the widgets, not the background @@ -166,37 +155,43 @@ void ChannelPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem & // { // QFile file("yourFile.png"); // file.open(QIODevice::WriteOnly); -// pixmap.save(&file, "PNG"); +// pixmap.save(&file, "JPG"); // file.close(); // } - if(mUseGrid || index.column()==0) + if(mZoom != 1.0) + pixmap = pixmap.scaled(mZoom*pixmap.size(),Qt::KeepAspectRatio,Qt::SmoothTransformation); + + if(IS_MSG_UNREAD(post.mMeta.mMsgStatus) || IS_MSG_NEW(post.mMeta.mMsgStatus)) { - if(mZoom != 1.0) - pixmap = pixmap.scaled(mZoom*pixmap.size(),Qt::KeepAspectRatio,Qt::SmoothTransformation); + QPainter p(&pixmap); + QFontMetricsF fm(option.font); - if(IS_MSG_UNREAD(post.mMeta.mMsgStatus) || IS_MSG_NEW(post.mMeta.mMsgStatus)) - { - QPainter p(&pixmap); - QFontMetricsF fm(option.font); + p.drawPixmap(mZoom*QPoint(0.1*fm.height(),-3.4*fm.height()),FilesDefs::getPixmapFromQtResourcePath(STAR_OVERLAY_IMAGE).scaled(mZoom*6*fm.height(),mZoom*6*fm.height(),Qt::KeepAspectRatio,Qt::SmoothTransformation)); + } - p.drawPixmap(mZoom*QPoint(0.1*fm.height(),-3.4*fm.height()),FilesDefs::getPixmapFromQtResourcePath(STAR_OVERLAY_IMAGE).scaled(mZoom*6*fm.height(),mZoom*6*fm.height(),Qt::KeepAspectRatio,Qt::SmoothTransformation)); - } + if(post.mUnreadCommentCount > 0) + { + QPainter p(&pixmap); + QFontMetricsF fm(option.font); - if(post.mUnreadCommentCount) - { - QPainter p(&pixmap); - QFontMetricsF fm(option.font); - - p.drawPixmap(QPoint(pixmap.width(),0.0)+mZoom*QPoint(-2.9*fm.height(),0.4*fm.height()), - FilesDefs::getPixmapFromQtResourcePath(COMMENT_OVERLAY_IMAGE).scaled(mZoom*3*fm.height(),mZoom*3*fm.height(), - Qt::KeepAspectRatio,Qt::SmoothTransformation)); - } + p.drawPixmap(QPoint(pixmap.width(),0.0)+mZoom*QPoint(-2.9*fm.height(),0.4*fm.height()), + FilesDefs::getPixmapFromQtResourcePath(UNREAD_COMMENT_OVERLAY_IMAGE).scaled(mZoom*3*fm.height(),mZoom*3*fm.height(), + Qt::KeepAspectRatio,Qt::SmoothTransformation)); + } + else if(post.mCommentCount > 0) + { + QPainter p(&pixmap); + QFontMetricsF fm(option.font); + p.drawPixmap(QPoint(pixmap.width(),0.0)+mZoom*QPoint(-2.9*fm.height(),0.4*fm.height()), + FilesDefs::getPixmapFromQtResourcePath(COMMENT_OVERLAY_IMAGE).scaled(mZoom*3*fm.height(),mZoom*3*fm.height(), + Qt::KeepAspectRatio,Qt::SmoothTransformation)); } painter->drawPixmap(option.rect.topLeft(), - pixmap.scaled(option.rect.width(),option.rect.width()*pixmap.height()/(float)pixmap.width(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation)); + pixmap.scaled(option.rect.width(),option.rect.width()*pixmap.height()/(float)pixmap.width(), + Qt::IgnoreAspectRatio,Qt::SmoothTransformation)); } else { @@ -264,6 +259,9 @@ QSize ChannelPostDelegate::sizeHint(const QStyleOptionViewItem& option, const QM float cell_width = mZoom*COLUMN_SIZE_FONT_FACTOR_W*fm.height(); float cell_height = mZoom*COLUMN_SIZE_FONT_FACTOR_W*fm.height()*aspect_ratio; +#ifdef DEBUG_CHANNEL_POSTS_WIDGET + RsDbg() << "SizeHint: mUseGrid=" << mUseGrid << " cell_width=" << cell_width << " cell_height=" << cell_height << " mZoom=" << mZoom ; +#endif if(mUseGrid || index.column()==0) return QSize(cell_width,cell_height); @@ -282,52 +280,54 @@ void ChannelPostDelegate::setWidgetGrid(bool use_grid) QWidget *ChannelPostFilesDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex& index) const { - ChannelPostFileInfo file = index.data(Qt::UserRole).value() ; + ChannelPostFileInfo file = index.data(Qt::UserRole).value() ; - if(index.column() == RsGxsChannelPostFilesModel::COLUMN_FILES_FILE) - { - GxsChannelFilesStatusWidget* w = new GxsChannelFilesStatusWidget(file,parent); - connect(w,SIGNAL(onButtonClick()),this->parent(),SLOT(updateDAll_PB())); - return w; - } - else - return NULL; + if(index.column() == RsGxsChannelPostFilesModel::COLUMN_FILES_FILE) + { + GxsChannelFilesStatusWidget* w = new GxsChannelFilesStatusWidget(file,parent,true); + w->setFocusPolicy(Qt::StrongFocus); + connect(w,SIGNAL(onButtonClick()),this->parent(),SLOT(updateDAll_PB())); + + return w; + } + else + return NULL; } void ChannelPostFilesDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const { - editor->setGeometry(option.rect); + editor->setGeometry(option.rect); } void ChannelPostFilesDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { - ChannelPostFileInfo file = index.data(Qt::UserRole).value() ; + ChannelPostFileInfo file = index.data(Qt::UserRole).value() ; - // prepare - painter->save(); - painter->setClipRect(option.rect); + // prepare + painter->save(); + painter->setClipRect(option.rect); painter->save(); painter->fillRect( option.rect, option.backgroundBrush); - //optionFocusRect.backgroundColor = option.palette.color(colorgroup, (option.state & QStyle::State_Selected) ? QPalette::Highlight : QPalette::Background); + //optionFocusRect.backgroundColor = option.palette.color(colorgroup, (option.state & QStyle::State_Selected) ? QPalette::Highlight : QPalette::Background); painter->restore(); switch(index.column()) { case RsGxsChannelPostFilesModel::COLUMN_FILES_NAME: painter->drawText(option.rect,Qt::AlignLeft | Qt::AlignVCenter," " + QString::fromUtf8(file.mName.c_str())); - break; + break; case RsGxsChannelPostFilesModel::COLUMN_FILES_SIZE: painter->drawText(option.rect,Qt::AlignRight | Qt::AlignVCenter,misc::friendlyUnit(qulonglong(file.mSize))); - break; + break; case RsGxsChannelPostFilesModel::COLUMN_FILES_DATE: painter->drawText(option.rect,Qt::AlignLeft | Qt::AlignVCenter,QDateTime::fromMSecsSinceEpoch(file.mPublishTime*1000).toString("MM/dd/yyyy, hh:mm")); - break; + break; case RsGxsChannelPostFilesModel::COLUMN_FILES_FILE: { - GxsChannelFilesStatusWidget w(file); + GxsChannelFilesStatusWidget w(file); w.setFixedWidth(option.rect.width()); - w.setFixedHeight(option.rect.height()); + w.setFixedHeight(option.rect.height()); - QPixmap pixmap(w.size()); + QPixmap pixmap(w.size()); // apparently we need to do the alternate colors manually //if(index.row() & 0x01) @@ -343,13 +343,13 @@ void ChannelPostFilesDelegate::paint(QPainter * painter, const QStyleOptionViewI default: painter->drawText(option.rect,Qt::AlignLeft,QString("[No data]")); - break; + break; } } QSize ChannelPostFilesDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { - ChannelPostFileInfo file = index.data(Qt::UserRole).value() ; + ChannelPostFileInfo file = index.data(Qt::UserRole).value() ; QFontMetricsF fm(option.font); @@ -369,18 +369,18 @@ QSize ChannelPostFilesDelegate::sizeHint(const QStyleOptionViewItem& option, con /** Constructor */ GxsChannelPostsWidgetWithModel::GxsChannelPostsWidgetWithModel(const RsGxsGroupId &channelId, QWidget *parent) : - GxsMessageFrameWidget(rsGxsChannels, parent), - ui(new Ui::GxsChannelPostsWidgetWithModel) + GxsMessageFrameWidget(rsGxsChannels, parent), + ui(new Ui::GxsChannelPostsWidgetWithModel) { - /* Invoke the Qt Designer generated object setup routine */ - ui->setupUi(this); + /* Invoke the Qt Designer generated object setup routine */ + ui->setupUi(this); ui->viewType_TB->setIcon(FilesDefs::getIconFromQtResourcePath(":icons/svg/gridlayout.svg")); ui->viewType_TB->setToolTip(tr("Click to switch to list view")); connect(ui->viewType_TB,SIGNAL(clicked()),this,SLOT(switchView())); ui->showUnread_TB->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); - ui->showUnread_TB->setChecked(false); + whileBlocking(ui->showUnread_TB)->setChecked(false); ui->showUnread_TB->setToolTip(tr("Show unread posts only")); connect(ui->showUnread_TB,SIGNAL(toggled(bool)),this,SLOT(switchOnlyUnread(bool))); @@ -393,7 +393,7 @@ GxsChannelPostsWidgetWithModel::GxsChannelPostsWidgetWithModel(const RsGxsGroupI mChannelPostsDelegate->setAspectRatio(ChannelPostThumbnailView::ASPECT_RATIO_16_9); - connect(ui->postsTree,SIGNAL(zoomRequested(bool)),this,SLOT(updateZoomFactor(bool))); + connect(ui->postsTree,SIGNAL(zoomRequested(bool)),this,SLOT(onUpdateZoomFactor(bool))); connect(ui->commentsDialog,SIGNAL(commentsLoaded(int)),this,SLOT(updateCommentsCount(int))); ui->channelPostFiles_TV->setModel(mChannelPostFilesModel = new RsGxsChannelPostFilesModel(this)); @@ -412,12 +412,14 @@ GxsChannelPostsWidgetWithModel::GxsChannelPostsWidgetWithModel(const RsGxsGroupI connect(ui->channelPostFiles_TV->header(),SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(sortColumnPostFiles(int,Qt::SortOrder))); connect(ui->channelFiles_TV->header(),SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(sortColumnFiles(int,Qt::SortOrder))); - connect(ui->channelPostFiles_TV,SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showChannelFilesContextMenu(QPoint))); + connect(ui->channelPostFiles_TV,SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showChannelPostFilesContextMenu(QPoint))); connect(ui->channelFiles_TV,SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showChannelFilesContextMenu(QPoint))); connect(ui->postsTree->selectionModel(),SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),this,SLOT(showPostDetails())); connect(ui->postsTree,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(postContextMenu(const QPoint&))); + connect(ui->channel_TW,SIGNAL(currentChanged(int)),this,SLOT(currentTabChanged(int))); + connect(mChannelPostsModel,SIGNAL(channelPostsLoaded()),this,SLOT(postChannelPostLoad())); ui->postName_LB->hide(); @@ -429,94 +431,149 @@ GxsChannelPostsWidgetWithModel::GxsChannelPostsWidgetWithModel(const RsGxsGroupI ui->postDetails_TE->setPlaceholderText(tr("No text to display")); - // Set initial size of the splitter - ui->splitter->setStretchFactor(0, 1); - ui->splitter->setStretchFactor(1, 0); + // Set initial size of the splitter + ui->splitter->setStretchFactor(0, 1); + ui->splitter->setStretchFactor(1, 0); - QFontMetricsF fm(font()); + QFontMetricsF fm(font()); - if(mChannelPostsModel->getMode() == RsGxsChannelPostsModel::TREE_MODE_GRID) - for(int i=0;icolumnCount();++i) - ui->postsTree->setColumnWidth(i,mChannelPostsDelegate->cellSize(i,font(),ui->postsTree->width())); + if(mChannelPostsModel->getMode() == RsGxsChannelPostsModel::TREE_MODE_GRID) + for(int i=0;icolumnCount();++i) + ui->postsTree->setColumnWidth(i,mChannelPostsDelegate->cellSize(i,font(),ui->postsTree->width())); - /* Setup UI helper */ + /* Setup UI helper */ - /* Connect signals */ - connect(ui->postButton, SIGNAL(clicked()), this, SLOT(createMsg())); - connect(ui->subscribeToolButton, SIGNAL(subscribe(bool)), this, SLOT(subscribeGroup(bool))); - connect(NotifyQt::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); + /* Connect signals */ + connect(ui->postButton, SIGNAL(clicked()), this, SLOT(createMsg())); + connect(ui->subscribeToolButton, SIGNAL(subscribe(bool)), this, SLOT(subscribeGroup(bool))); + connect(NotifyQt::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); - ui->postButton->setText(tr("Add new post")); - - /* add filter actions */ + ui->postButton->setText(tr("Add new post")); + + /* add filter actions */ ui->filterLineEdit->setPlaceholderText(tr("Search...")); - connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); + connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); ui->postsTree->setPlaceholderText(tr("No posts available in this channel")); ui->postsTree->setMinimumWidth(COLUMN_SIZE_FONT_FACTOR_W*QFontMetricsF(font()).height()+1); connect(ui->postsTree,SIGNAL(sizeChanged(QSize)),this,SLOT(handlePostsTreeSizeChange(QSize))); - /* Set initial section sizes */ - QHeaderView * channelpostfilesheader = ui->channelPostFiles_TV->header () ; - QHeaderView * channelfilesheader = ui->channelFiles_TV->header () ; + /* Set initial section sizes */ + QHeaderView * channelpostfilesheader = ui->channelPostFiles_TV->header () ; + QHeaderView * channelfilesheader = ui->channelFiles_TV->header () ; - channelpostfilesheader->resizeSection (RsGxsChannelPostFilesModel::COLUMN_FILES_NAME, fm.width("RetroShare-v0.6.5-1487-g6714648e5-Windows-x64-portable-20200518-Qt-5.14.2.7z")); - channelfilesheader->resizeSection (RsGxsChannelPostFilesModel::COLUMN_FILES_NAME, fm.width("RetroShare-v0.6.5-1487-g6714648e5-Windows-x64-portable-20200518-Qt-5.14.2.7z")); + channelpostfilesheader->resizeSection (RsGxsChannelPostFilesModel::COLUMN_FILES_NAME, fm.width("RetroShare-v0.6.5-1487-g6714648e5-Windows-x64-portable-20200518-Qt-5.14.2.7z")); + channelfilesheader->resizeSection (RsGxsChannelPostFilesModel::COLUMN_FILES_NAME, fm.width("RetroShare-v0.6.5-1487-g6714648e5-Windows-x64-portable-20200518-Qt-5.14.2.7z")); - /* Initialize feed widget */ - //ui->feedWidget->setSortRole(ROLE_PUBLISH, Qt::DescendingOrder); - //ui->feedWidget->setFilterCallback(filterItem); + /* Initialize feed widget */ + //ui->feedWidget->setSortRole(ROLE_PUBLISH, Qt::DescendingOrder); + //ui->feedWidget->setFilterCallback(filterItem); - /* load settings */ - processSettings(true); + /* load settings */ + processSettings(true); ui->channelPostFiles_TV->setColumnHidden(RsGxsChannelPostFilesModel::COLUMN_FILES_DATE, true); // no need to show this here. - /* Initialize subscribe button */ - QIcon icon; + /* Initialize subscribe button */ + QIcon icon; icon.addPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/redled.png"), QIcon::Normal, QIcon::On); icon.addPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/start.png"), QIcon::Normal, QIcon::Off); #ifdef TO_REMOVE - mAutoDownloadAction = new QAction(icon, "", this); - mAutoDownloadAction->setCheckable(true); - connect(mAutoDownloadAction, SIGNAL(triggered()), this, SLOT(toggleAutoDownload())); + mAutoDownloadAction = new QAction(icon, "", this); + mAutoDownloadAction->setCheckable(true); + connect(mAutoDownloadAction, SIGNAL(triggered()), this, SLOT(toggleAutoDownload())); - ui->subscribeToolButton->addSubscribedAction(mAutoDownloadAction); + ui->subscribeToolButton->addSubscribedAction(mAutoDownloadAction); setAutoDownload(false); #endif - ui->commentsDialog->setTokenService(rsGxsChannels->getTokenService(),rsGxsChannels); + ui->commentsDialog->setGxsService(rsGxsChannels); - /* Initialize GUI */ - settingsChanged(); + /* Initialize GUI */ + settingsChanged(); setGroupId(channelId); - mChannelPostsModel->updateChannel(channelId); + mChannelPostsModel->updateChannel(channelId); - mEventHandlerId = 0; - // Needs to be asynced because this function is called by another thread! - rsEvents->registerEventsHandler( [this](std::shared_ptr event) + mEventHandlerId = 0; + // Needs to be asynced because this function is called by another thread! + rsEvents->registerEventsHandler( [this](std::shared_ptr event) { RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); }, mEventHandlerId, RsEventType::GXS_CHANNELS ); } -void GxsChannelPostsWidgetWithModel::updateZoomFactor(bool zoom_or_unzoom) +void GxsChannelPostsWidgetWithModel::keyPressEvent(QKeyEvent *e) { - mChannelPostsDelegate->zoom(zoom_or_unzoom); + QModelIndex index = ui->postsTree->selectionModel()->currentIndex(); + + if(index.isValid() && mChannelPostsModel->getMode() == RsGxsChannelPostsModel::TREE_MODE_GRID) + { + int n = mChannelPostsModel->columnCount(index.row())-1; + + if(e->key() == Qt::Key_Left && index.column()==0) + { + ui->postsTree->setCurrentIndex(index.sibling(index.row(),n)); + e->accept(); + return; + } + if(e->key() == Qt::Key_Right && index.column()==n) + { + ui->postsTree->setCurrentIndex(index.sibling(index.row(),0)); + e->accept(); + return; + } + } + + GxsMessageFrameWidget::keyPressEvent(e); +} +void GxsChannelPostsWidgetWithModel::resizeEvent(QResizeEvent *e) +{ + GxsMessageFrameWidget::resizeEvent(e); + updateZoomFactor(0); +} +void GxsChannelPostsWidgetWithModel::currentTabChanged(int t) +{ + switch(t) + { + case CHANNEL_TABS_DETAILS: + case CHANNEL_TABS_FILES: + ui->showUnread_TB->setHidden(true); + ui->viewType_TB->setHidden(true); + break; + + case CHANNEL_TABS_POSTS: + ui->showUnread_TB->setHidden(false); + ui->viewType_TB->setHidden(false); + updateZoomFactor(0); // fixes a bug due to the widget now knowing its size when not displayed. + break; + } +} +void GxsChannelPostsWidgetWithModel::onUpdateZoomFactor(bool zoom_or_unzoom) +{ + if(zoom_or_unzoom) + updateZoomFactor(1); + else + updateZoomFactor(-1); +} +void GxsChannelPostsWidgetWithModel::updateZoomFactor(int what_to_do) +{ + if(what_to_do != 0) + mChannelPostsDelegate->zoom(what_to_do > 0); + + QSize s = ui->postsTree->size(); + int n_columns = std::max(1,(int)floor(s.width() / (float)(mChannelPostsDelegate->cellSize(0,font(),s.width())))); + mChannelPostsModel->setNumColumns(n_columns); // forces the update for(int i=0;icolumnCount();++i) ui->postsTree->setColumnWidth(i,mChannelPostsDelegate->cellSize(i,font(),ui->postsTree->width())); - QSize s = ui->postsTree->size(); - - int n_columns = std::max(1,(int)floor(s.width() / (mChannelPostsDelegate->cellSize(0,font(),s.width())))); - - mChannelPostsModel->setNumColumns(n_columns); // forces the update - - ui->postsTree->dataChanged(QModelIndex(),QModelIndex()); + if(what_to_do) + mChannelPostsModel->triggerViewUpdate(true,false); + else + mChannelPostsModel->triggerViewUpdate(false,true); } void GxsChannelPostsWidgetWithModel::sortColumnPostFiles(int col,Qt::SortOrder so) @@ -557,10 +614,10 @@ void GxsChannelPostsWidgetWithModel::postContextMenu(const QPoint&) } menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyMessageLink())); - if(IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) - menu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/pencil-edit-button.png"), tr("Edit"), this, SLOT(editPost())); + if(IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) + menu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/pencil-edit-button.png"), tr("Edit"), this, SLOT(editPost())); - menu.exec(QCursor::pos()); + menu.exec(QCursor::pos()); } void GxsChannelPostsWidgetWithModel::markMessageUnread() @@ -622,7 +679,7 @@ void GxsChannelPostsWidgetWithModel::switchView() selectItem(msg_id); ui->postsTree->setFocus(); - mChannelPostsModel->triggerViewUpdate(); // This is already called by setMode(), but the model cannot know how many + mChannelPostsModel->triggerViewUpdate(false,true); // This is already called by setMode(), but the model cannot know how many // columns is actually has until we call handlePostsTreeSizeChange(), so // we have to call it again here. } @@ -630,29 +687,29 @@ void GxsChannelPostsWidgetWithModel::switchView() void GxsChannelPostsWidgetWithModel::copyMessageLink() { try - { - if (groupId().isNull()) - throw std::runtime_error("No channel currently selected!"); + { + if (groupId().isNull()) + throw std::runtime_error("No channel currently selected!"); - QModelIndex index = ui->postsTree->selectionModel()->currentIndex(); + QModelIndex index = ui->postsTree->selectionModel()->currentIndex(); - if(!index.isValid()) - throw std::runtime_error("No post under mouse!"); + if(!index.isValid()) + throw std::runtime_error("No post under mouse!"); - RsGxsChannelPost post = index.data(Qt::UserRole).value() ; + RsGxsChannelPost post = index.data(Qt::UserRole).value() ; - if(post.mMeta.mMsgId.isNull()) - throw std::runtime_error("Post has empty MsgId!"); + if(post.mMeta.mMsgId.isNull()) + throw std::runtime_error("Post has empty MsgId!"); - RetroShareLink link = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_CHANNEL, groupId(), post.mMeta.mMsgId, QString::fromUtf8(post.mMeta.mMsgName.c_str())); + RetroShareLink link = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_CHANNEL, groupId(), post.mMeta.mMsgId, QString::fromUtf8(post.mMeta.mMsgName.c_str())); - if (!link.valid()) - throw std::runtime_error("Link is not valid"); + if (!link.valid()) + throw std::runtime_error("Link is not valid"); - QList urls; - urls.push_back(link); - RSLinkClipboard::copyLinks(urls); - } + QList urls; + urls.push_back(link); + RSLinkClipboard::copyLinks(urls); + } catch(std::exception& e) { QMessageBox::critical(NULL,tr("Link creation error"),tr("Link could not be created: ")+e.what()); @@ -681,41 +738,41 @@ void GxsChannelPostsWidgetWithModel::download() rsFiles->FileRequest(file.mName, file.mHash, file.mSize, destination, RS_FILE_REQ_ANONYMOUS_ROUTING, sources); } - ui->postDAll_PB->hide(); + ui->postDAll_PB->hide(); } void GxsChannelPostsWidgetWithModel::updateDAll_PB() { - QModelIndex index = ui->postsTree->selectionModel()->currentIndex(); - RsGxsChannelPost post = index.data(Qt::UserRole).value() ; + QModelIndex index = ui->postsTree->selectionModel()->currentIndex(); + RsGxsChannelPost post = index.data(Qt::UserRole).value() ; - size_t newFileToDl = 0; - uint64_t newFileTotalSize = 0; - QString newFilesDetails; + size_t newFileToDl = 0; + uint64_t newFileTotalSize = 0; + QString newFilesDetails; - for(auto& file:post.mFiles) - { - FileInfo fileInfo; - if (!rsFiles->FileDetails(file.mHash, RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_SPEC_ONLY, fileInfo)) { - ++newFileToDl; - newFileTotalSize += file.mSize; - newFilesDetails += QString::fromUtf8(file.mName.c_str()) + " " + misc::friendlyUnit(file.mSize) + "\n"; - } - } + for(auto& file:post.mFiles) + { + FileInfo fileInfo; + if (!rsFiles->FileDetails(file.mHash, RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_SPEC_ONLY, fileInfo)) { + ++newFileToDl; + newFileTotalSize += file.mSize; + newFilesDetails += QString::fromUtf8(file.mName.c_str()) + " " + misc::friendlyUnit(file.mSize) + "\n"; + } + } - ui->postDAll_PB->setHidden(newFileToDl == 0); - ui->postDAll_PB->setToolTip((newFileToDl == 1 ? tr("Download this file:") : tr("Download All these %1 files:").arg(newFileToDl) ) + "\n" - + newFilesDetails - + tr("Totaling: %1").arg(misc::friendlyUnit(newFileTotalSize))); + ui->postDAll_PB->setHidden(newFileToDl == 0); + ui->postDAll_PB->setToolTip((newFileToDl == 1 ? tr("Download this file:") : tr("Download All these %1 files:").arg(newFileToDl) ) + "\n" + + newFilesDetails + + tr("Totaling: %1").arg(misc::friendlyUnit(newFileTotalSize))); } void GxsChannelPostsWidgetWithModel::editPost() { QModelIndex index = ui->postsTree->selectionModel()->currentIndex(); - RsGxsChannelPost post = index.data(Qt::UserRole).value() ; + RsGxsChannelPost post = index.data(Qt::UserRole).value() ; - CreateGxsChannelMsg *msgDialog = new CreateGxsChannelMsg(post.mMeta.mGroupId,post.mMeta.mMsgId); + CreateGxsChannelMsg *msgDialog = new CreateGxsChannelMsg(post.mMeta.mGroupId,post.mMeta.mMsgId); msgDialog->show(); } @@ -725,7 +782,9 @@ void GxsChannelPostsWidgetWithModel::handlePostsTreeSizeChange(QSize s,bool forc return; int n_columns = std::max(1,(int)floor(s.width() / (mChannelPostsDelegate->cellSize(0,font(),ui->postsTree->width())))); - std::cerr << "nb columns: " << n_columns << " current count=" << mChannelPostsModel->columnCount() << std::endl; +#ifdef DEBUG_CHANNEL_POSTS_WIDGET + RsDbg() << "nb columns: " << n_columns << " current count=" << mChannelPostsModel->columnCount() ; +#endif // save current post. The setNumColumns() indeed loses selection @@ -744,69 +803,128 @@ void GxsChannelPostsWidgetWithModel::handlePostsTreeSizeChange(QSize s,bool forc void GxsChannelPostsWidgetWithModel::handleEvent_main_thread(std::shared_ptr event) { - const RsGxsChannelEvent *e = dynamic_cast(event.get()); + const RsGxsChannelEvent *e = dynamic_cast(event.get()); - if(!e) - return; + if(!e) + return; - switch(e->mChannelEventCode) - { - case RsChannelEventCode::NEW_CHANNEL: // [[fallthrough]]; + switch(e->mChannelEventCode) + { + case RsChannelEventCode::NEW_CHANNEL: // [[fallthrough]]; case RsChannelEventCode::DELETED_CHANNEL: // [[fallthrough]]; - case RsChannelEventCode::NEW_COMMENT: // [[fallthrough]]; - case RsChannelEventCode::NEW_VOTE: // [[fallthrough]]; case RsChannelEventCode::UPDATED_CHANNEL: // [[fallthrough]]; - case RsChannelEventCode::NEW_MESSAGE: // [[fallthrough]]; - case RsChannelEventCode::UPDATED_MESSAGE: case RsChannelEventCode::RECEIVED_PUBLISH_KEY: case RsChannelEventCode::SYNC_PARAMETERS_UPDATED: { - if(e->mChannelGroupId == groupId()) - updateDisplay(true); - } + if(e->mChannelGroupId == groupId()) + updateDisplay(true,false); + } + break; - default: - break; - } + case RsChannelEventCode::READ_STATUS_CHANGED: // This is already handled by setMsgReadStatus() that has been called and issued this event. + break; + + case RsChannelEventCode::NEW_MESSAGE: + { + if(e->mChannelGroupId == groupId()) + { +#ifdef DEBUG_CHANNEL_POSTS_WIDGET + RsDbg() << "Received new message in current channel, msgId=" << e->mChannelMsgId ; +#endif + + RsThread::async([this,E=*e]() // dereferencing to make a copy that will survive while e is deleted by the parent thread. + { + // 1 - get message data from p3GxsChannels. No need for pointers here, because we send only a single post to postToObject() + // At this point we dont know what kind of msg id we have. It can be a vote, a comment or an actual message. + + std::vector posts; + std::vector comments; + std::vector votes; + + const auto& msg_id(E.mChannelMsgId); + const auto& grp_id(E.mChannelGroupId); + + if(!rsGxsChannels->getChannelContent(grp_id, { msg_id }, posts,comments,votes) || posts.size() != 1) + { + RsErr() << " failed to retrieve channel message data for channel/msg " << grp_id << "/" << msg_id; + return; + } + + // 2 - update the model in the UI thread. + + RsQThreadUtils::postToObject( [post=posts[0],this]() + { + std::set added_files,removed_files; + + mChannelPostsModel->updateSinglePost(post,added_files,removed_files); + + std::set added_filesi,removed_filesi; + + for(auto f:added_files) added_filesi.insert(ChannelPostFileInfo(f,post.mMeta.mPublishTs)); + for(auto f:removed_files) removed_filesi.insert(ChannelPostFileInfo(f,post.mMeta.mPublishTs)); + + mChannelFilesModel->update_files(added_filesi,removed_filesi); + + },this); + }); + } + } + break; + + case RsChannelEventCode::NEW_COMMENT: + + if(e->mChannelGroupId == groupId() && e->mChannelThreadId != ui->commentsDialog->messageId()) + mChannelPostsModel->updatePostWithNewComment(e->mChannelThreadId); [[fallthrough]]; + + case RsChannelEventCode::NEW_VOTE: + + if(e->mChannelGroupId == groupId() && e->mChannelThreadId == ui->commentsDialog->messageId()) + ui->commentsDialog->refresh(); + break; + + default: + break; + + } } void GxsChannelPostsWidgetWithModel::showPostDetails() { QModelIndex index = ui->postsTree->selectionModel()->currentIndex(); - RsGxsChannelPost post = index.data(Qt::UserRole).value() ; + RsGxsChannelPost post = index.data(Qt::UserRole).value() ; #ifdef DEBUG_CHANNEL_POSTS_WIDGET - std::cerr << "showPostDetails: current index is " << index.row() << "," << index.column() << std::endl; + RsDbg() << "showPostDetails: current index is " << index.row() << "," << index.column() ; #endif - //QTextDocument doc; - //doc.setHtml(post.mMsg.c_str()); + //QTextDocument doc; + //doc.setHtml(post.mMsg.c_str()); - if(post.mMeta.mPublishTs == 0) - { - ui->postDetails_TE->clear(); - ui->postLogo_LB->hide(); - ui->postName_LB->hide(); - ui->postTime_LB->hide(); - mChannelPostFilesModel->clear(); - ui->details_TW->setEnabled(false); - //mLastSelectedPosts[groupId()].clear(); + if(post.mMeta.mPublishTs == 0) + { + ui->postDetails_TE->clear(); + ui->postLogo_LB->hide(); + ui->postName_LB->hide(); + ui->postTime_LB->hide(); + mChannelPostFilesModel->clear(); + ui->details_TW->setEnabled(false); + //mLastSelectedPosts[groupId()].clear(); - return; - } - ui->details_TW->setEnabled(true); + return; + } + ui->details_TW->setEnabled(true); - ui->postLogo_LB->show(); - ui->postName_LB->show(); - ui->postTime_LB->show(); + ui->postLogo_LB->show(); + ui->postName_LB->show(); + ui->postTime_LB->show(); #ifdef DEBUG_CHANNEL_POSTS_WIDGET - std::cerr << "showPostDetails: setting mLastSelectedPosts[groupId()] to current post Id " << post.mMeta.mMsgId << ". Previous value: " << mLastSelectedPosts[groupId()] << std::endl; + RsDbg() << "showPostDetails: setting mLastSelectedPosts[groupId()] to current post Id " << post.mMeta.mMsgId << ". Previous value: " << mLastSelectedPosts[groupId()] ; #endif - mLastSelectedPosts[groupId()] = post.mMeta.mMsgId; + mLastSelectedPosts[groupId()] = post.mMeta.mMsgId; - std::list files; - for(auto& file:post.mFiles) - files.push_back(ChannelPostFileInfo(file,post.mMeta.mPublishTs)); + std::list files; + for(auto& file:post.mFiles) + files.push_back(ChannelPostFileInfo(file,post.mMeta.mPublishTs)); mChannelPostFilesModel->setFiles(files); @@ -816,46 +934,51 @@ void GxsChannelPostsWidgetWithModel::showPostDetails() ui->commentsDialog->commentLoad(post.mMeta.mGroupId, all_msgs_versions, post.mMeta.mMsgId,true); #ifdef DEBUG_CHANNEL_POSTS_WIDGET - std::cerr << "Showing details about selected index : "<< index.row() << "," << index.column() << std::endl; + RsDbg() << "Showing details about selected index : "<< index.row() << "," << index.column() ; #endif ui->postDetails_TE->setText(RsHtml().formatText(NULL, QString::fromUtf8(post.mMsg.c_str()), /* RSHTML_FORMATTEXT_EMBED_SMILEYS |*/ RSHTML_FORMATTEXT_EMBED_LINKS)); - QPixmap postImage; + QPixmap postImage; - if (post.mThumbnail.mData != NULL) - GxsIdDetails::loadPixmapFromData(post.mThumbnail.mData, post.mThumbnail.mSize, postImage,GxsIdDetails::ORIGINAL); - else - postImage = FilesDefs::getPixmapFromQtResourcePath(ChannelPostThumbnailView::CHAN_DEFAULT_IMAGE); + if (post.mThumbnail.mData != NULL) + GxsIdDetails::loadPixmapFromData(post.mThumbnail.mData, post.mThumbnail.mSize, postImage,GxsIdDetails::ORIGINAL); + else + postImage = FilesDefs::getPixmapFromQtResourcePath(ChannelPostThumbnailView::CHAN_DEFAULT_IMAGE); int W = QFontMetricsF(font()).height() * 8; // Using fixed width so that the post will not displace the text when we browse. - ui->postLogo_LB->setPixmap(postImage); - ui->postLogo_LB->setFixedSize(W,postImage.height()/(float)postImage.width()*W); + ui->postLogo_LB->setPixmap(postImage); + ui->postLogo_LB->setFixedSize(W,postImage.height()/(float)postImage.width()*W); - ui->postName_LB->setText(QString::fromUtf8(post.mMeta.mMsgName.c_str())); + ui->postName_LB->setText(QString::fromUtf8(post.mMeta.mMsgName.c_str())); - ui->postTime_LB->setText(QDateTime::fromMSecsSinceEpoch(post.mMeta.mPublishTs*1000).toString("MM/dd/yyyy, hh:mm")); - ui->postTime_LB->setFixedWidth(W); + ui->postTime_LB->setText(QDateTime::fromMSecsSinceEpoch(post.mMeta.mPublishTs*1000).toString("MM/dd/yyyy, hh:mm")); + ui->postTime_LB->setFixedWidth(W); //ui->channelPostFiles_TV->resizeColumnToContents(RsGxsChannelPostFilesModel::COLUMN_FILES_FILE); //ui->channelPostFiles_TV->resizeColumnToContents(RsGxsChannelPostFilesModel::COLUMN_FILES_SIZE); ui->channelPostFiles_TV->setAutoSelect(true); - // Now also set the post as read + // Now also set the post as read - if(IS_MSG_UNREAD(post.mMeta.mMsgStatus) || IS_MSG_NEW(post.mMeta.mMsgStatus)) - { - RsGxsGrpMsgIdPair postId; - postId.second = post.mMeta.mMsgId; - postId.first = post.mMeta.mGroupId; + if(IS_MSG_UNREAD(post.mMeta.mMsgStatus) || IS_MSG_NEW(post.mMeta.mMsgStatus) || post.mUnreadCommentCount > 0) + { + mChannelPostsModel->setMsgReadStatus(index,true); - RsThread::async([postId]() { rsGxsChannels->markRead(postId, true) ; } ); - } + //RsGxsGrpMsgIdPair postId; + //postId.second = post.mMeta.mMsgId; + //postId.first = post.mMeta.mGroupId; - updateDAll_PB(); + //RsThread::async([postId]() + //{ + //rsGxsChannels->setMessageReadStatus(postId, true) ; + //} ); + } + + updateDAll_PB(); } void GxsChannelPostsWidgetWithModel::updateCommentsCount(int n) @@ -865,30 +988,30 @@ void GxsChannelPostsWidgetWithModel::updateCommentsCount(int n) else ui->details_TW->setTabText(2,tr("Comments")); } -void GxsChannelPostsWidgetWithModel::updateGroupData() +void GxsChannelPostsWidgetWithModel::updateData(bool update_group_data, bool update_posts) { - if(groupId().isNull()) + if(groupId().isNull()) { // clear post, files and comment widgets showPostDetails(); - return; + return; } - RsThread::async([this]() - { - RsGxsChannelGroup group; - std::vector groups; + RsThread::async([this,update_group_data,update_posts]() + { + std::vector groups; + RsGxsChannelGroup group; - if(rsGxsChannels->getChannelsInfo(std::list{ groupId() }, groups) && groups.size()==1) + if(rsGxsChannels->getChannelsInfo(std::list{ groupId() }, groups) && groups.size()==1) group = groups[0]; else if(!rsGxsChannels->getDistantSearchResultGroupData(groupId(),group)) - { - std::cerr << __PRETTY_FUNCTION__ << " failed to get group data for channel: " << groupId() << std::endl; - return; - } + { + std::cerr << __PRETTY_FUNCTION__ << " failed to get group data for channel: " << groupId() << std::endl; + return; + } - RsQThreadUtils::postToObject( [this,group]() + RsQThreadUtils::postToObject( [this,update_group_data,update_posts,group]() { if(mGroup.mMeta.mGroupId != group.mMeta.mGroupId) // this prevents any attempt to display the wrong index. Navigate() if needed will use mNavigatePendingMsgId { @@ -900,49 +1023,63 @@ void GxsChannelPostsWidgetWithModel::updateGroupData() updateCommentsCount(0); } - mGroup = group; - mChannelPostsModel->updateChannel(groupId()); - whileBlocking(ui->filterLineEdit)->clear(); - whileBlocking(ui->showUnread_TB)->setChecked(false); + if(update_group_data) + { + mGroup = group; + insertChannelDetails(mGroup); + } - insertChannelDetails(mGroup); + if(update_posts) + { + ui->postsTree->setPlaceholderText(tr("Loading...")); + + mChannelPostsModel->updateChannel(groupId()); + + whileBlocking(ui->filterLineEdit)->clear(); + whileBlocking(ui->showUnread_TB)->setChecked(false); + } emit groupDataLoaded(); emit groupChanged(this); // signals the parent widget to e.g. update the group tab name } ); - }); + }); } void GxsChannelPostsWidgetWithModel::postChannelPostLoad() { - std::cerr << "Post channel load..." << std::endl; +#ifdef DEBUG_CHANNEL_POSTS_WIDGET + std::cerr << "Post channel load..." << std::endl; +#endif - if (!mNavigatePendingMsgId.isNull()) - navigate(mNavigatePendingMsgId); + if (!mNavigatePendingMsgId.isNull()) + navigate(mNavigatePendingMsgId); - else if( (mLastSelectedPosts.count(groupId()) > 0) + else if( (mLastSelectedPosts.count(groupId()) > 0) && !mLastSelectedPosts[groupId()].isNull()) - { - QModelIndex index = mChannelPostsModel->getIndexOfMessage(mLastSelectedPosts[groupId()]); + { + QModelIndex index = mChannelPostsModel->getIndexOfMessage(mLastSelectedPosts[groupId()]); - std::cerr << "Setting current index to " << index.row() << ","<< index.column() << " for current post " - << mLastSelectedPosts[groupId()].toStdString() << std::endl; + std::cerr << "Setting current index to " << index.row() << ","<< index.column() << " for current post " + << mLastSelectedPosts[groupId()].toStdString() << std::endl; - ui->postsTree->selectionModel()->setCurrentIndex(index,QItemSelectionModel::ClearAndSelect); - ui->postsTree->scrollTo(index);//May change if model reloaded - ui->postsTree->setFocus(); - } - else - std::cerr << "No pre-selected channel post." << std::endl; + ui->postsTree->selectionModel()->setCurrentIndex(index,QItemSelectionModel::ClearAndSelect); + ui->postsTree->scrollTo(index);//May change if model reloaded + ui->postsTree->setFocus(); + } + else + std::cerr << "No pre-selected channel post." << std::endl; - std::list files; + std::list files; mChannelPostsModel->getFilesList(files); mChannelFilesModel->setFiles(files); - ui->channelFiles_TV->setAutoSelect(true); - ui->channelFiles_TV->sortByColumn(ui->channelFiles_TV->header()->sortIndicatorSection() - ,ui->channelFiles_TV->header()->sortIndicatorOrder()); + ui->channelFiles_TV->setAutoSelect(true); + ui->channelFiles_TV->sortByColumn(ui->channelFiles_TV->header()->sortIndicatorSection() + ,ui->channelFiles_TV->header()->sortIndicatorOrder()); + + // if there's no posts, this is what's going to be displayed. + ui->postsTree->setPlaceholderText(tr("No posts available in this channel.")); ui->infoPosts->setText(QString::number(mChannelPostsModel->getNumberOfPosts()) + " / " + QString::number(mGroup.mMeta.mVisibleMsgCount)); @@ -963,88 +1100,80 @@ void GxsChannelPostsWidgetWithModel::postChannelPostLoad() best = i; mChannelPostsDelegate->setAspectRatio(static_cast(best)); - mChannelPostsModel->triggerViewUpdate(); handlePostsTreeSizeChange(ui->postsTree->size(),true); // force the update + + updateZoomFactor(0); } -void GxsChannelPostsWidgetWithModel::updateDisplay(bool complete) +void GxsChannelPostsWidgetWithModel::updateDisplay(bool update_group_data,bool update_posts) { - // First, clear all widget - blank(); + // First, clear all widget + #ifdef DEBUG_CHANNEL std::cerr << "udateDisplay: groupId()=" << groupId()<< std::endl; #endif - if(groupId().isNull()) + if(groupId().isNull()) { #ifdef DEBUG_CHANNEL std::cerr << " group_id=0. Return!"<< std::endl; #endif - return; + return; } - if(mGroup.mMeta.mGroupId.isNull() && !groupId().isNull()) + if(mGroup.mMeta.mGroupId != groupId()) { #ifdef DEBUG_FORUMS std::cerr << " inconsistent group data. Reloading!"<< std::endl; #endif - complete = true; + update_group_data = true; + update_posts = true; } - if(complete) // need to update the group data, reload the messages etc. - { -#warning csoler 2020-06-02 : todo - //saveExpandedItems(mSavedExpandedMessages); - //if(mGroupId != mChannelPostsModel->currentGroupId()) - // mThreadId.clear(); - - updateGroupData(); - - return; - } + updateData(update_group_data,update_posts); } GxsChannelPostsWidgetWithModel::~GxsChannelPostsWidgetWithModel() { - rsEvents->unregisterEventsHandler(mEventHandlerId); - // save settings - processSettings(false); + rsEvents->unregisterEventsHandler(mEventHandlerId); + // save settings + processSettings(false); //delete(mAutoDownloadAction); delete mFilesDelegate; - delete ui; + delete ui; } void GxsChannelPostsWidgetWithModel::processSettings(bool load) { - QHeaderView *channelpostfilesheader = ui->channelPostFiles_TV->header () ; - QHeaderView *channelfilesheader = ui->channelFiles_TV->header () ; - - Settings->beginGroup(QString("ChannelPostsWidget")); + QHeaderView *channelpostfilesheader = ui->channelPostFiles_TV->header () ; + QHeaderView *channelfilesheader = ui->channelFiles_TV->header () ; - if (load) { + Settings->beginGroup(QString("ChannelPostsWidget")); - // state of files tree - channelpostfilesheader->restoreState(Settings->value("PostFilesTree").toByteArray()); - channelfilesheader->restoreState(Settings->value("FilesTree").toByteArray()); + if (load) { - // state of splitter - ui->splitter->restoreState(Settings->value("SplitterChannelPosts").toByteArray()); - } else { - // state of files tree - Settings->setValue("PostFilesTree", channelpostfilesheader->saveState()); - Settings->setValue("FilesTree", channelfilesheader->saveState()); + // state of files tree + channelpostfilesheader->restoreState(Settings->value("PostFilesTree").toByteArray()); + channelfilesheader->restoreState(Settings->value("FilesTree").toByteArray()); - // state of splitter - Settings->setValue("SplitterChannelPosts", ui->splitter->saveState()); - } + // state of splitter + ui->splitter->restoreState(Settings->value("SplitterChannelPosts").toByteArray()); + } else { + // state of files tree + Settings->setValue("PostFilesTree", channelpostfilesheader->saveState()); + Settings->setValue("FilesTree", channelfilesheader->saveState()); - Settings->endGroup(); + // state of splitter + Settings->setValue("SplitterChannelPosts", ui->splitter->saveState()); + } + + Settings->endGroup(); } void GxsChannelPostsWidgetWithModel::settingsChanged() { - mUseThread = Settings->getChannelLoadThread(); + mUseThread = Settings->getChannelLoadThread(); - //mStateHelper->setWidgetVisible(ui->progressBar, mUseThread); + //mStateHelper->setWidgetVisible(ui->progressBar, mUseThread); } QString GxsChannelPostsWidgetWithModel::groupName(bool) @@ -1064,15 +1193,15 @@ void GxsChannelPostsWidgetWithModel::groupNameChanged(const QString &/*name*/) QIcon GxsChannelPostsWidgetWithModel::groupIcon() { - /* CHANNEL IMAGE */ - QPixmap chanImage; - if (mGroup.mImage.mData != NULL) { - GxsIdDetails::loadPixmapFromData(mGroup.mImage.mData, mGroup.mImage.mSize, chanImage,GxsIdDetails::ORIGINAL); - } else { - chanImage = FilesDefs::getPixmapFromQtResourcePath(ChannelPostThumbnailView::CHAN_DEFAULT_IMAGE); - } + /* CHANNEL IMAGE */ + QPixmap chanImage; + if (mGroup.mImage.mData != NULL) { + GxsIdDetails::loadPixmapFromData(mGroup.mImage.mData, mGroup.mImage.mSize, chanImage,GxsIdDetails::ORIGINAL); + } else { + chanImage = FilesDefs::getPixmapFromQtResourcePath(ChannelPostThumbnailView::CHAN_DEFAULT_IMAGE); + } - return QIcon(chanImage); + return QIcon(chanImage); } /*************************************************************************************/ @@ -1082,50 +1211,50 @@ QIcon GxsChannelPostsWidgetWithModel::groupIcon() // Callback from Widget->FeedHolder->ServiceDialog->CommentContainer->CommentDialog, void GxsChannelPostsWidgetWithModel::openComments(uint32_t /*type*/, const RsGxsGroupId &groupId, const QVector& msg_versions,const RsGxsMessageId &msgId, const QString &title) { - emit loadComment(groupId, msg_versions,msgId, title); + emit loadComment(groupId, msg_versions,msgId, title); } void GxsChannelPostsWidgetWithModel::createMsg() { - if (groupId().isNull()) { - return; - } + if (groupId().isNull()) { + return; + } - if (!IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags)) { - return; - } + if (!IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags)) { + return; + } - CreateGxsChannelMsg *msgDialog = new CreateGxsChannelMsg(groupId()); - msgDialog->show(); + CreateGxsChannelMsg *msgDialog = new CreateGxsChannelMsg(groupId()); + msgDialog->show(); - /* window will destroy itself! */ + /* window will destroy itself! */ } void GxsChannelPostsWidgetWithModel::insertChannelDetails(const RsGxsChannelGroup &group) { // save selection if needed - /* IMAGE */ - QPixmap chanImage; - if (group.mImage.mData != NULL) { - GxsIdDetails::loadPixmapFromData(group.mImage.mData, group.mImage.mSize, chanImage,GxsIdDetails::ORIGINAL); - } else { + /* IMAGE */ + QPixmap chanImage; + if (group.mImage.mData != NULL) { + GxsIdDetails::loadPixmapFromData(group.mImage.mData, group.mImage.mSize, chanImage,GxsIdDetails::ORIGINAL); + } else { chanImage = FilesDefs::getPixmapFromQtResourcePath(ChannelPostThumbnailView::CHAN_DEFAULT_IMAGE); - } + } if(group.mMeta.mGroupName.empty()) - ui->channelName_LB->setText(tr("[No name]")); + ui->channelName_LB->setText(tr("[No name]")); else - ui->channelName_LB->setText(QString::fromUtf8(group.mMeta.mGroupName.c_str())); + ui->channelName_LB->setText(QString::fromUtf8(group.mMeta.mGroupName.c_str())); - ui->logoLabel->setPixmap(chanImage); + ui->logoLabel->setPixmap(chanImage); ui->logoLabel->setFixedSize(QSize(ui->logoLabel->height()*chanImage.width()/(float)chanImage.height(),ui->logoLabel->height())); // make the logo have the same aspect ratio than the original image - ui->postButton->setEnabled(bool(group.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH)); + ui->postButton->setEnabled(bool(group.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH)); #ifdef TO_REMOVE - bool autoDownload ; - rsGxsChannels->getChannelAutoDownload(group.mMeta.mGroupId,autoDownload); - setAutoDownload(autoDownload); + bool autoDownload ; + rsGxsChannels->getChannelAutoDownload(group.mMeta.mGroupId,autoDownload); + setAutoDownload(autoDownload); #endif setSubscribeButtonText(group.mMeta.mGroupId,group.mMeta.mSubscribeFlags, group.mMeta.mPop); @@ -1150,12 +1279,12 @@ void GxsChannelPostsWidgetWithModel::insertChannelDetails(const RsGxsChannelGrou } - ui->infoPosts->setText(QString::number(group.mMeta.mVisibleMsgCount)); + ui->infoPosts->setText(QString::number(group.mMeta.mVisibleMsgCount)); - if(group.mMeta.mLastPost==0) - ui->infoLastPost->setText(tr("Never")); - else - ui->infoLastPost->setText(DateTime::formatLongDateTime(group.mMeta.mLastPost)); + if(group.mMeta.mLastPost==0) + ui->infoLastPost->setText(tr("Never")); + else + ui->infoLastPost->setText(DateTime::formatLongDateTime(group.mMeta.mLastPost)); uint32_t current_sync_time = GxsGroupFrameDialog::checkDelay(rsGxsChannels->getSyncPeriod(group.mMeta.mGroupId))/86400 ; @@ -1181,78 +1310,91 @@ void GxsChannelPostsWidgetWithModel::insertChannelDetails(const RsGxsChannelGrou ui->infoSyncTimeLabel->setText(sync_string); - QString formatDescription = QString::fromUtf8(group.mDescription.c_str()); + QString formatDescription = QString::fromUtf8(group.mDescription.c_str()); - unsigned int formatFlag = RSHTML_FORMATTEXT_EMBED_LINKS; + unsigned int formatFlag = RSHTML_FORMATTEXT_EMBED_LINKS; - // embed smileys ? - if (Settings->valueFromGroup(QString("ChannelPostsWidget"), QString::fromUtf8("Emoteicons_ChannelDecription"), true).toBool()) { - formatFlag |= RSHTML_FORMATTEXT_EMBED_SMILEYS; - } + // embed smileys ? + if (Settings->valueFromGroup(QString("ChannelPostsWidget"), QString::fromUtf8("Emoteicons_ChannelDecription"), true).toBool()) { + formatFlag |= RSHTML_FORMATTEXT_EMBED_SMILEYS; + } - formatDescription = RsHtml().formatText(NULL, formatDescription, formatFlag); + formatDescription = RsHtml().formatText(NULL, formatDescription, formatFlag); - ui->infoDescription->setText(formatDescription); + ui->infoDescription->setText(formatDescription); - ui->infoAdministrator->setId(group.mMeta.mAuthorId) ; + ui->infoAdministrator->setId(group.mMeta.mAuthorId) ; - if(!group.mMeta.mAuthorId.isNull()) - { - RetroShareLink link = RetroShareLink::createMessage(group.mMeta.mAuthorId, ""); - ui->infoAdministrator->setText(link.toHtml()); - } - else - ui->infoAdministrator->setText("[No contact author]"); + if(!group.mMeta.mAuthorId.isNull()) + { + RetroShareLink link = RetroShareLink::createMessage(group.mMeta.mAuthorId, ""); + ui->infoAdministrator->setText(link.toHtml()); + } + else + ui->infoAdministrator->setText("[No contact author]"); - ui->infoCreated->setText(DateTime::formatLongDateTime(group.mMeta.mPublishTs)); + ui->infoCreated->setText(DateTime::formatLongDateTime(group.mMeta.mPublishTs)); - QString distrib_string ( "[unknown]" ); + QString distrib_string ( "[unknown]" ); - switch((RsGxsCircleType)group.mMeta.mCircleType) - { - case RsGxsCircleType::PUBLIC: distrib_string = tr("Public") ; - break ; - case RsGxsCircleType::EXTERNAL: - { - RsGxsCircleDetails det ; + switch((RsGxsCircleType)group.mMeta.mCircleType) + { + case RsGxsCircleType::PUBLIC: distrib_string = tr("Public") ; + break ; + case RsGxsCircleType::EXTERNAL: + { + RsGxsCircleDetails det ; - // !! What we need here is some sort of CircleLabel, which loads the circle and updates the label when done. + // !! What we need here is some sort of CircleLabel, which loads the circle and updates the label when done. - if(rsGxsCircles->getCircleDetails(group.mMeta.mCircleId,det)) - distrib_string = tr("Restricted to members of circle \"")+QString::fromUtf8(det.mCircleName.c_str()) +"\""; - else - distrib_string = tr("Restricted to members of circle ")+QString::fromStdString(group.mMeta.mCircleId.toStdString()) ; - } - break ; - case RsGxsCircleType::YOUR_EYES_ONLY: distrib_string = tr("Your eyes only"); - break ; - case RsGxsCircleType::LOCAL: distrib_string = tr("You and your friend nodes"); - break ; - default: - std::cerr << "(EE) badly initialised group distribution ID = " << group.mMeta.mCircleType << std::endl; - } + if(rsGxsCircles->getCircleDetails(group.mMeta.mCircleId,det)) + distrib_string = tr("Restricted to members of circle \"")+QString::fromUtf8(det.mCircleName.c_str()) +"\""; + else + distrib_string = tr("Restricted to members of circle ")+QString::fromStdString(group.mMeta.mCircleId.toStdString()) ; + } + break ; + case RsGxsCircleType::YOUR_EYES_ONLY: distrib_string = tr("Your eyes only"); + break ; + case RsGxsCircleType::LOCAL: distrib_string = tr("You and your friend nodes"); + break ; + default: + std::cerr << "(EE) badly initialised group distribution ID = " << group.mMeta.mCircleType << std::endl; + } - ui->infoDistribution->setText(distrib_string); + ui->infoDistribution->setText(distrib_string); #ifdef TODO - ui->infoWidget->show(); - ui->feedWidget->hide(); - ui->fileWidget->hide(); + ui->infoWidget->show(); + ui->feedWidget->hide(); + ui->fileWidget->hide(); - //ui->feedToolButton->setEnabled(false); - //ui->fileToolButton->setEnabled(false); + //ui->feedToolButton->setEnabled(false); + //ui->fileToolButton->setEnabled(false); #endif setSubscribeButtonText(group.mMeta.mGroupId,group.mMeta.mSubscribeFlags, group.mMeta.mPop); showPostDetails(); } - -void GxsChannelPostsWidgetWithModel::showChannelFilesContextMenu(QPoint /*p*/) +void GxsChannelPostsWidgetWithModel::showChannelFilesContextMenu(QPoint p) { - QMenu contextMnu(this) ; + QModelIndex index = ui->channelFiles_TV->indexAt(p); - QAction *action = contextMnu.addAction(QIcon(), tr("Copy Retroshare link"), this, SLOT(copyChannelFilesLink())); - action->setData(QVariant::fromValue(sender())); + if(!index.isValid()) + return; + + QMenu contextMnu(this) ; + contextMnu.addAction(QIcon(), tr("Copy Retroshare link"), this, SLOT(copyChannelFilesLink()))->setData(QVariant::fromValue(index)); + contextMnu.exec(QCursor::pos()); +} +void GxsChannelPostsWidgetWithModel::showChannelPostFilesContextMenu(QPoint p) +{ + QModelIndex index = ui->channelPostFiles_TV->indexAt(p); + + if(!index.isValid()) + return; + + QMenu contextMnu(this) ; + contextMnu.addAction(QIcon(), tr("Copy Retroshare link"), this, SLOT(copyChannelFilesLink()))->setData(QVariant::fromValue(index)); contextMnu.exec(QCursor::pos()); } @@ -1260,16 +1402,11 @@ void GxsChannelPostsWidgetWithModel::copyChannelFilesLink() { // Block the popup if no results available QAction *action = dynamic_cast(sender()); - RSTreeView *tree = dynamic_cast(action->data().value()); - - QModelIndexList sel = tree->selectionModel()->selection().indexes(); - - if(sel.empty()) - return; + QModelIndex s = action->data().toModelIndex(); ChannelPostFileInfo file; - if(!static_cast(tree->model())->getFileData(sel.front(),file)) + if(!static_cast(s.model())->getFileData(s,file)) return; RetroShareLink link = RetroShareLink::createFile(QString::fromUtf8(file.mName.c_str()), file.mSize, QString::fromStdString(file.mHash.toStdString())); @@ -1318,70 +1455,70 @@ void GxsChannelPostsWidgetWithModel::switchOnlyUnread(bool) } void GxsChannelPostsWidgetWithModel::filterChanged(QString s) { - QStringList ql = s.split(' ',QString::SkipEmptyParts); - uint32_t count; - mChannelPostsModel->setFilter(ql,ui->showUnread_TB->isChecked(),count); - mChannelFilesModel->setFilter(ql,count); + QStringList ql = s.split(' ',QtSkipEmptyParts); + uint32_t count; + mChannelPostsModel->setFilter(ql,ui->showUnread_TB->isChecked(),count); + mChannelFilesModel->setFilter(ql,count); } void GxsChannelPostsWidgetWithModel::blank() { - ui->postButton->setEnabled(false); - ui->subscribeToolButton->setEnabled(false); + ui->postButton->setEnabled(false); + ui->subscribeToolButton->setEnabled(false); - ui->channelName_LB->setText(tr("No Channel Selected")); - ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/channels.png")); - ui->infoPosts->setText(""); - ui->infoLastPost->setText(""); - ui->infoAdministrator->setText(""); - ui->infoDistribution->setText(""); - ui->infoCreated->setText(""); - ui->infoDescription->setText(""); + ui->channelName_LB->setText(tr("No Channel Selected")); + ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/channels.png")); + ui->infoPosts->setText(""); + ui->infoLastPost->setText(""); + ui->infoAdministrator->setText(""); + ui->infoDistribution->setText(""); + ui->infoCreated->setText(""); + ui->infoDescription->setText(""); - mChannelPostsModel->clear(); - mChannelPostFilesModel->clear(); - ui->postDetails_TE->clear(); - ui->postLogo_LB->hide(); - ui->postName_LB->hide(); - ui->postTime_LB->hide(); - ui->postDAll_PB->hide(); - groupNameChanged(QString()); + mChannelPostsModel->clear(); + mChannelPostFilesModel->clear(); + ui->postDetails_TE->clear(); + ui->postLogo_LB->hide(); + ui->postName_LB->hide(); + ui->postTime_LB->hide(); + ui->postDAll_PB->hide(); + groupNameChanged(QString()); } bool GxsChannelPostsWidgetWithModel::navigate(const RsGxsMessageId& msgId) { - QModelIndex index = mChannelPostsModel->getIndexOfMessage(msgId); + QModelIndex index = mChannelPostsModel->getIndexOfMessage(msgId); - if(!index.isValid()) - { - std::cerr << "(EE) Cannot navigate to msg " << msgId << " in channel " << mGroup.mMeta.mGroupId << ": index unknown. Setting mNavigatePendingMsgId." << std::endl; + if(!index.isValid()) + { + std::cerr << "(EE) Cannot navigate to msg " << msgId << " in channel " << mGroup.mMeta.mGroupId << ": index unknown. Setting mNavigatePendingMsgId." << std::endl; - mNavigatePendingMsgId = msgId; // not found. That means the forum may not be loaded yet. So we keep that post in mind, for after loading. - return true; // we have to return true here, otherwise the caller will intepret the async loading as an error. - } + mNavigatePendingMsgId = msgId; // not found. That means the forum may not be loaded yet. So we keep that post in mind, for after loading. + return true; // we have to return true here, otherwise the caller will intepret the async loading as an error. + } - ui->postsTree->selectionModel()->setCurrentIndex(index,QItemSelectionModel::ClearAndSelect); - ui->postsTree->scrollTo(index);//May change if model reloaded - ui->postsTree->setFocus(); + ui->postsTree->selectionModel()->setCurrentIndex(index,QItemSelectionModel::ClearAndSelect); + ui->postsTree->scrollTo(index);//May change if model reloaded + ui->postsTree->setFocus(); - ui->channel_TW->setCurrentIndex(CHANNEL_TABS_POSTS); - ui->details_TW->setCurrentIndex(CHANNEL_TABS_DETAILS); + ui->channel_TW->setCurrentIndex(CHANNEL_TABS_POSTS); + ui->details_TW->setCurrentIndex(CHANNEL_TABS_DETAILS); - mNavigatePendingMsgId.clear(); + mNavigatePendingMsgId.clear(); - return true; + return true; } void GxsChannelPostsWidgetWithModel::subscribeGroup(bool subscribe) { - RsGxsGroupId grpId(groupId()); - if (grpId.isNull()) return; + RsGxsGroupId grpId(groupId()); + if (grpId.isNull()) return; - RsThread::async([=]() - { - rsGxsChannels->subscribeToChannel(grpId, subscribe); - } ); + RsThread::async([=]() + { + rsGxsChannels->subscribeToChannel(grpId, subscribe); + } ); } #ifdef TO_REMOVE @@ -1393,52 +1530,50 @@ void GxsChannelPostsWidgetWithModel::setAutoDownload(bool autoDl) void GxsChannelPostsWidgetWithModel::toggleAutoDownload() { - RsGxsGroupId grpId = groupId(); - if (grpId.isNull()) { - return; - } + RsGxsGroupId grpId = groupId(); + if (grpId.isNull()) { + return; + } - bool autoDownload; - if(!rsGxsChannels->getChannelAutoDownload(grpId, autoDownload)) - { - std::cerr << __PRETTY_FUNCTION__ << " failed to get autodownload value " - << "for channel: " << grpId.toStdString() << std::endl; - return; - } + bool autoDownload; + if(!rsGxsChannels->getChannelAutoDownload(grpId, autoDownload)) + { + std::cerr << __PRETTY_FUNCTION__ << " failed to get autodownload value " + << "for channel: " << grpId.toStdString() << std::endl; + return; + } - RsThread::async([this, grpId, autoDownload]() - { - if(!rsGxsChannels->setChannelAutoDownload(grpId, !autoDownload)) - { - std::cerr << __PRETTY_FUNCTION__ << " failed to set autodownload " - << "for channel: " << grpId.toStdString() << std::endl; - return; - } - }); + RsThread::async([this, grpId, autoDownload]() + { + if(!rsGxsChannels->setChannelAutoDownload(grpId, !autoDownload)) + { + std::cerr << __PRETTY_FUNCTION__ << " failed to set autodownload " + << "for channel: " << grpId.toStdString() << std::endl; + return; + } + }); } #endif class GxsChannelPostsReadData { public: - explicit GxsChannelPostsReadData(bool read) - { - mRead = read; - mLastToken = 0; - } + explicit GxsChannelPostsReadData(bool read) + { + mRead = read; + } public: - bool mRead; - uint32_t mLastToken; + bool mRead; }; -void GxsChannelPostsWidgetWithModel::setAllMessagesReadDo(bool read, uint32_t& /*token*/) +void GxsChannelPostsWidgetWithModel::setAllMessagesReadDo(bool read) { - if (groupId().isNull() || !IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags)) - return; + if (groupId().isNull() || !IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags)) + return; - //QModelIndex src_index; + //QModelIndex src_index; - mChannelPostsModel->setAllMsgReadStatus(read); + mChannelPostsModel->setAllMsgReadStatus(read); } diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.h b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.h index eaac53c0f..8891b57dd 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.h +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.h @@ -47,7 +47,7 @@ class ChannelPostFilesDelegate: public QStyledItemDelegate Q_OBJECT public: - ChannelPostFilesDelegate(QObject *parent=0) : QStyledItemDelegate(parent){} + ChannelPostFilesDelegate(QObject *parent=0) : QStyledItemDelegate(parent){} virtual ~ChannelPostFilesDelegate(){} void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const override; @@ -104,11 +104,11 @@ public: /* GxsMessageFrameWidget */ virtual QIcon groupIcon() override; - virtual void groupIdChanged() override { updateDisplay(true); } + virtual void groupIdChanged() override { updateDisplay(true,true); } virtual QString groupName(bool) override; virtual bool navigate(const RsGxsMessageId&) override; - void updateDisplay(bool complete); + void updateDisplay(bool update_group_data, bool update_posts); #ifdef TODO /* FeedHolder */ @@ -137,11 +137,13 @@ protected: #endif /* GxsMessageFrameWidget */ - virtual void setAllMessagesReadDo(bool read, uint32_t &token) override; + virtual void setAllMessagesReadDo(bool read) override; + virtual void resizeEvent(QResizeEvent *e) override; + virtual void keyPressEvent(QKeyEvent *e) override; private slots: void showPostDetails(); - void updateGroupData(); + void updateData(bool update_group_data,bool update_posts); void download(); void updateDAll_PB(); void createMsg(); @@ -154,20 +156,23 @@ private slots: void editPost(); void postContextMenu(const QPoint&); void copyMessageLink(); - void updateZoomFactor(bool zoom_or_unzoom); + void onUpdateZoomFactor(bool zoom_or_unzoom); void switchView(); void switchOnlyUnread(bool b); void markMessageUnread(); public slots: + void currentTabChanged(int t); void sortColumnFiles(int col,Qt::SortOrder so); void sortColumnPostFiles(int col,Qt::SortOrder so); void updateCommentsCount(int n); void showChannelFilesContextMenu(QPoint p); + void showChannelPostFilesContextMenu(QPoint p); void copyChannelFilesLink(); private: - void processSettings(bool load); + void updateZoomFactor(int what_to_do); // -1=unzoom, 0=nothing, 1=zoom + void processSettings(bool load); RsGxsMessageId getCurrentItemId() const; void selectItem(const RsGxsMessageId& msg_id); diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.ui b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.ui index 4bdae007a..2740b4654 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.ui +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.ui @@ -29,10 +29,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -55,6 +55,13 @@ 0 + + + 12 + 75 + true + + Subscribe @@ -77,6 +84,12 @@ + + + 75 + true + + Qt::NoFocus @@ -181,7 +194,7 @@ - 1 + 0 @@ -189,12 +202,12 @@ - + + 25 75 true - false @@ -322,7 +335,7 @@ <html><head/><body><p>Includes all posts, comments and votes. This number is progressively updated when new friend connect. The local vs. at friends difference may indicate that you would get older posts by increasing the synchronization period.</p></body></html> - Posts (locally / at friends): + Items (locally / at friends): @@ -389,7 +402,7 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'.AppleSystemUIFont'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Description</span></p></body></html> @@ -521,7 +534,7 @@ p, li { white-space: pre-wrap; } - + 75 @@ -644,33 +657,34 @@ p, li { white-space: pre-wrap; } QLineEdit
    gui/common/LineEditClear.h
    + + RSTreeView + QTreeView +
    gui/common/RSTreeView.h
    + 1 +
    GxsIdLabel QLabel
    gui/gxs/GxsIdLabel.h
    + + ElidedLabel + QLabel +
    gui/common/ElidedLabel.h
    + 1 +
    SubscribeToolButton QToolButton
    gui/common/SubscribeToolButton.h
    - - RSTreeView - QTreeView -
    gui/common/RSTreeView.h
    - 1 -
    GxsCommentDialog QWidget
    gui/gxs/GxsCommentDialog.h
    1
    - - StyledElidedLabel - QLabel -
    gui/common/StyledElidedLabel.h
    -
    diff --git a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp index 3cf29ecf1..3224b428f 100644 --- a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp +++ b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp @@ -19,6 +19,7 @@ *******************************************************************************/ #include "CreateGxsForumMsg.h" +#include "ui_CreateGxsForumMsg.h" #include #include @@ -39,6 +40,7 @@ #include "util/HandleRichText.h" #include "util/misc.h" +#include "util/qtthreadsutils.h" #include #include @@ -53,67 +55,64 @@ /** Constructor */ CreateGxsForumMsg::CreateGxsForumMsg(const RsGxsGroupId &fId, const RsGxsMessageId &pId, const RsGxsMessageId& mOId, const RsGxsId& posterId, bool isModerating) : QDialog(NULL, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint), - mForumId(fId), mParentId(pId), mOrigMsgId(mOId),mPosterId(posterId),mIsModerating(isModerating) + mForumId(fId), mParentId(pId), mOrigMsgId(mOId),mPosterId(posterId),mIsModerating(isModerating), + ui(new Ui::CreateGxsForumMsg) { /* Invoke the Qt Designer generated object setup routine */ - ui.setupUi(this); + ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose, true); - /* Setup Queue */ - mForumQueue = new TokenQueue(rsGxsForums->getTokenService(), this); - mCirclesQueue = new TokenQueue(rsGxsCircles->getTokenService(), this); - /* Setup UI helper */ mStateHelper = new UIStateHelper(this); - mStateHelper->addWidget(CREATEGXSFORUMMSG_FORUMINFO, ui.postButton); - mStateHelper->addWidget(CREATEGXSFORUMMSG_FORUMINFO, ui.innerFrame); - mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_FORUMINFO, ui.forumName); - mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_FORUMINFO, ui.forumSubject); - mStateHelper->addClear(CREATEGXSFORUMMSG_FORUMINFO, ui.forumName); + mStateHelper->addWidget(CREATEGXSFORUMMSG_FORUMINFO, ui->postButton); + mStateHelper->addWidget(CREATEGXSFORUMMSG_FORUMINFO, ui->innerFrame); + mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_FORUMINFO, ui->forumName); + mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_FORUMINFO, ui->forumSubject, false); + mStateHelper->addClear(CREATEGXSFORUMMSG_FORUMINFO, ui->forumName); - mStateHelper->addWidget(CREATEGXSFORUMMSG_PARENTMSG, ui.postButton); - mStateHelper->addWidget(CREATEGXSFORUMMSG_PARENTMSG, ui.innerFrame); - mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_PARENTMSG, ui.forumName); - mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_PARENTMSG, ui.forumSubject); - mStateHelper->addClear(CREATEGXSFORUMMSG_PARENTMSG, ui.forumName); + mStateHelper->addWidget(CREATEGXSFORUMMSG_PARENTMSG, ui->postButton); + mStateHelper->addWidget(CREATEGXSFORUMMSG_PARENTMSG, ui->innerFrame); + mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_PARENTMSG, ui->forumName); + mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_PARENTMSG, ui->forumSubject, false); + mStateHelper->addClear(CREATEGXSFORUMMSG_PARENTMSG, ui->forumName); - mStateHelper->addWidget(CREATEGXSFORUMMSG_ORIGMSG, ui.postButton); - mStateHelper->addWidget(CREATEGXSFORUMMSG_ORIGMSG, ui.innerFrame); - mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_ORIGMSG, ui.forumName); - mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_ORIGMSG, ui.forumSubject); - mStateHelper->addClear(CREATEGXSFORUMMSG_ORIGMSG, ui.forumName); + mStateHelper->addWidget(CREATEGXSFORUMMSG_ORIGMSG, ui->postButton); + mStateHelper->addWidget(CREATEGXSFORUMMSG_ORIGMSG, ui->innerFrame); + mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_ORIGMSG, ui->forumName); + mStateHelper->addLoadPlaceholder(CREATEGXSFORUMMSG_ORIGMSG, ui->forumSubject, false); + mStateHelper->addClear(CREATEGXSFORUMMSG_ORIGMSG, ui->forumName); QString text = mOId.isNull()?(pId.isNull() ? tr("Start New Thread") : tr("Post Forum Message")):tr("Edit Message"); setWindowTitle(text); if (!mOId.isNull()) - ui.postButton->setText(tr ("Update")); + ui->postButton->setText(tr ("Update")); - ui.forumMessage->setPlaceholderText(tr ("Text")); + ui->forumMessage->setPlaceholderText(tr ("Text")); - ui.headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/forums.png")); - ui.headerFrame->setHeaderText(text); + ui->headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/forums.png")); + ui->headerFrame->setHeaderText(text); - ui.generateSpinBox->setEnabled(false); + ui->generateSpinBox->setEnabled(false); Settings->loadWidgetInformation(this); - connect(ui.hashBox, SIGNAL(fileHashingFinished(QList)), this, SLOT(fileHashingFinished(QList))); + connect(ui->hashBox, SIGNAL(fileHashingFinished(QList)), this, SLOT(fileHashingFinished(QList))); // connect up the buttons. - connect(ui.postButton, SIGNAL(clicked()), this, SLOT(createMsg())); - connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(reject())); - connect(ui.emoticonButton, SIGNAL(clicked()), this, SLOT(smileyWidgetForums())); - connect(ui.attachFileButton, SIGNAL(clicked()), this, SLOT(addFile())); - connect(ui.attachPictureButton, SIGNAL(clicked()), this, SLOT(addPicture())); - connect(ui.forumMessage, SIGNAL(textChanged()), this, SLOT(checkLength())); - connect(ui.generateCheckBox, SIGNAL(toggled(bool)), ui.generateSpinBox, SLOT(setEnabled(bool))); + connect(ui->postButton, SIGNAL(clicked()), this, SLOT(createMsg())); + connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(reject())); + connect(ui->emoticonButton, SIGNAL(clicked()), this, SLOT(smileyWidgetForums())); + connect(ui->attachFileButton, SIGNAL(clicked()), this, SLOT(addFile())); + connect(ui->attachPictureButton, SIGNAL(clicked()), this, SLOT(addPicture())); + connect(ui->forumMessage, SIGNAL(textChanged()), this, SLOT(checkLength())); + connect(ui->generateCheckBox, SIGNAL(toggled(bool)), ui->generateSpinBox, SLOT(setEnabled(bool))); setAcceptDrops(true); - ui.hashBox->setDropWidget(this); - ui.hashBox->setAutoHide(false); + ui->hashBox->setDropWidget(this); + ui->hashBox->setAutoHide(false); mParentMsgLoaded = false; mForumMetaLoaded = false; @@ -121,11 +120,11 @@ CreateGxsForumMsg::CreateGxsForumMsg(const RsGxsGroupId &fId, const RsGxsMessage newMsg(); - ui.hashGroupBox->hide(); + ui->hashGroupBox->hide(); #ifndef ENABLE_GENERATE - ui.generateCheckBox->hide(); - ui.generateSpinBox->hide(); + ui->generateCheckBox->hide(); + ui->generateSpinBox->hide(); #endif processSettings(true); } @@ -133,8 +132,9 @@ CreateGxsForumMsg::CreateGxsForumMsg(const RsGxsGroupId &fId, const RsGxsMessage CreateGxsForumMsg::~CreateGxsForumMsg() { processSettings(false); - delete(mForumQueue); - delete(mCirclesQueue); + + delete ui; + } void CreateGxsForumMsg::processSettings(bool load) @@ -147,14 +147,14 @@ void CreateGxsForumMsg::processSettings(bool load) RsGxsId gxs_id(Settings->value("IDChooser", QString::fromStdString(RsGxsId().toStdString())).toString().toStdString()); if(!gxs_id.isNull() && rsIdentity->isOwnId(gxs_id)) - ui.idChooser->setChosenId(gxs_id); + ui->idChooser->setChosenId(gxs_id); } else { // state of ID Chooser combobox RsGxsId id; - if(ui.idChooser->getChosenId(id)) + if(ui->idChooser->getChosenId(id)) Settings->setValue("IDChooser", QString::fromStdString(id.toStdString())); } @@ -176,11 +176,11 @@ void CreateGxsForumMsg::newMsg() std::set id_set ; id_set.insert(mPosterId) ; - ui.idChooser->loadIds(IDCHOOSER_ID_REQUIRED | IDCHOOSER_NO_CREATE, mPosterId); - ui.idChooser->setIdConstraintSet(id_set); + ui->idChooser->loadIds(IDCHOOSER_ID_REQUIRED | IDCHOOSER_NO_CREATE, mPosterId); + ui->idChooser->setIdConstraintSet(id_set); } else - ui.idChooser->loadIds(IDCHOOSER_ID_REQUIRED, mPosterId); + ui->idChooser->loadIds(IDCHOOSER_ID_REQUIRED, mPosterId); if (mForumId.isNull()) { mStateHelper->setActive(CREATEGXSFORUMMSG_FORUMINFO, false); @@ -190,126 +190,119 @@ void CreateGxsForumMsg::newMsg() mStateHelper->clear(CREATEGXSFORUMMSG_FORUMINFO); mStateHelper->clear(CREATEGXSFORUMMSG_PARENTMSG); mStateHelper->clear(CREATEGXSFORUMMSG_ORIGMSG); - ui.forumName->setText(tr("No Forum")); + ui->forumName->setText(tr("No Forum")); return; } - {/* request Data */ - mStateHelper->setLoading(CREATEGXSFORUMMSG_FORUMINFO, true); + mStateHelper->setLoading(CREATEGXSFORUMMSG_FORUMINFO, true); - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + if (mParentId.isNull()) + { + mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, false); + mParentMsgLoaded = true; + } + else + { + mStateHelper->setLoading(CREATEGXSFORUMMSG_PARENTMSG, true); + mParentMsgLoaded = false; + } - std::list groupIds; - groupIds.push_back(mForumId); + if (mOrigMsgId.isNull()) + { + mStateHelper->setActive(CREATEGXSFORUMMSG_ORIGMSG, false); + mOrigMsgLoaded = true; + } + else + { + mStateHelper->setLoading(CREATEGXSFORUMMSG_ORIGMSG, true); + mOrigMsgLoaded = false; + } - //std::cerr << "ForumsV2Dialog::newMsg() Requesting Group Summary(" << mForumId << ")"<< std::endl; + RsThread::async( [this]() + { + // We only need group Meta information, but forums do not provide it currently - uint32_t token; - mForumQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, groupIds, CREATEGXSFORUMMSG_FORUMINFO); - }/* request Data */ + std::vector forums_info; + rsGxsForums->getForumsInfo(std::list{ mForumId },forums_info); - if (mParentId.isNull()) { - mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, true); - mParentMsgLoaded = true; - } else { - mStateHelper->setLoading(CREATEGXSFORUMMSG_PARENTMSG, true); + // Load parent message - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + RsGxsForumMsg parent_msg; - GxsMsgReq msgIds; - std::set &vect = msgIds[mForumId]; - vect.insert(mParentId); + if(!mParentId.isNull()) + { + std::vector parent_msgs; + rsGxsForums->getForumContent(mForumId,std::set{ mParentId },parent_msgs); - //std::cerr << "ForumsV2Dialog::newMsg() Requesting Parent Summary(" << mParentId << ")"; - //std::cerr << std::endl; + if(parent_msgs.size() == 1) + parent_msg = *parent_msgs.begin(); + else + RsErr() << "Cannot get parent message " << mParentId << " from forum." ; + } - uint32_t token; - mForumQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, CREATEGXSFORUMMSG_PARENTMSG); - } + // Load original message (edit mode) - if (mOrigMsgId.isNull()) { - mStateHelper->setActive(CREATEGXSFORUMMSG_ORIGMSG, true); - mOrigMsgLoaded = true; - } else { - mStateHelper->setLoading(CREATEGXSFORUMMSG_ORIGMSG, true); + RsGxsForumMsg orig_msg; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + if(!mOrigMsgId.isNull()) + { + std::vector orig_msgs; + rsGxsForums->getForumContent(mForumId,std::set{ mOrigMsgId },orig_msgs); - GxsMsgReq msgIds; - std::set &vect = msgIds[mForumId]; - vect.insert(mOrigMsgId); + if(orig_msgs.size() == 1) + orig_msg = *orig_msgs.begin(); + else + RsErr() << "Cannot get orig message " << mOrigMsgId << " from forum." ; + } - //std::cerr << "ForumsV2Dialog::newMsg() Requesting Parent Summary(" << mParentId << ")"; - //std::cerr << std::endl; + // Now update GUI with all that nice data - uint32_t token; - mForumQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, CREATEGXSFORUMMSG_ORIGMSG); - } + RsQThreadUtils::postToObject( [this,forums_info,parent_msg,orig_msg]() + { + if(forums_info.size() != 1) + { + RsErr() << "Cannot retrieve group information for forum " << mForumId ; + + return; + } + auto fg(forums_info.front()); + + mForumMetaLoaded = true; + mForumMeta = fg.mMeta; + + if(!parent_msg.mMsg.empty()) + { + mParentMsg = parent_msg; + mParentMsgLoaded = true; + } + if(!orig_msg.mMsg.empty()) + { + mOrigMsg = orig_msg; + mOrigMsgLoaded = true; + } + + if(!mForumMeta.mCircleId.isNull()) + loadCircleInfo(RsGxsGroupId(mForumMeta.mCircleId)); + + // Now update the GUI + + mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, mParentMsgLoaded); + mStateHelper->setLoading(CREATEGXSFORUMMSG_PARENTMSG, false); + + mStateHelper->setActive(CREATEGXSFORUMMSG_ORIGMSG, mOrigMsgLoaded); + mStateHelper->setLoading(CREATEGXSFORUMMSG_ORIGMSG, false); + + mStateHelper->setActive(CREATEGXSFORUMMSG_FORUMINFO, mForumMetaLoaded); + mStateHelper->setLoading(CREATEGXSFORUMMSG_FORUMINFO, false); + + loadFormInformation(); + + },this); + }); } void CreateGxsForumMsg::loadFormInformation() { - if (!mOrigMsgId.isNull()) - { - if (mOrigMsgLoaded) { - mStateHelper->setActive(CREATEGXSFORUMMSG_ORIGMSG, true); - mStateHelper->setLoading(CREATEGXSFORUMMSG_ORIGMSG, false); - } else { - //std::cerr << "CreateGxsForumMsg::loadMsgInformation() ParentMsg not Loaded Yet"; - //std::cerr << std::endl; - - mStateHelper->setActive(CREATEGXSFORUMMSG_ORIGMSG, false); - - return; - } - } - else - { - mStateHelper->setActive(CREATEGXSFORUMMSG_ORIGMSG, true); - mStateHelper->setLoading(CREATEGXSFORUMMSG_ORIGMSG, false); - } - - - if (!mParentId.isNull()) - { - if (mParentMsgLoaded) { - mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, true); - mStateHelper->setLoading(CREATEGXSFORUMMSG_PARENTMSG, false); - } else { - //std::cerr << "CreateGxsForumMsg::loadMsgInformation() ParentMsg not Loaded Yet"; - //std::cerr << std::endl; - - mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, false); - - return; - } - } - else - { - mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, true); - mStateHelper->setLoading(CREATEGXSFORUMMSG_PARENTMSG, false); - } - - if (mForumMetaLoaded) { - mStateHelper->setActive(CREATEGXSFORUMMSG_FORUMINFO, true); - mStateHelper->setLoading(CREATEGXSFORUMMSG_FORUMINFO, false); - } else { - //std::cerr << "CreateGxsForumMsg::loadMsgInformation() ForumMeta not Loaded Yet"; - //std::cerr << std::endl; - - mStateHelper->setActive(CREATEGXSFORUMMSG_FORUMINFO, false); - - return; - } - - //std::cerr << "CreateGxsForumMsg::loadMsgInformation() Data Available!"; - //std::cerr << std::endl; - - //std::cerr << "CreateGxsForumMsg::loadMsgInformation() using signFlags=" << std::hex << mForumMeta.mSignFlags << std::dec << std::endl; - uint32_t fl = IDCHOOSER_ID_REQUIRED ; if( (mForumMeta.mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) || (mForumMeta.mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN)) @@ -318,19 +311,17 @@ void CreateGxsForumMsg::loadFormInformation() if(!mPosterId.isNull()) fl |= IDCHOOSER_NO_CREATE; - ui.idChooser->setFlags(fl) ; + ui->idChooser->setFlags(fl) ; QString name = QString::fromUtf8(mForumMeta.mGroupName.c_str()); QString subj; if(!mOrigMsgId.isNull()) - { subj = QString::fromUtf8(mOrigMsg.mMeta.mMsgName.c_str()); - } else if (!mParentId.isNull()) { QString title = QString::fromUtf8(mParentMsg.mMeta.mMsgName.c_str()); - name += " " + tr("In Reply to") + ": "; + name += " - " + tr("In Reply to") + ": "; name += title; QString text = title; @@ -341,18 +332,19 @@ void CreateGxsForumMsg::loadFormInformation() subj = "Re: " + title; } - ui.forumName->setText(misc::removeNewLine(name)); + ui->forumName->setText(misc::removeNewLine(name)); + std::cerr << "Setting name to \"" << misc::removeNewLine(name).toStdString() << std::endl; if(!subj.isNull()) - ui.forumSubject->setText(misc::removeNewLine(subj)); + ui->forumSubject->setText(misc::removeNewLine(subj)); - if (ui.forumSubject->text().isEmpty()) + if (ui->forumSubject->text().isEmpty()) { - ui.forumSubject->setFocus(); - ui.forumSubject->setPlaceholderText(tr ("Title")); + ui->forumSubject->setFocus(); + ui->forumSubject->setPlaceholderText(tr ("Title")); } else - ui.forumMessage->setFocus(); + ui->forumMessage->setFocus(); #ifdef TOGXS if (mForumMeta.mGroupFlags & RS_DISTRIB_AUTHEN_REQ) @@ -360,18 +352,18 @@ void CreateGxsForumMsg::loadFormInformation() if (1) #endif { - ui.signBox->setChecked(true); - ui.signBox->setEnabled(false); - ui.signBox->hide(); + ui->signBox->setChecked(true); + ui->signBox->setEnabled(false); + ui->signBox->hide(); } else { /* Uncheck sign box by default for anonymous forums */ - ui.signBox->setChecked(false); - ui.signBox->setEnabled(true); + ui->signBox->setChecked(false); + ui->signBox->setEnabled(true); } - //ui.forumMessage->setText(""); + //ui->forumMessage->setText(""); } static const uint32_t MAX_ALLOWED_GXS_MESSAGE_SIZE = 199000; @@ -379,27 +371,27 @@ static const uint32_t MAX_ALLOWED_GXS_MESSAGE_SIZE = 199000; void CreateGxsForumMsg::checkLength() { QString text; - RsHtml::optimizeHtml(ui.forumMessage, text); + RsHtml::optimizeHtml(ui->forumMessage, text); std::wstring msg = text.toStdWString(); int charRemains = MAX_ALLOWED_GXS_MESSAGE_SIZE - msg.length(); if(charRemains >= 0) { text = tr("It remains %1 characters after HTML conversion.").arg(charRemains); - ui.infoLabel->setStyleSheet("QLabel#infoLabel { }"); + ui->info_Label->setStyleSheet("QLabel#info_Label { }"); }else{ text = tr("Warning: This message is too big of %1 characters after HTML conversion.").arg((0-charRemains)); - ui.infoLabel->setStyleSheet("QLabel#infoLabel {color: red; font: bold; }"); + ui->info_Label->setStyleSheet("QLabel#info_Label {color: red; font: bold; }"); } - ui.postButton->setToolTip(text); - ui.postButton->setEnabled(charRemains>=0); - ui.infoLabel->setText(text); + ui->postButton->setToolTip(text); + ui->postButton->setEnabled(charRemains>=0); + ui->info_Label->setText(text); } void CreateGxsForumMsg::createMsg() { - QString name = misc::removeNewLine(ui.forumSubject->text()); + QString name = misc::removeNewLine(ui->forumSubject->text()); QString desc; - RsHtml::optimizeHtml(ui.forumMessage, desc); + RsHtml::optimizeHtml(ui->forumMessage, desc); if(name.isEmpty() | desc.isEmpty()) { /* error message */ @@ -428,9 +420,9 @@ void CreateGxsForumMsg::createMsg() if ((msg.mMsg == "") && (msg.mMeta.mMsgName == "")) return; /* do nothing */ - if (ui.signBox->isChecked()) { + if (ui->signBox->isChecked()) { RsGxsId authorId; - switch (ui.idChooser->getChosenId(authorId)) { + switch (ui->idChooser->getChosenId(authorId)) { case GxsIdChooser::KnowId: case GxsIdChooser::UnKnowId: msg.mMeta.mAuthorId = authorId; @@ -457,26 +449,26 @@ void CreateGxsForumMsg::createMsg() default: std::cerr << "CreateGxsForumMsg::createMsg() ERROR GETTING AuthorId!"; std::cerr << std::endl; - QMessageBox::warning(this, tr("RetroShare"),tr("Congrats, you found a bug!")+" "+QString(__FILE__)+":"+QString(__LINE__), QMessageBox::Ok, QMessageBox::Ok); + QMessageBox::warning(this, tr("RetroShare"),tr("Congrats, you found a bug!")+" "+QString(__FILE__)+":"+QString::number(__LINE__), QMessageBox::Ok, QMessageBox::Ok); return; - }//switch (ui.idChooser->getChosenId(authorId)) + }//switch (ui->idChooser->getChosenId(authorId)) } else { //std::cerr << "CreateGxsForumMsg::createMsg() No Signature (for now :)"; //std::cerr << std::endl; QMessageBox::warning(this, tr("RetroShare"),tr("Please choose Signing Id, it is required"), QMessageBox::Ok, QMessageBox::Ok); return; - }//if (ui.signBox->isChecked()) + }//if (ui->signBox->isChecked()) int generateCount = 0; #ifdef ENABLE_GENERATE - if (ui.generateCheckBox->isChecked()) { - generateCount = ui.generateSpinBox->value(); + if (ui->generateCheckBox->isChecked()) { + generateCount = ui->generateSpinBox->value(); if (QMessageBox::question(this, tr("Generate mass data"), tr("Do you really want to generate %1 messages ?").arg(generateCount), QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::No) { return; }//if (QMessageBox::question(this, - }//if (ui.generateCheckBox->isChecked()) + }//if (ui->generateCheckBox->isChecked()) #endif uint32_t token; @@ -503,7 +495,7 @@ void CreateGxsForumMsg::closeEvent (QCloseEvent * /*event*/) void CreateGxsForumMsg::reject() { - if (ui.forumMessage->document()->isModified()) { + if (ui->forumMessage->document()->isModified()) { QMessageBox::StandardButton ret; ret = QMessageBox::warning(this, tr("Cancel Forum Message"), tr("Forum Message has not been sent yet!\n" @@ -524,7 +516,7 @@ void CreateGxsForumMsg::reject() void CreateGxsForumMsg::smileyWidgetForums() { - Emoticons::showSmileyWidget(this, ui.emoticonButton, SLOT(addSmileys()), false); + Emoticons::showSmileyWidget(this, ui->emoticonButton, SLOT(addSmileys()), false); } void CreateGxsForumMsg::addSmileys() @@ -533,17 +525,17 @@ void CreateGxsForumMsg::addSmileys() // add trailing space smiley += QString(" "); // add preceding space when needed (not at start of text or preceding space already exists) - if(!ui.forumMessage->textCursor().atStart() && ui.forumMessage->toPlainText()[ui.forumMessage->textCursor().position() - 1] != QChar(' ')) + if(!ui->forumMessage->textCursor().atStart() && ui->forumMessage->toPlainText()[ui->forumMessage->textCursor().position() - 1] != QChar(' ')) smiley = QString(" ") + smiley; - ui.forumMessage->textCursor().insertText(smiley); + ui->forumMessage->textCursor().insertText(smiley); } void CreateGxsForumMsg::addFile() { QStringList files; if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) { - ui.hashBox->addAttachments(files,RS_FILE_REQ_ANONYMOUS_ROUTING); - ui.hashGroupBox->show(); + ui->hashBox->addAttachments(files,RS_FILE_REQ_ANONYMOUS_ROUTING); + ui->hashGroupBox->show(); } } @@ -554,7 +546,7 @@ void CreateGxsForumMsg::addPicture() QString encodedImage; if (RsHtml::makeEmbeddedImage(file, encodedImage, 640*480, MAX_ALLOWED_GXS_MESSAGE_SIZE - 200)) { QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(encodedImage); - ui.forumMessage->textCursor().insertFragment(fragment); + ui->forumMessage->textCursor().insertFragment(fragment); } } } @@ -576,194 +568,65 @@ void CreateGxsForumMsg::fileHashingFinished(QList hashedFiles) } if (!mesgString.isEmpty()) { - ui.forumMessage->textCursor().insertHtml(mesgString); + ui->forumMessage->textCursor().insertHtml(mesgString); } - ui.forumMessage->setFocus( Qt::OtherFocusReason ); - ui.hashGroupBox->hide(); + ui->forumMessage->setFocus( Qt::OtherFocusReason ); + ui->hashGroupBox->hide(); } -void CreateGxsForumMsg::loadForumInfo(const uint32_t &token) -{ - //std::cerr << "CreateGxsForumMsg::loadForumInfo()"; - //std::cerr << std::endl; - - std::list groupInfo; - rsGxsForums->getGroupSummary(token, groupInfo); - - if (groupInfo.size() == 1) - { - RsGroupMetaData fi = groupInfo.front(); - - mForumMeta = fi; - mForumMetaLoaded = true; - - if(!fi.mCircleId.isNull()) - { - //std::cerr << "Circle ID is not null: " << fi.mCircleId << ": loading circle info to add constraint to the GXS ID chooser." << std::endl; - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - std::list groupIds; - groupIds.push_back(RsGxsGroupId(fi.mCircleId)); - uint32_t _token; - - mCirclesQueue->requestGroupInfo(_token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds, CREATEGXSFORUMMSG_CIRCLENFO); - } - - loadFormInformation(); - } - else - { - std::cerr << "CreateGxsForumMsg::loadForumInfo() ERROR INVALID Number of Forums"; - std::cerr << std::endl; - - mStateHelper->setActive(CREATEGXSFORUMMSG_FORUMINFO, false); - mStateHelper->setLoading(CREATEGXSFORUMMSG_FORUMINFO, false); - } -} -void CreateGxsForumMsg::loadForumCircleInfo(const uint32_t& token) +void CreateGxsForumMsg::loadCircleInfo(const RsGxsGroupId& circle_id) { //std::cerr << "Loading forum circle info" << std::endl; - std::vector circle_grp_v ; - rsGxsCircles->getGroupData(token, circle_grp_v); - - if (circle_grp_v.empty()) + RsThread::async( [circle_id,this]() { - std::cerr << "(EE) unexpected empty result from getGroupData. Cannot process circle now!" << std::endl; - return ; - } - - if (circle_grp_v.size() != 1) - { - std::cerr << "(EE) very weird result from getGroupData. Should get exactly one circle" << std::endl; - return ; - } - - RsGxsCircleGroup cg = circle_grp_v.front(); + std::vector circle_grp_v ; + rsGxsCircles->getCirclesInfo(std::list{ circle_id }, circle_grp_v); - mForumCircleData = cg; - mForumCircleLoaded = true; - - //std::cerr << "Loaded content of circle " << cg.mMeta.mGroupId << std::endl; - - //for(std::set::const_iterator it(cg.mInvitedMembers.begin());it!=cg.mInvitedMembers.end();++it) - // std::cerr << " added constraint to circle element " << *it << std::endl; - - ui.idChooser->setIdConstraintSet(cg.mInvitedMembers) ; - ui.idChooser->setFlags(IDCHOOSER_NO_CREATE | ui.idChooser->flags()) ; // since there's a circle involved, no ID creation can be needed - - RsGxsId tmpid ; - if(ui.idChooser->countEnabledEntries() == 0) - { - QMessageBox::information(NULL,tr("No compatible ID for this forum"),tr("None of your identities is allowed to post in this forum. This could be due to the forum being limited to a circle that contains none of your identities, or forum flags requiring a PGP-signed identity.")) ; - close() ; - } -} - -void CreateGxsForumMsg::loadOrigMsg(const uint32_t &token) -{ - //std::cerr << "CreateGxsForumMsg::loadParentMsg()"; - //std::cerr << std::endl; - - // Only grab one.... ignore more (shouldn't be any). - std::vector msgs; - if (rsGxsForums->getMsgData(token, msgs)) - { - if (msgs.size() != 1) - { - /* error */ - std::cerr << "CreateGxsForumMsg::loadOrigMsg() ERROR wrong number of msgs"; - std::cerr << std::endl; - - mStateHelper->setActive(CREATEGXSFORUMMSG_ORIGMSG, false); - mStateHelper->setLoading(CREATEGXSFORUMMSG_ORIGMSG, false); - - return; - } - - mOrigMsg = msgs[0]; - mOrigMsgLoaded = true; - - loadFormInformation(); - } -} - - -void CreateGxsForumMsg::loadParentMsg(const uint32_t &token) -{ - //std::cerr << "CreateGxsForumMsg::loadParentMsg()"; - //std::cerr << std::endl; - - // Only grab one.... ignore more (shouldn't be any). - std::vector msgs; - if (rsGxsForums->getMsgData(token, msgs)) - { - if (msgs.size() != 1) - { - /* error */ - std::cerr << "CreateGxsForumMsg::loadParentMsg() ERROR wrong number of msgs"; - std::cerr << std::endl; - - mStateHelper->setActive(CREATEGXSFORUMMSG_PARENTMSG, false); - mStateHelper->setLoading(CREATEGXSFORUMMSG_PARENTMSG, false); - - return; - } - - mParentMsg = msgs[0]; - mParentMsgLoaded = true; - - loadFormInformation(); - } -} - -void CreateGxsForumMsg::loadRequest(const TokenQueue *queue, const TokenRequest &req) -{ - //std::cerr << "CreateGxsForum::loadRequest() UserType: " << req.mUserType; - //std::cerr << std::endl; - - if (queue == mForumQueue) - { - /* now switch on req */ - switch(req.mUserType) - { - case CREATEGXSFORUMMSG_FORUMINFO: - loadForumInfo(req.mToken); - break; - case CREATEGXSFORUMMSG_ORIGMSG: - loadOrigMsg(req.mToken); - break; - case CREATEGXSFORUMMSG_PARENTMSG: - loadParentMsg(req.mToken); - break; - default: - std::cerr << "CreateGxsForumMsg::loadRequest() UNKNOWN UserType " << req.mUserType << " for token request in mForumQueue"; - std::cerr << std::endl; - } - } - - if(queue == mCirclesQueue) + if (circle_grp_v.empty()) { - switch(req.mUserType) - { - case CREATEGXSFORUMMSG_CIRCLENFO: - loadForumCircleInfo(req.mToken) ; - break ; - default: - std::cerr << "CreateGxsForumMsg::loadRequest() UNKNOWN UserType " << req.mUserType << " for token request in mCirclesQueue"; - std::cerr << std::endl; - } + std::cerr << "(EE) unexpected empty result from getGroupData. Cannot process circle now!" << std::endl; + return ; } + + if (circle_grp_v.size() != 1) + { + std::cerr << "(EE) very weird result from getGroupData. Should get exactly one circle" << std::endl; + return ; + } + + RsGxsCircleGroup cg = circle_grp_v.front(); + + RsQThreadUtils::postToObject( [cg,this]() + { + mForumCircleData = cg; + mForumCircleLoaded = true; + + //std::cerr << "Loaded content of circle " << cg.mMeta.mGroupId << std::endl; + + //for(std::set::const_iterator it(cg.mInvitedMembers.begin());it!=cg.mInvitedMembers.end();++it) + // std::cerr << " added constraint to circle element " << *it << std::endl; + + ui->idChooser->setIdConstraintSet(cg.mInvitedMembers) ; + ui->idChooser->setFlags(IDCHOOSER_NO_CREATE | ui->idChooser->flags()) ; // since there's a circle involved, no ID creation can be needed + + RsGxsId tmpid ; + if(ui->idChooser->countEnabledEntries() == 0) + { + QMessageBox::information(NULL,tr("No compatible ID for this forum"),tr("None of your identities is allowed to post in this forum. This could be due to the forum being limited to a circle that contains none of your identities, or forum flags requiring a PGP-signed identity.")) ; + close() ; + } + }, this); + }); } + void CreateGxsForumMsg::setSubject(const QString& msg) { - ui.forumSubject->setText(msg); + ui->forumSubject->setText(msg); } void CreateGxsForumMsg::insertPastedText(const QString& msg) { - ui.forumMessage->append(msg); + ui->forumMessage->append(msg); } diff --git a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.h b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.h index 0bb2b22b2..8697fbbc3 100644 --- a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.h +++ b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.h @@ -21,16 +21,19 @@ #ifndef _CREATE_GXSFORUM_MSG_DIALOG_H #define _CREATE_GXSFORUM_MSG_DIALOG_H -#include "ui_CreateGxsForumMsg.h" - -#include "util/TokenQueue.h" +#include #include #include +#include "gui/common/HashBox.h" + +namespace Ui { + class CreateGxsForumMsg; +} class UIStateHelper; -class CreateGxsForumMsg : public QDialog, public TokenResponse +class CreateGxsForumMsg : public QDialog { Q_OBJECT @@ -39,7 +42,6 @@ public: ~CreateGxsForumMsg(); void newMsg(); /* cleanup */ - virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); void insertPastedText(const QString& msg) ; void setSubject(const QString& msg); @@ -58,15 +60,11 @@ private slots: protected: void closeEvent (QCloseEvent * event); + void loadCircleInfo(const RsGxsGroupId& circle_id); private: void processSettings(bool load); void loadFormInformation(); - void loadForumInfo(const uint32_t &token); - void loadParentMsg(const uint32_t &token); - void loadOrigMsg(const uint32_t &token); - void loadForumCircleInfo(const uint32_t &token); - RsGxsGroupId mForumId; RsGxsCircleId mCircleId ; RsGxsMessageId mParentId; @@ -84,13 +82,10 @@ private: RsGroupMetaData mForumMeta; RsGxsCircleGroup mForumCircleData ; - TokenQueue *mForumQueue; - TokenQueue *mCirclesQueue; - UIStateHelper *mStateHelper; /** Qt Designer generated object */ - Ui::CreateGxsForumMsg ui; + Ui::CreateGxsForumMsg *ui; }; #endif diff --git a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.ui b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.ui index 7af77f2d5..bae7223e3 100644 --- a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.ui +++ b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.ui @@ -7,7 +7,7 @@ 0 0 640 - 465 + 551
    @@ -17,7 +17,7 @@ :/images/logo/logo_16.png:/images/logo/logo_16.png - + 0 @@ -34,20 +34,27 @@ 0
    - - - - + QFrame::StyledPanel QFrame::Raised - + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + - + 0 @@ -68,7 +75,7 @@ QFrame::Raised - + 0 @@ -82,7 +89,7 @@ 0 - + 50 @@ -119,9 +126,9 @@ Forum Post - + - + @@ -132,17 +139,12 @@ - - - MS Sans Serif - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:''; font-size:; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> @@ -155,12 +157,12 @@ p, li { white-space: pre-wrap; } - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + 0 @@ -249,7 +251,7 @@ p, li { white-space: pre-wrap; } - + Qt::Horizontal @@ -298,7 +300,7 @@ p, li { white-space: pre-wrap; } Attach files via drag and drop - + @@ -322,7 +324,7 @@ p, li { white-space: pre-wrap; } - + @@ -341,7 +343,7 @@ p, li { white-space: pre-wrap; } - + Qt::Horizontal @@ -355,6 +357,13 @@ p, li { white-space: pre-wrap; } + + + 12 + 75 + true + + Post @@ -375,12 +384,6 @@ p, li { white-space: pre-wrap; } - - HashBox - QScrollArea -
    gui/common/HashBox.h
    - 1 -
    MimeTextEdit QTextEdit @@ -397,11 +400,16 @@ p, li { white-space: pre-wrap; }
    gui/common/HeaderFrame.h
    1
    + + HashBox + QScrollArea +
    gui/common/HashBox.h
    + 1 +
    - - + diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumGroupDialog.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumGroupDialog.cpp index 424091867..16d0c307b 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumGroupDialog.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumGroupDialog.cpp @@ -63,7 +63,7 @@ GxsForumGroupDialog::GxsForumGroupDialog(QWidget *parent) : GxsGroupDialog(ForumCreateEnabledFlags, ForumCreateDefaultsFlags, parent) { ui.pubKeyShare_cb->setEnabled(true) ; - ui.label_2->setToolTip(tr("

    Put one of your identities here to allow others to send feedback and also have moderator rights on the forum. You may as well leave that field blank and keep the forum anonymously administrated.

    ")); + ui.idChooserLabel->setToolTip(tr("

    Put one of your identities here to allow others to send feedback and also have moderator rights on the forum. You may as well leave that field blank and keep the forum anonymously administrated.

    ")); } GxsForumGroupDialog::GxsForumGroupDialog(Mode mode, RsGxsGroupId groupId, QWidget *parent) @@ -151,6 +151,7 @@ bool GxsForumGroupDialog::service_loadGroup(const RsGxsGenericGroupData *data, M // Local information. Description should be handled here. setSelectedModerators(pgroup->mAdminList.ids); + ui.adminsList->sortByChecked(true); mGroupData = *pgroup; // keeps the private information diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumModel.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumModel.cpp index 3d168acf7..18f518749 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumModel.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumModel.cpp @@ -46,6 +46,7 @@ RsGxsForumModel::RsGxsForumModel(QObject *parent) : QAbstractItemModel(parent), mUseChildTS(false),mFilteringEnabled(false),mTreeMode(TREE_MODE_TREE) { initEmptyHierarchy(mPosts); + mFont = QApplication::font(); } void RsGxsForumModel::preMods() @@ -117,14 +118,14 @@ int RsGxsForumModel::columnCount(const QModelIndex &/*parent*/) const return COLUMN_THREAD_NB_COLUMNS ; } -std::vector > RsGxsForumModel::getPostVersions(const RsGxsMessageId& mid) const +std::vector > RsGxsForumModel::getPostVersions(const RsGxsMessageId& mid) const { auto it = mPostVersions.find(mid); if(it != mPostVersions.end()) return it->second; else - return std::vector >(); + return std::vector >(); } bool RsGxsForumModel::getPostData(const QModelIndex& i,ForumModelPostEntry& fmpe) const @@ -399,7 +400,7 @@ QVariant RsGxsForumModel::data(const QModelIndex &index, int role) const if(role == Qt::FontRole) { - QFont font ; + QFont font = mFont; font.setBold( (fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_HAS_UNREAD_CHILDREN) || IS_MSG_UNREAD(fmpe.mMsgStatus)); return QVariant(font); } @@ -533,6 +534,15 @@ void RsGxsForumModel::setFilter(int column,const QStringList& strings,uint32_t& postMods(); } +void RsGxsForumModel::setFont(const QFont &font) +{ + preMods(); + + mFont = font; + + postMods(); +} + QVariant RsGxsForumModel::missingRole(const ForumModelPostEntry& fmpe,int /*column*/) const { if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_MISSING) @@ -562,12 +572,15 @@ QVariant RsGxsForumModel::toolTipRole(const ForumModelPostEntry& fmpe,int column if(!GxsIdDetails::MakeIdDesc(fmpe.mAuthorId, true, str, icons, comment,GxsIdDetails::ICON_TYPE_AVATAR)) return QVariant(); - int S = QFontMetricsF(QApplication::font()).height(); - QImage pix( (*icons.begin()).pixmap(QSize(4*S,4*S)).toImage()); + int S = QFontMetricsF(mFont).height(); + QImage pix( (*icons.begin()).pixmap(QSize(5*S,5*S)).toImage()); QString embeddedImage; - if(RsHtml::makeEmbeddedImage(pix.scaled(QSize(4*S,4*S), Qt::KeepAspectRatio, Qt::SmoothTransformation), embeddedImage, 8*S * 8*S)) + if(RsHtml::makeEmbeddedImage(pix.scaled(QSize(5*S,5*S), Qt::KeepAspectRatio, Qt::SmoothTransformation), embeddedImage, -1)) + { + embeddedImage.insert(embeddedImage.indexOf("src="), "style=\"float:left\" "); comment = "
    " + embeddedImage + "" + comment + "
    "; + } return comment; } @@ -596,7 +609,7 @@ QVariant RsGxsForumModel::backgroundRole(const ForumModelPostEntry& fmpe,int /*c QVariant RsGxsForumModel::sizeHintRole(int col) const { - float factor = QFontMetricsF(QApplication::font()).height()/14.0f ; + float factor = QFontMetricsF(mFont).height()/14.0f ; switch(col) { @@ -647,7 +660,7 @@ QVariant RsGxsForumModel::displayRole(const ForumModelPostEntry& fmpe,int col) c case COLUMN_THREAD_TITLE: if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_REDACTED) return QVariant(tr("[ ... Redacted message ... ]")); // else if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_PINNED) -// return QVariant( QString("").arg(QFontMetricsF(QFont()).height()) +// return QVariant( QString("").arg(QFontMetricsF(mFont).height()) // + QString::fromUtf8(fmpe.mTitle.c_str())); else return QVariant(QString::fromUtf8(fmpe.mTitle.c_str())); @@ -743,7 +756,7 @@ void RsGxsForumModel::clear() emit forumLoaded(); } -void RsGxsForumModel::setPosts(const RsGxsForumGroup& group, const std::vector& posts,const std::map > >& post_versions) +void RsGxsForumModel::setPosts(const RsGxsForumGroup& group, const std::vector& posts,const std::map > >& post_versions) { preMods(); @@ -797,7 +810,6 @@ void RsGxsForumModel::update_posts(const RsGxsGroupId& group_id) // 1 - get message data from p3GxsForums std::list forumIds; - std::vector msg_metas; std::vector groups; forumIds.push_back(group_id); @@ -808,21 +820,19 @@ void RsGxsForumModel::update_posts(const RsGxsGroupId& group_id) return; } - if(!rsGxsForums->getForumMsgMetaData(group_id,msg_metas)) - { - std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve forum message info for forum " << group_id << std::endl; - return; - } + // 2 - sort messages into a proper hierarchy - // 2 - sort the messages into a proper hierarchy - - auto post_versions = new std::map > >() ; - std::vector *vect = new std::vector(); + auto post_versions = new std::map > >() ; + std::vector *vect = new std::vector(); RsGxsForumGroup group = groups[0]; - computeMessagesHierarchy(group,msg_metas,*vect,*post_versions); + if(!rsGxsForums->getForumPostsHierarchy(group,*vect,*post_versions)) + { + std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve forum hierarchy of message info for forum " << group_id << std::endl; + return; + } - // 3 - update the model in the UI thread. + // 3 - update the model in the UI thread. RsQThreadUtils::postToObject( [group,vect,post_versions,this]() { @@ -832,10 +842,14 @@ void RsGxsForumModel::update_posts(const RsGxsGroupId& group_id) * Qt::QueuedConnection is important! */ - setPosts(group,*vect,*post_versions) ; + std::vector psts; + for(const auto& p:*vect) + psts.push_back( ForumModelPostEntry(p)); - delete vect; - delete post_versions; + setPosts(group,psts,*post_versions) ; + + delete vect; + delete post_versions; }, this ); @@ -843,379 +857,7 @@ void RsGxsForumModel::update_posts(const RsGxsGroupId& group_id) }); } -ForumModelIndex RsGxsForumModel::addEntry(std::vector& posts,const ForumModelPostEntry& entry,ForumModelIndex parent) -{ - uint32_t N = posts.size(); - posts.push_back(entry); - posts[N].mParent = parent; - posts[parent].mChildren.push_back(N); -#ifdef DEBUG_FORUMMODEL - std::cerr << "Added new entry " << N << " children of " << parent << std::endl; -#endif - if(N == parent) - std::cerr << "(EE) trying to add a post as its own parent!" << std::endl; - return ForumModelIndex(N); -} - -void RsGxsForumModel::generateMissingItem(const RsGxsMessageId &msgId,ForumModelPostEntry& entry) -{ - entry.mPostFlags = ForumModelPostEntry::FLAG_POST_IS_MISSING ; - entry.mTitle = std::string(tr("[ ... Missing Message ... ]").toUtf8()); - entry.mMsgId = msgId; - entry.mAuthorId.clear(); - entry.mPublishTs=0; - entry.mReputationWarningLevel = 3; -} - -void RsGxsForumModel::convertMsgToPostEntry(const RsGxsForumGroup& mForumGroup,const RsMsgMetaData& msg, bool /*useChildTS*/, ForumModelPostEntry& fentry) -{ - fentry.mTitle = msg.mMsgName; - fentry.mAuthorId = msg.mAuthorId; - fentry.mMsgId = msg.mMsgId; - fentry.mPublishTs = msg.mPublishTs; - fentry.mPostFlags = 0; - fentry.mMsgStatus = msg.mMsgStatus; - - if(mForumGroup.mPinnedPosts.ids.find(msg.mMsgId) != mForumGroup.mPinnedPosts.ids.end()) - fentry.mPostFlags |= ForumModelPostEntry::FLAG_POST_IS_PINNED; - - // Early check for a message that should be hidden because its author - // is flagged with a bad reputation - - computeReputationLevel(mForumGroup.mMeta.mSignFlags,fentry); -} - -void RsGxsForumModel::computeReputationLevel(uint32_t forum_sign_flags,ForumModelPostEntry& fentry) -{ - uint32_t idflags =0; - RsReputationLevel reputation_level = - rsReputations->overallReputationLevel(fentry.mAuthorId, &idflags); - - if(reputation_level == RsReputationLevel::LOCALLY_NEGATIVE) - fentry.mPostFlags |= ForumModelPostEntry::FLAG_POST_IS_REDACTED; - else - fentry.mPostFlags &= ~ForumModelPostEntry::FLAG_POST_IS_REDACTED; - - // We use a specific item model for forums in order to handle the post pinning. - - if(reputation_level == RsReputationLevel::UNKNOWN) - fentry.mReputationWarningLevel = 3 ; - else if(reputation_level == RsReputationLevel::LOCALLY_NEGATIVE) - fentry.mReputationWarningLevel = 2 ; - else if(reputation_level < rsGxsForums->minReputationForForwardingMessages(forum_sign_flags,idflags)) - fentry.mReputationWarningLevel = 1 ; - else - fentry.mReputationWarningLevel = 0 ; -} - -static bool decreasing_time_comp(const std::pair& e1,const std::pair& e2) { return e2.first < e1.first ; } - -void RsGxsForumModel::computeMessagesHierarchy(const RsGxsForumGroup& forum_group, - const std::vector& msgs_metas_array, - std::vector& posts, - std::map > >& mPostVersions - ) -{ - std::cerr << "updating messages data with " << msgs_metas_array.size() << " messages" << std::endl; - -#ifdef DEBUG_FORUMS - std::cerr << "Retrieved group data: " << std::endl; - std::cerr << " Group ID: " << forum_group.mMeta.mGroupId << std::endl; - std::cerr << " Admin lst: " << forum_group.mAdminList.ids.size() << " elements." << std::endl; - for(auto it(forum_group.mAdminList.ids.begin());it!=forum_group.mAdminList.ids.end();++it) - std::cerr << " " << *it << std::endl; - std::cerr << " Pinned Post: " << forum_group.mPinnedPosts.ids.size() << " messages." << std::endl; - for(auto it(forum_group.mPinnedPosts.ids.begin());it!=forum_group.mPinnedPosts.ids.end();++it) - std::cerr << " " << *it << std::endl; -#endif - - /* get messages */ - std::map msgs; - - for(uint32_t i=0;i > threadStack; - std::map > kids_array ; - std::set missing_parents; - - // First of all, remove all older versions of posts. This is done by first adding all posts into a hierarchy structure - // and then removing all posts which have a new versions available. The older versions are kept appart. - -#ifdef DEBUG_FORUMS - std::cerr << "GxsForumsFillThread::run() Collecting post versions" << std::endl; -#endif - mPostVersions.clear(); - - for ( auto msgIt = msgs.begin(); msgIt != msgs.end();++msgIt) - { - if(!msgIt->second.mOrigMsgId.isNull() && msgIt->second.mOrigMsgId != msgIt->second.mMsgId) - { -#ifdef DEBUG_FORUMS - std::cerr << " Post " << msgIt->second.mMeta.mMsgId << " is a new version of " << msgIt->second.mMeta.mOrigMsgId << std::endl; -#endif - auto msgIt2 = msgs.find(msgIt->second.mOrigMsgId); - - // Ensuring that the post exists allows to only collect the existing data. - - if(msgIt2 == msgs.end()) - continue ; - - // Make sure that the author is the same than the original message, or is a moderator. This should always happen when messages are constructed using - // the UI but nothing can prevent a nasty user to craft a new version of a message with his own signature. - - if(msgIt2->second.mAuthorId != msgIt->second.mAuthorId) - { - if( !IS_FORUM_MSG_MODERATION(msgIt->second.mMsgFlags) ) // if authors are different the moderation flag needs to be set on the editing msg - continue ; - - if( !forum_group.canEditPosts(msgIt->second.mAuthorId)) // if author is not a moderator, continue - continue ; - } - - // always add the post a self version - - if(mPostVersions[msgIt->second.mOrigMsgId].empty()) - mPostVersions[msgIt->second.mOrigMsgId].push_back(std::make_pair(msgIt2->second.mPublishTs,msgIt2->second.mMsgId)) ; - - mPostVersions[msgIt->second.mOrigMsgId].push_back(std::make_pair(msgIt->second.mPublishTs,msgIt->second.mMsgId)) ; - } - } - - // The following code assembles all new versions of a given post into the same array, indexed by the oldest version of the post. - - for(auto it(mPostVersions.begin());it!=mPostVersions.end();++it) - { - auto& v(it->second) ; - - for(size_t i=0;ifirst) - { - RsGxsMessageId sub_msg_id = v[i].second ; - - auto it2 = mPostVersions.find(sub_msg_id); - - if(it2 != mPostVersions.end()) - { - for(size_t j=0;jsecond.size();++j) - if(it2->second[j].second != sub_msg_id) // dont copy it, since it is already present at slot i - v.push_back(it2->second[j]) ; - - mPostVersions.erase(it2) ; // it2 is never equal to it - } - } - } - } - - - // Now remove from msg ids, all posts except the most recent one. And make the mPostVersion be indexed by the most recent version of the post, - // which corresponds to the item in the tree widget. - -#ifdef DEBUG_FORUMS - std::cerr << "Final post versions: " << std::endl; -#endif - std::map > > mTmp; - std::map most_recent_versions ; - - for(auto it(mPostVersions.begin());it!=mPostVersions.end();++it) - { -#ifdef DEBUG_FORUMS - std::cerr << "Original post: " << it.key() << std::endl; -#endif - // Finally, sort the posts from newer to older - - std::sort(it->second.begin(),it->second.end(),decreasing_time_comp) ; - -#ifdef DEBUG_FORUMS - std::cerr << " most recent version " << (*it)[0].first << " " << (*it)[0].second << std::endl; -#endif - for(size_t i=1;isecond.size();++i) - { - msgs.erase(it->second[i].second) ; - -#ifdef DEBUG_FORUMS - std::cerr << " older version " << (*it)[i].first << " " << (*it)[i].second << std::endl; -#endif - } - - mTmp[it->second[0].second] = it->second ; // index the versions map by the ID of the most recent post. - - // Now make sure that message parents are consistent. Indeed, an old post may have the old version of a post as parent. So we need to change that parent - // to the newest version. So we create a map of which is the most recent version of each message, so that parent messages can be searched in it. - - for(size_t i=1;isecond.size();++i) - most_recent_versions[it->second[i].second] = it->second[0].second ; - } - mPostVersions = mTmp ; - - // The next step is to find the top level thread messages. These are defined as the messages without - // any parent message ID. - - // this trick is needed because while we remove messages, the parents a given msg may already have been removed - // and wrongly understand as a missing parent. - - std::map kept_msgs; - - for ( auto msgIt = msgs.begin(); msgIt != msgs.end();++msgIt) - { - - if(msgIt->second.mParentId.isNull()) - { - - /* add all threads */ - const RsMsgMetaData& msg = msgIt->second; - -#ifdef DEBUG_FORUMS - std::cerr << "GxsForumsFillThread::run() Adding TopLevel Thread: mId: " << msg.mMsgId << std::endl; -#endif - - ForumModelPostEntry entry; - convertMsgToPostEntry(forum_group,msg, mUseChildTS, entry); - - ForumModelIndex entry_index = addEntry(posts,entry,0); - - //if (!mFlatView) - threadStack.push_back(std::make_pair(msg.mMsgId,entry_index)) ; - - //calculateExpand(msg, item); - //mItems.append(entry_index); - } - else - { -#ifdef DEBUG_FORUMS - std::cerr << "GxsForumsFillThread::run() Storing kid " << msgIt->first << " of message " << msgIt->second.mParentId << std::endl; -#endif - // The same missing parent may appear multiple times, so we first store them into a unique container. - - RsGxsMessageId parent_msg = msgIt->second.mParentId; - - if(msgs.find(parent_msg) == msgs.end()) - { - // also check that the message is not versionned - - std::map::const_iterator mrit = most_recent_versions.find(parent_msg) ; - - if(mrit != most_recent_versions.end()) - parent_msg = mrit->second ; - else - missing_parents.insert(parent_msg); - } - - kids_array[parent_msg].push_back(msgIt->first) ; - kept_msgs.insert(*msgIt) ; - } - } - - msgs = kept_msgs; - - // Also create a list of posts by time, when they are new versions of existing posts. Only the last one will have an item created. - - // Add a fake toplevel item for the parent IDs that we dont actually have. - - for(std::set::const_iterator it(missing_parents.begin());it!=missing_parents.end();++it) - { - // add dummy parent item - ForumModelPostEntry e ; - generateMissingItem(*it,e); - - ForumModelIndex e_index = addEntry(posts,e,0); // no parent -> parent is level 0 - //mItems.append( e_index ); - - threadStack.push_back(std::make_pair(*it,e_index)) ; - } -#ifdef DEBUG_FORUMS - std::cerr << "GxsForumsFillThread::run() Processing stack:" << std::endl; -#endif - // Now use a stack to go down the hierarchy - - while (!threadStack.empty()) - { - std::pair threadPair = threadStack.front(); - threadStack.pop_front(); - - std::map >::iterator it = kids_array.find(threadPair.first) ; - -#ifdef DEBUG_FORUMS - std::cerr << "GxsForumsFillThread::run() Node: " << threadPair.first << std::endl; -#endif - if(it == kids_array.end()) - continue ; - - - for(std::list::const_iterator it2(it->second.begin());it2!=it->second.end();++it2) - { - // We iterate through the top level thread items, and look for which message has the current item as parent. - // When found, the item is put in the thread list itself, as a potential new parent. - - auto mit = msgs.find(*it2) ; - - if(mit == msgs.end()) - { - std::cerr << "GxsForumsFillThread::run() Cannot find submessage " << *it2 << " !!!" << std::endl; - continue ; - } - - const RsMsgMetaData& msg(mit->second) ; -#ifdef DEBUG_FORUMS - std::cerr << "GxsForumsFillThread::run() adding sub_item " << msg.mMsgId << std::endl; -#endif - - - ForumModelPostEntry e ; - convertMsgToPostEntry(forum_group,msg,mUseChildTS,e) ; - ForumModelIndex e_index = addEntry(posts,e, threadPair.second); - - //calculateExpand(msg, item); - - /* add item to process list */ - threadStack.push_back(std::make_pair(msg.mMsgId, e_index)); - - msgs.erase(mit); - } - -#ifdef DEBUG_FORUMS - std::cerr << "GxsForumsFillThread::run() Erasing entry " << it->first << " from kids tab." << std::endl; -#endif - kids_array.erase(it) ; // This is not strictly needed, but it improves performance by reducing the search space. - } - -#ifdef DEBUG_FORUMS - std::cerr << "Kids array now has " << kids_array.size() << " elements" << std::endl; - for(std::map >::const_iterator it(kids_array.begin());it!=kids_array.end();++it) - { - std::cerr << "Node " << it->first << std::endl; - for(std::list::const_iterator it2(it->second.begin());it2!=it->second.end();++it2) - std::cerr << " " << *it2 << std::endl; - } - - std::cerr << "GxsForumsFillThread::run() stopped: " << (wasStopped() ? "yes" : "no") << std::endl; -#endif -} void RsGxsForumModel::setMsgReadStatus(const QModelIndex& i,bool read_status,bool with_children) { @@ -1245,8 +887,8 @@ void RsGxsForumModel::setMsgReadStatus(const QModelIndex& i,bool read_status,boo void RsGxsForumModel::recursSetMsgReadStatus(ForumModelIndex i,bool read_status,bool with_children) { - int newStatus = (read_status ? mPosts[i].mMsgStatus & ~static_cast(GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD) - : mPosts[i].mMsgStatus | static_cast(GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD)); + uint32_t newStatus = (read_status ? mPosts[i].mMsgStatus & ~static_cast(GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD) + : mPosts[i].mMsgStatus | static_cast(GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD)); bool bChanged = (mPosts[i].mMsgStatus != newStatus); mPosts[i].mMsgStatus = newStatus; //Remove Unprocessed and New flags @@ -1275,8 +917,8 @@ void RsGxsForumModel::recursSetMsgReadStatus(ForumModelIndex i,bool read_status, void *ref ; convertTabEntryToRefPointer(i,ref); // we dont use i+1 here because i is not a row, but an index in the mPosts tab - QModelIndex itemIndex = createIndex(i - 1, 0, ref); - emit dataChanged(itemIndex, itemIndex); + QModelIndex itemIndex = (mTreeMode == TREE_MODE_FLAT)?createIndex(i - 1, 0, ref):createIndex(mPosts[i].prow,0,ref); + emit dataChanged(itemIndex, itemIndex); } if(!with_children) @@ -1417,7 +1059,7 @@ void RsGxsForumModel::setAuthorOpinion(const QModelIndex& indx, RsOpinion op) for(uint32_t i=0;iupdateReputationLevel(mForumGroup.mMeta.mSignFlags,mPosts[i]); // notify the widgets that the data has changed. emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(0,COLUMN_THREAD_NB_COLUMNS-1,(void*)NULL)); diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumModel.h b/retroshare-gui/src/gui/gxsforums/GxsForumModel.h index 50de234fa..10248101f 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumModel.h +++ b/retroshare-gui/src/gui/gxsforums/GxsForumModel.h @@ -22,45 +22,21 @@ #include "retroshare/rsgxsifacetypes.h" #include #include +#include -// This class holds the actual hierarchy of posts, represented by identifiers -// It is responsible for auto-updating when necessary and holds a mutex to allow the Model to -// safely access the data. - -// The model contains a post in place 0 that is the parent of all posts. - -typedef uint32_t ForumModelIndex; - -struct ForumModelPostEntry +struct ForumModelPostEntry: public ForumPostEntry { - ForumModelPostEntry() : mPublishTs(0),mMostRecentTsInThread(0),mPostFlags(0),mReputationWarningLevel(0),mMsgStatus(0),prow(0) {} + ForumModelPostEntry() : mMostRecentTsInThread(0),prow(0) {} + ForumModelPostEntry(const ForumPostEntry& p) : mMostRecentTsInThread(0),prow(0) { *static_cast(this) = p; } - enum { // flags for display of posts. To be used in mPostFlags - FLAG_POST_IS_PINNED = 0x0001, - FLAG_POST_IS_MISSING = 0x0002, - FLAG_POST_IS_REDACTED = 0x0004, - FLAG_POST_HAS_UNREAD_CHILDREN = 0x0008, - FLAG_POST_HAS_READ_CHILDREN = 0x0010, - FLAG_POST_PASSES_FILTER = 0x0020, - FLAG_POST_CHILDREN_PASSES_FILTER = 0x0040, - }; - - std::string mTitle ; - RsGxsId mAuthorId ; - RsGxsMessageId mMsgId; - uint32_t mPublishTs; - uint32_t mMostRecentTsInThread; - uint32_t mPostFlags; - int mReputationWarningLevel; - int mMsgStatus; - - std::vector mChildren; - ForumModelIndex mParent; - int prow ; // parent row + uint32_t mMostRecentTsInThread; + int prow ; // parent row. Used by Qt abstract item models. }; // This class is the item model used by Qt to display the information +typedef uint32_t ForumModelIndex; + class RsGxsForumModel : public QAbstractItemModel { Q_OBJECT @@ -101,8 +77,9 @@ public: QModelIndex getIndexOfMessage(const RsGxsMessageId& mid) const; static const QString FilterString ; + void setFont(const QFont &font); - std::vector > getPostVersions(const RsGxsMessageId& mid) const; + std::vector > getPostVersions(const RsGxsMessageId& mid) const; // This method will asynchroneously update the data void updateForum(const RsGxsGroupId& forumGroup); @@ -195,11 +172,11 @@ private: static void convertMsgToPostEntry(const RsGxsForumGroup &mForumGroup, const RsMsgMetaData &msg, bool useChildTS, ForumModelPostEntry& fentry); void computeMessagesHierarchy(const RsGxsForumGroup& forum_group, const std::vector &msgs_array, std::vector& posts, std::map > > &mPostVersions); - void setPosts(const RsGxsForumGroup& group, const std::vector& posts,const std::map > >& post_versions); + void setPosts(const RsGxsForumGroup& group, const std::vector& posts,const std::map > >& post_versions); void initEmptyHierarchy(std::vector& posts); std::vector mPosts ; // store the list of posts updated from rsForums. - std::map > > mPostVersions; + std::map > > mPostVersions; QColor mTextColorRead ; QColor mTextColorUnread ; @@ -210,6 +187,7 @@ private: QColor mBackgroundColorPinned; QColor mBackgroundColorFiltered; + QFont mFont; friend class const_iterator; }; diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index fb962ca5c..6c87e8a04 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -276,7 +276,6 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget connect(ui->versions_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(changedVersion())); connect(ui->threadTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(threadListCustomPopupMenu(QPoint))); - connect(ui->postText, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuTextBrowser(QPoint))); connect(ui->forumName, SIGNAL(clicked(QPoint)), this, SLOT(showForumInfo())); ui->subscribeToolButton->hide() ; @@ -291,7 +290,6 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget connect(ui->threadTreeWidget, SIGNAL(clicked(QModelIndex)), this, SLOT(clickedThread(QModelIndex))); connect(ui->threadTreeWidget->selectionModel(), SIGNAL(currentChanged(const QModelIndex&,const QModelIndex&)), this, SLOT(changedSelection(const QModelIndex&,const QModelIndex&))); - connect(ui->viewBox, SIGNAL(currentIndexChanged(int)), this, SLOT(changedViewBox())); //connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(togglethreadview())); ui->expandButton->hide(); @@ -304,7 +302,9 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString))); connect(ui->filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterColumnChanged(int))); - connect(ui->actionSave_image, SIGNAL(triggered()), this, SLOT(saveImage())); + connect(ui->threadedView_TB, SIGNAL(toggled(bool)), this, SLOT(toggleThreadedView(bool))); + connect(ui->flatView_TB, SIGNAL(toggled(bool)), this, SLOT(toggleFlatView(bool))); + connect(ui->latestPostInThreadView_TB, SIGNAL(toggled(bool)), this, SLOT(toggleLstPostInThreadView(bool))); /* Set own item delegate */ RSElidedItemDelegate *itemDelegate = new RSElidedItemDelegate(this); @@ -376,6 +376,10 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget [this](std::shared_ptr event) { RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); }, mEventHandlerId, RsEventType::GXS_FORUMS ); + + mFontSizeHandler.registerFontSize(ui->threadTreeWidget, 1.4f, [this](QAbstractItemView *view, int) { + mThreadModel->setFont(view->font()); + }); } void GxsForumThreadWidget::handleEvent_main_thread(std::shared_ptr event) @@ -415,7 +419,9 @@ void GxsForumThreadWidget::blank() ui->forumName->setText(""); ui->progressText->hide(); ui->progressBar->hide(); - ui->viewBox->setEnabled(false); + ui->threadedView_TB->setEnabled(false); + ui->flatView_TB->setEnabled(false); + ui->latestPostInThreadView_TB->setEnabled(false); ui->filterLineEdit->setEnabled(false); mThreadModel->clear(); @@ -450,7 +456,13 @@ void GxsForumThreadWidget::processSettings(bool load) ui->filterLineEdit->setCurrentFilter(Settings->value("filterColumn", RsGxsForumModel::COLUMN_THREAD_TITLE).toInt()); // index of viewBox - ui->viewBox->setCurrentIndex(Settings->value("viewBox", VIEW_THREADED).toInt()); + switch(Settings->value("viewBox", VIEW_THREADED).toInt()) + { + default: + case VIEW_THREADED : ui->threadedView_TB->setChecked(true); break; + case VIEW_FLAT : ui->flatView_TB->setChecked(true); break; + case VIEW_LAST_POST: ui->latestPostInThreadView_TB->setChecked(true); break; + } // state of thread tree header->restoreState(Settings->value("ThreadTree").toByteArray()); @@ -778,25 +790,6 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/) contextMnu.exec(QCursor::pos()); } -void GxsForumThreadWidget::contextMenuTextBrowser(QPoint point) -{ - QMatrix matrix; - matrix.translate(ui->postText->horizontalScrollBar()->value(), ui->postText->verticalScrollBar()->value()); - - QMenu *contextMnu = ui->postText->createStandardContextMenu(matrix.map(point)); - - contextMnu->addSeparator(); - - if(ui->postText->checkImage(point)) - { - ui->actionSave_image->setData(point); - contextMnu->addAction(ui->actionSave_image); - } - - contextMnu->exec(ui->postText->viewport()->mapToGlobal(point)); - delete(contextMnu); -} - void GxsForumThreadWidget::headerContextMenuRequested(const QPoint &pos) { QMenu* header_context_menu = new QMenu(tr("Show column"), this); @@ -1044,7 +1037,9 @@ void GxsForumThreadWidget::updateForumDescription(bool success) ui->newthreadButton->show(); ui->forumName->setText(QString::fromUtf8(group.mMeta.mGroupName.c_str())); - ui->viewBox->setEnabled(true); + ui->flatView_TB->setEnabled(true); + ui->threadedView_TB->setEnabled(true); + ui->latestPostInThreadView_TB->setEnabled(true); ui->filterLineEdit->setEnabled(true); QString anti_spam_features1 ; @@ -1198,7 +1193,7 @@ void GxsForumThreadWidget::insertMessage() // add/show combobox for versions, if applicable, and enable it. If no older versions of the post available, hide the combobox. - std::vector > post_versions = mThreadModel->getPostVersions(mOrigThreadId); + std::vector > post_versions = mThreadModel->getPostVersions(mOrigThreadId); #ifdef DEBUG_FORUMS std::cerr << "Looking into existing versions for post " << mOrigThreadId << ", thread history: " << post_versions.size() << std::endl; @@ -1486,7 +1481,7 @@ void GxsForumThreadWidget::markMsgAsUnreadChildren() markMsgAsReadUnread(false, true, false); } -void GxsForumThreadWidget::setAllMessagesReadDo(bool read, uint32_t &/*token*/) +void GxsForumThreadWidget::setAllMessagesReadDo(bool read) { markMsgAsReadUnread(read, true, true); } @@ -1806,28 +1801,25 @@ void GxsForumThreadWidget::replyForumMessageData(const RsGxsForumMsg &msg) } } -void GxsForumThreadWidget::saveImage() -{ - QPoint point = ui->actionSave_image->data().toPoint(); - QTextCursor cursor = ui->postText->cursorForPosition(point); - ImageUtil::extractImage(window(), cursor); -} +void GxsForumThreadWidget::toggleThreadedView(bool b) { if(b) changedViewBox(VIEW_THREADED); } +void GxsForumThreadWidget::toggleFlatView(bool b) { if(b) changedViewBox(VIEW_FLAT); } +void GxsForumThreadWidget::toggleLstPostInThreadView(bool b) { if(b) changedViewBox(VIEW_LAST_POST); } -void GxsForumThreadWidget::changedViewBox() +void GxsForumThreadWidget::changedViewBox(int view_mode) { ui->threadTreeWidget->selectionModel()->clear(); ui->threadTreeWidget->selectionModel()->reset(); mThreadId.clear(); // save index - Settings->setValueToGroup("ForumThreadWidget", "viewBox", ui->viewBox->currentIndex()); + Settings->setValueToGroup("ForumThreadWidget", "viewBox", view_mode); - if(ui->viewBox->currentIndex() == VIEW_FLAT) + if(view_mode == VIEW_FLAT) mThreadModel->setTreeMode(RsGxsForumModel::TREE_MODE_FLAT); else mThreadModel->setTreeMode(RsGxsForumModel::TREE_MODE_TREE); - if(ui->viewBox->currentIndex() == VIEW_LAST_POST) + if(view_mode == VIEW_LAST_POST) mThreadModel->setSortMode(RsGxsForumModel::SORT_MODE_CHILDREN_PUBLISH_TS); else mThreadModel->setSortMode(RsGxsForumModel::SORT_MODE_PUBLISH_TS); @@ -1854,7 +1846,7 @@ void GxsForumThreadWidget::filterColumnChanged(int column) void GxsForumThreadWidget::filterItems(const QString& text) { - QStringList lst = text.split(" ",QString::SkipEmptyParts) ; + QStringList lst = text.split(" ",QtSkipEmptyParts) ; int filterColumn = ui->filterLineEdit->currentFilter(); @@ -1956,8 +1948,12 @@ void GxsForumThreadWidget::postForumLoading() ui->forumName->setText(QString::fromUtf8(mForumGroup.mMeta.mGroupName.c_str())); ui->threadTreeWidget->sortByColumn(RsGxsForumModel::COLUMN_THREAD_DATE, Qt::DescendingOrder); ui->threadTreeWidget->update(); - ui->viewBox->setEnabled(true); - ui->filterLineEdit->setEnabled(true); + ui->threadedView_TB->setEnabled(true); + ui->flatView_TB->setEnabled(true); + ui->flatView_TB->setEnabled(true); + ui->threadedView_TB->setEnabled(true); + ui->latestPostInThreadView_TB->setEnabled(true); + ui->filterLineEdit->setEnabled(true); recursRestoreExpandedItems(mThreadProxyModel->mapFromSource(mThreadModel->root()),mSavedExpandedMessages); //mUpdating = false; diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h index 6df3c5c89..8e6b1c01b 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h @@ -26,6 +26,7 @@ #include "gui/gxs/GxsMessageFrameWidget.h" #include #include "gui/gxs/GxsIdDetails.h" +#include "util/FontSizeHandler.h" class QSortFilterProxyModel; class QTreeWidgetItem; @@ -102,13 +103,12 @@ protected: virtual void updateDisplay(bool complete); /* GxsMessageFrameWidget */ - virtual void setAllMessagesReadDo(bool read, uint32_t &token); + virtual void setAllMessagesReadDo(bool read); void setMessageLoadingError(const QString& error); private slots: /** Create the context popup menu and it's submenus */ void threadListCustomPopupMenu(QPoint point); - void contextMenuTextBrowser(QPoint point); void headerContextMenuRequested(const QPoint& pos); void showForumInfo(); @@ -122,7 +122,11 @@ private slots: void replytoforummessage(); void editforummessage(); - void replyMessageData(const RsGxsForumMsg &msg); + void toggleThreadedView(bool); + void toggleFlatView(bool); + void toggleLstPostInThreadView(bool); + + void replyMessageData(const RsGxsForumMsg &msg); void editForumMessageData(const RsGxsForumMsg &msg); void replyForumMessageData(const RsGxsForumMsg &msg); void showAuthorInPeople(const RsGxsForumMsg& msg); @@ -130,8 +134,6 @@ private slots: // This method is used to perform an asynchroneous action on the message data. Any of the methods above can be used as parameter. void async_msg_action(const MsgMethod& method); - void saveImage(); - void markMsgAsRead(); void markMsgAsReadChildren(); void markMsgAsUnread(); @@ -153,7 +155,7 @@ private slots: void nextUnreadMessage(); void downloadAllFiles(); - void changedViewBox(); + void changedViewBox(int); void flagperson(); void filterColumnChanged(int column); @@ -214,7 +216,7 @@ private: unsigned int mNewCount; bool mDisplayBannedText; - /* Color definitions (for standard see qss.default) */ + /* Color definitions (for standard see default.qss) */ QColor mTextColorRead; QColor mTextColorUnread; QColor mTextColorUnreadChildren; @@ -233,6 +235,8 @@ private: QSortFilterProxyModel *mThreadProxyModel; QList mSavedExpandedMessages; + FontSizeHandler mFontSizeHandler; + Ui::GxsForumThreadWidget *ui; RsEventsHandlerId_t mEventHandlerId; }; diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui index b5fe3f95d..439234047 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui @@ -6,7 +6,7 @@ 0 0 - 800 + 848 600 @@ -48,10 +48,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -74,6 +74,13 @@ 0 + + + 12 + 75 + true + + Subscribe @@ -84,6 +91,12 @@
    + + + 75 + true + + Qt::NoFocus @@ -112,19 +125,29 @@ - + 0 0 + + + 12 + 75 + true + + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> Forum Name + + 2 + @@ -173,22 +196,63 @@
    - - - - Lastest post in thread - - - - - Threaded View - - - - - Flat View - - + + + Threaded + + + ... + + + + :/icons/svg/threaded-view.svg:/icons/svg/threaded-view.svg + + + true + + + true + + + + + + + Flat + + + ... + + + + :/icons/svg/flat-view.svg:/icons/svg/flat-view.svg + + + true + + + true + + + + + + + Latest post in thread + + + ... + + + + :/icons/svg/lastpost-view.svg:/icons/svg/lastpost-view.svg + + + true + + + true + @@ -210,6 +274,11 @@ + + + 10 + + Qt::CustomContextMenu @@ -405,7 +474,7 @@ - + @@ -499,9 +568,6 @@ MS Sans Serif - - Qt::CustomContextMenu -
    @@ -509,52 +575,49 @@
    - - - - :/images/document_save.png:/images/document_save.png - - - Save image - - - - RSTextBrowser - QTextBrowser -
    gui/common/RSTextBrowser.h
    -
    LineEditClear QLineEdit -
    gui/common/LineEditClear.h
    -
    - - StyledElidedLabel - QLabel -
    gui/common/StyledElidedLabel.h
    -
    - - SubscribeToolButton - QToolButton -
    gui/common/SubscribeToolButton.h
    +
    gui/common/LineEditClear.h
    GxsIdLabel QLabel
    gui/gxs/GxsIdLabel.h
    + + ElidedLabel + QLabel +
    gui/common/ElidedLabel.h
    + 1 +
    + + SubscribeToolButton + QToolButton +
    gui/common/SubscribeToolButton.h
    +
    RSImageBlockWidget QWidget
    gui/common/RSImageBlockWidget.h
    1
    + + RSTextBrowser + QTextBrowser +
    gui/common/RSTextBrowser.h
    +
    + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    - + diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumsDialog.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumsDialog.cpp index 9527d8675..5733d5a39 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumsDialog.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumsDialog.cpp @@ -24,9 +24,10 @@ #include "CreateGxsForumMsg.h" #include "GxsForumUserNotify.h" #include "gui/notifyqt.h" -#include "gui/gxs/GxsGroupShareKey.h" -#include "util/qtthreadsutils.h" #include "gui/common/GroupTreeWidget.h" +#include "gui/gxs/GxsGroupShareKey.h" +#include "util/misc.h" +#include "util/qtthreadsutils.h" class GxsForumGroupInfoData : public RsUserdata { @@ -39,7 +40,7 @@ public: /** Constructor */ GxsForumsDialog::GxsForumsDialog(QWidget *parent) : - GxsGroupFrameDialog(rsGxsForums, parent), mEventHandlerId(0) + GxsGroupFrameDialog(rsGxsForums, settingsGroupName(),parent), mEventHandlerId(0) { mCountChildMsgs = true; @@ -103,20 +104,36 @@ bool GxsForumsDialog::getGroupData(std::list& groupInfo) bool GxsForumsDialog::getGroupStatistics(const RsGxsGroupId& groupId,GxsGroupStatistic& stat) { - return rsGxsForums->getForumStatistics(groupId,stat); + RsGxsForumStatistics s; + + if(!rsGxsForums->getForumStatistics(groupId,s)) + return false; + + stat.mGrpId = groupId; + stat.mNumMsgs = s.mNumberOfMessages; + + stat.mTotalSizeOfMsgs = 0; // hopefuly unused. Required the loading of the full channel data, so not very convenient. + stat.mNumThreadMsgsNew = s.mNumberOfNewMessages; + stat.mNumThreadMsgsUnread = s.mNumberOfUnreadMessages; + stat.mNumChildMsgsNew = 0; + stat.mNumChildMsgsUnread = 0; + + return true; } - - QString GxsForumsDialog::getHelpString() const { + int H = misc::getFontSizeFactor("HelpButton").height(); + QString hlp_str = tr( - "

      Forums

    \ -

    Retroshare Forums look like internet forums, but they work in a decentralized way

    \ -

    You see forums your friends are subscribed to, and you forward subscribed forums to \ - your friends. This automatically promotes interesting forums in the network.

    \ -

    Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.

    \ - ").arg(QString::number(rsGxsForums->getDefaultStoragePeriod()/86400)).arg(QString::number(rsGxsForums->getDefaultSyncPeriod()/86400)); + "

      Forums

    " + "

    Retroshare Forums look like internet forums, but they work in a decentralized way

    " + "

    You see forums your friends are subscribed to, and you forward subscribed forums to" + " your friends. This automatically promotes interesting forums in the network.

    " + "

    Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.

    " + ).arg( QString::number(2*H) + , QString::number(rsGxsForums->getDefaultStoragePeriod()/86400) + , QString::number(rsGxsForums->getDefaultSyncPeriod()/86400)); return hlp_str ; } @@ -233,9 +250,11 @@ void GxsForumsDialog::groupInfoToGroupItemInfo(const RsGxsGenericGroupData *grou groupItemInfo.description = QString::fromUtf8(forumGroupData->mDescription.c_str()); if (!groupData->mMeta.mCircleId.isNull() ) + { if (details.mRestrictedCircleId == details.mCircleId) groupItemInfo.icon = FilesDefs::getIconFromQtResourcePath(":icons/png/forums-red.png"); else groupItemInfo.icon = FilesDefs::getIconFromQtResourcePath(":icons/png/forums-signed.png"); + } } diff --git a/retroshare-gui/src/gui/help/browser/helpbrowser.cpp b/retroshare-gui/src/gui/help/browser/helpbrowser.cpp index b21ba2cc5..0da10e9d9 100644 --- a/retroshare-gui/src/gui/help/browser/helpbrowser.cpp +++ b/retroshare-gui/src/gui/help/browser/helpbrowser.cpp @@ -117,7 +117,7 @@ HelpBrowser::~HelpBrowser() QString HelpBrowser::language() { - QString lang = Rshare::language(); + QString lang = RsApplication::language(); if (!QDir(":/help/" + lang).exists()) lang = "en"; return lang; @@ -348,7 +348,7 @@ HelpBrowser::find(bool forward) return; } - QTextDocument::FindFlags flags = 0; + QTextDocument::FindFlags flags = QTextDocument::FindFlags(); QTextCursor cursor = ui.txtBrowser->textCursor(); QString searchPhrase = ui.lineFind->text(); diff --git a/retroshare-gui/src/gui/help/browser/helptextbrowser.cpp b/retroshare-gui/src/gui/help/browser/helptextbrowser.cpp index a4b70058f..d9b012775 100644 --- a/retroshare-gui/src/gui/help/browser/helptextbrowser.cpp +++ b/retroshare-gui/src/gui/help/browser/helptextbrowser.cpp @@ -54,7 +54,7 @@ HelpTextBrowser::loadResource(int type, const QUrl &name) /* Fall back to English if there is no translation of the specified help * page in the current language. */ if (!name.path().contains("/")) { - QString language = Rshare::language(); + QString language = RsApplication::language(); if (!QDir(":/help/" + language).exists()) language = "en"; helpPath += language + "/"; diff --git a/retroshare-gui/src/gui/icons.qrc b/retroshare-gui/src/gui/icons.qrc index 48071b201..ff3771075 100644 --- a/retroshare-gui/src/gui/icons.qrc +++ b/retroshare-gui/src/gui/icons.qrc @@ -1,6 +1,9 @@ icons/onion.png + icons/svg/threaded-view.svg + icons/svg/flat-view.svg + icons/svg/lastpost-view.svg icons/svg/design.svg icons/svg/hidden.svg icons/svg/ratio-auto.svg @@ -12,6 +15,7 @@ icons/svg/display_options.svg icons/svg/listlayout.svg icons/svg/gridlayout.svg + icons/svg/people2.svg icons/stars/star0.png icons/stars/star1.png icons/stars/star2.png @@ -141,6 +145,7 @@ icons/search_red_128.png icons/security_high_128.png icons/security_low_128.png + icons/security_low_off_128.png icons/security_medium_128.png icons/settings/appearance.svg icons/settings/channels.svg @@ -204,6 +209,7 @@ icons/svg/newsfeed.svg icons/svg/options.svg icons/svg/paste.svg + icons/svg/paste_image.svg icons/svg/people-notify.svg icons/svg/people.svg icons/svg/person.svg @@ -340,5 +346,42 @@ icons/notification.png icons/wire.png icons/wire-circle.png + icons/folder-account.svg + icons/notification.svg + icons/groups/blue.svg + icons/groups/colored.svg + icons/groups/green.svg + icons/groups/indigo.svg + icons/groups/pink.svg + icons/groups/purple.svg + icons/groups/red.svg + icons/groups/yellow.svg + icons/newtab.svg + icons/newwindow.svg + icons/cancel.svg + icons/connection.svg + icons/plus.svg + icons/minus.svg + icons/svg/calendar-blank.svg + icons/svg/calendar-month.svg + icons/svg/calendar-today.svg + icons/svg/calendar-week.svg + icons/svg/refresh.svg + icons/filetype/any.svg + icons/filetype/archive.svg + icons/filetype/audio.svg + icons/filetype/document.svg + icons/filetype/img.svg + icons/filetype/picture.svg + icons/filetype/program.svg + icons/filetype/video.svg + icons/filetype/c.svg + icons/filetype/cpp.svg + icons/filetype/h.svg + icons/filetype/pdf.svg + icons/filetype/apk.svg + icons/filetype/dll.svg + icons/filetype/collection.svg + icons/filetype/patch.svg diff --git a/retroshare-gui/src/gui/icons/account-convert.svg b/retroshare-gui/src/gui/icons/account-convert.svg new file mode 100644 index 000000000..1e5609fad --- /dev/null +++ b/retroshare-gui/src/gui/icons/account-convert.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/retroshare-gui/src/gui/icons/account-plus.svg b/retroshare-gui/src/gui/icons/account-plus.svg new file mode 100644 index 000000000..cf743afad --- /dev/null +++ b/retroshare-gui/src/gui/icons/account-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/retroshare-gui/src/gui/icons/cancel.svg b/retroshare-gui/src/gui/icons/cancel.svg new file mode 100644 index 000000000..bb921b5fa --- /dev/null +++ b/retroshare-gui/src/gui/icons/cancel.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/retroshare-gui/src/gui/icons/connection.svg b/retroshare-gui/src/gui/icons/connection.svg new file mode 100644 index 000000000..b22e7275d --- /dev/null +++ b/retroshare-gui/src/gui/icons/connection.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/any.svg b/retroshare-gui/src/gui/icons/filetype/any.svg new file mode 100644 index 000000000..7e0cbf726 --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/any.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/apk.svg b/retroshare-gui/src/gui/icons/filetype/apk.svg new file mode 100644 index 000000000..81b468fc7 --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/apk.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/archive.svg b/retroshare-gui/src/gui/icons/filetype/archive.svg new file mode 100644 index 000000000..dc7f6ed1a --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/archive.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/audio.svg b/retroshare-gui/src/gui/icons/filetype/audio.svg new file mode 100644 index 000000000..d56eee2cc --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/audio.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/c.svg b/retroshare-gui/src/gui/icons/filetype/c.svg new file mode 100644 index 000000000..702863c5e --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/c.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/collection.svg b/retroshare-gui/src/gui/icons/filetype/collection.svg new file mode 100644 index 000000000..4a6b79ddf --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/collection.svg @@ -0,0 +1,190 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/cpp.svg b/retroshare-gui/src/gui/icons/filetype/cpp.svg new file mode 100644 index 000000000..fbacc8635 --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/cpp.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/dll.svg b/retroshare-gui/src/gui/icons/filetype/dll.svg new file mode 100644 index 000000000..7dbca1de8 --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/dll.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/document.svg b/retroshare-gui/src/gui/icons/filetype/document.svg new file mode 100644 index 000000000..e2976b503 --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/document.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/h.svg b/retroshare-gui/src/gui/icons/filetype/h.svg new file mode 100644 index 000000000..bf4963ba8 --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/h.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/img.svg b/retroshare-gui/src/gui/icons/filetype/img.svg new file mode 100644 index 000000000..66f8c4018 --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/img.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/patch.svg b/retroshare-gui/src/gui/icons/filetype/patch.svg new file mode 100644 index 000000000..2df822b37 --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/patch.svg @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/pdf.svg b/retroshare-gui/src/gui/icons/filetype/pdf.svg new file mode 100644 index 000000000..3be7f47a8 --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/pdf.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/picture.svg b/retroshare-gui/src/gui/icons/filetype/picture.svg new file mode 100644 index 000000000..91d8165b4 --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/picture.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/program.svg b/retroshare-gui/src/gui/icons/filetype/program.svg new file mode 100644 index 000000000..7ae7e7305 --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/program.svg @@ -0,0 +1,48 @@ + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/filetype/video.svg b/retroshare-gui/src/gui/icons/filetype/video.svg new file mode 100644 index 000000000..0dd6c78c7 --- /dev/null +++ b/retroshare-gui/src/gui/icons/filetype/video.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/folder-account.svg b/retroshare-gui/src/gui/icons/folder-account.svg new file mode 100644 index 000000000..1247cb476 --- /dev/null +++ b/retroshare-gui/src/gui/icons/folder-account.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/retroshare-gui/src/gui/icons/folder-open.svg b/retroshare-gui/src/gui/icons/folder-open.svg new file mode 100644 index 000000000..2cd0d4905 --- /dev/null +++ b/retroshare-gui/src/gui/icons/folder-open.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/retroshare-gui/src/gui/icons/folder.png b/retroshare-gui/src/gui/icons/folder.png index 01f942628..50b84dc56 100644 Binary files a/retroshare-gui/src/gui/icons/folder.png and b/retroshare-gui/src/gui/icons/folder.png differ diff --git a/retroshare-gui/src/gui/icons/folder.svg b/retroshare-gui/src/gui/icons/folder.svg new file mode 100644 index 000000000..4989f5d1c --- /dev/null +++ b/retroshare-gui/src/gui/icons/folder.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/retroshare-gui/src/gui/icons/folderopen.png b/retroshare-gui/src/gui/icons/folderopen.png index 544e5f0b7..9f83b2561 100644 Binary files a/retroshare-gui/src/gui/icons/folderopen.png and b/retroshare-gui/src/gui/icons/folderopen.png differ diff --git a/retroshare-gui/src/gui/icons/groups/blue.svg b/retroshare-gui/src/gui/icons/groups/blue.svg new file mode 100644 index 000000000..ee0b3786f --- /dev/null +++ b/retroshare-gui/src/gui/icons/groups/blue.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/groups/colored.svg b/retroshare-gui/src/gui/icons/groups/colored.svg new file mode 100644 index 000000000..8483f270f --- /dev/null +++ b/retroshare-gui/src/gui/icons/groups/colored.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/groups/green.svg b/retroshare-gui/src/gui/icons/groups/green.svg new file mode 100644 index 000000000..3ca8e3074 --- /dev/null +++ b/retroshare-gui/src/gui/icons/groups/green.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/groups/indigo.svg b/retroshare-gui/src/gui/icons/groups/indigo.svg new file mode 100644 index 000000000..56efae8d7 --- /dev/null +++ b/retroshare-gui/src/gui/icons/groups/indigo.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/groups/pink.svg b/retroshare-gui/src/gui/icons/groups/pink.svg new file mode 100644 index 000000000..e8b72e1df --- /dev/null +++ b/retroshare-gui/src/gui/icons/groups/pink.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/groups/purple.svg b/retroshare-gui/src/gui/icons/groups/purple.svg new file mode 100644 index 000000000..f4d78db5b --- /dev/null +++ b/retroshare-gui/src/gui/icons/groups/purple.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/groups/red.svg b/retroshare-gui/src/gui/icons/groups/red.svg new file mode 100644 index 000000000..07b706a28 --- /dev/null +++ b/retroshare-gui/src/gui/icons/groups/red.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/groups/yellow.svg b/retroshare-gui/src/gui/icons/groups/yellow.svg new file mode 100644 index 000000000..06982a820 --- /dev/null +++ b/retroshare-gui/src/gui/icons/groups/yellow.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/invite64.png b/retroshare-gui/src/gui/icons/invite64.png index 8ab342a7b..f07e0fb4f 100644 Binary files a/retroshare-gui/src/gui/icons/invite64.png and b/retroshare-gui/src/gui/icons/invite64.png differ diff --git a/retroshare-gui/src/gui/icons/minus.svg b/retroshare-gui/src/gui/icons/minus.svg new file mode 100644 index 000000000..fc2ccfaa8 --- /dev/null +++ b/retroshare-gui/src/gui/icons/minus.svg @@ -0,0 +1,42 @@ + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/newtab.svg b/retroshare-gui/src/gui/icons/newtab.svg new file mode 100644 index 000000000..5e7c4316b --- /dev/null +++ b/retroshare-gui/src/gui/icons/newtab.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/retroshare-gui/src/gui/icons/newwindow.svg b/retroshare-gui/src/gui/icons/newwindow.svg new file mode 100644 index 000000000..dd9e408cb --- /dev/null +++ b/retroshare-gui/src/gui/icons/newwindow.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/retroshare-gui/src/gui/icons/notification.svg b/retroshare-gui/src/gui/icons/notification.svg new file mode 100644 index 000000000..c0cb95ba0 --- /dev/null +++ b/retroshare-gui/src/gui/icons/notification.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/retroshare-gui/src/gui/icons/plus.svg b/retroshare-gui/src/gui/icons/plus.svg new file mode 100644 index 000000000..83b1dfbbb --- /dev/null +++ b/retroshare-gui/src/gui/icons/plus.svg @@ -0,0 +1,42 @@ + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/png/invite.png b/retroshare-gui/src/gui/icons/png/invite.png index 5fda4753e..7f0baf91b 100644 Binary files a/retroshare-gui/src/gui/icons/png/invite.png and b/retroshare-gui/src/gui/icons/png/invite.png differ diff --git a/retroshare-gui/src/gui/icons/security_low_off_128.png b/retroshare-gui/src/gui/icons/security_low_off_128.png new file mode 100644 index 000000000..a0f02b0a1 Binary files /dev/null and b/retroshare-gui/src/gui/icons/security_low_off_128.png differ diff --git a/retroshare-gui/src/gui/icons/svg/calendar-blank.svg b/retroshare-gui/src/gui/icons/svg/calendar-blank.svg new file mode 100644 index 000000000..240eea35c --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/calendar-blank.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/retroshare-gui/src/gui/icons/svg/calendar-month.svg b/retroshare-gui/src/gui/icons/svg/calendar-month.svg new file mode 100644 index 000000000..ad16153d4 --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/calendar-month.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/retroshare-gui/src/gui/icons/svg/calendar-today.svg b/retroshare-gui/src/gui/icons/svg/calendar-today.svg new file mode 100644 index 000000000..1673a26ca --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/calendar-today.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/retroshare-gui/src/gui/icons/svg/calendar-week.svg b/retroshare-gui/src/gui/icons/svg/calendar-week.svg new file mode 100644 index 000000000..b958f1bd9 --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/calendar-week.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/retroshare-gui/src/gui/icons/svg/download.svg b/retroshare-gui/src/gui/icons/svg/download.svg index 4cd19ee40..9c260c8e8 100644 --- a/retroshare-gui/src/gui/icons/svg/download.svg +++ b/retroshare-gui/src/gui/icons/svg/download.svg @@ -1,18 +1,18 @@ + inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)" + sodipodi:docname="download.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> @@ -36,18 +36,19 @@ inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1366" - inkscape:window-height="706" + inkscape:window-height="705" id="namedview6" showgrid="false" inkscape:zoom="5.3636364" - inkscape:cx="22" - inkscape:cy="21.813559" + inkscape:cx="22.186441" + inkscape:cy="21.720339" inkscape:window-x="-8" inkscape:window-y="-8" inkscape:window-maximized="1" - inkscape:current-layer="svg2" /> + inkscape:current-layer="svg2" + inkscape:pagecheckerboard="0" /> + style="fill:#00b400;fill-opacity:1" /> diff --git a/retroshare-gui/src/gui/icons/svg/flat-view.svg b/retroshare-gui/src/gui/icons/svg/flat-view.svg new file mode 100644 index 000000000..b08a1a281 --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/flat-view.svg @@ -0,0 +1,42 @@ + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/svg/invite.svg b/retroshare-gui/src/gui/icons/svg/invite.svg index afcefbd72..8a25949a8 100644 --- a/retroshare-gui/src/gui/icons/svg/invite.svg +++ b/retroshare-gui/src/gui/icons/svg/invite.svg @@ -2,25 +2,28 @@ image/svg+xml \ No newline at end of file + d="M 64,32 C 64,14.327 49.673,0 32,0 14.327,0 0,14.327 0,32 0,49.673 14.327,64 32,64 49.673,64 64,49.673 64,32" /> diff --git a/retroshare-gui/src/gui/icons/svg/lastpost-view.svg b/retroshare-gui/src/gui/icons/svg/lastpost-view.svg new file mode 100644 index 000000000..16d0807e0 --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/lastpost-view.svg @@ -0,0 +1,52 @@ + + + +image/svg+xml diff --git a/retroshare-gui/src/gui/icons/svg/paste_image.svg b/retroshare-gui/src/gui/icons/svg/paste_image.svg new file mode 100644 index 000000000..464798ffd --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/paste_image.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/svg/refresh.svg b/retroshare-gui/src/gui/icons/svg/refresh.svg new file mode 100644 index 000000000..eddf8330e --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/refresh.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/retroshare-gui/src/gui/icons/svg/threaded-view.svg b/retroshare-gui/src/gui/icons/svg/threaded-view.svg new file mode 100644 index 000000000..4210acc40 --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/threaded-view.svg @@ -0,0 +1,42 @@ + + + + + + + + diff --git a/retroshare-gui/src/gui/icons/svg/wire-notify.svg b/retroshare-gui/src/gui/icons/svg/wire-notify.svg new file mode 100644 index 000000000..7d4d6ccce --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/wire-notify.svg @@ -0,0 +1,56 @@ + + + +image/svg+xml diff --git a/retroshare-gui/src/gui/icons/svg/wire.svg b/retroshare-gui/src/gui/icons/svg/wire.svg new file mode 100644 index 000000000..9a8029016 --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/wire.svg @@ -0,0 +1,56 @@ + + + +image/svg+xml diff --git a/retroshare-gui/src/gui/images.qrc b/retroshare-gui/src/gui/images.qrc index fcdd4f3cc..473fd4844 100644 --- a/retroshare-gui/src/gui/images.qrc +++ b/retroshare-gui/src/gui/images.qrc @@ -22,10 +22,6 @@ images/streaming.png images/white-bubble-64.png images/orange-bubble-64.png - images/stock_signature_bad.png - images/stock_signature_ok.png - images/stock_signature_missing.png - images/stock_signature_unverified.png images/anonymous_128_blue.png images/browsable_128_green.png images/browsable_128_blue.png @@ -39,7 +35,6 @@ images/help/natgreen.png images/help/natred.png images/pgp.png - images/rs_wizard.png images/avatar_request.png images/avatar_refused.png images/avatar_request_unknown.png @@ -90,14 +85,6 @@ images/closepressed.png images/denied16.png images/filetype-association.png - images/FileTypeAny.png - images/FileTypeArchive.png - images/FileTypeAudio.png - images/FileTypeCDImage.png - images/FileTypeDocument.png - images/FileTypePicture.png - images/FileTypeProgram.png - images/FileTypeVideo.png images/foldermail.png images/folderopen.png images/fileopen.png @@ -107,9 +94,7 @@ images/graph-checking.png images/graph-blue.png images/avatar_background.png - images/button_cancel.png images/chat.png - images/cancel.png images/close-down.png images/copy.png images/delete.png @@ -205,10 +190,7 @@ images/junk.png images/junk_on.png images/junk_off.png - images/connect_friend.png images/kalarm.png - images/kbackgammon.png - images/kcmsystem24.png images/ledoff1.png images/ledon1.png images/locale.png @@ -226,6 +208,7 @@ images/logo/logo_info.png images/logo/logo_splash.png images/logo/logo_web_nobackground.png + images/logo/logo_web_nobackground_black.png images/mail-signed.png images/mail-signature-unknown.png images/mailforward24-hover.png @@ -273,16 +256,8 @@ images/replymailall24-hover.png images/reset.png images/resume.png - images/security-high-16.png - images/security-high-48.png - images/security-low-48.png - images/security-medium-48.png - images/security-high-off-48.png - images/security-low-off-48.png - images/security-medium-off-48.png images/save24.png images/send24.png - images/settings.png images/show_toolbox_frame.png images/start.png images/stop.png @@ -295,9 +270,6 @@ images/sort_incr.png images/sort_decrease.png images/sound.png - images/tab-dock.png - images/tab-undock.png - images/tab-new.png images/transferupdown.png images/tools_wizard.png images/uploads.png @@ -305,12 +277,6 @@ images/loader/indicator-32.gif images/loader/circleball-16.gif images/loader/progress.gif - images/mimetypes/pdf.png - images/mimetypes/rscollection-16.png - images/mimetypes/patch.png - images/mimetypes/source_c.png - images/mimetypes/source_cpp.png - images/mimetypes/source_h.png images/thumb-default-video.png images/user/add_user24.png images/user/add_user48.png @@ -354,13 +320,7 @@ images/up0down1.png images/up1down1.png images/up1down0.png - images/underconstruction.png images/user.png - images/view_calendar_day.png - images/view_calendar_week.png - images/view_calendar_month.png - images/view_calendar_list.png - images/view_split_top_bottom.png qss/chat/standard/private/info.xml qss/chat/standard/private/incoming.htm qss/chat/standard/private/outgoing.htm @@ -418,19 +378,18 @@ qss/chat/compact/history/main.css qss/chat/compact/history/variants/Standard.css qss/chat/compact/history/variants/Colored.css - qss/stylesheet/qss.default - qss/stylesheet/Standard.qss + qss/stylesheet/default.qss + qss/stylesheet/Standard_Light.qss + qss/stylesheet/Standard_Dark.qss images/tags/pgp-known.png images/tags/pgp-unknown.png images/tags/dev-ambassador.png images/tags/dev-translator.png images/tags/dev-patcher.png images/tags/developer.png - images/share-icon-16.png images/toasterEnable.png images/toasterDisable.png images/emblem-web.png - images/rsmessenger48.png images/SmileyText.png images/SimpleText.png images/ColoredText.png diff --git a/retroshare-gui/src/gui/images/FileTypeAny.png b/retroshare-gui/src/gui/images/FileTypeAny.png deleted file mode 100644 index 34e64b73c..000000000 Binary files a/retroshare-gui/src/gui/images/FileTypeAny.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/FileTypeArchive.png b/retroshare-gui/src/gui/images/FileTypeArchive.png deleted file mode 100644 index b982beb6c..000000000 Binary files a/retroshare-gui/src/gui/images/FileTypeArchive.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/FileTypeAudio.png b/retroshare-gui/src/gui/images/FileTypeAudio.png deleted file mode 100644 index 988b27bf7..000000000 Binary files a/retroshare-gui/src/gui/images/FileTypeAudio.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/FileTypeCDImage.png b/retroshare-gui/src/gui/images/FileTypeCDImage.png deleted file mode 100644 index cb3ae8289..000000000 Binary files a/retroshare-gui/src/gui/images/FileTypeCDImage.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/FileTypeDocument.png b/retroshare-gui/src/gui/images/FileTypeDocument.png deleted file mode 100644 index 41d20a5c3..000000000 Binary files a/retroshare-gui/src/gui/images/FileTypeDocument.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/FileTypePicture.png b/retroshare-gui/src/gui/images/FileTypePicture.png deleted file mode 100644 index 7e9bb14f6..000000000 Binary files a/retroshare-gui/src/gui/images/FileTypePicture.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/FileTypeProgram.png b/retroshare-gui/src/gui/images/FileTypeProgram.png deleted file mode 100644 index 63b9f6c32..000000000 Binary files a/retroshare-gui/src/gui/images/FileTypeProgram.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/FileTypeVideo.png b/retroshare-gui/src/gui/images/FileTypeVideo.png deleted file mode 100644 index 9bcc41b78..000000000 Binary files a/retroshare-gui/src/gui/images/FileTypeVideo.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/button_cancel.png b/retroshare-gui/src/gui/images/button_cancel.png deleted file mode 100644 index 3f0c98b7d..000000000 Binary files a/retroshare-gui/src/gui/images/button_cancel.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/cancel.png b/retroshare-gui/src/gui/images/cancel.png deleted file mode 100644 index 87cd0b012..000000000 Binary files a/retroshare-gui/src/gui/images/cancel.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/connect_friend.png b/retroshare-gui/src/gui/images/connect_friend.png deleted file mode 100755 index 3549e6d83..000000000 Binary files a/retroshare-gui/src/gui/images/connect_friend.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/kbackgammon.png b/retroshare-gui/src/gui/images/kbackgammon.png deleted file mode 100644 index 9bdda1083..000000000 Binary files a/retroshare-gui/src/gui/images/kbackgammon.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/kcmsystem24.png b/retroshare-gui/src/gui/images/kcmsystem24.png deleted file mode 100644 index cedcf7f0f..000000000 Binary files a/retroshare-gui/src/gui/images/kcmsystem24.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/logo/logo_web_nobackground_black.png b/retroshare-gui/src/gui/images/logo/logo_web_nobackground_black.png new file mode 100644 index 000000000..1be6fbdc0 Binary files /dev/null and b/retroshare-gui/src/gui/images/logo/logo_web_nobackground_black.png differ diff --git a/retroshare-gui/src/gui/images/mimetypes/patch.png b/retroshare-gui/src/gui/images/mimetypes/patch.png deleted file mode 100644 index 3925b7c2e..000000000 Binary files a/retroshare-gui/src/gui/images/mimetypes/patch.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/mimetypes/pdf.png b/retroshare-gui/src/gui/images/mimetypes/pdf.png deleted file mode 100644 index 73946b90d..000000000 Binary files a/retroshare-gui/src/gui/images/mimetypes/pdf.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/mimetypes/rscollection-16.png b/retroshare-gui/src/gui/images/mimetypes/rscollection-16.png deleted file mode 100644 index ab6d1686e..000000000 Binary files a/retroshare-gui/src/gui/images/mimetypes/rscollection-16.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/mimetypes/source_c.png b/retroshare-gui/src/gui/images/mimetypes/source_c.png deleted file mode 100644 index 51e7d3976..000000000 Binary files a/retroshare-gui/src/gui/images/mimetypes/source_c.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/mimetypes/source_cpp.png b/retroshare-gui/src/gui/images/mimetypes/source_cpp.png deleted file mode 100644 index 522dc111f..000000000 Binary files a/retroshare-gui/src/gui/images/mimetypes/source_cpp.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/mimetypes/source_h.png b/retroshare-gui/src/gui/images/mimetypes/source_h.png deleted file mode 100644 index 116790f4e..000000000 Binary files a/retroshare-gui/src/gui/images/mimetypes/source_h.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/rs_wizard.png b/retroshare-gui/src/gui/images/rs_wizard.png deleted file mode 100644 index 387d21177..000000000 Binary files a/retroshare-gui/src/gui/images/rs_wizard.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/rsmessenger48.png b/retroshare-gui/src/gui/images/rsmessenger48.png deleted file mode 100644 index f01ab76b4..000000000 Binary files a/retroshare-gui/src/gui/images/rsmessenger48.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/security-high-16.png b/retroshare-gui/src/gui/images/security-high-16.png deleted file mode 100644 index d93b4bdd9..000000000 Binary files a/retroshare-gui/src/gui/images/security-high-16.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/security-high-32.png b/retroshare-gui/src/gui/images/security-high-32.png deleted file mode 100755 index 95e73d93e..000000000 Binary files a/retroshare-gui/src/gui/images/security-high-32.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/security-high-48.png b/retroshare-gui/src/gui/images/security-high-48.png deleted file mode 100644 index fb54fd735..000000000 Binary files a/retroshare-gui/src/gui/images/security-high-48.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/security-high-off-48.png b/retroshare-gui/src/gui/images/security-high-off-48.png deleted file mode 100644 index d4149def2..000000000 Binary files a/retroshare-gui/src/gui/images/security-high-off-48.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/security-low-48.png b/retroshare-gui/src/gui/images/security-low-48.png deleted file mode 100644 index 9d5659f46..000000000 Binary files a/retroshare-gui/src/gui/images/security-low-48.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/security-low-off-48.png b/retroshare-gui/src/gui/images/security-low-off-48.png deleted file mode 100644 index 80901511d..000000000 Binary files a/retroshare-gui/src/gui/images/security-low-off-48.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/security-medium-48.png b/retroshare-gui/src/gui/images/security-medium-48.png deleted file mode 100644 index 9265eb46c..000000000 Binary files a/retroshare-gui/src/gui/images/security-medium-48.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/security-medium-off-48.png b/retroshare-gui/src/gui/images/security-medium-off-48.png deleted file mode 100644 index 89c83df46..000000000 Binary files a/retroshare-gui/src/gui/images/security-medium-off-48.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/settings.png b/retroshare-gui/src/gui/images/settings.png deleted file mode 100644 index 9e6d52b8b..000000000 Binary files a/retroshare-gui/src/gui/images/settings.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/share-icon-16.png b/retroshare-gui/src/gui/images/share-icon-16.png deleted file mode 100644 index a5de1924f..000000000 Binary files a/retroshare-gui/src/gui/images/share-icon-16.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/share-icon-24.png b/retroshare-gui/src/gui/images/share-icon-24.png deleted file mode 100644 index 09eee141f..000000000 Binary files a/retroshare-gui/src/gui/images/share-icon-24.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/share-icon-32.png b/retroshare-gui/src/gui/images/share-icon-32.png deleted file mode 100644 index 80fd96250..000000000 Binary files a/retroshare-gui/src/gui/images/share-icon-32.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/stock_signature_bad.png b/retroshare-gui/src/gui/images/stock_signature_bad.png deleted file mode 100644 index c8de64f7a..000000000 Binary files a/retroshare-gui/src/gui/images/stock_signature_bad.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/stock_signature_missing.png b/retroshare-gui/src/gui/images/stock_signature_missing.png deleted file mode 100644 index 66c03a4e6..000000000 Binary files a/retroshare-gui/src/gui/images/stock_signature_missing.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/stock_signature_ok.png b/retroshare-gui/src/gui/images/stock_signature_ok.png deleted file mode 100644 index 454421ad1..000000000 Binary files a/retroshare-gui/src/gui/images/stock_signature_ok.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/stock_signature_unverified.png b/retroshare-gui/src/gui/images/stock_signature_unverified.png deleted file mode 100644 index aae661fa6..000000000 Binary files a/retroshare-gui/src/gui/images/stock_signature_unverified.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/tab-dock.png b/retroshare-gui/src/gui/images/tab-dock.png deleted file mode 100644 index ba059de40..000000000 Binary files a/retroshare-gui/src/gui/images/tab-dock.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/tab-new.png b/retroshare-gui/src/gui/images/tab-new.png deleted file mode 100644 index 3bbbb51c1..000000000 Binary files a/retroshare-gui/src/gui/images/tab-new.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/tab-undock.png b/retroshare-gui/src/gui/images/tab-undock.png deleted file mode 100644 index f2827606c..000000000 Binary files a/retroshare-gui/src/gui/images/tab-undock.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/underconstruction.png b/retroshare-gui/src/gui/images/underconstruction.png deleted file mode 100644 index af754a98c..000000000 Binary files a/retroshare-gui/src/gui/images/underconstruction.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/view_calendar_day.png b/retroshare-gui/src/gui/images/view_calendar_day.png deleted file mode 100644 index a32fbb723..000000000 Binary files a/retroshare-gui/src/gui/images/view_calendar_day.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/view_calendar_list.png b/retroshare-gui/src/gui/images/view_calendar_list.png deleted file mode 100644 index f41b620b3..000000000 Binary files a/retroshare-gui/src/gui/images/view_calendar_list.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/view_calendar_month.png b/retroshare-gui/src/gui/images/view_calendar_month.png deleted file mode 100644 index e90194dcc..000000000 Binary files a/retroshare-gui/src/gui/images/view_calendar_month.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/view_calendar_week.png b/retroshare-gui/src/gui/images/view_calendar_week.png deleted file mode 100644 index eb12f42d8..000000000 Binary files a/retroshare-gui/src/gui/images/view_calendar_week.png and /dev/null differ diff --git a/retroshare-gui/src/gui/images/view_split_top_bottom.png b/retroshare-gui/src/gui/images/view_split_top_bottom.png deleted file mode 100644 index 8c0e4db56..000000000 Binary files a/retroshare-gui/src/gui/images/view_split_top_bottom.png and /dev/null differ diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.cpp b/retroshare-gui/src/gui/msgs/MessageComposer.cpp index 2be5efb35..47da8e913 100644 --- a/retroshare-gui/src/gui/msgs/MessageComposer.cpp +++ b/retroshare-gui/src/gui/msgs/MessageComposer.cpp @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include @@ -121,6 +123,8 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) /* Invoke the Qt Designer generated object setup routine */ ui.setupUi(this); + mAlreadySent = false; + m_msgType = NORMAL; // needed to send system flags with reply msgFlags = 0; @@ -136,8 +140,8 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) m_completer = NULL; - ui.distantFrame->hide(); - ui.sizeLimitFrame->hide(); + ui.info_Frame_Distant->hide(); + ui.info_Frame_SizeLimit->hide(); ui.respond_to_CB->hide(); ui.fromLabel->hide(); @@ -148,7 +152,7 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) ui.hashBox->hide(); // connect up the buttons. - connect( ui.actionSend, SIGNAL( triggered (bool)), this, SLOT( sendMessage( ) ) ); + connect( ui.actionSend, SIGNAL( triggered(bool)), this, SLOT( sendMessage() ), Qt::UniqueConnection ); //connect( ui.actionReply, SIGNAL( triggered (bool)), this, SLOT( replyMessage( ) ) ); connect(ui.boldbtn, SIGNAL(clicked()), this, SLOT(textBold())); connect(ui.underlinebtn, SIGNAL(clicked()), this, SLOT(textUnderline())); @@ -162,16 +166,16 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) connect(ui.actionContactsView, SIGNAL(triggered()), this, SLOT(toggleContacts())); connect(ui.actionSaveas, SIGNAL(triggered()), this, SLOT(saveasDraft())); connect(ui.actionAttach, SIGNAL(triggered()), this, SLOT(attachFile())); - connect(ui.titleEdit, SIGNAL(textChanged(const QString &)), this, SLOT(titleChanged())); + connect(ui.titleEdit, SIGNAL(textChanged(QString)), this, SLOT(titleChanged())); connect(ui.sizeincreaseButton, SIGNAL (clicked()), this, SLOT (fontSizeIncrease())); connect(ui.sizedecreaseButton, SIGNAL (clicked()), this, SLOT (fontSizeDecrease())); connect(ui.actionQuote, SIGNAL(triggered()), this, SLOT(blockQuote())); connect(ui.codeButton, SIGNAL (clicked()), this, SLOT (toggleCode())); - connect(ui.msgText, SIGNAL( checkSpellingChanged( bool ) ), this, SLOT( spellChecking( bool ) ) ); + connect(ui.msgText, SIGNAL( checkSpellingChanged(bool) ), this, SLOT( spellChecking(bool) ) ); - connect(ui.msgText, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)), this, SLOT(currentCharFormatChanged(const QTextCharFormat &))); + connect(ui.msgText, SIGNAL(currentCharFormatChanged(QTextCharFormat)), this, SLOT(currentCharFormatChanged(QTextCharFormat))); connect(ui.msgText, SIGNAL(cursorPositionChanged()), this, SLOT(cursorPositionChanged())); connect(ui.msgText->document(), SIGNAL(modificationChanged(bool)), actionSave, SLOT(setEnabled(bool))); @@ -206,12 +210,12 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) connect(ui.filterComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterComboBoxChanged(int))); - connect(ui.addToButton, SIGNAL(clicked(void)), this, SLOT(addTo())); - connect(ui.addCcButton, SIGNAL(clicked(void)), this, SLOT(addCc())); - connect(ui.addBccButton, SIGNAL(clicked(void)), this, SLOT(addBcc())); - connect(ui.addRecommendButton, SIGNAL(clicked(void)), this, SLOT(addRecommend())); + connect(ui.addToButton, SIGNAL(clicked()), this, SLOT(addTo())); + connect(ui.addCcButton, SIGNAL(clicked()), this, SLOT(addCc())); + connect(ui.addBccButton, SIGNAL(clicked()), this, SLOT(addBcc())); + connect(ui.addRecommendButton, SIGNAL(clicked()), this, SLOT(addRecommend())); - connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(const QString&,int)), this, SLOT(peerStatusChanged(const QString&,int))); + connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(QString,int)), this, SLOT(peerStatusChanged(QString,int))); connect(ui.friendSelectionWidget, SIGNAL(contentChanged()), this, SLOT(buildCompleter())); connect(ui.friendSelectionWidget, SIGNAL(doubleClicked(int,QString)), this, SLOT(addTo())); connect(ui.friendSelectionWidget, SIGNAL(itemSelectionChanged()), this, SLOT(friendSelectionChanged())); @@ -232,7 +236,7 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) ui.friendSelectionWidget->start(); QActionGroup *grp = new QActionGroup(this); - connect(grp, SIGNAL(triggered(QAction *)), this, SLOT(textAlign(QAction *))); + connect(grp, SIGNAL(triggered(QAction*)), this, SLOT(textAlign(QAction*))); actionAlignLeft = new QAction(QIcon(""), tr("&Left"), grp); actionAlignLeft->setShortcut(Qt::CTRL + Qt::Key_L); @@ -248,7 +252,7 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) actionAlignJustify->setCheckable(true); QActionGroup *grp2 = new QActionGroup(this); - connect(grp2, SIGNAL(triggered(QAction *)), this, SLOT(textStyle(QAction *))); + connect(grp2, SIGNAL(triggered(QAction*)), this, SLOT(textStyle(QAction*))); actionDisc = new QAction(QIcon(""), tr("Bullet list (disc)"), grp2); actionDisc->setCheckable(true); @@ -283,17 +287,44 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) ui.filterComboBox->setCurrentIndex(3); connect(ui.comboStyle, SIGNAL(activated(int)),this, SLOT(changeFormatType(int))); - connect(ui.comboFont, SIGNAL(activated(const QString &)), this, SLOT(textFamily(const QString &))); + connect(ui.comboFont, SIGNAL(activated(QString)), this, SLOT(textFamily(QString))); + +#if QT_VERSION < QT_VERSION_CHECK(5,11,0) + ui.comboFont->setMaximumWidth(QFontMetrics(ui.comboFont->font()).width("_")*20); +#else + ui.comboFont->setMaximumWidth(QFontMetrics(ui.comboFont->font()).horizontalAdvance("_")*20); +#endif ui.comboSize->setEditable(true); + ui.comboSize->style()->polish(ui.comboSize); // Needed else QLineEdit inside QComboBox background is painted with black color. QFontDatabase db; foreach(int size, db.standardSizes()) - ui.comboSize->addItem(QString::number(size)); + ui.comboSize->addItem(QString::number(size), size); - connect(ui.comboSize, SIGNAL(activated(const QString &)),this, SLOT(textSize(const QString &))); + QStyleOptionComboBox opt; QSize sh; + opt.initFrom(ui.comboSize); + opt.subControls = QStyle::SC_All; + opt.activeSubControls = QStyle::SC_None; + opt.editable = ui.comboSize->isEditable(); + sh = ui.comboSize->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, sh, ui.comboSize); + //+4 because there is hardcoded margins in QCommonStyle::drawControl(CE_ComboBoxLabel) +#if QT_VERSION < QT_VERSION_CHECK(5,11,0) + sh.setWidth(sh.width() + ui.comboSize->fontMetrics().width("8")*2 + 4); +#else + sh.setWidth(sh.width() + ui.comboSize->fontMetrics().horizontalAdvance("8")*2 + 4); +#endif + ui.comboSize->setMaximumWidth(sh.width()); + ui.comboSize->view()->setMinimumWidth(sh.width() + ui.comboSize->view()->verticalScrollBar()->minimumWidth() + 4); + + connect(ui.comboSize, SIGNAL(activated(QString)),this, SLOT(textSize(QString))); ui.comboSize->setCurrentIndex(ui.comboSize->findText(QString::number(QApplication::font().pointSize()))); + ui.toolBarFrame->setMinimumHeight( ui.comboStyle->height() + + ui.toolBarFrameHLayout->contentsMargins().top() + + ui.toolBarFrameHLayout->contentsMargins().bottom() + ); + QMenu * alignmentmenu = new QMenu(); alignmentmenu->addAction(actionAlignLeft); alignmentmenu->addAction(actionAlignCenter); @@ -313,11 +344,11 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) ui.styleButton->setMenu(formatlistmenu); QPixmap pxm(24,24); - pxm.fill(Qt::black); + pxm.fill(ui.msgText->palette().text().color()); ui.colorbtn->setIcon(pxm); QPixmap pxm2(24,24); - pxm2.fill(Qt::white); + pxm2.fill(ui.msgText->palette().window().color()); ui.color2btn->setIcon(pxm2); /* Set header resize modes and initial section sizes */ @@ -369,7 +400,7 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) // create tag menu TagsMenu *menu = new TagsMenu (tr("Tags"), this); connect(menu, SIGNAL(aboutToShow()), this, SLOT(tagAboutToShow())); - connect(menu, SIGNAL(tagSet(int, bool)), this, SLOT(tagSet(int, bool))); + connect(menu, SIGNAL(tagSet(int,bool)), this, SLOT(tagSet(int,bool))); connect(menu, SIGNAL(tagRemoveAll()), this, SLOT(tagRemoveAll())); ui.tagButton->setMenu(menu); @@ -378,6 +409,10 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) ui.hashBox->setDropWidget(this); ui.hashBox->setAutoHide(true); + mMessageFontSizeHandler.registerFontSize(ui.msgText, [this, db] (QWidget*, int fontSize) { + ui.comboSize->setCurrentIndex(ui.comboSize->findData(fontSize)); + }); + #if QT_VERSION < 0x040700 // embedded images are not supported before QT 4.7.0 ui.imagebtn->setVisible(false); @@ -408,21 +443,21 @@ void MessageComposer::updateCells(int,int) if(has_gxs) { ui.respond_to_CB->show(); - ui.distantFrame->show(); + ui.info_Frame_Distant->show(); ui.fromLabel->show(); checkLength(); } else { ui.respond_to_CB->hide(); - ui.distantFrame->hide() ; + ui.info_Frame_Distant->hide() ; ui.fromLabel->hide(); } if(rowCount > 20) - ui.sizeLimitFrame->show(); + ui.info_Frame_SizeLimit->show(); else - ui.sizeLimitFrame->hide(); + ui.info_Frame_SizeLimit->hide(); } void MessageComposer::processSettings(bool bLoad) @@ -619,7 +654,7 @@ void MessageComposer::addConnectAttemptMsg(const RsPgpId &gpgId, const RsPeerId // PGPId+SslId are always here. But if the peer is not a friend the SSL id cannot be used. // (todo) If the PGP id doesn't get us a PGP key from the keyring, we need to create a short invite - RetroShareLink link = RetroShareLink::createUnknownSslCertificate(sslId, gpgId); + RetroShareLink link = RetroShareLink::createUnknownSslCertificate(sslId, gpgId); if (!link.valid()) return; @@ -630,61 +665,20 @@ void MessageComposer::addConnectAttemptMsg(const RsPgpId &gpgId, const RsPeerId std::list msgList; std::list::const_iterator it; - rsMail->getMessageSummaries(msgList); - for(it = msgList.begin(); it != msgList.end(); ++it) { - if (it->msgflags & RS_MSG_TRASH) { - continue; - } - if ((it->msgflags & RS_MSG_BOXMASK) != RS_MSG_INBOX) { - continue; - } - if ((it->msgflags & RS_MSG_USER_REQUEST) == 0) { - continue; - } - if (it->title == title.toUtf8().constData()) { + rsMail->getMessageSummaries(Rs::Msgs::BoxName::BOX_INBOX,msgList); + + // do not re-add an existing request. + // note: the test with name() is very unsecure. We should use the ID instead. + + for(it = msgList.begin(); it != msgList.end(); ++it) + if((it->msgflags & RS_MSG_USER_REQUEST) && it->title == title.toUtf8().constData()) return; - } - } /* create a message */ QString msgText = tr("Hi %1,

    %2 wants to be friends with you on RetroShare.

    Respond now:
    %3

    Thanks,
    The RetroShare Team").arg(QString::fromUtf8(rsPeers->getGPGName(rsPeers->getGPGOwnId()).c_str()), link.name(), link.toHtml()); rsMail->SystemMessage(title.toUtf8().constData(), msgText.toUtf8().constData(), RS_MSG_USER_REQUEST); } -#ifdef UNUSED_CODE -void MessageComposer::sendChannelPublishKey(RsGxsChannelGroup &group) -{ -// QString channelName = QString::fromUtf8(group.mMeta.mGroupName.c_str()); - -// RetroShareLink link; -// if (!link.createGxsGroupLink(RetroShareLink::TYPE_CHANNEL, group.mMeta.mGroupId, channelName)) { -// return; -// } - -// QString title = tr("Publish key for channel %1").arg(channelName); - -// /* create a message */ -// QString msgText = tr("... %1 ...
    %2").arg(channelName, link.toHtml()); -// rsMail->SystemMessage(title.toUtf8().constData(), msgText.toUtf8().constData(), RS_MSG_PUBLISH_KEY); -} - -void MessageComposer::sendForumPublishKey(RsGxsForumGroup &group) -{ -// QString forumName = QString::fromUtf8(group.mMeta.mGroupName.c_str()); - -// RetroShareLink link; -// if (!link.createGxsGroupLink(RetroShareLink::TYPE_FORUM, group.mMeta.mGroupId, forumName)) { -// return; -// } - -// QString title = tr("Publish key for forum %1").arg(forumName); - -// /* create a message */ -// QString msgText = tr("... %1 ...
    %2").arg(forumName, link.toHtml()); -// rsMail->SystemMessage(title.toUtf8().constData(), msgText.toUtf8().constData(), RS_MSG_PUBLISH_KEY); -} -#endif - void MessageComposer::closeEvent (QCloseEvent * event) { bool bClose = true; @@ -772,7 +766,6 @@ void MessageComposer::buildCompleter() std::list::iterator peerIt; rsPeers->getFriendList(peers); - std::list gxsIds; QList gxsitems ; ui.friendSelectionWidget->items(gxsitems,FriendSelectionWidget::IDTYPE_GXS) ; @@ -781,9 +774,9 @@ void MessageComposer::buildCompleter() QStringList completerList; QStringList completerGroupList; - for (QList::const_iterator idIt = gxsitems.begin(); idIt != gxsitems.end(); ++idIt) + for (auto &idIt : gxsitems) { - RsGxsId id ( ui.friendSelectionWidget->idFromItem( *idIt ) ); + RsGxsId id ( ui.friendSelectionWidget->idFromItem( idIt ) ); RsIdentityDetails detail; if(rsIdentity->getIdDetails(id, detail)) @@ -903,6 +896,7 @@ void MessageComposer::addFile(const FileInfo &fileInfo) void MessageComposer::titleChanged() { calculateTitle(); + std::cerr << "Setting modified 004 = true" << std::endl; ui.msgText->document()->setModified(true); } @@ -1038,36 +1032,63 @@ MessageComposer *MessageComposer::newMsg(const std::string &msgId /* = ""*/) std::list groupInfoList; rsPeers->getGroupInfoList(groupInfoList); - std::list groupIds; - std::list::iterator groupIt; + // std::list groupIds; + // std::list::iterator groupIt; - // calculateGroupsOfSslIds(groupInfoList, msgInfo.msgto, groupIds); - // for (groupIt = groupIds.begin(); groupIt != groupIds.end(); ++groupIt ) { - // msgComposer->addRecipient(MessageComposer::TO, *groupIt, true) ; - // } + // calculateGroupsOfSslIds(groupInfoList, msgInfo.msgto, groupIds); + // for (groupIt = groupIds.begin(); groupIt != groupIds.end(); ++groupIt ) { + // msgComposer->addRecipient(MessageComposer::TO, *groupIt, true) ; + // } - // calculateGroupsOfSslIds(groupInfoList, msgInfo.msgcc, groupIds); - // for (groupIt = groupIds.begin(); groupIt != groupIds.end(); ++groupIt ) { - // msgComposer->addRecipient(MessageComposer::CC, *groupIt, true) ; - // } + // calculateGroupsOfSslIds(groupInfoList, msgInfo.msgcc, groupIds); + // for (groupIt = groupIds.begin(); groupIt != groupIds.end(); ++groupIt ) { + // msgComposer->addRecipient(MessageComposer::CC, *groupIt, true) ; + // } - // calculateGroupsOfSslIds(groupInfoList, msgInfo.msgbcc, groupIds); - // for (groupIt = groupIds.begin(); groupIt != groupIds.end(); ++groupIt ) { - // msgComposer->addRecipient(MessageComposer::BCC, *groupIt, true) ; - // } + // calculateGroupsOfSslIds(groupInfoList, msgInfo.msgbcc, groupIds); + // for (groupIt = groupIds.begin(); groupIt != groupIds.end(); ++groupIt ) { + // msgComposer->addRecipient(MessageComposer::BCC, *groupIt, true) ; + // } - for (std::set::const_iterator it = msgInfo.rspeerid_msgto.begin(); it != msgInfo.rspeerid_msgto.end(); ++it ) msgComposer->addRecipient(MessageComposer::TO, *it) ; - for (std::set::const_iterator it = msgInfo.rspeerid_msgcc.begin(); it != msgInfo.rspeerid_msgcc.end(); ++it ) msgComposer->addRecipient(MessageComposer::CC, *it) ; - for (std::set::const_iterator it = msgInfo.rspeerid_msgbcc.begin(); it != msgInfo.rspeerid_msgbcc.end(); ++it ) msgComposer->addRecipient(MessageComposer::BCC, *it) ; - for (std::set::const_iterator it = msgInfo.rsgxsid_msgto.begin(); it != msgInfo.rsgxsid_msgto.end(); ++it ) msgComposer->addRecipient(MessageComposer::TO, *it) ; - for (std::set::const_iterator it = msgInfo.rsgxsid_msgcc.begin(); it != msgInfo.rsgxsid_msgcc.end(); ++it ) msgComposer->addRecipient(MessageComposer::CC, *it) ; - for (std::set::const_iterator it = msgInfo.rsgxsid_msgbcc.begin(); it != msgInfo.rsgxsid_msgbcc.end(); ++it ) msgComposer->addRecipient(MessageComposer::BCC, *it) ; + for(auto m:msgInfo.destinations) + switch(m.mode()) + { + case MsgAddress::MSG_ADDRESS_MODE_TO: + if(m.type()==MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) + msgComposer->addRecipient(MessageComposer::TO,m.toGxsId()); + else if(m.type()==MsgAddress::MSG_ADDRESS_TYPE_RSPEERID) + msgComposer->addRecipient(MessageComposer::TO,m.toRsPeerId()); + break; + + case MsgAddress::MSG_ADDRESS_MODE_CC: + if(m.type()==MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) + msgComposer->addRecipient(MessageComposer::CC,m.toGxsId()); + else if(m.type()==MsgAddress::MSG_ADDRESS_TYPE_RSPEERID) + msgComposer->addRecipient(MessageComposer::CC,m.toRsPeerId()); + break; + + case MsgAddress::MSG_ADDRESS_MODE_BCC: + if(m.type()==MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) + msgComposer->addRecipient(MessageComposer::BCC,m.toGxsId()); + else if(m.type()==MsgAddress::MSG_ADDRESS_TYPE_RSPEERID) + msgComposer->addRecipient(MessageComposer::BCC,m.toRsPeerId()); + break; + default:break; + } + + // for (std::set::const_iterator it = msgInfo.rspeerid_msgto.begin(); it != msgInfo.rspeerid_msgto.end(); ++it ) msgComposer->addRecipient(MessageComposer::TO, *it) ; + // for (std::set::const_iterator it = msgInfo.rspeerid_msgcc.begin(); it != msgInfo.rspeerid_msgcc.end(); ++it ) msgComposer->addRecipient(MessageComposer::CC, *it) ; + // for (std::set::const_iterator it = msgInfo.rspeerid_msgbcc.begin(); it != msgInfo.rspeerid_msgbcc.end(); ++it ) msgComposer->addRecipient(MessageComposer::BCC, *it) ; + // for (std::set::const_iterator it = msgInfo.rsgxsid_msgto.begin(); it != msgInfo.rsgxsid_msgto.end(); ++it ) msgComposer->addRecipient(MessageComposer::TO, *it) ; + // for (std::set::const_iterator it = msgInfo.rsgxsid_msgcc.begin(); it != msgInfo.rsgxsid_msgcc.end(); ++it ) msgComposer->addRecipient(MessageComposer::CC, *it) ; + // for (std::set::const_iterator it = msgInfo.rsgxsid_msgbcc.begin(); it != msgInfo.rsgxsid_msgbcc.end(); ++it ) msgComposer->addRecipient(MessageComposer::BCC, *it) ; MsgTagInfo tagInfo; rsMail->getMessageTag(msgId, tagInfo); - msgComposer->m_tagIds = tagInfo.tagIds; + msgComposer->m_tagIds = tagInfo; msgComposer->showTagLabels(); + std::cerr << "Setting modified 005 = false" << std::endl; msgComposer->ui.msgText->document()->setModified(false); } @@ -1083,7 +1104,7 @@ QString MessageComposer::buildReplyHeader(const MessageInfo &msgInfo) QString from; if(msgInfo.msgflags & RS_MSG_DISTANT) { - link = RetroShareLink::createMessage(msgInfo.rsgxsid_srcId, ""); + link = RetroShareLink::createMessage(msgInfo.from.toGxsId(), ""); if (link.valid()) { from += link.toHtml(); @@ -1091,57 +1112,39 @@ QString MessageComposer::buildReplyHeader(const MessageInfo &msgInfo) } else { - link = RetroShareLink::createMessage(msgInfo.rspeerid_srcId, ""); + link = RetroShareLink::createMessage(msgInfo.from.toRsPeerId(), ""); if (link.valid()) { from += link.toHtml(); } } + QString to,cc; - QString to; - for ( std::set::const_iterator it = msgInfo.rspeerid_msgto.begin(); it != msgInfo.rspeerid_msgto.end(); ++it) + for(auto m:msgInfo.destinations) { - link = RetroShareLink::createMessage(*it, ""); + RetroShareLink link; + + if(m.type()==MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) + link = RetroShareLink::createMessage(m.toGxsId(), ""); + else + link = RetroShareLink::createMessage(m.toRsPeerId(), ""); + if (link.valid()) - { - if (!to.isEmpty()) - to += ", "; + if(m.mode()==MsgAddress::MSG_ADDRESS_MODE_TO) + { + if (!to.isEmpty()) + to += ", "; - to += link.toHtml(); - } - } - for ( std::set::const_iterator it = msgInfo.rsgxsid_msgto.begin(); it != msgInfo.rsgxsid_msgto.end(); ++it) - { - link = RetroShareLink::createMessage(*it, ""); - if (link.valid()) - { - if (!to.isEmpty()) - to += ", "; - - to += link.toHtml(); - } - } - - QString cc; - for (std::set::const_iterator it = msgInfo.rspeerid_msgcc.begin(); it != msgInfo.rspeerid_msgcc.end(); ++it) { - link = RetroShareLink::createMessage(*it, ""); - if (link.valid()) { - if (!cc.isEmpty()) { - cc += ", "; + to += link.toHtml(); } - cc += link.toHtml(); - } - } - for (std::set::const_iterator it = msgInfo.rsgxsid_msgcc.begin(); it != msgInfo.rsgxsid_msgcc.end(); ++it) { - link = RetroShareLink::createMessage(*it, ""); - if (link.valid()) { - if (!cc.isEmpty()) { - cc += ", "; - } - cc += link.toHtml(); - } - } + else if(m.mode()==MsgAddress::MSG_ADDRESS_MODE_CC) + { + if (!cc.isEmpty()) + cc += ", "; + cc += link.toHtml(); + } + } QString header = QString("-----%1-----").arg(tr("Original Message")); header += QString("
    %1: %2
    ").arg(tr("From"), from); @@ -1193,6 +1196,7 @@ void MessageComposer::setQuotedMsg(const QString &msg, const QString &header) ui.msgText->moveCursor(QTextCursor::Start); ui.msgText->setUndoRedoEnabled(true); + std::cerr << "Setting modified 006 = true" << std::endl; ui.msgText->document()->setModified(true); ui.msgText->setFocus( Qt::OtherFocusReason ); @@ -1205,6 +1209,11 @@ MessageComposer *MessageComposer::replyMsg(const std::string &msgId, bool all) return NULL; } + if(msgInfo.from.type()==MsgAddress::MSG_ADDRESS_TYPE_RSPEERID && msgInfo.from.toRsPeerId().isNull()) + { + QMessageBox::warning(nullptr,tr("Will not reply"),tr("There is no point in replying to a notification message!")); + return nullptr; + } MessageComposer *msgComposer = MessageComposer::newMsg(); msgComposer->m_msgParentId = msgId; msgComposer->m_msgType = REPLY; @@ -1214,14 +1223,18 @@ MessageComposer *MessageComposer::replyMsg(const std::string &msgId, bool all) msgComposer->setTitleText(QString::fromUtf8(msgInfo.title.c_str()), REPLY); msgComposer->setQuotedMsg(QString::fromUtf8(msgInfo.msg.c_str()), buildReplyHeader(msgInfo)); - if(!msgInfo.rspeerid_srcId.isNull()) msgComposer->addRecipient(MessageComposer::TO, msgInfo.rspeerid_srcId); - if(!msgInfo.rsgxsid_srcId.isNull()) msgComposer->addRecipient(MessageComposer::TO, msgInfo.rsgxsid_srcId); + if(msgInfo.from.type()==MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) + msgComposer->addRecipient(MessageComposer::TO, msgInfo.from.toGxsId()); + else if(msgInfo.from.type()==MsgAddress::MSG_ADDRESS_TYPE_RSPEERID) + msgComposer->addRecipient(MessageComposer::TO, msgInfo.from.toRsPeerId()); // make sure the current ID is among the ones the msg was actually sent to. - for(auto it(msgInfo.rsgxsid_msgto.begin());it!=msgInfo.rsgxsid_msgto.end();++it) - if(rsIdentity->isOwnId(*it)) +#warning: We do not know here what is the atual destination of the message, since it may have been sent to two of our IDs at once. + + for(auto m:msgInfo.destinations) + if(m.type()==MsgAddress::MSG_ADDRESS_TYPE_RSGXSID && rsIdentity->isOwnId(m.toGxsId())) { - msgComposer->ui.respond_to_CB->setDefaultId(*it) ; + msgComposer->ui.respond_to_CB->setDefaultId(m.toGxsId()) ; break ; } // Note: another solution is to do @@ -1230,23 +1243,27 @@ MessageComposer *MessageComposer::replyMsg(const std::string &msgId, bool all) if (all) { - RsPeerId ownId = rsPeers->getOwnId(); + for(auto m:msgInfo.destinations) + if(m.type()==MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) + msgComposer->addRecipient(MessageComposer::TO,m.toGxsId()); + else if(m.type()==MsgAddress::MSG_ADDRESS_TYPE_RSPEERID) + msgComposer->addRecipient(MessageComposer::TO,m.toRsPeerId()); - for (std::set::iterator tli = msgInfo.rspeerid_msgto.begin(); tli != msgInfo.rspeerid_msgto.end(); ++tli) - if (ownId != *tli) - msgComposer->addRecipient(MessageComposer::TO, *tli) ; + // for (std::set::iterator tli = msgInfo.rspeerid_msgto.begin(); tli != msgInfo.rspeerid_msgto.end(); ++tli) + // if (ownId != *tli) + // msgComposer->addRecipient(MessageComposer::TO, *tli) ; - for (std::set::iterator tli = msgInfo.rspeerid_msgcc.begin(); tli != msgInfo.rspeerid_msgcc.end(); ++tli) - if (ownId != *tli) - msgComposer->addRecipient(MessageComposer::TO, *tli) ; + // for (std::set::iterator tli = msgInfo.rspeerid_msgcc.begin(); tli != msgInfo.rspeerid_msgcc.end(); ++tli) + // if (ownId != *tli) + // msgComposer->addRecipient(MessageComposer::TO, *tli) ; - for (std::set::iterator tli = msgInfo.rsgxsid_msgto.begin(); tli != msgInfo.rsgxsid_msgto.end(); ++tli) - //if (ownId != *tli) - msgComposer->addRecipient(MessageComposer::TO, *tli) ; + // for (std::set::iterator tli = msgInfo.rsgxsid_msgto.begin(); tli != msgInfo.rsgxsid_msgto.end(); ++tli) + // //if (ownId != *tli) + // msgComposer->addRecipient(MessageComposer::TO, *tli) ; - for (std::set::iterator tli = msgInfo.rsgxsid_msgcc.begin(); tli != msgInfo.rsgxsid_msgcc.end(); ++tli) - //if (ownId != *tli) - msgComposer->addRecipient(MessageComposer::TO, *tli) ; + // for (std::set::iterator tli = msgInfo.rsgxsid_msgcc.begin(); tli != msgInfo.rsgxsid_msgcc.end(); ++tli) + // //if (ownId != *tli) + // msgComposer->addRecipient(MessageComposer::TO, *tli) ; } // needed to send system flags with reply @@ -1255,7 +1272,7 @@ MessageComposer *MessageComposer::replyMsg(const std::string &msgId, bool all) MsgTagInfo tagInfo; rsMail->getMessageTag(msgId, tagInfo); - msgComposer->m_tagIds = tagInfo.tagIds; + msgComposer->m_tagIds = tagInfo; msgComposer->showTagLabels(); msgComposer->calculateTitle(); @@ -1281,7 +1298,7 @@ MessageComposer *MessageComposer::forwardMsg(const std::string &msgId) msgComposer->setTitleText(QString::fromUtf8(msgInfo.title.c_str()), FORWARD); msgComposer->setQuotedMsg(QString::fromUtf8(msgInfo.msg.c_str()), buildReplyHeader(msgInfo)); - std::list& files_info = msgInfo.files; + const std::list& files_info = msgInfo.files; msgComposer->setFileList(files_info); @@ -1336,26 +1353,29 @@ void MessageComposer::setMsgText(const QString &msg, bool asHtml) c.movePosition(QTextCursor::End); ui.msgText->setTextCursor(c); + std::cerr << "Setting modified 007 = true" << std::endl; ui.msgText->document()->setModified(true); } void MessageComposer::sendMessage() { - if (sendMessage_internal(false)) { + /* check for existing title */ + + if (ui.titleEdit->text().isNull()) + if (QMessageBox::warning(this, tr("RetroShare"), tr("Do you want to send the message without a subject ?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) { + ui.titleEdit->setFocus(); + return ; // Don't send with an empty subject + } + + if (sendMessage_internal(false)) close(); - } } -bool MessageComposer::sendMessage_internal(bool bDraftbox) +bool MessageComposer::buildMessage(MessageInfo& mi) { - /* construct a message */ - MessageInfo mi; + // add a GXS signer/from in case the message is to be sent to a distant peer - // add a GXS signer/from in case the message is to be sent to a distant peer - - mi.rsgxsid_srcId = RsGxsId(ui.respond_to_CB->itemData(ui.respond_to_CB->currentIndex()).toString().toStdString()) ; - - //std::cerr << "MessageSend: setting 'from' field to GXS id = " << mi.rsgxsid_srcId << std::endl; + //std::cerr << "MessageSend: setting 'from' field to GXS id = " << mi.rsgxsid_srcId << std::endl; mi.title = misc::removeNewLine(ui.titleEdit->text()).toUtf8().constData(); // needed to send system flags with reply @@ -1365,14 +1385,6 @@ bool MessageComposer::sendMessage_internal(bool bDraftbox) RsHtml::optimizeHtml(ui.msgText, text); mi.msg = text.toUtf8().constData(); - /* check for existing title */ - if (bDraftbox == false && mi.title.empty()) { - if (QMessageBox::warning(this, tr("RetroShare"), tr("Do you want to send the message without a subject ?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) { - ui.titleEdit->setFocus(); - return false; // Don't send with an empty subject - } - } - int filesCount = ui.msgFileList->topLevelItemCount(); for (int i = 0; i < filesCount; ++i) { QTreeWidgetItem *item = ui.msgFileList->topLevelItem(i); @@ -1429,12 +1441,9 @@ bool MessageComposer::sendMessage_internal(bool bDraftbox) switch (type) { - case TO: mi.rspeerid_msgto.insert(*sslIt); - break; - case CC: mi.rspeerid_msgcc.insert(*sslIt); - break; - case BCC:mi.rspeerid_msgbcc.insert(*sslIt); - break; + case TO: mi.destinations.insert(MsgAddress(*sslIt,MsgAddress::MSG_ADDRESS_MODE_TO)); break; + case CC: mi.destinations.insert(MsgAddress(*sslIt,MsgAddress::MSG_ADDRESS_MODE_CC)); break; + case BCC: mi.destinations.insert(MsgAddress(*sslIt,MsgAddress::MSG_ADDRESS_MODE_BCC)); break; } } } @@ -1446,12 +1455,9 @@ bool MessageComposer::sendMessage_internal(bool bDraftbox) switch (type) { - case TO: mi.rspeerid_msgto.insert(pid); - break ; - case CC: mi.rspeerid_msgcc.insert(pid); - break ; - case BCC:mi.rspeerid_msgbcc.insert(pid); - break ; + case TO: mi.destinations.insert(MsgAddress(pid,MsgAddress::MSG_ADDRESS_MODE_TO)); break; + case CC: mi.destinations.insert(MsgAddress(pid,MsgAddress::MSG_ADDRESS_MODE_CC)); break; + case BCC: mi.destinations.insert(MsgAddress(pid,MsgAddress::MSG_ADDRESS_MODE_BCC)); break; } } break ; @@ -1461,12 +1467,9 @@ bool MessageComposer::sendMessage_internal(bool bDraftbox) switch (type) { - case TO: mi.rsgxsid_msgto.insert(gid) ; - break ; - case CC: mi.rsgxsid_msgcc.insert(gid) ; - break ; - case BCC:mi.rsgxsid_msgbcc.insert(gid) ; - break ; + case TO: mi.destinations.insert(MsgAddress(gid,MsgAddress::MSG_ADDRESS_MODE_TO)); break; + case CC: mi.destinations.insert(MsgAddress(gid,MsgAddress::MSG_ADDRESS_MODE_CC)); break; + case BCC: mi.destinations.insert(MsgAddress(gid,MsgAddress::MSG_ADDRESS_MODE_BCC)); break; } } break ; @@ -1476,6 +1479,49 @@ bool MessageComposer::sendMessage_internal(bool bDraftbox) break ; } } + bool at_least_one_gxsid = false; + + for(auto m:mi.destinations) + if(m.type() == MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) + { + at_least_one_gxsid=true; + break; + } + + if(!at_least_one_gxsid) + mi.from = Rs::Msgs::MsgAddress(rsPeers->getOwnId(),MsgAddress::MSG_ADDRESS_MODE_TO); + else + { + auto gxs_id_from = RsGxsId(ui.respond_to_CB->itemData(ui.respond_to_CB->currentIndex()).toString().toStdString()); + + if(gxs_id_from.isNull()) + { + QMessageBox::warning(this, tr("RetroShare"), tr("Please create an identity to sign distant messages, or remove the distant peers from the destination list."), QMessageBox::Ok); + return false; // Don't send if cannot sign. + } + mi.from = MsgAddress(RsGxsId(ui.respond_to_CB->itemData(ui.respond_to_CB->currentIndex()).toString().toStdString()),MsgAddress::MSG_ADDRESS_MODE_TO) ; + } + + return true; +} + +bool MessageComposer::sendMessage_internal(bool bDraftbox) +{ + if(mAlreadySent) + { + std::cerr << "Already_sent is true. Giving up." << std::endl; + return true; + } + + /* construct a message */ + MessageInfo mi; + + if(!buildMessage(mi)) + return false; + + std::cerr << "Setting already_sent=true" << std::endl; + + mAlreadySent = true; if (bDraftbox) { @@ -1500,21 +1546,15 @@ bool MessageComposer::sendMessage_internal(bool bDraftbox) else { /* check for the recipient */ - if (mi.rspeerid_msgto.empty() && mi.rspeerid_msgcc.empty() && mi.rspeerid_msgbcc.empty() - && mi.rsgxsid_msgto.empty() && mi.rsgxsid_msgcc.empty() && mi.rsgxsid_msgbcc.empty()) + if (mi.destinations.empty()) { QMessageBox::warning(this, tr("RetroShare"), tr("Please insert at least one recipient."), QMessageBox::Ok); return false; // Don't send with no recipient } - if(mi.rsgxsid_srcId.isNull() && !(mi.rsgxsid_msgto.empty() && mi.rsgxsid_msgcc.empty() && mi.rsgxsid_msgbcc.empty())) - { - QMessageBox::warning(this, tr("RetroShare"), tr("Please create an identity to sign distant messages, or remove the distant peers from the destination list."), QMessageBox::Ok); - return false; // Don't send if cannot sign. - } - if (rsMail->MessageSend(mi) == false) { + + if (rsMail->MessageSend(mi) == false) return false; - } if (m_msgParentId.empty() == false) { switch (m_msgType) { @@ -1536,19 +1576,17 @@ bool MessageComposer::sendMessage_internal(bool bDraftbox) /* insert new tags */ std::list::iterator tag; - for (tag = m_tagIds.begin(); tag != m_tagIds.end(); ++tag) { - if (std::find(tagInfo.tagIds.begin(), tagInfo.tagIds.end(), *tag) == tagInfo.tagIds.end()) { - rsMail->setMessageTag(mi.msgId, *tag, true); - } else { - tagInfo.tagIds.remove(*tag); - } - } + for (auto tag:m_tagIds) + if (tagInfo.find(tag) == tagInfo.end()) + rsMail->setMessageTag(mi.msgId, tag, true); + else + tagInfo.erase(tag); /* remove deleted tags */ - for (tag = tagInfo.tagIds.begin(); tag != tagInfo.tagIds.end(); ++tag) { - rsMail->setMessageTag(mi.msgId, *tag, false); - } + for (auto tag:tagInfo) + rsMail->setMessageTag(mi.msgId, tag, false); } + std::cerr << "Setting modified 001 = false" << std::endl; ui.msgText->document()->setModified(false); return true; @@ -1599,16 +1637,16 @@ bool MessageComposer::getRecipientFromRow(int row, enumType &type, destinationTy QString MessageComposer::getRecipientEmailAddress(const RsGxsId& id,const RsIdentityDetails& detail) { - return (QString("%2 <")+tr("Distant identity:")+" %2@%1>").arg(QString::fromStdString(id.toStdString())).arg(QString::fromUtf8(detail.mNickname.c_str())) ; + return (QString("%2 <")+tr("Distant identity:")+" %2@%1>").arg(QString::fromStdString(id.toStdString()), QString::fromUtf8(detail.mNickname.c_str())) ; } QString MessageComposer::getRecipientEmailAddress(const RsPeerId& /* id */,const RsPeerDetails& detail) { - QString location_name = detail.location.empty()?tr("[Missing]"):QString::fromUtf8(detail.location.c_str()) ; + QString location_name = detail.location.empty()?tr("[Missing]"):QString::fromUtf8(detail.location.c_str()) ; - return (QString("%1 (")+tr("Node name & id:")+" %2, %3)").arg(QString::fromUtf8(detail.name.c_str())) - .arg(location_name) - .arg(QString::fromUtf8(detail.id.toStdString().c_str())) ; + return (QString("%1 (")+tr("Node name & id:")+" %2, %3)").arg(QString::fromUtf8(detail.name.c_str()) + , location_name + , QString::fromUtf8(detail.id.toStdString().c_str())) ; } void MessageComposer::setRecipientToRow(int row, enumType type, destinationType dest_type, const std::string &id) @@ -1619,12 +1657,13 @@ void MessageComposer::setRecipientToRow(int row, enumType type, destinationType QComboBox *comboBox = dynamic_cast(ui.recipientWidget->cellWidget(row, COLUMN_RECIPIENT_TYPE)); if (comboBox == NULL) { - comboBox = new QComboBox; + comboBox = new RSComboBox; comboBox->addItem(tr("To"), TO); comboBox->addItem(tr("Cc"), CC); comboBox->addItem(tr("Bcc"), BCC); ui.recipientWidget->setCellWidget(row, COLUMN_RECIPIENT_TYPE, comboBox); + ui.recipientWidget->setRowHeight(row, comboBox->height()); comboBox->setLayoutDirection(Qt::RightToLeft); comboBox->installEventFilter(this); @@ -1789,7 +1828,7 @@ void MessageComposer::editingRecipientFinished() if (row >= rowCount) // not found return; - enumType type; + enumType type = TO; std::string id; // dummy destinationType dtype ; @@ -1818,13 +1857,13 @@ void MessageComposer::editingRecipientFinished() ui.friendSelectionWidget->items(gxsitems,FriendSelectionWidget::IDTYPE_GXS) ; RsIdentityDetails detail; - for (QList::const_iterator idIt = gxsitems.begin(); idIt != gxsitems.end(); ++idIt) + for (auto &idIt : gxsitems) { - RsGxsId id ( ui.friendSelectionWidget->idFromItem( *idIt ) ); + RsGxsId gxsId ( ui.friendSelectionWidget->idFromItem( idIt ) ); - if(rsIdentity->getIdDetails(id, detail) && text == getRecipientEmailAddress(id,detail)) + if(rsIdentity->getIdDetails(gxsId, detail) && text == getRecipientEmailAddress(gxsId,detail)) { - setRecipientToRow(row, type, PEER_TYPE_GXS, id.toStdString()); + setRecipientToRow(row, type, PEER_TYPE_GXS, gxsId.toStdString()); return ; } } @@ -2271,7 +2310,8 @@ void MessageComposer::addSmileys() // add trailing space smiley += QString(" "); // add preceding space when needed (not at start of text or preceding space already exists) - if(!ui.msgText->textCursor().atStart() && ui.msgText->toPlainText()[ui.msgText->textCursor().position() - 1] != QChar(' ')) + QString plainText = ui.msgText->toPlainText(); + if(!ui.msgText->textCursor().atStart() && plainText[ui.msgText->textCursor().position() - 1] != QChar(' ')) smiley = QString(" ") + smiley; ui.msgText->textCursor().insertText(smiley); } @@ -2308,14 +2348,14 @@ void MessageComposer::fontChanged(const QFont &f) void MessageComposer::colorChanged(const QColor &c) { - QPixmap pix(16, 16); + QPixmap pix(24, 24); pix.fill(c); ui.colorbtn->setIcon(pix); } void MessageComposer::colorChanged2(const QColor &c) { - QPixmap pix(16, 16); + QPixmap pix(24, 24); pix.fill(c); ui.color2btn->setIcon(pix); } @@ -2365,6 +2405,7 @@ bool MessageComposer::fileSave() QTextStream ts(&file); ts.setCodec(QTextCodec::codecForName("UTF-8")); ts << ui.msgText->document()->toHtml("UTF-8"); + std::cerr << "Setting modified 002 = false" << std::endl; ui.msgText->document()->setModified(false); return true; } @@ -2419,6 +2460,7 @@ void MessageComposer::filePrintPdf() void MessageComposer::setCurrentFileName(const QString &fileName) { this->fileName = fileName; + std::cerr << "Setting modified 003 = false" << std::endl; ui.msgText->document()->setModified(false); setWindowModified(false); @@ -2769,17 +2811,17 @@ void MessageComposer::tagSet(int tagId, bool set) return; } - std::list::iterator tag = std::find(m_tagIds.begin(), m_tagIds.end(), tagId); - if (tag == m_tagIds.end()) { - if (set) { - m_tagIds.push_back(tagId); - /* Keep the list sorted */ - m_tagIds.sort(); - } - } else { - if (set == false) { - m_tagIds.remove(tagId); - } + auto tag = m_tagIds.find(tagId); + + if (tag == m_tagIds.end()) + { + if (set) + m_tagIds.insert(tagId); + } + else + { + if (set == false) + m_tagIds.erase(tagId); } showTagLabels(); @@ -2806,11 +2848,11 @@ void MessageComposer::showTagLabels() rsMail->getMessageTagTypes(tags); std::map >::iterator tag; - for (std::list::iterator tagId = m_tagIds.begin(); tagId != m_tagIds.end(); ++tagId) { - tag = tags.types.find(*tagId); + for (auto tagId:m_tagIds) { + tag = tags.types.find(tagId); if (tag != tags.types.end()) { QLabel *tagLabel = new QLabel(TagDefs::name(tag->first, tag->second.first), this); - tagLabel->setMaximumHeight(16); + tagLabel->setMaximumHeight(QFontMetrics(tagLabel->font()).height()*1.2); tagLabel->setStyleSheet(TagDefs::labelStyleSheet(tag->second.second)); tagLabels.push_back(tagLabel); ui.tagLayout->addWidget(tagLabel); @@ -2820,13 +2862,14 @@ void MessageComposer::showTagLabels() ui.tagLayout->addStretch(); } } -void MessageComposer::on_closeSizeLimitFrameButton_clicked() + +void MessageComposer::on_closeInfoFrameButton_Distant_clicked() { - ui.sizeLimitFrame->setVisible(false); + ui.info_Frame_Distant->setVisible(false); } -void MessageComposer::on_closeInfoFrameButton_clicked() +void MessageComposer::on_closeInfoFrameButton_SizeLimit_clicked() { - ui.distantFrame->setVisible(false); + ui.info_Frame_SizeLimit->setVisible(false); } QString MessageComposer::inviteMessage() diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.h b/retroshare-gui/src/gui/msgs/MessageComposer.h index a5f6d773c..27bf28458 100644 --- a/retroshare-gui/src/gui/msgs/MessageComposer.h +++ b/retroshare-gui/src/gui/msgs/MessageComposer.h @@ -28,6 +28,7 @@ #include "ui_MessageComposer.h" #include "gui/msgs/MessageInterface.h" +#include "util/FontSizeHandler.h" class QAction; struct RsIdentityDetails; @@ -163,8 +164,8 @@ private slots: void tagSet(int tagId, bool set); void tagRemoveAll(); - void on_closeInfoFrameButton_clicked(); - void on_closeSizeLimitFrameButton_clicked(); + void on_closeInfoFrameButton_Distant_clicked(); + void on_closeInfoFrameButton_SizeLimit_clicked(); static QString inviteMessage(); @@ -172,6 +173,7 @@ private slots: private: static QString buildReplyHeader(const MessageInfo &msgInfo); + bool buildMessage(MessageInfo& mi); void processSettings(bool bLoad); @@ -250,11 +252,11 @@ private: std::string m_msgParentId; // parent message id std::string m_sDraftMsgId; // existing message id enumMessageType m_msgType; - std::list m_tagIds; + std::set m_tagIds; QList tagLabels; // needed to send system flags with reply - unsigned msgFlags; + unsigned int msgFlags; RSTreeWidgetItemCompareRole *m_compareRole; QCompleter *m_completer; @@ -264,6 +266,9 @@ private: QLabel *lineLabel; bool has_gxs; + bool mAlreadySent; // prevents a Qt bug that calls the same action twice. + + MessageFontSizeHandler mMessageFontSizeHandler; /** Qt Designer generated object */ Ui::MessageComposer ui; diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.ui b/retroshare-gui/src/gui/msgs/MessageComposer.ui index ff76237f9..a5ff266d4 100644 --- a/retroshare-gui/src/gui/msgs/MessageComposer.ui +++ b/retroshare-gui/src/gui/msgs/MessageComposer.ui @@ -6,8 +6,8 @@ 0 0 - 1008 - 755 + 800 + 650 @@ -31,12 +31,6 @@ 0 - - - 300 - 524287 - - 220 @@ -70,7 +64,7 @@ 0 - + @@ -86,12 +80,6 @@ 0 - - - 300 - 16777215 - - 220 @@ -176,7 +164,7 @@ - + @@ -339,7 +327,7 @@ false - 25 + 30 @@ -350,7 +338,7 @@ Qt::Vertical - + @@ -361,12 +349,12 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised - + 6 @@ -379,504 +367,485 @@ 6 - - - - 1 + + + + + 150 + 16777215 + - - - - - 16777215 - 16777215 - - - - Qt::ClickFocus - - - - Paragraph - - - - - Heading 1 - - - - - Heading 2 - - - - - Heading 2 - - - - - Heading 3 - - - - - Heading 4 - - - - - Heading 5 - - - - - Heading 6 - - - + + Qt::ClickFocus + + + + Paragraph + - - - - - 100 - 16777215 - - - - Qt::ClickFocus - - + + + Heading 1 + - - - - - 45 - 16777215 - - - - Qt::ClickFocus - - - Font size - - - - 22 - 22 - - - + + + Heading 2 + - - - - - 1677 - 1677 - - - - Qt::NoFocus - - - Increase font size - - - - - - - :/icons/textedit/font-increase.png:/icons/textedit/font-increase.png - - - - 24 - 24 - - - - true - - + + + Heading 2 + - - - - - 167 - 167 - - - - Qt::NoFocus - - - Decrease font size - - - - - - - :/icons/textedit/font-decrease.png:/icons/textedit/font-decrease.png - - - - 24 - 24 - - - - true - - + + + Heading 3 + - - - - - 0 - 0 - - - - - 1677 - 1677 - - - - Qt::NoFocus - - - Bold - - - - - - - :/icons/textedit/bold.png:/icons/textedit/bold.png - - - - 24 - 24 - - - - true - - - true - - + + + Heading 4 + - - - - - 0 - 0 - - - - - 167 - 167 - - - - Qt::NoFocus - - - Italic - - - - - - - :/icons/textedit/italic.png:/icons/textedit/italic.png - - - - 24 - 24 - - - - true - - - true - - + + + Heading 5 + - - - - - 0 - 0 - - - - - 167 - 167 - - - - Qt::NoFocus - - - Add an Image - - - - - - - :/icons/textedit/photo-of-a-landscape.png:/icons/textedit/photo-of-a-landscape.png - - - - 24 - 24 - - - - true - - + + + Heading 6 + - - - - - 0 - 0 - - - - - 167 - 167 - - - - Qt::NoFocus - - - Alignment - - - - - - - :/icons/textedit/align.png:/icons/textedit/align.png - - - - 24 - 24 - - - - QToolButton::InstantPopup - - - true - - - - - - - Qt::NoFocus - - - Sets text font to code style - - - - - - - :/icons/textedit/code.png:/icons/textedit/code.png - - - - 24 - 24 - - - - true - - - - - - - Qt::Horizontal - - - - 20 - 24 - - - - - - - - - 0 - 0 - - - - - 167 - 167 - - - - Qt::NoFocus - - - Underline - - - - - - - :/icons/textedit/underline.png:/icons/textedit/underline.png - - - - 24 - 24 - - - - true - - - true - - - - - - - Qt::NoFocus - - - - :/icons/textedit/smile.png:/icons/textedit/smile.png - - - - 24 - 24 - - - - true - - - - - - - - 0 - 0 - - - - - 167 - 167 - - - - Qt::NoFocus - - - Set Text color - - - - - - true - - - - - - - Set Text background color - - - - - - false - - - true - - - - - - - - - - - :/icons/textedit/numberd-list.png:/icons/textedit/numberd-list.png - - - - 24 - 24 - - - - false - - - QToolButton::InstantPopup - - - true - - - - + + + + + + Qt::ClickFocus + + + + + + + + 0 + 0 + + + + Qt::ClickFocus + + + Font size + + + + + + + Qt::NoFocus + + + Set Text color + + + + + + true + + + + + + + Qt::NoFocus + + + Set Text background color + + + + + + false + + + true + + + + + + + + 1677 + 1677 + + + + Qt::NoFocus + + + Increase font size + + + + + + + :/icons/textedit/font-increase.png:/icons/textedit/font-increase.png + + + + 24 + 24 + + + + true + + + + + + + + 167 + 167 + + + + Qt::NoFocus + + + Decrease font size + + + + + + + :/icons/textedit/font-decrease.png:/icons/textedit/font-decrease.png + + + + 24 + 24 + + + + true + + + + + + + + 0 + 0 + + + + + 1677 + 1677 + + + + Qt::NoFocus + + + Bold + + + + + + + :/icons/textedit/bold.png:/icons/textedit/bold.png + + + + 24 + 24 + + + + true + + + true + + + + + + + + 0 + 0 + + + + + 167 + 167 + + + + Qt::NoFocus + + + Underline + + + + + + + :/icons/textedit/underline.png:/icons/textedit/underline.png + + + + 24 + 24 + + + + true + + + true + + + + + + + + 0 + 0 + + + + + 167 + 167 + + + + Qt::NoFocus + + + Italic + + + + + + + :/icons/textedit/italic.png:/icons/textedit/italic.png + + + + 24 + 24 + + + + true + + + true + + + + + + + Qt::NoFocus + + + Sets text font to code style + + + + + + + :/icons/textedit/code.png:/icons/textedit/code.png + + + + 24 + 24 + + + + true + + + + + + + + + + + :/icons/textedit/numberd-list.png:/icons/textedit/numberd-list.png + + + + 24 + 24 + + + + false + + + QToolButton::InstantPopup + + + true + + + + + + + + 0 + 0 + + + + + 167 + 167 + + + + Qt::NoFocus + + + Alignment + + + + + + + :/icons/textedit/align.png:/icons/textedit/align.png + + + + 24 + 24 + + + + QToolButton::InstantPopup + + + true + + + + + + + + 0 + 0 + + + + + 167 + 167 + + + + Qt::NoFocus + + + Add an Image + + + + + + + :/icons/textedit/photo-of-a-landscape.png:/icons/textedit/photo-of-a-landscape.png + + + + 24 + 24 + + + + true + + + + + + + Qt::NoFocus + + + + :/icons/textedit/smile.png:/icons/textedit/smile.png + + + + 24 + 24 + + + + true + + + + + + + Qt::Horizontal + + + + 20 + 24 + + + - + + + + + 0 + 0 + 0 + + + @@ -897,6 +866,15 @@ + + + + 0 + 0 + 0 + + + @@ -917,6 +895,15 @@ + + + + 154 + 154 + 154 + + + @@ -947,7 +934,7 @@ QFrame::Box - + 6 @@ -961,7 +948,7 @@ 6 - + 16 @@ -980,7 +967,7 @@ - + Distant messages stay into your Outbox until an acknowledgement of receipt has been received. @@ -990,7 +977,7 @@ - + 16 @@ -1027,10 +1014,19 @@ border-image: url(:/images/closepressed.png) - + + + + + 0 + 0 + 0 + + + @@ -1051,6 +1047,15 @@ border-image: url(:/images/closepressed.png) + + + + 0 + 0 + 0 + + + @@ -1071,6 +1076,15 @@ border-image: url(:/images/closepressed.png) + + + + 154 + 154 + 154 + + + @@ -1101,7 +1115,7 @@ border-image: url(:/images/closepressed.png) QFrame::Box - + 6 @@ -1115,7 +1129,7 @@ border-image: url(:/images/closepressed.png) 6 - + 16 @@ -1134,7 +1148,7 @@ border-image: url(:/images/closepressed.png) - + Sending messages to more than 20 people at once is not recommended. If you need to send invites, dedicated forums is what you need. @@ -1144,7 +1158,7 @@ border-image: url(:/images/closepressed.png) - + 16 @@ -1284,7 +1298,7 @@ border-image: url(:/images/closepressed.png) 0 0 - 1008 + 1215 25 @@ -1386,6 +1400,17 @@ border-image: url(:/images/closepressed.png) + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    + + FriendSelectionWidget + QWidget +
    gui/common/FriendSelectionWidget.h
    + 1 +
    GxsIdChooser QComboBox @@ -1396,12 +1421,6 @@ border-image: url(:/images/closepressed.png) QTextEdit
    gui/common/MimeTextEdit.h
    - - FriendSelectionWidget - QWidget -
    gui/common/FriendSelectionWidget.h
    - 1 -
    HashBox QScrollArea diff --git a/retroshare-gui/src/gui/msgs/MessageModel.cpp b/retroshare-gui/src/gui/msgs/MessageModel.cpp index 3d3367553..dc2f16c7c 100644 --- a/retroshare-gui/src/gui/msgs/MessageModel.cpp +++ b/retroshare-gui/src/gui/msgs/MessageModel.cpp @@ -53,10 +53,11 @@ const QString RsMessageModel::FilterString("filtered"); RsMessageModel::RsMessageModel(QObject *parent) : QAbstractItemModel(parent) { - mCurrentBox = BOX_NONE; + mCurrentBox = Rs::Msgs::BoxName::BOX_NONE; mQuickViewFilter = QUICK_VIEW_ALL; mFilterType = FILTER_TYPE_NONE; mFilterStrings.clear(); + mFont = QApplication::font(); } void RsMessageModel::preMods() @@ -88,7 +89,7 @@ int RsMessageModel::rowCount(const QModelIndex& parent) const int RsMessageModel::columnCount(const QModelIndex &/*parent*/) const { - return COLUMN_THREAD_NB_COLUMNS ; + return COLUMN_THREAD_NB_COLUMNS; } bool RsMessageModel::getMessageData(const QModelIndex& i,Rs::Msgs::MessageInfo& fmpe) const @@ -167,7 +168,8 @@ QVariant RsMessageModel::headerData(int section, Qt::Orientation /*orientation*/ { case COLUMN_THREAD_DATE: return tr("Date"); case COLUMN_THREAD_AUTHOR: return tr("From"); - case COLUMN_THREAD_SUBJECT: return tr("Subject"); + case COLUMN_THREAD_TO: return tr("To"); + case COLUMN_THREAD_SUBJECT: return tr("Subject"); case COLUMN_THREAD_TAGS: return tr("Tags"); default: return QVariant(); @@ -189,8 +191,9 @@ QVariant RsMessageModel::headerData(int section, Qt::Orientation /*orientation*/ { case COLUMN_THREAD_ATTACHMENT: return tr("Click to sort by attachments"); case COLUMN_THREAD_SUBJECT: return tr("Click to sort by subject"); - case COLUMN_THREAD_READ: return tr("Click to sort by read"); - case COLUMN_THREAD_AUTHOR: return tr("Click to sort by from"); + case COLUMN_THREAD_READ: return tr("Click to sort by read status"); + case COLUMN_THREAD_AUTHOR: return tr("Click to sort by author"); + case COLUMN_THREAD_TO: return tr("Click to sort by destination"); case COLUMN_THREAD_DATE: return tr("Click to sort by date"); case COLUMN_THREAD_TAGS: return tr("Click to sort by tags"); case COLUMN_THREAD_STAR: return tr("Click to sort by star"); @@ -207,6 +210,8 @@ QVariant RsMessageModel::data(const QModelIndex &index, int role) const std::cerr << "calling data(" << index << ") role=" << role << std::endl; #endif + int coln = index.column(); + if(!index.isValid()) return QVariant(); @@ -244,11 +249,19 @@ QVariant RsMessageModel::data(const QModelIndex &index, int role) const if(role == Qt::FontRole) { - QFont font ; + QFont font = mFont; font.setBold(fmpe.msgflags & (RS_MSG_NEW | RS_MSG_UNREAD_BY_USER)); return QVariant(font); } + + if (role == Qt::TextAlignmentRole) + { + if((coln == COLUMN_THREAD_ATTACHMENT)) + return int( Qt::AlignHCenter | Qt::AlignVCenter); + else + return QVariant(); + } #ifdef DEBUG_MESSAGE_MODEL std::cerr << " [ok]" << std::endl; @@ -269,7 +282,7 @@ QVariant RsMessageModel::data(const QModelIndex &index, int role) const case MsgFlagsRole: return fmpe.msgflags ; case UnreadRole: return fmpe.msgflags & (RS_MSG_NEW | RS_MSG_UNREAD_BY_USER); case MsgIdRole: return QString::fromStdString(fmpe.msgId) ; - case SrcIdRole: return QString::fromStdString(fmpe.srcId.toStdString()) ; + case SrcIdRole: return QString::fromStdString(fmpe.from.toStdString()) ; default: return QVariant(); } @@ -312,6 +325,11 @@ bool RsMessageModel::passesFilter(const Rs::Msgs::MsgInfoSummary& fmpe,int /*col if(s.isNull()) passes_strings = false; break; + case FILTER_TYPE_TO: s = sortRole(fmpe,COLUMN_THREAD_TO).toString(); + if(s.isNull()) + passes_strings = false; + break; + case FILTER_TYPE_DATE: s = displayRole(fmpe,COLUMN_THREAD_DATE).toString(); break; case FILTER_TYPE_CONTENT: { @@ -380,30 +398,44 @@ void RsMessageModel::setFilter(FilterType filter_type, const QStringList& string std::cerr << std::endl; #endif - preMods(); - mFilterType = filter_type; mFilterStrings = strings; - postMods(); + if(rowCount() > 0) + emit dataChanged(createIndex(0,0),createIndex(rowCount()-1,RsMessageModel::columnCount()-1)); +} + +void RsMessageModel::setFont(const QFont &font) +{ + mFont = font; + + if (rowCount() > 0) { + emit dataChanged(createIndex(0,0), createIndex(rowCount() - 1, RsMessageModel::columnCount() - 1)); + } } QVariant RsMessageModel::toolTipRole(const Rs::Msgs::MsgInfoSummary& fmpe,int column) const { - if(column == COLUMN_THREAD_AUTHOR) + if(column == COLUMN_THREAD_AUTHOR || column == COLUMN_THREAD_TO) { QString str,comment ; QList icons; - if(!GxsIdDetails::MakeIdDesc(RsGxsId(fmpe.srcId.toStdString()), true, str, icons, comment,GxsIdDetails::ICON_TYPE_AVATAR)) + if(column == COLUMN_THREAD_AUTHOR && !GxsIdDetails::MakeIdDesc(RsGxsId(fmpe.from.toStdString()), true, str, icons, comment,GxsIdDetails::ICON_TYPE_AVATAR)) return QVariant(); - int S = QFontMetricsF(QApplication::font()).height(); - QImage pix( (*icons.begin()).pixmap(QSize(4*S,4*S)).toImage()); + if(column == COLUMN_THREAD_TO && !GxsIdDetails::MakeIdDesc(RsGxsId(fmpe.to.toStdString()), true, str, icons, comment,GxsIdDetails::ICON_TYPE_AVATAR)) + return QVariant(); + + int S = QFontMetricsF(QApplication::font()).height(); + QImage pix( (*icons.begin()).pixmap(QSize(5*S,5*S)).toImage()); QString embeddedImage; - if(RsHtml::makeEmbeddedImage(pix.scaled(QSize(4*S,4*S), Qt::KeepAspectRatio, Qt::SmoothTransformation), embeddedImage, 8*S * 8*S)) + if(RsHtml::makeEmbeddedImage(pix.scaled(QSize(5*S,5*S), Qt::KeepAspectRatio, Qt::SmoothTransformation), embeddedImage, -1)) + { + embeddedImage.insert(embeddedImage.indexOf("src="), "style=\"float:left\" "); comment = "
    " + embeddedImage + "" + comment + "
    "; + } return comment; } @@ -418,7 +450,7 @@ QVariant RsMessageModel::backgroundRole(const Rs::Msgs::MsgInfoSummary &/*fmpe*/ QVariant RsMessageModel::sizeHintRole(int col) const { - float factor = QFontMetricsF(QApplication::font()).height()/14.0f ; + float factor = QFontMetricsF(mFont).height()/14.0f ; switch(col) { @@ -426,7 +458,8 @@ QVariant RsMessageModel::sizeHintRole(int col) const case COLUMN_THREAD_SUBJECT: return QVariant( QSize(factor * 170, factor*14 )); case COLUMN_THREAD_DATE: return QVariant( QSize(factor * 75 , factor*14 )); case COLUMN_THREAD_AUTHOR: return QVariant( QSize(factor * 75 , factor*14 )); - } + case COLUMN_THREAD_TO: return QVariant( QSize(factor * 75 , factor*14 )); + } } QVariant RsMessageModel::authorRole(const Rs::Msgs::MsgInfoSummary& /*fmpe*/,int /*column*/) const @@ -446,84 +479,138 @@ QVariant RsMessageModel::sortRole(const Rs::Msgs::MsgInfoSummary& fmpe,int colum case COLUMN_THREAD_SPAM: return QVariant((fmpe.msgflags & RS_MSG_SPAM)? 1:0); - case COLUMN_THREAD_AUTHOR:{ + case COLUMN_THREAD_AUTHOR:{ QString name; - if(GxsIdTreeItemDelegate::computeName(RsGxsId(fmpe.srcId.toStdString()),name)) + if(GxsIdTreeItemDelegate::computeName(RsGxsId(fmpe.from.toStdString()),name)) return name; return ""; //Not Found } - default: - return displayRole(fmpe,column); + + case COLUMN_THREAD_TO: // fallthrough. In this case, the "to" field is not filled because the msg potentially has multiple destinations. + default: + return displayRole(fmpe,column); } } QVariant RsMessageModel::displayRole(const Rs::Msgs::MsgInfoSummary& fmpe,int col) const { - switch(col) - { - case COLUMN_THREAD_SUBJECT: return QVariant(QString::fromUtf8(fmpe.title.c_str())); - case COLUMN_THREAD_ATTACHMENT:return QVariant(QString::number(fmpe.count)); + switch(col) + { + case COLUMN_THREAD_SUBJECT: return QVariant(QString::fromUtf8(fmpe.title.c_str())); + case COLUMN_THREAD_ATTACHMENT:return QVariant(QString::number(fmpe.count)); - case COLUMN_THREAD_STAR: - case COLUMN_THREAD_SPAM: - case COLUMN_THREAD_READ:return QVariant(); - case COLUMN_THREAD_DATE:{ - QDateTime qtime; - qtime.setTime_t(fmpe.ts); + case COLUMN_THREAD_STAR: + case COLUMN_THREAD_SPAM: + case COLUMN_THREAD_READ:return QVariant(); + case COLUMN_THREAD_DATE:{ + QDateTime qtime; + qtime.setTime_t(fmpe.ts); - return QVariant(DateTime::formatDateTime(qtime)); - } + return QVariant(DateTime::formatDateTime(qtime)); + } - case COLUMN_THREAD_TAGS:{ - // Tags - Rs::Msgs::MsgTagInfo tagInfo; - rsMsgs->getMessageTag(fmpe.msgId, tagInfo); + case COLUMN_THREAD_TAGS:{ + // Tags + Rs::Msgs::MsgTagInfo tagInfo; + rsMsgs->getMessageTag(fmpe.msgId, tagInfo); - Rs::Msgs::MsgTagType Tags; - rsMsgs->getMessageTagTypes(Tags); + Rs::Msgs::MsgTagType Tags; + rsMsgs->getMessageTagTypes(Tags); - QString text; + QString text; - // build tag names - for (auto tagit = tagInfo.tagIds.begin(); tagit != tagInfo.tagIds.end(); ++tagit) - { - if (!text.isNull()) - text += ","; + // build tag names + for (auto tag:tagInfo) + { + if (!text.isNull()) + text += ","; - auto Tag = Tags.types.find(*tagit); + auto Tag = Tags.types.find(tag); - if (Tag != Tags.types.end()) - text += TagDefs::name(Tag->first, Tag->second.first); - else - RS_WARN("Unknown tag ", (int)Tag->first, " in message ", fmpe.msgId); - } - return text; - } - case COLUMN_THREAD_AUTHOR:{ - QString name; - RsGxsId id = RsGxsId(fmpe.srcId.toStdString()); + if (Tag != Tags.types.end()) + text += TagDefs::name(Tag->first, Tag->second.first); + else + RS_WARN("Unknown tag ", (int)Tag->first, " in message ", fmpe.msgId); + } + return text; + } + case COLUMN_THREAD_TO: { + QString name; - if(id.isNull()) - return QVariant(tr("[Notification]")); - if(GxsIdTreeItemDelegate::computeName(id,name)) - return name; - return QVariant(tr("[Unknown]")); - } + switch(mCurrentBox) + { + case Rs::Msgs::BoxName::BOX_DRAFTS: // in this case, we display the full list of destinations + case Rs::Msgs::BoxName::BOX_TRASH: // in this case, we display the full list of destinations + case Rs::Msgs::BoxName::BOX_SENT: // in this case, we display the full list of destinations + { + for(auto d:fmpe.destinations) + { + QString tmp; + GxsIdTreeItemDelegate::computeName(RsGxsId(d.toStdString()),tmp); // not nice, but works. + if(tmp.isNull()) + name += QString(tr("[Notification]") + ", "); + else + name += tmp + ", " ; + } + name.chop(2); + return name; + } + break; + case Rs::Msgs::BoxName::BOX_NONE: // in these cases, we display the actual destination + case Rs::Msgs::BoxName::BOX_INBOX: // in these cases, we display the actual destination + case Rs::Msgs::BoxName::BOX_OUTBOX: + { + RsGxsId id = RsGxsId(fmpe.to.toStdString()); // use "to" field, which is populated in Outbox, . + if(id.isNull()) + return QVariant(tr("[Notification]")); + else + { + GxsIdTreeItemDelegate::computeName(id,name); + return name; + } + } + break; + } + } + break; - default: - return QVariant("[ TODO ]"); - } + case COLUMN_THREAD_AUTHOR:{ + QString name; + RsGxsId id = RsGxsId(fmpe.from.toStdString()); - return QVariant("[ERROR]"); + if(id.isNull()) + return QVariant(tr("[Notification]")); + if(GxsIdTreeItemDelegate::computeName(id,name)) + return name; + return QVariant(tr("[Unknown]")); + } + + default: + return QVariant("[ TODO ]"); + } + + return QVariant("[ERROR]"); } QVariant RsMessageModel::userRole(const Rs::Msgs::MsgInfoSummary& fmpe,int col) const { switch(col) { - case COLUMN_THREAD_AUTHOR: return QVariant(QString::fromStdString(fmpe.srcId.toStdString())); - case COLUMN_THREAD_MSGID: return QVariant(QString::fromStdString(fmpe.msgId)); + case COLUMN_THREAD_AUTHOR: return QVariant(QString::fromStdString(fmpe.from.toStdString())); + case COLUMN_THREAD_MSGID: return QVariant(QString::fromStdString(fmpe.msgId)); + case COLUMN_THREAD_TO: + { + // First check if the .to field is filled. + + if(!fmpe.to.toStdString().empty()) + return QVariant(QString::fromStdString(fmpe.to.toStdString())); + + // In the Send box, .to is never filled. In this case we look into destinations. + + if(fmpe.destinations.size()==1) + return QVariant(QString::fromStdString((*fmpe.destinations.begin()).toStdString())); + } default: return QVariant(); } @@ -541,8 +628,8 @@ QVariant RsMessageModel::decorationRole(const Rs::Msgs::MsgInfoSummary& fmpe,int case COLUMN_THREAD_SUBJECT: { if(fmpe.msgflags & RS_MSG_NEW ) return FilesDefs::getIconFromQtResourcePath(":/images/message-state-new.png"); - if(fmpe.msgflags & RS_MSG_USER_REQUEST) return FilesDefs::getIconFromQtResourcePath(":/images/user/user_request16.png"); - if(fmpe.msgflags & RS_MSG_FRIEND_RECOMMENDATION) return FilesDefs::getIconFromQtResourcePath(":/images/user/friend_suggestion16.png"); + if(fmpe.msgflags & RS_MSG_USER_REQUEST) return FilesDefs::getIconFromQtResourcePath(":/images/user/user_request48.png"); + if(fmpe.msgflags & RS_MSG_FRIEND_RECOMMENDATION) return FilesDefs::getIconFromQtResourcePath(":/images/user/invite24.png"); if(fmpe.msgflags & RS_MSG_PUBLISH_KEY) return FilesDefs::getIconFromQtResourcePath(":/images/share-icon-16.png"); if(fmpe.msgflags & RS_MSG_UNREAD_BY_USER) @@ -566,8 +653,10 @@ QVariant RsMessageModel::decorationRole(const Rs::Msgs::MsgInfoSummary& fmpe,int case COLUMN_THREAD_SPAM: return FilesDefs::getIconFromQtResourcePath((fmpe.msgflags & RS_MSG_SPAM) ? (IMAGE_SPAM_ON ): (IMAGE_SPAM_OFF)); - case COLUMN_THREAD_AUTHOR://Return icon as place holder. - return FilesDefs::getIconFromGxsIdCache(RsGxsId(fmpe.srcId.toStdString()),QIcon(), exist); + case COLUMN_THREAD_TO://Return icon as place holder. + return FilesDefs::getIconFromGxsIdCache(RsGxsId(fmpe.to.toStdString()),QIcon(), exist); + case COLUMN_THREAD_AUTHOR://Return icon as place holder. + return FilesDefs::getIconFromGxsIdCache(RsGxsId(fmpe.from.toStdString()),QIcon(), exist); } return QVariant(); } @@ -594,7 +683,7 @@ void RsMessageModel::setMessages(const std::list& msgs for(auto it(msgs.begin());it!=msgs.end();++it) { mMessagesMap[(*it).msgId] = mMessages.size(); - mMessages.push_back(*it); + mMessages.push_back(*it); } // now update prow for all posts @@ -612,7 +701,7 @@ void RsMessageModel::setMessages(const std::list& msgs emit messagesLoaded(); } -void RsMessageModel::setCurrentBox(BoxName bn) +void RsMessageModel::setCurrentBox(Rs::Msgs::BoxName bn) { if(mCurrentBox != bn) { @@ -621,6 +710,10 @@ void RsMessageModel::setCurrentBox(BoxName bn) } } +Rs::Msgs::BoxName RsMessageModel::currentBox() const +{ + return mCurrentBox; +} void RsMessageModel::setQuickViewFilter(QuickViewFilter fn) { if(fn != mQuickViewFilter) @@ -629,47 +722,20 @@ void RsMessageModel::setQuickViewFilter(QuickViewFilter fn) std::cerr << "Changing new quickview filter to " << fn << std::endl; #endif - mQuickViewFilter = fn ; - updateMessages(); + mQuickViewFilter = fn ; + + if(rowCount() > 0) + emit dataChanged(createIndex(0,0),createIndex(rowCount()-1,RsMessageModel::columnCount()-1)); } } -void RsMessageModel::getMessageSummaries(BoxName box,std::list& msgs) -{ - rsMsgs->getMessageSummaries(msgs); - - // filter out messages that are not in the right box. - - for(auto it(msgs.begin());it!=msgs.end();) - { - bool ok = false; - - switch(box) - { - case BOX_INBOX : ok = (it->msgflags & RS_MSG_BOXMASK) == RS_MSG_INBOX && !(it->msgflags & RS_MSG_TRASH); break ; - case BOX_SENT : ok = (it->msgflags & RS_MSG_BOXMASK) == RS_MSG_SENTBOX && !(it->msgflags & RS_MSG_TRASH); break ; - case BOX_OUTBOX : ok = (it->msgflags & RS_MSG_BOXMASK) == RS_MSG_OUTBOX && !(it->msgflags & RS_MSG_TRASH); break ; - case BOX_DRAFTS : ok = (it->msgflags & RS_MSG_BOXMASK) == RS_MSG_DRAFTBOX && !(it->msgflags & RS_MSG_TRASH); break ; - case BOX_TRASH : ok = (it->msgflags & RS_MSG_TRASH) ; break ; - default: - ++it; - continue; - } - - if(ok) - ++it; - else - it = msgs.erase(it) ; - } -} - void RsMessageModel::updateMessages() { emit messagesAboutToLoad(); std::list msgs; - getMessageSummaries(mCurrentBox,msgs); + rsMsgs->getMessageSummaries(mCurrentBox,msgs); setMessages(msgs); emit messagesLoaded(); diff --git a/retroshare-gui/src/gui/msgs/MessageModel.h b/retroshare-gui/src/gui/msgs/MessageModel.h index 8021c3e24..3bbd6ee31 100644 --- a/retroshare-gui/src/gui/msgs/MessageModel.h +++ b/retroshare-gui/src/gui/msgs/MessageModel.h @@ -22,6 +22,7 @@ #include #include +#include #include "retroshare/rsmsgs.h" @@ -43,28 +44,20 @@ public: explicit RsMessageModel(QObject *parent = NULL); ~RsMessageModel(){} - enum BoxName { - BOX_NONE = 0x00, - BOX_INBOX = 0x01, - BOX_OUTBOX = 0x02, - BOX_DRAFTS = 0x03, - BOX_SENT = 0x04, - BOX_TRASH = 0x05 - }; - enum Columns { COLUMN_THREAD_STAR = 0x00, COLUMN_THREAD_ATTACHMENT = 0x01, COLUMN_THREAD_SUBJECT = 0x02, COLUMN_THREAD_READ = 0x03, COLUMN_THREAD_AUTHOR = 0x04, - COLUMN_THREAD_SPAM = 0x05, - COLUMN_THREAD_DATE = 0x06, - COLUMN_THREAD_TAGS = 0x07, - COLUMN_THREAD_MSGID = 0x08, - COLUMN_THREAD_NB_COLUMNS = 0x09, - COLUMN_THREAD_CONTENT = 0x09 - }; + COLUMN_THREAD_TO = 0x05, + COLUMN_THREAD_SPAM = 0x06, + COLUMN_THREAD_DATE = 0x07, + COLUMN_THREAD_TAGS = 0x08, + COLUMN_THREAD_MSGID = 0x09, + COLUMN_THREAD_CONTENT = 0x0a, + COLUMN_THREAD_NB_COLUMNS = 0x0b + }; enum QuickViewFilter { QUICK_VIEW_ALL = 0x00, @@ -84,10 +77,11 @@ public: FILTER_TYPE_NONE = 0x00, FILTER_TYPE_SUBJECT = 0x01, // These numbers have been carefuly chosen to match the ones in rsmsgs.h FILTER_TYPE_FROM = 0x02, - FILTER_TYPE_DATE = 0x03, - FILTER_TYPE_CONTENT = 0x04, - FILTER_TYPE_TAGS = 0x05, - FILTER_TYPE_ATTACHMENTS = 0x06, + FILTER_TYPE_TO = 0x03, + FILTER_TYPE_DATE = 0x04, + FILTER_TYPE_CONTENT = 0x05, + FILTER_TYPE_TAGS = 0x06, + FILTER_TYPE_ATTACHMENTS = 0x07, }; enum Roles{ SortRole = Qt::UserRole+1, @@ -103,14 +97,15 @@ public: QModelIndex getIndexOfMessage(const std::string &mid) const; static const QString FilterString ; - static void getMessageSummaries(BoxName box, std::list& msgs); // This method will asynchroneously update the data - void setCurrentBox(BoxName bn) ; + void setCurrentBox(Rs::Msgs::BoxName bn) ; + Rs::Msgs::BoxName currentBox() const ; void setQuickViewFilter(QuickViewFilter fn) ; void setFilter(FilterType filter_type, const QStringList& strings) ; + void setFont(const QFont &font); int rowCount(const QModelIndex& parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; @@ -187,10 +182,11 @@ private: QColor mTextColorNotSubscribed ; QColor mTextColorMissing ; - BoxName mCurrentBox ; + Rs::Msgs::BoxName mCurrentBox ; QuickViewFilter mQuickViewFilter ; QStringList mFilterStrings; FilterType mFilterType; + QFont mFont; std::vector mMessages; std::map mMessagesMap; diff --git a/retroshare-gui/src/gui/msgs/MessageUserNotify.cpp b/retroshare-gui/src/gui/msgs/MessageUserNotify.cpp index 071f794ff..b29f264fb 100644 --- a/retroshare-gui/src/gui/msgs/MessageUserNotify.cpp +++ b/retroshare-gui/src/gui/msgs/MessageUserNotify.cpp @@ -22,13 +22,21 @@ #include "MessageUserNotify.h" #include "gui/notifyqt.h" #include "gui/MainWindow.h" +#include "util/qtthreadsutils.h" +#include "gui/settings/rsharesettings.h" #include "gui/msgs/MessageInterface.h" MessageUserNotify::MessageUserNotify(QObject *parent) : UserNotify(parent) { - connect(NotifyQt::getInstance(), SIGNAL(messagesChanged()), this, SLOT(updateIcon())); + mEventHandlerId = 0; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) { RsQThreadUtils::postToObject( [this,event]() { handleEvent_main_thread(event); }); }, mEventHandlerId, RsEventType::MAIL_STATUS ); +} + +MessageUserNotify::~MessageUserNotify() +{ + rsEvents->unregisterEventsHandler(mEventHandlerId); } bool MessageUserNotify::hasSetting(QString *name, QString *group) @@ -72,3 +80,39 @@ void MessageUserNotify::iconClicked() { MainWindow::showWindow(MainWindow::Messages); } + +void MessageUserNotify::handleEvent_main_thread(std::shared_ptr event) +{ + if(event->mType != RsEventType::MAIL_STATUS) { + return; + } + + const RsMailStatusEvent *fe = dynamic_cast(event.get()); + if (!fe) { + return; + } + + std::set::const_iterator it; + + switch (fe->mMailStatusEventCode) + { + case RsMailStatusEventCode::NEW_MESSAGE: + for (it = fe->mChangedMsgIds.begin(); it != fe->mChangedMsgIds.end(); ++it) { + MessageInfo msgInfo; + if (rsMail->getMessage(*it, msgInfo)) { + NotifyQt::getInstance()->addToaster(RS_POPUP_MSG, msgInfo.msgId.c_str(), msgInfo.title.c_str(), msgInfo.msg.c_str() ); + } + } + updateIcon(); + break; + case RsMailStatusEventCode::MESSAGE_CHANGED: + case RsMailStatusEventCode::MESSAGE_REMOVED: + updateIcon(); + break; + case RsMailStatusEventCode::MESSAGE_SENT: + case RsMailStatusEventCode::TAG_CHANGED: + case RsMailStatusEventCode::MESSAGE_RECEIVED_ACK: + case RsMailStatusEventCode::SIGNATURE_FAILED: + break; + } +} diff --git a/retroshare-gui/src/gui/msgs/MessageUserNotify.h b/retroshare-gui/src/gui/msgs/MessageUserNotify.h index 58b30e8fc..f9b7458ab 100644 --- a/retroshare-gui/src/gui/msgs/MessageUserNotify.h +++ b/retroshare-gui/src/gui/msgs/MessageUserNotify.h @@ -21,6 +21,7 @@ #ifndef MESSAGEUSERNOTIFY_H #define MESSAGEUSERNOTIFY_H +#include #include "gui/common/UserNotify.h" class MessageUserNotify : public UserNotify @@ -29,6 +30,7 @@ class MessageUserNotify : public UserNotify public: MessageUserNotify(QObject *parent = 0); + virtual ~MessageUserNotify(); virtual bool hasSetting(QString *name, QString *group) override; @@ -41,6 +43,11 @@ private: virtual QString getNotifyMessage(bool plural) override; virtual void iconClicked() override; + + void handleEvent_main_thread(std::shared_ptr event); + +private: + RsEventsHandlerId_t mEventHandlerId; }; #endif // MESSAGEUSERNOTIFY_H diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.cpp b/retroshare-gui/src/gui/msgs/MessageWidget.cpp index 9b671129f..f4be23597 100644 --- a/retroshare-gui/src/gui/msgs/MessageWidget.cpp +++ b/retroshare-gui/src/gui/msgs/MessageWidget.cpp @@ -46,6 +46,7 @@ #include "util/HandleRichText.h" #include "util/DateTime.h" #include "util/QtVersion.h" +#include "util/qtthreadsutils.h" #include #include @@ -65,7 +66,7 @@ class RsHtmlMsg : public RsHtml { public: - RsHtmlMsg(uint msgFlags) : RsHtml() + explicit RsHtmlMsg(uint msgFlags) : RsHtml() { this->msgFlags = msgFlags; } @@ -134,6 +135,7 @@ MessageWidget::MessageWidget(bool controlled, QWidget *parent, Qt::WindowFlags f isWindow = false; currMsgFlags = 0; expandFiles = false; + ui.expandButton->hide(); ui.actionTextBesideIcon->setData(Qt::ToolButtonTextBesideIcon); ui.actionIconOnly->setData(Qt::ToolButtonIconOnly); @@ -143,7 +145,8 @@ MessageWidget::MessageWidget(bool controlled, QWidget *parent, Qt::WindowFlags f connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(getallrecommended())); connect(ui.msgText, SIGNAL(anchorClicked(QUrl)), this, SLOT(anchorClicked(QUrl))); connect(ui.sendInviteButton, SIGNAL(clicked()), this, SLOT(sendInvite())); - + connect(ui.expandButton, SIGNAL(clicked()), this, SLOT(expandTo())); + connect(ui.replyButton, SIGNAL(clicked()), this, SLOT(reply())); connect(ui.replyallButton, SIGNAL(clicked()), this, SLOT(replyAll())); connect(ui.forwardButton, SIGNAL(clicked()), this, SLOT(forward())); @@ -159,9 +162,6 @@ MessageWidget::MessageWidget(bool controlled, QWidget *parent, Qt::WindowFlags f viewsource->setShortcut(QKeySequence("CTRL+O")); connect(viewsource, SIGNAL(triggered()), this, SLOT(viewSource())); - connect(NotifyQt::getInstance(), SIGNAL(messagesTagsChanged()), this, SLOT(messagesTagsChanged())); - connect(NotifyQt::getInstance(), SIGNAL(messagesChanged()), this, SLOT(messagesChanged())); - ui.imageBlockWidget->addButtonAction(tr("Load images always for this message"), this, SLOT(loadImagesAlways()), true); ui.msgText->setImageBlockWidget(ui.imageBlockWidget); @@ -192,13 +192,13 @@ MessageWidget::MessageWidget(bool controlled, QWidget *parent, Qt::WindowFlags f QFont font = QFont("Arial", 10, QFont::Bold); ui.subjectText->setFont(font); - ui.toText->setMaximumHeight(ui.toText->fontMetrics().lineSpacing()*1.5); + ui.trans_ToText->setMaximumHeight(ui.trans_ToText->fontMetrics().lineSpacing()*1.5); ui.ccLabel->setVisible(false); - ui.ccText->setVisible(false); - ui.ccText->setMaximumHeight(ui.ccText->fontMetrics().lineSpacing()*1.5); + ui.trans_CCText->setVisible(false); + ui.trans_CCText->setMaximumHeight(ui.trans_CCText->fontMetrics().lineSpacing()*1.5); ui.bccLabel->setVisible(false); - ui.bccText->setVisible(false); - ui.bccText->setMaximumHeight(ui.bccText->fontMetrics().lineSpacing()*1.5); + ui.trans_BCCText->setVisible(false); + ui.trans_BCCText->setMaximumHeight(ui.trans_BCCText->fontMetrics().lineSpacing()*1.5); ui.tagsLabel->setVisible(false); @@ -210,7 +210,10 @@ MessageWidget::MessageWidget(bool controlled, QWidget *parent, Qt::WindowFlags f ui.dateText-> setText(""); - ui.inviteFrame->hide(); + ui.info_Frame_Invite->hide(); + + mEventHandlerId = 0; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) { RsQThreadUtils::postToObject( [this,event]() { handleEvent_main_thread(event); }); }, mEventHandlerId, RsEventType::MAIL_STATUS ); } MessageWidget::~MessageWidget() @@ -218,6 +221,47 @@ MessageWidget::~MessageWidget() if (isControlled == false) { processSettings("MessageWidget", false); } + + rsEvents->unregisterEventsHandler(mEventHandlerId); +} + +void MessageWidget::handleEvent_main_thread(std::shared_ptr event) +{ + if(event->mType != RsEventType::MAIL_STATUS) { + return; + } + + const RsMailStatusEvent *fe = dynamic_cast(event.get()); + if (!fe) { + return; + } + + switch (fe->mMailStatusEventCode) { + case RsMailStatusEventCode::MESSAGE_REMOVED: + if (fe->mChangedMsgIds.find(currMsgId) != fe->mChangedMsgIds.end()) { + if (isControlled) { + /* processed by MessagesDialog */ + return; + } + + /* messages was removed */ + if (isWindow) { + window()->close(); + } else { + deleteLater(); + } + } + break; + case RsMailStatusEventCode::TAG_CHANGED: + messagesTagsChanged(); + break; + case RsMailStatusEventCode::MESSAGE_SENT: + case RsMailStatusEventCode::MESSAGE_CHANGED: + case RsMailStatusEventCode::NEW_MESSAGE: + case RsMailStatusEventCode::MESSAGE_RECEIVED_ACK: + case RsMailStatusEventCode::SIGNATURE_FAILED: + break; + } } void MessageWidget::connectAction(enumActionType actionType, QToolButton* button) @@ -349,24 +393,25 @@ void MessageWidget::getcurrentrecommended() } std::list srcIds; - srcIds.push_back(msgInfo.rspeerid_srcId); + if(msgInfo.from.type()==MsgAddress::MSG_ADDRESS_TYPE_RSPEERID) + srcIds.push_back(msgInfo.from.toRsPeerId()); QModelIndexList list = ui.msgList->selectionModel()->selectedIndexes(); std::map files ; - for (QModelIndexList::const_iterator it(list.begin());it!=list.end();++it) { - FileInfo& fi(files[it->row()]) ; + for (auto &it : list) { + FileInfo& fi(files[it.row()]) ; - switch (it->column()) { + switch (it.column()) { case COLUMN_FILE_NAME: - fi.fname = it->data().toString().toUtf8().constData(); + fi.fname = it.data().toString().toUtf8().constData(); break ; case COLUMN_FILE_SIZE: - fi.size = it->data(Qt::UserRole).toULongLong() ; + fi.size = it.data(Qt::UserRole).toULongLong() ; break ; case COLUMN_FILE_HASH: - fi.hash = RsFileHash(it->data().toString().toStdString()) ; + fi.hash = RsFileHash(it.data().toString().toStdString()) ; break ; } } @@ -397,7 +442,10 @@ void MessageWidget::getallrecommended() for(it = recList.begin(); it != recList.end(); ++it) { std::cerr << "MessageWidget::getallrecommended() Calling File Request" << std::endl; std::list srcIds; - srcIds.push_back(msgInfo.rspeerid_srcId); + + if(msgInfo.from.type()==MsgAddress::MSG_ADDRESS_TYPE_RSPEERID) + srcIds.push_back(msgInfo.from.toRsPeerId()); + rsFiles->FileRequest(it->fname, it->hash, it->size, "", RS_FILE_REQ_ANONYMOUS_ROUTING, srcIds); } } @@ -407,25 +455,6 @@ void MessageWidget::messagesTagsChanged() showTagLabels(); } -void MessageWidget::messagesChanged() -{ - if (isControlled) { - /* processed by MessagesDialog */ - return; - } - - /* test Message */ - MessageInfo msgInfo; - if (rsMail->getMessage(currMsgId, msgInfo) == false) { - /* messages was removed */ - if (isWindow) { - window()->close(); - } else { - deleteLater(); - } - } -} - void MessageWidget::clearTagLabels() { /* clear all tags */ @@ -448,15 +477,17 @@ void MessageWidget::showTagLabels() MsgTagInfo tagInfo; rsMail->getMessageTag(currMsgId, tagInfo); - if (tagInfo.tagIds.empty() == false) { + if (!tagInfo.empty()) + { ui.tagsLabel->setVisible(true); MsgTagType Tags; rsMail->getMessageTagTypes(Tags); std::map >::iterator Tag; - for (std::list::iterator tagId = tagInfo.tagIds.begin(); tagId != tagInfo.tagIds.end(); ++tagId) { - Tag = Tags.types.find(*tagId); + for (auto tag:tagInfo) + { + Tag = Tags.types.find(tag); if (Tag != Tags.types.end()) { QLabel *tagLabel = new QLabel(TagDefs::name(Tag->first, Tag->second.first), this); tagLabel->setMaximumHeight(16); @@ -491,17 +522,17 @@ void MessageWidget::fill(const std::string &msgId) if (currMsgId.empty()) { /* blank it */ ui.dateText-> setText(""); - ui.toText->setText(""); + ui.trans_ToText->setText(""); ui.fromText->setText(""); ui.filesText->setText(""); ui.ccLabel->setVisible(false); - ui.ccText->setVisible(false); - ui.ccText->clear(); + ui.trans_CCText->setVisible(false); + ui.trans_CCText->clear(); ui.bccLabel->setVisible(false); - ui.bccText->setVisible(false); - ui.bccText->clear(); + ui.trans_BCCText->setVisible(false); + ui.trans_BCCText->clear(); ui.subjectText->setText(""); ui.msgList->clear(); @@ -511,7 +542,7 @@ void MessageWidget::fill(const std::string &msgId) clearTagLabels(); checkLength(); - ui.inviteFrame->hide(); + ui.info_Frame_Invite->hide(); ui.expandFilesButton->setChecked(false); ui.downloadButton->setEnabled(false); togglefileview(true); @@ -522,6 +553,9 @@ void MessageWidget::fill(const std::string &msgId) ui.deleteButton->setEnabled(false); ui.moreButton->setEnabled(false); + ui.expandButton->hide(); + ui.trans_ToText->setMaximumHeight(ui.trans_ToText->fontMetrics().lineSpacing()*1.5); + currMsgFlags = 0; return; @@ -542,17 +576,21 @@ void MessageWidget::fill(const std::string &msgId) return; } - if ((msgInfo.msgflags & RS_MSG_USER_REQUEST) && msgInfo.rsgxsid_srcId.isNull()){ - ui.inviteFrame->show(); - ui.sendInviteButton->hide(); - ui.infoLabel->setText(tr("You got an invite to make friend! You may accept this request.")); - } else if ((msgInfo.msgflags & RS_MSG_USER_REQUEST) && (!msgInfo.rsgxsid_srcId.isNull())){ - ui.inviteFrame->show(); - ui.sendInviteButton->show(); - ui.infoLabel->setText(tr("You got an invite to make friend! You may accept this request and send your own Certificate back")); - } else { - ui.inviteFrame->hide(); - } + if (msgInfo.msgflags & RS_MSG_USER_REQUEST) + if(msgInfo.from.type() == MsgAddress::MSG_ADDRESS_TYPE_RSPEERID) + { + ui.info_Frame_Invite->show(); + ui.sendInviteButton->hide(); + ui.infoLabel_Invite->setText(tr("You got an invite to make friend! You may accept this request.")); + } + else + { + ui.info_Frame_Invite->show(); + ui.sendInviteButton->show(); + ui.infoLabel_Invite->setText(tr("You got an invite to make friend! You may accept this request and send your own Certificate back")); + } + else + ui.info_Frame_Invite->hide(); const std::list &recList = msgInfo.files; std::list::const_iterator it; @@ -581,67 +619,60 @@ void MessageWidget::fill(const std::string &msgId) /* iterate through the sources */ RetroShareLink link; - QString text; + QString to_text,cc_text,bcc_text; - for(std::set::const_iterator pit = msgInfo.rspeerid_msgto.begin(); pit != msgInfo.rspeerid_msgto.end(); ++pit) { - link = RetroShareLink::createMessage(*pit, ""); - if (link.valid()) - text += link.toHtml() + " "; - } - for(std::set::const_iterator pit = msgInfo.rsgxsid_msgto.begin(); pit != msgInfo.rsgxsid_msgto.end(); ++pit) { - link = RetroShareLink::createMessage(*pit, ""); - if (link.valid()) - text += link.toHtml() + " "; - } - - ui.toText->setText(text); - - if (!msgInfo.rspeerid_msgcc.empty() || !msgInfo.rsgxsid_msgcc.empty()) + for(auto m:msgInfo.destinations) { + if(m.type()==MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) + link = RetroShareLink::createMessage(m.toGxsId(), ""); + else + link = RetroShareLink::createMessage(m.toRsPeerId(), ""); + + if (link.valid()) + switch(m.mode()) + { + case MsgAddress::MSG_ADDRESS_MODE_TO: to_text += link.toHtml() + " "; break; + case MsgAddress::MSG_ADDRESS_MODE_CC: cc_text += link.toHtml() + " "; break; + case MsgAddress::MSG_ADDRESS_MODE_BCC: bcc_text += link.toHtml() + " "; break; + default: break; + } + } + + ui.trans_ToText->setText(to_text); + + int recipientsCount = ui.trans_ToText->toPlainText().split(QRegExp("(\\s|\\n|\\r)+"), QtSkipEmptyParts).count(); + ui.expandButton->setText( QString::number(recipientsCount)+ " " + tr("more")); + + if (recipientsCount >=20) { + ui.expandButton->show(); + } else { + ui.expandButton->hide(); + ui.expandButton->setChecked(false); + ui.trans_ToText->setMaximumHeight(ui.trans_ToText->fontMetrics().lineSpacing()*1.5); + } + + if (!cc_text.isNull()) + { ui.ccLabel->setVisible(true); - ui.ccText->setVisible(true); + ui.trans_CCText->setVisible(true); - text.clear(); - for(std::set::const_iterator pit = msgInfo.rspeerid_msgcc.begin(); pit != msgInfo.rspeerid_msgcc.end(); ++pit) { - link = RetroShareLink::createMessage(*pit, ""); - if (link.valid()) - text += link.toHtml() + " "; - } - for(std::set::const_iterator pit = msgInfo.rsgxsid_msgcc.begin(); pit != msgInfo.rsgxsid_msgcc.end(); ++pit) { - link = RetroShareLink::createMessage(*pit, ""); - if (link.valid()) - text += link.toHtml() + " "; - } - - ui.ccText->setText(text); + ui.trans_CCText->setText(cc_text); } else { ui.ccLabel->setVisible(false); - ui.ccText->setVisible(false); - ui.ccText->clear(); + ui.trans_CCText->setVisible(false); + ui.trans_CCText->clear(); } - if (!msgInfo.rspeerid_msgbcc.empty() || !msgInfo.rsgxsid_msgbcc.empty()) + if (!bcc_text.isNull()) { ui.bccLabel->setVisible(true); - ui.bccText->setVisible(true); + ui.trans_BCCText->setVisible(true); - text.clear(); - for(std::set::const_iterator pit = msgInfo.rspeerid_msgbcc.begin(); pit != msgInfo.rspeerid_msgbcc.end(); ++pit) { - link = RetroShareLink::createMessage(*pit, ""); - if (link.valid()) - text += link.toHtml() + " "; - } - for(std::set::const_iterator pit = msgInfo.rsgxsid_msgbcc.begin(); pit != msgInfo.rsgxsid_msgbcc.end(); ++pit) { - link = RetroShareLink::createMessage(*pit, ""); - if (link.valid()) - text += link.toHtml() + " "; - } - - ui.bccText->setText(text); + ui.trans_BCCText->setText(bcc_text); } else { ui.bccLabel->setVisible(false); - ui.bccText->setVisible(false); - ui.bccText->clear(); + ui.trans_BCCText->setVisible(false); + ui.trans_BCCText->clear(); } ui.dateText->setText(DateTime::formatDateTime(msgInfo.ts)); @@ -655,21 +686,24 @@ void MessageWidget::fill(const std::string &msgId) // link.createMessage(ownId, ""); // } - if(msgInfo.msgflags & RS_MSG_DISTANT) // distant message + if(msgInfo.from.type()==Rs::Msgs::MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) // distant message { - tooltip_string = PeerDefs::rsidFromId(msgInfo.rsgxsid_srcId) ; - link = RetroShareLink::createMessage(msgInfo.rsgxsid_srcId, ""); + tooltip_string = PeerDefs::rsidFromId(msgInfo.from.toGxsId()) ; + link = RetroShareLink::createMessage(msgInfo.from.toGxsId(), ""); } else { - tooltip_string = PeerDefs::rsidFromId(msgInfo.rspeerid_srcId) ; - link = RetroShareLink::createMessage(msgInfo.rspeerid_srcId, ""); + tooltip_string = PeerDefs::rsidFromId(msgInfo.from.toRsPeerId()) ; + link = RetroShareLink::createMessage(msgInfo.from.toRsPeerId(), ""); } - if (((msgInfo.msgflags & RS_MSG_SYSTEM) && msgInfo.rspeerid_srcId == ownId) || msgInfo.rspeerid_srcId.isNull()) { + if ((msgInfo.msgflags & RS_MSG_SYSTEM) && msgInfo.from.toRsPeerId() == ownId) + { ui.fromText->setText("[Notification]"); if (toolButtonReply) toolButtonReply->setEnabled(false); - } else { + } + else + { ui.fromText->setText(link.toHtml()); ui.fromText->setToolTip(tooltip_string) ; if (toolButtonReply) toolButtonReply->setEnabled(true); @@ -683,7 +717,7 @@ void MessageWidget::fill(const std::string &msgId) if (Settings->valueFromGroup(QString("Messages"), QString::fromUtf8("Emoticons"), true).toBool()) { formatTextFlag |= RSHTML_FORMATTEXT_EMBED_SMILEYS ; } - text = RsHtmlMsg(msgInfo.msgflags).formatText(ui.msgText->document(), QString::fromUtf8(msgInfo.msg.c_str()), formatTextFlag); + QString text = RsHtmlMsg(msgInfo.msgflags).formatText(ui.msgText->document(), QString::fromUtf8(msgInfo.msg.c_str()), formatTextFlag); ui.msgText->resetImagesStatus(Settings->getMsgLoadEmbeddedImages() || (msgInfo.msgflags & RS_MSG_LOAD_EMBEDDED_IMAGES)); ui.msgText->setHtml(text); @@ -704,7 +738,8 @@ void MessageWidget::remove() return; } - bool deleteReal = false; +#ifdef TO_REMOVE + bool deleteReal = false; if (msgInfo.msgflags & RS_MSG_TRASH) { deleteReal = true; } else { @@ -729,8 +764,8 @@ void MessageWidget::remove() deleteLater(); } } - - emit messageRemoved(); +#endif + emit messageRemovalRequested(currMsgId); } void MessageWidget::print() @@ -860,19 +895,19 @@ void MessageWidget::loadImagesAlways() void MessageWidget::sendInvite() { - MessageInfo mi; + MessageInfo mi; - if (!rsMail) - return; + if (!rsMail) + return; - if (!rsMail->getMessage(currMsgId, mi)) - return; + if (!rsMail->getMessage(currMsgId, mi)) + return; - //if ((QMessageBox::question(this, tr("Send invite?"),tr("Do you really want send a invite with your Certificate?"),QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes))== QMessageBox::Yes) - //{ - MessageComposer::sendInvite(mi.rsgxsid_srcId,false); - //} + if(mi.from.type()!=MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) + return; + //if ((QMessageBox::question(this, tr("Send invite?"),tr("Do you really want to send an invite with your Certificate?"),QMessageBox::Yes, QMessageBox::No))== QMessageBox::Yes) + MessageComposer::sendInvite(mi.from.toGxsId(),false); } void MessageWidget::setToolbarButtonStyle(Qt::ToolButtonStyle style) @@ -916,4 +951,15 @@ void MessageWidget::checkLength() text = tr("%1 (%2) ").arg(charlength).arg(misc::friendlyUnit(charlength)); ui.sizeLabel->setText(text); -} \ No newline at end of file +} + +void MessageWidget::expandTo() +{ + if (ui.expandButton->isChecked()) { + ui.trans_ToText->setMaximumHeight(ui.trans_ToText->fontMetrics().lineSpacing()*3.5); + ui.expandButton->setToolTip(tr("Show less")); + } else { + ui.trans_ToText->setMaximumHeight(ui.trans_ToText->fontMetrics().lineSpacing()*1.5); + ui.expandButton->setToolTip(tr("Show more")); + } +} diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.h b/retroshare-gui/src/gui/msgs/MessageWidget.h index 5acf627f6..53b043720 100644 --- a/retroshare-gui/src/gui/msgs/MessageWidget.h +++ b/retroshare-gui/src/gui/msgs/MessageWidget.h @@ -22,6 +22,7 @@ #define _MESSAGEWIDGET_H #include +#include #include "ui_MessageWidget.h" class QToolButton; @@ -60,6 +61,7 @@ public: signals: void messageRemoved(); + void messageRemovalRequested(std::string); private slots: void reply(); @@ -71,11 +73,10 @@ private slots: void saveAs(); void refill(); void sendInvite(); - + void expandTo(); void msgfilelistWidgetCostumPopupMenu(QPoint); void messagesTagsChanged(); - void messagesChanged(); void togglefileview(bool noUpdate = false); void getcurrentrecommended(); @@ -93,11 +94,14 @@ private: void showTagLabels(); void setToolbarButtonStyle(Qt::ToolButtonStyle style); + void handleEvent_main_thread(std::shared_ptr event); + bool isControlled; bool isWindow; std::string currMsgId; unsigned int currMsgFlags; bool expandFiles; + RsEventsHandlerId_t mEventHandlerId; QList tagLabels; diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.ui b/retroshare-gui/src/gui/msgs/MessageWidget.ui index c781dc5d1..cd4a7c401 100644 --- a/retroshare-gui/src/gui/msgs/MessageWidget.ui +++ b/retroshare-gui/src/gui/msgs/MessageWidget.ui @@ -6,7 +6,7 @@ 0 0 - 698 + 738 539 @@ -51,93 +51,6 @@ 3 - - - - - 0 - 0 - - - - - 9 - - - - Bcc: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 9 - - - - To: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 9 - - - - Cc: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - false - - - - - - - - 0 - 0 - - - - - 9 - - - - Tags: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - @@ -146,11 +59,6 @@ 0 - - - 9 - - Qt::LeftToRight @@ -290,6 +198,89 @@
    + + + + + 0 + 0 + + + + Tags: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Subject: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Cc: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 0 + 0 + + + + Bcc: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + To: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + @@ -300,7 +291,6 @@ - 9 75 true @@ -313,6 +303,25 @@ + + + + + 0 + 0 + + + + + 16777215 + 16 + + + + true + + + @@ -333,11 +342,6 @@ 16777215 - - - 9 - - true @@ -346,8 +350,8 @@ - - + + 0 @@ -365,68 +369,9 @@ - - - - - 0 - 0 - - - - - 16777215 - 16 - - - - true - - - - - - - - 0 - 0 - - - - - 16777215 - 16 - - - - true - - - - + - - - - - 0 - 0 - - - - - 9 - - - - Subject: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - @@ -435,11 +380,6 @@ 0 - - - 9 - - From: @@ -448,6 +388,48 @@ + + + + 6 + + + + + + 0 + 0 + + + + + 16777215 + 16 + + + + true + + + + + + + + + + true + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + + + @@ -461,10 +443,19 @@ - + + + + + 0 + 0 + 0 + + + @@ -485,6 +476,15 @@ + + + + 0 + 0 + 0 + + + @@ -505,6 +505,15 @@ + + + + 154 + 154 + 154 + + + @@ -535,7 +544,7 @@ QFrame::Box - + 6 @@ -549,7 +558,7 @@ 6 - + 16 @@ -568,7 +577,7 @@ - + You got an invite to make friend! You may accept this request and send your own Certificate back @@ -810,8 +819,8 @@ - + diff --git a/retroshare-gui/src/gui/msgs/MessageWindow.cpp b/retroshare-gui/src/gui/msgs/MessageWindow.cpp index ad1067367..0c9abf2a2 100644 --- a/retroshare-gui/src/gui/msgs/MessageWindow.cpp +++ b/retroshare-gui/src/gui/msgs/MessageWindow.cpp @@ -150,7 +150,7 @@ void MessageWindow::tagAboutToShow() MsgTagInfo tagInfo; rsMail->getMessageTag(msgWidget->msgId(), tagInfo); - menu->activateActions(tagInfo.tagIds); + menu->activateActions(tagInfo); } void MessageWindow::tagRemoveAll() diff --git a/retroshare-gui/src/gui/msgs/MessagesDialog.cpp b/retroshare-gui/src/gui/msgs/MessagesDialog.cpp index ffc108a53..78493e5a7 100644 --- a/retroshare-gui/src/gui/msgs/MessagesDialog.cpp +++ b/retroshare-gui/src/gui/msgs/MessagesDialog.cpp @@ -44,9 +44,10 @@ #include "gui/settings/rsharesettings.h" #include "util/DateTime.h" -#include "util/RsProtectedTimer.h" +#include "util/misc.h" #include "util/QtVersion.h" #include "util/qtthreadsutils.h" +#include "util/RsProtectedTimer.h" #include #include @@ -94,6 +95,7 @@ #define ROW_SENTBOX 3 #define ROW_TRASHBOX 4 +// #define DEBUG_MESSAGES_DIALOG 1 class MessageSortFilterProxyModel: public QSortFilterProxyModel { @@ -139,14 +141,15 @@ MessagesDialog::MessagesDialog(QWidget *parent) inChange = false; lockUpdate = 0; lastSelectedIndex = QModelIndex(); + mLastCurrentQuickViewRow = -1; msgWidget = new MessageWidget(true, this); ui.msgLayout->addWidget(msgWidget); - connect(msgWidget, SIGNAL(messageRemoved()), this, SLOT(messageRemoved())); + connect(msgWidget, SIGNAL(messageRemovalRequested(std::string)), this, SLOT(removemessage())); connectActions(); - listMode = LIST_NOTHING; + //listMode = LIST_NOTHING; mMessageModel = new RsMessageModel(this); mMessageProxyModel = new MessageSortFilterProxyModel(this); @@ -165,6 +168,7 @@ MessagesDialog::MessagesDialog(QWidget *parent) ui.messageTreeWidget->setItemDelegateForColumn(RsMessageModel::COLUMN_THREAD_SUBJECT,itemDelegate); ui.messageTreeWidget->setItemDelegateForColumn(RsMessageModel::COLUMN_THREAD_AUTHOR,new GxsIdTreeItemDelegate()) ; + ui.messageTreeWidget->setItemDelegateForColumn(RsMessageModel::COLUMN_THREAD_TO,new GxsIdTreeItemDelegate()) ; // workaround for Qt bug, should be solved in next Qt release 4.7.0 // http://bugreports.qt.nokia.com/browse/QTBUG-8270 @@ -189,6 +193,7 @@ MessagesDialog::MessagesDialog(QWidget *parent) /* add filter actions */ ui.filterLineEdit->addFilter(QIcon(), tr("Subject"), RsMessageModel::COLUMN_THREAD_SUBJECT, tr("Search Subject")); ui.filterLineEdit->addFilter(QIcon(), tr("From"), RsMessageModel::COLUMN_THREAD_AUTHOR, tr("Search From")); + ui.filterLineEdit->addFilter(QIcon(), tr("To"), RsMessageModel::COLUMN_THREAD_TO, tr("Search To")); ui.filterLineEdit->addFilter(QIcon(), tr("Date"), RsMessageModel::COLUMN_THREAD_DATE, tr("Search Date")); ui.filterLineEdit->addFilter(QIcon(), tr("Content"), RsMessageModel::COLUMN_THREAD_CONTENT, tr("Search Content")); ui.filterLineEdit->addFilter(QIcon(), tr("Tags"), RsMessageModel::COLUMN_THREAD_TAGS, tr("Search Tags")); @@ -211,22 +216,27 @@ MessagesDialog::MessagesDialog(QWidget *parent) msgwheader->resizeSection (RsMessageModel::COLUMN_THREAD_SUBJECT, fm.width("You have a message")*3.0); msgwheader->resizeSection (RsMessageModel::COLUMN_THREAD_AUTHOR, fm.width("[Retroshare]")*1.1); + msgwheader->resizeSection (RsMessageModel::COLUMN_THREAD_TO, fm.width("[Retroshare]")*1.1); msgwheader->resizeSection (RsMessageModel::COLUMN_THREAD_DATE, fm.width("01/01/1970")*1.1); - QHeaderView_setSectionResizeModeColumn(msgwheader, RsMessageModel::COLUMN_THREAD_SUBJECT, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(msgwheader, RsMessageModel::COLUMN_THREAD_AUTHOR, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(msgwheader, RsMessageModel::COLUMN_THREAD_DATE, QHeaderView::Interactive); + msgwheader->setSectionResizeMode(RsMessageModel::COLUMN_THREAD_SUBJECT, QHeaderView::Interactive); + msgwheader->setSectionResizeMode(RsMessageModel::COLUMN_THREAD_AUTHOR, QHeaderView::Interactive); + msgwheader->setSectionResizeMode(RsMessageModel::COLUMN_THREAD_TO, QHeaderView::Interactive); + msgwheader->setSectionResizeMode(RsMessageModel::COLUMN_THREAD_DATE, QHeaderView::Interactive); - QHeaderView_setSectionResizeModeColumn(msgwheader, RsMessageModel::COLUMN_THREAD_STAR, QHeaderView::Fixed); - QHeaderView_setSectionResizeModeColumn(msgwheader, RsMessageModel::COLUMN_THREAD_ATTACHMENT, QHeaderView::Fixed); - QHeaderView_setSectionResizeModeColumn(msgwheader, RsMessageModel::COLUMN_THREAD_READ, QHeaderView::Fixed); - QHeaderView_setSectionResizeModeColumn(msgwheader, RsMessageModel::COLUMN_THREAD_SPAM, QHeaderView::Fixed); + msgwheader->setSectionResizeMode(RsMessageModel::COLUMN_THREAD_STAR, QHeaderView::Fixed); + msgwheader->setSectionResizeMode(RsMessageModel::COLUMN_THREAD_ATTACHMENT, QHeaderView::Fixed); + msgwheader->setSectionResizeMode(RsMessageModel::COLUMN_THREAD_READ, QHeaderView::Fixed); + msgwheader->setSectionResizeMode(RsMessageModel::COLUMN_THREAD_SPAM, QHeaderView::Fixed); ui.messageTreeWidget->setSortingEnabled(true); /* Set header sizes for the fixed columns and resize modes, must be set after processSettings */ msgwheader->setStretchLastSection(true); + QFontMetricsF fontMetrics(ui.messageTreeWidget->font()); + int iconHeight = fontMetrics.height() * 1.4; + ui.messageTreeWidget->setIconSize(QSize(iconHeight, iconHeight)); // fill folder list updateMessageSummaryList(); @@ -245,32 +255,26 @@ MessagesDialog::MessagesDialog(QWidget *parent) sortColumn(RsMessageModel::COLUMN_THREAD_DATE,Qt::DescendingOrder); - // load settings - processSettings(true); - //ui.messageTreeWidget->installEventFilter(this); // remove close button of the the first tab ui.tabWidget->hideCloseButton(0); ui.tabWidget->setHideTabBarWithOneTab(true); - int S = QFontMetricsF(font()).height(); - QString help_str = tr( - "

      Messages

    \ -

    Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.

    \ -

    It is also possible to send messages to other people's Identities using the global routing system. These messages \ - are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination.

    \ -

    Distant messages stay into your Outbox until an acknowledgement of receipt has been received.

    \ -

    Generally, you may use messages to recommend files to your friends by pasting file links, \ - or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback \ - to a channel's owner.

    \ - ").arg(QString::number(2*S), QString::number(S)) ; + int H = misc::getFontSizeFactor("HelpButton").height(); + QString help_str = tr( + "

      Messages

    " + "

    Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.

    " + "

    It is also possible to send messages to other people's Identities using the global routing system. These messages" + " are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination.

    " + "

    Distant messages stay into your Outbox until an acknowledgement of receipt has been received.

    " + "

    Generally, you may use messages to recommend files to your friends by pasting file links," + " or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback" + " to a channel's owner.

    " + ).arg(QString::number(2*H)) ; registerHelpButton(ui.helpButton,help_str,"MessagesDialog") ; - connect(NotifyQt::getInstance(), SIGNAL(messagesChanged()), mMessageModel, SLOT(updateMessages())); - connect(NotifyQt::getInstance(), SIGNAL(messagesTagsChanged()), this, SLOT(messagesTagsChanged())); - connect(ui.filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); connect(ui.filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterColumnChanged(int))); @@ -279,10 +283,10 @@ MessagesDialog::MessagesDialog(QWidget *parent) connect(ui.listWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(folderlistWidgetCustomPopupMenu(QPoint))); connect(ui.listWidget, SIGNAL(currentRowChanged(int)), this, SLOT(changeBox(int))); - connect(ui.quickViewWidget, SIGNAL(currentRowChanged(int)), this, SLOT(changeQuickView(int))); connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); connect(ui.tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(tabCloseRequested(int))); connect(ui.newmessageButton, SIGNAL(clicked()), this, SLOT(newmessage())); + connect(ui.quickViewWidget, SIGNAL(clicked(const QModelIndex&)), this, SLOT(resetQuickView(const QModelIndex&))); connect(ui.messageTreeWidget, SIGNAL(clicked(const QModelIndex&)) , this, SLOT(clicked(const QModelIndex&))); connect(ui.messageTreeWidget, SIGNAL(doubleClicked(const QModelIndex&)) , this, SLOT(doubleClicked(const QModelIndex&))); @@ -292,8 +296,33 @@ MessagesDialog::MessagesDialog(QWidget *parent) connect(ui.messageTreeWidget->selectionModel(), SIGNAL(currentChanged(const QModelIndex&,const QModelIndex&)), this, SLOT(currentChanged(const QModelIndex&,const QModelIndex&))); + // load settings + processSettings(true); + + ui.listWidget->setCurrentRow(0); // always starts with inbox => allows to setup the proper number of columns + mEventHandlerId=0; rsEvents->registerEventsHandler( [this](std::shared_ptr event) { RsQThreadUtils::postToObject( [this,event]() { handleEvent_main_thread(event); }); }, mEventHandlerId, RsEventType::MAIL_STATUS ); + + mTagEventHandlerId = 0; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) { RsQThreadUtils::postToObject( [this,event]() { handleTagEvent_main_thread(event); }); }, mEventHandlerId, RsEventType::MAIL_TAG ); + + mFontSizeHandler.registerFontSize(ui.listWidget, 1.5f, [this] (QAbstractItemView*, int fontSize) { + // Set new font size on all items + QList rows; + rows << ROW_INBOX << ROW_OUTBOX << ROW_DRAFTBOX; + + foreach (int row, rows) { + QListWidgetItem *item = ui.listWidget->item(row); + QFont font = item->font(); + font.setPointSize(fontSize); + item->setFont(font); + } + }); + mFontSizeHandler.registerFontSize(ui.quickViewWidget, 1.5f); + mFontSizeHandler.registerFontSize(ui.messageTreeWidget, 1.5f, [this] (QAbstractItemView *view, int) { + mMessageModel->setFont(view->font()); + }); } void MessagesDialog::handleEvent_main_thread(std::shared_ptr event) @@ -310,9 +339,34 @@ void MessagesDialog::handleEvent_main_thread(std::shared_ptr even case RsMailStatusEventCode::MESSAGE_SENT: case RsMailStatusEventCode::MESSAGE_REMOVED: case RsMailStatusEventCode::NEW_MESSAGE: + case RsMailStatusEventCode::MESSAGE_CHANGED: + case RsMailStatusEventCode::TAG_CHANGED: + mMessageModel->updateMessages(); updateMessageSummaryList(); break; - default: + case RsMailStatusEventCode::MESSAGE_RECEIVED_ACK: + case RsMailStatusEventCode::SIGNATURE_FAILED: + break; + } +} + +void MessagesDialog::handleTagEvent_main_thread(std::shared_ptr event) +{ + if (event->mType != RsEventType::MAIL_TAG) { + return; + } + + const RsMailTagEvent *fe = dynamic_cast(event.get()); + if (!fe) { + return; + } + + switch (fe->mMailTagEventCode) { + case RsMailTagEventCode::TAG_ADDED: + case RsMailTagEventCode::TAG_CHANGED: + case RsMailTagEventCode::TAG_REMOVED: + fillQuickView(); + mMessageModel->updateMessages(); break; } } @@ -324,14 +378,23 @@ void MessagesDialog::preModelUpdate() mTmpSavedSelectedIds.clear(); getSelectedMessages(mTmpSavedSelectedIds); + mTmpSavedCurrentId.clear(); + const QModelIndex& m = ui.messageTreeWidget->currentIndex(); + if (m.isValid()) { + mTmpSavedCurrentId = m.sibling(m.row(), RsMessageModel::COLUMN_THREAD_MSGID).data(RsMessageModel::MsgIdRole).toString(); + } +#ifdef DEBUG_MESSAGES_DIALOG std::cerr << "Pre-change: saving selection for " << mTmpSavedSelectedIds.size() << " indexes" << std::endl; +#endif } void MessagesDialog::postModelUpdate() { // restore selection +#ifdef DEBUG_MESSAGES_DIALOG std::cerr << "Post-change: restoring selection for " << mTmpSavedSelectedIds.size() << " indexes" << std::endl; +#endif QItemSelection sel; foreach(const QString& s,mTmpSavedSelectedIds) @@ -340,7 +403,17 @@ void MessagesDialog::postModelUpdate() sel.select(i.sibling(i.row(),0),i.sibling(i.row(),RsMessageModel::COLUMN_THREAD_NB_COLUMNS-1)); } - ui.messageTreeWidget->selectionModel()->select(sel,QItemSelectionModel::SelectCurrent); + // Restoring selection should not trigger anything, especially the re-display of the msg, which + // in turn will change the read status. + + whileBlocking(ui.messageTreeWidget->selectionModel())->select(sel,QItemSelectionModel::SelectCurrent); + + if (!mTmpSavedCurrentId.isEmpty()) { + QModelIndex index = mMessageProxyModel->mapFromSource(mMessageModel->getIndexOfMessage(mTmpSavedCurrentId.toStdString())); + if (index.isValid()) { + whileBlocking(ui.messageTreeWidget->selectionModel())->setCurrentIndex(index, QItemSelectionModel::Select); + } + } } void MessagesDialog::sortColumn(int col,Qt::SortOrder so) @@ -356,6 +429,9 @@ MessagesDialog::~MessagesDialog() { // save settings processSettings(false); + + rsEvents->unregisterEventsHandler(mEventHandlerId); + rsEvents->unregisterEventsHandler(mTagEventHandlerId); } UserNotify *MessagesDialog::createUserNotify(QObject *parent) @@ -365,7 +441,7 @@ UserNotify *MessagesDialog::createUserNotify(QObject *parent) void MessagesDialog::processSettings(bool load) { - int messageTreeVersion = 3; // version number for the settings to solve problems when modifying the column count + int messageTreeVersion = 4; // version number for the settings to solve problems when modifying the column count inProcessSettings = true; @@ -452,7 +528,7 @@ void MessagesDialog::fillQuickView() ui.quickViewWidget->clear(); // add static items - item = new QListWidgetItem(tr("Starred"), ui.quickViewWidget); + item = new QListWidgetItem(tr("Starred"), ui.quickViewWidget); item->setIcon(FilesDefs::getIconFromQtResourcePath(IMAGE_STAR_ON)); item->setData(ROLE_QUICKVIEW_TYPE, QUICKVIEW_TYPE_STATIC); item->setData(ROLE_QUICKVIEW_ID, QUICKVIEW_STATIC_ID_STARRED); @@ -618,13 +694,13 @@ void MessagesDialog::messageTreeWidgetCustomPopupMenu(QPoint /*point*/) QMenu contextMnu( this ); - QAction *action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(":/images/view_split_top_bottom.png"), tr("Open in a new window"), this, SLOT(openAsWindow())); + QAction *action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/newwindow.svg"), tr("Open in a new window"), this, SLOT(openAsWindow())); if (nCount != 1) { action->setDisabled(true); } - action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(":/images/tab-dock.png"), tr("Open in a new tab"), this, SLOT(openAsTab())); + action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/newtab.svg"), tr("Open in a new tab"), this, SLOT(openAsTab())); if (nCount != 1) { action->setDisabled(true); } @@ -704,12 +780,12 @@ void MessagesDialog::messageTreeWidgetCustomPopupMenu(QPoint /*point*/) // test if identity is known. If not, no need to call the people tab. Also some mails come from nodes and we wont show that node in the people tab either. // The problem here is that the field rsgxsid_srcId is always populated with either the GxsId or the node of the source, which is inconsistent. - if(nCount==1 && rsIdentity->getIdDetails(msgInfo.rsgxsid_srcId,details)) + if(nCount==1 && msgInfo.from.type() == MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) { - std::cerr << "Src ID = " << msgInfo.rsgxsid_srcId << std::endl; + std::cerr << "Src ID = " << msgInfo.from.toGxsId() << std::endl; - contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_AUTHOR_INFO),tr("Show author in People"),this,SLOT(showAuthorInPeopleTab())); - contextMnu.addSeparator(); + contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_AUTHOR_INFO),tr("Show in People"),this,SLOT(showAuthorInPeopleTab())); + contextMnu.addSeparator(); } contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_MESSAGE), tr("New Message"), this, SLOT(newmessage())); @@ -729,7 +805,7 @@ void MessagesDialog::showAuthorInPeopleTab() if (!rsMail->getMessage(mid, msgInfo)) return; - if(msgInfo.rsgxsid_srcId.isNull()) + if(msgInfo.from.type() != MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) return ; /* window will destroy itself! */ @@ -739,7 +815,7 @@ void MessagesDialog::showAuthorInPeopleTab() return ; MainWindow::showWindow(MainWindow::People); - idDialog->navigate(RsGxsId(msgInfo.rsgxsid_srcId)) ; + idDialog->navigate(RsGxsId(msgInfo.from.toGxsId())) ; } void MessagesDialog::folderlistWidgetCustomPopupMenu(QPoint /*point*/) @@ -783,7 +859,7 @@ void MessagesDialog::openAsWindow() } msgWidget->activateWindow(); - connect(msgWidget, SIGNAL(messageRemoved()), this, SLOT(messageRemoved())); + connect(msgWidget, SIGNAL(messageRemovalRequested(std::string)), this, SLOT(removemessage())); /* window will destroy itself! */ } @@ -803,7 +879,7 @@ void MessagesDialog::openAsTab() ui.tabWidget->addTab(msgWidget,FilesDefs::getIconFromQtResourcePath(IMAGE_MAIL), msgWidget->subject(true)); ui.tabWidget->setCurrentWidget(msgWidget); - connect(msgWidget, SIGNAL(messageRemoved()), this, SLOT(messageRemoved())); + connect(msgWidget, SIGNAL(messageRemovalRequested(std::string)), this, SLOT(removemessage())); /* window will destroy itself! */ } @@ -841,54 +917,76 @@ void MessagesDialog::changeBox(int box_row) if (item) { ui.quickViewWidget->setCurrentItem(NULL); - changeQuickView(-1); - listMode = LIST_BOX; + changeQuickView(-1); + //listMode = LIST_BOX; QString placeholderText = tr("No message available in your %1.").arg(item->text()); switch(box_row) { - case ROW_INBOX: mMessageModel->setCurrentBox(RsMessageModel::BOX_INBOX ); + case ROW_INBOX: mMessageModel->setCurrentBox(Rs::Msgs::BoxName::BOX_INBOX ); + break; + case ROW_OUTBOX: mMessageModel->setCurrentBox(Rs::Msgs::BoxName::BOX_OUTBOX); break; - case ROW_OUTBOX: mMessageModel->setCurrentBox(RsMessageModel::BOX_OUTBOX); + case ROW_DRAFTBOX: mMessageModel->setCurrentBox(Rs::Msgs::BoxName::BOX_DRAFTS); break; - case ROW_DRAFTBOX: mMessageModel->setCurrentBox(RsMessageModel::BOX_DRAFTS); + case ROW_SENTBOX: mMessageModel->setCurrentBox(Rs::Msgs::BoxName::BOX_SENT ); break; - case ROW_SENTBOX: mMessageModel->setCurrentBox(RsMessageModel::BOX_SENT ); - break; - case ROW_TRASHBOX: mMessageModel->setCurrentBox(RsMessageModel::BOX_TRASH ); + case ROW_TRASHBOX: mMessageModel->setCurrentBox(Rs::Msgs::BoxName::BOX_TRASH ); break; default: - mMessageModel->setCurrentBox(RsMessageModel::BOX_NONE); + mMessageModel->setCurrentBox(Rs::Msgs::BoxName::BOX_NONE); } insertMsgTxtAndFiles(ui.messageTreeWidget->currentIndex()); + ui.messageTreeWidget->setPlaceholderText(placeholderText); - } + ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_READ,box_row!=ROW_INBOX); + ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_STAR,box_row!=ROW_INBOX); + ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_SPAM,box_row!=ROW_INBOX); + ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_TAGS,box_row!=ROW_INBOX); + ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_MSGID,true); + ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_CONTENT,true); + } else { - mMessageModel->setCurrentBox(RsMessageModel::BOX_NONE); + mMessageModel->setCurrentBox(Rs::Msgs::BoxName::BOX_NONE); } inChange = false; updateMessageSummaryList(); } +void MessagesDialog::resetQuickView(const QModelIndex& i) +{ + if(!i.isValid()) + return; + + int n = ui.quickViewWidget->currentRow(); + + if(mLastCurrentQuickViewRow == n) + { + changeQuickView(-1); + ui.quickViewWidget->setCurrentRow(-1); + } + else + changeQuickView(n); +} void MessagesDialog::changeQuickView(int newrow) { - + mLastCurrentQuickViewRow = newrow; RsMessageModel::QuickViewFilter f = RsMessageModel::QUICK_VIEW_ALL ; QListWidgetItem* item = ui.quickViewWidget->item(newrow); if(item ) { - ui.listWidget->setCurrentItem(NULL); - changeBox(-1); - - listMode = LIST_QUICKVIEW; + //ui.listWidget->setCurrentItem(NULL); + //changeBox(-1); + //listMode = LIST_QUICKVIEW; QString placeholderText; - switch (item->data(ROLE_QUICKVIEW_TYPE).toInt()) { + switch (item->data(ROLE_QUICKVIEW_TYPE).toInt()) + { case QUICKVIEW_TYPE_TAG: { placeholderText = tr("No message using %1 tag available.").arg(item->data(ROLE_QUICKVIEW_TEXT).toString()); @@ -913,21 +1011,14 @@ void MessagesDialog::changeQuickView(int newrow) } } - insertMsgTxtAndFiles(ui.messageTreeWidget->currentIndex()); + //insertMsgTxtAndFiles(ui.messageTreeWidget->currentIndex()); ui.messageTreeWidget->setPlaceholderText(placeholderText); } mMessageModel->setQuickViewFilter(f); - mMessageProxyModel->setFilterRegExp(QRegExp(RsMessageModel::FilterString)); // this triggers the update of the proxy model + mMessageProxyModel->setFilterRegExp(QRegExp(RsMessageModel::FilterString)); // this triggers the update of the proxy model } -void MessagesDialog::messagesTagsChanged() -{ - fillQuickView(); - mMessageModel->updateMessages(); -} - - // click in messageTreeWidget void MessagesDialog::currentChanged(const QModelIndex& new_proxy_index,const QModelIndex& /*old_proxy_index*/) { @@ -951,21 +1042,16 @@ void MessagesDialog::clicked(const QModelIndex& proxy_index) case RsMessageModel::COLUMN_THREAD_READ: { mMessageModel->setMsgReadStatus(real_index, !isMessageRead(proxy_index)); - //Already updated by currentChanged - //insertMsgTxtAndFiles(proxy_index); - updateMessageSummaryList(); return; } case RsMessageModel::COLUMN_THREAD_STAR: { mMessageModel->setMsgStar(real_index, !hasMessageStar(proxy_index)); - updateMessageSummaryList(); return; } case RsMessageModel::COLUMN_THREAD_SPAM: { mMessageModel->setMsgJunk(real_index, !hasMessageSpam(proxy_index)); - updateMessageSummaryList(); return; } } @@ -1111,12 +1197,17 @@ void MessagesDialog::removemessage() bool doDelete = false; int listrow = ui.listWidget->currentRow(); - if (listrow == ROW_TRASHBOX) { + + if(listrow == ROW_TRASHBOX || (QApplication::keyboardModifiers() & Qt::ShiftModifier)) + doDelete = true; + + if(listrow == ROW_OUTBOX) + { + if(QMessageBox::question(nullptr,tr("Deletion is not recommended"),tr("Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete?")) + != QMessageBox::Yes) + return ; + doDelete = true; - } else { - if (QApplication::keyboardModifiers() & Qt::ShiftModifier) { - doDelete = true; - } } foreach (const QString& m, selectedMessages) { @@ -1155,7 +1246,7 @@ void MessagesDialog::undeletemessage() void MessagesDialog::filterChanged(const QString& text) { - QStringList items = text.split(' ',QString::SkipEmptyParts); + QStringList items = text.split(' ',QtSkipEmptyParts); RsMessageModel::FilterType f = RsMessageModel::FILTER_TYPE_NONE; @@ -1163,6 +1254,7 @@ void MessagesDialog::filterChanged(const QString& text) { case RsMessageModel::COLUMN_THREAD_SUBJECT: f = RsMessageModel::FILTER_TYPE_SUBJECT ; break; case RsMessageModel::COLUMN_THREAD_AUTHOR: f = RsMessageModel::FILTER_TYPE_FROM ; break; + case RsMessageModel::COLUMN_THREAD_TO: f = RsMessageModel::FILTER_TYPE_TO ; break; case RsMessageModel::COLUMN_THREAD_DATE: f = RsMessageModel::FILTER_TYPE_DATE ; break; case RsMessageModel::COLUMN_THREAD_CONTENT: f = RsMessageModel::FILTER_TYPE_CONTENT ; break; case RsMessageModel::COLUMN_THREAD_TAGS: f = RsMessageModel::FILTER_TYPE_TAGS ; break; @@ -1187,6 +1279,7 @@ void MessagesDialog::filterColumnChanged(int column) { case RsMessageModel::COLUMN_THREAD_SUBJECT: f = RsMessageModel::FILTER_TYPE_SUBJECT ; break; case RsMessageModel::COLUMN_THREAD_AUTHOR: f = RsMessageModel::FILTER_TYPE_FROM ; break; + case RsMessageModel::COLUMN_THREAD_TO: f = RsMessageModel::FILTER_TYPE_TO ; break; case RsMessageModel::COLUMN_THREAD_DATE: f = RsMessageModel::FILTER_TYPE_DATE ; break; case RsMessageModel::COLUMN_THREAD_CONTENT: f = RsMessageModel::FILTER_TYPE_CONTENT ; break; case RsMessageModel::COLUMN_THREAD_TAGS: f = RsMessageModel::FILTER_TYPE_TAGS ; break; @@ -1194,7 +1287,7 @@ void MessagesDialog::filterColumnChanged(int column) default:break; } - QStringList items = ui.filterLineEdit->text().split(' ',QString::SkipEmptyParts); + QStringList items = ui.filterLineEdit->text().split(' ',QtSkipEmptyParts); mMessageModel->setFilter(f,items); mMessageProxyModel->setFilterRegExp(QRegExp(RsMessageModel::FilterString)); // this triggers the update of the proxy model @@ -1220,7 +1313,7 @@ void MessagesDialog::updateMessageSummaryList() /* calculating the new messages */ std::list msgList; - rsMail->getMessageSummaries(msgList); + rsMail->getMessageSummaries(Rs::Msgs::BoxName::BOX_ALL,msgList); QMap tagCount; @@ -1236,17 +1329,14 @@ void MessagesDialog::updateMessageSummaryList() tagCount [*tagId] = nCount; } - if (it->msgflags & RS_MSG_STAR) { + if (it->msgflags & RS_MSG_STAR) ++starredCount; - } - if (it->msgflags & RS_MSG_SYSTEM) { + if (it->msgflags & RS_MSG_SYSTEM) ++systemCount; - } - if (it->msgflags & RS_MSG_SPAM) { + if (it->msgflags & RS_MSG_SPAM) ++spamCount; - } /* calculate box */ if (it->msgflags & RS_MSG_TRASH) { @@ -1264,7 +1354,7 @@ void MessagesDialog::updateMessageSummaryList() case RS_MSG_OUTBOX: ++newOutboxCount; break; - case RS_MSG_DRAFTBOX: + case RS_MSG_DRAFT: // not RS_MSG_DRAFTBOX because drafts are not considered outgoing ++newDraftCount; break; case RS_MSG_SENTBOX: @@ -1301,7 +1391,7 @@ void MessagesDialog::updateMessageSummaryList() break; } - +std::cerr << "NewInboxCount = " << newInboxCount << " NewDraftCount = " << newDraftCount << std::endl; QString textItem; /*updating the labels in leftcolumn*/ @@ -1335,7 +1425,7 @@ void MessagesDialog::updateMessageSummaryList() textItem = tr("Outbox") + " (" + QString::number(newOutboxCount)+")"; item->setText(textItem); QFont qf = item->font(); - qf.setBold(true); + qf.setBold(false); item->setFont(qf); } else @@ -1402,16 +1492,20 @@ void MessagesDialog::updateMessageSummaryList() QString text = qv_item->data(ROLE_QUICKVIEW_TEXT).toString(); switch (qv_item->data(ROLE_QUICKVIEW_ID).toInt()) { case QUICKVIEW_STATIC_ID_STARRED: - text += " (" + QString::number(starredCount) + ")"; + if(starredCount>0) + text += " (" + QString::number(starredCount) + ")"; break; case QUICKVIEW_STATIC_ID_SYSTEM: - text += " (" + QString::number(systemCount) + ")"; + if(systemCount > 0) + text += " (" + QString::number(systemCount) + ")"; break; case QUICKVIEW_STATIC_ID_SPAM: - text += " (" + QString::number(spamCount) + ")"; + if(spamCount > 0) + text += " (" + QString::number(spamCount) + ")"; break; case QUICKVIEW_STATIC_ID_ATTACHMENT: - text += " (" + QString::number(attachmentCount) + ")"; + if(attachmentCount > 0) + text += " (" + QString::number(attachmentCount) + ")"; break; } @@ -1425,11 +1519,10 @@ void MessagesDialog::updateMessageSummaryList() void MessagesDialog::tagAboutToShow() { -#ifdef TODO TagsMenu *menu = dynamic_cast(ui.tagButton->menu()); - if (menu == NULL) { + + if (menu == NULL) return; - } // activate actions from the first selected row MsgTagInfo tagInfo; @@ -1440,8 +1533,7 @@ void MessagesDialog::tagAboutToShow() if(!msgids.empty()) rsMail->getMessageTag(msgids.front().toStdString(), tagInfo); - menu->activateActions(tagInfo.tagIds); -#endif + menu->activateActions(tagInfo); } void MessagesDialog::tagRemoveAll() @@ -1455,9 +1547,8 @@ void MessagesDialog::tagRemoveAll() void MessagesDialog::tagSet(int tagId, bool set) { - if (tagId == 0) { + if (tagId == 0) return; - } QList msgids; getSelectedMessages(msgids); @@ -1469,7 +1560,7 @@ void MessagesDialog::tagSet(int tagId, bool set) void MessagesDialog::emptyTrash() { std::list msgs ; - mMessageModel->getMessageSummaries(RsMessageModel::BOX_TRASH,msgs); + rsMsgs->getMessageSummaries(Rs::Msgs::BoxName::BOX_TRASH,msgs); for(auto it(msgs.begin());it!=msgs.end();++it) rsMail->MessageDelete(it->msgId); diff --git a/retroshare-gui/src/gui/msgs/MessagesDialog.h b/retroshare-gui/src/gui/msgs/MessagesDialog.h index fab811ee7..7f9573f81 100644 --- a/retroshare-gui/src/gui/msgs/MessagesDialog.h +++ b/retroshare-gui/src/gui/msgs/MessagesDialog.h @@ -25,6 +25,7 @@ #include #include +#include "util/FontSizeHandler.h" #include "ui_MessagesDialog.h" @@ -66,7 +67,6 @@ protected: public slots: //void insertMessages(); - void messagesTagsChanged(); void messageRemoved(); void preModelUpdate(); void postModelUpdate(); @@ -80,6 +80,7 @@ private slots: void changeBox(int newrow); void changeQuickView(int newrow); + void resetQuickView(const QModelIndex& i); void updateCurrentMessage(); void clicked(const QModelIndex&); void doubleClicked(const QModelIndex&); @@ -112,6 +113,7 @@ private slots: private: void handleEvent_main_thread(std::shared_ptr event); + void handleTagEvent_main_thread(std::shared_ptr event); void updateInterface(); @@ -138,9 +140,10 @@ private: bool inChange; int lockUpdate; // use with LockUpdate - enum { LIST_NOTHING, LIST_BOX, LIST_QUICKVIEW } listMode; + // enum { LIST_NOTHING, LIST_BOX, LIST_QUICKVIEW } listMode; std::string mCurrMsgId; + int mLastCurrentQuickViewRow; // timer and index for showing message QTimer *timer; @@ -152,16 +155,20 @@ private: RsMessageModel *mMessageModel; MessageSortFilterProxyModel *mMessageProxyModel; - /* Color definitions (for standard see qss.default) */ + /* Color definitions (for standard see default.qss) */ QColor mTextColorInbox; /** Qt Designer generated object */ Ui::MessagesDialog ui; QList mTmpSavedSelectedIds; + QString mTmpSavedCurrentId; QModelIndex lastSelectedIndex; RsEventsHandlerId_t mEventHandlerId; + RsEventsHandlerId_t mTagEventHandlerId; + + FontSizeHandler mFontSizeHandler; }; #endif diff --git a/retroshare-gui/src/gui/msgs/MessagesDialog.ui b/retroshare-gui/src/gui/msgs/MessagesDialog.ui index 183396a2c..516511265 100644 --- a/retroshare-gui/src/gui/msgs/MessagesDialog.ui +++ b/retroshare-gui/src/gui/msgs/MessagesDialog.ui @@ -10,7 +10,7 @@ 485 - + 0 @@ -36,7 +36,7 @@ Messages - + 0 @@ -55,7 +55,7 @@ Qt::Horizontal - + 0 @@ -72,11 +72,11 @@ 0 - + true - + 3 @@ -188,23 +188,17 @@ - - + + 0 - + true - - QFrame::StyledPanel - - - QFrame::Raised - - + 3 @@ -275,13 +269,13 @@ - - + + 0 - + 3 @@ -321,7 +315,7 @@
    - + Qt::Horizontal @@ -352,7 +346,7 @@ Qt::NoFocus - + :/icons/help_64.png:/icons/help_64.png @@ -457,7 +451,7 @@ LineEditClear QLineEdit -
    gui/common/LineEditClear.h
    +
    gui/common/LineEditClear.h
    RSTabWidget @@ -476,8 +470,8 @@ listWidget - + diff --git a/retroshare-gui/src/gui/msgs/TagsMenu.cpp b/retroshare-gui/src/gui/msgs/TagsMenu.cpp index 357c37325..881ec268d 100644 --- a/retroshare-gui/src/gui/msgs/TagsMenu.cpp +++ b/retroshare-gui/src/gui/msgs/TagsMenu.cpp @@ -30,6 +30,7 @@ #include "gui/common/TagDefs.h" #include "gui/settings/NewTag.h" #include "gui/notifyqt.h" +#include "util/qtthreadsutils.h" #include "gui/msgs/MessageInterface.h" @@ -46,11 +47,18 @@ TagsMenu::TagsMenu(const QString &title, QWidget *parent) : QMenu (title, parent) { connect(this, SIGNAL(triggered (QAction*)), this, SLOT(tagTriggered(QAction*))); - connect(NotifyQt::getInstance(), SIGNAL(messagesTagsChanged()), this, SLOT(fillTags())); + + mEventHandlerId = 0; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) { RsQThreadUtils::postToObject( [this,event]() { handleEvent_main_thread(event); }); }, mEventHandlerId, RsEventType::MAIL_TAG ); fillTags(); } +TagsMenu::~TagsMenu() +{ + rsEvents->unregisterEventsHandler(mEventHandlerId); +} + void TagsMenu::paintEvent(QPaintEvent *e) { QMenu::paintEvent(e); @@ -89,6 +97,26 @@ void TagsMenu::paintEvent(QPaintEvent *e) } } +void TagsMenu::handleEvent_main_thread(std::shared_ptr event) +{ + if (event->mType != RsEventType::MAIL_TAG) { + return; + } + + const RsMailTagEvent *fe = dynamic_cast(event.get()); + if (!fe) { + return; + } + + switch (fe->mMailTagEventCode) { + case RsMailTagEventCode::TAG_ADDED: + case RsMailTagEventCode::TAG_CHANGED: + case RsMailTagEventCode::TAG_REMOVED: + fillTags(); + break; + } +} + void TagsMenu::fillTags() { clear(); @@ -142,7 +170,7 @@ void TagsMenu::fillTags() addAction(action); } -void TagsMenu::activateActions(std::list& tagIds) +void TagsMenu::activateActions(std::set& tagIds) { foreach(QObject *object, children()) { QAction *action = qobject_cast (object); @@ -158,7 +186,7 @@ void TagsMenu::activateActions(std::list& tagIds) continue; } - std::list::iterator tagId = std::find(tagIds.begin(), tagIds.end(), values [ACTION_TAGSINDEX_ID]); + auto tagId = std::find(tagIds.begin(), tagIds.end(), values [ACTION_TAGSINDEX_ID]); action->setChecked(tagId != tagIds.end()); } } diff --git a/retroshare-gui/src/gui/msgs/TagsMenu.h b/retroshare-gui/src/gui/msgs/TagsMenu.h index 279638aae..1cccb7e5f 100644 --- a/retroshare-gui/src/gui/msgs/TagsMenu.h +++ b/retroshare-gui/src/gui/msgs/TagsMenu.h @@ -24,6 +24,7 @@ #include #include +#include class TagsMenu : public QMenu { @@ -31,8 +32,9 @@ class TagsMenu : public QMenu public: TagsMenu(const QString &title, QWidget *parent); + virtual ~TagsMenu(); - void activateActions(std::list& tagIds); + void activateActions(std::set &tagIds); signals: void tagSet(int tagId, bool set); @@ -42,8 +44,14 @@ protected: virtual void paintEvent(QPaintEvent *e); private slots: - void fillTags(); void tagTriggered(QAction *action); + +private: + void handleEvent_main_thread(std::shared_ptr event); + void fillTags(); + +private: + RsEventsHandlerId_t mEventHandlerId; }; #endif diff --git a/retroshare-gui/src/gui/notifyqt.cpp b/retroshare-gui/src/gui/notifyqt.cpp index 7bb1b6cf2..d2dee5ac4 100644 --- a/retroshare-gui/src/gui/notifyqt.cpp +++ b/retroshare-gui/src/gui/notifyqt.cpp @@ -21,12 +21,6 @@ #include "gui/common/FilesDefs.h" #include -#include -#include -#include -//#include -#include - #include "notifyqt.h" #include #include @@ -55,6 +49,13 @@ #include "retroshare/rsplugin.h" +#include +#include +#include +//#include +#include +#include + /***** * #define NOTIFY_DEBUG ****/ @@ -223,37 +224,51 @@ bool NotifyQt::askForPassword(const std::string& title, const std::string& key_d { RsAutoUpdatePage::lockAllEvents() ; - QInputDialog dialog; + QString windowTitle; if (title == "") { - dialog.setWindowTitle(tr("Passphrase required")); + windowTitle = tr("Passphrase required"); } else if (title == "AuthSSLimpl::SignX509ReqWithGPG()") { - dialog.setWindowTitle(tr("You need to sign your node's certificate.")); + windowTitle = tr("You need to sign your node's certificate."); } else if (title == "p3IdService::service_CreateGroup()") { - dialog.setWindowTitle(tr("You need to sign your forum/chatrooms identity.")); + windowTitle = tr("You need to sign your forum/chatrooms identity."); } else { - dialog.setWindowTitle(QString::fromStdString(title)); + windowTitle = QString::fromStdString(title); } - dialog.setLabelText((prev_is_bad ? QString("%1

    ").arg(tr("Wrong password !")) : QString()) + QString("%1
    Profile: %2\n").arg(tr("Please enter your Retroshare passphrase"), QString::fromUtf8(key_details.c_str()))); - dialog.setTextEchoMode(QLineEdit::Password); - dialog.setModal(true); + QString labelText = ( prev_is_bad ? QString("%1

    ").arg(tr("Wrong password !")) : QString() ) + + QString("%1
    Profile: %2\n") + .arg( tr("Please enter your Retroshare passphrase") + , QString::fromUtf8(key_details.c_str()) ); + QLineEdit::EchoMode textEchoMode = QLineEdit::Password; + bool modal = true; - int ret = dialog.exec(); + bool sameThread = QThread::currentThread() == qApp->thread(); + Gui_InputDialogReturn ret; + qRegisterMetaType("Gui_InputDialogReturn"); + QMetaObject::invokeMethod( MainWindow::getInstance() + , "guiInputDialog" + , sameThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection + , Q_RETURN_ARG(Gui_InputDialogReturn, ret) + , Q_ARG(QString, windowTitle) + , Q_ARG(QString, labelText) + , Q_ARG(QLineEdit::EchoMode, textEchoMode) + , Q_ARG(bool, modal) + ); - cancelled = false ; + cancelled = false ; RsAutoUpdatePage::unlockAllEvents() ; - if (ret == QDialog::Rejected) { - password.clear() ; - cancelled = true ; - return true ; - } + if (ret.execReturn == QDialog::Rejected) { + password.clear() ; + cancelled = true ; + return true ; + } - if (ret == QDialog::Accepted) { - password = dialog.textValue().toUtf8().constData(); - return true; - } + if (ret.execReturn == QDialog::Accepted) { + password = ret.textValue.toUtf8().constData(); + return true; + } return false; } @@ -462,11 +477,13 @@ void NotifyQt::notifyChatCleared(const ChatId& chat_id) emit chatCleared(chat_id); } -void NotifyQt::notifyTurtleSearchResult(uint32_t search_id,const std::list& found_groups) +void NotifyQt::notifyTurtleSearchResult(uint32_t /*search_id*/,const std::list& /*found_groups*/) { std::cerr << "(EE) missing code to handle GXS turtle search result." << std::endl; } +#ifdef TO_REMOVE +// Mai 2023: distant turtle search now uses RsEvents. void NotifyQt::notifyTurtleSearchResult(const RsPeerId& pid,uint32_t search_id,const std::list& files) { { @@ -492,6 +509,7 @@ void NotifyQt::notifyTurtleSearchResult(const RsPeerId& pid,uint32_t search_id,c emit gotTurtleSearchResult(search_id,det) ; } } +#endif void NotifyQt::notifyHistoryChanged(uint32_t msgId, int type) { @@ -548,18 +566,6 @@ void NotifyQt::notifyListChange(int list, int type) break; case NOTIFY_LIST_SEARCHLIST: break; - case NOTIFY_LIST_MESSAGELIST: -#ifdef NOTIFY_DEBUG - std::cerr << "received msg changed" << std::endl ; -#endif - emit messagesChanged() ; - break; - case NOTIFY_LIST_MESSAGE_TAGS: -#ifdef NOTIFY_DEBUG - std::cerr << "received msg tags changed" << std::endl ; -#endif - emit messagesTagsChanged(); - break; case NOTIFY_LIST_CHANNELLIST: break; case NOTIFY_LIST_TRANSFERLIST: @@ -648,8 +654,6 @@ void NotifyQt::notifyListPreChange(int list, int /*type*/) break; case NOTIFY_LIST_SEARCHLIST: break; - case NOTIFY_LIST_MESSAGELIST: - break; case NOTIFY_LIST_CHANNELLIST: break; case NOTIFY_LIST_TRANSFERLIST: @@ -682,7 +686,6 @@ void NotifyQt::UpdateGUI() // the gui is running, then they get updated by callbacks. if(!already_updated) { - emit messagesChanged() ; emit neighboursChanged(); emit configChanged(); @@ -1162,3 +1165,123 @@ void NotifyQt::runningTick() } } +void NotifyQt::addToaster(uint notifyFlags, const std::string& id, const std::string& title, const std::string& msg) +{ + uint pos = 0; + + while (notifyFlags) { + uint type = notifyFlags & (1 << pos); + notifyFlags &= ~(1 << pos); + ++pos; + + ToasterItem *toaster = NULL; + + uint popupflags = Settings->getNotifyFlags(); + + switch(type) + { + case RS_POPUP_ENCRYPTED_MSG: + SoundManager::play(SOUND_MESSAGE_ARRIVED); + + if ((popupflags & RS_POPUP_MSG) && !_disableAllToaster) + { + toaster = new ToasterItem(new MessageToaster(std::string(), tr("Unknown title"), QString("[%1]").arg(tr("Encrypted message")))); + } + break; + case RS_POPUP_MSG: + SoundManager::play(SOUND_MESSAGE_ARRIVED); + + if ((popupflags & RS_POPUP_MSG) && !_disableAllToaster) + { + toaster = new ToasterItem(new MessageToaster(id, QString::fromUtf8(title.c_str()), QString::fromUtf8(msg.c_str()))); + } + break; + case RS_POPUP_CONNECT: + SoundManager::play(SOUND_USER_ONLINE); + + if ((popupflags & RS_POPUP_CONNECT) && !_disableAllToaster) + { + toaster = new ToasterItem(new OnlineToaster(RsPeerId(id))); + } + break; + case RS_POPUP_DOWNLOAD: + SoundManager::play(SOUND_DOWNLOAD_COMPLETE); + + if ((popupflags & RS_POPUP_DOWNLOAD) && !_disableAllToaster) + { + toaster = new ToasterItem(new DownloadToaster(RsFileHash(id), QString::fromUtf8(title.c_str()))); + } + break; + case RS_POPUP_CHAT: + if ((popupflags & RS_POPUP_CHAT) && !_disableAllToaster) + { + // TODO: fix for distant chat, look up if dstant chat uses RS_POPUP_CHAT + ChatDialog *chatDialog = ChatDialog::getChat(ChatId(RsPeerId(id))); + ChatWidget *chatWidget; + if (chatDialog && (chatWidget = chatDialog->getChatWidget()) && chatWidget->isActive()) { + // do not show when active + break; + } + toaster = new ToasterItem(new ChatToaster(RsPeerId(id), QString::fromUtf8(msg.c_str()))); + } + case RS_POPUP_GROUPCHAT: +#ifdef RS_DIRECT_CHAT + if ((popupflags & RS_POPUP_GROUPCHAT) && !_disableAllToaster) + { + MainWindow *mainWindow = MainWindow::getInstance(); + if (mainWindow && mainWindow->isActiveWindow() && !mainWindow->isMinimized()) { + if (MainWindow::getActivatePage() == MainWindow::Friends) { + if (FriendsDialog::isGroupChatActive()) { + // do not show when active + break; + } + } + } + toaster = new ToasterItem(new GroupChatToaster(RsPeerId(id), QString::fromUtf8(msg.c_str()))); + } +#endif // RS_DIRECT_CHAT + break; + case RS_POPUP_CHATLOBBY: + if ((popupflags & RS_POPUP_CHATLOBBY) && !_disableAllToaster) + { + ChatId chat_id(id); + + ChatDialog *chatDialog = ChatDialog::getChat(chat_id); + ChatWidget *chatWidget; + if (chatDialog && (chatWidget = chatDialog->getChatWidget()) && chatWidget->isActive()) { + // do not show when active + break; + } + + ChatLobbyDialog *chatLobbyDialog = dynamic_cast(chatDialog); + + RsGxsId sender(title); + if (!chatLobbyDialog || chatLobbyDialog->isParticipantMuted(sender)) + break; // participant is muted + + toaster = new ToasterItem(new ChatLobbyToaster(chat_id.toLobbyId(), sender, QString::fromUtf8(msg.c_str()))); + } + break; + case RS_POPUP_CONNECT_ATTEMPT: + if ((popupflags & RS_POPUP_CONNECT_ATTEMPT) && !_disableAllToaster) + { + // id = gpgid + // title = ssl name + // msg = peer id + toaster = new ToasterItem(new FriendRequestToaster(RsPgpId(id), QString::fromUtf8(title.c_str()), RsPeerId(msg))); + } + break; + } + + if (toaster) { + /* init attributes */ + toaster->widget->setWindowFlags(Qt::ToolTip | Qt::WindowStaysOnTopHint); + + /* add toaster to waiting list */ + //QMutexLocker lock(&waitingToasterMutex); + waitingToasterList.push_back(toaster); + } + } + /* Now start the waiting toasters */ + startWaitingToasters(); +} diff --git a/retroshare-gui/src/gui/notifyqt.h b/retroshare-gui/src/gui/notifyqt.h index 069ae8056..5782ef5b7 100644 --- a/retroshare-gui/src/gui/notifyqt.h +++ b/retroshare-gui/src/gui/notifyqt.h @@ -67,7 +67,9 @@ class NotifyQt: public QObject, public NotifyClient virtual void notifyChatStatus(const ChatId &chat_id,const std::string& status_string); virtual void notifyChatCleared(const ChatId &chat_id); virtual void notifyCustomState(const std::string& peer_id, const std::string& status_string); +#ifdef TO_REMOVE virtual void notifyTurtleSearchResult(const RsPeerId &pid, uint32_t search_id, const std::list& found_files); +#endif virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list& found_groups); virtual void notifyPeerHasNewAvatar(std::string peer_id) ; virtual void notifyOwnAvatarChanged() ; @@ -95,6 +97,7 @@ class NotifyQt: public QObject, public NotifyClient void testToaster(ToasterNotify *toasterNotify, /*RshareSettings::enumToasterPosition*/ int position, QPoint margin); void testToaster(QString tag, ToasterNotify *toasterNotify, /*RshareSettings::enumToasterPosition*/ int position, QPoint margin); + void addToaster(uint notifyFlags, const std::string& id, const std::string& title, const std::string& msg); void notifySettingsChanged(); signals: @@ -109,14 +112,11 @@ class NotifyQt: public QObject, public NotifyClient void lobbyListChanged() const ; void chatLobbyEvent(qulonglong,int,const RsGxsId&,const QString&) ; void neighboursChanged() const ; - void messagesChanged() const ; - void messagesTagsChanged() const; void configChanged() const ; void logInfoChanged(const QString&) const ; void chatStatusChanged(const ChatId&,const QString&) const ; void chatCleared(const ChatId&) const ; void peerHasNewCustomStateString(const QString& /* peer_id */, const QString& /* status_string */) const ; - void gotTurtleSearchResult(qulonglong search_id,FileDetail file) const ; void peerHasNewAvatar(const QString& peer_id) const ; void ownAvatarChanged() const ; void ownStatusMessageChanged() const ; diff --git a/retroshare-gui/src/gui/profile/ProfileManager.ui b/retroshare-gui/src/gui/profile/ProfileManager.ui index 9ec918e89..a2ffe541b 100644 --- a/retroshare-gui/src/gui/profile/ProfileManager.ui +++ b/retroshare-gui/src/gui/profile/ProfileManager.ui @@ -23,27 +23,36 @@ Profile Manager
    - + :/images/logo/logo_16.png:/images/logo/logo_16.png - - + + + 0 + + + 0 + + + 0 + + 0 0 - + 0 30 - + - + @@ -54,12 +63,12 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html>
    @@ -71,11 +80,11 @@ p, li { white-space: pre-wrap; }
    - + Full keys available in your keyring: - + diff --git a/retroshare-gui/src/gui/profile/ProfileWidget.cpp b/retroshare-gui/src/gui/profile/ProfileWidget.cpp index b6418ae56..670bb86c7 100644 --- a/retroshare-gui/src/gui/profile/ProfileWidget.cpp +++ b/retroshare-gui/src/gui/profile/ProfileWidget.cpp @@ -45,13 +45,13 @@ ProfileWidget::ProfileWidget(QWidget *parent, Qt::WindowFlags flags) connect(ui.CopyCertButton,SIGNAL(clicked()), this, SLOT(copyCert())); connect(ui.profile_Button,SIGNAL(clicked()), this, SLOT(profilemanager())); - ui.onlinesince->setText(DateTime::formatLongDateTime(Rshare::startupTime())); + ui.onLineSince->setText(DateTime::formatLongDateTime(RsApplication::startupTime())); } void ProfileWidget::showEvent ( QShowEvent * /*event*/ ) { /* set retroshare version */ - ui.version->setText(Rshare::retroshareVersion(true)); + ui.version->setText(RsApplication::retroshareVersion(true)); RsPeerDetails detail; if (rsPeers->getPeerDetails(rsPeers->getOwnId(),detail)) @@ -59,7 +59,7 @@ void ProfileWidget::showEvent ( QShowEvent * /*event*/ ) ui.name->setText(QString::fromUtf8(detail.name.c_str())); ui.country->setText(QString::fromUtf8(detail.location.c_str())); - ui.peerid->setText(QString::fromStdString(detail.id.toStdString())); + ui.peerId->setText(QString::fromStdString(detail.id.toStdString())); ui.ipAddressList->clear(); for(std::list::const_iterator it(detail.ipAddressList.begin());it!=detail.ipAddressList.end();++it) diff --git a/retroshare-gui/src/gui/profile/ProfileWidget.ui b/retroshare-gui/src/gui/profile/ProfileWidget.ui index 4462acad5..2bd1fae73 100644 --- a/retroshare-gui/src/gui/profile/ProfileWidget.ui +++ b/retroshare-gui/src/gui/profile/ProfileWidget.ui @@ -16,17 +16,35 @@ 0 - - + + 0 - + + 0 + + + 0 + + + 0 + + 0 - - + + + 2 + + + 2 + + + 2 + + 2 @@ -41,7 +59,7 @@ Edit status message - + :/images/edit_16.png:/images/edit_16.png @@ -61,7 +79,7 @@ Copy Certificate - + :/images/view-certificate-copy-32.png:/images/view-certificate-copy-32.png @@ -81,7 +99,7 @@ Profile Manager - + :/images/contact_new.png:/images/contact_new.png @@ -99,7 +117,7 @@ - + Qt::Horizontal @@ -128,18 +146,18 @@ 569 - + - + QFrame::Box QFrame::Sunken - + - + @@ -154,9 +172,10 @@ - + + 12 75 true @@ -169,7 +188,7 @@ - + 0 @@ -207,7 +226,7 @@ - + 0 @@ -245,7 +264,7 @@ - + 0 @@ -264,7 +283,7 @@ - + 0 @@ -286,16 +305,16 @@ - + QFrame::Box QFrame::Sunken - + - + 0 @@ -333,7 +352,7 @@ - + 0 @@ -352,7 +371,7 @@ - + 0 @@ -390,7 +409,7 @@ - + 0 @@ -409,7 +428,7 @@ - + @@ -427,9 +446,10 @@ - + + 12 75 true @@ -445,16 +465,16 @@ - + QFrame::Box QFrame::Sunken - + - + @@ -472,9 +492,10 @@ - + + 12 75 true @@ -487,7 +508,7 @@ - + 0 @@ -547,7 +568,7 @@ - + 0 @@ -566,7 +587,7 @@ - + Qt::Horizontal @@ -620,7 +641,7 @@ - + Qt::Horizontal @@ -633,7 +654,7 @@ - + Qt::Horizontal @@ -646,7 +667,7 @@ - + 0 @@ -675,7 +696,7 @@ - + 100 @@ -722,13 +743,6 @@ - - - StyledLabel - QLabel -
    gui/common/StyledLabel.h
    -
    -
    diff --git a/retroshare-gui/src/gui/profile/StatusMessage.ui b/retroshare-gui/src/gui/profile/StatusMessage.ui index 0f537c280..c5a29369f 100644 --- a/retroshare-gui/src/gui/profile/StatusMessage.ui +++ b/retroshare-gui/src/gui/profile/StatusMessage.ui @@ -35,7 +35,7 @@ :/images/logo/logo_16.png:/images/logo/logo_16.png
    - + 9 @@ -44,12 +44,7 @@ 113 - - QFrame#frame{background: white; -border: 1px solid #CCCCCC;} - - - + 91 @@ -73,7 +68,7 @@ border: 1px solid #CCCCCC;} - + 100 @@ -90,7 +85,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Status message</span></p></body></html> - + 100 @@ -107,7 +102,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your message</span></p></body></html> - + 20 @@ -129,7 +124,7 @@ p, li { white-space: pre-wrap; } :/images/user/personal64.png - + 0 @@ -138,14 +133,6 @@ p, li { white-space: pre-wrap; } 241 - - QFrame#frame_2{ -background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, -stop:0 #FEFEFE, stop:1 #E8E8E8); - -border: 1px solid #CCCCCC;} - - QFrame::StyledPanel @@ -166,11 +153,11 @@ border: 1px solid #CCCCCC;} - frame_2 - frame - label_3 - label_2 - label + gradFrame + plainBFrame + statusLabel + enterMsgLabel + iconLabel diff --git a/retroshare-gui/src/gui/qss/stylesheet/Standard.qss b/retroshare-gui/src/gui/qss/stylesheet/Standard.qss deleted file mode 100644 index 442055f3b..000000000 --- a/retroshare-gui/src/gui/qss/stylesheet/Standard.qss +++ /dev/null @@ -1,1231 +0,0 @@ -/* Standard stylesheet for RetroShare */ - -/* Standard rules */ - -QFrame#toolBarFrame, QFrame#toolBarFrameTop { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FEFEFE, stop:1 #E8E8E8); - border: 1px solid #CCCCCC; -} - -/* HeaderFrame */ - -HeaderFrame > QFrame#frame { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #9BDBF9, stop:1 #1592CD); - border: 0px; -} - -HeaderFrame > QFrame#frame > QLabel#headerLabel { - color: rgb(255, 255, 255); -} - -AvatarDialog QFrame#infoframe -{ - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -/* GenCertDialog */ - -GenCertDialog QLabel#genprofileinfo_label, QLabel#header_label, QLabel#entropy_label -{ - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -GenCertDialog QLabel#label_hiddenaddr { - border: 1px solid #50FF5B; - border-radius: 6px; - background: #CCFFCC; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #CCFFCC, stop:1 #AAFFAA); -} -GenCertDialog QLabel#no_node_label, GenCertDialog QLabel#no_gpg_key_label { - border: 1px solid #FFC550; - border-radius: 6px; - background: #FFEECC; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFEECC, stop:1 #FFE3AB); - padding: 4px; - font-size: 14pt; -} - -GenCertDialog > QFrame#headerFrame > QLabel#headerLabel { - color: rgb(255, 255, 255); -} - -GenCertDialog > QFrame#frame { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FEFEFE, stop:1 #E8E8E8); - border: 1px solid #CCCCCC; -} - -/* ConnectFriendWizard */ - -ConnectFriendWizard { -/* QWizard cannot be resized horizontal when banner pixmap is set - qproperty-bannerPixmap: url(:/images/connect/connectFriendBanner1.png);*/ - qproperty-titleFontSize: 16; - qproperty-titleFontWeight: 500; -/* qproperty-titleColor: white; */ -} - -/* FriendsDialog */ - -FriendsDialog QFrame#headFrame { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #9BDBF9, stop:1 #1592CD); - border: 1px; - border-radius: 4px; -} - -FriendsDialog QFrame#headFrame > QLabel#nicknameLabel { - color: rgb(255, 255, 255); -} - -FriendsDialog QTextEdit#msgText, FriendsDialog QTextEdit#lineEdit { - border: 1px solid #CCCCCC; -} - -/* Channels */ - -ChannelFeed QFrame#headFrame { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #F2F2F2, stop:1 #E6E6E6); - border: 1px solid #CCCCCC; -} - -ChannelFeed QLabel#logoLabel, EditChanDetails QLabel#logoLabel, CreateChannel QLabel#logoLabel { - border: 2px solid white; -} - -CreateChannelMsg QFrame#fileFrame { - border: 2px solid black; - background: white; -} - -GxsCreateCommentDialog QTextEdit#commentTextEdit { - border: 2px solid #0099cc; - border-radius: 6px; - background: white; -} - -GxsCreateCommentDialog QLabel#titleLabel { - font-size: 12pt; - font-weight: 600; - color: black; -} - -GxsCreateCommentDialog QLabel#replaytolabel { - font-weight: bold; - color: gray; -} - -GxsCreateCommentDialog QFrame#frame { - background: white; -} - -CreateGxsChannelMsg QPushButton#postButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -CreateGxsChannelMsg QPushButton#postButton:hover { - background: #03b1f3; - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - -CreateCircleDialog QPushButton#createButton, CreateLobbyDialog QPushButton#createButton, -IdEditDialog QPushButton#createButton, CreateGxsForumMsg QPushButton#postButton, -GxsCreateCommentDialog QPushButton#postButton, GxsGroupDialog QPushButton#createButton, -PulseAddDialog QPushButton#pushButton_Post, PulseTopLevel QToolButton#toolButton_follow, -PulseViewGroup QToolButton#toolButton_follow, WikiEditDialog QPushButton#pushButton_Submit{ - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 20px; - min-width: 4em; - padding: 2px; - padding-left: 6px; - padding-right: 6px; -} - -CreateCircleDialog QPushButton#createButton:hover, CreateLobbyDialog QPushButton#createButton:hover, -IdEditDialog QPushButton#createButton:hover, CreateGxsForumMsg QPushButton#postButton:hover, -GxsCreateCommentDialog QPushButton#postButton:hover, GxsGroupDialog QPushButton#createButton:hover, -ShareManager QPushButton#closeButton:hover, PulseAddDialog QPushButton#pushButton_Post:hover, -PulseTopLevel QToolButton#toolButton_follow:hover, PulseViewGroup QToolButton#toolButton_follow:hover, -WikiEditDialog QPushButton#pushButton_Submit:hover{ - background: #03b1f3; - border-radius: 4px; - min-width: 4em; - padding: 2px; - padding-left: 6px; - padding-right: 6px; -} - -ShareManager QPushButton#closeButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; - padding-left: 6px; - padding-right: 6px; -} - -ShareManager QPushButton#addButton{ - font: bold; - font-size: 12pt; - color: white; - background: #32CD32; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 4px; -} - -ShareManager QPushButton#addButton:hover{ - background: #5AD75A; - border-radius: 4px; - min-width: 4em; - padding: 4px; -} - -SearchDialog QPushButton#pushButtonSearch { - font: bold; - font-size: 12pt; - color: white; - background: #32CD32; - border-radius: 4px; - max-height: 25px; - min-width: 4em; - padding: 4px; -} - -SearchDialog QPushButton#pushButtonSearch:hover{ - background: #5AD75A; - border-radius: 4px; - min-width: 4em; - padding: 4px; -} - -CreateGxsForumMsg QPushButton#postButton:disabled, PostedCreatePostDialog QPushButton#submitButton:disabled, -CreateGxsChannelMsg QPushButton#postButton:disabled, GxsCreateCommentDialog QPushButton#postButton:disabled, -PulseAddDialog QPushButton#pushButton_Post:disabled, WikiEditDialog QPushButton#pushButton_Submit:disabled { - font: bold; - font-size: 12pt; - color: white; - background: #d40000; - border-radius: 4px; - max-height: 20px; - min-width: 4em; - padding-left: 6px; - padding-right: 6px; -} - -/* Forums */ - -GxsForumThreadWidget QPushButton#forumName -{ - font: bold; - font-size: 12pt; -} - -CreateForumMsg > QToolBar#toolBar, CreateForumV2Msg > QToolBar#toolBar { - background-image: url(:/images/headerFrame.png); -} - -/* MessengerWindow */ - -MessengerWindow QFrame#logoFrame { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FEFEFE, stop:1 #E8E8E8); - border: 1px solid #CCCCCC; -} - -MessengerWindow QFrame#messengerframetop{ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #9BDBF9, stop:1 #1592CD); - border: 0px; -} - -/* Create Distant Chat Invite */ - -CreateMsgLinkDialog QLabel#distantchatinfo_label -{ - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -/* Chat lobby */ - -ChatLobbyWidget QLabel#lobbyinfo_label -{ - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -ChatLobbyWidget QLabel#lobbyname_lineEdit -{ - font: bold; - font-size: 16pt; -} - -ChatLobbyWidget QGroupBox#lobbyinfo_groupBox -{ - - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FEFEFE, stop:1 #E8E8E8); - border-radius: 6px; - border: 1px solid #CCCCCC; - - padding: 14 6px; - font-size: 12pt; - font-weight: bold; - -} - -ChatLobbyWidget QGroupBox::title#lobbyinfo_groupBox -{ - padding: 4 12px; - background: #039bd5; - color: white; -} - -ChatLobbyWidget QLabel#lobbyInfoLabel { - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - - -ChatLobbyDialog QFrame#participantsFrame { - border: transparent; -} - -ChatLobbyDialog QListWidget#participantsList { - border: 1px solid #B8B6B1; - border-radius: 6px; - background: white; -} - -CreateLobbyDialog QFrame#roomFrame { - border: 2px solid #CCCCCC; - border-radius:6px; - background: white; -} - -CreateLobbyDialog QLabel#lobbyInfoLabel { - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -ChatWidget QTextEdit#chatTextEdit, ChatWidget QTextBrowser#textBrowser { - border: 1px solid #0099cc; - border-radius: 6px; - background: white; -} - -ChatWidget QFrame#infoFrame { - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -ChatWidget QFrame#titleBarFrame, QFrame#toolBarFrameTop { - -} - -PopupChatWindow QToolBar#chattoolBar{ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #9BDBF9, stop:1 #1592CD); - border: 0px; -} - -/* Messages */ - -MessageComposer QToolBar#toolBar { - -} - -MessagesDialog QFrame#folderFrame, MessagesDialog QFrame#quickViewFrame { - background: transparent; - -} - -/* Profile */ - -ProfileWidget QFrame#frame_1, ProfileWidget QFrame#frame_2, ProfileWidget QFrame#frame_3 { - background-color: white; - border: 2px solid #CCCCCC; -} - -/* Settings */ - -PluginItem > QFrame#frame { - border: 2px solid #A8B8D1; - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FCFDFE, stop: 1 #E2E8EF); - border-radius: 0px -} - -/* Network */ - -/*NetworkView > QGraphWidget#graphicsView -{ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); -} -*/ - -/* GetStartedDialog */ - -GetStartedDialog QTextEdit { - border: 1px solid #B8B6B1; - border-radius: 6px; - background: white; -} - -/* GenCertDialog */ - -/* GenCertDialog > QFrame#headerFrame { - background-image: url(:/images/genbackground.png); -} - -GenCertDialog > QFrame#headerFrame > QLabel#headerLabel { - color: rgb(255, 255, 255); -} -*/ - -/* ConnectFriendWizard */ - -ConnectFriendWizard QWizardPage#ConclusionPage > QGroupBox#peerDetailsFrame { - border: 2px solid #039bd5; - border-radius:6px; - background: white; - padding: 12 12px; -} - -ConnectFriendWizard QLabel#fr_label, QLabel#requestinfolabel, QLabel#cp_Label -{ - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -ConnectFriendWizard QGroupBox::title#peerDetailsFrame -{ - padding: 4 12px; - background: transparent; - padding: 4 12px; - background: #039bd5; - color: white; -} - -/* Toaster */ - -ChatToaster > QFrame#windowFrame, -ChatLobbyToaster > QFrame#windowFrame, -DownloadToaster > QFrame#windowFrame, -FriendRequestToaster > QFrame#windowFrame, -GroupChatToaster > QFrame#windowFrame, -MessageToaster >QFrame#windowFrame, -OnlineToaster > QFrame#windowFrame { - background-image: url(:/images/toaster/backgroundtoaster.png); -} - -/* Feeds */ - -AttachFileItem > QFrame#frame { - border: 2px solid black; - background: white; -} - -ChanNewItem > QFrame#frame { - border: 2px solid #D3D3D3; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFFF, stop:1 #F2F2F2); - border-radius: 10px; -} - -ChanNewItem QLabel#logoLabel { - border: 2px solid #D3D3D3; - border-radius: 2px; -} - -GxsChannelPostItem > QFrame#mainFrame[new=false] { - background-color: white; -} - -GxsChannelPostItem > QFrame#mainFrame[new=true] { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #F0F8FD, stop:0.8 #E6F2FD, stop: 0.81 #E6F2FD, stop: 1 #D2E7FD); -} - -GxsChannelPostItem QLabel#newLabel{ - border: 1px solid #167BE7; - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2291E0, stop: 1 #3EB3FF); - border-radius: 3px; - color: white; -} - -GxsChannelPostItem QLabel#subjectLabel, GxsChannelPostItem QLabel#titleLabel { - font: 11pt; - font: bold italic; -} - -GxsChannelPostItem QFrame#msgFrame { - border: 2px solid #82B9F4; - border-radius: 3px; -} - -GxsChannelPostItem QLabel#logoLabel { - border: 2px solid #D3D3D3; -} - -GxsChannelPostItem QLabel#logoLabel { - background-color: black; -} - -GxsCircleItem QFrame#mainFrame { - background-color: white; -} - -GxsCircleItem QLabel#gxsIdLabel, QLabel#nameLabel, QLabel#titleLabel { - font: 11pt; - font: bold italic; -} - - -ForumNewItem > QFrame#frame, ForumMsgItem > QFrame#frame { - border: 2px solid #CCCCCC; - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #EEEEEE, stop: 1 #CCCCCC); - border-radius: 10px; -} - -ForumNewItem > QLabel#nextNameLabel, ForumMsgItem > QLabel#nameLabel { - color: rgb(59, 89, 152); -} - -ForumMsgItem QLabel#iconLabel { - border: 2px solid #CCCCCC; - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #EEEEEE, stop: 1 #CCCCCC); - border-radius: 10px -} - -ForumMsgItem QFrame#prevFrame { - border: 2px solid black; - border-radius: 10px; -} - -SubFileItem QProgressBar#progressBar { - border: 1px solid black; - text-align: center; - color: white; - padding: 1px; - border-top-left-radius: 7px; - border-bottom-left-radius: 7px; - background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #fff, stop: 0.4999 #eee, stop: 0.5 #ddd, stop: 1 #eee); - min-width: 15px; -} - -SubFileItem QProgressBar#progressBar::chunk { - background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #78d, stop: 0.4999 #46a, stop: 0.5 #45a, stop: 1 #238); - border-top-left-radius: 7px; - border-bottom-left-radius: 7px; - border: 1px solid black; - min-width: 15px; -} - -PluginItem QLabel#infoLabel { - - color: #054A02; - font: bold; - -} - -ConfCertDialog QPlainTextEdit#plainTextEdit { - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -ServerPage QPlainTextEdit#plainTextEdit { - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -ServerPage QPlainTextEdit#hiddenpageInHelpPlainTextEdit { - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -ServerPage QPlainTextEdit#pteBobSimple { - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - - -/* ProfileManager */ - -ProfileManager > QFrame#headerFrame { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #9BDBF9, stop:1 #1592CD); - border: 1px solid #CCCCCC; -} - -ProfileManager QTextEdit#textEdit -{ - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -/* RSImageBlockWidget */ - -RSImageBlockWidget QFrame#infoFrame { - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -/* ShareManager */ - -ShareManager QLabel#labelInstructions { - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -/* MessageWidget */ - -MessageWidget QFrame#decryptFrame { - border: 1px solid #50FF5B; - border-radius: 6px; - background: #CCFFCC; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #CCFFCC, stop:1 #AAFFAA); -} - -MessageWidget QFrame#inviteFrame { - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -/* Posted Links */ - -PostedCreatePostDialog QLabel#info_label { - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -QLabel#sharekeyinfo_label{ - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -QLabel#subscribersLabel{ - border: 1px solid #CCCCCC; - border-radius: 6px; - -} - -QFrame#distantFrame{ - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -QLabel#avatarLabel{ - border: 2px solid #CCCCCC; - border-radius: 4px; -} - -IdDialog QFrame#headerFramePerson { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #9BDBF9, stop:1 #1592CD); - border: 1px; - border-radius: 4px; -} - -IdDialog QFrame#headerFrameCircle { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #9BDBF9, stop:1 #1592CD); - border: 1px; - border-radius: 4px; -} - -IdDialog QLabel#headerTextLabel { - color: rgb(255, 255, 255); -} - -IdDialog QLabel#headerTextLabel_Person { - color: rgb(255, 255, 255); -} - -IdDialog QLabel#headerTextLabel_Circles { - color: rgb(255, 255, 255); -} - -IdDialog QLabel#avlabel { - border: 4px solid white; - border-radius: 10px; -} - -IdDialog QFrame#inviteFrame { - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -IdEditDialog QLabel#info_label -{ - border: 1px solid #DCDC41; - border-radius: 6px; - background: #FFFFD7; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -GenCertDialog QComboBox#genPGPuser { - border: 2px solid #0099cc; - border-radius: 6px; - background: white; - font: bold; -} - -GenCertDialog QSpinBox#hiddenport_spinBox { - border: 2px solid #0099cc; - border-radius: 6px; - background: white; - font: bold; -} - -GenCertDialog QLineEdit#hiddenaddr_input { - border: 2px solid #0099cc; - border-radius: 6px; - background: white; - font: bold; -} - -GenCertDialog QLineEdit#password2_input { - border: 2px solid #0099cc; - border-radius: 6px; - background: white; - font: bold; -} - -GenCertDialog QLineEdit#password_input { - border: 2px solid #0099cc; - border-radius: 6px; - background: white; - font: bold; -} - -GenCertDialog QLineEdit#nickname_input { - border: 2px solid #0099cc; - border-radius: 6px; - background: white; - font: bold; -} - -GenCertDialog QLineEdit#node_input { - border: 2px solid #0099cc; - border-radius: 6px; - background: white; - font: bold; -} - -GenCertDialog QLineEdit#name_input { - border: 2px solid #0099cc; - border-radius: 6px; - background: white; - font: bold; -} - -GenCertDialog QPushButton#genButton { - border-image: url(:/images/btn_blue.png) 4; - border-width: 4; - font: bold; - color: white; -} - -GenCertDialog QPushButton#genButton:hover { - border-image: url(:/images/btn_blue_hover.png) 4; -} - -GenCertDialog QPushButton#genButton:disabled { - border-image: url(:/images/btn_27.png) 4; -/* font-size: 16pt; */ - font: bold; - color: black; -} - -ConnectFriendWizard QRadioButton { - font-size: 16pt; -} - -ConnectFriendWizard QPlainTextEdit#friendCertEdit { - border: none; - background: white; -} - -ConnectFriendWizard QFrame#friendFrame { - border: 2px solid #0099cc; - border-radius: 6px; - background: white; -} - -StartDialog QPushButton#loadButton { - border-image: url(:/images/btn_blue.png) 4; - border-width: 4; - font: bold; - color: white; -} - -StartDialog QPushButton#loadButton:hover { - border-image: url(:/images/btn_blue_hover.png) 4; -} - -StartDialog QFrame#loginframe{ - border-image: url(:/images/logo/background_lessblue.png) 0 0 0 0 stretch stretch; - border-width: 0px; -} - -GenCertDialog QFrame#profileframe{ - border-image: url(:/images/logo/background.png) 0 0 0 0 stretch stretch; - border-width: 0px; -} - -PostedListWidgetWithModel QComboBox#sortStrategy_CB { - font: bold; - color: #0099cc; -} - -PostedListWidgetWithModel QToolButton#submitPostButton, GxsChannelPostsWidgetWithModel QToolButton#postButton, -GxsForumThreadWidget QToolButton#newthreadButton { - font: bold; -} - -PostedListWidgetWithModel QToolButton#subscribeToolButton { - font: bold; - font-size: 15pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; -} - -PostedListWidgetWithModel QToolButton#subscribeToolButton:hover { - background: #03b1f3; - border-radius: 4px; -} - -PostedListWidgetWithModel QFrame#headerFrame { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FEFEFE, stop:1 #E8E8E8); - border: 1px solid #CCCCCC; -} - -GxsForumThreadWidget QToolButton#subscribeToolButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; -} - -GxsForumThreadWidget QToolButton#subscribeToolButton:hover { - background: #03b1f3; - border-radius: 4px; -} - -GxsForumMsgItem QFrame#mainFrame, PeerItem QFrame#mainFrame, GxsForumGroupItem QFrame#mainFrame, -GxsChannelGroupItem QFrame#mainFrame, MsgItem QFrame#mainFrame, ChatMsgItem QFrame#mainFrame -SecurityIpItem QFrame#mainFrame, MsgItem QFrame#msgFrame, SecurityItem QFrame#mainFrame{ - background-color: white; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton:hover { - background: #03b1f3; - border-radius: 4px; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton:pressed { - background: #03b1f3; - border-radius: 4px; - border: 1px solid gray; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton:disabled { - background: gray; - border-radius: 4px; - border: 1px solid gray; - color: lightgray; -} - -/* only for MenuButtonPopup */ - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton[popupMode="1"], -PostedListWidgetWithModel QToolButton#subscribeToolButton[popupMode="1"]{ - padding-right: 0px; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton::menu-arrow, -PostedListWidgetWithModel QToolButton#subscribeToolButton::menu-arrow{ - image: none; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton::menu-button, -PostedListWidgetWithModel QToolButton#subscribeToolButton::menu-button{ - image: none; -} - -GxsChannelFilesStatusWidget QToolButton#openFolderToolButton::menu-indicator { - image: none; -} - -GxsChannelFilesStatusWidget QToolButton#openFolderToolButton[popupMode="0"] { - padding-right: 0px; -} - -GxsChannelFilesStatusWidget QToolButton#openFolderToolButton::menu-indicator { - image: none; -} - -GxsChannelFilesStatusWidget QToolButton#openFolderToolButton[popupMode="0"] { - padding-right: 0px; -} - -GxsGroupDialog QLabel#groupLogo{ - border: 2px solid #CCCCCC; - border-radius: 3px; -} - -GxsChannelGroupItem QFrame#frame, GxsForumGroupItem QFrame#frame, -PostedGroupItem QFrame#frame { - background-color: white; -} - -HomePage QLabel#userCertLabel { - color: #0099cc; - font: bold; -} - -HomePage QPlainTextEdit#userCertEdit { - - background: transparent; -} - -HomePage QToolButton#addButton { - font: bold; - font-size: 15pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -HomePage QToolButton#addButton:hover { - background: #03b1f3; - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - - -PostedItem QFrame#mainFrame { - background-color: white; -} - -PostedItem > QFrame#mainFrame [new=false]{ - background: white; -} - -PostedItem QFrame#voteFrame { - background: #f8f9fa; -} - -BoardPostDisplayWidget_compact QFrame#mainFrame { - background-color: white; -} - -BoardPostDisplayWidget_compact > QFrame#mainFrame [new=false]{ - background: white; -} - -BoardPostDisplayWidget_compact > QFrame#mainFrame[new=true] { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #F0F8FD, stop:0.8 #E6F2FD, stop: 0.81 #E6F2FD, stop: 1 #D2E7FD); -} - -BoardPostDisplayWidget_compact QLabel#pictureLabel{ - border: 2px solid #CCCCCC; - border-radius: 3px; -} - -BoardPostDisplayWidget_compact QLabel#fromBoldLabel , -BoardPostDisplayWidget_card QLabel#fromBoldLabel { - font: bold; -} - -BoardPostDisplayWidget_compact QLabel#fromBoldLabel, QLabel#fromLabel, QLabel#dateLabel, QLabel#siteBoldLabel , -BoardPostDisplayWidget_card QLabel#fromBoldLabel, QLabel#fromLabel, QLabel#dateLabel, QLabel#siteBoldLabel{ - color: #787c7e; -} - -BoardPostDisplayWidget_compact QLabel#newLabel { - border: 1px solid #167BE7; - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2291E0, stop: 1 #3EB3FF); - border-radius: 3px; -} - -BoardPostDisplayWidget_card QLabel#newLabel { - border: 1px solid #167BE7; - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2291E0, stop: 1 #3EB3FF); - border-radius: 3px; -} - -PostedCardView QFrame#voteFrame { - background: #f8f9fa; -} - -BoardPostDisplayWidget_card QFrame#mainFrame{ - background: white; -} - -BoardPostDisplayWidget_card > QFrame#mainFrame [new=false]{ - background: white; -} - -BoardPostDisplayWidget_card > QFrame#mainFrame[new=true] { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #F0F8FD, stop:0.8 #E6F2FD, stop: 0.81 #E6F2FD, stop: 1 #D2E7FD); -} - -BoardPostDisplayWidget_compact QLabel#titleLabel, -BoardPostDisplayWidget_card QLabel#titleLabel{ - font-size: 12pt; - font: bold; -} - -GxsCommentDialog QComboBox#sortBox { - font: bold; - color: #0099cc; -} - -PostedListWidgetWithModel QTextBrowser#infoDescription { - background: transparent; - border: none; -} - -PostedCreatePostDialog QPushButton#submitButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -PostedCreatePostDialog QPushButton#submitButton:hover { - background: #03b1f3; - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - -MessageWidget QTextBrowser#toText , QTextBrowser#ccText , QTextBrowser#bccText { - background: transparent; - border: none; -} - -WireGroupItem QWidget:hover{ - background-color: #7ecbfb; -} - -WireDialog QFrame#frame{ - background-color: white; -} - -WireDialog QWidget#scrollAreaWidgetContents_groups{ - background-color: white; -} - -MessagesDialog QWidget#messageTreeWidget::item { - padding: 2px; -} - -MessagesDialog QWidget#messageTreeWidget::item:selected { - background-color: #cde8ff; - color: black; -} - -MessagesDialog QWidget#messageTreeWidget::item:hover { - background-color: #e5f3ff; - color: black; -} - -GxsForumThreadWidget QWidget#threadTreeWidget { - selection-background-color: #cde8ff; - show-decoration-selected: 1; -} - -GxsForumThreadWidget QWidget#threadTreeWidget::item { - padding: 2px; -} - -GxsForumThreadWidget QWidget#threadTreeWidget::item:selected:active , -GxsForumThreadWidget QWidget#threadTreeWidget::item:selected:!active { - background-color: #cde8ff; -} - -GxsChannelDialog GroupTreeWidget QTreeWidget#treeWidget::item{ - /*background-color: #F00000;*/ - /*padding: 2px*/ -} - -MainWindow QListWidget { - font-size: 12pt; -} - -PulseTopLevel QFrame#frame, PulseViewGroup QFrame#frame, PulseReply QFrame#frame { - border: 2px solid #c4cfd6; - background: white; -} - -PulseAddDialog QTextEdit#textEdit_Pulse { - border: 2px solid #c4cfd6; - border-radius: 6px; - background: white; -} - -PulseAddDialog QFrame#frame_input, QFrame#frame_reply, QFrame#frame { - border: 0px; -} - -PulseAddDialog QLabel#label_groupName { - font-size: 12pt; -} - -PulseReply #line_replyLine , PulseMessage #line{ - color: #c4cfd6; -} - -PulseReply QLabel#label_groupName{ - color: #5b7083; -} - -WireDialog QLabel#label_viewMode { - font-size: 12pt; -} - -WireGroupDialog QFrame#frame { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #9BDBF9, stop:1 #1592CD); - border: 0px; -} - -PhotoShare QPushButton#pushButton_YourAlbums, QPushButton#pushButton_SubscribedAlbums, -QPushButton#pushButton_SharedAlbums { - font-size: 12pt; -} - -AlbumItem QFrame#albumFrame { - border: 2px solid #CCCCCC; - border-radius: 10px -} - -PhotoItem QFrame#photoFrame { - border: 2px solid #CCCCCC; - border-radius: 10px -} - -PhotoItem QWidget:hover { - background-color: #7ecbfb; -} - -PhotoSlideShow QLabel#albumLabel { - font-size: 12pt; -} - -ChannelsCommentsItem QFrame#mainFrame, BoardsCommentsItem QFrame#mainFrame { - background-color: white; -} - -ChannelsCommentsItem QLabel#newCommentLabel, BoardsCommentsItem QLabel#newCommentLabel { - font-size: 12pt; - font: bold; -} - -ChannelsCommentsItem QLabel#subjectLabel, ChannelsCommentsItem QLabel#titleLabel , QLabel#nameLabel { - font-size: 12pt; - font: bold; -} - -BoardsCommentsItem QLabel#subjectLabel, QLabel#titleLabel , QLabel#nameLabel { - font-size: 12pt; - font: bold; -} - -NewFriendList QTreeView#peerTreeWidget::item:selected, QTreeView#peerTreeWidget::branch:selected:active { - background: #cde8ff; -} - -NewFriendList QTreeView#peerTreeWidget { - font-size: 12pt; -} - -WikiEditDialog QPushButton#pushButton_History { - font: bold; - font-size: 15px; - color: white; - background: #5bb62b; - border-radius: 4px; - max-height: 20px; - min-width: 4em; - padding: 2px; - padding-left: 6px; - padding-right: 6px; -} - -WikiEditDialog QPushButton#pushButton_History:hover { - background: #57af29; -} diff --git a/retroshare-gui/src/gui/qss/stylesheet/Standard_Dark.qss b/retroshare-gui/src/gui/qss/stylesheet/Standard_Dark.qss new file mode 100644 index 000000000..ffea0a4d8 --- /dev/null +++ b/retroshare-gui/src/gui/qss/stylesheet/Standard_Dark.qss @@ -0,0 +1,2557 @@ + /* Standard Dark stylesheet for RetroShare + Don't use font-size or font-weight, they are defined in .ui files. + Icon size are defined in .cpp files. + + For decoration, use px (pixel or dot) + For horizontal size, use em (width of M char) + For vertical size, use ex (height of x char to respect DotPerInch of your system) + See: https://doc.qt.io/qt-5/stylesheet-reference.html#length + + It use a public one for general widgets https://github.com/ColinDuquesnoy/QDarkStyleSheet + /qdarkstyle/dark/style.qss + Updated at 2021-11-04 Tag v3.0.2 + Replace all ":/qss_icons/dark" by ":/standard_dark" + */ + +/* --------------------------------------------------------------------------- + + WARNING! File created programmatically. All changes made in this file will be lost! + + Created by the qtsass compiler v0.3.0 + + The definitions are in the "qdarkstyle.qss._styles.scss" module + +--------------------------------------------------------------------------- */ +/* Light Style - QDarkStyleSheet ------------------------------------------ */ +/* + +See Qt documentation: + + - https://doc.qt.io/qt-5/stylesheet.html + - https://doc.qt.io/qt-5/stylesheet-reference.html + - https://doc.qt.io/qt-5/stylesheet-examples.html + +--------------------------------------------------------------------------- */ +/* Reset elements ------------------------------------------------------------ + +Resetting everything helps to unify styles across different operating systems + +--------------------------------------------------------------------------- */ +* { + padding: 0px; + margin: 0px; + border: 0px; + border-style: none; + border-image: none; + outline: 0; +} + +/* specific reset for elements inside QToolBar */ +QToolBar * { + margin: 0px; + padding: 0px; +} + +/* QWidget ---------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QWidget { + background-color: #19232D; + border: 0px solid #455364; + padding: 0px; + color: #E0E1E3; + selection-background-color: #346792; + selection-color: #E0E1E3; +} + +QWidget:disabled { + background-color: #19232D; + color: #9DA9B5; + selection-background-color: #26486B; + selection-color: #9DA9B5; +} + +QWidget::item:selected { + background-color: #346792; +} + +QWidget::item:hover:!selected { + background-color: #1A72BB; +} + +/* QMainWindow ------------------------------------------------------------ + +This adjusts the splitter in the dock widget, not qsplitter +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmainwindow + +--------------------------------------------------------------------------- */ +QMainWindow::separator { + background-color: #455364; + border: 0px solid #19232D; + spacing: 0px; + padding: 2px; +} + +QMainWindow::separator:hover { + background-color: #60798B; + border: 0px solid #1A72BB; +} + +QMainWindow::separator:horizontal { + width: 5px; + margin-top: 2px; + margin-bottom: 2px; + image: url(":/standard_dark/rc/toolbar_separator_vertical.png"); +} + +QMainWindow::separator:vertical { + height: 5px; + margin-left: 2px; + margin-right: 2px; + image: url(":/standard_dark/rc/toolbar_separator_horizontal.png"); +} + +/* QToolTip --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtooltip + +--------------------------------------------------------------------------- */ +QToolTip { + background-color: #346792; + color: #E0E1E3; + /* If you remove the border property, background stops working on Windows */ + border: none; + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + /* Remove opacity, fix #174 - may need to use RGBA */ +} + +/* QStatusBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar + +--------------------------------------------------------------------------- */ +QStatusBar { + border: 1px solid #455364; + /* Fixes Spyder #9120, #9121 */ + background: #455364; + /* Fixes #205, white vertical borders separating items */ +} + +QStatusBar::item { + border: none; +} + +QStatusBar QToolTip { + background-color: #1A72BB; + border: 1px solid #19232D; + color: #19232D; + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + /* Reducing transparency to read better */ + opacity: 230; +} + +QStatusBar QLabel { + /* Fixes Spyder #9120, #9121 */ + background: transparent; +} + +/* QCheckBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcheckbox + +--------------------------------------------------------------------------- */ +QCheckBox { + background-color: #19232D; + color: #E0E1E3; + spacing: 4px; + outline: none; + padding-top: 4px; + padding-bottom: 4px; +} + +QCheckBox:focus { + border: none; +} + +QCheckBox QWidget:disabled { + background-color: #19232D; + color: #9DA9B5; +} + +QCheckBox::indicator { + margin-left: 2px; + height: 14px; + width: 14px; +} + +QCheckBox::indicator:unchecked { + image: url(":/standard_dark/rc/checkbox_unchecked.png"); +} + +QCheckBox::indicator:unchecked:hover, QCheckBox::indicator:unchecked:focus, QCheckBox::indicator:unchecked:pressed { + border: none; + image: url(":/standard_dark/rc/checkbox_unchecked_focus.png"); +} + +QCheckBox::indicator:unchecked:disabled { + image: url(":/standard_dark/rc/checkbox_unchecked_disabled.png"); +} + +QCheckBox::indicator:checked { + image: url(":/standard_dark/rc/checkbox_checked.png"); +} + +QCheckBox::indicator:checked:hover, QCheckBox::indicator:checked:focus, QCheckBox::indicator:checked:pressed { + border: none; + image: url(":/standard_dark/rc/checkbox_checked_focus.png"); +} + +QCheckBox::indicator:checked:disabled { + image: url(":/standard_dark/rc/checkbox_checked_disabled.png"); +} + +QCheckBox::indicator:indeterminate { + image: url(":/standard_dark/rc/checkbox_indeterminate.png"); +} + +QCheckBox::indicator:indeterminate:disabled { + image: url(":/standard_dark/rc/checkbox_indeterminate_disabled.png"); +} + +QCheckBox::indicator:indeterminate:focus, QCheckBox::indicator:indeterminate:hover, QCheckBox::indicator:indeterminate:pressed { + image: url(":/standard_dark/rc/checkbox_indeterminate_focus.png"); +} + +/* QGroupBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox + +--------------------------------------------------------------------------- */ +QGroupBox { + font-weight: bold; + border: 1px solid #455364; + border-radius: 4px; + padding: 2px; + margin-top: 6px; + margin-bottom: 4px; +} + +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + left: 4px; + padding-left: 2px; + padding-right: 4px; + padding-top: -4px; +} + +QGroupBox::indicator { + margin-left: 2px; + margin-top: 2px; + padding: 0; + height: 14px; + width: 14px; +} + +QGroupBox::indicator:unchecked { + border: none; + image: url(":/standard_dark/rc/checkbox_unchecked.png"); +} + +QGroupBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:focus, QGroupBox::indicator:unchecked:pressed { + border: none; + image: url(":/standard_dark/rc/checkbox_unchecked_focus.png"); +} + +QGroupBox::indicator:unchecked:disabled { + image: url(":/standard_dark/rc/checkbox_unchecked_disabled.png"); +} + +QGroupBox::indicator:checked { + border: none; + image: url(":/standard_dark/rc/checkbox_checked.png"); +} + +QGroupBox::indicator:checked:hover, QGroupBox::indicator:checked:focus, QGroupBox::indicator:checked:pressed { + border: none; + image: url(":/standard_dark/rc/checkbox_checked_focus.png"); +} + +QGroupBox::indicator:checked:disabled { + image: url(":/standard_dark/rc/checkbox_checked_disabled.png"); +} + +/* QRadioButton ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qradiobutton + +--------------------------------------------------------------------------- */ +QRadioButton { + background-color: #19232D; + color: #E0E1E3; + spacing: 4px; + padding-top: 4px; + padding-bottom: 4px; + border: none; + outline: none; +} + +QRadioButton:focus { + border: none; +} + +QRadioButton:disabled { + background-color: #19232D; + color: #9DA9B5; + border: none; + outline: none; +} + +QRadioButton QWidget { + background-color: #19232D; + color: #E0E1E3; + spacing: 0px; + padding: 0px; + outline: none; + border: none; +} + +QRadioButton::indicator { + border: none; + outline: none; + margin-left: 2px; + height: 14px; + width: 14px; +} + +QRadioButton::indicator:unchecked { + image: url(":/standard_dark/rc/radio_unchecked.png"); +} + +QRadioButton::indicator:unchecked:hover, QRadioButton::indicator:unchecked:focus, QRadioButton::indicator:unchecked:pressed { + border: none; + outline: none; + image: url(":/standard_dark/rc/radio_unchecked_focus.png"); +} + +QRadioButton::indicator:unchecked:disabled { + image: url(":/standard_dark/rc/radio_unchecked_disabled.png"); +} + +QRadioButton::indicator:checked { + border: none; + outline: none; + image: url(":/standard_dark/rc/radio_checked.png"); +} + +QRadioButton::indicator:checked:hover, QRadioButton::indicator:checked:focus, QRadioButton::indicator:checked:pressed { + border: none; + outline: none; + image: url(":/standard_dark/rc/radio_checked_focus.png"); +} + +QRadioButton::indicator:checked:disabled { + outline: none; + image: url(":/standard_dark/rc/radio_checked_disabled.png"); +} + +/* QMenuBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar + +--------------------------------------------------------------------------- */ +QMenuBar { + background-color: #455364; + padding: 2px; + border: 1px solid #19232D; + color: #E0E1E3; + selection-background-color: #1A72BB; +} + +QMenuBar:focus { + border: 1px solid #346792; +} + +QMenuBar::item { + background: transparent; + padding: 4px; +} + +QMenuBar::item:selected { + padding: 4px; + background: transparent; + border: 0px solid #455364; + background-color: #1A72BB; +} + +QMenuBar::item:pressed { + padding: 4px; + border: 0px solid #455364; + background-color: #1A72BB; + color: #E0E1E3; + margin-bottom: 0px; + padding-bottom: 0px; +} + +/* QMenu ------------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu + +--------------------------------------------------------------------------- */ +QMenu { + border: 0px solid #455364; + color: #E0E1E3; + margin: 0px; + background-color: #37414F; + selection-background-color: #1A72BB; +} + +QMenu::separator { + height: 1px; + background-color: #60798B; + color: #E0E1E3; +} + +QMenu::item { + background-color: #37414F; + padding: 4px 24px 4px 28px; + /* Reserve space for selection border */ + border: 1px transparent #455364; +} + +QMenu::item:selected { + color: #E0E1E3; + background-color: #1A72BB; +} + +QMenu::item:pressed { + background-color: #1A72BB; +} + +QMenu::icon { + padding-left: 10px; + width: 14px; + height: 14px; +} + +QMenu::indicator { + padding-left: 8px; + width: 12px; + height: 12px; + /* non-exclusive indicator = check box style indicator (see QActionGroup::setExclusive) */ + /* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */ +} + +QMenu::indicator:non-exclusive:unchecked { + image: url(":/standard_dark/rc/checkbox_unchecked.png"); +} + +QMenu::indicator:non-exclusive:unchecked:hover, QMenu::indicator:non-exclusive:unchecked:focus, QMenu::indicator:non-exclusive:unchecked:pressed { + border: none; + image: url(":/standard_dark/rc/checkbox_unchecked_focus.png"); +} + +QMenu::indicator:non-exclusive:unchecked:disabled { + image: url(":/standard_dark/rc/checkbox_unchecked_disabled.png"); +} + +QMenu::indicator:non-exclusive:checked { + image: url(":/standard_dark/rc/checkbox_checked.png"); +} + +QMenu::indicator:non-exclusive:checked:hover, QMenu::indicator:non-exclusive:checked:focus, QMenu::indicator:non-exclusive:checked:pressed { + border: none; + image: url(":/standard_dark/rc/checkbox_checked_focus.png"); +} + +QMenu::indicator:non-exclusive:checked:disabled { + image: url(":/standard_dark/rc/checkbox_checked_disabled.png"); +} + +QMenu::indicator:non-exclusive:indeterminate { + image: url(":/standard_dark/rc/checkbox_indeterminate.png"); +} + +QMenu::indicator:non-exclusive:indeterminate:disabled { + image: url(":/standard_dark/rc/checkbox_indeterminate_disabled.png"); +} + +QMenu::indicator:non-exclusive:indeterminate:focus, QMenu::indicator:non-exclusive:indeterminate:hover, QMenu::indicator:non-exclusive:indeterminate:pressed { + image: url(":/standard_dark/rc/checkbox_indeterminate_focus.png"); +} + +QMenu::indicator:exclusive:unchecked { + image: url(":/standard_dark/rc/radio_unchecked.png"); +} + +QMenu::indicator:exclusive:unchecked:hover, QMenu::indicator:exclusive:unchecked:focus, QMenu::indicator:exclusive:unchecked:pressed { + border: none; + outline: none; + image: url(":/standard_dark/rc/radio_unchecked_focus.png"); +} + +QMenu::indicator:exclusive:unchecked:disabled { + image: url(":/standard_dark/rc/radio_unchecked_disabled.png"); +} + +QMenu::indicator:exclusive:checked { + border: none; + outline: none; + image: url(":/standard_dark/rc/radio_checked.png"); +} + +QMenu::indicator:exclusive:checked:hover, QMenu::indicator:exclusive:checked:focus, QMenu::indicator:exclusive:checked:pressed { + border: none; + outline: none; + image: url(":/standard_dark/rc/radio_checked_focus.png"); +} + +QMenu::indicator:exclusive:checked:disabled { + outline: none; + image: url(":/standard_dark/rc/radio_checked_disabled.png"); +} + +QMenu::right-arrow { + margin: 5px; + padding-left: 12px; + image: url(":/standard_dark/rc/arrow_right.png"); + height: 12px; + width: 12px; +} + +/* QAbstractItemView ------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QAbstractItemView { + alternate-background-color: #19232D; + color: #E0E1E3; + border: 1px solid #455364; + border-radius: 4px; +} + +QAbstractItemView QLineEdit { + padding: 2px; +} + +/* QAbstractScrollArea ---------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QAbstractScrollArea { + background-color: #19232D; + border: 1px solid #455364; + border-radius: 4px; + /* fix #159 */ + padding: 2px; + /* remove min-height to fix #244 */ + color: #E0E1E3; +} + +QAbstractScrollArea:disabled { + color: #9DA9B5; +} + +/* QScrollArea ------------------------------------------------------------ + +--------------------------------------------------------------------------- */ +QScrollArea QWidget QWidget:disabled { + background-color: #19232D; +} + +/* QScrollBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qscrollbar + +--------------------------------------------------------------------------- */ +QScrollBar:horizontal { + height: 16px; + margin: 2px 16px 2px 16px; + border: 1px solid #455364; + border-radius: 4px; + background-color: #19232D; +} + +QScrollBar:vertical { + background-color: #19232D; + width: 16px; + margin: 16px 2px 16px 2px; + border: 1px solid #455364; + border-radius: 4px; +} + +QScrollBar::handle:horizontal { + background-color: #60798B; + border: 1px solid #455364; + border-radius: 4px; + min-width: 8px; +} + +QScrollBar::handle:horizontal:hover { + background-color: #346792; + border: #346792; + border-radius: 4px; + min-width: 8px; +} + +QScrollBar::handle:horizontal:focus { + border: 1px solid #1A72BB; +} + +QScrollBar::handle:vertical { + background-color: #60798B; + border: 1px solid #455364; + min-height: 8px; + border-radius: 4px; +} + +QScrollBar::handle:vertical:hover { + background-color: #346792; + border: #346792; + border-radius: 4px; + min-height: 8px; +} + +QScrollBar::handle:vertical:focus { + border: 1px solid #1A72BB; +} + +QScrollBar::add-line:horizontal { + margin: 0px 0px 0px 0px; + border-image: url(":/standard_dark/rc/arrow_right_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::add-line:horizontal:hover, QScrollBar::add-line:horizontal:on { + border-image: url(":/standard_dark/rc/arrow_right.png"); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::add-line:vertical { + margin: 3px 0px 3px 0px; + border-image: url(":/standard_dark/rc/arrow_down_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on { + border-image: url(":/standard_dark/rc/arrow_down.png"); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal { + margin: 0px 3px 0px 3px; + border-image: url(":/standard_dark/rc/arrow_left_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on { + border-image: url(":/standard_dark/rc/arrow_left.png"); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:vertical { + margin: 3px 0px 3px 0px; + border-image: url(":/standard_dark/rc/arrow_up_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:vertical:hover, QScrollBar::sub-line:vertical:on { + border-image: url(":/standard_dark/rc/arrow_up.png"); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal { + background: none; +} + +QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { + background: none; +} + +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + background: none; +} + +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + background: none; +} + +/* QTextEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-specific-widgets + +--------------------------------------------------------------------------- */ +QTextEdit { + background-color: #19232D; + color: #E0E1E3; + border-radius: 4px; + border: 1px solid #455364; +} + +QTextEdit:focus { + border: 1px solid #1A72BB; +} + +QTextEdit:selected { + background: #346792; + color: #455364; +} + +/* QPlainTextEdit --------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QPlainTextEdit { + background-color: #19232D; + color: #E0E1E3; + border-radius: 4px; + border: 1px solid #455364; +} + +QPlainTextEdit:focus { + border: 1px solid #1A72BB; +} + +QPlainTextEdit:selected { + background: #346792; + color: #455364; +} + +/* QSizeGrip -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsizegrip + +--------------------------------------------------------------------------- */ +QSizeGrip { + background: transparent; + width: 12px; + height: 12px; + image: url(":/standard_dark/rc/window_grip.png"); +} + +/* QStackedWidget --------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QStackedWidget { + padding: 2px; + border: 1px solid #455364; + border: 1px solid #19232D; +} + +/* QToolBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbar + +--------------------------------------------------------------------------- */ +QToolBar { + background-color: #455364; + border-bottom: 1px solid #19232D; + padding: 1px; + font-weight: bold; + spacing: 2px; +} + +QToolBar:disabled { + /* Fixes #272 */ + background-color: #455364; +} + +QToolBar::handle:horizontal { + width: 16px; + image: url(":/standard_dark/rc/toolbar_move_horizontal.png"); +} + +QToolBar::handle:vertical { + height: 16px; + image: url(":/standard_dark/rc/toolbar_move_vertical.png"); +} + +QToolBar::separator:horizontal { + width: 16px; + image: url(":/standard_dark/rc/toolbar_separator_horizontal.png"); +} + +QToolBar::separator:vertical { + height: 16px; + image: url(":/standard_dark/rc/toolbar_separator_vertical.png"); +} + +QToolButton#qt_toolbar_ext_button { + background: #455364; + border: 0px; + color: #E0E1E3; + image: url(":/standard_dark/rc/arrow_right.png"); +} + +/* QAbstractSpinBox ------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractSpinBox { + background-color: #19232D; + border: 1px solid #455364; + color: #E0E1E3; + /* This fixes 103, 111 */ + padding-top: 2px; + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + border-radius: 4px; + /* min-width: 5px; removed to fix 109 */ +} + +QAbstractSpinBox:up-button { + background-color: transparent #19232D; + subcontrol-origin: border; + subcontrol-position: top right; + border-left: 1px solid #455364; + border-bottom: 1px solid #455364; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-bottom: -1px; +} + +QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off { + image: url(":/standard_dark/rc/arrow_up_disabled.png"); + height: 8px; + width: 8px; +} + +QAbstractSpinBox::up-arrow:hover { + image: url(":/standard_dark/rc/arrow_up.png"); +} + +QAbstractSpinBox:down-button { + background-color: transparent #19232D; + subcontrol-origin: border; + subcontrol-position: bottom right; + border-left: 1px solid #455364; + border-top: 1px solid #455364; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-top: -1px; +} + +QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off { + image: url(":/standard_dark/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QAbstractSpinBox::down-arrow:hover { + image: url(":/standard_dark/rc/arrow_down.png"); +} + +QAbstractSpinBox:hover { + border: 1px solid #346792; + color: #E0E1E3; +} + +QAbstractSpinBox:focus { + border: 1px solid #1A72BB; +} + +QAbstractSpinBox:selected { + background: #346792; + color: #455364; +} + +/* ------------------------------------------------------------------------ */ +/* DISPLAYS --------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QLabel ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe + +--------------------------------------------------------------------------- */ +QLabel { + background-color: #19232D; + border: 0px solid #455364; + padding: 2px; + margin: 0px; + color: #E0E1E3; +} + +QLabel:disabled { + background-color: #19232D; + border: 0px solid #455364; + color: #9DA9B5; +} + +/* QTextBrowser ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QTextBrowser { + background-color: #19232D; + border: 1px solid #455364; + color: #E0E1E3; + border-radius: 4px; +} + +QTextBrowser:disabled { + background-color: #19232D; + border: 1px solid #455364; + color: #9DA9B5; + border-radius: 4px; +} + +QTextBrowser:hover, QTextBrowser:!hover, QTextBrowser:selected, QTextBrowser:pressed { + border: 1px solid #455364; +} + +/* QGraphicsView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QGraphicsView { + background-color: #19232D; + border: 1px solid #455364; + color: #E0E1E3; + border-radius: 4px; +} + +QGraphicsView:disabled { + background-color: #19232D; + border: 1px solid #455364; + color: #9DA9B5; + border-radius: 4px; +} + +QGraphicsView:hover, QGraphicsView:!hover, QGraphicsView:selected, QGraphicsView:pressed { + border: 1px solid #455364; +} + +/* QCalendarWidget -------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCalendarWidget { + border: 1px solid #455364; + border-radius: 4px; +} + +QCalendarWidget:disabled { + background-color: #19232D; + color: #9DA9B5; +} + +/* QLCDNumber ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QLCDNumber { + background-color: #19232D; + color: #E0E1E3; +} + +QLCDNumber:disabled { + background-color: #19232D; + color: #9DA9B5; +} + +/* QProgressBar ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qprogressbar + +--------------------------------------------------------------------------- */ +QProgressBar { + background-color: #19232D; + border: 1px solid #455364; + color: #E0E1E3; + border-radius: 4px; + text-align: center; +} + +QProgressBar:disabled { + background-color: #19232D; + border: 1px solid #455364; + color: #9DA9B5; + border-radius: 4px; + text-align: center; +} + +QProgressBar::chunk { + background-color: #346792; + color: #19232D; + border-radius: 4px; +} + +QProgressBar::chunk:disabled { + background-color: #26486B; + color: #9DA9B5; + border-radius: 4px; +} + +/* ------------------------------------------------------------------------ */ +/* BUTTONS ---------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QPushButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qpushbutton + +--------------------------------------------------------------------------- */ +QPushButton { + background-color: #455364; + color: #E0E1E3; + border-radius: 4px; + padding: 2px; + outline: none; + border: none; +} + +QPushButton:disabled { + background-color: #455364; + color: #9DA9B5; + border-radius: 4px; + padding: 2px; +} + +QPushButton:checked { + background-color: #60798B; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QPushButton:checked:disabled { + background-color: #60798B; + color: #9DA9B5; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QPushButton:checked:selected { + background: #60798B; +} + +QPushButton:hover { + background-color: #54687A; + color: #E0E1E3; +} + +QPushButton:pressed { + background-color: #60798B; +} + +QPushButton:selected { + background: #60798B; + color: #E0E1E3; +} + +QPushButton::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: bottom right; + bottom: 4px; +} + +QDialogButtonBox QPushButton { + /* Issue #194 #248 - Special case of QPushButton inside dialogs, for better UI */ + min-width: 80px; +} + +/* QToolButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbutton + +--------------------------------------------------------------------------- */ +QToolButton { + background-color: #455364; + color: #E0E1E3; + border-radius: 4px; + padding: 2px; + outline: none; + border: none; + /* The subcontrols below are used only in the DelayedPopup mode */ + /* The subcontrols below are used only in the MenuButtonPopup mode */ + /* The subcontrol below is used only in the InstantPopup or DelayedPopup mode */ +} + +QToolButton:disabled { + background-color: #455364; + color: #9DA9B5; + border-radius: 4px; + padding: 2px; +} + +QToolButton:checked { + background-color: #60798B; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QToolButton:checked:disabled { + background-color: #60798B; + color: #9DA9B5; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QToolButton:checked:hover { + background-color: #54687A; + color: #E0E1E3; +} + +QToolButton:checked:pressed { + background-color: #60798B; +} + +QToolButton:checked:selected { + background: #60798B; + color: #E0E1E3; +} + +QToolButton:hover { + background-color: #54687A; + color: #E0E1E3; +} + +QToolButton:pressed { + background-color: #60798B; +} + +QToolButton:selected { + background: #60798B; + color: #E0E1E3; +} + +QToolButton[popupMode="0"] { + /* Only for DelayedPopup */ + padding-right: 2px; +} + +QToolButton[popupMode="1"] { + /* Only for MenuButtonPopup */ + padding-right: 20px; +} + +QToolButton[popupMode="1"]::menu-button { + border: none; +} + +QToolButton[popupMode="1"]::menu-button:hover { + border: none; + border-left: 1px solid #455364; + border-radius: 0; +} + +QToolButton[popupMode="2"] { + /* Only for InstantPopup */ + padding-right: 2px; +} + +QToolButton::menu-button { + padding: 2px; + border-radius: 4px; + width: 12px; + border: none; + outline: none; +} + +QToolButton::menu-button:hover { + border: 1px solid #346792; +} + +QToolButton::menu-button:checked:hover { + border: 1px solid #346792; +} + +QToolButton::menu-indicator { + image: url(":/standard_dark/rc/arrow_down.png"); + height: 8px; + width: 8px; + top: 0; + /* Exclude a shift for better image */ + left: -2px; + /* Shift it a bit */ +} + +QToolButton::menu-arrow { + image: url(":/standard_dark/rc/arrow_down.png"); + height: 8px; + width: 8px; +} + +QToolButton::menu-arrow:hover { + image: url(":/standard_dark/rc/arrow_down_focus.png"); +} + +/* QCommandLinkButton ----------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCommandLinkButton { + background-color: transparent; + border: 1px solid #455364; + color: #E0E1E3; + border-radius: 4px; + padding: 0px; + margin: 0px; +} + +QCommandLinkButton:disabled { + background-color: transparent; + color: #9DA9B5; +} + +/* ------------------------------------------------------------------------ */ +/* INPUTS - NO FIELDS ----------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QComboBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QComboBox { + border: 1px solid #455364; + border-radius: 4px; + selection-background-color: #346792; + padding-left: 4px; + padding-right: 4px; + /* padding-right = 36; 4 + 16*2 See scrollbar size */ + /* changed to 4px to fix #239 */ + /* Fixes #103, #111 */ + min-height: 1.5em; + /* padding-top: 2px; removed to fix #132 */ + /* padding-bottom: 2px; removed to fix #132 */ + /* min-width: 75px; removed to fix #109 */ + /* Needed to remove indicator - fix #132 */ +} + +QComboBox QAbstractItemView { + border: 1px solid #455364; + border-radius: 0; + background-color: #19232D; + selection-background-color: #346792; +} + +QComboBox QAbstractItemView:hover { + background-color: #19232D; + color: #E0E1E3; +} + +QComboBox QAbstractItemView:selected { + background: #346792; + color: #455364; +} + +QComboBox QAbstractItemView:alternate { + background: #19232D; +} + +QComboBox:disabled { + background-color: #19232D; + color: #9DA9B5; +} + +QComboBox:hover { + border: 1px solid #346792; +} + +QComboBox:focus { + border: 1px solid #1A72BB; +} + +QComboBox:on { + selection-background-color: #346792; +} + +QComboBox::indicator { + border: none; + border-radius: 0; + background-color: transparent; + selection-background-color: transparent; + color: transparent; + selection-color: transparent; + /* Needed to remove indicator - fix #132 */ +} + +QComboBox::indicator:alternate { + background: #19232D; +} + +QComboBox::item:alternate { + background: #19232D; +} + +QComboBox::item:checked { + font-weight: bold; +} + +QComboBox::item:selected { + border: 0px solid transparent; +} + +QComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid #455364; +} + +QComboBox::down-arrow { + image: url(":/standard_dark/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QComboBox::down-arrow:on, QComboBox::down-arrow:hover, QComboBox::down-arrow:focus { + image: url(":/standard_dark/rc/arrow_down.png"); +} + +/* QSlider ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qslider + +--------------------------------------------------------------------------- */ +QSlider:disabled { + background: #19232D; +} + +QSlider:focus { + border: none; +} + +QSlider::groove:horizontal { + background: #455364; + border: 1px solid #455364; + height: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::groove:vertical { + background: #455364; + border: 1px solid #455364; + width: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::add-page:vertical { + background: #346792; + border: 1px solid #455364; + width: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::add-page:vertical :disabled { + background: #26486B; +} + +QSlider::sub-page:horizontal { + background: #346792; + border: 1px solid #455364; + height: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::sub-page:horizontal:disabled { + background: #26486B; +} + +QSlider::handle:horizontal { + background: #9DA9B5; + border: 1px solid #455364; + width: 8px; + height: 8px; + margin: -8px 0px; + border-radius: 4px; +} + +QSlider::handle:horizontal:hover { + background: #346792; + border: 1px solid #346792; +} + +QSlider::handle:horizontal:focus { + border: 1px solid #1A72BB; +} + +QSlider::handle:vertical { + background: #9DA9B5; + border: 1px solid #455364; + width: 8px; + height: 8px; + margin: 0 -8px; + border-radius: 4px; +} + +QSlider::handle:vertical:hover { + background: #346792; + border: 1px solid #346792; +} + +QSlider::handle:vertical:focus { + border: 1px solid #1A72BB; +} + +/* QLineEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlineedit + +--------------------------------------------------------------------------- */ +QLineEdit { + background-color: #19232D; + padding-top: 2px; + /* This QLineEdit fix 103, 111 */ + padding-bottom: 2px; + /* This QLineEdit fix 103, 111 */ + padding-left: 4px; + padding-right: 4px; + border-style: solid; + border: 1px solid #455364; + border-radius: 4px; + color: #E0E1E3; +} + +QLineEdit:disabled { + background-color: #19232D; + color: #9DA9B5; +} + +QLineEdit:hover { + border: 1px solid #346792; + color: #E0E1E3; +} + +QLineEdit:focus { + border: 1px solid #1A72BB; +} + +QLineEdit:selected { + background-color: #346792; + color: #455364; +} + +/* QTabWiget -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabWidget { + padding: 2px; + selection-background-color: #455364; +} + +QTabWidget QWidget { + /* Fixes #189 */ + border-radius: 4px; +} + +QTabWidget::pane { + border: 1px solid #455364; + border-radius: 4px; + margin: 0px; + /* Fixes double border inside pane with pyqt5 */ + padding: 0px; +} + +QTabWidget::pane:selected { + background-color: #455364; + border: 1px solid #346792; +} + +/* QTabBar ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabBar, QDockWidget QTabBar { + qproperty-drawBase: 0; + border-radius: 4px; + margin: 0px; + padding: 2px; + border: 0; + /* left: 5px; move to the right by 5px - removed for fix */ +} + +QTabBar::close-button, QDockWidget QTabBar::close-button { + border: 0; + margin: 0; + padding: 4px; + image: url(":/standard_dark/rc/window_close.png"); +} + +QTabBar::close-button:hover, QDockWidget QTabBar::close-button:hover { + image: url(":/standard_dark/rc/window_close_focus.png"); +} + +QTabBar::close-button:pressed, QDockWidget QTabBar::close-button:pressed { + image: url(":/standard_dark/rc/window_close_pressed.png"); +} + +QTabBar::tab, QDockWidget QTabBar::tab { + /* !selected and disabled ----------------------------------------- */ + /* selected ------------------------------------------------------- */ +} + +QTabBar::tab:top:selected:disabled, QDockWidget QTabBar::tab:top:selected:disabled { + border-bottom: 3px solid #26486B; + color: #9DA9B5; + background-color: #455364; +} + +QTabBar::tab:bottom:selected:disabled, QDockWidget QTabBar::tab:bottom:selected:disabled { + border-top: 3px solid #26486B; + color: #9DA9B5; + background-color: #455364; +} + +QTabBar::tab:left:selected:disabled, QDockWidget QTabBar::tab:left:selected:disabled { + border-right: 3px solid #26486B; + color: #9DA9B5; + background-color: #455364; +} + +QTabBar::tab:right:selected:disabled, QDockWidget QTabBar::tab:right:selected:disabled { + border-left: 3px solid #26486B; + color: #9DA9B5; + background-color: #455364; +} + +QTabBar::tab:top:!selected:disabled, QDockWidget QTabBar::tab:top:!selected:disabled { + border-bottom: 3px solid #19232D; + color: #9DA9B5; + background-color: #19232D; +} + +QTabBar::tab:bottom:!selected:disabled, QDockWidget QTabBar::tab:bottom:!selected:disabled { + border-top: 3px solid #19232D; + color: #9DA9B5; + background-color: #19232D; +} + +QTabBar::tab:left:!selected:disabled, QDockWidget QTabBar::tab:left:!selected:disabled { + border-right: 3px solid #19232D; + color: #9DA9B5; + background-color: #19232D; +} + +QTabBar::tab:right:!selected:disabled, QDockWidget QTabBar::tab:right:!selected:disabled { + border-left: 3px solid #19232D; + color: #9DA9B5; + background-color: #19232D; +} + +QTabBar::tab:top:!selected, QDockWidget QTabBar::tab:top:!selected { + border-bottom: 2px solid #19232D; + margin-top: 2px; +} + +QTabBar::tab:bottom:!selected, QDockWidget QTabBar::tab:bottom:!selected { + border-top: 2px solid #19232D; + margin-bottom: 2px; +} + +QTabBar::tab:left:!selected, QDockWidget QTabBar::tab:left:!selected { + border-left: 2px solid #19232D; + margin-right: 2px; +} + +QTabBar::tab:right:!selected, QDockWidget QTabBar::tab:right:!selected { + border-right: 2px solid #19232D; + margin-left: 2px; +} + +QTabBar::tab:top, QDockWidget QTabBar::tab:top { + background-color: #455364; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + min-width: 5px; + border-bottom: 3px solid #455364; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QTabBar::tab:top:selected, QDockWidget QTabBar::tab:top:selected { + background-color: #54687A; + border-bottom: 3px solid #259AE9; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QTabBar::tab:top:!selected:hover, QDockWidget QTabBar::tab:top:!selected:hover { + border: 1px solid #1A72BB; + border-bottom: 3px solid #1A72BB; + /* Fixes spyder-ide/spyder#9766 and #243 */ + padding-left: 3px; + padding-right: 3px; +} + +QTabBar::tab:bottom, QDockWidget QTabBar::tab:bottom { + border-top: 3px solid #455364; + background-color: #455364; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + min-width: 5px; +} + +QTabBar::tab:bottom:selected, QDockWidget QTabBar::tab:bottom:selected { + background-color: #54687A; + border-top: 3px solid #259AE9; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +QTabBar::tab:bottom:!selected:hover, QDockWidget QTabBar::tab:bottom:!selected:hover { + border: 1px solid #1A72BB; + border-top: 3px solid #1A72BB; + /* Fixes spyder-ide/spyder#9766 and #243 */ + padding-left: 3px; + padding-right: 3px; +} + +QTabBar::tab:left, QDockWidget QTabBar::tab:left { + background-color: #455364; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + min-height: 5px; +} + +QTabBar::tab:left:selected, QDockWidget QTabBar::tab:left:selected { + background-color: #54687A; + border-right: 3px solid #259AE9; +} + +QTabBar::tab:left:!selected:hover, QDockWidget QTabBar::tab:left:!selected:hover { + border: 1px solid #1A72BB; + border-right: 3px solid #1A72BB; + /* Fixes different behavior #271 */ + margin-right: 0px; + padding-right: -1px; +} + +QTabBar::tab:right, QDockWidget QTabBar::tab:right { + background-color: #455364; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + min-height: 5px; +} + +QTabBar::tab:right:selected, QDockWidget QTabBar::tab:right:selected { + background-color: #54687A; + border-left: 3px solid #259AE9; +} + +QTabBar::tab:right:!selected:hover, QDockWidget QTabBar::tab:right:!selected:hover { + border: 1px solid #1A72BB; + border-left: 3px solid #1A72BB; + /* Fixes different behavior #271 */ + margin-left: 0px; + padding-left: 0px; +} + +QTabBar QToolButton, QDockWidget QTabBar QToolButton { + /* Fixes #136 */ + background-color: #455364; + height: 12px; + width: 12px; +} + +QTabBar QToolButton:pressed, QDockWidget QTabBar QToolButton:pressed { + background-color: #455364; +} + +QTabBar QToolButton:pressed:hover, QDockWidget QTabBar QToolButton:pressed:hover { + border: 1px solid #346792; +} + +QTabBar QToolButton::left-arrow:enabled, QDockWidget QTabBar QToolButton::left-arrow:enabled { + image: url(":/standard_dark/rc/arrow_left.png"); +} + +QTabBar QToolButton::left-arrow:disabled, QDockWidget QTabBar QToolButton::left-arrow:disabled { + image: url(":/standard_dark/rc/arrow_left_disabled.png"); +} + +QTabBar QToolButton::right-arrow:enabled, QDockWidget QTabBar QToolButton::right-arrow:enabled { + image: url(":/standard_dark/rc/arrow_right.png"); +} + +QTabBar QToolButton::right-arrow:disabled, QDockWidget QTabBar QToolButton::right-arrow:disabled { + image: url(":/standard_dark/rc/arrow_right_disabled.png"); +} + +/* QDockWiget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QDockWidget { + outline: 1px solid #455364; + background-color: #19232D; + border: 1px solid #455364; + border-radius: 4px; + titlebar-close-icon: url(":/standard_dark/rc/transparent.png"); + titlebar-normal-icon: url(":/standard_dark/rc/transparent.png"); +} + +QDockWidget::title { + /* Better size for title bar */ + padding: 3px; + spacing: 4px; + border: none; + background-color: #455364; +} + +QDockWidget::close-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + border: 0; + margin: 0; + padding: 0; + image: url(":/standard_dark/rc/window_close.png"); +} + +QDockWidget::close-button:hover { + image: url(":/standard_dark/rc/window_close_focus.png"); +} + +QDockWidget::close-button:pressed { + image: url(":/standard_dark/rc/window_close_pressed.png"); +} + +QDockWidget::float-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + border: 0; + margin: 0; + padding: 0; + image: url(":/standard_dark/rc/window_undock.png"); +} + +QDockWidget::float-button:hover { + image: url(":/standard_dark/rc/window_undock_focus.png"); +} + +QDockWidget::float-button:pressed { + image: url(":/standard_dark/rc/window_undock_pressed.png"); +} + +/* QTreeView QListView QTableView ----------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtreeview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview + +--------------------------------------------------------------------------- */ +QTreeView:branch:selected, QTreeView:branch:hover { + background: url(":/standard_dark/rc/transparent.png"); +} + +QTreeView:branch:has-siblings:!adjoins-item { + border-image: url(":/standard_dark/rc/branch_line.png") 0; +} + +QTreeView:branch:has-siblings:adjoins-item { + border-image: url(":/standard_dark/rc/branch_more.png") 0; +} + +QTreeView:branch:!has-children:!has-siblings:adjoins-item { + border-image: url(":/standard_dark/rc/branch_end.png") 0; +} + +QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings { + border-image: none; + image: url(":/standard_dark/rc/branch_closed.png"); +} + +QTreeView:branch:open:has-children:!has-siblings, QTreeView:branch:open:has-children:has-siblings { + border-image: none; + image: url(":/standard_dark/rc/branch_open.png"); +} + +QTreeView:branch:has-children:!has-siblings:closed:hover, QTreeView:branch:closed:has-children:has-siblings:hover { + image: url(":/standard_dark/rc/branch_closed_focus.png"); +} + +QTreeView:branch:open:has-children:!has-siblings:hover, QTreeView:branch:open:has-children:has-siblings:hover { + image: url(":/standard_dark/rc/branch_open_focus.png"); +} + +QTreeView::indicator:checked, +QListView::indicator:checked, +QTableView::indicator:checked, +QColumnView::indicator:checked { + image: url(":/standard_dark/rc/checkbox_checked.png"); +} + +QTreeView::indicator:checked:hover, QTreeView::indicator:checked:focus, QTreeView::indicator:checked:pressed, +QListView::indicator:checked:hover, +QListView::indicator:checked:focus, +QListView::indicator:checked:pressed, +QTableView::indicator:checked:hover, +QTableView::indicator:checked:focus, +QTableView::indicator:checked:pressed, +QColumnView::indicator:checked:hover, +QColumnView::indicator:checked:focus, +QColumnView::indicator:checked:pressed { + image: url(":/standard_dark/rc/checkbox_checked_focus.png"); +} + +QTreeView::indicator:unchecked, +QListView::indicator:unchecked, +QTableView::indicator:unchecked, +QColumnView::indicator:unchecked { + image: url(":/standard_dark/rc/checkbox_unchecked.png"); +} + +QTreeView::indicator:unchecked:hover, QTreeView::indicator:unchecked:focus, QTreeView::indicator:unchecked:pressed, +QListView::indicator:unchecked:hover, +QListView::indicator:unchecked:focus, +QListView::indicator:unchecked:pressed, +QTableView::indicator:unchecked:hover, +QTableView::indicator:unchecked:focus, +QTableView::indicator:unchecked:pressed, +QColumnView::indicator:unchecked:hover, +QColumnView::indicator:unchecked:focus, +QColumnView::indicator:unchecked:pressed { + image: url(":/standard_dark/rc/checkbox_unchecked_focus.png"); +} + +QTreeView::indicator:indeterminate, +QListView::indicator:indeterminate, +QTableView::indicator:indeterminate, +QColumnView::indicator:indeterminate { + image: url(":/standard_dark/rc/checkbox_indeterminate.png"); +} + +QTreeView::indicator:indeterminate:hover, QTreeView::indicator:indeterminate:focus, QTreeView::indicator:indeterminate:pressed, +QListView::indicator:indeterminate:hover, +QListView::indicator:indeterminate:focus, +QListView::indicator:indeterminate:pressed, +QTableView::indicator:indeterminate:hover, +QTableView::indicator:indeterminate:focus, +QTableView::indicator:indeterminate:pressed, +QColumnView::indicator:indeterminate:hover, +QColumnView::indicator:indeterminate:focus, +QColumnView::indicator:indeterminate:pressed { + image: url(":/standard_dark/rc/checkbox_indeterminate_focus.png"); +} + +QTreeView, +QListView, +QTableView, +QColumnView { + background-color: #19232D; + border: 1px solid #455364; + color: #E0E1E3; + gridline-color: #455364; + border-radius: 4px; +} + +QTreeView:disabled, +QListView:disabled, +QTableView:disabled, +QColumnView:disabled { + background-color: #19232D; + color: #9DA9B5; +} + +QTreeView:selected, +QListView:selected, +QTableView:selected, +QColumnView:selected { + background-color: #346792; + color: #455364; +} + +QTreeView:focus, +QListView:focus, +QTableView:focus, +QColumnView:focus { + border: 1px solid #1A72BB; +} + +QTreeView::item:pressed, +QListView::item:pressed, +QTableView::item:pressed, +QColumnView::item:pressed { + background-color: #346792; +} + +QTreeView::item:selected:active, +QListView::item:selected:active, +QTableView::item:selected:active, +QColumnView::item:selected:active { + background-color: #346792; +} + +QTreeView::item:selected:!active, +QListView::item:selected:!active, +QTableView::item:selected:!active, +QColumnView::item:selected:!active { + color: #E0E1E3; + background-color: #37414F; +} + +QTreeView::item:!selected:hover, +QListView::item:!selected:hover, +QTableView::item:!selected:hover, +QColumnView::item:!selected:hover { + outline: 0; + color: #E0E1E3; + background-color: #37414F; +} + +QTableCornerButton::section { + background-color: #19232D; + border: 1px transparent #455364; + border-radius: 0px; +} + +/* QHeaderView ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview + +--------------------------------------------------------------------------- */ +QHeaderView { + background-color: #455364; + border: 0px transparent #455364; + padding: 0; + margin: 0; + border-radius: 0; +} + +QHeaderView:disabled { + background-color: #455364; + border: 1px transparent #455364; +} + +QHeaderView::section { + background-color: #455364; + color: #E0E1E3; + border-radius: 0; + text-align: left; + font-size: 13px; +} + +QHeaderView::section::horizontal { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-left: 1px solid #19232D; +} + +QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one { + border-left: 1px solid #455364; +} + +QHeaderView::section::horizontal:disabled { + color: #9DA9B5; +} + +QHeaderView::section::vertical { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-top: 1px solid #19232D; +} + +QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one { + border-top: 1px solid #455364; +} + +QHeaderView::section::vertical:disabled { + color: #9DA9B5; +} + +QHeaderView::down-arrow { + /* Those settings (border/width/height/background-color) solve bug */ + /* transparent arrow background and size */ + background-color: #455364; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url(":/standard_dark/rc/arrow_down.png"); +} + +QHeaderView::up-arrow { + background-color: #455364; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url(":/standard_dark/rc/arrow_up.png"); +} + +/* QToolBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbox + +--------------------------------------------------------------------------- */ +QToolBox { + padding: 0px; + border: 0px; + border: 1px solid #455364; +} + +QToolBox:selected { + padding: 0px; + border: 2px solid #346792; +} + +QToolBox::tab { + background-color: #19232D; + border: 1px solid #455364; + color: #E0E1E3; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QToolBox::tab:disabled { + color: #9DA9B5; +} + +QToolBox::tab:selected { + background-color: #60798B; + border-bottom: 2px solid #346792; +} + +QToolBox::tab:selected:disabled { + background-color: #455364; + border-bottom: 2px solid #26486B; +} + +QToolBox::tab:!selected { + background-color: #455364; + border-bottom: 2px solid #455364; +} + +QToolBox::tab:!selected:disabled { + background-color: #19232D; +} + +QToolBox::tab:hover { + border-color: #1A72BB; + border-bottom: 2px solid #1A72BB; +} + +QToolBox QScrollArea QWidget QWidget { + padding: 0px; + border: 0px; + background-color: #19232D; +} + +/* QFrame ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe +https://doc.qt.io/qt-5/qframe.html#-prop +https://doc.qt.io/qt-5/qframe.html#details +https://stackoverflow.com/questions/14581498/qt-stylesheet-for-hline-vline-color + +--------------------------------------------------------------------------- */ +/* (dot) .QFrame fix #141, #126, #123 */ +.QFrame { + border-radius: 4px; + border: 1px solid #455364; + /* No frame */ + /* HLine */ + /* HLine */ +} + +.QFrame[frameShape="0"] { + border-radius: 4px; + border: 1px transparent #455364; +} + +.QFrame[frameShape="4"] { + max-height: 2px; + border: none; + background-color: #455364; +} + +.QFrame[frameShape="5"] { + max-width: 2px; + border: none; + background-color: #455364; +} + +/* QSplitter -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsplitter + +--------------------------------------------------------------------------- */ +QSplitter { + background-color: #455364; + spacing: 0px; + padding: 0px; + margin: 0px; +} + +QSplitter::handle { + background-color: #455364; + border: 0px solid #19232D; + spacing: 0px; + padding: 1px; + margin: 0px; +} + +QSplitter::handle:hover { + background-color: #9DA9B5; +} + +QSplitter::handle:horizontal { + width: 5px; + image: url(":/standard_dark/rc/line_vertical.png"); +} + +QSplitter::handle:vertical { + height: 5px; + image: url(":/standard_dark/rc/line_horizontal.png"); +} + +/* QDateEdit, QDateTimeEdit ----------------------------------------------- + +--------------------------------------------------------------------------- */ +QDateEdit, QDateTimeEdit { + selection-background-color: #346792; + border-style: solid; + border: 1px solid #455364; + border-radius: 4px; + /* This fixes 103, 111 */ + padding-top: 2px; + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + min-width: 10px; +} + +QDateEdit:on, QDateTimeEdit:on { + selection-background-color: #346792; +} + +QDateEdit::drop-down, QDateTimeEdit::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid #455364; +} + +QDateEdit::down-arrow, QDateTimeEdit::down-arrow { + image: url(":/standard_dark/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QDateEdit::down-arrow:on, QDateEdit::down-arrow:hover, QDateEdit::down-arrow:focus, QDateTimeEdit::down-arrow:on, QDateTimeEdit::down-arrow:hover, QDateTimeEdit::down-arrow:focus { + image: url(":/standard_dark/rc/arrow_down.png"); +} + +QDateEdit QAbstractItemView, QDateTimeEdit QAbstractItemView { + background-color: #19232D; + border-radius: 4px; + border: 1px solid #455364; + selection-background-color: #346792; +} + +/* QAbstractView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractView:hover { + border: 1px solid #346792; + color: #E0E1E3; +} + +QAbstractView:selected { + background: #346792; + color: #455364; +} + +/* PlotWidget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +PlotWidget { + /* Fix cut labels in plots #134 */ + padding: 0px; +} + +/**********************************/ +/* RetroShare specific part */ +/**********************************/ + +/**** Fix QPushButton ****/ + +QPushButton, +QPushButton:disabled, +QPushButton:checked { + padding-left: 6px; + padding-right: 6px; +} + +/**** Fix QTreeView Items ****/ + +QTreeView::item, +QListView::item, +QTableView::item, +QColumnView::item { + color: #F0F0F0; + background: transparent; +} +QTreeView:branch:!selected:hover, +QTreeView:branch:selected:!active { + color: #E0E1E3; + background-color: #37414F; +} + +/**** Fix QSplitter ****/ + +QSplitter { + background-color: rgba(0,0,0,0); +} +QSplitter::handle { + background-color: rgba(0,0,0,0); + border: 0px; + border-radius: 2px; + padding: 0px; +} + + +/**** Standard rules ****/ + +QFrame[objectName^="feedFrame"],/* Frame used in Feeds*/ +QFrame[objectName^="plainFrame"],/* Frame used in Widget with plain background*/ +QFrame[objectName^="plainBFrame"] {/* Frame used in Widget with plain bordered background*/ + background-color: #19232D; +} +QFrame[objectName^="plainBFrame"] { + border: 1px solid #32414B; +} + +/* Frame used in old Feeds*/ +QFrame#feedFrame[new=false] { + background-color: #19232D; +} +/* Frame used in new Feeds*/ +QFrame#feedFrame[new=true] { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #19232D, stop:0.8 #1251A0, stop: 0.81 #1251A0, stop: 1 #19232D); +} +QFrame#feedFrame QLabel { + background: transparent; +} + +QFrame[objectName^="gradFrame"],/* Frame used in Widget with gradient colored background*/ +QFrame#bottomFrame,/* Frame used at the bottom of dialog*/ +QFrame#toasterFrame,/* Frame used in Toasters*/ +QFrame#toolBarFrame {/* Frame used for buttons*/ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #19232D, stop:1 #32414B); + border: 1px solid #455364; +} +QFrame#toolBarFrame > LineEditClear { + background-color: #29333D; +} +QFrame[objectName^="gradFrame"] QComboBox, +QFrame[objectName^="gradFrame"] QLineEdit, +QFrame[objectName^="gradFrame"] QTextEdit { + background-color: #29333D; +} +QFrame[objectName^="gradFrame"] QComboBox QAbstractItemView { + background-color: #555555; + selection-background-color: #1464A0; +} + +QLabel#avatarLabel{ + border: 2px solid #CCCCCC; + border-radius: 4px; +} + + +/* HeaderFrame & TitleBarFrame */ + +QFrame[objectName^="headerFrame"], +QFrame[objectName^="headerBFrame"], +QToolBar#headerToolBar, +QFrame#titleBarFrame { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #455364, stop: 0.5 #54687A,stop: 0.6 #44586A, stop:1 #455364); + border: 0px; +} +QFrame[objectName^="headerBFrame"] { + border: 1px; + border-radius: 4px; +} +QFrame[objectName^="headerFrame"] > *:!hover, +QFrame[objectName^="headerBFrame"] > *:!hover, +QFrame#titleBarFrame > *:!hover { + background: transparent; + color: white; +} +QFrame#titleBarFrame QComboBox, +QFrame#titleBarFrame QLineEdit, +QFrame#titleBarFrame QTextEdit { + background: #29333D; +} + + +/**** Special Page tweak ****/ + + +/* Forums */ + +GxsForumThreadWidget QWidget#threadTreeWidget { + selection-background-color: #005599; + show-decoration-selected: 1; +} + +GxsForumThreadWidget QWidget#threadTreeWidget::item { + padding: 2px; +} + +GxsForumThreadWidget QWidget#threadTreeWidget::item:selected:active , +GxsForumThreadWidget QWidget#threadTreeWidget::item:selected:!active { + background-color: #005599; +} + + +/* Posted */ + +BoardPostDisplayWidget_compact QFrame#voteFrame, +BoardPostDisplayWidget_card QFrame#voteFrame, +PostedItem QFrame#voteFrame { + background: rgba( 80, 80, 80, 20% ); +} + +BoardPostDisplayWidget_card QToolButton#voteUpButton, +BoardPostDisplayWidget_compact QToolButton#voteUpButton { + background-color: #166716; + border: none; + border-radius: 4px; +} +BoardPostDisplayWidget_card QToolButton#voteDownButton, +BoardPostDisplayWidget_compact QToolButton#voteDownButton { + background-color: #673232; + border: none; + border-radius: 4px; +} + +BoardPostDisplayWidget_card QToolButton#voteUpButton:hover, +BoardPostDisplayWidget_compact QToolButton#voteUpButton:hover { + background-color: #166716; + border: 2px solid #808080; + border-radius: 4px; +} +BoardPostDisplayWidget_card QToolButton#voteDownButton:hover, +BoardPostDisplayWidget_compact QToolButton#voteDownButton:hover { + background-color: #673232; + border: 2px solid #808080; + border-radius: 4px; +} + +BoardPostDisplayWidget_card QToolButton#voteUpButton:disabled, +BoardPostDisplayWidget_compact QToolButton#voteUpButton:disabled, +BoardPostDisplayWidget_card QToolButton#voteDownButton:disabled, +BoardPostDisplayWidget_compact QToolButton#voteDownButton:disabled { + background: transparent; + border: none; +} + +BoardPostDisplayWidget_card QLabel#pictureLabel, +BoardPostDisplayWidget_compact QLabel#pictureLabel{ + border: 2px solid #444444; + border-radius: 3px; +} + + +/*************** Optional ***************/ + +/**** WikiPoos ****/ +WikiEditDialog QPushButton#pushButton_History { + color: white; + background: #5bb62b; + border-radius: 4px; + max-height: 20px; + min-width: 4em; + padding: 2px; + padding-left: 6px; + padding-right: 6px; +} + +WikiEditDialog QPushButton#pushButton_History:hover { + background: #57af29; +} + + +/**** The Wire ****/ + +WireGroupItem QFrame#wire_frame QLabel{ + background: transparent; +} +WireGroupItem QFrame#wire_frame:hover { + background-color: #346792; +} + +PulseTopLevel QFrame#frame, +PulseViewGroup QFrame#frame, +PulseReply QFrame#frame { + border: 2px solid #38444d; + border-radius: 6px; +} + +PulseReply #line_replyLine, +PulseMessage #line{ + color: #c4cfd6; +} + +PulseReply QLabel#label_groupName{ + color: #5b7083; +} + +PulseReplySeperator QFrame#frame { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #455364, stop: 0.5 #54687A,stop: 0.6 #44586A, stop:1 #455364); + border-radius: 10px; +} + +QLabel#label_masthead{ + border: 2px solid #CCCCCC; + border-radius: 4px; +} + +/**** Color definitions ****/ + +ForumsDialog, GxsForumThreadWidget +{ + qproperty-textColorRead: darkgray; + qproperty-textColorUnread: white; + qproperty-textColorUnreadChildren: red; + qproperty-textColorNotSubscribed: white; + qproperty-textColorMissing: darkred; + qproperty-textColorPinned: #D07000; + + qproperty-backgroundColorPinned: #19232D; + qproperty-backgroundColorFiltered: darkGreen; +} + +GroupTreeWidget +{ + qproperty-textColorCategory: rgb(3, 155, 198); + qproperty-textColorPrivateKey: rgb(249,185,0); +} + +NetworkDialog { + qproperty-backgroundColorSelf: darkred; + qproperty-backgroundColorOwnSign: darkred; + qproperty-backgroundColorAcceptConnection: black; + qproperty-backgroundColorHasSignedMe: darkred; + qproperty-backgroundColorDenied: #201F1F; + qproperty-textColor: white; +} + +NewFriendList { + qproperty-textColorStatusAway: #4040A0; + qproperty-textColorStatusBusy: #A04040; + qproperty-textColorStatusOnline: #40A040; + qproperty-textColorStatusInactive: #A0A040; + qproperty-textColorStatusOffline: gray; + qproperty-textColorGroup: rgb(123, 123, 123); +} + +RSTextBrowser, MimeTextEdit +{ + /*qproperty-textColorQuote: rgb(125, 125, 255);*/ + qproperty-textColorQuotes: ColorList(#789922 #039bd5 #800000 #800080 #008080 #b10dc9 #85144b #3d9970); +} + +/* OpModeStatus need to be at end to overload other values*/ + +OpModeStatus { + qproperty-opMode_Full_Color: #007000; + qproperty-opMode_NoTurtle_Color: #000070; + qproperty-opMode_Gaming_Color: #707000; + qproperty-opMode_Minimal_Color: #700000; +} +OpModeStatus[opMode="Full"] { + color: #F0F0F0; + background: #007000; +} +OpModeStatus[opMode="NoTurtle"] { + color: #F0F0F0; + background: #000070; +} +OpModeStatus[opMode="Gaming"] { + color: #F0F0F0; + background: #707000; +} +OpModeStatus[opMode="Minimal"] { + color: #F0F0F0; + background: #700000; +} + +/*Property Values at end to overwrite other settings*/ + +[new=false] { + background: #19232D; +} +[new=true] { + background: #1251A0; +} + +[valid=true] { + background: rgba(0,255,0,15%); +} + +[valid=false] { + background: rgba(255,0,0,15%); +} + +[WrongValue="true"] { + background-color: #702020; +} diff --git a/retroshare-gui/src/gui/qss/stylesheet/Standard_Light.qss b/retroshare-gui/src/gui/qss/stylesheet/Standard_Light.qss new file mode 100644 index 000000000..40fe0b78c --- /dev/null +++ b/retroshare-gui/src/gui/qss/stylesheet/Standard_Light.qss @@ -0,0 +1,2671 @@ +/* Standard Light stylesheet for RetroShare + Don't use font-size or font-weight, they are defined in .ui files. + Icon size are defined in .cpp files. + + For decoration, use px (pixel or dot) + For horizontal size, use em (width of M char) + For vertical size, use ex (height of x char to respect DotPerInch of your system) + See: https://doc.qt.io/qt-5/stylesheet-reference.html#length + + It use a public one for general widgets https://github.com/ColinDuquesnoy/QDarkStyleSheet + /qdarkstyle/light/style.qss + Updated at 2021-11-04 Tag v3.0.2 + Replace all ":/qss_icons/light" by ":/standard_light" + */ + +/* --------------------------------------------------------------------------- + + WARNING! File created programmatically. All changes made in this file will be lost! + + Created by the qtsass compiler v0.3.0 + + The definitions are in the "qdarkstyle.qss._styles.scss" module + +--------------------------------------------------------------------------- */ +/* Dark Style - QDarkStyleSheet ------------------------------------------ */ +/* + +See Qt documentation: + + - https://doc.qt.io/qt-5/stylesheet.html + - https://doc.qt.io/qt-5/stylesheet-reference.html + - https://doc.qt.io/qt-5/stylesheet-examples.html + +--------------------------------------------------------------------------- */ +/* Reset elements ------------------------------------------------------------ + +Resetting everything helps to unify styles across different operating systems + +--------------------------------------------------------------------------- */ +* { + padding: 0px; + margin: 0px; + border: 0px; + border-style: none; + border-image: none; + outline: 0; +} + +/* specific reset for elements inside QToolBar */ +QToolBar * { + margin: 0px; + padding: 0px; +} + +/* QWidget ---------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QWidget { + background-color: #FAFAFA; + border: 0px solid #C9CDD0; + padding: 0px; + color: #19232D; + selection-background-color: #9FCBFF; + selection-color: #19232D; +} + +QWidget:disabled { + background-color: #FAFAFA; + color: #788D9C; + selection-background-color: #DAEDFF; + selection-color: #788D9C; +} + +QWidget::item:selected { + background-color: #9FCBFF; +} + +QWidget::item:hover:!selected { + background-color: #73C7FF; +} + +/* QMainWindow ------------------------------------------------------------ + +This adjusts the splitter in the dock widget, not qsplitter +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmainwindow + +--------------------------------------------------------------------------- */ +QMainWindow::separator { + background-color: #C9CDD0; + border: 0px solid #FAFAFA; + spacing: 0px; + padding: 2px; +} + +QMainWindow::separator:hover { + background-color: #ACB1B6; + border: 0px solid #73C7FF; +} + +QMainWindow::separator:horizontal { + width: 5px; + margin-top: 2px; + margin-bottom: 2px; + image: url(":/standard_light/rc/toolbar_separator_vertical.png"); +} + +QMainWindow::separator:vertical { + height: 5px; + margin-left: 2px; + margin-right: 2px; + image: url(":/standard_light/rc/toolbar_separator_horizontal.png"); +} + +/* QToolTip --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtooltip + +--------------------------------------------------------------------------- */ +QToolTip { + background-color: #9FCBFF; + color: #19232D; + /* If you remove the border property, background stops working on Windows */ + border: none; + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + /* Remove opacity, fix #174 - may need to use RGBA */ +} + +/* QStatusBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar + +--------------------------------------------------------------------------- */ +QStatusBar { + border: 1px solid #C9CDD0; + /* Fixes Spyder #9120, #9121 */ + background: #C9CDD0; + /* Fixes #205, white vertical borders separating items */ +} + +QStatusBar::item { + border: none; +} + +QStatusBar QToolTip { + background-color: #73C7FF; + border: 1px solid #FAFAFA; + color: #FAFAFA; + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + /* Reducing transparency to read better */ + opacity: 230; +} + +QStatusBar QLabel { + /* Fixes Spyder #9120, #9121 */ + background: transparent; +} + +/* QCheckBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcheckbox + +--------------------------------------------------------------------------- */ +QCheckBox { + background-color: #FAFAFA; + color: #19232D; + spacing: 4px; + outline: none; + padding-top: 4px; + padding-bottom: 4px; +} + +QCheckBox:focus { + border: none; +} + +QCheckBox QWidget:disabled { + background-color: #FAFAFA; + color: #788D9C; +} + +QCheckBox::indicator { + margin-left: 2px; + height: 14px; + width: 14px; +} + +QCheckBox::indicator:unchecked { + image: url(":/standard_light/rc/checkbox_unchecked.png"); +} + +QCheckBox::indicator:unchecked:hover, QCheckBox::indicator:unchecked:focus, QCheckBox::indicator:unchecked:pressed { + border: none; + image: url(":/standard_light/rc/checkbox_unchecked_focus.png"); +} + +QCheckBox::indicator:unchecked:disabled { + image: url(":/standard_light/rc/checkbox_unchecked_disabled.png"); +} + +QCheckBox::indicator:checked { + image: url(":/standard_light/rc/checkbox_checked.png"); +} + +QCheckBox::indicator:checked:hover, QCheckBox::indicator:checked:focus, QCheckBox::indicator:checked:pressed { + border: none; + image: url(":/standard_light/rc/checkbox_checked_focus.png"); +} + +QCheckBox::indicator:checked:disabled { + image: url(":/standard_light/rc/checkbox_checked_disabled.png"); +} + +QCheckBox::indicator:indeterminate { + image: url(":/standard_light/rc/checkbox_indeterminate.png"); +} + +QCheckBox::indicator:indeterminate:disabled { + image: url(":/standard_light/rc/checkbox_indeterminate_disabled.png"); +} + +QCheckBox::indicator:indeterminate:focus, QCheckBox::indicator:indeterminate:hover, QCheckBox::indicator:indeterminate:pressed { + image: url(":/standard_light/rc/checkbox_indeterminate_focus.png"); +} + +/* QGroupBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox + +--------------------------------------------------------------------------- */ +QGroupBox { + font-weight: bold; + border: 1px solid #C0C4C8; + border-radius: 4px; + padding: 2px; + margin-top: 6px; + margin-bottom: 4px; +} + +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + left: 4px; + padding-left: 2px; + padding-right: 4px; + padding-top: -4px; +} + +QGroupBox::indicator { + margin-left: 2px; + margin-top: 2px; + padding: 0; + height: 14px; + width: 14px; +} + +QGroupBox::indicator:unchecked { + border: none; + image: url(":/standard_light/rc/checkbox_unchecked.png"); +} + +QGroupBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:focus, QGroupBox::indicator:unchecked:pressed { + border: none; + image: url(":/standard_light/rc/checkbox_unchecked_focus.png"); +} + +QGroupBox::indicator:unchecked:disabled { + image: url(":/standard_light/rc/checkbox_unchecked_disabled.png"); +} + +QGroupBox::indicator:checked { + border: none; + image: url(":/standard_light/rc/checkbox_checked.png"); +} + +QGroupBox::indicator:checked:hover, QGroupBox::indicator:checked:focus, QGroupBox::indicator:checked:pressed { + border: none; + image: url(":/standard_light/rc/checkbox_checked_focus.png"); +} + +QGroupBox::indicator:checked:disabled { + image: url(":/standard_light/rc/checkbox_checked_disabled.png"); +} + +/* QRadioButton ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qradiobutton + +--------------------------------------------------------------------------- */ +QRadioButton { + background-color: #FAFAFA; + color: #19232D; + spacing: 4px; + padding-top: 4px; + padding-bottom: 4px; + border: none; + outline: none; +} + +QRadioButton:focus { + border: none; +} + +QRadioButton:disabled { + background-color: #FAFAFA; + color: #788D9C; + border: none; + outline: none; +} + +QRadioButton QWidget { + background-color: #FAFAFA; + color: #19232D; + spacing: 0px; + padding: 0px; + outline: none; + border: none; +} + +QRadioButton::indicator { + border: none; + outline: none; + margin-left: 2px; + height: 14px; + width: 14px; +} + +QRadioButton::indicator:unchecked { + image: url(":/standard_light/rc/radio_unchecked.png"); +} + +QRadioButton::indicator:unchecked:hover, QRadioButton::indicator:unchecked:focus, QRadioButton::indicator:unchecked:pressed { + border: none; + outline: none; + image: url(":/standard_light/rc/radio_unchecked_focus.png"); +} + +QRadioButton::indicator:unchecked:disabled { + image: url(":/standard_light/rc/radio_unchecked_disabled.png"); +} + +QRadioButton::indicator:checked { + border: none; + outline: none; + image: url(":/standard_light/rc/radio_checked.png"); +} + +QRadioButton::indicator:checked:hover, QRadioButton::indicator:checked:focus, QRadioButton::indicator:checked:pressed { + border: none; + outline: none; + image: url(":/standard_light/rc/radio_checked_focus.png"); +} + +QRadioButton::indicator:checked:disabled { + outline: none; + image: url(":/standard_light/rc/radio_checked_disabled.png"); +} + +/* QMenuBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar + +--------------------------------------------------------------------------- */ +QMenuBar { + background-color: #C9CDD0; + padding: 2px; + border: 1px solid #FAFAFA; + color: #19232D; + selection-background-color: #73C7FF; +} + +QMenuBar:focus { + border: 1px solid #9FCBFF; +} + +QMenuBar::item { + background: transparent; + padding: 4px; +} + +QMenuBar::item:selected { + padding: 4px; + background: transparent; + border: 0px solid #C9CDD0; + background-color: #73C7FF; +} + +QMenuBar::item:pressed { + padding: 4px; + border: 0px solid #C9CDD0; + background-color: #73C7FF; + color: #19232D; + margin-bottom: 0px; + padding-bottom: 0px; +} + +/* QMenu ------------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu + +--------------------------------------------------------------------------- */ +QMenu { + border: 0px solid #C9CDD0; + color: #19232D; + margin: 0px; + background-color: #CED1D4; + selection-background-color: #73C7FF; +} + +QMenu::separator { + height: 1px; + background-color: #ACB1B6; + color: #19232D; +} + +QMenu::item { + background-color: #CED1D4; + padding: 4px 24px 4px 28px; + /* Reserve space for selection border */ + border: 1px transparent #C9CDD0; +} + +QMenu::item:selected { + color: #19232D; + background-color: #73C7FF; +} + +QMenu::item:pressed { + background-color: #73C7FF; +} + +QMenu::icon { + padding-left: 10px; + width: 14px; + height: 14px; +} + +QMenu::indicator { + padding-left: 8px; + width: 12px; + height: 12px; + /* non-exclusive indicator = check box style indicator (see QActionGroup::setExclusive) */ + /* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */ +} + +QMenu::indicator:non-exclusive:unchecked { + image: url(":/standard_light/rc/checkbox_unchecked.png"); +} + +QMenu::indicator:non-exclusive:unchecked:hover, QMenu::indicator:non-exclusive:unchecked:focus, QMenu::indicator:non-exclusive:unchecked:pressed { + border: none; + image: url(":/standard_light/rc/checkbox_unchecked_focus.png"); +} + +QMenu::indicator:non-exclusive:unchecked:disabled { + image: url(":/standard_light/rc/checkbox_unchecked_disabled.png"); +} + +QMenu::indicator:non-exclusive:checked { + image: url(":/standard_light/rc/checkbox_checked.png"); +} + +QMenu::indicator:non-exclusive:checked:hover, QMenu::indicator:non-exclusive:checked:focus, QMenu::indicator:non-exclusive:checked:pressed { + border: none; + image: url(":/standard_light/rc/checkbox_checked_focus.png"); +} + +QMenu::indicator:non-exclusive:checked:disabled { + image: url(":/standard_light/rc/checkbox_checked_disabled.png"); +} + +QMenu::indicator:non-exclusive:indeterminate { + image: url(":/standard_light/rc/checkbox_indeterminate.png"); +} + +QMenu::indicator:non-exclusive:indeterminate:disabled { + image: url(":/standard_light/rc/checkbox_indeterminate_disabled.png"); +} + +QMenu::indicator:non-exclusive:indeterminate:focus, QMenu::indicator:non-exclusive:indeterminate:hover, QMenu::indicator:non-exclusive:indeterminate:pressed { + image: url(":/standard_light/rc/checkbox_indeterminate_focus.png"); +} + +QMenu::indicator:exclusive:unchecked { + image: url(":/standard_light/rc/radio_unchecked.png"); +} + +QMenu::indicator:exclusive:unchecked:hover, QMenu::indicator:exclusive:unchecked:focus, QMenu::indicator:exclusive:unchecked:pressed { + border: none; + outline: none; + image: url(":/standard_light/rc/radio_unchecked_focus.png"); +} + +QMenu::indicator:exclusive:unchecked:disabled { + image: url(":/standard_light/rc/radio_unchecked_disabled.png"); +} + +QMenu::indicator:exclusive:checked { + border: none; + outline: none; + image: url(":/standard_light/rc/radio_checked.png"); +} + +QMenu::indicator:exclusive:checked:hover, QMenu::indicator:exclusive:checked:focus, QMenu::indicator:exclusive:checked:pressed { + border: none; + outline: none; + image: url(":/standard_light/rc/radio_checked_focus.png"); +} + +QMenu::indicator:exclusive:checked:disabled { + outline: none; + image: url(":/standard_light/rc/radio_checked_disabled.png"); +} + +QMenu::right-arrow { + margin: 5px; + padding-left: 12px; + image: url(":/standard_light/rc/arrow_right.png"); + height: 12px; + width: 12px; +} + +/* QAbstractItemView ------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QAbstractItemView { + alternate-background-color: #FAFAFA; + color: #19232D; + border: 1px solid #C9CDD0; + border-radius: 4px; +} + +QAbstractItemView QLineEdit { + padding: 2px; +} + +/* QAbstractScrollArea ---------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QAbstractScrollArea { + background-color: #FAFAFA; + border: 1px solid #C9CDD0; + border-radius: 4px; + /* fix #159 */ + padding: 2px; + /* remove min-height to fix #244 */ + color: #19232D; +} + +QAbstractScrollArea:disabled { + color: #788D9C; +} + +/* QScrollArea ------------------------------------------------------------ + +--------------------------------------------------------------------------- */ +QScrollArea QWidget QWidget:disabled { + background-color: #FAFAFA; +} + +/* QScrollBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qscrollbar + +--------------------------------------------------------------------------- */ +QScrollBar:horizontal { + height: 16px; + margin: 2px 16px 2px 16px; + border: 1px solid #C9CDD0; + border-radius: 4px; + background-color: #FAFAFA; +} + +QScrollBar:vertical { + background-color: #FAFAFA; + width: 16px; + margin: 16px 2px 16px 2px; + border: 1px solid #C9CDD0; + border-radius: 4px; +} + +QScrollBar::handle:horizontal { + background-color: #ACB1B6; + border: 1px solid #C9CDD0; + border-radius: 4px; + min-width: 8px; +} + +QScrollBar::handle:horizontal:hover { + background-color: #9FCBFF; + border: #9FCBFF; + border-radius: 4px; + min-width: 8px; +} + +QScrollBar::handle:horizontal:focus { + border: 1px solid #73C7FF; +} + +QScrollBar::handle:vertical { + background-color: #ACB1B6; + border: 1px solid #C9CDD0; + min-height: 8px; + border-radius: 4px; +} + +QScrollBar::handle:vertical:hover { + background-color: #9FCBFF; + border: #9FCBFF; + border-radius: 4px; + min-height: 8px; +} + +QScrollBar::handle:vertical:focus { + border: 1px solid #73C7FF; +} + +QScrollBar::add-line:horizontal { + margin: 0px 0px 0px 0px; + border-image: url(":/standard_light/rc/arrow_right_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::add-line:horizontal:hover, QScrollBar::add-line:horizontal:on { + border-image: url(":/standard_light/rc/arrow_right.png"); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::add-line:vertical { + margin: 3px 0px 3px 0px; + border-image: url(":/standard_light/rc/arrow_down_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on { + border-image: url(":/standard_light/rc/arrow_down.png"); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal { + margin: 0px 3px 0px 3px; + border-image: url(":/standard_light/rc/arrow_left_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on { + border-image: url(":/standard_light/rc/arrow_left.png"); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:vertical { + margin: 3px 0px 3px 0px; + border-image: url(":/standard_light/rc/arrow_up_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:vertical:hover, QScrollBar::sub-line:vertical:on { + border-image: url(":/standard_light/rc/arrow_up.png"); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal { + background: none; +} + +QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { + background: none; +} + +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + background: none; +} + +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + background: none; +} + +/* QTextEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-specific-widgets + +--------------------------------------------------------------------------- */ +QTextEdit { + background-color: #FAFAFA; + color: #19232D; + border-radius: 4px; + border: 1px solid #C9CDD0; +} + +QTextEdit:focus { + border: 1px solid #73C7FF; +} + +QTextEdit:selected { + background: #9FCBFF; + color: #C9CDD0; +} + +/* QPlainTextEdit --------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QPlainTextEdit { + background-color: #FAFAFA; + color: #19232D; + border-radius: 4px; + border: 1px solid #C9CDD0; +} + +QPlainTextEdit:focus { + border: 1px solid #73C7FF; +} + +QPlainTextEdit:selected { + background: #9FCBFF; + color: #C9CDD0; +} + +/* QSizeGrip -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsizegrip + +--------------------------------------------------------------------------- */ +QSizeGrip { + background: transparent; + width: 12px; + height: 12px; + image: url(":/standard_light/rc/window_grip.png"); +} + +/* QStackedWidget --------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QStackedWidget { + padding: 2px; + border: 1px solid #C9CDD0; + border: 1px solid #FAFAFA; +} + +/* QToolBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbar + +--------------------------------------------------------------------------- */ +QToolBar { + background-color: #C9CDD0; + border-bottom: 1px solid #FAFAFA; + padding: 1px; + font-weight: bold; + spacing: 2px; +} + +QToolBar:disabled { + /* Fixes #272 */ + background-color: #C9CDD0; +} + +QToolBar::handle:horizontal { + width: 16px; + image: url(":/standard_light/rc/toolbar_move_horizontal.png"); +} + +QToolBar::handle:vertical { + height: 16px; + image: url(":/standard_light/rc/toolbar_move_vertical.png"); +} + +QToolBar::separator:horizontal { + width: 16px; + image: url(":/standard_light/rc/toolbar_separator_horizontal.png"); +} + +QToolBar::separator:vertical { + height: 16px; + image: url(":/standard_light/rc/toolbar_separator_vertical.png"); +} + +QToolButton#qt_toolbar_ext_button { + background: #C9CDD0; + border: 0px; + color: #19232D; + image: url(":/standard_light/rc/arrow_right.png"); +} + +/* QAbstractSpinBox ------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractSpinBox { + background-color: #FAFAFA; + border: 1px solid #C9CDD0; + color: #19232D; + /* This fixes 103, 111 */ + padding-top: 2px; + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + border-radius: 4px; + /* min-width: 5px; removed to fix 109 */ +} + +QAbstractSpinBox:up-button { + background-color: transparent #FAFAFA; + subcontrol-origin: border; + subcontrol-position: top right; + border-left: 1px solid #C9CDD0; + border-bottom: 1px solid #C9CDD0; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-bottom: -1px; +} + +QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off { + image: url(":/standard_light/rc/arrow_up_disabled.png"); + height: 8px; + width: 8px; +} + +QAbstractSpinBox::up-arrow:hover { + image: url(":/standard_light/rc/arrow_up.png"); +} + +QAbstractSpinBox:down-button { + background-color: transparent #FAFAFA; + subcontrol-origin: border; + subcontrol-position: bottom right; + border-left: 1px solid #C9CDD0; + border-top: 1px solid #C9CDD0; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-top: -1px; +} + +QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off { + image: url(":/standard_light/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QAbstractSpinBox::down-arrow:hover { + image: url(":/standard_light/rc/arrow_down.png"); +} + +QAbstractSpinBox:hover { + border: 1px solid #9FCBFF; + color: #19232D; +} + +QAbstractSpinBox:focus { + border: 1px solid #73C7FF; +} + +QAbstractSpinBox:selected { + background: #9FCBFF; + color: #C9CDD0; +} + +/* ------------------------------------------------------------------------ */ +/* DISPLAYS --------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QLabel ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe + +--------------------------------------------------------------------------- */ +QLabel { + background-color: #FAFAFA; + border: 0px solid #C9CDD0; + padding: 2px; + margin: 0px; + color: #19232D; +} + +QLabel:disabled { + background-color: #FAFAFA; + border: 0px solid #C9CDD0; + color: #788D9C; +} + +/* QTextBrowser ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QTextBrowser { + background-color: #FAFAFA; + border: 1px solid #C9CDD0; + color: #19232D; + border-radius: 4px; +} + +QTextBrowser:disabled { + background-color: #FAFAFA; + border: 1px solid #C9CDD0; + color: #788D9C; + border-radius: 4px; +} + +QTextBrowser:hover, QTextBrowser:!hover, QTextBrowser:selected, QTextBrowser:pressed { + border: 1px solid #C9CDD0; +} + +/* QGraphicsView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QGraphicsView { + background-color: #FAFAFA; + border: 1px solid #C9CDD0; + color: #19232D; + border-radius: 4px; +} + +QGraphicsView:disabled { + background-color: #FAFAFA; + border: 1px solid #C9CDD0; + color: #788D9C; + border-radius: 4px; +} + +QGraphicsView:hover, QGraphicsView:!hover, QGraphicsView:selected, QGraphicsView:pressed { + border: 1px solid #C9CDD0; +} + +/* QCalendarWidget -------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCalendarWidget { + border: 1px solid #C9CDD0; + border-radius: 4px; +} + +QCalendarWidget:disabled { + background-color: #FAFAFA; + color: #788D9C; +} + +/* QLCDNumber ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QLCDNumber { + background-color: #FAFAFA; + color: #19232D; +} + +QLCDNumber:disabled { + background-color: #FAFAFA; + color: #788D9C; +} + +/* QProgressBar ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qprogressbar + +--------------------------------------------------------------------------- */ +QProgressBar { + background-color: #FAFAFA; + border: 1px solid #C9CDD0; + color: #19232D; + border-radius: 4px; + text-align: center; +} + +QProgressBar:disabled { + background-color: #FAFAFA; + border: 1px solid #C9CDD0; + color: #788D9C; + border-radius: 4px; + text-align: center; +} + +QProgressBar::chunk { + background-color: #9FCBFF; + color: #FAFAFA; + border-radius: 4px; +} + +QProgressBar::chunk:disabled { + background-color: #DAEDFF; + color: #788D9C; + border-radius: 4px; +} + +/* ------------------------------------------------------------------------ */ +/* BUTTONS ---------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QPushButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qpushbutton + +--------------------------------------------------------------------------- */ +QPushButton { + background-color: #C9CDD0; + color: #19232D; + border-radius: 4px; + padding: 2px; + outline: none; + border: none; +} + +QPushButton:disabled { + background-color: #C9CDD0; + color: #788D9C; + border-radius: 4px; + padding: 2px; +} + +QPushButton:checked { + background-color: #ACB1B6; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QPushButton:checked:disabled { + background-color: #ACB1B6; + color: #788D9C; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QPushButton:checked:selected { + background: #ACB1B6; +} + +QPushButton:hover { + background-color: #B9BDC1; + color: #19232D; +} + +QPushButton:pressed { + background-color: #ACB1B6; +} + +QPushButton:selected { + background: #ACB1B6; + color: #19232D; +} + +QPushButton::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: bottom right; + bottom: 4px; +} + +QDialogButtonBox QPushButton { + /* Issue #194 #248 - Special case of QPushButton inside dialogs, for better UI */ + min-width: 80px; +} + +/* QToolButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbutton + +--------------------------------------------------------------------------- */ +QToolButton { + background-color: #C9CDD0; + color: #19232D; + border-radius: 4px; + padding: 2px; + outline: none; + border: none; + /* The subcontrols below are used only in the DelayedPopup mode */ + /* The subcontrols below are used only in the MenuButtonPopup mode */ + /* The subcontrol below is used only in the InstantPopup or DelayedPopup mode */ +} + +QToolButton:disabled { + background-color: #C9CDD0; + color: #788D9C; + border-radius: 4px; + padding: 2px; +} + +QToolButton:checked { + background-color: #ACB1B6; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QToolButton:checked:disabled { + background-color: #ACB1B6; + color: #788D9C; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QToolButton:checked:hover { + background-color: #B9BDC1; + color: #19232D; +} + +QToolButton:checked:pressed { + background-color: #ACB1B6; +} + +QToolButton:checked:selected { + background: #ACB1B6; + color: #19232D; +} + +QToolButton:hover { + background-color: #B9BDC1; + color: #19232D; +} + +QToolButton:pressed { + background-color: #ACB1B6; +} + +QToolButton:selected { + background: #ACB1B6; + color: #19232D; +} + +QToolButton[popupMode="0"] { + /* Only for DelayedPopup */ + padding-right: 2px; +} + +QToolButton[popupMode="1"] { + /* Only for MenuButtonPopup */ + padding-right: 20px; +} + +QToolButton[popupMode="1"]::menu-button { + border: none; +} + +QToolButton[popupMode="1"]::menu-button:hover { + border: none; + border-left: 1px solid #C9CDD0; + border-radius: 0; +} + +QToolButton[popupMode="2"] { + /* Only for InstantPopup */ + padding-right: 2px; +} + +QToolButton::menu-button { + padding: 2px; + border-radius: 4px; + width: 12px; + border: none; + outline: none; +} + +QToolButton::menu-button:hover { + border: 1px solid #9FCBFF; +} + +QToolButton::menu-button:checked:hover { + border: 1px solid #9FCBFF; +} + +QToolButton::menu-indicator { + image: url(":/standard_light/rc/arrow_down.png"); + height: 8px; + width: 8px; + top: 0; + /* Exclude a shift for better image */ + left: -2px; + /* Shift it a bit */ +} + +QToolButton::menu-arrow { + image: url(":/standard_light/rc/arrow_down.png"); + height: 8px; + width: 8px; +} + +QToolButton::menu-arrow:hover { + image: url(":/standard_light/rc/arrow_down_focus.png"); +} + +/* QCommandLinkButton ----------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCommandLinkButton { + background-color: transparent; + border: 1px solid #C9CDD0; + color: #19232D; + border-radius: 4px; + padding: 0px; + margin: 0px; +} + +QCommandLinkButton:disabled { + background-color: transparent; + color: #788D9C; +} + +/* ------------------------------------------------------------------------ */ +/* INPUTS - NO FIELDS ----------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QComboBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QComboBox { + border: 1px solid #C0C4C8; + border-radius: 4px; + selection-background-color: #9FCBFF; + padding-left: 4px; + padding-right: 4px; + /* padding-right = 36; 4 + 16*2 See scrollbar size */ + /* changed to 4px to fix #239 */ + /* Fixes #103, #111 */ + min-height: 1.5em; + /* padding-top: 2px; removed to fix #132 */ + /* padding-bottom: 2px; removed to fix #132 */ + /* min-width: 75px; removed to fix #109 */ + /* Needed to remove indicator - fix #132 */ +} + +QComboBox QAbstractItemView { + border: 1px solid #C0C4C8; + border-radius: 0; + background-color: #FAFAFA; + selection-background-color: #9FCBFF; +} + +QComboBox QAbstractItemView:hover { + background-color: #FAFAFA; + color: #19232D; +} + +QComboBox QAbstractItemView:selected { + background: #9FCBFF; + color: #C0C4C8; +} + +QComboBox QAbstractItemView:alternate { + background: #FAFAFA; +} + +QComboBox:disabled { + background-color: #FAFAFA; + color: #788D9C; +} + +QComboBox:hover { + border: 1px solid #9FCBFF; +} + +QComboBox:focus { + border: 1px solid #73C7FF; +} + +QComboBox:on { + selection-background-color: #9FCBFF; +} + +QComboBox::indicator { + border: none; + border-radius: 0; + background-color: transparent; + selection-background-color: transparent; + color: transparent; + selection-color: transparent; + /* Needed to remove indicator - fix #132 */ +} + +QComboBox::indicator:alternate { + background: #FAFAFA; +} + +QComboBox::item { + /* Remove to fix #282, #285 and MR #288*/ + /*&:checked { + font-weight: bold; + } + + &:selected { + border: 0px solid transparent; + } + */ +} + +QComboBox::item:alternate { + background: #FAFAFA; +} + +QComboBox::item:checked { + font-weight: bold; +} + +QComboBox::item:selected { + border: 0px solid transparent; +} + +QComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid #C9CDD0; +} + +QComboBox::down-arrow { + image: url(":/standard_light/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QComboBox::down-arrow:on, QComboBox::down-arrow:hover, QComboBox::down-arrow:focus { + image: url(":/standard_light/rc/arrow_down.png"); +} + +/* QSlider ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qslider + +--------------------------------------------------------------------------- */ +QSlider:disabled { + background: #FAFAFA; +} + +QSlider:focus { + border: none; +} + +QSlider::groove:horizontal { + background: #C9CDD0; + border: 1px solid #C9CDD0; + height: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::groove:vertical { + background: #C9CDD0; + border: 1px solid #C9CDD0; + width: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::add-page:vertical { + background: #9FCBFF; + border: 1px solid #C9CDD0; + width: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::add-page:vertical :disabled { + background: #DAEDFF; +} + +QSlider::sub-page:horizontal { + background: #9FCBFF; + border: 1px solid #C9CDD0; + height: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::sub-page:horizontal:disabled { + background: #DAEDFF; +} + +QSlider::handle:horizontal { + background: #788D9C; + border: 1px solid #C9CDD0; + width: 8px; + height: 8px; + margin: -8px 0px; + border-radius: 4px; +} + +QSlider::handle:horizontal:hover { + background: #9FCBFF; + border: 1px solid #9FCBFF; +} + +QSlider::handle:horizontal:focus { + border: 1px solid #73C7FF; +} + +QSlider::handle:vertical { + background: #788D9C; + border: 1px solid #C9CDD0; + width: 8px; + height: 8px; + margin: 0 -8px; + border-radius: 4px; +} + +QSlider::handle:vertical:hover { + background: #9FCBFF; + border: 1px solid #9FCBFF; +} + +QSlider::handle:vertical:focus { + border: 1px solid #73C7FF; +} + +/* QLineEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlineedit + +--------------------------------------------------------------------------- */ +QLineEdit { + background-color: #FAFAFA; + padding-top: 2px; + /* This QLineEdit fix 103, 111 */ + padding-bottom: 2px; + /* This QLineEdit fix 103, 111 */ + padding-left: 4px; + padding-right: 4px; + border-style: solid; + border: 1px solid #C0C4C8; + border-radius: 4px; + color: #19232D; +} + +QLineEdit:disabled { + background-color: #FAFAFA; + color: #9DA9B5; +} + +QLineEdit:hover { + border: 1px solid #9FCBFF; + color: #19232D; +} + +QLineEdit:focus { + border: 1px solid #73C7FF; +} + +QLineEdit:selected { + background-color: #9FCBFF; + color: #C9CDD0; +} + +/* QTabWiget -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabWidget { + padding: 2px; + selection-background-color: #C9CDD0; +} + +QTabWidget QWidget { + /* Fixes #189 */ + border-radius: 4px; +} + +QTabWidget::pane { + border: 1px solid #C9CDD0; + border-radius: 4px; + margin: 0px; + /* Fixes double border inside pane with pyqt5 */ + padding: 0px; +} + +QTabWidget::pane:selected { + background-color: #C9CDD0; + border: 1px solid #9FCBFF; +} + +/* QTabBar ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabBar, QDockWidget QTabBar { + qproperty-drawBase: 0; + border-radius: 4px; + margin: 0px; + padding: 2px; + border: 0; + /* left: 5px; move to the right by 5px - removed for fix */ +} + +QTabBar::close-button, QDockWidget QTabBar::close-button { + border: 0; + margin: 0; + padding: 4px; + image: url(":/standard_light/rc/window_close.png"); +} + +QTabBar::close-button:hover, QDockWidget QTabBar::close-button:hover { + image: url(":/standard_light/rc/window_close_focus.png"); +} + +QTabBar::close-button:pressed, QDockWidget QTabBar::close-button:pressed { + image: url(":/standard_light/rc/window_close_pressed.png"); +} + +QTabBar::tab, QDockWidget QTabBar::tab { + /* !selected and disabled ----------------------------------------- */ + /* selected ------------------------------------------------------- */ +} + +QTabBar::tab:top:selected:disabled, QDockWidget QTabBar::tab:top:selected:disabled { + border-bottom: 3px solid #DAEDFF; + color: #788D9C; + background-color: #C9CDD0; +} + +QTabBar::tab:bottom:selected:disabled, QDockWidget QTabBar::tab:bottom:selected:disabled { + border-top: 3px solid #DAEDFF; + color: #788D9C; + background-color: #C9CDD0; +} + +QTabBar::tab:left:selected:disabled, QDockWidget QTabBar::tab:left:selected:disabled { + border-right: 3px solid #DAEDFF; + color: #788D9C; + background-color: #C9CDD0; +} + +QTabBar::tab:right:selected:disabled, QDockWidget QTabBar::tab:right:selected:disabled { + border-left: 3px solid #DAEDFF; + color: #788D9C; + background-color: #C9CDD0; +} + +QTabBar::tab:top:!selected:disabled, QDockWidget QTabBar::tab:top:!selected:disabled { + border-bottom: 3px solid #FAFAFA; + color: #788D9C; + background-color: #FAFAFA; +} + +QTabBar::tab:bottom:!selected:disabled, QDockWidget QTabBar::tab:bottom:!selected:disabled { + border-top: 3px solid #FAFAFA; + color: #788D9C; + background-color: #FAFAFA; +} + +QTabBar::tab:left:!selected:disabled, QDockWidget QTabBar::tab:left:!selected:disabled { + border-right: 3px solid #FAFAFA; + color: #788D9C; + background-color: #FAFAFA; +} + +QTabBar::tab:right:!selected:disabled, QDockWidget QTabBar::tab:right:!selected:disabled { + border-left: 3px solid #FAFAFA; + color: #788D9C; + background-color: #FAFAFA; +} + +QTabBar::tab:top:!selected, QDockWidget QTabBar::tab:top:!selected { + border-bottom: 2px solid #FAFAFA; + margin-top: 2px; +} + +QTabBar::tab:bottom:!selected, QDockWidget QTabBar::tab:bottom:!selected { + border-top: 2px solid #FAFAFA; + margin-bottom: 2px; +} + +QTabBar::tab:left:!selected, QDockWidget QTabBar::tab:left:!selected { + border-left: 2px solid #FAFAFA; + margin-right: 2px; +} + +QTabBar::tab:right:!selected, QDockWidget QTabBar::tab:right:!selected { + border-right: 2px solid #FAFAFA; + margin-left: 2px; +} + +QTabBar::tab:top, QDockWidget QTabBar::tab:top { + background-color: #C9CDD0; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + min-width: 5px; + border-bottom: 3px solid #C9CDD0; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QTabBar::tab:top:selected, QDockWidget QTabBar::tab:top:selected { + background-color: #B9BDC1; + border-bottom: 3px solid #37AEFE; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QTabBar::tab:top:!selected:hover, QDockWidget QTabBar::tab:top:!selected:hover { + border: 1px solid #73C7FF; + border-bottom: 3px solid #73C7FF; + /* Fixes spyder-ide/spyder#9766 and #243 */ + padding-left: 3px; + padding-right: 3px; +} + +QTabBar::tab:bottom, QDockWidget QTabBar::tab:bottom { + border-top: 3px solid #C9CDD0; + background-color: #C9CDD0; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + min-width: 5px; +} + +QTabBar::tab:bottom:selected, QDockWidget QTabBar::tab:bottom:selected { + background-color: #B9BDC1; + border-top: 3px solid #37AEFE; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +QTabBar::tab:bottom:!selected:hover, QDockWidget QTabBar::tab:bottom:!selected:hover { + border: 1px solid #73C7FF; + border-top: 3px solid #73C7FF; + /* Fixes spyder-ide/spyder#9766 and #243 */ + padding-left: 3px; + padding-right: 3px; +} + +QTabBar::tab:left, QDockWidget QTabBar::tab:left { + background-color: #C9CDD0; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + min-height: 5px; +} + +QTabBar::tab:left:selected, QDockWidget QTabBar::tab:left:selected { + background-color: #B9BDC1; + border-right: 3px solid #37AEFE; +} + +QTabBar::tab:left:!selected:hover, QDockWidget QTabBar::tab:left:!selected:hover { + border: 1px solid #73C7FF; + border-right: 3px solid #73C7FF; + /* Fixes different behavior #271 */ + margin-right: 0px; + padding-right: -1px; +} + +QTabBar::tab:right, QDockWidget QTabBar::tab:right { + background-color: #C9CDD0; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + min-height: 5px; +} + +QTabBar::tab:right:selected, QDockWidget QTabBar::tab:right:selected { + background-color: #B9BDC1; + border-left: 3px solid #37AEFE; +} + +QTabBar::tab:right:!selected:hover, QDockWidget QTabBar::tab:right:!selected:hover { + border: 1px solid #73C7FF; + border-left: 3px solid #73C7FF; + /* Fixes different behavior #271 */ + margin-left: 0px; + padding-left: 0px; +} + +QTabBar QToolButton, QDockWidget QTabBar QToolButton { + /* Fixes #136 */ + background-color: #C9CDD0; + height: 12px; + width: 12px; +} + +QTabBar QToolButton:pressed, QDockWidget QTabBar QToolButton:pressed { + background-color: #C9CDD0; +} + +QTabBar QToolButton:pressed:hover, QDockWidget QTabBar QToolButton:pressed:hover { + border: 1px solid #9FCBFF; +} + +QTabBar QToolButton::left-arrow:enabled, QDockWidget QTabBar QToolButton::left-arrow:enabled { + image: url(":/standard_light/rc/arrow_left.png"); +} + +QTabBar QToolButton::left-arrow:disabled, QDockWidget QTabBar QToolButton::left-arrow:disabled { + image: url(":/standard_light/rc/arrow_left_disabled.png"); +} + +QTabBar QToolButton::right-arrow:enabled, QDockWidget QTabBar QToolButton::right-arrow:enabled { + image: url(":/standard_light/rc/arrow_right.png"); +} + +QTabBar QToolButton::right-arrow:disabled, QDockWidget QTabBar QToolButton::right-arrow:disabled { + image: url(":/standard_light/rc/arrow_right_disabled.png"); +} + +/* QDockWiget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QDockWidget { + outline: 1px solid #C9CDD0; + background-color: #FAFAFA; + border: 1px solid #C9CDD0; + border-radius: 4px; + titlebar-close-icon: url(":/standard_light/rc/transparent.png"); + titlebar-normal-icon: url(":/standard_light/rc/transparent.png"); +} + +QDockWidget::title { + /* Better size for title bar */ + padding: 3px; + spacing: 4px; + border: none; + background-color: #C9CDD0; +} + +QDockWidget::close-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + border: 0; + margin: 0; + padding: 0; + image: url(":/standard_light/rc/window_close.png"); +} + +QDockWidget::close-button:hover { + image: url(":/standard_light/rc/window_close_focus.png"); +} + +QDockWidget::close-button:pressed { + image: url(":/standard_light/rc/window_close_pressed.png"); +} + +QDockWidget::float-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + border: 0; + margin: 0; + padding: 0; + image: url(":/standard_light/rc/window_undock.png"); +} + +QDockWidget::float-button:hover { + image: url(":/standard_light/rc/window_undock_focus.png"); +} + +QDockWidget::float-button:pressed { + image: url(":/standard_light/rc/window_undock_pressed.png"); +} + +/* QTreeView QListView QTableView ----------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtreeview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview + +--------------------------------------------------------------------------- */ +QTreeView:branch:selected, QTreeView:branch:hover { + background: url(":/standard_light/rc/transparent.png"); +} + +QTreeView:branch:has-siblings:!adjoins-item { + border-image: url(":/standard_light/rc/branch_line.png") 0; +} + +QTreeView:branch:has-siblings:adjoins-item { + border-image: url(":/standard_light/rc/branch_more.png") 0; +} + +QTreeView:branch:!has-children:!has-siblings:adjoins-item { + border-image: url(":/standard_light/rc/branch_end.png") 0; +} + +QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings { + border-image: none; + image: url(":/standard_light/rc/branch_closed.png"); +} + +QTreeView:branch:open:has-children:!has-siblings, QTreeView:branch:open:has-children:has-siblings { + border-image: none; + image: url(":/standard_light/rc/branch_open.png"); +} + +QTreeView:branch:has-children:!has-siblings:closed:hover, QTreeView:branch:closed:has-children:has-siblings:hover { + image: url(":/standard_light/rc/branch_closed_focus.png"); +} + +QTreeView:branch:open:has-children:!has-siblings:hover, QTreeView:branch:open:has-children:has-siblings:hover { + image: url(":/standard_light/rc/branch_open_focus.png"); +} + +QTreeView::indicator:checked, +QListView::indicator:checked, +QTableView::indicator:checked, +QColumnView::indicator:checked { + image: url(":/standard_light/rc/checkbox_checked.png"); +} + +QTreeView::indicator:checked:hover, QTreeView::indicator:checked:focus, QTreeView::indicator:checked:pressed, +QListView::indicator:checked:hover, +QListView::indicator:checked:focus, +QListView::indicator:checked:pressed, +QTableView::indicator:checked:hover, +QTableView::indicator:checked:focus, +QTableView::indicator:checked:pressed, +QColumnView::indicator:checked:hover, +QColumnView::indicator:checked:focus, +QColumnView::indicator:checked:pressed { + image: url(":/standard_light/rc/checkbox_checked_focus.png"); +} + +QTreeView::indicator:unchecked, +QListView::indicator:unchecked, +QTableView::indicator:unchecked, +QColumnView::indicator:unchecked { + image: url(":/standard_light/rc/checkbox_unchecked.png"); +} + +QTreeView::indicator:unchecked:hover, QTreeView::indicator:unchecked:focus, QTreeView::indicator:unchecked:pressed, +QListView::indicator:unchecked:hover, +QListView::indicator:unchecked:focus, +QListView::indicator:unchecked:pressed, +QTableView::indicator:unchecked:hover, +QTableView::indicator:unchecked:focus, +QTableView::indicator:unchecked:pressed, +QColumnView::indicator:unchecked:hover, +QColumnView::indicator:unchecked:focus, +QColumnView::indicator:unchecked:pressed { + image: url(":/standard_light/rc/checkbox_unchecked_focus.png"); +} + +QTreeView::indicator:indeterminate, +QListView::indicator:indeterminate, +QTableView::indicator:indeterminate, +QColumnView::indicator:indeterminate { + image: url(":/standard_light/rc/checkbox_indeterminate.png"); +} + +QTreeView::indicator:indeterminate:hover, QTreeView::indicator:indeterminate:focus, QTreeView::indicator:indeterminate:pressed, +QListView::indicator:indeterminate:hover, +QListView::indicator:indeterminate:focus, +QListView::indicator:indeterminate:pressed, +QTableView::indicator:indeterminate:hover, +QTableView::indicator:indeterminate:focus, +QTableView::indicator:indeterminate:pressed, +QColumnView::indicator:indeterminate:hover, +QColumnView::indicator:indeterminate:focus, +QColumnView::indicator:indeterminate:pressed { + image: url(":/standard_light/rc/checkbox_indeterminate_focus.png"); +} + +QTreeView, +QListView, +QTableView, +QColumnView { + background-color: #FAFAFA; + border: 1px solid #C9CDD0; + color: #19232D; + gridline-color: #C9CDD0; + border-radius: 4px; +} + +QTreeView:disabled, +QListView:disabled, +QTableView:disabled, +QColumnView:disabled { + background-color: #FAFAFA; + color: #788D9C; +} + +QTreeView:selected, +QListView:selected, +QTableView:selected, +QColumnView:selected { + background-color: #9FCBFF; + color: #C9CDD0; +} + +QTreeView:focus, +QListView:focus, +QTableView:focus, +QColumnView:focus { + border: 1px solid #73C7FF; +} + +QTreeView::item:pressed, +QListView::item:pressed, +QTableView::item:pressed, +QColumnView::item:pressed { + background-color: #9FCBFF; +} + +QTreeView::item:selected:active, +QListView::item:selected:active, +QTableView::item:selected:active, +QColumnView::item:selected:active { + background-color: #9FCBFF; +} + +QTreeView::item:selected:!active, +QListView::item:selected:!active, +QTableView::item:selected:!active, +QColumnView::item:selected:!active { + color: #19232D; + background-color: #CED1D4; +} + +QTreeView::item:!selected:hover, +QListView::item:!selected:hover, +QTableView::item:!selected:hover, +QColumnView::item:!selected:hover { + outline: 0; + color: #19232D; + background-color: #CED1D4; +} + +QTableCornerButton::section { + background-color: #FAFAFA; + border: 1px transparent #C9CDD0; + border-radius: 0px; +} + +/* QHeaderView ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview + +--------------------------------------------------------------------------- */ +QHeaderView { + background-color: #C9CDD0; + border: 0px transparent #C9CDD0; + padding: 0; + margin: 0; + border-radius: 0; +} + +QHeaderView:disabled { + background-color: #C9CDD0; + border: 1px transparent #C9CDD0; +} + +QHeaderView::section { + background-color: #C9CDD0; + color: #19232D; + border-radius: 0; + text-align: left; + font-size: 13px; +} + +QHeaderView::section::horizontal { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-left: 1px solid #FAFAFA; +} + +QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one { + border-left: 1px solid #C9CDD0; +} + +QHeaderView::section::horizontal:disabled { + color: #788D9C; +} + +QHeaderView::section::vertical { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-top: 1px solid #FAFAFA; +} + +QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one { + border-top: 1px solid #C9CDD0; +} + +QHeaderView::section::vertical:disabled { + color: #788D9C; +} + +QHeaderView::down-arrow { + /* Those settings (border/width/height/background-color) solve bug */ + /* transparent arrow background and size */ + background-color: #C9CDD0; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url(":/standard_light/rc/arrow_down.png"); +} + +QHeaderView::up-arrow { + background-color: #C9CDD0; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url(":/standard_light/rc/arrow_up.png"); +} + +/* QToolBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbox + +--------------------------------------------------------------------------- */ +QToolBox { + padding: 0px; + border: 0px; + border: 1px solid #C9CDD0; +} + +QToolBox:selected { + padding: 0px; + border: 2px solid #9FCBFF; +} + +QToolBox::tab { + background-color: #FAFAFA; + border: 1px solid #C9CDD0; + color: #19232D; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QToolBox::tab:disabled { + color: #788D9C; +} + +QToolBox::tab:selected { + background-color: #ACB1B6; + border-bottom: 2px solid #9FCBFF; +} + +QToolBox::tab:selected:disabled { + background-color: #C9CDD0; + border-bottom: 2px solid #DAEDFF; +} + +QToolBox::tab:!selected { + background-color: #C9CDD0; + border-bottom: 2px solid #C9CDD0; +} + +QToolBox::tab:!selected:disabled { + background-color: #FAFAFA; +} + +QToolBox::tab:hover { + border-color: #73C7FF; + border-bottom: 2px solid #73C7FF; +} + +QToolBox QScrollArea QWidget QWidget { + padding: 0px; + border: 0px; + background-color: #FAFAFA; +} + +/* QFrame ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe +https://doc.qt.io/qt-5/qframe.html#-prop +https://doc.qt.io/qt-5/qframe.html#details +https://stackoverflow.com/questions/14581498/qt-stylesheet-for-hline-vline-color + +--------------------------------------------------------------------------- */ +/* (dot) .QFrame fix #141, #126, #123 */ +.QFrame { + border-radius: 4px; + border: 1px solid #C9CDD0; + /* No frame */ + /* HLine */ + /* HLine */ +} + +.QFrame[frameShape="0"] { + border-radius: 4px; + border: 1px transparent #C9CDD0; +} + +.QFrame[frameShape="4"] { + max-height: 2px; + border: none; + background-color: #C9CDD0; +} + +.QFrame[frameShape="5"] { + max-width: 2px; + border: none; + background-color: #C9CDD0; +} + +/* QSplitter -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsplitter + +--------------------------------------------------------------------------- */ +QSplitter { + background-color: #C9CDD0; + spacing: 0px; + padding: 0px; + margin: 0px; +} + +QSplitter::handle { + background-color: #C9CDD0; + border: 0px solid #FAFAFA; + spacing: 0px; + padding: 1px; + margin: 0px; +} + +QSplitter::handle:hover { + background-color: #788D9C; +} + +QSplitter::handle:horizontal { + width: 2px; + image: url(":/standard_light/rc/line_vertical.png"); +} + +QSplitter::handle:vertical { + height: 2px; + image: url(":/standard_light/rc/line_horizontal.png"); +} + +/* QDateEdit, QDateTimeEdit ----------------------------------------------- + +--------------------------------------------------------------------------- */ +QDateEdit, QDateTimeEdit { + selection-background-color: #9FCBFF; + border-style: solid; + border: 1px solid #C9CDD0; + border-radius: 4px; + /* This fixes 103, 111 */ + padding-top: 2px; + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + min-width: 10px; +} + +QDateEdit:on, QDateTimeEdit:on { + selection-background-color: #9FCBFF; +} + +QDateEdit::drop-down, QDateTimeEdit::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid #C9CDD0; +} + +QDateEdit::down-arrow, QDateTimeEdit::down-arrow { + image: url(":/standard_light/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QDateEdit::down-arrow:on, QDateEdit::down-arrow:hover, QDateEdit::down-arrow:focus, QDateTimeEdit::down-arrow:on, QDateTimeEdit::down-arrow:hover, QDateTimeEdit::down-arrow:focus { + image: url(":/standard_light/rc/arrow_down.png"); +} + +QDateEdit QAbstractItemView, QDateTimeEdit QAbstractItemView { + background-color: #FAFAFA; + border-radius: 4px; + border: 1px solid #C9CDD0; + selection-background-color: #9FCBFF; +} + +/* QAbstractView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractView:hover { + border: 1px solid #9FCBFF; + color: #19232D; +} + +QAbstractView:selected { + background: #9FCBFF; + color: #C9CDD0; +} + +/* PlotWidget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +PlotWidget { + /* Fix cut labels in plots #134 */ + padding: 0px; +} + +/**********************************/ +/* RetroShare specific part */ +/**********************************/ + +/**** Fix QPushButton ****/ + +QPushButton, +QPushButton:disabled, +QPushButton:checked { + padding-left: 6px; + padding-right: 6px; +} + +/**** Fix QTreeView Items ****/ + +QTreeView::item, +QListView::item, +QTableView::item, +QColumnView::item { + color: #101010; + background: transparent; +} +QTreeView:branch:!selected:hover, +QTreeView:branch:selected:!active { + color: #19232D; + background-color: #CED1D4; +} + +/**** Fix QSplitter ****/ + +QSplitter { + background-color: rgba(0,0,0,0); +} +QSplitter::handle { + background-color: rgba(0,0,0,0); + border: 0px; + border-radius: 2px; + padding: 0px; +} + + +/**** Standard rules ****/ + +QFrame[objectName^="feedFrame"],/* Frame used in Feeds*/ +QFrame[objectName^="plainFrame"],/* Frame used in Widget with plain background*/ +QFrame[objectName^="plainBFrame"] {/* Frame used in Widget with plain bordered background*/ + background-color: white; +} +QFrame[objectName^="plainBFrame"] { + border: 1px solid #CCCCCC; +} + +/* Frame used in old Feeds*/ +QFrame#feedFrame[new=false] { + background-color: #white; +} +/* Frame used in new Feeds*/ +QFrame#feedFrame[new=true] { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #F0F8FD, stop:0.8 #E6F2FD, stop: 0.81 #E6F2FD, stop: 1 #D2E7FD); +} +QFrame#feedFrame QLabel { + background: transparent; +} + +QFrame[objectName^="gradFrame"],/* Frame used in Widget with gradient colored background*/ +QFrame#bottomFrame,/* Frame used at the bottom of dialog*/ +QFrame#toasterFrame,/* Frame used in Toasters*/ +QFrame#toolBarFrame {/* Frame used for buttons*/ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FEFEFE, stop:1 #E8E8E8); + border: 1px solid #CCCCCC; +} +QFrame#toolBarFrame > LineEditClear { + background-color: white; +} +QFrame[objectName^="gradFrame"] QComboBox, +QFrame[objectName^="gradFrame"] QLineEdit, +QFrame[objectName^="gradFrame"] QTextEdit { + background-color: white; +} +QFrame[objectName^="gradFrame"] QComboBox QAbstractItemView { + background-color: #CCCCCC; + selection-background-color: #1464A0; +} + +QLabel#avatarLabel{ + border: 2px solid #CCCCCC; + border-radius: 4px; +} + + +/* HeaderFrame */ + +QFrame[objectName^="headerFrame"], +QFrame[objectName^="headerBFrame"], +QToolBar#headerToolBar { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #9BDBF9, stop:1 #1592CD); + border: 0px; +} +QFrame[objectName^="headerBFrame"] { + border: 1px; + border-radius: 4px; +} +QFrame[objectName^="headerFrame"] > *:!hover, +QFrame[objectName^="headerBFrame"] > *:!hover { + background: transparent; + color: white; +} + +/* TitleBarFrame */ + +QFrame#titleBarFrame { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #F0F8FD, stop:1 #E6F2FD); + border: 0px; +} +QFrame#titleBarFrame > *:!hover { + background: transparent; + color: black; +} +QFrame#titleBarFrame QComboBox, +QFrame#titleBarFrame QLineEdit, +QFrame#titleBarFrame QTextEdit { + background: white; +} + +/* HomePage */ + +HomePage QLabel#userCertLabel { + color: #0099cc; +} + + +/* Chat lobby */ + +ChatLobbyWidget QGroupBox#lobbyinfo_groupBox +{ + color: black; + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); + border-radius: 6px; + border: 1px solid #CCCCCC; + + padding: 14 6px; + +} +ChatLobbyWidget QGroupBox#lobbyinfo_groupBox > QLabel +{ + color: black;/*Needed for white font system*/ +} + +ChatLobbyWidget QGroupBox::title#lobbyinfo_groupBox +{ + padding: 4 12px; + background: #039bd5; + color: white; +} + +ChatLobbyDialog QListWidget#participantsList { + border: 1px solid #B8B6B1; + border-radius: 6px; + background: white; + color: black; +} + +CreateLobbyDialog QFrame#roomFrame { + border: 2px solid #CCCCCC; + border-radius:6px; + background: white; +} + +ChatWidget QTextEdit#chatTextEdit, +ChatWidget QTextBrowser#textBrowser { + border: 1px solid #0099cc; + border-radius: 6px; + background: white; + color: black; +} + + +/* MessagesDialog */ + +MessagesDialog QWidget#messageTreeWidget::item { + padding: 2px; +} + +MessagesDialog QWidget#messageTreeWidget::item:selected { + background-color: #cde8ff; + color: black; +} + +MessagesDialog QWidget#messageTreeWidget::item:hover { + background-color: #e5f3ff; + color: black; +} + + +/* Forums */ + +GxsForumThreadWidget QWidget#threadTreeWidget { + selection-background-color: #cde8ff; + show-decoration-selected: 1; +} + +GxsForumThreadWidget QWidget#threadTreeWidget::item { + padding: 2px; +} + +GxsForumThreadWidget QWidget#threadTreeWidget::item:selected:active , +GxsForumThreadWidget QWidget#threadTreeWidget::item:selected:!active { + background-color: #cde8ff; +} + +/* GxsCreateCommentDialog */ + +GxsCreateCommentDialog QTextEdit#commentTextEdit { + border: 2px solid #0099cc; + border-radius: 6px; + background: white; + color: black;/*Needed for white font system*/ +} + + +/* GxsCommentDialog */ + +GxsCommentDialog QComboBox#sortBox { + color: #0099cc; +} + + +/* GxsGroupDialog */ + +GxsGroupDialog QLabel#groupLogo{ + border: 2px solid #CCCCCC; + border-radius: 3px; +} + + +/* Settings */ + +PluginItem QFrame#pluginFrame { + border: 2px solid #A8B8D1; + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FCFDFE, stop: 1 #E2E8EF); + border-radius: 0px +} +PluginItem QLabel#infoLabel { + color: #054A02; +} + + +/* Feeds */ + +AttachFileItem QFrame#frame { + border: 2px solid black; + background: white; +} + +GxsChannelPostItem QLabel#newLabel{ + border: 1px solid #167BE7; + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2291E0, stop: 1 #3EB3FF); + border-radius: 3px; + color: white; +} +GxsChannelPostItem QFrame#msgFrame { + border: 2px solid #82B9F4; + border-radius: 3px; +} +GxsChannelPostItem QLabel#logoLabel { + border: 2px solid #D3D3D3; + background-color: black; +} + +SubFileItem QProgressBar#progressBar { + border: 1px solid black; + text-align: center; + color: white; + padding: 1px; + border-top-left-radius: 7px; + border-bottom-left-radius: 7px; + background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #fff, stop: 0.4999 #eee, stop: 0.5 #ddd, stop: 1 #eee); + min-width: 15px; +} +SubFileItem QProgressBar#progressBar::chunk { + background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #78d, stop: 0.4999 #46a, stop: 0.5 #45a, stop: 1 #238); + border-top-left-radius: 7px; + border-bottom-left-radius: 7px; + border: 1px solid black; + min-width: 15px; +} + + +/* Posted */ + +BoardPostDisplayWidget_compact QFrame#voteFrame, +BoardPostDisplayWidget_card QFrame#voteFrame, +PostedItem QFrame#voteFrame { + background: rgba( 20, 20, 20, 20% ); +} + +BoardPostDisplayWidget_card QToolButton#voteUpButton, +BoardPostDisplayWidget_compact QToolButton#voteUpButton { + background: #32CD32; + border: none; + border-radius: 4px; +} +BoardPostDisplayWidget_card QToolButton#voteDownButton, +BoardPostDisplayWidget_compact QToolButton#voteDownButton { + background: #CD3232; + border: none; + border-radius: 4px; +} + +BoardPostDisplayWidget_card QToolButton#voteUpButton:hover, +BoardPostDisplayWidget_compact QToolButton#voteUpButton:hover { + background: #32CD32; + border: 2px solid #808080; + border-radius: 4px; +} +BoardPostDisplayWidget_card QToolButton#voteDownButton:hover, +BoardPostDisplayWidget_compact QToolButton#voteDownButton:hover { + background: #CD3232; + border: 2px solid #808080; + border-radius: 4px; +} + +BoardPostDisplayWidget_card QToolButton#voteUpButton:disabled, +BoardPostDisplayWidget_compact QToolButton#voteUpButton:disabled, +BoardPostDisplayWidget_card QToolButton#voteDownButton:disabled, +BoardPostDisplayWidget_compact QToolButton#voteDownButton:disabled { + background: transparent; + border: none; +} + +BoardPostDisplayWidget_compact QLabel#pictureLabel { + border: 2px solid #CCCCCC; + border-radius: 3px; +} + +PostedListWidgetWithModel QComboBox#sortStrategy_CB { + color: #0099cc; +} + +PostedListWidgetWithModel QTextBrowser#infoDescription { + background: transparent; + border: none; +} + +BoardPostDisplayWidget_compact QLabel#fromBoldLabel, +BoardPostDisplayWidget_compact QLabel#fromLabel, +BoardPostDisplayWidget_compact QLabel#dateLabel, +BoardPostDisplayWidget_compact QLabel#siteBoldLabel, +BoardPostDisplayWidget_card QLabel#fromBoldLabel, +BoardPostDisplayWidget_card QLabel#fromLabel, +BoardPostDisplayWidget_card QLabel#dateLabel, +BoardPostDisplayWidget_card QLabel#siteBoldLabel { + color: #787c7e; +} + +/* GenCertDialog + Change colors here because GUI is not started yet so no user StyleSheet loads */ + +GenCertDialog QFrame#profileframe{ + border-image: url(:/images/logo/background.png) 0 0 0 0 stretch stretch; + border-width: 0px; +} + +GenCertDialog QFrame#profileframe QCheckBox, +GenCertDialog QFrame#profileframe QLabel { + background: transparent; +} + +GenCertDialog QLabel#info_Label:enabled { + color: black; + border: 1px solid #DCDC41; + border-radius: 6px; + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); +} + +GenCertDialog QGroupBox#groupBox, +GenCertDialog QGroupBox#profile_groupBox { + background: rgba(0,0,0,10%); +} +GenCertDialog QGroupBox#profile_groupBox QComboBox, +GenCertDialog QGroupBox#profile_groupBox QSpinBox, +GenCertDialog QGroupBox#profile_groupBox QLineEdit, +GenCertDialog QComboBox#genPGPuser { + border: 2px solid #0099cc; + border-radius: 6px; + background: white; + color: black; +} + +GenCertDialog QPushButton#genButton { + border-image: url(:/images/btn_blue.png) 4; + border-width: 4; + color: white; +} +GenCertDialog QPushButton#genButton:hover { + border-image: url(:/images/btn_blue_hover.png) 4; +} +GenCertDialog QPushButton#genButton:disabled { + border-image: url(:/images/btn_27.png) 4; + color: black; +} + +/* StartDialog + To get the same style for all user and not use last connected one. */ + +StartDialog QFrame#loginframe{ + border-image: url(:/images/logo/background_lessblue.png) 0 0 0 0 stretch stretch; + border-width: 0px; +} + +StartDialog QFrame#loginframe QCheckBox, +StartDialog QFrame#loginframe QLabel { + background: transparent; +} +StartDialog QGroupBox#profilGBox { + background: rgba(0,0,0,10%); + border-radius: 3px; + border-width: 0px; +} + +StartDialog QPushButton#loadButton { + background: transparent; + border-image: url(:/images/btn_blue.png) 4; + border-width: 4; + color: white; +} +StartDialog QPushButton#loadButton:hover { + background: transparent; + border-image: url(:/images/btn_blue_hover.png) 4; +} diff --git a/retroshare-gui/src/gui/qss/stylesheet/default.qss b/retroshare-gui/src/gui/qss/stylesheet/default.qss new file mode 100644 index 000000000..4b8d1645f --- /dev/null +++ b/retroshare-gui/src/gui/qss/stylesheet/default.qss @@ -0,0 +1,362 @@ +/* Default stylesheet + This file is used as default for all stylesheets and can be overloaded + Don't use font-size or font-weight, they are defined in .ui files. + Icon size are defined in .cpp files. + + For decoration, use px (pixel or dot) + For horizontal size, use em (width of M char) + For vertical size, use ex (height of x char to respect DotPerInch of your system) + See: https://doc.qt.io/qt-5/stylesheet-reference.html#length + https://doc.qt.io/qt-5/stylesheet-syntax.html + */ + +/**** Standard rules ****/ + +/* Transparent background objects = name starting by trans_*/ +QObject[objectName^="trans_"] { + background: transparent; +} +/* Specific for scrollarea contents */ +QScrollArea[objectName^="trans_"] > QWidget > QWidget { + background: transparent; +} + +/* Informatives background objects = name starting by info*/ +QObject[objectName^="info_"]:enabled {/*enabled is needed for not be overrided :https://doc.qt.io/qt-5/stylesheet-syntax.html#conflict-resolution*/ + color: black; + border: 1px solid #DCDC41; + border-radius: 6px; + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); +} +/* For label inside informative frame */ +QFrame[objectName^="info_"] > QLabel +{ + color: black; + background: transparent; +} + +/* Specifics Buttons */ +QPushButton#applyButton:enabled,/*enabled is needed for not be overrided :https://doc.qt.io/qt-5/stylesheet-syntax.html#conflict-resolution*/ +QPushButton#createButton:enabled, +QPushButton#postButton:enabled, +QToolButton#addButton:enabled, +QToolButton#followButton:enabled { + color: white; + background: #0099cc; + border-radius: 4px; + min-height: 4ex; + /*max-height: 4ex; This doesn't work on windows*/ + min-width: 4em; + padding-left: 6px; + padding-right: 6px; +} + +QPushButton#applyButton:disabled, +QPushButton#createButton:disabled, +QPushButton#postButton:disabled, +QToolButton#addButton:disabled, +QToolButton#followButton:disabled { + color: white; + background: #d40000; + border-radius: 4px; + padding-left: 6px; + padding-right: 6px; +} + +QPushButton#applyButton:hover, +QPushButton#createButton:hover, +QPushButton#postButton:hover, +QToolButton#addButton:hover, +QToolButton#followButton:hover { + color: white; + background: #03b1f3; + border-radius: 4px; + padding-left: 6px; + padding-right: 6px; +} + +QPushButton#searchButton:enabled, +QPushButton#addButton:enabled { + color: white; + background: #32CD32; + border-radius: 4px; + min-height: 4ex; + /*max-height: 4ex; This doesn't work on windows*/ + min-width: 4em; + padding: 4px; +} + +QPushButton#searchButton:hover, +QPushButton#addButton:hover { + color: white; + background: #5AD75A; + border-radius: 4px; + padding: 4px; +} + +QToolButton#subscribeToolButton:enabled { + color: white; + background: #0099cc; + border-radius: 4px; + min-height: 4ex; + /*max-height: 4ex; This doesn't work on windows*/ +} + +QToolButton#subscribeToolButton:disabled { + background: gray; + border-radius: 4px; + border: 1px solid gray; + color: lightgray; +} + +QToolButton#subscribeToolButton:hover { + background: #03b1f3; + border-radius: 4px; +} + +QToolButton#subscribeToolButton:pressed { + background: #03b1f3; + border-radius: 4px; + border: 1px solid gray; +} + +QToolButton#subscribeToolButton[popupMode="1"]{ + padding-right: 0px; +} + +QToolButton#subscribeToolButton::menu-arrow{ + image: none; +} + +QToolButton#subscribeToolButton::menu-button{ + image: none; +} + + +QLabel#newLabel:enabled { + border: 1px solid #167BE7; + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2291E0, stop: 1 #3EB3FF); + border-radius: 3px; + color: black; +} + + +/* AvatarWidget */ + +AvatarWidget{border-width: 10px;} +AvatarWidget[frameState="NORMAL"]{border-image:url(:/images/avatarstatus-bg-116.png);} +AvatarWidget[frameState="OFFLINE"]{border-image:url(:/images/avatarstatus-bg-offline-116.png);} +AvatarWidget[frameState="INACTIVE"]{border-image:url(:/images/avatarstatus-bg-idle-116.png);} +AvatarWidget[frameState="ONLINE"]{border-image:url(:/images/avatarstatus-bg-online-116.png);} +AvatarWidget[frameState="AWAY"]{border-image:url(:/images/avatarstatus-bg-away-116.png);} +AvatarWidget[frameState="BUSY"]{border-image:url(:/images/avatarstatus-bg-busy-116.png);} + + +/* ConnectFriendWizard */ + +ConnectFriendWizard { +/* QWizard cannot be resized horizontal when banner pixmap is set + qproperty-bannerPixmap: url(:/images/connect/connectFriendBanner1.png);*/ + qproperty-titleFontSize: 16; + qproperty-titleFontWeight: 500; +/* qproperty-titleColor: white; */ +} + + +/* GxsChannelFilesStatusWidget */ + +GxsChannelFilesStatusWidget QToolButton#openFolderToolButton[popupMode="0"] { + padding-right: 0px; +} + +GxsChannelFilesStatusWidget QToolButton#openFolderToolButton::menu-indicator { + image: none; +} + + +/* Forums */ + +GxsForumThreadWidget QLabel#forumName +{ + color: #0099cc; +} + + +/* Posted */ + +BoardPostDisplayWidget_compact QFrame#voteFrame, +BoardPostDisplayWidget_card QFrame#voteFrame, +PostedItem QFrame#voteFrame { + background: rgba( 20, 20, 20, 20% ); +} + +BoardPostDisplayWidget_card QToolButton#voteUpButton, +BoardPostDisplayWidget_compact QToolButton#voteUpButton { + background: rgba(50,205,50,50%); + border: none; + border-radius: 4px; +} +BoardPostDisplayWidget_card QToolButton#voteDownButton, +BoardPostDisplayWidget_compact QToolButton#voteDownButton { + background: rgba(205,50,50,50%); + border: none; + border-radius: 4px; +} + +BoardPostDisplayWidget_card QToolButton#voteUpButton:hover, +BoardPostDisplayWidget_compact QToolButton#voteUpButton:hover { + background: rgba(50,205,50,75%); + border: 2px solid #808080; + border-radius: 4px; +} +BoardPostDisplayWidget_card QToolButton#voteDownButton:hover, +BoardPostDisplayWidget_compact QToolButton#voteDownButton:hover { + background: rgba(205,50,50,75%); + border: 2px solid #808080; + border-radius: 4px; +} + +BoardPostDisplayWidget_card QToolButton#voteUpButton:disabled, +BoardPostDisplayWidget_compact QToolButton#voteUpButton:disabled, +BoardPostDisplayWidget_card QToolButton#voteDownButton:disabled, +BoardPostDisplayWidget_compact QToolButton#voteDownButton:disabled { + background: transparent; + border: none; +} + + +/**** Color definitions ****/ + +ForumsDialog, GxsForumThreadWidget +{ + qproperty-textColorRead: darkgray; + qproperty-textColorUnread: black; + qproperty-textColorUnreadChildren: darkgray; + qproperty-textColorNotSubscribed: black; + qproperty-textColorMissing: darkRed; + qproperty-textColorPinned: darkOrange; + + qproperty-backgroundColorPinned: rgb(255, 200, 180); + qproperty-backgroundColorFiltered: rgb(255, 240, 210); +} + +FriendSelectionWidget +{ + qproperty-textColorOnline: blue; +} + +GroupTreeWidget +{ + qproperty-textColorCategory: rgb(79, 79, 79); + qproperty-textColorPrivateKey: rgb(35,91,159); +} + +MessagesDialog +{ + qproperty-textColorInbox: rgb(49, 106, 197); +} + +NetworkDialog +{ + qproperty-backgroundColorSelf: yellow; + qproperty-backgroundColorOwnSign: rgb(69, 255, 69); + qproperty-backgroundColorAcceptConnection: rgb(67, 192, 67); + qproperty-backgroundColorHasSignedMe: rgb(178, 66, 178); + qproperty-backgroundColorDenied: lightGray; + qproperty-textColor: black; +} + +NewFriendList +{ + qproperty-textColorStatusOffline: black; + qproperty-textColorStatusAway: gray; + qproperty-textColorStatusBusy: darkred; + qproperty-textColorStatusOnline: darkGreen; + qproperty-textColorStatusInactive: orange; + qproperty-textColorGroup: rgb(123, 123, 123); +} + +SearchDialog +{ + qproperty-textColorLocal: red; + qproperty-textColorDownloading: green; + qproperty-textColorNoSources: rgb(0, 0, 19); + qproperty-textColorLowSources: rgb(0, 0, 38); + qproperty-textColorHighSources: rgb(0, 0, 228); +} + +RSTextBrowser, MimeTextEdit +{ + /*qproperty-textColorQuote: rgb(120, 153, 34);*/ + qproperty-textColorQuotes: ColorList(#789922 #039bd5 #800000 #800080 #008080 #b10dc9 #85144b #3d9970); +} + +/* OpModeStatus need to be at end to overload other values*/ + +OpModeStatus { + qproperty-opMode_Full_Color: #CCFFCC; + qproperty-opMode_NoTurtle_Color: #CCCCFF; + qproperty-opMode_Gaming_Color: #FFFFCC; + qproperty-opMode_Minimal_Color: #FFCCCC; +} +OpModeStatus[opMode="Full"] { + color: black; + background: #CCFFCC; +} +OpModeStatus[opMode="NoTurtle"] { + color: black; + background: #CCCCFF; +} +OpModeStatus[opMode="Gaming"] { + color: black; + background: #FFFFCC; +} +OpModeStatus[opMode="Minimal"] { + color: black; + background: #FFCCCC; +} + +/*Property Values at end to overwrite other settings*/ + +[new=false] { + /*background: rgba(248,248,248,75%);*/ +} +[new=true] { + background: rgba(220,236,253,75%); +} + +[valid=true] { + background: rgba(0,255,0,15%); +} + +[valid=false] { + background: rgba(255,0,0,15%); +} + +[WrongValue="true"] { + background-color: #FF8080; +} + +GenCertDialog QPushButton#genButton { + border-image: url(:/images/btn_blue.png) 4; + border-width: 4; + color: white; +} +GenCertDialog QPushButton#genButton:hover { + border-image: url(:/images/btn_blue_hover.png) 4; +} +GenCertDialog QPushButton#genButton:disabled { + border-image: url(:/images/btn_27.png) 4; + color: black; +} + +StartDialog QPushButton#loadButton { + background: transparent; + border-image: url(:/images/btn_blue.png) 4; + border-width: 4; + color: white; +} +StartDialog QPushButton#loadButton:hover { + background: transparent; + border-image: url(:/images/btn_blue_hover.png) 4; +} diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/Standard_Dark.qrc b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/Standard_Dark.qrc new file mode 100644 index 000000000..be5703005 --- /dev/null +++ b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/Standard_Dark.qrc @@ -0,0 +1,214 @@ + + + rc/.keep + rc/arrow_down.png + rc/arrow_down@2x.png + rc/arrow_down_disabled.png + rc/arrow_down_disabled@2x.png + rc/arrow_down_focus.png + rc/arrow_down_focus@2x.png + rc/arrow_down_pressed.png + rc/arrow_down_pressed@2x.png + rc/arrow_left.png + rc/arrow_left@2x.png + rc/arrow_left_disabled.png + rc/arrow_left_disabled@2x.png + rc/arrow_left_focus.png + rc/arrow_left_focus@2x.png + rc/arrow_left_pressed.png + rc/arrow_left_pressed@2x.png + rc/arrow_right.png + rc/arrow_right@2x.png + rc/arrow_right_disabled.png + rc/arrow_right_disabled@2x.png + rc/arrow_right_focus.png + rc/arrow_right_focus@2x.png + rc/arrow_right_pressed.png + rc/arrow_right_pressed@2x.png + rc/arrow_up.png + rc/arrow_up@2x.png + rc/arrow_up_disabled.png + rc/arrow_up_disabled@2x.png + rc/arrow_up_focus.png + rc/arrow_up_focus@2x.png + rc/arrow_up_pressed.png + rc/arrow_up_pressed@2x.png + rc/base_icon.png + rc/base_icon@2x.png + rc/base_icon_disabled.png + rc/base_icon_disabled@2x.png + rc/base_icon_focus.png + rc/base_icon_focus@2x.png + rc/base_icon_pressed.png + rc/base_icon_pressed@2x.png + rc/branch_closed.png + rc/branch_closed@2x.png + rc/branch_closed_disabled.png + rc/branch_closed_disabled@2x.png + rc/branch_closed_focus.png + rc/branch_closed_focus@2x.png + rc/branch_closed_pressed.png + rc/branch_closed_pressed@2x.png + rc/branch_end.png + rc/branch_end@2x.png + rc/branch_end_disabled.png + rc/branch_end_disabled@2x.png + rc/branch_end_focus.png + rc/branch_end_focus@2x.png + rc/branch_end_pressed.png + rc/branch_end_pressed@2x.png + rc/branch_line.png + rc/branch_line@2x.png + rc/branch_line_disabled.png + rc/branch_line_disabled@2x.png + rc/branch_line_focus.png + rc/branch_line_focus@2x.png + rc/branch_line_pressed.png + rc/branch_line_pressed@2x.png + rc/branch_more.png + rc/branch_more@2x.png + rc/branch_more_disabled.png + rc/branch_more_disabled@2x.png + rc/branch_more_focus.png + rc/branch_more_focus@2x.png + rc/branch_more_pressed.png + rc/branch_more_pressed@2x.png + rc/branch_open.png + rc/branch_open@2x.png + rc/branch_open_disabled.png + rc/branch_open_disabled@2x.png + rc/branch_open_focus.png + rc/branch_open_focus@2x.png + rc/branch_open_pressed.png + rc/branch_open_pressed@2x.png + rc/checkbox_checked.png + rc/checkbox_checked@2x.png + rc/checkbox_checked_disabled.png + rc/checkbox_checked_disabled@2x.png + rc/checkbox_checked_focus.png + rc/checkbox_checked_focus@2x.png + rc/checkbox_checked_pressed.png + rc/checkbox_checked_pressed@2x.png + rc/checkbox_indeterminate.png + rc/checkbox_indeterminate@2x.png + rc/checkbox_indeterminate_disabled.png + rc/checkbox_indeterminate_disabled@2x.png + rc/checkbox_indeterminate_focus.png + rc/checkbox_indeterminate_focus@2x.png + rc/checkbox_indeterminate_pressed.png + rc/checkbox_indeterminate_pressed@2x.png + rc/checkbox_unchecked.png + rc/checkbox_unchecked@2x.png + rc/checkbox_unchecked_disabled.png + rc/checkbox_unchecked_disabled@2x.png + rc/checkbox_unchecked_focus.png + rc/checkbox_unchecked_focus@2x.png + rc/checkbox_unchecked_pressed.png + rc/checkbox_unchecked_pressed@2x.png + rc/line_horizontal.png + rc/line_horizontal@2x.png + rc/line_horizontal_disabled.png + rc/line_horizontal_disabled@2x.png + rc/line_horizontal_focus.png + rc/line_horizontal_focus@2x.png + rc/line_horizontal_pressed.png + rc/line_horizontal_pressed@2x.png + rc/line_vertical.png + rc/line_vertical@2x.png + rc/line_vertical_disabled.png + rc/line_vertical_disabled@2x.png + rc/line_vertical_focus.png + rc/line_vertical_focus@2x.png + rc/line_vertical_pressed.png + rc/line_vertical_pressed@2x.png + rc/radio_checked.png + rc/radio_checked@2x.png + rc/radio_checked_disabled.png + rc/radio_checked_disabled@2x.png + rc/radio_checked_focus.png + rc/radio_checked_focus@2x.png + rc/radio_checked_pressed.png + rc/radio_checked_pressed@2x.png + rc/radio_unchecked.png + rc/radio_unchecked@2x.png + rc/radio_unchecked_disabled.png + rc/radio_unchecked_disabled@2x.png + rc/radio_unchecked_focus.png + rc/radio_unchecked_focus@2x.png + rc/radio_unchecked_pressed.png + rc/radio_unchecked_pressed@2x.png + rc/toolbar_move_horizontal.png + rc/toolbar_move_horizontal@2x.png + rc/toolbar_move_horizontal_disabled.png + rc/toolbar_move_horizontal_disabled@2x.png + rc/toolbar_move_horizontal_focus.png + rc/toolbar_move_horizontal_focus@2x.png + rc/toolbar_move_horizontal_pressed.png + rc/toolbar_move_horizontal_pressed@2x.png + rc/toolbar_move_vertical.png + rc/toolbar_move_vertical@2x.png + rc/toolbar_move_vertical_disabled.png + rc/toolbar_move_vertical_disabled@2x.png + rc/toolbar_move_vertical_focus.png + rc/toolbar_move_vertical_focus@2x.png + rc/toolbar_move_vertical_pressed.png + rc/toolbar_move_vertical_pressed@2x.png + rc/toolbar_separator_horizontal.png + rc/toolbar_separator_horizontal@2x.png + rc/toolbar_separator_horizontal_disabled.png + rc/toolbar_separator_horizontal_disabled@2x.png + rc/toolbar_separator_horizontal_focus.png + rc/toolbar_separator_horizontal_focus@2x.png + rc/toolbar_separator_horizontal_pressed.png + rc/toolbar_separator_horizontal_pressed@2x.png + rc/toolbar_separator_vertical.png + rc/toolbar_separator_vertical@2x.png + rc/toolbar_separator_vertical_disabled.png + rc/toolbar_separator_vertical_disabled@2x.png + rc/toolbar_separator_vertical_focus.png + rc/toolbar_separator_vertical_focus@2x.png + rc/toolbar_separator_vertical_pressed.png + rc/toolbar_separator_vertical_pressed@2x.png + rc/transparent.png + rc/transparent@2x.png + rc/transparent_disabled.png + rc/transparent_disabled@2x.png + rc/transparent_focus.png + rc/transparent_focus@2x.png + rc/transparent_pressed.png + rc/transparent_pressed@2x.png + rc/window_close.png + rc/window_close@2x.png + rc/window_close_disabled.png + rc/window_close_disabled@2x.png + rc/window_close_focus.png + rc/window_close_focus@2x.png + rc/window_close_pressed.png + rc/window_close_pressed@2x.png + rc/window_grip.png + rc/window_grip@2x.png + rc/window_grip_disabled.png + rc/window_grip_disabled@2x.png + rc/window_grip_focus.png + rc/window_grip_focus@2x.png + rc/window_grip_pressed.png + rc/window_grip_pressed@2x.png + rc/window_minimize.png + rc/window_minimize@2x.png + rc/window_minimize_disabled.png + rc/window_minimize_disabled@2x.png + rc/window_minimize_focus.png + rc/window_minimize_focus@2x.png + rc/window_minimize_pressed.png + rc/window_minimize_pressed@2x.png + rc/window_undock.png + rc/window_undock@2x.png + rc/window_undock_disabled.png + rc/window_undock_disabled@2x.png + rc/window_undock_focus.png + rc/window_undock_focus@2x.png + rc/window_undock_pressed.png + rc/window_undock_pressed@2x.png + + + diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/.keep b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/.keep new file mode 100644 index 000000000..8d1c8b69c --- /dev/null +++ b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/.keep @@ -0,0 +1 @@ + diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down.png new file mode 100644 index 000000000..5575ab5ce Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down@2x.png new file mode 100644 index 000000000..4596a5ce8 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_disabled.png new file mode 100644 index 000000000..bdf8c1abb Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_disabled@2x.png new file mode 100644 index 000000000..dc1bcb524 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_focus.png new file mode 100644 index 000000000..94fcdc359 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_focus@2x.png new file mode 100644 index 000000000..2b12f74d0 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_pressed.png new file mode 100644 index 000000000..4058c58b3 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_pressed@2x.png new file mode 100644 index 000000000..d43b0affa Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_down_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left.png new file mode 100644 index 000000000..7fbc35065 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left@2x.png new file mode 100644 index 000000000..dc649ca70 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_disabled.png new file mode 100644 index 000000000..fa3b282cc Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_disabled@2x.png new file mode 100644 index 000000000..87c928ea3 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_focus.png new file mode 100644 index 000000000..52a0d9102 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_focus@2x.png new file mode 100644 index 000000000..0ee702924 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_pressed.png new file mode 100644 index 000000000..c04ce0943 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_pressed@2x.png new file mode 100644 index 000000000..02218c80d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_left_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right.png new file mode 100644 index 000000000..fd31b4f2a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right@2x.png new file mode 100644 index 000000000..4dbc93120 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_disabled.png new file mode 100644 index 000000000..bb4cdb036 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_disabled@2x.png new file mode 100644 index 000000000..50f173096 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_focus.png new file mode 100644 index 000000000..9dd8f0f0b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_focus@2x.png new file mode 100644 index 000000000..1ac9d5c9e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_pressed.png new file mode 100644 index 000000000..8ce10fcbe Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_pressed@2x.png new file mode 100644 index 000000000..86e3b9286 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_right_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up.png new file mode 100644 index 000000000..2ea571e47 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up@2x.png new file mode 100644 index 000000000..51b1d7234 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_disabled.png new file mode 100644 index 000000000..146b65f16 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_disabled@2x.png new file mode 100644 index 000000000..cacee7f74 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_focus.png new file mode 100644 index 000000000..ab33162c7 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_focus@2x.png new file mode 100644 index 000000000..0c8ef33f4 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_pressed.png new file mode 100644 index 000000000..c3368d096 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_pressed@2x.png new file mode 100644 index 000000000..a63819665 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/arrow_up_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon.png new file mode 100644 index 000000000..1aeed5554 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon@2x.png new file mode 100644 index 000000000..f42fc6610 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_disabled.png new file mode 100644 index 000000000..1aeed5554 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_disabled@2x.png new file mode 100644 index 000000000..f42fc6610 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_focus.png new file mode 100644 index 000000000..1aeed5554 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_focus@2x.png new file mode 100644 index 000000000..f42fc6610 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_pressed.png new file mode 100644 index 000000000..1aeed5554 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_pressed@2x.png new file mode 100644 index 000000000..f42fc6610 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/base_icon_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed.png new file mode 100644 index 000000000..d484c324b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed@2x.png new file mode 100644 index 000000000..f49651b70 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_disabled.png new file mode 100644 index 000000000..aa622523c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_disabled@2x.png new file mode 100644 index 000000000..ac318f5b1 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_focus.png new file mode 100644 index 000000000..0a98eab66 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_focus@2x.png new file mode 100644 index 000000000..39fd0d0e2 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_pressed.png new file mode 100644 index 000000000..049f4bfe5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_pressed@2x.png new file mode 100644 index 000000000..f58ae2238 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_closed_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end.png new file mode 100644 index 000000000..210984565 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end@2x.png new file mode 100644 index 000000000..91f3bd02d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_disabled.png new file mode 100644 index 000000000..fe819bc14 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_disabled@2x.png new file mode 100644 index 000000000..580247709 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_focus.png new file mode 100644 index 000000000..9a978c0cc Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_focus@2x.png new file mode 100644 index 000000000..ece9b825d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_pressed.png new file mode 100644 index 000000000..1d4050997 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_pressed@2x.png new file mode 100644 index 000000000..4822745c4 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_end_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line.png new file mode 100644 index 000000000..75cc027f8 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line@2x.png new file mode 100644 index 000000000..727370558 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_disabled.png new file mode 100644 index 000000000..01c6cffa7 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_disabled@2x.png new file mode 100644 index 000000000..57789e942 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_focus.png new file mode 100644 index 000000000..599626230 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_focus@2x.png new file mode 100644 index 000000000..34e7d603f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_pressed.png new file mode 100644 index 000000000..6a54b0948 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_pressed@2x.png new file mode 100644 index 000000000..fb74fd324 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_line_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more.png new file mode 100644 index 000000000..045f963fa Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more@2x.png new file mode 100644 index 000000000..ccde09316 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_disabled.png new file mode 100644 index 000000000..8630b91c9 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_disabled@2x.png new file mode 100644 index 000000000..37d2cdbbd Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_focus.png new file mode 100644 index 000000000..38067367f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_focus@2x.png new file mode 100644 index 000000000..d80ccb8cc Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_pressed.png new file mode 100644 index 000000000..a306eb288 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_pressed@2x.png new file mode 100644 index 000000000..7044b2822 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_more_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open.png new file mode 100644 index 000000000..445ec7181 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open@2x.png new file mode 100644 index 000000000..febb31878 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_disabled.png new file mode 100644 index 000000000..3b840d767 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_disabled@2x.png new file mode 100644 index 000000000..d6c5b40ed Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_focus.png new file mode 100644 index 000000000..fecf8733e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_focus@2x.png new file mode 100644 index 000000000..296d17553 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_pressed.png new file mode 100644 index 000000000..8a7cffab5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_pressed@2x.png new file mode 100644 index 000000000..24e282c85 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/branch_open_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked.png new file mode 100644 index 000000000..aa5f56720 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked@2x.png new file mode 100644 index 000000000..60b4fb2ae Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_disabled.png new file mode 100644 index 000000000..208f3709e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_disabled@2x.png new file mode 100644 index 000000000..7c8ad0c58 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_focus.png new file mode 100644 index 000000000..a35def37f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_focus@2x.png new file mode 100644 index 000000000..925cd3620 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_pressed.png new file mode 100644 index 000000000..f95dc13eb Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_pressed@2x.png new file mode 100644 index 000000000..641c047ae Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_checked_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate.png new file mode 100644 index 000000000..02de1ad2c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate@2x.png new file mode 100644 index 000000000..8fabf6ea4 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_disabled.png new file mode 100644 index 000000000..df99affe0 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_disabled@2x.png new file mode 100644 index 000000000..3102eaa3f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_focus.png new file mode 100644 index 000000000..370454348 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_focus@2x.png new file mode 100644 index 000000000..8da0a8c98 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_pressed.png new file mode 100644 index 000000000..b971d7fae Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_pressed@2x.png new file mode 100644 index 000000000..9e37b8433 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_indeterminate_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked.png new file mode 100644 index 000000000..80bcf2b66 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked@2x.png new file mode 100644 index 000000000..df0fa4d5a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_disabled.png new file mode 100644 index 000000000..ede58c818 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_disabled@2x.png new file mode 100644 index 000000000..6721b38f5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_focus.png new file mode 100644 index 000000000..3883d2d5a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_focus@2x.png new file mode 100644 index 000000000..35c061c0d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_pressed.png new file mode 100644 index 000000000..d98639eed Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_pressed@2x.png new file mode 100644 index 000000000..88a52460d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/checkbox_unchecked_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal.png new file mode 100644 index 000000000..bc858c8d0 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal@2x.png new file mode 100644 index 000000000..7ea4f9c1c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_disabled.png new file mode 100644 index 000000000..72e073a78 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_disabled@2x.png new file mode 100644 index 000000000..09a439df9 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_focus.png new file mode 100644 index 000000000..c84512bb5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_focus@2x.png new file mode 100644 index 000000000..8dd58f609 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_pressed.png new file mode 100644 index 000000000..7ca2605bd Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_pressed@2x.png new file mode 100644 index 000000000..bd9661781 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_horizontal_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical.png new file mode 100644 index 000000000..49a910526 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical@2x.png new file mode 100644 index 000000000..cbb017ee6 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_disabled.png new file mode 100644 index 000000000..965854688 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_disabled@2x.png new file mode 100644 index 000000000..7836a9465 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_focus.png new file mode 100644 index 000000000..512ee7d23 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_focus@2x.png new file mode 100644 index 000000000..af503251d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_pressed.png new file mode 100644 index 000000000..b8dd21535 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_pressed@2x.png new file mode 100644 index 000000000..e1d43a83e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/line_vertical_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked.png new file mode 100644 index 000000000..2a1d26a4f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked@2x.png new file mode 100644 index 000000000..eb2cbb46c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_disabled.png new file mode 100644 index 000000000..f78c15360 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_disabled@2x.png new file mode 100644 index 000000000..30168e86b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_focus.png new file mode 100644 index 000000000..6d9c9801c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_focus@2x.png new file mode 100644 index 000000000..63476a075 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_pressed.png new file mode 100644 index 000000000..421ecb44a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_pressed@2x.png new file mode 100644 index 000000000..9030e1013 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_checked_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked.png new file mode 100644 index 000000000..23b06ced3 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked@2x.png new file mode 100644 index 000000000..41e790ac7 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_disabled.png new file mode 100644 index 000000000..075ca8557 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_disabled@2x.png new file mode 100644 index 000000000..61cd48ffe Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_focus.png new file mode 100644 index 000000000..d58758039 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_focus@2x.png new file mode 100644 index 000000000..0f12c860b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_pressed.png new file mode 100644 index 000000000..37c09a6d8 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_pressed@2x.png new file mode 100644 index 000000000..9e424e4b3 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/radio_unchecked_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal.png new file mode 100644 index 000000000..9d2f51f06 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal@2x.png new file mode 100644 index 000000000..c35b46532 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled.png new file mode 100644 index 000000000..013ac4578 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled@2x.png new file mode 100644 index 000000000..f713dd4d0 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_focus.png new file mode 100644 index 000000000..6d0d42588 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_focus@2x.png new file mode 100644 index 000000000..0a5ca39b1 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed.png new file mode 100644 index 000000000..e414c0c52 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed@2x.png new file mode 100644 index 000000000..e8e8af20f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical.png new file mode 100644 index 000000000..140846d75 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical@2x.png new file mode 100644 index 000000000..7edf454a3 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_disabled.png new file mode 100644 index 000000000..5cd85dd72 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_disabled@2x.png new file mode 100644 index 000000000..07d5ae1bf Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_focus.png new file mode 100644 index 000000000..9aac0365a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_focus@2x.png new file mode 100644 index 000000000..c3b1d1805 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_pressed.png new file mode 100644 index 000000000..30b3921e2 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_pressed@2x.png new file mode 100644 index 000000000..bd0120745 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_move_vertical_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal.png new file mode 100644 index 000000000..96e2689ff Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal@2x.png new file mode 100644 index 000000000..5944e44c9 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled.png new file mode 100644 index 000000000..941e14509 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled@2x.png new file mode 100644 index 000000000..e44a33be6 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus.png new file mode 100644 index 000000000..590b31471 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus@2x.png new file mode 100644 index 000000000..ca88313f6 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed.png new file mode 100644 index 000000000..38004682a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed@2x.png new file mode 100644 index 000000000..d4b88c047 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical.png new file mode 100644 index 000000000..b503c8093 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical@2x.png new file mode 100644 index 000000000..2725a7fa1 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled.png new file mode 100644 index 000000000..6aa1fbdd7 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled@2x.png new file mode 100644 index 000000000..8e54cfa8e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_focus.png new file mode 100644 index 000000000..fcdfc0f21 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_focus@2x.png new file mode 100644 index 000000000..51b083965 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed.png new file mode 100644 index 000000000..9d6f84d51 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed@2x.png new file mode 100644 index 000000000..3876a8e87 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent.png new file mode 100644 index 000000000..3a95111e5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent@2x.png new file mode 100644 index 000000000..4c4b95225 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_disabled.png new file mode 100644 index 000000000..3a95111e5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_disabled@2x.png new file mode 100644 index 000000000..4c4b95225 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_focus.png new file mode 100644 index 000000000..3a95111e5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_focus@2x.png new file mode 100644 index 000000000..4c4b95225 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_pressed.png new file mode 100644 index 000000000..3a95111e5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_pressed@2x.png new file mode 100644 index 000000000..4c4b95225 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/transparent_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close.png new file mode 100644 index 000000000..0115ca3f3 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close@2x.png new file mode 100644 index 000000000..41dcd8160 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_disabled.png new file mode 100644 index 000000000..55144fff8 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_disabled@2x.png new file mode 100644 index 000000000..766aef7c1 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_focus.png new file mode 100644 index 000000000..61df25f82 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_focus@2x.png new file mode 100644 index 000000000..2ea50b1a9 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_pressed.png new file mode 100644 index 000000000..042311def Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_pressed@2x.png new file mode 100644 index 000000000..b54d9a16d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_close_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip.png new file mode 100644 index 000000000..9ea1c438f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip@2x.png new file mode 100644 index 000000000..b31309e8b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_disabled.png new file mode 100644 index 000000000..b66e23b99 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_disabled@2x.png new file mode 100644 index 000000000..ee3d0ba88 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_focus.png new file mode 100644 index 000000000..400af158c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_focus@2x.png new file mode 100644 index 000000000..83c9ec634 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_pressed.png new file mode 100644 index 000000000..f71dd8c9a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_pressed@2x.png new file mode 100644 index 000000000..109878a35 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_grip_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize.png new file mode 100644 index 000000000..07517b943 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize@2x.png new file mode 100644 index 000000000..434bb07cd Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_disabled.png new file mode 100644 index 000000000..a1ee4aeda Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_disabled@2x.png new file mode 100644 index 000000000..8454ad832 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_focus.png new file mode 100644 index 000000000..3b56123f1 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_focus@2x.png new file mode 100644 index 000000000..a66fb71ec Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_pressed.png new file mode 100644 index 000000000..9b70c0ade Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_pressed@2x.png new file mode 100644 index 000000000..5750a8e7e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_minimize_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock.png new file mode 100644 index 000000000..9be9cdf77 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock@2x.png new file mode 100644 index 000000000..40345ab94 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_disabled.png new file mode 100644 index 000000000..ea92aee04 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_disabled@2x.png new file mode 100644 index 000000000..fb8d5483c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_focus.png new file mode 100644 index 000000000..5b0338d9b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_focus@2x.png new file mode 100644 index 000000000..9fea75b09 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_pressed.png new file mode 100644 index 000000000..4bc657b21 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_pressed@2x.png new file mode 100644 index 000000000..2ea0c2c71 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/dark/rc/window_undock_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/Standard_Light.qrc b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/Standard_Light.qrc new file mode 100644 index 000000000..f6af4ae87 --- /dev/null +++ b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/Standard_Light.qrc @@ -0,0 +1,214 @@ + + + rc/.keep + rc/arrow_down.png + rc/arrow_down@2x.png + rc/arrow_down_disabled.png + rc/arrow_down_disabled@2x.png + rc/arrow_down_focus.png + rc/arrow_down_focus@2x.png + rc/arrow_down_pressed.png + rc/arrow_down_pressed@2x.png + rc/arrow_left.png + rc/arrow_left@2x.png + rc/arrow_left_disabled.png + rc/arrow_left_disabled@2x.png + rc/arrow_left_focus.png + rc/arrow_left_focus@2x.png + rc/arrow_left_pressed.png + rc/arrow_left_pressed@2x.png + rc/arrow_right.png + rc/arrow_right@2x.png + rc/arrow_right_disabled.png + rc/arrow_right_disabled@2x.png + rc/arrow_right_focus.png + rc/arrow_right_focus@2x.png + rc/arrow_right_pressed.png + rc/arrow_right_pressed@2x.png + rc/arrow_up.png + rc/arrow_up@2x.png + rc/arrow_up_disabled.png + rc/arrow_up_disabled@2x.png + rc/arrow_up_focus.png + rc/arrow_up_focus@2x.png + rc/arrow_up_pressed.png + rc/arrow_up_pressed@2x.png + rc/base_icon.png + rc/base_icon@2x.png + rc/base_icon_disabled.png + rc/base_icon_disabled@2x.png + rc/base_icon_focus.png + rc/base_icon_focus@2x.png + rc/base_icon_pressed.png + rc/base_icon_pressed@2x.png + rc/branch_closed.png + rc/branch_closed@2x.png + rc/branch_closed_disabled.png + rc/branch_closed_disabled@2x.png + rc/branch_closed_focus.png + rc/branch_closed_focus@2x.png + rc/branch_closed_pressed.png + rc/branch_closed_pressed@2x.png + rc/branch_end.png + rc/branch_end@2x.png + rc/branch_end_disabled.png + rc/branch_end_disabled@2x.png + rc/branch_end_focus.png + rc/branch_end_focus@2x.png + rc/branch_end_pressed.png + rc/branch_end_pressed@2x.png + rc/branch_line.png + rc/branch_line@2x.png + rc/branch_line_disabled.png + rc/branch_line_disabled@2x.png + rc/branch_line_focus.png + rc/branch_line_focus@2x.png + rc/branch_line_pressed.png + rc/branch_line_pressed@2x.png + rc/branch_more.png + rc/branch_more@2x.png + rc/branch_more_disabled.png + rc/branch_more_disabled@2x.png + rc/branch_more_focus.png + rc/branch_more_focus@2x.png + rc/branch_more_pressed.png + rc/branch_more_pressed@2x.png + rc/branch_open.png + rc/branch_open@2x.png + rc/branch_open_disabled.png + rc/branch_open_disabled@2x.png + rc/branch_open_focus.png + rc/branch_open_focus@2x.png + rc/branch_open_pressed.png + rc/branch_open_pressed@2x.png + rc/checkbox_checked.png + rc/checkbox_checked@2x.png + rc/checkbox_checked_disabled.png + rc/checkbox_checked_disabled@2x.png + rc/checkbox_checked_focus.png + rc/checkbox_checked_focus@2x.png + rc/checkbox_checked_pressed.png + rc/checkbox_checked_pressed@2x.png + rc/checkbox_indeterminate.png + rc/checkbox_indeterminate@2x.png + rc/checkbox_indeterminate_disabled.png + rc/checkbox_indeterminate_disabled@2x.png + rc/checkbox_indeterminate_focus.png + rc/checkbox_indeterminate_focus@2x.png + rc/checkbox_indeterminate_pressed.png + rc/checkbox_indeterminate_pressed@2x.png + rc/checkbox_unchecked.png + rc/checkbox_unchecked@2x.png + rc/checkbox_unchecked_disabled.png + rc/checkbox_unchecked_disabled@2x.png + rc/checkbox_unchecked_focus.png + rc/checkbox_unchecked_focus@2x.png + rc/checkbox_unchecked_pressed.png + rc/checkbox_unchecked_pressed@2x.png + rc/line_horizontal.png + rc/line_horizontal@2x.png + rc/line_horizontal_disabled.png + rc/line_horizontal_disabled@2x.png + rc/line_horizontal_focus.png + rc/line_horizontal_focus@2x.png + rc/line_horizontal_pressed.png + rc/line_horizontal_pressed@2x.png + rc/line_vertical.png + rc/line_vertical@2x.png + rc/line_vertical_disabled.png + rc/line_vertical_disabled@2x.png + rc/line_vertical_focus.png + rc/line_vertical_focus@2x.png + rc/line_vertical_pressed.png + rc/line_vertical_pressed@2x.png + rc/radio_checked.png + rc/radio_checked@2x.png + rc/radio_checked_disabled.png + rc/radio_checked_disabled@2x.png + rc/radio_checked_focus.png + rc/radio_checked_focus@2x.png + rc/radio_checked_pressed.png + rc/radio_checked_pressed@2x.png + rc/radio_unchecked.png + rc/radio_unchecked@2x.png + rc/radio_unchecked_disabled.png + rc/radio_unchecked_disabled@2x.png + rc/radio_unchecked_focus.png + rc/radio_unchecked_focus@2x.png + rc/radio_unchecked_pressed.png + rc/radio_unchecked_pressed@2x.png + rc/toolbar_move_horizontal.png + rc/toolbar_move_horizontal@2x.png + rc/toolbar_move_horizontal_disabled.png + rc/toolbar_move_horizontal_disabled@2x.png + rc/toolbar_move_horizontal_focus.png + rc/toolbar_move_horizontal_focus@2x.png + rc/toolbar_move_horizontal_pressed.png + rc/toolbar_move_horizontal_pressed@2x.png + rc/toolbar_move_vertical.png + rc/toolbar_move_vertical@2x.png + rc/toolbar_move_vertical_disabled.png + rc/toolbar_move_vertical_disabled@2x.png + rc/toolbar_move_vertical_focus.png + rc/toolbar_move_vertical_focus@2x.png + rc/toolbar_move_vertical_pressed.png + rc/toolbar_move_vertical_pressed@2x.png + rc/toolbar_separator_horizontal.png + rc/toolbar_separator_horizontal@2x.png + rc/toolbar_separator_horizontal_disabled.png + rc/toolbar_separator_horizontal_disabled@2x.png + rc/toolbar_separator_horizontal_focus.png + rc/toolbar_separator_horizontal_focus@2x.png + rc/toolbar_separator_horizontal_pressed.png + rc/toolbar_separator_horizontal_pressed@2x.png + rc/toolbar_separator_vertical.png + rc/toolbar_separator_vertical@2x.png + rc/toolbar_separator_vertical_disabled.png + rc/toolbar_separator_vertical_disabled@2x.png + rc/toolbar_separator_vertical_focus.png + rc/toolbar_separator_vertical_focus@2x.png + rc/toolbar_separator_vertical_pressed.png + rc/toolbar_separator_vertical_pressed@2x.png + rc/transparent.png + rc/transparent@2x.png + rc/transparent_disabled.png + rc/transparent_disabled@2x.png + rc/transparent_focus.png + rc/transparent_focus@2x.png + rc/transparent_pressed.png + rc/transparent_pressed@2x.png + rc/window_close.png + rc/window_close@2x.png + rc/window_close_disabled.png + rc/window_close_disabled@2x.png + rc/window_close_focus.png + rc/window_close_focus@2x.png + rc/window_close_pressed.png + rc/window_close_pressed@2x.png + rc/window_grip.png + rc/window_grip@2x.png + rc/window_grip_disabled.png + rc/window_grip_disabled@2x.png + rc/window_grip_focus.png + rc/window_grip_focus@2x.png + rc/window_grip_pressed.png + rc/window_grip_pressed@2x.png + rc/window_minimize.png + rc/window_minimize@2x.png + rc/window_minimize_disabled.png + rc/window_minimize_disabled@2x.png + rc/window_minimize_focus.png + rc/window_minimize_focus@2x.png + rc/window_minimize_pressed.png + rc/window_minimize_pressed@2x.png + rc/window_undock.png + rc/window_undock@2x.png + rc/window_undock_disabled.png + rc/window_undock_disabled@2x.png + rc/window_undock_focus.png + rc/window_undock_focus@2x.png + rc/window_undock_pressed.png + rc/window_undock_pressed@2x.png + + + diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/.keep b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/.keep new file mode 100644 index 000000000..8d1c8b69c --- /dev/null +++ b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/.keep @@ -0,0 +1 @@ + diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down.png new file mode 100644 index 000000000..f07aa76f0 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down@2x.png new file mode 100644 index 000000000..b16b9df17 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_disabled.png new file mode 100644 index 000000000..d94e55b95 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_disabled@2x.png new file mode 100644 index 000000000..a1bc87416 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_focus.png new file mode 100644 index 000000000..fcd681205 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_focus@2x.png new file mode 100644 index 000000000..a0463e5e9 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_pressed.png new file mode 100644 index 000000000..bbe79a97e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_pressed@2x.png new file mode 100644 index 000000000..28ae890ae Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_down_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left.png new file mode 100644 index 000000000..070870107 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left@2x.png new file mode 100644 index 000000000..c067c7ac1 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_disabled.png new file mode 100644 index 000000000..76ae59b10 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_disabled@2x.png new file mode 100644 index 000000000..815f33c07 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_focus.png new file mode 100644 index 000000000..c0856669a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_focus@2x.png new file mode 100644 index 000000000..48af7238c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_pressed.png new file mode 100644 index 000000000..f47340e3c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_pressed@2x.png new file mode 100644 index 000000000..51b5b7a07 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_left_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right.png new file mode 100644 index 000000000..45f7857e5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right@2x.png new file mode 100644 index 000000000..bafdf16c9 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_disabled.png new file mode 100644 index 000000000..82d1dd284 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_disabled@2x.png new file mode 100644 index 000000000..8d95d8323 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_focus.png new file mode 100644 index 000000000..3b3c1b6f8 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_focus@2x.png new file mode 100644 index 000000000..8a3870bdd Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_pressed.png new file mode 100644 index 000000000..b4176d59d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_pressed@2x.png new file mode 100644 index 000000000..24dfe4e19 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_right_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up.png new file mode 100644 index 000000000..7e185babf Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up@2x.png new file mode 100644 index 000000000..6925245e3 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_disabled.png new file mode 100644 index 000000000..54394e210 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_disabled@2x.png new file mode 100644 index 000000000..0f582d323 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_focus.png new file mode 100644 index 000000000..4bc54733f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_focus@2x.png new file mode 100644 index 000000000..bdf7f6b2d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_pressed.png new file mode 100644 index 000000000..04bc9e4ec Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_pressed@2x.png new file mode 100644 index 000000000..cd6231f26 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/arrow_up_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon.png new file mode 100644 index 000000000..1aeed5554 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon@2x.png new file mode 100644 index 000000000..f42fc6610 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_disabled.png new file mode 100644 index 000000000..1aeed5554 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_disabled@2x.png new file mode 100644 index 000000000..f42fc6610 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_focus.png new file mode 100644 index 000000000..1aeed5554 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_focus@2x.png new file mode 100644 index 000000000..f42fc6610 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_pressed.png new file mode 100644 index 000000000..1aeed5554 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_pressed@2x.png new file mode 100644 index 000000000..f42fc6610 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/base_icon_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed.png new file mode 100644 index 000000000..f41c767e6 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed@2x.png new file mode 100644 index 000000000..24bb5fba2 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_disabled.png new file mode 100644 index 000000000..2a6b24dea Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_disabled@2x.png new file mode 100644 index 000000000..91d7d6518 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_focus.png new file mode 100644 index 000000000..2058d895f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_focus@2x.png new file mode 100644 index 000000000..18d665af9 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_pressed.png new file mode 100644 index 000000000..35f982fab Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_pressed@2x.png new file mode 100644 index 000000000..2008d6256 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_closed_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end.png new file mode 100644 index 000000000..6b0bfe03d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end@2x.png new file mode 100644 index 000000000..9ce5439cb Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_disabled.png new file mode 100644 index 000000000..dfa9baa8d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_disabled@2x.png new file mode 100644 index 000000000..8ef19e30d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_focus.png new file mode 100644 index 000000000..85f17bad7 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_focus@2x.png new file mode 100644 index 000000000..d756b2919 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_pressed.png new file mode 100644 index 000000000..7a868658e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_pressed@2x.png new file mode 100644 index 000000000..561e6ebf6 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_end_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line.png new file mode 100644 index 000000000..e55608ddc Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line@2x.png new file mode 100644 index 000000000..59967fd60 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_disabled.png new file mode 100644 index 000000000..d758b7b6c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_disabled@2x.png new file mode 100644 index 000000000..a35c3a66d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_focus.png new file mode 100644 index 000000000..800cc587c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_focus@2x.png new file mode 100644 index 000000000..7d21d64a9 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_pressed.png new file mode 100644 index 000000000..638046579 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_pressed@2x.png new file mode 100644 index 000000000..7ca30cd61 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_line_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more.png new file mode 100644 index 000000000..140129295 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more@2x.png new file mode 100644 index 000000000..5a3b1e98f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_disabled.png new file mode 100644 index 000000000..d801611bb Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_disabled@2x.png new file mode 100644 index 000000000..2505e2a7c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_focus.png new file mode 100644 index 000000000..be5b2cbfa Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_focus@2x.png new file mode 100644 index 000000000..ca0f99e0e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_pressed.png new file mode 100644 index 000000000..6e744b78e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_pressed@2x.png new file mode 100644 index 000000000..fdaf01f03 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_more_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open.png new file mode 100644 index 000000000..e43b940cb Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open@2x.png new file mode 100644 index 000000000..691e38c18 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_disabled.png new file mode 100644 index 000000000..9e445449e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_disabled@2x.png new file mode 100644 index 000000000..246bdbbed Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_focus.png new file mode 100644 index 000000000..a4b332e3e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_focus@2x.png new file mode 100644 index 000000000..27c8dcacf Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_pressed.png new file mode 100644 index 000000000..205f9414e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_pressed@2x.png new file mode 100644 index 000000000..d09878a61 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/branch_open_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked.png new file mode 100644 index 000000000..f63f2b38f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked@2x.png new file mode 100644 index 000000000..7617ed7dc Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_disabled.png new file mode 100644 index 000000000..2eab1ba0c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_disabled@2x.png new file mode 100644 index 000000000..518d55d5e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_focus.png new file mode 100644 index 000000000..fccb71edc Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_focus@2x.png new file mode 100644 index 000000000..e12217d0a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_pressed.png new file mode 100644 index 000000000..d93ca9903 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_pressed@2x.png new file mode 100644 index 000000000..7ee1d3514 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_checked_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate.png new file mode 100644 index 000000000..8f4d0f161 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate@2x.png new file mode 100644 index 000000000..3d106399b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_disabled.png new file mode 100644 index 000000000..0a093c819 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_disabled@2x.png new file mode 100644 index 000000000..06db251f9 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_focus.png new file mode 100644 index 000000000..33fd572bd Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_focus@2x.png new file mode 100644 index 000000000..691ddf1da Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_pressed.png new file mode 100644 index 000000000..2aff90928 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_pressed@2x.png new file mode 100644 index 000000000..fb4e03861 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_indeterminate_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked.png new file mode 100644 index 000000000..3c0608784 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked@2x.png new file mode 100644 index 000000000..fa0648786 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_disabled.png new file mode 100644 index 000000000..bba927e50 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_disabled@2x.png new file mode 100644 index 000000000..592d5949a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_focus.png new file mode 100644 index 000000000..7e460184a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_focus@2x.png new file mode 100644 index 000000000..3f96917b5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_pressed.png new file mode 100644 index 000000000..5fd771d1a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_pressed@2x.png new file mode 100644 index 000000000..57f25fbae Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/checkbox_unchecked_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal.png new file mode 100644 index 000000000..22a0b1e2b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal@2x.png new file mode 100644 index 000000000..8bd474944 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_disabled.png new file mode 100644 index 000000000..3dc9c69e0 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_disabled@2x.png new file mode 100644 index 000000000..a2d3664af Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_focus.png new file mode 100644 index 000000000..136faa84c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_focus@2x.png new file mode 100644 index 000000000..398d22432 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_pressed.png new file mode 100644 index 000000000..e2027b14e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_pressed@2x.png new file mode 100644 index 000000000..24b83299b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_horizontal_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical.png new file mode 100644 index 000000000..0a4c5f364 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical@2x.png new file mode 100644 index 000000000..e67ccf52b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_disabled.png new file mode 100644 index 000000000..9700752d9 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_disabled@2x.png new file mode 100644 index 000000000..0f57c568f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_focus.png new file mode 100644 index 000000000..15ef20825 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_focus@2x.png new file mode 100644 index 000000000..a35e97ed0 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_pressed.png new file mode 100644 index 000000000..7399cd38e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_pressed@2x.png new file mode 100644 index 000000000..e018b9af8 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/line_vertical_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked.png new file mode 100644 index 000000000..878b6c53c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked@2x.png new file mode 100644 index 000000000..ed20cd4cf Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_disabled.png new file mode 100644 index 000000000..1aa26ee00 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_disabled@2x.png new file mode 100644 index 000000000..72b69d59b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_focus.png new file mode 100644 index 000000000..90a54c6e1 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_focus@2x.png new file mode 100644 index 000000000..81771885f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_pressed.png new file mode 100644 index 000000000..10170e374 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_pressed@2x.png new file mode 100644 index 000000000..378608298 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_checked_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked.png new file mode 100644 index 000000000..639a55480 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked@2x.png new file mode 100644 index 000000000..a2f23fd6f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_disabled.png new file mode 100644 index 000000000..6f7424ca7 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_disabled@2x.png new file mode 100644 index 000000000..bf9330f24 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_focus.png new file mode 100644 index 000000000..2316d7872 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_focus@2x.png new file mode 100644 index 000000000..9695890ba Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_pressed.png new file mode 100644 index 000000000..2f2a7ba21 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_pressed@2x.png new file mode 100644 index 000000000..22a7e7139 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/radio_unchecked_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal.png new file mode 100644 index 000000000..a1109caf8 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal@2x.png new file mode 100644 index 000000000..69bb6347d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_disabled.png new file mode 100644 index 000000000..e11055a6a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_disabled@2x.png new file mode 100644 index 000000000..9085b627e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_focus.png new file mode 100644 index 000000000..3c0be5a0e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_focus@2x.png new file mode 100644 index 000000000..f01973d05 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_pressed.png new file mode 100644 index 000000000..94c0f5b6d Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_pressed@2x.png new file mode 100644 index 000000000..612ea774f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_horizontal_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical.png new file mode 100644 index 000000000..b16c48c40 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical@2x.png new file mode 100644 index 000000000..853962cd6 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_disabled.png new file mode 100644 index 000000000..9b3caec07 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_disabled@2x.png new file mode 100644 index 000000000..bdda6796a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_focus.png new file mode 100644 index 000000000..6a432a4ba Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_focus@2x.png new file mode 100644 index 000000000..817a8da55 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_pressed.png new file mode 100644 index 000000000..50228af7b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_pressed@2x.png new file mode 100644 index 000000000..1946791ad Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_move_vertical_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal.png new file mode 100644 index 000000000..f6661b4b1 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal@2x.png new file mode 100644 index 000000000..77cadc217 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_disabled.png new file mode 100644 index 000000000..a65e13e46 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_disabled@2x.png new file mode 100644 index 000000000..77b9abcaf Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_focus.png new file mode 100644 index 000000000..843633ffa Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_focus@2x.png new file mode 100644 index 000000000..21d4011fc Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_pressed.png new file mode 100644 index 000000000..edf05752f Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_pressed@2x.png new file mode 100644 index 000000000..977ec62a9 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_horizontal_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical.png new file mode 100644 index 000000000..2776d87b5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical@2x.png new file mode 100644 index 000000000..ab9e773a8 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_disabled.png new file mode 100644 index 000000000..cb443940b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_disabled@2x.png new file mode 100644 index 000000000..f4e241ab2 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_focus.png new file mode 100644 index 000000000..4a45d55c0 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_focus@2x.png new file mode 100644 index 000000000..c58d8d120 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_pressed.png new file mode 100644 index 000000000..408fa169a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_pressed@2x.png new file mode 100644 index 000000000..92feb3652 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/toolbar_separator_vertical_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent.png new file mode 100644 index 000000000..3a95111e5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent@2x.png new file mode 100644 index 000000000..4c4b95225 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_disabled.png new file mode 100644 index 000000000..3a95111e5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_disabled@2x.png new file mode 100644 index 000000000..4c4b95225 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_focus.png new file mode 100644 index 000000000..3a95111e5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_focus@2x.png new file mode 100644 index 000000000..4c4b95225 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_pressed.png new file mode 100644 index 000000000..3a95111e5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_pressed@2x.png new file mode 100644 index 000000000..4c4b95225 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/transparent_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close.png new file mode 100644 index 000000000..607170bae Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close@2x.png new file mode 100644 index 000000000..607f894a6 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_disabled.png new file mode 100644 index 000000000..449deec63 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_disabled@2x.png new file mode 100644 index 000000000..eda9fb4ce Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_focus.png new file mode 100644 index 000000000..1cd49c73e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_focus@2x.png new file mode 100644 index 000000000..a13da2129 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_pressed.png new file mode 100644 index 000000000..c5e2a9143 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_pressed@2x.png new file mode 100644 index 000000000..278288ed1 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_close_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip.png new file mode 100644 index 000000000..c03b1dce3 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip@2x.png new file mode 100644 index 000000000..7074bd6d2 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_disabled.png new file mode 100644 index 000000000..3c479884b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_disabled@2x.png new file mode 100644 index 000000000..eb4a063a7 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_focus.png new file mode 100644 index 000000000..46c77d37a Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_focus@2x.png new file mode 100644 index 000000000..f487c6adb Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_pressed.png new file mode 100644 index 000000000..a4d075905 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_pressed@2x.png new file mode 100644 index 000000000..54dc3d8a8 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_grip_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize.png new file mode 100644 index 000000000..9e1a7f12c Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize@2x.png new file mode 100644 index 000000000..dcd2570cc Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_disabled.png new file mode 100644 index 000000000..9fd0ef169 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_disabled@2x.png new file mode 100644 index 000000000..251cefcce Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_focus.png new file mode 100644 index 000000000..4d748783b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_focus@2x.png new file mode 100644 index 000000000..97901fed5 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_pressed.png new file mode 100644 index 000000000..78de6557b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_pressed@2x.png new file mode 100644 index 000000000..6b961459b Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_minimize_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock.png new file mode 100644 index 000000000..4da192f33 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock@2x.png new file mode 100644 index 000000000..5cfe75ccc Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_disabled.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_disabled.png new file mode 100644 index 000000000..b0db9c7a7 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_disabled.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_disabled@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_disabled@2x.png new file mode 100644 index 000000000..9468c9f32 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_disabled@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_focus.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_focus.png new file mode 100644 index 000000000..85fb0468e Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_focus.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_focus@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_focus@2x.png new file mode 100644 index 000000000..e13b2f075 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_focus@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_pressed.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_pressed.png new file mode 100644 index 000000000..d368cc9ad Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_pressed.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_pressed@2x.png b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_pressed@2x.png new file mode 100644 index 000000000..b30f0dbb6 Binary files /dev/null and b/retroshare-gui/src/gui/qss/stylesheet/qdarkstyle/light/rc/window_undock_pressed@2x.png differ diff --git a/retroshare-gui/src/gui/qss/stylesheet/qss.default b/retroshare-gui/src/gui/qss/stylesheet/qss.default deleted file mode 100644 index 7e1ecf8b2..000000000 --- a/retroshare-gui/src/gui/qss/stylesheet/qss.default +++ /dev/null @@ -1,275 +0,0 @@ -/* Default stylesheet - This file is used as default for all stylesheets and can be overloaded */ - -/* AvatarWidget */ - -AvatarWidget{border-width: 10px;} -AvatarWidget[frameState="NORMAL"]{border-image:url(:/images/avatarstatus-bg-116.png);} -AvatarWidget[frameState="OFFLINE"]{border-image:url(:/images/avatarstatus-bg-offline-116.png);} -AvatarWidget[frameState="INACTIVE"]{border-image:url(:/images/avatarstatus-bg-idle-116.png);} -AvatarWidget[frameState="ONLINE"]{border-image:url(:/images/avatarstatus-bg-online-116.png);} -AvatarWidget[frameState="AWAY"]{border-image:url(:/images/avatarstatus-bg-away-116.png);} -AvatarWidget[frameState="BUSY"]{border-image:url(:/images/avatarstatus-bg-busy-116.png);} - -/* Font */ - -QLabel#titleBarLabel -{ - font-weight: bold; - qproperty-fontSizeFactor: 115; -} - -QLabel#toasterLabel -{ - font-weight: bold; -} - -ChatWidget QLabel#titleLabel, ChatWidget QLabel#statusLabel -{ - qproperty-fontSizeFactor: 125; -} - -ChatWidget QFrame#pluginTitleFrame, QFrame#pluginTopFrame -{ - background: transparent; -} - -FriendsDialog QLabel#nicknameLabel -{ - qproperty-fontSizeFactor: 200; -} - -ChatMsgItem QLabel#peerNameLabel -{ - qproperty-fontSizeFactor: 175; -} - -PeerItem QLabel#peerNameLabel -{ - qproperty-fontSizeFactor: 175; -} - -SecurityItem QLabel#peerNameLabel, SecurityItem QLabel#requestLabel -{ - qproperty-fontSizeFactor: 175; -} - -SecurityIpItem QLabel#titleLabel -{ - qproperty-fontSizeFactor: 175; -} - -PostedItem QLabel#titleLabel -{ - qproperty-fontSizeFactor: 120; -} - -PostedItem QLabel#scoreLabel -{ - qproperty-fontSizeFactor: 140; -} - -GxsChannelPostItem QLabel#titleLabel -{ - qproperty-fontSizeFactor: 125; -} - -PluginItem QLabel#subjectLabel -{ - qproperty-fontSizeFactor: 125; -} - -RSettingsWin QLabel#pageName -{ - qproperty-fontSizeFactor: 125; -} - -ConfCertDialog QLabel#servicePermissionsLabel -{ - qproperty-fontSizeFactor: 125; -} - -GxsChannelPostsWidgetWithModel QLabel#channelName_LB -{ - qproperty-fontSizeFactor: 250; -} - -PostedListWidgetWithModel QLabel#namelabel -{ - qproperty-fontSizeFactor: 250; -} - -CreateLobbyDialog QLabel#lobbyInfoLabel -{ - qproperty-fontSizeFactor: 150; -} - -HeaderFrame QLabel#headerLabel -{ - qproperty-fontSizeFactor: 225; -} - -ConnectFrientWizard QLabel#fr_label -{ - qproperty-fontSizeFactor: 125; -} - -ConnectFrientWizard QLabel#requestinfolabel -{ - qproperty-fontSizeFactor: 125; -} - -ShareManager QLabel#labelInstructions -{ - qproperty-fontSizeFactor: 125; -} - -CryptoPage QLabel#publicLabel, CryptoPage QLabel#otherLabel -{ - qproperty-fontSizeFactor: 125; -} - -ProfileWidget QLabel#publicLabel, ProfileWidget QLabel#otherLabel, ProfileWidget QLabel#myLabel -{ - qproperty-fontSizeFactor: 125; -} - -PostedCreatePostDialog QLabel#info_label -{ - qproperty-fontSizeFactor: 125; -} - -/* Color definitions */ - -ForumsDialog, GxsForumThreadWidget -{ - qproperty-textColorRead: darkgray; - qproperty-textColorUnread: black; - qproperty-textColorUnreadChildren: darkgray; - qproperty-textColorNotSubscribed: black; - qproperty-textColorMissing: darkRed; - qproperty-textColorPinned: darkOrange; - - qproperty-backgroundColorPinned: rgb(255, 200, 180); - qproperty-backgroundColorFiltered: rgb(255, 240, 210); -} - -GxsForumThreadWidget StyledElidedLabel#forumName -{ - padding: 2px; - font: bold; - font-size: 15pt; -} - -GroupTreeWidget -{ - qproperty-textColorCategory: rgb(79, 79, 79); - qproperty-textColorPrivateKey: rgb(35,91,159); -} - -FriendSelectionWidget -{ - qproperty-textColorOnline: blue; -} - -MessagesDialog -{ - qproperty-textColorInbox: rgb(49, 106, 197); -} - -NewFriendList -{ - qproperty-textColorStatusOffline: black; - qproperty-textColorStatusAway: gray; - qproperty-textColorStatusBusy: gray; - qproperty-textColorStatusOnline: darkGreen; - qproperty-textColorStatusInactive: gray; - qproperty-textColorGroup: rgb(123, 123, 123); -} - -SearchDialog -{ - qproperty-textColorLocal: red; - qproperty-textColorDownloading: green; - qproperty-textColorNoSources: rgb(0, 0, 19); - qproperty-textColorLowSources: rgb(0, 0, 38); - qproperty-textColorHighSources: rgb(0, 0, 228); -} - -NetworkDialog -{ - qproperty-backgroundColorSelf: yellow; - qproperty-backgroundColorOwnSign: rgb(69, 255, 69); - qproperty-backgroundColorAcceptConnection: rgb(67, 192, 67); - qproperty-backgroundColorHasSignedMe: rgb(178, 66, 178); - qproperty-backgroundColorDenied: lightGray; -} - -RSTextBrowser, MimeTextEdit -{ - /*qproperty-textColorQuote: rgb(120, 153, 34);*/ - qproperty-textColorQuotes: ColorList(#789922 #039bd5 #800000 #800080 #008080 #b10dc9 #85144b #3d9970); -} - -QLabel#headerTextLabel_Person -{ - qproperty-fontSizeFactor: 225; -} - -QLabel#headerTextLabel_Circles -{ - qproperty-fontSizeFactor: 225; -} - -IdEditDialog QLabel#info_label -{ - qproperty-fontSizeFactor: 125; -} - -GenCertDialog QLabel#header_label -{ - qproperty-fontSizeFactor: 120; -} - -GenCertDialog QLabel#genprofileinfo_label -{ - qproperty-fontSizeFactor: 120; -} - -GenCertDialog QLabel#entropy_label -{ - qproperty-fontSizeFactor: 115; -} - -/* OpModeStatus need to be at end to overload other values*/ -OpModeStatus { - qproperty-opMode_Full_Color: #CCFFCC; - qproperty-opMode_NoTurtle_Color: #CCCCFF; - qproperty-opMode_Gaming_Color: #FFFFCC; - qproperty-opMode_Minimal_Color: #FFCCCC; -} -OpModeStatus[opMode="Full"] { - background: #CCFFCC; -} -OpModeStatus[opMode="NoTurtle"] { - background: #CCCCFF; -} -OpModeStatus[opMode="Gaming"] { - background: #FFFFCC; -} -OpModeStatus[opMode="Minimal"] { - background: #FFCCCC; -} - -/*Property Values at end to overwrite other settings*/ - -[new=false] { - background: #F8F8F8; -} -[new=true] { - background: #DCECFD; -} - -[WrongValue="true"] { - background-color: #FF8080; -} diff --git a/retroshare-gui/src/gui/settings/AppearancePage.cpp b/retroshare-gui/src/gui/settings/AppearancePage.cpp index 407d5c061..2aecd6024 100755 --- a/retroshare-gui/src/gui/settings/AppearancePage.cpp +++ b/retroshare-gui/src/gui/settings/AppearancePage.cpp @@ -18,20 +18,13 @@ * * *******************************************************************************/ -#include -#include -#include -#include -#include -#include - -#include "lang/languagesupport.h" -#include #include "AppearancePage.h" -#include "rsharesettings.h" -#include "util/misc.h" + +#include "rshare.h" #include "gui/MainWindow.h" #include "gui/notifyqt.h" +#include "gui/common/FilesDefs.h" +#include "gui/settings/rsharesettings.h" #include "gui/statusbar/peerstatus.h" #include "gui/statusbar/natstatus.h" #include "gui/statusbar/dhtstatus.h" @@ -42,7 +35,18 @@ #include "gui/statusbar/SoundStatus.h" #include "gui/statusbar/ToasterDisable.h" #include "gui/statusbar/SysTrayStatus.h" -#include "gui/common/FilesDefs.h" +#include "lang/languagesupport.h" +#include "util/misc.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include /** Constructor */ AppearancePage::AppearancePage(QWidget * parent, Qt::WindowFlags flags) @@ -51,8 +55,6 @@ AppearancePage::AppearancePage(QWidget * parent, Qt::WindowFlags flags) /* Invoke the Qt Designer generated object setup routine */ ui.setupUi(this); - connect(ui.cmboStyleSheet, SIGNAL(activated(int)), this, SLOT(loadStyleSheet(int))); - connect(ui.grpStatus, SIGNAL(toggled(bool)), this /* pMainWindow->statusBar(), */, SLOT(switch_status_grpStatus(bool))); connect(ui.checkBoxStatusCompactMode, SIGNAL(toggled(bool)), this /* pMainWindow, */, SLOT(switch_status_compactMode(bool))); connect(ui.checkBoxDisableSysTrayToolTip, SIGNAL(toggled(bool)), this /* pMainWindow, */, SLOT(switch_status_showToolTip(bool))); @@ -70,17 +72,19 @@ AppearancePage::AppearancePage(QWidget * parent, Qt::WindowFlags flags) /* Populate combo boxes */ foreach (QString code, LanguageSupport::languageCodes()) { - ui.cmboLanguage->addItem(FilesDefs::getIconFromQtResourcePath(":/images/flags/" + code + ".png"), LanguageSupport::languageName(code), code); - } - foreach (QString style, QStyleFactory::keys()) { - ui.cmboStyle->addItem(style, style.toLower()); + ui.cmboLanguage->addItem(FilesDefs::getIconFromQtResourcePath(":/images/flags/" + code + ".png"), LanguageSupport::languageName(code), code); } - // add empty entry representing "no style sheet" - ui.cmboStyleSheet->addItem("", ""); + // Note: apparently, on some linux systems (e.g. Debian 11), the gtk2 style makes Qt libs crash when the environment variable is not set. + // So we first check that it's here before start. + + foreach (QString style, QStyleFactory::keys()) { + if(style.toLower() != "gtk2" || (getenv("QT_QPA_PLATFORMTHEME")!=nullptr && !strcmp(getenv("QT_QPA_PLATFORMTHEME"),"gtk2"))) + ui.cmboStyle->addItem(style, style.toLower()); + } QMap styleSheets; - Rshare::getAvailableStyleSheets(styleSheets); + RsApplication::getAvailableStyleSheets(styleSheets); foreach (QString name, styleSheets.keys()) { ui.cmboStyleSheet->addItem(name, styleSheets[name]); @@ -92,10 +96,14 @@ AppearancePage::AppearancePage(QWidget * parent, Qt::WindowFlags flags) connect(ui.cmboLanguage, SIGNAL(currentIndexChanged(int)), this, SLOT(updateLanguageCode() )); connect(ui.cmboStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(updateInterfaceStyle() )); connect(ui.cmboStyleSheet, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSheetName() )); - connect(ui.checkBoxDisableSysTrayToolTip, SIGNAL(toggled(bool)), this, SLOT(updateStatusToolTip() )); + connect(ui.cmboStyleSheet, SIGNAL(activated(int)) , this, SLOT(loadStyleSheet(int) )); + connect(ui.checkBoxDisableSysTrayToolTip, SIGNAL(toggled(bool)) , this, SLOT(updateStatusToolTip() )); connect(ui.mainPageButtonType_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRbtPageOnToolBar() )); // connect(ui.menuItemsButtonType_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(updateActionButtonLoc() )); + + connect(ui.minimumFontSize_SB, SIGNAL(valueChanged(int)), this, SLOT(updateFontSize())) ; + } void AppearancePage::switch_status_grpStatus(bool b) { switch_status(MainWindow::StatusGrpStatus ,"ShowStatusBar", b) ; } @@ -128,10 +136,31 @@ void AppearancePage::switch_status(MainWindow::StatusElement s,const QString& ke void AppearancePage::updateLanguageCode() { Settings->setLanguageCode(LanguageSupport::languageCode(ui.cmboLanguage->currentText())); } void AppearancePage::updateInterfaceStyle() { - Rshare::setStyle(ui.cmboStyle->currentText()); - Settings->setInterfaceStyle(ui.cmboStyle->currentText()); +#ifndef QT_NO_CURSOR + QApplication::setOverrideCursor(Qt::WaitCursor); +#endif + RsApplication::setStyle(ui.cmboStyle->currentText()); + Settings->setInterfaceStyle(ui.cmboStyle->currentText()); +#ifndef QT_NO_CURSOR + QApplication::restoreOverrideCursor(); +#endif } -void AppearancePage::updateSheetName() { Settings->setSheetName(ui.cmboStyleSheet->itemData(ui.cmboStyleSheet->currentIndex()).toString()); } +void AppearancePage::updateSheetName() +{ + Settings->setSheetName(ui.cmboStyleSheet->itemData(ui.cmboStyleSheet->currentIndex()).toString()); +} + +void AppearancePage::loadStyleSheet(int index) +{ +#ifndef QT_NO_CURSOR + QApplication::setOverrideCursor(Qt::WaitCursor); +#endif + RsApplication::loadStyleSheet(ui.cmboStyleSheet->itemData(index).toString()); +#ifndef QT_NO_CURSOR + QApplication::restoreOverrideCursor(); +#endif +} + void AppearancePage::updateRbtPageOnToolBar() { Settings->setPageButtonLoc(!ui.mainPageButtonType_CB->currentIndex()); @@ -225,7 +254,7 @@ void AppearancePage::updateCmboToolButtonSize() // NotifyQt::getInstance()->notifySettingsChanged(); // } -void AppearancePage::updateStyle() { Rshare::setStyle(ui.cmboStyle->currentText()); } +void AppearancePage::updateStyle() { RsApplication::setStyle(ui.cmboStyle->currentText()); } /** Loads the settings for this page */ void AppearancePage::load() @@ -233,7 +262,7 @@ void AppearancePage::load() int index = ui.cmboLanguage->findData(Settings->getLanguageCode()); whileBlocking(ui.cmboLanguage)->setCurrentIndex(index); - index = ui.cmboStyle->findData(Rshare::style().toLower()); + index = ui.cmboStyle->findData(RsApplication::style().toLower()); whileBlocking(ui.cmboStyle)->setCurrentIndex(index); index = ui.cmboStyleSheet->findData(Settings->getSheetName()); @@ -245,9 +274,9 @@ void AppearancePage::load() index = ui.mainPageButtonType_CB->findData(Settings->getPageButtonLoc()); if (index != 0) { - ui.cmboTollButtonsStyle->hide(); - }else { - ui.cmboTollButtonsStyle->show(); + ui.cmboTollButtonsStyle->show(); + }else { + ui.cmboTollButtonsStyle->hide(); } whileBlocking(ui.mainPageButtonType_CB)->setCurrentIndex(!Settings->getPageButtonLoc()); @@ -333,9 +362,12 @@ void AppearancePage::load() whileBlocking(ui.checkBoxShowToasterDisable)->setChecked(Settings->valueFromGroup("StatusBar", "ShowToaster", QVariant(true)).toBool()); whileBlocking(ui.checkBoxShowSystrayOnStatus)->setChecked(Settings->valueFromGroup("StatusBar", "ShowSysTrayOnStatusBar", QVariant(false)).toBool()); + whileBlocking(ui.minimumFontSize_SB)->setValue(Settings->getFontSize()); } -void AppearancePage::loadStyleSheet(int index) +void AppearancePage::updateFontSize() { - Rshare::loadStyleSheet(ui.cmboStyleSheet->itemData(index).toString()); + Settings->setFontSize(ui.minimumFontSize_SB->value()); + + NotifyQt::getInstance()->notifySettingsChanged(); } diff --git a/retroshare-gui/src/gui/settings/AppearancePage.h b/retroshare-gui/src/gui/settings/AppearancePage.h index 897563753..741bd752e 100755 --- a/retroshare-gui/src/gui/settings/AppearancePage.h +++ b/retroshare-gui/src/gui/settings/AppearancePage.h @@ -71,6 +71,8 @@ private slots: // void updateCmboListItemSize(); void updateStyle() ; + void updateFontSize(); + private: void switch_status(MainWindow::StatusElement s,const QString& key,bool b); diff --git a/retroshare-gui/src/gui/settings/AppearancePage.ui b/retroshare-gui/src/gui/settings/AppearancePage.ui index a06a4933e..13dc7a48e 100755 --- a/retroshare-gui/src/gui/settings/AppearancePage.ui +++ b/retroshare-gui/src/gui/settings/AppearancePage.ui @@ -14,22 +14,7 @@ Qt::NoContextMenu - - 6 - - - 6 - - - 6 - - - 6 - - - 0 - - + @@ -45,7 +30,7 @@ - + 150 @@ -86,110 +71,12 @@ - - - - - 0 - 64 - - - - Qt::NoContextMenu - - - - - - Style - - - - - - - 150 - 0 - - - - Choose RetroShare's interface style - - - - - - - Qt::Horizontal - - - - 215 - 20 - - - - - - - - - - - - 0 - 64 - - - - Style Sheet - - - - - - - 150 - 0 - - - - - - - - Qt::Horizontal - - - - 215 - 20 - - - - - - - - - - - Qt::Vertical - - - - 361 - 61 - - - - - + 0 - 228 + 0 @@ -198,8 +85,8 @@ Tool Bar - - + + @@ -209,7 +96,7 @@ - + Buttons @@ -237,7 +124,7 @@ - + @@ -253,7 +140,7 @@ 0 - + Icon Only @@ -289,21 +176,8 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - - + Icon Size = 8x8 @@ -352,10 +226,79 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + +
    - + + + + Fonts + + + + + + + + Minimum font size + + + + + + + 5 + + + 64 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 188 + 96 + + + + + + + + Status Bar @@ -464,8 +407,113 @@
    + + + + Qt::Vertical + + + + 361 + 61 + + + + + + + + + 0 + 64 + + + + Qt::NoContextMenu + + + + + + Style + + + + + + + 150 + 0 + + + + Choose RetroShare's interface style + + + + + + + Qt::Horizontal + + + + 215 + 20 + + + + + + + + + + + + 0 + 64 + + + + Style Sheet + + + + + + + 150 + 0 + + + + + + + + Qt::Horizontal + + + + 215 + 20 + + + + + + +
    + + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    +
    diff --git a/retroshare-gui/src/gui/settings/ChannelPage.cpp b/retroshare-gui/src/gui/settings/ChannelPage.cpp index ef2fa6307..857cc972e 100644 --- a/retroshare-gui/src/gui/settings/ChannelPage.cpp +++ b/retroshare-gui/src/gui/settings/ChannelPage.cpp @@ -22,6 +22,7 @@ #include "rsharesettings.h" #include "util/misc.h" #include "gui/notifyqt.h" +#include "retroshare/rsgxschannels.h" ChannelPage::ChannelPage(QWidget * parent, Qt::WindowFlags flags) : ConfigPage(parent, flags) @@ -35,6 +36,9 @@ ChannelPage::ChannelPage(QWidget * parent, Qt::WindowFlags flags) connect(ui.emoteicon_checkBox,SIGNAL(toggled(bool)),this,SLOT(updateEmotes())) ; + // Connecting the spin box with the maximum auto download size in channels + connect(ui.autoDownloadSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateMaxAutoDownloadSizeLimit(int))); + } ChannelPage::~ChannelPage() @@ -49,6 +53,13 @@ void ChannelPage::load() Settings->beginGroup(QString("ChannelPostsWidget")); whileBlocking(ui.emoteicon_checkBox)->setChecked(Settings->value("Emoteicons_ChannelDecription", true).toBool()); Settings->endGroup(); + + // Getting the maximum auto download size from the configuration + uint64_t maxAutoDownloadSize; + rsGxsChannels->getMaxAutoDownloadSizeLimit(maxAutoDownloadSize); + int temp=(maxAutoDownloadSize/(Size_Of_1_GB)); + whileBlocking(ui.autoDownloadSpinBox)->setValue(temp); + } void ChannelPage::updateEmotes() @@ -57,3 +68,10 @@ void ChannelPage::updateEmotes() Settings->setValue("Emoteicons_ChannelDecription", ui.emoteicon_checkBox->isChecked()); Settings->endGroup(); } + +// Function to update the maximum size allowed for auto download in channels +void ChannelPage::updateMaxAutoDownloadSizeLimit(int value) +{ + uint64_t temp=(static_cast(value)*Size_Of_1_GB); + rsGxsChannels->setMaxAutoDownloadSizeLimit(temp); +} diff --git a/retroshare-gui/src/gui/settings/ChannelPage.h b/retroshare-gui/src/gui/settings/ChannelPage.h index 93f32cabc..adb573711 100644 --- a/retroshare-gui/src/gui/settings/ChannelPage.h +++ b/retroshare-gui/src/gui/settings/ChannelPage.h @@ -25,6 +25,8 @@ #include "ui_ChannelPage.h" #include "gui/common/FilesDefs.h" +#define Size_Of_1_GB (1024 * 1024 * 1024) // It is the size of 1 GB in bytes. + class ChannelPage : public ConfigPage { Q_OBJECT @@ -43,6 +45,9 @@ public: private slots: void updateEmotes(); + // Function to update the maximum size allowed for auto download in channels + void updateMaxAutoDownloadSizeLimit(int value); + private: Ui::ChannelPage ui; }; diff --git a/retroshare-gui/src/gui/settings/ChannelPage.ui b/retroshare-gui/src/gui/settings/ChannelPage.ui index 5e75e442e..8ea42f71a 100644 --- a/retroshare-gui/src/gui/settings/ChannelPage.ui +++ b/retroshare-gui/src/gui/settings/ChannelPage.ui @@ -6,22 +6,23 @@ 0 0 - 423 + 526 334 - - - - - Tabs + + + + + Qt::Vertical - - - - - - + + + 20 + 5 + + + @@ -39,18 +40,43 @@
    + + + + Tabs + + + + + + + + - - - Qt::Vertical + + + Downloads - - - 20 - 40 - - - + + + + + 1 + + + 200 + + + + + + + Maximum Auto Download Size (in GBs) + + + + +
    diff --git a/retroshare-gui/src/gui/settings/ChatPage.cpp b/retroshare-gui/src/gui/settings/ChatPage.cpp index 357f2698c..1f35fe62c 100644 --- a/retroshare-gui/src/gui/settings/ChatPage.cpp +++ b/retroshare-gui/src/gui/settings/ChatPage.cpp @@ -18,26 +18,27 @@ * * *******************************************************************************/ +#include "ChatPage.h" + +#include "rsharesettings.h" +#include "gui/MainWindow.h" +#include "gui/notifyqt.h" +#include "gui/RetroShareLink.h" +#include "gui/chat/ChatDialog.h" +#include "util/misc.h" + +#include "retroshare/rsconfig.h" +#include "retroshare/rshistory.h" +#include "retroshare/rsmsgs.h" +#include "retroshare/rsnotify.h" +#include "retroshare/rspeers.h" + #include #include #include + #include -#include -#include -#include -#include "ChatPage.h" -#include "gui/MainWindow.h" -#include -#include "gui/chat/ChatDialog.h" -#include "gui/notifyqt.h" -#include "rsharesettings.h" -#include "util/misc.h" -#include - -#include -#include - #define VARIANT_STANDARD "Standard" #define IMAGE_CHAT_CREATE ":/icons/png/add.png" #define IMAGE_CHAT_OPEN ":/icons/png/typing.png" @@ -124,9 +125,6 @@ void ChatPage::updateFontsAndEmotes() /** Saves the changes on this page */ void ChatPage::updateChatParams() { - // state of distant Chat combobox - Settings->setValue("DistantChat", ui.distantChatComboBox->currentIndex()); - Settings->setChatScreenFont(fontTempChat.toString()); NotifyQt::getInstance()->notifyChatFontChanged(); @@ -134,6 +132,7 @@ void ChatPage::updateChatParams() Settings->setChatSendAsPlainTextByDef(ui.sendAsPlainTextByDef->isChecked()); Settings->setChatLoadEmbeddedImages(ui.loadEmbeddedImages->isChecked()); Settings->setChatDoNotSendIsTyping(ui.DontSendTyping->isChecked()); + Settings->setShrinkChatTextEdit(ui.shrinkChatTextEdit->isChecked()); } void ChatPage::updateChatSearchParams() @@ -247,6 +246,7 @@ ChatPage::ChatPage(QWidget * parent, Qt::WindowFlags flags) connect(ui.sendAsPlainTextByDef, SIGNAL(toggled(bool)), this, SLOT(updateChatParams())); connect(ui.loadEmbeddedImages, SIGNAL(toggled(bool)), this, SLOT(updateChatParams())); connect(ui.DontSendTyping, SIGNAL(toggled(bool)), this, SLOT(updateChatParams())); + connect(ui.shrinkChatTextEdit, SIGNAL(toggled(bool)), this, SLOT(updateChatParams())); connect(ui.sbSearch_CharToStart, SIGNAL(valueChanged(int)), this, SLOT(updateChatSearchParams())); connect(ui.cbSearch_CaseSensitively, SIGNAL(toggled(bool)), this, SLOT(updateChatSearchParams())); @@ -295,6 +295,29 @@ ChatPage::ChatPage(QWidget * parent, Qt::WindowFlags flags) connect(ui.privateStyle, SIGNAL(currentIndexChanged(int)), this,SLOT(on_privateList_currentRowChanged(int))); connect(ui.historyStyle, SIGNAL(currentIndexChanged(int)), this,SLOT(on_historyList_currentRowChanged(int))); + //Resize system size square + qreal logicalPPCX = ui.systemSize_Frame->logicalDpiX()/2.54; + qreal logicalPPCY = ui.systemSize_Frame->logicalDpiY()/2.54; + + ui.systemSize_Frame->setMinimumSize(logicalPPCX,logicalPPCY); + ui.systemSize_Frame->setMaximumSize(logicalPPCX,logicalPPCY); + ui.systemSize_Frame->setToolTip(QString("Your system reports a screen with %1 DPI (Dots Per Inches) = %2 PPC (Pixels Per Centimeters).") + .arg(ui.systemSize_Frame->logicalDpiX()).arg(logicalPPCX)); + + //Resize system font size square + qreal ptFontSize = (qreal)QApplication::font().pointSize(); + qreal pxFontSize = (qreal)QFontMetrics(QApplication::font()).height(); + qreal px1ptSize = pxFontSize / ptFontSize; + //1 pt = 1/72 inch = 2.54/72 cm + qreal px1cmSize = (px1ptSize * 72.0) / 2.54; + + ui.systemFontSize_Frame->setMinimumSize(px1cmSize,px1cmSize); + ui.systemFontSize_Frame->setMaximumSize(px1cmSize,px1cmSize); + + ui.systemFontSize_Frame->setToolTip(QString("Your default font is %1 points high = %2 mm. Qt print it with %3 pixels.\nSo Font use %4 PPC (Pixels Per Centimeters).") + .arg(ptFontSize).arg((ptFontSize*25.4)/72.0).arg(pxFontSize).arg(px1cmSize)); + + /* Add user notify */ const QList &userNotifyList = MainWindow::getInstance()->getUserNotifyList() ; QList::const_iterator it; @@ -369,9 +392,23 @@ ChatPage::load() whileBlocking(ui.minimumContrast)->setValue(Settings->value("MinimumContrast", 4.5).toDouble()); Settings->endGroup(); - // state of distant Chat combobox - int index = Settings->value("DistantChat", 0).toInt(); - whileBlocking(ui.distantChatComboBox)->setCurrentIndex(index); + // state of distant Chat combobox + + switch(rsMsgs->getDistantChatPermissionFlags()) + { + default: + case RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_NONE: + whileBlocking(ui.distantChatComboBox)->setCurrentIndex(0); + break ; + + case RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS: + whileBlocking(ui.distantChatComboBox)->setCurrentIndex(1); + break ; + + case RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY: + whileBlocking(ui.distantChatComboBox)->setCurrentIndex(2); + break ; + } fontTempChat.fromString(Settings->getChatScreenFont()); @@ -379,6 +416,7 @@ ChatPage::load() whileBlocking(ui.sendAsPlainTextByDef)->setChecked(Settings->getChatSendAsPlainTextByDef()); whileBlocking(ui.loadEmbeddedImages)->setChecked(Settings->getChatLoadEmbeddedImages()); whileBlocking(ui.DontSendTyping)->setChecked(Settings->getChatDoNotSendIsTyping()); + whileBlocking(ui.shrinkChatTextEdit)->setChecked(Settings->getShrinkChatTextEdit()); std::string advsetting; if(rsConfig->getConfigurationOption(RS_CONFIG_ADVANCED, advsetting) && (advsetting == "YES")) diff --git a/retroshare-gui/src/gui/settings/ChatPage.ui b/retroshare-gui/src/gui/settings/ChatPage.ui index 484a632f8..0f60752ac 100644 --- a/retroshare-gui/src/gui/settings/ChatPage.ui +++ b/retroshare-gui/src/gui/settings/ChatPage.ui @@ -95,6 +95,16 @@ + + + + When focus on text browser after showing chat room + + + Shrink text edit field when not needed + + + @@ -395,6 +405,78 @@ + + + + + + If your system is set up correctly, this next square should measure 1 cm. + + + true + + + + + + + + 64 + 64 + + + + + 64 + 64 + + + + QFrame::Box + + + QFrame::Plain + + + + + + + + + + + This next square is scaled accordingly to your system font size. + + + true + + + + + + + + 64 + 64 + + + + + 64 + 64 + + + + QFrame::Box + + + QFrame::Plain + + + + + @@ -527,7 +609,7 @@ - + @@ -543,7 +625,7 @@ - + 0 @@ -644,7 +726,7 @@ - + Everyone @@ -725,7 +807,7 @@ - + @@ -741,7 +823,7 @@ - + 0 @@ -1176,7 +1258,7 @@ - + @@ -1192,7 +1274,7 @@ - + 0 @@ -1285,6 +1367,11 @@ QComboBox
    gui/gxs/GxsIdChooser.h
    + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    diff --git a/retroshare-gui/src/gui/settings/CryptoPage.cpp b/retroshare-gui/src/gui/settings/CryptoPage.cpp index 99317c14d..296f6aec3 100755 --- a/retroshare-gui/src/gui/settings/CryptoPage.cpp +++ b/retroshare-gui/src/gui/settings/CryptoPage.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include //for rsPeers variable #include //for rsPeers variable @@ -58,11 +59,16 @@ CryptoPage::CryptoPage(QWidget * parent, Qt::WindowFlags flags) // hide profile manager as it causes bugs when generating a new profile. //ui.profile_Button->hide() ; - //connect(ui.exportprofile,SIGNAL(clicked()), this, SLOT(profilemanager())); - connect(ui.exportprofile,SIGNAL(clicked()), this, SLOT(exportProfile())); + //connect(ui.exportprofile,SIGNAL(clicked()), this, SLOT(profilemanager())); + connect(ui.exportprofile,SIGNAL(clicked()), this, SLOT(exportProfile())); + connect(ui.exportfriendslist,SIGNAL(clicked()), this, SLOT(exportFriendsList()) ); + // Remove this because it duplicates functionality of the HomePage. + ui.retroshareId_LB->hide(); + ui.retroshareId_content_LB->hide(); + ui.stackPageCertificate->hide(); - ui.onlinesince->setText(DateTime::formatLongDateTime(Rshare::startupTime())); + ui.onlinesince->setText(DateTime::formatLongDateTime(RsApplication::startupTime())); } #ifdef UNUSED_CODE @@ -103,11 +109,11 @@ void CryptoPage::showEvent ( QShowEvent * /*event*/ ) ui.pgpfingerprint->setText(misc::fingerPrintStyleSplit(QString::fromStdString(detail.fpr.toStdString()))); std::string invite ; - rsPeers->getShortInvite(invite,rsPeers->getOwnId(),RetroshareInviteFlags::RADIX_FORMAT | RetroshareInviteFlags::DNS | RetroshareInviteFlags::CURRENT_IP); - ui.retroshareid->setText(QString::fromUtf8(invite.c_str())); + rsPeers->getShortInvite(invite,rsPeers->getOwnId(),RetroshareInviteFlags::RADIX_FORMAT | RsPeers::defaultCertificateFlags); + ui.retroshareId_content_LB->setText(QString::fromUtf8(invite.c_str())); /* set retroshare version */ - ui.version->setText(Rshare::retroshareVersion(true)); + ui.version->setText(RsApplication::retroshareVersion(true)); std::list ids; ids.clear(); @@ -139,7 +145,7 @@ void CryptoPage::load() { std::string cert ; - RetroshareInviteFlags flags = RetroshareInviteFlags::DNS | RetroshareInviteFlags::CURRENT_IP; + RetroshareInviteFlags flags = RetroshareInviteFlags::DNS | RetroshareInviteFlags::CURRENT_LOCAL_IP | RetroshareInviteFlags::CURRENT_EXTERNAL_IP; if(ui._shortFormat_CB->isChecked()) { @@ -161,7 +167,7 @@ CryptoPage::load() RsPeerDetails detail; rsPeers->getPeerDetails(rsPeers->getOwnId(),detail); - ui.certplainTextEdit->setToolTip(ConfCertDialog::getCertificateDescription(detail, ui._includeSignatures_CB->isChecked(), ui._shortFormat_CB->isChecked(), ui._includeAllIPs_CB->isChecked() )); + ui.certplainTextEdit->setToolTip(ConfCertDialog::getCertificateDescription(detail, ui._includeSignatures_CB->isChecked(), ui._shortFormat_CB->isChecked(), flags)); } void @@ -225,3 +231,8 @@ void CryptoPage::showStats() { StatisticsWindow::showYourself(); } + +void CryptoPage::exportFriendsList() +{ + NewFriendList().exportFriendlistClicked(); +} diff --git a/retroshare-gui/src/gui/settings/CryptoPage.h b/retroshare-gui/src/gui/settings/CryptoPage.h index e595c63c4..e10cbb97a 100755 --- a/retroshare-gui/src/gui/settings/CryptoPage.h +++ b/retroshare-gui/src/gui/settings/CryptoPage.h @@ -51,6 +51,7 @@ class CryptoPage : public ConfigPage bool fileSave(); bool fileSaveAs(); void showStats(); + void exportFriendsList(); private: QString fileName; diff --git a/retroshare-gui/src/gui/settings/CryptoPage.ui b/retroshare-gui/src/gui/settings/CryptoPage.ui index 6f45b9ea8..c0d602368 100755 --- a/retroshare-gui/src/gui/settings/CryptoPage.ui +++ b/retroshare-gui/src/gui/settings/CryptoPage.ui @@ -7,39 +7,120 @@ 0 0 869 - 487 + 493
    - - - 0 - - - - Node information - + + + + + + + 0 + 0 + + + + + 75 + true + + + + TextLabel + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + Location ID: + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + Location: + + + - + Retroshare ID: - - - - Statistics: + + + + 6 - + + + + + 16 + 16 + + + + + + + :/images/info16.png + + + + + + + + 12 + 75 + true + + + + Profile + + + + - - + + 0 @@ -64,8 +145,81 @@ - - + + + + 6 + + + + + + 16 + 16 + + + + + + + :/images/info16.png + + + + + + + + 12 + 75 + true + + + + Other Information + + + + + + + + + Show statistics + + + + + + + Export Profile: + + + + + + + + 0 + 0 + + + + + 75 + true + + + + TextLabel + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + 0 @@ -79,28 +233,12 @@ - Location ID: + Friend nodes: - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 40 - 20 - - - - - - + + 0 @@ -118,28 +256,44 @@ - - + + + + + 0 + 0 + + + + + 100 + 0 + + - Export Profile: + PGP Id : - - - - - 75 - true - + + + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - TextLabel + Export profile - - + + + + Statistics: + + + + + 0 @@ -176,57 +330,41 @@ - - - - - 0 - 0 - - - - - 100 - 0 - - + + - Location: + Profile path: - - - - - - - 16 - 16 - - - - :/images/info16.png - - - - - - - - 75 - true - - - - Public Information - - - - + + + + Qt::Horizontal + + + + 40 + 20 + + + - - + + + + + 75 + true + + + + TextLabel + + + + + 0 @@ -244,16 +382,6 @@ - - - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - Export - - - @@ -273,90 +401,24 @@ - - + + + + + 75 + true + + - Show statistics + TextLabel + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - 6 - - - - - - 16 - 16 - - - - - - - :/images/info16.png - - - - - - - - 75 - true - - - - Other Information - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Profile path: - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - Friend nodes: - - - - - + + 0 @@ -374,41 +436,18 @@ - - - - 6 + + + + + 75 + true + - - - - - 16 - 16 - - - - - - - :/images/info16.png - - - - - - - - 75 - true - - - - Profile - - - - + + TextLabel + + @@ -429,94 +468,66 @@ - - - - - 0 - 0 - - - - - 75 - true - - + + + + + + + 16 + 16 + + + + :/images/info16.png + + + + + + + + 12 + 75 + true + + + + Public Information + + + + + + + - TextLabel - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + Export Friendslist: - - - - - 0 - 0 - + + + + Export friends list - + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + - 100 - 0 + 40 + 20 - - PGP Id : - - - - - - - - 75 - true - - - - TextLabel - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - - 0 - 0 - - - - - 75 - true - - - - TextLabel - - - - - - - - 75 - true - - - - TextLabel - - + @@ -536,10 +547,7 @@
    - - - Certificate - + @@ -638,13 +646,6 @@ - - - StyledLabel - QLabel -
    gui/common/StyledLabel.h
    -
    -
    diff --git a/retroshare-gui/src/gui/settings/GeneralPage.ui b/retroshare-gui/src/gui/settings/GeneralPage.ui index ab2863f1c..3eea0544f 100755 --- a/retroshare-gui/src/gui/settings/GeneralPage.ui +++ b/retroshare-gui/src/gui/settings/GeneralPage.ui @@ -146,10 +146,10 @@ - When checked, this instance receives new parameters (like RsLink or RsFile) and avoid new one. + <html><head/><body><p>When checked, this retroshare instance will accept calls by your operating system to open Retroshare collection files, and download links.</p></body></html> - Use Local Server to get new arguments. + Accept operating systems calls true diff --git a/retroshare-gui/src/gui/settings/JsonApiPage.cc b/retroshare-gui/src/gui/settings/JsonApiPage.cc index 5f1bb225f..ace092e0c 100644 --- a/retroshare-gui/src/gui/settings/JsonApiPage.cc +++ b/retroshare-gui/src/gui/settings/JsonApiPage.cc @@ -23,11 +23,14 @@ #include "rsharesettings.h" #include "jsonapi/jsonapi.h" #include "util/misc.h" +#include "util/qtthreadsutils.h" #include #include #include +#define IMAGE_LEDOFF ":/images/ledoff1.png" +#define IMAGE_LEDON ":/images/ledon1.png" JsonApiPage::JsonApiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/) { @@ -57,9 +60,41 @@ JsonApiPage::JsonApiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/) QRegExpValidator *ipValidator = new QRegExpValidator(ipRegex, this); ui.listenAddressLineEdit->setValidator(ipValidator); + ui.providersListView->setSelectionMode(QAbstractItemView::NoSelection); // prevents edition. + mEventHandlerId = 0; + + rsEvents->registerEventsHandler( [this](std::shared_ptr e) + { + if(e->mType != RsEventType::JSON_API) + return; + + auto je = dynamic_cast(e.get()); + + if(!je) + return; +#ifdef DEBUG + std::cerr << "Caught JSONAPI event! code=" << static_cast(je->mJsonApiEventCode) << std::endl; +#endif + + RsQThreadUtils::postToObject([=]() { load(); }, this ); + }, + mEventHandlerId, RsEventType::JSON_API ); } +JsonApiPage::~JsonApiPage() +{ + rsEvents->unregisterEventsHandler(mEventHandlerId); +} +QString JsonApiPage::helpText() const +{ + return tr("

      Webinterface

    \ +

    Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. \ + Please refer to the Retroshare documentation for how to use this feature.

    \ +

    Unless you know what you're doing, you shouldn't need to change anything in this page. \ + The web interface for instance will automatically register its own token to the JSON API which will be visible \ + in the list of authenticated tokens after you enable it.

    "); +} void JsonApiPage::enableJsonApi(bool checked) { ui.addTokenPushButton->setEnabled(checked); @@ -80,7 +115,6 @@ void JsonApiPage::enableJsonApi(bool checked) bool JsonApiPage::updateParams() { bool ok = true; - bool changed = false; uint16_t port = static_cast(ui.portSpinBox->value()); QString listenAddress = ui.listenAddressLineEdit->text(); @@ -94,9 +128,9 @@ bool JsonApiPage::updateParams() void JsonApiPage::load() { - whileBlocking(ui.portSpinBox)->setValue(Settings->getJsonApiPort()); - whileBlocking(ui.listenAddressLineEdit)->setText(Settings->getJsonApiListenAddress()); - whileBlocking(ui.enableCheckBox)->setChecked(Settings->getJsonApiEnabled()); + whileBlocking(ui.portSpinBox)->setValue(rsJsonApi->listeningPort()); + whileBlocking(ui.listenAddressLineEdit)->setText(QString::fromStdString(rsJsonApi->getBindingAddress())); + whileBlocking(ui.enableCheckBox)->setChecked(rsJsonApi->isRunning()); QStringList newTk; @@ -105,10 +139,20 @@ void JsonApiPage::load() QString::fromStdString(it.first) + ":" + QString::fromStdString(it.second) ); - whileBlocking(ui.tokensListView)->setModel(new QStringListModel(newTk)); -} + whileBlocking(ui.tokensListView)->setModel(new QStringListModel(newTk)); -QString JsonApiPage::helpText() const { return ""; } + QStringList newTk2; + + for(const auto& it : rsJsonApi->getResourceProviders()) + newTk2.push_back( QString::fromStdString(it.get().getName())) ; + + whileBlocking(ui.providersListView)->setModel(new QStringListModel(newTk2)); + + if(rsJsonApi->isRunning()) + ui.statusLabelLED->setPixmap(FilesDefs::getPixmapFromQtResourcePath(IMAGE_LEDON)) ; + else + ui.statusLabelLED->setPixmap(FilesDefs::getPixmapFromQtResourcePath(IMAGE_LEDOFF)) ; +} bool JsonApiPage::checkStartJsonApi() { @@ -188,23 +232,23 @@ void JsonApiPage::addTokenClicked() whileBlocking(ui.tokensListView)->setModel(new QStringListModel(newTk)); } -void JsonApiPage::removeTokenClicked() -{ - QString token(ui.tokenLineEdit->text()); - rsJsonApi->revokeAuthToken(token.toStdString()); - - QStringList newTk; - - for(const auto& it : rsJsonApi->getAuthorizedTokens()) - newTk.push_back( - QString::fromStdString(it.first) + ":" + - QString::fromStdString(it.second) ); - - whileBlocking(ui.tokensListView)->setModel(new QStringListModel(Settings->getJsonApiAuthTokens()) ); -} - +void JsonApiPage::removeTokenClicked() +{ + QString token(ui.tokenLineEdit->text()); + std::string tokenStr = token.toStdString(); + rsJsonApi->revokeAuthToken(tokenStr.substr(0, tokenStr.find_first_of(":"))); + + QStringList newTk; + + for(const auto& it : rsJsonApi->getAuthorizedTokens()) + newTk.push_back( + QString::fromStdString(it.first) + ":" + + QString::fromStdString(it.second) ); + + whileBlocking(ui.tokensListView)->setModel(new QStringListModel(Settings->getJsonApiAuthTokens()) ); +} + void JsonApiPage::tokenClicked(const QModelIndex& index) { ui.tokenLineEdit->setText(ui.tokensListView->model()->data(index).toString()); } - diff --git a/retroshare-gui/src/gui/settings/JsonApiPage.h b/retroshare-gui/src/gui/settings/JsonApiPage.h index 7f69bbd1e..ef28a4294 100644 --- a/retroshare-gui/src/gui/settings/JsonApiPage.h +++ b/retroshare-gui/src/gui/settings/JsonApiPage.h @@ -20,6 +20,8 @@ #pragma once +#include "retroshare/rsevents.h" + #include "retroshare-gui/configpage.h" #include "gui/common/FilesDefs.h" #include "ui_JsonApiPage.h" @@ -31,7 +33,7 @@ class JsonApiPage : public ConfigPage public: JsonApiPage(QWidget * parent = nullptr, Qt::WindowFlags flags = 0); - ~JsonApiPage() override = default; + ~JsonApiPage() override ; virtual QPixmap iconPixmap() const override { @@ -63,4 +65,6 @@ public slots: private: Ui::JsonApiPage ui; /// Qt Designer generated object + RsEventsHandlerId_t mEventHandlerId; }; + diff --git a/retroshare-gui/src/gui/settings/JsonApiPage.ui b/retroshare-gui/src/gui/settings/JsonApiPage.ui index 24b534712..f8d31e38f 100644 --- a/retroshare-gui/src/gui/settings/JsonApiPage.ui +++ b/retroshare-gui/src/gui/settings/JsonApiPage.ui @@ -13,7 +13,7 @@ Form - + @@ -25,13 +25,65 @@ JSON API Server - + - - - Enable RetroShare JSON API Server - - + + + + + Enable RetroShare JSON API Server + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Status: + + + + + + + + + + :/images/ledoff1.png + + + + + + + + + + + Listen Address: + + + + + + + 127.0.0.1 + + + + @@ -57,24 +109,6 @@ - - - - - - Listen Address: - - - - - - - 127.0.0.1 - - - - - @@ -110,13 +144,23 @@ - Authenticated Tokens + Authenticated Tokens: + + + + Registered services: + + + + + +
    @@ -142,6 +186,8 @@
    - + + + diff --git a/retroshare-gui/src/gui/settings/MessagePage.cpp b/retroshare-gui/src/gui/settings/MessagePage.cpp index 91a24ab02..be8b515ff 100644 --- a/retroshare-gui/src/gui/settings/MessagePage.cpp +++ b/retroshare-gui/src/gui/settings/MessagePage.cpp @@ -18,6 +18,8 @@ * * *******************************************************************************/ +#include + #include "rshare.h" #include "rsharesettings.h" #include "retroshare/rsmsgs.h" @@ -27,6 +29,8 @@ #include "gui/common/TagDefs.h" #include #include "NewTag.h" +#include "util/qtthreadsutils.h" +#include "gui/notifyqt.h" MessagePage::MessagePage(QWidget * parent, Qt::WindowFlags flags) : ConfigPage(parent, flags) @@ -47,17 +51,28 @@ MessagePage::MessagePage(QWidget * parent, Qt::WindowFlags flags) ui.openComboBox->addItem(tr("A new tab"), RshareSettings::MSG_OPEN_TAB); ui.openComboBox->addItem(tr("A new window"), RshareSettings::MSG_OPEN_WINDOW); - + + // Font size + QFontDatabase db; + foreach(int size, db.standardSizes()) { + ui.minimumFontSize->addItem(QString::number(size), size); + } + connect(ui.comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(distantMsgsComboBoxChanged(int))); connect(ui.setMsgToReadOnActivate,SIGNAL(toggled(bool)), this,SLOT(updateMsgToReadOnActivate())); connect(ui.loadEmbeddedImages, SIGNAL(toggled(bool)), this,SLOT(updateLoadEmbededImages() )); connect(ui.openComboBox, SIGNAL(currentIndexChanged(int)),this,SLOT(updateMsgOpen() )); connect(ui.emoticonscheckBox, SIGNAL(toggled(bool)), this,SLOT(updateLoadEmoticons() )); + connect(ui.minimumFontSize, SIGNAL(activated(QString)), this, SLOT(updateFontSize())) ; + + mTagEventHandlerId = 0; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) { RsQThreadUtils::postToObject( [this,event]() { handleEvent_main_thread(event); }); }, mTagEventHandlerId, RsEventType::MAIL_TAG ); } MessagePage::~MessagePage() { + rsEvents->unregisterEventsHandler(mTagEventHandlerId); delete(m_pTags); } @@ -111,12 +126,11 @@ void MessagePage::updateMsgTags() void MessagePage::load() { - Settings->beginGroup(QString("Messages")); whileBlocking(ui.setMsgToReadOnActivate)->setChecked(Settings->getMsgSetToReadOnActivate()); whileBlocking(ui.loadEmbeddedImages)->setChecked(Settings->getMsgLoadEmbeddedImages()); whileBlocking(ui.openComboBox)->setCurrentIndex(ui.openComboBox->findData(Settings->getMsgOpen())); whileBlocking(ui.emoticonscheckBox)->setChecked(Settings->value("Emoticons", true).toBool()); - Settings->endGroup(); + whileBlocking(ui.minimumFontSize)->setCurrentIndex(ui.minimumFontSize->findData(Settings->getMessageFontSize())); // state of filter combobox @@ -134,6 +148,27 @@ MessagePage::load() fillTags(); } +void MessagePage::handleEvent_main_thread(std::shared_ptr event) +{ + if (event->mType != RsEventType::MAIL_TAG) { + return; + } + + const RsMailTagEvent *fe = dynamic_cast(event.get()); + if (!fe) { + return; + } + + switch (fe->mMailTagEventCode) { + case RsMailTagEventCode::TAG_ADDED: + case RsMailTagEventCode::TAG_CHANGED: + case RsMailTagEventCode::TAG_REMOVED: + rsMail->getMessageTagTypes(*m_pTags); + fillTags(); + break; + } +} + // fill tags void MessagePage::fillTags() { @@ -272,3 +307,9 @@ void MessagePage::currentRowChangedTag(int row) ui.deletepushButton->setEnabled(bDeleteEnable); } +void MessagePage::updateFontSize() +{ + Settings->setMessageFontSize(ui.minimumFontSize->currentData().toInt()); + + NotifyQt::getInstance()->notifySettingsChanged(); +} diff --git a/retroshare-gui/src/gui/settings/MessagePage.h b/retroshare-gui/src/gui/settings/MessagePage.h index f3a4c12a7..c5b9f7544 100644 --- a/retroshare-gui/src/gui/settings/MessagePage.h +++ b/retroshare-gui/src/gui/settings/MessagePage.h @@ -60,13 +60,16 @@ private slots: void updateDistantMsgs() ; void updateMsgTags() ; void updateLoadEmoticons(); + void updateFontSize(); private: + void handleEvent_main_thread(std::shared_ptr event); void fillTags(); /* Pointer for not include of rsmsgs.h */ MsgTagType *m_pTags; std::list m_changedTagIds; + RsEventsHandlerId_t mTagEventHandlerId; Ui::MessagePage ui; }; diff --git a/retroshare-gui/src/gui/settings/MessagePage.ui b/retroshare-gui/src/gui/settings/MessagePage.ui index 58da48b9f..3e5ab3842 100644 --- a/retroshare-gui/src/gui/settings/MessagePage.ui +++ b/retroshare-gui/src/gui/settings/MessagePage.ui @@ -16,44 +16,15 @@ 0 - - - - - Distant messages: - - - - - - - Everyone - - - - - Contacts - - - - - Nobody - - - - - - - - Accept encrypted distant messages from - - - - - - - + + + + + 0 + 0 + + Reading @@ -65,20 +36,6 @@ - - - - - - Open messages in - - - - - - - - @@ -93,10 +50,24 @@ + + + + + + Open messages in + + + + + + + + - + Tags @@ -172,8 +143,111 @@ + + + + Distant messages: + + + + + + + Everyone + + + + + Contacts + + + + + Nobody + + + + + + + + Accept encrypted distant messages from + + + + + + + + + + + 0 + 0 + + + + Fonts + + + + + + + + Qt::LeftToRight + + + Minimum font size + + + + + + + + MS Sans Serif + 10 + + + + Qt::ClickFocus + + + Font size + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    +
    diff --git a/retroshare-gui/src/gui/settings/NotifyPage.ui b/retroshare-gui/src/gui/settings/NotifyPage.ui index 8abfa09d9..fba357bcf 100755 --- a/retroshare-gui/src/gui/settings/NotifyPage.ui +++ b/retroshare-gui/src/gui/settings/NotifyPage.ui @@ -382,7 +382,7 @@ - + 0 @@ -495,6 +495,13 @@ systray_ChatLobby pushButtonDisableAll + + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    +
    diff --git a/retroshare-gui/src/gui/settings/PluginItem.ui b/retroshare-gui/src/gui/settings/PluginItem.ui index 063c27377..202baf819 100644 --- a/retroshare-gui/src/gui/settings/PluginItem.ui +++ b/retroshare-gui/src/gui/settings/PluginItem.ui @@ -10,12 +10,21 @@ 177
    - - + + + 0 + + + 0 + + + 0 + + 0 - + true @@ -28,11 +37,11 @@ QFrame::StyledPanel - + - + - + QLayout::SetDefaultConstraint @@ -73,16 +82,22 @@ - + + + + 75 + true + + TextLabel - + 0 @@ -91,6 +106,7 @@ + 12 75 true @@ -104,7 +120,7 @@ - + @@ -140,7 +156,7 @@ p, li { white-space: pre-wrap; } - + Qt::Horizontal @@ -196,7 +212,7 @@ p, li { white-space: pre-wrap; } - + @@ -205,9 +221,9 @@ p, li { white-space: pre-wrap; } QFrame::Raised - + - + File name: @@ -230,7 +246,7 @@ p, li { white-space: pre-wrap; } - + File hash: @@ -253,7 +269,7 @@ p, li { white-space: pre-wrap; } - + Status: @@ -285,13 +301,6 @@ p, li { white-space: pre-wrap; } - - - StyledLabel - QLabel -
    gui/common/StyledLabel.h
    -
    -
    diff --git a/retroshare-gui/src/gui/settings/ServerPage.cpp b/retroshare-gui/src/gui/settings/ServerPage.cpp index e17fc9919..be2404bc8 100755 --- a/retroshare-gui/src/gui/settings/ServerPage.cpp +++ b/retroshare-gui/src/gui/settings/ServerPage.cpp @@ -21,6 +21,7 @@ #include "ServerPage.h" #include +#include "gui/MainWindow.h" #include "rshare.h" #include "rsharesettings.h" #include "util/i2pcommon.h" @@ -47,6 +48,10 @@ #include #include +#ifdef RS_USE_I2P_SAM3 +#include +#endif + #define ICON_STATUS_UNKNOWN ":/images/ledoff1.png" #define ICON_STATUS_WORKING ":/images/yellowled.png" #define ICON_STATUS_OK ":/images/ledon1.png" @@ -64,11 +69,11 @@ /// // Tabs numbers *after* non relevant tabs are removed. So do not use them to add/remove tabs!! -const static uint32_t TAB_HIDDEN_SERVICE_OUTGOING = 0; +//nst static uint32_t TAB_HIDDEN_SERVICE_OUTGOING = 0; const static uint32_t TAB_HIDDEN_SERVICE_INCOMING = 1; -const static uint32_t TAB_HIDDEN_SERVICE_I2P_BOB = 2; +const static uint32_t TAB_HIDDEN_SERVICE_I2P = 2; -const static uint32_t TAB_NETWORK = 0; +//nst static uint32_t TAB_NETWORK = 0; const static uint32_t TAB_HIDDEN_SERVICE = 1; const static uint32_t TAB_IP_FILTERS = 2; const static uint32_t TAB_RELAYS = 3; @@ -79,14 +84,14 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) : ConfigPage(parent, flags) , manager(NULL), mOngoingConnectivityCheck(-1) , mIsHiddenNode(false), mHiddenType(RS_HIDDEN_TYPE_NONE) - , mBobAccessible(false) + , mSamAccessible(false) , mEventHandlerId(0) { /* Invoke the Qt Designer generated object setup routine */ ui.setupUi(this); -#ifndef RS_USE_I2P_BOB - ui.hiddenServiceTab->removeTab(TAB_HIDDEN_SERVICE_I2P_BOB); // warning: the order of operation here is very important. +#ifndef RS_USE_I2P_SAM3 + ui.hiddenServiceTab->removeTab(TAB_HIDDEN_SERVICE_I2P); // warning: the order of operation here is very important. #endif if(RsAccounts::isHiddenNode()) @@ -98,20 +103,31 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) { // Here we use absolute numbers instead of consts defined above, because the consts correspond to the tab number *after* this tab removal. - ui.hiddenpage_proxyAddress_i2p->hide() ; - ui.hiddenpage_proxyLabel_i2p->hide() ; - ui.hiddenpage_proxyPort_i2p->hide() ; - ui.label_i2p_outgoing->hide() ; - ui.iconlabel_i2p_outgoing->hide() ; - ui.plainTextEdit->hide() ; + ui.hiddenpage_proxyAddress_tor->setEnabled(false) ; + ui.hiddenpage_proxyPort_tor->setEnabled(false) ; + ui.hiddenpage_localAddress->setEnabled(false) ; + ui.hiddenpage_localPort->setEnabled(false) ; + ui.hiddenpage_serviceAddress->setEnabled(false) ; + ui.hiddenpage_servicePort->setEnabled(false) ; + ui.testIncoming_PB->hide() ; + ui.l_incomingTestResult->hide() ; + ui.iconlabel_service_incoming->hide() ; + + // ui.hiddenpage_proxyAddress_i2p->hide() ; + // ui.hiddenpage_proxyLabel_i2p->hide() ; + // ui.hiddenpage_proxyPort_i2p->hide() ; + // ui.label_i2p_outgoing->hide() ; + // ui.iconlabel_i2p_outgoing->hide() ; + + ui.info_SocksProxy->hide() ; ui.hiddenpage_configuration->hide() ; ui.l_hiddenpage_configuration->hide() ; - ui.hiddenpageInHelpPlainTextEdit->hide() ; + ui.info_HiddenPageInHelp->hide() ; ui.hiddenpage_outHeader->setText(tr("Tor has been automatically configured by Retroshare. You shouldn't need to change anything here.")) ; ui.hiddenpage_inHeader->setText(tr("Tor has been automatically configured by Retroshare. You shouldn't need to change anything here.")) ; - ui.hiddenServiceTab->removeTab(TAB_HIDDEN_SERVICE_I2P_BOB); // warning: the order of operation here is very important. + ui.hiddenServiceTab->removeTab(TAB_HIDDEN_SERVICE_I2P); // warning: the order of operation here is very important. } } else @@ -153,8 +169,8 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) ui.leBobB32Addr->hide(); ui.pbBobGenAddr->hide(); - QObject::connect(ui.filteredIpsTable,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(ipFilterContextMenu(const QPoint&))) ; - QObject::connect(ui.whiteListIpsTable,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(ipWhiteListContextMenu(const QPoint&))) ; + QObject::connect(ui.filteredIpsTable,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(ipFilterContextMenu(QPoint))) ; + QObject::connect(ui.whiteListIpsTable,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(ipWhiteListContextMenu(QPoint))) ; QObject::connect(ui.denyAll_CB,SIGNAL(toggled(bool)),this,SLOT(toggleIpFiltering(bool))); QObject::connect(ui.includeFromDHT_CB,SIGNAL(toggled(bool)),this,SLOT(toggleAutoIncludeDHT(bool))); QObject::connect(ui.includeFromFriends_CB,SIGNAL(toggled(bool)),this,SLOT(toggleAutoIncludeFriends(bool))); @@ -162,18 +178,18 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) QObject::connect(ui.groupIPRanges_SB,SIGNAL(valueChanged(int)),this,SLOT(setGroupIpLimit(int))); QObject::connect(ui.ipInputAddBlackList_PB,SIGNAL(clicked()),this,SLOT(addIpRangeToBlackList())); QObject::connect(ui.ipInputAddWhiteList_PB,SIGNAL(clicked()),this,SLOT(addIpRangeToWhiteList())); - QObject::connect(ui.ipInput_LE,SIGNAL(textChanged(const QString&)),this,SLOT(checkIpRange(const QString&))); + QObject::connect(ui.ipInput_LE,SIGNAL(textChanged(QString)),this,SLOT(checkIpRange(QString))); QObject::connect(ui.filteredIpsTable,SIGNAL(currentCellChanged(int,int,int,int)),this,SLOT(updateSelectedBlackListIP(int,int,int,int))); QObject::connect(ui.whiteListIpsTable,SIGNAL(currentCellChanged(int,int,int,int)),this,SLOT(updateSelectedWhiteListIP(int,int,int,int))); - QObject::connect(ui.pbBobStart, SIGNAL(clicked()), this, SLOT(startBOB())); - QObject::connect(ui.pbBobRestart, SIGNAL(clicked()), this, SLOT(restartBOB())); - QObject::connect(ui.pbBobStop, SIGNAL(clicked()), this, SLOT(stopBOB())); + QObject::connect(ui.pbBobStart, SIGNAL(clicked()), this, SLOT(startSam())); + QObject::connect(ui.pbBobRestart, SIGNAL(clicked()), this, SLOT(restartSam())); + QObject::connect(ui.pbBobStop, SIGNAL(clicked()), this, SLOT(stopSam())); QObject::connect(ui.pbBobGenAddr, SIGNAL(clicked()), this, SLOT(getNewKey())); QObject::connect(ui.pbBobLoadKey, SIGNAL(clicked()), this, SLOT(loadKey())); - QObject::connect(ui.cb_enableBob, SIGNAL(toggled(bool)), this, SLOT(enableBob(bool))); + QObject::connect(ui.cb_enableBob, SIGNAL(toggled(bool)), this, SLOT(enableSam(bool))); - QObject::connect(ui.cbBobAdvanced, SIGNAL(toggled(bool)), this, SLOT(toggleBobAdvancedSettings(bool))); + QObject::connect(ui.cbBobAdvanced, SIGNAL(toggled(bool)), this, SLOT(toggleSamAdvancedSettings(bool))); QObject::connect(ui.sbBobLengthIn, SIGNAL(valueChanged(int)), this, SLOT(tunnelSettingsChanged(int))); QObject::connect(ui.sbBobLengthOut, SIGNAL(valueChanged(int)), this, SLOT(tunnelSettingsChanged(int))); @@ -182,23 +198,19 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) QObject::connect(ui.sbBobVarianceIn, SIGNAL(valueChanged(int)), this, SLOT(tunnelSettingsChanged(int))); QObject::connect(ui.sbBobVarianceOut, SIGNAL(valueChanged(int)), this, SLOT(tunnelSettingsChanged(int))); - // These two spin boxes are used for the same thing - keep them in sync! - QObject::connect(ui.hiddenpage_proxyPort_i2p, SIGNAL(valueChanged(int)), this, SLOT(syncI2PProxyPortNormal(int))); - QObject::connect(ui.hiddenpage_proxyPort_i2p_2, SIGNAL(valueChanged(int)), this, SLOT(syncI2PProxyPortBob(int))); - // These two line edits are used for the same thing - keep them in sync! QObject::connect(ui.hiddenpage_proxyAddress_i2p, SIGNAL(textChanged(QString)), this, SLOT(syncI2PProxyAddrNormal(QString))); - QObject::connect(ui.hiddenpage_proxyAddress_i2p_2, SIGNAL(textChanged(QString)), this, SLOT(syncI2PProxyAddrBob(QString))); + QObject::connect(ui.hiddenpage_proxyAddress_i2p_2, SIGNAL(textChanged(QString)), this, SLOT(syncI2PProxyAddrSam(QString))); connect(NotifyQt::getInstance(), SIGNAL(connectionWithoutCert()), this, SLOT(connectionWithoutCert())); QObject::connect(ui.localPort,SIGNAL(valueChanged(int)),this,SLOT(saveAddresses())); QObject::connect(ui.extPort,SIGNAL(valueChanged(int)),this,SLOT(saveAddresses())); - connect( ui.netModeComboBox, SIGNAL( activated ( int ) ), this, SLOT( toggleUPnP( ) ) ); - connect( ui.allowIpDeterminationCB, SIGNAL( toggled( bool ) ), this, SLOT( toggleIpDetermination(bool) ) ); - connect( ui.cleanKnownIPs_PB, SIGNAL( clicked( ) ), this, SLOT( clearKnownAddressList() ) ); - connect( ui.testIncoming_PB, SIGNAL( clicked( ) ), this, SLOT( saveAndTestInProxy() ) ); + connect( ui.netModeComboBox, SIGNAL( activated(int) ), this, SLOT( toggleUPnP() ) ); + connect( ui.allowIpDeterminationCB, SIGNAL( toggled(bool) ), this, SLOT( toggleIpDetermination(bool) ) ); + connect( ui.cleanKnownIPs_PB, SIGNAL( clicked() ), this, SLOT( clearKnownAddressList() ) ); + connect( ui.testIncoming_PB, SIGNAL( clicked() ), this, SLOT( saveAndTestInProxy() ) ); #ifdef SERVER_DEBUG std::cerr << "ServerPage::ServerPage() called"; @@ -207,15 +219,16 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) connect(ui.discComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(saveAddresses())); connect(ui.netModeComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(saveAddresses())); - connect(ui.localAddress, SIGNAL(textChanged(QString)),this,SLOT(saveAddresses())); - connect(ui.extAddress, SIGNAL(textChanged(QString)),this,SLOT(saveAddresses())); - connect(ui.dynDNS, SIGNAL(textChanged(QString)),this,SLOT(saveAddresses())); + connect(ui.localAddress, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); + connect(ui.extAddress, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); + connect(ui.dynDNS, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); connect(ui.hiddenpage_proxyAddress_tor, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); connect(ui.hiddenpage_proxyPort_tor, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); connect(ui.hiddenpage_proxyAddress_i2p, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); connect(ui.hiddenpage_proxyPort_i2p, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); + connect(ui.hiddenpage_localPort, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); connect(ui.totalDownloadRate,SIGNAL(valueChanged(int)),this,SLOT(saveRates())); connect(ui.totalUploadRate, SIGNAL(valueChanged(int)),this,SLOT(saveRates())); @@ -230,7 +243,7 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) QObject::connect(ui.addPushButton,SIGNAL(clicked()),this,SLOT(addServer())); QObject::connect(ui.removePushButton,SIGNAL(clicked()),this,SLOT(removeServer())); - QObject::connect(ui.DhtLineEdit,SIGNAL(textChanged(const QString &)),this,SLOT(checkKey())); + QObject::connect(ui.DhtLineEdit,SIGNAL(textChanged(QString)),this,SLOT(checkKey())); QObject::connect(ui.enableCheckBox,SIGNAL(stateChanged(int)),this,SLOT(updateEnabled())); QObject::connect(ui.serverCheckBox,SIGNAL(stateChanged(int)),this,SLOT(updateEnabled())); @@ -373,7 +386,7 @@ void ServerPage::load() } mIsHiddenNode = (detail.netMode == RS_NETMODE_HIDDEN); - rsAutoProxyMonitor::taskSync(autoProxyType::I2PBOB, autoProxyTask::getSettings, &mBobSettings); + rsAutoProxyMonitor::taskSync(autoProxyType::I2PSAM3, autoProxyTask::getSettings, &mSamSettings); loadCommon(); updateStatus(); @@ -435,8 +448,8 @@ void ServerPage::load() { if (detail.vs_disc != RS_VS_DISC_OFF) netIndex = 1; // PRIVATE - else - netIndex = 3; // NONE + //else //Use default value + // netIndex = 3; // NONE } whileBlocking(ui.discComboBox)->setCurrentIndex(netIndex); @@ -461,6 +474,7 @@ void ServerPage::load() whileBlocking(ui.ipAddressList)->clear(); + detail.ipAddressList.sort(); for(std::list::const_iterator it(detail.ipAddressList.begin());it!=detail.ipAddressList.end();++it) whileBlocking(ui.ipAddressList)->addItem(QString::fromStdString(*it)); @@ -826,10 +840,10 @@ void ServerPage::ipWhiteListContextMenu(const QPoint& /* point */) return ; } - QString range0 = RsNetUtil::printAddrRange(addr,0) ; - QString range1 = RsNetUtil::printAddrRange(addr,1) ; - QString range2 = RsNetUtil::printAddrRange(addr,2) ; - +// QString range0 = RsNetUtil::printAddrRange(addr,0) ; +// QString range1 = RsNetUtil::printAddrRange(addr,1) ; +// QString range2 = RsNetUtil::printAddrRange(addr,2) ; +// // contextMenu.addAction(QObject::tr("Whitelist only IP " )+range0,this,SLOT(enableBannedIp()))->setEnabled(false) ; //#warning UNIMPLEMENTED CODE // contextMenu.addAction(QObject::tr("Whitelist entire range ")+range1,this,SLOT(enableBannedIp()))->setEnabled(false) ; @@ -870,9 +884,9 @@ void ServerPage::updateStatus() loadFilteredIps() ; - updateStatusBob(); + updateStatusSam(); - // this is used by BOB + // this is used by SAM if (mOngoingConnectivityCheck > 0) { mOngoingConnectivityCheck--; @@ -932,6 +946,28 @@ void ServerPage::updateStatus() else ui.iconlabel_ext->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/ledoff1.png")); + if (ui.ipAddressList->isEnabled() ) + { + whileBlocking(ui.ipAddressList)->clear(); + detail.ipAddressList.sort(); + for(auto& it : detail.ipAddressList) + whileBlocking(ui.ipAddressList)->addItem(QString::fromStdString(it).replace("sec",tr("sec")).replace("loc",tr("local")).replace("ext",tr("external"))); + } + + QString toolTip = tr("List of OpenDns servers used."); + if (ui.IPServersLV->isEnabled() ) + { + std::list ip_list; + rsPeers->getCurrentExtIPList(ip_list); + if ( !ip_list.empty() ) + { + toolTip += tr("\n\nList of found external IP:\n"); + for(std::list::const_iterator it(ip_list.begin());it!=ip_list.end();++it) + toolTip += " " + QString::fromStdString(*it) +"\n" ; + } + } + if(ui.IPServersLV->toolTip() != toolTip) + ui.IPServersLV->setToolTip(toolTip); } void ServerPage::toggleUPnP() @@ -1098,24 +1134,24 @@ void ServerPage::loadHiddenNode() ui.iconlabel_upnp->hide(); ui.label_nat->hide(); - ui.label_warningBandwidth->hide(); + ui.info_warningBandwidth->hide(); ui.iconlabel_netLimited->hide(); ui.textlabel_netLimited->hide(); ui.iconlabel_ext->hide(); ui.textlabel_ext->hide(); ui.extPortLabel->hide(); - + ui.ipAddressLabel->hide(); ui.cleanKnownIPs_PB->hide(); - + ui.ipAddressList->hide(); ui.allowIpDeterminationCB->hide(); ui.IPServersLV->hide(); - + ui.textlabel_hiddenMode->show(); ui.iconlabel_hiddenMode->show() ; ui.iconlabel_hiddenMode->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/ledon1.png")); - + // CHANGE OPTIONS ON whileBlocking(ui.discComboBox)->removeItem(3); whileBlocking(ui.discComboBox)->removeItem(2); @@ -1160,6 +1196,7 @@ void ServerPage::loadHiddenNode() // show what we have in ipAddresses. (should be nothing!) ui.ipAddressList->clear(); + detail.ipAddressList.sort(); for(std::list::const_iterator it(detail.ipAddressList.begin());it!=detail.ipAddressList.end();++it) whileBlocking(ui.ipAddressList)->addItem(QString::fromStdString(*it)); @@ -1333,6 +1370,7 @@ void ServerPage::saveAddressesHiddenNode() void ServerPage::updateOutProxyIndicator() { + MainWindow::getInstance()->torstatusReset(); QTcpSocket socket ; // Tor @@ -1349,32 +1387,50 @@ void ServerPage::updateOutProxyIndicator() ui.iconlabel_tor_outgoing->setToolTip(tr("Tor proxy is not enabled")) ; } - // I2P - socket.connectToHost(ui.hiddenpage_proxyAddress_i2p->text(),ui.hiddenpage_proxyPort_i2p->text().toInt()); - if(socket.waitForConnected(500)) - { - socket.disconnectFromHost(); - ui.iconlabel_i2p_outgoing->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_OK)) ; - ui.iconlabel_i2p_outgoing->setToolTip(tr("Proxy seems to work.")) ; - } - else - { - ui.iconlabel_i2p_outgoing->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_UNKNOWN)) ; - ui.iconlabel_i2p_outgoing->setToolTip(tr("I2P proxy is not enabled")) ; - } - - // I2P - BOB - socket.connectToHost(ui.hiddenpage_proxyAddress_i2p_2->text(), 2827); - if(true == (mBobAccessible = socket.waitForConnected(500))) + if (mHiddenType == RS_HIDDEN_TYPE_I2P && mSamSettings.enable) + { + // I2P - SAM + // Note: there is only "the SAM port", there is no additional proxy port! + samStatus ss; + rsAutoProxyMonitor::taskSync(autoProxyType::I2PSAM3, autoProxyTask::status, &ss); + if(ss.state == samStatus::samState::online) + { + socket.disconnectFromHost(); + ui.iconlabel_i2p_outgoing->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_OK)) ; + ui.iconlabel_i2p_outgoing->setToolTip(tr("Proxy seems to work.")) ; + } + else + { + ui.iconlabel_i2p_outgoing->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_UNKNOWN)) ; + ui.iconlabel_i2p_outgoing->setToolTip(tr("I2P proxy is not enabled")) ; + } + } + else + { + socket.connectToHost(ui.hiddenpage_proxyAddress_i2p->text(),ui.hiddenpage_proxyPort_i2p->text().toInt()); + if(socket.waitForConnected(500)) + { + socket.disconnectFromHost(); + ui.iconlabel_i2p_outgoing->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_OK)) ; + ui.iconlabel_i2p_outgoing->setToolTip(tr("Proxy seems to work.")) ; + } + else + { + ui.iconlabel_i2p_outgoing->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_UNKNOWN)) ; + ui.iconlabel_i2p_outgoing->setToolTip(tr("I2P proxy is not enabled")) ; + } + } + socket.connectToHost(ui.hiddenpage_proxyAddress_i2p_2->text(), 7656); + if(true == (mSamAccessible = socket.waitForConnected(1000))) { socket.disconnectFromHost(); ui.iconlabel_i2p_outgoing_2->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_OK)) ; - ui.iconlabel_i2p_outgoing_2->setToolTip(tr("BOB is running and accessible")) ; + ui.iconlabel_i2p_outgoing_2->setToolTip(tr("SAMv3 is running and accessible")) ; } else { ui.iconlabel_i2p_outgoing_2->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_UNKNOWN)) ; - ui.iconlabel_i2p_outgoing_2->setToolTip(tr("BOB is not accessible! Is it running?")) ; + ui.iconlabel_i2p_outgoing_2->setToolTip(tr("SAMv3 is not accessible! Is i2p running and SAM enabled?")) ; } } @@ -1385,28 +1441,18 @@ void ServerPage::updateInProxyIndicator() if(!mIsHiddenNode) return ; - //ui.iconlabel_tor_incoming->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_UNKNOWN)) ; + //ui.iconlabel_tor_incoming->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_UNKNOWN)) ; //ui.testIncomingTor_PB->setIcon(FilesDefs::getIconFromQtResourcePath(":/loader/circleball-16.gif")) ; QMovie *movie = new QMovie(":/images/loader/circleball-16.gif"); ui.iconlabel_service_incoming->setMovie(movie); movie->start(); - if (mHiddenType == RS_HIDDEN_TYPE_I2P && mBobSettings.enable) { - - QTcpSocket tcpSocket; - - const QString host = ui.hiddenpage_proxyAddress_i2p->text(); - qint16 port = ui.hiddenpage_proxyPort_i2p->text().toInt(); - QByteArray addr = ui.leBobB32Addr->text().toUtf8(); - addr.push_back('\n'); - - mOngoingConnectivityCheck = 5; // timeout in sec - - tcpSocket.connectToHost(host, port); - tcpSocket.write(addr); // write addr - tcpSocket.write(addr); // trigger connection error since RS expects a tls connection - tcpSocket.close(); - tcpSocket.waitForDisconnected(5 * 1000); + if (mHiddenType == RS_HIDDEN_TYPE_I2P && mSamSettings.enable) { + // there is no inproxy for SAMv3, since every connection goes through sam itself + auto secw = new samEstablishConnectionWrapper(); + secw->address = mSamSettings.address; + secw->connection = nullptr; + rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::establishConnection, this, secw); return; } @@ -1419,18 +1465,10 @@ void ServerPage::updateInProxyIndicator() QNetworkProxy proxy ; proxy.setType(QNetworkProxy::Socks5Proxy); - switch (mHiddenType) { - case RS_HIDDEN_TYPE_I2P: - proxy.setHostName(ui.hiddenpage_proxyAddress_i2p->text()); - proxy.setPort(ui.hiddenpage_proxyPort_i2p->text().toInt()); - break; - case RS_HIDDEN_TYPE_TOR: - proxy.setHostName(ui.hiddenpage_proxyAddress_tor->text()); - proxy.setPort(ui.hiddenpage_proxyPort_tor->text().toInt()); - break; - default: - return; - } + + proxy.setHostName(ui.hiddenpage_proxyAddress_tor->text()); + proxy.setPort(ui.hiddenpage_proxyPort_tor->text().toInt()); + proxy.setCapabilities(QNetworkProxy::HostNameLookupCapability | proxy.capabilities()) ; QNetworkProxy::setApplicationProxy(proxy) ; @@ -1445,53 +1483,58 @@ void ServerPage::updateInProxyIndicator() QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy) ; } -void ServerPage::startBOB() +void ServerPage::startSam() { - rsAutoProxyMonitor::taskAsync(autoProxyType::I2PBOB, autoProxyTask::start); + rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::start); updateStatus(); } -void ServerPage::restartBOB() +void ServerPage::restartSam() { - rsAutoProxyMonitor::taskAsync(autoProxyType::I2PBOB, autoProxyTask::stop); - rsAutoProxyMonitor::taskAsync(autoProxyType::I2PBOB, autoProxyTask::start); + rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::stop); + rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::start); updateStatus(); } -void ServerPage::stopBOB() +void ServerPage::stopSam() { - rsAutoProxyMonitor::taskAsync(autoProxyType::I2PBOB, autoProxyTask::stop); + rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::stop); updateStatus(); } void ServerPage::getNewKey() { - bobSettings *bs = new bobSettings(); - - rsAutoProxyMonitor::taskAsync(autoProxyType::I2PBOB, autoProxyTask::receiveKey, this, bs); - - updateStatus(); + i2p::address *addr = new i2p::address(); + rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::receiveKey, this, addr); } void ServerPage::loadKey() { - mBobSettings.address.privateKey = ui.pteBobServerKey->toPlainText().toStdString(); - mBobSettings.address.publicKey = i2p::publicKeyFromPrivate(mBobSettings.address.privateKey); - mBobSettings.address.base32 = i2p::keyToBase32Addr(mBobSettings.address.publicKey); + auto priv = ui.pteBobServerKey->toPlainText().toStdString(); + auto pub = i2p::publicKeyFromPrivate(priv); + if (pub.empty()) { + // something went wrong! + ui.pteBobServerKey->setPlainText("FAILED! Something went wrong while parsing the key!"); + return; + } - rsAutoProxyMonitor::taskSync(autoProxyType::I2PBOB, autoProxyTask::setSettings, &mBobSettings); + mSamSettings.address.privateKey = priv; + mSamSettings.address.publicKey = pub; + mSamSettings.address.base32 = i2p::keyToBase32Addr(mSamSettings.address.publicKey); + + rsAutoProxyMonitor::taskSync(autoProxyType::I2PSAM3, autoProxyTask::setSettings, &mSamSettings); } -void ServerPage::enableBob(bool checked) +void ServerPage::enableSam(bool checked) { - mBobSettings.enable = checked; + mSamSettings.enable = checked; - rsAutoProxyMonitor::taskSync(autoProxyType::I2PBOB, autoProxyTask::setSettings, &mBobSettings); + rsAutoProxyMonitor::taskSync(autoProxyType::I2PSAM3, autoProxyTask::setSettings, &mSamSettings); - setUpBobElements(); + setUpSamElements(); } int8_t fitRange(int i, int min, int max) { @@ -1513,21 +1556,21 @@ void ServerPage::tunnelSettingsChanged(int) vi = ui.sbBobVarianceIn->value(); vo = ui.sbBobVarianceOut->value(); - mBobSettings.inLength = fitRange(li, 0, 7); - mBobSettings.outLength = fitRange(lo, 0, 7); - mBobSettings.inQuantity = fitRange(qi, 1, 16); - mBobSettings.outQuantity = fitRange(qo, 1, 16); - mBobSettings.inVariance = fitRange(vi, -1, 2); - mBobSettings.outVariance = fitRange(vo, -1, 2); + mSamSettings.inLength = fitRange(li, 0, 7); + mSamSettings.outLength = fitRange(lo, 0, 7); + mSamSettings.inQuantity = fitRange(qi, 1, 16); + mSamSettings.outQuantity = fitRange(qo, 1, 16); + mSamSettings.inVariance = fitRange(vi, -1, 2); + mSamSettings.outVariance = fitRange(vo, -1, 2); - rsAutoProxyMonitor::taskSync(autoProxyType::I2PBOB, autoProxyTask::setSettings, &mBobSettings); + rsAutoProxyMonitor::taskSync(autoProxyType::I2PSAM3, autoProxyTask::setSettings, &mSamSettings); } -void ServerPage::toggleBobAdvancedSettings(bool checked) +void ServerPage::toggleSamAdvancedSettings(bool checked) { ui.swBobAdvanced->setCurrentIndex(checked ? 1 : 0); - if (!mBobSettings.address.privateKey.empty()) { + if (!mSamSettings.address.privateKey.empty()) { if (checked) { ui.pbBobGenAddr->show(); } else { @@ -1536,57 +1579,91 @@ void ServerPage::toggleBobAdvancedSettings(bool checked) } } -void ServerPage::syncI2PProxyPortNormal(int i) -{ - ui.hiddenpage_proxyPort_i2p_2->setValue(i); -} - -void ServerPage::syncI2PProxyPortBob(int i) -{ - ui.hiddenpage_proxyPort_i2p->setValue(i); - - // update port - saveBob(); - rsAutoProxyMonitor::taskSync(autoProxyType::I2PBOB, autoProxyTask::reloadConfig); -} - void ServerPage::syncI2PProxyAddrNormal(QString t) { ui.hiddenpage_proxyAddress_i2p_2->setText(t); } -void ServerPage::syncI2PProxyAddrBob(QString t) +void ServerPage::syncI2PProxyAddrSam(QString t) { ui.hiddenpage_proxyAddress_i2p->setText(t); // update addr - saveBob(); - rsAutoProxyMonitor::taskSync(autoProxyType::I2PBOB, autoProxyTask::reloadConfig); + saveSam(); + rsAutoProxyMonitor::taskSync(autoProxyType::I2PSAM3, autoProxyTask::reloadConfig); } void ServerPage::taskFinished(taskTicket *&ticket) { - if (ticket->task == autoProxyTask::receiveKey) { - bobSettings *s = NULL; - switch (ticket->types.front()) { - case autoProxyType::I2PBOB: - // update settings - s = (struct bobSettings *)ticket->data; - mBobSettings = *s; - delete s; - s = NULL; - ticket->data = NULL; - break; - default: - break; - } - } +#ifdef RS_USE_I2P_SAM3 + switch (ticket->task) { + case autoProxyTask::receiveKey: + { + i2p::address *addr = nullptr; + addr = static_cast(ticket->data); + + if (ticket->types.front() != autoProxyType::I2PSAM3) + RS_WARN("auto proxy task finished but not for SMA, not exptected! Also not a serious problem."); + else { + // update settings + auto copy = *addr; + RsQThreadUtils::postToObject( + [this, copy]() + { + mSamSettings.address = copy; + rsAutoProxyMonitor::taskSync(autoProxyType::I2PSAM3, autoProxyTask::setSettings, &mSamSettings); + updateStatusSam(); + + }); + } + + delete addr; + addr = nullptr; + ticket->data = nullptr; + + + break; + } + case autoProxyTask::establishConnection: + { + samEstablishConnectionWrapper *secw = nullptr; + secw = static_cast(ticket->data); + + if (ticket->types.front() != autoProxyType::I2PSAM3) + RS_WARN("auto proxy task finished but not for SMA, not exptected! Also not a serious problem."); + else { + bool res = ticket->result == autoProxyStatus::ok && !!secw->connection->ses; + // update settings + if (res) { + sam3CloseConnection(secw->connection); + secw->connection = nullptr; // freed by above call + } + + RsQThreadUtils::postToObject( + [this, res]() + { + updateInProxyIndicatorResult(res); + + }); + } + + if (secw->connection) + delete secw->connection; + delete secw; + secw = nullptr; + ticket->data = nullptr; + break; + } + default: + RS_DBG("unsupported task!", ticket->task); + } if (ticket->data) std::cerr << "(WW) ServerPage::taskFinished data set. This should NOT happen - check the code!" << std::endl; delete ticket; - ticket = NULL; + ticket = nullptr; + #endif //RS_USE_I2P_SAM3 } void ServerPage::connectionWithoutCert() @@ -1613,14 +1690,13 @@ void ServerPage::loadCommon() // I2P rsPeers->getProxyServer(RS_HIDDEN_TYPE_I2P, proxyaddr, proxyport, status); whileBlocking(ui.hiddenpage_proxyAddress_i2p) -> setText(QString::fromStdString(proxyaddr)); - whileBlocking(ui.hiddenpage_proxyAddress_i2p_2)->setText(QString::fromStdString(proxyaddr)); // this one is for bob tab + whileBlocking(ui.hiddenpage_proxyAddress_i2p_2)->setText(QString::fromStdString(proxyaddr)); // this one is for sam tab whileBlocking(ui.hiddenpage_proxyPort_i2p) -> setValue(proxyport); - whileBlocking(ui.hiddenpage_proxyPort_i2p_2)->setValue(proxyport); // this one is for bob tab // don't use whileBlocking here - ui.cb_enableBob->setChecked(mBobSettings.enable); + ui.cb_enableBob->setChecked(mSamSettings.enable); - if (!mBobSettings.address.privateKey.empty()) { + if (!mSamSettings.address.privateKey.empty()) { ui.lBobB32Addr->show(); ui.leBobB32Addr->show(); } @@ -1642,10 +1718,10 @@ void ServerPage::saveCommon() rsPeers->setProxyServer(RS_HIDDEN_TYPE_TOR, new_proxyaddr, new_proxyport); } - saveBob(); + saveSam(); } -void ServerPage::saveBob() +void ServerPage::saveSam() { std::string orig_proxyaddr, new_proxyaddr; uint16_t orig_proxyport, new_proxyport; @@ -1656,20 +1732,30 @@ void ServerPage::saveBob() new_proxyaddr = ui.hiddenpage_proxyAddress_i2p -> text().toStdString(); new_proxyport = ui.hiddenpage_proxyPort_i2p -> value(); + // SAMv3 has no proxy port, everything goes through the SAM port. + // Still need to check the proxyport for manual i2p if ((new_proxyaddr != orig_proxyaddr) || (new_proxyport != orig_proxyport)) { rsPeers->setProxyServer(RS_HIDDEN_TYPE_I2P, new_proxyaddr, new_proxyport); } } -void ServerPage::updateStatusBob() +void ServerPage::updateStatusSam() { - QString addr = QString::fromStdString(mBobSettings.address.base32); + QString addr = QString::fromStdString(mSamSettings.address.base32); if (ui.leBobB32Addr->text() != addr) { ui.leBobB32Addr->setText(addr); ui.hiddenpage_serviceAddress->setText(addr); - ui.pteBobServerKey->setPlainText(QString::fromStdString(mBobSettings.address.privateKey)); + ui.pteBobServerKey->setPlainText(QString::fromStdString(mSamSettings.address.privateKey)); - if (!mBobSettings.address.privateKey.empty()) { + std::string signingKeyType, cryptoKeyType; + if (i2p::getKeyTypes(mSamSettings.address.publicKey, signingKeyType, cryptoKeyType)) + ui.samKeyInfo->setText(tr("Your key uses the following algorithms: %1 and %2"). + arg(QString::fromStdString(signingKeyType)). + arg(QString::fromStdString(cryptoKeyType))); + else + ui.samKeyInfo->setText(tr("unkown key type")); + + if (!mSamSettings.address.privateKey.empty()) { // we have an addr -> show fields ui.lBobB32Addr->show(); ui.leBobB32Addr->show(); @@ -1686,128 +1772,82 @@ void ServerPage::updateStatusBob() ui.pbBobGenAddr->hide(); } - saveAddresses(); + saveAddresses(); } - bobStates bs; - rsAutoProxyMonitor::taskSync(autoProxyType::I2PBOB, autoProxyTask::status, &bs); + samStatus ss; + rsAutoProxyMonitor::taskSync(autoProxyType::I2PSAM3, autoProxyTask::status, &ss); QString bobSimpleText = QString(); - bobSimpleText.append(tr("RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4)\n\n" - "When changing options (e.g. port) use the buttons at the bottom to restart BOB.\n\n"). - arg(mBobSettings.address.privateKey.empty() ? tr("client") : tr("server"), + bobSimpleText.append(tr("RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3\n(id: %4)\n\n" + "When changing options use the buttons at the bottom to restart SAMv3.\n\n"). + arg(mSamSettings.address.privateKey.empty() ? tr("client") : tr("server"), ui.hiddenpage_proxyAddress_i2p_2->text(), - ui.hiddenpage_proxyPort_i2p_2->text(), - bs.tunnelName.empty() ? tr("unknown") : - QString::fromStdString(bs.tunnelName))); + "7656", + ss.sessionName.empty() ? tr("unknown") : + QString::fromStdString(ss.sessionName))); - // update BOB UI based on state - std::string errorString; - switch (bs.cs) { - case csDoConnect: - case csConnected: - case csDoDisconnect: - case csWaitForBob: - ui.iconlabel_i2p_bob->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_WORKING)); - ui.iconlabel_i2p_bob->setToolTip(tr("BOB is processing a request")); + // update SAM UI based on state + QString s; + QString icon; + switch (ss.state) { + case samStatus::samState::offline: + enableSamElements(false); - enableBobElements(false); + ui.pbBobStart->setEnabled(true); + ui.pbBobRestart->setEnabled(false); + ui.pbBobStop->setEnabled(false); - { - QString s; - switch (bs.ct) { - case ctRunCheck: - s = tr("connectivity check"); - break; - case ctRunGetKeys: - s = tr("generating key"); - break; - case ctRunSetUp: - s = tr("starting up"); - break; - case ctRunShutDown: - s = tr("shuting down"); - default: - break; - } - bobSimpleText.append(tr("BOB is processing a request: %1").arg(s)); - } + s = tr("Offline, no SAM session is established yet.\n"); + icon = ICON_STATUS_ERROR; + break; + case samStatus::samState::connectSession: + enableSamElements(false); - ui.pbBobStart->setEnabled(false); - ui.pbBobRestart->setEnabled(false); - ui.pbBobStop->setEnabled(false); - break; - case csError: - // get error msg from bob - rsAutoProxyMonitor::taskSync(autoProxyType::I2PBOB, autoProxyTask::getErrorInfo, &errorString); - - ui.iconlabel_i2p_bob->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_ERROR)); - ui.iconlabel_i2p_bob->setToolTip(tr("BOB is broken\n") + QString::fromStdString(errorString)); - - enableBobElements(false); - - bobSimpleText.append(tr("BOB encountered an error:\n")); - bobSimpleText.append(QString::fromStdString(errorString)); - - ui.pbBobStart->setEnabled(true); - ui.pbBobRestart->setEnabled(false); + ui.pbBobStart->setEnabled(false); + ui.pbBobRestart->setEnabled(false); ui.pbBobStop->setEnabled(true); - break; - case csDisconnected: - case csIdel: - switch (bs.ct) { - case ctRunSetUp: - ui.iconlabel_i2p_bob->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_OK)); - ui.iconlabel_i2p_bob->setToolTip(tr("BOB tunnel is running")); - enableBobElements(false); + s = tr("SAM is trying to establish a session ... this can take some time.\n"); + icon = ICON_STATUS_WORKING; + break; + case samStatus::samState::connectForward: + enableSamElements(false); - bobSimpleText.append(tr("BOB is working fine: tunnel established")); + ui.pbBobStart->setEnabled(false); + ui.pbBobRestart->setEnabled(false); + ui.pbBobStop->setEnabled(true); - ui.pbBobStart->setEnabled(false); - ui.pbBobRestart->setEnabled(true); - ui.pbBobStop->setEnabled(true); - break; - case ctRunCheck: - case ctRunGetKeys: - ui.iconlabel_i2p_bob->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_WORKING)); - ui.iconlabel_i2p_bob->setToolTip(tr("BOB is processing a request")); + s = tr("SAM session established! Now setting up a forward session ...\n"); + icon = ICON_STATUS_WORKING; + break; + case samStatus::samState::online: + enableSamElements(true); - enableBobElements(false); + ui.pbBobStart->setEnabled(false); + ui.pbBobRestart->setEnabled(true); + ui.pbBobStop->setEnabled(true); - bobSimpleText.append(tr("BOB is processing a request")); + s = tr("Online, SAM is working as exptected\n"); + icon = ICON_STATUS_OK; + break; + } + ui.iconlabel_i2p_bob->setPixmap(icon); + ui.iconlabel_i2p_bob->setToolTip(s); + bobSimpleText.append(s); - ui.pbBobStart->setEnabled(false); - ui.pbBobRestart->setEnabled(false); - ui.pbBobStop->setEnabled(false); - break; - case ctRunShutDown: - case ctIdle: - ui.iconlabel_i2p_bob->setPixmap(FilesDefs::getPixmapFromQtResourcePath(ICON_STATUS_UNKNOWN)); - ui.iconlabel_i2p_bob->setToolTip(tr("BOB tunnel is not running")); - enableBobElements(true); + ui.info_BobSimple->setPlainText(bobSimpleText); - bobSimpleText.append(tr("BOB is inactive: tunnel closed")); - - ui.pbBobStart->setEnabled(true); - ui.pbBobRestart->setEnabled(false); - ui.pbBobStop->setEnabled(false); - break; - } - break; - - } - ui.pteBobSimple->setPlainText(bobSimpleText); // disable elements when BOB is not accessible - if (!mBobAccessible) { + if (!mSamAccessible) { ui.pbBobStart->setEnabled(false); - ui.pbBobStart->setToolTip("BOB is not accessible"); + ui.pbBobStart->setToolTip("SAMv3 is not accessible"); ui.pbBobRestart->setEnabled(false); - ui.pbBobRestart->setToolTip("BOB is not accessible"); - // don't disable the stop button! (in case bob is running you are otherwise unable to stop and disable it) - ui.pbBobStop->setToolTip("BOB is not accessible"); + ui.pbBobRestart->setToolTip("SAMv3 is not accessible"); + // don't disable the stop button! (in case SAM is running you are otherwise unable to stop and disable it) + ui.pbBobStop->setToolTip("SAMv3 is not accessible"); } else { ui.pbBobStart->setToolTip(""); ui.pbBobRestart->setToolTip(""); @@ -1815,26 +1855,34 @@ void ServerPage::updateStatusBob() } } -void ServerPage::setUpBobElements() +void ServerPage::setUpSamElements() { - ui.gbBob->setEnabled(mBobSettings.enable); - if (mBobSettings.enable) { + ui.gbBob->setEnabled(mSamSettings.enable); + if (mSamSettings.enable) { ui.hiddenpage_proxyAddress_i2p->setEnabled(false); - ui.hiddenpage_proxyAddress_i2p->setToolTip("Use I2P/BOB settings to change this value"); + ui.hiddenpage_proxyAddress_i2p->setToolTip("Use I2P settings to change this value"); ui.hiddenpage_proxyPort_i2p->setEnabled(false); - ui.hiddenpage_proxyPort_i2p->setToolTip("Use I2P/BOB settings to change this value"); + ui.hiddenpage_proxyPort_i2p->setToolTip("Use I2P settings to change this value"); - ui.leBobB32Addr->setText(QString::fromStdString(mBobSettings.address.base32)); - ui.pteBobServerKey->setPlainText(QString::fromStdString(mBobSettings.address.privateKey)); + ui.leBobB32Addr->setText(QString::fromStdString(mSamSettings.address.base32)); + ui.pteBobServerKey->setPlainText(QString::fromStdString(mSamSettings.address.privateKey)); + + std::string signingKeyType, cryptoKeyType; + if (i2p::getKeyTypes(mSamSettings.address.publicKey, signingKeyType, cryptoKeyType)) + ui.samKeyInfo->setText(tr("You key uses %1 for signing and %2 for crypto"). + arg(QString::fromStdString(signingKeyType)). + arg(QString::fromStdString(cryptoKeyType))); + else + ui.samKeyInfo->setText(tr("unkown key type")); // cast to int to avoid problems int li, lo, qi, qo, vi, vo; - li = mBobSettings.inLength; - lo = mBobSettings.outLength; - qi = mBobSettings.inQuantity; - qo = mBobSettings.outQuantity; - vi = mBobSettings.inVariance; - vo = mBobSettings.outVariance; + li = mSamSettings.inLength; + lo = mSamSettings.outLength; + qi = mSamSettings.inQuantity; + qo = mSamSettings.outQuantity; + vi = mSamSettings.inVariance; + vo = mSamSettings.outVariance; ui.sbBobLengthIn ->setValue(li); ui.sbBobLengthOut ->setValue(lo); @@ -1850,7 +1898,7 @@ void ServerPage::setUpBobElements() } } -void ServerPage::enableBobElements(bool enable) +void ServerPage::enableSamElements(bool enable) { if (enable) { ui.pbBobGenAddr->setEnabled(true); @@ -1863,13 +1911,13 @@ void ServerPage::enableBobElements(bool enable) ui.cb_enableBob->setToolTip(tr("")); } else { ui.pbBobGenAddr->setEnabled(false); - ui.pbBobGenAddr->setToolTip(tr("stop BOB tunnel first to generate a new key")); + ui.pbBobGenAddr->setToolTip(tr("stop SAM tunnel first to generate a new key")); ui.pbBobLoadKey->setEnabled(false); - ui.pbBobLoadKey->setToolTip(tr("stop BOB tunnel first to load a key")); + ui.pbBobLoadKey->setToolTip(tr("stop SAM tunnel first to load a key")); ui.cb_enableBob->setEnabled(false); - ui.cb_enableBob->setToolTip(tr("stop BOB tunnel first to disable BOB")); + ui.cb_enableBob->setToolTip(tr("stop SAM tunnel first to disable SAM")); } } @@ -1896,6 +1944,7 @@ void ServerPage::handleNetworkReply(QNetworkReply *reply) { int error = reply->error() ; + RS_INFO("error:", error); if(reply->isOpen() && error == QNetworkReply::SslHandshakeFailedError) updateInProxyIndicatorResult(true); else diff --git a/retroshare-gui/src/gui/settings/ServerPage.h b/retroshare-gui/src/gui/settings/ServerPage.h index de971881b..7d82f2190 100755 --- a/retroshare-gui/src/gui/settings/ServerPage.h +++ b/retroshare-gui/src/gui/settings/ServerPage.h @@ -34,7 +34,7 @@ #endif #include -#include +#include #include "retroshare-gui/configpage.h" #include "retroshare-gui/RsAutoUpdatePage.h" @@ -97,22 +97,19 @@ private slots: void handleNetworkReply(QNetworkReply *reply); void updateInProxyIndicator(); - // i2p bob - void startBOB(); - void restartBOB(); - void stopBOB(); + // i2p SAMv3 + void startSam(); + void restartSam(); + void stopSam(); void getNewKey(); void loadKey(); - void enableBob(bool checked); + void enableSam(bool checked); void tunnelSettingsChanged(int); - void toggleBobAdvancedSettings(bool checked); - - void syncI2PProxyPortNormal(int i); - void syncI2PProxyPortBob(int i); + void toggleSamAdvancedSettings(bool checked); void syncI2PProxyAddrNormal(QString); - void syncI2PProxyAddrBob(QString); + void syncI2PProxyAddrSam(QString); void connectionWithoutCert(); @@ -133,11 +130,11 @@ public: private: void loadCommon(); void saveCommon(); - void saveBob(); - void updateStatusBob(); + void saveSam(); + void updateStatusSam(); - void setUpBobElements(); - void enableBobElements(bool enable); + void setUpSamElements(); + void enableSamElements(bool enable); void updateInProxyIndicatorResult(bool success); @@ -160,8 +157,8 @@ private: bool mIsHiddenNode; uint32_t mHiddenType; - bobSettings mBobSettings; - bool mBobAccessible; // keeps track wether bob is accessable or not to en/disable the corresponding buttons + samSettings mSamSettings; + bool mSamAccessible; // keeps track wether SAM is accessable or not to en/disable the corresponding buttons RsEventsHandlerId_t mEventHandlerId; void handleEvent(std::shared_ptr event); diff --git a/retroshare-gui/src/gui/settings/ServerPage.ui b/retroshare-gui/src/gui/settings/ServerPage.ui index 5ef7308b1..93eb82637 100755 --- a/retroshare-gui/src/gui/settings/ServerPage.ui +++ b/retroshare-gui/src/gui/settings/ServerPage.ui @@ -6,8 +6,8 @@ 0 0 - 712 - 502 + 738 + 579
    @@ -195,7 +195,7 @@
    - + Automatic (UPnP) @@ -214,7 +214,7 @@ - + 200 @@ -256,11 +256,14 @@ - - - 16 - 16 - + + + 0 + 0 + + + + Qt::LeftToRight @@ -272,6 +275,12 @@ + + + 0 + 0 + + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> @@ -290,13 +299,29 @@ 6 + + + + + 0 + 0 + + + + Local network + + + - - - 16 - 16 - + + + 0 + 0 + + + + Qt::LeftToRight @@ -306,13 +331,6 @@ - - - - Local network - - - @@ -351,13 +369,29 @@ 6 + + + + + 0 + 0 + + + + UPnP + + + - - - 16 - 16 - + + + 0 + 0 + + + + Qt::LeftToRight @@ -367,13 +401,6 @@ - - - - UPnP - - - @@ -386,11 +413,14 @@ - - - 16 - 16 - + + + 0 + 0 + + + + Qt::LeftToRight @@ -402,6 +432,12 @@ + + + 0 + 0 + + 75 @@ -416,7 +452,224 @@ - + + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 154 + 154 + 154 + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + border: 1px solid #DCDC41; border-radius: 6px; @@ -487,7 +740,7 @@ connecting when you have few friends. It also helps if you're behind a firewall or a VPN. - Allow RetroShare to ask my ip to these websites: + Allow RetroShare to ask my ip to these DNS servers: true @@ -502,6 +755,9 @@ behind a firewall or a VPN. 0 + + List of OpenDns servers used. + QAbstractItemView::NoEditTriggers @@ -582,12 +838,6 @@ behind a firewall or a VPN. - - - 16 - 16 - - @@ -665,7 +915,7 @@ behind a firewall or a VPN. - + 0 @@ -861,7 +1111,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + 0 @@ -908,9 +1158,9 @@ If you have issues connecting over Tor check the Tor logs too. - + - Automatic I2P/BOB + Automatic I2P @@ -918,7 +1168,7 @@ If you have issues connecting over Tor check the Tor logs too. - Enable I2P BOB - changing this requires a restart to fully take effect + Enable I2P SAMv3 - changing this requires a restart to fully take effect @@ -950,7 +1200,7 @@ If you have issues connecting over Tor check the Tor logs too. - I2P Basic Open Bridge + I2P Simple Anonymous Messaging @@ -982,21 +1232,17 @@ If you have issues connecting over Tor check the Tor logs too. - - - I2P proxy port + + + Qt::Horizontal - - - - - - 10 + + + 40 + 20 + - - 65535 - - + @@ -1016,7 +1262,7 @@ If you have issues connecting over Tor check the Tor logs too. <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - BOB accessible + SAM accessible @@ -1073,12 +1319,12 @@ If you have issues connecting over Tor check the Tor logs too. true - 1 + 0 - + 0 @@ -1304,6 +1550,13 @@ If you have issues connecting over Tor check the Tor logs too. + + + + <key info> + + + @@ -1359,7 +1612,7 @@ If you have issues connecting over Tor check the Tor logs too. - BOB status + SAM status @@ -1959,13 +2212,230 @@ If you have issues connecting over Tor check the Tor logs too. - + 0 0 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 154 + 154 + 154 + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + border: 1px solid #DCDC41; border-radius: 6px; @@ -2037,13 +2507,230 @@ If you have issues connecting over Tor check the Tor logs too. - + 0 0 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 154 + 154 + 154 + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + + + + 255 + 255 + 215 + + + + + 255 + 255 + 178 + + + + + + + + border: 1px solid #DCDC41; border-radius: 6px; @@ -2080,6 +2767,13 @@ If you have issues connecting over Tor check the Tor logs too. + + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    +
    localAddress localPort diff --git a/retroshare-gui/src/gui/settings/ServicePermissionsPage.cpp b/retroshare-gui/src/gui/settings/ServicePermissionsPage.cpp index 15a0bf70f..84df07589 100644 --- a/retroshare-gui/src/gui/settings/ServicePermissionsPage.cpp +++ b/retroshare-gui/src/gui/settings/ServicePermissionsPage.cpp @@ -35,10 +35,10 @@ ServicePermissionsPage::ServicePermissionsPage(QWidget * parent, Qt::WindowFlags ui.cb_hideOffline->setChecked(true); - connect(ui.cb_hideOffline, SIGNAL(toggled(bool)), ui.frame, SLOT(setHideOffline(bool))); + connect(ui.cb_hideOffline, SIGNAL(toggled(bool)), ui.gradFrame, SLOT(setHideOffline(bool))); //QObject::connect(ui.tableWidget,SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(tableItemChanged(QTableWidgetItem *))); - ui.frame->setHideOffline(ui.cb_hideOffline->isChecked()); + ui.gradFrame->setHideOffline(ui.cb_hideOffline->isChecked()); // Not implemented? ui.pushButton->hide(); diff --git a/retroshare-gui/src/gui/settings/ServicePermissionsPage.ui b/retroshare-gui/src/gui/settings/ServicePermissionsPage.ui index 488ba9518..2dd6f7bc1 100644 --- a/retroshare-gui/src/gui/settings/ServicePermissionsPage.ui +++ b/retroshare-gui/src/gui/settings/ServicePermissionsPage.ui @@ -10,7 +10,7 @@ 331 - + @@ -45,16 +45,16 @@ 0 - + - + - + ServicePermissions @@ -71,7 +71,7 @@ - + Qt::Horizontal diff --git a/retroshare-gui/src/gui/settings/TransferPage.cpp b/retroshare-gui/src/gui/settings/TransferPage.cpp index 2faa8d5f7..5b3b49908 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.cpp +++ b/retroshare-gui/src/gui/settings/TransferPage.cpp @@ -30,6 +30,7 @@ #include "retroshare/rspeers.h" #include +#include #include #include @@ -40,19 +41,29 @@ TransferPage::TransferPage(QWidget * parent, Qt::WindowFlags flags) /* Invoke the Qt Designer generated object setup routine */ ui.setupUi(this); + int max_tr_low,max_tr_high; + rsTurtle->getMaxTRForwardRateLimits(max_tr_low,max_tr_high); + + ui._max_tr_up_per_sec_SB->setMinimum(max_tr_low); + ui._max_tr_up_per_sec_SB->setMaximum(max_tr_high); + + whileBlocking(ui._trustFriendNodesWithBannedFiles_CB)->setChecked(rsFiles->trustFriendNodesWithBannedFiles()); + QObject::connect(ui._queueSize_SB,SIGNAL(valueChanged(int)),this,SLOT(updateQueueSize(int))) ; QObject::connect(ui._max_up_SB,SIGNAL(valueChanged(int)),this,SLOT(updateMaxUploadSlots(int))) ; QObject::connect(ui._defaultStrategy_CB,SIGNAL(activated(int)),this,SLOT(updateDefaultStrategy(int))) ; - QObject::connect(ui._e2e_encryption_CB,SIGNAL(activated(int)),this,SLOT(updateEncryptionPolicy(int))) ; + //QObject::connect(ui._e2e_encryption_CB,SIGNAL(activated(int)),this,SLOT(updateEncryptionPolicy(int))) ; QObject::connect(ui._diskSpaceLimit_SB,SIGNAL(valueChanged(int)),this,SLOT(updateDiskSizeLimit(int))) ; QObject::connect(ui._max_tr_up_per_sec_SB, SIGNAL( valueChanged( int ) ), this, SLOT( updateMaxTRUpRate(int) ) ); QObject::connect(ui._filePermDirectDL_CB,SIGNAL(activated(int)),this,SLOT(updateFilePermDirectDL(int))); + QObject::connect(ui._trustFriendNodesWithBannedFiles_CB,SIGNAL(toggled(bool)),this,SLOT(toggleTrustFriendNodesWithBannedFiles(bool))) ; QObject::connect(ui.incomingButton, SIGNAL(clicked( bool ) ), this , SLOT( setIncomingDirectory() ) ); QObject::connect(ui.autoDLColl_CB, SIGNAL(toggled(bool)), this, SLOT(updateAutoDLColl())); QObject::connect(ui.partialButton, SIGNAL(clicked( bool ) ), this , SLOT( setPartialsDirectory() ) ); QObject::connect(ui.editShareButton, SIGNAL(clicked()), this, SLOT(editDirectories())); QObject::connect(ui.autoCheckDirectories_CB, SIGNAL(clicked(bool)), this, SLOT(toggleAutoCheckDirectories(bool))); + QObject::connect(ui.minimumFontSize_SB, SIGNAL(valueChanged(int)), this, SLOT(updateFontSize())) ; QObject::connect(ui.autoCheckDirectories_CB, SIGNAL(toggled(bool)), this,SLOT(updateAutoCheckDirectories())) ; QObject::connect(ui.autoCheckDirectoriesDelay_SB,SIGNAL(valueChanged(int)),this,SLOT(updateAutoScanDirectoriesPeriod())) ; @@ -87,7 +98,10 @@ void TransferPage::updateIgnoreLists() std::cerr << " suffixes: " ; for(auto it(ls.begin());it!=ls.end();++it) std::cerr << "\"" << *it << "\" " ; std::cerr << std::endl; #endif } - +void TransferPage::toggleTrustFriendNodesWithBannedFiles(bool b) +{ + rsFiles->setTrustFriendNodesWithBannedFiles(b); +} void TransferPage::updateMaxTRUpRate(int b) { rsTurtle->setMaxTRForwardRate(b) ; @@ -98,6 +112,7 @@ void TransferPage::updateMaxUploadSlots(int b) rsFiles->setMaxUploadSlotsPerFriend(b) ; } +#ifdef TO_REMOVE void TransferPage::updateEncryptionPolicy(int b) { switch(b) @@ -109,6 +124,7 @@ void TransferPage::updateEncryptionPolicy(int b) break ; } } +#endif void TransferPage::updateFilePermDirectDL(int i) { @@ -146,11 +162,13 @@ void TransferPage::load() case FileChunksInfo::CHUNK_STRATEGY_RANDOM: whileBlocking(ui._defaultStrategy_CB)->setCurrentIndex(2) ; break ; } +#ifdef TO_REMOVE switch(rsFiles->defaultEncryptionPolicy()) { case RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE: whileBlocking(ui._e2e_encryption_CB)->setCurrentIndex(0) ; break ; case RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT : whileBlocking(ui._e2e_encryption_CB)->setCurrentIndex(1) ; break ; } +#endif whileBlocking(ui._diskSpaceLimit_SB)->setValue(rsFiles->freeDiskSpaceLimit()) ; whileBlocking(ui._max_tr_up_per_sec_SB)->setValue(rsTurtle->getMaxTRForwardRate()) ; @@ -188,6 +206,14 @@ void TransferPage::load() whileBlocking(ui.suffixesIgnoreList_CB)->setChecked( ignore_flags & RS_FILE_SHARE_FLAGS_IGNORE_SUFFIXES ) ; whileBlocking(ui.prefixesIgnoreList_LE)->setText( ignore_prefixes_string ); whileBlocking(ui.suffixesIgnoreList_LE)->setText( ignore_suffixes_string ); + + Settings->beginGroup(QString("File")); +#if defined(Q_OS_DARWIN) + whileBlocking(ui.minimumFontSize_SB)->setValue( Settings->value("MinimumFontSize", 13 ).toInt()); +#else + whileBlocking(ui.minimumFontSize_SB)->setValue( Settings->value("MinimumFontSize", 11 ).toInt()); +#endif + Settings->endGroup(); } void TransferPage::updateDefaultStrategy(int i) @@ -197,11 +223,19 @@ void TransferPage::updateDefaultStrategy(int i) case 0: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_STREAMING) ; break ; - case 2: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; - break ; + case 2: +#ifdef WINDOWS_SYS + if(QMessageBox::Yes != QMessageBox::warning(nullptr,tr("Warning"),tr("On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use \"progressive\")?"),QMessageBox::Yes,QMessageBox::No)) + { + ui._defaultStrategy_CB->setCurrentIndex(1); + return; + } +#endif + rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; + break ; case 1: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) ; - break ; + break ; default: ; } } @@ -290,6 +324,13 @@ void TransferPage::editDirectories() ShareManager::showYourself() ; } +void TransferPage::updateFontSize() +{ + Settings->beginGroup(QString("File")); + Settings->setValue("MinimumFontSize", ui.minimumFontSize_SB->value()); + Settings->endGroup(); +} + void TransferPage::updateAutoCheckDirectories() { rsFiles->setWatchEnabled(ui.autoCheckDirectories_CB->isChecked()) ; } void TransferPage::updateAutoScanDirectoriesPeriod() { rsFiles->setWatchPeriod(ui.autoCheckDirectoriesDelay_SB->value()); } void TransferPage::updateShareDownloadDirectory() { rsFiles->shareDownloadDirectory(ui.shareDownloadDirectoryCB->isChecked());} diff --git a/retroshare-gui/src/gui/settings/TransferPage.h b/retroshare-gui/src/gui/settings/TransferPage.h index 19ceedfca..077d5a6ec 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.h +++ b/retroshare-gui/src/gui/settings/TransferPage.h @@ -47,7 +47,6 @@ class TransferPage: public ConfigPage void updateDefaultStrategy(int) ; void updateDiskSizeLimit(int) ; void updateMaxTRUpRate(int); - void updateEncryptionPolicy(int); void updateMaxUploadSlots(int); void updateFilePermDirectDL(int); void updateIgnoreLists(); @@ -58,6 +57,8 @@ class TransferPage: public ConfigPage void updateAutoDLColl(); void setPartialsDirectory(); void toggleAutoCheckDirectories(bool); + void toggleTrustFriendNodesWithBannedFiles(bool); + void updateFontSize(); void updateAutoCheckDirectories() ; void updateAutoScanDirectoriesPeriod() ; diff --git a/retroshare-gui/src/gui/settings/TransferPage.ui b/retroshare-gui/src/gui/settings/TransferPage.ui index 4c925ebb1..4b48be012 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.ui +++ b/retroshare-gui/src/gui/settings/TransferPage.ui @@ -7,7 +7,7 @@ 0 0 701 - 527 + 638 @@ -30,7 +30,7 @@ - Edit Share + Configure shared directories @@ -67,6 +67,9 @@ + + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + minute(s) @@ -289,7 +292,7 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -299,6 +302,40 @@ p, li { white-space: pre-wrap; } + + + + + Minimum font size for Shared Files + + + + + + + 11 + + + 64 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + Qt::Vertical @@ -363,13 +400,6 @@ p, li { white-space: pre-wrap; } - - - - End-to-end encryption: - - - @@ -401,12 +431,12 @@ p, li { white-space: pre-wrap; } - + true - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> @@ -467,24 +497,7 @@ p, li { white-space: pre-wrap; } - - - <html><head/><body><p>Anonymous tunnels can be end-o-end encrypted. In order to maintain backward compatibility, this can be made optional (choosing &quot;Accepted&quot;), but in the end, all Retroshare nodes will be switched to &quot;Enforced&quot;, meaning that all anonymous transfers will be end-to-end encrypted. With &quot;Accepted&quot;, it is likely that you will transfer using twice as many tunnels, since there is no way to know that an encrypted and a clear tunnel actually transfer from the same source.</p></body></html> - - - - Accepted - - - - - Enforced - - - - - - + <html><head/><body><p>How RS manage direct download setting.</p></body></html> @@ -510,7 +523,7 @@ p, li { white-space: pre-wrap; } - + Trust friend nodes with banned files @@ -538,6 +551,13 @@ p, li { white-space: pre-wrap; } + + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    +
    diff --git a/retroshare-gui/src/gui/settings/WebuiPage.cpp b/retroshare-gui/src/gui/settings/WebuiPage.cpp index 8bdc11146..4b36b758c 100644 --- a/retroshare-gui/src/gui/settings/WebuiPage.cpp +++ b/retroshare-gui/src/gui/settings/WebuiPage.cpp @@ -27,6 +27,7 @@ #include #include "util/misc.h" +#include "util/qtthreadsutils.h" #include "retroshare/rswebui.h" #include "retroshare/rsjsonapi.h" @@ -40,6 +41,8 @@ resource_api::ApiServerLocal* WebuiPage::apiServerLocal = 0; #endif resource_api::RsControlModule* WebuiPage::controlModule = 0; +#define IMAGE_LEDOFF ":/images/ledoff1.png" +#define IMAGE_LEDON ":/images/ledon1.png" WebuiPage::WebuiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/) { @@ -50,11 +53,22 @@ WebuiPage::WebuiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/) connect(ui.password_LE, SIGNAL(textChanged(QString)), this, SLOT(onPasswordValueChanged(QString))); connect(ui.startWebBrowser_PB, SIGNAL(clicked()), this, SLOT(onStartWebBrowserClicked())); connect(ui.webInterfaceFilesDirectory_PB, SIGNAL(clicked()), this, SLOT(selectWebInterfaceDirectory())); + + mEventsHandlerId = 0; + + rsEvents->registerEventsHandler( [this](std::shared_ptr /* event */) + { +#ifdef DEBUG + std::cerr << "Caught JSONAPI event in webui!" << std::endl; +#endif + RsQThreadUtils::postToObject([=]() { load(); }, this ); + }, + mEventsHandlerId, RsEventType::JSON_API ); } WebuiPage::~WebuiPage() { - + rsEvents->unregisterEventsHandler(mEventsHandlerId); } void WebuiPage::selectWebInterfaceDirectory() @@ -65,25 +79,20 @@ void WebuiPage::selectWebInterfaceDirectory() return; whileBlocking(ui.webInterfaceFiles_LE)->setText(dirname); + + QString S; + updateParams(S); } bool WebuiPage::updateParams(QString &errmsg) { std::cerr << "WebuiPage::save()" << std::endl; - bool ok = true; - bool changed = false; - if(ui.enableWebUI_CB->isChecked() != Settings->getWebinterfaceEnabled()) - changed = true; - if(ui.webInterfaceFiles_LE->text() != Settings->getWebinterfaceFilesDirectory()) - changed = true; - if(changed) - { - // store config - Settings->setWebinterfaceEnabled(ui.enableWebUI_CB->isChecked()); - Settings->setWebinterfaceFilesDirectory(ui.webInterfaceFiles_LE->text()); - } - return ok; + // store config + Settings->setWebinterfaceEnabled(ui.enableWebUI_CB->isChecked()); + Settings->setWebinterfaceFilesDirectory(ui.webInterfaceFiles_LE->text()); + + return true; } void WebuiPage::onPasswordValueChanged(QString password) @@ -107,12 +116,27 @@ void WebuiPage::onPasswordValueChanged(QString password) bool WebuiPage::restart() { - return checkStartWebui(); + if(ui.password_LE->text().isNull()) + { + QMessageBox::critical(nullptr,tr("Missing passphrase"),tr("Please set a passphrase to proect the access to the WEB interface.")); + return false; + } + + rsWebUi->setUserPassword(ui.password_LE->text().toStdString()); + rsWebUi->setHtmlFilesDirectory(ui.webInterfaceFiles_LE->text().toStdString()); + + setCursor(Qt::WaitCursor) ; + rsWebUi->restart(); + setCursor(Qt::ArrowCursor) ; + + return true; } -void WebuiPage::load() +void WebuiPage::loadParams() { - std::cerr << "WebuiPage::load()" << std::endl; +#ifdef DEBUG + std::cerr << "WebuiPage::load()" << std::endl; +#endif whileBlocking(ui.enableWebUI_CB)->setChecked(Settings->getWebinterfaceEnabled()); whileBlocking(ui.webInterfaceFiles_LE)->setText(Settings->getWebinterfaceFilesDirectory()); @@ -122,6 +146,15 @@ void WebuiPage::load() if(it != smap.end()) whileBlocking(ui.password_LE)->setText(QString::fromStdString(it->second)); + else + whileBlocking(ui.enableWebUI_CB)->setChecked(false); + + if(rsWebUi->isRunning()) + ui.statusLabelLED->setPixmap(FilesDefs::getPixmapFromQtResourcePath(IMAGE_LEDON)) ; + else + ui.statusLabelLED->setPixmap(FilesDefs::getPixmapFromQtResourcePath(IMAGE_LEDOFF)) ; +#else + ui.statusLabelLED->setPixmap(FilesDefs::getPixmapFromQtResourcePath(IMAGE_LEDOFF)) ; #endif } @@ -133,13 +166,11 @@ QString WebuiPage::helpText() const

    Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.

    "); } -/*static*/ bool WebuiPage::checkStartWebui() +/*static*/ bool WebuiPage::checkStartWebui() // This is supposed to be called from main(). But normally the parameters below (including the paswd + // for the webUI should be saved in p3webui instead. { - if(!Settings->getWebinterfaceEnabled()) - return false; - - rsWebUi->setHtmlFilesDirectory(Settings->getWebinterfaceFilesDirectory().toStdString()); - rsWebUi->restart(); + rsWebUi->setHtmlFilesDirectory(Settings->getWebinterfaceFilesDirectory().toStdString()); + rsWebUi->restart(); return true; } @@ -168,15 +199,21 @@ QString WebuiPage::helpText() const void WebuiPage::onEnableCBClicked(bool checked) { - ui.params_GB->setEnabled(checked); - ui.apply_PB->setEnabled(checked); - ui.startWebBrowser_PB->setEnabled(checked); - QString S; + QString errmsg; + updateParams(errmsg); - Settings->setWebinterfaceEnabled(checked); + ui.params_GB->setEnabled(checked); + ui.startWebBrowser_PB->setEnabled(checked); + ui.apply_PB->setEnabled(checked); if(checked) - checkStartWebui(); + { + if(!restart()) + { + QMessageBox::warning(0, tr("failed to start Webinterface"), "Failed to start the webinterface."); + return; + } + } else checkShutdownWebui(); } @@ -194,15 +231,12 @@ void WebuiPage::onAllIPCBClicked(bool /*checked*/) } void WebuiPage::onApplyClicked() { - rsWebUi->setUserPassword(ui.password_LE->text().toStdString()); + QString errmsg; + updateParams(errmsg); - if(!restart()) - { - QMessageBox::warning(0, tr("failed to start Webinterface"), "Failed to start the webinterface."); - return; - } + restart(); - emit passwordChanged(); + load(); } void WebuiPage::onStartWebBrowserClicked() { showWebui(); } diff --git a/retroshare-gui/src/gui/settings/WebuiPage.h b/retroshare-gui/src/gui/settings/WebuiPage.h index 9ba8886ac..391612cf8 100644 --- a/retroshare-gui/src/gui/settings/WebuiPage.h +++ b/retroshare-gui/src/gui/settings/WebuiPage.h @@ -20,6 +20,8 @@ #pragma once +#include "retroshare/rsevents.h" + #include "retroshare-gui/configpage.h" #include "gui/common/FilesDefs.h" #include "ui_WebuiPage.h" @@ -42,11 +44,11 @@ public: ~WebuiPage(); /** Loads the settings for this page */ - virtual void load(); + virtual void load() override { loadParams() ; } - virtual QPixmap iconPixmap() const { return FilesDefs::getPixmapFromQtResourcePath(":/icons/settings/webinterface.svg") ; } - virtual QString pageName() const { return tr("Webinterface") ; } - virtual QString helpText() const; + virtual QPixmap iconPixmap() const override { return FilesDefs::getPixmapFromQtResourcePath(":/icons/settings/webinterface.svg") ; } + virtual QString pageName() const override { return tr("Webinterface") ; } + virtual QString helpText() const override ; // call this after start of libretroshare/Retroshare // checks the settings and starts the webinterface if required @@ -67,10 +69,9 @@ public slots: void onApplyClicked(); void onStartWebBrowserClicked(); -signals: - void passwordChanged(); - private: + virtual void loadParams(); + /** Qt Designer generated object */ Ui::WebuiPage ui; @@ -83,4 +84,6 @@ private: static resource_api::ApiServerLocal* apiServerLocal; #endif static resource_api::RsControlModule* controlModule; + + RsEventsHandlerId_t mEventsHandlerId; }; diff --git a/retroshare-gui/src/gui/settings/WebuiPage.ui b/retroshare-gui/src/gui/settings/WebuiPage.ui index 5ca37e9b6..91d59736f 100644 --- a/retroshare-gui/src/gui/settings/WebuiPage.ui +++ b/retroshare-gui/src/gui/settings/WebuiPage.ui @@ -6,8 +6,8 @@ 0 0 - 960 - 717 + 570 + 646 @@ -15,11 +15,45 @@ - - - Enable Retroshare WEB Interface - - + + + + + Enable Retroshare WEB Interface + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Status: + + + + + + + + + + :/images/ledoff1.png + + + + diff --git a/retroshare-gui/src/gui/settings/rsettingswin.cpp b/retroshare-gui/src/gui/settings/rsettingswin.cpp index 6d3f10bbc..a9fab8895 100644 --- a/retroshare-gui/src/gui/settings/rsettingswin.cpp +++ b/retroshare-gui/src/gui/settings/rsettingswin.cpp @@ -52,8 +52,6 @@ # include "JsonApiPage.h" #endif -#define IMAGE_GENERAL ":/images/kcmsystem24.png" - #define ITEM_SPACING 2 #include "rsettingswin.h" @@ -95,6 +93,8 @@ SettingsPage::SettingsPage(QWidget *parent) connect(ui.listWidget, SIGNAL(currentRowChanged(int)), this, SLOT(setNewPage(int))); connect(this, SIGNAL(finished(int)), this, SLOT(dialogFinished(int))); + + mFontSizeHandler.registerFontSize(ui.listWidget); } SettingsPage::~SettingsPage() @@ -178,12 +178,9 @@ SettingsPage::initStackedWidget() addPage(new ServicePermissionsPage() ); // PERMISSIONS #ifdef RS_JSONAPI JsonApiPage *jsonapi_p = new JsonApiPage() ; - addPage(new JsonApiPage()); + addPage(jsonapi_p); #ifdef RS_WEBUI - WebuiPage *webui_p = new WebuiPage() ; - addPage(new WebuiPage() ); - - QObject::connect(webui_p,SIGNAL(passwordChanged()),jsonapi_p,SLOT(load())); + addPage(new WebuiPage()); #endif #endif @@ -226,8 +223,8 @@ SettingsPage::setNewPage(int page) mHelpBrowser->clear(); return ; } - ui.pageName->setText(pagew->pageName()); - ui.pageicon->setPixmap(pagew->iconPixmap()) ; + ui.pageNameLabel->setText(pagew->pageName()); + ui.pageIconLabel->setPixmap(pagew->iconPixmap()) ; ui.stackedWidget->setCurrentIndex(page); ui.listWidget->setCurrentRow(page); diff --git a/retroshare-gui/src/gui/settings/rsettingswin.h b/retroshare-gui/src/gui/settings/rsettingswin.h index a3242aaa4..47eb33e4b 100755 --- a/retroshare-gui/src/gui/settings/rsettingswin.h +++ b/retroshare-gui/src/gui/settings/rsettingswin.h @@ -27,10 +27,11 @@ #include #include "ui_settingsw.h" +#include "util/FontSizeHandler.h" class FloatingHelpBrowser; -#define IMAGE_PREFERENCES ":/icons/png/options.png" +#define PREF_IMAGE_PREFERENCES ":/icons/png/options.png" class SettingsPage: public MainPage { @@ -46,7 +47,7 @@ public: void postModDirectories(bool update_local); - virtual QIcon iconPixmap() const { return FilesDefs::getIconFromQtResourcePath(IMAGE_PREFERENCES) ; } //MainPage + virtual QIcon iconPixmap() const { return FilesDefs::getIconFromQtResourcePath(PREF_IMAGE_PREFERENCES) ; } //MainPage virtual QString pageName() const { return tr("Preferences") ; } //MainPage protected: @@ -72,6 +73,8 @@ private: FloatingHelpBrowser *mHelpBrowser; static int lastPage; + FontSizeHandler mFontSizeHandler; + /* UI - from Designer */ Ui::Settings ui; }; diff --git a/retroshare-gui/src/gui/settings/rsharesettings.cpp b/retroshare-gui/src/gui/settings/rsharesettings.cpp index 86a93559e..d878d6c99 100644 --- a/retroshare-gui/src/gui/settings/rsharesettings.cpp +++ b/retroshare-gui/src/gui/settings/rsharesettings.cpp @@ -109,7 +109,7 @@ void RshareSettings::initSettings() setDefault(SETTING_STYLE, "GTK+"); #else #if defined(Q_OS_MAC) - setDefault(SETTING_STYLE, "macintosh (aqua)"); + setDefault(SETTING_STYLE, "Fusion"); #else static QStringList styles = QStyleFactory::keys(); #if defined(Q_OS_WIN) @@ -129,7 +129,7 @@ void RshareSettings::initSettings() #endif setDefault(SETTING_LANGUAGE, LanguageSupport::defaultLanguageCode()); - setDefault(SETTING_SHEETNAME, ":Standard"); + setDefault(SETTING_SHEETNAME, ":Standard_Light"); /* defaults here are not ideal.... but dusent matter */ @@ -537,6 +537,16 @@ void RshareSettings::setChatSendAsPlainTextByDef(bool bValue) setValueToGroup("Chat", "SendAsPlainTextByDef", bValue); } +bool RshareSettings::getShrinkChatTextEdit() +{ + return valueFromGroup("Chat", "ShrinkChatTextEdit", false).toBool(); +} + +void RshareSettings::setShrinkChatTextEdit(bool bValue) +{ + setValueToGroup("Chat", "ShrinkChatTextEdit", bValue); +} + bool RshareSettings::getChatSearchShowBarByDefault() { return valueFromGroup("Chat", "SearchShowBarByDefault", false).toBool(); @@ -900,7 +910,7 @@ void RshareSettings::setUseLocalServer(bool value) { if (value != getUseLocalServer()) { setValue("UseLocalServer", value); - Rshare::updateLocalServer(); + RsApplication::updateLocalServer(); } } @@ -1180,6 +1190,38 @@ void RshareSettings::setPageAlreadyDisplayed(const QString& page_name,bool b) return setValueToGroup("PageAlreadyDisplayed",page_name,b); } +int RshareSettings::getFontSize() +{ +#if defined(Q_OS_DARWIN) + int defaultFontSize = 13; +#else + int defaultFontSize = 11; +#endif + + return value("FontSize", defaultFontSize).toInt(); +} + +void RshareSettings::setFontSize(int value) +{ + setValue("FontSize", value); +} + +int RshareSettings::getMessageFontSize() +{ +#if defined(Q_OS_DARWIN) + int defaultFontSize = 12; +#else + int defaultFontSize = 11; +#endif + + return valueFromGroup("Message", "FontSize", defaultFontSize).toInt(); +} + +void RshareSettings::setMessageFontSize(int value) +{ + setValueToGroup("Message", "FontSize", value); +} + #ifdef RS_JSONAPI bool RshareSettings::getJsonApiEnabled() { diff --git a/retroshare-gui/src/gui/settings/rsharesettings.h b/retroshare-gui/src/gui/settings/rsharesettings.h index abf728391..317dedb56 100644 --- a/retroshare-gui/src/gui/settings/rsharesettings.h +++ b/retroshare-gui/src/gui/settings/rsharesettings.h @@ -217,6 +217,9 @@ public: bool getChatSendAsPlainTextByDef(); void setChatSendAsPlainTextByDef(bool bValue); + bool getShrinkChatTextEdit(); + void setShrinkChatTextEdit(bool bValue); + bool getChatSearchShowBarByDefault(); void setChatSearchShowBarByDefault(bool bValue); @@ -340,6 +343,12 @@ public: bool getPageAlreadyDisplayed(const QString& page_code) ; void setPageAlreadyDisplayed(const QString& page_code,bool b) ; + int getFontSize(); + void setFontSize(int value); + + int getMessageFontSize(); + void setMessageFontSize(int value); + #ifdef RS_JSONAPI bool getJsonApiEnabled(); void setJsonApiEnabled(bool enabled); diff --git a/retroshare-gui/src/gui/settings/settings.ui b/retroshare-gui/src/gui/settings/settings.ui index 8d774dce2..18b910fb3 100755 --- a/retroshare-gui/src/gui/settings/settings.ui +++ b/retroshare-gui/src/gui/settings/settings.ui @@ -47,7 +47,7 @@ - + 0 @@ -56,6 +56,7 @@ + 12 75 true @@ -66,7 +67,7 @@ - + 24 @@ -215,13 +216,6 @@ - - - StyledLabel - QLabel -
    gui/common/StyledLabel.h
    -
    -
    diff --git a/retroshare-gui/src/gui/settings/settingsw.ui b/retroshare-gui/src/gui/settings/settingsw.ui index fa6f197db..605e8558e 100644 --- a/retroshare-gui/src/gui/settings/settingsw.ui +++ b/retroshare-gui/src/gui/settings/settingsw.ui @@ -35,11 +35,6 @@ 16777215 - - - 11 - - Qt::IgnoreAction @@ -78,7 +73,7 @@
    - + 24 @@ -91,7 +86,7 @@ - + 0 @@ -134,8 +129,8 @@ 0 0 - 1313 - 849 + 1264 + 845 @@ -169,13 +164,6 @@
    - - - StyledLabel - QLabel -
    gui/common/StyledLabel.h
    -
    -
    diff --git a/retroshare-gui/src/gui/statistics/BandwidthGraphWindow.cpp b/retroshare-gui/src/gui/statistics/BandwidthGraphWindow.cpp index 87a87a5f8..f621d355b 100644 --- a/retroshare-gui/src/gui/statistics/BandwidthGraphWindow.cpp +++ b/retroshare-gui/src/gui/statistics/BandwidthGraphWindow.cpp @@ -42,7 +42,7 @@ #define DEFAULT_ALWAYS_ON_TOP false #define DEFAULT_OPACITY 100 #define DEFAULT_STYLE LineGraph -#define DEFAULT_GRAPHCOLOR DefaultColor +#define DEFAULT_GRAPHCOLOR false #define DEFAULT_DIRECTION DefaultDirection #define ADD_TO_FILTER(f,v,b) (f = ((b) ? ((f) | (v)) : ((f) & ~(v)))) @@ -135,16 +135,16 @@ void BandwidthGraph::toggleReceiveRate(bool b) void BandwidthGraph::switchGraphColor() { - if(ui.frmGraph->getFlags() & RSGraphWidget::RSGRAPH_FLAGS_DARK_STYLE) - { - ui.frmGraph->resetFlags(RSGraphWidget::RSGRAPH_FLAGS_DARK_STYLE); - ui.btnGraphColor->setIcon(FilesDefs::getIconFromQtResourcePath(IMG_GRAPH_LIGHT)); - } - else + if(ui.btnGraphColor->isChecked()) { ui.frmGraph->setFlags(RSGraphWidget::RSGRAPH_FLAGS_DARK_STYLE); ui.btnGraphColor->setIcon(FilesDefs::getIconFromQtResourcePath(IMG_GRAPH_DARK)); } + else + { + ui.frmGraph->resetFlags(RSGraphWidget::RSGRAPH_FLAGS_DARK_STYLE); + ui.btnGraphColor->setIcon(FilesDefs::getIconFromQtResourcePath(IMG_GRAPH_LIGHT)); + } saveSettings(); } @@ -158,9 +158,9 @@ BandwidthGraph::loadSettings() setOpacity(ui.sldrOpacity->value()); /* Set whether we are plotting bandwidth as area graphs or not */ - int graphColor = getSetting(SETTING_GRAPHCOLOR, DEFAULT_GRAPHCOLOR).toInt(); + ui.btnGraphColor->setChecked(getSetting(SETTING_GRAPHCOLOR, DEFAULT_GRAPHCOLOR).toBool()); - if(graphColor>0) + if(ui.btnGraphColor->isChecked()) { ui.frmGraph->setFlags(RSGraphWidget::RSGRAPH_FLAGS_DARK_STYLE); ui.btnGraphColor->setIcon(FilesDefs::getIconFromQtResourcePath(IMG_GRAPH_DARK)); diff --git a/retroshare-gui/src/gui/statistics/BandwidthGraphWindow.ui b/retroshare-gui/src/gui/statistics/BandwidthGraphWindow.ui index 56f1818f8..17d2ee6c5 100644 --- a/retroshare-gui/src/gui/statistics/BandwidthGraphWindow.ui +++ b/retroshare-gui/src/gui/statistics/BandwidthGraphWindow.ui @@ -61,7 +61,7 @@ PushButton - false + true @@ -180,7 +180,15 @@ QFrame::Raised - + + + + 0 + 0 + 218 + 88 + + 1 diff --git a/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.h b/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.h index c0ae4b4b2..0445ab76f 100644 --- a/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.h +++ b/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.h @@ -18,6 +18,8 @@ * * *******************************************************************************/ +#pragma once + #include "ui_BandwidthStatsWidget.h" #include "BWGraph.h" diff --git a/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.ui b/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.ui index dc36efbad..f62171aa1 100644 --- a/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.ui +++ b/retroshare-gui/src/gui/statistics/BandwidthStatsWidget.ui @@ -49,7 +49,7 @@ - + 0 @@ -69,7 +69,7 @@ - + Up @@ -90,7 +90,7 @@ - + 0 @@ -110,7 +110,7 @@ - + @@ -120,7 +120,7 @@ - + Current @@ -141,7 +141,7 @@ - + Default @@ -179,6 +179,11 @@
    gui/statistics/BWGraph.h
    1 + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    diff --git a/retroshare-gui/src/gui/statistics/GxsIdStatistics.cpp b/retroshare-gui/src/gui/statistics/GxsIdStatistics.cpp index c7fe1068c..3037839c2 100644 --- a/retroshare-gui/src/gui/statistics/GxsIdStatistics.cpp +++ b/retroshare-gui/src/gui/statistics/GxsIdStatistics.cpp @@ -44,6 +44,7 @@ #include "util/misc.h" #include "util/qtthreadsutils.h" +#ifdef TODO static QColor colorScale(float f) { if(f == 0) @@ -51,6 +52,7 @@ static QColor colorScale(float f) else return QColor::fromHsv((int)((1.0-f)*280),200,255) ; } +#endif GxsIdStatistics::GxsIdStatistics(QWidget *parent) : RsAutoUpdatePage(4000,parent) diff --git a/retroshare-gui/src/gui/statistics/Histogram.cpp b/retroshare-gui/src/gui/statistics/Histogram.cpp index 6cd1c4906..77e272b31 100644 --- a/retroshare-gui/src/gui/statistics/Histogram.cpp +++ b/retroshare-gui/src/gui/statistics/Histogram.cpp @@ -33,15 +33,15 @@ Histogram::Histogram(double start, double end, int bins) std::cerr << "Null histogram created! Please check your parameters" << std::endl; } -void Histogram::draw(QPainter *painter) const +void Histogram::draw(QPainter */*painter*/) const { } void Histogram::insert(double val) { - long int bin = (uint32_t)floor((val - mStart)/(mEnd - mStart) * mBins.size()); + long int bin = (long int)floor((val - mStart)/(mEnd - mStart) * mBins.size()); - if(bin >= 0 && bin < mBins.size()) + if(bin >= 0 && bin < (long int)mBins.size()) ++mBins[bin]; } diff --git a/retroshare-gui/src/gui/statistics/Histogram.h b/retroshare-gui/src/gui/statistics/Histogram.h index ca71d3b82..3931b15db 100644 --- a/retroshare-gui/src/gui/statistics/Histogram.h +++ b/retroshare-gui/src/gui/statistics/Histogram.h @@ -20,6 +20,7 @@ #include #include +#include class QPainter; diff --git a/retroshare-gui/src/gui/statistics/StatisticsWindow.cpp b/retroshare-gui/src/gui/statistics/StatisticsWindow.cpp index 48b1462cc..684fdc69d 100644 --- a/retroshare-gui/src/gui/statistics/StatisticsWindow.cpp +++ b/retroshare-gui/src/gui/statistics/StatisticsWindow.cpp @@ -22,6 +22,7 @@ #include "ui_StatisticsWindow.h" #include #include +#include #include #include diff --git a/retroshare-gui/src/gui/statusbar/OpModeStatus.cpp b/retroshare-gui/src/gui/statusbar/OpModeStatus.cpp index f44f6d29c..994974342 100644 --- a/retroshare-gui/src/gui/statusbar/OpModeStatus.cpp +++ b/retroshare-gui/src/gui/statusbar/OpModeStatus.cpp @@ -30,7 +30,7 @@ #include OpModeStatus::OpModeStatus(QWidget *parent) - : QComboBox(parent) + : RSComboBox(parent) { onUpdate = false; opMode_Full_Color = QColor("#CCFFCC"); diff --git a/retroshare-gui/src/gui/statusbar/OpModeStatus.h b/retroshare-gui/src/gui/statusbar/OpModeStatus.h index 80fc111a5..9ffe282a3 100644 --- a/retroshare-gui/src/gui/statusbar/OpModeStatus.h +++ b/retroshare-gui/src/gui/statusbar/OpModeStatus.h @@ -21,9 +21,9 @@ #ifndef OP_MODE_STATUS_H #define OP_MODE_STATUS_H -#include +#include "gui/common/RSComboBox.h" -class OpModeStatus : public QComboBox +class OpModeStatus : public RSComboBox { Q_OBJECT Q_PROPERTY(QColor opMode_Full_Color READ getOpMode_Full_Color WRITE setOpMode_Full_Color DESIGNABLE true) diff --git a/retroshare-gui/src/gui/statusbar/torstatus.cpp b/retroshare-gui/src/gui/statusbar/torstatus.cpp index f046f09cc..d43de1df3 100644 --- a/retroshare-gui/src/gui/statusbar/torstatus.cpp +++ b/retroshare-gui/src/gui/statusbar/torstatus.cpp @@ -28,11 +28,10 @@ #include "retroshare/rsconfig.h" #include "retroshare/rsinit.h" #include "retroshare/rspeers.h" +#include "retroshare/rstor.h" #include #include "util/misc.h" -#include "TorControl/TorManager.h" -#include "TorControl/TorControl.h" #include "gui/common/FilesDefs.h" #include @@ -92,8 +91,8 @@ void TorStatus::getTorStatus() if(RsAccounts::isTorAuto()) { // get Tor status - int tor_control_status = Tor::TorManager::instance()->control()->status(); - int torstatus = Tor::TorManager::instance()->control()->torStatus(); + RsTorConnectivityStatus tor_control_status = RsTor::torConnectivityStatus(); + RsTorStatus torstatus = RsTor::torStatus(); QString tor_control_status_str,torstatus_str ; bool tor_control_ok ; @@ -101,30 +100,31 @@ void TorStatus::getTorStatus() switch(tor_control_status) { default: - case Tor::TorControl::Error : tor_control_ok = false ; tor_control_status_str = "Error" ; break ; - case Tor::TorControl::NotConnected: tor_control_ok = false ; tor_control_status_str = "Not connected" ; break ; - case Tor::TorControl::Connecting: tor_control_ok = false ; tor_control_status_str = "Connecting" ; break ; - case Tor::TorControl::Authenticating: tor_control_ok = false ; tor_control_status_str = "Authenticating" ; break ; - case Tor::TorControl::Connected: tor_control_ok = true ; tor_control_status_str = "Connected" ; break ; - } + case RsTorConnectivityStatus::ERROR : tor_control_ok = false ; tor_control_status_str = "Error" ; break ; + case RsTorConnectivityStatus::NOT_CONNECTED: tor_control_ok = false ; tor_control_status_str = "Not connected" ; break ; + case RsTorConnectivityStatus::CONNECTING: tor_control_ok = false ; tor_control_status_str = "Connecting" ; break ; + case RsTorConnectivityStatus::AUTHENTICATING: tor_control_ok = false ; tor_control_status_str = "Authenticating" ; break ; + case RsTorConnectivityStatus::AUTHENTICATED: tor_control_ok = false ; tor_control_status_str = "Connected" ; break ; + case RsTorConnectivityStatus::HIDDEN_SERVICE_READY: tor_control_ok = true ; tor_control_status_str = "Hidden service ready" ; break ; + } switch(torstatus) { default: - case Tor::TorControl::TorUnknown: torstatus_str = "Unknown" ; break ; - case Tor::TorControl::TorOffline: torstatus_str = "Tor offline" ; break ; - case Tor::TorControl::TorReady: torstatus_str = "Tor ready" ; break ; + case RsTorStatus::UNKNOWN: torstatus_str = "Unknown" ; break ; + case RsTorStatus::OFFLINE: torstatus_str = "Tor offline" ; break ; + case RsTorStatus::READY: torstatus_str = "Tor ready" ; break ; } #define MIN_RS_NET_SIZE 10 - if(torstatus == Tor::TorControl::TorOffline || !online || !tor_control_ok) + if(torstatus == RsTorStatus::OFFLINE || !online || !tor_control_ok) { // RED - some issue. torstatusLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/tor-stopping.png").scaledToHeight(1.5*S,Qt::SmoothTransformation)); torstatusLabel->setToolTip( text + tr("Tor is currently offline")); } - else if(torstatus == Tor::TorControl::TorReady && online && tor_control_ok) + else if(torstatus == RsTorStatus::READY && online && tor_control_ok) { torstatusLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/tor-on.png").scaledToHeight(1.5*S,Qt::SmoothTransformation)); torstatusLabel->setToolTip( text + tr("Tor is OK")); @@ -141,12 +141,12 @@ void TorStatus::getTorStatus() if(!_updated) { RsPeerDetails pd; - uint32_t hiddentype; - if (rsPeers->getPeerDetails(rsPeers->getOwnId(), pd)) { + uint32_t hiddentype = RS_HIDDEN_TYPE_UNKNOWN; + + if (rsPeers->getPeerDetails(rsPeers->getOwnId(), pd)) + { if(pd.netMode == RS_NETMODE_HIDDEN) - { hiddentype = pd.hiddenType; - } } std::string proxyaddr; uint16_t proxyport; @@ -168,7 +168,7 @@ void TorStatus::getTorStatus() torstatusLabel->setToolTip( text + tr("Tor proxy is not available")); } } - if(hiddentype == RS_HIDDEN_TYPE_I2P) + else if(hiddentype == RS_HIDDEN_TYPE_I2P) { statusTor->setText("" + tr("I2P") + ":"); rsPeers->getProxyServer(RS_HIDDEN_TYPE_I2P, proxyaddr, proxyport, status); @@ -185,6 +185,11 @@ void TorStatus::getTorStatus() torstatusLabel->setToolTip( text + tr("i2p proxy is not available")); } } + else + { + torstatusLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/tile_inactive_48.png").scaledToHeight(S,Qt::SmoothTransformation)); + torstatusLabel->setToolTip(tr("No tor configuration")); + } _updated = true; } } diff --git a/retroshare-gui/src/gui/style/StyleDialog.ui b/retroshare-gui/src/gui/style/StyleDialog.ui index 312453628..1da590d9b 100644 --- a/retroshare-gui/src/gui/style/StyleDialog.ui +++ b/retroshare-gui/src/gui/style/StyleDialog.ui @@ -102,7 +102,7 @@
    - + 0 @@ -183,6 +183,11 @@
    gui/common/HeaderFrame.h
    1 + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    diff --git a/retroshare-gui/src/gui/toaster/ChatLobbyToaster.ui b/retroshare-gui/src/gui/toaster/ChatLobbyToaster.ui index b6408ed93..e45b87103 100644 --- a/retroshare-gui/src/gui/toaster/ChatLobbyToaster.ui +++ b/retroshare-gui/src/gui/toaster/ChatLobbyToaster.ui @@ -22,30 +22,48 @@ 100
    - + 0 - + + 0 + + + 0 + + + 0 + + 0 - + QFrame::WinPanel QFrame::Raised - - + + + 2 + + + 2 + + + 2 + + 2 2 - + 6 @@ -79,13 +97,20 @@ + + + 12 + 75 + true + + Name - + Qt::Horizontal @@ -123,7 +148,7 @@ - + 2 diff --git a/retroshare-gui/src/gui/toaster/ChatToaster.ui b/retroshare-gui/src/gui/toaster/ChatToaster.ui index 8b517684b..1c6ee5ae2 100644 --- a/retroshare-gui/src/gui/toaster/ChatToaster.ui +++ b/retroshare-gui/src/gui/toaster/ChatToaster.ui @@ -22,30 +22,48 @@ 100 - + 0 - + + 0 + + + 0 + + + 0 + + 0 - + QFrame::WinPanel QFrame::Raised - - + + + 2 + + + 2 + + + 2 + + 2 2 - + 6 @@ -79,13 +97,20 @@ + + + 12 + 75 + true + + Name - + Qt::Horizontal @@ -123,7 +148,7 @@ - + 2 diff --git a/retroshare-gui/src/gui/toaster/DownloadToaster.ui b/retroshare-gui/src/gui/toaster/DownloadToaster.ui index de68906b7..86ef2a666 100644 --- a/retroshare-gui/src/gui/toaster/DownloadToaster.ui +++ b/retroshare-gui/src/gui/toaster/DownloadToaster.ui @@ -22,30 +22,48 @@ 100 - + 0 - + + 0 + + + 0 + + + 0 + + 0 - + QFrame::WinPanel QFrame::Raised - - + + + 2 + + + 2 + + + 2 + + 2 2 - + 6 @@ -82,13 +100,20 @@ + + + 12 + 75 + true + + Download completed - + Qt::Horizontal @@ -126,7 +151,7 @@ - + diff --git a/retroshare-gui/src/gui/toaster/FriendRequestToaster.ui b/retroshare-gui/src/gui/toaster/FriendRequestToaster.ui index ae203707a..e420b68b4 100644 --- a/retroshare-gui/src/gui/toaster/FriendRequestToaster.ui +++ b/retroshare-gui/src/gui/toaster/FriendRequestToaster.ui @@ -22,30 +22,48 @@ 100 - + 0 - + + 0 + + + 0 + + + 0 + + 0 - + QFrame::WinPanel QFrame::Raised - - + + + 2 + + + 2 + + + 2 + + 2 2 - + 6 @@ -79,13 +97,20 @@ + + + 12 + 75 + true + + Friend Request - + Qt::Horizontal @@ -123,7 +148,7 @@ - + 2 diff --git a/retroshare-gui/src/gui/toaster/GroupChatToaster.ui b/retroshare-gui/src/gui/toaster/GroupChatToaster.ui index 83ffdfd9a..9f701023a 100644 --- a/retroshare-gui/src/gui/toaster/GroupChatToaster.ui +++ b/retroshare-gui/src/gui/toaster/GroupChatToaster.ui @@ -22,30 +22,48 @@ 100 - + 0 - + + 0 + + + 0 + + + 0 + + 0 - + QFrame::WinPanel QFrame::Raised - - + + + 2 + + + 2 + + + 2 + + 2 2 - + 6 @@ -79,13 +97,20 @@ + + + 12 + 75 + true + + Name - + Qt::Horizontal @@ -123,7 +148,7 @@ - + 2 diff --git a/retroshare-gui/src/gui/toaster/MessageToaster.cpp b/retroshare-gui/src/gui/toaster/MessageToaster.cpp index 93772ca68..1f4894ba3 100644 --- a/retroshare-gui/src/gui/toaster/MessageToaster.cpp +++ b/retroshare-gui/src/gui/toaster/MessageToaster.cpp @@ -21,7 +21,11 @@ #include "MessageToaster.h" #include "../MainWindow.h" +#include #include +#include + +#include "gui/msgs/MessageInterface.h" MessageToaster::MessageToaster(const std::string &peerId, const QString &title, const QString &message) : QWidget(NULL) { @@ -39,8 +43,24 @@ MessageToaster::MessageToaster(const std::string &peerId, const QString &title, ui.textLabel->setText(message); ui.textLabel->setToolTip(message); - std::string name = (!RsPeerId(peerId).isNull())? (rsPeers->getPeerName(RsPeerId(peerId))): (rsPeers->getGPGName(RsPgpId(peerId))) ; - ui.toasterLabel->setText(ui.toasterLabel->text() + " " + QString::fromUtf8(name.c_str())); + MessageInfo mi; + + if (!rsMail->getMessage(peerId, mi)) + return; + + QString srcName; + + if(mi.msgflags & RS_MSG_DISTANT) + { + RsIdentityDetails details ; + rsIdentity->getIdDetails(mi.from.toGxsId(), details) ; + + srcName = QString::fromUtf8(details.mNickname.c_str()); + } + else + srcName = QString::fromUtf8(rsPeers->getPeerName(mi.from.toRsPeerId()).c_str()); + + ui.toasterLabel->setText(ui.toasterLabel->text() + " " + srcName); } void MessageToaster::openmessageClicked() diff --git a/retroshare-gui/src/gui/toaster/MessageToaster.ui b/retroshare-gui/src/gui/toaster/MessageToaster.ui index 89dcb79a4..1dce4be57 100644 --- a/retroshare-gui/src/gui/toaster/MessageToaster.ui +++ b/retroshare-gui/src/gui/toaster/MessageToaster.ui @@ -22,30 +22,48 @@ 100 - + 0 - + + 0 + + + 0 + + + 0 + + 0 - + QFrame::WinPanel QFrame::Raised - - + + + 2 + + + 2 + + + 2 + + 2 2 - + 6 @@ -79,13 +97,20 @@ + + + 12 + 75 + true + + 1 new Message from - + Qt::Horizontal @@ -123,7 +148,7 @@ - + 2 diff --git a/retroshare-gui/src/gui/toaster/OnlineToaster.ui b/retroshare-gui/src/gui/toaster/OnlineToaster.ui index a40f9f80c..248870e66 100644 --- a/retroshare-gui/src/gui/toaster/OnlineToaster.ui +++ b/retroshare-gui/src/gui/toaster/OnlineToaster.ui @@ -22,30 +22,48 @@ 100 - + 0 - + + 0 + + + 0 + + + 0 + + 0 - + QFrame::WinPanel QFrame::Raised - - + + + 2 + + + 2 + + + 2 + + 2 2 - + 6 @@ -79,13 +97,20 @@ + + + 12 + 75 + true + + RetroShare - + Qt::Horizontal @@ -123,7 +148,7 @@ - + 2 diff --git a/retroshare-gui/src/gui/unfinished/ApplicationWindow.ui b/retroshare-gui/src/gui/unfinished/ApplicationWindow.ui index ffa98afbd..df4f39a2c 100644 --- a/retroshare-gui/src/gui/unfinished/ApplicationWindow.ui +++ b/retroshare-gui/src/gui/unfinished/ApplicationWindow.ui @@ -53,6 +53,15 @@ + + + + 0 + 0 + 0 + + + @@ -73,6 +82,15 @@ + + + + 0 + 0 + 0 + + + @@ -93,6 +111,15 @@ + + + + 154 + 154 + 154 + + + diff --git a/retroshare-gui/src/gui/unfinished/CalDialog.ui b/retroshare-gui/src/gui/unfinished/CalDialog.ui index 8615caa12..598e7f870 100644 --- a/retroshare-gui/src/gui/unfinished/CalDialog.ui +++ b/retroshare-gui/src/gui/unfinished/CalDialog.ui @@ -1,7 +1,8 @@ - + + CalDialog - - + + 0 0 @@ -9,76 +10,68 @@ 540 - + Form - - + + 0 - + 6 - + 0 - + 6 - + 0 - - - + + + QTabWidget::Rounded - + 0 - + Qt::ElideNone - - - - 0 - 0 - 734 - 501 - - - + + Local Calendars - - - - + + + + QLayout::SetMaximumSize - - - + + + 75 true - + Shared Calendar List - - - - + + + + 0 0 - + 289 0 @@ -88,154 +81,154 @@ - - - + + + 75 true - + Share Details - - - + + + QLayout::SetMaximumSize - - - + + + Name: - - + + - - - + + + Location: - - - + + + QLayout::SetMaximumSize - - - - + + + + 0 0 - - - - + + + + 0 0 - + 30 0 - + 0 16777215 - + 0 0 - + ... - - - + + + Status: - - - + + + 100 0 - + 0 16777215 - + Private - + Public - - - + + + Allow List: - + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - + + - - <Disabled> + + <Disabled> - - - + + + QLayout::SetMaximumSize - + Qt::Horizontal - + 40 20 @@ -244,15 +237,15 @@ - - + + Add - - + + Remove @@ -261,16 +254,8 @@ - - - - 26 - 45 - 760 - 509 - - - + + Peer Calendars @@ -278,8 +263,15 @@ + + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    +
    - +
    diff --git a/retroshare-gui/src/gui/unfinished/GamesDialog.ui b/retroshare-gui/src/gui/unfinished/GamesDialog.ui index 074504d9d..95c5a4daf 100644 --- a/retroshare-gui/src/gui/unfinished/GamesDialog.ui +++ b/retroshare-gui/src/gui/unfinished/GamesDialog.ui @@ -77,7 +77,7 @@ p, li { white-space: pre-wrap; }
    - + GameType: 0. Want to Add your Game here? @@ -326,6 +326,13 @@ p, li { white-space: pre-wrap; }
    + + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    +
    diff --git a/retroshare-gui/src/gui/unfinished/LibraryDialog.ui b/retroshare-gui/src/gui/unfinished/LibraryDialog.ui index da20212c0..e7bb8319a 100644 --- a/retroshare-gui/src/gui/unfinished/LibraryDialog.ui +++ b/retroshare-gui/src/gui/unfinished/LibraryDialog.ui @@ -169,7 +169,7 @@
    - + 0 @@ -805,6 +805,13 @@ p, li { white-space: pre-wrap; }
    + + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    +
    diff --git a/retroshare-gui/src/gui/unfinished/PhotoDialog.cpp b/retroshare-gui/src/gui/unfinished/PhotoDialog.cpp index 42fd5acee..83009c267 100644 --- a/retroshare-gui/src/gui/unfinished/PhotoDialog.cpp +++ b/retroshare-gui/src/gui/unfinished/PhotoDialog.cpp @@ -42,7 +42,7 @@ /* Images for context menu icons */ #define IMAGE_REMOVEFRIEND ":/images/removefriend16.png" -#define IMAGE_REMOVE ":/images/cancel.png" +#define IMAGE_REMOVE ":/icons/cancel.svg" #define IMAGE_CHAT ":/images/chat.png" /* Images for Status icons */ #define IMAGE_PEER ":/images/user/identity16.png" diff --git a/retroshare-gui/src/gui/unfinished/PhotoShow.ui b/retroshare-gui/src/gui/unfinished/PhotoShow.ui index 112a63e4d..49e0be621 100644 --- a/retroshare-gui/src/gui/unfinished/PhotoShow.ui +++ b/retroshare-gui/src/gui/unfinished/PhotoShow.ui @@ -68,7 +68,7 @@ - + 320 x 320 @@ -94,7 +94,7 @@ - + 1 Sec @@ -243,8 +243,15 @@ + + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    +
    - + diff --git a/retroshare-gui/src/gui/unfinished/StatisticDialog.ui b/retroshare-gui/src/gui/unfinished/StatisticDialog.ui index 9543c0b83..6904b8b8f 100644 --- a/retroshare-gui/src/gui/unfinished/StatisticDialog.ui +++ b/retroshare-gui/src/gui/unfinished/StatisticDialog.ui @@ -486,7 +486,16 @@ 6 - + + 9 + + + 9 + + + 9 + + 9 @@ -496,7 +505,7 @@ - + 0 0 @@ -862,9 +871,9 @@
    - + - + 1 0 @@ -879,11 +888,20 @@ 6 - + + 9 + + + 9 + + + 9 + + 9 - + 120 @@ -900,7 +918,16 @@ 6 - + + 0 + + + 0 + + + 0 + + 0 @@ -938,7 +965,7 @@ - + 0 0 @@ -968,7 +995,16 @@ 6 - + + 9 + + + 9 + + + 9 + + 9 @@ -976,7 +1012,16 @@ 6 - + + 3 + + + 3 + + + 3 + + 3 @@ -1060,7 +1105,16 @@ 3 - + + 0 + + + 0 + + + 0 + + 0 @@ -1068,7 +1122,16 @@ 0 - + + 0 + + + 0 + + + 0 + + 0 @@ -1173,7 +1236,16 @@ 1 - + + 0 + + + 0 + + + 0 + + 0 diff --git a/retroshare-gui/src/gui/unfinished/profile/ProfileEdit.ui b/retroshare-gui/src/gui/unfinished/profile/ProfileEdit.ui index a4cdaf000..d1ff3203a 100644 --- a/retroshare-gui/src/gui/unfinished/profile/ProfileEdit.ui +++ b/retroshare-gui/src/gui/unfinished/profile/ProfileEdit.ui @@ -1,56 +1,57 @@ - + + ProfileEdit - - + + 0 0 - 540 + 571 469 - + Profile Edit - + Qt::LeftToRight - - - - + + + + Qt::Vertical - - + + - - + + 75 true - + Profile - - + + Qt::CustomContextMenu - + false - + Category - + Thoughts @@ -58,99 +59,99 @@ - - - - - + + + + + 75 true - + Edit Profile Category - - + + - + Birthday - + School - + University - + Phone Number - + Favourite Books - + Favourite Music - + Favourite Films - - - + + + Qt::RightToLeft - + or Custom Entry - - + + - - + + - - + + - - + + Add Entry - - + + :/images/add_24x24.png:/images/add_24x24.png - + Qt::Horizontal - + 71 28 @@ -159,36 +160,36 @@ - - + + Qt::RightToLeft - + Move - - + + :/images/down.png:/images/down.png - - + + Move - - + + :/images/up.png:/images/up.png - + Qt::Horizontal - + 71 28 @@ -197,15 +198,15 @@ - - + + Qt::RightToLeft - + Close Editor - - + + :/images/close_normal.png:/images/close_normal.png @@ -214,8 +215,15 @@ + + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    +
    - +
    diff --git a/retroshare-gui/src/lang/retroshare_bg.ts b/retroshare-gui/src/lang/retroshare_bg.ts index 86615025a..c57ad6a7a 100644 --- a/retroshare-gui/src/lang/retroshare_bg.ts +++ b/retroshare-gui/src/lang/retroshare_bg.ts @@ -84,13 +84,6 @@ - - AddCommentDialog - - Add Comment - Добави коментар - - AddFileAssociationDialog @@ -128,12 +121,12 @@ - + Search Criteria - + Add a further search criterion. @@ -143,7 +136,7 @@ - + Cancels the search. @@ -163,17 +156,6 @@ - - AlbumCreateDialog - - Description: - Описание: - - - Quality: - Качество: - - AlbumDialog @@ -202,10 +184,6 @@ Caption - - Description: - Описание: - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -562,7 +540,7 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. @@ -588,10 +566,23 @@ p, li { white-space: pre-wrap; } + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb @@ -634,7 +625,7 @@ p, li { white-space: pre-wrap; } Премахване на - + Set your Avatar picture @@ -721,7 +712,7 @@ p, li { white-space: pre-wrap; } Връщане - + Always on Top @@ -740,14 +731,6 @@ p, li { white-space: pre-wrap; } % Opaque - - Save - Запазване - - - Cancel - Отмяна - Since: @@ -825,7 +808,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment @@ -855,12 +838,12 @@ p, li { white-space: pre-wrap; } - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -868,7 +851,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up @@ -888,7 +871,7 @@ p, li { white-space: pre-wrap; } - + Posted by @@ -926,7 +909,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up @@ -946,7 +929,7 @@ p, li { white-space: pre-wrap; } - + Click to view picture @@ -976,7 +959,7 @@ p, li { white-space: pre-wrap; } - + Toggle Message Read Status @@ -986,7 +969,7 @@ p, li { white-space: pre-wrap; } Нов - + TextLabel @@ -994,12 +977,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this - + 0 @@ -1019,18 +1002,18 @@ p, li { white-space: pre-wrap; } - + New Comment - + Copy RetroShare Link - + Expand Разширяване @@ -1045,12 +1028,12 @@ p, li { white-space: pre-wrap; } Премахни елемент - + Name Име - + Comm value @@ -1219,17 +1202,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels - + Tabs - + General @@ -1239,7 +1222,17 @@ p, li { white-space: pre-wrap; } - + + Downloads + + + + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab @@ -1247,7 +1240,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1270,7 +1263,7 @@ into the image, so as to ChannelsCommentsItem - + I like this @@ -1295,18 +1288,18 @@ into the image, so as to - + New Comment - + Copy RetroShare Link - + Expand Разширяване @@ -1321,7 +1314,7 @@ into the image, so as to Премахни елемент - + Name Име @@ -1331,17 +1324,7 @@ into the image, so as to - - Comment - - - - - Comments - - - - + Hide Скрий @@ -1349,7 +1332,7 @@ into the image, so as to ChatLobbyDialog - + Name Име @@ -1540,7 +1523,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby @@ -1573,13 +1556,14 @@ into the image, so as to - + + Unknown Lobby - - + + Remove All @@ -1587,13 +1571,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Име - + Count @@ -1603,29 +1587,7 @@ into the image, so as to - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - - - - - - Public chat rooms - - - - + Create chat room @@ -1635,7 +1597,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1692,12 +1654,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1707,23 +1669,42 @@ Double click a chat room to enter and chat. - + [No topic provided] - + + Private Subscribed + + + + + + Public Subscribed + + + + + Private - + + + Public - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted @@ -1733,27 +1714,22 @@ Double click a chat room to enter and chat. - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe - + Search Chat lobbies - + Search Name - + Columns @@ -1768,47 +1744,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: - + Type: - + Security: - + Peers: - - - - - - + + + + + + TextLabel @@ -1823,7 +1799,7 @@ Double click a chat room to enter and chat. - + Show Показване @@ -1843,7 +1819,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item Премахни елемент @@ -1888,7 +1864,7 @@ Double click a chat room to enter and chat. ChatPage - + General @@ -1903,7 +1879,7 @@ Double click a chat room to enter and chat. - + Enable custom fonts @@ -1923,7 +1899,7 @@ Double click a chat room to enter and chat. - + General settings @@ -1948,7 +1924,7 @@ Double click a chat room to enter and chat. - + Blink tab icon @@ -1978,7 +1954,7 @@ Double click a chat room to enter and chat. - + Change Chat Font @@ -1988,7 +1964,7 @@ Double click a chat room to enter and chat. - + History @@ -2012,7 +1988,7 @@ Double click a chat room to enter and chat. - + Choose your default font for Chat. @@ -2082,12 +2058,22 @@ Double click a chat room to enter and chat. - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2097,7 +2083,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2194,7 +2190,7 @@ Double click a chat room to enter and chat. - + Case sensitive Чувствителност към регистъра @@ -2300,7 +2296,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat @@ -2336,7 +2332,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close @@ -2371,12 +2367,12 @@ Double click a chat room to enter and chat. - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2456,11 +2452,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2498,7 +2489,7 @@ Double click a chat room to enter and chat. - + is typing... @@ -2520,7 +2511,7 @@ after HTML conversion. - + Do you really want to physically delete the history? @@ -2570,7 +2561,7 @@ after HTML conversion. - + Find Case Sensitively @@ -2592,7 +2583,7 @@ after HTML conversion. - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> @@ -2607,12 +2598,12 @@ after HTML conversion. - + (Status) - + Attach a File @@ -2628,12 +2619,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> - + Person id: @@ -2644,12 +2635,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. @@ -2669,7 +2660,7 @@ Double click on it to add his name on text writer. - + Don't stop to color after @@ -2695,7 +2686,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: @@ -2717,7 +2708,7 @@ Double click on it to add his name on text writer. - + Personal Circles @@ -2743,7 +2734,7 @@ Double click on it to add his name on text writer. - + Friends @@ -2803,7 +2794,7 @@ Double click on it to add his name on text writer. - + External Circles (Admin) @@ -2819,7 +2810,7 @@ Double click on it to add his name on text writer. - + Circles @@ -2871,45 +2862,45 @@ Double click on it to add his name on text writer. - + RetroShare RetroShare - + - + Error : cannot get peer details. - + Retroshare ID - + <p>This Retroshare ID contains: - + <p>This certificate contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: @@ -2919,7 +2910,7 @@ Double click on it to add his name on text writer. - + Not connected @@ -3001,12 +2992,17 @@ Double click on it to add his name on text writer. без - + <li>a <b>node ID</b> and <b>name</b> - + + <b>DNS:</b> : + + + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3026,7 +3022,7 @@ Double click on it to add his name on text writer. - + with @@ -3094,7 +3090,7 @@ Double click on it to add his name on text writer. - + @@ -3110,12 +3106,12 @@ Double click on it to add his name on text writer. - + Peer details - + Name: Име: @@ -3125,17 +3121,17 @@ Double click on it to add his name on text writer. - + Options Настройки - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: @@ -3145,7 +3141,7 @@ Double click on it to add his name on text writer. - + Please paste below your friend's Retroshare ID @@ -3170,12 +3166,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with - + Sorry, some error appeared @@ -3195,32 +3201,27 @@ Double click on it to add his name on text writer. - + Key validity: - + Profile ID: - - Signers - - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. - + To accept the Friend Request, click the Accept button. @@ -3266,17 +3267,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed - + Not a valid Retroshare certificate! - + RetroShare Invitation @@ -3296,12 +3297,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3309,7 +3310,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3349,7 +3350,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Profile password needed. @@ -3374,7 +3375,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3384,7 +3385,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3423,7 +3424,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + IP-Addr: @@ -3433,7 +3434,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Show Advanced options @@ -3458,7 +3459,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already in your keyring @@ -3471,7 +3472,7 @@ even if you don't make friends. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. @@ -3506,7 +3507,7 @@ even if you don't make friends. - + No IP in this certificate! @@ -3516,12 +3517,7 @@ even if you don't make friends. - - [Unknown] - - - - + Added with certificate from %1 @@ -3586,7 +3582,7 @@ even if you don't make friends. - + UDP Setup @@ -3614,7 +3610,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant @@ -3624,17 +3620,20 @@ p, li { white-space: pre-wrap; } - + + Unknown State - + + Offline - + + Behind Symmetric NAT @@ -3644,12 +3643,14 @@ p, li { white-space: pre-wrap; } - + + NET Restart - + + Behind NAT @@ -3659,7 +3660,8 @@ p, li { white-space: pre-wrap; } - + + NET STATE GOOD! @@ -3684,7 +3686,7 @@ p, li { white-space: pre-wrap; } - + Lookup requires DHT @@ -3976,7 +3978,7 @@ p, li { white-space: pre-wrap; } - + @@ -3984,7 +3986,8 @@ p, li { white-space: pre-wrap; } - + + UNVERIFIABLE FORWARD! @@ -3994,7 +3997,7 @@ p, li { white-space: pre-wrap; } - + Searching @@ -4030,12 +4033,12 @@ p, li { white-space: pre-wrap; } - + Name Име - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4055,7 +4058,7 @@ p, li { white-space: pre-wrap; } - + IDs @@ -4075,18 +4078,18 @@ p, li { white-space: pre-wrap; } - + Cancel Отмяна - + Nickname - + Invited Members @@ -4101,11 +4104,7 @@ p, li { white-space: pre-wrap; } - Type - Тип - - - + Name: Име: @@ -4145,19 +4144,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - + Please set a name for your Circle - + No Restriction Circle Selected @@ -4167,12 +4166,24 @@ p, li { white-space: pre-wrap; } - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add Добавяне @@ -4182,7 +4193,7 @@ p, li { white-space: pre-wrap; } - + Search @@ -4235,13 +4246,13 @@ p, li { white-space: pre-wrap; } - + Create - + Add Member @@ -4260,7 +4271,7 @@ p, li { white-space: pre-wrap; } - + Group Name: @@ -4295,7 +4306,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post @@ -4305,7 +4316,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4450,17 +4461,17 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -4485,7 +4496,12 @@ p, li { white-space: pre-wrap; } - + + Cannot publish post + + + + Load thumbnail picture @@ -4500,18 +4516,12 @@ p, li { white-space: pre-wrap; } Скрий - - + Generate mass data - - Do you really want to generate %1 messages ? - - - - + You are about to add files you're not actually sharing. Do you still want this to happen? @@ -4545,7 +4555,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message @@ -4555,7 +4565,16 @@ p, li { white-space: pre-wrap; } Форум - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> + + + + Attach File @@ -4570,16 +4589,7 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> - - - - + Attach a Picture @@ -4594,7 +4604,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4624,17 +4634,17 @@ p, li { white-space: pre-wrap; } - + No Forum - + In Reply to - + Title Заглавие @@ -4687,7 +4697,7 @@ Do you want to discard this message? - + No compatible ID for this forum @@ -4697,8 +4707,8 @@ Do you want to discard this message? - - + + Generate mass data @@ -4721,7 +4731,7 @@ Do you want to discard this message? CreateLobbyDialog - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -4756,7 +4766,7 @@ Do you want to discard this message? - + Create @@ -4766,7 +4776,7 @@ Do you want to discard this message? Отмяна - + require PGP-signed identities @@ -4781,7 +4791,7 @@ Do you want to discard this message? - + Create Chat Room @@ -4802,7 +4812,7 @@ Do you want to discard this message? - + Identity to use: @@ -4810,17 +4820,17 @@ Do you want to discard this message? CryptoPage - + Public Information - + Name: Име: - + Location: @@ -4830,12 +4840,12 @@ Do you want to discard this message? - + Software Version: - + Online since: @@ -4855,12 +4865,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -4870,7 +4875,7 @@ Do you want to discard this message? - + Other Information @@ -4880,17 +4885,12 @@ Do you want to discard this message? - + Profile - - Certificate - - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -4900,7 +4900,7 @@ Do you want to discard this message? - + Export Identity @@ -4970,33 +4970,33 @@ and use the import button to load it - + TextLabel - + PGP fingerprint: - - Node information - - - - + PGP Id : - + Friend nodes: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5086,7 +5086,7 @@ and use the import button to load it DLListDelegate - + B @@ -5754,7 +5754,7 @@ and use the import button to load it DownloadToaster - + Start file @@ -5762,38 +5762,38 @@ and use the import button to load it ExprParamElement - + - + to - + ignore case - - - dd.MM.yyyy + + + yyyy-MM-dd - - + + KB - - + + MB - - + + GB @@ -5801,12 +5801,12 @@ and use the import button to load it ExpressionWidget - + Expression Widget - + Delete this expression @@ -5968,7 +5968,7 @@ and use the import button to load it FilesDefs - + Picture @@ -5978,7 +5978,7 @@ and use the import button to load it - + Audio @@ -6038,11 +6038,21 @@ and use the import button to load it C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories @@ -6164,7 +6174,7 @@ and use the import button to load it - + ID @@ -6206,7 +6216,7 @@ and use the import button to load it - + Group @@ -6242,7 +6252,7 @@ and use the import button to load it - + Search @@ -6258,7 +6268,7 @@ and use the import button to load it - + Profile details @@ -6495,7 +6505,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request @@ -6533,7 +6543,7 @@ at least one peer was not added to a group - + Mark all @@ -6544,16 +6554,132 @@ at least one peer was not added to a group + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Име + + + + Node ID + + + + + Address + + + + + Status + Статус + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message - - + + Broadcast @@ -6636,33 +6762,38 @@ at least one peer was not added to a group - + Keyring - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. - - + + Network - + + Friend Server + + + + Network graph - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. @@ -6680,7 +6811,17 @@ at least one peer was not added to a group Парола - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters @@ -6690,17 +6831,12 @@ at least one peer was not added to a group - + Port - - Use BOB - - - - + This password is for PGP @@ -6721,38 +6857,38 @@ at least one peer was not added to a group - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -6772,12 +6908,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -6787,38 +6923,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel - + hidden address - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -6862,13 +7003,13 @@ and use the import button to load it - + Import profile - + Create new profile and new Retroshare node @@ -6878,7 +7019,7 @@ and use the import button to load it - + Tor/I2P address @@ -6913,7 +7054,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -6923,12 +7064,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -6938,12 +7074,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7169,27 +7300,13 @@ and use the import button to load it - + Invite Friends - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - - - - + Add Your Friends to RetroShare @@ -7199,39 +7316,57 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + Connect To Friends - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port @@ -7239,49 +7374,45 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - - - - + Further Help and Support - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website @@ -7306,7 +7437,7 @@ p, li { white-space: pre-wrap; } - + RetroShare Invitation @@ -7356,12 +7487,12 @@ p, li { white-space: pre-wrap; } - + RetroShare Support - + It has many features, including built-in chat, messaging, @@ -7485,7 +7616,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat @@ -7493,7 +7624,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] @@ -7663,7 +7794,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title Заглавие @@ -7676,12 +7807,12 @@ p, li { white-space: pre-wrap; } - + Description - + Number of Unread message @@ -7706,7 +7837,7 @@ p, li { white-space: pre-wrap; } - + You are admin (modify names and description using Edit menu) @@ -7721,14 +7852,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post - + Name Име @@ -7739,13 +7870,13 @@ p, li { white-space: pre-wrap; } - + Never - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -7758,7 +7889,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and @@ -7894,7 +8025,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels @@ -7905,22 +8036,22 @@ p, li { white-space: pre-wrap; } - + Enable Auto-Download - + My Channels - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels @@ -7940,12 +8071,12 @@ p, li { white-space: pre-wrap; } - + Disable Auto-Download - + Set download directory @@ -7980,22 +8111,22 @@ p, li { white-space: pre-wrap; } - + Play - + Open folder - + Open file - + Error @@ -8015,17 +8146,17 @@ p, li { white-space: pre-wrap; } - + Are you sure that you want to cancel and delete the file? - + Can't open folder - + Play File @@ -8035,25 +8166,10 @@ p, li { white-space: pre-wrap; } - - GxsChannelFilesWidget - - Form - Формуляр - - - Title - Заглавие - - - Status - Статус - - GxsChannelGroupDialog - + Create New Channel @@ -8091,8 +8207,18 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel @@ -8107,7 +8233,7 @@ p, li { white-space: pre-wrap; } - + Expand Разширяване @@ -8122,7 +8248,7 @@ p, li { white-space: pre-wrap; } - + Loading @@ -8136,6 +8262,11 @@ p, li { white-space: pre-wrap; } New Channel: + + + Never + + Hide @@ -8145,7 +8276,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: @@ -8166,7 +8297,7 @@ p, li { white-space: pre-wrap; } - + Play @@ -8228,18 +8359,18 @@ p, li { white-space: pre-wrap; } Скрий - + New Нов - + 0 - - + + Comment @@ -8254,17 +8385,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + Comments - + Post @@ -8289,35 +8420,16 @@ p, li { white-space: pre-wrap; } - - GxsChannelPostsWidget - - Title - Заглавие - - - Search Title - Търсене в заглавието - - - Feeds - Информационни канали - - - Description: - Описание: - - GxsChannelPostsWidgetWithModel - + Post to Channel - + Add new post @@ -8387,7 +8499,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -8423,7 +8535,7 @@ p, li { white-space: pre-wrap; } - + Comments @@ -8438,13 +8550,13 @@ p, li { white-space: pre-wrap; } Информационни канали - - + + Click to switch to list view - + Show unread posts only @@ -8459,7 +8571,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -8474,7 +8586,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -8534,12 +8646,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -8614,12 +8736,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed @@ -8670,17 +8793,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -8795,7 +8918,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container @@ -8808,7 +8931,7 @@ p, li { white-space: pre-wrap; } Формуляр - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -8838,7 +8961,7 @@ p, li { white-space: pre-wrap; } - + Comment @@ -8877,7 +9000,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment @@ -8901,6 +9024,21 @@ p, li { white-space: pre-wrap; } Vote Down + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -8910,7 +9048,7 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -8939,7 +9077,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -8970,7 +9108,7 @@ before you can comment - + It remains %1 characters after HTML conversion. @@ -9021,7 +9159,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum @@ -9037,7 +9175,7 @@ before you can comment - + Expand Разширяване @@ -9056,6 +9194,11 @@ before you can comment Moderator list + + + TextLabel + + Loading... @@ -9085,13 +9228,13 @@ before you can comment GxsForumMsgItem - - + + Subject: - + Unsubscribe To Forum @@ -9102,7 +9245,7 @@ before you can comment - + Expand Разширяване @@ -9122,17 +9265,17 @@ before you can comment - + Loading... - + Forum Feed - + Hide Скрий @@ -9145,59 +9288,66 @@ before you can comment Формуляр - + Start new Thread for Selected Forum - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Търсене Форуми - + New Thread - - - Threaded View - - - - - Flat View - - - + Title Заглавие - - + + Date Дата - + Author Автор - - Save image - - - - + Loading - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9207,12 +9357,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message @@ -9252,23 +9397,23 @@ before you can comment Търсене на автор - + No name Няма име - - + + Reply - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -9311,16 +9456,12 @@ before you can comment - + Hide Скрий - Expand - Разширяване - - - + [unknown] @@ -9350,8 +9491,8 @@ before you can comment - - + + Distribution @@ -9365,10 +9506,6 @@ before you can comment Anti-spam - - none - без - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -9438,12 +9575,12 @@ before you can comment - + New thread - + Edit Редактиране @@ -9504,7 +9641,7 @@ before you can comment - + Show column @@ -9524,7 +9661,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive @@ -9576,7 +9713,7 @@ This message is missing. You should receive it later. - + No result. @@ -9586,7 +9723,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -9601,7 +9738,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -9667,12 +9804,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums @@ -9707,12 +9844,12 @@ This message is missing. You should receive it later. GxsGroupDialog - + Name Име - + Key recipients can publish to restricted-type group and can view and publish for private-type channels @@ -9723,12 +9860,12 @@ This message is missing. You should receive it later. - + Description - + Message Distribution @@ -9736,7 +9873,7 @@ This message is missing. You should receive it later. - + Public @@ -9796,7 +9933,7 @@ This message is missing. You should receive it later. - + Comments: @@ -9819,7 +9956,7 @@ This message is missing. You should receive it later. - + All People @@ -9835,12 +9972,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -9857,23 +9994,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -9889,22 +10026,28 @@ This message is missing. You should receive it later. - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo - + Submit Group Changes - + Owner: @@ -9914,12 +10057,12 @@ This message is missing. You should receive it later. - + Info - + ID @@ -9929,7 +10072,7 @@ This message is missing. You should receive it later. - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -10004,7 +10147,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity @@ -10020,27 +10168,22 @@ This message is missing. You should receive it later. - + Created - + Cancel Отмяна - + Create - - Author - Автор - - - + GxsIdLabel @@ -10048,7 +10191,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading @@ -10108,7 +10251,7 @@ This message is missing. You should receive it later. - + Synchronise posts of last... @@ -10165,12 +10308,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link @@ -10193,7 +10336,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature @@ -10206,14 +10349,14 @@ This message is missing. You should receive it later. GxsIdDetails - + Not found - - + + [Banned] @@ -10223,7 +10366,7 @@ This message is missing. You should receive it later. - + Loading... @@ -10233,7 +10376,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -10253,6 +10401,14 @@ This message is missing. You should receive it later. + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -10264,7 +10420,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -10312,7 +10468,7 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] @@ -10699,7 +10855,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -10715,7 +10871,7 @@ p, li { white-space: pre-wrap; } - + Authors @@ -10734,7 +10890,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -10808,7 +10964,7 @@ p, li { white-space: pre-wrap; } Формуляр - + Add friend @@ -10818,7 +10974,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -10846,7 +11002,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -10856,7 +11012,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard @@ -10866,7 +11022,7 @@ private and secure decentralized communication platform. - + Send via Email @@ -10886,13 +11042,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -10904,12 +11084,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -10924,12 +11104,7 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... @@ -11194,14 +11369,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All - + Reputation @@ -11211,12 +11386,12 @@ p, li { white-space: pre-wrap; } - + Anonymous Id - + Create new Identity @@ -11226,7 +11401,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -11241,27 +11416,27 @@ p, li { white-space: pre-wrap; } - + Close - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -11277,29 +11452,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles - + Circle name @@ -11319,18 +11504,20 @@ p, li { white-space: pre-wrap; } - + + Edit identity - + + Delete identity - + Chat with this peer @@ -11340,78 +11527,78 @@ p, li { white-space: pre-wrap; } - + Owner node ID : - + Identity name : - + () - + Identity ID - + Send message - + Identity info - + Identity ID : - + Owner node name : - + Create new... - + Type: - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: - + Negative - + Neutral @@ -11422,17 +11609,17 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous @@ -11447,24 +11634,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you - - + + My own identities - - + + My contacts - + Show Items @@ -11479,7 +11666,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -11489,7 +11681,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -11564,7 +11756,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -11594,7 +11786,7 @@ p, li { white-space: pre-wrap; } непознат - + Invited @@ -11609,7 +11801,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle @@ -11657,7 +11849,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -11665,7 +11857,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -11708,7 +11900,7 @@ These identities will soon be not supported anymore. - + Boards @@ -11788,7 +11980,7 @@ These identities will soon be not supported anymore. - + information @@ -11804,17 +11996,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -11919,7 +12106,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -11969,21 +12156,21 @@ These identities will soon be not supported anymore. - - - + + + People - + Your Avatar Click here to change your avatar - + Linked to neighbor nodes @@ -11993,7 +12180,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -12008,7 +12195,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -12023,12 +12210,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -12048,12 +12235,12 @@ These identities will soon be not supported anymore. - + Owned by - + Node name: @@ -12063,7 +12250,7 @@ These identities will soon be not supported anymore. - + Really delete? @@ -12071,7 +12258,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname @@ -12101,7 +12288,13 @@ These identities will soon be not supported anymore. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity @@ -12115,7 +12308,7 @@ These identities will soon be not supported anymore. - + @@ -12125,7 +12318,12 @@ These identities will soon be not supported anymore. - + + No avatar chosen + + + + Edit identity @@ -12136,27 +12334,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -12176,7 +12374,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -12186,12 +12384,18 @@ These identities will soon be not supported anymore. - + Error KeyID invalid - + + + No Avatar chosen. A default image will be automatically displayed from your new identity. + + + + Import image @@ -12201,12 +12405,7 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. - - - - + Unknown GpgId @@ -12216,7 +12415,7 @@ These identities will soon be not supported anymore. - + Create New Identity @@ -12226,10 +12425,15 @@ These identities will soon be not supported anymore. Тип - + Choose image... + + + Remove + Премахване на + @@ -12255,7 +12459,7 @@ These identities will soon be not supported anymore. Добавяне - + Create @@ -12265,13 +12469,13 @@ These identities will soon be not supported anymore. Отмяна - + Your Avatar Click here to change your avatar - + Linked to your profile @@ -12281,7 +12485,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -12355,7 +12559,7 @@ These identities will soon be not supported anymore. - + Copy Копиране @@ -12365,12 +12569,12 @@ These identities will soon be not supported anymore. Премахване на - + %1 's Message History - + Mark all @@ -12393,18 +12597,34 @@ These identities will soon be not supported anymore. ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -12422,27 +12642,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: - + Listen Address: - + + Status: + + + + 127.0.0.1 - + Token: @@ -12463,7 +12688,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -12472,26 +12702,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File - + Open Folder - + Checking... @@ -12501,7 +12736,7 @@ These identities will soon be not supported anymore. - + Recommend in a message to... @@ -12529,7 +12764,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend @@ -12545,7 +12780,8 @@ These identities will soon be not supported anymore. - + + Options Настройки @@ -12566,7 +12802,7 @@ These identities will soon be not supported anymore. - + Quit @@ -12577,12 +12813,12 @@ These identities will soon be not supported anymore. - + RetroShare %1 a secure decentralized communication platform - + Unfinished @@ -12607,11 +12843,12 @@ These identities will soon be not supported anymore. + Status Статус - + Notify @@ -12622,31 +12859,35 @@ These identities will soon be not supported anymore. + Open Messages - + + Bandwidth Graph - + Applications + Help Помощ - + + Minimize - + Maximize @@ -12661,7 +12902,12 @@ These identities will soon be not supported anymore. RetroShare - + + Close window + + + + %1 new message @@ -12691,7 +12937,7 @@ These identities will soon be not supported anymore. - + Do you really want to exit RetroShare ? @@ -12711,7 +12957,7 @@ These identities will soon be not supported anymore. Показване - + Make sure this link has not been forged to drag you to a malicious website. @@ -12756,12 +13002,13 @@ These identities will soon be not supported anymore. - + + Statistics - + Show web interface @@ -12776,7 +13023,7 @@ These identities will soon be not supported anymore. - + Really quit ? @@ -12785,17 +13032,17 @@ These identities will soon be not supported anymore. MessageComposer - + Compose - + Contacts - + Paragraph @@ -12831,12 +13078,12 @@ These identities will soon be not supported anymore. - + Font size - + Increase font size @@ -12851,32 +13098,32 @@ These identities will soon be not supported anymore. - + Italic - + Alignment - + Add an Image - + Sets text font to code style - + Underline - + Subject: @@ -12887,32 +13134,32 @@ These identities will soon be not supported anymore. - + Tags - + Address list: - + Recommend this friend - + Set Text color - + Set Text background color - + Recommended Files @@ -12982,7 +13229,7 @@ These identities will soon be not supported anymore. - + Send To: @@ -13022,7 +13269,7 @@ These identities will soon be not supported anymore. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> @@ -13042,18 +13289,18 @@ These identities will soon be not supported anymore. - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team - - + + Save Message - + Message has not been Sent. Do you want to save message to draft box? @@ -13064,7 +13311,17 @@ Do you want to save message to draft box? - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" @@ -13084,7 +13341,7 @@ Do you want to save message to draft box? - + Original Message @@ -13094,21 +13351,21 @@ Do you want to save message to draft box? - + - + To - - + + Cc - + Sent @@ -13123,7 +13380,7 @@ Do you want to save message to draft box? - + Re: @@ -13133,30 +13390,30 @@ Do you want to save message to draft box? - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? - + Please insert at least one recipient. - + Bcc - + Unknown Неизвестен @@ -13271,13 +13528,13 @@ Do you want to save message to draft box? - + Open File... - + HTML-Files (*.htm *.html);;All Files (*) @@ -13297,7 +13554,7 @@ Do you want to save message to draft box? - + Message has not been Sent. Do you want to save message ? @@ -13318,7 +13575,7 @@ Do you want to save message ? - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -13348,18 +13605,18 @@ Do you want to save message ? - - + + Close - + From: От: - + Bullet list (disc) @@ -13399,13 +13656,13 @@ Do you want to save message ? - - + + Thanks, <br> - + Distant identity: @@ -13415,12 +13672,12 @@ Do you want to save message ? - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -13498,7 +13755,7 @@ Do you want to save message ? По подразбиране - + A new tab @@ -13508,7 +13765,7 @@ Do you want to save message ? - + Edit Tag @@ -13531,7 +13788,7 @@ Do you want to save message ? MessageToaster - + Sub: @@ -13539,7 +13796,7 @@ Do you want to save message ? MessageUserNotify - + Message @@ -13567,7 +13824,7 @@ Do you want to save message ? MessageWidget - + Recommended Files @@ -13577,37 +13834,37 @@ Do you want to save message ? - + Subject: - + From: От: - + To: До: - + Cc: - + Bcc: - + Tags: - + Reply @@ -13647,7 +13904,7 @@ Do you want to save message ? - + Send Invite @@ -13699,7 +13956,7 @@ Do you want to save message ? - + Confirm %1 as friend @@ -13709,12 +13966,12 @@ Do you want to save message ? - + View source - + No subject @@ -13724,17 +13981,22 @@ Do you want to save message ? - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -13743,14 +14005,24 @@ Do you want to save message ? %1 (%2) + + + Show less + + + + + Show more + + - + Download all - + Print Document @@ -13765,12 +14037,12 @@ Do you want to save message ? - + Load images always for this message - + Hide the attachment pane @@ -13792,10 +14064,6 @@ Do you want to save message ? Compose - - Delete - Изтриване - Print @@ -13874,7 +14142,7 @@ Do you want to save message ? MessagesDialog - + New Message @@ -13884,20 +14152,16 @@ Do you want to save message ? - Delete - Изтриване - - - + - - + + Tags - - + + Inbox @@ -13927,17 +14191,17 @@ Do you want to save message ? - + Total Inbox: - + Quick View - + Print... @@ -13968,7 +14232,7 @@ Do you want to save message ? - + Subject @@ -13978,7 +14242,7 @@ Do you want to save message ? - + Date Дата @@ -13988,7 +14252,7 @@ Do you want to save message ? - + Search Subject @@ -13997,6 +14261,16 @@ Do you want to save message ? Search From + + + To + + + + + Search To + + Search Date @@ -14023,12 +14297,12 @@ Do you want to save message ? - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred @@ -14104,7 +14378,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -14118,7 +14392,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -14133,18 +14407,28 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts - + No Box selected. - + @@ -14179,7 +14463,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -14233,7 +14527,7 @@ Do you want to save message ? - + Expand Разширяване @@ -14243,7 +14537,7 @@ Do you want to save message ? Премахни елемент - + from @@ -14278,7 +14572,7 @@ Do you want to save message ? - + Hide Скрий @@ -14419,7 +14713,7 @@ Do you want to save message ? - + Remove unused keys... @@ -14429,7 +14723,7 @@ Do you want to save message ? - + Clean keyring @@ -14443,7 +14737,13 @@ Notes: Your old keyring will be backed up. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info @@ -14476,18 +14776,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. - - - Export/create a new node - - Trusted keys only - + Search name @@ -14497,12 +14792,12 @@ For security, your keyring was previously backed-up to file - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -14535,7 +14830,7 @@ Reported error: NewFriendList - + Offline Friends @@ -14556,7 +14851,7 @@ Reported error: - + Groups @@ -14586,19 +14881,19 @@ Reported error: - - + + Search - + ID - + Search ID @@ -14608,12 +14903,12 @@ Reported error: - + Show Items - + Last contact @@ -14623,7 +14918,7 @@ Reported error: - + Group @@ -14738,7 +15033,7 @@ Reported error: - + Do you want to remove this node? @@ -14748,7 +15043,7 @@ Reported error: - + Done! @@ -14855,7 +15150,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -14870,7 +15165,7 @@ at least one peer was not added to a group - + Newest on top @@ -14880,12 +15175,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15114,10 +15409,6 @@ at least one peer was not added to a group Disable All Toaster temporarily - - Feed - Емисия - Systray @@ -15127,7 +15418,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -15147,12 +15438,12 @@ at least one peer was not added to a group - + Please enter your Retroshare passphrase - + Unregistered plugin/executable @@ -15167,7 +15458,7 @@ at least one peer was not added to a group - + Test Тест @@ -15178,17 +15469,19 @@ at least one peer was not added to a group + Unknown title - + + Encrypted message - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -15196,7 +15489,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online @@ -15335,7 +15628,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -15380,12 +15678,7 @@ p, li { white-space: pre-wrap; } - - Options - Настройки - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -15431,21 +15724,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - - + + Error : cannot get peer details. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) @@ -15463,7 +15756,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -15539,12 +15832,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -15570,7 +15863,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat @@ -15591,7 +15884,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Премахни елемент - + Name: Име: @@ -15631,7 +15924,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message @@ -15689,7 +15982,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Скрий - + Send Message @@ -15856,13 +16149,6 @@ Warning: In your File-Transfer option, you select allow direct download to No. - - PhotoCommentItem - - Form - Формуляр - - PhotoDialog @@ -15935,10 +16221,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.... ... - - Add Comment - Добави коментар - Album @@ -16018,17 +16300,17 @@ p, li { white-space: pre-wrap; } - + My Albums - + Subscribed Albums - + Shared Albums @@ -16057,7 +16339,7 @@ requesting to edit it! PhotoSlideShow - + Album Name @@ -16116,19 +16398,19 @@ requesting to edit it! - - + + TextLabel - + Posted by - + ago @@ -16164,12 +16446,12 @@ requesting to edit it! PluginItem - + TextLabel - + Show more details about this plugin @@ -16380,12 +16662,27 @@ p, li { white-space: pre-wrap; } - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -16438,7 +16735,7 @@ p, li { white-space: pre-wrap; } Нов - + Vote up @@ -16458,8 +16755,8 @@ p, li { white-space: pre-wrap; } - - + + Comments @@ -16484,13 +16781,13 @@ p, li { white-space: pre-wrap; } - - + + Comment - + Comments @@ -16518,12 +16815,12 @@ p, li { white-space: pre-wrap; } PostedCreatePostDialog - + Create a new Post - + RetroShare RetroShare @@ -16538,12 +16835,22 @@ p, li { white-space: pre-wrap; } - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File - + Post image @@ -16559,7 +16866,17 @@ p, li { white-space: pre-wrap; } - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -16569,7 +16886,7 @@ p, li { white-space: pre-wrap; } - + Please add a Title @@ -16589,12 +16906,22 @@ p, li { white-space: pre-wrap; } - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -16609,7 +16936,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -16620,7 +16947,7 @@ p, li { white-space: pre-wrap; } - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -16630,7 +16957,7 @@ p, li { white-space: pre-wrap; } Заглавие - + Link @@ -16638,12 +16965,12 @@ p, li { white-space: pre-wrap; } PostedDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -16677,7 +17004,7 @@ p, li { white-space: pre-wrap; } PostedGroupDialog - + Create New Board @@ -16715,7 +17042,17 @@ p, li { white-space: pre-wrap; } PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted @@ -16731,7 +17068,7 @@ p, li { white-space: pre-wrap; } - + Expand Разширяване @@ -16746,12 +17083,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + + Never + + + + New Board @@ -16764,18 +17106,18 @@ p, li { white-space: pre-wrap; } PostedItem - + 0 - - + + Comments - + Copy RetroShare Link @@ -16786,12 +17128,12 @@ p, li { white-space: pre-wrap; } - + Comment - + Comments @@ -16801,7 +17143,7 @@ p, li { white-space: pre-wrap; } - + Click to view Picture @@ -16811,17 +17153,17 @@ p, li { white-space: pre-wrap; } Скрий - + Vote up - + Vote down - + Set as read and remove item Задай като четене и премахване на елемент @@ -16831,7 +17173,7 @@ p, li { white-space: pre-wrap; } Нов - + New Comment: @@ -16841,7 +17183,7 @@ p, li { white-space: pre-wrap; } - + Name Име @@ -16882,34 +17224,11 @@ p, li { white-space: pre-wrap; } - + Loading - - PostedListWidget - - Form - Формуляр - - - New - Нов - - - Next - Следващ - - - RetroShare - RetroShare - - - Previous - Предишна - - PostedListWidgetWithModel @@ -16928,7 +17247,17 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 @@ -16938,15 +17267,15 @@ p, li { white-space: pre-wrap; } - + - + unknown непознат - + Distribution: @@ -16956,42 +17285,42 @@ p, li { white-space: pre-wrap; } - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -17011,7 +17340,7 @@ p, li { white-space: pre-wrap; } - + Search @@ -17041,17 +17370,17 @@ p, li { white-space: pre-wrap; } - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -17066,12 +17395,17 @@ p, li { white-space: pre-wrap; } - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -17081,27 +17415,31 @@ p, li { white-space: pre-wrap; } Редактиране - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -17116,7 +17454,7 @@ p, li { white-space: pre-wrap; } - + Never @@ -17190,6 +17528,16 @@ p, li { white-space: pre-wrap; } No Channel Selected + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -17279,16 +17627,16 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -17396,7 +17744,7 @@ and use the import button to load it ProfileWidget - + Edit status message @@ -17412,7 +17760,7 @@ and use the import button to load it - + Public Information @@ -17447,12 +17795,12 @@ and use the import button to load it - + Other Information - + My Address @@ -17496,27 +17844,27 @@ and use the import button to load it PulseAddDialog - + Add to Pulse - + Display As - + URL - + GroupLabel - + IDLabel @@ -17526,12 +17874,12 @@ and use the import button to load it От: - + Head - + Head Shot @@ -17561,13 +17909,13 @@ and use the import button to load it - - + + Whats happening? - + @@ -17579,12 +17927,22 @@ and use the import button to load it - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -17599,7 +17957,7 @@ and use the import button to load it - + Reply to Pulse @@ -17614,30 +17972,24 @@ and use the import button to load it - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - Date - Дата - - - ... - ... + + Load Picture File + @@ -17648,7 +18000,7 @@ and use the import button to load it Формуляр - + @@ -17667,7 +18019,7 @@ and use the import button to load it PulseReply - + icn @@ -17677,7 +18029,7 @@ and use the import button to load it - + REPLY @@ -17704,7 +18056,7 @@ and use the import button to load it - + FOLLOW @@ -17714,7 +18066,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -17734,7 +18086,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -17850,7 +18202,7 @@ and use the import button to load it - + FOLLOW @@ -17858,37 +18210,42 @@ and use the import button to load it PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -17920,7 +18277,7 @@ and use the import button to load it - + FOLLOW @@ -17928,8 +18285,8 @@ and use the import button to load it QObject - - + + Confirmation @@ -18197,12 +18554,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + File Request canceled - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. @@ -18233,7 +18590,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + Cannot start Tor Manager! @@ -18267,7 +18624,7 @@ The error reported is:" - + Multiple instances @@ -18286,6 +18643,26 @@ The error reported is:" + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -18365,7 +18742,7 @@ Reported error is: - + You appear to have nodes associated to DSA keys: @@ -18375,7 +18752,7 @@ Reported error is: - + enabled @@ -18385,7 +18762,7 @@ Reported error is: - + Move IP %1 to whitelist @@ -18401,7 +18778,7 @@ Reported error is: - + %1 seconds ago @@ -18468,7 +18845,7 @@ Security: no anonymous IDs - + Join chat room @@ -18496,7 +18873,7 @@ Security: no anonymous IDs - + Indefinitely @@ -18676,13 +19053,29 @@ Security: no anonymous IDs Ban list + + + Name + Име + + Node + + + + + Address + + + + + Status Статус - + NXS @@ -18925,6 +19318,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -19064,7 +19469,7 @@ p, li { white-space: pre-wrap; } - + Network Wide @@ -19231,7 +19636,7 @@ p, li { white-space: pre-wrap; } Формуляр - + The loading of embedded images is blocked. @@ -19244,7 +19649,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default @@ -19417,12 +19822,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -19430,12 +19845,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -20123,7 +20538,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name Име @@ -20244,7 +20659,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name Име @@ -20264,7 +20679,7 @@ If you believe it is correct, remove the corresponding line from the file and re - + Profile ID @@ -20320,7 +20735,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -20334,11 +20749,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - - RsMessageModel @@ -20352,6 +20762,11 @@ prevents the message to be forwarded to your friends. From + + + To + + Subject @@ -20374,12 +20789,17 @@ prevents the message to be forwarded to your friends. - Click to sort by read + Click to sort by read status - Click to sort by from + Click to sort by author + + + + + Click to sort by destination @@ -20403,7 +20823,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -20424,7 +20846,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. @@ -20485,7 +20907,7 @@ prevents the message to be forwarded to your friends. - + Unable to open log file '%1': %2 @@ -20506,7 +20928,7 @@ prevents the message to be forwarded to your friends. - + opmode @@ -20536,7 +20958,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -20554,7 +20976,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -20571,12 +20993,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) - + Start Search @@ -20637,7 +21059,7 @@ prevents the message to be forwarded to your friends. - + KeyWords @@ -20652,7 +21074,7 @@ prevents the message to be forwarded to your friends. - + Filename @@ -20752,23 +21174,23 @@ prevents the message to be forwarded to your friends. - + File Name - + Download - + Copy RetroShare Link - + Send RetroShare Link @@ -20778,7 +21200,7 @@ prevents the message to be forwarded to your friends. - + Download Notice @@ -20815,7 +21237,7 @@ prevents the message to be forwarded to your friends. - + Folder Папка @@ -20826,17 +21248,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) - + Open Folder - + Create Collection... @@ -20856,7 +21278,7 @@ prevents the message to be forwarded to your friends. - + Collection @@ -20864,7 +21286,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details @@ -20880,22 +21302,22 @@ prevents the message to be forwarded to your friends. Премахни елемент - + IP address: - + Peer ID: - + Location: - + Peer Name: @@ -20912,7 +21334,7 @@ prevents the message to be forwarded to your friends. Скрий - + but reported: @@ -20937,8 +21359,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -20946,7 +21368,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare @@ -20977,7 +21399,7 @@ prevents the message to be forwarded to your friends. - + Expand Разширяване @@ -21022,12 +21444,12 @@ prevents the message to be forwarded to your friends. - + Write Message - + Connect Attempt @@ -21047,17 +21469,12 @@ prevents the message to be forwarded to your friends. - + Unknown Security Issue - - A unknown peer - - - - + Unknown Неизвестен @@ -21067,7 +21484,17 @@ prevents the message to be forwarded to your friends. - + + SSL request + + + + + An unknown peer + + + + Hide Скрий @@ -21077,7 +21504,7 @@ prevents the message to be forwarded to your friends. - + Certificate has wrong signature!! This peer is not who he claims to be. @@ -21087,12 +21514,12 @@ prevents the message to be forwarded to your friends. - + Certificate caused an internal error. - + Peer/node not in friendlist (PGP id= @@ -21151,12 +21578,12 @@ prevents the message to be forwarded to your friends. - + Local Address - + NAT @@ -21177,22 +21604,22 @@ prevents the message to be forwarded to your friends. - + Local network - + External ip address finder - + UPnP - + Known / Previous IPs: @@ -21205,21 +21632,16 @@ behind a firewall or a VPN. - - Allow RetroShare to ask my ip to these websites: - - - - - - + + + kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -21229,23 +21651,46 @@ behind a firewall or a VPN. - + Onion Address - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -21255,7 +21700,7 @@ behind a firewall or a VPN. - + I2P Address @@ -21280,37 +21725,95 @@ behind a firewall or a VPN. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -21325,71 +21828,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. непознат - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -21399,22 +21838,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -21426,12 +21850,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -21441,7 +21865,7 @@ Also check your ports! - + Download limit (KB/s) @@ -21456,23 +21880,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -21483,17 +21907,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -21503,12 +21917,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -21518,17 +21927,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -21568,7 +21967,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start @@ -21583,12 +21982,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - BOB status - - - - + Incoming @@ -21624,7 +22018,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -21679,7 +22098,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Warning: This bandwidth adds up to the max bandwidth. @@ -21704,7 +22123,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -21716,7 +22135,7 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Filters @@ -21739,7 +22158,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status Статус @@ -21799,17 +22218,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -21825,18 +22255,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -21871,12 +22301,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -21899,22 +22329,22 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -21949,7 +22379,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -21959,12 +22389,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -22044,7 +22474,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with @@ -22054,12 +22484,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Share - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -22078,7 +22508,7 @@ Select the Friends with which you want to Share your Channel. - + Shared directory @@ -22098,17 +22528,17 @@ Select the Friends with which you want to Share your Channel. - + Add new - + Cancel Отмяна - + Add a Share Directory @@ -22118,7 +22548,7 @@ Select the Friends with which you want to Share your Channel. Премахване на - + Apply and close @@ -22209,7 +22639,7 @@ Select the Friends with which you want to Share your Channel. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. @@ -22217,7 +22647,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files @@ -22268,11 +22698,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files - + Download selected @@ -22282,7 +22717,7 @@ Select the Friends with which you want to Share your Channel. - + Copy retroshare Links to Clipboard @@ -22297,7 +22732,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted @@ -22313,7 +22748,7 @@ Select the Friends with which you want to Share your Channel. - + Create Collection... @@ -22338,7 +22773,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted because they have not been indexed yet. @@ -22481,12 +22916,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration - + Create interface @@ -22510,7 +22945,7 @@ Select the Friends with which you want to Share your Channel. - + Log In @@ -22849,7 +23284,7 @@ This choice can be reverted in settings. - + Message: @@ -23086,7 +23521,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags @@ -23122,12 +23557,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown Неизвестен @@ -23137,18 +23575,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -23158,12 +23591,57 @@ p, li { white-space: pre-wrap; } - + + Error + + + + + Not connected + + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -23171,7 +23649,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -23181,7 +23659,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -23192,11 +23670,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -23224,7 +23703,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options @@ -23235,7 +23714,7 @@ p, li { white-space: pre-wrap; } - + Shared Directories @@ -23245,22 +23724,27 @@ p, li { white-space: pre-wrap; } - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -23345,7 +23829,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -23354,7 +23838,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -23379,7 +23868,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming @@ -23444,12 +23938,7 @@ p, li { white-space: pre-wrap; } - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -23459,7 +23948,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -23487,7 +23986,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed @@ -23515,19 +24014,19 @@ p, li { white-space: pre-wrap; } TransfersDialog - - + + Downloads - + Uploads - + Name i.e: file name Име @@ -23734,7 +24233,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... @@ -23759,7 +24263,7 @@ p, li { white-space: pre-wrap; } - + Anonymous end-to-end encrypted tunnel 0x @@ -23780,7 +24284,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -23813,7 +24317,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name @@ -23828,7 +24342,7 @@ p, li { white-space: pre-wrap; } - + Expand all @@ -23955,23 +24469,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns - + File Transfers - + Path Пътека @@ -23981,7 +24490,7 @@ p, li { white-space: pre-wrap; } - + Could not delete preview file @@ -23991,7 +24500,7 @@ p, li { white-space: pre-wrap; } - + Create Collection... @@ -24006,7 +24515,7 @@ p, li { white-space: pre-wrap; } - + Collection @@ -24016,7 +24525,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x @@ -24430,12 +24939,17 @@ p, li { white-space: pre-wrap; } Формуляр - + Enable Retroshare WEB Interface - + + Status: + + + + Web parameters @@ -24475,17 +24989,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -24495,12 +25019,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface @@ -24637,7 +25161,7 @@ p, li { white-space: pre-wrap; } - + Page Name @@ -24652,7 +25176,7 @@ p, li { white-space: pre-wrap; } - + << @@ -24740,7 +25264,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History @@ -24775,7 +25299,7 @@ p, li { white-space: pre-wrap; } - + \/ @@ -24805,14 +25329,18 @@ p, li { white-space: pre-wrap; } - - + + History + + + + Show Edit History - + Status Статус @@ -24833,7 +25361,7 @@ p, li { white-space: pre-wrap; } - + Submit @@ -24916,16 +25444,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - - - - + Settings @@ -24940,7 +25459,7 @@ p, li { white-space: pre-wrap; } - + Who to Follow @@ -24960,7 +25479,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -24990,11 +25509,7 @@ p, li { white-space: pre-wrap; } - New - Нов - - - + Yourself @@ -25004,7 +25519,7 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare @@ -25067,35 +25582,42 @@ p, li { white-space: pre-wrap; } Формуляр - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + Премахване на + + + Location: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -25140,11 +25662,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + + + + + Following + + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Неизвестен @@ -25222,7 +25774,7 @@ p, li { white-space: pre-wrap; } - + k e.g: 3.1 k @@ -25259,7 +25811,7 @@ p, li { white-space: pre-wrap; } pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_ca_ES.ts b/retroshare-gui/src/lang/retroshare_ca_ES.ts index fe57c6488..1e88b2136 100644 --- a/retroshare-gui/src/lang/retroshare_ca_ES.ts +++ b/retroshare-gui/src/lang/retroshare_ca_ES.ts @@ -84,13 +84,6 @@ Només node ocult - - AddCommentDialog - - Add Comment - Afegir comentari - - AddFileAssociationDialog @@ -128,12 +121,12 @@ RetroShare: Cerca Avançada - + Search Criteria Criteris de Cerca - + Add a further search criterion. Afegeix un altre criteri de cerca. @@ -143,7 +136,7 @@ Reinicialitzar els criteris de cerca. - + Cancels the search. Cancel·la la cerca. @@ -163,177 +156,6 @@ Cerca - - AlbumCreateDialog - - Create Album - Crear àlbum - - - Album Name: - Nom d'àlbum: - - - Category: - Categoria: - - - Animals - Animals - - - Family - Família - - - Friends - Amics - - - Flowers - Flors - - - Holiday - Vacances - - - Landscapes - Paisatges - - - Pets - Mascotes - - - Portraits - Retrats - - - Travel - Viatges - - - Work - Treball - - - Random - Aleatori - - - Caption: - Llegenda: - - - Where: - On: - - - Photographer: - Fotògraf: - - - Description: - Descripció: - - - Share Options - Opcions de compartició: - - - Policy: - Política: - - - Quality: - Qualitat: - - - Comments: - Comentari: - - - Identity: - Identitat: - - - Public - Públic - - - Restricted - Restringit - - - Resize Images (< 1Mb) - Redimensionar imatges (< 1Mb) - - - Resize Images (< 10Mb) - Redimensionar imatges (< 10Mb) - - - Send Original Images - Enviar imatges originals - - - No Comments Allowed - No es permeten els comentaris - - - Authenticated Comments - Comentaris autenticats - - - Any Comments Allowed - Qualsevol comentari permès - - - Publish with Identity - Publicar amb identitat - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Arrosegar i deixar per inserir imatges. Clica en una imatge per editar-ne els detalls a sota.</span></p></body></html> - - - Back - Enrere - - - Add Photos - Afegir fotos. - - - Publish Album - Publicar àlbum - - - Untitle Album - Àlbum sense títol - - - Say something about this album... - Digues alguna cosa sobre aquest àlbum... - - - Where were these taken? - On ha anat a parar això? - - - Load Album Thumbnail - Carrega la miniatura de l'àlbum - - AlbumDialog @@ -342,19 +164,11 @@ p, li { white-space: pre-wrap; } Album Àlbum - - Album Thumbnail - Miniatura de l'àlbum - TextLabel EtiquetaTexte - - Summary - Resum - Album Title: @@ -370,34 +184,6 @@ p, li { white-space: pre-wrap; } Caption Llegenda - - Where: - On: - - - When - Quan - - - Description: - Descripció: - - - Share Options - Opcions de compartició: - - - Comments - Comentaris - - - Publish Identity - Publicar identitat - - - Visibility - Visibilitat - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -766,7 +552,7 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. Avís: Els serveis aquí esmentat són experimentals. Si us plau, ajuda'ns a testejar-los. @@ -782,14 +568,6 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem Circles Cercles - - GxsForums - FòrumsGxs - - - GxsChannels - CanalsGxs - The Wire @@ -801,10 +579,23 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem Fotos + + AspectRatioPixmapLabel + + + Save image + Desar imatge + + + + Copy image + + + AttachFileItem - + %p Kb %p kb @@ -841,17 +632,13 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem Browse... - - Add Avatar - Afegir avatar - Remove Treure - + Set your Avatar picture Tria la fotografia del teu avatar @@ -870,10 +657,6 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - Carrega avatar - AvatarWidget @@ -942,22 +725,10 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem Restablir - Receive Rate - Taxa de Recepció - - - Send Rate - Taxa d'enviament - - - + Always on Top Sempre per damunt - - Style - Estil - Changes the transparency of the Bandwidth Graph @@ -973,23 +744,11 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem % Opaque % Opac - - Save - Desa - - - Cancel - Cancel·la - Since: Des de: - - Hide Settings - Amagar opcions - BandwidthStatsWidget @@ -1062,7 +821,7 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem BoardPostDisplayWidgetBase - + Comment Comentari @@ -1092,12 +851,12 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem Copia l'enllaç RetroShare - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> <p><font color="#ff0000"><b>L'autor d'aquest missatge (amb Id %1) està expulsat.</b> - + ago @@ -1105,7 +864,7 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem BoardPostDisplayWidget_card - + Vote up Votar positiu @@ -1125,7 +884,7 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem \/ - + Posted by @@ -1163,7 +922,7 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem BoardPostDisplayWidget_compact - + Vote up Votar positiu @@ -1183,7 +942,7 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem \/ - + Click to view picture @@ -1213,7 +972,7 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem Compartir - + Toggle Message Read Status Canvia l'estat dels missatges llegits @@ -1223,7 +982,7 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem Nou - + TextLabel @@ -1231,12 +990,12 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem BoardsCommentsItem - + I like this M'agrada - + 0 0 @@ -1256,18 +1015,18 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem Avatar - + New Comment - + Copy RetroShare Link Copia l'enllaç RetroShare - + Expand Ampliar @@ -1282,12 +1041,12 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem Eliminar l'element - + Name Nom - + Comm value @@ -1456,17 +1215,17 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem ChannelPage - + Channels Canals - + Tabs Pestanyes - + General General @@ -1476,11 +1235,17 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem - Load posts in background (Thread) - Carrega les entrades en segon pla (Utilitza fils) + + Downloads + Descarregues - + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab Obrir cada canal en una nova pestanya @@ -1488,7 +1253,7 @@ Però recorda: Totes les dades generades aquí *SERAN* perdudes quan actualitzem ChannelPostDelegate - + files @@ -1511,7 +1276,7 @@ into the image, so as to ChannelsCommentsItem - + I like this M'agrada @@ -1536,18 +1301,18 @@ into the image, so as to Avatar - + New Comment - + Copy RetroShare Link Copia l'enllaç RetroShare - + Expand Ampliar @@ -1562,7 +1327,7 @@ into the image, so as to Eliminar l'element - + Name Nom @@ -1572,17 +1337,7 @@ into the image, so as to - - Comment - Comentari - - - - Comments - Comentaris - - - + Hide Amagar @@ -1590,7 +1345,7 @@ into the image, so as to ChatLobbyDialog - + Name Nom @@ -1781,7 +1536,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby Mostra el xat de sala @@ -1793,22 +1548,6 @@ into the image, so as to Chats Xats - - You have %1 new messages - Tens %1 nous missatges - - - You have %1 new message - Tens %1 nou missatge - - - %1 new messages - %1 missatges nous - - - %1 new message - %1 missatges nous - You have %1 mentions @@ -1830,13 +1569,14 @@ into the image, so as to - + + Unknown Lobby Sala desconeguda - - + + Remove All Suprimeix-ho tot @@ -1844,13 +1584,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Nom - + Count Comte @@ -1860,33 +1600,7 @@ into the image, so as to Tema - - Private Subscribed chat rooms - Sales de xat privades subscrites - - - - - Public Subscribed chat rooms - Sales de xat públiques subscrites - - - - Private chat rooms - Sales de xat privades - - - - - Public chat rooms - Sales de xat públiques - - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/images/add_24x24.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Sales de xat</h1> <p>Les sales de xat són sales distribuïdes que funcionen molt semblant a les de IRC. Et permeten parlar anònimament amb moltíssima gent sense haver-los de fer amics.</p> <p>Una sala de xat pot ser pública (els teus amics la veuen ) o privades (els teus amics no poden veure-la si no els invites amb <img src=":/images/add_24x24.png" width=%2/>). Un cop has sigut invitat a una sala privada podràs veure quan els teus amics la estan usant.</p> <p>La llista de l'esquerra mostra sales de xat en que participen els teus amics. Pots o bé <ul> <li>Fer clic dret per crear una sala de xat nova</li> <li>Fer doble clic per entrar a una sala, xatejar, i que els teus amics ho vegin</li> </ul> Nota: Per a que les sales de xat funcionin correctament el teu ordinador a d'anar a l'hora. Comprova-ho! </p> - - - + Create chat room Crear sala de xat @@ -1896,7 +1610,7 @@ into the image, so as to Abandonar sala - + Create a non anonymous identity and enter this room Crear una identitat no anònima i entrar a aquesta sala @@ -1955,12 +1669,12 @@ Selecciona entre les sales de la esquerra per mostrar-ne els detalls. Fes doble clic a les sales per entrar-hi i xatejar. - + %1 invites you to chat room named %2 %1 t'invita a una sala de xat anomenada %2 - + Choose a non anonymous identity for this chat room: Escull una identitat no anònima per aquesta sala: @@ -1970,31 +1684,31 @@ Fes doble clic a les sales per entrar-hi i xatejar. Escull una identitat per aquesta sala: - Create chat lobby - Crear sala de xat - - - + [No topic provided] [No s'ha proporcionat cap assumpte] - Selected lobby info - Informació de la sala seleccionada - - - + + Private Privat - + + + Public Públic - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted IDs anònimes acceptades @@ -2004,42 +1718,25 @@ Fes doble clic a les sales per entrar-hi i xatejar. Eliminar auto-subscripció - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe Afegir auto-subscripció - + Search Chat lobbies Cercar sales de xat - + Search Name Cercar nom - Subscribed - Subscrit - - - + Columns Columnes - - Yes - - - - No - No - Chat rooms @@ -2051,47 +1748,47 @@ Fes doble clic a les sales per entrar-hi i xatejar. - + Chat Room info - + Chat room Name: Nom de la sala de xat: - + Chat room Id: Id de la sala de xat: - + Topic: Tema: - + Type: Tipus: - + Security: Seguretat: - + Peers: Contactes: - - - - - - + + + + + + TextLabel EtiquetaText @@ -2106,13 +1803,24 @@ Fes doble clic a les sales per entrar-hi i xatejar. Ids anònims prohibits - + Show Mostra - + + Private Subscribed + + + + + + Public Subscribed + + + + column columna @@ -2126,7 +1834,7 @@ Fes doble clic a les sales per entrar-hi i xatejar. ChatMsgItem - + Remove Item Eliminar l'element @@ -2171,46 +1879,22 @@ Fes doble clic a les sales per entrar-hi i xatejar. ChatPage - + General General - - Distant Chat - Xat distant - Everyone Tothom - - Contacts - Contactes - Nobody Ningú - Accept encrypted distant chat from - Acceptar xats distants encriptats de - - - Chat Settings - Configuració xat - - - Enable Emoticons Private Chat - Activa les emoticones al xat privat - - - Enable Emoticons Group Chat - Activa emoticones pels xats en grup - - - + Enable custom fonts Activa tipus de lletra personalitzats @@ -2219,10 +1903,6 @@ Fes doble clic a les sales per entrar-hi i xatejar. Enable custom font size Activa mida de lletra personalitzat - - Minimum font size - Mida de lletra mínima - Enable bold @@ -2234,7 +1914,7 @@ Fes doble clic a les sales per entrar-hi i xatejar. Activa cursiva - + General settings @@ -2259,11 +1939,7 @@ Fes doble clic a les sales per entrar-hi i xatejar. Carrega imatges incrustades - Chat Lobby - Sala de xat - - - + Blink tab icon Icona de pestanya parpellejant @@ -2272,10 +1948,6 @@ Fes doble clic a les sales per entrar-hi i xatejar. Do not send typing notifications No enviar avís d'estar escribint - - Private Chat - Xat privat - Open Window for new chat @@ -2297,11 +1969,7 @@ Fes doble clic a les sales per entrar-hi i xatejar. Icona de pestanya/finestra parpellejant - Chat Font - Tipus de lletra pel xat - - - + Change Chat Font Canviar tipografia pel xat @@ -2311,14 +1979,10 @@ Fes doble clic a les sales per entrar-hi i xatejar. Tipus de lletra pel xat: - + History Històric - - Style - Estil - @@ -2333,17 +1997,13 @@ Fes doble clic a les sales per entrar-hi i xatejar. Variant: Variant: - - Group chat - Xat en grup - Private chat Xat privat - + Choose your default font for Chat. Escull una tipografia pel Xat. @@ -2407,22 +2067,28 @@ Fes doble clic a les sales per entrar-hi i xatejar. <html><head/><body><p align="justify">In this tab you can setup how many chat messages Retroshare will keep saved on the disc and how much of the previous conversation it will display, for the different chat systems. The max storage period allows to discard old messages and prevents the chat history from filling up with volatile chat (e.g. chat lobbies and distant chat).</p></body></html> <html><head/><body><p align="justify">En aquesta pestanya pots modificar quants missatges de xat el RetroShare mantindrà emmagatzemats en disc i quantes de les converses prèvies mostrarà pels diferents sistemes de xat. El període màxim d'emmagatzematge et permet descartar missatges vells i impedeix que l'historial de xat s'ompli amb xats esporàdics (per ex. sales de xat i xats distants).</p></body></html> - - Chatlobbies - Salesxat - Enabled: Activat: - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2432,7 +2098,17 @@ Fes doble clic a les sales per entrar-hi i xatejar. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms Sales de xat @@ -2529,11 +2205,7 @@ Fes doble clic a les sales per entrar-hi i xatejar. Període màxim d'emmagatzemat, en dies (0=Il·limitat): - Search by default - Cerca per defecte - - - + Case sensitive Diferenciar majúscules/minúscules @@ -2572,10 +2244,6 @@ Fes doble clic a les sales per entrar-hi i xatejar. Threshold for automatic search Límit per fer una cerca automàtica - - Default identity for chat lobbies: - Identitat per defecte per les sales de xat: - Show Bar by default @@ -2643,7 +2311,7 @@ Fes doble clic a les sales per entrar-hi i xatejar. ChatToaster - + Show Chat Mostra xat @@ -2679,7 +2347,7 @@ Fes doble clic a les sales per entrar-hi i xatejar. ChatWidget - + Close Tancar @@ -2714,12 +2382,12 @@ Fes doble clic a les sales per entrar-hi i xatejar. Cursiva - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon Insertar emoticona @@ -2728,10 +2396,6 @@ Fes doble clic a les sales per entrar-hi i xatejar. Attach a Picture Adjunta una imatge - - <html><head/><body><p>QToolButton:disabled {</p><p> image: url(:/icons/png/send-message-blocked.png) ;</p><p>}</p><p><br/></p></body></html> - <html><head/><body><p>QToolButton:desactivat {</p><p> imatge: url(:/icons/png/send-message-blocked.png) ;}</p><p>}</p><p><br/></p></body></html> - Strike @@ -2803,11 +2467,6 @@ Fes doble clic a les sales per entrar-hi i xatejar. Insert horizontal rule Inserir regla horitzontal - - - Save image - Desar imatge - Import sticker @@ -2845,7 +2504,7 @@ Fes doble clic a les sales per entrar-hi i xatejar. - + is typing... està escrivint... @@ -2869,7 +2528,7 @@ després de convertir a HTML. Escull el tipus de lletra - + Do you really want to physically delete the history? Segur que vols eliminar físicament l'historial? @@ -2919,7 +2578,7 @@ després de convertir a HTML. està ocupat i pot no respondre - + Find Case Sensitively Cercar diferenciant majúscules i minúscules @@ -2941,7 +2600,7 @@ després de convertir a HTML. No deixis de colorejar fins trobar X elements (Necessita més UCP) - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> <b>Trobar anterior </b><br/><i>Ctrl+Shift+G</i> @@ -2956,16 +2615,12 @@ després de convertir a HTML. <b>Trobar </b><br/><i>Ctrl+F</i> - + (Status) (Estat) - Set text font & color - Estableix tipus de lletra i color - - - + Attach a File Adjunta un arxiu @@ -2981,12 +2636,12 @@ després de convertir a HTML. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> <b>Marca el text seleccionat</b><br><i>Ctrl+M</i> - + Person id: Id de la persona: @@ -2998,12 +2653,12 @@ Double click on it to add his name on text writer. Doble clic per afegir el seu nom al text escrit. - + Unsigned No signat - + items found. Elements trobats. @@ -3023,7 +2678,7 @@ Doble clic per afegir el seu nom al text escrit. Escriu un missatge aquí - + Don't stop to color after No t'aturis a colorejar després de @@ -3049,7 +2704,7 @@ Doble clic per afegir el seu nom al text escrit. CirclesDialog - + Showing details: Mostrant detalls: @@ -3071,7 +2726,7 @@ Doble clic per afegir el seu nom al text escrit. - + Personal Circles Cercles personals @@ -3097,7 +2752,7 @@ Doble clic per afegir el seu nom al text escrit. - + Friends Amics @@ -3157,7 +2812,7 @@ Doble clic per afegir el seu nom al text escrit. Amics dels amics - + External Circles (Admin) Cercles externs (Admin) @@ -3173,7 +2828,7 @@ Doble clic per afegir el seu nom al text escrit. - + Circles Cercles @@ -3225,43 +2880,48 @@ Doble clic per afegir el seu nom al text escrit. - + RetroShare RetroShare - + - + Error : cannot get peer details. Error: no es poden obtenir detalls del contacte. - + Retroshare ID - + <p>This Retroshare ID contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: + + + <b>DNS:</b> : + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3273,7 +2933,7 @@ Doble clic per afegir el seu nom al text escrit. Encriptació - + Not connected No connectat @@ -3355,25 +3015,17 @@ Doble clic per afegir el seu nom al text escrit. cap - + <p>This certificate contains: <p>Aquest certificat conté: - + <li>a <b>node ID</b> and <b>name</b> <li>un<b>ID de node</b> i <b>nom</b> - an <b>onion address</b> and <b>port</b> - una <b>adreça onion</b> i <b>port</b> - - - an <b>IP address</b> and <b>port</b> - una <b>adreça IP</b> i <b>port</b> - - - + <p>You can use this certificate to make new friends. Send it by email, or give it hand to hand.</p> <p>Pots utilitzar aquest certificat per fer nous amics. Envia'l per correu o entrega'l en ma.</p> @@ -3388,7 +3040,7 @@ Doble clic per afegir el seu nom al text escrit. <html><head/><body><p>Aquest és el mètode d'encriptat utilitzat per <span style=" font-weight:600;">OpenSSL</span>. La conexió cap a nodes amics</p><p>és sempre forta i si hi ha DHE disponible la conexió a més a més utilitza</p><p>&quot;perfect forward secrecy&quot;.</p></body></html> - + with amb @@ -3405,118 +3057,16 @@ Doble clic per afegir el seu nom al text escrit. Connect Friend Wizard Auxiliar de connexió amb amic - - Add a new Friend - Afegir un nou amic - - - &You get a certificate file from your friend - &El teu amic et proporciona un arxiu de certificat - - - &Make friend with selected friends of my friends - &Fes-te amic dels amics seleccionats dels teus amics - - - &Send an Invitation by Email - (Your friend will receive an email with instructions how to download RetroShare) - &Envia una invitació per correu electrònic -(El teu amic rebrà un correu electrònic amb instruccions sobre com descarregar el RetroShare) - - - Include signatures - Inclou les signatures - - - Copy your Cert to Clipboard - Copiar el teu certificat al porta-retalls - - - Save your Cert into a File - Desar el teu certificar en un arxiu - - - Run Email program - Executa el programa de correu electrònic - Open Cert of your friend from File Obre el certificat d'un amic des d'un arxiu - - Open certificate - Obre un certificat - - - Please, paste your friend's Retroshare certificate into the box below - Si us plau, enganxa el certificat de Retroshare dels teus amics a la caixa inferior - - - Certificate files - Arxiu de certificat - - - Use PGP certificates saved in files. - Utilitza certificats PGP desat en arxius. - - - Import friend's certificate... - Importa certificats d'amics... - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - Has de generar un arxiu amb el teu certificat i donar-lo al teu amic. També pots utilitzar un arxiu generat anteriorment. - - - Export my certificate... - Exportar el meu certificat... - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - Arrossega i deixa el certificat dels teus amics a aquesta finestra o especifica una ubicació a la part inferior - - - Browse - Navegar - - - Friends of friends - Amics d'amics - - - Select now who you want to make friends with. - Selecciona amb qui et vols fer amic ara. - - - Show me: - Mostra-m'ho: - - - Make friend with these peers - Fer-se amic amb aquests contactes - RetroShare ID ID RetroShare - - Use RetroShare ID for adding a Friend which is available in your network. - Utilitza la Id de RetroShare per afegir un amic que es troba disponible a la xarxa. - - - Add Friends RetroShare ID... - Afegir amics utilitzant la Id de RetroShare... - - - Paste Friends RetroShare ID in the box below - Enganxar Id de RetroShare de l'amic a la casella inferior - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - Introdueix el Id de RetroShare del teu amic, ex. Contacte@BDE8D16A46D938CF - RetroShare is better with Friends @@ -3558,27 +3108,7 @@ Doble clic per afegir el seu nom al text escrit. Correu electrònic - Invite Friends by Email - Convidar amics per correu electrònic - - - Enter your friends' email addresses (separate each one with a semicolon) - Introdueix l'adreça de correu electrònic dels teus amics (Separa-les amb un punt i coma) - - - Your friends' email addresses: - L'adreça de correu electrònic dels teus amics: - - - Enter Friends Email addresses - Introdueix les adreces de correu electrònic dels teus amics - - - Subject: - Assumpte: - - - + @@ -3594,77 +3124,32 @@ Doble clic per afegir el seu nom al text escrit. Detalls sobre la petició - + Peer details Detalls del contacte - + Name: Nom: - - Email: - Correu electrònic: - - - Node: - Node: - - - Please note that RetroShare will require excessive amounts of bandwidth, memory and CPU if you add too many friends. You can add as many friends as you like, but more than 40 will probably require too much -resources. - Si us plau, tingues en compte que RetroShare necessitarà una quantitat excessiva d'ample de banda, memòria i CPU si afegeixes masses amics. Pots afegir tants amics com vulguis, però més de 40 serà probablement excessiu. - Location: Ubicació: - + Options Opcions - This wizard will help you to connect to your friend(s) to RetroShare network.<br>Select how you would like to add a friend: - Aquest assistent t'ajudarà a connectar amb el(s) teu(s) amic(s) de la xarxa RetroShare.<br>Escull com t'agradaria afegir un amic: - - - Enter the certificate manually - Introdueix el certificat manualment - - - Enter RetroShare ID manually - Introdueix la Id de RetroShare manualment - - - &Send an Invitation by Web Mail Providers - &Envia una Invitació utilitzant web mail - - - Recommend many friends to each other - Recomanar molts amics els uns als altres - - - RetroShare certificate - Certificat Retroshare - - - Please paste below your friend's Retroshare certificate - Si us plau, enganxa el certificat de Retroshare del teu amic aquí sota - - - Paste certificate - Enganxar certificat - - - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> <html><head/><body><p>Aquesta casella espera el certificat de Retroshare del teu amic. AVÍS: No és el mateix que la clau del perfil del teu amic. No enganxis la clau del perfil del teu amic aquí (Ni tan sols part d'ella). No funcionarà.</p></body></html> - + Add friend to group: Afegir amic al grup: @@ -3674,7 +3159,7 @@ resources. Autentica amic (Signa clau PGP) - + Please paste below your friend's Retroshare ID @@ -3699,16 +3184,22 @@ resources. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with Afegir com amic amb qui connectar - To accept the Friend Request, click the Finish button. - Per acceptar la petició de l'amic, clica al botó acabar. - - - + Sorry, some error appeared Ho sentim, ha aparegut algun error @@ -3728,32 +3219,27 @@ resources. Detalls sobre el teu amic: - + Key validity: Validesa de la clau: - + Profile ID: - - Signers - Signants - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Signar la clau d'un amic és una forma d'expressar la teva confiança en aquest amic als teus altres amics. Les signatures a sota testimonien criptogràficament que els propietaris de les claus llistades reconeixen la clau PGP com autèntica. </span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. Aquest contacte ja és a la llista d'amics. Afegir-lo potser només actualitzi la seva adreça IP. - + To accept the Friend Request, click the Accept button. @@ -3799,49 +3285,17 @@ resources. - + Certificate Load Failed Càrrega de certificat fallida - Cannot get peer details of PGP key %1 - No es poden aconseguir els detalls del contacte de la clau PGP %1 - - - Any peer I've not signed - Qualsevol contacte que no he signat - - - Friends of my friends who already trust me - Amics dels meus amics que ja confien en mi - - - Signed peers showing as denied - Contactes signats mostrats com denegats - - - Peer name - Nom del contacte - - - Also signed by - També signat per - - - Peer id - Id contacte - - - Certificate appears to be valid - El certificat sembla vàlid - - - + Not a valid Retroshare certificate! No és un certificat de Retroshare vàlid! - + RetroShare Invitation Invitació al RetroShare @@ -3863,12 +3317,12 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? Aquest és el teu certificat! No vols fer-te amic amb tu mateix, oi? - + @@ -3876,7 +3330,7 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir - + This key is already on your trusted list Aquesta clau ja és a la teva llista de confiança @@ -3916,7 +3370,7 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir Tens una petició d'amic de - + Profile password needed. @@ -3941,7 +3395,7 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir - + Valid Retroshare ID @@ -3951,47 +3405,7 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir - Certificate Load Failed:file %1 not found - Carrega de certificat fallada: No es troba l'arxiu %1 - - - This Peer %1 is not available in your Network - El contacte %1 no està disponible a la teva xarxa - - - Use new certificate format (safer, more robust) - Utilitza el format nou de certificat (més robust i segur) - - - Use old (backward compatible) certificate format - Utilitza el format de certificat antic (Compatible amb versions anteriors) - - - Remove signatures - Elimina signatures - - - RetroShare Invite - Invita al RetroShare - - - Connect Friend Help - Ajuda de connectar amic - - - You can copy this text and send it to your friend via email or some other way - Pots copiar aquest text i enviar-lo al teu amic per correu electrònic a un altre mètode - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - S'ha copiat el teu certificat al porta-retalls, enganxa'l i envia'l al teu amic per correu - - - Save as... - Desa com... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -4030,11 +3444,7 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir *** Cap *** - Use as direct source, when available - Utilitza com a font directa quan estigui disponible - - - + IP-Addr: Adreça IP: @@ -4044,7 +3454,7 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir Adreça IP: - + Show Advanced options Mostrar opcions avançades @@ -4053,10 +3463,6 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Signar la clau d'un amic és una forma d'expressar la teva confiança en aquest amic als teus altres amics. Els ajudarà a decidir si volen acceptar o no connexions d'aquesta clau basant-se en la teva confiança. Signar una clau és completament opcional i no es pot desfer, fes-ho amb cura.</span></p></body></html> - - <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> - <html><head/><body><p align="justify">El Retroshare periòdicament comprova la teva llista d'amics per arxius navegables que coincideixin amb els mateixos que estàs descarregant, per establir una transferència directa. En aquest cas els teus amics sabran què descarregues.</p><p align="justify">Si no vols que això passi per algun amic en concret, desmarca aquesta casella. Encara podràs realitzar transferències directes si ho demanes explícitament, per exemple descarregant de la llista del teu amic directament. Això s'aplicarà a totes les ubicacions del mateix node.</p></body></html> - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> @@ -4067,45 +3473,13 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir <html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> <html><head/><body><p>Els contactes que tenen aquesta opció no poden connectar-se si la seva adreça no és a la llista blanca. Això et protegeix d'atacs de reenviament. Quan s'usen, els contactes refusats són notificats a la secció de Novetats amb un tiquet de seguretat. Des d'allí es pot decidir que fer amb la IP. S'aplica a totes les ubicacions del mateix node.</p></body></html> - - Recommend many friends to each others - Recomanar molts amics els uns als altres - - - Friend Recommendations - Recomanacions de l'amic - - - The text below is your Retroshare certificate. You have to provide it to your friend - El text a sota és el teu certificat de Retroshare. L'has de proporcionar al teu amic - - - Message: - Missatge: - - - Recommend friends - Recomanar amics - - - To - A - - - Please select at least one friend for recommendation. - Si us plau, escull almenys un amic per recomanació. - - - Please select at least one friend as recipient. - Si us plau, selecciona almenys un amic com a destinatari. - Add key to keyring Afegeix clau al clauer - + This key is already in your keyring Aquesta claus ja és al clauer @@ -4121,7 +3495,7 @@ missatges distants a aquest contacte encara que no sigueu amics. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. El certificat té un nombre de versió erroni. Recorda que les xarxes v0.6 i v0.5 són incompatibles. @@ -4156,7 +3530,7 @@ encara que no sigueu amics. Afegir la IP a la llista blanca - + No IP in this certificate! Aquest certificat no té IP! @@ -4166,27 +3540,10 @@ encara que no sigueu amics. <p>Aquest certificat no té IP. Només podràs utilitzar descobriment i DHT per trobar-lo. Com que és necessari que estigui a la llista blanca d'IPs el contacte provocarà un avís a la pestanya de Novetats. Des d'allí podràs afegir la IP a la llista blanca.</p> - - [Unknown] - [Desconegut] - - - + Added with certificate from %1 Afegit amb el certificat de %1 - - Paste Cert of your friend from Clipboard - Enganxa el certificat del teu amic des del porta-retalls - - - Certificate Load Failed:can't read from file %1 - Carrega de certificat fallada: no es pot llegir de l'arxiu %1 - - - Certificate Load Failed:something is wrong with %1 - Carrega de certificat fallada: Hi ha alguna cosa malament amb %1 - ConnectProgressDialog @@ -4248,7 +3605,7 @@ encara que no sigueu amics. - + UDP Setup Configuració UDP @@ -4284,7 +3641,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:13pt;">pots tancar-lo.</span></p></body></html> - + Connection Assistant Auxiliar de connexió @@ -4294,17 +3651,20 @@ p, li { white-space: pre-wrap; } Id contacte invàlida - + + Unknown State Estat desconegut - + + Offline Fora de línia - + + Behind Symmetric NAT Darrera NAT simètric @@ -4314,12 +3674,14 @@ p, li { white-space: pre-wrap; } Darrera NAT i sense DHT - + + NET Restart Reiniciar xarxa - + + Behind NAT Darrera NAT @@ -4329,7 +3691,8 @@ p, li { white-space: pre-wrap; } Sense DHT - + + NET STATE GOOD! ESTAT DE LA XARXA BO! @@ -4354,7 +3717,7 @@ p, li { white-space: pre-wrap; } Trobant contactes RS - + Lookup requires DHT Descobriment requereix DHT @@ -4646,7 +4009,7 @@ p, li { white-space: pre-wrap; } Si us plau, intenta-ho important un certificat complet - + @@ -4654,7 +4017,8 @@ p, li { white-space: pre-wrap; } N/A - + + UNVERIFIABLE FORWARD! REENVIAMENT NO VERIFICABLE! @@ -4664,7 +4028,7 @@ p, li { white-space: pre-wrap; } REENVIAMENT NO VERIFICABLE I SENSE DHT - + Searching Cercant @@ -4700,12 +4064,12 @@ p, li { white-space: pre-wrap; } Detalls del cercle - + Name Nom - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> <html><head/><body><p>El nom del cercle, contacte de l'autor i la llista de membres invitats serà visible a tots els membres invitats. Si el cercle no és privat, també serà visible pels nodes veïns dels nodes que pertanyen als membres invitats.</p></body></html> @@ -4725,7 +4089,7 @@ p, li { white-space: pre-wrap; } - + IDs Ids @@ -4745,18 +4109,18 @@ p, li { white-space: pre-wrap; } Filtre - + Cancel - + Nickname Sobrenom - + Invited Members Membres convidats @@ -4771,15 +4135,7 @@ p, li { white-space: pre-wrap; } Gent Coneguda - ID - ID - - - Type - Tipus - - - + Name: Nom: @@ -4819,23 +4175,19 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Els cercles poden restringir-se a membres d'un altre cercle. Només els membres d'aquest segon cercle podran veure el nou cercle i el contingut (llistat de membres, etc.).</p></body></html> - Only visible to members of: - Només visible a membres de: - - - - + + RetroShare RetroShare - + Please set a name for your Circle Si us plau, introdueix un nom pel teu cercle - + No Restriction Circle Selected No s'ha seleccionat cap cercle de restricció @@ -4845,12 +4197,24 @@ p, li { white-space: pre-wrap; } No s'ha seleccionat cap cercle de limitacions - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] [Desconegut] - + Add Afegir @@ -4860,7 +4224,7 @@ p, li { white-space: pre-wrap; } Treure - + Search Cercar @@ -4875,10 +4239,6 @@ p, li { white-space: pre-wrap; } Signed Signat - - Signed by known nodes - Signat per nodes coneguts - Edit Circle @@ -4895,10 +4255,6 @@ p, li { white-space: pre-wrap; } PGP Identity Identitat PGP - - Anon Id - Id anonima - Circle name @@ -4921,17 +4277,13 @@ p, li { white-space: pre-wrap; } Crear Nou Cercle - + Create Crear - PGP Linked Id - Id enllaç PGP - - - + Add Member Afegir Membre @@ -4950,7 +4302,7 @@ p, li { white-space: pre-wrap; } Crear grup - + Group Name: Nom del grup: @@ -4985,7 +4337,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post Nova entrada al canal @@ -4995,7 +4347,7 @@ p, li { white-space: pre-wrap; } Entrada al canal - + Post @@ -5056,23 +4408,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Fes arrossegar i deixar / Botó d'afegir arxius per calcular el número de hash d'arxius nous.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Copiar/Enganxar enllaços RetroShare dels teus compartits</span></p></body></html> - - Add File to Attach - Afegir arxiu per adjuntar - Add Channel Thumbnail Afegir miniatura del canal - - Message - Missatge - - - Subject : - Assumpte: - @@ -5158,17 +4498,17 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -5187,17 +4527,18 @@ p, li { white-space: pre-wrap; } The following files will only be shared for 30 days. Think about adding them to a shared directory. - - File already Added and Hashed - Arxiu ja afegit i hash calculat - Please add a Subject Si us plau, afegeix un assumpte - + + Cannot publish post + + + + Load thumbnail picture Carrega miniatura @@ -5212,18 +4553,12 @@ p, li { white-space: pre-wrap; } Amagar - - + Generate mass data Generar dades en massa - - Do you really want to generate %1 messages ? - Segur que vols generar %1 missatges? - - - + You are about to add files you're not actually sharing. Do you still want this to happen? Estàs a punt d'afegir arxius que ara mateix no comparteixes. Segur que ho vols fer? @@ -5257,7 +4592,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message Publica missatge al fòrum @@ -5266,10 +4601,6 @@ p, li { white-space: pre-wrap; } Forum Fòrum - - Subject - Assumpte - Attach File @@ -5290,8 +4621,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -5310,7 +4641,7 @@ p, li { white-space: pre-wrap; } Podeu adjuntar arxius arrossegant i deixant anar en aquesta finestra - + Post @@ -5340,17 +4671,17 @@ p, li { white-space: pre-wrap; } - + No Forum Sense fòrum - + In Reply to En resposta a - + Title Títol @@ -5404,7 +4735,7 @@ Vols descartar aquest missatge? Carrega arxiu d'imatge - + No compatible ID for this forum No hi ha un ID compatible amb aquest fòrum @@ -5414,8 +4745,8 @@ Vols descartar aquest missatge? Cap de les teves identitats té permès publicar en aquest fòrum. Això pot deures a que el fòrum estigui limitat a un cercle que no té cap de les teves identitats, o a que el fòrum requereixi una identitat signada amb PGP. - - + + Generate mass data Generar dades en massa @@ -5424,10 +4755,6 @@ Vols descartar aquest missatge? Do you really want to generate %1 messages ? Segur que vols generar %1 missatges? - - Send - Enviar - Post as @@ -5442,23 +4769,7 @@ Vols descartar aquest missatge? CreateLobbyDialog - Create Chat Lobby - Crear sala de xat - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - Un sala de xat és un grup de xat descentralitzat i anònim. Tots els participants reben tots els missatges. Un cop la sala és creada pots invitar altres amics de la pestanya d'amics. - - - Lobby name: - Nom de la sala: - - - Lobby topic: - Assumpte de la sala: - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5493,7 +4804,7 @@ Vols descartar aquest missatge? - + Create Crear @@ -5503,11 +4814,7 @@ Vols descartar aquest missatge? - <html><head/><body><p>If you check this, only PGP-signed ids can be used to join and talk in this lobby. This limitation prevents anonymous spamming as it becomes possible for at least some people in the lobby to locate the spammer's node.</p></body></html> - <html><head/><body><p>Si marques aquí només ids signades amb PGP podran ser utilitzades per accedir i parlar a la sala. Aquesta limitació evita l'spam anònim donat que esdevé possible que, com a mínim algunes de les persones de la sala, puguin localitzar el node de l'spammer.</p></body></html> - - - + require PGP-signed identities requereix identitats signades amb PGP @@ -5522,11 +4829,7 @@ Vols descartar aquest missatge? Escull els amics amb qui vols fer un xat en grup. - Invited friends - Amics convidats - - - + Create Chat Room Crear sala de xat @@ -5547,7 +4850,7 @@ Vols descartar aquest missatge? Contactes: - + Identity to use: Identitat a utilitzar: @@ -5555,17 +4858,17 @@ Vols descartar aquest missatge? CryptoPage - + Public Information Informació pública - + Name: Nom: - + Location: Ubicació: @@ -5575,12 +4878,12 @@ Vols descartar aquest missatge? Id d'ubicació: - + Software Version: Versió de programari: - + Online since: En línia des de: @@ -5600,12 +4903,7 @@ Vols descartar aquest missatge? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5615,7 +4913,7 @@ Vols descartar aquest missatge? - + Other Information Altra informació @@ -5625,17 +4923,12 @@ Vols descartar aquest missatge? - + Profile Perfil - - Certificate - Certificat - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5645,11 +4938,7 @@ Vols descartar aquest missatge? Inclou les signatures - Save Key into a file - Desa la clau a un arxiu - - - + Export Identity Exportar identitat @@ -5722,33 +5011,33 @@ i utilitzar el botó d'importació per carregar-lo - + TextLabel EtiquetaText - + PGP fingerprint: fingerprint PGP: - - Node information - Informació de node - - - + PGP Id : Id PGP: - + Friend nodes: Nodes de l'amic: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5787,14 +5076,6 @@ i utilitzar el botó d'importació per carregar-lo Node Node - - Create new node... - Crear node nou... - - - show statistics window - mostra la finestra d'estadístiques - DHTGraphSource @@ -5811,10 +5092,6 @@ i utilitzar el botó d'importació per carregar-lo DHT DHT - - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your friends to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your friends.</p> - <p>Retroshare utilitza el DHT de Bittorrent com a repetidor per les connexions. No emmagatzema la teva IP al DHT. ⇥⇥⇥⇥ En lloc d'això el DHT és utilitzat pels teus contactes per contactar amb tu mentre es processen peticions DHT estàndard. ⇥⇥⇥⇥⇥⇥⇥⇥⇥⇥⇥⇥L'indicador d'estat es tornarà verd tan aviat com el Retroshare obtingui una resposta per DHT d'un dels teus amics.</p> - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your trusted nodes to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your trusted nodes.</p> @@ -5850,7 +5127,7 @@ i utilitzar el botó d'importació per carregar-lo DLListDelegate - + B B @@ -6518,7 +5795,7 @@ i utilitzar el botó d'importació per carregar-lo DownloadToaster - + Start file Arxiu d'inici @@ -6526,38 +5803,38 @@ i utilitzar el botó d'importació per carregar-lo ExprParamElement - + - + to a - + ignore case ignora majúscules/minúscules - - - dd.MM.yyyy - dd.mm.aaaa + + + yyyy-MM-dd + - - + + KB kB - - + + MB MB - - + + GB GB @@ -6565,12 +5842,12 @@ i utilitzar el botó d'importació per carregar-lo ExpressionWidget - + Expression Widget Giny d'expressió - + Delete this expression Suprimir aquesta expressió @@ -6732,7 +6009,7 @@ i utilitzar el botó d'importació per carregar-lo FilesDefs - + Picture Imatge @@ -6742,7 +6019,7 @@ i utilitzar el botó d'importació per carregar-lo Vídeo - + Audio Àudio @@ -6802,11 +6079,21 @@ i utilitzar el botó d'importació per carregar-lo C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Directoris dels amics @@ -6928,7 +6215,7 @@ i utilitzar el botó d'importació per carregar-lo - + ID ID @@ -6963,10 +6250,6 @@ i utilitzar el botó d'importació per carregar-lo Show State Mostrar Estat - - Trusted nodes - Nodes de confiança - @@ -6974,7 +6257,7 @@ i utilitzar el botó d'importació per carregar-lo Mostra grups - + Group Grup @@ -7010,7 +6293,7 @@ i utilitzar el botó d'importació per carregar-lo Afegir al grup - + Search Cerca @@ -7026,7 +6309,7 @@ i utilitzar el botó d'importació per carregar-lo Ordena per estat - + Profile details Detalls del perfil @@ -7270,7 +6553,7 @@ com a mínim un dels contactes no s'ha afegit a un grup FriendRequestToaster - + Confirm Friend Request Confirma la petició d'amic @@ -7287,10 +6570,6 @@ com a mínim un dels contactes no s'ha afegit a un grup FriendSelectionWidget - - Search : - Cercar: - Sort by state @@ -7312,7 +6591,7 @@ com a mínim un dels contactes no s'ha afegit a un grup Busca als amics - + Mark all Marcar tots/es @@ -7323,16 +6602,134 @@ com a mínim un dels contactes no s'ha afegit a un grup Marcar cap + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Nom + + + + Node ID + + + + + Address + Adreça + + + + Status + Estat + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + Fer amic + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + El repetidor no està activat o està trencat. +Estan tots els serveis funcionant correctament?? +Comprova els teus ports! + + FriendsDialog - + Edit status message Editar missatge d'estat - - + + Broadcast Difusió @@ -7415,33 +6812,38 @@ com a mínim un dels contactes no s'ha afegit a un grup Restablir tipografia per defecte - + Keyring Clauer - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - <h1><img width="32" src=":/images/help_64.png">&nbsp;&nbsp;Xarxa</h1> <p>La pestanya Xarxa mostra els nodes RertoShare dels teus amics: Els nodes de RetroShare veïns amb que estàs.connectat. </p> <p>Pots agrupar els nodes en grups per millorar el control de l'accés a les dades, per permetre només a alguns nodes veure alguns arxius.</p> <p>A la dreta, trobaràs 3 útils pestanyes: <ul> <li>Difusió envia missatges a tots els nodes connectats a la vegada</li><li>El gràfic de xarxa propera mostra la xarxa al teu voltant, basant-se en la informació de descobriment</li> <li>Anell de claus conté les claus que tens, principalment les reenviades pels nodes dels teus amics cap a tu</li> </ul> </p> - - - + Retroshare broadcast chat: messages are sent to all connected friends. Xat de difusió del RetroShare: Els missatges són enviats a tots els amics connectats. - - + + Network Xarxa - + + Friend Server + + + + Network graph Gràfic de xarxa - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. Estableix aquí el teu missatge d'estat. @@ -7459,7 +6861,17 @@ com a mínim un dels contactes no s'ha afegit a un grup Contrasenya - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters Tots els camps són obligatoris amb un mínim de 3 caràcters @@ -7469,17 +6881,12 @@ com a mínim un dels contactes no s'ha afegit a un grup Les contrasenyes no coincideixen - + Port Port - - Use BOB - Utilitza BOB - - - + This password is for PGP Aquesta contrasenya és pel PGP @@ -7500,50 +6907,38 @@ com a mínim un dels contactes no s'ha afegit a un grup Ha fallat la generació del teu nou certificat, potser la contrasenya PGP sigui incorrecta! - Options - Opcions - - - + PGP Key Length Longitud de clau PGP - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> <html><head/><body><p>Utilitza una contrasenya complicada. Aquesta contrasenya protegeix la clau privada del teu node!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> <html><head/><body><p>Si us plau, mou el ratolí una mica per captar tanta aleatorietat com sigui possible. És necessari arribar fins el 20% per crear la clau del teu node.</p></body></html> - + Standard node Node estàndard - TOR/I2P Hidden node - Node ocult Tor/I2P - - - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> <html><head/><body><p>El nom del teu node estableix la instancia de Retroshare que</p><p>s'executarà en el teu ordinador.</p></body></html> - Use existing profile - Tornar a utilitzar un perfil existent - - - + Node name Nom del node - + Node type: @@ -7563,12 +6958,12 @@ com a mínim un dels contactes no s'ha afegit a un grup - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> <html><head/><body><p>El nom del perfil t'identifica a tu a la xarxa.</p><p>És l'utilitzat pels teus amics per acceptar les teves connexions.</p><p>Pots crear multiples nodes de Retroshare amb el</p><p>mateix perfil a ordinadors diferents.</p><p><br/></p></body></html> - + Export this profle Exportar aquest perfil @@ -7578,42 +6973,43 @@ com a mínim un dels contactes no s'ha afegit a un grup - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> <html><head/><body><p>Pot ser una adreça Tor Onion del tipus: xa76giaf6ifda7ri63i263.onion <br/>o una adreça I2P del tipus: [52 caràcters].b32.i2p </p>Per tal d'obtindre'n una has de configurar o Tor o I2P per crear un nou servei ocult/servidor de túnel. <p><p>Pots deixar-ho en blanc ara, però el teu node només funcionarà si poses una adreça Tor/I2P a les opcions del Retroshare a Opcions>Xarxa->Panell de configuració de servei ocult.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> <html><head/><body><p>Les identitats s'utilitzen quan escrius en sales de xat, fòrums i comentaris en canals. </p><p>També s'empren quan envies/reps correus electrònics per la xarxa de Retroshare. Pots crear </p><p>una identitat signada ara o deixar-ho per més tard, quan ho necessitis.</p></body></html> - + Go! Som-hi! - - + + TextLabel EtiquetaText - Advanced options - Opcions avançades - - - + hidden address adreça oculta - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. El teu perfil està associat a un parell de clau PGP. RetroShare ara mateix ignora les claus DSA. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> <html><head/><body><p>Aquest és el teu port de connexió.</p><p>Qualsevol valor entre 1024 i 65535 </p><p>serà vàlid. Podràs canviar-ho més tard.</p></body></html> @@ -7661,13 +7057,13 @@ i utilitzar el botó d'importació per carregar-lo El teu perfil no s'ha desat. Hi ha hagut un error. - + Import profile Importar perfil - + Create new profile and new Retroshare node Crear un nou perfil i un node nou de Retroshare @@ -7677,7 +7073,7 @@ i utilitzar el botó d'importació per carregar-lo Crear un node nou de Retroshare - + Tor/I2P address Adreça Tor/I2P @@ -7712,7 +7108,7 @@ i utilitzar el botó d'importació per carregar-lo - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7722,12 +7118,7 @@ i utilitzar el botó d'importació per carregar-lo - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> <p>La creació de node està desactivada fins que els camps estiguin completats correctament.</p> @@ -7737,12 +7128,7 @@ i utilitzar el botó d'importació per carregar-lo <p>La creació de node està desactivada fins que s'hagi acumulat suficient aleatorietat. Si us plau, mou el ratolí fins que arribis com a mínim al 20%.</p> - - I2P instance address with BOB enabled - Adreça de la instancia I2P amb BOB activat. - - - + I2P instance address Adreça instancia I2P @@ -7968,36 +7354,13 @@ i utilitzar el botó d'importació per carregar-lo Començant - + Invite Friends Convidar amics - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">El RetroShare és res sense els teus amics. Clica en el botó per començar el procés.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Envia una invitació per correu electrònic amb el teu "Id de Certificat" al teus amics.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Assegurat de rebre la seva invitació també... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Només pots connectar-te amb els teus amics si tots dos us heu afegit com amics.</span></p></body></html> - - - + Add Your Friends to RetroShare Afegir els teus amics al RetroShare @@ -8007,136 +7370,103 @@ p, li { white-space: pre-wrap; } Afegir amics - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> - p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Estigues en línia a la vegada que els teus amics i el Retroshare automàticament us connectarà!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">El teu client necessita trobar la xarxa Retroshare abans de poder fer les connexions.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Això pot trigar entre 5-30 minuts la primera vegada que engegues el RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">L'indicador de DHT (A la barra d'estat) es tornarà Verda quan pugui realitzar connexions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Al cap d'un parell de minuts, l'indicador de NAT (També a la barra d'estat) canviarà a Groc o Verd.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Si continua Vermell, tens un Tallafocs Dolentot que el Retroshare té problemes per travessar.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Busca a la secció d'Ajuda Extra per més consells sobre connectar-se.</span></p></body></html> + + Connect To Friends + Connectar-se als amics - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Pots millorar el rendiment del Retroshare obrint un port extern. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Això accelerarà les connexions i permetrà que més gent connecti amb tu. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">La forma més senzilla de fer-ho és activant el UPnP en el teu encaminador o aparell Wifi.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Com que cada encaminador és diferent hauràs de ser tu qui trobi les instruccions per com fer-ho.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Si no saps de que t'estem parlant no hi pensis més, el Retroshare continuarà funcionant.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Avançat: Obrir port del tallafocs <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Tens problemes per iniciar-te amb el RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Mira la PMF Viqui. És una mica antiga, estem intentant posar-la al dia.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Busca en els fòrums en línia. Fes preguntes i parla sobre les possibilitats.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Prova els fòrums interns de RetroShare </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">⇥- Apareixeran com disponibles quan et connectis amb amics.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) Si tot i així estàs encallat. Envia'ns un correu.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Disfruta utilitzant el RetroShare</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> + - - Connect To Friends - Connectar-se als amics - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Quan els teus amics t'envien la seva invitació, clica per obrir la finestra Afegir amics..</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enganxa el &quot;Certificat ID&quot; dels teus amics a la finestra i afegeix-los com amics.</span></p></body></html> - - - - Advanced: Open Firewall Port - Avançat: Obrir port del tallafocs - - - + Further Help and Support Més ajuda i suport - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website Obrir lloc web del RS @@ -8161,7 +7491,7 @@ p, li { white-space: pre-wrap; } Resposta de correu electrònic - + RetroShare Invitation Invitació al RetroShare @@ -8211,12 +7541,12 @@ p, li { white-space: pre-wrap; } Resposta per RetroShare - + RetroShare Support Suport del RetroShare - + It has many features, including built-in chat, messaging, Té múltiples utilitats, incloent-hi xat, missatgeria, @@ -8340,7 +7670,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat Mostra xat en grup @@ -8348,7 +7678,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] [Desconegut] @@ -8514,20 +7844,11 @@ p, li { white-space: pre-wrap; } You can let your friends know about your forum by sharing it with them. Select the friends with which you want to share your forum. Pots fer que els teus amics sàpiguen del teu fòrum compartint-lo amb ells. Escull els amics amb qui vols compartir el teu fòrum. - - Share topic admin permissions - Compartir els permisos d'administrador del tema - - - You can allow your friends to edit the topic. Select them in the list below. Note: it is not possible to revoke Posted admin permissions. - Pots permetre als teus amics editar el tema. Selecciona'ls a la llista inferior. -Nota: No es poden revocar els permisos d'administrador publicats - GroupTreeWidget - + Title Títol @@ -8540,12 +7861,12 @@ Nota: No es poden revocar els permisos d'administrador publicats - + Description Descripció - + Number of Unread message @@ -8570,35 +7891,7 @@ Nota: No es poden revocar els permisos d'administrador publicats - Sort Descending Order - Ordena en ordre descendent - - - Sort Ascending Order - Ordena en ordre ascendent - - - Sort by Name - Ordena per nom - - - Sort by Popularity - Ordena per popularitat - - - Sort by Last Post - Ordena per darrer missatge - - - Sort by Number of Posts - Ordenar per nombre de publicacións - - - Sort by Unread - Ordena per no llegit - - - + You are admin (modify names and description using Edit menu) Ets l'administrador (Modifica noms i descripció utilitzant el menú Editar) @@ -8613,14 +7906,14 @@ Nota: No es poden revocar els permisos d'administrador publicatsId - - + + Last Post Darrera publicació - + Name Nom @@ -8631,17 +7924,13 @@ Nota: No es poden revocar els permisos d'administrador publicatsPopularitat - + Never Mai - Display - Mostra - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8654,7 +7943,7 @@ Nota: No es poden revocar els permisos d'administrador publicats GuiExprElement - + and i @@ -8790,7 +8079,7 @@ Nota: No es poden revocar els permisos d'administrador publicats GxsChannelDialog - + Channels Canals @@ -8801,26 +8090,22 @@ Nota: No es poden revocar els permisos d'administrador publicatsCrear canal - + Enable Auto-Download Activa l'auto-descàrrega - + My Channels Els meus canals - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Canals</h1> <p>Canals et permet publicar dades (Ex: pel·lícules, música) que es propagaran per la xarxa</p> <p>Pots veure els canals als que tens amics subscrits i tu faràs el mateix amb els teus. Això promociona els canals populars dins la xarxa.</p> <p>Només el creador del canal pot publicar en un canal. Els altres contactes a la xarxa només poden llegir el canal, a no ser que el canal sigui privat. No obstant, pots compartir els drets de publicació o lectura amb nodes de Retroshare amics.</p> <p>Els canals poden ser anònims o associats a una identitat de Retroshare per tal que els lectors puguin contactar amb tu si volen. Activa "Permetre comentaris" si vols permetre que els usuaris facin comentaris sobre el que publiques.</p><p>Les entrades publicades es mantenen durant %1 dies, i es sincronitzen pels últims %2 dies, a no ser que ho canviïs.</p> - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Canals subscrits @@ -8840,12 +8125,12 @@ Nota: No es poden revocar els permisos d'administrador publicatsSeleccionar directori de descarrega del canal - + Disable Auto-Download Desactivar auto-descàrrega - + Set download directory Seleccionar directori de descarrega @@ -8880,22 +8165,22 @@ Nota: No es poden revocar els permisos d'administrador publicats - + Play Reproduir - + Open folder Obrir directori - + Open file - + Error Error @@ -8915,17 +8200,17 @@ Nota: No es poden revocar els permisos d'administrador publicatsComprovant - + Are you sure that you want to cancel and delete the file? Segur que vols cancel·lar i esborrar aquest arxiu? - + Can't open folder No es pot obrir el directori - + Play File Reproduir arxiu @@ -8935,37 +8220,10 @@ Nota: No es poden revocar els permisos d'administrador publicatsL'arxiu %1 no existeix a la ruta. - - GxsChannelFilesWidget - - Form - Formulari - - - Filename - Nom d'arxiu - - - Size - Mida - - - Title - Títol - - - Published - Publicat - - - Status - Estat - - GxsChannelGroupDialog - + Create New Channel Crear nou canal @@ -9003,9 +8261,19 @@ Nota: No es poden revocar els permisos d'administrador publicats GxsChannelGroupItem - - Subscribe to Channel - Subscriu-te al canal + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel + @@ -9019,7 +8287,7 @@ Nota: No es poden revocar els permisos d'administrador publicats - + Expand Ampliar @@ -9034,7 +8302,7 @@ Nota: No es poden revocar els permisos d'administrador publicatsDescripció del canal - + Loading Carregant @@ -9049,8 +8317,9 @@ Nota: No es poden revocar els permisos d'administrador publicats - New Channel - Nou canal + + Never + Mai @@ -9061,7 +8330,7 @@ Nota: No es poden revocar els permisos d'administrador publicats GxsChannelPostItem - + New Comment: Nou comentari: @@ -9082,7 +8351,7 @@ Nota: No es poden revocar els permisos d'administrador publicats - + Play Reproduir @@ -9138,28 +8407,24 @@ Nota: No es poden revocar els permisos d'administrador publicatsFiles Arxius - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - Avís! Tens menys de %1 hores i %2 minuts abans que aquest arxiu sigui esborrat. Considera desar-lo. - Hide Amagar - + New Nou - + 0 0 - - + + Comment Comentari @@ -9174,21 +8439,17 @@ Nota: No es poden revocar els permisos d'administrador publicatsNo m'agrada - Loading - Carregant - - - + Loading... - + Comments Comentaris - + Post @@ -9213,139 +8474,16 @@ Nota: No es poden revocar els permisos d'administrador publicatsReproduir Medi - - GxsChannelPostsWidget - - Post to Channel - Publica al canal - - - Add new post - Afegir nova publicació - - - Loading - Carregant - - - Search channels - Cercar canals - - - Title - Títol - - - Search Title - Cerca títol - - - Message - Missatge - - - Search Message - Cercar missatge - - - Filename - Nom d'arxiu - - - Search Filename - Cercar arxiu - - - No Channel Selected - No hi ha canal seleccionat - - - Never - Mai - - - Public - Públic - - - Restricted to members of circle " - Restringit a membres del cercle " - - - Restricted to members of circle - Restringit a membres del cercle - - - Your eyes only - Només per tu - - - You and your friend nodes - Per tu i pels nodes dels teus amics - - - Disable Auto-Download - Desactivar auto-descàrrega - - - Enable Auto-Download - Activar auto-descàrrega - - - Show feeds - Mostra fonts - - - Show files - Mostra arxius - - - Administrator: - Administrador: - - - Last Post: - Última publicació: - - - unknown - desconegut - - - Distribution: - Distribució: - - - Feeds - Fonts - - - Files - Arxius - - - Subscribers - Subscriptors - - - Description: - Descripció: - - - Posts (at neighbor nodes): - Publicat (A nodes veïns): - - GxsChannelPostsWidgetWithModel - + Post to Channel Publica al canal - + Add new post Afegir nova publicació @@ -9415,7 +8553,7 @@ Nota: No es poden revocar els permisos d'administrador publicats - Posts (locally / at friends): + Items (locally / at friends): @@ -9441,7 +8579,7 @@ Nota: No es poden revocar els permisos d'administrador publicats Details - + Detalls @@ -9451,7 +8589,7 @@ Nota: No es poden revocar els permisos d'administrador publicats - + Comments Comentaris @@ -9466,13 +8604,13 @@ Nota: No es poden revocar els permisos d'administrador publicatsFonts - - + + Click to switch to list view - + Show unread posts only @@ -9487,7 +8625,7 @@ Nota: No es poden revocar els permisos d'administrador publicats - + No text to display @@ -9502,7 +8640,7 @@ Nota: No es poden revocar els permisos d'administrador publicats - + Switch to list view @@ -9562,12 +8700,22 @@ Nota: No es poden revocar els permisos d'administrador publicats - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -9642,12 +8790,13 @@ Nota: No es poden revocar els permisos d'administrador publicatsPer tu i pels nodes dels teus amics - + + Copy Retroshare link - + Subscribed Subscrit @@ -9684,7 +8833,7 @@ Nota: No es poden revocar els permisos d'administrador publicats Enable Auto-Download - + Activa l'auto-descàrrega @@ -9698,17 +8847,17 @@ Nota: No es poden revocar els permisos d'administrador publicats GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -9728,27 +8877,11 @@ Nota: No es poden revocar els permisos d'administrador publicatsRemove Item Eliminar l'element - - for identity - per identitat - - - You received a membership request for circle: - Has rebut una petició de pertinença al cercle: - Grant membership request Accepta la petició de pertinença - - Revoke membership request - Rebutja la petició de pertinença - - - You received an invitation for circle: - Has rebut una invitació pel cercle: - @@ -9839,7 +8972,7 @@ Nota: No es poden revocar els permisos d'administrador publicats GxsCommentContainer - + Comment Container Contenidor de comentari @@ -9852,7 +8985,7 @@ Nota: No es poden revocar els permisos d'administrador publicatsFormulari - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9882,7 +9015,7 @@ Nota: No es poden revocar els permisos d'administrador publicatsRefrescar - + Comment Comentari @@ -9921,7 +9054,7 @@ Nota: No es poden revocar els permisos d'administrador publicats GxsCommentTreeWidget - + Reply to Comment Resposta al comentari @@ -9945,6 +9078,21 @@ Nota: No es poden revocar els permisos d'administrador publicatsVote Down Votar negatiu + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9954,7 +9102,7 @@ Nota: No es poden revocar els permisos d'administrador publicatsFer comentari - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9983,26 +9131,10 @@ p, li { white-space: pre-wrap; } - + Post - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comentari</span></p></body></html> - - - Signed by - Signat per - Reply to Comment @@ -10031,7 +9163,7 @@ before you can comment abans de poder comentar - + It remains %1 characters after HTML conversion. @@ -10073,14 +9205,6 @@ abans de poder comentar Forum moderators can edit/delete/pinup others posts - - Add Forum Admins - Afegir administradors de fòrum - - - Select Forum Admins - Seleccionar administradors de fòrum - Create @@ -10090,7 +9214,7 @@ abans de poder comentar GxsForumGroupItem - + Subscribe to Forum Subscriure's al fòrum @@ -10106,7 +9230,7 @@ abans de poder comentar - + Expand Ampliar @@ -10126,8 +9250,9 @@ abans de poder comentar - Loading - Carregant + + TextLabel + @@ -10158,13 +9283,13 @@ abans de poder comentar GxsForumMsgItem - - + + Subject: Assumpte: - + Unsubscribe To Forum Donar de baixa del fòrum @@ -10175,7 +9300,7 @@ abans de poder comentar - + Expand Ampliar @@ -10195,21 +9320,17 @@ abans de poder comentar En resposta a: - Loading - Carregant - - - + Loading... - + Forum Feed Font del fòrum - + Hide Amagar @@ -10222,63 +9343,66 @@ abans de poder comentar Formulari - + Start new Thread for Selected Forum Comença nova conversa al fòrum seleccionat - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Cercar fòrums - Last Post - Darrer missatge - - - + New Thread Nova conversa - - - Threaded View - Vista per conversa - - - - Flat View - Vista plana - - + Title Títol - - + + Date Data - + Author Autor - - Save image - Desar imatge - - - + Loading Carregant - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -10288,12 +9412,7 @@ abans de poder comentar - - Lastest post in thread - - - - + Reply Message Respondre missatge @@ -10317,10 +9436,6 @@ abans de poder comentar Download all files Descarregar tots els arxius - - Next unread - Següent no llegit - Search Title @@ -10337,35 +9452,23 @@ abans de poder comentar Cerca autor - Content - Contingut - - - Search Content - Cerca contingut - - - <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - <p>Subscriure's al fòrum buscarà les entrades publicades disponibles dels teus amics subscrits, i farà el fòrum visible a tots els teus altres amics.</p><p>Després podràs des-subscriure't des del menú contextual de la llista de fòrums a l'esquerra.</p> - - - + No name Sense nom - - + + Reply Resposta - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -10408,20 +9511,12 @@ abans de poder comentar Copia l'enllaç RetroShare - + Hide Amagar - Expand - Ampliar - - - [Banned] - [Expulsat] - - - + [unknown] [desconegut] @@ -10451,8 +9546,8 @@ abans de poder comentar Només per tu - - + + Distribution Distribució @@ -10466,26 +9561,6 @@ abans de poder comentar Anti-spam Anti-spam - - [ ... Redacted message ... ] - [ ... Missatge modificat ... ] - - - Anonymous - Anònim - - - signed - signat - - - none - cap - - - [ ... Missing Message ... ] - [ ... Missatge perdut ... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10555,16 +9630,12 @@ abans de poder comentar Missatge original - + New thread Nova conversa - Read status - Estat de lectura - - - + Edit Editar @@ -10625,7 +9696,7 @@ abans de poder comentar Reputació de l'autor - + Show column @@ -10645,7 +9716,7 @@ abans de poder comentar - + Anonymous/unknown posts forwarded if reputation is positive Els missatges anònims/desconeguts es propagaran si la reputació és positiva @@ -10697,7 +9768,7 @@ This message is missing. You should receive it later. - + No result. @@ -10707,7 +9778,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -10722,26 +9793,7 @@ This message is missing. You should receive it later. - Information for this identity is currently missing. - No hi ha informació per aquesta identitat - - - You have banned this ID. The message will not be -displayed nor forwarded to your friends. - Has prohibit aquesta identitat. El missatge no es mostrarà ni propagarà als teus amics. - - - You have not set an opinion for this person, - and your friends do not vote positively: Spam regulation -prevents the message to be forwarded to your friends. - No has establert una opinió per aquesta persona i els teus amics no opinien positivament: L'anti-spam evita que el missatge sigui propagat als teus amics. - - - Message will be forwarded to your friends. - El missatge es propagarà als teus amics. - - - + (Latest) (Nou) @@ -10750,10 +9802,6 @@ prevents the message to be forwarded to your friends. (Old) (Vell) - - You cant act on the author to a non-existant Message - No pots fer res a l'autor d'un missatge que no existeix - From @@ -10811,12 +9859,12 @@ prevents the message to be forwarded to your friends. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Fòrums</h1> <p>Els fòrums de Retroshare es veuen com fòrums d'Internet, però funcionen de forma descentralitzada</p> <p>Tu veus els fòrums als que els teus amics estan subscrits i tu fas el mateix amb els teus pels teus amics. Això promociona automàticament els fòrums interessants a la xarxa.</p> <p>Els missatges es mantenen durant %1 dies i es sincronitzen durant %2 dies, si no ho canvies.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> + - + Forums Fòrums @@ -10847,35 +9895,16 @@ prevents the message to be forwarded to your friends. Altres fòrums - - GxsForumsFillThread - - Waiting - Esperant - - - Retrieving - Recuperant - - - Loading - Carregant - - GxsGroupDialog - + Name Nom - Add Icon - Afegir icona - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels Els destinataris de les claus poden publicar en grups restringits, i poden veure i publicar en canals privats @@ -10884,22 +9913,14 @@ prevents the message to be forwarded to your friends. Share Publish Key Compartir clau pública - - check peers you would like to share private publish key with - comprovar els contactes amb qui t'agradaria compartir les claus de publicació - - - Share Key With - Compartir clau amb - - + Description Descripció - + Message Distribution Distribució de missatge @@ -10907,7 +9928,7 @@ prevents the message to be forwarded to your friends. - + Public Públic @@ -10926,14 +9947,6 @@ prevents the message to be forwarded to your friends. New Thread Nova conversa - - Required - Requerit - - - Encrypted Msgs - Encriptar missatge - Personal Signatures @@ -10975,7 +9988,7 @@ prevents the message to be forwarded to your friends. Protecció-Spam - + Comments: Comentari: @@ -10998,7 +10011,7 @@ prevents the message to be forwarded to your friends. Anti Spam: - + All People @@ -11014,12 +10027,12 @@ prevents the message to be forwarded to your friends. - + Restricted to circle: Restringit al cercle: - + Limited to your friends Limitat als teus amics @@ -11036,23 +10049,23 @@ prevents the message to be forwarded to your friends. - + Message tracking Seguiment de missatges - - + + PGP signature required Signatura PGP requerida - + Never Mai - + Only friends nodes in group Només els nodes d'amics al grup @@ -11068,30 +10081,28 @@ prevents the message to be forwarded to your friends. Si us plau, afegeix un nom - + PGP signature from known ID required Signatura PGP de ID coneguda requerida - + + + [None] + + + + Load Group Logo Carrega logotip del grup - + Submit Group Changes Publicar canvis al grup - Failed to Prepare Group MetaData - please Review - Fallo al preparar les metadades del Grup - Revisa-les - - - Will be used to send feedback - S'utilitzarà per enviar resposta - - - + Owner: Propietari: @@ -11101,12 +10112,12 @@ prevents the message to be forwarded to your friends. Estableix una descripció - + Info Informació - + ID ID @@ -11116,7 +10127,7 @@ prevents the message to be forwarded to your friends. Darrer missatge - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> <html><head/><body><p>Els missatges es distribuiran més enllà dels nodes dels teus amics, sempre que la gent es subscrigui al canal/fòrum/publicació que creis.</p></body></html> @@ -11191,7 +10202,12 @@ prevents the message to be forwarded to your friends. Defavorir IDs no signats i IDs de nodes desconeguts - + + Author: + + + + Popularity Popularitat @@ -11207,27 +10223,22 @@ prevents the message to be forwarded to your friends. - + Created - + Cancel - + Create Crear - - Author - Autor - - - + GxsIdLabel EtiquetaGxsId @@ -11235,7 +10246,7 @@ prevents the message to be forwarded to your friends. GxsGroupFrameDialog - + Loading Carregant @@ -11295,7 +10306,7 @@ prevents the message to be forwarded to your friends. Editar detalls - + Synchronise posts of last... Sincronitza els missatges dels/de les últims/es... @@ -11352,16 +10363,12 @@ prevents the message to be forwarded to your friends. - + Search for - Share publish permissions - Compartir permisos de publicació - - - + Copy RetroShare Link Copia l'enllaç RetroShare @@ -11384,7 +10391,7 @@ prevents the message to be forwarded to your friends. GxsIdChooser - + No Signature Sense signatura @@ -11397,40 +10404,24 @@ prevents the message to be forwarded to your friends. GxsIdDetails - Loading - Carregant - - - + Not found No trobat - - No Signature - Sense signatura - - - + + [Banned] [Expulsat] - - Authentication - Autenticació - unknown Key clau desconeguda - anonymous - anònim - - - + Loading... @@ -11440,7 +10431,12 @@ prevents the message to be forwarded to your friends. - + + [Nobody] + + + + Identity&nbsp;name Identitat&nbsp;nom @@ -11454,16 +10450,20 @@ prevents the message to be forwarded to your friends. Node Node - - Signed&nbsp;by - Signat&nbsp;per - [Unknown] [Desconegut] + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -11475,7 +10475,7 @@ prevents the message to be forwarded to your friends. GxsIdStatisticsWidget - + Total identities: @@ -11523,17 +10523,13 @@ prevents the message to be forwarded to your friends. GxsIdTreeItemDelegate - + [Unknown] [Desconegut] GxsMessageFramePostWidget - - Loading - Carregant - Loading... @@ -11650,10 +10646,6 @@ prevents the message to be forwarded to your friends. Group ID / Author ID Grup / Autor - - Number of messages / Publish TS - Nombre de missatges / TS publicats - Local size of data @@ -11669,10 +10661,6 @@ prevents the message to be forwarded to your friends. Popularity Popularitat - - Details - Dells - @@ -11705,41 +10693,6 @@ prevents the message to be forwarded to your friends. No - - GxsTunnelsDialog - - Authenticated tunnels: - Túnels autenticats: - - - Tunnel ID: %1 - ID túnel: %1 - - - from: %1 - de: %1 - - - to: %1 - a: %1 - - - status: %1 - estat: %1 - - - total sent: %1 bytes - total enviat: %1 bytes - - - total recv: %1 bytes - Total rebut: %1 bytes - - - Unknown Peer - Contacte desconegut - - HashBox @@ -11952,48 +10905,12 @@ prevents the message to be forwarded to your friends. About Sobre - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare provides file sharing, chat, messages and channels</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Useful external links to more information:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Wiki</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare's Forum</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Project Page</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Team Blog</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Dev Twitter</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Retroshare és una plataforma descentralitzada</span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">segura i privada de comunicacions, de codi obert i multi-plataforma. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Permet compartir tot el que vulguis amb seguretat amb amics </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;"> utilitzant certificats per autenticar els contactes i OpenSSL per encriptar les comunicacions.</span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Retroshare proporciona compartició d'arxius, xat, missatgeria i canals.</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Enllaços externs útils amb més informació:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Pàgina web del Retroshare</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Viqui del Retroshare</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Fòrum del Retroshare</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Plana de projecte del Retroshare</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Bloc de l'equip del Retroshare</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Twitter Desenvolupament Retroshare</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -12009,7 +10926,7 @@ p, li { white-space: pre-wrap; } - + Authors Autors @@ -12028,7 +10945,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -12041,38 +10958,6 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Daniel Wester</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">wester@speedmail.se</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">German: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Jan</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Keller</span><span style=" font-family:'MS Shell Dlg 2';"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">trilarion@users.sourceforge.net</span><span style=" font-family:'MS Shell Dlg 2';">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Traducció Retroshare:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Plana web traductors Retroshare:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Alemany: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Català: </span><span style=" font-size:8pt;"> Josep Creus</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">creus.informatic@gmail.com</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polac: </span>Maciej Mrug</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Suec: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> -</body></html> - License Agreement @@ -12138,12 +11023,12 @@ p, li { white-space: pre-wrap; } Formulari - + <html><head/><body><p>Copy your RetroShare ID to clipboard</p></body></html> - + Add friend @@ -12158,7 +11043,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -12167,32 +11052,12 @@ p, li { white-space: pre-wrap; } This is your Retroshare ID. Copy and share with your friends! - - Did you receive a certificate from a friend? - Has rebut un certificat de part d'un amic? - - - Add friends certificate - Afegir certificat d'un amic - - - Add certificate file - Afegir arxiu de certificat - - - Share your RetroShare Key - Comparteix la teva clau de Retroshare - ... ... - - The text below is your own Retroshare certificate. Send it to your friends - El text a sota és el teu certificat de Retroshare. Envia'l als teus amic - Open Source cross-platform, @@ -12202,20 +11067,12 @@ private and secure decentralized communication platform. - Launch startup wizard - Executar assistent d'inici - - - Do you need help with RetroShare? - Necessites ajuda amb el RetroShare? - - - + Open Web Help Ajuda a la web oberta - + Copy your Cert to Clipboard Copiar el teu certificat al porta-retalls @@ -12225,7 +11082,7 @@ private and secure decentralized communication platform. Desar el teu certificar a un arxiu - + Send via Email Enviar per correu @@ -12245,13 +11102,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -12263,17 +11144,12 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -12282,19 +11158,11 @@ new short format Your Retroshare ID is copied to Clipboard, paste and send it to your friend via email or some other way - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your certificate on this page and send it to friends, and add your friends' certificate.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange certificates with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Benvingut a Retroshare!</h1>  <p>Necessites <b>fer amics</b>! Un cop hagis creat una xarxa de nodes de Retroshare, o t'hagis unit a una xarxa existent, podràs intercanviar arxius, xatejar, parlar a fòrums, etc.</p><div align=center><IMG align="center" width="%2" src=":/images/network_map.png"/></div><p>Per fer-ho, copia el teu certificat d'aquesta pàgina i envia'l als teus amics, i afegeix aquí els certificats del teus amics.</p> <p>Una altra opció és cercar a internet per "servidors de xat de Retroshare" (administrats independentment). Els servidors et permeten intercanviar certificats amb un node de Retroshare dedicat, utilitzant-lo podràs trobar altres persones anònimament.</p> - RetroShare Invite Invitació de RetroShare - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - S'ha copiat el teu certificat al porta-retalls, enganxa'l i envia'l al teu amic per correu - Save as... @@ -12566,14 +11434,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Tot - + Reputation Reputació @@ -12583,12 +11451,12 @@ p, li { white-space: pre-wrap; } Cerca - + Anonymous Id Id anònim - + Create new Identity Crear nova identitat @@ -12598,7 +11466,7 @@ p, li { white-space: pre-wrap; } Crear nou cercle - + Persons Persones @@ -12613,27 +11481,27 @@ p, li { white-space: pre-wrap; } Persona - + Close Tancar - + Ban-option: Opció-expulsar: - + Auto-Ban all identities signed by the same node Expulsa automàticament totes les identitats signades pel mateix node - + Friend votes: Vots de l'amic: - + Positive votes Vots positius @@ -12649,29 +11517,39 @@ p, li { white-space: pre-wrap; } Vots negatius - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics Estadístiques d'ús - + Circles Cercles - + Circle name Nom del cercle @@ -12691,18 +11569,20 @@ p, li { white-space: pre-wrap; } Cercles personals - + + Edit identity Editar identitat - + + Delete identity Esborrar identitat - + Chat with this peer Xatejar amb aquest contacte @@ -12712,98 +11592,78 @@ p, li { white-space: pre-wrap; } Començar un xat distant amb aquest contacte - + Owner node ID : Id del node propietari: - + Identity name : Nom de la identitat: - + () () - + Identity ID Id d'identitat - + Send message Enviar missatge - + Identity info Informació d'identitat - + Identity ID : Id d'identitat: - + Owner node name : Nom del node propietari: - + Create new... Crear nou... - + Type: Tipus: - + Send Invite Enviar invitació - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> <html><head/><body><p>La opinió mitjana dels nodes veïns sobre aquesta identitat. Negativa és dolent,</p><p>positiva és bo. Zero és neutre.</p></body></html> - + Your opinion: La teva opinió: - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </p> -<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">La teva opinió sobre una identitat controla la visibilitat d'aquesta per tu i els teus nodes amics. La teva opinió es comparteix amb els teus amics i s'utilitza per calcular una puntuació de reputació: Si la teva opinió sobre una identitat és neutre, la puntuació de reputació és la mitjana de l'opinió dels teus amics. Si no, la teva opinió estableix la puntuació.</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">La puntuació total s'utilitza en les sales de xat, fòrums i canals per decidir que fer amb cada identitat. Quan la puntuació està per sota de -1 la identitat és expulsada, tots els missatges, fòrums i canals per dita identitat no es reenvien, en cap sentit. Alguns fòrums tenen una opció anti-SPAM que obliga a tindre un nivell de reputació no negatiu, fent que siguin més sensibles a males reputacions. Les identitats expulsades van perdent gradualment la seva activitat i finalment desapareixent (després de 5 dies). </p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Pots canviar aquests mínims i el temps d'inactivitat per esborrar una identitat a Preferencies -&gt; Gent. </p> -<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - + Negative Negatiu - + Neutral Neutre @@ -12814,17 +11674,17 @@ p, li { white-space: pre-wrap; } Positiu - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> <html><head/><body><p>La puntuació de reputació global, calculada amb les teves puntuacions i la dels teus amics.</p><p>Negativa és dolent, positiva és bo. Zero és neutre. Si la puntuació és massa baixa,</p><p>la identitat es marca com dolenta, i es filtrarà als fòrums, sales de xat,</p><p>canals, etc.</p></body></html> - + Overall: Global: - + Anonymous Anònim @@ -12839,24 +11699,24 @@ p, li { white-space: pre-wrap; } ID cerca - + This identity is owned by you Aquesta identitat és propietat teva - - + + My own identities Les meves identitats - - + + My contacts Els meus contactes - + Show Items Mostrar elements @@ -12871,7 +11731,12 @@ p, li { white-space: pre-wrap; } Associat al meu node - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles Altres cercles @@ -12881,7 +11746,7 @@ p, li { white-space: pre-wrap; } Cercles als que pertanyo - + Circle ID: ID Cercle: @@ -12956,7 +11821,7 @@ p, li { white-space: pre-wrap; } No ets membre (No tens accés a dades limitades a aquest cercle) - + Identity ID: Id d'identitat: @@ -12986,7 +11851,7 @@ p, li { white-space: pre-wrap; } desconegut - + Invited Convidat @@ -13001,7 +11866,7 @@ p, li { white-space: pre-wrap; } Membre - + Edit Circle Editar cercle @@ -13049,7 +11914,7 @@ p, li { white-space: pre-wrap; } Permet pertinença - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -13060,7 +11925,7 @@ T'hauries de lliurar d'ella i utilitzar-ne una de nova. Aquestes identitats deixaran de ser suportades en breu. - + [Unknown node] [Node desconegut] @@ -13103,7 +11968,7 @@ Aquestes identitats deixaran de ser suportades en breu. Identitat anònima - + Boards @@ -13183,7 +12048,7 @@ Aquestes identitats deixaran de ser suportades en breu. - + information informació @@ -13199,29 +12064,12 @@ Aquestes identitats deixaran de ser suportades en breu. Copiar identitat al porta-retalls - Send invite? - Enviar invitació? - - - Do you really want send a invite with your Certificate? - Estàs segur de voler enviar una invitació amb el teu certificat? - - - + Banned Expulsat - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identitats</h1><p>En aquesta pestanya pots crear/editar identitats <b>pseudo-anònimes</b> i <b>cercles</b>.</p><p>Les <b>Identitats</b> s'utilitzen per identificar les teves dades: signar missatges publicats a les sales de xat, fòrums i canals, rebre comentaris utilitzant el sistema intern de correu electrònic o publicar-ne a entrades dels canals, xatejar utilitzant túnels segurs, etc.</p> <p>Les identitats poden estar <b>signades</b> pel certificat del seu node de Rertoshare. És més fàcil confiar en identitats signades però es poden seguir fàcilment fins a la IP del node al que pertanyen.</p> <p>Les <b>identitats anònimes</b> et permetran interactuar amb altres usuaris de forma anònima. No es poden falsificar, però ningú pot provar qui té en realitat una determinada identitat.</p> <p>Els <b>cercles</b> són grups d'identitats (anònimes o signades) que són compartides a certa distancia, salts entre nodes, per la xarxa. Es poden utilitzar per restringir la visibilitat de fòrums, canals, etc. </p> <p>Un <b>cercle</b> pot estar restringit a un altre cercle, limitant la visibilitat als membres d'aquest cercle o inclús es pot auto-restringir, que vol dir que només es visible a membres invitats.</p> - - - Unknown ID: - ID desconegut: - - - + positive positiu @@ -13265,19 +12113,11 @@ Aquestes identitats deixaran de ser suportades en breu. Forums Fòrums - - Posted - Enviat - Chat Xat - - Unknown - Desconegut - [Unknown] @@ -13298,14 +12138,6 @@ Aquestes identitats deixaran de ser suportades en breu. Creation of author signature in service %1 Creació de signatura d'autor al servei %1 - - Message/vote/comment - Missatge/vot/comentari - - - %1 in %2 tab - %1 a la pestanya %2 - Distant message signature validation. @@ -13326,19 +12158,11 @@ Aquestes identitats deixaran de ser suportades en breu. Signature in distant tunnel system. Signatura al sistema de túnel distant. - - Update of identity data. - Actualització de dades d'identitat - Generic signature validation. Comprovació de signatura genèrica - - Generic signature. - Signatura genèrica - Generic encryption. @@ -13350,11 +12174,7 @@ Aquestes identitats deixaran de ser suportades en breu. Desencriptació genèrica - Membership verification in circle %1. - Comprovació de pertinença al cercle %1. - - - + Add to Contacts Afegir a contactes @@ -13404,21 +12224,21 @@ Aquestes identitats deixaran de ser suportades en breu. Hola,<br> vull ser amic amb tu en el RetroShare.<br> - - - + + + People Gent - + Your Avatar Click here to change your avatar El teu avatar - + Linked to neighbor nodes Associat a nodes veïns @@ -13428,7 +12248,7 @@ Aquestes identitats deixaran de ser suportades en breu. Associat a nodes distants - + Linked to a friend Retroshare node Associat a un node de RetroShare d'un amic @@ -13443,7 +12263,7 @@ Aquestes identitats deixaran de ser suportades en breu. Associat a un node de RetroShare desconegut - + Chat with this person Xat amb aquesta persona @@ -13458,12 +12278,12 @@ Aquestes identitats deixaran de ser suportades en breu. Xat distant rebutjat amb aquesta persona. - + Last used: Últim utilitzat: - + +50 Known PGP +50 PGP conegut @@ -13483,12 +12303,12 @@ Aquestes identitats deixaran de ser suportades en breu. Estàs segur de voler esborrar aquesta identitat? - + Owned by Propietat de - + Node name: Nom del node: @@ -13498,7 +12318,7 @@ Aquestes identitats deixaran de ser suportades en breu. ID node : - + Really delete? Segur que vols esborrar? @@ -13506,7 +12326,7 @@ Aquestes identitats deixaran de ser suportades en breu. IdEditDialog - + Nickname Sobrenom @@ -13536,7 +12356,7 @@ Aquestes identitats deixaran de ser suportades en breu. Pseudònim - + Import image @@ -13546,12 +12366,19 @@ Aquestes identitats deixaran de ser suportades en breu. - - Use the mouse to zoom and adjust the image for your avatar. + + + No Avatar chosen. A default image will be automatically displayed from your new identity. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity Nova identitat @@ -13565,7 +12392,7 @@ Aquestes identitats deixaran de ser suportades en breu. - + @@ -13575,7 +12402,12 @@ Aquestes identitats deixaran de ser suportades en breu. N/A - + + No avatar chosen + + + + Edit identity Editar identitat @@ -13586,27 +12418,27 @@ Aquestes identitats deixaran de ser suportades en breu. Actualitza - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -13626,7 +12458,7 @@ Aquestes identitats deixaran de ser suportades en breu. - + Identity update failed @@ -13636,11 +12468,7 @@ Aquestes identitats deixaran de ser suportades en breu. - Error getting key! - Error obtenint clau! - - - + Error KeyID invalid Error de IDClau invàlida @@ -13655,7 +12483,7 @@ Aquestes identitats deixaran de ser suportades en breu. Nom real desconegut - + Create New Identity Crear nova identitat @@ -13665,10 +12493,15 @@ Aquestes identitats deixaran de ser suportades en breu. Tipus - + Choose image... + + + Remove + Treure + @@ -13694,7 +12527,7 @@ Aquestes identitats deixaran de ser suportades en breu. Afegir - + Create Crear @@ -13704,17 +12537,13 @@ Aquestes identitats deixaran de ser suportades en breu. - + Your Avatar Click here to change your avatar El teu avatar - Set Avatar - Escull avatar - - - + Linked to your profile Associat al teu perfil @@ -13724,7 +12553,7 @@ Aquestes identitats deixaran de ser suportades en breu. Pots tindre una o més identitats. S'utilitzen quan escrius en sales de xat, fòrums i comentes en canals. Funcionen també com a destinataris en xats distants i en el sistema de correu distant de RetroShare. - + The nickname is too short. Please input at least %1 characters. El sobrenom és massa curt. Si us plau, introdueix com a mínim %1 caràcters. @@ -13783,10 +12612,6 @@ Aquestes identitats deixaran de ser suportades en breu. PGP name: Nom PGP: - - GXS id: - id GXS: - PGP id: @@ -13802,7 +12627,7 @@ Aquestes identitats deixaran de ser suportades en breu. - + Copy Copiar @@ -13812,12 +12637,12 @@ Aquestes identitats deixaran de ser suportades en breu. Treure - + %1 's Message History - + Mark all Marcar totes @@ -13836,26 +12661,38 @@ Aquestes identitats deixaran de ser suportades en breu. Quote Cita - - Send - Enviar - ImageUtil - - + + Save image Desar imatge + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + + + + Cannot save the image, invalid filename No es pot guardar la imatge, nom de l'arxiu invàlid - + + Copy image + + + + + Not an image No és una imatge @@ -13873,27 +12710,32 @@ Aquestes identitats deixaran de ser suportades en breu. - + Enable RetroShare JSON API Server - + Port: Port: - + Listen Address: - + + Status: + Estat: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -13914,7 +12756,12 @@ Aquestes identitats deixaran de ser suportades en breu. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -13923,26 +12770,31 @@ Aquestes identitats deixaran de ser suportades en breu. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File Obrir arxiu - + Open Folder Obrir directori - + Checking... Comprovant... @@ -13952,7 +12804,7 @@ Aquestes identitats deixaran de ser suportades en breu. comprovar arxius - + Recommend in a message to... Recomanar en un missatge a... @@ -13980,7 +12832,7 @@ Aquestes identitats deixaran de ser suportades en breu. MainWindow - + Add Friend Afegeix amic @@ -13996,7 +12848,8 @@ Aquestes identitats deixaran de ser suportades en breu. - + + Options Opcions @@ -14017,7 +12870,7 @@ Aquestes identitats deixaran de ser suportades en breu. - + Quit Sortir @@ -14028,12 +12881,12 @@ Aquestes identitats deixaran de ser suportades en breu. Auxiliar d'inici ràpid - + RetroShare %1 a secure decentralized communication platform RetroShare %1 és una plataforma de comunicació segura descentralitzada - + Unfinished Inacabat @@ -14060,11 +12913,12 @@ Si us plau, allibera una mica d'espai i clica Ok. + Status Estat - + Notify Notificar @@ -14075,31 +12929,35 @@ Si us plau, allibera una mica d'espai i clica Ok. + Open Messages Obrir Missatges - + + Bandwidth Graph Gràfic d'ample de banda - + Applications Aplicacions + Help Ajuda - + + Minimize Minimitzar - + Maximize Maximitzar @@ -14114,7 +12972,12 @@ Si us plau, allibera una mica d'espai i clica Ok. RetroShare - + + Close window + + + + %1 new message %1 missatges nous @@ -14144,7 +13007,7 @@ Si us plau, allibera una mica d'espai i clica Ok. %1 amics connectats - + Do you really want to exit RetroShare ? Segur que vols sortir del RetroShare? @@ -14164,7 +13027,7 @@ Si us plau, allibera una mica d'espai i clica Ok. Mostra - + Make sure this link has not been forged to drag you to a malicious website. Assegura't de que aquest enllaç no ha estat modificat per portar-te a un lloc web malicios. @@ -14209,12 +13072,13 @@ Si us plau, allibera una mica d'espai i clica Ok. Taula de permisos dels serveis - + + Statistics Estadístiques - + Show web interface Mostrar interficie web @@ -14229,7 +13093,7 @@ Si us plau, allibera una mica d'espai i clica Ok. directori s'està acabant (L'actual límit és - + Really quit ? Segur que vols sortir ? @@ -14238,17 +13102,17 @@ Si us plau, allibera una mica d'espai i clica Ok. MessageComposer - + Compose Redacta - + Contacts Contactes - + Paragraph Paràgraf @@ -14284,12 +13148,12 @@ Si us plau, allibera una mica d'espai i clica Ok. Capçalera 6 - + Font size Mida del tipus de lletra - + Increase font size Augmentar la mida del tipus de lletra @@ -14304,32 +13168,32 @@ Si us plau, allibera una mica d'espai i clica Ok. Negreta - + Italic Cursiva - + Alignment Alineació - + Add an Image Afegir una imatge - + Sets text font to code style Posa el tipus de lletra del text com si fos codi - + Underline Subratllat - + Subject: Assumpte: @@ -14340,32 +13204,32 @@ Si us plau, allibera una mica d'espai i clica Ok. - + Tags Etiquetes - + Address list: Llista d'adreces: - + Recommend this friend Recomanar aquest amic - + Set Text color Estableix color de lletra - + Set Text background color Estableix color de fons de la lletra - + Recommended Files Arxius recomanats @@ -14435,7 +13299,7 @@ Si us plau, allibera una mica d'espai i clica Ok. Afegir citació - + Send To: Enviar a: @@ -14459,10 +13323,6 @@ Si us plau, allibera una mica d'espai i clica Ok. &Justify &Justificat - - All addresses (mixed) - Totes les adreces (mesclades) - All people @@ -14474,7 +13334,7 @@ Si us plau, allibera una mica d'espai i clica Ok. Els meus contactes - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> Hola,<br>Et recomano un bon amic meu; pots confiar en ell si confies en mi. <br> @@ -14494,18 +13354,18 @@ Si us plau, allibera una mica d'espai i clica Ok. vol ser amic teu al RetroShare - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team Hola %1, <br><br>%2 vol ser amic teu al RetroShare.<br><br>Respondre ara:<br>%3 <br><br>Gràcies,<br>L'equip RetroShare - - + + Save Message Desar el missatge - + Message has not been Sent. Do you want to save message to draft box? El missatge no s'ha enviat. @@ -14517,7 +13377,17 @@ Vols desar el missatge a la bústia d'esborranys? Enganxa l'enllaç RetroShare - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" Afegir a "A" @@ -14537,7 +13407,7 @@ Vols desar el missatge a la bústia d'esborranys? Afegir com a recomanat - + Original Message Missatge original @@ -14547,21 +13417,21 @@ Vols desar el missatge a la bústia d'esborranys? Des de - + - + To A - - + + Cc CC - + Sent Enviat @@ -14576,7 +13446,7 @@ Vols desar el missatge a la bústia d'esborranys? A %1, %2 va escriure: - + Re: Re: @@ -14586,30 +13456,30 @@ Vols desar el missatge a la bústia d'esborranys? Reenvia: - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? Vols enviar el missatge sense especificar un assumpte? - + Please insert at least one recipient. Si us plau, introdueix almenys un destinatari. - + Bcc C/o - + Unknown Desconegut @@ -14724,13 +13594,13 @@ Vols desar el missatge a la bústia d'esborranys? Detalls - + Open File... Obrir arxiu... - + HTML-Files (*.htm *.html);;All Files (*) Arxius HTML (*.htm *.html);;Tots els arxius (*) @@ -14750,7 +13620,7 @@ Vols desar el missatge a la bústia d'esborranys? Exportar a PDF - + Message has not been Sent. Do you want to save message ? El missatge no s'ha enviat. @@ -14772,7 +13642,7 @@ Voleu desar el missatge? Afegir arxiu extra - + Hi,<br>I want to be friends with you on RetroShare.<br> Hola,<br> vull ser amic amb tu en el RetroShare.<br> @@ -14796,28 +13666,24 @@ Voleu desar el missatge? Warning: This message is too big of %1 characters after HTML conversion. - - You have a friend invite - Tens una petició d'amistat - Respond now: Respondre ara: - - + + Close Tancar - + From: De: - + Friend Nodes Nodes de l'amic @@ -14862,13 +13728,13 @@ Voleu desar el missatge? Llista ordenada (romanic ascendent) - - + + Thanks, <br> Gràcies, <br> - + Distant identity: Identitat distant: @@ -14878,12 +13744,12 @@ Voleu desar el missatge? [Falta] - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. Si us plau, crea una identitat per signar missatges distants o treu els contactes distants de la llista de destinataris. - + Node name & id: Nom i Id del node: @@ -14961,7 +13827,7 @@ Voleu desar el missatge? Per defecte - + A new tab Una pestanya nova @@ -14971,7 +13837,7 @@ Voleu desar el missatge? Una finestra nova - + Edit Tag Editar etiqueta @@ -14994,7 +13860,7 @@ Voleu desar el missatge? MessageToaster - + Sub: Sub: @@ -15002,7 +13868,7 @@ Voleu desar el missatge? MessageUserNotify - + Message Missatge @@ -15030,7 +13896,7 @@ Voleu desar el missatge? MessageWidget - + Recommended Files Arxius recomanats @@ -15040,37 +13906,37 @@ Voleu desar el missatge? Descarregar tots els arxius recomanats - + Subject: Assumpte: - + From: De: - + To: A: - + Cc: CC: - + Bcc: C/o: - + Tags: Etiquetes: - + Reply Resposta @@ -15110,7 +13976,7 @@ Voleu desar el missatge? - + Send Invite Envia invitació @@ -15162,7 +14028,7 @@ Voleu desar el missatge? - + Confirm %1 as friend Confirma %1 com amic @@ -15172,12 +14038,12 @@ Voleu desar el missatge? Afegeix %1 com amic - + View source - + No subject Sense assumpte @@ -15187,17 +14053,22 @@ Voleu desar el missatge? Descarregar - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -15207,21 +14078,23 @@ Voleu desar el missatge? - Send invite? - Enviar invitació? + + Show less + - Do you really want send a invite with your Certificate? - Estàs segur de voler enviar una invitació amb el teu certificat? + + Show more + - + Download all Descarregar tot - + Print Document Imprimir document @@ -15236,12 +14109,12 @@ Voleu desar el missatge? Arxius-HTML (*.htm *.html);;Tots els arxius (*) - + Load images always for this message Carregar sempre les imatges per aquest missatge - + Hide the attachment pane Oculta el panell d'adjunció @@ -15263,42 +14136,6 @@ Voleu desar el missatge? Compose Redacta - - Reply to selected message - Respon al missatge seleccionat - - - Reply - Resposta - - - Reply all to selected message - Respondre a tothom del missatge seleccionat - - - Reply all - Respon a tothom - - - Forward selected message - Reenviar missatge seleccionat - - - Forward - Endavant - - - Remove selected message - Esborra el missatge seleccionat - - - Delete - Esborrar - - - Print selected message - Imprimir el missatge seleccionat - Print @@ -15377,7 +14214,7 @@ Voleu desar el missatge? MessagesDialog - + New Message Missatge nou @@ -15387,60 +14224,16 @@ Voleu desar el missatge? Redacta - Reply to selected message - Respon al missatge seleccionat - - - Reply - Resposta - - - Reply all to selected message - Respon a tothom del missatge seleccionat - - - Reply all - Respon a tothom - - - Forward selected message - Reenviar missatge seleccionat - - - Foward - Reenvia - - - Remove selected message - Esborra el missatge seleccionat - - - Delete - Esborrar - - - Print selected message - Imprimir el missatge seleccionat - - - Print - Impressió - - - Display - Mostra - - - + - - + + Tags Etiquetes - - + + Inbox Safata d'entrada @@ -15470,21 +14263,17 @@ Voleu desar el missatge? Paperera - + Total Inbox: Total safata d'entrada: - Folders - Carpetes - - - + Quick View Vista ràpida - + Print... Impressió... @@ -15494,26 +14283,6 @@ Voleu desar el missatge? Print Preview Prèvia d'impressió - - Buttons Icon Only - Botons: Només icona - - - Buttons Text Beside Icon - Botons: Text al costat de la icona - - - Buttons with Text - Botons: amb text - - - Buttons Text Under Icon - Botons: Text sota la icona - - - Set Text Under Icon - Establir text sota la icona - Save As... @@ -15535,7 +14304,7 @@ Voleu desar el missatge? Reenviar missatge - + Subject Assumpte @@ -15545,7 +14314,7 @@ Voleu desar el missatge? Des de - + Date Data @@ -15555,39 +14324,7 @@ Voleu desar el missatge? Contingut - Click to sort by attachments - Clica per ordenar pels fitxers adjunts - - - Click to sort by subject - Clica per ordenar per assumptes - - - Click to sort by read - Clica per ordenar per llegits - - - Click to sort by from - Clica per ordenar pel remitent - - - Click to sort by date - Clica per ordenar per data - - - Click to sort by tags - Clica per ordenar per etiquetes - - - Click to sort by star - Clica per ordenar per marcats - - - Forward selected Message - Reenviar missatge seleccionat - - - + Search Subject Assumpte de la cerca @@ -15596,6 +14333,11 @@ Voleu desar el missatge? Search From Cerca de + + + Search To + + Search Date @@ -15622,14 +14364,14 @@ Voleu desar el missatge? Cerca adjunts - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - <h1><img width="32" src=":/images/help_64.png">&nbsp;&nbsp;Missatges</h1> <p>Retroshare té el seu propi sistema de correu electrònic. Pots enviar/rebre correus de/a els nodes dels teus amics.</p> <p>També és possible enviar missatges a identitats d'altra gent utilitzant el sistema de encaminament global. Aquests missatges són sempre encriptats i reenviats per nodes intermediaris fins que arriben al seu destí. </p> <p>Els missatges distants es queden a la teva bustia de sortints fins que no es rep confirmació d'entrega.</p> <p>Generalment s'envien missatges per recomanar arxius a amics enviant els enllaços, recomanar nodes d'amics a altres amics, per millorar la teva xarxa, o respostes a propietaris de canals.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + - + Starred - Marcat + @@ -15703,7 +14445,7 @@ Voleu desar el missatge? - Show author in People + Show in People @@ -15717,7 +14459,7 @@ Voleu desar el missatge? - + No message using %1 tag available. @@ -15732,38 +14474,33 @@ Voleu desar el missatge? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts Esborranys - + No Box selected. - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - No hi ha missatges marcats. Les marques et permeten donar als missatges un estat especial per trobar-los fàcilment. Per marcar un missatge clica a l'estrella gris al costat del missatge. - - - No system messages available. - No hi ha missatges de sistema disponibles. - - + To - A + A - Click to sort by to - Clica per ordenar per destinatari - - - This message goes to a distant person. - Aquest missatge va cap a una persona distant. - - - + @@ -15771,26 +14508,6 @@ Voleu desar el missatge? Total: Total: - - Messages - Missatges - - - Click to sort by signature - Clica per ordenar per signatura - - - This message was signed and the signature checks - Aquest missatge és firmat i la signatura vàlida - - - This message was signed but the signature doesn't check - Aquest missatge està signat però la signatura no és vàlida - - - This message comes from a distant person. - Aquest missatge prové d'una persona distant. - Mail @@ -15818,7 +14535,17 @@ Voleu desar el missatge? MimeTextEdit - + + Save image + Desar imatge + + + + Copy image + + + + Paste as plain text Enganxa com a text pla @@ -15872,7 +14599,7 @@ Voleu desar el missatge? - + Expand Ampliar @@ -15882,7 +14609,7 @@ Voleu desar el missatge? Eliminar l'element - + from des de @@ -15917,18 +14644,10 @@ Voleu desar el missatge? Msg pendent - + Hide Amagar - - Send invite? - Enviar invitació? - - - Do you really want send a invite with your Certificate? - Estàs segur de voler enviar una invitació amb el teu certificat? - NATStatus @@ -16066,7 +14785,7 @@ Voleu desar el missatge? ID del contacte - + Remove unused keys... Eliminar claus no utilitzades... @@ -16076,7 +14795,7 @@ Voleu desar el missatge? - + Clean keyring Neteja el clauer @@ -16093,7 +14812,13 @@ Notes: Es guardarà una copia de seguretat del teu clauer antic. L'eliminació potser falli si tens múltiples instancies de RetroShare a la mateixa màquina. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info Informació del clauer @@ -16128,18 +14853,13 @@ Per seguretat, s'ha fet una copia de seguretat del teu clauer Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. Inconsistència de dades al clauer. Això és probablement un "bug". Si us plau, contacta amb els desenvolupadors. - - - Export/create a new node - Exporta/Crea un node nou - Trusted keys only Només claus de confiança - + Search name Cercar nom @@ -16149,12 +14869,12 @@ Per seguretat, s'ha fet una copia de seguretat del teu clauer Cerca Id contacte - + Profile details... Detalls del perfil... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -16163,13 +14883,6 @@ Reported error: Error reportat: - - NetworkPage - - Network - Xarxa - - NetworkView @@ -16196,7 +14909,7 @@ Error reportat: NewFriendList - + Offline Friends @@ -16217,7 +14930,7 @@ Error reportat: - + Groups Grups @@ -16247,19 +14960,19 @@ Error reportat: importar la teva llista d'amics, incloent els grups - - + + Search - + ID ID - + Search ID ID cerca @@ -16269,12 +14982,12 @@ Error reportat: - + Show Items Mostrar elements - + Last contact @@ -16284,7 +14997,7 @@ Error reportat: IP - + Group Grup @@ -16399,7 +15112,7 @@ Error reportat: Contreure tot - + Do you want to remove this node? Voleu suprimir aquest node? @@ -16409,7 +15122,7 @@ Error reportat: Voleu suprimir aquest amic? - + Done! Fet! @@ -16523,11 +15236,7 @@ com a mínim un dels contactes no s'ha afegit a un grup NewsFeed - Log entries - Entrades en el registre - - - + Activity Stream @@ -16542,11 +15251,7 @@ com a mínim un dels contactes no s'ha afegit a un grup Suprimeix-ho tot - This is a test. - Això és un test. - - - + Newest on top El més nou a dalt @@ -16556,21 +15261,12 @@ com a mínim un dels contactes no s'ha afegit a un grup El més vell a dalt - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;News Feed</h1> <p>The Log Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel and Forum posts</li> <li>New Channels and Forums you can subscribe to</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Novetats</h1> -<p>La font de noticies mostra els últims esdeveniments a la xarxa ordenats per hora de recepció. Això et proporciona un resum de l'activitat dels teus amics. Pots triar quins esdeveniments es mostren a <b>Opcions</b>. </p> <p>Els esdeveniments mostrats són: <ul> <li>Intents de connexió (útil per fer amics amb gent nova i controlar qui està intentant connectar-te)</li> <li>Publicacions a canals i fòrums</li> <li>Nous canals i fòrums als que et pots subscriure</li> <li>Missatges privats dels teus amics</li> </ul> </p> - - - Log - Registre - - - + Activity @@ -16625,10 +15321,6 @@ com a mínim un dels contactes no s'ha afegit a un grup Blogs Blocs - - Security - Seguretat - @@ -16650,10 +15342,6 @@ com a mínim un dels contactes no s'ha afegit a un grup Message Missatge - - Connect attempt - Intent de connexió - @@ -16670,10 +15358,6 @@ com a mínim un dels contactes no s'ha afegit a un grup Ip security Seguretat Ip - - Log - Registre - Friend Connected @@ -16684,10 +15368,6 @@ com a mínim un dels contactes no s'ha afegit a un grup Circles Cercles - - Links - Enllaços - Activity @@ -16740,26 +15420,6 @@ com a mínim un dels contactes no s'ha afegit a un grup Chat rooms Sales de xat - - Chat Rooms - Sales de xat - - - Count occurrences of my current identity - Comptar quants cops hi ha la meva identitat actual - - - Count occurrences of any of the following texts (separate by newlines): - Comptar coincidències de qualsevol dels texts següents (un per línia): - - - Checked, if the identity and the text above occurrences must be in the same case to trigger count. - Marca'l si identitats i texts a la part superior han de coincidir en majúscules/minúscules pel comptador. - - - Case sensitive - Diferenciar majúscules/minúscules - Position @@ -16836,24 +15496,16 @@ com a mínim un dels contactes no s'ha afegit a un grup Disable All Toaster temporarily Deshabilitar notificacions temporalment - - Feed - Font - Systray Àrea de notificació - - Count all unread messages - Comptar tots els missatges no llegits - NotifyQt - + Passphrase required Es requereix contrasenya @@ -16873,12 +15525,12 @@ com a mínim un dels contactes no s'ha afegit a un grup Contrasenya incorrecta ! - + Please enter your Retroshare passphrase Si us plau, introdueix la contrasenya del Retroshare - + Unregistered plugin/executable Complement/Executable no registrat @@ -16893,19 +15545,7 @@ com a mínim un dels contactes no s'ha afegit a un grup Si us plau, comprova l'hora del sistema. - Examining shared files... - Examinant arxius compartits... - - - Hashing file - Calculant número de hash - - - Saving file index... - Desant índex de l'arxiu... - - - + Test Test @@ -16916,17 +15556,19 @@ com a mínim un dels contactes no s'ha afegit a un grup + Unknown title Títol desconegut - + + Encrypted message Missatge encriptat - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). Perquè aquestes sales de xat funcionin l'hora en el teu ordinador ha de ser correcta. Si us plau, comprova que és el cas (És possible que una variació de varis minuts s'hagi detectat respecte els teus amics). @@ -16934,7 +15576,7 @@ com a mínim un dels contactes no s'ha afegit a un grup OnlineToaster - + Friend Online Amic en línia @@ -16986,10 +15628,6 @@ Tràfic baix: 10 %s del tràfic estàndard i PENDENT: posar en pausa totes les t PGPKeyDialog - - Dialog - Diàleg - Profile info @@ -17055,10 +15693,6 @@ Tràfic baix: 10 %s del tràfic estàndard i PENDENT: posar en pausa totes les t This profile has signed your own profile key Aquest perfil ha signat la clau del teu perfil - - Key signatures : - Signatures de la clau : - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> @@ -17088,23 +15722,20 @@ p, li { white-space: pre-wrap; } Clau PGP - - These options apply to all nodes of the profile: - Aquestes opcions s'apliquen a tots els nodes del perfil: + + Friend options + - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> - <html><head/><body><p><span style=" font-size:10pt;">Signar la clau d'un amic és una forma d'expressar la teva confiança en aquest amic als teus altres amics. Els ajudarà a decidir si volen acceptar o no connexions d'aquesta clau basant-se en la teva confiança. Signar una clau és completament opcional i no es pot desfer, fes-ho amb cura.</span></p></body></html> + + These options apply to all nodes of the profile: + Aquestes opcions s'apliquen a tots els nodes del perfil: Keysigning: - - Sign PGP key - Signa clau PGP - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -17141,12 +15772,7 @@ p, li { white-space: pre-wrap; } Inclou les signatures - - Options - Opcions - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> <html><head/><body><p align="justify">El RetroShare periòdicament comprova la teva llista d'amics per arxius navegables que coincideixin amb els mateixos que estàs descarregant, per establir una transferència directa. En aquest cas els teus amics sabran què descarregues.</p><p align="justify">Si no vols que això passi per algun amic en concret, desmarca aquesta casella. Encara podràs realitzar transferències directes si ho demanes explícitament, per exemple descarregant de la llista del teu amic directament. Això s'aplicarà a totes les ubicacions del mateix node.</p></body></html> @@ -17160,10 +15786,6 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this profile (e.g. when the message author is a signed identity that belongs to this profile). This can be used for instance to send files between your own nodes.</p></body></html> - - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> - <html><head/><body><p>Aquesta opció et permet descarregar automàticament un arxiu recomanat en un missatge que provingui d'aquest node. Això es pot utilitzar per exemple per enviar arxius entre els teus nodes. S'aplica a totes les ubicacions del mateix node.</p></body></html> - Auto-download recommended files from this node @@ -17196,21 +15818,21 @@ p, li { white-space: pre-wrap; } kB/s - - + + RetroShare RetroShare - - + + Error : cannot get peer details. Error: no es poden obtenir detalls del contacte. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) L'algorisme de la clau proporcionada no és suportada pel RetroShare @@ -17231,7 +15853,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. El nivell de confiança és una forma d'expressar la teva confiança en aquesta clau. No s'utilitza pel programa ni es comparteix, però et pot ser útil per recordar claus bones/dolentes. @@ -17300,10 +15922,6 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir Check the password! - - Maybe password is wrong - Potser la contrasenya sigui incorrecta - You haven't set a trust level for this key. @@ -17311,12 +15929,12 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir - + Retroshare profile Perfil de Retroshare - + This is your own PGP key, and it is signed by : Aquesta és la teva clau PGP i està signada per : @@ -17342,7 +15960,7 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir PeerItem - + Chat Xat @@ -17363,7 +15981,7 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir Eliminar l'element - + Name: Nom: @@ -17403,7 +16021,7 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir Diferencia de temps: - + Write Message Escriure missatge @@ -17417,10 +16035,6 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir Friend Connected Amic connectat - - Connect Attempt - Intent de connexió - Connection refused by peer @@ -17459,17 +16073,13 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir Unknown Desconegut - - Unknown Peer - Contacte desconegut - Hide Amagar - + Send Message Enviar missatge @@ -17521,10 +16131,6 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir Chat with this person as... Xat amb aquesta persona com... - - Send message to this person - Enviar un missatge a aquesta persona - Invite to Circle @@ -17583,10 +16189,6 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir <html><head/><body><p>Anyone in your contact list will automatically have a positive opinion if not set. This allows to automatically raise reputations of used nodes. </p></body></html> <html><head/><body><p>Qualsevol de la teva llista de contactes tindrà automàticament una opinió positiva, si no ho canvies. Això permet que la reputació dels nodes en ús tinguin millor reputació.</p></body></html> - - automatically give "Positive" opinion to my contacts - donar automàticament una opinió "Positiva" als meus contactes - use "positive" as the default opinion for contacts (instead of neutral) @@ -17644,13 +16246,6 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir <html><head/><body><p>Per tal d'evitar que identitats expulsades esborrades tornin perquè estan sent usades a fòrums o canals, se les manté en una llista durant un temps. Si després d'aquest temps, s'esborren de la llista però continuen sent usades, tornaran a propagar-se per fòrums, sales de xat, etc.</p></body></html> - - PhotoCommentItem - - Form - Formulari - - PhotoDialog @@ -17658,23 +16253,11 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir PhotoShare PhotoShare - - Photo - Foto - TextLabel EtiquetaTexte - - Comment - Comentari - - - Summary - Resum - Album / Photo Name @@ -17683,7 +16266,7 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir Details - + Detalls @@ -17735,14 +16318,6 @@ Avís: En les opcions de Transferència d'arxius, has marcat descarrega dir ... ... - - Add Comment - Afegir comentari - - - Write a comment... - Escriure un comentari... - Album @@ -17813,10 +16388,6 @@ p, li { white-space: pre-wrap; } Create Album Crear àlbum - - View Album - Veure àlbum - Edit Album Details @@ -17838,17 +16409,17 @@ p, li { white-space: pre-wrap; } Presentació de diapositives - + My Albums Els meus àlbums - + Subscribed Albums Àlbums subscrits - + Shared Albums Àlbums compartits @@ -17878,7 +16449,7 @@ abans de demanar editar-lo! PhotoSlideShow - + Album Name Nom d'àlbum @@ -17937,19 +16508,19 @@ abans de demanar editar-lo! - - + + TextLabel - + Posted by - + ago @@ -17985,12 +16556,12 @@ abans de demanar editar-lo! PluginItem - + TextLabel EtiquetaTexte - + Show more details about this plugin Mostra més detalls sobre aquest complement @@ -18136,61 +16707,6 @@ p, li { white-space: pre-wrap; } Plugin look-up directories Directoris on buscar complements - - Plugin disabled. Click the enable button and restart Retroshare - Complement deshabilitat. Clica el botó d'activació o reinicia el Retroshare - - - [disabled] - [desactivat] - - - No API number supplied. Please read plugin development manual. - No s'ha proporcionat número d'API. Si us plau, llegeix el manual de desenvolupament de complements. - - - [loading problem] - [problema de carrega] - - - No SVN number supplied. Please read plugin development manual. - No s'ha proporcionat número d'SVN. Si us plau, llegeix el manual de desenvolupament de complements. - - - Loading error. - Error carregant. - - - Missing symbol. Wrong version? - Falten símbols. Versió equivocada? - - - No plugin object - Sense objecte del complement - - - Plugins is loaded. - Complement carregat. - - - Unknown status. - Estat desconegut. - - - Check this for developing plugins. They will not -be checked for the hash. However, in normal -times, checking the hash protects you from -malicious behavior of crafted plugins. - Activa pels complements en desenvolupament. -No se'ls comprovarà el hash. No obstant, en -circumstancies normals, comprovar el hash et -protegeix de l'acció maliciosa de complements -modificats. - - - <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Plugins</h1> <p>Plugins are loaded from the directories listed in the bottom list.</p> <p>For security reasons, accepted plugins load automatically until the main Retroshare executable or the plugin library changes. In such a case, the user needs to confirm them again. After the program is started, you can enable a plugin manually by clicking on the "Enable" button and then restart Retroshare.</p> <p>If you want to develop your own plugins, contact the developpers team they will be happy to help you out!</p> - <h1><img width="24" src=":/images/help_64.png">&nbsp;&nbsp;Complements</h1> <p>Els complements es carreguen dels directoris del llistat inferior.</p> <p> Per raons de seguretat, els complements acceptats es carreguen automàticament mentre l'executable principal del Retroshare o els complements no canviïn. En tal cas, l'usuari haurà de confirmar-ho altre cop. Un cop el programa s'ha iniciat, pots habilitar un complement manualment fent clic al botó "Activa" i després reiniciant el Retroshare.</p> <p>Si vols desenvolupar els teus propis complements contacta amb els desenvolupadors i estaran contents d'ajudar-te!</p> - Plugins @@ -18260,12 +16776,27 @@ modificats. Posar la finestra per damunt - + + Ban this person (Sets negative opinion) + Expulsa aquesta persona (Emet una opinió negativa) + + + + Give neutral opinion + Opinió neutre + + + + Give positive opinion + Opinió positiva + + + Choose window color... - + Dock window @@ -18299,22 +16830,6 @@ modificats. Close conversation? - - The person you are talking to has deleted the secured chat tunnel. - La persona amb qui estaves parlant ha esborrat el túnel de xat segur. - - - The chat partner deleted the secure tunnel, messages will be delivered as soon as possible - El company de xat ha esborrat el túnel segur, els missatges s'entregaran el més aviat possible. - - - Closing this window will end the conversation, notify the peer and remove the encrypted tunnel. - Tancar aquesta finestra finalitzarà la conversa, notifica-ho al contacte i esborra el túnel encriptat. - - - Kill the tunnel? - Matar el túnel? - PostedCardView @@ -18334,7 +16849,7 @@ modificats. Nou - + Vote up Votar positiu @@ -18354,8 +16869,8 @@ modificats. \/ - - + + Comments Comentaris @@ -18380,13 +16895,13 @@ modificats. - - + + Comment Comentari - + Comments Comentaris @@ -18414,20 +16929,12 @@ modificats. PostedCreatePostDialog - Signed by: - Signat per: - - - Notes - Notes - - - + Create a new Post - + RetroShare RetroShare @@ -18442,12 +16949,22 @@ modificats. - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File Carrega arxiu d'imatge - + Post image @@ -18463,7 +16980,17 @@ modificats. - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -18473,23 +17000,7 @@ modificats. - Submit Post - Publica entrada - - - You are submitting a link. The key to a successful submission is interesting content and a descriptive title. - Estàs enviant un enllaç. La clau per a que tingui èxit és un contingut interessant i un títol descriptiu. - - - Submit - Publica - - - Submit a new Post - Publica una entrada nova - - - + Please add a Title Si us plau, afegeix un títol @@ -18509,12 +17020,22 @@ modificats. - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -18529,7 +17050,7 @@ modificats. Publica com - + Post @@ -18540,7 +17061,7 @@ modificats. Imatge - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -18550,7 +17071,7 @@ modificats. Títol - + Link Enllaç @@ -18558,44 +17079,12 @@ modificats. PostedDialog - Posted Links - Enllaços publicats - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Posted</h1> <p>The posted service allows you to share internet links, that spread among Retroshare nodes like forums and channels</p> <p>Links can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Posted links are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/images/help_64.png">&nbsp;&nbsp;Publicacions</h1> <p>El servei de publicacions et permet compartir enllaços d'Internet que es distribueixen entre els nodes de Retroshare com si fos un fòrum o canal</p> <p>Els enllaços poden ser comentats pels usuaris subscrits. També hi ha un sistema de promoció que permet destacar enllaços importants.</p> <p>No hi ha cap restricció en quins enllaços es comparteixen. Sigues curós al fer clic en ells.</p> <p>Els enllaços publicats es mantenen durant %1 dies i es sincronitzen durant els últims %2 dies, a no ser que ho canviïs.</p> - - - Create Topic - Crear tema - - - My Topics - Els meus temes - - - Subscribed Topics - Temes subscrits - - - Popular Topics - Temes populars - - - Other Topics - Altres temes - - - Links - Enllaços - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -18629,31 +17118,7 @@ modificats. PostedGroupDialog - Posted Topic - Tema publicat - - - Add Topic Admins - Afegir administradors de tema - - - Select Topic Admins - Seleccionar administradors de tema - - - Create New Topic - Crear nou tema - - - Edit Topic - Editar tema - - - Update Topic - Actualitzar tema - - - + Create New Board @@ -18691,7 +17156,17 @@ modificats. PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted Subscriure's als publicats @@ -18707,7 +17182,7 @@ modificats. - + Expand Ampliar @@ -18722,24 +17197,17 @@ modificats. - Posted Description - Descripció dels publicats - - - Loading - Carregant - - - New Posted - Publicats nous - - - + Loading... - + + Never + Mai + + + New Board @@ -18752,22 +17220,18 @@ modificats. PostedItem - + 0 0 - Site - Lloc - - - - + + Comments Comentaris - + Copy RetroShare Link Copia l'enllaç RetroShare @@ -18778,12 +17242,12 @@ modificats. - + Comment Comentari - + Comments Comentaris @@ -18793,7 +17257,7 @@ modificats. <p><font color="#ff0000"><b>L'autor d'aquest missatge (amb Id %1) està expulsat.</b> - + Click to view Picture @@ -18803,21 +17267,17 @@ modificats. Amagar - + Vote up Votar positiu - + Vote down Votar negatiu - \/ - \/ - - - + Set as read and remove item Marcar com llegit i eliminar l'element @@ -18827,7 +17287,7 @@ modificats. Nou - + New Comment: Nou comentari: @@ -18837,7 +17297,7 @@ modificats. Valor del comentari - + Name Nom @@ -18878,77 +17338,10 @@ modificats. - + Loading Carregant - - By - Per - - - - PostedListWidget - - Form - Formulari - - - Hot - Calent - - - New - Nou - - - Top - Capdamunt - - - Today - Avui - - - Yesterday - Ahir - - - This Week - Aquesta setmana - - - This Month - Aquest mes - - - This Year - Aquest any - - - Submit a new Post - Publica una entrada nova - - - Next - Següent - - - RetroShare - RetroShare - - - Please create or choose a Signing Id before Voting - Si us plau, crea o escull una Id signant abans de votar - - - Previous - Previ - - - 1-10 - 1-10 - PostedListWidgetWithModel @@ -18960,7 +17353,7 @@ modificats. Details - + Detalls @@ -18968,7 +17361,17 @@ modificats. - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -18978,15 +17381,15 @@ modificats. Administrador: - + - + unknown desconegut - + Distribution: Distribució: @@ -18996,42 +17399,42 @@ modificats. - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts Publicacions - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -19051,7 +17454,7 @@ modificats. Calent - + Search @@ -19081,17 +17484,17 @@ modificats. - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -19106,12 +17509,17 @@ modificats. Buit - + Copy RetroShare Link Copia l'enllaç RetroShare - + + Copy http Link + + + + Show author in People tab @@ -19121,27 +17529,31 @@ modificats. Editar - + + information informació - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -19156,7 +17568,7 @@ modificats. Subscriure's - + Never Mai @@ -19230,6 +17642,16 @@ modificats. No Channel Selected No hi ha canal seleccionat + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -19238,14 +17660,6 @@ modificats. Tabs Pestanyes - - Open each topic in a new tab - Obrir cada tema en una nova pestanya - - - Links - Enllaços - Open each board in a new tab @@ -19259,10 +17673,6 @@ modificats. PostedUserNotify - - Posted - Enviat - Board Post @@ -19331,25 +17741,17 @@ modificats. Directori de perfils - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Selecciona una clau de node de RetroShare de la llista inferior per ser utilitzada en un altre ordinador, i prem &quot;Exportar clau seleccionada.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Per crear una nova ubicació en un altre ordinador, selecciona el gestor de identitats en el diàleg d'entrada. Des d'allà podràs importar l'arxiu de clau i crear una nova ubicació per aquella clau.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Crear un node nou amb la mateixa clau fa que els nodes dels teus amics acceptin el nou node automàticament.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> + @@ -19459,7 +17861,7 @@ i utilitzar el botó d'importació per carregar-lo ProfileWidget - + Edit status message Editar missatge d'estat @@ -19475,7 +17877,7 @@ i utilitzar el botó d'importació per carregar-lo Directori de perfils - + Public Information Informació pública @@ -19510,12 +17912,12 @@ i utilitzar el botó d'importació per carregar-lo En línia des de: - + Other Information Altra informació - + My Address La meva adreça @@ -19559,51 +17961,27 @@ i utilitzar el botó d'importació per carregar-lo PulseAddDialog - Post From: - Entrada de: - - - Account 1 - Compte 1 - - - Account 2 - Compte 2 - - - Account 3 - Compte 3 - - - + Add to Pulse Afegir al Pols - filter - filtre - - - URL Adder - Afegidor d'URL - - - + Display As Mostra com - + URL URL - + GroupLabel - + IDLabel @@ -19613,12 +17991,12 @@ i utilitzar el botó d'importació per carregar-lo De: - + Head - + Head Shot @@ -19648,13 +18026,13 @@ i utilitzar el botó d'importació per carregar-lo Negatiu - - + + Whats happening? - + @@ -19666,12 +18044,22 @@ i utilitzar el botó d'importació per carregar-lo - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -19680,17 +18068,13 @@ i utilitzar el botó d'importació per carregar-lo Cancel Cancel·la - - Post Pulse to Wire - Publica Pols a Wire - Post - + Reply to Pulse @@ -19705,34 +18089,24 @@ i utilitzar el botó d'importació per carregar-lo - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - Des de - - - Date - Data - - - ... - ... + + Load Picture File + Carrega arxiu d'imatge @@ -19743,7 +18117,7 @@ i utilitzar el botó d'importació per carregar-lo Formulari - + @@ -19762,7 +18136,7 @@ i utilitzar el botó d'importació per carregar-lo PulseReply - + icn @@ -19772,7 +18146,7 @@ i utilitzar el botó d'importació per carregar-lo - + REPLY @@ -19799,7 +18173,7 @@ i utilitzar el botó d'importació per carregar-lo - + FOLLOW @@ -19809,7 +18183,7 @@ i utilitzar el botó d'importació per carregar-lo - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -19829,7 +18203,7 @@ i utilitzar el botó d'importació per carregar-lo - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -19945,7 +18319,7 @@ i utilitzar el botó d'importació per carregar-lo - + FOLLOW @@ -19953,37 +18327,42 @@ i utilitzar el botó d'importació per carregar-lo PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -20015,7 +18394,7 @@ i utilitzar el botó d'importació per carregar-lo - + FOLLOW @@ -20023,8 +18402,8 @@ i utilitzar el botó d'importació per carregar-lo QObject - - + + Confirmation Confirmació @@ -20295,12 +18674,12 @@ Els caràcters <b>",|,/,\,&lt;&gt;,*,?</b> es substitui Detalls del contacte - + File Request canceled Petició d'arxiu cancel·lada - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. Aquesta versió de RetroShare utilitza l'OpenPGP-SDK. Com a efecte secundari no utilitza el clauer PGP del sistema, sinó un clauer compartit per totes les instancies de RetroShare. <br><br>No sembla que tinguis aquest clauer, tot i que tens claus PGP als comptes existents de RetroShare, probablement perquè acabes de canviar a aquesta nova versió del programa. @@ -20331,7 +18710,7 @@ Els caràcters <b>",|,/,\,&lt;&gt;,*,?</b> es substitui S'ha produït un error inesperat. Si us plau, informa 'RsInit::InitRetroShare unexpected return code %1'. - + Cannot start Tor Manager! No es pot iniciar "Tor Manager"! @@ -20369,7 +18748,7 @@ L'error reportat és:" No ha estat possible iniciar un servei ocult. - + Multiple instances Múltiples instancies @@ -20390,6 +18769,26 @@ Arxiu bloquejant:\n Hi ha hagut un error inesperat quan el RetroShare intentava obtenir el bloqueig d'instància única Arxiu de bloqueig:\n + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -20410,14 +18809,6 @@ Arxiu de bloqueig:\n End-to-end encrypted conversation established - - Tunnel is pending... Messages will be delivered as soon as possible - Túnel pendent... Els missatges s'entregaran el més aviat possible - - - Secured tunnel is working. Messages are delivered immediately! - Túnel segur establert. Els missatges s'entregaran immediatament! - The collection file %1 could not be opened. @@ -20480,7 +18871,7 @@ L'error reportat és: Dades reenviades - + You appear to have nodes associated to DSA keys: Sembla que tens nodes associats a claus DSA: @@ -20490,7 +18881,7 @@ L'error reportat és: Les claus DSA encara no són suportades en aquesta versió de RetroShare. Tots aquests nodes no es podran utilitzar. Ho sentim molt. - + enabled activat @@ -20500,7 +18891,7 @@ L'error reportat és: desactivat - + Move IP %1 to whitelist Mou la IP %1 a la llista blanca @@ -20516,7 +18907,7 @@ L'error reportat és: - + %1 seconds ago fa %1 segons @@ -20584,7 +18975,7 @@ Security: no anonymous IDs Seguretat: IDs anònimes no - + Join chat room Afegeix-te a la sala de xat @@ -20612,7 +19003,7 @@ Seguretat: IDs anònimes no no s'ha pogut interpretar l'arxiu XML! - + Indefinitely Indefinidament @@ -20792,13 +19183,29 @@ Seguretat: IDs anònimes no Ban list + + + Name + Nom + + Node + Node + + + + Address + Adreça + + + + Status Estat - + NXS @@ -20991,10 +19398,6 @@ Seguretat: IDs anònimes no Click to resume the hashing process Clica per continuar amb el càlcul de hash - - <p>This certificate contains: - <p>Aquest certificat conté: - Idle @@ -21045,6 +19448,18 @@ Seguretat: IDs anònimes no Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -21207,7 +19622,7 @@ p, li { white-space: pre-wrap; } - + Network Wide Tota la xarxa @@ -21390,7 +19805,7 @@ p, li { white-space: pre-wrap; } Formulari - + The loading of embedded images is blocked. La càrrega d'imatges incrustades està bloquejada. @@ -21403,7 +19818,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default Permès per defecte @@ -21576,12 +19991,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + Desar imatge + + + + Copy image + + + + Document source @@ -21589,12 +20014,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options Opcions de la vista d'arbre - + Show Header @@ -21624,14 +20049,6 @@ p, li { white-space: pre-wrap; } Show column … - - Show column... - Mostrar columna... - - - [no title] - [sense títol] - RatesStatus @@ -22294,7 +20711,7 @@ Si creus que és correcta, treu la línia corresponent de l'arxiu i torna&a RsDownloadListModel - + Name i.e: file name Nom @@ -22415,7 +20832,7 @@ Si creus que és correcta, treu la línia corresponent de l'arxiu i torna&a RsFriendListModel - + Name Nom @@ -22435,7 +20852,7 @@ Si creus que és correcta, treu la línia corresponent de l'arxiu i torna&a IP - + Profile ID @@ -22491,7 +20908,7 @@ prevents the message to be forwarded to your friends. El missatge es propagarà als teus amics. - + [ ... Redacted message ... ] [ ... Missatge modificat ... ] @@ -22505,11 +20922,6 @@ prevents the message to be forwarded to your friends. [Unknown] [Desconegut] - - - [ ... Missing Message ... ] - [ ... Missatge perdut ... ] - RsMessageModel @@ -22523,6 +20935,11 @@ prevents the message to be forwarded to your friends. From Des de + + + To + A + Subject @@ -22545,13 +20962,18 @@ prevents the message to be forwarded to your friends. - Click to sort by read - Clica per ordenar per llegits + Click to sort by read status + - Click to sort by from - Clica per ordenar pel remitent + Click to sort by author + + + + + Click to sort by destination + @@ -22574,7 +20996,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -22595,7 +21019,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. Reinicialitza TOTS les valors de configuració del RetroShare. @@ -22656,7 +21080,7 @@ prevents the message to be forwarded to your friends. Defineix la llengua del RetroShare. - + Unable to open log file '%1': %2 Incapaç d'obrir l'arxiu de registre '%1': %2 @@ -22677,11 +21101,7 @@ prevents the message to be forwarded to your friends. No s'ha pogut crear el directori de dades: %1 - Revision - Revisió - - - + opmode ModeOp @@ -22711,7 +21131,7 @@ prevents the message to be forwarded to your friends. Informació d'ús de la IGU de RetroShare - + Invalid language code specified: El codi d'idioma especificat no és vàlid: @@ -22729,7 +21149,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. Error d'accés al registre. Potser necessitis drets d'administrador. @@ -22746,12 +21166,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) Inserir una paraula clau aquí (com a mínim 3 caràcters de longitud) - + Start Search Iniciar cerca @@ -22813,7 +21233,7 @@ prevents the message to be forwarded to your friends. Neteja - + KeyWords Paraules Clau @@ -22828,7 +21248,7 @@ prevents the message to be forwarded to your friends. Id cerca - + Filename Nom d'arxiu @@ -22928,23 +21348,23 @@ prevents the message to be forwarded to your friends. Descarregar seleccionats - + File Name Nom d'arxiu - + Download Descarregar - + Copy RetroShare Link Copia l'enllaç RetroShare - + Send RetroShare Link Enviar enllaç RetroShare @@ -22954,7 +21374,7 @@ prevents the message to be forwarded to your friends. - + Download Notice Avís de descarrega @@ -22991,7 +21411,7 @@ prevents the message to be forwarded to your friends. Suprimeix-ho tot - + Folder Directori @@ -23002,17 +21422,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) Enllaç(os) RetroShare nou(s) - + Open Folder Obrir directori - + Create Collection... Crear col·lecció... @@ -23032,7 +21452,7 @@ prevents the message to be forwarded to your friends. Descarregar d'arxiu de col·lecció... - + Collection Col·lecció @@ -23040,7 +21460,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details Detalls del contacte @@ -23056,22 +21476,22 @@ prevents the message to be forwarded to your friends. Eliminar l'element - + IP address: Adreça IP: - + Peer ID: ID del contacte: - + Location: Ubicació: - + Peer Name: Nom del contacte: @@ -23088,7 +21508,7 @@ prevents the message to be forwarded to your friends. Amagar - + but reported: però reportat: @@ -23113,8 +21533,8 @@ prevents the message to be forwarded to your friends. <p>Aquesta és la IP que el teu amic diu estar connectat. Si just has canviat d'IP això és un fals avís. Si no, significa que la teva connexió amb aquest amic està sent encaminada per un contacte intermig, que seria sospitós.</p> - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> <html><head/><body><p>Aquest avís apareix per protegir-te contra atacs de reenviament. En tal cas, l'amic amb qui estàs connectat veurà la IP de l'atacant, no la teva IP externa.</p><p><br/></p><p>No obstant, si acabes de canviar la teva IP per qualsevol motiu (alguns proveïdors forcen el canvi d'IP regularment) aquest avís només t'indica que t'has connectat amb el teu amic abans que el RetroShare hagi notat el canvi d'IP. Res malament en tal cas.</p><p><br/></p><p>Pots evitar fàcilment els falsos avisos afegint a la llista blanca les teves IPs (Ex.:El rang d'IPs del teu proveïdor) o deshabilitant completament aquests avisos a Opcions-&gt;Notificar-&gt;Novetats.</p></body></html> @@ -23122,7 +21542,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare vol ser amic teu al RetroShare @@ -23153,7 +21573,7 @@ prevents the message to be forwarded to your friends. - + Expand Ampliar @@ -23198,12 +21618,12 @@ prevents the message to be forwarded to your friends. Estat: - + Write Message Escriure missatge - + Connect Attempt Intent de connexió @@ -23223,17 +21643,22 @@ prevents the message to be forwarded to your friends. Intent de connexió (Sortint) desconegut - + Unknown Security Issue Problema de seguretat desconegut - - A unknown peer + + SSL request - + + An unknown peer + + + + Unknown Desconegut @@ -23243,11 +21668,7 @@ prevents the message to be forwarded to your friends. - Unknown Peer - Contacte desconegut - - - + Hide Amagar @@ -23257,7 +21678,7 @@ prevents the message to be forwarded to your friends. Voleu suprimir aquest amic? - + Certificate has wrong signature!! This peer is not who he claims to be. El certificat té una signatura incorrecta!! Aquest contacte no és qui diu ser. @@ -23267,12 +21688,12 @@ prevents the message to be forwarded to your friends. Certificat perdut/danyat. No és un usuari de RetroShare. - + Certificate caused an internal error. El certificat a provocat un error intern. - + Peer/node not in friendlist (PGP id= El contacte/node no és a la llista d'amics (Id PGP= @@ -23331,12 +21752,12 @@ prevents the message to be forwarded to your friends. - + Local Address Adreça local - + NAT NAT @@ -23357,22 +21778,22 @@ prevents the message to be forwarded to your friends. Port: - + Local network Xarxa local - + External ip address finder Cercador d'adreça IP externa - + UPnP UPnP - + Known / Previous IPs: Conegudes / IPs previes: @@ -23388,21 +21809,16 @@ connectar-te quan tens pocs amics. També ajuda si estàs darrera d'un tallafocs o una VPN. - - Allow RetroShare to ask my ip to these websites: - Permet que el RetroShare pregunti la meva IP a aquests llocs web: - - - - - + + + kB/s kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. El rang de ports acceptats va de 10 fins 65535. Normalment els ports per sota 1024 estan reservats pel teu sistema. @@ -23412,23 +21828,46 @@ d'un tallafocs o una VPN. El rang de ports acceptables va de 1024 a 65535. Els ports per sota 1024 estan reservats pel teu sistema. - + Onion Address Adreça Onion - + Discovery On (recommended) Descobriment activat (Recomanat) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. S'ha configurat Tor automàticament per part de Retroshare. No hauria de fer falta que canviessis res aquí. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off Descobriment desactivat @@ -23438,7 +21877,7 @@ d'un tallafocs o una VPN. Ocult - Mira la configuració - + I2P Address Adreça I2P @@ -23463,41 +21902,95 @@ d'un tallafocs o una VPN. Entrants correctes - - + + + Proxy seems to work. El repetidor sembla que funciona - + + I2P proxy is not enabled El repetidor I2P no està activat - - BOB is running and accessible - BOB està en funcionament i accessible + + SAMv3 is running and accessible + - BOB is not accessible! Is it running? - No es pot accedir a BOB! Està en funcionament? + SAMv3 is not accessible! Is i2p running and SAM enabled? + - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - RetroShare utilitza BOB per establir a %1 túnel a %2:%3 (anomenat %4) - -Quan es canvien opcions (per exemple el port) utilitza els botons inferiors per reiniciar BOB. - - + - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client client @@ -23512,73 +22005,7 @@ Quan es canvien opcions (per exemple el port) utilitza els botons inferiors per desconegut - - - - BOB is processing a request - BOB està processant una petició - - - - connectivity check - comprovació de connectivitat - - - - generating key - generant clau - - - - starting up - iniciant - - - - shuting down - apagant - - - - BOB is processing a request: %1 - BOB està processant una petició: %1 - - - - BOB is broken - - BOB està trencat - - - - - BOB encountered an error: - - BOB ha trobat un error: - - - - - BOB tunnel is running - El túnel BOB està funcionant - - - - BOB is working fine: tunnel established - BOB funciona correctament: túnel establert - - - - BOB tunnel is not running - El túnel BOB no està funcionant - - - - BOB is inactive: tunnel closed - BOB és inactiu: túnel tancat - - - + request a new server key demana una clau nova de servidor @@ -23588,22 +22015,7 @@ Quan es canvien opcions (per exemple el port) utilitza els botons inferiors per carrega una clau de servidor de base64 - - stop BOB tunnel first to generate a new key - para el túnel BOB per generar abans una clau nova - - - - stop BOB tunnel first to load a key - Para túnel BOB abans per carregar una clau - - - - stop BOB tunnel first to disable BOB - para el túnel BOB abans per desactivar BOB - - - + You are reachable through the hidden service. Se't pot contactar a través d'un servei ocult. @@ -23617,12 +22029,12 @@ Estan tots els serveis funcionant correctament?? Comprova els teus ports! - + [Hidden mode] [Node ocult] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> <html><head/><body><p>Això buida la llista d'adreces conegudes. Això és útil si per alguna rao la teva llista d'adreces conté una adreça invàlida/irrellevant/caducada que vols evitar passar als teus amics com una adreça de contacte.</p></body></html> @@ -23632,7 +22044,7 @@ Comprova els teus ports! Neteja - + Download limit (KB/s) Límit de baixada (KiB/s) @@ -23647,24 +22059,24 @@ Comprova els teus ports! Límit de pujada (KiB/s) - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> <html><head/><body><p>El límit de pujada afecta a tota l'aplicació. Un límit de pujada massa baix pot bloquejar eventualment serveis de baixa prioritat (Fòrums, canals). El valor mínim recomanat és de 50 KiB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. AVÍS: Aquests valors no tenen en compte els Repetidors. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -23681,17 +22093,7 @@ Ara introdueix l'adreça (e.g. 127.0.0.1) i el port que has escullit abans Pots connectar-te a nodes ocults, encara que estiguis en un node estàndard, així que perquè no configurar Tor i/o I2P? - - Automatic I2P/BOB - I2P/BOB automàtic - - - - Enable I2P BOB - changing this requires a restart to fully take effect - Activa I2P BOB - canviar això necessita que reiniciïs per tindre efecte - - - + enableds advanced settings activar opcions avançades @@ -23701,12 +22103,7 @@ Pots connectar-te a nodes ocults, encara que estiguis en un node estàndard, aix mode avançat - - I2P Basic Open Bridge - Pont Obert I2P Bàsic - - - + I2P Instance address Adreça instancia I2P @@ -23716,17 +22113,7 @@ Pots connectar-te a nodes ocults, encara que estiguis en un node estàndard, aix 127.0.0.1 - - I2P proxy port - Port del proxy I2P - - - - BOB accessible - BOB accessible - - - + Address Adreça @@ -23766,7 +22153,7 @@ Pots connectar-te a nodes ocults, encara que estiguis en un node estàndard, aix carrega clau - + Start Començar @@ -23781,12 +22168,7 @@ Pots connectar-te a nodes ocults, encara que estiguis en un node estàndard, aix Atura - - BOB status - Estat del BOB - - - + Incoming Entrants @@ -23834,7 +22216,32 @@ Finalment assegurat que els ports coincideixen amb la configuració. Si tens problemes connectant-te sobre Tor comprova també els registres de Tor. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay Repetidor @@ -23889,7 +22296,7 @@ Si tens problemes connectant-te sobre Tor comprova també els registres de Tor.< Total: - + Warning: This bandwidth adds up to the max bandwidth. Avís: Aquest ample de banda es sumarà a l'ample de banda màxim. @@ -23914,7 +22321,7 @@ Si tens problemes connectant-te sobre Tor comprova també els registres de Tor.< Eliminar servidor - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -23928,7 +22335,7 @@ Si tens problemes connectant-te sobre Tor comprova també els registres de Tor.< Xarxa - + IP Filters Filtres IP @@ -23951,7 +22358,7 @@ Si tens problemes connectant-te sobre Tor comprova també els registres de Tor.< - + Status Estat @@ -24011,17 +22418,28 @@ Si tens problemes connectant-te sobre Tor comprova també els registres de Tor.< Afegir a la llista blanca - + Hidden Service Configuration Configuració dels serveis ocults - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p></p>Aquest és el port cap al repetidor Socks de Tor. El teu node de Retroshare pot utilitzar-lo per connectar a</p><p>nodes Ocults. El llum de la dreta es tornarà verd quan el port estigui actiu en el teu ordinador.</p><p>Això no significa que el transit del teu Retroshare vagi per Tor. Només ho farà si </p><p>connectes contra nodes Ocults o estàs corrent un node Ocult tu mateix.</body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>El llum de l'esquerra serà verd quan el port d'entrada estigui actiu en el teu ordinador. No indica</p><p>que el teu transit de Retroshare vagi per Tor. Només ho farà si</p><p>et connectes a nodes Ocults, o si estàs corrent un node ocult tu mateix.</p></body></html> @@ -24037,18 +22455,18 @@ Si tens problemes connectant-te sobre Tor comprova també els registres de Tor.< - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>El llum de l'esquerra serà verd quan el port d'entrada estigui actiu en el teu ordinador. No indica</p><p>que el teu transit de Retroshare vagi per I2P. Només ho farà si</p><p>et connectes a nodes Ocults, o si estàs corrent un node ocult tu mateix.</p></body></html> - + I2P outgoing Okay Sortints I2P correctes - + Service Address Adreça del servei @@ -24083,12 +22501,12 @@ Si tens problemes connectant-te sobre Tor comprova també els registres de Tor.< Si us plau, escriu una adreça de servei - + IP Range Rang IP - + Reported by DHT for IP masquerading Anunciat per DHT per enmascarament IP @@ -24111,12 +22529,12 @@ Si tens problemes connectant-te sobre Tor comprova també els registres de Tor.< Afegit per tu - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> <html><head/><body><p>Mentre que les IPs llistades s'obtenen de les fonts següents: IPs d'un certificat intercanviat manualment, rangs d'IPs introduïts per tu en aquesta finestra o en els elements de seguretat de novetats</p><p>El comportament per defecte del Retroshare és (1) sempre permetre connexions a contactes amb una IP a la llista blanca, encara que també apareguin a la llista negra; (2) opcionalment es pot forçar a que les IPs hagin d'estar a la llista blanca. Pots canviar aquest comportament per cada contacte a la finestra &quot;Detalls&quot; de cada node de Retroshare.</p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> <html><head/><body><p>La DHT et permet respondre les peticions de connexió dels teus amics utilitzant el protocol @@ -24124,12 +22542,12 @@ de connexió dels teus amics utilitzant el protocol </p><p>El servei de descobriment envia els noms dels nodes i les identitats dels teus contactes de confiança als nodes contactats, per ajudar a que escullin amics nous. No obstant, l'amistat mai és automàtica i els dos contactes encara haurien de confiar entre ells per permetre la connexió. - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> <html><head/><body><p>L'indicador es torna verd quan el Retroshare aconsegueix obtindre la teva pròpia IP d'una de les webs llistades, si ho tens activat. El Retroshare intentarà també utilitzar altres mètodes per obtenir la teva IP. - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> <html><head/><body><p>Aquesta llista s'omple automàticament amb informació recopilada des de múltiples fonts: contactes que fan masquerading anunciats per DHT, rangs d'IP entrats per tu, i rangs d'IP anunciats pels teus amics. La configuració per defecte hauria de protegir-te contra repetidors de tràfic massius.</p><p>Detectar automàticament IPs que fan masquerading pot acabar posant IPs amigues a la llista negra. En tal cas, utilitza el menú contextual per afegir-los a la llista blanca.</p></body></html> @@ -24164,26 +22582,22 @@ de connexió dels teus amics utilitzant el protocol Expulsa automàticament els rangs d'IP fent reenviament DHT començant a - + Outgoing Manual Tor/I2P Tor/I2P sortint manual - - <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. <br/>If you prefer to use BOB to automatically manage I2P check the other tab.</p></body></html> - <html><head/><body><p>Configura el teu proxy SOCKS per Tor i I2P aquí.<br/>Si prefereixes utilitzar BOB per controlar automàticament l'I2P comprova l'altra pestanya.</p></body></html> - Tor Socks Proxy Repetidor socks TOR - + Tor outgoing Okay Sortints Tor correcte - + Tor proxy is not enabled El repetidor Tor no està activat @@ -24263,7 +22677,7 @@ de connexió dels teus amics utilitzant el protocol ShareKey - + check peers you would like to share private publish key with comprovar els contactes amb qui t'agradaria compartir les claus de publicació @@ -24273,12 +22687,12 @@ de connexió dels teus amics utilitzant el protocol Compartit amb els amics - + Share Compartir - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. Pots fer que els teus amics sàpiguen del teu canal compartint-lo amb ells. @@ -24299,7 +22713,7 @@ Escull els amics amb qui vols compartir el teu canal. Directori de directoris compartits - + Shared directory Directori compartit @@ -24319,17 +22733,17 @@ Escull els amics amb qui vols compartir el teu canal. Visibilitat - + Add new Afegir nou - + Cancel Cancel·la - + Add a Share Directory Afegeix un directori compartit @@ -24339,7 +22753,7 @@ Escull els amics amb qui vols compartir el teu canal. Treure - + Apply and close Aplicar i tancar @@ -24430,7 +22844,7 @@ Escull els amics amb qui vols compartir el teu canal. Directori no trobat o nom del directori no acceptat. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. Aquesta és una llista dels directoris compartits. Pots afegir-ne i treure'n utilitzant els botons a la part inferior. Quan afegeixes un nou directori inicialment tots els seus arxius es comparteixen. Pots especificar permisos específics per cada directori. @@ -24438,7 +22852,7 @@ Escull els amics amb qui vols compartir el teu canal. SharedFilesDialog - + Files Arxius @@ -24489,11 +22903,16 @@ Escull els amics amb qui vols compartir el teu canal. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files comprovar arxius - + Download selected Descarregar seleccionats @@ -24503,7 +22922,7 @@ Escull els amics amb qui vols compartir el teu canal. Descarregar - + Copy retroshare Links to Clipboard Copiar enllaç RetroShare al porta-retalls @@ -24518,7 +22937,7 @@ Escull els amics amb qui vols compartir el teu canal. Enviar enllaç RetroShare - + Some files have been omitted Alguns arxius s'han omès @@ -24534,7 +22953,7 @@ Escull els amics amb qui vols compartir el teu canal. Consell(s) - + Create Collection... Crear col·lecció... @@ -24559,7 +22978,7 @@ Escull els amics amb qui vols compartir el teu canal. Descarregar d'arxiu de col·lecció... - + Some files have been omitted because they have not been indexed yet. Alguns arxius s'han omès perquè encara no han estat indexats. @@ -24702,12 +23121,12 @@ Escull els amics amb qui vols compartir el teu canal. SplashScreen - + Load configuration Carrega configuració - + Create interface Crear interfície @@ -24731,7 +23150,7 @@ Escull els amics amb qui vols compartir el teu canal. Recordar contrasenya - + Log In Validar-se @@ -25088,7 +23507,7 @@ Això es pot canviar a les opcions de configuració. Missatge d'estat - + Message: Missatge: @@ -25333,7 +23752,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags Eliminar totes les etiquetes @@ -25369,12 +23788,15 @@ p, li { white-space: pre-wrap; } Configura Tor... - + + Tor status: Estat Tor: - + + + Unknown Desconegut @@ -25384,18 +23806,13 @@ p, li { white-space: pre-wrap; } No iniciat - - Hidden service address: - Adreça del servei ocult: + + Hidden address: + - - Tor bootstrap status: - Estat bootstrap de Tor: - - - - + + Not set No configurat @@ -25405,12 +23822,57 @@ p, li { white-space: pre-wrap; } Adreça Onion: - + + Error + Error + + + + Not connected + No connectat + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path Comprova que Tor és accessible a les rutes d'executables - + [Waiting for Tor...] [Esperant al Tor...] @@ -25418,21 +23880,17 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor Tor - - <p>This version of Retroshare uses Tor to connect to your friends.</p> - <p>Aquesta versió de Retroshare utilitza Tor per connectar amb els teus amics.</p> - <p>This version of Retroshare uses Tor to connect to your trusted nodes.</p> - + Tor is currently offline Tor és fora de línia @@ -25443,11 +23901,12 @@ p, li { white-space: pre-wrap; } + No tor configuration Sense configuració Tor - + Tor proxy is OK @@ -25475,7 +23934,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options Opcions de transferència @@ -25486,7 +23945,7 @@ p, li { white-space: pre-wrap; } Màxim de descarregues simultànies: - + Shared Directories Directoris compartits @@ -25496,22 +23955,27 @@ p, li { white-space: pre-wrap; } Compartir automàticament directori entrant (recomanat) - - Edit Share - Editar compartits - - - + Directories - + + Configure shared directories + Configura els directoris compartits + + + Auto-check shared directories every Auto-comprova els directoris compartits cada + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) minut(s) @@ -25596,7 +24060,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -25605,7 +24069,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) Màxim de pujades simultànies per amic (0 = il·limitades) @@ -25630,7 +24099,12 @@ p, li { white-space: pre-wrap; } Permetre descarregues directes: - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming En flux @@ -25689,38 +24163,13 @@ p, li { white-space: pre-wrap; } Trust friend nodes with banned files - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Retroshare</span><span style=" font-size:8pt;"> és capaç de transferir dades i peticions de cerca entre contactes que no necessàriament siguin amics. No obstant, aquest tràfic només passa entre els amics connectats i és anònima.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Pots especificar per separat els permisos de compartició per cada directori compartit a la finestra d'arxius compartits:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Navegables pels amics:</span>: Els arxius són vistos pels teus amics.</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Compartits anònimament</span>: Els arxius es poden descarregar a través de túnels anònims distants.</li></ul></body></html> - Max. tunnel req. forwarded per second: Màxim de peticions de túnels reenviades per segon: - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - <html><head/><body><p><span style=" font-weight:600;">En flux</span>fa que la transferència es faci en fragments de 1 MiB per ordre, facilitant la previsualització mentre es descarrega. <span style=" font-weight:600;">Aleatori</span>és completament aleatori i afavoreix el comportament en eixam. <span style=" font-weight:600;">Progressiu</span>és un compromís, sol·licitant el proper fragment aleatòriament dins dels propers 50 MiB següents al final de l'arxiu parcial. Això permet aleatorietat i a la vegada evita temps llargs d'inicialització amb els arxius grossos.</p></body></html> - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> <html><head/><body><p>El Retroshare pausarà totes les transferències i gravacions de configuració al disc si l'espai lliure queda per sota d'aquest llindar. Això evita la pèrdua d'informació en alguns sistemes. Una finestra de notificació t'avisarà quan això passi.</p></body></html> @@ -25732,7 +24181,17 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú </p><p>El valor per defecte és 20. Si no n'estàs segur, deixa-ho així.</p></body></html> - + + Warning + Avís + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory Establir el directori d'entrants @@ -25760,7 +24219,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú TransferUserNotify - + Download completed Descarrega completa @@ -25784,39 +24243,23 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú %1 completed transfer - - You have %1 completed downloads - Tens %1 descarregues completes - - - You have %1 completed download - Tens %1 descarrega completa - - - %1 completed downloads - %1 descarregues completades - - - %1 completed download - %1 descarrega completada - TransfersDialog - - + + Downloads Descarregues - + Uploads Pujades - + Name i.e: file name Nom @@ -26023,11 +24466,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Especificar... - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1> <p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p> <p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p> <p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - <h1><img width="32" src=":/images/help_64.png">&nbsp;&nbsp;Transferència d'arxiu</h1> <p>Retroshare contempla dues formes de fer això: transferències directes dels teus amics, i transferències distants amb túnels anònims. A més amés, les transferències d'arxius són multi-origen i permet fer-les en eixam (pots ser origen mentre descarregues)</p> <p>Pots compartir arxius amb <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> la icona de la barra lateral esquerra. Aquests arxius es llistaran a la pestanya els meus arxius. Pots triar per cada grup d'amics si poden o no veure'l a la pestanya arxius d'amics.</p> <p>La pestanya cerca dona resultats pels arxius del teus amics i arxius que es poden accedir distants anònimament utilitzant el sistema de túnels multi-salt.</p> - - - + Move in Queue... Moure a la cua... @@ -26052,7 +24491,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Escull directori - + Anonymous end-to-end encrypted tunnel 0x Túnel anònim encriptat d'extrem a extrem 0x @@ -26073,7 +24512,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú RetroShare - + @@ -26106,7 +24545,17 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú L'arxiu %1 no s'ha completat. Si es un fitxer multimèdia intenta una prèvia. - + + Warning + Avís + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name Canviar el nom de l'arxiu @@ -26121,7 +24570,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Si us plau, introdueix un nou--i vàlid--nom d'arxiu - + Expand all Expandeix tot @@ -26248,23 +24697,18 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Columnes - + File Transfers Transferències d'arxius - + Path Ruta @@ -26274,7 +24718,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Mostra columna de ruta - + Could not delete preview file No s'ha pogut esborrar l'arxiu de previsualització @@ -26284,7 +24728,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Tornar-ho a intentar? - + Create Collection... Crear col·lecció... @@ -26299,7 +24743,12 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Veure col·lecció... - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Collection Col·lecció @@ -26309,7 +24758,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú %1 túnels - + Anonymous tunnel 0x Túnel anònim 0x @@ -26530,10 +24979,6 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú File transfer tunnels - - Anonymous tunnels - Túnels anònims - Authenticated tunnels @@ -26727,12 +25172,17 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Formulari - + Enable Retroshare WEB Interface Habilita la interfície WEB del RetroShare - + + Status: + Estat: + + + Web parameters Paràmetres web @@ -26766,35 +25216,33 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú <html><head/><body><p>Note: these settings do not affect retroshare-service, which has a command line switch to activate the web interface and select the listening port.</p></body></html> - - Port: - Port: - Allow access from all IP addresses (Default: localhost only) Permetre accés des de qualsevol adreça IP (Per defecte: només connexió local) - Apply setting and start browser - Aplicar opcions i iniciar navegador - - - Note: these settings do not affect retroshare-nogui. Retroshare-nogui has a command line switch to activate the web interface. - Nota: Aquestes opcions no afecten al Retroshare-nogui. Retroshare-nogui té un paràmetre en línia de comanda per activar la interfície web. - - - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Interfície web</h1> <p>La interfície web et permet controlar el Retroshare des del navegador. Múltiples dispositius poden compartir el control sobre una instancia de Retroshare. Per tan pots començar una conversa en una tauleta i més tard utilitzar un ordinador d'escriptori per continuar-la.</p><p>Avís: no exposis la teva interfície web a Internet, perquè no hi ha control d'accés ni encriptació. Si vols utilitzar la interfície web des d'Internet utilitza un túnel SSH o un repetidor per assegurar la connexió.</p> - + Webinterface not enabled Interfície Web no habilitada @@ -26804,12 +25252,12 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú La interfície web no està activada. Activa-la a Configuració -> Interfície web. - + failed to start Webinterface Fallo al iniciar interfície Web - + Webinterface Interfície Web @@ -26946,11 +25394,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Pàgines wiki - New Group - Nou grup - - - + Page Name Nom de pàgina @@ -26965,7 +25409,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Id d'origen - + << << @@ -27053,7 +25497,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú WikiEditDialog - + Page Edit History Historial d'edició de la pàgina @@ -27088,7 +25532,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú IdPàgina - + \/ \/ @@ -27118,14 +25562,18 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Etiquetes - - + + History + Històric + + + Show Edit History Mostra historial d'edició - + Status Estat @@ -27146,7 +25594,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Desfés - + Submit Publica @@ -27218,10 +25666,6 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú WireDialog - - TimeRange - Rang de temps - Create Account @@ -27233,16 +25677,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú - ... - ... - - - - Refresh - Refrescar - - - + Settings @@ -27257,7 +25692,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Altres - + Who to Follow @@ -27277,7 +25712,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú - + Most Recent @@ -27307,85 +25742,17 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú - Last Month - L'últim mes - - - Last Week - L'ultima setmana - - - Today - Avui - - - New - Nou - - - from - des de - - - until - fins - - - Search/Filter - Cercar/Filtrar - - - Network Wide - Tota la xarxa - - - Manage Accounts - Controlar comptes - - - Showing: - Mostrant: - - - + Yourself Tu mateix - - Friends - Amics - Following Seguint - Custom - Personalitzat - - - Account 1 - Compte 1 - - - Account 2 - Compte 2 - - - Account 3 - Compte 3 - - - CheckBox - Casella de selecció - - - Post Pulse to Wire - Publica Pols a Wire - - - + RetroShare RetroShare @@ -27448,35 +25815,42 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Formulari - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + Treure + + + Location: Ubicació: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -27521,11 +25895,41 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Edit Profile + + + Own + + + + + N/A + N/A + + + + Following + Seguint + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Desconegut @@ -27603,7 +26007,7 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú %1y any %2d - + k e.g: 3.1 k k @@ -27636,15 +26040,11 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif *.webp) - - Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - Imatges (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - pgpid_item_model - + Do you accept connections signed by this profile? Acceptes connexions signades amb aquest perfil? @@ -27653,10 +26053,6 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Name of the profile Nom del perfil - - This column indicates trust level and whether you signed the profile PGP key - Aquesta columna indica el nivell de confiança i si has signat la clau de perfil PGP - This column indicates the trust level you indicated and whether you signed the profile PGP key @@ -27767,10 +26163,6 @@ Si tens molt ample de banda pots augmentar-lo fins a 30-40, per permetre que tú Denied - - - - - - PGP key signed by you diff --git a/retroshare-gui/src/lang/retroshare_cs.ts b/retroshare-gui/src/lang/retroshare_cs.ts index 24f243cde..9ddff2a55 100644 --- a/retroshare-gui/src/lang/retroshare_cs.ts +++ b/retroshare-gui/src/lang/retroshare_cs.ts @@ -84,13 +84,6 @@ - - AddCommentDialog - - Add Comment - Přidat komentář - - AddFileAssociationDialog @@ -129,12 +122,12 @@ RetroShare: rozšířené hledání - + Search Criteria Kritéria pro vyhledávání - + Add a further search criterion. Přidat další kriterium pro vyhledávání @@ -144,7 +137,7 @@ Vymazat kritéria pro vyhledávání - + Cancels the search. Zrušit hledání. @@ -164,177 +157,6 @@ Hledat - - AlbumCreateDialog - - Create Album - Vytvořit album - - - Album Name: - Jméno alba: - - - Category: - Kategorie: - - - Animals - Zvířata - - - Family - Rodina - - - Friends - Kontakty - - - Flowers - Květiny - - - Holiday - Prázdniny - - - Landscapes - Krajiny - - - Pets - Domácí mazlíčci - - - Portraits - Portréty - - - Travel - Cestování - - - Work - Práce - - - Random - Náhodné - - - Caption: - Nadpis: - - - Where: - Kde: - - - Photographer: - Fotograf: - - - Description: - Popis: - - - Share Options - Sdílet nastavení - - - Policy: - Pravidla - - - Quality: - Kvalita: - - - Comments: - Komentáře: - - - Identity: - Identita: - - - Public - Veřejné - - - Restricted - Omezené - - - Resize Images (< 1Mb) - Zmenšit obrázky (< 1Mb) - - - Resize Images (< 10Mb) - Zmenšit obrázky (< 10Mb) - - - Send Original Images - Poslat původní obrázky - - - No Comments Allowed - Zakázat komentáře - - - Authenticated Comments - Pouze autentizované komentáře - - - Any Comments Allowed - Kdokoliv může komentovat - - - Publish with Identity - Publikovat pod identitou - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Táhni &amp; Pusť pro vložení obrázku. Klikni na obrázek pro změnu detailů.</span></p></body></html> - - - Back - Zpět - - - Add Photos - Přidat fotografie - - - Publish Album - Publikovat album - - - Untitle Album - Bezejmenné album - - - Say something about this album... - Ohodnotit toto album... - - - Where were these taken? - Kde byly vyfoceny? - - - Load Album Thumbnail - Nahrád náhled alba - - AlbumDialog @@ -343,19 +165,11 @@ p, li { white-space: pre-wrap; } Album Album - - Album Thumbnail - Náhled alba - TextLabel Textový popisek - - Summary - Shrnutí - Album Title: @@ -371,34 +185,6 @@ p, li { white-space: pre-wrap; } Caption legenda - - Where: - Kde: - - - When - Kdy - - - Description: - Popis: - - - Share Options - Možnsti sdílení - - - Comments - Komentáře - - - Publish Identity - Zveřejnit identitu - - - Visibility - Viditelnost - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -767,7 +553,7 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. Varování: Zdejší služby jsou testovací, pomožte nám je otestovat. @@ -783,14 +569,6 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo Circles Okruhy lidí - - GxsForums - Fóra - - - GxsChannels - Kanály - The Wire @@ -802,10 +580,23 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo Fotografie + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb %p Kb @@ -842,17 +633,13 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo Browse... - - Add Avatar - Přidat fotku - Remove Odebrat - + Set your Avatar picture Zobrazit fotku @@ -871,10 +658,6 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - Načíst fotku - AvatarWidget @@ -943,22 +726,10 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo Reset - Receive Rate - Rychlost stahování - - - Send Rate - Rychlost odesílání - - - + Always on Top Podržet nad ostatními - - Style - Styl - Changes the transparency of the Bandwidth Graph @@ -974,23 +745,11 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo % Opaque % Opaque - - Save - Uložit - - - Cancel - Zrušit - Since: Od: - - Hide Settings - Skrýt nastavení - BandwidthStatsWidget @@ -1063,7 +822,7 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo BoardPostDisplayWidgetBase - + Comment Komentáře @@ -1093,12 +852,12 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo Kopírovat RetroShare odkaz - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -1106,7 +865,7 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo BoardPostDisplayWidget_card - + Vote up @@ -1126,7 +885,7 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo - + Posted by @@ -1164,7 +923,7 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo BoardPostDisplayWidget_compact - + Vote up @@ -1184,7 +943,7 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo - + Click to view picture @@ -1214,7 +973,7 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo - + Toggle Message Read Status Označit zprávu za přečtenou @@ -1224,7 +983,7 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo Nový - + TextLabel Textový popisek @@ -1232,12 +991,12 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo BoardsCommentsItem - + I like this - + 0 0 @@ -1257,18 +1016,18 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo Avatar - + New Comment - + Copy RetroShare Link Kopírovat RetroShare odkaz - + Expand Rozbalit @@ -1283,12 +1042,12 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo - + Name - + Comm value @@ -1457,17 +1216,17 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo ChannelPage - + Channels Kanály - + Tabs Záložky - + General Obecné @@ -1477,11 +1236,17 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo - Load posts in background (Thread) - Načítat příspěvky na pozadí + + Downloads + Stahování - + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab Otevřít nový kanál v nové záložce @@ -1489,7 +1254,7 @@ Ale měj na paměti, že veškerá zdejší nastavení se mohou změnit s každo ChannelPostDelegate - + files @@ -1512,7 +1277,7 @@ into the image, so as to ChannelsCommentsItem - + I like this @@ -1537,18 +1302,18 @@ into the image, so as to Avatar - + New Comment - + Copy RetroShare Link Kopírovat RetroShare odkaz - + Expand Rozbalit @@ -1563,7 +1328,7 @@ into the image, so as to - + Name @@ -1573,17 +1338,7 @@ into the image, so as to - - Comment - Komentáře - - - - Comments - - - - + Hide Skrýt @@ -1591,7 +1346,7 @@ into the image, so as to ChatLobbyDialog - + Name @@ -1782,7 +1537,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby Ukázat konverzační místnost @@ -1794,22 +1549,6 @@ into the image, so as to Chats - - You have %1 new messages - Máte %1 nových zpráv - - - You have %1 new message - Máte %1 novou zprávu - - - %1 new messages - %1 nových zpráv - - - %1 new message - %1 nová zpráva - You have %1 mentions @@ -1831,13 +1570,14 @@ into the image, so as to - + + Unknown Lobby Neznámá místnost - - + + Remove All Smazat vše @@ -1845,13 +1585,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Jméno - + Count Počet @@ -1861,29 +1601,7 @@ into the image, so as to Téma - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - - - - - - Public chat rooms - - - - + Create chat room @@ -1893,7 +1611,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1950,12 +1668,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1965,31 +1683,31 @@ Double click a chat room to enter and chat. - Create chat lobby - Vytvořit konverzační místnost - - - + [No topic provided] [nebylo poskytnuto žádné téma] - Selected lobby info - Informace o místnosti - - - + + Private Soukromé - + + + Public Veřejné - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted Anonymní ID přijato @@ -1999,42 +1717,25 @@ Double click a chat room to enter and chat. Odstranit automatické přihlašování - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe Automaticky přihlásit - + Search Chat lobbies Hledat místnost - + Search Name Hledat - Subscribed - Přihlášen - - - + Columns Sloupce - - Yes - Ano - - - No - Ne - Chat rooms @@ -2046,47 +1747,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: Téma: - + Type: Typ: - + Security: Bezpečnost: - + Peers: Počet uživatelů: - - - - - - + + + + + + TextLabel Textový popisek @@ -2101,13 +1802,24 @@ Double click a chat room to enter and chat. Bez anonymních ID - + Show Ukázat - + + Private Subscribed + + + + + + Public Subscribed + + + + column sloupec @@ -2121,7 +1833,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item Odstranit předmět @@ -2166,46 +1878,22 @@ Double click a chat room to enter and chat. ChatPage - + General Obecné - - Distant Chat - Vzdálený chat - Everyone Všichni - - Contacts - Kontakty - Nobody Nikdo - Accept encrypted distant chat from - Přijmout šifrovaný vzdálený chat od - - - Chat Settings - Nastavení chatu - - - Enable Emoticons Private Chat - Povolit smajlíky v soukromém chatu - - - Enable Emoticons Group Chat - Používat smajlíky ve skupinovém chatu - - - + Enable custom fonts Povolit vlastní fonty @@ -2214,10 +1902,6 @@ Double click a chat room to enter and chat. Enable custom font size Povolit vlastní velikost fontů - - Minimum font size - Minimální velikost fontu - Enable bold @@ -2229,7 +1913,7 @@ Double click a chat room to enter and chat. Povolit latinku - + General settings @@ -2254,11 +1938,7 @@ Double click a chat room to enter and chat. Načíst vložené obrázky - Chat Lobby - Konverzace - - - + Blink tab icon Ikona upozornění @@ -2267,10 +1947,6 @@ Double click a chat room to enter and chat. Do not send typing notifications - - Private Chat - Soukromý chat - Open Window for new chat @@ -2292,11 +1968,7 @@ Double click a chat room to enter and chat. - Chat Font - Font chatu - - - + Change Chat Font Změnit font chatu @@ -2306,14 +1978,10 @@ Double click a chat room to enter and chat. Font chatu: - + History Historie - - Style - Styl - @@ -2328,17 +1996,13 @@ Double click a chat room to enter and chat. Variant: - - Group chat - Skupinový chat - Private chat Soukromý chat - + Choose your default font for Chat. @@ -2402,22 +2066,28 @@ Double click a chat room to enter and chat. <html><head/><body><p align="justify">In this tab you can setup how many chat messages Retroshare will keep saved on the disc and how much of the previous conversation it will display, for the different chat systems. The max storage period allows to discard old messages and prevents the chat history from filling up with volatile chat (e.g. chat lobbies and distant chat).</p></body></html> <html><head/><body><p align="justify">Zde se nastavuje uchovávání historie na vašem HDD pro různé druhy chatu. Zprávy staršího data budou smazány, aby nedošlo k přesycení sítě (např. pro konverzační místnosti a vzdálený chat).</p></body></html> - - Chatlobbies - Konverzační místnosti - Enabled: Aktivováno: - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2427,7 +2097,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2524,11 +2204,7 @@ Double click a chat room to enter and chat. Neukládat starší než...dní (0 = bez omezení) - Search by default - Defaultní hledání - - - + Case sensitive Citlivost velikost písmen @@ -2567,10 +2243,6 @@ Double click a chat room to enter and chat. Threshold for automatic search Práh automatického vyhledávání - - Default identity for chat lobbies: - Výchozí identita pro konverzační místnost: - Show Bar by default @@ -2638,7 +2310,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat Zobrazit chat @@ -2674,7 +2346,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close Zavřít @@ -2709,12 +2381,12 @@ Double click a chat room to enter and chat. Kurzíva - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2794,11 +2466,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2836,7 +2503,7 @@ Double click a chat room to enter and chat. - + is typing... píše... @@ -2858,7 +2525,7 @@ after HTML conversion. - + Do you really want to physically delete the history? Chcete opravdu vymazati historii z počítače? @@ -2908,7 +2575,7 @@ after HTML conversion. je zaneprázdněn a může se stát, že neodpoví - + Find Case Sensitively Hledat s rozlišením malých a velkých písmen @@ -2930,7 +2597,7 @@ after HTML conversion. Nezastavovat vybarvování po X nálezech (vyšší zátěž CPU) - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> <b>Hledat předchozí </b><br/><i>Ctrl+Shift+G</i> @@ -2945,16 +2612,12 @@ after HTML conversion. <b>Hledat </b><br/><i>Ctrl+F</i> - + (Status) (Status) - Set text font & color - Nastav typ a barvu písma - - - + Attach a File Přiožit soubor @@ -2970,12 +2633,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> <b>Označ vybraný text</b><br><i>Ctrl+M</i> - + Person id: @@ -2986,12 +2649,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. Nalezeno. @@ -3011,7 +2674,7 @@ Double click on it to add his name on text writer. Zde napiš zprávu... - + Don't stop to color after Nezastavovat vybarvování po @@ -3037,7 +2700,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: Ukazuji detaily: @@ -3059,7 +2722,7 @@ Double click on it to add his name on text writer. - + Personal Circles Osobní Kruhy @@ -3085,7 +2748,7 @@ Double click on it to add his name on text writer. - + Friends Kontakty @@ -3145,7 +2808,7 @@ Double click on it to add his name on text writer. Kontakty kontaktů - + External Circles (Admin) Externí Kruhy (Admin) @@ -3161,7 +2824,7 @@ Double click on it to add his name on text writer. - + Circles Okruhy lidí @@ -3213,43 +2876,48 @@ Double click on it to add his name on text writer. - + RetroShare RetroShare - + - + Error : cannot get peer details. Chyba : nemohu získat údaje kontaktu - + Retroshare ID - + <p>This Retroshare ID contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: + + + <b>DNS:</b> : + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3261,7 +2929,7 @@ Double click on it to add his name on text writer. Šifrování - + Not connected Nespojen @@ -3343,25 +3011,17 @@ Double click on it to add his name on text writer. žádný - + <p>This certificate contains: <p>Tento certifikát obsahuje - + <li>a <b>node ID</b> and <b>name</b> <li>a <b>ID uzlu</b> a <b>jméno</b> - an <b>onion address</b> and <b>port</b> - <b>onion (TOR) adresa</b> a <b>port</b> - - - an <b>IP address</b> and <b>port</b> - an <b>IP adresa</b> a <b>port</b> - - - + <p>You can use this certificate to make new friends. Send it by email, or give it hand to hand.</p> <p>Tento certifikát musíš předat svým budoucím kontaktům. Použij emailu nebo jiné komunikační platformy.</p> @@ -3376,7 +3036,7 @@ Double click on it to add his name on text writer. <html><head/><body><p>Šifrovcí metoda použitá <span style=" font-weight:600;">OpenSSL</span>. Spojení s kontakty</p><p>je vždy silně šifrováno a pokud je použito DHE, spojení navíc využívá</p><p>&quot;zabezpečené přeposílání&quot;.</p></body></html> - + with s @@ -3393,104 +3053,16 @@ Double click on it to add his name on text writer. Connect Friend Wizard Průvodce přidáním kontaktu - - Add a new Friend - Přidat kontakt - - - &You get a certificate file from your friend - &Nahrát soubor s certifikátem kontaktu (který vám například přišel emailem s pozvánkou). - - - &Make friend with selected friends of my friends - Přidat vybrané důvěryhodné kontakty mých důveryhodných kontaktů - - - Include signatures - Zahrnout podpisy - - - Copy your Cert to Clipboard - Kopírovat váš certifikát do schránky - - - Save your Cert into a File - Uložit váš certifikát do souboru - - - Run Email program - Spustit emailový klient - Open Cert of your friend from File - - Certificate files - Soubory certifikátu - - - Use PGP certificates saved in files. - Nahrát PGP certifikáty ze souboru. - - - Import friend's certificate... - Importovat certifikát kontaktu... - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - Musíte vygenerovat soubor s certifikátem a předat jej vašemu kontaktu. Můžete také použít již existující dříve vytvořený soubor. - - - Export my certificate... - Exportovat můj certifikát... - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - Přetáhněte certifikát kontaktu do tohoto okna a nebo zadejte cestu k tomu souboru do pole níže - - - Browse - Procházet - - - Friends of friends - Kontakty kontaktů - - - Select now who you want to make friends with. - Vyberte koho chcete přidat mezi své kontakty. - - - Show me: - Ukaž mi: - - - Make friend with these peers - Přidat tyto protějšky do kontaktů - RetroShare ID RetroShare ID - - Use RetroShare ID for adding a Friend which is available in your network. - Použít RetroShareID k přidání kontaktu dostupného ve vaší síti. - - - Add Friends RetroShare ID... - Přidat kontakty RetroShare ID... - - - Paste Friends RetroShare ID in the box below - Vložte RetroShare ID vašich kontaktů do textového pole níže - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - Zadejte RetroShare ID vašeho kontaktu, např. Franta@BDE8D16A46D938CF - RetroShare is better with Friends @@ -3532,27 +3104,7 @@ Double click on it to add his name on text writer. Email - Invite Friends by Email - Pozvěte kontakty emailem - - - Enter your friends' email addresses (separate each one with a semicolon) - Zadejte emailové adresy vašich kontaktů oddělené středníkem. - - - Your friends' email addresses: - Emailové adresy vašich kontaktů: - - - Enter Friends Email addresses - Vložte emailové adresy vašich kontaktů - - - Subject: - Předmět: - - - + @@ -3568,40 +3120,32 @@ Double click on it to add his name on text writer. Podrobnosti požadavku - + Peer details Podrobnosti o kontaktu - + Name: Jméno: - - Email: - Email: - - - Node: - Uzel: - Location: Umístění: - + Options Možnosti - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: Přidat do skupiny: @@ -3611,7 +3155,7 @@ Double click on it to add his name on text writer. Autentizovat kontakt (podepsat PGP klíč), potvrzuje vaši plnou důvěru,nelze vzít zpět! - + Please paste below your friend's Retroshare ID @@ -3636,16 +3180,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with Přidat jako kontakt pro přímé spojení - To accept the Friend Request, click the Finish button. - Klikni na "Finish" pro přidání kontaktu - - - + Sorry, some error appeared Je to smutné, ale došlo k nějaké chybě @@ -3665,32 +3215,27 @@ Double click on it to add his name on text writer. Detaily vašeho kontaktu: - + Key validity: Validita klíče: - + Profile ID: - - Signers - Podepsali - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. Tento protějšek se již nachází ve vašem seznamu kontaktů. Jeho opětovné přidání může nanejvýš nastavit jeho novou IP adresu. - + To accept the Friend Request, click the Accept button. @@ -3736,45 +3281,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed Načítání certifikátu selhalo - Cannot get peer details of PGP key %1 - Nelze získat podrobnost o PGP klíči %1 - - - Any peer I've not signed - Nepodepsané kontakty - - - Friends of my friends who already trust me - Kontakty kontaktů které mi již důvěřují - - - Signed peers showing as denied - Podepsané protějšky zobrazené jako odmítnuté - - - Peer name - Jméno protějšku - - - Also signed by - Podepsán také (kým): - - - Peer id - ID protějšku - - - + Not a valid Retroshare certificate! - + RetroShare Invitation Pozvánka do RetroShare - sociální P2P sítě zaměřené především na sdílení souborů. @@ -3794,12 +3311,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3807,7 +3324,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3847,7 +3364,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Žádost o přidání do kontaktu od: - + Profile password needed. @@ -3872,7 +3389,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3882,55 +3399,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - Certificate Load Failed:file %1 not found - Načtení certifikátu selhalo: soubor %1 nebyl nalezen - - - This Peer %1 is not available in your Network - Protějšek %1 není ve vaší síti dostupný. - - - Use new certificate format (safer, more robust) - Nyní je používán starý (zpětně kompatibilní) formát certifikátu (kliknutím přepnete na nový). - - - Use old (backward compatible) certificate format - Nyní je používán nový formát certifikátu (bezpečnější a odolnější). - - - Remove signatures - Odstranit podpisy - - - RetroShare Invite - Pozvánka do RetroShare - - - Connect Friend Help - Informace - - - You can copy this text and send it to your friend via email or some other way - V horní části okna průvodce se nachází váš PGP certifikát, který musíte nějakým způsobem poslat vašemu kontaktu, například pomocí emailu, skypu, facebooku, výměnou na fóru nebo jakkoliv jinak, můžete použít cokoliv čím si posíláte textové zprávy. Váš kontakt vám rovněž musí zaslat svůj certifikát, takže si je vlastně vyměníte. Vy zkopírujete a vložíte jeho certifikát do textového pole v dolní části obrazovky průvodce, a on udělá to samé s váším certifikátem. Pokud vše funguje jak má, mělo by se vám podařit navázat přímé spojení. - -O vašem PGP certifikátu: Váš PGP který obsahuje jedinečný veřejný klíč vaší identity, a ve spodní části také vaší lokální a veřejnou IP adresu a umístění. Kontaktu jemuž tento certifikát pošlete byste proto měli alespoň elementárně důvěřovat. Podle účelu použití tohoto programu se může jednat o členy vaší rodiny, přátele či obchodní kontakty, ale také třeba lidi z druhého konce světa, o kterých jediné co s jistotou víte je, že sdílíte společné zájmy. - -Spojení: Abyste se mohli spojit, musí alespoň jeden z vás mít veřejnou IP adresu, případně musíte být napojeni na někoho kdo ji má a poslouží jako prostředník (tzv. proxy) pro přeposílání zpráv, souborů a ostatních typů dat. - -Program RetroShare vám umožňuje vytvořit si vlastní sociální síť, která vám zajistí lepší soukromí, protože vaše data nejsou ukládána v počítačích velkých firem, ale pouze u vás a vašich kontaktů. Protože si ji ale musíte vybudovat vy sami pěkně od píky, je dobré k získávání nových kontaktů využít existujících sociálních a komunikačních služeb které již užíváte. - -RetroShare neaspiruje na to být nejlepší sociální sítí, má své mouchy a problémy, ale jeho hlavní devizou je právě možnost vytvořit částečně anonymní P2P síť, v níž můžete relativně bezpečně sdílet soubory a diskutovat, při vhodné volbě přezdívky a kontaktů dokonce získáte i jistou míru anonymity. - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Váš certifikát byl zkopírován do schránky, vložte ho do zprávy kterou pošlete vašemu kontaktu emailem či jiným způsobem. - - - Save as... - Uložit jako... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3969,11 +3438,7 @@ RetroShare neaspiruje na to být nejlepší sociální sítí, má své mouchy a *** Nic *** - Use as direct source, when available - Stahovat přímo od pokud možno - - - + IP-Addr: @@ -3983,7 +3448,7 @@ RetroShare neaspiruje na to být nejlepší sociální sítí, má své mouchy a - + Show Advanced options @@ -4002,41 +3467,13 @@ RetroShare neaspiruje na to být nejlepší sociální sítí, má své mouchy a <html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> - - Recommend many friends to each others - Doporučit kontakty jiným kontaktům - - - Friend Recommendations - Doporučené kontakty - - - Message: - Zpráva: - - - Recommend friends - Doporučit kontakty - - - To - Pro - - - Please select at least one friend for recommendation. - Prosím zvol alespoň jeden kontakt pro doporučení - - - Please select at least one friend as recipient. - Prosím zvol alespoň jednoho příjemce - Add key to keyring Přidat klíč do klíčenky - + This key is already in your keyring Tento klíč je již v klíčence @@ -4052,7 +3489,7 @@ pro posílání např. zpráv uzlům, které nemáte přímo v kontaktech. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. Nesprávná verze certifikátu. RetroShare verze 0,6 a 0,5 jsou vzájemně nekompatibilní. @@ -4087,7 +3524,7 @@ které nemáte přímo v kontaktech. Přidat IP do whitelist - + No IP in this certificate! V certifikátu není IP adresa! @@ -4097,27 +3534,10 @@ které nemáte přímo v kontaktech. <p>V certifikátu není IP adresa. Discovery a DHT se ji pokusí najít. Po jejím nalezení se v Událostech objeví bezpečnostní upozornění, pomocí kterého můžete tuto adresu přidat do whitelist pro úspěšné spojení.</p> - - [Unknown] - - - - + Added with certificate from %1 Přidán s certifikátem od %1 - - Paste Cert of your friend from Clipboard - Vložit certifikát vašeho kontaktu ze schránky - - - Certificate Load Failed:can't read from file %1 - Načtení certifikátu selhalo: nemůžu přečíst soubor %1 - - - Certificate Load Failed:something is wrong with %1 - Načtení certifikátu selhalo: něco je špatně s %1 - ConnectProgressDialog @@ -4179,7 +3599,7 @@ které nemáte přímo v kontaktech. - + UDP Setup Zkouším UDP @@ -4207,7 +3627,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant Pokus o spojení - informace @@ -4217,17 +3637,20 @@ p, li { white-space: pre-wrap; } Neplatné ID kontaktu - + + Unknown State Neznámý stav - + + Offline Odpojen - + + Behind Symmetric NAT Za symetrickým NAT @@ -4237,12 +3660,14 @@ p, li { white-space: pre-wrap; } Za NAT & bez DHT - + + NET Restart NET Restart - + + Behind NAT Za NAT @@ -4252,7 +3677,8 @@ p, li { white-space: pre-wrap; } Bez DHT - + + NET STATE GOOD! STAV SÍTĚ V POŘÁDKU @@ -4277,7 +3703,7 @@ p, li { white-space: pre-wrap; } Hledám RS uzly - + Lookup requires DHT Vyžaduje zapnuté DHT @@ -4569,7 +3995,7 @@ p, li { white-space: pre-wrap; } Prosím zopakujte import kompletního certifikátu - + @@ -4577,7 +4003,8 @@ p, li { white-space: pre-wrap; } nedostupné - + + UNVERIFIABLE FORWARD! NEOVĚŘITELNÝ FORWARD! @@ -4587,7 +4014,7 @@ p, li { white-space: pre-wrap; } NEOVĚŘITELNÝ FORWARD & BEZ DHT! - + Searching Vyhledávám @@ -4623,12 +4050,12 @@ p, li { white-space: pre-wrap; } Detail Kruhu - + Name Jméno - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4648,7 +4075,7 @@ p, li { white-space: pre-wrap; } - + IDs ID @@ -4668,18 +4095,18 @@ p, li { white-space: pre-wrap; } Filtr - + Cancel Zrušit - + Nickname Přezdívka - + Invited Members @@ -4694,15 +4121,7 @@ p, li { white-space: pre-wrap; } - ID - ID - - - Type - Typ - - - + Name: Jméno: @@ -4742,19 +4161,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - + Please set a name for your Circle Nastavte prosím jméno vašeho Kruhu - + No Restriction Circle Selected Nevybráno žádné omezení Kruhu @@ -4764,12 +4183,24 @@ p, li { white-space: pre-wrap; } Nevybrány žádné limity Kruhu - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add Přidat @@ -4779,7 +4210,7 @@ p, li { white-space: pre-wrap; } Odstranit - + Search Hledat @@ -4794,10 +4225,6 @@ p, li { white-space: pre-wrap; } Signed Podepsáno - - Signed by known nodes - Podepsáno známými uzly - Edit Circle @@ -4814,10 +4241,6 @@ p, li { white-space: pre-wrap; } PGP Identity PGP identita - - Anon Id - Anonymní ID - Circle name @@ -4840,17 +4263,13 @@ p, li { white-space: pre-wrap; } - + Create Vytvořit - PGP Linked Id - PGP link ID - - - + Add Member @@ -4869,7 +4288,7 @@ p, li { white-space: pre-wrap; } Vytvořit skupinu - + Group Name: Jméno skupiny: @@ -4904,7 +4323,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post Přidat příspěvek @@ -4914,7 +4333,7 @@ p, li { white-space: pre-wrap; } Zpráva - + Post @@ -4975,23 +4394,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Přetáhni soubory zde nebo klikni na Přidat soubory.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Zkopíruj/Vlož RetroShare odkazy ze svých sdílení</span></p></body></html> - - Add File to Attach - Přiložit soubor - Add Channel Thumbnail Nastavit obrázek - - Message - Zpráva - - - Subject : - Předmět: - @@ -5077,17 +4484,17 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -5106,17 +4513,18 @@ p, li { white-space: pre-wrap; } The following files will only be shared for 30 days. Think about adding them to a shared directory. - - File already Added and Hashed - Soubor je již přidán a zatříděn - Please add a Subject Prosím zadejte předmět - + + Cannot publish post + + + + Load thumbnail picture Nahrát miniaturu @@ -5131,18 +4539,12 @@ p, li { white-space: pre-wrap; } Skrýt - - + Generate mass data Generovat hromadné údaje - - Do you really want to generate %1 messages ? - Opravdu chcete vygenerovat %1 zpráv? - - - + You are about to add files you're not actually sharing. Do you still want this to happen? Chcete přidat soubory, které však přímo nesdílíte. Opravdu? @@ -5176,7 +4578,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message Odeslat příspěvek na fórum @@ -5185,10 +4587,6 @@ p, li { white-space: pre-wrap; } Forum Fórum - - Subject - Předmět - Attach File @@ -5209,8 +4607,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -5229,7 +4627,7 @@ p, li { white-space: pre-wrap; } Přetáhnutím do tohoto okna můžete přiložit soubory - + Post @@ -5259,17 +4657,17 @@ p, li { white-space: pre-wrap; } - + No Forum Žádné fórum - + In Reply to Reakce na - + Title Nadpis @@ -5322,7 +4720,7 @@ Do you want to discard this message? Nahrát soubor s obrázkem - + No compatible ID for this forum @@ -5332,8 +4730,8 @@ Do you want to discard this message? - - + + Generate mass data Generovat hromadné údaje @@ -5342,10 +4740,6 @@ Do you want to discard this message? Do you really want to generate %1 messages ? Opravdu chcete vygenerovat %1 zpráv? - - Send - Odeslat - Post as @@ -5360,23 +4754,7 @@ Do you want to discard this message? CreateLobbyDialog - Create Chat Lobby - Vytvořit konverzační místnost - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - Konverzační místnosti jsou decentralizované a anonymní konverzační skupiny (chat). Všichni účastníci obdrží vždy všechny zprávy. Jakmile je skupina vytvořena, můžete pozvat další kontakty (v záložce Kontakty). - - - Lobby name: - Jméno místnosti: - - - Lobby topic: - Téma konverzace: - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5411,7 +4789,7 @@ Do you want to discard this message? - + Create Vytvořit @@ -5421,7 +4799,7 @@ Do you want to discard this message? Zrušit - + require PGP-signed identities @@ -5436,11 +4814,7 @@ Do you want to discard this message? Zvolte kontakty, s nimiž chcete uskutečnit skupinovou konverzaci - Invited friends - Pozvané kontakty - - - + Create Chat Room @@ -5461,7 +4835,7 @@ Do you want to discard this message? Kontakty: - + Identity to use: Použitá identita: @@ -5469,17 +4843,17 @@ Do you want to discard this message? CryptoPage - + Public Information Veřejné informace - + Name: Jméno: - + Location: Umístění: @@ -5489,12 +4863,12 @@ Do you want to discard this message? ID lokace: - + Software Version: Verze RetroShare : - + Online since: Připojen od: @@ -5514,12 +4888,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5529,7 +4898,7 @@ Do you want to discard this message? - + Other Information Další informace @@ -5539,17 +4908,12 @@ Do you want to discard this message? - + Profile - - Certificate - Certifikát - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5559,11 +4923,7 @@ Do you want to discard this message? Zahrnout podpisy - Save Key into a file - Uložit klíč do souboru - - - + Export Identity Exportovat identitu @@ -5637,33 +4997,33 @@ tam ji importujte. - + TextLabel Textový popisek - + PGP fingerprint: PGP otisk: - - Node information - Informace o uzlu - - - + PGP Id : PGP ID : - + Friend nodes: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5702,14 +5062,6 @@ tam ji importujte. Node Uzel - - Create new node... - Vytvořte nový uzel... - - - show statistics window - Zobrazit statistiky - DHTGraphSource @@ -5761,7 +5113,7 @@ tam ji importujte. DLListDelegate - + B B @@ -6429,7 +5781,7 @@ tam ji importujte. DownloadToaster - + Start file Spustit soubor @@ -6437,38 +5789,38 @@ tam ji importujte. ExprParamElement - + - + to pro - + ignore case ignorovat případy - - - dd.MM.yyyy - dd.MM.yyyy + + + yyyy-MM-dd + - - + + KB KB - - + + MB MB - - + + GB GB @@ -6476,12 +5828,12 @@ tam ji importujte. ExpressionWidget - + Expression Widget Výrazný Widget - + Delete this expression Odstranit tento výraz @@ -6643,7 +5995,7 @@ tam ji importujte. FilesDefs - + Picture Obrázek @@ -6653,7 +6005,7 @@ tam ji importujte. Video - + Audio Audio @@ -6713,11 +6065,21 @@ tam ji importujte. C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Sdílené soubory a složky mých kontaktů @@ -6839,7 +6201,7 @@ tam ji importujte. - + ID ID @@ -6881,7 +6243,7 @@ tam ji importujte. Zobrazit skupiny - + Group Skupina @@ -6917,7 +6279,7 @@ tam ji importujte. Přidat do skupiny - + Search @@ -6933,7 +6295,7 @@ tam ji importujte. - + Profile details @@ -7170,7 +6532,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request Potvrdit přidání kontaktu @@ -7187,10 +6549,6 @@ at least one peer was not added to a group FriendSelectionWidget - - Search : - Hledat : - Sort by state @@ -7212,7 +6570,7 @@ at least one peer was not added to a group Hledat kontakty - + Mark all Označit vše @@ -7223,16 +6581,132 @@ at least one peer was not added to a group + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + + + + + Node ID + + + + + Address + + + + + Status + Status + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + Přidat kontakt + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message Editovat status - - + + Broadcast Rozhlas @@ -7315,33 +6789,38 @@ at least one peer was not added to a group Nastavit výchozí font - + Keyring Klíčenka - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. RetroShare rozhlas: zpráva je odeslána všem připojeným kontaktům. - - + + Network Síť - + + Friend Server + + + + Network graph Síťový graf - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. Zde napiš svůj status. @@ -7359,7 +6838,17 @@ at least one peer was not added to a group Heslo - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters Všechny prvky vyžadují zadání alespoň tří znaků. @@ -7369,17 +6858,12 @@ at least one peer was not added to a group Hesla nejsou stejná - + Port Port - - Use BOB - - - - + This password is for PGP Heslo pro PGP @@ -7400,38 +6884,38 @@ at least one peer was not added to a group Nemůžu vygenerovat nový certifikát, možná jste špatně napsali PGP heslo! - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -7451,12 +6935,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -7466,42 +6950,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel Textový popisek - Advanced options - Pokročilé volby - - - + hidden address - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. Váš profil je spojen s PGP párem klíčů. V současné době RetroShare ignoruje DSA klíče. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> <html><head/><body><p>Port pro komunikaci.</p><p>Hodnota mezi 1024 a 65535 </p><p>by měla být OK. Můžete to změnit pak později.</p></body></html> @@ -7549,13 +7034,13 @@ a vytvořit nový node využívající stejný profil. Profil se nepodařilo uložit, protože nastala chyba. - + Import profile Importovat profil - + Create new profile and new Retroshare node @@ -7565,7 +7050,7 @@ a vytvořit nový node využívající stejný profil. - + Tor/I2P address @@ -7600,7 +7085,7 @@ a vytvořit nový node využívající stejný profil. - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7610,12 +7095,7 @@ a vytvořit nový node využívající stejný profil. - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -7625,12 +7105,7 @@ a vytvořit nový node využívající stejný profil. - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7856,36 +7331,13 @@ a vytvořit nový node využívající stejný profil. Začínáme - + Invite Friends Pozvat přátelé - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Bez kontaktů nestojí RetroShare za nic. Klikněte na tlačítko a pozvěte nové lidi!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Pošlete pozvánku s vaším &quot;certifikátem&quot; vašim přátelům.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Ujistěte se, že vám také pošlou pozvánku... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Můžete se spojit pouze tehdy, pokud jste se do kontaktů přidali navzájem.</span></p></body></html> - - - + Add Your Friends to RetroShare Přidat tvoje přátele do Retroshare @@ -7895,89 +7347,103 @@ p, li { white-space: pre-wrap; } Přidat přátele - + + Connect To Friends + Připojit k přátelům + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Pokročílé: Otevřený Port Firewallu + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - Připojit k přátelům - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - Pokročílé: Otevřený Port Firewallu - - - + Further Help and Support Další pomoc a podpora - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website Otevřít webovou stránku RetroShare @@ -8002,7 +7468,7 @@ p, li { white-space: pre-wrap; } Emailová zpětná vazba - + RetroShare Invitation Pozvánka do RetroShare @@ -8056,12 +7522,12 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne RetroShare zpětná vazba - + RetroShare Support RetroShare Podpora - + It has many features, including built-in chat, messaging, @@ -8185,7 +7651,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne GroupChatToaster - + Show Group Chat Zobrazit skupinovou konverzaci @@ -8193,7 +7659,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne GroupChooser - + [Unknown] @@ -8363,7 +7829,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne GroupTreeWidget - + Title Nadpis @@ -8376,12 +7842,12 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - + Description Popis - + Number of Unread message @@ -8406,19 +7872,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - Sort by Name - Seřadit podle jména - - - Sort by Popularity - Seřadit podle oblíbenosti - - - Sort by Last Post - Seřadit podle posledního příspěvku - - - + You are admin (modify names and description using Edit menu) @@ -8433,14 +7887,14 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - - + + Last Post Poslední příspěvek - + Name @@ -8451,17 +7905,13 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne Popularita - + Never - Display - Zobrazit - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8474,7 +7924,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne GuiExprElement - + and a @@ -8610,7 +8060,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne GxsChannelDialog - + Channels Kanály @@ -8621,22 +8071,22 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne Vytvořit kanál - + Enable Auto-Download Zapnout automatické stahování - + My Channels Moje kanály - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Odebírané kanály @@ -8656,12 +8106,12 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - + Disable Auto-Download Vypnout automatické stahování - + Set download directory @@ -8696,22 +8146,22 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - + Play Přehrát - + Open folder - + Open file - + Error Chyba @@ -8731,17 +8181,17 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - + Are you sure that you want to cancel and delete the file? - + Can't open folder - + Play File Přehrát soubor @@ -8751,33 +8201,10 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne Soubor %1 neexistuje. - - GxsChannelFilesWidget - - Form - Formulář - - - Filename - Jméno souboru - - - Size - Velikost - - - Title - Nadpis - - - Status - Status - - GxsChannelGroupDialog - + Create New Channel Vytvořit nový kanál @@ -8815,9 +8242,19 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne GxsChannelGroupItem - - Subscribe to Channel - Odebírat kanál + + Last activity + + + + + TextLabel + Textový popisek + + + + Subscribe this Channel + @@ -8831,7 +8268,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - + Expand Rozbalit @@ -8846,7 +8283,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne Popis kanálu - + Loading Nahrávám @@ -8861,8 +8298,9 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - New Channel - Nový kanál + + Never + @@ -8873,7 +8311,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne GxsChannelPostItem - + New Comment: @@ -8894,7 +8332,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - + Play Přehrát @@ -8956,18 +8394,18 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne Skrýt - + New Nový - + 0 0 - - + + Comment Komentáře @@ -8982,21 +8420,17 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - Loading - Nahrávám - - - + Loading... - + Comments - + Post @@ -9021,67 +8455,16 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne Přehrát - - GxsChannelPostsWidget - - Post to Channel - Přidat příspěvek do kanálu - - - Loading - Nahrávám - - - Title - Nadpis - - - Search Title - Hledat podle jména fóra - - - Message - Text příspěvku - - - Filename - Jméno souboru - - - No Channel Selected - Není vybrán žádný kanál - - - Disable Auto-Download - Vypnout automatické stahování - - - Enable Auto-Download - Zapnout automatické stahování - - - Feeds - Kanály - - - Files - Soubory - - - Description: - Popis: - - GxsChannelPostsWidgetWithModel - + Post to Channel Přidat příspěvek do kanálu - + Add new post @@ -9151,7 +8534,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - Posts (locally / at friends): + Items (locally / at friends): @@ -9187,7 +8570,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - + Comments Komentáře @@ -9202,13 +8585,13 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne Kanály - - + + Click to switch to list view - + Show unread posts only @@ -9223,7 +8606,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - + No text to display @@ -9238,7 +8621,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - + Switch to list view @@ -9298,12 +8681,22 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -9378,12 +8771,13 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - + + Copy Retroshare link - + Subscribed Přihlášen @@ -9434,17 +8828,17 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne GxsCircleItem - + TextLabel Textový popisek - + Circle name: - + Accept @@ -9559,7 +8953,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne GxsCommentContainer - + Comment Container @@ -9572,7 +8966,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne Formulář - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9602,7 +8996,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - + Comment Komentáře @@ -9641,7 +9035,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne GxsCommentTreeWidget - + Reply to Comment Reagovat na komentář @@ -9665,6 +9059,21 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne Vote Down Palec dolu + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9674,7 +9083,7 @@ Při používání sítě proto pokud možno používejte pouhou přezdívku, ne - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9703,7 +9112,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -9734,7 +9143,7 @@ before you can comment - + It remains %1 characters after HTML conversion. @@ -9785,7 +9194,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum Odebírat fórum @@ -9801,7 +9210,7 @@ before you can comment - + Expand Rozbalit @@ -9821,8 +9230,9 @@ before you can comment - Loading - Nahrávám + + TextLabel + Textový popisek @@ -9853,13 +9263,13 @@ before you can comment GxsForumMsgItem - - + + Subject: Předmět: - + Unsubscribe To Forum Neodebírat fórum @@ -9870,7 +9280,7 @@ before you can comment - + Expand Rozbalit @@ -9890,21 +9300,17 @@ before you can comment - Loading - Nahrávám - - - + Loading... - + Forum Feed - + Hide Skrýt @@ -9917,63 +9323,66 @@ before you can comment Formulář - + Start new Thread for Selected Forum Založit nové vlákno ve vybraném fóru - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Hledat ve fórech - Last Post - Poslední příspěvek - - - + New Thread - - - Threaded View - podle vláken - - - - Flat View - Vše za sebou - - + Title Nadpis - - + + Date Datum - + Author Autor - - Save image - - - - + Loading Načítám - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9983,12 +9392,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message Odpovědět na příspěvek @@ -10012,10 +9416,6 @@ before you can comment Download all files Stáhnout všechny soubory - - Next unread - Další nepřečtený - Search Title @@ -10032,31 +9432,23 @@ before you can comment Hledat podle autora - Content - Obsah - - - Search Content - Hledat v obsahu zprávy - - - + No name Bez jména - - + + Reply Odpovědět - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -10099,16 +9491,12 @@ before you can comment Kopírovat RetroShare odkaz - + Hide Skrýt - Expand - Rozbalit - - - + [unknown] @@ -10138,8 +9526,8 @@ before you can comment - - + + Distribution @@ -10153,22 +9541,6 @@ before you can comment Anti-spam - - Anonymous - Anonymní sdílení - - - signed - podepsáno - - - none - žádný - - - [ ... Missing Message ... ] - [ ... chybějící zpráva ... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10238,12 +9610,12 @@ before you can comment Původní zpráva - + New thread - + Edit Editovat @@ -10304,7 +9676,7 @@ before you can comment - + Show column @@ -10324,7 +9696,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive @@ -10376,7 +9748,7 @@ This message is missing. You should receive it later. - + No result. @@ -10386,7 +9758,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -10401,7 +9773,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -10467,12 +9839,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums Fórum @@ -10503,31 +9875,16 @@ This message is missing. You should receive it later. Ostatní fóra - - GxsForumsFillThread - - Waiting - Čekám - - - Retrieving - Stahuji - - - Loading - Načítám - - GxsGroupDialog - + Name Jméno uživatele - + Key recipients can publish to restricted-type group and can view and publish for private-type channels @@ -10536,22 +9893,14 @@ This message is missing. You should receive it later. Share Publish Key - - check peers you would like to share private publish key with - zaškrtněte protějšky s nimiž chcete sdílet soukromý klíč k publikačnímu právu - - - Share Key With - Sdílet klíč s - - + Description Popis - + Message Distribution @@ -10559,7 +9908,7 @@ This message is missing. You should receive it later. - + Public Veřejné @@ -10619,7 +9968,7 @@ This message is missing. You should receive it later. - + Comments: Komentáře: @@ -10642,7 +9991,7 @@ This message is missing. You should receive it later. - + All People @@ -10658,12 +10007,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -10680,23 +10029,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -10712,22 +10061,28 @@ This message is missing. You should receive it later. Detaily - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo - + Submit Group Changes - + Owner: @@ -10737,12 +10092,12 @@ This message is missing. You should receive it later. - + Info - + ID ID @@ -10752,7 +10107,7 @@ This message is missing. You should receive it later. Poslední příspěvek - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -10827,7 +10182,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity Popularita @@ -10843,27 +10203,22 @@ This message is missing. You should receive it later. - + Created - + Cancel Zrušit - + Create Vytvořit - - Author - Autor - - - + GxsIdLabel @@ -10871,7 +10226,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading Nahrávám @@ -10931,7 +10286,7 @@ This message is missing. You should receive it later. - + Synchronise posts of last... @@ -10988,12 +10343,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link Kopírovat RetroShare odkaz @@ -11016,7 +10371,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature @@ -11029,18 +10384,14 @@ This message is missing. You should receive it later. GxsIdDetails - Loading - Nahrávám - - - + Not found - - + + [Banned] @@ -11050,7 +10401,7 @@ This message is missing. You should receive it later. - + Loading... @@ -11060,7 +10411,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -11080,6 +10436,14 @@ This message is missing. You should receive it later. + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -11091,7 +10455,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -11139,17 +10503,13 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] GxsMessageFramePostWidget - - Loading - Nahrávám - Loading... @@ -11530,7 +10890,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -11546,7 +10906,7 @@ p, li { white-space: pre-wrap; } - + Authors Autoři @@ -11565,7 +10925,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -11639,7 +10999,7 @@ p, li { white-space: pre-wrap; } Formulář - + Add friend @@ -11649,7 +11009,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -11677,7 +11037,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -11687,7 +11047,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard Kopírovat váš certifikát do schránky @@ -11697,7 +11057,7 @@ private and secure decentralized communication platform. Uložit váš certifikát do souboru - + Send via Email @@ -11717,13 +11077,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -11735,12 +11119,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -11755,12 +11139,7 @@ new short format Pozvánka do RetroShare - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... Uložit jako... @@ -12025,14 +11404,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Vše - + Reputation @@ -12042,12 +11421,12 @@ p, li { white-space: pre-wrap; } Hledat - + Anonymous Id - + Create new Identity Vytvořit novou identitu @@ -12057,7 +11436,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -12072,27 +11451,27 @@ p, li { white-space: pre-wrap; } - + Close Zavřít - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -12108,29 +11487,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles Okruhy lidí - + Circle name @@ -12150,18 +11539,20 @@ p, li { white-space: pre-wrap; } Osobní Kruhy - + + Edit identity - + + Delete identity - + Chat with this peer @@ -12171,78 +11562,78 @@ p, li { white-space: pre-wrap; } - + Owner node ID : - + Identity name : - + () - + Identity ID - + Send message Odeslat zprávu - + Identity info - + Identity ID : - + Owner node name : - + Create new... - + Type: Typ: - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: - + Negative - + Neutral @@ -12253,17 +11644,17 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous Anonymní sdílení @@ -12278,24 +11669,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you - - + + My own identities - - + + My contacts - + Show Items @@ -12310,7 +11701,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -12320,7 +11716,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -12395,7 +11791,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -12425,7 +11821,7 @@ p, li { white-space: pre-wrap; } neznámé - + Invited @@ -12440,7 +11836,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle Upravit Kruh @@ -12488,7 +11884,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -12496,7 +11892,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -12539,7 +11935,7 @@ These identities will soon be not supported anymore. - + Boards @@ -12581,7 +11977,7 @@ These identities will soon be not supported anymore. Message - + Zpráva @@ -12619,7 +12015,7 @@ These identities will soon be not supported anymore. - + information @@ -12635,17 +12031,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -12750,7 +12141,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -12800,21 +12191,21 @@ These identities will soon be not supported anymore. - - - + + + People - + Your Avatar Click here to change your avatar - + Linked to neighbor nodes @@ -12824,7 +12215,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -12839,7 +12230,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -12854,12 +12245,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -12879,12 +12270,12 @@ These identities will soon be not supported anymore. - + Owned by - + Node name: @@ -12894,7 +12285,7 @@ These identities will soon be not supported anymore. - + Really delete? @@ -12902,7 +12293,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname Přezdívka @@ -12932,7 +12323,13 @@ These identities will soon be not supported anymore. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity @@ -12946,7 +12343,7 @@ These identities will soon be not supported anymore. - + @@ -12956,7 +12353,12 @@ These identities will soon be not supported anymore. nedostupné - + + No avatar chosen + + + + Edit identity @@ -12967,27 +12369,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -13007,7 +12409,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -13017,12 +12419,18 @@ These identities will soon be not supported anymore. - + Error KeyID invalid - + + + No Avatar chosen. A default image will be automatically displayed from your new identity. + + + + Import image @@ -13032,12 +12440,7 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. - - - - + Unknown GpgId @@ -13047,7 +12450,7 @@ These identities will soon be not supported anymore. - + Create New Identity @@ -13057,10 +12460,15 @@ These identities will soon be not supported anymore. Typ - + Choose image... + + + Remove + Odebrat + @@ -13086,7 +12494,7 @@ These identities will soon be not supported anymore. Přidat - + Create Vytvořit @@ -13096,13 +12504,13 @@ These identities will soon be not supported anymore. Zrušit - + Your Avatar Click here to change your avatar - + Linked to your profile @@ -13112,7 +12520,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -13186,7 +12594,7 @@ These identities will soon be not supported anymore. - + Copy Kopírovat @@ -13196,12 +12604,12 @@ These identities will soon be not supported anymore. Odebrat - + %1 's Message History - + Mark all Označit vše @@ -13220,26 +12628,38 @@ These identities will soon be not supported anymore. Quote Citovat - - Send - Odeslat - ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -13257,27 +12677,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: Port: - + Listen Address: - + + Status: + Status: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -13298,7 +12723,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -13307,26 +12737,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File Otevřít soubor - + Open Folder Otevřít složku - + Checking... Kontroluji... @@ -13336,7 +12771,7 @@ These identities will soon be not supported anymore. Zkontrolovat soubory - + Recommend in a message to... @@ -13364,7 +12799,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend Přidat kontakt @@ -13380,7 +12815,8 @@ These identities will soon be not supported anymore. - + + Options Nastavení @@ -13401,7 +12837,7 @@ These identities will soon be not supported anymore. - + Quit Ukončit @@ -13412,12 +12848,12 @@ These identities will soon be not supported anymore. Průvodce nastavením - + RetroShare %1 a secure decentralized communication platform RetroShare %1 - bezpečná decentralizovaná komunikační platforma - + Unfinished Nedokončeno @@ -13442,11 +12878,12 @@ These identities will soon be not supported anymore. + Status Status - + Notify Upozornit @@ -13457,31 +12894,35 @@ These identities will soon be not supported anymore. + Open Messages Zobrazit zprávy - + + Bandwidth Graph Graf přenosové rychlosti - + Applications Aplikace + Help Nápověda - + + Minimize Minimalizovat - + Maximize Maximalizovat @@ -13496,7 +12937,12 @@ These identities will soon be not supported anymore. RetroShare - + + Close window + + + + %1 new message %1 nová zpráva @@ -13526,7 +12972,7 @@ These identities will soon be not supported anymore. %1 kontaktů připojeno - + Do you really want to exit RetroShare ? Opravdu chcete ukončit RetroShare? @@ -13546,7 +12992,7 @@ These identities will soon be not supported anymore. Zobrazit - + Make sure this link has not been forged to drag you to a malicious website. Ujistěte se, že tento odkaz nebyl zfalšován za účelem dostat vás na škodlivé webové stránky. @@ -13591,12 +13037,13 @@ These identities will soon be not supported anymore. - + + Statistics - + Show web interface @@ -13611,7 +13058,7 @@ These identities will soon be not supported anymore. - + Really quit ? @@ -13620,17 +13067,17 @@ These identities will soon be not supported anymore. MessageComposer - + Compose Napsat zprávu - + Contacts Kontakty - + Paragraph Odstavec @@ -13666,12 +13113,12 @@ These identities will soon be not supported anymore. Nadpis 6. úrovně - + Font size Velikost fontu - + Increase font size Zvětšit velikost fontu @@ -13686,32 +13133,32 @@ These identities will soon be not supported anymore. Tučné - + Italic Kurzíva - + Alignment Zarovnání - + Add an Image Vložit obrázek - + Sets text font to code style Zdrojový kód (nastaví neproporcionální font) - + Underline Podtržené - + Subject: Předmět: @@ -13722,32 +13169,32 @@ These identities will soon be not supported anymore. - + Tags Štítky - + Address list: - + Recommend this friend - + Set Text color - + Set Text background color - + Recommended Files Doporučené soubory @@ -13817,7 +13264,7 @@ These identities will soon be not supported anymore. Odsadí citaci - + Send To: Odeslat komu: @@ -13857,7 +13304,7 @@ These identities will soon be not supported anymore. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> Ahoj,<br>doporučuji ti tento kontakt. Když důvěřuješ mě, můžeš důvěřovat také tomuto kontaktu. <br> @@ -13877,18 +13324,18 @@ These identities will soon be not supported anymore. si vás chce přidat do kontaktů. - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team Ahoj %1,<br><br>%2 si vás chce přidat do kontaktů.<br><br>Odpovězte nyní:<br>%3<br><br>Děkujeme,<br>Tým RetroShare - - + + Save Message Uložit zprávu - + Message has not been Sent. Do you want to save message to draft box? Zpráva nebyla odeslána. @@ -13900,7 +13347,17 @@ Chcete ji uložit jako koncept? Vložit RetroShare odkaz - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" Přidat do "Komu" @@ -13920,7 +13377,7 @@ Chcete ji uložit jako koncept? Doporučit - + Original Message Původní zpráva @@ -13930,21 +13387,21 @@ Chcete ji uložit jako koncept? Od - + - + To Komu - - + + Cc Cc - + Sent Odesláno @@ -13959,7 +13416,7 @@ Chcete ji uložit jako koncept? Na %1, %2 odpověděl: - + Re: Re: @@ -13969,30 +13426,30 @@ Chcete ji uložit jako koncept? Fwd: - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? Chcete odeslat zprávu bez předmětu? - + Please insert at least one recipient. Prosím zadejte alespoň jednoho příjemce. - + Bcc Bcc - + Unknown Neznámý @@ -14107,13 +13564,13 @@ Chcete ji uložit jako koncept? Detaily - + Open File... Otevřít soubor... - + HTML-Files (*.htm *.html);;All Files (*) HTML soubory (*.htm *.html);;Všechny soubory (*) @@ -14133,7 +13590,7 @@ Chcete ji uložit jako koncept? Exportovat do PDF - + Message has not been Sent. Do you want to save message ? Zpráva nebyla odeslána. Chcete ji uložit? @@ -14154,7 +13611,7 @@ Do you want to save message ? Přidat další soubor - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -14184,18 +13641,18 @@ Do you want to save message ? - - + + Close Zavřít - + From: Od: - + Bullet list (disc) @@ -14235,13 +13692,13 @@ Do you want to save message ? - - + + Thanks, <br> - + Distant identity: @@ -14251,12 +13708,12 @@ Do you want to save message ? - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -14334,7 +13791,7 @@ Do you want to save message ? Výchozí - + A new tab Nová karta @@ -14344,7 +13801,7 @@ Do you want to save message ? Nové okno - + Edit Tag Editovat štítek @@ -14367,7 +13824,7 @@ Do you want to save message ? MessageToaster - + Sub: @@ -14375,7 +13832,7 @@ Do you want to save message ? MessageUserNotify - + Message Zpráva @@ -14403,7 +13860,7 @@ Do you want to save message ? MessageWidget - + Recommended Files Doporučené soubory @@ -14413,37 +13870,37 @@ Do you want to save message ? Stáhnou všechny doporučené soubory - + Subject: Předmět: - + From: Od: - + To: Pro: - + Cc: Cc: - + Bcc: Bcc: - + Tags: Štítky: - + Reply Odpovědět @@ -14483,7 +13940,7 @@ Do you want to save message ? - + Send Invite @@ -14535,7 +13992,7 @@ Do you want to save message ? - + Confirm %1 as friend @@ -14545,12 +14002,12 @@ Do you want to save message ? Přidat %1 do kontaktů - + View source - + No subject Bez předmětu @@ -14560,17 +14017,22 @@ Do you want to save message ? Stáhnout - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -14579,14 +14041,24 @@ Do you want to save message ? %1 (%2) + + + Show less + + + + + Show more + + - + Download all Stáhnout vše - + Print Document Vytisknout dokument @@ -14601,12 +14073,12 @@ Do you want to save message ? HTML soubory (*.htm *.html);;Všechny soubory (*) - + Load images always for this message - + Hide the attachment pane @@ -14628,42 +14100,6 @@ Do you want to save message ? Compose Napsat - - Reply to selected message - Odpovědět na označenou zprávu - - - Reply - Odpovědět - - - Reply all to selected message - Odpovědět na označené zprávy - - - Reply all - Odpovědět všem - - - Forward selected message - Přeposlat označenou zprávu - - - Forward - Vpřed - - - Remove selected message - Odstranit označenou zprávu - - - Delete - Smazat - - - Print selected message - Vytisknout označenou zprávu - Print @@ -14742,7 +14178,7 @@ Do you want to save message ? MessagesDialog - + New Message Nová zpráva @@ -14752,60 +14188,16 @@ Do you want to save message ? Napsat - Reply to selected message - Odpovědět na označenou zprávu - - - Reply - Odpovědět - - - Reply all to selected message - Odpovědět na označené zprávy - - - Reply all - Odpovědět všem - - - Forward selected message - Přeposlat označenou zprávu - - - Foward - Přeposlat - - - Remove selected message - Odstranit označenou zprávu - - - Delete - Smazat - - - Print selected message - Vytisknout označenou zprávu - - - Print - Tisknout - - - Display - Zobrazit - - - + - - + + Tags Štítky - - + + Inbox Příchozí @@ -14835,21 +14227,17 @@ Do you want to save message ? Koš - + Total Inbox: Příchozí celkem: - Folders - Složky - - - + Quick View Zobrazit pouze - + Print... Tisknout... @@ -14880,7 +14268,7 @@ Do you want to save message ? Přeposlat zprávu - + Subject Předmět @@ -14890,7 +14278,7 @@ Do you want to save message ? Od - + Date Datum @@ -14900,39 +14288,7 @@ Do you want to save message ? Obsah - Click to sort by attachments - Seřazení podle příloh - - - Click to sort by subject - Seřadit podle předmětu - - - Click to sort by read - Seřadit podle přečtených - - - Click to sort by from - Seřadit podle odesílatele - - - Click to sort by date - Seřadit podle datumu - - - Click to sort by tags - Seřadit podle štítků - - - Click to sort by star - Seřadit podle ohvězdičkování - - - Forward selected Message - Přeposlat označenou zprávu - - - + Search Subject Hledat v předmětu zprávy @@ -14941,6 +14297,11 @@ Do you want to save message ? Search From Hledat podle odesílatele + + + Search To + + Search Date @@ -14967,14 +14328,14 @@ Do you want to save message ? Hledat v přílohách - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred - Ohvězdičkované + @@ -15048,7 +14409,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -15062,7 +14423,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -15077,34 +14438,33 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts Koncepty - + No Box selected. - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - Nemáte ohvězdičkované žádné zprávy. Ohvězdičkování slouží ke zvýraznění zpráv, abyste je mohli snáze najít. Zprávu ohvězdičkujete kliknutím na světle šedou hvezdičku kterékoliv zprávy nebo pomocí kontextového menu, ktere otevřete tím, že na ni kliknete pravým tlačítkem myši. - - - No system messages available. - Nemáte žádné zprávy systému. - - + To - Pro + Pro - Click to sort by to - Pro seřazení klikněte - - - + @@ -15112,10 +14472,6 @@ Do you want to save message ? Total: Celkem: - - Messages - Zprávy - Mail @@ -15143,7 +14499,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -15197,7 +14563,7 @@ Do you want to save message ? - + Expand Rozbalit @@ -15207,7 +14573,7 @@ Do you want to save message ? Odstranit položku - + from @@ -15242,7 +14608,7 @@ Do you want to save message ? - + Hide Skrýt @@ -15383,7 +14749,7 @@ Do you want to save message ? ID certifikátu - + Remove unused keys... @@ -15393,7 +14759,7 @@ Do you want to save message ? - + Clean keyring @@ -15407,7 +14773,13 @@ Notes: Your old keyring will be backed up. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info @@ -15440,18 +14812,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. - - - Export/create a new node - - Trusted keys only - + Search name @@ -15461,25 +14828,18 @@ For security, your keyring was previously backed-up to file - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: - - NetworkPage - - Network - Síť - - NetworkView @@ -15506,7 +14866,7 @@ Reported error: NewFriendList - + Offline Friends @@ -15527,7 +14887,7 @@ Reported error: - + Groups Skupiny @@ -15557,19 +14917,19 @@ Reported error: - - + + Search - + ID ID - + Search ID @@ -15579,12 +14939,12 @@ Reported error: - + Show Items - + Last contact @@ -15594,7 +14954,7 @@ Reported error: IP - + Group Skupina @@ -15709,7 +15069,7 @@ Reported error: Zabalit vše - + Do you want to remove this node? Chcete odstranit tento node? @@ -15719,7 +15079,7 @@ Reported error: Opravdu chcete odstranit tento kontakt? - + Done! @@ -15826,7 +15186,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -15841,11 +15201,7 @@ at least one peer was not added to a group Smazat vše - This is a test. - Toto je test. - - - + Newest on top @@ -15855,12 +15211,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15915,10 +15271,6 @@ at least one peer was not added to a group Blogs Blogy - - Security - Bezpečnost - @@ -15940,10 +15292,6 @@ at least one peer was not added to a group Message Zpráva - - Connect attempt - Pokus o připojení - @@ -16097,10 +15445,6 @@ at least one peer was not added to a group Disable All Toaster temporarily - - Feed - Kanál - Systray @@ -16110,7 +15454,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -16130,12 +15474,12 @@ at least one peer was not added to a group Chybné heslo! - + Please enter your Retroshare passphrase - + Unregistered plugin/executable Nezaregistrovaný plugin či program @@ -16150,19 +15494,7 @@ at least one peer was not added to a group - Examining shared files... - Prohledávám sdílené soubory... - - - Hashing file - Počítám kryptografickou sumu (hash) souboru. - - - Saving file index... - Ukládám index souborů... - - - + Test Test @@ -16173,17 +15505,19 @@ at least one peer was not added to a group + Unknown title - + + Encrypted message - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -16191,7 +15525,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online Kontakt je online @@ -16330,7 +15664,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -16339,10 +15678,6 @@ p, li { white-space: pre-wrap; } Keysigning: - - Sign PGP key - Podepsat PGP klíč - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -16379,12 +15714,7 @@ p, li { white-space: pre-wrap; } Zahrnout podpisy - - Options - - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -16430,21 +15760,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - - + + Error : cannot get peer details. Chyba : nemohu získat údaje kontaktu - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) @@ -16462,7 +15792,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -16531,10 +15861,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Check the password! - - Maybe password is wrong - Možná že bylo špatně zadané heslo - You haven't set a trust level for this key. @@ -16542,12 +15868,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -16573,7 +15899,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat Konverzace @@ -16594,7 +15920,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Odstranit položku - + Name: Jméno: @@ -16634,7 +15960,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message Napsat zprávu @@ -16648,10 +15974,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Friend Connected se připojil. - - Connect Attempt - se pokusil připojit. - Connection refused by peer @@ -16690,17 +16012,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.Unknown - - Unknown Peer - Neznámý protějšek - Hide Skrýt - + Send Message Poslat zprávu @@ -16867,13 +16185,6 @@ Warning: In your File-Transfer option, you select allow direct download to No. - - PhotoCommentItem - - Form - Formulář - - PhotoDialog @@ -16886,14 +16197,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.TextLabel Textový popisek - - Comment - Komentáře - - - Summary - Shrnutí - Album / Photo Name @@ -16954,10 +16257,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.... ... - - Add Comment - Přidat komentář - Album @@ -17041,17 +16340,17 @@ p, li { white-space: pre-wrap; } - + My Albums - + Subscribed Albums - + Shared Albums @@ -17080,7 +16379,7 @@ requesting to edit it! PhotoSlideShow - + Album Name Jméno alba: @@ -17139,19 +16438,19 @@ requesting to edit it! - - + + TextLabel Textový popisek - + Posted by - + ago @@ -17187,12 +16486,12 @@ requesting to edit it! PluginItem - + TextLabel Textový popisek - + Show more details about this plugin @@ -17403,12 +16702,27 @@ p, li { white-space: pre-wrap; } Podržet okno nad ostatními - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -17461,7 +16775,7 @@ p, li { white-space: pre-wrap; } Nový - + Vote up @@ -17481,8 +16795,8 @@ p, li { white-space: pre-wrap; } - - + + Comments Komentáře @@ -17507,13 +16821,13 @@ p, li { white-space: pre-wrap; } - - + + Comment Komentáře - + Comments @@ -17541,12 +16855,12 @@ p, li { white-space: pre-wrap; } PostedCreatePostDialog - + Create a new Post - + RetroShare RetroShare @@ -17561,12 +16875,22 @@ p, li { white-space: pre-wrap; } - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File Nahrát soubor s obrázkem - + Post image @@ -17582,7 +16906,17 @@ p, li { white-space: pre-wrap; } - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -17592,7 +16926,7 @@ p, li { white-space: pre-wrap; } - + Please add a Title @@ -17612,12 +16946,22 @@ p, li { white-space: pre-wrap; } - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -17632,7 +16976,7 @@ p, li { white-space: pre-wrap; } Psát jako - + Post @@ -17643,7 +16987,7 @@ p, li { white-space: pre-wrap; } - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -17653,7 +16997,7 @@ p, li { white-space: pre-wrap; } Nadpis - + Link @@ -17661,16 +17005,12 @@ p, li { white-space: pre-wrap; } PostedDialog - Posted Links - Odeslané odkazy - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -17704,7 +17044,7 @@ p, li { white-space: pre-wrap; } PostedGroupDialog - + Create New Board @@ -17742,7 +17082,17 @@ p, li { white-space: pre-wrap; } PostedGroupItem - + + Last activity + + + + + TextLabel + Textový popisek + + + Subscribe to Posted @@ -17758,7 +17108,7 @@ p, li { white-space: pre-wrap; } - + Expand Rozbalit @@ -17773,16 +17123,17 @@ p, li { white-space: pre-wrap; } - Loading - Nahrávám - - - + Loading... - + + Never + + + + New Board @@ -17795,18 +17146,18 @@ p, li { white-space: pre-wrap; } PostedItem - + 0 0 - - + + Comments Komentáře - + Copy RetroShare Link Kopírovat RetroShare odkaz @@ -17817,12 +17168,12 @@ p, li { white-space: pre-wrap; } - + Comment Komentáře - + Comments @@ -17832,7 +17183,7 @@ p, li { white-space: pre-wrap; } - + Click to view Picture @@ -17842,17 +17193,17 @@ p, li { white-space: pre-wrap; } Skrýt - + Vote up - + Vote down - + Set as read and remove item Označit za přečtené a odstranit položku @@ -17862,7 +17213,7 @@ p, li { white-space: pre-wrap; } Nový - + New Comment: @@ -17872,7 +17223,7 @@ p, li { white-space: pre-wrap; } - + Name @@ -17913,34 +17264,11 @@ p, li { white-space: pre-wrap; } Textový popisek - + Loading Nahrávám - - PostedListWidget - - Form - Formulář - - - New - Nový - - - Top - Nahoře - - - Next - Další - - - RetroShare - RetroShare - - PostedListWidgetWithModel @@ -17959,7 +17287,17 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -17969,15 +17307,15 @@ p, li { white-space: pre-wrap; } - + - + unknown neznámé - + Distribution: @@ -17987,42 +17325,42 @@ p, li { white-space: pre-wrap; } - + Created - + TextLabel Textový popisek - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -18042,7 +17380,7 @@ p, li { white-space: pre-wrap; } - + Search @@ -18072,17 +17410,17 @@ p, li { white-space: pre-wrap; } - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -18097,12 +17435,17 @@ p, li { white-space: pre-wrap; } - + Copy RetroShare Link Kopírovat RetroShare odkaz - + + Copy http Link + + + + Show author in People tab @@ -18112,27 +17455,31 @@ p, li { white-space: pre-wrap; } Editovat - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -18147,7 +17494,7 @@ p, li { white-space: pre-wrap; } Odebírat - + Never @@ -18221,6 +17568,16 @@ p, li { white-space: pre-wrap; } No Channel Selected Není vybrán žádný kanál + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -18310,16 +17667,16 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -18431,7 +17788,7 @@ tam ji importujte. ProfileWidget - + Edit status message Editovat status @@ -18447,7 +17804,7 @@ tam ji importujte. - + Public Information Veřejné informace @@ -18482,12 +17839,12 @@ tam ji importujte. Připojen od: - + Other Information Další informace - + My Address @@ -18531,27 +17888,27 @@ tam ji importujte. PulseAddDialog - + Add to Pulse - + Display As - + URL - + GroupLabel - + IDLabel @@ -18561,12 +17918,12 @@ tam ji importujte. Od: - + Head - + Head Shot @@ -18596,13 +17953,13 @@ tam ji importujte. - - + + Whats happening? - + @@ -18614,12 +17971,22 @@ tam ji importujte. - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -18634,7 +18001,7 @@ tam ji importujte. - + Reply to Pulse @@ -18649,34 +18016,24 @@ tam ji importujte. - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - Od - - - Date - Datum - - - ... - ... + + Load Picture File + Nahrát soubor s obrázkem @@ -18687,7 +18044,7 @@ tam ji importujte. Formulář - + @@ -18706,7 +18063,7 @@ tam ji importujte. PulseReply - + icn @@ -18716,7 +18073,7 @@ tam ji importujte. - + REPLY @@ -18743,7 +18100,7 @@ tam ji importujte. - + FOLLOW @@ -18753,7 +18110,7 @@ tam ji importujte. - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -18773,7 +18130,7 @@ tam ji importujte. - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -18889,7 +18246,7 @@ tam ji importujte. - + FOLLOW @@ -18897,37 +18254,42 @@ tam ji importujte. PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -18959,7 +18321,7 @@ tam ji importujte. - + FOLLOW @@ -18967,8 +18329,8 @@ tam ji importujte. QObject - - + + Confirmation Potvrzení @@ -19236,12 +18598,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace Peer detaily - + File Request canceled Požadavek o stáhnutí souboru byl zrušen. - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. @@ -19272,7 +18634,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace Nastala neočekávaná chyba. Prosím pošlete hlášení 'RsInit::InitRetroShare unexpected return code %1'. - + Cannot start Tor Manager! @@ -19306,7 +18668,7 @@ The error reported is:" - + Multiple instances Běží několik isntancí @@ -19325,6 +18687,26 @@ The error reported is:" + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -19404,7 +18786,7 @@ Reported error is: - + You appear to have nodes associated to DSA keys: @@ -19414,7 +18796,7 @@ Reported error is: - + enabled @@ -19424,7 +18806,7 @@ Reported error is: - + Move IP %1 to whitelist @@ -19440,7 +18822,7 @@ Reported error is: - + %1 seconds ago @@ -19507,7 +18889,7 @@ Security: no anonymous IDs - + Join chat room @@ -19535,7 +18917,7 @@ Security: no anonymous IDs - + Indefinitely @@ -19715,13 +19097,29 @@ Security: no anonymous IDs Ban list + + + Name + + + Node + Uzel + + + + Address + + + + + Status Status - + NXS @@ -19914,10 +19312,6 @@ Security: no anonymous IDs Click to resume the hashing process - - <p>This certificate contains: - <p>Tento certifikát obsahuje - Idle @@ -19968,6 +19362,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -20117,7 +19523,7 @@ p, li { white-space: pre-wrap; } - + Network Wide @@ -20284,7 +19690,7 @@ p, li { white-space: pre-wrap; } Formulář - + The loading of embedded images is blocked. @@ -20297,7 +19703,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default @@ -20470,12 +19876,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -20483,12 +19899,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -21176,7 +20592,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name @@ -21297,7 +20713,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name @@ -21317,7 +20733,7 @@ If you believe it is correct, remove the corresponding line from the file and re IP - + Profile ID @@ -21373,7 +20789,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -21387,11 +20803,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - [ ... chybějící zpráva ... ] - RsMessageModel @@ -21405,6 +20816,11 @@ prevents the message to be forwarded to your friends. From Od + + + To + + Subject @@ -21427,13 +20843,18 @@ prevents the message to be forwarded to your friends. - Click to sort by read - Seřadit podle přečtených + Click to sort by read status + - Click to sort by from - Seřadit podle odesílatele + Click to sort by author + + + + + Click to sort by destination + @@ -21456,7 +20877,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -21477,7 +20900,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. Obnoví všechna(!) uložená nastavení RetroShare na výchozí. @@ -21538,7 +20961,7 @@ prevents the message to be forwarded to your friends. Nastaví použitý jazyk. - + Unable to open log file '%1': %2 Nemohu otevřít log soubor '%1': %2 @@ -21559,7 +20982,7 @@ prevents the message to be forwarded to your friends. - + opmode @@ -21589,7 +21012,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -21607,7 +21030,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -21624,12 +21047,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) Zadejkte klíčové slovo (alespoň 3 znaky dlouhé, např. mkv) - + Start Search Začít vyhledávat @@ -21691,7 +21114,7 @@ Vysoká pravděpodobnost že soubor bude nalezen Smazat - + KeyWords Klíčová slova @@ -21706,7 +21129,7 @@ Vysoká pravděpodobnost že soubor bude nalezen Identifikátor dotazu - + Filename Jméno souboru @@ -21806,23 +21229,23 @@ Vysoká pravděpodobnost že soubor bude nalezen Stáhnout vybrané - + File Name Jméno souboru - + Download Stáhnout - + Copy RetroShare Link Kopírovat RetroShare odkaz - + Send RetroShare Link Poslat odkaz RetroShare @@ -21832,7 +21255,7 @@ Vysoká pravděpodobnost že soubor bude nalezen - + Download Notice Stáhnout poznámku @@ -21869,7 +21292,7 @@ Vysoká pravděpodobnost že soubor bude nalezen Odebrat vše - + Folder Složka @@ -21880,17 +21303,17 @@ Vysoká pravděpodobnost že soubor bude nalezen - + New RetroShare Link(s) Nový odkaz RetroShare (1 či více) - + Open Folder Otevřít složku - + Create Collection... @@ -21910,7 +21333,7 @@ Vysoká pravděpodobnost že soubor bude nalezen Stáhnou podle souboru kolekce... - + Collection Kolekce @@ -21918,7 +21341,7 @@ Vysoká pravděpodobnost že soubor bude nalezen SecurityIpItem - + Peer details Podrobnosti o kontaktu @@ -21934,22 +21357,22 @@ Vysoká pravděpodobnost že soubor bude nalezen Odstranit položku - + IP address: - + Peer ID: ID protějšku: - + Location: Umístění: - + Peer Name: @@ -21966,7 +21389,7 @@ Vysoká pravděpodobnost že soubor bude nalezen Skrýt - + but reported: @@ -21991,8 +21414,8 @@ Vysoká pravděpodobnost že soubor bude nalezen - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -22000,7 +21423,7 @@ Vysoká pravděpodobnost že soubor bude nalezen SecurityItem - + wants to be friend with you on RetroShare si vás chce přidat do kontaktů. @@ -22031,7 +21454,7 @@ Vysoká pravděpodobnost že soubor bude nalezen - + Expand Rozbalit @@ -22076,12 +21499,12 @@ Vysoká pravděpodobnost že soubor bude nalezen Status: - + Write Message Napsat zprávu - + Connect Attempt Pokus o připojení @@ -22101,17 +21524,22 @@ Vysoká pravděpodobnost že soubor bude nalezen Neznámý (odchozí) pokus o připojení - + Unknown Security Issue Neznámá bezpečnostní událost - - A unknown peer + + SSL request - + + An unknown peer + + + + Unknown @@ -22121,11 +21549,7 @@ Vysoká pravděpodobnost že soubor bude nalezen - Unknown Peer - Neznámý Peer - - - + Hide Skrýt @@ -22135,7 +21559,7 @@ Vysoká pravděpodobnost že soubor bude nalezen Opravdu chcete odstranit tento kontakt? - + Certificate has wrong signature!! This peer is not who he claims to be. @@ -22145,12 +21569,12 @@ Vysoká pravděpodobnost že soubor bude nalezen - + Certificate caused an internal error. - + Peer/node not in friendlist (PGP id= @@ -22209,12 +21633,12 @@ Vysoká pravděpodobnost že soubor bude nalezen - + Local Address Lokální adresa - + NAT @@ -22235,22 +21659,22 @@ Vysoká pravděpodobnost že soubor bude nalezen Port: - + Local network Mapa sítě - + External ip address finder Vyhledávač externích IP adres - + UPnP UPnP - + Known / Previous IPs: @@ -22263,21 +21687,16 @@ behind a firewall or a VPN. - - Allow RetroShare to ask my ip to these websites: - Pro zjištění mé veřejné IP adresy použít následující strány: - - - - - + + + kB/s kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -22287,23 +21706,46 @@ behind a firewall or a VPN. - + Onion Address - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -22313,7 +21755,7 @@ behind a firewall or a VPN. - + I2P Address @@ -22338,37 +21780,95 @@ behind a firewall or a VPN. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -22383,71 +21883,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. neznámé - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -22457,22 +21893,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -22484,12 +21905,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -22499,7 +21920,7 @@ Also check your ports! Vymazat - + Download limit (KB/s) @@ -22514,23 +21935,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -22541,17 +21962,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -22561,12 +21972,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -22576,17 +21982,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 127.0.0.1 - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -22626,7 +22022,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start @@ -22641,12 +22037,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - BOB status - - - - + Incoming Příchozí @@ -22682,7 +22073,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -22737,7 +22153,7 @@ If you have issues connecting over Tor check the Tor logs too. Celkem: - + Warning: This bandwidth adds up to the max bandwidth. @@ -22762,7 +22178,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -22774,7 +22190,7 @@ If you have issues connecting over Tor check the Tor logs too. Síť - + IP Filters @@ -22797,7 +22213,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status Status @@ -22857,17 +22273,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -22883,18 +22310,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -22929,12 +22356,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -22957,22 +22384,22 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -23007,7 +22434,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -23017,12 +22444,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -23102,7 +22529,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with zaškrtněte protějšky s nimiž chcete sdílet soukromý klíč k publikačnímu právu @@ -23112,12 +22539,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Share - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -23136,7 +22563,7 @@ Select the Friends with which you want to Share your Channel. Sdílení složek a souborů v nich obsažených - + Shared directory @@ -23156,17 +22583,17 @@ Select the Friends with which you want to Share your Channel. Viditelnost - + Add new - + Cancel Zrušit - + Add a Share Directory Přidat sdílenou složku @@ -23176,7 +22603,7 @@ Select the Friends with which you want to Share your Channel. Odebrat - + Apply and close Uložit a zavřít @@ -23267,7 +22694,7 @@ Select the Friends with which you want to Share your Channel. Složka nebyla nalezena nebo její jméno je neplatné. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. @@ -23275,7 +22702,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files Soubory @@ -23326,11 +22753,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files Zkontrolovat soubory - + Download selected Stáhnout vybrané @@ -23340,7 +22772,7 @@ Select the Friends with which you want to Share your Channel. Stáhnout - + Copy retroshare Links to Clipboard Zkopírovat RetrosShare odkazy do schránky @@ -23355,7 +22787,7 @@ Select the Friends with which you want to Share your Channel. Poslat RetroShare odkazy - + Some files have been omitted @@ -23371,7 +22803,7 @@ Select the Friends with which you want to Share your Channel. Doporučení - + Create Collection... @@ -23396,7 +22828,7 @@ Select the Friends with which you want to Share your Channel. Stáhnou podle souboru kolekce... - + Some files have been omitted because they have not been indexed yet. @@ -23456,7 +22888,7 @@ Select the Friends with which you want to Share your Channel. Message - + Zpráva @@ -23539,12 +22971,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration Načítám nastavení - + Create interface Vytvářím rozhraní @@ -23568,7 +23000,7 @@ Select the Friends with which you want to Share your Channel. Zapamatovat heslo - + Log In Přihlásit se @@ -23909,7 +23341,7 @@ This choice can be reverted in settings. Zpráva o statusu - + Message: Zpráva: @@ -24146,7 +23578,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags Odstranit všechny štítky @@ -24182,12 +23614,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown @@ -24197,18 +23632,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -24218,12 +23648,57 @@ p, li { white-space: pre-wrap; } - + + Error + Chyba + + + + Not connected + Nespojen + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -24231,7 +23706,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -24241,7 +23716,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -24252,11 +23727,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -24284,7 +23760,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options @@ -24295,7 +23771,7 @@ p, li { white-space: pre-wrap; } Maximální počet současných stahování: - + Shared Directories @@ -24305,22 +23781,27 @@ p, li { white-space: pre-wrap; } Automaticky sdílet příchozí adresář (doporučeno) - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -24405,7 +23886,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -24414,7 +23895,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -24439,7 +23925,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming Streamování @@ -24504,12 +23995,7 @@ p, li { white-space: pre-wrap; } - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -24519,7 +24005,17 @@ p, li { white-space: pre-wrap; } - + + Warning + Upozornění + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -24547,7 +24043,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed Stahování dokončeno @@ -24575,19 +24071,19 @@ p, li { white-space: pre-wrap; } TransfersDialog - - + + Downloads Stahování - + Uploads Odesílání - + Name i.e: file name Jméno @@ -24794,7 +24290,12 @@ p, li { white-space: pre-wrap; } Zvolit... - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... Přesunout do fronty... @@ -24819,7 +24320,7 @@ p, li { white-space: pre-wrap; } Zvolte adresář - + Anonymous end-to-end encrypted tunnel 0x @@ -24840,7 +24341,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -24873,7 +24374,17 @@ p, li { white-space: pre-wrap; } Stahování souboru %1 ještě není dokončeno. Pokud jde o soubor médií (hudba, filmy, ...), můžete se zkusit podívat na jeho náhled. - + + Warning + Upozornění + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name Změnit jméno souboru @@ -24888,7 +24399,7 @@ p, li { white-space: pre-wrap; } Prosím vložte nové--a platné--jméno souboru - + Expand all Rozbalit vše @@ -25015,23 +24526,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Sloupce - + File Transfers - + Path Cesta @@ -25041,7 +24547,7 @@ p, li { white-space: pre-wrap; } - + Could not delete preview file @@ -25051,7 +24557,7 @@ p, li { white-space: pre-wrap; } - + Create Collection... @@ -25066,7 +24572,7 @@ p, li { white-space: pre-wrap; } - + Collection Kolekce @@ -25076,7 +24582,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x @@ -25490,12 +24996,17 @@ p, li { white-space: pre-wrap; } Formulář - + Enable Retroshare WEB Interface - + + Status: + Status: + + + Web parameters @@ -25535,17 +25046,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -25555,12 +25076,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface @@ -25697,11 +25218,7 @@ p, li { white-space: pre-wrap; } Stránky Wiki - New Group - Nová skupina - - - + Page Name @@ -25716,7 +25233,7 @@ p, li { white-space: pre-wrap; } - + << @@ -25804,7 +25321,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History @@ -25839,7 +25356,7 @@ p, li { white-space: pre-wrap; } - + \/ @@ -25869,14 +25386,18 @@ p, li { white-space: pre-wrap; } Štítky - - + + History + Historie + + + Show Edit History - + Status Status @@ -25897,7 +25418,7 @@ p, li { white-space: pre-wrap; } - + Submit @@ -25980,16 +25501,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - - - - + Settings @@ -26004,7 +25516,7 @@ p, li { white-space: pre-wrap; } Ostatní - + Who to Follow @@ -26024,7 +25536,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -26054,25 +25566,17 @@ p, li { white-space: pre-wrap; } - New - Nový - - - + Yourself - - Friends - Kontakty - Following - + RetroShare RetroShare @@ -26135,35 +25639,42 @@ p, li { white-space: pre-wrap; } Formulář - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + Odebrat + + + Location: Umístění: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -26208,11 +25719,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + nedostupné + + + + Following + + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Neznámý @@ -26290,7 +25831,7 @@ p, li { white-space: pre-wrap; } %1 r. %2 d. - + k e.g: 3.1 k k @@ -26327,7 +25868,7 @@ p, li { white-space: pre-wrap; } pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_da.ts b/retroshare-gui/src/lang/retroshare_da.ts index 41f99845c..4cb8c0823 100644 --- a/retroshare-gui/src/lang/retroshare_da.ts +++ b/retroshare-gui/src/lang/retroshare_da.ts @@ -121,12 +121,12 @@ - + Search Criteria - + Add a further search criterion. @@ -136,7 +136,7 @@ - + Cancels the search. @@ -540,7 +540,7 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. @@ -566,10 +566,23 @@ p, li { white-space: pre-wrap; } + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb @@ -612,7 +625,7 @@ p, li { white-space: pre-wrap; } - + Set your Avatar picture @@ -699,7 +712,7 @@ p, li { white-space: pre-wrap; } - + Always on Top @@ -718,10 +731,6 @@ p, li { white-space: pre-wrap; } % Opaque - - Cancel - Annuller - Since: @@ -799,7 +808,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment @@ -829,12 +838,12 @@ p, li { white-space: pre-wrap; } - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -842,7 +851,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up @@ -862,7 +871,7 @@ p, li { white-space: pre-wrap; } - + Posted by @@ -900,7 +909,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up @@ -920,7 +929,7 @@ p, li { white-space: pre-wrap; } - + Click to view picture @@ -950,7 +959,7 @@ p, li { white-space: pre-wrap; } - + Toggle Message Read Status @@ -960,7 +969,7 @@ p, li { white-space: pre-wrap; } - + TextLabel @@ -968,12 +977,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this - + 0 @@ -993,18 +1002,18 @@ p, li { white-space: pre-wrap; } - + New Comment - + Copy RetroShare Link - + Expand @@ -1019,12 +1028,12 @@ p, li { white-space: pre-wrap; } - + Name Navn - + Comm value @@ -1193,17 +1202,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels - + Tabs - + General @@ -1213,7 +1222,17 @@ p, li { white-space: pre-wrap; } - + + Downloads + + + + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab @@ -1221,7 +1240,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1244,7 +1263,7 @@ into the image, so as to ChannelsCommentsItem - + I like this @@ -1269,18 +1288,18 @@ into the image, so as to - + New Comment - + Copy RetroShare Link - + Expand @@ -1295,7 +1314,7 @@ into the image, so as to - + Name Navn @@ -1305,17 +1324,7 @@ into the image, so as to - - Comment - - - - - Comments - - - - + Hide @@ -1323,7 +1332,7 @@ into the image, so as to ChatLobbyDialog - + Name Navn @@ -1514,7 +1523,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby @@ -1547,13 +1556,14 @@ into the image, so as to - + + Unknown Lobby - - + + Remove All @@ -1561,13 +1571,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Navn - + Count @@ -1577,29 +1587,7 @@ into the image, so as to - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - - - - - - Public chat rooms - - - - + Create chat room @@ -1609,7 +1597,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1666,12 +1654,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1681,23 +1669,42 @@ Double click a chat room to enter and chat. - + [No topic provided] - + + Private Subscribed + + + + + + Public Subscribed + + + + + Private - + + + Public - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted @@ -1707,27 +1714,22 @@ Double click a chat room to enter and chat. - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe - + Search Chat lobbies - + Search Name - + Columns @@ -1742,47 +1744,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: - + Type: - + Security: - + Peers: - - - - - - + + + + + + TextLabel @@ -1797,7 +1799,7 @@ Double click a chat room to enter and chat. - + Show @@ -1817,7 +1819,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item @@ -1862,7 +1864,7 @@ Double click a chat room to enter and chat. ChatPage - + General @@ -1877,7 +1879,7 @@ Double click a chat room to enter and chat. - + Enable custom fonts @@ -1897,7 +1899,7 @@ Double click a chat room to enter and chat. - + General settings @@ -1922,7 +1924,7 @@ Double click a chat room to enter and chat. - + Blink tab icon @@ -1952,7 +1954,7 @@ Double click a chat room to enter and chat. - + Change Chat Font @@ -1962,7 +1964,7 @@ Double click a chat room to enter and chat. - + History @@ -1986,7 +1988,7 @@ Double click a chat room to enter and chat. - + Choose your default font for Chat. @@ -2056,12 +2058,22 @@ Double click a chat room to enter and chat. - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2071,7 +2083,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2168,7 +2190,7 @@ Double click a chat room to enter and chat. - + Case sensitive Forskel på store og små bogstaver @@ -2274,7 +2296,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat @@ -2310,7 +2332,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close @@ -2345,12 +2367,12 @@ Double click a chat room to enter and chat. - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2430,11 +2452,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2472,7 +2489,7 @@ Double click a chat room to enter and chat. - + is typing... @@ -2494,7 +2511,7 @@ after HTML conversion. - + Do you really want to physically delete the history? @@ -2544,7 +2561,7 @@ after HTML conversion. - + Find Case Sensitively @@ -2566,7 +2583,7 @@ after HTML conversion. - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> @@ -2581,12 +2598,12 @@ after HTML conversion. - + (Status) - + Attach a File @@ -2602,12 +2619,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> - + Person id: @@ -2618,12 +2635,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. @@ -2643,7 +2660,7 @@ Double click on it to add his name on text writer. - + Don't stop to color after @@ -2669,7 +2686,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: @@ -2691,7 +2708,7 @@ Double click on it to add his name on text writer. - + Personal Circles @@ -2717,7 +2734,7 @@ Double click on it to add his name on text writer. - + Friends @@ -2777,7 +2794,7 @@ Double click on it to add his name on text writer. - + External Circles (Admin) @@ -2793,7 +2810,7 @@ Double click on it to add his name on text writer. - + Circles @@ -2845,45 +2862,45 @@ Double click on it to add his name on text writer. - + RetroShare RetroShare - + - + Error : cannot get peer details. - + Retroshare ID - + <p>This Retroshare ID contains: - + <p>This certificate contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: @@ -2893,7 +2910,7 @@ Double click on it to add his name on text writer. - + Not connected @@ -2975,12 +2992,17 @@ Double click on it to add his name on text writer. - + <li>a <b>node ID</b> and <b>name</b> - + + <b>DNS:</b> : + + + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3000,7 +3022,7 @@ Double click on it to add his name on text writer. - + with @@ -3068,7 +3090,7 @@ Double click on it to add his name on text writer. - + @@ -3084,12 +3106,12 @@ Double click on it to add his name on text writer. - + Peer details - + Name: Navn: @@ -3099,17 +3121,17 @@ Double click on it to add his name on text writer. - + Options Indstillinger - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: @@ -3119,7 +3141,7 @@ Double click on it to add his name on text writer. - + Please paste below your friend's Retroshare ID @@ -3144,12 +3166,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with - + Sorry, some error appeared @@ -3169,32 +3201,27 @@ Double click on it to add his name on text writer. - + Key validity: - + Profile ID: - - Signers - - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. - + To accept the Friend Request, click the Accept button. @@ -3240,17 +3267,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed - + Not a valid Retroshare certificate! - + RetroShare Invitation @@ -3270,12 +3297,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3283,7 +3310,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3323,7 +3350,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Profile password needed. @@ -3348,7 +3375,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3358,7 +3385,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3397,7 +3424,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + IP-Addr: @@ -3407,7 +3434,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Show Advanced options @@ -3432,7 +3459,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already in your keyring @@ -3445,7 +3472,7 @@ even if you don't make friends. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. @@ -3480,7 +3507,7 @@ even if you don't make friends. - + No IP in this certificate! @@ -3490,12 +3517,7 @@ even if you don't make friends. - - [Unknown] - - - - + Added with certificate from %1 @@ -3560,7 +3582,7 @@ even if you don't make friends. - + UDP Setup @@ -3588,7 +3610,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant @@ -3598,17 +3620,20 @@ p, li { white-space: pre-wrap; } - + + Unknown State - + + Offline - + + Behind Symmetric NAT @@ -3618,12 +3643,14 @@ p, li { white-space: pre-wrap; } - + + NET Restart - + + Behind NAT @@ -3633,7 +3660,8 @@ p, li { white-space: pre-wrap; } - + + NET STATE GOOD! @@ -3658,7 +3686,7 @@ p, li { white-space: pre-wrap; } - + Lookup requires DHT @@ -3950,7 +3978,7 @@ p, li { white-space: pre-wrap; } - + @@ -3958,7 +3986,8 @@ p, li { white-space: pre-wrap; } - + + UNVERIFIABLE FORWARD! @@ -3968,7 +3997,7 @@ p, li { white-space: pre-wrap; } - + Searching @@ -4004,12 +4033,12 @@ p, li { white-space: pre-wrap; } - + Name Navn - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4029,7 +4058,7 @@ p, li { white-space: pre-wrap; } - + IDs @@ -4049,18 +4078,18 @@ p, li { white-space: pre-wrap; } - + Cancel Annuller - + Nickname - + Invited Members @@ -4075,7 +4104,7 @@ p, li { white-space: pre-wrap; } - + Name: Navn: @@ -4115,19 +4144,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - + Please set a name for your Circle - + No Restriction Circle Selected @@ -4137,12 +4166,24 @@ p, li { white-space: pre-wrap; } - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add @@ -4152,7 +4193,7 @@ p, li { white-space: pre-wrap; } - + Search @@ -4205,13 +4246,13 @@ p, li { white-space: pre-wrap; } - + Create - + Add Member @@ -4230,7 +4271,7 @@ p, li { white-space: pre-wrap; } - + Group Name: @@ -4265,7 +4306,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post @@ -4275,7 +4316,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4420,17 +4461,17 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -4455,7 +4496,12 @@ p, li { white-space: pre-wrap; } - + + Cannot publish post + + + + Load thumbnail picture @@ -4470,18 +4516,12 @@ p, li { white-space: pre-wrap; } - - + Generate mass data - - Do you really want to generate %1 messages ? - - - - + You are about to add files you're not actually sharing. Do you still want this to happen? @@ -4515,7 +4555,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message @@ -4525,7 +4565,16 @@ p, li { white-space: pre-wrap; } - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> + + + + Attach File @@ -4540,16 +4589,7 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> - - - - + Attach a Picture @@ -4564,7 +4604,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4594,17 +4634,17 @@ p, li { white-space: pre-wrap; } - + No Forum - + In Reply to - + Title @@ -4657,7 +4697,7 @@ Do you want to discard this message? - + No compatible ID for this forum @@ -4667,8 +4707,8 @@ Do you want to discard this message? - - + + Generate mass data @@ -4691,7 +4731,7 @@ Do you want to discard this message? CreateLobbyDialog - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -4726,7 +4766,7 @@ Do you want to discard this message? - + Create @@ -4736,7 +4776,7 @@ Do you want to discard this message? Annuller - + require PGP-signed identities @@ -4751,7 +4791,7 @@ Do you want to discard this message? - + Create Chat Room @@ -4772,7 +4812,7 @@ Do you want to discard this message? - + Identity to use: @@ -4780,17 +4820,17 @@ Do you want to discard this message? CryptoPage - + Public Information - + Name: Navn: - + Location: @@ -4800,12 +4840,12 @@ Do you want to discard this message? - + Software Version: - + Online since: @@ -4825,12 +4865,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -4840,7 +4875,7 @@ Do you want to discard this message? - + Other Information @@ -4850,17 +4885,12 @@ Do you want to discard this message? - + Profile - - Certificate - - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -4870,7 +4900,7 @@ Do you want to discard this message? - + Export Identity @@ -4940,33 +4970,33 @@ and use the import button to load it - + TextLabel - + PGP fingerprint: - - Node information - - - - + PGP Id : - + Friend nodes: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5056,7 +5086,7 @@ and use the import button to load it DLListDelegate - + B @@ -5724,7 +5754,7 @@ and use the import button to load it DownloadToaster - + Start file @@ -5732,38 +5762,38 @@ and use the import button to load it ExprParamElement - + - + to - + ignore case - - - dd.MM.yyyy + + + yyyy-MM-dd - - + + KB - - + + MB - - + + GB @@ -5771,12 +5801,12 @@ and use the import button to load it ExpressionWidget - + Expression Widget - + Delete this expression @@ -5938,7 +5968,7 @@ and use the import button to load it FilesDefs - + Picture @@ -5948,7 +5978,7 @@ and use the import button to load it - + Audio @@ -6008,11 +6038,21 @@ and use the import button to load it C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories @@ -6134,7 +6174,7 @@ and use the import button to load it - + ID @@ -6176,7 +6216,7 @@ and use the import button to load it - + Group @@ -6212,7 +6252,7 @@ and use the import button to load it - + Search @@ -6228,7 +6268,7 @@ and use the import button to load it - + Profile details @@ -6465,7 +6505,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request @@ -6503,7 +6543,7 @@ at least one peer was not added to a group - + Mark all @@ -6514,16 +6554,132 @@ at least one peer was not added to a group + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Navn + + + + Node ID + + + + + Address + + + + + Status + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message - - + + Broadcast @@ -6606,33 +6762,38 @@ at least one peer was not added to a group - + Keyring - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. - - + + Network - + + Friend Server + + + + Network graph - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. @@ -6650,7 +6811,17 @@ at least one peer was not added to a group - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters @@ -6660,17 +6831,12 @@ at least one peer was not added to a group - + Port - - Use BOB - - - - + This password is for PGP @@ -6691,38 +6857,38 @@ at least one peer was not added to a group - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -6742,12 +6908,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -6757,38 +6923,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel - + hidden address - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -6832,13 +7003,13 @@ and use the import button to load it - + Import profile - + Create new profile and new Retroshare node @@ -6848,7 +7019,7 @@ and use the import button to load it - + Tor/I2P address @@ -6883,7 +7054,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -6893,12 +7064,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -6908,12 +7074,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7139,27 +7300,13 @@ and use the import button to load it - + Invite Friends - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - - - - + Add Your Friends to RetroShare @@ -7169,39 +7316,57 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + Connect To Friends - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port @@ -7209,49 +7374,45 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - - - - + Further Help and Support - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website @@ -7276,7 +7437,7 @@ p, li { white-space: pre-wrap; } - + RetroShare Invitation @@ -7326,12 +7487,12 @@ p, li { white-space: pre-wrap; } - + RetroShare Support - + It has many features, including built-in chat, messaging, @@ -7455,7 +7616,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat @@ -7463,7 +7624,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] @@ -7633,7 +7794,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title @@ -7646,12 +7807,12 @@ p, li { white-space: pre-wrap; } - + Description - + Number of Unread message @@ -7676,7 +7837,7 @@ p, li { white-space: pre-wrap; } - + You are admin (modify names and description using Edit menu) @@ -7691,14 +7852,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post - + Name Navn @@ -7709,13 +7870,13 @@ p, li { white-space: pre-wrap; } - + Never - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -7728,7 +7889,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and @@ -7864,7 +8025,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels @@ -7875,22 +8036,22 @@ p, li { white-space: pre-wrap; } - + Enable Auto-Download - + My Channels - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels @@ -7910,12 +8071,12 @@ p, li { white-space: pre-wrap; } - + Disable Auto-Download - + Set download directory @@ -7950,22 +8111,22 @@ p, li { white-space: pre-wrap; } - + Play - + Open folder - + Open file - + Error @@ -7985,17 +8146,17 @@ p, li { white-space: pre-wrap; } - + Are you sure that you want to cancel and delete the file? - + Can't open folder - + Play File @@ -8008,7 +8169,7 @@ p, li { white-space: pre-wrap; } GxsChannelGroupDialog - + Create New Channel @@ -8046,8 +8207,18 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel @@ -8062,7 +8233,7 @@ p, li { white-space: pre-wrap; } - + Expand @@ -8077,7 +8248,7 @@ p, li { white-space: pre-wrap; } - + Loading @@ -8091,6 +8262,11 @@ p, li { white-space: pre-wrap; } New Channel: + + + Never + + Hide @@ -8100,7 +8276,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: @@ -8121,7 +8297,7 @@ p, li { white-space: pre-wrap; } - + Play @@ -8183,18 +8359,18 @@ p, li { white-space: pre-wrap; } - + New - + 0 - - + + Comment @@ -8209,17 +8385,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + Comments - + Post @@ -8247,13 +8423,13 @@ p, li { white-space: pre-wrap; } GxsChannelPostsWidgetWithModel - + Post to Channel - + Add new post @@ -8323,7 +8499,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -8359,7 +8535,7 @@ p, li { white-space: pre-wrap; } - + Comments @@ -8374,13 +8550,13 @@ p, li { white-space: pre-wrap; } - - + + Click to switch to list view - + Show unread posts only @@ -8395,7 +8571,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -8410,7 +8586,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -8470,12 +8646,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -8550,12 +8736,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed @@ -8606,17 +8793,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -8731,7 +8918,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container @@ -8744,7 +8931,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -8774,7 +8961,7 @@ p, li { white-space: pre-wrap; } - + Comment @@ -8813,7 +9000,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment @@ -8837,6 +9024,21 @@ p, li { white-space: pre-wrap; } Vote Down + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -8846,7 +9048,7 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -8875,7 +9077,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -8906,7 +9108,7 @@ before you can comment - + It remains %1 characters after HTML conversion. @@ -8957,7 +9159,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum @@ -8973,7 +9175,7 @@ before you can comment - + Expand @@ -8992,6 +9194,11 @@ before you can comment Moderator list + + + TextLabel + + Loading... @@ -9021,13 +9228,13 @@ before you can comment GxsForumMsgItem - - + + Subject: - + Unsubscribe To Forum @@ -9038,7 +9245,7 @@ before you can comment - + Expand @@ -9058,17 +9265,17 @@ before you can comment - + Loading... - + Forum Feed - + Hide @@ -9081,59 +9288,66 @@ before you can comment - + Start new Thread for Selected Forum - + + Threaded + + + + + + + ... + + + + + Flat + + + + + Latest post in thread + + + + Search forums - + New Thread - - - Threaded View - - - - - Flat View - - - + Title - - + + Date - + Author - - Save image - - - - + Loading - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9143,12 +9357,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message @@ -9188,23 +9397,23 @@ before you can comment - + No name - - + + Reply - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -9247,12 +9456,12 @@ before you can comment - + Hide - + [unknown] @@ -9282,8 +9491,8 @@ before you can comment - - + + Distribution @@ -9366,12 +9575,12 @@ before you can comment - + New thread - + Edit @@ -9432,7 +9641,7 @@ before you can comment - + Show column @@ -9452,7 +9661,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive @@ -9504,7 +9713,7 @@ This message is missing. You should receive it later. - + No result. @@ -9514,7 +9723,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -9529,7 +9738,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -9595,12 +9804,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums @@ -9635,12 +9844,12 @@ This message is missing. You should receive it later. GxsGroupDialog - + Name Navn - + Key recipients can publish to restricted-type group and can view and publish for private-type channels @@ -9651,12 +9860,12 @@ This message is missing. You should receive it later. - + Description - + Message Distribution @@ -9664,7 +9873,7 @@ This message is missing. You should receive it later. - + Public @@ -9724,7 +9933,7 @@ This message is missing. You should receive it later. - + Comments: @@ -9747,7 +9956,7 @@ This message is missing. You should receive it later. - + All People @@ -9763,12 +9972,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -9785,23 +9994,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -9817,22 +10026,28 @@ This message is missing. You should receive it later. - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo - + Submit Group Changes - + Owner: @@ -9842,12 +10057,12 @@ This message is missing. You should receive it later. - + Info - + ID @@ -9857,7 +10072,7 @@ This message is missing. You should receive it later. - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -9932,7 +10147,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity @@ -9948,27 +10168,22 @@ This message is missing. You should receive it later. - + Created - + Cancel Annuller - + Create - - Author - - - - + GxsIdLabel @@ -9976,7 +10191,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading @@ -10036,7 +10251,7 @@ This message is missing. You should receive it later. - + Synchronise posts of last... @@ -10093,12 +10308,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link @@ -10121,7 +10336,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature @@ -10134,14 +10349,14 @@ This message is missing. You should receive it later. GxsIdDetails - + Not found - - + + [Banned] @@ -10151,7 +10366,7 @@ This message is missing. You should receive it later. - + Loading... @@ -10161,7 +10376,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -10181,6 +10401,14 @@ This message is missing. You should receive it later. + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -10192,7 +10420,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -10240,7 +10468,7 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] @@ -10627,7 +10855,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -10643,7 +10871,7 @@ p, li { white-space: pre-wrap; } - + Authors @@ -10662,7 +10890,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -10736,7 +10964,7 @@ p, li { white-space: pre-wrap; } - + Add friend @@ -10746,7 +10974,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -10774,7 +11002,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -10784,7 +11012,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard @@ -10794,7 +11022,7 @@ private and secure decentralized communication platform. - + Send via Email @@ -10814,13 +11042,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -10832,12 +11084,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -10852,12 +11104,7 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... @@ -11122,14 +11369,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All - + Reputation @@ -11139,12 +11386,12 @@ p, li { white-space: pre-wrap; } - + Anonymous Id - + Create new Identity @@ -11154,7 +11401,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -11169,27 +11416,27 @@ p, li { white-space: pre-wrap; } - + Close - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -11205,29 +11452,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles - + Circle name @@ -11247,18 +11504,20 @@ p, li { white-space: pre-wrap; } - + + Edit identity - + + Delete identity - + Chat with this peer @@ -11268,78 +11527,78 @@ p, li { white-space: pre-wrap; } - + Owner node ID : - + Identity name : - + () - + Identity ID - + Send message - + Identity info - + Identity ID : - + Owner node name : - + Create new... - + Type: - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: - + Negative - + Neutral @@ -11350,17 +11609,17 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous @@ -11375,24 +11634,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you - - + + My own identities - - + + My contacts - + Show Items @@ -11407,7 +11666,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -11417,7 +11681,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -11492,7 +11756,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -11522,7 +11786,7 @@ p, li { white-space: pre-wrap; } - + Invited @@ -11537,7 +11801,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle @@ -11585,7 +11849,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -11593,7 +11857,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -11636,7 +11900,7 @@ These identities will soon be not supported anymore. - + Boards @@ -11716,7 +11980,7 @@ These identities will soon be not supported anymore. - + information @@ -11732,17 +11996,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -11847,7 +12106,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -11897,21 +12156,21 @@ These identities will soon be not supported anymore. - - - + + + People - + Your Avatar Click here to change your avatar - + Linked to neighbor nodes @@ -11921,7 +12180,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -11936,7 +12195,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -11951,12 +12210,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -11976,12 +12235,12 @@ These identities will soon be not supported anymore. - + Owned by - + Node name: @@ -11991,7 +12250,7 @@ These identities will soon be not supported anymore. - + Really delete? @@ -11999,7 +12258,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname @@ -12029,7 +12288,13 @@ These identities will soon be not supported anymore. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity @@ -12043,7 +12308,7 @@ These identities will soon be not supported anymore. - + @@ -12053,7 +12318,12 @@ These identities will soon be not supported anymore. - + + No avatar chosen + + + + Edit identity @@ -12064,27 +12334,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -12104,7 +12374,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -12114,12 +12384,18 @@ These identities will soon be not supported anymore. - + Error KeyID invalid - + + + No Avatar chosen. A default image will be automatically displayed from your new identity. + + + + Import image @@ -12129,12 +12405,7 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. - - - - + Unknown GpgId @@ -12144,7 +12415,7 @@ These identities will soon be not supported anymore. - + Create New Identity @@ -12154,10 +12425,15 @@ These identities will soon be not supported anymore. - + Choose image... + + + Remove + + @@ -12183,7 +12459,7 @@ These identities will soon be not supported anymore. - + Create @@ -12193,13 +12469,13 @@ These identities will soon be not supported anymore. Annuller - + Your Avatar Click here to change your avatar - + Linked to your profile @@ -12209,7 +12485,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -12283,7 +12559,7 @@ These identities will soon be not supported anymore. - + Copy Kopiér @@ -12293,12 +12569,12 @@ These identities will soon be not supported anymore. - + %1 's Message History - + Mark all @@ -12321,18 +12597,34 @@ These identities will soon be not supported anymore. ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -12350,27 +12642,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: - + Listen Address: - + + Status: + + + + 127.0.0.1 - + Token: @@ -12391,7 +12688,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -12400,26 +12702,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File - + Open Folder - + Checking... @@ -12429,7 +12736,7 @@ These identities will soon be not supported anymore. - + Recommend in a message to... @@ -12457,7 +12764,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend @@ -12473,7 +12780,8 @@ These identities will soon be not supported anymore. - + + Options Indstillinger @@ -12494,7 +12802,7 @@ These identities will soon be not supported anymore. - + Quit @@ -12505,12 +12813,12 @@ These identities will soon be not supported anymore. - + RetroShare %1 a secure decentralized communication platform - + Unfinished @@ -12535,11 +12843,12 @@ These identities will soon be not supported anymore. + Status - + Notify @@ -12550,31 +12859,35 @@ These identities will soon be not supported anymore. + Open Messages - + + Bandwidth Graph - + Applications + Help - + + Minimize - + Maximize @@ -12589,7 +12902,12 @@ These identities will soon be not supported anymore. RetroShare - + + Close window + + + + %1 new message @@ -12619,7 +12937,7 @@ These identities will soon be not supported anymore. - + Do you really want to exit RetroShare ? @@ -12639,7 +12957,7 @@ These identities will soon be not supported anymore. - + Make sure this link has not been forged to drag you to a malicious website. @@ -12684,12 +13002,13 @@ These identities will soon be not supported anymore. - + + Statistics - + Show web interface @@ -12704,7 +13023,7 @@ These identities will soon be not supported anymore. - + Really quit ? @@ -12713,17 +13032,17 @@ These identities will soon be not supported anymore. MessageComposer - + Compose - + Contacts - + Paragraph @@ -12759,12 +13078,12 @@ These identities will soon be not supported anymore. - + Font size - + Increase font size @@ -12779,32 +13098,32 @@ These identities will soon be not supported anymore. - + Italic - + Alignment - + Add an Image - + Sets text font to code style - + Underline - + Subject: @@ -12815,32 +13134,32 @@ These identities will soon be not supported anymore. - + Tags - + Address list: - + Recommend this friend - + Set Text color - + Set Text background color - + Recommended Files @@ -12910,7 +13229,7 @@ These identities will soon be not supported anymore. - + Send To: @@ -12950,7 +13269,7 @@ These identities will soon be not supported anymore. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> @@ -12970,18 +13289,18 @@ These identities will soon be not supported anymore. - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team - - + + Save Message - + Message has not been Sent. Do you want to save message to draft box? @@ -12992,7 +13311,17 @@ Do you want to save message to draft box? - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" @@ -13012,7 +13341,7 @@ Do you want to save message to draft box? - + Original Message @@ -13022,21 +13351,21 @@ Do you want to save message to draft box? - + - + To - - + + Cc - + Sent @@ -13051,7 +13380,7 @@ Do you want to save message to draft box? - + Re: @@ -13061,30 +13390,30 @@ Do you want to save message to draft box? - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? - + Please insert at least one recipient. - + Bcc - + Unknown @@ -13199,13 +13528,13 @@ Do you want to save message to draft box? Detaljer - + Open File... - + HTML-Files (*.htm *.html);;All Files (*) @@ -13225,7 +13554,7 @@ Do you want to save message to draft box? - + Message has not been Sent. Do you want to save message ? @@ -13246,7 +13575,7 @@ Do you want to save message ? - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -13276,18 +13605,18 @@ Do you want to save message ? - - + + Close - + From: Fra: - + Bullet list (disc) @@ -13327,13 +13656,13 @@ Do you want to save message ? - - + + Thanks, <br> - + Distant identity: @@ -13343,12 +13672,12 @@ Do you want to save message ? - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -13426,7 +13755,7 @@ Do you want to save message ? - + A new tab @@ -13436,7 +13765,7 @@ Do you want to save message ? - + Edit Tag @@ -13459,7 +13788,7 @@ Do you want to save message ? MessageToaster - + Sub: @@ -13467,7 +13796,7 @@ Do you want to save message ? MessageUserNotify - + Message @@ -13495,7 +13824,7 @@ Do you want to save message ? MessageWidget - + Recommended Files @@ -13505,37 +13834,37 @@ Do you want to save message ? - + Subject: - + From: Fra: - + To: Til: - + Cc: - + Bcc: - + Tags: - + Reply @@ -13575,7 +13904,7 @@ Do you want to save message ? - + Send Invite @@ -13627,7 +13956,7 @@ Do you want to save message ? - + Confirm %1 as friend @@ -13637,12 +13966,12 @@ Do you want to save message ? - + View source - + No subject @@ -13652,17 +13981,22 @@ Do you want to save message ? - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -13671,14 +14005,24 @@ Do you want to save message ? %1 (%2) + + + Show less + + + + + Show more + + - + Download all - + Print Document @@ -13693,12 +14037,12 @@ Do you want to save message ? - + Load images always for this message - + Hide the attachment pane @@ -13798,7 +14142,7 @@ Do you want to save message ? MessagesDialog - + New Message @@ -13808,16 +14152,16 @@ Do you want to save message ? - + - - + + Tags - - + + Inbox @@ -13847,17 +14191,17 @@ Do you want to save message ? - + Total Inbox: - + Quick View - + Print... @@ -13888,7 +14232,7 @@ Do you want to save message ? - + Subject @@ -13898,7 +14242,7 @@ Do you want to save message ? - + Date @@ -13908,7 +14252,7 @@ Do you want to save message ? - + Search Subject @@ -13917,6 +14261,16 @@ Do you want to save message ? Search From + + + To + + + + + Search To + + Search Date @@ -13943,12 +14297,12 @@ Do you want to save message ? - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred @@ -14024,7 +14378,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -14038,7 +14392,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -14053,18 +14407,28 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts - + No Box selected. - + @@ -14099,7 +14463,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -14153,7 +14527,7 @@ Do you want to save message ? - + Expand @@ -14163,7 +14537,7 @@ Do you want to save message ? - + from @@ -14198,7 +14572,7 @@ Do you want to save message ? - + Hide @@ -14339,7 +14713,7 @@ Do you want to save message ? - + Remove unused keys... @@ -14349,7 +14723,7 @@ Do you want to save message ? - + Clean keyring @@ -14363,7 +14737,13 @@ Notes: Your old keyring will be backed up. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info @@ -14396,18 +14776,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. - - - Export/create a new node - - Trusted keys only - + Search name @@ -14417,12 +14792,12 @@ For security, your keyring was previously backed-up to file - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -14455,7 +14830,7 @@ Reported error: NewFriendList - + Offline Friends @@ -14476,7 +14851,7 @@ Reported error: - + Groups @@ -14506,19 +14881,19 @@ Reported error: - - + + Search - + ID - + Search ID @@ -14528,12 +14903,12 @@ Reported error: - + Show Items - + Last contact @@ -14543,7 +14918,7 @@ Reported error: - + Group @@ -14658,7 +15033,7 @@ Reported error: - + Do you want to remove this node? @@ -14668,7 +15043,7 @@ Reported error: - + Done! @@ -14775,7 +15150,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -14790,7 +15165,7 @@ at least one peer was not added to a group - + Newest on top @@ -14800,12 +15175,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15043,7 +15418,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -15063,12 +15438,12 @@ at least one peer was not added to a group - + Please enter your Retroshare passphrase - + Unregistered plugin/executable @@ -15083,7 +15458,7 @@ at least one peer was not added to a group - + Test @@ -15094,17 +15469,19 @@ at least one peer was not added to a group + Unknown title - + + Encrypted message - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -15112,7 +15489,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online @@ -15251,7 +15628,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -15296,12 +15678,7 @@ p, li { white-space: pre-wrap; } - - Options - Indstillinger - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -15347,21 +15724,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - - + + Error : cannot get peer details. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) @@ -15379,7 +15756,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -15448,10 +15825,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Check the password! - - Maybe password is wrong - Måske password er forkert - You haven't set a trust level for this key. @@ -15459,12 +15832,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -15490,7 +15863,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat @@ -15511,7 +15884,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Name: Navn: @@ -15551,7 +15924,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message @@ -15609,7 +15982,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Send Message @@ -15927,17 +16300,17 @@ p, li { white-space: pre-wrap; } - + My Albums - + Subscribed Albums - + Shared Albums @@ -15966,7 +16339,7 @@ requesting to edit it! PhotoSlideShow - + Album Name @@ -16025,19 +16398,19 @@ requesting to edit it! - - + + TextLabel - + Posted by - + ago @@ -16073,12 +16446,12 @@ requesting to edit it! PluginItem - + TextLabel - + Show more details about this plugin @@ -16289,12 +16662,27 @@ p, li { white-space: pre-wrap; } - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -16347,7 +16735,7 @@ p, li { white-space: pre-wrap; } - + Vote up @@ -16367,8 +16755,8 @@ p, li { white-space: pre-wrap; } - - + + Comments @@ -16393,13 +16781,13 @@ p, li { white-space: pre-wrap; } - - + + Comment - + Comments @@ -16427,12 +16815,12 @@ p, li { white-space: pre-wrap; } PostedCreatePostDialog - + Create a new Post - + RetroShare RetroShare @@ -16447,12 +16835,22 @@ p, li { white-space: pre-wrap; } - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File - + Post image @@ -16468,7 +16866,17 @@ p, li { white-space: pre-wrap; } - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -16478,7 +16886,7 @@ p, li { white-space: pre-wrap; } - + Please add a Title @@ -16498,12 +16906,22 @@ p, li { white-space: pre-wrap; } - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -16518,7 +16936,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -16529,7 +16947,7 @@ p, li { white-space: pre-wrap; } - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -16539,7 +16957,7 @@ p, li { white-space: pre-wrap; } - + Link @@ -16547,12 +16965,12 @@ p, li { white-space: pre-wrap; } PostedDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -16586,7 +17004,7 @@ p, li { white-space: pre-wrap; } PostedGroupDialog - + Create New Board @@ -16624,7 +17042,17 @@ p, li { white-space: pre-wrap; } PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted @@ -16640,7 +17068,7 @@ p, li { white-space: pre-wrap; } - + Expand @@ -16655,12 +17083,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + + Never + + + + New Board @@ -16673,18 +17106,18 @@ p, li { white-space: pre-wrap; } PostedItem - + 0 - - + + Comments - + Copy RetroShare Link @@ -16695,12 +17128,12 @@ p, li { white-space: pre-wrap; } - + Comment - + Comments @@ -16710,7 +17143,7 @@ p, li { white-space: pre-wrap; } - + Click to view Picture @@ -16720,17 +17153,17 @@ p, li { white-space: pre-wrap; } - + Vote up - + Vote down - + Set as read and remove item @@ -16740,7 +17173,7 @@ p, li { white-space: pre-wrap; } - + New Comment: @@ -16750,7 +17183,7 @@ p, li { white-space: pre-wrap; } - + Name Navn @@ -16791,18 +17224,11 @@ p, li { white-space: pre-wrap; } - + Loading - - PostedListWidget - - RetroShare - RetroShare - - PostedListWidgetWithModel @@ -16821,7 +17247,17 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 @@ -16831,15 +17267,15 @@ p, li { white-space: pre-wrap; } - + - + unknown - + Distribution: @@ -16849,42 +17285,42 @@ p, li { white-space: pre-wrap; } - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -16904,7 +17340,7 @@ p, li { white-space: pre-wrap; } - + Search @@ -16934,17 +17370,17 @@ p, li { white-space: pre-wrap; } - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -16959,12 +17395,17 @@ p, li { white-space: pre-wrap; } - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -16974,27 +17415,31 @@ p, li { white-space: pre-wrap; } - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -17009,7 +17454,7 @@ p, li { white-space: pre-wrap; } - + Never @@ -17083,6 +17528,16 @@ p, li { white-space: pre-wrap; } No Channel Selected + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -17172,16 +17627,16 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -17289,7 +17744,7 @@ and use the import button to load it ProfileWidget - + Edit status message @@ -17305,7 +17760,7 @@ and use the import button to load it - + Public Information @@ -17340,12 +17795,12 @@ and use the import button to load it - + Other Information - + My Address @@ -17389,27 +17844,27 @@ and use the import button to load it PulseAddDialog - + Add to Pulse - + Display As - + URL - + GroupLabel - + IDLabel @@ -17419,12 +17874,12 @@ and use the import button to load it Fra: - + Head - + Head Shot @@ -17454,13 +17909,13 @@ and use the import button to load it - - + + Whats happening? - + @@ -17472,12 +17927,22 @@ and use the import button to load it - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -17492,7 +17957,7 @@ and use the import button to load it - + Reply to Pulse @@ -17507,20 +17972,25 @@ and use the import button to load it - + Like Pulse - + Hide Pictures - + Add Pictures + + + Load Picture File + + PulseMessage @@ -17530,7 +18000,7 @@ and use the import button to load it - + @@ -17549,7 +18019,7 @@ and use the import button to load it PulseReply - + icn @@ -17559,7 +18029,7 @@ and use the import button to load it - + REPLY @@ -17586,7 +18056,7 @@ and use the import button to load it - + FOLLOW @@ -17596,7 +18066,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -17616,7 +18086,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -17732,7 +18202,7 @@ and use the import button to load it - + FOLLOW @@ -17740,37 +18210,42 @@ and use the import button to load it PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -17802,7 +18277,7 @@ and use the import button to load it - + FOLLOW @@ -17810,8 +18285,8 @@ and use the import button to load it QObject - - + + Confirmation @@ -18079,12 +18554,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + File Request canceled - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. @@ -18115,7 +18590,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + Cannot start Tor Manager! @@ -18149,7 +18624,7 @@ The error reported is:" - + Multiple instances @@ -18168,6 +18643,26 @@ The error reported is:" + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -18247,7 +18742,7 @@ Reported error is: - + You appear to have nodes associated to DSA keys: @@ -18257,7 +18752,7 @@ Reported error is: - + enabled @@ -18267,7 +18762,7 @@ Reported error is: - + Move IP %1 to whitelist @@ -18283,7 +18778,7 @@ Reported error is: - + %1 seconds ago @@ -18350,7 +18845,7 @@ Security: no anonymous IDs - + Join chat room @@ -18378,7 +18873,7 @@ Security: no anonymous IDs - + Indefinitely @@ -18558,13 +19053,29 @@ Security: no anonymous IDs Ban list + + + Name + Navn + - Status + Node + Address + + + + + + Status + + + + NXS @@ -18807,6 +19318,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -18946,7 +19469,7 @@ p, li { white-space: pre-wrap; } - + Network Wide @@ -19113,7 +19636,7 @@ p, li { white-space: pre-wrap; } - + The loading of embedded images is blocked. @@ -19126,7 +19649,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default @@ -19299,12 +19822,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -19312,12 +19845,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -20005,7 +20538,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name Navn @@ -20126,7 +20659,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name Navn @@ -20146,7 +20679,7 @@ If you believe it is correct, remove the corresponding line from the file and re - + Profile ID @@ -20202,7 +20735,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -20216,11 +20749,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - - RsMessageModel @@ -20234,6 +20762,11 @@ prevents the message to be forwarded to your friends. From + + + To + + Subject @@ -20256,12 +20789,17 @@ prevents the message to be forwarded to your friends. - Click to sort by read + Click to sort by read status - Click to sort by from + Click to sort by author + + + + + Click to sort by destination @@ -20285,7 +20823,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -20306,7 +20846,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. @@ -20367,7 +20907,7 @@ prevents the message to be forwarded to your friends. - + Unable to open log file '%1': %2 @@ -20388,7 +20928,7 @@ prevents the message to be forwarded to your friends. - + opmode @@ -20418,7 +20958,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -20436,7 +20976,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -20453,12 +20993,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) - + Start Search @@ -20519,7 +21059,7 @@ prevents the message to be forwarded to your friends. - + KeyWords @@ -20534,7 +21074,7 @@ prevents the message to be forwarded to your friends. - + Filename @@ -20634,23 +21174,23 @@ prevents the message to be forwarded to your friends. - + File Name - + Download - + Copy RetroShare Link - + Send RetroShare Link @@ -20660,7 +21200,7 @@ prevents the message to be forwarded to your friends. - + Download Notice @@ -20697,7 +21237,7 @@ prevents the message to be forwarded to your friends. - + Folder @@ -20708,17 +21248,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) - + Open Folder - + Create Collection... @@ -20738,7 +21278,7 @@ prevents the message to be forwarded to your friends. - + Collection @@ -20746,7 +21286,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details @@ -20762,22 +21302,22 @@ prevents the message to be forwarded to your friends. - + IP address: - + Peer ID: - + Location: - + Peer Name: @@ -20794,7 +21334,7 @@ prevents the message to be forwarded to your friends. - + but reported: @@ -20819,8 +21359,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -20828,7 +21368,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare @@ -20859,7 +21399,7 @@ prevents the message to be forwarded to your friends. - + Expand @@ -20904,12 +21444,12 @@ prevents the message to be forwarded to your friends. - + Write Message - + Connect Attempt @@ -20929,17 +21469,12 @@ prevents the message to be forwarded to your friends. - + Unknown Security Issue - - A unknown peer - - - - + Unknown @@ -20949,7 +21484,17 @@ prevents the message to be forwarded to your friends. - + + SSL request + + + + + An unknown peer + + + + Hide @@ -20959,7 +21504,7 @@ prevents the message to be forwarded to your friends. - + Certificate has wrong signature!! This peer is not who he claims to be. @@ -20969,12 +21514,12 @@ prevents the message to be forwarded to your friends. - + Certificate caused an internal error. - + Peer/node not in friendlist (PGP id= @@ -21033,12 +21578,12 @@ prevents the message to be forwarded to your friends. - + Local Address Lokale Adresse - + NAT @@ -21059,22 +21604,22 @@ prevents the message to be forwarded to your friends. - + Local network - + External ip address finder - + UPnP - + Known / Previous IPs: @@ -21087,21 +21632,16 @@ behind a firewall or a VPN. - - Allow RetroShare to ask my ip to these websites: - - - - - - + + + kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -21111,23 +21651,46 @@ behind a firewall or a VPN. - + Onion Address - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -21137,7 +21700,7 @@ behind a firewall or a VPN. - + I2P Address @@ -21162,37 +21725,95 @@ behind a firewall or a VPN. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -21207,71 +21828,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -21281,22 +21838,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -21308,12 +21850,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -21323,7 +21865,7 @@ Also check your ports! - + Download limit (KB/s) @@ -21338,23 +21880,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -21365,17 +21907,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -21385,12 +21917,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -21400,17 +21927,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -21450,7 +21967,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start @@ -21465,12 +21982,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - BOB status - - - - + Incoming @@ -21506,7 +22018,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -21561,7 +22098,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Warning: This bandwidth adds up to the max bandwidth. @@ -21586,7 +22123,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -21598,7 +22135,7 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Filters @@ -21621,7 +22158,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status @@ -21681,17 +22218,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -21707,18 +22255,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -21753,12 +22301,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -21781,22 +22329,22 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -21831,7 +22379,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -21841,12 +22389,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -21926,7 +22474,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with @@ -21936,12 +22484,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Share - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -21960,7 +22508,7 @@ Select the Friends with which you want to Share your Channel. - + Shared directory @@ -21980,17 +22528,17 @@ Select the Friends with which you want to Share your Channel. - + Add new - + Cancel Annuller - + Add a Share Directory @@ -22000,7 +22548,7 @@ Select the Friends with which you want to Share your Channel. - + Apply and close @@ -22091,7 +22639,7 @@ Select the Friends with which you want to Share your Channel. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. @@ -22099,7 +22647,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files @@ -22150,11 +22698,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files - + Download selected @@ -22164,7 +22717,7 @@ Select the Friends with which you want to Share your Channel. - + Copy retroshare Links to Clipboard @@ -22179,7 +22732,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted @@ -22195,7 +22748,7 @@ Select the Friends with which you want to Share your Channel. - + Create Collection... @@ -22220,7 +22773,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted because they have not been indexed yet. @@ -22363,12 +22916,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration - + Create interface @@ -22392,7 +22945,7 @@ Select the Friends with which you want to Share your Channel. - + Log In Log ind @@ -22731,7 +23284,7 @@ This choice can be reverted in settings. - + Message: @@ -22968,7 +23521,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags @@ -23004,12 +23557,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown @@ -23019,18 +23575,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -23040,12 +23591,57 @@ p, li { white-space: pre-wrap; } - + + Error + + + + + Not connected + + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -23053,7 +23649,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -23063,7 +23659,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -23074,11 +23670,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -23106,7 +23703,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options @@ -23117,7 +23714,7 @@ p, li { white-space: pre-wrap; } - + Shared Directories @@ -23127,22 +23724,27 @@ p, li { white-space: pre-wrap; } - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -23227,7 +23829,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -23236,7 +23838,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -23261,7 +23868,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming @@ -23326,12 +23938,7 @@ p, li { white-space: pre-wrap; } - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -23341,7 +23948,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -23369,7 +23986,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed @@ -23397,19 +24014,19 @@ p, li { white-space: pre-wrap; } TransfersDialog - - + + Downloads - + Uploads - + Name i.e: file name Navn @@ -23616,7 +24233,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... @@ -23641,7 +24263,7 @@ p, li { white-space: pre-wrap; } - + Anonymous end-to-end encrypted tunnel 0x @@ -23662,7 +24284,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -23695,7 +24317,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name @@ -23710,7 +24342,7 @@ p, li { white-space: pre-wrap; } - + Expand all @@ -23837,23 +24469,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns - + File Transfers - + Path @@ -23863,7 +24490,7 @@ p, li { white-space: pre-wrap; } - + Could not delete preview file @@ -23873,7 +24500,7 @@ p, li { white-space: pre-wrap; } - + Create Collection... @@ -23888,7 +24515,7 @@ p, li { white-space: pre-wrap; } - + Collection @@ -23898,7 +24525,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x @@ -24312,12 +24939,17 @@ p, li { white-space: pre-wrap; } - + Enable Retroshare WEB Interface - + + Status: + + + + Web parameters @@ -24357,17 +24989,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -24377,12 +25019,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface @@ -24519,7 +25161,7 @@ p, li { white-space: pre-wrap; } - + Page Name @@ -24534,7 +25176,7 @@ p, li { white-space: pre-wrap; } - + << @@ -24622,7 +25264,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History @@ -24657,7 +25299,7 @@ p, li { white-space: pre-wrap; } - + \/ @@ -24687,14 +25329,18 @@ p, li { white-space: pre-wrap; } - - + + History + + + + Show Edit History - + Status @@ -24715,7 +25361,7 @@ p, li { white-space: pre-wrap; } - + Submit @@ -24798,12 +25444,7 @@ p, li { white-space: pre-wrap; } - - Refresh - - - - + Settings @@ -24818,7 +25459,7 @@ p, li { white-space: pre-wrap; } - + Who to Follow @@ -24838,7 +25479,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -24868,7 +25509,7 @@ p, li { white-space: pre-wrap; } - + Yourself @@ -24878,7 +25519,7 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare @@ -24941,35 +25582,42 @@ p, li { white-space: pre-wrap; } - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + + + + Location: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -25014,11 +25662,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + + + + + Following + + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) @@ -25096,7 +25774,7 @@ p, li { white-space: pre-wrap; } - + k e.g: 3.1 k @@ -25133,7 +25811,7 @@ p, li { white-space: pre-wrap; } pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_de.qm b/retroshare-gui/src/lang/retroshare_de.qm index 8c2ee9aa1..f33befdf9 100644 Binary files a/retroshare-gui/src/lang/retroshare_de.qm and b/retroshare-gui/src/lang/retroshare_de.qm differ diff --git a/retroshare-gui/src/lang/retroshare_de.ts b/retroshare-gui/src/lang/retroshare_de.ts index 4fa1bb85b..e37c020a9 100644 --- a/retroshare-gui/src/lang/retroshare_de.ts +++ b/retroshare-gui/src/lang/retroshare_de.ts @@ -56,7 +56,7 @@ Max score: %1 - + Höchstpunktzahl: %1 @@ -81,14 +81,7 @@ Only Hidden Node - - - - - AddCommentDialog - - Add Comment - Kommentar hinzufügen + Nur Hidden knoten @@ -129,12 +122,12 @@ RetroShare: Erweiterte Suche - + Search Criteria Suchkriterien - + Add a further search criterion. Ein weiteres Suchkriterium hinzufügen. @@ -144,7 +137,7 @@ Suchkriterien zurücksetzen. - + Cancels the search. Bricht die Suche ab. @@ -164,177 +157,6 @@ Suchen - - AlbumCreateDialog - - Create Album - Album erstellen - - - Album Name: - Albumname - - - Category: - Kategorie: - - - Animals - Tiere - - - Family - Familie - - - Friends - Freunde - - - Flowers - Blumen - - - Holiday - Urlaub - - - Landscapes - Landschaften - - - Pets - Haustiere - - - Portraits - Porträts - - - Travel - Reise - - - Work - Arbeit - - - Random - Zufall - - - Caption: - Überschrift: - - - Where: - Wo: - - - Photographer: - Fotograf: - - - Description: - Beschreibung: - - - Share Options - Freigabeeinstellungen - - - Policy: - Richtlinie: - - - Quality: - Qualität: - - - Comments: - Kommentare - - - Identity: - Identität - - - Public - Öffentlich - - - Restricted - Eingeschränkt - - - Resize Images (< 1Mb) - Bildgröße ändern (< 1Mb) - - - Resize Images (< 10Mb) - Bildgröße ändern (< 10Mb) - - - Send Original Images - Originalbilder senden - - - No Comments Allowed - Keine Kommentare erlaubt - - - Authenticated Comments - Authentifizierte Kommentare - - - Any Comments Allowed - Jegliche Kommentare erlaubt - - - Publish with Identity - Mit Identität veröffentlichen - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Füge Bilder per Drag 'n' Drop ein. Klicke auf ein Bild, um die darunter stehenden Details zu bearbeiten.</span></p></body></html> - - - Back - Zurück - - - Add Photos - Fotos hinzufügen - - - Publish Album - Album veröffentlichen - - - Untitle Album - Albumtitel entfernen - - - Say something about this album... - Sage etwas über dieses Album... - - - Where were these taken? - Wo wurden diese aufgenommen? - - - Load Album Thumbnail - Albumvorschau laden - - AlbumDialog @@ -343,19 +165,11 @@ p, li { white-space: pre-wrap; } Album Album - - Album Thumbnail - Albumvorschau - TextLabel TextLabel - - Summary - Zusammenfassung - Album Title: @@ -364,41 +178,13 @@ p, li { white-space: pre-wrap; } Category: - Kategorie + Kategorie: Caption Überschrift - - Where: - Wo: - - - When - Wann: - - - Description: - Beschreibung - - - Share Options - Freigabeeinstellungen - - - Comments - Kommentare - - - Publish Identity - Veröffentlichungsidentität - - - Visibility - Sichtbarkeit - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -438,57 +224,57 @@ p, li { white-space: pre-wrap; } Form - Formular + Formular Quality: - Qualität: + Qualität: Embedded Only (<50Kb) - + Nur eingebettet (<50 KB) Share Original Images - + Orginal Bild teilen Copy Original Images (extra disk space) - + Originalbilder kopieren (zusätzlicher Speicherplatz) Resize Images (< 200Kb) - Bildgröße ändern (< 10Mb) {200K?} + Bildgröße ändern (< 10Mb) {200K?} Resize Images (< 1Mb) - Bildgröße ändern (< 1Mb) + Bildgröße ändern (< 1Mb) Caption: - Überschrift: + Überschrift: Photographer: - Fotograf: + Fotograf: Where: - Wo: + Wo: When: - + Wann: @@ -496,37 +282,37 @@ p, li { white-space: pre-wrap; } Create New Album - + Neues Album erstellen Create - Erstellen + Erstellen Album - Album + Album Edit ALbum - + Album bearbeiten Update Album - + Album aktualisieren Add Album Admins - + Album-Administratoren hinzufügen Select Album Admins - + Album-Admins auswählen @@ -635,7 +421,7 @@ p, li { white-space: pre-wrap; } Choose the style of Tool Buttons. - Wähle den Stil für die Werkzeugschaltflächen + Wähle den Stil für die Werkzeugschaltflächen. @@ -670,22 +456,22 @@ p, li { white-space: pre-wrap; } Show Toaster Disable - + Toaster-Deaktivierung anzeigen Show Sound Status - + Sound Status anzeigen Show Network Rate Status - + Netzwerkrate anzeigen Show Discovery Status - + Entdeckungsstatus anzeigen @@ -695,7 +481,7 @@ p, li { white-space: pre-wrap; } Show Hashing Status - + Hashing Status anzeigen @@ -705,17 +491,17 @@ p, li { white-space: pre-wrap; } Show Peer Status - + Peer Status anzeigen Show Status ComboBox - + Status ComboBox anzeigen Remove surplus text in status bar. - Überschüssigen Text aus Statusleiste entfernen + Überschüssigen Text aus Statusleiste entfernen. @@ -725,7 +511,7 @@ p, li { white-space: pre-wrap; } Show Operating Mode Status - + Betriebsmodusstatus anzeigen @@ -735,12 +521,12 @@ p, li { white-space: pre-wrap; } Disable SysTray ToolTip - + SysTray Kurzinfo deaktivieren Main page items: - + Hauptseitenelemente: @@ -750,7 +536,7 @@ p, li { white-space: pre-wrap; } Item list - + Item Liste @@ -767,10 +553,10 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. - Warnung: Diese Dienste sind experimentell. Bitte hilf uns sie zu testen. + Warnung: Diese Dienste sind experimentell. Bitte hilf uns sie zu testen. Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Protokolle ändern. @@ -783,14 +569,6 @@ Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Proto Circles Kreise - - GxsForums - Gxs-Foren - - - GxsChannels - Gxs-Kanäle - The Wire @@ -802,10 +580,23 @@ Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Proto Fotos + + AspectRatioPixmapLabel + + + Save image + Bild speichern + + + + Copy image + Bild kopieren + + AttachFileItem - + %p Kb %p KiB @@ -830,7 +621,7 @@ Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Proto TextLabel - TextLabel + TextLabel @@ -840,11 +631,7 @@ Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Proto Browse... - - - - Add Avatar - Avatar hinzufügen + Durchsuchen... @@ -852,28 +639,24 @@ Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Proto Entfernen - + Set your Avatar picture Dein Avatarbild festlegen Import image - + Bild importieren Image files (*.jpg *.png);;All files (*) - + Bilddateien (*.jpg *.png);;Alle Dateien (*) Use the mouse to zoom and adjust the image for your avatar. - - - - Load Avatar - Avatar laden + Benutzen Sie die Maus, um das Bild für Ihren Avatar zu vergrößern und anzupassen. @@ -910,22 +693,22 @@ Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Proto PushButton - + Up - Hoch + Hoch Down - Herunter + Herunter Clears the graph - + Grafik zurücksetzen @@ -935,7 +718,7 @@ Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Proto TextLabel - TextLabel + TextLabel @@ -943,22 +726,10 @@ Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Proto Zurücksetzen - Receive Rate - Empfangsrate - - - Send Rate - Senderate - - - + Always on Top Immer im Vordergrund - - Style - Stil - Changes the transparency of the Bandwidth Graph @@ -974,23 +745,11 @@ Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Proto % Opaque % undurchsichtig - - Save - Speichern - - - Cancel - Abbrechen - Since: Seit: - - Hide Settings - Einstellungen verbergen - BandwidthStatsWidget @@ -1024,7 +783,7 @@ Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Proto Total - + Insgesamt @@ -1037,275 +796,275 @@ Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Proto Filename - Dateiname + Dateiname Hash - Prüfsumme + Prüfsumme Size - Größe + Größe Banned since... - + Gesperrt seit... Remove - Entfernen + Entfernen BoardPostDisplayWidgetBase - + Comment - Kommentar + Kommentar 1 comment - + 1 Kommentar %1 comments - + %1 Kommentare No comments yet. Click to add one. - + Noch keine Kommentare. Klicken Sie, um einen hinzuzufügen. Loading - + Lade Copy RetroShare Link - RetroShare-Link kopieren + RetroShare-Link kopieren - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + <p><font color="#ff0000"><b>Der Autor dieser Nachricht (mit der ID %1) ist gesperrt.</b> - + ago - + vor BoardPostDisplayWidget_card - + Vote up - Daumen hoch + Daumen hoch 0 - 0 + 0 Vote down - Daumen runter + Daumen runter \/ - \/ + \/ - + Posted by - + Gepostet von Toggle Message Read Status - Lesestatus der Nachricht umschalten + Lesestatus der Nachricht umschalten New - Neu + Neu PictureLabel - + TextLabel - TextLabel + TextLabel Comments - Kommentare + Kommentare Share - + Teilen BoardPostDisplayWidget_compact - + Vote up - Daumen hoch + Daumen hoch 0 - 0 + 0 Vote down - Daumen runter + Daumen runter \/ - \/ + \/ - + Click to view picture - + Zum Betrachten des Bildes anklicken PictureLabel_compact - + Posted by - + Gepostet von Comments - Kommentare + Kommentare Expand - Erweitern + Erweitern Share - + Teilen - + Toggle Message Read Status - Lesestatus der Nachricht umschalten + Lesestatus der Nachricht umschalten New - Neu + Neu - + TextLabel - TextLabel + TextLabel BoardsCommentsItem - + I like this - Das gefällt mir + Das gefällt mir - + 0 - 0 + 0 I dislike this - Das gefällt mir nicht + Das gefällt mir nicht Toggle Message Read Status - Lesestatus der Nachricht umschalten + Lesestatus der Nachricht umschalten Avatar - Avatar + Avatar - + New Comment - + Neuer Kommentar - + Copy RetroShare Link - RetroShare-Link kopieren + RetroShare-Link kopieren - + Expand - Erweitern + Erweitern Set as read and remove item - Als gelesen markieren und Eintrag entfernen + Als gelesen markieren und Eintrag entfernen Remove Item - + Eintrag entfernen - + Name - Name + Name - + Comm value - + Comment - Kommentar + Kommentar Comments - + Kommentare Hide - Verbergen + Verbergen @@ -1426,77 +1185,83 @@ Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Proto Legend: - + Legende: Current - + Aktuell Total - + Gesamt Log scale - + Log skalieren Default - Standard + Standard Dark - + Dunkel ChannelPage - + Channels Kanäle - + Tabs Reiter - + General Allgemein Load Emoticons - + Emoticons laden - Load posts in background (Thread) - Beiträge im Hintergrund laden (Thread) + + Downloads + Downloads - + + Maximum Auto Download Size (in GBs) + Maximale Größe des automatischen Downloads (in GB) + + + Open each channel in a new tab - Jeden Kanal in einem neuen Reiter öffnen. + Jeden Kanal in einem neuen Reiter öffnen ChannelPostDelegate - + files - + Dateien file - + Datei @@ -1506,92 +1271,84 @@ Aber denke daran, dass alle Daten hier VERLOREN gehen werden, wenn wir die Proto Use mouse to center and zoom into the image, so as to crop it for your post. - + Benutzen Sie die Maus zum Zentrieren und Zoomen +in das Bild hinein, um es für + um es für Ihren Beitrag anzupassen. ChannelsCommentsItem - + I like this - Das gefällt mir + Das gefällt mir 0 - 0 + 0 I dislike this - Das gefällt mir nicht + Das gefällt mir nicht Toggle Message Read Status - Lesestatus der Nachricht umschalten + Lesestatus der Nachricht umschalten Avatar - Avatar + Avatar - + New Comment - + Neuer Kommentar - + Copy RetroShare Link - RetroShare-Link kopieren + RetroShare-Link kopieren - + Expand - Erweitern + Erweitern Set as read and remove item - Als gelesen markieren und Eintrag entfernen + Als gelesen markieren und Eintrag entfernen Remove Item - + Artikel entfernen - + Name - Name + Name Comm value - + - - Comment - Kommentar - - - - Comments - - - - + Hide - Verbergen + Verbergen ChatLobbyDialog - + Name Name @@ -1608,7 +1365,7 @@ into the image, so as to Ban this person (Sets negative opinion) - + Diese Person verbannen (setzt negative Meinung) @@ -1658,12 +1415,12 @@ into the image, so as to This participant is not active since: - Teilnehmer inaktiv seit: + Teilnehmer inaktiv seit: seconds - Sekunden + Sekunden @@ -1673,17 +1430,17 @@ into the image, so as to Give neutral opinion - + Neutrale Meinung abgeben Give positive opinion - + Eine positive Meinung abgeben Show author in people tab - + Autor auf der Registerkarte Personen anzeigen @@ -1693,18 +1450,18 @@ into the image, so as to Leave this chat room (Unsubscribe) - + Diesen Chatraum verlassen (Abmelden) Welcome to chat room %1 - + Willkommen im Chatraum %1 Room chat - + Chatraum @@ -1751,7 +1508,7 @@ into the image, so as to Chat room management - + Chatraum-Verwaltung @@ -1766,23 +1523,23 @@ into the image, so as to Do you want to unsubscribe to this chat room? - + Möchten Sie sich von diesem Chatraum abmelden? Redock to Main window - + Zurückdocken zum Hauptfenster Undock to a new window - + Abdocken in ein neues Fenster ChatLobbyToaster - + Show Chat Lobby Chatlobby anzeigen @@ -1794,50 +1551,35 @@ into the image, so as to Chats Chats - - You have %1 new messages - Du hast %1 neue Nachrichten - - - You have %1 new message - Du hast %1 neue Nachricht - - - %1 new messages - %1 neue Nachrichten - - - %1 new message - %1 neue Nachricht - You have %1 mentions - + Sie haben %1 Erwähnungen You have %1 mention - + Sie haben %1 Erwähnung %1 mentions - + %1 Erwähnungen %1 mention - + %1 Erwähnung - + + Unknown Lobby Unbekannte Lobby - - + + Remove All Alle entfernen @@ -1845,13 +1587,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Name - + Count Anzahl @@ -1861,29 +1603,7 @@ into the image, so as to Thema - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - Private Chaträume - - - - - Public chat rooms - Öffentliche Chaträume - - - + Create chat room Chatraum erstellen @@ -1893,14 +1613,14 @@ into the image, so as to Diesen Raum verlassen - + Create a non anonymous identity and enter this room Create an identity and enter this chat room - + Erstellen Sie eine Identität und betreten Sie diesen Chatraum @@ -1910,12 +1630,12 @@ into the image, so as to Enter this chat room as... - + Diesen Chatraum betreten als... Copy RetroShare Link - RetroShare-Link kopieren + RetroShare-Link kopieren @@ -1950,12 +1670,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + %1 lädt dich in den Chatraum namens %2 ein - + Choose a non anonymous identity for this chat room: @@ -1965,31 +1685,31 @@ Double click a chat room to enter and chat. - Create chat lobby - Chatlobby erstellen - - - + [No topic provided] [Kein Thema angegeben] - Selected lobby info - Info zur ausgewählten Lobby - - - + + Private Privat - + + + Public Öffentlich - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted Anonyme Kennungen akzeptiert @@ -1999,42 +1719,25 @@ Double click a chat room to enter and chat. Autom. Abonnement entfernen - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe Autom. Abonnement hinzufügen - + Search Chat lobbies Chatlobbys durchsuchen - + Search Name Name durchsuchen - Subscribed - Abonniert - - - + Columns Spalten - - Yes - Ja - - - No - Nein - Chat rooms @@ -2046,47 +1749,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: Chatraumname: - + Chat room Id: Chatraumkennung: - + Topic: Thema: - + Type: Typ: - + Security: Sicherheit: - + Peers: Nachbarn: - - - - - - + + + + + + TextLabel TextLabel @@ -2101,13 +1804,24 @@ Double click a chat room to enter and chat. Keine anonymen Kennungen - + Show Zeige - + + Private Subscribed + Privat abonniert + + + + + Public Subscribed + Öffentlich abonniert + + + column Spalte @@ -2121,7 +1835,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item Eintrag entfernen @@ -2166,46 +1880,22 @@ Double click a chat room to enter and chat. ChatPage - + General Allgemein - - Distant Chat - Fernchat - Everyone Jeder - - Contacts - Kontakte - Nobody Niemand - Accept encrypted distant chat from - Verschlüsselten Fernchat annehmen von - - - Chat Settings - Chat-Einstellungen - - - Enable Emoticons Private Chat - Emoticons für privaten Chat - - - Enable Emoticons Group Chat - Emoticons für Gruppenchat - - - + Enable custom fonts Angepasste Schriftarten aktivieren @@ -2214,10 +1904,6 @@ Double click a chat room to enter and chat. Enable custom font size Angepasste Schriftgröße aktivieren - - Minimum font size - Minimale Schriftgröße - Enable bold @@ -2229,9 +1915,9 @@ Double click a chat room to enter and chat. Kursivschrift aktivieren - + General settings - + Allgemeine Einstellungen @@ -2254,22 +1940,14 @@ Double click a chat room to enter and chat. Eingebettete Bilder laden - Chat Lobby - Chatlobby - - - + Blink tab icon Blinkendes Reitersymbol Do not send typing notifications - - - - Private Chat - Privater Chat + Senden Sie keine Tippbenachrichtigungen @@ -2292,11 +1970,7 @@ Double click a chat room to enter and chat. Blinkendes Fenster/Reitersymbol - Chat Font - Chat-Schriftart - - - + Change Chat Font Chat-Schriftart wählen @@ -2306,14 +1980,10 @@ Double click a chat room to enter and chat. Chat-Schriftart: - + History Verlauf - - Style - Stil - @@ -2328,19 +1998,15 @@ Double click a chat room to enter and chat. Variant: Variante: - - Group chat - Gruppenchat - Private chat Privater Chat - + Choose your default font for Chat. - + Wählen Sie Ihre Standardschriftart für Chat. @@ -2395,140 +2061,152 @@ Double click a chat room to enter and chat. /me is sending a message with /me - + /me sendet eine Nachricht mit /me <html><head/><body><p align="justify">In this tab you can setup how many chat messages Retroshare will keep saved on the disc and how much of the previous conversation it will display, for the different chat systems. The max storage period allows to discard old messages and prevents the chat history from filling up with volatile chat (e.g. chat lobbies and distant chat).</p></body></html> <html><head/><body><p align="justify">In diesem Tab kannst du für die verschiedenen Chatsysteme festlegen, wieviele Nachrichten RetroShare auf Festplatte gespeichert hält, und wieviel der vorangehenden Unterhaltung angezeigt wird. Die maximale Speicherzeit erlaubt das Verwerfen alter Nachrichten und verhindert das unberechenbare Füllen des Unterhaltungsverlaufs (z. B. Chatlobbys und Fernchat).</p></body></html> - - Chatlobbies - Chatlobbys - Enabled: Aktiviert: - + Search - Suchen + Suchen - + + When focus on text browser after showing chat room + Wenn Sie sich auf den Textbrowser konzentrieren, nachdem Sie den Chatraum angezeigt haben + + + + Shrink text edit field when not needed + Textbearbeitungsfeld verkleinern, wenn es nicht benötigt wird + + + Fonts - + Schriftarten Minimum displayed font size - + Angezeigte Mindestschriftgröße - + + If your system is set up correctly, this next square should measure 1 cm. + Wenn Ihr System richtig eingerichtet ist, sollte dieses nächste Quadrat 1 cm messen. + + + + This next square is scaled accordingly to your system font size. + Dieses nächste Quadrat wird entsprechend der Schriftgröße Ihres Systems skaliert. + + + Chat rooms - Chaträume + Chaträume Checked, if the identity and the text above occurrences must be in the same case to trigger count. - + Überprüft, ob die Identität und der Text über den Vorkommen in derselben Groß-/Kleinschreibung vorliegen müssen, um die Zählung auszulösen. Case sensitive search - + Groß- und Kleinschreibung beachten Default identity for chat rooms: - + Standardidentität für Chatrooms: Count all unread messages - Alle ungelesenen Nachrichten zählen + Alle ungelesenen Nachrichten zählen Count occurrences of my current identity - + Zähle Vorkommen meiner aktuellen Identität Count occurrences of any of the following texts (separate by newlines): - + Zählen Sie das Vorkommen eines der folgenden Texte (getrennt durch Zeilenumbrüche): Author: - + Autor: Description: - + Beschreibung: Accept chat from: - + Akzeptiere Chat von: Contacts only - + Nur Kontakte Enable Emoticons - + Emoticons aktivieren Broadcast - Rundschreiben + Rundschreiben Node-to-node chat - + Knoten-Chat Saved messages (0 = unlimited): - Gespeicherte Nachrichten (0 = unbegrenzt) + Gespeicherte Nachrichten (0 = unbegrenzt): Number of messages restored (0 = off): - Anzahl wiederhergestelter Nachrichten (0 = aus) + Anzahl wiederhergestellter Nachrichten (0 = aus): Distant chat - + Distant-Chat Maximum storage period, in days (0=keep all): - Maximale Speicherzeit in Tagen (0 = alle behalten) + Maximale Speicherzeit in Tagen (0 = alle behalten): - Search by default - Suchgrundeinstellung - - - + Case sensitive Groß-/Kleinschreibung unterscheiden @@ -2567,10 +2245,6 @@ Double click a chat room to enter and chat. Threshold for automatic search Grenzwert für automatische Suche - - Default identity for chat lobbies: - Standardidentität für Chatlobbys - Show Bar by default @@ -2599,7 +2273,7 @@ Double click a chat room to enter and chat. Chats - Chats + Chats @@ -2638,7 +2312,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat Chat anzeigen @@ -2653,40 +2327,40 @@ Double click a chat room to enter and chat. You have %1 mentions - + Sie haben %1 Erwähnungen You have %1 mention - + Sie haben %1 Erwähnung %1 mentions - + %1 Erwähnungen %1 mention - + %1 Erwähnung ChatWidget - + Close Schließen Insert sticker - + Sticker einfügen Set font & color - + Schriftart und Farbe einstellen @@ -2709,14 +2383,14 @@ Double click a chat room to enter and chat. Kursiv - + <html><head/><body><p>Chat menu</p></body></html> - + <html><head/><body><p>Chat-Menü</p></body></html> - + Insert emoticon - + Emoticon einfügen @@ -2794,15 +2468,10 @@ Double click a chat room to enter and chat. Insert horizontal rule Horizontale Linie einfügen - - - Save image - Bild speichern - Import sticker - + Sticker importieren @@ -2818,7 +2487,7 @@ Double click a chat room to enter and chat. Don't replace tag with Emote Icon. - + Ersetzen Sie den Tag nicht durch das Emote-Symbol. @@ -2828,15 +2497,15 @@ Double click a chat room to enter and chat. Send as CommonMark - + Als CommonMark senden Text will be formatted using CommonMark. - + Der Text wird mit CommonMark formatiert. - + is typing... tippt... @@ -2851,15 +2520,16 @@ nach der HTML-Konvertierung. Warning: This message is too big of %1 characters after HTML conversion. - + Warnung: Diese Nachricht ist mit %1 Zeichen zu groß +nach der HTML-Konvertierung. Choose your font. - + Wählen Sie Ihre Schriftart. - + Do you really want to physically delete the history? Möchtest du wirklich den Nachrichtenverlauf löschen? @@ -2891,7 +2561,7 @@ after HTML conversion. Messages you send will be delivered after Friend is again Online. - + Die von Ihnen gesendeten Nachrichten werden zugestellt, sobald Ihr Freund wieder online ist. @@ -2909,7 +2579,7 @@ after HTML conversion. antwortet möglicherweise nicht, da der Status auf "Beschäftigt" gesetzt wurde - + Find Case Sensitively Unter Berücksichtigung von Groß-/Kleinschreibung suchen @@ -2931,7 +2601,7 @@ after HTML conversion. Nach Finden von X Elementen mit dem Einfärben nicht aufhören (benötigt mehr CPU) - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> <b>Vorherige finden </b><br/><i>Strg+Umschalt+G</i> @@ -2946,16 +2616,12 @@ after HTML conversion. <b>Finden </b><br/><i>Strg+F</i> - + (Status) (Status) - Set text font & color - Schriftart & Textfarbe festlegen - - - + Attach a File Datei anhängen @@ -2971,30 +2637,31 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> <b>Markiere diesen ausgewählten Text</b><br><i>Strg+M</i> - + Person id: - + Personen-ID: Double click on it to add his name on text writer. - + +Doppelklicken Sie darauf, um seinen Namen im Textschreiber hinzuzufügen. - + Unsigned - + Nicht signiert - + items found. - Elemente gefunden. + Elemente gefunden. @@ -3012,7 +2679,7 @@ Double click on it to add his name on text writer. Hier eine Nachricht eingeben - + Don't stop to color after Nach Finden von @@ -3038,9 +2705,9 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: - Detailanzeige: + Detailanzeige: @@ -3060,7 +2727,7 @@ Double click on it to add his name on text writer. - + Personal Circles Persönliche Kreise @@ -3086,7 +2753,7 @@ Double click on it to add his name on text writer. - + Friends Freunde @@ -3146,7 +2813,7 @@ Double click on it to add his name on text writer. Freunde von Freunden - + External Circles (Admin) Externe Kreise (Admin) @@ -3162,7 +2829,7 @@ Double click on it to add his name on text writer. - + Circles Kreise @@ -3193,7 +2860,7 @@ Double click on it to add his name on text writer. Current address: - + Aktuelle Adresse: @@ -3214,47 +2881,52 @@ Double click on it to add his name on text writer. - + RetroShare RetroShare - + - + Error : cannot get peer details. Fehler: Kann Nachbardetails nicht ermitteln. - + Retroshare ID - + - + <p>This Retroshare ID contains: - + <p>Diese Retroshare-ID enthält: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: + + + <b>DNS:</b> : + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> - + <p>Sie können diese Retroshare ID verwenden, um neue Freunde zu bekommen. Schicken Sie sie per E-Mail, oder geben Sie sie von Hand zu Hand.</p> @@ -3262,7 +2934,7 @@ Double click on it to add his name on text writer. Verschlüsselung - + Not connected Nicht verbunden @@ -3309,12 +2981,12 @@ Double click on it to add his name on text writer. Connectivity - + Konnektivität List of known addresses: - + Liste bekannter Adressen: @@ -3325,12 +2997,12 @@ Double click on it to add his name on text writer. short format - + Kurzformat Include IP history - + IP-Verlauf einbeziehen @@ -3344,25 +3016,17 @@ Double click on it to add his name on text writer. keine - + <p>This certificate contains: <p>Dieses Zertifikat enthält: - + <li>a <b>node ID</b> and <b>name</b> <li>eine <b>Netzknoten-ID</b> und <b>Name</b> - an <b>onion address</b> and <b>port</b> - eine <b>Onion-Adresse</b> und <b>Port</b> - - - an <b>IP address</b> and <b>port</b> - eine <b>IP-Adresse</b> und <b>Port</b> - - - + <p>You can use this certificate to make new friends. Send it by email, or give it hand to hand.</p> Du kannst dieses Zertifikat zum Schließen von neuen Freundschaften verwenden. Versende es per E-Mail oder gib es von Hand zu Hand. @@ -3377,7 +3041,7 @@ Double click on it to add his name on text writer. <html><head/><body><p>Dies ist die Verschlüsselungsmethode die von <span style=" font-weight:600;">OpenSSL</span> benutzt wird. Die Verbindung zu befreundeten Netzknoten ist immer stark verschlüsselt.</p><p>Und wenn DHE vorhanden ist dann verwendet die Verbindung noch dazu</p><p>&quot;Perfect Forward Secrecy&quot;.</p></body></html> - + with mit @@ -3394,104 +3058,16 @@ Double click on it to add his name on text writer. Connect Friend Wizard Assistent um sich zu einem Freund zu verbinden - - Add a new Friend - Einen neuen Freund hinzufügen - - - &You get a certificate file from your friend - &Du hast eine Datei mit einem Zertifikat deines Freund bekommen - - - &Make friend with selected friends of my friends - Ausgewählte Freunde von Freunden hinzu&fügen - - - Include signatures - Signaturen einschließen - - - Copy your Cert to Clipboard - Dein Zertifikat in die Zwischenablage kopieren - - - Save your Cert into a File - Zertifikat als Datei speichern - - - Run Email program - Das Standard-E-Mailprogramm starten - Open Cert of your friend from File - - - - Certificate files - Zertifikat-Dateien - - - Use PGP certificates saved in files. - In Dateien gespeicherte PGP Zertifikate benutzen. - - - Import friend's certificate... - Zertifikat eines Freundes importieren... - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - Du musst eine Datei mit deinem Zertifikat erstellen und deinem Freund zukommen lassen. Alternativ kannst Du auch eine Datei verwenden, die Du zuvor erstellt hast. - - - Export my certificate... - Mein Zertifikat exportieren... - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - Gib die Datei mit dem Zertifikat ein oder ziehe sie per Drag'n'Drop in das Fenster - - - Browse - Durchsuchen - - - Friends of friends - Freunde von Freunden - - - Select now who you want to make friends with. - Wähle nun aus, wen du als Freund hinzufügen möchtest. - - - Show me: - Zeige mir: - - - Make friend with these peers - Diese Nachbarn zu deinen Freunden hinzufügen + Öffnen Sie das Zertifikat Ihres Freundes von der Datei RetroShare ID RetroShare-ID - - Use RetroShare ID for adding a Friend which is available in your network. - RetroShare-ID benutzen, um einen Freund aus deinem Netzwerk hinzuzufügen. - - - Add Friends RetroShare ID... - RetroShare-ID des Freundes einfügen... - - - Paste Friends RetroShare ID in the box below - RetroShare-ID des Freundes in das Feld unten einfügen - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - RetroShare-ID des Freundes eingeben, z. B. Nachbar@BDE8D16A46D938CF - RetroShare is better with Friends @@ -3500,7 +3076,7 @@ Double click on it to add his name on text writer. Invite your Friends from other Networks to RetroShare. - + Laden Sie Ihre Freunde aus anderen Netzwerken zu RetroShare ein. @@ -3533,27 +3109,7 @@ Double click on it to add his name on text writer. E-Mail - Invite Friends by Email - Freunde per E-Mail einladen - - - Enter your friends' email addresses (separate each one with a semicolon) - Gib die E-Mail-Adressen deines Freundes an (mehrere Adressen müssen mit Semikolon getrennt werden) - - - Your friends' email addresses: - E-Mail-Adresse deines Freundes: - - - Enter Friends Email addresses - Gib die E-Mail-Adresse deines Freundes ein - - - Subject: - Betreff: - - - + @@ -3569,60 +3125,32 @@ Double click on it to add his name on text writer. Details der Anfrage - + Peer details Nachbardetails - + Name: Name: - - Email: - E-Mail: - - - Node: - Netzknoten: - Location: Ort: - + Options Optionen - Enter the certificate manually - Zertifikat manuell eingeben - - - Enter RetroShare ID manually - RetroShare-Kennung manuell eingeben - - - Recommend many friends to each other - Viele Freunde einander empfehlen - - - RetroShare certificate - RetroShare-Zertifikat - - - Paste certificate - Zertifikat einfügen - - - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: Freund zur Gruppe hinzufügen: @@ -3632,48 +3160,54 @@ Double click on it to add his name on text writer. Freund authentifizieren (PGP-Schlüssel unterzeichnen) - + Please paste below your friend's Retroshare ID - + Bitte fügen Sie unten die Retroshare-ID Ihres Freundes ein Paste ID of your friend from Clipboard - + ID eines Freundes aus der Zwischenablage einfügen Paste - + Einfügen Open - + Öffnen Please, paste your friend's Retroshare ID into the box below - + Bitte fügen Sie die Retroshare-ID Ihres Freundes in das unten stehende Feld ein - + + Signers: + Unterzeichner: + + + + Known IP: + Bekannte IP: + + + Add as friend to connect with Als Freund hinzufügen, zu dem verbunden wird - To accept the Friend Request, click the Finish button. - Abschließen-Knopf anklicken, um die Anfrage zu akzeptieren - - - + Sorry, some error appeared Entschuldigung, es trat ein Fehler auf Here is the error message: - Dies ist die Fehlermeldung: + Dies ist die Fehlermeldung: @@ -3686,39 +3220,34 @@ Double click on it to add his name on text writer. Details über deinen Freund: - + Key validity: Schlüssel-Gültigkeit: - + Profile ID: - + - - Signers - Unterzeichner - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. Dieser Nachbar ist bereits in deiner Freundliste vorhanden. Das nochmalige Hinzufügen ändert nur seine IP. - + To accept the Friend Request, click the Accept button. - + Um die Freundschaftsanfrage anzunehmen, klicken Sie auf die Schaltfläche Annehmen. Abnormal size read is bigger than memory block. - Größe der eingehenden Daten ist größer als Speicherblock + Größe der eingehenden Daten ist größer als Speicherblock. @@ -3757,49 +3286,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed Das Zertifikat konnte nicht geladen werden - Cannot get peer details of PGP key %1 - Kann Nachbardetails von PGP-Schlüssel %1 nicht abrufen - - - Any peer I've not signed - Jeden Nachbarn, den ich nicht unterzeichnet habe - - - Friends of my friends who already trust me - Freunde meiner Freunde, welche mir schon vertrauen - - - Signed peers showing as denied - Unterzeichnete Nachbarn, die geblockt sind - - - Peer name - Nachbarname - - - Also signed by - Auch unterzeichnet von - - - Peer id - Nachbar-ID - - - Certificate appears to be valid - Zertifikat scheint gültig zu sein - - - + Not a valid Retroshare certificate! Kein gültiges RetroShare-Zertifikat! - + RetroShare Invitation RetroShare-Einladung @@ -3819,27 +3316,27 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + Accept - + Akzeptieren - + This key is already on your trusted list You have already signed this key - + Sie haben diesen Schlüssel bereits unterzeichnet @@ -3872,82 +3369,42 @@ Warning: In your File-Transfer option, you select allow direct download to No.Du hast eine Freundschaftsanfrage von - + Profile password needed. Identity creation failed - + Identitätserstellung fehlgeschlagen Cannot create an identity linked to your profile without your profile password. - + Ohne Ihr Profilpasswort können Sie keine mit Ihrem Profil verknüpfte Identität erstellen. Signature failed - + Unterschrift fehlgeschlagen Signature failed. Uncheck the key signature box if you want to make friends without signing the friends' certificate - + Signatur fehlgeschlagen. Deaktivieren Sie das Kontrollkästchen für die Schlüsselsignatur, wenn Sie Freundschaften schließen möchten, ohne das Zertifikat der Freunde zu signieren - + Valid Retroshare ID - + Gültige Retroshare-ID Valid certificate - + Gültiges Zertifikat - Certificate Load Failed:file %1 not found - Fehler beim Laden des Zertifikats: Datei %1 nicht gefunden - - - This Peer %1 is not available in your Network - Der Nutzer %1 ist nicht in deinem Netzwerk verfügbar - - - Use new certificate format (safer, more robust) - Neues Zertifikatsformat benutzen (sicherer und robuster) - - - Use old (backward compatible) certificate format - Altes (rückwärtskompatibles) Zertifikatsformat benutzen - - - Remove signatures - Signaturen entfernen - - - RetroShare Invite - RetroShare-Einladung - - - Connect Friend Help - Verbindungshilfe - - - You can copy this text and send it to your friend via email or some other way - Du kannst diesen Text kopieren und an deinen Freund per E-Mail senden oder über einen anderen Weg zukommen lassen - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Dein Zertifikat wurde in die Zwischenablage kopiert. Du kannst es per E-Mail oder auf andere Weise an deinen Freund senden. - - - Save as... - Speichern unter... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3986,11 +3443,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.*** Keine *** - Use as direct source, when available - Wenn verfügbar als direkte Quelle nutzen - - - + IP-Addr: IP-Adr.: @@ -4000,7 +3453,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.IP-Adresse - + Show Advanced options Erweiterte Optionen anzeigen @@ -4019,41 +3472,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> - - Recommend many friends to each others - Viele Freunde einander empfehlen - - - Friend Recommendations - Freundempfehlungen - - - Message: - Nachricht: - - - Recommend friends - Freunde empfehlen - - - To - An - - - Please select at least one friend for recommendation. - Bitte mindestens einen Freund als Empfehlung wählen. - - - Please select at least one friend as recipient. - Bitte mindestens einen Empfänger wählen. - Add key to keyring Schlüssel zum Schlüsselbund hinzufügen. - + This key is already in your keyring Schlüssel ist bereits in deinem Schlüsselbund. @@ -4067,7 +3492,7 @@ even if you don't make friends. Selbst wenn ihr euch nicht anfreundet, könnte es nützlich sein, um Fernnachrichten an diesen Teilnehmer zu senden. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. Das Zertifikat hat die falsche Versionsnummer. Beachte, dass v0.6- und v0.5-Netze inkompatibel sind. @@ -4103,7 +3528,7 @@ Das Zertifikat hat die falsche Versionsnummer. Beachte, dass v0.6- und v0.5-Netz IP zu Whitelist hinzufügen - + No IP in this certificate! Zertifikat enthält keine IP! @@ -4113,27 +3538,10 @@ Das Zertifikat hat die falsche Versionsnummer. Beachte, dass v0.6- und v0.5-Netz <p>Dieses Zertifikat enthält keine IP. Du wirst auf Discovery und DHT angewiesen sein un sie herauszufinden. Da du Whitelist-Freigabe forderst wird der Nachbar eine Sicherheitswarnung im Neuigkeitenreiter auslösen. Von dort kannst die die IP freigeben.</p> - - [Unknown] - [Unbekannt] - - - + Added with certificate from %1 Hinzugefügt mit Zertifikat von %1 - - Paste Cert of your friend from Clipboard - Zertifikat deines Freundes aus der Zwischenablage einfügen - - - Certificate Load Failed:can't read from file %1 - Fehler beim Laden des Zertifikats: Datei %1 konnte nicht gelesen werden - - - Certificate Load Failed:something is wrong with %1 - Fehler beim Laden des Zertifikats: Mit %1 stimmt etwas nicht - ConnectProgressDialog @@ -4155,7 +3563,7 @@ Das Zertifikat hat die falsche Versionsnummer. Beachte, dass v0.6- und v0.5-Netz Network - Netzwerk + Netzwerk @@ -4195,7 +3603,7 @@ Das Zertifikat hat die falsche Versionsnummer. Beachte, dass v0.6- und v0.5-Netz - + UDP Setup UDP-Aufbau @@ -4207,7 +3615,7 @@ Das Zertifikat hat die falsche Versionsnummer. Beachte, dass v0.6- und v0.5-Netz Status - Status + Status @@ -4223,7 +3631,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant Verbindungsassistent @@ -4233,17 +3641,20 @@ p, li { white-space: pre-wrap; } Ungültige Peer-ID - + + Unknown State Unbekannter Zustand - + + Offline Offline - + + Behind Symmetric NAT Hinter Symmetrischem NAT @@ -4253,12 +3664,14 @@ p, li { white-space: pre-wrap; } Hinter NAT & kein DHT - + + NET Restart Netzneustart - + + Behind NAT Hinter NAT @@ -4268,7 +3681,8 @@ p, li { white-space: pre-wrap; } Kein DHT - + + NET STATE GOOD! NETZZUSTAND GUT! @@ -4293,7 +3707,7 @@ p, li { white-space: pre-wrap; } RS-Nachbarn werden gesucht - + Lookup requires DHT Suche erfordert DHT @@ -4341,12 +3755,12 @@ p, li { white-space: pre-wrap; } Initial connections can take a while, please be patient - Erstverbindungen können etwas Zeit in Anspruch nehmen. Bitte gedulde dich. + Erstverbindungen können etwas Zeit in Anspruch nehmen. Bitte gedulde dich If an error is detected it will be displayed here - Wenn ein Fehler festgestellt wird, wird er hier angezeigt. + Wenn ein Fehler festgestellt wird, wird er hier angezeigt @@ -4398,7 +3812,7 @@ p, li { white-space: pre-wrap; } DHT Lookup has taken too long - DHT-Suche hat zu lange gedauert. + DHT-Suche hat zu lange gedauert @@ -4408,7 +3822,7 @@ p, li { white-space: pre-wrap; } UDP Connection has taken too long - UDP-Verbindung hat zu lange gedauert. + UDP-Verbindung hat zu lange gedauert @@ -4423,7 +3837,7 @@ p, li { white-space: pre-wrap; } In this case the UDP connection attempt has failed. - In diesem Fall ist der UDP-Verbindungsversuch fehlgeschlagen + In diesem Fall ist der UDP-Verbindungsversuch fehlgeschlagen. @@ -4527,7 +3941,7 @@ p, li { white-space: pre-wrap; } Please contact them to add your Full Certificate - Bitte kontaktiere ihn/sie, damit sie dein vollständiges Zertifikat hinzufügen. + Bitte kontaktiere ihn/sie, damit sie dein vollständiges Zertifikat hinzufügen @@ -4537,7 +3951,7 @@ p, li { white-space: pre-wrap; } They are either offline or their DHT is Off - Er/Sie ist entweder offline oder sein/ihr DHT ist aus. + Er/Sie ist entweder offline oder sein/ihr DHT ist aus @@ -4552,7 +3966,7 @@ p, li { white-space: pre-wrap; } You have previously connected to this Friend - Du warst vorher bereits mit diesem Freund verbunden. + Du warst vorher bereits mit diesem Freund verbunden @@ -4585,7 +3999,7 @@ p, li { white-space: pre-wrap; } Bitte versuche noch einmal ein vollständiges Zertifikat zu importieren - + @@ -4593,7 +4007,8 @@ p, li { white-space: pre-wrap; } N/V - + + UNVERIFIABLE FORWARD! NICHT VERIFIZIERBARE WEITERLEITUNG! @@ -4603,7 +4018,7 @@ p, li { white-space: pre-wrap; } NICHT VERIFIZIERBARE WEITERLEITUNG & KEIN DHT - + Searching Suchen @@ -4615,7 +4030,7 @@ p, li { white-space: pre-wrap; } Only Advanced Retroshare users should switch off the DHT. - Nur fortgeschrittene RetroShare-Benutzer sollten DHT ausschalten + Nur fortgeschrittene RetroShare-Benutzer sollten DHT ausschalten. @@ -4625,7 +4040,7 @@ p, li { white-space: pre-wrap; } They need a Certificate + Node for UDP connections to succeed - Für eine erfolgreiche UDP-Verbindung benötigen sie ein Zertifikat und einen Netzknoten. + Für eine erfolgreiche UDP-Verbindung benötigen sie ein Zertifikat und einen Netzknoten @@ -4639,19 +4054,19 @@ p, li { white-space: pre-wrap; } Kreisdetails - + Name Name - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> - + <html><head/><body><p>Der Kreisname, der Kontaktautor und die Liste der eingeladenen Mitglieder sind für alle eingeladenen Mitglieder sichtbar. Wenn der Kreis nicht privat ist, ist er auch für Nachbarknoten der Knoten sichtbar, die die eingeladenen Mitglieder hosten.</p></body></html> <html><head/><body><p>The creator of a circle is purely optional. It is however useful for public circles so that people know with whom to discuss membership aspects.</p></body></html> - + <html><head/><body><p>Der Ersteller eines Kreises ist rein optional. Es ist jedoch für öffentliche Kreise nützlich, damit die Leute wissen, mit wem sie Mitgliedschaftsaspekte besprechen können.</p></body></html> @@ -4661,22 +4076,22 @@ p, li { white-space: pre-wrap; } Only &visible to members of: - + Nur & sichtbar für Mitglieder von: - + IDs IDs Profile - Profil + Profil Signed by friend node - + Signiert von Freund Knoten @@ -4684,25 +4099,25 @@ p, li { white-space: pre-wrap; } Filter - + Cancel - Abbrechen + Abbrechen - + Nickname Spitzname - + Invited Members Eingeladene Mitglieder <html><head/><body><p>Members of this list will be automatically proposed to join the circle (by accepting membership). They will</p><p>not receive data that is restricted to this circle until they do so.</p></body></html> - + <html><head/><body><p>Mitglieder dieser Liste werden automatisch für den Beitritt zum Kreis vorgeschlagen (durch Annahme der Mitgliedschaft). Sie erhalten</p><p>keine Daten, die auf diesen Kreis beschränkt sind, bis sie dies tun.</p></body></html> @@ -4710,15 +4125,7 @@ p, li { white-space: pre-wrap; } Bekannte Personen - ID - ID - - - Type - Typ - - - + Name: Name: @@ -4740,12 +4147,12 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Publicly distributed circles are visible to your friends, which will get to know the circle data (Creator, members, etc)</p></body></html> - + <html><head/><body><p>Öffentlich verteilte Kreise sind für deine Freunde sichtbar, die dadurch die Daten des Kreises ( Ersteller, Mitglieder, etc)</p></body></html> <html><head/><body><p>Private (a.k.a. self-restricted) circles are only visible to the invited members of these circles. In practice the circle uses its own list of invited members to limit its own distribution. </p></body></html> - + <html><head/><body><p>Private (auch bekannt als selbstbeschränkte) Kreise sind nur für die eingeladenen Mitglieder dieser Kreise sichtbar. In der Praxis verwendet der Kreis seine eigene Liste eingeladener Mitglieder, um seine eigene Verteilung einzuschränken. </p></body></html> @@ -4755,26 +4162,22 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Circles can be restricted to the members of another circle. Only the members of that second circle will be allowed to see the new circle and its content (list of members, etc).</p></body></html> - + <html><head/><body><p>Kreise können auf die Mitglieder eines anderen Kreises beschränkt werden. Nur die Mitglieder dieses zweiten Kreises dürfen den neuen Kreis und seinen Inhalt (Liste der Mitglieder usw.) sehen.</p></body></html> - Only visible to members of: - Nur sichtbar für Mitglieder von: - - - - + + RetroShare RetroShare - + Please set a name for your Circle Bitte einen Namen für deinen Kreis vergeben. - + No Restriction Circle Selected Kein Einschränkungskreis ausgewählt @@ -4784,12 +4187,26 @@ p, li { white-space: pre-wrap; } Keine Einschränkungen für Kreis gewählt - - [Unknown] - [Unbekannt] + + Circle created + Kreis erstellt - + + Your new circle has been created: + Name: %1 + Id: %2. + Ihr neuer Kreis wurde erstellt: + Name: %1 + ID: %2. + + + + [Unknown] + [Unbekannt] + + + Add Hinzufügen @@ -4799,7 +4216,7 @@ p, li { white-space: pre-wrap; } Entfernen - + Search Suchen @@ -4814,10 +4231,6 @@ p, li { white-space: pre-wrap; } Signed Unterzeichnet - - Signed by known nodes - Von bekannten Netzknoten unterzeichnet - Edit Circle @@ -4827,17 +4240,13 @@ p, li { white-space: pre-wrap; } [Anonymous Id] - + [Anonymous ID] PGP Identity PGP-Identität - - Anon Id - Anonyme ID - Circle name @@ -4860,17 +4269,13 @@ p, li { white-space: pre-wrap; } Neuen Kreis erstellen - + Create Erstellen - PGP Linked Id - PGP-verknüpfte ID - - - + Add Member Mitglied hinzufügen @@ -4889,7 +4294,7 @@ p, li { white-space: pre-wrap; } Gruppe erstellen - + Group Name: Gruppenname: @@ -4906,7 +4311,7 @@ p, li { white-space: pre-wrap; } To be defined - + Noch zu definieren @@ -4924,7 +4329,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post Neuer Kanalbeitrag @@ -4934,44 +4339,44 @@ p, li { white-space: pre-wrap; } Kanalbeitrag - + Post - + Posten Cancel - Abbrechen + Abbrechen <html><head/><body><p>Choose aspect ratio policy. In 'Auto' mode, the most suitable aspect ratio is chosen for you.</p></body></html> - + <html><head/><body><p>Wählen Sie das Seitenverhältnis. Im Modus "Auto" wird das am besten geeignete Seitenverhältnis für Sie ausgewählt.</p></body></html> Auto - + 1:1 - 1:1 + 1:1 3:4 - 3:4 + 3:4 16:9 - 16:9 + 16:9 <html><head/><body><p>Remove Thumbnail</p></body></html> - + <html><head/><body><p>Vorschaubild entfernen</p></body></html> @@ -4995,23 +4400,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Benutze Drag & Drop / Datei hinzufügen Knopf, um Hashwert für neue Dateien zu erstellen.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> RetroShare-Links von deinen Freigaben kopieren/einfügen</span></p></body></html> - - Add File to Attach - Datei hinzufügen - Add Channel Thumbnail Miniaturbild hinzufügen - - Message - Nachricht - - - Subject : - Betreff: - @@ -5027,27 +4420,27 @@ p, li { white-space: pre-wrap; } Title - Titel + Titel <html><head/><body><p>Hide</p></body></html> - + <html><head/><body><p>Ausblenden</p></body></html> <html><head/><body><p>Add File</p></body></html> - + <html><head/><body><p>Datei hinzufügen</p></body></html> <html><head/><body><p>Paste retroshare link(s) from clipboard.</p></body></html> - + <html><head/><body><p>Retroshare-Link(s) aus der Zwischenablage einfügen.</p></body></html> <html><head/><body><p>Remove File</p></body></html> - + <html><head/><body><p>Datei entfernen</p></body></html> @@ -5088,7 +4481,7 @@ p, li { white-space: pre-wrap; } Attachments (%1) - + Anhänge (%1) @@ -5097,38 +4490,34 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Diese Datei ist bereits in diesem Beitrag enthalten: - + Post refers to non shared files - + Post bezieht sich auf nicht freigegebene Dateien This post contains files that you are currently not sharing. Do you still want to post? - + Dieser Beitrag enthält Dateien, die Sie derzeit nicht freigeben. Möchten Sie trotzdem posten? Post refers to temporary shared files - + Beitrag bezieht sich auf temporäre freigegebene Dateien The following files will only be shared for 30 days. Think about adding them to a shared directory. - - - - File already Added and Hashed - Datei wurde schon hinzugefügt und gehasht + Die folgenden Dateien werden nur für 30 Tage freigegeben. Denken Sie darüber nach, sie in ein freigegebenes Verzeichnis aufzunehmen. @@ -5136,55 +4525,54 @@ p, li { white-space: pre-wrap; } Bitte einen Betreff hinzufügen - + + Cannot publish post + Beitrag kann nicht veröffentlicht werden + + + Load thumbnail picture Miniaturbild laden Show - + Zeigen Hide - Verbergen + Verbergen - - + Generate mass data Massendaten erzeugen - - Do you really want to generate %1 messages ? - Möchtest du wirklich %1 Nachrichten erzeugen? - - - + You are about to add files you're not actually sharing. Do you still want this to happen? Du bist dabei, Dateien hinzuzufügen, die du nicht freigegeben hast. Willst du das wirklich tun? Edit Channel Post - + Kanalbeitrag bearbeiten Update - Aktualisieren + Aktualisieren Close this window? - + Dieses Fenster schließen? Do you really want to discard your post? - + Wollen Sie Ihren Beitrag wirklich verwerfen? @@ -5196,7 +4584,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message Forumsnachricht veröffentlichen @@ -5205,10 +4593,6 @@ p, li { white-space: pre-wrap; } Forum Forum - - Subject - Betreff - Attach File @@ -5229,14 +4613,14 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> - +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> + Attach a Picture - Bild anhängen + Bild anhängen @@ -5249,14 +4633,14 @@ p, li { white-space: pre-wrap; } Du kannst Dateien mit Drag'n'Drop anhängen - + Post - + Posten Cancel - Abbrechen + Abbrechen @@ -5266,42 +4650,42 @@ p, li { white-space: pre-wrap; } Edit Message - + Nachricht bearbeiten Update - Aktualisieren + Aktualisieren Text - + - + No Forum Kein Forum - + In Reply to Als Antwort auf - + Title - Titel + Titel It remains %1 characters after HTML conversion. - + Es verbleiben %1 Zeichen nach der HTML-Konvertierung. Warning: This message is too big of %1 characters after HTML conversion. - + Warnung: Diese Nachricht ist mit %1 Zeichen zu groß nach der HTML-Konvertierung. @@ -5323,13 +4707,14 @@ p, li { white-space: pre-wrap; } Cancel Forum Message - + Forum-Nachricht abbrechen Forum Message has not been sent yet! Do you want to discard this message? - + Forum Nachricht wurde noch nicht gesendet! +Möchten Sie diese Nachricht verwerfen? @@ -5339,21 +4724,21 @@ Do you want to discard this message? Load Picture File - Bilddatei laden + Bilddatei laden - + No compatible ID for this forum Keine kompatible Kennung für dieses Forum None of your identities is allowed to post in this forum. This could be due to the forum being limited to a circle that contains none of your identities, or forum flags requiring a PGP-signed identity. - + Keine Ihrer Identitäten darf in diesem Forum schreiben. Dies könnte daran liegen, dass das Forum auf einen Kreis beschränkt ist, der keine Ihrer Identitäten enthält, oder dass Forum-Flags eine PGP-signierte Identität erfordern. - - + + Generate mass data Massendaten erzeugen @@ -5362,10 +4747,6 @@ Do you want to discard this message? Do you really want to generate %1 messages ? Möchtest du wirklich %1 Nachrichten erzeugen? - - Send - Senden - Post as @@ -5380,25 +4761,9 @@ Do you want to discard this message? CreateLobbyDialog - Create Chat Lobby - Chatlobby erstellen - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - Eine Chatlobby ist eine dezentralisierte und anonyme Chatgruppe. Alle Teilnehmer sehen alle Nachrichten. Wenn die Lobby erstellt wurde, kannst du Freunde über den "Freunde"-Reiter einladen. - - - Lobby name: - Lobbyname: - - - Lobby topic: - Lobbythema: - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. - + Ein Chatroom ist eine dezentralisierte und anonyme Chatgruppe. Alle Teilnehmer erhalten alle Nachrichten. Sobald der Raum erstellt ist, Siekönnen andere Freundesknoten mit der Schaltfläche "Einladen" oben rechts einladen. @@ -5431,17 +4796,17 @@ Do you want to discard this message? - + Create - Erstellen + Erstellen Cancel - Abbrechen + Abbrechen - + require PGP-signed identities erfordert PGP-signierte Identitäten @@ -5456,11 +4821,7 @@ Do you want to discard this message? Wähle die Freunde mit denen du chatten möchtest. - Invited friends - Freunde einladen - - - + Create Chat Room Chatraum erstellen @@ -5468,12 +4829,12 @@ Do you want to discard this message? Put a sensible chat room name here - + Geben Sie hier einen sinnvollen Chatroom-Namen ein Set a descriptive topic here - + Legen Sie hier ein beschreibendes Thema fest @@ -5481,7 +4842,7 @@ Do you want to discard this message? Kontakte: - + Identity to use: Zu verwendende Identität: @@ -5489,17 +4850,17 @@ Do you want to discard this message? CryptoPage - + Public Information Öffentliche Information - + Name: Name: - + Location: Ort: @@ -5509,12 +4870,12 @@ Do you want to discard this message? Ort-ID: - + Software Version: Softwareversion: - + Online since: Online seit: @@ -5526,7 +4887,7 @@ Do you want to discard this message? Statistics: - + Statistiken: @@ -5534,44 +4895,34 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export Show statistics - + Zeige Statistiken - + Other Information Andere Informationen Profile path: - + Profilpfad: - + Profile - Profil + Profil - - Certificate - Zertifikat - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> - + <html><head/><body><p>Diese Option umfasst alle Signaturen Ihres Profilschlüssels. Unterschriften sind nicht zwingend erforderlich, sondern nur eine Möglichkeit, Ihr Vertrauen in ein bestimmtes Profil auszudrücken.</p></body></html> @@ -5579,23 +4930,19 @@ Do you want to discard this message? Signaturen einschließen - Save Key into a file - Schlüssel in Datei sichern - - - + Export Identity - Identität exportieren + Identität exportieren RetroShare Identity files (*.asc) - RetroShare-Identitätsdateien (*.asc) + RetroShare-Identitätsdateien (*.asc) Identity saved - Identität gespeichert + Identität gespeichert @@ -5604,7 +4951,7 @@ It is encrypted You can now copy it to another computer and use the import button to load it - Deine Identität wurde erfolgreich gespeichert + Deine Identität wurde erfolgreich gespeichert Sie ist verschlüsselt Du kannst die Identität nun auf einen anderen Computer kopieren @@ -5613,12 +4960,12 @@ und den Import zum Laden verwenden Identity not saved - Identität nicht gespeichert + Identität nicht gespeichert Your identity was not saved. An error occurred. - Deine Identität wurde nicht gespeichert. Ein Fehler ist aufgetreten. + Deine Identität wurde nicht gespeichert. Ein Fehler ist aufgetreten. @@ -5657,50 +5004,50 @@ und den Import zum Laden verwenden - + TextLabel TextLabel - + PGP fingerprint: - PGP-Fingerabdruck + PGP-Fingerabdruck: - - Node information - Netzknoteninformation - - - + PGP Id : PGP-ID : - + Friend nodes: Freundknoten: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> Short format - + Kurzformat <html><head/><body><p>IP history is the list of IP you used accross time. Including this might help your friends reach you. This is optional for privacy reasons.</p></body></html> - + <html><head/><body><p>Der IP-Verlauf ist die Liste der IP-Adressen, die Sie im Laufe der Zeit verwendet haben. Wenn Sie dies hinzufügen, können Ihre Freunde Sie möglicherweise leichter erreichen. Dies ist aus Datenschutzgründen optional.</p></body></html> Include IP history - + IP-Verlauf einbeziehen @@ -5710,7 +5057,7 @@ und den Import zum Laden verwenden <html><head/><body><p>Saves your profile key pair into a file. This allows you to create a new node for the same profile, by importing this key pair on a different computer. Friends who already accept connections from you will automatically accept connections from that new node after you add them yourself. Your key is exported encrypted and you will need your login password to create a new profile.</p></body></html> - + <html><head/><body><p>Speichert Ihr Profilschlüsselpaar in einer Datei. Dadurch können Sie einen neuen Knoten für dasselbe Profil erstellen, indem Sie dieses Schlüsselpaar auf einem anderen Computer importieren. Freunde, die bereits Verbindungen von Ihnen akzeptieren, akzeptieren automatisch Verbindungen von diesem neuen Knoten, nachdem Sie sie selbst hinzugefügt haben. Ihr Schlüssel wird verschlüsselt exportiert und Sie benötigen Ihr Login-Passwort, um ein neues Profil zu erstellen.</p></body></html> @@ -5722,14 +5069,6 @@ und den Import zum Laden verwenden Node Netzknoten - - Create new node... - Neuen Netzknoten erstellen... - - - show statistics window - Statistikfenster anzeigen - DHTGraphSource @@ -5775,13 +5114,13 @@ und den Import zum Laden verwenden No peer found in DHT - + Kein Peer in DHT gefunden DLListDelegate - + B B @@ -5803,7 +5142,7 @@ und den Import zum Laden verwenden Faster - Schneller + Schneller @@ -5813,7 +5152,7 @@ und den Import zum Laden verwenden Slower - Langsamer + Langsamer @@ -6055,7 +5394,7 @@ und den Import zum Laden verwenden Restarting - + Neustart @@ -6125,17 +5464,17 @@ und den Import zum Laden verwenden UPNP FORWARD - UPNP WEITERLEIT. + UPNP WEITERLEITUNG NATPMP FORWARD - NATPMP WEITERLEIT. + NATPMP WEITERLEITUNG MANUAL FORWARD - MANUELLE WEITERLEIT. + MANUELLE WEITERLEITUNG @@ -6296,7 +5635,7 @@ und den Import zum Laden verwenden %1 secs ago - vor %1 Sek. + vor %1 Sekunden @@ -6306,7 +5645,7 @@ und den Import zum Laden verwenden Relays - + Relais @@ -6415,7 +5754,7 @@ und den Import zum Laden verwenden Relay - + @@ -6449,7 +5788,7 @@ und den Import zum Laden verwenden DownloadToaster - + Start file Datei ausführen @@ -6457,38 +5796,38 @@ und den Import zum Laden verwenden ExprParamElement - + - + to bis - + ignore case Groß-/Kleinschreibung ignorieren - - - dd.MM.yyyy - TT.MM.JJJJ + + + yyyy-MM-dd + - - + + KB KiB - - + + MB MiB - - + + GB GiB @@ -6496,12 +5835,12 @@ und den Import zum Laden verwenden ExpressionWidget - + Expression Widget Ausdruck Oberfläche - + Delete this expression Diesen Ausdruck löschen @@ -6546,7 +5885,7 @@ und den Import zum Laden verwenden Friend Help - Freunde-Hilfe + Freunde-Hilfe @@ -6663,7 +6002,7 @@ und den Import zum Laden verwenden FilesDefs - + Picture Bild @@ -6673,7 +6012,7 @@ und den Import zum Laden verwenden Video - + Audio Audio @@ -6733,11 +6072,21 @@ und den Import zum Laden verwenden C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Dateien von Freunden @@ -6749,7 +6098,7 @@ und den Import zum Laden verwenden # Files - + # Dateien @@ -6779,12 +6128,12 @@ und den Import zum Laden verwenden Column %1 - + Spalte %1 Row %1 - + Zeile %1 @@ -6817,17 +6166,17 @@ und den Import zum Laden verwenden Load emoticons (costly) - + Emoticons laden (kostspielig) Minimum font size - Minimale Schriftgröße + Minimale Schriftgröße Minimum text contrast - Minimaler Text-Kontrast + Minimaler Text-Kontrast @@ -6842,7 +6191,7 @@ und den Import zum Laden verwenden Forums - Foren + Foren @@ -6850,7 +6199,7 @@ und den Import zum Laden verwenden Friends - Freunde + Freunde @@ -6859,9 +6208,9 @@ und den Import zum Laden verwenden - + ID - + @@ -6876,7 +6225,7 @@ und den Import zum Laden verwenden export your friendlist including groups - + Exportieren Sie Ihre Freundesliste einschließlich Gruppen @@ -6886,7 +6235,7 @@ und den Import zum Laden verwenden import your friendlist including groups - + Importieren Sie Ihre Freundesliste einschließlich Gruppen @@ -6901,7 +6250,7 @@ und den Import zum Laden verwenden Gruppen anzeigen - + Group Gruppe @@ -6937,7 +6286,7 @@ und den Import zum Laden verwenden Zu Gruppe hinzufügen - + Search Suchen @@ -6945,7 +6294,7 @@ und den Import zum Laden verwenden Search ID - Kennung suchen + Kennung suchen @@ -6953,7 +6302,7 @@ und den Import zum Laden verwenden Nach Status sortieren - + Profile details Profildetails @@ -7034,7 +6383,8 @@ und den Import zum Laden verwenden (keep in mind that the file is unencrypted!) - + +(Beachten Sie, dass die Datei unverschlüsselt ist!) @@ -7053,23 +6403,25 @@ und den Import zum Laden verwenden at least one peer was not added - + +Mindestens ein Peer wurde nicht hinzugefügt at least one peer was not added to a group - + +Mindestens ein Peer wurde nicht zu einer Gruppe hinzugefügt Select file for importing your friendlist from - + Wählen Sie die Datei aus, aus der Sie Ihre Freundesliste importieren möchten Select a file for exporting your friendlist to - + Wählen Sie eine Datei aus, in die Sie Ihre Freundesliste exportieren möchten @@ -7100,7 +6452,7 @@ at least one peer was not added to a group Show Items - + Elemente anzeigen @@ -7173,12 +6525,12 @@ at least one peer was not added to a group Please select at least one friend for recommendation. - Bitte mindestens einen Freund als Empfehlung wählen. + Bitte mindestens einen Freund als Empfehlung wählen. Please select at least one friend as recipient. - Bitte mindestens einen Empfänger wählen. + Bitte mindestens einen Empfänger wählen. @@ -7188,13 +6540,13 @@ at least one peer was not added to a group A recommendation message was sent to each of the chosen friends! - + An jeden der ausgewählten Freunde wurde eine Empfehlungsnachricht gesendet! FriendRequestToaster - + Confirm Friend Request Freundschaftsanfrage bestätigen @@ -7211,10 +6563,6 @@ at least one peer was not added to a group FriendSelectionWidget - - Search : - Suchen: - Sort by state @@ -7223,7 +6571,7 @@ at least one peer was not added to a group Filter only connected - + Nur verbundene Filtern @@ -7236,7 +6584,7 @@ at least one peer was not added to a group Freunde suchen - + Mark all Alle markieren @@ -7247,16 +6595,132 @@ at least one peer was not added to a group Keine markieren + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Name + + + + Node ID + + + + + Address + Adresse + + + + Status + Status + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + Freund hinzufügen + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message Statusnachricht bearbeiten - - + + Broadcast Rundschreiben @@ -7339,33 +6803,38 @@ at least one peer was not added to a group Schriftart auf den Standard setzen - + Keyring Schlüsselbund - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. RetroShare-Rundschreiben: Nachrichten werden an alle verbundenen Freunde gesendet. - - + + Network Netzwerk - + + Friend Server + Freundes-Server + + + Network graph Netzwerkgraph - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. Stelle hier deine Statusmeldung ein. @@ -7383,27 +6852,32 @@ at least one peer was not added to a group Passwort - + + SAMv3 support is not available + SAMv3-Unterstützung ist nicht verfügbar + + + + I2P instance address with SAMv3 enabled + I2P-Instanzadresse mit aktiviertem SAMv3 + + + All fields are required with a minimum of 3 characters Alle Felder sind mit min. 3 Zeichen zu versehen Passwords do not match - Passwörter stimmen nicht überein. + Passwörter stimmen nicht überein - + Port Port - - Use BOB - - - - + This password is for PGP Das ist das Passwort für PGP @@ -7424,112 +6898,109 @@ at least one peer was not added to a group Das Erzeugen deines neuen Zertifikats ist fehlgeschlagen. Vielleicht ist das PGP-Passwort falsch? - + PGP Key Length - + PGP-Schlüssellänge - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Geben Sie hier ein sicheres Passwort ein. Dieses Passwort schützt Ihren privaten Knotenschlüssel!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + <html><head/><body><p>Bitte bewegen Sie Ihre Maus, um so viel Zufälligkeit wie möglich zu sammeln. Zum Erstellen Ihrer Knotenschlüssel sind mindestens 20 % erforderlich.</p></body></html> - + Standard node Standardknoten - TOR/I2P Hidden node - TOR/I2P Versteckter Knoten - - - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + <html><head/><body><p>Ihr Knotenname bezeichnet die Retroshare-Instanz, die</p><p>auf diesem Computer ausgeführt wird.</p></body></html> - + Node name Knotenname - + Node type: - + Knotentyp: Hidden node (over Tor) - + Hidden Knoten (über Tor) Hidden node (Tor/I2P - Manually configured) - + Hidden Knoten (Tor/I2P – manuell konfiguriert) advanced options - + erweiterte Optionen - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + <html><head/><body><p>Der Profilname identifiziert Sie über das Netzwerk.</p><p>Er wird von Ihren Freunden verwendet, um Verbindungen von Ihnen anzunehmen.</p><p>Das können Sie Erstellen Sie mehrere Retroshare-Knoten mit demselben Profil auf verschiedenen Computern.</p><p><br/></p></body></html> - + Export this profle Dieses Profil exportieren Use existing profile... - + Vorhandenes Profil verwenden... - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - - <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + + Use I2P + I2P verwenden - + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> + <html><head/><body><p>Identitäten werden verwendet, wenn Sie in Chatrooms, Foren und Kanalkommentaren schreiben. </p><p>Sie empfangen/senden auch E-Mails über das Retroshare-Netzwerk. Sie können</p><p>eine signierte Identität jetzt erstellen oder dies später tun, wenn Sie sie benötigen.</p></body></html> + + + Go! Los! - - + + TextLabel - TextLabel + TextLabel - Advanced options - Erweiterte Einstellungen - - - + hidden address versteckte Adresse - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. Dein Profil ist mit einem PGP-Schlüsselpaar verknüpft. RetroShare ignoriert derzeit DSA-Schlüssel. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> <html><head/><body><p>Dies ist dein Verbindungsport.</p><p>Ein Wert zwischen 1024 und 65535 </p><p>sollte ok sein. Du kannst ihn später ändern.</p></body></html> @@ -7577,30 +7048,30 @@ und den Import zum Laden verwenden Dein Profil wurde nicht gespeichert. Ein Fehler ist aufgetreten. - + Import profile Profil importieren - + Create new profile and new Retroshare node - + Neues Profil und neuen Retroshare-Knoten erstellen Create new Retroshare node - + Neuen Retroshare-Knoten erstellen - + Tor/I2P address - + Tor/I2P-Adresse Username - + Benutzername @@ -7610,7 +7081,7 @@ und den Import zum Laden verwenden Password again - + Passwort wiederholen @@ -7628,7 +7099,7 @@ und den Import zum Laden verwenden - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7638,12 +7109,7 @@ und den Import zum Laden verwenden - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -7653,12 +7119,7 @@ und den Import zum Laden verwenden - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7670,7 +7131,7 @@ und den Import zum Laden verwenden RetroShare profile files (*.asc);;All files (*) - + RetroShare-Profildateien (*.asc);;Alle Dateien (*) @@ -7695,22 +7156,22 @@ und den Import zum Laden verwenden The GXS nickname is too short. Please input at least %1 characters. - + Der GXS-Spitzname ist zu kurz. Bitte geben Sie mindestens %1 Zeichen ein. The GXS nickname is too long. Please reduce the length to %1 characters. - + Der GXS-Spitzname ist zu lang. Bitte reduzieren Sie die Länge auf %1 Zeichen. Tor is not available - + Tor ist nicht verfügbar No Tor executable has been found on your system. You need to install Tor before creating a hidden identity. - + Es wurde keine ausführbare Tor-Datei auf deinem System gefunden. Du musst Tor installieren, bevor du eine hidden Identität erstellen kannst. @@ -7791,22 +7252,22 @@ und den Import zum Laden verwenden When checked, this instance receives new parameters (like RsLink or RsFile) and avoid new one. - + Wenn diese Instanz geprüft wird, erhält sie neue Parameter (wie RsLink oder RsFile) und vermeidet neue Parameter. Use Local Server to get new arguments. - + Verwenden Sie Local Server, um neue Argumente zu erhalten. <html><head/><body><p>Install RetroShare with a package installer to get</p><p>/usr/share/applications/retroshare.desktop</p></body></html> - + <html><head/><body><p>Installieren Sie RetroShare mit einem Paket-Installer, um</p><p>/usr/share/applications/retroshare.desktop</p></body></html> !!!The RetroShare's desktop file is missing or wrong!!! - + !!!Die Desktop-Datei von RetroShare fehlt oder ist falsch!!! @@ -7821,32 +7282,32 @@ und den Import zum Laden verwenden seconds - Sekunden + Sekunden You have sufficient rights. - + Sie haben genügend Rechte. You don't have sufficient rights. Run RetroShare as Admin to change this setting. - + Sie haben nicht genügend Rechte. Führen Sie RetroShare als Administrator aus, um diese Einstellung zu ändern. For security reasons the usage of auto-login is discouraged, you can enable it but you are on your own! - + Aus Sicherheitsgründen wird von der Verwendung der automatischen Anmeldung abgeraten, Sie können sie zwar aktivieren, sind aber auf sich allein gestellt! Your RetroShare build has auto-login disabled. - + In Ihrem RetroShare-Programm ist die automatische Anmeldung deaktiviert. No Qt-compatible system tray was found on this system. - + Auf diesem System wurde kein Qt-kompatibler Systemtray gefunden. @@ -7884,36 +7345,13 @@ und den Import zum Laden verwenden Erste Schritte - + Invite Friends Freunde einladen - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare ist nichts ohne deine Freunde. Klicke auf &quot;Freunde einladen&quot; um den Prozess zu starten.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Schicke eine Einladungsmail mit deinem &quot;Zertifikat&quot; an deine Freunde.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Versichere dich ihre Einladung zurück zu bekommen... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Du kannst dich nur zu deinen Freunden verbinden, wenn ihr euch gegenseitig hinzugefügt habt.</span></p></body></html> - - - + Add Your Friends to RetroShare Füge deine Freunde zu RetroShare hinzu @@ -7923,89 +7361,103 @@ p, li { white-space: pre-wrap; } Freunde hinzufügen - + + Connect To Friends + Zu Freunden verbinden + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Erweitert: Öffne Firewall Port + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - Zu Freunden verbinden - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - Erweitert: Öffne Firewall Port - - - + Further Help and Support Weitere Hilfe und Support - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website RS-Website öffnen @@ -8030,7 +7482,7 @@ p, li { white-space: pre-wrap; } E-Mail-Feedback - + RetroShare Invitation RetroShare-Einladung @@ -8080,12 +7532,12 @@ p, li { white-space: pre-wrap; } RetroShare Feedback - + RetroShare Support RetroShare Support - + It has many features, including built-in chat, messaging, Es hat viele Funktionen wie Chat, Nachrichten, @@ -8135,12 +7587,12 @@ p, li { white-space: pre-wrap; } Receive time - + Empfangszeit Sending time - + Sendezeit @@ -8155,12 +7607,12 @@ p, li { white-space: pre-wrap; } Data hash - + Datenhash Branching factor - + Verzweigungsfaktor @@ -8209,7 +7661,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat Gruppenchat anzeigen @@ -8217,7 +7669,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] [Unbekannt] @@ -8255,72 +7707,72 @@ p, li { white-space: pre-wrap; } Directory content is visible to friend nodes (see list at right) - + Der Inhalt des Verzeichnisses ist für Freundesknoten sichtbar (siehe Liste rechts) Directory content is NOT visible to friend nodes - + Der Verzeichnisinhalt ist für Freundesknoten NICHT sichtbar Directory can be searched anonymously - + Das Verzeichnis kann anonym durchsucht werden Directory cannot be searched anonymously - + Das Verzeichnis kann nicht anonym durchsucht werden Files can be accessed using anonymous tunnels - + Auf Dateien kann über anonyme Tunnel zugegriffen werden Files can be accessed using anonymous & end-to-end encrypted tunnels - + Auf Dateien kann über anonyme und Ende-zu-Ende-verschlüsselte Tunnel zugegriffen werden Files cannot be downloaded anonymously - + Dateien können nicht anonym heruntergeladen werden All friend nodes can see this directory - + Alle Freundesknoten können dieses Verzeichnis sehen Only visible to friend nodes in groups: %1 - + Nur für Freundesknoten in Gruppen sichtbar: %1 Not visible to friend nodes - + Für Freundesknoten nicht sichtbar Files can be downloaded (but not searched) anonymously - + Dateien können anonym heruntergeladen (aber nicht durchsucht) werden Files can be downloaded and searched anonymously - + Dateien können anonym heruntergeladen und durchsucht werden Files can be searched (but not downloaded) anonymously - + Dateien können anonym durchsucht (aber nicht heruntergeladen) werden No one can anonymously access/search these files. - + Niemand kann anonym auf diese Dateien zugreifen bzw. diese durchsuchen. @@ -8351,22 +7803,22 @@ p, li { white-space: pre-wrap; } Share channel publish permissions - + Teilen Sie die Veröffentlichungsberechtigung für dieses Kanal You can allow your friends to publish in your channel, or send the publish permissions to another Retroshare instance of yours. Select the friends which you want to be allowed to publish in this channel. Note: it is currently not possible to revoke channel publish permissions. - + Sie können Ihren Freunden erlauben, in Ihrem Kanal zu veröffentlichen, oder die Veröffentlichungsberechtigung an eine andere Retroshare-Instanz von Ihnen senden. Wählen Sie die Freunde aus, denen Sie erlauben wollen, in diesem Kanal zu veröffentlichen. Hinweis: Es ist derzeit nicht möglich, die Veröffentlichungsberechtigung für den Kanal zu widerrufen. Share board admin permissions - + Teilen Sie die Veröffentlichungsberechtigung für dieses Board You can allow your friends to edit the board. Select them in the list below. Note: it is not possible to revoke Board admin permissions. - + Sie können Ihren Freunden erlauben, das Board zu bearbeiten. Wählen Sie sie in der Liste unten aus. Hinweis: Es ist nicht möglich, die Administratorrechte für das Board zu entziehen. @@ -8383,19 +7835,11 @@ p, li { white-space: pre-wrap; } You can let your friends know about your forum by sharing it with them. Select the friends with which you want to share your forum. Du kannst deine Freunde von deinem Forum wissen lassen, indem du es mit ihnen teilst. Wähle die Freunde, mit denen du das Forum teilen willst. - - Share topic admin permissions - Thema-Administratorrechte teilen - - - You can allow your friends to edit the topic. Select them in the list below. Note: it is not possible to revoke Posted admin permissions. - Du kannst deinen Freunden die Bearbeitung des Themas erlauben, indem du sie in der Liste unten auswählst. Hinweis: Der Widerruf von Posted-Administratorrechten ist nicht möglich. - GroupTreeWidget - + Title Titel @@ -8408,12 +7852,12 @@ p, li { white-space: pre-wrap; } - + Description Beschreibung - + Number of Unread message @@ -8435,67 +7879,51 @@ p, li { white-space: pre-wrap; } Search entire network... - + Suche im gesamten Netzwerk... - Sort by Name - Nach Name sortieren - - - Sort by Popularity - Nach Beliebtheit sortieren - - - Sort by Last Post - Nach letztem Beitrag sortieren - - - + You are admin (modify names and description using Edit menu) - + Sie sind Administrator (ändern Sie Namen und Beschreibung über das Menü Bearbeiten) You have been granted as publisher (you can post here!) - + Sie wurden als Publisher zugelassen (Sie können hier posten!) Id - ID + ID - - + + Last Post Letzter Beitrag - + Name - Name + Name Popularity - Beliebtheit + Beliebtheit - + Never Nie - Display - Anzeigen - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> - + <html><head/><body><p>Sucht ein einzelnes Schlüsselwort im erreichbaren Netz.</p><p>Objekte, die bereits von befreundeten Knoten bereitgestellt wurden, werden nicht gemeldet.</p></body></html> @@ -8506,7 +7934,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and und @@ -8606,43 +8034,43 @@ p, li { white-space: pre-wrap; } Authenticated tunnels: - Authentifizierte Tunnel: + Authentifizierte Tunnel: Tunnel ID: %1 - Tunnelkennung: %1 + Tunnelkennung: %1 from: %1 (%2) - + von: %1 (%2) to: %1 (%2) - + an: %1 (%2) status: %1 - Status: %1 + Status: %1 total sent: %1 bytes - Gesendet gesamt: %1 bytes + Gesendet gesamt: %1 bytes total recv: %1 bytes - Empfangen gesamt: %1 bytes + Empfangen gesamt: %1 bytes GxsChannelDialog - + Channels Kanäle @@ -8653,22 +8081,22 @@ p, li { white-space: pre-wrap; } Kanal erstellen - + Enable Auto-Download Auto-Download aktivieren - + My Channels Eigene Kanäle - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Abonnierte Kanäle @@ -8688,12 +8116,12 @@ p, li { white-space: pre-wrap; } Kanal-Download-Verzeichnis auswählen - + Disable Auto-Download Auto-Download deaktivieren - + Set download directory Herunterladeverzeichnis festlegen @@ -8728,22 +8156,22 @@ p, li { white-space: pre-wrap; } - + Play - Abspielen + Abspielen - + Open folder Ordner öffnen - + Open file - + Datei öffnen - + Error Fehler @@ -8763,57 +8191,30 @@ p, li { white-space: pre-wrap; } Überprüfe - + Are you sure that you want to cancel and delete the file? Möchtest du wirklich abbrechen und die Datei löschen? - + Can't open folder Kann Ordnder nicht öffnen - + Play File - Datei abspielen + Datei abspielen File %1 does not exist at location. - Datei %1 existiert nicht. - - - - GxsChannelFilesWidget - - Form - Formular - - - Filename - Dateiname - - - Size - Größe - - - Title - Titel - - - Published - Veröffentlicht - - - Status - Status + Datei %1 existiert nicht. GxsChannelGroupDialog - + Create New Channel Neuen Kanal erstellen @@ -8851,23 +8252,33 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - Kanal abonnieren + + Last activity + Letzte Aktivität + + + + TextLabel + TextLabel + + + + Subscribe this Channel + Diesen Kanal abonnieren Subscribe - Abonnieren + Abonnieren Copy RetroShare Link - RetroShare-Link kopieren + RetroShare-Link kopieren - + Expand Erweitern @@ -8882,23 +8293,24 @@ p, li { white-space: pre-wrap; } Kanalbeschreibung - + Loading Lade Publish permission received for channel: - + Veröffentlichungserlaubnis für Kanal erhalten: New Channel: - + Neuer Kanal: - New Channel - Neuer Kanal + + Never + Nie @@ -8909,7 +8321,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: Neuer Kommentar: @@ -8930,7 +8342,7 @@ p, li { white-space: pre-wrap; } - + Play Abspielen @@ -8986,28 +8398,24 @@ p, li { white-space: pre-wrap; } Files Dateien - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - Warnung! Du hast weniger als %1 Stunden und %2 Minuten bevor die Datei gelöscht wird. Denke daran, sie zu speichern. - Hide Verbergen - + New Neu - + 0 0 - - + + Comment Kommentar @@ -9022,23 +8430,19 @@ p, li { white-space: pre-wrap; } Das gefällt mir nicht - Loading - Lade - - - + Loading... - + Lade... - + Comments - + Kommentare - + Post - + Posten @@ -9061,154 +8465,39 @@ p, li { white-space: pre-wrap; } Medium abspielen - - GxsChannelPostsWidget - - Post to Channel - In Kanal veröffentlichen - - - Loading - Lade - - - Search channels - Kanäle durchsuchen - - - Title - Titel - - - Search Title - Titel durchsuchen - - - Message - Nachricht - - - Search Message - Nachricht suchen - - - Filename - Dateiname - - - Search Filename - Dateiname suchen - - - No Channel Selected - Keinen Kanal gewählt - - - Never - Nie - - - Public - Öffentlich - - - Restricted to members of circle " - Beschränkt auf Mitglieder des Kreises " - - - Restricted to members of circle - Beschränkt auf Mitglieder des Kreises - - - Your eyes only - Nur Ihre Augen - - - Disable Auto-Download - Auto-Download deaktivieren - - - Enable Auto-Download - Auto-Download aktivieren - - - Show feeds - Zeige Feeds - - - Show files - Zeige Dateien - - - Administrator: - Administrator: - - - Last Post: - Letzter Beitrag: - - - unknown - unbekannt - - - Distribution: - Verteilung: - - - Feeds - Feeds - - - Files - Dateien - - - Subscribers - Abonnenten - - - Description: - Beschreibung: - - - Posts (at neighbor nodes): - Beiträge (bei Nachbarknoten) - - GxsChannelPostsWidgetWithModel - + Post to Channel - In Kanal veröffentlichen + In Kanal veröffentlichen - + Add new post - + Beitrag erstellen ... - + ... Search channels - Kanäle durchsuchen + Kanäle durchsuchen Channel details - + Kanal-Details Channel title - + Kanal-Titel @@ -9216,18 +8505,18 @@ p, li { white-space: pre-wrap; } TextLabel - TextLabel + TextLabel Distribution: - Verteilung: + Verteilung: <html><head/><body><p>Includes all posts, comments and votes. This number is progressively updated when new friend connect. The local vs. at friends difference may indicate that you would get older posts by increasing the synchronization period.</p></body></html> - + <html><head/><body><p>Enthält alle Beiträge, Kommentare und Abstimmungen. Diese Zahl @@ -9235,296 +8524,307 @@ p, li { white-space: pre-wrap; } unknown - unbekannt + unbekannt <html><head/><body><p>This includes posts, comments to posts and votes to comments.</p></body></html> - + <html><head/><body><p>Dies umfasst Beiträge, Kommentare zu Beiträgen und Stimmen zu Kommentaren.</p></body></html> Last activity: - + Letzte Aktivität: Administrator: - Administrator: + Administrator: - Posts (locally / at friends): - + Items (locally / at friends): + Artikel (vor Ort / bei Freunden): Created: - + Erstellt: Sync period: - + Sync-Zeitraum: Posts - Beiträge + Beiträge <html><head/><body><p>Click to view post. </p><p>Use Ctrl+mouse wheel </p><p>to zoom/unzoom.</p></body></html> - + <html><head/><body><p>Klicken Sie, um den Beitrag zu sehen. </p><p>Verwenden Sie Strg+Mausrad</p><p>zum Zoomen/Entzoomen.</p></body></html> Details - Details + Details Files - Dateien + Dateien - + Comments - Kommentare + Kommentare All files - + Alle Dateien Feeds - Feeds + Feeds - - + + Click to switch to list view - + Klicken Sie, um zur Listenansicht zu wechseln - + Show unread posts only - + Nur ungelesene Beiträge anzeigen No files in this post, or no post selected - + Keine Dateien in diesem Beitrag, oder kein Beitrag ausgewählt No files in the channel, or no channel selected - + Keine Dateien im Kanal, oder kein Kanal ausgewählt - + No text to display - + Kein Text zum Anzeigen Search... - + Suchen... No posts available in this channel - + Keine Beiträge in diesem Kanal vorhanden - + Switch to list view - + Zur Listenansicht wechseln Switch to grid view - + Zur Gitteransicht wechseln Download files - + Dateien herunterladen Mark as unread - Als ungelesen markieren + Als ungelesen markieren Copy RetroShare Link - RetroShare-Link kopieren + RetroShare-Link kopieren Edit - Bearbeiten + Bearbeiten Click to switch to grid view - + Klicken, um zur Rasteransicht zu wechseln Link creation error - + Fehler bei der Link-Erstellung Link could not be created: - + Link konnte nicht erstellt werden: Download this file: - + Diese Datei herunterladen: Download All these %1 files: - + Alle diese %1-Dateien herunterladen: Totaling: %1 - + Gesamtwert: %1 - + Comments (%1) - + Kommentare (%1) - + + Loading... + Lade... + + + + No posts available in this channel. + Keine Beiträge in diesem Kanal vorhanden. + + + [No name] - + [Kein Name] Never - Nie + Nie 5 days - 5 Tage + 5 Tage 2 weeks - 2 Wochen + 2 Wochen 1 month - 1 Monat + 1 Monat 3 months - + 3 Monate 6 months - + 6 Monate 1 year - 1 Jahr + 1 Jahr indefinitly - + Unbegrenzt Unknown - Unbekannt + Unbekannt Public - Öffentlich + Öffentlich Restricted to members of circle " - Beschränkt auf Mitglieder des Kreises " + Beschränkt auf Mitglieder des Kreises " Restricted to members of circle - Beschränkt auf Mitglieder des Kreises + Beschränkt auf Mitglieder des Kreises Your eyes only - Nur Ihre Augen + Nurfür Ihre Augen You and your friend nodes - + Du und deine Freundschaftsknoten - + + Copy Retroshare link - + RetroShare-Link kopieren - + Subscribed - Abonniert + Abonniert Subscribe - Abonnieren + Abonnieren Channel info missing - + Kanalinformationen fehlen To subscribe, first request the channel information by right-clicking Request Data in the search results. - + Um sich zu abonnieren, fordern Sie zunächst die Kanalinformationen an, indem Sie in den Suchergebnissen mit der rechten Maustaste auf Daten anfordern klicken. Channel info requested... - + Kanalinformationen angefordert... No Channel Selected - Keinen Kanal gewählt + Kein Kanal ausgewählt Disable Auto-Download - Auto-Download deaktivieren + Auto-Download deaktivieren Enable Auto-Download - Auto-Download aktivieren + Auto-Download aktivieren @@ -9538,132 +8838,132 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - TextLabel + TextLabel - + Circle name: - + Kreisname: - + Accept - + Akzeptieren Revoke - + Widerrufen Details - Details + Details Remove Item - + Eintrag entfernen Grant membership request - + Mitgliedschaftsantrag gewähren Revoke membership - + Mitgliedschaft widerrufen You received a membership request a circle you're administrating: - + Sie haben einen Antrag auf Mitgliedschaft in einem von Ihnen verwalteten Kreis erhalten: Grant membership - + Mitgliedschaft gewähren Grant membership to this circle, for this identity - + Gewährung der Mitgliedschaft in diesem Kreis, für diese Identität You received an invitation to join this circle: - + Sie haben eine Einladung erhalten, diesem Kreis beizutreten: Accept invitation - + Einladung annehmen has left this circle. - + hat diesen Kreis verlassen. which you invited, has joined this circle you're administrating. - + die Sie eingeladen haben, ist zu diesem Kreis beigetreten, den Sie verwalten. Revoke membership for that identity - + Entzug der Mitgliedschaft für diese Identität has joined this circle. - + ist diesem Kreis beigetreten. Your identity %1 has been revoked from this circle. - + Ihre Identität %1 wurde aus diesem Kreis entfernt. Cancel membership request - + Mitgliedsantrag stornieren Cancel your membership request from that circle - + Ihren Mitgliedschaftsantrag aus diesem Kreis stornieren Your identity %1 as been accepted in this circle. - + Ihre Identität %1 wurde in diesem Kreis akzeptiert. Cancel membership - + Mitgliedschaft kündigen Cancel your membership from that circle - + Ihre Mitgliedschaft in diesem Kreis kündigen Received event from unknown Circle: - + Ereignis von unbekanntem Kreis erhalten: GxsCommentContainer - + Comment Container Kommentarcontainer @@ -9676,14 +8976,14 @@ p, li { white-space: pre-wrap; } Formular - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sortieren nach</span></p></body></html> Hot - Heiß + Hot @@ -9698,7 +8998,7 @@ p, li { white-space: pre-wrap; } Voter ID: - Wähler-ID + Wähler-ID: @@ -9706,7 +9006,7 @@ p, li { white-space: pre-wrap; } Aktualisieren - + Comment Kommentar @@ -9745,7 +9045,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment Auf Kommentar antworten @@ -9757,7 +9057,7 @@ p, li { white-space: pre-wrap; } Copy Comment - + Kommentar kopieren @@ -9769,6 +9069,21 @@ p, li { white-space: pre-wrap; } Vote Down Dagegen stimmen + + + Show Author + Autor anzeigen + + + + Cannot vote + Kann nicht abstimmen + + + + Error while voting: + Fehler bei der Abstimmung: + GxsCreateCommentDialog @@ -9778,69 +9093,57 @@ p, li { white-space: pre-wrap; } Kommentieren - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Compose new Comment</span></p></body></html> - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Neuen Kommentar verfassen</span></p></body></html> Type in your comment - + Geben Sie Ihren Kommentar ein Cancel - Abbrechen + Abbrechen TextLabel - TextLabel + TextLabel Post as: - + Posten als: - + Post - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Kommentar</span></p></body></html> - - - Signed by - Unterzeichnet von + Posten Reply to Comment - Auf Kommentar antworten + Auf Kommentar antworten Replying to - + Antwort auf Type your reply - + Geben Sie Ihre Antwort ein @@ -9852,17 +9155,17 @@ p, li { white-space: pre-wrap; } You need to create an Identity before you can comment Du musst eine Identität erstellen, -bevor du kommentieren kannst. +bevor du kommentieren kannst - + It remains %1 characters after HTML conversion. - + Es verbleiben %1 Zeichen nach der HTML-Konvertierung. Warning: This message is too big of %1 characters after HTML conversion. - + Warnung: Diese Nachricht ist mit %1 Zeichen zu groß nach der HTML-Konvertierung. @@ -9870,7 +9173,7 @@ bevor du kommentieren kannst. <p>Put one of your identities here to allow others to send feedback and also have moderator rights on the forum. You may as well leave that field blank and keep the forum anonymously administrated.</p> - + <p>Geben Sie hier eine Ihrer Identitäten ein, damit andere Feedback senden können und auch über Moderatorrechte im Forum verfügen. Sie können dieses Feld auch leer lassen und das Forum anonym verwalten.</p> @@ -9895,15 +9198,7 @@ bevor du kommentieren kannst. Forum moderators can edit/delete/pinup others posts - - - - Add Forum Admins - Forum-Administratoren hinzufügen - - - Select Forum Admins - Forum-Administratoren auswählen + Forummoderatoren können Beiträge bearbeiten, löschen oder anheften @@ -9914,23 +9209,23 @@ bevor du kommentieren kannst. GxsForumGroupItem - + Subscribe to Forum Forum abonnieren Subscribe - Abonnieren + Abonnieren Copy RetroShare link - + RetroShare-Link kopieren - + Expand Erweitern @@ -9947,26 +9242,27 @@ bevor du kommentieren kannst. Moderator list - + Moderatorenliste - Loading - Lade + + TextLabel + TextLabel Loading... - + Lade... Moderator list changed - + Moderatorenliste geändert Forum updated - + Forum aktualisiert @@ -9982,24 +9278,24 @@ bevor du kommentieren kannst. GxsForumMsgItem - - + + Subject: - Betreff: + Betreff: - + Unsubscribe To Forum Forum abbestellen Unsubscribe - Abbestellen + Abbestellen - + Expand Erweitern @@ -10016,24 +9312,20 @@ bevor du kommentieren kannst. In Reply to: - Als Antwort auf: + Als Antwort auf: - Loading - Lade - - - + Loading... - + Lade... - + Forum Feed Forumfeed - + Hide Verbergen @@ -10046,63 +9338,66 @@ bevor du kommentieren kannst. Formular - + Start new Thread for Selected Forum Ein neues Thema im ausgewählten Forum starten - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Foren durchsuchen - Last Post - Letzter Beitrag - - - + New Thread - Neues Thema - - - - Threaded View - Hierarchische Ansicht - - - - Flat View - Ebene Ansicht + Neues Thema - + Title Titel - - + + Date Datum - + Author Autor - - Save image - Bild speichern - - - + Loading Lade - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -10112,12 +9407,7 @@ bevor du kommentieren kannst. - - Lastest post in thread - - - - + Reply Message Auf Nachricht antworten @@ -10134,17 +9424,13 @@ bevor du kommentieren kannst. Next unread message - + Nächste ungelesene Nachricht Download all files Alle Dateien herunterladen - - Next unread - Nächste ungelesene - Search Title @@ -10161,33 +9447,25 @@ bevor du kommentieren kannst. Autor durchsuchen - Content - Inhalt - - - Search Content - Inhalt durchsuchen - - - + No name Kein Name - - + + Reply Antwort - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... - + Lade... @@ -10228,20 +9506,12 @@ bevor du kommentieren kannst. RetroShare-Link kopieren - + Hide Verbergen - Expand - Erweitern - - - [Banned] - [Gebannt] - - - + [unknown] [unbekannt] @@ -10263,7 +9533,7 @@ bevor du kommentieren kannst. Only friends nodes in group - + Nur Freundesknoten in der Gruppe @@ -10271,41 +9541,21 @@ bevor du kommentieren kannst. Nur Ihre Augen - - + + Distribution Verteilung Owner - + Eigentümer Anti-spam Anti-Spam - - [ ... Redacted message ... ] - [ ... Redigierte Nachricht ... ] - - - Anonymous - Anonym - - - signed - unterzeichnet - - - none - keine - - - [ ... Missing Message ... ] - [ ... Fehlende Nachricht ... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10375,14 +9625,14 @@ bevor du kommentieren kannst. Ursprüngliche Nachricht - + New thread - + Edit - Bearbeiten + Bearbeiten @@ -10413,7 +9663,7 @@ bevor du kommentieren kannst. Give neutral opinion - + Neutrale Meinung abgeben @@ -10433,7 +9683,7 @@ bevor du kommentieren kannst. Show author in people tab - + Autor auf der Registerkarte Personen anzeigen @@ -10441,9 +9691,9 @@ bevor du kommentieren kannst. - + Show column - + Spalte anzeigen @@ -10458,10 +9708,10 @@ bevor du kommentieren kannst. <b>Loading...<b> - + <b>Lade...<b> - + Anonymous/unknown posts forwarded if reputation is positive @@ -10499,53 +9749,54 @@ bevor du kommentieren kannst. Last seen at friends: - + Zuletzt bei Freunden gesehen: Moderators - + Moderatoren Missing Message: This message is missing. You should receive it later. - + Fehlende Nachricht: +Diese Nachricht fehlt. Sie sollten es später erhalten. - + No result. - + Kein Ergebnis. Found %1 results. - + %1 Ergebnisse gefunden. - + Failed to retrieve this message. Is the database currently overloaded? - + Diese Nachricht konnte nicht abgerufen werden. Ist die Datenbank derzeit überlastet? No data for this message. Is the database corrupted? - + Keine Daten für diese Nachricht. Ist die Datenbank beschädigt? More than one entry for this message. Is the database corrupted? - + Mehr als ein Eintrag für diese Nachricht. Ist die Datenbank beschädigt? - + (Latest) - + (Neueste) (Old) - + (Alt) @@ -10604,12 +9855,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums Foren @@ -10640,35 +9891,16 @@ This message is missing. You should receive it later. Andere Foren - - GxsForumsFillThread - - Waiting - Warten - - - Retrieving - Abrufen - - - Loading - Laden - - GxsGroupDialog - + Name Name - Add Icon - Icon hinzufügen - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels Schlüsselempfänger können in eingeschränkten Gruppen veröffentlichen und können private Kanäle ansehen und darin veröffentlichen @@ -10677,22 +9909,14 @@ This message is missing. You should receive it later. Share Publish Key Veröffentlichungsschlüssel freigeben - - check peers you would like to share private publish key with - Markiere die Nachbarn, an welche du den privaten Veröffentlichungsschlüssel verteilen willst - - - Share Key With - Schlüssel verteilen an - - + Description Beschreibung - + Message Distribution Nachrichtenverteilung @@ -10700,7 +9924,7 @@ This message is missing. You should receive it later. - + Public Öffentlich @@ -10719,14 +9943,6 @@ This message is missing. You should receive it later. New Thread Neues Thema - - Required - Notwendig - - - Encrypted Msgs - Verschlüsselte Nachr. - Personal Signatures @@ -10768,7 +9984,7 @@ This message is missing. You should receive it later. Spamschutz - + Comments: Kommentare: @@ -10778,7 +9994,7 @@ This message is missing. You should receive it later. TextLabel - TextLabel + TextLabel @@ -10791,14 +10007,14 @@ This message is missing. You should receive it later. Anti-Spam: - + All People - + Alle Leute My Contacts - + Meine Kontakte @@ -10807,14 +10023,14 @@ This message is missing. You should receive it later. - + Restricted to circle: Beschränkt auf Kreis: - + Limited to your friends - + Beschränkt auf deine Freunde @@ -10829,31 +10045,31 @@ This message is missing. You should receive it later. - + Message tracking Nachrichtenverfolggung - - + + PGP signature required PGP-Signatur erforderlich - + Never Nie - + Only friends nodes in group - + Nur Freundesknoten in der Gruppe Failed to Prepare Group MetaData: - + Gruppenmetadaten konnten nicht vorbereitet werden: @@ -10861,30 +10077,28 @@ This message is missing. You should receive it later. Bitte Name hinzufügen - + PGP signature from known ID required PGP-Signatur aus bekannter Kennung erforderlich - + + + [None] + [Keine] + + + Load Group Logo Gruppenlogo laden - + Submit Group Changes Gruppenänderungen übermitteln - Failed to Prepare Group MetaData - please Review - Aufbereiten der Gruppenmetadaten fehlgeschlagen - bitte überprüfen - - - Will be used to send feedback - Wird zum Senden von Rückmeldungen genutzt werden - - - + Owner: Eigentümer: @@ -10894,12 +10108,12 @@ This message is missing. You should receive it later. Gib hier eine aussagekräftige Beschreibung ein - + Info Info - + ID ID @@ -10909,14 +10123,14 @@ This message is missing. You should receive it later. Letzter Beitrag - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> - + <html><head/><body><p>Nachrichten werden weit über Ihre Freundesknoten hinaus verbreitet, solange die Leute den Kanal/das Forum/den von Ihnen erstellten Beitrag abonnieren.</p></body></html > <html><head/><body><p>Messages will spread among Retroshare nodes that host one of the identities listed as member of the circle and who also subscribe the media. Only these nodes will be able to see that this forum/channel/posted media exists. </p></body></html> - + <html><head/><body><p>Nachrichten werden an Retroshare-Knoten verteilt, die eine der als Mitglied des Kreises aufgeführten Identitäten hosten und auch die Medien abonnieren. Nur diese Knoten können sehen, dass dieses Forum/dieser Kanal/dieses gepostete Medium existiert. </p></body></html> @@ -10926,12 +10140,12 @@ This message is missing. You should receive it later. <html><head/><body><p>Messages will only be distributed to the selected subset of your friend nodes. They will not forward messages with each other, but only use your own node as a central hub to distribute them.</p></body></html> - + <html><head/><body><p>Nachrichten werden nur an die ausgewählte Teilmenge Ihrer Freundesknoten verteilt. Sie leiten Nachrichten nicht untereinander weiter, sondern nutzen nur Ihren eigenen Knoten als zentralen Hub, um sie zu verteilen.</p></body></html> Restricted node group - + Auf Knotengruppe @@ -10941,27 +10155,27 @@ This message is missing. You should receive it later. <html><head/><body><p>Click to add a Logo</p></body></html> - + <html><head/><body><p>Hier klicken, um ein Logo hinzuzufügen</p></body></html> <html><head/><body><p>The identity here can be used to send feedback.</p></body></html> - + <html><head/><body><p>Die Identität hier kann zum Senden von Feedback verwendet werden.</p></body></html> Add moderators - + Moderatoren hinzufügen Re&quired - + Erforderlich Encrypted &Msgs - + Verschlüsselte &Nachrichten @@ -10984,7 +10198,12 @@ This message is missing. You should receive it later. - + + Author: + Autor: + + + Popularity Beliebtheit @@ -10997,30 +10216,25 @@ This message is missing. You should receive it later. Moderators: - + Moderatoren: - + Created - + Erstellt - + Cancel - Abbrechen + Abbrechen - + Create - Erstellen + Erstellen - - Author - Autor - - - + GxsIdLabel GxsIdLabel @@ -11028,7 +10242,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading Lade @@ -11065,17 +10279,17 @@ This message is missing. You should receive it later. Remove this search - + Entfernen Sie diese Suche Remove all searches - + Alle Suchanfragen entfernen Request data - + Daten anfordern @@ -11088,9 +10302,9 @@ This message is missing. You should receive it later. Details bearbeiten - + Synchronise posts of last... - + Synchronisieren Sie die Beiträge der letzten... @@ -11137,20 +10351,20 @@ This message is missing. You should receive it later. Store posts for at most... - + Speichern Sie Beiträge höchstens... Share publish permissions... - + Veröffentlichungsberechtigungen teilen... - + Search for - + Suchen nach - + Copy RetroShare Link RetroShare-Link kopieren @@ -11173,7 +10387,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature Keine Signatur @@ -11186,50 +10400,39 @@ This message is missing. You should receive it later. GxsIdDetails - Loading - Lade - - - + Not found Nicht gefunden - - No Signature - Keine Signatur - - - + + [Banned] [Gebannt] - - Authentication - Authentifizierung - unknown Key unbekannter Schlüssel - anonymous - anonym - - - + Loading... - + Lade... [None] - + [Keine] - + + [Nobody] + [Niemand] + + + Identity&nbsp;name Identitätsname @@ -11241,11 +10444,7 @@ This message is missing. You should receive it later. Node - Netzknoten - - - Signed&nbsp;by - Unterzeichnet&nbsp;von + Knoten @@ -11253,80 +10452,84 @@ This message is missing. You should receive it later. [Unbekannt] + + GxsIdLabel + + + [Nobody] + [Niemand] + + GxsIdStatistics Router Statistics - Routerstatistiken + Routerstatistiken GxsIdStatisticsWidget - + Total identities: - + Gesamte Identitäten: Usage types - + Nutzungsarten Usage per service - + Nutzung pro Service Identity age (in weeks): - + Alter der Identität (in Wochen): Last used (hours ago): - + Zuletzt verwendet (vor Stunden): Managed keys - Verwaltete Schlüssel + Verwaltete Schlüssel : Service ID = - : Dienst-ID = + : Dienst-ID = Routing matrix ( - Routingmatrix ( + Routingmatrix ( [Unknown identity] - [Unbekannte Identität] + [Unbekannte Identität] GxsIdTreeItemDelegate - + [Unknown] - [Unbekannt] + [Unbekannt] GxsMessageFramePostWidget - - Loading - Laden - Loading... - + Lade... @@ -11339,27 +10542,27 @@ This message is missing. You should receive it later. Random Bias: %1 - + Zufällige Tendenz: %1 GXS Groups: - + Service: %1 (%2) - Group ID: %3, policy: %4, status: %5, last contact: %6 - + Dienst: %1 (%2) – Gruppen-ID: %3, Richtlinie: %4, Status: %5, letzter Kontakt: %6 Peer: %1: status: %2/%3, last contact: %4, Master key: %5. - + Peer: %1:\t status: %2/%3, \t letzter Kontakt: %4, \t Master-Schlüssel: %5. Peer: %1: no information available - + Peer: %1: keine Informationen verfügbar @@ -11367,108 +10570,108 @@ This message is missing. You should receive it later. Router Statistics - Routerstatistiken + Routerstatistiken GroupBox - + ID - + Destination - Ziel + Ziel Data status - Datenstatus + Datenstatus Data size - + Datengröße Data hash - + Datenhash Sending time - + Sendezeit Sending time (secs ago) - Sendezeit (vergangene Sekunden) + Sendezeit (vergangene Sekunden) Publish TS - + Number of messages - + Anzahl der Nachrichten Group ID - + Destination ID - + Ziel-ID Gxs Transport Groups: - + Gxs-Transportgruppen: Group ID / Author - + Gruppen-ID/Autor Local size of data - + Lokale Datengröße Subscribed - Abonniert + Abonniert Popularity - Beliebtheit + Beliebtheit View details - + Details anzeigen Unknown Peer - Unbekannter Nachbar + Unbekannter Nachbar Pending data items - + Ausstehende Datenelemente @@ -11486,41 +10689,6 @@ This message is missing. You should receive it later. Nein - - GxsTunnelsDialog - - Authenticated tunnels: - Authentifizierte Tunnel: - - - Tunnel ID: %1 - Tunnelkennung: %1 - - - from: %1 - von: %1 - - - to: %1 - an: %1 - - - status: %1 - Status: %1 - - - total sent: %1 bytes - Gesendet gesamt: %1 bytes - - - total recv: %1 bytes - Empfangen gesamt: %1 bytes - - - Unknown Peer - Unbekannter Nachbar - - HashBox @@ -11545,17 +10713,17 @@ This message is missing. You should receive it later. Examining shared files... - Prüfe freigegebene Dateien... + Prüfe freigegebene Dateien... Hashing file - Erstelle Prüfsumme + Erstelle Prüfsumme Saving file index... - Speichere Dateiindex... + Speichere Dateiindex... @@ -11738,7 +10906,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -11754,7 +10922,7 @@ p, li { white-space: pre-wrap; } - + Authors Autoren @@ -11773,7 +10941,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -11851,28 +11019,24 @@ p, li { white-space: pre-wrap; } Formular - + Add friend - + Freund hinzufügen Do you need help with Retroshare? - + Benötigen Sie Hilfe bei Retroshare? - + <html><head/><body><p>Share your RetroShare ID</p></body></html> - + <html><head/><body><p>Teilen Sie Ihre RetroShare-ID</p></body></html> This is your Retroshare ID. Copy and share with your friends! - - - - Add certificate file - Zertifikatsdatei hinzufügen + Dies ist Ihre Retroshare-ID. Kopieren Sie es und teilen Sie es mit Ihren Freunden! @@ -11883,19 +11047,20 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Copy your RetroShare ID to clipboard</p></body></html> - + <html><head/><body><p>Kopieren Sie Ihre RetroShare-ID in die Zwischenablage</p></body></html> Open Source cross-platform, private and secure decentralized communication platform. - + Plattformübergreifendes Open Source, +Private und sichere dezentrale Kommunikationsplattform. - + Did you receive a Retroshare ID from a friend? - + Haben Sie eine Retroshare-ID von einem Freund erhalten? @@ -11903,17 +11068,17 @@ private and secure decentralized communication platform. Webhilfe öffnen - + Copy your Cert to Clipboard - Dein Zertifikat in die Zwischenablage kopieren + Dein Zertifikat in die Zwischenablage kopieren Save your Cert into a File - Zertifikat als Datei speichern + Zertifikat als Datei speichern - + Send via Email Über E-Mail senden @@ -11925,65 +11090,84 @@ private and secure decentralized communication platform. Recommend friends to each others - + Empfehlen Sie einander Freunde weiter Copy your Retroshare ID to Clipboard + Kopieren Sie Ihre Retroshare-ID in die Zwischenablage + + + + Include current local IP + Aktuelle lokale IP einschließen + + + + Include current external IP + Aktuelle externe IP einschließen + + + + Include my DNS + Meinen DNS einbeziehen + + + + Include all IPs history + Beziehen Sie den gesamten IP-Verlauf ein + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - + Include all your known IPs - + Geben Sie alle Ihre bekannten IP-Adressen an - + Use old certificate format - + Verwenden Sie das alte Zertifikatsformat Displays the certificate format used up to version 0.6.5 Old Retroshare nodes will not understand the new short format - + - + Use new (short) certificate format - + Verwenden Sie das neue (kurze) Zertifikatsformat - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way - + Ihr Retroshare-Zertifikat wurde in die Zwischenablage kopiert, fügen Sie es ein und senden Sie es per E-Mail oder auf andere Weise an Ihren Freund Your Retroshare ID is copied to Clipboard, paste and send it to your friend via email or some other way - + Ihre Retroshare-ID wurde in die Zwischenablage kopiert, fügen Sie es ein und senden Sie es per E-Mail oder auf andere Weise an Ihren Freund RetroShare Invite - RetroShare-Einladung + RetroShare-Einladung - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... Speichern als... RetroShare Certificate (*.rsc );;All Files (*) - RetroShare-Zertifikat (*.rsc );;Alle Dateien (*) + RetroShare-Zertifikat (*.rsc );;Alle Dateien (*) @@ -12056,7 +11240,7 @@ p, li { white-space: pre-wrap; } Auto-Ban all identities signed by the same node - + Auto-Ban aller Identitäten, die von demselben Knoten unterzeichnet wurden @@ -12205,17 +11389,17 @@ p, li { white-space: pre-wrap; } Negative (Banned by you) - + Negativ (von Ihnen verbannt) Positive (according to your friends) - + Positiv (nach Meinung Ihrer Freunde) Negative (according to your friends) - + Negativ (nach Meinung Ihrer Freunde) @@ -12241,14 +11425,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Alle - + Reputation Reputation @@ -12258,12 +11442,12 @@ p, li { white-space: pre-wrap; } Suchen - + Anonymous Id Anonyme ID - + Create new Identity Neue Identität erstellen @@ -12273,7 +11457,7 @@ p, li { white-space: pre-wrap; } Neuen Kreis erstellen - + Persons Personen @@ -12288,27 +11472,27 @@ p, li { white-space: pre-wrap; } Person - + Close Schließen - + Ban-option: - + Auto-Ban all identities signed by the same node - + Auto-Ban aller Identitäten, die von demselben Knoten unterzeichnet wurden - + Friend votes: - + Freund Bewertungen: - + Positive votes Positive Stimmen @@ -12324,29 +11508,39 @@ p, li { white-space: pre-wrap; } Negative Stimmen - + Created on : - + Erstellt am: - + + Auto-Ban profile + Auto-Ban-Profil + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + Identität editieren + + + Usage statistics - + Nutzungsstatistiken - + Circles Kreise - + Circle name Kreisname @@ -12366,18 +11560,20 @@ p, li { white-space: pre-wrap; } Persönliche Kreise - + + Edit identity Identität bearbeiten - + + Delete identity Identität löschen - + Chat with this peer Chatte mit diesem Nachbarn @@ -12387,78 +11583,78 @@ p, li { white-space: pre-wrap; } Stellt einen Fernchat mit diesem Nachbarn her - + Owner node ID : - Eigentümerknoten-ID + Eigentümerknoten-ID : - + Identity name : Identitätsname : - + () () - + Identity ID Identitäts-ID - + Send message Nachricht senden - + Identity info Identitätsinformationen - + Identity ID : Identitäts-ID : - + Owner node name : Eigentümerknotenname : - + Create new... - + Neu erstellen... - + Type: Typ: - + Send Invite Einladung senden - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: Deine Meinung: - + Negative Negativ - + Neutral Neutral @@ -12469,17 +11665,17 @@ p, li { white-space: pre-wrap; } Positiv - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: Insgesamt: - + Anonymous Anonym @@ -12494,24 +11690,24 @@ p, li { white-space: pre-wrap; } Kennung suchen - + This identity is owned by you Diese Identität gehört dir - - + + My own identities - Meine eigenen Identitäten + Meine Identitäten - - + + My contacts Meine Kontakte - + Show Items @@ -12523,10 +11719,15 @@ p, li { white-space: pre-wrap; } Linked to my node + Verknüpft mit meinem Knoten + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - + Other circles Andere Kreise @@ -12536,7 +11737,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: Kreiskennung: @@ -12573,17 +11774,17 @@ p, li { white-space: pre-wrap; } User (Can only request membership). - + Benutzer (kann nur die Mitgliedschaft beantragen). Distribution: - Verteilung: + Verteilung: subscribed (Receive/forward membership requests from others and invite list). - + abonniert (Empfang/Weiterleitung von Beitrittsanfragen anderer und Einladungsliste). @@ -12603,7 +11804,7 @@ p, li { white-space: pre-wrap; } Full member (you have access to data limited to this circle) - + Vollmitglied (Sie haben Zugang zu Daten, die auf diesen Kreis beschränkt sind) @@ -12611,7 +11812,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: Identitätskennung: @@ -12633,7 +11834,7 @@ p, li { white-space: pre-wrap; } Subscription request pending - + Abonnementanforderung ausstehend @@ -12641,14 +11842,14 @@ p, li { white-space: pre-wrap; } unbekannt - + Invited Eingeladen Subscription pending - + Abonnement ausstehend @@ -12656,7 +11857,7 @@ p, li { white-space: pre-wrap; } Mitglied - + Edit Circle Kreis bearbeiten @@ -12668,12 +11869,12 @@ p, li { white-space: pre-wrap; } Request subscription - + Abonnement anfordern Accept circle invitation - + Kreiseinladung annehmen @@ -12683,7 +11884,7 @@ p, li { white-space: pre-wrap; } Cancel subscribe request - + Abo-Anfrage abbrechen @@ -12691,7 +11892,7 @@ p, li { white-space: pre-wrap; } for identity - für Identität + für Identität @@ -12701,10 +11902,10 @@ p, li { white-space: pre-wrap; } Grant membership - + Mitgliedschaft gewähren - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -12712,7 +11913,7 @@ These identities will soon be not supported anymore. - + [Unknown node] [Unbekannter Knoten] @@ -12721,7 +11922,7 @@ These identities will soon be not supported anymore. Unverified signature from node - + Ungeprüfte Signatur vom Knoten @@ -12742,7 +11943,7 @@ These identities will soon be not supported anymore. Identity owned by you, linked to your Retroshare node but not yet validated - + Identität, die Ihnen gehört und mit Ihrem Retroshare-Knoten verknüpft, aber noch nicht validiert ist @@ -12755,19 +11956,19 @@ These identities will soon be not supported anymore. Anonyme Identität - + Boards - + GxsMail author - + GxsMail Autor GxsCircles - + @@ -12782,7 +11983,7 @@ These identities will soon be not supported anymore. Group author for group %1 in service %2 - + Gruppenautor für Gruppe %1 im Dienst %2 @@ -12797,7 +11998,7 @@ These identities will soon be not supported anymore. Message - Nachricht + Nachricht @@ -12807,7 +12008,7 @@ These identities will soon be not supported anymore. Message in chat room %1 - + Nachricht im Chatraum %1 @@ -12827,48 +12028,43 @@ These identities will soon be not supported anymore. Membership verification in circle "%1" (%2). - + Verifizierung der Mitgliedschaft im Kreis "%1" (%2). Membership verification in circle (ID=%1). - + Verifizierung der Mitgliedschaft im Kreis (ID=%1). - + information This identity link was copied to your clipboard. Paste it in a mail, or a message to transmit the identity to someone. - + Dieser Identitätslink wurde in Ihre Zwischenablage kopiert. Fügen Sie ihn in eine E-Mail oder eine Nachricht ein, um die Identität an jemanden zu übermitteln. Copy identity to clipboard - + Identität in die Zwischenablage kopieren - + Banned Gebannt - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive - positiv + positiv negative - negativ + negativ @@ -12878,17 +12074,17 @@ These identities will soon be not supported anymore. Negative (Banned by you) - + Negativ (von Ihnen verbannt) Positive (according to your friends) - + Positiv (nach Meinung Ihrer Freunde) Negative (according to your friends) - + Negativ (nach Meinung Ihrer Freunde) @@ -12905,19 +12101,11 @@ These identities will soon be not supported anymore. Forums Foren - - Posted - Veröffentlicht - Chat Chat - - Unknown - Unbekannt - [Unknown] @@ -12938,10 +12126,6 @@ These identities will soon be not supported anymore. Creation of author signature in service %1 - - Message/vote/comment - Nachricht/Stimme/Kommentar - Distant message signature validation. @@ -12955,22 +12139,18 @@ These identities will soon be not supported anymore. Signature validation in distant tunnel system. - + Signaturvalidierung im entfernten Tunnelsystem. Signature in distant tunnel system. - + Signatur im entfernten Tunnelsystem. Generic signature validation. - - Generic signature. - Generische Signatur. - Generic encryption. @@ -12982,7 +12162,7 @@ These identities will soon be not supported anymore. Generische Entschlüsselung. - + Add to Contacts Zu Kontakte hinzufügen @@ -13019,7 +12199,7 @@ These identities will soon be not supported anymore. Too many identities - + Zu viele Identitäten @@ -13032,21 +12212,21 @@ These identities will soon be not supported anymore. - - - + + + People Leute - + Your Avatar Click here to change your avatar Dein Avatar - + Linked to neighbor nodes Mit Nachbarknoten verknüpft @@ -13056,7 +12236,7 @@ These identities will soon be not supported anymore. Mit entfernten Netzknoten verknüpft - + Linked to a friend Retroshare node Mit befreundetem RetroShare-Netzknoten verknüpft @@ -13071,7 +12251,7 @@ These identities will soon be not supported anymore. Mit unbekanntem RetroShare-Netzknoten verknüpft - + Chat with this person Mit dieser Person chatten @@ -13086,12 +12266,12 @@ These identities will soon be not supported anymore. Fernchat mit dieser Person abgelehnt. - + Last used: Zuletzt verwendet: - + +50 Known PGP +50 PGP bekannt @@ -13111,12 +12291,12 @@ These identities will soon be not supported anymore. Möchtest du diese Identität wirklich löschen? - + Owned by Im Besitz von - + Node name: Netzknotenname: @@ -13126,7 +12306,7 @@ These identities will soon be not supported anymore. Netzknoten-ID : - + Really delete? Wirklich löschen? @@ -13134,7 +12314,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname Spitzname @@ -13164,22 +12344,29 @@ These identities will soon be not supported anymore. Pseudonym - + Import image - + Bild importieren Image files (*.jpg *.png);;All files (*) - + Bilddateien (*.jpg *.png);;Alle Dateien (*) - - Use the mouse to zoom and adjust the image for your avatar. - + + + No Avatar chosen. A default image will be automatically displayed from your new identity. + Kein Avatar ausgewählt. Von Ihrer neuen Identität wird automatisch ein Standardbild angezeigt. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + Verwenden Sie die Maus, um das Bild für Ihren Avatar zu vergrößern und anzupassen. Drücken Sie Entf, um es zu entfernen. + + + New identity Neue Identität @@ -13193,7 +12380,7 @@ These identities will soon be not supported anymore. - + @@ -13203,7 +12390,12 @@ These identities will soon be not supported anymore. N/A - + + No avatar chosen + Kein Avatar ausgewählt + + + Edit identity Identität bearbeiten @@ -13211,64 +12403,60 @@ These identities will soon be not supported anymore. Update - Aktualisieren + Aktualisieren - - + + Profile password needed. - + Profilpasswort erforderlich. - + - + Identity creation failed - + Identitätserstellung fehlgeschlagen - - + + Cannot create an identity linked to your profile without your profile password. - + Ohne Ihr Profilpasswort können Sie keine mit Ihrem Profil verknüpfte Identität erstellen. - + Identity creation success - + Erfolgreiche Identitätserstellung Your new identity was successfuly created, its ID is %1. - + Ihre neue Identität wurde erfolgreich erstellt, ihre ID ist %1. Cannot create identity. Something went wrong. - + Identität kann nicht erstellt werden. Etwas ist schief gelaufen. Cannot create identity. Something went wrong. Check your profile password. - + Identität kann nicht erstellt werden. Etwas ist schief gelaufen. Überprüfen Sie Ihr Profilpasswort. - + Identity update failed - + Die Identitätsaktualisierung ist fehlgeschlagen Cannot update identity. Something went wrong. Check your profile password. - + Identität kann nicht aktualisiert werden. Etwas ist schief gelaufen. Überprüfen Sie Ihr Profilpasswort. - Error getting key! - Fehler beim Holen des Schlüssels! - - - + Error KeyID invalid Fehler Schlüssel-ID ungültig @@ -13283,7 +12471,7 @@ These identities will soon be not supported anymore. Unbekannter Klarname - + Create New Identity Neue Identität erstellen @@ -13293,9 +12481,14 @@ These identities will soon be not supported anymore. Typ - + Choose image... - + Bild auswählen... + + + + Remove + Entfernen @@ -13322,27 +12515,23 @@ These identities will soon be not supported anymore. Hinzufügen - + Create - Erstellen + Erstellen Cancel - Abbrechen + Abbrechen - + Your Avatar Click here to change your avatar Dein Avatar - Set Avatar - Avatar festlegen - - - + Linked to your profile Mit deinem Profil verknüpft @@ -13352,7 +12541,7 @@ These identities will soon be not supported anymore. Du kannst eine oder mehrere Identitäten haben. Sie werden genutzt, um in Chatlobbys, Foren und Kanalkommentaren zu schreiben. Sie dienen als Zieladresse für Fernchat und das RetroShare-Fernnachrichtensystem. - + The nickname is too short. Please input at least %1 characters. Der Spitzname ist zu kurz. Bitte mindestens %1 Zeichen eingeben. @@ -13382,18 +12571,18 @@ These identities will soon be not supported anymore. Positive votes - Positive Stimmen + Positive Stimmen 0 - 0 + 0 Negative votes - Negative Stimmen + Negative Stimmen @@ -13411,10 +12600,6 @@ These identities will soon be not supported anymore. PGP name: PGP-Name: - - GXS id: - GXS-ID: - PGP id: @@ -13430,7 +12615,7 @@ These identities will soon be not supported anymore. - + Copy Kopieren @@ -13440,12 +12625,12 @@ These identities will soon be not supported anymore. Entfernen - + %1 's Message History - + Mark all Alle markieren @@ -13464,26 +12649,38 @@ These identities will soon be not supported anymore. Quote - - Send - Senden - ImageUtil - - + + Save image Bild speichern - Cannot save the image, invalid filename - + Save Picture File + Bilddatei speichern + + + + Pictures (*.png *.xpm *.jpg) + Bilder (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + Das Bild kann nicht gespeichert werden, ungültiger Dateiname + + + + Copy image + Bild kopieren + + + + Not an image Kein Bild @@ -13493,84 +12690,99 @@ These identities will soon be not supported anymore. Form - Formular + Formular JSON API Server - + - + Enable RetroShare JSON API Server - + RetroShare JSON API Server aktivieren - + Port: - Port: + Port: - + Listen Address: - + Listenadresse: - + + Status: + Status: + + + 127.0.0.1 - 127.0.0.1 + 127.0.0.1 - + Token: - + <html><head/><body><p>Tokens should spell as &quot;user:password&quot; where both user and password are alphanumeric strings.</p></body></html> - + <html><head/><body><p>Tokens sollten als &quot;Benutzer:Passwort&quot; geschrieben werden, wobei sowohl Benutzer als auch Passwort alphanumerische Zeichenfolgen sind.</p></body></html> Add - Hinzufügen + Hinzufügen Remove - Entfernen + Entfernen - Authenticated Tokens - + Authenticated Tokens: + Authentifizierte Token: + + + + Registered services: + Registrierte Dienste: Apply settings - + Einstellungen übernehmen - + JSON API - + + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare stellt eine JSON-API zur Verfügung, die es anderen Programmen ermöglicht, mit seinem Kern zu kommunizieren, indem sie Token-gesteuerte HTTP-Anfragen an http://localhost:[port] stellen. Bitte lesen Sie in der Retroshare-Dokumentation nach, wie Sie diese Funktion nutzen können. </p> <p>Wenn Sie nicht wissen, was Sie tun, sollten Sie an dieser Seite nichts ändern müssen. Die Weboberfläche beispielsweise registriert automatisch ihr eigenes Token für die JSON-API, das in der Liste der authentifizierten Token angezeigt wird, nachdem Sie es aktiviert haben.</p>> LocalSharedFilesDialog - - + + Open File Datei öffnen - + Open Folder Ordner öffnen - + Checking... Überprüfe... @@ -13580,19 +12792,19 @@ These identities will soon be not supported anymore. Dateien überprüfen - + Recommend in a message to... - + Empfehlen Sie in einer Nachricht an... Share on channel... - + Auf Kanal teilen... Share on forum... - + Im Forum teilen... @@ -13608,7 +12820,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend Freund hinzufügen @@ -13624,7 +12836,8 @@ These identities will soon be not supported anymore. - + + Options Optionen @@ -13645,7 +12858,7 @@ These identities will soon be not supported anymore. - + Quit Schließen @@ -13656,12 +12869,12 @@ These identities will soon be not supported anymore. Schnellstart-Assistent - + RetroShare %1 a secure decentralized communication platform RetroShare %1 - eine sichere und dezentralisierte Kommunikationsplattform - + Unfinished unfertig @@ -13690,11 +12903,12 @@ Bitte gib etwas Speicher frei und drücke OK. + Status Status - + Notify Meldungen @@ -13705,31 +12919,35 @@ Bitte gib etwas Speicher frei und drücke OK. + Open Messages Nachrichten öffnen - + + Bandwidth Graph Bandbreiten-Graph - + Applications Anwendungen + Help Hilfe - + + Minimize Minimieren - + Maximize Maximieren @@ -13744,7 +12962,12 @@ Bitte gib etwas Speicher frei und drücke OK. RetroShare - + + Close window + Fenster schließen + + + %1 new message %1 neue Nachricht @@ -13774,7 +12997,7 @@ Bitte gib etwas Speicher frei und drücke OK. %1 Freunde verbunden - + Do you really want to exit RetroShare ? Möchtest du RetroShare wirklich beenden? @@ -13794,7 +13017,7 @@ Bitte gib etwas Speicher frei und drücke OK. Anzeigen - + Make sure this link has not been forged to drag you to a malicious website. Vergewissere dich, dass dieser Link nicht gefälscht ist, um dich auf eine bösartige Webseite zu locken. @@ -13806,17 +13029,17 @@ Bitte gib etwas Speicher frei und drücke OK. Never ask me again - + Frag mich nie wieder This will be saved only for this session. - + Dies wird nur für diese Sitzung gespeichert. This will be saved permanently. You'll need to clean RetroShare.conf to revert. - + Dies wird dauerhaft gespeichert. Um dies rückgängig zu machen, müssen Sie die RetroShare.conf wieder zurücksetzen. @@ -13839,12 +13062,13 @@ Bitte gib etwas Speicher frei und drücke OK. Serviceberechtigungsmatrix - + + Statistics Statistiken - + Show web interface Weboberfläche anzeigen @@ -13859,7 +13083,7 @@ Bitte gib etwas Speicher frei und drücke OK. Ordner ist sehr gering (Die aktuelle Grenze ist - + Really quit ? Wirklich beenden? @@ -13868,17 +13092,17 @@ Bitte gib etwas Speicher frei und drücke OK. MessageComposer - + Compose Verfassen - + Contacts Kontakte - + Paragraph Absatz @@ -13914,12 +13138,12 @@ Bitte gib etwas Speicher frei und drücke OK. Überschrift 6 - + Font size Schriftgröße - + Increase font size Schrift vergrößern @@ -13934,32 +13158,32 @@ Bitte gib etwas Speicher frei und drücke OK. Fett - + Italic Kursiv - + Alignment Ausrichtung - + Add an Image Ein Bild hinzufügen - + Sets text font to code style Setzt Schriftart auf Codestil - + Underline Unterstrichen - + Subject: Betreff: @@ -13970,32 +13194,32 @@ Bitte gib etwas Speicher frei und drücke OK. - + Tags Schlagwörter - + Address list: Adressliste: - + Recommend this friend Diesen Freund empfehlen - + Set Text color Textfarbe festlegen - + Set Text background color Texthintergrundfarbe festlegen - + Recommended Files Empfohlene Dateien @@ -14065,7 +13289,7 @@ Bitte gib etwas Speicher frei und drücke OK. Blockquote hinzufügen - + Send To: Senden an: @@ -14089,10 +13313,6 @@ Bitte gib etwas Speicher frei und drücke OK. &Justify &Blocksatz - - All addresses (mixed) - Alle Adressen (gemischt) - All people @@ -14104,7 +13324,7 @@ Bitte gib etwas Speicher frei und drücke OK. Meine Kontakte - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> Hallo, <br> ich empfehle dir einen guten Freund von mir. Du kannst ihm vertrauen, wenn du mir vertraust. <br> @@ -14124,18 +13344,18 @@ Bitte gib etwas Speicher frei und drücke OK. möchte mit dir in RetroShare befreundet sein - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team Hallo %1,<br><br>%2 möchte mit dir in RetroShare befreundet sein.<br><br>Jetzt antworten:<br>%3<br><br>Grüße,<br>Das RetroShare Team - - + + Save Message Nachricht speichern - + Message has not been Sent. Do you want to save message to draft box? Nachricht wurde noch nicht gesendet. @@ -14147,7 +13367,17 @@ Möchtest du die Nachricht in den Entwürfen speichern? RetroShare Link einfügen - + + Will not reply + Wird nicht antworten + + + + There is no point in replying to a notification message! + Es hat keinen Sinn, auf eine Benachrichtigung zu antworten! + + + Add to "To" Zu "An" hinzufügen @@ -14167,7 +13397,7 @@ Möchtest du die Nachricht in den Entwürfen speichern? Als empfohlen hinzufügen - + Original Message Ursprüngliche Nachricht @@ -14177,21 +13407,21 @@ Möchtest du die Nachricht in den Entwürfen speichern? Von - + - + To An - - + + Cc Cc - + Sent Gesendet @@ -14206,7 +13436,7 @@ Möchtest du die Nachricht in den Entwürfen speichern? Am %1, schrieb %2: - + Re: Re: @@ -14216,30 +13446,30 @@ Möchtest du die Nachricht in den Entwürfen speichern? Fwd: - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? Möchtest du die Nachricht ohne Betreff senden ? - + Please insert at least one recipient. Bitte gib mindestens einen Empfänger ein. - + Bcc Bcc - + Unknown Unbekannt @@ -14354,13 +13584,13 @@ Möchtest du die Nachricht in den Entwürfen speichern? Details - + Open File... Datei öffnen... - + HTML-Files (*.htm *.html);;All Files (*) HTML-Dateien (*.htm *.html);;Alle Dateien (*) @@ -14380,7 +13610,7 @@ Möchtest du die Nachricht in den Entwürfen speichern? PDF exportieren - + Message has not been Sent. Do you want to save message ? Nachricht noch nicht versandt. @@ -14402,48 +13632,48 @@ Möchtest du die Nachricht speichern ? Zusätzliche Datei hinzufügen - + Hi,<br>I want to be friends with you on RetroShare.<br> - + Hallo,<br>Ich möchte mit dir auf RetroShare befreundet sein.<br> Invite message - + Einladungsnachricht Respond now: - + Jetzt reagieren: Message Size: %1 - + Größe der Nachricht: %1 It remains %1 characters after HTML conversion. - + Es verbleiben %1 Zeichen nach der HTML-Konvertierung. Warning: This message is too big of %1 characters after HTML conversion. - + Warnung: Diese Nachricht ist mit %1 Zeichen zu groß nach der HTML-Konvertierung. - - + + Close Schließen - + From: Von: - + Friend Nodes Befreundete Netzknoten @@ -14488,13 +13718,13 @@ Möchtest du die Nachricht speichern ? Geordnete Liste (Römisch groß) - - + + Thanks, <br> Danke, <br> - + Distant identity: Fernidentität: @@ -14504,12 +13734,12 @@ Möchtest du die Nachricht speichern ? [Fehlend] - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. Bitte erstelle eine Identität, um Fernnachrichten zu signieren oder entferne die fernen Nachbarn aus der Zieladressliste. - + Node name & id: Netzknotenname & ID: @@ -14554,7 +13784,7 @@ Möchtest du die Nachricht speichern ? Load Emoticons - + Emoticons laden @@ -14587,7 +13817,7 @@ Möchtest du die Nachricht speichern ? Standard - + A new tab Neuem Tab @@ -14597,7 +13827,7 @@ Möchtest du die Nachricht speichern ? Neuem Fenster - + Edit Tag Schlagwort bearbeiten @@ -14620,7 +13850,7 @@ Möchtest du die Nachricht speichern ? MessageToaster - + Sub: Betreff: @@ -14628,35 +13858,35 @@ Möchtest du die Nachricht speichern ? MessageUserNotify - + Message Nachricht You have %1 new mails - + Sie haben %1 neue Mails You have %1 new mail - + Sie haben %1 neue Mail %1 new mails - + %1 neue Mails %1 new mail - + %1 neue Mail MessageWidget - + Recommended Files Empfohlene Dateien @@ -14666,84 +13896,84 @@ Möchtest du die Nachricht speichern ? Alle Dateien herunterladen - + Subject: Betreff: - + From: Von: - + To: An: - + Cc: Cc: - + Bcc: Bcc: - + Tags: Schlagwörter: - + Reply - + Antworten <html><head/><body><p>Reply to All</p></body></html> - + <html><head/><body><p>Allen antworten</p></body></html> Reply all - Allen antworten + Allen antworten <html><head/><body><p>Forward selected Message</p></body></html> - + <html><head/><body><p>Ausgewählte Nachricht weiterleiten</p></body></html> Forward - Vorwärts + Weiterleiten Delete - Löschen + Löschen <html><head/><body><p>More actions</p></body></html> - + <html><head/><body><p>Weitere Aktionen</p></body></html> More - + Mehr - + Send Invite - Einladung senden + Einladung senden Message Size: - + Nachrichtengröße: @@ -14774,21 +14004,21 @@ Möchtest du die Nachricht speichern ? Save as - + Speichern unter Buttons Text Beside Icon - Button Text neben Icon + Button Text neben Icon Buttons Icon only - + Button nur mit Icon - + Confirm %1 as friend %1 als Freund bestätigen @@ -14798,12 +14028,12 @@ Möchtest du die Nachricht speichern ? %1 als Freund hinzufügen - + View source - + Quelle anzeigen - + No subject Kein Betreff @@ -14813,33 +14043,48 @@ Möchtest du die Nachricht speichern ? Herunterladen - + You got an invite to make friend! You may accept this request. - + Du hast eine Freundschaftseinladung erhalten! Du kannst diese Anfrage annehmen. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + Sie haben eine Einladung erhalten, um Freunde zu werden! Sie können diese Anfrage annehmen und Ihr eigenes Zertifikat zurückschicken - + + more + mehr + + + Document source - + Quelle des Dokuments %1 (%2) - + + + + + Show less + Weniger anzeigen + + + + Show more + Mehr anzeigen - + Download all Alle herunterladen - + Print Document Dokument drucken @@ -14854,12 +14099,12 @@ Möchtest du die Nachricht speichern ? HTML-Dateien (*.htm *.html);;Alle Dateien (*) - + Load images always for this message Bilde für diese Nachricht immer laden - + Hide the attachment pane Anhangsansicht verstecken @@ -14881,42 +14126,6 @@ Möchtest du die Nachricht speichern ? Compose Verfassen - - Reply to selected message - Auf gewählte Nachricht antworten - - - Reply - Antwort - - - Reply all to selected message - Auf gewählte Nachricht an alle Empfänger antworten - - - Reply all - Allen antworten - - - Forward selected message - Gewählte Nachricht weiterleiten - - - Forward - Vorwärts - - - Remove selected message - Gewählte Nachricht entfernen - - - Delete - Löschen - - - Print selected message - Gewählte Nachricht drucken - Print @@ -14995,7 +14204,7 @@ Möchtest du die Nachricht speichern ? MessagesDialog - + New Message Neue Nachricht @@ -15005,60 +14214,16 @@ Möchtest du die Nachricht speichern ? Verfassen - Reply to selected message - Auf gewählte Nachricht antworten - - - Reply - Antworten - - - Reply all to selected message - Auf gewählte Nachricht an alle Empfänger antworten - - - Reply all - Allen antworten - - - Forward selected message - Gewählte Nachricht weiterleiten - - - Foward - Weiterleiten - - - Remove selected message - Gewählte Nachricht entfernen - - - Delete - Löschen - - - Print selected message - Gewählte Nachricht drucken - - - Print - Drucken - - - Display - Anzeigen - - - + - - + + Tags Schlagwörter - - + + Inbox Posteingang @@ -15088,21 +14253,17 @@ Möchtest du die Nachricht speichern ? Papierkorb - + Total Inbox: Posteingang gesamt: - Folders - Ordner - - - + Quick View Schnellansicht - + Print... Drucken... @@ -15112,26 +14273,6 @@ Möchtest du die Nachricht speichern ? Print Preview Druckvorschau - - Buttons Icon Only - Buttons nur mit Icon - - - Buttons Text Beside Icon - Button Text neben Icon - - - Buttons with Text - Buttons mit Text - - - Buttons Text Under Icon - Buttons Text unter dem Icon - - - Set Text Under Icon - Text unter dem Icon - Save As... @@ -15153,7 +14294,7 @@ Möchtest du die Nachricht speichern ? Weiterleiten - + Subject Betreff @@ -15163,7 +14304,7 @@ Möchtest du die Nachricht speichern ? Von - + Date Datum @@ -15173,39 +14314,7 @@ Möchtest du die Nachricht speichern ? Inhalt - Click to sort by attachments - Klicken, um nach Anhang zu sortieren - - - Click to sort by subject - Klicken, um nach Betreff zu sortieren - - - Click to sort by read - Klicken, um nach Gelesen / Ungelesen zu sortieren - - - Click to sort by from - Klicken, um nach Von zu sortieren - - - Click to sort by date - Klicken, um nach Datum zu sortieren - - - Click to sort by tags - Klicken, um nach Schlagwörter zu sortieren - - - Click to sort by star - Klicken, um nach Kennzeichnung zu sortieren - - - Forward selected Message - Gewählte Nachricht weiterleiten - - - + Search Subject Betreff durchsuchen @@ -15214,6 +14323,11 @@ Möchtest du die Nachricht speichern ? Search From Von durchsuchen + + + Search To + + Search Date @@ -15240,14 +14354,14 @@ Möchtest du die Nachricht speichern ? Anhänge durchsuchen - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred - Gekennzeichnet + Markiert @@ -15257,12 +14371,12 @@ Möchtest du die Nachricht speichern ? Spam - + Attachment - + Anhang @@ -15292,7 +14406,7 @@ Möchtest du die Nachricht speichern ? Mark as Junk - + Als Junk markieren @@ -15321,8 +14435,8 @@ Möchtest du die Nachricht speichern ? - Show author in People - + Show in People + In Personen anzeigen @@ -15332,56 +14446,51 @@ Möchtest du die Nachricht speichern ? No message available in your %1. - + In Ihrem %1 ist keine Nachricht verfügbar. - + No message using %1 tag available. - + Keine Nachricht mit %1-Tag verfügbar. No %1 message available. - + Keine %1-Nachricht verfügbar. No starred message available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - + Keine markierte Nachricht verfügbar. Mithilfe von Sternen können Sie Nachrichten einen besonderen Status zuweisen, um sie leichter auffindbar zu machen. Um eine Nachricht zu markieren, klicken Sie auf den hellgrauen Stern neben einer Nachricht. - + + Deletion is not recommended + Eine Löschung wird nicht empfohlen + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + Nachrichten in diesem Feld werden beim Empfang automatisch gelöscht. Das manuelle Löschen einer Nachricht garantiert nicht, dass die Nachricht nicht zugestellt wird. Nachrichten, die nicht zugestellt werden können, bleiben jedoch auf unbestimmte Zeit hier. Möchten Sie fortfahren und löschen? + + + Drafts Entwürfe - + No Box selected. - - - - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - Es sind keine gekennzeichneten Nachrichten vorhanden. Durch die Kennzeichnung kannst du Nachrichten mit einem speziellen Status versehen, sodass sie leichter zu finden sind. Klicke zum Kennzeichnen einer Nachricht auf den hellgrauen Stern neben der jeweiligen Nachricht. - - - No system messages available. - Keine Systemnachrichten vorhanden. + Keine Box ausgewählt. + To - An + An - Click to sort by to - Klicken, um nach Empfänger zu sortieren - - - This message goes to a distant person. - Diese Nachricht geht zu einer entfernten Person. - - - + @@ -15389,30 +14498,10 @@ Möchtest du die Nachricht speichern ? Total: Gesamt: - - Messages - Nachrichten - - - Click to sort by signature - Anklicken, um nach Signatur zu sortieren - - - This message was signed and the signature checks - Diese Nachricht wurde signiert und die Signatur stimmt überein. - - - This message was signed but the signature doesn't check - Diese Nachricht wurde signiert und die Signatur stimmt nicht überein. - - - This message comes from a distant person. - Diese Nachricht kommt von einer entfernten Person. - Mail - + @@ -15436,19 +14525,29 @@ Möchtest du die Nachricht speichern ? MimeTextEdit - + + Save image + Bild speichern + + + + Copy image + Bild kopieren + + + Paste as plain text Als Klartext einfügen Spoiler - + Select text to hide, then push this button - + Wählen Sie den auszublendenden Text aus und drücken Sie dann diese Taste @@ -15466,7 +14565,7 @@ Möchtest du die Nachricht speichern ? Send Invite - Einladung senden + Einladung senden @@ -15490,7 +14589,7 @@ Möchtest du die Nachricht speichern ? - + Expand Erweitern @@ -15500,19 +14599,19 @@ Möchtest du die Nachricht speichern ? Element entfernen - + from - von + von Reply to invite - + Auf Einladung antworten This message invites you to make friend! You may accept this request. - + Diese Nachricht lädt Sie ein, Freundschaft zu schließen! Sie können diese Anfrage annehmen. @@ -15535,7 +14634,7 @@ Möchtest du die Nachricht speichern ? Wartend - + Hide Verbergen @@ -15676,17 +14775,17 @@ Möchtest du die Nachricht speichern ? Nachbar-ID - + Remove unused keys... Unbenutzte Schlüssel entfernen... Remove this key - + Diesen Schlüssel entfernen - + Clean keyring Schlüsselbund bereinigen @@ -15704,7 +14803,14 @@ Anmerkungen: Dein alter Schlüsselbund wird gesichert. Die Entfernung kann fehlschlagen, wenn mehrere Instanzen von Retroshare auf der selben Maschine laufen. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + Sie haben %1 akzeptierte Peers unter anderen ausgewählt, + Bist du sicher, dass du sie wieder entfreunden möchtest? + + + Keyring info Schlüsselbund-Informationen @@ -15715,8 +14821,8 @@ Anmerkungen: Dein alter Schlüsselbund wird gesichert. For security, your keyring was previously backed-up to file - %1 Schlüssel wurden aus dem Schlüsselbund entfernt. -Der Schlüsselbund wurde aus Sicherheitsgründen zuvor in einer Datei gesichert. + %1 Schlüssel wurden aus dem Schlüsselbund entfernt. +Der Schlüsselbund wurde aus Sicherheitsgründen zuvor in einer Datei gesichert. @@ -15740,18 +14846,13 @@ Der Schlüsselbund wurde aus Sicherheitsgründen zuvor in einer Datei gesichert. Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. Dateninkonsistenz im Schlüsselbund. Dies ist wahrscheinlich ein Bug. Bitte die Entwickler kontaktieren. - - - Export/create a new node - Einen neuen Netzknoten exportieren/erstellen - Trusted keys only Nur vertrauenswürdige Schlüssel - + Search name Name suchen @@ -15761,12 +14862,12 @@ Der Schlüsselbund wurde aus Sicherheitsgründen zuvor in einer Datei gesichert. Nachbar-ID suchen - + Profile details... Profildetails... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -15775,13 +14876,6 @@ Reported error: Gemeldeter Fehler: - - NetworkPage - - Network - Netzwerk - - NetworkView @@ -15808,296 +14902,299 @@ Reported error: NewFriendList - + Offline Friends - + Offline-Freunde Show Offline Friends - + Offline-Freunde anzeigen Status - Status + Status Show status - + Status anzeigen - + Groups - Gruppen + Gruppen Show groups - + Zeige Gruppen export friendlist - Freundesliste exportieren + Freundesliste exportieren export your friendlist including groups - + Exportieren Sie Ihre Freundesliste einschließlich Gruppen import friendlist - Freundesliste importieren + Freundesliste importieren import your friendlist including groups - + Importieren Sie Ihre Freundesliste einschließlich Gruppen - - + + Search - Suchen + Suchen - + ID - + - + Search ID - Kennung suchen + Kennung suchen Online friends on top - + Online-Freunde an der Spitze - + Show Items - + Elemente anzeigen - + Last contact - + Letzter Kontakt IP - IP + IP - + Group - Gruppe + Gruppe Friend - Freund + Freund Node - Netzknoten + Netzknoten UNKNOWN TYPE - + UNBEKANNTER TYP Edit Group - Gruppe ändern + Gruppe ändern Remove Group - Gruppe entfernen + Gruppe entfernen Profile details - Profildetails + Profildetails Deny connections - Verbindungen ablehnen + Verbindungen ablehnen Add to group - Zu Gruppe hinzufügen + Zu Gruppe hinzufügen Move to group - In Gruppe verschieben + In Gruppe verschieben Create new group - Neue Gruppe erstellen + Neue Gruppe erstellen Remove from group - + Aus der Gruppe entfernen Remove from all groups - Aus allen Gruppen entfernen + Aus allen Gruppen entfernen Chat - Chat + Chat Send message to this node - Nachricht an diesen Knoten senden + Nachricht an diesen Knoten senden Node details - Knotendetails + Knotendetails Recommend this node to... - Diesen Knoten empfehlen an... + Diesen Knoten empfehlen an... Attempt to connect - Verbindung versuchen + Verbindung versuchen Copy certificate link - Zertifikat-Link kopieren + Zertifikat-Link kopieren Remove Friend Node - Freundknoten entfernen + Freundknoten entfernen Paste certificate link - Zertifikat-Link einfügen + Zertifikat-Link einfügen Expand all - Alle erweitern + Alle erweitern Collapse all - Alle reduzieren + Alle reduzieren - + Do you want to remove this node? - Möchtest du diesen Netzknoten entfernen? + Möchtest du diesen Netzknoten entfernen? Do you want to remove this Friend? - Möchtest du diesen Freund entfernen? + Möchtest du diesen Freund entfernen? - + Done! - Fertig! + Fertig! Your friendlist is stored at: - Deine Freundesliste wird gespeichert unter: + Deine Freundesliste wird gespeichert unter: (keep in mind that the file is unencrypted!) - + +(Beachten Sie, dass die Datei unverschlüsselt ist!) Your friendlist was imported from: - Deine Freundesliste wurde importiert aus: + Deine Freundesliste wurde importiert aus: Done - but errors happened! - Fertig - aber Fehler sind aufgetreten! + Fertig - aber Fehler sind aufgetreten! at least one peer was not added - + +Mindestens ein Peer wurde nicht hinzugefügt at least one peer was not added to a group - + +Mindestens ein Peer wurde nicht zu einer Gruppe hinzugefügt Select file for importing your friendlist from - + Wählen Sie die Datei aus, aus der Sie Ihre Freundesliste importieren möchten XML File (*.xml);;All Files (*) - XML-Datei (*.xml);;Alle Dateien (*) + XML-Datei (*.xml);;Alle Dateien (*) Select a file for exporting your friendlist to - + Wählen Sie eine Datei aus, in die Sie Ihre Freundesliste exportieren möchten Error - Fehler + Fehler File is not writeable! - Datei ist nicht schreibbar! + Datei ist nicht schreibbar! File is not readable! - Datei ist nicht lesbar! + Datei ist nicht lesbar! @@ -16132,13 +15229,9 @@ at least one peer was not added to a group NewsFeed - Log entries - Protokolleinträge - - - + Activity Stream - + Aktivitätsstream @@ -16151,11 +15244,7 @@ at least one peer was not added to a group Alle entfernen - This is a test. - Dies ist ein Test. - - - + Newest on top Neueste oben @@ -16165,18 +15254,14 @@ at least one peer was not added to a group Älteste oben - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - Log - Protokoll - - - + Activity - + Aktivität @@ -16184,22 +15269,22 @@ at least one peer was not added to a group You have %1 logged events - + Sie haben %1 protokollierte Ereignisse You have %1 logged event - + Sie haben %1 protokolliertes Ereignis %1 logged events - + %1 protokollierte Ereignisse %1 logged event - + %1 protokolliertes Ereignis @@ -16229,10 +15314,6 @@ at least one peer was not added to a group Blogs Blogs - - Security - Sicherheit - @@ -16254,10 +15335,6 @@ at least one peer was not added to a group Message Nachricht - - Connect attempt - Verbindungsversuch - @@ -16274,14 +15351,10 @@ at least one peer was not added to a group Ip security IP-Sicherheit - - Log - Protokoll - Activity - + Aktivität @@ -16340,10 +15413,6 @@ at least one peer was not added to a group Chat rooms Chaträume - - Chat Rooms - Chaträume - Position @@ -16419,36 +15488,28 @@ at least one peer was not added to a group Disable All Toaster temporarily Alle Hinweise vorübergehend deaktivieren - - Feed - Neuigkeiten - Systray Benachrichtigungsfeld - - Count all unread messages - Alle ungelesenen Nachrichten zählen - NotifyQt - + Passphrase required Passphrase erforderlich You need to sign your node's certificate. - + Sie müssen das Zertifikat Ihres Knotens signieren. You need to sign your forum/chatrooms identity. - + Sie müssen Ihre Forum-/Chatroom-Identität unterschreiben. @@ -16456,12 +15517,12 @@ at least one peer was not added to a group Falsches Passwort! - + Please enter your Retroshare passphrase - + Bitte geben Sie Ihr Retroshare-Passwort ein - + Unregistered plugin/executable Nicht registriertes Plug-in/Programm @@ -16476,19 +15537,7 @@ at least one peer was not added to a group Bitte überprüfe deine Systemuhr. - Examining shared files... - Prüfe freigegebene Dateien... - - - Hashing file - Erstelle Prüfsumme - - - Saving file index... - Speichere Dateiindex... - - - + Test Test @@ -16499,17 +15548,19 @@ at least one peer was not added to a group + Unknown title Unbekannter Titel - + + Encrypted message - Verschlüsselte Nachr. + Verschlüsselte Nachricht - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). Damit die Chatlobbys richtig funktionieren, muss auf deinem Computer die richtige Zeit eingestellt sein. Bitte prüfe ob dies der Fall ist. (Es wurde eine mögliche Zeitabweichung von mehreren Minuten gegenüber deinen Freunden festgestellt.) @@ -16517,7 +15568,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online Freund Online @@ -16558,21 +15609,17 @@ Minimalmodus: 10% vom Standarddatenaufkommen und (unfertig) pausiert alle Datei <p>Warning: This Operating mode disables the tunneling service. This means you can use distant chat not anonymously download files and the mail service will be slower.</p><p>This state will be saved after restart, so do not forget that you changed it!</p> - + <p>Warnung: In diesem Betriebsmodus ist der Tunneldienst deaktiviert. Das bedeutet, dass Sie den Distant-Chat nicht anonym nutzen können und der Mail-Dienst langsamer wird.</p><p>Dieser Zustand wird nach dem Neustart gespeichert, vergessen Sie also nicht, dass Sie ihn geändert haben!</p> Turtle routing disabled! - + Turtle-Routing deaktiviert! PGPKeyDialog - - Dialog - Dialog - Profile info @@ -16638,10 +15685,6 @@ Minimalmodus: 10% vom Standarddatenaufkommen und (unfertig) pausiert alle Datei This profile has signed your own profile key - - Key signatures : - Schlüsselsignaturen : - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> @@ -16667,7 +15710,12 @@ p, li { white-space: pre-wrap; } PGP-Schlüssel - + + Friend options + + + + These options apply to all nodes of the profile: @@ -16676,10 +15724,6 @@ p, li { white-space: pre-wrap; } Keysigning: - - Sign PGP key - PGP-Schlüssel unterzeichnen - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -16716,12 +15760,7 @@ p, li { white-space: pre-wrap; } Signaturen einschließen - - Options - Optionen - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -16767,21 +15806,21 @@ p, li { white-space: pre-wrap; } kB/s - - + + RetroShare RetroShare - - + + Error : cannot get peer details. Fehler: Kann Nachbardetails nicht ermitteln. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) Der angegebene Schlüsselalgorithmus wird von RetroShare nicht unterstützt. @@ -16800,7 +15839,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. Das Vertrauensniveau drückt dein eigenes Vertrauen in diesen Schlüssel aus. Es wird weder von der Software genutzt noch geteilt, kann aber zum Merken guter bzw. schlechter Schlüssel nützlich sein. @@ -16852,12 +15891,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. Identity creation failed - + Identitätserstellung fehlgeschlagen Cannot create an identity linked to your profile without your profile password. - + Ohne Ihr Profilpasswort können Sie keine mit Ihrem Profil verknüpfte Identität erstellen. @@ -16869,10 +15908,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Check the password! - - Maybe password is wrong - Vielleicht ist das Passwort falsch - You haven't set a trust level for this key. @@ -16880,12 +15915,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile RetroShare-Profil - + This is your own PGP key, and it is signed by : Dies ist dein eigener PGP-Schlüssel und er wurde signiert von: @@ -16911,7 +15946,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat Chat @@ -16932,7 +15967,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Element entfernen - + Name: Name: @@ -16944,7 +15979,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. Trust: - Vertrauen: + Vertrauen: @@ -16969,10 +16004,10 @@ Warning: In your File-Transfer option, you select allow direct download to No. Time offset: - + Zeitdifferenz: - + Write Message Nachricht schreiben @@ -16986,14 +16021,10 @@ Warning: In your File-Transfer option, you select allow direct download to No.Friend Connected Freund verbunden - - Connect Attempt - Verbindungsversuch - Connection refused by peer - + Verbindung von Peer abgelehnt @@ -17003,7 +16034,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. Friend Time Offset - + Zeitversatz des Freundes @@ -17014,7 +16045,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. Unknown peer - + Unbekannter Peer @@ -17026,11 +16057,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. Unknown - Unbekannt - - - Unknown Peer - Unbekannter Nachbar + Unbekannt @@ -17038,7 +16065,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Verbergen - + Send Message Nachricht senden @@ -17073,7 +16100,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. Drag your circles or people to each other. - Ziehe deine Kreise oder Leute zueinander + Ziehe deine Kreise oder Leute zueinander. @@ -17090,29 +16117,25 @@ Warning: In your File-Transfer option, you select allow direct download to No.Chat with this person as... Mit dieser Person chatten als... - - Send message to this person - Nachricht an diese Person senden - Invite to Circle - + Zum Kreis einladen Send message - Nachricht senden + Nachricht senden Send invite - + Einladung senden Add to Contacts - Zu Kontakte hinzufügen + Zu Kontakte hinzufügen @@ -17150,52 +16173,52 @@ Warning: In your File-Transfer option, you select allow direct download to No. <html><head/><body><p>Anyone in your contact list will automatically have a positive opinion if not set. This allows to automatically raise reputations of used nodes. </p></body></html> - + <html><head/><body><p>Jeder in Ihrer Kontaktliste hat automatisch eine positive Meinung, wenn dies nicht festgelegt ist. Dadurch kann die Reputation verwendeter Knoten automatisch erhöht werden. </p></body></html> use "positive" as the default opinion for contacts (instead of neutral) - + use "positive" as the default opinion for contacts (instead of neutral) Automatically add identities owned by friend nodes to my contacts - + Füge automatisch Identitäten von Freundesknoten zu meinen Kontakten hinzu Difference in votes (+/-) to rate an ID negatively: - + Unterschied in den Stimmen (+/-), um eine ID negativ zu bewerten: <html><head/><body><p>When an identity receives more negative votes than positive votes, it switches from &quot;Neutral&quot; to &quot;Negative (according to your friends)&quot;. By default, a one-vote difference is enough, but you can make this harder to happen by selecting a higher number here.</p></body></html> - + <html><head/><body><p>Wenn eine Identität mehr negative als positive Stimmen erhält, wechselt sie von „Neutral“ zu „Neutral“. zu „Negativ (laut deinen Freunden)“. Standardmäßig reicht ein Unterschied von einer Stimme aus, aber Sie können dies erschweren, indem Sie hier eine höhere Zahl auswählen.</p></body></html> <html><head/><body><p>When an identity receives more positive votes than negative votes, it switches from &quot;Neutral&quot; to &quot;Positive (according to your friends)&quot;. By default, a one-vote difference is enough, but you can make this harder to happen by selecting a higher number here.</p></body></html> - + <html><head/><body><p>Wenn eine Identität mehr positive als negative Stimmen erhält, wechselt sie von „Neutral“ zu „Neutral“. zu „Positiv (laut deinen Freunden)“. Standardmäßig reicht ein Unterschied von einer Stimme aus, aber Sie können dies erschweren, indem Sie hier eine höhere Zahl auswählen.</p></body></html> Difference in votes (+/-) to rate an ID positively: - + Differenz in den Stimmen (+/-), um eine ID positiv zu bewerten: Delete banned identities after (0 means indefinitely): - + Gesperrte Identitäten löschen nach (0 bedeutet auf unbestimmte Zeit): Reset reputation of banned identities after (0 means never): - + Reputation gesperrter Identitäten zurücksetzen nach (0 bedeutet nie): <html><head/><body><p>Banned identities are not stamped and therefore lose activity. They get deleted automatically after a finit period of time.</p></body></html> - + <html><head/><body><p>Gesperrte Identitäten werden nicht gestempelt und verlieren daher ihre Aktivität. Sie werden nach einer bestimmten Zeitspanne automatisch gelöscht.</p></body></html> @@ -17206,14 +16229,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. <html><head/><body><p>In order to prevent deleted banned IDs to come back because they are used in e.g. forums or channels, banned identities are kept in a list for some time. After that, they are &quot;cleared&quot; from the banning list, and will be downloaded again as unbanned if used in forus, chat rooms, etc.</p></body></html> - - - - - PhotoCommentItem - - Form - Formular + <html><head/><body><p>Um zu verhindern, dass gelöschte gesperrte IDs zurückkommen, weil sie z. B. in In Foren oder Kanälen werden gesperrte Identitäten für einige Zeit in einer Liste gespeichert. Danach werden sie „gelöscht“. aus der Sperrliste entfernt und bei Verwendung in Foren, Chatrooms usw. erneut als nicht gesperrt heruntergeladen.</p></body></html> @@ -17223,57 +16239,45 @@ Warning: In your File-Transfer option, you select allow direct download to No.PhotoShare PhotoShare - - Photo - Foto - TextLabel TextLabel - - Comment - Kommentar - - - Summary - Zusammenfassung - Album / Photo Name - + Album-/Fotoname Details - Details + Details 50 % - + 75 % - + 100 % - + 200 % - + Comments - Kommentare + Kommentare @@ -17288,30 +16292,22 @@ Warning: In your File-Transfer option, you select allow direct download to No. Photo Title: - Fototitel + Fototitel: When - Wann: + Wann ... ... - - Add Comment - Kommentar hinzufügen - - - Write a comment... - Schreibe einen Kommentar... - Album - Album + Album @@ -17378,10 +16374,6 @@ p, li { white-space: pre-wrap; } Create Album Album erstellen - - View Album - Album ansehen - Edit Album Details @@ -17403,17 +16395,17 @@ p, li { white-space: pre-wrap; } Diaschau - + My Albums Eigene Alben - + Subscribed Albums Abonnierte Alben - + Shared Albums Freigegebene Alben @@ -17443,7 +16435,7 @@ kannst musst du eines auswählen! PhotoSlideShow - + Album Name Albumname @@ -17499,44 +16491,44 @@ kannst musst du eines auswählen! Photo View - + Fotoansicht - - + + TextLabel - TextLabel + TextLabel - + Posted by - + Gepostet von - + ago - + vor Copy RetroShare link - + RetroShare-Link kopieren Share - + Verteilen information - + Informationen The Retrohare link was copied to your clipboard. - + Der Retrohare-Link wurde in Ihre Zwischenablage kopiert. @@ -17550,12 +16542,12 @@ kannst musst du eines auswählen! PluginItem - + TextLabel TextLabel - + Show more details about this plugin Mehr Details über dieses Plug-in anzeigen @@ -17610,7 +16602,7 @@ p, li { white-space: pre-wrap; } File name: - Dateiname: + Dateiname: @@ -17620,7 +16612,7 @@ p, li { white-space: pre-wrap; } Status: - Status: + Status: @@ -17638,22 +16630,22 @@ p, li { white-space: pre-wrap; } Error: instance '%1' can't create a widget - + Fehler: Instanz „%1“ kann kein Widget erstellen Error: failed to remove file %1 (uninstalling plugin '%2') - + Fehler: Datei %1 konnte nicht entfernt werden (Plugin „%2“ wird deinstalliert) Error (uninstall): no plugin with name '%1' found - + Fehler (Deinstallation): Kein Plugin mit dem Namen „%1“ gefunden Error (installation): plugin file %1 doesn't exist - + Fehler (Installation): Plugin-Datei %1 existiert nicht @@ -17701,51 +16693,6 @@ p, li { white-space: pre-wrap; } Plugin look-up directories Plug-in Ordner - - [disabled] - [deaktivert] - - - No API number supplied. Please read plugin development manual. - Keine API-Nummer angegeben. Bitte konsultiere das Handbuch für die Entwicklung von Plug-ins. - - - [loading problem] - [Ladeproblem] - - - No SVN number supplied. Please read plugin development manual. - Keine SVN-Nummer angegeben. Bitte konsultiere das Handbuch für die Entwicklung von Plug-ins. - - - Loading error. - Fehler beim Laden. - - - Missing symbol. Wrong version? - Fehlendes Symbol. Falsche Version? - - - No plugin object - Kein Plug-in Objekt - - - Plugins is loaded. - Plug-in ist geladen. - - - Unknown status. - Unbekannter Status. - - - Check this for developing plugins. They will not -be checked for the hash. However, in normal -times, checking the hash protects you from -malicious behavior of crafted plugins. - Lies dies, um über die Plug-in-Entwicklung zu erfahren. Ihre Prüfsumme wird nicht überprüft, normalerweise -schützt dich aber eine Überprüfung des Prüfsumme vor -schädlichem Verhalten von Plug-ins. - Plugins @@ -17815,15 +16762,30 @@ schädlichem Verhalten von Plug-ins. Immer im Vordergrund - - Choose window color... - + + Ban this person (Sets negative opinion) + Diese Person verbannen (setzt negative Meinung) - + + Give neutral opinion + Neutrale Meinung abgeben + + + + Give positive opinion + Positive Meinung abgeben + + + + Choose window color... + Wählen Sie die Fensterfarbe... + + + Dock window - + Fenster andocken @@ -17831,36 +16793,28 @@ schädlichem Verhalten von Plug-ins. Remote status unknown. - + Remote-Status unbekannt. Can't send message immediately, because there is no tunnel available. - + Kann die Nachricht nicht sofort senden, da kein Tunnel verfügbar ist. Your partner closed the conversation. - + Ihr Partner hat das Gespräch beendet. Closing this window will end the conversation. Unsent messages will be dropped. - + Wenn Sie dieses Fenster schließen, wird die Konversation beendet. Nicht gesendete Nachrichten werden verworfen. Close conversation? - - - - Closing this window will end the conversation, notify the peer and remove the encrypted tunnel. - Das Schließen dieses Fensters beendet die Unterhaltung, benachrichtigt den Gesprächspartner und löscht den verschlüsselten Tunnel. - - - Kill the tunnel? - Tunnel schließen? + Gespräch beenden? @@ -17868,113 +16822,105 @@ schädlichem Verhalten von Plug-ins. Posted by - + Gepostet von Toggle Message Read Status - Lesestatus der Nachricht umschalten + Lesestatus der Nachricht umschalten New - Neu + Neu - + Vote up - Daumen hoch + Daumen hoch 0 - 0 + 0 Vote down - Daumen runter + Daumen runter \/ - \/ + \/ - - + + Comments - Kommentare + Kommentare Share - + Verteilen Set as read and remove item - Als gelesen markieren und Eintrag entfernen + Als gelesen markieren und Eintrag entfernen Remove Item - + Eintrag entfernen PictureLabel - + - - + + Comment - Kommentar + Kommentar - + Comments - + Kommentare Loading - + Lade Copy RetroShare Link - RetroShare-Link kopieren + RetroShare-Link kopieren Show author in people tab - + Autor auf der Registerkarte Personen anzeigen <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + <p><font color="#ff0000"><b>Der Autor dieser Nachricht (mit der ID %1) ist gesperrt.</b> PostedCreatePostDialog - Signed by: - Unterzeichnet von: - - - Notes - Notizen - - - + Create a new Post - + Neuen Beitrag erstellen - + RetroShare RetroShare @@ -17986,110 +16932,124 @@ schädlichem Verhalten von Plug-ins. Message is too large.<br />actual size: %1 bytes, maximum size: %2 bytes. - + Nachricht ist zu groß.<br />Aktuelle Größe: %1 Bytes, maximale Größe: %2 Bytes. - + + Error while creating post + Fehler beim Erstellen eines Beitrags + + + + An error occurred while creating the post. + Beim Erstellen des Beitrags ist ein Fehler aufgetreten. + + + Load Picture File - Bilddatei laden + Bilddatei laden - + Post image - + Bild posten Do you want to share and link the original image? - + Möchten Sie das Originalbild teilen und verlinken? You already added a link.<br />Do you want to replace it? - + Sie haben bereits einen Link hinzugefügt.<br />Möchten Sie ihn ersetzen? - + + No clipboard image found. + Kein Bild in der Zwischenablage gefunden. + + + + There is no image data in the clipboard to paste + In der Zwischenablage befinden sich keine Bilddaten zum Einfügen + + + Close this window? - + Dieses Fenster schließen? Do you really want to discard your post? - + Wollen Sie Ihren Beitrag wirklich verwerfen? - Submit Post - Beitrag einreichen - - - You are submitting a link. The key to a successful submission is interesting content and a descriptive title. - Du reichst einen Link ein. Der Schlüssel für einen erfolgreichen Beitrag ist interessanter Inhalt und eine passende Überschrift. - - - Submit - Einreichen - - - Submit a new Post - Einen neuen Beitrag einreichen - - - + Please add a Title Bitte füge einen Titel hinzu Create a Post - + Beitrag erstellen Preview - Vorschau + Vorschau Add Picture - + Bild hinzufügen - + Post size is limited to 32 KB, pictures will be downscaled. - + Die Größe der Beiträge ist auf 32 KB begrenzt, die Bilder werden verkleinert. - + + Paste image from clipboard + Bild aus Zwischenablage einfügen + + + + Paste Picture + Bild einfügen + + + Remove image - + Bild entfernen Url - + Post as - Veröffentlichen als + Veröffentlichen als - + Post - + Posten Image - Bild + Bild - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. - + Sie reichen einen Beitrag ein. Der Schlüssel zu einem erfolgreichen Beitrag ist ein interessanter Inhalt und ein beschreibender Titel. @@ -18097,7 +17057,7 @@ schädlichem Verhalten von Plug-ins. Titel - + Link Link @@ -18105,96 +17065,48 @@ schädlichem Verhalten von Plug-ins. PostedDialog - Posted Links - Veröffentlichte Links - - - Create Topic - Thema erstellen - - - My Topics - Eigene Themen - - - Subscribed Topics - Abonnierte Themen - - - Popular Topics - Beliebte Themen - - - Other Topics - Andere Themen - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards - + Create Board - + Board erstellen My Boards - + Meine Boards Subscribed Boards - + Abbonnierte Boards Popular Boards - + Populäre Boards Other Boards - + Andere Boards PostedGroupDialog - Posted Topic - Posted-Thema - - - Add Topic Admins - Thema-Aministratoren hinzufügen - - - Select Topic Admins - Themenverwalter auswählen - - - Create New Topic - Neues Thema erstellen - - - Edit Topic - Thema bearbeiten - - - Update Topic - Thema aktualisieren - - - + Create New Board - + Neues Board erstellen @@ -18209,44 +17121,54 @@ schädlichem Verhalten von Plug-ins. Edit Board - + Board bearbeiten Update Board - + Board aktuallisieren Add Board Admins - + Board-Admins hinzufügen Select Board Admins - + Board-Admins auswählen PostedGroupItem - + + Last activity + Letzte Aktivität + + + + TextLabel + TextLabel + + + Subscribe to Posted Posted abonnieren Subscribe - Abonnieren + Abonnieren Copy RetroShare Link - RetroShare-Link kopieren + RetroShare-Link kopieren - + Expand Erweitern @@ -18258,29 +17180,22 @@ schädlichem Verhalten von Plug-ins. Board Description - + Board Beschreibung - Posted Description - Posted Beschreibung - - - Loading - Lade - - - New Posted - Neues Posted - - - + Loading... - + Lade... - + + Never + Nie + + + New Board - + Neuer Board @@ -18291,72 +17206,64 @@ schädlichem Verhalten von Plug-ins. PostedItem - + 0 0 - Site - Site - - - - + + Comments Kommentare - + Copy RetroShare Link - RetroShare-Link kopieren + RetroShare-Link kopieren Show author in people tab - + Autor auf der Registerkarte Personen anzeigen - + Comment Kommentar - + Comments - + Kommentare <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + <p><font color="#ff0000"><b>Der Autor dieser Mitteilung (mit ID %1) ist gesperrt.</b> - + Click to view Picture - + Zum Betrachten des Bildes anklicken Hide - Verbergen + Verbergen - + Vote up Daumen hoch - + Vote down Daumen runter - \/ - \/ - - - + Set as read and remove item Als gelesen markieren und Eintrag entfernen @@ -18366,7 +17273,7 @@ schädlichem Verhalten von Plug-ins. Neu - + New Comment: Neuer Kommentar: @@ -18376,20 +17283,20 @@ schädlichem Verhalten von Plug-ins. Kommentarwert - + Name - Name + Name Posted by - + Gepostet von Expand - Erweitern + Erweitern @@ -18399,12 +17306,12 @@ schädlichem Verhalten von Plug-ins. Share - + Teilen Notes - Notizen + Notizen @@ -18414,360 +17321,322 @@ schädlichem Verhalten von Plug-ins. TextLabel - TextLabel + TextLabel - + Loading Lade - - By - Von - - - - PostedListWidget - - Form - Formular - - - Hot - Heiß - - - New - Neu - - - Top - Anfang - - - Today - Heute - - - Yesterday - Gestern - - - This Week - diese Woche - - - This Month - diesen Monat - - - This Year - dieses Jahr - - - Submit a new Post - Einen neuen Beitrag einreichen - - - Next - Nächstes - - - RetroShare - RetroShare - - - Please create or choose a Signing Id before Voting - Vor dem Abstimmen bitte eine Signier-ID erstellen oder auswählen - - - Previous - Vorherige - - - 1-10 - 1-10 - PostedListWidgetWithModel Form - Formular + Formular Details - Details + Details Board Details - + Board Details - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + <html><head/><body><p>Maximale Anzahl von Datenelementen (einschließlich Beiträgen, Kommentaren, Abstimmungen) über Freundschaftsknoten hinweg.</p></body></html> + + + + Items (at friends): + Artikel (bei Freunden): + + + 0 - 0 + 0 Administrator: - Administrator: + Administrator: - + - + unknown - unbekannt + unbekannt - + Distribution: - Verteilung: + Verteilung: Last activity: - + Letzte Aktivität: - + Created - + Erstellt - + TextLabel - TextLabel + TextLabel - + Popularity: - + Popularität: - - Contributions: - - - - + Sync period: - + Sync-Zeitraum: - + + Number of subscribed friend nodes + Anzahl der abonnierten Freundesknoten + + + Posts - Beiträge + Beiträge - + Create Post - + Beitrag erstellen - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> - + <html><head/><body><p><span style="font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI-Symbol'; Schriftgröße: 14pt; Farbe: #24292e; Hintergrundfarbe: #ffffff;">Sortierung auswählen</span></p></body></html> New - Neu + Neu Top - Anfang + Top Hot - Heiß + Heiß - + Search - Suchen + Suchen Classic view - + Klassische Ansicht Previous - Vorherige + Vorherige 1-10 - 1-10 + 1-10 Next - Nächstes + Nächstes <html><head/><body><p>Default identity used when voting</p></body></html> - + <html><head/><body><p>Standard-Identität, die bei der Abstimmung verwendet wird</p></body></html> - + No files in this post, or no post selected - + Keine Dateien in diesem Beitrag, oder kein Beitrag ausgewählt - + No posts available in this board - + Keine Beiträge in diesem Board vorhanden - + Click to switch to card view - + Klicken, um zur Kartenansicht zu wechseln Click to switch to compact view - + Klicken, um zur Kompaktansicht zu wechseln Empty - + Leer - + Copy RetroShare Link - RetroShare-Link kopieren + RetroShare-Link kopieren - + + Copy http Link + http-Link kopieren + + + Show author in People tab - + Autor auf der Registerkarte Personen anzeigen Edit - Bearbeiten + Bearbeiten - + + information - + Informationen - + + The Retrohare link was copied to your clipboard. - + Der Retrohare-Link wurde in Ihre Zwischenablage kopiert. - + + Link creation error - + Fehler bei der Link-Erstellung - + + Link could not be created: - + Link konnte nicht erstellt werden: - + [No name] - + [Kein Name] Subscribed - Abonniert + Abonniert Subscribe - Abonnieren + Abonnieren - + Never - Nie + Nie 5 days - 5 Tage + 5 Tage 2 weeks - 2 Wochen + 2 Wochen 1 month - 1 Monat + 1 Monat 3 months - + 3 Monate 6 months - + 6 Monate 1 year - 1 Jahr + 1 Jahr indefinitly - + Unbegrenzt Unknown - Unbekannt + Unbekannt Public - Öffentlich + Öffentlich Restricted to members of circle " - Beschränkt auf Mitglieder des Kreises " + Beschränkt auf Mitglieder des Kreises " Restricted to members of circle - Beschränkt auf Mitglieder des Kreises + Beschränkt auf Mitglieder des Kreises Your eyes only - Nur Ihre Augen + Nur für Ihre Augen You and your friend nodes - + Sie und Ihr Freund Knotenpunkte No Channel Selected - Keinen Kanal gewählt + Keinen Kanal gewählt + + + + Could not vote + Konnte nicht abstimmen + + + + Error occured while voting: + Bei der Abstimmung ist ein Fehler aufgetreten: @@ -18777,46 +17646,38 @@ schädlichem Verhalten von Plug-ins. Tabs Reiter - - Open each topic in a new tab - Jedes Thema in einem neuen Reiter öffnen. - Open each board in a new tab - + Öffnen Sie jedes Board in einem neuen Tab Boards - + PostedUserNotify - - Posted - Posted - Board Post - + Board Beitrag You have %1 new board posts - + Sie haben %1 neue Beiträge im Board You have %1 new board post - + Sie haben %1 neuen Board Beitrag %1 new board post - + %1 neuer Beitrag im Board @@ -18866,16 +17727,16 @@ schädlichem Verhalten von Plug-ins. Profil-Manager - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -18987,7 +17848,7 @@ und den Import zum Laden verwenden ProfileWidget - + Edit status message Statusnachricht ändern @@ -19003,7 +17864,7 @@ und den Import zum Laden verwenden Profil-Manager - + Public Information Öffentliche Information @@ -19038,12 +17899,12 @@ und den Import zum Laden verwenden Online seit: - + Other Information Andere Informationen - + My Address Meine Adresse @@ -19081,72 +17942,48 @@ und den Import zum Laden verwenden Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Dein Zertifikat ist in die Zwischenablage kopiert worden. Du kannst es per E-Mail oder auf andere Weise an deinen Freund senden. + Dein Zertifikat ist in die Zwischenablage kopiert worden. Du kannst es per E-Mail oder auf andere Weise an deinen Freund senden PulseAddDialog - Post From: - Beitrag von: - - - Account 1 - Konto 1 - - - Account 2 - Konto 2 - - - Account 3 - Konto 3 - - - + Add to Pulse Zu Puls hinzufügen - filter - filtern - - - URL Adder - URL-Hinzufüger - - - + Display As Anzeigen als - + URL URL - + GroupLabel - + IDLabel From: - Von: + Von: - + Head - + Head Shot @@ -19163,26 +18000,26 @@ und den Import zum Laden verwenden Positive - Positiv + Positiv Neutral - Neutral + Neutral Negative - Negativ + Negativ - - + + Whats happening? - + Was geschieht? - + @@ -19191,36 +18028,42 @@ und den Import zum Laden verwenden Drag and Drop Image - + Drag and Drop Bild - + + Remove all images + Entfernen Sie alle Bilder + + + Clear Display As - + + Add Picture + Bild hinzufügen + + + Post - + Posten Cancel Abbrechen - - Post Pulse to Wire - Puls an Wire senden - Post - + Posten - + Reply to Pulse - + Antworten @@ -19230,37 +18073,27 @@ und den Import zum Laden verwenden Republish Pulse - + Neu veröffentlichen - + Like Pulse - + Hide Pictures - + Bilder ausblenden - + Add Pictures - - - - - PulseItem - - From - Von + Bilder hinzufügen - Date - Datum - - - ... - + + Load Picture File + Bilddatei laden @@ -19268,15 +18101,15 @@ und den Import zum Laden verwenden Form - Formular + Formular - + Click to view picture - + Zum Betrachten des Bildes anklicken @@ -19284,13 +18117,13 @@ und den Import zum Laden verwenden Image - Bild + Bild PulseReply - + icn @@ -19300,9 +18133,9 @@ und den Import zum Laden verwenden - + REPLY - + Antworten @@ -19314,7 +18147,7 @@ und den Import zum Laden verwenden REPUBLISH - + REPUBLIKIEREN @@ -19324,12 +18157,12 @@ und den Import zum Laden verwenden SHOW - + Zeigen - + FOLLOW - + Folgen @@ -19337,7 +18170,7 @@ und den Import zum Laden verwenden - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -19357,7 +18190,7 @@ und den Import zum Laden verwenden - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -19387,7 +18220,7 @@ und den Import zum Laden verwenden ... - + ... @@ -19448,7 +18281,7 @@ und den Import zum Laden verwenden REPLY - + Antworten @@ -19460,7 +18293,7 @@ und den Import zum Laden verwenden REPUBLISH - + REPUBLIKIEREN @@ -19470,48 +18303,53 @@ und den Import zum Laden verwenden SHOW - + Anzeigen - + FOLLOW - + Folgen PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + Standort - + + Edit profile + Profil editieren + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -19543,16 +18381,16 @@ und den Import zum Laden verwenden - + FOLLOW - + Folgen QObject - - + + Confirmation Bestätigung @@ -19573,32 +18411,32 @@ hinzufügen und den Assistent zum Hinzufügen von Freunden zu starten. Warning: Retroshare is about to ask your system to open this file. - + Warnung: Retroshare fordert Ihr System auf, diese Datei zu öffnen. Before you do so, please make sure that this file does not contain malicious executable code. - + Bevor Sie dies tun, stellen Sie bitte sicher, dass diese Datei keinen schädlichen ausführbaren Code enthält. Identity added to People - + Identität zu Personen hinzugefügt The identity was added to people. You can now chat with it, send messages to it, etc. - + Die Identität wurde zu Personen hinzugefügt. Sie können jetzt mit ihm chatten, Nachrichten an ihn senden usw. Identity cannot be added to People - + Identität kann nicht zu Personen hinzugefügt werden The identity was not added to people. Some error occured. The link is probably corrupted. - + Die Identität war nicht an Personen gebunden. Es ist ein Fehler aufgetreten. Der Link ist wahrscheinlich beschädigt. @@ -19713,17 +18551,17 @@ hinzufügen und den Assistent zum Hinzufügen von Freunden zu starten. Posted not found - + Die gepostete Nachricht wurde nicht gefunden Posted message not found - + Die gepostete Nachricht wurde nicht gefunden Posted messages not found - + Gepostete Nachrichten wurden nicht gefunden @@ -19733,22 +18571,22 @@ hinzufügen und den Assistent zum Hinzufügen von Freunden zu starten. Click to browse/download this file collection - + Klickenr, um diese Dateisammlung zu durchsuchen/herunterzuladen %1 (%2) - + Identity link (name=%1, ID=%2) - + Identitätslink (Name=%1, ID=%2) %1 (%2 files, %3) - + %1 (%2 Dateien, %3) @@ -19768,7 +18606,7 @@ hinzufügen und den Assistent zum Hinzufügen von Freunden zu starten. Chat room not found - + Chatraum nicht gefunden @@ -19823,12 +18661,12 @@ Die Zeichen <b>",|,/,\,&lt;,&gt;,*,?</b> werden durch & Nachbardetails - + File Request canceled Dateianforderung abgebrochen - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. Diese Version von RetroShare benutzt das OpenPGP-SDK. Der Schlüsselring des Systems wird nicht mehr verwendet, sondern ein eigener Schlüsselring für alle laufenden Instanzen.<br><br>Du scheinst keinen solchen Schlüsselring zu besitzen, obwohl Schlüssel von existierenden RetroShare-Accounts benötigt werden. Vielleicht hast du auch gerade zu dieser Version gewechselt. @@ -19859,41 +18697,45 @@ Die Zeichen <b>",|,/,\,&lt;,&gt;,*,?</b> werden durch & Ein unerwarteter Fehler ist aufgetreten. Bitte melde 'RsInit::InitRetroShare unexpected return code %1'. - + Cannot start Tor Manager! - + Tor Manager kann nicht gestartet werden! Tor cannot be started on your system: - + Tor kann auf deinem System nicht gestartet werden: + + Cannot start Tor - + Tor kann nicht gestartet werden Sorry but Tor cannot be started on your system! The error reported is:" - + Tor kann auf deinem System leider nicht gestartet werden! + +Die Fehlermeldung lautet:" Cannot start a hidden tor service! - + Kann einen hidden Tor service nicht starten! It was not possible to start a hidden service. - + Es war nicht möglich, einen hidden service zu starten. - + Multiple instances Mehrere Instanzen @@ -19912,7 +18754,29 @@ Lockdatei: An unexpected error occurred when Retroshare tried to acquire the single instance lock Lock file: - Ein unerwarteter Fehler während des "Single instance lock" ist aufgetreten + Ein ist ein unerwarteter Fehler während des "Single instance lock" aufgetreten +Lock datei: + + + + + Old certificate + Altes Zertifikat + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + Dieser Knoten verwendet alte Zertifikatseinstellungen, die von Ihrer aktuellen OpenSSL-Bibliotheksversion als zu schwach angesehen wird. Sie müssen einen neuen Knoten erstellen, der möglicherweise das gleiche Profil verwendet. + + + + Tor error + Tor-Fehler + + + + Cannot run/configure Tor. Make sure it is installed on your system. + Tor kann nicht ausgeführt/konfiguriert werden. Stellen Sie sicher, dass es auf Ihrem System installiert ist. @@ -19922,17 +18786,17 @@ Lockdatei: Tunnel is pending - + Tunnel ist in Vorbereitung (some undelivered messages) - + (einige unzustellbare Nachrichten) End-to-end encrypted conversation established - + Ende-zu-Ende-verschlüsselte Konversation aufgebaut @@ -19996,7 +18860,7 @@ Der gemeldete Fehler ist: Daten weiter - + You appear to have nodes associated to DSA keys: Du scheinst Netzknoten zu besitzen, die mit DSA-Schlüsseln verknüpft sind: @@ -20006,7 +18870,7 @@ Der gemeldete Fehler ist: DSA-Schlüssel werden von dieser Version von RetroShare noch nicht unterstützt. Alle diese Netzknoten können nicht benutzt werden. Das tut uns sehr leid. - + enabled aktiviert @@ -20016,7 +18880,7 @@ Der gemeldete Fehler ist: deaktivert - + Move IP %1 to whitelist IP %1 in Whitelist verschieben @@ -20032,7 +18896,7 @@ Der gemeldete Fehler ist: - + %1 seconds ago Vor %1 Sekunden @@ -20100,9 +18964,9 @@ Security: no anonymous IDs Sicherheit: keine anonymen Kennungen - + Join chat room - + Treten Sie dem Chatroom bei @@ -20125,12 +18989,12 @@ Sicherheit: keine anonymen Kennungen unable to parse XML file! - + XML-Datei kann nicht geparst werden! - + Indefinitely - + Unbestimmt @@ -20170,198 +19034,214 @@ Sicherheit: keine anonymen Kennungen Processing - + Verarbeitung Choosing group - + Gruppe auswählen Creating receipt - + Quittung erstellen Signing receipt - + Quittung unterschreiben Serializing - + Serialisierung Creating payload - + Payload erstellen Encrypting payload - + Verschlüsselung der Nutzlast Publishing - + Veröffentlichung Waiting for receipt - + Warte auf die Quittung Receipt received - + Quittung erhalten Receipt signature failed - + Die Signatur der Quittung ist fehlgeschlagen Encryption failed - + Die Verschlüsselung ist fehlgeschlagen Discovery - Discovery + Discovery Chat - Chat + Chat Messages - Nachrichten + Nachrichten Turtle - + Heartbeat - + File transfer - + Global router - + File database - + Datei-Datenbank Service info - + Serviceinformationen Bandwidth control - + Bandbreitenkontrolle Mail - + Distant mail - + Distant-Mail Service control - + Servicekontrolle Distant chat - + Distant-Chat GXS Tunnel - + Ban list - + Bannliste + + + + Name + Name + Node + Knoten + + + + Address + Adresse + + + + Status - Status + Status - + NXS - + Identities - Identitäten + Identitäten GXS Photo - + GXS Wiki - + GXS TheWire - + Forums - Foren + Foren Boards - + Channels - Kanäle + Kanäle Circles - Kreise + Kreise Reputation - Reputation + Reputation @@ -20371,12 +19251,12 @@ Sicherheit: keine anonymen Kennungen GXS Transport - + JSon API - + @@ -20390,176 +19270,184 @@ Sicherheit: keine anonymen Kennungen Group admin signature creation - + Erstellung der Gruppenadministratorsignatur Group admin signature validation - + Validierung der Gruppenadministratorsignatur Group author signature creation - + Erstellung der Gruppenautorsignatur Group author signature validation - + Validierung der Signatur des Gruppenautors Message author signature creation - + Erstellung der Signatur des Nachrichtenautors Message author signature validation - + Validierung der Signatur des Nachrichtenautors Routine group author signature check. - + Routinemäßige Überprüfung der Gruppenautorensignatur. Routine message author signature check - + Routinemäßige Überprüfung der Signatur des Nachrichtenautors Chat room signature validation - + Validierung der Chatroom-Signatur Global router message validation - + Globale Router-Nachrichtenvalidierung Global router message creation - + Erstellung globaler Router-Nachrichten DH Key exchange validation for GXS tunnel - + DH-Schlüsselaustauschvalidierung für GXS-Tunnel DH Key exchange creation for GXS tunnel - + Erstellung des DH-Schlüsselaustauschs für den GXS-Tunnel New identity from GXS sync - + Neue Identität durch GXS-Synchronisierung New friend identity from discovery - + Neue Freundesidentität durch Entdeckung New identity requested from friend node - + Neue Identität vom Freundesknoten angefordert Generic signature validation - + Generische Signaturvalidierung Generic signature creation - + Generische Signaturerstellung Generic data decryption - + Generische Datenentschlüsselung Generic data encryption - + Generische Datenverschlüsselung Circle membership checking - + Überprüfung der Mitgliedschaft im Kreis Click to pause the hashing process - + Klicken, um den Hashing-Vorgang anzuhalten [Hashing is paused] - + [Hashing ist pausiert] Click to resume the hashing process - - - - <p>This certificate contains: - <p>Dieses Zertifikat enthält: + Klicken, um den Hashing-Vorgang fortzusetzen Idle - Untätig + Untätig Virtual peers available - + Virtuelle Peers verfügbar Passive - + Active - Aktiv + Aktiv Requesting peers - + Peers angefordert Never - Nie + Nie Tunnel OK - + Tunnel active - + Tunnel aktiv Client - + Server - + + + + + + Missing channel post + Fehlender Kanalbeitrag + + + + + [System] + @@ -20724,7 +19612,7 @@ p, li { white-space: pre-wrap; } - + Network Wide Netzwerkweit @@ -20756,7 +19644,7 @@ p, li { white-space: pre-wrap; } Where do you want to have the buttons for the page? - + Wo möchten Sie die Schaltflächen für die Seite haben? @@ -20907,7 +19795,7 @@ p, li { white-space: pre-wrap; } Formular - + The loading of embedded images is blocked. Das Laden eingebetteter Bilder ist blockiert. @@ -20920,7 +19808,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default Standardmäßig erlaubt @@ -20957,72 +19845,72 @@ p, li { white-space: pre-wrap; } Location info exchange between friends. Helps to find actual address in case of dynamic IPs<br>Without it you will have to rely on DHT only for getting fresh addresses - + Austausch von Standortinformationen zwischen Freunden. Hilft beim Ermitteln der aktuellen Adresse im Falle von dynamischen IPs<br> Ohne sie sind Sie nur auf DHT angewiesen, um an die neue Adressen zu kommen Used by direct F2F chat, distant chat and chat lobbies - + Wird von direkten F2F-Chats, Distanzchats und Chat-Lobbys verwendet Mailing service. Also required for direct f2f chat - + Mailing-Dienst. Auch für direkten f2f-Chat erforderlich Anonymous routing. Used by file transfers and file search,<br> distant chat, distant mail and distant channels/etc sync - + Anonymous routing. Verwendet für Dateiübertragungen und Dateisuche,,<br> Distanz-Chat, Distanz-Mail und Distanz-Kanäle/etc-Synchronisation Checks if peers alive - + Prüft, ob Peers aktiv sind File transfer. If you kill it - you won't be able to dl files from friend shares. Anonymous access unnaffected - + Dateiübertragung. Wenn Sie es abschalten, können Sie keine Dateien von Freunden herunterladen. Anonymer Zugriff nicht betroffen Used by distant mail for immediate delivery using anonymous tunnels (turtle router) - + Wird von Distant-Mails für die sofortige Zustellung über anonyme Tunnel verwendet (Turtle-Router) Exchange shared directories info, aka browsable(visible) files - + Austausch von Informationen über gemeinsam genutzte Verzeichnisse, d. h. durchsuchbare (sichtbare) Dateien Allows your node to tell to your friends which service are ON on your side, and vice-versa - + Ermöglicht Ihrem Knotenpunkt, Ihren Freunden mitzuteilen, welche Dienste auf Ihrer Seite eingeschaltet sind, und umgekehrt Speed management - + Verwaltung der Geschwindigkeit Used by distant chat, distant mail, and distant channels sync for transfer data using anonymous tunnels - + Verwendet von Distanz-Chat, Distanz-Mail und Distanz-Kanal-Synchronisation für die Datenübertragung über anonyme Tunnel IP filter lists exchange - + Austausch von IP-Filterlisten Share user status like online, away, busy with friends - + Teilen Sie den Benutzerstatus, z. B. online, abwesend oder mit Freunden beschäftigt Identity data exchange. Required by all identities-related functions like chats, forums, mail, etc - + Identitätsdatenaustausch. Erforderlich für alle identitätsbezogenen Funktionen wie Chats, Foren, E-Mail usw @@ -21057,22 +19945,22 @@ p, li { white-space: pre-wrap; } Votes exchange - bans/upvotes for Identities - + Stimmenaustausch - Sperren/Upvotes für Identitäten Used by distant mail for deferred delivery - stored at friends when target offline - + Wird von Distant-Mail für die verzögerte Zustellung verwendet – bei Freunden gespeichert, wenn das Ziel offline ist Measures the Round Trip Time between you and your friends - + Misst die Hin- und Rücklaufzeit zwischen Ihnen und Ihren Freunden unknown - unbekannt + unbekannt @@ -21093,61 +19981,63 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + Quelltext anzeigen - + + Save image + Bild speichern + + + + Copy image + Bild kopieren + + + Document source - + Quelle des Dokuments RSTreeWidget - + Tree View Options Baumansichtoptionen - + Show Header - + Kopfzeile anzeigen Sort by column … - + Nach Spalte sortieren ... Sort Descending Order - + Sortierung absteigend Sort Ascending Order - + Aufsteigend sortieren [no title] - + [kein Titel] Show column … - - - - Show column... - Spalte anzeigen... - - - [no title] - [kein Titel] + Spalte anzeigen ... @@ -21173,7 +20063,7 @@ p, li { white-space: pre-wrap; } Download... - + Herunterladen... @@ -21183,7 +20073,7 @@ p, li { white-space: pre-wrap; } Recommend in a message to... - + Empfehlen Sie in einer Nachricht an... @@ -21196,12 +20086,12 @@ p, li { white-space: pre-wrap; } [All friend nodes] - + [Alle Freundesknoten] Only - Nur + Nur @@ -21211,7 +20101,7 @@ p, li { white-space: pre-wrap; } This node hasn't sent any directory information yet. - + Dieser Knoten hat noch keine Verzeichnisinformationen gesendet. @@ -21219,234 +20109,234 @@ p, li { white-space: pre-wrap; } Paragraph formatting - + Absatzformatierung Font size - Schriftgröße + Schriftgröße Text foreground color - + Vordergrundfarbe des Textes . - + Text background color - + Text-Hintergrundfarbe Undo (CTRL+Z) - + Rückgängig (STRG+Z) Undo - + Rückgängig Redo - + Wiederholen Cut (CTRL+X) - + Ausschneiden (STRG+X) Cut - + Ausschneiden Copy (CTRL+C) - + Kopieren (STRG+C) Copy - Kopieren + Kopieren Paste (CTRL+V) - + Einfügen (STRG+V) Paste - + Einfügen Link (CTRL+L) - + Link (STRG+L) Link - Link + Link Bold - Fett + Fett Italic (CTRL+I) - + Kursiv (STRG+I) Italic - Kursiv + Kursiv Underline (CTRL+U) - + Unterstrichen (STRG+U) Underline - Unterstrichen + Unterstrichen Bullet list (CTRL+-) - + Aufzählungsliste (STRG+-) Bullet list - + Aufzählungsliste Ordered list (CTRL+=) - + Geordnete Liste (STRG+=) Ordered list - + Geordnete Liste Decrease indentation (CTRL+,) - + Einzug verkleinern (STRG+,) Increase indentation (CTRL+.) - + Einrückung vergrößern (STRG+.) Attach a Picture - Bild anhängen + Bild anhängen Text - + TextLabel - TextLabel + TextLabel Standard - + Heading 1 - Überschrift 1 + Überschrift 1 Heading 2 - Überschrift 2 + Überschrift 2 Heading 3 - Überschrift 3 + Überschrift 3 Heading 4 - Überschrift 4 + Überschrift 4 Monospace - + Remove character formatting - + Zeichenformatierung entfernen Remove all formatting - + Alle Formatierungen entfernen Edit document source - + Dokumentquelle bearbeiten Document source - + Quelle des Dokuments Create a link - + Einen Link erstellen Link URL: - + Load Picture File - Bilddatei laden + Bilddatei laden It remains %1 characters after HTML conversion. - + Es verbleiben %1 Zeichen nach der HTML-Konvertierung. Warning: This message is too big of %1 characters after HTML conversion. - + Warnung: Diese Nachricht ist mit %1 Zeichen zu groß nach der HTML-Konvertierung. Text (optional) - + @@ -21516,32 +20406,32 @@ p, li { white-space: pre-wrap; } Save Collection File. - Kollektionsdatei speichern. + Kollektionsdatei speichern. File already exists. - Datei existiert bereits. + Datei existiert bereits. What do you want to do? - Was willst du tun? + Was willst du tun? Overwrite - Überschreiben + Überschreiben Merge - Zusammenfügen + Zusammenfügen Cancel - Abbrechen + Abbrechen @@ -21564,12 +20454,12 @@ p, li { white-space: pre-wrap; } Destination: - + Ziel: Right click to change download directory - + Rechtsklick zum Ändern des Download-Verzeichnisses @@ -21680,17 +20570,17 @@ Die betroffenen Dateien sind rot markiert Download files - + Dateien herunterladen Specify... - + Spezifizieren... Choose directory - + Verzeichnis wählen @@ -21732,12 +20622,12 @@ Die betroffenen Dateien sind rot markiert Do you want to remove them and all their children, too? - + Möchten Sie alle und ihre untergeordneten Elemente ebenfalls entfernen? Do you want to remove this file from the list? - + Möchten Sie diese Datei aus der Liste entfernen? @@ -21811,49 +20701,49 @@ Wenn du glaubst dass es eine korrekte Datei ist, entferne die entsprechende Zeil RsDownloadListModel - + Name i.e: file name - Name + Name Size i.e: file size - Größe + Größe Completed - Fertiggestellt + Fertiggestellt Speed i.e: Download speed - Geschwindigkeit + Geschwindigkeit Progress / Availability i.e: % downloaded - Fortschritt/Verfügbarkeit + Fortschritt/Verfügbarkeit Sources i.e: Sources - Quellen + Quellen Status - Status + Status Speed / Queue position - Geschwindigkeit/Warteschlangenposition + Geschwindigkeit/Warteschlangenposition @@ -21864,12 +20754,12 @@ Wenn du glaubst dass es eine korrekte Datei ist, entferne die entsprechende Zeil Download time i.e: Estimated Time of Arrival / Time left - Restzeit + Restzeit Hash - Prüfsumme + Prüfsumme @@ -21932,34 +20822,34 @@ Wenn du glaubst dass es eine korrekte Datei ist, entferne die entsprechende Zeil RsFriendListModel - + Name - Name + Name Id - ID + ID Last contact - + Letzter Kontakt IP - IP + IP - + Profile ID - + Profil-ID (Not yet validated) - + (Noch nicht bestätigt) @@ -21967,7 +20857,7 @@ Wenn du glaubst dass es eine korrekte Datei ist, entferne die entsprechende Zeil Title - Titel + Titel @@ -21977,55 +20867,53 @@ Wenn du glaubst dass es eine korrekte Datei ist, entferne die entsprechende Zeil Date - Datum + Datum Author - Autor + Autor Information for this identity is currently missing. - + Informationen zu dieser Identität fehlen derzeit. You have banned this ID. The message will not be displayed nor forwarded to your friends. - + Sie haben diese ID verbannt. Die Nachricht wird weder +angezeigt oder an Ihre Freunde weitergeleitet. You have not set an opinion for this person, and your friends do not vote positively: Spam regulation prevents the message to be forwarded to your friends. - + Sie haben keine Meinung zu dieser Person abgegeben, + und Ihre Freunde stimmen nicht positiv ab: Die Spam-Verordnung +verhindert, dass die Nachricht an Ihre Freunde weitergeleitet wird. Message will be forwarded to your friends. - + Die Nachricht wird an Ihre Freunde weitergeleitet. - + [ ... Redacted message ... ] - [ ... Redigierte Nachricht ... ] + [ ... Redigierte Nachricht ... ] [Notification] - + [Benachrichtigung] [Unknown] - [Unbekannt] - - - - [ ... Missing Message ... ] - [ ... Fehlende Nachricht ... ] + [Unbekannt] @@ -22033,72 +20921,84 @@ prevents the message to be forwarded to your friends. Date - Datum + Datum From - Von + Von + + + + To + An Subject - Betreff + Betreff Tags - Schlagwörter + Schlagwörter Click to sort by attachments - Klicken, um nach Anhang zu sortieren + Klicken, um nach Anhang zu sortieren Click to sort by subject - Klicken, um nach Betreff zu sortieren + Klicken, um nach Betreff zu sortieren - Click to sort by read - Klicken, um nach Gelesen / Ungelesen zu sortieren + Click to sort by read status + Klicken, um nach Lesestatus zu sortieren - Click to sort by from - Klicken, um nach Von zu sortieren + Click to sort by author + Klicken, um nach Autor zu sortieren + + + + Click to sort by destination + Klicken, um nach Zielort zu sortieren Click to sort by date - Klicken, um nach Datum zu sortieren + Klicken, um nach Datum zu sortieren Click to sort by tags - Klicken, um nach Schlagwörter zu sortieren + Klicken, um nach Schlagwörter zu sortieren Click to sort by star - Klicken, um nach Kennzeichnung zu sortieren + Klicken, um nach Kennzeichnung zu sortieren Click to sort by junk status - + Klicken, um nach Junk-Status zu sortieren - + + + [Notification] - + [Benachrichtigung] [Unknown] - [Unbekannt] + [Unbekannt] @@ -22112,7 +21012,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. Setzt alle RetroShare-Einstellungen zurück. @@ -22125,7 +21025,7 @@ prevents the message to be forwarded to your friends. filename - + Dateiname @@ -22135,7 +21035,7 @@ prevents the message to be forwarded to your friends. level - + @@ -22145,7 +21045,7 @@ prevents the message to be forwarded to your friends. style - + Stil @@ -22155,7 +21055,7 @@ prevents the message to be forwarded to your friends. stylesheet - + @@ -22165,7 +21065,7 @@ prevents the message to be forwarded to your friends. language - + Sprache @@ -22173,7 +21073,7 @@ prevents the message to be forwarded to your friends. Setzt die Sprache. - + Unable to open log file '%1': %2 Logdatei "%1": %2 kann nicht geöffnet werden @@ -22181,7 +21081,7 @@ prevents the message to be forwarded to your friends. Invalid operating mode specified: - + Ungültige Betriebsart angegeben: @@ -22194,41 +21094,37 @@ prevents the message to be forwarded to your friends. Datenverzeichnis konnte nicht erstellt werden: %1 - Revision - Revision - - - + opmode - + Sets RetroShare's operating mode. - + Legt den Betriebsmodus von RetroShare fest. RsLinkURL - + Open RsLink with protocol retroshare:// - + RsLink mit Protokoll retroshare:// öffnen Open RsFile with or without arg. - + RsFile mit oder ohne Arg öffnen. RetroShare GUI Usage Information - + RetroShare GUI-Nutzungsinformationen - + Invalid language code specified: Ungültige Sprach-Codierung ausgewählt: @@ -22246,10 +21142,10 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. - + Fehler beim Zugriff auf die Registrierung. Möglicherweise benötigen Sie Administratorrechte. @@ -22263,12 +21159,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) Gib einen Suchbegriff ein (min. 3 Zeichen) - + Start Search Suche starten @@ -22330,7 +21226,7 @@ prevents the message to be forwarded to your friends. Leeren - + KeyWords Schlüsselwörter @@ -22345,7 +21241,7 @@ prevents the message to be forwarded to your friends. Such-ID - + Filename Dateiname @@ -22445,33 +21341,33 @@ prevents the message to be forwarded to your friends. Auswahl herunterladen - + File Name Dateiname - + Download Herunterladen - + Copy RetroShare Link RetroShare-Link kopieren - + Send RetroShare Link RetroShare-Link senden Mark as bad - + Als schlecht markieren - + Download Notice Download-Hinweis @@ -22508,7 +21404,7 @@ prevents the message to be forwarded to your friends. Alle entfernen - + Folder Ordner @@ -22516,20 +21412,20 @@ prevents the message to be forwarded to your friends. Obtained via - + Erhältlich über - + New RetroShare Link(s) Neu(e) RetroShare-Link(s) - + Open Folder Ordner öffnen - + Create Collection... Kollektion erstellen... @@ -22549,7 +21445,7 @@ prevents the message to be forwarded to your friends. Von Kollektion herunterladen... - + Collection Kollektion @@ -22557,7 +21453,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details Nachbardetails @@ -22573,22 +21469,22 @@ prevents the message to be forwarded to your friends. Element entfernen - + IP address: IP-Adresse: - + Peer ID: Nachbar-ID: - + Location: Ort: - + Peer Name: Nachbarname: @@ -22605,7 +21501,7 @@ prevents the message to be forwarded to your friends. Verbergen - + but reported: aber gemeldet: @@ -22630,8 +21526,8 @@ prevents the message to be forwarded to your friends. <p>Dies ist die IP, von der dein Freund behauptet, dass er mit ihr verbunden ist. Wenn du deine IP gerade geändert hast, ist dies ein Fehlalarm. Falls nicht, bedeutet dies, dass deine Verbindung zu diesem Freund durch einen zwischengeschalteten Nachbarn weitergeleitet wird, was verdächtig wäre.</p> - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> <html><head/><body><p>Diese Warnung ist hier um dich vor Netzwerktrafficweiterleitungsattacken zu schützen. In so einem Fall sieht der Freund mit dem du verbunden bist nicht deine externe IP sondern die IP des Angreifers.</p><p><br/></p><p>Wenn du allerdings deine IP gerade geändert hast (einige Netzprovider erzwingen eine Änderung der IP in regelmäßigem Abstand), dann bedeutet diese Warnung, dass dein Freund sich zu deiner neuen IP verbunden hat, bevor Retroshare etwas über den IP-Wechsel herausgefunden hat. In diesem Fall ist nicht falsch.</p><p><br/></p><p>Du kannst dies Warnung ganz einfach unterdrücken, indem du deine eigene IP zur Whitelist hinzufügst (z.B. den IP-Bereich deines Netzproviders) oder diese Warnung komplett in Optionen-&gt;Meldungen-&gt;Feed deaktivierst.</p></body></html> @@ -22639,7 +21535,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare möchte mit dir in RetroShare befreundet sein @@ -22670,7 +21566,7 @@ prevents the message to be forwarded to your friends. - + Expand Erweitern @@ -22692,7 +21588,7 @@ prevents the message to be forwarded to your friends. Trust: - Vertrauen: + Vertrauen: @@ -22715,12 +21611,12 @@ prevents the message to be forwarded to your friends. Status: - + Write Message Nachricht schreiben - + Connect Attempt Verbindungsversuch @@ -22740,31 +21636,32 @@ prevents the message to be forwarded to your friends. Unbekannter (ausgehender) Verbindungsversuch - + Unknown Security Issue Unbekanntes Sicherheitsproblem - - A unknown peer - + + SSL request + SSL-Anfrage - + + An unknown peer + Ein unbekannter Peer + + + Unknown - Unbekannt + Unbekannt Profile ID: - + Profil-ID: - Unknown Peer - Unbekannter Nachbar - - - + Hide Verbergen @@ -22774,7 +21671,7 @@ prevents the message to be forwarded to your friends. Möchtest du diesen Freund entfernen? - + Certificate has wrong signature!! This peer is not who he claims to be. Zertifikat hat die falsche Signatur!! Dieser Nachbar ist nicht, wer er vorgibt zu sein. @@ -22784,12 +21681,12 @@ prevents the message to be forwarded to your friends. Fehlendes/beschädigtes SSL-Zertifikat. Kein echter Retroshare-Benutzer - + Certificate caused an internal error. Zertifikat verursachte einen internen Fehler. - + Peer/node not in friendlist (PGP id= Nachbar/Netzknoten nicht in Freundesliste (PGP-ID= @@ -22848,14 +21745,14 @@ prevents the message to be forwarded to your friends. - + Local Address Lokale Adresse - + NAT - + @@ -22874,22 +21771,22 @@ prevents the message to be forwarded to your friends. Port: - + Local network Lokales Netz - + External ip address finder Externer IP Adressen Finder - + UPnP UPnP - + Known / Previous IPs: Bekannte / vorherige IPs: @@ -22905,21 +21802,16 @@ wird es helfen Verbindungen aufzubauen, trotz geringer Anzahl von Freunden. Es hilft auch, wenn du dich hinter einer Firewall/VPN befindest. - - Allow RetroShare to ask my ip to these websites: - RetroShare erlauben, folgende Webseiten nach deiner IP zu fragen: - - - - - + + + kB/s KiB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. Akzeptable Ports reichen von 10 bis 65535. Normalerweise sind Ports unter 1024 von deinem System reserviert. @@ -22929,23 +21821,49 @@ Es hilft auch, wenn du dich hinter einer Firewall/VPN befindest. Akzeptable Ports reichen von 10 bis 65535. Normalerweise sind Ports unter 1024 von deinem System reserviert. - + Onion Address Onion-Adresse - + Discovery On (recommended) Discovery Ein (empfohlen) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. + Tor wurde von Retroshare automatisch konfiguriert. Hier sollten Sie keine Änderungen vornehmenen. + + + + sec - + + local + lokal + + + + external + Externe + + + + + +List of found external IP: + + + +Liste der gefundenen externen IP: + + + + Discovery Off Discovery Aus @@ -22955,7 +21873,7 @@ Es hilft auch, wenn du dich hinter einer Firewall/VPN befindest. Versteckt - Siehe Konfiguration - + I2P Address I2P-Adresse @@ -22980,141 +21898,129 @@ Es hilft auch, wenn du dich hinter einer Firewall/VPN befindest. eingehend in Ordnung - - + + + Proxy seems to work. Proxy scheint zu funktionieren. - + + I2P proxy is not enabled I2P-Proxy ist nicht aktiviert - - BOB is running and accessible - + + SAMv3 is running and accessible + SAMv3 läuft und ist zugänglich - BOB is not accessible! Is it running? - + SAMv3 is not accessible! Is i2p running and SAM enabled? + SAMv3 ist nicht zugänglich! Läuft i2p und ist SAM aktiviert? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + Ihr Schlüssel verwendet die folgenden Algorithmen: %1 und %2 + + + + + unkown key type + unbekannter Schlüsseltyp + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + RetroShare verwendet SAMv3, um einen %1-Tunnel bei %2:%3 einzurichten +(ID: %4) + +Wenn Sie Optionen ändern, verwenden Sie die Schaltflächen unten, um SAMv3 neu zu starten. + + - + + Offline, no SAM session is established yet. + + Offline, es wurde noch keine SAM-Sitzung eingerichtet. + + + + + SAM is trying to establish a session ... this can take some time. + + SAM versucht, eine Sitzung aufzubauen ... dies kann einige Zeit dauern. + + + + + SAM session established! Now setting up a forward session ... + + SAM-Sitzung eingerichtet! Richten Sie jetzt eine Weiterleitungssitzung ein ... + + + + + Online, SAM is working as exptected + + Online, SAM funktioniert wie erwartet + + + + + You key uses %1 for signing and %2 for crypto + Ihr Schlüssel verwendet %1 zum Signieren und %2 für die Verschlüsselung + + + + stop SAM tunnel first to generate a new key + Stoppen Sie zunächst den SAM-Tunnel, um einen neuen Schlüssel zu generieren + + + + stop SAM tunnel first to load a key + Stoppen Sie zuerst den SAM-Tunnel, um einen Schlüssel zu laden + + + + stop SAM tunnel first to disable SAM + Stoppen Sie zuerst den SAM-Tunnel, um SAM zu deaktivieren + + + client server - + Server unknown - unbekannt + unbekannt - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key - + Fordern Sie einen neuen Serverschlüssel an load server key from base64 - + Serverschlüssel von Base64 laden - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. Du bist durch den versteckten Dienst erreichbar. @@ -23123,15 +22029,17 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. The proxy is not enabled or broken. Are all services up and running fine?? Also check your ports! - + Der Proxy ist nicht aktiviert oder defekt. +Sind alle Dienste betriebsbereit? +Überprüfen Sie auch Ihre Ports! - + [Hidden mode] [Versteckter Modus] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> <html><head/><body><p>Dies löscht die Liste der bekannten Adressen. Diese Funktion ist nützlich, wenn deine Adressliste aus irgendeinem Grund ungültige/irrelevante/abgelaufene Adressen enthält, von denen du nicht willst, dass sie an deine Freunde als Kontaktadressen weitergegeben werden.</p></body></html> @@ -23141,7 +22049,7 @@ Also check your ports! Leeren - + Download limit (KB/s) Download-Limit (KB/s) @@ -23156,23 +22064,24 @@ Also check your ports! Upload-Limit (KB/s) - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> <html><head/><body><p>Die Uploadbegrenzung deckt die gesamte Saoftware ab. Eine zu kleine Uploadbegrenzung kann letztendlich Dienste mit niedriger Priorität (Foren, Kanäle) blockieren. Ein Minimumwert von 50KB/s wird empfohlen.</p></body></html> - + WARNING: These values don't take into account the Relays. - + WARNUNG: +Diese Werte berücksichtigen nicht die Relais. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + <html><head/><body><p>Konfiguriere deinen Tor und I2P SOCKS Proxy hier. Damit kannst du dich auch mit hidden Knoten verbinden.</p><p> </p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -23180,57 +22089,38 @@ Tunnel Wizard -> Client Tunnel -> SOCKS 4/4a/5 -> enter a name -> le Now enter the address (e.g. 127.0.0.1) and the port you've picked before for the I2P Proxy. You can connect to Hidden Nodes, even if you are running a standard Node, so why not setup Tor and/or I2P? - + Tor-Socks-Proxy-Standard: 127.0.0.1:9050. In der Torrc-Konfiguration einstellen und hier aktualisieren. + +I2P-Socks-Proxy: Informationen zum Einrichten eines Client-Tunnels finden Sie unter http://127.0.0.1:7657/i2ptunnelmgr: +Tunnel-Assistent -> Client-Tunnel -> SOCKS 4/4a/5 -> geben Sie einen Namen ein -> lassen Sie „Outproxies“ leer -> geben Sie den Port ein (merken Sie sich!) [Vielleicht möchten Sie auch die Erreichbarkeit auf 127.0.0.1 setzen] -> Weiter -> 'Auto Start' ankreuzen -> Fertig! +Geben Sie nun die Adresse (z. B. 127.0.0.1) und den Port ein, den Sie zuvor für den I2P-Proxy ausgewählt haben. + +Sie können sich mit versteckten Knoten verbinden, auch wenn Sie einen Standardknoten betreiben. Warum also nicht Tor und/oder I2P einrichten? - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings - + aktiviert erweiterte Einstellungen advanced mode - + Erweiterter Modus - - I2P Basic Open Bridge - - - - + I2P Instance address - + I2P-Instanzadresse 127.0.0.1 - 127.0.0.1 + 127.0.0.1 - - I2P proxy port - - - - - BOB accessible - - - - + Address - + Adresse @@ -23240,62 +22130,57 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why generate new - + neu erstellen Tunnel length (in/out) - + Tunnellänge (ein/aus) Tunnel quantity (in/out) - + Tunnelmenge (ein/aus) Tunnel variance (in/out) - + Tunnelvarianz (ein/aus) <html><head/><body><p>Server Key - When a key it set it will be used to setup a hidden<br/>service for I2P. Otherwise only a client tunnel is created.</p></body></html> - + <html><head/><body><p>Server Key - Wenn ein Key gesetzt wird, wird er verwendet um einen hidden<br/>Service für I2P einzurichten. Ansonsten wird nur ein Client-Tunnel erstellt.</p></body></html> load key - + Ladeschlüssel - + Start - Start + Start Restart - + Neustart Stop - Stop + Stop - - BOB status - - - - + Incoming - Eingehend + Eingehend <html><head/><body><p>Setup your hidden address (and port if needed)</p></body></html> - + <html><head/><body><p>Einstellen der hidden Adresse (und Port, falls erforderlich)</p></body></html> @@ -23321,42 +22206,78 @@ This is your external address on the Tor/I2P network. Finally make sure that the Ports match the configuration. If you have issues connecting over Tor check the Tor logs too. - + Um Verbindungen zu empfangen, müssen Sie zunächst einen versteckten Tor/I2P-Service einrichten. + +Für Tor: Siehe torrc und Dokumentation für HOWTO-Details. + +Für I2P: Informationen zum Einrichten eines Servertunnels finden Sie unter http://127.0.0.1:7657/i2ptunnelmgr: +Tunnel-Assistent -> Servertunnel -> Standard -> Geben Sie einen Namen ein -> Geben Sie die Adresse und den Port ein, den Ihr RS verwendet (siehe Lokale Adresse oben) -> Aktivieren Sie „Autostart“ -> Fertig! + +Sobald dies erledigt ist, fügen Sie die Onion/I2P (Base32)-Adresse in das Feld oben ein. +Dies ist Ihre externe Adresse im Tor/I2P-Netzwerk. +Stellen Sie abschließend sicher, dass die Ports mit der Konfiguration übereinstimmen. + +Wenn Sie Probleme beim Herstellen einer Verbindung über Tor haben, überprüfen Sie auch die Tor-Protokolle. - + + Automatic I2P + Automatisch I2P + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + Aktivieren Sie I2P SAMv3 - eine Änderung dieser Einstellung erfordert einen Neustart, um vollständig wirksam zu werden + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + SAM zugänglich + + + + SAM status + + + + Relay - + Relais Enable Relay Connections - + Aktivieren von Relais-Verbindungen Use Relay Servers - + Verwenden Sie Relay-Server Relay options - + Relaisoptionen Number - + Nummer Bandwidth per link - + Bandbreite pro Verbindung Total Bandwidth - + Gesamtbandbreite @@ -23376,17 +22297,17 @@ If you have issues connecting over Tor check the Tor logs too. Total: - Gesamt: + Gesamt: - + Warning: This bandwidth adds up to the max bandwidth. - + Warnung: Diese Bandbreite summiert sich zur maximalen Bandbreite. Relay Server Setup - + Relay-Server-Setup @@ -23396,7 +22317,7 @@ If you have issues connecting over Tor check the Tor logs too. Server DHT Key - + Server-DHT-Schlüssel @@ -23404,7 +22325,7 @@ If you have issues connecting over Tor check the Tor logs too. Server entfernen - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -23416,7 +22337,7 @@ If you have issues connecting over Tor check the Tor logs too. Netzwerk - + IP Filters IP-Filter @@ -23439,7 +22360,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status Status @@ -23499,24 +22420,35 @@ If you have issues connecting over Tor check the Tor logs too. Zu Whitelist hinzufügen - + Hidden Service Configuration Versteckte Dienstkonfiguration - + + Allow RetroShare to ask my ip to these DNS servers: + Erlauben Sie RetroShare, meine IP bei diesen DNS-Servern zu erfragen: + + + + + List of OpenDns servers used. + Liste der verwendeten OpenDns-Server. + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> I2P Socks Proxy - + @@ -23525,18 +22457,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + I2P ausgehend Okay - + Service Address Dienstadresse @@ -23571,12 +22503,12 @@ If you have issues connecting over Tor check the Tor logs too. Bitte geben Sie eine Dienstadresse ein - + IP Range IP-Bereich - + Reported by DHT for IP masquerading Von DHT für IP-Maskierung gemeldet @@ -23599,22 +22531,22 @@ If you have issues connecting over Tor check the Tor logs too. Von dir hinzugefügt - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> <html><head/><body><p>IPs auf der Whitelist werden aus folgenden Quellen gesammelt: IPs eines manuell ausgetauschten Zertifikats, von dir in diesem Fenster oder in den Sicherheitseingabeelementen eingegebene IP-Bereiche.</p><p>Das Standardverhalten von RetroShare ist (1) Verbindungen zu Nachbarn mit IP-Adressen in der Whitelist immer zulassen, auch wenn die IP ebenfalls in der Blacklist eingetragen ist; (2) optional erfordern, dass die IPs in der Whitelist eingetragen sind. Du kannst dieses Verhalten für jeden Nachbarn im &quot;Details&quot;-Fenster eines jeden RetroShare-Netzknotens ändern.</p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> <html><head/><body><p>DHT erlaubt es dir Verbindungdsanfragen von deinen Freunden mit Hilfe von BitTorrent's DHT zu beantworten. Es verbessert die Konnektivität enorm. Im DHT werden keine Informationen gespeichert. Es dient nur als Proxysystem um Verbindung mit anderen Retroshare Netzknoten aufzunehmen.</p><p>Der Discovery Dienst sendet node namen und ids deiner vertreuenswürdigen Konakte an verbundene Nachbarn, um ihnen bei der Wahl neuer Freunde zu helfen. Die Freundschaft wird jedoch nie automatisch hergestellt und beide Nachbarn müssen sich immer noch gegenseitig vertrauen, um eine Verbindung zu erlauben. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> <html><head/><body><p>Die Kugel wird grün, sobald es RetroShare gelingt, deine eigene IP von den unten aufgeführten Webseiten zu bekommen - sofern du diese Aktion aktiviert hast. RetroShare nutzt auch noch andere Wege, um deine IP herauszufinden.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> <html><head/><body><p>Diese Liste wird automatisch mit Informationen aus veschiedenen Quellen gefüllt: Maskierte Nachbarn gemeldet vom DHT, von dir eingetragene IP Bereiche und von deinen Freunden übermittelte IP Bereiche. Die Grundeinstellung sollte dich gegen groß angelegte Verbindungsweiterleitungsattacken schützen.</p><p>Automatisches eintragen von markierten IPs kan die IPs deiner Freunde auf die Blacklist setzen. Benutze in diesem Fall das Kontextmenü, um sie auf die Whitelist zu verschieben.</p></body></html> @@ -23649,9 +22581,9 @@ If you have issues connecting over Tor check the Tor logs too. Automatisch Bereiche DHT-maskierender IPs sperren, beginnend ab - + Outgoing Manual Tor/I2P - + Ausgehend manuelles Tor/I2P @@ -23659,12 +22591,12 @@ If you have issues connecting over Tor check the Tor logs too. Tor Socks Proxy - + Tor outgoing Okay - Tor ausgehend o. k. + Tor ausgehend Okay - + Tor proxy is not enabled Tor-Proxy ist nicht aktiviert @@ -23744,7 +22676,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with Wähle die Nachbarn, mit denen du den privaten Veröffentlichungsschlüssel teilen möchtest @@ -23754,12 +22686,12 @@ If you have issues connecting over Tor check the Tor logs too. Für Freund teilen - + Share Teilen - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. Du kannst deine Freunde von deinem Kanal wissen lassen, indem du ihn mit ihnen teilst. @@ -23779,9 +22711,9 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. Ordnerfreigabe-Manager - + Shared directory - + Freigegebenes Verzeichnis @@ -23799,17 +22731,17 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. Sichtbarkeit - + Add new - + Neu hinzufügen - + Cancel Abbrechen - + Add a Share Directory Freigabe hinzufügen @@ -23819,7 +22751,7 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. Entfernen - + Apply and close Anwenden und Schließen @@ -23841,7 +22773,7 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. Choose directory to share... - + Verzeichnis zum Freigeben auswählen... @@ -23851,32 +22783,32 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. [Unset] (Double click to change) - + [Ungesetzt] (Doppelklick zum Ändern) Double click to select which groups of friends can see the files - + Doppelklick, um auszuwählen, welche Gruppen von Freunden die Dateien sehen dürfen Double click to change the name that friends will see. - + Doppelklicken Sie darauf, um den Namen zu ändern, den Ihre Freunde sehen werden. Double click to change shared directory path - + Doppelklick zum Ändern des gemeinsamen Verzeichnispfades Directory does not exist! Double click to change shared directory path - + Das Verzeichnis existiert nicht! Doppelklicken Sie, um den Pfad zum gemeinsamen Verzeichnis zu ändern [All friend nodes] - + [Alle Freundesknoten] @@ -23891,7 +22823,7 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. Choose a directory to share - + Wählen Sie ein Verzeichnis zur Freigabe @@ -23910,7 +22842,7 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. Ordner nicht gefunden oder Ordnername nicht akzeptiert. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. Dies ist eine Liste freigegebener Ordner. Du kannst mit den Knöpfen unten Ordner hinzufügen und entfernen. Wenn du einen neuen Ordner hinzufügst sind alle Dateien darin von Anfang an freigegeben. Du kannst für jeden freigegebenen Ordner die Freigabeflags separat festlegen. @@ -23918,14 +22850,14 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. SharedFilesDialog - + Files Dateien Configure shared directories - + Freigegebene Verzeichnisse konfigurieren @@ -23969,11 +22901,16 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + <html><head/><body><p>Erzwingt die erneute Überprüfung aller freigegebenen Verzeichnisse. Während sich die automatische Dateiprüfung aus Effizienzgründen nur um neue/entfernte Dateien kümmert, erzwingt diese Schaltfläche die erneute Prüfung aller Dateien und führt möglicherweise ein erneutes Hashing vorhandener Dateien durch, die sich möglicherweise geändert haben. </p></body></html> + + + check files Dateien prüfen - + Download selected Auswahl herunterladen @@ -23983,7 +22920,7 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. Herunterladen - + Copy retroshare Links to Clipboard RetroShare-Links in die Zwischenablage kopieren @@ -23998,9 +22935,9 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. RetroShare-Links senden - + Some files have been omitted - + Einige Dateien wurden ausgelassen @@ -24014,14 +22951,14 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. Empfehlung(en) - + Create Collection... Kollektion erstellen... Stop sharing this file - + Freigabe dieser Datei beenden @@ -24039,39 +22976,39 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. Von Kollektion herunterladen... - + Some files have been omitted because they have not been indexed yet. - + Einige Dateien wurden ausgelassen, weil sie noch nicht indexiert wurden. Search string should be at least 3 characters long. - + Der Suchbegriff sollte mindestens 3 Zeichen lang sein. More than 3000 results. Add more/longer search words to select less. - + Mehr als 3000 Ergebnisse. Fügen Sie mehr/längere Suchbegriffe hinzu, um weniger auszuwählen. Warning: You reach max (%1) files in flat list. No more will be added. - + Warnung: Sie haben die maximale Anzahl (%1) von Dateien in der Flat-Liste erreicht. Es werden keine weiteren hinzugefügt. No result. - + Kein Ergebnis. More than %1 results. Add more/longer search words to select less. - + Mehr als %1 Ergebnisse. Fügen Sie mehr/längere Suchbegriffe hinzu, um weniger auszuwählen. Found %1 results. - + %1 Ergebnisse gefunden. @@ -24094,7 +23031,7 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. New Msg - Neue Nachr. + Neue Nachricht @@ -24182,12 +23119,12 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. SplashScreen - + Load configuration Konfiguration laden - + Create interface Oberfläche erstellen @@ -24211,7 +23148,7 @@ Wähle die Freunde, mit denen du den Kanal teilen willst. Passwort speichern - + Log In Anmelden @@ -24231,7 +23168,11 @@ Die aktuellen Identitäten/Orte werden nicht geändert. p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">New Profile/Node</span></a></p></body></html> - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Neues Profil/Knoten</span></a></p></body></html> @@ -24371,7 +23312,7 @@ Du kannst die Auswahl in den Optionen zurücksetzen. Identities - Identitäten + Identitäten @@ -24381,7 +23322,7 @@ Du kannst die Auswahl in den Optionen zurücksetzen. Gxs Transport - + @@ -24564,7 +23505,7 @@ Du kannst die Auswahl in den Optionen zurücksetzen. Statusnachricht - + Message: Nachricht: @@ -24809,7 +23750,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags Alle Schlagwörter entfernen @@ -24837,117 +23778,161 @@ p, li { white-space: pre-wrap; } Dialog - Dialog + Dialog Setting up Tor... - + Einrichten von Tor... - + + Tor status: - + - + + + Unknown Unbekannt Not started - + Nicht gestartet - - Hidden service address: - + + Hidden address: + Hidden adresse: - - Tor bootstrap status: - - - - - + + Not set - + Nicht festgelegt Onion address: - + Onion adresse: - + + Error + Fehler + + + + Not connected + Nicht verbunden + + + + Connecting + Verbinde + + + + Socket connected + Socket verbunden + + + + Authenticating + Authentifizierung + + + + Authenticated + Authentifiziert + + + + Hidden service ready + Hidden Service bereit + + + + Tor offline + + + + + Tor ready + Tor bereit + + + Check that Tor is accessible in your executable path - + Prüfe, ob Tor in deinem ausführbaren Pfad zugänglich ist - + [Waiting for Tor...] - + [Warten auf Tor...] TorStatus - + Tor Tor <p>This version of Retroshare uses Tor to connect to your trusted nodes.</p> - + <p>Diese Version von Retroshare benutzt Tor, um sich mit deinen vertrauenswürdigen Knoten zu verbinden.</p> - + Tor is currently offline - + Tor ist derzeit offline Tor is OK - + Tor ist OK + No tor configuration - + Keine Tor-Konfiguration - + Tor proxy is OK - + Tor-Proxy ist OK Tor proxy is not available - + Tor-Proxy ist nicht verfügbar I2P - + i2p proxy is OK - + i2p-Proxy ist OK i2p proxy is not available - + i2p-Proxy ist nicht verfügbar TransferPage - + Transfer options Übertragungsoptionen @@ -24958,32 +23943,37 @@ p, li { white-space: pre-wrap; } Maximale gleichzeitige Downloads: - + Shared Directories - + Freigegebene Verzeichnisse Automatically share incoming directory (Recommended) - Eingehende Ordner automatisch freigeben (Empfohlen) + Eingehende Ordner automatisch freigeben (Empfohlen) - - Edit Share - - - - + Directories - + Verzeichnisse - + + Configure shared directories + Freigegebene Verzeichnisse konfigurieren + + + Auto-check shared directories every - + Freigegebene Verzeichnisse automatisch überprüfen + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) Minute(n) @@ -24995,7 +23985,7 @@ p, li { white-space: pre-wrap; } follow symbolic links - + symbolischen Links folgen @@ -25005,12 +23995,12 @@ p, li { white-space: pre-wrap; } Ignore duplicate files/directories - + Doppelte Dateien/Verzeichnisse ignorieren Maximum depth (0=unlimited): - + Maximale Tiefe (0=unbegrenzt): @@ -25020,7 +24010,7 @@ p, li { white-space: pre-wrap; } Ignore files ending with: - + Ignoriere Dateien, die mit: @@ -25030,7 +24020,7 @@ p, li { white-space: pre-wrap; } ignore files starting with: - + Dateien ignorieren, die mit: @@ -25056,19 +24046,19 @@ p, li { white-space: pre-wrap; } Automatically donwload RsCollection file content (Not recommended) - + Inhalt der RsCollection-Datei automatisch herunterladen (nicht empfohlen) Partials Directory - + Partials-Verzeichnis <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -25077,9 +24067,14 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + Mindestschriftgröße für freigegebene Dateien + + + Maximum uploads per friend (0 = no limit) - + Maximale Uploads pro Freund (0 = keine Begrenzung) @@ -25099,10 +24094,15 @@ p, li { white-space: pre-wrap; } Allow direct download: + Direkten Download zulassen: + + + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - + Streaming Streaming @@ -25154,12 +24154,12 @@ p, li { white-space: pre-wrap; } Per user - + Pro Benutzer Trust friend nodes with banned files - + Vertrauen Sie befreundeten Knoten mit gebannten Dateien @@ -25167,14 +24167,9 @@ p, li { white-space: pre-wrap; } Max. weiterzuleitende Tunnelanfragen pro Sekunde: - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>bewirkt dass die Übertragung 1MB große Dateistücke in aufsteigender Ordnung anfordert, so dass eine Vorschau während des Downloads ermögllicht wird. <span style=" font-weight:600;">Zufällig</span> ist rein zufällig und begünstigt Schwarmverhalten. <span style=" font-weight:600;">Progressiv</span> ist ein Kompromiss der das nächste Teilstück zufällig innerhalb von weniger als 50 MB nach dem Ende der patiellen Datei auswählt. Das erlaubt etwas Zufälligket während es hohe Initialisationzeiten für leere Dateien vehindert.</p></body></html> - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> - <html><head/><body><p>RetroShare wird alle Übertragungen und das Speichern von Konfigurationsdaten aussetzen, wenn der freie Festplattenspeicher unter dieses Limit fällt. Auf einigen Systemen verhindert dies Informationsverlust. Ein Hinweisfenster wird dich warnen, wenn das passiert.</p></body></html> + <html><head/><body><p>RetroShare wird alle Übertragungen und das Speichern von Konfigurationsdaten aussetzen, wenn der freie Festplattenspeicher unter dieses Limit fällt. Auf einigen Systemen verhindert dies Informationsverlust. Ein Hinweisfenster wird dich warnen, wenn das passiert.</p></body></html> @@ -25182,24 +24177,34 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Dieser Wert kontrolliert, wie viele Tunnel-Anfragen dein Nachbar pro Sekunde weiterleiten darf.</p><p>Wenn du eine große Internet-Bandbreite hast, kannst du diesen auf 30–40 erhöhen, um statistisch längere Tunnel zu ermöglichen. Vorsicht! Dies erzeugt viele kleine Pakete die deine eigenen Dateitransfers merklich verlangsamen können.</p><p>Voreinstellung ist 20. Wenn du dir nicht sicher bist, belasse es dabei.</p></body></html> - + + Warning + Warnung + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + Auf Windows-Systemen kann das zufällige Schreiben in die Mitte großer leerer Dateien dazu führen, dass die Software mehrere Sekunden lang hängen bleibt. Möchten Sie diese Option trotzdem verwenden (andernfalls „progressiv“ verwenden)? + + + Set Incoming Directory - + Eingehendes Verzeichnis festlegen Invalid Input. Have you got the right to write on it? - + Ungültige Eingabe. Haben Sie die Rechte, darauf zu schreiben? Set Partials Directory - + Partialverzeichnis festlegen Invalid Input. It can't be an already shared directory. - + Ungültige Eingabe. Es kann sich nicht um ein bereits freigegebenes Verzeichnis handeln. @@ -25210,63 +24215,47 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed Download abgeschlossen You have %1 completed transfers - + Sie haben %1 transfer abgeschlossen You have %1 completed transfer - + Sie haben %1 transfer abgeschlossen %1 completed transfers - + %1 transfers abgeschlossen %1 completed transfer - - - - You have %1 completed downloads - Du hast %1 fertige Downloads - - - You have %1 completed download - Du hast %1 fertigen Download - - - %1 completed downloads - %1 fertige Downloads - - - %1 completed download - %1 fertiger Download + %1 transfer abgeschlossen TransfersDialog - - + + Downloads Downloads - + Uploads Uploads - + Name i.e: file name Name @@ -25353,7 +24342,7 @@ p, li { white-space: pre-wrap; } Peer i.e: user name / tunnel id - Nachbar + Nachbar @@ -25473,7 +24462,12 @@ p, li { white-space: pre-wrap; } Spezifizieren... - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; Dateiübertragung</h1><p>Retroshare bietet zwei Möglichkeiten, Dateien zu übertragen: direkte Übertragungen von Ihren Freunden und anonyme, getunnelte Fernübertragungen. Außerdem ist der Dateitransfer quellenübergreifend und erlaubt das Schwärmen (Sie können beim Herunterladen eine Quelle sein)</p><p>Sie können Dateien über das Symbol <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> in der linken Seitenleiste teilen. Diese Dateien werden in der Registerkarte "Meine Dateien" aufgelistet. Sie können für jede Freundesgruppe entscheiden, ob sie diese Dateien in der Registerkarte "Dateien von Freunden" sehen können oder nicht</p><p>Die Registerkarte "Suchen" zeigt Dateien aus den Dateilisten Ihrer Freunde und entfernte Dateien an, die über das Multi-Hop-Tunnelsystem anonym erreicht werden können.</p> + + + Move in Queue... In Warteschlange verschieben... @@ -25498,7 +24492,7 @@ p, li { white-space: pre-wrap; } Ordner auswählen - + Anonymous end-to-end encrypted tunnel 0x Anonymer Ende-zu-Ende-verschlüsselter Tunnel 0x @@ -25506,7 +24500,7 @@ p, li { white-space: pre-wrap; } Tunnel - + @@ -25519,7 +24513,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -25552,7 +24546,17 @@ p, li { white-space: pre-wrap; } Datei %1 ist nicht komplett. Falls es eine Mediadatei ist, dann versuche "Vorschau". - + + Warning + Warnung + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + Auf Windows-Systemen kann das Schreiben in der Mitte großer leerer Dateien dazu führen, dass die Software für einige Sekunden hängen bleibt. Möchten Sie diese Option trotzdem verwenden? + + + Change file name Dateinamen ändern @@ -25567,7 +24571,7 @@ p, li { white-space: pre-wrap; } Bitte gib einen neuen -- und gültigen -- Dateinamen ein - + Expand all Alle erweitern @@ -25670,47 +24674,42 @@ p, li { white-space: pre-wrap; } Peer - Nachbar + Nachbar Show Peer Column - + Peer-Spalte anzeigen Show Transferred Column - + Übertragene Spalte anzeigen Progress - Fortschritt + Fortschritt Show Progress Column - + Fortschrittsspalte anzeigen - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Spalten - + File Transfers Dateiübertragungen - + Path Pfad @@ -25720,7 +24719,7 @@ p, li { white-space: pre-wrap; } Pfadspalte anzeigen - + Could not delete preview file Konnte Vorschaudatei nicht löschen @@ -25730,7 +24729,7 @@ p, li { white-space: pre-wrap; } Nochmal versuchen? - + Create Collection... Kollektion erstellen... @@ -25745,17 +24744,17 @@ p, li { white-space: pre-wrap; } Kollektion ansehen... - + Collection Kollektion %1 tunnels - + %1 Tunnel - + Anonymous tunnel 0x Anonymer Tunnel 0x @@ -25788,12 +24787,12 @@ p, li { white-space: pre-wrap; } Show Empty - + Leere anzeigen Temporary shared files - + Temporäre freigegebene Dateien @@ -25804,7 +24803,7 @@ p, li { white-space: pre-wrap; } Empty - + Leer @@ -25815,7 +24814,7 @@ p, li { white-space: pre-wrap; } Friends Directories [updating...] - + Verzeichnisse von Freunden [Aktualisierung...] @@ -25825,7 +24824,7 @@ p, li { white-space: pre-wrap; } My Directories [updating...] - + Meine Verzeichnisse [Aktualisierung...] @@ -25835,7 +24834,7 @@ p, li { white-space: pre-wrap; } # Files - + # Dateien @@ -25884,7 +24883,7 @@ p, li { white-space: pre-wrap; } Unknown Peer - Unbekannter Nachbar + Unbekannter Nachbar @@ -25928,7 +24927,7 @@ p, li { white-space: pre-wrap; } Request id: %1 %3 secs ago from %2 %4 (%5 hits) - + Anfrage-ID: vor %1 %3 Sekunden von %2 %4 (%5 Treffer) @@ -25974,11 +24973,7 @@ p, li { white-space: pre-wrap; } File transfer tunnels - - - - Anonymous tunnels - Anonyme Tunnel + Dateiübertragungstunnel @@ -25988,7 +24983,7 @@ p, li { white-space: pre-wrap; } GXS sync tunnels - + GXS sync Tunnel @@ -26173,48 +25168,49 @@ p, li { white-space: pre-wrap; } Formular - + Enable Retroshare WEB Interface RetroShare-Weboberfläche aktivieren - + + Status: + Status: + + + Web parameters Web-Parameter Password: - + Passwort: Web interface directory: - + Verzeichnis der Webschnittstelle: <html><head/><body><p>Select directory for webinterface files (advanced)</p></body></html> - + <html><head/><body><p>Verzeichnis für Webinterface-Dateien auswählen (erweitert)</p></body></html> Apply settings - + Einstellungen übernehmen Start web browser - + Starten Sie den Webbrowser <html><head/><body><p>Note: these settings do not affect retroshare-service, which has a command line switch to activate the web interface and select the listening port.</p></body></html> - - - - Port: - Port: + <html><head/><body><p>Hinweis: Diese Einstellungen haben keinen Einfluss auf den retroshare-Service, der über einen Kommandozeilenschalter verfügt, um die Web-Schnittstelle zu aktivieren und den Listening-Port auszuwählen.</p></body></html> @@ -26222,21 +25218,27 @@ p, li { white-space: pre-wrap; } Zugriff von allen IP-Adressen erlauben (standardmäßig nur localhost) - Apply setting and start browser - Einstellung anwenden und Browser starten - - - + Please select the directory were to find retroshare webinterface files - + Bitte wählen Sie das Verzeichnis aus, in dem sich die retroshare webui dateien befinden - + + Missing passphrase + Passwort fehlt + + + + Please set a passphrase to proect the access to the WEB interface. + Bitte legen Sie eine Passwort fest, um den Zugriff auf die WEB-Schnittstelle zu schützen. + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled Weboberfläche nicht aktiviert @@ -26246,12 +25248,12 @@ p, li { white-space: pre-wrap; } Die Weboberfläche ist nicht aktiviert. Aktivieren Sie sie unter Einstellungen -> Weboberfläche. - + failed to start Webinterface Start der Weboberfläche fehlgeschlagen - + Webinterface Weboberfläche @@ -26372,7 +25374,7 @@ p, li { white-space: pre-wrap; } Cancel - Abbrechen + Abbrechen @@ -26388,11 +25390,7 @@ p, li { white-space: pre-wrap; } Wiki-Seiten - New Group - Neue Gruppe - - - + Page Name Seitenname @@ -26407,7 +25405,7 @@ p, li { white-space: pre-wrap; } Orig. ID - + << << @@ -26464,7 +25462,7 @@ p, li { white-space: pre-wrap; } Create Group - Gruppe erstellen + Gruppe erstellen @@ -26495,7 +25493,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History Bearbeitungsverlauf der Seite @@ -26530,7 +25528,7 @@ p, li { white-space: pre-wrap; } Seiten-ID - + \/ \/ @@ -26560,14 +25558,18 @@ p, li { white-space: pre-wrap; } Schlagwörter - - + + History + Verlauf + + + Show Edit History Bearbeitungsverlauf anzeigen - + Status Status @@ -26588,7 +25590,7 @@ p, li { white-space: pre-wrap; } Rückgängig machen - + Submit Absenden @@ -26660,29 +25662,20 @@ p, li { white-space: pre-wrap; } WireDialog - - TimeRange - TimeRange - Create Account - + Account erstellen Post Pulse - + Beitrag erstellen - - Refresh - Aktualisieren - - - + Settings - + Einstellungen @@ -26692,152 +25685,84 @@ p, li { white-space: pre-wrap; } Others - Andere + Andere - + Who to Follow - + Wem folgen HomePage - + < - + > - + - + Most Recent - + Show Posts from - + Beiträge anzeigen von All Time - + Allzeit Last 24 hours - + Letzte 24 Stunden Last 7 days - + Letzte 7 Tage Last 30 days - + Letzte 30 Tage - Last Month - Letzter Monat - - - Last Week - Letzte Woche - - - Today - Heute - - - New - Neu - - - from - von - - - until - bis - - - Search/Filter - Suchen/Filtern - - - Network Wide - Netzwerkweit - - - Manage Accounts - Konten verwalten - - - Showing: - Zeige: - - - + Yourself Du - - Friends - Freunde - Following Folgend - Custom - Benutzerdefiniert - - - Account 1 - Konto 1 - - - Account 2 - Konto 2 - - - Account 3 - Konto 3 - - - CheckBox - CheckBox - - - Post Pulse to Wire - Puls an Wire senden - - - + RetroShare - RetroShare + RetroShare Please create or choose Wire Groupd first - + Bitte erstelle oder wählen Sie ihr Wire Account The Wire - The Wire + The Wire @@ -26845,37 +25770,37 @@ p, li { white-space: pre-wrap; } Create New Wire - + Neuen Account erstellen Create - Erstellen + Erstellen Wire - + Edit Wire - + Account bearbeiten Update Wire - + Account aktualisieren Add Wire Admins - + Admins hinzufügen Select Wire Admins - + Admins auswählen @@ -26883,37 +25808,44 @@ p, li { white-space: pre-wrap; } Form - Formular - - - - Masthead - + Formular + + MastHead background Image - + Hintergrundbild - + Select Image - + Bild auswählen - + Tagline: - + Schlagwort: - Location: - Ort: + Remove + Entfernen - + + Location: + Ort: + + + Load Masthead - + Hintergrund Bild + + + + Use the mouse to zoom and adjust the image for your background. + Benutzen Sie die Maus, um das Bild zu zoomen und für Ihren Hintergrund anzupassen. @@ -26921,13 +25853,13 @@ p, li { white-space: pre-wrap; } Form - Formular + Formular Avatar - Avatar + Avatar @@ -26937,12 +25869,12 @@ p, li { white-space: pre-wrap; } Type - Typ + Typ \/ - \/ + \/ @@ -26957,13 +25889,43 @@ p, li { white-space: pre-wrap; } Edit Profile + Profil editieren + + + + Own + Eigene + + + + N/A + + + Following + Folgend + + + + Unfollow + Entfolgen + + + + Other + Andere + + + + Follow + Folgen + misc - + Unknown Unknown (size) Unbekannt @@ -27003,7 +25965,7 @@ p, li { white-space: pre-wrap; } PB petabytes (1024 terabytes) - + @@ -27041,7 +26003,7 @@ p, li { white-space: pre-wrap; } %1J %2T - + k e.g: 3.1 k Ki @@ -27072,19 +26034,15 @@ p, li { white-space: pre-wrap; } Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif *.webp) - - - - Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - Bilder (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) + Bilder (*.png *.jpeg *.xpm *.jpg *.tiff *.gif *.webp) pgpid_item_model - + Do you accept connections signed by this profile? - + Akzeptieren Sie von diesem Profil signierte Verbindungen? @@ -27094,22 +26052,22 @@ p, li { white-space: pre-wrap; } This column indicates the trust level you indicated and whether you signed the profile PGP key - + In dieser Spalte wird die von Ihnen angegebene Vertrauensstufe angezeigt und ob Sie den PGP-Schlüssel des Profils signiert haben Did that peer sign your own profile PGP key - + Hat dieser Peer Ihren eigenen Profil-PGP-Schlüssel signiert PGP Key Id of that profile - + PGP-Schlüssel-ID dieses Profils Last time this key was used (received time, or to check connection) - + Wann dieser Schlüssel zuletzt verwendet wurde (Empfangszeit oder zur Überprüfung der Verbindung) @@ -27124,12 +26082,12 @@ p, li { white-space: pre-wrap; } Trust level - + Vertrauens Level Has signed your key? - + Haben Sie Ihren Schlüssel signiert? @@ -27149,17 +26107,17 @@ p, li { white-space: pre-wrap; } Marginally trusted peer - + Wenig vertrauenswürdiger Peer Fully trusted peer - + Völlig vertrauenswürdige rPeer Untrusted peer - + Nicht vertrauenswürdiger Peer @@ -27199,7 +26157,7 @@ p, li { white-space: pre-wrap; } Denied - + Verweigert @@ -27210,7 +26168,8 @@ p, li { white-space: pre-wrap; } has authenticated you. Right-click and select 'make friend' to be able to connect. - + hat dich authentifiziert. +Klicken Sie mit der rechten Maustaste und wählen Sie „Freundschaft schließen“, um eine Verbindung herzustellen. @@ -27218,17 +26177,17 @@ Right-click and select 'make friend' to be able to connect. Plugin disabled. Click the enable button and restart Retroshare - + Plugin deaktiviert. Klicken Sie auf die Schaltfläche "Aktivieren" und starten Sie Retroshare neu [disabled] - [deaktivert] + [deaktivert] No API number supplied. Please read plugin development manual. - Keine API-Nummer angegeben. Bitte konsultiere das Handbuch für die Entwicklung von Plug-ins. + Keine API-Nummer angegeben. Bitte konsultiere das Handbuch für die Entwicklung von Plug-ins. @@ -27237,37 +26196,37 @@ Right-click and select 'make friend' to be able to connect. [loading problem] - [Ladeproblem] + [Ladeproblem] No SVN number supplied. Please read plugin development manual. - Keine SVN-Nummer angegeben. Bitte konsultiere das Handbuch für die Entwicklung von Plug-ins. + Keine SVN-Nummer angegeben. Bitte konsultiere das Handbuch für die Entwicklung von Plug-ins. Loading error. - Fehler beim Laden. + Fehler beim Laden. Missing symbol. Wrong version? - Fehlendes Symbol. Falsche Version? + Fehlendes Symbol. Falsche Version? No plugin object - Kein Plug-in Objekt + Kein Plug-in Objekt Plugins is loaded. - Plug-in ist geladen. + Plug-in ist geladen. Unknown status. - Unbekannter Status. + Unbekannter Status. @@ -27287,7 +26246,7 @@ schädlichem Verhalten von Plug-ins. Plugins - Plug-ins + Plug-ins diff --git a/retroshare-gui/src/lang/retroshare_el.ts b/retroshare-gui/src/lang/retroshare_el.ts index a334a32f9..1b43e7f05 100644 --- a/retroshare-gui/src/lang/retroshare_el.ts +++ b/retroshare-gui/src/lang/retroshare_el.ts @@ -84,13 +84,6 @@ - - AddCommentDialog - - Add Comment - Προσθήκη σχολίου - - AddFileAssociationDialog @@ -129,12 +122,12 @@ RetroShare: Σύνθετη Αναζήτηση - + Search Criteria Κριτήρια αναζήτησης - + Add a further search criterion. Προσθήκη κριτηρίου αναζήτησης @@ -144,7 +137,7 @@ Επαναφορά κριτηρίου αναζήτησης - + Cancels the search. Διακοπη αναζητησης @@ -164,177 +157,6 @@ Αναζήτηση - - AlbumCreateDialog - - Create Album - Δημιουργία άλμπουμ - - - Album Name: - Όνομα άλμπουμ: - - - Category: - Κατηγορία: - - - Animals - Ζώα - - - Family - Οικογένεια - - - Friends - Φίλοι - - - Flowers - Λουλούδια - - - Holiday - Διακοπές - - - Landscapes - Τοπία - - - Pets - Κατοικίδια ζώα - - - Portraits - Πορτρέτα - - - Travel - Ταξίδια - - - Work - Εργασία - - - Random - Τυχαία - - - Caption: - Λεζάντα: - - - Where: - Όπου: - - - Photographer: - Φωτογράφος: - - - Description: - Περιγραφή: - - - Share Options - Μοιρασμα ρυθμισεων - - - Policy: - Πολιτική: - - - Quality: - Ποιότητα: - - - Comments: - Σχόλια: - - - Identity: - Ταυτότητα: - - - Public - Δημοσια - - - Restricted - Περιορισμένη - - - Resize Images (< 1Mb) - Αλλαγή μεγέθους εικόνων (< 1Mb) - - - Resize Images (< 10Mb) - Αλλαγή μεγέθους εικόνων (< 10Mb) - - - Send Original Images - Αποστολή αυθεντικών εικόνων - - - No Comments Allowed - Δεν επιτρέπονται σχόλια - - - Authenticated Comments - Επικυρωμένα σχόλια - - - Any Comments Allowed - Επιτρέπονται όλα τα σχόλια - - - Publish with Identity - Δημοσίευση με ταυτότητα - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">⏎ -<html><head><meta name="qrichtext" content="1" /><style type="text/css">⏎ -p, li { white-space: pre-wrap; }⏎ -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">⏎ -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - - - Back - Πίσω - - - Add Photos - Προσθήκη φωτογραφιών - - - Publish Album - Δημοσίευση άλμπουμ - - - Untitle Album - Ατιτλο άλμπουμ - - - Say something about this album... - Πειτε κατι σχετικά με αυτό το άλμπουμ... - - - Where were these taken? - Πού τραβήχτηκαν αυτές; - - - Load Album Thumbnail - Φορτωση εικονιδιων του άλμπουμ - - AlbumDialog @@ -343,19 +165,11 @@ p, li { white-space: pre-wrap; }⏎ Album Άλμπουμ - - Album Thumbnail - Εικονιδια του άλμπουμ - TextLabel Ετικέτα Κειμένου - - Summary - Περίληψη - Album Title: @@ -371,34 +185,6 @@ p, li { white-space: pre-wrap; }⏎ Caption Λεζάντα - - Where: - Πού: - - - When - Πότε - - - Description: - Περιγραφή: - - - Share Options - Ρυθμίσεις Διαμοιρασμού - - - Comments - Σχόλια - - - Publish Identity - Δημοσιεύση ταυτότητας - - - Visibility - Ορατότητα - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -483,7 +269,7 @@ p, li { white-space: pre-wrap; }⏎ Where: - + Όπου: @@ -767,7 +553,7 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. Προειδοποίηση: Οι υπηρεσίες εδώ είναι πειραματικές. Βοηθήστε μας να τις δοκιμάσουμε. @@ -783,14 +569,6 @@ p, li { white-space: pre-wrap; } Circles Κύκλοι - - GxsForums - GxsForums - - - GxsChannels - GxsChannels - The Wire @@ -802,10 +580,23 @@ p, li { white-space: pre-wrap; } Φωτογραφίες + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb %p Kb @@ -842,17 +633,13 @@ p, li { white-space: pre-wrap; } Browse... - - Add Avatar - Προσθήκη Άβαταρ - Remove Μετακινηση - + Set your Avatar picture Ορισμός εικόνας Avatar @@ -871,10 +658,6 @@ p, li { white-space: pre-wrap; } Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - Μεταφόρτωση μικρογραφίας - AvatarWidget @@ -943,22 +726,10 @@ p, li { white-space: pre-wrap; } Επαναφορά - Receive Rate - Rate ελλειφθει - - - Send Rate - Αποστολη Rate - - - + Always on Top Παντα μπροστα - - Style - Στιλ - Changes the transparency of the Bandwidth Graph @@ -974,23 +745,11 @@ p, li { white-space: pre-wrap; } % Opaque % Αδιαφανεια - - Save - Αποθήκευση - - - Cancel - Διακοπη - Since: Από: - - Hide Settings - Απόκρυψη ρυθμίσεων - BandwidthStatsWidget @@ -1063,9 +822,9 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment - + Σχόλιο @@ -1093,12 +852,12 @@ p, li { white-space: pre-wrap; } - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -1106,7 +865,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up @@ -1126,7 +885,7 @@ p, li { white-space: pre-wrap; } \/ - + Posted by @@ -1164,7 +923,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up @@ -1184,7 +943,7 @@ p, li { white-space: pre-wrap; } \/ - + Click to view picture @@ -1214,7 +973,7 @@ p, li { white-space: pre-wrap; } - + Toggle Message Read Status Αναγνωση καταστασης της εναλλαγης μυνηματος @@ -1224,7 +983,7 @@ p, li { white-space: pre-wrap; } - + TextLabel @@ -1232,12 +991,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this Μου αρέσει - + 0 0 @@ -1257,18 +1016,18 @@ p, li { white-space: pre-wrap; } Εικονιδιο - + New Comment - + Copy RetroShare Link - + Expand @@ -1283,19 +1042,19 @@ p, li { white-space: pre-wrap; } - + Name - + Comm value Comment - + Σχόλιο @@ -1457,17 +1216,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels Κανάλια - + Tabs Καρτέλες - + General Γενικά @@ -1477,7 +1236,17 @@ p, li { white-space: pre-wrap; } - + + Downloads + Λήψεις + + + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab Άνοιγμα κάθε καναλιού σε νέα καρτέλα @@ -1485,7 +1254,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1508,7 +1277,7 @@ into the image, so as to ChannelsCommentsItem - + I like this Μου αρέσει @@ -1533,18 +1302,18 @@ into the image, so as to Εικονιδιο - + New Comment - + Copy RetroShare Link - + Expand @@ -1559,7 +1328,7 @@ into the image, so as to - + Name @@ -1569,17 +1338,7 @@ into the image, so as to - - Comment - - - - - Comments - - - - + Hide @@ -1587,7 +1346,7 @@ into the image, so as to ChatLobbyDialog - + Name @@ -1778,7 +1537,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby Εμφανιση του προθαλαμου συνομιλιων @@ -1790,22 +1549,6 @@ into the image, so as to Chats - - You have %1 new messages - Έχετε %1 νέα μηνύματα - - - You have %1 new message - Έχετε %1 νέο μήνυμα - - - %1 new messages - %1 νέα μηνύματα - - - %1 new message - %1 νέο μήνυμα - You have %1 mentions @@ -1827,13 +1570,14 @@ into the image, so as to - + + Unknown Lobby Άγνωστη Αίθουσα - - + + Remove All Αφαίρεση Όλων @@ -1841,13 +1585,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Όνομα - + Count Υπολογισμος @@ -1857,29 +1601,7 @@ into the image, so as to Θέμα - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - - - - - - Public chat rooms - - - - + Create chat room @@ -1889,7 +1611,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1946,12 +1668,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1961,31 +1683,31 @@ Double click a chat room to enter and chat. - Create chat lobby - Δημιουργια προθαλαμου συνομιλιων - - - + [No topic provided] [Δεν υπαρχει κανενα θεμα] - Selected lobby info - Πληροφοριες επιλεγμενου προθαλαμου συνομιλιων - - - + + Private Ιδιωτικα - + + + Public Δημοσια - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted @@ -1995,42 +1717,25 @@ Double click a chat room to enter and chat. - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe - + Search Chat lobbies Αναζήτηση στις Αίθουσες Συνομιλίας - + Search Name Ανζήτηση Ονόματος - Subscribed - Εγγεγραμμένος - - - + Columns Στήλες - - Yes - Ναι - - - No - Όχι - Chat rooms @@ -2042,47 +1747,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: Θέμα: - + Type: Τυπος: - + Security: Ασφάλεια: - + Peers: - - - - - - + + + + + + TextLabel Ετικετα κειμενου @@ -2097,13 +1802,24 @@ Double click a chat room to enter and chat. Δεν υπάρχουν ανώνυμες ταυτότητες - + Show Εμφάνιση - + + Private Subscribed + + + + + + Public Subscribed + + + + column στήλη @@ -2117,7 +1833,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item Απομακρυνση στοιχειου @@ -2162,7 +1878,7 @@ Double click a chat room to enter and chat. ChatPage - + General Γενικά @@ -2177,19 +1893,7 @@ Double click a chat room to enter and chat. - Chat Settings - Ρυθμισεις συνομιλιων - - - Enable Emoticons Private Chat - Ενεργοποίηση Emoticons Private Chat - - - Enable Emoticons Group Chat - Ενεργοποιηση της ομαδικης συνομιλιας με εικονιδια - - - + Enable custom fonts Ενεργοποίηση προσαρμοσμένων γραμματοσειρων @@ -2198,10 +1902,6 @@ Double click a chat room to enter and chat. Enable custom font size Ενεργοποίηση προσαρμοσμένου μέγεθους γραμματοσειρων - - Minimum font size - Ελάχιστο μέγεθος γραμματοσειράς - Enable bold @@ -2213,7 +1913,7 @@ Double click a chat room to enter and chat. Ενεργοποίηση πλάγιας γραφής - + General settings @@ -2238,11 +1938,7 @@ Double click a chat room to enter and chat. - Chat Lobby - Chat λόμπι - - - + Blink tab icon Αναβοσβήνει το εικονίδιο στηλοθέτη @@ -2251,10 +1947,6 @@ Double click a chat room to enter and chat. Do not send typing notifications - - Private Chat - Ιδιωτικη συνομιλια - Open Window for new chat @@ -2276,11 +1968,7 @@ Double click a chat room to enter and chat. Αναβοσβήνει το εικονίδιο παράθυρου/tab - Chat Font - Γραμματοσειρά συνομιλίας - - - + Change Chat Font Αλλαγή της γραμματοσειράς της συνομιλίας @@ -2290,14 +1978,10 @@ Double click a chat room to enter and chat. Γραμματοσειρά συνομιλίας: - + History Ιστορικό - - Style - Στιλ - @@ -2312,17 +1996,13 @@ Double click a chat room to enter and chat. Variant: - - Group chat - Ομαδική συνομιλία - Private chat Ιδιωτική συνομιλία - + Choose your default font for Chat. @@ -2392,12 +2072,22 @@ Double click a chat room to enter and chat. - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2407,7 +2097,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2454,7 +2154,7 @@ Double click a chat room to enter and chat. Description: - + Περιγραφη: @@ -2504,11 +2204,7 @@ Double click a chat room to enter and chat. Μέγιστη περίοδος αποθήκευσης, σε μέρες (0 = κράτα όλα) - Search by default - Προκαθορισμένη Αναζήτηση - - - + Case sensitive Διάκριση πεζών-κεφαλαίων @@ -2547,10 +2243,6 @@ Double click a chat room to enter and chat. Threshold for automatic search - - Default identity for chat lobbies: - Προκαθορισμένη ταυτότητα για της αίθουσες συνομιλίας: - Show Bar by default @@ -2618,7 +2310,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat Εμφάνιση συνομιλίας @@ -2654,7 +2346,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close Κλεισιμο @@ -2689,12 +2381,12 @@ Double click a chat room to enter and chat. Italic - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2774,11 +2466,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2816,7 +2503,7 @@ Double click a chat room to enter and chat. - + is typing... γράφει... @@ -2838,7 +2525,7 @@ after HTML conversion. - + Do you really want to physically delete the history? Θέλετε πραγματικά να διαγράψετε το ιστορικό; @@ -2888,7 +2575,7 @@ after HTML conversion. Είναι απασχολημένος και δεν μπορεί να απαντήσει - + Find Case Sensitively @@ -2910,7 +2597,7 @@ after HTML conversion. - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> <b>Εύρεση Προηγούμενου </b><br/><i>Ctrl+Shift+G</i> @@ -2925,16 +2612,12 @@ after HTML conversion. <b>Εύρεση</b><br/><i>Ctrl+F</i> - + (Status) (Κατάσταση) - Set text font & color - Καθορισμός γραμματοσειράς & χρώματος κειμένου - - - + Attach a File Επισύναψη αρχείου @@ -2950,12 +2633,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> <b>Επισήμανση επιλεγμένου κειμένου</b><br><i>Ctrl+M</i> - + Person id: @@ -2966,12 +2649,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. στοιχεία βρέθηκαν. @@ -2991,7 +2674,7 @@ Double click on it to add his name on text writer. Πληκτρολογείστε μήνυμα εδώ - + Don't stop to color after @@ -3017,7 +2700,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: Εμφάνιση λεπτομερειών: @@ -3039,7 +2722,7 @@ Double click on it to add his name on text writer. - + Personal Circles Προσωπικοί κύκλοι @@ -3065,7 +2748,7 @@ Double click on it to add his name on text writer. - + Friends Φίλοι @@ -3125,7 +2808,7 @@ Double click on it to add his name on text writer. Φίλοι φίλων - + External Circles (Admin) @@ -3141,7 +2824,7 @@ Double click on it to add his name on text writer. - + Circles Κύκλοι @@ -3193,40 +2876,40 @@ Double click on it to add his name on text writer. - + RetroShare RetroShare - + - + Error : cannot get peer details. Σφάλμα: οι peer λεπτομέρειες δεν μπορουν να παρθουν. - + Retroshare ID - + <p>This Retroshare ID contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: @@ -3236,7 +2919,7 @@ Double click on it to add his name on text writer. Κρυπτογράφηση - + Not connected Μη συνδεδεμένος @@ -3318,17 +3001,22 @@ Double click on it to add his name on text writer. κανένας - + <p>This certificate contains: <p>Αυτό το πιστοποιητικό περιλαμβάνει: - + <li>a <b>node ID</b> and <b>name</b> <li>η <b>ταυτότητα του κόμβου</b> και <b>όνομα</b> - + + <b>DNS:</b> : + + + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3348,7 +3036,7 @@ Double click on it to add his name on text writer. - + with με @@ -3365,104 +3053,16 @@ Double click on it to add his name on text writer. Connect Friend Wizard Συνδεση με τον οδηγο φιλου - - Add a new Friend - Προσθήκη νέου φίλου - - - &You get a certificate file from your friend - & Μπορείτε να πάρετε ένα αρχείο πιστοποιητικού από το φίλο σας - - - &Make friend with selected friends of my friends - &Δημιουργια φίλου με επιλεγμένους φίλους από τους φίλους μου - - - Include signatures - Περιλαμβάνουν υπογραφές - - - Copy your Cert to Clipboard - Αντιγράψετε σας Cert πρόχειρο - - - Save your Cert into a File - Αποθηκεύσετε Cert σας σε ένα αρχείο - - - Run Email program - Εκτελέστε το πρόγραμμα ηλεκτρονικού ταχυδρομείου - Open Cert of your friend from File - - Certificate files - Αρχεία πιστοποιητικού - - - Use PGP certificates saved in files. - Χρήση πιστοποιητικών PGP αποθηκευμένα σε αρχεία. - - - Import friend's certificate... - Εισαγωγή πιστοποιητικού φιλων... - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - Θα πρέπει να δημιουργήσετε ένα αρχείο με το πιστοποιητικό σας και να το δώσετε στο φίλο σας. Επίσης, μπορείτε να χρησιμοποιήσετε ένα αρχείο που δημιουργείται πριν. - - - Export my certificate... - Εξαγωγή του πιστοποιητικό μου... - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - Σύρετε και να ρίξει το πιστοποιητικό τους φίλους σας σε αυτό το παράθυρο ή να καθορίσετε τη διαδρομή στο παρακάτω πλαίσιο - - - Browse - Περιγραφη - - - Friends of friends - Φίλοι φίλων - - - Select now who you want to make friends with. - Τώρα επιλέξτε με ποιούς θέλετε να γίνεται φίλος/η. - - - Show me: - Δείξε μου: - - - Make friend with these peers - Γίνει φίλος με τους συμμαθητές αυτών - RetroShare ID RetroShare ID - - Use RetroShare ID for adding a Friend which is available in your network. - Χρήση RetroShare ID για την προσθήκη ενός φίλου που είναι διαθέσιμα στο δίκτυό σας. - - - Add Friends RetroShare ID... - Προσθηκη των RetroShare ID... - - - Paste Friends RetroShare ID in the box below - Επικόλληση τους φίλους eMule ομάδα + Ultra ID στο παρακάτω πλαίσιο - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - Εισαγάγετε το RetroShare ID του φίλου σας, π.χ. Peer@BDE8D16A46D938CF - RetroShare is better with Friends @@ -3504,27 +3104,7 @@ Double click on it to add his name on text writer. Email - Invite Friends by Email - Πρόσκληση φίλων μέ Email - - - Enter your friends' email addresses (separate each one with a semicolon) - Εισαγωγη email διευθύνσεων των φιλων σας (ξεχωριστά τον καθένα με ένα ερωτηματικό) - - - Your friends' email addresses: - Η Email διευθυνση των φιλων σας: - - - Enter Friends Email addresses - Εισαγετε τις Email διευθυνσεις φιλων - - - Subject: - Θέμα: - - - + @@ -3540,44 +3120,32 @@ Double click on it to add his name on text writer. Λεπτομέρειες σχετικά με το αίτημα - + Peer details Peer λεπτομέρειες - + Name: Όνομα: - - Email: - Email: - - - Node: - Κόμβος: - Location: Τοποθεσία: - + Options Επιλογές - Enter the certificate manually - Εισάγεται το πιστοποιητικό χειρονακτικός - - - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: Προσθηκη φίλου στην Ομάδα: @@ -3587,7 +3155,7 @@ Double click on it to add his name on text writer. Έλεγχος ταυτότητας φίλου (υπογραφη PGP κλειδίου) - + Please paste below your friend's Retroshare ID @@ -3612,16 +3180,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with Πρόσθηκη ως φίλο-για να συνδεθείτε με - To accept the Friend Request, click the Finish button. - Για να αποδεχθείε την αίτηση του φίλου, πατήστε το πλαισιο Τέλος. - - - + Sorry, some error appeared Συγγνώμη, εμφανίστηκς κάποιο σφαλμα @@ -3641,32 +3215,27 @@ Double click on it to add his name on text writer. Λεπτομέρειες σχετικά με τον φίλο σας: - + Key validity: Ισχύς κλειδιού: - + Profile ID: - - Signers - Υπογράφοντες - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. Αυτός ο ομότιμος είναι ήδη στην λιστα φιλων. Προσθέτοντας μπορεί να ρυθμιστεί μόνο η διεύθυνση ip. - + To accept the Friend Request, click the Accept button. @@ -3712,45 +3281,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed Η φορτωση του πιστοποιητικου απετυχε - Cannot get peer details of PGP key %1 - Οι peer λεπτομέρειες του κλειδιου PGP key %1 δεν μπορουν να παρθουν. - - - Any peer I've not signed - Κάθε φορέα που δεν έχω υπογράψει - - - Friends of my friends who already trust me - Φίλοι φίλων μου που με εμπιστευονται - - - Signed peers showing as denied - Υπεγράφη συμμαθητές δείχνει όπως αρνήθηκε - - - Peer name - Όνομα ομότιμης οντότητας - - - Also signed by - Επίσης υπεγράφη από - - - Peer id - Peer id - - - + Not a valid Retroshare certificate! - + RetroShare Invitation Πρόσκληση RetroShare @@ -3770,12 +3311,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3783,7 +3324,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3823,7 +3364,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Έχετε ένα αίτημα φίλιας από - + Profile password needed. @@ -3848,7 +3389,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3858,47 +3399,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - Certificate Load Failed:file %1 not found - Η φορτωση του πιστοποιητικου απετυχε: αρχείο %1 δεν βρέθηκε - - - This Peer %1 is not available in your Network - Αυτός ο ομότιμος %1 δεν είναι διαθέσιμος στο δίκτυό σας - - - Use new certificate format (safer, more robust) - Χρήση νέας μορφής πιστοποιητικού (ασφαλέστερη, πιο ισχυρή) - - - Use old (backward compatible) certificate format - Χρήση παλιάς μορφής πιστοποιητικού (συμβατή) - - - Remove signatures - Αφαιρέση υπογραφων - - - RetroShare Invite - Πρόσκληση RetroShare - - - Connect Friend Help - Βοήθεια συνδεσης με φίλο - - - You can copy this text and send it to your friend via email or some other way - Μπορείτε να αντιγράψετε το κείμενο και να το στείλετε σε φίλο σας μέσω email ή με κάποιο άλλον τρόπο - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Σας Cert αντιγράφεται στο Πρόχειρο, πάστα και να το στείλετε στο φίλο σας μέσω email ή κάποιο άλλο τρόπο - - - Save as... - Αποθηκευση ως... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3937,11 +3438,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.*** Κανένας *** - Use as direct source, when available - Use as direct source, when available - - - + IP-Addr: @@ -3951,7 +3448,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Διεύθυνση IP - + Show Advanced options @@ -3970,33 +3467,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> - - Friend Recommendations - Συστάσεις Φίλων - - - Message: - Μήνυμα: - - - Recommend friends - Προτείνετε φίλους - - - To - Προς - - - Please select at least one friend as recipient. - Παρακαλώ επιλέξτε τουλάχιστον ένα φίλο ως παραλήπτη. - Add key to keyring - + This key is already in your keyring @@ -4009,7 +3486,7 @@ even if you don't make friends. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. @@ -4044,7 +3521,7 @@ even if you don't make friends. Πρόσθεση του IP στην λίστα αποδοχής - + No IP in this certificate! @@ -4054,12 +3531,7 @@ even if you don't make friends. - - [Unknown] - [Άγνωστο] - - - + Added with certificate from %1 @@ -4124,7 +3596,7 @@ even if you don't make friends. - + UDP Setup @@ -4152,7 +3624,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant @@ -4162,17 +3634,20 @@ p, li { white-space: pre-wrap; } - + + Unknown State Άγνωστη Κατάσταση - + + Offline Χωρίς σύνδεση - + + Behind Symmetric NAT @@ -4182,12 +3657,14 @@ p, li { white-space: pre-wrap; } - + + NET Restart - + + Behind NAT @@ -4197,7 +3674,8 @@ p, li { white-space: pre-wrap; } - + + NET STATE GOOD! @@ -4222,7 +3700,7 @@ p, li { white-space: pre-wrap; } - + Lookup requires DHT @@ -4514,7 +3992,7 @@ p, li { white-space: pre-wrap; } - + @@ -4522,7 +4000,8 @@ p, li { white-space: pre-wrap; } N/A - + + UNVERIFIABLE FORWARD! @@ -4532,7 +4011,7 @@ p, li { white-space: pre-wrap; } - + Searching Γίνεται αναζήτηση @@ -4568,12 +4047,12 @@ p, li { white-space: pre-wrap; } Λεπτομέρειες κύκλου - + Name Όνομα - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4593,7 +4072,7 @@ p, li { white-space: pre-wrap; } - + IDs Ταυτότητες @@ -4613,18 +4092,18 @@ p, li { white-space: pre-wrap; } Φίλτρο - + Cancel - + Nickname Ψευδώνυμο - + Invited Members @@ -4639,15 +4118,7 @@ p, li { white-space: pre-wrap; } - ID - ID - - - Type - Τυπος - - - + Name: @@ -4687,19 +4158,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - + Please set a name for your Circle Ορίστε ένα όνομα για τον κύκλο σας - + No Restriction Circle Selected Κανένας περιορισμός κύκλου εχει επιλέγθει @@ -4709,12 +4180,24 @@ p, li { white-space: pre-wrap; } Δεν υπάρχουν περιορισμοί επιλεγμένου Κύκλου - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] [Άγνωστο] - + Add Προσθηκη @@ -4724,7 +4207,7 @@ p, li { white-space: pre-wrap; } Αφαίρεση - + Search Αναζητηση @@ -4777,13 +4260,13 @@ p, li { white-space: pre-wrap; } - + Create - + Add Member @@ -4802,7 +4285,7 @@ p, li { white-space: pre-wrap; } Δημιουργια μιας ομαδας - + Group Name: Όνομα ομάδας: @@ -4837,7 +4320,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post Νεο ποσταρισμα στο καναλι @@ -4847,7 +4330,7 @@ p, li { white-space: pre-wrap; } Ποσταρισμα στο καναλι - + Post @@ -4908,23 +4391,11 @@ p, li { white-space: pre-wrap; }⏎ <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Use Drag and Drop / Add Files button, to Hash new files.</span></p>⏎ <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Copy/Paste RetroShare links from your shares</span></p></body></html> - - Add File to Attach - Προσθηκη αρχειου προς επισύναψη - Add Channel Thumbnail Προσθηκη εικονιδιου του καναλιού - - Message - Μυνημα - - - Subject : - Θέμα: - @@ -5010,17 +4481,17 @@ p, li { white-space: pre-wrap; }⏎ - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -5039,17 +4510,18 @@ p, li { white-space: pre-wrap; }⏎ The following files will only be shared for 30 days. Think about adding them to a shared directory. - - File already Added and Hashed - Το αρχείο εχει προσθέθει και κατακερματίζεται - Please add a Subject Παρακαλείσθε να προσθέσετε ένα θέμα - + + Cannot publish post + + + + Load thumbnail picture Φορτωση εικονιδιου εικονας @@ -5064,18 +4536,12 @@ p, li { white-space: pre-wrap; }⏎ - - + Generate mass data - - Do you really want to generate %1 messages ? - - - - + You are about to add files you're not actually sharing. Do you still want this to happen? Είστε έτοιμοι να προσθέσετε τα αρχεία που στην πραγματικότητα δεν μοιράζεστε. Είστε βέβαιοι ότι θέλετε να συμβεί αυτό; @@ -5109,7 +4575,7 @@ p, li { white-space: pre-wrap; }⏎ CreateGxsForumMsg - + Post Forum Message Ποσταρισμα μυνηματος στο φορουμ @@ -5118,10 +4584,6 @@ p, li { white-space: pre-wrap; }⏎ Forum Φορουμ - - Subject - Θέμα: - Attach File @@ -5142,8 +4604,8 @@ p, li { white-space: pre-wrap; }⏎ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -5162,7 +4624,7 @@ p, li { white-space: pre-wrap; } Μπορείτε να επισυνάψετε αρχεία μέσω drag and drop σε αυτό το παράθυρο - + Post @@ -5192,17 +4654,17 @@ p, li { white-space: pre-wrap; } - + No Forum Κανενα φόρουμ - + In Reply to Απάντηση στον - + Title Τίτλος @@ -5255,7 +4717,7 @@ Do you want to discard this message? Φορτωση αρχειου εικονας - + No compatible ID for this forum @@ -5265,8 +4727,8 @@ Do you want to discard this message? - - + + Generate mass data @@ -5275,10 +4737,6 @@ Do you want to discard this message? Do you really want to generate %1 messages ? - - Send - Αποστολη - Post as @@ -5293,23 +4751,7 @@ Do you want to discard this message? CreateLobbyDialog - Create Chat Lobby - Δημιουργια προθαλαμου συνομιλιων - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - Ένα chat λόμπι είναι μια αποκεντρωμένη και ανώνυμη συνομιλία ομάδας. Όλοι οι συμμετέχοντες δέχονται όλα τα μηνύματα. Αφού δημιουργηθεί το λόμπι μπορείτε να προσκαλέσετε άλλους φίλους από την καρτέλα "φίλοι". - - - Lobby name: - Ονομα προθαλαμου: - - - Lobby topic: - Θεμα προθαλαμου: - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5344,7 +4786,7 @@ Do you want to discard this message? - + Create @@ -5354,7 +4796,7 @@ Do you want to discard this message? - + require PGP-signed identities @@ -5369,11 +4811,7 @@ Do you want to discard this message? Επιλέξτε τους φίλους με τους οποιους θέλετε να κανετε μια ομαδική συζήτηση. - Invited friends - Προσκληση φιλων - - - + Create Chat Room @@ -5394,7 +4832,7 @@ Do you want to discard this message? Επαφες: - + Identity to use: @@ -5402,17 +4840,17 @@ Do you want to discard this message? CryptoPage - + Public Information Δημοσιες πληροφοριες - + Name: Ονομα: - + Location: Τοπος: @@ -5422,12 +4860,12 @@ Do you want to discard this message? ID Τοπου: - + Software Version: Έκδοση λογισμικού: - + Online since: Online από: @@ -5447,12 +4885,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5462,7 +4895,7 @@ Do you want to discard this message? - + Other Information Άλλες πληροφορίες @@ -5472,17 +4905,12 @@ Do you want to discard this message? - + Profile - - Certificate - Πιστοποιητικό - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5492,11 +4920,7 @@ Do you want to discard this message? Περιλαμβάνουν υπογραφές - Save Key into a file - Αποθηκεύστε το κλειδί σε ένα αρχείο - - - + Export Identity Εξαγωγή ταυτότητας @@ -5566,33 +4990,33 @@ and use the import button to load it - + TextLabel Ετικετα κειμενου - + PGP fingerprint: - - Node information - - - - + PGP Id : - + Friend nodes: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5682,7 +5106,7 @@ and use the import button to load it DLListDelegate - + B Β @@ -6350,7 +5774,7 @@ and use the import button to load it DownloadToaster - + Start file Έναρξη αρχείου @@ -6358,38 +5782,38 @@ and use the import button to load it ExprParamElement - + - + to να - + ignore case ανεξαρτήτως πεζών - - - dd.MM.yyyy - ΑΔ.MM.yyyy + + + yyyy-MM-dd + - - + + KB KB - - + + MB MB - - + + GB GB @@ -6397,12 +5821,12 @@ and use the import button to load it ExpressionWidget - + Expression Widget Έκφραση Widget - + Delete this expression Διαγράφη αυτής της έκφρασης @@ -6564,7 +5988,7 @@ and use the import button to load it FilesDefs - + Picture Εικονα @@ -6574,7 +5998,7 @@ and use the import button to load it Βιντεο - + Audio Ήχος @@ -6634,11 +6058,21 @@ and use the import button to load it C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Καταλογοι φιλων @@ -6760,7 +6194,7 @@ and use the import button to load it - + ID ID @@ -6802,7 +6236,7 @@ and use the import button to load it Εμφάνιση ομάδων - + Group Ομάδα @@ -6838,7 +6272,7 @@ and use the import button to load it Προσθηκη σε ομαδα - + Search Αναζήτηση @@ -6854,7 +6288,7 @@ and use the import button to load it - + Profile details @@ -7067,7 +6501,7 @@ at least one peer was not added to a group To - + Στον @@ -7093,7 +6527,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request Επιβεβαίωση αίτημα φίλου @@ -7110,10 +6544,6 @@ at least one peer was not added to a group FriendSelectionWidget - - Search : - Αναζητηση : - Sort by state @@ -7135,7 +6565,7 @@ at least one peer was not added to a group Αναζήτηση φίλων - + Mark all Επισημάνση όλων @@ -7146,16 +6576,132 @@ at least one peer was not added to a group + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + + + + + Node ID + + + + + Address + + + + + Status + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + Δημιουργια φιλου + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message Επεξεργασια μήνυματος κατάστασης - - + + Broadcast Ραδιοφωνική μετάδοση @@ -7238,33 +6784,38 @@ at least one peer was not added to a group Επαναφορα της προεπιλεγμενης γραμματοσειρας - + Keyring - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. - - + + Network Δίκτυο - + + Friend Server + + + + Network graph - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. @@ -7282,7 +6833,17 @@ at least one peer was not added to a group Κωδικος - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters Τα πεδία είναι υποχρεωτικά με τουλάχιστον 3 χαρακτήρες @@ -7292,17 +6853,12 @@ at least one peer was not added to a group - + Port Υποδοχη - - Use BOB - - - - + This password is for PGP @@ -7323,38 +6879,38 @@ at least one peer was not added to a group - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -7374,12 +6930,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -7389,38 +6945,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel - + hidden address - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -7464,13 +7025,13 @@ and use the import button to load it - + Import profile - + Create new profile and new Retroshare node @@ -7480,7 +7041,7 @@ and use the import button to load it - + Tor/I2P address @@ -7515,7 +7076,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7525,12 +7086,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -7540,12 +7096,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7771,36 +7322,13 @@ and use the import button to load it Ξεκινώντας - + Invite Friends Προσκληση φιλων - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">⏎ -<html><head><meta name="qrichtext" content="1" /><style type="text/css">⏎ -p, li { white-space: pre-wrap; }⏎ -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">⏎ -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p>⏎ -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p>⏎ -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p>⏎ -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p>⏎ -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> - - - - + Add Your Friends to RetroShare Προσθεστε του φιλους σας στο RetroShare @@ -7810,89 +7338,103 @@ p, li { white-space: pre-wrap; }⏎ Προσθηκη φιλων - + + Connect To Friends + Συνδεθείτε με τους φίλους + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Για προχωρημένους: Ανοιγμα της υποδοχης του Firewall + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - Συνδεθείτε με τους φίλους - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - Για προχωρημένους: Ανοιγμα της υποδοχης του Firewall - - - + Further Help and Support Περαιτέρω βοήθεια και υποστήριξη - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website Ανοιγμα της RS Ιστοσελιδας @@ -7917,7 +7459,7 @@ p, li { white-space: pre-wrap; } Email ανατροφοδότηση - + RetroShare Invitation RetroShare Προσκληση @@ -7967,12 +7509,12 @@ p, li { white-space: pre-wrap; } RetroShare ανατροφοδότηση - + RetroShare Support Υποστηριξη RetroShare - + It has many features, including built-in chat, messaging, @@ -8096,7 +7638,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat Εμφάνιση ομαδικής συνομιλίας @@ -8104,7 +7646,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] [Άγνωστο] @@ -8274,7 +7816,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title Τίτλος @@ -8287,12 +7829,12 @@ p, li { white-space: pre-wrap; } - + Description Περιγραφή - + Number of Unread message @@ -8317,19 +7859,7 @@ p, li { white-space: pre-wrap; } - Sort by Name - Ταξινόμηση κατά όνομα - - - Sort by Popularity - Ταξινόμηση κατά δημοτικότητα - - - Sort by Last Post - Ταξινόμηση κατά το τελευταιο ποσταρισμα - - - + You are admin (modify names and description using Edit menu) @@ -8344,14 +7874,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post - + Τελευταία Δημοσίευση - + Name @@ -8362,17 +7892,13 @@ p, li { white-space: pre-wrap; } Δημοτικότητα - + Never - Display - Εμφάνιση - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8385,7 +7911,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and και @@ -8521,7 +8047,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels Κανάλια @@ -8532,22 +8058,22 @@ p, li { white-space: pre-wrap; } Δημιουργία καναλιού - + Enable Auto-Download Ενεργοποίηση αυτόματης λήψης - + My Channels Τα κανάλια μου - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Εγγεγραμμένα Κανάλια @@ -8567,12 +8093,12 @@ p, li { white-space: pre-wrap; } - + Disable Auto-Download Απενεργοποίηση της αυτόματης λήψης - + Set download directory @@ -8607,22 +8133,22 @@ p, li { white-space: pre-wrap; } - + Play Παιξιμο - + Open folder Άνοιγμα φακέλου - + Open file - + Error Σφαλμα @@ -8642,17 +8168,17 @@ p, li { white-space: pre-wrap; } - + Are you sure that you want to cancel and delete the file? Είστε βέβαιοι ότι θέλετε να ακυρώσετε και να διαγράψετε το αρχείο; - + Can't open folder Ο φάκελος δεν ανοίγει - + Play File Αναπαραγωγή αρχείου @@ -8662,37 +8188,10 @@ p, li { white-space: pre-wrap; } Το αρχείο %1 δεν υπάρχει στην τοποθεσία. - - GxsChannelFilesWidget - - Form - Φόρμα - - - Filename - Όνομα αρχείου - - - Size - Μέγεθος - - - Title - Τίτλος - - - Published - Δημοσιεύτηκε - - - Status - Κατάσταση - - GxsChannelGroupDialog - + Create New Channel Δημιουργία Νέου Καναλιού @@ -8730,9 +8229,19 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - Εγγραφή στο Κανάλι + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel + @@ -8746,7 +8255,7 @@ p, li { white-space: pre-wrap; } - + Expand Επέκταση @@ -8761,7 +8270,7 @@ p, li { white-space: pre-wrap; } Περιγραφή Καναλιού - + Loading Φορτωση @@ -8776,8 +8285,9 @@ p, li { white-space: pre-wrap; } - New Channel - Νέο Κανάλι + + Never + @@ -8788,7 +8298,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: @@ -8809,7 +8319,7 @@ p, li { white-space: pre-wrap; } - + Play Παιξιμο @@ -8865,28 +8375,24 @@ p, li { white-space: pre-wrap; } Files Αρχεία - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - Προειδοποίηση! Έχετε λιγότερο από ό, τι ώρες %1 και το %2 λεπτά πριν από αυτό το αρχείο έχει διαγραφεί θεωρούν αποθηκεύοντάς. - Hide Απόκρυψη - + New Νέο - + 0 0 - - + + Comment Σχόλιο @@ -8901,21 +8407,17 @@ p, li { white-space: pre-wrap; } Δεν μου αρέσει - Loading - Φορτωση - - - + Loading... - + Comments - + Post @@ -8940,83 +8442,16 @@ p, li { white-space: pre-wrap; } Παιξιμο πολυμεσων - - GxsChannelPostsWidget - - Post to Channel - Ποσταρισμα στο καναλι - - - Loading - Φορτωση - - - Search channels - Αναζήτηση καναλιών - - - Title - Τίτλος - - - Search Title - Αναζήτηση τίτλου - - - Message - Μήνυμα - - - Search Message - Αναζήτηση Μηνύματος - - - Filename - Όνομα αρχείου - - - Search Filename - Αναζήτηση Ονόματος Αρχείου - - - No Channel Selected - Δεν υπάρχει επιλεγμένο κανάλι - - - Disable Auto-Download - Απενεργοποίηση αυτόματης λήψης - - - Enable Auto-Download - Ενεργοποίηση αυτόματης λήψης - - - Show files - Εμφάνιση αρχείων - - - Feeds - Feeds - - - Files - Αρχεία - - - Description: - Περιγραφή: - - GxsChannelPostsWidgetWithModel - + Post to Channel Ποσταρισμα στο καναλι - + Add new post @@ -9086,7 +8521,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -9122,7 +8557,7 @@ p, li { white-space: pre-wrap; } - + Comments @@ -9137,13 +8572,13 @@ p, li { white-space: pre-wrap; } Feeds - - + + Click to switch to list view - + Show unread posts only @@ -9158,7 +8593,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -9173,7 +8608,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -9233,12 +8668,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -9313,12 +8758,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed Εγγεγραμμένος @@ -9350,7 +8796,7 @@ p, li { white-space: pre-wrap; } Disable Auto-Download - + Απενεργοποίηση της αυτόματης λήψης @@ -9369,17 +8815,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -9494,7 +8940,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container Σχόλιο @@ -9507,7 +8953,7 @@ p, li { white-space: pre-wrap; } Φόρμα - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9537,7 +8983,7 @@ p, li { white-space: pre-wrap; } Ανανέωση - + Comment Σχόλιο @@ -9576,7 +9022,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment Απάντηση στο σχόλιο @@ -9600,6 +9046,21 @@ p, li { white-space: pre-wrap; } Vote Down Ψηφίστε κάτω + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9609,7 +9070,7 @@ p, li { white-space: pre-wrap; } Δημιουργια σχολιου - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9638,26 +9099,10 @@ p, li { white-space: pre-wrap; } - + Post - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">⏎ -<html><head><meta name="qrichtext" content="1" /><style type="text/css">⏎ -p, li { white-space: pre-wrap; }⏎ -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">⏎ -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - - - Signed by - Υπογράφεται από - Reply to Comment @@ -9685,7 +9130,7 @@ before you can comment Πρέπει να δημιουργήσετε μια ταυτότητα για να μπορείτε να σχολιάσετε - + It remains %1 characters after HTML conversion. @@ -9736,7 +9181,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum Εγγραφείτε στο φόρουμ @@ -9752,7 +9197,7 @@ before you can comment - + Expand Επεκταση @@ -9772,8 +9217,9 @@ before you can comment - Loading - Φορτωση + + TextLabel + @@ -9804,13 +9250,13 @@ before you can comment GxsForumMsgItem - - + + Subject: Θέμα: - + Unsubscribe To Forum Διαγραφείτε από το φόρουμ @@ -9821,7 +9267,7 @@ before you can comment - + Expand Επεκταση @@ -9841,21 +9287,17 @@ before you can comment - Loading - Φορτωση - - - + Loading... - + Forum Feed - + Hide Απόκρυψη @@ -9868,63 +9310,66 @@ before you can comment Φόρμα - + Start new Thread for Selected Forum Έναρξη νέας μηνυματοσειράς στο επιλεγμενο φόρουμ - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Αναζήτηση στα φόρουμ - Last Post - Τελευταιο ποστ - - - + New Thread Νέο θεμα - - - Threaded View - Περασμένη κλωστή άποψη - - - - Flat View - Επίπεδη προβολή - - + Title Τίτλος - - + + Date Ημερομηνία - + Author Δημιουργος - - Save image - - - - + Loading Φορτωση - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9934,12 +9379,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message Μήνυμα απάντησης @@ -9963,10 +9403,6 @@ before you can comment Download all files Λήψη όλων των αρχείων - - Next unread - Επόμενο μη αναγνωσμένο - Search Title @@ -9983,31 +9419,23 @@ before you can comment Αναζήτηση συγγραφέα - Content - Περιεχόμενο - - - Search Content - Αναζήτηση περιεχομένου - - - + No name Δεν υπάρχει όνομα - - + + Reply Απάντηση - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -10050,16 +9478,12 @@ before you can comment Αντιγραφη του Λινκ - + Hide Απόκρυψη - Expand - Επεκταση - - - + [unknown] @@ -10089,8 +9513,8 @@ before you can comment - - + + Distribution @@ -10104,22 +9528,6 @@ before you can comment Anti-spam - - Anonymous - Ανώνυμος - - - signed - υπέγραψε - - - none - κανένας - - - [ ... Missing Message ... ] - [ ... Λείπει ενα μήνυμα...] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10189,12 +9597,12 @@ before you can comment Αρχικό μήνυμα - + New thread - + Edit Επεξεργασία @@ -10255,7 +9663,7 @@ before you can comment - + Show column @@ -10275,7 +9683,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive @@ -10327,7 +9735,7 @@ This message is missing. You should receive it later. - + No result. @@ -10337,7 +9745,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -10352,7 +9760,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -10418,12 +9826,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums Φόρουμ @@ -10454,35 +9862,16 @@ This message is missing. You should receive it later. Άλλα φόρουμ - - GxsForumsFillThread - - Waiting - Αναμονή - - - Retrieving - Ανάκτηση - - - Loading - Φορτωση - - GxsGroupDialog - + Name Όνομα - Add Icon - Προσθήκη εικονίδιου - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels Οι βασικοι αποδέκτες μπορουν να δημοσιεύουν σε περιορίσμενοι ομαδα και μπορουν να βλεπουν και να δημοσιεύουν ιδιωτικόυ ΤΥΠΟΥ καναλια @@ -10491,22 +9880,14 @@ This message is missing. You should receive it later. Share Publish Key Μοιρασμα δημοσιου κλειδίου - - check peers you would like to share private publish key with - Ελέγξτε τους ομοτυμους που θα θέλατε να μοιραστείτε το ιδιωτικο σας κλειδι δημοσιευσης - - - Share Key With - Μοιρασμα κλειδιου με - - + Description Περιγραφή - + Message Distribution Μήνυμα διανομής @@ -10514,7 +9895,7 @@ This message is missing. You should receive it later. - + Public Δημοσια @@ -10533,14 +9914,6 @@ This message is missing. You should receive it later. New Thread Νέο θεμα - - Required - Απαιτείται - - - Encrypted Msgs - Κρυπτογραφημένα μηνύματα - Personal Signatures @@ -10582,7 +9955,7 @@ This message is missing. You should receive it later. - + Comments: Σχόλια: @@ -10605,7 +9978,7 @@ This message is missing. You should receive it later. - + All People @@ -10621,12 +9994,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -10643,23 +10016,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -10675,22 +10048,28 @@ This message is missing. You should receive it later. Προσθέστε ένα όνομα - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo Λογότυπο ομάδας φόρτωσης - + Submit Group Changes - + Owner: @@ -10700,12 +10079,12 @@ This message is missing. You should receive it later. - + Info Πληροφορίες - + ID ID @@ -10715,7 +10094,7 @@ This message is missing. You should receive it later. Τελευταία Δημοσίευση - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -10790,7 +10169,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity Δημοτικότητα @@ -10806,27 +10190,22 @@ This message is missing. You should receive it later. - + Created - + Cancel - + Create - - Author - Δημιουργος - - - + GxsIdLabel GxsIdLabel @@ -10834,7 +10213,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading Φορτωση @@ -10894,7 +10273,7 @@ This message is missing. You should receive it later. Επεξεργασία Λεπτομερειών - + Synchronise posts of last... @@ -10951,12 +10330,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link Αντιγραφή του RetroShare Συνδέσμου @@ -10979,7 +10358,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature Καμία υπογραφή @@ -10992,22 +10371,14 @@ This message is missing. You should receive it later. GxsIdDetails - Loading - Φορτωση - - - + Not found Δεν βρέθηκε - - No Signature - Καμία υπογραφή - - - + + [Banned] @@ -11017,7 +10388,7 @@ This message is missing. You should receive it later. - + Loading... @@ -11027,7 +10398,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -11047,6 +10423,14 @@ This message is missing. You should receive it later. [Άγνωστο] + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -11058,7 +10442,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -11106,17 +10490,13 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] [Άγνωστο] GxsMessageFramePostWidget - - Loading - Φορτωση - Loading... @@ -11497,7 +10877,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -11513,7 +10893,7 @@ p, li { white-space: pre-wrap; } - + Authors Δημιουργοι @@ -11532,7 +10912,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -11612,7 +10992,7 @@ p, li { white-space: pre-wrap; }⏎ - + Add friend @@ -11622,7 +11002,7 @@ p, li { white-space: pre-wrap; }⏎ - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -11650,7 +11030,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -11660,7 +11040,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard Αντιγράψετε σας Cert πρόχειρο @@ -11670,7 +11050,7 @@ private and secure decentralized communication platform. Αποθηκεύσετε Cert σας σε ένα αρχείο - + Send via Email @@ -11690,13 +11070,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -11708,12 +11112,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -11728,12 +11132,7 @@ new short format Πρόσκληση RetroShare - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... @@ -11998,14 +11397,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Όλα - + Reputation Φήμη @@ -12015,12 +11414,12 @@ p, li { white-space: pre-wrap; } Αναζητηση - + Anonymous Id - + Create new Identity Δημιουργια νέας ταυτότητας @@ -12030,7 +11429,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -12045,27 +11444,27 @@ p, li { white-space: pre-wrap; } - + Close Κλεισιμο - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -12081,29 +11480,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles Κύκλοι - + Circle name @@ -12123,18 +11532,20 @@ p, li { white-space: pre-wrap; } Προσωπικοί κύκλοι - + + Edit identity Επεξεργασία Ταυτότητας - + + Delete identity Διαγραφή Ταυτότητας - + Chat with this peer @@ -12144,78 +11555,78 @@ p, li { white-space: pre-wrap; } - + Owner node ID : - + Identity name : - + () - + Identity ID - + Send message Αποστολή μηνύματος - + Identity info - + Identity ID : - + Owner node name : - + Create new... - + Type: Τυπος: - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: Η άποψή σας: - + Negative Αρνητικό - + Neutral @@ -12226,17 +11637,17 @@ p, li { white-space: pre-wrap; } Θετικό - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous Ανώνυμος @@ -12251,24 +11662,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you - - + + My own identities - - + + My contacts - + Show Items @@ -12283,7 +11694,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -12293,7 +11709,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -12368,7 +11784,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -12398,7 +11814,7 @@ p, li { white-space: pre-wrap; } Άγνωστο - + Invited @@ -12413,7 +11829,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle @@ -12461,7 +11877,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -12469,7 +11885,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -12512,7 +11928,7 @@ These identities will soon be not supported anymore. - + Boards @@ -12592,7 +12008,7 @@ These identities will soon be not supported anymore. - + information @@ -12608,17 +12024,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -12723,7 +12134,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -12773,21 +12184,21 @@ These identities will soon be not supported anymore. - - - + + + People - + Your Avatar Click here to change your avatar Το άβατάρ σας - + Linked to neighbor nodes @@ -12797,7 +12208,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -12812,7 +12223,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -12827,12 +12238,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -12852,12 +12263,12 @@ These identities will soon be not supported anymore. - + Owned by - + Node name: @@ -12867,7 +12278,7 @@ These identities will soon be not supported anymore. - + Really delete? @@ -12875,7 +12286,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname Ψευδώνυμο @@ -12905,7 +12316,13 @@ These identities will soon be not supported anymore. Ψευδώνυμο - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity Νέα ταυτότητα @@ -12919,7 +12336,7 @@ These identities will soon be not supported anymore. - + @@ -12929,7 +12346,12 @@ These identities will soon be not supported anymore. N/A - + + No avatar chosen + + + + Edit identity Επεξεργασία Ταυτότητας @@ -12940,27 +12362,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -12980,7 +12402,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -12990,12 +12412,18 @@ These identities will soon be not supported anymore. - + Error KeyID invalid - + + + No Avatar chosen. A default image will be automatically displayed from your new identity. + + + + Import image @@ -13005,12 +12433,7 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. - - - - + Unknown GpgId @@ -13020,7 +12443,7 @@ These identities will soon be not supported anymore. - + Create New Identity @@ -13030,10 +12453,15 @@ These identities will soon be not supported anymore. Τυπος - + Choose image... + + + Remove + Μετακινηση + @@ -13059,7 +12487,7 @@ These identities will soon be not supported anymore. Προσθηκη - + Create @@ -13069,13 +12497,13 @@ These identities will soon be not supported anymore. - + Your Avatar Click here to change your avatar Το άβατάρ σας - + Linked to your profile @@ -13085,7 +12513,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -13159,7 +12587,7 @@ These identities will soon be not supported anymore. - + Copy Αντίγραφη @@ -13169,12 +12597,12 @@ These identities will soon be not supported anymore. Μετακινηση - + %1 's Message History - + Mark all Επισημάνση όλων @@ -13193,26 +12621,38 @@ These identities will soon be not supported anymore. Quote Απόσπασμα - - Send - Αποστολη - ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -13230,27 +12670,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: Υποδοχη: - + Listen Address: - + + Status: + Κατασταση: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -13271,7 +12716,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -13280,26 +12730,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File Άνοιγμα αρχείου - + Open Folder Άνοιγμα φακέλου - + Checking... Έλεγχος... @@ -13309,7 +12764,7 @@ These identities will soon be not supported anymore. Ελέγχος αρχειων - + Recommend in a message to... @@ -13337,7 +12792,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend Προσθήκη φίλου @@ -13353,7 +12808,8 @@ These identities will soon be not supported anymore. - + + Options Επιλογές @@ -13374,7 +12830,7 @@ These identities will soon be not supported anymore. - + Quit Αποχωρηση @@ -13385,12 +12841,12 @@ These identities will soon be not supported anymore. Οδηγός γρήγορης έναρξης - + RetroShare %1 a secure decentralized communication platform Το RetroShare %1 ειναι μια πλατφόρμα ασφαλούς αποκεντρωμένης επικοινωνίας - + Unfinished Ημιτελής @@ -13419,11 +12875,12 @@ These identities will soon be not supported anymore. + Status Κατασταση - + Notify Κοινοποιηση @@ -13434,31 +12891,35 @@ These identities will soon be not supported anymore. + Open Messages Ανοιγμα μυνηματων - + + Bandwidth Graph Διάγραμμα εύρους ζώνης - + Applications Εφαρμογές + Help Βοήθεια - + + Minimize Ελαχιστοποίηση - + Maximize Μεγιστοποίηση @@ -13473,7 +12934,12 @@ These identities will soon be not supported anymore. RetroShare - + + Close window + + + + %1 new message νέο μήνυμα %1 @@ -13503,7 +12969,7 @@ These identities will soon be not supported anymore. %1 φίλοι που συνδέονται - + Do you really want to exit RetroShare ? Θέλετε πραγματικά να αποχωρησετε απο το RetroShare ? @@ -13523,7 +12989,7 @@ These identities will soon be not supported anymore. Εμφανιση - + Make sure this link has not been forged to drag you to a malicious website. Βεβαιωθείτε ότι αυτή η σύνδεση δεν σφυρηλατήθηκε για να σας σύρει σε μια κακόβουλη ιστοσελίδα. @@ -13568,12 +13034,13 @@ These identities will soon be not supported anymore. - + + Statistics Στατιστικές - + Show web interface @@ -13588,7 +13055,7 @@ These identities will soon be not supported anymore. - + Really quit ? @@ -13597,17 +13064,17 @@ These identities will soon be not supported anymore. MessageComposer - + Compose Συνθέση - + Contacts Επαφές - + Paragraph Παράγραφος @@ -13643,12 +13110,12 @@ These identities will soon be not supported anymore. Επικεφαλιδα 6 - + Font size Μέγεθος γραμματοσειράς - + Increase font size Αύξηση μεγέθους γραμματοσειράς @@ -13663,32 +13130,32 @@ These identities will soon be not supported anymore. Bold - + Italic Italic - + Alignment Ευθυγράμμιση - + Add an Image Προσθέστε μια εικόνα - + Sets text font to code style Ορίζει κώδικα στυλ γραμματοσειράς κειμένου - + Underline Υπογράμμιση - + Subject: Θέμα: @@ -13699,32 +13166,32 @@ These identities will soon be not supported anymore. - + Tags Ετικέτες - + Address list: - + Recommend this friend - + Set Text color Καθορίστε το χρώμα του κειμένου - + Set Text background color - + Recommended Files Συνιστάμενα αρχεία @@ -13794,7 +13261,7 @@ These identities will soon be not supported anymore. Προσθέστε Blockquote - + Send To: Αποστολή σε: @@ -13834,7 +13301,7 @@ These identities will soon be not supported anymore. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> Γεια σας, <br>θα ήθελα να σαςσυστήσω ένα καλό φίλο μου, μπορείτε να τον εμπιστευθείτε πάρα πολύ όταν μπορείτε και με εμπιστεύεσται. <br> @@ -13854,18 +13321,18 @@ These identities will soon be not supported anymore. θέλει να είναι φίλος μαζί σας στο RetroShare - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team Γεια σου % 1, <br><br>%2 θέλει να είναι φίλοι μαζί σας σχετικά στο RetroShare.<br><br>Απάντηση τώρα: <br>%3 <br><br>ευχαριστώ, <br>η ομάδα του RetroShare - - + + Save Message Αποθηκεύση μυνηματος - + Message has not been Sent. Do you want to save message to draft box? Μήνυμα δεν έχει σταλεί. @@ -13877,7 +13344,17 @@ Do you want to save message to draft box? Επικολληση του Λινκ - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" Προσθηκη του "Σε" @@ -13897,7 +13374,7 @@ Do you want to save message to draft box? Προσθήκη ως προτείνομενο - + Original Message Αυθεντικο μήνυμα @@ -13907,21 +13384,21 @@ Do you want to save message to draft box? Απο - + - + To Στον - - + + Cc CC - + Sent Σταλθηκε @@ -13936,7 +13413,7 @@ Do you want to save message to draft box? Στις % 1, %2 έγραψε: - + Re: Re: @@ -13946,30 +13423,30 @@ Do you want to save message to draft box? Fwd: - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? Θέλετε να στείλετε το μήνυμα χωρίς υποκείμενο; - + Please insert at least one recipient. Παρακαλώ εισάγετε τουλάχιστον έναν παραλήπτη. - + Bcc Bcc - + Unknown Άγνωστο @@ -14084,13 +13561,13 @@ Do you want to save message to draft box? Λεπετομέρειες - + Open File... Ανοιγμα αρχειου... - + HTML-Files (*.htm *.html);;All Files (*) Αρχεία HTML (*.htm * .html)??Όλα τα αρχεία (*) @@ -14110,7 +13587,7 @@ Do you want to save message to draft box? Εξαγωγή PDF - + Message has not been Sent. Do you want to save message ? Μήνυμα δεν έχει σταλεί. @@ -14132,7 +13609,7 @@ Do you want to save message ? Προσθηκη επιπλεον αρχειου - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -14162,18 +13639,18 @@ Do you want to save message ? - - + + Close Κλεισιμο - + From: Από: - + Bullet list (disc) @@ -14213,13 +13690,13 @@ Do you want to save message ? - - + + Thanks, <br> Ευχαριστούμε, <br> - + Distant identity: @@ -14229,12 +13706,12 @@ Do you want to save message ? [Λείπει] - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -14312,7 +13789,7 @@ Do you want to save message ? Προεπιλογή - + A new tab Μια νέα καρτέλα @@ -14322,7 +13799,7 @@ Do you want to save message ? Ένα νέο παράθυρο - + Edit Tag Επεξεργασια ετικέτας @@ -14345,7 +13822,7 @@ Do you want to save message ? MessageToaster - + Sub: Θεμα: @@ -14353,7 +13830,7 @@ Do you want to save message ? MessageUserNotify - + Message Μυνημα @@ -14381,7 +13858,7 @@ Do you want to save message ? MessageWidget - + Recommended Files Συνιστάμενα αρχεία @@ -14391,37 +13868,37 @@ Do you want to save message ? Λυψη ολων των συνιστωμενων αρχειων - + Subject: Θέμα: - + From: Από: - + To: Σε: - + Cc: CC: - + Bcc: BCC: - + Tags: Ετικέτες: - + Reply Απάντηση @@ -14461,7 +13938,7 @@ Do you want to save message ? - + Send Invite @@ -14505,7 +13982,7 @@ Do you want to save message ? Buttons Text Beside Icon - + Πλαισια κειμένου δίπλα από το εικονίδιο @@ -14513,7 +13990,7 @@ Do you want to save message ? - + Confirm %1 as friend Επιβεβαιώσει %1 ως φίλο @@ -14523,12 +14000,12 @@ Do you want to save message ? Προσθήκη %1 ως φίλος - + View source - + No subject Χωρις θεμα @@ -14538,17 +14015,22 @@ Do you want to save message ? Λυψη - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -14557,14 +14039,24 @@ Do you want to save message ? %1 (%2) + + + Show less + + + + + Show more + + - + Download all Λυψη ολων - + Print Document Εκτύπωση εγγράφου @@ -14579,12 +14071,12 @@ Do you want to save message ? Αρχεία HTML (*.htm * .html)??Όλα τα αρχεία (*) - + Load images always for this message - + Hide the attachment pane @@ -14606,42 +14098,6 @@ Do you want to save message ? Compose Συνθέση - - Reply to selected message - Απαντήση σε επιλεγμένο μήνυμα - - - Reply - Απάντηση - - - Reply all to selected message - Απάντηση όλα σε επιλεγμένο μήνυμα - - - Reply all - Απάντηση σε όλους - - - Forward selected message - Προώθηση του επιλεγμένου μηνύματος - - - Forward - Προς τα εμπρός - - - Remove selected message - Κατάργηση του επιλεγμένου μηνύματος - - - Delete - Διαγραφη - - - Print selected message - Εκτύπωση επιλεγμένου μηνύματος - Print @@ -14720,7 +14176,7 @@ Do you want to save message ? MessagesDialog - + New Message Νέο μήνυμα @@ -14730,60 +14186,16 @@ Do you want to save message ? Συνθέση - Reply to selected message - Απαντήσετε σε επιλεγμένο μήνυμα - - - Reply - Απάντηση - - - Reply all to selected message - Απάντηση όλα σε επιλεγμένο μήνυμα - - - Reply all - Απάντηση σε όλους - - - Forward selected message - Προώθηση του επιλεγμένου μηνύματος - - - Foward - Foward - - - Remove selected message - Κατάργηση του επιλεγμένου μηνύματος - - - Delete - Διαγραφη - - - Print selected message - Εκτύπωση επιλεγμένου μηνύματος - - - Print - Εκτυπωση - - - Display - Οθονη - - - + - - + + Tags Ετικέτες - - + + Inbox "Εισερχόμενα" @@ -14813,21 +14225,17 @@ Do you want to save message ? Σκουπίδια - + Total Inbox: Συνολικός φάκελος"Εισερχόμενα": - Folders - Φάκελοι - - - + Quick View ΠΡΟΒΟΛΗ - + Print... Εκτύπωση... @@ -14837,26 +14245,6 @@ Do you want to save message ? Print Preview Προεπισκόπηση εκτύπωσης - - Buttons Icon Only - Κουμπιά εικόνα μόνο - - - Buttons Text Beside Icon - Κουμπιά κειμένου δίπλα από το εικονίδιο - - - Buttons with Text - Πλαισια με κείμενο - - - Buttons Text Under Icon - Πλαισια κειμένου κάτω από το εικονίδιο - - - Set Text Under Icon - Ορισμός κειμένου κάτω από το εικονίδιο - Save As... @@ -14878,7 +14266,7 @@ Do you want to save message ? Μήνυμα προς τα εμπρός - + Subject Θέμα: @@ -14888,7 +14276,7 @@ Do you want to save message ? Απο - + Date Ημερομηνία @@ -14898,39 +14286,7 @@ Do you want to save message ? Περιεχόμενο - Click to sort by attachments - Κάντε κλικ στο κουμπί για να ταξινομήσετε με συνημμένα - - - Click to sort by subject - Κάντε κλικ στο κουμπί για να ταξινομήσετε με θέμα - - - Click to sort by read - Κάντε κλικ για να ταξινομήσετε από read - - - Click to sort by from - Κάντε κλικ στο κουμπί για να ταξινομήσετε από από - - - Click to sort by date - Κάντε κλικ για να ταξινομήσετε κατά ημερομηνία - - - Click to sort by tags - Κάντε κλικ στο κουμπί για να ταξινομήσετε με ετικέτες - - - Click to sort by star - Κάντε κλικ στο κουμπί για να ταξινομήσετε με αστέρι - - - Forward selected Message - Προώθηση του επιλεγμένου μηνύματος - - - + Search Subject Θέμα αναζήτησης @@ -14939,6 +14295,11 @@ Do you want to save message ? Search From Αναζήτηση από + + + Search To + + Search Date @@ -14965,14 +14326,14 @@ Do you want to save message ? Αναζήτηση συνημμένων - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred - Πρωταγωνίστησε + @@ -15046,7 +14407,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -15060,7 +14421,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -15075,34 +14436,33 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts Σχέδια - + No Box selected. - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - Δεν ειναι διαθέσιμα μηνύματα με αστέρι. Τα Αστέρια σας αφήνουν να δώσει μηνύματα, ένα ειδικό καθεστώς για να τους διευκολύνετε την εύρεση. Για να πρωταγωνιστήσει ένα μήνυμα, κάντε κλικ στο φως γκρι αστέρι δίπλα σε κάθε μήνυμα. - - - No system messages available. - Χωρίς σύστημα μηνύματα διαθέσιμα. - - + To - Στον + Στον - Click to sort by to - Κάντε κλικ στο κουμπί για να ταξινομήσετε με βάση να - - - + @@ -15110,10 +14470,6 @@ Do you want to save message ? Total: Σύνολο: - - Messages - Μηνύματα - Mail @@ -15141,7 +14497,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -15195,7 +14561,7 @@ Do you want to save message ? - + Expand Επεκταση @@ -15205,7 +14571,7 @@ Do you want to save message ? Απομακρυνση στοιχειου - + from από @@ -15240,7 +14606,7 @@ Do you want to save message ? Msg σε εκκρεμότητα - + Hide Αποκρυψη @@ -15381,7 +14747,7 @@ Do you want to save message ? Peer ID - + Remove unused keys... Κατάργηση αχρησιμοποίητων κλειδιών... @@ -15391,7 +14757,7 @@ Do you want to save message ? - + Clean keyring Εκκαθαριση κλειδοθήκης @@ -15409,7 +14775,13 @@ Notes: Your old keyring will be backed up. Η αφαίρεση μπορεί να αποτύχει κατά την εκτέλεση πολλαπλών Retroshare παρουσίων στο ίδιο μηχάνημα. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info Πληροφορίες κλειδοθήκων @@ -15445,18 +14817,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. Ασυνέπεια δεδομένων στην κλειδοθήκη. Αυτό είναι πιθανότατα ένα bug. Επικοινωνήστε με τους προγραμματιστές. - - - Export/create a new node - - Trusted keys only - + Search name Αναζήτηση ονόματος @@ -15466,25 +14833,18 @@ For security, your keyring was previously backed-up to file - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: - - NetworkPage - - Network - Δίκτυο - - NetworkView @@ -15511,7 +14871,7 @@ Reported error: NewFriendList - + Offline Friends @@ -15532,7 +14892,7 @@ Reported error: - + Groups Ομαδες @@ -15562,19 +14922,19 @@ Reported error: - - + + Search - + ID ID - + Search ID @@ -15584,12 +14944,12 @@ Reported error: - + Show Items - + Last contact @@ -15599,7 +14959,7 @@ Reported error: - + Group Ομάδα @@ -15714,7 +15074,7 @@ Reported error: Σύμπτυξη όλων - + Do you want to remove this node? @@ -15724,7 +15084,7 @@ Reported error: Θέλετε να διαγραψετε αυτόν τον φίλο? - + Done! Έγινε! @@ -15833,7 +15193,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -15848,11 +15208,7 @@ at least one peer was not added to a group Μετακινηση ολων - This is a test. - Αυτό είναι μια δοκιμη. - - - + Newest on top @@ -15862,12 +15218,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15922,10 +15278,6 @@ at least one peer was not added to a group Blogs Ιστολογια - - Security - Ασφαλεια - @@ -15947,10 +15299,6 @@ at least one peer was not added to a group Message Μυνημα - - Connect attempt - Συνδέση προσπάθειας - @@ -16104,10 +15452,6 @@ at least one peer was not added to a group Disable All Toaster temporarily - - Feed - Feed - Systray @@ -16117,7 +15461,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -16137,12 +15481,12 @@ at least one peer was not added to a group Λάθος κωδικός! - + Please enter your Retroshare passphrase - + Unregistered plugin/executable Μη καταγεγραμμένου plugin/εκτελέσιμο @@ -16157,19 +15501,7 @@ at least one peer was not added to a group Παρακαλώ ελέγξτε το ρολόι του συστήματός σας. - Examining shared files... - Εξέταση κοινόχρηστων αρχείων... - - - Hashing file - Κατακερματισμος αρχείου - - - Saving file index... - Αποθήκευση αρχείου ευρετηρίου... - - - + Test Δοκιμή @@ -16180,17 +15512,19 @@ at least one peer was not added to a group + Unknown title Άγνωστος τίτλος - + + Encrypted message Κρυπτογραφημένο μήνυμα - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -16198,7 +15532,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online Φίλος Online @@ -16250,10 +15584,6 @@ Low Traffic: 10% standard traffic and TODO: pauses all file-transfers PGPKeyDialog - - Dialog - Διαλόγος - Profile info @@ -16344,7 +15674,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -16353,10 +15688,6 @@ p, li { white-space: pre-wrap; } Keysigning: - - Sign PGP key - Υπογραφη PGP κλειδίου - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -16393,12 +15724,7 @@ p, li { white-space: pre-wrap; } Περιλαμβάνουν υπογραφές - - Options - Επιλογές - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -16444,21 +15770,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - - + + Error : cannot get peer details. Σφάλμα: οι peer λεπτομέρειες δεν μπορουν να παρθουν. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) Ο παρεχόμενος αλγόριθμος κλειδιού δεν υποστηρίζεται από το RetroShare⏎ (κλειδιά RSA μόνο υποστηρίζονται προς το παρόν) @@ -16476,7 +15802,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -16545,10 +15871,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Check the password! - - Maybe password is wrong - Μαλλον ο κωδικος ειναι λαθος - You haven't set a trust level for this key. @@ -16556,12 +15878,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -16587,7 +15909,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat Συνομιλια @@ -16608,7 +15930,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Απομακρυνση στοιχειου - + Name: Ονομα: @@ -16648,7 +15970,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message Εισαγωγη μυνηματος @@ -16662,10 +15984,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Friend Connected Φίλος συνδεθηκε - - Connect Attempt - Συνδέση προσπάθειας - Connection refused by peer @@ -16704,17 +16022,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.Unknown Άγνωστο - - Unknown Peer - Άγνωστο Peer - Hide Αποκρυψη - + Send Message Αποστολή Μηνύματος @@ -16881,13 +16195,6 @@ Warning: In your File-Transfer option, you select allow direct download to No. - - PhotoCommentItem - - Form - Φορμα - - PhotoDialog @@ -16895,23 +16202,11 @@ Warning: In your File-Transfer option, you select allow direct download to No.PhotoShare PhotoShare - - Photo - Φωτογραφία - TextLabel Ετικετα κειμενου - - Comment - Σχολιο - - - Summary - Περίληψη - Album / Photo Name @@ -16972,14 +16267,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.... ... - - Add Comment - Προσθήκη σχολίου - - - Write a comment... - Γράψτε ένα σχόλιο... - Album @@ -17050,10 +16337,6 @@ p, li { white-space: pre-wrap; }⏎ Create Album Δημιουργία άλμπουμ - - View Album - Εμφανιση άλμπουμ - Edit Album Details @@ -17075,17 +16358,17 @@ p, li { white-space: pre-wrap; }⏎ Προβολή διαφανειών - + My Albums Τα αλμπουμ μου - + Subscribed Albums Εγγεγραμμένα Αλμπουμ - + Shared Albums Κοινόχρηστα άλμπουμ @@ -17114,7 +16397,7 @@ requesting to edit it! PhotoSlideShow - + Album Name Όνομα άλμπουμ @@ -17173,19 +16456,19 @@ requesting to edit it! - - + + TextLabel - + Posted by - + ago @@ -17221,12 +16504,12 @@ requesting to edit it! PluginItem - + TextLabel Ετικετα κειμενου - + Show more details about this plugin Εμφανιση περισσότερων λεπτομέρειων σχετικά με αυτό το plugin @@ -17372,41 +16655,6 @@ p, li { white-space: pre-wrap; }⏎ Plugin look-up directories Plugin look-up καταλόγους - - No API number supplied. Please read plugin development manual. - Δεν περεχετε αριθμός API. Παρακαλώ διαβάστε το εγχειρίδιο ανάπτυξης plugin. - - - No SVN number supplied. Please read plugin development manual. - Δεν παρεχετε αριθμός SVN. Παρακαλώ διαβάστε το εγχειρίδιο ανάπτυξης plugin. - - - Loading error. - Σφάλμα φόρτωσης. - - - Missing symbol. Wrong version? - Λείπει το σύμβολο. Λάθος έκδοση; - - - No plugin object - Κανένα αντικείμενο plugin - - - Plugins is loaded. - Plugins είναι φορτωμένο. - - - Unknown status. - Άγνωστη κατάσταση. - - - Check this for developing plugins. They will not -be checked for the hash. However, in normal -times, checking the hash protects you from -malicious behavior of crafted plugins. - Ελέγξτε αυτό για την ανάπτυξη των plugins. Αυτοί δεν θα ελεγχθεί για τον κατακερματισμό. Ωστόσο, υπό κανονικές συνθήκες, έλεγχος hash σας προστατεύει από κακόβουλη συμπεριφορά του δημιουργημένο plugins. - Plugins @@ -17476,12 +16724,27 @@ malicious behavior of crafted plugins. Ορισμός παράθυρο στην κορυφή - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -17534,7 +16797,7 @@ malicious behavior of crafted plugins. - + Vote up @@ -17554,8 +16817,8 @@ malicious behavior of crafted plugins. \/ - - + + Comments @@ -17580,13 +16843,13 @@ malicious behavior of crafted plugins. - - + + Comment - + Σχόλιο - + Comments @@ -17614,20 +16877,12 @@ malicious behavior of crafted plugins. PostedCreatePostDialog - Signed by: - Υπογράφεται από: - - - Notes - Σημειώσεις - - - + Create a new Post - + RetroShare RetroShare @@ -17642,12 +16897,22 @@ malicious behavior of crafted plugins. - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File Φορτωση αρχειου εικονας - + Post image @@ -17663,7 +16928,17 @@ malicious behavior of crafted plugins. - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -17673,15 +16948,7 @@ malicious behavior of crafted plugins. - Submit Post - Υποβάλει θέσης - - - Submit - Υποβολη - - - + Please add a Title Παρακαλώ προσθέστε Τίτλο @@ -17701,12 +16968,22 @@ malicious behavior of crafted plugins. - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -17721,7 +16998,7 @@ malicious behavior of crafted plugins. Δημοσίευση ως - + Post @@ -17732,7 +17009,7 @@ malicious behavior of crafted plugins. Εικόνα - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -17742,7 +17019,7 @@ malicious behavior of crafted plugins. Τίτλος - + Link Σύνδεσμος @@ -17750,32 +17027,12 @@ malicious behavior of crafted plugins. PostedDialog - Posted Links - Δημοσιεύθηκε συνδέσεις - - - My Topics - Τα θέματα μου - - - Subscribed Topics - Εγγεγραμμένα θέματα - - - Popular Topics - Δημοφιλής θέματα - - - Other Topics - Άλλα θέματα - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -17809,27 +17066,7 @@ malicious behavior of crafted plugins. PostedGroupDialog - Posted Topic - Το θεμα καταχωρήθηκε - - - Add Topic Admins - Προσθήκη θέματων διαχειριστων - - - Select Topic Admins - Επιλέξτε το θέμα Admins - - - Create New Topic - Δημιουργήστε Νέο Θέμα - - - Edit Topic - Επεξεργασία Θέματος - - - + Create New Board @@ -17867,7 +17104,17 @@ malicious behavior of crafted plugins. PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted @@ -17883,7 +17130,7 @@ malicious behavior of crafted plugins. - + Expand Επεκταση @@ -17898,16 +17145,17 @@ malicious behavior of crafted plugins. - Loading - Φορτωση - - - + Loading... - + + Never + + + + New Board @@ -17920,22 +17168,18 @@ malicious behavior of crafted plugins. PostedItem - + 0 0 - Site - Τοποθεσία - - - - + + Comments Σχολια - + Copy RetroShare Link @@ -17946,12 +17190,12 @@ malicious behavior of crafted plugins. - + Comment Σχόλιο - + Comments @@ -17961,7 +17205,7 @@ malicious behavior of crafted plugins. - + Click to view Picture @@ -17971,21 +17215,17 @@ malicious behavior of crafted plugins. - + Vote up - + Vote down - \/ - \/ - - - + Set as read and remove item Ορισμος ως αναγνωσμένο και κατάργηση στοιχείου @@ -17995,7 +17235,7 @@ malicious behavior of crafted plugins. Νεο - + New Comment: @@ -18005,7 +17245,7 @@ malicious behavior of crafted plugins. - + Name @@ -18046,69 +17286,10 @@ malicious behavior of crafted plugins. - + Loading Φορτωση - - By - Από - - - - PostedListWidget - - Form - Φορμα - - - Hot - Ζεστό - - - New - Νεο - - - Top - Κορυφή - - - Today - Σήμερα - - - Yesterday - Χθες - - - This Week - Αυτή την εβδομάδα - - - This Month - Αυτό το μήνα - - - This Year - Φέτος - - - Next - Επόμενο - - - RetroShare - RetroShare - - - Please create or choose a Signing Id before Voting - Δημιουργήστε ή επιλέξτε ένα Id υπογραφής πριν από την ψηφοφορία - - - Previous - Προηγούμενη - PostedListWidgetWithModel @@ -18128,7 +17309,17 @@ malicious behavior of crafted plugins. - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -18138,15 +17329,15 @@ malicious behavior of crafted plugins. - + - + unknown Άγνωστο - + Distribution: @@ -18156,42 +17347,42 @@ malicious behavior of crafted plugins. - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts Δημοσιεύσεις - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -18211,7 +17402,7 @@ malicious behavior of crafted plugins. Ζεστό - + Search @@ -18241,17 +17432,17 @@ malicious behavior of crafted plugins. - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -18266,12 +17457,17 @@ malicious behavior of crafted plugins. - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -18281,27 +17477,31 @@ malicious behavior of crafted plugins. Επεξεργασία - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -18316,7 +17516,7 @@ malicious behavior of crafted plugins. Εγγραφη - + Never @@ -18390,6 +17590,16 @@ malicious behavior of crafted plugins. No Channel Selected Δεν υπάρχει επιλεγμένο κανάλι + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -18411,10 +17621,6 @@ malicious behavior of crafted plugins. PostedUserNotify - - Posted - Καταχωρήθηκε - Board Post @@ -18483,16 +17689,16 @@ malicious behavior of crafted plugins. Διαχειριστης προφιλ - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -18600,7 +17806,7 @@ and use the import button to load it ProfileWidget - + Edit status message Επεξεργασια μήνυματος κατάστασης @@ -18616,7 +17822,7 @@ and use the import button to load it Διαχειριστης προφιλ - + Public Information Δημοσιες πληροφοριες @@ -18651,12 +17857,12 @@ and use the import button to load it Online από: - + Other Information Άλλες πληροφορίες - + My Address Η διεύθυνσή μου @@ -18700,51 +17906,27 @@ and use the import button to load it PulseAddDialog - Post From: - Καταχώρηση από: - - - Account 1 - Λογαριασμός 1 - - - Account 2 - Λογαριασμος 2 - - - Account 3 - Λογαριασμός 3 - - - + Add to Pulse Προσθηκη στο Pulse - filter - φίλτρο - - - URL Adder - URL αθροιστής - - - + Display As Εμφάνιση ως - + URL URL - + GroupLabel - + IDLabel @@ -18754,12 +17936,12 @@ and use the import button to load it Από: - + Head - + Head Shot @@ -18789,13 +17971,13 @@ and use the import button to load it Αρνητικό - - + + Whats happening? - + @@ -18807,12 +17989,22 @@ and use the import button to load it - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -18821,17 +18013,13 @@ and use the import button to load it Cancel Διακοπη - - Post Pulse to Wire - Θέση παλμό για σύρμα - Post - + Reply to Pulse @@ -18846,34 +18034,24 @@ and use the import button to load it - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - Απο - - - Date - Ημερομηνία - - - ... - ... + + Load Picture File + Φορτωση αρχειου εικονας @@ -18884,7 +18062,7 @@ and use the import button to load it - + @@ -18903,7 +18081,7 @@ and use the import button to load it PulseReply - + icn @@ -18913,7 +18091,7 @@ and use the import button to load it - + REPLY @@ -18940,7 +18118,7 @@ and use the import button to load it - + FOLLOW @@ -18950,7 +18128,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -18970,7 +18148,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -19086,7 +18264,7 @@ and use the import button to load it - + FOLLOW @@ -19094,37 +18272,42 @@ and use the import button to load it PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -19156,7 +18339,7 @@ and use the import button to load it - + FOLLOW @@ -19164,8 +18347,8 @@ and use the import button to load it QObject - - + + Confirmation Επιβεβαίωση @@ -19435,12 +18618,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace Peer λεπτομέρειες - + File Request canceled Ακυρώθηκε η αίτηση αρχειου - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. Αυτή η έκδοση του RetroShare χρησιμοποιεί το OpenPGP-SDK. Ως παρενέργεια, δεν χρησιμοποιεί το κοινό σύστημα διαχείρισης κλειδιών του PGP, αλλά έχει είναι δική ΜΠΡΕΛΟΚ συμμερίζονται όλες οι παρουσίες RetroShare. <br><br>Δεν φαίνεται να έχουν ένα τέτοιο μπρελόκ, αν και τα κλειδιά του PGP αναφέρονται από τους υπάρχοντες λογαριασμούς eMule ομάδα + Ultra, πιθανώς επειδή έχετε αλλάξει μόνο σε αυτήν την νέα έκδοση του λογισμικού. @@ -19471,7 +18654,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace Παρουσιάστηκε μη αναμενόμενο σφάλμα. Παρακαλούμε να το αναφέρετε» RsInit::InitRetroShare απροσδόκητη επιστροφή κωδικός % 1». - + Cannot start Tor Manager! @@ -19505,7 +18688,7 @@ The error reported is:" - + Multiple instances Πολλές εμφανίσεις @@ -19526,6 +18709,26 @@ The error reported is:" Παρουσιάστηκε μη αναμενόμενο σφάλμα όταν το Retroshare προσπάθησε να αποκτήσει το μόνο παράδειγμα κλείδωμα κλειδωμένο αρχείο: + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -19605,7 +18808,7 @@ Reported error is: - + You appear to have nodes associated to DSA keys: @@ -19615,7 +18818,7 @@ Reported error is: - + enabled ενεργοποιημένο @@ -19625,7 +18828,7 @@ Reported error is: απενεργοποιημένο - + Move IP %1 to whitelist @@ -19641,7 +18844,7 @@ Reported error is: - + %1 seconds ago %1 δευτερόλεπτα πριν @@ -19708,7 +18911,7 @@ Security: no anonymous IDs - + Join chat room @@ -19736,7 +18939,7 @@ Security: no anonymous IDs - + Indefinitely @@ -19917,12 +19120,28 @@ Security: no anonymous IDs - - Status + + Name + Node + + + + + Address + + + + + + Status + + + + NXS @@ -20115,10 +19334,6 @@ Security: no anonymous IDs Click to resume the hashing process - - <p>This certificate contains: - <p>Αυτό το πιστοποιητικό περιλαμβάνει: - Idle @@ -20169,6 +19384,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -20333,7 +19560,7 @@ p, li { white-space: pre-wrap; }⏎ - + Network Wide Δίκτυο ευρείας @@ -20507,7 +19734,7 @@ p, li { white-space: pre-wrap; } Φορμα - + The loading of embedded images is blocked. @@ -20520,7 +19747,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default @@ -20693,12 +19920,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -20706,12 +19943,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -21401,7 +20638,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name @@ -21522,7 +20759,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name @@ -21542,7 +20779,7 @@ If you believe it is correct, remove the corresponding line from the file and re - + Profile ID @@ -21598,7 +20835,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -21612,11 +20849,6 @@ prevents the message to be forwarded to your friends. [Unknown] [Άγνωστο] - - - [ ... Missing Message ... ] - [ ... Λείπει ενα μήνυμα...] - RsMessageModel @@ -21630,6 +20862,11 @@ prevents the message to be forwarded to your friends. From + + + To + Στον + Subject @@ -21652,13 +20889,18 @@ prevents the message to be forwarded to your friends. - Click to sort by read - Κάντε κλικ για να ταξινομήσετε από read + Click to sort by read status + - Click to sort by from - Κάντε κλικ στο κουμπί για να ταξινομήσετε από από + Click to sort by author + + + + + Click to sort by destination + @@ -21681,7 +20923,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -21702,7 +20946,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. Επαναφέρει όλα της αποθηκευμένα ρυθμίσεις της RetroShare. @@ -21763,7 +21007,7 @@ prevents the message to be forwarded to your friends. Ορίζει το eMule ομάδα + Ultra του γλώσσα. - + Unable to open log file '%1': %2 Δεν είναι δυνατή η ανοιχτό αρχείο καταγραφής '% 1': %2 @@ -21784,7 +21028,7 @@ prevents the message to be forwarded to your friends. - + opmode @@ -21814,7 +21058,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -21832,7 +21076,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -21849,12 +21093,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) Εισάγετε μια λέξη-κλειδί εδώ (τουλάχιστον 3 char μακρά) - + Start Search Έναρξη αναζήτησης @@ -21915,7 +21159,7 @@ prevents the message to be forwarded to your friends. Εκκαθαριση - + KeyWords Λέξεις-κλειδιά @@ -21930,7 +21174,7 @@ prevents the message to be forwarded to your friends. Αναγνωριστικό αναζήτησης - + Filename Όνομα αρχείου @@ -22030,23 +21274,23 @@ prevents the message to be forwarded to your friends. Λυψη επιλεγμενου - + File Name Ονομα αρχειου - + Download Λυψη - + Copy RetroShare Link Αντιγραφη του Λινκ - + Send RetroShare Link Αποστολη ενος RetroShare λινκ @@ -22056,7 +21300,7 @@ prevents the message to be forwarded to your friends. - + Download Notice Λυψη ανακοίνωσης @@ -22093,7 +21337,7 @@ prevents the message to be forwarded to your friends. Μετακινηση ολων - + Folder Φάκελος @@ -22104,17 +21348,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) Νέα RetroShare Λινκ(s) - + Open Folder Άνοιγμα Φακέλου - + Create Collection... Δημιουργία Συλλογής ... @@ -22134,7 +21378,7 @@ prevents the message to be forwarded to your friends. Λυψη απο συλλογη αρχειων... - + Collection Συλλογή @@ -22142,7 +21386,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details Peer λεπτομέρειες @@ -22158,22 +21402,22 @@ prevents the message to be forwarded to your friends. Απομακρυνση στοιχειου - + IP address: Διεύθυνση IP: - + Peer ID: Peer ID: - + Location: Τοπος: - + Peer Name: @@ -22190,7 +21434,7 @@ prevents the message to be forwarded to your friends. Αποκρυψη - + but reported: @@ -22215,8 +21459,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -22224,7 +21468,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare θέλει να είναι φίλος μαζί σας στο RetroShare @@ -22255,7 +21499,7 @@ prevents the message to be forwarded to your friends. - + Expand Επεκταση @@ -22300,12 +21544,12 @@ prevents the message to be forwarded to your friends. Κατασταση: - + Write Message Εισαγωγη μυνηματος - + Connect Attempt Συνδέστε την προσπάθεια @@ -22325,17 +21569,22 @@ prevents the message to be forwarded to your friends. Άγνωστο (εξερχόμενη) σύνδεση προσπάθεια - + Unknown Security Issue Αγνωστο θεμα ασφαλειας - - A unknown peer + + SSL request - + + An unknown peer + + + + Unknown Άγνωστο @@ -22345,11 +21594,7 @@ prevents the message to be forwarded to your friends. - Unknown Peer - Άγνωστο Peer - - - + Hide Αποκρυψη @@ -22359,7 +21604,7 @@ prevents the message to be forwarded to your friends. Θέλετε να διαγραψετε αυτόν τον φίλο? - + Certificate has wrong signature!! This peer is not who he claims to be. @@ -22369,12 +21614,12 @@ prevents the message to be forwarded to your friends. - + Certificate caused an internal error. - + Peer/node not in friendlist (PGP id= @@ -22433,12 +21678,12 @@ prevents the message to be forwarded to your friends. - + Local Address Τοπική διεύθυνση - + NAT @@ -22459,22 +21704,22 @@ prevents the message to be forwarded to your friends. Υποδοχη: - + Local network Τοπικό δίκτυο - + External ip address finder Αναζητηση εξωτερικής ip διεύθυνσης - + UPnP UPnP - + Known / Previous IPs: Γνωστα / προηγούμενα IPs: @@ -22487,21 +21732,16 @@ behind a firewall or a VPN. Εάν καταργήσετε την επιλογή αυτή, το RetroShare μπορεί να καθορίσει μόνο IP σας όταν συνδέεστε σε κάποιον. Αφήνοντας αυτό ελέγχεται βοηθά τη σύνδεση όταν έχετε μερικούς φίλους. Βοηθά επίσης εάν είστε πίσω από ένα τείχος προστασίας ή ένα VPN. - - Allow RetroShare to ask my ip to these websites: - Επιτρέπει το eMule ομάδα + Ultra να ρωτήσω ip μου σε αυτούς τους ιστοχώρους: - - - - - + + + kB/s kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -22511,23 +21751,46 @@ behind a firewall or a VPN. - + Onion Address Διεύθυνση Onion - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -22537,7 +21800,7 @@ behind a firewall or a VPN. - + I2P Address @@ -22562,37 +21825,95 @@ behind a firewall or a VPN. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -22607,71 +21928,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. Άγνωστο - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -22681,22 +21938,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -22708,12 +21950,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -22723,7 +21965,7 @@ Also check your ports! Εκκαθαριση - + Download limit (KB/s) @@ -22738,23 +21980,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -22765,17 +22007,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -22785,12 +22017,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -22800,17 +22027,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 127.0.0.1 - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -22850,7 +22067,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start Εναρξη @@ -22865,12 +22082,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why Παυση - - BOB status - - - - + Incoming Εισερχόμενα @@ -22906,7 +22118,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -22961,7 +22198,7 @@ If you have issues connecting over Tor check the Tor logs too. Σύνολο: - + Warning: This bandwidth adds up to the max bandwidth. @@ -22986,7 +22223,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -22998,7 +22235,7 @@ If you have issues connecting over Tor check the Tor logs too. Δίκτυο - + IP Filters @@ -23021,7 +22258,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status Κατασταση @@ -23081,17 +22318,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -23107,18 +22355,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -23153,12 +22401,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -23181,22 +22429,22 @@ If you have issues connecting over Tor check the Tor logs too. Προστέθηκαν από εσάς - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -23231,7 +22479,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -23241,12 +22489,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -23326,7 +22574,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with Ελέγξτε τους ομοτυμους που θα θέλατε να μοιραστείτε το ιδιωτικο σας κλειδι δημοσιευσης @@ -23336,12 +22584,12 @@ If you have issues connecting over Tor check the Tor logs too. Μερίδιο για φίλο - + Share - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -23360,7 +22608,7 @@ Select the Friends with which you want to Share your Channel. Μοιρασμα διαχειριστη - + Shared directory @@ -23380,17 +22628,17 @@ Select the Friends with which you want to Share your Channel. Ορατότητα - + Add new - + Cancel - + Add a Share Directory Προσθέστε έναν κατάλογο μεριδίου @@ -23400,7 +22648,7 @@ Select the Friends with which you want to Share your Channel. Μετακινηση - + Apply and close Συσχέτιση και κλείσιμο @@ -23491,7 +22739,7 @@ Select the Friends with which you want to Share your Channel. Ο κατάλογος δεν βρέθηκε ή το όνομα καταλόγου δεν γίνετε δεκτο. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. @@ -23499,7 +22747,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files Αρχεια @@ -23550,11 +22798,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files Ελεγχος αρχειων - + Download selected Λυψη επιλεγμενου @@ -23564,7 +22817,7 @@ Select the Friends with which you want to Share your Channel. Λυψη - + Copy retroshare Links to Clipboard Αντιγραφη των retroshare Λινκ στο Clipboard @@ -23579,7 +22832,7 @@ Select the Friends with which you want to Share your Channel. Αποστολη των retroshare Λινκ - + Some files have been omitted @@ -23595,7 +22848,7 @@ Select the Friends with which you want to Share your Channel. Recommendation(s) - + Create Collection... Δημιουργία Συλλογής ... @@ -23620,7 +22873,7 @@ Select the Friends with which you want to Share your Channel. Λυψη απο συλλογη αρχειων... - + Some files have been omitted because they have not been indexed yet. @@ -23763,12 +23016,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration Ρύθμιση παραμέτρων - + Create interface Δημιουργία διασύνδεσης @@ -23792,7 +23045,7 @@ Select the Friends with which you want to Share your Channel. Εκθυμηση του κωδικου - + Log In Συνδέση @@ -24131,7 +23384,7 @@ This choice can be reverted in settings. Μήνυμα κατάστασης - + Message: Μήνυμα: @@ -24376,7 +23629,7 @@ p, li { white-space: pre-wrap; }⏎ TagsMenu - + Remove All Tags Αφαιρέση ολων των ετικετων @@ -24412,12 +23665,15 @@ p, li { white-space: pre-wrap; }⏎ - + + Tor status: - + + + Unknown Άγνωστο @@ -24427,18 +23683,13 @@ p, li { white-space: pre-wrap; }⏎ - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -24448,12 +23699,57 @@ p, li { white-space: pre-wrap; }⏎ - + + Error + + + + + Not connected + Μη συνδεδεμένος + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -24461,7 +23757,7 @@ p, li { white-space: pre-wrap; }⏎ TorStatus - + Tor @@ -24471,7 +23767,7 @@ p, li { white-space: pre-wrap; }⏎ - + Tor is currently offline @@ -24482,11 +23778,12 @@ p, li { white-space: pre-wrap; }⏎ + No tor configuration - + Tor proxy is OK @@ -24514,7 +23811,7 @@ p, li { white-space: pre-wrap; }⏎ TransferPage - + Transfer options Επιλογές μεταφοράς @@ -24525,7 +23822,7 @@ p, li { white-space: pre-wrap; }⏎ Μέγιστη ταυτόχρονη λυψη: - + Shared Directories @@ -24535,22 +23832,27 @@ p, li { white-space: pre-wrap; }⏎ Διαμοιράζονται αυτόματα τα Εισερχόμενα κατάλογο (συνιστάται) - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -24635,7 +23937,7 @@ p, li { white-space: pre-wrap; }⏎ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -24644,7 +23946,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -24669,7 +23976,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming Streaming @@ -24734,12 +24046,7 @@ p, li { white-space: pre-wrap; } Max. σήραγγα Αίτ. διαβιβάζονται ανά δευτερόλεπτο: - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -24749,7 +24056,17 @@ p, li { white-space: pre-wrap; } - + + Warning + Προειδοποίηση + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -24777,7 +24094,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed Ολοκληρωση λυψης @@ -24801,39 +24118,23 @@ p, li { white-space: pre-wrap; } %1 completed transfer - - You have %1 completed downloads - Έχετε %1 ολοκληρώμενη λυψη - - - You have %1 completed download - Η λήψη %1 ολοκληρώθηκε - - - %1 completed downloads - %1 ολοκληρώμενη λυψη - - - %1 completed download - %1 ολοκληρώμενη λυψη - TransfersDialog - - + + Downloads Λήψεις - + Uploads Προσθήκες - + Name i.e: file name Ονομα @@ -25040,7 +24341,12 @@ p, li { white-space: pre-wrap; } Καθορίσμος... - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... Μετακίνηση στην ουρά... @@ -25065,7 +24371,7 @@ p, li { white-space: pre-wrap; } Επιλογη κατάλογου - + Anonymous end-to-end encrypted tunnel 0x @@ -25086,7 +24392,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -25119,7 +24425,17 @@ p, li { white-space: pre-wrap; } Το αρχείο %1 δεν έχει ολοκληρωθεί. Εάν είναι ένα αρχείο πολυμέσων, προσπαθήστε να κάνετε προεπισκόπηση. - + + Warning + Προειδοποίηση + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name Αλλαγή όνοματος αρχείου @@ -25134,7 +24450,7 @@ p, li { white-space: pre-wrap; } Παρακαλούμε εισάγετε ένα νέο--και έγκυρο--όνομα αρχείου - + Expand all Επεκταση ολων @@ -25261,23 +24577,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Στήλες - + File Transfers - + Path Διαδρομή @@ -25287,7 +24598,7 @@ p, li { white-space: pre-wrap; } - + Could not delete preview file @@ -25297,7 +24608,7 @@ p, li { white-space: pre-wrap; } - + Create Collection... Δημιουργία Συλλογής ... @@ -25312,7 +24623,7 @@ p, li { white-space: pre-wrap; } Εμφάνιση Συλλογής ... - + Collection Συλλογή @@ -25322,7 +24633,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x @@ -25736,12 +25047,17 @@ p, li { white-space: pre-wrap; } Φορμα - + Enable Retroshare WEB Interface - + + Status: + Κατασταση: + + + Web parameters Παράμετροι δικτύου @@ -25781,17 +25097,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -25801,12 +25127,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface @@ -25943,11 +25269,7 @@ p, li { white-space: pre-wrap; } Σελίδες wiki - New Group - Νέα ομάδα - - - + Page Name Όνομα σελίδας @@ -25962,7 +25284,7 @@ p, li { white-space: pre-wrap; } Orig Id - + << << @@ -26050,7 +25372,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History Σελίδα επεξεργασίας ιστορίκου @@ -26085,7 +25407,7 @@ p, li { white-space: pre-wrap; } PageId - + \/ \/ @@ -26115,14 +25437,18 @@ p, li { white-space: pre-wrap; } Ετικέτες - - + + History + Ιστορικό + + + Show Edit History Εμφανιση ιστορικόυ - + Status Κατασταση @@ -26143,7 +25469,7 @@ p, li { white-space: pre-wrap; } Επαναφορά - + Submit Υποβολη @@ -26215,10 +25541,6 @@ p, li { white-space: pre-wrap; } WireDialog - - TimeRange - TimeRange - Create Account @@ -26230,16 +25552,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - Ανανέωση - - - + Settings @@ -26254,7 +25567,7 @@ p, li { white-space: pre-wrap; } Άλλοι - + Who to Follow @@ -26274,7 +25587,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -26304,85 +25617,17 @@ p, li { white-space: pre-wrap; } - Last Month - Περασμένος μήνας - - - Last Week - Προηγούμενη εβδομάδα - - - Today - Σήμερα - - - New - Νεο - - - from - από - - - until - μέχρι - - - Search/Filter - Φίλτρο αναζήτησης - - - Network Wide - Δίκτυο ευρείας - - - Manage Accounts - Διαχείριση λογαριασμών - - - Showing: - Εμφανιση: - - - + Yourself τον εαυτό σας - - Friends - Φίλοι - Following Μετά - Custom - Προσαρμογη - - - Account 1 - Λογαριασμός 1 - - - Account 2 - Λογαριασμος 2 - - - Account 3 - Λογαριασμός 3 - - - CheckBox - Πλαίσιο ελέγχου - - - Post Pulse to Wire - Θέση παλμό για σύρμα - - - + RetroShare RetroShare @@ -26445,35 +25690,42 @@ p, li { white-space: pre-wrap; } - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + Μετακινηση + + + Location: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -26518,11 +25770,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + N/A + + + + Following + Μετά + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Άγνωστο @@ -26600,7 +25882,7 @@ p, li { white-space: pre-wrap; } % 1y % 2d - + k e.g: 3.1 k k @@ -26633,15 +25915,11 @@ p, li { white-space: pre-wrap; } Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif *.webp) - - Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - Εικόνες (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_en.ts b/retroshare-gui/src/lang/retroshare_en.ts index 3b670aeaa..74a7b83b3 100644 --- a/retroshare-gui/src/lang/retroshare_en.ts +++ b/retroshare-gui/src/lang/retroshare_en.ts @@ -121,12 +121,12 @@ - + Search Criteria - + Add a further search criterion. @@ -136,7 +136,7 @@ - + Cancels the search. @@ -540,7 +540,7 @@ p, li { white-space: pre-wrap; } - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. @@ -566,10 +566,23 @@ p, li { white-space: pre-wrap; } + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb @@ -612,7 +625,7 @@ p, li { white-space: pre-wrap; } - + Set your Avatar picture @@ -699,7 +712,7 @@ p, li { white-space: pre-wrap; } - + Always on Top @@ -795,7 +808,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment @@ -825,12 +838,12 @@ p, li { white-space: pre-wrap; } - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -838,7 +851,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up @@ -858,7 +871,7 @@ p, li { white-space: pre-wrap; } - + Posted by @@ -896,7 +909,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up @@ -916,7 +929,7 @@ p, li { white-space: pre-wrap; } - + Click to view picture @@ -946,7 +959,7 @@ p, li { white-space: pre-wrap; } - + Toggle Message Read Status @@ -956,7 +969,7 @@ p, li { white-space: pre-wrap; } - + TextLabel @@ -964,12 +977,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this - + 0 @@ -989,18 +1002,18 @@ p, li { white-space: pre-wrap; } - + New Comment - + Copy RetroShare Link - + Expand @@ -1015,12 +1028,12 @@ p, li { white-space: pre-wrap; } - + Name - + Comm value @@ -1189,17 +1202,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels - + Tabs - + General @@ -1209,7 +1222,17 @@ p, li { white-space: pre-wrap; } - + + Downloads + + + + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab @@ -1217,7 +1240,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1240,7 +1263,7 @@ into the image, so as to ChannelsCommentsItem - + I like this @@ -1265,18 +1288,18 @@ into the image, so as to - + New Comment - + Copy RetroShare Link - + Expand @@ -1291,7 +1314,7 @@ into the image, so as to - + Name @@ -1301,17 +1324,7 @@ into the image, so as to - - Comment - - - - - Comments - - - - + Hide @@ -1319,7 +1332,7 @@ into the image, so as to ChatLobbyDialog - + Name @@ -1510,7 +1523,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby @@ -1543,13 +1556,14 @@ into the image, so as to - + + Unknown Lobby - - + + Remove All @@ -1557,13 +1571,13 @@ into the image, so as to ChatLobbyWidget - - + + Name - + Count @@ -1573,29 +1587,7 @@ into the image, so as to - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - - - - - - Public chat rooms - - - - + Create chat room @@ -1605,7 +1597,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1662,12 +1654,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1677,23 +1669,42 @@ Double click a chat room to enter and chat. - + [No topic provided] - + + Private Subscribed + + + + + + Public Subscribed + + + + + Private - + + + Public - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted @@ -1703,27 +1714,22 @@ Double click a chat room to enter and chat. - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe - + Search Chat lobbies - + Search Name - + Columns @@ -1738,47 +1744,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: - + Type: - + Security: - + Peers: - - - - - - + + + + + + TextLabel @@ -1793,7 +1799,7 @@ Double click a chat room to enter and chat. - + Show @@ -1813,7 +1819,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item @@ -1858,7 +1864,7 @@ Double click a chat room to enter and chat. ChatPage - + General @@ -1873,7 +1879,7 @@ Double click a chat room to enter and chat. - + Enable custom fonts @@ -1893,7 +1899,7 @@ Double click a chat room to enter and chat. - + General settings @@ -1918,7 +1924,7 @@ Double click a chat room to enter and chat. - + Blink tab icon @@ -1948,7 +1954,7 @@ Double click a chat room to enter and chat. - + Change Chat Font @@ -1958,7 +1964,7 @@ Double click a chat room to enter and chat. - + History @@ -1982,7 +1988,7 @@ Double click a chat room to enter and chat. - + Choose your default font for Chat. @@ -2052,12 +2058,22 @@ Double click a chat room to enter and chat. - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2067,7 +2083,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2164,7 +2190,7 @@ Double click a chat room to enter and chat. - + Case sensitive @@ -2270,7 +2296,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat @@ -2306,7 +2332,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close @@ -2341,12 +2367,12 @@ Double click a chat room to enter and chat. - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2426,11 +2452,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2468,7 +2489,7 @@ Double click a chat room to enter and chat. - + is typing... @@ -2490,7 +2511,7 @@ after HTML conversion. - + Do you really want to physically delete the history? @@ -2540,7 +2561,7 @@ after HTML conversion. - + Find Case Sensitively @@ -2562,7 +2583,7 @@ after HTML conversion. - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> @@ -2577,12 +2598,12 @@ after HTML conversion. - + (Status) - + Attach a File @@ -2598,12 +2619,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> - + Person id: @@ -2614,12 +2635,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. @@ -2639,7 +2660,7 @@ Double click on it to add his name on text writer. - + Don't stop to color after @@ -2665,7 +2686,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: @@ -2687,7 +2708,7 @@ Double click on it to add his name on text writer. - + Personal Circles @@ -2713,7 +2734,7 @@ Double click on it to add his name on text writer. - + Friends @@ -2773,7 +2794,7 @@ Double click on it to add his name on text writer. - + External Circles (Admin) @@ -2789,7 +2810,7 @@ Double click on it to add his name on text writer. - + Circles @@ -2841,45 +2862,45 @@ Double click on it to add his name on text writer. - + RetroShare - + - + Error : cannot get peer details. - + Retroshare ID - + <p>This Retroshare ID contains: - + <p>This certificate contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: @@ -2889,7 +2910,7 @@ Double click on it to add his name on text writer. - + Not connected @@ -2971,12 +2992,17 @@ Double click on it to add his name on text writer. - + <li>a <b>node ID</b> and <b>name</b> - + + <b>DNS:</b> : + + + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -2996,7 +3022,7 @@ Double click on it to add his name on text writer. - + with @@ -3064,7 +3090,7 @@ Double click on it to add his name on text writer. - + @@ -3080,12 +3106,12 @@ Double click on it to add his name on text writer. - + Peer details - + Name: @@ -3095,17 +3121,17 @@ Double click on it to add his name on text writer. - + Options - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: @@ -3115,7 +3141,7 @@ Double click on it to add his name on text writer. - + Please paste below your friend's Retroshare ID @@ -3140,12 +3166,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with - + Sorry, some error appeared @@ -3165,32 +3201,27 @@ Double click on it to add his name on text writer. - + Key validity: - + Profile ID: - - Signers - - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. - + To accept the Friend Request, click the Accept button. @@ -3236,17 +3267,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed - + Not a valid Retroshare certificate! - + RetroShare Invitation @@ -3266,12 +3297,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3279,7 +3310,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3319,7 +3350,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Profile password needed. @@ -3344,7 +3375,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3354,7 +3385,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3393,7 +3424,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + IP-Addr: @@ -3403,7 +3434,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Show Advanced options @@ -3428,7 +3459,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already in your keyring @@ -3441,7 +3472,7 @@ even if you don't make friends. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. @@ -3476,7 +3507,7 @@ even if you don't make friends. - + No IP in this certificate! @@ -3486,12 +3517,7 @@ even if you don't make friends. - - [Unknown] - - - - + Added with certificate from %1 @@ -3556,7 +3582,7 @@ even if you don't make friends. - + UDP Setup @@ -3584,7 +3610,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant @@ -3594,17 +3620,20 @@ p, li { white-space: pre-wrap; } - + + Unknown State - + + Offline - + + Behind Symmetric NAT @@ -3614,12 +3643,14 @@ p, li { white-space: pre-wrap; } - + + NET Restart - + + Behind NAT @@ -3629,7 +3660,8 @@ p, li { white-space: pre-wrap; } - + + NET STATE GOOD! @@ -3654,7 +3686,7 @@ p, li { white-space: pre-wrap; } - + Lookup requires DHT @@ -3946,7 +3978,7 @@ p, li { white-space: pre-wrap; } - + @@ -3954,7 +3986,8 @@ p, li { white-space: pre-wrap; } - + + UNVERIFIABLE FORWARD! @@ -3964,7 +3997,7 @@ p, li { white-space: pre-wrap; } - + Searching @@ -4000,12 +4033,12 @@ p, li { white-space: pre-wrap; } - + Name - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4025,7 +4058,7 @@ p, li { white-space: pre-wrap; } - + IDs @@ -4045,18 +4078,18 @@ p, li { white-space: pre-wrap; } - + Cancel - + Nickname - + Invited Members @@ -4071,7 +4104,7 @@ p, li { white-space: pre-wrap; } - + Name: @@ -4111,19 +4144,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare - + Please set a name for your Circle - + No Restriction Circle Selected @@ -4133,12 +4166,24 @@ p, li { white-space: pre-wrap; } - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add @@ -4148,7 +4193,7 @@ p, li { white-space: pre-wrap; } - + Search @@ -4201,13 +4246,13 @@ p, li { white-space: pre-wrap; } - + Create - + Add Member @@ -4226,7 +4271,7 @@ p, li { white-space: pre-wrap; } - + Group Name: @@ -4261,7 +4306,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post @@ -4271,7 +4316,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4416,17 +4461,17 @@ p, li { white-space: pre-wrap; } - + RetroShare - + This file already in this post: - + Post refers to non shared files @@ -4451,7 +4496,12 @@ p, li { white-space: pre-wrap; } - + + Cannot publish post + + + + Load thumbnail picture @@ -4466,18 +4516,12 @@ p, li { white-space: pre-wrap; } - - + Generate mass data - - Do you really want to generate %1 messages ? - - - - + You are about to add files you're not actually sharing. Do you still want this to happen? @@ -4511,7 +4555,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message @@ -4521,7 +4565,16 @@ p, li { white-space: pre-wrap; } - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> + + + + Attach File @@ -4536,16 +4589,7 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> - - - - + Attach a Picture @@ -4560,7 +4604,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4590,17 +4634,17 @@ p, li { white-space: pre-wrap; } - + No Forum - + In Reply to - + Title @@ -4653,7 +4697,7 @@ Do you want to discard this message? - + No compatible ID for this forum @@ -4663,8 +4707,8 @@ Do you want to discard this message? - - + + Generate mass data @@ -4687,7 +4731,7 @@ Do you want to discard this message? CreateLobbyDialog - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -4722,7 +4766,7 @@ Do you want to discard this message? - + Create @@ -4732,7 +4776,7 @@ Do you want to discard this message? - + require PGP-signed identities @@ -4747,7 +4791,7 @@ Do you want to discard this message? - + Create Chat Room @@ -4768,7 +4812,7 @@ Do you want to discard this message? - + Identity to use: @@ -4776,17 +4820,17 @@ Do you want to discard this message? CryptoPage - + Public Information - + Name: - + Location: @@ -4796,12 +4840,12 @@ Do you want to discard this message? - + Software Version: - + Online since: @@ -4821,12 +4865,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -4836,7 +4875,7 @@ Do you want to discard this message? - + Other Information @@ -4846,17 +4885,12 @@ Do you want to discard this message? - + Profile - - Certificate - - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -4866,7 +4900,7 @@ Do you want to discard this message? - + Export Identity @@ -4936,33 +4970,33 @@ and use the import button to load it - + TextLabel - + PGP fingerprint: - - Node information - - - - + PGP Id : - + Friend nodes: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5052,7 +5086,7 @@ and use the import button to load it DLListDelegate - + B @@ -5720,7 +5754,7 @@ and use the import button to load it DownloadToaster - + Start file @@ -5728,38 +5762,38 @@ and use the import button to load it ExprParamElement - + - + to - + ignore case - - - dd.MM.yyyy + + + yyyy-MM-dd - - + + KB - - + + MB - - + + GB @@ -5767,12 +5801,12 @@ and use the import button to load it ExpressionWidget - + Expression Widget - + Delete this expression @@ -5934,7 +5968,7 @@ and use the import button to load it FilesDefs - + Picture @@ -5944,7 +5978,7 @@ and use the import button to load it - + Audio @@ -6004,11 +6038,21 @@ and use the import button to load it C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories @@ -6130,7 +6174,7 @@ and use the import button to load it - + ID @@ -6172,7 +6216,7 @@ and use the import button to load it - + Group @@ -6208,7 +6252,7 @@ and use the import button to load it - + Search @@ -6224,7 +6268,7 @@ and use the import button to load it - + Profile details @@ -6461,7 +6505,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request @@ -6499,7 +6543,7 @@ at least one peer was not added to a group - + Mark all @@ -6510,16 +6554,132 @@ at least one peer was not added to a group + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + + + + + Node ID + + + + + Address + + + + + Status + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message - - + + Broadcast @@ -6602,33 +6762,38 @@ at least one peer was not added to a group - + Keyring - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. - - + + Network - + + Friend Server + + + + Network graph - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. @@ -6646,7 +6811,17 @@ at least one peer was not added to a group - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters @@ -6656,17 +6831,12 @@ at least one peer was not added to a group - + Port - - Use BOB - - - - + This password is for PGP @@ -6687,38 +6857,38 @@ at least one peer was not added to a group - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -6738,12 +6908,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -6753,38 +6923,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel - + hidden address - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -6828,13 +7003,13 @@ and use the import button to load it - + Import profile - + Create new profile and new Retroshare node @@ -6844,7 +7019,7 @@ and use the import button to load it - + Tor/I2P address @@ -6879,7 +7054,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -6889,12 +7064,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -6904,12 +7074,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7135,27 +7300,13 @@ and use the import button to load it - + Invite Friends - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - - - - + Add Your Friends to RetroShare @@ -7165,39 +7316,57 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + Connect To Friends - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port @@ -7205,49 +7374,45 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - - - - + Further Help and Support - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website @@ -7272,7 +7437,7 @@ p, li { white-space: pre-wrap; } - + RetroShare Invitation @@ -7322,12 +7487,12 @@ p, li { white-space: pre-wrap; } - + RetroShare Support - + It has many features, including built-in chat, messaging, @@ -7451,7 +7616,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat @@ -7459,7 +7624,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] @@ -7629,7 +7794,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title @@ -7642,12 +7807,12 @@ p, li { white-space: pre-wrap; } - + Description - + Number of Unread message @@ -7672,7 +7837,7 @@ p, li { white-space: pre-wrap; } - + You are admin (modify names and description using Edit menu) @@ -7687,14 +7852,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post - + Name @@ -7705,13 +7870,13 @@ p, li { white-space: pre-wrap; } - + Never - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -7724,7 +7889,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and @@ -7860,7 +8025,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels @@ -7871,22 +8036,22 @@ p, li { white-space: pre-wrap; } - + Enable Auto-Download - + My Channels - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels @@ -7906,12 +8071,12 @@ p, li { white-space: pre-wrap; } - + Disable Auto-Download - + Set download directory @@ -7946,22 +8111,22 @@ p, li { white-space: pre-wrap; } - + Play - + Open folder - + Open file - + Error @@ -7981,17 +8146,17 @@ p, li { white-space: pre-wrap; } - + Are you sure that you want to cancel and delete the file? - + Can't open folder - + Play File @@ -8004,7 +8169,7 @@ p, li { white-space: pre-wrap; } GxsChannelGroupDialog - + Create New Channel @@ -8042,8 +8207,18 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel @@ -8058,7 +8233,7 @@ p, li { white-space: pre-wrap; } - + Expand @@ -8073,7 +8248,7 @@ p, li { white-space: pre-wrap; } - + Loading @@ -8087,6 +8262,11 @@ p, li { white-space: pre-wrap; } New Channel: + + + Never + + Hide @@ -8096,7 +8276,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: @@ -8117,7 +8297,7 @@ p, li { white-space: pre-wrap; } - + Play @@ -8179,18 +8359,18 @@ p, li { white-space: pre-wrap; } - + New - + 0 - - + + Comment @@ -8205,17 +8385,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + Comments - + Post @@ -8243,13 +8423,13 @@ p, li { white-space: pre-wrap; } GxsChannelPostsWidgetWithModel - + Post to Channel - + Add new post @@ -8319,7 +8499,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -8355,7 +8535,7 @@ p, li { white-space: pre-wrap; } - + Comments @@ -8370,13 +8550,13 @@ p, li { white-space: pre-wrap; } - - + + Click to switch to list view - + Show unread posts only @@ -8391,7 +8571,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -8406,7 +8586,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -8466,12 +8646,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -8546,12 +8736,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed @@ -8602,17 +8793,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -8727,7 +8918,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container @@ -8740,7 +8931,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -8770,7 +8961,7 @@ p, li { white-space: pre-wrap; } - + Comment @@ -8809,7 +9000,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment @@ -8833,6 +9024,21 @@ p, li { white-space: pre-wrap; } Vote Down + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -8842,7 +9048,7 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -8871,7 +9077,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -8902,7 +9108,7 @@ before you can comment - + It remains %1 characters after HTML conversion. @@ -8953,7 +9159,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum @@ -8969,7 +9175,7 @@ before you can comment - + Expand @@ -8988,6 +9194,11 @@ before you can comment Moderator list + + + TextLabel + + Loading... @@ -9017,13 +9228,13 @@ before you can comment GxsForumMsgItem - - + + Subject: - + Unsubscribe To Forum @@ -9034,7 +9245,7 @@ before you can comment - + Expand @@ -9054,17 +9265,17 @@ before you can comment - + Loading... - + Forum Feed - + Hide @@ -9077,59 +9288,66 @@ before you can comment - + Start new Thread for Selected Forum - + + Threaded + + + + + + + ... + + + + + Flat + + + + + Latest post in thread + + + + Search forums - + New Thread - - - Threaded View - - - - - Flat View - - - + Title - - + + Date - + Author - - Save image - - - - + Loading - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9139,12 +9357,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message @@ -9184,23 +9397,23 @@ before you can comment - + No name - - + + Reply - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -9243,12 +9456,12 @@ before you can comment - + Hide - + [unknown] @@ -9278,8 +9491,8 @@ before you can comment - - + + Distribution @@ -9362,12 +9575,12 @@ before you can comment - + New thread - + Edit @@ -9428,7 +9641,7 @@ before you can comment - + Show column @@ -9448,7 +9661,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive @@ -9500,7 +9713,7 @@ This message is missing. You should receive it later. - + No result. @@ -9510,7 +9723,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -9525,7 +9738,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -9591,12 +9804,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums @@ -9631,12 +9844,12 @@ This message is missing. You should receive it later. GxsGroupDialog - + Name - + Key recipients can publish to restricted-type group and can view and publish for private-type channels @@ -9647,12 +9860,12 @@ This message is missing. You should receive it later. - + Description - + Message Distribution @@ -9660,7 +9873,7 @@ This message is missing. You should receive it later. - + Public @@ -9720,7 +9933,7 @@ This message is missing. You should receive it later. - + Comments: @@ -9743,7 +9956,7 @@ This message is missing. You should receive it later. - + All People @@ -9759,12 +9972,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -9781,23 +9994,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -9813,22 +10026,28 @@ This message is missing. You should receive it later. - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo - + Submit Group Changes - + Owner: @@ -9838,12 +10057,12 @@ This message is missing. You should receive it later. - + Info - + ID @@ -9853,7 +10072,7 @@ This message is missing. You should receive it later. - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -9928,7 +10147,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity @@ -9944,27 +10168,22 @@ This message is missing. You should receive it later. - + Created - + Cancel - + Create - - Author - - - - + GxsIdLabel @@ -9972,7 +10191,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading @@ -10032,7 +10251,7 @@ This message is missing. You should receive it later. - + Synchronise posts of last... @@ -10089,12 +10308,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link @@ -10117,7 +10336,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature @@ -10130,14 +10349,14 @@ This message is missing. You should receive it later. GxsIdDetails - + Not found - - + + [Banned] @@ -10147,7 +10366,7 @@ This message is missing. You should receive it later. - + Loading... @@ -10157,7 +10376,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -10177,6 +10401,14 @@ This message is missing. You should receive it later. + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -10188,7 +10420,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -10236,7 +10468,7 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] @@ -10623,7 +10855,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -10639,7 +10871,7 @@ p, li { white-space: pre-wrap; } - + Authors @@ -10658,7 +10890,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -10732,7 +10964,7 @@ p, li { white-space: pre-wrap; } - + Add friend @@ -10742,7 +10974,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -10770,7 +11002,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -10780,7 +11012,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard @@ -10790,7 +11022,7 @@ private and secure decentralized communication platform. - + Send via Email @@ -10810,13 +11042,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -10828,12 +11084,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -10848,12 +11104,7 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... @@ -11118,14 +11369,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All - + Reputation @@ -11135,12 +11386,12 @@ p, li { white-space: pre-wrap; } - + Anonymous Id - + Create new Identity @@ -11150,7 +11401,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -11165,27 +11416,27 @@ p, li { white-space: pre-wrap; } - + Close - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -11201,29 +11452,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles - + Circle name @@ -11243,18 +11504,20 @@ p, li { white-space: pre-wrap; } - + + Edit identity - + + Delete identity - + Chat with this peer @@ -11264,78 +11527,78 @@ p, li { white-space: pre-wrap; } - + Owner node ID : - + Identity name : - + () - + Identity ID - + Send message - + Identity info - + Identity ID : - + Owner node name : - + Create new... - + Type: - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: - + Negative - + Neutral @@ -11346,17 +11609,17 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous @@ -11371,24 +11634,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you - - + + My own identities - - + + My contacts - + Show Items @@ -11403,7 +11666,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -11413,7 +11681,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -11488,7 +11756,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -11518,7 +11786,7 @@ p, li { white-space: pre-wrap; } - + Invited @@ -11533,7 +11801,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle @@ -11581,7 +11849,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -11589,7 +11857,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -11632,7 +11900,7 @@ These identities will soon be not supported anymore. - + Boards @@ -11712,7 +11980,7 @@ These identities will soon be not supported anymore. - + information @@ -11728,17 +11996,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -11843,7 +12106,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -11893,21 +12156,21 @@ These identities will soon be not supported anymore. - - - + + + People - + Your Avatar Click here to change your avatar - + Linked to neighbor nodes @@ -11917,7 +12180,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -11932,7 +12195,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -11947,12 +12210,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -11972,12 +12235,12 @@ These identities will soon be not supported anymore. - + Owned by - + Node name: @@ -11987,7 +12250,7 @@ These identities will soon be not supported anymore. - + Really delete? @@ -11995,7 +12258,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname @@ -12025,7 +12288,13 @@ These identities will soon be not supported anymore. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity @@ -12039,7 +12308,7 @@ These identities will soon be not supported anymore. - + @@ -12049,7 +12318,12 @@ These identities will soon be not supported anymore. - + + No avatar chosen + + + + Edit identity @@ -12060,27 +12334,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -12100,7 +12374,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -12110,12 +12384,18 @@ These identities will soon be not supported anymore. - + Error KeyID invalid - + + + No Avatar chosen. A default image will be automatically displayed from your new identity. + + + + Import image @@ -12125,12 +12405,7 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. - - - - + Unknown GpgId @@ -12140,7 +12415,7 @@ These identities will soon be not supported anymore. - + Create New Identity @@ -12150,10 +12425,15 @@ These identities will soon be not supported anymore. - + Choose image... + + + Remove + + @@ -12179,7 +12459,7 @@ These identities will soon be not supported anymore. - + Create @@ -12189,13 +12469,13 @@ These identities will soon be not supported anymore. - + Your Avatar Click here to change your avatar - + Linked to your profile @@ -12205,7 +12485,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -12279,7 +12559,7 @@ These identities will soon be not supported anymore. - + Copy @@ -12289,12 +12569,12 @@ These identities will soon be not supported anymore. - + %1 's Message History - + Mark all @@ -12317,18 +12597,34 @@ These identities will soon be not supported anymore. ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -12346,27 +12642,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: - + Listen Address: - + + Status: + + + + 127.0.0.1 - + Token: @@ -12387,7 +12688,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -12396,26 +12702,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File - + Open Folder - + Checking... @@ -12425,7 +12736,7 @@ These identities will soon be not supported anymore. - + Recommend in a message to... @@ -12453,7 +12764,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend @@ -12469,7 +12780,8 @@ These identities will soon be not supported anymore. - + + Options @@ -12490,7 +12802,7 @@ These identities will soon be not supported anymore. - + Quit @@ -12501,12 +12813,12 @@ These identities will soon be not supported anymore. - + RetroShare %1 a secure decentralized communication platform - + Unfinished @@ -12531,11 +12843,12 @@ These identities will soon be not supported anymore. + Status - + Notify @@ -12546,31 +12859,35 @@ These identities will soon be not supported anymore. + Open Messages - + + Bandwidth Graph - + Applications + Help - + + Minimize - + Maximize @@ -12585,7 +12902,12 @@ These identities will soon be not supported anymore. - + + Close window + + + + %1 new message @@ -12615,7 +12937,7 @@ These identities will soon be not supported anymore. - + Do you really want to exit RetroShare ? @@ -12635,7 +12957,7 @@ These identities will soon be not supported anymore. - + Make sure this link has not been forged to drag you to a malicious website. @@ -12680,12 +13002,13 @@ These identities will soon be not supported anymore. - + + Statistics - + Show web interface @@ -12700,7 +13023,7 @@ These identities will soon be not supported anymore. - + Really quit ? @@ -12709,17 +13032,17 @@ These identities will soon be not supported anymore. MessageComposer - + Compose - + Contacts - + Paragraph @@ -12755,12 +13078,12 @@ These identities will soon be not supported anymore. - + Font size - + Increase font size @@ -12775,32 +13098,32 @@ These identities will soon be not supported anymore. - + Italic - + Alignment - + Add an Image - + Sets text font to code style - + Underline - + Subject: @@ -12811,32 +13134,32 @@ These identities will soon be not supported anymore. - + Tags - + Address list: - + Recommend this friend - + Set Text color - + Set Text background color - + Recommended Files @@ -12906,7 +13229,7 @@ These identities will soon be not supported anymore. - + Send To: @@ -12946,7 +13269,7 @@ These identities will soon be not supported anymore. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> @@ -12966,18 +13289,18 @@ These identities will soon be not supported anymore. - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team - - + + Save Message - + Message has not been Sent. Do you want to save message to draft box? @@ -12988,7 +13311,17 @@ Do you want to save message to draft box? - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" @@ -13008,7 +13341,7 @@ Do you want to save message to draft box? - + Original Message @@ -13018,21 +13351,21 @@ Do you want to save message to draft box? - + - + To - - + + Cc - + Sent @@ -13047,7 +13380,7 @@ Do you want to save message to draft box? - + Re: @@ -13057,30 +13390,30 @@ Do you want to save message to draft box? - - - + + + RetroShare - + Do you want to send the message without a subject ? - + Please insert at least one recipient. - + Bcc - + Unknown @@ -13195,13 +13528,13 @@ Do you want to save message to draft box? - + Open File... - + HTML-Files (*.htm *.html);;All Files (*) @@ -13221,7 +13554,7 @@ Do you want to save message to draft box? - + Message has not been Sent. Do you want to save message ? @@ -13242,7 +13575,7 @@ Do you want to save message ? - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -13272,18 +13605,18 @@ Do you want to save message ? - - + + Close - + From: - + Bullet list (disc) @@ -13323,13 +13656,13 @@ Do you want to save message ? - - + + Thanks, <br> - + Distant identity: @@ -13339,12 +13672,12 @@ Do you want to save message ? - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -13422,7 +13755,7 @@ Do you want to save message ? - + A new tab @@ -13432,7 +13765,7 @@ Do you want to save message ? - + Edit Tag @@ -13455,7 +13788,7 @@ Do you want to save message ? MessageToaster - + Sub: @@ -13463,7 +13796,7 @@ Do you want to save message ? MessageUserNotify - + Message @@ -13491,7 +13824,7 @@ Do you want to save message ? MessageWidget - + Recommended Files @@ -13501,37 +13834,37 @@ Do you want to save message ? - + Subject: - + From: - + To: - + Cc: - + Bcc: - + Tags: - + Reply @@ -13571,7 +13904,7 @@ Do you want to save message ? - + Send Invite @@ -13623,7 +13956,7 @@ Do you want to save message ? - + Confirm %1 as friend @@ -13633,12 +13966,12 @@ Do you want to save message ? - + View source - + No subject @@ -13648,17 +13981,22 @@ Do you want to save message ? - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -13667,14 +14005,24 @@ Do you want to save message ? %1 (%2) + + + Show less + + + + + Show more + + - + Download all - + Print Document @@ -13689,12 +14037,12 @@ Do you want to save message ? - + Load images always for this message - + Hide the attachment pane @@ -13794,7 +14142,7 @@ Do you want to save message ? MessagesDialog - + New Message @@ -13804,16 +14152,16 @@ Do you want to save message ? - + - - + + Tags - - + + Inbox @@ -13843,17 +14191,17 @@ Do you want to save message ? - + Total Inbox: - + Quick View - + Print... @@ -13884,7 +14232,7 @@ Do you want to save message ? - + Subject @@ -13894,7 +14242,7 @@ Do you want to save message ? - + Date @@ -13904,7 +14252,7 @@ Do you want to save message ? - + Search Subject @@ -13913,6 +14261,16 @@ Do you want to save message ? Search From + + + To + + + + + Search To + + Search Date @@ -13939,12 +14297,12 @@ Do you want to save message ? - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred @@ -14020,7 +14378,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -14034,7 +14392,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -14049,18 +14407,28 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts - + No Box selected. - + @@ -14095,7 +14463,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -14149,7 +14527,7 @@ Do you want to save message ? - + Expand @@ -14159,7 +14537,7 @@ Do you want to save message ? - + from @@ -14194,7 +14572,7 @@ Do you want to save message ? - + Hide @@ -14335,7 +14713,7 @@ Do you want to save message ? - + Remove unused keys... @@ -14345,7 +14723,7 @@ Do you want to save message ? - + Clean keyring @@ -14359,7 +14737,13 @@ Notes: Your old keyring will be backed up. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info @@ -14392,18 +14776,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. - - - Export/create a new node - - Trusted keys only - + Search name @@ -14413,12 +14792,12 @@ For security, your keyring was previously backed-up to file - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -14451,7 +14830,7 @@ Reported error: NewFriendList - + Offline Friends @@ -14472,7 +14851,7 @@ Reported error: - + Groups @@ -14502,19 +14881,19 @@ Reported error: - - + + Search - + ID - + Search ID @@ -14524,12 +14903,12 @@ Reported error: - + Show Items - + Last contact @@ -14539,7 +14918,7 @@ Reported error: - + Group @@ -14654,7 +15033,7 @@ Reported error: - + Do you want to remove this node? @@ -14664,7 +15043,7 @@ Reported error: - + Done! @@ -14771,7 +15150,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -14786,7 +15165,7 @@ at least one peer was not added to a group - + Newest on top @@ -14796,12 +15175,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15039,7 +15418,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -15059,12 +15438,12 @@ at least one peer was not added to a group - + Please enter your Retroshare passphrase - + Unregistered plugin/executable @@ -15079,7 +15458,7 @@ at least one peer was not added to a group - + Test @@ -15090,17 +15469,19 @@ at least one peer was not added to a group + Unknown title - + + Encrypted message - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -15108,7 +15489,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online @@ -15247,7 +15628,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -15292,12 +15678,7 @@ p, li { white-space: pre-wrap; } - - Options - - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -15343,21 +15724,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare - - + + Error : cannot get peer details. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) @@ -15375,7 +15756,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -15451,12 +15832,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -15482,7 +15863,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat @@ -15503,7 +15884,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Name: @@ -15543,7 +15924,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message @@ -15601,7 +15982,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Send Message @@ -15919,17 +16300,17 @@ p, li { white-space: pre-wrap; } - + My Albums - + Subscribed Albums - + Shared Albums @@ -15958,7 +16339,7 @@ requesting to edit it! PhotoSlideShow - + Album Name @@ -16017,19 +16398,19 @@ requesting to edit it! - - + + TextLabel - + Posted by - + ago @@ -16065,12 +16446,12 @@ requesting to edit it! PluginItem - + TextLabel - + Show more details about this plugin @@ -16281,12 +16662,27 @@ p, li { white-space: pre-wrap; } - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -16339,7 +16735,7 @@ p, li { white-space: pre-wrap; } - + Vote up @@ -16359,8 +16755,8 @@ p, li { white-space: pre-wrap; } - - + + Comments @@ -16385,13 +16781,13 @@ p, li { white-space: pre-wrap; } - - + + Comment - + Comments @@ -16419,12 +16815,12 @@ p, li { white-space: pre-wrap; } PostedCreatePostDialog - + Create a new Post - + RetroShare @@ -16439,12 +16835,22 @@ p, li { white-space: pre-wrap; } - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File - + Post image @@ -16460,7 +16866,17 @@ p, li { white-space: pre-wrap; } - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -16470,7 +16886,7 @@ p, li { white-space: pre-wrap; } - + Please add a Title @@ -16490,12 +16906,22 @@ p, li { white-space: pre-wrap; } - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -16510,7 +16936,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -16521,7 +16947,7 @@ p, li { white-space: pre-wrap; } - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -16531,7 +16957,7 @@ p, li { white-space: pre-wrap; } - + Link @@ -16539,12 +16965,12 @@ p, li { white-space: pre-wrap; } PostedDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -16578,7 +17004,7 @@ p, li { white-space: pre-wrap; } PostedGroupDialog - + Create New Board @@ -16616,7 +17042,17 @@ p, li { white-space: pre-wrap; } PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted @@ -16632,7 +17068,7 @@ p, li { white-space: pre-wrap; } - + Expand @@ -16647,12 +17083,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + + Never + + + + New Board @@ -16665,18 +17106,18 @@ p, li { white-space: pre-wrap; } PostedItem - + 0 - - + + Comments - + Copy RetroShare Link @@ -16687,12 +17128,12 @@ p, li { white-space: pre-wrap; } - + Comment - + Comments @@ -16702,7 +17143,7 @@ p, li { white-space: pre-wrap; } - + Click to view Picture @@ -16712,17 +17153,17 @@ p, li { white-space: pre-wrap; } - + Vote up - + Vote down - + Set as read and remove item @@ -16732,7 +17173,7 @@ p, li { white-space: pre-wrap; } - + New Comment: @@ -16742,7 +17183,7 @@ p, li { white-space: pre-wrap; } - + Name @@ -16783,7 +17224,7 @@ p, li { white-space: pre-wrap; } - + Loading @@ -16806,7 +17247,17 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 @@ -16816,15 +17267,15 @@ p, li { white-space: pre-wrap; } - + - + unknown - + Distribution: @@ -16834,42 +17285,42 @@ p, li { white-space: pre-wrap; } - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -16889,7 +17340,7 @@ p, li { white-space: pre-wrap; } - + Search @@ -16919,17 +17370,17 @@ p, li { white-space: pre-wrap; } - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -16944,12 +17395,17 @@ p, li { white-space: pre-wrap; } - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -16959,27 +17415,31 @@ p, li { white-space: pre-wrap; } - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -16994,7 +17454,7 @@ p, li { white-space: pre-wrap; } - + Never @@ -17068,6 +17528,16 @@ p, li { white-space: pre-wrap; } No Channel Selected + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -17157,16 +17627,16 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -17274,7 +17744,7 @@ and use the import button to load it ProfileWidget - + Edit status message @@ -17290,7 +17760,7 @@ and use the import button to load it - + Public Information @@ -17325,12 +17795,12 @@ and use the import button to load it - + Other Information - + My Address @@ -17374,27 +17844,27 @@ and use the import button to load it PulseAddDialog - + Add to Pulse - + Display As - + URL - + GroupLabel - + IDLabel @@ -17404,12 +17874,12 @@ and use the import button to load it - + Head - + Head Shot @@ -17439,13 +17909,13 @@ and use the import button to load it - - + + Whats happening? - + @@ -17457,12 +17927,22 @@ and use the import button to load it - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -17477,7 +17957,7 @@ and use the import button to load it - + Reply to Pulse @@ -17492,20 +17972,25 @@ and use the import button to load it - + Like Pulse - + Hide Pictures - + Add Pictures + + + Load Picture File + + PulseMessage @@ -17515,7 +18000,7 @@ and use the import button to load it - + @@ -17534,7 +18019,7 @@ and use the import button to load it PulseReply - + icn @@ -17544,7 +18029,7 @@ and use the import button to load it - + REPLY @@ -17571,7 +18056,7 @@ and use the import button to load it - + FOLLOW @@ -17581,7 +18066,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -17601,7 +18086,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -17717,7 +18202,7 @@ and use the import button to load it - + FOLLOW @@ -17725,37 +18210,42 @@ and use the import button to load it PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -17787,7 +18277,7 @@ and use the import button to load it - + FOLLOW @@ -17795,8 +18285,8 @@ and use the import button to load it QObject - - + + Confirmation @@ -18064,12 +18554,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + File Request canceled - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. @@ -18100,7 +18590,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + Cannot start Tor Manager! @@ -18134,7 +18624,7 @@ The error reported is:" - + Multiple instances @@ -18153,6 +18643,26 @@ The error reported is:" + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -18232,7 +18742,7 @@ Reported error is: - + You appear to have nodes associated to DSA keys: @@ -18242,7 +18752,7 @@ Reported error is: - + enabled @@ -18252,7 +18762,7 @@ Reported error is: - + Move IP %1 to whitelist @@ -18268,7 +18778,7 @@ Reported error is: - + %1 seconds ago @@ -18335,7 +18845,7 @@ Security: no anonymous IDs - + Join chat room @@ -18363,7 +18873,7 @@ Security: no anonymous IDs - + Indefinitely @@ -18544,12 +19054,28 @@ Security: no anonymous IDs - - Status + + Name + Node + + + + + Address + + + + + + Status + + + + NXS @@ -18792,6 +19318,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -18931,7 +19469,7 @@ p, li { white-space: pre-wrap; } - + Network Wide @@ -19098,7 +19636,7 @@ p, li { white-space: pre-wrap; } - + The loading of embedded images is blocked. @@ -19111,7 +19649,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default @@ -19284,12 +19822,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -19297,12 +19845,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -19990,7 +20538,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name @@ -20111,7 +20659,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name @@ -20131,7 +20679,7 @@ If you believe it is correct, remove the corresponding line from the file and re - + Profile ID @@ -20187,7 +20735,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -20201,11 +20749,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - - RsMessageModel @@ -20219,6 +20762,11 @@ prevents the message to be forwarded to your friends. From + + + To + + Subject @@ -20241,12 +20789,17 @@ prevents the message to be forwarded to your friends. - Click to sort by read + Click to sort by read status - Click to sort by from + Click to sort by author + + + + + Click to sort by destination @@ -20270,7 +20823,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -20291,7 +20846,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. @@ -20352,7 +20907,7 @@ prevents the message to be forwarded to your friends. - + Unable to open log file '%1': %2 @@ -20373,7 +20928,7 @@ prevents the message to be forwarded to your friends. - + opmode @@ -20403,7 +20958,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -20421,7 +20976,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -20438,12 +20993,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) - + Start Search @@ -20504,7 +21059,7 @@ prevents the message to be forwarded to your friends. - + KeyWords @@ -20519,7 +21074,7 @@ prevents the message to be forwarded to your friends. - + Filename @@ -20619,23 +21174,23 @@ prevents the message to be forwarded to your friends. - + File Name - + Download - + Copy RetroShare Link - + Send RetroShare Link @@ -20645,7 +21200,7 @@ prevents the message to be forwarded to your friends. - + Download Notice @@ -20682,7 +21237,7 @@ prevents the message to be forwarded to your friends. - + Folder @@ -20693,17 +21248,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) - + Open Folder - + Create Collection... @@ -20723,7 +21278,7 @@ prevents the message to be forwarded to your friends. - + Collection @@ -20731,7 +21286,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details @@ -20747,22 +21302,22 @@ prevents the message to be forwarded to your friends. - + IP address: - + Peer ID: - + Location: - + Peer Name: @@ -20779,7 +21334,7 @@ prevents the message to be forwarded to your friends. - + but reported: @@ -20804,8 +21359,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -20813,7 +21368,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare @@ -20844,7 +21399,7 @@ prevents the message to be forwarded to your friends. - + Expand @@ -20889,12 +21444,12 @@ prevents the message to be forwarded to your friends. - + Write Message - + Connect Attempt @@ -20914,17 +21469,12 @@ prevents the message to be forwarded to your friends. - + Unknown Security Issue - - A unknown peer - - - - + Unknown @@ -20934,7 +21484,17 @@ prevents the message to be forwarded to your friends. - + + SSL request + + + + + An unknown peer + + + + Hide @@ -20944,7 +21504,7 @@ prevents the message to be forwarded to your friends. - + Certificate has wrong signature!! This peer is not who he claims to be. @@ -20954,12 +21514,12 @@ prevents the message to be forwarded to your friends. - + Certificate caused an internal error. - + Peer/node not in friendlist (PGP id= @@ -21018,12 +21578,12 @@ prevents the message to be forwarded to your friends. - + Local Address - + NAT @@ -21044,22 +21604,22 @@ prevents the message to be forwarded to your friends. - + Local network - + External ip address finder - + UPnP - + Known / Previous IPs: @@ -21072,21 +21632,16 @@ behind a firewall or a VPN. - - Allow RetroShare to ask my ip to these websites: - - - - - - + + + kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -21096,23 +21651,46 @@ behind a firewall or a VPN. - + Onion Address - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -21122,7 +21700,7 @@ behind a firewall or a VPN. - + I2P Address @@ -21147,37 +21725,95 @@ behind a firewall or a VPN. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -21192,71 +21828,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -21266,22 +21838,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -21293,12 +21850,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -21308,7 +21865,7 @@ Also check your ports! - + Download limit (KB/s) @@ -21323,23 +21880,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -21350,17 +21907,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -21370,12 +21917,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -21385,17 +21927,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -21435,7 +21967,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start @@ -21450,12 +21982,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - BOB status - - - - + Incoming @@ -21491,7 +22018,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -21546,7 +22098,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Warning: This bandwidth adds up to the max bandwidth. @@ -21571,7 +22123,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -21583,7 +22135,7 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Filters @@ -21606,7 +22158,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status @@ -21666,17 +22218,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -21692,18 +22255,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -21738,12 +22301,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -21766,22 +22329,22 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -21816,7 +22379,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -21826,12 +22389,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -21911,7 +22474,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with @@ -21921,12 +22484,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Share - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -21945,7 +22508,7 @@ Select the Friends with which you want to Share your Channel. - + Shared directory @@ -21965,17 +22528,17 @@ Select the Friends with which you want to Share your Channel. - + Add new - + Cancel - + Add a Share Directory @@ -21985,7 +22548,7 @@ Select the Friends with which you want to Share your Channel. - + Apply and close @@ -22076,7 +22639,7 @@ Select the Friends with which you want to Share your Channel. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. @@ -22084,7 +22647,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files @@ -22135,11 +22698,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files - + Download selected @@ -22149,7 +22717,7 @@ Select the Friends with which you want to Share your Channel. - + Copy retroshare Links to Clipboard @@ -22164,7 +22732,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted @@ -22180,7 +22748,7 @@ Select the Friends with which you want to Share your Channel. - + Create Collection... @@ -22205,7 +22773,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted because they have not been indexed yet. @@ -22348,12 +22916,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration - + Create interface @@ -22377,7 +22945,7 @@ Select the Friends with which you want to Share your Channel. - + Log In @@ -22716,7 +23284,7 @@ This choice can be reverted in settings. - + Message: @@ -22953,7 +23521,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags @@ -22989,12 +23557,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown @@ -23004,18 +23575,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -23025,12 +23591,57 @@ p, li { white-space: pre-wrap; } - + + Error + + + + + Not connected + + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -23038,7 +23649,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -23048,7 +23659,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -23059,11 +23670,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -23091,7 +23703,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options @@ -23102,7 +23714,7 @@ p, li { white-space: pre-wrap; } - + Shared Directories @@ -23112,22 +23724,27 @@ p, li { white-space: pre-wrap; } - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -23212,7 +23829,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -23221,7 +23838,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -23246,7 +23868,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming @@ -23311,12 +23938,7 @@ p, li { white-space: pre-wrap; } - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -23326,7 +23948,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -23354,7 +23986,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed @@ -23382,19 +24014,19 @@ p, li { white-space: pre-wrap; } TransfersDialog - - + + Downloads - + Uploads - + Name i.e: file name @@ -23601,7 +24233,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... @@ -23626,7 +24263,7 @@ p, li { white-space: pre-wrap; } - + Anonymous end-to-end encrypted tunnel 0x @@ -23647,7 +24284,7 @@ p, li { white-space: pre-wrap; } - + @@ -23680,7 +24317,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name @@ -23695,7 +24342,7 @@ p, li { white-space: pre-wrap; } - + Expand all @@ -23822,23 +24469,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns - + File Transfers - + Path @@ -23848,7 +24490,7 @@ p, li { white-space: pre-wrap; } - + Could not delete preview file @@ -23858,7 +24500,7 @@ p, li { white-space: pre-wrap; } - + Create Collection... @@ -23873,7 +24515,7 @@ p, li { white-space: pre-wrap; } - + Collection @@ -23883,7 +24525,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x @@ -24297,12 +24939,17 @@ p, li { white-space: pre-wrap; } - + Enable Retroshare WEB Interface - + + Status: + + + + Web parameters @@ -24342,17 +24989,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -24362,12 +25019,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface @@ -24504,7 +25161,7 @@ p, li { white-space: pre-wrap; } - + Page Name @@ -24519,7 +25176,7 @@ p, li { white-space: pre-wrap; } - + << @@ -24607,7 +25264,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History @@ -24642,7 +25299,7 @@ p, li { white-space: pre-wrap; } - + \/ @@ -24672,14 +25329,18 @@ p, li { white-space: pre-wrap; } - - + + History + + + + Show Edit History - + Status @@ -24700,7 +25361,7 @@ p, li { white-space: pre-wrap; } - + Submit @@ -24783,12 +25444,7 @@ p, li { white-space: pre-wrap; } - - Refresh - - - - + Settings @@ -24803,7 +25459,7 @@ p, li { white-space: pre-wrap; } - + Who to Follow @@ -24823,7 +25479,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -24853,7 +25509,7 @@ p, li { white-space: pre-wrap; } - + Yourself @@ -24863,7 +25519,7 @@ p, li { white-space: pre-wrap; } - + RetroShare @@ -24926,35 +25582,42 @@ p, li { white-space: pre-wrap; } - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + + + + Location: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -24999,11 +25662,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + + + + + Following + + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) @@ -25081,7 +25774,7 @@ p, li { white-space: pre-wrap; } - + k e.g: 3.1 k @@ -25118,7 +25811,7 @@ p, li { white-space: pre-wrap; } pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_es.qm b/retroshare-gui/src/lang/retroshare_es.qm index c0d639a4c..782b9d443 100644 Binary files a/retroshare-gui/src/lang/retroshare_es.qm and b/retroshare-gui/src/lang/retroshare_es.qm differ diff --git a/retroshare-gui/src/lang/retroshare_es.ts b/retroshare-gui/src/lang/retroshare_es.ts index 3df49a47e..cc21a60c3 100644 --- a/retroshare-gui/src/lang/retroshare_es.ts +++ b/retroshare-gui/src/lang/retroshare_es.ts @@ -84,13 +84,6 @@ Sólo nodo oculto - - AddCommentDialog - - Add Comment - Añadir un comentario - - AddFileAssociationDialog @@ -129,12 +122,12 @@ RetroShare: Búsqueda avanzada - + Search Criteria Criterios de búsqueda - + Add a further search criterion. Añadir un criterio de búsqueda adicional. @@ -144,7 +137,7 @@ Reinicializa el criterio de búsqueda. - + Cancels the search. Cancela la búsqueda. @@ -164,177 +157,6 @@ Buscar - - AlbumCreateDialog - - Create Album - Crear álbum - - - Album Name: - Nombre del álbum: - - - Category: - Categoría: - - - Animals - Animales - - - Family - Familia - - - Friends - Amigos - - - Flowers - Flores - - - Holiday - Festivo - - - Landscapes - Paisajes - - - Pets - Mascotas - - - Portraits - Retratos - - - Travel - Viajes - - - Work - Trabajo - - - Random - Aleatorio - - - Caption: - Título: - - - Where: - Dónde: - - - Photographer: - Fotógrafo: - - - Description: - Descripción: - - - Share Options - Opciones de compartición - - - Policy: - Política: - - - Quality: - Calidad: - - - Comments: - Comentarios: - - - Identity: - Identidad: - - - Public - Público - - - Restricted - Restringido - - - Resize Images (< 1Mb) - Redimensionar imágenes (< 1Mb) - - - Resize Images (< 10Mb) - Redimensionar imágenes (< 10Mb) - - - Send Original Images - Enviar imágenes originales - - - No Comments Allowed - No se permiten comentarios - - - Authenticated Comments - Comentarios autenticados - - - Any Comments Allowed - Permitir cualquier comentario - - - Publish with Identity - Publicar con identidad - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> - <html><head><meta name="qrichtext" content="1" /><style type="text/css"> - p, li { white-space: pre-wrap; } - </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> - <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Arrastrar y soltar para insertar imágenes. A continuación pulse en una imagen para editar los detalles.</span></p></body></html> - - - Back - Atrás - - - Add Photos - Añadir fotos - - - Publish Album - Publicar álbum - - - Untitle Album - Álbum sin título - - - Say something about this album... - Diga algo sobre este álbum... - - - Where were these taken? - ¿Dónde estaban tomadas? - - - Load Album Thumbnail - Cargar miniatura del álbum - - AlbumDialog @@ -343,19 +165,11 @@ p, li { white-space: pre-wrap; } Album Álbum - - Album Thumbnail - Miniatura del álbum - TextLabel Texto de la etiqueta - - Summary - Resumen - Album Title: @@ -371,34 +185,6 @@ p, li { white-space: pre-wrap; } Caption Título - - Where: - Dónde: - - - When - Cuándo - - - Description: - Descripción: - - - Share Options - Opciones de compartición - - - Comments - Comentarios - - - Publish Identity - Publicar identidad - - - Visibility - Visibilidad - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -483,7 +269,7 @@ p, li { white-space: pre-wrap; } Where: - + Donde: @@ -767,7 +553,7 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. Advertencia: Los servicios aquí son experimentales. Por favor, ayúdenos a probarlos. @@ -783,14 +569,6 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro Circles Círculos - - GxsForums - GxsForos - - - GxsChannels - GxsCanales - The Wire @@ -802,10 +580,23 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro Fotos + + AspectRatioPixmapLabel + + + Save image + Guardar imagen + + + + Copy image + + + AttachFileItem - + %p Kb %p Kb @@ -842,17 +633,13 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro Browse... - - Add Avatar - Añadir avatar - Remove Eliminar - + Set your Avatar picture Establecer imagen de avatar @@ -871,10 +658,6 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - Cargar avatar - AvatarWidget @@ -943,22 +726,10 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro Reinicializar - Receive Rate - Tasa de recepción - - - Send Rate - Tasa de envío - - - + Always on Top Siempre encima - - Style - Estilo - Changes the transparency of the Bandwidth Graph @@ -974,23 +745,11 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro % Opaque % Transparencia - - Save - Guardar - - - Cancel - Cancelar - Since: Desde: - - Hide Settings - Ocultar ajustes - BandwidthStatsWidget @@ -1063,7 +822,7 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro BoardPostDisplayWidgetBase - + Comment Comentario @@ -1093,12 +852,12 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro Copiar enlace de RetroShare - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> <p><font color="#ff0000"><b>El autor de este mensaje (con Identificación %1) está excluído.</b> - + ago @@ -1106,7 +865,7 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro BoardPostDisplayWidget_card - + Vote up Votar positivo @@ -1126,7 +885,7 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro \/ - + Posted by @@ -1164,7 +923,7 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro BoardPostDisplayWidget_compact - + Vote up Votar positivo @@ -1184,7 +943,7 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro \/ - + Click to view picture @@ -1214,7 +973,7 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro Compartir - + Toggle Message Read Status Cambiar el estado de lectura del mensaje @@ -1224,7 +983,7 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro Nuevo - + TextLabel @@ -1232,12 +991,12 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro BoardsCommentsItem - + I like this Esto me gusta - + 0 0 @@ -1257,18 +1016,18 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro Avatar - + New Comment - + Copy RetroShare Link Copiar enlace de RetroShare - + Expand @@ -1283,12 +1042,12 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro - + Name Nombre - + Comm value @@ -1457,17 +1216,17 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro ChannelPage - + Channels Canales - + Tabs Pestañas - + General General @@ -1477,11 +1236,17 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro - Load posts in background (Thread) - Cargar mensajes en segundo plano (hilo) + + Downloads + Descargas - + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab Abrir cada canal en una nueva pestaña @@ -1489,7 +1254,7 @@ Pero recuerde: Todos los datos aquí *SE PERDERÁN* cuando se actualicen los pro ChannelPostDelegate - + files @@ -1512,7 +1277,7 @@ into the image, so as to ChannelsCommentsItem - + I like this Esto me gusta @@ -1537,18 +1302,18 @@ into the image, so as to Avatar - + New Comment - + Copy RetroShare Link Copiar enlace de RetroShare - + Expand @@ -1563,7 +1328,7 @@ into the image, so as to - + Name Nombre @@ -1573,17 +1338,7 @@ into the image, so as to - - Comment - Comentario - - - - Comments - Comentarios - - - + Hide Ocultar @@ -1591,7 +1346,7 @@ into the image, so as to ChatLobbyDialog - + Name Nombre @@ -1782,7 +1537,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby Mostrar sala de chat @@ -1794,22 +1549,6 @@ into the image, so as to Chats Chats - - You have %1 new messages - Tiene %1 nuevos mensajes - - - You have %1 new message - Tiene %1 nuevo mensaje - - - %1 new messages - %1 nuevos mensajes - - - %1 new message - %1 nuevo mensaje - You have %1 mentions @@ -1831,13 +1570,14 @@ into the image, so as to - + + Unknown Lobby Sala desconocida - - + + Remove All Borrar todo @@ -1845,13 +1585,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Nombre - + Count Recuento @@ -1861,33 +1601,7 @@ into the image, so as to Tema - - Private Subscribed chat rooms - Salas de chat privadas suscritas - - - - - Public Subscribed chat rooms - Salas de chat públicas suscritas - - - - Private chat rooms - Salas de chat privadas - - - - - Public chat rooms - Salas de chat públicas - - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/images/add_24x24.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Salas de chat</h1> <p>Las salas de chat funcionan de forma bastante parecida al IRC. Le permiten hablar de forma anónima con montones de personas sin necesidad de hacer amigos.</p> <p>Una sala de chat puede ser pública (sus amigos la ven) o privada (sus amigos no pueden verla, a menos que les invite con <img src=":/images/add_24x24.png" width=%2/>). Una vez haya sido invitado a una sala privada, podrá verla cuando la estén usando sus amigos.</p> <p>La lista de la izquierda muestra salas de chat en las que están participando sus amigos. Puede <ul> <li>Hacer clic para crear una nueva sala de chat</li> <li>Hacer doble clic en una sala de chat para entrar, chatear, y mostrarla a sus amigos.</li> </ul> Aviso: Para que las salas de chat funcionen adecuadamente, su computadora tiene que estar en hora. ¡Compruebe el reloj de su sistema! </p> - - - + Create chat room Crear sala de chat @@ -1897,7 +1611,7 @@ into the image, so as to Abandonar esta sala - + Create a non anonymous identity and enter this room Crear una identidad no anónima y entrar en esta sala @@ -1956,12 +1670,12 @@ Seleccione salas de chat a la izquierda para mostrar detalles. Haga doble clic en una sala de chat para entrar y conversar. - + %1 invites you to chat room named %2 %1 le invita a una sala de chat llamada %2 - + Choose a non anonymous identity for this chat room: Escoja una identidad no anónima para esta sala de chat: @@ -1971,31 +1685,31 @@ Haga doble clic en una sala de chat para entrar y conversar. Escoja una identidad para esta sala de chat: - Create chat lobby - Crear sala de chat - - - + [No topic provided] [No se ha proporcionado tema] - Selected lobby info - Información sobre la sala - - - + + Private Privada - + + + Public Pública - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted Identificaciones anónimas aceptadas @@ -2005,42 +1719,25 @@ Haga doble clic en una sala de chat para entrar y conversar. Suprimir autosuscripción - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe Añadir autosuscripción - + Search Chat lobbies Buscar salas de chat - + Search Name Buscar por nombre - Subscribed - Suscrito - - - + Columns Columnas - - Yes - - - - No - No - Chat rooms @@ -2052,47 +1749,47 @@ Haga doble clic en una sala de chat para entrar y conversar. - + Chat Room info - + Chat room Name: Nombre de la sala de chat: - + Chat room Id: Identificador de la sala de chat: - + Topic: Tema: - + Type: Tipo: - + Security: Seguridad: - + Peers: Vecinos: - - - - - - + + + + + + TextLabel Etiqueta de texto @@ -2107,13 +1804,24 @@ Haga doble clic en una sala de chat para entrar y conversar. Sin identificaciones anónimas - + Show Mostrar - + + Private Subscribed + + + + + + Public Subscribed + + + + column columna @@ -2127,7 +1835,7 @@ Haga doble clic en una sala de chat para entrar y conversar. ChatMsgItem - + Remove Item Eliminar elemento @@ -2172,46 +1880,22 @@ Haga doble clic en una sala de chat para entrar y conversar. ChatPage - + General General - - Distant Chat - Chat distante - Everyone Todos - - Contacts - Contactos - Nobody Nadie - Accept encrypted distant chat from - Aceptar chat distante cifrado de - - - Chat Settings - Ajustes del chat - - - Enable Emoticons Private Chat - Habilitar emoticonos en conversación privada - - - Enable Emoticons Group Chat - Habilitar emoticonos en conversación en grupo - - - + Enable custom fonts Habilitar fuentes personalizadas @@ -2220,10 +1904,6 @@ Haga doble clic en una sala de chat para entrar y conversar. Enable custom font size Habilitar tamaño de fuente personalizado - - Minimum font size - Tamaño mínimo de fuente - Enable bold @@ -2235,7 +1915,7 @@ Haga doble clic en una sala de chat para entrar y conversar. Habilitar cursiva - + General settings @@ -2260,11 +1940,7 @@ Haga doble clic en una sala de chat para entrar y conversar. Cargar imágenes incrustadas - Chat Lobby - Sala de chat - - - + Blink tab icon Icono de pestaña intermitente @@ -2273,10 +1949,6 @@ Haga doble clic en una sala de chat para entrar y conversar. Do not send typing notifications No enviar notificaciones de actividad de escritura - - Private Chat - Chat privado - Open Window for new chat @@ -2298,11 +1970,7 @@ Haga doble clic en una sala de chat para entrar y conversar. Icono de ventana/pestaña intermitente - Chat Font - Fuente del chat - - - + Change Chat Font Cambiar fuente del chat @@ -2312,14 +1980,10 @@ Haga doble clic en una sala de chat para entrar y conversar. Fuente del chat: - + History Historial - - Style - Estilo - @@ -2334,17 +1998,13 @@ Haga doble clic en una sala de chat para entrar y conversar. Variant: Variante: - - Group chat - Chat en grupo - Private chat Chat privado - + Choose your default font for Chat. Escoja su fuente predeterminada para Chat. @@ -2408,22 +2068,28 @@ Haga doble clic en una sala de chat para entrar y conversar. <html><head/><body><p align="justify">In this tab you can setup how many chat messages Retroshare will keep saved on the disc and how much of the previous conversation it will display, for the different chat systems. The max storage period allows to discard old messages and prevents the chat history from filling up with volatile chat (e.g. chat lobbies and distant chat).</p></body></html> <html><head/><body><p align="justify">En esta pestaña puedes configurar cuantos mensajes guardará en disco RetroShare y cuantas conversaciones previas mostrará para los distintos sistemas de chateo. El periodo máximo de almacenado permite eliminar mensajes viejos y evita que el historial de chateo se llene de conversaciones intrascendentes (salas de chateo y chateo distante)</p></body></html> - - Chatlobbies - Salasdechat - Enabled: Habilitar: - + Search Buscar - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2433,7 +2099,17 @@ Haga doble clic en una sala de chat para entrar y conversar. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms Salas de chat @@ -2530,11 +2206,7 @@ Haga doble clic en una sala de chat para entrar y conversar. Máximo periodo de almacenamiento, en días (0=mantener todo): - Search by default - Búsqueda por defecto - - - + Case sensitive Discriminar minúsculas/mayúsculas @@ -2573,10 +2245,6 @@ Haga doble clic en una sala de chat para entrar y conversar. Threshold for automatic search Umbral para búsqueda automática - - Default identity for chat lobbies: - Identidad por defecto para las salas de conversación: - Show Bar by default @@ -2644,7 +2312,7 @@ Haga doble clic en una sala de chat para entrar y conversar. ChatToaster - + Show Chat Mostrar chat @@ -2680,7 +2348,7 @@ Haga doble clic en una sala de chat para entrar y conversar. ChatWidget - + Close Cerrar @@ -2715,12 +2383,12 @@ Haga doble clic en una sala de chat para entrar y conversar. Cursiva - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon Insertar emoticono @@ -2729,10 +2397,6 @@ Haga doble clic en una sala de chat para entrar y conversar. Attach a Picture Adjuntar una imagen - - <html><head/><body><p>QToolButton:disabled {</p><p> image: url(:/icons/png/send-message-blocked.png) ;</p><p>}</p><p><br/></p></body></html> - <html><head/><body><p>QToolButton:disabled {</p><p> image: url(:/icons/png/send-message-blocked.png) ;</p><p>}</p><p><br/></p></body></html> - Strike @@ -2804,11 +2468,6 @@ Haga doble clic en una sala de chat para entrar y conversar. Insert horizontal rule Insertar regla horizontal - - - Save image - Guardar imagen - Import sticker @@ -2846,7 +2505,7 @@ Haga doble clic en una sala de chat para entrar y conversar. - + is typing... está escribiendo... @@ -2870,7 +2529,7 @@ after HTML conversion. Escoja su fuente. - + Do you really want to physically delete the history? ¿Seguro que quiere borrar el historial? @@ -2920,7 +2579,7 @@ after HTML conversion. está ocupado e igual no contesta - + Find Case Sensitively Buscar discriminando mayúsculas/minúsculas @@ -2942,7 +2601,7 @@ after HTML conversion. No detenerse a colorear después de que X elementos se encontrasen (necesita más CPU) - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> <b>Buscar anterior</b><br/><i>Ctrl+Mayús+G</i> @@ -2957,16 +2616,12 @@ after HTML conversion. <b>Buscar </b><br/><i>Ctrl+F</i> - + (Status) (Estado) - Set text font & color - Configurar fuente de texto y color - - - + Attach a File Adjuntar un archivo @@ -2982,12 +2637,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> <b>Marcar este texto seleccionado</b><br><i>Ctrl+M</i> - + Person id: Identificación persona: @@ -2999,12 +2654,12 @@ Double click on it to add his name on text writer. Haga doble clic sobre este para añadir su nombre en el compositor de texto. - + Unsigned No firmado - + items found. elementos encontrados. @@ -3024,7 +2679,7 @@ Haga doble clic sobre este para añadir su nombre en el compositor de texto.Escriba un mensaje aquí - + Don't stop to color after No parar de colorear tras @@ -3050,7 +2705,7 @@ Haga doble clic sobre este para añadir su nombre en el compositor de texto. CirclesDialog - + Showing details: Mostrando detalles: @@ -3072,7 +2727,7 @@ Haga doble clic sobre este para añadir su nombre en el compositor de texto. - + Personal Circles Círculos personales @@ -3098,7 +2753,7 @@ Haga doble clic sobre este para añadir su nombre en el compositor de texto. - + Friends Amigos @@ -3158,7 +2813,7 @@ Haga doble clic sobre este para añadir su nombre en el compositor de texto.Amigos de sus amigos - + External Circles (Admin) Círculos externos (Admin) @@ -3174,7 +2829,7 @@ Haga doble clic sobre este para añadir su nombre en el compositor de texto. - + Circles Círculos @@ -3226,43 +2881,48 @@ Haga doble clic sobre este para añadir su nombre en el compositor de texto. - + RetroShare RetroShare - + - + Error : cannot get peer details. Error: No se pueden obtener los detalles del vecino. - + Retroshare ID - + <p>This Retroshare ID contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: + + + <b>DNS:</b> : + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3274,7 +2934,7 @@ Haga doble clic sobre este para añadir su nombre en el compositor de texto.Cifrado - + Not connected No conectado @@ -3356,25 +3016,17 @@ Haga doble clic sobre este para añadir su nombre en el compositor de texto.ninguno - + <p>This certificate contains: <p>Este certificado contiene: - + <li>a <b>node ID</b> and <b>name</b> <li>una <b>identificación de nodo</b> y <b>nombre</b> - an <b>onion address</b> and <b>port</b> - una <b>dirección .onion</b> y <b>puerto</b> - - - an <b>IP address</b> and <b>port</b> - una <b>dirección IP</b> y <b>puerto</b> - - - + <p>You can use this certificate to make new friends. Send it by email, or give it hand to hand.</p> <p>Puede usar este certificado para hacer nuevos amigos. Envíelo por correo electrónico, o proporciónelo en mano.</p> @@ -3389,7 +3041,7 @@ Haga doble clic sobre este para añadir su nombre en el compositor de texto.<html><head/><body><p>Este es el método de cifrado usado por <span style=" font-weight:600;">OpenSSL</span>. La conexión a nodos amigos</p><p>siempre se cifra fuertemente, y si está presente el DHE (intercambio de claves Diffie-Hellman)</p><p>la conexión además usa &quot;secreto perfecto hacia delante&quot; (perfect forward secrecy).</p></body></html> - + with con @@ -3406,118 +3058,16 @@ Haga doble clic sobre este para añadir su nombre en el compositor de texto.Connect Friend Wizard Asistente para conectarse con los amigos - - Add a new Friend - Añadir un amigo nuevo - - - &You get a certificate file from your friend - &Obtener un archivo de certificado de su amigo - - - &Make friend with selected friends of my friends - Hacer a&migos con los amigos de mis amigos seleccionados - - - &Send an Invitation by Email - (Your friend will receive an email with instructions how to download RetroShare) - &Enviar una invitación por correo - (Su amigo recibirá un correo electrónico con instrucciones sobre cómo descargar RetroShare) - - - Include signatures - Incluir firmas - - - Copy your Cert to Clipboard - Copiar su certificado al portapapeles - - - Save your Cert into a File - Guardar su certificado en un archivo - - - Run Email program - Abrir programa de email - Open Cert of your friend from File Abrir certificado de su amigo desde fichero - - Open certificate - Abrir certificado - - - Please, paste your friend's Retroshare certificate into the box below - Por favor, pegue el certificado Retroshare de su amigo en el recuadro de debajo - - - Certificate files - Archivos de certificados PGP - - - Use PGP certificates saved in files. - Usar certificados PGP guardados en archivos. - - - Import friend's certificate... - Importar certificado PGP de un amigo... - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - Tiene que crear un archivo con su certificado PGP y enviárselo a un amigo. También puede usar un archivo generado anteriormente. - - - Export my certificate... - Exportar mi certificado PGP... - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - Arrastre y suelte el certificado de sus amigos en esta ventana o especifique la ruta aquí - - - Browse - Navegar - - - Friends of friends - Amigos de amigos - - - Select now who you want to make friends with. - Elija ahora quienes quiere hacer sus amigos. - - - Show me: - Mostrarme: - - - Make friend with these peers - Hacer amistad con estos vecinos - RetroShare ID ID de RetroShare - - Use RetroShare ID for adding a Friend which is available in your network. - Utilize la ID de RetroShare para añadir a amigos que estén disponibles en su red. - - - Add Friends RetroShare ID... - Añadir la ID de RetroShare del amigo... - - - Paste Friends RetroShare ID in the box below - Pegar el ID de amigos de RetroShare en el siguiente cuadro - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - Introduzca el ID de RetroShare de su amigo, p,ej. Peer@BDE8D16A46D938CF - RetroShare is better with Friends @@ -3559,27 +3109,7 @@ Haga doble clic sobre este para añadir su nombre en el compositor de texto.Correo electrónico - Invite Friends by Email - Invitar a amigos por correo electrónico - - - Enter your friends' email addresses (separate each one with a semicolon) - Introduzca las direcciones de email de sus amigos (separadas cada una con un punto y coma) - - - Your friends' email addresses: - Direcciones de correo de sus amigos: - - - Enter Friends Email addresses - Introduzca la dirección de correo de su amigo - - - Subject: - Asunto: - - - + @@ -3595,78 +3125,32 @@ Haga doble clic sobre este para añadir su nombre en el compositor de texto.Detalles de la solicitud - + Peer details Detalles del vecino - + Name: Nombre: - - Email: - Email: - - - Node: - Nodo: - - - Please note that RetroShare will require excessive amounts of bandwidth, memory and CPU if you add too many friends. You can add as many friends as you like, but more than 40 will probably require too much -resources. - Por favor, observe que RetroShare requerirá cantidades excesivas de ancho de banda, memoria y CPU si añade demasiados amigos. Puede añadir tantos amigos como quiera, pero más de 40 probablemente requerirá demasiados -recursos. - Location: Lugar: - + Options Opciones - This wizard will help you to connect to your friend(s) to RetroShare network.<br>Select how you would like to add a friend: - Este asistente le ayudará a conectar a su(s) amigo(s) a la red RetroShare.<br>Seleccione cómo desea añadir un amigo: - - - Enter the certificate manually - Introduzca el certificado manualmente - - - Enter RetroShare ID manually - Introduzca la identificación de RetroShare manualmente - - - &Send an Invitation by Web Mail Providers - &Enviar una invitación mediante proveedores de correo web - - - Recommend many friends to each other - Intercambie muchas recomendaciones de amigos con sus amigos - - - RetroShare certificate - Certificado de RetroShare - - - Please paste below your friend's Retroshare certificate - Por favor, pegue debajo el certificado de RetroShare de su amigo - - - Paste certificate - Pegar certificado - - - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> <html><head/><body><p>Este recuadro espera el certificado de RetroShare de su amigo. ADVERTENCIA: Este es distinto de la clave del perfil de su amigo. No pegue aquí la clave del perfil de su amigo (ni siquiera una parte de ella). No va a funcionar.</p></body></html> - + Add friend to group: Añadir amigo a grupo: @@ -3676,7 +3160,7 @@ recursos. Autenticar amigo (firmar la clave PGP) - + Please paste below your friend's Retroshare ID @@ -3701,16 +3185,22 @@ recursos. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with Añadir como amigo al conectarse con - To accept the Friend Request, click the Finish button. - Para aceptar la solicitud de amigo, pulse en el botón Finalizar. - - - + Sorry, some error appeared Lo siento, ha ocurrido un error @@ -3730,32 +3220,27 @@ recursos. Detalles acerca de su amigo: - + Key validity: Validez de la clave: - + Profile ID: - - Signers - Firmantes - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Firmar la clave de un amigo es una forma de expresar su confianza en este amigo a sus otros amigos. Las firmas de debajo atestiguan criptográficamente que los titulares de las claves listadas reconocen como auténtica la clave PGP actual.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. Este vecino ya está en su lista de amigos. Añadiendolo sólo podrá establecer su dirección ip. - + To accept the Friend Request, click the Accept button. @@ -3801,49 +3286,17 @@ recursos. - + Certificate Load Failed Error al cargar el certificado - Cannot get peer details of PGP key %1 - No se pudieron obtener los detalles del vecino con clave PGP %1 - - - Any peer I've not signed - Vecinos a quienes no he firmado las claves PGP - - - Friends of my friends who already trust me - Amigos de amigos que me han firmado la clave PGP - - - Signed peers showing as denied - Vecinos bloqueados a quienes he firmado la llave PGP - - - Peer name - Nombre del vecino - - - Also signed by - Tambien firmado por - - - Peer id - ID del vecino - - - Certificate appears to be valid - El certificado parece ser válido - - - + Not a valid Retroshare certificate! ¡No es un certificado RetroShare válido! - + RetroShare Invitation Invitación de RetroShare @@ -3865,12 +3318,12 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? ¿Este es su propio certificado? No querría hacerse amigo de si mismo. ¿No es así? - + @@ -3878,7 +3331,7 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc - + This key is already on your trusted list Esta clave ya está en su lista de confianza @@ -3918,7 +3371,7 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc Tiene una solicitud de amistad de - + Profile password needed. @@ -3943,7 +3396,7 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc - + Valid Retroshare ID @@ -3953,47 +3406,7 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc - Certificate Load Failed:file %1 not found - La carga del certificado PGP ha fallado: archivo %1 no encontrado - - - This Peer %1 is not available in your Network - Este vecino %1 no está disponible en su red - - - Use new certificate format (safer, more robust) - Usar el nuevo formato de certificado (más seguro y robusto) - - - Use old (backward compatible) certificate format - Usar el viejo formato de certificado (compatible con versiones anteriores) - - - Remove signatures - Quitar las firmas - - - RetroShare Invite - Invitar a RetroShare - - - Connect Friend Help - Ayuda para conectar con sus amigos - - - You can copy this text and send it to your friend via email or some other way - Puede copiar este texto y enviarlo a su amigo por email o de alguna otra forma - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Su certificado se ha copiado al portapapeles. Péguelo y envíeselo a un amigo por email u otro medio - - - Save as... - Guardar como... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -4032,11 +3445,7 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc *** Ningúno *** - Use as direct source, when available - Utilizar como fuente directa, cuando esté disponible - - - + IP-Addr: Dir-IP: @@ -4046,7 +3455,7 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc Dirección-IP - + Show Advanced options Mostrar opciones avanzadas @@ -4055,10 +3464,6 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Firmar una clave de un amigo es una forma de expresar su confianza en este amigo al resto de sus amigos. Les ayuda a decidir si permitir conexiones desde esa clave en base a la propia confianza de usted. Firmar una clave es absolutamente opcional y no se puede deshacer, así que hágalo juiciosamente. </span></p></body></html> - - <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> - <html><head/><body><p align="justify">RetroShare comprueba periódicamente sus listas de amigos en busca de ficheros explorables que coincidan con sus transferencias, para establecer una transferencia directa. En tal caso, su amigo sabe que usted está descargando el fichero.</p><p align="justify">Para evitar este comportamiento sólo para este amigo, desmarque esta casilla. Aún puede efectuar una transferencia directa si la pide explícitamente, por ejemplo, descargando de la lista de ficheros de su amigo. Está ajuste se aplica a todas las ubicaciones del mismo nodo.</p></body></html> - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> @@ -4069,45 +3474,13 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc <html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> <html><head/><body><p>Los vecinos que tengan esta opción no pueden conectar si la dirección de su conexión no está en la lista blanca. Esto le protege de ataques de reenvío de tráfico. Cuando lo use, se informará de los vecinos rechazados mediante &quot;elementos de seguridad de la suscripción (feed)&quot; en la sección de Suscripción de Noticias. Desde allí, puede incluir sus IPs en lista blanca/negra. Se aplica a todas las ubicaciones del mismo nodo.</p></body></html> - - Recommend many friends to each others - Recomendar varios amigos a los demás - - - Friend Recommendations - Recomendaciones de amigo - - - The text below is your Retroshare certificate. You have to provide it to your friend - El texto de debajo es su certificado Retroshare. Tiene que proporcionárselo a su amigo. - - - Message: - Mensage: - - - Recommend friends - Recomendar amigos - - - To - A - - - Please select at least one friend for recommendation. - Por favor, seleccione al menos un amigo por recomendación. - - - Please select at least one friend as recipient. - Por favor, seleccione al menos un amigo como destinatario. - Add key to keyring Añadir al grupo de claves ('keyring') - + This key is already in your keyring Esta clave ya está en su grupo de claves ('keyring') @@ -4123,7 +3496,7 @@ mensajes distantes a este vecino incluso si no hace amigos. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. El certificado tiene un número de versión incorrecto. Recuerde que las redes de v0.6 y v0.5 son incompatibles. @@ -4158,7 +3531,7 @@ incluso si no hace amigos. Añadir IP a la lista blanca - + No IP in this certificate! ¡No hay IP en este certificado! @@ -4168,27 +3541,10 @@ incluso si no hace amigos. <p>Este certificado no tiene IP. Dependerá del descubrimiento y la DHT (tabla distribuida de hashes) para encontrarlo. A causa de que usted requiere que se limpie la lista blanca, el vecino generará una advertencia de seguridad en la pestaña de Novedades (feed). Desde allí puede añadir su IP a la lista blanca.</p> - - [Unknown] - - - - + Added with certificate from %1 Añadido con el certificado de %1 - - Paste Cert of your friend from Clipboard - Pegar certificado de su amigo desde el Portapapeles - - - Certificate Load Failed:can't read from file %1 - La carga del certificado falló: No se pudo leer del archivo %1 - - - Certificate Load Failed:something is wrong with %1 - La carga del certificado falló: Hay algo mal con %1 - ConnectProgressDialog @@ -4250,7 +3606,7 @@ incluso si no hace amigos. - + UDP Setup Configurar UDP @@ -4286,7 +3642,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:13pt;">puede cerrarlo.</span></p></body></html> - + Connection Assistant Asistente de conexión @@ -4296,17 +3652,20 @@ p, li { white-space: pre-wrap; } ID del vecino inválido - + + Unknown State Estado desconocido - + + Offline Desconectado - + + Behind Symmetric NAT Detrás de NAT simétrico @@ -4316,12 +3675,14 @@ p, li { white-space: pre-wrap; } Detrás de NAT y sin DHT - + + NET Restart Reiniciar red - + + Behind NAT Detrás de NAT @@ -4331,7 +3692,8 @@ p, li { white-space: pre-wrap; } Sin DHT - + + NET STATE GOOD! ESTADO DE LA RED BUENO! @@ -4356,7 +3718,7 @@ p, li { white-space: pre-wrap; } Encontrando vecinos de RS - + Lookup requires DHT La búsqueda requiere DHT @@ -4648,7 +4010,7 @@ p, li { white-space: pre-wrap; } Por favor, intenta volver a importar el certificado completo - + @@ -4656,7 +4018,8 @@ p, li { white-space: pre-wrap; } N/A - + + UNVERIFIABLE FORWARD! REENVÍO NO VERIFICABLE! @@ -4666,7 +4029,7 @@ p, li { white-space: pre-wrap; } REENVÍO NO VERIFICABLE Y SIN DHT - + Searching Buscando @@ -4702,12 +4065,12 @@ p, li { white-space: pre-wrap; } Detalles del círculo - + Name Nombre - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> <html><head/><body><p>El nombre, contacto del autor y lista de miembros invitados del círculo será visible para todos los miembros invitados. Si el círculo no es privado, también será visible a los nodos vecinos de los nodos que alojen a los miembros invitados.</p></body></html> @@ -4727,7 +4090,7 @@ p, li { white-space: pre-wrap; } - + IDs IDs @@ -4747,18 +4110,18 @@ p, li { white-space: pre-wrap; } Filtrar - + Cancel Cancelar - + Nickname Apodo - + Invited Members Miembros invitados @@ -4773,15 +4136,7 @@ p, li { white-space: pre-wrap; } Personas conocidas - ID - ID - - - Type - Tipo - - - + Name: Nombre: @@ -4821,23 +4176,19 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Los círculos se pueden restringir a los miembros de otro círculo. Sólo los miembros de ese segundo círculo tendrán permitido ver el nuevo círculo y su contenido (lista de miembros, etc.).</p></body></html> - Only visible to members of: - Sólo visible para los miembros de: - - - - + + RetroShare RetroShare - + Please set a name for your Circle Por favor elija un nombre para su círculo - + No Restriction Circle Selected Círculo seleccionado sin restricciones @@ -4847,12 +4198,24 @@ p, li { white-space: pre-wrap; } No hay limitaciones en el círculo seleccionado - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add Añadir @@ -4862,7 +4225,7 @@ p, li { white-space: pre-wrap; } Eliminar - + Search Buscar @@ -4877,10 +4240,6 @@ p, li { white-space: pre-wrap; } Signed Firmado - - Signed by known nodes - Firmado por nodos conocidos - Edit Circle @@ -4897,10 +4256,6 @@ p, li { white-space: pre-wrap; } PGP Identity Identidad PGP - - Anon Id - Identidad anónima - Circle name @@ -4923,17 +4278,13 @@ p, li { white-space: pre-wrap; } Crear nuevo círculo - + Create Crear - PGP Linked Id - Identidad vinculada a PGP - - - + Add Member Añadir miembro @@ -4952,7 +4303,7 @@ p, li { white-space: pre-wrap; } Crear un grupo - + Group Name: Nombre del grupo: @@ -4987,7 +4338,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post Nuevo mensaje del canal @@ -4997,7 +4348,7 @@ p, li { white-space: pre-wrap; } Mensaje del canal - + Post @@ -5058,23 +4409,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Utilice arrastrar y soltar / Botón añadir archivos, para nuevos hash de archivos</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Copiar/pegar enlaces de RetroShare desde sus recursos compartidos</span></p></body></html> - - Add File to Attach - Adjuntar archivo - Add Channel Thumbnail Añadir imagen al canal - - Message - Mensaje - - - Subject : - Asunto: - @@ -5160,17 +4499,17 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -5189,17 +4528,18 @@ p, li { white-space: pre-wrap; } The following files will only be shared for 30 days. Think about adding them to a shared directory. - - File already Added and Hashed - Archivo ya añadido y hash generado - Please add a Subject Por favor, añada un asunto - + + Cannot publish post + + + + Load thumbnail picture Cargar imagen en miniatura @@ -5214,18 +4554,12 @@ p, li { white-space: pre-wrap; } Ocultar - - + Generate mass data Generar datos masivos - - Do you really want to generate %1 messages ? - ¿De veras quiere generar %1 mensajes? - - - + You are about to add files you're not actually sharing. Do you still want this to happen? Está a punto de añadir archivos que actualmente no está compartiendo. ¿Seguro que quiere continuar? @@ -5259,7 +4593,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message Enviar mensaje al foro @@ -5268,10 +4602,6 @@ p, li { white-space: pre-wrap; } Forum Foro - - Subject - Asunto - Attach File @@ -5292,8 +4622,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -5312,7 +4642,7 @@ p, li { white-space: pre-wrap; } En esta ventana puede adjuntar archivos mediante arrastrar y soltar - + Post @@ -5342,17 +4672,17 @@ p, li { white-space: pre-wrap; } - + No Forum Ningún foro - + In Reply to En respuesta a - + Title Título @@ -5406,7 +4736,7 @@ Do you want to discard this message? Cargar archivo de imagen - + No compatible ID for this forum Identificación no compatible para este foro @@ -5416,8 +4746,8 @@ Do you want to discard this message? Ninguna de sus identidades tiene permitido publicar en este foro. Esto se podría deber a que el foro se esté limitando a un círculo que no contiene ninguna de sus identidades, o a que los indicativos del foro requieran una identidad firmada-con-PGP. - - + + Generate mass data Generar datos masivos @@ -5426,10 +4756,6 @@ Do you want to discard this message? Do you really want to generate %1 messages ? ¿De veras quiere generar %1 mensajes? - - Send - Enviar - Post as @@ -5444,23 +4770,7 @@ Do you want to discard this message? CreateLobbyDialog - Create Chat Lobby - Crear sala de chat - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - Un "Chat lobby" es una sala de chat en grupo descentralizada y anónima. Todos los participantes reciben todos los mensajes. Una vez que se crea la sala puede invitar a otros amigos de la ficha de Amigos. - - - Lobby name: - Nombre de la sala: - - - Lobby topic: - Tema de la sala: - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5495,7 +4805,7 @@ Do you want to discard this message? - + Create Crear @@ -5505,11 +4815,7 @@ Do you want to discard this message? Cancelar - <html><head/><body><p>If you check this, only PGP-signed ids can be used to join and talk in this lobby. This limitation prevents anonymous spamming as it becomes possible for at least some people in the lobby to locate the spammer's node.</p></body></html> - <html><head/><body><p>Si marca esto, sólo se pueden usar las identificaciones firmadas-con-PGP para unirse y hablar en esta sala. Esta limitación previene el spam anónimo ya que se hace posible para, al menos algunas personas en la sala, localizar el nodo spammer.</p></body></html> - - - + require PGP-signed identities requiere identidades firmadas-con-PGP @@ -5524,11 +4830,7 @@ Do you want to discard this message? Seleccione los amigos para el chat de grupo. - Invited friends - Amigos invitados - - - + Create Chat Room Crear sala de chat @@ -5549,7 +4851,7 @@ Do you want to discard this message? Contactos: - + Identity to use: Identidad a usar: @@ -5557,17 +4859,17 @@ Do you want to discard this message? CryptoPage - + Public Information Información pública - + Name: Nombre: - + Location: Lugar: @@ -5577,12 +4879,12 @@ Do you want to discard this message? ID del lugar: - + Software Version: Versión del programa: - + Online since: En línea desde: @@ -5602,12 +4904,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5617,7 +4914,7 @@ Do you want to discard this message? - + Other Information Otra información @@ -5627,17 +4924,12 @@ Do you want to discard this message? - + Profile Perfil - - Certificate - Certificado - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5647,11 +4939,7 @@ Do you want to discard this message? Incluir firmas - Save Key into a file - Guardar mi clave en un archivo - - - + Export Identity Exportar identidad @@ -5725,33 +5013,33 @@ y utilizar el botón Importar para cargarla - + TextLabel Texto de la etiqueta - + PGP fingerprint: Huella de validación de clave PGP: - - Node information - Información del nodo - - - + PGP Id : Identificación de PGP : - + Friend nodes: Nodos amigos: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5790,14 +5078,6 @@ y utilizar el botón Importar para cargarla Node Nodo - - Create new node... - Crear nuevo nodo... - - - show statistics window - mostrar ventana de estadísticas - DHTGraphSource @@ -5814,10 +5094,6 @@ y utilizar el botón Importar para cargarla DHT DHT - - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your friends to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your friends.</p> - <p>Retroshare usar la DHT (tabla de hashes dinámica) de Bittorrent como un proxy (interpuesto) para conexiones. No "almacena" su IP en la DHT. En su lugar, la DHT es usada por sus amigos para llegar a usted mientras se procesan peticiones DHT estándar. El indicador de estado se volverá verde tan pronto como Retroshare obtenga una respuesta DHT de uno de sus amigos.</p> - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your trusted nodes to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your trusted nodes.</p> @@ -5853,7 +5129,7 @@ y utilizar el botón Importar para cargarla DLListDelegate - + B B @@ -6521,7 +5797,7 @@ y utilizar el botón Importar para cargarla DownloadToaster - + Start file Abrir archivo @@ -6529,38 +5805,38 @@ y utilizar el botón Importar para cargarla ExprParamElement - + - + to a - + ignore case Ignorar Mayús/Minús - - - dd.MM.yyyy - dd.MM.yyyy + + + yyyy-MM-dd + - - + + KB KB - - + + MB MB - - + + GB GB @@ -6568,12 +5844,12 @@ y utilizar el botón Importar para cargarla ExpressionWidget - + Expression Widget Widget de expresiones - + Delete this expression Borrar esta expresión @@ -6735,7 +6011,7 @@ y utilizar el botón Importar para cargarla FilesDefs - + Picture Imagen @@ -6745,7 +6021,7 @@ y utilizar el botón Importar para cargarla Vídeo - + Audio Audio @@ -6805,11 +6081,21 @@ y utilizar el botón Importar para cargarla C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Carpetas de amigos @@ -6931,7 +6217,7 @@ y utilizar el botón Importar para cargarla - + ID Identidad @@ -6966,10 +6252,6 @@ y utilizar el botón Importar para cargarla Show State Mostrar estado - - Trusted nodes - Nodos de confianza - @@ -6977,7 +6259,7 @@ y utilizar el botón Importar para cargarla Mostrar grupos - + Group Grupo @@ -7013,7 +6295,7 @@ y utilizar el botón Importar para cargarla Añadir a grupo - + Search Buscar @@ -7029,7 +6311,7 @@ y utilizar el botón Importar para cargarla Ordenar por estado - + Profile details Detalles del perfil @@ -7273,7 +6555,7 @@ al menos un vecino no fue añadido al grupo FriendRequestToaster - + Confirm Friend Request Confirmar solicitud de amistad @@ -7290,10 +6572,6 @@ al menos un vecino no fue añadido al grupo FriendSelectionWidget - - Search : - Buscar: - Sort by state @@ -7315,7 +6593,7 @@ al menos un vecino no fue añadido al grupo Buscar a amigos - + Mark all Marcar todo @@ -7326,16 +6604,134 @@ al menos un vecino no fue añadido al grupo No marcar nada + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Nombre + + + + Node ID + + + + + Address + Dirección + + + + Status + Estado + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + Hacer amigo + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + El proxy no está habilitado o está estropeado. +¿¿Están todos los servicios en marcha y ejecutándose correctamente?? +¡Compruebe también sus puertos! + + FriendsDialog - + Edit status message Editar mensaje de estado - - + + Broadcast Difusión @@ -7418,33 +6814,38 @@ al menos un vecino no fue añadido al grupo Restablecer la fuente por defecto - + Keyring Juego de claves - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Red</h1> <p>La pestaña de Red muestra sus nodos RetroShare amigos: los nodos RetroShare vecinos que están conectados a usted. </p> <p>Puede agrupar nodos juntos para permitir un nivel de regulación más fino del acceso a la información, por ejemplo para permitir que sólo algunos nodos vean algunos de sus archivos.</p> <p>A la derecha, encontrará 3 pestañas útiles: <ul> <li>Difusión envía mensajes a todos los nodos conectados a la vez</li> <li>Gráfica de red local muestra la red alrededor de usted, basándose en la información de descubrimiento</li> <li>El juego de claves contiene claves de nodos que ha recopilado, en su mayoría redirigidos hacia usted por sus nodos amigos</li> </ul> </p> - - - + Retroshare broadcast chat: messages are sent to all connected friends. Chat de difusión de RetroShare: Los mensajes se envían a todos los amigos conectados. - - + + Network Red - + + Friend Server + + + + Network graph Gráfica de la red - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. Configure su mensaje de estado aquí. @@ -7462,7 +6863,17 @@ al menos un vecino no fue añadido al grupo Contraseña - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters Todos los campos requieren como mínimo 3 letras @@ -7472,17 +6883,12 @@ al menos un vecino no fue añadido al grupo Las contraseñas no coinciden - + Port Puerto - - Use BOB - Usar BOB - - - + This password is for PGP Esta contraseña es para PGP @@ -7503,50 +6909,38 @@ al menos un vecino no fue añadido al grupo ¡Fallo al generar su nuevo certificado, quizá la contraseña PGP está mal! - Options - Opciones - - - + PGP Key Length Tamaño de la clave PGP - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> <html><head/><body><p>Introduzca aquí una contraseña robusta. ¡Esta contraseña protege la clave privada de su nodo!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> <html><head/><body><p>Por favor, mueva su ratón al azar para adquirir tanta aleatoriedad como sea posible. Se necesita un mínimo del 20% para crear las claves de su nodo.</p></body></html> - + Standard node Nodo estándar - TOR/I2P Hidden node - Nodo oculto TOR/I2P - - - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> <html><head/><body><p>El nombre de su nodo designa la instancia de RetroShare que</p><p>se ejecutará en esta máquina.</p></body></html> - Use existing profile - Usar perfil existente - - - + Node name Nombre del nodo - + Node type: @@ -7566,12 +6960,12 @@ al menos un vecino no fue añadido al grupo - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> <html><head/><body><p>El nombre del perfil le identifica en la red.</p><p>Es usado por sus amigos para aceptar conexiones de usted.</p><p>Puede crear múltiples nodos de RetroShare con el</p><p>mismo perfil en distintas máquinas.</p><p><br/></p></body></html> - + Export this profle Exportar este perfil @@ -7581,42 +6975,43 @@ al menos un vecino no fue añadido al grupo - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> <html><head/><body><p>Esto debe ser una dirección onion de Tor con la forma: xa76giaf6ifda7ri63i263.onion <br/>o una dirección I2P con la forma: [52 caracteres].b32.i2p </p><p>Para obtener una, tiene que configurar Tor o bien I2P para crear un nuevo servicio oculto / túnel de servidor. </p><p> También puede dejar esto en blanco ahora, pero su nodo sólo funcionará si establece correctamente la dirección del servicio Tor/I2P en el panel de configuración Opciones-&gt;Red-&gt;Servicio oculto.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> <html><head/><body><p>Las identidades se usan cuando escribe en salas de chat, foros y comentarios de canal.</p><p>También reciben/envían correo electrónico sobre la red RetroShare. Puede crear</p><p>ahora una identidad firmada, o hacerlo más tarde cuando le sea necesaria.</p></body></html> - + Go! ¡Vamos! - - + + TextLabel EtiquetaTexto - Advanced options - Opciones avanzadas - - - + hidden address dirección oculta - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. Su perfil está asociado con un par de claves PGP. RetroShare actualmente ignora las claves DSA. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> <html><head/><body><p>Este es su puerto de conexión.</p><p>Cualquier valor entre 1024 y 65535 </p><p>debería estar bien. Puede cambiarlo más tarde.</p></body></html> @@ -7664,13 +7059,13 @@ y usar el botón Importar para cargarlo Su perfil no fue guardado. Ocurrió un error. - + Import profile Perfil importado - + Create new profile and new Retroshare node Crear nuevo perfil y nuevo nodo RetroShare @@ -7680,7 +7075,7 @@ y usar el botón Importar para cargarlo Crear nuevo nodo RetroShare - + Tor/I2P address Dirección Tor/I2P @@ -7715,7 +7110,7 @@ y usar el botón Importar para cargarlo - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7725,12 +7120,7 @@ y usar el botón Importar para cargarlo - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> <p>La creación de nodo está deshabilitada hasta que todos los campos estén establecidos correctamente.</p> @@ -7740,12 +7130,7 @@ y usar el botón Importar para cargarlo <p>La creación de nodo está deshabilitada hasta que se recoja suficiente aleatoriedad. Por favor, mueva su ratón hasta que alcance al menos el 20%.</p> - - I2P instance address with BOB enabled - Dirección de instancia de I2P con BOB habilitado - - - + I2P instance address Dirección de instancia de I2P @@ -7971,36 +7356,13 @@ y usar el botón Importar para cargarlo Primeros pasos - + Invite Friends Invitar a los amigos - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> - <html><head><meta name="qrichtext" content="1" /><style type="text/css"> - p, li { white-space: pre-wrap; } - </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> - <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare no es nada sin sus amigos. Pulse en el botón para iniciar el proceso.</span></p> - <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> - <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Envíe por correo electrónico una invitación con su &quot;Certificado ID&quot; a sus amigos.</span></p> - <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> - <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Asegúrese de obtener de vuelta la invitación de su amigo... </span></p> - <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Sólo puede conectarse con amigos, si se han añadido unos a otros.</span></p></body></html> - - - + Add Your Friends to RetroShare Añadir a sus amigos a RetroShare @@ -8010,136 +7372,103 @@ p, li { white-space: pre-wrap; } Añadir amigos - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">¡Permanezca conectado al mismo tiempo que sus amigos, y Retroshare conectará automáticamente con usted!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Su cliente necesita encontrar la red Retroshare antes de poder hacer conexiones.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Esto lleva entre 5-30 minutos la primera vez que inicie Retroshare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">El indicador de la DHT (en la barra de estado) se vuelve verde cuando puede realizar conexiones.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Tras un par de minutos, el indicador de NAT (también en la barra de estado) cambia a amarillo o verde.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Si permanece rojo, entonces tiene un cortafuegos molesto, con el que RetroShare lucha para conectar a través de él.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Vea la sección Ayuda Adicional para más recomendaciones sobre cómo conectar.</span></p></body></html> + + Connect To Friends + Conectar con amigos - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Puede mejorar su rendimiento de Retroshare abriendo un puerto externo. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Esto acelerará las conexiones y permitirá a más personas conectar con usted. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">La forma más fácil de hacer esto es habilitando UPnP en su dispositivo inalámbrico o router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Como cada router es diferente, necesitará averiguar el modelo de su router y buscar las instrucciones en Internet.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Si nada de esto tiene sentido para usted, no se preocupe por ello, Retroshare todavía funcionará.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Avanzado: Abrir el puerto del cortafuegos <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">¿Tiene problemas iniciándose con RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Mire al wiki de preguntas frecuentes (FAQ). Este es un poco antiguo, estamos tratando de actualizarlo.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Revise los foros en línea. Formule preguntas y discuta características.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Pruebe en los foros internos de RetroShare </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - Estos entran en línea una vez este conectado a amigos.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) Si aún está estancado, escríbanos un correo.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Disfrute del Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> + - - Connect To Friends - Conectar con amigos - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Cuando sus amigos le envíen invitaciones, pulse para abrir la ventana Añadir Amigos.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Pegue los &quot;Certificados de identificación&quot; de sus amgios en la ventana y añádalos como amigos.</span></p></body></html> - - - - Advanced: Open Firewall Port - Avanzado: Abrir el puerto del cortafuegos - - - + Further Help and Support Más ayuda y soporte técnico - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website Abrir sitio web de RS @@ -8164,7 +7493,7 @@ p, li { white-space: pre-wrap; } Email para enviar comentarios - + RetroShare Invitation Invitación de RetroShare @@ -8214,12 +7543,12 @@ p, li { white-space: pre-wrap; } Comentarios de RetroShare - + RetroShare Support Soporte de RetroShare - + It has many features, including built-in chat, messaging, Tiene muchas características, incluyendo un chan integrado, mensajería, @@ -8343,7 +7672,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat Mostrar chat de grupo @@ -8351,7 +7680,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] [Desconocido] @@ -8517,19 +7846,11 @@ p, li { white-space: pre-wrap; } You can let your friends know about your forum by sharing it with them. Select the friends with which you want to share your forum. Puede dejar que sus amigos sepan de su foro al compartirlo con ellos. Seleccione a los amigos con los que quiera compartir su foro. - - Share topic admin permissions - Compartir permisos de administrador del hilo - - - You can allow your friends to edit the topic. Select them in the list below. Note: it is not possible to revoke Posted admin permissions. - Puede permitir que sus amigos editen el hilo. Selecciónelos en la lista de debajo. Nota: No es posible revocar permisos de administrador de Posted. - GroupTreeWidget - + Title Título @@ -8542,12 +7863,12 @@ p, li { white-space: pre-wrap; } - + Description Descripción - + Number of Unread message @@ -8572,35 +7893,7 @@ p, li { white-space: pre-wrap; } - Sort Descending Order - Ordenar en orden descendente - - - Sort Ascending Order - Ordenar en orden ascendente - - - Sort by Name - Ordenar por nombre - - - Sort by Popularity - Ordenar por popularidad - - - Sort by Last Post - Ordenar por última entrada - - - Sort by Number of Posts - Ordenar por número de mensajes - - - Sort by Unread - Ordenar por no leídos - - - + You are admin (modify names and description using Edit menu) Usted es administrador (modifique nombres y descripciones usando el menú Editar) @@ -8615,14 +7908,14 @@ p, li { white-space: pre-wrap; } ID - - + + Last Post Última publicación - + Name Nombre @@ -8633,17 +7926,13 @@ p, li { white-space: pre-wrap; } Popularidad - + Never Nunca - Display - Mostrar - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8656,7 +7945,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and y @@ -8792,7 +8081,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels Canales @@ -8803,26 +8092,22 @@ p, li { white-space: pre-wrap; } Crear canal - + Enable Auto-Download Activar descarga automática - + My Channels Mis canales - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Canales</h1> <p>Los canales le permiten publicar datos (ej. películas, música) que se diseminarán por la red</p> <p>Puede ver los canales a los que están suscritos sus amigos, y reenviar automáticamente los canales a los que esté suscrito a sus amigos. Esto promueve buenos canales en la red.</p> <p>Sólo el creador del canal puede publicar en ese canal. Otros vecinos en la red sólo pueden leer de él, a no ser que el canal sea privado. Sin embargo, puede compartir los derechos de publicación o lectura con nodos RetroShare amigos.</p> <p>Los canales pueden hacerse anónimos, o ligados a una identidad de RetroShare de forma que los lectores puedan contactar con usted si lo necesitan. Habilite "Permitir comentarios" si quiere permitir a los usuarios comentar en sus posts.</p> <p>Los posts de canal se conservan durante %1 días, y se sincronizan para los últimos %2 días, a menos que cambie esto.</p> - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Canales suscritos @@ -8842,12 +8127,12 @@ p, li { white-space: pre-wrap; } Seleccione el directorio de descarga del canal - + Disable Auto-Download Desactivar descarga automática - + Set download directory Establecer directorio de descarga @@ -8882,22 +8167,22 @@ p, li { white-space: pre-wrap; } - + Play Reproducir - + Open folder Abrir carpeta - + Open file - + Error Error @@ -8917,17 +8202,17 @@ p, li { white-space: pre-wrap; } Comprobando - + Are you sure that you want to cancel and delete the file? ¿Está seguro de que quiere cancelar y borrar el archivo? - + Can't open folder No se pudo abrir la carpeta - + Play File Reproducir archivo @@ -8937,37 +8222,10 @@ p, li { white-space: pre-wrap; } Archivo %1 no está en ese lugar. - - GxsChannelFilesWidget - - Form - Formulario - - - Filename - Nombre del archivo - - - Size - Tamaño - - - Title - Título - - - Published - Publicado - - - Status - Estado - - GxsChannelGroupDialog - + Create New Channel Crear nuevo canal @@ -9005,9 +8263,19 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - Suscribirse al canal + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel + @@ -9021,7 +8289,7 @@ p, li { white-space: pre-wrap; } - + Expand Expandir @@ -9036,7 +8304,7 @@ p, li { white-space: pre-wrap; } Descripción del canal - + Loading Cargando @@ -9051,8 +8319,9 @@ p, li { white-space: pre-wrap; } - New Channel - Nuevo canal + + Never + Nunca @@ -9063,7 +8332,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: Nuevo comentario: @@ -9084,7 +8353,7 @@ p, li { white-space: pre-wrap; } - + Play Reproducir @@ -9140,28 +8409,24 @@ p, li { white-space: pre-wrap; } Files Archivos - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - ¡Aviso! Tiene menos de %1 horas y %2 minutos antes que este archivo sea eliminado, considere la posibilidad de guardarlo. - Hide Ocultar - + New Nuevo - + 0 0 - - + + Comment Comentario @@ -9176,21 +8441,17 @@ p, li { white-space: pre-wrap; } Esto no me gusta - Loading - Cargando - - - + Loading... - + Comments Comentarios - + Post @@ -9215,139 +8476,16 @@ p, li { white-space: pre-wrap; } Reproducir medio - - GxsChannelPostsWidget - - Post to Channel - Mensaje al canal - - - Add new post - Añadir nuevo mensaje - - - Loading - Cargando - - - Search channels - Buscar canales - - - Title - Título - - - Search Title - Buscar por título - - - Message - Mensaje - - - Search Message - Buscar mensaje - - - Filename - Nombre del archivo - - - Search Filename - Buscar nombre de archivo - - - No Channel Selected - Ningún canal seleccionado - - - Never - Nunca - - - Public - Público - - - Restricted to members of circle " - Restringido a los miembros del círculo " - - - Restricted to members of circle - Restringido a los miembros del círculo - - - Your eyes only - Sólo para sus ojos - - - You and your friend nodes - Usted y sus nodos amigos - - - Disable Auto-Download - Desactivar descarga automática - - - Enable Auto-Download - Activar descarga automática - - - Show feeds - Mostrar novedades (feeds) - - - Show files - Mostrar archivos - - - Administrator: - Administrador: - - - Last Post: - Último post: - - - unknown - desconocido - - - Distribution: - Distribución: - - - Feeds - Novedades (feeds) - - - Files - Archivos - - - Subscribers - Suscriptores - - - Description: - Descripción: - - - Posts (at neighbor nodes): - Publicaciones (en nodos vecinos): - - GxsChannelPostsWidgetWithModel - + Post to Channel Mensaje al canal - + Add new post Añadir nuevo mensaje @@ -9417,7 +8555,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -9453,7 +8591,7 @@ p, li { white-space: pre-wrap; } - + Comments Comentarios @@ -9468,13 +8606,13 @@ p, li { white-space: pre-wrap; } Novedades (feeds) - - + + Click to switch to list view - + Show unread posts only @@ -9489,7 +8627,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -9504,7 +8642,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -9564,12 +8702,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -9644,12 +8792,13 @@ p, li { white-space: pre-wrap; } Usted y sus nodos amigos - + + Copy Retroshare link - + Subscribed Suscrito @@ -9700,17 +8849,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -9730,27 +8879,11 @@ p, li { white-space: pre-wrap; } Remove Item Eliminar elemento - - for identity - para la identidad - - - You received a membership request for circle: - Ha recibido una solicitud de membresía para el círculo: - Grant membership request Conceder solicitud de membresía - - Revoke membership request - Revocar solicitud de membresía - - - You received an invitation for circle: - Ha recibido una invitación para el círculo: - @@ -9841,7 +8974,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container Comentarios aquí @@ -9854,7 +8987,7 @@ p, li { white-space: pre-wrap; } Formulario - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9884,7 +9017,7 @@ p, li { white-space: pre-wrap; } Refrescar - + Comment Comentario @@ -9923,7 +9056,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment Responder al comentario @@ -9947,6 +9080,21 @@ p, li { white-space: pre-wrap; } Vote Down Votar negativo + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9956,7 +9104,7 @@ p, li { white-space: pre-wrap; } Hacer comentario - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9985,22 +9133,10 @@ p, li { white-space: pre-wrap; } - + Post - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comentario</span></p></body></html> - - - Signed by - Firmado por - Reply to Comment @@ -10028,7 +9164,7 @@ before you can comment Es necesario crear una identidad⏎ antes de poder comentar - + It remains %1 characters after HTML conversion. @@ -10070,14 +9206,6 @@ before you can comment Forum moderators can edit/delete/pinup others posts - - Add Forum Admins - Añadir administradores al foro - - - Select Forum Admins - Seleccionar administradores del foro - Create @@ -10087,7 +9215,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum Suscribirse al foro @@ -10103,7 +9231,7 @@ before you can comment - + Expand Expandir @@ -10123,8 +9251,9 @@ before you can comment - Loading - Cargando + + TextLabel + @@ -10155,13 +9284,13 @@ before you can comment GxsForumMsgItem - - + + Subject: Tema: - + Unsubscribe To Forum Anular suscripción al foro @@ -10172,7 +9301,7 @@ before you can comment - + Expand Expandir @@ -10192,21 +9321,17 @@ before you can comment En respuesta a: - Loading - Cargando - - - + Loading... - + Forum Feed Novedad (feed) del canal - + Hide Ocultar @@ -10219,63 +9344,66 @@ before you can comment Formulario - + Start new Thread for Selected Forum Iniciar nuevo tema para el foro seleccionado - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Buscar foros - Last Post - Último mensaje - - - + New Thread Nuevo hilo - - - Threaded View - Vista por discusión - - - - Flat View - Vista plana - - + Title Título - - + + Date Fecha - + Author Autor - - Save image - Guardar imagen - - - + Loading Cargando - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -10285,12 +9413,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message Responder mensaje @@ -10314,10 +9437,6 @@ before you can comment Download all files Descargar todos los archivos - - Next unread - Siguiente no leído - Search Title @@ -10334,35 +9453,23 @@ before you can comment Buscar por autor - Content - Contenido - - - Search Content - Buscar por contenido - - - <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - <p>Suscribiendose al foro reunirá los posts disponibles de los amigos a los que esté suscrito, y hará el foro visible al resto de sus amigos.</p><p>Posteriormente puede desuscribirse desde el menú contextual de la lista del foro a la izquierda.</p> - - - + No name Sin nombre - - + + Reply Responder - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -10405,20 +9512,12 @@ before you can comment Copiar enlace de RetroShare - + Hide Ocultar - Expand - Expandir - - - [Banned] - [Excluido] - - - + [unknown] [desconocido] @@ -10448,8 +9547,8 @@ before you can comment Sólo para sus ojos - - + + Distribution Distribución @@ -10463,26 +9562,6 @@ before you can comment Anti-spam Anti-spam - - [ ... Redacted message ... ] - [ ... Mensaje redactado ... ] - - - Anonymous - Anónimo - - - signed - firmado - - - none - ninguno - - - [ ... Missing Message ... ] - [ ... Mensaje perdido ... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10552,16 +9631,12 @@ before you can comment Mensaje original - + New thread Nuevo hilo - Read status - Estado de lectura - - - + Edit Editar @@ -10622,7 +9697,7 @@ before you can comment Reputación del autor - + Show column @@ -10642,7 +9717,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive Posts anónimos/desconocidos reenviados si la reputación es positiva @@ -10694,7 +9769,7 @@ This message is missing. You should receive it later. - + No result. @@ -10704,7 +9779,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -10719,30 +9794,7 @@ This message is missing. You should receive it later. - Information for this identity is currently missing. - La información para esta identidad actualmente está desaparecida. - - - You have banned this ID. The message will not be -displayed nor forwarded to your friends. - Ha excluido esta identificación. El mensaje no será -mostrado ni reenviado a sus amigos. - - - You have not set an opinion for this person, - and your friends do not vote positively: Spam regulation -prevents the message to be forwarded to your friends. - No ha establecido una opinión para esta persona, -y sus amigos no la han votado positivamente: La -regulación de spam evita que este mensaje sea -reenviado a sus amigos. - - - Message will be forwarded to your friends. - El mensaje será reenviado a sus amigos. - - - + (Latest) (Más reciente) @@ -10751,10 +9803,6 @@ reenviado a sus amigos. (Old) (Antiguo) - - You cant act on the author to a non-existant Message - No puede actuar sobre el autor de un mensaje no-existente - From @@ -10812,12 +9860,12 @@ reenviado a sus amigos. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Foros</h1> <p>Los foros de RetroShare se parecen a los foros de Internet, pero funcionan de forma descentralizada</p> <p>Puede ver los foros a los que están suscritos sus amigos, y reenviar los foros a los que esté suscrito a sus amigos. Esto automáticamente promueve foros interesantes en la red.</p> <p>Los mensajes del foro se conservan durante %1 días y sincronizan para los últimos dos días, a menos que lo configure de otro modo.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> + - + Forums Foros @@ -10848,35 +9896,16 @@ reenviado a sus amigos. Otros foros - - GxsForumsFillThread - - Waiting - Esperando - - - Retrieving - Recuperando - - - Loading - Cargando - - GxsGroupDialog - + Name Nombre - Add Icon - Añadir icono - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels Los destinatarios de la clave pueden publicar en grupos de tipo restringido, y pueden ver y publicar en canales de tipo privado @@ -10885,22 +9914,14 @@ reenviado a sus amigos. Share Publish Key Compartir clave de publicación - - check peers you would like to share private publish key with - marque los vecinos con los que desea compartir la clave privada de publicación - - - Share Key With - Compartir clave con - - + Description Descripción - + Message Distribution Distribución del mensaje @@ -10908,7 +9929,7 @@ reenviado a sus amigos. - + Public Público @@ -10927,14 +9948,6 @@ reenviado a sus amigos. New Thread Nuevo hilo - - Required - Requerido - - - Encrypted Msgs - Mensajes cifrados - Personal Signatures @@ -10976,7 +9989,7 @@ reenviado a sus amigos. Protección-del-spam - + Comments: Comentarios: @@ -10999,7 +10012,7 @@ reenviado a sus amigos. Anti-spam: - + All People @@ -11015,12 +10028,12 @@ reenviado a sus amigos. - + Restricted to circle: Restringido al círculo: - + Limited to your friends Limitado a sus amigos @@ -11037,23 +10050,23 @@ reenviado a sus amigos. - + Message tracking Rastreo de mensaje - - + + PGP signature required Se requiere firma PGP - + Never Nunca - + Only friends nodes in group Sólo nodos amigos en el grupo @@ -11069,30 +10082,28 @@ reenviado a sus amigos. Por favor añadir un nombre - + PGP signature from known ID required Se requiere firma PGP de identificación conocida - + + + [None] + + + + Load Group Logo Cargar el logo del grupo - + Submit Group Changes Enviar cambios del grupo - Failed to Prepare Group MetaData - please Review - Fallo al preparar Metadatos del grupo - por favor revise - - - Will be used to send feedback - Se usará para enviar comentarios - - - + Owner: Propietario: @@ -11102,12 +10113,12 @@ reenviado a sus amigos. Configure una descripción explicativa aquí - + Info Información - + ID ID @@ -11117,7 +10128,7 @@ reenviado a sus amigos. Último mensaje - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> <html><head/><body><p>Los mensajes se difundirán mucho más allá de los nodos de sus amigos, mientras la gente se suscriba al canal/foro/posted que está creando.</p></body></html> @@ -11192,7 +10203,12 @@ reenviado a sus amigos. Desfavorecer identificaciones no firmadas e identificaciones desde nodos desconocidos - + + Author: + + + + Popularity Popularidad @@ -11208,27 +10224,22 @@ reenviado a sus amigos. - + Created - + Cancel Cancelar - + Create Crear - - Author - Autor - - - + GxsIdLabel GxsEtiquetaIdentificación @@ -11236,7 +10247,7 @@ reenviado a sus amigos. GxsGroupFrameDialog - + Loading Cargando @@ -11296,7 +10307,7 @@ reenviado a sus amigos. Editar detalles - + Synchronise posts of last... Sincronizar posts de los últimos... @@ -11353,16 +10364,12 @@ reenviado a sus amigos. - + Search for - Share publish permissions - Compartir permisos de publicación - - - + Copy RetroShare Link Copiar enlace de RetroShare @@ -11385,7 +10392,7 @@ reenviado a sus amigos. GxsIdChooser - + No Signature Sin Firma @@ -11398,40 +10405,24 @@ reenviado a sus amigos. GxsIdDetails - Loading - Cargando - - - + Not found No encontrado - - No Signature - Sin Firma - - - + + [Banned] [Excluido] - - Authentication - Autentificación - unknown Key clave desconocida - anonymous - anónimo - - - + Loading... @@ -11441,7 +10432,12 @@ reenviado a sus amigos. - + + [Nobody] + + + + Identity&nbsp;name Nombre&nbsp;de&nbsp;identidad @@ -11455,16 +10451,20 @@ reenviado a sus amigos. Node Nodo - - Signed&nbsp;by - Firmado&nbsp;por - [Unknown] [Desconocida] + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -11476,7 +10476,7 @@ reenviado a sus amigos. GxsIdStatisticsWidget - + Total identities: @@ -11524,17 +10524,13 @@ reenviado a sus amigos. GxsIdTreeItemDelegate - + [Unknown] GxsMessageFramePostWidget - - Loading - Cargando - Loading... @@ -11651,10 +10647,6 @@ reenviado a sus amigos. Group ID / Author Identificación del grupo / Autor - - Number of messages / Publish TS - Número de mensajes / Publicar estadísticas de transporte - Local size of data @@ -11670,10 +10662,6 @@ reenviado a sus amigos. Popularity Popularidad - - Details - Detalles - @@ -11706,41 +10694,6 @@ reenviado a sus amigos. No - - GxsTunnelsDialog - - Authenticated tunnels: - Túneles autentificados: - - - Tunnel ID: %1 - Identificador de túnel: %1 - - - from: %1 - de: %1 - - - to: %1 - a: %1 - - - status: %1 - estado: %1 - - - total sent: %1 bytes - total envd: %1 bytes - - - total recv: %1 bytes - total recb: %1 bytes - - - Unknown Peer - Vecino desconocido - - HashBox @@ -11953,48 +10906,12 @@ reenviado a sus amigos. About Acerca de - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare provides file sharing, chat, messages and channels</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Useful external links to more information:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Wiki</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare's Forum</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Project Page</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Team Blog</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Dev Twitter</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare es una plataforma de comunicación descentralizada </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">multi-sistema, descentralizada, privada y segura. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Le permite compartir de forma segura con sus amigos, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">usando un web-of-trust para autentificar vecinos y OpenSSL para cifrar toda la comunicación. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare proporciona compartición de ficheros, chat, mensajes y canales</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"Enlaces externos útiles para mayor información:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Página web de RetroShare</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Wiki de RetroShare</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Foro de RetroShare</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Página del proyecto RetroShare</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Blog del equipo de RetroShare</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Twitter de desarrollo de RetroShare</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -12010,7 +10927,7 @@ p, li { white-space: pre-wrap; } - + Authors Autores @@ -12029,7 +10946,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -12042,36 +10959,6 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Daniel Wester</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">wester@speedmail.se</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">German: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Jan</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Keller</span><span style=" font-family:'MS Shell Dlg 2';"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">trilarion@users.sourceforge.net</span><span style=" font-family:'MS Shell Dlg 2';">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Traducciones de RetroShare:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Traductores del sitio web de RetroShare:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Sueco: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Daniel Wester</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">wester@speedmail.se</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Alemán: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Jan</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Keller</span><span style=" font-family:'MS Shell Dlg 2';"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">trilarion@users.sourceforge.net</span><span style=" font-family:'MS Shell Dlg 2';">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polaco: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - License Agreement @@ -12133,50 +11020,34 @@ p, li { white-space: pre-wrap; } Formulario - + <html><head/><body><p>Copy your RetroShare ID to clipboard</p></body></html> - + <html><head/><body><p>Copia tu ID de RetroShare al portapapeles</p></body></html> - + Add friend - + Agregar amigo Did you receive a Retroshare ID from a friend? - + ¿Recibiste una identificación de Retroshare de una amiga? Do you need help with Retroshare? - + ¿Necesitas ayuda con Retroshare? - + <html><head/><body><p>Share your RetroShare ID</p></body></html> - + <html><head/><body><p>Comparte tu ID de RetroShare</p></body></html> This is your Retroshare ID. Copy and share with your friends! - - - - Did you receive a certificate from a friend? - ¿Ha recibido un certificado de un amigo? - - - Add friends certificate - Añadir certificado de amigos - - - Add certificate file - Añadir fichero de certificado - - - Share your RetroShare Key - Compartir su clave de RetroShare + Este es tu ID de Retroshare. ¡Cópialo y compártelo con tus amigos! @@ -12184,10 +11055,6 @@ p, li { white-space: pre-wrap; } ... ... - - The text below is your own Retroshare certificate. Send it to your friends - El texto de debajo es su propio certificado de RetroShare. Envíeselo a sus amigos - Open Source cross-platform, @@ -12197,20 +11064,12 @@ private and secure decentralized communication platform. de código abierto, multi-sistema, privada y segura. - Launch startup wizard - Iniciar asistente de arranque - - - Do you need help with RetroShare? - ¿Necesita ayuda con RetroShare? - - - + Open Web Help Ayuda de Open Web - + Copy your Cert to Clipboard Copiar su certificado al portapapeles @@ -12220,7 +11079,7 @@ de código abierto, multi-sistema, privada y segura. Guardar su certificado en un fichero - + Send via Email Enviar vía correo electrónico @@ -12237,16 +11096,40 @@ de código abierto, multi-sistema, privada y segura. Copy your Retroshare ID to Clipboard + Copia tu ID de Retroshare al portapapeles + + + + Include current local IP - - + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -12258,17 +11141,12 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -12277,19 +11155,11 @@ new short format Your Retroshare ID is copied to Clipboard, paste and send it to your friend via email or some other way - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your certificate on this page and send it to friends, and add your friends' certificate.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange certificates with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;¡Bienvenido a RetroShare!</h1> <p>¡Necesita hacer <b>hacer amigos</b>! Después de que cree una red de amigos o se una a una red existente, podrá intercambiar ficheros, chatear, hablar en foros, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>Para hacerlo así, copie su certificado en esta página y envíelo a los amigos, y añada el certificado de sus amigos.</p> <p>Otra opción es buscar en Internet por "servidores de chat de RetroShare" (administrados independientemente). Estos servidores le permite intercambiar certificados con un nodo dedicado de RetroShare, a través del cual podrá encontrarse anónimamente con otras personas.</p> - RetroShare Invite Invitación de RetroShare - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Su certificado se copia al Portapapeles, pegue y envíeselo a su amigo por correo electrónico o de algún otro modo - Save as... @@ -12303,7 +11173,7 @@ new short format Home - Página principal + Casa @@ -12561,14 +11431,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Todo - + Reputation Reputación @@ -12578,12 +11448,12 @@ p, li { white-space: pre-wrap; } Buscar - + Anonymous Id ID anónima - + Create new Identity Crear nueva identidad @@ -12593,7 +11463,7 @@ p, li { white-space: pre-wrap; } Crear nuevo círculo - + Persons Personas @@ -12608,27 +11478,27 @@ p, li { white-space: pre-wrap; } Persona - + Close Cerrar - + Ban-option: Opción de exclusión: - + Auto-Ban all identities signed by the same node Auto-excluir todas las identidades firmadas por el mismo nodo - + Friend votes: Votos de amigos: - + Positive votes Votos positivos @@ -12644,29 +11514,39 @@ p, li { white-space: pre-wrap; } Votos negativos - + Created on : - + Creado el : - + + Auto-Ban profile + Perfil de prohibición automática + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + Editar identidad + + + Usage statistics Estadísticas de uso - + Circles Círculos - + Circle name Nombre del círculo @@ -12686,18 +11566,20 @@ p, li { white-space: pre-wrap; } Círculos personales - + + Edit identity Editar identidad - + + Delete identity Borrar indentidad - + Chat with this peer Charlar con este vecino @@ -12707,98 +11589,78 @@ p, li { white-space: pre-wrap; } Abre un chat a distancia con este vecino - + Owner node ID : - Identificación del nodo propietario : + Identificación del nodo: - + Identity name : - Nombre de la identidad : + Nombre de identidad: - + () () - + Identity ID Identificación de la identidad - + Send message Enviar mensaje - + Identity info Información de la identidad - + Identity ID : Identificación de la identidad : - + Owner node name : Nombre del nodo propietario : - + Create new... Crear nueva... - + Type: Tipo: - + Send Invite Enviar invitación - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> <html><head/><body><p>La opinión media de los nodos vecinos acerca de esta identidad. Negativo es malo,</p><p>positivo es bueno. Cero es neutral.</p></body></html> - + Your opinion: Su opinión: - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </p> -<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Su propia opinión acerca de una identidad rige la visibilidad de esa identidad para si mismo y los nodos de sus amigos. Su propia opinión es compartida entre amgios y usada para calcular una puntuación de reputación: Si su opinión acerca de una identidad es neutral, la puntuación de reputación es la diferencia entre las opiniones positivas y negativas del amigo. Si no, su propia opinión proporciona la puntuación.</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">La puntuación global se usa en salas de chat, foros y canales para decidir sobre las acciones a tomar para cada identidad específica. Cuando la puntuación global es menor que -1, la identidad es excluida, lo que evita que sean reenviados todos los mensajes y foros/canales cuya autoría pertenezca a esta identidad, en ambos sentidos. Algunos foros también tienen indicativos anti-spam especiales que requieren un nivel de reputación no negativo, y eventualmente desaparecen (tras 5 días).</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Puede cambiar los umbrales y el tiempo de inactividad para eliminar identidades en Preferencias -&gt; Personas. </p> -<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - + Negative Negativo - + Neutral Neutral @@ -12809,17 +11671,17 @@ p, li { white-space: pre-wrap; } Positivo - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> <html><head/><body><p>Puntuación de reputación global, contando la suya y las de sus amigos.</p><p>Negativo es malo, positivo es bueno, cero es neutral. Si la puntuación es demasiado baja,</p><p>la identidad se señalará como mala, y será rechazada en foros, salas de chat,</p><p>canales, etc.</p></body></html> - + Overall: Global: - + Anonymous Anónimo @@ -12834,24 +11696,24 @@ p, li { white-space: pre-wrap; } Buscar identificación - + This identity is owned by you Esta identidad es propiedad de usted - - + + My own identities Mis propias identidades - - + + My contacts Mis contactos - + Show Items Mostrar elementos @@ -12866,7 +11728,12 @@ p, li { white-space: pre-wrap; } Enlazado a mi nodo - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles Otros círculos @@ -12876,7 +11743,7 @@ p, li { white-space: pre-wrap; } Círculos a los que pertenezco - + Circle ID: Identificación del círculo: @@ -12951,7 +11818,7 @@ p, li { white-space: pre-wrap; } No es miembro (no tiene acceso a datos limitados a este círculo) - + Identity ID: Identificación de identidad: @@ -12981,7 +11848,7 @@ p, li { white-space: pre-wrap; } desconocido - + Invited Invitado @@ -12996,7 +11863,7 @@ p, li { white-space: pre-wrap; } Miembro - + Edit Circle Editar círculo @@ -13044,7 +11911,7 @@ p, li { white-space: pre-wrap; } Conceder membresía - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -13055,7 +11922,7 @@ Debe deshacerse de ella ahora y usar una nueva. Estas identidades pronto dejarán de estar soportadas. - + [Unknown node] [Nodo desconocido] @@ -13098,7 +11965,7 @@ Estas identidades pronto dejarán de estar soportadas. Identidad anónima - + Boards @@ -13178,7 +12045,7 @@ Estas identidades pronto dejarán de estar soportadas. - + information información @@ -13194,29 +12061,12 @@ Estas identidades pronto dejarán de estar soportadas. Copiar identidad al portapapeles - Send invite? - ¿Enviar invitación? - - - Do you really want send a invite with your Certificate? - ¿Está seguro de que quiere enviar una invitación con su certificado? - - - + Banned Excluido - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identidades</h1> <p>En esta pestaña puede crear/editar <b>identidades pseudo-anónimas</b>, y <b>círculos</b>.</p> <p>Las <b>identidades</b> se usan para identificar sus datos de forma segura: firmar mensajes en salas de chat, foros y posts en canales, recibir comentarios usando el sistema de correo electrónico integrado de RetroShare, comentarios publicados tras los posts en los canales, chat usando túneles seguros, etc.</p> <p>Las identidades opcionalmente pueden estar <b>firmadas</b> por el certificado de su nodo RetroShare. Es más fácil confiar en las identidades firmadas pero son más fácilmente vinvulables con la dirección IP de su nodo.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - Unknown ID: - Identidad desconocida: - - - + positive positivo @@ -13260,19 +12110,11 @@ Estas identidades pronto dejarán de estar soportadas. Forums Foros - - Posted - Posted - Chat Chat - - Unknown - Desconocido - [Unknown] @@ -13293,14 +12135,6 @@ Estas identidades pronto dejarán de estar soportadas. Creation of author signature in service %1 Creación de firma del autor en servicio %1 - - Message/vote/comment - Mensaje/voto/comentario - - - %1 in %2 tab - %1 en la pestaña %2 - Distant message signature validation. @@ -13321,19 +12155,11 @@ Estas identidades pronto dejarán de estar soportadas. Signature in distant tunnel system. Firma en sistema de túnel distante. - - Update of identity data. - Actualizar datos de identidad. - Generic signature validation. Validación de firma genérica. - - Generic signature. - Firma genérica. - Generic encryption. @@ -13345,11 +12171,7 @@ Estas identidades pronto dejarán de estar soportadas. Descifrado genérico. - Membership verification in circle %1. - Verificación de membresía en el círculo %1. - - - + Add to Contacts Añadir a contactos @@ -13399,21 +12221,21 @@ Estas identidades pronto dejarán de estar soportadas. Hola,<br>quiero que seamos amigos en RetroShare.<br> - - - + + + People Personas - + Your Avatar Click here to change your avatar Su avatar - + Linked to neighbor nodes Enlazado hacia nodos vecinos @@ -13423,7 +12245,7 @@ Estas identidades pronto dejarán de estar soportadas. Enlazado hacia nodos distantes - + Linked to a friend Retroshare node Enlazado hacia un nodo de RetroShare amigo @@ -13438,7 +12260,7 @@ Estas identidades pronto dejarán de estar soportadas. Enlazado hacia un nodo RetroShare desconocido - + Chat with this person Conversar con esta persona @@ -13453,12 +12275,12 @@ Estas identidades pronto dejarán de estar soportadas. Conversación distante rechazada con esta persona. - + Last used: Usado por última vez: - + +50 Known PGP +50 PGP conocidos @@ -13478,12 +12300,12 @@ Estas identidades pronto dejarán de estar soportadas. ¿De verdad quiere borrar esta identidad? - + Owned by Propiedad de - + Node name: Nombre del nodo: @@ -13493,7 +12315,7 @@ Estas identidades pronto dejarán de estar soportadas. Identificación del nodo: - + Really delete? ¿Está seguro de borrar? @@ -13501,7 +12323,7 @@ Estas identidades pronto dejarán de estar soportadas. IdEditDialog - + Nickname Apodo @@ -13531,7 +12353,7 @@ Estas identidades pronto dejarán de estar soportadas. Seudónimo - + Import image @@ -13541,12 +12363,19 @@ Estas identidades pronto dejarán de estar soportadas. - - Use the mouse to zoom and adjust the image for your avatar. + + + No Avatar chosen. A default image will be automatically displayed from your new identity. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity Nueva identidad @@ -13560,7 +12389,7 @@ Estas identidades pronto dejarán de estar soportadas. - + @@ -13570,7 +12399,12 @@ Estas identidades pronto dejarán de estar soportadas. N/A - + + No avatar chosen + + + + Edit identity Editar identidad @@ -13581,27 +12415,27 @@ Estas identidades pronto dejarán de estar soportadas. Actualizar - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -13621,7 +12455,7 @@ Estas identidades pronto dejarán de estar soportadas. - + Identity update failed @@ -13631,11 +12465,7 @@ Estas identidades pronto dejarán de estar soportadas. - Error getting key! - ¡Error al obtener la clave! - - - + Error KeyID invalid Error, ID de la clave no válida @@ -13650,7 +12480,7 @@ Estas identidades pronto dejarán de estar soportadas. Nombre real desconocido - + Create New Identity Crear nueva identidad @@ -13660,10 +12490,15 @@ Estas identidades pronto dejarán de estar soportadas. Tipo - + Choose image... + + + Remove + + @@ -13689,7 +12524,7 @@ Estas identidades pronto dejarán de estar soportadas. Añadir - + Create Crear @@ -13699,17 +12534,13 @@ Estas identidades pronto dejarán de estar soportadas. Cancelar - + Your Avatar Click here to change your avatar Su avatar - Set Avatar - Establecer avatar - - - + Linked to your profile Enlazado a su perfil @@ -13719,7 +12550,7 @@ Estas identidades pronto dejarán de estar soportadas. Puede tener una o más identidades. Se usan cuando escribe un salas de chat, foros y comentarios de canales. Actúan como el destinatario para conversaciones distantes y el sistema de correo distante de RetroShare. - + The nickname is too short. Please input at least %1 characters. El apodo es demasiado corto. Por favor, introduzca al menos %1 caracteres. @@ -13778,10 +12609,6 @@ Estas identidades pronto dejarán de estar soportadas. PGP name: Nombre de PGP: - - GXS id: - Identificación de GXS: - PGP id: @@ -13797,7 +12624,7 @@ Estas identidades pronto dejarán de estar soportadas. - + Copy Copiar @@ -13807,12 +12634,12 @@ Estas identidades pronto dejarán de estar soportadas. Quitar - + %1 's Message History - + Mark all Marcar todo @@ -13831,26 +12658,38 @@ Estas identidades pronto dejarán de estar soportadas. Quote Citar - - Send - Enviar - ImageUtil - - + + Save image Guardar imagen + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + + + + Cannot save the image, invalid filename No se puede guardar la imagen, nombre de fichero no válido - + + Copy image + + + + + Not an image No es una imagen @@ -13868,27 +12707,32 @@ Estas identidades pronto dejarán de estar soportadas. - + Enable RetroShare JSON API Server - + Port: Puerto: - + Listen Address: - + + Status: + Estado: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -13909,7 +12753,12 @@ Estas identidades pronto dejarán de estar soportadas. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -13918,26 +12767,31 @@ Estas identidades pronto dejarán de estar soportadas. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File Abrir archivo - + Open Folder Abrir carpeta - + Checking... Comprobando... @@ -13947,7 +12801,7 @@ Estas identidades pronto dejarán de estar soportadas. Comprobar archivos - + Recommend in a message to... Recomendar en un mensaje a... @@ -13975,7 +12829,7 @@ Estas identidades pronto dejarán de estar soportadas. MainWindow - + Add Friend Añadir a amigo @@ -13991,7 +12845,8 @@ Estas identidades pronto dejarán de estar soportadas. - + + Options Opciones @@ -14012,7 +12867,7 @@ Estas identidades pronto dejarán de estar soportadas. - + Quit Cerrar @@ -14023,12 +12878,12 @@ Estas identidades pronto dejarán de estar soportadas. Asistente para el inicio rápido - + RetroShare %1 a secure decentralized communication platform RetroShare %1 es una plataforma de comunicación descentralizada y segura - + Unfinished Incompleto @@ -14057,11 +12912,12 @@ Estas identidades pronto dejarán de estar soportadas. + Status Estado - + Notify Notificación @@ -14072,31 +12928,35 @@ Estas identidades pronto dejarán de estar soportadas. + Open Messages Abrir mensajes - + + Bandwidth Graph Gráfico del uso de la red - + Applications Aplicaciones + Help Ayuda - + + Minimize Minimizar - + Maximize Maximizar @@ -14111,7 +12971,12 @@ Estas identidades pronto dejarán de estar soportadas. RetroShare - + + Close window + + + + %1 new message %1 nuevo mensaje @@ -14141,7 +13006,7 @@ Estas identidades pronto dejarán de estar soportadas. %1 amigos conectados - + Do you really want to exit RetroShare ? ¿Realmente desea salir de RetroShare? @@ -14161,7 +13026,7 @@ Estas identidades pronto dejarán de estar soportadas. Mostrar - + Make sure this link has not been forged to drag you to a malicious website. Asegúrese de que este enlace no ha sido falsificado para arrastrarle a un sitio web malicioso. @@ -14206,12 +13071,13 @@ Estas identidades pronto dejarán de estar soportadas. Matriz de permisos del servicio - + + Statistics Estadísticas - + Show web interface Mostrar interfaz web @@ -14226,7 +13092,7 @@ Estas identidades pronto dejarán de estar soportadas. directorio está descenciendo (el límite actual es - + Really quit ? ¿Está seguro de salir? @@ -14235,17 +13101,17 @@ Estas identidades pronto dejarán de estar soportadas. MessageComposer - + Compose Componer - + Contacts Contactos - + Paragraph Párrafo @@ -14281,12 +13147,12 @@ Estas identidades pronto dejarán de estar soportadas. Encabezamiento 6 - + Font size Tamaño de letra - + Increase font size Aumentar tamaño de letra @@ -14301,32 +13167,32 @@ Estas identidades pronto dejarán de estar soportadas. Negrita - + Italic Cursiva - + Alignment Alineación - + Add an Image Añadir una imagen - + Sets text font to code style Cambia el estilo de letra a tipo codigo - + Underline Subrayado - + Subject: Asunto: @@ -14337,32 +13203,32 @@ Estas identidades pronto dejarán de estar soportadas. - + Tags Etiquetas - + Address list: Lista de direcciones: - + Recommend this friend Recomendar este amigo - + Set Text color Establecer color del texto - + Set Text background color Establecer color de fondo - + Recommended Files Archivos recomendados @@ -14432,7 +13298,7 @@ Estas identidades pronto dejarán de estar soportadas. Añadir cita - + Send To: Enviar a: @@ -14456,10 +13322,6 @@ Estas identidades pronto dejarán de estar soportadas. &Justify &Justificar - - All addresses (mixed) - Todas las direcciones (mezcladas) - All people @@ -14471,7 +13333,7 @@ Estas identidades pronto dejarán de estar soportadas. Mis contactos - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> Hola,<br>Le recomiendo a un buen amigo mío, puede confiar en él tanto como confía en mí. <br> @@ -14491,18 +13353,18 @@ Estas identidades pronto dejarán de estar soportadas. quiere ser su amigo en RetroShare - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team Hola %1,<br><br>%2 quiere ser su amigo en RetroShare.<br><br>Responder ahora:<br>%3<br><br>Gracias,<br>El equipo de RetroShare - - + + Save Message Guardar mensaje - + Message has not been Sent. Do you want to save message to draft box? El mensaje no se ha enviado. @@ -14514,7 +13376,17 @@ Do you want to save message to draft box? Pegar enlace de RetroShare - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" Añadir a "A" @@ -14534,7 +13406,7 @@ Do you want to save message to draft box? Añadir como recomendado - + Original Message Mensaje original @@ -14544,21 +13416,21 @@ Do you want to save message to draft box? De - + - + To A - - + + Cc Cc - + Sent Enviar @@ -14573,7 +13445,7 @@ Do you want to save message to draft box? En %1, %2 escribió: - + Re: Re: @@ -14583,30 +13455,30 @@ Do you want to save message to draft box? Env: - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? ¿Quiere enviar este mensaje sin asunto? - + Please insert at least one recipient. Por favor, introduzca por lo menos un destinatario. - + Bcc Bcc - + Unknown Desconocido @@ -14721,13 +13593,13 @@ Do you want to save message to draft box? Detalles - + Open File... Abrir archivo... - + HTML-Files (*.htm *.html);;All Files (*) Archivos HTML (*.htm *.html);;Todos los archivos(*) @@ -14747,7 +13619,7 @@ Do you want to save message to draft box? Exportar PDF - + Message has not been Sent. Do you want to save message ? El mensaje no se ha enviado. @@ -14769,7 +13641,7 @@ Do you want to save message ? Añadir otro archivo - + Hi,<br>I want to be friends with you on RetroShare.<br> Hola,<br>quiero establecer amistad contigo en RetroShare.<br> @@ -14793,28 +13665,24 @@ Do you want to save message ? Warning: This message is too big of %1 characters after HTML conversion. - - You have a friend invite - Tiene una invitación de amistad. - Respond now: Responder ahora: - - + + Close Cerrar - + From: De: - + Friend Nodes Nodos amigos @@ -14859,13 +13727,13 @@ Do you want to save message ? Lista ordenada (números romanos en mayúscula) - - + + Thanks, <br> Gracias, <br> - + Distant identity: Identidad distante: @@ -14875,12 +13743,12 @@ Do you want to save message ? [Desaparecido] - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. Por favor, cree una identidad para firmar mensajes distantes, o elimine los vecinos distantes de la lista de destinos. - + Node name & id: Nombre de nodo e identificación: @@ -14958,7 +13826,7 @@ Do you want to save message ? Por defecto - + A new tab Una pestaña nueva @@ -14968,7 +13836,7 @@ Do you want to save message ? Una ventana nueva - + Edit Tag Editar etiqueta @@ -14991,7 +13859,7 @@ Do you want to save message ? MessageToaster - + Sub: Asunto: @@ -14999,7 +13867,7 @@ Do you want to save message ? MessageUserNotify - + Message Mensaje @@ -15027,7 +13895,7 @@ Do you want to save message ? MessageWidget - + Recommended Files Archivos recomendados @@ -15037,37 +13905,37 @@ Do you want to save message ? Descargar todos los archivos recomendados - + Subject: Asunto: - + From: De: - + To: A: - + Cc: Cc: - + Bcc: Bcc: - + Tags: Etiquetas: - + Reply Responder @@ -15107,7 +13975,7 @@ Do you want to save message ? - + Send Invite Enviar invitación @@ -15159,7 +14027,7 @@ Do you want to save message ? - + Confirm %1 as friend Confirmar %1 como amigo @@ -15169,12 +14037,12 @@ Do you want to save message ? Añadir %1 como amigo - + View source - + No subject Sin asunto @@ -15184,17 +14052,22 @@ Do you want to save message ? Descargar - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -15204,21 +14077,23 @@ Do you want to save message ? - Send invite? - ¿Enviar invitación? + + Show less + - Do you really want send a invite with your Certificate? - ¿Está seguro de que quiere enviar una invitación con su certificado? + + Show more + - + Download all Dercargar todo - + Print Document Imprimir documento @@ -15233,12 +14108,12 @@ Do you want to save message ? Archivos HTML (*.htm *.html);;Todos los archivos(*) - + Load images always for this message Cargar siempre imágenes para este mensaje - + Hide the attachment pane Ocultar el panel de adjunto @@ -15260,42 +14135,6 @@ Do you want to save message ? Compose Componer - - Reply to selected message - Responder al mensaje seleccionado - - - Reply - Responder - - - Reply all to selected message - Responder a todos los mensajes seleccionados - - - Reply all - Responder a todos - - - Forward selected message - Reenviar mensaje seleccionado - - - Forward - Adelante - - - Remove selected message - Borrar mensaje seleccionado - - - Delete - Borrar - - - Print selected message - Imprimir mensaje seleccionado - Print @@ -15374,7 +14213,7 @@ Do you want to save message ? MessagesDialog - + New Message Nuevo mensaje @@ -15384,60 +14223,16 @@ Do you want to save message ? Componer - Reply to selected message - Responder a mensaje seleccionado - - - Reply - Responder - - - Reply all to selected message - Responder a todos los mensajes seleccionados - - - Reply all - Responder a todos - - - Forward selected message - Reenviar mensaje seleccionado - - - Foward - Reenviar - - - Remove selected message - Borrar mensaje seleccionado - - - Delete - Borrar - - - Print selected message - Imprimir mensaje seleccionado - - - Print - Imprimir - - - Display - Mostrar - - - + - - + + Tags Etiquetas - - + + Inbox Bandeja de entrada @@ -15467,21 +14262,17 @@ Do you want to save message ? Papelera - + Total Inbox: Buzón de entrada total: - Folders - Carpetas - - - + Quick View Vista rápida - + Print... Imprimir... @@ -15491,26 +14282,6 @@ Do you want to save message ? Print Preview Vista previa - - Buttons Icon Only - Botones solo con icono - - - Buttons Text Beside Icon - Botones con texto al lado del icono - - - Buttons with Text - Botones con texto - - - Buttons Text Under Icon - Botones con texto debajo del icono - - - Set Text Under Icon - Poner texto debajo de los iconos - Save As... @@ -15532,7 +14303,7 @@ Do you want to save message ? Reenviar mensaje - + Subject Asunto @@ -15542,7 +14313,7 @@ Do you want to save message ? De - + Date Fecha @@ -15552,39 +14323,7 @@ Do you want to save message ? Contenido - Click to sort by attachments - Pulsar para ordenar por adjuntos - - - Click to sort by subject - Pulsar para ordenar por asunto - - - Click to sort by read - Pulsar para ordenar por leido - - - Click to sort by from - Pulsar para ordenar por remitente - - - Click to sort by date - Pulsar para ordenar por fecha - - - Click to sort by tags - Pulsar para ordenar por etiqueta - - - Click to sort by star - Pulsar para ordenar por estrella - - - Forward selected Message - Reenviar mensaje seleccionado - - - + Search Subject Buscar por el asunto @@ -15593,6 +14332,11 @@ Do you want to save message ? Search From Buscar desde + + + Search To + + Search Date @@ -15619,14 +14363,14 @@ Do you want to save message ? Buscar por adjuntos - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>RetroShare tiene su propio sistema interno de correo electrónico. Puede recibir/enviar correos de/a nodos amigos conectados.</p> <p>También es posible enviar mensajes a las identidades de otras personas usando el sistema de enrutamiento global. Estos mensajes siempre se cifran y firman, y son repetidos por nodos intermedios hasta que alcanzan su destino final. </p> <p>Los mensajes distantes permanecen en su Bandeja de Salida hasta que llegue un acuse de recibo.</p> <p>Generalmente, puede usar mensajes para recomendar archivos a sus amigos pegando los enlaces de los archivos, o puede recomendar nodos amigos a otros nodos amigos para fortalecer su red, o enviar comentarios al propietario de un canal.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + - + Starred - Con estrella + @@ -15700,7 +14444,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -15714,7 +14458,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -15729,38 +14473,33 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts Borradores - + No Box selected. - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - No hay mensajes favoritos disponibles. Las estrellas permiten dar un estatus especial a los mensajes para que sean más fáciles de encontrar. Para marcar como favorito un mensaje, pulse en la estrella gris claro al lado de cualquier mensaje. - - - No system messages available. - No hay mensajes del sistema disponibles. - - + To - A + A - Click to sort by to - Pulsar para ordenar por destinatario - - - This message goes to a distant person. - Este mensaje va a una persona distante. - - - + @@ -15768,26 +14507,6 @@ Do you want to save message ? Total: Total: - - Messages - Mensajes - - - Click to sort by signature - Haga clic en ordenar por firma - - - This message was signed and the signature checks - Este mensaje fue firmado y la firma comprobada - - - This message was signed but the signature doesn't check - Este mensaje esta firmado, pero la firma no se ha comprobado - - - This message comes from a distant person. - Este mensaje viene de una persona distante. - Mail @@ -15815,7 +14534,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + Guardar imagen + + + + Copy image + + + + Paste as plain text Pegar como texto sin cifrar @@ -15869,7 +14598,7 @@ Do you want to save message ? - + Expand Abrir @@ -15879,7 +14608,7 @@ Do you want to save message ? Quitar objeto - + from de @@ -15914,18 +14643,10 @@ Do you want to save message ? Mensajes pendientes - + Hide Ocultar - - Send invite? - ¿Enviar invitación? - - - Do you really want send a invite with your Certificate? - ¿Está seguro de que quiere enviar una invitación con su certificado? - NATStatus @@ -16063,7 +14784,7 @@ Do you want to save message ? ID del vecino - + Remove unused keys... Eliminar claves sin uso... @@ -16073,7 +14794,7 @@ Do you want to save message ? - + Clean keyring Vaciar el juego de claves @@ -16090,7 +14811,13 @@ Nota: Se hará copia de seguridad de su viejo juego de claves. La eliminación puede fallar cuando se ejecutan varias instancias de Retroshare en la misma máquina. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info Información del juego de claves @@ -16126,18 +14853,13 @@ Para mayor seguridad, previamente se hizo copia de seguridad en fichero de su ju Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. Inconsistencia de datos en el juego de claves. Probablemente esto es un error. Póngase en contacto con los desarrolladores. - - - Export/create a new node - Exportar/crear un nuevo nodo - Trusted keys only Sólo claves de confianza - + Search name Buscar nombre @@ -16147,12 +14869,12 @@ Para mayor seguridad, previamente se hizo copia de seguridad en fichero de su ju Buscar identificación del vecino - + Profile details... Detalles del perfil... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -16161,13 +14883,6 @@ Reported error: Se informo del error: - - NetworkPage - - Network - Red - - NetworkView @@ -16194,7 +14909,7 @@ Se informo del error: NewFriendList - + Offline Friends @@ -16215,7 +14930,7 @@ Se informo del error: - + Groups Grupos @@ -16245,19 +14960,19 @@ Se informo del error: importar su lista de amigos incluyendo grupos - - + + Search Buscar - + ID - + Search ID @@ -16267,12 +14982,12 @@ Se informo del error: - + Show Items Mostrar elementos - + Last contact @@ -16282,7 +14997,7 @@ Se informo del error: IP - + Group Grupo @@ -16397,7 +15112,7 @@ Se informo del error: - + Do you want to remove this node? ¿Quiere eliminar este nodo? @@ -16407,7 +15122,7 @@ Se informo del error: ¿Quiere eliminar este amigo? - + Done! ¡Hecho! @@ -16521,11 +15236,7 @@ al menos un vecino no fue añadido al grupo NewsFeed - Log entries - Entradas de registro (log) - - - + Activity Stream @@ -16540,11 +15251,7 @@ al menos un vecino no fue añadido al grupo Quitar todo - This is a test. - Esto es una prueba. - - - + Newest on top Los más recientes arriba @@ -16554,20 +15261,12 @@ al menos un vecino no fue añadido al grupo Los más antiguos arriba - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;News Feed</h1> <p>The Log Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel and Forum posts</li> <li>New Channels and Forums you can subscribe to</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Suscripción de noticias</h1> <p>La suscripción de registro (log feed) muestra los últimos eventos en su red, ordenados por la hora a la que los recibió. Esto le proporciona un compendio de la actividad de sus amigos. Puede configurar qué eventos mostrar pulsando en <b>Opciones</b>. </p> <p>Los distintos eventos mostrados son: <ul> <li>Intentos de conexión (útil para hacer amigos con nuevas personas y controlar quién está tratando de acceder a usted)</li> <li>Posts de canal y foro</li> <li>Nuevos canales y foros a los que puede suscribirse</li> <li>Mensajes privados de sus amigos</li> </ul> </p> - - - Log - Registro (log) - - - + Activity @@ -16622,10 +15321,6 @@ al menos un vecino no fue añadido al grupo Blogs Blogs - - Security - Seguridad - @@ -16647,10 +15342,6 @@ al menos un vecino no fue añadido al grupo Message Mensaje - - Connect attempt - Intento de conectar - @@ -16667,10 +15358,6 @@ al menos un vecino no fue añadido al grupo Ip security Seguridad de la IP - - Log - Registro (log) - Friend Connected @@ -16681,10 +15368,6 @@ al menos un vecino no fue añadido al grupo Circles Círculos - - Links - Enlaces - Activity @@ -16737,26 +15420,6 @@ al menos un vecino no fue añadido al grupo Chat rooms Salas de chat - - Chat Rooms - Salas de chat - - - Count occurrences of my current identity - Contar apariciones de mi identidad actual - - - Count occurrences of any of the following texts (separate by newlines): - Contar apariciones de cualquiera de los siguientes textos (separar en líneas): - - - Checked, if the identity and the text above occurrences must be in the same case to trigger count. - Márquelo, si las apariciones de la identidad y el texto anterior deben coincidir en mayúsculas y minúsculas para incrementar el recuento. - - - Case sensitive - Distingue mayúsculas y minúsculas - Position @@ -16832,24 +15495,16 @@ al menos un vecino no fue añadido al grupo Disable All Toaster temporarily Deshabilitar todas las notificaciones temporalmente - - Feed - Novedades (feed) - Systray Bandeja del sistema - - Count all unread messages - Contar todos los mensajes no leídos - NotifyQt - + Passphrase required Se requiere frase-contraseña @@ -16869,12 +15524,12 @@ al menos un vecino no fue añadido al grupo ¡Contraseña errónea! - + Please enter your Retroshare passphrase Por favor, introduzca su frase-contraseña de RetroShare - + Unregistered plugin/executable Plugin no registrado/ejecutable @@ -16889,19 +15544,7 @@ al menos un vecino no fue añadido al grupo Por favor, compruebe su reloj del sistema. - Examining shared files... - Examinando archivos compartidos... - - - Hashing file - Calculando hash del archivo - - - Saving file index... - Guardando indice del archivo... - - - + Test Prueba @@ -16912,17 +15555,19 @@ al menos un vecino no fue añadido al grupo + Unknown title Título desconocido - + + Encrypted message Mesaje criptado - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). Para que las salas de chat funcionen adecuadamente, la hora de su computadora tiene que se correcta. Por favor, compruebe si este es el caso (una posible desincronización de varios minutos fue detectada con sus amigos). @@ -16930,7 +15575,7 @@ al menos un vecino no fue añadido al grupo OnlineToaster - + Friend Online Amigo conectado @@ -16982,10 +15627,6 @@ Sin Anonimato D/S: desactiva el reenvío de archivos PGPKeyDialog - - Dialog - Diálogo - Profile info @@ -17051,10 +15692,6 @@ Sin Anonimato D/S: desactiva el reenvío de archivos This profile has signed your own profile key Este perfil ha firmado su propia clave del perfil - - Key signatures : - Firmas de clave : - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> @@ -17084,23 +15721,20 @@ p, li { white-space: pre-wrap; } Clave PGP - - These options apply to all nodes of the profile: - Estas opciones se aplican a todos los nodos del perfil: + + Friend options + - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> - <html><head/><body><p><span style=" font-size:10pt;">Firmar la clave de un amigo es una forma de expresar su confianza en este amigo al resto de sus amigos. Les ayuda a decidir si permitir conexiones desde esa clave en base a su propia confianza. Firmar una clave es absolutamente opcional y no puede deshacerse, así que hágalo con sabiduría.</span></p></body></html> + + These options apply to all nodes of the profile: + Estas opciones se aplican a todos los nodos del perfil: Keysigning: - - Sign PGP key - Firmar clave PGP - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -17137,12 +15771,7 @@ p, li { white-space: pre-wrap; } Incluir firmas - - Options - Opciones - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> <html><head/><body><p align="justify">RetroShare comprueba periódicamente las listas de su amigo en busca de ficheros navegables que coincidan con sus transferencias, para establecer una transferencia directa. En este caso, su amigo sabe que usted está descargando el fichero.</p><p align="justify">Para evitar este comportamiento, sólo para este amigo, desmarque esta casilla. Aún podrá realizar una transferencia directa si la pide explícitamente, por ejemplo, descargándolo de la lista de ficheros de su amigo. Esta configuración se aplica a todas las ubicaciones del mismo nodo.</p></body></html> @@ -17156,10 +15785,6 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this profile (e.g. when the message author is a signed identity that belongs to this profile). This can be used for instance to send files between your own nodes.</p></body></html> - - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> - <html><head/><body><p>Esta opción le permite descargar automáticamente un fichero que esté recomendado en un mensaje proveniente de este nodo. Esto se puede usar, por ejemplo, para enviar ficheros entre sus propios nodos. Se aplica a todas las ubicaciones del mismo nodo.</p></body></html> - Auto-download recommended files from this node @@ -17192,21 +15817,21 @@ p, li { white-space: pre-wrap; } KB/s - - + + RetroShare RetroShare - - + + Error : cannot get peer details. Error: No se pueden obtener los detalles del vecino. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) El algoritmo de la clave proporcionada no está soportado por RetroShare @@ -17227,7 +15852,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. El nivel de confianza es una forma de expresar su propia confianza en esta clave. No es utilizado por la aplicación ni se comparte, pero puede serle útil para recordar buenas/malas claves. @@ -17296,10 +15921,6 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc Check the password! - - Maybe password is wrong - Probablemente la contraseña es errónea - You haven't set a trust level for this key. @@ -17307,12 +15928,12 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc - + Retroshare profile Perfil de RetroShare - + This is your own PGP key, and it is signed by : Esta es su propia clave PGP, y está firmada por: @@ -17338,7 +15959,7 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc PeerItem - + Chat Chat @@ -17359,7 +15980,7 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc Quitar objeto - + Name: Nombre: @@ -17399,7 +16020,7 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc Desfase temporal: - + Write Message Escribir mensaje @@ -17413,10 +16034,6 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc Friend Connected Amigo conectado - - Connect Attempt - Intentando conectar - Connection refused by peer @@ -17455,17 +16072,13 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc Unknown - - Unknown Peer - Vecino desconocido - Hide Ocultar - + Send Message Enviar mensaje @@ -17517,10 +16130,6 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc Chat with this person as... Chatear con esta persona como... - - Send message to this person - Enviar un mensaje a esta persona - Invite to Circle @@ -17579,10 +16188,6 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc <html><head/><body><p>Anyone in your contact list will automatically have a positive opinion if not set. This allows to automatically raise reputations of used nodes. </p></body></html> <html><head/><body><p>Cualquiera en su lista de contactos automáticamente tendrá una opinión positiva si no está establecida. Esto permite erigir automáticamente las reputaciones de los nodos usados. </p></body></html> - - automatically give "Positive" opinion to my contacts - dar automáticamente una opinión "Positiva" a mis contactos - use "positive" as the default opinion for contacts (instead of neutral) @@ -17640,13 +16245,6 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc <html><head/><body><p>Para evitar que las identificaciones borradas reaparezcan porque sean usadas, por ejemplo, en foros o canales, se conservan en una lista durante algún tiempo. Tras aquello, se &quot;eliminan&quot; de la lista de exclusión, y se descargarán de nuevo como no excluidas si se usan en foros, salas de chat, etc.</p></body></html> - - PhotoCommentItem - - Form - Formulario - - PhotoDialog @@ -17654,23 +16252,11 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc PhotoShare Compartir fotos - - Photo - Fotografía - TextLabel Texto de la etiqueta - - Comment - Comentario - - - Summary - Resumen - Album / Photo Name @@ -17731,14 +16317,6 @@ Advertencia: En su opción de Transferencia-de-fichero, establezca permitir desc ... ... - - Add Comment - Añadir comentario - - - Write a comment... - Escribir un comentario... - Album @@ -17809,10 +16387,6 @@ p, li { white-space: pre-wrap; } Create Album Crear álbum - - View Album - Ver álbum - Edit Album Details @@ -17834,17 +16408,17 @@ p, li { white-space: pre-wrap; } Diapositivas - + My Albums Mi álbum - + Subscribed Albums Álbum suscritos - + Shared Albums Álbumes compartidos @@ -17874,7 +16448,7 @@ solicitar editarlo! PhotoSlideShow - + Album Name Nombre del album @@ -17933,19 +16507,19 @@ solicitar editarlo! - - + + TextLabel - + Posted by - + ago @@ -17981,12 +16555,12 @@ solicitar editarlo! PluginItem - + TextLabel Texto de la etiqueta - + Show more details about this plugin Mostrar más detalles sobre este plugin @@ -18132,60 +16706,6 @@ p, li { white-space: pre-wrap; } Plugin look-up directories Directorios de búsqueda de plugin - - Plugin disabled. Click the enable button and restart Retroshare - Complemento deshabilitado. Haga clic en el botón habilitar y reinicie Retroshare - - - [disabled] - [deshabilitado] - - - No API number supplied. Please read plugin development manual. - No se ha suministrado el número del API. Por favor lea el manual de desarrollo del plugin. - - - [loading problem] - [problema al cargar] - - - No SVN number supplied. Please read plugin development manual. - No se ha suministrado el número del SVN. Por favor lea el manual de desarrollo del plugin. - - - Loading error. - Error cargando. - - - Missing symbol. Wrong version? - Símbolo faltante. ¿Versión incorrecta? - - - No plugin object - Ningún objeto plugin - - - Plugins is loaded. - Los plugins están cargados. - - - Unknown status. - Estado desconocido. - - - Check this for developing plugins. They will not -be checked for the hash. However, in normal -times, checking the hash protects you from -malicious behavior of crafted plugins. - Marque esto para el desarrollo de plugins. Esto hará -que no se compruebe el hash. Sin embargo, en -condiciones normales, el control de hash le protege -de un posible comportamiento malicioso de los plugins. - - - <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Plugins</h1> <p>Plugins are loaded from the directories listed in the bottom list.</p> <p>For security reasons, accepted plugins load automatically until the main Retroshare executable or the plugin library changes. In such a case, the user needs to confirm them again. After the program is started, you can enable a plugin manually by clicking on the "Enable" button and then restart Retroshare.</p> <p>If you want to develop your own plugins, contact the developpers team they will be happy to help you out!</p> - <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Complementos</h1> <p>Los complementos (plugins) se cargan desde los directorios que aparecen en la lista del fondo.</p> <p>Por razones de seguridad, los complementos aceptados se cargan automáticamente hasta que el ejecutable principal de RetroShare o la librería del complemento cambian. En tal caso, el usuario necesita confirmarlos de nuevo. Después de que se inicie el programa, puede habilitar un complemento manualmente haciendo clic en el botón "Habilitar", y luego reiniciar RetroShare.</p> <p>Si quiere desarrollar sus propios complementos, contacte con el equipo de desarrolladores ¡ellos estarán contentos de auxiliarle!</p> - Plugins @@ -18255,12 +16775,27 @@ de un posible comportamiento malicioso de los plugins. Ventana de ajustes en la parte superior - + + Ban this person (Sets negative opinion) + Excluir a esta persona (establece una opinión negativa) + + + + Give neutral opinion + Dar una opinión neutral + + + + Give positive opinion + Dar una opinión positiva + + + Choose window color... - + Dock window @@ -18294,22 +16829,6 @@ de un posible comportamiento malicioso de los plugins. Close conversation? - - The person you are talking to has deleted the secured chat tunnel. - La persona con la está hablando ha eliminado el túnel de chat seguro. - - - The chat partner deleted the secure tunnel, messages will be delivered as soon as possible - El interlocutor del chat eliminó el túnel seguro, los mensajes se entregarán tan pronto como sea posible. - - - Closing this window will end the conversation, notify the peer and remove the encrypted tunnel. - Cerrando esta ventana finalizará la conversación, notifíqueselo al vecino y retire el túnel cifrado. - - - Kill the tunnel? - ¿Matar el túnel? - PostedCardView @@ -18329,7 +16848,7 @@ de un posible comportamiento malicioso de los plugins. Nuevo - + Vote up Votar positivo @@ -18349,8 +16868,8 @@ de un posible comportamiento malicioso de los plugins. \/ - - + + Comments Comentarios @@ -18375,13 +16894,13 @@ de un posible comportamiento malicioso de los plugins. - - + + Comment Comentario - + Comments Comentarios @@ -18409,20 +16928,12 @@ de un posible comportamiento malicioso de los plugins. PostedCreatePostDialog - Signed by: - Firmado por: - - - Notes - Notas - - - + Create a new Post - + RetroShare RetroShare @@ -18437,12 +16948,22 @@ de un posible comportamiento malicioso de los plugins. - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File Cargar archivo de imagen - + Post image @@ -18458,7 +16979,17 @@ de un posible comportamiento malicioso de los plugins. - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -18468,23 +16999,7 @@ de un posible comportamiento malicioso de los plugins. - Submit Post - Enviar mensaje - - - You are submitting a link. The key to a successful submission is interesting content and a descriptive title. - Está publicando un enlace. La clave de un envío exitoso es un contenido interesante y un título descriptivo - - - Submit - Enviar - - - Submit a new Post - Publicar un nuevo envío - - - + Please add a Title Por favor añada un título @@ -18504,12 +17019,22 @@ de un posible comportamiento malicioso de los plugins. - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -18524,7 +17049,7 @@ de un posible comportamiento malicioso de los plugins. Publicar como - + Post @@ -18535,7 +17060,7 @@ de un posible comportamiento malicioso de los plugins. Imágen - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -18545,7 +17070,7 @@ de un posible comportamiento malicioso de los plugins. Título - + Link Enlace @@ -18553,44 +17078,12 @@ de un posible comportamiento malicioso de los plugins. PostedDialog - Posted Links - Enlaces de Posted - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Posted</h1> <p>The posted service allows you to share internet links, that spread among Retroshare nodes like forums and channels</p> <p>Links can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Posted links are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Posted</h1> <p>El servicio posted le permite compartir enlaces de Internet, que se difunden entre nodos RetroShare como foros y canales</p> <p>Los enlaces pueden ser comentados por usuarios suscritos. Es un sistema de promoción que también da la oportunidad de ilustrar enlaces importantes.</p> <p>No hay restricciones en cuanto a qué enlaces se comparten. Tenga cuidado cuando pulse sobre ellos.</p> <p>Los enlaces de posted se conservan durante %1 días, y se sincronizan más allá de los últimos %2 días, a menos que usted cambie esto.</p> - - - Create Topic - Crear tema - - - My Topics - Mis temas - - - Subscribed Topics - Temas suscritos - - - Popular Topics - Temas populares - - - Other Topics - Otros temas - - - Links - Enlaces - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -18624,31 +17117,7 @@ de un posible comportamiento malicioso de los plugins. PostedGroupDialog - Posted Topic - Tema de Posted - - - Add Topic Admins - Añadir tema de administradores - - - Select Topic Admins - Seleccionar tema de administradores - - - Create New Topic - Crear nuevo tema - - - Edit Topic - Editar tema - - - Update Topic - Actualizar temática - - - + Create New Board @@ -18686,7 +17155,17 @@ de un posible comportamiento malicioso de los plugins. PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted Suscribirse a Posted @@ -18702,7 +17181,7 @@ de un posible comportamiento malicioso de los plugins. - + Expand Expandir @@ -18717,24 +17196,17 @@ de un posible comportamiento malicioso de los plugins. - Posted Description - Descripción de Posted - - - Loading - Cargando - - - New Posted - Nuevo Posted - - - + Loading... - + + Never + Nunca + + + New Board @@ -18747,22 +17219,18 @@ de un posible comportamiento malicioso de los plugins. PostedItem - + 0 0 - Site - Lugar - - - - + + Comments Comentarios - + Copy RetroShare Link Copiar enlace de RetroShare @@ -18773,12 +17241,12 @@ de un posible comportamiento malicioso de los plugins. - + Comment Comentario - + Comments Comentarios @@ -18788,7 +17256,7 @@ de un posible comportamiento malicioso de los plugins. <p><font color="#ff0000"><b>El autor de este mensaje (con Identificación %1) está excluído.</b> - + Click to view Picture @@ -18798,21 +17266,17 @@ de un posible comportamiento malicioso de los plugins. Ocultar - + Vote up Votar positivo - + Vote down Votar negativo - \/ - \/ - - - + Set as read and remove item Ajustar como leer y eliminar elemento @@ -18822,7 +17286,7 @@ de un posible comportamiento malicioso de los plugins. Nuevo - + New Comment: Nuevo comentario: @@ -18832,7 +17296,7 @@ de un posible comportamiento malicioso de los plugins. Valor del comentario - + Name Nombre @@ -18873,77 +17337,10 @@ de un posible comportamiento malicioso de los plugins. - + Loading Cargando - - By - Por - - - - PostedListWidget - - Form - Formulario - - - Hot - Acalorado - - - New - Nuevo - - - Top - Más alto - - - Today - Hoy - - - Yesterday - Ayer - - - This Week - Esta semana - - - This Month - Este mes - - - This Year - Este año - - - Submit a new Post - Publicar un nuevo envío - - - Next - Siguiente - - - RetroShare - RetroShare - - - Please create or choose a Signing Id before Voting - Por favor, cree o seleccione una Id de firma antes de votar - - - Previous - Anterior - - - 1-10 - 1-10 - PostedListWidgetWithModel @@ -18963,7 +17360,17 @@ de un posible comportamiento malicioso de los plugins. - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -18973,15 +17380,15 @@ de un posible comportamiento malicioso de los plugins. Administrador: - + - + unknown desconocido - + Distribution: Distribución: @@ -18991,42 +17398,42 @@ de un posible comportamiento malicioso de los plugins. - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -19046,7 +17453,7 @@ de un posible comportamiento malicioso de los plugins. Acalorado - + Search Buscar @@ -19076,17 +17483,17 @@ de un posible comportamiento malicioso de los plugins. - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -19101,12 +17508,17 @@ de un posible comportamiento malicioso de los plugins. Vacío - + Copy RetroShare Link Copiar enlace de RetroShare - + + Copy http Link + + + + Show author in People tab @@ -19116,27 +17528,31 @@ de un posible comportamiento malicioso de los plugins. Editar - + + information información - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -19151,7 +17567,7 @@ de un posible comportamiento malicioso de los plugins. Suscribirse - + Never Nunca @@ -19225,6 +17641,16 @@ de un posible comportamiento malicioso de los plugins. No Channel Selected Ningún canal seleccionado + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -19233,14 +17659,6 @@ de un posible comportamiento malicioso de los plugins. Tabs Pestañas - - Open each topic in a new tab - Abrir cada asunto en una nueva pestaña - - - Links - Enlaces - Open each board in a new tab @@ -19254,10 +17672,6 @@ de un posible comportamiento malicioso de los plugins. PostedUserNotify - - Posted - Posted - Board Post @@ -19326,25 +17740,17 @@ de un posible comportamiento malicioso de los plugins. Administrador de perfiles - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Seleccione una clave de nodo RetroShare de la lista de debajo para ser usada en otra computadora, y pulse &quot;Exportar clave seleccionada.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Para crear una nueva ubicación en un equipo distinto, seleccione el administrador de identidades en la ventana de inicio de sesión. Desde allí puede importar el fichero de clave y crear una nueva ubicación para esa clave. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Crear un nuevo nodo con la misma clave permite que sus nodos amigos le acepten automáticamente.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> + @@ -19455,7 +17861,7 @@ y utilizar el botón Importar para cargarla ProfileWidget - + Edit status message Editar mensaje de estado @@ -19471,7 +17877,7 @@ y utilizar el botón Importar para cargarla Administrador de perfiles - + Public Information Información pública @@ -19506,12 +17912,12 @@ y utilizar el botón Importar para cargarla En línea desde: - + Other Information Otra información - + My Address Mi dirección @@ -19555,51 +17961,27 @@ y utilizar el botón Importar para cargarla PulseAddDialog - Post From: - Entrada de: - - - Account 1 - Cuenta 1 - - - Account 2 - Cuenta 2 - - - Account 3 - Cuenta 3 - - - + Add to Pulse Añadir a Pulse - filter - filtro - - - URL Adder - URL añadida - - - + Display As Mostrar como - + URL URL - + GroupLabel - + IDLabel @@ -19609,12 +17991,12 @@ y utilizar el botón Importar para cargarla De: - + Head - + Head Shot @@ -19644,13 +18026,13 @@ y utilizar el botón Importar para cargarla Negativo - - + + Whats happening? - + @@ -19662,12 +18044,22 @@ y utilizar el botón Importar para cargarla - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -19676,17 +18068,13 @@ y utilizar el botón Importar para cargarla Cancel Cancelar - - Post Pulse to Wire - Mensaje de Pulso para Wire - Post - + Reply to Pulse @@ -19701,34 +18089,24 @@ y utilizar el botón Importar para cargarla - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - De - - - Date - Fecha - - - ... - ... + + Load Picture File + Cargar archivo de imagen @@ -19739,7 +18117,7 @@ y utilizar el botón Importar para cargarla Formulario - + @@ -19758,7 +18136,7 @@ y utilizar el botón Importar para cargarla PulseReply - + icn @@ -19768,7 +18146,7 @@ y utilizar el botón Importar para cargarla - + REPLY @@ -19795,7 +18173,7 @@ y utilizar el botón Importar para cargarla - + FOLLOW @@ -19805,7 +18183,7 @@ y utilizar el botón Importar para cargarla - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -19825,7 +18203,7 @@ y utilizar el botón Importar para cargarla - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -19941,7 +18319,7 @@ y utilizar el botón Importar para cargarla - + FOLLOW @@ -19949,37 +18327,42 @@ y utilizar el botón Importar para cargarla PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -20011,7 +18394,7 @@ y utilizar el botón Importar para cargarla - + FOLLOW @@ -20019,8 +18402,8 @@ y utilizar el botón Importar para cargarla QObject - - + + Confirmation Confirmación @@ -20290,12 +18673,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace Detalles del vecino - + File Request canceled Solicitud del archivo cancelada - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. Esta versión de RetroShare está usando OpenPGP SDK. Como efecto secundario, no está utilizando el juego de claves PGP compartido por el sistema, pero tiene su propio juego de claves compartido por todas las instancias de RetroShare. <br><br>No parece que tenga tal juego de claves, aunque las claves PGP son mencionadas por cuentas existentes de RetroShare, probablemente debido a que acaba de cambiar a esta nueva versión del programa. @@ -20326,7 +18709,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace Ocurrió un error inesperado. Error: 'RsInit::InitRetroShare unexpected return code %1'. - + Cannot start Tor Manager! ¡No se puede iniciar el Administrador de Tor! @@ -20364,7 +18747,7 @@ El error obtenido es:" No fue posible iniciar un servicio oculto. - + Multiple instances Instancias múltiples @@ -20387,6 +18770,26 @@ archivo bloqueado: Archivo bloqueado: + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -20407,14 +18810,6 @@ archivo bloqueado: End-to-end encrypted conversation established - - Tunnel is pending... Messages will be delivered as soon as possible - El túnel está pendiente... Los mensajes se entregarán tan pronto como sea posible - - - Secured tunnel is working. Messages are delivered immediately! - El túnel asegurado está funcionando. ¡Los mensajes se entregarán inmediatamente! - The collection file %1 could not be opened. @@ -20477,7 +18872,7 @@ El error reportado es: Datos reenviados - + You appear to have nodes associated to DSA keys: Parece que tiene nodos asociados a claves DSA: @@ -20487,7 +18882,7 @@ El error reportado es: Las claves DSA aún no están soportadas por esta versión de RetroShare. Todos estos nodos serán inutilizables. Lo sentimos por esto. - + enabled habilitado @@ -20497,7 +18892,7 @@ El error reportado es: deshabilitado - + Move IP %1 to whitelist Mover IP %1 a la lista blanca @@ -20513,7 +18908,7 @@ El error reportado es: - + %1 seconds ago hace %1 segundos @@ -20581,7 +18976,7 @@ Security: no anonymous IDs Seguridad: No hay identificaciones anónimas - + Join chat room Unirse a la sala de chat @@ -20609,7 +19004,7 @@ Seguridad: No hay identificaciones anónimas ¡no se pudo interpretar el fichero XML! - + Indefinitely Indefinidamente @@ -20789,13 +19184,29 @@ Seguridad: No hay identificaciones anónimas Ban list + + + Name + Nombre + + Node + Nodo + + + + Address + Dirección + + + + Status Estado - + NXS @@ -20988,10 +19399,6 @@ Seguridad: No hay identificaciones anónimas Click to resume the hashing process Haz clic para continuar con el proceso de hashing - - <p>This certificate contains: - <p>Este certificado contiene: - Idle @@ -21042,6 +19449,18 @@ Seguridad: No hay identificaciones anónimas Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -21199,7 +19618,7 @@ p, li { white-space: pre-wrap; } - + Network Wide En toda la red @@ -21382,7 +19801,7 @@ p, li { white-space: pre-wrap; } Formulario - + The loading of embedded images is blocked. La carga de las imágenes incrustadas esta bloqueada. @@ -21395,7 +19814,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default Permitido por defecto @@ -21568,12 +19987,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + Guardar imagen + + + + Copy image + + + + Document source @@ -21581,12 +20010,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options Opciones de vista de árbol - + Show Header @@ -21616,14 +20045,6 @@ p, li { white-space: pre-wrap; } Show column … - - Show column... - Mostrar columna... - - - [no title] - [sin título] - RatesStatus @@ -22284,7 +20705,7 @@ Si crees que es correcto, elimina la correspondiente línea del archivo y reábr RsDownloadListModel - + Name i.e: file name Nombre @@ -22405,7 +20826,7 @@ Si crees que es correcto, elimina la correspondiente línea del archivo y reábr RsFriendListModel - + Name Nombre @@ -22425,7 +20846,7 @@ Si crees que es correcto, elimina la correspondiente línea del archivo y reábr IP - + Profile ID @@ -22485,7 +20906,7 @@ reenviado a sus amigos. El mensaje será reenviado a sus amigos. - + [ ... Redacted message ... ] [ ... Mensaje redactado ... ] @@ -22499,11 +20920,6 @@ reenviado a sus amigos. [Unknown] - - - [ ... Missing Message ... ] - [ ... Mensaje perdido ... ] - RsMessageModel @@ -22517,6 +20933,11 @@ reenviado a sus amigos. From + + + To + A + Subject @@ -22539,13 +20960,18 @@ reenviado a sus amigos. - Click to sort by read - Pulsar para ordenar por leido + Click to sort by read status + - Click to sort by from - Pulsar para ordenar por remitente + Click to sort by author + + + + + Click to sort by destination + @@ -22568,7 +20994,9 @@ reenviado a sus amigos. - + + + [Notification] @@ -22589,7 +21017,7 @@ reenviado a sus amigos. Rshare - + Resets ALL stored RetroShare settings. Reiniciar todos los ajustes de RetroShare. @@ -22650,7 +21078,7 @@ reenviado a sus amigos. Determinar el idioma de retroShare. - + Unable to open log file '%1': %2 No se puede abrir el archivo de registro '%1': %2 @@ -22671,11 +21099,7 @@ reenviado a sus amigos. No se pudo crear el directorio de datos: %1 - Revision - Revisión - - - + opmode modoop @@ -22705,7 +21129,7 @@ reenviado a sus amigos. Información sobre el uso de la GUI - + Invalid language code specified: Código de idioma especificado no válido: @@ -22723,7 +21147,7 @@ reenviado a sus amigos. RshareSettings - + Registry Access Error. Maybe you need Administrator right. Error de acceso al registro. Puede que necesite privilegios de Administrador. @@ -22740,12 +21164,12 @@ reenviado a sus amigos. SearchDialog - + Enter a keyword here (at least 3 char long) Introduzca una palabra clave aquí (como mínimo 3 letras) - + Start Search Comenzar búsqueda @@ -22807,7 +21231,7 @@ en la red (siempre informar de archivos disponibles) Limpiar - + KeyWords Palabras clave @@ -22822,7 +21246,7 @@ en la red (siempre informar de archivos disponibles) ID de la búsqueda - + Filename Nombre de archivo @@ -22922,23 +21346,23 @@ en la red (siempre informar de archivos disponibles) Descargar seleccionados - + File Name Nombre de archivo - + Download Descargar - + Copy RetroShare Link Copiar enlace de RetroShare - + Send RetroShare Link Enviar enlace de RetroShare @@ -22948,7 +21372,7 @@ en la red (siempre informar de archivos disponibles) - + Download Notice Notificación de descarga @@ -22985,7 +21409,7 @@ en la red (siempre informar de archivos disponibles) Borrar todo - + Folder Carpeta @@ -22996,17 +21420,17 @@ en la red (siempre informar de archivos disponibles) - + New RetroShare Link(s) Nuevo(s) enlace(s) de RetroShare - + Open Folder Abrir carpeta - + Create Collection... Crear colección... @@ -23026,7 +21450,7 @@ en la red (siempre informar de archivos disponibles) Descargar desde archivo de colección... - + Collection Colección @@ -23034,7 +21458,7 @@ en la red (siempre informar de archivos disponibles) SecurityIpItem - + Peer details Detalles del vecino @@ -23050,22 +21474,22 @@ en la red (siempre informar de archivos disponibles) Eliminar objeto - + IP address: Dirección IP: - + Peer ID: Identificación del vecino: - + Location: Lugar: - + Peer Name: Nombre del vecino: @@ -23082,7 +21506,7 @@ en la red (siempre informar de archivos disponibles) Ocultar - + but reported: pero se informó de: @@ -23107,8 +21531,8 @@ en la red (siempre informar de archivos disponibles) <p>Esta es la IP a la que su amigo afirma estar conectado. Si acaba de cambiar las IPs, esta es una advertencia en falso. Si no, eso significa que su conexión con este amigo está siendo repetida por un vecino intermedio, que sería sospechoso.</p> - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> <html><head/><body><p>Esta advertencia está aquí para protegerle contra ataques de interposición y reenvío de tráfico. </p><p><br/></p><p>Sin embargo, si sencillamente su IP cambia por alguna razón (algunos ISPs fuerzan cambios de IPs regularmente) esta advertencia sólo le dice que un amigo conectó a la nueva IP antes de que RetroShare notara el cambio de IP. No hay nada incorrecto en este caso.</p><p><br/></p><p>Puede suprimir fácilmente falsas advertencias añadiendo sus propias IPs a la lista-blanca (ej. el rango de su ISP), o deshabilitando completamente estas advertencias en Opciones-&gt;Notificar-&gt;Novedades (feed).</p></body></html> @@ -23116,7 +21540,7 @@ en la red (siempre informar de archivos disponibles) SecurityItem - + wants to be friend with you on RetroShare quiere ser su amigo en RetroShare @@ -23147,7 +21571,7 @@ en la red (siempre informar de archivos disponibles) - + Expand Expandir @@ -23192,12 +21616,12 @@ en la red (siempre informar de archivos disponibles) Estado: - + Write Message Escribir mensaje - + Connect Attempt Intentando conectar @@ -23217,17 +21641,22 @@ en la red (siempre informar de archivos disponibles) Desconocido (saliente) intento de conexión - + Unknown Security Issue Problema de seguridad desconocido - - A unknown peer + + SSL request - + + An unknown peer + + + + Unknown @@ -23237,11 +21666,7 @@ en la red (siempre informar de archivos disponibles) - Unknown Peer - Vecino desconocido - - - + Hide Ocultar @@ -23251,7 +21676,7 @@ en la red (siempre informar de archivos disponibles) ¿Quiere eliminar este amigo? - + Certificate has wrong signature!! This peer is not who he claims to be. ¡¡El certificado tiene una firma errónea!! El vecino no es quien dice ser. @@ -23261,12 +21686,12 @@ en la red (siempre informar de archivos disponibles) Certificado perdido/dañado. No es un usuario RetroShare real. - + Certificate caused an internal error. El certificado provocó un error interno. - + Peer/node not in friendlist (PGP id= El vecino/nodo no está en la lista de amigos (identificación PGP= @@ -23325,12 +21750,12 @@ en la red (siempre informar de archivos disponibles) - + Local Address Dirección local - + NAT NAT @@ -23351,22 +21776,22 @@ en la red (siempre informar de archivos disponibles) Puerto: - + Local network Red local - + External ip address finder Buscador de direcciónes IP externas - + UPnP UPnP - + Known / Previous IPs: IPs conocidas / anteriores: @@ -23382,21 +21807,16 @@ behind a firewall or a VPN. tras de un cortafuegos o una VPN. - - Allow RetroShare to ask my ip to these websites: - Permitir a RetroShare preguntarle mi ip a estos sitios web: - - - - - + + + kB/s kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. Rango de puertos aceptable desde 10 a 65535. Normalmente los puertos por debajo del 1024 están reservados por su sistema. @@ -23406,23 +21826,46 @@ behind a firewall or a VPN. Rango de puertos aceptable desde 10 a 65535. Normalmente los puertos por debajo del 1024 están reservados para su sistema. - + Onion Address Dirección onion - + Discovery On (recommended) Descubrimiento activado (recomendado) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. Tor ha sido configurado automáticamente por Retroshare. No deberías necesitar cambiar nada aquí. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off Descubrimiento inactivo @@ -23432,7 +21875,7 @@ behind a firewall or a VPN. Oculto - Ver configuración - + I2P Address Dirección I2P @@ -23457,41 +21900,95 @@ behind a firewall or a VPN. entrada correcta - - + + + Proxy seems to work. El proxy parece funcionar. - + + I2P proxy is not enabled El proxy I2P no está habilitado - - BOB is running and accessible - BOB está funcionando y accesible + + SAMv3 is running and accessible + - BOB is not accessible! Is it running? - BOB no es accesible! Está funcionando? + SAMv3 is not accessible! Is i2p running and SAM enabled? + - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - Retroshare utiliza BOB para crear un %1 túnel en %2:%3 (llamado %4) - -Al cambiar opciones (p.e. el puerto) utiliza los botones de abajo para reiniciar BOB. - - + - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client cliente @@ -23506,73 +22003,7 @@ Al cambiar opciones (p.e. el puerto) utiliza los botones de abajo para reiniciar desconocido - - - - BOB is processing a request - BOB está procesando una petición - - - - connectivity check - comprobación de conectividad - - - - generating key - creando clave - - - - starting up - iniciando - - - - shuting down - apagando - - - - BOB is processing a request: %1 - BOB está procesando una petición: %1 - - - - BOB is broken - - BOB está roto - - - - - BOB encountered an error: - - BOB ha encontrado un error: - - - - - BOB tunnel is running - El túnel de BOB está funcionando - - - - BOB is working fine: tunnel established - BOB está funcionando bien: túnel establecido - - - - BOB tunnel is not running - El túnel de BOB no está funcionando - - - - BOB is inactive: tunnel closed - BOB está inactivo: túnel cerrado - - - + request a new server key solicita una nueva clave de servidor @@ -23582,22 +22013,7 @@ Al cambiar opciones (p.e. el puerto) utiliza los botones de abajo para reiniciar carga la clave de servidor desde base64 - - stop BOB tunnel first to generate a new key - para generar una nueva clave, primero detén el túnel BOB - - - - stop BOB tunnel first to load a key - para cargar una clave, primero detén el túnel BOB - - - - stop BOB tunnel first to disable BOB - detén el túnel BOB para desactivar BOB - - - + You are reachable through the hidden service. Usted no es alcanzable mediante el servicio oculto. @@ -23611,12 +22027,12 @@ Also check your ports! ¡Compruebe también sus puertos! - + [Hidden mode] [Modo oculto] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> <html><head/><body><p>Esto limpia la lista de direcciones conocidas. Esta acción es útil si por algún motivo su lista de direcciones contiene una dirección no-válida/irrelevante/caducada que quiera evitar pasar a sus amigos como dirección de contacto.</p></body></html> @@ -23626,7 +22042,7 @@ Also check your ports! Limpiar - + Download limit (KB/s) Límite de descarga (KB/s) @@ -23641,24 +22057,24 @@ Also check your ports! Límite de subida (KB/s) - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> <html><head/><body><p>El límite de subida cubre el total de la aplicación. Un límite de subida demasiado pequeño eventualmente podría bloquear servicios de prioridad baja (canales de foros). Un valor mínimo recomendado es 50 KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. ATENCIÓN: Estos valores no tienen en cuenta los Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -23675,17 +22091,7 @@ Ahora, añade la dirección (p.e. 127.0.0.1) y el puerto que has elegido para el Puedes conectar con nodos ocultos incluso si estás utilizando un nodo estándar. ¿Por qué no utilizar Tor y/o I2P? - - Automatic I2P/BOB - I2P/BOB automático - - - - Enable I2P BOB - changing this requires a restart to fully take effect - Activar I2P BOB - este cambio requiere reiniciar para que tenga el efecto esperado - - - + enableds advanced settings activa la configuración avanzada @@ -23695,12 +22101,7 @@ Puedes conectar con nodos ocultos incluso si estás utilizando un nodo estándar modo avanzado - - I2P Basic Open Bridge - I2P Basic Open Bridge - - - + I2P Instance address Dirección de instancia de I2P @@ -23710,17 +22111,7 @@ Puedes conectar con nodos ocultos incluso si estás utilizando un nodo estándar 127.0.0.1 - - I2P proxy port - Puerto del proxy I2P - - - - BOB accessible - BOB accesible - - - + Address Dirección @@ -23760,7 +22151,7 @@ Puedes conectar con nodos ocultos incluso si estás utilizando un nodo estándar cargar clave - + Start Iniciar @@ -23775,12 +22166,7 @@ Puedes conectar con nodos ocultos incluso si estás utilizando un nodo estándar Detener - - BOB status - Estado de BOB - - - + Incoming Entrante @@ -23827,7 +22213,32 @@ Para terminar, asegúrate de que los puertos coinciden con la configuración. Si tienes problemas conectando a través de Tor, comprueba sus logs. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay Repetidor @@ -23882,7 +22293,7 @@ Si tienes problemas conectando a través de Tor, comprueba sus logs.Total: - + Warning: This bandwidth adds up to the max bandwidth. Atención: este ancho de banda supera el máximo ancho de banda. @@ -23907,7 +22318,7 @@ Si tienes problemas conectando a través de Tor, comprueba sus logs.Quitar servidor - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -23921,7 +22332,7 @@ Si tienes problemas conectando a través de Tor, comprueba sus logs.Red - + IP Filters Filtros de IP @@ -23944,7 +22355,7 @@ Si tienes problemas conectando a través de Tor, comprueba sus logs. - + Status Estado @@ -24004,17 +22415,28 @@ Si tienes problemas conectando a través de Tor, comprueba sus logs.Añadir a la lista blanca - + Hidden Service Configuration Configuración de servicio oculto - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>Este es el puerto proxy Socks de Tor. Su nodo RetroShare puede usar este puerto para conectar a</p><p>nodos ocultos. El led de la derecha se vuelve verde cuando este puerto esté activo en su computadora. </p><p>Sin embargo esto no significa que su tráfico de RetroShare transite a través de Tor. Sólo lo hace si </p><p>conecta a nodos ocultos, o si usted mismo está ejecutando un nodo oculto.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>Este led a la izquierda será verde cuando el puerto de escucha esté activo en su computadora. No</p><p>significa que su tráfico de RetroShare transite a través de Tor. Sólo lo hará si</p><p>conecta a nodos ocultos, o si usted mismo está ejecutando un nodo oculto.</p></body></html> @@ -24030,18 +22452,18 @@ Si tienes problemas conectando a través de Tor, comprueba sus logs. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>Este led a la izquierda será verde cuando el puerto de escucha esté activo en su computadora. No</p><p>significa que su tráfico de RetroShare transite a través de I2P. Sólo lo hará si</p><p>conecta a nodos ocultos, o si usted mismo está ejecutando un nodo oculto.</p></body></html> - + I2P outgoing Okay Salida de I2P correcta - + Service Address Dirección del servicio @@ -24076,12 +22498,12 @@ Si tienes problemas conectando a través de Tor, comprueba sus logs.Por favor, introduzca una dirección de servicio - + IP Range Rango de IPs - + Reported by DHT for IP masquerading Fue señalado por la DHT (tabla distribuida de hashes) para enmascaramiento de IP (IP masquerading) @@ -24104,22 +22526,22 @@ Si tienes problemas conectando a través de Tor, comprueba sus logs.Añadido por usted - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> <html><head/><body><p>Las IPs en lista blanca son reunidas desde las siguientes fuentes: IPs provenientes del interior de certificados intercambiados manualmente, rangos de IPs introducidos por usted en esta ventana, o en los elementos de seguridad de las novedades (feed).</p><p>El comportamiento predeterminado para RetroShare es (1) permitir siempre la conexión a los vecinos con IP en la lista blanca; (2) requerir opcionalmente que las IPs estén en la lista blanca. Puede cambiar este comportamiento en la ventana &quot;Detalles&quot; de cada nodo RetroShare. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> <html><head/><body><p>La DHT (tabla dinámica de hashes) le permite responder a las peticiones de conexión de sus amigos usando la DHT de BitTorrent. Esto mejora enormemente la conectividad. No se almacena en realidad información en la DHT, sólo se usa como un proxy (interpuesto) del sistema para ponerse en contacto con otros nodos RetroShare.</p><p>El servicio de Descubrimiento envía el nombre del nodo y las identificaciones de sus contactos de confianza a vecinos conectados, para ayudarles a elegir nuevos amigos. Sin embargo, el establecimiento de amistad nunca es automático, y ambos vecinos todavía necesitan confiar el uno en el otro para permitir la conexión. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> <html><head/><body><p>El indicador se vuelve verde tan pronto como RetroShare logra obtener su propia IP de los sitios web listados debajo, si habilita esa acción. RetroShare también usará otros medios para averiguar su propia IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> <html><head/><body><p>Esta lista se rellena automáticamente con información reunida en múltiples fuentes: vecinos con enmascaramiento de los que informó la DHT, rangos de IPs introducidos por usted, y rangos de IPs de los que informaron sus amigos. La configuración predeterminada debe protegerle contra la repetición de tráfico a gran escala.</p><p>Conjeturar automáticamente si las IPs son de enmascaramiento puede incluir las IPs de sus amigos en la lista negra. En ese caso, use el menú contextual para incluirlas en la lista blanca.</p></body></html> @@ -24154,26 +22576,22 @@ Si tienes problemas conectando a través de Tor, comprueba sus logs.Excluir automáticamente rangos de IPs de enmascaramiento de la DHT comenzando en - + Outgoing Manual Tor/I2P Tor/I2P saliente manual - - <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. <br/>If you prefer to use BOB to automatically manage I2P check the other tab.</p></body></html> - <html><head/><body><p>Configura tus SOCKS proxy Tor e I2P aquí. <br/>Si prefieres utilizar BOB para gestionar automáticamente I2P, visita la otra pestaña.</p></body></html> - Tor Socks Proxy Proxy Socks de Tor - + Tor outgoing Okay Salida de Tor correcta - + Tor proxy is not enabled El proxy de Tor no está habilitado @@ -24253,7 +22671,7 @@ Si tienes problemas conectando a través de Tor, comprueba sus logs. ShareKey - + check peers you would like to share private publish key with seleccione los vecinos con los que desea compartir su clave privada de publicación @@ -24263,12 +22681,12 @@ Si tienes problemas conectando a través de Tor, comprueba sus logs.Compartir con amigo - + Share Compartir - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. Puede permitir a sus amigos saber de su canal al compartirlo con ellos. @@ -24288,7 +22706,7 @@ Seleccione los amigos con los que quiere compartir su canal. Administrador de carpetas compartidas - + Shared directory Directorio compartido @@ -24308,17 +22726,17 @@ Seleccione los amigos con los que quiere compartir su canal. Visibilidad - + Add new Añadir nuevo - + Cancel Cancelar - + Add a Share Directory Compartir una carpeta @@ -24328,7 +22746,7 @@ Seleccione los amigos con los que quiere compartir su canal. Quitar - + Apply and close Aplicar y cerrar @@ -24419,7 +22837,7 @@ Seleccione los amigos con los que quiere compartir su canal. Carpeta no encontrada o nombre de carpeta no aceptado. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. Esta es una lista de carpetas compartidas. Puedes añadir o quitar carpetas utilizando los botones inferiores. Cuando añades una carpeta inicialmente se comparte todo su contenido. Puedes cambiar los permisos individualmente para cada carpeta. @@ -24427,7 +22845,7 @@ Seleccione los amigos con los que quiere compartir su canal. SharedFilesDialog - + Files Archivos @@ -24478,11 +22896,16 @@ Seleccione los amigos con los que quiere compartir su canal. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files Comprobar archivos - + Download selected Descargar seleccionados @@ -24492,7 +22915,7 @@ Seleccione los amigos con los que quiere compartir su canal. Descargar - + Copy retroshare Links to Clipboard Copiar enlace de RetroShare al portapapeles @@ -24507,7 +22930,7 @@ Seleccione los amigos con los que quiere compartir su canal. Enviar enlaces de RetroShare - + Some files have been omitted Algunos ficheros se han omitido @@ -24523,7 +22946,7 @@ Seleccione los amigos con los que quiere compartir su canal. Recomendaciones - + Create Collection... Crear colección... @@ -24548,7 +22971,7 @@ Seleccione los amigos con los que quiere compartir su canal. Descargar desde archivo de colección... - + Some files have been omitted because they have not been indexed yet. Algunos ficheros se han omitido porque aún no han sido indexados. @@ -24691,12 +23114,12 @@ Seleccione los amigos con los que quiere compartir su canal. SplashScreen - + Load configuration Cargar configuración - + Create interface Crear interfaz @@ -24720,7 +23143,7 @@ Seleccione los amigos con los que quiere compartir su canal. Recordar contraseña - + Log In Iniciar sesión @@ -25077,7 +23500,7 @@ Esta elección puede revertirse en la configuración. Mensaje de estado - + Message: Mensage: @@ -25322,7 +23745,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags Quitar todas las etiquetas @@ -25358,12 +23781,15 @@ p, li { white-space: pre-wrap; } Configurando Tor... - + + Tor status: Estado Tor: - + + + Unknown Desconocido @@ -25373,18 +23799,13 @@ p, li { white-space: pre-wrap; } No iniciado - - Hidden service address: - Dirección del servicio oculto: + + Hidden address: + - - Tor bootstrap status: - Estado de la secuencia Tor: - - - - + + Not set No establecido @@ -25394,12 +23815,57 @@ p, li { white-space: pre-wrap; } Dirección onion: - + + Error + Error + + + + Not connected + No conectado + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path Comprueba que Tor es accesible en tu ruta de ejecución - + [Waiting for Tor...] [Esperando a Tor...] @@ -25407,21 +23873,17 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor Tor - - <p>This version of Retroshare uses Tor to connect to your friends.</p> - <p>Esta versión de RetroShare utiliza Tor para conectar con tus amigos.</p> - <p>This version of Retroshare uses Tor to connect to your trusted nodes.</p> - + Tor is currently offline Tor está actualmente fuera de línea @@ -25432,11 +23894,12 @@ p, li { white-space: pre-wrap; } + No tor configuration Sin configuración de Tor - + Tor proxy is OK @@ -25464,7 +23927,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options Opciones de transferencias @@ -25475,7 +23938,7 @@ p, li { white-space: pre-wrap; } Máximas descargas simultáneas: - + Shared Directories Directorios compartidos @@ -25485,22 +23948,27 @@ p, li { white-space: pre-wrap; } Compartir automáticamente el directorio de entrada (recomendado) - - Edit Share - Editar compartidos - - - + Directories - + + Configure shared directories + Configurar directorios compartidos + + + Auto-check shared directories every Comprobar automáticamente los directorios compartidos cada + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) minuto(s) @@ -25585,7 +24053,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -25594,7 +24062,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) Máximo de subidas por amigo (0 = sin límite) @@ -25619,7 +24092,12 @@ p, li { white-space: pre-wrap; } Permitir descarga directa: - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming Streaming @@ -25678,38 +24156,13 @@ p, li { white-space: pre-wrap; } Trust friend nodes with banned files - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> es capaz de transferir datos y peticiones de búsqueda entre vecinos que no necesariamente son amigos. Sin embargo, este tráfico sólo transita a través de una lista de amigos conectados, y es anónimo.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Puede establecer indicativos para cada directorio compartido por separado en el cuadro de diálogo de ficheros compartidos para que sean:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Explorables por amigos</span>: Los ficheros son vistos por sus amigos.</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Compartidos anónimamente</span>: Los ficheros son alcanzables anónimamente a través de túneles anónimos F2F (entre amigos).</li></ul></body></html> - Max. tunnel req. forwarded per second: Máximo de peticiones de túnel repetidas por segundo: - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>provoca que la transferencia requiera 1 MB de pedazos del archivo en orden desde el principio, para facilitar la previsualización durante la descarga. <span style=" font-weight:600;">Aleatoria</span> es puramente aleatoria y favorece un comportamiento de enjambre (subir y bajar el archivo simultáneamente). <span style=" font-weight:600;">Progresiva</span> es un equilibrio, selecciona el siguiente pedazo aleatoriamente dentro de los 50 MB posteriores al final de un archivo parcial. Eso permite cierta aleatorización a la vez que previene grandes tiempos de inicialización de archivos vacíos.</p></body></html> - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> <html><head/><body><p>RetroShare suspenderá todas las transferencias y configurará el guardado de archivos si el espacio de disco baja de este límite. Esto previene la pérdida de información en algunos sistemas. Una ventana emergente le alertará cuando eso suceda.</p></body></html> @@ -25719,7 +24172,17 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Este valor controla cuantas peticiones de túneles puede repetir por segundo su vecino. </p><p>Si tiene un gran ancho de banda para Internet, puede elevar esto hasta 30-40, para estadísticamente permitir pasar a túneles más largos. No obstante tenga mucho cuidado, ya que esto genera muchos paquetes pequeños que pueden ralentizar significativamente su propia transferencia de archivos. </p><p>El valor por defecto es 20. Si no está seguro, déjelo así.</p></body></html> - + + Warning + Aviso + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory Establecer directorio de entrada @@ -25747,7 +24210,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed Descarga completa @@ -25771,39 +24234,23 @@ p, li { white-space: pre-wrap; } %1 completed transfer - - You have %1 completed downloads - Tiene %1 descargas completas - - - You have %1 completed download - Tiene %1 descarga completa - - - %1 completed downloads - %1 descargas completas - - - %1 completed download - %1 descarga completa - TransfersDialog - - + + Downloads Descargas - + Uploads Enviando - + Name i.e: file name Nombre @@ -26010,11 +24457,7 @@ p, li { white-space: pre-wrap; } Especificar... - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1> <p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p> <p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p> <p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Transferencia de archivos</h1> <p>RetroShare tiene dos formas de transferir archivos: transferencias directas desde sus amigos, y transferencias distantes anónimas por túnel. Además, la transferencia de archivos es desde múltiples-fuentes y permite comportamiento de enjambre (puede ser fuente a la vez que descarga)</p> <p>Puede compartir archivos usando el <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icono del lado izquierdo de la barra lateral. Estos archivos se listarán en la pestaña Mis Archivos. Puede decidir para cada grupo de amigos si pueden o no ver estos archivos en su pestaña de Archivos de Amigos</p> <p>La pestaña de búsqueda informa de archivos de las listas de archivos de sus amigos, y de archivos distantes que se pueden alcanzar de forma anónima usando la sistema de tunelización de múltiples-saltos.</p> - - - + Move in Queue... Mover en la lista de espera... @@ -26039,7 +24482,7 @@ p, li { white-space: pre-wrap; } Elegir directorio - + Anonymous end-to-end encrypted tunnel 0x Túnel anónimo cifrado extremo-a-extremo 0x @@ -26060,7 +24503,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -26093,7 +24536,17 @@ p, li { white-space: pre-wrap; } El archivo %1 no está completo todavía. Si es un archivo multimedia, trate de obtener una vista previa. - + + Warning + Aviso + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name Cambiar nombre de archivo @@ -26108,7 +24561,7 @@ p, li { white-space: pre-wrap; } Por favor, introduzca un nuevo - y válido - nombre de archivo - + Expand all Expandir todo @@ -26235,23 +24688,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Columnas - + File Transfers Transferencia de archivos - + Path Ruta @@ -26261,7 +24709,7 @@ p, li { white-space: pre-wrap; } Mostrar columna de ruta - + Could not delete preview file No se pudo borrar el archivo de vista previa @@ -26271,7 +24719,7 @@ p, li { white-space: pre-wrap; } ¿Intentarlo de nuevo? - + Create Collection... Crear colección... @@ -26286,7 +24734,12 @@ p, li { white-space: pre-wrap; } Ver colección... - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Collection Colección @@ -26296,7 +24749,7 @@ p, li { white-space: pre-wrap; } %1 túneles - + Anonymous tunnel 0x Túnel anónimo 0x @@ -26517,10 +24970,6 @@ p, li { white-space: pre-wrap; } File transfer tunnels - - Anonymous tunnels - Túneles anónimos - Authenticated tunnels @@ -26714,12 +25163,17 @@ p, li { white-space: pre-wrap; } Formulario - + Enable Retroshare WEB Interface Habilitar interfaz WEB de RetroShare - + + Status: + Estado: + + + Web parameters Parámetros web @@ -26753,35 +25207,33 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Note: these settings do not affect retroshare-service, which has a command line switch to activate the web interface and select the listening port.</p></body></html> - - Port: - Puerto: - Allow access from all IP addresses (Default: localhost only) Permitir el acceso desde todas las direcciones IP (Predeterminado: sólo localhost (nodo local)) - Apply setting and start browser - Aplicar configuración e iniciar navegador - - - Note: these settings do not affect retroshare-nogui. Retroshare-nogui has a command line switch to activate the web interface. - Nota: estas configuraciones no afectan a retroshare-nogui (aplicación en línea de comandos sin interfaz gráfica). retroshare-nogui tiene un parámetro de línea comandos para activar la interfaz web. - - - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Interfaz web</h1> <p>La interfaz web le permite controlar Retroshare desde el navegador. Múltiples dispositivos pueden compatir el control sobre una instancia Retroshare. Así que podría iniciar una conversación en una tableta y posteriormente usar una computadora de escritorio para continuarla.</p> <p>Advertencia: No exponga la interfaz web hacia Internet, porque no hay control de acceso ni cifrado. Si quiere usar la interfaz web sobre Internet, use un túnel SSH o un proxy para asegurar la conexión.</p> - + Webinterface not enabled Interfaz web no habilitada @@ -26791,12 +25243,12 @@ p, li { white-space: pre-wrap; } La interfaz web no está habilitada. Habilítela en Configuración -> Interfaz web - + failed to start Webinterface fallo al iniciar la interfaz web - + Webinterface Interfaz web @@ -26933,11 +25385,7 @@ p, li { white-space: pre-wrap; } Páginas Wiki - New Group - Nuevo grupo - - - + Page Name Nombre página @@ -26952,7 +25400,7 @@ p, li { white-space: pre-wrap; } ID original - + << << @@ -27040,7 +25488,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History Historial de edición de páginas @@ -27075,7 +25523,7 @@ p, li { white-space: pre-wrap; } ID de página - + \/ \/ @@ -27105,14 +25553,18 @@ p, li { white-space: pre-wrap; } Etiquetas - - + + History + Historial + + + Show Edit History Mostrar historial de ediciones - + Status Estado @@ -27133,7 +25585,7 @@ p, li { white-space: pre-wrap; } Revertir - + Submit Enviar @@ -27205,10 +25657,6 @@ p, li { white-space: pre-wrap; } WireDialog - - TimeRange - Intervalo de tiempo - Create Account @@ -27220,16 +25668,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - Refrescar - - - + Settings @@ -27244,7 +25683,7 @@ p, li { white-space: pre-wrap; } Otros - + Who to Follow @@ -27264,7 +25703,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -27294,85 +25733,17 @@ p, li { white-space: pre-wrap; } - Last Month - Mes pasado - - - Last Week - Semana pasada - - - Today - Hoy - - - New - Nuevo - - - from - de - - - until - hasta - - - Search/Filter - Buscar/Filtrar - - - Network Wide - En toda la red - - - Manage Accounts - Administrar cuentas - - - Showing: - Mostrando: - - - + Yourself Yo mismo - - Friends - Amigos - Following Siguiente - Custom - Personalizar - - - Account 1 - Cuenta 1 - - - Account 2 - Cuenta 2 - - - Account 3 - Cuenta 3 - - - CheckBox - Casilla de verificación - - - Post Pulse to Wire - Mensaje de Pulso para Wire - - - + RetroShare RetroShare @@ -27435,35 +25806,42 @@ p, li { white-space: pre-wrap; } Formulario - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + + + + Location: Lugar: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -27508,11 +25886,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + N/A + + + + Following + Siguiente + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Desconocido @@ -27590,7 +25998,7 @@ p, li { white-space: pre-wrap; } %1a. %2d - + k e.g: 3.1 k k @@ -27623,15 +26031,11 @@ p, li { white-space: pre-wrap; } Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif *.webp) - - Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - Imágenes (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - pgpid_item_model - + Do you accept connections signed by this profile? ¿Acepta las conexiones firmadas por este perfil? @@ -27640,10 +26044,6 @@ p, li { white-space: pre-wrap; } Name of the profile Nombre del perfil - - This column indicates trust level and whether you signed the profile PGP key - Esta columna indica el nivel de confianza y si ha firmado la clave PGP del perfil - This column indicates the trust level you indicated and whether you signed the profile PGP key @@ -27754,10 +26154,6 @@ p, li { white-space: pre-wrap; } Denied - - - - - - PGP key signed by you diff --git a/retroshare-gui/src/lang/retroshare_fi.ts b/retroshare-gui/src/lang/retroshare_fi.ts index 4356c9860..2a52e18a6 100644 --- a/retroshare-gui/src/lang/retroshare_fi.ts +++ b/retroshare-gui/src/lang/retroshare_fi.ts @@ -84,13 +84,6 @@ Ainoastaan piilotettu solmu - - AddCommentDialog - - Add Comment - Lisää kommentti - - AddFileAssociationDialog @@ -128,12 +121,12 @@ Retroshare: tarkennettu haku - + Search Criteria Hakuehdot - + Add a further search criterion. Lisää hakuehto. @@ -143,7 +136,7 @@ Tyhjennä hakuehdot. - + Cancels the search. Peruu haun. @@ -163,177 +156,6 @@ Haku - - AlbumCreateDialog - - Create Album - Luo albumi - - - Album Name: - Albumin nimi: - - - Category: - Luokka: - - - Animals - Eläimet - - - Family - Sukulaiset - - - Friends - Ystävät - - - Flowers - Kukat - - - Holiday - Loma - - - Landscapes - Maisemat - - - Pets - Lemmikit - - - Portraits - Muotokuvat - - - Travel - Matkustaminen - - - Work - Työ - - - Random - Satunnainen - - - Caption: - Kuvateksti: - - - Where: - Missä: - - - Photographer: - Valokuvaaja: - - - Description: - Kuvaus: - - - Share Options - Jakoasetukset - - - Policy: - Käytänne: - - - Quality: - Laatu: - - - Comments: - Kommentit: - - - Identity: - Henkilöllisyys: - - - Public - Julkinen - - - Restricted - Rajoitettu - - - Resize Images (< 1Mb) - Muuta kuvien kokoa (< 1Mb) - - - Resize Images (< 10Mb) - Muuta kuvien kokoa (< 10Mb) - - - Send Original Images - Lähetä alkuperäiset kuvat - - - No Comments Allowed - Kommentteja ei sallittu - - - Authenticated Comments - Varmennetut kommentit - - - Any Comments Allowed - Kaikki kommentit sallittu - - - Publish with Identity - Julkaise henkilöllisyyden kera - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Vedä ja pudota lisätäksesi kuvia. Paina kuvaa muokataksesi tietoja alhaalla.</span></p></body></html> - - - Back - Takaisin - - - Add Photos - Lisää kuvia - - - Publish Album - Julkaise albumi - - - Untitle Album - Nimetön albumi - - - Say something about this album... - Kirjoita tietoja albumista - - - Where were these taken? - Missä nämä on otettu? - - - Load Album Thumbnail - Lataa albumin näytekuva - - AlbumDialog @@ -342,19 +164,11 @@ p, li { white-space: pre-wrap; } Album Albumi - - Album Thumbnail - Albumin näytekuva - TextLabel TekstiMerkki - - Summary - Yhteenveto - Album Title: @@ -370,34 +184,6 @@ p, li { white-space: pre-wrap; } Caption Kuvateksti - - Where: - Missä: - - - When - Milloin - - - Description: - Kuvaus: - - - Share Options - Jakoasetukset - - - Comments - Kommentit - - - Publish Identity - Julkaise henkilöllisyys - - - Visibility - Näkyvyys - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -766,7 +552,7 @@ p, li { white-space: pre-wrap; } Retroshare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. Varoitus: nämä palvelut ovat kokeellisia. Auta meitä niiden testaamisessa. @@ -782,14 +568,6 @@ p, li { white-space: pre-wrap; } Circles Piirit - - GxsForums - Gxs-foorumit - - - GxsChannels - GxsKanavat - The Wire @@ -801,10 +579,23 @@ p, li { white-space: pre-wrap; } Valokuvat + + AspectRatioPixmapLabel + + + Save image + Tallenna kuva + + + + Copy image + + + AttachFileItem - + %p Kb %p Kb @@ -841,17 +632,13 @@ p, li { white-space: pre-wrap; } Browse... - - Add Avatar - Lisää avatar - Remove Poista - + Set your Avatar picture Aseta avatarkuvasi @@ -870,10 +657,6 @@ p, li { white-space: pre-wrap; } Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - Lataa avatar - AvatarWidget @@ -942,22 +725,10 @@ p, li { white-space: pre-wrap; } Palauta asetukset - Receive Rate - Vastaanottonopeus - - - Send Rate - Lähetysnopeus - - - + Always on Top Aina päällimmäisenä - - Style - Tyyli - Changes the transparency of the Bandwidth Graph @@ -973,23 +744,11 @@ p, li { white-space: pre-wrap; } % Opaque % näkyvä - - Save - Tallenna - - - Cancel - Peru - Since: Alkaen: - - Hide Settings - Piilota asetukset - BandwidthStatsWidget @@ -1062,7 +821,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment Kommentti @@ -1092,12 +851,12 @@ p, li { white-space: pre-wrap; } Kopioi Retroshare-linkki - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> <p><font color="#ff0000"><b>Tämän viestin kirjoittaja (tunnisteella %1) on pannassa.</b> - + ago @@ -1105,7 +864,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up Äänestä ylös @@ -1125,7 +884,7 @@ p, li { white-space: pre-wrap; } \/ - + Posted by @@ -1163,7 +922,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up Äänestä ylös @@ -1183,7 +942,7 @@ p, li { white-space: pre-wrap; } \/ - + Click to view picture @@ -1213,7 +972,7 @@ p, li { white-space: pre-wrap; } Jaa - + Toggle Message Read Status Vaihda viestin tila luetuksi tai päinvastoin @@ -1223,7 +982,7 @@ p, li { white-space: pre-wrap; } Uusi - + TextLabel @@ -1231,12 +990,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this Pidän tästä - + 0 0 @@ -1256,18 +1015,18 @@ p, li { white-space: pre-wrap; } Avatar - + New Comment - + Copy RetroShare Link Kopioi Retroshare-linkki - + Expand Laajenna @@ -1282,12 +1041,12 @@ p, li { white-space: pre-wrap; } Poista kohde - + Name Nimi - + Comm value @@ -1456,17 +1215,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels Kanavat - + Tabs Välilehdet - + General Yleiset @@ -1476,11 +1235,17 @@ p, li { white-space: pre-wrap; } - Load posts in background (Thread) - Lataa viestit taustalla (aihe) + + Downloads + Lataukset - + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab Avaa jokainen kanava uuteen välilehteen @@ -1488,7 +1253,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1511,7 +1276,7 @@ into the image, so as to ChannelsCommentsItem - + I like this Pidän tästä @@ -1536,18 +1301,18 @@ into the image, so as to Avatar - + New Comment - + Copy RetroShare Link Kopioi Retroshare-linkki - + Expand Laajenna @@ -1562,7 +1327,7 @@ into the image, so as to Poista kohde - + Name Nimi @@ -1572,17 +1337,7 @@ into the image, so as to - - Comment - Kommentti - - - - Comments - Kommentit - - - + Hide Piilota @@ -1590,7 +1345,7 @@ into the image, so as to ChatLobbyDialog - + Name Nimi @@ -1781,7 +1536,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby Näytä keskusteluhuone @@ -1793,22 +1548,6 @@ into the image, so as to Chats Keskustelut - - You have %1 new messages - Sinulle on uusia viestejä %1 kpl - - - You have %1 new message - Sinulle on %1 uusi viesti - - - %1 new messages - %1 kpl uusia viestejä - - - %1 new message - %1 uusi viesti - You have %1 mentions @@ -1830,13 +1569,14 @@ into the image, so as to - + + Unknown Lobby Tuntematon huone - - + + Remove All Poista kaikki @@ -1844,13 +1584,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Nimi - + Count Lkm @@ -1860,33 +1600,7 @@ into the image, so as to Aihe - - Private Subscribed chat rooms - Yksityiset tilatut keskusteluhuoneet - - - - - Public Subscribed chat rooms - Julkiset tilatut keskusteluhuoneet - - - - Private chat rooms - Yksityiset keskusteluhuoneet - - - - - Public chat rooms - Julkiset keskusteluhuoneet - - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/images/add_24x24.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Keskusteluhuoneet</h1><p>Keskusteluhuoneissa voit käydä nimettömiä keskusteluja lukuisien ihmisten kanssa ilman tarvetta ystävystyä.</p><p>Keskusteluhuone voi olla julkinen (ystäviesi nähtävissä) tai yksityinen (ystäväsi eivät näe sitä, ellet kutsu heitä painamalla <img src=":/images/add_24x24.png" width=%2/>). Kun sinut on kutsuttu yksityiseen huoneeseen, näet sen ystäviesi käyttäessä sitä</p><p>Vasemmalla oleva luettelo näyttää keskusteluhuoneet, joissa on ystäviäsi. Voit<ul> <li>Käyttää hiiren oikeata painiketta luodaksesi uuden huoneen</li><li>Kaksoisnapauttaa huonetta liittyäksesi keskusteluun</li></ul>Huomaa, että tietokoneesi on oltava oikeassa ajassa, jotta keskusteluhuoneet toimivat kunnolla. Tarkista siis järjestelmäsi kello!</p> - - - + Create chat room Luo keskusteluhuone @@ -1896,7 +1610,7 @@ into the image, so as to Poistu huoneesta - + Create a non anonymous identity and enter this room Luo nimellä varustettu henkilöllisyys ja astu huoneeseen @@ -1955,12 +1669,12 @@ Valitse huoneita vasemmalta nähdäksesi tietoja. Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. - + %1 invites you to chat room named %2 %1 kutsuu sinut keskusteluhuoneeseen nimeltä %2 - + Choose a non anonymous identity for this chat room: Valitse nimellä varustettu henkilöllisyys tätä keskusteluhuonetta varten: @@ -1970,31 +1684,31 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Valitse henkilöllisyys tätä keskusteluhuonetta varten: - Create chat lobby - Luo keskusteluhuone - - - + [No topic provided] [Ei aihetta] - Selected lobby info - Tietoja valitusta huoneesta - - - + + Private Yksityinen - + + + Public Julkinen - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted Nimettömät tunnisteet hyväksytty @@ -2004,42 +1718,25 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Poista automaattinen tilaus - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe Lisää automaattinen tilaus - + Search Chat lobbies Hae keskusteluauloista - + Search Name Hae nimeä - Subscribed - Tilattu - - - + Columns Sarakkeet - - Yes - Kyllä - - - No - Ei - Chat rooms @@ -2051,47 +1748,47 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. - + Chat Room info - + Chat room Name: Keskusteluhuoneen nimi: - + Chat room Id: Keskusteluhuoneen tunniste: - + Topic: Aihe: - + Type: Tyyppi: - + Security: Tietoturva: - + Peers: Vertaiset: - - - - - - + + + + + + TextLabel TekstiMerkki @@ -2106,13 +1803,24 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Ei nimettömiä tunnisteita - + Show Näytä - + + Private Subscribed + + + + + + Public Subscribed + + + + column sarake @@ -2126,7 +1834,7 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. ChatMsgItem - + Remove Item Poista kohde @@ -2171,46 +1879,22 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. ChatPage - + General Yleiset - - Distant Chat - Etäinen keskustelu - Everyone Jokainen - - Contacts - Kontaktit - Nobody Ei kukaan - Accept encrypted distant chat from - Hyväksy salattu etäinen keskustelu: - - - Chat Settings - Keskusteluasetukset - - - Enable Emoticons Private Chat - Ota hymiöt käyttöön yksityiskeskustelussa - - - Enable Emoticons Group Chat - Ota hymiöt käyttöön ryhmäkeskustelussa - - - + Enable custom fonts Käytä omia kirjasimia @@ -2219,10 +1903,6 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Enable custom font size Käytä mukautettuja kirjasinkokoja - - Minimum font size - Kirjasin vähimmäiskoko - Enable bold @@ -2234,7 +1914,7 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Käytä kursiivia - + General settings @@ -2259,11 +1939,7 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Lataa upotetut kuvat - Chat Lobby - Keskusteluhuone - - - + Blink tab icon Vilkuta välilehtikuvaketta @@ -2272,10 +1948,6 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Do not send typing notifications Älä lähetä kirjoittamista koskevia ilmoituksia - - Private Chat - Yksityinen keskustelu - Open Window for new chat @@ -2297,11 +1969,7 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Vilkuta ikkuna- tai välilehtikuvaketta - Chat Font - Keskustelun kirjasin - - - + Change Chat Font Vaihda keskustelun kirjasin @@ -2311,14 +1979,10 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Keskustelun kirjasin: - + History Historia - - Style - Tyyli - @@ -2333,17 +1997,13 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Variant: Muunnelma: - - Group chat - Ryhmäkeskustelu - Private chat Yksityinen keskustelu - + Choose your default font for Chat. Valitse oletuskirjasin keskustelulle. @@ -2407,22 +2067,28 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. <html><head/><body><p align="justify">In this tab you can setup how many chat messages Retroshare will keep saved on the disc and how much of the previous conversation it will display, for the different chat systems. The max storage period allows to discard old messages and prevents the chat history from filling up with volatile chat (e.g. chat lobbies and distant chat).</p></body></html> <html><head/><body><p align="justify">Tässä välilehdessä voit määrittää, kuinka monta chat-viestiä Retroshare pitää tallennettuna kiintolevylle ja kuinka paljon edellisestä keskustelusta näytetään eri keskustelutoiminnoissa. Säilytyksen enimmäisaika mahdollistaa vanhojen viestien hävittämisen ja estää keskusteluhistorian täyttymisen (esim. keskusteluaulat ja etäiset keskustelut).</p></body></html> - - Chatlobbies - Keskusteluaulat - Enabled: Käytössä: - + Search Haku - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2432,7 +2098,17 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms Keskusteluhuoneet @@ -2529,11 +2205,7 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Varastoinnin enimmäisaika, päivinä (0=pidä kaikki): - Search by default - Haku oletuksena - - - + Case sensitive Huomioi kirjainkoko @@ -2572,10 +2244,6 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Threshold for automatic search Automaattisen haun raja-arvo - - Default identity for chat lobbies: - Oletushenkilöllisyys keskusteluauloihin: - Show Bar by default @@ -2643,7 +2311,7 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. ChatToaster - + Show Chat Näytä keskustelu @@ -2679,7 +2347,7 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. ChatWidget - + Close Sulje @@ -2714,12 +2382,12 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Kursivointi - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon Syötä hymiö @@ -2799,11 +2467,6 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. Insert horizontal rule Syötä vaakaviiva - - - Save image - Tallenna kuva - Import sticker @@ -2841,7 +2504,7 @@ Kaksoisnapauta huonetta siirtyäksesi keskustelemaan. - + is typing... kirjoittaa... @@ -2865,7 +2528,7 @@ iso HTML-muuntamisen jälkeen. Valitse kirjasin. - + Do you really want to physically delete the history? Haluatko todella tuhota historian pysyvästi? @@ -2915,7 +2578,7 @@ iso HTML-muuntamisen jälkeen. on kiireinen, eikä välttämättä vastaa - + Find Case Sensitively Huomioi kirjainkoko @@ -2937,7 +2600,7 @@ iso HTML-muuntamisen jälkeen. Älä lopeta värittämistä, kun X kohdetta löydetty (vaatii konetehoa) - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> <b>Hae edellinen </b><br/><i>Ctrl+Shift+G</i> @@ -2952,16 +2615,12 @@ iso HTML-muuntamisen jälkeen. <b>Hae </b><br/><i>Ctrl+F</i> - + (Status) (Tila) - Set text font & color - Aseta tekstin kirjasinlaji & väri - - - + Attach a File Liitä tiedosto @@ -2977,12 +2636,12 @@ iso HTML-muuntamisen jälkeen. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> <b>Merkitse tämä valittu teksti</b><br><i>Ctrl+M</i> - + Person id: Henkilön tunniste: @@ -2994,12 +2653,12 @@ Double click on it to add his name on text writer. Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan. - + Unsigned Allekirjoittamaton - + items found. Kohteita löytyi. @@ -3019,7 +2678,7 @@ Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan.Kirjoita viesti tähän - + Don't stop to color after Älä lopeta värittämistä jälkeen @@ -3045,7 +2704,7 @@ Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan. CirclesDialog - + Showing details: Näytetään tietoja: @@ -3067,7 +2726,7 @@ Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan. - + Personal Circles Henkilökohtaiset piirit @@ -3093,7 +2752,7 @@ Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan. - + Friends Ystävät @@ -3153,7 +2812,7 @@ Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan.Ystävien ystävät - + External Circles (Admin) Ulkoiset piirit (Ylläpito) @@ -3169,7 +2828,7 @@ Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan. - + Circles Piirit @@ -3221,43 +2880,48 @@ Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan. - + RetroShare Retroshare - + - + Error : cannot get peer details. Virhe: vertaisen yksityiskohtia ei saatu. - + Retroshare ID - + <p>This Retroshare ID contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: + + + <b>DNS:</b> : + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3269,7 +2933,7 @@ Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan.Salaus - + Not connected Ei yhteyttä @@ -3351,25 +3015,17 @@ Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan.ei mitään - + <p>This certificate contains: <p>Tämä varmenne sisältää: - + <li>a <b>node ID</b> and <b>name</b> <li> <b>solmun tunniste</b> ja <b>nimi</b> - an <b>onion address</b> and <b>port</b> - <b>onion-osoite</b> ja <b>portti</b> - - - an <b>IP address</b> and <b>port</b> - <b>IP-osoite</b> ja <b>ja</b> - - - + <p>You can use this certificate to make new friends. Send it by email, or give it hand to hand.</p> <p>Voit käyttää tätä varmennetta luodaksesi uusia ystäviä. Lähetä se sähköpostitse tai anna se tavatessanne.</p> @@ -3384,7 +3040,7 @@ Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan.<html><head/><body><p>Tätä salaus-metodia käyttää <span style=" font-weight:600;">OpenSSL</span>. Yhteys ystäväsolmuihin</p><p>on aina vahvasti salattu ja jos DHE on läsnä yhteys edelleen käyttää</p><p>&quot;täydellistä forward secrecy-ominaisuutta&quot; (salausavaimen murtaminen ei johda aiemmin salattujen viestien tietoturvan vaarantumiseen).</p></body></html> - + with kanssa @@ -3401,118 +3057,16 @@ Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan.Connect Friend Wizard Ohjattu toiminto ystävän yhdistämiseksi - - Add a new Friend - Lisää uusi ystävä - - - &You get a certificate file from your friend - &Saat varmenteen ystävältäsi - - - &Make friend with selected friends of my friends - &Ystävysty valitsemieni ystävien ystävien kanssa - - - &Send an Invitation by Email - (Your friend will receive an email with instructions how to download RetroShare) - &Lähetä kutsu sähköpostilla - (Ystäväsi saa sähköpostin, jossa on ohjeet Retrosharen lataamiseksi) - - - Include signatures - Sisällytä allekirjoitukset - - - Copy your Cert to Clipboard - Kopioi varmenteesi leikepöydälle - - - Save your Cert into a File - Tallenna varmenteesi tiedostoon - - - Run Email program - Käynnistä sähköpostiohjelma - Open Cert of your friend from File Avaa ystäväsi varmenne tiedostosta - - Open certificate - Avaa varmenne - - - Please, paste your friend's Retroshare certificate into the box below - Ole hyvä ja liitä ystäväsi Retroshare-varmenne allaolevaan laatikkoon - - - Certificate files - Varmennetiedostot - - - Use PGP certificates saved in files. - Käytä tiedostoihin tallennettuja PGP-varmenteita. - - - Import friend's certificate... - Tuo ystävän varmenne... - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - Sinun tulee luoda tiedosto, joka sisältää varmenteesi ja antaa se ystävällesi. Voit myös käyttää aiemmin luotua tiedostoa. - - - Export my certificate... - Vie varmenteeni... - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - Vedä ja pudota ystäväsi varmenne tähän ikkunaan tai määritä polku allaolevaan laatikkoon - - - Browse - Selaa - - - Friends of friends - Ystävien ystäviä - - - Select now who you want to make friends with. - Valitse nyt, kenen kanssa haluat ystävystyä. - - - Show me: - Näytä: - - - Make friend with these peers - Ystävysty näiden vertaisten kanssa - RetroShare ID Retrosharen tunniste - - Use RetroShare ID for adding a Friend which is available in your network. - Käytä Retroshare-tunnistetta verkossasi olevan ystävän lisäämiseen. - - - Add Friends RetroShare ID... - Lisää ystävän Retroshare-tunniste... - - - Paste Friends RetroShare ID in the box below - Liitä ystävän Retroshare-tunniste allaolevaan laatikkoon - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - Anna ystäväsi Retroshare-tunniste, tyyliin Vertainen@BDE8D16A46D938CF - RetroShare is better with Friends @@ -3554,27 +3108,7 @@ Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan.Sähköposti - Invite Friends by Email - Kutsu ystäviä sähköpostilla - - - Enter your friends' email addresses (separate each one with a semicolon) - Kirjoita ystäviesi sähköpostiosoitteet (erottele ne puolipisteellä) - - - Your friends' email addresses: - Ystäviesi sähköpostiosoitteet: - - - Enter Friends Email addresses - Kirjoita ystäviesi sähköpostiosoitteet - - - Subject: - Aihe: - - - + @@ -3590,78 +3124,32 @@ Kaksoisnapsauta sitä lisätäksesi hänen nimensä tekstinkirjoittajaan.Tietoja pyynnöstä - + Peer details Vertaisen tiedot - + Name: Nimi: - - Email: - Sähköposti: - - - Node: - Solmu: - - - Please note that RetroShare will require excessive amounts of bandwidth, memory and CPU if you add too many friends. You can add as many friends as you like, but more than 40 will probably require too much -resources. - Huomioithan, että Retroshare edellyttää kohtuuttomia määriä tietoliikennekaistaa, muistia ja suoritintehoa, jos lisäät paljon ystäviä. Voit lisätä niin monta ystävää kuin haluat, mutta yli 40 luultavasti vaatii liikaa -resursseja. - Location: Sijainti: - + Options Asetukset - This wizard will help you to connect to your friend(s) to RetroShare network.<br>Select how you would like to add a friend: - Tämä aputoiminta auttaa sinua ottamaan yhteyden ystäviisi Retroshare-verkossa.<br>Valitse miten haluaisit lisätä ystävän: - - - Enter the certificate manually - Anna varmenne manuaalisesti - - - Enter RetroShare ID manually - Anna Retroshare tunniste manuaalisesti - - - &Send an Invitation by Web Mail Providers - &Lähetä kutsu webmailpalvelun kautta - - - Recommend many friends to each other - Suosittele useita ystäviä toisilleen - - - RetroShare certificate - Retroshare varmenne - - - Please paste below your friend's Retroshare certificate - Ole hyvä ja liitä alle ystäväsi Retroshare-varmenne - - - Paste certificate - Liitä varmenne - - - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> <html><head/><body><p>Tämä laatikko vaatii sinun ystäväsi Retroshare-varmenteen. VAROITUS: se on erilainen, kuin ystäväsi profiiliavain. Älä liitä ystäväsi profiiliavainta tähän (edes osaa siitä). Se ei tule toimimaan.</p></body></html> - + Add friend to group: Lisää ystävä ryhmään: @@ -3671,7 +3159,7 @@ resursseja. Varmenna ystävä (allekirjoita PGP-avain) - + Please paste below your friend's Retroshare ID @@ -3696,16 +3184,22 @@ resursseja. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with Lisää ystäväksi, johon otat yhteyden - To accept the Friend Request, click the Finish button. - Paina Valmis-painiketta hyväksyäksesi ystäväpyynnön - - - + Sorry, some error appeared Valitettavasti on tapahtunut jokin virhe @@ -3725,32 +3219,27 @@ resursseja. Tietoja ystävästäsi: - + Key validity: Avaimen kelpoisuus: - + Profile ID: - - Signers - Allekirjoittajat - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Ystäväsi avaimen allekirjoittamisella ilmaiset luottamuksesi tähän ystävään muille ystävillesi. Allekirjoitukset alla kryptograafisesti todistavat, että luettelon avaimien omistajat tunnistavat nykyisen PGP-avaimen aidoksi.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. Tämä vertainen on jo ystäväluettelossasi. Hänen lisäämisensä saattaa ainoastaan määrittää uuden IP-osoitteen. - + To accept the Friend Request, click the Accept button. @@ -3796,49 +3285,17 @@ resursseja. - + Certificate Load Failed Varmenteen lataus epäonnistui - Cannot get peer details of PGP key %1 - Vertaistietoja ei kyetty hakemaan PGP-avaimelle %1 - - - Any peer I've not signed - Kaikki vertaiset, joita en ole allekirjoittanut - - - Friends of my friends who already trust me - Ystävieni ystävät, jotka jo luottavat minuun - - - Signed peers showing as denied - Allekirjoitetut vertaiset, jotka näkyvät torjuttuina - - - Peer name - Vertaisen nimi - - - Also signed by - Muita allekirjoittaneita - - - Peer id - Vertaisen tunniste - - - Certificate appears to be valid - Varmenne näyttää olevan kelvollinen - - - + Not a valid Retroshare certificate! Ei kelvollinen Retroshare-varmenne! - + RetroShare Invitation Retroshare-kutsu @@ -3860,12 +3317,12 @@ Varoitus: Tiedostonsiirto-asetuksissa Salli suora lataus on asetettu Ei. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? Tämä on oma varmenteesi! Et haluaisi olla oma ystäväsi. Ethän? - + @@ -3873,7 +3330,7 @@ Varoitus: Tiedostonsiirto-asetuksissa Salli suora lataus on asetettu Ei. - + This key is already on your trusted list Tämä avain on jo luotettujen luettelossa @@ -3913,7 +3370,7 @@ Varoitus: Tiedostonsiirto-asetuksissa Salli suora lataus on asetettu Ei.Sinulle on ystäväpyyntö, lähettäjä - + Profile password needed. @@ -3938,7 +3395,7 @@ Varoitus: Tiedostonsiirto-asetuksissa Salli suora lataus on asetettu Ei. - + Valid Retroshare ID @@ -3948,47 +3405,7 @@ Varoitus: Tiedostonsiirto-asetuksissa Salli suora lataus on asetettu Ei. - Certificate Load Failed:file %1 not found - Varmenteen avaaminen epäonnistui: tiedostoa %1 ei löydy - - - This Peer %1 is not available in your Network - Vertainen %1 ei ole verkossasi - - - Use new certificate format (safer, more robust) - Käytä uutta varmenneformaattia (turvallisempi ja vakaampi) - - - Use old (backward compatible) certificate format - Käytä vanhaa (takaisinpäin yhteensopivaa) varmenneformaattia - - - Remove signatures - Poista allekirjoitukset - - - RetroShare Invite - Retroshare-kutsu - - - Connect Friend Help - Ohje ystävän yhdistämisestä - - - You can copy this text and send it to your friend via email or some other way - Voit kopioida tämän tekstin ja lähettää sen ystävällesi sähköpostilla tai muulla tavoin - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Varmenteesi on kopioitu leikepöydälle, liitä ja lähetä se ystävällesi sähköpostilla tai muulla tavoin - - - Save as... - Tallenna nimellä... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -4027,11 +3444,7 @@ Varoitus: Tiedostonsiirto-asetuksissa Salli suora lataus on asetettu Ei.*** Ei mitään *** - Use as direct source, when available - Käytä suorana lähteenä, kun saatavilla - - - + IP-Addr: IP-osoite: @@ -4041,7 +3454,7 @@ Varoitus: Tiedostonsiirto-asetuksissa Salli suora lataus on asetettu Ei.IP-osoite: - + Show Advanced options Näytä lisäasetukset @@ -4050,10 +3463,6 @@ Varoitus: Tiedostonsiirto-asetuksissa Salli suora lataus on asetettu Ei.<html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Ystäväsi avaimen allekirjoittamisella ilmaiset luottamuksesi tähän ystävään muille ystävillesi. Se auttaa heitä päättämään salliako yhteydet siitä avaimesta perustuen sinun omaan luottamukseen. Avaimen allekirjoittaminen on täysin vapaaehtoista, eikä sitä voi perua, joten tee niin harkiten.</span></p></body></html> - - <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> - <html><head/><body><p align="justify">Retroshare käy ajoittain läpi ystäväluettelosi siirtojasi vastaavien selattavien tiedostojen varalta, jotta voitaisiin muodostaa suora siirtoyhteys. Tällaisessa tapauksessa ystäväsi tietää, että lataat tiedostoa.</p><p align="justify">Estääksesi toiminnan tämän ystävän tapauksessa, poista rasti tästä ruudusta. Voit silti muodostaa suoran siirtoyhteyden halutessasi, esim. lataamalla suoraan ystäväsi tiedostoluettelosta. Tätä asetusta sovelletaan kaikkiin saman solmun sijainteihin.</p></body></html> - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> @@ -4064,45 +3473,13 @@ Varoitus: Tiedostonsiirto-asetuksissa Salli suora lataus on asetettu Ei.<html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> <html><head/><body><p>Tällä asetuksella varustetut vertaiset eivät voi muodostaa yhteyttä, jos heidän osoitteensa ei ole sallittujen luettelossa. Tämä suojelee sinua liikenteen välittämiseen perustuvilta hyökkäyksiltä. Asetuksen myötä hylätyt vertaiset raportoidaan &quot;tietoturvasyötteen nimikkeisiin&quot; Uutissyöte-alueella. Voit sieltä lisätä heidän IP:nsä sallittujen/estettyjen luetteloon. Tämä pätee saman solmun kaikkiin sijainteihin.</p></body></html> - - Recommend many friends to each others - Suosittele useita ystäviä toisilleen - - - Friend Recommendations - Ystäväsuositukset - - - The text below is your Retroshare certificate. You have to provide it to your friend - Teksti alapuolella on Retroshare-varmenteesi. Sinun täytyy toimittaa se ystävällesi - - - Message: - Viesti: - - - Recommend friends - Suosittele ystäviä - - - To - Vastaanottaja - - - Please select at least one friend for recommendation. - Ole hyvä ja valitse ainakin yksi ystävä suositeltavaksi. - - - Please select at least one friend as recipient. - Ole hyvä ja valitse ainakin yksi ystävä vastaanottajaksi. - Add key to keyring Lisää avain avainnippuun - + This key is already in your keyring Tämä avain on jo avainnipussasi @@ -4118,7 +3495,7 @@ lähettämiseen tälle vertaiselle, vaikkette ystävystyisikään. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. Varmenteella on väärä versionumero. Muista, että versioiden 0.6 ja 0.5 verkot eivät ole keskenään yhteensopivia. @@ -4153,7 +3530,7 @@ vaikkette ystävystyisikään. Lisää IP sallittujen luetteloon - + No IP in this certificate! Ei IP-osoitetta tässä varmenteessa! @@ -4163,27 +3540,10 @@ vaikkette ystävystyisikään. <p>Varmenteessa ei ole IP-osoitetta. Etsintä ja DHT hakevat osoitteen. Vertainen aiheuttaa tietoturvavaroituksen Uutissyöte-välilehdessä, koska olet määrittänyt sallittujen luettelossa olemisen pakolliseksi. Voit sallia vertaisen IP-osoitteen Uutissyöte-välilehdeltä.</p> - - [Unknown] - [Tuntematon] - - - + Added with certificate from %1 Varmenne lisätty %1 - - Paste Cert of your friend from Clipboard - Liitä ystäväsi varmenne leikepöydältä - - - Certificate Load Failed:can't read from file %1 - Varmenteen avaaminen epäonnistui:ei voitu lukea tiedostosta %1 - - - Certificate Load Failed:something is wrong with %1 - Varmenteen lataus epäonnistui: jotain on vialla %1 - ConnectProgressDialog @@ -4245,7 +3605,7 @@ vaikkette ystävystyisikään. - + UDP Setup UDP:n asetukset @@ -4281,7 +3641,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:13pt;">voit sulkea sen.</span></p></body></html> - + Connection Assistant Yhteysavustaja @@ -4291,17 +3651,20 @@ p, li { white-space: pre-wrap; } Väärä vertaistunniste - + + Unknown State Tuntematon tila - + + Offline Ei yhteyttä - + + Behind Symmetric NAT Symmetrisen NAT:in takana @@ -4311,12 +3674,14 @@ p, li { white-space: pre-wrap; } NAT:in takana & ilman DHT:tä - + + NET Restart Verkon uudelleenkäynnistys - + + Behind NAT NAT:in takana @@ -4326,7 +3691,8 @@ p, li { white-space: pre-wrap; } Ei DHT:tä - + + NET STATE GOOD! VERKON TILA HYVÄ! @@ -4351,7 +3717,7 @@ p, li { white-space: pre-wrap; } Haetaan Retroshare-vertaisia - + Lookup requires DHT Haku vaatii DHT:tä @@ -4643,7 +4009,7 @@ p, li { white-space: pre-wrap; } Yritä tuoda täydellinen varmenne uudelleen - + @@ -4651,7 +4017,8 @@ p, li { white-space: pre-wrap; } Ei sovellu - + + UNVERIFIABLE FORWARD! VARMISTAMATON VÄLITYS! @@ -4661,7 +4028,7 @@ p, li { white-space: pre-wrap; } VARMISTAMATON VÄLITYS EIKÄ DHT:TÄ! - + Searching Haetaan @@ -4697,12 +4064,12 @@ p, li { white-space: pre-wrap; } Piirin tiedot - + Name Nimi - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> <html><head/><body><p>Piirin nimi, kirjoittajan yhteystiedot ja kutsuttujen jäsenten-luettelo ovat näkyviä kaikille kutsutuille jäsenille. Jos piiri ei ole yksityinen, se tulee olemaan näkyvä myös naapuripiireille, jotka isännöivät kutsuttuja jäseniä.</p></body></html> @@ -4722,7 +4089,7 @@ p, li { white-space: pre-wrap; } - + IDs Tunnisteet @@ -4742,18 +4109,18 @@ p, li { white-space: pre-wrap; } Suodata - + Cancel - + Nickname Nimimerkki - + Invited Members Kutsutut jäsenet @@ -4768,15 +4135,7 @@ p, li { white-space: pre-wrap; } Tuntemasi ihmiset - ID - Tunniste - - - Type - Tyyppi - - - + Name: Nimi: @@ -4816,23 +4175,19 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Piirit voidaan rajoittaa vain toisen piirin jäsenille. Vain jäsenet toisesta piiristä saavat nähdä uuden piirin ja sen sisällön (jäsenluettelo, jne).</p></body></html> - Only visible to members of: - Näkyy ainoastaan jäsenille: - - - - + + RetroShare Retroshare - + Please set a name for your Circle Anna piirillesi nimi - + No Restriction Circle Selected Rajoituspiiriä ei valittuna @@ -4842,12 +4197,24 @@ p, li { white-space: pre-wrap; } Piirien rajoituksia ei valittuna - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] [Tuntematon] - + Add Lisää @@ -4857,7 +4224,7 @@ p, li { white-space: pre-wrap; } Poista - + Search Haku @@ -4872,10 +4239,6 @@ p, li { white-space: pre-wrap; } Signed Allekirjoitettu - - Signed by known nodes - Tunnettujen solmujen allekirjoittama - Edit Circle @@ -4892,10 +4255,6 @@ p, li { white-space: pre-wrap; } PGP Identity PGP-henkilöllisyys - - Anon Id - Nimetön tunniste - Circle name @@ -4918,17 +4277,13 @@ p, li { white-space: pre-wrap; } Luo uusi piiri - + Create Luo - PGP Linked Id - PGP:n linkitetty tunniste - - - + Add Member Lisää jäsen @@ -4947,7 +4302,7 @@ p, li { white-space: pre-wrap; } Luo ryhmä - + Group Name: Ryhmä nimi: @@ -4982,7 +4337,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post Uusi kirjoitus kanavalle @@ -4992,7 +4347,7 @@ p, li { white-space: pre-wrap; } Kanavakirjoitus - + Post @@ -5053,23 +4408,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Vedä ja pudota ja paina Lisää tiedostoja -painiketta uusien tiedostojen hash-arvojen laskemiseksi.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Kopioi ja liitä Retroshare-linkkejä jaetuista tiedostoistasi.</span></p></body></html> - - Add File to Attach - Lisää liitettävä tiedosto - Add Channel Thumbnail Lisää kanavan näytekuva - - Message - Viesti - - - Subject : - Aihe: - @@ -5155,17 +4498,17 @@ p, li { white-space: pre-wrap; } - + RetroShare Retroshare - + This file already in this post: - + Post refers to non shared files @@ -5184,17 +4527,18 @@ p, li { white-space: pre-wrap; } The following files will only be shared for 30 days. Think about adding them to a shared directory. - - File already Added and Hashed - Tiedosto on jo lisätty ja tiivistetty (hash) - Please add a Subject Ole hyvä ja lisää aihe - + + Cannot publish post + + + + Load thumbnail picture Lataa näytekuva @@ -5209,18 +4553,12 @@ p, li { white-space: pre-wrap; } Piilota - - + Generate mass data Luo massatietoja - - Do you really want to generate %1 messages ? - Haluatko todella luoda %1 viestiä? - - - + You are about to add files you're not actually sharing. Do you still want this to happen? Olet aikeissa lisätä tiedostoja, joita et todellisuudessa jaa. Haluatko silti tehdä tämän? @@ -5254,7 +4592,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message Lähetä viesti foorumiin @@ -5263,10 +4601,6 @@ p, li { white-space: pre-wrap; } Forum Foorumi - - Subject - Aihe - Attach File @@ -5287,8 +4621,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -5307,7 +4641,7 @@ p, li { white-space: pre-wrap; } Voit liittää tiedostoja vetämällä ja pudottamalla niitä tähän ikkunaan - + Post @@ -5337,17 +4671,17 @@ p, li { white-space: pre-wrap; } - + No Forum Ei foorumia - + In Reply to Vastauksena - + Title Otsikko @@ -5401,7 +4735,7 @@ Haluatko hävittää tämän viestin? Lataa kuvatiedosto - + No compatible ID for this forum Ei yhteensopiva tunniste tälle foorumille @@ -5411,8 +4745,8 @@ Haluatko hävittää tämän viestin? Mikään sinun henkilöllisyyksistä ei saa kirjoittaa tälle foorumille. Tämä voi johtua siitä, että foorumi on rajattu piirille, johon sinun henkilöllisyydet eivät kuulu tai foorumi-ilmaisimet vaativat PGP-allekirjoitetun henkilöllisyyden. - - + + Generate mass data Luo massatietoja @@ -5421,10 +4755,6 @@ Haluatko hävittää tämän viestin? Do you really want to generate %1 messages ? Haluatko todella luoda %1 viestiä? - - Send - Lähetä - Post as @@ -5439,23 +4769,7 @@ Haluatko hävittää tämän viestin? CreateLobbyDialog - Create Chat Lobby - Luo keskusteluhuone - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - Keskusteluhuone on hajautettu ja nimetön keskusteluryhmä. Kaikki osallistujat näkevät kaikki viestit. Kun huone on luotu, voit kutsua muita ystäviäsi Ystävät-välilehdeltä - - - Lobby name: - Huoneen nimi: - - - Lobby topic: - Huoneen aihe: - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5490,7 +4804,7 @@ Haluatko hävittää tämän viestin? - + Create Luo @@ -5500,11 +4814,7 @@ Haluatko hävittää tämän viestin? - <html><head/><body><p>If you check this, only PGP-signed ids can be used to join and talk in this lobby. This limitation prevents anonymous spamming as it becomes possible for at least some people in the lobby to locate the spammer's node.</p></body></html> - <html><head/><body><p>Jos rastitat tämän, vain PGP-allekirjoitettuja tunnisteita voi käyttää huoneeseen liittymiseen ja siellä keskustelemiseen. Tämä rajoitus estää nimettömän roskaviestittämisen, koska osa huoneessa olevista ihmisistä pystyy paikantamaan roskaviestittäjän solmun.</p></body></html> - - - + require PGP-signed identities vaatii PGP-allekirjoitetut henkilöllisyydet @@ -5519,11 +4829,7 @@ Haluatko hävittää tämän viestin? Valitse ystävät ryhmäkeskusteluun. - Invited friends - Kutsutut ystävät - - - + Create Chat Room Luo keskusteluhuone @@ -5544,7 +4850,7 @@ Haluatko hävittää tämän viestin? Kontaktit: - + Identity to use: Käytä henkilöllisyyttä: @@ -5552,17 +4858,17 @@ Haluatko hävittää tämän viestin? CryptoPage - + Public Information Julkiset tiedot - + Name: Nimi: - + Location: Sijainti: @@ -5572,12 +4878,12 @@ Haluatko hävittää tämän viestin? Sijaintitunniste: - + Software Version: Ohjelmiston versio: - + Online since: Linjoilla alkaen: @@ -5597,12 +4903,7 @@ Haluatko hävittää tämän viestin? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5612,7 +4913,7 @@ Haluatko hävittää tämän viestin? - + Other Information Muita tietoja @@ -5622,17 +4923,12 @@ Haluatko hävittää tämän viestin? - + Profile Profiili - - Certificate - Varmenne - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5642,11 +4938,7 @@ Haluatko hävittää tämän viestin? Sisällytä allekirjoitukset - Save Key into a file - Tallenna avain tiedostoon - - - + Export Identity Vie henkilöllisyys @@ -5720,33 +5012,33 @@ ja käyttää "Tuo"-painiketta ladataksesi sen - + TextLabel TekstiMerkki - + PGP fingerprint: PGP-sormenjälki: - - Node information - Solmun tiedot - - - + PGP Id : PGP tunniste: - + Friend nodes: Ystäväsolmut: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5785,14 +5077,6 @@ ja käyttää "Tuo"-painiketta ladataksesi sen Node Solmu - - Create new node... - Luo uusi solmu... - - - show statistics window - näytä tilastoikkuna - DHTGraphSource @@ -5809,10 +5093,6 @@ ja käyttää "Tuo"-painiketta ladataksesi sen DHT DHT - - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your friends to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your friends.</p> - <p>Retroshare käyttää Bittorrentin DHT:tä välityspalvelimena yhteyksille. Se ei "tallenna" sinun IP:täsi DHT:n. Sen sijaan DHT:tä käyttävät sinun ystäväsi saadakseen sinuun yhteyden samalla, kun se käsittelee normaaleja DHT-pyyntöjä. Tilailmaisin muuttuu vihreäksi heti, kun Retroshare DHT-vastauksen yhdeltäkin ystävältä.</p> - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your trusted nodes to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your trusted nodes.</p> @@ -5848,7 +5128,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen DLListDelegate - + B B @@ -6516,7 +5796,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen DownloadToaster - + Start file Käynnistä tiedosto @@ -6524,38 +5804,38 @@ ja käyttää "Tuo"-painiketta ladataksesi sen ExprParamElement - + - + to vastaanottajalle - + ignore case sivuuta kirjainkoko - - - dd.MM.yyyy - pp.KK.vvvv + + + yyyy-MM-dd + - - + + KB kB - - + + MB MB - - + + GB GB @@ -6563,12 +5843,12 @@ ja käyttää "Tuo"-painiketta ladataksesi sen ExpressionWidget - + Expression Widget Lausekevimpain - + Delete this expression Poista tämä lauseke @@ -6730,7 +6010,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen FilesDefs - + Picture Kuva @@ -6740,7 +6020,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen Video - + Audio Ääni @@ -6800,11 +6080,21 @@ ja käyttää "Tuo"-painiketta ladataksesi sen C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Ystävien hakemistot @@ -6926,7 +6216,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen - + ID Tunniste @@ -6961,10 +6251,6 @@ ja käyttää "Tuo"-painiketta ladataksesi sen Show State Näytä tila - - Trusted nodes - Luetetut solmut - @@ -6972,7 +6258,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen Näytä ryhmät - + Group Ryhmä @@ -7008,7 +6294,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen Lisää ryhmään - + Search Haku @@ -7024,7 +6310,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen Lajittele tilan perusteella - + Profile details Profiilin tiedot @@ -7268,7 +6554,7 @@ ainakin yksi vertainen jäi lisäämättä ryhmään FriendRequestToaster - + Confirm Friend Request Vahvista ystäväpyyntö @@ -7285,10 +6571,6 @@ ainakin yksi vertainen jäi lisäämättä ryhmään FriendSelectionWidget - - Search : - Haku : - Sort by state @@ -7310,7 +6592,7 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Hae ystäviä - + Mark all Merkitse kaikki @@ -7321,16 +6603,134 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Merkitse mitään + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Nimi + + + + Node ID + + + + + Address + Osoite + + + + Status + Tila + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + Ystävysty + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + Välityspalvelin ei ole käytössä tai on rikki. +Ovatko kaikki palvelut päällä ja käynnissä?? +Tarkista myös porttisi! + + FriendsDialog - + Edit status message Muokkaa tilaviestiä - - + + Broadcast Kuulutus @@ -7413,33 +6813,38 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Palauta oletuskirjasin - + Keyring Avainnippu - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Verkko</h1> <p>Verkko-näkymä näyttää ystäväsolmusi: Retroshare-ystäväsolmut, jotka ovat yhdistettynä sinuun. </p> <p>Voit ryhmitellä solmusi ja näin hienosäätää pääsyä tietoihisi, sallia vain tiettyjen solmujen nähdä vain tietyt tiedostosi.</p> <p>Oikealla näet kolme hyödyllistä välilehteä: <ul> <li>Kuulutus lähettää viestejä kaikille linjoilla oleville ystävillesi samanaikaisesti</li> <li>Paikallinen verkko näyttää sinua ympäröivän verkoston, perustuen etsintätietoihin</li> <li>Avainnippu sisältää keräämäsi solmuavaimet, joista useimmat ovat ystäväsolmujesi välittämiä</li> </ul> </p> - - - + Retroshare broadcast chat: messages are sent to all connected friends. Retrosharen kuulutus: viestit lähetetään kaikille linjoilla oleville ystäville. - - + + Network Verkko - + + Friend Server + + + + Network graph Verkkokaavio - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. Aseta tilaviestisi tähän. @@ -7457,7 +6862,17 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Salasana - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters Kaikki kentät ovat pakollisia ja vähintään 3 merkkiä @@ -7467,17 +6882,12 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Salasanat eivät täsmää - + Port Portti - - Use BOB - Ota BOB käyttöön - - - + This password is for PGP Tämä salasana on PGP:tä varten @@ -7498,50 +6908,38 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Uuden varmenteesi luonti epäonnistui, ehkä PGP-salasanasi oli väärin! - Options - Asetukset - - - + PGP Key Length PGP-avaimen pituus - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> <html><head/><body><p>Laita vahva salasana tähän. Tämä salasana suojelee sinun yksityistä solmuavainta!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> <html><head/><body><p>Ole hyvä ja liikuta hiirtäsi ympäriinsä, jolloin autat keräämään satunnaisuutta mahdollisimman paljon. Vähintään 20% tarvitaan solmuavaimiesi luontiin.</p></body></html> - + Standard node Normaali solmu - TOR/I2P Hidden node - TOR/I2P piilotettu solmu - - - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> <html><head/><body><p>Sinun solmunimesi määrittää Retroshare-instanssin, joka</p><p>tulee toimimaan tässä tietokoneessa</p></body></html> - Use existing profile - Käytä olemassaolevaa profiilia - - - + Node name Solmun nimi - + Node type: @@ -7561,12 +6959,12 @@ ainakin yksi vertainen jäi lisäämättä ryhmään - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> <html><head/><body><p>Profiilin nimi yksilöi sinut läpi verkoston.</p><p>Ystäväsi käyttävät sitä hyväksyäkseen yhteydet sinulta.</p><p>Voit luoda monia Retroshare-solmuja</p><p>samalla profiililla eri tietokoneille.</p><p><br/></p></body></html> - + Export this profle Vie tämä profiili @@ -7576,42 +6974,43 @@ ainakin yksi vertainen jäi lisäämättä ryhmään - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> <html><head/><body><p>Tämän pitäisi olla Tor Onion-osoite muotoa: xa76giaf6ifda7ri63i263.onion <br/>tai I2P-osoite muodossa: [52 merkkiä].b32.i2p </p><p>Saadaksesi sellaisen määritä joko Tor tai I2P luomaan uuden piilotetun palvelu / palvelin-tunnelin. </p><p>Voit myös jättää tämän tyhjäksi nyt, mutta solmusi toimii ainoastaan, jos olet oikein määrittänyt Tor/I2P-palvelu osoitteen Asetukset-&gt;Verkko-&gt;Piilotetun palvelun asetusnäkymässä.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> <html><head/><body><p>Henkilöllisyyksiä käytetään, kun kirjoitat keskusteluhuoneisiin, foorumeille ja kanavakommentteihin. </p><p>Ne myös vastaanottavat/lähettävät sähköpostia Retroshare-verkossa. Voit luoda</p><p>allekirjoitetun henkilöllisyyden nyt, tai tehdä sen myöhemmin, kun tarvitset sitä.</p></body></html> - + Go! Mene! - - + + TextLabel Tekstiselite - Advanced options - Lisäasetukset - - - + hidden address piilotettu osoite - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. Profiilisi on kytketty PGP-avainpariin. Retroshare sivuuttaa DSA-avaimet. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> <html><head/><body><p>Tämä on sinun yhteysportti.</p><p>Minkä tahansa arvon 1024 ja 65535 </p><p>väliltä pitäisi olla ok. Voit muuttaa sen myöhemmin.</p></body></html> @@ -7659,13 +7058,13 @@ ja käyttää tuo-painiketta sen lataamiseen Profiiliasi ei tallennettu. Virhe tapahtui. - + Import profile Tuo profiili - + Create new profile and new Retroshare node Luo uusi profiili ja uusi Retroshare-solmu @@ -7675,7 +7074,7 @@ ja käyttää tuo-painiketta sen lataamiseen Luo uusi Retroshare-solmu - + Tor/I2P address Tor/I2P-osoite @@ -7710,7 +7109,7 @@ ja käyttää tuo-painiketta sen lataamiseen - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7720,12 +7119,7 @@ ja käyttää tuo-painiketta sen lataamiseen - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> <p>Solmun luonti on kytketty pois päältä kunnes kaikki kentät ovat asetettu oikein.</p> @@ -7735,12 +7129,7 @@ ja käyttää tuo-painiketta sen lataamiseen <p>Solmua ei luoda ennen kuin tarpeeksi satunnaisuutta on kerätty. Ole hyvä ja liikuta hiirtäsi ympäriinsä kunnes saavutat vähintään 20%.</p> - - I2P instance address with BOB enabled - I2P-instanssiosoite, jossa BOB on kytketty päälle - - - + I2P instance address I2P-instanssiosoite @@ -7966,36 +7355,13 @@ ja käyttää tuo-painiketta sen lataamiseen Aloittaminen - + Invite Friends Kutsu ystäviä - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Retroshare ei ole mitään ilman ystäviä. Paina nappia aloittaaksesi prosessin.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Lähetä ystävillesi kutsu ja &quot;varmennetunnisteesi&quot; sähköpostilla.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Pyydä myös heiltä vastaava kutsu... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Saat yhteyden ystävääsi vain, jos lisäätte toisenne varmenteet.</span></p></body></html> - - - + Add Your Friends to RetroShare Lisää ystäviäsi Retroshareen @@ -8005,136 +7371,103 @@ p, li { white-space: pre-wrap; } Lisää ystäviä - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Kun olette linjoilla ystävienne kanssa samanaikaisesti, Retroshare yhdistää teidät automaattisesti!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Ohjelman on löydettävä Retroshare-verkko, jotta yhteyksien luominen on mahdollista.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Tämä vie 5-30 minuuttia, kun käynnistät Retrosharen ensimmäistä kertaa</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">DHT-merkki tilarivillä muuttuu vihreäksi, kun yhteyksien luominen on mahdollista.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Muutaman minuutin jälkeen NAT-merkki (myös tilarivillä) vaihtuu keltaisesta vihreään.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Jos se pysyy punaisena, sinulla on palomuuri, jonka läpi Retroshare ei pääse.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Katso Lisäapua-osiosta neuvoja yhteyden luomiseksi.</span></p></body></html> + + Connect To Friends + Ota yhteys ystäviin - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Voit parantaa Retrosharen suorituskykyä avaamalla ulkoisen portin. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Tämä nopeuttaa yhteyksiä ja sallii useampien käyttäjien olla yhteydessä sinuun. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Helpoin tapa on ottaa UPnP käyttöön langattoman tukiasemasi tai reitittimesi asetuksissa.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Jokainen reititin on erilainen, joten etsi ohjeet reitittimellesi internetin hakukoneilla.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Jos et ymmärrä edellisestä mitään, älä huoli, koska Retroshare toimii joka tapauksessa.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Vaativa: Avaa palomuurin portti <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Onko sinulla ongelmia päästä Retrosharen kanssa alkuun?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) katso usein kysytyt kysymykset (FAQ Wiki). Se on hieman vanhentunut, yritämme ajantasaistaa sitä.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) tutustu keskustelupalstaamme. Kysele tai keskustele ominaisuuksista.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) kokeile Retrosharen sisäisiä keskustelupalstoja </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - Nämä ilmestyvät näkyviin, kun olet saanut yhteyden ystäviisi.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) jos olet edelleen jumissa, lähetä meille sähköpostia.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Nauti Retrosharetuksesta</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> + - - Connect To Friends - Ota yhteys ystäviin - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Kun ystäväsi lähettävät sinulle kutsunsa, klikkaa avataksesi Lisää ystäviä -ikkuna.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Kopioi ja liitä ystäviesi &quot;varmennetunnisteet&quot; ikkunaan ja lisää heidät ystäviksesi.</span></p></body></html> - - - - Advanced: Open Firewall Port - Vaativa: Avaa palomuurin portti - - - + Further Help and Support Lisää ohjeita ja tukea - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website Avaa RS-verkkosivu @@ -8159,7 +7492,7 @@ p, li { white-space: pre-wrap; } Sähköpostipalaute - + RetroShare Invitation Retroshare-kutsu @@ -8209,12 +7542,12 @@ p, li { white-space: pre-wrap; } Palaute Retrosharelle - + RetroShare Support Retrosharen tuki - + It has many features, including built-in chat, messaging, Sillä on monia ominaisuuksia, mukaan lukien keskustelu, viestit, @@ -8338,7 +7671,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat Näytä ryhmäkeskustelu @@ -8346,7 +7679,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] [Tuntematon] @@ -8512,19 +7845,11 @@ p, li { white-space: pre-wrap; } You can let your friends know about your forum by sharing it with them. Select the friends with which you want to share your forum. Voit antaa ystäviesi tietää foorumistasi jakamalla sen heidän kanssaan. Valitse ystävät, joiden kanssa haluat jakaa foorumin. - - Share topic admin permissions - Jaa keskustelunaihe ylläpitooikeuksia - - - You can allow your friends to edit the topic. Select them in the list below. Note: it is not possible to revoke Posted admin permissions. - Voit sallia ystäviesi muokata aihetta. Valitse heidät alla olevasta luettelosta. Huomautus: Lähetettyjen ylläpito-oikeuksia ei voi kumota. - GroupTreeWidget - + Title Otsikko @@ -8537,12 +7862,12 @@ p, li { white-space: pre-wrap; } - + Description Kuvaus - + Number of Unread message @@ -8567,35 +7892,7 @@ p, li { white-space: pre-wrap; } - Sort Descending Order - Laskeva järjestys - - - Sort Ascending Order - Nouseva järjestys - - - Sort by Name - Järjestä nimen mukaan - - - Sort by Popularity - Järjestä suosion mukaan - - - Sort by Last Post - Järjestä viimeisimmän viestin mukaan - - - Sort by Number of Posts - Järjestä viestien määrän mukaan - - - Sort by Unread - Järjestä lukemattomien mukaan - - - + You are admin (modify names and description using Edit menu) Olet ylläpitäjä (muokkaa nimiä ja kuvaksia käyttäen Muokkaa-valikkoa) @@ -8610,14 +7907,14 @@ p, li { white-space: pre-wrap; } Tunniste - - + + Last Post Viimeisin viesti - + Name Nimi @@ -8628,17 +7925,13 @@ p, li { white-space: pre-wrap; } Suosio - + Never Ei koskaan - Display - Näytä - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8651,7 +7944,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and ja @@ -8787,7 +8080,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels Kanavat @@ -8798,26 +8091,22 @@ p, li { white-space: pre-wrap; } Luo kanava - + Enable Auto-Download Ota käyttöön automaattinen lataus - + My Channels Kanavani - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Kanavat</h1> <p>Kanavat sallivat sinun lähettää dataa (esim. elokuvia, musiikkia) , jotka leviävät verkostossa.</p> <p>Voit nähdä mitä kanavia ystäväsi tilaavat, ja automaattisesti edelleenlähettää tilatut kanavat ystävillesi. Tämä edistää verkoston hyviä kanavia.</p> <p>Ainoastaan kanavan luoja pystyy lähettämään kyseiselle kanavalle. Muut vertaiset verkostossa pystyvät vain lukemaan sitä, ellei kanava ole yksityinen. Kaikesta huolimatta voit jakaa lähetys- tai luku-oikeuksia ystäviesi Retroshare-solmuille.</p> <p>Kanavista voidaan tehdä nimettömiä, tai niihin voidaan liittää Retroshare-henkilöllisyys, että lukijat voivat yhteyden sinuun tarvittaessa. Salli "Salli kommentit", jos haluat käyttäjien kommentoivan viestejäsi.</p> <p>Kanavan viestit säilyvät %1 päivää, and pidetään ajan tasalla %2 päivän ajan, ellet sinä muuta tätä.</p> - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Tilatut kanavat @@ -8837,12 +8126,12 @@ p, li { white-space: pre-wrap; } Valitse kanavan lataushakemisto - + Disable Auto-Download Ota automaattinen lataus pois käytöstä - + Set download directory Aseta lataushakemisto @@ -8877,22 +8166,22 @@ p, li { white-space: pre-wrap; } - + Play Toista - + Open folder Avaa kansio - + Open file - + Error Virhe @@ -8912,17 +8201,17 @@ p, li { white-space: pre-wrap; } Tarkistetaan - + Are you sure that you want to cancel and delete the file? Oletko varma, että haluat peruuttaa ja poistaa tiedoston? - + Can't open folder Kansiota ei voida avata - + Play File Toista tiedosto @@ -8932,37 +8221,10 @@ p, li { white-space: pre-wrap; } Tiedostoa %1 ei löydy sijainnista. - - GxsChannelFilesWidget - - Form - Lomake - - - Filename - Tiedostonimi - - - Size - Koko - - - Title - Otsikko - - - Published - Julkaistu - - - Status - Tila - - GxsChannelGroupDialog - + Create New Channel Luo uusi kanava @@ -9000,9 +8262,19 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - Tilaa kanava + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel + @@ -9016,7 +8288,7 @@ p, li { white-space: pre-wrap; } - + Expand Laajenna @@ -9031,7 +8303,7 @@ p, li { white-space: pre-wrap; } Kanavan kuvaus - + Loading Ladataan @@ -9046,8 +8318,9 @@ p, li { white-space: pre-wrap; } - New Channel - Uusi kanava + + Never + Ei koskaan @@ -9058,7 +8331,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: Uusi kommentti: @@ -9079,7 +8352,7 @@ p, li { white-space: pre-wrap; } - + Play Toista @@ -9135,28 +8408,24 @@ p, li { white-space: pre-wrap; } Files Tiedostot - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - Varoitus! Sinulla on alle %1 tuntia ja %2 minuuttia aikaa, ennen kuin tämä tiedosto poistetaan. Harkitse sen tallentamista. - Hide Piilota - + New Uusi - + 0 0 - - + + Comment Kommentti @@ -9171,21 +8440,17 @@ p, li { white-space: pre-wrap; } En pidä tästä - Loading - Ladataan - - - + Loading... - + Comments Kommentit - + Post @@ -9210,139 +8475,16 @@ p, li { white-space: pre-wrap; } Toista media - - GxsChannelPostsWidget - - Post to Channel - Lähetä viesti kanavalle - - - Add new post - Lisää uusi kirjoitus - - - Loading - Ladataan - - - Search channels - Hae kanavia - - - Title - Otsikko - - - Search Title - Hae otsikolla - - - Message - Viesti - - - Search Message - Hae viestejä - - - Filename - Tiedostonimi - - - Search Filename - Hae tiedostonimiä - - - No Channel Selected - Ei kanavaa valittuna - - - Never - Ei koskaan - - - Public - Julkinen - - - Restricted to members of circle " - Rajoitettu piirin jäseniin " - - - Restricted to members of circle - Rajoitettu piirin jäseniin - - - Your eyes only - Vain silmillesi - - - You and your friend nodes - Sinä ja ystäväsolmusi - - - Disable Auto-Download - Ota automaattinen lataus pois käytöstä - - - Enable Auto-Download - Ota käyttöön automaattinen lataus - - - Show feeds - Näytä syötteet - - - Show files - Näytä tiedostot - - - Administrator: - Ylläpitäjä: - - - Last Post: - Viimeisin viesti: - - - unknown - tuntematon - - - Distribution: - Jakelu: - - - Feeds - Syötteet - - - Files - Tiedostot - - - Subscribers - Tilaajat - - - Description: - Kuvaus: - - - Posts (at neighbor nodes): - Viestit (naapurisolmuissa): - - GxsChannelPostsWidgetWithModel - + Post to Channel Lähetä viesti kanavalle - + Add new post Lisää uusi kirjoitus @@ -9412,7 +8554,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -9448,7 +8590,7 @@ p, li { white-space: pre-wrap; } - + Comments Kommentit @@ -9463,13 +8605,13 @@ p, li { white-space: pre-wrap; } Syötteet - - + + Click to switch to list view - + Show unread posts only @@ -9484,7 +8626,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -9499,7 +8641,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -9559,12 +8701,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -9639,12 +8791,13 @@ p, li { white-space: pre-wrap; } Sinä ja ystäväsolmusi - + + Copy Retroshare link - + Subscribed Tilattu @@ -9695,17 +8848,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -9725,27 +8878,11 @@ p, li { white-space: pre-wrap; } Remove Item Poista kohde - - for identity - henkilöllisyydelle - - - You received a membership request for circle: - Olet vastaanottanut jäsenyyspyydön piiriin: - Grant membership request Myönnä jäsenyyspyyntö - - Revoke membership request - Kumoa jäsenyyspyyntö - - - You received an invitation for circle: - Olet vastaanottanut kutsun piiriin: - @@ -9836,7 +8973,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container Kommenttisäiliö @@ -9849,7 +8986,7 @@ p, li { white-space: pre-wrap; } Lomake - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9879,7 +9016,7 @@ p, li { white-space: pre-wrap; } Päivitä - + Comment Kommentti @@ -9918,7 +9055,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment Vastaa kommenttiin @@ -9942,6 +9079,21 @@ p, li { white-space: pre-wrap; } Vote Down Äänestä alas + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9951,7 +9103,7 @@ p, li { white-space: pre-wrap; } Lisää kommentti - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9980,26 +9132,10 @@ p, li { white-space: pre-wrap; } - + Post - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Kommentti</span></p></body></html> - - - Signed by - Allekirjoittaja - Reply to Comment @@ -10028,7 +9164,7 @@ before you can comment kuin voit kommentoida - + It remains %1 characters after HTML conversion. @@ -10070,14 +9206,6 @@ kuin voit kommentoida Forum moderators can edit/delete/pinup others posts - - Add Forum Admins - Lisää ylläpitäjiä foorumiin - - - Select Forum Admins - Valitse foorumin ylläpitäjiä - Create @@ -10087,7 +9215,7 @@ kuin voit kommentoida GxsForumGroupItem - + Subscribe to Forum Tilaa foorumi @@ -10103,7 +9231,7 @@ kuin voit kommentoida - + Expand Laajenna @@ -10123,8 +9251,9 @@ kuin voit kommentoida - Loading - Ladataan + + TextLabel + @@ -10155,13 +9284,13 @@ kuin voit kommentoida GxsForumMsgItem - - + + Subject: Aihe: - + Unsubscribe To Forum Lopeta foorumin tilaus @@ -10172,7 +9301,7 @@ kuin voit kommentoida - + Expand Laajenna @@ -10192,21 +9321,17 @@ kuin voit kommentoida Vastauksena: - Loading - Ladataan - - - + Loading... - + Forum Feed Foorumisyöte - + Hide Piilota @@ -10219,63 +9344,66 @@ kuin voit kommentoida Lomake - + Start new Thread for Selected Forum Aloita uusi viestiketju valitussa foorumissa - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Hae foorumeista - Last Post - Viimeisin viesti - - - + New Thread Uusi viestiketju - - - Threaded View - Ketjunäkymä - - - - Flat View - Tasanäkymä - - + Title Otsikko - - + + Date Päiväys - + Author Kirjoittaja - - Save image - Tallenna kuva - - - + Loading Ladataan - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -10285,12 +9413,7 @@ kuin voit kommentoida - - Lastest post in thread - - - - + Reply Message Vastaa viestiin @@ -10314,10 +9437,6 @@ kuin voit kommentoida Download all files Lataa kaikki tiedostot - - Next unread - Seuraava lukematon - Search Title @@ -10334,35 +9453,23 @@ kuin voit kommentoida Hae kirjoittajaa - Content - Sisältö - - - Search Content - Hae sisältöä - - - <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - <p>Foorumin tilaaminen kerää kaikki saatavilla olevat viestit tilaajaystäviltäsi, ja tekee foorumista näkyvän kaikille muille ystävillesi.</p><p>Myöhemmin voit peruuttaa tilauksen foorumin kontekstivalikosta vasemmalla.</p> - - - + No name Ei nimeä - - + + Reply Vastaa - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -10405,20 +9512,12 @@ kuin voit kommentoida Kopioi Retroshare-linkki - + Hide Piilota - Expand - Laajenna - - - [Banned] - [Pannassa] - - - + [unknown] [tuntematon] @@ -10448,8 +9547,8 @@ kuin voit kommentoida Vain silmillesi - - + + Distribution @@ -10463,26 +9562,6 @@ kuin voit kommentoida Anti-spam Roskapostin esto - - [ ... Redacted message ... ] - [ ... Muokattu viesti ... ] - - - Anonymous - Nimetön - - - signed - allekirjoitettu - - - none - ei mitään - - - [ ... Missing Message ... ] - [ ... Puuttuva viesti ... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10552,16 +9631,12 @@ kuin voit kommentoida Alkuperäinen viesti - + New thread Uusi viestiketju - Read status - Lue tilaviesti - - - + Edit Muokkaa @@ -10622,7 +9697,7 @@ kuin voit kommentoida Kirjoittajan maine - + Show column @@ -10642,7 +9717,7 @@ kuin voit kommentoida - + Anonymous/unknown posts forwarded if reputation is positive Nimettömät/tuntemattomat viestit lähetetään edelleen, jos maine on myönteinen @@ -10694,7 +9769,7 @@ This message is missing. You should receive it later. - + No result. @@ -10704,7 +9779,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -10719,29 +9794,7 @@ This message is missing. You should receive it later. - Information for this identity is currently missing. - Tämän henkilöllisyyden tiedot ovat tällä hetkellä kateissa. - - - You have banned this ID. The message will not be -displayed nor forwarded to your friends. - Olet laittanut tämän tunnisteen pannaan. Viestiä ei -näytetä eikä lähetä eteenpäin ystävillesi. - - - You have not set an opinion for this person, - and your friends do not vote positively: Spam regulation -prevents the message to be forwarded to your friends. - Et ole asettanut mielipidettä tästä henkilöstä, - ja ystäväsi eivät äänestä myönteisesti: Roskapostin säätely -estää viestin lähettämisen eteenpäin ystävillesi. - - - Message will be forwarded to your friends. - Viesti tullaan välittämään ystävillesi. - - - + (Latest) (Viimeisin) @@ -10750,10 +9803,6 @@ estää viestin lähettämisen eteenpäin ystävillesi. (Old) (Vanha) - - You cant act on the author to a non-existant Message - Et voi ottaa toimia olemattoman viestin kirjoittajan suhteen - From @@ -10811,12 +9860,12 @@ estää viestin lähettämisen eteenpäin ystävillesi. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Foorumit</h1> <p>Retrosharen foorumit toimivat hajautetusti</p> <p>Näet foorumit, jotka ystäväsi ovat tilanneet ja vastaavasti välität tilaamasi foorumit ystävillesi. Tällä tavoin kiinnostavien foorumeiden näkyvyys lisääntyy automaattisesti.</p> <p>Foorumiviestit pidetään %1 päivän ajan ja ajantasaistetaan viimeisiltä %2 päivältä ellet määritä sitä toisin.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> + - + Forums Foorumi @@ -10847,35 +9896,16 @@ estää viestin lähettämisen eteenpäin ystävillesi. Muut foorumit - - GxsForumsFillThread - - Waiting - Odotetaan - - - Retrieving - Noudetaan - - - Loading - Ladataan - - GxsGroupDialog - + Name Nimi - Add Icon - Lisää kuvake - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels Avaimen vastaanottajat voivat julkaista rajoitetuille ryhmille ja voivat nähdä sekä julkaista yksityisille kanaville @@ -10884,22 +9914,14 @@ estää viestin lähettämisen eteenpäin ystävillesi. Share Publish Key Jaa julkaisuavain - - check peers you would like to share private publish key with - rastita vertaiset, joiden kanssa haluat jakaa yksityisen julkaisuavaimesi - - - Share Key With - Jaa avain - - + Description Kuvaus - + Message Distribution Viestin leviäminen @@ -10907,7 +9929,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. - + Public Julkinen @@ -10926,14 +9948,6 @@ estää viestin lähettämisen eteenpäin ystävillesi. New Thread Uusi viestiketju - - Required - Vaaditaan - - - Encrypted Msgs - Salatut viestit - Personal Signatures @@ -10975,7 +9989,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Roskaposti-suojaus - + Comments: Kommentit: @@ -10998,7 +10012,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Roskapostin esto: - + All People @@ -11014,12 +10028,12 @@ estää viestin lähettämisen eteenpäin ystävillesi. - + Restricted to circle: Rajoitettu piiriin: - + Limited to your friends Rajattu ystäviisi @@ -11036,23 +10050,23 @@ estää viestin lähettämisen eteenpäin ystävillesi. - + Message tracking Viestiseuranta - - + + PGP signature required PGP-allekirjoitus vaaditaan - + Never Ei koskaan - + Only friends nodes in group Vain ryhmässä olevat ystäväsolmut @@ -11068,30 +10082,28 @@ estää viestin lähettämisen eteenpäin ystävillesi. Ole hyvä ja lisää nimi - + PGP signature from known ID required PGP-allekirjoitus tunnetulta tunnisteelta vaaditaan - + + + [None] + + + + Load Group Logo Lataa ryhmän logo - + Submit Group Changes Vahvista ryhmän muutokset - Failed to Prepare Group MetaData - please Review - Ryhmän metatietojen luonti epäonnistui - tarkista tiedot - - - Will be used to send feedback - Käytetään palautteen lähettämiseen - - - + Owner: Omistaja: @@ -11101,12 +10113,12 @@ estää viestin lähettämisen eteenpäin ystävillesi. Aseta kuvaava kuvaus tähän - + Info Tietoja - + ID Tunniste @@ -11116,7 +10128,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Viimeisin viesti - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> <html><head/><body><p>Viestit leviävät ystäväsolmujen ulkopuolelle, niin kauan kun ihmiset tilaavat kanavan/foorumin/lähetetyn, jolle luot sisältöä.</p></body></html> @@ -11191,7 +10203,12 @@ estää viestin lähettämisen eteenpäin ystävillesi. Haittaa allekirjoittamattomia tunnisteita ja tunnisteita tuntemattomista solmuista - + + Author: + + + + Popularity Suosio @@ -11207,27 +10224,22 @@ estää viestin lähettämisen eteenpäin ystävillesi. - + Created - + Cancel - + Create Luo - - Author - Kirjoittaja - - - + GxsIdLabel GxsTunnisteselite @@ -11235,7 +10247,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. GxsGroupFrameDialog - + Loading Ladataan @@ -11295,7 +10307,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Muokkaa tietoja - + Synchronise posts of last... Ajantasaista viestit ajalta... @@ -11352,16 +10364,12 @@ estää viestin lähettämisen eteenpäin ystävillesi. - + Search for - Share publish permissions - Jaa julkaisuoikeudet - - - + Copy RetroShare Link Kopioi Retroshare-linkki @@ -11384,7 +10392,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. GxsIdChooser - + No Signature Ei allekirjoitusta @@ -11397,40 +10405,24 @@ estää viestin lähettämisen eteenpäin ystävillesi. GxsIdDetails - Loading - Ladataan - - - + Not found Ei löydy - - No Signature - Ei allekirjoitusta - - - + + [Banned] [Pannassa] - - Authentication - Varmennus - unknown Key tuntematon avain - anonymous - nimetön - - - + Loading... @@ -11440,7 +10432,12 @@ estää viestin lähettämisen eteenpäin ystävillesi. - + + [Nobody] + + + + Identity&nbsp;name Henkilöllisyyden&nbsp;nimi @@ -11454,16 +10451,20 @@ estää viestin lähettämisen eteenpäin ystävillesi. Node Solmu - - Signed&nbsp;by - Allekirjoittama - [Unknown] [Tuntematon] + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -11475,7 +10476,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. GxsIdStatisticsWidget - + Total identities: @@ -11523,17 +10524,13 @@ estää viestin lähettämisen eteenpäin ystävillesi. GxsIdTreeItemDelegate - + [Unknown] [Tuntematon] GxsMessageFramePostWidget - - Loading - Ladataan - Loading... @@ -11650,10 +10647,6 @@ estää viestin lähettämisen eteenpäin ystävillesi. Group ID / Author Ryhmätunniste / Kirjoittaja - - Number of messages / Publish TS - Viestien määrä / Julkaise liikennetilastot - Local size of data @@ -11669,10 +10662,6 @@ estää viestin lähettämisen eteenpäin ystävillesi. Popularity Suosio - - Details - Tiedot - @@ -11705,33 +10694,6 @@ estää viestin lähettämisen eteenpäin ystävillesi. Ei - - GxsTunnelsDialog - - Authenticated tunnels: - Varmennetut tunnelit: - - - Tunnel ID: %1 - Tunnelitunniste: %1 - - - status: %1 - tila: %1 - - - total sent: %1 bytes - lähetetty yhteensä: %1 tavua - - - total recv: %1 bytes - vastaanotettu yhteensä: %1 tavua - - - Unknown Peer - Tuntematon vertainen - - HashBox @@ -11944,48 +10906,12 @@ estää viestin lähettämisen eteenpäin ystävillesi. About Tietoja - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare provides file sharing, chat, messages and channels</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Useful external links to more information:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Wiki</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare's Forum</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Project Page</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Team Blog</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Dev Twitter</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Retroshare on avoimen lähdekoodin alustariippumaton, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">yksityinen ja turvallinen hajautettu viestintäalusta. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Se antaa sinun jakaa turvallisesti ystäväsi, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">käyttäen luottamuksen verkkoa todentaakseen vertaiset ja OpenSSL kaiken viestinnän salaukseen. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Retroshare tarjoaa tiedostojen jakamisen, keskustelun, viestit ja kanavat</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Hyödyllisiä ulkoisia linkkejä lisätietoja varten:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Retroshare verkkosivu</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare wiki</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retrosharen foorumi</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare projekti-sivu</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare työryhmän blogi</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare kehittäjien Twitter</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -12001,7 +10927,7 @@ p, li { white-space: pre-wrap; } - + Authors Tekijät @@ -12020,7 +10946,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -12033,36 +10959,6 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Daniel Wester</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">wester@speedmail.se</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">German: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Jan</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Keller</span><span style=" font-family:'MS Shell Dlg 2';"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">trilarion@users.sourceforge.net</span><span style=" font-family:'MS Shell Dlg 2';">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Retroshare käännökset:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Retroshare verkkosivuston kääntäjät:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Ruotsi: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Daniel Wester</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">wester@speedmail.se</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Saksa: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Jan</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Keller</span><span style=" font-family:'MS Shell Dlg 2';"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">trilarion@users.sourceforge.net</span><span style=" font-family:'MS Shell Dlg 2';">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Puola: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - License Agreement @@ -12128,12 +11024,12 @@ p, li { white-space: pre-wrap; } Lomake - + <html><head/><body><p>Copy your RetroShare ID to clipboard</p></body></html> - + Add friend @@ -12148,7 +11044,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -12157,32 +11053,12 @@ p, li { white-space: pre-wrap; } This is your Retroshare ID. Copy and share with your friends! - - Did you receive a certificate from a friend? - Saitko varmenteen ystävältäsi? - - - Add friends certificate - Lisää ystäväsi varmenne - - - Add certificate file - Lisää varmenne-tiedosto - - - Share your RetroShare Key - Jaa Retroshare-avaimesi - ... ... - - The text below is your own Retroshare certificate. Send it to your friends - Teksti alapuolella on Retroshare-varmenteesi. Lähetä se ystävillesi - Open Source cross-platform, @@ -12193,20 +11069,12 @@ yksityinen ja turvallinen hajautettu viestintäalusta. - Launch startup wizard - Käynnistä ohjattu aloitus - - - Do you need help with RetroShare? - Tarvitsetko apua Retrosharen kanssa? - - - + Open Web Help Avaa verkkotuki (englanniksi) - + Copy your Cert to Clipboard Kopioi varmenteesi leikepöydälle @@ -12216,7 +11084,7 @@ yksityinen ja turvallinen hajautettu viestintäalusta. Tallenna varmenteesi tiedostoon - + Send via Email Lähetä sähköpostitse @@ -12236,13 +11104,37 @@ yksityinen ja turvallinen hajautettu viestintäalusta. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -12254,17 +11146,12 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -12273,19 +11160,11 @@ new short format Your Retroshare ID is copied to Clipboard, paste and send it to your friend via email or some other way - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your certificate on this page and send it to friends, and add your friends' certificate.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange certificates with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Tervetuloa Retroshareen!</h1> <p>Sinun pitää <b>tehdä ystäviä</b>! Kun olet luonut ystäväverkoston tai liittynyt olemassa olevaan verkostoon voit vaihtaa tiedostoja, keskustella, jutustella foorumeilla, jne. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>Näin tehdäksesi, kopioi varmenteesi tällä sivulla ja lähetä se ystävillesi, ja lisää ystäviesi varmenteet.</p> <p>Toinen vaihtoehto on etsiä internetistä "Retroshare chat servers" (itsenäisesti hallinnoituja). Nämä palvelimet antavat sinun vaihtaa varmenteita palvelin Retroshare-solmun kanssa, jonka kautta voit nimettömästi tavata muita ihmisiä.</p> - RetroShare Invite Retroshare-kutsu - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Varmenteesi on kopioitu leikepöydälle, liitä ja lähetä se ystävällesi sähköpostilla tai muulla tavoin - Save as... @@ -12557,14 +11436,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Kaikki - + Reputation Maine @@ -12574,12 +11453,12 @@ p, li { white-space: pre-wrap; } Haku - + Anonymous Id Nimetön tunniste - + Create new Identity Luo uusi henkilöllisyys @@ -12589,7 +11468,7 @@ p, li { white-space: pre-wrap; } Luo uusi piiri - + Persons Henkilöt @@ -12604,27 +11483,27 @@ p, li { white-space: pre-wrap; } Henkilö - + Close Sulje - + Ban-option: Pannaus-vaihtoehto: - + Auto-Ban all identities signed by the same node Automaattisesti pannaa kaikki henkilöllisyydet, jotka ovat saman solmun allekirjoittamia - + Friend votes: Ystävän äänet: - + Positive votes Myönteisiä ääniä @@ -12640,29 +11519,39 @@ p, li { white-space: pre-wrap; } Kielteisiä ääniä - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics Käyttötilastot - + Circles Piirit - + Circle name Piirin nimi @@ -12682,18 +11571,20 @@ p, li { white-space: pre-wrap; } Henkilökohtaiset piirit - + + Edit identity Muokkaa henkilöllisyyttä - + + Delete identity Poista henkilöllisyys - + Chat with this peer Keskustele vertaisen kanssa @@ -12703,98 +11594,78 @@ p, li { white-space: pre-wrap; } Käynnistää etäisen keskustelun vertaisen kanssa - + Owner node ID : Omistajasolmun tunniste: - + Identity name : Henkilöllisyyden nimi: - + () () - + Identity ID Henkilöllisyystunniste - + Send message Lähetä viesti - + Identity info Henkilöllisyyden tiedot - + Identity ID : Henkilöllisyystunniste: - + Owner node name : Omistajasolmun nimi: - + Create new... Luo uusi... - + Type: Tyyppi: - + Send Invite Lähetä kutsu - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> <html><head/><body><p>Naapurisolmujen mielipiteiden keskiarvo tästä henkilöllisyydestä. Kielteinen on huono,</p><p>myönteinen on hyvä. Nolla on neutraali.</p></body></html> - + Your opinion: Sinun mielipiteesi: - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </p> -<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Sinun oma mielipiteesi henkilöllisyydestä määrittää kyseisen henkilöllisyyden näkyvyyden itsellesi ja ystäväsolmuille. Sinun oma mielipiteesi jaetaan ystäviesi kesken ja käytetään maineen pisteytyksen laskemiseen: Jos mielipiteesi henkilöllisyydestä on neutraali, maineen pisteytys lasketaan ystäviesi myönteisten ja kielteisten mielipiteiden erotuksesta. Jos ei, sinun oma mielipiteesi antaa pisteytyksen.</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Kokonaispisteytystä käytetään keskusteluauloissa, foorumeilla ja kanavilla toimien määrittämiseen kullekin tietylle henkilöllisyydelle. Kun kokonaispisteytys on alle -1, henkilöllisyys asetetaan pannaan, joka estää tämän henkilöllisyyden kirjoittamien kaikkien viestien ja foorumien/kanavien eteenpäin välityksen, kumpaankin suuntaan. Jotkin foorumit omaavat myös erikois roskapostinestoilmaisimia, jotka vaativat ei-kielteisen maineen tason, tehden niistä herkempiä huonoille mielipiteille. Pannassa olevat henkilöllisyydet vähitellen menettävät toimeliaisuuden ja lopulta katoavat (5 päivän jälkeen).</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Sinä voit muuttaa kynnyksiä ja toimettomuuden aikaa henkilöllisyyksien poistamiseen asetuksista -&gt; Ihmiset. </p> -<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - + Negative Kielteinen - + Neutral Neutraali @@ -12805,17 +11676,17 @@ p, li { white-space: pre-wrap; } Myönteinen - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> <html><head/><body><p>Kokonaismainepisteytys, mukaan laskien sinun sekä ystäviesi.</p><p>Kielteinen on huono, myönteinen on hyvä. Nolla on neutraali. Jos pisteytys on liian alhainen,</p><p>henkilöllisyys merkitään huonoksi, ja tullaan suodattamaan pois foorumeilta, keskusteluauloista,</p><p>kanavilta, jne.</p></body></html> - + Overall: Yhteensä: - + Anonymous Nimetön @@ -12830,24 +11701,24 @@ p, li { white-space: pre-wrap; } Hae tunnistetta - + This identity is owned by you Tämä henkilöllisyys on sinun omistamasi - - + + My own identities Minun henkilöllisyyteni - - + + My contacts - + Show Items Näytä kohteet @@ -12862,7 +11733,12 @@ p, li { white-space: pre-wrap; } Linkitetty solmuuni - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles Muut piirit @@ -12872,7 +11748,7 @@ p, li { white-space: pre-wrap; } Piirit joihin kuulun - + Circle ID: Piiri tunniste: @@ -12947,7 +11823,7 @@ p, li { white-space: pre-wrap; } Ei jäsen (ei ole pääsyä tälle piirille rajoitettuun dataan) - + Identity ID: Henkilöllisyystunniste: @@ -12977,7 +11853,7 @@ p, li { white-space: pre-wrap; } tuntematon - + Invited Kutsuttu @@ -12992,7 +11868,7 @@ p, li { white-space: pre-wrap; } Jäsen - + Edit Circle Muokkaa piiriä @@ -13040,7 +11916,7 @@ p, li { white-space: pre-wrap; } Myönnä jäsenyys - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -13051,7 +11927,7 @@ Sinun pitäisi hankkiutua siitä eroon ja käyttää uutta. Näitä henkilöllisyyksien tuki lakkaa pian. - + [Unknown node] [Tuntematon solmu] @@ -13094,7 +11970,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Nimetön henkilöllisyys - + Boards @@ -13174,7 +12050,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - + information tietoa @@ -13190,29 +12066,12 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Kopioi henkilöllisyys leikepöydälle - Send invite? - Lähetä kutsu? - - - Do you really want send a invite with your Certificate? - Haluatko todella lähettää kutsun varmenteellasi? - - - + Banned Pannassa - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - Unknown ID: - Tuntematon tunniste: - - - + positive positiviinen @@ -13256,19 +12115,11 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Forums Foorumit - - Posted - Lähetetty - Chat Keskustelu - - Unknown - Tuntematon - [Unknown] @@ -13289,14 +12140,6 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Creation of author signature in service %1 Kirjoittajan allekirjoituksen luonti palvelussa %1 - - Message/vote/comment - Viesti/ääni/kommentti - - - %1 in %2 tab - %1 %2 välilehdessä - Distant message signature validation. @@ -13317,19 +12160,11 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Signature in distant tunnel system. Allekirjoitus etäisessä tunnelijärjestelmässä. - - Update of identity data. - Henkilöllisyys-datan päivitys. - Generic signature validation. Yleinen allekirjoituksen vahvistaminen. - - Generic signature. - Yleinen allekirjoitus. - Generic encryption. @@ -13341,11 +12176,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Yleinen salauksen purku. - Membership verification in circle %1. - Jäsenyyden varmistus piirissä %1. - - - + Add to Contacts @@ -13395,21 +12226,21 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Hei,<br>haluan olla ystäväsi Retrosharessa.<br> - - - + + + People Ihmiset - + Your Avatar Click here to change your avatar Sinun avatar - + Linked to neighbor nodes Linkitetty naapurisolmuihin @@ -13419,7 +12250,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Linkitetty etäisiin solmuihin - + Linked to a friend Retroshare node Linkitetty ystävä Retroshare-solmuun @@ -13434,7 +12265,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Linkitetty tuntemattomaan Retroshare-solmuun - + Chat with this person Keskustele henkilön kanssa @@ -13449,12 +12280,12 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Tämä henkilö torjui etäisen keskustelun - + Last used: Viimeksi käytetty: - + +50 Known PGP +50 tiedettyä PGP:tä @@ -13474,12 +12305,12 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Haluatko todella poistaa tämän henkilöllisyyden? - + Owned by Omistama - + Node name: Solmun nimi: @@ -13489,7 +12320,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Solmun tunniste : - + Really delete? Tuhotaanko? @@ -13497,7 +12328,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. IdEditDialog - + Nickname Nimimerkki @@ -13527,7 +12358,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Nimimerkki - + Import image @@ -13537,12 +12368,19 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - - Use the mouse to zoom and adjust the image for your avatar. + + + No Avatar chosen. A default image will be automatically displayed from your new identity. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity Uusi henkilöllisyys @@ -13556,7 +12394,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - + @@ -13566,7 +12404,12 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Ei sovellu - + + No avatar chosen + + + + Edit identity Muokkaa henkilöllisyyttä @@ -13577,27 +12420,27 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Päivitä - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -13617,7 +12460,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - + Identity update failed @@ -13627,11 +12470,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - Error getting key! - Virhe haettaessa avainta! - - - + Error KeyID invalid Virhe: viallinen avaimen tunniste @@ -13646,7 +12485,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Tuntematon oikea nimi - + Create New Identity Luo uusi henkilöllisyys @@ -13656,10 +12495,15 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Tyyppi - + Choose image... + + + Remove + Poista + @@ -13685,7 +12529,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Lisää - + Create Luo @@ -13695,17 +12539,13 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - + Your Avatar Click here to change your avatar Sinun avatar - Set Avatar - Aseta Avatar - - - + Linked to your profile Linkitetty profiiliisi @@ -13715,7 +12555,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Sinulla voi olla yksi tai useampi henkilöllisyys. Niitä käytetään usein kirjoitettaessa keskusteluhuoneisiin, foorumeille ja kanavakommentteihin. Ne toimivat kohteena etäiselle keskustelulle ja Retrosharen etäiselle postijärjestelmälle. - + The nickname is too short. Please input at least %1 characters. Nimimerkki on liian lyhyt. Syötä vähintään %1 merkkiä. @@ -13774,10 +12614,6 @@ Näitä henkilöllisyyksien tuki lakkaa pian. PGP name: PGP-nimi: - - GXS id: - GXS tunniste: - PGP id: @@ -13793,7 +12629,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - + Copy Kopioi @@ -13803,12 +12639,12 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Poista - + %1 's Message History - + Mark all Merkitse kaikki @@ -13827,26 +12663,38 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Quote Lainaa - - Send - Lähetä - ImageUtil - - + + Save image Tallenna kuva + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + + + + Cannot save the image, invalid filename Ei voi tallentaa kuvaa, virheellinen tiedostonnimi - + + Copy image + + + + + Not an image Ei ole kuva @@ -13864,27 +12712,32 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - + Enable RetroShare JSON API Server - + Port: Portti: - + Listen Address: - + + Status: + Tila: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -13905,7 +12758,12 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -13914,26 +12772,31 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File Avaa tiedosto - + Open Folder Avaa kansio - + Checking... Tarkistaa... @@ -13943,7 +12806,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Tarkista tiedostot - + Recommend in a message to... Suosittele viestissä vastaanottajalle... @@ -13971,7 +12834,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. MainWindow - + Add Friend Lisää ystävä @@ -13987,7 +12850,8 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - + + Options Asetukset @@ -14008,7 +12872,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - + Quit Lopeta @@ -14019,12 +12883,12 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Ohjattu nopea käynnistys - + RetroShare %1 a secure decentralized communication platform Retroshare %1 turvallinen hajautettu viestintäalusta - + Unfinished Kesken @@ -14053,11 +12917,12 @@ Näitä henkilöllisyyksien tuki lakkaa pian. + Status Tila - + Notify Huomauta @@ -14068,31 +12933,35 @@ Näitä henkilöllisyyksien tuki lakkaa pian. + Open Messages Avaa viestit - + + Bandwidth Graph Siirtonopeuskuvaaja - + Applications Ohjelmat + Help Ohje - + + Minimize Pienennä - + Maximize Suurenna @@ -14107,7 +12976,12 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Retroshare - + + Close window + + + + %1 new message %1 uusi viesti @@ -14137,7 +13011,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. %1 ystävää yhdistettynä - + Do you really want to exit RetroShare ? Haluatko todella poistua Retrosharesta? @@ -14157,7 +13031,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Näytä - + Make sure this link has not been forged to drag you to a malicious website. Varmista, että tämä linkki ei ole huijaus, joka johtaa haitalliselle sivustolle. @@ -14202,12 +13076,13 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Palveluiden käyttöoikeudet - + + Statistics Tilastot - + Show web interface Näytä verkkokäyttöliittymä @@ -14222,7 +13097,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. on käymässä vähiin (tämänhetkinen raja on - + Really quit ? Lopeta? @@ -14231,17 +13106,17 @@ Näitä henkilöllisyyksien tuki lakkaa pian. MessageComposer - + Compose Kirjoita viesti - + Contacts Yhteystiedot - + Paragraph Kappale @@ -14277,12 +13152,12 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Otsikko 6 - + Font size Kirjasinkoko - + Increase font size Suurenna kirjasinkokoa @@ -14297,32 +13172,32 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Lihavointi - + Italic Kursivointi - + Alignment Asettelu - + Add an Image Lisää kuva - + Sets text font to code style Asettaa tekstin kirjasinlajin koodityyliseksi - + Underline Alleviivaus - + Subject: Aihe: @@ -14333,32 +13208,32 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - + Tags Merkkaukset - + Address list: Osoiteluettelo: - + Recommend this friend Suosittele tätä ystävää - + Set Text color Aseta tekstin väri - + Set Text background color Aseta tekstin taustaväri - + Recommended Files Suositellut tiedostot @@ -14428,7 +13303,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. Lisää lainauslohko (blockquote) - + Send To: Lähetä: @@ -14452,10 +13327,6 @@ Näitä henkilöllisyyksien tuki lakkaa pian. &Justify Tasaa &molemmat reunat - - All addresses (mixed) - Kaikki osoitteet (sekaisin) - All people @@ -14467,7 +13338,7 @@ Näitä henkilöllisyyksien tuki lakkaa pian. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> Hei,<br>suosittelen ystävääni; voit luottaa häneen, kuten luotat minuun.<br> @@ -14487,18 +13358,18 @@ Näitä henkilöllisyyksien tuki lakkaa pian. haluaa olla ystäväsi Retrosharessa - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team Hei %1,<br><br>%2 haluaa olla ystäväsi Retrosharessa.<br><br>Vastaa nyt:<br>%3<br><br>Kiittäen,<br>Retroshare-tiimi. - - + + Save Message Tallenna viesti - + Message has not been Sent. Do you want to save message to draft box? Viestiä ei ole lähetetty. @@ -14510,7 +13381,17 @@ Haluatko tallentaa viestin luonnoslaatikkoon? Liitä Retroshare-linkki - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" Lisää vastaanottajiin @@ -14530,7 +13411,7 @@ Haluatko tallentaa viestin luonnoslaatikkoon? Lisää suosituksena - + Original Message Alkuperäinen viesti @@ -14540,21 +13421,21 @@ Haluatko tallentaa viestin luonnoslaatikkoon? Lähettäjä - + - + To Vastaanottaja - - + + Cc Kopio - + Sent Lähetetyt @@ -14569,7 +13450,7 @@ Haluatko tallentaa viestin luonnoslaatikkoon? %1, %2 kirjoitti: - + Re: Vs: @@ -14579,30 +13460,30 @@ Haluatko tallentaa viestin luonnoslaatikkoon? Vl: - - - + + + RetroShare Retroshare - + Do you want to send the message without a subject ? Haluatko lähettää viestin ilman otsikkoa? - + Please insert at least one recipient. Ole hyvä ja lisää ainakin yksi vastaanottaja. - + Bcc Piilokopio - + Unknown Tuntematon @@ -14717,13 +13598,13 @@ Haluatko tallentaa viestin luonnoslaatikkoon? Tiedot - + Open File... Avaa tiedosto... - + HTML-Files (*.htm *.html);;All Files (*) HTML-tiedostot (*.htm *.html);;Kaikki tiedostot (*) @@ -14743,7 +13624,7 @@ Haluatko tallentaa viestin luonnoslaatikkoon? Vie PDF - + Message has not been Sent. Do you want to save message ? Viestiä ei ole lähetetty. @@ -14765,7 +13646,7 @@ Haluatko tallentaa viestin? Lisää ylimääräinen tiedosto - + Hi,<br>I want to be friends with you on RetroShare.<br> Hei,<br>haluan olla ystäväsi Retrosharessa.<br> @@ -14789,28 +13670,24 @@ Haluatko tallentaa viestin? Warning: This message is too big of %1 characters after HTML conversion. - - You have a friend invite - Sinulle on ystäväkutsu - Respond now: Vastaa nyt: - - + + Close Sulje - + From: Lähettäjä: - + Friend Nodes Ystäväsolmut @@ -14855,13 +13732,13 @@ Haluatko tallentaa viestin? - - + + Thanks, <br> Kiitos, <br> - + Distant identity: Etäinen henkilöllisyys: @@ -14871,12 +13748,12 @@ Haluatko tallentaa viestin? [Puuttuva] - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. Ole hyvä ja luo henkilöllisyys allekirjoittaaksesi etäiset viestit, tai poista etäiset vertaiset kohdeluttelosta. - + Node name & id: Solmun nimi & tunniste: @@ -14954,7 +13831,7 @@ Haluatko tallentaa viestin? Oletus - + A new tab Uudessa välilehdessä @@ -14964,7 +13841,7 @@ Haluatko tallentaa viestin? Uudessa ikkunassa - + Edit Tag Muokkaa merkkausta @@ -14987,7 +13864,7 @@ Haluatko tallentaa viestin? MessageToaster - + Sub: Aih: @@ -14995,7 +13872,7 @@ Haluatko tallentaa viestin? MessageUserNotify - + Message Viesti @@ -15023,7 +13900,7 @@ Haluatko tallentaa viestin? MessageWidget - + Recommended Files Suositellut tiedostot @@ -15033,37 +13910,37 @@ Haluatko tallentaa viestin? Lataa kaikki suositellut tiedostot - + Subject: Aihe: - + From: Lähettäjä: - + To: Vastaanottaja: - + Cc: Kopio: - + Bcc: Piilokopio: - + Tags: Merkkaukset: - + Reply Vastaa @@ -15103,7 +13980,7 @@ Haluatko tallentaa viestin? - + Send Invite Lähetä kutsu @@ -15147,7 +14024,7 @@ Haluatko tallentaa viestin? Buttons Text Beside Icon - + Painikkeet tekstillä kuvakkeen vieressä @@ -15155,7 +14032,7 @@ Haluatko tallentaa viestin? - + Confirm %1 as friend Hyväksy %1 ystäväksesi @@ -15165,12 +14042,12 @@ Haluatko tallentaa viestin? Lisää %1 ystäväksi - + View source - + No subject Ei aihetta @@ -15180,17 +14057,22 @@ Haluatko tallentaa viestin? Lataa - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -15200,21 +14082,23 @@ Haluatko tallentaa viestin? - Send invite? - Lähetä kutsu? + + Show less + - Do you really want send a invite with your Certificate? - Haluatko todella lähettää kutsun varmenteellasi? + + Show more + - + Download all Lataa kaikki - + Print Document Tulosta asiakirja @@ -15229,12 +14113,12 @@ Haluatko tallentaa viestin? HTML-tiedostot (*.htm *.html);;Kaikki tiedostot (*) - + Load images always for this message Lataa kuvat aina tämän viestin osalta - + Hide the attachment pane Piilota liitteet-näkymä @@ -15256,42 +14140,6 @@ Haluatko tallentaa viestin? Compose Kirjoita - - Reply to selected message - Vastaa valittuun viestiin - - - Reply - Vastaa - - - Reply all to selected message - Vastaa kaikkiin valittuihin viesteihin - - - Reply all - Vastaa kaikille - - - Forward selected message - Välitä valittu viesti - - - Forward - Eteenpäin - - - Remove selected message - Poista valittu viesti - - - Delete - Tuhoa - - - Print selected message - Tulosta valittu viesti - Print @@ -15370,7 +14218,7 @@ Haluatko tallentaa viestin? MessagesDialog - + New Message Uusi viesti @@ -15380,60 +14228,16 @@ Haluatko tallentaa viestin? Kirjoita viesti - Reply to selected message - Vastaa valittuun viestiin - - - Reply - Vastaa - - - Reply all to selected message - Vastaa kaikkiin valittuihin viesteihin - - - Reply all - Vastaa kaikille - - - Forward selected message - Välitä valittu viesti - - - Foward - Välitä - - - Remove selected message - Poista valittu viesti - - - Delete - Tuhoa - - - Print selected message - Tulosta valittu viesti - - - Print - Tulosta - - - Display - Näytä - - - + - - + + Tags Merkkaukset - - + + Inbox Saapuneet @@ -15463,21 +14267,17 @@ Haluatko tallentaa viestin? Roskat - + Total Inbox: Saapuneet yhteensä: - Folders - Kansiot - - - + Quick View Pikanäkymä - + Print... Tulosta... @@ -15487,26 +14287,6 @@ Haluatko tallentaa viestin? Print Preview Tulostuksen esikatselu - - Buttons Icon Only - Painikkeet vain kuvakkeilla - - - Buttons Text Beside Icon - Painikkeet tekstillä kuvakkeiden vieressä - - - Buttons with Text - Painikkeet tekstillä - - - Buttons Text Under Icon - Painikkeet tekstillä kuvakkeiden alla - - - Set Text Under Icon - Aseta teksti kuvakkeen alle - Save As... @@ -15528,7 +14308,7 @@ Haluatko tallentaa viestin? Välitä viesti - + Subject Aihe @@ -15538,7 +14318,7 @@ Haluatko tallentaa viestin? Lähettäjä - + Date Päiväys @@ -15548,39 +14328,7 @@ Haluatko tallentaa viestin? Sisältö - Click to sort by attachments - Järjestä liitetiedostojen mukaan - - - Click to sort by subject - Järjestä otsikon mukaan - - - Click to sort by read - Järjestä luettujen mukaan - - - Click to sort by from - Järjestä lähettäjän mukaan - - - Click to sort by date - Järjestä ajan mukaan - - - Click to sort by tags - Järjestä merkkausten mukaan - - - Click to sort by star - Järjestä tähtien mukaan - - - Forward selected Message - Välitä valittu viesti - - - + Search Subject Hae aihetta @@ -15589,6 +14337,11 @@ Haluatko tallentaa viestin? Search From Hae lähettäjää + + + Search To + + Search Date @@ -15615,14 +14368,14 @@ Haluatko tallentaa viestin? Hae liitetiedostoja - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Viestit</h1> <p>Retrosharella on sen oma sisäinen sähköpostijärjestelmä. Voit lähettää/vastaanottaa sähköposteja yhdistetyiltä ystäväsolmuilta.</p> <p>On myös mahdollista lähettää viestejä muiden ihmisten henkilöllisyyksiin käyttäen yleisreititinjärjestelmää. Nämä viestit ovat aina salattuja ja allekirjoitettuja, ja ne välitetään välissä olevien solmujen kautta, kunnes ne saavuttavat lopullisen kohteensa. </p> <p>Etäiset viestit säilyvät sinun Lähtevissä kunnes vastaanottotodistus on saatu.</p> <p>Yleisesti, sinä voit käyttää viestejä suositellaksesi tiedostoja ystävillesi liittäen tiedostolinkkejä, tai suosittelemalla ystäväsolmuja muille ystäväsolmuille, täten vahvistaaksesi omaa verkkoasi, tai antaaksesi palautetta kanavan omistajalle.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + - + Starred - Tähdelliset + @@ -15696,7 +14449,7 @@ Haluatko tallentaa viestin? - Show author in People + Show in People @@ -15710,7 +14463,7 @@ Haluatko tallentaa viestin? - + No message using %1 tag available. @@ -15725,38 +14478,33 @@ Haluatko tallentaa viestin? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts Luonnokset - + No Box selected. - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - Ei tähdellä merkittyjä viestejä. Tähtien avulla voit antaa viesteille erikoisaseman ja helpottaa löytämistä. Antaaksesi viestille tähden, paina vaaleanharmaata tähteä viestin vieressä. - - - No system messages available. - Ei järjestelmäviestejä. - - + To - Vastaanottaja + Vastaanottaja - Click to sort by to - Järjestä vastaanottajan mukaan - - - This message goes to a distant person. - Tämä viesti menee etäisellä henkilölle. - - - + @@ -15764,26 +14512,6 @@ Haluatko tallentaa viestin? Total: Yhteensä: - - Messages - Viestit - - - Click to sort by signature - Järjestä allekirjoituksen mukaan - - - This message was signed and the signature checks - Tämä viesti on allekirjoitettu ja allekirjoitus täsmää - - - This message was signed but the signature doesn't check - Tämä viesti on allekirjoitettu, mutta allekirjoitus ei täsmää - - - This message comes from a distant person. - Tämä viesti tulee etäiseltä henkilöltä. - Mail @@ -15811,7 +14539,17 @@ Haluatko tallentaa viestin? MimeTextEdit - + + Save image + Tallenna kuva + + + + Copy image + + + + Paste as plain text Liitä muokkaamattomana tekstinä @@ -15865,7 +14603,7 @@ Haluatko tallentaa viestin? - + Expand Laajenna @@ -15875,7 +14613,7 @@ Haluatko tallentaa viestin? Poista kohde - + from alkaen @@ -15910,18 +14648,10 @@ Haluatko tallentaa viestin? Odottava viesti - + Hide Piilota - - Send invite? - Lähetä kutsu? - - - Do you really want send a invite with your Certificate? - Haluatko todella lähettää kutsun varmenteellasi? - NATStatus @@ -16059,7 +14789,7 @@ Haluatko tallentaa viestin? Vertaisen tunniste - + Remove unused keys... Poista käyttämättömät avaimet... @@ -16069,7 +14799,7 @@ Haluatko tallentaa viestin? - + Clean keyring Tyhjennä avainnippu @@ -16087,7 +14817,13 @@ Huom.: vanha avainnippusi varmuuskopioidaan. Poisto voi epäonnistua, jos koneessasi on käynnissä useita Retroshareja samanaikaisesti. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info Avainnipun tiedot @@ -16122,18 +14858,13 @@ Avainippusi varmuuskopioitiin tiedostoon ennen poistoa. Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. Tietojen epäjohdonmukaisuus avainnipussa. Tämä on todennäköisesti ohjelmointivirhe. Ota yhteyttä kehittäjiin. - - - Export/create a new node - Vie/luo uusi solmu - Trusted keys only Luotetut avaimet ainoastaan - + Search name Hae nimeä @@ -16143,12 +14874,12 @@ Avainippusi varmuuskopioitiin tiedostoon ennen poistoa. Hae vertaisen tunnistetta - + Profile details... Profiilin tiedot... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -16157,13 +14888,6 @@ Reported error: Raportoitu virhe: - - NetworkPage - - Network - Verkko - - NetworkView @@ -16190,7 +14914,7 @@ Raportoitu virhe: NewFriendList - + Offline Friends @@ -16211,7 +14935,7 @@ Raportoitu virhe: - + Groups Ryhmät @@ -16241,19 +14965,19 @@ Raportoitu virhe: tuo ystäväluettelo mukaan lukien ryhmät - - + + Search Haku - + ID Tunniste - + Search ID @@ -16263,12 +14987,12 @@ Raportoitu virhe: - + Show Items Näytä kohteet - + Last contact @@ -16278,7 +15002,7 @@ Raportoitu virhe: IP - + Group Ryhmä @@ -16393,7 +15117,7 @@ Raportoitu virhe: Kutista kaikki - + Do you want to remove this node? Haluatko poistaa tämän solmun? @@ -16403,7 +15127,7 @@ Raportoitu virhe: Haluatko poistaa tämän ystävän? - + Done! Valmis! @@ -16517,11 +15241,7 @@ ainakin yksi vertainen jäi lisäämättä ryhmään NewsFeed - Log entries - Lokimerkinnät - - - + Activity Stream @@ -16536,11 +15256,7 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Poista kaikki - This is a test. - This is a test. - - - + Newest on top Uusin ylimmäisenä @@ -16550,20 +15266,12 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Vanhin ylimmäisenä - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;News Feed</h1> <p>The Log Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel and Forum posts</li> <li>New Channels and Forums you can subscribe to</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Uutissyöte</h1> <p>Lokisyöte näyttää uusimmat tapahtumat verkostossasi vastaanottohetken mukaan järjestettynä. Näin saat yhteenvedon ystäviesi toiminnasta. Voit määrittää näytettävät tapahtumat <b>Asetuksista</b>. </p> <p>Näytettäviä tapahtumia: <ul> <li>Yhteydenottoyritykset (hyödyllisiä ystävien hankkimiseen ja yhteydenottojen hallintaan)</li> <li>Viestit kanaville ja foorumeille</li> <li>Uudet kanavat ja foorumit, jotka ovat tilattavissasi</li> <li>Yksityisviestit ystäviltäsi</li> </ul> </p> - - - Log - Loki - - - + Activity @@ -16618,10 +15326,6 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Blogs Blogit - - Security - Turvallisuus - @@ -16643,10 +15347,6 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Message Viesti - - Connect attempt - Yhteydenottoyritys - @@ -16663,10 +15363,6 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Ip security IP-tietoturva - - Log - Loki - Friend Connected @@ -16677,10 +15373,6 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Circles Piirit - - Links - Linkit - Activity @@ -16733,14 +15425,6 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Chat rooms Keskusteluhuoneet - - Chat Rooms - Keskusteluhuoneet - - - Case sensitive - Huomioi kirjainkoko - Position @@ -16816,24 +15500,16 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Disable All Toaster temporarily Estä väliaikaisesti kaikki ponnahdusviestit - - Feed - Syöte - Systray Ilmaisinalue - - Count all unread messages - Laske lukemattomat viestit - NotifyQt - + Passphrase required Salasana vaadittu @@ -16853,12 +15529,12 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Väärä salasana! - + Please enter your Retroshare passphrase Anna Retroshare salasanasi: - + Unregistered plugin/executable Rekisteröimätön lisäosa/suoritettava tiedosto @@ -16873,19 +15549,7 @@ ainakin yksi vertainen jäi lisäämättä ryhmään Tarkista järjestelmän kello. - Examining shared files... - Tarkastellaan jaettuja tiedostoja... - - - Hashing file - Luodaan tiivistettä (hash) tiedostolle - - - Saving file index... - Tallennetaan tiedostoluetteloa... - - - + Test Test @@ -16896,17 +15560,19 @@ ainakin yksi vertainen jäi lisäämättä ryhmään + Unknown title Tuntematon otsikko - + + Encrypted message Salattu viesti - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). Keskusteluaulojen toiminnan varmistamiseksi tietokoneesi ajan on oltava oikeassa. Tarkista, että näin on (mahdollinen useiden minuuttien aikasiirtymä havaittiin ystävilläsi). @@ -16914,7 +15580,7 @@ ainakin yksi vertainen jäi lisäämättä ryhmään OnlineToaster - + Friend Online Ystävä linjoilla @@ -16966,10 +15632,6 @@ ainakin yksi vertainen jäi lisäämättä ryhmään PGPKeyDialog - - Dialog - Ikkuna - Profile info @@ -17035,10 +15697,6 @@ ainakin yksi vertainen jäi lisäämättä ryhmään This profile has signed your own profile key Tämä profiili on allekirjoitettu sinun profiiliavaimellasi - - Key signatures : - Avain allekirjoitukset: - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> @@ -17068,23 +15726,20 @@ p, li { white-space: pre-wrap; } PGP-avain - - These options apply to all nodes of the profile: - Nämä vaihtoehdot koskevat kaikkia solmuja profiilissa: + + Friend options + - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> - <html><head/><body><p><span style=" font-size:10pt;">Ystäväsi avaimen allekirjoittamisella ilmaiset luottamuksesi tähän ystävään muille ystävillesi. Se auttaa heitä päättämään salliako yhteydet siitä avaimesta perustuen sinun omaan luottamukseen. Avaimen allekirjoittaminen on täysin vapaaehtoista, eikä sitä voi perua, joten tee niin harkiten.</span></p></body></html> + + These options apply to all nodes of the profile: + Nämä vaihtoehdot koskevat kaikkia solmuja profiilissa: Keysigning: - - Sign PGP key - Allekirjoita PGP-avain - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -17121,12 +15776,7 @@ p, li { white-space: pre-wrap; } Sisällytä allekirjoitukset - - Options - Asetukset - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> <html><head/><body><p align="justify">Retroshare käy ajoittain läpi ystäväluettelosi siirtojasi vastaavien selattavien tiedostojen varalta, jotta voitaisiin muodostaa suora siirtoyhteys. Tällaisessa tapauksessa ystäväsi tietää, että lataat tiedostoa.</p><p align="justify">Estääksesi toiminnan tämän ystävän tapauksessa, poista rasti tästä ruudusta. Voit silti muodostaa suoran siirtoyhteyden halutessasi, esim. lataamalla suoraan ystäväsi tiedostoluettelosta. Tätä asetusta sovelletaan kaikkiin saman solmun sijainteihin.</p></body></html> @@ -17140,10 +15790,6 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this profile (e.g. when the message author is a signed identity that belongs to this profile). This can be used for instance to send files between your own nodes.</p></body></html> - - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> - <html><head/><body><p>Tämä asetus sallii automaattisen suositellun tiedoston latauksen viestistä, joka saapuu tästä solmusta. Tätä voidaan esimerkiksi käyttää tiedostojen lähettämiseen omien solmujesi kesken. Sovelletaan kaikkiin sijainteihin samasta solmusta.</p></body></html> - Auto-download recommended files from this node @@ -17176,21 +15822,21 @@ p, li { white-space: pre-wrap; } kB/s - - + + RetroShare Retroshare - - + + Error : cannot get peer details. Virhe haettaessa vertaisen tietoja. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) Retroshare ei tue antamaasi avainalgoritmia @@ -17211,7 +15857,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. Luottamustaso ilmaisee omaa luottamustasi tähän avaimeen. Ohjelma ei käytä sitä eikä sitä jaeta, mutta se voi olla hyödyllinen hyvien sekä huonojen avainten muistamiseen. @@ -17280,10 +15926,6 @@ Varoitus: Tiedostonsiirto-asetuksissa estit Salli suora latauksen valitsemalla E Check the password! - - Maybe password is wrong - Salasana saattaa olla väärin - You haven't set a trust level for this key. @@ -17291,12 +15933,12 @@ Varoitus: Tiedostonsiirto-asetuksissa estit Salli suora latauksen valitsemalla E - + Retroshare profile Retroshare-profiili - + This is your own PGP key, and it is signed by : Tämä on sinun oma PGP-avain ja sen on allekirjoittanut: @@ -17322,7 +15964,7 @@ Varoitus: Tiedostonsiirto-asetuksissa estit Salli suora latauksen valitsemalla E PeerItem - + Chat Keskustelu @@ -17343,7 +15985,7 @@ Varoitus: Tiedostonsiirto-asetuksissa estit Salli suora latauksen valitsemalla E Poista kohde - + Name: Nimi: @@ -17383,7 +16025,7 @@ Varoitus: Tiedostonsiirto-asetuksissa estit Salli suora latauksen valitsemalla E Aikaero: - + Write Message Kirjoita viesti @@ -17397,10 +16039,6 @@ Varoitus: Tiedostonsiirto-asetuksissa estit Salli suora latauksen valitsemalla E Friend Connected Ystävä yhdistyneenä - - Connect Attempt - Yhteydenottoyritys - Connection refused by peer @@ -17439,17 +16077,13 @@ Varoitus: Tiedostonsiirto-asetuksissa estit Salli suora latauksen valitsemalla E Unknown Tuntematon - - Unknown Peer - Tuntematon vertainen - Hide Piilota - + Send Message Lähetä viesti @@ -17501,10 +16135,6 @@ Varoitus: Tiedostonsiirto-asetuksissa estit Salli suora latauksen valitsemalla E Chat with this person as... Keskustelu henkilön kanssa... - - Send message to this person - Lähetä viesti tälle henkilölle - Invite to Circle @@ -17563,10 +16193,6 @@ Varoitus: Tiedostonsiirto-asetuksissa estit Salli suora latauksen valitsemalla E <html><head/><body><p>Anyone in your contact list will automatically have a positive opinion if not set. This allows to automatically raise reputations of used nodes. </p></body></html> - - automatically give "Positive" opinion to my contacts - anna automaattisesti "Myönteinen" mielipide yhteyshenkilöilleni - use "positive" as the default opinion for contacts (instead of neutral) @@ -17624,13 +16250,6 @@ Varoitus: Tiedostonsiirto-asetuksissa estit Salli suora latauksen valitsemalla E <html><head/><body><p>Poistettujen pannattujen tunnisteiden paluun estämiseksi, koska niitä käytetään esim. foorumeilla tai kanavilla, pannatut henkilöllisyydet pidetään luettelossa jonkin aikaa. Sen jälkeen ne &quot;tyhjennetään&quot; pannattujen luettelosta ja ladataan uudestaan pannattomiksi, jos niitä käytetään foorumeille, keskusteluhuoneissa jne.</p></body></html> - - PhotoCommentItem - - Form - Lomake - - PhotoDialog @@ -17638,23 +16257,11 @@ Varoitus: Tiedostonsiirto-asetuksissa estit Salli suora latauksen valitsemalla E PhotoShare PhotoShare - - Photo - Valokuva - TextLabel TekstiMerkki - - Comment - Kommentti - - - Summary - Yhteenveto - Album / Photo Name @@ -17715,14 +16322,6 @@ Varoitus: Tiedostonsiirto-asetuksissa estit Salli suora latauksen valitsemalla E ... ... - - Add Comment - Lisää kommentti - - - Write a comment... - Kirjoita kommentti... - Album @@ -17793,10 +16392,6 @@ p, li { white-space: pre-wrap; } Create Album Luo albumi - - View Album - Näytä albumi - Edit Album Details @@ -17818,17 +16413,17 @@ p, li { white-space: pre-wrap; } Diaesitys - + My Albums Albumini - + Subscribed Albums Tilatut albumit - + Shared Albums Jaetut albumit @@ -17858,7 +16453,7 @@ yrität muokata sitä! PhotoSlideShow - + Album Name Albumin nimi @@ -17917,19 +16512,19 @@ yrität muokata sitä! - - + + TextLabel - + Posted by - + ago @@ -17965,12 +16560,12 @@ yrität muokata sitä! PluginItem - + TextLabel TekstiMerkki - + Show more details about this plugin Näytä lisätietoja lisäosasta @@ -18116,56 +16711,6 @@ p, li { white-space: pre-wrap; } Plugin look-up directories Lisäosien hakemistot - - Plugin disabled. Click the enable button and restart Retroshare - Lisäosa on estetty. Napsauta salli-painiketta ja käynnistä Retroshare uudestaan. - - - [disabled] - [estetty] - - - No API number supplied. Please read plugin development manual. - API-numeroa ei annettu. Ole hyvä ja lue ohje lisäosien kehittämisestä. - - - [loading problem] - [latausongelma] - - - No SVN number supplied. Please read plugin development manual. - SVN-numeroa ei annettu. Ole hyvä ja lue ohje lisäosien kehittämisestä. - - - Loading error. - Virhe ladattaessa. - - - Missing symbol. Wrong version? - Puuttuva merkki. Väärä versio? - - - No plugin object - Ei lisäosaobjektia - - - Plugins is loaded. - Lisäosat ladattu. - - - Unknown status. - Tila tuntematon. - - - Check this for developing plugins. They will not -be checked for the hash. However, in normal -times, checking the hash protects you from -malicious behavior of crafted plugins. - Rastita tämä lisäosien kehittämisen yhteydessä. Tiivistettä (hash) -ei tällöin tarkasteta. Tavanomaisessa käytössä -tiivisteen tarkistaminen suojelee sinua -vahingoittamistarkoituksessa tehdyiltä lisäosilta. - Plugins @@ -18235,12 +16780,27 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Aseta ikkuna päällimmäiseksi - + + Ban this person (Sets negative opinion) + Estä tämä henkilö (antaa kielteisen mielipiteen) + + + + Give neutral opinion + Anna neutraali mielipide + + + + Give positive opinion + Anna myönteinen mielipide + + + Choose window color... - + Dock window @@ -18274,22 +16834,6 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Close conversation? - - The person you are talking to has deleted the secured chat tunnel. - Henkilö, jonka kanssa puhut on poistanut suojatun keskustelutunnelin. - - - The chat partner deleted the secure tunnel, messages will be delivered as soon as possible - Keskustelukumppani on poistanut suojatun tunnelin, viestit toimitetaan mahdollisimman pian. - - - Closing this window will end the conversation, notify the peer and remove the encrypted tunnel. - Tämän ikkunan sulkeminen lopettaa keskustelun, ilmoittaa vertaiselle ja poistaa salatun tunnelin. - - - Kill the tunnel? - Suljetaanko tunneli? - PostedCardView @@ -18309,7 +16853,7 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Uusi - + Vote up Äänestä ylös @@ -18329,8 +16873,8 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. \/ - - + + Comments Kommentit @@ -18355,13 +16899,13 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. - - + + Comment Kommentti - + Comments Kommentit @@ -18389,20 +16933,12 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. PostedCreatePostDialog - Signed by: - Allekirjoitettu: - - - Notes - Huomiot - - - + Create a new Post - + RetroShare Retroshare @@ -18417,12 +16953,22 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File Lataa kuvatiedosto - + Post image @@ -18438,7 +16984,17 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -18448,23 +17004,7 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. - Submit Post - Lähetä viesti - - - You are submitting a link. The key to a successful submission is interesting content and a descriptive title. - Olet lähettämässä linkkiä. Lähettämässäsi linkissä tulisi mielellään olla mielenkiintoista sisältöä ja kuvaava otsikko. - - - Submit - Lähetä - - - Submit a new Post - Lähetä uusi viesti - - - + Please add a Title Ole hyvä ja lisää otsikko @@ -18484,12 +17024,22 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -18504,7 +17054,7 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Lähetä - + Post @@ -18515,7 +17065,7 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Kuva - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -18525,7 +17075,7 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Otsikko - + Link Linkki @@ -18533,44 +17083,12 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. PostedDialog - Posted Links - Lähetetyt linkit - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Posted</h1> <p>The posted service allows you to share internet links, that spread among Retroshare nodes like forums and channels</p> <p>Links can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Posted links are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Lähetetyt</h1> <p>Lähetetyt-palvelu sallii sinun jakaa internet-linkkejä, jotka leviävät Retroshare-solmuihin kuten foorumeille ja kanaville</p> <p>Tilaavat käyttäjät voivat kommentoida linkkejä. Edistämisjärjestelmä mahdollistaa tärkeiden linkkien korostamisen.</p> <p>Linkkien jakamisessa ei ole mitään rajoituksia, joten ole siis varovainen niitä avatessasi.</p> <p>Lähetetyt linkit pidetään %1 päivän ajan, ja ajantasaistetaan viimeisten %2 päivän ajan, ellet muuta tätä.</p> - - - Create Topic - Luo aihe - - - My Topics - Aiheeni - - - Subscribed Topics - Tilatut viestiketjut - - - Popular Topics - Suositut viestiketjut - - - Other Topics - Muut viestiketjut - - - Links - Linkit - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -18604,31 +17122,7 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. PostedGroupDialog - Posted Topic - Lähetetyn Aihe - - - Add Topic Admins - Lisää viestiketjujen ylläpitäjiä - - - Select Topic Admins - Valitse viestiketjujen ylläpitäjiä - - - Create New Topic - Luo uusi aihe - - - Edit Topic - Muokkaa aihetta - - - Update Topic - Päivitä aihe - - - + Create New Board @@ -18666,7 +17160,17 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted Tilaa Lähetetyt @@ -18682,7 +17186,7 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. - + Expand Laajenna @@ -18697,24 +17201,17 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. - Posted Description - Lähetetyn kuvaus - - - Loading - Ladataan - - - New Posted - Uudet Lähetetyt - - - + Loading... - + + Never + Ei koskaan + + + New Board @@ -18727,22 +17224,18 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. PostedItem - + 0 0 - Site - Sivusto - - - - + + Comments Kommentit - + Copy RetroShare Link Kopioi Retroshare-linkki @@ -18753,12 +17246,12 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. - + Comment Kommentti - + Comments Kommentit @@ -18768,7 +17261,7 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. <p><font color="#ff0000"><b>Tämän viestin kirjoittaja (tunnisteella %1) on pannassa.</b> - + Click to view Picture @@ -18778,21 +17271,17 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Piilota - + Vote up Äänestä ylös - + Vote down Äänestä alas - \/ - \/ - - - + Set as read and remove item Merkitse luetuksi ja poista kohde @@ -18802,7 +17291,7 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Uusi - + New Comment: Uusi kommentti: @@ -18812,7 +17301,7 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Kommentin arvo - + Name Nimi @@ -18853,77 +17342,10 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. - + Loading Ladataan - - By - Käyttäjältä - - - - PostedListWidget - - Form - Lomake - - - Hot - Suosittu - - - New - Uusi - - - Top - Ylimmäiseksi - - - Today - Tänään - - - Yesterday - Eilen - - - This Week - Tällä viikolla - - - This Month - Tässä kuussa - - - This Year - Tänä vuonna - - - Submit a new Post - Lähetä uusi viesti - - - Next - Seur. - - - RetroShare - Retroshare - - - Please create or choose a Signing Id before Voting - Luo tai valitse allekirjoitustunniste ennen äänestämistä - - - Previous - Edellinen - - - 1-10 - 1-10 - PostedListWidgetWithModel @@ -18943,7 +17365,17 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -18953,15 +17385,15 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Ylläpitäjä: - + - + unknown tuntematon - + Distribution: Jakelu: @@ -18971,42 +17403,42 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts Viestejä - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -19026,7 +17458,7 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Suosittu - + Search Haku @@ -19056,17 +17488,17 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -19081,12 +17513,17 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Tyhjä - + Copy RetroShare Link Kopioi Retroshare-linkki - + + Copy http Link + + + + Show author in People tab @@ -19096,27 +17533,31 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Muokkaa - + + information tietoa - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -19131,7 +17572,7 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Aloita tilaus - + Never Ei koskaan @@ -19205,6 +17646,16 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. No Channel Selected Ei kanavaa valittuna + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -19213,14 +17664,6 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Tabs Välilehdet - - Open each topic in a new tab - Avaa jokainen aihe uuteen välilehteen - - - Links - Linkit - Open each board in a new tab @@ -19234,10 +17677,6 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. PostedUserNotify - - Posted - Lähetetty - Board Post @@ -19306,16 +17745,16 @@ vahingoittamistarkoituksessa tehdyiltä lisäosilta. Profiilin hallinta - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -19427,7 +17866,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen ProfileWidget - + Edit status message Muokkaa tilaviestiä @@ -19443,7 +17882,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen Profiilin hallinta - + Public Information Julkiset tiedot @@ -19478,12 +17917,12 @@ ja käyttää "Tuo"-painiketta ladataksesi sen Linjoilla alkaen: - + Other Information Muita tietoja - + My Address Osoitteeni @@ -19527,51 +17966,27 @@ ja käyttää "Tuo"-painiketta ladataksesi sen PulseAddDialog - Post From: - Lähettäjä - - - Account 1 - Tili 1 - - - Account 2 - Tili 2 - - - Account 3 - Tili 3 - - - + Add to Pulse Lisää pulssiin - filter - suodata - - - URL Adder - Linkin lisääjä - - - + Display As Näytä muodossa - + URL URL - + GroupLabel - + IDLabel @@ -19581,12 +17996,12 @@ ja käyttää "Tuo"-painiketta ladataksesi sen Lähettäjä: - + Head - + Head Shot @@ -19616,13 +18031,13 @@ ja käyttää "Tuo"-painiketta ladataksesi sen Kielteinen - - + + Whats happening? - + @@ -19634,12 +18049,22 @@ ja käyttää "Tuo"-painiketta ladataksesi sen - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -19648,17 +18073,13 @@ ja käyttää "Tuo"-painiketta ladataksesi sen Cancel Peru - - Post Pulse to Wire - Lähetä pulssi lennättimeen - Post - + Reply to Pulse @@ -19673,34 +18094,24 @@ ja käyttää "Tuo"-painiketta ladataksesi sen - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - Lähettäjä - - - Date - Päiväys - - - ... - ... + + Load Picture File + Lataa kuvatiedosto @@ -19711,7 +18122,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen Lomake - + @@ -19730,7 +18141,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen PulseReply - + icn @@ -19740,7 +18151,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen - + REPLY @@ -19767,7 +18178,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen - + FOLLOW @@ -19777,7 +18188,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -19797,7 +18208,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -19913,7 +18324,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen - + FOLLOW @@ -19921,37 +18332,42 @@ ja käyttää "Tuo"-painiketta ladataksesi sen PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -19983,7 +18399,7 @@ ja käyttää "Tuo"-painiketta ladataksesi sen - + FOLLOW @@ -19991,8 +18407,8 @@ ja käyttää "Tuo"-painiketta ladataksesi sen QObject - - + + Confirmation Vahvistus @@ -20263,12 +18679,12 @@ Merkit <b>",|,/,\,&lt;,&gt;,*,?</b> korvataan merkillä Vertaisen tiedot - + File Request canceled Tiedostopyyntö peruttu - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. Tämä Retrosharen versio käyttää OpenPGP-SDK:ta. Tämän takia se ei käytä järjestelmäjaettua PGP-avainketjua, vaan sillä on oma avainketjunsa jaettuna kaikkien käynnissä olevien Retrosharejen kanssa.<br><br>Sinulla ei näytä olevan tällaista avainketjua, vaikka olemassaolevissa Retroshare-tileissä mainitaan PGP-avaimet. Tämä johtuu todennäköisesti siitä, että siirryit juuri ohjelman uudempaan versioon. @@ -20299,7 +18715,7 @@ Merkit <b>",|,/,\,&lt;,&gt;,*,?</b> korvataan merkillä Odottamaton virhe. Ole hyvä ja raportoi 'RsInit::InitRetroShare unexpected return code %1'. - + Cannot start Tor Manager! @@ -20335,7 +18751,7 @@ The error reported is:" Piilotetun palvelun käynnistäminen ei ollut mahdollista. - + Multiple instances Useita instansseja @@ -20358,6 +18774,26 @@ Lukitustiedosto: Lukitustiedosto: + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -20378,14 +18814,6 @@ Lukitustiedosto: End-to-end encrypted conversation established - - Tunnel is pending... Messages will be delivered as soon as possible - Tunneli odottaa...Viestit toimitetaan mahdollisimman pian - - - Secured tunnel is working. Messages are delivered immediately! - Suojattu tunneli toimii. Viestit toimitetaan välittömästi! - The collection file %1 could not be opened. @@ -20448,7 +18876,7 @@ Virhe: Datan lähetys - + You appear to have nodes associated to DSA keys: Sinulla näyttäisi olevan solmuja kytkettynä DSA-avaimiin: @@ -20458,7 +18886,7 @@ Virhe: Retroshare ei tällä hetkellä tue DSA-avaimia. Et voi käyttää näitä solmuja. Olemme pahoillamme. - + enabled käytössä @@ -20468,7 +18896,7 @@ Virhe: estetty - + Move IP %1 to whitelist Lisää IP %1 sallittujen luetteloon @@ -20484,7 +18912,7 @@ Virhe: - + %1 seconds ago %1 sekuntia sitten @@ -20552,7 +18980,7 @@ Security: no anonymous IDs Tietoturva: ei nimettömiä tunnisteita - + Join chat room Liity keskusteluhuoneeseen @@ -20580,7 +19008,7 @@ Tietoturva: ei nimettömiä tunnisteita XML-tiedoston jäsentäminen epäonnistui! - + Indefinitely Toistaiseksi @@ -20760,13 +19188,29 @@ Tietoturva: ei nimettömiä tunnisteita Ban list + + + Name + Nimi + + Node + Solmu + + + + Address + Osoite + + + + Status Tila - + NXS @@ -20959,10 +19403,6 @@ Tietoturva: ei nimettömiä tunnisteita Click to resume the hashing process Napsauta jatkaaksesi tiivisteen laskentaa - - <p>This certificate contains: - <p>Tämä varmenne sisältää: - Idle @@ -21013,6 +19453,18 @@ Tietoturva: ei nimettömiä tunnisteita Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -21175,7 +19627,7 @@ p, li { white-space: pre-wrap; } - + Network Wide Verkon laajuinen @@ -21358,7 +19810,7 @@ p, li { white-space: pre-wrap; } Lomake - + The loading of embedded images is blocked. Upotettujen kuvien lataaminen on estetty. @@ -21371,7 +19823,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default Sallittu oletuksena @@ -21544,12 +19996,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + Tallenna kuva + + + + Copy image + + + + Document source @@ -21557,12 +20019,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -21592,14 +20054,6 @@ p, li { white-space: pre-wrap; } Show column … - - Show column... - Näytä sarake... - - - [no title] - [ei otsikkoa] - RatesStatus @@ -22262,7 +20716,7 @@ Jos se on mielestäsi kunnollinen, poista mainittu rivi tiedostosta ja avaa se u RsDownloadListModel - + Name i.e: file name Nimi @@ -22383,7 +20837,7 @@ Jos se on mielestäsi kunnollinen, poista mainittu rivi tiedostosta ja avaa se u RsFriendListModel - + Name Nimi @@ -22403,7 +20857,7 @@ Jos se on mielestäsi kunnollinen, poista mainittu rivi tiedostosta ja avaa se u IP - + Profile ID @@ -22462,7 +20916,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Viesti tullaan välittämään ystävillesi. - + [ ... Redacted message ... ] [ ... Muokattu viesti ... ] @@ -22476,11 +20930,6 @@ estää viestin lähettämisen eteenpäin ystävillesi. [Unknown] [Tuntematon] - - - [ ... Missing Message ... ] - [ ... Puuttuva viesti ... ] - RsMessageModel @@ -22494,6 +20943,11 @@ estää viestin lähettämisen eteenpäin ystävillesi. From Lähettäjä + + + To + Vastaanottaja + Subject @@ -22516,13 +20970,18 @@ estää viestin lähettämisen eteenpäin ystävillesi. - Click to sort by read - Järjestä luettujen mukaan + Click to sort by read status + - Click to sort by from - Järjestä lähettäjän mukaan + Click to sort by author + + + + + Click to sort by destination + @@ -22545,7 +21004,9 @@ estää viestin lähettämisen eteenpäin ystävillesi. - + + + [Notification] @@ -22566,7 +21027,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Rshare - + Resets ALL stored RetroShare settings. Palauttaa KAIKKI tallennetut Retrosharen asetukset. @@ -22627,7 +21088,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Asettaa Retrosharen kielen. - + Unable to open log file '%1': %2 Lokitiedoston '%1': %2 avaaminen epäonnistui @@ -22648,11 +21109,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Datahakemistoa ei voitu luoda: %1 - Revision - Tarkistus - - - + opmode käyttötapa @@ -22682,7 +21139,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Retrosharen graafisen käyttöliittymän käyttötiedot - + Invalid language code specified: Virheellinen kielikoodi määritelty: @@ -22700,7 +21157,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. RshareSettings - + Registry Access Error. Maybe you need Administrator right. Rekisterin käyttövirhe. Tarvitset ehkä Järjestelmänvalvojan oikeudet. @@ -22717,12 +21174,12 @@ estää viestin lähettämisen eteenpäin ystävillesi. SearchDialog - + Enter a keyword here (at least 3 char long) Anna hakusana (vähintään 3 merkkiä) - + Start Search Aloita haku @@ -22784,7 +21241,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Tyhjennä - + KeyWords Hakusanat @@ -22799,7 +21256,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Hakutunniste - + Filename Tiedostonimi @@ -22899,23 +21356,23 @@ estää viestin lähettämisen eteenpäin ystävillesi. Lataa valitut - + File Name Tiedoston nimi - + Download Lataa - + Copy RetroShare Link Kopioi Retroshare-linkki - + Send RetroShare Link Lähetä Retroshare-linkki @@ -22925,7 +21382,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. - + Download Notice Lataushuomautus @@ -22962,7 +21419,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Poista kaikki - + Folder Kansio @@ -22973,17 +21430,17 @@ estää viestin lähettämisen eteenpäin ystävillesi. - + New RetroShare Link(s) Uusi Retroshare-linkki/-linkit - + Open Folder Avaa kansio - + Create Collection... Luo kokoelma... @@ -23003,7 +21460,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Lataa kokoelmatiedostosta... - + Collection Kokoelma @@ -23011,7 +21468,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. SecurityIpItem - + Peer details Vertaisen tiedot @@ -23027,22 +21484,22 @@ estää viestin lähettämisen eteenpäin ystävillesi. Poista kohde - + IP address: IP-osoite: - + Peer ID: Vertaisen tunniste: - + Location: Sijainti: - + Peer Name: Vertaisen nimi: @@ -23059,7 +21516,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Piilota - + but reported: mutta raportoitu: @@ -23084,8 +21541,8 @@ estää viestin lähettämisen eteenpäin ystävillesi. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -23093,7 +21550,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. SecurityItem - + wants to be friend with you on RetroShare haluaa olla ystäväsi Retrosharessa @@ -23124,7 +21581,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. - + Expand Laajenna @@ -23169,12 +21626,12 @@ estää viestin lähettämisen eteenpäin ystävillesi. Tila: - + Write Message Kirjoita viesti - + Connect Attempt Yhteydenottoyritys @@ -23194,17 +21651,22 @@ estää viestin lähettämisen eteenpäin ystävillesi. Tuntematon (lähtevä) yhteydenottoyritys - + Unknown Security Issue Tuntematon tietoturvaongelma - - A unknown peer + + SSL request - + + An unknown peer + + + + Unknown Tuntematon @@ -23214,11 +21676,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. - Unknown Peer - Tuntematon vertainen - - - + Hide Piilota @@ -23228,7 +21686,7 @@ estää viestin lähettämisen eteenpäin ystävillesi. Haluatko poistaa tämän ystävän? - + Certificate has wrong signature!! This peer is not who he claims to be. Varmenteella on väärä allekirjoitus! Vertainen ei ole se, joka hän väittää olevansa. @@ -23238,12 +21696,12 @@ estää viestin lähettämisen eteenpäin ystävillesi. Puuttuva/vioittunut SSL-varmenne. Ei todellinen Retrosharen käyttäjä. - + Certificate caused an internal error. Varmenne aiheutti sisäisen virheen. - + Peer/node not in friendlist (PGP id= Vertainen/solmu ei ole ystäväluettelossa (PGP tunniste= @@ -23302,12 +21760,12 @@ estää viestin lähettämisen eteenpäin ystävillesi. - + Local Address Paikallinen osoite - + NAT NAT @@ -23328,22 +21786,22 @@ estää viestin lähettämisen eteenpäin ystävillesi. Portti: - + Local network Paikallinen verkko - + External ip address finder Ulkoisen IP-osoitteen paikallistaminen - + UPnP UPnP - + Known / Previous IPs: Tunnetut / aiemmat IP:t: @@ -23359,21 +21817,16 @@ jättäminen päälle helpottaa yhteydenottoa, kun sinulla on vähän ystäviä. Tämä auttaa myös, jos olet palomuurin tai VPN:n takana. - - Allow RetroShare to ask my ip to these websites: - Salli Retrosharen kysyä IP:täni näiltä verkkosivuilta: - - - - - + + + kB/s kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. Hyväksyttävä porttiavaruus on välillä 10-65535. Porttia 1024 pienemmät ovat yleensä järjestelmäsi käyttöön varattuja. @@ -23383,23 +21836,46 @@ vähän ystäviä. Tämä auttaa myös, jos olet palomuurin tai VPN:n takana.Hyväksyttävä porttiavaruus on välillä 10-65535. Porttia 1024 pienemmät ovat yleensä järjestelmäsi käyttöön varattuja. - + Onion Address Onion-osoite - + Discovery On (recommended) Etsintä käytössä (suositus) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. Tor on Retrosharen automaattisesti määrittelemä. Sinun ei pitäisi tarvita muuttaa mitään tässä. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off Etsintä ei käytössä @@ -23409,7 +21885,7 @@ vähän ystäviä. Tämä auttaa myös, jos olet palomuurin tai VPN:n takana.Piilotettu - Katso asetukset - + I2P Address I2P-osoite @@ -23434,41 +21910,95 @@ vähän ystäviä. Tämä auttaa myös, jos olet palomuurin tai VPN:n takana.saapuva ok - - + + + Proxy seems to work. Välityspalvelin näyttää toimivan. - + + I2P proxy is not enabled I2P-välityspalvelin ei ole käytössä - - BOB is running and accessible - BOB on käynnissä ja saatavilla + + SAMv3 is running and accessible + - BOB is not accessible! Is it running? - BOB ei ole saatavilla! Onko se käynnissä? + SAMv3 is not accessible! Is i2p running and SAM enabled? + - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - Retroshare käyttää BOB:a määrittääkseen %1 -tunnelin %2:%3 (nimetty %4) - -Kun muutat asetuksia (esim. porttia) käytä painikkeita alhaalla käynnistääksesi uudelleen BOB:n. - - + - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client asiakas @@ -23483,73 +22013,7 @@ Kun muutat asetuksia (esim. porttia) käytä painikkeita alhaalla käynnistääk tuntematon - - - - BOB is processing a request - BOB käsittelee pyyntöä - - - - connectivity check - yhteys tarkistus - - - - generating key - luodaan avainta - - - - starting up - käynnistyy - - - - shuting down - suljetaan - - - - BOB is processing a request: %1 - BOB käsittelee pyyntöä: %1 - - - - BOB is broken - - BOB on rikki - - - - - BOB encountered an error: - - BOB virhe tapahtui: - - - - - BOB tunnel is running - BOB-tunneli on käynnissä - - - - BOB is working fine: tunnel established - BOB toimii hyvin: tunneli toiminnassa - - - - BOB tunnel is not running - BOB-tunneli ei ole käynnissä - - - - BOB is inactive: tunnel closed - BOB on toimeton: tunneli suljettu - - - + request a new server key pyydä uutta palvelin-avainta @@ -23559,22 +22023,7 @@ Kun muutat asetuksia (esim. porttia) käytä painikkeita alhaalla käynnistääk lataa palvelin avain base64:sta - - stop BOB tunnel first to generate a new key - pysäytä ensiksi BOB-tunneli luodaksesi uuden avaimen - - - - stop BOB tunnel first to load a key - pysäytä ensiksi BOB-tunneli ladataksesi avaimen - - - - stop BOB tunnel first to disable BOB - pysäytä ensiksi BOB-tunneli kytkeäksesi BOB:n pois päältä - - - + You are reachable through the hidden service. Olet tavoitettavissa piilotetun palvelun kautta. @@ -23588,12 +22037,12 @@ Ovatko kaikki palvelut päällä ja käynnissä?? Tarkista myös porttisi! - + [Hidden mode] [Piilotettu tila] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -23603,7 +22052,7 @@ Tarkista myös porttisi! Tyhjennä - + Download limit (KB/s) Latausraja (KB/s) @@ -23618,23 +22067,23 @@ Tarkista myös porttisi! Lähetysraja (KB/s) - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> <html><head/><body><p>Lähetysrajoitus käsittää koko ohjelman. Liian alhainen rajoitus voi lopulta estää alhaisen prioriteetin palvelut (foorumit, kanavat) Suositeltu vähimmäisarvo on 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -23651,17 +22100,7 @@ Kirjoita nyt osoite (esim. 127.0.0.1) ja portti, jonka valitsit aiemmin I2P-väl Voit nyt yhdistää Piilotettuihin solmuihin, ja vaikka käytössäsi olisi normaali Solmu, miksi et määrittäisi Tor ja/tai I2P? - - Automatic I2P/BOB - Automaattinen I2P/BOB - - - - Enable I2P BOB - changing this requires a restart to fully take effect - Salli I2P BOB - vaatii uudelleenkäynnistyksen toimiakseen - - - + enableds advanced settings sallii lisäasetukset @@ -23671,12 +22110,7 @@ Voit nyt yhdistää Piilotettuihin solmuihin, ja vaikka käytössäsi olisi norm edistynyt tila - - I2P Basic Open Bridge - - - - + I2P Instance address I2P-instanssiosoite @@ -23686,17 +22120,7 @@ Voit nyt yhdistää Piilotettuihin solmuihin, ja vaikka käytössäsi olisi norm 127.0.0.1 - - I2P proxy port - I2P-välityspalvelinportti - - - - BOB accessible - BOB saatavissa - - - + Address Osoite @@ -23736,7 +22160,7 @@ Voit nyt yhdistää Piilotettuihin solmuihin, ja vaikka käytössäsi olisi norm lataa avain - + Start Käynnistä @@ -23751,12 +22175,7 @@ Voit nyt yhdistää Piilotettuihin solmuihin, ja vaikka käytössäsi olisi norm Pysäytä - - BOB status - BOB-tila - - - + Incoming Saapuva @@ -23803,7 +22222,32 @@ Lopuksi varmista, että portit vastaavat asetuksia. Jos sinulla on ongelmia yhteydenluonnissa Tor-verkkoon, tarkista myös Tor-lokisi.. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay Välitys @@ -23858,7 +22302,7 @@ Jos sinulla on ongelmia yhteydenluonnissa Tor-verkkoon, tarkista myös Tor-lokis Yhteensä: - + Warning: This bandwidth adds up to the max bandwidth. @@ -23883,7 +22327,7 @@ Jos sinulla on ongelmia yhteydenluonnissa Tor-verkkoon, tarkista myös Tor-lokis Poista palvelin - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -23897,7 +22341,7 @@ Jos sinulla on ongelmia yhteydenluonnissa Tor-verkkoon, tarkista myös Tor-lokis Verkko - + IP Filters IP-suodattimet @@ -23920,7 +22364,7 @@ Jos sinulla on ongelmia yhteydenluonnissa Tor-verkkoon, tarkista myös Tor-lokis - + Status Tila @@ -23980,17 +22424,28 @@ Jos sinulla on ongelmia yhteydenluonnissa Tor-verkkoon, tarkista myös Tor-lokis Lisää sallittujen luetteloon - + Hidden Service Configuration Piilotetun palvelun asetukset - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>Tämä on Tor SOCKS-välityspalvelimen portti. Retroshare-solmusi voi käyttää tätä porttia yhdistääkseen</p><p>Piilotettuihin solmuihin. Tämä valo oikealla muuttuu vihreäksi, kun portti on käytössä tietokoneellasi. </p><p>Tämä ei kuitenkaan tarkoita sitä, että Retroshare-liikenteesi siirtyy Tor:n kautta. Näin tapahtuu ainoastaan, jos </p><p>sinä itse yhdistät Piilotettuihin solmuihin, tai käytät Piilotettua solmua itse.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -24006,18 +22461,18 @@ Jos sinulla on ongelmia yhteydenluonnissa Tor-verkkoon, tarkista myös Tor-lokis - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay I2P lähtevä ok - + Service Address Palvelun osoite @@ -24052,12 +22507,12 @@ Jos sinulla on ongelmia yhteydenluonnissa Tor-verkkoon, tarkista myös Tor-lokis Täytä palveluosoite - + IP Range IP-avaruus - + Reported by DHT for IP masquerading DHT raportoi IP:n naamioinnista @@ -24080,22 +22535,22 @@ Jos sinulla on ongelmia yhteydenluonnissa Tor-verkkoon, tarkista myös Tor-lokis Sinun lisäämäsi - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> <html><head/><body><p>Sallitut IP:t kerätään seuraavista lähteistä: käsin vaihdettuihin varmenteisiin sisältyvät IP:t, tässä ikkunassa lisäämäsi tai tietoturvasyötteen nimikkeistä poimimasi IP-alueet.</p><p>Oletuksena Retroshare (1) sallii aina yhteyden sallittujen luettelossa oleviin vertaisiin, myös IP-osoitteen ollessa estettyjen luettelossa; (2) valinnaisesti vaatii, että IP:t sisältyvät sallittujen luetteloon. Voit muuttaa toimintaa vertaiskohtaisesti jokaisen Retroshare-solmun &quot;Tiedot&quot;-ikkunassa.</p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> <html><head/><body><p>DHT sallii sinun vastata ystäviesi yhteyspyyntöihin käyttäen BitTorrentin DHT:tä. Se parantaa yhteydenpitoa huomattavasti. DHT:lle ei kuitenkaan tallenneta mitään tietoa. Sitä käytetään ainoastaan välityspalvelin-järjestelmänä yhteydenmuodostamisessa muihin Retroshare-solmuihin.</p><p>Etsintä-palvelu lähettää solmun nimen ja luotetuttujen kontaktien tunnisteet yhdistetyille vertaisille, auttaen heitä valitsemaan uusia ystäviä. Ystävyys ei kuitenkaan ole milloinkaan automaattista ja molempien vertaisten pitää luottaa toisiinsa salliakseen yhteyden. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> <html><head/><body><p>Tämä tilailmaisin muuttuu vihreäksi heti, kun Retroshare onnistuu saamaan sinun oman IP:si alla olevilta verkkosivuilta, jos olet sallinut sen toiminnon. Retroshare yrittää myös saada muilla tavoin selville oman IP:si.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> <html><head/><body><p>Luettelo täyttyy automaattisesti useista lähteistä kerätyn tiedon perusteella: DHT:n raportoimat naamioituneet vertaiset, ystäviesi raportoimat ja itse antamasi IP-avaruudet.</p><p>Naamioituneiden IP-osoitteiden automaattinen arvaaminen saattaa viedä ystäväsi estettyjen luetteloon. Tällaisissa tapauksissa voit käyttää pikavalikkoa lisätäksesi heidät sallittuihin.</p></body></html> @@ -24130,26 +22585,22 @@ Jos sinulla on ongelmia yhteydenluonnissa Tor-verkkoon, tarkista myös Tor-lokis Automaattisesti aseta pannaan DHT:n naamioivat IP:t alkaen - + Outgoing Manual Tor/I2P - - <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. <br/>If you prefer to use BOB to automatically manage I2P check the other tab.</p></body></html> - <html><head/><body><p>Määritä Tor and I2P SOCKS-välityspalvelin tässä. <br/>Jos käytät mieluummin BOB:a automaattisesti hallitaksesi I2P tarkista toinen välilehti.</p></body></html> - Tor Socks Proxy Tor SOCKS-välityspalvelin - + Tor outgoing Okay Tor lähtevä ok - + Tor proxy is not enabled Tor-välityspalvelin ei ole käytössä @@ -24229,7 +22680,7 @@ Jos sinulla on ongelmia yhteydenluonnissa Tor-verkkoon, tarkista myös Tor-lokis ShareKey - + check peers you would like to share private publish key with rastita vertaiset, joiden kanssa haluat jakaa yksityisen julkaisuavaimesi @@ -24239,12 +22690,12 @@ Jos sinulla on ongelmia yhteydenluonnissa Tor-verkkoon, tarkista myös Tor-lokis Jaa ystävälle - + Share Jaa - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -24263,7 +22714,7 @@ Select the Friends with which you want to Share your Channel. Jaettujen kansioiden hallinta - + Shared directory Jaettu hakemisto @@ -24283,17 +22734,17 @@ Select the Friends with which you want to Share your Channel. Näkyvyys - + Add new Lisää uusi - + Cancel Peruuta - + Add a Share Directory Lisää jaettava hakemisto @@ -24303,7 +22754,7 @@ Select the Friends with which you want to Share your Channel. Poista - + Apply and close Käytä ja sulje @@ -24394,7 +22845,7 @@ Select the Friends with which you want to Share your Channel. Hakemistoa ei löydy tai nimeä ei hyväksytty. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. Tämä on luettelo jaetuista kansioista. Voit lisätä ja poistaa kansioita alareunan painikkeiden avulla. Kun lisäät uuden kansion, aluksi kaikki kyseisen kansion tiedostot jaetaan. Voit erikseen määritellä jakomerkkejä kullekin jaetulle kansiolle. @@ -24402,7 +22853,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files Tiedostot @@ -24453,11 +22904,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files tarkista tiedostot - + Download selected Lataa valitut @@ -24467,7 +22923,7 @@ Select the Friends with which you want to Share your Channel. Lataa - + Copy retroshare Links to Clipboard Kopioi Retroshare-linkit leikepöydälle @@ -24482,7 +22938,7 @@ Select the Friends with which you want to Share your Channel. Lähetä Retroshare-linkit - + Some files have been omitted Jotkin tiedostot on jätetty pois @@ -24498,7 +22954,7 @@ Select the Friends with which you want to Share your Channel. Suositukset - + Create Collection... Luo kokoelma... @@ -24523,7 +22979,7 @@ Select the Friends with which you want to Share your Channel. Lataa kokoelmatiedostosta... - + Some files have been omitted because they have not been indexed yet. Jotkin tiedostot on jätetty pois koska niitä ei ole luetteloitu vielä. @@ -24666,12 +23122,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration Avataan asetuksia - + Create interface Luodaan käyttöliittymää @@ -24695,7 +23151,7 @@ Select the Friends with which you want to Share your Channel. Tallenna salasana - + Log In Kirjaudu sisään @@ -25040,7 +23496,7 @@ This choice can be reverted in settings. Tilaviesti - + Message: Viesti: @@ -25285,7 +23741,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags Poista kaikki merkkaukset @@ -25321,12 +23777,15 @@ p, li { white-space: pre-wrap; } Muodostetaan Tor-yhteys... - + + Tor status: Tor-tila: - + + + Unknown Tuntematon @@ -25336,18 +23795,13 @@ p, li { white-space: pre-wrap; } Ei käynnistynyt - - Hidden service address: - Piilotetun palvelun osoite: - - - - Tor bootstrap status: + + Hidden address: - - + + Not set Ei asetettu @@ -25357,12 +23811,57 @@ p, li { white-space: pre-wrap; } Onion-osoite: - + + Error + Virhe + + + + Not connected + Ei yhteyttä + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] [Odotetaan Tor...] @@ -25370,21 +23869,17 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor Tor - - <p>This version of Retroshare uses Tor to connect to your friends.</p> - <p>Tämä Retrosharen versio käyttää Tor-verkkoa yhdistääkseen ystäviisi.</p> - <p>This version of Retroshare uses Tor to connect to your trusted nodes.</p> - + Tor is currently offline Tor ei ole nyt linjoilla @@ -25395,11 +23890,12 @@ p, li { white-space: pre-wrap; } + No tor configuration Ei tor-asetuksia - + Tor proxy is OK @@ -25427,7 +23923,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options Siirtoasetukset @@ -25438,7 +23934,7 @@ p, li { white-space: pre-wrap; } Samanaikaisten latausten maksimimäärä: - + Shared Directories Jaetut hakemistot @@ -25448,22 +23944,27 @@ p, li { white-space: pre-wrap; } Jaa saapuvien hakemisto automaattisesti (suositeltavaa) - - Edit Share - Muokkaa jakoa - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every Tarkista jaetut hakemistot automaattisesti joka + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) minuutti @@ -25548,7 +24049,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -25557,7 +24058,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) Enimmäislähetykset ystävää kohden (0 = ei rajaa) @@ -25582,7 +24088,12 @@ p, li { white-space: pre-wrap; } Salli suora lataaminen: - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming Suoratoisto @@ -25641,38 +24152,13 @@ p, li { white-space: pre-wrap; } Trust friend nodes with banned files - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Retroshare</span><span style=" font-size:8pt;"> kykenee siirtämään dataa ja etsimään hakuja vertaisten välillä, jotka eivät välttämättä ole ystäviä. Tämä liikenne kaikesta huolimatta kauttakulkee ainoastaan yhdistettynä ystäväluettelelossa olevien kautta ja on nimetöntä.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Sinä voit erikseen asettaa jakoilmaisimia jokaiselle jaetulle hakemistolle Jaetut tiedostot-ikkunassa:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ystävien selattavissa</span>: tiedostot, jotka näkyvät ystäville.</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Nimettömästi jaetut</span>: tiedostot, jotka ovat nimettömästi saatavissa etäisten F2F-tunneleitten kautta.</li></ul></body></html> - Max. tunnel req. forwarded per second: Välitettyjen tunnelipyyntöjen maksimimäärä per sekunti: - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> <html><head/><body><p>Retroshare keskeyttää kaikki siirrot ja asetustiedoston tallennukset, jos levytila menee alle tämän rajoituksen. Se estää tiedon häviämisen joissakin järjestelmissä. Ponnahdusikkuna varoittaa sinua, kun näin käy.</p></body></html> @@ -25682,7 +24168,17 @@ p, li { white-space: pre-wrap; } - + + Warning + Varoitus + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory Aseta saapuvien hakemisto @@ -25710,7 +24206,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed Lataus suoritettu @@ -25734,39 +24230,23 @@ p, li { white-space: pre-wrap; } %1 completed transfer - - You have %1 completed downloads - Sinulla on %1 kpl valmiita latauksia - - - You have %1 completed download - Sinulla on %1 valmis lataus - - - %1 completed downloads - %1 kpl valmiita latauksia - - - %1 completed download - %1 valmis lataus - TransfersDialog - - + + Downloads Lataukset - + Uploads Lähetykset - + Name i.e: file name Nimi @@ -25973,7 +24453,12 @@ p, li { white-space: pre-wrap; } Määritä... - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... Siirrä jonossa... @@ -25998,7 +24483,7 @@ p, li { white-space: pre-wrap; } Valitse hakemisto - + Anonymous end-to-end encrypted tunnel 0x Nimetön päästä-päähän salattu tunneli 0x @@ -26019,7 +24504,7 @@ p, li { white-space: pre-wrap; } Retroshare - + @@ -26052,7 +24537,17 @@ p, li { white-space: pre-wrap; } Tiedosto %1 ei ole valmis. Jos se on mediatiedosto, voit yrittää esikatsella sitä. - + + Warning + Varoitus + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name Muuta tiedostonimeä @@ -26067,7 +24562,7 @@ p, li { white-space: pre-wrap; } Kirjoita uusi ja validi tiedostonimi - + Expand all Laajenna kaikki @@ -26194,23 +24689,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Sarakkeet - + File Transfers Tiedostojen siirrot - + Path Polku @@ -26220,7 +24710,7 @@ p, li { white-space: pre-wrap; } Näytä Polku-sarake - + Could not delete preview file Esikatselutiedostoa ei voitu poistaa @@ -26230,7 +24720,7 @@ p, li { white-space: pre-wrap; } Yritä uudelleen? - + Create Collection... Luo kokoelma... @@ -26245,7 +24735,7 @@ p, li { white-space: pre-wrap; } Näytä kokoelma... - + Collection Kokoelma @@ -26255,7 +24745,7 @@ p, li { white-space: pre-wrap; } %1 tunnelia - + Anonymous tunnel 0x Nimetön tunneli 0x @@ -26476,10 +24966,6 @@ p, li { white-space: pre-wrap; } File transfer tunnels - - Anonymous tunnels - Nimettömiä tunneleita - Authenticated tunnels @@ -26673,12 +25159,17 @@ p, li { white-space: pre-wrap; } Lomake - + Enable Retroshare WEB Interface Salli Retroshare-verkkokäyttöliittymä - + + Status: + Tila: + + + Web parameters Verkkoparametrit @@ -26712,35 +25203,33 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Note: these settings do not affect retroshare-service, which has a command line switch to activate the web interface and select the listening port.</p></body></html> - - Port: - Portti: - Allow access from all IP addresses (Default: localhost only) Salli pääsy kaikista IP-osoitteista (Oletus: sisäinen verkkoliityntä ainoastaan) - Apply setting and start browser - Käytä asetusta ja käynnistä selain - - - Note: these settings do not affect retroshare-nogui. Retroshare-nogui has a command line switch to activate the web interface. - Huomautus: nämä asetukset eivät vaikuta retroshare-nogui:n. Retroshare-nogui:ssa on komentorivivalitsin verkkokäyttöliittymän aktivoimiseksi. - - - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Verkkokäyttöliittymä</h1> <p>Verkkokäyttöliittymä sallii sinun hallita Retrosharea selaimestasi. Lukuisat laitteet voivat jakaa yhden Retroshare-instanssin hallinnan. Voit aloittaa keskustelun tabletillasi ja myöhemmin käyttää pöytäkonetta sitä jatkaaksesi.</p> <p>Varoitus: älä paljasta verkkokäyttöliittymää internetille, sillä siihen ei ole mitään käytönhallintaa eikä salausta. Jos haluat käyttää verkkokäyttöliittymää internetin kautta, käytä SSH-tunnelia tai välityspalvelinta yhteyden suojaamiseen.</p> - + Webinterface not enabled Verkkokäyttöliittymä ei ole käytössä @@ -26750,12 +25239,12 @@ p, li { white-space: pre-wrap; } Verkkokäyttöliittymä ei ole käytössä. Salli se Asetukset -> Verkkokäyttöliittymä. - + failed to start Webinterface verkkokäyttöliittymän käynnistys epäonnistui - + Webinterface Verkkokäyttöliittymä @@ -26892,11 +25381,7 @@ p, li { white-space: pre-wrap; } Wikisivut - New Group - Uusi ryhmä - - - + Page Name Sivun nimi @@ -26911,7 +25396,7 @@ p, li { white-space: pre-wrap; } Alkup. tunniste - + << << @@ -26999,7 +25484,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History Muokkaushistoria @@ -27034,7 +25519,7 @@ p, li { white-space: pre-wrap; } PageId - + \/ \/ @@ -27064,14 +25549,18 @@ p, li { white-space: pre-wrap; } Merkkaukset - - + + History + Historia + + + Show Edit History Näytä muokkaushistoria - + Status Tila @@ -27092,7 +25581,7 @@ p, li { white-space: pre-wrap; } Palauta - + Submit Lähetä @@ -27164,10 +25653,6 @@ p, li { white-space: pre-wrap; } WireDialog - - TimeRange - Aikaväli - Create Account @@ -27179,16 +25664,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - Päivitä - - - + Settings @@ -27203,7 +25679,7 @@ p, li { white-space: pre-wrap; } Muut - + Who to Follow @@ -27223,7 +25699,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -27253,85 +25729,17 @@ p, li { white-space: pre-wrap; } - Last Month - Viime kuussa - - - Last Week - Viime viikolla - - - Today - Tänään - - - New - Uusi - - - from - alkaen - - - until - päättyen - - - Search/Filter - Haku/suodatus - - - Network Wide - Verkon laajuinen - - - Manage Accounts - Hallitse tilejä - - - Showing: - Näyttää: - - - + Yourself Sinä itse - - Friends - Ystävät - Following Seurataan - Custom - Räätälöity - - - Account 1 - Tili 1 - - - Account 2 - Tili 2 - - - Account 3 - Tili 3 - - - CheckBox - Valintaruutu - - - Post Pulse to Wire - Lähetä pulssi lennättimeen - - - + RetroShare Retroshare @@ -27394,35 +25802,42 @@ p, li { white-space: pre-wrap; } Lomake - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + Poista + + + Location: Sijainti: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -27467,11 +25882,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + Ei sovellu + + + + Following + Seurataan + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Tuntematon @@ -27549,7 +25994,7 @@ p, li { white-space: pre-wrap; } %1y %2d - + k e.g: 3.1 k k @@ -27582,15 +26027,11 @@ p, li { white-space: pre-wrap; } Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif *.webp) - - Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - Kuvat (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - pgpid_item_model - + Do you accept connections signed by this profile? Hyväksytkö tämän profiilin allekirjoittamat yhteydet? @@ -27599,10 +26040,6 @@ p, li { white-space: pre-wrap; } Name of the profile Profiilin nimi - - This column indicates trust level and whether you signed the profile PGP key - Tämä sarake osoittaa luottamustason ja mikäli olet allekirjoittanut profiilin PGP-avaimen. - This column indicates the trust level you indicated and whether you signed the profile PGP key @@ -27713,10 +26150,6 @@ p, li { white-space: pre-wrap; } Denied - - - - - - PGP key signed by you diff --git a/retroshare-gui/src/lang/retroshare_fr.ts b/retroshare-gui/src/lang/retroshare_fr.ts index cc9597926..127c0fdd7 100644 --- a/retroshare-gui/src/lang/retroshare_fr.ts +++ b/retroshare-gui/src/lang/retroshare_fr.ts @@ -84,13 +84,6 @@ Nœud caché seulement - - AddCommentDialog - - Add Comment - Ajouter un commentaire - - AddFileAssociationDialog @@ -129,12 +122,12 @@ Retroshare : Recherche avancée - + Search Criteria Critère(s) de recherche - + Add a further search criterion. Ajouter un critère de recherche. @@ -144,7 +137,7 @@ Réinitialiser les critères de recherche. - + Cancels the search. Annuler la recherche. @@ -164,177 +157,6 @@ Rechercher - - AlbumCreateDialog - - Create Album - Créer un album - - - Album Name: - Nom de l'album : - - - Category: - Catégorie : - - - Animals - Animaux - - - Family - Famille - - - Friends - Amis - - - Flowers - Fleurs - - - Holiday - Vacances - - - Landscapes - Paysages - - - Pets - Animaux - - - Portraits - Portraits - - - Travel - Voyage - - - Work - Travail - - - Random - Aléatoire - - - Caption: - Légende : - - - Where: - Où : - - - Photographer: - Photographe : - - - Description: - Description : - - - Share Options - Options de partage - - - Policy: - Politique : - - - Quality: - Qualité : - - - Comments: - Commentaires : - - - Identity: - Identité : - - - Public - Public - - - Restricted - Limité - - - Resize Images (< 1Mb) - Redimensionner les images (< 1Mo) - - - Resize Images (< 10Mb) - Redimensionner les images (< 10Mo) - - - Send Original Images - Envoyer images originales - - - No Comments Allowed - Aucun commentaire admis - - - Authenticated Comments - Commentaires authentifiés - - - Any Comments Allowed - Aucun commentaire admis - - - Publish with Identity - Publier avec l'identité - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Glissez &amp; Déposez pour insérer des images. Cliquez sur une image pour modifier les détails ci-dessous.</span></p></body></html> - - - Back - Retour - - - Add Photos - Ajouter photos - - - Publish Album - Publier l'album - - - Untitle Album - Album sans titre - - - Say something about this album... - Donnez des détails sur cette album... - - - Where were these taken? - Où cela a été pris ? - - - Load Album Thumbnail - Charger la miniature de l'album - - AlbumDialog @@ -343,19 +165,11 @@ p, li { white-space: pre-wrap; } Album Album - - Album Thumbnail - Miniature de l'album - TextLabel Etiquette - - Summary - Résumé - Album Title: @@ -371,34 +185,6 @@ p, li { white-space: pre-wrap; } Caption Légende - - Where: - Où : - - - When - Quand : - - - Description: - Description : - - - Share Options - options de partage - - - Comments - Commentaires - - - Publish Identity - Publier l'identité - - - Visibility - Visibilité - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -767,7 +553,7 @@ p, li { white-space: pre-wrap; } Retroshare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. Avertissements : Ces services sont expérimentaux. Aidez nous à les tester @@ -783,14 +569,6 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à Circles Cercles - - GxsForums - GxsForums - - - GxsChannels - ChaînesGxs - The Wire @@ -802,10 +580,23 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à Photos + + AspectRatioPixmapLabel + + + Save image + Sauvegarder image + + + + Copy image + + + AttachFileItem - + %p Kb %p Ko @@ -842,17 +633,13 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à Browse... - - Add Avatar - Ajouter avatar - Remove Supprimer - + Set your Avatar picture Mettre votre image d'avatar @@ -871,10 +658,6 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - Charger l'avatar - AvatarWidget @@ -943,22 +726,10 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à Réinitialiser - Receive Rate - Vitesse de réception - - - Send Rate - Vitesse d'émission - - - + Always on Top Toujours visible - - Style - Style - Changes the transparency of the Bandwidth Graph @@ -974,23 +745,11 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à % Opaque % opaque - - Save - Sauvegarder - - - Cancel - Annuler - Since: Statistiques enregistrées depuis : - - Hide Settings - Masquer les options - BandwidthStatsWidget @@ -1063,7 +822,7 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à BoardPostDisplayWidgetBase - + Comment Commentaire @@ -1093,12 +852,12 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> <p><font color="#ff0000"><b>L'auteur de ce message (avec l'ID %1) est banni.</b> - + ago @@ -1106,7 +865,7 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à BoardPostDisplayWidget_card - + Vote up Voter pour @@ -1126,7 +885,7 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à \/ - + Posted by @@ -1164,7 +923,7 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à BoardPostDisplayWidget_compact - + Vote up Voter pour @@ -1184,7 +943,7 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à \/ - + Click to view picture @@ -1214,7 +973,7 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à Partager - + Toggle Message Read Status Changer l'état de lecture du message @@ -1224,7 +983,7 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à Nouveau - + TextLabel @@ -1232,12 +991,12 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à BoardsCommentsItem - + I like this J'aime ça - + 0 0 @@ -1257,18 +1016,18 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à Avatar - + New Comment - + Copy RetroShare Link - + Expand @@ -1283,12 +1042,12 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à - + Name Nom - + Comm value @@ -1457,17 +1216,17 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à ChannelPage - + Channels Chaînes - + Tabs Onglets - + General Général @@ -1477,11 +1236,17 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à - Load posts in background (Thread) - Charger les messages en tâche de fond (fils, "threads") + + Downloads + Téléchargements - + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab Ouvrir chaque chaîne dans un nouvel onglet @@ -1489,7 +1254,7 @@ Mais rappelez-vous : Toutes les données *SERONT* perdus quand nous mettrons à ChannelPostDelegate - + files @@ -1512,7 +1277,7 @@ into the image, so as to ChannelsCommentsItem - + I like this J'aime ça @@ -1537,18 +1302,18 @@ into the image, so as to Avatar - + New Comment - + Copy RetroShare Link - + Expand @@ -1563,7 +1328,7 @@ into the image, so as to - + Name Nom @@ -1573,17 +1338,7 @@ into the image, so as to - - Comment - Commentaire - - - - Comments - Commentaires - - - + Hide Cacher @@ -1591,7 +1346,7 @@ into the image, so as to ChatLobbyDialog - + Name Nom @@ -1782,7 +1537,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby Afficher le salon de tchat @@ -1794,22 +1549,6 @@ into the image, so as to Chats Tchats - - You have %1 new messages - Vous avez %1 nouveaux messages - - - You have %1 new message - Vous avez %1 nouveau message - - - %1 new messages - %1 nouveaux messages - - - %1 new message - %1 nouveau message - You have %1 mentions @@ -1831,13 +1570,14 @@ into the image, so as to - + + Unknown Lobby Salon inconnu - - + + Remove All Tout supprimer @@ -1845,13 +1585,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Nom - + Count Participants @@ -1861,37 +1601,7 @@ into the image, so as to Sujet - - Private Subscribed chat rooms - Salons de tchat privés abonnés - - - - - Public Subscribed chat rooms - Salons de tchat publics abonnés - - - - Private chat rooms - Salons de tchat privés - - - - - Public chat rooms - Salons de tchat publics - - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/images/add_24x24.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Salons de tchat</h1> <p>Les salons de tchat fonctionnent à peu près comme l'IRC. Ils vous permettent de discuter anonymement avec de nombreuses personnes sans avoir besoin d'être des amis. - -Un salon de tchat peut être de type public (vos amis le voient) ou privé (vos amis ne le voient pas, à moins que vous les invitiez avec <img src=":/images/add_24x24.png" width=%2/>). Une fois que vous aurez été invité à un salon privé, vous serez capable de le voir lorsque vos amis l'utiliseront. - -La liste à gauche montre les salons de tchat auxquels vos amis participent. Vous pouvez soit :<ul> <li>Faire un clic droit pour créer un nouveau salon de tchat</li> <li>Faire un double clic sur un salon pour y entrer, tchatter, et le montrer à vos amis</li> </ul> Note : pour que les salons de tchat fonctionnent correctement, votre ordinateur doit être à l'heure. Alors vérifiez l'horloge de votre système ! </p> - - - + Create chat room Créer salon de tchat @@ -1901,7 +1611,7 @@ La liste à gauche montre les salons de tchat auxquels vos amis participent. Vou Quitter ce salon - + Create a non anonymous identity and enter this room Créer une identité non anonyme et entrer dans cette salle @@ -1960,12 +1670,12 @@ Sélectionnez un des salons de tchat à gauche pour en afficher les détails. Double-cliquez sur un salon pour y entrer et discuter. - + %1 invites you to chat room named %2 %1 vous invite à un salon de tchat nommée %2 - + Choose a non anonymous identity for this chat room: Choisissez une identité anonyme pour de salon de tchat. @@ -1975,31 +1685,31 @@ Double-cliquez sur un salon pour y entrer et discuter. Choisissez une identité pour ce salon : - Create chat lobby - Créer un nouveau salon de tchat - - - + [No topic provided] [Sans sujet déterminé] - Selected lobby info - Info du salon sélectionné - - - + + Private Privé - + + + Public Public - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted IDs anonymes acceptées @@ -2009,42 +1719,25 @@ Double-cliquez sur un salon pour y entrer et discuter. Retirer des abonnements auto - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe Ajouter aux abonnements auto - + Search Chat lobbies Rechercher des salons de tchat - + Search Name Rechercher par nom - Subscribed - Abonné - - - + Columns Colonnes - - Yes - Oui - - - No - Non - Chat rooms @@ -2056,47 +1749,47 @@ Double-cliquez sur un salon pour y entrer et discuter. - + Chat Room info - + Chat room Name: Nom du salon de chat : - + Chat room Id: ID du salon de chat : - + Topic: Sujet : - + Type: Type : - + Security: Sécurité : - + Peers: Contacts : - - - - - - + + + + + + TextLabel Etiquette @@ -2111,13 +1804,24 @@ Double-cliquez sur un salon pour y entrer et discuter. Aucune IDs anonymes - + Show Montrer - + + Private Subscribed + + + + + + Public Subscribed + + + + column colonn @@ -2131,7 +1835,7 @@ Double-cliquez sur un salon pour y entrer et discuter. ChatMsgItem - + Remove Item Supprimer @@ -2176,46 +1880,22 @@ Double-cliquez sur un salon pour y entrer et discuter. ChatPage - + General Général - - Distant Chat - Tchat distant - Everyone Tout le monde - - Contacts - Contacts - Nobody Personne - Accept encrypted distant chat from - Accepter un tchat éloigné et chiffré de la part de - - - Chat Settings - Paramètres du tchat - - - Enable Emoticons Private Chat - Activer les émoticônes pour le tchat privé - - - Enable Emoticons Group Chat - Activer les émoticônes pour le tchat public - - - + Enable custom fonts Activer les polices personnalisées @@ -2224,10 +1904,6 @@ Double-cliquez sur un salon pour y entrer et discuter. Enable custom font size Activer la taille de la police personnalisée - - Minimum font size - Taille de police minimale - Enable bold @@ -2239,7 +1915,7 @@ Double-cliquez sur un salon pour y entrer et discuter. Activer l'italique - + General settings @@ -2264,11 +1940,7 @@ Double-cliquez sur un salon pour y entrer et discuter. Charger les images intégrées - Chat Lobby - Salons de tchat - - - + Blink tab icon Icône d'onglet clignotant @@ -2277,10 +1949,6 @@ Double-cliquez sur un salon pour y entrer et discuter. Do not send typing notifications N'envoyez pas de notifications de frappe - - Private Chat - Tchat privé - Open Window for new chat @@ -2302,11 +1970,7 @@ Double-cliquez sur un salon pour y entrer et discuter. Fenêtre/Icône d'onglet clignotant - Chat Font - Police d'écriture - - - + Change Chat Font Changer la police du tchat @@ -2316,14 +1980,10 @@ Double-cliquez sur un salon pour y entrer et discuter. Police d'écriture : - + History Historique - - Style - Style - @@ -2338,17 +1998,13 @@ Double-cliquez sur un salon pour y entrer et discuter. Variant: Variante : - - Group chat - Tchat public - Private chat Tchat privé - + Choose your default font for Chat. Choisissez votre police de caractère par défaut pour les tchats. @@ -2412,22 +2068,28 @@ Double-cliquez sur un salon pour y entrer et discuter. <html><head/><body><p align="justify">In this tab you can setup how many chat messages Retroshare will keep saved on the disc and how much of the previous conversation it will display, for the different chat systems. The max storage period allows to discard old messages and prevents the chat history from filling up with volatile chat (e.g. chat lobbies and distant chat).</p></body></html> <html><head/><body><p align="justify">Dans cet onglet, vous pouvez configurer le nombre de messages de tchat que Retroshare gardera sauvegardé sur le disque et combien de la conversation précédente, elle affiche, pour les différents systèmes de discussions. La période de stockage max permet de supprimer les anciens messages et empêche l'historique des conversations de remplir les tchats volatiles (par exemple, les salons de tchat et tchat à distance).</p></body></html> - - Chatlobbies - Salons de tchat - Enabled: Activé : - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2437,7 +2099,17 @@ Double-cliquez sur un salon pour y entrer et discuter. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms Salons de tchat @@ -2534,11 +2206,7 @@ Double-cliquez sur un salon pour y entrer et discuter. Période maximale de stockage, en jours (0=garde tout) : - Search by default - Recherche préconfigurée - - - + Case sensitive Respecter la casse @@ -2577,10 +2245,6 @@ Double-cliquez sur un salon pour y entrer et discuter. Threshold for automatic search Seuil pour recherche automatique - - Default identity for chat lobbies: - Identité par défaut pour les salons de tchat : - Show Bar by default @@ -2648,7 +2312,7 @@ Double-cliquez sur un salon pour y entrer et discuter. ChatToaster - + Show Chat Afficher le tchat @@ -2684,7 +2348,7 @@ Double-cliquez sur un salon pour y entrer et discuter. ChatWidget - + Close Fermer @@ -2719,12 +2383,12 @@ Double-cliquez sur un salon pour y entrer et discuter. Italique - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon Insérer émoticône @@ -2804,11 +2468,6 @@ Double-cliquez sur un salon pour y entrer et discuter. Insert horizontal rule Insérer ligne horizontale - - - Save image - Sauvegarder image - Import sticker @@ -2846,7 +2505,7 @@ Double-cliquez sur un salon pour y entrer et discuter. - + is typing... écrit... @@ -2870,7 +2529,7 @@ après la conversion en HTML. Choisissez votre police de caractère. - + Do you really want to physically delete the history? Etes-vous vraiment sûr de vouloir supprimer définitivement l'historique ? @@ -2920,7 +2579,7 @@ après la conversion en HTML. est occupé et peut ne pas répondre - + Find Case Sensitively Trouver en tenant compte de la casse @@ -2942,7 +2601,7 @@ après la conversion en HTML. Ne pas cesser de colorer après X articles trouvés (nécessite davantage de CPU) - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> <b>Trouver le précédent </b><br/><i>Ctrl+Shift+G</i> @@ -2957,16 +2616,12 @@ après la conversion en HTML. <b>Trouver </b><br/><i>Ctrl+F</i> - + (Status) (Statut) - Set text font & color - Régler police de caractères du texte et couleur - - - + Attach a File Joindre un fichier @@ -2982,12 +2637,12 @@ après la conversion en HTML. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> <b>Marquer ce texte comme sélectionné</b><br><i>Ctrl+M</i> - + Person id: Id d'identité: @@ -2999,12 +2654,12 @@ Double click on it to add his name on text writer. Double cliquez pour ajouter son nom dans le champ de saisie du message. - + Unsigned Non signé - + items found. articles trouvés. @@ -3024,7 +2679,7 @@ Double cliquez pour ajouter son nom dans le champ de saisie du message.Saisissez votre message ici - + Don't stop to color after Ne pas cesser de colorer après @@ -3050,7 +2705,7 @@ Double cliquez pour ajouter son nom dans le champ de saisie du message. CirclesDialog - + Showing details: Afficher les détails : @@ -3072,7 +2727,7 @@ Double cliquez pour ajouter son nom dans le champ de saisie du message. - + Personal Circles Cercles personnels @@ -3098,7 +2753,7 @@ Double cliquez pour ajouter son nom dans le champ de saisie du message. - + Friends Amis @@ -3158,7 +2813,7 @@ Double cliquez pour ajouter son nom dans le champ de saisie du message.Amis des Amis - + External Circles (Admin) Cercles extérieurs (Admin) @@ -3174,7 +2829,7 @@ Double cliquez pour ajouter son nom dans le champ de saisie du message. - + Circles Cercles @@ -3226,43 +2881,48 @@ Double cliquez pour ajouter son nom dans le champ de saisie du message. - + RetroShare Retroshare - + - + Error : cannot get peer details. Erreur : impossible d'obtenir les détails de ce contact. - + Retroshare ID - + <p>This Retroshare ID contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: + + + <b>DNS:</b> : + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3274,7 +2934,7 @@ Double cliquez pour ajouter son nom dans le champ de saisie du message.Chiffrement - + Not connected Non connecté @@ -3356,25 +3016,17 @@ Double cliquez pour ajouter son nom dans le champ de saisie du message.aucun - + <p>This certificate contains: <p>Ce certificat contient : - + <li>a <b>node ID</b> and <b>name</b> <li>un <b>ID de noeud</b> et <b>nom</b> - an <b>onion address</b> and <b>port</b> - une <b>adresse onion</b> et <b>port</b> - - - an <b>IP address</b> and <b>port</b> - une <b>addresse IP</b> et <b>port</b> - - - + <p>You can use this certificate to make new friends. Send it by email, or give it hand to hand.</p> <p>Vous pouvez utiliser ce certificat pour vous faire de nouveaux amis. Envoyez-le par courrier électronique, ou donnez-le de main à la main.</p> @@ -3389,7 +3041,7 @@ Double cliquez pour ajouter son nom dans le champ de saisie du message.<html><head/><body><p>Ceci est la méthode de chiffrement utilisée par <span style=" font-weight:600;">OpenSSL</span>. La connexion aux noeuds amis est </p><p>toujours lourdement chiffrée, et si la DHE est présente la connexion utilise ensuite </p><p>&quot;perfect forward secrecy&quot;.</p></body></html> - + with avec @@ -3406,118 +3058,16 @@ Double cliquez pour ajouter son nom dans le champ de saisie du message.Connect Friend Wizard Assistant de connexion à un ami - - Add a new Friend - Ajouter un nouvel ami - - - &You get a certificate file from your friend - Vous avez un possédez le certificat de votre ami dans un &Fichier - - - &Make friend with selected friends of my friends - Devenir a&mi avec les amis sélectionnés de vos amis - - - &Send an Invitation by Email - (Your friend will receive an email with instructions how to download RetroShare) - &Envoyer une invitation par Mail -(Votre ami recevra un mail avec les instruction pour télécharger RetroShare) - - - Include signatures - Inclure les signatures - - - Copy your Cert to Clipboard - Copier votre certificat dans le presse-papier - - - Save your Cert into a File - Enregistrer votre certificat dans un fichier - - - Run Email program - Envoyer par courrier électronique - Open Cert of your friend from File Ouvrir le certificat de votre ami depuis un fichier - - Open certificate - Ouvrir le certificat - - - Please, paste your friend's Retroshare certificate into the box below - Veuillez coller le certificat de votre ami Retroshare dans la case ci-dessous - - - Certificate files - Fichiers de certificats - - - Use PGP certificates saved in files. - Utiliser des certificats PGP contenus dans des fichiers. - - - Import friend's certificate... - Importer le certificat d'un ami... - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - Vous devez générer un fichier à partir de votre certificat et le transmettre à votre ami. Vous pouvez aussi utiliser un fichier généré auparavant. - - - Export my certificate... - Exporter mon certificat... - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - Glisser et déposer le certificat de votre ami dans cette fenêtre ou importez le à partir de votre disque dur - - - Browse - Parcourir - - - Friends of friends - Amis de vos amis - - - Select now who you want to make friends with. - Veuillez selectionner avec qui vous souhaitez devenir ami. - - - Show me: - Afficher : - - - Make friend with these peers - Devenir ami avec ces contacts - RetroShare ID ID Retroshare - - Use RetroShare ID for adding a Friend which is available in your network. - Utilisez l'ID Retroshare pour ajouter un ami qui est disponible dans votre réseau. - - - Add Friends RetroShare ID... - Ajouter l'ID d'amis Retroshare... - - - Paste Friends RetroShare ID in the box below - Coller l'ID Retroshare d'amis ci-dessous - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - Entrez l'ID Retroshare de votre ami, p. ex.. Contact@BDE8D16A46D938CF - RetroShare is better with Friends @@ -3559,27 +3109,7 @@ Double cliquez pour ajouter son nom dans le champ de saisie du message.Email - Invite Friends by Email - Inviter un ami à rejoindre Retroshare par e-mail - - - Enter your friends' email addresses (separate each one with a semicolon) - Entrez les adresses e-mail de vos amis (séparées par un point-virgule) - - - Your friends' email addresses: - Destinataire(s) : - - - Enter Friends Email addresses - Entrez l'adresse e-mail de vos amis - - - Subject: - Sujet : - - - + @@ -3595,77 +3125,32 @@ Double cliquez pour ajouter son nom dans le champ de saisie du message.Détails de la demande - + Peer details Détails du contact - + Name: Nom : - - Email: - E-Mail : - - - Node: - Noeud : - - - Please note that RetroShare will require excessive amounts of bandwidth, memory and CPU if you add too many friends. You can add as many friends as you like, but more than 40 will probably require too much -resources. - Veuillez noter que Retroshare nécessitera beaucoup de bande passante, mémoire et CPU si vous ajoutez de nombreux amis. Vous pouvez ajouter autant d'amis que vous le souhaitez, mais avec avec plus de 40 cela nécessitera probablement trop de ressources. - Location: Emplacement : - + Options Options - This wizard will help you to connect to your friend(s) to RetroShare network.<br>Select how you would like to add a friend: - Cet assistant vous aidera à vous connecter à vos amis avec Retroshare.<br>Il y a diverses possibilités pour le faire : - - - Enter the certificate manually - Entrer manuellement le certificat - - - Enter RetroShare ID manually - Entrer manuellement l'ID Retroshare - - - &Send an Invitation by Web Mail Providers - Envoyez une invitation par me&ssagerie électronique - - - Recommend many friends to each other - Recommander plusieurs amis les uns aux autres - - - RetroShare certificate - Certificat Retroshare - - - Please paste below your friend's Retroshare certificate - Veuillez coller ci-dessous le certificat de votre ami Retroshare - - - Paste certificate - Collez le certificat - - - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> <html><head/><body><p>Cette boîte s'attend au certificat de votre ami Retroshare. AVERTISSEMENT : cela est différent de la clé PGP de votre ami. Ne collez pas ici la clé de profil de votre ami (même pas une partie). Cela ne fonctionnera pas.</p></body></html> - + Add friend to group: Ajouter l'ami à un groupe : @@ -3675,7 +3160,7 @@ resources. Ami authentifié (clé PGP signée) - + Please paste below your friend's Retroshare ID @@ -3700,16 +3185,22 @@ resources. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with Ajouter cet ami pour communiquer avec lui - To accept the Friend Request, click the Finish button. - Pour accepter la demande d'amitié, cliquez sur le bouton Terminer. - - - + Sorry, some error appeared Désolé, des erreurs sont survenues @@ -3729,32 +3220,27 @@ resources. À propos de votre ami : - + Key validity: Validité de la clé : - + Profile ID: - - Signers - Ils lui font aussi confiance : - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Signer la clé d'un ami est un moyen d'exprimer votre confiance en cet ami, à vos autres amis. Les signatures sous cryptographie attestent que les propriétaires des clés répertoriées reconnaissent la clé PGP actuelle comme authentique.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. Ce contact est déjà dans votre liste d'am. L'ajouter se limitera à enregistrer son adresse IP. - + To accept the Friend Request, click the Accept button. @@ -3800,49 +3286,17 @@ resources. - + Certificate Load Failed Le chargement du certificat à échoué - Cannot get peer details of PGP key %1 - Impossible d'obtenir les détails de la clé PGP %1 - - - Any peer I've not signed - Tous les contacts dont vous n'avez pas signé les certificats - - - Friends of my friends who already trust me - Amis de vos amis qui vous ont déjà accordé leur confiance - - - Signed peers showing as denied - Contacts signées montrés comme refusés - - - Peer name - Nom du contact - - - Also signed by - Également signé par - - - Peer id - ID du contact - - - Certificate appears to be valid - Le certificat semble valide - - - + Not a valid Retroshare certificate! Certificat Retroshare non valide! - + RetroShare Invitation Invitation Retroshare @@ -3864,12 +3318,12 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? C'est votre propre certificat! Vous ne voulez pas devenir ami avec vous même. N'est-ce pas? - + @@ -3877,7 +3331,7 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg - + This key is already on your trusted list Cette clé est déjà dans votre liste de confiance. @@ -3917,7 +3371,7 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg Vous avez une demande d'amitié de - + Profile password needed. @@ -3942,7 +3396,7 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg - + Valid Retroshare ID @@ -3952,47 +3406,7 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg - Certificate Load Failed:file %1 not found - L'importation du certificat a échoué : le fichier %1 n'a pas été trouvé - - - This Peer %1 is not available in your Network - Ce contact %1 n'est pas disponible dans votre réseau - - - Use new certificate format (safer, more robust) - Utiliser le nouveau format de certificat (plus sure, plus robuste) - - - Use old (backward compatible) certificate format - Utilisez l'ancien format de certificat (rétrocompatible) - - - Remove signatures - Supprimer les signatures - - - RetroShare Invite - Invitation Retroshare - - - Connect Friend Help - Aide pour l'envoi du certificat - - - You can copy this text and send it to your friend via email or some other way - Vous pouvez copier votre certificat et l'envoyer à vos amis par courrier électronique ou par tout autre moyen - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Votre certificat a été copié dans le presse-papier, collez-le et envoyez-le par courrier electronique ou par tout autre moyen - - - Save as... - Enregistrer sous... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -4031,11 +3445,7 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg *** Aucune *** - Use as direct source, when available - Utiliser en source directe, quand disponible - - - + IP-Addr: Addr-IP : @@ -4045,7 +3455,7 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg Adresse IP - + Show Advanced options Afficher les options avancées @@ -4054,10 +3464,6 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Signer la clé d'un ami est une façon d'exprimer à vos autres amis votre confiance en cet ami. Cela les aide à décider, en se basant sur votre propre confiance, si ils doivent permettre des connexions depuis cette clé. Signer une clé est absolument facultatif et ne peut pas être défait, alors faites-le avec sagesse.</span></p></body></html> - - <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> - <html><head/><body><p align="justify">Retroshare vérifie périodiquement vos listes d'amis pour les recherches de fichier correspondant à vos transferts, afin d'établir un transfert direct. Dans ce cas, votre ami sait que vous téléchargez le fichier.</p><p align="justify">Pour éviter ce comportement pour cet ami uniquement, décochez cette case. Vous pouvez toujours effectuer un transfert direct si vous le demandez explicitement, par ex. Téléchargement de la liste de fichiers de votre ami. Ce paramètre est appliqué à tous les emplacements de même ami.</p></body></html> - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> @@ -4068,45 +3474,13 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg <html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> <html><head/><body><p>Les personnes qui ont cette option ne peuvent pas se connecter si leur adresse de connexion n'est pas dans la liste blanche. Cela vous protège contre les attaques de transfert de trafic. Lorsqu'ils sont utilisés, les homologues rejetés seront signalés par des &quot;alertes de sécurité&quot; dans le fil d'actualité. De là, vous pouvez mettre en liste blanche ou noir leur IP. S'applique à tous les emplacements de même personne.</p></body></html> - - Recommend many friends to each others - Recommander plusieurs amis les uns aux autres - - - Friend Recommendations - Recommandations d'amis - - - The text below is your Retroshare certificate. You have to provide it to your friend - Le texte ci-dessous est votre certificat Retroshare. Vous devez le fournir à votre ami - - - Message: - Message : - - - Recommend friends - Amis recommandés - - - To - Pour - - - Please select at least one friend for recommendation. - Veuillez sélectionner au moins un ami à recommander. - - - Please select at least one friend as recipient. - Veuillez sélectionner au moins un destinataire. - Add key to keyring Ajouter la clé au trousseau - + This key is already in your keyring Cette clé est déjà dans votre trousseau @@ -4122,7 +3496,7 @@ l'envoi de messages distants à ce contact même si vous n'êtes pas amis. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. Le certificat a un mauvais numéro de version. Souvenez-vous que les réseaux v0.6 et v0.5 sont incompatibles. @@ -4157,7 +3531,7 @@ contact même si vous n'êtes pas amis. Ajouter l'IP dans la liste blanche - + No IP in this certificate! Pas d'IP dans ce certificat ! @@ -4167,27 +3541,10 @@ contact même si vous n'êtes pas amis. <p>Ce certificat n'a pas d'IP. Vous devrez compter sur la découverte et la DHT pour le trouver. Parce que vous exigez l'autorisation liste blanche, le pair lèvera un avertissement de sécurité dans l'onglet "Fil d'actualités". De là, vous pourrez passer son IP en liste blanche.</p> - - [Unknown] - [Inconnu] - - - + Added with certificate from %1 Ajoutée avec certificat depuis %1 - - Paste Cert of your friend from Clipboard - Coller le certificat de votre ami depuis le presse-papier - - - Certificate Load Failed:can't read from file %1 - Échec de chargement du certificat : ne peut pas lire le fichier %1 - - - Certificate Load Failed:something is wrong with %1 - Échec de chargement du certificat : quelque chose ne va pas dans %1 - ConnectProgressDialog @@ -4249,7 +3606,7 @@ contact même si vous n'êtes pas amis. - + UDP Setup Réglage UDP @@ -4285,7 +3642,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:13pt;">vous pouvez fermer la fenêtre.</span></p></body></html> - + Connection Assistant Assistant de connexion @@ -4295,17 +3652,20 @@ p, li { white-space: pre-wrap; } ID du contact incorrecte - + + Unknown State État inconnu - + + Offline Hors ligne - + + Behind Symmetric NAT Derrière un NAT symétrique @@ -4315,12 +3675,14 @@ p, li { white-space: pre-wrap; } Derrière un NAT & Pas de DHT - + + NET Restart Redémarrage du NET - + + Behind NAT Derrière un NAT @@ -4330,7 +3692,8 @@ p, li { white-space: pre-wrap; } Pas de DHT - + + NET STATE GOOD! ÉTAT DU NET : BON ! @@ -4355,7 +3718,7 @@ p, li { white-space: pre-wrap; } Recherche de contacts RS - + Lookup requires DHT Lookup nécessite la DHT @@ -4647,7 +4010,7 @@ p, li { white-space: pre-wrap; } Veuillez réessayez d'importer le certificat en entier - + @@ -4655,7 +4018,8 @@ p, li { white-space: pre-wrap; } N/A - + + UNVERIFIABLE FORWARD! FORWARD INVÉRIFIABLE ! @@ -4665,7 +4029,7 @@ p, li { white-space: pre-wrap; } FORWARD INVÉRIFIABLE & PAS DE DHT - + Searching Recherche @@ -4701,12 +4065,12 @@ p, li { white-space: pre-wrap; } Détails du cercle - + Name Nom - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> <html><head/><body><p>Le nom du cercle, le contact de l'auteur et la liste des membres invités sera visible à tous les invités. Si le cercle n'est pas privé, ils seront également visibles aux nœuds voisins de ceux qui hébergent les invités.</p></body></html> @@ -4726,7 +4090,7 @@ p, li { white-space: pre-wrap; } - + IDs IDs @@ -4746,18 +4110,18 @@ p, li { white-space: pre-wrap; } Filtre - + Cancel Annuler - + Nickname Surnom - + Invited Members Membres invités @@ -4772,15 +4136,7 @@ p, li { white-space: pre-wrap; } Personnes connues - ID - ID - - - Type - Type - - - + Name: Nom : @@ -4820,23 +4176,19 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Les cercles peuvent être limités aux membres d'un autre cercle. Seuls les membres de ce deuxième cercle seront autorisés à voir le nouveau cercle et son contenu (la liste des membres, etc)</p></body></html> - Only visible to members of: - Seulement visible par les membres de : - - - - + + RetroShare Retroshare - + Please set a name for your Circle S'il vous plaît donnez un nom à votre cercle - + No Restriction Circle Selected Aucune restriction de cercle sélectionnée @@ -4846,12 +4198,24 @@ p, li { white-space: pre-wrap; } Aucune limitation de cercle sélectionnée - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] [Inconnu] - + Add Ajouter @@ -4861,7 +4225,7 @@ p, li { white-space: pre-wrap; } Enlever - + Search Rechercher @@ -4876,10 +4240,6 @@ p, li { white-space: pre-wrap; } Signed Signé - - Signed by known nodes - Signé par des noeuds connus - Edit Circle @@ -4896,10 +4256,6 @@ p, li { white-space: pre-wrap; } PGP Identity Identité PGP - - Anon Id - ID anon - Circle name @@ -4922,17 +4278,13 @@ p, li { white-space: pre-wrap; } Créer un nouveau cercle - + Create Créer - PGP Linked Id - ID PGP liée - - - + Add Member Ajouter membre @@ -4951,7 +4303,7 @@ p, li { white-space: pre-wrap; } Créer un groupe - + Group Name: Nom du groupe : @@ -4986,7 +4338,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post Nouvel article sur la chaîne @@ -4996,7 +4348,7 @@ p, li { white-space: pre-wrap; } Message - + Post @@ -5057,23 +4409,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Utiliser "glisser-déposer" / le bouton d'ajout, pour hacher de nouveaux fichiers.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Copier/collez des liens Retroshare depuis vos partages.</span></p></body></html> - - Add File to Attach - Joindre un fichier - Add Channel Thumbnail Incorporer une miniature - - Message - Message - - - Subject : - Sujet : - @@ -5159,17 +4499,17 @@ p, li { white-space: pre-wrap; } - + RetroShare Retroshare - + This file already in this post: - + Post refers to non shared files @@ -5188,17 +4528,18 @@ p, li { white-space: pre-wrap; } The following files will only be shared for 30 days. Think about adding them to a shared directory. - - File already Added and Hashed - Fichier déjà ajouté et hashé - Please add a Subject Veuillez ajouter un sujet à votre message - + + Cannot publish post + + + + Load thumbnail picture Charger la miniature @@ -5213,18 +4554,12 @@ p, li { white-space: pre-wrap; } Cacher - - + Generate mass data Générer des données en masse - - Do you really want to generate %1 messages ? - Voulez-vous vraiment générer %1 messages ? - - - + You are about to add files you're not actually sharing. Do you still want this to happen? Vous êtes sur le point d'ajouter les fichiers que vous ne partagez pas actuellement. Voulez-vous toujours faire cela ? @@ -5258,7 +4593,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message Poster un message sur le forum @@ -5267,10 +4602,6 @@ p, li { white-space: pre-wrap; } Forum Forum - - Subject - Sujet - Attach File @@ -5291,8 +4622,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -5311,7 +4642,7 @@ p, li { white-space: pre-wrap; } Vous pouvez joindre des fichiers par glisser/déposer - + Post @@ -5341,17 +4672,17 @@ p, li { white-space: pre-wrap; } - + No Forum Aucun forum - + In Reply to En réponse à - + Title Titre @@ -5405,7 +4736,7 @@ Voulez-vous annuler ce message? Charger le fichier image - + No compatible ID for this forum Pas d'ID compatible pour ce forum @@ -5415,8 +4746,8 @@ Voulez-vous annuler ce message? Aucune de vos identités n'est autorisée à poster dans ce forum. Ceci pourrait être dû à un forum qui serait limité à un cercle qui ne contient aucune de vos identités, ou à des drapeaux de forum exigeant une identité signée en PGP. - - + + Generate mass data Générer des données en masse @@ -5425,10 +4756,6 @@ Voulez-vous annuler ce message? Do you really want to generate %1 messages ? Voulez-vous vraiment générer %1 messages ? - - Send - Envoyer - Post as @@ -5443,23 +4770,7 @@ Voulez-vous annuler ce message? CreateLobbyDialog - Create Chat Lobby - Créer un salon de tchat - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - Un salon de chat est un tchat en groupe décentralisé et anonyme. Tous les participants reçoivent tous les messages. Une fois que le salon est créé, vous pouvez inviter d'autres amis à partir de l'onglet Amis. - - - Lobby name: - Nom du salon : - - - Lobby topic: - Sujet du salon : - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5494,7 +4805,7 @@ Voulez-vous annuler ce message? - + Create Créer @@ -5504,11 +4815,7 @@ Voulez-vous annuler ce message? Annuler - <html><head/><body><p>If you check this, only PGP-signed ids can be used to join and talk in this lobby. This limitation prevents anonymous spamming as it becomes possible for at least some people in the lobby to locate the spammer's node.</p></body></html> - <html><head/><body><p>Si vous cochez ceci, seules les IDs signées en PGP peuvent être utilisées pour rejoindre ce salon et y parler. Cette limitation empêche le publipostage anonyme excessif car il devient possible pour au moins quelques personnes dans ce salon de localiser le noeud du spammeur.</p></body></html> - - - + require PGP-signed identities nécessite des identités signées PGP @@ -5523,11 +4830,7 @@ Voulez-vous annuler ce message? Selectionner les amis avec qui vous voulez communiquer. - Invited friends - Amis invités - - - + Create Chat Room Créer un salon de tchat @@ -5548,7 +4851,7 @@ Voulez-vous annuler ce message? Contacts : - + Identity to use: Identité à utiliser : @@ -5556,17 +4859,17 @@ Voulez-vous annuler ce message? CryptoPage - + Public Information Information publique - + Name: Nom : - + Location: Emplacement : @@ -5576,12 +4879,12 @@ Voulez-vous annuler ce message? ID de l'emplacement : - + Software Version: Version du logiciel : - + Online since: En ligne depuis : @@ -5601,12 +4904,7 @@ Voulez-vous annuler ce message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5616,7 +4914,7 @@ Voulez-vous annuler ce message? - + Other Information Autres informations @@ -5626,17 +4924,12 @@ Voulez-vous annuler ce message? - + Profile Profil - - Certificate - Certificat - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5646,11 +4939,7 @@ Voulez-vous annuler ce message? Inclure les signatures - Save Key into a file - Enregistrer votre clé dans un fichier - - - + Export Identity Exporter l'identité @@ -5724,33 +5013,33 @@ et utiliser le bouton d'importation pour la charger - + TextLabel Etiquette - + PGP fingerprint: Empreinte PGP : - - Node information - Information de noeud - - - + PGP Id : ID PGP : - + Friend nodes: Noeuds amis - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5789,14 +5078,6 @@ et utiliser le bouton d'importation pour la charger Node Noeud - - Create new node... - Créer nouveau noeud ... - - - show statistics window - afficher la fenêtre de statistiques - DHTGraphSource @@ -5813,10 +5094,6 @@ et utiliser le bouton d'importation pour la charger DHT DHT - - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your friends to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your friends.</p> - <p>Retroshare utilise la DHT de Bittorrent comme un proxy pour les connexions. Cela ne "stocke" pas votre IP dans la DHT. Au lieu de cela, la DHT est utilisée par vos amis pour vous atteindre tout en effectuant des requêtes DHT standards. Le voyant de statut deviendra vert aussitôt que Retroshare obtiendra une réponse DHT d'un de vos amis.</p> - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your trusted nodes to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your trusted nodes.</p> @@ -5852,7 +5129,7 @@ et utiliser le bouton d'importation pour la charger DLListDelegate - + B o @@ -6520,7 +5797,7 @@ et utiliser le bouton d'importation pour la charger DownloadToaster - + Start file Ouvrir le fichier @@ -6528,38 +5805,38 @@ et utiliser le bouton d'importation pour la charger ExprParamElement - + - + to à - + ignore case Ignorer la casse - - - dd.MM.yyyy - jj.MM.aaaa + + + yyyy-MM-dd + - - + + KB Ko - - + + MB Mo - - + + GB Go @@ -6567,12 +5844,12 @@ et utiliser le bouton d'importation pour la charger ExpressionWidget - + Expression Widget Expression Widget - + Delete this expression Supprimer cette expression @@ -6734,7 +6011,7 @@ et utiliser le bouton d'importation pour la charger FilesDefs - + Picture Image @@ -6744,7 +6021,7 @@ et utiliser le bouton d'importation pour la charger Vidéo - + Audio Audio @@ -6804,11 +6081,21 @@ et utiliser le bouton d'importation pour la charger C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Dossiers partagés de mes amis @@ -6930,7 +6217,7 @@ et utiliser le bouton d'importation pour la charger - + ID ID @@ -6965,10 +6252,6 @@ et utiliser le bouton d'importation pour la charger Show State Afficher l'état - - Trusted nodes - Amis de confiance - @@ -6976,7 +6259,7 @@ et utiliser le bouton d'importation pour la charger Afficher les groupes - + Group Groupe @@ -7012,7 +6295,7 @@ et utiliser le bouton d'importation pour la charger Ajouter à un groupe - + Search Rechercher @@ -7028,7 +6311,7 @@ et utiliser le bouton d'importation pour la charger Trier par état - + Profile details Détails du profil @@ -7273,7 +6556,7 @@ au moins un contact n'a pas été ajouté au groupe FriendRequestToaster - + Confirm Friend Request Accepter la demande d'amitié @@ -7290,10 +6573,6 @@ au moins un contact n'a pas été ajouté au groupe FriendSelectionWidget - - Search : - Rechercher : - Sort by state @@ -7315,7 +6594,7 @@ au moins un contact n'a pas été ajouté au groupe Rechercher des amis - + Mark all Tout marquer @@ -7326,16 +6605,134 @@ au moins un contact n'a pas été ajouté au groupe Marquer aucun + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Nom + + + + Node ID + + + + + Address + Adresse + + + + Status + Statut + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + Devenir ami + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + Ce proxy n'est pas activé ou est cassé. +Tous les services sont-ils bien en marche ? +Vérifiez aussi vos ports ! + + FriendsDialog - + Edit status message Modifier le message d'état - - + + Broadcast Tchat entre amis @@ -7418,33 +6815,38 @@ au moins un contact n'a pas été ajouté au groupe Réinitialiser à la valeur par défaut - + Keyring Trousseau - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Réseau</h1> <p>L'onglet réseau montre les noeuds de vos amis Retroshare : les noeuds Retroshare voisins qui sont connectés à vous.</p> <p>Vous pouvez grouper les noeuds ensemble pour permettre un niveau d'accès plus fin à l'information, par exemple pour permettre seulement à quelques noeuds de voir vos fichiers.</p> <p>Sur la droite, vous trouverez 3 onglets utiles : <ul> <li>Tchat entre amis (en anglais : "broadcast") : diffuse les messages immédiatement à tous les noeuds amis connectés</li> <li>Graphe réseau : ce graphe montre le réseau autours de vous, en se basant sur l'information de découverte</li> <li>Trousseau : contient les clés des noeuds que vous avez collecté, elles sont transférées jusqu'à vous principalement par les noeuds de vos amis</li> </ul> </p> - - - + Retroshare broadcast chat: messages are sent to all connected friends. Retroshare broadcast chat : les messages sont envoyés à tous vos amis en ligne. - - + + Network Réseau - + + Friend Server + + + + Network graph Graphe réseau - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. Mettez ici votre message de statut. @@ -7462,7 +6864,17 @@ au moins un contact n'a pas été ajouté au groupe Mot de passe - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters Tous les champs sont requis avec un minimum de 3 caractères @@ -7472,17 +6884,12 @@ au moins un contact n'a pas été ajouté au groupe Les mots de passe ne correspondent pas - + Port Port - - Use BOB - Utiliser BOB - - - + This password is for PGP Ce mot de passe est pour PGP @@ -7503,50 +6910,38 @@ au moins un contact n'a pas été ajouté au groupe Échec lors de la génération de votre nouveau certificat, peut-être que votre mot de passe PGP est faux ! - Options - Options - - - + PGP Key Length Longueur de la clé PGP - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> <html><head/><body><p>Mettez un mot de passe fort ici. Ce mot de passe protège votre clé privée!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> <html><head/><body><p>S'il vous plaît déplacer votre souris afin de recueillir autant de données aléatoires que possible. Un minimum de 20% est nécessaire pour créer votre clé d'emplacement</p></body></html> - + Standard node Emplacement standard - TOR/I2P Hidden node - Emplacement Caché TOR/I2P - - - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> <html><head/><body><p>Votre nom d'emplacement désigne l'instance de Retroshare exécutée sur cet ordinateur.</p></body></html> - Use existing profile - Utiliser un profil existant - - - + Node name Nom de l'emplacement - + Node type: @@ -7566,14 +6961,14 @@ au moins un contact n'a pas été ajouté au groupe - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> <html><head/><body><p>Le nom du profil vous identifie sur le réseau. Il est utilisé par vos amis pour accepter vos connexions. Vous pouvez créer plusieurs emplacement Retroshare avec le même profil sur différents ordinateurs.</p></body></html> - + Export this profle Exporter ce profil @@ -7583,7 +6978,7 @@ Vous pouvez créer plusieurs emplacement Retroshare avec le même profil sur dif - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> <html><head/><body><p>Cela doit être une adresse Tor Onion de la forme: xa76giaf6ifda7ri63i263.onion <br/>ou une addresse I2P de cette forme: [52 characters].b32.i2p @@ -7592,39 +6987,40 @@ Pour en obtenir une, vous devez configurer Tor ou I2P pour créer un nouveau tun Vous pouvez également laisser ce champ vide, mais votre nœud ne fonctionnera que si vous définissez correctement l'adresse de service Tor / I2P dans le panneau de configuration Préférences -&gt; Réseaux -&gt; Configuration Hidden Service.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> <html><head/><body><p>Les identités sont utilisées lorsque vous écrivez dans des salons de tchat, des forums et des commentaires de chaîne. Ils reçoivent/envoient également du courrier électronique sur le réseau Retroshare. Vous pouvez créer une identité signée maintenant, ou le faire plus tard lorsque vous en aurez besoin.</p></body></html> - + Go! C'est parti ! - - + + TextLabel Étiquette - Advanced options - Options avancées - - - + hidden address adresse cachée - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. Votre profil est associé à une paire de clé PGP. Actuellement RetroShare ignore les clés DSA. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> <html><head/><body><p>Ceci est votre port de connexion.</p><p>N'importe quelle valeur entre 1024 et 65535 </p><p> devrait être OK. Il vous sera possible de la changer plus tard.</p></body></html> @@ -7672,13 +7068,13 @@ et l'utiliser au moyen du bouton d'importation afin de le chargerVotre profil n'a pas été sauvegardé. Une erreur est arrivée. - + Import profile Importer profil - + Create new profile and new Retroshare node Créer un nouveau profil et un nouveau emplacement Retroshare @@ -7688,7 +7084,7 @@ et l'utiliser au moyen du bouton d'importation afin de le chargerCréer un nouveau emplacement Retroshare - + Tor/I2P address Adresse Tor/I2P @@ -7723,7 +7119,7 @@ et l'utiliser au moyen du bouton d'importation afin de le charger - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7733,12 +7129,7 @@ et l'utiliser au moyen du bouton d'importation afin de le charger - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> <p>La création du nœud est désactivée jusqu'à ce que les champs soient correctement remplis.</p> @@ -7748,12 +7139,7 @@ et l'utiliser au moyen du bouton d'importation afin de le charger<p>La création du nœud est désactivée jusqu'à ce que suffisamment d'éléments aléatoires soient collectés. Veuillez déplacer votre souris jusqu'à ce que vous atteigniez au moins 20%.</p> - - I2P instance address with BOB enabled - Adresse d'instance I2P avec BOB activé - - - + I2P instance address Adresse d'instance I2P @@ -7979,36 +7365,13 @@ et l'utiliser au moyen du bouton d'importation afin de le chargerMise en route - + Invite Friends Inviter des amis - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:12pt;">Retroshare n'est rien sans vos amis. Cliquez sur le bouton pour démarrer le procédure</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:12pt;">Envoyez à vos amis un email avec votre "certificat d'identité".</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:12pt;">Soyez sur de recevoir leur invitation en retour... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:12pt;">Vous ne pouvez vous connecter avec vos amis que si vous vous êtes mutuellement ajoutés les uns aux autres.</span></p></body></html> - - - + Add Your Friends to RetroShare Ajouter vos amis à Retroshare @@ -8018,136 +7381,103 @@ p, li { white-space: pre-wrap; } Ajouter des amis - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Soyez en ligne en même temps que vos amis et ainsi RetroShare vous connectera automatiquement !</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Votre client a besoin de trouver le réseau RetroShare avant qu'il ne soit capable d'effectuer des connexions.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Cela prend 5 à 30 minutes la première fois que vous démarrez RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">L'indicateur DHT (dans la barre de statut) se colorera en vert lorsqu'il pourra effectuer des connexions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Après deux minutes , l'indicateur NAT (aussi situé dans la barre de statut) se colorera en jaune ou en vert.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Si il reste en rouge, alors vous avez un pare-feu ennuyeux, que RetroShare ne parvient pas à traverser.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Regardez dans la section "Davantage d'aide" pour plus de conseils de connexion.</span></p></body></html> + + Connect To Friends + Se connecter aux amis - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Vous pouvez augmenter la performance de votre Retroshare en ouvrant un port externe. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Cela va augmenter la vitesse des connexions et permettre à davantage de personnes de se connecter à vous. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">La façon la plus facile de faire cela consiste à activer UPnP dans votre box Sans-fil ou Routeur.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Comme chaque routeur est conçu différemment, vous devrez découvrir votre modèle de routeur et rechercher dans Internet afin de trouver des instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Si rien de tout ceci ne vous paraît évident, ne vous inquiétez pas Retroshare marchera malgré tout.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Avancé : ouvrir un port dans le pare-feu <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Rencontrez vous des difficultés pour débuter avec RetroShare ?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Lisez la FAQ située dans le Wiki. Elle est un peu vieille, nous essayons de l'actualiser.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Regardez les forums en ligne. Posez des questions et discutez des fonctionnalités.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Essayez les forums internes à RetroShare </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - Ceux-ci arriveront en ligne lorsque vous serez connecté à des amis.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) Si vous êtes encore bloqué, écrivez-nous.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Appréciez Retroshare</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> + - - Connect To Friends - Se connecter aux amis - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Quand vos amis vous envoient leurs invitations, cliquez pour ouvrir la fenêtre Ajout d'amis.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Collez les &quot;Certificats ID&quot; de vos amis dans la fenêtre puis ajoutez-les comme amis.</span></p></body></html> - - - - Advanced: Open Firewall Port - Avancé : ouvrir un port dans le pare-feu - - - + Further Help and Support Aide supplémentaire et support - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website Ouvrir le site web de RS @@ -8172,7 +7502,7 @@ p, li { white-space: pre-wrap; } Commentaires par email - + RetroShare Invitation Invitation Retroshare @@ -8222,12 +7552,12 @@ p, li { white-space: pre-wrap; } Retour-utilisateur Retroshare - + RetroShare Support Aide Retroshare - + It has many features, including built-in chat, messaging, Il a de nombreuses fonctionnalités, telles qu'un tchat intégré, messagerie, @@ -8351,7 +7681,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat Afficher le Tchat public @@ -8359,7 +7689,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] [Inconnu] @@ -8525,19 +7855,11 @@ p, li { white-space: pre-wrap; } You can let your friends know about your forum by sharing it with them. Select the friends with which you want to share your forum. Vous pouvez laisser vos amis prendre connaissance de votre forum en le partageant avec eux. Choisissez les amis avec lesquels vous voulez partager votre forum. - - Share topic admin permissions - Partager les permissions d'administration de sujet - - - You can allow your friends to edit the topic. Select them in the list below. Note: it is not possible to revoke Posted admin permissions. - Vous pouvez permettre à vos amis d'éditer le sujet. Choisissez-les dans la liste ci-dessous. Note : il n'est pas possible de révoquer des permissions d'administration Postées (Posted admin permissions). - GroupTreeWidget - + Title Titre @@ -8550,12 +7872,12 @@ p, li { white-space: pre-wrap; } - + Description Description - + Number of Unread message @@ -8580,35 +7902,7 @@ p, li { white-space: pre-wrap; } - Sort Descending Order - Trier Ordre décroissant - - - Sort Ascending Order - Trier Ordre croissant - - - Sort by Name - Trier par nom - - - Sort by Popularity - Trier par popularité - - - Sort by Last Post - Trier par dernier message - - - Sort by Number of Posts - Trier par quantité de messages - - - Sort by Unread - Trier par Non lus - - - + You are admin (modify names and description using Edit menu) Vous êtes administrateur (modifiez les noms et la description en utilisant le menu Edition) @@ -8623,14 +7917,14 @@ p, li { white-space: pre-wrap; } Id - - + + Last Post Dernier commentaire - + Name Nom @@ -8641,17 +7935,13 @@ p, li { white-space: pre-wrap; } Popularité - + Never Jamais - Display - Affichage - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8664,7 +7954,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and et @@ -8800,7 +8090,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels Chaînes @@ -8811,34 +8101,22 @@ p, li { white-space: pre-wrap; } Créer une chaîne - + Enable Auto-Download Activer le téléchargement automatique - + My Channels Vos chaînes - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Chaînes</h1> <p>Les chaînes vous permettent de poster des données (exemples : films, musiques) qui seront diffusées dans le réseau - -Vous pouvez voir les chaînes auxquelles sont abonnés vos amis, et vous transférez automatiquement à vos amis les chaînes auxquelles vous êtes abonné. Ceci promeut les bonnes chaînes dans le réseau. - -Seul le créateur d'une chaîne peut poster dans cette chaîne. Les autres personnes dans le réseau peuvent seulement lire dedans, à moins que la chaîne ne soit privée. Vous pouvez cependant partager les droits de poster ou de lire avec vos amis Retroshare. - -Les chaînes peuvent être anonymes, ou attachées à une identité Retroshare afin que les lecteurs puissent prendre contact avec vous si besoin. Permettez "Autoriser commentaires" si vous voulez laisser la possibilité aux utilisateurs de commenter vos postages. - -Les publications sont conservés pendant %1 jours et synchronisés au cours des derniers %2 jours, à moins que vous ne les modifiez.</p> - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Chaînes abonnées @@ -8858,12 +8136,12 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Spécifier le répertoire de téléchargement pour cette chaîne - + Disable Auto-Download Désactiver le téléchargement automatique - + Set download directory Spécifier le répertoire de téléchargement @@ -8898,22 +8176,22 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des - + Play - + Open folder Ouvrir dossier - + Open file - + Error Erreur @@ -8933,17 +8211,17 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Vérification - + Are you sure that you want to cancel and delete the file? Êtes-vous sûr(e) de vouloir annuler et supprimer ce fichier ? - + Can't open folder Impossible d'ouvrir le dossier - + Play File Lecture @@ -8953,37 +8231,10 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Le fichier %1 n'existe pas à cet endroit. - - GxsChannelFilesWidget - - Form - Formulaire - - - Filename - Nom du fichier - - - Size - Taille - - - Title - Titre - - - Published - Publié - - - Status - Statut - - GxsChannelGroupDialog - + Create New Channel Créer une nouvelle chaîne @@ -9021,9 +8272,19 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des GxsChannelGroupItem - - Subscribe to Channel - S'abonner à la chaîne + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel + @@ -9037,7 +8298,7 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des - + Expand Étendre @@ -9052,7 +8313,7 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Description de la chaîne - + Loading Chargement @@ -9067,8 +8328,9 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des - New Channel - Nouvelle chaîne + + Never + Jamais @@ -9079,7 +8341,7 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des GxsChannelPostItem - + New Comment: Nouveau commentaire : @@ -9100,7 +8362,7 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des - + Play Lecture @@ -9156,28 +8418,24 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Files Fichiers - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - Avertissement ! Vous avez moins de %1 heure(s) et %2 minute(s) avant que ce fichier ne soit supprimé. Pensez à l'enregistrer. - Hide Cacher - + New Nouveau - + 0 0 - - + + Comment Commentaire @@ -9192,21 +8450,17 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Je n'aime pas ça - Loading - Chargement - - - + Loading... - + Comments Commentaires - + Post @@ -9231,139 +8485,16 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Lire le média - - GxsChannelPostsWidget - - Post to Channel - Poster dans la chaîne - - - Add new post - Ajouter une nouvelle publication - - - Loading - Chargement - - - Search channels - Chercher chaînes - - - Title - Titre - - - Search Title - Chercher titre - - - Message - Message - - - Search Message - Chercher message - - - Filename - Nom du fichier - - - Search Filename - Chercher nom de fichier - - - No Channel Selected - Aucune chaîne sélectionnée - - - Never - Jamais - - - Public - Public - - - Restricted to members of circle " - Limité aux membres du cercle " - - - Restricted to members of circle - Limité aux membres du cercle - - - Your eyes only - Vos yeux seulement - - - You and your friend nodes - Vous et vos noeuds amis - - - Disable Auto-Download - Désactiver le téléchargement automatique - - - Enable Auto-Download - Activer le téléchargement automatique - - - Show feeds - Afficher les flux - - - Show files - Afficher les fichiers - - - Administrator: - Administrateur : - - - Last Post: - Dernier message : - - - unknown - inconnu - - - Distribution: - Distribution : - - - Feeds - Flux - - - Files - Fichiers - - - Subscribers - Abonnés - - - Description: - Description : - - - Posts (at neighbor nodes): - Posts (chez vos noeuds voisins) : - - GxsChannelPostsWidgetWithModel - + Post to Channel Poster dans la chaîne - + Add new post Ajouter une nouvelle publication @@ -9433,7 +8564,7 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des - Posts (locally / at friends): + Items (locally / at friends): @@ -9469,7 +8600,7 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des - + Comments Commentaires @@ -9484,13 +8615,13 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Flux - - + + Click to switch to list view - + Show unread posts only @@ -9505,7 +8636,7 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des - + No text to display @@ -9520,7 +8651,7 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des - + Switch to list view @@ -9580,12 +8711,22 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -9660,12 +8801,13 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Vous et vos noeuds amis - + + Copy Retroshare link - + Subscribed Abonné @@ -9716,17 +8858,17 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -9746,27 +8888,11 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Remove Item Supprimer - - for identity - pour l'identité - - - You received a membership request for circle: - Vous avez reçu une demande d'adhésion pour le cercle: - Grant membership request Demande d'adhésion - - Revoke membership request - Révoquer la demande d'adhésion - - - You received an invitation for circle: - Vous avez reçu une invitation pour le cercle: - @@ -9857,7 +8983,7 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des GxsCommentContainer - + Comment Container Le conteneur de commentaires @@ -9870,7 +8996,7 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Formulaire - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9900,7 +9026,7 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Rafraîchir - + Comment Commentaire @@ -9939,7 +9065,7 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des GxsCommentTreeWidget - + Reply to Comment Répondre au commentaire @@ -9963,6 +9089,21 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Vote Down Voter - + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9972,7 +9113,7 @@ Les publications sont conservés pendant %1 jours et synchronisés au cours des Commenter - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -10001,26 +9142,10 @@ p, li { white-space: pre-wrap; } - + Post - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Commentaire</span></p></body></html> - - - Signed by - Signé par - Reply to Comment @@ -10049,7 +9174,7 @@ before you can comment avant de pouvoir commenter - + It remains %1 characters after HTML conversion. @@ -10091,14 +9216,6 @@ avant de pouvoir commenter Forum moderators can edit/delete/pinup others posts - - Add Forum Admins - Ajouter admins de forum - - - Select Forum Admins - Sélectionner admins de forum - Create @@ -10108,7 +9225,7 @@ avant de pouvoir commenter GxsForumGroupItem - + Subscribe to Forum S'abonner au forum @@ -10124,7 +9241,7 @@ avant de pouvoir commenter - + Expand Montrer @@ -10144,8 +9261,9 @@ avant de pouvoir commenter - Loading - Chargement + + TextLabel + @@ -10176,13 +9294,13 @@ avant de pouvoir commenter GxsForumMsgItem - - + + Subject: Sujet : - + Unsubscribe To Forum Se désabonner du forum @@ -10193,7 +9311,7 @@ avant de pouvoir commenter - + Expand Montrer @@ -10213,21 +9331,17 @@ avant de pouvoir commenter En réponse à : - Loading - Chargement - - - + Loading... - + Forum Feed Flux de forum - + Hide Cacher @@ -10240,63 +9354,66 @@ avant de pouvoir commenter Formulaire - + Start new Thread for Selected Forum Lancer un nouveau fil dans le forum sélectionné - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Chercher - Last Post - Dernier article - - - + New Thread Nouveau fil - - - Threaded View - Affichage en arborescence - - - - Flat View - Affichage à plat - - + Title Titre - - + + Date Date - + Author Auteur - - Save image - Sauvegarder image - - - + Loading Chargement - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -10306,12 +9423,7 @@ avant de pouvoir commenter - - Lastest post in thread - - - - + Reply Message Répondre au message @@ -10335,10 +9447,6 @@ avant de pouvoir commenter Download all files Télécharger tous les fichiers - - Next unread - Suivant non lu - Search Title @@ -10355,36 +9463,23 @@ avant de pouvoir commenter Rechercher par auteur - Content - Contenu - - - Search Content - Rechercher contenu - - - <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - <p>L'abonnement au forum rassemblera les messages disponibles à partir de vos amis qui y sont abonnés et rendra le forum visible à tous vos autres amis. -Ensuite vous pourrez vous désabonner via le menu contextuel de la liste des forums à gauche.</p> - - - + No name Aucun nom - - + + Reply Répondre - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -10427,20 +9522,12 @@ Ensuite vous pourrez vous désabonner via le menu contextuel de la liste des for Copier le lien Retroshare - + Hide Cacher - Expand - Montrer - - - [Banned] - [Banni] - - - + [unknown] [inconnu] @@ -10470,8 +9557,8 @@ Ensuite vous pourrez vous désabonner via le menu contextuel de la liste des for Vos yeux seulement - - + + Distribution Distribution @@ -10485,26 +9572,6 @@ Ensuite vous pourrez vous désabonner via le menu contextuel de la liste des for Anti-spam Anti-spam - - [ ... Redacted message ... ] - [ ... Message rédigé ... ] - - - Anonymous - Anonyme - - - signed - Signé - - - none - Aucun - - - [ ... Missing Message ... ] - [ ... Message manquant... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10574,16 +9641,12 @@ Ensuite vous pourrez vous désabonner via le menu contextuel de la liste des for Message d'origine - + New thread Nouveau fil - Read status - Lire l'état - - - + Edit Modifier @@ -10644,7 +9707,7 @@ Ensuite vous pourrez vous désabonner via le menu contextuel de la liste des for Réputation de l'auteur - + Show column @@ -10664,7 +9727,7 @@ Ensuite vous pourrez vous désabonner via le menu contextuel de la liste des for - + Anonymous/unknown posts forwarded if reputation is positive Messages anonymes / inconnus transmis si la réputation est positive @@ -10716,7 +9779,7 @@ This message is missing. You should receive it later. - + No result. @@ -10726,7 +9789,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -10741,26 +9804,7 @@ This message is missing. You should receive it later. - Information for this identity is currently missing. - Les informations pour cette identité sont actuellement manquantes. - - - You have banned this ID. The message will not be -displayed nor forwarded to your friends. - Vous avez banni cet ID. Le message ne sera pas affiché ou transmis à vos amis. - - - You have not set an opinion for this person, - and your friends do not vote positively: Spam regulation -prevents the message to be forwarded to your friends. - Vous n'avez pas donné d'opinion pour cette personne et vos amis ne votent pas positivement: La régulation du spam empêche le message d'être transmis à vos amis. - - - Message will be forwarded to your friends. - Le message sera transmis à vos amis. - - - + (Latest) (Derniers) @@ -10769,10 +9813,6 @@ prevents the message to be forwarded to your friends. (Old) (Anciens) - - You cant act on the author to a non-existant Message - Vous ne pouvez pas agir sur l'auteur pour un message inexistant - From @@ -10830,14 +9870,12 @@ prevents the message to be forwarded to your friends. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Les forums de Retroshare ressemblent aux forums d'internet, mais ils fonctionnent de façon décentralisée. -Vous voyez les forums auxquels sont abonnés vos amis, et vous transférez à vos amis les forums auxquels vous vous êtes abonné. Ceci promeut automatiquement dans le réseau les forums intéressants. -Les messages du forum sont conservés pour %1 jours et synchronisés au cours des derniers %2 jours, à moins que vous ne les configuriez autrement.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> + - + Forums Forums @@ -10868,35 +9906,16 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de Autres forums - - GxsForumsFillThread - - Waiting - En attente - - - Retrieving - Récupération - - - Loading - Chargement - - GxsGroupDialog - + Name Nom - Add Icon - Ajouter une icône - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels Ceux avec qui vous partagez votre clé peuvent publier sur les types de groupe à accès limité, et peuvent voir et publier sur les chaines à accès privé @@ -10905,22 +9924,14 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de Share Publish Key Partager la clé de publication - - check peers you would like to share private publish key with - Visualiser les personnes avec qui vous partagez votre clé de publication privée - - - Share Key With - Clé partagée avec - - + Description Description - + Message Distribution Distribution de message @@ -10928,7 +9939,7 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de - + Public Public @@ -10947,14 +9958,6 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de New Thread Nouveau fil - - Required - Requis - - - Encrypted Msgs - Msgs chiffrés - Personal Signatures @@ -10996,7 +9999,7 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de Protection Spam - + Comments: Commentaires : @@ -11019,7 +10022,7 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de Anti-spam : - + All People @@ -11035,12 +10038,12 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de - + Restricted to circle: Limité au groupe : - + Limited to your friends Limité à vos amis @@ -11057,23 +10060,23 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de - + Message tracking Suivi de message - - + + PGP signature required Signature PGP requise - + Never Jamais - + Only friends nodes in group Seulement les noeuds d'amis dans le groupe @@ -11089,30 +10092,28 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de Veuillez ajoutez un nom - + PGP signature from known ID required La signature PGP de l'ID connue est exigée - + + + [None] + + + + Load Group Logo Charger le logo du groupe - + Submit Group Changes Soumettre des changements de groupe - Failed to Prepare Group MetaData - please Review - Echec à préparer les méta-données de groupe - veuillez examiner - - - Will be used to send feedback - Sera utilisé pour envoyer du retour d'information - - - + Owner: Propriétaire : @@ -11122,12 +10123,12 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de Mettez ici une description descriptive - + Info Info - + ID ID @@ -11137,7 +10138,7 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de Dernier article - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> <html><head/><body><p>Les messages se propageront bien au-delà de vos nœuds amis, à condition que les gens s'abonnent à la chaîne, au forum ou à la publication que vous créez.</p></body></html> @@ -11212,7 +10213,12 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de Défavoriser les IDs non signées et les IDs issues de noeuds inconnus - + + Author: + + + + Popularity Popularité @@ -11228,27 +10234,22 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de - + Created - + Cancel Annuler - + Create Créer - - Author - Auteur - - - + GxsIdLabel GxsIdLabel @@ -11256,7 +10257,7 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de GxsGroupFrameDialog - + Loading Chargement @@ -11316,7 +10317,7 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de Modifier détails - + Synchronise posts of last... Synchronisation des derniers messages... @@ -11373,16 +10374,12 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de - + Search for - Share publish permissions - Partager les permissions de publication - - - + Copy RetroShare Link Copier le lien Retroshare @@ -11405,7 +10402,7 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de GxsIdChooser - + No Signature Sans signature @@ -11418,40 +10415,24 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de GxsIdDetails - Loading - Chargement - - - + Not found Non trouvé - - No Signature - Sans signature - - - + + [Banned] [Banni] - - Authentication - Authentification - unknown Key clé inconnue - anonymous - anonyme - - - + Loading... @@ -11461,7 +10442,12 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de - + + [Nobody] + + + + Identity&nbsp;name Nom&nbsp;d'identité @@ -11475,16 +10461,20 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de Node Noeud - - Signed&nbsp;by - Signé&nbsp;par - [Unknown] [Inconnu] + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -11496,7 +10486,7 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de GxsIdStatisticsWidget - + Total identities: @@ -11544,17 +10534,13 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de GxsIdTreeItemDelegate - + [Unknown] [Inconnu] GxsMessageFramePostWidget - - Loading - Chargement - Loading... @@ -11671,10 +10657,6 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de Group ID / Author ID du groupe / Auteur - - Number of messages / Publish TS - Nombre de message / Tampon Horaire de publication (TS) - Local size of data @@ -11690,10 +10672,6 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de Popularity Popularité - - Details - Détails - @@ -11726,41 +10704,6 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de Non - - GxsTunnelsDialog - - Authenticated tunnels: - Tunnels authentifiés : - - - Tunnel ID: %1 - ID de tunnel : %1 - - - from: %1 - depuis : %1 - - - to: %1 - vers : %1 - - - status: %1 - statut : %1 - - - total sent: %1 bytes - total envoyé : %1 octets - - - total recv: %1 bytes - total reçu : %1 octets - - - Unknown Peer - Pair inconnu - - HashBox @@ -11973,48 +10916,12 @@ Les messages du forum sont conservés pour %1 jours et synchronisés au cours de About À propos - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare provides file sharing, chat, messages and channels</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Useful external links to more information:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Wiki</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare's Forum</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Project Page</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Team Blog</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Dev Twitter</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare est une plateforme de communication décentalisée, sécurisée et privée, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">elle est open-source et trans-plateformes. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Elle vous laisse partager avec vos amis de façon sécurisée, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">en utilisant un web-de-confiance (web-of-trust) pour authentifier les pairs, et OpenSSL pour chiffrer toutes les communications. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare permet partage de fichiers, tchat, messages, et chaînes</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Liens externes utiles pour davantage d'information :</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Wiki</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Forum de RetroShare</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Page du projet Retroshare</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Blog de l'équipe RetroShare</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Twitter de dév RetroShare</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -12030,7 +10937,7 @@ p, li { white-space: pre-wrap; } - + Authors Auteurs @@ -12049,7 +10956,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -12062,36 +10969,6 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Daniel Wester</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">wester@speedmail.se</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">German: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Jan</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Keller</span><span style=" font-family:'MS Shell Dlg 2';"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">trilarion@users.sourceforge.net</span><span style=" font-family:'MS Shell Dlg 2';">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Traductions RetroShare :</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Traducteurs du site web de RetroShare :</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Suédois : </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Daniel Wester</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">wester@speedmail.se</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Allemand : </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Jan</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Keller</span><span style=" font-family:'MS Shell Dlg 2';"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">trilarion@users.sourceforge.net</span><span style=" font-family:'MS Shell Dlg 2';">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polonais : </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - License Agreement @@ -12157,12 +11034,12 @@ p, li { white-space: pre-wrap; } Formulaire - + <html><head/><body><p>Copy your RetroShare ID to clipboard</p></body></html> - + Add friend @@ -12177,7 +11054,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -12186,32 +11063,12 @@ p, li { white-space: pre-wrap; } This is your Retroshare ID. Copy and share with your friends! - - Did you receive a certificate from a friend? - Avez-vous reçu le certificat d'un ami ? - - - Add friends certificate - Ajouter le certificat d'un ami - - - Add certificate file - Ajouter un fichier de certificat - - - Share your RetroShare Key - Partagez votre clé RetroShare - ... ... - - The text below is your own Retroshare certificate. Send it to your friends - Le texte ci-dessous est votre propre certificat Retroshare. Envoyez-le à vos amis - Open Source cross-platform, @@ -12222,20 +11079,12 @@ Plate-forme de communication décentralisée privée et sécurisée. - Launch startup wizard - Lancez l'assistant de démarrage - - - Do you need help with RetroShare? - Besoin d'aide avec RetroShare? - - - + Open Web Help Ouvrir l'aide Web - + Copy your Cert to Clipboard Copiez votre Certificat en mémoire. @@ -12245,7 +11094,7 @@ Plate-forme de communication décentralisée privée et sécurisée. Sauvez votre Certificat dans un fichier - + Send via Email Envoyez votre Certificat par e-mail @@ -12265,13 +11114,37 @@ Plate-forme de communication décentralisée privée et sécurisée. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -12283,17 +11156,12 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -12302,19 +11170,11 @@ new short format Your Retroshare ID is copied to Clipboard, paste and send it to your friend via email or some other way - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your certificate on this page and send it to friends, and add your friends' certificate.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange certificates with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Bienvenu sur Retroshare!</h1> <p>Vous devez <b>vous faire des amis</b>! Une fois que vous avez créé un réseau d'amis, ou que vous vous êtes joint à un réseau existant, vous pourrez échanger des fichiers, discuter, parler dans des forums, etc.</p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> Pour ce faire, copier votre certificat dans cette page et l'envoyer à vos amis. Ensuite, ajouter le certificat de vos amis.<p> <p>Une autre option est de rechercher sur Internet des "Retroshare chat servers" (administré indépendamment ). Ces serveurs vous permettent d'échanger votre certificat avec un emplacement Retroshare dédié, grâce auquel vous pourrez rencontrer d'autres personnes anonymement.</p> - RetroShare Invite Invitation Retroshare - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Votre certificat a été copié en mémoire, collez-le et envoyez-le par courrier électronique ou par tout autre moyen - Save as... @@ -12586,14 +11446,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Tout - + Reputation Réputation @@ -12603,12 +11463,12 @@ p, li { white-space: pre-wrap; } Rechercher - + Anonymous Id ID anonyme - + Create new Identity Créer une nouvelle identité @@ -12618,7 +11478,7 @@ p, li { white-space: pre-wrap; } Créer un nouveau cercle - + Persons Personnes @@ -12633,27 +11493,27 @@ p, li { white-space: pre-wrap; } Personne - + Close Fermer - + Ban-option: Option de "ban" : - + Auto-Ban all identities signed by the same node Bannir automatiquement toutes les identités signées par la même personne - + Friend votes: Votes des Amis : - + Positive votes Votes positifs @@ -12670,29 +11530,39 @@ p, li { white-space: pre-wrap; } Votes négatifs - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics Statistiques d'utilisation - + Circles Cercles - + Circle name Nom du cercle @@ -12712,18 +11582,20 @@ Votes négatifs Cercles personnels - + + Edit identity Modifier l'identité - + + Delete identity Supprimer l'identité - + Chat with this peer Tchater avec ce pair @@ -12733,78 +11605,78 @@ Votes négatifs Lancer un tchat distant avec ce pair - + Owner node ID : ID du noeud propriétaire : - + Identity name : Nom de l'identité : - + () () - + Identity ID ID de l'identité - + Send message Envoyer message - + Identity info Info d'identité - + Identity ID : ID de l'identité : - + Owner node name : Nom du noeud propriétaire : - + Create new... Créer nouveau... - + Type: Type : - + Send Invite Envoyer invitation - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> <html><head/><body><p>Moyenne des avis des noeuds voisins concernant cette identité. Négatif est mauvais,</p><p> positif est bon. Zéro est neutre.</p></body></html> - + Your opinion: Votre opinion : - + Negative Négative - + Neutral Neutre @@ -12815,17 +11687,17 @@ Votes négatifs Positive - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> <html><head/><body><p>Le score de réputation global, représenté (accounting) pour vous et vos amis</p><p>Négatif est mauvais, positif est bon. Zéro est neutre. Si le score est trop bas,</p><p> l'identité est indiquée comme néfaste et sera filtrée dans les forums, les salons de tchat,</p><p> les chaînes, etc.</p></body></html> - + Overall: Générale : - + Anonymous Anonymes @@ -12840,24 +11712,24 @@ Votes négatifs Chercher ID - + This identity is owned by you Cette identité est possédée par vous-même - - + + My own identities Mes propres identités - - + + My contacts Mes contacts - + Show Items Options d'affichage @@ -12872,7 +11744,12 @@ Votes négatifs Lié à mon noeud - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles Autres cercles @@ -12882,7 +11759,7 @@ Votes négatifs Cercles auxquels j'appartient - + Circle ID: ID du cercle : @@ -12957,7 +11834,7 @@ Votes négatifs Pas un membre (n'a pas d'accès aux données limitées à ce cercle) - + Identity ID: ID de l'identité : @@ -12987,7 +11864,7 @@ Votes négatifs inconnu - + Invited Invité(e) @@ -13002,7 +11879,7 @@ Votes négatifs Membre - + Edit Circle Modifier le cercle @@ -13050,7 +11927,7 @@ Votes négatifs Autoriser à adhérer - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -13061,7 +11938,7 @@ Vous devriez vous en débarrasser maintenant et en utiliser une nouvelle. Ces identités ne seront bientôt plus supportées. - + [Unknown node] [Noeud inconnu] @@ -13104,7 +11981,7 @@ Ces identités ne seront bientôt plus supportées. Identité anonyme - + Boards @@ -13184,7 +12061,7 @@ Ces identités ne seront bientôt plus supportées. - + information information @@ -13200,34 +12077,12 @@ Ces identités ne seront bientôt plus supportées. Copier identité vers le presse-papiers - Send invite? - Envoyer invitation ? - - - Do you really want send a invite with your Certificate? - Voulez-vous vraiment envoyer une invitation avec votre certificat ? - - - + Banned Banni - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identités</h1> <p>Dans cet onglet vous pouvez créer/éditer des <b>identités pseudo-anonymes</b>, et des <b>cercles</b>. -<p><b>Les identités</b> sont utilisés pour identifier vos données de manière sécurisée : signez les messages dans les salons de tchat, les messages de forum et de canal, recevez des commentaires à l'aide du système de messagerie intégré Retroshare, publiez des commentaires après les messages de canaux, discutez en utilisant des tunnels sécurisés, etc.</p> -<p>Les identités peuvent éventuellement être <b>signées</b> par le certificat de votre emplacement Retroshare. Les identités signées sont plus faciles à faire confiance mais sont facilement liées à l'adresse IP de votre nœud.</p> -<p><b>Les Identités anonymes</b> vous permettent d'interagir anonymement avec d'autres utilisateurs. Ils ne peuvent pas être falsifiés, mais personne ne peut prouver qui possède vraiment une identité donnée.</p> - <p><b>Les Cercles </b> sont des groupes d'identités (anonymes ou signés), qui sont partagés à distance sur le réseau. Ils peuvent être utilisés pour restreindre la visibilité aux forums, chaînes, etc.</p> - <p>Un <b>cercle</b> peut être restreint à un autre cercle, limitant ainsi sa visibilité aux membres de ce cercle ou même auto-restreint, ce qui signifie qu'il est seulement visible pour les membres invités.</p> - - - Unknown ID: - ID inconnu : - - - + positive positif @@ -13271,19 +12126,11 @@ Ces identités ne seront bientôt plus supportées. Forums Forums - - Posted - Publié - Chat Tchat - - Unknown - Inconnu - [Unknown] @@ -13304,14 +12151,6 @@ Ces identités ne seront bientôt plus supportées. Creation of author signature in service %1 Création d'une signature d'auteur en service %1 - - Message/vote/comment - Message/vote/commentaire - - - %1 in %2 tab - %1 en %2 onglet - Distant message signature validation. @@ -13332,19 +12171,11 @@ Ces identités ne seront bientôt plus supportées. Signature in distant tunnel system. Signature dans un système de tunnel distant. - - Update of identity data. - Mise à jour des données d'identité. - Generic signature validation. Validation de signature générique. - - Generic signature. - Signature générique. - Generic encryption. @@ -13356,11 +12187,7 @@ Ces identités ne seront bientôt plus supportées. Déchiffrement générique. - Membership verification in circle %1. - Vérification de l'adhésion dans le cercle %1. - - - + Add to Contacts Ajouter aux contacts @@ -13410,21 +12237,21 @@ Ces identités ne seront bientôt plus supportées. Salut,<br>je voudrais être ami avec vous sur RetroShare. <br> - - - + + + People Pers. - + Your Avatar Click here to change your avatar Votre avatar - + Linked to neighbor nodes Liée(s) aux noeuds voisins @@ -13434,7 +12261,7 @@ Ces identités ne seront bientôt plus supportées. Liée(s) aux noeuds distants - + Linked to a friend Retroshare node Liée(s) à un noeud Retroshare ami @@ -13449,7 +12276,7 @@ Ces identités ne seront bientôt plus supportées. Liée(s) à un noeud Retroshare inconnu - + Chat with this person Tchater avec cette personne @@ -13464,12 +12291,12 @@ Ces identités ne seront bientôt plus supportées. Tchat distant avec cette personne refusé - + Last used: Dernièrement utilisée : - + +50 Known PGP +50 PGP connue @@ -13489,12 +12316,12 @@ Ces identités ne seront bientôt plus supportées. Voulez-vous vraiment supprimer cette identité ? - + Owned by Possédé par - + Node name: Nom de noeud : @@ -13504,7 +12331,7 @@ Ces identités ne seront bientôt plus supportées. ID de noeud : - + Really delete? Vraiment supprimer ? @@ -13512,7 +12339,7 @@ Ces identités ne seront bientôt plus supportées. IdEditDialog - + Nickname Surnom @@ -13542,7 +12369,7 @@ Ces identités ne seront bientôt plus supportées. Pseudonyme - + Import image @@ -13552,12 +12379,19 @@ Ces identités ne seront bientôt plus supportées. - - Use the mouse to zoom and adjust the image for your avatar. + + + No Avatar chosen. A default image will be automatically displayed from your new identity. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity Nouvelle identité @@ -13571,7 +12405,7 @@ Ces identités ne seront bientôt plus supportées. - + @@ -13581,7 +12415,12 @@ Ces identités ne seront bientôt plus supportées. N/A - + + No avatar chosen + + + + Edit identity Modifier l'identité @@ -13592,27 +12431,27 @@ Ces identités ne seront bientôt plus supportées. Mettre à jour - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -13632,7 +12471,7 @@ Ces identités ne seront bientôt plus supportées. - + Identity update failed @@ -13642,11 +12481,7 @@ Ces identités ne seront bientôt plus supportées. - Error getting key! - Erreur lors de la récupération de la clé ! - - - + Error KeyID invalid Erreur ID de la clé invalide @@ -13661,7 +12496,7 @@ Ces identités ne seront bientôt plus supportées. Vrai nom inconnu - + Create New Identity Créer une nouvelle identité @@ -13671,10 +12506,15 @@ Ces identités ne seront bientôt plus supportées. Type - + Choose image... + + + Remove + + @@ -13700,7 +12540,7 @@ Ces identités ne seront bientôt plus supportées. Ajouter - + Create Créer @@ -13710,17 +12550,13 @@ Ces identités ne seront bientôt plus supportées. Annuler - + Your Avatar Click here to change your avatar Votre avatar - Set Avatar - Mettre l'avatar - - - + Linked to your profile Liée à votre profil @@ -13730,7 +12566,7 @@ Ces identités ne seront bientôt plus supportées. Vous pouvez avoir une seule ou plusieurs identités. Elles sont utilisées lorsque vous écrivez dans des salons de tchat, forums, et dans les commentaires de chaînes. Elles agissent comme destination pour le tchat distant et pour le système de courrier distant de Retroshare. - + The nickname is too short. Please input at least %1 characters. Ce pseudonyme est trop court. Veuillez saisir au moins %1 caractères. @@ -13789,10 +12625,6 @@ Ces identités ne seront bientôt plus supportées. PGP name: Nom PGP : - - GXS id: - Id GXS : - PGP id: @@ -13808,7 +12640,7 @@ Ces identités ne seront bientôt plus supportées. - + Copy Copier @@ -13818,12 +12650,12 @@ Ces identités ne seront bientôt plus supportées. Supprimer - + %1 's Message History - + Mark all Tout marquer @@ -13842,26 +12674,38 @@ Ces identités ne seront bientôt plus supportées. Quote Citer - - Send - Envoyer - ImageUtil - - + + Save image Sauvegarder image + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + + + + Cannot save the image, invalid filename Ne peut pas sauvegarder l'image, le nom de fichier est invalide - + + Copy image + + + + + Not an image Pas une image @@ -13879,27 +12723,32 @@ Ces identités ne seront bientôt plus supportées. - + Enable RetroShare JSON API Server - + Port: - + Port : - + Listen Address: - + + Status: + + + + 127.0.0.1 127.0.0.1 - + Token: @@ -13920,7 +12769,12 @@ Ces identités ne seront bientôt plus supportées. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -13929,26 +12783,31 @@ Ces identités ne seront bientôt plus supportées. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File Ouvrir le fichier - + Open Folder Ouvrir le dossier de destination - + Checking... Vérification en cours... @@ -13958,7 +12817,7 @@ Ces identités ne seront bientôt plus supportées. Vérifier vos fichiers - + Recommend in a message to... Recommander par messagerie à ... @@ -13986,7 +12845,7 @@ Ces identités ne seront bientôt plus supportées. MainWindow - + Add Friend Ajouter un ami @@ -14002,7 +12861,8 @@ Ces identités ne seront bientôt plus supportées. - + + Options Options @@ -14023,7 +12883,7 @@ Ces identités ne seront bientôt plus supportées. - + Quit Quitter @@ -14034,12 +12894,12 @@ Ces identités ne seront bientôt plus supportées. Assistant de configuration rapide - + RetroShare %1 a secure decentralized communication platform Retroshare %1 - Logiciel de communication sécurisé et décentralisé - + Unfinished Inachevé @@ -14068,11 +12928,12 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. + Status Statut - + Notify Notifications @@ -14083,31 +12944,35 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. + Open Messages Ouvrir la messagerie - + + Bandwidth Graph Graphique de bande passante - + Applications Applications + Help Aide - + + Minimize Réduire - + Maximize Agrandir @@ -14122,7 +12987,12 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. Retroshare - + + Close window + + + + %1 new message %1 nouveau message @@ -14152,7 +13022,7 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. %1 amis connectés - + Do you really want to exit RetroShare ? Etes-vous sûr de vouloir quitter Retroshare ? @@ -14172,7 +13042,7 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. Afficher - + Make sure this link has not been forged to drag you to a malicious website. Assurez-vous que ce lien n'a pas été créé pour vous emmener vers un site Web malveillant. @@ -14217,12 +13087,13 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. Matrice des autorisations de services - + + Statistics Statistiques - + Show web interface Afficher l'interface web @@ -14237,7 +13108,7 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. dossier a beaucoup diminué ! (la limite actuelle est - + Really quit ? Voulez-vous vraiment quitter ? @@ -14246,17 +13117,17 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. MessageComposer - + Compose Écrire - + Contacts Contacts - + Paragraph Paragraphe @@ -14292,12 +13163,12 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. Titre 6 - + Font size Taille de police - + Increase font size Augmenter la police @@ -14312,32 +13183,32 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. Gras - + Italic Italique - + Alignment Alignement - + Add an Image Insérer une image - + Sets text font to code style Paramétrer la police d'écriture dans le code - + Underline Souligné - + Subject: Sujet : @@ -14348,32 +13219,32 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. - + Tags Mots clés - + Address list: Liste d'adresses : - + Recommend this friend Recommander cet ami - + Set Text color Définir la couleur du texte - + Set Text background color Définir la couleur de fond du texte - + Recommended Files Fichiers recommandés @@ -14443,7 +13314,7 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. Ajouter une citation - + Send To: Envoyer à : @@ -14467,10 +13338,6 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. &Justify &Justifier le texte - - All addresses (mixed) - Toutes adresses (mélangé) - All people @@ -14482,7 +13349,7 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. Mes contacts - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> Bonjour, <br>Je vous recommande un(e) bon(nne) ami(e), vous pouvez lui faire confiance autant qu'à moi. <br> @@ -14502,18 +13369,18 @@ Veuillez libérer de l'espace disque et cliquer sur Ok. veut devenir ami(e) avec toi sur Retroshare - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team Bonjour %1,<br><br>%2 veut devenir ton ami(e) sur Retroshare.<br><br>Répondre maintenant :<br>%3<br><br>Merci,<br>L'équipe de Retroshare - - + + Save Message Enregistrer le message - + Message has not been Sent. Do you want to save message to draft box? Le message n'a pas été envoyé @@ -14525,7 +13392,17 @@ Désirez-vous enregistrer le message dans les brouillons? Coller le lien Retroshare - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" Ajouter à "A" @@ -14545,7 +13422,7 @@ Désirez-vous enregistrer le message dans les brouillons? Ajouter comme fichier recommandé - + Original Message Message d'origine @@ -14555,21 +13432,21 @@ Désirez-vous enregistrer le message dans les brouillons? De - + - + To Pour - - + + Cc Cc - + Sent Eléments envoyés @@ -14584,7 +13461,7 @@ Désirez-vous enregistrer le message dans les brouillons? Sur %1, %2 à écrit : - + Re: Re : @@ -14594,30 +13471,30 @@ Désirez-vous enregistrer le message dans les brouillons? Tr : - - - + + + RetroShare Retroshare - + Do you want to send the message without a subject ? Souhaitez-vous envoyer ce message sans sujet ? - + Please insert at least one recipient. Veuillez inscrire au moins un destinataire. - + Bcc Cci - + Unknown Inconnu @@ -14732,13 +13609,13 @@ Désirez-vous enregistrer le message dans les brouillons? Détails - + Open File... Ouvrir un fichier... - + HTML-Files (*.htm *.html);;All Files (*) Fichiers HTML (*.htm *.html);;tous les fichiers (*) @@ -14758,7 +13635,7 @@ Désirez-vous enregistrer le message dans les brouillons? Exporter en PDF - + Message has not been Sent. Do you want to save message ? Le message n'a pas été envoyé. @@ -14780,7 +13657,7 @@ Voulez-vous enregistrer votre message ? Ajouter un fichier supplémentaire - + Hi,<br>I want to be friends with you on RetroShare.<br> Salut,<br>je voudrais être ami avec vous sur RetroShare. <br> @@ -14804,28 +13681,24 @@ Voulez-vous enregistrer votre message ? Warning: This message is too big of %1 characters after HTML conversion. - - You have a friend invite - Vous avez une invitation de la part d'un ami - Respond now: Répondre maintenant : - - + + Close Fermer - + From: De : - + Friend Nodes Noeuds amis @@ -14870,13 +13743,13 @@ Voulez-vous enregistrer votre message ? Liste ordonnée (romain majuscule) - - + + Thanks, <br> Remerciements, <br> - + Distant identity: Identité distante : @@ -14886,12 +13759,12 @@ Voulez-vous enregistrer votre message ? [Manquante] - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. Veuillez créer une identité pour signer vos messages distants, ou enlever de la liste de destinations les pairs distants. - + Node name & id: Nom de noeud et id: @@ -14969,7 +13842,7 @@ Voulez-vous enregistrer votre message ? Par défaut - + A new tab Un nouvel onglet @@ -14979,7 +13852,7 @@ Voulez-vous enregistrer votre message ? Une nouvelle fenêtre - + Edit Tag Modifier le mot clé @@ -15002,7 +13875,7 @@ Voulez-vous enregistrer votre message ? MessageToaster - + Sub: Sous : @@ -15010,7 +13883,7 @@ Voulez-vous enregistrer votre message ? MessageUserNotify - + Message Message @@ -15038,7 +13911,7 @@ Voulez-vous enregistrer votre message ? MessageWidget - + Recommended Files Fichiers recommandés @@ -15048,37 +13921,37 @@ Voulez-vous enregistrer votre message ? Télécharger tous les fichiers recommandés - + Subject: Sujet : - + From: De : - + To: Pour : - + Cc: Cc : - + Bcc: Cci : - + Tags: Mots clés : - + Reply Répondre @@ -15100,7 +13973,7 @@ Voulez-vous enregistrer votre message ? Forward - + Suivant @@ -15118,7 +13991,7 @@ Voulez-vous enregistrer votre message ? - + Send Invite Envoyer invitation @@ -15170,7 +14043,7 @@ Voulez-vous enregistrer votre message ? - + Confirm %1 as friend Confirmer %1 comme ami @@ -15180,12 +14053,12 @@ Voulez-vous enregistrer votre message ? Ajouter %1 comme ami - + View source - + No subject Pas de sujet @@ -15195,17 +14068,22 @@ Voulez-vous enregistrer votre message ? Télécharger - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -15215,21 +14093,23 @@ Voulez-vous enregistrer votre message ? - Send invite? - Envoyer invitation ? + + Show less + - Do you really want send a invite with your Certificate? - Voulez-vous vraiment envoyer une invitation avec votre certificat ? + + Show more + - + Download all Tout télécharger - + Print Document Imprimer le document @@ -15244,12 +14124,12 @@ Voulez-vous enregistrer votre message ? Fichiers HTML (*.htm *.html);;tous les fichiers (*) - + Load images always for this message Toujours charger les images pour ce message - + Hide the attachment pane Cacher le panneau pièce jointe @@ -15271,42 +14151,6 @@ Voulez-vous enregistrer votre message ? Compose Écrire - - Reply to selected message - Répondre au(x) message(s) sélectionné(s) - - - Reply - Répondre - - - Reply all to selected message - Répondre à tous les destinataires du(des) message(s) sélectionné(s) - - - Reply all - Répondre à tous - - - Forward selected message - Transférer le(s) message(s) sélectionné(s) - - - Forward - Suivante - - - Remove selected message - Supprimer le(s) message(s) sélectionné(s) - - - Delete - Supprimer - - - Print selected message - Imprimer le(s) message(s) sélectionné(s) - Print @@ -15385,7 +14229,7 @@ Voulez-vous enregistrer votre message ? MessagesDialog - + New Message Nouveau message @@ -15395,60 +14239,16 @@ Voulez-vous enregistrer votre message ? Écrire - Reply to selected message - Répondre au(x) message(s) sélectionné(s) - - - Reply - Répondre - - - Reply all to selected message - Répondre à tous les destinataires du(des) message(s) sélectionné(s) - - - Reply all - Répondre à tous - - - Forward selected message - Transférer le(s) message(s) sélectionné(s) - - - Foward - Transférer - - - Remove selected message - Supprimer le(s) message(s) sélectionné(s) - - - Delete - Supprimer - - - Print selected message - Imprimer le(s) message(s) sélectionné(s) - - - Print - Imprimer - - - Display - Affichage - - - + - - + + Tags Mots clés - - + + Inbox Boîte de réception @@ -15478,21 +14278,17 @@ Voulez-vous enregistrer votre message ? Corbeille - + Total Inbox: Tous les messages : - Folders - Dossiers - - - + Quick View Vue rapide - + Print... Imprimer... @@ -15502,26 +14298,6 @@ Voulez-vous enregistrer votre message ? Print Preview Aperçu avant impression - - Buttons Icon Only - Icônes uniquement - - - Buttons Text Beside Icon - Texte à coté des icônes - - - Buttons with Text - Icônes avec texte - - - Buttons Text Under Icon - Texte en dessous des icônes - - - Set Text Under Icon - Définir le texte sous les icônes - Save As... @@ -15543,7 +14319,7 @@ Voulez-vous enregistrer votre message ? Faire suivre le(s) message(s) - + Subject Sujet @@ -15553,7 +14329,7 @@ Voulez-vous enregistrer votre message ? De - + Date Date @@ -15563,39 +14339,7 @@ Voulez-vous enregistrer votre message ? Contenu - Click to sort by attachments - Cliquer pour trier par fichiers attachés - - - Click to sort by subject - Cliquer pour trier par sujet - - - Click to sort by read - Cliquer pour trier par lu - - - Click to sort by from - Cliquer pour trier par expéditeur - - - Click to sort by date - Cliquer pour trier par date - - - Click to sort by tags - Cliquer pour trier par mots clés - - - Click to sort by star - Cliquer pour trier par suivi - - - Forward selected Message - Transférer le(s) message(s) sélectionné(s) - - - + Search Subject Rechercher sujet @@ -15604,6 +14348,11 @@ Voulez-vous enregistrer votre message ? Search From Rechercher de + + + Search To + + Search Date @@ -15630,14 +14379,14 @@ Voulez-vous enregistrer votre message ? Rechercher pièces jointes - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare a son propre système de messagerie interne. Vous pouvez en envoyer/recevoir vers/depuis les noeuds de vos amis connectés.</p> <p>Il est aussi possible d'envoyer des messages vers les Identités d'autres personnes en utilisant le système de routage global. Ces messages sont toujours chiffrés et sont relayés par des noeuds intermédiaires jusqu'à ce qu'ils atteignent leur destination finale. </p> <p>Les messages distants restent dans votre boite d'envoi jusqu'à ce qu'un accusé de réception soit reçu.</p> <p>De façon générale, vous pouvez utiliser les messages afin de recommander des fichiers à vos amis en y collant des liens de fichiers, ou recommander des noeuds amis à d'autres noeuds amis, afin de renforcer votre réseau, ou envoyer du retour d'information (feedback) au propriétaire d'une chaîne.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + - + Starred - Suivi + @@ -15711,7 +14460,7 @@ Voulez-vous enregistrer votre message ? - Show author in People + Show in People @@ -15725,7 +14474,7 @@ Voulez-vous enregistrer votre message ? - + No message using %1 tag available. @@ -15740,38 +14489,33 @@ Voulez-vous enregistrer votre message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts Brouillons - + No Box selected. - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - Il n'y a pas de messages suivis. Suivre un message vous permettra de le retrouver plus facilement ultérieurement. Pour suivre un message, cliquez sur l'étoile grise devant n'importe quel message. - - - No system messages available. - Aucun message système disponible. - - + To - Pour + Pour - Click to sort by to - Cliquer pour trier par destinataire - - - This message goes to a distant person. - Ce message va vers une personne distante. - - - + @@ -15779,26 +14523,6 @@ Voulez-vous enregistrer votre message ? Total: Total : - - Messages - Messages - - - Click to sort by signature - Cliquer pour trier par signature - - - This message was signed and the signature checks - Ce message a été signé et la signature vérifiée - - - This message was signed but the signature doesn't check - Ce message a été signé mais la signature n'a pas été vérifiée - - - This message comes from a distant person. - Ce message vient d'une personne distante. - Mail @@ -15826,7 +14550,17 @@ Voulez-vous enregistrer votre message ? MimeTextEdit - + + Save image + Sauvegarder image + + + + Copy image + + + + Paste as plain text Coller comme texte brut @@ -15880,7 +14614,7 @@ Voulez-vous enregistrer votre message ? - + Expand Développer @@ -15890,7 +14624,7 @@ Voulez-vous enregistrer votre message ? Effacer le message - + from depuis @@ -15925,18 +14659,10 @@ Voulez-vous enregistrer votre message ? Message(s) en attente - + Hide Cacher - - Send invite? - Envoyer invitation ? - - - Do you really want send a invite with your Certificate? - Voulez-vous vraiment envoyer une invitation avec votre certificat ? - NATStatus @@ -16074,7 +14800,7 @@ Voulez-vous enregistrer votre message ? ID du contact - + Remove unused keys... Suppression des clés inutilisées... @@ -16084,7 +14810,7 @@ Voulez-vous enregistrer votre message ? - + Clean keyring Nettoyer le trousseau @@ -16102,7 +14828,13 @@ Remarques : votre ancien trousseau sera sauvegardé. La suppression peut échouer lors de l'exécution de plusieurs instances de Retroshare sur la même machine. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info Info du trousseau @@ -16138,18 +14870,13 @@ Par mesure de sécurité votre trousseau précédent à été sauvegardé sous f Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. Incohérence des données dans le trousseau de clés. Il s'agit très probablement d'un bug. S'il vous plaît contacter les développeurs. - - - Export/create a new node - Exporter/créer un nouveau noeud - Trusted keys only Clés de confiance uniquement - + Search name Chercher nom @@ -16159,12 +14886,12 @@ Par mesure de sécurité votre trousseau précédent à été sauvegardé sous f Chercher ID de pair - + Profile details... Détails du profil ... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -16173,13 +14900,6 @@ Reported error: Erreur remontée : - - NetworkPage - - Network - Réseau - - NetworkView @@ -16206,7 +14926,7 @@ Erreur remontée : NewFriendList - + Offline Friends @@ -16227,7 +14947,7 @@ Erreur remontée : - + Groups Groupes @@ -16257,19 +14977,19 @@ Erreur remontée : Importer votre liste d'amis en incluant les groupes - - + + Search - + ID ID - + Search ID Chercher ID @@ -16279,12 +14999,12 @@ Erreur remontée : - + Show Items Options d'affichage - + Last contact @@ -16294,7 +15014,7 @@ Erreur remontée : IP - + Group Groupe @@ -16409,7 +15129,7 @@ Erreur remontée : Tout replier - + Do you want to remove this node? Voulez-vous retirer ce noeud ? @@ -16419,7 +15139,7 @@ Erreur remontée : Désirez-vous supprimer cet ami ? - + Done! Terminé ! @@ -16534,11 +15254,7 @@ au moins un contact n'a pas été ajouté au groupe NewsFeed - Log entries - Entrées du journal - - - + Activity Stream @@ -16553,11 +15269,7 @@ au moins un contact n'a pas été ajouté au groupe Tout effacer - This is a test. - C'est un test. - - - + Newest on top Les plus récents en haut @@ -16567,21 +15279,12 @@ au moins un contact n'a pas été ajouté au groupe Les plus anciens en haut - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;News Feed</h1> <p>The Log Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel and Forum posts</li> <li>New Channels and Forums you can subscribe to</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Fil d'actualités</h1> <p>Le fil d'actualités affiche les derniers événements survenus dans votre réseau, triés selon le moment où vous les avez reçus. Cela vous donne un résumé de l'activité de vos amis. Vous pouvez configurer les événements à afficher en cliquant sur <b>Options</ b>. -Les divers événements affichés sont : <ul> <li>Les tentatives de connexion (utile pour ajouter de nouveaux amis et savoir qui essaie de vous contacter) </li> <li> Les nouveaux articles dans les chaînes et les forums</li> <li>Les nouvelles chaînes et forums auxquels vous pouvez vous abonner</li> <li>Les messages privés de vos amis </li> </ul> </p> - - - Log - Journal - - - + Activity @@ -16636,10 +15339,6 @@ Les divers événements affichés sont : <ul> <li>Les tentatives de Blogs Blogs - - Security - Sécurité - @@ -16661,10 +15360,6 @@ Les divers événements affichés sont : <ul> <li>Les tentatives de Message Message - - Connect attempt - Tentative de connexion - @@ -16681,10 +15376,6 @@ Les divers événements affichés sont : <ul> <li>Les tentatives de Ip security Sécurité IP - - Log - Journal - Friend Connected @@ -16695,10 +15386,6 @@ Les divers événements affichés sont : <ul> <li>Les tentatives de Circles Cercles - - Links - Liens - Activity @@ -16751,26 +15438,6 @@ Les divers événements affichés sont : <ul> <li>Les tentatives de Chat rooms Salons de tchat - - Chat Rooms - Salons de tchat - - - Count occurrences of my current identity - Compter les occurrences de mon identité actuelle - - - Count occurrences of any of the following texts (separate by newlines): - Compter les occurrences de n'importe lequel des textes suivants (séparés par des retours à la ligne) : - - - Checked, if the identity and the text above occurrences must be in the same case to trigger count. - Sélectionné, si l'identité et le texte ci-dessus de même origine doivent être dans le même cas pour déclencher le comptage. - - - Case sensitive - Sensible à la casse - Position @@ -16846,24 +15513,16 @@ Les divers événements affichés sont : <ul> <li>Les tentatives de Disable All Toaster temporarily Désactiver toutes les notifications grille-pain temporairement - - Feed - Flux - Systray Zone de notification - - Count all unread messages - Compter tous les messages non lus - NotifyQt - + Passphrase required Phrase de passe requise @@ -16883,12 +15542,12 @@ Les divers événements affichés sont : <ul> <li>Les tentatives de Mauvais mot de passe ! - + Please enter your Retroshare passphrase Veuillez saisir votre phrase de passe Retroshare - + Unregistered plugin/executable Extension/exécutable non enregistrée @@ -16903,19 +15562,7 @@ Les divers événements affichés sont : <ul> <li>Les tentatives de S'il vous plaît vérifier votre horloge système. - Examining shared files... - Analyse des fichiers partagés... - - - Hashing file - Hachage fichier - - - Saving file index... - Enregistrement de l'index des fichiers... - - - + Test Test @@ -16926,17 +15573,19 @@ Les divers événements affichés sont : <ul> <li>Les tentatives de + Unknown title Titre inconnu - + + Encrypted message Message chiffré - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). Afin que les salons de tchat fonctionnent correctement, l'heure de votre ordinateur doit être correcte. Veuillez vérifier que c'est le cas (un possible décalage de plusieurs minutes a été détecté avec vos amis). @@ -16944,7 +15593,7 @@ Les divers événements affichés sont : <ul> <li>Les tentatives de OnlineToaster - + Friend Online En ligne @@ -16996,10 +15645,6 @@ Trafic faible : 10% du trafic standard et TODO : tous les transferts de fichiers PGPKeyDialog - - Dialog - Dialogue - Profile info @@ -17065,10 +15710,6 @@ Trafic faible : 10% du trafic standard et TODO : tous les transferts de fichiers This profile has signed your own profile key Ce profil a signé votre propre clé de profil - - Key signatures : - Signatures de clé : - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> @@ -17098,23 +15739,20 @@ p, li { white-space: pre-wrap; } Clé PGP - - These options apply to all nodes of the profile: - Ces options s'appliquent à tous les emplacement du profil : + + Friend options + - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> - <html><head/><body><p><span style=" font-size:10pt;">Signer la clé d'un ami est une façon d'exprimer à vos autres amis votre confiance en cet ami. Cela les aide à décider, en se basant sur votre propre confiance, si ils doivent permettre des connexions depuis cette clé. Signer une clé est absolument facultatif et ne peut pas être défait, alors faites-le avec sagesse.</span></p></body></html> + + These options apply to all nodes of the profile: + Ces options s'appliquent à tous les emplacement du profil : Keysigning: - - Sign PGP key - Signer la clé PGP - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -17151,12 +15789,7 @@ p, li { white-space: pre-wrap; } Inclure les signatures - - Options - Options - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> <html><head/><body><p align="justify">Retroshare vérifie périodiquement les listes de votre ami pour trouver des fichiers parcourables correspondants à vos transferts, afin d'établir un transfert direct. Dans ce cas, votre ami sait que vous téléchargez le fichier.</p><p align="justify">Pour empêcher ce comportement pour cet ami seulement, décochez cette boîte. Vous pouvez toujours exécuter un transfert direct si vous le demandez explicitement, par exemple en téléchargeant depuis la liste de fichiers de votre ami. Cet réglage est appliqué à tous les emplacements du même noeud.</p></body></html> @@ -17170,10 +15803,6 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this profile (e.g. when the message author is a signed identity that belongs to this profile). This can be used for instance to send files between your own nodes.</p></body></html> - - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> - <html><head/><body><p>Cette option vous permet de télécharger automatiquement un fichier qui serait recommandé dans un message venant de ce noeud. Ceci peut être utilisé par exemple pour envoyer des fichiers entre vos propres noeuds. L'option est appliquée à tous les emplacements du même noeud.</p></body></html> - Auto-download recommended files from this node @@ -17206,21 +15835,21 @@ p, li { white-space: pre-wrap; } KO/s - - + + RetroShare RetroShare - - + + Error : cannot get peer details. Erreur : impossible d'obtenir les détails de ce contact. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) L'algorithme de la clé fournie n'est pas supporté par Retroshare @@ -17241,7 +15870,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. Le niveau de confiance est une façon d'exprimer votre propre confiance en cette clé. Cela n'est pas utilisé par le logiciel, ni partagé, mais cela peut être utile pour vous afin de vous rappeler les bonnes/mauvaises clés. @@ -17310,10 +15939,6 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg Check the password! - - Maybe password is wrong - Le mot de passe est peut-être incorrect - You haven't set a trust level for this key. @@ -17321,12 +15946,12 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg - + Retroshare profile Profil Retroshare - + This is your own PGP key, and it is signed by : Ceci est votre propre clé PGP, et elle a été signée par : @@ -17352,7 +15977,7 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg PeerItem - + Chat Tchat @@ -17373,7 +15998,7 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg Effacer - + Name: Nom : @@ -17413,7 +16038,7 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg Décalage temps  : - + Write Message Écrire un message @@ -17427,10 +16052,6 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg Friend Connected Ami connecté - - Connect Attempt - Tentative de connexion - Connection refused by peer @@ -17469,17 +16090,13 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg Unknown - - Unknown Peer - Contact inconnu - Hide Cacher - + Send Message Envoyer le message @@ -17531,10 +16148,6 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg Chat with this person as... Tchater avec cette personne en tant que ... - - Send message to this person - Envoyer un message à cette personne - Invite to Circle @@ -17593,10 +16206,6 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg <html><head/><body><p>Anyone in your contact list will automatically have a positive opinion if not set. This allows to automatically raise reputations of used nodes. </p></body></html> <html><head/><body><p>Toute personne dans votre liste de contacts aura automatiquement une opinion positive si elle n'est pas définie. Cela permet d'augmenter automatiquement la réputation des nœuds utilisés.</p></body></html> - - automatically give "Positive" opinion to my contacts - Donner automatiquement l'avis "positif" à mes contacts - use "positive" as the default opinion for contacts (instead of neutral) @@ -17654,13 +16263,6 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg <html><head/><body><p>Afin d'empêcher les ID bannies supprimées de revenir parce qu'ils sont utilisés dans, par ex. Forums ou canaux, les identités bannies sont conservées dans une liste pendant un certain temps. Après cela, ils sont "effacés" À partir de la liste d'interdiction, et sera téléchargé à nouveau comme non autorisé s'il est utilisé dans les forums, les salons de tchat, etc.</p></body></html> - - PhotoCommentItem - - Form - Formulaire - - PhotoDialog @@ -17668,23 +16270,11 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg PhotoShare PhotoShare - - Photo - Photo - TextLabel Etiquette - - Comment - Commentaire - - - Summary - Résumé - Album / Photo Name @@ -17745,14 +16335,6 @@ Attention: Dans vos Préférences de Fichiers, vous avez interdit le télécharg ... ... - - Add Comment - Ajouter un commentaire - - - Write a comment... - Ecrivez un commentaire... - Album @@ -17823,10 +16405,6 @@ p, li { white-space: pre-wrap; } Create Album Créer un album - - View Album - Afficher l'album - Edit Album Details @@ -17848,17 +16426,17 @@ p, li { white-space: pre-wrap; } Diaporama - + My Albums Vos albums - + Subscribed Albums Albums abonnés - + Shared Albums Albums partagés @@ -17888,7 +16466,7 @@ avant de vouloir le modifier ! PhotoSlideShow - + Album Name Nom de l'album @@ -17947,19 +16525,19 @@ avant de vouloir le modifier ! - - + + TextLabel - + Posted by - + ago @@ -17995,12 +16573,12 @@ avant de vouloir le modifier ! PluginItem - + TextLabel Etiquette - + Show more details about this plugin sera activé aprés le redémarrage de Retroshare @@ -18146,60 +16724,6 @@ p, li { white-space: pre-wrap; } Plugin look-up directories Dossiers des extensions - - Plugin disabled. Click the enable button and restart Retroshare - Plug-in désactivé. Cliquez le bouton "activer" puis redémarrez Retroshare - - - [disabled] - [désactivé] - - - No API number supplied. Please read plugin development manual. - Aucun numéro d'API fourni. S'il vous plaît lire le manuel de développement des extensions. - - - [loading problem] - [problème de chargement] - - - No SVN number supplied. Please read plugin development manual. - Aucun numéro de SVN fourni. S'il vous plaît lire le manuel de développement des extensions. - - - Loading error. - Erreur de chargement. - - - Missing symbol. Wrong version? - Symbole manquant. Mauvaise version ? - - - No plugin object - Pas d'extension - - - Plugins is loaded. - L'extension est chargée - - - Unknown status. - Statut inconnue. - - - Check this for developing plugins. They will not -be checked for the hash. However, in normal -times, checking the hash protects you from -malicious behavior of crafted plugins. - Cochez cette case pour le développement des extensions. Elles ne seront pas -vérifié par hachage. Toutefois, dans des conditions normales -en vérifiant la valeur de hachage cela vous protège contre les -comportements malveillants des extensions. - - - <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Plugins</h1> <p>Plugins are loaded from the directories listed in the bottom list.</p> <p>For security reasons, accepted plugins load automatically until the main Retroshare executable or the plugin library changes. In such a case, the user needs to confirm them again. After the program is started, you can enable a plugin manually by clicking on the "Enable" button and then restart Retroshare.</p> <p>If you want to develop your own plugins, contact the developpers team they will be happy to help you out!</p> - <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Extensions</h1> <p>Les extensions sont chargées depuis les répertoires affichés dans la liste tout en bas.</p> <p>Pour des raisons de sécurité, les extensions reconnues sont chargées automatiquement, jusqu'à ce que l'exécutable principal Retroshare ou que de la bibliothèque de plug-in ne changent. Dans un tel cas, l'utilisateur doit confirmer les plugins à nouveau. Après le démarrage du programme, vous pouvez activer un plugin manuellement en cliquant sur ​​le bouton "Activer" puis ensuite redémarrer Retroshare.</p> <p>Si vous voulez développer vos propres extensions, contactez l'équipe de développeurs, ils seront heureux de vous aider !</p> - Plugins @@ -18269,12 +16793,27 @@ comportements malveillants des extensions. Mettre la fenêtre sur le dessus - + + Ban this person (Sets negative opinion) + Bannir cette personne (met une opinion négative) + + + + Give neutral opinion + Donne opinion neutre + + + + Give positive opinion + Donne opinion positive + + + Choose window color... - + Dock window @@ -18308,22 +16847,6 @@ comportements malveillants des extensions. Close conversation? - - The person you are talking to has deleted the secured chat tunnel. - La personne à laquelle vous parliez a supprimé le tunnel de tchat sécurisé. - - - The chat partner deleted the secure tunnel, messages will be delivered as soon as possible - Le partenaire de tchat a supprimé le tunnel sécurisé, les messages seront livrés dès que possible. - - - Closing this window will end the conversation, notify the peer and remove the encrypted tunnel. - La fermeture de cette fenêtre met fin à la conversation, informez le contact puis supprimez le tunnel chiffré. - - - Kill the tunnel? - Tuer ce tunnel ? - PostedCardView @@ -18343,7 +16866,7 @@ comportements malveillants des extensions. Nouveau - + Vote up Voter pour @@ -18363,8 +16886,8 @@ comportements malveillants des extensions. \/ - - + + Comments Commentaires @@ -18389,13 +16912,13 @@ comportements malveillants des extensions. - - + + Comment Commentaire - + Comments Commentaires @@ -18423,20 +16946,12 @@ comportements malveillants des extensions. PostedCreatePostDialog - Signed by: - Signé par : - - - Notes - Notes - - - + Create a new Post - + RetroShare Retroshare @@ -18451,12 +16966,22 @@ comportements malveillants des extensions. - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File Charger le fichier image - + Post image @@ -18472,7 +16997,17 @@ comportements malveillants des extensions. - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -18482,23 +17017,7 @@ comportements malveillants des extensions. - Submit Post - Soumettre l'article - - - You are submitting a link. The key to a successful submission is interesting content and a descriptive title. - Vous proposez un lien. La clé d'une proposition réussie est un contenu intéressant et ayant un titre descriptif. - - - Submit - Soumettre - - - Submit a new Post - Soumettre un nouveau lien - - - + Please add a Title Veuillez ajouter un titre @@ -18518,12 +17037,22 @@ comportements malveillants des extensions. - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -18538,7 +17067,7 @@ comportements malveillants des extensions. Poster en tant que - + Post @@ -18549,7 +17078,7 @@ comportements malveillants des extensions. Image - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -18559,7 +17088,7 @@ comportements malveillants des extensions. Titre - + Link Lien @@ -18567,44 +17096,12 @@ comportements malveillants des extensions. PostedDialog - Posted Links - Liens publiés - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Posted</h1> <p>The posted service allows you to share internet links, that spread among Retroshare nodes like forums and channels</p> <p>Links can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Posted links are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Liens</h1> <p>Le service de publication vous permet de partager des liens internet, qui se propagent entre les nœuds Retroshare à la manière des forums et des chaînes</p> <p>Les liens peuvent être commentés par les utilisateurs inscrits. Un système de promotion donne également la possibilité de mettre en avant les liens importants.</p> <p>Il n'y a aucune restriction concernant les liens qui sont partagés. Soyez prudent lorsque vous cliquez sur eux.</p> <p>Les liens publiés sont conservés pour %1 jours et synchronisés au cours des derniers %2 jours, à moins que vous ne les modifiez.</p> - - - Create Topic - Créer un sujet - - - My Topics - Vos sujets - - - Subscribed Topics - Sujets abonnés - - - Popular Topics - Sujets populaires - - - Other Topics - Autres sujets - - - Links - Liens - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -18638,31 +17135,7 @@ comportements malveillants des extensions. PostedGroupDialog - Posted Topic - Sujet publié - - - Add Topic Admins - Ajouter des admins au sujet - - - Select Topic Admins - Selectionner les admins - - - Create New Topic - Créer un nouveau sujet - - - Edit Topic - Éditer le sujet - - - Update Topic - Mettre à jour le sujet - - - + Create New Board @@ -18700,7 +17173,17 @@ comportements malveillants des extensions. PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted Abonné à Posté @@ -18716,7 +17199,7 @@ comportements malveillants des extensions. - + Expand Montrer @@ -18731,24 +17214,17 @@ comportements malveillants des extensions. - Posted Description - Description postée - - - Loading - Chargement - - - New Posted - Nouveau post - - - + Loading... - + + Never + Jamais + + + New Board @@ -18761,22 +17237,18 @@ comportements malveillants des extensions. PostedItem - + 0 0 - Site - Site - - - - + + Comments Commentaires - + Copy RetroShare Link @@ -18787,12 +17259,12 @@ comportements malveillants des extensions. - + Comment Commentaire - + Comments Commentaires @@ -18802,7 +17274,7 @@ comportements malveillants des extensions. <p><font color="#ff0000"><b>L'auteur de ce message (avec l'ID %1) est banni.</b> - + Click to view Picture @@ -18812,21 +17284,17 @@ comportements malveillants des extensions. Cacher - + Vote up Voter pour - + Vote down Voter contre - \/ - \/ - - - + Set as read and remove item Définir comme lu et supprimer l'élément @@ -18836,7 +17304,7 @@ comportements malveillants des extensions. Nouveau - + New Comment: Nouveau commentaire : @@ -18846,7 +17314,7 @@ comportements malveillants des extensions. Valeur du commentaire - + Name Nom @@ -18887,77 +17355,10 @@ comportements malveillants des extensions. - + Loading Chargement - - By - Par - - - - PostedListWidget - - Form - Formulaire - - - Hot - Chaud - - - New - Nouveau - - - Top - Top - - - Today - Aujourd'hui - - - Yesterday - Hier - - - This Week - Cette semaine - - - This Month - Ce mois-ci - - - This Year - Cette année - - - Submit a new Post - Soumettre un nouveau lien - - - Next - Suivant - - - RetroShare - RetroShare - - - Please create or choose a Signing Id before Voting - Veuillez créer ou choisir une ID de signature avant de voter - - - Previous - Précédent - - - 1-10 - 1-10 - PostedListWidgetWithModel @@ -18977,7 +17378,17 @@ comportements malveillants des extensions. - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -18987,15 +17398,15 @@ comportements malveillants des extensions. Administrateur : - + - + unknown inconnu - + Distribution: Distribution : @@ -19005,42 +17416,42 @@ comportements malveillants des extensions. - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -19057,10 +17468,10 @@ comportements malveillants des extensions. Hot - + Hot - + Search @@ -19090,17 +17501,17 @@ comportements malveillants des extensions. - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -19115,12 +17526,17 @@ comportements malveillants des extensions. Vide - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -19130,27 +17546,31 @@ comportements malveillants des extensions. Modifier - + + information information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -19165,7 +17585,7 @@ comportements malveillants des extensions. S'abonner - + Never Jamais @@ -19239,6 +17659,16 @@ comportements malveillants des extensions. No Channel Selected Aucune chaîne sélectionnée + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -19247,14 +17677,6 @@ comportements malveillants des extensions. Tabs Onglets - - Open each topic in a new tab - Ouvrir chaque sujet dans un nouvel onglet - - - Links - Liens - Open each board in a new tab @@ -19268,10 +17690,6 @@ comportements malveillants des extensions. PostedUserNotify - - Posted - Publié - Board Post @@ -19340,25 +17758,17 @@ comportements malveillants des extensions. Gestionnaire de profil - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Sélectionnez une clé de noeud Retroshare depuis la liste ci-dessous afin de l'utiliser sur un autre ordinateur, puis pressez &quot;Exporter la clé sélectionnée.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Pour créer un nouvel emplacement sur un ordinateur différent, sélectionnez le gestionnaire d'identité dans la fenêtre de connexion (fenêtre de login). Depuis là vous pouvez importer le fichier clé puis créer une nouvel emplacement pour cette clé. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Créer un nouveau noeud avec la même clé permet à vos noeuds amis de vous accepter automatiquement.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> + @@ -19469,7 +17879,7 @@ et utiliser le bouton d'importation pour la charger ProfileWidget - + Edit status message Modifier le message d'état @@ -19485,7 +17895,7 @@ et utiliser le bouton d'importation pour la charger Gestionnaire de profil - + Public Information Information publique @@ -19520,12 +17930,12 @@ et utiliser le bouton d'importation pour la charger En ligne depuis : - + Other Information Autres informations - + My Address Votre adresse @@ -19569,51 +17979,27 @@ et utiliser le bouton d'importation pour la charger PulseAddDialog - Post From: - Article de : - - - Account 1 - Compte 1 - - - Account 2 - Compte 2 - - - Account 3 - Compte 3 - - - + Add to Pulse Ajouter a Pulse - filter - filtre - - - URL Adder - Additionneur URL - - - + Display As Afficher en tant que - + URL URL - + GroupLabel - + IDLabel @@ -19623,12 +18009,12 @@ et utiliser le bouton d'importation pour la charger De : - + Head - + Head Shot @@ -19658,13 +18044,13 @@ et utiliser le bouton d'importation pour la charger Négative - - + + Whats happening? - + @@ -19676,12 +18062,22 @@ et utiliser le bouton d'importation pour la charger - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -19690,17 +18086,13 @@ et utiliser le bouton d'importation pour la charger Cancel Annuler - - Post Pulse to Wire - Publier Pulse sur Wire - Post - + Reply to Pulse @@ -19715,34 +18107,24 @@ et utiliser le bouton d'importation pour la charger - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - De - - - Date - Date - - - ... - ... + + Load Picture File + Charger le fichier image @@ -19753,7 +18135,7 @@ et utiliser le bouton d'importation pour la charger Formulaire - + @@ -19772,7 +18154,7 @@ et utiliser le bouton d'importation pour la charger PulseReply - + icn @@ -19782,7 +18164,7 @@ et utiliser le bouton d'importation pour la charger - + REPLY @@ -19809,7 +18191,7 @@ et utiliser le bouton d'importation pour la charger - + FOLLOW @@ -19819,7 +18201,7 @@ et utiliser le bouton d'importation pour la charger - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -19839,7 +18221,7 @@ et utiliser le bouton d'importation pour la charger - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -19955,7 +18337,7 @@ et utiliser le bouton d'importation pour la charger - + FOLLOW @@ -19963,37 +18345,42 @@ et utiliser le bouton d'importation pour la charger PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -20025,7 +18412,7 @@ et utiliser le bouton d'importation pour la charger - + FOLLOW @@ -20033,8 +18420,8 @@ et utiliser le bouton d'importation pour la charger QObject - - + + Confirmation Confirmation @@ -20304,12 +18691,12 @@ Les caractères <b>",|,/,\,&lt;,&gt;,*,?</b> seront rem Détails du contact - + File Request canceled Demande de fichier annulée - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. Cette version de Retroshare utilise OpenPGP SDK. En contre partie, elle n'utilise plus le système de trousseau de clés PGP, mais possède son propre trousseau de clés partagé par toutes les instances de Retroshare. <br><br> Vous ne semblez pas posséder un tel trousseau, bien que des clés PGP apparaissent pour les comptes Retroshare existants, probablement parce que vous venez d'installer cette nouvelle version du logiciel. @@ -20340,7 +18727,7 @@ Les caractères <b>",|,/,\,&lt;,&gt;,*,?</b> seront rem Une erreur inattendue s'est produite. Vous pouvez la reporter 'RsInit::InitRetroShare unexpected return code %1'. - + Cannot start Tor Manager! Ne peut pas démarrer le Tor Manager ! @@ -20378,7 +18765,7 @@ L'erreur rapportée est : " Il n'était pas possible de démarrer un service caché. - + Multiple instances Instances multiples @@ -20400,6 +18787,26 @@ Fichier verrouillé : Fichier verrouillé : + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -20420,14 +18827,6 @@ Fichier verrouillé : End-to-end encrypted conversation established - - Tunnel is pending... Messages will be delivered as soon as possible - Le tunnel est en suspens ... Les messages seront livrés dès que possible - - - Secured tunnel is working. Messages are delivered immediately! - Le tunnel sécurisé est en marche. Les messages sont livrés immédiatement ! - The collection file %1 could not be opened. @@ -20490,7 +18889,7 @@ L'erreur rapportée est : Données transférées - + You appear to have nodes associated to DSA keys: Vous semblez avoir des noeuds associés à vos clés DSA : @@ -20500,7 +18899,7 @@ L'erreur rapportée est : Les clés DSA ne sont pas encore supportées par cette version de RetroShare. Tous ces noeuds seront inutilisables. Nous sommes vraiment désolés pour cela. - + enabled activé @@ -20510,7 +18909,7 @@ L'erreur rapportée est : désactivé - + Move IP %1 to whitelist Ajouter l'IP %1 en liste blanche @@ -20526,7 +18925,7 @@ L'erreur rapportée est : - + %1 seconds ago %1 secondes avant @@ -20594,7 +18993,7 @@ Security: no anonymous IDs Securité : pas d'IDs anomymes - + Join chat room Rejoindre le salon de tchat @@ -20622,7 +19021,7 @@ Securité : pas d'IDs anomymes incapable de faire l'analyse syntaxique (anglais: parse) du fichier XML ! - + Indefinitely Indéfiniment @@ -20802,13 +19201,29 @@ Securité : pas d'IDs anomymes Ban list + + + Name + Nom + + Node + Noeud + + + + Address + Adresse + + + + Status Statut - + NXS @@ -21001,10 +19416,6 @@ Securité : pas d'IDs anomymes Click to resume the hashing process - - <p>This certificate contains: - <p>Ce certificat contient : - Idle @@ -21055,6 +19466,18 @@ Securité : pas d'IDs anomymes Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -21217,7 +19640,7 @@ p, li { white-space: pre-wrap; } - + Network Wide Anonyme @@ -21400,7 +19823,7 @@ p, li { white-space: pre-wrap; } Formulaire - + The loading of embedded images is blocked. Le chargement des images intégrées est bloqué. @@ -21413,7 +19836,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default Autorisé par défaut @@ -21586,12 +20009,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + Sauvegarder image + + + + Copy image + + + + Document source @@ -21599,12 +20032,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options Options d'affichage d'arborescence - + Show Header @@ -21634,14 +20067,6 @@ p, li { white-space: pre-wrap; } Show column … - - Show column... - Afficher la colonne... - - - [no title] - [pas de titre] - RatesStatus @@ -22304,7 +20729,7 @@ Si vous pensez qu'il est correct, supprimez la ligne correspondante du fich RsDownloadListModel - + Name i.e: file name Nom @@ -22425,7 +20850,7 @@ Si vous pensez qu'il est correct, supprimez la ligne correspondante du fich RsFriendListModel - + Name Nom @@ -22445,7 +20870,7 @@ Si vous pensez qu'il est correct, supprimez la ligne correspondante du fich IP - + Profile ID @@ -22501,7 +20926,7 @@ prevents the message to be forwarded to your friends. Le message sera transmis à vos amis. - + [ ... Redacted message ... ] [ ... Message rédigé ... ] @@ -22515,11 +20940,6 @@ prevents the message to be forwarded to your friends. [Unknown] [Inconnu] - - - [ ... Missing Message ... ] - [ ... Message manquant... ] - RsMessageModel @@ -22533,6 +20953,11 @@ prevents the message to be forwarded to your friends. From De + + + To + + Subject @@ -22555,13 +20980,18 @@ prevents the message to be forwarded to your friends. - Click to sort by read - Cliquer pour trier par lu + Click to sort by read status + - Click to sort by from - Cliquer pour trier par expéditeur + Click to sort by author + + + + + Click to sort by destination + @@ -22584,7 +21014,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -22605,7 +21037,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. Réinitialisation de tous les paramètres de Retroshare. @@ -22666,7 +21098,7 @@ prevents the message to be forwarded to your friends. Définit la langue de Retroshare. - + Unable to open log file '%1': %2 Impossible d'ouvrir le journal '%1': %2 @@ -22687,11 +21119,7 @@ prevents the message to be forwarded to your friends. N'a pas pu créer le dossier de données : %1 - Revision - Révision - - - + opmode @@ -22721,7 +21149,7 @@ prevents the message to be forwarded to your friends. Information concernant le GUI de Retroshare - + Invalid language code specified: Le code de langue indiqué n'est pas valide : @@ -22739,7 +21167,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. Erreur d'accès au registre. Peut-être vous avez besoin des droits d'administrateur. @@ -22756,12 +21184,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) Entrez un mot clé ici (minimum 3 caractères) - + Start Search Lancer la recherche @@ -22823,7 +21251,7 @@ prevents the message to be forwarded to your friends. Effacer - + KeyWords Mots clés @@ -22838,7 +21266,7 @@ prevents the message to be forwarded to your friends. ID de recherche - + Filename Nom du fichier @@ -22938,23 +21366,23 @@ prevents the message to be forwarded to your friends. Télécharger la sélection - + File Name Nom du fichier - + Download Télécharger - + Copy RetroShare Link Copier le lien Retroshare - + Send RetroShare Link Envoyer le lien Retroshare @@ -22964,7 +21392,7 @@ prevents the message to be forwarded to your friends. - + Download Notice Télécharger la notice @@ -23001,7 +21429,7 @@ prevents the message to be forwarded to your friends. Tout supprimer - + Folder Dossier @@ -23012,17 +21440,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) Nouveau(x) lien(s) Retroshare - + Open Folder Ouvrir répertoire - + Create Collection... Créer une collection ... @@ -23042,7 +21470,7 @@ prevents the message to be forwarded to your friends. Télécharger à partir d'un fichier collection... - + Collection Collection @@ -23050,7 +21478,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details Détails du pair @@ -23066,22 +21494,22 @@ prevents the message to be forwarded to your friends. Supprimer élément - + IP address: Adresse IP : - + Peer ID: ID du pair : - + Location: Emplacement : - + Peer Name: Nom du pair : @@ -23098,7 +21526,7 @@ prevents the message to be forwarded to your friends. Cacher - + but reported: mais signalé : @@ -23123,8 +21551,8 @@ prevents the message to be forwarded to your friends. <p>Ceci est l'IP à laquelle votre ami prétend être connecté. Si vous avez juste changé d'IPs, ceci est une fausse alerte. Sinon, cela signifie que votre connexion à cet ami est retransmise via un pair intermédiaire, ce qui serait suspect.</p> - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> <html><head/><body><p>Cet avertissement est ici pour vous protéger contre les attaques visant le traffic transféré. Dans un tel cas, l'ami auquel vous êtes connecté ne verra pas votre IP externe, mais celle de l'attaquant. </p><p><br/></p><p>Cependant, si vous avez juste changé d'IP pour quelque raison que ce soit (quelques fournisseurs d'accès Internet forcent régulièrement le changement d'IPs) cet avertissement vous informe juste qu'un ami s'est connecté à la nouvelle IP avant que Retroshare n'aie compris que l'IP avait changé. Dans ce cas tout va bien.</p><p><br/></p><p>Vous pouvez facilement supprimer les fausses alertes en mettant en liste blanche vos propres IPs (par exemple la plage d'adresses de votre votre fournisseur d'accès Internet), ou en mettant complètement hors de service ces avertissements dans Options -&gt; Notifications -&gt; le Fil d'actualités.</p></body></html> @@ -23132,7 +21560,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare veut devenir ton ami(e) sur Retroshare @@ -23163,7 +21591,7 @@ prevents the message to be forwarded to your friends. - + Expand Déplier @@ -23208,12 +21636,12 @@ prevents the message to be forwarded to your friends. Statut : - + Write Message Envoyer un message - + Connect Attempt Tentative de connexion @@ -23233,17 +21661,22 @@ prevents the message to be forwarded to your friends. Tentative de connexion (sortante) inconnue - + Unknown Security Issue Problème de sécurité inconnue - - A unknown peer + + SSL request - + + An unknown peer + + + + Unknown @@ -23253,11 +21686,7 @@ prevents the message to be forwarded to your friends. - Unknown Peer - Contact inconnu - - - + Hide Cacher @@ -23267,7 +21696,7 @@ prevents the message to be forwarded to your friends. Désirez-vous supprimer cet ami ? - + Certificate has wrong signature!! This peer is not who he claims to be. Ce certificat a une signature erronée ! Cette personne n'est pas celle qu'elle prétend être. @@ -23277,12 +21706,12 @@ prevents the message to be forwarded to your friends. Certificat manquant/endommagé. Ce n'est pas un utilisateur réel de Retroshare. - + Certificate caused an internal error. Ce certificat a provoqué une erreur interne. - + Peer/node not in friendlist (PGP id= Le pair/noeud n'est pas dans la liste d'amis (ID PGP= @@ -23341,12 +21770,12 @@ prevents the message to be forwarded to your friends. - + Local Address Adresse locale - + NAT NAT @@ -23367,22 +21796,22 @@ prevents the message to be forwarded to your friends. Port : - + Local network Réseau local - + External ip address finder Découverte de l'adresse IP externe - + UPnP UPnP - + Known / Previous IPs: IPs connues / précédentes : @@ -23398,21 +21827,16 @@ que si vous vous connectez à quelqu'un. Laisser cette case cochée vous ai derrière un pare-feu ou un VPN (virtual private network). - - Allow RetroShare to ask my ip to these websites: - Autoriser Retroshare à récupérer mon adresse IP à partir de ces sites : - - - - - + + + kB/s Ko/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. La gamme de ports acceptables s'étend de 10 à 65535. Normalement les ports en dessous de 1024 sont réservés à votre système. @@ -23422,23 +21846,46 @@ derrière un pare-feu ou un VPN (virtual private network). La gamme de ports acceptables s'étend de 10 à 65535. Normalement les ports en dessous de 1024 sont réservés à votre système. - + Onion Address Adresse Onion - + Discovery On (recommended) Découverte activée (recommandé) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. Tor a été configuré automatiquement par Retroshare. Vous ne devriez rien avoir à changer ici. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off Découverte désactivée @@ -23448,7 +21895,7 @@ derrière un pare-feu ou un VPN (virtual private network). Caché - Voir config - + I2P Address Adresse I2P @@ -23473,39 +21920,95 @@ derrière un pare-feu ou un VPN (virtual private network). entrant OK - - + + + Proxy seems to work. Le proxy semble fonctionner. - + + I2P proxy is not enabled proxy I2P non activé - - BOB is running and accessible - BOB en cours d'exécution et accessible + + SAMv3 is running and accessible + - BOB is not accessible! Is it running? - BOB n'est pas accessible ! Est-il en cours d'exécution ? + SAMv3 is not accessible! Is i2p running and SAM enabled? + - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - RetroShare utilise BOB pour installer un tunnel %1 à %2: % 3 (nommé %4) - -Si vous modifiez des options (par exemple le port), utilisez les boutons du bas afin de redémarrer BOB. + - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client client @@ -23520,73 +22023,7 @@ Si vous modifiez des options (par exemple le port), utilisez les boutons du bas inconnu - - - - BOB is processing a request - BOB traite une requête - - - - connectivity check - vérification de connectivité - - - - generating key - génération de clé - - - - starting up - démarrage - - - - shuting down - en cours d'arrêt - - - - BOB is processing a request: %1 - BOB traite une requête : %1 - - - - BOB is broken - - BOB est cassé - - - - - BOB encountered an error: - - BOB a rencontré une erreur : - - - - - BOB tunnel is running - Le tunnel BOB fonctionne - - - - BOB is working fine: tunnel established - BOB marche bien : tunnel établi - - - - BOB tunnel is not running - Le tunnel BOB ne fonctionne pas - - - - BOB is inactive: tunnel closed - BOB est inactif : tunnel fermé - - - + request a new server key @@ -23596,22 +22033,7 @@ Si vous modifiez des options (par exemple le port), utilisez les boutons du bas - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. Vous êtes accessible à travers ce service caché. @@ -23625,12 +22047,12 @@ Tous les services sont-ils bien en marche ? Vérifiez aussi vos ports ! - + [Hidden mode] [Mode caché] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> <html><head/><body><p>Ceci vide la liste d'adresses connues. Cette action est utile si, pour une raison quelconque, votre liste d'adresse contient une adresse invalide/sans rapport/expirée que vous voulez éviter de passer à vos amis en tant qu'adresse de contact.</p></body></html> @@ -23640,7 +22062,7 @@ Vérifiez aussi vos ports ! Effacer - + Download limit (KB/s) Limite de téléchargement (KB/s) @@ -23655,23 +22077,23 @@ Vérifiez aussi vos ports ! Limite d'envoi (KB/s) - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> <html><head/><body><p>La limite de téléversement (upload) concerne le logiciel entier. Une trop petite limite de téléversement pourrait éventuellement bloquer des services à basse priorité (forums, chaînes). La valeur minimum recommandée est 50 Ko/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -23688,17 +22110,7 @@ Maintenant saisissez l'adresse (ex: 127.0.0.1) et le port que vous avez cho Vous pouvez vous connecter à des noeuds cachés, même si vous exécutez un noeud standard, alors pourquoi ne pas paramétrer Tor et/ou I2P ? - - Automatic I2P/BOB - Automatique I2P/BOB - - - - Enable I2P BOB - changing this requires a restart to fully take effect - Permettre BOB dans I2P - modifier ceci exige un redémarrage pour prendre effet - - - + enableds advanced settings paramètres avancés permis @@ -23708,12 +22120,7 @@ Vous pouvez vous connecter à des noeuds cachés, même si vous exécutez un noe mode avancé - - I2P Basic Open Bridge - I2P Basic Open Bridge - - - + I2P Instance address Adresse d'instance I2P @@ -23723,17 +22130,7 @@ Vous pouvez vous connecter à des noeuds cachés, même si vous exécutez un noe 127.0.0.1 - - I2P proxy port - Port du proxy I2P - - - - BOB accessible - BOB accessible - - - + Address Adresse @@ -23773,7 +22170,7 @@ Vous pouvez vous connecter à des noeuds cachés, même si vous exécutez un noe - + Start Démarrer @@ -23788,12 +22185,7 @@ Vous pouvez vous connecter à des noeuds cachés, même si vous exécutez un noe Stopper - - BOB status - Statut du BOB - - - + Incoming Entrant @@ -23840,7 +22232,32 @@ Assurez-vous finalement que les Ports correspondent à la configuration. Si vous avez des soucis concernant la connexion via Tor, pensez à lire les logs de Tor aussi. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay Relais @@ -23895,7 +22312,7 @@ Si vous avez des soucis concernant la connexion via Tor, pensez à lire les logs Total : - + Warning: This bandwidth adds up to the max bandwidth. Avertissement : cette bande passante s'ajoute à la bande passante max. @@ -23920,7 +22337,7 @@ Si vous avez des soucis concernant la connexion via Tor, pensez à lire les logs Supprimer serveur - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -23932,7 +22349,7 @@ Si vous avez des soucis concernant la connexion via Tor, pensez à lire les logs Réseau - + IP Filters Filtres d'IP @@ -23955,7 +22372,7 @@ Si vous avez des soucis concernant la connexion via Tor, pensez à lire les logs - + Status Statut @@ -24015,17 +22432,28 @@ Si vous avez des soucis concernant la connexion via Tor, pensez à lire les logs Ajouter en liste blanche - + Hidden Service Configuration Configuration de service caché - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>Ceci est le port du proxy Socks de Tor. Votre noeud Retroshare peut utiliser ce port pour se connecter à </p><p>des noeuds cachés. La led à droite devient verte quand le port est actif sur votre ordinateur. </p><p>Ceci ne signifie pas cependant que votre traffic Retroshare traffic transite à travers Tor. Cela le signifie seulement si </p><p>vous vous connectez à des noeuds cachés, ou si vous exécutez vous-même un noeud caché.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>Cette led est verte dans le port d'écoute sur la gauche est active dans votre ordinateur. Cela ne signifie pas</p><p>que le traffic de votre Retroshare transite à travers Tor. Cela sera le cas seulement si</p><p>vous vous connectez à des noeuds cachés, ou si vous exécutez vous-même un noeud caché.</p></body></html> @@ -24041,18 +22469,18 @@ Si vous avez des soucis concernant la connexion via Tor, pensez à lire les logs - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>Cette led est verte dans le port d'écoute sur la gauche est active dans votre ordinateur. Cela ne signifie pas</p><p>que le traffic de votre Retroshare transite à travers I2P. Cela sera le cas seulement si</p><p>vous vous connectez à des noeuds cachés, ou si vous exécutez vous-même un noeud caché.</p></body></html> - + I2P outgoing Okay I2P sortant OK - + Service Address Adresse de service @@ -24087,12 +22515,12 @@ Si vous avez des soucis concernant la connexion via Tor, pensez à lire les logs Veuillez remplir par une adresse de service - + IP Range Plage d'IP - + Reported by DHT for IP masquerading Rapporté par la DHT concernant masquerading d'IP (se fait passer pour). @@ -24115,22 +22543,22 @@ Si vous avez des soucis concernant la connexion via Tor, pensez à lire les logs Ajouté par vous - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> <html><head/><body><p>Les adresses IP de la liste blanche sont rassemblées depuis les sources suivantes : IPs venant à l'intérieur d'un certificat échangé manuellement, gammes IP entrées par vous dans cette fenêtre, ou dans les articles du flux de sécurité.</p><p>Le comportement par défaut de Retroshare est de (1) toujours permettre la connexion aux pairs ayant leur IP dans la liste blanche, même si cette IP est aussi présente dans la liste noire; (2) exiger facultativement que les IPs soient dans la liste blanche. Vous pouvez changer ce comportement pour chaque pair à partir de la fenêtre &quot;Détails&quot de chaque noeud Retroshare. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> <html><head/><body><p>La DHT vous permet de répondre aux demandes de connexion de vos amis utilisant la DHT de BitTorrent. Elle améliore grandement la connectivité. Aucune informations ne sont stockées en réalité dans la DHT. Elle est seulement utilisé comme un système de proxy afin de se mettre en contact avec d'autres noeuds Retroshare.</p><p>Le service de Découverte envoie le nom de noeud et les IDs de vos contacts éprouvés à vos pairs connectés, afin de les aider à choisir de nouveaux amis. L'amitié n'est cependant jamais automatique, et deux pairs doivent toujours avoir confiance l'un en l'autre pour permettre la connexion. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> <html><head/><body><p>La balle devient verte aussitôt que Retroshare réussit à obtenir votre propre IP depuis les sites Web listés ci-dessous, si vous avez permis cette action. Retroshare utilisera aussi d'autres moyens pour découvrir votre propre IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> <html><head/><body><p>Cette liste est automatiquement remplie d'informations rassemblées depuis des sources multiples : pairs en mode masquerading rapportés par la DHT, plages IP entrées par vous et plages IP rapportées par vos amis. Les réglages par défaut devraient vous protéger contre le relayage de trafic de grande échelle.</p><p>Devenir automatiquement les IPs employant le masquage peut avoir pour conséquence de placer vos IPs amies dans la liste noire. Dans ce cas, utilisez le menu de contexte afin de les mettre en liste blanche.</p></body></html> @@ -24165,26 +22593,22 @@ Si vous avez des soucis concernant la connexion via Tor, pensez à lire les logs Bannir automatiquement de la DHT les plages auxquelles débutent les IP masquerading - + Outgoing Manual Tor/I2P - - <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. <br/>If you prefer to use BOB to automatically manage I2P check the other tab.</p></body></html> - <html><head/><body><p>Configurer ici votre proxy SOCKS Tor et I2P. <br/>Si vous préférez utiliser BOB afin qu'il se débrouille automatiquement avec I2P, alors vérifiez l'autre onglet.</p></body></html> - Tor Socks Proxy Proxy Socks de Tor - + Tor outgoing Okay Tor sortant OK - + Tor proxy is not enabled Le proxy de Tor n'est pas activé @@ -24264,7 +22688,7 @@ Si vous avez des soucis concernant la connexion via Tor, pensez à lire les logs ShareKey - + check peers you would like to share private publish key with Visualiser les contacts avec qui vous partagez votre clé de publication privée @@ -24274,12 +22698,12 @@ Si vous avez des soucis concernant la connexion via Tor, pensez à lire les logs Partager avec vos amis - + Share Partager - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. Vous pouvez laisser vos amis connaître vos chaînes en les partageant avec eux. @@ -24299,7 +22723,7 @@ Sélectionnez les amis avec lesquels vous voulez partager votre chaîne.Gestionnaire des dossiers partagés - + Shared directory Dossier partagé @@ -24319,17 +22743,17 @@ Sélectionnez les amis avec lesquels vous voulez partager votre chaîne.Visibilité - + Add new Ajouter un nouveau - + Cancel Annuler - + Add a Share Directory Ajouter un dossier à partager @@ -24339,7 +22763,7 @@ Sélectionnez les amis avec lesquels vous voulez partager votre chaîne.Supprimer - + Apply and close Appliquer et fermer @@ -24430,7 +22854,7 @@ Sélectionnez les amis avec lesquels vous voulez partager votre chaîne.Le dossier n'a pas été trouvé ou le nom du dossier n'est pas accepté. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. Il s'agit d'une liste des dossiers partagés. Vous pouvez ajouter et supprimer des dossiers en utilisant les boutons en bas. Lorsque vous ajoutez un nouveau dossier, initialement tous les fichiers contenus dans ce dossier sont partagés. Vous pouvez configurer séparément le type de partage pour chaque répertoire sélectionné. @@ -24438,7 +22862,7 @@ Sélectionnez les amis avec lesquels vous voulez partager votre chaîne. SharedFilesDialog - + Files Fichiers @@ -24489,11 +22913,16 @@ Sélectionnez les amis avec lesquels vous voulez partager votre chaîne. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files Vérifier vos fichiers - + Download selected Télécharger la sélection @@ -24503,7 +22932,7 @@ Sélectionnez les amis avec lesquels vous voulez partager votre chaîne.Télécharger - + Copy retroshare Links to Clipboard Copier le lien Retroshare @@ -24518,7 +22947,7 @@ Sélectionnez les amis avec lesquels vous voulez partager votre chaîne.Envoyer le lien Retroshare - + Some files have been omitted Certains fichiers ont été omis @@ -24534,7 +22963,7 @@ Sélectionnez les amis avec lesquels vous voulez partager votre chaîne.Recommandation(s) - + Create Collection... Créer une collection ... @@ -24559,7 +22988,7 @@ Sélectionnez les amis avec lesquels vous voulez partager votre chaîne.Télécharger à partir d'un fichier collection... - + Some files have been omitted because they have not been indexed yet. Certains fichiers ont été omis car leur hachage n'est pas encore disponible. @@ -24702,12 +23131,12 @@ Sélectionnez les amis avec lesquels vous voulez partager votre chaîne. SplashScreen - + Load configuration Chargement de la configuration - + Create interface Création de l'interface @@ -24731,7 +23160,7 @@ Sélectionnez les amis avec lesquels vous voulez partager votre chaîne.Se rappeler du mot de passe - + Log In Se connecter @@ -25088,7 +23517,7 @@ Ce choix peut être inversé dans des paramétrages. Message d'état - + Message: Message : @@ -25333,7 +23762,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags Supprimer tout les mots clés @@ -25369,12 +23798,15 @@ p, li { white-space: pre-wrap; } Paramétrage de Tor ... - + + Tor status: Statut de Tor : - + + + Unknown Inconnu @@ -25384,18 +23816,13 @@ p, li { white-space: pre-wrap; } Non démarré - - Hidden service address: - Adresse du service caché : + + Hidden address: + - - Tor bootstrap status: - Statut de l'amorçage de Tor : - - - - + + Not set Non défini @@ -25405,12 +23832,57 @@ p, li { white-space: pre-wrap; } Adresse Onion : - + + Error + Erreur + + + + Not connected + Non connecté + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path Vérification que Tor est accessible dans votre chemin d'exécutables - + [Waiting for Tor...] [En attente de Tor ...] @@ -25418,21 +23890,17 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor Tor - - <p>This version of Retroshare uses Tor to connect to your friends.</p> - <p>Cette version de Retroshare utilise Tor pour se connecter à vos amis.</p> - <p>This version of Retroshare uses Tor to connect to your trusted nodes.</p> - + Tor is currently offline Tor est hors ligne actuellement @@ -25443,11 +23911,12 @@ p, li { white-space: pre-wrap; } + No tor configuration Pas de configuration de Tor - + Tor proxy is OK @@ -25475,7 +23944,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options Options de transfert @@ -25486,7 +23955,7 @@ p, li { white-space: pre-wrap; } Maximum de téléchargements simultanés : - + Shared Directories Dossiers partagés @@ -25496,22 +23965,27 @@ p, li { white-space: pre-wrap; } Partager automatiquement le dossier de réception (recommandé) - - Edit Share - Modifier le partage - - - + Directories - + + Configure shared directories + Configurer les dossier partagés + + + Auto-check shared directories every Vérifier automatiquement le partage toutes les : + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) minute(s) @@ -25596,7 +24070,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -25605,7 +24079,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -25630,7 +24109,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming Streaming @@ -25689,38 +24173,13 @@ p, li { white-space: pre-wrap; } Trust friend nodes with banned files - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> est capable de transférer des fichiers et d'effectuer des recherches entre personnes qui ne sont pas amies. Cependant, ce trafic se fait à travers une liste de contacts anonymes.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Vous pouvez paramétrer le type de partage dans la fenêtre de partage de dossier :</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Visible par mes amis</span>: les fichiers sont visibles par mes amis.</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Partage anonyme</span>: les fichiers sont accessibles anonymement par des tunnels F2F.</li></ul></body></html> - Max. tunnel req. forwarded per second: Nombre max. de requêtes de tunnels transmises par sec. : - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - <html><head/><body><p><span style=" font-weight:600;">Streaming </span> a pour conséquence que le transfert demande des morceaux de fichier de taille de 1 Mo en ordre croissant, ceci facilitant la prévisualisation lors du téléchargement. <span style=" font-weight:600;">Random</span> est purement aléatoire et favorise le comportement en essaimage. <span style=" font-weight:600;">Progressif</span> est un compromis, choisissant le prochain morceau au hasard dans moins de 50 Mo après la fin du fichier partiel. Cela permet un certain aléatoire tout en empêchant des grands temps d'initialisation de fichiers vides.</p></body></html> - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> <html><head/><body><p>Retroshare suspendra tous les transferts et la sauvegarde de fichier de configuration si l'espace disque descend en dessous de cette limite. Cela empêche la perte d'informations sur certains systèmes. Une fenêtre contextuelle vous avertira si cela arrive.</p></body></html> @@ -25730,7 +24189,17 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Cette valeur contrôle le nombre de requêtes de tunnels que votre pair peut transmettre par seconde. </p><p> Si vous avez une grande bande passante, vous pouvez l'augmenter jusqu'à 30-40, pour permettre statistiquement aux tunnels plus long de passer. Soyez très prudent cependant, car cela génère de nombreux petits paquets qui peuvent considérablement ralentir le transfert de vos propres fichiers. </p><p>La valeur par défaut est de 20. Si vous n'êtes pas certain, gardez là ainsi.</p></body></html> - + + Warning + Attention + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory Spécifier le dossier des fichiers terminés @@ -25758,7 +24227,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed Téléchargement terminé @@ -25782,39 +24251,23 @@ p, li { white-space: pre-wrap; } %1 completed transfer - - You have %1 completed downloads - Vous avez %1 téléchargements terminés - - - You have %1 completed download - Vous avez %1 téléchargement terminé - - - %1 completed downloads - %1 téléchargements terminés - - - %1 completed download - %1 téléchargement terminé - TransfersDialog - - + + Downloads Téléchargements - + Uploads Envois - + Name i.e: file name Nom @@ -26021,11 +24474,7 @@ p, li { white-space: pre-wrap; } Spécifier... - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1> <p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p> <p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p> <p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Partage de fichiers</h1> <p>Retroshare utilise deux modes de transfert de fichiers : les transferts directs depuis vos amis, et les transferts distants anonymes par tunnels. En plus, le transfert de fichier est multi-source et permet l'essaimage (vous pouvez être une source pendant le téléchargement) </p> <p>Vous pouvez partager des fichiers en utilisant l'icône <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> dans la barre latérale gauche. Ces fichiers seront listés dans l'onglet "Vos fichiers". Vous pouvez décider pour chaque groupe d'amis s'ils peuvent ou pas voir ces fichiers dans l'onglet Mes amis</p> <p>L'onglet "Rechercher" liste les fichiers de vos amis et des fichiers distants qui peuvent être atteints anonymement en utilisant le système à effet tunnel à sauts multiples.</p> - - - + Move in Queue... Mettre en file d'attente... @@ -26050,7 +24499,7 @@ p, li { white-space: pre-wrap; } Choisir le répertoire - + Anonymous end-to-end encrypted tunnel 0x Tunnel chiffré de bout en bout anonyme 0x @@ -26071,7 +24520,7 @@ p, li { white-space: pre-wrap; } Retroshare - + @@ -26104,7 +24553,17 @@ p, li { white-space: pre-wrap; } Le fichier %1 n'est pas terminé. Si c'est un fichier multimédia, essayez de le prévisualiser. - + + Warning + Attention + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name Changer le nom du fichier @@ -26119,7 +24578,7 @@ p, li { white-space: pre-wrap; } S'il vous plaît entrez un nouveau--et valide--nomdefichier - + Expand all Tout déplier @@ -26246,23 +24705,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Colonnes - + File Transfers Transferts de fichiers - + Path Chemin @@ -26272,7 +24726,7 @@ p, li { white-space: pre-wrap; } Afficher la colonne des chemins - + Could not delete preview file N'a pas pu supprimer le fichier d'aperçu @@ -26282,7 +24736,7 @@ p, li { white-space: pre-wrap; } Le réessayer ? - + Create Collection... Créer une collection ... @@ -26297,7 +24751,12 @@ p, li { white-space: pre-wrap; } Vue collection ... - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Collection Collection @@ -26307,7 +24766,7 @@ p, li { white-space: pre-wrap; } %1 tunnels - + Anonymous tunnel 0x Tunnel anonyme 0x @@ -26528,10 +24987,6 @@ p, li { white-space: pre-wrap; } File transfer tunnels - - Anonymous tunnels - Tunnels anonymes - Authenticated tunnels @@ -26725,12 +25180,17 @@ p, li { white-space: pre-wrap; } Formulaire - + Enable Retroshare WEB Interface Activer l'interface WEB de Retroshare - + + Status: + + + + Web parameters Paramètres web @@ -26764,27 +25224,33 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Note: these settings do not affect retroshare-service, which has a command line switch to activate the web interface and select the listening port.</p></body></html> - - Port: - Port: - Allow access from all IP addresses (Default: localhost only) - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Interface WEB</h1> <p>L'interface web vous permet de contrôler Retroshare à partir de votre navigateur. Plusieurs périphériques peuvent partager le contrôle d'une instance Retroshare. Donc, vous pourriez commencer une conversation sur une tablette et utiliser plus tard un ordinateur de bureau pour la continuer.</p><p>Attention : ne pas exposer l'interface web à l'Internet, car il n'y a aucun contrôle d'accès et aucun chiffrement. Si vous voulez utiliser l'interface web sur Internet, utiliser un tunnel SSH ou un proxy afin de sécuriser la connexion.</p> - + Webinterface not enabled Interface web non permise @@ -26794,12 +25260,12 @@ p, li { white-space: pre-wrap; } L'interface web n'est pas activée. Activez là via Options -> Interface web. - + failed to start Webinterface échec de lancement de l'interface web - + Webinterface Interface web @@ -26936,11 +25402,7 @@ p, li { white-space: pre-wrap; } Pages Wiki - New Group - Nouveau groupe - - - + Page Name Nom de la page @@ -26955,7 +25417,7 @@ p, li { white-space: pre-wrap; } Id d'origine - + << << @@ -27043,7 +25505,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History Historique des modifications de la page @@ -27078,7 +25540,7 @@ p, li { white-space: pre-wrap; } PageId - + \/ \/ @@ -27108,14 +25570,18 @@ p, li { white-space: pre-wrap; } Mots clés - - + + History + Historique + + + Show Edit History Afficher l'historique des modifications - + Status Statut @@ -27136,7 +25602,7 @@ p, li { white-space: pre-wrap; } Revenir - + Submit Soumettre @@ -27208,10 +25674,6 @@ p, li { white-space: pre-wrap; } WireDialog - - TimeRange - TimeRange - Create Account @@ -27223,16 +25685,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - Rafraîchir - - - + Settings @@ -27247,7 +25700,7 @@ p, li { white-space: pre-wrap; } Autres - + Who to Follow @@ -27267,7 +25720,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -27297,85 +25750,17 @@ p, li { white-space: pre-wrap; } - Last Month - Mois dernier - - - Last Week - Semaine dernière - - - Today - Aujourd'hui - - - New - Nouveau - - - from - De - - - until - jusqu'à - - - Search/Filter - Rechercher/Filtrer - - - Network Wide - Tout le réseau - - - Manage Accounts - Gestionnaire de comptes - - - Showing: - Affichage : - - - + Yourself Moi - - Friends - Amis - Following Following - Custom - Personnalisé - - - Account 1 - Compte 1 - - - Account 2 - Compte 2 - - - Account 3 - Compte 3 - - - CheckBox - CheckBox - - - Post Pulse to Wire - Publier Pulse sur Wire - - - + RetroShare @@ -27438,35 +25823,42 @@ p, li { white-space: pre-wrap; } Formulaire - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + + + + Location: Emplacement : - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -27511,11 +25903,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + N/A + + + + Following + Following + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Inconnue @@ -27593,7 +26015,7 @@ p, li { white-space: pre-wrap; } %1a %2j - + k e.g: 3.1 k k @@ -27626,15 +26048,11 @@ p, li { white-space: pre-wrap; } Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif *.webp) - - Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - Images (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - pgpid_item_model - + Do you accept connections signed by this profile? @@ -27753,10 +26171,6 @@ p, li { white-space: pre-wrap; } Denied - - - - - - PGP key signed by you diff --git a/retroshare-gui/src/lang/retroshare_hu.ts b/retroshare-gui/src/lang/retroshare_hu.ts index 7ef052108..d5967ea59 100644 --- a/retroshare-gui/src/lang/retroshare_hu.ts +++ b/retroshare-gui/src/lang/retroshare_hu.ts @@ -84,13 +84,6 @@ Csak rejtett csomópont - - AddCommentDialog - - Add Comment - Hozzászólás írása - - AddFileAssociationDialog @@ -129,12 +122,12 @@ RetroShare: Összetett keresés - + Search Criteria Keresési feltétel - + Add a further search criterion. További keresési feltétel hozzáadása. @@ -144,7 +137,7 @@ Keresési feltételek törlése. - + Cancels the search. Keresés megszakítása. @@ -164,177 +157,6 @@ Keresés - - AlbumCreateDialog - - Create Album - Album létrehozása - - - Album Name: - Album neve: - - - Category: - Kategória: - - - Animals - Állatok - - - Family - Család - - - Friends - Barátok - - - Flowers - Virágok - - - Holiday - Vakáció - - - Landscapes - Tájegységek - - - Pets - Háziállatok - - - Portraits - Portrék - - - Travel - Utazás - - - Work - Munka - - - Random - Véletlenszerű - - - Caption: - Képaláírás: - - - Where: - Helyszín: - - - Photographer: - Fényképezte: - - - Description: - Leírás: - - - Share Options - Megosztási beállítások - - - Policy: - Szabályok: - - - Quality: - Minőség: - - - Comments: - Hozzászólások: - - - Identity: - Személyazonosság: - - - Public - Publikus - - - Restricted - Korlátozott - - - Resize Images (< 1Mb) - Képek átméretezése (< 1Mb) - - - Resize Images (< 10Mb) - Képek átméretezése (< 10Mb) - - - Send Original Images - Eredeti képek küldése - - - No Comments Allowed - Hozzászólások letiltva - - - Authenticated Comments - Hitelesített hozzászólások - - - Any Comments Allowed - Minden hozzászólás engedélyezve - - - Publish with Identity - Küldés személyazonossággal - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Dobd be ide a képeket, majd kattints rájuk, hogy szerkeszd a részleteiket.</span></p></body></html> - - - Back - Vissza - - - Add Photos - Fényképek hozzáadása - - - Publish Album - Album közzététele - - - Untitle Album - Névtelen album - - - Say something about this album... - Mondj valamit az albumról... - - - Where were these taken? - Ezek hol készültek? - - - Load Album Thumbnail - Album bélyegkép betöltése - - AlbumDialog @@ -343,19 +165,11 @@ p, li { white-space: pre-wrap; } Album Album - - Album Thumbnail - Album bélyegkép - TextLabel Címke - - Summary - Összefoglalva - Album Title: @@ -371,34 +185,6 @@ p, li { white-space: pre-wrap; } Caption Képaláírás - - Where: - Helyszín: - - - When - Mikor - - - Description: - Leírás: - - - Share Options - Megosztási beállítások - - - Comments - Hozzászólások - - - Publish Identity - Személyazonosság közzététele - - - Visibility - Láthatóság - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -767,7 +553,7 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. Vigyázat: Az itt látható szolgáltatások kísérleti jellegűek, viszont örömmel fogadjuk segítséged a tesztelésben. @@ -783,14 +569,6 @@ p, li { white-space: pre-wrap; } Circles Körök - - GxsForums - Gxs fórumok - - - GxsChannels - Gxs csatornák - The Wire @@ -802,10 +580,23 @@ p, li { white-space: pre-wrap; } Fényképek + + AspectRatioPixmapLabel + + + Save image + Kép mentése + + + + Copy image + + + AttachFileItem - + %p Kb %p Kb @@ -842,17 +633,13 @@ p, li { white-space: pre-wrap; } Browse... - - Add Avatar - Avatár hozzáadása - Remove Eltávolítás - + Set your Avatar picture Avatár beállítása @@ -871,10 +658,6 @@ p, li { white-space: pre-wrap; } Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - Avatár betöltése - AvatarWidget @@ -943,22 +726,10 @@ p, li { white-space: pre-wrap; } Visszaállítás - Receive Rate - Fogadási arány - - - Send Rate - Küldési arány - - - + Always on Top Mindig felül - - Style - Stílus - Changes the transparency of the Bandwidth Graph @@ -974,23 +745,11 @@ p, li { white-space: pre-wrap; } % Opaque % átlátszóság - - Save - Mentés - - - Cancel - Mégse - Since: Átvitel kezdete: - - Hide Settings - Beállítások elrejtése - BandwidthStatsWidget @@ -1063,7 +822,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment Hozzászólás @@ -1093,12 +852,12 @@ p, li { white-space: pre-wrap; } - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> <p><font color="#ff0000"><b>Az üzenet szerzője (azonosító: %1) bannolva van.</b> - + ago @@ -1106,7 +865,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up Szavazás mellette @@ -1126,7 +885,7 @@ p, li { white-space: pre-wrap; } \/ - + Posted by @@ -1164,7 +923,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up Szavazás mellette @@ -1184,7 +943,7 @@ p, li { white-space: pre-wrap; } \/ - + Click to view picture @@ -1214,7 +973,7 @@ p, li { white-space: pre-wrap; } Megosztás - + Toggle Message Read Status Üzenet olvasottságának váltása @@ -1224,7 +983,7 @@ p, li { white-space: pre-wrap; } Új - + TextLabel @@ -1232,12 +991,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this Tetszik - + 0 0 @@ -1257,18 +1016,18 @@ p, li { white-space: pre-wrap; } Avatár - + New Comment - + Copy RetroShare Link - + Expand Lenyitás @@ -1283,12 +1042,12 @@ p, li { white-space: pre-wrap; } - + Name Név - + Comm value @@ -1457,17 +1216,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels Csatornák - + Tabs Fülek - + General Általános @@ -1477,11 +1236,17 @@ p, li { white-space: pre-wrap; } - Load posts in background (Thread) - Hozzászólások betöltése a háttérben (Fonál) + + Downloads + Letöltések - + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab Minden egyes csatorna megnyitása új fülön @@ -1489,7 +1254,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1512,7 +1277,7 @@ into the image, so as to ChannelsCommentsItem - + I like this Tetszik @@ -1537,18 +1302,18 @@ into the image, so as to Avatár - + New Comment - + Copy RetroShare Link - + Expand Lenyitás @@ -1563,7 +1328,7 @@ into the image, so as to - + Name Név @@ -1573,17 +1338,7 @@ into the image, so as to - - Comment - Hozzászólás - - - - Comments - Hozzászólások - - - + Hide Elrejt @@ -1591,7 +1346,7 @@ into the image, so as to ChatLobbyDialog - + Name Név @@ -1782,7 +1537,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby Társalgószoba megjelenítése @@ -1794,22 +1549,6 @@ into the image, so as to Chats Társalgószobák - - You have %1 new messages - %1 új üzeneted van - - - You have %1 new message - %1 új üzeneted van - - - %1 new messages - %1 új üzenet - - - %1 new message - %1 új üzenet - You have %1 mentions @@ -1831,13 +1570,14 @@ into the image, so as to - + + Unknown Lobby Ismeretlen szoba - - + + Remove All Összes eltávolítása @@ -1845,13 +1585,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Név - + Count Résztvevők száma @@ -1861,33 +1601,7 @@ into the image, so as to Téma - - Private Subscribed chat rooms - Feliratkozásaid: Privát társalgószobák - - - - - Public Subscribed chat rooms - Feliratkozásaid: Nyilvános társalgószobák - - - - Private chat rooms - Privát társalgószobák - - - - - Public chat rooms - Nyilvános társalgószobák - - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/images/add_24x24.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Társalgószobák</h1> <p>A társalgószobák az IRC-hez hasonlóan működnek. Névtelen módon beszélgethetsz, anélkül, hogy fel kellene venned a személyeket barátnak.</p> <p>Egy társalgószoba lehet nyilvános (a barátaid látják) vagy privát (a barátaid nem látják, mindaddig míg nem hívod meg őket: <img src=":/images/add_24x24.png" width=%2/>). Ha meghívnak egy privát szobába, akkor válik számodra láthatóvá, ha egy barátod is belépett az adott szobába.</p> <p>A bal oldali listában találhatók azok a szobák, amikbe a barátaid bejelentkeztek. Továbbá <ul> <li>Létrehozatsz új szobát Jobb klikkel</li> <li>Dupla kattintással belépsz a szobába. Ekkor a szoba láthatóvá válik a további barátaid számára.</li> </ul> Megjegyzés: A társalgószobák zökkenőmentes működéséhez nem árt ha pontos a számítógép órája. Vess rá egy pillantást! </p> - - - + Create chat room Társalgószoba létrehozása @@ -1897,7 +1611,7 @@ into the image, so as to Szoba elhagyása - + Create a non anonymous identity and enter this room Hozz létre egy személyazonosságot, amely nem Álnév típusú és lépj be a szobába @@ -1956,12 +1670,12 @@ Kattints egy társalgószobára a bal oldali listában, hogy lásd a részleteke Kattints duplán egy társalgószobára a belépéshez. - + %1 invites you to chat room named %2 %1 meghívott téged a %2 nevű társalgószobába - + Choose a non anonymous identity for this chat room: Ehhez a társalgószobához válassz nyilvános felhasználónevet: @@ -1971,31 +1685,31 @@ Kattints duplán egy társalgószobára a belépéshez. Válassz személyazonosságot ehhez a szobához: - Create chat lobby - Társalgószoba létrehozása - - - + [No topic provided] [Nincs téma beállítva] - Selected lobby info - Kiválasztott csevegőszoba adatai - - - + + Private Privát - + + + Public Publikus - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted Névtelen azonosítók elfogadottak @@ -2005,42 +1719,25 @@ Kattints duplán egy társalgószobára a belépéshez. Automatikus feliratkozás megszüntetése - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe Automatikus feliratkozás engedélyezése - + Search Chat lobbies Társalgószobák keresése - + Search Name Név keresése - Subscribed - Feliratkozva - - - + Columns Oszlopok - - Yes - Igen - - - No - Nem - Chat rooms @@ -2052,47 +1749,47 @@ Kattints duplán egy társalgószobára a belépéshez. - + Chat Room info - + Chat room Name: Társalgószoba neve: - + Chat room Id: Társalgószoba azonosító: - + Topic: Téma: - + Type: Típus: - + Security: Biztonság: - + Peers: Partnerek: - - - - - - + + + + + + TextLabel Szövegcímke @@ -2107,13 +1804,24 @@ Kattints duplán egy társalgószobára a belépéshez. Névtelen azonosítók nem engedélyezettek - + Show Megjelenítés - + + Private Subscribed + + + + + + Public Subscribed + + + + column oszlop @@ -2127,7 +1835,7 @@ Kattints duplán egy társalgószobára a belépéshez. ChatMsgItem - + Remove Item Eltávolítás @@ -2172,46 +1880,22 @@ Kattints duplán egy társalgószobára a belépéshez. ChatPage - + General Általános - - Distant Chat - Távoli beszélgetés - Everyone Mindenki - - Contacts - Kapcsolatok - Nobody Senki - Accept encrypted distant chat from - Titkosított távoli beszélgetés fogadása tőle: - - - Chat Settings - Beszélgetés beállításai - - - Enable Emoticons Private Chat - Hangulatjelek engedélyezése Privát beszélgetésnél - - - Enable Emoticons Group Chat - Hangulatjelek engedélyezése Csoportos beszélgetésnél - - - + Enable custom fonts Egyéni betűtípus engedélyezése @@ -2220,10 +1904,6 @@ Kattints duplán egy társalgószobára a belépéshez. Enable custom font size Egyéni betűméret engedélyezése - - Minimum font size - Minimális betűméret - Enable bold @@ -2235,7 +1915,7 @@ Kattints duplán egy társalgószobára a belépéshez. Dőlt betűk engedélyezése - + General settings @@ -2260,11 +1940,7 @@ Kattints duplán egy társalgószobára a belépéshez. Beágyazott képek betöltése - Chat Lobby - Társalgószoba - - - + Blink tab icon Villogó ikon a fülön @@ -2273,10 +1949,6 @@ Kattints duplán egy társalgószobára a belépéshez. Do not send typing notifications Ne küldjön értesítést arról, ha írok - - Private Chat - Privát beszélgetés - Open Window for new chat @@ -2298,11 +1970,7 @@ Kattints duplán egy társalgószobára a belépéshez. Villogó ikon az ablakon/fülön - Chat Font - Beszélgetés betűtípusa - - - + Change Chat Font Beszélgetés betűtípusának megváltoztatása @@ -2312,14 +1980,10 @@ Kattints duplán egy társalgószobára a belépéshez. Beszélgetés betűtípusa: - + History Előzmények - - Style - Stílus - @@ -2334,17 +1998,13 @@ Kattints duplán egy társalgószobára a belépéshez. Variant: Változat: - - Group chat - Csoportos beszélgetés - Private chat Privát beszélgetés - + Choose your default font for Chat. Válassz betűtípust a Beszélgetéshez. @@ -2408,22 +2068,28 @@ Kattints duplán egy társalgószobára a belépéshez. <html><head/><body><p align="justify">In this tab you can setup how many chat messages Retroshare will keep saved on the disc and how much of the previous conversation it will display, for the different chat systems. The max storage period allows to discard old messages and prevents the chat history from filling up with volatile chat (e.g. chat lobbies and distant chat).</p></body></html> <html><head/><body><p align="justify">Ezen a fülön beállíthatod, hogy a különböző típusú üzenetekből mennyit tároljon el a RetroShare a merevlemezen és hogy mennyi előző beszélgetést állítson vissza az aktuális ablakba. A maximális tárolási idő beállítása lehetővé teszi a régi üzenetek mellőzését, illetve segít megakadályozni, hogy az előzmények tele legyenek kevésbé fontos beszélgetésekkel (például egyes társalgószobák vagy távoli üzenetek előzményei). </p></body></html> - - Chatlobbies - Társalgószobák - Enabled: Engedélyezve: - + Search Keresés - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2433,7 +2099,17 @@ Kattints duplán egy társalgószobára a belépéshez. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms Társalgószobák @@ -2530,11 +2206,7 @@ Kattints duplán egy társalgószobára a belépéshez. Tárolási idő napokban (0=végtelen) - Search by default - Keresés alapértelmezései - - - + Case sensitive Kis- és nagybetű érzékeny @@ -2573,10 +2245,6 @@ Kattints duplán egy társalgószobára a belépéshez. Threshold for automatic search Automatikus keresés küszöb - - Default identity for chat lobbies: - Alapértelmezett személyazonosság a társalgószobákhoz: - Show Bar by default @@ -2644,7 +2312,7 @@ Kattints duplán egy társalgószobára a belépéshez. ChatToaster - + Show Chat Beszélgetés mutatása @@ -2680,7 +2348,7 @@ Kattints duplán egy társalgószobára a belépéshez. ChatWidget - + Close Bezárás @@ -2715,12 +2383,12 @@ Kattints duplán egy társalgószobára a belépéshez. Dőlt - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon Hangulatjel beillesztése @@ -2729,10 +2397,6 @@ Kattints duplán egy társalgószobára a belépéshez. Attach a Picture Kép csatolása - - <html><head/><body><p>QToolButton:disabled {</p><p> image: url(:/icons/png/send-message-blocked.png) ;</p><p>}</p><p><br/></p></body></html> - <html><head/><body><p>QToolButton:disabled {</p><p> image: url(:/icons/png/send-message-blocked.png) ;</p><p>}</p><p><br/></p></body></html> - Strike @@ -2804,11 +2468,6 @@ Kattints duplán egy társalgószobára a belépéshez. Insert horizontal rule Vízszintes vonalzó beillesztése - - - Save image - Kép mentése - Import sticker @@ -2846,7 +2505,7 @@ Kattints duplán egy társalgószobára a belépéshez. - + is typing... éppen ír... @@ -2870,7 +2529,7 @@ a HTML átalakítás után. Válassz betütípust. - + Do you really want to physically delete the history? Tényleg törölni akarod az előzményeket? @@ -2920,7 +2579,7 @@ a HTML átalakítás után. elfoglalt és valószínűleg nem fog válaszolni - + Find Case Sensitively Kis- és nagybetű érzékenység szerinti keresés @@ -2942,7 +2601,7 @@ a HTML átalakítás után. Ne hagyd abba a színezést X elem megtalálása után (több CPU erőforrás szükséges) - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> <b>Előző keresése </b><br/><i>Ctrl+Shift+G</i> @@ -2957,16 +2616,12 @@ a HTML átalakítás után. <b>Keresés </b><br/><i>Ctrl+F</i> - + (Status) (Állapot) - Set text font & color - Betűtípus és szín beállítása - - - + Attach a File Fájl csatolása @@ -2982,12 +2637,12 @@ a HTML átalakítás után. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> <b>Kiválasztott szöveg megjelölése</b><br><i>Ctrl+M</i> - + Person id: Személyazonosító @@ -2999,12 +2654,12 @@ Double click on it to add his name on text writer. A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz. - + Unsigned Aláiratlan - + items found. találat. @@ -3024,7 +2679,7 @@ A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz.Írj be egy üzenetet ide - + Don't stop to color after Ne állj le a színezéssel, miután @@ -3050,7 +2705,7 @@ A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz. CirclesDialog - + Showing details: Részletek megjelenítése: @@ -3072,7 +2727,7 @@ A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz. - + Personal Circles Személyes köreim @@ -3098,7 +2753,7 @@ A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz. - + Friends Barátok @@ -3158,7 +2813,7 @@ A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz.Barátok barátai - + External Circles (Admin) Külső körök (Admin) @@ -3174,7 +2829,7 @@ A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz. - + Circles Körök @@ -3226,43 +2881,48 @@ A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz. - + RetroShare RetroShare - + - + Error : cannot get peer details. Hiba: a partner adatai nem elérhetőek. - + Retroshare ID - + <p>This Retroshare ID contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: + + + <b>DNS:</b> : + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3274,7 +2934,7 @@ A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz.Titkosítás - + Not connected Nem csatlakozott @@ -3356,25 +3016,17 @@ A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz.nincs - + <p>This certificate contains: <p>Ez a tanúsítvány tartalmaz: - + <li>a <b>node ID</b> and <b>name</b> <li>egy <b>csomópont azonosítót</b> és <b>nevet</b> - an <b>onion address</b> and <b>port</b> - egy <b>onion címet</b> és <b>portot</b> - - - an <b>IP address</b> and <b>port</b> - egy <b>IP címet</b> és <b>portot</b> - - - + <p>You can use this certificate to make new friends. Send it by email, or give it hand to hand.</p> <p>Használd ezt a tanúsítványt, hogy új barátokat szerezz. Küldd el emailben, vagy juttasd el a címzettnek egyéb módon.</p> @@ -3389,7 +3041,7 @@ A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz.<html><head/><body><p>Ez az <span style=" font-weight:600;">OpenSSL</span> által használt titkosítási eljárás. Az összeköttetés a barátok csomópontjaihoz</p><p>mindig erősen titkosított és ha a DHE jelen van, akkor az összeköttetés további </p><p>&quot;tökéletes továbbítási titkosítást&quot;.</p> használ.</body></html> - + with ­ @@ -3406,118 +3058,16 @@ A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz.Connect Friend Wizard Barát hozzáadása varázsló - - Add a new Friend - Új barát hozzáadása - - - &You get a certificate file from your friend - &Tanúsítvány fájl érkezett a barátodtól - - - &Make friend with selected friends of my friends - &Barátaim barátjainak felvétele barátként - - - &Send an Invitation by Email - (Your friend will receive an email with instructions how to download RetroShare) - &Küldj meghívót emailben - (A címzett emailben kapja meg hogyan kell letölteni a Retroshare-t) - - - Include signatures - Aláírásokat tartalmaz - - - Copy your Cert to Clipboard - Tanúsítványod másolása a vágólapra - - - Save your Cert into a File - Tanúsítványod mentése fájlba - - - Run Email program - Levelező program indítása - Open Cert of your friend from File Ismerős tanúsítványának megnyitása fájlból - - Open certificate - Tanusítvány megnyitása - - - Please, paste your friend's Retroshare certificate into the box below - Kérlek illeszd be a barátod Retroshare tanúsítványát az alábbi mezőbe - - - Certificate files - Tanúsítvány fájlok - - - Use PGP certificates saved in files. - Fájlokba mentett PGP tanúsítványok használata. - - - Import friend's certificate... - Barát tanúsítványának importálása - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - Készíttetned kell egy fájlt, ami tartalmazza a tanúsítványodat, majd ezt el kell juttatnod a barátodhoz. Természetesen használhatsz korábban készített fájlt is. - - - Export my certificate... - Tanúsítványom exportálása... - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - Dobd be ebbe az ablakba a barátod tanúsítványát, vagy add meg az elérési útját az alábbi mezőben - - - Browse - Böngészés - - - Friends of friends - Barátok barátai - - - Select now who you want to make friends with. - Most válaszd ki, hogy kivel szeretnél baráti kapcsolatot létrehozni. - - - Show me: - Mutasd - - - Make friend with these peers - Barátkozás velük - RetroShare ID RetroShare azonosító - - Use RetroShare ID for adding a Friend which is available in your network. - RetroShare azonosító használata egy a hálózatodban elérhető barát felvételéhez. - - - Add Friends RetroShare ID... - Barát RetroShare azonosítójának megadása... - - - Paste Friends RetroShare ID in the box below - Illeszd be az alábbi mezőbe a barát RetroShare azonosítóját - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - Írd be a barátod RetroShare azonosítóját! Pl.: Partner@BDE8D16A46D938CF - RetroShare is better with Friends @@ -3559,27 +3109,7 @@ A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz.Email - Invite Friends by Email - Barátok meghívása emailben - - - Enter your friends' email addresses (separate each one with a semicolon) - Írd be a barátaid email címeit (különítsd el őket egy-egy pontosvesszővel) - - - Your friends' email addresses: - A barátaid email címei: - - - Enter Friends Email addresses - Írd be a barátaid email címeit - - - Subject: - Tárgy: - - - + @@ -3595,78 +3125,32 @@ A nevet kettős kattintással hozzáadhatod a szövegszerkesztőhöz.A kérelem részletei - + Peer details Partner részletei - + Name: Név: - - Email: - Email: - - - Node: - Csomópont: - - - Please note that RetroShare will require excessive amounts of bandwidth, memory and CPU if you add too many friends. You can add as many friends as you like, but more than 40 will probably require too much -resources. - Kérlek vedd figyelembe, hogy a RetroShare sok sávszélességet, memóriát vagy CPU használatot igényel, ha túl sok barátot veszel fel. Természetesen annyi barátot vehetsz fel amennyit csak szeretnél, de 40-nél több barát felvétele esetleg túl sok -erőforrást igényel. - Location: Hely: - + Options Beállítások - This wizard will help you to connect to your friend(s) to RetroShare network.<br>Select how you would like to add a friend: - Ez a varázsló segít abban, hogy csatlakozhass a barát(ok)hoz a RetroShare hálózaton keresztül. <br>Válaszd ki, miként szeretnéd felvenni: - - - Enter the certificate manually - Tanúsítvány beírása kézzel - - - Enter RetroShare ID manually - RetroShare azonosító beírása kézzel - - - &Send an Invitation by Web Mail Providers - &Küldés és meghívás webes email kiszolgálókon keresztül - - - Recommend many friends to each other - Ajánlj barátokat egymásnak - - - RetroShare certificate - RetroShare tanúsítvány - - - Please paste below your friend's Retroshare certificate - Kérlek illeszd be alább a barátod Retroshare tanúsítványát - - - Paste certificate - Tanúsítvány beillesztése - - - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> <html><head/><body><p>A mezőbe a barátod Retroshare tanúsítványát illeszd be. FIGYELEM: ez különbözik a barátod profil kulcsától. Ne illeszd be ide a barátod profil kulcsát (vagy annak egy részét), mert nem fog működni!</p></body></html> - + Add friend to group: Barát hozzáadása a csoporthoz: @@ -3676,7 +3160,7 @@ erőforrást igényel. Barát azonosítása (PGP kulcs aláírása) - + Please paste below your friend's Retroshare ID @@ -3701,16 +3185,22 @@ erőforrást igényel. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with Barát hozzáadása - To accept the Friend Request, click the Finish button. - A baráti kérelem elfogadásához kattints a Kész gombra. - - - + Sorry, some error appeared Sajnálom, hiba történt @@ -3730,32 +3220,27 @@ erőforrást igényel. A barátod részletei: - + Key validity: Kulcs érvényessége: - + Profile ID: - - Signers - Aláírók - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">A barátod kulcsának aláírása alkalmas arra, hogy kifejezd a bizalmad iránta és ezt jelezd a többiek felé. Az aláírások kriptográfiailag bizonyítják, hogy az alábbi kulcsok hitelesnek ismerik el az aktuális PGP kulcsot.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. A személy már szerepel a barátlistádon. Az újbóli felvétele csak az IP címét fogja változtatni. - + To accept the Friend Request, click the Accept button. @@ -3801,49 +3286,17 @@ erőforrást igényel. - + Certificate Load Failed A tanúsítvány betöltése sikertelen - Cannot get peer details of PGP key %1 - A %1 PGP kulcshoz tartozó partner adatainak lehívása sikertelen - - - Any peer I've not signed - Akárki, akit nem írtam alá - - - Friends of my friends who already trust me - Barátaim barátai, akik már megbíznak bennem - - - Signed peers showing as denied - Aláírt partnerek elutasítottként jelennek meg - - - Peer name - Partner neve - - - Also signed by - Aláírva általa is - - - Peer id - Partner azonosító - - - Certificate appears to be valid - Úgy tűnik, érvényes a tanúsítvány - - - + Not a valid Retroshare certificate! Érvénytelen Retroshare tanúsítvány! - + RetroShare Invitation RetroShare meghívás @@ -3865,12 +3318,12 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? Ez a saját tanusítványod! Ugye nem saját magadat akarod ismerősként megadni?! - + @@ -3878,7 +3331,7 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen - + This key is already on your trusted list A kulcs már fenn van a megbízhatók listáján @@ -3918,7 +3371,7 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen Van egy barát felkérésed tőle - + Profile password needed. @@ -3943,7 +3396,7 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen - + Valid Retroshare ID @@ -3953,47 +3406,7 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen - Certificate Load Failed:file %1 not found - Tanúsítvány betöltése sikertelen: nem található ez a fájl: %1 - - - This Peer %1 is not available in your Network - Nem elérhető a hálózatodban %1 azonosítójú partner - - - Use new certificate format (safer, more robust) - Új tanúsítvány formátum használata (biztonságosabb, robusztusabb) - - - Use old (backward compatible) certificate format - Régi típusú tanúsítvány használata (visszafelé kompatibilis) - - - Remove signatures - Aláírások eltávolítása - - - RetroShare Invite - RetroShare meghívás - - - Connect Friend Help - Barát csatlakozása súgó - - - You can copy this text and send it to your friend via email or some other way - Ezt a szöveget másolhatod, majd elküldheted a barátodnak emailben, illetve megoszthatod vele egyéb módon is. - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - A tanúsítványod a vágólapra lett másolva. Illeszd be és küld el a barátodnak emailben vagy oszd meg vele egyéb módon - - - Save as... - Mentés másként... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -4032,11 +3445,7 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen *** Nincs *** - Use as direct source, when available - Közvetlen forrásként használat, amikor lehetséges - - - + IP-Addr: IP-cím: @@ -4046,7 +3455,7 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen IP-cím: - + Show Advanced options Haladó beállítások megjelenítése @@ -4055,10 +3464,6 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">A barátod kulcsának aláírása alkalmas arra, hogy kifejezd a bizalmad iránta és ezt jelezd a többiek felé. Ez segíthet nekik eldönteni, hogy elfogadják-e a kapcsolódást az adott kulcs tulajdonosától. Egy kulcs aláírása csak egy lehetőség, de visszavonhatatlan. Ezért fontold meg és dönts okosan.</span></p></body></html> - - <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> - <html><head/><body><p align="justify">A Retroshare időnként ellenőrzi a barátlistád kereshető fájlokért, melyek megegyeznek az átviteli fájlokkal, azért, hogy közvetlen fájlátvitel valósulhasson meg. Ebben az esetben a barátod tudni fogja, hogy letöltöd azt a fájlt.</p><p align="justify">Hogy elkerüld ezt a viselkedést, és ki szeretnéd hagyni ebből ezt a barátodat, akkor szüntesd meg a doboz kijelölését. Továbbra is lehetőséged lesz a fájl letöltésére tőle, ehhez azonban előbb igényelned kell azt. Például az adott fájl manuális letöltésével a barátod megosztott mappájából. Ez a beállítás egy adott csomóponthoz tartozó összes helyszínre érvényes lesz.</p></body></html> - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> @@ -4069,45 +3474,13 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen <html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> <html><head/><body><p>Azon ismerősök, akiknél ez a beállítás szerepel, nem tudnak kapcsolódni, ha a címük hiányzik az engedélyezettek listájáról. Ez védelmet nyújt az adatforgalom-átirányítás jellegű támadásokkal szemben. Ha ez van beállítva, akkor az elutasított kapcsolatot a &quot;biztonsági hírcsatorna tétel&quot; a Hírcsatornába irányítja. Ott letilthatod vagy engedélyezheted az IP címüket. Ugyanazon csomópont összes helyszinére vonatkozik. </p></body></html> - - Recommend many friends to each others - Barátaid ajánlása egymásnak - - - Friend Recommendations - Ajánlott barátok - - - The text below is your Retroshare certificate. You have to provide it to your friend - Ez a személyes Retroshare tanúsítványod. Ezt kell eljuttatnod a barátaidhoz - - - Message: - Üzenet: - - - Recommend friends - Barátok ajánlása - - - To - Címzett - - - Please select at least one friend for recommendation. - Kérlek, válassz ki az ajánláshoz legalább egy barátot. - - - Please select at least one friend as recipient. - Kérlek, válassz ki legalább egy barátot címzettnek. - Add key to keyring Kulcs hozzáadása a kulcstartóhoz - + This key is already in your keyring Ez a kulcs már szerepel a kulcstartódban @@ -4123,7 +3496,7 @@ távoli üzeneteket szeretnél küldeni ennek a partnernek, de nem veszed fel barátnak. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. A tanúsítvány verziója rossz. Kérlek vedd figyelembe, hogy a v0.6 és a v0.5 hálózatok nem kompatibilisek egymással. @@ -4158,7 +3531,7 @@ távoli üzeneteket szeretnél küldeni ennek a partnernek, IP hozzáadása a fehérlistához - + No IP in this certificate! Ez a tanúsítvány nem tartalmaz IP-t! @@ -4168,27 +3541,10 @@ távoli üzeneteket szeretnél küldeni ennek a partnernek, <p>Ez a tanúsítvány nem tartalmaz IP-t. A felfedezésre és a DHT-re vagy utalva, hogy megtaláld. Mivel fehérlistás engedélyezést kértél, ezért egy biztonsági figyelmeztetést fogsz kapni a Hírek fülön. Itt hozzáadhatod a partner IP-jét a fehérlistához.</p> - - [Unknown] - [Ismeretlen] - - - + Added with certificate from %1 Tanúsítvánnyal hozzáadva innen: %1 - - Paste Cert of your friend from Clipboard - Barát tanúsítványának beillesztése a Vágólapról - - - Certificate Load Failed:can't read from file %1 - Tanúsítvány betöltése sikertelen: nem olvasható az alábbi fájl: %1 - - - Certificate Load Failed:something is wrong with %1 - Tanúsítvány betöltése sikertelen: valami gond van ezzel: %1 - ConnectProgressDialog @@ -4250,7 +3606,7 @@ távoli üzeneteket szeretnél küldeni ennek a partnernek, - + UDP Setup UDP kapcsolat létrehozása @@ -4278,7 +3634,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant Kapcsolódási segéd @@ -4288,17 +3644,20 @@ p, li { white-space: pre-wrap; } Érvénytelen partner azonosító - + + Unknown State Ismeretlen állapot - + + Offline Kilépett - + + Behind Symmetric NAT Szimmetrikus NAT mögött @@ -4308,12 +3667,14 @@ p, li { white-space: pre-wrap; } NAT mögött, DHT nélkül - + + NET Restart Hálózat újraindítása - + + Behind NAT NAT mögött @@ -4323,7 +3684,8 @@ p, li { white-space: pre-wrap; } Nincs DHT - + + NET STATE GOOD! A hálózat elérhető! @@ -4348,7 +3710,7 @@ p, li { white-space: pre-wrap; } RS partnerek keresése - + Lookup requires DHT A felkutatáshoz DHT szükséges @@ -4640,7 +4002,7 @@ p, li { white-space: pre-wrap; } Kérlek, próbáld meg újból importálni a tanúsítványt - + @@ -4648,7 +4010,8 @@ p, li { white-space: pre-wrap; } N/A - + + UNVERIFIABLE FORWARD! Végrehajthatatlan továbbítás! @@ -4658,7 +4021,7 @@ p, li { white-space: pre-wrap; } Végrehajthatatlan továbbítás és nincs DHT - + Searching Keresés @@ -4694,12 +4057,12 @@ p, li { white-space: pre-wrap; } Kör részletei - + Name Név - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> <html><head/><body><p>A kör neve, a kapcsolattartó és a meghívott tagok listája látható lesz az összes meghívott számára. Ha a kör nem privát, akkor látható lesz a meghívott csomópontok szomszédos csomópontjai által is.</p></body></html> @@ -4719,7 +4082,7 @@ p, li { white-space: pre-wrap; } - + IDs Azonosító @@ -4739,18 +4102,18 @@ p, li { white-space: pre-wrap; } Szűrő - + Cancel - + Nickname Becenév - + Invited Members Meghívott tagok @@ -4765,15 +4128,7 @@ p, li { white-space: pre-wrap; } Ismert személyek - ID - Azonosító - - - Type - Típus - - - + Name: Név: @@ -4813,23 +4168,19 @@ p, li { white-space: pre-wrap; } - Only visible to members of: - Csak a következő csoportok tagjai számára látható: - - - - + + RetroShare RetroShare - + Please set a name for your Circle Kérlek, nevezd el a körödet - + No Restriction Circle Selected Nincs korlátozás kiválasztva. @@ -4839,12 +4190,24 @@ p, li { white-space: pre-wrap; } Nincs határ kiválasztva. - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] [Ismeretlen] - + Add Hozzáadás @@ -4854,7 +4217,7 @@ p, li { white-space: pre-wrap; } Eltávolítás - + Search Keresés @@ -4869,10 +4232,6 @@ p, li { white-space: pre-wrap; } Signed Aláírt - - Signed by known nodes - Ismert csomópontok által aláírva - Edit Circle @@ -4889,10 +4248,6 @@ p, li { white-space: pre-wrap; } PGP Identity PGP Személyazonosság - - Anon Id - Névtelen azonosító - Circle name @@ -4915,17 +4270,13 @@ p, li { white-space: pre-wrap; } Új kör létrehozása - + Create Létrehoz - PGP Linked Id - PGP-hez linkelt azonosító - - - + Add Member Tag hozzáadása @@ -4944,7 +4295,7 @@ p, li { white-space: pre-wrap; } Csoport létrehozása - + Group Name: Csoport neve: @@ -4979,7 +4330,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post Új bejegyzés a csatornán @@ -4989,7 +4340,7 @@ p, li { white-space: pre-wrap; } Üzenet - + Post @@ -5050,23 +4401,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Dobáld be a fájlokat / Használd a fájl hozzáadása gombot új fájlok megosztásához.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Másolj/Illessz be RetroShare hivatkozásokat a megosztásaidból</span></p></body></html> - - Add File to Attach - Melléklet csatolása - Add Channel Thumbnail Előnézeti kép hozzáadása - - Message - Üzenet - - - Subject : - Tárgy: - @@ -5152,17 +4491,17 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -5181,17 +4520,18 @@ p, li { white-space: pre-wrap; } The following files will only be shared for 30 days. Think about adding them to a shared directory. - - File already Added and Hashed - A fájl már hozzá van adva és hashelve van. - Please add a Subject Kérlek, adj meg egy tárgyat - + + Cannot publish post + + + + Load thumbnail picture Előnézeti kép betöltése @@ -5206,18 +4546,12 @@ p, li { white-space: pre-wrap; } Elrejt - - + Generate mass data Adattömeg létrehozása - - Do you really want to generate %1 messages ? - Valóban generálni szeretnél %1 üzenetet ? - - - + You are about to add files you're not actually sharing. Do you still want this to happen? Fájlokat fogsz hozzáadni a megosztásodhoz. Biztos ezt szeretnéd tenni? @@ -5251,7 +4585,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message Fórum üzenet beküldése @@ -5260,10 +4594,6 @@ p, li { white-space: pre-wrap; } Forum Fórum - - Subject - Tárgy - Attach File @@ -5284,8 +4614,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -5304,7 +4634,7 @@ p, li { white-space: pre-wrap; } Fájlokat az ablakba dobálva csatolhatsz - + Post @@ -5334,17 +4664,17 @@ p, li { white-space: pre-wrap; } - + No Forum Nincs fórum - + In Reply to Válasz - + Title Cím @@ -5398,7 +4728,7 @@ Törölni szeretnéd? Kép betöltése - + No compatible ID for this forum Nem kompatibilis azonosító ehhez a fórumhoz @@ -5408,8 +4738,8 @@ Törölni szeretnéd? Egyetlen személyazonosságod számára sem engedélyezett a hozzászólás ezen a fórumon. Ennek oka az lehet, hogy a fórum korlátozva van egy olyan körre, amely nem tartalmazza semelyik személyazonosságod, vagy pedig a fórum jelölők megkövetelik a PGP hitelesítésű azonosítókat. - - + + Generate mass data Adattömeg létrehozása @@ -5418,10 +4748,6 @@ Törölni szeretnéd? Do you really want to generate %1 messages ? Valóban generálni szeretnél %1 üzenetet ? - - Send - Küldés - Post as @@ -5436,23 +4762,7 @@ Törölni szeretnéd? CreateLobbyDialog - Create Chat Lobby - Társalgószoba létrehozása - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - A társalgószoba egy központosítatlan, névtelen helyszín a beszélgetésekhez. Az összes résztvevő megkapja az összes üzenetet. A szoba létrehozása után meghívhatod abba barátaidat a barátlistádról. - - - Lobby name: - Chatszoba neve: - - - Lobby topic: - A szoba témája: - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5487,7 +4797,7 @@ Törölni szeretnéd? - + Create @@ -5497,7 +4807,7 @@ Törölni szeretnéd? - + require PGP-signed identities PGP hitelesítésű azonosító megkövetelése @@ -5512,11 +4822,7 @@ Törölni szeretnéd? Válassz ki barátokat a csoportos beszélgetéshez. - Invited friends - Meghívott barátok - - - + Create Chat Room Társalgószoba létrehozása @@ -5537,7 +4843,7 @@ Törölni szeretnéd? Kapcsolatok: - + Identity to use: Használandó személyazonosság: @@ -5545,17 +4851,17 @@ Törölni szeretnéd? CryptoPage - + Public Information Publikus adatok - + Name: Név: - + Location: Hely: @@ -5565,12 +4871,12 @@ Törölni szeretnéd? Helyszín azonosító: - + Software Version: Alkalmazás verziója: - + Online since: Online ettől kezdve: @@ -5590,12 +4896,7 @@ Törölni szeretnéd? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5605,7 +4906,7 @@ Törölni szeretnéd? - + Other Information Egyéb adatok @@ -5615,17 +4916,12 @@ Törölni szeretnéd? - + Profile Profil - - Certificate - Tanúsítvány - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5635,11 +4931,7 @@ Törölni szeretnéd? Aláírásokat tartalmaz - Save Key into a file - Kulcs mentése fájlba - - - + Export Identity Személyazonosság exportálása @@ -5711,33 +5003,33 @@ az importálás gombot, hogy betöltsd. - + TextLabel Szövegcímke - + PGP fingerprint: PGP ujjlenyomat: - - Node information - Csomópont információ - - - + PGP Id : PGP azonosító : - + Friend nodes: Barát csomópontok: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5776,14 +5068,6 @@ az importálás gombot, hogy betöltsd. Node Csomópont - - Create new node... - Új csomópont létrehozása... - - - show statistics window - Statisztika megjelenítése - DHTGraphSource @@ -5835,7 +5119,7 @@ az importálás gombot, hogy betöltsd. DLListDelegate - + B B @@ -6503,7 +5787,7 @@ az importálás gombot, hogy betöltsd. DownloadToaster - + Start file Fájl indítása @@ -6511,38 +5795,38 @@ az importálás gombot, hogy betöltsd. ExprParamElement - + - + to neki - + ignore case nagybetűk figyelmen kívül hagyása - - - dd.MM.yyyy - yyyy.MM.dd + + + yyyy-MM-dd + - - + + KB KB - - + + MB MB - - + + GB GB @@ -6550,12 +5834,12 @@ az importálás gombot, hogy betöltsd. ExpressionWidget - + Expression Widget Feltételek beállítása - + Delete this expression Feltétel törlése @@ -6717,7 +6001,7 @@ az importálás gombot, hogy betöltsd. FilesDefs - + Picture Kép @@ -6727,7 +6011,7 @@ az importálás gombot, hogy betöltsd. Videó - + Audio Hang @@ -6787,11 +6071,21 @@ az importálás gombot, hogy betöltsd. C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Barátok mappái @@ -6913,7 +6207,7 @@ az importálás gombot, hogy betöltsd. - + ID Azonosító @@ -6948,10 +6242,6 @@ az importálás gombot, hogy betöltsd. Show State Állapot megjelenítése - - Trusted nodes - Megbízható csomópontok - @@ -6959,7 +6249,7 @@ az importálás gombot, hogy betöltsd. Csoportok mutatása - + Group Csoport @@ -6995,7 +6285,7 @@ az importálás gombot, hogy betöltsd. Hozzáadás a csoporthoz - + Search Keresés @@ -7011,7 +6301,7 @@ az importálás gombot, hogy betöltsd. Rendezés állapot szerint - + Profile details Profil részletek @@ -7255,7 +6545,7 @@ legalább egy partner nem lett hozzáadva a csoporthoz FriendRequestToaster - + Confirm Friend Request Baráti felkérés jóváhagyása @@ -7272,10 +6562,6 @@ legalább egy partner nem lett hozzáadva a csoporthoz FriendSelectionWidget - - Search : - Keresés: - Sort by state @@ -7297,7 +6583,7 @@ legalább egy partner nem lett hozzáadva a csoporthoz Barát keresése - + Mark all Jelöld mind @@ -7308,16 +6594,132 @@ legalább egy partner nem lett hozzáadva a csoporthoz Egyiket se jelöld + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Név + + + + Node ID + + + + + Address + Cím + + + + Status + Állapot + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + Barátság kezdeményezése + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message Állapot szerkesztése - - + + Broadcast Üzenőfal @@ -7400,33 +6802,38 @@ legalább egy partner nem lett hozzáadva a csoporthoz Alapértelmezett betűtípus visszaállítása - + Keyring Kulcstartó - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Hálózat</h1> <p>A Hálózat fül tartalmazza a barátaid Retroshare csomópontjait: pontosabban azokat a szomszédos Retroshare csomópontokat, akik kapcsolódtak hozzád. </p> <p>Csoportokba rendezheted őket, és így beállíthatod például azt, hogy mely csoportok férhessenek hozzá egy-egy fájlodhoz.</p> <p>Jobb oldalt 3 hasznos fület találsz: <ul> <li>Az Üzenőfal segítségével egyszerre küldhetsz üzenetet az összes csomópontnak</li> <li>A Hálózat gráf a felfedezés információit felhasználva megmutatja, hogy kikkel állasz kapcsolatban.</li> <li>A Kulcstartóban találhatók az összegyűjtött csomópontok kulcsai, leginkább a barátiad csomópontjain keresztül jutnak el hozzád ezek a kulcsok.</li> </ul> </p> - - - + Retroshare broadcast chat: messages are sent to all connected friends. Retroshare üzenőfal: az ide írt üzeneteidet az összes barátod láthatja. - - + + Network Hálózat - + + Friend Server + + + + Network graph Hálózat gráf - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. Add meg az állapotüzenetedet. @@ -7444,7 +6851,17 @@ legalább egy partner nem lett hozzáadva a csoporthoz Jelszó - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters Az összes adatnak legalább 3 karakter hosszúnak kell lennie @@ -7454,17 +6871,12 @@ legalább egy partner nem lett hozzáadva a csoporthoz A jelszavak nem egyeznek - + Port Port - - Use BOB - Használj BOB-t - - - + This password is for PGP Ez egy PGP jelszó @@ -7485,50 +6897,38 @@ legalább egy partner nem lett hozzáadva a csoporthoz Az új tanúsítványod létrehozása meghiúsult, talán rossz PGP jelszót adtál meg. - Options - Beállítások - - - + PGP Key Length PGP kulcs hossza - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node Alap csomópont - TOR/I2P Hidden node - TOR/I2P rejtett csomópont - - - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - Use existing profile - Meglévő profil használata - - - + Node name Csomópont neve - + Node type: @@ -7548,12 +6948,12 @@ legalább egy partner nem lett hozzáadva a csoporthoz - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle Profil mentése @@ -7563,42 +6963,43 @@ legalább egy partner nem lett hozzáadva a csoporthoz - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! Nyomás! - - + + TextLabel Szövegcimke - Advanced options - Haladó beállítások - - - + hidden address rejtett cím - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -7646,13 +7047,13 @@ Most már átmásolhatod egy másik számítógépre Hiba történt. A profilodat nem sikerült elmenteni. - + Import profile Profil importálása - + Create new profile and new Retroshare node Új profil és Retroshare csomópont létrehozása @@ -7662,7 +7063,7 @@ Most már átmásolhatod egy másik számítógépre Új Retroshare csomópont létrehozása - + Tor/I2P address Tor/I2P cím @@ -7697,7 +7098,7 @@ Most már átmásolhatod egy másik számítógépre - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7707,12 +7108,7 @@ Most már átmásolhatod egy másik számítógépre - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -7722,12 +7118,7 @@ Most már átmásolhatod egy másik számítógépre - - I2P instance address with BOB enabled - I2P hivatkozás bekapcsolt BOB-val - - - + I2P instance address I2P hivatkozás címe @@ -7953,36 +7344,13 @@ Most már átmásolhatod egy másik számítógépre Első lépések - + Invite Friends Barátok meghívása - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">A RetroShare nem működhet barátok nélkül. Kattints a gombra a folyamat elindításához.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Küldj emailben egy meghívót a tanúsítványoddal együtt a barátaidnak.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Gondoskodj róla, hogy te is megkapd az ő tanúsítványukat... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Csak akkor csatlakozhattok a barátoddal egymáshoz, ha már mindketten felvettétek a másikat.</span></p></body></html> - - - + Add Your Friends to RetroShare Barátaid hozzáadása a RetroSharehez @@ -7992,95 +7360,103 @@ p, li { white-space: pre-wrap; } Barát hozzáadása - + + Connect To Friends + Csatlakozás a barátokhoz + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Haladó: Port nyitása a tűzfalon + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - Csatlakozás a barátokhoz - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Mikor a barátaid meghívót küldenek, kattints rá, hogy megnyisd a Barátok hozzáadása ablakot.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Illeszd be az abalakba a barátaid tanúsítványait és vedd fel őket!</span></p></body></html> - - - - Advanced: Open Firewall Port - Haladó: Port nyitása a tűzfalon - - - + Further Help and Support További segítség és támogatás - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website RetroShare weboldal megnyitása @@ -8105,7 +7481,7 @@ p, li { white-space: pre-wrap; } Visszajelzés emailben - + RetroShare Invitation RetroShare meghívás @@ -8155,12 +7531,12 @@ p, li { white-space: pre-wrap; } RetroShare visszajelzés - + RetroShare Support RetroShare támogatás - + It has many features, including built-in chat, messaging, Sok funkciója van, többek között beépített társalgó és üzenetküldő. @@ -8284,7 +7660,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat Csoportos beszélgetés mutatása @@ -8292,7 +7668,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] [Ismeretlen] @@ -8462,7 +7838,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title Cím @@ -8475,12 +7851,12 @@ p, li { white-space: pre-wrap; } - + Description Leírás - + Number of Unread message @@ -8505,35 +7881,7 @@ p, li { white-space: pre-wrap; } - Sort Descending Order - Csökkenő sorbarendezés - - - Sort Ascending Order - Növekvő sorbarendezés - - - Sort by Name - Rendezés név szerint - - - Sort by Popularity - Rendezés népszerűség szerint - - - Sort by Last Post - Rendezés utolsó üzenet szerint - - - Sort by Number of Posts - Bejegyzések száma szerinti rendezés - - - Sort by Unread - Olvasatlanság szerinti rendezés - - - + You are admin (modify names and description using Edit menu) @@ -8548,14 +7896,14 @@ p, li { white-space: pre-wrap; } Azonosító - - + + Last Post Utolsó bejegyzés - + Name Név @@ -8566,17 +7914,13 @@ p, li { white-space: pre-wrap; } - + Never Soha - Display - Megjelenítés beállításai - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8589,7 +7933,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and és @@ -8725,7 +8069,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels Csatornák @@ -8736,22 +8080,22 @@ p, li { white-space: pre-wrap; } Csatorna létrehozása - + Enable Auto-Download Automatikus letöltés engedélyezése - + My Channels Csatornáim - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Feliratkozások @@ -8771,12 +8115,12 @@ p, li { white-space: pre-wrap; } Válassz a csatornához letöltési könyvtárat - + Disable Auto-Download Automatikus letöltés tiltása - + Set download directory Állítsd be a letöltési könyvtárat @@ -8811,22 +8155,22 @@ p, li { white-space: pre-wrap; } - + Play Lejátszás - + Open folder Mappa megnyitása - + Open file - + Error Hiba @@ -8846,17 +8190,17 @@ p, li { white-space: pre-wrap; } Ellenőrzés - + Are you sure that you want to cancel and delete the file? - + Can't open folder A mappa nem nyitható meg - + Play File Fájl lejátszása @@ -8866,37 +8210,10 @@ p, li { white-space: pre-wrap; } Nem található %1 fájl - - GxsChannelFilesWidget - - Form - Forma - - - Filename - Fájlnév - - - Size - Méret - - - Title - Cím - - - Published - Közzétéve - - - Status - Állapot - - GxsChannelGroupDialog - + Create New Channel Új csatorna létrehozása @@ -8934,9 +8251,19 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - Feliratkozás a csatornára + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel + @@ -8950,7 +8277,7 @@ p, li { white-space: pre-wrap; } - + Expand Lenyitás @@ -8965,7 +8292,7 @@ p, li { white-space: pre-wrap; } Csatorna leírása - + Loading Töltés @@ -8980,8 +8307,9 @@ p, li { white-space: pre-wrap; } - New Channel - Új csatorna + + Never + Soha @@ -8992,7 +8320,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: Új hozzászólás: @@ -9013,7 +8341,7 @@ p, li { white-space: pre-wrap; } - + Play Lejátszás @@ -9069,28 +8397,24 @@ p, li { white-space: pre-wrap; } Files Fájlok - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - Vigyázz! A fájl törlődni fog kevesbb, mint %1 óra %2 perc múlva. Ha menteni szeretnéd, tedd meg időben. - Hide Elrejt - + New Új - + 0 0 - - + + Comment Hozzászólás @@ -9105,21 +8429,17 @@ p, li { white-space: pre-wrap; } Nem tetszik - Loading - Töltés - - - + Loading... - + Comments Hozzászólások - + Post @@ -9144,115 +8464,16 @@ p, li { white-space: pre-wrap; } Média lejátszása - - GxsChannelPostsWidget - - Post to Channel - Új bejegyzés - - - Add new post - Új hozzászólás - - - Loading - Töltés - - - Search channels - Keresés a csatornákban - - - Title - Cím - - - Search Title - Cím keresése - - - Message - Üzenet - - - Search Message - Üzenet keresése - - - Filename - Fájlnév - - - Search Filename - Keresés a fájlok között - - - No Channel Selected - Nincs csatorna kiválasztva - - - Never - Soha - - - Public - Nyilvános - - - Disable Auto-Download - Automatikus letöltés tiltása - - - Enable Auto-Download - Automatikus letöltés engedélyezése - - - Show files - Mutasd a fájlokat - - - Administrator: - Adminisztrátor: - - - Last Post: - Utolsó bejegyzés - - - unknown - ismeretlen - - - Distribution: - Megosztás - - - Feeds - Hírcsatornák - - - Files - Fájlok - - - Subscribers - Feliratkozottak - - - Description: - Leírás: - - GxsChannelPostsWidgetWithModel - + Post to Channel Új bejegyzés - + Add new post Új hozzászólás @@ -9322,7 +8543,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -9358,7 +8579,7 @@ p, li { white-space: pre-wrap; } - + Comments Hozzászólások @@ -9373,13 +8594,13 @@ p, li { white-space: pre-wrap; } Hírcsatornák - - + + Click to switch to list view - + Show unread posts only @@ -9394,7 +8615,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -9409,7 +8630,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -9469,12 +8690,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -9549,12 +8780,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed Feliratkozva @@ -9605,17 +8837,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -9635,19 +8867,11 @@ p, li { white-space: pre-wrap; } Remove Item Tétel törlése - - for identity - előle: - Grant membership request Tagsági kérelem jóváhagyása - - Revoke membership request - Tagsági kérelem visszavonása - @@ -9738,7 +8962,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container Hozzászólás a tárolóhoz @@ -9751,7 +8975,7 @@ p, li { white-space: pre-wrap; } Forma - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9781,7 +9005,7 @@ p, li { white-space: pre-wrap; } Frissítés - + Comment Hozzászólás @@ -9820,7 +9044,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment Válasz a hozzászólásra @@ -9844,6 +9068,21 @@ p, li { white-space: pre-wrap; } Vote Down Szavazás ellene + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9853,7 +9092,7 @@ p, li { white-space: pre-wrap; } Hozzászólás írása - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9882,26 +9121,10 @@ p, li { white-space: pre-wrap; } - + Post - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Hozzászólás</span></p></body></html> - - - Signed by - Aláírva általa - Reply to Comment @@ -9930,7 +9153,7 @@ before you can comment mielőtt hozzászólhatsz - + It remains %1 characters after HTML conversion. @@ -9972,14 +9195,6 @@ mielőtt hozzászólhatsz Forum moderators can edit/delete/pinup others posts - - Add Forum Admins - Fórum adminisztrátorok hozzáadása - - - Select Forum Admins - Fórum adminisztrátorok kiválasztása - Create @@ -9989,7 +9204,7 @@ mielőtt hozzászólhatsz GxsForumGroupItem - + Subscribe to Forum Feliratkozás a fórumra @@ -10005,7 +9220,7 @@ mielőtt hozzászólhatsz - + Expand Lenyitás @@ -10025,8 +9240,9 @@ mielőtt hozzászólhatsz - Loading - Töltés + + TextLabel + @@ -10057,13 +9273,13 @@ mielőtt hozzászólhatsz GxsForumMsgItem - - + + Subject: Tárgy: - + Unsubscribe To Forum Leiratkozás a fórumról @@ -10074,7 +9290,7 @@ mielőtt hozzászólhatsz - + Expand Lenyitás @@ -10094,21 +9310,17 @@ mielőtt hozzászólhatsz Válasz címzettje: - Loading - Töltés - - - + Loading... - + Forum Feed - + Hide Elrejt @@ -10121,63 +9333,66 @@ mielőtt hozzászólhatsz Forma - + Start new Thread for Selected Forum Új fonál indítása a kiválasztotta fórumban - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Fórumok keresése - Last Post - Utolsó beküldés - - - + New Thread Új szál - - - Threaded View - Fa nézet - - - - Flat View - Egyszerű nézet - - + Title Cím - - + + Date Dátum - + Author Szerző - - Save image - Kép mentése - - - + Loading Töltés - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -10187,12 +9402,7 @@ mielőtt hozzászólhatsz - - Lastest post in thread - - - - + Reply Message Válasz az üzenetre @@ -10216,10 +9426,6 @@ mielőtt hozzászólhatsz Download all files Összes fájl letöltése - - Next unread - Következő olvasatlan - Search Title @@ -10236,31 +9442,23 @@ mielőtt hozzászólhatsz Szerző keresése - Content - Tartalom - - - Search Content - Tartalom keresése - - - + No name Nincs név - - + + Reply Válasz - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -10303,20 +9501,12 @@ mielőtt hozzászólhatsz RetroShare hivatkozás másolása - + Hide Elrejt - Expand - Lenyitás - - - [Banned] - [Letiltva] - - - + [unknown] [ismeretlen] @@ -10346,8 +9536,8 @@ mielőtt hozzászólhatsz - - + + Distribution @@ -10361,26 +9551,6 @@ mielőtt hozzászólhatsz Anti-spam Szemétszűrő - - [ ... Redacted message ... ] - [ ... Szerkesztett üzenet ... ] - - - Anonymous - Névtelen - - - signed - aláírt - - - none - nincs - - - [ ... Missing Message ... ] - [ ... Hiányzó üzenet ... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10450,16 +9620,12 @@ mielőtt hozzászólhatsz Eredeti üzenet - + New thread Új szál - Read status - Elolvasott / nem olvasott - - - + Edit Szerkesztés @@ -10520,7 +9686,7 @@ mielőtt hozzászólhatsz Szerző megitélése - + Show column @@ -10540,7 +9706,7 @@ mielőtt hozzászólhatsz - + Anonymous/unknown posts forwarded if reputation is positive @@ -10592,7 +9758,7 @@ This message is missing. You should receive it later. - + No result. @@ -10602,7 +9768,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -10617,17 +9783,7 @@ This message is missing. You should receive it later. - Information for this identity is currently missing. - A személyazonossághoz tartozó információ jelenleg hiányzik. - - - You have banned this ID. The message will not be -displayed nor forwarded to your friends. - Tiltottad ezt az azonosítót. Az üzenet nem lesz -megjelenítve és nem lesz továbbítva a barátaid számára. - - - + (Latest) (Legutóbbi) @@ -10693,12 +9849,12 @@ megjelenítve és nem lesz továbbítva a barátaid számára. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums Fórum @@ -10729,35 +9885,16 @@ megjelenítve és nem lesz továbbítva a barátaid számára. Egyéb fórumok - - GxsForumsFillThread - - Waiting - Várakozás - - - Retrieving - Lekérdezés - - - Loading - Töltés - - GxsGroupDialog - + Name Név - Add Icon - Ikon hozzáadása - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels Kulccsal rendelkező személyek írhatnak a korlátozott csoportokban és olvashatják, valamint írhatnak a privát csatornákra is. @@ -10766,22 +9903,14 @@ megjelenítve és nem lesz továbbítva a barátaid számára. Share Publish Key Közzétételi kulcs megosztása - - check peers you would like to share private publish key with - Jelöld ki azon partnereidet, akikkel szeretnél privát kulcsot megosztani. - - - Share Key With - Kulcs megosztása velük: - - + Description Leírás - + Message Distribution Üzenet elosztás @@ -10789,7 +9918,7 @@ megjelenítve és nem lesz továbbítva a barátaid számára. - + Public Publikus @@ -10808,14 +9937,6 @@ megjelenítve és nem lesz továbbítva a barátaid számára. New Thread Új fonál - - Required - Szükséges - - - Encrypted Msgs - Titkosított üzenetek - Personal Signatures @@ -10857,7 +9978,7 @@ megjelenítve és nem lesz továbbítva a barátaid számára. - + Comments: Hozzászólások @@ -10880,7 +10001,7 @@ megjelenítve és nem lesz továbbítva a barátaid számára. - + All People @@ -10896,12 +10017,12 @@ megjelenítve és nem lesz továbbítva a barátaid számára. - + Restricted to circle: - + Limited to your friends @@ -10918,23 +10039,23 @@ megjelenítve és nem lesz továbbítva a barátaid számára. - + Message tracking Üzenet követése - - + + PGP signature required PGP hitelesítés szükséges - + Never Soha - + Only friends nodes in group @@ -10950,22 +10071,28 @@ megjelenítve és nem lesz továbbítva a barátaid számára. Kérlek, adj meg egy nevet - + PGP signature from known ID required Szükség van PGP aláírásra egy ismert azonosítótól - + + + [None] + + + + Load Group Logo Csoport logó betöltése - + Submit Group Changes - + Owner: Tulajdonos @@ -10975,12 +10102,12 @@ megjelenítve és nem lesz továbbítva a barátaid számára. - + Info Információ - + ID Azonosító @@ -10990,7 +10117,7 @@ megjelenítve és nem lesz továbbítva a barátaid számára. Utolsó beküldés - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -11065,7 +10192,12 @@ megjelenítve és nem lesz továbbítva a barátaid számára. Aláíratlan és ismeretlen csomóponthoz tartozó azonosítók eltávolítása a kedvencek közül - + + Author: + + + + Popularity Népszerűség @@ -11081,27 +10213,22 @@ megjelenítve és nem lesz továbbítva a barátaid számára. - + Created - + Cancel - + Create - - Author - Szerző - - - + GxsIdLabel Gxs azonosító címke @@ -11109,7 +10236,7 @@ megjelenítve és nem lesz továbbítva a barátaid számára. GxsGroupFrameDialog - + Loading Töltés @@ -11169,7 +10296,7 @@ megjelenítve és nem lesz továbbítva a barátaid számára. Részletek szerkesztése - + Synchronise posts of last... Add meg a szinkronizálandó elmúlt időtartamot... @@ -11226,16 +10353,12 @@ megjelenítve és nem lesz továbbítva a barátaid számára. - + Search for - Share publish permissions - Nyilvános engedélyek megosztása - - - + Copy RetroShare Link RetroShare hivatkozás másolása @@ -11258,7 +10381,7 @@ megjelenítve és nem lesz továbbítva a barátaid számára. GxsIdChooser - + No Signature Nincs aláírás @@ -11271,40 +10394,24 @@ megjelenítve és nem lesz továbbítva a barátaid számára. GxsIdDetails - Loading - Töltés - - - + Not found Nem található - - No Signature - Nincs aláírás - - - + + [Banned] [Letiltva] - - Authentication - Azonosítás - unknown Key ismeretlen kulcs - anonymous - névtelen - - - + Loading... @@ -11314,7 +10421,12 @@ megjelenítve és nem lesz továbbítva a barátaid számára. - + + [Nobody] + + + + Identity&nbsp;name Személyazonosság&nbsp;név @@ -11334,6 +10446,14 @@ megjelenítve és nem lesz továbbítva a barátaid számára. [Ismeretlen] + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -11345,7 +10465,7 @@ megjelenítve és nem lesz továbbítva a barátaid számára. GxsIdStatisticsWidget - + Total identities: @@ -11393,17 +10513,13 @@ megjelenítve és nem lesz továbbítva a barátaid számára. GxsIdTreeItemDelegate - + [Unknown] [Ismeretlen] GxsMessageFramePostWidget - - Loading - Töltés - Loading... @@ -11535,10 +10651,6 @@ megjelenítve és nem lesz továbbítva a barátaid számára. Popularity Népszerüség - - Details - Részletek - @@ -11571,33 +10683,6 @@ megjelenítve és nem lesz továbbítva a barátaid számára. Nem - - GxsTunnelsDialog - - Authenticated tunnels: - Azonosított csatornák - - - Tunnel ID: %1 - Alagút azonosító: %1 - - - status: %1 - állapot: %1 - - - total sent: %1 bytes - elküldve: %1 byte - - - total recv: %1 bytes - fogadva: %1 byte - - - Unknown Peer - Ismeretlen kapcsolat - - HashBox @@ -11810,48 +10895,12 @@ megjelenítve és nem lesz továbbítva a barátaid számára. About Névjegy - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare provides file sharing, chat, messages and channels</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Useful external links to more information:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Wiki</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare's Forum</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Project Page</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Team Blog</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Dev Twitter</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">A RetroShare egy Nyílt Forrású platformok közötti, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">privát és biztonságos decentralizált kommunikációt nyújtó szolgáltatás. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Segítségével biztonságosan oszthatod meg a barátlistádat, mert </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">egy megbízhatósági hálózat: "web-of-trust" által hitelesíti a partnereket és OpenSSL használatával titkosít minden kommunikációt. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">A RetroShare lehetőséget biztosít fájlmegosztásra, beszélgetésre, üzenetküldésre valamint csatornák használatára</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Hasznos linkek további információhoz:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Retroshare Weboldal</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Wiki</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Fórum</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Projekt Oldala</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Csapat Blogja</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Fejlesztői Twitter</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -11867,7 +10916,7 @@ p, li { white-space: pre-wrap; } - + Authors Szerzők @@ -11886,7 +10935,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -11964,12 +11013,12 @@ p, li { white-space: pre-wrap; } Forma - + <html><head/><body><p>Copy your RetroShare ID to clipboard</p></body></html> - + Add friend @@ -11984,7 +11033,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -11993,32 +11042,12 @@ p, li { white-space: pre-wrap; } This is your Retroshare ID. Copy and share with your friends! - - Did you receive a certificate from a friend? - Kaptál egy tanúsítványt egy barátodtól? - - - Add friends certificate - Ismerősök tanusítványainak hozzáadása. - - - Add certificate file - Tanusítvány-fájl hozzáadása - - - Share your RetroShare Key - Saját RetroShare kulcsod megosztása - ... ... - - The text below is your own Retroshare certificate. Send it to your friends - Az alábbi szöveghalmaz a te RetroShare tanusítványod. Küld el a barátaidnak. - Open Source cross-platform, @@ -12029,20 +11058,12 @@ privát és biztonságos decentralizált kommunikációt nyújtó szolgáltatás - Launch startup wizard - Nyisd meg az indító varázslót - - - Do you need help with RetroShare? - Segítségre van szükséged? - - - + Open Web Help Nyisd meg a segítség honlapot - + Copy your Cert to Clipboard Tanúsítványod másolása a vágólapra @@ -12052,7 +11073,7 @@ privát és biztonságos decentralizált kommunikációt nyújtó szolgáltatás Mentsd el egy fájlba a tanusítványodat - + Send via Email Küld el emailben @@ -12072,13 +11093,37 @@ privát és biztonságos decentralizált kommunikációt nyújtó szolgáltatás - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -12090,12 +11135,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -12110,12 +11155,7 @@ new short format RetroShare meghívó - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... Mentés mint... @@ -12380,14 +11420,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Összes - + Reputation Népszerűség @@ -12397,12 +11437,12 @@ p, li { white-space: pre-wrap; } Keresés - + Anonymous Id Névtelen azonosító - + Create new Identity Új személyazonosság létrehozása @@ -12412,7 +11452,7 @@ p, li { white-space: pre-wrap; } Hozz létre új kört - + Persons Személyek @@ -12427,27 +11467,27 @@ p, li { white-space: pre-wrap; } Személy - + Close Bezárás - + Ban-option: Letiltási opció: - + Auto-Ban all identities signed by the same node Automatikusan bannolj minden Személyazonosságot amelyet ugyanez a csomópont írt alá - + Friend votes: Ismerős szavazatai: - + Positive votes Elismerő szavazatok @@ -12463,29 +11503,39 @@ p, li { white-space: pre-wrap; } Bíráló szavazatok - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics Használati statisztika - + Circles Körök - + Circle name Kör neve @@ -12505,18 +11555,20 @@ p, li { white-space: pre-wrap; } Személyes körök - + + Edit identity Személyazonosság szerkesztése - + + Delete identity Személyazonosság törlése - + Chat with this peer Beszélgetés ezzel a partnerrel @@ -12526,78 +11578,78 @@ p, li { white-space: pre-wrap; } Távoli beszélgetést kezdeményez ezzel a partnerrel - + Owner node ID : Tulajdonos csomópont azonosító : - + Identity name : Személyazonosság név : - + () () - + Identity ID Személyazonosság azonosító - + Send message Üzenet elküldése - + Identity info Személyazonosság információ - + Identity ID : Személyazonosság azonosító : - + Owner node name : Csomópont tulajdonos neve: - + Create new... Új létrehozása - + Type: Típus: - + Send Invite Meghívó küldése - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: A véleményed: - + Negative rossz - + Neutral semleges @@ -12608,17 +11660,17 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: Általánosan - + Anonymous Névtelen @@ -12633,24 +11685,24 @@ p, li { white-space: pre-wrap; } Azonosító keresése - + This identity is owned by you Ez a személyazonosság a tiéd - - + + My own identities Saját személyazonosságaim - - + + My contacts Kapcsolataim - + Show Items Elemek megjelenítése @@ -12665,7 +11717,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles Más körök @@ -12675,7 +11732,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: Kör azonosító: @@ -12750,7 +11807,7 @@ p, li { white-space: pre-wrap; } Nem-tag (nem férsz hozzá a kör adataihoz) - + Identity ID: Személyazonosság azonosító: @@ -12780,7 +11837,7 @@ p, li { white-space: pre-wrap; } ismeretlen - + Invited Meghívott @@ -12795,7 +11852,7 @@ p, li { white-space: pre-wrap; } Tag - + Edit Circle Kör szerkesztése @@ -12843,7 +11900,7 @@ p, li { white-space: pre-wrap; } Tagság megadása - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -12854,7 +11911,7 @@ Szabadulj meg tőle és készíts egy újat. Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + [Unknown node] [Ismeretlen csomópont] @@ -12897,7 +11954,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Névtelen személyazonosság - + Boards @@ -12977,7 +12034,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + information Információ @@ -12993,25 +12050,12 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Személyazonosság másolása a vágólapra - Send invite? - Küldesz meghívót - - - + Banned Letiltva - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Személyazonosságok</h1> <p>Ezen a fülön készíthetsz új vagy szerkesztheted a már meglévő <b>ál-névtelen személyazonosságokat</b>, és <b>köröket</b>.</p> <p>A <b>személyazonosságokat</b> használjuk az adataid biztonságos azonosításához: aláírják az üzeneteid a társalgószobákban, a fórum- és csatorna hozzászólásaidat, visszajelzést kapnak a Retroshare beépített e-mail rendszerén keresztül, hozzászólhatsz csatorna bejegyzésekhez, biztonságos alagutakon keresztül beszélgethetsz, stb.</p> <p>Személyazonosságaidat<b>aláírhatod</b> a Retroshare csomópontod tanúsítványával. Az aláírt Személyazonosságok jobban ellenőrizhetőbbek ezért megbízhatóbbnak számíthatnak, ugyanakkor hozzá vannak kapcsolva a csomópontod IP címéhez.</p> <p>Az úgynevezett<b>Álnevek</b> segítségével névtelenséged megőrzésével léphetsz kapcsolatba a többiekkel. Nem visszakereshető, ezáltal senki sem tudhatja, hogy pontosan kihez is tartozik egy ilyen személyazonosság.</p> <p>A <b>Körök</b> tulajdonképpen a hálózat személyazonosságainak (Álnév típusú, vagy aláírt) részhalmazai. Felhasználhatók arra, hogy szigorítsuk a hozzáférést egy fórumhoz, csatornához, stb. </p> <p>Egy <b>kör</b> szűkíthető további körökkel, ezáltal láthatatlanná téve bizonyos tartalmakat olyanok számára akik nem tagjai a szűkebb köröknek. Sőt egy kör önmaga is lehet korlátozott, ez azt jelenti, hogy csak a meghívott személyek számára lesz látható a tartalom.</p> - - - Unknown ID: - Ismeretlen azonosító: - - - + positive @@ -13060,10 +12104,6 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Chat Beszélgetés - - Unknown - Ismeretlen - [Unknown] @@ -13104,19 +12144,11 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Signature in distant tunnel system. - - Update of identity data. - Személyazonosság adat frissítése. - Generic signature validation. Általános aláírás hitelesítés. - - Generic signature. - Általános aláírás - Generic encryption. @@ -13128,7 +12160,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Titkosítás feloldása (általános) - + Add to Contacts Hozzáadás a kapcsolatokhoz @@ -13178,21 +12210,21 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - - - + + + People Személyek - + Your Avatar Click here to change your avatar Saját avatár - + Linked to neighbor nodes @@ -13202,7 +12234,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + Linked to a friend Retroshare node @@ -13217,7 +12249,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + Chat with this person Beszélgetés ezzel a személlyel @@ -13232,12 +12264,12 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.A távoli beszélgetés nem engedélyezett ezzel a személlyel. - + Last used: Utoljára használva: - + +50 Known PGP 50-nél több ismert PGP @@ -13257,12 +12289,12 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Tényleg törölni szeretnéd ezt a személyazonosságot? - + Owned by - + Node name: @@ -13272,7 +12304,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Csomópont azonosító : - + Really delete? Tényleg törlöd? @@ -13280,7 +12312,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. IdEditDialog - + Nickname Becenév @@ -13310,7 +12342,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Álnév - + Import image @@ -13320,12 +12352,19 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - - Use the mouse to zoom and adjust the image for your avatar. + + + No Avatar chosen. A default image will be automatically displayed from your new identity. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity Új személyazonosság @@ -13339,7 +12378,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + @@ -13349,7 +12388,12 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.N/A - + + No avatar chosen + + + + Edit identity Személyazonosság szerkesztése @@ -13360,27 +12404,27 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Frissít - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -13400,7 +12444,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + Identity update failed @@ -13410,11 +12454,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - Error getting key! - Hiba a kulcs beolvasásakor! - - - + Error KeyID invalid Hiba, érvénytelen Kulcs azonosító @@ -13429,7 +12469,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Ismeretlen igazi név - + Create New Identity Új személyazonosság létrehozása @@ -13439,10 +12479,15 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Típus - + Choose image... + + + Remove + Eltávolítás + @@ -13468,7 +12513,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Hozzáadás - + Create @@ -13478,17 +12523,13 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + Your Avatar Click here to change your avatar Saját avatár - Set Avatar - Avatár beállítása - - - + Linked to your profile @@ -13498,7 +12539,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Rendelkezhetsz egy vagy több személyazonossággal. Írhatsz velük társalgószobákba, hozzászólhatsz fórumokhoz és csatorna bejegyzésekhez. Végpontként viselkednek távoli beszélgetések valamint Retroshare távoli üzenetküldés esetén. - + The nickname is too short. Please input at least %1 characters. @@ -13557,10 +12598,6 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.PGP name: - - GXS id: - GXS azonosító: - PGP id: @@ -13576,7 +12613,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + Copy Másolás @@ -13586,12 +12623,12 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Eltávolítás - + %1 's Message History - + Mark all Összes megjelölése @@ -13610,26 +12647,38 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Quote Idézés - - Send - Küldés - ImageUtil - - + + Save image Kép mentése + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + + + + Cannot save the image, invalid filename Kép mentése sikertelen, érvénytelen fájlnév - + + Copy image + + + + + Not an image Ez nem kép @@ -13647,27 +12696,32 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + Enable RetroShare JSON API Server - + Port: Port: - + Listen Address: - + + Status: + Állapot: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -13688,7 +12742,12 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -13697,26 +12756,31 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File Fájl megnyitása - + Open Folder Mappa megnyitása - + Checking... Ellenőrzés... @@ -13726,7 +12790,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Fájlok ellenőrzése - + Recommend in a message to... @@ -13754,7 +12818,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. MainWindow - + Add Friend Barát hozzáadása @@ -13770,7 +12834,8 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + + Options Beállítások @@ -13791,7 +12856,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + Quit Kilépés @@ -13802,12 +12867,12 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Gyors beállítások varázsló - + RetroShare %1 a secure decentralized communication platform RetroShare %1 egy biztonságos, központosítatlan kommunikációs platform - + Unfinished Befejezetlen @@ -13836,11 +12901,12 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. + Status Állapot - + Notify Értesítés @@ -13851,31 +12917,35 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. + Open Messages Levelek megnyitása - + + Bandwidth Graph Sávszélesség grafikon - + Applications Alkalmazások + Help Súgó - + + Minimize Minimalizálás - + Maximize Teljes képernyő @@ -13890,7 +12960,12 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.RetroShare - + + Close window + + + + %1 new message %1 új üzenet @@ -13920,7 +12995,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.%1 csatlakozott barát - + Do you really want to exit RetroShare ? Tényleg ki szeretnél lépni a RetroShareből? @@ -13940,7 +13015,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Mutat - + Make sure this link has not been forged to drag you to a malicious website. Bizonyosodj meg róla, hogy ez a hivatkozás nem egy veszélyes weboldalra mutat. @@ -13985,12 +13060,13 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Szolgáltatás jogosultságok mátrix - + + Statistics Statisztika - + Show web interface Beépített böngésző megnyitása @@ -14005,7 +13081,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + Really quit ? Tényleg kilépsz? @@ -14014,17 +13090,17 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.MessageComposer - + Compose Írás - + Contacts Kapcsolatok - + Paragraph Bekezdés @@ -14060,12 +13136,12 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Címsor 6 - + Font size Betűméret - + Increase font size Betűméret növelése @@ -14080,32 +13156,32 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Félkövér - + Italic Dőlt - + Alignment Igazítás - + Add an Image Kép hozzáadása - + Sets text font to code style Kódrészlet beállítása - + Underline Aláhúzott - + Subject: Tárgy: @@ -14116,32 +13192,32 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból. - + Tags Címkék - + Address list: Címek listája: - + Recommend this friend - + Set Text color Szövegszin beállítása - + Set Text background color Szöveg háttérszinének beállítása - + Recommended Files Ajánlott fájlok @@ -14211,7 +13287,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Hosszabb idézet - + Send To: Küldés neki: @@ -14235,10 +13311,6 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.&Justify &sorkizárt - - All addresses (mixed) - Minden cím (vegyes) - All people @@ -14250,7 +13322,7 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.Kapcsolataim - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> Szia,<br>Szeretném a figyelmedbe ajánlani egy barátomat. Ha bennem megbízol, benne is megbízhatsz. <br> @@ -14270,18 +13342,18 @@ Ezek a személyazonosságok hamarosan kikerülnek a támogatásból.szeretne a barátod lenni - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team Szia %1,<br><br>%2 szeretne a barátod lenni.<br><br>Válaszolj neki:<br>%3<br><br>Köszönettel,<br>a RetroShare csapat - - + + Save Message Üzenet mentése - + Message has not been Sent. Do you want to save message to draft box? Az üzenet nem lett elküldve. @@ -14293,7 +13365,17 @@ Szeretnéd piszkozatként menteni az üzenetet? RetroShare link beillesztése - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" Hozzáadás címzettként @@ -14313,7 +13395,7 @@ Szeretnéd piszkozatként menteni az üzenetet? Hozzáadás ajánlottként - + Original Message Eredeti üzenet @@ -14323,21 +13405,21 @@ Szeretnéd piszkozatként menteni az üzenetet? Feladó - + - + To Neki - - + + Cc Másolat - + Sent Küldve @@ -14352,7 +13434,7 @@ Szeretnéd piszkozatként menteni az üzenetet? %1, %2 írta: - + Re: Vá: @@ -14362,30 +13444,30 @@ Szeretnéd piszkozatként menteni az üzenetet? Tov: - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? Tárgy nélkül szeretnéd elküldeni az üzenetet? - + Please insert at least one recipient. Kérlek, adj meg legalább egy fogadót. - + Bcc Rejtett másolat - + Unknown Ismeretlen @@ -14500,13 +13582,13 @@ Szeretnéd piszkozatként menteni az üzenetet? Részletek - + Open File... Fájl megnyitása... - + HTML-Files (*.htm *.html);;All Files (*) HTML-Fájlok (*.htm *.html);;Összes fájl (*) @@ -14526,7 +13608,7 @@ Szeretnéd piszkozatként menteni az üzenetet? PDF Exportálása - + Message has not been Sent. Do you want to save message ? Az üzenet nem lett elküldve. @@ -14548,7 +13630,7 @@ Szeretnéd menteni az üzenetet? Extra fájl hozzáadása - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -14572,28 +13654,24 @@ Szeretnéd menteni az üzenetet? Warning: This message is too big of %1 characters after HTML conversion. - - You have a friend invite - Van egy barát felkérésed - Respond now: Válasz most: - - + + Close Bezárás - + From: Feladó: - + Friend Nodes Barát csomópontok @@ -14638,13 +13716,13 @@ Szeretnéd menteni az üzenetet? - - + + Thanks, <br> Kösz, <br> - + Distant identity: Távoli személyazonosság: @@ -14654,12 +13732,12 @@ Szeretnéd menteni az üzenetet? [Hiányzik] - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. Hozz létre egy személyazonosságot, hogy aláírd a távoli üzeneteket, vagy töröld a távoli partnereket a cél listáról. - + Node name & id: Csomópont név & azonosító: @@ -14737,7 +13815,7 @@ Szeretnéd menteni az üzenetet? Alapértelmezett - + A new tab Új fül @@ -14747,7 +13825,7 @@ Szeretnéd menteni az üzenetet? Új ablak - + Edit Tag Címke szerkesztése @@ -14770,7 +13848,7 @@ Szeretnéd menteni az üzenetet? MessageToaster - + Sub: Tárgy: @@ -14778,7 +13856,7 @@ Szeretnéd menteni az üzenetet? MessageUserNotify - + Message Üzenet @@ -14806,7 +13884,7 @@ Szeretnéd menteni az üzenetet? MessageWidget - + Recommended Files Ajánlott fájlok @@ -14816,37 +13894,37 @@ Szeretnéd menteni az üzenetet? Az összes ajánlott fájl letöltése - + Subject: Tárgy: - + From: Feladó: - + To: Címzett: - + Cc: Másolat: - + Bcc: Rejtett másolat: - + Tags: Címkék: - + Reply Válasz @@ -14886,7 +13964,7 @@ Szeretnéd menteni az üzenetet? - + Send Invite Meghívó küldése @@ -14938,7 +14016,7 @@ Szeretnéd menteni az üzenetet? - + Confirm %1 as friend Elfogadom %1 baráti felkérését @@ -14948,12 +14026,12 @@ Szeretnéd menteni az üzenetet? %1 hozzáadása barátként - + View source - + No subject Nincs tárgy @@ -14963,17 +14041,22 @@ Szeretnéd menteni az üzenetet? Letöltés - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -14983,17 +14066,23 @@ Szeretnéd menteni az üzenetet? - Send invite? - Küldesz meghívót? + + Show less + + + + + Show more + - + Download all Az összes letöltése - + Print Document Dokumentum nyomtatása @@ -15008,12 +14097,12 @@ Szeretnéd menteni az üzenetet? Html-Fájlok (*.htm *.html);;Összes fájl (*) - + Load images always for this message Ezen üzenethez mindig töltse be a képeket - + Hide the attachment pane Csatolmány mező elrejtése @@ -15035,42 +14124,6 @@ Szeretnéd menteni az üzenetet? Compose Írás - - Reply to selected message - Válasz a kijelölt üzenetre - - - Reply - Válasz - - - Reply all to selected message - Válasz az összes kijelölt üzenetre - - - Reply all - Válasz mindenre - - - Forward selected message - Kijelölt üzenet továbbítása - - - Forward - Előre - - - Remove selected message - Kijelölt üzenet eltávolítása - - - Delete - Törlés - - - Print selected message - Kijelölt üzenet nyomtatása - Print @@ -15149,7 +14202,7 @@ Szeretnéd menteni az üzenetet? MessagesDialog - + New Message Új üzenet @@ -15159,60 +14212,16 @@ Szeretnéd menteni az üzenetet? Írás - Reply to selected message - Válasz a kiválasztott üzenetre - - - Reply - Válasz - - - Reply all to selected message - Válasz az összes kiválasztott üzenetre - - - Reply all - Válasz mindenre - - - Forward selected message - Kiválasztott üzenet továbbítása - - - Foward - Továbbítás - - - Remove selected message - Kiválasztott üzenet eltávolítása - - - Delete - Törlés - - - Print selected message - Kiválasztott üzenet nyomtatása - - - Print - Nyomtatás - - - Display - Megjelenítés beállításai - - - + - - + + Tags Címkék - - + + Inbox Beérkezett üzenetek @@ -15242,21 +14251,17 @@ Szeretnéd menteni az üzenetet? Kuka - + Total Inbox: Összes beérkezett: - Folders - Mappák - - - + Quick View Gyors nézet - + Print... Nyomtatás... @@ -15266,26 +14271,6 @@ Szeretnéd menteni az üzenetet? Print Preview Nyomatási kép - - Buttons Icon Only - Gombok csak ikonokként - - - Buttons Text Beside Icon - Szöveg az ikonok mellett - - - Buttons with Text - Gombok csak szöveggel - - - Buttons Text Under Icon - Gombok ikon alatti szöveggel - - - Set Text Under Icon - Szöveg beállítása - Save As... @@ -15307,7 +14292,7 @@ Szeretnéd menteni az üzenetet? Üzenet továbbítása - + Subject Tárgy @@ -15317,7 +14302,7 @@ Szeretnéd menteni az üzenetet? Feladó - + Date Dátum @@ -15327,39 +14312,7 @@ Szeretnéd menteni az üzenetet? Tartalom - Click to sort by attachments - Rendezés mellékletek szerint - - - Click to sort by subject - Rendezés tárgy szerint - - - Click to sort by read - Rendezés olvasottság szerint - - - Click to sort by from - Rendezés alak szerint - - - Click to sort by date - Rendezés dátum szerint - - - Click to sort by tags - Rendezés címkék szerint - - - Click to sort by star - Rendezés csillagozottság szerint - - - Forward selected Message - Kijelölt üzenet továbbítása - - - + Search Subject Tárgy keresése @@ -15368,6 +14321,11 @@ Szeretnéd menteni az üzenetet? Search From Keresés ebből + + + Search To + + Search Date @@ -15394,14 +14352,14 @@ Szeretnéd menteni az üzenetet? Mellékletek keresése - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred - Csillagozott + @@ -15475,7 +14433,7 @@ Szeretnéd menteni az üzenetet? - Show author in People + Show in People @@ -15489,7 +14447,7 @@ Szeretnéd menteni az üzenetet? - + No message using %1 tag available. @@ -15504,34 +14462,33 @@ Szeretnéd menteni az üzenetet? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts Piszkozatok - + No Box selected. - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - Nincs elérhető csillagozott üzenet. A csillagokkal megjelölheted fontos üzeneteidet, hogy azokat könnyen megtaláld. Ehhez kattints a világosszürke csillagra az üzenet mellett. - - - No system messages available. - Nincs elérhető rendszerüzenet. - - + To - Címzett + Címzett - Click to sort by to - Rendezés címzett szerint - - - + @@ -15539,22 +14496,6 @@ Szeretnéd menteni az üzenetet? Total: Összes: - - Messages - Üzenetek - - - Click to sort by signature - Rendezés aláírás szerint - - - This message was signed and the signature checks - Az üzenet aláírást tartalmazott és az értéke egyezett - - - This message was signed but the signature doesn't check - Az üzenet aláírást tartalmazott, de az értéke nem egyezik meg - Mail @@ -15582,7 +14523,17 @@ Szeretnéd menteni az üzenetet? MimeTextEdit - + + Save image + Kép mentése + + + + Copy image + + + + Paste as plain text Beillesztés sima szövegként @@ -15636,7 +14587,7 @@ Szeretnéd menteni az üzenetet? - + Expand Lenyitás @@ -15646,7 +14597,7 @@ Szeretnéd menteni az üzenetet? Eltávolítás - + from tőle @@ -15681,14 +14632,10 @@ Szeretnéd menteni az üzenetet? Függő üzenetek - + Hide Elrejt - - Send invite? - Küldesz meghívót? - NATStatus @@ -15826,7 +14773,7 @@ Szeretnéd menteni az üzenetet? Partner azonosító - + Remove unused keys... Használatlan kulcsok eltávolítása... @@ -15836,7 +14783,7 @@ Szeretnéd menteni az üzenetet? - + Clean keyring Kulcstartó takarítása @@ -15854,7 +14801,13 @@ Megyjegyzés: A régi kulcstartódról biztonsági másolat készül. Az eltávolítás sikertelenül végződhet, ha egyszerre több Retroshare klienst futtatsz ugyanazon a gépen. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info Kulcstartó adatai @@ -15890,18 +14843,13 @@ A biztonság kedvéért a kulcstartód ezt megelőzően el lett mentve egy fájl Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. Adatrendezési hiba a kulcstartóban. Ez valószínűleg egy programhiba. Kérlek lépj kapcsolatba a fejlesztőkkel. - - - Export/create a new node - - Trusted keys only Csak megbízható kulcsok - + Search name Név keresése @@ -15911,25 +14859,18 @@ A biztonság kedvéért a kulcstartód ezt megelőzően el lett mentve egy fájl Partner azonosító keresése - + Profile details... Profil részletei - + Key removal has failed. Your keyring remains intact. Reported error: - - NetworkPage - - Network - Hálózat - - NetworkView @@ -15956,7 +14897,7 @@ Reported error: NewFriendList - + Offline Friends @@ -15977,7 +14918,7 @@ Reported error: - + Groups Csoportok @@ -16007,19 +14948,19 @@ Reported error: barátlista visszaállítása a megtartott csoportokkal - - + + Search Keresés - + ID Azonosító - + Search ID Azonosító keresése @@ -16029,12 +14970,12 @@ Reported error: - + Show Items Elemek megjelenítése - + Last contact @@ -16044,7 +14985,7 @@ Reported error: IP - + Group Csoport @@ -16159,7 +15100,7 @@ Reported error: Összes becsukása - + Do you want to remove this node? El szeretnéd távolítani ezt a csomópontot? @@ -16169,7 +15110,7 @@ Reported error: El szeretnéd távolítani ezt a barátot? - + Done! Kész! @@ -16283,11 +15224,7 @@ legalább egy partner nem lett hozzáadva a csoporthoz NewsFeed - Log entries - Naplóbejegyzések - - - + Activity Stream @@ -16302,11 +15239,7 @@ legalább egy partner nem lett hozzáadva a csoporthoz Összes eltávolítása - This is a test. - Ez egy teszt. - - - + Newest on top A legújabb felül @@ -16316,16 +15249,12 @@ legalább egy partner nem lett hozzáadva a csoporthoz A legrégibb felül - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - Log - Napló - - - + Activity @@ -16380,10 +15309,6 @@ legalább egy partner nem lett hozzáadva a csoporthoz Blogs Blogok - - Security - Biztonság - @@ -16405,10 +15330,6 @@ legalább egy partner nem lett hozzáadva a csoporthoz Message Üzenet - - Connect attempt - Csatlakozási kísérlet - @@ -16425,10 +15346,6 @@ legalább egy partner nem lett hozzáadva a csoporthoz Ip security IP biztonság - - Log - Napló - Friend Connected @@ -16439,10 +15356,6 @@ legalább egy partner nem lett hozzáadva a csoporthoz Circles Körök - - Links - Hivatkozások - Activity @@ -16495,14 +15408,6 @@ legalább egy partner nem lett hozzáadva a csoporthoz Chat rooms Társalgószobák - - Chat Rooms - Társalgószobák - - - Case sensitive - Kis- és nagybetű érzékeny - Position @@ -16578,10 +15483,6 @@ legalább egy partner nem lett hozzáadva a csoporthoz Disable All Toaster temporarily - - Feed - Hírcsatorna - Systray @@ -16591,7 +15492,7 @@ legalább egy partner nem lett hozzáadva a csoporthoz NotifyQt - + Passphrase required @@ -16611,12 +15512,12 @@ legalább egy partner nem lett hozzáadva a csoporthoz Rossz jelszó! - + Please enter your Retroshare passphrase - + Unregistered plugin/executable Nem regisztrált beépülő/futtatható állomány @@ -16631,19 +15532,7 @@ legalább egy partner nem lett hozzáadva a csoporthoz Kérlek, ellenőrízd a rendszerórádat. - Examining shared files... - Megosztott fájlok vizsgálata... - - - Hashing file - Fájl hashelése - - - Saving file index... - Fájlindex mentése - - - + Test Teszt @@ -16654,17 +15543,19 @@ legalább egy partner nem lett hozzáadva a csoporthoz + Unknown title Ismeretlen cím - + + Encrypted message Titkosított üzenet - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). Ahhoz, hogy a társalgószobák megfelelően működjenek, a számítógép órájának pontosnak kell lennie. Kérlek ellenőrizd (Lehetséges időeltérést tapasztaltunk a barátaidhoz képest). @@ -16672,7 +15563,7 @@ legalább egy partner nem lett hozzáadva a csoporthoz OnlineToaster - + Friend Online Bejelentkezett barát @@ -16724,10 +15615,6 @@ legalább egy partner nem lett hozzáadva a csoporthoz PGPKeyDialog - - Dialog - Párbeszéd - Profile info @@ -16793,10 +15680,6 @@ legalább egy partner nem lett hozzáadva a csoporthoz This profile has signed your own profile key - - Key signatures : - Kulcs aláírások: - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> @@ -16822,23 +15705,20 @@ p, li { white-space: pre-wrap; } PGP kulcs - - These options apply to all nodes of the profile: - Ezek a beállítások a következő profil összes csomópontjára érvényesek: + + Friend options + - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> - <html><head/><body><p><span style=" font-size:10pt;">A barátod kulcsának aláírása alkalmas arra, hogy kifejezd a bizalmad iránta és ezt jelezd a többiek felé. Ez segíthet nekik eldönteni, hogy elfogadják-e a kapcsolódást az adott kulcs tulajdonosától. Egy kulcs aláírása csak egy lehetőség, de visszavonhatatlan. Ezért fontold meg és dönts okosan.</span></p></body></html> + + These options apply to all nodes of the profile: + Ezek a beállítások a következő profil összes csomópontjára érvényesek: Keysigning: - - Sign PGP key - PGP kulcs aláírása - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -16875,29 +15755,20 @@ p, li { white-space: pre-wrap; } Aláírásokat tartalmaz - - Options - Beállítások - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> <html><head/><body><p align="justify">A Retroshare időnként ellenőrzi a barátlistád kereshető fájlokért, melyek megegyeznek az átviteli fájlokkal, azért, hogy közvetlen fájlátvitel valósulhasson meg. Ebben az esetben a barátod tudni fogja, hogy letöltöd azt a fájlt.</p><p align="justify">Hogy elkerüld ezt a viselkedést, és ki szeretnéd hagyni ebből ezt a barátodat, akkor szüntesd meg a doboz kijelölését. Továbbra is lehetőséged lesz a fájl letöltésére tőle, ehhez azonban előbb igényelned kell azt. Például az adott fájl manuális letöltésével a barátod megosztott mappájából. Ez a beállítás egy adott csomóponthoz tartozó összes helyszínre érvényes lesz.</p></body></html> Use as direct source, when available - + Közvetlen forrásként használat, amikor csak lehetséges <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this profile (e.g. when the message author is a signed identity that belongs to this profile). This can be used for instance to send files between your own nodes.</p></body></html> - - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> - <html><head/><body><p>Ez az opció lehetővé teszi, hogy önműködően letöltsd az ennek a csomópontnak valamelyik üzenetben javasolt fájlt. Arra is használhatod, hogy saját csomópontjaid között fájlokat továbbíts. Ugyanazon csomópont összes helyszinére vonatkozik.</p></body></html> - Auto-download recommended files from this node @@ -16930,21 +15801,21 @@ p, li { white-space: pre-wrap; } kB/másodpercenként - - + + RetroShare RetroShare - - + + Error : cannot get peer details. Hiba: a partner adatai nem elérhetőek. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) A RetroShare nem támogatja a kulcsot. @@ -16965,7 +15836,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -17034,10 +15905,6 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen Check the password! - - Maybe password is wrong - Talán rossz a jelszó - You haven't set a trust level for this key. @@ -17045,12 +15912,12 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen - + Retroshare profile RetroShare profil - + This is your own PGP key, and it is signed by : @@ -17076,7 +15943,7 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen PeerItem - + Chat Beszélgetés @@ -17097,7 +15964,7 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen Eltávolítás - + Name: Név: @@ -17137,7 +16004,7 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen Időeltolódás: - + Write Message Üzenet írása @@ -17151,10 +16018,6 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen Friend Connected Barát bejelentkezett - - Connect Attempt - Kapcsolódási kísérlet - Connection refused by peer @@ -17193,17 +16056,13 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen Unknown Ismeretlen - - Unknown Peer - Ismeretlen partner - Hide Elrejt - + Send Message Üzenet küldése @@ -17255,10 +16114,6 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen Chat with this person as... Beszélgetés ezzel a személlyel mint... - - Send message to this person - Üzenet küldése ennek a személynek - Invite to Circle @@ -17374,13 +16229,6 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen - - PhotoCommentItem - - Form - Forma - - PhotoDialog @@ -17388,23 +16236,11 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen PhotoShare Fényképmegosztás - - Photo - Fénykép - TextLabel Címke - - Comment - Hozzászólás - - - Summary - Összefoglalva - Album / Photo Name @@ -17465,14 +16301,6 @@ Figyelmeztetés: az Átvitel beállításainál Nem engedélyezted a közvetlen ... ... - - Add Comment - Hozzászólás írása - - - Write a comment... - Hozzászólás írása... - Album @@ -17543,10 +16371,6 @@ p, li { white-space: pre-wrap; } Create Album Album létrehozása - - View Album - Album megnézése - Edit Album Details @@ -17568,17 +16392,17 @@ p, li { white-space: pre-wrap; } Diavetítés - + My Albums Albumaim - + Subscribed Albums Album feliratkozások - + Shared Albums Megosztott albumok @@ -17607,7 +16431,7 @@ requesting to edit it! PhotoSlideShow - + Album Name Album neve @@ -17666,19 +16490,19 @@ requesting to edit it! - - + + TextLabel - + Posted by - + ago @@ -17714,12 +16538,12 @@ requesting to edit it! PluginItem - + TextLabel Szövegcímke - + Show more details about this plugin Beépülő részleteinek mutatása @@ -17865,51 +16689,6 @@ p, li { white-space: pre-wrap; } Plugin look-up directories Beéplők könyvtárai - - [disabled] - [leállítva] - - - No API number supplied. Please read plugin development manual. - Nincs támogatott API szám. Kérlek, olvasd el a beépülők fejlesztéséhez kapcsolódó leírást. - - - [loading problem] - [betöltési hiba] - - - No SVN number supplied. Please read plugin development manual. - Nincs támogatott SVN szám. Kérlek, olvasd el a beépülők fejlesztéséhez kapcsolódó leírást. - - - Loading error. - Hiba a betöltéskor - - - Missing symbol. Wrong version? - Hizányzó szimbólum. Rossz verzió? - - - No plugin object - Nem található beépülő - - - Plugins is loaded. - Beépülő betöltve. - - - Unknown status. - Ismeretlen állapot. - - - Check this for developing plugins. They will not -be checked for the hash. However, in normal -times, checking the hash protects you from -malicious behavior of crafted plugins. - Fejlesztő verziók használatáért jelöld be ezt, így a hash értékeik nem -lesznek ellenőrízve. Alapállapotban a hash érték ellenőrzése megvéd -a kártevőként működő beépülők használatától. - Plugins @@ -17979,12 +16758,27 @@ a kártevőként működő beépülők használatától. Mindig felül - + + Ban this person (Sets negative opinion) + Személy bannolása (Negatív véleményt állít be) + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -18018,14 +16812,6 @@ a kártevőként működő beépülők használatától. Close conversation? - - Closing this window will end the conversation, notify the peer and remove the encrypted tunnel. - Ha bezárod ezt az ablakot, akkor a beszélgetés megszakad és megszűnik titkosított alagút. - - - Kill the tunnel? - Alagút bezárása? - PostedCardView @@ -18045,7 +16831,7 @@ a kártevőként működő beépülők használatától. Új - + Vote up Szavazás mellette @@ -18065,8 +16851,8 @@ a kártevőként működő beépülők használatától. \/ - - + + Comments Hozzászólások @@ -18091,13 +16877,13 @@ a kártevőként működő beépülők használatától. - - + + Comment Hozzászólás - + Comments Hozzászólások @@ -18125,20 +16911,12 @@ a kártevőként működő beépülők használatától. PostedCreatePostDialog - Signed by: - Általa aláírva: - - - Notes - Jegyzetek - - - + Create a new Post - + RetroShare RetroShare @@ -18153,12 +16931,22 @@ a kártevőként működő beépülők használatától. - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File Kép betöltése - + Post image @@ -18174,7 +16962,17 @@ a kártevőként működő beépülők használatától. - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -18184,19 +16982,7 @@ a kártevőként működő beépülők használatától. - Submit Post - Beküldés - - - Submit - Jóváhagyás - - - Submit a new Post - Új hozzászólás beküldése - - - + Please add a Title Kérlek, adj meg egy címet @@ -18216,12 +17002,22 @@ a kártevőként működő beépülők használatától. - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -18236,7 +17032,7 @@ a kártevőként működő beépülők használatától. Hozzászólás mint - + Post @@ -18247,7 +17043,7 @@ a kártevőként működő beépülők használatától. Kép - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -18257,7 +17053,7 @@ a kártevőként működő beépülők használatától. Cím - + Link Hivatkozás @@ -18265,40 +17061,12 @@ a kártevőként működő beépülők használatától. PostedDialog - Posted Links - Közzétett hivatkozások - - - Create Topic - Téma létrehozása - - - My Topics - Topikjaim - - - Subscribed Topics - Feliratkozott témák - - - Popular Topics - Népszerű témák - - - Other Topics - Egyéb témák - - - Links - Hivatkozások - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -18332,31 +17100,7 @@ a kártevőként működő beépülők használatától. PostedGroupDialog - Posted Topic - Beküldött téma - - - Add Topic Admins - Téma adminok hozzáadása - - - Select Topic Admins - Téma adminok kiválasztása - - - Create New Topic - Új téma létrehozása - - - Edit Topic - Téma szerkesztése - - - Update Topic - Téma frissítése - - - + Create New Board @@ -18394,7 +17138,17 @@ a kártevőként működő beépülők használatától. PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted @@ -18410,7 +17164,7 @@ a kártevőként működő beépülők használatától. - + Expand Lenyitás @@ -18425,16 +17179,17 @@ a kártevőként működő beépülők használatától. - Loading - Töltés - - - + Loading... - + + Never + Soha + + + New Board @@ -18447,22 +17202,18 @@ a kártevőként működő beépülők használatától. PostedItem - + 0 0 - Site - Oldal - - - - + + Comments Hozzászólások - + Copy RetroShare Link @@ -18473,12 +17224,12 @@ a kártevőként működő beépülők használatától. - + Comment Hozzászólás - + Comments Hozzászólások @@ -18488,7 +17239,7 @@ a kártevőként működő beépülők használatától. <p><font color="#ff0000"><b>Az üzenet szerzője (azonosító: %1) bannolva van.</b> - + Click to view Picture @@ -18498,21 +17249,17 @@ a kártevőként működő beépülők használatától. Elrejt - + Vote up Szavazás mellette - + Vote down Szavazás ellene - \/ - \/ - - - + Set as read and remove item Megjelölés olvasottként és eltávolítás @@ -18522,7 +17269,7 @@ a kártevőként működő beépülők használatától. Új - + New Comment: Új hozzászólás @@ -18532,7 +17279,7 @@ a kártevőként működő beépülők használatától. - + Name Név @@ -18573,77 +17320,10 @@ a kártevőként működő beépülők használatától. - + Loading Töltés - - By - által - - - - PostedListWidget - - Form - Forma - - - Hot - Népszerű - - - New - Új - - - Top - Magas - - - Today - Ma - - - Yesterday - Tegnap - - - This Week - A héten - - - This Month - A hónapban - - - This Year - Az évben - - - Submit a new Post - Új hozzászólás beküldése - - - Next - Következő - - - RetroShare - RetroShare - - - Please create or choose a Signing Id before Voting - Kérlek, hozz létre vagy válassz ki egy Aláíró azonosítót a szavazás előtt - - - Previous - Előző - - - 1-10 - 1-10 - PostedListWidgetWithModel @@ -18663,7 +17343,17 @@ a kártevőként működő beépülők használatától. - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -18673,15 +17363,15 @@ a kártevőként működő beépülők használatától. Adminisztrátor: - + - + unknown ismeretlen - + Distribution: @@ -18691,42 +17381,42 @@ a kártevőként működő beépülők használatától. - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts Bejegyzések - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -18746,7 +17436,7 @@ a kártevőként működő beépülők használatától. Népszerű - + Search Keresés @@ -18776,17 +17466,17 @@ a kártevőként működő beépülők használatától. - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -18801,12 +17491,17 @@ a kártevőként működő beépülők használatától. Üres - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -18816,27 +17511,31 @@ a kártevőként működő beépülők használatától. Szerkesztés - + + information Információ - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -18851,7 +17550,7 @@ a kártevőként működő beépülők használatától. Feliratkozás - + Never Soha @@ -18925,6 +17624,16 @@ a kártevőként működő beépülők használatától. No Channel Selected Nincs csatorna kiválasztva + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -18933,14 +17642,6 @@ a kártevőként működő beépülők használatától. Tabs Fülek - - Open each topic in a new tab - Minden egyes téma megnyitása új fülön - - - Links - Hivatkozások - Open each board in a new tab @@ -18954,10 +17655,6 @@ a kártevőként működő beépülők használatától. PostedUserNotify - - Posted - Beküldve - Board Post @@ -19026,16 +17723,16 @@ a kártevőként működő beépülők használatától. Profilkezelő - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -19145,7 +17842,7 @@ az importálás gombot, hogy betöltsd. ProfileWidget - + Edit status message Állapot szerkesztése @@ -19161,7 +17858,7 @@ az importálás gombot, hogy betöltsd. Profilkezelő - + Public Information Publikus adatok @@ -19196,12 +17893,12 @@ az importálás gombot, hogy betöltsd. Online ettől kezdve: - + Other Information Egyéb adatok - + My Address Címem @@ -19245,51 +17942,27 @@ az importálás gombot, hogy betöltsd. PulseAddDialog - Post From: - Küldés ebből: - - - Account 1 - Profil 1 - - - Account 2 - Profil 2 - - - Account 3 - Profil 3 - - - + Add to Pulse Pulzushoz adás - filter - szűrő - - - URL Adder - URL hozzáadó - - - + Display As Mutatás mint - + URL URL - + GroupLabel - + IDLabel @@ -19299,12 +17972,12 @@ az importálás gombot, hogy betöltsd. Feladó: - + Head - + Head Shot @@ -19334,13 +18007,13 @@ az importálás gombot, hogy betöltsd. rossz - - + + Whats happening? - + @@ -19352,12 +18025,22 @@ az importálás gombot, hogy betöltsd. - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -19366,17 +18049,13 @@ az importálás gombot, hogy betöltsd. Cancel Mégse - - Post Pulse to Wire - Pulzus küldése a vezetékhez - Post - + Reply to Pulse @@ -19391,34 +18070,24 @@ az importálás gombot, hogy betöltsd. - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - Feladó - - - Date - Dátum - - - ... - ... + + Load Picture File + Kép betöltése @@ -19429,7 +18098,7 @@ az importálás gombot, hogy betöltsd. Forma - + @@ -19448,7 +18117,7 @@ az importálás gombot, hogy betöltsd. PulseReply - + icn @@ -19458,7 +18127,7 @@ az importálás gombot, hogy betöltsd. - + REPLY @@ -19485,7 +18154,7 @@ az importálás gombot, hogy betöltsd. - + FOLLOW @@ -19495,7 +18164,7 @@ az importálás gombot, hogy betöltsd. - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -19515,7 +18184,7 @@ az importálás gombot, hogy betöltsd. - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -19631,7 +18300,7 @@ az importálás gombot, hogy betöltsd. - + FOLLOW @@ -19639,37 +18308,42 @@ az importálás gombot, hogy betöltsd. PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -19701,7 +18375,7 @@ az importálás gombot, hogy betöltsd. - + FOLLOW @@ -19709,8 +18383,8 @@ az importálás gombot, hogy betöltsd. QObject - - + + Confirmation Megerősítés @@ -19981,12 +18655,12 @@ A <b>",|,/,\,&lt;,&gt;,*,?</b> karakterek le lesznek cs Partner részletei - + File Request canceled Fájl kérése megszakítva - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. A RetroShare ezen verziója OpenPGP-SDK-t használ. Ennek hála, nem használja a rendszer PGP kulcstartóját, viszont van egy saját kulcstartója, amit az összes futó RetroShare elérhet. <br><br>Úgy tűnik, hogy még nem rendelkezel ilyen kulcstartóval annak ellenére, hogy már létrehozott RetroShare fiókjaidban szerepelnek PGP kulcsok. Ez valószínűleg azért lehetséges, mert most frissítettél az alkalmazás új verziójára. @@ -20017,7 +18691,7 @@ A <b>",|,/,\,&lt;,&gt;,*,?</b> karakterek le lesznek cs Váratlan hiba történt. Kérlek jelentsd 'RsInit::InitRetroShare unexpected return code %1'. - + Cannot start Tor Manager! A Tor-kezelő nem indul! @@ -20053,7 +18727,7 @@ The error reported is:" - + Multiple instances Több példány @@ -20076,6 +18750,26 @@ Kérlek, először zárd be azt. Zárolt fájl: Zárolófájl: + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -20158,7 +18852,7 @@ A hibajelentés: Adat továbbítása - + You appear to have nodes associated to DSA keys: @@ -20168,7 +18862,7 @@ A hibajelentés: - + enabled elindítva @@ -20178,7 +18872,7 @@ A hibajelentés: leállítva - + Move IP %1 to whitelist @@ -20194,7 +18888,7 @@ A hibajelentés: - + %1 seconds ago %1 másodperccel ezelőtt @@ -20262,7 +18956,7 @@ Security: no anonymous IDs Biztonság: névtelen azonosítók nem engedélyezettek - + Join chat room Belépés a társalgószobába @@ -20290,7 +18984,7 @@ Biztonság: névtelen azonosítók nem engedélyezettek nem lehet értelmezni az XML fájlt! - + Indefinitely @@ -20470,13 +19164,29 @@ Biztonság: névtelen azonosítók nem engedélyezettek Ban list + + + Name + Név + + Node + Csomópont + + + + Address + Cím + + + + Status Állapot - + NXS @@ -20669,10 +19379,6 @@ Biztonság: névtelen azonosítók nem engedélyezettek Click to resume the hashing process - - <p>This certificate contains: - <p>Ez a tanúsítvány tartalmaz: - Idle @@ -20723,6 +19429,18 @@ Biztonság: névtelen azonosítók nem engedélyezettek Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -20885,7 +19603,7 @@ p, li { white-space: pre-wrap; } - + Network Wide Egész hálózat @@ -21068,7 +19786,7 @@ p, li { white-space: pre-wrap; } Forma - + The loading of embedded images is blocked. A beágyazott képek megjelenítése tiltva van. @@ -21081,7 +19799,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default Alapértelmezetten engedélyezve @@ -21254,12 +19972,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + Kép mentése + + + + Copy image + + + + Document source @@ -21267,12 +19995,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options Fa nézet beállítása - + Show Header @@ -21302,14 +20030,6 @@ p, li { white-space: pre-wrap; } Show column … - - Show column... - Mutatandó oszlop... - - - [no title] - [nincs cím] - RatesStatus @@ -21970,7 +20690,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name Név @@ -22091,7 +20811,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name Név @@ -22111,7 +20831,7 @@ If you believe it is correct, remove the corresponding line from the file and re IP - + Profile ID @@ -22168,7 +20888,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] [ ... Szerkesztett üzenet ... ] @@ -22182,11 +20902,6 @@ prevents the message to be forwarded to your friends. [Unknown] [Ismeretlen] - - - [ ... Missing Message ... ] - [ ... Hiányzó üzenet ... ] - RsMessageModel @@ -22200,6 +20915,11 @@ prevents the message to be forwarded to your friends. From + + + To + + Subject @@ -22222,13 +20942,18 @@ prevents the message to be forwarded to your friends. - Click to sort by read - Rendezés olvasottság szerint + Click to sort by read status + - Click to sort by from - Rendezés alak szerint + Click to sort by author + + + + + Click to sort by destination + @@ -22251,7 +20976,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -22272,7 +20999,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. Az összes tárolt RetroShare beállítás visszaváltása alapértelmezettre. @@ -22333,7 +21060,7 @@ prevents the message to be forwarded to your friends. RetroShare nyelvi beállítása. - + Unable to open log file '%1': %2 Naplófájl megnyitása sikertelen: '%1': %2 @@ -22354,11 +21081,7 @@ prevents the message to be forwarded to your friends. - Revision - Változat - - - + opmode működési mód @@ -22388,7 +21111,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -22406,7 +21129,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -22423,12 +21146,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) Írj be egy kulcsszót (legalább három karakter hosszú legyen) - + Start Search Keresés indítása @@ -22490,7 +21213,7 @@ prevents the message to be forwarded to your friends. Tisztítás - + KeyWords Kulcsszavak @@ -22505,7 +21228,7 @@ prevents the message to be forwarded to your friends. Keresés azonosító - + Filename Fájlnév @@ -22605,23 +21328,23 @@ prevents the message to be forwarded to your friends. Kiválasztott letöltése - + File Name Fájlnév - + Download Letöltés - + Copy RetroShare Link RetroShare link másolása - + Send RetroShare Link RetroShare hivatkozás küldése @@ -22631,7 +21354,7 @@ prevents the message to be forwarded to your friends. - + Download Notice Megjegyzés letöltése @@ -22668,7 +21391,7 @@ prevents the message to be forwarded to your friends. Összes eltávolítása - + Folder Mappa @@ -22679,17 +21402,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) Új RetroShare hivatkozás(ok) - + Open Folder Mappa megnyitása - + Create Collection... Gyűjtemény létrehozása @@ -22709,7 +21432,7 @@ prevents the message to be forwarded to your friends. Letöltés kollekciófájlból... - + Collection Kollekció @@ -22717,7 +21440,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details Partner részletei @@ -22733,22 +21456,22 @@ prevents the message to be forwarded to your friends. Eltávolítás - + IP address: IP cím: - + Peer ID: Partner azonosító: - + Location: Hely: - + Peer Name: Kapcsolat neve: @@ -22765,7 +21488,7 @@ prevents the message to be forwarded to your friends. Elrejt - + but reported: @@ -22790,8 +21513,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -22799,7 +21522,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare a barátod szeretne lenni @@ -22830,7 +21553,7 @@ prevents the message to be forwarded to your friends. - + Expand Lenyitás @@ -22875,12 +21598,12 @@ prevents the message to be forwarded to your friends. Állapot: - + Write Message Üzenet írása - + Connect Attempt Csatlakozási kísérlet @@ -22900,17 +21623,22 @@ prevents the message to be forwarded to your friends. Ismeretlen (kimenő) csatlakozási kísérlet - + Unknown Security Issue Ismeretlen biztonsági kockázat - - A unknown peer + + SSL request - + + An unknown peer + + + + Unknown Ismeretlen @@ -22920,11 +21648,7 @@ prevents the message to be forwarded to your friends. - Unknown Peer - Ismeretlen partner - - - + Hide Elrejt @@ -22934,7 +21658,7 @@ prevents the message to be forwarded to your friends. El szeretnéd távolítani ezt a barátot? - + Certificate has wrong signature!! This peer is not who he claims to be. @@ -22944,12 +21668,12 @@ prevents the message to be forwarded to your friends. - + Certificate caused an internal error. - + Peer/node not in friendlist (PGP id= Partner/csomópont nincs a barátlistádon (PGP azonosító= @@ -23008,12 +21732,12 @@ prevents the message to be forwarded to your friends. - + Local Address Helyi cím - + NAT NAT @@ -23034,22 +21758,22 @@ prevents the message to be forwarded to your friends. Port: - + Local network Helyi hálózat - + External ip address finder Külső IP cím kereső - + UPnP UPnP - + Known / Previous IPs: Ismert / Előző IP címek: @@ -23062,21 +21786,16 @@ behind a firewall or a VPN. Amennyiben ezt nem jelölöd be, a RetroShare csak akkor tudja meghatározni az IP címedet, ha már csatlakoztál valakihez. Engedélyezve hagyva akkor segíthet, ha csak kevés barátod van, vagy tűzfal mögül csatlakozol, illetve VPN-t használsz. - - Allow RetroShare to ask my ip to these websites: - Engedélyezem a RetroSharenek, hogy a következő oldalakon lekérdezze az IP címemet: - - - - - + + + kB/s KB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -23086,23 +21805,46 @@ behind a firewall or a VPN. - + Onion Address Onion cím - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -23112,7 +21854,7 @@ behind a firewall or a VPN. Rejtett - Lásd Beállítások - + I2P Address I2P cím @@ -23137,37 +21879,95 @@ behind a firewall or a VPN. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client ügyfél @@ -23182,71 +21982,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. ismeretlen - - - - BOB is processing a request - - - - - connectivity check - kapcsolat ellenőrzése - - - - generating key - kulcs létrehozása - - - - starting up - indulás - - - - shuting down - leállás - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -23256,22 +21992,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. Elérhető vagy a rejtett szolgáltatáson keresztül. @@ -23283,12 +22004,12 @@ Also check your ports! - + [Hidden mode] [Rejtett mód] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -23298,7 +22019,7 @@ Also check your ports! Tisztítás - + Download limit (KB/s) Letöltési korlát (KB/s) @@ -23313,23 +22034,23 @@ Also check your ports! Feltöltési korlát (KB/s) - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -23340,17 +22061,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - Önműködő I2P/BOB - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -23360,12 +22071,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -23375,17 +22081,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 127.0.0.1 - - I2P proxy port - - - - - BOB accessible - - - - + Address Cím @@ -23425,7 +22121,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why kulcs betöltése - + Start Indítás @@ -23440,12 +22136,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why Leállítás - - BOB status - - - - + Incoming Bejövő @@ -23481,7 +22172,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay Közvetítő @@ -23536,7 +22252,7 @@ If you have issues connecting over Tor check the Tor logs too. Összesen: - + Warning: This bandwidth adds up to the max bandwidth. @@ -23561,7 +22277,7 @@ If you have issues connecting over Tor check the Tor logs too. Kiszolgáló eltávolítása - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -23573,7 +22289,7 @@ If you have issues connecting over Tor check the Tor logs too. Hálózat - + IP Filters IP szűrők @@ -23596,7 +22312,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status Állapot @@ -23656,17 +22372,28 @@ If you have issues connecting over Tor check the Tor logs too. Hozzáadás a fehérlistához - + Hidden Service Configuration Rejtett szolgáltatás beállításai - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -23682,18 +22409,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay I2P kimenő kapcsolat rendben - + Service Address Kiszolgáló címe @@ -23728,12 +22455,12 @@ If you have issues connecting over Tor check the Tor logs too. Kérlek adj meg egy szolgáltatás címet - + IP Range IP tartomány - + Reported by DHT for IP masquerading @@ -23756,22 +22483,22 @@ If you have issues connecting over Tor check the Tor logs too. Hozzáadva általad - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -23806,7 +22533,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -23816,12 +22543,12 @@ If you have issues connecting over Tor check the Tor logs too. Tor Socks Proxy - + Tor outgoing Okay Tor kimenő forgalom Rendben - + Tor proxy is not enabled Tor proxy nincs engedélyezve @@ -23901,7 +22628,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with Jelöld be, hogy mely partnereiddel szeretnél privát kulcsot megosztani @@ -23911,12 +22638,12 @@ If you have issues connecting over Tor check the Tor logs too. Megosztás barátnak - + Share Megosztás - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -23935,7 +22662,7 @@ Select the Friends with which you want to Share your Channel. Megosztáskezelő - + Shared directory Megosztott mappa @@ -23955,17 +22682,17 @@ Select the Friends with which you want to Share your Channel. Láthatóság - + Add new Hozzáadás - + Cancel Mégse - + Add a Share Directory Mappa hozzáadása a megosztáshoz @@ -23975,7 +22702,7 @@ Select the Friends with which you want to Share your Channel. Eltávolítás - + Apply and close Alkalmazás és bezárás @@ -24066,7 +22793,7 @@ Select the Friends with which you want to Share your Channel. Nem található mappa, vagy a neve nem elfogadható. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. Ezen listán a megosztott mappákat láthatod. Hozzáadhatsz újakat vagy eltávolíthatsz már megosztottakat az alul található gombok használatával. Mikor egy új mappát adsz hozzá, az összes benne található fájl meg lesz osztva. Megosztási módokat egyenként testreszabhatod ki a listán szereplő mappákra. @@ -24074,7 +22801,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files Fájlok @@ -24125,11 +22852,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files Megosztás ellenőrzése - + Download selected Kiválasztott letöltése @@ -24139,7 +22871,7 @@ Select the Friends with which you want to Share your Channel. Letöltés - + Copy retroshare Links to Clipboard RetroShare hivatkozás másolása a vágólapra @@ -24154,7 +22886,7 @@ Select the Friends with which you want to Share your Channel. RetroShare hivatkozás küldése - + Some files have been omitted @@ -24170,7 +22902,7 @@ Select the Friends with which you want to Share your Channel. Ajánlás(ok) - + Create Collection... Gyűjtemény létrehozása @@ -24195,7 +22927,7 @@ Select the Friends with which you want to Share your Channel. Letöltés kollekciófájlból... - + Some files have been omitted because they have not been indexed yet. @@ -24338,12 +23070,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration Beállítások betöltése - + Create interface Felület létrehozása @@ -24367,7 +23099,7 @@ Select the Friends with which you want to Share your Channel. Jelszó megjegyzése - + Log In Bejelentkezés @@ -24708,7 +23440,7 @@ This choice can be reverted in settings. Állapot üzenet - + Message: Üzenet: @@ -24953,7 +23685,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags Összes címke eltávolítása @@ -24989,12 +23721,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown Ismeretlen @@ -25004,18 +23739,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set Nincs beállítva @@ -25025,12 +23755,57 @@ p, li { white-space: pre-wrap; } - + + Error + Hiba + + + + Not connected + Nem csatlakozott + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -25038,7 +23813,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor Tor @@ -25048,7 +23823,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -25059,11 +23834,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -25091,7 +23867,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options Átvitel beállításai @@ -25102,7 +23878,7 @@ p, li { white-space: pre-wrap; } Maximum egyidejű letöltések száma: - + Shared Directories Megosztott könyvtárak @@ -25112,22 +23888,27 @@ p, li { white-space: pre-wrap; } A kész letöltések automatikus megosztása (Ajánlott) - - Edit Share - - - - + Directories - + + Configure shared directories + Megosztott könyvtárak beállításai + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -25212,7 +23993,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -25221,7 +24002,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) Ismewrősök feltöltéseinek száma legfeljebb (0=korlátlan) @@ -25246,7 +24032,12 @@ p, li { white-space: pre-wrap; } Közvetlen letöltés engedélyezése: - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming Streamelés @@ -25311,12 +24102,7 @@ p, li { white-space: pre-wrap; } Maximális továbbított csatornák száma másodpercenként: - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -25326,7 +24112,17 @@ p, li { white-space: pre-wrap; } - + + Warning + Vigyázat + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory Fogadó könyvtár beállítása @@ -25354,7 +24150,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed Letöltés elkészült @@ -25378,39 +24174,23 @@ p, li { white-space: pre-wrap; } %1 completed transfer - - You have %1 completed downloads - %1 letöltésed elkészült - - - You have %1 completed download - %1 letöltésed elkészült - - - %1 completed downloads - %1 elkészült letöltés - - - %1 completed download - %1 elkészült letöltés - TransfersDialog - - + + Downloads Letöltések - + Uploads Feltöltések - + Name i.e: file name Név @@ -25617,7 +24397,12 @@ p, li { white-space: pre-wrap; } Meghatározás... - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... Mozgatás a sorban... @@ -25642,7 +24427,7 @@ p, li { white-space: pre-wrap; } Mappa kiválasztása - + Anonymous end-to-end encrypted tunnel 0x @@ -25663,7 +24448,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -25696,7 +24481,17 @@ p, li { white-space: pre-wrap; } %1 fájl nem teljes. Amennyiben ez egy médiafájl, próbáld ki az előnézetet. - + + Warning + Vigyázat + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name Fájlnév megváltoztatása @@ -25711,7 +24506,7 @@ p, li { white-space: pre-wrap; } Kérlek, írj be egy új --és megfelelő-- fájlnevet - + Expand all Összes lenyitása @@ -25838,23 +24633,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Oszlopok - + File Transfers Fájl átvitelek - + Path Elérési út @@ -25864,7 +24654,7 @@ p, li { white-space: pre-wrap; } Elérési útvonal mutatása - + Could not delete preview file @@ -25874,7 +24664,7 @@ p, li { white-space: pre-wrap; } Újból megpróbálod? - + Create Collection... Gyűjtemény létrehozása @@ -25889,7 +24679,7 @@ p, li { white-space: pre-wrap; } Gyűjtemény megtekintése - + Collection Kollekció @@ -25899,7 +24689,7 @@ p, li { white-space: pre-wrap; } %1 alagút - + Anonymous tunnel 0x @@ -26120,10 +24910,6 @@ p, li { white-space: pre-wrap; } File transfer tunnels - - Anonymous tunnels - Névtelen alagutak - Authenticated tunnels @@ -26317,12 +25103,17 @@ p, li { white-space: pre-wrap; } Forma - + Enable Retroshare WEB Interface - + + Status: + Állapot: + + + Web parameters @@ -26362,21 +25153,27 @@ p, li { white-space: pre-wrap; } Engedélyezd a hozzáférést az összes IP cím részére (Alapértelmezett: csak localhost) - Apply setting and start browser - Beállítások alkalmazása és a böngésző indítása - - - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled A beépített böngésző nincs engedélyezve @@ -26386,12 +25183,12 @@ p, li { white-space: pre-wrap; } A beépített böngészőt a menü "Beállítások" -> "Böngésző" pontjai alatt engedélyezheted. - + failed to start Webinterface a böngészőt nem sikerült elindítani - + Webinterface Böngésző @@ -26528,11 +25325,7 @@ p, li { white-space: pre-wrap; } Wiki oldalak - New Group - Új csoport - - - + Page Name Oldalnév @@ -26547,7 +25340,7 @@ p, li { white-space: pre-wrap; } Eredeti azonosító - + << << @@ -26635,7 +25428,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History Oldalszerkesztés előzményei @@ -26670,7 +25463,7 @@ p, li { white-space: pre-wrap; } Oldal azonosító - + \/ \/ @@ -26700,14 +25493,18 @@ p, li { white-space: pre-wrap; } Címkék - - + + History + Előzmények + + + Show Edit History Szerkesztési előzmények mutatása - + Status Állapot @@ -26728,7 +25525,7 @@ p, li { white-space: pre-wrap; } Visszaállítás - + Submit Jóváhagyás @@ -26800,10 +25597,6 @@ p, li { white-space: pre-wrap; } WireDialog - - TimeRange - Időhatár - Create Account @@ -26815,16 +25608,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - Frissítés - - - + Settings @@ -26839,7 +25623,7 @@ p, li { white-space: pre-wrap; } Többiek - + Who to Follow @@ -26859,7 +25643,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -26889,85 +25673,17 @@ p, li { white-space: pre-wrap; } - Last Month - Utolsó hónap - - - Last Week - Utolsó hét - - - Today - Ma - - - New - Új - - - from - tőle - - - until - eddig - - - Search/Filter - Kereső/Szűrés - - - Network Wide - Egész hálózat - - - Manage Accounts - Profilok kezelése - - - Showing: - Mutatás: - - - + Yourself Saját magad - - Friends - Barátok - Following Követve - Custom - Testreszabott - - - Account 1 - Profil 1 - - - Account 2 - Profil 2 - - - Account 3 - Profil 3 - - - CheckBox - Jelölőnégyzet - - - Post Pulse to Wire - Pulzus küldése a vezetékhez - - - + RetroShare RetroShare @@ -27030,35 +25746,42 @@ p, li { white-space: pre-wrap; } Forma - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + Eltávolítás + + + Location: Hely: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -27103,11 +25826,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + N/A + + + + Following + Követve + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Ismeretlen @@ -27185,7 +25938,7 @@ p, li { white-space: pre-wrap; } %1y %2d - + k e.g: 3.1 k k @@ -27218,15 +25971,11 @@ p, li { white-space: pre-wrap; } Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif *.webp) - - Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - Képek (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - pgpid_item_model - + Do you accept connections signed by this profile? @@ -27345,10 +26094,6 @@ p, li { white-space: pre-wrap; } Denied - - - - - - PGP key signed by you diff --git a/retroshare-gui/src/lang/retroshare_it.ts b/retroshare-gui/src/lang/retroshare_it.ts index 389d7d42d..ade137565 100644 --- a/retroshare-gui/src/lang/retroshare_it.ts +++ b/retroshare-gui/src/lang/retroshare_it.ts @@ -84,13 +84,6 @@ - - AddCommentDialog - - Add Comment - Aggiungi un commento - - AddFileAssociationDialog @@ -129,12 +122,12 @@ RetroShare: Ricerca Avanzata - + Search Criteria Criteri di Ricerca - + Add a further search criterion. Aggiungi un altro criterio di ricerca. @@ -144,7 +137,7 @@ Reinizializza i criteri di ricerca. - + Cancels the search. Annulla la ricerca. @@ -164,177 +157,6 @@ Ricerca - - AlbumCreateDialog - - Create Album - Creare Album - - - Album Name: - Nome album: - - - Category: - Categoria: - - - Animals - Animali - - - Family - Famiglia - - - Friends - Amici - - - Flowers - Fiori - - - Holiday - Vacanze - - - Landscapes - Panorami - - - Pets - Animali domestici - - - Portraits - Ritratti - - - Travel - Viaggi - - - Work - Lavoro - - - Random - Casuale - - - Caption: - Didascalia: - - - Where: - Dove: - - - Photographer: - Fotografo: - - - Description: - Descrizione: - - - Share Options - Opzioni condivisione - - - Policy: - Politica: - - - Quality: - Qualità: - - - Comments: - Commenti: - - - Identity: - Identità: - - - Public - Pubblico - - - Restricted - Limitato - - - Resize Images (< 1Mb) - Ridimensionare le immagini (< 1 Mb) - - - Resize Images (< 10Mb) - Ridimensionare le immagini (< 10 Mb) - - - Send Original Images - Invia le immagini originali - - - No Comments Allowed - Nessun commento permesso - - - Authenticated Comments - Commenti autenticati - - - Any Comments Allowed - Eventuali commenti ammessi - - - Publish with Identity - Pubblica con identità - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Trascina &amp; Lascia per inserire immagini. Clicca sull'immagine per modificare i dettagli in basso.</span></p></body></html> - - - Back - Indietro - - - Add Photos - Aggiungi foto - - - Publish Album - Pubblicare Album - - - Untitle Album - Togli titolo Album - - - Say something about this album... - Dì qualcosa su questo album... - - - Where were these taken? - Dove sono state prese queste? - - - Load Album Thumbnail - Miniatura dell'Album Load - - AlbumDialog @@ -343,19 +165,11 @@ p, li { white-space: pre-wrap; } Album Album - - Album Thumbnail - Miniatura dell'album - TextLabel EtichettaTesto - - Summary - Riassunto - Album Title: @@ -371,34 +185,6 @@ p, li { white-space: pre-wrap; } Caption Didascalia - - Where: - Dove: - - - When - Quando - - - Description: - Descrizione: - - - Share Options - Opzioni condivisione - - - Comments - Commenti - - - Publish Identity - Pubblicare l'identità - - - Visibility - Visibilità - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -767,7 +553,7 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. Avvertimento: I servizi qui presenti sono sperimentali. Per favore aiutaci a testarli. @@ -783,14 +569,6 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro Circles Circoli - - GxsForums - GxsForums - - - GxsChannels - Canali Gxs - The Wire @@ -802,10 +580,23 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro Fotografie + + AspectRatioPixmapLabel + + + Save image + Salva immagine + + + + Copy image + + + AttachFileItem - + %p Kb %p Kb @@ -842,17 +633,13 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro Browse... - - Add Avatar - Aggiungi Avatar - Remove Rimuovi - + Set your Avatar picture Imposta immagine Avatar @@ -871,10 +658,6 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - Carica Avatar - AvatarWidget @@ -943,22 +726,10 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro Reimposta - Receive Rate - Velocità di Ricezione - - - Send Rate - Velocità di Invio - - - + Always on Top Sempre in Primopiano - - Style - Stile - Changes the transparency of the Bandwidth Graph @@ -974,23 +745,11 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro % Opaque % Opacità - - Save - Salva - - - Cancel - Annulla - Since: Dal: - - Hide Settings - Nascondi Impostazioni - BandwidthStatsWidget @@ -1063,7 +822,7 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro BoardPostDisplayWidgetBase - + Comment Commento @@ -1093,12 +852,12 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> <p><font color="#ff0000"><b>L’autore di questo messaggio (con ID %1) è bloccato.</b> - + ago @@ -1106,7 +865,7 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro BoardPostDisplayWidget_card - + Vote up Vota per @@ -1126,7 +885,7 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro \/ - + Posted by @@ -1164,7 +923,7 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro BoardPostDisplayWidget_compact - + Vote up Vota per @@ -1184,7 +943,7 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro \/ - + Click to view picture @@ -1214,7 +973,7 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro Condividi - + Toggle Message Read Status Cambia lo stato dei messaggi letti @@ -1224,7 +983,7 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro Nuovo - + TextLabel @@ -1232,12 +991,12 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro BoardsCommentsItem - + I like this Mi piace - + 0 0 @@ -1257,18 +1016,18 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro Avatar - + New Comment - + Copy RetroShare Link - + Expand Allarga @@ -1283,12 +1042,12 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro - + Name Nome - + Comm value @@ -1457,17 +1216,17 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro ChannelPage - + Channels Canali - + Tabs Tabs - + General Generale @@ -1477,11 +1236,17 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro - Load posts in background (Thread) - Carica i post in sottofondo (Argomento) + + Downloads + Scaricamenti - + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab Apri ogni canale in una nuova tab @@ -1489,7 +1254,7 @@ Ma ricorda: Qualsiasi dato qui presente *SARÀ PERSO* quando aggiorneremo il pro ChannelPostDelegate - + files @@ -1512,7 +1277,7 @@ into the image, so as to ChannelsCommentsItem - + I like this Mi piace @@ -1537,18 +1302,18 @@ into the image, so as to Avatar - + New Comment - + Copy RetroShare Link - + Expand Allarga @@ -1563,7 +1328,7 @@ into the image, so as to - + Name Nome @@ -1573,17 +1338,7 @@ into the image, so as to - - Comment - Commento - - - - Comments - - - - + Hide Nascondi @@ -1591,7 +1346,7 @@ into the image, so as to ChatLobbyDialog - + Name Nome @@ -1782,7 +1537,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby Mostra Chat di Gruppo @@ -1794,22 +1549,6 @@ into the image, so as to Chats Chat - - You have %1 new messages - Hai %1 nuovi messaggi - - - You have %1 new message - Hai %1 nuovo messaggio - - - %1 new messages - %1 nuovi messaggi - - - %1 new message - %1 nuovo messaggio - You have %1 mentions @@ -1831,13 +1570,14 @@ into the image, so as to - + + Unknown Lobby Gruppo di interesse sconosciuto - - + + Remove All Rimuovi tutto @@ -1845,13 +1585,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Nome - + Count Count @@ -1861,33 +1601,7 @@ into the image, so as to Argomento - - Private Subscribed chat rooms - Stanze di conversazione private sottoscritte - - - - - Public Subscribed chat rooms - Stanze di conversazione pubbliche sottoscritte - - - - Private chat rooms - Stanze di conversazione private - - - - - Public chat rooms - Stanze di conversazione pubbliche - - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/images/add_24x24.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Stanze di conversazione</h1> <p>Le stanze di conversazione funzionano similmente a IRC. Esse ti permettono di parlare anonimamente con moltissime persone senza la necessità di avere amici.</p> <p>Una stanza di conversazione può essere pubblica (i tuoi amici la vedono) o privata (i tuoi amici non possono vederla, a meno che tu non li inviti con <img src=":/images/add_24x24.png" width=%2/>). Una volta che sei stato invitato ad una stanza di conversazione privata, sarai in grado di vederla quando i tuoi amici la staranno usando.</p> <p>La lista a sinistra mostra il gruppo di conversazione alla quale i tuoi amici stanno partecipando. Puoi sia <ul> <li>Fare clic sul pulsante destro per creare una nuova stanza di conversazione</li> <li>Fare doppio clic su una stanza di conversazione per entrare, chiacchierare e mostrare la stanza stessa ai tuoi amici</li> </ul> Nota: Per far funzionare adeguatamente le stanze di conversazione, il tuo computer deve avere l'ora impostata correttamente. Quindi controlla l'ora del tuo sistema!</p> - - - + Create chat room Crea chat room @@ -1897,7 +1611,7 @@ into the image, so as to Lascia questa stanza - + Create a non anonymous identity and enter this room Crea un'identità non anonima ed entra in questa stanza @@ -1956,12 +1670,12 @@ Seleziona delle stanze di conversazione sulla sinistra per vederne i dettagli. Fai doppio clic su una stanza di conversazione per entrare e conversare. - + %1 invites you to chat room named %2 %1 ti invita alla stanza di conversazione chiamata %2 - + Choose a non anonymous identity for this chat room: @@ -1971,31 +1685,31 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Scegli un'identità per questa stanza di conversazione: - Create chat lobby - Crea chat di gruppo - - - + [No topic provided] [Nessun argomento disponibile] - Selected lobby info - Informazioni sul gruppo di interesse selezionato - - - + + Private Privato - + + + Public Pubblico - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted ID anonime accettati @@ -2005,42 +1719,25 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Disabilita Abbonamento Automatico - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe Abilita Abbonamento Automatico - + Search Chat lobbies Cerca i gruppi delle chat - + Search Name Cerca nome - Subscribed - Sottoscritto - - - + Columns Colonne - - Yes - - - - No - No - Chat rooms @@ -2052,47 +1749,47 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare. - + Chat Room info - + Chat room Name: Nome chat room: - + Chat room Id: ID chat room: - + Topic: Argomento: - + Type: Tipo: - + Security: Sicurezza: - + Peers: Amici: - - - - - - + + + + + + TextLabel Etichetta Testo @@ -2107,13 +1804,24 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Nessuna ID anonima - + Show Mostra - + + Private Subscribed + + + + + + Public Subscribed + + + + column colonna @@ -2127,7 +1835,7 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare. ChatMsgItem - + Remove Item Rimuovi Elemento @@ -2172,46 +1880,22 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.ChatPage - + General Generale - - Distant Chat - Conversazione a distanza - Everyone Tutti - - Contacts - Contatti - Nobody Nessuno - Accept encrypted distant chat from - Accetta una conversazione criptata a distanza da - - - Chat Settings - Impostazioni Chat - - - Enable Emoticons Private Chat - Abilita Emoticons nella Conversazione Privata - - - Enable Emoticons Group Chat - Abilita Emoticons per la Chat di Gruppo - - - + Enable custom fonts Attivare i caratteri personalizzati @@ -2220,10 +1904,6 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Enable custom font size Abilita dimensione del carattere personalizzata - - Minimum font size - Dimensioni minime del font - Enable bold @@ -2235,7 +1915,7 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Abilitare il corsivo - + General settings @@ -2260,11 +1940,7 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Carica immagini incorporate - Chat Lobby - Grippo di discussione - - - + Blink tab icon Lampeggiare l'icona sulla scheda @@ -2273,10 +1949,6 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Do not send typing notifications Non inviare le notifiche di digitazione - - Private Chat - Chat Privata - Open Window for new chat @@ -2298,11 +1970,7 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Lampeggiare l'icona finestra/scheda - Chat Font - Chat Font - - - + Change Chat Font Cambia Font per la Chat @@ -2312,14 +1980,10 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Font per la Chat - + History Storico - - Style - Stile - @@ -2334,17 +1998,13 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Variant: Variante - - Group chat - Chat di gruppo - Private chat Chat privata - + Choose your default font for Chat. @@ -2408,22 +2068,28 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.<html><head/><body><p align="justify">In this tab you can setup how many chat messages Retroshare will keep saved on the disc and how much of the previous conversation it will display, for the different chat systems. The max storage period allows to discard old messages and prevents the chat history from filling up with volatile chat (e.g. chat lobbies and distant chat).</p></body></html> <html><head/><body><p align="justify">In questa finestra puoi impostare quanti messaggi delle aree di conversazione RetroShare conserverà salvati sul disco e quanto verrà mostrato delle previe conversazioni, per i diversi sistemi di chat. Il periodo massimo di archiviazione consente di eliminare i messaggi vecchi e previene che lo storico delle conversazioni si riempa con chiacchiere volatili (p.es. aree di conversazione e conversazioni a distanza).</p></body></html> - - Chatlobbies - Gruppi di chat - Enabled: Abilitato: - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2433,7 +2099,17 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms Chat room @@ -2530,11 +2206,7 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Periodo massimo di archiviazione, in giorni (0 = mantieni tutti): - Search by default - Ricerca predefinita - - - + Case sensitive Maiusc./minusc. significativo @@ -2573,10 +2245,6 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Threshold for automatic search Soglia per la ricerca automatica - - Default identity for chat lobbies: - Identità predefinita per le aree di conversazione: - Show Bar by default @@ -2644,7 +2312,7 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare. ChatToaster - + Show Chat Mostra Chat @@ -2680,7 +2348,7 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare. ChatWidget - + Close Chiudi @@ -2715,12 +2383,12 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Corsivo - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon Inserisci emoticon @@ -2800,11 +2468,6 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare.Insert horizontal rule Inserisci riga orizzontale - - - Save image - Salva immagine - Import sticker @@ -2842,7 +2505,7 @@ Fai doppio clic su una stanza di conversazione per entrare e conversare. - + is typing... sta scrivendo... @@ -2866,7 +2529,7 @@ dopo la conversione in HTML. - + Do you really want to physically delete the history? Vuoi veramente cancellare lo storico dal disco? @@ -2916,7 +2579,7 @@ dopo la conversione in HTML. è occupato probabilmente non risponderà - + Find Case Sensitively Ricerca rispettando maiuscole/minuscole @@ -2938,7 +2601,7 @@ dopo la conversione in HTML. Non smettere di colorare dopo X elementi trovati (richiede più potenza CPU) - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> <b>Trova precedente </b><br/><i>Ctrl+Shift+G</i> @@ -2953,16 +2616,12 @@ dopo la conversione in HTML. <b>Trova </b><br/><i>Ctrl+F</i> - + (Status) (Stato) - Set text font & color - Imposta font e colore del testo - - - + Attach a File Allega un file @@ -2978,12 +2637,12 @@ dopo la conversione in HTML. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> <b>Contrassegna questo testo selezionato</b><br><i>Ctr+M</i> - + Person id: @@ -2994,12 +2653,12 @@ Double click on it to add his name on text writer. - + Unsigned Non firmato - + items found. elementi trovati. @@ -3019,7 +2678,7 @@ Double click on it to add his name on text writer. Digitare un messaggio qui - + Don't stop to color after Non smettere di colorare dopo @@ -3045,7 +2704,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: Visualizzando i dettagli: @@ -3067,7 +2726,7 @@ Double click on it to add his name on text writer. - + Personal Circles Circoli personali @@ -3093,7 +2752,7 @@ Double click on it to add his name on text writer. - + Friends Amici @@ -3153,7 +2812,7 @@ Double click on it to add his name on text writer. Amico di Amici - + External Circles (Admin) Cerchia Esterna (Admin) @@ -3169,7 +2828,7 @@ Double click on it to add his name on text writer. - + Circles Circoli @@ -3221,43 +2880,48 @@ Double click on it to add his name on text writer. - + RetroShare RetroShare - + - + Error : cannot get peer details. Errore: impossibile ottenere dettagli contatto - + Retroshare ID - + <p>This Retroshare ID contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: + + + <b>DNS:</b> : + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3269,7 +2933,7 @@ Double click on it to add his name on text writer. Cifratura - + Not connected Non connesso @@ -3351,25 +3015,17 @@ Double click on it to add his name on text writer. nessuno - + <p>This certificate contains: <p>Questo certificato contiene: - + <li>a <b>node ID</b> and <b>name</b> <li>un <b>ID nodo</b> ed un <b>nome</b> - an <b>onion address</b> and <b>port</b> - un <b>indirizzo onion</b> ed una <b>porta</b> - - - an <b>IP address</b> and <b>port</b> - un <b>indirizz IP</b> ed una <b>porta</b> - - - + <p>You can use this certificate to make new friends. Send it by email, or give it hand to hand.</p> <p>Puoi usare questo certificato per farti nuovi amici. Invialo per email, o consegnalo di persona.</p> @@ -3384,7 +3040,7 @@ Double click on it to add his name on text writer. <html><head/><body><p>Questo è un metodo di criptazione usato da <span style=" font-weight:600;">OpenSSL</span>. La connessione ai nodi amici</p><p>è sempre pesantemente criptata e in caso sia presente il DHE la connessione utilizzerà anche </p><p>&quot;la perfetta segretezza in avanti&quot;.</p></body></html> - + with con @@ -3401,108 +3057,16 @@ Double click on it to add his name on text writer. Connect Friend Wizard Wizard Connessione Amici - - Add a new Friend - Aggiungere un nuovo amico - - - &You get a certificate file from your friend - &Y-Ottieno un file di certificato dal tuo amico - - - &Make friend with selected friends of my friends - Fatti a&mico con amici degli amici selezionati - - - Include signatures - Includi firme - - - Copy your Cert to Clipboard - Copia nel PortaBlocco il Certificato - - - Save your Cert into a File - Salva il tuo certificato in un File - - - Run Email program - Lancia il programma di posta elettronica - Open Cert of your friend from File - - Please, paste your friend's Retroshare certificate into the box below - Per favore, incolla il certificato Retroshare del tuo amico nel riquadro sottostante - - - Certificate files - File di certificato - - - Use PGP certificates saved in files. - Utilizzo di certificati PGP salvato nel file. - - - Import friend's certificate... - Importare il certificato di un amico... - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - È necessario generare un file con il tuo certificato e darlo al tuo amico. Inoltre, è possibile utilizzare un file già generato. - - - Export my certificate... - Esportare il mio certificato... - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - Trascinare e rilasciare il certificato di tuoi amici in questa finestra o specificare il percorso nella casella sottostante - - - Browse - Scorri - - - Friends of friends - Amici di amici - - - Select now who you want to make friends with. - Selezionare ora con chi desideri fare amicizia. - - - Show me: - Fammi vedere: - - - Make friend with these peers - Farti amico con questi contatti - RetroShare ID ID RetroShare - - Use RetroShare ID for adding a Friend which is available in your network. - Utilizzare ID RetroShare per aggiuntgere un amico disponibile in rete. - - - Add Friends RetroShare ID... - Aggiungere l'ID RetroShare degli amici.... - - - Paste Friends RetroShare ID in the box below - Incollare ID degli amici RetroShare nella casella sottostante - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - Immettere l'ID RetroShare del tuo amico, ad esempio Peer@BDE8D16A46D938CF - RetroShare is better with Friends @@ -3544,27 +3108,7 @@ Double click on it to add his name on text writer. Email - Invite Friends by Email - Invitare gli amici via Email - - - Enter your friends' email addresses (separate each one with a semicolon) - Inserire indirizzi email dei tuoi amici (separare ognuno con un punto e virgola) - - - Your friends' email addresses: - Indirizzi email dei tuoi amici: - - - Enter Friends Email addresses - Inserisci gli indirizzi Email di amici - - - Subject: - Oggetto: - - - + @@ -3580,77 +3124,32 @@ Double click on it to add his name on text writer. Dettagli su richiesta - + Peer details Dettagli contatto - + Name: Nome: - - Email: - Posta elettronica: - - - Node: - Nodo : - - - Please note that RetroShare will require excessive amounts of bandwidth, memory and CPU if you add too many friends. You can add as many friends as you like, but more than 40 will probably require too much -resources. - Tieni conto che se aggiungi troppi amici RetroShare richiederà quantità eccessive di banda, memoria e CPU. Puoi aggiungere quanti amici vuoi, ma oltre i 40 probabilmente serviranno troppo risorse. - Location: Località: - + Options Opzioni - This wizard will help you to connect to your friend(s) to RetroShare network.<br>Select how you would like to add a friend: - Questa procedura guidata aiuterà a collegarti ai tuoi amici nella rete RetroShare.<br>Scegli come vorresti aggiungere un amico: - - - Enter the certificate manually - Inserisce il certificato manualmente - - - Enter RetroShare ID manually - Inserisce l’ID RetroShare manualmente - - - &Send an Invitation by Web Mail Providers - &Spedisci un Invinto tramite gestori di Web Mail - - - Recommend many friends to each other - Raccomanda molti amici a vicenda - - - RetroShare certificate - Certificato Retroshare - - - Please paste below your friend's Retroshare certificate - Per favore, incolla il certificato Retroshare del tuo amico - - - Paste certificate - Incollare il certificato - - - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> <html><head/><body><p>Questo riquadro richiede il certificato Retroshare del tuo amico. ATTENZIONE: Si tratta di una cosa diversa dalla chiave di profilo del tuo amico. Non incollare la chiave di profilo del tuo amico qui (nemmeno una sua parte). Non funzionerebbe.</p></body></html> - + Add friend to group: Aggiungi i tuoi amici al gruppo: @@ -3660,7 +3159,7 @@ resources. Autenticare amico (firma chiave PGP) - + Please paste below your friend's Retroshare ID @@ -3685,16 +3184,22 @@ resources. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with Aggiungi come amico per connettersi con - To accept the Friend Request, click the Finish button. - Per accettare la Richiesta di Amicizia, fai clic sul bottone Fine. - - - + Sorry, some error appeared Siamo spiacenti, si è verificato qualche errore @@ -3714,32 +3219,27 @@ resources. Dettagli sul tuo amico: - + Key validity: Chiave validità: - + Profile ID: - - Signers - Firmatari - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Firmare la chiave di un amico è un modo di esprimergli la tua fiducia davanti agli altri amici. Le firme qui sotto attestano crittologicamente che i possessori delle chiavi elencate riconoscono l'attuale chiave PGP come autentica.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. Questo contatto è già sulla tua lista amici. Aggiungendolo potrebbe aver appena impostato l'indirizzo ip. - + To accept the Friend Request, click the Accept button. @@ -3785,49 +3285,17 @@ resources. - + Certificate Load Failed Errore caricando il certificato - Cannot get peer details of PGP key %1 - Non è possibile ottenere dettagli contatto della chiave PGP %1 - - - Any peer I've not signed - Qualsiasi contatto che non ho firmato - - - Friends of my friends who already trust me - Amici dei miei amici che già si fidano di me - - - Signed peers showing as denied - Contatti Firmati appaiono come non accettati - - - Peer name - Nome contatto - - - Also signed by - Firmato anche da - - - Peer id - Id contatto - - - Certificate appears to be valid - Il certificato sembra valido - - - + Not a valid Retroshare certificate! Non è un certificato Retroshare valido! - + RetroShare Invitation Inviti RetroShare @@ -3847,12 +3315,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3860,7 +3328,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3900,7 +3368,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Hai una richiesta di amicizia da - + Profile password needed. @@ -3925,7 +3393,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3935,47 +3403,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - Certificate Load Failed:file %1 not found - Fallito caricamento certificato: file %1 introvabile - - - This Peer %1 is not available in your Network - Questo contatto %1 indisponibile sulla tua rete - - - Use new certificate format (safer, more robust) - Utilizza nuovo formato di certificato (più sicuro, più robusto) - - - Use old (backward compatible) certificate format - Usa precedente formato di certificato (compatibile) - - - Remove signatures - Rimuovi firme - - - RetroShare Invite - Invito RetroShare - - - Connect Friend Help - Aiuto connessione amico - - - You can copy this text and send it to your friend via email or some other way - Puoi copiare questo testo e inviarlo al tuo amico via email o qualche altra maniera - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Il vostro Certificato è copiato nel PortaBlocco, incollalo e invialo ai tuoi amici via email o qualche altro modo - - - Save as... - Salva come... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -4014,11 +3442,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.*** Nessuno *** - Use as direct source, when available - Usa come fonte diretta, quando disponibile - - - + IP-Addr: Ind. IP: @@ -4028,7 +3452,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Indirizzo IP - + Show Advanced options Mostra Opzioni avanzate @@ -4037,10 +3461,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Firmare la chiave di un amico è un modo di esprimergli la tua fiducia davanti agli altri amici. Li aiuta a decidere quando accettare connessioni basate su quella chiave, fidandosi di te. Firmare una chiave è assolutamente facoltativo e la firma non si può revocare, quindi scegli saggiamente quando farlo.</span></p></body></html> - - <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> - <html><head/><body><p align="justify">Retroshare cerca periodicamente, nelle liste dei tuoi amici, files corrispondenti ai tuoi trasferimenti, così da poter stabilire dei trasferimenti diretti. In questo caso, il tuo amico saprà che tu stai scaricando uno dei suoi files.</p><p align="justify">Per prevenire questo comportamento solo per questo amico, deseleziona questa opzione. Puoi comunque effettuare un trasferimento diretto se lo richiedi esplicitamente, ad es. scaricando qualcosa dalla lista di files del tuo amico. Questa impostazione è applicata a tutte le locazioni dello stesso nodo.</p></body></html> - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> @@ -4051,45 +3471,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> <html><head/><body><p>Gli utenti con questa opzione abilitata non possono connettersi se il loro indirizzo di connessione non è nella lista degli indirizzi permessi. Questo ti protegge da attacchi basati sul traffico. Quando l'opzione viene utilizzata, gli utenti rifiutati vengono riportati su &quot;elementi sulla sicurezza dei dati in arrivo&quot; nella sezione relativa alle novità sui dati in arrivo. Da li, potrai permettere/bloccare i loro indizzi IP. Si applica a tutte le locazioni dello stesso nodo.</p></body></html> - - Recommend many friends to each others - Raccomanda molti amici gli uni agli altri - - - Friend Recommendations - Consigli dell'amico - - - The text below is your Retroshare certificate. You have to provide it to your friend - Il testo sottostante è il tuo certificato Retroshare. Dovrai darlo al tuo amico. - - - Message: - Messaggio: - - - Recommend friends - Raccomanda amici - - - To - A - - - Please select at least one friend for recommendation. - Si prega di selezionare almeno un amico da raccomandare. - - - Please select at least one friend as recipient. - Si prega di selezionare almeno un amico come destinatario. - Add key to keyring Aggiungi chiave al portachiavi. - + This key is already in your keyring Questa chiave è già presente nel portachiavi @@ -4105,7 +3493,7 @@ messaggi distanti a questo contatto anche se non hai amici. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. Il certificato ha un numero di versione errato. Ricorda che la versione 0.5 e la 0.6 delle reti sono incompatibili. @@ -4140,7 +3528,7 @@ anche se non hai amici. Aggiungi IP alla whitelist - + No IP in this certificate! Nessun IP in questo certificato @@ -4150,27 +3538,10 @@ anche se non hai amici. <p>Questo certificato non ha indirizzo IP. Dovrai utilizzare la ricerca e la DHT per trovare il tuo amico. Dato che richiedi l'uso di una lista di IP autorizzati, l'utente sarà segnalato nella lista degli elementi di sicurezza in ingresso. Da li potrai autorizzare il suo indirizzo IP.</p> - - [Unknown] - - - - + Added with certificate from %1 Aggiunto con certificato da %1 - - Paste Cert of your friend from Clipboard - Incolla il Certificato del tuo amico dal PortaBlocco - - - Certificate Load Failed:can't read from file %1 - Fallito caricamento certificato: impossibile leggere dal file %1 - - - Certificate Load Failed:something is wrong with %1 - Fallito caricamento certificato: qualcosa non va con %1 - ConnectProgressDialog @@ -4232,7 +3603,7 @@ anche se non hai amici. - + UDP Setup Impostazione UDP @@ -4260,7 +3631,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant Assistente di connessione @@ -4270,17 +3641,20 @@ p, li { white-space: pre-wrap; } ID dell'amico non valido - + + Unknown State Stato sconosciuto - + + Offline Offline - + + Behind Symmetric NAT Dietro ad un NAT simmetrico @@ -4290,12 +3664,14 @@ p, li { white-space: pre-wrap; } Dietro un NAT & nessun DHT - + + NET Restart Riavvio rete - + + Behind NAT Dietro un NAT @@ -4305,7 +3681,8 @@ p, li { white-space: pre-wrap; } Nessun DHT - + + NET STATE GOOD! Stato della rete buono! @@ -4330,7 +3707,7 @@ p, li { white-space: pre-wrap; } Ricerca degli amici RS in corso - + Lookup requires DHT Il controllo richiede DHT @@ -4622,7 +3999,7 @@ p, li { white-space: pre-wrap; } Si prega di riprovare importando l'intero Certificato - + @@ -4630,7 +4007,8 @@ p, li { white-space: pre-wrap; } N/D - + + UNVERIFIABLE FORWARD! FORWARD NON VERIFICABILE! @@ -4640,7 +4018,7 @@ p, li { white-space: pre-wrap; } FORWARD NON VERIFICABILE E NESSUNA DHT! - + Searching Cercando @@ -4676,12 +4054,12 @@ p, li { white-space: pre-wrap; } Dettagli della cerchia - + Name Nome - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4701,7 +4079,7 @@ p, li { white-space: pre-wrap; } - + IDs ID @@ -4721,18 +4099,18 @@ p, li { white-space: pre-wrap; } Filtro - + Cancel Annulla - + Nickname Soprannome - + Invited Members Membri invitati @@ -4747,15 +4125,7 @@ p, li { white-space: pre-wrap; } Persone conosciute - ID - ID - - - Type - Tipo - - - + Name: Nome: @@ -4795,23 +4165,19 @@ p, li { white-space: pre-wrap; } - Only visible to members of: - Visibile soltanto ai membri di: - - - - + + RetroShare RetroShare - + Please set a name for your Circle Per favore imposta un nome per la tua cerchia - + No Restriction Circle Selected Nessuna cerchia ristretta selezionata @@ -4821,12 +4187,24 @@ p, li { white-space: pre-wrap; } Nessuna cerchia limitata selezionata - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add Aggiungi @@ -4836,7 +4214,7 @@ p, li { white-space: pre-wrap; } Rimuovi - + Search Cerca @@ -4851,10 +4229,6 @@ p, li { white-space: pre-wrap; } Signed Firmato - - Signed by known nodes - Firmato da Nodi conosciuti - Edit Circle @@ -4871,10 +4245,6 @@ p, li { white-space: pre-wrap; } PGP Identity Identità PGP - - Anon Id - Id Anonimo - Circle name @@ -4897,17 +4267,13 @@ p, li { white-space: pre-wrap; } Crea una nuova cerchia - + Create Crea - PGP Linked Id - PGP Id Collegato - - - + Add Member Aggiungere membro @@ -4926,7 +4292,7 @@ p, li { white-space: pre-wrap; } Crea un Gruppo - + Group Name: Nome gruppo: @@ -4961,7 +4327,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post Nuovo post nel canale @@ -4971,7 +4337,7 @@ p, li { white-space: pre-wrap; } Post del canale - + Post @@ -5032,23 +4398,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Usa i bottoni Trascina-Lascia / Aggiungi Files, per segmentare nuovi files.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Copia/Incolla collegamenti RetroShare dalle tue condivisioni</span></p></body></html> - - Add File to Attach - Aggiungi un file da allegare - Add Channel Thumbnail Aggiungi miniature del canale - - Message - Messaggio - - - Subject : - Oggetto: - @@ -5134,17 +4488,17 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -5163,17 +4517,18 @@ p, li { white-space: pre-wrap; } The following files will only be shared for 30 days. Think about adding them to a shared directory. - - File already Added and Hashed - File già aggiunto e codificato - Please add a Subject Aggiungi un Oggetto - + + Cannot publish post + + + + Load thumbnail picture Carica una miniatura d'immagine @@ -5188,18 +4543,12 @@ p, li { white-space: pre-wrap; } Nascondi - - + Generate mass data Genera dati di massa - - Do you really want to generate %1 messages ? - Vuoi davvero generare %1 messaggi ? - - - + You are about to add files you're not actually sharing. Do you still want this to happen? Stai per aggiungere dei file che non stai condividendo veramente. Vuoi comunque che questo succeda? @@ -5233,7 +4582,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message Posta un Messaggio nel Forum @@ -5242,10 +4591,6 @@ p, li { white-space: pre-wrap; } Forum Forum - - Subject - Oggetto - Attach File @@ -5266,8 +4611,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -5286,7 +4631,7 @@ p, li { white-space: pre-wrap; } Puoi allegare files con Trascina e Lascia qui in questa finestra - + Post @@ -5316,17 +4661,17 @@ p, li { white-space: pre-wrap; } - + No Forum Nessun forum - + In Reply to In Risposta a - + Title Titolo @@ -5379,7 +4724,7 @@ Do you want to discard this message? Carica un file immagine - + No compatible ID for this forum ID non compatibile con questo forum @@ -5389,8 +4734,8 @@ Do you want to discard this message? A nessuna delle tue identità è permesso scrivere in questo forum. Questo può derivare dalla limitazione del forum ad una cerchia nella quale non è presente nessuna delle tue identità, oppure perché il forum richiede identità firmate con PGP. - - + + Generate mass data Genera dati di massa @@ -5399,10 +4744,6 @@ Do you want to discard this message? Do you really want to generate %1 messages ? Vuoi davvero generare %1 messaggi ? - - Send - Invia - Post as @@ -5417,23 +4758,7 @@ Do you want to discard this message? CreateLobbyDialog - Create Chat Lobby - Crea un gruppo di Chat - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - Un gruppo di discussione (lobby) è un gruppo di conversazione anonimo e decentralizzato. Tutti i partecipanti ricevono tutti i messaggi. Una volta creata la lobby è possibile invitare altri amici dalla scheda amici. - - - Lobby name: - Nome del gruppo: - - - Lobby topic: - Argomento Gruppo di Conversazione: - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5468,7 +4793,7 @@ Do you want to discard this message? - + Create Crea @@ -5478,11 +4803,7 @@ Do you want to discard this message? Annulla - <html><head/><body><p>If you check this, only PGP-signed ids can be used to join and talk in this lobby. This limitation prevents anonymous spamming as it becomes possible for at least some people in the lobby to locate the spammer's node.</p></body></html> - Se la imposti, solo le identità firmate con PGP potranno essere usate per unirsi e parlare in questo gruppo. Questa limitazione previene lo spamming anonimo dato che diventa possibile, almeno per qualcuno del gruppo, localizzare il nodo dello spammer. - - - + require PGP-signed identities richiede identità firmate-PGP @@ -5497,11 +4818,7 @@ Do you want to discard this message? Seleziona gli Amici con cui avere conversazione di gruppo. - Invited friends - Amici invitati - - - + Create Chat Room Crea una stanza di conversazione @@ -5522,7 +4839,7 @@ Do you want to discard this message? Contatti: - + Identity to use: Identità da utilizzare: @@ -5530,17 +4847,17 @@ Do you want to discard this message? CryptoPage - + Public Information Informazioni pubbliche - + Name: Nome: - + Location: Località: @@ -5550,12 +4867,12 @@ Do you want to discard this message? ID della località: - + Software Version: Versione del software: - + Online since: Online dal: @@ -5575,12 +4892,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5590,7 +4902,7 @@ Do you want to discard this message? - + Other Information Altre informazioni @@ -5600,17 +4912,12 @@ Do you want to discard this message? - + Profile Profilo - - Certificate - Certicato - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5620,11 +4927,7 @@ Do you want to discard this message? Includi Firma - Save Key into a file - Salvare la chiave in un file - - - + Export Identity Esporta Identità @@ -5696,33 +4999,33 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari - + TextLabel Etichetta Testo - + PGP fingerprint: Impronta PGP: - - Node information - Informazioni nodo - - - + PGP Id : Id PGP : - + Friend nodes: Nodi amici: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5761,14 +5064,6 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari Node Nodo - - Create new node... - Crea nuovo nodo... - - - show statistics window - Mostra la finestra delle statistiche - DHTGraphSource @@ -5785,10 +5080,6 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari DHT DHT - - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your friends to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your friends.</p> - <p>Retroshare usa il DHT di Bittorrent come proxy per le connessioni. Non "salva" il tuo indirizzo IP nel DHT. Al contrario il DHT è utilizzato dai tuoi amici per raggiungerti, tramite delle normali richieste al DHT. La pallina di stato diventerà verde non appena Retroshare otterrà una risposta DHT da uno dei tuoi amici.</p> - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your trusted nodes to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your trusted nodes.</p> @@ -5824,7 +5115,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari DLListDelegate - + B B @@ -6492,7 +5783,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari DownloadToaster - + Start file File di avvio @@ -6500,38 +5791,38 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari ExprParamElement - + - + to a - + ignore case ignora maius./minus. - - - dd.MM.yyyy - gg.MM.aaaa + + + yyyy-MM-dd + - - + + KB KB - - + + MB MB - - + + GB GB @@ -6539,12 +5830,12 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari ExpressionWidget - + Expression Widget Widget di Espressione - + Delete this expression Cancella Espressione @@ -6706,7 +5997,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari FilesDefs - + Picture Immagine @@ -6716,7 +6007,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari Video - + Audio File audio @@ -6776,11 +6067,21 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Cartelle amici @@ -6902,7 +6203,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari - + ID ID @@ -6937,10 +6238,6 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari Show State Mostra Stato - - Trusted nodes - Nodi fidati - @@ -6948,7 +6245,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari Mostra Grupppi - + Group Gruppo @@ -6984,7 +6281,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari Aggiungi al gruppo - + Search Cerca @@ -7000,7 +6297,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari Ordina per stato - + Profile details Dettagli profilo @@ -7244,7 +6541,7 @@ uno o più peer non sono stati aggiunti ad un gruppo FriendRequestToaster - + Confirm Friend Request Conferma richiesta di amicizia @@ -7261,10 +6558,6 @@ uno o più peer non sono stati aggiunti ad un gruppo FriendSelectionWidget - - Search : - Cerca: - Sort by state @@ -7286,7 +6579,7 @@ uno o più peer non sono stati aggiunti ad un gruppo Cerca Amici - + Mark all Contrassegna tutto @@ -7297,16 +6590,134 @@ uno o più peer non sono stati aggiunti ad un gruppo + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Nome + + + + Node ID + + + + + Address + + + + + Status + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + Fatti amico + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + Il proxy non è abilitato, o è danneggiato. +I servizi sono tutti sù e ben funzionanti?? +Controlla anche le tue porte! + + FriendsDialog - + Edit status message Modificare il messaggio di stato - - + + Broadcast Trasmetti @@ -7389,33 +6800,38 @@ uno o più peer non sono stati aggiunti ad un gruppo Reinizializza carattere predefinito - + Keyring Deposito delle Chiavi - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Rete</h1> <p>La scheda Rete mostra i tui nodi RetroShare amici: i nodi di RetroShare adiacenti che sono collegati a te. </p> <p>Puoi raggruppare assieme i nodi per consentire un accesso più granulare alle informazioni, p.es. consentire solo ad alcuni nodi di vedere certi tuoi file.</p> <p>A destra, troverai 3 schede utili: <ul><li>Diffusione, per inviare messaggi contemporaneamente a tutti i nodi connessi</li> <li>Grafico rete locale, mostra la rete intorno a te, basandosi sulle informazioni di rilevamento</li> <li>Portachiavi, contiene le chiavi di nodo che hai raccolto, per lo più trasmesse dai tuoi nodi amici</li></ul></p> - - - + Retroshare broadcast chat: messages are sent to all connected friends. - - + + Network Rete - + + Friend Server + + + + Network graph Grafico della rete - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. Imposta il tuo messaggio di stato qui @@ -7433,7 +6849,17 @@ uno o più peer non sono stati aggiunti ad un gruppo Parola chiave - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters Ogni campio deve avere minimo 3 caratteri @@ -7443,17 +6869,12 @@ uno o più peer non sono stati aggiunti ad un gruppo Le password non corrispondono - + Port Porta - - Use BOB - - - - + This password is for PGP Questa Password è per PGP @@ -7474,46 +6895,38 @@ uno o più peer non sono stati aggiunti ad un gruppo Impossibile generare il nuovo certificato, forse la password PGP è errata! - Options - Opzioni - - - + PGP Key Length Lunghezza chiave PGP - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node Nodo standard - TOR/I2P Hidden node - Nodo TOR/I2P nascosto - - - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name Nome nodo - + Node type: @@ -7533,12 +6946,12 @@ uno o più peer non sono stati aggiunti ad un gruppo - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle Esporta questo profilo @@ -7548,42 +6961,43 @@ uno o più peer non sono stati aggiunti ad un gruppo - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel - Advanced options - Opzioni avanzate - - - + hidden address indirizzo nascosto - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. Il tuo profilo è associato ad una coppia di chiavi PGP. RetroShare attualmente ignora chiavi DSA. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> <html><head/><body><p>Questa è la porta di connessione.</p><p>Qualsiasi valore tra 1024 e 65535 </p><p>dovrebbe andar bene. Puoi modificarlo in seguito.</p></body></html> @@ -7631,13 +7045,13 @@ il bottone IMPORT per caricarlo Profilo non salvato. Si è verificato un errore. - + Import profile Importa profilo - + Create new profile and new Retroshare node @@ -7647,7 +7061,7 @@ il bottone IMPORT per caricarlo Crea nuovo nodo Retroshare - + Tor/I2P address Indirizzo Tor/I2P @@ -7682,7 +7096,7 @@ il bottone IMPORT per caricarlo - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7692,12 +7106,7 @@ il bottone IMPORT per caricarlo - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -7707,12 +7116,7 @@ il bottone IMPORT per caricarlo - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7938,36 +7342,13 @@ il bottone IMPORT per caricarlo Avvio - + Invite Friends Invita amici - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare è nulla senza i tuoi amici. Fai click sul bottone per cominciare il processo.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Manda un invito via mail col tuo &quot;ID Certificato&quot; ai tuoi amici </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Assicurati di ricevere anche il loro invito... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Puoi connetterti agli amici solo se vi siete aggiunti reciprocamente.</span></p></body></html> - - - + Add Your Friends to RetroShare Aggiungi i tuoi amici a RetroShare @@ -7977,89 +7358,103 @@ p, li { white-space: pre-wrap; } Aggiungi amici - + + Connect To Friends + Connetti con amici + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Avanzate: Apri porta nel firewall + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - Connetti con amici - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - Avanzate: Apri porta nel firewall - - - + Further Help and Support Ulteriore aiuto e supporto - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website Apri il sito di RS @@ -8084,7 +7479,7 @@ p, li { white-space: pre-wrap; } Opinioni via email - + RetroShare Invitation Inviti RetroShare @@ -8134,12 +7529,12 @@ p, li { white-space: pre-wrap; } Opinioni su RetroShare - + RetroShare Support Supporto RetroShare - + It has many features, including built-in chat, messaging, Ha molte funzionalità, come conversazioni integrate, messaggerie, @@ -8263,7 +7658,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat Mostra conversazioni di gruppo @@ -8271,7 +7666,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] [Sconosciuto] @@ -8437,15 +7832,11 @@ p, li { white-space: pre-wrap; } You can let your friends know about your forum by sharing it with them. Select the friends with which you want to share your forum. Puoi far sapere agli amici del tuo forum condividendolo con loro. Seleziona gli amici con cui vuoi condividere il forum. - - Share topic admin permissions - Condividi i permessi amministrativi dell’argomento - GroupTreeWidget - + Title Titolo @@ -8458,12 +7849,12 @@ p, li { white-space: pre-wrap; } - + Description Descrizione - + Number of Unread message @@ -8488,27 +7879,7 @@ p, li { white-space: pre-wrap; } - Sort Descending Order - Ordinamento decrescente - - - Sort Ascending Order - Ordinamento crescente - - - Sort by Name - Ordina per nome - - - Sort by Popularity - Ordina per popolarità - - - Sort by Last Post - Ordina per post recente - - - + You are admin (modify names and description using Edit menu) @@ -8523,14 +7894,14 @@ p, li { white-space: pre-wrap; } Id - - + + Last Post Ultimo post - + Name Nome @@ -8541,17 +7912,13 @@ p, li { white-space: pre-wrap; } Popolarità - + Never Mai - Display - Mostra - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8564,7 +7931,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and e @@ -8700,7 +8067,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels Canali @@ -8711,22 +8078,22 @@ p, li { white-space: pre-wrap; } Cra canale - + Enable Auto-Download Abilita scaricamento automatico - + My Channels Miei canali - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Canali sottoscritti @@ -8746,12 +8113,12 @@ p, li { white-space: pre-wrap; } Seleziona la cartella di download per il canale - + Disable Auto-Download Annulla scaricamento automatico - + Set download directory Imposta la cartella di download @@ -8786,22 +8153,22 @@ p, li { white-space: pre-wrap; } - + Play Esegui - + Open folder Apri cartella - + Open file - + Error Errore @@ -8821,17 +8188,17 @@ p, li { white-space: pre-wrap; } Verifica - + Are you sure that you want to cancel and delete the file? Sei sicuro di voler annullare ed eliminare questo file? - + Can't open folder Non è possibile aprire la cartella - + Play File Riprodurre File @@ -8841,37 +8208,10 @@ p, li { white-space: pre-wrap; } Il file %1 non esiste nella posizione. - - GxsChannelFilesWidget - - Form - Modulo - - - Filename - Nome file - - - Size - Dimensioni - - - Title - Titolo - - - Published - Pubblicato - - - Status - Status - - GxsChannelGroupDialog - + Create New Channel Crea un Nuovo Canale @@ -8909,9 +8249,19 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - Abbonati al Canale + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel + @@ -8925,7 +8275,7 @@ p, li { white-space: pre-wrap; } - + Expand Allarga @@ -8940,7 +8290,7 @@ p, li { white-space: pre-wrap; } Descrizione Canale - + Loading Sto caricando... @@ -8955,8 +8305,9 @@ p, li { white-space: pre-wrap; } - New Channel - Nuovo canale + + Never + Mai @@ -8967,7 +8318,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: Nuovo commento: @@ -8988,7 +8339,7 @@ p, li { white-space: pre-wrap; } - + Play Esegui @@ -9045,28 +8396,24 @@ p, li { white-space: pre-wrap; } Files Files - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - Attenzione! Hai meno di %1 ore e %2 minuti prima che questo file venga eliminato. Considera di salvarlo. - Hide Nascondi - + New Nuovo - + 0 0 - - + + Comment Commento @@ -9081,21 +8428,17 @@ p, li { white-space: pre-wrap; } Non mi piace - Loading - Sto caricando... - - - + Loading... - + Comments - + Post @@ -9120,119 +8463,16 @@ p, li { white-space: pre-wrap; } Esegui Media - - GxsChannelPostsWidget - - Post to Channel - Posta sul Canale - - - Loading - Sto caricando... - - - Search channels - Cerca canali - - - Title - Titolo - - - Search Title - Ricerca Titolo - - - Message - Messaggio - - - Search Message - Cerca Messaggio - - - Filename - Nome file - - - Search Filename - Cerca Nome File - - - No Channel Selected - Nessun Canale Selezionato - - - Never - Mai - - - Public - Pubblico - - - Disable Auto-Download - Disabilita Download Automatico - - - Enable Auto-Download - Abilita Download Automatico - - - Show feeds - Mostra notizie - - - Show files - Mostra files - - - Administrator: - Amministratore: - - - Last Post: - Ultimo post: - - - unknown - sconosciuto - - - Distribution: - Distribuzione: - - - Feeds - Dispaccio - - - Files - Files - - - Subscribers - Iscritti - - - Description: - Descrizione: - - - Posts (at neighbor nodes): - Posts (a nodi adiacenti): - - GxsChannelPostsWidgetWithModel - + Post to Channel Posta sul Canale - + Add new post @@ -9302,7 +8542,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -9338,7 +8578,7 @@ p, li { white-space: pre-wrap; } - + Comments Commenti @@ -9353,13 +8593,13 @@ p, li { white-space: pre-wrap; } Dispaccio - - + + Click to switch to list view - + Show unread posts only @@ -9374,7 +8614,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -9389,7 +8629,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -9449,12 +8689,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -9501,7 +8751,7 @@ p, li { white-space: pre-wrap; } Unknown - + Scononsciuto @@ -9529,12 +8779,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed Sottoscritto @@ -9566,12 +8817,12 @@ p, li { white-space: pre-wrap; } Disable Auto-Download - + Annulla scaricamento automatico Enable Auto-Download - + Abilita scaricamento automatico @@ -9585,17 +8836,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -9710,7 +8961,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container Commenta Contenitore @@ -9723,7 +8974,7 @@ p, li { white-space: pre-wrap; } Modulo - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9753,7 +9004,7 @@ p, li { white-space: pre-wrap; } Aggiornamento - + Comment Commento @@ -9792,7 +9043,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment Risposta al commento @@ -9816,6 +9067,21 @@ p, li { white-space: pre-wrap; } Vote Down Vota contro + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9825,7 +9091,7 @@ p, li { white-space: pre-wrap; } Commento di rendere - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9854,26 +9120,10 @@ p, li { white-space: pre-wrap; } - + Post - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//IT" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Commento</span></p></body></html> - - - Signed by - FIrmato da - Reply to Comment @@ -9902,7 +9152,7 @@ before you can comment prima che tu possa commentare - + It remains %1 characters after HTML conversion. @@ -9944,14 +9194,6 @@ prima che tu possa commentare Forum moderators can edit/delete/pinup others posts - - Add Forum Admins - Aggiungi Amministratori al Forum - - - Select Forum Admins - Seleziona Amministratori del Forum - Create @@ -9961,7 +9203,7 @@ prima che tu possa commentare GxsForumGroupItem - + Subscribe to Forum Abbonati al Forum @@ -9977,7 +9219,7 @@ prima che tu possa commentare - + Expand Allarga @@ -9997,8 +9239,9 @@ prima che tu possa commentare - Loading - Sto caricando... + + TextLabel + @@ -10029,13 +9272,13 @@ prima che tu possa commentare GxsForumMsgItem - - + + Subject: Oggetto: - + Unsubscribe To Forum Abbandona Forum @@ -10046,7 +9289,7 @@ prima che tu possa commentare - + Expand Allarga @@ -10066,21 +9309,17 @@ prima che tu possa commentare In Risposta a: - Loading - Sto caricando... - - - + Loading... - + Forum Feed Forum Notizie - + Hide Nascondi @@ -10093,63 +9332,66 @@ prima che tu possa commentare Modulo - + Start new Thread for Selected Forum Avvia un nuovo argomento nel forum selezionato - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Ricerca forums - Last Post - Ultimo post - - - + New Thread Nuovo Thread - - - Threaded View - Vista per argomento - - - - Flat View - Vista semplice - - + Title Titolo - - + + Date Data - + Author Autore - - Save image - Salva immagine - - - + Loading Sto caricando - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -10159,12 +9401,7 @@ prima che tu possa commentare - - Lastest post in thread - - - - + Reply Message Messaggio di risposta @@ -10188,10 +9425,6 @@ prima che tu possa commentare Download all files Scarica tutti i files - - Next unread - Successivo non letto - Search Title @@ -10208,31 +9441,23 @@ prima che tu possa commentare Cerca autore - Content - Contenuto - - - Search Content - Ricerca di contenuti - - - + No name Nessun nome - - + + Reply Rispondi - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -10275,20 +9500,12 @@ prima che tu possa commentare Copia collegamento RetroShare - + Hide Nascondi - Expand - Allarga - - - [Banned] - [Bloccato] - - - + [unknown] [sconosciuto] @@ -10318,8 +9535,8 @@ prima che tu possa commentare - - + + Distribution Distribuzione @@ -10333,26 +9550,6 @@ prima che tu possa commentare Anti-spam Anti-spam - - [ ... Redacted message ... ] - [ ... Messaggio Redatto ... ] - - - Anonymous - Anonimo - - - signed - firmato - - - none - nessuno - - - [ ... Missing Message ... ] - [ ... Messaggio Perso ... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10422,12 +9619,12 @@ prima che tu possa commentare Messaggio Originale - + New thread - + Edit Modifica @@ -10488,7 +9685,7 @@ prima che tu possa commentare Reputazione autore - + Show column @@ -10508,7 +9705,7 @@ prima che tu possa commentare - + Anonymous/unknown posts forwarded if reputation is positive @@ -10560,7 +9757,7 @@ This message is missing. You should receive it later. - + No result. @@ -10570,7 +9767,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -10585,7 +9782,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -10651,12 +9848,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums Forums @@ -10687,35 +9884,16 @@ This message is missing. You should receive it later. Altri froum - - GxsForumsFillThread - - Waiting - in attesa - - - Retrieving - Recupero - - - Loading - Caricamento - - GxsGroupDialog - + Name Nome - Add Icon - Aggiungi icona - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels I destinatari della chiave possono pubblicare nei canali di tipo limitato, e vedere e pubblicare in questi canali. @@ -10724,22 +9902,14 @@ This message is missing. You should receive it later. Share Publish Key Condividi chiave pubblicazione - - check peers you would like to share private publish key with - verifica i contatti con cui vuoi condividere la chiave privata di pubblicazione - - - Share Key With - Condividi chiave con - - + Description Descrizione - + Message Distribution Distribuzione messaggio @@ -10747,7 +9917,7 @@ This message is missing. You should receive it later. - + Public Pubblico @@ -10766,14 +9936,6 @@ This message is missing. You should receive it later. New Thread Nuovo Thread - - Required - Obbligatorio - - - Encrypted Msgs - Messaggi cifrati - Personal Signatures @@ -10815,7 +9977,7 @@ This message is missing. You should receive it later. - + Comments: Commenti: @@ -10838,7 +10000,7 @@ This message is missing. You should receive it later. Anti-spam: - + All People @@ -10854,12 +10016,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -10876,23 +10038,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required Richiesta firma PGP - + Never Mai - + Only friends nodes in group @@ -10908,30 +10070,28 @@ This message is missing. You should receive it later. Aggiungi un Nome - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo caricamento Logo Gruppo - + Submit Group Changes Applica Modifiche al Gruppo - Failed to Prepare Group MetaData - please Review - Non è stato possibile preparare i MetaDati del Gruppo — procedi con la Revisione - - - Will be used to send feedback - Verrà utilizzato per inviare feedback - - - + Owner: Proprietario: @@ -10941,12 +10101,12 @@ This message is missing. You should receive it later. Inserisci qui una descrizione - + Info Info - + ID ID @@ -10956,7 +10116,7 @@ This message is missing. You should receive it later. Ultimo post - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -11031,7 +10191,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity Popolarità @@ -11047,27 +10212,22 @@ This message is missing. You should receive it later. - + Created - + Cancel Annulla - + Create Crea - - Author - Autore - - - + GxsIdLabel GxsIdLabel @@ -11075,7 +10235,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading Sto caricando... @@ -11135,7 +10295,7 @@ This message is missing. You should receive it later. Modifica Dettagli - + Synchronise posts of last... @@ -11192,12 +10352,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link Copia Collegamento RetroShare @@ -11220,7 +10380,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature Nessuna firma @@ -11233,40 +10393,24 @@ This message is missing. You should receive it later. GxsIdDetails - Loading - Sto caricando... - - - + Not found Non trovato - - No Signature - Nessuna firma - - - + + [Banned] [Bloccato] - - Authentication - Autenticazione - unknown Key Chiave sconosciuta - anonymous - Anonimo - - - + Loading... @@ -11276,7 +10420,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name Nome&nbsp;dell’identità @@ -11290,16 +10439,20 @@ This message is missing. You should receive it later. Node Nodo - - Signed&nbsp;by - Firmato&nbsp;da - [Unknown] [Scononsciuto] + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -11311,7 +10464,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -11359,17 +10512,13 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] GxsMessageFramePostWidget - - Loading - Sto caricando... - Loading... @@ -11501,10 +10650,6 @@ This message is missing. You should receive it later. Popularity Popolarità - - Details - Dettagli - @@ -11514,7 +10659,7 @@ This message is missing. You should receive it later. Unknown Peer - + Contatto sconosciuto @@ -11524,7 +10669,7 @@ This message is missing. You should receive it later. Unknown - + Scononsciuto @@ -11537,29 +10682,6 @@ This message is missing. You should receive it later. No - - GxsTunnelsDialog - - Tunnel ID: %1 - ID tunnel: %1 - - - from: %1 - da: %1 - - - to: %1 - a: %1 - - - status: %1 - stato: %1 - - - Unknown Peer - Nodo sconosciuto - - HashBox @@ -11777,7 +10899,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -11793,7 +10915,7 @@ p, li { white-space: pre-wrap; } - + Authors Autori @@ -11812,7 +10934,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -11890,7 +11012,7 @@ p, li { white-space: pre-wrap; } Modulo - + Add friend @@ -11900,7 +11022,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -11928,7 +11050,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -11938,7 +11060,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard Copia nel PortaBlocco il Certificato @@ -11948,7 +11070,7 @@ private and secure decentralized communication platform. Salva il tuo certificato in un File - + Send via Email Invia via email @@ -11968,13 +11090,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -11986,12 +11132,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -12006,12 +11152,7 @@ new short format Invito RetroShare - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... Salva come... @@ -12276,14 +11417,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Tutto - + Reputation Reputazione @@ -12293,12 +11434,12 @@ p, li { white-space: pre-wrap; } Cerca - + Anonymous Id Id Anonimo - + Create new Identity Crea nuova identità @@ -12308,7 +11449,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -12323,27 +11464,27 @@ p, li { white-space: pre-wrap; } - + Close Chiudi - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes Voti positivi @@ -12359,29 +11500,39 @@ p, li { white-space: pre-wrap; } Voti negativi - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles Circoli - + Circle name Nome della cerchia @@ -12401,18 +11552,20 @@ p, li { white-space: pre-wrap; } Circoli personali - + + Edit identity Modifica Identità - + + Delete identity Cancella identità - + Chat with this peer Conversa con questo contatto @@ -12422,78 +11575,78 @@ p, li { white-space: pre-wrap; } Avvia una conversazione a distanza con questo contatto - + Owner node ID : ID nodo proprietario : - + Identity name : Nome dell’identità : - + () () - + Identity ID ID dell'identità - + Send message Invia Messaggio - + Identity info Info sull'identità - + Identity ID : ID dell’identità : - + Owner node name : Nome nodo proprietario : - + Create new... - + Type: Tipo: - + Send Invite Manda invito - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> <html><head/><body><p>Opinione media dei nodi adiacenti riguardo questa identità. Negativa è male,</p><p>positiva è buono. Zero è neutrale.</p></body></html> - + Your opinion: La tua opinione: - + Negative Negativo - + Neutral Neutrale @@ -12504,17 +11657,17 @@ p, li { white-space: pre-wrap; } Positivo - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> <html><head/><body><p>Punteggio complessivo della reputazione, tenendo conto del tuo voto e quello dei tuoi amici.</p><p>Negativo è male, positivo è bene. Zero è neutrale. Se il punteggio è troppo basso, l’identità viene marchiata come pessima, e sarà filtrata via nei forum, nelle aree di conversazione, nei canali, ecc.</p></body></html> - + Overall: Complessivo: - + Anonymous Anonimo @@ -12529,24 +11682,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you Questa identità ti appartiene - - + + My own identities Le mie identità - - + + My contacts Contatti - + Show Items @@ -12561,7 +11714,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -12571,7 +11729,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -12646,7 +11804,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: ID dell'identità: @@ -12676,7 +11834,7 @@ p, li { white-space: pre-wrap; } sconosciuto - + Invited @@ -12691,7 +11849,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle Modifica Circolo @@ -12739,7 +11897,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -12747,7 +11905,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -12790,7 +11948,7 @@ These identities will soon be not supported anymore. Identità anonima - + Boards @@ -12870,7 +12028,7 @@ These identities will soon be not supported anymore. - + information @@ -12886,17 +12044,12 @@ These identities will soon be not supported anymore. - + Banned Bloccato - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive positivo @@ -12945,10 +12098,6 @@ These identities will soon be not supported anymore. Chat Chat - - Unknown - Sconosciuto - [Unknown] @@ -13005,7 +12154,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -13055,21 +12204,21 @@ These identities will soon be not supported anymore. Ciao,<br>vorrei essere tuo amico sul network RetroShare.<br> - - - + + + People Persone - + Your Avatar Click here to change your avatar Il Tuo Avatar - + Linked to neighbor nodes Collegato a nodi adiacenti @@ -13079,7 +12228,7 @@ These identities will soon be not supported anymore. Collegato a nodi distanti - + Linked to a friend Retroshare node Collegato a un nodo RetroShare tuo amico @@ -13094,7 +12243,7 @@ These identities will soon be not supported anymore. Collegato a un nodo RetroShare sconosciuto - + Chat with this person Conversa con questa persona @@ -13109,12 +12258,12 @@ These identities will soon be not supported anymore. Conversazione a distanza con questa persona: rifiutata. - + Last used: Ultimo utilizzo: - + +50 Known PGP +50 PGP Conosciuta @@ -13134,12 +12283,12 @@ These identities will soon be not supported anymore. Vuoi davvero eliminare questa identità? - + Owned by Appartenente a - + Node name: Nome nodo: @@ -13149,7 +12298,7 @@ These identities will soon be not supported anymore. ID Nodo : - + Really delete? Cancellare davvero? @@ -13157,7 +12306,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname Soprannome @@ -13187,7 +12336,7 @@ These identities will soon be not supported anymore. Pseudonimo - + Import image @@ -13197,12 +12346,19 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. + + + No Avatar chosen. A default image will be automatically displayed from your new identity. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity Nuova identità @@ -13216,7 +12372,7 @@ These identities will soon be not supported anymore. - + @@ -13226,7 +12382,12 @@ These identities will soon be not supported anymore. N/D - + + No avatar chosen + + + + Edit identity Modifica Identità @@ -13237,27 +12398,27 @@ These identities will soon be not supported anymore. Aggiorna - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -13277,7 +12438,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -13287,11 +12448,7 @@ These identities will soon be not supported anymore. - Error getting key! - Errore ricevendo la chiave! - - - + Error KeyID invalid Errore KeyId non valido @@ -13306,7 +12463,7 @@ These identities will soon be not supported anymore. Nome reale sconosciuto - + Create New Identity Crea Nuova Identità @@ -13316,10 +12473,15 @@ These identities will soon be not supported anymore. Tipo - + Choose image... + + + Remove + Rimuovi + @@ -13345,7 +12507,7 @@ These identities will soon be not supported anymore. Aggiungi - + Create Crea @@ -13355,17 +12517,13 @@ These identities will soon be not supported anymore. Annulla - + Your Avatar Click here to change your avatar Il Tuo Avatar - Set Avatar - Imposta Avatar - - - + Linked to your profile Collegato al tuo profilo @@ -13375,7 +12533,7 @@ These identities will soon be not supported anymore. Puoi avere una o più identità. Vengono impiegate quando scrivi nelle aree di discussione, sui forum e per i commenti nei canali. Fungono da destinazione per le conversazioni a distanza e per il sistema postale a distanza di RetroShare. - + The nickname is too short. Please input at least %1 characters. Nickname troppo corto. Inserisci almeno %1 caratteri. @@ -13434,10 +12592,6 @@ These identities will soon be not supported anymore. PGP name: Nome PGP: - - GXS id: - id GXS: - PGP id: @@ -13453,7 +12607,7 @@ These identities will soon be not supported anymore. - + Copy Copia @@ -13463,12 +12617,12 @@ These identities will soon be not supported anymore. Rimuovi - + %1 's Message History - + Mark all Contrassegna tutto @@ -13487,26 +12641,38 @@ These identities will soon be not supported anymore. Quote Cita - - Send - Invia - ImageUtil - - + + Save image Salva immagine - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -13524,27 +12690,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: Porta: - + Listen Address: - + + Status: + Stato: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -13565,7 +12736,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -13574,26 +12750,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File Aprire file - + Open Folder Apri cartella - + Checking... Verifica... @@ -13603,7 +12784,7 @@ These identities will soon be not supported anymore. Verifica file - + Recommend in a message to... @@ -13631,7 +12812,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend Aggiungi amico @@ -13647,7 +12828,8 @@ These identities will soon be not supported anymore. - + + Options Opzioni @@ -13668,7 +12850,7 @@ These identities will soon be not supported anymore. - + Quit Esci @@ -13679,12 +12861,12 @@ These identities will soon be not supported anymore. Auto configuratore rapido - + RetroShare %1 a secure decentralized communication platform RetroShare %1 una piattaforma di comunicazione sicura decentralizzata - + Unfinished Non finito @@ -13711,11 +12893,12 @@ Libera un po' di spazio e clicca OK. + Status Stato - + Notify Notifica @@ -13726,31 +12909,35 @@ Libera un po' di spazio e clicca OK. + Open Messages Apri messaggi - + + Bandwidth Graph Grafico banda passante - + Applications Applicazioni + Help Aiuto - + + Minimize Riduci - + Maximize Ingrandisci @@ -13765,7 +12952,12 @@ Libera un po' di spazio e clicca OK. RetroShare - + + Close window + + + + %1 new message %1 nuovo messaggio @@ -13795,7 +12987,7 @@ Libera un po' di spazio e clicca OK. amici connessi %1 - + Do you really want to exit RetroShare ? Vuoi davvero uscire da RetroShare? @@ -13815,7 +13007,7 @@ Libera un po' di spazio e clicca OK. Mostra - + Make sure this link has not been forged to drag you to a malicious website. Accertati che questo link non sia stato creato per condurti a siti malevoli. @@ -13860,12 +13052,13 @@ Libera un po' di spazio e clicca OK. Matrice dei permessi sui servizi - + + Statistics Statistiche - + Show web interface Mostra interfaccia web @@ -13880,7 +13073,7 @@ Libera un po' di spazio e clicca OK. - + Really quit ? Uscire davvero? @@ -13889,17 +13082,17 @@ Libera un po' di spazio e clicca OK. MessageComposer - + Compose Componi - + Contacts Contatti - + Paragraph Paragrafo @@ -13935,12 +13128,12 @@ Libera un po' di spazio e clicca OK. Titolo 6 - + Font size Dimensione carattere - + Increase font size Ingrandisci carattere @@ -13955,32 +13148,32 @@ Libera un po' di spazio e clicca OK. Grassetto - + Italic Corsivo - + Alignment Allinemento - + Add an Image Aggiungere un'immagine - + Sets text font to code style Predefinisci il carattere di testo con stile di codice - + Underline Sottolinea - + Subject: Oggetto: @@ -13991,32 +13184,32 @@ Libera un po' di spazio e clicca OK. - + Tags Etichette - + Address list: - + Recommend this friend - + Set Text color Imposta colore del testo - + Set Text background color Imposta colore di sfondo del testo - + Recommended Files Files raccomandati @@ -14086,7 +13279,7 @@ Libera un po' di spazio e clicca OK. Aggiungi citazione - + Send To: Invia a: @@ -14121,7 +13314,7 @@ Libera un po' di spazio e clicca OK. Contatti - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> Ciao, <br>ti raccomando un mio buon amico; ci si può fidare di lui quanto di me. <br> @@ -14141,19 +13334,19 @@ Libera un po' di spazio e clicca OK. vuole essere amico con te su RetroShare - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team Hi %1,<br><br>%2 vuole esserti amico su RetroShare.<br><br>Rispondi ora:<br>%3<br><br>Grazie,<br>Il Team RetroShare - - + + Save Message Salva messaggio - + Message has not been Sent. Do you want to save message to draft box? Messaggio non inviato @@ -14165,7 +13358,17 @@ Vuoi salvarlo nelle bozze? Incolla collegamento RetroShare - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" Aggiungi in "A:" @@ -14185,7 +13388,7 @@ Vuoi salvarlo nelle bozze? Aggiungi come raccomandato - + Original Message Messaggio Originale @@ -14195,21 +13398,21 @@ Vuoi salvarlo nelle bozze? Da - + - + To A - - + + Cc CC - + Sent Inviato @@ -14224,7 +13427,7 @@ Vuoi salvarlo nelle bozze? Su %1, %2 scrive: - + Re: Re: @@ -14234,30 +13437,30 @@ Vuoi salvarlo nelle bozze? Inoltra: - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? Invio messaggio senza oggetto? - + Please insert at least one recipient. Inserisci almeno un destinatario. - + Bcc BCC - + Unknown Scononsciuto @@ -14372,13 +13575,13 @@ Vuoi salvarlo nelle bozze? Dettagli - + Open File... Apri file ... - + HTML-Files (*.htm *.html);;All Files (*) HTML-Files (*.htm *.html);;Tutti Files (*) @@ -14398,7 +13601,7 @@ Vuoi salvarlo nelle bozze? Esporta PDF - + Message has not been Sent. Do you want to save message ? Messaggio non inviato. @@ -14420,7 +13623,7 @@ Vuoi salvarlo? Aggiungi File Extra - + Hi,<br>I want to be friends with you on RetroShare.<br> Ciao,<br>vorrei essere tuo amico sul network RetroShare.<br> @@ -14444,28 +13647,24 @@ Vuoi salvarlo? Warning: This message is too big of %1 characters after HTML conversion. - - You have a friend invite - Hai una richiesta di amicizia - Respond now: Rispondi subito: - - + + Close Chiudi - + From: Da: - + Friend Nodes Nodi Amici @@ -14510,13 +13709,13 @@ Vuoi salvarlo? Elenco ordinato (romani maiuscolo) - - + + Thanks, <br> Grazie, <br> - + Distant identity: Identità distante: @@ -14526,12 +13725,12 @@ Vuoi salvarlo? [Mancante] - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. Devi crearti un’identità per firmare i messaggi a distanza, altrimenti rimuovi i contatti a distanza dalla lista di destinazione. - + Node name & id: Nome & ID nodo: @@ -14609,7 +13808,7 @@ Vuoi salvarlo? Predefinito - + A new tab Una nuova cartella @@ -14619,7 +13818,7 @@ Vuoi salvarlo? Una nuova finestra - + Edit Tag Modifica etichetta @@ -14642,7 +13841,7 @@ Vuoi salvarlo? MessageToaster - + Sub: Sotto: @@ -14650,7 +13849,7 @@ Vuoi salvarlo? MessageUserNotify - + Message Messaggio @@ -14678,7 +13877,7 @@ Vuoi salvarlo? MessageWidget - + Recommended Files Files raccomandati @@ -14688,37 +13887,37 @@ Vuoi salvarlo? Scarica tutti i files raccomandati - + Subject: Oggetto: - + From: Da: - + To: A: - + Cc: Copia a: - + Bcc: Bcc: - + Tags: Etichette: - + Reply Rispondi @@ -14758,7 +13957,7 @@ Vuoi salvarlo? - + Send Invite Manda invito @@ -14810,7 +14009,7 @@ Vuoi salvarlo? - + Confirm %1 as friend Conferma %1 come amico @@ -14820,12 +14019,12 @@ Vuoi salvarlo? Aggiungi %1 come amico - + View source - + No subject Nessun oggetto @@ -14835,17 +14034,22 @@ Vuoi salvarlo? Scarica - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -14854,14 +14058,24 @@ Vuoi salvarlo? %1 (%2) + + + Show less + + + + + Show more + + - + Download all Scarica tutto - + Print Document Stampa Documento @@ -14876,12 +14090,12 @@ Vuoi salvarlo? HTML-Files (*.htm *.html);;Tutti Files (*) - + Load images always for this message Carica sempre le immagini per questo messaggio - + Hide the attachment pane Nascondi pannello allegati @@ -14903,42 +14117,6 @@ Vuoi salvarlo? Compose Compose - - Reply to selected message - Rispondi al messaggio selezionato - - - Reply - Rispondi - - - Reply all to selected message - Rispondi a tutti i messaggi - - - Reply all - Rispondi a tutti - - - Forward selected message - Inoltra messaggio selezionato - - - Forward - Avanti - - - Remove selected message - Rimuovi messaggio selezionato - - - Delete - Cancella - - - Print selected message - Stampa messaggio selzionato - Print @@ -15017,7 +14195,7 @@ Vuoi salvarlo? MessagesDialog - + New Message Nuovo messaggio @@ -15027,60 +14205,16 @@ Vuoi salvarlo? Componi - Reply to selected message - Rispondi al messaggio selezionato - - - Reply - Rispondi - - - Reply all to selected message - Rispondi a tutti i messaggi - - - Reply all - Rispondi a tutti - - - Forward selected message - Inoltra messaggio selezionato - - - Foward - Inoltra: - - - Remove selected message - Rimuovi messaggio selezionato - - - Delete - Cancella - - - Print selected message - Stampa messaggio selzionato - - - Print - Stampa - - - Display - Mostra - - - + - - + + Tags Etichette - - + + Inbox Casella di posta: @@ -15110,21 +14244,17 @@ Vuoi salvarlo? Cestino - + Total Inbox: Totale ricezione: - Folders - Cartelle - - - + Quick View Panoramica - + Print... Stampa... @@ -15134,26 +14264,6 @@ Vuoi salvarlo? Print Preview Anteprima stampa - - Buttons Icon Only - Solo icone bottoni - - - Buttons Text Beside Icon - Testo bottoni accanto alle icone - - - Buttons with Text - Bottoni con testo - - - Buttons Text Under Icon - Testo bottoni sotto le icone - - - Set Text Under Icon - Predisponi testo sotto icone - Save As... @@ -15175,7 +14285,7 @@ Vuoi salvarlo? Inoltra messaggio - + Subject Oggetto @@ -15185,7 +14295,7 @@ Vuoi salvarlo? Da - + Date Data @@ -15195,39 +14305,7 @@ Vuoi salvarlo? Contenuti - Click to sort by attachments - Clicca per ordinare per allegato - - - Click to sort by subject - Clicca per ordinare per oggetto - - - Click to sort by read - Clicca per ordinare per lettura - - - Click to sort by from - Clicca per ordinare per mittente - - - Click to sort by date - Clicca per ordinare per data - - - Click to sort by tags - Clicca per ordinare per etichetta - - - Click to sort by star - Clicca per ordinare per evidenziatura - - - Forward selected Message - Inoltra messaggio selezionato - - - + Search Subject Oggetto ricerca @@ -15237,6 +14315,11 @@ ricerca Search From Ricerca da + + + Search To + + Search Date @@ -15263,14 +14346,14 @@ ricerca Ricerca allegati - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messaggi</h1> <p>RetroShare ha un suo sistema postale email interno. Puoi inviare/ricevere email a/da nodi amici a cui sei connesso.</p> <p>È altresì possibile inviare messaggi alle Identità altrui utilizzando il sistema di instradazione globale. Questi messaggi sono sempre crittografati e firmati, e vengono reinstradati da nodi intermedi finché non raggiungono la destinazione finale.</p> <p>I messaggi a distanza rimangono nella tua Casella in Uscita fin quando non ricevono una ricevuta di confermata consegna.</p> <p>Generalmente, puoi utilizzare i messaggi per raccomandare file ai tuoi amici, incollandovi i link ai file, o per raccomandare nodi amici ad altri nodi amici, al fine di irrobustire la tua rete, o per inviare un feedback al titolare di un canale.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + - + Starred - Evidenziato + @@ -15344,7 +14427,7 @@ ricerca - Show author in People + Show in People @@ -15358,7 +14441,7 @@ ricerca - + No message using %1 tag available. @@ -15373,34 +14456,33 @@ ricerca - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts Bozze - + No Box selected. - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - Messaggi speciali non disponibili. I contrassegni (star) consentono di dare ai messaggi uno status speciale per renderli più facili da trovare. Per contrassegnare un messaggio, fare clic sulla stella grigia accanto a un qualsiasi messaggio. - - - No system messages available. - Nessun messaggio sistema. - - + To - A + A - Click to sort by to - Clicca per ordinare per - - - + @@ -15408,26 +14490,6 @@ ricerca Total: Totale: - - Messages - Messaggi - - - Click to sort by signature - Clicca per ordinare per firma - - - This message was signed and the signature checks - Questo messaggio è stato firmato, e la firma corrisponde - - - This message was signed but the signature doesn't check - Questo messaggio è stato firmato, ma la firma non corrisponde - - - This message comes from a distant person. - Questo messaggio proviene da una persona distante - Mail @@ -15455,7 +14517,17 @@ ricerca MimeTextEdit - + + Save image + Salva immagine + + + + Copy image + + + + Paste as plain text Incolla come testo non formattato @@ -15509,7 +14581,7 @@ ricerca - + Expand Allarga @@ -15519,7 +14591,7 @@ ricerca Rimuovi elemento - + from Da @@ -15554,7 +14626,7 @@ ricerca Messaggio in attesa - + Hide Nascondi @@ -15695,7 +14767,7 @@ ricerca ID contatto - + Remove unused keys... Rimuovi chiavi non usate... @@ -15705,7 +14777,7 @@ ricerca - + Clean keyring Pulisci il portachiavi @@ -15723,7 +14795,13 @@ Nota: Il tuo vecchio portachiavi sarà salvato. La rimozione potrebbe fallire quando istanze multiple di Retroshare sono in esecuzione sulla stessa macchina. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info Informazioni sul Portachiavi @@ -15759,18 +14837,13 @@ Per sicurezza, il tuo portachiavi è stato precedentemente salvato su di un file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. Inconsistenza nei dati nel portachiavi. Questo è molto probabilmente un bug. Per favore contatta gli sviluppatori. - - - Export/create a new node - Esporta/crea un nuovo nodo - Trusted keys only Solo chiavi fidate - + Search name Cerca nome @@ -15780,12 +14853,12 @@ Per sicurezza, il tuo portachiavi è stato precedentemente salvato su di un file Ricerca ID contatto - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -15794,13 +14867,6 @@ Reported error: Errore riportato: - - NetworkPage - - Network - Rete - - NetworkView @@ -15827,7 +14893,7 @@ Errore riportato: NewFriendList - + Offline Friends @@ -15848,7 +14914,7 @@ Errore riportato: - + Groups Gruppi @@ -15878,19 +14944,19 @@ Errore riportato: Esporta il tuo elenco amici, inclusi i gruppi - - + + Search - + ID ID - + Search ID @@ -15900,12 +14966,12 @@ Errore riportato: - + Show Items - + Last contact @@ -15915,7 +14981,7 @@ Errore riportato: IP - + Group Gruppo @@ -16030,7 +15096,7 @@ Errore riportato: - + Do you want to remove this node? Vuoi rimuovere questo nodo? @@ -16040,7 +15106,7 @@ Errore riportato: Vuoi rimuovere questo amico? - + Done! Fatto! @@ -16154,7 +15220,7 @@ uno o più peer non sono stati aggiunti ad un gruppo NewsFeed - + Activity Stream @@ -16169,11 +15235,7 @@ uno o più peer non sono stati aggiunti ad un gruppo Rimuovi tutto - This is a test. - Questo è un test. - - - + Newest on top Più recenti in cima @@ -16183,12 +15245,12 @@ uno o più peer non sono stati aggiunti ad un gruppo Più vecchi in cima - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -16243,10 +15305,6 @@ uno o più peer non sono stati aggiunti ad un gruppo Blogs Blogs - - Security - Sicurezza - @@ -16268,10 +15326,6 @@ uno o più peer non sono stati aggiunti ad un gruppo Message Messaggio - - Connect attempt - Tentativo connessione - @@ -16298,10 +15352,6 @@ uno o più peer non sono stati aggiunti ad un gruppo Circles Circoli - - Links - Link - Mails @@ -16430,24 +15480,16 @@ uno o più peer non sono stati aggiunti ad un gruppo Disable All Toaster temporarily Disabilita temporaneamente tutte le notifiche del Toaster - - Feed - Dispaccio - Systray Riquadro sistema - - Count all unread messages - Conta tutti i messaggi non letti - NotifyQt - + Passphrase required @@ -16467,12 +15509,12 @@ uno o più peer non sono stati aggiunti ad un gruppo Password errata ! - + Please enter your Retroshare passphrase - + Unregistered plugin/executable Plugin/eseguibile non registrato @@ -16487,19 +15529,7 @@ uno o più peer non sono stati aggiunti ad un gruppo Per favore controlla l'orologio di sistema. - Examining shared files... - Esame files condivisi... - - - Hashing file - Calcolando l' hash del file - - - Saving file index... - Salvataggio indice file... - - - + Test Test @@ -16510,17 +15540,19 @@ uno o più peer non sono stati aggiunti ad un gruppo + Unknown title Titolo sconosciuto - + + Encrypted message Messaggio criptato - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). Perché le aree di discussione funzionino correttamente, l'orario del tuo computer deve essere corretto. Per favore controlla che questo sia il tuo caso (Una probabile differenza di diversi minuti è stata rilevata con i tuoi amici). @@ -16528,7 +15560,7 @@ uno o più peer non sono stati aggiunti ad un gruppo OnlineToaster - + Friend Online Amico online @@ -16580,10 +15612,6 @@ Basso Traffico: 10% di traffico standard e TODO: sospende tutti i trasferimenti PGPKeyDialog - - Dialog - Dialogo - Profile info @@ -16649,10 +15677,6 @@ Basso Traffico: 10% di traffico standard e TODO: sospende tutti i trasferimenti This profile has signed your own profile key - - Key signatures : - Firme chiave : - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> @@ -16678,23 +15702,20 @@ p, li { white-space: pre-wrap; } Chiave PGP - - These options apply to all nodes of the profile: + + Friend options - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> - <html><head/><body><p><span style=" font-size:10pt;">Firmare la chiave di un amico è un modo di esprimergli la tua fiducia davanti agli altri amici. Li aiuta a decidere quando accettare connessioni basate su quella chiave, fidandosi di te. Firmare una chiave è assolutamente facoltativo e la firma non si può revocare, quindi scegli saggiamente quando farlo.</span></p></body></html> + + These options apply to all nodes of the profile: + Keysigning: - - Sign PGP key - Firma Chiave PGP - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -16731,12 +15752,7 @@ p, li { white-space: pre-wrap; } Includi firme - - Options - Opzioni - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> <html><head/><body><p align="justify">Retroshare cerca periodicamente, nelle liste dei tuoi amici, files corrispondenti ai tuoi trasferimenti, così da poter stabilire dei trasferimenti diretti. In questo caso, il tuo amico saprà che tu stai scaricando uno dei suoi files.</p><p align="justify">Per prevenire questo comportamento solo per questo amico, deseleziona questa opzione. Puoi comunque effettuare un trasferimento diretto se lo richiedi esplicitamente, ad es. scaricando qualcosa dalla lista di files del tuo amico. Questa impostazione è applicata a tutte le locazioni dello stesso nodo.</p></body></html> @@ -16750,10 +15766,6 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this profile (e.g. when the message author is a signed identity that belongs to this profile). This can be used for instance to send files between your own nodes.</p></body></html> - - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> - <html><head/><body><p>Questa opzione ti permette di scaricare automaticamente un file raccomandato in un qualche messaggio arrivato da questo nodo. Può essere utile, ad esempio, per inviare files tra i tuoi nodi. L'opzione viene applicata a tutte le locazioni dello stesso nodo.</p></body></html> - Auto-download recommended files from this node @@ -16786,21 +15798,21 @@ p, li { white-space: pre-wrap; } kB/s - - + + RetroShare RetroShare - - + + Error : cannot get peer details. Errore: impossibile ottenere dettagli contatto - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) L'algoritmo a chiave fornito non è supportato da RetroShare (chiavi RSA solo sono supportate al momento) @@ -16818,7 +15830,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. Il livello di fiducia è un modo per esprimere la fiducia che riponi in questa chiave. Non viene utilizzato dal programma, né viene condiviso, ma può esserti utile a ricordare le chiavi buone e quelle cattive. @@ -16887,10 +15899,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Check the password! - - Maybe password is wrong - Forse la password è sbagliata - You haven't set a trust level for this key. @@ -16898,12 +15906,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile Profilo Retroshare - + This is your own PGP key, and it is signed by : Questa è la tua chiave PGP, ed è firmata da : @@ -16929,7 +15937,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat Conversazione @@ -16950,7 +15958,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Rimuovi elemento - + Name: Nome: @@ -16990,7 +15998,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message Scrivi messaggio @@ -17004,10 +16012,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Friend Connected Amico connesso - - Connect Attempt - Tentativo connessione - Connection refused by peer @@ -17044,11 +16048,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. Unknown - - - - Unknown Peer - Contatto sconosciuto + Scononsciuto @@ -17056,7 +16056,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Nascondi - + Send Message Invia Messaggio @@ -17223,13 +16223,6 @@ Warning: In your File-Transfer option, you select allow direct download to No. - - PhotoCommentItem - - Form - Modulo - - PhotoDialog @@ -17237,23 +16230,11 @@ Warning: In your File-Transfer option, you select allow direct download to No.PhotoShare Sondivisione Foto - - Photo - Foto - TextLabel Etichetta Testo - - Comment - Commento - - - Summary - Riassunto - Album / Photo Name @@ -17314,14 +16295,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.... ... - - Add Comment - Aggiungi un commento - - - Write a comment... - Scrivi un commento... - Album @@ -17388,10 +16361,6 @@ p, li { white-space: pre-wrap; } Create Album Creare Album - - View Album - Vista Album - Edit Album Details @@ -17413,17 +16382,17 @@ p, li { white-space: pre-wrap; } Proiezione - + My Albums Miei album - + Subscribed Albums Album Sottoscritti - + Shared Albums Album condivisi @@ -17452,7 +16421,7 @@ requesting to edit it! PhotoSlideShow - + Album Name Nome album @@ -17511,19 +16480,19 @@ requesting to edit it! - - + + TextLabel - + Posted by - + ago @@ -17559,12 +16528,12 @@ requesting to edit it! PluginItem - + TextLabel EtichettaTesto - + Show more details about this plugin Visualizza ulteriori dettagli su questo plugin @@ -17710,59 +16679,6 @@ Altro... Plugin look-up directories Cartella scorcio moduli aggiuntivi - - Plugin disabled. Click the enable button and restart Retroshare - Plugin disattivato. Cliccare il bottone "attiva" e riavviare RetroShare. - - - [disabled] - [disattivato] - - - No API number supplied. Please read plugin development manual. - Nessun numero di API in dotazione. Si prega di leggere manuale di sviluppo plugin. - - - [loading problem] - [problema di caricamento] - - - No SVN number supplied. Please read plugin development manual. - Nessun numero SVN in dotazione. Si prega di leggere manuale di sviluppo plugin. - - - Loading error. - Errore caricamento. - - - Missing symbol. Wrong version? - Simbolo errato. Versione sbagliata? - - - No plugin object - Nessun oggetto modulo aggiuntivo - - - Plugins is loaded. - Modulo aggiuntivo caricato. - - - Unknown status. - Stato sconosciuto. - - - Check this for developing plugins. They will not -be checked for the hash. However, in normal -times, checking the hash protects you from -malicious behavior of crafted plugins. - Abilita se stai sviluppando dei plugins. -Su di essi non verrà effettuato il controllo dell'hash. -Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin contraffatti. - - - <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Plugins</h1> <p>Plugins are loaded from the directories listed in the bottom list.</p> <p>For security reasons, accepted plugins load automatically until the main Retroshare executable or the plugin library changes. In such a case, the user needs to confirm them again. After the program is started, you can enable a plugin manually by clicking on the "Enable" button and then restart Retroshare.</p> <p>If you want to develop your own plugins, contact the developpers team they will be happy to help you out!</p> - <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;I Plugin</h1> <p>I plugins vengono caricati dalle cartelle elencate nella lista sottostante.</p><p>Per motivi di sicurezza, i plugin accettati vengono caricati automaticamente fino a quando non vengono modificati l'eseguibile principale di RetroShare o la libreria dei plugin. In tal caso, l'utente dovrà riconfermarli. Dopo l'avvio del programma, puoi abilitare manualmente un plugin cliccando sul bottone "Abilita" e riavviando RetroShare.</p> <p>Se vuoi sviluppare un tuo plugin, contatta il team degli sviluppatori, saranno felici di aiutarti!</p> - Plugins @@ -17832,12 +16748,27 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Disponi finestra in cima - + + Ban this person (Sets negative opinion) + Banna persona (esprimi ufficialmente parere negativo) + + + + Give neutral opinion + Esprimi parere neutro + + + + Give positive opinion + Esprimi parere positivo + + + Choose window color... - + Dock window @@ -17871,14 +16802,6 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Close conversation? - - Closing this window will end the conversation, notify the peer and remove the encrypted tunnel. - Chiudere questa finestra terminerà la conversazione, verrà notificato all'altro peer e rimuoverà il tunnel cifrato. - - - Kill the tunnel? - Terminare il tunnel? - PostedCardView @@ -17898,7 +16821,7 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Nuovo - + Vote up Vota per @@ -17918,8 +16841,8 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin \/ - - + + Comments Commenti @@ -17944,13 +16867,13 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin - - + + Comment Commento - + Comments @@ -17978,20 +16901,12 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin PostedCreatePostDialog - Signed by: - Firmato da: - - - Notes - Note - - - + Create a new Post - + RetroShare RetroShare @@ -18006,12 +16921,22 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File Carica un file immagine - + Post image @@ -18027,7 +16952,17 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -18037,23 +16972,7 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin - Submit Post - Inviare Post - - - You are submitting a link. The key to a successful submission is interesting content and a descriptive title. - Stai proponendo un link. La chiave per una proposizione di successo è: contenuti interessanti, e un titolo descrittivo. - - - Submit - Invia - - - Submit a new Post - Invia un nuovo Post - - - + Please add a Title Aggiungi un Titolo @@ -18073,12 +16992,22 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -18093,7 +17022,7 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Pubblica come - + Post @@ -18104,7 +17033,7 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Immagine - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -18114,7 +17043,7 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Titolo - + Link Collegamento @@ -18122,40 +17051,12 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin PostedDialog - Posted Links - Link Postato - - - Create Topic - Crea Argomento - - - My Topics - Miei argomenti - - - Subscribed Topics - Argomenti sottoscritti - - - Popular Topics - Argomenti popolari - - - Other Topics - Altri argomenti - - - Links - Link - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -18189,31 +17090,7 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin PostedGroupDialog - Posted Topic - Argomento inviato - - - Add Topic Admins - Aggiungi Amministratore degli Argomenti - - - Select Topic Admins - Seleziona Amministratore degli Argomenti - - - Create New Topic - Crea Nuovo Argomento - - - Edit Topic - Modifica Argomento - - - Update Topic - Aggiorna Argomento - - - + Create New Board @@ -18251,7 +17128,17 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted @@ -18267,7 +17154,7 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin - + Expand Allarga @@ -18282,16 +17169,17 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin - Loading - Sto caricando... - - - + Loading... - + + Never + Mai + + + New Board @@ -18304,22 +17192,18 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin PostedItem - + 0 0 - Site - Sito - - - - + + Comments Commenti - + Copy RetroShare Link @@ -18330,12 +17214,12 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin - + Comment Commento - + Comments @@ -18345,7 +17229,7 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin <p><font color="#ff0000"><b>L’autore di questo messaggio (con ID %1) è bloccato.</b> - + Click to view Picture @@ -18355,21 +17239,17 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Nascondi - + Vote up Vota per - + Vote down Vota contro - \/ - \/ - - - + Set as read and remove item Definisci letto e rimuovi elemento @@ -18379,7 +17259,7 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Nuovo - + New Comment: Nuovo commento: @@ -18389,7 +17269,7 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin - + Name Nome @@ -18430,77 +17310,10 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin - + Loading Sto caricando... - - By - Da - - - - PostedListWidget - - Form - Modulo - - - Hot - Scottante - - - New - Nuovo - - - Top - In alto - - - Today - Oggi - - - Yesterday - Ieri - - - This Week - Questa settimana - - - This Month - Questo mese - - - This Year - Quest'anno - - - Submit a new Post - Invia un nuovo Post - - - Next - Successivo - - - RetroShare - RetroShare - - - Please create or choose a Signing Id before Voting - Per favore crea o scegli un Id per firmare prima di votare - - - Previous - Precedente - - - 1-10 - 1-10 - PostedListWidgetWithModel @@ -18520,7 +17333,17 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -18530,15 +17353,15 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Amministratore: - + - + unknown sconosciuto - + Distribution: Distribuzione: @@ -18548,42 +17371,42 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts Post - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -18603,7 +17426,7 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Scottante - + Search @@ -18633,17 +17456,17 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -18658,12 +17481,17 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Vuoto - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -18673,27 +17501,31 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Modifica - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -18708,7 +17540,7 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Entra - + Never Mai @@ -18750,7 +17582,7 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Unknown - + Scononsciuto @@ -18782,6 +17614,16 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin No Channel Selected Nessun Canale Selezionato + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -18790,10 +17632,6 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Tabs Tabs - - Open each topic in a new tab - Apri ciascun argomento in una nuova scheda - Open each board in a new tab @@ -18807,10 +17645,6 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin PostedUserNotify - - Posted - Pubblicato - Board Post @@ -18879,16 +17713,16 @@ Per il normale utilizzo abilitare il controllo dell'hash ti protegge plugin Gestore Profilo - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -18998,7 +17832,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari ProfileWidget - + Edit status message Modificare il messaggio di stato @@ -19014,7 +17848,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari Gestore Profilo - + Public Information Informazioni pubbliche @@ -19049,12 +17883,12 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari in linea dal: - + Other Information Altre informazioni - + My Address Il mio indirizzo @@ -19098,51 +17932,27 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari PulseAddDialog - Post From: - Post da: - - - Account 1 - Conto 1 - - - Account 2 - Conto 2 - - - Account 3 - Conto 3 - - - + Add to Pulse Aggiungere al segnale - filter - filtro - - - URL Adder - Aggiunge URL - - - + Display As Visualizzare come - + URL URL - + GroupLabel - + IDLabel @@ -19152,12 +17962,12 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari Da: - + Head - + Head Shot @@ -19187,13 +17997,13 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari Negativo - - + + Whats happening? - + @@ -19205,12 +18015,22 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -19219,17 +18039,13 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari Cancel Annulla - - Post Pulse to Wire - Manda un segnale sul filo - Post - + Reply to Pulse @@ -19244,34 +18060,24 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - Da - - - Date - Data - - - ... - ... + + Load Picture File + Carica un file immagine @@ -19282,7 +18088,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari - + @@ -19301,7 +18107,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari PulseReply - + icn @@ -19311,7 +18117,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari - + REPLY @@ -19338,7 +18144,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari - + FOLLOW @@ -19348,7 +18154,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -19368,7 +18174,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -19484,7 +18290,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari - + FOLLOW @@ -19492,37 +18298,42 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -19554,7 +18365,7 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari - + FOLLOW @@ -19562,8 +18373,8 @@ Ora puoi copiarla su un altro computer e utilizzare il pulsante Importa per cari QObject - - + + Confirmation Conferma @@ -19833,12 +18644,12 @@ Caratteri <b>", |, \, &lt;&gt;,, *,?</b> saranno sostit Dettagli contatto - + File Request canceled Richiesta file cancellata - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. Questa versione di RetroShare usa OpenPGP-SDK. Come effetto collaterale, non utilizza il portachiavi PGP condiviso di sistema, ma ha il proprio portachiavi condiviso da tutte le istanze di RetroShare. <br><br>Non sembri avere un tale portachiavi, sebbene chiavi PGP siano menzionati da account RetroShare esistenti, probabilmente perché hai appena cambiato per questa nuova versione del software. @@ -19869,7 +18680,7 @@ Caratteri <b>", |, \, &lt;&gt;,, *,?</b> saranno sostit Errore inatteso. Riferisci "RsInit::InitRetroShare unexpected return code %1". - + Cannot start Tor Manager! @@ -19903,7 +18714,7 @@ The error reported is:" - + Multiple instances Istanze multiple @@ -19927,6 +18738,26 @@ Blocca file. Blocco del file: + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -20009,7 +18840,7 @@ L’errore segnalato è: Inoltro dati - + You appear to have nodes associated to DSA keys: Sembri avere nodi associati a chiavi DSA: @@ -20019,7 +18850,7 @@ L’errore segnalato è: Chiavi DSA non sono ancora supportate da questa versione di RetroShare. Tutti questi nodi saranno inutilizzabili. Siamo molto spiacenti per questo. - + enabled abilitato @@ -20029,7 +18860,7 @@ L’errore segnalato è: disabilitato - + Move IP %1 to whitelist Sposta l’IP %1 alla lista bianca @@ -20045,7 +18876,7 @@ L’errore segnalato è: - + %1 seconds ago %1 secondi fa @@ -20112,7 +18943,7 @@ Security: no anonymous IDs - + Join chat room @@ -20140,7 +18971,7 @@ Security: no anonymous IDs impossibile analizzare il file XML! - + Indefinitely @@ -20320,13 +19151,29 @@ Security: no anonymous IDs Ban list + + + Name + Nome + - Status + Node + Nodo + + + + Address + + Status + + + + NXS @@ -20397,7 +19244,7 @@ Security: no anonymous IDs Unknown - + Scononsciuto @@ -20519,10 +19366,6 @@ Security: no anonymous IDs Click to resume the hashing process - - <p>This certificate contains: - <p>Questo certificato contiene: - Idle @@ -20573,6 +19416,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -20735,7 +19590,7 @@ p, li { white-space: pre-wrap; } - + Network Wide Tutta la rete @@ -20918,7 +19773,7 @@ p, li { white-space: pre-wrap; } Modulo - + The loading of embedded images is blocked. Caricamento immagini bloccato @@ -20931,7 +19786,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default Concesso di default @@ -21104,12 +19959,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + Salva immagine + + + + Copy image + + + + Document source @@ -21117,12 +19982,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -21814,7 +20679,7 @@ Se ritieni sia corretto, rimuovi dal file la riga corrispondente e ri-aprilo con RsDownloadListModel - + Name i.e: file name Nome @@ -21929,13 +20794,13 @@ Se ritieni sia corretto, rimuovi dal file la riga corrispondente e ri-aprilo con Unknown - + Scononsciuto RsFriendListModel - + Name Nome @@ -21955,7 +20820,7 @@ Se ritieni sia corretto, rimuovi dal file la riga corrispondente e ri-aprilo con IP - + Profile ID @@ -22011,7 +20876,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] [ ... Messaggio Redatto ... ] @@ -22025,11 +20890,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - [ ... Messaggio Perso ... ] - RsMessageModel @@ -22043,6 +20903,11 @@ prevents the message to be forwarded to your friends. From Da + + + To + A + Subject @@ -22065,13 +20930,18 @@ prevents the message to be forwarded to your friends. - Click to sort by read - Clicca per ordinare per lettura + Click to sort by read status + - Click to sort by from - Clicca per ordinare per mittente + Click to sort by author + + + + + Click to sort by destination + @@ -22094,7 +20964,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -22115,7 +20987,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. Ripristina TUTTI i parametri Retroshare memorizzati @@ -22176,7 +21048,7 @@ prevents the message to be forwarded to your friends. Definisci lingua RetroShare - + Unable to open log file '%1': %2 Impossibile aprire file di LOG '%1': %2 @@ -22197,11 +21069,7 @@ prevents the message to be forwarded to your friends. Impossibile creare la cartella dati: %1 - Revision - Revisione - - - + opmode @@ -22231,7 +21099,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: Codice linguaggio incorretto: @@ -22249,7 +21117,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -22266,12 +21134,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) Immetti una chiave (di almeno 3 caratteri) - + Start Search Inizia ricerca @@ -22332,7 +21200,7 @@ prevents the message to be forwarded to your friends. Cancella - + KeyWords Parole Chiave @@ -22347,7 +21215,7 @@ prevents the message to be forwarded to your friends. Rierca ID - + Filename Nome File @@ -22447,23 +21315,23 @@ prevents the message to be forwarded to your friends. Scarica selezionati - + File Name Nome File - + Download Scarica - + Copy RetroShare Link Copia collegamento RetroShare - + Send RetroShare Link Invia collegamento RetroShare @@ -22473,7 +21341,7 @@ prevents the message to be forwarded to your friends. - + Download Notice Scarica Informativa @@ -22510,7 +21378,7 @@ prevents the message to be forwarded to your friends. Rimuovi tutto - + Folder Cartella @@ -22521,17 +21389,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) Nuovo collegamento(i) RetroShare - + Open Folder Apri cartella - + Create Collection... Crea Raccolta... @@ -22551,7 +21419,7 @@ prevents the message to be forwarded to your friends. Scarica da una raccolta di file... - + Collection Raccolta @@ -22559,7 +21427,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details Dettagli contatto @@ -22575,22 +21443,22 @@ prevents the message to be forwarded to your friends. Rimuovi Elemento - + IP address: Indirizzo IP: - + Peer ID: ID contatto: - + Location: Località: - + Peer Name: Nome contatto: @@ -22607,7 +21475,7 @@ prevents the message to be forwarded to your friends. Nascondi - + but reported: @@ -22632,8 +21500,8 @@ prevents the message to be forwarded to your friends. <p>Questo è l’IP a cui il tuo amico sostiene di essere connesso. Se avete appena cambiato gli IP, allora questo è un falso allarme. Altrimenti, significa che la tua connessione a questo amico è inoltrata da un peer intermedio, ed è una cosa sospetta.</p> - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> <html><head/><body><p>Questo avviso serve a proteggerti dagli attacchi tramite inoltro del traffico. In simili casi, l’amico a cui sei connesso non vedrà il tuo IP esterno, vedrà invece l’IP di chi esegue l’attacco.</p><p><br/></p><p>Però, se per qualche motivo avete appena cambiato gli IP (alcuni ISP ti cambiano l’IP a intervalli regolari), allora questo avviso ti sta solo dicendo che un amico si è connesso al tuo nuovo IP prima che RetroShare si sia accorto che l’IP è cambiato. In questo caso, non c’è nulla che non vada.</p><p><br/></p><p>Puoi facilmente evitare falsi allarmi mettendo in lista bianca i tuoi indirizzi IP (p.es. l’intervallo dei tuoi IP), o disabilitando del tutto questi avvisi in Opzioni-&gt;Notifica-&gt;News Feed.</p></body></html> @@ -22641,7 +21509,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare vuole essere amico con te su RetroShare @@ -22672,7 +21540,7 @@ prevents the message to be forwarded to your friends. - + Expand Allarga @@ -22717,12 +21585,12 @@ prevents the message to be forwarded to your friends. Stato: - + Write Message Scrivi messaggio - + Connect Attempt Tentativo Connessione @@ -22742,31 +21610,32 @@ prevents the message to be forwarded to your friends. Tentativi di connessione sconosciuto (uscente) - + Unknown Security Issue Evento di sicurezza sconosciuto - - A unknown peer + + SSL request - - Unknown + + An unknown peer + + + Unknown + Scononsciuto + Profile ID: - Unknown Peer - Contatto sconosciuto - - - + Hide Nascondi @@ -22776,7 +21645,7 @@ prevents the message to be forwarded to your friends. Vuoi rimuovere questo amico? - + Certificate has wrong signature!! This peer is not who he claims to be. Il Certificato ha una firma errata!! Questo contatto non è chi afferma di essere. @@ -22786,12 +21655,12 @@ prevents the message to be forwarded to your friends. Certificato Mancante/Danneggiato. Non è un vero utente RetroShare. - + Certificate caused an internal error. Il certificato ha causato un errore interno. - + Peer/node not in friendlist (PGP id= Peer/nodo non in lista-amici (PGP id= @@ -22850,12 +21719,12 @@ prevents the message to be forwarded to your friends. - + Local Address Indirizzo Locale - + NAT @@ -22876,22 +21745,22 @@ prevents the message to be forwarded to your friends. Porta: - + Local network Rete locale - + External ip address finder Rilevatore di indirizzo IP esterno - + UPnP UPnP - + Known / Previous IPs: IP conosciuti / precedenti: @@ -22904,21 +21773,16 @@ behind a firewall or a VPN. Se si deseleziona questo, RetroShare può determinare solo il tuo IP quando si connette a qualcuno. Lasciare questo selezionato, aiuta a connettersi quando si hanno pochi amici. Aiuta anche se sei dietro un firewall o una VPN. - - Allow RetroShare to ask my ip to these websites: - Permetti a RetroShare di chiedere il mio IP a questi siti: - - - - - + + + kB/s kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. L’intervallo di porte consentite va da 10 a 65535. In genere le porte al di sotto della 1024 sono riservate al sistema. @@ -22928,23 +21792,46 @@ behind a firewall or a VPN. L’intervallo di porte consentite va da 10 a 65535. In genere le porte al di sotto della 1024 sono riservate al sistema. - + Onion Address Indirizzo Onion - + Discovery On (recommended) Scoperta Attivata (raccomandato) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off Scoperta Disattivata @@ -22954,7 +21841,7 @@ behind a firewall or a VPN. Nascosto - Vedi Configurazione - + I2P Address Indirizzo I2P @@ -22979,37 +21866,95 @@ behind a firewall or a VPN. in entrata ok - - + + + Proxy seems to work. Il proxy sembra funzionare. - + + I2P proxy is not enabled proxy di I2P non abilitato - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -23024,71 +21969,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. sconosciuto - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -23098,22 +21979,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. Sei raggiungibile tramite servizio nascosto. @@ -23127,12 +21993,12 @@ I servizi sono tutti sù e ben funzionanti?? Controlla anche le tue porte! - + [Hidden mode] [Modalità Nascosta] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> <html><head/><body><p>Questo azzera la lista degli indirizzi noti. Questa azione è utile se per qualche ragione la tua lista di indirizzi contenesse un indirizzo non valido/irrilevante/scaduto che vorresti evitare di passare ai tuoi amici come indirizzo di contatto.</p></body></html> @@ -23142,7 +22008,7 @@ Controlla anche le tue porte! Cancella - + Download limit (KB/s) Limite scaricamento (KB/s) @@ -23157,23 +22023,23 @@ Controlla anche le tue porte! Limite caricamento (KB/s) - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> <html><head/><body><p>Il limite di upload copre l’intero software. Un limite di upload troppo piccolo potrebbe eventualmente bloccare i servizi a bassa priorità (forum, canali). Il valore minimo raccomandato è di 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -23184,17 +22050,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -23204,12 +22060,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -23219,17 +22070,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 127.0.0.1 - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -23269,7 +22110,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start Start @@ -23284,12 +22125,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why Stop - - BOB status - - - - + Incoming In arrivo @@ -23325,7 +22161,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay Relay @@ -23380,7 +22241,7 @@ If you have issues connecting over Tor check the Tor logs too. Totale: - + Warning: This bandwidth adds up to the max bandwidth. @@ -23405,7 +22266,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -23417,7 +22278,7 @@ If you have issues connecting over Tor check the Tor logs too. Rete - + IP Filters Filtro IP @@ -23440,7 +22301,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status Status @@ -23500,17 +22361,28 @@ If you have issues connecting over Tor check the Tor logs too. Aggiungi alla lista bianca - + Hidden Service Configuration Configurazione Servizio Nascosto - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -23526,18 +22398,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay I2P in uscita ok - + Service Address Indirizzo Servizio @@ -23572,12 +22444,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range Intervallo IP - + Reported by DHT for IP masquerading Segnalato dalla DHT per mascheramento IP @@ -23600,22 +22472,22 @@ If you have issues connecting over Tor check the Tor logs too. Aggiunto da te - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> <html><head/><body><p>Gli IP della lista bianca vengono ottenuti dalle seguenti fonti: IP provenienti da un certificato scambiato manualmente; gamme di IP inserite da te in questa finestra o negli elementi immessi nella sicurezza.</p><p>Il comportamento di default di RetroShare è di (1) autorizzare sempre la connessione ai peer il cui IP è nella lista bianca, anche se quell’IP appare anche nella lista nera; (2) opzionalmente richiede che gli IP siano nella lista bianca. Puoi modificare questo comportamento per ciascun contatto nella finestra &quot;Dettagli&quot; di ciascun nodo RetroShare. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> <html><head/><body><p>La DHT ti consente di rispondere a richieste di connessione dai tuoi amici che usano la DHT di BitTorrent. Migliora notevolmente la connettività. Nessuna informazione viene memorizzata nella DHT; viene impiegata solo come sistema di proxy per entrare in contatto con altri nodi di RetroShare.</p><p>Il servizio Discovery invia il nome del nodo e gli ID dei tuoi contatti fidati ai peers connessi, per aiutarli a scegliere nuovi amici. Però l’amicizia non è mai automatica, ed entrambi i peer dovranno pur sempre aggiudicarsi la fiducia a vicenda per consentire la connessione. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> <html><head/><body><p>Il punto diventa verde non appena RetroShare riesce ad ottenere il tuo IP dai siti elencati qui sotto, se hai abilitato l’operazione. RetroShare utilizzerà anche altri metodi per scoprire il tuo IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> <html><head/><body><p>Questa lista viene compilata automaticamente con informazioni reperite da molteplici fonti: i contatti mascherati segnalati dalla DHT; gli intervalli IP immessi da te; e gli intervalli IP segnalati dai tuoi amici. Le impostazioni di default dovrebbero proteggerti dal relaying del traffico su larga scala.</p><p>L'individuazione automatizzata degli IP mascherati potrebbe far finire in lista nera gli IP dei tuoi amici. In questo caso, usa il menù contestuale per metterli in lista bianca.</p></body></html> @@ -23650,7 +22522,7 @@ If you have issues connecting over Tor check the Tor logs too. Blocca automaticamente gli intervalli degli IP mascherati della DHT che iniziano da - + Outgoing Manual Tor/I2P @@ -23660,12 +22532,12 @@ If you have issues connecting over Tor check the Tor logs too. Tor Socks Proxy - + Tor outgoing Okay Tor in uscita ok - + Tor proxy is not enabled proxy di Tor non abilitato @@ -23745,7 +22617,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with verifica i contatti con cui vuoi condividere la chiave privata di pubblicazione @@ -23755,12 +22627,12 @@ If you have issues connecting over Tor check the Tor logs too. Condividi con amici - + Share Condividi - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. Puoi far sapere agli amici del tuo Canale condividendolo con loro. @@ -23780,7 +22652,7 @@ Seleziona gli Amici con cui vuoi Condividere il Canale. Gestore cartella condivisa - + Shared directory @@ -23800,17 +22672,17 @@ Seleziona gli Amici con cui vuoi Condividere il Canale. Visibilità - + Add new - + Cancel Annulla - + Add a Share Directory Aggiungi cartella condivisa @@ -23820,7 +22692,7 @@ Seleziona gli Amici con cui vuoi Condividere il Canale. Rimuovi - + Apply and close Applicare e chiudere @@ -23911,7 +22783,7 @@ Seleziona gli Amici con cui vuoi Condividere il Canale. Cartella non trovata o nome Cartella non accettato. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. Questo è un elenco delle cartelle condivise. Puoi aggiungere e rimuovere cartelle usando i bottoni in fondo. Quando aggiungi una nuova cartella, all’inizio tutti i file in essa contenuti vengono condivisi. Puoi impostare separatamente i parametri di condivisione per ciascuna cartella condivisa. @@ -23919,7 +22791,7 @@ Seleziona gli Amici con cui vuoi Condividere il Canale. SharedFilesDialog - + Files Files @@ -23970,11 +22842,16 @@ Seleziona gli Amici con cui vuoi Condividere il Canale. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files controllare i file - + Download selected Scarica selezionati @@ -23984,7 +22861,7 @@ Seleziona gli Amici con cui vuoi Condividere il Canale. Scarica - + Copy retroshare Links to Clipboard Copia negli Appunti Collegamenti RetroShare @@ -23999,7 +22876,7 @@ Seleziona gli Amici con cui vuoi Condividere il Canale. Invia collegamento RetroShare - + Some files have been omitted @@ -24015,7 +22892,7 @@ Seleziona gli Amici con cui vuoi Condividere il Canale. Raccomandazione(i) - + Create Collection... Crea Raccolta... @@ -24040,7 +22917,7 @@ Seleziona gli Amici con cui vuoi Condividere il Canale. Scarica da una raccolta di file... - + Some files have been omitted because they have not been indexed yet. @@ -24183,12 +23060,12 @@ Seleziona gli Amici con cui vuoi Condividere il Canale. SplashScreen - + Load configuration Carica configurazione - + Create interface Crea interfaccia @@ -24212,7 +23089,7 @@ Seleziona gli Amici con cui vuoi Condividere il Canale. Ricorda parola-chiave - + Log In Login @@ -24565,7 +23442,7 @@ Questa scelta può essere ripristinata in Impostazioni. Messaggio di stato - + Message: Messaggio: @@ -24810,7 +23687,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags Rimuovi tutte le etichette @@ -24846,14 +23723,17 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown - + Scononsciuto @@ -24861,18 +23741,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -24882,12 +23757,57 @@ p, li { white-space: pre-wrap; } - + + Error + Errore + + + + Not connected + Non connesso + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -24895,7 +23815,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -24905,7 +23825,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -24916,11 +23836,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -24948,7 +23869,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options Opzioni traferimento @@ -24959,7 +23880,7 @@ p, li { white-space: pre-wrap; } Massimo scaricamenti simultanei: - + Shared Directories @@ -24969,22 +23890,27 @@ p, li { white-space: pre-wrap; } Condividi automaticamente cartella ricezione (Raccomandato) - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) minuto(i) @@ -25069,7 +23995,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -25078,7 +24004,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -25103,7 +24034,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming Streaming @@ -25168,12 +24104,7 @@ p, li { white-space: pre-wrap; } Massimo numero di richieste di tunnel inoltrate per secondo: - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>costringe il trasferimento a richiedere chunk di file da 1MB in ordine crescente, facilitando l’anteprima durante lo scaricamento. <span style=" font-weight:600;">Random</span> è puramente casuale e favorisce lo swarming. <span style=" font-weight:600;">Progressivo</span> è un compromesso: seleziona il prossimo chunk casualmente entro un margine che non superi i 50MB di distanza dalla fine del file parziale. Questo consente una randomizzazione parziale ma al contempo previene lunghi tempi di inizializzazione per grossi file vuoti.</p></body></html> - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> <html><head/><body><p>RetroShare sospenderà tutti i trasferimenti ed il salvataggio del file di configurazione qualora lo spazio libero sul disco dovesse scendere al di sotto di questo limite. Su alcuni sistemi, questo previene la perdita di informazioni. Una finestra di popup ti avviserà quando questo accade.</p></body></html> @@ -25183,7 +24114,17 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Questo valore controlla quante richieste di tunnel al secondo può inoltrare il tuo contatto.</p><p>Se disponi di una connessione Internet a banda larga, può portarlo su fino a 30-40, consentendo così il passaggio di tunnel statisticamente più lunghi. Fai molta attenzione però: questo genererà molti pacchetti piccoli che possono rallentare notevolmente il tuo trasferimento di file.</p><p>Il valore predefinito è 20. Nel dubbio, lascialo così.</p></body></html> - + + Warning + Avvertimento + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -25211,7 +24152,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed Completato scaricamento @@ -25235,39 +24176,23 @@ p, li { white-space: pre-wrap; } %1 completed transfer - - You have %1 completed downloads - Hai scaricato il %1 - - - You have %1 completed download - Hai completato il %1 di scaricamento - - - %1 completed downloads - completato %1 scaricamenti - - - %1 completed download - completato %1 scaricamento - TransfersDialog - - + + Downloads Scaricamenti - + Uploads Caricamenti - + Name i.e: file name Nome @@ -25474,11 +24399,7 @@ p, li { white-space: pre-wrap; } Specifica... - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1> <p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p> <p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p> <p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Trasferimento File</h1> <p>RetroShare offre due modi per trasferie file: trasferimenti diretti dai tuoi amici, e trasferimenti a distanza anonimizzati con tunnel. Inoltre, il trasferimento file è multi-fonte e consente lo swarming (puoi essere una fonta mentre scarichi).</p> <p>Puoi condividere file usando l’icona <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> bekka barra laterale sinistra. Queste file verranno elencati nella finestrella "I Miei File". Per ciascun gruppo di amici, puoi stabilire se potranno vedere o meno questi file nella finestra "File degli Amici".</p> <p>La finestra di ricerca riporta i file nelle liste dei file dei tuoi amici, ed i file distanti che possono essere raggiunti anonimamente tramite il sistema di tunneling a multi-hop.</p> - - - + Move in Queue... Sposta in coda... @@ -25503,7 +24424,7 @@ p, li { white-space: pre-wrap; } Scegli la cartella - + Anonymous end-to-end encrypted tunnel 0x @@ -25524,7 +24445,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -25557,7 +24478,17 @@ p, li { white-space: pre-wrap; } File %1 non completato. Se file multimediale, provane un anteprima. - + + Warning + Avvertimento + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name Cambia il nome del file @@ -25572,7 +24503,7 @@ p, li { white-space: pre-wrap; } Per favore inserisci un nuovo--e valido--nome per il file - + Expand all Espandi tutto @@ -25699,23 +24630,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Colonne - + File Transfers Trasferimento file - + Path Tracciato @@ -25725,7 +24651,7 @@ p, li { white-space: pre-wrap; } Visualizza colonna dei Percorsi - + Could not delete preview file Impossibile eliminare il file anteprima @@ -25735,7 +24661,7 @@ p, li { white-space: pre-wrap; } Riprovare? - + Create Collection... Crea Raccolta... @@ -25750,7 +24676,12 @@ p, li { white-space: pre-wrap; } Guarda Raccolta... - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Collection Raccolta @@ -25760,7 +24691,7 @@ p, li { white-space: pre-wrap; } %1 tunnel - + Anonymous tunnel 0x Tunnel anonimo 0x @@ -25889,7 +24820,7 @@ p, li { white-space: pre-wrap; } Unknown Peer - + Contatto sconosciuto @@ -25981,10 +24912,6 @@ p, li { white-space: pre-wrap; } File transfer tunnels - - Anonymous tunnels - Tunnel anonimi - Authenticated tunnels @@ -26178,12 +25105,17 @@ p, li { white-space: pre-wrap; } Modulo - + Enable Retroshare WEB Interface Abilita l’Interfaccia Web di RetroShare - + + Status: + Stato: + + + Web parameters Parametri web @@ -26217,27 +25149,33 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Note: these settings do not affect retroshare-service, which has a command line switch to activate the web interface and select the listening port.</p></body></html> - - Port: - Porta: - Allow access from all IP addresses (Default: localhost only) - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Interfaccia Web</h1><p>L’Interfaccia Web ti consente di controllare RetroShare tramite browser. Più dispositivi possono condividere il controllo di un’istanza di RetroShare. Quindi, potresti avviare una conversazione su un tablet, per poi proseguirla su un PC da tavolo.</p> <p>Attenzione: non esporre l’Interfaccia Web all’Internet, dato che non dispone di alcun sistema di controllo dell’accesso, né di cifratura. Se vuoi usare l’Interfaccia Web tramite Internet, usa un tunnel SSH o un proxy verso una connessione sicura.</p> - + Webinterface not enabled Interfaccia Web non abilitata @@ -26247,12 +25185,12 @@ p, li { white-space: pre-wrap; } L’Interfaccia Web non è abilitata. Attivala in Impostazioni -> Interfaccia Web - + failed to start Webinterface Non so riuscito ad avviare l’Interfaccia Web - + Webinterface Interfaccia Web @@ -26389,11 +25327,7 @@ p, li { white-space: pre-wrap; } Pagine wiki - New Group - Nuovo gruppo - - - + Page Name Nome della Pagina @@ -26408,7 +25342,7 @@ p, li { white-space: pre-wrap; } Id originale - + << << @@ -26496,7 +25430,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History Storico modifiche pagina @@ -26531,7 +25465,7 @@ p, li { white-space: pre-wrap; } Id pagina - + \/ \/ @@ -26561,14 +25495,18 @@ p, li { white-space: pre-wrap; } Etichette - - + + History + Storico + + + Show Edit History Visualizza storico modifiche - + Status Status @@ -26589,7 +25527,7 @@ p, li { white-space: pre-wrap; } Rimposta - + Submit Invia @@ -26661,10 +25599,6 @@ p, li { white-space: pre-wrap; } WireDialog - - TimeRange - Lasso di tempo - Create Account @@ -26676,16 +25610,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - Aggiornamento - - - + Settings @@ -26700,7 +25625,7 @@ p, li { white-space: pre-wrap; } Altri - + Who to Follow @@ -26720,7 +25645,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -26750,85 +25675,17 @@ p, li { white-space: pre-wrap; } - Last Month - Mese scorso - - - Last Week - La settimana scorsa - - - Today - Oggi - - - New - Nuovo - - - from - Da - - - until - fino al - - - Search/Filter - Ricerca/filtro - - - Network Wide - Livello di rete - - - Manage Accounts - Gestire gli account - - - Showing: - Mostrando: - - - + Yourself Te stesso - - Friends - Amici - Following Seguendo - Custom - Personalizzato - - - Account 1 - Conto 1 - - - Account 2 - Conto 2 - - - Account 3 - Conto 3 - - - CheckBox - Casella da baffare - - - Post Pulse to Wire - Posta segnale sil filo - - - + RetroShare RetroShare @@ -26891,35 +25748,42 @@ p, li { white-space: pre-wrap; } - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + Rimuovi + + + Location: Località: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -26964,11 +25828,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + N/D + + + + Following + Seguendo + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Scononsciuto @@ -27046,7 +25940,7 @@ p, li { white-space: pre-wrap; } %1y %2d - + k e.g: 3.1 k k @@ -27079,15 +25973,11 @@ p, li { white-space: pre-wrap; } Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif *.webp) - - Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - Immagini (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_ja_JP.ts b/retroshare-gui/src/lang/retroshare_ja_JP.ts index ce4e63aeb..5f2256dd5 100644 --- a/retroshare-gui/src/lang/retroshare_ja_JP.ts +++ b/retroshare-gui/src/lang/retroshare_ja_JP.ts @@ -84,13 +84,6 @@ - - AddCommentDialog - - Add Comment - コメントを追加 - - AddFileAssociationDialog @@ -129,12 +122,12 @@ RetroShare: 高度な検索 - + Search Criteria 検索基準 - + Add a further search criterion. さらに検索基準を追加 @@ -144,7 +137,7 @@ 検索基準をリセット - + Cancels the search. 検索をキャンセル @@ -164,121 +157,6 @@ 検索 - - AlbumCreateDialog - - Create Album - アルバムを作成 - - - Album Name: - アルバム名: - - - Category: - カテゴリー - - - Animals - 動物 - - - Family - 家庭 - - - Friends - 友達 - - - Flowers - - - - Holiday - 旅行 - - - Landscapes - 風景 - - - Pets - ペット - - - Portraits - 肖像画 - - - Travel - トラベル - - - Work - 仕事 - - - Random - ランダム - - - Caption: - キャプション - - - Where: - 位置: - - - Photographer: - 写真家: - - - Description: - 説明: - - - Share Options - 共有のオプション - - - Policy: - ポリシー: - - - Quality: - 画質: - - - Comments: - コメント: - - - Public - パブリック - - - Resize Images (< 1Mb) - イメージのサイズを変更 (< 1Mb) - - - Resize Images (< 10Mb) - イメージのサイズを変更 (< 10Mb) - - - Back - 戻る - - - Add Photos - 写真を追加 - - - Where were these taken? - いつ撮りましたか? - - AlbumDialog @@ -307,22 +185,6 @@ Caption - - Where: - 位置: - - - Description: - 説明: - - - Share Options - 共有のオプション - - - Comments - コメント - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -679,7 +541,7 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. @@ -705,10 +567,23 @@ p, li { white-space: pre-wrap; } + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb %p Kb @@ -751,7 +626,7 @@ p, li { white-space: pre-wrap; } 削除 - + Set your Avatar picture @@ -838,22 +713,10 @@ p, li { white-space: pre-wrap; } リセット - Receive Rate - 受信速度 - - - Send Rate - 送信速度 - - - + Always on Top 常に手前に表示 - - Style - スタイル - Changes the transparency of the Bandwidth Graph @@ -869,23 +732,11 @@ p, li { white-space: pre-wrap; } % Opaque % 不透明 - - Save - 保存 - - - Cancel - キャンセル - Since: 開始: - - Hide Settings - 設定を非表示 - BandwidthStatsWidget @@ -958,7 +809,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment コメント @@ -988,12 +839,12 @@ p, li { white-space: pre-wrap; } RetroShareリンクをコピー - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -1001,7 +852,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up @@ -1021,7 +872,7 @@ p, li { white-space: pre-wrap; } - + Posted by @@ -1059,7 +910,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up @@ -1079,7 +930,7 @@ p, li { white-space: pre-wrap; } - + Click to view picture @@ -1109,7 +960,7 @@ p, li { white-space: pre-wrap; } - + Toggle Message Read Status 未読/既読の切り替え @@ -1119,7 +970,7 @@ p, li { white-space: pre-wrap; } 新規 - + TextLabel ラベル @@ -1127,12 +978,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this - + 0 0 @@ -1152,18 +1003,18 @@ p, li { white-space: pre-wrap; } - + New Comment - + Copy RetroShare Link RetroShareリンクをコピー - + Expand 展開 @@ -1178,12 +1029,12 @@ p, li { white-space: pre-wrap; } アイテムを削除 - + Name 名前 - + Comm value @@ -1352,17 +1203,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels - + Tabs - + General 一般 @@ -1372,7 +1223,17 @@ p, li { white-space: pre-wrap; } - + + Downloads + + + + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab @@ -1380,7 +1241,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1403,7 +1264,7 @@ into the image, so as to ChannelsCommentsItem - + I like this @@ -1428,18 +1289,18 @@ into the image, so as to - + New Comment - + Copy RetroShare Link RetroShareリンクをコピー - + Expand 展開 @@ -1454,7 +1315,7 @@ into the image, so as to アイテムを削除 - + Name 名前 @@ -1464,17 +1325,7 @@ into the image, so as to - - Comment - コメント - - - - Comments - - - - + Hide 非表示 @@ -1482,7 +1333,7 @@ into the image, so as to ChatLobbyDialog - + Name 名前 @@ -1673,7 +1524,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby チャットロビーを表示 @@ -1706,13 +1557,14 @@ into the image, so as to - + + Unknown Lobby - - + + Remove All @@ -1720,13 +1572,13 @@ into the image, so as to ChatLobbyWidget - - + + Name 名前 - + Count カウント @@ -1736,29 +1588,7 @@ into the image, so as to 話題 - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - プライベートチャット - - - - - Public chat rooms - 公開チャット - - - + Create chat room @@ -1768,7 +1598,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1825,12 +1655,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1840,27 +1670,42 @@ Double click a chat room to enter and chat. - Create chat lobby - チャットロビーを作成 - - - + [No topic provided] [話題はありません] - + + Private プライベート - + + Private Subscribed + + + + + + Public Subscribed + + + + + + Public パブリック - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted @@ -1870,38 +1715,25 @@ Double click a chat room to enter and chat. - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe - + Search Chat lobbies - + Search Name - + Columns - - Yes - はい - - - No - いいえ - Chat rooms @@ -1913,47 +1745,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: 話題: - + Type: タイプ - + Security: - + Peers: - - - - - - + + + + + + TextLabel ラベル @@ -1968,7 +1800,7 @@ Double click a chat room to enter and chat. - + Show @@ -1988,7 +1820,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item アイテムを削除 @@ -2033,7 +1865,7 @@ Double click a chat room to enter and chat. ChatPage - + General 一般 @@ -2048,15 +1880,7 @@ Double click a chat room to enter and chat. - Chat Settings - チャット設定 - - - Enable Emoticons Group Chat - グループチャットで顔文字を有効にする - - - + Enable custom fonts @@ -2076,7 +1900,7 @@ Double click a chat room to enter and chat. - + General settings @@ -2101,7 +1925,7 @@ Double click a chat room to enter and chat. - + Blink tab icon @@ -2110,10 +1934,6 @@ Double click a chat room to enter and chat. Do not send typing notifications - - Private Chat - プライベートチャット - Open Window for new chat @@ -2135,11 +1955,7 @@ Double click a chat room to enter and chat. - Chat Font - チャットフォント - - - + Change Chat Font チャットフォントを変更 @@ -2149,14 +1965,10 @@ Double click a chat room to enter and chat. チャットフォント: - + History 履歴 - - Style - スタイル - @@ -2171,17 +1983,13 @@ Double click a chat room to enter and chat. Variant: - - Group chat - グループチャット - Private chat プライベートチャット - + Choose your default font for Chat. @@ -2251,12 +2059,22 @@ Double click a chat room to enter and chat. - + Search 検索 - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2266,7 +2084,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2313,7 +2141,7 @@ Double click a chat room to enter and chat. Description: - + 説明 @@ -2363,7 +2191,7 @@ Double click a chat room to enter and chat. - + Case sensitive 大文字・小文字を区別 @@ -2469,7 +2297,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat チャットを表示 @@ -2505,7 +2333,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close 閉じる @@ -2540,12 +2368,12 @@ Double click a chat room to enter and chat. 斜体 - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2625,11 +2453,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2667,7 +2490,7 @@ Double click a chat room to enter and chat. - + is typing... 書き込み中... @@ -2689,7 +2512,7 @@ after HTML conversion. - + Do you really want to physically delete the history? 本当に履歴を削除しますか? @@ -2739,7 +2562,7 @@ after HTML conversion. - + Find Case Sensitively @@ -2761,7 +2584,7 @@ after HTML conversion. - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> @@ -2776,12 +2599,12 @@ after HTML conversion. - + (Status) - + Attach a File @@ -2797,12 +2620,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> - + Person id: @@ -2813,12 +2636,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. @@ -2838,7 +2661,7 @@ Double click on it to add his name on text writer. - + Don't stop to color after @@ -2864,7 +2687,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: @@ -2886,7 +2709,7 @@ Double click on it to add his name on text writer. - + Personal Circles @@ -2912,7 +2735,7 @@ Double click on it to add his name on text writer. - + Friends 友達 @@ -2972,7 +2795,7 @@ Double click on it to add his name on text writer. - + External Circles (Admin) @@ -2988,7 +2811,7 @@ Double click on it to add his name on text writer. - + Circles @@ -3040,45 +2863,45 @@ Double click on it to add his name on text writer. - + RetroShare RetroShare - + - + Error : cannot get peer details. エラー: ピア詳細を取得できません. - + Retroshare ID - + <p>This Retroshare ID contains: - + <p>This certificate contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: @@ -3088,7 +2911,7 @@ Double click on it to add his name on text writer. - + Not connected @@ -3170,12 +2993,17 @@ Double click on it to add his name on text writer. - + <li>a <b>node ID</b> and <b>name</b> - + + <b>DNS:</b> : + + + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3195,7 +3023,7 @@ Double click on it to add his name on text writer. - + with @@ -3217,10 +3045,6 @@ Double click on it to add his name on text writer. Open Cert of your friend from File - - Browse - ブラウズ - RetroShare ID @@ -3267,7 +3091,7 @@ Double click on it to add his name on text writer. Eメール - + @@ -3283,12 +3107,12 @@ Double click on it to add his name on text writer. - + Peer details - + Name: 名前: @@ -3298,17 +3122,17 @@ Double click on it to add his name on text writer. 場所: - + Options - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: @@ -3318,7 +3142,7 @@ Double click on it to add his name on text writer. - + Please paste below your friend's Retroshare ID @@ -3343,12 +3167,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with - + Sorry, some error appeared @@ -3368,32 +3202,27 @@ Double click on it to add his name on text writer. - + Key validity: - + Profile ID: - - Signers - - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. - + To accept the Friend Request, click the Accept button. @@ -3439,17 +3268,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed 証明書の読み込みに失敗 - + Not a valid Retroshare certificate! - + RetroShare Invitation @@ -3469,12 +3298,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3482,7 +3311,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3522,7 +3351,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Profile password needed. @@ -3547,7 +3376,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3557,11 +3386,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - Save as... - 名前を付けて保存 - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3600,7 +3425,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + IP-Addr: @@ -3610,7 +3435,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Show Advanced options @@ -3635,7 +3460,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already in your keyring @@ -3648,7 +3473,7 @@ even if you don't make friends. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. @@ -3683,7 +3508,7 @@ even if you don't make friends. - + No IP in this certificate! @@ -3693,12 +3518,7 @@ even if you don't make friends. - - [Unknown] - - - - + Added with certificate from %1 @@ -3763,7 +3583,7 @@ even if you don't make friends. - + UDP Setup @@ -3791,7 +3611,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant @@ -3801,17 +3621,20 @@ p, li { white-space: pre-wrap; } - + + Unknown State - + + Offline - + + Behind Symmetric NAT @@ -3821,12 +3644,14 @@ p, li { white-space: pre-wrap; } - + + NET Restart - + + Behind NAT @@ -3836,7 +3661,8 @@ p, li { white-space: pre-wrap; } - + + NET STATE GOOD! @@ -3861,7 +3687,7 @@ p, li { white-space: pre-wrap; } - + Lookup requires DHT @@ -4153,7 +3979,7 @@ p, li { white-space: pre-wrap; } - + @@ -4161,7 +3987,8 @@ p, li { white-space: pre-wrap; } N/A - + + UNVERIFIABLE FORWARD! @@ -4171,7 +3998,7 @@ p, li { white-space: pre-wrap; } - + Searching @@ -4207,12 +4034,12 @@ p, li { white-space: pre-wrap; } - + Name 名前 - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4232,7 +4059,7 @@ p, li { white-space: pre-wrap; } - + IDs ID @@ -4252,18 +4079,18 @@ p, li { white-space: pre-wrap; } - + Cancel キャンセル - + Nickname - + Invited Members @@ -4278,15 +4105,7 @@ p, li { white-space: pre-wrap; } - ID - ID - - - Type - タイプ - - - + Name: 名前: @@ -4326,19 +4145,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - + Please set a name for your Circle - + No Restriction Circle Selected @@ -4348,12 +4167,24 @@ p, li { white-space: pre-wrap; } - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add 追加 @@ -4363,7 +4194,7 @@ p, li { white-space: pre-wrap; } - + Search 検索 @@ -4416,13 +4247,13 @@ p, li { white-space: pre-wrap; } - + Create 作成 - + Add Member @@ -4441,7 +4272,7 @@ p, li { white-space: pre-wrap; } - + Group Name: @@ -4476,7 +4307,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post @@ -4486,7 +4317,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4546,10 +4377,6 @@ p, li { white-space: pre-wrap; } Add Channel Thumbnail - - Subject : - 件名: - @@ -4635,17 +4462,17 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -4670,7 +4497,12 @@ p, li { white-space: pre-wrap; } 件名を追加してください - + + Cannot publish post + + + + Load thumbnail picture @@ -4685,18 +4517,12 @@ p, li { white-space: pre-wrap; } 非表示 - - + Generate mass data - - Do you really want to generate %1 messages ? - - - - + You are about to add files you're not actually sharing. Do you still want this to happen? @@ -4730,7 +4556,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message @@ -4739,10 +4565,6 @@ p, li { white-space: pre-wrap; } Forum - - Subject - 件名 - Attach File @@ -4763,8 +4585,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -4783,7 +4605,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4813,17 +4635,17 @@ p, li { white-space: pre-wrap; } - + No Forum - + In Reply to - + Title タイトル @@ -4876,7 +4698,7 @@ Do you want to discard this message? 画像ファイルを開く - + No compatible ID for this forum @@ -4886,8 +4708,8 @@ Do you want to discard this message? - - + + Generate mass data @@ -4896,10 +4718,6 @@ Do you want to discard this message? Do you really want to generate %1 messages ? - - Send - 送信 - Post as @@ -4914,7 +4732,7 @@ Do you want to discard this message? CreateLobbyDialog - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -4949,7 +4767,7 @@ Do you want to discard this message? - + Create 作成 @@ -4959,7 +4777,7 @@ Do you want to discard this message? キャンセル - + require PGP-signed identities @@ -4974,7 +4792,7 @@ Do you want to discard this message? - + Create Chat Room @@ -4995,7 +4813,7 @@ Do you want to discard this message? - + Identity to use: @@ -5003,17 +4821,17 @@ Do you want to discard this message? CryptoPage - + Public Information - + Name: 名前: - + Location: 場所: @@ -5023,12 +4841,12 @@ Do you want to discard this message? - + Software Version: - + Online since: @@ -5048,12 +4866,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5063,7 +4876,7 @@ Do you want to discard this message? - + Other Information @@ -5073,17 +4886,12 @@ Do you want to discard this message? - + Profile - - Certificate - - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5093,7 +4901,7 @@ Do you want to discard this message? - + Export Identity @@ -5163,33 +4971,33 @@ and use the import button to load it - + TextLabel ラベル - + PGP fingerprint: - - Node information - - - - + PGP Id : - + Friend nodes: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5279,7 +5087,7 @@ and use the import button to load it DLListDelegate - + B @@ -5947,7 +5755,7 @@ and use the import button to load it DownloadToaster - + Start file @@ -5955,38 +5763,38 @@ and use the import button to load it ExprParamElement - + - + to - + ignore case - - - dd.MM.yyyy + + + yyyy-MM-dd - - + + KB - - + + MB - - + + GB @@ -5994,12 +5802,12 @@ and use the import button to load it ExpressionWidget - + Expression Widget - + Delete this expression @@ -6161,7 +5969,7 @@ and use the import button to load it FilesDefs - + Picture @@ -6171,7 +5979,7 @@ and use the import button to load it - + Audio @@ -6231,11 +6039,21 @@ and use the import button to load it C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories @@ -6357,7 +6175,7 @@ and use the import button to load it - + ID ID @@ -6399,7 +6217,7 @@ and use the import button to load it - + Group @@ -6435,7 +6253,7 @@ and use the import button to load it - + Search 検索 @@ -6451,7 +6269,7 @@ and use the import button to load it - + Profile details @@ -6688,7 +6506,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request @@ -6726,7 +6544,7 @@ at least one peer was not added to a group - + Mark all @@ -6737,16 +6555,132 @@ at least one peer was not added to a group + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + 名前 + + + + Node ID + + + + + Address + + + + + Status + 状態 + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message - - + + Broadcast @@ -6829,33 +6763,38 @@ at least one peer was not added to a group フォントをデフォルトに戻す - + Keyring - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. - - + + Network - + + Friend Server + + + + Network graph - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. @@ -6873,7 +6812,17 @@ at least one peer was not added to a group - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters すべてのフィールドは最低3文字以上必要です @@ -6883,17 +6832,12 @@ at least one peer was not added to a group - + Port ポート - - Use BOB - - - - + This password is for PGP @@ -6914,38 +6858,38 @@ at least one peer was not added to a group - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -6965,12 +6909,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -6980,38 +6924,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel ラベル - + hidden address - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -7055,13 +7004,13 @@ and use the import button to load it - + Import profile - + Create new profile and new Retroshare node @@ -7071,7 +7020,7 @@ and use the import button to load it - + Tor/I2P address @@ -7106,7 +7055,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7116,12 +7065,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -7131,12 +7075,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7362,27 +7301,13 @@ and use the import button to load it - + Invite Friends - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - - - - + Add Your Friends to RetroShare @@ -7392,39 +7317,57 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + Connect To Friends - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port @@ -7432,49 +7375,45 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - - - - + Further Help and Support - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website @@ -7499,7 +7438,7 @@ p, li { white-space: pre-wrap; } - + RetroShare Invitation @@ -7549,12 +7488,12 @@ p, li { white-space: pre-wrap; } - + RetroShare Support - + It has many features, including built-in chat, messaging, @@ -7678,7 +7617,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat @@ -7686,7 +7625,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] @@ -7856,7 +7795,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title タイトル @@ -7869,12 +7808,12 @@ p, li { white-space: pre-wrap; } - + Description 説明 - + Number of Unread message @@ -7899,7 +7838,7 @@ p, li { white-space: pre-wrap; } - + You are admin (modify names and description using Edit menu) @@ -7914,14 +7853,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post 最新の投稿 - + Name 名前 @@ -7932,17 +7871,13 @@ p, li { white-space: pre-wrap; } 人気度 - + Never - Display - 表示 - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -7955,7 +7890,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and @@ -8091,7 +8026,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels @@ -8102,22 +8037,22 @@ p, li { white-space: pre-wrap; } チャンネルを作成 - + Enable Auto-Download 自動ダウンロード有効 - + My Channels - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels 購読済みのチャンネル @@ -8137,12 +8072,12 @@ p, li { white-space: pre-wrap; } - + Disable Auto-Download 自動ダウンロード無効 - + Set download directory @@ -8177,22 +8112,22 @@ p, li { white-space: pre-wrap; } - + Play 再生 - + Open folder - + Open file - + Error @@ -8212,17 +8147,17 @@ p, li { white-space: pre-wrap; } - + Are you sure that you want to cancel and delete the file? - + Can't open folder - + Play File @@ -8232,25 +8167,10 @@ p, li { white-space: pre-wrap; } - - GxsChannelFilesWidget - - Form - フォーム - - - Title - タイトル - - - Status - 状態 - - GxsChannelGroupDialog - + Create New Channel @@ -8288,9 +8208,19 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - チャンネルを購読 + + Last activity + + + + + TextLabel + ラベル + + + + Subscribe this Channel + @@ -8304,7 +8234,7 @@ p, li { white-space: pre-wrap; } - + Expand 展開 @@ -8319,7 +8249,7 @@ p, li { white-space: pre-wrap; } チャンネルの説明 - + Loading ロード中 @@ -8334,8 +8264,9 @@ p, li { white-space: pre-wrap; } - New Channel - 新規チャンネル + + Never + @@ -8346,7 +8277,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: @@ -8367,7 +8298,7 @@ p, li { white-space: pre-wrap; } - + Play 再生 @@ -8429,18 +8360,18 @@ p, li { white-space: pre-wrap; } 非表示 - + New 新規 - + 0 0 - - + + Comment コメント @@ -8455,21 +8386,17 @@ p, li { white-space: pre-wrap; } - Loading - ロード中 - - - + Loading... - + Comments - + Post @@ -8494,51 +8421,16 @@ p, li { white-space: pre-wrap; } メディアを再生 - - GxsChannelPostsWidget - - Post to Channel - チャンネルに投稿 - - - Loading - ロード中 - - - Title - タイトル - - - No Channel Selected - チャンネルが選択されていません。 - - - Disable Auto-Download - 自動ダウンロード無効 - - - Enable Auto-Download - 自動ダウンロード有効 - - - Files - ファイル - - - Description: - 説明 - - GxsChannelPostsWidgetWithModel - + Post to Channel チャンネルに投稿 - + Add new post @@ -8608,7 +8500,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -8644,7 +8536,7 @@ p, li { white-space: pre-wrap; } - + Comments コメント @@ -8659,13 +8551,13 @@ p, li { white-space: pre-wrap; } - - + + Click to switch to list view - + Show unread posts only @@ -8680,7 +8572,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -8695,7 +8587,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -8755,12 +8647,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -8835,12 +8737,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed @@ -8891,17 +8794,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel ラベル - + Circle name: - + Accept @@ -9016,7 +8919,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container @@ -9029,7 +8932,7 @@ p, li { white-space: pre-wrap; } フォーム - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9059,7 +8962,7 @@ p, li { white-space: pre-wrap; } - + Comment コメント @@ -9098,7 +9001,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment @@ -9122,6 +9025,21 @@ p, li { white-space: pre-wrap; } Vote Down + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9131,7 +9049,7 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9160,7 +9078,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -9191,7 +9109,7 @@ before you can comment - + It remains %1 characters after HTML conversion. @@ -9242,7 +9160,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum @@ -9258,7 +9176,7 @@ before you can comment - + Expand 展開 @@ -9278,8 +9196,9 @@ before you can comment - Loading - ロード中 + + TextLabel + ラベル @@ -9310,13 +9229,13 @@ before you can comment GxsForumMsgItem - - + + Subject: - + Unsubscribe To Forum @@ -9327,7 +9246,7 @@ before you can comment - + Expand 展開 @@ -9347,21 +9266,17 @@ before you can comment - Loading - ロード中 - - - + Loading... - + Forum Feed - + Hide 非表示 @@ -9374,63 +9289,66 @@ before you can comment フォーム - + Start new Thread for Selected Forum - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums - Last Post - 最新の投稿 - - - + New Thread - - - Threaded View - - - - - Flat View - - - + Title タイトル - - + + Date 期日 - + Author - - Save image - - - - + Loading ロード中 - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9440,12 +9358,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message @@ -9485,23 +9398,23 @@ before you can comment - + No name - - + + Reply - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -9544,16 +9457,12 @@ before you can comment RetroShareリンクをコピー - + Hide 非表示 - Expand - 展開 - - - + [unknown] @@ -9583,8 +9492,8 @@ before you can comment - - + + Distribution @@ -9667,12 +9576,12 @@ before you can comment - + New thread - + Edit @@ -9733,7 +9642,7 @@ before you can comment - + Show column @@ -9753,7 +9662,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive @@ -9805,7 +9714,7 @@ This message is missing. You should receive it later. - + No result. @@ -9815,7 +9724,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -9830,7 +9739,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -9896,12 +9805,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums @@ -9932,23 +9841,16 @@ This message is missing. You should receive it later. - - GxsForumsFillThread - - Loading - ロード中 - - GxsGroupDialog - + Name 名前 - + Key recipients can publish to restricted-type group and can view and publish for private-type channels @@ -9959,12 +9861,12 @@ This message is missing. You should receive it later. - + Description 説明 - + Message Distribution @@ -9972,7 +9874,7 @@ This message is missing. You should receive it later. - + Public パブリック @@ -10032,7 +9934,7 @@ This message is missing. You should receive it later. - + Comments: コメント: @@ -10055,7 +9957,7 @@ This message is missing. You should receive it later. - + All People @@ -10071,12 +9973,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -10093,23 +9995,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -10125,22 +10027,28 @@ This message is missing. You should receive it later. 名前を追加してください - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo - + Submit Group Changes - + Owner: 所有者: @@ -10150,12 +10058,12 @@ This message is missing. You should receive it later. - + Info 情報 - + ID ID @@ -10165,7 +10073,7 @@ This message is missing. You should receive it later. 最新の投稿 - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -10240,7 +10148,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity 人気度 @@ -10256,27 +10169,22 @@ This message is missing. You should receive it later. - + Created - + Cancel キャンセル - + Create 作成 - - Author - - - - + GxsIdLabel @@ -10284,7 +10192,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading ロード中 @@ -10344,7 +10252,7 @@ This message is missing. You should receive it later. - + Synchronise posts of last... @@ -10401,12 +10309,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link RetroShareリンクをコピー @@ -10429,7 +10337,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature @@ -10442,18 +10350,14 @@ This message is missing. You should receive it later. GxsIdDetails - Loading - ロード中 - - - + Not found - - + + [Banned] @@ -10463,7 +10367,7 @@ This message is missing. You should receive it later. - + Loading... @@ -10473,7 +10377,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -10493,6 +10402,14 @@ This message is missing. You should receive it later. + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -10504,7 +10421,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -10552,17 +10469,13 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] GxsMessageFramePostWidget - - Loading - ロード中 - Loading... @@ -10943,7 +10856,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -10959,7 +10872,7 @@ p, li { white-space: pre-wrap; } - + Authors @@ -10978,7 +10891,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -11052,7 +10965,7 @@ p, li { white-space: pre-wrap; } フォーム - + Add friend @@ -11062,7 +10975,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -11090,7 +11003,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -11100,7 +11013,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard @@ -11110,7 +11023,7 @@ private and secure decentralized communication platform. - + Send via Email @@ -11130,13 +11043,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -11148,12 +11085,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -11168,12 +11105,7 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... 名前を付けて保存 @@ -11438,14 +11370,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All - + Reputation @@ -11455,12 +11387,12 @@ p, li { white-space: pre-wrap; } 検索 - + Anonymous Id - + Create new Identity @@ -11470,7 +11402,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -11485,27 +11417,27 @@ p, li { white-space: pre-wrap; } - + Close 閉じる - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -11521,29 +11453,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles - + Circle name @@ -11563,18 +11505,20 @@ p, li { white-space: pre-wrap; } - + + Edit identity - + + Delete identity - + Chat with this peer @@ -11584,78 +11528,78 @@ p, li { white-space: pre-wrap; } - + Owner node ID : - + Identity name : - + () - + Identity ID - + Send message - + Identity info - + Identity ID : - + Owner node name : - + Create new... - + Type: タイプ - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: - + Negative - + Neutral @@ -11666,17 +11610,17 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous @@ -11691,24 +11635,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you - - + + My own identities - - + + My contacts - + Show Items @@ -11723,7 +11667,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -11733,7 +11682,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -11808,7 +11757,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -11838,7 +11787,7 @@ p, li { white-space: pre-wrap; } - + Invited @@ -11853,7 +11802,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle @@ -11901,7 +11850,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -11909,7 +11858,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -11952,7 +11901,7 @@ These identities will soon be not supported anymore. - + Boards @@ -12032,7 +11981,7 @@ These identities will soon be not supported anymore. - + information @@ -12048,17 +11997,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -12163,7 +12107,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -12213,21 +12157,21 @@ These identities will soon be not supported anymore. - - - + + + People - + Your Avatar Click here to change your avatar - + Linked to neighbor nodes @@ -12237,7 +12181,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -12252,7 +12196,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -12267,12 +12211,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -12292,12 +12236,12 @@ These identities will soon be not supported anymore. - + Owned by - + Node name: @@ -12307,7 +12251,7 @@ These identities will soon be not supported anymore. - + Really delete? @@ -12315,7 +12259,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname @@ -12345,7 +12289,13 @@ These identities will soon be not supported anymore. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity @@ -12359,7 +12309,7 @@ These identities will soon be not supported anymore. - + @@ -12369,7 +12319,12 @@ These identities will soon be not supported anymore. N/A - + + No avatar chosen + + + + Edit identity @@ -12380,27 +12335,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -12420,7 +12375,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -12430,12 +12385,18 @@ These identities will soon be not supported anymore. - + Error KeyID invalid - + + + No Avatar chosen. A default image will be automatically displayed from your new identity. + + + + Import image @@ -12445,12 +12406,7 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. - - - - + Unknown GpgId @@ -12460,7 +12416,7 @@ These identities will soon be not supported anymore. - + Create New Identity @@ -12470,10 +12426,15 @@ These identities will soon be not supported anymore. タイプ - + Choose image... + + + Remove + 削除 + @@ -12499,7 +12460,7 @@ These identities will soon be not supported anymore. 追加 - + Create 作成 @@ -12509,13 +12470,13 @@ These identities will soon be not supported anymore. キャンセル - + Your Avatar Click here to change your avatar - + Linked to your profile @@ -12525,7 +12486,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -12599,7 +12560,7 @@ These identities will soon be not supported anymore. - + Copy @@ -12609,12 +12570,12 @@ These identities will soon be not supported anymore. 削除 - + %1 's Message History - + Mark all @@ -12633,26 +12594,38 @@ These identities will soon be not supported anymore. Quote - - Send - 送信 - ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -12670,27 +12643,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: - + Listen Address: - + + Status: + 状態: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -12711,7 +12689,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -12720,26 +12703,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File - + Open Folder - + Checking... @@ -12749,7 +12737,7 @@ These identities will soon be not supported anymore. - + Recommend in a message to... @@ -12777,7 +12765,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend @@ -12793,7 +12781,8 @@ These identities will soon be not supported anymore. - + + Options @@ -12814,7 +12803,7 @@ These identities will soon be not supported anymore. - + Quit 終了 @@ -12825,12 +12814,12 @@ These identities will soon be not supported anymore. - + RetroShare %1 a secure decentralized communication platform - + Unfinished @@ -12855,11 +12844,12 @@ These identities will soon be not supported anymore. + Status 状態 - + Notify @@ -12870,31 +12860,35 @@ These identities will soon be not supported anymore. + Open Messages - + + Bandwidth Graph - + Applications + Help ヘルプ - + + Minimize - + Maximize @@ -12909,7 +12903,12 @@ These identities will soon be not supported anymore. RetroShare - + + Close window + + + + %1 new message @@ -12939,7 +12938,7 @@ These identities will soon be not supported anymore. - + Do you really want to exit RetroShare ? @@ -12959,7 +12958,7 @@ These identities will soon be not supported anymore. - + Make sure this link has not been forged to drag you to a malicious website. @@ -13004,12 +13003,13 @@ These identities will soon be not supported anymore. - + + Statistics - + Show web interface @@ -13024,7 +13024,7 @@ These identities will soon be not supported anymore. - + Really quit ? @@ -13033,17 +13033,17 @@ These identities will soon be not supported anymore. MessageComposer - + Compose - + Contacts - + Paragraph @@ -13079,12 +13079,12 @@ These identities will soon be not supported anymore. - + Font size - + Increase font size @@ -13099,32 +13099,32 @@ These identities will soon be not supported anymore. 太字 - + Italic 斜体 - + Alignment - + Add an Image - + Sets text font to code style - + Underline 下線 - + Subject: @@ -13135,32 +13135,32 @@ These identities will soon be not supported anymore. - + Tags - + Address list: - + Recommend this friend - + Set Text color - + Set Text background color - + Recommended Files @@ -13230,7 +13230,7 @@ These identities will soon be not supported anymore. - + Send To: @@ -13270,7 +13270,7 @@ These identities will soon be not supported anymore. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> @@ -13290,18 +13290,18 @@ These identities will soon be not supported anymore. - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team - - + + Save Message - + Message has not been Sent. Do you want to save message to draft box? @@ -13312,7 +13312,17 @@ Do you want to save message to draft box? RetroShareリンクを貼り付け - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" @@ -13332,7 +13342,7 @@ Do you want to save message to draft box? - + Original Message @@ -13342,21 +13352,21 @@ Do you want to save message to draft box? - + - + To - - + + Cc - + Sent @@ -13371,7 +13381,7 @@ Do you want to save message to draft box? - + Re: @@ -13381,30 +13391,30 @@ Do you want to save message to draft box? - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? - + Please insert at least one recipient. - + Bcc - + Unknown @@ -13519,13 +13529,13 @@ Do you want to save message to draft box? 詳細 - + Open File... ファイルを開く... - + HTML-Files (*.htm *.html);;All Files (*) @@ -13545,7 +13555,7 @@ Do you want to save message to draft box? - + Message has not been Sent. Do you want to save message ? @@ -13566,7 +13576,7 @@ Do you want to save message ? さらにファイルを追加 - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -13596,18 +13606,18 @@ Do you want to save message ? - - + + Close 閉じる - + From: - + Bullet list (disc) @@ -13647,13 +13657,13 @@ Do you want to save message ? - - + + Thanks, <br> - + Distant identity: @@ -13663,12 +13673,12 @@ Do you want to save message ? - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -13746,7 +13756,7 @@ Do you want to save message ? - + A new tab @@ -13756,7 +13766,7 @@ Do you want to save message ? - + Edit Tag @@ -13779,7 +13789,7 @@ Do you want to save message ? MessageToaster - + Sub: @@ -13787,7 +13797,7 @@ Do you want to save message ? MessageUserNotify - + Message @@ -13815,7 +13825,7 @@ Do you want to save message ? MessageWidget - + Recommended Files @@ -13825,37 +13835,37 @@ Do you want to save message ? - + Subject: - + From: - + To: - + Cc: - + Bcc: - + Tags: - + Reply @@ -13895,7 +13905,7 @@ Do you want to save message ? - + Send Invite @@ -13947,7 +13957,7 @@ Do you want to save message ? - + Confirm %1 as friend @@ -13957,12 +13967,12 @@ Do you want to save message ? - + View source - + No subject @@ -13972,17 +13982,22 @@ Do you want to save message ? ダウンロード - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -13991,14 +14006,24 @@ Do you want to save message ? %1 (%2) + + + Show less + + + + + Show more + + - + Download all - + Print Document @@ -14013,12 +14038,12 @@ Do you want to save message ? - + Load images always for this message - + Hide the attachment pane @@ -14040,10 +14065,6 @@ Do you want to save message ? Compose - - Forward - 進む - Print @@ -14122,7 +14143,7 @@ Do you want to save message ? MessagesDialog - + New Message @@ -14132,24 +14153,16 @@ Do you want to save message ? - Print - 印刷 - - - Display - 表示 - - - + - - + + Tags - - + + Inbox @@ -14179,17 +14192,17 @@ Do you want to save message ? - + Total Inbox: - + Quick View - + Print... @@ -14220,7 +14233,7 @@ Do you want to save message ? - + Subject 件名 @@ -14230,7 +14243,7 @@ Do you want to save message ? - + Date 期日 @@ -14240,7 +14253,7 @@ Do you want to save message ? - + Search Subject @@ -14249,6 +14262,16 @@ Do you want to save message ? Search From + + + To + + + + + Search To + + Search Date @@ -14275,12 +14298,12 @@ Do you want to save message ? - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred @@ -14356,7 +14379,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -14370,7 +14393,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -14385,18 +14408,28 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts - + No Box selected. - + @@ -14431,7 +14464,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -14485,7 +14528,7 @@ Do you want to save message ? - + Expand 展開 @@ -14495,7 +14538,7 @@ Do you want to save message ? アイテムを削除 - + from @@ -14530,7 +14573,7 @@ Do you want to save message ? - + Hide 非表示 @@ -14671,7 +14714,7 @@ Do you want to save message ? ピア ID - + Remove unused keys... @@ -14681,7 +14724,7 @@ Do you want to save message ? - + Clean keyring @@ -14695,7 +14738,13 @@ Notes: Your old keyring will be backed up. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info @@ -14728,18 +14777,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. - - - Export/create a new node - - Trusted keys only - + Search name @@ -14749,12 +14793,12 @@ For security, your keyring was previously backed-up to file - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -14787,7 +14831,7 @@ Reported error: NewFriendList - + Offline Friends @@ -14808,7 +14852,7 @@ Reported error: - + Groups @@ -14838,19 +14882,19 @@ Reported error: - - + + Search 検索 - + ID ID - + Search ID @@ -14860,12 +14904,12 @@ Reported error: - + Show Items - + Last contact @@ -14875,7 +14919,7 @@ Reported error: - + Group @@ -14990,7 +15034,7 @@ Reported error: - + Do you want to remove this node? @@ -15000,7 +15044,7 @@ Reported error: - + Done! @@ -15107,7 +15151,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -15122,7 +15166,7 @@ at least one peer was not added to a group - + Newest on top @@ -15132,12 +15176,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15375,7 +15419,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -15395,12 +15439,12 @@ at least one peer was not added to a group - + Please enter your Retroshare passphrase - + Unregistered plugin/executable @@ -15415,7 +15459,7 @@ at least one peer was not added to a group - + Test @@ -15426,17 +15470,19 @@ at least one peer was not added to a group + Unknown title - + + Encrypted message - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -15444,7 +15490,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online @@ -15583,7 +15629,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -15628,12 +15679,7 @@ p, li { white-space: pre-wrap; } - - Options - - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -15679,21 +15725,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - - + + Error : cannot get peer details. エラー: ピア詳細を取得できません. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) @@ -15711,7 +15757,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -15780,10 +15826,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Check the password! - - Maybe password is wrong - おそらくパスワードが間違っています - You haven't set a trust level for this key. @@ -15791,12 +15833,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -15822,7 +15864,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat チャット @@ -15843,7 +15885,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.アイテムを削除 - + Name: 名前: @@ -15883,7 +15925,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message メッセージを作成 @@ -15941,7 +15983,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.非表示 - + Send Message @@ -16108,13 +16150,6 @@ Warning: In your File-Transfer option, you select allow direct download to No. - - PhotoCommentItem - - Form - フォーム - - PhotoDialog @@ -16127,10 +16162,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.TextLabel ラベル - - Comment - コメント - Album / Photo Name @@ -16191,10 +16222,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.... ... - - Add Comment - コメントを追加 - Album @@ -16274,17 +16301,17 @@ p, li { white-space: pre-wrap; } - + My Albums - + Subscribed Albums - + Shared Albums @@ -16313,7 +16340,7 @@ requesting to edit it! PhotoSlideShow - + Album Name @@ -16372,19 +16399,19 @@ requesting to edit it! - - + + TextLabel ラベル - + Posted by - + ago @@ -16420,12 +16447,12 @@ requesting to edit it! PluginItem - + TextLabel ラベル - + Show more details about this plugin @@ -16567,10 +16594,6 @@ p, li { white-space: pre-wrap; } Plugin look-up directories - - [disabled] - <無効> - Plugins @@ -16640,12 +16663,27 @@ p, li { white-space: pre-wrap; } - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -16698,7 +16736,7 @@ p, li { white-space: pre-wrap; } 新規 - + Vote up @@ -16718,8 +16756,8 @@ p, li { white-space: pre-wrap; } - - + + Comments コメント @@ -16744,13 +16782,13 @@ p, li { white-space: pre-wrap; } - - + + Comment コメント - + Comments @@ -16778,16 +16816,12 @@ p, li { white-space: pre-wrap; } PostedCreatePostDialog - Notes - メモ - - - + Create a new Post - + RetroShare RetroShare @@ -16802,12 +16836,22 @@ p, li { white-space: pre-wrap; } - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File 画像ファイルを開く - + Post image @@ -16823,7 +16867,17 @@ p, li { white-space: pre-wrap; } - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -16833,11 +16887,7 @@ p, li { white-space: pre-wrap; } - Submit - 投稿 - - - + Please add a Title タイトルを追加してください @@ -16857,12 +16907,22 @@ p, li { white-space: pre-wrap; } - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -16877,7 +16937,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -16888,7 +16948,7 @@ p, li { white-space: pre-wrap; } - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -16898,7 +16958,7 @@ p, li { white-space: pre-wrap; } タイトル - + Link リンク @@ -16906,12 +16966,12 @@ p, li { white-space: pre-wrap; } PostedDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -16945,7 +17005,7 @@ p, li { white-space: pre-wrap; } PostedGroupDialog - + Create New Board @@ -16983,7 +17043,17 @@ p, li { white-space: pre-wrap; } PostedGroupItem - + + Last activity + + + + + TextLabel + ラベル + + + Subscribe to Posted @@ -16999,7 +17069,7 @@ p, li { white-space: pre-wrap; } - + Expand 展開 @@ -17014,16 +17084,17 @@ p, li { white-space: pre-wrap; } - Loading - ロード中 - - - + Loading... - + + Never + + + + New Board @@ -17036,18 +17107,18 @@ p, li { white-space: pre-wrap; } PostedItem - + 0 0 - - + + Comments コメント - + Copy RetroShare Link RetroShareリンクをコピー @@ -17058,12 +17129,12 @@ p, li { white-space: pre-wrap; } - + Comment コメント - + Comments @@ -17073,7 +17144,7 @@ p, li { white-space: pre-wrap; } - + Click to view Picture @@ -17083,17 +17154,17 @@ p, li { white-space: pre-wrap; } 非表示 - + Vote up - + Vote down - + Set as read and remove item @@ -17103,7 +17174,7 @@ p, li { white-space: pre-wrap; } 新規 - + New Comment: @@ -17113,7 +17184,7 @@ p, li { white-space: pre-wrap; } - + Name 名前 @@ -17154,50 +17225,11 @@ p, li { white-space: pre-wrap; } ラベル - + Loading ロード中 - - PostedListWidget - - Form - フォーム - - - New - 新規 - - - Today - 今日 - - - Yesterday - 昨日 - - - This Week - 今週 - - - This Month - 今月 - - - This Year - 今年 - - - RetroShare - RetroShare - - - 1-10 - 1-10 - - PostedListWidgetWithModel @@ -17216,7 +17248,17 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -17226,15 +17268,15 @@ p, li { white-space: pre-wrap; } - + - + unknown - + Distribution: @@ -17244,42 +17286,42 @@ p, li { white-space: pre-wrap; } - + Created - + TextLabel ラベル - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -17299,7 +17341,7 @@ p, li { white-space: pre-wrap; } - + Search 検索 @@ -17329,17 +17371,17 @@ p, li { white-space: pre-wrap; } - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -17354,12 +17396,17 @@ p, li { white-space: pre-wrap; } - + Copy RetroShare Link RetroShareリンクをコピー - + + Copy http Link + + + + Show author in People tab @@ -17369,27 +17416,31 @@ p, li { white-space: pre-wrap; } - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -17404,7 +17455,7 @@ p, li { white-space: pre-wrap; } 購読 - + Never @@ -17478,6 +17529,16 @@ p, li { white-space: pre-wrap; } No Channel Selected チャンネルが選択されていません。 + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -17567,16 +17628,16 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -17684,7 +17745,7 @@ and use the import button to load it ProfileWidget - + Edit status message @@ -17700,7 +17761,7 @@ and use the import button to load it - + Public Information @@ -17735,12 +17796,12 @@ and use the import button to load it - + Other Information - + My Address @@ -17784,27 +17845,27 @@ and use the import button to load it PulseAddDialog - + Add to Pulse - + Display As - + URL URL - + GroupLabel - + IDLabel @@ -17814,12 +17875,12 @@ and use the import button to load it - + Head - + Head Shot @@ -17849,13 +17910,13 @@ and use the import button to load it - - + + Whats happening? - + @@ -17867,12 +17928,22 @@ and use the import button to load it - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -17887,7 +17958,7 @@ and use the import button to load it - + Reply to Pulse @@ -17902,30 +17973,24 @@ and use the import button to load it - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - Date - 期日 - - - ... - ... + + Load Picture File + 画像ファイルを開く @@ -17936,7 +18001,7 @@ and use the import button to load it フォーム - + @@ -17955,7 +18020,7 @@ and use the import button to load it PulseReply - + icn @@ -17965,7 +18030,7 @@ and use the import button to load it - + REPLY @@ -17992,7 +18057,7 @@ and use the import button to load it - + FOLLOW @@ -18002,7 +18067,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -18022,7 +18087,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -18138,7 +18203,7 @@ and use the import button to load it - + FOLLOW @@ -18146,37 +18211,42 @@ and use the import button to load it PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -18208,7 +18278,7 @@ and use the import button to load it - + FOLLOW @@ -18216,8 +18286,8 @@ and use the import button to load it QObject - - + + Confirmation @@ -18485,12 +18555,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + File Request canceled - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. @@ -18521,7 +18591,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + Cannot start Tor Manager! @@ -18555,7 +18625,7 @@ The error reported is:" - + Multiple instances @@ -18574,6 +18644,26 @@ The error reported is:" + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -18653,7 +18743,7 @@ Reported error is: - + You appear to have nodes associated to DSA keys: @@ -18663,7 +18753,7 @@ Reported error is: - + enabled @@ -18673,7 +18763,7 @@ Reported error is: - + Move IP %1 to whitelist @@ -18689,7 +18779,7 @@ Reported error is: - + %1 seconds ago @@ -18756,7 +18846,7 @@ Security: no anonymous IDs - + Join chat room @@ -18784,7 +18874,7 @@ Security: no anonymous IDs - + Indefinitely @@ -18964,13 +19054,29 @@ Security: no anonymous IDs Ban list + + + Name + 名前 + + Node + + + + + Address + + + + + Status 状態 - + NXS @@ -19213,6 +19319,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -19352,7 +19470,7 @@ p, li { white-space: pre-wrap; } - + Network Wide @@ -19519,7 +19637,7 @@ p, li { white-space: pre-wrap; } フォーム - + The loading of embedded images is blocked. @@ -19532,7 +19650,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default @@ -19705,12 +19823,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -19718,12 +19846,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -20411,7 +20539,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name 名前 @@ -20532,7 +20660,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name 名前 @@ -20552,7 +20680,7 @@ If you believe it is correct, remove the corresponding line from the file and re - + Profile ID @@ -20608,7 +20736,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -20622,11 +20750,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - - RsMessageModel @@ -20640,6 +20763,11 @@ prevents the message to be forwarded to your friends. From + + + To + + Subject @@ -20662,12 +20790,17 @@ prevents the message to be forwarded to your friends. - Click to sort by read + Click to sort by read status - Click to sort by from + Click to sort by author + + + + + Click to sort by destination @@ -20691,7 +20824,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -20712,7 +20847,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. 保存された Retoroshare の設定をすべてリセット. @@ -20773,7 +20908,7 @@ prevents the message to be forwarded to your friends. Retoroshare の言語を設定. - + Unable to open log file '%1': %2 ログファイル '%1" が開けません: %2 @@ -20794,7 +20929,7 @@ prevents the message to be forwarded to your friends. - + opmode @@ -20824,7 +20959,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -20842,7 +20977,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -20859,12 +20994,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) - + Start Search @@ -20925,7 +21060,7 @@ prevents the message to be forwarded to your friends. - + KeyWords @@ -20940,7 +21075,7 @@ prevents the message to be forwarded to your friends. - + Filename @@ -21040,23 +21175,23 @@ prevents the message to be forwarded to your friends. - + File Name - + Download ダウンロード - + Copy RetroShare Link RetroShareリンクをコピー - + Send RetroShare Link @@ -21066,7 +21201,7 @@ prevents the message to be forwarded to your friends. - + Download Notice ダウンロード @@ -21103,7 +21238,7 @@ prevents the message to be forwarded to your friends. - + Folder @@ -21114,17 +21249,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) - + Open Folder - + Create Collection... @@ -21144,7 +21279,7 @@ prevents the message to be forwarded to your friends. - + Collection @@ -21152,7 +21287,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details @@ -21168,22 +21303,22 @@ prevents the message to be forwarded to your friends. アイテムを削除 - + IP address: - + Peer ID: - + Location: 場所: - + Peer Name: @@ -21200,7 +21335,7 @@ prevents the message to be forwarded to your friends. 非表示 - + but reported: @@ -21225,8 +21360,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -21234,7 +21369,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare @@ -21265,7 +21400,7 @@ prevents the message to be forwarded to your friends. - + Expand 展開 @@ -21310,12 +21445,12 @@ prevents the message to be forwarded to your friends. 状態: - + Write Message メッセージを作成 - + Connect Attempt @@ -21335,17 +21470,12 @@ prevents the message to be forwarded to your friends. - + Unknown Security Issue - - A unknown peer - - - - + Unknown @@ -21355,7 +21485,17 @@ prevents the message to be forwarded to your friends. - + + SSL request + + + + + An unknown peer + + + + Hide 非表示 @@ -21365,7 +21505,7 @@ prevents the message to be forwarded to your friends. - + Certificate has wrong signature!! This peer is not who he claims to be. @@ -21375,12 +21515,12 @@ prevents the message to be forwarded to your friends. - + Certificate caused an internal error. - + Peer/node not in friendlist (PGP id= @@ -21439,12 +21579,12 @@ prevents the message to be forwarded to your friends. - + Local Address ローカル アドレス - + NAT @@ -21465,22 +21605,22 @@ prevents the message to be forwarded to your friends. - + Local network - + External ip address finder - + UPnP - + Known / Previous IPs: @@ -21493,21 +21633,16 @@ behind a firewall or a VPN. - - Allow RetroShare to ask my ip to these websites: - - - - - - + + + kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -21517,23 +21652,46 @@ behind a firewall or a VPN. - + Onion Address - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -21543,7 +21701,7 @@ behind a firewall or a VPN. - + I2P Address @@ -21568,37 +21726,95 @@ behind a firewall or a VPN. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -21613,71 +21829,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -21687,22 +21839,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -21714,12 +21851,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -21729,7 +21866,7 @@ Also check your ports! - + Download limit (KB/s) @@ -21744,23 +21881,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -21771,17 +21908,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -21791,12 +21918,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -21806,17 +21928,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 127.0.0.1 - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -21856,7 +21968,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start @@ -21871,12 +21983,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - BOB status - - - - + Incoming 受信 @@ -21912,7 +22019,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -21967,7 +22099,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Warning: This bandwidth adds up to the max bandwidth. @@ -21992,7 +22124,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -22004,7 +22136,7 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Filters @@ -22027,7 +22159,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status 状態 @@ -22087,17 +22219,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -22113,18 +22256,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -22159,12 +22302,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -22187,22 +22330,22 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -22237,7 +22380,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -22247,12 +22390,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -22332,7 +22475,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with @@ -22342,12 +22485,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Share - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -22366,7 +22509,7 @@ Select the Friends with which you want to Share your Channel. - + Shared directory @@ -22386,17 +22529,17 @@ Select the Friends with which you want to Share your Channel. - + Add new - + Cancel キャンセル - + Add a Share Directory @@ -22406,7 +22549,7 @@ Select the Friends with which you want to Share your Channel. 削除 - + Apply and close @@ -22497,7 +22640,7 @@ Select the Friends with which you want to Share your Channel. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. @@ -22505,7 +22648,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files ファイル @@ -22556,11 +22699,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files - + Download selected @@ -22570,7 +22718,7 @@ Select the Friends with which you want to Share your Channel. ダウンロード - + Copy retroshare Links to Clipboard @@ -22585,7 +22733,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted @@ -22601,7 +22749,7 @@ Select the Friends with which you want to Share your Channel. - + Create Collection... @@ -22626,7 +22774,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted because they have not been indexed yet. @@ -22769,12 +22917,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration - + Create interface @@ -22798,7 +22946,7 @@ Select the Friends with which you want to Share your Channel. - + Log In ログイン @@ -23137,7 +23285,7 @@ This choice can be reverted in settings. - + Message: @@ -23374,7 +23522,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags @@ -23410,12 +23558,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown @@ -23425,18 +23576,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -23446,12 +23592,57 @@ p, li { white-space: pre-wrap; } - + + Error + + + + + Not connected + + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -23459,7 +23650,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -23469,7 +23660,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -23480,11 +23671,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -23512,7 +23704,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options @@ -23523,7 +23715,7 @@ p, li { white-space: pre-wrap; } - + Shared Directories @@ -23533,22 +23725,27 @@ p, li { white-space: pre-wrap; } - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -23633,7 +23830,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -23642,7 +23839,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -23667,7 +23869,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming @@ -23732,12 +23939,7 @@ p, li { white-space: pre-wrap; } - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -23747,7 +23949,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -23775,7 +23987,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed @@ -23803,19 +24015,19 @@ p, li { white-space: pre-wrap; } TransfersDialog - - + + Downloads - + Uploads - + Name i.e: file name 名前 @@ -24022,7 +24234,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... @@ -24047,7 +24264,7 @@ p, li { white-space: pre-wrap; } - + Anonymous end-to-end encrypted tunnel 0x @@ -24068,7 +24285,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -24101,7 +24318,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name @@ -24116,7 +24343,7 @@ p, li { white-space: pre-wrap; } - + Expand all @@ -24243,23 +24470,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns - + File Transfers - + Path @@ -24269,7 +24491,7 @@ p, li { white-space: pre-wrap; } - + Could not delete preview file @@ -24279,7 +24501,7 @@ p, li { white-space: pre-wrap; } - + Create Collection... @@ -24294,7 +24516,7 @@ p, li { white-space: pre-wrap; } - + Collection @@ -24304,7 +24526,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x @@ -24718,12 +24940,17 @@ p, li { white-space: pre-wrap; } フォーム - + Enable Retroshare WEB Interface - + + Status: + 状態: + + + Web parameters @@ -24763,17 +24990,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -24783,12 +25020,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface @@ -24925,7 +25162,7 @@ p, li { white-space: pre-wrap; } - + Page Name @@ -24940,7 +25177,7 @@ p, li { white-space: pre-wrap; } - + << @@ -25028,7 +25265,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History @@ -25063,7 +25300,7 @@ p, li { white-space: pre-wrap; } - + \/ @@ -25093,14 +25330,18 @@ p, li { white-space: pre-wrap; } - - + + History + 履歴 + + + Show Edit History - + Status 状態 @@ -25121,7 +25362,7 @@ p, li { white-space: pre-wrap; } - + Submit 投稿 @@ -25204,16 +25445,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - - - - + Settings @@ -25228,7 +25460,7 @@ p, li { white-space: pre-wrap; } - + Who to Follow @@ -25248,7 +25480,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -25278,29 +25510,17 @@ p, li { white-space: pre-wrap; } - Today - 今日 - - - New - 新規 - - - + Yourself - - Friends - 友達 - Following - + RetroShare RetroShare @@ -25363,35 +25583,42 @@ p, li { white-space: pre-wrap; } フォーム - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + 削除 + + + Location: 場所: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -25436,11 +25663,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + N/A + + + + Following + + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) @@ -25518,7 +25775,7 @@ p, li { white-space: pre-wrap; } - + k e.g: 3.1 k @@ -25555,7 +25812,7 @@ p, li { white-space: pre-wrap; } pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_ko.ts b/retroshare-gui/src/lang/retroshare_ko.ts index d3aa306a1..927baa9e7 100644 --- a/retroshare-gui/src/lang/retroshare_ko.ts +++ b/retroshare-gui/src/lang/retroshare_ko.ts @@ -84,13 +84,6 @@ - - AddCommentDialog - - Add Comment - 설명 추가 - - AddFileAssociationDialog @@ -129,12 +122,12 @@ 레트로 쉐어: 고급 검색 - + Search Criteria 검색 문구 - + Add a further search criterion. 검색 문구 더 추가합니다. @@ -144,7 +137,7 @@ 검색 문구를 초기화합니다. - + Cancels the search. 검색을 취소합니다. @@ -164,177 +157,6 @@ 검색 - - AlbumCreateDialog - - Create Album - 앨범 만들기 - - - Album Name: - 앨범 이름: - - - Category: - 분류: - - - Animals - 동물 - - - Family - 가족 - - - Friends - 친구 - - - Flowers - 화훼 - - - Holiday - 휴일 - - - Landscapes - 수평 사진 - - - Pets - 반려동물 - - - Portraits - 수직 사진 - - - Travel - 여행 - - - Work - 작업 - - - Random - 임의 - - - Caption: - 자막설명: - - - Where: - 장소: - - - Photographer: - 사진가: - - - Description: - 설명: - - - Share Options - 공유 옵션 - - - Policy: - 정책: - - - Quality: - 화질: - - - Comments: - 설명: - - - Identity: - 식별: - - - Public - 공용 - - - Restricted - 제한 - - - Resize Images (< 1Mb) - 그림 크기 조절(< 1Mb) - - - Resize Images (< 10Mb) - 그림 크기 조절(< 10Mb) - - - Send Original Images - 원본 그림 보내기 - - - No Comments Allowed - 설명을 추가할 수 없습니다 - - - Authenticated Comments - 인증한 설명 - - - Any Comments Allowed - 어떤 설명이든 추가할 수 있음 - - - Publish with Identity - 신원 정보와 함께 게시 - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> 그림을 추가하려면 끌어다놓으십시오. 하단 세부 정보를 편집하려면 그림을 누르십시오.</span></p></body></html> - - - Back - 뒤로 - - - Add Photos - 사진 추가 - - - Publish Album - 앨범 게시 - - - Untitle Album - 제목 없는 앨범 - - - Say something about this album... - 이 앨범의 설명을 적으세요... - - - Where were these taken? - 어디서 찍었을까요? - - - Load Album Thumbnail - 앨범 미리 보기 그림 불러오기 - - AlbumDialog @@ -343,19 +165,11 @@ p, li { white-space: pre-wrap; } Album 앨범 - - Album Thumbnail - 앨범 미리 보기 그림 - TextLabel 텍스트 레이블 - - Summary - 요약 - Album Title: @@ -371,30 +185,6 @@ p, li { white-space: pre-wrap; } Caption 자막 설명 - - Where: - 장소: - - - When - 일시 - - - Description: - 설명: - - - Share Options - 공유 옵션 - - - Comments - 설명 - - - Publish Identity - 게시 신원 - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -755,7 +545,7 @@ p, li { white-space: pre-wrap; } 레트로 쉐어 - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. @@ -781,10 +571,23 @@ p, li { white-space: pre-wrap; } 사진 + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb %pKb @@ -821,17 +624,13 @@ p, li { white-space: pre-wrap; } Browse... - - Add Avatar - 아바타 추가 - Remove 제거 - + Set your Avatar picture 아바타 사진 설정 @@ -850,10 +649,6 @@ p, li { white-space: pre-wrap; } Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - 아바타 불러오기 - AvatarWidget @@ -922,22 +717,10 @@ p, li { white-space: pre-wrap; } 초기화 - Receive Rate - 수신율 - - - Send Rate - 송신율 - - - + Always on Top 항상 위로 - - Style - 스타일 - Changes the transparency of the Bandwidth Graph @@ -953,23 +736,11 @@ p, li { white-space: pre-wrap; } % Opaque % 투명도 - - Save - 저장 - - - Cancel - 취소 - Since: 시초: - - Hide Settings - 설정 숨기기 - BandwidthStatsWidget @@ -1042,7 +813,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment 답글 달기 @@ -1072,12 +843,12 @@ p, li { white-space: pre-wrap; } 레트로 쉐어 링크 복사 - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -1085,7 +856,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up @@ -1105,7 +876,7 @@ p, li { white-space: pre-wrap; } - + Posted by @@ -1143,7 +914,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up @@ -1163,7 +934,7 @@ p, li { white-space: pre-wrap; } - + Click to view picture @@ -1193,7 +964,7 @@ p, li { white-space: pre-wrap; } - + Toggle Message Read Status @@ -1203,7 +974,7 @@ p, li { white-space: pre-wrap; } - + TextLabel 텍스트 레이블 @@ -1211,12 +982,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this - + 0 0 @@ -1236,18 +1007,18 @@ p, li { white-space: pre-wrap; } - + New Comment - + Copy RetroShare Link 레트로 쉐어 링크 복사 - + Expand 확장 @@ -1262,12 +1033,12 @@ p, li { white-space: pre-wrap; } 항목 제거 - + Name 이름 - + Comm value @@ -1436,17 +1207,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels - + Tabs - + General 일반 @@ -1456,7 +1227,17 @@ p, li { white-space: pre-wrap; } - + + Downloads + + + + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab @@ -1464,7 +1245,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1487,7 +1268,7 @@ into the image, so as to ChannelsCommentsItem - + I like this @@ -1512,18 +1293,18 @@ into the image, so as to - + New Comment - + Copy RetroShare Link 레트로 쉐어 링크 복사 - + Expand 확장 @@ -1538,7 +1319,7 @@ into the image, so as to 항목 제거 - + Name 이름 @@ -1548,17 +1329,7 @@ into the image, so as to - - Comment - 답글 달기 - - - - Comments - - - - + Hide 숨김 @@ -1566,7 +1337,7 @@ into the image, so as to ChatLobbyDialog - + Name 이름 @@ -1757,7 +1528,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby 대화 대기방 보이기 @@ -1790,13 +1561,14 @@ into the image, so as to - + + Unknown Lobby - - + + Remove All @@ -1804,13 +1576,13 @@ into the image, so as to ChatLobbyWidget - - + + Name 이름 - + Count 계수 @@ -1820,29 +1592,7 @@ into the image, so as to 주제 - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - - - - - - Public chat rooms - - - - + Create chat room @@ -1852,7 +1602,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1909,12 +1659,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1924,27 +1674,42 @@ Double click a chat room to enter and chat. - Create chat lobby - 대화 대기방 만들기 - - - + [No topic provided] [설정한 주제가 없습니다] - + + Private 개인용 - + + Private Subscribed + + + + + + Public Subscribed + + + + + + Public 공용 - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted @@ -1954,27 +1719,22 @@ Double click a chat room to enter and chat. - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe - + Search Chat lobbies - + Search Name - + Columns @@ -1989,47 +1749,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: - + Type: 유형: - + Security: - + Peers: - - - - - - + + + + + + TextLabel 텍스트 레이블 @@ -2044,7 +1804,7 @@ Double click a chat room to enter and chat. - + Show 표시 @@ -2064,7 +1824,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item 항목 제거 @@ -2109,7 +1869,7 @@ Double click a chat room to enter and chat. ChatPage - + General 일반 @@ -2124,15 +1884,7 @@ Double click a chat room to enter and chat. - Chat Settings - 대화 설정 - - - Enable Emoticons Group Chat - 이모티콘 집단 대화 활성화 - - - + Enable custom fonts @@ -2152,7 +1904,7 @@ Double click a chat room to enter and chat. - + General settings @@ -2177,7 +1929,7 @@ Double click a chat room to enter and chat. - + Blink tab icon @@ -2186,10 +1938,6 @@ Double click a chat room to enter and chat. Do not send typing notifications - - Private Chat - 개인 대화 - Open Window for new chat @@ -2211,11 +1959,7 @@ Double click a chat room to enter and chat. - Chat Font - 대화 글꼴 - - - + Change Chat Font 대화 글꼴 바꾸기 @@ -2225,14 +1969,10 @@ Double click a chat room to enter and chat. 대화 글꼴: - + History 기록 - - Style - 스타일 - @@ -2247,17 +1987,13 @@ Double click a chat room to enter and chat. Variant: - - Group chat - 집단 대화 - Private chat 개인 대화 - + Choose your default font for Chat. @@ -2327,12 +2063,22 @@ Double click a chat room to enter and chat. - + Search 검색 - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2342,7 +2088,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2439,7 +2195,7 @@ Double click a chat room to enter and chat. - + Case sensitive 대소문자 구분 @@ -2545,7 +2301,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat 대화 보이기 @@ -2581,7 +2337,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close 닫기 @@ -2616,12 +2372,12 @@ Double click a chat room to enter and chat. 기울임 - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2701,11 +2457,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2743,7 +2494,7 @@ Double click a chat room to enter and chat. - + is typing... 입력중 ... @@ -2765,7 +2516,7 @@ after HTML conversion. - + Do you really want to physically delete the history? 실제 기록을 정말로 삭제하시겠습니까? @@ -2815,7 +2566,7 @@ after HTML conversion. 다른 용무중이며 응답하지 않을 수도 있습니다 - + Find Case Sensitively @@ -2837,7 +2588,7 @@ after HTML conversion. - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> @@ -2852,12 +2603,12 @@ after HTML conversion. - + (Status) - + Attach a File @@ -2873,12 +2624,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> - + Person id: @@ -2889,12 +2640,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. @@ -2914,7 +2665,7 @@ Double click on it to add his name on text writer. - + Don't stop to color after @@ -2940,7 +2691,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: @@ -2962,7 +2713,7 @@ Double click on it to add his name on text writer. - + Personal Circles @@ -2988,7 +2739,7 @@ Double click on it to add his name on text writer. - + Friends 친구 @@ -3048,7 +2799,7 @@ Double click on it to add his name on text writer. - + External Circles (Admin) @@ -3064,7 +2815,7 @@ Double click on it to add his name on text writer. - + Circles @@ -3116,45 +2867,45 @@ Double click on it to add his name on text writer. - + RetroShare 레트로 쉐어 - + - + Error : cannot get peer details. 오류 : 동료 세부 정보를 가져올 수 없습니다 - + Retroshare ID - + <p>This Retroshare ID contains: - + <p>This certificate contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: @@ -3164,7 +2915,7 @@ Double click on it to add his name on text writer. - + Not connected @@ -3246,12 +2997,17 @@ Double click on it to add his name on text writer. 없음 - + <li>a <b>node ID</b> and <b>name</b> - + + <b>DNS:</b> : + + + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3271,7 +3027,7 @@ Double click on it to add his name on text writer. - + with @@ -3288,10 +3044,6 @@ Double click on it to add his name on text writer. Connect Friend Wizard 친구 연결 마법사 - - Include signatures - 서명 포함 - Open Cert of your friend from File @@ -3302,10 +3054,6 @@ Double click on it to add his name on text writer. RetroShare ID 레트로 쉐어 ID - - Add Friends RetroShare ID... - 친구 레트로 쉐어 ID 추가... - RetroShare is better with Friends @@ -3347,11 +3095,7 @@ Double click on it to add his name on text writer. 이메일 - Subject: - 제목: - - - + @@ -3367,12 +3111,12 @@ Double click on it to add his name on text writer. - + Peer details - + Name: 이름: @@ -3382,17 +3126,17 @@ Double click on it to add his name on text writer. 지역: - + Options 옵션 - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: @@ -3402,7 +3146,7 @@ Double click on it to add his name on text writer. - + Please paste below your friend's Retroshare ID @@ -3427,12 +3171,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with - + Sorry, some error appeared @@ -3452,32 +3206,27 @@ Double click on it to add his name on text writer. - + Key validity: - + Profile ID: - - Signers - - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. - + To accept the Friend Request, click the Accept button. @@ -3523,17 +3272,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed 서명 불러오기에 실패했습니다 - + Not a valid Retroshare certificate! - + RetroShare Invitation 레트로 쉐어 초대 @@ -3553,12 +3302,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3566,7 +3315,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3606,7 +3355,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Profile password needed. @@ -3631,7 +3380,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3641,15 +3390,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - RetroShare Invite - 레트로 쉐어 초대 - - - Save as... - 다른 이름으로 저장... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3688,7 +3429,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + IP-Addr: @@ -3698,7 +3439,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Show Advanced options @@ -3723,7 +3464,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already in your keyring @@ -3736,7 +3477,7 @@ even if you don't make friends. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. @@ -3771,7 +3512,7 @@ even if you don't make friends. - + No IP in this certificate! @@ -3781,12 +3522,7 @@ even if you don't make friends. - - [Unknown] - - - - + Added with certificate from %1 @@ -3851,7 +3587,7 @@ even if you don't make friends. - + UDP Setup @@ -3879,7 +3615,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant @@ -3889,17 +3625,20 @@ p, li { white-space: pre-wrap; } - + + Unknown State - + + Offline - + + Behind Symmetric NAT @@ -3909,12 +3648,14 @@ p, li { white-space: pre-wrap; } - + + NET Restart - + + Behind NAT @@ -3924,7 +3665,8 @@ p, li { white-space: pre-wrap; } - + + NET STATE GOOD! @@ -3949,7 +3691,7 @@ p, li { white-space: pre-wrap; } - + Lookup requires DHT @@ -4241,7 +3983,7 @@ p, li { white-space: pre-wrap; } - + @@ -4249,7 +3991,8 @@ p, li { white-space: pre-wrap; } 없음 - + + UNVERIFIABLE FORWARD! @@ -4259,7 +4002,7 @@ p, li { white-space: pre-wrap; } - + Searching @@ -4295,12 +4038,12 @@ p, li { white-space: pre-wrap; } - + Name 이름 - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4320,7 +4063,7 @@ p, li { white-space: pre-wrap; } - + IDs ID @@ -4340,18 +4083,18 @@ p, li { white-space: pre-wrap; } - + Cancel 취소 - + Nickname - + Invited Members @@ -4366,15 +4109,7 @@ p, li { white-space: pre-wrap; } - ID - ID - - - Type - 형식 - - - + Name: 이름: @@ -4414,19 +4149,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare 레트로 쉐어 - + Please set a name for your Circle - + No Restriction Circle Selected @@ -4436,12 +4171,24 @@ p, li { white-space: pre-wrap; } - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add 추가 @@ -4451,7 +4198,7 @@ p, li { white-space: pre-wrap; } - + Search 검색 @@ -4504,13 +4251,13 @@ p, li { white-space: pre-wrap; } - + Create 만들기 - + Add Member @@ -4529,7 +4276,7 @@ p, li { white-space: pre-wrap; } - + Group Name: @@ -4564,7 +4311,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post @@ -4574,7 +4321,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4634,10 +4381,6 @@ p, li { white-space: pre-wrap; } Add Channel Thumbnail - - Subject : - 제목 : - @@ -4723,17 +4466,17 @@ p, li { white-space: pre-wrap; } - + RetroShare 레트로 쉐어 - + This file already in this post: - + Post refers to non shared files @@ -4758,7 +4501,12 @@ p, li { white-space: pre-wrap; } 제목을 입력해주십시오 - + + Cannot publish post + + + + Load thumbnail picture @@ -4773,18 +4521,12 @@ p, li { white-space: pre-wrap; } 숨김 - - + Generate mass data - - Do you really want to generate %1 messages ? - - - - + You are about to add files you're not actually sharing. Do you still want this to happen? @@ -4818,7 +4560,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message @@ -4827,10 +4569,6 @@ p, li { white-space: pre-wrap; } Forum 포럼 - - Subject - 제목 - Attach File @@ -4851,8 +4589,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -4871,7 +4609,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4901,17 +4639,17 @@ p, li { white-space: pre-wrap; } - + No Forum - + In Reply to - + Title 제목 @@ -4964,7 +4702,7 @@ Do you want to discard this message? 그림 파일 불러오기 - + No compatible ID for this forum @@ -4974,8 +4712,8 @@ Do you want to discard this message? - - + + Generate mass data @@ -4984,10 +4722,6 @@ Do you want to discard this message? Do you really want to generate %1 messages ? - - Send - 보내기 - Post as @@ -5002,7 +4736,7 @@ Do you want to discard this message? CreateLobbyDialog - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5037,7 +4771,7 @@ Do you want to discard this message? - + Create 만들기 @@ -5047,7 +4781,7 @@ Do you want to discard this message? 취소 - + require PGP-signed identities @@ -5062,7 +4796,7 @@ Do you want to discard this message? - + Create Chat Room @@ -5083,7 +4817,7 @@ Do you want to discard this message? - + Identity to use: @@ -5091,17 +4825,17 @@ Do you want to discard this message? CryptoPage - + Public Information - + Name: 이름: - + Location: 지역: @@ -5111,12 +4845,12 @@ Do you want to discard this message? - + Software Version: - + Online since: @@ -5136,12 +4870,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5151,7 +4880,7 @@ Do you want to discard this message? - + Other Information @@ -5161,17 +4890,12 @@ Do you want to discard this message? - + Profile - - Certificate - 인증 - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5181,7 +4905,7 @@ Do you want to discard this message? 서명 포함 - + Export Identity @@ -5251,33 +4975,33 @@ and use the import button to load it - + TextLabel 텍스트 레이블 - + PGP fingerprint: - - Node information - - - - + PGP Id : - + Friend nodes: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5367,7 +5091,7 @@ and use the import button to load it DLListDelegate - + B @@ -6035,7 +5759,7 @@ and use the import button to load it DownloadToaster - + Start file @@ -6043,38 +5767,38 @@ and use the import button to load it ExprParamElement - + - + to - + ignore case - - - dd.MM.yyyy + + + yyyy-MM-dd - - + + KB - - + + MB - - + + GB @@ -6082,12 +5806,12 @@ and use the import button to load it ExpressionWidget - + Expression Widget - + Delete this expression @@ -6249,7 +5973,7 @@ and use the import button to load it FilesDefs - + Picture @@ -6259,7 +5983,7 @@ and use the import button to load it - + Audio @@ -6319,11 +6043,21 @@ and use the import button to load it C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories @@ -6445,7 +6179,7 @@ and use the import button to load it - + ID ID @@ -6487,7 +6221,7 @@ and use the import button to load it - + Group @@ -6523,7 +6257,7 @@ and use the import button to load it - + Search 검색 @@ -6539,7 +6273,7 @@ and use the import button to load it - + Profile details @@ -6776,7 +6510,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request @@ -6814,7 +6548,7 @@ at least one peer was not added to a group - + Mark all @@ -6825,16 +6559,132 @@ at least one peer was not added to a group + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + 이름 + + + + Node ID + + + + + Address + + + + + Status + 상태 + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message - - + + Broadcast @@ -6917,33 +6767,38 @@ at least one peer was not added to a group 글꼴을 기본으로 재설정 - + Keyring - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. - - + + Network - + + Friend Server + + + + Network graph - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. @@ -6961,7 +6816,17 @@ at least one peer was not added to a group 암호 - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters 모든 분야의 3 문자의 최소 필요합니다 @@ -6971,17 +6836,12 @@ at least one peer was not added to a group - + Port 포트 - - Use BOB - - - - + This password is for PGP @@ -7002,38 +6862,38 @@ at least one peer was not added to a group - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -7053,12 +6913,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -7068,38 +6928,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel 텍스트 레이블 - + hidden address - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -7143,13 +7008,13 @@ and use the import button to load it - + Import profile - + Create new profile and new Retroshare node @@ -7159,7 +7024,7 @@ and use the import button to load it - + Tor/I2P address @@ -7194,7 +7059,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7204,12 +7069,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -7219,12 +7079,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7450,27 +7305,13 @@ and use the import button to load it - + Invite Friends - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - - - - + Add Your Friends to RetroShare 레트로 쉐어에 친구 추가하기 @@ -7480,39 +7321,57 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + Connect To Friends - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port @@ -7520,49 +7379,45 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - - - - + Further Help and Support - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website @@ -7587,7 +7442,7 @@ p, li { white-space: pre-wrap; } - + RetroShare Invitation 레트로 쉐어 초대 @@ -7637,12 +7492,12 @@ p, li { white-space: pre-wrap; } 레트로 쉐어 피드백 - + RetroShare Support 레트로 쉐어 지원 - + It has many features, including built-in chat, messaging, @@ -7766,7 +7621,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat @@ -7774,7 +7629,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] @@ -7944,7 +7799,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title 제목 @@ -7957,12 +7812,12 @@ p, li { white-space: pre-wrap; } - + Description 설명 - + Number of Unread message @@ -7987,7 +7842,7 @@ p, li { white-space: pre-wrap; } - + You are admin (modify names and description using Edit menu) @@ -8002,14 +7857,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post 최신 게시글 - + Name 이름 @@ -8020,17 +7875,13 @@ p, li { white-space: pre-wrap; } 인기도 - + Never - Display - 표시 - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8043,7 +7894,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and @@ -8179,7 +8030,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels @@ -8190,22 +8041,22 @@ p, li { white-space: pre-wrap; } 채널 만들기 - + Enable Auto-Download 자동 다운로드 활성화 - + My Channels - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels 가입한 채널 @@ -8225,12 +8076,12 @@ p, li { white-space: pre-wrap; } - + Disable Auto-Download 자동 다운로드 비활성화 - + Set download directory @@ -8265,22 +8116,22 @@ p, li { white-space: pre-wrap; } - + Play - + Open folder - + Open file - + Error @@ -8300,17 +8151,17 @@ p, li { white-space: pre-wrap; } - + Are you sure that you want to cancel and delete the file? - + Can't open folder - + Play File @@ -8320,25 +8171,10 @@ p, li { white-space: pre-wrap; } - - GxsChannelFilesWidget - - Form - 양식 - - - Title - 제목 - - - Status - 상태 - - GxsChannelGroupDialog - + Create New Channel @@ -8376,9 +8212,19 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - 채널에 가입 + + Last activity + + + + + TextLabel + 텍스트 레이블 + + + + Subscribe this Channel + @@ -8392,7 +8238,7 @@ p, li { white-space: pre-wrap; } - + Expand 확장 @@ -8407,7 +8253,7 @@ p, li { white-space: pre-wrap; } 채널 설명 - + Loading 불러오는 중 @@ -8422,8 +8268,9 @@ p, li { white-space: pre-wrap; } - New Channel - 새 채널 + + Never + @@ -8434,7 +8281,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: @@ -8455,7 +8302,7 @@ p, li { white-space: pre-wrap; } - + Play @@ -8517,18 +8364,18 @@ p, li { white-space: pre-wrap; } 숨김 - + New 새 글 - + 0 0 - - + + Comment 답글 달기 @@ -8543,21 +8390,17 @@ p, li { white-space: pre-wrap; } - Loading - 불러오는 중 - - - + Loading... - + Comments - + Post @@ -8582,55 +8425,16 @@ p, li { white-space: pre-wrap; } 미디어 재생 - - GxsChannelPostsWidget - - Post to Channel - 채널에 게시하기 - - - Loading - 불러오는 중 - - - Title - 제목 - - - Search Title - 제목 검색 - - - No Channel Selected - 선택한 채널 없음 - - - Disable Auto-Download - 자동 다운로드 비활성화 - - - Enable Auto-Download - 자동 다운로드 활성화 - - - Feeds - 피드 - - - Description: - 설명: - - GxsChannelPostsWidgetWithModel - + Post to Channel 채널에 게시하기 - + Add new post @@ -8700,7 +8504,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -8736,7 +8540,7 @@ p, li { white-space: pre-wrap; } - + Comments 설명 @@ -8751,13 +8555,13 @@ p, li { white-space: pre-wrap; } 피드 - - + + Click to switch to list view - + Show unread posts only @@ -8772,7 +8576,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -8787,7 +8591,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -8847,12 +8651,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -8927,12 +8741,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed @@ -8983,17 +8798,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel 텍스트 레이블 - + Circle name: - + Accept @@ -9108,7 +8923,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container @@ -9121,7 +8936,7 @@ p, li { white-space: pre-wrap; } 양식 - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9151,7 +8966,7 @@ p, li { white-space: pre-wrap; } - + Comment 답글 달기 @@ -9190,7 +9005,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment @@ -9214,6 +9029,21 @@ p, li { white-space: pre-wrap; } Vote Down + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9223,7 +9053,7 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9252,7 +9082,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -9283,7 +9113,7 @@ before you can comment - + It remains %1 characters after HTML conversion. @@ -9334,7 +9164,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum @@ -9350,7 +9180,7 @@ before you can comment - + Expand 확장 @@ -9370,8 +9200,9 @@ before you can comment - Loading - 불러오는 중 + + TextLabel + 텍스트 레이블 @@ -9402,13 +9233,13 @@ before you can comment GxsForumMsgItem - - + + Subject: 제목: - + Unsubscribe To Forum @@ -9419,7 +9250,7 @@ before you can comment - + Expand 확장 @@ -9439,21 +9270,17 @@ before you can comment - Loading - 불러오는 중 - - - + Loading... - + Forum Feed - + Hide 숨김 @@ -9466,63 +9293,66 @@ before you can comment 양식 - + Start new Thread for Selected Forum - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums 포럼 검색 - Last Post - 최신 게시글 - - - + New Thread - - - Threaded View - - - - - Flat View - - - + Title 제목 - - + + Date 날짜 - + Author 작성자 - - Save image - - - - + Loading 불러오는 중 - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9532,12 +9362,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message @@ -9577,23 +9402,23 @@ before you can comment 작성자 검색 - + No name 이름 없음 - - + + Reply - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -9636,16 +9461,12 @@ before you can comment 레트로 쉐어 링크 복사 - + Hide 숨김 - Expand - 확장 - - - + [unknown] @@ -9675,8 +9496,8 @@ before you can comment - - + + Distribution @@ -9690,10 +9511,6 @@ before you can comment Anti-spam - - none - 없음 - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -9763,12 +9580,12 @@ before you can comment - + New thread - + Edit 편집 @@ -9829,7 +9646,7 @@ before you can comment - + Show column @@ -9849,7 +9666,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive @@ -9901,7 +9718,7 @@ This message is missing. You should receive it later. - + No result. @@ -9911,7 +9728,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -9926,7 +9743,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -9992,12 +9809,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums @@ -10028,23 +9845,16 @@ This message is missing. You should receive it later. - - GxsForumsFillThread - - Loading - 불러오는 중 - - GxsGroupDialog - + Name 이름 - + Key recipients can publish to restricted-type group and can view and publish for private-type channels @@ -10055,12 +9865,12 @@ This message is missing. You should receive it later. - + Description 설명 - + Message Distribution @@ -10068,7 +9878,7 @@ This message is missing. You should receive it later. - + Public 공용 @@ -10128,7 +9938,7 @@ This message is missing. You should receive it later. - + Comments: 설명: @@ -10151,7 +9961,7 @@ This message is missing. You should receive it later. - + All People @@ -10167,12 +9977,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -10189,23 +9999,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -10221,22 +10031,28 @@ This message is missing. You should receive it later. 이름을 입력해주십시오 - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo - + Submit Group Changes - + Owner: @@ -10246,12 +10062,12 @@ This message is missing. You should receive it later. - + Info 정보 - + ID ID @@ -10261,7 +10077,7 @@ This message is missing. You should receive it later. 최신 게시글 - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -10336,7 +10152,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity 인기도 @@ -10352,27 +10173,22 @@ This message is missing. You should receive it later. - + Created - + Cancel 취소 - + Create 만들기 - - Author - 작성자 - - - + GxsIdLabel @@ -10380,7 +10196,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading 불러오는 중 @@ -10440,7 +10256,7 @@ This message is missing. You should receive it later. - + Synchronise posts of last... @@ -10497,12 +10313,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link 레트로 쉐어 링크 복사 @@ -10525,7 +10341,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature @@ -10538,18 +10354,14 @@ This message is missing. You should receive it later. GxsIdDetails - Loading - 불러오는 중 - - - + Not found - - + + [Banned] @@ -10559,7 +10371,7 @@ This message is missing. You should receive it later. - + Loading... @@ -10569,7 +10381,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -10589,6 +10406,14 @@ This message is missing. You should receive it later. + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -10600,7 +10425,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -10648,17 +10473,13 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] GxsMessageFramePostWidget - - Loading - 불러오는 중 - Loading... @@ -11039,7 +10860,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -11055,7 +10876,7 @@ p, li { white-space: pre-wrap; } - + Authors @@ -11074,7 +10895,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -11148,7 +10969,7 @@ p, li { white-space: pre-wrap; } 양식 - + Add friend @@ -11158,7 +10979,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -11186,7 +11007,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -11196,7 +11017,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard @@ -11206,7 +11027,7 @@ private and secure decentralized communication platform. - + Send via Email @@ -11226,13 +11047,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -11244,12 +11089,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -11264,12 +11109,7 @@ new short format 레트로 쉐어 초대 - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... 다른 이름으로 저장... @@ -11534,14 +11374,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All 모두 - + Reputation @@ -11551,12 +11391,12 @@ p, li { white-space: pre-wrap; } 검색 - + Anonymous Id - + Create new Identity @@ -11566,7 +11406,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -11581,27 +11421,27 @@ p, li { white-space: pre-wrap; } - + Close 닫기 - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -11617,29 +11457,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles - + Circle name @@ -11659,18 +11509,20 @@ p, li { white-space: pre-wrap; } - + + Edit identity - + + Delete identity - + Chat with this peer @@ -11680,78 +11532,78 @@ p, li { white-space: pre-wrap; } - + Owner node ID : - + Identity name : - + () - + Identity ID - + Send message - + Identity info - + Identity ID : - + Owner node name : - + Create new... - + Type: 유형: - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: - + Negative - + Neutral @@ -11762,17 +11614,17 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous @@ -11787,24 +11639,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you - - + + My own identities - - + + My contacts - + Show Items @@ -11819,7 +11671,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -11829,7 +11686,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -11904,7 +11761,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -11934,7 +11791,7 @@ p, li { white-space: pre-wrap; } - + Invited @@ -11949,7 +11806,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle @@ -11997,7 +11854,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -12005,7 +11862,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -12048,7 +11905,7 @@ These identities will soon be not supported anymore. - + Boards @@ -12128,7 +11985,7 @@ These identities will soon be not supported anymore. - + information @@ -12144,17 +12001,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -12259,7 +12111,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -12309,21 +12161,21 @@ These identities will soon be not supported anymore. - - - + + + People - + Your Avatar Click here to change your avatar - + Linked to neighbor nodes @@ -12333,7 +12185,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -12348,7 +12200,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -12363,12 +12215,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -12388,12 +12240,12 @@ These identities will soon be not supported anymore. - + Owned by - + Node name: @@ -12403,7 +12255,7 @@ These identities will soon be not supported anymore. - + Really delete? @@ -12411,7 +12263,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname @@ -12441,7 +12293,13 @@ These identities will soon be not supported anymore. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity @@ -12455,7 +12313,7 @@ These identities will soon be not supported anymore. - + @@ -12465,7 +12323,12 @@ These identities will soon be not supported anymore. 없음 - + + No avatar chosen + + + + Edit identity @@ -12476,27 +12339,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -12516,7 +12379,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -12526,12 +12389,18 @@ These identities will soon be not supported anymore. - + Error KeyID invalid - + + + No Avatar chosen. A default image will be automatically displayed from your new identity. + + + + Import image @@ -12541,12 +12410,7 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. - - - - + Unknown GpgId @@ -12556,7 +12420,7 @@ These identities will soon be not supported anymore. - + Create New Identity @@ -12566,10 +12430,15 @@ These identities will soon be not supported anymore. 형식 - + Choose image... + + + Remove + 제거 + @@ -12595,7 +12464,7 @@ These identities will soon be not supported anymore. 추가 - + Create 만들기 @@ -12605,13 +12474,13 @@ These identities will soon be not supported anymore. 취소 - + Your Avatar Click here to change your avatar - + Linked to your profile @@ -12621,7 +12490,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -12695,7 +12564,7 @@ These identities will soon be not supported anymore. - + Copy 복사하기 @@ -12705,12 +12574,12 @@ These identities will soon be not supported anymore. 제거 - + %1 's Message History - + Mark all @@ -12729,26 +12598,38 @@ These identities will soon be not supported anymore. Quote - - Send - 보내기 - ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -12766,27 +12647,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: - + Listen Address: - + + Status: + 상태: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -12807,7 +12693,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -12816,26 +12707,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File - + Open Folder - + Checking... @@ -12845,7 +12741,7 @@ These identities will soon be not supported anymore. - + Recommend in a message to... @@ -12873,7 +12769,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend @@ -12889,7 +12785,8 @@ These identities will soon be not supported anymore. - + + Options 옵션 @@ -12910,7 +12807,7 @@ These identities will soon be not supported anymore. - + Quit @@ -12921,12 +12818,12 @@ These identities will soon be not supported anymore. - + RetroShare %1 a secure decentralized communication platform - + Unfinished @@ -12955,11 +12852,12 @@ These identities will soon be not supported anymore. + Status 상태 - + Notify @@ -12970,31 +12868,35 @@ These identities will soon be not supported anymore. + Open Messages - + + Bandwidth Graph - + Applications + Help 도움말 - + + Minimize - + Maximize @@ -13009,7 +12911,12 @@ These identities will soon be not supported anymore. 레트로 쉐어 - + + Close window + + + + %1 new message @@ -13039,7 +12946,7 @@ These identities will soon be not supported anymore. - + Do you really want to exit RetroShare ? 정말로 레트로 쉐어를 나가시겠습니까? @@ -13059,7 +12966,7 @@ These identities will soon be not supported anymore. 표시 - + Make sure this link has not been forged to drag you to a malicious website. @@ -13104,12 +13011,13 @@ These identities will soon be not supported anymore. - + + Statistics - + Show web interface @@ -13124,7 +13032,7 @@ These identities will soon be not supported anymore. - + Really quit ? @@ -13133,17 +13041,17 @@ These identities will soon be not supported anymore. MessageComposer - + Compose - + Contacts - + Paragraph @@ -13179,12 +13087,12 @@ These identities will soon be not supported anymore. - + Font size - + Increase font size @@ -13199,32 +13107,32 @@ These identities will soon be not supported anymore. 굵게 - + Italic 기울임 - + Alignment - + Add an Image - + Sets text font to code style - + Underline 밑줄 - + Subject: 제목: @@ -13235,32 +13143,32 @@ These identities will soon be not supported anymore. - + Tags - + Address list: - + Recommend this friend - + Set Text color - + Set Text background color - + Recommended Files @@ -13330,7 +13238,7 @@ These identities will soon be not supported anymore. - + Send To: @@ -13370,7 +13278,7 @@ These identities will soon be not supported anymore. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> @@ -13390,18 +13298,18 @@ These identities will soon be not supported anymore. 레트로 쉐어에서 여러분과 친구가 되고 싶어합니다. - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team - - + + Save Message - + Message has not been Sent. Do you want to save message to draft box? @@ -13412,7 +13320,17 @@ Do you want to save message to draft box? 레트로 쉐어 링크 붙여넣기 - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" @@ -13432,7 +13350,7 @@ Do you want to save message to draft box? - + Original Message @@ -13442,21 +13360,21 @@ Do you want to save message to draft box? 보낸이 - + - + To - - + + Cc - + Sent @@ -13471,7 +13389,7 @@ Do you want to save message to draft box? - + Re: @@ -13481,30 +13399,30 @@ Do you want to save message to draft box? - - - + + + RetroShare 레트로 쉐어 - + Do you want to send the message without a subject ? 제목 없이 메시지를 보내시겠습니까? - + Please insert at least one recipient. - + Bcc - + Unknown 알 수 없음 @@ -13619,13 +13537,13 @@ Do you want to save message to draft box? - + Open File... - + HTML-Files (*.htm *.html);;All Files (*) @@ -13645,7 +13563,7 @@ Do you want to save message to draft box? - + Message has not been Sent. Do you want to save message ? @@ -13666,7 +13584,7 @@ Do you want to save message ? 추가 파일 추가 - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -13696,18 +13614,18 @@ Do you want to save message ? - - + + Close 닫기 - + From: 어디에서 : - + Bullet list (disc) @@ -13747,13 +13665,13 @@ Do you want to save message ? - - + + Thanks, <br> - + Distant identity: @@ -13763,12 +13681,12 @@ Do you want to save message ? - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -13846,7 +13764,7 @@ Do you want to save message ? 기본값 - + A new tab @@ -13856,7 +13774,7 @@ Do you want to save message ? - + Edit Tag @@ -13879,7 +13797,7 @@ Do you want to save message ? MessageToaster - + Sub: @@ -13887,7 +13805,7 @@ Do you want to save message ? MessageUserNotify - + Message @@ -13915,7 +13833,7 @@ Do you want to save message ? MessageWidget - + Recommended Files @@ -13925,37 +13843,37 @@ Do you want to save message ? - + Subject: 제목: - + From: 어디에서 : - + To: 어디로 : - + Cc: - + Bcc: - + Tags: - + Reply @@ -13995,7 +13913,7 @@ Do you want to save message ? - + Send Invite @@ -14047,7 +13965,7 @@ Do you want to save message ? - + Confirm %1 as friend @@ -14057,12 +13975,12 @@ Do you want to save message ? - + View source - + No subject 제목 없음 @@ -14072,17 +13990,22 @@ Do you want to save message ? 다운로드 - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -14091,14 +14014,24 @@ Do you want to save message ? %1 (%2) + + + Show less + + + + + Show more + + - + Download all - + Print Document @@ -14113,12 +14046,12 @@ Do you want to save message ? - + Load images always for this message - + Hide the attachment pane @@ -14140,10 +14073,6 @@ Do you want to save message ? Compose - - Delete - 삭제 - Print @@ -14222,7 +14151,7 @@ Do you want to save message ? MessagesDialog - + New Message @@ -14232,24 +14161,16 @@ Do you want to save message ? - Delete - 삭제 - - - Display - 표시 - - - + - - + + Tags - - + + Inbox @@ -14279,17 +14200,17 @@ Do you want to save message ? - + Total Inbox: - + Quick View - + Print... @@ -14320,7 +14241,7 @@ Do you want to save message ? - + Subject 제목 @@ -14330,7 +14251,7 @@ Do you want to save message ? 보낸이 - + Date 날짜 @@ -14340,11 +14261,7 @@ Do you want to save message ? - Click to sort by subject - 제목별로 정렬하려면 누르십시오 - - - + Search Subject 제목 검색 @@ -14353,6 +14270,16 @@ Do you want to save message ? Search From + + + To + + + + + Search To + + Search Date @@ -14379,12 +14306,12 @@ Do you want to save message ? - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred @@ -14460,7 +14387,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -14474,7 +14401,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -14489,18 +14416,28 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts - + No Box selected. - + @@ -14535,7 +14472,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -14589,7 +14536,7 @@ Do you want to save message ? - + Expand 확장 @@ -14599,7 +14546,7 @@ Do you want to save message ? 항목 제거 - + from @@ -14634,7 +14581,7 @@ Do you want to save message ? - + Hide 숨김 @@ -14775,7 +14722,7 @@ Do you want to save message ? 동료 ID - + Remove unused keys... @@ -14785,7 +14732,7 @@ Do you want to save message ? - + Clean keyring @@ -14799,7 +14746,13 @@ Notes: Your old keyring will be backed up. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info @@ -14832,18 +14785,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. - - - Export/create a new node - - Trusted keys only - + Search name @@ -14853,12 +14801,12 @@ For security, your keyring was previously backed-up to file - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -14891,7 +14839,7 @@ Reported error: NewFriendList - + Offline Friends @@ -14912,7 +14860,7 @@ Reported error: - + Groups @@ -14942,19 +14890,19 @@ Reported error: - - + + Search 검색 - + ID ID - + Search ID @@ -14964,12 +14912,12 @@ Reported error: - + Show Items - + Last contact @@ -14979,7 +14927,7 @@ Reported error: - + Group @@ -15094,7 +15042,7 @@ Reported error: - + Do you want to remove this node? @@ -15104,7 +15052,7 @@ Reported error: - + Done! @@ -15211,7 +15159,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -15226,7 +15174,7 @@ at least one peer was not added to a group - + Newest on top @@ -15236,12 +15184,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15470,10 +15418,6 @@ at least one peer was not added to a group Disable All Toaster temporarily - - Feed - 피드 - Systray @@ -15483,7 +15427,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -15503,12 +15447,12 @@ at least one peer was not added to a group - + Please enter your Retroshare passphrase - + Unregistered plugin/executable @@ -15523,7 +15467,7 @@ at least one peer was not added to a group - + Test 시험 @@ -15534,17 +15478,19 @@ at least one peer was not added to a group + Unknown title - + + Encrypted message - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -15552,7 +15498,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online @@ -15691,7 +15637,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -15736,12 +15687,7 @@ p, li { white-space: pre-wrap; } 서명 포함 - - Options - 옵션 - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -15787,21 +15733,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare Retroshare (뒤에몫) - - + + Error : cannot get peer details. 오류 : 동료 세부 정보를 가져올 수 없습니다 - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) @@ -15819,7 +15765,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -15888,10 +15834,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Check the password! - - Maybe password is wrong - 비밀번호가 잘못된 것 같습니다 - You haven't set a trust level for this key. @@ -15899,12 +15841,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -15930,7 +15872,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat 대화 @@ -15951,7 +15893,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.항목 제거 - + Name: 이름: @@ -15991,7 +15933,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message 메시지 작성 @@ -16049,7 +15991,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.숨김 - + Send Message @@ -16216,13 +16158,6 @@ Warning: In your File-Transfer option, you select allow direct download to No. - - PhotoCommentItem - - Form - 양식 - - PhotoDialog @@ -16235,14 +16170,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.TextLabel 텍스트 레이블 - - Comment - 답글 달기 - - - Summary - 요약 - Album / Photo Name @@ -16303,10 +16230,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.... ... - - Add Comment - 설명 추가 - Album @@ -16386,17 +16309,17 @@ p, li { white-space: pre-wrap; } - + My Albums - + Subscribed Albums - + Shared Albums @@ -16425,7 +16348,7 @@ requesting to edit it! PhotoSlideShow - + Album Name @@ -16484,19 +16407,19 @@ requesting to edit it! - - + + TextLabel 텍스트 레이블 - + Posted by - + ago @@ -16532,12 +16455,12 @@ requesting to edit it! PluginItem - + TextLabel 텍스트 레이블 - + Show more details about this plugin @@ -16748,12 +16671,27 @@ p, li { white-space: pre-wrap; } - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -16806,7 +16744,7 @@ p, li { white-space: pre-wrap; } - + Vote up @@ -16826,8 +16764,8 @@ p, li { white-space: pre-wrap; } - - + + Comments 설명 @@ -16852,13 +16790,13 @@ p, li { white-space: pre-wrap; } - - + + Comment 답글 달기 - + Comments @@ -16886,12 +16824,12 @@ p, li { white-space: pre-wrap; } PostedCreatePostDialog - + Create a new Post - + RetroShare Retroshare (뒤에몫) @@ -16906,12 +16844,22 @@ p, li { white-space: pre-wrap; } - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File 그림 파일 불러오기 - + Post image @@ -16927,7 +16875,17 @@ p, li { white-space: pre-wrap; } - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -16937,7 +16895,7 @@ p, li { white-space: pre-wrap; } - + Please add a Title @@ -16957,12 +16915,22 @@ p, li { white-space: pre-wrap; } - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -16977,7 +16945,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -16988,7 +16956,7 @@ p, li { white-space: pre-wrap; } - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -16998,7 +16966,7 @@ p, li { white-space: pre-wrap; } 제목 - + Link @@ -17006,12 +16974,12 @@ p, li { white-space: pre-wrap; } PostedDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -17045,7 +17013,7 @@ p, li { white-space: pre-wrap; } PostedGroupDialog - + Create New Board @@ -17083,7 +17051,17 @@ p, li { white-space: pre-wrap; } PostedGroupItem - + + Last activity + + + + + TextLabel + 텍스트 레이블 + + + Subscribe to Posted @@ -17099,7 +17077,7 @@ p, li { white-space: pre-wrap; } - + Expand 확장 @@ -17114,16 +17092,17 @@ p, li { white-space: pre-wrap; } - Loading - 불러오는 중 - - - + Loading... - + + Never + + + + New Board @@ -17136,18 +17115,18 @@ p, li { white-space: pre-wrap; } PostedItem - + 0 0 - - + + Comments 설명 - + Copy RetroShare Link 레트로 쉐어 링크 복사 @@ -17158,12 +17137,12 @@ p, li { white-space: pre-wrap; } - + Comment 답글 달기 - + Comments @@ -17173,7 +17152,7 @@ p, li { white-space: pre-wrap; } - + Click to view Picture @@ -17183,17 +17162,17 @@ p, li { white-space: pre-wrap; } 숨김 - + Vote up - + Vote down - + Set as read and remove item 항목을 읽음으로 설정하고 제거 @@ -17203,7 +17182,7 @@ p, li { white-space: pre-wrap; } 새 글 - + New Comment: @@ -17213,7 +17192,7 @@ p, li { white-space: pre-wrap; } - + Name 이름 @@ -17254,34 +17233,11 @@ p, li { white-space: pre-wrap; } 텍스트 레이블 - + Loading 불러오는 중 - - PostedListWidget - - Form - 양식 - - - New - 새 글 - - - Next - 다음 - - - RetroShare - Retroshare (뒤에몫) - - - Previous - 이전 - - PostedListWidgetWithModel @@ -17300,7 +17256,17 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -17310,15 +17276,15 @@ p, li { white-space: pre-wrap; } - + - + unknown - + Distribution: @@ -17328,42 +17294,42 @@ p, li { white-space: pre-wrap; } - + Created - + TextLabel 텍스트 레이블 - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -17383,7 +17349,7 @@ p, li { white-space: pre-wrap; } - + Search 검색 @@ -17413,17 +17379,17 @@ p, li { white-space: pre-wrap; } - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -17438,12 +17404,17 @@ p, li { white-space: pre-wrap; } - + Copy RetroShare Link 레트로 쉐어 링크 복사 - + + Copy http Link + + + + Show author in People tab @@ -17453,27 +17424,31 @@ p, li { white-space: pre-wrap; } 편집 - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -17488,7 +17463,7 @@ p, li { white-space: pre-wrap; } 가입 - + Never @@ -17562,6 +17537,16 @@ p, li { white-space: pre-wrap; } No Channel Selected 선택한 채널 없음 + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -17651,16 +17636,16 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -17768,7 +17753,7 @@ and use the import button to load it ProfileWidget - + Edit status message @@ -17784,7 +17769,7 @@ and use the import button to load it - + Public Information @@ -17819,12 +17804,12 @@ and use the import button to load it - + Other Information - + My Address @@ -17868,27 +17853,27 @@ and use the import button to load it PulseAddDialog - + Add to Pulse - + Display As - + URL - + GroupLabel - + IDLabel @@ -17898,12 +17883,12 @@ and use the import button to load it 어디에서 : - + Head - + Head Shot @@ -17933,13 +17918,13 @@ and use the import button to load it - - + + Whats happening? - + @@ -17951,12 +17936,22 @@ and use the import button to load it - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -17971,7 +17966,7 @@ and use the import button to load it - + Reply to Pulse @@ -17986,34 +17981,24 @@ and use the import button to load it - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - 보낸이 - - - Date - 날짜 - - - ... - ... + + Load Picture File + 그림 파일 불러오기 @@ -18024,7 +18009,7 @@ and use the import button to load it 양식 - + @@ -18043,7 +18028,7 @@ and use the import button to load it PulseReply - + icn @@ -18053,7 +18038,7 @@ and use the import button to load it - + REPLY @@ -18080,7 +18065,7 @@ and use the import button to load it - + FOLLOW @@ -18090,7 +18075,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -18110,7 +18095,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -18226,7 +18211,7 @@ and use the import button to load it - + FOLLOW @@ -18234,37 +18219,42 @@ and use the import button to load it PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -18296,7 +18286,7 @@ and use the import button to load it - + FOLLOW @@ -18304,8 +18294,8 @@ and use the import button to load it QObject - - + + Confirmation @@ -18573,12 +18563,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + File Request canceled - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. @@ -18609,7 +18599,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace 예상치 못한 오류가 발생했습니다. 'RsInit::InitRetroShare unexpexted return code %1' 을 보고해 주십시오. - + Cannot start Tor Manager! @@ -18643,7 +18633,7 @@ The error reported is:" - + Multiple instances @@ -18664,6 +18654,26 @@ The error reported is:" + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -18743,7 +18753,7 @@ Reported error is: - + You appear to have nodes associated to DSA keys: @@ -18753,7 +18763,7 @@ Reported error is: - + enabled @@ -18763,7 +18773,7 @@ Reported error is: - + Move IP %1 to whitelist @@ -18779,7 +18789,7 @@ Reported error is: - + %1 seconds ago @@ -18846,7 +18856,7 @@ Security: no anonymous IDs - + Join chat room @@ -18874,7 +18884,7 @@ Security: no anonymous IDs - + Indefinitely @@ -19054,13 +19064,29 @@ Security: no anonymous IDs Ban list + + + Name + 이름 + + Node + + + + + Address + + + + + Status 상태 - + NXS @@ -19303,6 +19329,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -19442,7 +19480,7 @@ p, li { white-space: pre-wrap; } - + Network Wide @@ -19609,7 +19647,7 @@ p, li { white-space: pre-wrap; } 양식 - + The loading of embedded images is blocked. @@ -19622,7 +19660,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default @@ -19795,12 +19833,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -19808,12 +19856,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -20501,7 +20549,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name 이름 @@ -20622,7 +20670,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name 이름 @@ -20642,7 +20690,7 @@ If you believe it is correct, remove the corresponding line from the file and re - + Profile ID @@ -20698,7 +20746,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -20712,11 +20760,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - - RsMessageModel @@ -20730,6 +20773,11 @@ prevents the message to be forwarded to your friends. From 보낸이 + + + To + + Subject @@ -20752,12 +20800,17 @@ prevents the message to be forwarded to your friends. - Click to sort by read + Click to sort by read status - Click to sort by from + Click to sort by author + + + + + Click to sort by destination @@ -20781,7 +20834,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -20802,7 +20857,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. 저장한 모든 레트로 쉐어 설정을 초기화합니다. @@ -20863,7 +20918,7 @@ prevents the message to be forwarded to your friends. 레트로 쉐어 언어를 설정합니다. - + Unable to open log file '%1': %2 @@ -20884,7 +20939,7 @@ prevents the message to be forwarded to your friends. - + opmode @@ -20914,7 +20969,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -20932,7 +20987,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -20949,12 +21004,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) - + Start Search @@ -21015,7 +21070,7 @@ prevents the message to be forwarded to your friends. - + KeyWords @@ -21030,7 +21085,7 @@ prevents the message to be forwarded to your friends. - + Filename @@ -21130,23 +21185,23 @@ prevents the message to be forwarded to your friends. - + File Name - + Download 다운로드 - + Copy RetroShare Link 레트로 쉐어 링크 복사 - + Send RetroShare Link 레트로 쉐어 링크 보내기 @@ -21156,7 +21211,7 @@ prevents the message to be forwarded to your friends. - + Download Notice 다운로드 @@ -21193,7 +21248,7 @@ prevents the message to be forwarded to your friends. - + Folder 폴더 @@ -21204,17 +21259,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) 새 레트로 쉐어 링크 만들기 - + Open Folder - + Create Collection... @@ -21234,7 +21289,7 @@ prevents the message to be forwarded to your friends. - + Collection @@ -21242,7 +21297,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details @@ -21258,22 +21313,22 @@ prevents the message to be forwarded to your friends. 항목 제거 - + IP address: - + Peer ID: - + Location: 지역: - + Peer Name: @@ -21290,7 +21345,7 @@ prevents the message to be forwarded to your friends. 숨김 - + but reported: @@ -21315,8 +21370,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -21324,7 +21379,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare 레트로 쉐어에서 여러분을 친구로 삼고 싶어합니다 @@ -21355,7 +21410,7 @@ prevents the message to be forwarded to your friends. - + Expand 확장 @@ -21400,12 +21455,12 @@ prevents the message to be forwarded to your friends. 상태: - + Write Message 메시지 작성 - + Connect Attempt @@ -21425,17 +21480,12 @@ prevents the message to be forwarded to your friends. - + Unknown Security Issue - - A unknown peer - - - - + Unknown 알 수 없음 @@ -21445,7 +21495,17 @@ prevents the message to be forwarded to your friends. - + + SSL request + + + + + An unknown peer + + + + Hide 숨김 @@ -21455,7 +21515,7 @@ prevents the message to be forwarded to your friends. - + Certificate has wrong signature!! This peer is not who he claims to be. @@ -21465,12 +21525,12 @@ prevents the message to be forwarded to your friends. - + Certificate caused an internal error. - + Peer/node not in friendlist (PGP id= @@ -21529,12 +21589,12 @@ prevents the message to be forwarded to your friends. - + Local Address 지역 주소 - + NAT @@ -21555,22 +21615,22 @@ prevents the message to be forwarded to your friends. - + Local network - + External ip address finder - + UPnP - + Known / Previous IPs: @@ -21583,21 +21643,16 @@ behind a firewall or a VPN. - - Allow RetroShare to ask my ip to these websites: - 이 웹사이트에서의 내 아이피 요청을 레트로 쉐어가 허용합니다: - - - - - + + + kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -21607,23 +21662,46 @@ behind a firewall or a VPN. - + Onion Address - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -21633,7 +21711,7 @@ behind a firewall or a VPN. - + I2P Address @@ -21658,37 +21736,95 @@ behind a firewall or a VPN. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -21703,71 +21839,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -21777,22 +21849,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -21804,12 +21861,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -21819,7 +21876,7 @@ Also check your ports! - + Download limit (KB/s) @@ -21834,23 +21891,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -21861,17 +21918,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -21881,12 +21928,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -21896,17 +21938,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 127.0.0.1 - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -21946,7 +21978,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start @@ -21961,12 +21993,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - BOB status - - - - + Incoming @@ -22002,7 +22029,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -22057,7 +22109,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Warning: This bandwidth adds up to the max bandwidth. @@ -22082,7 +22134,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -22094,7 +22146,7 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Filters @@ -22117,7 +22169,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status 상태 @@ -22177,17 +22229,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -22203,18 +22266,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -22249,12 +22312,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -22277,22 +22340,22 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -22327,7 +22390,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -22337,12 +22400,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -22422,7 +22485,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with @@ -22432,12 +22495,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Share - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -22456,7 +22519,7 @@ Select the Friends with which you want to Share your Channel. - + Shared directory @@ -22476,17 +22539,17 @@ Select the Friends with which you want to Share your Channel. - + Add new - + Cancel 취소 - + Add a Share Directory @@ -22496,7 +22559,7 @@ Select the Friends with which you want to Share your Channel. 제거 - + Apply and close @@ -22587,7 +22650,7 @@ Select the Friends with which you want to Share your Channel. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. @@ -22595,7 +22658,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files @@ -22646,11 +22709,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files - + Download selected @@ -22660,7 +22728,7 @@ Select the Friends with which you want to Share your Channel. 다운로드 - + Copy retroshare Links to Clipboard 레트로 쉐어 링크를 클립보드에 복사 @@ -22675,7 +22743,7 @@ Select the Friends with which you want to Share your Channel. 레트로 쉐어 링크 보내기 - + Some files have been omitted @@ -22691,7 +22759,7 @@ Select the Friends with which you want to Share your Channel. - + Create Collection... @@ -22716,7 +22784,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted because they have not been indexed yet. @@ -22859,12 +22927,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration - + Create interface @@ -22888,7 +22956,7 @@ Select the Friends with which you want to Share your Channel. - + Log In 로그인 @@ -23227,7 +23295,7 @@ This choice can be reverted in settings. - + Message: @@ -23464,7 +23532,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags @@ -23500,12 +23568,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown 알 수 없음 @@ -23515,18 +23586,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -23536,12 +23602,57 @@ p, li { white-space: pre-wrap; } - + + Error + + + + + Not connected + + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -23549,7 +23660,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -23559,7 +23670,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -23570,11 +23681,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -23602,7 +23714,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options @@ -23613,7 +23725,7 @@ p, li { white-space: pre-wrap; } - + Shared Directories @@ -23623,22 +23735,27 @@ p, li { white-space: pre-wrap; } - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -23723,7 +23840,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -23732,7 +23849,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -23757,7 +23879,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming @@ -23822,12 +23949,7 @@ p, li { white-space: pre-wrap; } - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -23837,7 +23959,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -23865,7 +23997,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed @@ -23893,19 +24025,19 @@ p, li { white-space: pre-wrap; } TransfersDialog - - + + Downloads - + Uploads - + Name i.e: file name 이름 @@ -24112,7 +24244,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... @@ -24137,7 +24274,7 @@ p, li { white-space: pre-wrap; } - + Anonymous end-to-end encrypted tunnel 0x @@ -24158,7 +24295,7 @@ p, li { white-space: pre-wrap; } Retroshare (뒤에몫) - + @@ -24191,7 +24328,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name @@ -24206,7 +24353,7 @@ p, li { white-space: pre-wrap; } - + Expand all @@ -24333,23 +24480,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns - + File Transfers - + Path 경로 @@ -24359,7 +24501,7 @@ p, li { white-space: pre-wrap; } - + Could not delete preview file @@ -24369,7 +24511,7 @@ p, li { white-space: pre-wrap; } - + Create Collection... @@ -24384,7 +24526,7 @@ p, li { white-space: pre-wrap; } - + Collection @@ -24394,7 +24536,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x @@ -24808,12 +24950,17 @@ p, li { white-space: pre-wrap; } 양식 - + Enable Retroshare WEB Interface - + + Status: + 상태: + + + Web parameters @@ -24853,17 +25000,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -24873,12 +25030,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface @@ -25015,7 +25172,7 @@ p, li { white-space: pre-wrap; } - + Page Name @@ -25030,7 +25187,7 @@ p, li { white-space: pre-wrap; } - + << @@ -25118,7 +25275,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History @@ -25153,7 +25310,7 @@ p, li { white-space: pre-wrap; } - + \/ @@ -25183,14 +25340,18 @@ p, li { white-space: pre-wrap; } - - + + History + 기록 + + + Show Edit History - + Status 상태 @@ -25211,7 +25372,7 @@ p, li { white-space: pre-wrap; } - + Submit @@ -25294,16 +25455,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - - - - + Settings @@ -25318,7 +25470,7 @@ p, li { white-space: pre-wrap; } - + Who to Follow @@ -25338,7 +25490,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -25368,25 +25520,17 @@ p, li { white-space: pre-wrap; } - New - 새 피드 - - - + Yourself - - Friends - 친구 - Following - + RetroShare @@ -25449,35 +25593,42 @@ p, li { white-space: pre-wrap; } 양식 - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + 제거 + + + Location: 지역: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -25522,11 +25673,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + 없음 + + + + Following + + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) 알 수 없음 @@ -25604,7 +25785,7 @@ p, li { white-space: pre-wrap; } - + k e.g: 3.1 k @@ -25641,7 +25822,7 @@ p, li { white-space: pre-wrap; } pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_nl.ts b/retroshare-gui/src/lang/retroshare_nl.ts index c59474c60..bb4fef66a 100644 --- a/retroshare-gui/src/lang/retroshare_nl.ts +++ b/retroshare-gui/src/lang/retroshare_nl.ts @@ -84,13 +84,6 @@ - - AddCommentDialog - - Add Comment - Een opmerking toevoegen - - AddFileAssociationDialog @@ -128,12 +121,12 @@ RetroShare: Geavanceerd Zoeken - + Search Criteria Zoek Criteria - + Add a further search criterion. Voeg een volgend zoek criterium toe @@ -143,7 +136,7 @@ Reset de zoekopdracht - + Cancels the search. Annuleer de zoekopdracht @@ -163,177 +156,6 @@ Zoeken - - AlbumCreateDialog - - Create Album - Maak album - - - Album Name: - Album Naam: - - - Category: - Categorie: - - - Animals - Beesten - - - Family - Familie - - - Friends - Vrienden - - - Flowers - Bloemen - - - Holiday - Vakantie - - - Landscapes - Landschappen - - - Pets - Huisdieren - - - Portraits - Portretten - - - Travel - Reizen - - - Work - Werk - - - Random - Willekeurig - - - Caption: - Onderschrift: - - - Where: - Waar: - - - Photographer: - Fotograaf - - - Description: - Beschrijving - - - Share Options - Deel Opties - - - Policy: - Beleid: - - - Quality: - Kwaliteit - - - Comments: - Opmerkingen: - - - Identity: - Identiteit: - - - Public - Publiek - - - Restricted - Beperkt - - - Resize Images (< 1Mb) - Resize Images (< 1Mb) - - - Resize Images (< 10Mb) - Resize Images (< 10Mb) - - - Send Original Images - Stuur de originele plaatjes - - - No Comments Allowed - Geen opmerkingen toegestaan - - - Authenticated Comments - Toegevoegde opmerkingen - - - Any Comments Allowed - Opmerkingen toegestaan - - - Publish with Identity - Publiceer met de identiteit - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">⏎ -<html><head><meta name="qrichtext" content="1" /><style type="text/css">⏎ -p, li { white-space: pre-wrap; }⏎ -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">⏎ -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Sleep &amp; laat los om plaatjes in te voegen. Klik op een plaatje om de gegevens eronder te bewerken.</span></p></body></html> - - - Back - Terug - - - Add Photos - Foto's toevoegen - - - Publish Album - Publiceer Album - - - Untitle Album - Verwijder Album Titel - - - Say something about this album... - Vertel iets over dit album... - - - Where were these taken? - Waar zijn deze genomen? - - - Load Album Thumbnail - Laad album miniatuur - - AlbumDialog @@ -342,19 +164,11 @@ p, li { white-space: pre-wrap; }⏎ Album Album - - Album Thumbnail - Album miniatuur - TextLabel Tekst label - - Summary - Overzicht - Album Title: @@ -370,34 +184,6 @@ p, li { white-space: pre-wrap; }⏎ Caption Onderschrift - - Where: - Waar: - - - When - Wanneer - - - Description: - Beschrijving: - - - Share Options - Deel Opties - - - Comments - Opmerkingen - - - Publish Identity - Publiceer Identiteit - - - Visibility - Zichtbaarheid - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -766,7 +552,7 @@ p, li { white-space: pre-wrap; }⏎ RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. Waarschuwing: Deze service is experimenteel. Help ons door dit te testen.⏎ @@ -782,14 +568,6 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update Circles Cirkels - - GxsForums - GxsForums - - - GxsChannels - GxsKanalen - The Wire @@ -801,10 +579,23 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update Foto 's + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb %p Kb @@ -841,17 +632,13 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update Browse... - - Add Avatar - Avatar toevoegen - Remove Verwijderen - + Set your Avatar picture Uw Avatar afbeelding instellen @@ -870,10 +657,6 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - Laad Avatar - AvatarWidget @@ -942,22 +725,10 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update Opnieuw instellen - Receive Rate - Ontvang ranglijst - - - Send Rate - Verzend ranglijst - - - + Always on Top Altijd op de voorgrond - - Style - Stijl - Changes the transparency of the Bandwidth Graph @@ -973,23 +744,11 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update % Opaque Ondoorzichtig - - Save - Opslaan - - - Cancel - Annuleren - Since: Sinds - - Hide Settings - Verberg instellingen - BandwidthStatsWidget @@ -1062,7 +821,7 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update BoardPostDisplayWidgetBase - + Comment @@ -1092,12 +851,12 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update Kopieer RetroShare Link - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -1105,7 +864,7 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update BoardPostDisplayWidget_card - + Vote up Stemmen van @@ -1125,7 +884,7 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update \/ - + Posted by @@ -1163,7 +922,7 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update BoardPostDisplayWidget_compact - + Vote up Stemmen van @@ -1183,7 +942,7 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update \/ - + Click to view picture @@ -1213,7 +972,7 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update - + Toggle Message Read Status Verander boodschap gelezen status @@ -1223,7 +982,7 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update Nieuw - + TextLabel Tekst label @@ -1231,12 +990,12 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update BoardsCommentsItem - + I like this Ik vind dit leuk! - + 0 0 @@ -1256,18 +1015,18 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update Avatar - + New Comment - + Copy RetroShare Link Kopieer RetroShare Link - + Expand Uitbreiden @@ -1282,12 +1041,12 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update Item verwijderen - + Name Naam - + Comm value @@ -1456,17 +1215,17 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update ChannelPage - + Channels Kanalen - + Tabs Tabbladen - + General Algemeen @@ -1476,11 +1235,17 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update - Load posts in background (Thread) - Laad berichten op achtergrond (draad) + + Downloads + Downloads - + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab Elk kanaal in een nieuw tabblad openen @@ -1488,7 +1253,7 @@ Maar onthoudt: Elke data hier *ZAL* verloren gaan als de protocollen een update ChannelPostDelegate - + files @@ -1511,7 +1276,7 @@ into the image, so as to ChannelsCommentsItem - + I like this Ik vind dit leuk! @@ -1536,18 +1301,18 @@ into the image, so as to Avatar - + New Comment - + Copy RetroShare Link Kopieer RetroShare Link - + Expand Uitbreiden @@ -1562,7 +1327,7 @@ into the image, so as to Item verwijderen - + Name Naam @@ -1572,17 +1337,7 @@ into the image, so as to - - Comment - - - - - Comments - - - - + Hide @@ -1590,7 +1345,7 @@ into the image, so as to ChatLobbyDialog - + Name Naam @@ -1781,7 +1536,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby Toon chat Portaal @@ -1793,22 +1548,6 @@ into the image, so as to Chats - - You have %1 new messages - U heeft %1 nieuwe berichten - - - You have %1 new message - U heeft %1 nieuw bericht - - - %1 new messages - %1 nieuwe berichten - - - %1 new message - %1 nieuw bericht - You have %1 mentions @@ -1830,13 +1569,14 @@ into the image, so as to - + + Unknown Lobby Onbekende Lobby - - + + Remove All Verwijder alles @@ -1844,13 +1584,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Naam - + Count Count @@ -1860,29 +1600,7 @@ into the image, so as to Onderwerp - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - - - - - - Public chat rooms - - - - + Create chat room @@ -1892,7 +1610,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1949,12 +1667,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1964,31 +1682,31 @@ Double click a chat room to enter and chat. - Create chat lobby - Maak een nieuw chat Portaal - - - + [No topic provided] [Geen onderwerp ingevoerd] - Selected lobby info - Gekozen portaal gegevens - - - + + Private Prive - + + + Public Publiek - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted @@ -1998,42 +1716,25 @@ Double click a chat room to enter and chat. Niet Automatisch Abonneren - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe Automatisch Abonneren - + Search Chat lobbies Zoek Chat lobby 's - + Search Name Zoek Naam - Subscribed - Geabonneerd - - - + Columns Kolommen - - Yes - Ja - - - No - Nee - Chat rooms @@ -2045,47 +1746,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: Onderwerp: - + Type: Type - + Security: Beveiliging - + Peers: Verbindingen: - - - - - - + + + + + + TextLabel Tekst label @@ -2100,13 +1801,24 @@ Double click a chat room to enter and chat. - + Show Toon - + + Private Subscribed + + + + + + Public Subscribed + + + + column @@ -2120,7 +1832,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item Item verwijderen @@ -2165,7 +1877,7 @@ Double click a chat room to enter and chat. ChatPage - + General Algemeen @@ -2180,19 +1892,7 @@ Double click a chat room to enter and chat. - Chat Settings - Chat instellingen - - - Enable Emoticons Private Chat - Inschakelen Emoticons Privé Chat - - - Enable Emoticons Group Chat - Inschakelen Emoticons Groep Chat - - - + Enable custom fonts Activeer eigen lettertype @@ -2212,7 +1912,7 @@ Double click a chat room to enter and chat. Activeer "Schuin" - + General settings @@ -2237,11 +1937,7 @@ Double click a chat room to enter and chat. Ingesloten afbeeldingen laden - Chat Lobby - Chat portaal - - - + Blink tab icon Knipper "tab" ikoon @@ -2250,10 +1946,6 @@ Double click a chat room to enter and chat. Do not send typing notifications - - Private Chat - Privé Chat - Open Window for new chat @@ -2275,11 +1967,7 @@ Double click a chat room to enter and chat. Knipper "scherm/tab" ikoon - Chat Font - Chat Font - - - + Change Chat Font Verander de Chat Font @@ -2289,14 +1977,10 @@ Double click a chat room to enter and chat. Chat Font: - + History Geschiedenis - - Style - Stijl - @@ -2311,17 +1995,13 @@ Double click a chat room to enter and chat. Variant: - - Group chat - Groeps chat - Private chat Privé Chat - + Choose your default font for Chat. @@ -2385,22 +2065,28 @@ Double click a chat room to enter and chat. <html><head/><body><p align="justify">In this tab you can setup how many chat messages Retroshare will keep saved on the disc and how much of the previous conversation it will display, for the different chat systems. The max storage period allows to discard old messages and prevents the chat history from filling up with volatile chat (e.g. chat lobbies and distant chat).</p></body></html> <html><head/> <body><p align="justify"> op dit tabblad kunt u instellen hoeveel chatberichten Retroshare blijft opgeslagen op de schijf en hoeveel van de vorige conversatie wordt weergegeven, voor de verschillende chat-systemen. De maximale opslagperiode te ontdoen van oude berichten en voorkomt u dat de chatgeschiedenis uit te vullen met vluchtige chat (bijvoorbeeld chat lobby's en verre chat).</p></body></html> - - Chatlobbies - Chatlobbies - Enabled: Ingeschakeld: - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2410,7 +2096,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2457,7 +2153,7 @@ Double click a chat room to enter and chat. Description: - + Beschrijving @@ -2507,11 +2203,7 @@ Double click a chat room to enter and chat. Maximale opslagperiode, in dagen (0 = houden alle): - Search by default - Standaard zoeken - - - + Case sensitive Hoofdletter gevoelig @@ -2617,7 +2309,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat Toon chat @@ -2653,7 +2345,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close Sluiten @@ -2688,12 +2380,12 @@ Double click a chat room to enter and chat. Schuin - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2773,11 +2465,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2815,7 +2502,7 @@ Double click a chat room to enter and chat. - + is typing... typt.... @@ -2837,7 +2524,7 @@ after HTML conversion. - + Do you really want to physically delete the history? Wil je echt voorgoed de geschiedenis verwijderen? @@ -2887,7 +2574,7 @@ after HTML conversion. is bezig en kan mogelijk niet reageren - + Find Case Sensitively Zoek hoofdlettergevoelig @@ -2909,7 +2596,7 @@ after HTML conversion. Niet stoppen met kleuren na X items gevonden (meer CPU nodig) - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> <b>Zoek vorige</b> <br/><i>Ctrl + Shift + G</i> @@ -2924,16 +2611,12 @@ after HTML conversion. <b>Vinden</b> <br/><i>Ctrl + F</i> - + (Status) (Status) - Set text font & color - Tekst instellen lettertype & kleur - - - + Attach a File Een bestand toevoegen @@ -2949,12 +2632,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> <b>Markeer deze geselecteerde tekst</b><br><i>Ctrl + M</i> - + Person id: @@ -2965,12 +2648,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. objecten gevonden. @@ -2990,7 +2673,7 @@ Double click on it to add his name on text writer. Typ een bericht hier - + Don't stop to color after @@ -3016,7 +2699,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: Toon details: @@ -3038,7 +2721,7 @@ Double click on it to add his name on text writer. - + Personal Circles Persoonlijke Cirkels @@ -3064,7 +2747,7 @@ Double click on it to add his name on text writer. - + Friends Vrienden @@ -3124,7 +2807,7 @@ Double click on it to add his name on text writer. Vrienden van Vrienden - + External Circles (Admin) Externe Cirkels (Administrator) @@ -3140,7 +2823,7 @@ Double click on it to add his name on text writer. - + Circles Cirkels @@ -3192,45 +2875,45 @@ Double click on it to add his name on text writer. - + RetroShare RetroShare - + - + Error : cannot get peer details. Error: kan geen verbindings gegevens vinden. - + Retroshare ID - + <p>This Retroshare ID contains: - + <p>This certificate contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: @@ -3240,7 +2923,7 @@ Double click on it to add his name on text writer. Versleuteling - + Not connected Niet verbonden @@ -3322,12 +3005,17 @@ Double click on it to add his name on text writer. Geen - + <li>a <b>node ID</b> and <b>name</b> - + + <b>DNS:</b> : + + + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3347,7 +3035,7 @@ Double click on it to add his name on text writer. - + with @@ -3364,104 +3052,16 @@ Double click on it to add his name on text writer. Connect Friend Wizard Wizard verbinding maken met een vriend - - Add a new Friend - Voeg een nieuwe vriend toe - - - &You get a certificate file from your friend - &U heeft een certificaat bestand gekregen van een vriend - - - &Make friend with selected friends of my friends - &Maak een vriend met geselecteerde vrienden van mijn vrienden - - - Include signatures - Inclusief handtekeningen - - - Copy your Cert to Clipboard - Kopieer uw certificaat naar het klembord - - - Save your Cert into a File - Sla uw Certificaat op in een bestand - - - Run Email program - Start Email programma - Open Cert of your friend from File - - Certificate files - Certificaat bestanden - - - Use PGP certificates saved in files. - Gebruik opgeslagen certificaat bestanden - - - Import friend's certificate... - Importeer een vriend certificaat... - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - U moet een certificaat bestand maken en aan een vriend sturen. U kunt een reeds eerder gemaakt bestand gebruiken. - - - Export my certificate... - Exporteer mijn certificaat... - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - Sleep en plaats uw vriends certificaat in dit scherm of tik de lokatie van het bestand in onderstaande venster - - - Browse - Bladeren - - - Friends of friends - Vrienden van vrienden - - - Select now who you want to make friends with. - Kies nu met wie je vrienden wilt worden - - - Show me: - Toon me: - - - Make friend with these peers - Wordt vriend met deze verbindingen - RetroShare ID RetroShare ID - - Use RetroShare ID for adding a Friend which is available in your network. - Gebruik RetroShare ID om een vriend toe te voegen die al in je netwerk beschikbaar is. - - - Add Friends RetroShare ID... - Voeg je vriend's RetroShare ID toe - - - Paste Friends RetroShare ID in the box below - Plak je vriend's RetroShare ID in het veld hieronder - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - Enter de RetroShare ID van je vriend, zoiets als verbinding@BDE8D16A46D938CF - RetroShare is better with Friends @@ -3503,27 +3103,7 @@ Double click on it to add his name on text writer. Email - Invite Friends by Email - Nodig vrienden uit via email - - - Enter your friends' email addresses (separate each one with a semicolon) - Vul het email adres van uw vriend of vrienden in (elke gescheiden door een ;) - - - Your friends' email addresses: - Uw vriend's email adres: - - - Enter Friends Email addresses - Enter uw vriend's email adres: - - - Subject: - Onderwerp: - - - + @@ -3539,44 +3119,32 @@ Double click on it to add his name on text writer. Gegevens van uw aanvraag - + Peer details Verbindings details - + Name: Naam: - - Email: - Email: - - - Node: - Knooppunt - Location: Woonplaats: - + Options Opties - Enter the certificate manually - Voeg het certificaat handmatig in - - - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: Voeg een vriend toe aan een groep: @@ -3586,7 +3154,7 @@ Double click on it to add his name on text writer. Verifieer vriend (Teken PGP Sleutel) - + Please paste below your friend's Retroshare ID @@ -3611,16 +3179,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with Voeg toe als vriend om mee verbonden te worden - To accept the Friend Request, click the Finish button. - Om je vriend's verzoek te accepteren klik de Klaar knop - - - + Sorry, some error appeared Sorry, een error verscheen @@ -3640,32 +3214,27 @@ Double click on it to add his name on text writer. Gegevens van uw vriend: - + Key validity: Sleutel deugdelijkheid: - + Profile ID: - - Signers - Ondertekenaars - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. Deze verbinding staat al op je vriend zijn lijst. Toevoegen stelt waarschijnlijk alleen zijn ip adres in. - + To accept the Friend Request, click the Accept button. @@ -3711,45 +3280,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed Certificaat fout - Cannot get peer details of PGP key %1 - Kan geen verbindings details krijgen van de PGP sleutel %1 - - - Any peer I've not signed - Iedere verbinding die ik niet bevestigd hebt - - - Friends of my friends who already trust me - Vrienden van vrienden die me al vertrouwen - - - Signed peers showing as denied - Bevestigde verbindingen tonen als geweigerd - - - Peer name - Verbindings naam - - - Also signed by - Ook ondertekend door - - - Peer id - Verbindings ID - - - + Not a valid Retroshare certificate! - + RetroShare Invitation RetroShare uitnodiging @@ -3769,12 +3310,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3782,7 +3323,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3822,7 +3363,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.U heeft een aanvraag om vriend te worden - + Profile password needed. @@ -3847,7 +3388,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3857,47 +3398,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - Certificate Load Failed:file %1 not found - Certificaat laden lukt niet: bestand %1 niet gevonden - - - This Peer %1 is not available in your Network - Deze verbinding %1 is niet beschikbaar in je netwerk - - - Use new certificate format (safer, more robust) - Gebruik nieuw certificaat format (veiliger) - - - Use old (backward compatible) certificate format - Gebruik oude (backward compatible) certificaat format - - - Remove signatures - Verwijder handtekeningen - - - RetroShare Invite - RetroShare uitnodiging - - - Connect Friend Help - Connect vriend help - - - You can copy this text and send it to your friend via email or some other way - U kunt deze tekst kopiëren en naar een vriend sturen via mail of een andere manier - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Uw certificaat is op het klembord geplaatst, plak en stuur het naar een vriend via email of op een andere manier - - - Save as... - Sla op als... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3936,11 +3437,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.*** Geen *** - Use as direct source, when available - Gebruiken als directe bron indien mogelijk - - - + IP-Addr: IP-Adr: @@ -3950,7 +3447,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.IP Adres: - + Show Advanced options @@ -3969,41 +3466,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> - - Recommend many friends to each others - Alle vrienden aan elke anderen aanbevelen - - - Friend Recommendations - Vriend aanbevelingen - - - Message: - Bericht: - - - Recommend friends - Aanbevolen vrienden - - - To - Aan - - - Please select at least one friend for recommendation. - Selecteer minstens één vriend om aan te bevelen. - - - Please select at least one friend as recipient. - Selecteer minstens één vriend als ontvanger. - Add key to keyring Sleutel toevoegen aan keyring - + This key is already in your keyring Deze sleutel is al in uw keyring @@ -4016,7 +3485,7 @@ even if you don't make friends. Schakel dit selectievakje in om de sleutel toe te voegen aan uw sleutelverzameling. Dit kan handig zijn voor het verzenden van verre berichten naar deze verbinding, zelfs als u vrienden maakt. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. Certificaat heeft verkeerde versienummer. Vergeet niet dat v0.6 en v0.5 netwerken niet compatibel zijn. @@ -4051,7 +3520,7 @@ even if you don't make friends. IP toevoegen aan whitelist - + No IP in this certificate! Geen IP in dit certificaat @@ -4061,23 +3530,10 @@ even if you don't make friends. - - [Unknown] - - - - + Added with certificate from %1 Toegevoegd met certificaat van %1 - - Paste Cert of your friend from Clipboard - Certificaat van vriend plakken uit het klempbord - - - Certificate Load Failed:can't read from file %1 - Certificaat laden lukt niet: kan niet lezen van bestand %1 - ConnectProgressDialog @@ -4139,7 +3595,7 @@ even if you don't make friends. - + UDP Setup UDP setup @@ -4167,7 +3623,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant Verbindings assistent @@ -4177,17 +3633,20 @@ p, li { white-space: pre-wrap; } Niet werkende Peer ID - + + Unknown State Onbekende status - + + Offline Offline - + + Behind Symmetric NAT Achter Symmetric NAT @@ -4197,12 +3656,14 @@ p, li { white-space: pre-wrap; } Achter NAT & geen DHT - + + NET Restart Herstarten netwerk - + + Behind NAT Achter NAT @@ -4212,7 +3673,8 @@ p, li { white-space: pre-wrap; } Geen DHT - + + NET STATE GOOD! Net status ok! @@ -4237,7 +3699,7 @@ p, li { white-space: pre-wrap; } Zoek RS Peers - + Lookup requires DHT Lookup heeft DHT nodig @@ -4529,7 +3991,7 @@ p, li { white-space: pre-wrap; } Probeer opnieuw de volledige certificaat te importeren - + @@ -4537,7 +3999,8 @@ p, li { white-space: pre-wrap; } Onbekend - + + UNVERIFIABLE FORWARD! ONCONTROLEERBARE DOORSTURINGEN! @@ -4547,7 +4010,7 @@ p, li { white-space: pre-wrap; } ONCONTROLEERBARE DOORSTURING & GEEN DHT - + Searching Zoeken @@ -4583,12 +4046,12 @@ p, li { white-space: pre-wrap; } Cirkel Gegevens - + Name Naam - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4608,7 +4071,7 @@ p, li { white-space: pre-wrap; } - + IDs IDs @@ -4628,18 +4091,18 @@ p, li { white-space: pre-wrap; } Filter - + Cancel Annuleren - + Nickname Gebruikersnaam - + Invited Members @@ -4654,15 +4117,7 @@ p, li { white-space: pre-wrap; } - ID - ID - - - Type - Type - - - + Name: Naam: @@ -4702,19 +4157,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - + Please set a name for your Circle Kies een naam voor uw Cirkel - + No Restriction Circle Selected Geen Restrictie Cirkel Geselecteerd @@ -4724,12 +4179,24 @@ p, li { white-space: pre-wrap; } Geen Cirkel Limitaties Geselecteerd - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add Toevoegen @@ -4739,7 +4206,7 @@ p, li { white-space: pre-wrap; } Verwijder - + Search Zoek @@ -4754,10 +4221,6 @@ p, li { white-space: pre-wrap; } Signed Getekend - - Signed by known nodes - Ondertekend door bekende knooppunten - Edit Circle @@ -4774,10 +4237,6 @@ p, li { white-space: pre-wrap; } PGP Identity PGP identiteit - - Anon Id - Anoniem ID - Circle name @@ -4800,17 +4259,13 @@ p, li { white-space: pre-wrap; } - + Create Maak - PGP Linked Id - PGP geaccocieerd ID - - - + Add Member @@ -4829,7 +4284,7 @@ p, li { white-space: pre-wrap; } Maak een groep - + Group Name: Groeps Naam: @@ -4864,7 +4319,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post Nieuw kanaal bericht @@ -4874,7 +4329,7 @@ p, li { white-space: pre-wrap; } Kanaal bericht - + Post @@ -4935,23 +4390,11 @@ p, li { white-space: pre-wrap; }⏎ <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Gebruik Slepen en Neerzetten / Voeg Bestanden Toe knop om nieuwe bestanden te indexeren.</span></p>⏎ <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Kopieer en plak RetroShare links van je gedeelden.</span></p></body></html> - - Add File to Attach - Voeg bestand toe - Add Channel Thumbnail Voeg kanaal miniatuur toe - - Message - Bericht - - - Subject : - Onderwerp - @@ -5037,17 +4480,17 @@ p, li { white-space: pre-wrap; }⏎ - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -5066,17 +4509,18 @@ p, li { white-space: pre-wrap; }⏎ The following files will only be shared for 30 days. Think about adding them to a shared directory. - - File already Added and Hashed - Bestand is reeds toegevoegd en in de hash opgenomen - Please add a Subject Voeg een onderwerp toe - + + Cannot publish post + + + + Load thumbnail picture Laad miniatuur plaatje @@ -5091,18 +4535,12 @@ p, li { white-space: pre-wrap; }⏎ - - + Generate mass data Massa gegevens genereren - - Do you really want to generate %1 messages ? - Wilt u echt %1 berichten genereren? - - - + You are about to add files you're not actually sharing. Do you still want this to happen? U gaat nu bestanden toevoegen die niet gedeeld zijn. Weet u zeker dat u dat wilt? @@ -5136,7 +4574,7 @@ p, li { white-space: pre-wrap; }⏎ CreateGxsForumMsg - + Post Forum Message Post forum bericht @@ -5145,10 +4583,6 @@ p, li { white-space: pre-wrap; }⏎ Forum Forum - - Subject - Onderwerp - Attach File @@ -5169,8 +4603,8 @@ p, li { white-space: pre-wrap; }⏎ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -5189,7 +4623,7 @@ p, li { white-space: pre-wrap; } U kunt bestanden toevoegen via Slepen en Neerzetten in dit scherm - + Post @@ -5219,17 +4653,17 @@ p, li { white-space: pre-wrap; } - + No Forum Geen Forum - + In Reply to In antwoord op - + Title Titel @@ -5282,7 +4716,7 @@ Do you want to discard this message? Laad images bestand - + No compatible ID for this forum @@ -5292,8 +4726,8 @@ Do you want to discard this message? - - + + Generate mass data Massa gegevens genereren @@ -5302,10 +4736,6 @@ Do you want to discard this message? Do you really want to generate %1 messages ? Wilt u echt %1 berichten genereren? - - Send - Verstuur - Post as @@ -5320,23 +4750,7 @@ Do you want to discard this message? CreateLobbyDialog - Create Chat Lobby - Maak een nieuw chat portaal - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - Een chat portaal is een centraal en anonieme chat groep. Alle deelnemers ontvangen alle berichten. Zodra er een nieuw portaal is opgericht kunt u vrienden uitnodigen via de "Vrienden" knop. - - - Lobby name: - Portaal naam: - - - Lobby topic: - Portaal onderwerp - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5371,7 +4785,7 @@ Do you want to discard this message? - + Create Maak @@ -5381,7 +4795,7 @@ Do you want to discard this message? Annuleren - + require PGP-signed identities PGP-ondertekende identiteiten vereisen @@ -5396,11 +4810,7 @@ Do you want to discard this message? Kies de vrienden met wie je een groeps chat wil - Invited friends - Uitgenodigde vrienden - - - + Create Chat Room @@ -5421,7 +4831,7 @@ Do you want to discard this message? Contacts: - + Identity to use: @@ -5429,17 +4839,17 @@ Do you want to discard this message? CryptoPage - + Public Information Publieke informatie - + Name: Naam: - + Location: Woonplaats: @@ -5449,12 +4859,12 @@ Do you want to discard this message? Locatie ID: - + Software Version: Software Versie: - + Online since: Online sinds: @@ -5474,12 +4884,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5489,7 +4894,7 @@ Do you want to discard this message? - + Other Information Andere informatie @@ -5499,17 +4904,12 @@ Do you want to discard this message? - + Profile - - Certificate - Certificaat - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5519,11 +4919,7 @@ Do you want to discard this message? Inclusief handtekeningen - Save Key into a file - Sla sleutel op in een bestand - - - + Export Identity Exporteer identiteit @@ -5597,33 +4993,33 @@ en daar de importeer functie gebruiken - + TextLabel Tekst label - + PGP fingerprint: PGP vingerafdruk: - - Node information - Knooppunt informatie - - - + PGP Id : PGP-Id: - + Friend nodes: Vriend knooppunten: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5662,14 +5058,6 @@ en daar de importeer functie gebruiken Node Knooppunt - - Create new node... - Maal nieuw knooppunt - - - show statistics window - toon statistieken scherm - DHTGraphSource @@ -5721,7 +5109,7 @@ en daar de importeer functie gebruiken DLListDelegate - + B B @@ -6389,7 +5777,7 @@ en daar de importeer functie gebruiken DownloadToaster - + Start file Start bestand @@ -6397,38 +5785,38 @@ en daar de importeer functie gebruiken ExprParamElement - + - + to naar - + ignore case negeer - - - dd.MM.yyyy - dd.MM.yyyy + + + yyyy-MM-dd + - - + + KB KB - - + + MB MB - - + + GB GB @@ -6436,12 +5824,12 @@ en daar de importeer functie gebruiken ExpressionWidget - + Expression Widget Expression Widget - + Delete this expression Verwijder deze Expression @@ -6603,7 +5991,7 @@ en daar de importeer functie gebruiken FilesDefs - + Picture PLaatje @@ -6613,7 +6001,7 @@ en daar de importeer functie gebruiken Video - + Audio Audio @@ -6673,11 +6061,21 @@ en daar de importeer functie gebruiken C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Vrienden directories @@ -6799,7 +6197,7 @@ en daar de importeer functie gebruiken - + ID ID @@ -6841,7 +6239,7 @@ en daar de importeer functie gebruiken Toon groepen - + Group Groep @@ -6877,7 +6275,7 @@ en daar de importeer functie gebruiken Voeg toe aan groep - + Search Zoeken @@ -6893,7 +6291,7 @@ en daar de importeer functie gebruiken Sorteer per datum - + Profile details @@ -7104,7 +6502,7 @@ at least one peer was not added to a group To - + Naar @@ -7130,7 +6528,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request Bevestig vriend verzoek @@ -7147,10 +6545,6 @@ at least one peer was not added to a group FriendSelectionWidget - - Search : - Zoeken: - Sort by state @@ -7172,7 +6566,7 @@ at least one peer was not added to a group Zoek vrienden - + Mark all Selecteer alles @@ -7183,16 +6577,132 @@ at least one peer was not added to a group Selecteer geen + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Naam + + + + Node ID + + + + + Address + + + + + Status + Status + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + Maak een vriend + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message Bewerk berichten status - - + + Broadcast Uitzenden @@ -7275,33 +6785,38 @@ at least one peer was not added to a group Reset lettertype naar standaard - + Keyring Sleutelbos - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. Retroshare groepschat: berichten worden verstuurd naar alle verbonden vrienden. - - + + Network Netwerk - + + Friend Server + + + + Network graph Netwerk grafiek - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. Stel hier uw statusbericht in. @@ -7319,7 +6834,17 @@ at least one peer was not added to a group Wachtwoord - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters Alle velden moet minimaal 3 karakters bevatten @@ -7329,17 +6854,12 @@ at least one peer was not added to a group Wachtwoorden komen niet overeen - + Port Poort - - Use BOB - - - - + This password is for PGP @@ -7360,38 +6880,38 @@ at least one peer was not added to a group - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -7411,12 +6931,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -7426,38 +6946,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel Tekst label - + hidden address - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -7501,13 +7026,13 @@ and use the import button to load it - + Import profile - + Create new profile and new Retroshare node @@ -7517,7 +7042,7 @@ and use the import button to load it - + Tor/I2P address @@ -7552,7 +7077,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7562,12 +7087,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -7577,12 +7097,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7808,36 +7323,13 @@ and use the import button to load it We gaan starten - + Invite Friends Nodig vrienden uit - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">⏎ -<html><head><meta name="qrichtext" content="1" /><style type="text/css">⏎ -p, li { white-space: pre-wrap; }⏎ -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">⏎ -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is niets zonder uw vrienden. Klik op de knop om het proces te starten.</span></p>⏎ -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p>⏎ -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email een uitnodiging met uw &quot;ID Certificaat&quot; aan uw vrienden.</span></p>⏎ -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p>⏎ -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Wees zeker dat u een uitnodiging terugkrijgt... </span></p>⏎ -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">U kunt alleen verbinding maken met een vriend als u beide elkaar heeft toegevoegd.</span></p></body></html> - - - + Add Your Friends to RetroShare Nodig jouw vrienden uit voor RetroShare @@ -7847,89 +7339,103 @@ p, li { white-space: pre-wrap; }⏎ Voeg vrienden toe - + + Connect To Friends + Maak verbinding met vrienden + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Geavanceerd: Open een poort in je Firewall + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - Maak verbinding met vrienden - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - Geavanceerd: Open een poort in je Firewall - - - + Further Help and Support Meer Help en Ondersteuning - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website Open RetroShare Website @@ -7954,7 +7460,7 @@ p, li { white-space: pre-wrap; } Email terugkoppeling - + RetroShare Invitation RetroShare uitnodiging @@ -8004,12 +7510,12 @@ p, li { white-space: pre-wrap; } RetroShare terugkoppeling - + RetroShare Support RetroShare ondersteuning - + It has many features, including built-in chat, messaging, @@ -8133,7 +7639,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat Toon groeps chat @@ -8141,7 +7647,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] @@ -8311,7 +7817,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title Titel @@ -8324,12 +7830,12 @@ p, li { white-space: pre-wrap; } - + Description Beschrijving - + Number of Unread message @@ -8354,19 +7860,7 @@ p, li { white-space: pre-wrap; } - Sort by Name - Sorteer op naam - - - Sort by Popularity - Sorteer op populariteit - - - Sort by Last Post - Sorteer op laatste post - - - + You are admin (modify names and description using Edit menu) @@ -8381,14 +7875,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post Het laatste bericht - + Name Naam @@ -8399,17 +7893,13 @@ p, li { white-space: pre-wrap; } Populariteit - + Never - Display - Toon - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8422,7 +7912,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and en @@ -8558,7 +8048,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels Kanalen @@ -8569,22 +8059,22 @@ p, li { white-space: pre-wrap; } Maak een nieuw kanaal - + Enable Auto-Download Activeer automatisch downloaden - + My Channels Mijn Kanalen - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Geabonneerde kanalen @@ -8604,12 +8094,12 @@ p, li { white-space: pre-wrap; } - + Disable Auto-Download Automatisch downloaden uitschakelen - + Set download directory @@ -8644,22 +8134,22 @@ p, li { white-space: pre-wrap; } - + Play Bespelen - + Open folder Open map - + Open file - + Error Error @@ -8679,17 +8169,17 @@ p, li { white-space: pre-wrap; } Controleren - + Are you sure that you want to cancel and delete the file? Weet u zeker dat u wilt annuleren en daarna het bestand te verwijderen? - + Can't open folder Kan de map niet openen - + Play File Speel bestand @@ -8699,37 +8189,10 @@ p, li { white-space: pre-wrap; } Bestand %1 bestaat niet op deze locatie - - GxsChannelFilesWidget - - Form - Formulier - - - Filename - Bestandsnaam - - - Size - Grootte - - - Title - Titel - - - Published - Gepubliceerd - - - Status - Status - - GxsChannelGroupDialog - + Create New Channel Maak een nieuw kanaal @@ -8767,9 +8230,19 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - Registreer bij dit kanaal + + Last activity + + + + + TextLabel + Tekst label + + + + Subscribe this Channel + @@ -8783,7 +8256,7 @@ p, li { white-space: pre-wrap; } - + Expand Uitbreiden @@ -8798,7 +8271,7 @@ p, li { white-space: pre-wrap; } Kanaal beschrijving - + Loading Laden @@ -8813,8 +8286,9 @@ p, li { white-space: pre-wrap; } - New Channel - Nieuw kanaal + + Never + @@ -8825,7 +8299,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: @@ -8846,7 +8320,7 @@ p, li { white-space: pre-wrap; } - + Play Bespelen @@ -8902,28 +8376,24 @@ p, li { white-space: pre-wrap; } Files Bestanden - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - Waarschuwing! U heeft minder dan %1 uur en %2 minuten voordat dit bestand verwijderd is. Overweeg om het op te slaan. - Hide Verberg - + New Nieuw - + 0 0 - - + + Comment Opmerking @@ -8938,21 +8408,17 @@ p, li { white-space: pre-wrap; } Ik vindt dit niet leuk - Loading - Laden - - - + Loading... - + Comments - + Post @@ -8977,87 +8443,16 @@ p, li { white-space: pre-wrap; } Speel media - - GxsChannelPostsWidget - - Post to Channel - Post op dit kanaal - - - Loading - Laden - - - Search channels - Zoek kanalen - - - Title - Titel - - - Search Title - Zoek Titel - - - Message - Bericht - - - Search Message - Zoek bericht - - - Filename - Bestandsnaam - - - Search Filename - Zoek bestandsnaam - - - No Channel Selected - Geen kanaal geselecteerd - - - Disable Auto-Download - Automatisch downloaden uitschakelen - - - Enable Auto-Download - Activeer automatisch downloaden - - - Show feeds - Toon feeds - - - Show files - Bestanden weergeven - - - Feeds - Feeds - - - Files - Bestanden - - - Description: - Beschrijving: - - GxsChannelPostsWidgetWithModel - + Post to Channel Post op dit kanaal - + Add new post @@ -9127,7 +8522,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -9163,7 +8558,7 @@ p, li { white-space: pre-wrap; } - + Comments Opmerkingen @@ -9178,13 +8573,13 @@ p, li { white-space: pre-wrap; } Feeds - - + + Click to switch to list view - + Show unread posts only @@ -9199,7 +8594,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -9214,7 +8609,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -9274,12 +8669,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -9354,12 +8759,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed Geabonneerd @@ -9410,17 +8816,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel Tekst label - + Circle name: - + Accept @@ -9535,7 +8941,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container Opmerkingen container @@ -9548,7 +8954,7 @@ p, li { white-space: pre-wrap; } Formulier - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9578,7 +8984,7 @@ p, li { white-space: pre-wrap; } Ververs - + Comment Opmerkingen @@ -9617,7 +9023,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment Antwoord op een opmerking @@ -9641,6 +9047,21 @@ p, li { white-space: pre-wrap; } Vote Down Stem omlaag + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9650,7 +9071,7 @@ p, li { white-space: pre-wrap; } Geef een opmerking - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9679,26 +9100,10 @@ p, li { white-space: pre-wrap; } - + Post - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">⏎ -<html><head><meta name="qrichtext" content="1" /><style type="text/css">⏎ -p, li { white-space: pre-wrap; }⏎ -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">⏎ -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Opmerking</span></p></body></html> - - - Signed by - Getekend door - Reply to Comment @@ -9727,7 +9132,7 @@ before you can comment voor je een opmerking kan doen - + It remains %1 characters after HTML conversion. @@ -9769,14 +9174,6 @@ voor je een opmerking kan doen Forum moderators can edit/delete/pinup others posts - - Add Forum Admins - Toevoegen van Forum beheerders - - - Select Forum Admins - Selecteer Forum beheerders - Create @@ -9786,7 +9183,7 @@ voor je een opmerking kan doen GxsForumGroupItem - + Subscribe to Forum Registreer bij dit forum @@ -9802,7 +9199,7 @@ voor je een opmerking kan doen - + Expand Uitbreiden @@ -9822,8 +9219,9 @@ voor je een opmerking kan doen - Loading - Laden + + TextLabel + Tekst label @@ -9854,13 +9252,13 @@ voor je een opmerking kan doen GxsForumMsgItem - - + + Subject: Onderwerp: - + Unsubscribe To Forum Uitschrijven bij dit forum @@ -9871,7 +9269,7 @@ voor je een opmerking kan doen - + Expand Uitbreiden @@ -9891,21 +9289,17 @@ voor je een opmerking kan doen In antwoord op: - Loading - Laden - - - + Loading... - + Forum Feed Forum Feed - + Hide Verbergen @@ -9918,63 +9312,66 @@ voor je een opmerking kan doen Formulier - + Start new Thread for Selected Forum Start een nieuw draadje in het geselecteerde forum - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Zoek forums - Last Post - Het laatste bericht - - - + New Thread Nieuw draadje - - - Threaded View - Threaded View - - - - Flat View - Flat View - - + Title Titel - - + + Date Datum - + Author Auteur - - Save image - - - - + Loading Laden - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9984,12 +9381,7 @@ voor je een opmerking kan doen - - Lastest post in thread - - - - + Reply Message Beantwoord bericht @@ -10013,10 +9405,6 @@ voor je een opmerking kan doen Download all files Download alle bestanden - - Next unread - Volgende ongelezen - Search Title @@ -10033,31 +9421,23 @@ voor je een opmerking kan doen Zoek Auteur - Content - Inhoud - - - Search Content - Zoek Inhoud - - - + No name Geen naam - - + + Reply Antwoord - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -10100,16 +9480,12 @@ voor je een opmerking kan doen Kopieer RetroShare Link - + Hide Verberg - Expand - Uitbreiden - - - + [unknown] @@ -10139,8 +9515,8 @@ voor je een opmerking kan doen - - + + Distribution @@ -10154,22 +9530,6 @@ voor je een opmerking kan doen Anti-spam - - Anonymous - Anoniem - - - signed - Getekend - - - none - Geen - - - [ ... Missing Message ... ] - [ ... Bericht ontbreekt ... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10239,12 +9599,12 @@ voor je een opmerking kan doen Origineel bericht - + New thread - + Edit Bewerk @@ -10305,7 +9665,7 @@ voor je een opmerking kan doen - + Show column @@ -10325,7 +9685,7 @@ voor je een opmerking kan doen - + Anonymous/unknown posts forwarded if reputation is positive @@ -10377,7 +9737,7 @@ This message is missing. You should receive it later. - + No result. @@ -10387,7 +9747,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -10402,7 +9762,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -10468,12 +9828,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums Forums @@ -10504,35 +9864,16 @@ This message is missing. You should receive it later. Andere forums - - GxsForumsFillThread - - Waiting - Wachten - - - Retrieving - Ontvangen - - - Loading - Laden - - GxsGroupDialog - + Name Naam - Add Icon - Ikoon toevoegen - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels Sleutel ontvangers kunnen voor een beperkte groep publiceren en kunnen kijken en publiceren op Privé actige Kanalen. @@ -10541,22 +9882,14 @@ This message is missing. You should receive it later. Share Publish Key Deel Publieke Sleutel - - check peers you would like to share private publish key with - Controleer welke verbinding je wilt delen met een openbare Privé Sleutel - - - Share Key With - Deel sleutel met - - + Description Beschrijving - + Message Distribution Berichten Distributie @@ -10564,7 +9897,7 @@ This message is missing. You should receive it later. - + Public Publiek @@ -10583,14 +9916,6 @@ This message is missing. You should receive it later. New Thread Nieuw draadje - - Required - Benodigd - - - Encrypted Msgs - Versleutelde berichten - Personal Signatures @@ -10632,7 +9957,7 @@ This message is missing. You should receive it later. - + Comments: Opmerkingen: @@ -10655,7 +9980,7 @@ This message is missing. You should receive it later. - + All People @@ -10671,12 +9996,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -10693,23 +10018,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -10725,30 +10050,28 @@ This message is missing. You should receive it later. Voeg een naam toe - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo Laad groep logo - + Submit Group Changes Groep wijzigingen verzenden - Failed to Prepare Group MetaData - please Review - Mislukt te bereiden groep metagegevens - Lees - - - Will be used to send feedback - Zal worden gebruikt voor het verzenden van feedback - - - + Owner: Eigenaar: @@ -10758,12 +10081,12 @@ This message is missing. You should receive it later. - + Info - + ID ID @@ -10773,7 +10096,7 @@ This message is missing. You should receive it later. Het laatste bericht - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -10848,7 +10171,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity Populariteit @@ -10864,27 +10192,22 @@ This message is missing. You should receive it later. - + Created - + Cancel Annuleren - + Create Maak - - Author - Auteur - - - + GxsIdLabel @@ -10892,7 +10215,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading Laden @@ -10952,7 +10275,7 @@ This message is missing. You should receive it later. Bewerk Details - + Synchronise posts of last... @@ -11009,12 +10332,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link Kopieer RetroShare Link @@ -11037,7 +10360,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature Geen handtekening @@ -11050,40 +10373,24 @@ This message is missing. You should receive it later. GxsIdDetails - Loading - Laden - - - + Not found Niet gevonden - - No Signature - Geen handtekening - - - + + [Banned] - - Authentication - Verificatie - unknown Key onbekende sleutel - anonymous - anoniem - - - + Loading... @@ -11093,7 +10400,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -11113,6 +10425,14 @@ This message is missing. You should receive it later. + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -11124,7 +10444,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -11172,17 +10492,13 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] GxsMessageFramePostWidget - - Loading - Laden - Loading... @@ -11323,7 +10639,7 @@ This message is missing. You should receive it later. Unknown Peer - + Onbekenden verbinding @@ -11563,7 +10879,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -11579,7 +10895,7 @@ p, li { white-space: pre-wrap; } - + Authors Auteurs @@ -11598,7 +10914,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -11676,7 +10992,7 @@ p, li { white-space: pre-wrap; }⏎ Formulier - + Add friend @@ -11686,7 +11002,7 @@ p, li { white-space: pre-wrap; }⏎ - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -11714,7 +11030,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -11724,7 +11040,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard Kopieer uw certificaat naar het klembord @@ -11734,7 +11050,7 @@ private and secure decentralized communication platform. Sla uw Certificaat op in een bestand - + Send via Email @@ -11754,13 +11070,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -11772,12 +11112,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -11792,12 +11132,7 @@ new short format RetroShare uitnodiging - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... Sla op als... @@ -12062,14 +11397,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Alles - + Reputation Reputatie @@ -12079,12 +11414,12 @@ p, li { white-space: pre-wrap; } Zoek - + Anonymous Id Anoniem Id - + Create new Identity Maak een nieuwe identiteit @@ -12094,7 +11429,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -12109,27 +11444,27 @@ p, li { white-space: pre-wrap; } - + Close Sluiten - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -12145,29 +11480,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles Cirkels - + Circle name @@ -12187,18 +11532,20 @@ p, li { white-space: pre-wrap; } Persoonlijke Cirkels - + + Edit identity Identiteit aanpassen - + + Delete identity - + Chat with this peer Chat met deze verbinding @@ -12208,78 +11555,78 @@ p, li { white-space: pre-wrap; } Start een chat met deze verbinding - + Owner node ID : Eigenaar knooppunt-ID: - + Identity name : Identiteitsnaam: - + () - + Identity ID - + Send message Verstuur bericht - + Identity info - + Identity ID : Identiteit ID: - + Owner node name : Knooppuntnaam van de eigenaar: - + Create new... - + Type: Type - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: - + Negative - + Neutral @@ -12290,17 +11637,17 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous Anoniem @@ -12315,24 +11662,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you Deze identiteit is eigendom van u - - + + My own identities - - + + My contacts - + Show Items @@ -12347,7 +11694,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -12357,7 +11709,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -12432,7 +11784,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -12462,7 +11814,7 @@ p, li { white-space: pre-wrap; } onbekend - + Invited @@ -12477,7 +11829,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle Bewerk Cirkel @@ -12525,7 +11877,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -12533,7 +11885,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -12576,7 +11928,7 @@ These identities will soon be not supported anymore. Anonieme identiteit - + Boards @@ -12656,7 +12008,7 @@ These identities will soon be not supported anymore. - + information @@ -12672,17 +12024,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -12787,7 +12134,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -12837,21 +12184,21 @@ These identities will soon be not supported anymore. - - - + + + People Mensen - + Your Avatar Click here to change your avatar - + Linked to neighbor nodes @@ -12861,7 +12208,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -12876,7 +12223,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -12891,12 +12238,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -12916,12 +12263,12 @@ These identities will soon be not supported anymore. - + Owned by - + Node name: @@ -12931,7 +12278,7 @@ These identities will soon be not supported anymore. - + Really delete? @@ -12939,7 +12286,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname Gebruikersnaam @@ -12969,7 +12316,7 @@ These identities will soon be not supported anymore. Pseudoniem - + Import image @@ -12979,12 +12326,19 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. + + + No Avatar chosen. A default image will be automatically displayed from your new identity. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity Nieuwe identiteit @@ -12998,7 +12352,7 @@ These identities will soon be not supported anymore. - + @@ -13008,7 +12362,12 @@ These identities will soon be not supported anymore. Onbekend - + + No avatar chosen + + + + Edit identity Identiteit aanpassen @@ -13019,27 +12378,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -13059,7 +12418,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -13069,11 +12428,7 @@ These identities will soon be not supported anymore. - Error getting key! - Fout bij ophalen sleutel! - - - + Error KeyID invalid SleutelID is ongeldig @@ -13088,7 +12443,7 @@ These identities will soon be not supported anymore. Onbekende echte naam - + Create New Identity Maak een nieuwe identiteit @@ -13098,10 +12453,15 @@ These identities will soon be not supported anymore. Type - + Choose image... + + + Remove + Verwijderen + @@ -13127,7 +12487,7 @@ These identities will soon be not supported anymore. Toevoegen - + Create Maak @@ -13137,13 +12497,13 @@ These identities will soon be not supported anymore. Annuleren - + Your Avatar Click here to change your avatar - + Linked to your profile @@ -13153,7 +12513,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -13227,7 +12587,7 @@ These identities will soon be not supported anymore. - + Copy Kopieer @@ -13237,12 +12597,12 @@ These identities will soon be not supported anymore. Verwijderen - + %1 's Message History - + Mark all Merk alles @@ -13261,26 +12621,38 @@ These identities will soon be not supported anymore. Quote Citaat - - Send - Verstuur - ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -13298,27 +12670,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: Poort: - + Listen Address: - + + Status: + Status: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -13339,7 +12716,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -13348,26 +12730,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File Open bestand - + Open Folder Open map - + Checking... Controleren... @@ -13377,7 +12764,7 @@ These identities will soon be not supported anymore. Controleer bestanden - + Recommend in a message to... @@ -13405,7 +12792,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend Vriend toevoegen @@ -13421,7 +12808,8 @@ These identities will soon be not supported anymore. - + + Options Opties @@ -13442,7 +12830,7 @@ These identities will soon be not supported anymore. - + Quit Stoppen @@ -13453,12 +12841,12 @@ These identities will soon be not supported anymore. Snel start Wizard - + RetroShare %1 a secure decentralized communication platform RetroShare %1 is een beveiligd gedecentraliseerde communicatie platform - + Unfinished Niet afgemaakt @@ -13486,11 +12874,12 @@ Maak meer ruimte vrij en klik Ok. + Status Status - + Notify Notify @@ -13501,31 +12890,35 @@ Maak meer ruimte vrij en klik Ok. + Open Messages Open berichten - + + Bandwidth Graph Grafische bandbreedte - + Applications Applicaties + Help Help - + + Minimize Minimalisser - + Maximize Maximalisseer @@ -13540,7 +12933,12 @@ Maak meer ruimte vrij en klik Ok. RetroShare - + + Close window + + + + %1 new message %1 nieuw bericht @@ -13570,7 +12968,7 @@ Maak meer ruimte vrij en klik Ok. %1 vrienden verbonden - + Do you really want to exit RetroShare ? Wil je RetroShare stoppen? @@ -13590,7 +12988,7 @@ Maak meer ruimte vrij en klik Ok. Toon - + Make sure this link has not been forged to drag you to a malicious website. Wees er zeker van dat deze link je niet naar een verdachte website stuurt @@ -13635,12 +13033,13 @@ Maak meer ruimte vrij en klik Ok. Service toestemming matrix - + + Statistics Statistieken - + Show web interface @@ -13655,7 +13054,7 @@ Maak meer ruimte vrij en klik Ok. - + Really quit ? @@ -13664,17 +13063,17 @@ Maak meer ruimte vrij en klik Ok. MessageComposer - + Compose Opstellen - + Contacts Contacten - + Paragraph Paragraph @@ -13710,12 +13109,12 @@ Maak meer ruimte vrij en klik Ok. Kop 6 - + Font size Letter grootte - + Increase font size Verklein letter grootte @@ -13730,32 +13129,32 @@ Maak meer ruimte vrij en klik Ok. Vet - + Italic Schuin - + Alignment Uitlijning - + Add an Image Voeg een plaatje toe - + Sets text font to code style Zet lettertype om in code stijl - + Underline Onderlijnd - + Subject: Onderwerp: @@ -13766,32 +13165,32 @@ Maak meer ruimte vrij en klik Ok. - + Tags Labels - + Address list: - + Recommend this friend - + Set Text color - + Set Text background color - + Recommended Files Aanbevolen bestanden @@ -13861,7 +13260,7 @@ Maak meer ruimte vrij en klik Ok. Voeg een citaat blok toe - + Send To: Verstuur naar: @@ -13901,7 +13300,7 @@ Maak meer ruimte vrij en klik Ok. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> Hallo,<br>ik wil een goede vriend van mij aanraden; als je mij vertrouwd kun je hem ook vertrouwen. <br> @@ -13921,18 +13320,18 @@ Maak meer ruimte vrij en klik Ok. wil vrienden met je zijn op RetroShare - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team Hi %1,<br><br>%2 wil vrienden met je zijn op RetroShare<br><br>Reageer nu:<br>%3<br><br>Bedankt,<br>Het RetroShare Team - - + + Save Message Bewaar bericht - + Message has not been Sent. Do you want to save message to draft box? Bericht is niet verzonden.⏎ @@ -13944,7 +13343,17 @@ Wil je het bericht bewaren in de concepten map? PLak RetroShare Link - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" Voeg toe aan "Aan" @@ -13964,7 +13373,7 @@ Wil je het bericht bewaren in de concepten map? Voeg toe als "Aanbevolen" - + Original Message Origineel bericht @@ -13974,21 +13383,21 @@ Wil je het bericht bewaren in de concepten map? Van - + - + To Naar - - + + Cc Cc - + Sent Zenden @@ -14003,7 +13412,7 @@ Wil je het bericht bewaren in de concepten map? Op %1, %2 schreef: - + Re: Antw: @@ -14013,30 +13422,30 @@ Wil je het bericht bewaren in de concepten map? Doorst: - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? Wil je dit bericht versturen zonder onderwerp? - + Please insert at least one recipient. Voeg minstens één ontvanger toe. - + Bcc Bcc - + Unknown Onbekend @@ -14151,13 +13560,13 @@ Wil je het bericht bewaren in de concepten map? Gegevens - + Open File... Open bestand... - + HTML-Files (*.htm *.html);;All Files (*) HTML- bestand (*.htm *.html );;Alle bestanden (*) @@ -14177,7 +13586,7 @@ Wil je het bericht bewaren in de concepten map? Export PDF - + Message has not been Sent. Do you want to save message ? Bericht is niet verzonden.⏎ @@ -14199,7 +13608,7 @@ Wil je het bericht bewaren? Voeg extra bestand toe - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -14229,18 +13638,18 @@ Wil je het bericht bewaren? - - + + Close Sluiten - + From: Van: - + Bullet list (disc) @@ -14280,13 +13689,13 @@ Wil je het bericht bewaren? - - + + Thanks, <br> - + Distant identity: @@ -14296,12 +13705,12 @@ Wil je het bericht bewaren? - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -14379,7 +13788,7 @@ Wil je het bericht bewaren? Standaard - + A new tab Een nieuwe tab @@ -14389,7 +13798,7 @@ Wil je het bericht bewaren? Een nieuw scherm - + Edit Tag Bewerk Label @@ -14412,7 +13821,7 @@ Wil je het bericht bewaren? MessageToaster - + Sub: Ond: @@ -14420,7 +13829,7 @@ Wil je het bericht bewaren? MessageUserNotify - + Message Bericht @@ -14448,7 +13857,7 @@ Wil je het bericht bewaren? MessageWidget - + Recommended Files Aanbevolen bestanden @@ -14458,37 +13867,37 @@ Wil je het bericht bewaren? Download alle Aanbevolen bestanden - + Subject: Onderwerp: - + From: Van: - + To: Aan: - + Cc: Cc: - + Bcc: Bcc: - + Tags: Labels: - + Reply Antwoord @@ -14528,7 +13937,7 @@ Wil je het bericht bewaren? - + Send Invite @@ -14580,7 +13989,7 @@ Wil je het bericht bewaren? - + Confirm %1 as friend Bevestig %1 als vriend @@ -14590,12 +13999,12 @@ Wil je het bericht bewaren? Voeg %1 als vriend toe - + View source - + No subject Geen onderwerp @@ -14605,17 +14014,22 @@ Wil je het bericht bewaren? Download - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -14624,14 +14038,24 @@ Wil je het bericht bewaren? %1 (%2) + + + Show less + + + + + Show more + + - + Download all Download alles - + Print Document Print Document @@ -14646,12 +14070,12 @@ Wil je het bericht bewaren? HTML- bestand (*.htm *.html );;Alle bestanden (*) - + Load images always for this message Afbeeldingen altijd laden voor dit bericht - + Hide the attachment pane Het venster bijlage verbergen @@ -14673,42 +14097,6 @@ Wil je het bericht bewaren? Compose Opstellen - - Reply to selected message - Antwoord op geselecteerde bericht - - - Reply - Antwoord - - - Reply all to selected message - Antwoord op alle geselecteerde berichten - - - Reply all - Beantwoord alles - - - Forward selected message - Stuur geselecteerd bericht door - - - Forward - Doorsturen - - - Remove selected message - Verwijder geselecteerde bericht - - - Delete - Verwijderen - - - Print selected message - Print geselecteerd bericht - Print @@ -14787,7 +14175,7 @@ Wil je het bericht bewaren? MessagesDialog - + New Message Nieuw bericht @@ -14797,60 +14185,16 @@ Wil je het bericht bewaren? Opstellen - Reply to selected message - Antwoord op geselecteerde bericht - - - Reply - Antwoord - - - Reply all to selected message - Antwoord op alle geselecteerde berichten - - - Reply all - Beantwoord alles - - - Forward selected message - Stuur geselecteerd bericht door - - - Foward - Doorsturen - - - Remove selected message - Verwijder geselecteerde bericht - - - Delete - Verwijderen - - - Print selected message - Print geselecteerd bericht - - - Print - Print - - - Display - Toon - - - + - - + + Tags Labels - - + + Inbox Inbox @@ -14880,21 +14224,17 @@ Wil je het bericht bewaren? Asbak - + Total Inbox: Totaal inbox: - Folders - Mappen - - - + Quick View Snelle blik - + Print... Print... @@ -14904,26 +14244,6 @@ Wil je het bericht bewaren? Print Preview Print Voorbeeld - - Buttons Icon Only - Alleen knoppen tekst - - - Buttons Text Beside Icon - Knoppen tekst naast ikoon - - - Buttons with Text - Knoppen met tekst - - - Buttons Text Under Icon - Knoppen tekst onder ikoon - - - Set Text Under Icon - PLaats Tekst onder ikoon - Save As... @@ -14945,7 +14265,7 @@ Wil je het bericht bewaren? Stuur bericht door - + Subject Onderwerp @@ -14955,7 +14275,7 @@ Wil je het bericht bewaren? Van - + Date Datum @@ -14965,39 +14285,7 @@ Wil je het bericht bewaren? Inhoud - Click to sort by attachments - Klik om op bijlages te sorteren - - - Click to sort by subject - Klik om op "Onderwerp" te sorteren - - - Click to sort by read - Klik om op "Gelezen" te sorteren - - - Click to sort by from - Klik om op "Afzender" te sorteren - - - Click to sort by date - Klik om op "Datum" te sorteren - - - Click to sort by tags - Klik om op "Labels" te sorteren - - - Click to sort by star - Klik om op "Sterren" te sorteren - - - Forward selected Message - Stuur geselecteerd bericht door - - - + Search Subject Zoek Onderwerp @@ -15006,6 +14294,11 @@ Wil je het bericht bewaren? Search From Zoek van + + + Search To + + Search Date @@ -15032,14 +14325,14 @@ Wil je het bericht bewaren? Zoek Bijlagen - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred - Starred + @@ -15113,7 +14406,7 @@ Wil je het bericht bewaren? - Show author in People + Show in People @@ -15127,7 +14420,7 @@ Wil je het bericht bewaren? - + No message using %1 tag available. @@ -15142,34 +14435,33 @@ Wil je het bericht bewaren? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts Concepten - + No Box selected. - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - Geen "Sterren" berichten aanwezig. Sterren geven je bericht een speciale status zodat je de berichten makkelijker kan vinden. Om een bericht een ster te geven klik je op een lichte grijze ster naast een bericht. - - - No system messages available. - Geen systeem berichten beschikbaar - - + To - Naar + Naar - Click to sort by to - Klik om te sorteren op - - - + @@ -15177,22 +14469,6 @@ Wil je het bericht bewaren? Total: Totaal: - - Messages - Berichten - - - Click to sort by signature - Klik om te sorteren op tekening - - - This message was signed and the signature checks - Dit bericht heeft een valide handtekening - - - This message was signed but the signature doesn't check - Dit bericht heeft een ongeldige handtekening - Mail @@ -15220,7 +14496,17 @@ Wil je het bericht bewaren? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -15274,7 +14560,7 @@ Wil je het bericht bewaren? - + Expand Uitbreiden @@ -15284,7 +14570,7 @@ Wil je het bericht bewaren? Item verwijderen - + from van @@ -15319,7 +14605,7 @@ Wil je het bericht bewaren? Bericht in behandeling - + Hide Verberg @@ -15460,7 +14746,7 @@ Wil je het bericht bewaren? Verbindings ID - + Remove unused keys... Verwijder ongebruikte sleutels... @@ -15470,7 +14756,7 @@ Wil je het bericht bewaren? - + Clean keyring Schoon sleutelring @@ -15488,7 +14774,13 @@ Opmerkingen: Je oude sleutelbos zal gebackupped worden. Deze operatie kan mislukken als er meerdere Retroshare instanties draaien op dezelfde machine. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info Sleutelring info @@ -15524,18 +14816,13 @@ Voor de veiligheid is je sleutelbos gebackupped. Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. Datainconsistentie in de sleutelbos. Dit is hoogstwaarschijnlijk een bug. Neem contact op met de ontwikkelaars. - - - Export/create a new node - - Trusted keys only - + Search name @@ -15545,25 +14832,18 @@ Voor de veiligheid is je sleutelbos gebackupped. - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: - - NetworkPage - - Network - Netwerk - - NetworkView @@ -15590,7 +14870,7 @@ Reported error: NewFriendList - + Offline Friends @@ -15611,7 +14891,7 @@ Reported error: - + Groups Groepen @@ -15641,19 +14921,19 @@ Reported error: importeer vriendenlijst, inclusief groepen - - + + Search - + ID ID - + Search ID @@ -15663,12 +14943,12 @@ Reported error: - + Show Items - + Last contact @@ -15678,7 +14958,7 @@ Reported error: IP - + Group Groep @@ -15793,7 +15073,7 @@ Reported error: - + Do you want to remove this node? @@ -15803,7 +15083,7 @@ Reported error: Wil je deze vriend verwijderen= - + Done! Klaar! @@ -15910,7 +15190,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -15925,11 +15205,7 @@ at least one peer was not added to a group Verwijder alles - This is a test. - Dit is een test. - - - + Newest on top @@ -15939,12 +15215,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15999,10 +15275,6 @@ at least one peer was not added to a group Blogs Blogs - - Security - Veiligheid - @@ -16024,10 +15296,6 @@ at least one peer was not added to a group Message Bericht - - Connect attempt - Verbindings poging - @@ -16181,10 +15449,6 @@ at least one peer was not added to a group Disable All Toaster temporarily Alle Toasters tijdelijk uitschakelen - - Feed - Feed - Systray @@ -16194,7 +15458,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -16214,12 +15478,12 @@ at least one peer was not added to a group Foutief wachtwoord! - + Please enter your Retroshare passphrase - + Unregistered plugin/executable Ongeregistreerde plugin/executable @@ -16234,19 +15498,7 @@ at least one peer was not added to a group Controleer uw systeem klok - Examining shared files... - Onderzoek van gedeelde bestanden... - - - Hashing file - Indexeren van bestanden - - - Saving file index... - Bestands index opslaan... - - - + Test Test @@ -16257,17 +15509,19 @@ at least one peer was not added to a group + Unknown title Onbekende titel - + + Encrypted message Versleutelde berichten - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -16275,7 +15529,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online Vriend online @@ -16327,10 +15581,6 @@ Laag verkeer: 10% standaard verkeerd en TODO: pauseerd alle bestands overdrachte PGPKeyDialog - - Dialog - Dialoog - Profile info @@ -16421,7 +15671,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -16430,10 +15685,6 @@ p, li { white-space: pre-wrap; } Keysigning: - - Sign PGP key - Onderteken PGP Sleutel - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -16470,19 +15721,14 @@ p, li { white-space: pre-wrap; } Inclusief handtekeningen - - Options - Opties - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> Use as direct source, when available - + Gebruiken als directe bron, indien beschikbaar @@ -16521,21 +15767,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - - + + Error : cannot get peer details. Error: kan geen verbindings gegevens vinden. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) De ingevoerde sleutel algoritme wordt niet ondersteund door RetroShare⏎ @@ -16554,7 +15800,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -16623,10 +15869,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Check the password! - - Maybe password is wrong - Misschien is uw wachtwoord fout - You haven't set a trust level for this key. @@ -16634,12 +15876,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -16665,7 +15907,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat Chat @@ -16686,7 +15928,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Item verwijderen - + Name: Naam: @@ -16726,7 +15968,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message Schrijf een bericht @@ -16740,10 +15982,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Friend Connected Vriend verbonden - - Connect Attempt - Verbindings poging - Connection refused by peer @@ -16782,17 +16020,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.Unknown Onbekend - - Unknown Peer - Onbekende Verbinding - Hide Verberg - + Send Message Verstuur bericht @@ -16959,13 +16193,6 @@ Warning: In your File-Transfer option, you select allow direct download to No. - - PhotoCommentItem - - Form - Formulier - - PhotoDialog @@ -16973,23 +16200,11 @@ Warning: In your File-Transfer option, you select allow direct download to No.PhotoShare PhotoShare - - Photo - Foto - TextLabel Tekst label - - Comment - Opmerkingen - - - Summary - Overzicht - Album / Photo Name @@ -17050,14 +16265,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.... ... - - Add Comment - Een opmerking toevoegen - - - Write a comment... - Schrijf een opmerking - Album @@ -17128,10 +16335,6 @@ p, li { white-space: pre-wrap; }⏎ Create Album Maak album - - View Album - Bekijk Album - Edit Album Details @@ -17153,17 +16356,17 @@ p, li { white-space: pre-wrap; }⏎ Slide Show - + My Albums Mijn Albums - + Subscribed Albums Geabonneerde Albums - + Shared Albums Gedeelde Albums @@ -17193,7 +16396,7 @@ voordat je het kunt bewerken! PhotoSlideShow - + Album Name Album Naam @@ -17252,19 +16455,19 @@ voordat je het kunt bewerken! - - + + TextLabel Tekst label - + Posted by - + ago @@ -17300,12 +16503,12 @@ voordat je het kunt bewerken! PluginItem - + TextLabel Tekst label - + Show more details about this plugin Toon meer gegevens van deze plugin @@ -17451,41 +16654,6 @@ p, li { white-space: pre-wrap; }⏎ Plugin look-up directories Plugin look-up directories - - No API number supplied. Please read plugin development manual. - Geen API nummer gevonden. Lees de plugin ontwerp handleiding. - - - No SVN number supplied. Please read plugin development manual. - Geen SVN nummer gevonden. Lees de plugin ontwerp handleiding. - - - Loading error. - Laad error. - - - Missing symbol. Wrong version? - Er mist een symbool. Verkeerde versie? - - - No plugin object - Geen plugin object - - - Plugins is loaded. - Plugin is geladen - - - Unknown status. - Onbekende status - - - Check this for developing plugins. They will not -be checked for the hash. However, in normal -times, checking the hash protects you from -malicious behavior of crafted plugins. - Controleer dit voor plugin ontwikkeling. Zij worden niet gecontroleerd voor de index. Echter, gewoonlijk zal het controleren van de index je beschermen tegen verdacht gebruik van de plugins - Plugins @@ -17555,12 +16723,27 @@ malicious behavior of crafted plugins. Zet scherm boven - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -17594,14 +16777,6 @@ malicious behavior of crafted plugins. Close conversation? - - Closing this window will end the conversation, notify the peer and remove the encrypted tunnel. - Het sluiten van dit venster zal het gesprek beëindigen en de chat-tunnel verwijderen. - - - Kill the tunnel? - Verwijder de tunnel? - PostedCardView @@ -17621,7 +16796,7 @@ malicious behavior of crafted plugins. Nieuw - + Vote up Stemmen van @@ -17641,8 +16816,8 @@ malicious behavior of crafted plugins. \/ - - + + Comments Opmerkingen @@ -17667,13 +16842,13 @@ malicious behavior of crafted plugins. - - + + Comment - + Comments @@ -17701,20 +16876,12 @@ malicious behavior of crafted plugins. PostedCreatePostDialog - Signed by: - Ondertekend door: - - - Notes - Notities - - - + Create a new Post - + RetroShare RetroShare @@ -17729,12 +16896,22 @@ malicious behavior of crafted plugins. - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File Laad images bestand - + Post image @@ -17750,7 +16927,17 @@ malicious behavior of crafted plugins. - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -17760,23 +16947,7 @@ malicious behavior of crafted plugins. - Submit Post - Bevestig Bericht - - - You are submitting a link. The key to a successful submission is interesting content and a descriptive title. - U verzendt een link. De sleutel tot een succesvolle indiening is interessante inhoud en een beschrijvende titel. - - - Submit - Bevestig - - - Submit a new Post - Een nieuw bericht verzenden - - - + Please add a Title Voeg een titel toe @@ -17796,12 +16967,22 @@ malicious behavior of crafted plugins. - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -17816,7 +16997,7 @@ malicious behavior of crafted plugins. - + Post @@ -17827,7 +17008,7 @@ malicious behavior of crafted plugins. PLaatje - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -17837,7 +17018,7 @@ malicious behavior of crafted plugins. Titel - + Link Koppeling @@ -17845,36 +17026,12 @@ malicious behavior of crafted plugins. PostedDialog - Posted Links - Geposte Links - - - Create Topic - Thema aanmaken - - - My Topics - Mijn Onderwerpen - - - Subscribed Topics - Geabonneerde Onderwerpen - - - Popular Topics - Populaire Onderwerpen - - - Other Topics - Andere Onderwerpen - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -17908,31 +17065,7 @@ malicious behavior of crafted plugins. PostedGroupDialog - Posted Topic - Geplaatst Onderwerp - - - Add Topic Admins - Admins onderwerp toevoegen - - - Select Topic Admins - Selcteer Admins onderwerp - - - Create New Topic - Maak een nieuw onderwerp - - - Edit Topic - Onderwerp bewerken - - - Update Topic - Bijwerken van onderwerp - - - + Create New Board @@ -17970,7 +17103,17 @@ malicious behavior of crafted plugins. PostedGroupItem - + + Last activity + + + + + TextLabel + Tekst label + + + Subscribe to Posted Abonneren op onderwerp @@ -17986,7 +17129,7 @@ malicious behavior of crafted plugins. - + Expand Uitbreiden @@ -18001,24 +17144,17 @@ malicious behavior of crafted plugins. - Posted Description - Geplaatste beschrijving - - - Loading - Laden - - - New Posted - Nieuw geplaatst - - - + Loading... - + + Never + + + + New Board @@ -18031,22 +17167,18 @@ malicious behavior of crafted plugins. PostedItem - + 0 0 - Site - Site - - - - + + Comments Opmerkingen - + Copy RetroShare Link Kopieer RetroShare Link @@ -18057,12 +17189,12 @@ malicious behavior of crafted plugins. - + Comment Opmerking - + Comments @@ -18072,7 +17204,7 @@ malicious behavior of crafted plugins. - + Click to view Picture @@ -18082,21 +17214,17 @@ malicious behavior of crafted plugins. - + Vote up Stemmen van - + Vote down Wegstemmen - \/ - \/ - - - + Set as read and remove item Markeer als gelezen en verplaats item @@ -18106,7 +17234,7 @@ malicious behavior of crafted plugins. Nieuw - + New Comment: @@ -18116,7 +17244,7 @@ malicious behavior of crafted plugins. - + Name Naam @@ -18157,73 +17285,10 @@ malicious behavior of crafted plugins. Tekst label - + Loading Laden - - By - Door - - - - PostedListWidget - - Form - Formulier - - - Hot - Hot - - - New - Nieuw - - - Top - Boven - - - Today - Vandaag - - - Yesterday - Gisteren - - - This Week - Deze Week - - - This Month - Deze Maand - - - This Year - Dit Jaar - - - Submit a new Post - Een nieuw bericht verzenden - - - Next - Volgend - - - RetroShare - RetroShare - - - Please create or choose a Signing Id before Voting - Maak of kies een teken-identiteit voor het stemmen - - - Previous - Vorige - PostedListWidgetWithModel @@ -18243,7 +17308,17 @@ malicious behavior of crafted plugins. - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -18253,15 +17328,15 @@ malicious behavior of crafted plugins. - + - + unknown onbekend - + Distribution: @@ -18271,42 +17346,42 @@ malicious behavior of crafted plugins. - + Created - + TextLabel Tekst label - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -18326,7 +17401,7 @@ malicious behavior of crafted plugins. Hot - + Search @@ -18356,17 +17431,17 @@ malicious behavior of crafted plugins. - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -18381,12 +17456,17 @@ malicious behavior of crafted plugins. - + Copy RetroShare Link Kopieer RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -18396,27 +17476,31 @@ malicious behavior of crafted plugins. Bewerk - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -18431,7 +17515,7 @@ malicious behavior of crafted plugins. Registreren - + Never @@ -18505,6 +17589,16 @@ malicious behavior of crafted plugins. No Channel Selected Geen kanaal geselecteerd + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -18513,10 +17607,6 @@ malicious behavior of crafted plugins. Tabs Tabblad - - Open each topic in a new tab - Elk onderwerp openen in een nieuw tabblad - Open each board in a new tab @@ -18530,10 +17620,6 @@ malicious behavior of crafted plugins. PostedUserNotify - - Posted - Gepost - Board Post @@ -18602,16 +17688,16 @@ malicious behavior of crafted plugins. Profiel Beheerder - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -18723,7 +17809,7 @@ en daar de importeer functie gebruiken ProfileWidget - + Edit status message Bewerk berichten status @@ -18739,7 +17825,7 @@ en daar de importeer functie gebruiken Profiel Beheerder - + Public Information Publieke informatie @@ -18774,12 +17860,12 @@ en daar de importeer functie gebruiken Online sinds: - + Other Information Andere informatie - + My Address Mijn adres @@ -18823,51 +17909,27 @@ en daar de importeer functie gebruiken PulseAddDialog - Post From: - Bericht van: - - - Account 1 - Account 1 - - - Account 2 - Account 2 - - - Account 3 - Account 3 - - - + Add to Pulse Voeg aan Pulse toe - filter - filter - - - URL Adder - URL toevoeger - - - + Display As Toon als - + URL URL - + GroupLabel - + IDLabel @@ -18877,12 +17939,12 @@ en daar de importeer functie gebruiken Van: - + Head - + Head Shot @@ -18912,13 +17974,13 @@ en daar de importeer functie gebruiken - - + + Whats happening? - + @@ -18930,12 +17992,22 @@ en daar de importeer functie gebruiken - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -18944,17 +18016,13 @@ en daar de importeer functie gebruiken Cancel Annuleren - - Post Pulse to Wire - Post Pulse to Wire - Post - + Reply to Pulse @@ -18969,34 +18037,24 @@ en daar de importeer functie gebruiken - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - Van - - - Date - Datum - - - ... - ... + + Load Picture File + Laad images bestand @@ -19007,7 +18065,7 @@ en daar de importeer functie gebruiken Formulier - + @@ -19026,7 +18084,7 @@ en daar de importeer functie gebruiken PulseReply - + icn @@ -19036,7 +18094,7 @@ en daar de importeer functie gebruiken - + REPLY @@ -19063,7 +18121,7 @@ en daar de importeer functie gebruiken - + FOLLOW @@ -19073,7 +18131,7 @@ en daar de importeer functie gebruiken - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -19093,7 +18151,7 @@ en daar de importeer functie gebruiken - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -19209,7 +18267,7 @@ en daar de importeer functie gebruiken - + FOLLOW @@ -19217,37 +18275,42 @@ en daar de importeer functie gebruiken PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -19279,7 +18342,7 @@ en daar de importeer functie gebruiken - + FOLLOW @@ -19287,8 +18350,8 @@ en daar de importeer functie gebruiken QObject - - + + Confirmation Bevestiging @@ -19559,12 +18622,12 @@ Karakters <b>",|,/,\,&lt;,&gt;,*,?</b> worden vervangen Verbindings details - + File Request canceled Bestands aanvraag gestopt - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. Deze versie van RetroShare maakt gebruik van OpenPGP-SDK. Als bijeffect gebruikt het niet de gedeelde PGP sleutelring maar heeft zijn eigen sleutelring die gebruikt wordt door alle RetroShare gevallen.<br><br> @@ -19595,7 +18658,7 @@ Karakters <b>",|,/,\,&lt;,&gt;,*,?</b> worden vervangen Een onverwachte error verscheen. Stuur een report 'RsInit::InitRetroShare onverwachte return code %1'. - + Cannot start Tor Manager! @@ -19629,7 +18692,7 @@ The error reported is:" - + Multiple instances Meerdere gevallen @@ -19652,6 +18715,26 @@ Lock file:⏎ Lock file:⏎ + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -19732,7 +18815,7 @@ De error is: %2 Gegevens doorsturen - + You appear to have nodes associated to DSA keys: @@ -19742,7 +18825,7 @@ De error is: %2 - + enabled @@ -19752,7 +18835,7 @@ De error is: %2 - + Move IP %1 to whitelist @@ -19768,7 +18851,7 @@ De error is: %2 - + %1 seconds ago @@ -19835,7 +18918,7 @@ Security: no anonymous IDs - + Join chat room @@ -19863,7 +18946,7 @@ Security: no anonymous IDs - + Indefinitely @@ -20043,13 +19126,29 @@ Security: no anonymous IDs Ban list + + + Name + Naam + + Node + Knooppunt + + + + Address + + + + + Status Status - + NXS @@ -20292,6 +19391,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -20454,7 +19565,7 @@ p, li { white-space: pre-wrap; }⏎ - + Network Wide Netwerk breed @@ -20634,7 +19745,7 @@ p, li { white-space: pre-wrap; }⏎ Formulier - + The loading of embedded images is blocked. Het laden van ingesloten afbeeldingen is geblokkeerd. @@ -20647,7 +19758,7 @@ p, li { white-space: pre-wrap; }⏎ RSPermissionMatrixWidget - + Allowed by default @@ -20820,12 +19931,22 @@ p, li { white-space: pre-wrap; }⏎ RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -20833,12 +19954,12 @@ p, li { white-space: pre-wrap; }⏎ RSTreeWidget - + Tree View Options - + Show Header @@ -21530,7 +20651,7 @@ Als u denkt dat het is juist dat, de bijbehorende regel uit het bestand verwijde RsDownloadListModel - + Name i.e: file name Naam @@ -21651,7 +20772,7 @@ Als u denkt dat het is juist dat, de bijbehorende regel uit het bestand verwijde RsFriendListModel - + Name Naam @@ -21671,7 +20792,7 @@ Als u denkt dat het is juist dat, de bijbehorende regel uit het bestand verwijde IP - + Profile ID @@ -21727,7 +20848,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -21741,11 +20862,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - [ ... Bericht ontbreekt ... ] - RsMessageModel @@ -21759,6 +20875,11 @@ prevents the message to be forwarded to your friends. From Van + + + To + Naar + Subject @@ -21781,13 +20902,18 @@ prevents the message to be forwarded to your friends. - Click to sort by read - Klik om op "Gelezen" te sorteren + Click to sort by read status + - Click to sort by from - Klik om op "Afzender" te sorteren + Click to sort by author + + + + + Click to sort by destination + @@ -21810,7 +20936,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -21831,7 +20959,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. Resets ALLE opgslagen RetroShare instellingen @@ -21892,7 +21020,7 @@ prevents the message to be forwarded to your friends. Stel RetroShare's taal in. - + Unable to open log file '%1': %2 Het is niet mogelijk om het log bestand '%1': %2 te openen @@ -21913,7 +21041,7 @@ prevents the message to be forwarded to your friends. Kan geen gegevensmap maken: %1 - + opmode @@ -21943,7 +21071,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -21961,7 +21089,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -21978,12 +21106,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) Plaats een sleutelwoord hier (minstens 3 karakters) - + Start Search Start zoeken @@ -22045,7 +21173,7 @@ prevents the message to be forwarded to your friends. Leeg - + KeyWords Sleutelwoorden @@ -22060,7 +21188,7 @@ prevents the message to be forwarded to your friends. Zoek ID - + Filename Bestandsnaam @@ -22160,23 +21288,23 @@ prevents the message to be forwarded to your friends. Download geselecteerd - + File Name Bestandsnaam - + Download Download - + Copy RetroShare Link Kopieer RetroShare Link - + Send RetroShare Link Stuur RetroShare link @@ -22186,7 +21314,7 @@ prevents the message to be forwarded to your friends. - + Download Notice Download @@ -22223,7 +21351,7 @@ prevents the message to be forwarded to your friends. Verwijder alles - + Folder Map @@ -22234,17 +21362,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) Nieuwe RetroShare link(s) - + Open Folder Open map - + Create Collection... Collectie maken... @@ -22264,7 +21392,7 @@ prevents the message to be forwarded to your friends. Download van collectief bestand... - + Collection Collectie @@ -22272,7 +21400,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details Verbindings details @@ -22288,22 +21416,22 @@ prevents the message to be forwarded to your friends. Item verwijderen - + IP address: - + Peer ID: Verbindings ID: - + Location: Woonplaats: - + Peer Name: @@ -22320,7 +21448,7 @@ prevents the message to be forwarded to your friends. Verbergen - + but reported: @@ -22345,8 +21473,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -22354,7 +21482,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare wil vrienden zijn met je op RetroShare @@ -22385,7 +21513,7 @@ prevents the message to be forwarded to your friends. - + Expand Uitbreiden @@ -22430,12 +21558,12 @@ prevents the message to be forwarded to your friends. Status: - + Write Message Schrijf een bericht - + Connect Attempt Verbindings poging @@ -22455,17 +21583,22 @@ prevents the message to be forwarded to your friends. Onbekende (uitgaande) verbindings poging - + Unknown Security Issue Onbekend veiligheids probleem - - A unknown peer + + SSL request - + + An unknown peer + + + + Unknown Onbekend @@ -22475,11 +21608,7 @@ prevents the message to be forwarded to your friends. - Unknown Peer - Onbekenden verbinding - - - + Hide Verberg @@ -22489,7 +21618,7 @@ prevents the message to be forwarded to your friends. Wil je deze vriend verwijderen= - + Certificate has wrong signature!! This peer is not who he claims to be. Certificaat heeft verkeerde handtekening! Deze verbinding is niet wie hij beweert te zijn. @@ -22499,12 +21628,12 @@ prevents the message to be forwarded to your friends. Ontbrekende/Beschadigd certificaat. Niet een echte Retroshare gebruiker. - + Certificate caused an internal error. Certificaat heeft een interne fout veroorzaakt. - + Peer/node not in friendlist (PGP id= @@ -22563,12 +21692,12 @@ prevents the message to be forwarded to your friends. - + Local Address Lokaal adres - + NAT @@ -22589,22 +21718,22 @@ prevents the message to be forwarded to your friends. Poort: - + Local network Lokaal Netwerk - + External ip address finder Extern ip adres vinder - + UPnP UPnP - + Known / Previous IPs: Bekende / Eerdere IP's: @@ -22620,21 +21749,16 @@ kun je makkelijker verbonden worden met je vrienden. Het helpt⏎ je ook als ja achter een Firewall of VPN zit. - - Allow RetroShare to ask my ip to these websites: - Sta RetroShare toe om mijn ip-adres te vragen aan de volgende websites: - - - - - + + + kB/s kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. Aanvaardbare poorten variëren van 10 tot 65535. Normaal zijn poorten onder 1024 gereserveerd door uw systeem. @@ -22644,23 +21768,46 @@ je ook als ja achter een Firewall of VPN zit. Aanvaardbare poorten variëren van 10 tot 65535. Normaal zijn poorten onder 1024 gereserveerd door uw systeem. - + Onion Address UI adres - + Discovery On (recommended) Discovery ingeschakeld (aanbevolen) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off Ontdekking uit @@ -22670,7 +21817,7 @@ je ook als ja achter een Firewall of VPN zit. - + I2P Address @@ -22695,37 +21842,95 @@ je ook als ja achter een Firewall of VPN zit. - - + + + Proxy seems to work. Proxy lijkt te werken. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -22740,71 +21945,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. onbekend - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -22814,22 +21955,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -22841,12 +21967,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -22856,7 +21982,7 @@ Also check your ports! Leeg - + Download limit (KB/s) @@ -22871,23 +21997,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -22898,17 +22024,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -22918,12 +22034,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -22933,17 +22044,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 127.0.0.1 - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -22983,7 +22084,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start Start @@ -22998,12 +22099,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why Stop - - BOB status - - - - + Incoming Binnenkomend @@ -23039,7 +22135,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -23094,7 +22215,7 @@ If you have issues connecting over Tor check the Tor logs too. Totaal: - + Warning: This bandwidth adds up to the max bandwidth. @@ -23119,7 +22240,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -23131,7 +22252,7 @@ If you have issues connecting over Tor check the Tor logs too. Netwerk - + IP Filters @@ -23154,7 +22275,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status Status @@ -23214,17 +22335,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -23240,18 +22372,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -23286,12 +22418,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -23314,22 +22446,22 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -23364,7 +22496,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -23374,12 +22506,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -23459,7 +22591,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with Controleer welke verbinding je wilt delen met een openbare Privé Sleutel @@ -23469,12 +22601,12 @@ If you have issues connecting over Tor check the Tor logs too. Delen voor vriend - + Share Deel - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. U kunt uw vrienden laten weten over uw kanaal door met hen te delen. @@ -23494,7 +22626,7 @@ Selecteer de vrienden waarmee u uw kanaal wilt delen. Gedeelde mappen manager - + Shared directory @@ -23514,17 +22646,17 @@ Selecteer de vrienden waarmee u uw kanaal wilt delen. Zichtbaarheid - + Add new - + Cancel Annuleren - + Add a Share Directory Voeg een gedeelde directory toe @@ -23534,7 +22666,7 @@ Selecteer de vrienden waarmee u uw kanaal wilt delen. Verwijderen - + Apply and close Toepassen en sluiten @@ -23625,7 +22757,7 @@ Selecteer de vrienden waarmee u uw kanaal wilt delen. directory niet gevonden of directory naam niet geaccepteerd - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. Dit is een lijst van gedeelde mappen. U kunt toevoegen en verwijderen van mappen met behulp van de knoppen aan de onderkant. Wanneer u een nieuwe map, aanvankelijk alle bestanden in die map worden gedeeld. U kunt delen vlaggen voor elke gedeelde map afzonderlijk instellen. @@ -23633,7 +22765,7 @@ Selecteer de vrienden waarmee u uw kanaal wilt delen. SharedFilesDialog - + Files Bestanden @@ -23684,11 +22816,16 @@ Selecteer de vrienden waarmee u uw kanaal wilt delen. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files controleer bestanden - + Download selected Download geselecteerd @@ -23698,7 +22835,7 @@ Selecteer de vrienden waarmee u uw kanaal wilt delen. Download - + Copy retroshare Links to Clipboard Kopieer Retroshare link naar het klembord @@ -23713,7 +22850,7 @@ Selecteer de vrienden waarmee u uw kanaal wilt delen. Stuur RetroShare links - + Some files have been omitted @@ -23729,7 +22866,7 @@ Selecteer de vrienden waarmee u uw kanaal wilt delen. Aanbeveling(en) - + Create Collection... Collectie maken... @@ -23754,7 +22891,7 @@ Selecteer de vrienden waarmee u uw kanaal wilt delen. Download van collectief bestand... - + Some files have been omitted because they have not been indexed yet. @@ -23897,12 +23034,12 @@ Selecteer de vrienden waarmee u uw kanaal wilt delen. SplashScreen - + Load configuration Laad configuratie - + Create interface Maak interface @@ -23926,7 +23063,7 @@ Selecteer de vrienden waarmee u uw kanaal wilt delen. Onthoudt wachtwoord - + Log In Log In @@ -24267,7 +23404,7 @@ This choice can be reverted in settings. Berichten status - + Message: Bericht: @@ -24512,7 +23649,7 @@ p, li { white-space: pre-wrap; }⏎ TagsMenu - + Remove All Tags Verwijder alle labels @@ -24548,12 +23685,15 @@ p, li { white-space: pre-wrap; }⏎ - + + Tor status: - + + + Unknown Onbekend @@ -24563,18 +23703,13 @@ p, li { white-space: pre-wrap; }⏎ - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -24584,12 +23719,57 @@ p, li { white-space: pre-wrap; }⏎ - + + Error + + + + + Not connected + Niet verbonden + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -24597,7 +23777,7 @@ p, li { white-space: pre-wrap; }⏎ TorStatus - + Tor @@ -24607,7 +23787,7 @@ p, li { white-space: pre-wrap; }⏎ - + Tor is currently offline @@ -24618,11 +23798,12 @@ p, li { white-space: pre-wrap; }⏎ + No tor configuration - + Tor proxy is OK @@ -24650,7 +23831,7 @@ p, li { white-space: pre-wrap; }⏎ TransferPage - + Transfer options Overdrachts opties @@ -24661,7 +23842,7 @@ p, li { white-space: pre-wrap; }⏎ Maximum gelijktijdige downloads: - + Shared Directories @@ -24671,22 +23852,27 @@ p, li { white-space: pre-wrap; }⏎ Deel automatisch uw opslag directory (Aanbevolen) - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -24771,7 +23957,7 @@ p, li { white-space: pre-wrap; }⏎ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -24780,7 +23966,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -24805,7 +23996,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming Streaming @@ -24870,12 +24066,7 @@ p, li { white-space: pre-wrap; } Max. tunnel aanvraag. doorgestuurd per seconde: - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -24885,7 +24076,17 @@ p, li { white-space: pre-wrap; } - + + Warning + Waarschuwing + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -24913,7 +24114,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed Download klaar @@ -24937,39 +24138,23 @@ p, li { white-space: pre-wrap; } %1 completed transfer - - You have %1 completed downloads - Je hebt %1 complete downloads - - - You have %1 completed download - Je hebt %1 complete download - - - %1 completed downloads - %1 complete downloads - - - %1 completed download - %1 complete download - TransfersDialog - - + + Downloads Downloads - + Uploads Uploads - + Name i.e: file name Naam @@ -25176,7 +24361,12 @@ p, li { white-space: pre-wrap; } Specificeer... - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... Verplaats in Rij... @@ -25201,7 +24391,7 @@ p, li { white-space: pre-wrap; } Kies directory - + Anonymous end-to-end encrypted tunnel 0x @@ -25222,7 +24412,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -25255,7 +24445,17 @@ p, li { white-space: pre-wrap; } Bestand %1 is niet kompleet. Als het een media bestand is probeer deze te openen. - + + Warning + Waarschuwing + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name Verander bestandsnaam @@ -25270,7 +24470,7 @@ p, li { white-space: pre-wrap; } Vul een nieuwe -en geldige- bestandsnaam in - + Expand all Alles uitklappen @@ -25397,23 +24597,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Kolommen - + File Transfers Bestandsoverdrachten - + Path Pad @@ -25423,7 +24618,7 @@ p, li { white-space: pre-wrap; } Pad kolom weergeven - + Could not delete preview file Kan geen gegevens verwijderen voorvertoningsbestand @@ -25433,7 +24628,7 @@ p, li { white-space: pre-wrap; } Probeer het opnieuw? - + Create Collection... Collectie maken.. @@ -25448,7 +24643,7 @@ p, li { white-space: pre-wrap; } Bekijk collectie.. - + Collection Collectie @@ -25458,7 +24653,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x Anonieme tunnel 0x @@ -25587,7 +24782,7 @@ p, li { white-space: pre-wrap; } Unknown Peer - + Onbekenden verbinding @@ -25872,12 +25067,17 @@ p, li { white-space: pre-wrap; } Formulier - + Enable Retroshare WEB Interface - + + Status: + Status: + + + Web parameters @@ -25917,17 +25117,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -25937,12 +25147,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface @@ -26079,11 +25289,7 @@ p, li { white-space: pre-wrap; } Wiki pagina's - New Group - Nieuwe Groep - - - + Page Name Pagina Naam @@ -26098,7 +25304,7 @@ p, li { white-space: pre-wrap; } Orig Id - + << << @@ -26186,7 +25392,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History Pagina Bewerkte Geschiedenis @@ -26221,7 +25427,7 @@ p, li { white-space: pre-wrap; } PaginaID - + \/ \/ @@ -26251,14 +25457,18 @@ p, li { white-space: pre-wrap; } Labels - - + + History + Geschiedenis + + + Show Edit History Toon Bewerkte Geschiedenis - + Status Status @@ -26279,7 +25489,7 @@ p, li { white-space: pre-wrap; } Omkeren - + Submit Bevestig @@ -26351,10 +25561,6 @@ p, li { white-space: pre-wrap; } WireDialog - - TimeRange - TimeRange - Create Account @@ -26366,16 +25572,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - Ververs - - - + Settings @@ -26390,7 +25587,7 @@ p, li { white-space: pre-wrap; } Anderen - + Who to Follow @@ -26410,7 +25607,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -26440,85 +25637,17 @@ p, li { white-space: pre-wrap; } - Last Month - Verleden Maand - - - Last Week - Verleden Week - - - Today - Vandaag - - - New - Nieuw - - - from - van - - - until - totdat - - - Search/Filter - Zoek/Filter - - - Network Wide - Netwerk breed - - - Manage Accounts - Beheer Accounts - - - Showing: - Toon: - - - + Yourself Uzelf - - Friends - Vrienden - Following Volgend - Custom - Custom - - - Account 1 - Account 1 - - - Account 2 - Account 2 - - - Account 3 - Account 3 - - - CheckBox - CheckBox - - - Post Pulse to Wire - Post Pulse to Wire - - - + RetroShare RetroShare @@ -26581,35 +25710,42 @@ p, li { white-space: pre-wrap; } Formulier - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + Verwijderen + + + Location: Woonplaats: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -26654,11 +25790,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + + + + + Following + Volgend + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Onbekend @@ -26736,7 +25902,7 @@ p, li { white-space: pre-wrap; } %1y %2d - + k e.g: 3.1 k k @@ -26773,7 +25939,7 @@ p, li { white-space: pre-wrap; } pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_pl.ts b/retroshare-gui/src/lang/retroshare_pl.ts index ef7478036..637121e24 100644 --- a/retroshare-gui/src/lang/retroshare_pl.ts +++ b/retroshare-gui/src/lang/retroshare_pl.ts @@ -84,13 +84,6 @@ - - AddCommentDialog - - Add Comment - Dodaj komentarz - - AddFileAssociationDialog @@ -129,12 +122,12 @@ RetroShare: Wyszukiwanie zaawansowane - + Search Criteria Kryteria wyszukiwania - + Add a further search criterion. Dodaj następne kryterium wyszukiwania. @@ -144,7 +137,7 @@ Resetuj kryteria wyszukiwania. - + Cancels the search. Anuluj wyszukiwanie. @@ -164,109 +157,6 @@ Szukaj - - AlbumCreateDialog - - Create Album - Utwórz album - - - Album Name: - Nazwa albumu: - - - Category: - Kategoria: - - - Animals - Zwierzęta - - - Family - Rodzina - - - Friends - Przyjaciele - - - Flowers - Kwiaty - - - Holiday - Wakacje - - - Pets - Zwierzęta - - - Travel - Podróż - - - Work - Praca - - - Random - Losowe - - - Where: - Gdzie: - - - Photographer: - Fotograf: - - - Description: - Opis - - - Quality: - Jakość: - - - Comments: - Komentarze: - - - Public - Publiczne - - - No Comments Allowed - Komentowanie zabronione - - - Authenticated Comments - Komentarze dozwolone - - - Any Comments Allowed - Jakiekolwiek komentarze dozwolone - - - Back - Wstecz - - - Add Photos - Dodaj zdjęcia - - - Publish Album - Publikuj album - - - Say something about this album... - Powiedz coś o tym albumie... - - AlbumDialog @@ -280,10 +170,6 @@ TextLabel - - Summary - Podsumowanie - Album Title: @@ -299,26 +185,6 @@ Caption - - Where: - Gdzie: - - - When - Kiedy - - - Description: - Opis - - - Comments - Komentarze - - - Visibility - Widoczność - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -683,7 +549,7 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. @@ -709,10 +575,23 @@ p, li { white-space: pre-wrap; } + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb %p Kb @@ -755,7 +634,7 @@ p, li { white-space: pre-wrap; } Usuń - + Set your Avatar picture @@ -842,22 +721,10 @@ p, li { white-space: pre-wrap; } Zresetuj - Receive Rate - Prędkość pobierania - - - Send Rate - Prędkość wysyłania - - - + Always on Top Zawsze na wierzchu - - Style - Styl - Changes the transparency of the Bandwidth Graph @@ -873,23 +740,11 @@ p, li { white-space: pre-wrap; } % Opaque % nieprzezroczysty - - Save - Zapisz - - - Cancel - Anuluj - Since: Od: - - Hide Settings - Ukryj ustawienia - BandwidthStatsWidget @@ -962,7 +817,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment @@ -992,12 +847,12 @@ p, li { white-space: pre-wrap; } - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -1005,7 +860,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up @@ -1025,7 +880,7 @@ p, li { white-space: pre-wrap; } \/ - + Posted by @@ -1063,7 +918,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up @@ -1083,7 +938,7 @@ p, li { white-space: pre-wrap; } \/ - + Click to view picture @@ -1113,7 +968,7 @@ p, li { white-space: pre-wrap; } - + Toggle Message Read Status Przełącz status przeczytanej wiadomości @@ -1123,7 +978,7 @@ p, li { white-space: pre-wrap; } Nowy - + TextLabel @@ -1131,12 +986,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this - + 0 0 @@ -1156,18 +1011,18 @@ p, li { white-space: pre-wrap; } Awatar - + New Comment - + Copy RetroShare Link - + Expand Rozwiń @@ -1182,12 +1037,12 @@ p, li { white-space: pre-wrap; } Usuń element - + Name - + Comm value @@ -1356,17 +1211,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels Kanały - + Tabs - + General Ogólne @@ -1376,7 +1231,17 @@ p, li { white-space: pre-wrap; } - + + Downloads + Pobierania + + + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab @@ -1384,7 +1249,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1407,7 +1272,7 @@ into the image, so as to ChannelsCommentsItem - + I like this @@ -1432,18 +1297,18 @@ into the image, so as to Awatar - + New Comment - + Copy RetroShare Link - + Expand Rozwiń @@ -1458,7 +1323,7 @@ into the image, so as to Usuń element - + Name @@ -1468,17 +1333,7 @@ into the image, so as to - - Comment - - - - - Comments - - - - + Hide Ukryj @@ -1486,7 +1341,7 @@ into the image, so as to ChatLobbyDialog - + Name @@ -1677,7 +1532,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby Pokaż lobby rozmów @@ -1689,22 +1544,6 @@ into the image, so as to Chats - - You have %1 new messages - Masz %1 nowych wiadomości - - - You have %1 new message - Masz %1 nową wiadomość - - - %1 new messages - %1 nowych wiadomości - - - %1 new message - %1 nowa wiadomość - You have %1 mentions @@ -1726,13 +1565,14 @@ into the image, so as to - + + Unknown Lobby - - + + Remove All @@ -1740,13 +1580,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Nazwa - + Count Liczba @@ -1756,29 +1596,7 @@ into the image, so as to Temat - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - - - - - - Public chat rooms - - - - + Create chat room @@ -1788,7 +1606,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1845,12 +1663,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1860,31 +1678,31 @@ Double click a chat room to enter and chat. - Create chat lobby - Stwórz lobby rozmów - - - + [No topic provided] [Nie podano tematu] - Selected lobby info - Informacje o zaznaczonym lobby - - - + + Private Prywatny - + + + Public Publiczne - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted @@ -1894,42 +1712,25 @@ Double click a chat room to enter and chat. Wyłącz autosubskrypcję - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe Dodaj autosubskrypcję - + Search Chat lobbies Wyszukaj lobby rozmów - + Search Name - Subscribed - Subskrybowane - - - + Columns Kolumny - - Yes - Tak - - - No - Nie - Chat rooms @@ -1941,47 +1742,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: - + Type: Typ: - + Security: - + Peers: - - - - - - + + + + + + TextLabel @@ -1996,13 +1797,24 @@ Double click a chat room to enter and chat. - + Show Pokaż - + + Private Subscribed + + + + + + Public Subscribed + + + + column @@ -2016,7 +1828,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item Usuń element @@ -2061,7 +1873,7 @@ Double click a chat room to enter and chat. ChatPage - + General Ogólne @@ -2076,15 +1888,7 @@ Double click a chat room to enter and chat. - Chat Settings - Ustawienia rozmów - - - Enable Emoticons Group Chat - Włącz emotikony w rozmowach grupowych - - - + Enable custom fonts @@ -2104,7 +1908,7 @@ Double click a chat room to enter and chat. - + General settings @@ -2129,7 +1933,7 @@ Double click a chat room to enter and chat. - + Blink tab icon @@ -2138,10 +1942,6 @@ Double click a chat room to enter and chat. Do not send typing notifications - - Private Chat - Chat Prywatny - Open Window for new chat @@ -2163,11 +1963,7 @@ Double click a chat room to enter and chat. - Chat Font - Czcionka w rozmowach - - - + Change Chat Font Zmień czcionkę @@ -2177,14 +1973,10 @@ Double click a chat room to enter and chat. Czcionka w rozmowach: - + History Historia - - Style - Styl - @@ -2199,17 +1991,13 @@ Double click a chat room to enter and chat. Variant: - - Group chat - Chat grupowy - Private chat Chat prywatny - + Choose your default font for Chat. @@ -2279,12 +2067,22 @@ Double click a chat room to enter and chat. - + Search Szukaj - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2294,7 +2092,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2391,7 +2199,7 @@ Double click a chat room to enter and chat. - + Case sensitive Rozróżnianie wielkości liter @@ -2497,7 +2305,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat Pokaż Chat @@ -2533,7 +2341,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close Zamknij @@ -2568,12 +2376,12 @@ Double click a chat room to enter and chat. Pochylenie - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2653,11 +2461,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2695,7 +2498,7 @@ Double click a chat room to enter and chat. - + is typing... pisze... @@ -2717,7 +2520,7 @@ after HTML conversion. - + Do you really want to physically delete the history? Czy naprawdę chcesz fizycznie usunąć historię? @@ -2767,7 +2570,7 @@ after HTML conversion. jest Zajęty i może nie odpowiedzieć - + Find Case Sensitively @@ -2789,7 +2592,7 @@ after HTML conversion. - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> @@ -2804,12 +2607,12 @@ after HTML conversion. - + (Status) - + Attach a File @@ -2825,12 +2628,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> - + Person id: @@ -2841,12 +2644,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. @@ -2866,7 +2669,7 @@ Double click on it to add his name on text writer. - + Don't stop to color after @@ -2892,7 +2695,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: Pokazywanie szczegółów: @@ -2914,7 +2717,7 @@ Double click on it to add his name on text writer. - + Personal Circles Kręgi Osobiste @@ -2940,7 +2743,7 @@ Double click on it to add his name on text writer. - + Friends Przyjaciele @@ -3000,7 +2803,7 @@ Double click on it to add his name on text writer. - + External Circles (Admin) @@ -3016,7 +2819,7 @@ Double click on it to add his name on text writer. - + Circles Kręgi @@ -3068,45 +2871,45 @@ Double click on it to add his name on text writer. - + RetroShare RetroShare - + - + Error : cannot get peer details. - + Retroshare ID - + <p>This Retroshare ID contains: - + <p>This certificate contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: @@ -3116,7 +2919,7 @@ Double click on it to add his name on text writer. - + Not connected @@ -3198,12 +3001,17 @@ Double click on it to add his name on text writer. brak - + <li>a <b>node ID</b> and <b>name</b> - + + <b>DNS:</b> : + + + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3223,7 +3031,7 @@ Double click on it to add his name on text writer. - + with @@ -3240,23 +3048,11 @@ Double click on it to add his name on text writer. Connect Friend Wizard - - Include signatures - Załącz podpisy - Open Cert of your friend from File - - Export my certificate... - Wyeksportuj swój certyfikat... - - - Browse - Przeglądaj - RetroShare ID @@ -3303,19 +3099,7 @@ Double click on it to add his name on text writer. Email - Invite Friends by Email - Zaproś Przyjaciół przez Email - - - Enter your friends' email addresses (separate each one with a semicolon) - Wpisz adres email twoich przyjaciół (oddziel każdy średnikiem) - - - Subject: - Temat: - - - + @@ -3331,36 +3115,32 @@ Double click on it to add his name on text writer. - + Peer details - + Name: Nazwa: - - Email: - Email: - Location: Miejsce: - + Options Opcje - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: Dodaj przyjaciela do grupy: @@ -3370,7 +3150,7 @@ Double click on it to add his name on text writer. Uwierzytelnij znajomego (Podpisz Klucz PGP) - + Please paste below your friend's Retroshare ID @@ -3395,12 +3175,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with - + Sorry, some error appeared @@ -3420,32 +3210,27 @@ Double click on it to add his name on text writer. - + Key validity: - + Profile ID: - - Signers - - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. - + To accept the Friend Request, click the Accept button. @@ -3491,17 +3276,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed Ładowanie certyfikatu nie powiodło się - + Not a valid Retroshare certificate! - + RetroShare Invitation Zaproszenie RetroShare @@ -3521,12 +3306,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3534,7 +3319,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3574,7 +3359,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Profile password needed. @@ -3599,7 +3384,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3609,19 +3394,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - Remove signatures - Usuń podpisy - - - You can copy this text and send it to your friend via email or some other way - Możesz skopiować ten tekst i wysłać go do swojego przyjaciele poprzez email, czy też w inny sposób - - - Save as... - Zapisz jako... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3660,7 +3433,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + IP-Addr: @@ -3670,7 +3443,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Show Advanced options @@ -3689,21 +3462,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> - - Message: - Wiadomość: - - - To - Do - Add key to keyring - + This key is already in your keyring @@ -3716,7 +3481,7 @@ even if you don't make friends. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. @@ -3751,7 +3516,7 @@ even if you don't make friends. - + No IP in this certificate! @@ -3761,12 +3526,7 @@ even if you don't make friends. - - [Unknown] - - - - + Added with certificate from %1 @@ -3831,7 +3591,7 @@ even if you don't make friends. - + UDP Setup @@ -3859,7 +3619,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant @@ -3869,17 +3629,20 @@ p, li { white-space: pre-wrap; } - + + Unknown State - + + Offline - + + Behind Symmetric NAT @@ -3889,12 +3652,14 @@ p, li { white-space: pre-wrap; } - + + NET Restart - + + Behind NAT @@ -3904,7 +3669,8 @@ p, li { white-space: pre-wrap; } - + + NET STATE GOOD! @@ -3929,7 +3695,7 @@ p, li { white-space: pre-wrap; } - + Lookup requires DHT @@ -4221,7 +3987,7 @@ p, li { white-space: pre-wrap; } - + @@ -4229,7 +3995,8 @@ p, li { white-space: pre-wrap; } - + + UNVERIFIABLE FORWARD! @@ -4239,7 +4006,7 @@ p, li { white-space: pre-wrap; } - + Searching @@ -4275,12 +4042,12 @@ p, li { white-space: pre-wrap; } - + Name Nazwa - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4300,7 +4067,7 @@ p, li { white-space: pre-wrap; } - + IDs ID @@ -4320,18 +4087,18 @@ p, li { white-space: pre-wrap; } - + Cancel Anuluj - + Nickname Ksywa - + Invited Members @@ -4346,15 +4113,7 @@ p, li { white-space: pre-wrap; } - ID - ID - - - Type - Typ - - - + Name: Nazwa: @@ -4394,19 +4153,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - + Please set a name for your Circle - + No Restriction Circle Selected @@ -4416,12 +4175,24 @@ p, li { white-space: pre-wrap; } - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add Dodaj @@ -4431,7 +4202,7 @@ p, li { white-space: pre-wrap; } - + Search Szukaj @@ -4484,13 +4255,13 @@ p, li { white-space: pre-wrap; } - + Create Utwórz - + Add Member @@ -4509,7 +4280,7 @@ p, li { white-space: pre-wrap; } Utwórz Grupę - + Group Name: Nazwa grupy: @@ -4544,7 +4315,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post @@ -4554,7 +4325,7 @@ p, li { white-space: pre-wrap; } Wiadomość - + Post @@ -4614,14 +4385,6 @@ p, li { white-space: pre-wrap; } Add Channel Thumbnail - - Message - Wiadomość - - - Subject : - Temat: - @@ -4707,17 +4470,17 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -4742,7 +4505,12 @@ p, li { white-space: pre-wrap; } - + + Cannot publish post + + + + Load thumbnail picture @@ -4757,18 +4525,12 @@ p, li { white-space: pre-wrap; } Ukryj - - + Generate mass data - - Do you really want to generate %1 messages ? - - - - + You are about to add files you're not actually sharing. Do you still want this to happen? @@ -4802,7 +4564,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message @@ -4811,10 +4573,6 @@ p, li { white-space: pre-wrap; } Forum Forum - - Subject - Temat - Attach File @@ -4835,8 +4593,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -4855,7 +4613,7 @@ p, li { white-space: pre-wrap; } Możesz dołączyć pliki poprzez "przeciągnij i upuść" w tym oknie - + Post @@ -4885,17 +4643,17 @@ p, li { white-space: pre-wrap; } - + No Forum - + In Reply to W Odpowiedzi do - + Title Tytuł @@ -4948,7 +4706,7 @@ Do you want to discard this message? Wczytaj obraz - + No compatible ID for this forum @@ -4958,8 +4716,8 @@ Do you want to discard this message? - - + + Generate mass data @@ -4968,10 +4726,6 @@ Do you want to discard this message? Do you really want to generate %1 messages ? - - Send - Wyślij - Post as @@ -4986,7 +4740,7 @@ Do you want to discard this message? CreateLobbyDialog - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5021,7 +4775,7 @@ Do you want to discard this message? - + Create Utwórz @@ -5031,7 +4785,7 @@ Do you want to discard this message? Anuluj - + require PGP-signed identities @@ -5046,7 +4800,7 @@ Do you want to discard this message? - + Create Chat Room @@ -5067,7 +4821,7 @@ Do you want to discard this message? Kontakty: - + Identity to use: @@ -5075,17 +4829,17 @@ Do you want to discard this message? CryptoPage - + Public Information Informacje Publiczne - + Name: Nazwa: - + Location: Miejsce: @@ -5095,12 +4849,12 @@ Do you want to discard this message? - + Software Version: - + Online since: Online od: @@ -5120,12 +4874,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5135,7 +4884,7 @@ Do you want to discard this message? - + Other Information Inne Informacje @@ -5145,17 +4894,12 @@ Do you want to discard this message? - + Profile - - Certificate - Certyfikat - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5165,11 +4909,7 @@ Do you want to discard this message? Załącz podpisy - Save Key into a file - Zapisz Klucz do pliku - - - + Export Identity Eksportuj Tożsamość @@ -5239,33 +4979,33 @@ and use the import button to load it - + TextLabel - + PGP fingerprint: - - Node information - - - - + PGP Id : - + Friend nodes: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5355,7 +5095,7 @@ and use the import button to load it DLListDelegate - + B B @@ -6023,7 +5763,7 @@ and use the import button to load it DownloadToaster - + Start file @@ -6031,38 +5771,38 @@ and use the import button to load it ExprParamElement - + - + to - + ignore case - - - dd.MM.yyyy - dd.MM.rrrr + + + yyyy-MM-dd + - - + + KB KB - - + + MB MB - - + + GB GB @@ -6070,12 +5810,12 @@ and use the import button to load it ExpressionWidget - + Expression Widget - + Delete this expression @@ -6237,7 +5977,7 @@ and use the import button to load it FilesDefs - + Picture Obraz @@ -6247,7 +5987,7 @@ and use the import button to load it Wideo - + Audio Audio @@ -6307,11 +6047,21 @@ and use the import button to load it C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Katalogi Przyjaciół @@ -6433,7 +6183,7 @@ and use the import button to load it - + ID ID @@ -6475,7 +6225,7 @@ and use the import button to load it Pokaż Grupy - + Group Grupa @@ -6511,7 +6261,7 @@ and use the import button to load it Dodaj do grupy - + Search Szukaj @@ -6527,7 +6277,7 @@ and use the import button to load it - + Profile details @@ -6764,7 +6514,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request @@ -6802,7 +6552,7 @@ at least one peer was not added to a group Szukaj Przyjaciół - + Mark all Zaznacz wszystkie @@ -6813,16 +6563,132 @@ at least one peer was not added to a group + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + + + + + Node ID + + + + + Address + + + + + Status + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message - - + + Broadcast @@ -6905,33 +6771,38 @@ at least one peer was not added to a group Zresetuj czcionkę do domyślnej - + Keyring - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. - - + + Network - + + Friend Server + + + + Network graph - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. @@ -6949,7 +6820,17 @@ at least one peer was not added to a group Hasło - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters @@ -6959,17 +6840,12 @@ at least one peer was not added to a group - + Port Port - - Use BOB - - - - + This password is for PGP @@ -6990,38 +6866,38 @@ at least one peer was not added to a group - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -7041,12 +6917,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -7056,38 +6932,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel - + hidden address - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -7131,13 +7012,13 @@ and use the import button to load it - + Import profile - + Create new profile and new Retroshare node @@ -7147,7 +7028,7 @@ and use the import button to load it - + Tor/I2P address @@ -7182,7 +7063,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7192,12 +7073,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -7207,12 +7083,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7438,27 +7309,13 @@ and use the import button to load it Pierwsze kroki - + Invite Friends Zaproś Przyjaciół - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - - - - + Add Your Friends to RetroShare @@ -7468,89 +7325,103 @@ p, li { white-space: pre-wrap; } Dodaj Przyjaciół - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + Connect To Friends - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Zaawansowane: Otwórz Port Firewalla + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - Zaawansowane: Otwórz Port Firewalla - - - + Further Help and Support Dalsza Pomoc i Wsparcie - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website Otwórz stronę RS @@ -7575,7 +7446,7 @@ p, li { white-space: pre-wrap; } Opinia Email - + RetroShare Invitation Zaproszenie RetroShare @@ -7625,12 +7496,12 @@ p, li { white-space: pre-wrap; } Opinia o RetroShare - + RetroShare Support Wsparcie RetroShare - + It has many features, including built-in chat, messaging, @@ -7754,7 +7625,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat Pokaż Chat Grupy @@ -7762,7 +7633,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] @@ -7932,7 +7803,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title Tytuł @@ -7945,12 +7816,12 @@ p, li { white-space: pre-wrap; } - + Description Opis - + Number of Unread message @@ -7975,19 +7846,7 @@ p, li { white-space: pre-wrap; } - Sort by Name - Sortuj według Nazwy - - - Sort by Popularity - Sortuj według Popularności - - - Sort by Last Post - Sortuj według Ostatniego Postu - - - + You are admin (modify names and description using Edit menu) @@ -8002,14 +7861,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post Ostatni Post - + Name @@ -8020,17 +7879,13 @@ p, li { white-space: pre-wrap; } Popularność - + Never - Display - Wyświetl - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8043,7 +7898,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and i @@ -8179,7 +8034,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels Kanały @@ -8190,22 +8045,22 @@ p, li { white-space: pre-wrap; } Stwórz kanał - + Enable Auto-Download Włącz auto-pobieranie - + My Channels Moje Kanały - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Subskrybowane kanały @@ -8225,12 +8080,12 @@ p, li { white-space: pre-wrap; } - + Disable Auto-Download Wyłącz auto-pobieranie - + Set download directory @@ -8265,22 +8120,22 @@ p, li { white-space: pre-wrap; } - + Play Odtwórz - + Open folder - + Open file - + Error Błąd @@ -8300,17 +8155,17 @@ p, li { white-space: pre-wrap; } - + Are you sure that you want to cancel and delete the file? - + Can't open folder - + Play File @@ -8320,29 +8175,10 @@ p, li { white-space: pre-wrap; } - - GxsChannelFilesWidget - - Form - Formularz - - - Size - Rozmiar - - - Title - Tytuł - - - Status - Stan - - GxsChannelGroupDialog - + Create New Channel @@ -8380,9 +8216,19 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - Zapisz się na kanał + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel + @@ -8396,7 +8242,7 @@ p, li { white-space: pre-wrap; } - + Expand Rozwiń @@ -8411,7 +8257,7 @@ p, li { white-space: pre-wrap; } Opis kanału - + Loading Wczytywanie @@ -8426,8 +8272,9 @@ p, li { white-space: pre-wrap; } - New Channel - Nowy kanał + + Never + @@ -8438,7 +8285,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: @@ -8459,7 +8306,7 @@ p, li { white-space: pre-wrap; } - + Play Odtwórz @@ -8515,28 +8362,24 @@ p, li { white-space: pre-wrap; } Files Pliki - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - Uwaga! Masz mniej niż %1 godzin i %2 minut zanim ten plik zostanie skasowany. Rozważ jego zapisanie. - Hide Ukryj - + New Nowy - + 0 0 - - + + Comment Skomentuj @@ -8551,21 +8394,17 @@ p, li { white-space: pre-wrap; } - Loading - Wczytywanie - - - + Loading... - + Comments - + Post @@ -8590,59 +8429,16 @@ p, li { white-space: pre-wrap; } Odtwórz multimedia - - GxsChannelPostsWidget - - Post to Channel - Napisz post na kanale - - - Loading - Wczytywanie - - - Title - Tytuł - - - Search Title - Szukaj Tytuł - - - Message - Wiadomość - - - No Channel Selected - Nie wybrano kanału - - - Disable Auto-Download - Wyłącz auto-pobieranie - - - Enable Auto-Download - Włącz auto-pobieranie - - - Files - Pliki - - - Description: - Opis - - GxsChannelPostsWidgetWithModel - + Post to Channel Napisz post na kanale - + Add new post @@ -8712,7 +8508,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -8748,7 +8544,7 @@ p, li { white-space: pre-wrap; } - + Comments Komentarze @@ -8763,13 +8559,13 @@ p, li { white-space: pre-wrap; } - - + + Click to switch to list view - + Show unread posts only @@ -8784,7 +8580,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -8799,7 +8595,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -8859,12 +8655,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -8939,12 +8745,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed Subskrybowane @@ -8995,17 +8802,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -9120,7 +8927,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container @@ -9133,7 +8940,7 @@ p, li { white-space: pre-wrap; } Formularz - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9163,7 +8970,7 @@ p, li { white-space: pre-wrap; } Odśwież - + Comment Komentarz @@ -9202,7 +9009,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment Odpowiedz na Komentarz @@ -9226,6 +9033,21 @@ p, li { white-space: pre-wrap; } Vote Down Głosuj przeciw + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9235,7 +9057,7 @@ p, li { white-space: pre-wrap; } Skomentuj - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9264,21 +9086,10 @@ p, li { white-space: pre-wrap; } - + Post - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; }⏎ </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Komentarz</span></p></body></html> - Reply to Comment @@ -9306,7 +9117,7 @@ before you can comment - + It remains %1 characters after HTML conversion. @@ -9357,7 +9168,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum Zasubskrybuj Forum @@ -9373,7 +9184,7 @@ before you can comment - + Expand Rozwiń @@ -9393,8 +9204,9 @@ before you can comment - Loading - Wczytywanie + + TextLabel + @@ -9425,13 +9237,13 @@ before you can comment GxsForumMsgItem - - + + Subject: Temat: - + Unsubscribe To Forum @@ -9442,7 +9254,7 @@ before you can comment - + Expand Rozwiń @@ -9462,21 +9274,17 @@ before you can comment - Loading - Wczytywanie - - - + Loading... - + Forum Feed - + Hide Ukryj @@ -9489,63 +9297,66 @@ before you can comment Formularz - + Start new Thread for Selected Forum Rozpocznij nowy Wątek dla Wybranego Forum - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Przeszukaj fora - Last Post - Ostatni Post - - - + New Thread Nowy Wątek - - - Threaded View - Widok Wątku - - - - Flat View - Widok Płaski - - + Title Tytuł - - + + Date Data - + Author Autor - - Save image - - - - + Loading Wczytywanie - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9555,12 +9366,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message Odpowiedz Wiadomością @@ -9584,10 +9390,6 @@ before you can comment Download all files Pobierz wszystkie pliki - - Next unread - Następne nieprzeczytane - Search Title @@ -9604,31 +9406,23 @@ before you can comment Szukaj Autora - Content - Zawartość - - - Search Content - Szukaj Zawartości - - - + No name Bez nazwy - - + + Reply Odpowiedz - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -9671,16 +9465,12 @@ before you can comment Skopiuj Link RetroShare - + Hide Ukryj - Expand - Rozwiń - - - + [unknown] @@ -9710,8 +9500,8 @@ before you can comment - - + + Distribution @@ -9725,22 +9515,6 @@ before you can comment Anti-spam - - Anonymous - Anonimowy - - - signed - podpisane - - - none - brak - - - [ ... Missing Message ... ] - [ ... Brakująca Wiadomość ... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -9810,12 +9584,12 @@ before you can comment Oryginalna Wiadomość - + New thread - + Edit Edytuj @@ -9876,7 +9650,7 @@ before you can comment - + Show column @@ -9896,7 +9670,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive @@ -9948,7 +9722,7 @@ This message is missing. You should receive it later. - + No result. @@ -9958,7 +9732,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -9973,7 +9747,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -10039,12 +9813,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums Fora @@ -10075,31 +9849,16 @@ This message is missing. You should receive it later. Inne Fora - - GxsForumsFillThread - - Waiting - Oczekiwanie - - - Loading - Wczytywanie - - GxsGroupDialog - + Name Nazwa - Add Icon - Dodaj Ikonę - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels @@ -10110,12 +9869,12 @@ This message is missing. You should receive it later. - + Description Opis - + Message Distribution Dystrybucja Wiadomości @@ -10123,7 +9882,7 @@ This message is missing. You should receive it later. - + Public Publiczne @@ -10142,14 +9901,6 @@ This message is missing. You should receive it later. New Thread Nowy Wątek - - Required - Wymagane - - - Encrypted Msgs - Zaszyfrowane Wiadomości - Personal Signatures @@ -10191,7 +9942,7 @@ This message is missing. You should receive it later. - + Comments: Komentarze: @@ -10214,7 +9965,7 @@ This message is missing. You should receive it later. - + All People @@ -10230,12 +9981,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -10252,23 +10003,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -10284,22 +10035,28 @@ This message is missing. You should receive it later. Proszę, dodaj Nazwę - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo Załaduj Logo Grupy - + Submit Group Changes - + Owner: @@ -10309,12 +10066,12 @@ This message is missing. You should receive it later. - + Info - + ID ID @@ -10324,7 +10081,7 @@ This message is missing. You should receive it later. Ostatni Post - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -10399,7 +10156,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity Popularność @@ -10415,27 +10177,22 @@ This message is missing. You should receive it later. - + Created - + Cancel Anuluj - + Create Utwórz - - Author - Autor - - - + GxsIdLabel @@ -10443,7 +10200,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading Wczytywanie @@ -10503,7 +10260,7 @@ This message is missing. You should receive it later. - + Synchronise posts of last... @@ -10560,12 +10317,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link Skopiuj Link RetroShare @@ -10588,7 +10345,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature @@ -10601,18 +10358,14 @@ This message is missing. You should receive it later. GxsIdDetails - Loading - Wczytywanie - - - + Not found - - + + [Banned] @@ -10622,7 +10375,7 @@ This message is missing. You should receive it later. - + Loading... @@ -10632,7 +10385,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -10652,6 +10410,14 @@ This message is missing. You should receive it later. + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -10663,7 +10429,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -10711,17 +10477,13 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] GxsMessageFramePostWidget - - Loading - Wczytywanie - Loading... @@ -11102,7 +10864,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -11118,7 +10880,7 @@ p, li { white-space: pre-wrap; } - + Authors Autorzy @@ -11137,7 +10899,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -11215,7 +10977,7 @@ p, li { white-space: pre-wrap; } Formularz - + Add friend @@ -11225,7 +10987,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -11253,7 +11015,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -11263,7 +11025,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard @@ -11273,7 +11035,7 @@ private and secure decentralized communication platform. - + Send via Email @@ -11293,13 +11055,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -11311,12 +11097,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -11331,12 +11117,7 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... Zapisz jako... @@ -11601,14 +11382,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Wszyscy - + Reputation Reputacja @@ -11618,12 +11399,12 @@ p, li { white-space: pre-wrap; } Szukaj - + Anonymous Id - + Create new Identity Stwórz nową Tożsamość @@ -11633,7 +11414,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -11648,27 +11429,27 @@ p, li { white-space: pre-wrap; } - + Close Zamknij - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -11684,29 +11465,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles Kręgi - + Circle name @@ -11726,18 +11517,20 @@ p, li { white-space: pre-wrap; } Kręgi Osobiste - + + Edit identity - + + Delete identity - + Chat with this peer @@ -11747,78 +11540,78 @@ p, li { white-space: pre-wrap; } - + Owner node ID : - + Identity name : - + () - + Identity ID - + Send message - + Identity info - + Identity ID : - + Owner node name : - + Create new... - + Type: Typ: - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: - + Negative - + Neutral @@ -11829,17 +11622,17 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous Anonim @@ -11854,24 +11647,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you - - + + My own identities - - + + My contacts - + Show Items @@ -11886,7 +11679,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -11896,7 +11694,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -11971,7 +11769,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -12001,7 +11799,7 @@ p, li { white-space: pre-wrap; } nieznane - + Invited @@ -12016,7 +11814,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle @@ -12064,7 +11862,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -12072,7 +11870,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -12115,7 +11913,7 @@ These identities will soon be not supported anymore. - + Boards @@ -12195,7 +11993,7 @@ These identities will soon be not supported anymore. - + information @@ -12211,17 +12009,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -12326,7 +12119,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -12376,21 +12169,21 @@ These identities will soon be not supported anymore. - - - + + + People - + Your Avatar Click here to change your avatar - + Linked to neighbor nodes @@ -12400,7 +12193,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -12415,7 +12208,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -12430,12 +12223,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -12455,12 +12248,12 @@ These identities will soon be not supported anymore. - + Owned by - + Node name: @@ -12470,7 +12263,7 @@ These identities will soon be not supported anymore. - + Really delete? @@ -12478,7 +12271,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname Ksywa @@ -12508,7 +12301,13 @@ These identities will soon be not supported anymore. Pseudonim - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity @@ -12522,7 +12321,7 @@ These identities will soon be not supported anymore. - + @@ -12532,7 +12331,12 @@ These identities will soon be not supported anymore. - + + No avatar chosen + + + + Edit identity @@ -12543,27 +12347,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -12583,7 +12387,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -12593,12 +12397,18 @@ These identities will soon be not supported anymore. - + Error KeyID invalid - + + + No Avatar chosen. A default image will be automatically displayed from your new identity. + + + + Import image @@ -12608,12 +12418,7 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. - - - - + Unknown GpgId @@ -12623,7 +12428,7 @@ These identities will soon be not supported anymore. - + Create New Identity @@ -12633,10 +12438,15 @@ These identities will soon be not supported anymore. Typ - + Choose image... + + + Remove + Usuń + @@ -12662,7 +12472,7 @@ These identities will soon be not supported anymore. Dodaj - + Create Utwórz @@ -12672,13 +12482,13 @@ These identities will soon be not supported anymore. Anuluj - + Your Avatar Click here to change your avatar - + Linked to your profile @@ -12688,7 +12498,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -12762,7 +12572,7 @@ These identities will soon be not supported anymore. - + Copy Skopiuj @@ -12772,12 +12582,12 @@ These identities will soon be not supported anymore. Usuń - + %1 's Message History - + Mark all Zaznacz wszystkie @@ -12796,26 +12606,38 @@ These identities will soon be not supported anymore. Quote Cytat - - Send - Wyślij - ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -12833,27 +12655,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: - + Listen Address: - + + Status: + Status: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -12874,7 +12701,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -12883,26 +12715,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File Otwórz Plik - + Open Folder Otwórz folder - + Checking... Sprawdzanie... @@ -12912,7 +12749,7 @@ These identities will soon be not supported anymore. - + Recommend in a message to... @@ -12940,7 +12777,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend Dodaj Przyjaciela @@ -12956,7 +12793,8 @@ These identities will soon be not supported anymore. - + + Options Opcje @@ -12977,7 +12815,7 @@ These identities will soon be not supported anymore. - + Quit Zamknij @@ -12988,12 +12826,12 @@ These identities will soon be not supported anymore. Kreator szybkiego startu - + RetroShare %1 a secure decentralized communication platform RetroShare %1 bezpieczna, zdecentralizowana platforma komunikacji - + Unfinished Niedokończone @@ -13018,11 +12856,12 @@ These identities will soon be not supported anymore. + Status Stan - + Notify Powiadom @@ -13033,31 +12872,35 @@ These identities will soon be not supported anymore. + Open Messages - + + Bandwidth Graph - + Applications Aplikacje + Help Pomoc - + + Minimize Minimalizuj - + Maximize Maksymalizuj @@ -13072,7 +12915,12 @@ These identities will soon be not supported anymore. RetroShare - + + Close window + + + + %1 new message %1 nowa wiadomość @@ -13102,7 +12950,7 @@ These identities will soon be not supported anymore. %1 przyjaciół połączonych - + Do you really want to exit RetroShare ? Czy naprawczę chcesz wyjść z RetroShare ? @@ -13122,7 +12970,7 @@ These identities will soon be not supported anymore. Pokaż - + Make sure this link has not been forged to drag you to a malicious website. @@ -13167,12 +13015,13 @@ These identities will soon be not supported anymore. - + + Statistics - + Show web interface @@ -13187,7 +13036,7 @@ These identities will soon be not supported anymore. - + Really quit ? @@ -13196,17 +13045,17 @@ These identities will soon be not supported anymore. MessageComposer - + Compose - + Contacts Kontakty - + Paragraph Paragraf @@ -13242,12 +13091,12 @@ These identities will soon be not supported anymore. - + Font size - + Increase font size Zwiększ rozmiar czcionki @@ -13262,32 +13111,32 @@ These identities will soon be not supported anymore. Pogrubienie - + Italic Pochylenie - + Alignment Wyrównanie - + Add an Image Dodaj Obraz - + Sets text font to code style - + Underline Podkreślenie - + Subject: Temat: @@ -13298,32 +13147,32 @@ These identities will soon be not supported anymore. - + Tags Tagi - + Address list: - + Recommend this friend - + Set Text color - + Set Text background color - + Recommended Files Polecane pliki @@ -13393,7 +13242,7 @@ These identities will soon be not supported anymore. - + Send To: Wyślij do: @@ -13433,7 +13282,7 @@ These identities will soon be not supported anymore. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> @@ -13453,18 +13302,18 @@ These identities will soon be not supported anymore. chce być twoim przyjacielem na RetroShare - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team - - + + Save Message Zapisz wiadomość - + Message has not been Sent. Do you want to save message to draft box? Wiadomość nie została wysłana. @@ -13476,7 +13325,17 @@ Czy chcesz zapisać wiadomość do wersji roboczych? Wklej Link RetroShare - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" Dodaj do "Do" @@ -13496,7 +13355,7 @@ Czy chcesz zapisać wiadomość do wersji roboczych? Dodaj jako Polecane - + Original Message Oryginalna Wiadomość @@ -13506,21 +13365,21 @@ Czy chcesz zapisać wiadomość do wersji roboczych? Od - + - + To Do - - + + Cc - + Sent Wysłane @@ -13535,7 +13394,7 @@ Czy chcesz zapisać wiadomość do wersji roboczych? - + Re: Re: @@ -13545,30 +13404,30 @@ Czy chcesz zapisać wiadomość do wersji roboczych? Fwd: - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? Czy chcesz wysłać tą wiadomość bez tematu ? - + Please insert at least one recipient. Proszę dodaj przynajmniej jednego odbiorcę. - + Bcc - + Unknown Nieznane @@ -13683,13 +13542,13 @@ Czy chcesz zapisać wiadomość do wersji roboczych? Szczegóły - + Open File... Otwórz Plik... - + HTML-Files (*.htm *.html);;All Files (*) Pliki HTML (*.htm *.html);;Wszystkie pliki (*) @@ -13709,7 +13568,7 @@ Czy chcesz zapisać wiadomość do wersji roboczych? Eksport PDF - + Message has not been Sent. Do you want to save message ? Wiadomość nie została wysłana. @@ -13731,7 +13590,7 @@ Czy chcesz zapisać wiadomość ? Dodaj dodatkowy plik - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -13761,18 +13620,18 @@ Czy chcesz zapisać wiadomość ? - - + + Close Zamknij - + From: Od klatki: - + Bullet list (disc) @@ -13812,13 +13671,13 @@ Czy chcesz zapisać wiadomość ? - - + + Thanks, <br> - + Distant identity: @@ -13828,12 +13687,12 @@ Czy chcesz zapisać wiadomość ? - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -13911,7 +13770,7 @@ Czy chcesz zapisać wiadomość ? Domyślne - + A new tab Nowa karta @@ -13921,7 +13780,7 @@ Czy chcesz zapisać wiadomość ? Nowe okno - + Edit Tag Edytuj Tag @@ -13944,7 +13803,7 @@ Czy chcesz zapisać wiadomość ? MessageToaster - + Sub: @@ -13952,7 +13811,7 @@ Czy chcesz zapisać wiadomość ? MessageUserNotify - + Message Wiadomość @@ -13980,7 +13839,7 @@ Czy chcesz zapisać wiadomość ? MessageWidget - + Recommended Files Rekomendowane Pliki @@ -13990,37 +13849,37 @@ Czy chcesz zapisać wiadomość ? Pobierz wszystkie Polecane Pliki - + Subject: Temat: - + From: Od klatki: - + To: Do klatki: - + Cc: - + Bcc: - + Tags: Tagi: - + Reply Odpowiedz @@ -14060,7 +13919,7 @@ Czy chcesz zapisać wiadomość ? - + Send Invite @@ -14112,7 +13971,7 @@ Czy chcesz zapisać wiadomość ? - + Confirm %1 as friend Zatwierdź %1 jako przyjaciela @@ -14122,12 +13981,12 @@ Czy chcesz zapisać wiadomość ? Dodaj %1 jako przyjaciela - + View source - + No subject Brak tematu @@ -14137,17 +13996,22 @@ Czy chcesz zapisać wiadomość ? Pobierz - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -14156,14 +14020,24 @@ Czy chcesz zapisać wiadomość ? %1 (%2) + + + Show less + + + + + Show more + + - + Download all Pobierz wszystkie - + Print Document Drukuj Dokument @@ -14178,12 +14052,12 @@ Czy chcesz zapisać wiadomość ? Pliki HTML (*.htm *.html);;Wszystkie pliki (*) - + Load images always for this message - + Hide the attachment pane @@ -14205,34 +14079,6 @@ Czy chcesz zapisać wiadomość ? Compose - - Reply to selected message - Odpowiedz na wybraną wiadomość - - - Reply - Odpowiedz - - - Reply all to selected message - Odpowiedz na wszystkie wybrane wiadomości - - - Forward selected message - Prześlij dalej wybraną wiadomość - - - Remove selected message - Usuń wybraną wiadomość - - - Delete - Usuń - - - Print selected message - Drukuj wybraną wiadomość - Print @@ -14311,7 +14157,7 @@ Czy chcesz zapisać wiadomość ? MessagesDialog - + New Message Nowa Wiadmość @@ -14321,52 +14167,16 @@ Czy chcesz zapisać wiadomość ? - Reply to selected message - Odpowiedz na wybraną wiadomość - - - Reply - Odpowiedz - - - Reply all to selected message - Odpowiedz na wszystkie wybrane wiadomości - - - Forward selected message - Prześlij dalej wybraną wiadomość - - - Remove selected message - Usuń wybraną wiadomość - - - Delete - Usuń - - - Print selected message - Drukuj wybraną wiadomość - - - Print - Drukuj - - - Display - Wyświetl - - - + - - + + Tags Tagi - - + + Inbox Przychodzące @@ -14396,21 +14206,17 @@ Czy chcesz zapisać wiadomość ? Kosz - + Total Inbox: - Folders - Foldery - - - + Quick View Szybki podgląd - + Print... Drukuj... @@ -14420,26 +14226,6 @@ Czy chcesz zapisać wiadomość ? Print Preview Podgląd Wydruku - - Buttons Icon Only - Tylko ikony przycisków - - - Buttons Text Beside Icon - Tekst obok przycisków ikon - - - Buttons with Text - Przyciski z tekstem - - - Buttons Text Under Icon - Tekst przycisków pod ikonami - - - Set Text Under Icon - Ustaw tekst pod ikoną - Save As... @@ -14461,7 +14247,7 @@ Czy chcesz zapisać wiadomość ? - + Subject Tytuł @@ -14471,7 +14257,7 @@ Czy chcesz zapisać wiadomość ? Od - + Date Data @@ -14481,7 +14267,7 @@ Czy chcesz zapisać wiadomość ? Zawartość - + Search Subject @@ -14490,6 +14276,11 @@ Czy chcesz zapisać wiadomość ? Search From + + + Search To + + Search Date @@ -14516,17 +14307,7 @@ Czy chcesz zapisać wiadomość ? Szukaj Załączników - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - - - - - Starred - - - - + System System @@ -14596,12 +14377,7 @@ Czy chcesz zapisać wiadomość ? - - Show author in People - - - - + Empty trash @@ -14611,7 +14387,7 @@ Czy chcesz zapisać wiadomość ? - + No message using %1 tag available. @@ -14626,22 +14402,48 @@ Czy chcesz zapisać wiadomość ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts - + No Box selected. + To - Do + Do - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + + + + Starred + + + + + Show in People + + + + @@ -14649,10 +14451,6 @@ Czy chcesz zapisać wiadomość ? Total: - - Messages - Wiadomości - Mail @@ -14680,7 +14478,17 @@ Czy chcesz zapisać wiadomość ? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -14734,7 +14542,7 @@ Czy chcesz zapisać wiadomość ? - + Expand Rozwiń @@ -14744,7 +14552,7 @@ Czy chcesz zapisać wiadomość ? Usuń element - + from od @@ -14779,7 +14587,7 @@ Czy chcesz zapisać wiadomość ? - + Hide Ukryj @@ -14920,7 +14728,7 @@ Czy chcesz zapisać wiadomość ? - + Remove unused keys... Usuń nieużywane klucze... @@ -14930,7 +14738,7 @@ Czy chcesz zapisać wiadomość ? - + Clean keyring @@ -14944,7 +14752,13 @@ Notes: Your old keyring will be backed up. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info @@ -14977,18 +14791,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. - - - Export/create a new node - - Trusted keys only - + Search name @@ -14998,12 +14807,12 @@ For security, your keyring was previously backed-up to file - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -15036,7 +14845,7 @@ Reported error: NewFriendList - + Offline Friends @@ -15057,7 +14866,7 @@ Reported error: - + Groups Grupy @@ -15087,19 +14896,19 @@ Reported error: - - + + Search Szukaj - + ID ID - + Search ID @@ -15109,12 +14918,12 @@ Reported error: - + Show Items - + Last contact @@ -15124,7 +14933,7 @@ Reported error: - + Group Grupa @@ -15239,7 +15048,7 @@ Reported error: Zwiń wszystkie - + Do you want to remove this node? @@ -15249,7 +15058,7 @@ Reported error: Czy chcesz usunąć tego Przyjaciela? - + Done! @@ -15356,7 +15165,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -15371,11 +15180,7 @@ at least one peer was not added to a group - This is a test. - To jest test. - - - + Newest on top @@ -15385,12 +15190,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15445,10 +15250,6 @@ at least one peer was not added to a group Blogs Blogi - - Security - Bezpieczeństwo - @@ -15526,7 +15327,7 @@ at least one peer was not added to a group Private Chat - + Prywatny Chat @@ -15632,7 +15433,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -15652,12 +15453,12 @@ at least one peer was not added to a group - + Please enter your Retroshare passphrase - + Unregistered plugin/executable @@ -15672,7 +15473,7 @@ at least one peer was not added to a group - + Test Test @@ -15683,17 +15484,19 @@ at least one peer was not added to a group + Unknown title - + + Encrypted message - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -15701,7 +15504,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online @@ -15840,7 +15643,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -15849,10 +15657,6 @@ p, li { white-space: pre-wrap; } Keysigning: - - Sign PGP key - Podpisz klucz PGP - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -15889,12 +15693,7 @@ p, li { white-space: pre-wrap; } Załącz podpisy - - Options - Opcje - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -15940,21 +15739,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - - + + Error : cannot get peer details. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) @@ -15972,7 +15771,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -16041,10 +15840,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Check the password! - - Maybe password is wrong - Być może hasło jest błędne - You haven't set a trust level for this key. @@ -16052,12 +15847,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -16083,7 +15878,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat Chat @@ -16104,7 +15899,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Usuń element - + Name: Nazwa: @@ -16144,7 +15939,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message Napisz wiadomość @@ -16202,7 +15997,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Ukryj - + Send Message @@ -16369,13 +16164,6 @@ Warning: In your File-Transfer option, you select allow direct download to No. - - PhotoCommentItem - - Form - Formularz - - PhotoDialog @@ -16383,23 +16171,11 @@ Warning: In your File-Transfer option, you select allow direct download to No.PhotoShare - - Photo - Zdjęcie - TextLabel - - Comment - Komentarz - - - Summary - Podsumowanie - Album / Photo Name @@ -16460,14 +16236,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.... ... - - Add Comment - Dodaj Komentarz - - - Write a comment... - Napisz komentarz... - Album @@ -16534,10 +16302,6 @@ p, li { white-space: pre-wrap; } Create Album Utwórz Album - - View Album - Pokaż Album - Edit Album Details @@ -16559,17 +16323,17 @@ p, li { white-space: pre-wrap; } Pokaz Slajdów - + My Albums Moje Albumy - + Subscribed Albums Subskrybowane Albumy - + Shared Albums @@ -16598,7 +16362,7 @@ requesting to edit it! PhotoSlideShow - + Album Name @@ -16657,19 +16421,19 @@ requesting to edit it! - - + + TextLabel - + Posted by - + ago @@ -16705,12 +16469,12 @@ requesting to edit it! PluginItem - + TextLabel - + Show more details about this plugin Pokaż więcej szczegółów o tej wtyczce @@ -16925,12 +16689,27 @@ p, li { white-space: pre-wrap; } - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -16983,7 +16762,7 @@ p, li { white-space: pre-wrap; } Nowy - + Vote up @@ -17003,8 +16782,8 @@ p, li { white-space: pre-wrap; } \/ - - + + Comments Komentarze @@ -17029,13 +16808,13 @@ p, li { white-space: pre-wrap; } - - + + Comment - + Comments @@ -17063,16 +16842,12 @@ p, li { white-space: pre-wrap; } PostedCreatePostDialog - Notes - Notki - - - + Create a new Post - + RetroShare RetroShare @@ -17087,12 +16862,22 @@ p, li { white-space: pre-wrap; } - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File Wczytaj obraz - + Post image @@ -17108,7 +16893,17 @@ p, li { white-space: pre-wrap; } - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -17118,7 +16913,7 @@ p, li { white-space: pre-wrap; } - + Please add a Title @@ -17138,12 +16933,22 @@ p, li { white-space: pre-wrap; } - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -17158,7 +16963,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -17169,7 +16974,7 @@ p, li { white-space: pre-wrap; } Obraz - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -17179,7 +16984,7 @@ p, li { white-space: pre-wrap; } Tytuł - + Link @@ -17187,28 +16992,12 @@ p, li { white-space: pre-wrap; } PostedDialog - My Topics - Moje Tematy - - - Subscribed Topics - Subskrybowane Tematy - - - Popular Topics - Popularne Tematy - - - Other Topics - Inne Tematy - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -17242,7 +17031,7 @@ p, li { white-space: pre-wrap; } PostedGroupDialog - + Create New Board @@ -17280,7 +17069,17 @@ p, li { white-space: pre-wrap; } PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted @@ -17296,7 +17095,7 @@ p, li { white-space: pre-wrap; } - + Expand Rozwiń @@ -17311,16 +17110,17 @@ p, li { white-space: pre-wrap; } - Loading - Wczytywanie - - - + Loading... - + + Never + + + + New Board @@ -17333,22 +17133,18 @@ p, li { white-space: pre-wrap; } PostedItem - + 0 0 - Site - Strona - - - - + + Comments Komentarze - + Copy RetroShare Link @@ -17359,12 +17155,12 @@ p, li { white-space: pre-wrap; } - + Comment Skomentuj - + Comments @@ -17374,7 +17170,7 @@ p, li { white-space: pre-wrap; } - + Click to view Picture @@ -17384,21 +17180,17 @@ p, li { white-space: pre-wrap; } Ukryj - + Vote up - + Vote down - \/ - \/ - - - + Set as read and remove item @@ -17408,7 +17200,7 @@ p, li { white-space: pre-wrap; } Nowy - + New Comment: @@ -17418,7 +17210,7 @@ p, li { white-space: pre-wrap; } - + Name @@ -17459,42 +17251,11 @@ p, li { white-space: pre-wrap; } - + Loading Wczytywanie - - PostedListWidget - - Form - Formularz - - - New - Nowy - - - Today - Dzisiaj - - - Yesterday - Wczoraj - - - Next - Następne - - - RetroShare - RetroShare - - - Previous - Poprzednie - - PostedListWidgetWithModel @@ -17513,7 +17274,17 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -17523,15 +17294,15 @@ p, li { white-space: pre-wrap; } - + - + unknown nieznane - + Distribution: @@ -17541,42 +17312,42 @@ p, li { white-space: pre-wrap; } - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -17596,7 +17367,7 @@ p, li { white-space: pre-wrap; } - + Search Szukaj @@ -17626,17 +17397,17 @@ p, li { white-space: pre-wrap; } - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -17651,12 +17422,17 @@ p, li { white-space: pre-wrap; } - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -17666,27 +17442,31 @@ p, li { white-space: pre-wrap; } Edytuj - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -17701,7 +17481,7 @@ p, li { white-space: pre-wrap; } Zapisz się - + Never @@ -17775,6 +17555,16 @@ p, li { white-space: pre-wrap; } No Channel Selected Nie wybrano kanału + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -17864,16 +17654,16 @@ p, li { white-space: pre-wrap; } Menedżer profili - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -17981,7 +17771,7 @@ and use the import button to load it ProfileWidget - + Edit status message @@ -17997,7 +17787,7 @@ and use the import button to load it Menedżer profili - + Public Information Informacje Publiczne @@ -18032,12 +17822,12 @@ and use the import button to load it Online od: - + Other Information Inne Informacje - + My Address Mój Adres @@ -18081,43 +17871,27 @@ and use the import button to load it PulseAddDialog - Account 1 - Konto 1 - - - Account 2 - Konto 2 - - - Account 3 - Konto 3 - - - + Add to Pulse - filter - filtr - - - + Display As Wyświetl Jako - + URL URL - + GroupLabel - + IDLabel @@ -18127,12 +17901,12 @@ and use the import button to load it Od klatki: - + Head - + Head Shot @@ -18162,13 +17936,13 @@ and use the import button to load it - - + + Whats happening? - + @@ -18180,12 +17954,22 @@ and use the import button to load it - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -18200,7 +17984,7 @@ and use the import button to load it - + Reply to Pulse @@ -18215,34 +17999,24 @@ and use the import button to load it - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - Od - - - Date - Data - - - ... - ... + + Load Picture File + Wczytaj obraz @@ -18253,7 +18027,7 @@ and use the import button to load it Formularz - + @@ -18272,7 +18046,7 @@ and use the import button to load it PulseReply - + icn @@ -18282,7 +18056,7 @@ and use the import button to load it - + REPLY @@ -18309,7 +18083,7 @@ and use the import button to load it - + FOLLOW @@ -18319,7 +18093,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -18339,7 +18113,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -18455,7 +18229,7 @@ and use the import button to load it - + FOLLOW @@ -18463,37 +18237,42 @@ and use the import button to load it PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -18525,7 +18304,7 @@ and use the import button to load it - + FOLLOW @@ -18533,8 +18312,8 @@ and use the import button to load it QObject - - + + Confirmation @@ -18803,12 +18582,12 @@ Symbole <b>",|,/,\,&lt;,&gt;,*,?</b> zostaną zastąpio - + File Request canceled - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. @@ -18839,7 +18618,7 @@ Symbole <b>",|,/,\,&lt;,&gt;,*,?</b> zostaną zastąpio - + Cannot start Tor Manager! @@ -18873,7 +18652,7 @@ The error reported is:" - + Multiple instances @@ -18892,6 +18671,26 @@ The error reported is:" + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -18971,7 +18770,7 @@ Reported error is: - + You appear to have nodes associated to DSA keys: @@ -18981,7 +18780,7 @@ Reported error is: - + enabled @@ -18991,7 +18790,7 @@ Reported error is: - + Move IP %1 to whitelist @@ -19007,7 +18806,7 @@ Reported error is: - + %1 seconds ago @@ -19074,7 +18873,7 @@ Security: no anonymous IDs - + Join chat room @@ -19102,7 +18901,7 @@ Security: no anonymous IDs - + Indefinitely @@ -19283,12 +19082,28 @@ Security: no anonymous IDs - - Status + + Name + Node + + + + + Address + + + + + + Status + + + + NXS @@ -19531,6 +19346,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -19675,7 +19502,7 @@ p, li { white-space: pre-wrap; } - + Network Wide @@ -19842,7 +19669,7 @@ p, li { white-space: pre-wrap; } Formularz - + The loading of embedded images is blocked. @@ -19855,7 +19682,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default @@ -20028,12 +19855,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -20041,12 +19878,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -20736,7 +20573,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name @@ -20857,7 +20694,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name @@ -20877,7 +20714,7 @@ If you believe it is correct, remove the corresponding line from the file and re - + Profile ID @@ -20933,7 +20770,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -20947,11 +20784,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - [ ... Brakująca Wiadomość ... ] - RsMessageModel @@ -20965,6 +20797,11 @@ prevents the message to be forwarded to your friends. From Od + + + To + Do + Subject @@ -20987,12 +20824,17 @@ prevents the message to be forwarded to your friends. - Click to sort by read + Click to sort by read status - Click to sort by from + Click to sort by author + + + + + Click to sort by destination @@ -21016,7 +20858,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -21037,7 +20881,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. @@ -21098,7 +20942,7 @@ prevents the message to be forwarded to your friends. - + Unable to open log file '%1': %2 @@ -21119,7 +20963,7 @@ prevents the message to be forwarded to your friends. - + opmode @@ -21149,7 +20993,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -21167,7 +21011,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -21184,12 +21028,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) - + Start Search @@ -21250,7 +21094,7 @@ prevents the message to be forwarded to your friends. - + KeyWords @@ -21265,7 +21109,7 @@ prevents the message to be forwarded to your friends. - + Filename @@ -21365,23 +21209,23 @@ prevents the message to be forwarded to your friends. - + File Name Nazwa pliku - + Download Pobierz - + Copy RetroShare Link Skopiuj link RetroShare - + Send RetroShare Link @@ -21391,7 +21235,7 @@ prevents the message to be forwarded to your friends. - + Download Notice Pobierz @@ -21428,7 +21272,7 @@ prevents the message to be forwarded to your friends. - + Folder Folder @@ -21439,17 +21283,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) - + Open Folder Otwórz folder - + Create Collection... @@ -21469,7 +21313,7 @@ prevents the message to be forwarded to your friends. - + Collection @@ -21477,7 +21321,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details @@ -21493,22 +21337,22 @@ prevents the message to be forwarded to your friends. Usuń element - + IP address: - + Peer ID: - + Location: Miejsce: - + Peer Name: @@ -21525,7 +21369,7 @@ prevents the message to be forwarded to your friends. Ukryj - + but reported: @@ -21550,8 +21394,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -21559,7 +21403,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare chce być przyjacielem z tobą na RetroShare @@ -21590,7 +21434,7 @@ prevents the message to be forwarded to your friends. - + Expand Rozwiń @@ -21635,12 +21479,12 @@ prevents the message to be forwarded to your friends. Status: - + Write Message Napisz wiadomość - + Connect Attempt @@ -21660,17 +21504,12 @@ prevents the message to be forwarded to your friends. - + Unknown Security Issue - - A unknown peer - - - - + Unknown Nieznane @@ -21680,7 +21519,17 @@ prevents the message to be forwarded to your friends. - + + SSL request + + + + + An unknown peer + + + + Hide Ukryj @@ -21690,7 +21539,7 @@ prevents the message to be forwarded to your friends. Czy chcesz usunąć tego Przyjaciela? - + Certificate has wrong signature!! This peer is not who he claims to be. @@ -21700,12 +21549,12 @@ prevents the message to be forwarded to your friends. - + Certificate caused an internal error. - + Peer/node not in friendlist (PGP id= @@ -21764,12 +21613,12 @@ prevents the message to be forwarded to your friends. - + Local Address Adres Lokalny - + NAT @@ -21790,22 +21639,22 @@ prevents the message to be forwarded to your friends. - + Local network - + External ip address finder - + UPnP - + Known / Previous IPs: @@ -21818,21 +21667,16 @@ behind a firewall or a VPN. - - Allow RetroShare to ask my ip to these websites: - - - - - - + + + kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -21842,23 +21686,46 @@ behind a firewall or a VPN. - + Onion Address - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -21868,7 +21735,7 @@ behind a firewall or a VPN. - + I2P Address @@ -21893,37 +21760,95 @@ behind a firewall or a VPN. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -21938,71 +21863,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. nieznane - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -22012,22 +21873,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -22039,12 +21885,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -22054,7 +21900,7 @@ Also check your ports! - + Download limit (KB/s) @@ -22069,23 +21915,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -22096,17 +21942,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -22116,12 +21952,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -22131,17 +21962,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 127.0.0.1 - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -22181,7 +22002,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start Start @@ -22196,12 +22017,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why Stop - - BOB status - - - - + Incoming Przychodzące @@ -22237,7 +22053,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -22292,7 +22133,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Warning: This bandwidth adds up to the max bandwidth. @@ -22317,7 +22158,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -22329,7 +22170,7 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Filters @@ -22352,7 +22193,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status Stan @@ -22412,17 +22253,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -22438,18 +22290,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -22484,12 +22336,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -22512,22 +22364,22 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -22562,7 +22414,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -22572,12 +22424,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -22657,7 +22509,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with @@ -22667,12 +22519,12 @@ If you have issues connecting over Tor check the Tor logs too. Podziel się z przyjacielem - + Share - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -22691,7 +22543,7 @@ Select the Friends with which you want to Share your Channel. - + Shared directory @@ -22711,17 +22563,17 @@ Select the Friends with which you want to Share your Channel. Widoczność - + Add new - + Cancel Anuluj - + Add a Share Directory @@ -22731,7 +22583,7 @@ Select the Friends with which you want to Share your Channel. Usuń - + Apply and close Zastosuj i zamknij @@ -22822,7 +22674,7 @@ Select the Friends with which you want to Share your Channel. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. @@ -22830,7 +22682,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files Pliki @@ -22881,11 +22733,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files - + Download selected @@ -22895,7 +22752,7 @@ Select the Friends with which you want to Share your Channel. Pobierz - + Copy retroshare Links to Clipboard @@ -22910,7 +22767,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted @@ -22926,7 +22783,7 @@ Select the Friends with which you want to Share your Channel. - + Create Collection... @@ -22951,7 +22808,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted because they have not been indexed yet. @@ -23094,12 +22951,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration - + Create interface @@ -23123,7 +22980,7 @@ Select the Friends with which you want to Share your Channel. - + Log In @@ -23462,7 +23319,7 @@ This choice can be reverted in settings. - + Message: Wiadomość: @@ -23703,7 +23560,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags Usuń wszystkie tagi @@ -23739,12 +23596,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown Nieznane @@ -23754,18 +23614,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -23775,12 +23630,57 @@ p, li { white-space: pre-wrap; } - + + Error + Błąd + + + + Not connected + + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -23788,7 +23688,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -23798,7 +23698,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -23809,11 +23709,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -23841,7 +23742,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options Opcje transferu @@ -23852,7 +23753,7 @@ p, li { white-space: pre-wrap; } Maksymalna ilość jednoczesnych pobierań: - + Shared Directories @@ -23862,22 +23763,27 @@ p, li { white-space: pre-wrap; } - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -23962,7 +23868,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -23971,7 +23877,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -23996,7 +23907,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming @@ -24061,12 +23977,7 @@ p, li { white-space: pre-wrap; } - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -24076,7 +23987,17 @@ p, li { white-space: pre-wrap; } - + + Warning + Ostrzeżenie + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -24104,7 +24025,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed Pobieranie zakończone @@ -24128,39 +24049,23 @@ p, li { white-space: pre-wrap; } %1 completed transfer - - You have %1 completed downloads - Masz %1 zakończonych pobierań - - - You have %1 completed download - Masz %1 zakończone pobieranie - - - %1 completed downloads - %1 zakończonych pobierań - - - %1 completed download - %1 zakończone pobieranie - TransfersDialog - - + + Downloads Pobierania - + Uploads - + Name i.e: file name Nazwa @@ -24367,7 +24272,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... @@ -24392,7 +24302,7 @@ p, li { white-space: pre-wrap; } - + Anonymous end-to-end encrypted tunnel 0x @@ -24413,7 +24323,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -24446,7 +24356,17 @@ p, li { white-space: pre-wrap; } - + + Warning + Ostrzeżenie + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name @@ -24461,7 +24381,7 @@ p, li { white-space: pre-wrap; } - + Expand all Rozwiń wszystkie @@ -24588,23 +24508,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Kolumny - + File Transfers Transfery plików - + Path Ścieżka @@ -24614,7 +24529,7 @@ p, li { white-space: pre-wrap; } - + Could not delete preview file @@ -24624,7 +24539,7 @@ p, li { white-space: pre-wrap; } - + Create Collection... @@ -24639,7 +24554,7 @@ p, li { white-space: pre-wrap; } - + Collection @@ -24649,7 +24564,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x @@ -25063,12 +24978,17 @@ p, li { white-space: pre-wrap; } Formularz - + Enable Retroshare WEB Interface - + + Status: + Status: + + + Web parameters @@ -25108,17 +25028,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -25128,12 +25058,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface @@ -25270,11 +25200,7 @@ p, li { white-space: pre-wrap; } Strony Wiki - New Group - Nowa Grupa - - - + Page Name @@ -25289,7 +25215,7 @@ p, li { white-space: pre-wrap; } - + << << @@ -25377,7 +25303,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History Historia Edycji Strony @@ -25412,7 +25338,7 @@ p, li { white-space: pre-wrap; } - + \/ \/ @@ -25442,14 +25368,18 @@ p, li { white-space: pre-wrap; } Tagi - - + + History + Historia + + + Show Edit History Pokaż Historię Edycji - + Status Status @@ -25470,7 +25400,7 @@ p, li { white-space: pre-wrap; } - + Submit @@ -25553,16 +25483,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - Odśwież - - - + Settings @@ -25577,7 +25498,7 @@ p, li { white-space: pre-wrap; } Inni - + Who to Follow @@ -25597,7 +25518,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -25627,57 +25548,17 @@ p, li { white-space: pre-wrap; } - Last Month - Ostatni miesiąc - - - Last Week - Ostatni tydzień - - - Today - Dziś - - - New - Nowy - - - from - od - - - Manage Accounts - Zarządzaj Kontami - - - + Yourself - - Friends - Przyjaciele - Following Następujące - Account 1 - Konto 1 - - - Account 2 - Konto 2 - - - Account 3 - Konto 3 - - - + RetroShare RetroShare @@ -25740,35 +25621,42 @@ p, li { white-space: pre-wrap; } Formularz - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + Usuń + + + Location: Miejsce: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -25813,11 +25701,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + + + + + Following + Następujące + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Nieznane @@ -25895,7 +25813,7 @@ p, li { white-space: pre-wrap; } - + k e.g: 3.1 k @@ -25932,7 +25850,7 @@ p, li { white-space: pre-wrap; } pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_pt.ts b/retroshare-gui/src/lang/retroshare_pt.ts index 4835855cf..842fde2d7 100644 --- a/retroshare-gui/src/lang/retroshare_pt.ts +++ b/retroshare-gui/src/lang/retroshare_pt.ts @@ -121,12 +121,12 @@ - + Search Criteria - + Add a further search criterion. @@ -136,7 +136,7 @@ - + Cancels the search. @@ -540,7 +540,7 @@ p, li { white-space: pre-wrap; } - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. @@ -566,10 +566,23 @@ p, li { white-space: pre-wrap; } + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb @@ -612,7 +625,7 @@ p, li { white-space: pre-wrap; } - + Set your Avatar picture @@ -699,7 +712,7 @@ p, li { white-space: pre-wrap; } Repor - + Always on Top @@ -795,7 +808,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment @@ -825,12 +838,12 @@ p, li { white-space: pre-wrap; } - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -838,7 +851,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up @@ -858,7 +871,7 @@ p, li { white-space: pre-wrap; } - + Posted by @@ -896,7 +909,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up @@ -916,7 +929,7 @@ p, li { white-space: pre-wrap; } - + Click to view picture @@ -946,7 +959,7 @@ p, li { white-space: pre-wrap; } - + Toggle Message Read Status @@ -956,7 +969,7 @@ p, li { white-space: pre-wrap; } - + TextLabel @@ -964,12 +977,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this - + 0 @@ -989,18 +1002,18 @@ p, li { white-space: pre-wrap; } - + New Comment - + Copy RetroShare Link - + Expand @@ -1015,12 +1028,12 @@ p, li { white-space: pre-wrap; } - + Name - + Comm value @@ -1189,17 +1202,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels - + Tabs - + General @@ -1209,7 +1222,17 @@ p, li { white-space: pre-wrap; } - + + Downloads + + + + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab @@ -1217,7 +1240,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1240,7 +1263,7 @@ into the image, so as to ChannelsCommentsItem - + I like this @@ -1265,18 +1288,18 @@ into the image, so as to - + New Comment - + Copy RetroShare Link - + Expand @@ -1291,7 +1314,7 @@ into the image, so as to - + Name @@ -1301,17 +1324,7 @@ into the image, so as to - - Comment - - - - - Comments - - - - + Hide @@ -1319,7 +1332,7 @@ into the image, so as to ChatLobbyDialog - + Name @@ -1510,7 +1523,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby @@ -1543,13 +1556,14 @@ into the image, so as to - + + Unknown Lobby - - + + Remove All @@ -1557,13 +1571,13 @@ into the image, so as to ChatLobbyWidget - - + + Name - + Count @@ -1573,29 +1587,7 @@ into the image, so as to - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - - - - - - Public chat rooms - - - - + Create chat room @@ -1605,7 +1597,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1662,12 +1654,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1677,23 +1669,42 @@ Double click a chat room to enter and chat. - + [No topic provided] - + + Private Subscribed + + + + + + Public Subscribed + + + + + Private - + + + Public - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted @@ -1703,27 +1714,22 @@ Double click a chat room to enter and chat. - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe - + Search Chat lobbies - + Search Name - + Columns @@ -1738,47 +1744,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: - + Type: - + Security: - + Peers: - - - - - - + + + + + + TextLabel @@ -1793,7 +1799,7 @@ Double click a chat room to enter and chat. - + Show Mostrar @@ -1813,7 +1819,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item @@ -1858,7 +1864,7 @@ Double click a chat room to enter and chat. ChatPage - + General @@ -1873,7 +1879,7 @@ Double click a chat room to enter and chat. - + Enable custom fonts @@ -1893,7 +1899,7 @@ Double click a chat room to enter and chat. - + General settings @@ -1918,7 +1924,7 @@ Double click a chat room to enter and chat. - + Blink tab icon @@ -1948,7 +1954,7 @@ Double click a chat room to enter and chat. - + Change Chat Font @@ -1958,7 +1964,7 @@ Double click a chat room to enter and chat. - + History @@ -1982,7 +1988,7 @@ Double click a chat room to enter and chat. - + Choose your default font for Chat. @@ -2052,12 +2058,22 @@ Double click a chat room to enter and chat. - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2067,7 +2083,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2164,7 +2190,7 @@ Double click a chat room to enter and chat. - + Case sensitive Sensível capitalização @@ -2270,7 +2296,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat @@ -2306,7 +2332,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close @@ -2341,12 +2367,12 @@ Double click a chat room to enter and chat. - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2426,11 +2452,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2468,7 +2489,7 @@ Double click a chat room to enter and chat. - + is typing... @@ -2490,7 +2511,7 @@ after HTML conversion. - + Do you really want to physically delete the history? @@ -2540,7 +2561,7 @@ after HTML conversion. - + Find Case Sensitively @@ -2562,7 +2583,7 @@ after HTML conversion. - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> @@ -2577,12 +2598,12 @@ after HTML conversion. - + (Status) - + Attach a File @@ -2598,12 +2619,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> - + Person id: @@ -2614,12 +2635,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. @@ -2639,7 +2660,7 @@ Double click on it to add his name on text writer. - + Don't stop to color after @@ -2665,7 +2686,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: @@ -2687,7 +2708,7 @@ Double click on it to add his name on text writer. - + Personal Circles @@ -2713,7 +2734,7 @@ Double click on it to add his name on text writer. - + Friends @@ -2773,7 +2794,7 @@ Double click on it to add his name on text writer. - + External Circles (Admin) @@ -2789,7 +2810,7 @@ Double click on it to add his name on text writer. - + Circles @@ -2841,45 +2862,45 @@ Double click on it to add his name on text writer. - + RetroShare - + - + Error : cannot get peer details. - + Retroshare ID - + <p>This Retroshare ID contains: - + <p>This certificate contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: @@ -2889,7 +2910,7 @@ Double click on it to add his name on text writer. - + Not connected @@ -2971,12 +2992,17 @@ Double click on it to add his name on text writer. - + <li>a <b>node ID</b> and <b>name</b> - + + <b>DNS:</b> : + + + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -2996,7 +3022,7 @@ Double click on it to add his name on text writer. - + with @@ -3064,7 +3090,7 @@ Double click on it to add his name on text writer. - + @@ -3080,12 +3106,12 @@ Double click on it to add his name on text writer. - + Peer details - + Name: Nome: @@ -3095,17 +3121,17 @@ Double click on it to add his name on text writer. - + Options Opções - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: @@ -3115,7 +3141,7 @@ Double click on it to add his name on text writer. - + Please paste below your friend's Retroshare ID @@ -3140,12 +3166,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with - + Sorry, some error appeared @@ -3165,32 +3201,27 @@ Double click on it to add his name on text writer. - + Key validity: - + Profile ID: - - Signers - - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. - + To accept the Friend Request, click the Accept button. @@ -3236,17 +3267,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed - + Not a valid Retroshare certificate! - + RetroShare Invitation @@ -3266,12 +3297,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3279,7 +3310,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3319,7 +3350,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Profile password needed. @@ -3344,7 +3375,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3354,7 +3385,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3393,7 +3424,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + IP-Addr: @@ -3403,7 +3434,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Show Advanced options @@ -3428,7 +3459,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already in your keyring @@ -3441,7 +3472,7 @@ even if you don't make friends. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. @@ -3476,7 +3507,7 @@ even if you don't make friends. - + No IP in this certificate! @@ -3486,12 +3517,7 @@ even if you don't make friends. - - [Unknown] - - - - + Added with certificate from %1 @@ -3556,7 +3582,7 @@ even if you don't make friends. - + UDP Setup @@ -3584,7 +3610,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant @@ -3594,17 +3620,20 @@ p, li { white-space: pre-wrap; } - + + Unknown State - + + Offline - + + Behind Symmetric NAT @@ -3614,12 +3643,14 @@ p, li { white-space: pre-wrap; } - + + NET Restart - + + Behind NAT @@ -3629,7 +3660,8 @@ p, li { white-space: pre-wrap; } - + + NET STATE GOOD! @@ -3654,7 +3686,7 @@ p, li { white-space: pre-wrap; } - + Lookup requires DHT @@ -3946,7 +3978,7 @@ p, li { white-space: pre-wrap; } - + @@ -3954,7 +3986,8 @@ p, li { white-space: pre-wrap; } - + + UNVERIFIABLE FORWARD! @@ -3964,7 +3997,7 @@ p, li { white-space: pre-wrap; } - + Searching @@ -4000,12 +4033,12 @@ p, li { white-space: pre-wrap; } - + Name - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4025,7 +4058,7 @@ p, li { white-space: pre-wrap; } - + IDs @@ -4045,18 +4078,18 @@ p, li { white-space: pre-wrap; } - + Cancel - + Nickname - + Invited Members @@ -4071,7 +4104,7 @@ p, li { white-space: pre-wrap; } - + Name: Nome: @@ -4111,19 +4144,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare - + Please set a name for your Circle - + No Restriction Circle Selected @@ -4133,12 +4166,24 @@ p, li { white-space: pre-wrap; } - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add Adicionar @@ -4148,7 +4193,7 @@ p, li { white-space: pre-wrap; } - + Search @@ -4201,13 +4246,13 @@ p, li { white-space: pre-wrap; } - + Create - + Add Member @@ -4226,7 +4271,7 @@ p, li { white-space: pre-wrap; } - + Group Name: @@ -4261,7 +4306,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post @@ -4271,7 +4316,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4416,17 +4461,17 @@ p, li { white-space: pre-wrap; } - + RetroShare - + This file already in this post: - + Post refers to non shared files @@ -4451,7 +4496,12 @@ p, li { white-space: pre-wrap; } - + + Cannot publish post + + + + Load thumbnail picture @@ -4466,18 +4516,12 @@ p, li { white-space: pre-wrap; } - - + Generate mass data - - Do you really want to generate %1 messages ? - - - - + You are about to add files you're not actually sharing. Do you still want this to happen? @@ -4511,7 +4555,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message @@ -4521,7 +4565,16 @@ p, li { white-space: pre-wrap; } - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> + + + + Attach File @@ -4536,16 +4589,7 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> - - - - + Attach a Picture @@ -4560,7 +4604,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4590,17 +4634,17 @@ p, li { white-space: pre-wrap; } - + No Forum - + In Reply to - + Title @@ -4653,7 +4697,7 @@ Do you want to discard this message? - + No compatible ID for this forum @@ -4663,8 +4707,8 @@ Do you want to discard this message? - - + + Generate mass data @@ -4687,7 +4731,7 @@ Do you want to discard this message? CreateLobbyDialog - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -4722,7 +4766,7 @@ Do you want to discard this message? - + Create @@ -4732,7 +4776,7 @@ Do you want to discard this message? - + require PGP-signed identities @@ -4747,7 +4791,7 @@ Do you want to discard this message? - + Create Chat Room @@ -4768,7 +4812,7 @@ Do you want to discard this message? - + Identity to use: @@ -4776,17 +4820,17 @@ Do you want to discard this message? CryptoPage - + Public Information - + Name: Nome: - + Location: @@ -4796,12 +4840,12 @@ Do you want to discard this message? - + Software Version: - + Online since: @@ -4821,12 +4865,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -4836,7 +4875,7 @@ Do you want to discard this message? - + Other Information @@ -4846,17 +4885,12 @@ Do you want to discard this message? - + Profile - - Certificate - - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -4866,7 +4900,7 @@ Do you want to discard this message? - + Export Identity @@ -4936,33 +4970,33 @@ and use the import button to load it - + TextLabel - + PGP fingerprint: - - Node information - - - - + PGP Id : - + Friend nodes: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5052,7 +5086,7 @@ and use the import button to load it DLListDelegate - + B @@ -5720,7 +5754,7 @@ and use the import button to load it DownloadToaster - + Start file @@ -5728,38 +5762,38 @@ and use the import button to load it ExprParamElement - + - + to - + ignore case - - - dd.MM.yyyy + + + yyyy-MM-dd - - + + KB - - + + MB - - + + GB @@ -5767,12 +5801,12 @@ and use the import button to load it ExpressionWidget - + Expression Widget - + Delete this expression @@ -5934,7 +5968,7 @@ and use the import button to load it FilesDefs - + Picture @@ -5944,7 +5978,7 @@ and use the import button to load it - + Audio @@ -6004,11 +6038,21 @@ and use the import button to load it C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories @@ -6130,7 +6174,7 @@ and use the import button to load it - + ID @@ -6172,7 +6216,7 @@ and use the import button to load it - + Group @@ -6208,7 +6252,7 @@ and use the import button to load it - + Search @@ -6224,7 +6268,7 @@ and use the import button to load it - + Profile details @@ -6461,7 +6505,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request @@ -6499,7 +6543,7 @@ at least one peer was not added to a group - + Mark all @@ -6510,16 +6554,132 @@ at least one peer was not added to a group + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + + + + + Node ID + + + + + Address + + + + + Status + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message - - + + Broadcast @@ -6602,33 +6762,38 @@ at least one peer was not added to a group - + Keyring - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. - - + + Network - + + Friend Server + + + + Network graph - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. @@ -6646,7 +6811,17 @@ at least one peer was not added to a group - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters @@ -6656,17 +6831,12 @@ at least one peer was not added to a group - + Port - - Use BOB - - - - + This password is for PGP @@ -6687,38 +6857,38 @@ at least one peer was not added to a group - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -6738,12 +6908,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -6753,38 +6923,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel - + hidden address - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -6828,13 +7003,13 @@ and use the import button to load it - + Import profile - + Create new profile and new Retroshare node @@ -6844,7 +7019,7 @@ and use the import button to load it - + Tor/I2P address @@ -6879,7 +7054,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -6889,12 +7064,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -6904,12 +7074,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7135,27 +7300,13 @@ and use the import button to load it - + Invite Friends - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - - - - + Add Your Friends to RetroShare @@ -7165,39 +7316,57 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + Connect To Friends - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port @@ -7205,49 +7374,45 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - - - - + Further Help and Support - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website @@ -7272,7 +7437,7 @@ p, li { white-space: pre-wrap; } - + RetroShare Invitation @@ -7322,12 +7487,12 @@ p, li { white-space: pre-wrap; } - + RetroShare Support - + It has many features, including built-in chat, messaging, @@ -7451,7 +7616,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat @@ -7459,7 +7624,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] @@ -7629,7 +7794,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title @@ -7642,12 +7807,12 @@ p, li { white-space: pre-wrap; } - + Description - + Number of Unread message @@ -7672,7 +7837,7 @@ p, li { white-space: pre-wrap; } - + You are admin (modify names and description using Edit menu) @@ -7687,14 +7852,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post - + Name @@ -7705,13 +7870,13 @@ p, li { white-space: pre-wrap; } - + Never - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -7724,7 +7889,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and @@ -7860,7 +8025,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels @@ -7871,22 +8036,22 @@ p, li { white-space: pre-wrap; } - + Enable Auto-Download - + My Channels - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels @@ -7906,12 +8071,12 @@ p, li { white-space: pre-wrap; } - + Disable Auto-Download - + Set download directory @@ -7946,22 +8111,22 @@ p, li { white-space: pre-wrap; } - + Play - + Open folder - + Open file - + Error @@ -7981,17 +8146,17 @@ p, li { white-space: pre-wrap; } - + Are you sure that you want to cancel and delete the file? - + Can't open folder - + Play File @@ -8004,7 +8169,7 @@ p, li { white-space: pre-wrap; } GxsChannelGroupDialog - + Create New Channel @@ -8042,8 +8207,18 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel @@ -8058,7 +8233,7 @@ p, li { white-space: pre-wrap; } - + Expand @@ -8073,7 +8248,7 @@ p, li { white-space: pre-wrap; } - + Loading @@ -8087,6 +8262,11 @@ p, li { white-space: pre-wrap; } New Channel: + + + Never + + Hide @@ -8096,7 +8276,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: @@ -8117,7 +8297,7 @@ p, li { white-space: pre-wrap; } - + Play @@ -8179,18 +8359,18 @@ p, li { white-space: pre-wrap; } - + New - + 0 - - + + Comment @@ -8205,17 +8385,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + Comments - + Post @@ -8243,13 +8423,13 @@ p, li { white-space: pre-wrap; } GxsChannelPostsWidgetWithModel - + Post to Channel - + Add new post @@ -8319,7 +8499,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -8355,7 +8535,7 @@ p, li { white-space: pre-wrap; } - + Comments @@ -8370,13 +8550,13 @@ p, li { white-space: pre-wrap; } - - + + Click to switch to list view - + Show unread posts only @@ -8391,7 +8571,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -8406,7 +8586,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -8466,12 +8646,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -8546,12 +8736,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed @@ -8602,17 +8793,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -8727,7 +8918,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container @@ -8740,7 +8931,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -8770,7 +8961,7 @@ p, li { white-space: pre-wrap; } - + Comment @@ -8809,7 +9000,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment @@ -8833,6 +9024,21 @@ p, li { white-space: pre-wrap; } Vote Down + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -8842,7 +9048,7 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -8871,7 +9077,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -8902,7 +9108,7 @@ before you can comment - + It remains %1 characters after HTML conversion. @@ -8953,7 +9159,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum @@ -8969,7 +9175,7 @@ before you can comment - + Expand @@ -8988,6 +9194,11 @@ before you can comment Moderator list + + + TextLabel + + Loading... @@ -9017,13 +9228,13 @@ before you can comment GxsForumMsgItem - - + + Subject: - + Unsubscribe To Forum @@ -9034,7 +9245,7 @@ before you can comment - + Expand @@ -9054,17 +9265,17 @@ before you can comment - + Loading... - + Forum Feed - + Hide @@ -9077,59 +9288,66 @@ before you can comment - + Start new Thread for Selected Forum - + + Threaded + + + + + + + ... + + + + + Flat + + + + + Latest post in thread + + + + Search forums - + New Thread - - - Threaded View - - - - - Flat View - - - + Title - - + + Date - + Author - - Save image - - - - + Loading - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9139,12 +9357,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message @@ -9184,23 +9397,23 @@ before you can comment - + No name - - + + Reply - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -9243,12 +9456,12 @@ before you can comment - + Hide - + [unknown] @@ -9278,8 +9491,8 @@ before you can comment - - + + Distribution @@ -9362,12 +9575,12 @@ before you can comment - + New thread - + Edit @@ -9428,7 +9641,7 @@ before you can comment - + Show column @@ -9448,7 +9661,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive @@ -9500,7 +9713,7 @@ This message is missing. You should receive it later. - + No result. @@ -9510,7 +9723,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -9525,7 +9738,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -9591,12 +9804,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums @@ -9631,12 +9844,12 @@ This message is missing. You should receive it later. GxsGroupDialog - + Name - + Key recipients can publish to restricted-type group and can view and publish for private-type channels @@ -9647,12 +9860,12 @@ This message is missing. You should receive it later. - + Description - + Message Distribution @@ -9660,7 +9873,7 @@ This message is missing. You should receive it later. - + Public @@ -9720,7 +9933,7 @@ This message is missing. You should receive it later. - + Comments: @@ -9743,7 +9956,7 @@ This message is missing. You should receive it later. - + All People @@ -9759,12 +9972,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -9781,23 +9994,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -9813,22 +10026,28 @@ This message is missing. You should receive it later. - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo - + Submit Group Changes - + Owner: @@ -9838,12 +10057,12 @@ This message is missing. You should receive it later. - + Info - + ID @@ -9853,7 +10072,7 @@ This message is missing. You should receive it later. - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -9928,7 +10147,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity @@ -9944,27 +10168,22 @@ This message is missing. You should receive it later. - + Created - + Cancel - + Create - - Author - - - - + GxsIdLabel @@ -9972,7 +10191,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading @@ -10032,7 +10251,7 @@ This message is missing. You should receive it later. - + Synchronise posts of last... @@ -10089,12 +10308,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link @@ -10117,7 +10336,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature @@ -10130,14 +10349,14 @@ This message is missing. You should receive it later. GxsIdDetails - + Not found - - + + [Banned] @@ -10147,7 +10366,7 @@ This message is missing. You should receive it later. - + Loading... @@ -10157,7 +10376,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -10177,6 +10401,14 @@ This message is missing. You should receive it later. + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -10188,7 +10420,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -10236,7 +10468,7 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] @@ -10623,7 +10855,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -10639,7 +10871,7 @@ p, li { white-space: pre-wrap; } - + Authors @@ -10658,7 +10890,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -10732,7 +10964,7 @@ p, li { white-space: pre-wrap; } - + Add friend @@ -10742,7 +10974,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -10770,7 +11002,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -10780,7 +11012,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard @@ -10790,7 +11022,7 @@ private and secure decentralized communication platform. - + Send via Email @@ -10810,13 +11042,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -10828,12 +11084,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -10848,12 +11104,7 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... @@ -11118,14 +11369,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All - + Reputation @@ -11135,12 +11386,12 @@ p, li { white-space: pre-wrap; } - + Anonymous Id - + Create new Identity @@ -11150,7 +11401,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -11165,27 +11416,27 @@ p, li { white-space: pre-wrap; } - + Close - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -11201,29 +11452,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles - + Circle name @@ -11243,18 +11504,20 @@ p, li { white-space: pre-wrap; } - + + Edit identity - + + Delete identity - + Chat with this peer @@ -11264,78 +11527,78 @@ p, li { white-space: pre-wrap; } - + Owner node ID : - + Identity name : - + () - + Identity ID - + Send message - + Identity info - + Identity ID : - + Owner node name : - + Create new... - + Type: - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: - + Negative - + Neutral @@ -11346,17 +11609,17 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous @@ -11371,24 +11634,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you - - + + My own identities - - + + My contacts - + Show Items @@ -11403,7 +11666,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -11413,7 +11681,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -11488,7 +11756,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -11518,7 +11786,7 @@ p, li { white-space: pre-wrap; } - + Invited @@ -11533,7 +11801,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle @@ -11581,7 +11849,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -11589,7 +11857,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -11632,7 +11900,7 @@ These identities will soon be not supported anymore. - + Boards @@ -11712,7 +11980,7 @@ These identities will soon be not supported anymore. - + information @@ -11728,17 +11996,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -11843,7 +12106,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -11893,21 +12156,21 @@ These identities will soon be not supported anymore. - - - + + + People - + Your Avatar Click here to change your avatar - + Linked to neighbor nodes @@ -11917,7 +12180,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -11932,7 +12195,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -11947,12 +12210,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -11972,12 +12235,12 @@ These identities will soon be not supported anymore. - + Owned by - + Node name: @@ -11987,7 +12250,7 @@ These identities will soon be not supported anymore. - + Really delete? @@ -11995,7 +12258,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname @@ -12025,7 +12288,13 @@ These identities will soon be not supported anymore. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity @@ -12039,7 +12308,7 @@ These identities will soon be not supported anymore. - + @@ -12049,7 +12318,12 @@ These identities will soon be not supported anymore. - + + No avatar chosen + + + + Edit identity @@ -12060,27 +12334,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -12100,7 +12374,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -12110,12 +12384,18 @@ These identities will soon be not supported anymore. - + Error KeyID invalid - + + + No Avatar chosen. A default image will be automatically displayed from your new identity. + + + + Import image @@ -12125,12 +12405,7 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. - - - - + Unknown GpgId @@ -12140,7 +12415,7 @@ These identities will soon be not supported anymore. - + Create New Identity @@ -12150,10 +12425,15 @@ These identities will soon be not supported anymore. - + Choose image... + + + Remove + + @@ -12179,7 +12459,7 @@ These identities will soon be not supported anymore. Adicionar - + Create @@ -12189,13 +12469,13 @@ These identities will soon be not supported anymore. - + Your Avatar Click here to change your avatar - + Linked to your profile @@ -12205,7 +12485,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -12279,7 +12559,7 @@ These identities will soon be not supported anymore. - + Copy Copiar @@ -12289,12 +12569,12 @@ These identities will soon be not supported anymore. - + %1 's Message History - + Mark all @@ -12317,18 +12597,34 @@ These identities will soon be not supported anymore. ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -12346,27 +12642,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: - + Listen Address: - + + Status: + + + + 127.0.0.1 - + Token: @@ -12387,7 +12688,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -12396,26 +12702,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File - + Open Folder - + Checking... @@ -12425,7 +12736,7 @@ These identities will soon be not supported anymore. - + Recommend in a message to... @@ -12453,7 +12764,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend @@ -12469,7 +12780,8 @@ These identities will soon be not supported anymore. - + + Options Opções @@ -12490,7 +12802,7 @@ These identities will soon be not supported anymore. - + Quit @@ -12501,12 +12813,12 @@ These identities will soon be not supported anymore. - + RetroShare %1 a secure decentralized communication platform - + Unfinished @@ -12531,11 +12843,12 @@ These identities will soon be not supported anymore. + Status - + Notify @@ -12546,31 +12859,35 @@ These identities will soon be not supported anymore. + Open Messages - + + Bandwidth Graph - + Applications + Help - + + Minimize - + Maximize @@ -12585,7 +12902,12 @@ These identities will soon be not supported anymore. - + + Close window + + + + %1 new message @@ -12615,7 +12937,7 @@ These identities will soon be not supported anymore. - + Do you really want to exit RetroShare ? @@ -12635,7 +12957,7 @@ These identities will soon be not supported anymore. Mostrar - + Make sure this link has not been forged to drag you to a malicious website. @@ -12680,12 +13002,13 @@ These identities will soon be not supported anymore. - + + Statistics - + Show web interface @@ -12700,7 +13023,7 @@ These identities will soon be not supported anymore. - + Really quit ? @@ -12709,17 +13032,17 @@ These identities will soon be not supported anymore. MessageComposer - + Compose - + Contacts - + Paragraph @@ -12755,12 +13078,12 @@ These identities will soon be not supported anymore. - + Font size - + Increase font size @@ -12775,32 +13098,32 @@ These identities will soon be not supported anymore. - + Italic - + Alignment - + Add an Image - + Sets text font to code style - + Underline - + Subject: @@ -12811,32 +13134,32 @@ These identities will soon be not supported anymore. - + Tags - + Address list: - + Recommend this friend - + Set Text color - + Set Text background color - + Recommended Files @@ -12906,7 +13229,7 @@ These identities will soon be not supported anymore. - + Send To: @@ -12946,7 +13269,7 @@ These identities will soon be not supported anymore. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> @@ -12966,18 +13289,18 @@ These identities will soon be not supported anymore. - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team - - + + Save Message - + Message has not been Sent. Do you want to save message to draft box? @@ -12988,7 +13311,17 @@ Do you want to save message to draft box? - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" @@ -13008,7 +13341,7 @@ Do you want to save message to draft box? - + Original Message @@ -13018,21 +13351,21 @@ Do you want to save message to draft box? - + - + To - - + + Cc - + Sent @@ -13047,7 +13380,7 @@ Do you want to save message to draft box? - + Re: @@ -13057,30 +13390,30 @@ Do you want to save message to draft box? - - - + + + RetroShare - + Do you want to send the message without a subject ? - + Please insert at least one recipient. - + Bcc - + Unknown @@ -13195,13 +13528,13 @@ Do you want to save message to draft box? - + Open File... - + HTML-Files (*.htm *.html);;All Files (*) @@ -13221,7 +13554,7 @@ Do you want to save message to draft box? - + Message has not been Sent. Do you want to save message ? @@ -13242,7 +13575,7 @@ Do you want to save message ? - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -13272,18 +13605,18 @@ Do you want to save message ? - - + + Close - + From: De: - + Bullet list (disc) @@ -13323,13 +13656,13 @@ Do you want to save message ? - - + + Thanks, <br> - + Distant identity: @@ -13339,12 +13672,12 @@ Do you want to save message ? - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -13422,7 +13755,7 @@ Do you want to save message ? Omissão - + A new tab @@ -13432,7 +13765,7 @@ Do you want to save message ? - + Edit Tag @@ -13455,7 +13788,7 @@ Do you want to save message ? MessageToaster - + Sub: @@ -13463,7 +13796,7 @@ Do you want to save message ? MessageUserNotify - + Message @@ -13491,7 +13824,7 @@ Do you want to save message ? MessageWidget - + Recommended Files @@ -13501,37 +13834,37 @@ Do you want to save message ? - + Subject: - + From: De: - + To: Para: - + Cc: - + Bcc: - + Tags: - + Reply @@ -13571,7 +13904,7 @@ Do you want to save message ? - + Send Invite @@ -13623,7 +13956,7 @@ Do you want to save message ? - + Confirm %1 as friend @@ -13633,12 +13966,12 @@ Do you want to save message ? - + View source - + No subject @@ -13648,17 +13981,22 @@ Do you want to save message ? - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -13667,14 +14005,24 @@ Do you want to save message ? %1 (%2) + + + Show less + + + + + Show more + + - + Download all - + Print Document @@ -13689,12 +14037,12 @@ Do you want to save message ? - + Load images always for this message - + Hide the attachment pane @@ -13716,10 +14064,6 @@ Do you want to save message ? Compose - - Delete - Apagar - Print @@ -13798,7 +14142,7 @@ Do you want to save message ? MessagesDialog - + New Message @@ -13808,20 +14152,16 @@ Do you want to save message ? - Delete - Apagar - - - + - - + + Tags - - + + Inbox @@ -13851,17 +14191,17 @@ Do you want to save message ? - + Total Inbox: - + Quick View - + Print... @@ -13892,7 +14232,7 @@ Do you want to save message ? - + Subject @@ -13902,7 +14242,7 @@ Do you want to save message ? - + Date @@ -13912,7 +14252,7 @@ Do you want to save message ? - + Search Subject @@ -13921,6 +14261,16 @@ Do you want to save message ? Search From + + + To + + + + + Search To + + Search Date @@ -13947,12 +14297,12 @@ Do you want to save message ? - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred @@ -14028,7 +14378,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -14042,7 +14392,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -14057,18 +14407,28 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts - + No Box selected. - + @@ -14103,7 +14463,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -14157,7 +14527,7 @@ Do you want to save message ? - + Expand @@ -14167,7 +14537,7 @@ Do you want to save message ? - + from @@ -14202,7 +14572,7 @@ Do you want to save message ? - + Hide @@ -14343,7 +14713,7 @@ Do you want to save message ? - + Remove unused keys... @@ -14353,7 +14723,7 @@ Do you want to save message ? - + Clean keyring @@ -14367,7 +14737,13 @@ Notes: Your old keyring will be backed up. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info @@ -14400,18 +14776,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. - - - Export/create a new node - - Trusted keys only - + Search name @@ -14421,12 +14792,12 @@ For security, your keyring was previously backed-up to file - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -14459,7 +14830,7 @@ Reported error: NewFriendList - + Offline Friends @@ -14480,7 +14851,7 @@ Reported error: - + Groups @@ -14510,19 +14881,19 @@ Reported error: - - + + Search - + ID - + Search ID @@ -14532,12 +14903,12 @@ Reported error: - + Show Items - + Last contact @@ -14547,7 +14918,7 @@ Reported error: - + Group @@ -14662,7 +15033,7 @@ Reported error: - + Do you want to remove this node? @@ -14672,7 +15043,7 @@ Reported error: - + Done! @@ -14779,7 +15150,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -14794,7 +15165,7 @@ at least one peer was not added to a group - + Newest on top @@ -14804,12 +15175,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15047,7 +15418,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -15067,12 +15438,12 @@ at least one peer was not added to a group - + Please enter your Retroshare passphrase - + Unregistered plugin/executable @@ -15087,7 +15458,7 @@ at least one peer was not added to a group - + Test @@ -15098,17 +15469,19 @@ at least one peer was not added to a group + Unknown title - + + Encrypted message - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -15116,7 +15489,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online @@ -15255,7 +15628,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -15300,12 +15678,7 @@ p, li { white-space: pre-wrap; } - - Options - Opções - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -15351,21 +15724,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare - - + + Error : cannot get peer details. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) @@ -15383,7 +15756,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -15459,12 +15832,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -15490,7 +15863,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat @@ -15511,7 +15884,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Name: Nome: @@ -15551,7 +15924,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message @@ -15609,7 +15982,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Send Message @@ -15927,17 +16300,17 @@ p, li { white-space: pre-wrap; } - + My Albums - + Subscribed Albums - + Shared Albums @@ -15966,7 +16339,7 @@ requesting to edit it! PhotoSlideShow - + Album Name @@ -16025,19 +16398,19 @@ requesting to edit it! - - + + TextLabel - + Posted by - + ago @@ -16073,12 +16446,12 @@ requesting to edit it! PluginItem - + TextLabel - + Show more details about this plugin @@ -16289,12 +16662,27 @@ p, li { white-space: pre-wrap; } - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -16347,7 +16735,7 @@ p, li { white-space: pre-wrap; } - + Vote up @@ -16367,8 +16755,8 @@ p, li { white-space: pre-wrap; } - - + + Comments @@ -16393,13 +16781,13 @@ p, li { white-space: pre-wrap; } - - + + Comment - + Comments @@ -16427,12 +16815,12 @@ p, li { white-space: pre-wrap; } PostedCreatePostDialog - + Create a new Post - + RetroShare @@ -16447,12 +16835,22 @@ p, li { white-space: pre-wrap; } - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File - + Post image @@ -16468,7 +16866,17 @@ p, li { white-space: pre-wrap; } - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -16478,7 +16886,7 @@ p, li { white-space: pre-wrap; } - + Please add a Title @@ -16498,12 +16906,22 @@ p, li { white-space: pre-wrap; } - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -16518,7 +16936,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -16529,7 +16947,7 @@ p, li { white-space: pre-wrap; } - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -16539,7 +16957,7 @@ p, li { white-space: pre-wrap; } - + Link @@ -16547,12 +16965,12 @@ p, li { white-space: pre-wrap; } PostedDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -16586,7 +17004,7 @@ p, li { white-space: pre-wrap; } PostedGroupDialog - + Create New Board @@ -16624,7 +17042,17 @@ p, li { white-space: pre-wrap; } PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted @@ -16640,7 +17068,7 @@ p, li { white-space: pre-wrap; } - + Expand @@ -16655,12 +17083,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + + Never + + + + New Board @@ -16673,18 +17106,18 @@ p, li { white-space: pre-wrap; } PostedItem - + 0 - - + + Comments - + Copy RetroShare Link @@ -16695,12 +17128,12 @@ p, li { white-space: pre-wrap; } - + Comment - + Comments @@ -16710,7 +17143,7 @@ p, li { white-space: pre-wrap; } - + Click to view Picture @@ -16720,17 +17153,17 @@ p, li { white-space: pre-wrap; } - + Vote up - + Vote down - + Set as read and remove item @@ -16740,7 +17173,7 @@ p, li { white-space: pre-wrap; } - + New Comment: @@ -16750,7 +17183,7 @@ p, li { white-space: pre-wrap; } - + Name @@ -16791,7 +17224,7 @@ p, li { white-space: pre-wrap; } - + Loading @@ -16814,7 +17247,17 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 @@ -16824,15 +17267,15 @@ p, li { white-space: pre-wrap; } - + - + unknown - + Distribution: @@ -16842,42 +17285,42 @@ p, li { white-space: pre-wrap; } - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -16897,7 +17340,7 @@ p, li { white-space: pre-wrap; } - + Search @@ -16927,17 +17370,17 @@ p, li { white-space: pre-wrap; } - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -16952,12 +17395,17 @@ p, li { white-space: pre-wrap; } - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -16967,27 +17415,31 @@ p, li { white-space: pre-wrap; } - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -17002,7 +17454,7 @@ p, li { white-space: pre-wrap; } - + Never @@ -17076,6 +17528,16 @@ p, li { white-space: pre-wrap; } No Channel Selected + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -17165,16 +17627,16 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -17282,7 +17744,7 @@ and use the import button to load it ProfileWidget - + Edit status message @@ -17298,7 +17760,7 @@ and use the import button to load it - + Public Information @@ -17333,12 +17795,12 @@ and use the import button to load it - + Other Information - + My Address @@ -17382,27 +17844,27 @@ and use the import button to load it PulseAddDialog - + Add to Pulse - + Display As - + URL - + GroupLabel - + IDLabel @@ -17412,12 +17874,12 @@ and use the import button to load it De: - + Head - + Head Shot @@ -17447,13 +17909,13 @@ and use the import button to load it - - + + Whats happening? - + @@ -17465,12 +17927,22 @@ and use the import button to load it - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -17485,7 +17957,7 @@ and use the import button to load it - + Reply to Pulse @@ -17500,20 +17972,25 @@ and use the import button to load it - + Like Pulse - + Hide Pictures - + Add Pictures + + + Load Picture File + + PulseMessage @@ -17523,7 +18000,7 @@ and use the import button to load it - + @@ -17542,7 +18019,7 @@ and use the import button to load it PulseReply - + icn @@ -17552,7 +18029,7 @@ and use the import button to load it - + REPLY @@ -17579,7 +18056,7 @@ and use the import button to load it - + FOLLOW @@ -17589,7 +18066,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -17609,7 +18086,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -17725,7 +18202,7 @@ and use the import button to load it - + FOLLOW @@ -17733,37 +18210,42 @@ and use the import button to load it PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -17795,7 +18277,7 @@ and use the import button to load it - + FOLLOW @@ -17803,8 +18285,8 @@ and use the import button to load it QObject - - + + Confirmation @@ -18072,12 +18554,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + File Request canceled - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. @@ -18108,7 +18590,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + Cannot start Tor Manager! @@ -18142,7 +18624,7 @@ The error reported is:" - + Multiple instances @@ -18161,6 +18643,26 @@ The error reported is:" + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -18240,7 +18742,7 @@ Reported error is: - + You appear to have nodes associated to DSA keys: @@ -18250,7 +18752,7 @@ Reported error is: - + enabled @@ -18260,7 +18762,7 @@ Reported error is: - + Move IP %1 to whitelist @@ -18276,7 +18778,7 @@ Reported error is: - + %1 seconds ago @@ -18343,7 +18845,7 @@ Security: no anonymous IDs - + Join chat room @@ -18371,7 +18873,7 @@ Security: no anonymous IDs - + Indefinitely @@ -18552,12 +19054,28 @@ Security: no anonymous IDs - - Status + + Name + Node + + + + + Address + + + + + + Status + + + + NXS @@ -18800,6 +19318,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -18939,7 +19469,7 @@ p, li { white-space: pre-wrap; } - + Network Wide @@ -19106,7 +19636,7 @@ p, li { white-space: pre-wrap; } - + The loading of embedded images is blocked. @@ -19119,7 +19649,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default @@ -19292,12 +19822,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -19305,12 +19845,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -19998,7 +20538,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name @@ -20119,7 +20659,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name @@ -20139,7 +20679,7 @@ If you believe it is correct, remove the corresponding line from the file and re - + Profile ID @@ -20195,7 +20735,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -20209,11 +20749,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - - RsMessageModel @@ -20227,6 +20762,11 @@ prevents the message to be forwarded to your friends. From + + + To + + Subject @@ -20249,12 +20789,17 @@ prevents the message to be forwarded to your friends. - Click to sort by read + Click to sort by read status - Click to sort by from + Click to sort by author + + + + + Click to sort by destination @@ -20278,7 +20823,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -20299,7 +20846,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. @@ -20360,7 +20907,7 @@ prevents the message to be forwarded to your friends. - + Unable to open log file '%1': %2 @@ -20381,7 +20928,7 @@ prevents the message to be forwarded to your friends. - + opmode @@ -20411,7 +20958,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -20429,7 +20976,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -20446,12 +20993,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) - + Start Search @@ -20512,7 +21059,7 @@ prevents the message to be forwarded to your friends. - + KeyWords @@ -20527,7 +21074,7 @@ prevents the message to be forwarded to your friends. - + Filename @@ -20627,23 +21174,23 @@ prevents the message to be forwarded to your friends. - + File Name - + Download - + Copy RetroShare Link - + Send RetroShare Link @@ -20653,7 +21200,7 @@ prevents the message to be forwarded to your friends. - + Download Notice @@ -20690,7 +21237,7 @@ prevents the message to be forwarded to your friends. - + Folder @@ -20701,17 +21248,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) - + Open Folder - + Create Collection... @@ -20731,7 +21278,7 @@ prevents the message to be forwarded to your friends. - + Collection @@ -20739,7 +21286,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details @@ -20755,22 +21302,22 @@ prevents the message to be forwarded to your friends. - + IP address: - + Peer ID: - + Location: - + Peer Name: @@ -20787,7 +21334,7 @@ prevents the message to be forwarded to your friends. - + but reported: @@ -20812,8 +21359,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -20821,7 +21368,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare @@ -20852,7 +21399,7 @@ prevents the message to be forwarded to your friends. - + Expand @@ -20897,12 +21444,12 @@ prevents the message to be forwarded to your friends. - + Write Message - + Connect Attempt @@ -20922,17 +21469,12 @@ prevents the message to be forwarded to your friends. - + Unknown Security Issue - - A unknown peer - - - - + Unknown @@ -20942,7 +21484,17 @@ prevents the message to be forwarded to your friends. - + + SSL request + + + + + An unknown peer + + + + Hide @@ -20952,7 +21504,7 @@ prevents the message to be forwarded to your friends. - + Certificate has wrong signature!! This peer is not who he claims to be. @@ -20962,12 +21514,12 @@ prevents the message to be forwarded to your friends. - + Certificate caused an internal error. - + Peer/node not in friendlist (PGP id= @@ -21026,12 +21578,12 @@ prevents the message to be forwarded to your friends. - + Local Address - + NAT @@ -21052,22 +21604,22 @@ prevents the message to be forwarded to your friends. - + Local network - + External ip address finder - + UPnP - + Known / Previous IPs: @@ -21080,21 +21632,16 @@ behind a firewall or a VPN. - - Allow RetroShare to ask my ip to these websites: - - - - - - + + + kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -21104,23 +21651,46 @@ behind a firewall or a VPN. - + Onion Address - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -21130,7 +21700,7 @@ behind a firewall or a VPN. - + I2P Address @@ -21155,37 +21725,95 @@ behind a firewall or a VPN. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -21200,71 +21828,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -21274,22 +21838,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -21301,12 +21850,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -21316,7 +21865,7 @@ Also check your ports! - + Download limit (KB/s) @@ -21331,23 +21880,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -21358,17 +21907,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -21378,12 +21917,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -21393,17 +21927,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -21443,7 +21967,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start @@ -21458,12 +21982,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - BOB status - - - - + Incoming @@ -21499,7 +22018,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -21554,7 +22098,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Warning: This bandwidth adds up to the max bandwidth. @@ -21579,7 +22123,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -21591,7 +22135,7 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Filters @@ -21614,7 +22158,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status @@ -21674,17 +22218,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -21700,18 +22255,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -21746,12 +22301,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -21774,22 +22329,22 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -21824,7 +22379,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -21834,12 +22389,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -21919,7 +22474,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with @@ -21929,12 +22484,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Share - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -21953,7 +22508,7 @@ Select the Friends with which you want to Share your Channel. - + Shared directory @@ -21973,17 +22528,17 @@ Select the Friends with which you want to Share your Channel. - + Add new - + Cancel - + Add a Share Directory @@ -21993,7 +22548,7 @@ Select the Friends with which you want to Share your Channel. - + Apply and close @@ -22084,7 +22639,7 @@ Select the Friends with which you want to Share your Channel. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. @@ -22092,7 +22647,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files @@ -22143,11 +22698,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files - + Download selected @@ -22157,7 +22717,7 @@ Select the Friends with which you want to Share your Channel. - + Copy retroshare Links to Clipboard @@ -22172,7 +22732,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted @@ -22188,7 +22748,7 @@ Select the Friends with which you want to Share your Channel. - + Create Collection... @@ -22213,7 +22773,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted because they have not been indexed yet. @@ -22356,12 +22916,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration - + Create interface @@ -22385,7 +22945,7 @@ Select the Friends with which you want to Share your Channel. - + Log In @@ -22724,7 +23284,7 @@ This choice can be reverted in settings. - + Message: @@ -22961,7 +23521,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags @@ -22997,12 +23557,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown @@ -23012,18 +23575,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -23033,12 +23591,57 @@ p, li { white-space: pre-wrap; } - + + Error + + + + + Not connected + + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -23046,7 +23649,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -23056,7 +23659,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -23067,11 +23670,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -23099,7 +23703,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options @@ -23110,7 +23714,7 @@ p, li { white-space: pre-wrap; } - + Shared Directories @@ -23120,22 +23724,27 @@ p, li { white-space: pre-wrap; } - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -23220,7 +23829,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -23229,7 +23838,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -23254,7 +23868,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming @@ -23319,12 +23938,7 @@ p, li { white-space: pre-wrap; } - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -23334,7 +23948,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -23362,7 +23986,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed @@ -23390,19 +24014,19 @@ p, li { white-space: pre-wrap; } TransfersDialog - - + + Downloads - + Uploads - + Name i.e: file name @@ -23609,7 +24233,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... @@ -23634,7 +24263,7 @@ p, li { white-space: pre-wrap; } - + Anonymous end-to-end encrypted tunnel 0x @@ -23655,7 +24284,7 @@ p, li { white-space: pre-wrap; } - + @@ -23688,7 +24317,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name @@ -23703,7 +24342,7 @@ p, li { white-space: pre-wrap; } - + Expand all @@ -23830,23 +24469,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns - + File Transfers - + Path Caminho @@ -23856,7 +24490,7 @@ p, li { white-space: pre-wrap; } - + Could not delete preview file @@ -23866,7 +24500,7 @@ p, li { white-space: pre-wrap; } - + Create Collection... @@ -23881,7 +24515,7 @@ p, li { white-space: pre-wrap; } - + Collection @@ -23891,7 +24525,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x @@ -24305,12 +24939,17 @@ p, li { white-space: pre-wrap; } - + Enable Retroshare WEB Interface - + + Status: + + + + Web parameters @@ -24350,17 +24989,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -24370,12 +25019,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface @@ -24512,7 +25161,7 @@ p, li { white-space: pre-wrap; } - + Page Name @@ -24527,7 +25176,7 @@ p, li { white-space: pre-wrap; } - + << @@ -24615,7 +25264,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History @@ -24650,7 +25299,7 @@ p, li { white-space: pre-wrap; } - + \/ @@ -24680,14 +25329,18 @@ p, li { white-space: pre-wrap; } - - + + History + + + + Show Edit History - + Status @@ -24708,7 +25361,7 @@ p, li { white-space: pre-wrap; } - + Submit @@ -24791,12 +25444,7 @@ p, li { white-space: pre-wrap; } - - Refresh - - - - + Settings @@ -24811,7 +25459,7 @@ p, li { white-space: pre-wrap; } - + Who to Follow @@ -24831,7 +25479,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -24861,7 +25509,7 @@ p, li { white-space: pre-wrap; } - + Yourself @@ -24871,7 +25519,7 @@ p, li { white-space: pre-wrap; } - + RetroShare @@ -24934,35 +25582,42 @@ p, li { white-space: pre-wrap; } - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + + + + Location: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -25007,11 +25662,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + + + + + Following + + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) @@ -25089,7 +25774,7 @@ p, li { white-space: pre-wrap; } - + k e.g: 3.1 k @@ -25126,7 +25811,7 @@ p, li { white-space: pre-wrap; } pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_ru.qm b/retroshare-gui/src/lang/retroshare_ru.qm index c60f6f497..cfa22ad5c 100644 Binary files a/retroshare-gui/src/lang/retroshare_ru.qm and b/retroshare-gui/src/lang/retroshare_ru.qm differ diff --git a/retroshare-gui/src/lang/retroshare_ru.ts b/retroshare-gui/src/lang/retroshare_ru.ts index cfe0de745..20b2f9e16 100644 --- a/retroshare-gui/src/lang/retroshare_ru.ts +++ b/retroshare-gui/src/lang/retroshare_ru.ts @@ -84,13 +84,6 @@ Только скрытый узел сети - - AddCommentDialog - - Add Comment - Добавить комментарий - - AddFileAssociationDialog @@ -129,12 +122,12 @@ RetroShare: расширенный поиск - + Search Criteria Критерии поиска - + Add a further search criterion. Добавить дополнительный критерий поиска. @@ -144,7 +137,7 @@ Сбросить критерии поиска. - + Cancels the search. Отменяет поиск. @@ -164,177 +157,6 @@ Поиск - - AlbumCreateDialog - - Create Album - Создать альбом - - - Album Name: - Название альбома - - - Category: - Категория: - - - Animals - Дикие животные - - - Family - Семья - - - Friends - Узлы сети - - - Flowers - Цветы - - - Holiday - Праздник - - - Landscapes - Пейзажи - - - Pets - Домашние животные - - - Portraits - Портреты - - - Travel - Путешествия - - - Work - Работа - - - Random - Случайно - - - Caption: - Заголовок: - - - Where: - Где: - - - Photographer: - Фотограф: - - - Description: - Описание: - - - Share Options - Настройки общего доступа - - - Policy: - Политика: - - - Quality: - Качество: - - - Comments: - Комментарии: - - - Identity: - Личность: - - - Public - Публичный - - - Restricted - Ограниченный - - - Resize Images (< 1Mb) - Изменение размера изображений (< 1 МБ) - - - Resize Images (< 10Mb) - Изменение размера изображений (< 10 МБ) - - - Send Original Images - Отправить исходные изображения - - - No Comments Allowed - Комментарии запрещены - - - Authenticated Comments - Авторизованные комментарии - - - Any Comments Allowed - Любые комментарии разрешены - - - Publish with Identity - Опубликовать под псевдонимом - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Перетащите картинку для вставки. Нажмите на картинку для редактирования подробностей.</span></p></body></html> - - - Back - Назад - - - Add Photos - Добавить фото - - - Publish Album - Опубликовать альбом - - - Untitle Album - Удалить название альбома - - - Say something about this album... - Сделать отклик об альбоме... - - - Where were these taken? - Источник контента - - - Load Album Thumbnail - Загрузить миниатюру альбома - - AlbumDialog @@ -343,19 +165,11 @@ p, li { white-space: pre-wrap; } Album Альбом - - Album Thumbnail - Миниатюра альбома - TextLabel Текстовая метка - - Summary - Резюме - Album Title: @@ -371,34 +185,6 @@ p, li { white-space: pre-wrap; } Caption Надпись - - Where: - Где: - - - When - Когда - - - Description: - Описание: - - - Share Options - Настройки общего доступа - - - Comments - Комментарии - - - Publish Identity - Опубликовать личность - - - Visibility - Видимость - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -767,7 +553,7 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. Предупреждение: это экспериментальные сервисы. Пожалуйста, помогите нам протестировать их. @@ -783,14 +569,6 @@ p, li { white-space: pre-wrap; } Circles Круги - - GxsForums - Форумы Gxs - - - GxsChannels - Каналы Gxs - The Wire @@ -802,10 +580,23 @@ p, li { white-space: pre-wrap; } Фотографии + + AspectRatioPixmapLabel + + + Save image + Сохранить изображение + + + + Copy image + + + AttachFileItem - + %p Kb %p кБ @@ -842,17 +633,13 @@ p, li { white-space: pre-wrap; } Browse... - - Add Avatar - Добавить аватар - Remove Удалить эту позицию - + Set your Avatar picture Установить ваш аватар @@ -871,10 +658,6 @@ p, li { white-space: pre-wrap; } Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - Загрузить аватар - AvatarWidget @@ -943,22 +726,10 @@ p, li { white-space: pre-wrap; } Сброс - Receive Rate - Скорость приёма - - - Send Rate - Скорость отдачи - - - + Always on Top Поверх всех окон - - Style - Стиль - Changes the transparency of the Bandwidth Graph @@ -974,23 +745,11 @@ p, li { white-space: pre-wrap; } % Opaque % непрозрачности - - Save - Сохранить - - - Cancel - Отмена - Since: С: - - Hide Settings - Скрыть настройки - BandwidthStatsWidget @@ -1063,7 +822,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment Комментарий @@ -1093,12 +852,12 @@ p, li { white-space: pre-wrap; } Скопировать ссылку RetroShare - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> <p><font color="#ff0000"><b>Автор этого сообщения (личность %1) заблокирован.</b> - + ago @@ -1106,7 +865,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up Голосовать "за" @@ -1126,7 +885,7 @@ p, li { white-space: pre-wrap; } \/ - + Posted by @@ -1164,7 +923,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up Голосовать "за" @@ -1184,7 +943,7 @@ p, li { white-space: pre-wrap; } \/ - + Click to view picture @@ -1214,7 +973,7 @@ p, li { white-space: pre-wrap; } Предоставить общий доступ - + Toggle Message Read Status Изменить статус прочитанного сообщения @@ -1224,7 +983,7 @@ p, li { white-space: pre-wrap; } Новый - + TextLabel Текстовая метка @@ -1232,12 +991,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this Мне нравится - + 0 0 @@ -1257,18 +1016,18 @@ p, li { white-space: pre-wrap; } Аватар - + New Comment - + Copy RetroShare Link Скопировать ссылку RetroShare - + Expand @@ -1283,12 +1042,12 @@ p, li { white-space: pre-wrap; } Удалить объект - + Name Имя - + Comm value @@ -1457,17 +1216,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels Каналы - + Tabs Вкладки - + General Общее @@ -1477,11 +1236,17 @@ p, li { white-space: pre-wrap; } - Load posts in background (Thread) - Загрузить сообщения в фоне (потоком) + + Downloads + Обмен файлами - + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab Открывать каждый канал в новой вкладке @@ -1489,7 +1254,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1512,7 +1277,7 @@ into the image, so as to ChannelsCommentsItem - + I like this Мне нравится @@ -1537,18 +1302,18 @@ into the image, so as to Аватар - + New Comment - + Copy RetroShare Link Скопировать ссылку RetroShare - + Expand @@ -1563,7 +1328,7 @@ into the image, so as to Удалить объект - + Name Имя @@ -1573,17 +1338,7 @@ into the image, so as to - - Comment - Комментарий - - - - Comments - Комментарии - - - + Hide @@ -1591,7 +1346,7 @@ into the image, so as to ChatLobbyDialog - + Name Имя @@ -1772,18 +1527,18 @@ into the image, so as to Redock to Main window - + Перезакрепить в главном окне Undock to a new window - + Открепить в новом окне ChatLobbyToaster - + Show Chat Lobby Показать чат-комнату @@ -1795,22 +1550,6 @@ into the image, so as to Chats Чаты - - You have %1 new messages - У вас %1 новых сообщений - - - You have %1 new message - У вас %1 новых сообщений - - - %1 new messages - %1 новых сообщений - - - %1 new message - %1 новое сообщение - You have %1 mentions @@ -1832,13 +1571,14 @@ into the image, so as to - + + Unknown Lobby Неизвестная чат-комната - - + + Remove All Удалить всё @@ -1846,13 +1586,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Имя - + Count Всего @@ -1862,33 +1602,7 @@ into the image, so as to Тема - - Private Subscribed chat rooms - Подписанные приватные чат-комнаты - - - - - Public Subscribed chat rooms - Подписанные публичные чат-комнаты - - - - Private chat rooms - Приватные чат-комнаты - - - - - Public chat rooms - Публичные чат-комнаты - - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/images/add_24x24.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - <h1><img width="%1" src=":/icons/help_64.png">Чат-комнаты</h1> <p>Чат-комнаты это распределенная система чатов для общения, которые функционируют по довольно схожим с IRC принципам. Чаты позволяют анонимно общаться с множеством людей без необходимости добавлять их в список своих контактов.</p> <p>Чат-комнаты могут быть публичным (участники из списка ваших контактов видят их) или приватным (участники из списка ваших контактов не видят их до тех пор, пока они не получат ваше приглашение присоединиться к чату. < img src=":/images/add_24x24.png «width=%2/ >). В случае, когда в приватную чат-комнату были приглашены вы, она становится вам видима. Но это только в том случае, когда один или несколько ваших доверенных узлов используют её. </p> <p>Список слева показывает чат-комнаты, в которых находится один или несколько участников из вашего окружения. Вы можете <ul><li>щёлкнуть правой кнопкой мыши для создания новой чат-комнаты</li>, <li>дважды щёлкнуть по существующей чат-комнате, чтобы войти в неё, общаться и показать её своим друзьям.</li></ul> Примечание: Для правильной работы чат-комнат, время вашего компьютера должно быть установлено точно. Поэтому проверьте ваши системные часы! </p> - - - + Create chat room Создать чат-комнату @@ -1898,7 +1612,7 @@ into the image, so as to Покинуть эту чат-комнату - + Create a non anonymous identity and enter this room Создать неанонимную личность и войти в чат-комнату @@ -1957,12 +1671,12 @@ Double click a chat room to enter and chat. Двойной щелчок мыши для входа в комнату и общения. - + %1 invites you to chat room named %2 %1 приглашает вас в чат-комнату %2 - + Choose a non anonymous identity for this chat room: Выберите неанонимную личность для этой чат-комнаты: @@ -1972,31 +1686,31 @@ Double click a chat room to enter and chat. Выберите личность, от имени которой вы будете общаться чат-комнате: - Create chat lobby - Создать чат-комнату - - - + [No topic provided] [тема не указана] - Selected lobby info - Информация о выбранной чат-комнате - - - + + Private приватная - + + + Public публичная - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted Допустимы анонимные участники @@ -2006,42 +1720,25 @@ Double click a chat room to enter and chat. Удалить автоподписку - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe Установить автоподписку - + Search Chat lobbies Поиск чатов - + Search Name Поиск по имени - Subscribed - Подписка - - - + Columns Столбцы - - Yes - Да - - - No - Нет - Chat rooms @@ -2053,47 +1750,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: Название чат-комнаты: - + Chat room Id: Идентификатор чат-комнаты: - + Topic: Тема: - + Type: Тип: - + Security: Безопасность: - + Peers: Участников: - - - - - - + + + + + + TextLabel Текстовая метка @@ -2108,13 +1805,24 @@ Double click a chat room to enter and chat. Анонимные участники не допускаются - + Show Показать - + + Private Subscribed + + + + + + Public Subscribed + + + + column столбец @@ -2128,7 +1836,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item Удалить объект @@ -2173,46 +1881,22 @@ Double click a chat room to enter and chat. ChatPage - + General Главное - - Distant Chat - Удалённый чат - Everyone Все - - Contacts - Контакты - Nobody Никто - Accept encrypted distant chat from - Разрешить удалённый шифрованный чат от - - - Chat Settings - Настройки чата - - - Enable Emoticons Private Chat - Разрешить смайлики в приватном чате - - - Enable Emoticons Group Chat - Разрешить смайлики в групповом чате - - - + Enable custom fonts Разрешить пользовательские шрифты @@ -2221,10 +1905,6 @@ Double click a chat room to enter and chat. Enable custom font size Разрешить нестандартный размер шрифта - - Minimum font size - Минимальный размер шрифта - Enable bold @@ -2236,7 +1916,7 @@ Double click a chat room to enter and chat. Курсив - + General settings @@ -2261,11 +1941,7 @@ Double click a chat room to enter and chat. Загружать внедрённые изображения - Chat Lobby - Чат-комната - - - + Blink tab icon Мерцание иконки вкладки @@ -2274,10 +1950,6 @@ Double click a chat room to enter and chat. Do not send typing notifications Не отсылать уведомления о наборе текста - - Private Chat - Приватный чат - Open Window for new chat @@ -2299,11 +1971,7 @@ Double click a chat room to enter and chat. Мерцание иконки окна/вкладки - Chat Font - Шрифт чата - - - + Change Chat Font Изменить шрифт чата @@ -2313,14 +1981,10 @@ Double click a chat room to enter and chat. Шрифт чата: - + History История - - Style - Стиль - @@ -2335,17 +1999,13 @@ Double click a chat room to enter and chat. Variant: Вариант: - - Group chat - Групповой чат - Private chat Приватный чат - + Choose your default font for Chat. Выберите свой шрифт по умолчанию для чата. @@ -2409,22 +2069,28 @@ Double click a chat room to enter and chat. <html><head/><body><p align="justify">In this tab you can setup how many chat messages Retroshare will keep saved on the disc and how much of the previous conversation it will display, for the different chat systems. The max storage period allows to discard old messages and prevents the chat history from filling up with volatile chat (e.g. chat lobbies and distant chat).</p></body></html> <html><head/><body><p align="justify">В этой вкладке вы можете задать, какое количество сообщений чата RetroShare будет хранить на диске, а также объём отображения состоявшихся бесед для различных систем чатов. Максимальный период хранения позволяет очищать историю чатов и предотвращает её заполнение временными чатами (например, обычные чаты или удалённые чаты).</p></body></html> - - Chatlobbies - Комнаты чата - Enabled: Включено: - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2434,7 +2100,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms Чат-комнаты @@ -2531,11 +2207,7 @@ Double click a chat room to enter and chat. Максимальный срок хранения, в днях (0 - бесконечно): - Search by default - Параметры поиска по умолчанию - - - + Case sensitive Учитывать регистр @@ -2574,10 +2246,6 @@ Double click a chat room to enter and chat. Threshold for automatic search Порог автоматического поиска - - Default identity for chat lobbies: - Личность по умолчанию для чат-комнат: - Show Bar by default @@ -2645,7 +2313,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat Показать чат @@ -2681,7 +2349,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close Закрыть @@ -2716,12 +2384,12 @@ Double click a chat room to enter and chat. Курсив - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon Вставить смайлик @@ -2730,10 +2398,6 @@ Double click a chat room to enter and chat. Attach a Picture Прикрепить картинку - - <html><head/><body><p>QToolButton:disabled {</p><p> image: url(:/icons/png/send-message-blocked.png) ;</p><p>}</p><p><br/></p></body></html> - <html><head/><body><p>QToolButton: деактивирована {</p><p> image: url(:/icons/png/send-message-blocked.png) ;</p><p>}</p><p><br/></p></body></html> - Strike @@ -2805,11 +2469,6 @@ Double click a chat room to enter and chat. Insert horizontal rule Вставить горизонтальную черту - - - Save image - Сохранить изображение - Import sticker @@ -2847,7 +2506,7 @@ Double click a chat room to enter and chat. - + is typing... печатает... @@ -2871,7 +2530,7 @@ after HTML conversion. Выберите шрифт. - + Do you really want to physically delete the history? Вы действительно хотите удалить с диска историю сообщений? @@ -2921,7 +2580,7 @@ after HTML conversion. сейчас занят и не может вам ответить - + Find Case Sensitively Найти с учётом регистра @@ -2943,7 +2602,7 @@ after HTML conversion. Продолжить выделять цветом после X найденных вхождений (требуется больше ресурсов процессора) - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> <b>Найти предыдущее </b><br/><i>Ctrl+Shift+G</i> @@ -2958,16 +2617,12 @@ after HTML conversion. <b>Найти</b><br/><i>Ctrl+F</i> - + (Status) (Состояние) - Set text font & color - Указать тип шрифта и цвет текста - - - + Attach a File Прикрепить файл @@ -2983,12 +2638,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> <b>Отметить этот выделенный текст</b><br><i>Ctrl + M</i> - + Person id: Идентификатор личности: @@ -2999,12 +2654,12 @@ Double click on it to add his name on text writer. Двойной щелчок, чтобы добавить имя в текстовый редактор. - + Unsigned Не подписано - + items found. удовлетворяют условию. @@ -3024,7 +2679,7 @@ Double click on it to add his name on text writer. Печатайте ваши сообщения здесь - + Don't stop to color after Продолжить выделять цветом после @@ -3050,7 +2705,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: Подробности: @@ -3072,7 +2727,7 @@ Double click on it to add his name on text writer. - + Personal Circles Личные круги @@ -3098,7 +2753,7 @@ Double click on it to add his name on text writer. - + Friends Узлы сети @@ -3158,7 +2813,7 @@ Double click on it to add his name on text writer. Ближнее окружение - + External Circles (Admin) Внешние круги (администратор) @@ -3174,7 +2829,7 @@ Double click on it to add his name on text writer. - + Circles Круги @@ -3226,43 +2881,48 @@ Double click on it to add his name on text writer. - + RetroShare RetroShare - + - + Error : cannot get peer details. Ошибка: не могу получить совокупность деталей. - + Retroshare ID - + <p>This Retroshare ID contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: + + + <b>DNS:</b> : + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3274,7 +2934,7 @@ Double click on it to add his name on text writer. Шифрование - + Not connected не соединён @@ -3356,25 +3016,17 @@ Double click on it to add his name on text writer. нет - + <p>This certificate contains: <p>Этот сертификат содержит: - + <li>a <b>node ID</b> and <b>name</b> <li><b>идентификатор узла</b> и <b>имя</b> - an <b>onion address</b> and <b>port</b> - <b>onion-адрес</b> и <b>порт</b> - - - an <b>IP address</b> and <b>port</b> - <b>IP-адрес</b> и <b>порт</b> - - - + <p>You can use this certificate to make new friends. Send it by email, or give it hand to hand.</p> <p>Вы можете использовать этот сертификат, чтобы пополнить список ваших контактов. Отправьте его потенциальному участнику по электронной почте или передайте лично в руки.</p> @@ -3389,7 +3041,7 @@ Double click on it to add his name on text writer. <html><head/> <body><p>Это метод шифрования, используемый <span style="font-weight:600;"> OpenSSL</span>. Подключение к доверенному узлу</p> <p>всегда шифруется стойким алгоритмом и если DHE присутствует, дальнейшее соединение использует метод</p> <p>«совершенной секретности с упреждением».</p></body></html> - + with с @@ -3406,118 +3058,16 @@ Double click on it to add his name on text writer. Connect Friend Wizard Помощник подключения к удалённому узлу - - Add a new Friend - Добавить новый узел - - - &You get a certificate file from your friend - &Вы получаете сертификат доверенного узла - - - &Make friend with selected friends of my friends - &Добавить в личное окружение контакты моих доверенных узлов - - - &Send an Invitation by Email - (Your friend will receive an email with instructions how to download RetroShare) - &Отправить приглашение по электронной почте -(ваш контакт получит письмо с инструкциями, откуда скачать RetroShare) - - - Include signatures - Вставить подписи - - - Copy your Cert to Clipboard - Скопировать ваш сертификат в буфер обмена - - - Save your Cert into a File - Сохранить ваш сертификат в файл - - - Run Email program - Запустить почтовый клиент - Open Cert of your friend from File Открыть сертификат вашего контакта из файла - - Open certificate - Открыть сертификат - - - Please, paste your friend's Retroshare certificate into the box below - Пожалуйста, вставьте сертификат другого участника сети в поле внизу - - - Certificate files - Файлы сертификатов - - - Use PGP certificates saved in files. - Использовать PGP-сертификаты, сохранённые в файлах. - - - Import friend's certificate... - Импортировать сертификат доверенного узла - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - Вам следует создать файл с вашим сертификатом и передать его потенциальному участнику сети. Также вы можете использовать файл созданный заранее. - - - Export my certificate... - Экспортировать мой сертификат - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - Перетащите файл с сертификатом другого участника сети в это окно или укажите путь к нему в поле ниже - - - Browse - Обзор - - - Friends of friends - Ближнее окружение - - - Select now who you want to make friends with. - Выберите с кем вы хотите обменяться сертификатами. - - - Show me: - Показать мне: - - - Make friend with these peers - Обменяться сертификатами с этими участниками - RetroShare ID Идентификатор RetroShare - - Use RetroShare ID for adding a Friend which is available in your network. - Использовать идентификатор RetroShare для обмена сертификатами с существующим узлом сети. - - - Add Friends RetroShare ID... - Добавить RetroShare ID других участников... - - - Paste Friends RetroShare ID in the box below - Вставить RetroShare ID других участников в поле ниже - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - Введите RetroShare ID участника сети. Например, Peer@BDE8D16A46D938CF - RetroShare is better with Friends @@ -3559,27 +3109,7 @@ Double click on it to add his name on text writer. Электронная почта - Invite Friends by Email - Пригласить потенциального участника сети по электронной почте - - - Enter your friends' email addresses (separate each one with a semicolon) - Введите адреса электронных почт потенциальных участников сети (адреса разделять запятыми) - - - Your friends' email addresses: - Адреса электронной почты: - - - Enter Friends Email addresses - Введите адреса электронных почт потенциальных участников сети - - - Subject: - Тема: - - - + @@ -3595,77 +3125,32 @@ Double click on it to add his name on text writer. Подробности запроса - + Peer details Сведения об участнике - + Name: Имя: - - Email: - Эл. почта - - - Node: - Узел сети: - - - Please note that RetroShare will require excessive amounts of bandwidth, memory and CPU if you add too many friends. You can add as many friends as you like, but more than 40 will probably require too much -resources. - Обратите внимание на тот факт, что вы можете добавлять в ваше окружение столько контактов, сколько пожелаете. Но их количество более 40, вероятно, приведёт к заметной загрузке CPU, памяти и пропускной способности вашего интернет-канала. - Location: Расположение: - + Options Параметры - This wizard will help you to connect to your friend(s) to RetroShare network.<br>Select how you would like to add a friend: - Этот мастер поможет вам соединиться с другими участниками сети RetroShare (тёмной сети).<br>Для этого доступны следующие способы: - - - Enter the certificate manually - Ввести сертификат вручную - - - Enter RetroShare ID manually - Ввести личность RetroShare вручную - - - &Send an Invitation by Web Mail Providers - &Отправить приглашение через провайдеров веб-почты. - - - Recommend many friends to each other - Рекомендовать друг другу несколько контактов из окружения - - - RetroShare certificate - Сертификат RetroShare - - - Please paste below your friend's Retroshare certificate - Пожалуйста, вставьте сертификат другого участника сети в поле внизу - - - Paste certificate - Вставить сертификат - - - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> <html><head/><body><p>Сюда следует вводить сертификаты потенциальных контактов. ВНИМАНИЕ: сертификаты — это не просто пбличные PGP-ключи, это более сложная структура данных. Не вставляйте сюда PGP-ключи своих потенциальных контактов (ни полностью, ни частично) – это не сработает. Сертификат должен вводиться полностью!</p></body></html> - + Add friend to group: Добавить этот узел в группу: @@ -3675,7 +3160,7 @@ resources. Аутентификация доверенного узла (подписать его PGP-ключ) - + Please paste below your friend's Retroshare ID @@ -3700,16 +3185,22 @@ resources. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with Добавить сертификат участника для последующего соединения с ним - To accept the Friend Request, click the Finish button. - Чтобы принять запрос на предложение обменяться сертификатами, нажмите кнопку «Завершить». - - - + Sorry, some error appeared К сожалению, появились некоторые ошибки @@ -3729,32 +3220,27 @@ resources. Подробная информация об узле: - + Key validity: Уровень доверия к ключу: - + Profile ID: - - Signers - Подписавшие - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Подписание публичного ключа участника сети – это способ обозначить своё доверие тому или иному участнику. Сигнатуры, которые вы видите ниже, подтверждают, что ключи в списке заверены и признаются как подлинные.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. Этот участник уже находится в вашем доверенном окружении. Добавление сертификата снова лишь установит актуальный IP-адрес этого узла. - + To accept the Friend Request, click the Accept button. @@ -3800,49 +3286,17 @@ resources. - + Certificate Load Failed Ошибка загрузки сертификата - Cannot get peer details of PGP key %1 - Не удаётся получить подробности PGP-ключа участника %1 - - - Any peer I've not signed - Любой участник, ключ которого не подписан мною - - - Friends of my friends who already trust me - Участники из окружения, которые подписали мой сертификат - - - Signed peers showing as denied - Подписанные участники показывать как отвергнутые - - - Peer name - Имя участника - - - Also signed by - Также подписано - - - Peer id - Идентификатор участника - - - Certificate appears to be valid - Сертификат в порядке - - - + Not a valid Retroshare certificate! Недействительный сертификат RetroShare! - + RetroShare Invitation Приглашение в RetroShare @@ -3862,12 +3316,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? Это же ваш собственный сертификат! Вы не хотели бы соединиться с самим собой, не так ли? - + @@ -3875,7 +3329,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list Этот ключ уже находится в вашем доверенном списке @@ -3915,7 +3369,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.У вас имеется запрос на соединение от - + Profile password needed. @@ -3940,7 +3394,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3950,47 +3404,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - Certificate Load Failed:file %1 not found - Ошибка загрузки сертификата: %1 не найден - - - This Peer %1 is not available in your Network - Этот участник %1 не доступен в вашей сети - - - Use new certificate format (safer, more robust) - Использовать новый формат сертификата (безопаснее) - - - Use old (backward compatible) certificate format - Использовать старый формат сертификата (совместим со старыми версиями) - - - Remove signatures - Удаление подписи - - - RetroShare Invite - Приглашение в RetroShare - - - Connect Friend Help - Помощь по установлению соединения - - - You can copy this text and send it to your friend via email or some other way - Вы можете скопировать этот текст и отправить его контрагенту по электронной почте или любым другим способом - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Ваш сертификат скопирован в буфер обмена. Отправьте контрагенту письмо с этим сертификатом по электронной почте или же воспользуйтесь любым другим доступным способом. - - - Save as... - Сохранить как... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -4029,11 +3443,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.*** Никого *** - Use as direct source, when available - Использовать как прямой источник, при возможности - - - + IP-Addr: IP-адрес: @@ -4043,7 +3453,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.IP-адрес: - + Show Advanced options Показать дополнительные настройки @@ -4052,10 +3462,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Механизм подписания ключей может оказаться полезным другим участникам сети, которые, добавляя чужой сертификат в своё окружение, имеют возможность посмотреть, кто подписал ключ в сертификате. Следует отметить, что подписание чужих ключей не является обязательным и не может быть впоследствии отменено. Поэтому подходите к вопросу подписания, взвесив все «за» и «против».</span></p></body></html> - - <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> - <html><head/><body><p align="justify">RetroShare периодически проверяет папки ваших контактов, доступные вам к просмотру, на предмет наличия там интересующего вас файла. Если файл находится, в целях скачивания с контактом устанавливается прямое соединение – не через систему анонимных туннелей. В этом случае узел-источник из вашего окружения достоверно знает, что файл качаете именно вы – пользователь с конкретным сертификатом.</p><p align="justify">Чтобы исключить такого рода небезопасное поведение вашего клиент-сервера, снимите здесь галочку. Отметим, что прямое соединение всё равно установится, если вы напрямую выберете в открытой к просмотру папке файл для скачивания. Включение/отключение возможности прямого соединения при файлообмене применяется ко всем местоположениям одного узла.</p></body></html> - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> @@ -4066,45 +3472,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> <html><head/><body><p>Участники тёмной сети, для которых активирована эта опция, не смогут установить с вами соединение, если их IP-адрес не внесён в белый список. Подобный подход защищает вас от атаки типа «перенаправление трафика». Когда опция включена, блокируемые участники будут получать сообщения через "уведомления системы безопасности". Здесь вы имеете возможность занести определённые IP-адреса в белый/чёрный список. Применяется ко всем местоположениям, привязанным к конкретному сертификату.</p></body></html> - - Recommend many friends to each others - Рекомендовать друг друга множеству участников сети - - - Friend Recommendations - Рекомендации одних участников сети другим участникам - - - The text below is your Retroshare certificate. You have to provide it to your friend - Нижеследующий текст – это ваш сертификат RetroShare. Для установления соединения вам следует передать его действующему участнику тёмной сети. - - - Message: - Сообщение: - - - Recommend friends - Рекомендовать участников - - - To - Кому - - - Please select at least one friend for recommendation. - Выберите по меньшей мере одного участника для того, чтобы порекомендовать его - - - Please select at least one friend as recipient. - Выберите по меньшей мере одного участника на роль получателя рекомендации - Add key to keyring Добавить ключ в связку ключей - + This key is already in your keyring Это ключ уже в вашей связке @@ -4120,7 +3494,7 @@ even if you don't make friends. даже если вы не являетесь доверенными. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. Сертификат имеет неправильный номер версии. Помните, что сети v0.6 и v0.5 несовместимы. @@ -4155,7 +3529,7 @@ even if you don't make friends. Добавить IP в белый список - + No IP in this certificate! В этом сертификате отсутствует IP-адрес! @@ -4165,27 +3539,10 @@ even if you don't make friends. Этот сертификат не содержит в себе IP-адреса. В данном случае для установления соединения с узлом ваш клиент задействует сервис обнаружения и распределённую таблицу хешей DHT. Поскольку вам требуется разрешение белого списка, подключение к участнику вызовет предупреждение системы безопасности во вкладке новостей. Оттуда вы можете добавить его IP-адрес в белый список. - - [Unknown] - - - - + Added with certificate from %1 Добавлено с сертификатом от %1 - - Paste Cert of your friend from Clipboard - Вставить сертификат участника из буфера обмена - - - Certificate Load Failed:can't read from file %1 - Ошибка загрузки сертификата: не удаётся прочитать файл %1 - - - Certificate Load Failed:something is wrong with %1 - Ошибка загрузки сертификата: что-то не так с %1 - ConnectProgressDialog @@ -4247,7 +3604,7 @@ even if you don't make friends. - + UDP Setup Установление UDP @@ -4283,7 +3640,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:13pt;">то можете закрыть его.</span></p></body></html> - + Connection Assistant Помощник соединения @@ -4293,17 +3650,20 @@ p, li { white-space: pre-wrap; } Неверный идентификатор участника - + + Unknown State Неизвестное состояние - + + Offline Не в сети - + + Behind Symmetric NAT За симметричным NAT @@ -4313,12 +3673,14 @@ p, li { white-space: pre-wrap; } Плохая сеть: непрозрачный NAT, не работает DHT - + + NET Restart Перезапуск сети - + + Behind NAT За маршрутизатором @@ -4328,7 +3690,8 @@ p, li { white-space: pre-wrap; } DHT не работает - + + NET STATE GOOD! СОСТОЯНИЕ СЕТИ ХОРОШЕЕ! @@ -4353,7 +3716,7 @@ p, li { white-space: pre-wrap; } Поиск участников тёмной сети - + Lookup requires DHT Поиск узла требует DHT @@ -4645,7 +4008,7 @@ p, li { white-space: pre-wrap; } Пожалуйста, повторите попытку импорта полного сертификата. - + @@ -4653,7 +4016,8 @@ p, li { white-space: pre-wrap; } Нет данных - + + UNVERIFIABLE FORWARD! НЕПРОВЕРЕННАЯ ПЕРЕСЫЛКА! @@ -4663,7 +4027,7 @@ p, li { white-space: pre-wrap; } Неподдающееся проверке перенаправление! DHT не работает - + Searching Поиск @@ -4699,12 +4063,12 @@ p, li { white-space: pre-wrap; } Подробности о круге - + Name Имя - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> <html><head/><body><p>Имя круга, контакты автора и список приглашённых будут видны всем приглашённым участникам. Если круг не является приватным, он также будет виден соседним узлам, на которых размещаются приглашённые члены.</p></body></html> @@ -4724,7 +4088,7 @@ p, li { white-space: pre-wrap; } - + IDs Идентификаторы @@ -4744,18 +4108,18 @@ p, li { white-space: pre-wrap; } Фильтр - + Cancel - + Nickname Псевдоним - + Invited Members Приглашённые пользователи @@ -4770,15 +4134,7 @@ p, li { white-space: pre-wrap; } Известные пользователи - ID - Идентификатор - - - Type - Тип - - - + Name: Имя: @@ -4818,23 +4174,19 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Информация о круге может быть доступна участникам другого круга. В данном случае участникам этого круга будут доступны все арибуты первого круга (список участников, авторство и т. п.), а также привязанный к нему контент.</p></body></html> - Only visible to members of: - Видим только членам круга: - - - - + + RetroShare RetroShare - + Please set a name for your Circle Пожалуйста, установите название вашего круга - + No Restriction Circle Selected Не выбрано ограничение круга @@ -4844,12 +4196,24 @@ p, li { white-space: pre-wrap; } Не выбраны ограничения круга - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add Добавить @@ -4859,7 +4223,7 @@ p, li { white-space: pre-wrap; } Удалить - + Search Поиск @@ -4874,10 +4238,6 @@ p, li { white-space: pre-wrap; } Signed Подписано - - Signed by known nodes - Подписано известными узлами - Edit Circle @@ -4894,10 +4254,6 @@ p, li { white-space: pre-wrap; } PGP Identity PGP-личность - - Anon Id - Анонимный идентификатор - Circle name @@ -4920,17 +4276,13 @@ p, li { white-space: pre-wrap; } Создать новый круг - + Create Создать - PGP Linked Id - Идентификатор, привязанный к PGP-ключу - - - + Add Member Добавить члена @@ -4949,7 +4301,7 @@ p, li { white-space: pre-wrap; } Создать группу - + Group Name: Имя группы: @@ -4984,7 +4336,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post Новое сообщение канала @@ -4994,7 +4346,7 @@ p, li { white-space: pre-wrap; } Сообщение канала - + Post @@ -5055,23 +4407,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Используйте кнопку "Перетащить и Отпустить / Добавить файлы", чтобы хешировать новые файлы.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Копируйте / вставьте ссылки RetroShare ваших файлов</span></p></body></html> - - Add File to Attach - Добавить файл во вложение - Add Channel Thumbnail Добавить изображение-миниатюру для канала - - Message - Сообщение - - - Subject : - Тема: - @@ -5157,17 +4497,17 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -5186,17 +4526,18 @@ p, li { white-space: pre-wrap; } The following files will only be shared for 30 days. Think about adding them to a shared directory. - - File already Added and Hashed - Файл уже добавлен и хеширован - Please add a Subject Добавьте тему сообщения - + + Cannot publish post + + + + Load thumbnail picture Загрузить изображение-миниатюру @@ -5211,18 +4552,12 @@ p, li { white-space: pre-wrap; } - - + Generate mass data Создание массовой информации - - Do you really want to generate %1 messages ? - Вы действительно хотите создать %1 сообщений? - - - + You are about to add files you're not actually sharing. Do you still want this to happen? Вы хотите добавить файлы которые не ещё не общедоступны. Продолжить в любом случае? @@ -5256,7 +4591,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message Создать сообщение на форуме @@ -5265,10 +4600,6 @@ p, li { white-space: pre-wrap; } Forum Форум - - Subject - Тема - Attach File @@ -5289,8 +4620,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -5309,7 +4640,7 @@ p, li { white-space: pre-wrap; } Вы можете добавить файлы перетаскиванием - + Post @@ -5339,17 +4670,17 @@ p, li { white-space: pre-wrap; } - + No Forum Нет форума - + In Reply to В ответ на - + Title Название @@ -5403,7 +4734,7 @@ Do you want to discard this message? Загрузить файл изображения - + No compatible ID for this forum Нет совместимого идентификатора для этого форума @@ -5413,8 +4744,8 @@ Do you want to discard this message? Ни один из ваших идентификаторов не имеет прав для отправки сообщений в этот форум. Возможно, доступ к форуму ограничен кругом, в котором вы не состоите, или форум требует наличие подписанного идентификатора. - - + + Generate mass data Создание массовой информации @@ -5423,10 +4754,6 @@ Do you want to discard this message? Do you really want to generate %1 messages ? Вы действительно хотите создать %1 сообщений? - - Send - Отправить - Post as @@ -5441,23 +4768,7 @@ Do you want to discard this message? CreateLobbyDialog - Create Chat Lobby - Создать чат-комнату - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - Комната чата – децентрализованная и анонимная чат-группа. Все участники публично отправляют и принимают сообщения друг друга. После создания комнаты чата вы можете пригласить туда других участников из своего окружения, воспользовавшись кнопкой вверху справа с подсказкой «Пригласить участников в эту чат-комнату» - - - Lobby name: - Имя комнаты: - - - Lobby topic: - Тема: - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5492,7 +4803,7 @@ Do you want to discard this message? - + Create Создать @@ -5502,11 +4813,7 @@ Do you want to discard this message? - <html><head/><body><p>If you check this, only PGP-signed ids can be used to join and talk in this lobby. This limitation prevents anonymous spamming as it becomes possible for at least some people in the lobby to locate the spammer's node.</p></body></html> - <html><head/><body><p>Если вы отметите это, только подписанные участники смогут общаться в этой комнате. Это ограничение предотвращает спам от имени анонимных участников и делает возможным или, по меньшей мере, определить узел спаммера.</p></body></html> - - - + require PGP-signed identities требовать PGP-подписи личностей @@ -5521,11 +4828,7 @@ Do you want to discard this message? Отметьте участников, с которыми вы желаете организовать чат - Invited friends - Приглашённые участники - - - + Create Chat Room Создать чат-комнату @@ -5546,7 +4849,7 @@ Do you want to discard this message? Контакты: - + Identity to use: Личность для использования: @@ -5554,17 +4857,17 @@ Do you want to discard this message? CryptoPage - + Public Information Публичная информация - + Name: Имя: - + Location: Местоположение: @@ -5574,12 +4877,12 @@ Do you want to discard this message? Идентификатор местоположения: - + Software Version: Версия программы: - + Online since: Подключён с: @@ -5599,12 +4902,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5614,7 +4912,7 @@ Do you want to discard this message? - + Other Information Прочее @@ -5624,17 +4922,12 @@ Do you want to discard this message? - + Profile Профиль - - Certificate - Сертификат - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5644,11 +4937,7 @@ Do you want to discard this message? Вставить подписи - Save Key into a file - Сохранить ключ в файл - - - + Export Identity Экспорт личности @@ -5722,33 +5011,33 @@ and use the import button to load it - + TextLabel Текстовая метка - + PGP fingerprint: PGP-отпечаток: - - Node information - Сведения об узле сети - - - + PGP Id : PGP-идентификатор: - + Friend nodes: Доверенные узлы: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5787,14 +5076,6 @@ and use the import button to load it Node Узел сети - - Create new node... - Создание нового узла... - - - show statistics window - Показать окно статистики - DHTGraphSource @@ -5811,10 +5092,6 @@ and use the import button to load it DHT DHT - - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your friends to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your friends.</p> - <p>RetroShare использует DHT-сеть BitTorrent в качестве вспомогательной службы для установления соединений. В DHT не хранится ваш IP-адрес. DHT используется участниками из вашего окружения для установления соединения через стандартные DHT-запросы. Индикатор статуса DHT станет зелёным сразу же, как только RetroShare получит DHT-ответ от одного из ваших контактов.</p> - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your trusted nodes to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your trusted nodes.</p> @@ -5850,7 +5127,7 @@ and use the import button to load it DLListDelegate - + B Б @@ -6518,7 +5795,7 @@ and use the import button to load it DownloadToaster - + Start file Начальный файл @@ -6526,38 +5803,38 @@ and use the import button to load it ExprParamElement - + - + to кому - + ignore case без учёта регистра - - - dd.MM.yyyy - dd.MM.yyyy + + + yyyy-MM-dd + - - + + KB КБ - - + + MB МБ - - + + GB ГБ @@ -6565,12 +5842,12 @@ and use the import button to load it ExpressionWidget - + Expression Widget Визуализация выражения - + Delete this expression Удалить это выражение @@ -6732,7 +6009,7 @@ and use the import button to load it FilesDefs - + Picture Изображение @@ -6742,7 +6019,7 @@ and use the import button to load it Видео - + Audio Аудио @@ -6802,11 +6079,21 @@ and use the import button to load it C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Папки доверенных участников @@ -6928,7 +6215,7 @@ and use the import button to load it - + ID Идентификатор @@ -6963,10 +6250,6 @@ and use the import button to load it Show State Показать состояние - - Trusted nodes - Доверенные узлы - @@ -6974,7 +6257,7 @@ and use the import button to load it Показать группы - + Group Группа @@ -7010,7 +6293,7 @@ and use the import button to load it добавить в группу - + Search Поиск @@ -7026,7 +6309,7 @@ and use the import button to load it Сортировать по состоянию - + Profile details Сведения об узле @@ -7270,7 +6553,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request Подтвердить запрос на установление контакта @@ -7287,10 +6570,6 @@ at least one peer was not added to a group FriendSelectionWidget - - Search : - Поиск: - Sort by state @@ -7312,7 +6591,7 @@ at least one peer was not added to a group Поиск контактов - + Mark all Отметить все @@ -7323,16 +6602,134 @@ at least one peer was not added to a group Снять отметки + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Имя + + + + Node ID + + + + + Address + Адрес + + + + Status + Статус + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + Добавить узел в окружение + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + Прокси не включён или неисправен. +Все ли службы запущены и работают? +Также проверьте порты. + + FriendsDialog - + Edit status message Изменить ваш статус - - + + Broadcast Широковещательный чат @@ -7415,33 +6812,38 @@ at least one peer was not added to a group Сбросить настройки шрифта - + Keyring Массив ключей - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png"> Сеть</h1> <p>Вкладка «Сеть» показывает ваше доверенное окружение в сети RetroShare, а именно: те узлы RetroShare, с которыми вы соединены или можете соединиться, когда участник появится в сети. </p> <p>Можно группировать узлы, чтобы позднее детально разграничить уровень доступа к информации, например, разрешить только определённым узлам видеть определённые файлы или структуру ваших папок.</p> <p>Справа, вы найдете 3 полезные вкладки: <ul><li>Широковещательный чат отправляет сообщения сразу всем подключенным узлам </li> <li>Граф локальной сети отображает в удобной форме окружающие вас узлы, основываясь на информации, полученной от специального сервиса обнаружения</li> <li>Массив ключей содержит идентификаторы пользователей, собранных вашим клиентом от других участников сети</li></ul></p> - - - + Retroshare broadcast chat: messages are sent to all connected friends. Широковещательный чат RetroShare: сообщения будут рассылаться всем подключённым узлам. - - + + Network Сеть - + + Friend Server + + + + Network graph Визуализация сети - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. Установить сообщение о своём статусе @@ -7459,7 +6861,17 @@ at least one peer was not added to a group Пароль - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters Все поля должны обязательно быть заполнены текстом, состоящим из не менее 3 символов @@ -7469,17 +6881,12 @@ at least one peer was not added to a group Пароли не совпадают - + Port Порт - - Use BOB - Использовать BOB - - - + This password is for PGP Данный пароль предназначен для PGP @@ -7500,50 +6907,38 @@ at least one peer was not added to a group Не удалось создать ваш новый сертификат. Может быть, введён неправильный пароль PGP! - Options - Параметры - - - + PGP Key Length Длина ключа PGP - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> <html><head/><body><p>Введите здесь надёжный пароль. Пароль не должен быть короче восьми символов и содержать тривиальных комбинаций букв и цифр. Это очень важно, так как этот пароль защищает ваш приватный ключ!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> <html><head/><body><p>Прежде, чем продолжить, подвигайте мышью, чтобы собрать необходимые случайные данные. Индикатор прогресса должен дойти как минимум до 20%, но желательно достигнуть 100%</p></body></html> - + Standard node Регулярный узел - TOR/I2P Hidden node - Скрытый Tor- / i2p-узел - - - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> <html><head/><body><p>Название вашего узла определяет имя экземпляра клиент-сервера RetroShare, </p><p>который будет запущен на этом компьютере</p></body></html> - Use existing profile - Использовать существующий профиль - - - + Node name Название узла - + Node type: @@ -7563,12 +6958,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> <html><head/><body><p>Имя профиля идентифицирует вас в рамках вашего сетевого окружения.</p><p>Оно используется участниками сети, чтобы отличить вас от других участников и установить с вами соединение.</p><p>В рамках одного профиля вы имеете возможность</p><p>создать на различных машинах множество узлов с разными названиями.</p><p><br/></p></body></html> - + Export this profle Экспортировать профиль @@ -7578,42 +6973,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> <html><head/><body><p>Здесь следует указать onion-адрес наподобие: xa76giaf6ifda7ri63i263.onion <br/>, или же i2p-адрес в форме: [52 символа].b32.i2p </p><p>Для того, чтобы получить такие адреса, вам необходимо сконфигурировать скрытые или Tor-, или i2p-сервисы/серверы. В случае, если у вас нет ни того, ни другого, вы можете пропустить этот шаг и вернуться к настройкам позднее через конфигурационную панель RetroShare: Настройки → Сеть → Настройка скрытых сервисов.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> <html><head/><body><p>Личности-идентификаторы используются при общении в чатах, а также когда вы оставляете комментарии к сообщениям в форумах или каналах. </p><p>Кроме того, они необходимы для адресации участников при пересылке сообщений через встроенный почтовый сервис RetroShare.</p><p>У вас есть возможность создать анонимную или подписанную личность прямо сейчас. Но сделать это можно и позднее, воспользовавшись вкладкой «Участники».</p></body></html> - + Go! Начнём! - - + + TextLabel Текстовая метка - Advanced options - Дополнительные параметры - - - + hidden address Скрытый адрес - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. Ваш профиль связан с парой ключей PGP. В настоящее время RetroShare игнорирует DSA-ключи. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> <html><head/> <body><p>Это ваш порт подключения</p> <p>Любое значение от 1024 до 65535</p> <p>допустимо. Вы можете изменить его позже.</p></body></html> @@ -7661,13 +7057,13 @@ and use the import button to load it Ваш профиль не был сохранён. Произошла ошибка. - + Import profile Импортировать профиль - + Create new profile and new Retroshare node Создать новый профиль и узел RetroShare @@ -7677,7 +7073,7 @@ and use the import button to load it Создать новый узел RetroShare - + Tor/I2P address Адрес Tor/I2P @@ -7712,7 +7108,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7722,12 +7118,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> <p>Создание узла отключено до тех пор, пока не будут правильно заданы все поля.</p> @@ -7737,12 +7128,7 @@ and use the import button to load it <p>Создание узла отключено, пока не будет собрано достаточное количество случайных чисел. Пожалуйста, перемещайте мышь по кругу, пока не будет достигнуто по крайней мере 20%.</p> - - I2P instance address with BOB enabled - Адрес экземпляра I2P с включённым BOB - - - + I2P instance address Адрес экземпляра I2P @@ -7968,36 +7354,13 @@ and use the import button to load it Быстрый старт - + Invite Friends Пригласить участников - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare – это анонимная приватная f2f-сеть, поэтому вам необходимо соединиться как минимум с одним действующим участником сети. Нажмите на кнопку, чтобы добавить участника себе в окружение.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Отправьте приглашение с вашим сертификатом по электронной почте.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Аналогично получите приглашения от других участников сети. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Помните: соединение в тёмной сети RetroShare предполагает взаимный обмен сертификатами; только в этом случае вы сможете соединиться с контрагентом.</span></p></body></html> - - - + Add Your Friends to RetroShare Добавить ваших друзей и близких в RetroShare @@ -8007,136 +7370,103 @@ p, li { white-space: pre-wrap; } Добавить узлы в окружение - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Запустите RetroShare в то же время, что и ваш доверенный узел, и RetroShare в автоматическом режиме соединит вас!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Вашему клиенту необходимо найти сеть RetroShare до того, как станут возможными соединения между узлами.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Обычно это занимает 2-30 минут после первого запуска RetroShare. Не забудьте включить UPnP в вашем модеме или роутере!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Если индикатор DHT (см. кружок на панели состояния внизу) стал зелёным, то соединения с узлами сети возможны.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Если у вас работает UPnP или вручную настроен открытый порт, индикатор NAT (также см. на панель состояния) переключается из жёлтого состояния в зелёное.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Если он остаётся в красном состоянии, тогда это говорит о непрозрачном межсетевом экране, сквозь который RetroShare будет пытаться «пробиться».</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Посмотрите в раздел «Помощь», чтобы получить более полную информацию о соединениях.</span></p></body></html> + + Connect To Friends + Соединиться с доверенными узлами - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Вы можете существенно улучшить производительность и соединяемость Retroshare, открыв в вашем модеме или роутере внешний порт. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Это ускорит соединения с другими узлами, так как позволит другим участникам, у которых нет открытого порта, легко подключаться к вам. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Простейший способ это сделать – активировать UPnP в вашем модеме или роутере.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Так как модемов и роутеров множество и настраиваются они по-разному, мы рекомендуем вам поискать в Интернете информацию по запросу следующего вида: «открыть порт в модеме <модель_модема>.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Если всё же вам не удалось открыть порт, не беспокойтесь, Retroshare всё равно будет работать: в сети множество пользователей с открытыми портами.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Дополнительная настройка: открыть порт межсетевого экрана <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Имеются трудности в освоении RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Почитайте FAQ в Вики. Материал слегка устарел, но он всё же содержит основную информацию.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Почитайте форумы в Интернете. Задайте там актуальные для вас вопросы или укажите нерешённые проблемы.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Если вы уже подключены к сети, почитайте внутренные форумы RetroShare.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> – подчеркнём: они доступны только в том случае, если у вас имеется хотя бы один соединённый с вами узел.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) Если у вас ничего не получается, зайдите на сайт https://adorabilis.wordpress.com или в группу Вконтакте https://vk.com/retroshare и оставьте комментарий с вопросом в одной из тем. Вам обязательно ответят.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> + - - Connect To Friends - Соединиться с доверенными узлами - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Когда контрагенты отправят вам свои приглашения, чтобы их добавить, откройте окно "Добавить узлы в окружение".</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Вставьте &quot;сертификаты&quot; в окне и добавьте их как доверенные узлы.</span></p></body></html> - - - - Advanced: Open Firewall Port - Дополнительная настройка: открыть порт межсетевого экрана - - - + Further Help and Support Дополнительная помощь и поддержка - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website Открыть официальный сайт RetroShare @@ -8161,7 +7491,7 @@ p, li { white-space: pre-wrap; } Написать отзыв - + RetroShare Invitation Приглашение из RetroShare @@ -8211,12 +7541,12 @@ p, li { white-space: pre-wrap; } Отзывы о RetroShare - + RetroShare Support Команда поддержки RetroShare - + It has many features, including built-in chat, messaging, В ней много особенностей, включая встроенный чат, систему передачи сообщений, @@ -8340,7 +7670,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat Показать групповой чат @@ -8348,7 +7678,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] [неизвестно] @@ -8514,19 +7844,11 @@ p, li { white-space: pre-wrap; } You can let your friends know about your forum by sharing it with them. Select the friends with which you want to share your forum. Вы имеете возможность поделиться с доверенным окружением информацией о созданном вами форуме. Выберите контакты, которым вы хотели бы дать информацию о созданном форуме. - - Share topic admin permissions - Разрешения администратора общей темы - - - You can allow your friends to edit the topic. Select them in the list below. Note: it is not possible to revoke Posted admin permissions. - Вы можете разрешить вашим контактам изменять тему. Для этого выберите тот или иной контакт в списке ниже. Примечание: невозможно отобрать права администратора в сервисе публикаций. - GroupTreeWidget - + Title Название @@ -8539,12 +7861,12 @@ p, li { white-space: pre-wrap; } - + Description Описание - + Number of Unread message @@ -8569,35 +7891,7 @@ p, li { white-space: pre-wrap; } - Sort Descending Order - Сортировать по убыванию - - - Sort Ascending Order - Сортировать по возрастанию - - - Sort by Name - Сортировать по имени - - - Sort by Popularity - Сортировать по популярности - - - Sort by Last Post - Сортировать по последнему сообщению - - - Sort by Number of Posts - Сортировать по количеству сообщений - - - Sort by Unread - Сортировать по количеству непрочтённых сообщений - - - + You are admin (modify names and description using Edit menu) Вы администратор (изменяйте название и описание используя меню "Редактировать") @@ -8612,14 +7906,14 @@ p, li { white-space: pre-wrap; } Идентификатор - - + + Last Post Последнее непрочтённое - + Name Имя @@ -8630,17 +7924,13 @@ p, li { white-space: pre-wrap; } Популярность - + Never Никогда - Display - Показать - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8653,7 +7943,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and и @@ -8789,7 +8079,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels Каналы @@ -8800,26 +8090,22 @@ p, li { white-space: pre-wrap; } Создать канал - + Enable Auto-Download Включить автоматическое скачивание - + My Channels Мои каналы - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Каналы</h1> <p>Каналы дают возможность публиковать контент (например, кино или музыку), который подлежит раздаче пользователям сети.</p> <p>В списке каналов содержатся те каналы, на которые подписано ваше доверенное окружение, равно как и ваш узел автоматически отсылает окружению информацию о каналах, на которые подписаны вы. Такой механизм позволяет распространять по сети информацию о хороших каналах и блокировать неудачные.</p> <p>Оставлять сообщения в канале может только его создатель. Остальные участники могут лишь читать его содержимое и только в том случае, если канал не является приватным. Тем не менее, вы можете ⇥ дать права на чтение или модификацию канала пользователям из доверенного окружения.</p>⇥ <p>Канал может быть анонимным или псевдонимным, если за ним закреплён определённый идентификатор пользователя. ⇥ Включите режим «Разрешить комментарии», если Вы хотите дать пользователям возможность комментировать сообщения.</p> <p>Сообщения канала удаляются через %1 месяца.</p> - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Подписка на каналы @@ -8839,12 +8125,12 @@ p, li { white-space: pre-wrap; } Выберите папку загрузки для канала - + Disable Auto-Download Отменить автоматическое скачивание - + Set download directory Выберите папку загрузки @@ -8879,22 +8165,22 @@ p, li { white-space: pre-wrap; } - + Play Воспроизвести - + Open folder Открыть папку - + Open file - + Error Ошибка @@ -8914,17 +8200,17 @@ p, li { white-space: pre-wrap; } Проверка - + Are you sure that you want to cancel and delete the file? Вы уверены, что хотите отменить операцию и удалить файл? - + Can't open folder Не удалось открыть папку - + Play File Проиграть файл @@ -8934,37 +8220,10 @@ p, li { white-space: pre-wrap; } Файл %1 не существует в указанном месте. - - GxsChannelFilesWidget - - Form - Форма - - - Filename - Имя файла - - - Size - Размер - - - Title - Название - - - Published - Опубликовано - - - Status - Статус - - GxsChannelGroupDialog - + Create New Channel Создать новый канал @@ -9002,9 +8261,19 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - Подписаться на канал + + Last activity + + + + + TextLabel + Текстовая метка + + + + Subscribe this Channel + @@ -9018,7 +8287,7 @@ p, li { white-space: pre-wrap; } - + Expand Раскрыть @@ -9033,7 +8302,7 @@ p, li { white-space: pre-wrap; } Описание канала - + Loading Загрузка @@ -9048,8 +8317,9 @@ p, li { white-space: pre-wrap; } - New Channel - Новый канал + + Never + Никогда @@ -9060,7 +8330,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: Новый комментарий: @@ -9081,7 +8351,7 @@ p, li { white-space: pre-wrap; } - + Play Воспроизвести @@ -9137,28 +8407,24 @@ p, li { white-space: pre-wrap; } Files файлов - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - Внимание! У вас есть менее %1 часов и %2 минут, прежде чем файл будет удалён. Рассмотрите возможность его сохранения. - Hide Скрыть - + New Новый - + 0 0 - - + + Comment Комментарий @@ -9173,21 +8439,17 @@ p, li { white-space: pre-wrap; } Мне не понравилось - Loading - Загрузка - - - + Loading... - + Comments Комментарии - + Post @@ -9212,139 +8474,16 @@ p, li { white-space: pre-wrap; } Проиграть медиафайл - - GxsChannelPostsWidget - - Post to Channel - Создать сообщение в канале - - - Add new post - Добавить новое сообщение - - - Loading - Загрузка - - - Search channels - Поиск каналов - - - Title - Название - - - Search Title - Поиск по названию - - - Message - Почтовая служба - - - Search Message - Поиск сообщения - - - Filename - Имя файла - - - Search Filename - Поиск файла по имени - - - No Channel Selected - Не выбраны каналы - - - Never - Никогда - - - Public - Публичный - - - Restricted to members of circle " - Только для членов круга " - - - Restricted to members of circle - Только для членов круга - - - Your eyes only - Только для вас - - - You and your friend nodes - Вы и ваше окружение - - - Disable Auto-Download - Отменить автоматическое скачивание - - - Enable Auto-Download - Включить автоматическое скачивание - - - Show feeds - Отобразить сообщения - - - Show files - Показать файлы - - - Administrator: - Администратор: - - - Last Post: - Последнее сообщение: - - - unknown - неизвестно - - - Distribution: - Распространение: - - - Feeds - Каналы - - - Files - файлов - - - Subscribers - Подписчики - - - Description: - Описание: - - - Posts (at neighbor nodes): - Сообщений (соседние узлы): - - GxsChannelPostsWidgetWithModel - + Post to Channel Создать сообщение в канале - + Add new post Добавить новое сообщение @@ -9414,7 +8553,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -9450,7 +8589,7 @@ p, li { white-space: pre-wrap; } - + Comments Комментарии @@ -9465,13 +8604,13 @@ p, li { white-space: pre-wrap; } Каналы - - + + Click to switch to list view - + Show unread posts only @@ -9486,7 +8625,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -9501,7 +8640,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -9561,12 +8700,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -9623,12 +8772,12 @@ p, li { white-space: pre-wrap; } Restricted to members of circle " - + Ограничено для членов круга " Restricted to members of circle - + Ограничено для членов круга @@ -9641,12 +8790,13 @@ p, li { white-space: pre-wrap; } Вы и ваше окружение - + + Copy Retroshare link - + Subscribed @@ -9697,17 +8847,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel Текстовая метка - + Circle name: - + Accept @@ -9727,27 +8877,11 @@ p, li { white-space: pre-wrap; } Remove Item Удалить объект - - for identity - для личности - - - You received a membership request for circle: - Вы получили запрос на членство в круге: - Grant membership request Удовлетворить запрос на членство - - Revoke membership request - Отказать в запросе на членство - - - You received an invitation for circle: - Вы получили приглашение в круг: - @@ -9838,7 +8972,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container Контейнер комментариев @@ -9851,7 +8985,7 @@ p, li { white-space: pre-wrap; } Форма - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9881,7 +9015,7 @@ p, li { white-space: pre-wrap; } Обновить - + Comment Комментарий @@ -9920,7 +9054,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment Ответ на комментарий @@ -9944,6 +9078,21 @@ p, li { white-space: pre-wrap; } Vote Down Голосовать против + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9953,7 +9102,7 @@ p, li { white-space: pre-wrap; } Сделать комментарий - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9982,26 +9131,10 @@ p, li { white-space: pre-wrap; } - + Post - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Комментарий</span></p></body></html> - - - Signed by - Подписано - Reply to Comment @@ -10030,7 +9163,7 @@ before you can comment чем вы сможете комментировать - + It remains %1 characters after HTML conversion. @@ -10072,14 +9205,6 @@ before you can comment Forum moderators can edit/delete/pinup others posts - - Add Forum Admins - Добавить администраторов форума - - - Select Forum Admins - Выбрать администраторов форума - Create @@ -10089,7 +9214,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum Подписаться на форум @@ -10105,7 +9230,7 @@ before you can comment - + Expand Раскрыть @@ -10125,8 +9250,9 @@ before you can comment - Loading - Загрузка + + TextLabel + Текстовая метка @@ -10157,13 +9283,13 @@ before you can comment GxsForumMsgItem - - + + Subject: Тема: - + Unsubscribe To Forum Отписаться от форума @@ -10174,7 +9300,7 @@ before you can comment - + Expand Раскрыть @@ -10194,21 +9320,17 @@ before you can comment В ответ на: - Loading - Загрузка - - - + Loading... - + Forum Feed Послать в форум - + Hide Скрыть @@ -10221,63 +9343,66 @@ before you can comment Форма - + Start new Thread for Selected Forum Начать новую тему в выбранном форуме - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Поиск по форумам - Last Post - Последнее сообщение - - - + New Thread Новая тема - - - Threaded View - Древовидный вид - - - - Flat View - Плоский вид - - + Title Название - - + + Date Дата - + Author Автор - - Save image - Сохранить изображение - - - + Loading Загрузка - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -10287,12 +9412,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message Ответить на сообщение @@ -10316,10 +9436,6 @@ before you can comment Download all files Скачать все файлы - - Next unread - Следующее непрочитанное - Search Title @@ -10336,35 +9452,23 @@ before you can comment Поиск Автора - Content - Содержимое - - - Search Content - Поиск контента - - - <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - <p>Подписка на форум означает, что ваш клиент будет собирать среди доверенного окружения все имеющиеся сообщения, а также, в свою очередь, делать форумный котент видимым для других участников из вашего окружения.</p> <p>Впоследствии, при желании, вы сможете отписаться от форума, воспользовавшись контекстным меню.</p> - - - + No name Без названия - - + + Reply Ответ - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -10407,20 +9511,12 @@ before you can comment Скопировать ссылку RetroShare - + Hide Скрыть - Expand - Раскрыть - - - [Banned] - [Заблокировано] - - - + [unknown] [неизвестно] @@ -10450,8 +9546,8 @@ before you can comment Только для вас - - + + Distribution Распространение @@ -10465,26 +9561,6 @@ before you can comment Anti-spam Анти-спам - - [ ... Redacted message ... ] - [ ... Отредактированное сообщение ... ] - - - Anonymous - Аноним - - - signed - подписано - - - none - нет - - - [ ... Missing Message ... ] - [ ... Пропущенное сообщение ... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10554,16 +9630,12 @@ before you can comment Оригинал сообщения - + New thread Новая тема - Read status - Указывать состояние прочитано / не прочитано - - - + Edit Изменить @@ -10624,7 +9696,7 @@ before you can comment Репутация автора - + Show column @@ -10644,7 +9716,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive Сообщения анонимных авторов, а также авторов с неизвестными ключами, будут перенаправляться, если их репутация положительна @@ -10696,7 +9768,7 @@ This message is missing. You should receive it later. - + No result. @@ -10706,7 +9778,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -10721,28 +9793,7 @@ This message is missing. You should receive it later. - Information for this identity is currently missing. - В настоящее время информация об этой личности отсутствует - - - You have banned this ID. The message will not be -displayed nor forwarded to your friends. - Вы заблокировали этого участника. Его сообщения -не будут отображаться и не будут транслироваться вашему окружению. - - - You have not set an opinion for this person, - and your friends do not vote positively: Spam regulation -prevents the message to be forwarded to your friends. - Вы не указали своё мнение об этом участнике, -но некоторые узлы из вашего окружения установили для него отрицательную репутацию. Поэтому система предотвращения спама в вашем клиент-сервере не будет транслировать сообщения этого участника другим узлам из вашего окружения. - - - Message will be forwarded to your friends. - Сообщения не будут перенаправляться вашему окружению. - - - + (Latest) (Последнее) @@ -10751,10 +9802,6 @@ prevents the message to be forwarded to your friends. (Old) (Старое) - - You cant act on the author to a non-existant Message - Вы не можете влиять на автора несуществующего сообщения. - From @@ -10812,12 +9859,12 @@ prevents the message to be forwarded to your friends. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Форумы</h1> ⇥⇥⇥<p>Форумы в RetroShare выглядят схоже и преследуют те же цели, что и интернет-форумы. Ключевым отличием является их децентрализованность.</p> ⇥⇥⇥<p>В списке доступных форумов значатся форумы, на которые подписано ваше доверенное окружение. В свою очередь, вы отдаёте окружению информацию о том,⇥⇥⇥на какие форумы подписаны вы. Такой механизм распространения продвигает по сети хорошие форумы и блокирует неудачные.</p> <р> Сообщения форумов хранятся в течение %1 дней и синхронизируются с другими узлами в течение %2 дней. </p> <р> У вас есть возможность изменить эти значения.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> + - + Forums Форумы @@ -10848,35 +9895,16 @@ prevents the message to be forwarded to your friends. Другие форумы - - GxsForumsFillThread - - Waiting - ожидание - - - Retrieving - Получение - - - Loading - Загрузка - - GxsGroupDialog - + Name Имя - Add Icon - Добавить значок - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels Получатели ключа могут публиковать сообщения в группы с ограниченным доступом, просматривать и публиковать сообщения в приватных каналах @@ -10885,22 +9913,14 @@ prevents the message to be forwarded to your friends. Share Publish Key Поделиться публичным ключом - - check peers you would like to share private publish key with - проверить участников, с которыми вы хотите поделиться приватным ключом - - - Share Key With - Поделиться ключом с - - + Description Описание - + Message Distribution Распространение сообщений @@ -10908,7 +9928,7 @@ prevents the message to be forwarded to your friends. - + Public Публичные @@ -10927,14 +9947,6 @@ prevents the message to be forwarded to your friends. New Thread Новая тема - - Required - Требуется - - - Encrypted Msgs - Шифрованное сообщение - Personal Signatures @@ -10976,7 +9988,7 @@ prevents the message to be forwarded to your friends. Защита от спама - + Comments: Комментарии: @@ -10999,7 +10011,7 @@ prevents the message to be forwarded to your friends. Анти-спам: - + All People @@ -11015,12 +10027,12 @@ prevents the message to be forwarded to your friends. - + Restricted to circle: Ограничено кругом: - + Limited to your friends Ограничено вашими доверенными узлами @@ -11037,23 +10049,23 @@ prevents the message to be forwarded to your friends. - + Message tracking Отслеживание сообщений - - + + PGP signature required Необходима PGP-подпись - + Never Никогда - + Only friends nodes in group Только для доверенных участников в группе @@ -11069,30 +10081,28 @@ prevents the message to be forwarded to your friends. Добавьте имя - + PGP signature from known ID required Необходима PGP-подпись от известного идентификатора - + + + [None] + + + + Load Group Logo Загрузить логотип группы - + Submit Group Changes Отправить изменения группы - Failed to Prepare Group MetaData - please Review - Не удалось подготовить метаданные группы - пожалуйста, проверьте - - - Will be used to send feedback - Будет использовано для обратной связи - - - + Owner: Владелец: @@ -11102,12 +10112,12 @@ prevents the message to be forwarded to your friends. Укажите здесь осмысленное описание - + Info Сведения - + ID Идентификатор @@ -11117,7 +10127,7 @@ prevents the message to be forwarded to your friends. Последнее сообщение - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> <html><head/><body><p>Сообщения будут распространяться далеко за пределы вашего доверенного окружения до тех пор, пока кто-нибудь подписан на созданный вами канал/форум/публикацию.</p></body></html> @@ -11192,7 +10202,12 @@ prevents the message to be forwarded to your friends. Запретить неподписанные и неизвестные идентификаторы - + + Author: + + + + Popularity Популярность @@ -11208,27 +10223,22 @@ prevents the message to be forwarded to your friends. - + Created - + Cancel - + Create Создать - - Author - Автор - - - + GxsIdLabel Идентификатор Gxs @@ -11236,7 +10246,7 @@ prevents the message to be forwarded to your friends. GxsGroupFrameDialog - + Loading Загрузка @@ -11296,7 +10306,7 @@ prevents the message to be forwarded to your friends. Редактировать подробности - + Synchronise posts of last... Синхронизировать контент в течение... @@ -11353,16 +10363,12 @@ prevents the message to be forwarded to your friends. - + Search for - Share publish permissions - Поделиться правами на запись - - - + Copy RetroShare Link Скопировать ссылку RetroShare @@ -11385,7 +10391,7 @@ prevents the message to be forwarded to your friends. GxsIdChooser - + No Signature Без подписи @@ -11398,40 +10404,24 @@ prevents the message to be forwarded to your friends. GxsIdDetails - Loading - Загрузка - - - + Not found Не найден - - No Signature - Без подписи - - - + + [Banned] [Заблокировано] - - Authentication - Аутентификация - unknown Key неизвестный ключ - anonymous - анонимный - - - + Loading... @@ -11441,7 +10431,12 @@ prevents the message to be forwarded to your friends. - + + [Nobody] + + + + Identity&nbsp;name Имя&nbsp;личности @@ -11455,16 +10450,20 @@ prevents the message to be forwarded to your friends. Node - - Signed&nbsp;by - Подписано - [Unknown] [неизвестный] + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -11476,7 +10475,7 @@ prevents the message to be forwarded to your friends. GxsIdStatisticsWidget - + Total identities: @@ -11524,17 +10523,13 @@ prevents the message to be forwarded to your friends. GxsIdTreeItemDelegate - + [Unknown] GxsMessageFramePostWidget - - Loading - Загрузка - Loading... @@ -11651,10 +10646,6 @@ prevents the message to be forwarded to your friends. Group ID / Author Идентификатор группы / автор - - Number of messages / Publish TS - Количество сообщений / Время публикации - Local size of data @@ -11670,10 +10661,6 @@ prevents the message to be forwarded to your friends. Popularity Популярность - - Details - Подробности - @@ -11706,41 +10693,6 @@ prevents the message to be forwarded to your friends. Нет - - GxsTunnelsDialog - - Authenticated tunnels: - Авторизованные туннели: - - - Tunnel ID: %1 - Идентификатор туннеля: %1 - - - from: %1 - от: %1 - - - to: %1 - к: %1 - - - status: %1 - статус: %1 - - - total sent: %1 bytes - всего отправлено: %1 байт - - - total recv: %1 bytes - всего получено: %1 байт - - - Unknown Peer - Неизвестный участник - - HashBox @@ -11765,17 +10717,17 @@ prevents the message to be forwarded to your friends. Examining shared files... - Проверка файлов, открытых к доступу... + Проверка файлов, открытых к доступу... Hashing file - Хеширование файла + Хеширование файла Saving file index... - Сохранение списка файлов... + Сохранение списка файлов... @@ -11953,48 +10905,12 @@ prevents the message to be forwarded to your friends. About О программе - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare provides file sharing, chat, messages and channels</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Useful external links to more information:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Wiki</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare's Forum</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Project Page</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Team Blog</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Dev Twitter</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare – это кроссплатформенное приложение на основе открытого ПО, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">персональная защищённая децентрализованная коммуникационная система.⇥</span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Она позволяет осуществлять безопасный файлообмен совместно с доверенными участниками, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">использует сеть доверия для установления подлинности участников и OpenSSL для шифрования всей передаваемой информации. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare предоставляет сервисы файлообмена, чатов, электронной почты и каналов</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Следующие полезные ссылки дают больше сведений:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Вебсайт Retroshare</span></a></li> -<li style=" font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net">Вики-страница Retroshare</a></li> -<li style=" font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net">Форум RetroShare</a></li> -<li style=" font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net">Страница проекта Retroshare</a></li> -<li style=" font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net">Блог команды RetroShare</a></li> -<li style=" font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net">Twitter разработчиков RetroShare</a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -12010,7 +10926,7 @@ p, li { white-space: pre-wrap; } - + Authors Авторы @@ -12029,7 +10945,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -12042,36 +10958,6 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Daniel Wester</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">wester@speedmail.se</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">German: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Jan</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Keller</span><span style=" font-family:'MS Shell Dlg 2';"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">trilarion@users.sourceforge.net</span><span style=" font-family:'MS Shell Dlg 2';">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Перевод интерфейса RetroShare:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Переводчики веб-сайта RetroShare:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Шведский язык: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Daniel Wester</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">wester@speedmail.se</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Немецкий язык: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Jan</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Keller</span><span style=" font-family:'MS Shell Dlg 2';"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">trilarion@users.sourceforge.net</span><span style=" font-family:'MS Shell Dlg 2';">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Польский язык: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - License Agreement @@ -12137,50 +11023,34 @@ p, li { white-space: pre-wrap; } Форма - + <html><head/><body><p>Copy your RetroShare ID to clipboard</p></body></html> - + <html><head/><body><p>Скопируйте свой идентификатор RetroShare в буфер обмена</p></body></html> - + Add friend - + Добавить узел Did you receive a Retroshare ID from a friend? - + Вы получили идентификатор Retroshare от друга? Do you need help with Retroshare? - + Вам нужна помощь с Retroshare? - + <html><head/><body><p>Share your RetroShare ID</p></body></html> - + <html><head/><body><p>Поделитесь своим идентификатором RetroShare</p></body></html> This is your Retroshare ID. Copy and share with your friends! - - - - Did you receive a certificate from a friend? - У вас уже есть сертификат другого участника тёмной сети? - - - Add friends certificate - Добавить сертификат - - - Add certificate file - Добавить файл сертификата - - - Share your RetroShare Key - Предоставить мой сертификат + Это ваш Retroshare ID. Скопируйте и поделитесь с друзьями! @@ -12188,10 +11058,6 @@ p, li { white-space: pre-wrap; } ... ... - - The text below is your own Retroshare certificate. Send it to your friends - Текст, который вы видите ниже, есть ваш сертификат. Отправьте его тому, с кем вы желаете соединиться - Open Source cross-platform, @@ -12202,20 +11068,12 @@ private and secure decentralized communication platform. - Launch startup wizard - Мастер запуска - - - Do you need help with RetroShare? - Вам нужна помощь по RetroShare? - - - + Open Web Help Открыть помощь в веб - + Copy your Cert to Clipboard Скопировать сертификат в буфер обмена @@ -12225,7 +11083,7 @@ private and secure decentralized communication platform. Сохранить сертификат в файл - + Send via Email Послать по электронной почте @@ -12245,16 +11103,40 @@ private and secure decentralized communication platform. - - - Include all your known IPs + + Include current local IP - - Use old certificate format + + Include current external IP + + + Include my DNS + + + + + Include all IPs history + Включить историю всех IP-адресов + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + + Include all your known IPs + Включите все ваши известные IP-адреса + + + + Use old certificate format + Использовать старый формат сертификата + Displays the certificate format used up to version 0.6.5 @@ -12263,17 +11145,12 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Use new (short) certificate format - + Использовать (короткий) формат сертификата - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -12282,19 +11159,11 @@ new short format Your Retroshare ID is copied to Clipboard, paste and send it to your friend via email or some other way - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your certificate on this page and send it to friends, and add your friends' certificate.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange certificates with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Добро пожаловать в Retroshare!</h1> <p>Вам нужно <b>добавить доверенные узлы</b>! После добавления доверенных узлов или присоединения к существующей сети, вы сможете обмениваться файлами, общаться в чате, на форумах и т. д. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>Для этого скопируйте свой сертификат с этой страницы и отправьте его своим контактам, а также добавьте их сертификаты.</p> <p>Другой вариант — найти в интернете "чат-серверы Retroshare" (независимо от администрирования). Эти серверы позволяют обмениваться сертификатами с выделенным узлом Retroshare, через который вы сможете анонимно встречаться с другими людьми.</p> - RetroShare Invite Пригласить в RetroShare - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Ваш сертификат скопирован в буфер обмена. Отправьте контрагенту письмо с этим сертификатом по электронной почте или же воспользуйтесь любым другим доступным способом. - Save as... @@ -12566,14 +11435,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Все участники - + Reputation Репутация @@ -12583,12 +11452,12 @@ p, li { white-space: pre-wrap; } Поиск - + Anonymous Id Анонимный идентификатор - + Create new Identity Создать новую личность @@ -12598,7 +11467,7 @@ p, li { white-space: pre-wrap; } Создать новый круг - + Persons Действия над участниками @@ -12613,27 +11482,27 @@ p, li { white-space: pre-wrap; } Участник - + Close Закрыть - + Ban-option: Блокировка: - + Auto-Ban all identities signed by the same node Автоматически блокировать все личности, созданные этим узлом - + Friend votes: - Рейтинг согласно мнению участников из окружения: + Голоса друзей: - + Positive votes Положительное мнение @@ -12649,29 +11518,39 @@ p, li { white-space: pre-wrap; } Отрицательное мнение - + Created on : - + Создано: - + + Auto-Ban profile + Профиль автобана + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + Изменить личность + + + Usage statistics Статистика использования - + Circles Круги - + Circle name Имя круга @@ -12691,18 +11570,20 @@ p, li { white-space: pre-wrap; } Личные круги - + + Edit identity Редактировать личность - + + Delete identity Удалить личность - + Chat with this peer Чат с этим участником @@ -12712,119 +11593,99 @@ p, li { white-space: pre-wrap; } Запустить удалённый чат с этим участником - + Owner node ID : - Идентификатор владельца узла: + Идентификатор узла: - + Identity name : Псевдоним: - + () () - + Identity ID Идентификатор личности - + Send message Отправить сообщение - + Identity info Информация о личности - + Identity ID : Идентификатор личности: - + Owner node name : - Имя владельца узла: + Имя узла: - + Create new... Создать новую личность... - + Type: Тип: - + Send Invite Пригласить - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> <html><head/><body><p>Среднее мнение об этой личности с соседних узлов. Отрицательное — плохо</p><p>Положительное — хорошо. Ноль нейтрален. <p></body></html> - + Your opinion: Ваше мнение: - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </p> -<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ваше собственное мнение о личности определяет видимость этой личности для вас самих и ваших доверенных узлов. Ваше мнение передаётся доверенным узлам и используется для вычисления оценки репутации: если ваше мнение о личности нейтрально, оценка репутации — это разница между положительными и отрицательными мнениями ваших контактов, а если нет, то оценку определяет ваше мнение.</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Общий балл используется в чатах, форумах и каналах, чтобы определить действия, которые необходимо предпринять в отношении каждой конкретной личности. Когда общий балл меньше -1, личность блокируется, что предотвращает пересылку всех ею созданных сообщений и форумов/каналов, в обоих направлениях. Некоторые форумы также имеют специальные флаги для защиты от нежелательной почты, которые требуют не отрицательного уровня репутации, что делает их более чувствительными к плохим мнениям. Заблокированные личности постепенно теряют свою активность и в конечном итоге исчезают (через 5 дней).</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Вы можете изменить пороговые значения и время бездействия для удаления личностей в "Настройках" → "Участники". </p> -<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - + Negative - Отрицательное мнение + Отрицательно - + Neutral - Нейтральное мнение + Нейтральный Positive - Положительное мнение + Положительный - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> <html><head/><body><p>Интегральное значение репутации, основанное на вашем мнении и мнении ваших контактов.</p><p>Отрицательное значение — плохая репутация, положительное — хорошая, ноль — нейтральная. Если значение слишком низкое,</p><p>личность будет помечена как плохая и отфильтрована в форумах, чатах,</p><p>каналах и т.п.</p></body></html> - + Overall: Общая: - + Anonymous Анонимные участники @@ -12839,24 +11700,24 @@ p, li { white-space: pre-wrap; } Поиск идентификатора - + This identity is owned by you Эта личность закреплена за вами - - + + My own identities Личности, созданные мною - - + + My contacts Мои контакты - + Show Items Показать... @@ -12871,7 +11732,12 @@ p, li { white-space: pre-wrap; } Личности, привязанные к моему узлу - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles Другие круги @@ -12881,7 +11747,7 @@ p, li { white-space: pre-wrap; } Круги со мной - + Circle ID: Идентификатор круга: @@ -12933,7 +11799,7 @@ p, li { white-space: pre-wrap; } unsubscribed (Only receive invite list). Last seen: %1 days ago. - + отписался (Только получать список приглашений). Последний раз был в сети: %1 дней назад. @@ -12956,14 +11822,14 @@ p, li { white-space: pre-wrap; } Не член (нет доступа к данным доступным кругу) - + Identity ID: Идентификатор личности: Status: - Статус: + Статус: @@ -12986,7 +11852,7 @@ p, li { white-space: pre-wrap; } неизвестно - + Invited Приглашён @@ -13001,7 +11867,7 @@ p, li { white-space: pre-wrap; } Член - + Edit Circle Редактировать круг @@ -13049,7 +11915,7 @@ p, li { white-space: pre-wrap; } Разрешить членство - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -13060,7 +11926,7 @@ These identities will soon be not supported anymore. Поддержка таких идентификаторов вскоре прекратится. - + [Unknown node] [неизвестный узел] @@ -13103,7 +11969,7 @@ These identities will soon be not supported anymore. Анонимная личность - + Boards @@ -13145,7 +12011,7 @@ These identities will soon be not supported anymore. Message - + Сообщение @@ -13183,7 +12049,7 @@ These identities will soon be not supported anymore. - + information информация @@ -13199,29 +12065,12 @@ These identities will soon be not supported anymore. Скопировать личность в буфер обмена - Send invite? - Послать приглашение - - - Do you really want send a invite with your Certificate? - Отправить приглашение с Вашим сертификатом? - - - + Banned Заблокированные участники - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Личности</h1> <p>В этой вкладке вы имеете возможность создавать/редактировать <b>анонимные и псевдонимные личности</b>, а также <b>круги</b>.</p> <p><b>Личности</b> используются для безопасной публикации сообщений: от имени личностей вы посылаете сообщения в чаты, форумы и каналы, получаете отклики через встроенный в RetroShare почтовый сервис, публикуете комментарии в каналах, чатах. От имени личностей в определённых случаях прокладываются анонимные туннели и т. п.</p> <p>Личности не обязательно должны быть <b>подписаны</b> вашим личным сертификатом. Подписанные личности иногда полезны, если вы хотите подчеркнуть авторство того или иного сообщения. Однако по подписанным личностям зачастую можно отследить IP-адрес автора сообщения.</p> <p><b>Анонимные личности</b> позволяют вам анонимно, а значит – безопасно, взаимодействовать с другими участниками тёмной сети. Анонимные личности не могут быть подменены, но никто не может однозначно обозначить привязку анонимной личности к конкретному сертификату, а значит – и пользователю.</p> <p><b>Круги</b> – это совокупность личностей (анонимных или подписанных), информация о которых широко распространяется по тёмной сети. Круги используются для создания форумов и каналов, содержимое которых доступно только участникам конкретного круга </p> <p><b>Один круг</b> может быть ограничен другим кругом, как следствие, определяя видимость его участников определённому множеству участников, принадлежащему другому кругу. Есть возможность создавать самый приватный тип кругов, где информация о них доступна только членам самого круга, читайте – закрытого клуба.</p> <p><b>Локальный круг</b> есть совокупность доверенных узлов, представленных их PGP-идентификаторами, и широко используемых для ограничения доступности каналов и форумов. Такого рода круги не распространяются по сети и список его членов доступен только вам.</p> - - - Unknown ID: - Неизвестный идентификатор: - - - + positive положительно @@ -13265,19 +12114,11 @@ These identities will soon be not supported anymore. Forums Форумы - - Posted - Публикации - Chat Чаты - - Unknown - Неизвестно - [Unknown] @@ -13298,14 +12139,6 @@ These identities will soon be not supported anymore. Creation of author signature in service %1 Создание сигнатуры администратора в сервисе %1 - - Message/vote/comment - Сообщение / голос / комментарий - - - %1 in %2 tab - %1 во вкладке %2 - Distant message signature validation. @@ -13326,19 +12159,11 @@ These identities will soon be not supported anymore. Signature in distant tunnel system. Подпись в системе удалённого туннелирования - - Update of identity data. - обновление данных о личности. - Generic signature validation. Базовая проверка подлинности сигнатуры - - Generic signature. - Базовая сигнатура - Generic encryption. @@ -13350,11 +12175,7 @@ These identities will soon be not supported anymore. Базовое дешифрование. - Membership verification in circle %1. - Проверка членства в круге %1 - - - + Add to Contacts Добавить в контакты @@ -13404,21 +12225,21 @@ These identities will soon be not supported anymore. Приветствую, <br>предлагаю обменяться сертификатами RetroShare.<br> - - - + + + People Участники - + Your Avatar Click here to change your avatar Нажмите здесь, чтобы изменить свой аватар - + Linked to neighbor nodes Личности, привязанные к ближнему окружению @@ -13428,7 +12249,7 @@ These identities will soon be not supported anymore. Личности, привязанные к удалённому узлу - + Linked to a friend Retroshare node Личности, привязанные к доверенному окружению @@ -13443,7 +12264,7 @@ These identities will soon be not supported anymore. Привязан к неизвестному узлу - + Chat with this person Начать чат @@ -13458,12 +12279,12 @@ These identities will soon be not supported anymore. В удалённом чате с этим человеком отказано. - + Last used: - Последний раз появлялся: + Последний раз появлялся: - + +50 Known PGP +50 известных PGP @@ -13483,12 +12304,12 @@ These identities will soon be not supported anymore. Вы действительно хотите удалить эту личность? - + Owned by Принадлежит... - + Node name: Имя узла: @@ -13498,15 +12319,15 @@ These identities will soon be not supported anymore. Идентификатор узла: - + Really delete? - Действительно удалить? + Действительно удалить? IdEditDialog - + Nickname Псевдоним @@ -13536,7 +12357,7 @@ These identities will soon be not supported anymore. Псевдоним - + Import image @@ -13546,12 +12367,19 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. + + + No Avatar chosen. A default image will be automatically displayed from your new identity. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity Новая личность @@ -13565,7 +12393,7 @@ These identities will soon be not supported anymore. - + @@ -13575,7 +12403,12 @@ These identities will soon be not supported anymore. Недоступен - + + No avatar chosen + + + + Edit identity Редактировать личность @@ -13586,27 +12419,27 @@ These identities will soon be not supported anymore. Обновить - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -13626,7 +12459,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -13636,11 +12469,7 @@ These identities will soon be not supported anymore. - Error getting key! - Ошибка при получении ключа! - - - + Error KeyID invalid Ошибка: недействительный идентификатор ключа @@ -13655,7 +12484,7 @@ These identities will soon be not supported anymore. Неизвестное имя - + Create New Identity Создать новую личность @@ -13665,10 +12494,15 @@ These identities will soon be not supported anymore. Тип - + Choose image... + + + Remove + + @@ -13694,7 +12528,7 @@ These identities will soon be not supported anymore. Добавить - + Create Создать @@ -13704,17 +12538,13 @@ These identities will soon be not supported anymore. - + Your Avatar Click here to change your avatar Нажмите здесь, чтобы изменить аватар - Set Avatar - Установить аватар - - - + Linked to your profile Привязан к моему профилю @@ -13724,7 +12554,7 @@ These identities will soon be not supported anymore. Вы можете иметь один или несколько идентификаторов. Они используются, когда вы пишете в чате лобби, на форумах и канале комментариев. Они выступают в качестве получателя для удалённого чата и удалённой почтовой системы Retroshare. - + The nickname is too short. Please input at least %1 characters. Псевдоним является слишком коротким. Пожалуйста, введите по крайней мере %1 символов. @@ -13783,10 +12613,6 @@ These identities will soon be not supported anymore. PGP name: PGP-псевдоним: - - GXS id: - Идентификатор GXS: - PGP id: @@ -13802,7 +12628,7 @@ These identities will soon be not supported anymore. - + Copy Копировать @@ -13812,12 +12638,12 @@ These identities will soon be not supported anymore. Удалить - + %1 's Message History - + Mark all Отметить всё @@ -13836,26 +12662,38 @@ These identities will soon be not supported anymore. Quote Цитата - - Send - Отправить - ImageUtil - - + + Save image Сохранить изображение + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + + + + Cannot save the image, invalid filename Невозможно сохранить изображение, неверное имя файла - + + Copy image + + + + + Not an image Не является изображением @@ -13873,27 +12711,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: Порт: - + Listen Address: - + + Status: + Статус: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -13914,7 +12757,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -13923,26 +12771,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File Открыть файл - + Open Folder Открыть папку - + Checking... Проверка... @@ -13952,7 +12805,7 @@ These identities will soon be not supported anymore. Проверить файлы - + Recommend in a message to... Рекомендовать в сообщении для... @@ -13980,7 +12833,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend Добавить контакт @@ -13996,7 +12849,8 @@ These identities will soon be not supported anymore. - + + Options Параметры @@ -14017,7 +12871,7 @@ These identities will soon be not supported anymore. - + Quit Выход @@ -14028,12 +12882,12 @@ These identities will soon be not supported anymore. Помощник быстрого старта - + RetroShare %1 a secure decentralized communication platform RetroShare %1 — безопасная децентрализованная коммуникационная платформа - + Unfinished Ещё не готово @@ -14062,11 +12916,12 @@ RetroShare безопасно приостановит доступ диска + Status Статус - + Notify Уведомить @@ -14077,31 +12932,35 @@ RetroShare безопасно приостановит доступ диска + Open Messages Открыть почту - + + Bandwidth Graph График пропускной способности - + Applications Программа + Help Помощь - + + Minimize Свернуть - + Maximize Развернуть @@ -14116,7 +12975,12 @@ RetroShare безопасно приостановит доступ диска RetroShare - + + Close window + + + + %1 new message %1 новое сообщение @@ -14146,7 +13010,7 @@ RetroShare безопасно приостановит доступ диска %1 узлов сети соединено - + Do you really want to exit RetroShare ? Вы действительно хотите выйти из RetroShare? @@ -14166,7 +13030,7 @@ RetroShare безопасно приостановит доступ диска Показать - + Make sure this link has not been forged to drag you to a malicious website. Убедитесь, что эта ссылка не была подделана, чтобы перенаправить вас на вредоносный веб-сайт. @@ -14211,12 +13075,13 @@ RetroShare безопасно приостановит доступ диска Управление правами доступа - + + Statistics Статистика функционирования - + Show web interface Показать веб-интерфейс @@ -14231,7 +13096,7 @@ RetroShare безопасно приостановит доступ диска не хватает места в данной папке (текущий лимит - + Really quit ? Хотите выйти? @@ -14240,17 +13105,17 @@ RetroShare безопасно приостановит доступ диска MessageComposer - + Compose Составить - + Contacts Контакты - + Paragraph Абзац @@ -14286,12 +13151,12 @@ RetroShare безопасно приостановит доступ диска Заголовок 6 - + Font size Размер шрифта - + Increase font size Увеличить размер шрифта @@ -14306,32 +13171,32 @@ RetroShare безопасно приостановит доступ диска Полужирный - + Italic Курсив - + Alignment Выравнивание - + Add an Image Добавить изображение - + Sets text font to code style Установка шрифта для стиля кода - + Underline Подчёркнутый - + Subject: Тема: @@ -14342,32 +13207,32 @@ RetroShare безопасно приостановит доступ диска - + Tags Метки - + Address list: Список адресов - + Recommend this friend Рекомендовать этого доверенного участника - + Set Text color Задать цвет текста - + Set Text background color Задать цвет фона текста - + Recommended Files Рекомендованные файлы @@ -14437,7 +13302,7 @@ RetroShare безопасно приостановит доступ диска Добавить цитату - + Send To: Отправить: @@ -14461,10 +13326,6 @@ RetroShare безопасно приостановит доступ диска &Justify По ширине - - All addresses (mixed) - Все адреса (смешано) - All people @@ -14476,7 +13337,7 @@ RetroShare безопасно приостановит доступ диска Мои контакты - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> Здравствуйте, <br>я рекомендую вам один из моих лучших контактов. Вы можете доверять ему ровно настолько, насколько вы доверяете мне. Это хороший узел, поверьте.<br> @@ -14496,18 +13357,18 @@ RetroShare безопасно приостановит доступ диска желает установить с вами соединение - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team Наилучшие пожелания %1,<br><br>%2 хочет установить с вами соединение.<br><br>Откликнитесь, пожалуйста:<br>%3<br><br>Это в интересах всей сети.<br>Команда разработчиков RetroShare - - + + Save Message Сохранить сообщение - + Message has not been Sent. Do you want to save message to draft box? Сообщение не отправлено. @@ -14519,7 +13380,17 @@ Do you want to save message to draft box? Вставить ссылку RetroShare - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" Добавить к "кому" @@ -14539,7 +13410,7 @@ Do you want to save message to draft box? Добавить как рекомендацию - + Original Message Оригинал сообщения @@ -14549,21 +13420,21 @@ Do you want to save message to draft box? От - + - + To Кому - - + + Cc Копия - + Sent Отправлено @@ -14578,7 +13449,7 @@ Do you want to save message to draft box? %1 %2 написал(а): - + Re: Ответ: @@ -14588,30 +13459,30 @@ Do you want to save message to draft box? Перенаправление: - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? Отправить сообщение без темы? - + Please insert at least one recipient. Пожалуйста, укажите хотя бы одного получателя - + Bcc Невидимая копия - + Unknown Неизвестно @@ -14726,13 +13597,13 @@ Do you want to save message to draft box? Подробности - + Open File... Открыть файл... - + HTML-Files (*.htm *.html);;All Files (*) HTML-файлы (*.htm *.html);;Все файлы (*) @@ -14752,7 +13623,7 @@ Do you want to save message to draft box? Экспорт PDF - + Message has not been Sent. Do you want to save message ? Сообщение не отправлено. @@ -14774,7 +13645,7 @@ Do you want to save message ? Добавить файл - + Hi,<br>I want to be friends with you on RetroShare.<br> Привет, <br>Есть предложение обменяться сертификатами друг с другом. Не возражаете?<br> @@ -14798,28 +13669,24 @@ Do you want to save message ? Warning: This message is too big of %1 characters after HTML conversion. - - You have a friend invite - Вы получили предложение на соединение с действующим узлом RetroShare - Respond now: Ответить сейчас: - - + + Close Закрыть - + From: Из: - + Friend Nodes Доверенные узлы сети @@ -14864,13 +13731,13 @@ Do you want to save message ? Отсортированный список (в римской системе по убыванию) - - + + Thanks, <br> Спасибо, <br> - + Distant identity: Удалённая личность: @@ -14880,12 +13747,12 @@ Do you want to save message ? [Отсутствует] - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. Пожалуйста, создайте личность для подписи отдалённых сообщений или удалите отдалённых участников из списка назначения. - + Node name & id: Имя и идентификатор узла: @@ -14963,7 +13830,7 @@ Do you want to save message ? По умолчанию - + A new tab Новая вкладка @@ -14973,7 +13840,7 @@ Do you want to save message ? Новое окно - + Edit Tag Изменить метку @@ -14996,7 +13863,7 @@ Do you want to save message ? MessageToaster - + Sub: Тема: @@ -15004,7 +13871,7 @@ Do you want to save message ? MessageUserNotify - + Message Сообщение @@ -15032,7 +13899,7 @@ Do you want to save message ? MessageWidget - + Recommended Files Рекомендованные файлы @@ -15042,37 +13909,37 @@ Do you want to save message ? Скачать все рекомендованные файлы - + Subject: Тема: - + From: Из: - + To: В: - + Cc: Копия: - + Bcc: Невидимая копия: - + Tags: Метки: - + Reply Ответ @@ -15112,7 +13979,7 @@ Do you want to save message ? - + Send Invite Послать приглашение @@ -15164,7 +14031,7 @@ Do you want to save message ? - + Confirm %1 as friend Установить соединение с %1 @@ -15174,12 +14041,12 @@ Do you want to save message ? Добавить %1 в моё окружение - + View source - + No subject Без темы @@ -15189,17 +14056,22 @@ Do you want to save message ? Скачать - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -15209,21 +14081,23 @@ Do you want to save message ? - Send invite? - Послать приглашение + + Show less + - Do you really want send a invite with your Certificate? - Отправить приглашение с вашим сертификатом? + + Show more + - + Download all Скачать всё - + Print Document Распечатать документ @@ -15238,12 +14112,12 @@ Do you want to save message ? HTML-файлы (*.htm *.html);;Все файлы (*) - + Load images always for this message Загружать изображения всегда для этого сообщения - + Hide the attachment pane Скрыть панель вложений @@ -15265,42 +14139,6 @@ Do you want to save message ? Compose Составить - - Reply to selected message - Ответить на сообщение - - - Reply - Ответ - - - Reply all to selected message - Ответить всем на данное сообщение - - - Reply all - Ответить всем - - - Forward selected message - Переслать выбранные сообщения - - - Forward - Вперёд - - - Remove selected message - Удалить выделенное сообщение - - - Delete - Удалить - - - Print selected message - Напечатать данное сообщение - Print @@ -15379,7 +14217,7 @@ Do you want to save message ? MessagesDialog - + New Message Новое сообщение @@ -15389,60 +14227,16 @@ Do you want to save message ? Составить - Reply to selected message - Ответить на сообщение - - - Reply - Ответ - - - Reply all to selected message - Ответить всем на выделенное сообщение - - - Reply all - Ответить всем - - - Forward selected message - Переслать выбранные сообщения - - - Foward - Переслать - - - Remove selected message - Удалить выделенное сообщение - - - Delete - Удалить - - - Print selected message - Напечатать данное сообщение - - - Print - Печать - - - Display - Показать - - - + - - + + Tags Метки - - + + Inbox Входящие @@ -15472,21 +14266,17 @@ Do you want to save message ? Корзина - + Total Inbox: Все входящие: - Folders - Папки - - - + Quick View Быстрый просмотр - + Print... Печать... @@ -15496,26 +14286,6 @@ Do you want to save message ? Print Preview Предварительный просмотр - - Buttons Icon Only - Только кнопки - - - Buttons Text Beside Icon - Текст рядом с кнопкой - - - Buttons with Text - Кнопки с текстом - - - Buttons Text Under Icon - Текст под кнопками - - - Set Text Under Icon - Установить текст под кнопкой - Save As... @@ -15537,7 +14307,7 @@ Do you want to save message ? Переслать сообщение - + Subject Тема @@ -15547,7 +14317,7 @@ Do you want to save message ? От - + Date Дата @@ -15557,39 +14327,7 @@ Do you want to save message ? Содержимое - Click to sort by attachments - Сортировка по вложенным файлам - - - Click to sort by subject - Сортировка по темам - - - Click to sort by read - Сортировка по прочитанным сообщениям - - - Click to sort by from - Сортировка по отправителю - - - Click to sort by date - Сортировка по дате - - - Click to sort by tags - Сортировка по меткам - - - Click to sort by star - Сортировка по звёздам - - - Forward selected Message - Переслать выбранное сообщение - - - + Search Subject Поиск темы @@ -15598,6 +14336,11 @@ Do you want to save message ? Search From Поиск отправителя + + + Search To + + Search Date @@ -15624,14 +14367,14 @@ Do you want to save message ? Поиск вложений - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Сообщения</h1> <p>В RetroShare имеется собственный почтовый сервис. Вы можете отправлять/получать письма в пределах доверенного окружения.</p> <p>Благодаря глобальной системе маршрутизации данных, возможна рассылка писем другим участникам сети. Эти сообщения всегда подвергаются шифрованию и передаются адресату через промежуточные узлы сети. </p> <p>Для надёжной идентификации отправителя рекомендуется криптографически подписывать сообщения, используя the <img width="16" src=":/images/stock_signature_ok.png"/> кнопку в редакторе сообщений. Сообщения удалённым пользователям остаются в папке "Исходящие" до тех пор, пока не будет получено подтверждение в получении.</p> <p>Почтовый сервис RetroShare может быть использован для передачи ссылок на файлы или рекомендаций по включению в круг доверенных, что укрепит вашу сеть, а также для откликов на объявления в каналах.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + - + Starred - Отмечено звездой + @@ -15705,7 +14448,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -15719,7 +14462,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -15734,38 +14477,33 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts Черновики - + No Box selected. - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - Нет оценённых сообщений. Оценка сообщений присваивает им специальный статус для последующего удобного поиска и ранжирования. Чтобы оценить сообщение щёлкните на звезду серого цвета рядом с ним. - - - No system messages available. - Системные сообщения отсутствуют. - - + To - Кому + Кому - Click to sort by to - Нажмите, чтобы отсортировать по получателю - - - This message goes to a distant person. - Это сообщение будет отправлено удалённому участнику. - - - + @@ -15773,26 +14511,6 @@ Do you want to save message ? Total: Всего: - - Messages - Почта - - - Click to sort by signature - Нажмите, чтобы отсортировать по подписи - - - This message was signed and the signature checks - Это сообщение было подписано и подпись проверена - - - This message was signed but the signature doesn't check - Это сообщение было подписано, но подпись не была проверена - - - This message comes from a distant person. - Это сообщение пришло от удалённых лиц. - Mail @@ -15820,7 +14538,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + Сохранить изображение + + + + Copy image + + + + Paste as plain text Вставить как простой текст @@ -15874,7 +14602,7 @@ Do you want to save message ? - + Expand Развернуть @@ -15884,7 +14612,7 @@ Do you want to save message ? Удалить объект - + from от @@ -15919,18 +14647,10 @@ Do you want to save message ? Ожидающее сообщение - + Hide Спрятать - - Send invite? - Послать приглашение - - - Do you really want send a invite with your Certificate? - Отправить приглашение с вашим сертификатом? - NATStatus @@ -16068,7 +14788,7 @@ Do you want to save message ? Идентификатор участника - + Remove unused keys... Удалить неиспользуемые ключи... @@ -16078,7 +14798,7 @@ Do you want to save message ? - + Clean keyring Чистый массив ключей @@ -16096,7 +14816,13 @@ Notes: Your old keyring will be backed up. При удалении может произойти сбой, если на одном компьютере запущено несколько экземпляров RetroShare. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info Информация о массиве ключей @@ -16132,18 +14858,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. Несоответствие данных в хранилище ключей. Вероятнее всего, это ошибка. Пожалуйста, свяжитесь с разработчиками. - - - Export/create a new node - Экспортировать/создать новый узел - Trusted keys only Только доверенные ключи - + Search name Поиск по имени @@ -16153,12 +14874,12 @@ For security, your keyring was previously backed-up to file Поиск идентификатора участника - + Profile details... Сведения о профиле... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -16167,13 +14888,6 @@ Reported error: Сообщение о ошибке: - - NetworkPage - - Network - Сеть - - NetworkView @@ -16200,107 +14914,107 @@ Reported error: NewFriendList - + Offline Friends - + Друзья офлайн Show Offline Friends - + Показать друзей офлайн Status - Статус + Статус Show status - + Показать статус - + Groups - Группы + Группы Show groups - + Показать группы export friendlist - Экспорт списка контактов + Экспорт списка контактов export your friendlist including groups - Экспорт списка контактов, включая информацию о группах + Экспорт списка контактов, включая информацию о группах import friendlist - Импорт списка контактов + Импорт списка контактов import your friendlist including groups - Импорт списка контактов, включая информацию о группах + Импорт списка контактов, включая информацию о группах - - + + Search - + Поиск - + ID - + - + Search ID - Поиск идентификатора + Поиск идентификатора Online friends on top - + Онлайн-друзья наверху - + Show Items - Показать... + Показать... - + Last contact - + Последний контакт IP - IP + IP - + Group - Группа + Группа Friend - + Друг Node - + Узел @@ -16310,126 +15024,126 @@ Reported error: Edit Group - Редактировать группу + Редактировать группу Remove Group - Удалить группу + Удалить группу Profile details - Сведения об узле + Сведения об узле Deny connections - + Запретить соединения Add to group - добавить в группу + добавить в группу Move to group - Переместить в группу + Переместить в группу Create new group - Создать новую группу + Создать новую группу Remove from group - + Удалить из группы Remove from all groups - Удалить из всех групп + Удалить из всех групп Chat - + Чат Send message to this node - Послать сообщение этому узлу + Послать сообщение этому узлу Node details - Сведения об узле + Сведения об узле Recommend this node to... - Рекомендовать этого участника... + Рекомендовать этого участника... Attempt to connect - Соединиться + Соединиться Copy certificate link - Скопировать ссылку сертификата + Скопировать ссылку сертификата Remove Friend Node - Удалить этого участника + Удалить этого участника Paste certificate link - Вставить ссылку на сертификат + Вставить ссылку на сертификат Expand all - Раскрыть всё + Раскрыть всё Collapse all - Свернуть всё + Свернуть всё - + Do you want to remove this node? - Вы хотите удалить этот узел? + Вы хотите удалить этот узел? Do you want to remove this Friend? - + Вы хотите удалить этот контакт? - + Done! - Готово! + Готово! Your friendlist is stored at: - Ваш список список контактов сохранён в: + Ваш список список контактов сохранён в: (keep in mind that the file is unencrypted!) - + (помните, что файл не зашифрован!) @@ -16437,32 +15151,32 @@ Reported error: Your friendlist was imported from: - Ваш список контактов импортирован из: + Ваш список контактов импортирован из: Done - but errors happened! - Выполнено, но с ошибками! + Выполнено, но с ошибками! at least one peer was not added - + как минимум один участник не добавлен at least one peer was not added to a group - + как минимум один участник не добавлен в группу Select file for importing your friendlist from - Выберите файл, в котором хранится список ваших контактов + Выберите файл, в котором хранится список ваших контактов @@ -16479,7 +15193,7 @@ at least one peer was not added to a group Error - Ошибка + Ошибка @@ -16527,11 +15241,7 @@ at least one peer was not added to a group NewsFeed - Log entries - Журнал - - - + Activity Stream @@ -16546,11 +15256,7 @@ at least one peer was not added to a group Очистить всё - This is a test. - Это проверка. - - - + Newest on top Новые наверху @@ -16560,20 +15266,12 @@ at least one peer was not added to a group Старые наверху - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;News Feed</h1> <p>The Log Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel and Forum posts</li> <li>New Channels and Forums you can subscribe to</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Новостная лента</h1> <p>Лента новостей отображает последние события вашей сети в порядке получения. Можно настроить какие виды событий отображать в журнале, нажав <b>Параметры</b>. </p> <p>События могут быть следующими: <ul> <li>попытка соединения (полезно для пополнения вашего окружения новыми доверенными участниками и отслеживания тех участников, которые пытаются к вам подключиться)</li> <li>появление сообщений в форумах и каналах</li> <li>появление новых форумов или каналов</li> <li>личные сообщения от ваших контактов</li> </ul> </p> - - - Log - Журнал - - - + Activity @@ -16628,10 +15326,6 @@ at least one peer was not added to a group Blogs Блоги - - Security - Безопасность - @@ -16653,10 +15347,6 @@ at least one peer was not added to a group Message Сообщение - - Connect attempt - Попытка соединения - @@ -16673,10 +15363,6 @@ at least one peer was not added to a group Ip security IP-безопасность - - Log - Журнал - Friend Connected @@ -16687,10 +15373,6 @@ at least one peer was not added to a group Circles Круги - - Links - Публикации - Activity @@ -16743,26 +15425,6 @@ at least one peer was not added to a group Chat rooms Чат-комнаты - - Chat Rooms - Чаты - - - Count occurrences of my current identity - Подсчёт нахождений моей текущей личности - - - Count occurrences of any of the following texts (separate by newlines): - Подсчёт нахождений любых нижеследующих фрагментов текста (каждый с новой строки): - - - Checked, if the identity and the text above occurrences must be in the same case to trigger count. - Отметьте, если для подсчёта должны одновременно присутствовать и личность, и текст выше. - - - Case sensitive - Учитывать регистр - Position @@ -16838,24 +15500,16 @@ at least one peer was not added to a group Disable All Toaster temporarily Временно отключить все всплывающие уведомления - - Feed - Канал - Systray Панель уведомлений - - Count all unread messages - Подсчёт всех непрочитанных сообщений - NotifyQt - + Passphrase required Требуется ключевая фраза @@ -16875,12 +15529,12 @@ at least one peer was not added to a group Неверный пароль! - + Please enter your Retroshare passphrase Пожалуйста, введите ваш пароль для PGP-ключа - + Unregistered plugin/executable Незарегистрированный плагин/исполняемый файл. @@ -16895,19 +15549,7 @@ at least one peer was not added to a group Пожалуйста, проверьте ваши системные часы. - Examining shared files... - Проверка файлов, открытых к доступу... - - - Hashing file - Хеширование файла - - - Saving file index... - Сохранение списка файлов... - - - + Test Тест @@ -16918,17 +15560,19 @@ at least one peer was not added to a group + Unknown title Неизвестный заголовок - + + Encrypted message Шифрованное сообщение - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). Для надлежащей работы чата требуется, чтобы системное время компьютера было точным. Пожалуйста, проверьте его. (Смещение системного времени в несколько минут может нарушить общение с другими участниками сети.) @@ -16936,7 +15580,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online Успешное соединение с узлом сети! @@ -16989,10 +15633,6 @@ at least one peer was not added to a group PGPKeyDialog - - Dialog - Диалоговое окно - Profile info @@ -17058,10 +15698,6 @@ at least one peer was not added to a group This profile has signed your own profile key Этот ключ подписан вашим собственным PGP-ключом - - Key signatures : - Ключ подписи: - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> @@ -17091,23 +15727,20 @@ p, li { white-space: pre-wrap; } PGP-ключ - - These options apply to all nodes of the profile: - Эти опции применяются для всех местоположений, привязанных к профилю: + + Friend options + - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> - <html><head/><body><p><span style=" font-size:10pt;">Механизм подписания ключей может оказаться полезным другим участникам сети, которые, добавляя чужой сертификат в своё окружение, имеют возможность посмотреть, кто подписал ключ в сертификате. Следует отметить, что подписание чужих ключей не является обязательным и не может быть впоследствии отменено. Поэтому подходите к вопросу подписания, взвесив все «за» и «против».</span></p></body></html> + + These options apply to all nodes of the profile: + Эти опции применяются для всех местоположений, привязанных к профилю: Keysigning: - - Sign PGP key - Подписать PGP-ключ - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -17144,12 +15777,7 @@ p, li { white-space: pre-wrap; } Вставить подписи - - Options - Параметры - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> <html><head/><body><p align="justify">RetroShare периодически проверяет папки ваших контактов, доступные вам к просмотру, на предмет наличия там интересующего вас файла. Если файл находится, в целях скачивания с контактом устанавливается прямое соединение – не через систему анонимных туннелей. В этом случае узел-источник из вашего окружения достоверно знает, что файл качаете именно вы – пользователь с конкретным сертификатом.</p><p align="justify">Чтобы исключить такого рода небезопасное поведение вашего клиент-сервера, снимите здесь галочку. Отметим, что прямое соединение всё равно установится, если вы напрямую выберете в открытой к просмотру папке файл для скачивания. Включение/отключение возможности прямого соединения при файлообмене применяется ко всем местоположениям одного узла.</p></body></html> @@ -17163,10 +15791,6 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this profile (e.g. when the message author is a signed identity that belongs to this profile). This can be used for instance to send files between your own nodes.</p></body></html> - - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> - <html><head/><body><p>Эта опция позволяет вам автоматически скачивать рекомендованный в сообщении файл, если само сообщение поступило от конкретного узла сети. Такой подход может оказаться весьма удобным, например, когда вы пересылаете файлы с одного узла, принадлежащего вам, на другой. Применяется ко всем местоположениям, привязанным к конкретному сертификату.</p></body></html> - Auto-download recommended files from this node @@ -17199,21 +15823,21 @@ p, li { white-space: pre-wrap; } кБ/с - - + + RetroShare RetroShare - - + + Error : cannot get peer details. Ошибка: не могу получить совокупность деталей. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) Предоставленный алгоритм ключа не поддерживается RetroShare @@ -17232,7 +15856,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Предупреждение: в настройках файлообмена вы запретили прямую загрузку. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. Уровень доверия является способом выразить доверие в этом ключе. Он не используется сторонним программным обеспечением, но может быть полезным для вас, чтобы запомнить хорошие/плохие ключи. @@ -17301,10 +15925,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Check the password! - - Maybe password is wrong - Может быть, неправильный пароль - You haven't set a trust level for this key. @@ -17312,12 +15932,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile Профиль RetroShare - + This is your own PGP key, and it is signed by : Это ваш собственный ключ PGP и он подписан: @@ -17343,7 +15963,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat Чат @@ -17364,7 +15984,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Удалить объект - + Name: Имя: @@ -17404,7 +16024,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Смещение времени: - + Write Message Написать сообщение @@ -17418,10 +16038,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Friend Connected Соединение установлено - - Connect Attempt - Попытка соединения - Connection refused by peer @@ -17460,17 +16076,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.Unknown - - Unknown Peer - Неизвестный участник - Hide Спрятать - + Send Message Отправить сообщение @@ -17522,10 +16134,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Chat with this person as... Инициировать чат с этим человеком от имени... - - Send message to this person - Послать сообщение - Invite to Circle @@ -17584,10 +16192,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p>Anyone in your contact list will automatically have a positive opinion if not set. This allows to automatically raise reputations of used nodes. </p></body></html> <html><head/><body><p>Если не указано иное, любому участнику из вашего окружения будет автоматически присвоена положительная репутация.</p></body></html> - - automatically give "Positive" opinion to my contacts - давать положительный голос каждому из моего окружения - use "positive" as the default opinion for contacts (instead of neutral) @@ -17645,13 +16249,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p>Для того, чтобы предотвратить активность заблокированных личностей в форумах или каналах, информация о них некоторое время должна храниться. После этого они &quot;удаляются&quot; из списка блокировки, скачиваются снова как незаблокированные и могут участвовать форумах, чатах и т.п.</p></body></html> - - PhotoCommentItem - - Form - Форма - - PhotoDialog @@ -17659,23 +16256,11 @@ Warning: In your File-Transfer option, you select allow direct download to No.PhotoShare PhotoShare - - Photo - Фото - TextLabel Текстовая метка - - Comment - Комментарий - - - Summary - Резюме - Album / Photo Name @@ -17736,14 +16321,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.... ... - - Add Comment - Добавить комментарий - - - Write a comment... - Напишите комментарий... - Album @@ -17814,10 +16391,6 @@ p, li { white-space: pre-wrap; } Create Album Создать альбом - - View Album - Просмотреть альбом - Edit Album Details @@ -17839,17 +16412,17 @@ p, li { white-space: pre-wrap; } Слайд-шоу - + My Albums Мои альбомы - + Subscribed Albums Подписанные альбомы - + Shared Albums Общие альбомы @@ -17879,7 +16452,7 @@ requesting to edit it! PhotoSlideShow - + Album Name Название альбома @@ -17938,19 +16511,19 @@ requesting to edit it! - - + + TextLabel Текстовая метка - + Posted by - + ago @@ -17986,12 +16559,12 @@ requesting to edit it! PluginItem - + TextLabel Текстовая метка - + Show more details about this plugin Показать подробности об этом плагине @@ -18137,60 +16710,6 @@ p, li { white-space: pre-wrap; } Plugin look-up directories Папки поиска плагинов - - Plugin disabled. Click the enable button and restart Retroshare - Плагин отключён. Нажмите кнопку "Включить" и перезапустите RetroShare - - - [disabled] - [отключено] - - - No API number supplied. Please read plugin development manual. - Нет номера API. Пожалуйста, прочитайте руководство по разработке плагинов. - - - [loading problem] - [проблема загрузки] - - - No SVN number supplied. Please read plugin development manual. - Нет номера SVN. Пожалуйста, прочитайте руководство по разработке плагинов. - - - Loading error. - Ошибка загрузки. - - - Missing symbol. Wrong version? - Пропущен символ. Неправильная версия? - - - No plugin object - Плагин отсутствует - - - Plugins is loaded. - Плагины загружены. - - - Unknown status. - Неизвестное состояние. - - - Check this for developing plugins. They will not -be checked for the hash. However, in normal -times, checking the hash protects you from -malicious behavior of crafted plugins. - Плагины, находящиеся в стадии разработки, требуют проверки. -Они не могут быть проверены по хэш-сумме, однако в обычной -ситуации проверка хэш-суммы защищает вас от злонамеренных -действий, осуществляемых подменёнными плагинами. - - - <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Plugins</h1> <p>Plugins are loaded from the directories listed in the bottom list.</p> <p>For security reasons, accepted plugins load automatically until the main Retroshare executable or the plugin library changes. In such a case, the user needs to confirm them again. After the program is started, you can enable a plugin manually by clicking on the "Enable" button and then restart Retroshare.</p> <p>If you want to develop your own plugins, contact the developpers team they will be happy to help you out!</p> - <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Plugins</h1><p>Плагины загружаются из каталогов, перечисленных в нижней части списка.</p><p>По соображениям безопасности, разрешённые плагины загружаются автоматически до главного исполняемого файла RetroShare или изменения библиотеки плагинов. В таком случае, пользователь должен подтвердить их снова. После запуска программы, вы можете включить плагин вручную, нажав на кнопку "Включить" и перезагрузить RetroShare.</p> <p>Если вы хотите разрабатывать свои собственные плагины, свяжитесь с командой Разработчиков, они будут рады помочь вам!</p> - Plugins @@ -18260,12 +16779,27 @@ malicious behavior of crafted plugins. Разместить окно сверху - + + Ban this person (Sets negative opinion) + Заблокировать этого участника (устанавливает отрицательную репутацию) + + + + Give neutral opinion + Установить нейтральное мнение + + + + Give positive opinion + Установить положительное мнение + + + Choose window color... - + Dock window @@ -18299,22 +16833,6 @@ malicious behavior of crafted plugins. Close conversation? - - The person you are talking to has deleted the secured chat tunnel. - Собеседник, с которым вы общались, удалил защищённый туннель чата. - - - The chat partner deleted the secure tunnel, messages will be delivered as soon as possible - Собеседник удалил защищённый туннель, сообщения будут доставлены как только появится возможность - - - Closing this window will end the conversation, notify the peer and remove the encrypted tunnel. - Закрытие этого окна приведёт к завершению разговора, уведомлению участника и удалению шифрованного туннеля. - - - Kill the tunnel? - Удалить тоннель? - PostedCardView @@ -18334,7 +16852,7 @@ malicious behavior of crafted plugins. Новый - + Vote up Голосовать "за" @@ -18354,8 +16872,8 @@ malicious behavior of crafted plugins. \/ - - + + Comments Комментарии @@ -18380,13 +16898,13 @@ malicious behavior of crafted plugins. - - + + Comment Комментарий - + Comments Комментарии @@ -18414,20 +16932,12 @@ malicious behavior of crafted plugins. PostedCreatePostDialog - Signed by: - Подписан: - - - Notes - Примечания - - - + Create a new Post - + RetroShare RetroShare @@ -18442,12 +16952,22 @@ malicious behavior of crafted plugins. - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File Загрузить файл изображения - + Post image @@ -18463,7 +16983,17 @@ malicious behavior of crafted plugins. - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -18473,23 +17003,7 @@ malicious behavior of crafted plugins. - Submit Post - Отправить сообщение - - - You are submitting a link. The key to a successful submission is interesting content and a descriptive title. - Вы отправляете ссылку. Ключ к успешной презентации — это интересное содержание и информативное название. - - - Submit - Отправить - - - Submit a new Post - Отправить новое сообщение - - - + Please add a Title Пожалуйста, добавьте заголовок @@ -18509,12 +17023,22 @@ malicious behavior of crafted plugins. - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -18529,7 +17053,7 @@ malicious behavior of crafted plugins. Отправить как - + Post @@ -18540,7 +17064,7 @@ malicious behavior of crafted plugins. Изображение - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -18550,7 +17074,7 @@ malicious behavior of crafted plugins. Название - + Link Ссылка @@ -18558,44 +17082,12 @@ malicious behavior of crafted plugins. PostedDialog - Posted Links - Опубликованное - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Posted</h1> <p>The posted service allows you to share internet links, that spread among Retroshare nodes like forums and channels</p> <p>Links can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Posted links are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Ссылки</h1> <p>Сервис «Ссылки» даёт Вам возможность поделиться с окружением полезными ссылками, информация о которых будет распространяться по сети как форумы ⇥ каналы</p> ⇥ <p>Ссылки могут комментироваться подписчиками. Система продвижения сообщений даёт возможность ⇥ информировать о важных ссылках.</p> ⇥ <p>Ограничения на тип и характер публикуемых ссылок отсутствует; будьте осторожны при переходах по ним.</p> <р> Размещенные ссылки удаляются через %1 месяца. </p> - - - Create Topic - Создать тему - - - My Topics - Мои темы - - - Subscribed Topics - Подписка на темы - - - Popular Topics - Популярные темы - - - Other Topics - Другие темы - - - Links - Публикации - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -18629,31 +17121,7 @@ malicious behavior of crafted plugins. PostedGroupDialog - Posted Topic - Опубликованная тема - - - Add Topic Admins - Добавить администраторов темы - - - Select Topic Admins - Выбрать администраторов темы - - - Create New Topic - Создать новую тему - - - Edit Topic - Изменить тему - - - Update Topic - Обновить тему - - - + Create New Board @@ -18691,7 +17159,17 @@ malicious behavior of crafted plugins. PostedGroupItem - + + Last activity + + + + + TextLabel + Текстовая метка + + + Subscribe to Posted Подписаться на сообщения @@ -18707,7 +17185,7 @@ malicious behavior of crafted plugins. - + Expand Раскрыть @@ -18722,24 +17200,17 @@ malicious behavior of crafted plugins. - Posted Description - Описание канала ссылок - - - Loading - Загрузка - - - New Posted - Новые сообщения - - - + Loading... - + + Never + Никогда + + + New Board @@ -18752,22 +17223,18 @@ malicious behavior of crafted plugins. PostedItem - + 0 0 - Site - Сайт - - - - + + Comments Комментарии - + Copy RetroShare Link Скопировать ссылку RetroShare @@ -18778,12 +17245,12 @@ malicious behavior of crafted plugins. - + Comment Комментарий - + Comments Комментарии @@ -18793,7 +17260,7 @@ malicious behavior of crafted plugins. <p><font color="#ff0000"><b>Автор этого сообщения (личность %1) заблокирован.</b> - + Click to view Picture @@ -18803,21 +17270,17 @@ malicious behavior of crafted plugins. - + Vote up Голосовать "за" - + Vote down Голосовать "против" - \/ - \/ - - - + Set as read and remove item Установить как чтение и удаление элемента @@ -18827,7 +17290,7 @@ malicious behavior of crafted plugins. Новый - + New Comment: Новый комментарий: @@ -18837,7 +17300,7 @@ malicious behavior of crafted plugins. Значение комментария - + Name Имя @@ -18878,77 +17341,10 @@ malicious behavior of crafted plugins. Текстовая метка - + Loading Загрузка - - By - По - - - - PostedListWidget - - Form - Форма - - - Hot - Горячий - - - New - Новый - - - Top - В начало списка - - - Today - Сегодня - - - Yesterday - Вчера - - - This Week - На этой неделе - - - This Month - В этом месяце - - - This Year - В этом году - - - Submit a new Post - Отправить новое сообщение - - - Next - Следующий - - - RetroShare - RetroShare - - - Please create or choose a Signing Id before Voting - Пожалуйста, создайте или выберите идентификатор подписавшего до голосования - - - Previous - Предыдущий - - - 1-10 - 1-10 - PostedListWidgetWithModel @@ -18968,7 +17364,17 @@ malicious behavior of crafted plugins. - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -18978,15 +17384,15 @@ malicious behavior of crafted plugins. Администратор: - + - + unknown - + Distribution: Распространение: @@ -18996,42 +17402,42 @@ malicious behavior of crafted plugins. - + Created - + TextLabel Текстовая метка - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts Сообщения - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -19051,7 +17457,7 @@ malicious behavior of crafted plugins. Горячий - + Search @@ -19081,17 +17487,17 @@ malicious behavior of crafted plugins. - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -19106,12 +17512,17 @@ malicious behavior of crafted plugins. Пусто - + Copy RetroShare Link Скопировать ссылку RetroShare - + + Copy http Link + + + + Show author in People tab @@ -19121,27 +17532,31 @@ malicious behavior of crafted plugins. - + + information информация - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -19156,7 +17571,7 @@ malicious behavior of crafted plugins. Подписаться - + Never Никогда @@ -19208,12 +17623,12 @@ malicious behavior of crafted plugins. Restricted to members of circle " - + Ограничено для членов круга " Restricted to members of circle - + Ограничено для членов круга @@ -19230,6 +17645,16 @@ malicious behavior of crafted plugins. No Channel Selected Не выбраны каналы + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -19238,14 +17663,6 @@ malicious behavior of crafted plugins. Tabs Вкладки - - Open each topic in a new tab - Открывать каждое сообщение в новой вкладке - - - Links - Публикации - Open each board in a new tab @@ -19259,10 +17676,6 @@ malicious behavior of crafted plugins. PostedUserNotify - - Posted - Сообщения - Board Post @@ -19331,25 +17744,17 @@ malicious behavior of crafted plugins. Управление профилями - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Выберите ключ узла Retroshare из приведённого ниже списка, который будет использоваться на другом компьютере, и нажмите "Экспортировать выбранный ключ".</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Чтобы создать новое местоположение на другом компьютере, выберите "Новый профиль/узел" в окне входа в систему. Оттуда вы сможете импортировать файл ключа и создать для него новое местоположение. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Создание нового узла с тем же ключом позволяет доверенным узлам принимать вас автоматически.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> + @@ -19460,7 +17865,7 @@ and use the import button to load it ProfileWidget - + Edit status message Изменить ваш статус @@ -19476,7 +17881,7 @@ and use the import button to load it Управление профилями - + Public Information Публичная информация @@ -19511,12 +17916,12 @@ and use the import button to load it Подключён с: - + Other Information Прочее - + My Address Мой адрес @@ -19560,51 +17965,27 @@ and use the import button to load it PulseAddDialog - Post From: - Сообщение от: - - - Account 1 - Учётная запись 1 - - - Account 2 - Учётная запись 2 - - - Account 3 - Учётная запись 3 - - - + Add to Pulse Добавить в Pulse - filter - фильтр - - - URL Adder - Ссылка добавлена - - - + Display As Показать как - + URL URL - + GroupLabel - + IDLabel @@ -19614,12 +17995,12 @@ and use the import button to load it Из: - + Head - + Head Shot @@ -19649,13 +18030,13 @@ and use the import button to load it Отрицательное мнение - - + + Whats happening? - + @@ -19667,12 +18048,22 @@ and use the import button to load it - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -19681,17 +18072,13 @@ and use the import button to load it Cancel Отмена - - Post Pulse to Wire - Сообщение-импульс для Телеграфа - Post - + Reply to Pulse @@ -19706,34 +18093,24 @@ and use the import button to load it - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - От - - - Date - Дата - - - ... - ... + + Load Picture File + Загрузить файл изображения @@ -19744,7 +18121,7 @@ and use the import button to load it Форма - + @@ -19763,7 +18140,7 @@ and use the import button to load it PulseReply - + icn @@ -19773,7 +18150,7 @@ and use the import button to load it - + REPLY @@ -19800,7 +18177,7 @@ and use the import button to load it - + FOLLOW @@ -19810,7 +18187,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -19830,7 +18207,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -19946,7 +18323,7 @@ and use the import button to load it - + FOLLOW @@ -19954,37 +18331,42 @@ and use the import button to load it PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -20016,7 +18398,7 @@ and use the import button to load it - + FOLLOW @@ -20024,8 +18406,8 @@ and use the import button to load it QObject - - + + Confirmation Подтверждение @@ -20296,12 +18678,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace Сведения об участнике - + File Request canceled Запрос на файл отменён - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. Эта версия RetroShare использует OpenPGP-SDK. В качестве побочного эффекта, она не использует системное публичное PGP хранилище, но имеет своё собственное хранилище, которое используется всеми экземплярами RetroShare. <br><br>Похоже, что вы не имеете такое хранилище, хотя ключи PGP упоминаются учётными записями RetroShare, вероятно, потому, что вы только что обновились до этой новой версии программного обеспечения. @@ -20332,7 +18714,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace Произошла непредвиденная ошибка. Пожалуйста, сообщите 'RsInit::InitRetroShare unexpected return code %1'. - + Cannot start Tor Manager! Не удаётся запустить менеджер Tor! @@ -20368,7 +18750,7 @@ The error reported is:" Не удалось запустить скрытую службу. - + Multiple instances Множественные копии @@ -20390,6 +18772,26 @@ The error reported is:" Файл блокировки: + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -20410,14 +18812,6 @@ The error reported is:" End-to-end encrypted conversation established - - Tunnel is pending... Messages will be delivered as soon as possible - Туннель находится в ожидании... Сообщения будут доставлены как можно скорее - - - Secured tunnel is working. Messages are delivered immediately! - Защищённый туннель функционирует. Сообщения доставляются немедленно! - The collection file %1 could not be opened. @@ -20480,7 +18874,7 @@ Reported error is: Транзитный трафик - + You appear to have nodes associated to DSA keys: Похоже, у вас имеются узлы, привязанные к DSA-ключам: @@ -20490,7 +18884,7 @@ Reported error is: К сожалению, на данный момент DSA-ключи не поддерживаются криптоплатформой RetroShare. Все эти узлы не будут задействованы. - + enabled включено @@ -20500,7 +18894,7 @@ Reported error is: отключено - + Move IP %1 to whitelist Перенести IP %1 в белый список @@ -20516,7 +18910,7 @@ Reported error is: - + %1 seconds ago %1 секунд назад @@ -20584,7 +18978,7 @@ Security: no anonymous IDs Безопасность: анонимные участники запрещены - + Join chat room Присоединиться к чат-комнате @@ -20612,7 +19006,7 @@ Security: no anonymous IDs не получается обработать файл XML! - + Indefinitely Неограниченно @@ -20792,13 +19186,29 @@ Security: no anonymous IDs Ban list + + + Name + Имя + + Node + + + + + Address + Адрес + + + + Status Статус - + NXS @@ -20991,10 +19401,6 @@ Security: no anonymous IDs Click to resume the hashing process Нажмите, чтобы возобновить процесс хеширования - - <p>This certificate contains: - <p>Этот сертификат содержит: - Idle @@ -21045,6 +19451,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -21184,7 +19602,7 @@ p, li { white-space: pre-wrap; } - + Network Wide Обширная сеть @@ -21354,7 +19772,7 @@ p, li { white-space: pre-wrap; } Форма - + The loading of embedded images is blocked. Блокируется загрузка внедрённых изображений. @@ -21367,7 +19785,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default Разрешено по умолчанию @@ -21540,12 +19958,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + Сохранить изображение + + + + Copy image + + + + Document source @@ -21553,12 +19981,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options Настройка древовидного представления - + Show Header @@ -21588,14 +20016,6 @@ p, li { white-space: pre-wrap; } Show column … - - Show column... - Показать столбец... - - - [no title] - [без заголовка] - RatesStatus @@ -22258,7 +20678,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name Имя @@ -22379,7 +20799,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name Имя @@ -22399,7 +20819,7 @@ If you believe it is correct, remove the corresponding line from the file and re IP - + Profile ID @@ -22457,7 +20877,7 @@ prevents the message to be forwarded to your friends. Сообщения не будут перенаправляться вашему окружению. - + [ ... Redacted message ... ] [ ... Отредактированное сообщение ... ] @@ -22471,11 +20891,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - [ ... Пропущенное сообщение ... ] - RsMessageModel @@ -22489,6 +20904,11 @@ prevents the message to be forwarded to your friends. From От + + + To + + Subject @@ -22511,13 +20931,18 @@ prevents the message to be forwarded to your friends. - Click to sort by read - Сортировка по прочитанным сообщениям + Click to sort by read status + - Click to sort by from - Сортировка по отправителю + Click to sort by author + + + + + Click to sort by destination + @@ -22540,7 +20965,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -22561,7 +20988,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. Сбрасывает ВСЕ сохранённые настройки RetroShare. @@ -22622,7 +21049,7 @@ prevents the message to be forwarded to your friends. Настройки локализации RetroShare. - + Unable to open log file '%1': %2 Не получается открыть файл журнала '%1': %2 @@ -22643,11 +21070,7 @@ prevents the message to be forwarded to your friends. Не удалось создать каталог данных: %1 - Revision - Редакция - - - + opmode Расширенный режим @@ -22677,7 +21100,7 @@ prevents the message to be forwarded to your friends. Информация об использовании графического интерфейса RetroShare - + Invalid language code specified: Указан недействительный код языка: @@ -22695,7 +21118,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. Ошибка доступа к реестру, возможно необходимы права администратора. @@ -22712,12 +21135,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) Введите ключевое слово (не менее 3 символов) - + Start Search Начать поиск @@ -22778,7 +21201,7 @@ prevents the message to be forwarded to your friends. Очистить - + KeyWords Ключевые слова @@ -22793,7 +21216,7 @@ prevents the message to be forwarded to your friends. Поиск идентификатора - + Filename Имя файла @@ -22893,23 +21316,23 @@ prevents the message to be forwarded to your friends. Скачать выделенное - + File Name Имя файла - + Download Скачать - + Copy RetroShare Link Скопировать ссылку RetroShare - + Send RetroShare Link Отправить RetroShare-ссылку @@ -22919,7 +21342,7 @@ prevents the message to be forwarded to your friends. - + Download Notice Скачать @@ -22956,7 +21379,7 @@ prevents the message to be forwarded to your friends. Удалить всё - + Folder Папка @@ -22967,17 +21390,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) Новая RetroShare-ссылка - + Open Folder Открыть папку - + Create Collection... Создание коллекции... @@ -22997,7 +21420,7 @@ prevents the message to be forwarded to your friends. Загрузить из файла коллекции... - + Collection Коллекция @@ -23005,7 +21428,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details Сведения об участнике @@ -23021,22 +21444,22 @@ prevents the message to be forwarded to your friends. Удалить объект - + IP address: IP-адрес: - + Peer ID: Идентификатор участника: - + Location: Расположение: - + Peer Name: Имя участника: @@ -23053,7 +21476,7 @@ prevents the message to be forwarded to your friends. Скрыть - + but reported: но сообщил: @@ -23078,8 +21501,8 @@ prevents the message to be forwarded to your friends. <p>Это IP-адрес, к которому, как утверждает ваш контакт, он подключён. Если вы только что изменили свой IP-адрес, можно не обращать ванимания на это предупреждение. Если же нет, это означает, что подключение к этому контакту перенаправляется неким промежуточным узлом, что является достаточно подозрительным.</p> - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> <html><head/> <body><p>Это предупреждение показывается, чтобы защитить вас от атаки типа «перенаправление трафика». В этом случае контакт, к которому вы подключены не увидит ваш внешний IP-адрес, но увидит IP-адрес злоумышленника. </p> <p><br/></p> <p>Однако, если вы только что изменили IP-адрес по какой-либо причине (некоторые провайдеры регулярно меняют IP-адреса) это предупреждение просто говорит вам, что друг подключился на новый IP-адрес, прежде чем RetroShare поняла, что IP-адрес изменился. Ничего страшного в этом случае нет.</p><p><br/></p><p>Ложные предупреждения можно легко отключить, составив белый список ваших собственных IP-адресов (например, диапазон вашего провайдера) или полностью отключить эти предупреждения в опции -&gt; Уведомления -&gt; Журнал.</p></body></html> @@ -23087,7 +21510,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare предлагает установить с вами соединение @@ -23118,7 +21541,7 @@ prevents the message to be forwarded to your friends. - + Expand Развернуть @@ -23163,12 +21586,12 @@ prevents the message to be forwarded to your friends. Статус: - + Write Message Написать сообщение - + Connect Attempt Попытка соединения @@ -23188,17 +21611,22 @@ prevents the message to be forwarded to your friends. Неизвестная попытка соединения (исходящая) - + Unknown Security Issue Неизвестная проблема безопасности - - A unknown peer + + SSL request - + + An unknown peer + + + + Unknown @@ -23208,11 +21636,7 @@ prevents the message to be forwarded to your friends. - Unknown Peer - Неизвестный участник - - - + Hide Спрятать @@ -23222,7 +21646,7 @@ prevents the message to be forwarded to your friends. Вы хотите удалить этот узел из вашего окружения? - + Certificate has wrong signature!! This peer is not who he claims to be. Сертификат имеет неправильную подпись!!! Этот участник — не тот, за кого он себя выдаёт. @@ -23232,12 +21656,12 @@ prevents the message to be forwarded to your friends. Утерян/повреждён сертификат. Не настоящий пользователь Retroshare. - + Certificate caused an internal error. Сертификат вызвал внутреннюю ошибку. - + Peer/node not in friendlist (PGP id= Участник / узел не находится в доверенном окружении (PGP iD = @@ -23296,12 +21720,12 @@ prevents the message to be forwarded to your friends. - + Local Address Локальный адрес - + NAT NAT @@ -23322,22 +21746,22 @@ prevents the message to be forwarded to your friends. Порт: - + Local network Локальная сеть - + External ip address finder Поисковик внешнего IP-адреса - + UPnP UPnP - + Known / Previous IPs: Известные/предыдущие IP-адреса: @@ -23350,21 +21774,16 @@ behind a firewall or a VPN. Если вы снимете этот флажок, RetroShare может определить ваш IP-адрес только при подключении к кому-нибудь. Этот флажок помогает в установлении соединений на начальном этапе, когда у вас мало контактов. Он также помогает, если вы находитесь за межсетевым экраном или используете VPN. - - Allow RetroShare to ask my ip to these websites: - Разрешить RetroShare спрашивать мой IP-адрес у этих сайтов: - - - - - + + + kB/s кБ/с - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. Диапазон доступных портов: от 1024 до 65535. Обычно порты ниже 1024 зарезервированы операционной системой. @@ -23374,23 +21793,46 @@ behind a firewall or a VPN. Диапазон доступных портов: от 1024 до 65535. Обычно порты ниже 1024 зарезервированы операционной системой. - + Onion Address Onion-адрес - + Discovery On (recommended) Обнаружение включено (рекомендуется) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. Tor был автоматически настроен Retroshare. Здесь не нужно ничего менять. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off Обнаружение выключено @@ -23400,7 +21842,7 @@ behind a firewall or a VPN. Скрытые - см. конфигурацию - + I2P Address Адрес I2P @@ -23425,41 +21867,95 @@ behind a firewall or a VPN. Входящие ОК - - + + + Proxy seems to work. Прокси функционирует. - + + I2P proxy is not enabled I2P-прокси не включён - - BOB is running and accessible - BOB работает и доступен + + SAMv3 is running and accessible + - BOB is not accessible! Is it running? - BOB недоступен! Он работает? + SAMv3 is not accessible! Is i2p running and SAM enabled? + - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - RetroShare использует BOB для создания %1 туннеля на %2:%3 (с именем %4) - -При изменении параметров (например, порта) используйте кнопки внизу, чтобы перезапустить BOB. - - + - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client клиентского @@ -23474,71 +21970,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. неизвестно - - - - BOB is processing a request - BOB обрабатывает запрос - - - - connectivity check - проверка подключения - - - - generating key - создание ключа - - - - starting up - запуск - - - - shuting down - завершение работы - - - - BOB is processing a request: %1 - BOB обрабатывает запрос: %1 - - - - BOB is broken - - BOB не функционирует - - - - BOB encountered an error: - - BOB столкнулся с ошибкой: - - - - BOB tunnel is running - BOB-туннель работает - - - - BOB is working fine: tunnel established - BOB работает нормально: туннель установлен - - - - BOB tunnel is not running - BOB-туннель не работает - - - - BOB is inactive: tunnel closed - BOB неактивен: туннель закрыт - - - + request a new server key Запрос нового ключа сервера @@ -23548,22 +21980,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. Загрузить ключ сервера из base64 - - stop BOB tunnel first to generate a new key - Чтобы создать новый ключ, сначала остановите туннель BOB - - - - stop BOB tunnel first to load a key - Чтобы загрузить ключ, сначала остановите туннель BOB - - - - stop BOB tunnel first to disable BOB - Чтобы отключить BOB, сначала остановите туннель BOB - - - + You are reachable through the hidden service. Вы доступны через скрытые службы. @@ -23577,12 +21994,12 @@ Also check your ports! Также проверьте порты. - + [Hidden mode] [Скрытый режим] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> <html><head/> <body><p>Это очищает список известных IP-адресов, что может оказаться полезным, если по какой-либо причине ваш список адресов содержит недопустимые/ошибочные/недействующие адреса, которые нежелательно передавать контактам из вашего окружения.</p></body></html> @@ -23592,7 +22009,7 @@ Also check your ports! Очистить - + Download limit (KB/s) Лимит загрузки (КБ/с) @@ -23607,24 +22024,24 @@ Also check your ports! Лимит отдачи (КБ/с) - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> <html><head/> <body><p>Лимит выгрузки охватывает всё программное обеспечение. Слишком маленький лимит выгрузки в конечном итоге может заблокировать службы с низким приоритетом (форумы, каналы). Минимально рекомендуемое значение - 50 КБ/с.</p></body></html> - + WARNING: These values don't take into account the Relays. ПРЕДУПРЕЖДЕНИЕ: Эти значения не учитывают трансляторы. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -23641,17 +22058,7 @@ Socks-прокси I2P: см. http://127.0.0.1:7657/i2ptunnelmgr для наст Вы можете подключиться к скрытым службам, даже если используете стандартный узел, так почему бы не настроить Tor и/или I2P? - - Automatic I2P/BOB - Автоиспользование I2P/BOB - - - - Enable I2P BOB - changing this requires a restart to fully take effect - Включить I2P BOB (изменение этого параметра требует перезагрузки для вступления в силу) - - - + enableds advanced settings Появляются дополнительные настройки @@ -23661,12 +22068,7 @@ Socks-прокси I2P: см. http://127.0.0.1:7657/i2ptunnelmgr для наст Расширенный режим - - I2P Basic Open Bridge - Основной открытый мост I2P - - - + I2P Instance address Адрес экземпляра I2P @@ -23676,17 +22078,7 @@ Socks-прокси I2P: см. http://127.0.0.1:7657/i2ptunnelmgr для наст 127.0.0.1 - - I2P proxy port - Порт I2P-прокси - - - - BOB accessible - BOB доступен - - - + Address Адрес @@ -23726,7 +22118,7 @@ Socks-прокси I2P: см. http://127.0.0.1:7657/i2ptunnelmgr для наст Загрузить ключ - + Start Запуск @@ -23741,12 +22133,7 @@ Socks-прокси I2P: см. http://127.0.0.1:7657/i2ptunnelmgr для наст Стоп - - BOB status - Статус BOB - - - + Incoming Входящие @@ -23793,7 +22180,32 @@ If you have issues connecting over Tor check the Tor logs too. Если у вас есть проблемы с подключением через Tor, не забудьте проверить также журналы Tor. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay Транслятор @@ -23848,7 +22260,7 @@ If you have issues connecting over Tor check the Tor logs too. Всего: - + Warning: This bandwidth adds up to the max bandwidth. Предупреждение: эта пропускная способность увеличивает максимальную ширину канала. @@ -23873,7 +22285,7 @@ If you have issues connecting over Tor check the Tor logs too. Удалить сервер - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -23887,7 +22299,7 @@ If you have issues connecting over Tor check the Tor logs too. Сеть - + IP Filters IP-фильтры @@ -23910,7 +22322,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status Статус @@ -23970,17 +22382,28 @@ If you have issues connecting over Tor check the Tor logs too. Добавить в белый список - + Hidden Service Configuration Настройка скрытых служб - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>Здесь указан socks-порт службы Tor-прокси. Ваш узел RetroShare будет использовать этот порт для соединения со</p><p>скрытыми узлами других пользователей. Если служба Tor установлена и правильно настроена, то индикатор слева должен быть зелёного цвета. </p><p>Отметим: это не означает, что весь ваш трафик транслируется через сеть Tor. Такое утверждение справедливо </p><p>только для скрытых узлов, с которыми вы соединены, или в случае, когда у вас самого скрытый узел.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>Если служба Tor установлена и правильно настроена, то индикатор слева должен быть зелёного цвета. </p><p>Отметим: это не означает, что весь ваш трафик транслируется через сеть Tor. Такое утверждение справедливо </p><p>только для скрытых узлов, с которыми вы соединены, или в случае, когда у вас самого скрытый узел.</p></body></html> @@ -23996,18 +22419,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>Если служба i2p установлена и правильно настроена, то индикатор слева должен быть зелёного цвета. </p><p>Это не означает, что весь ваш трафик транслируется через сеть i2p. Такое утверждение справедливо </p><p>только для скрытых узлов, с которыми вы соединены, или в случае, когда у вас самого скрытый узел.</p></body></html> - + I2P outgoing Okay Исходящие I2P ОК - + Service Address Адрес службы @@ -24042,12 +22465,12 @@ If you have issues connecting over Tor check the Tor logs too. Пожалуйста, заполните адрес службы - + IP Range Диапазон IP-адресов - + Reported by DHT for IP masquerading Получено из DHT; попытка подмены IP-адреса @@ -24070,22 +22493,22 @@ If you have issues connecting over Tor check the Tor logs too. Добавлен вами - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> <html><head/> <body><p>IP адреса из белого списка собраны из следующих источников: IP адреса поступившие вручную при обмене сертификатами, диапазоны IP, введённые вами в этом окне или в окне безопасности элементов канала.</p> <p>Поведение по умолчанию для Retroshare: (1) всегда разрешать подключение к участникам с IP из белого списка, даже если этот IP также занесён в чёрный список; (2) дополнительно требуется, чтобы IP адрес находился в белом списке. Вы можете изменить это поведение для каждого участника в окне "Подробности" каждого узла Retroshare. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> <html><head/><body><p>DHT позволяет быстро соединяться с доверенными узлами, обрабатывая их поисковые запросы, что значительно упрощает процедуру установления соединения. Никакая информация на самом деле в DHT не хранится. Она используется только в качестве промежуточной системы, позволяющей бстрее установить соединение с другими узлами сети RetroShare.</p><p>Сервис обнаружения посылает информацию о местоположении и идентификаторы доверенных узлов всем подключенным участникам, чтобы помочь им в установлении соединения. Найденые контакты не соединяются автоматически; чтобы иметь возможность соединиться, обе стороны должны добавить сертификаты друг друга вручную. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> <html><head/> <body><p>Индикатор становится зелёным, как только Retroshare удаётся получить свой собственный IP от веб-сайтов перечисленных ниже, если вы включили это действие. Retroshare также будет использовать другие средства, чтобы узнать свой IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> <html><head/> <body><p>Этот список автоматически заполняется информацией, собранной из нескольких источников: ретрансляция участников, информация о которых получена из DHT, диапазоны IP-адресов, введённые вами, а также диапазоны IP-адресов сообщённые вашими друзьями. Параметры по умолчанию должны защитить вас от крупномасштабной ретрансляции трафика.</p> <p>Автоматический подбор ретранслирующих IP-адресов может привести к тому, что IP-адреса контактов из вашего окружения будут добавлены в чёрный список. В этом случае, используйте контекстное меню, чтобы вернуть их в белый список.</p></body></html> @@ -24120,26 +22543,22 @@ If you have issues connecting over Tor check the Tor logs too. Автоматически запретить диапазон DHT по маске IP, начиная с - + Outgoing Manual Tor/I2P Ручная настройка исходящих Tor/I2P - - <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. <br/>If you prefer to use BOB to automatically manage I2P check the other tab.</p></body></html> - <html><head/><body><p>Настройте здесь свои socks-прокси Tor и I2P. <br/>Если вы предпочитаете использовать BOB для автоматического управления I2P, откройте соседнюю вкладку.</p></body></html> - Tor Socks Proxy Socks-прокси Tor - + Tor outgoing Okay Исходящие Tor OK - + Tor proxy is not enabled Tor-прокси не включён @@ -24219,7 +22638,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with проверить участников, с которыми вы хотите поделиться приватным ключом @@ -24229,12 +22648,12 @@ If you have issues connecting over Tor check the Tor logs too. Доступен доверенному узлу - + Share Предоставить общий доступ - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. Вы имеете возможность оповестить друзей о канале, предоставив им право публикации. @@ -24254,7 +22673,7 @@ Select the Friends with which you want to Share your Channel. Менеджер доступа к папкам - + Shared directory Доступная папка @@ -24274,17 +22693,17 @@ Select the Friends with which you want to Share your Channel. Доступно - + Add new Добавить новую - + Cancel Отмена - + Add a Share Directory Добавить папку для доступа @@ -24294,7 +22713,7 @@ Select the Friends with which you want to Share your Channel. Удалить - + Apply and close Применить @@ -24385,7 +22804,7 @@ Select the Friends with which you want to Share your Channel. Папка не найдена или неприменимое имя папки. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. Это список разделяемых папок. Вы можете добавлять или удалять папки, используя кнопки внизу. Когда вы открываете доступ к папке, всё её содержимое доступно к скачиванию. Вы можете отдельно установить флаги доступа к каждой из разделяемых папок. @@ -24393,7 +22812,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files Файлообмен @@ -24444,11 +22863,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files проверить файлы - + Download selected Скачать выделенное @@ -24458,7 +22882,7 @@ Select the Friends with which you want to Share your Channel. Скачать - + Copy retroshare Links to Clipboard Скопировать RetroShare-ссылки в буфер обмена @@ -24473,7 +22897,7 @@ Select the Friends with which you want to Share your Channel. Отправить RetroShare-ссылки - + Some files have been omitted Некоторые файлы были пропущены @@ -24489,7 +22913,7 @@ Select the Friends with which you want to Share your Channel. Рекомендации - + Create Collection... Создание коллекции... @@ -24514,7 +22938,7 @@ Select the Friends with which you want to Share your Channel. Загрузить из файла коллекции... - + Some files have been omitted because they have not been indexed yet. Некоторые файлы были пропущены, поскольку они ещё не были проиндексированы. @@ -24657,12 +23081,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration Загрузка параметров - + Create interface Создание интерфейса @@ -24686,7 +23110,7 @@ Select the Friends with which you want to Share your Channel. Запомнить пароль - + Log In Войти @@ -25041,7 +23465,7 @@ This choice can be reverted in settings. Статус сообщения - + Message: Сообщение: @@ -25286,7 +23710,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags Удалить все метки @@ -25322,12 +23746,15 @@ p, li { white-space: pre-wrap; } Настройка Tor... - + + Tor status: Статус Tor: - + + + Unknown Неизвестно @@ -25337,18 +23764,13 @@ p, li { white-space: pre-wrap; } Не запущен - - Hidden service address: - Адрес скрытой службы: + + Hidden address: + - - Tor bootstrap status: - Статус начальной загрузки Tor: - - - - + + Not set Не задан @@ -25358,12 +23780,57 @@ p, li { white-space: pre-wrap; } Onion-адрес: - + + Error + Ошибка + + + + Not connected + не соединён + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path Убедитесь, что Tor находится в одной из папок, доступных для запуска исполняемых файлов - + [Waiting for Tor...] [Ожидание Tor...] @@ -25371,21 +23838,17 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor Tor - - <p>This version of Retroshare uses Tor to connect to your friends.</p> - <p>Эта версия Retroshare использует Tor для подключения к вашим доверенным узлам.</p> - <p>This version of Retroshare uses Tor to connect to your trusted nodes.</p> - + Tor is currently offline Tor сейчас недоступен @@ -25396,11 +23859,12 @@ p, li { white-space: pre-wrap; } + No tor configuration Нет конфигурации Tor - + Tor proxy is OK @@ -25428,7 +23892,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options Параметры передачи @@ -25439,7 +23903,7 @@ p, li { white-space: pre-wrap; } Максимальное количество одновременных закачек: - + Shared Directories Разделяемые папки @@ -25449,22 +23913,27 @@ p, li { white-space: pre-wrap; } Автоматически открывать доступ к входящей папке (рекомендуется) - - Edit Share - Редактировать разделяемые ресурсы - - - + Directories - + + Configure shared directories + Настроить разделяемые папки + + + Auto-check shared directories every Автоматические проверять разделяемые папки каждые + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) минут(-ы) @@ -25549,7 +24018,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -25558,7 +24027,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) Максимальное количество закачек для участника (0 - неограниченно): @@ -25583,7 +24057,12 @@ p, li { white-space: pre-wrap; } Разрешить прямую загрузку: - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming Последовательный @@ -25642,30 +24121,13 @@ p, li { white-space: pre-wrap; } Trust friend nodes with banned files - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:9pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> способна передавать данные и поисковые запросы между участниками сети, не обязательно между собой соединёнными. Однако этот трафик передаётся только через подключённые узлы из вашего окружения и является анонимным.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">В диалоговом окне раздач для каждой папки по отдельности вы можете установить свои флаги с целью обеспечения:</span></p> <ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">обзора папок контактами из вашего окружения</span>: файлы в папках видимы только вашим доверенным окружением.</li> <li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">анонимного доступа</span>: файлы доступны анонимно через F2F-туннели.</li></ul></body></html> - Max. tunnel req. forwarded per second: Максимум туннельных запросов, переданных в секунду: - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - <html><head/> <body><p><span style="font-weight:600;"> Потоковая</span> передача файла требует предачи частей в 1 MB в возрастающем порядке, облегчая просмотр во время загрузки. <span style="font-weight:600;">Случайная</span> передача является чисто случайной и напоминает заполнение мозаики. <span style="font-weight:600;">Прогрессивная</span> передача является компромиссом, выбирая следующий фрагмент в случайном порядке в пределах менее чем 50 МБ после окончания загрузки предыдущего фрагмента. Это позволяет некоторые случайности, одновременно сокращая время инициализации большого пустого файла.</p></body></html> - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> <html><head/> <body><p>Retroshare будет приостанавливать все передачи и сохранение конфигурационного файла, если свободное место на диске ниже этого предела. Это предотвращает потерю информации на некоторых системах. Всплывающее окно предупредит вас, когда это произойдёт.</p></body></html> @@ -25675,7 +24137,17 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Это значение определяет как много туннелей в секунду можно создавать. </p><p>Если у вас быстрое подключение к сети, вы можете повысить это значение до 30-40, Учтите, что это создаёт много мелких пакетов и может сильно замедлить передачу файлов.</p><p>Значение по умолчанию - 20. Если вы не уверены, оставьте значение по умолчанию.</p></body></html> - + + Warning + Предупреждение + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory Указать входящую папку @@ -25703,7 +24175,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed Загрузка завершена @@ -25727,39 +24199,23 @@ p, li { white-space: pre-wrap; } %1 completed transfer - - You have %1 completed downloads - У вас %1 завершённых закачек - - - You have %1 completed download - У вас есть %1 завершённая загрузка - - - %1 completed downloads - %1 завершённых закачек - - - %1 completed download - %1 завершённых загрузок - TransfersDialog - - + + Downloads Обмен файлами - + Uploads Передача - + Name i.e: file name Имя @@ -25966,11 +24422,7 @@ p, li { white-space: pre-wrap; } Выбрать... - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1> <p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p> <p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p> <p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1> <p>RetroShare поддерживает два метода передачи файлов: прямые передачи между друзьями и анонимные туннельные передачи. Кроме этого поддерживается загрузка от нескольких источников (вы также можете быть источником, пока скачиваете файл)</p> <p>Есть возможность раздавать свои файлы, воспользуйтесь значком <img src=":/images/directoryadd_24x24_shadow.png" width=16 /> на панели. Эти файлы будут добавлены в список разделяемых вами ресурсов. Дополнительно вы можете указать доступность этих файлов для ближнего окружения</p> <p>Вкладка "Поиск" позволяет искать файлы среди доступных ресурсов ваших контактов, а также у удалённых пользователей, через сервис анонимных туннелей.</p> - - - + Move in Queue... Переместить в очереди... @@ -25995,7 +24447,7 @@ p, li { white-space: pre-wrap; } Выберите каталог - + Anonymous end-to-end encrypted tunnel 0x Анонимный туннель со сквозным шифрованием 0x @@ -26016,7 +24468,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -26049,7 +24501,17 @@ p, li { white-space: pre-wrap; } Файл %1 не завершён. Если это медиафайл, попробуйте предпросмотр - + + Warning + Предупреждение + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name Измените имя файла @@ -26064,7 +24526,7 @@ p, li { white-space: pre-wrap; } Пожалуйста введите новое--и действительное--имя файла - + Expand all Раскрыть всё @@ -26191,23 +24653,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Столбцы - + File Transfers Файлообмен - + Path Путь @@ -26217,7 +24674,7 @@ p, li { white-space: pre-wrap; } Показать столбец "Путь" - + Could not delete preview file Не удалось удалить файл предварительного просмотра @@ -26227,7 +24684,7 @@ p, li { white-space: pre-wrap; } Попробуйте ещё раз? - + Create Collection... Создание коллекции... @@ -26242,7 +24699,12 @@ p, li { white-space: pre-wrap; } Просмотр коллекции... - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Collection Коллекция @@ -26252,7 +24714,7 @@ p, li { white-space: pre-wrap; } %1 туннелей - + Anonymous tunnel 0x Анонимный туннель 0x @@ -26473,10 +24935,6 @@ p, li { white-space: pre-wrap; } File transfer tunnels - - Anonymous tunnels - Анонимные туннели - Authenticated tunnels @@ -26670,12 +25128,17 @@ p, li { white-space: pre-wrap; } Форма - + Enable Retroshare WEB Interface Включить веб-интерфейс Retroshare - + + Status: + Статус: + + + Web parameters Параметры сети @@ -26709,35 +25172,33 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Note: these settings do not affect retroshare-service, which has a command line switch to activate the web interface and select the listening port.</p></body></html> - - Port: - Порт: - Allow access from all IP addresses (Default: localhost only) Разрешить доступ от всех IP-адресов (по умолчанию: только localhost) - Apply setting and start browser - Применить настройки и запустить браузер - - - Note: these settings do not affect retroshare-nogui. Retroshare-nogui has a command line switch to activate the web interface. - Примечание: эти настройки не влияют на retroshare-nogui. У Retroshare-nogui есть ключ командной строки для активации веб-интерфейса. - - - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> <h1><img width="24" src=":/icons/help_64.png">Веб-интерфейс</h1> <p>Веб-интерфейс позволяет управлять Retroshare из браузера. Несколько устройств могут иметь контроль над одним экземпляром Retroshare. Так вы можете начать разговор на планшете и позднее использовать настольный компьютер для его продолжения.</p> <p>Предупреждение: не оставляйте веб-интерфейс подключённым к интернету, потому что нет никакого контроля доступа и нет шифрования. Если вы хотите использовать веб-интерфейс через интернет, используйте SSH-туннель или прокси-сервер для безопасного соединения.</p> - + Webinterface not enabled Веб-интерфейс не включён @@ -26747,12 +25208,12 @@ p, li { white-space: pre-wrap; } Веб-интерфейс не включён. Включите его в настройках -> Веб-интерфейс. - + failed to start Webinterface не удалось запустить веб-интерфейс - + Webinterface Веб-интерфейс @@ -26889,11 +25350,7 @@ p, li { white-space: pre-wrap; } Wiki-страницы - New Group - Новая группа - - - + Page Name Название страницы @@ -26908,7 +25365,7 @@ p, li { white-space: pre-wrap; } Уникальный идентификатор - + << << @@ -26996,7 +25453,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History История редактирования страницы @@ -27031,7 +25488,7 @@ p, li { white-space: pre-wrap; } Идентификатор страницы - + \/ \/ @@ -27061,14 +25518,18 @@ p, li { white-space: pre-wrap; } Метки - - + + History + История + + + Show Edit History Показать историю редактирования - + Status Статус @@ -27089,7 +25550,7 @@ p, li { white-space: pre-wrap; } Вернуться - + Submit Отправить @@ -27161,10 +25622,6 @@ p, li { white-space: pre-wrap; } WireDialog - - TimeRange - Диапазон времени - Create Account @@ -27176,16 +25633,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - Обновить - - - + Settings @@ -27200,7 +25648,7 @@ p, li { white-space: pre-wrap; } Другие - + Who to Follow @@ -27220,7 +25668,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -27250,85 +25698,17 @@ p, li { white-space: pre-wrap; } - Last Month - Последний месяц - - - Last Week - Последняя неделя - - - Today - Сегодня - - - New - Новый - - - from - от - - - until - до - - - Search/Filter - Поиск/Фильтр - - - Network Wide - Обширная сеть - - - Manage Accounts - Управление учётными записями - - - Showing: - Показаны: - - - + Yourself Себя - - Friends - Сетевые узлы - Following Следовавший - Custom - Пользовательские - - - Account 1 - Учётная запись 1 - - - Account 2 - Учётная запись 2 - - - Account 3 - Учётная запись 3 - - - CheckBox - Флажок - - - Post Pulse to Wire - Сообщение-импульс для Телеграфа - - - + RetroShare RetroShare @@ -27391,35 +25771,42 @@ p, li { white-space: pre-wrap; } Форма - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + + + + Location: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -27464,11 +25851,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + + + + + Following + Следовавший + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Неизвестно @@ -27546,7 +25963,7 @@ p, li { white-space: pre-wrap; } %1 г. %2 дн. - + k e.g: 3.1 k к @@ -27579,15 +25996,11 @@ p, li { white-space: pre-wrap; } Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif *.webp) - - Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - Изображения (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - pgpid_item_model - + Do you accept connections signed by this profile? Разрешаете ли вы соединения, подписанные этим ключом? @@ -27596,10 +26009,6 @@ p, li { white-space: pre-wrap; } Name of the profile Имя профиля - - This column indicates trust level and whether you signed the profile PGP key - Этот столбец указывает уровень доверия и подписан ли PGP-ключ профиля - This column indicates the trust level you indicated and whether you signed the profile PGP key @@ -27710,10 +26119,6 @@ p, li { white-space: pre-wrap; } Denied - - - - - - PGP key signed by you diff --git a/retroshare-gui/src/lang/retroshare_sl.ts b/retroshare-gui/src/lang/retroshare_sl.ts index a8c42dad2..581ac731c 100644 --- a/retroshare-gui/src/lang/retroshare_sl.ts +++ b/retroshare-gui/src/lang/retroshare_sl.ts @@ -121,12 +121,12 @@ - + Search Criteria - + Add a further search criterion. @@ -136,7 +136,7 @@ - + Cancels the search. @@ -156,13 +156,6 @@ - - AlbumCreateDialog - - Quality: - Kakovost: - - AlbumDialog @@ -547,7 +540,7 @@ p, li { white-space: pre-wrap; } - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. @@ -573,10 +566,23 @@ p, li { white-space: pre-wrap; } + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb @@ -619,7 +625,7 @@ p, li { white-space: pre-wrap; } - + Set your Avatar picture @@ -706,7 +712,7 @@ p, li { white-space: pre-wrap; } Ponastavi - + Always on Top @@ -725,14 +731,6 @@ p, li { white-space: pre-wrap; } % Opaque - - Save - Shrani - - - Cancel - Prekliči - Since: @@ -810,7 +808,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment @@ -840,12 +838,12 @@ p, li { white-space: pre-wrap; } - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -853,7 +851,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up @@ -873,7 +871,7 @@ p, li { white-space: pre-wrap; } - + Posted by @@ -911,7 +909,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up @@ -931,7 +929,7 @@ p, li { white-space: pre-wrap; } - + Click to view picture @@ -961,7 +959,7 @@ p, li { white-space: pre-wrap; } - + Toggle Message Read Status @@ -971,7 +969,7 @@ p, li { white-space: pre-wrap; } - + TextLabel @@ -979,12 +977,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this - + 0 @@ -1004,18 +1002,18 @@ p, li { white-space: pre-wrap; } - + New Comment - + Copy RetroShare Link - + Expand @@ -1030,12 +1028,12 @@ p, li { white-space: pre-wrap; } - + Name Ime - + Comm value @@ -1204,17 +1202,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels - + Tabs - + General @@ -1224,7 +1222,17 @@ p, li { white-space: pre-wrap; } - + + Downloads + + + + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab @@ -1232,7 +1240,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1255,7 +1263,7 @@ into the image, so as to ChannelsCommentsItem - + I like this @@ -1280,18 +1288,18 @@ into the image, so as to - + New Comment - + Copy RetroShare Link - + Expand @@ -1306,7 +1314,7 @@ into the image, so as to - + Name Ime @@ -1316,17 +1324,7 @@ into the image, so as to - - Comment - - - - - Comments - - - - + Hide @@ -1334,7 +1332,7 @@ into the image, so as to ChatLobbyDialog - + Name Ime @@ -1525,7 +1523,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby @@ -1558,13 +1556,14 @@ into the image, so as to - + + Unknown Lobby - - + + Remove All @@ -1572,13 +1571,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Ime - + Count @@ -1588,29 +1587,7 @@ into the image, so as to - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - - - - - - Public chat rooms - - - - + Create chat room @@ -1620,7 +1597,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1677,12 +1654,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1692,23 +1669,42 @@ Double click a chat room to enter and chat. - + [No topic provided] - + + Private Subscribed + + + + + + Public Subscribed + + + + + Private - + + + Public - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted @@ -1718,38 +1714,25 @@ Double click a chat room to enter and chat. - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe - + Search Chat lobbies - + Search Name - + Columns - - Yes - Da - - - No - Ne - Chat rooms @@ -1761,47 +1744,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: - + Type: Vrsta: - + Security: - + Peers: - - - - - - + + + + + + TextLabel @@ -1816,7 +1799,7 @@ Double click a chat room to enter and chat. - + Show Pokaži @@ -1836,7 +1819,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item @@ -1881,7 +1864,7 @@ Double click a chat room to enter and chat. ChatPage - + General @@ -1896,7 +1879,7 @@ Double click a chat room to enter and chat. - + Enable custom fonts @@ -1916,7 +1899,7 @@ Double click a chat room to enter and chat. - + General settings @@ -1941,7 +1924,7 @@ Double click a chat room to enter and chat. - + Blink tab icon @@ -1971,7 +1954,7 @@ Double click a chat room to enter and chat. - + Change Chat Font @@ -1981,7 +1964,7 @@ Double click a chat room to enter and chat. - + History @@ -2005,7 +1988,7 @@ Double click a chat room to enter and chat. - + Choose your default font for Chat. @@ -2075,12 +2058,22 @@ Double click a chat room to enter and chat. - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2090,7 +2083,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2187,7 +2190,7 @@ Double click a chat room to enter and chat. - + Case sensitive Razlikuj velike in male črke @@ -2293,7 +2296,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat @@ -2329,7 +2332,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close @@ -2364,12 +2367,12 @@ Double click a chat room to enter and chat. - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2449,11 +2452,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2491,7 +2489,7 @@ Double click a chat room to enter and chat. - + is typing... @@ -2513,7 +2511,7 @@ after HTML conversion. - + Do you really want to physically delete the history? @@ -2563,7 +2561,7 @@ after HTML conversion. - + Find Case Sensitively @@ -2585,7 +2583,7 @@ after HTML conversion. - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> @@ -2600,12 +2598,12 @@ after HTML conversion. - + (Status) - + Attach a File @@ -2621,12 +2619,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> - + Person id: @@ -2637,12 +2635,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. @@ -2662,7 +2660,7 @@ Double click on it to add his name on text writer. - + Don't stop to color after @@ -2688,7 +2686,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: @@ -2710,7 +2708,7 @@ Double click on it to add his name on text writer. - + Personal Circles @@ -2736,7 +2734,7 @@ Double click on it to add his name on text writer. - + Friends @@ -2796,7 +2794,7 @@ Double click on it to add his name on text writer. - + External Circles (Admin) @@ -2812,7 +2810,7 @@ Double click on it to add his name on text writer. - + Circles @@ -2864,45 +2862,45 @@ Double click on it to add his name on text writer. - + RetroShare - + - + Error : cannot get peer details. - + Retroshare ID - + <p>This Retroshare ID contains: - + <p>This certificate contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: @@ -2912,7 +2910,7 @@ Double click on it to add his name on text writer. - + Not connected @@ -2994,12 +2992,17 @@ Double click on it to add his name on text writer. brez - + <li>a <b>node ID</b> and <b>name</b> - + + <b>DNS:</b> : + + + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3019,7 +3022,7 @@ Double click on it to add his name on text writer. - + with @@ -3087,7 +3090,7 @@ Double click on it to add his name on text writer. - + @@ -3103,12 +3106,12 @@ Double click on it to add his name on text writer. - + Peer details - + Name: Ime: @@ -3118,17 +3121,17 @@ Double click on it to add his name on text writer. - + Options Možnosti - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: @@ -3138,7 +3141,7 @@ Double click on it to add his name on text writer. - + Please paste below your friend's Retroshare ID @@ -3163,12 +3166,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with - + Sorry, some error appeared @@ -3188,32 +3201,27 @@ Double click on it to add his name on text writer. - + Key validity: - + Profile ID: - - Signers - - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. - + To accept the Friend Request, click the Accept button. @@ -3259,17 +3267,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed - + Not a valid Retroshare certificate! - + RetroShare Invitation @@ -3289,12 +3297,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3302,7 +3310,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3342,7 +3350,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Profile password needed. @@ -3367,7 +3375,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3377,7 +3385,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3416,7 +3424,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + IP-Addr: @@ -3426,7 +3434,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Show Advanced options @@ -3451,7 +3459,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already in your keyring @@ -3464,7 +3472,7 @@ even if you don't make friends. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. @@ -3499,7 +3507,7 @@ even if you don't make friends. - + No IP in this certificate! @@ -3509,12 +3517,7 @@ even if you don't make friends. - - [Unknown] - - - - + Added with certificate from %1 @@ -3579,7 +3582,7 @@ even if you don't make friends. - + UDP Setup @@ -3607,7 +3610,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant @@ -3617,17 +3620,20 @@ p, li { white-space: pre-wrap; } - + + Unknown State - + + Offline - + + Behind Symmetric NAT @@ -3637,12 +3643,14 @@ p, li { white-space: pre-wrap; } - + + NET Restart - + + Behind NAT @@ -3652,7 +3660,8 @@ p, li { white-space: pre-wrap; } - + + NET STATE GOOD! @@ -3677,7 +3686,7 @@ p, li { white-space: pre-wrap; } - + Lookup requires DHT @@ -3969,7 +3978,7 @@ p, li { white-space: pre-wrap; } - + @@ -3977,7 +3986,8 @@ p, li { white-space: pre-wrap; } - + + UNVERIFIABLE FORWARD! @@ -3987,7 +3997,7 @@ p, li { white-space: pre-wrap; } - + Searching @@ -4023,12 +4033,12 @@ p, li { white-space: pre-wrap; } - + Name Ime - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4048,7 +4058,7 @@ p, li { white-space: pre-wrap; } - + IDs @@ -4068,18 +4078,18 @@ p, li { white-space: pre-wrap; } - + Cancel Prekliči - + Nickname - + Invited Members @@ -4094,7 +4104,7 @@ p, li { white-space: pre-wrap; } - + Name: Ime: @@ -4134,19 +4144,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare - + Please set a name for your Circle - + No Restriction Circle Selected @@ -4156,12 +4166,24 @@ p, li { white-space: pre-wrap; } - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add Dodaj @@ -4171,7 +4193,7 @@ p, li { white-space: pre-wrap; } - + Search @@ -4224,13 +4246,13 @@ p, li { white-space: pre-wrap; } - + Create - + Add Member @@ -4249,7 +4271,7 @@ p, li { white-space: pre-wrap; } - + Group Name: @@ -4284,7 +4306,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post @@ -4294,7 +4316,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4439,17 +4461,17 @@ p, li { white-space: pre-wrap; } - + RetroShare - + This file already in this post: - + Post refers to non shared files @@ -4474,7 +4496,12 @@ p, li { white-space: pre-wrap; } - + + Cannot publish post + + + + Load thumbnail picture @@ -4489,18 +4516,12 @@ p, li { white-space: pre-wrap; } - - + Generate mass data - - Do you really want to generate %1 messages ? - - - - + You are about to add files you're not actually sharing. Do you still want this to happen? @@ -4534,7 +4555,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message @@ -4544,7 +4565,16 @@ p, li { white-space: pre-wrap; } - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> + + + + Attach File @@ -4559,16 +4589,7 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> - - - - + Attach a Picture @@ -4583,7 +4604,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4613,17 +4634,17 @@ p, li { white-space: pre-wrap; } - + No Forum - + In Reply to - + Title @@ -4676,7 +4697,7 @@ Do you want to discard this message? - + No compatible ID for this forum @@ -4686,8 +4707,8 @@ Do you want to discard this message? - - + + Generate mass data @@ -4710,7 +4731,7 @@ Do you want to discard this message? CreateLobbyDialog - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -4745,7 +4766,7 @@ Do you want to discard this message? - + Create @@ -4755,7 +4776,7 @@ Do you want to discard this message? Prekliči - + require PGP-signed identities @@ -4770,7 +4791,7 @@ Do you want to discard this message? - + Create Chat Room @@ -4791,7 +4812,7 @@ Do you want to discard this message? - + Identity to use: @@ -4799,17 +4820,17 @@ Do you want to discard this message? CryptoPage - + Public Information - + Name: Ime: - + Location: @@ -4819,12 +4840,12 @@ Do you want to discard this message? - + Software Version: - + Online since: @@ -4844,12 +4865,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -4859,7 +4875,7 @@ Do you want to discard this message? - + Other Information @@ -4869,17 +4885,12 @@ Do you want to discard this message? - + Profile - - Certificate - - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -4889,7 +4900,7 @@ Do you want to discard this message? - + Export Identity @@ -4959,33 +4970,33 @@ and use the import button to load it - + TextLabel - + PGP fingerprint: - - Node information - - - - + PGP Id : - + Friend nodes: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5075,7 +5086,7 @@ and use the import button to load it DLListDelegate - + B @@ -5743,7 +5754,7 @@ and use the import button to load it DownloadToaster - + Start file @@ -5751,38 +5762,38 @@ and use the import button to load it ExprParamElement - + - + to - + ignore case - - - dd.MM.yyyy + + + yyyy-MM-dd - - + + KB - - + + MB - - + + GB @@ -5790,12 +5801,12 @@ and use the import button to load it ExpressionWidget - + Expression Widget - + Delete this expression @@ -5957,7 +5968,7 @@ and use the import button to load it FilesDefs - + Picture @@ -5967,7 +5978,7 @@ and use the import button to load it - + Audio @@ -6027,11 +6038,21 @@ and use the import button to load it C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories @@ -6153,7 +6174,7 @@ and use the import button to load it - + ID @@ -6195,7 +6216,7 @@ and use the import button to load it - + Group @@ -6231,7 +6252,7 @@ and use the import button to load it - + Search @@ -6247,7 +6268,7 @@ and use the import button to load it - + Profile details @@ -6484,7 +6505,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request @@ -6522,7 +6543,7 @@ at least one peer was not added to a group - + Mark all @@ -6533,16 +6554,132 @@ at least one peer was not added to a group + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Ime + + + + Node ID + + + + + Address + + + + + Status + Stanje + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message - - + + Broadcast @@ -6625,33 +6762,38 @@ at least one peer was not added to a group - + Keyring - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. - - + + Network - + + Friend Server + + + + Network graph - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. @@ -6669,7 +6811,17 @@ at least one peer was not added to a group - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters @@ -6679,17 +6831,12 @@ at least one peer was not added to a group - + Port - - Use BOB - - - - + This password is for PGP @@ -6710,38 +6857,38 @@ at least one peer was not added to a group - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -6761,12 +6908,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -6776,38 +6923,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel - + hidden address - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -6851,13 +7003,13 @@ and use the import button to load it - + Import profile - + Create new profile and new Retroshare node @@ -6867,7 +7019,7 @@ and use the import button to load it - + Tor/I2P address @@ -6902,7 +7054,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -6912,12 +7064,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -6927,12 +7074,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7158,27 +7300,13 @@ and use the import button to load it - + Invite Friends - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - - - - + Add Your Friends to RetroShare @@ -7188,39 +7316,57 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + Connect To Friends - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port @@ -7228,49 +7374,45 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - - - - + Further Help and Support - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website @@ -7295,7 +7437,7 @@ p, li { white-space: pre-wrap; } - + RetroShare Invitation @@ -7345,12 +7487,12 @@ p, li { white-space: pre-wrap; } - + RetroShare Support - + It has many features, including built-in chat, messaging, @@ -7474,7 +7616,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat @@ -7482,7 +7624,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] @@ -7652,7 +7794,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title @@ -7665,12 +7807,12 @@ p, li { white-space: pre-wrap; } - + Description - + Number of Unread message @@ -7695,7 +7837,7 @@ p, li { white-space: pre-wrap; } - + You are admin (modify names and description using Edit menu) @@ -7710,14 +7852,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post - + Name Ime @@ -7728,13 +7870,13 @@ p, li { white-space: pre-wrap; } - + Never - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -7747,7 +7889,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and @@ -7883,7 +8025,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels @@ -7894,22 +8036,22 @@ p, li { white-space: pre-wrap; } - + Enable Auto-Download - + My Channels - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels @@ -7929,12 +8071,12 @@ p, li { white-space: pre-wrap; } - + Disable Auto-Download - + Set download directory @@ -7969,22 +8111,22 @@ p, li { white-space: pre-wrap; } - + Play - + Open folder - + Open file - + Error @@ -8004,17 +8146,17 @@ p, li { white-space: pre-wrap; } - + Are you sure that you want to cancel and delete the file? - + Can't open folder - + Play File @@ -8024,17 +8166,10 @@ p, li { white-space: pre-wrap; } - - GxsChannelFilesWidget - - Status - Stanje - - GxsChannelGroupDialog - + Create New Channel @@ -8072,8 +8207,18 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel @@ -8088,7 +8233,7 @@ p, li { white-space: pre-wrap; } - + Expand @@ -8103,7 +8248,7 @@ p, li { white-space: pre-wrap; } - + Loading @@ -8117,6 +8262,11 @@ p, li { white-space: pre-wrap; } New Channel: + + + Never + + Hide @@ -8126,7 +8276,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: @@ -8147,7 +8297,7 @@ p, li { white-space: pre-wrap; } - + Play @@ -8209,18 +8359,18 @@ p, li { white-space: pre-wrap; } - + New - + 0 - - + + Comment @@ -8235,17 +8385,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + Comments - + Post @@ -8273,13 +8423,13 @@ p, li { white-space: pre-wrap; } GxsChannelPostsWidgetWithModel - + Post to Channel - + Add new post @@ -8349,7 +8499,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -8385,7 +8535,7 @@ p, li { white-space: pre-wrap; } - + Comments @@ -8400,13 +8550,13 @@ p, li { white-space: pre-wrap; } - - + + Click to switch to list view - + Show unread posts only @@ -8421,7 +8571,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -8436,7 +8586,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -8496,12 +8646,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -8576,12 +8736,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed @@ -8632,17 +8793,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -8757,7 +8918,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container @@ -8770,7 +8931,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -8800,7 +8961,7 @@ p, li { white-space: pre-wrap; } - + Comment @@ -8839,7 +9000,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment @@ -8863,6 +9024,21 @@ p, li { white-space: pre-wrap; } Vote Down + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -8872,7 +9048,7 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -8901,7 +9077,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -8932,7 +9108,7 @@ before you can comment - + It remains %1 characters after HTML conversion. @@ -8983,7 +9159,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum @@ -8999,7 +9175,7 @@ before you can comment - + Expand @@ -9018,6 +9194,11 @@ before you can comment Moderator list + + + TextLabel + + Loading... @@ -9047,13 +9228,13 @@ before you can comment GxsForumMsgItem - - + + Subject: - + Unsubscribe To Forum @@ -9064,7 +9245,7 @@ before you can comment - + Expand @@ -9084,17 +9265,17 @@ before you can comment - + Loading... - + Forum Feed - + Hide @@ -9107,59 +9288,66 @@ before you can comment - + Start new Thread for Selected Forum - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums - + New Thread - - - Threaded View - - - - - Flat View - - - + Title - - + + Date - + Author - - Save image - - - - + Loading - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9169,12 +9357,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message @@ -9214,23 +9397,23 @@ before you can comment - + No name - - + + Reply - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -9273,12 +9456,12 @@ before you can comment - + Hide - + [unknown] @@ -9308,8 +9491,8 @@ before you can comment - - + + Distribution @@ -9323,10 +9506,6 @@ before you can comment Anti-spam - - none - brez - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -9396,12 +9575,12 @@ before you can comment - + New thread - + Edit @@ -9462,7 +9641,7 @@ before you can comment - + Show column @@ -9482,7 +9661,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive @@ -9534,7 +9713,7 @@ This message is missing. You should receive it later. - + No result. @@ -9544,7 +9723,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -9559,7 +9738,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -9625,12 +9804,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums @@ -9665,12 +9844,12 @@ This message is missing. You should receive it later. GxsGroupDialog - + Name Ime - + Key recipients can publish to restricted-type group and can view and publish for private-type channels @@ -9681,12 +9860,12 @@ This message is missing. You should receive it later. - + Description - + Message Distribution @@ -9694,7 +9873,7 @@ This message is missing. You should receive it later. - + Public @@ -9754,7 +9933,7 @@ This message is missing. You should receive it later. - + Comments: @@ -9777,7 +9956,7 @@ This message is missing. You should receive it later. - + All People @@ -9793,12 +9972,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -9815,23 +9994,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -9847,22 +10026,28 @@ This message is missing. You should receive it later. - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo - + Submit Group Changes - + Owner: @@ -9872,12 +10057,12 @@ This message is missing. You should receive it later. - + Info - + ID @@ -9887,7 +10072,7 @@ This message is missing. You should receive it later. - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -9962,7 +10147,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity @@ -9978,27 +10168,22 @@ This message is missing. You should receive it later. - + Created - + Cancel Prekliči - + Create - - Author - - - - + GxsIdLabel @@ -10006,7 +10191,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading @@ -10066,7 +10251,7 @@ This message is missing. You should receive it later. - + Synchronise posts of last... @@ -10123,12 +10308,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link @@ -10151,7 +10336,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature @@ -10164,14 +10349,14 @@ This message is missing. You should receive it later. GxsIdDetails - + Not found - - + + [Banned] @@ -10181,7 +10366,7 @@ This message is missing. You should receive it later. - + Loading... @@ -10191,7 +10376,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -10211,6 +10401,14 @@ This message is missing. You should receive it later. + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -10222,7 +10420,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -10270,7 +10468,7 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] @@ -10657,7 +10855,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -10673,7 +10871,7 @@ p, li { white-space: pre-wrap; } - + Authors @@ -10692,7 +10890,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -10766,7 +10964,7 @@ p, li { white-space: pre-wrap; } - + Add friend @@ -10776,7 +10974,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -10804,7 +11002,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -10814,7 +11012,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard @@ -10824,7 +11022,7 @@ private and secure decentralized communication platform. - + Send via Email @@ -10844,13 +11042,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -10862,12 +11084,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -10882,12 +11104,7 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... @@ -11152,14 +11369,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All - + Reputation @@ -11169,12 +11386,12 @@ p, li { white-space: pre-wrap; } - + Anonymous Id - + Create new Identity @@ -11184,7 +11401,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -11199,27 +11416,27 @@ p, li { white-space: pre-wrap; } - + Close - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -11235,29 +11452,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles - + Circle name @@ -11277,18 +11504,20 @@ p, li { white-space: pre-wrap; } - + + Edit identity - + + Delete identity - + Chat with this peer @@ -11298,78 +11527,78 @@ p, li { white-space: pre-wrap; } - + Owner node ID : - + Identity name : - + () - + Identity ID - + Send message - + Identity info - + Identity ID : - + Owner node name : - + Create new... - + Type: Vrsta: - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: - + Negative - + Neutral @@ -11380,17 +11609,17 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous @@ -11405,24 +11634,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you - - + + My own identities - - + + My contacts - + Show Items @@ -11437,7 +11666,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -11447,7 +11681,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -11522,7 +11756,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -11552,7 +11786,7 @@ p, li { white-space: pre-wrap; } neznano - + Invited @@ -11567,7 +11801,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle @@ -11615,7 +11849,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -11623,7 +11857,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -11666,7 +11900,7 @@ These identities will soon be not supported anymore. - + Boards @@ -11746,7 +11980,7 @@ These identities will soon be not supported anymore. - + information @@ -11762,17 +11996,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -11877,7 +12106,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -11927,21 +12156,21 @@ These identities will soon be not supported anymore. - - - + + + People - + Your Avatar Click here to change your avatar - + Linked to neighbor nodes @@ -11951,7 +12180,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -11966,7 +12195,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -11981,12 +12210,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -12006,12 +12235,12 @@ These identities will soon be not supported anymore. - + Owned by - + Node name: @@ -12021,7 +12250,7 @@ These identities will soon be not supported anymore. - + Really delete? @@ -12029,7 +12258,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname @@ -12059,7 +12288,13 @@ These identities will soon be not supported anymore. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity @@ -12073,7 +12308,7 @@ These identities will soon be not supported anymore. - + @@ -12083,7 +12318,12 @@ These identities will soon be not supported anymore. - + + No avatar chosen + + + + Edit identity @@ -12094,27 +12334,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -12134,7 +12374,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -12144,12 +12384,18 @@ These identities will soon be not supported anymore. - + Error KeyID invalid - + + + No Avatar chosen. A default image will be automatically displayed from your new identity. + + + + Import image @@ -12159,12 +12405,7 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. - - - - + Unknown GpgId @@ -12174,7 +12415,7 @@ These identities will soon be not supported anymore. - + Create New Identity @@ -12184,10 +12425,15 @@ These identities will soon be not supported anymore. - + Choose image... + + + Remove + + @@ -12213,7 +12459,7 @@ These identities will soon be not supported anymore. Dodaj - + Create @@ -12223,13 +12469,13 @@ These identities will soon be not supported anymore. Prekliči - + Your Avatar Click here to change your avatar - + Linked to your profile @@ -12239,7 +12485,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -12313,7 +12559,7 @@ These identities will soon be not supported anymore. - + Copy Kopiraj @@ -12323,12 +12569,12 @@ These identities will soon be not supported anymore. - + %1 's Message History - + Mark all @@ -12351,18 +12597,34 @@ These identities will soon be not supported anymore. ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -12380,27 +12642,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: - + Listen Address: - + + Status: + + + + 127.0.0.1 - + Token: @@ -12421,7 +12688,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -12430,26 +12702,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File - + Open Folder - + Checking... @@ -12459,7 +12736,7 @@ These identities will soon be not supported anymore. - + Recommend in a message to... @@ -12487,7 +12764,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend @@ -12503,7 +12780,8 @@ These identities will soon be not supported anymore. - + + Options Možnosti @@ -12524,7 +12802,7 @@ These identities will soon be not supported anymore. - + Quit @@ -12535,12 +12813,12 @@ These identities will soon be not supported anymore. - + RetroShare %1 a secure decentralized communication platform - + Unfinished @@ -12565,11 +12843,12 @@ These identities will soon be not supported anymore. + Status Stanje - + Notify @@ -12580,31 +12859,35 @@ These identities will soon be not supported anymore. + Open Messages - + + Bandwidth Graph - + Applications + Help Pomoč - + + Minimize - + Maximize @@ -12619,7 +12902,12 @@ These identities will soon be not supported anymore. - + + Close window + + + + %1 new message @@ -12649,7 +12937,7 @@ These identities will soon be not supported anymore. - + Do you really want to exit RetroShare ? @@ -12669,7 +12957,7 @@ These identities will soon be not supported anymore. Pokaži - + Make sure this link has not been forged to drag you to a malicious website. @@ -12714,12 +13002,13 @@ These identities will soon be not supported anymore. - + + Statistics - + Show web interface @@ -12734,7 +13023,7 @@ These identities will soon be not supported anymore. - + Really quit ? @@ -12743,17 +13032,17 @@ These identities will soon be not supported anymore. MessageComposer - + Compose - + Contacts - + Paragraph @@ -12789,12 +13078,12 @@ These identities will soon be not supported anymore. - + Font size - + Increase font size @@ -12809,32 +13098,32 @@ These identities will soon be not supported anymore. - + Italic - + Alignment - + Add an Image - + Sets text font to code style - + Underline - + Subject: @@ -12845,32 +13134,32 @@ These identities will soon be not supported anymore. - + Tags - + Address list: - + Recommend this friend - + Set Text color - + Set Text background color - + Recommended Files @@ -12940,7 +13229,7 @@ These identities will soon be not supported anymore. - + Send To: @@ -12980,7 +13269,7 @@ These identities will soon be not supported anymore. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> @@ -13000,18 +13289,18 @@ These identities will soon be not supported anymore. - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team - - + + Save Message - + Message has not been Sent. Do you want to save message to draft box? @@ -13022,7 +13311,17 @@ Do you want to save message to draft box? - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" @@ -13042,7 +13341,7 @@ Do you want to save message to draft box? - + Original Message @@ -13052,21 +13351,21 @@ Do you want to save message to draft box? - + - + To - - + + Cc - + Sent @@ -13081,7 +13380,7 @@ Do you want to save message to draft box? - + Re: @@ -13091,30 +13390,30 @@ Do you want to save message to draft box? - - - + + + RetroShare - + Do you want to send the message without a subject ? - + Please insert at least one recipient. - + Bcc - + Unknown @@ -13229,13 +13528,13 @@ Do you want to save message to draft box? - + Open File... - + HTML-Files (*.htm *.html);;All Files (*) @@ -13255,7 +13554,7 @@ Do you want to save message to draft box? - + Message has not been Sent. Do you want to save message ? @@ -13276,7 +13575,7 @@ Do you want to save message ? - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -13306,18 +13605,18 @@ Do you want to save message ? - - + + Close - + From: Od: - + Bullet list (disc) @@ -13357,13 +13656,13 @@ Do you want to save message ? - - + + Thanks, <br> - + Distant identity: @@ -13373,12 +13672,12 @@ Do you want to save message ? - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -13456,7 +13755,7 @@ Do you want to save message ? Privzeto - + A new tab @@ -13466,7 +13765,7 @@ Do you want to save message ? - + Edit Tag @@ -13489,7 +13788,7 @@ Do you want to save message ? MessageToaster - + Sub: @@ -13497,7 +13796,7 @@ Do you want to save message ? MessageUserNotify - + Message @@ -13525,7 +13824,7 @@ Do you want to save message ? MessageWidget - + Recommended Files @@ -13535,37 +13834,37 @@ Do you want to save message ? - + Subject: - + From: Od: - + To: Do: - + Cc: - + Bcc: - + Tags: - + Reply @@ -13605,7 +13904,7 @@ Do you want to save message ? - + Send Invite @@ -13657,7 +13956,7 @@ Do you want to save message ? - + Confirm %1 as friend @@ -13667,12 +13966,12 @@ Do you want to save message ? - + View source - + No subject @@ -13682,17 +13981,22 @@ Do you want to save message ? - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -13701,14 +14005,24 @@ Do you want to save message ? %1 (%2) + + + Show less + + + + + Show more + + - + Download all - + Print Document @@ -13723,12 +14037,12 @@ Do you want to save message ? - + Load images always for this message - + Hide the attachment pane @@ -13750,10 +14064,6 @@ Do you want to save message ? Compose - - Delete - Izbriši - Print @@ -13832,7 +14142,7 @@ Do you want to save message ? MessagesDialog - + New Message @@ -13842,20 +14152,16 @@ Do you want to save message ? - Delete - Izbriši - - - + - - + + Tags - - + + Inbox @@ -13885,17 +14191,17 @@ Do you want to save message ? - + Total Inbox: - + Quick View - + Print... @@ -13926,7 +14232,7 @@ Do you want to save message ? - + Subject @@ -13936,7 +14242,7 @@ Do you want to save message ? - + Date @@ -13946,7 +14252,7 @@ Do you want to save message ? - + Search Subject @@ -13955,6 +14261,16 @@ Do you want to save message ? Search From + + + To + + + + + Search To + + Search Date @@ -13981,12 +14297,12 @@ Do you want to save message ? - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred @@ -14062,7 +14378,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -14076,7 +14392,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -14091,18 +14407,28 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts - + No Box selected. - + @@ -14137,7 +14463,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -14191,7 +14527,7 @@ Do you want to save message ? - + Expand @@ -14201,7 +14537,7 @@ Do you want to save message ? - + from @@ -14236,7 +14572,7 @@ Do you want to save message ? - + Hide @@ -14377,7 +14713,7 @@ Do you want to save message ? - + Remove unused keys... @@ -14387,7 +14723,7 @@ Do you want to save message ? - + Clean keyring @@ -14401,7 +14737,13 @@ Notes: Your old keyring will be backed up. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info @@ -14434,18 +14776,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. - - - Export/create a new node - - Trusted keys only - + Search name @@ -14455,12 +14792,12 @@ For security, your keyring was previously backed-up to file - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -14493,7 +14830,7 @@ Reported error: NewFriendList - + Offline Friends @@ -14514,7 +14851,7 @@ Reported error: - + Groups @@ -14544,19 +14881,19 @@ Reported error: - - + + Search - + ID - + Search ID @@ -14566,12 +14903,12 @@ Reported error: - + Show Items - + Last contact @@ -14581,7 +14918,7 @@ Reported error: - + Group @@ -14696,7 +15033,7 @@ Reported error: - + Do you want to remove this node? @@ -14706,7 +15043,7 @@ Reported error: - + Done! @@ -14813,7 +15150,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -14828,7 +15165,7 @@ at least one peer was not added to a group - + Newest on top @@ -14838,12 +15175,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15081,7 +15418,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -15101,12 +15438,12 @@ at least one peer was not added to a group - + Please enter your Retroshare passphrase - + Unregistered plugin/executable @@ -15121,7 +15458,7 @@ at least one peer was not added to a group - + Test @@ -15132,17 +15469,19 @@ at least one peer was not added to a group + Unknown title - + + Encrypted message - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -15150,7 +15489,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online @@ -15289,7 +15628,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -15334,12 +15678,7 @@ p, li { white-space: pre-wrap; } - - Options - Možnosti - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -15385,21 +15724,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare - - + + Error : cannot get peer details. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) @@ -15417,7 +15756,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -15493,12 +15832,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -15524,7 +15863,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat @@ -15545,7 +15884,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Name: Ime: @@ -15585,7 +15924,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message @@ -15643,7 +15982,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Send Message @@ -15961,17 +16300,17 @@ p, li { white-space: pre-wrap; } - + My Albums - + Subscribed Albums - + Shared Albums @@ -16000,7 +16339,7 @@ requesting to edit it! PhotoSlideShow - + Album Name @@ -16059,19 +16398,19 @@ requesting to edit it! - - + + TextLabel - + Posted by - + ago @@ -16107,12 +16446,12 @@ requesting to edit it! PluginItem - + TextLabel - + Show more details about this plugin @@ -16323,12 +16662,27 @@ p, li { white-space: pre-wrap; } - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -16381,7 +16735,7 @@ p, li { white-space: pre-wrap; } - + Vote up @@ -16401,8 +16755,8 @@ p, li { white-space: pre-wrap; } - - + + Comments @@ -16427,13 +16781,13 @@ p, li { white-space: pre-wrap; } - - + + Comment - + Comments @@ -16461,12 +16815,12 @@ p, li { white-space: pre-wrap; } PostedCreatePostDialog - + Create a new Post - + RetroShare @@ -16481,12 +16835,22 @@ p, li { white-space: pre-wrap; } - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File - + Post image @@ -16502,7 +16866,17 @@ p, li { white-space: pre-wrap; } - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -16512,7 +16886,7 @@ p, li { white-space: pre-wrap; } - + Please add a Title @@ -16532,12 +16906,22 @@ p, li { white-space: pre-wrap; } - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -16552,7 +16936,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -16563,7 +16947,7 @@ p, li { white-space: pre-wrap; } - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -16573,7 +16957,7 @@ p, li { white-space: pre-wrap; } - + Link @@ -16581,12 +16965,12 @@ p, li { white-space: pre-wrap; } PostedDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -16620,7 +17004,7 @@ p, li { white-space: pre-wrap; } PostedGroupDialog - + Create New Board @@ -16658,7 +17042,17 @@ p, li { white-space: pre-wrap; } PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted @@ -16674,7 +17068,7 @@ p, li { white-space: pre-wrap; } - + Expand @@ -16689,12 +17083,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + + Never + + + + New Board @@ -16707,18 +17106,18 @@ p, li { white-space: pre-wrap; } PostedItem - + 0 - - + + Comments - + Copy RetroShare Link @@ -16729,12 +17128,12 @@ p, li { white-space: pre-wrap; } - + Comment - + Comments @@ -16744,7 +17143,7 @@ p, li { white-space: pre-wrap; } - + Click to view Picture @@ -16754,17 +17153,17 @@ p, li { white-space: pre-wrap; } - + Vote up - + Vote down - + Set as read and remove item @@ -16774,7 +17173,7 @@ p, li { white-space: pre-wrap; } - + New Comment: @@ -16784,7 +17183,7 @@ p, li { white-space: pre-wrap; } - + Name Ime @@ -16825,7 +17224,7 @@ p, li { white-space: pre-wrap; } - + Loading @@ -16848,7 +17247,17 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 @@ -16858,15 +17267,15 @@ p, li { white-space: pre-wrap; } - + - + unknown neznano - + Distribution: @@ -16876,42 +17285,42 @@ p, li { white-space: pre-wrap; } - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -16931,7 +17340,7 @@ p, li { white-space: pre-wrap; } - + Search @@ -16961,17 +17370,17 @@ p, li { white-space: pre-wrap; } - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -16986,12 +17395,17 @@ p, li { white-space: pre-wrap; } - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -17001,27 +17415,31 @@ p, li { white-space: pre-wrap; } - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -17036,7 +17454,7 @@ p, li { white-space: pre-wrap; } - + Never @@ -17110,6 +17528,16 @@ p, li { white-space: pre-wrap; } No Channel Selected + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -17199,16 +17627,16 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -17316,7 +17744,7 @@ and use the import button to load it ProfileWidget - + Edit status message @@ -17332,7 +17760,7 @@ and use the import button to load it - + Public Information @@ -17367,12 +17795,12 @@ and use the import button to load it - + Other Information - + My Address @@ -17416,27 +17844,27 @@ and use the import button to load it PulseAddDialog - + Add to Pulse - + Display As - + URL - + GroupLabel - + IDLabel @@ -17446,12 +17874,12 @@ and use the import button to load it Od: - + Head - + Head Shot @@ -17481,13 +17909,13 @@ and use the import button to load it - - + + Whats happening? - + @@ -17499,12 +17927,22 @@ and use the import button to load it - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -17519,7 +17957,7 @@ and use the import button to load it - + Reply to Pulse @@ -17534,26 +17972,24 @@ and use the import button to load it - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - ... - ... + + Load Picture File + @@ -17564,7 +18000,7 @@ and use the import button to load it - + @@ -17583,7 +18019,7 @@ and use the import button to load it PulseReply - + icn @@ -17593,7 +18029,7 @@ and use the import button to load it - + REPLY @@ -17620,7 +18056,7 @@ and use the import button to load it - + FOLLOW @@ -17630,7 +18066,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -17650,7 +18086,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -17766,7 +18202,7 @@ and use the import button to load it - + FOLLOW @@ -17774,37 +18210,42 @@ and use the import button to load it PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -17836,7 +18277,7 @@ and use the import button to load it - + FOLLOW @@ -17844,8 +18285,8 @@ and use the import button to load it QObject - - + + Confirmation @@ -18113,12 +18554,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + File Request canceled - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. @@ -18149,7 +18590,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + Cannot start Tor Manager! @@ -18183,7 +18624,7 @@ The error reported is:" - + Multiple instances @@ -18202,6 +18643,26 @@ The error reported is:" + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -18281,7 +18742,7 @@ Reported error is: - + You appear to have nodes associated to DSA keys: @@ -18291,7 +18752,7 @@ Reported error is: - + enabled @@ -18301,7 +18762,7 @@ Reported error is: - + Move IP %1 to whitelist @@ -18317,7 +18778,7 @@ Reported error is: - + %1 seconds ago @@ -18384,7 +18845,7 @@ Security: no anonymous IDs - + Join chat room @@ -18412,7 +18873,7 @@ Security: no anonymous IDs - + Indefinitely @@ -18592,13 +19053,29 @@ Security: no anonymous IDs Ban list + + + Name + Ime + + Node + + + + + Address + + + + + Status Stanje - + NXS @@ -18841,6 +19318,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -18980,7 +19469,7 @@ p, li { white-space: pre-wrap; } - + Network Wide @@ -19147,7 +19636,7 @@ p, li { white-space: pre-wrap; } - + The loading of embedded images is blocked. @@ -19160,7 +19649,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default @@ -19333,12 +19822,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -19346,12 +19845,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -20039,7 +20538,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name Ime @@ -20160,7 +20659,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name Ime @@ -20180,7 +20679,7 @@ If you believe it is correct, remove the corresponding line from the file and re - + Profile ID @@ -20236,7 +20735,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -20250,11 +20749,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - - RsMessageModel @@ -20268,6 +20762,11 @@ prevents the message to be forwarded to your friends. From + + + To + + Subject @@ -20290,12 +20789,17 @@ prevents the message to be forwarded to your friends. - Click to sort by read + Click to sort by read status - Click to sort by from + Click to sort by author + + + + + Click to sort by destination @@ -20319,7 +20823,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -20340,7 +20846,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. @@ -20401,7 +20907,7 @@ prevents the message to be forwarded to your friends. - + Unable to open log file '%1': %2 @@ -20422,7 +20928,7 @@ prevents the message to be forwarded to your friends. - + opmode @@ -20452,7 +20958,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -20470,7 +20976,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -20487,12 +20993,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) - + Start Search @@ -20553,7 +21059,7 @@ prevents the message to be forwarded to your friends. - + KeyWords @@ -20568,7 +21074,7 @@ prevents the message to be forwarded to your friends. - + Filename @@ -20668,23 +21174,23 @@ prevents the message to be forwarded to your friends. - + File Name - + Download - + Copy RetroShare Link - + Send RetroShare Link @@ -20694,7 +21200,7 @@ prevents the message to be forwarded to your friends. - + Download Notice @@ -20731,7 +21237,7 @@ prevents the message to be forwarded to your friends. - + Folder @@ -20742,17 +21248,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) - + Open Folder - + Create Collection... @@ -20772,7 +21278,7 @@ prevents the message to be forwarded to your friends. - + Collection @@ -20780,7 +21286,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details @@ -20796,22 +21302,22 @@ prevents the message to be forwarded to your friends. - + IP address: - + Peer ID: - + Location: - + Peer Name: @@ -20828,7 +21334,7 @@ prevents the message to be forwarded to your friends. - + but reported: @@ -20853,8 +21359,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -20862,7 +21368,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare @@ -20893,7 +21399,7 @@ prevents the message to be forwarded to your friends. - + Expand @@ -20938,12 +21444,12 @@ prevents the message to be forwarded to your friends. - + Write Message - + Connect Attempt @@ -20963,17 +21469,12 @@ prevents the message to be forwarded to your friends. - + Unknown Security Issue - - A unknown peer - - - - + Unknown @@ -20983,7 +21484,17 @@ prevents the message to be forwarded to your friends. - + + SSL request + + + + + An unknown peer + + + + Hide @@ -20993,7 +21504,7 @@ prevents the message to be forwarded to your friends. - + Certificate has wrong signature!! This peer is not who he claims to be. @@ -21003,12 +21514,12 @@ prevents the message to be forwarded to your friends. - + Certificate caused an internal error. - + Peer/node not in friendlist (PGP id= @@ -21067,12 +21578,12 @@ prevents the message to be forwarded to your friends. - + Local Address - + NAT @@ -21093,22 +21604,22 @@ prevents the message to be forwarded to your friends. - + Local network - + External ip address finder - + UPnP - + Known / Previous IPs: @@ -21121,21 +21632,16 @@ behind a firewall or a VPN. - - Allow RetroShare to ask my ip to these websites: - - - - - - + + + kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -21145,23 +21651,46 @@ behind a firewall or a VPN. - + Onion Address - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -21171,7 +21700,7 @@ behind a firewall or a VPN. - + I2P Address @@ -21196,37 +21725,95 @@ behind a firewall or a VPN. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -21241,71 +21828,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. neznano - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -21315,22 +21838,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -21342,12 +21850,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -21357,7 +21865,7 @@ Also check your ports! - + Download limit (KB/s) @@ -21372,23 +21880,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -21399,17 +21907,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -21419,12 +21917,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -21434,17 +21927,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -21484,7 +21967,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start @@ -21499,12 +21982,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - BOB status - - - - + Incoming @@ -21540,7 +22018,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -21595,7 +22098,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Warning: This bandwidth adds up to the max bandwidth. @@ -21620,7 +22123,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -21632,7 +22135,7 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Filters @@ -21655,7 +22158,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status Stanje @@ -21715,17 +22218,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -21741,18 +22255,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -21787,12 +22301,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -21815,22 +22329,22 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -21865,7 +22379,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -21875,12 +22389,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -21960,7 +22474,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with @@ -21970,12 +22484,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Share - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -21994,7 +22508,7 @@ Select the Friends with which you want to Share your Channel. - + Shared directory @@ -22014,17 +22528,17 @@ Select the Friends with which you want to Share your Channel. - + Add new - + Cancel Prekliči - + Add a Share Directory @@ -22034,7 +22548,7 @@ Select the Friends with which you want to Share your Channel. - + Apply and close @@ -22125,7 +22639,7 @@ Select the Friends with which you want to Share your Channel. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. @@ -22133,7 +22647,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files @@ -22184,11 +22698,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files - + Download selected @@ -22198,7 +22717,7 @@ Select the Friends with which you want to Share your Channel. - + Copy retroshare Links to Clipboard @@ -22213,7 +22732,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted @@ -22229,7 +22748,7 @@ Select the Friends with which you want to Share your Channel. - + Create Collection... @@ -22254,7 +22773,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted because they have not been indexed yet. @@ -22397,12 +22916,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration - + Create interface @@ -22426,7 +22945,7 @@ Select the Friends with which you want to Share your Channel. - + Log In @@ -22765,7 +23284,7 @@ This choice can be reverted in settings. - + Message: @@ -23002,7 +23521,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags @@ -23038,12 +23557,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown @@ -23053,18 +23575,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -23074,12 +23591,57 @@ p, li { white-space: pre-wrap; } - + + Error + + + + + Not connected + + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -23087,7 +23649,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -23097,7 +23659,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -23108,11 +23670,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -23140,7 +23703,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options @@ -23151,7 +23714,7 @@ p, li { white-space: pre-wrap; } - + Shared Directories @@ -23161,22 +23724,27 @@ p, li { white-space: pre-wrap; } - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -23261,7 +23829,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -23270,7 +23838,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -23295,7 +23868,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming @@ -23360,12 +23938,7 @@ p, li { white-space: pre-wrap; } - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -23375,7 +23948,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -23403,7 +23986,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed @@ -23431,19 +24014,19 @@ p, li { white-space: pre-wrap; } TransfersDialog - - + + Downloads - + Uploads - + Name i.e: file name Ime @@ -23650,7 +24233,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... @@ -23675,7 +24263,7 @@ p, li { white-space: pre-wrap; } - + Anonymous end-to-end encrypted tunnel 0x @@ -23696,7 +24284,7 @@ p, li { white-space: pre-wrap; } - + @@ -23729,7 +24317,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name @@ -23744,7 +24342,7 @@ p, li { white-space: pre-wrap; } - + Expand all @@ -23871,23 +24469,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns - + File Transfers - + Path Pot @@ -23897,7 +24490,7 @@ p, li { white-space: pre-wrap; } - + Could not delete preview file @@ -23907,7 +24500,7 @@ p, li { white-space: pre-wrap; } - + Create Collection... @@ -23922,7 +24515,7 @@ p, li { white-space: pre-wrap; } - + Collection @@ -23932,7 +24525,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x @@ -24346,12 +24939,17 @@ p, li { white-space: pre-wrap; } - + Enable Retroshare WEB Interface - + + Status: + + + + Web parameters @@ -24391,17 +24989,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -24411,12 +25019,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface @@ -24553,7 +25161,7 @@ p, li { white-space: pre-wrap; } - + Page Name @@ -24568,7 +25176,7 @@ p, li { white-space: pre-wrap; } - + << @@ -24656,7 +25264,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History @@ -24691,7 +25299,7 @@ p, li { white-space: pre-wrap; } - + \/ @@ -24721,14 +25329,18 @@ p, li { white-space: pre-wrap; } - - + + History + + + + Show Edit History - + Status Stanje @@ -24749,7 +25361,7 @@ p, li { white-space: pre-wrap; } - + Submit @@ -24832,16 +25444,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - - - - + Settings @@ -24856,7 +25459,7 @@ p, li { white-space: pre-wrap; } - + Who to Follow @@ -24876,7 +25479,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -24906,7 +25509,7 @@ p, li { white-space: pre-wrap; } - + Yourself @@ -24916,7 +25519,7 @@ p, li { white-space: pre-wrap; } - + RetroShare @@ -24979,35 +25582,42 @@ p, li { white-space: pre-wrap; } - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + + + + Location: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -25052,11 +25662,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + + + + + Following + + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) @@ -25134,7 +25774,7 @@ p, li { white-space: pre-wrap; } - + k e.g: 3.1 k @@ -25171,7 +25811,7 @@ p, li { white-space: pre-wrap; } pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_sr.ts b/retroshare-gui/src/lang/retroshare_sr.ts index 6d5a3f97d..01e51db3d 100644 --- a/retroshare-gui/src/lang/retroshare_sr.ts +++ b/retroshare-gui/src/lang/retroshare_sr.ts @@ -122,12 +122,12 @@ Напредна претрага - + Search Criteria Критеријум претраге - + Add a further search criterion. Додајте додатни критеријум претраге. @@ -137,7 +137,7 @@ Поништите критеријум претраге. - + Cancels the search. Отказује претрагу. @@ -157,13 +157,6 @@ Претражи - - AlbumCreateDialog - - Public - Јавно - - AlbumDialog @@ -548,7 +541,7 @@ p, li { white-space: pre-wrap; } Ретрошер - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. @@ -574,10 +567,23 @@ p, li { white-space: pre-wrap; } + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb %p kB @@ -620,7 +626,7 @@ p, li { white-space: pre-wrap; } Уклони - + Set your Avatar picture @@ -707,22 +713,10 @@ p, li { white-space: pre-wrap; } Поништи - Receive Rate - Брзина пријема - - - Send Rate - Брзина слања - - - + Always on Top Увек на врху - - Style - Стил - Changes the transparency of the Bandwidth Graph @@ -738,23 +732,11 @@ p, li { white-space: pre-wrap; } % Opaque % непровидно - - Save - Сачувај - - - Cancel - Откажи - Since: Од: - - Hide Settings - Сакриј подешавања - BandwidthStatsWidget @@ -827,7 +809,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment Коментар @@ -857,12 +839,12 @@ p, li { white-space: pre-wrap; } - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -870,7 +852,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up @@ -890,7 +872,7 @@ p, li { white-space: pre-wrap; } - + Posted by @@ -928,7 +910,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up @@ -948,7 +930,7 @@ p, li { white-space: pre-wrap; } - + Click to view picture @@ -978,7 +960,7 @@ p, li { white-space: pre-wrap; } - + Toggle Message Read Status Промени статус порука @@ -988,7 +970,7 @@ p, li { white-space: pre-wrap; } - + TextLabel @@ -996,12 +978,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this - + 0 0 @@ -1021,18 +1003,18 @@ p, li { white-space: pre-wrap; } - + New Comment - + Copy RetroShare Link - + Expand Прошири @@ -1047,12 +1029,12 @@ p, li { white-space: pre-wrap; } Уклони ставку - + Name Назив - + Comm value @@ -1221,17 +1203,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels - + Tabs - + General @@ -1241,7 +1223,17 @@ p, li { white-space: pre-wrap; } - + + Downloads + + + + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab @@ -1249,7 +1241,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1272,7 +1264,7 @@ into the image, so as to ChannelsCommentsItem - + I like this @@ -1297,18 +1289,18 @@ into the image, so as to - + New Comment - + Copy RetroShare Link - + Expand Прошири @@ -1323,7 +1315,7 @@ into the image, so as to Уклони ставку - + Name Назив @@ -1333,17 +1325,7 @@ into the image, so as to - - Comment - Коментар - - - - Comments - - - - + Hide Сакриј @@ -1351,7 +1333,7 @@ into the image, so as to ChatLobbyDialog - + Name Назив @@ -1542,7 +1524,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby @@ -1575,13 +1557,14 @@ into the image, so as to - + + Unknown Lobby - - + + Remove All @@ -1589,13 +1572,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Назив - + Count @@ -1605,29 +1588,7 @@ into the image, so as to - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - - - - - - Public chat rooms - - - - + Create chat room @@ -1637,7 +1598,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1694,12 +1655,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1709,23 +1670,42 @@ Double click a chat room to enter and chat. - + [No topic provided] - + + Private Subscribed + + + + + + Public Subscribed + + + + + Private Приватно - + + + Public Јавно - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted @@ -1735,38 +1715,25 @@ Double click a chat room to enter and chat. - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe - + Search Chat lobbies - + Search Name - + Columns - - Yes - Да - - - No - Не - Chat rooms @@ -1778,47 +1745,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: - + Type: - + Security: - + Peers: - - - - - - + + + + + + TextLabel @@ -1833,7 +1800,7 @@ Double click a chat room to enter and chat. - + Show Прикажи @@ -1853,7 +1820,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item Уклони ставку @@ -1898,7 +1865,7 @@ Double click a chat room to enter and chat. ChatPage - + General @@ -1913,7 +1880,7 @@ Double click a chat room to enter and chat. - + Enable custom fonts @@ -1933,7 +1900,7 @@ Double click a chat room to enter and chat. - + General settings @@ -1958,7 +1925,7 @@ Double click a chat room to enter and chat. - + Blink tab icon @@ -1988,7 +1955,7 @@ Double click a chat room to enter and chat. - + Change Chat Font @@ -1998,14 +1965,10 @@ Double click a chat room to enter and chat. - + History - - Style - Стил - @@ -2026,7 +1989,7 @@ Double click a chat room to enter and chat. - + Choose your default font for Chat. @@ -2096,12 +2059,22 @@ Double click a chat room to enter and chat. - + Search Претражи - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2111,7 +2084,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2208,7 +2191,7 @@ Double click a chat room to enter and chat. - + Case sensitive Разликује велика и мала слова @@ -2314,7 +2297,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat @@ -2350,7 +2333,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close Затвори @@ -2385,12 +2368,12 @@ Double click a chat room to enter and chat. - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2470,11 +2453,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2512,7 +2490,7 @@ Double click a chat room to enter and chat. - + is typing... @@ -2534,7 +2512,7 @@ after HTML conversion. - + Do you really want to physically delete the history? @@ -2584,7 +2562,7 @@ after HTML conversion. - + Find Case Sensitively @@ -2606,7 +2584,7 @@ after HTML conversion. - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> @@ -2621,12 +2599,12 @@ after HTML conversion. - + (Status) - + Attach a File @@ -2642,12 +2620,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> - + Person id: @@ -2658,12 +2636,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. @@ -2683,7 +2661,7 @@ Double click on it to add his name on text writer. - + Don't stop to color after @@ -2709,7 +2687,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: @@ -2731,7 +2709,7 @@ Double click on it to add his name on text writer. - + Personal Circles @@ -2757,7 +2735,7 @@ Double click on it to add his name on text writer. - + Friends @@ -2817,7 +2795,7 @@ Double click on it to add his name on text writer. - + External Circles (Admin) @@ -2833,7 +2811,7 @@ Double click on it to add his name on text writer. - + Circles @@ -2885,45 +2863,45 @@ Double click on it to add his name on text writer. - + RetroShare Ретрошер - + - + Error : cannot get peer details. - + Retroshare ID - + <p>This Retroshare ID contains: - + <p>This certificate contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: @@ -2933,7 +2911,7 @@ Double click on it to add his name on text writer. - + Not connected @@ -3015,12 +2993,17 @@ Double click on it to add his name on text writer. - + <li>a <b>node ID</b> and <b>name</b> - + + <b>DNS:</b> : + + + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3040,7 +3023,7 @@ Double click on it to add his name on text writer. - + with @@ -3108,7 +3091,7 @@ Double click on it to add his name on text writer. - + @@ -3124,12 +3107,12 @@ Double click on it to add his name on text writer. - + Peer details - + Name: Назив: @@ -3139,17 +3122,17 @@ Double click on it to add his name on text writer. Место: - + Options Опције - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: @@ -3159,7 +3142,7 @@ Double click on it to add his name on text writer. - + Please paste below your friend's Retroshare ID @@ -3184,12 +3167,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with - + Sorry, some error appeared @@ -3209,32 +3202,27 @@ Double click on it to add his name on text writer. - + Key validity: - + Profile ID: - - Signers - - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. - + To accept the Friend Request, click the Accept button. @@ -3280,17 +3268,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed - + Not a valid Retroshare certificate! - + RetroShare Invitation @@ -3310,12 +3298,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3323,7 +3311,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3363,7 +3351,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Profile password needed. @@ -3388,7 +3376,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3398,7 +3386,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3437,7 +3425,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + IP-Addr: @@ -3447,7 +3435,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Show Advanced options @@ -3472,7 +3460,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already in your keyring @@ -3485,7 +3473,7 @@ even if you don't make friends. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. @@ -3520,7 +3508,7 @@ even if you don't make friends. - + No IP in this certificate! @@ -3530,12 +3518,7 @@ even if you don't make friends. - - [Unknown] - - - - + Added with certificate from %1 @@ -3600,7 +3583,7 @@ even if you don't make friends. - + UDP Setup @@ -3628,7 +3611,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant @@ -3638,17 +3621,20 @@ p, li { white-space: pre-wrap; } - + + Unknown State - + + Offline - + + Behind Symmetric NAT @@ -3658,12 +3644,14 @@ p, li { white-space: pre-wrap; } - + + NET Restart - + + Behind NAT @@ -3673,7 +3661,8 @@ p, li { white-space: pre-wrap; } - + + NET STATE GOOD! @@ -3698,7 +3687,7 @@ p, li { white-space: pre-wrap; } - + Lookup requires DHT @@ -3990,7 +3979,7 @@ p, li { white-space: pre-wrap; } - + @@ -3998,7 +3987,8 @@ p, li { white-space: pre-wrap; } - + + UNVERIFIABLE FORWARD! @@ -4008,7 +3998,7 @@ p, li { white-space: pre-wrap; } - + Searching @@ -4044,12 +4034,12 @@ p, li { white-space: pre-wrap; } - + Name Назив - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4069,7 +4059,7 @@ p, li { white-space: pre-wrap; } - + IDs ИД @@ -4089,18 +4079,18 @@ p, li { white-space: pre-wrap; } - + Cancel - + Nickname - + Invited Members @@ -4115,11 +4105,7 @@ p, li { white-space: pre-wrap; } - ID - ИД - - - + Name: Назив: @@ -4159,19 +4145,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare Ретрошер - + Please set a name for your Circle - + No Restriction Circle Selected @@ -4181,12 +4167,24 @@ p, li { white-space: pre-wrap; } - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add Додај @@ -4196,7 +4194,7 @@ p, li { white-space: pre-wrap; } - + Search Претражи @@ -4249,13 +4247,13 @@ p, li { white-space: pre-wrap; } - + Create - + Add Member @@ -4274,7 +4272,7 @@ p, li { white-space: pre-wrap; } - + Group Name: @@ -4309,7 +4307,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post @@ -4319,7 +4317,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4464,17 +4462,17 @@ p, li { white-space: pre-wrap; } - + RetroShare Ретрошер - + This file already in this post: - + Post refers to non shared files @@ -4499,7 +4497,12 @@ p, li { white-space: pre-wrap; } - + + Cannot publish post + + + + Load thumbnail picture @@ -4514,18 +4517,12 @@ p, li { white-space: pre-wrap; } Сакриј - - + Generate mass data - - Do you really want to generate %1 messages ? - - - - + You are about to add files you're not actually sharing. Do you still want this to happen? @@ -4559,7 +4556,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message @@ -4568,10 +4565,6 @@ p, li { white-space: pre-wrap; } Forum - - Subject - Наслов - Attach File @@ -4592,8 +4585,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -4612,7 +4605,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4642,17 +4635,17 @@ p, li { white-space: pre-wrap; } - + No Forum - + In Reply to - + Title @@ -4705,7 +4698,7 @@ Do you want to discard this message? - + No compatible ID for this forum @@ -4715,8 +4708,8 @@ Do you want to discard this message? - - + + Generate mass data @@ -4739,7 +4732,7 @@ Do you want to discard this message? CreateLobbyDialog - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -4774,7 +4767,7 @@ Do you want to discard this message? - + Create @@ -4784,7 +4777,7 @@ Do you want to discard this message? - + require PGP-signed identities @@ -4799,7 +4792,7 @@ Do you want to discard this message? - + Create Chat Room @@ -4820,7 +4813,7 @@ Do you want to discard this message? - + Identity to use: @@ -4828,17 +4821,17 @@ Do you want to discard this message? CryptoPage - + Public Information - + Name: Назив: - + Location: Место: @@ -4848,12 +4841,12 @@ Do you want to discard this message? - + Software Version: - + Online since: @@ -4873,12 +4866,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -4888,7 +4876,7 @@ Do you want to discard this message? - + Other Information @@ -4898,17 +4886,12 @@ Do you want to discard this message? - + Profile - - Certificate - - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -4918,7 +4901,7 @@ Do you want to discard this message? - + Export Identity @@ -4988,33 +4971,33 @@ and use the import button to load it - + TextLabel - + PGP fingerprint: - - Node information - - - - + PGP Id : - + Friend nodes: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5104,7 +5087,7 @@ and use the import button to load it DLListDelegate - + B @@ -5772,7 +5755,7 @@ and use the import button to load it DownloadToaster - + Start file @@ -5780,38 +5763,38 @@ and use the import button to load it ExprParamElement - + - + to - + ignore case - - - dd.MM.yyyy + + + yyyy-MM-dd - - + + KB - - + + MB - - + + GB @@ -5819,12 +5802,12 @@ and use the import button to load it ExpressionWidget - + Expression Widget - + Delete this expression @@ -5986,7 +5969,7 @@ and use the import button to load it FilesDefs - + Picture @@ -5996,7 +5979,7 @@ and use the import button to load it - + Audio @@ -6056,11 +6039,21 @@ and use the import button to load it C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories @@ -6182,7 +6175,7 @@ and use the import button to load it - + ID ИД @@ -6224,7 +6217,7 @@ and use the import button to load it - + Group @@ -6260,7 +6253,7 @@ and use the import button to load it - + Search Претражи @@ -6276,7 +6269,7 @@ and use the import button to load it - + Profile details @@ -6513,7 +6506,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request @@ -6551,7 +6544,7 @@ at least one peer was not added to a group - + Mark all @@ -6562,16 +6555,132 @@ at least one peer was not added to a group + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Назив + + + + Node ID + + + + + Address + + + + + Status + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message - - + + Broadcast @@ -6654,33 +6763,38 @@ at least one peer was not added to a group - + Keyring - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. - - + + Network - + + Friend Server + + + + Network graph - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. @@ -6698,7 +6812,17 @@ at least one peer was not added to a group - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters @@ -6708,17 +6832,12 @@ at least one peer was not added to a group - + Port - - Use BOB - - - - + This password is for PGP @@ -6739,38 +6858,38 @@ at least one peer was not added to a group - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -6790,12 +6909,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -6805,38 +6924,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel - + hidden address - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -6880,13 +7004,13 @@ and use the import button to load it - + Import profile - + Create new profile and new Retroshare node @@ -6896,7 +7020,7 @@ and use the import button to load it - + Tor/I2P address @@ -6931,7 +7055,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -6941,12 +7065,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -6956,12 +7075,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7187,27 +7301,13 @@ and use the import button to load it - + Invite Friends - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - - - - + Add Your Friends to RetroShare @@ -7217,39 +7317,57 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + Connect To Friends - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port @@ -7257,49 +7375,45 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - - - - + Further Help and Support - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website @@ -7324,7 +7438,7 @@ p, li { white-space: pre-wrap; } - + RetroShare Invitation @@ -7374,12 +7488,12 @@ p, li { white-space: pre-wrap; } - + RetroShare Support - + It has many features, including built-in chat, messaging, @@ -7503,7 +7617,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat @@ -7511,7 +7625,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] @@ -7681,7 +7795,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title @@ -7694,12 +7808,12 @@ p, li { white-space: pre-wrap; } - + Description - + Number of Unread message @@ -7724,7 +7838,7 @@ p, li { white-space: pre-wrap; } - + You are admin (modify names and description using Edit menu) @@ -7739,14 +7853,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post Последња порука - + Name Назив @@ -7757,13 +7871,13 @@ p, li { white-space: pre-wrap; } Популарност - + Never - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -7776,7 +7890,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and @@ -7912,7 +8026,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels @@ -7923,22 +8037,22 @@ p, li { white-space: pre-wrap; } - + Enable Auto-Download - + My Channels - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels @@ -7958,12 +8072,12 @@ p, li { white-space: pre-wrap; } - + Disable Auto-Download - + Set download directory @@ -7998,22 +8112,22 @@ p, li { white-space: pre-wrap; } - + Play - + Open folder - + Open file - + Error @@ -8033,17 +8147,17 @@ p, li { white-space: pre-wrap; } - + Are you sure that you want to cancel and delete the file? - + Can't open folder - + Play File @@ -8053,17 +8167,10 @@ p, li { white-space: pre-wrap; } - - GxsChannelFilesWidget - - Form - Образац - - GxsChannelGroupDialog - + Create New Channel @@ -8101,8 +8208,18 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel @@ -8117,7 +8234,7 @@ p, li { white-space: pre-wrap; } - + Expand Прошири @@ -8132,7 +8249,7 @@ p, li { white-space: pre-wrap; } - + Loading @@ -8146,6 +8263,11 @@ p, li { white-space: pre-wrap; } New Channel: + + + Never + + Hide @@ -8155,7 +8277,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: @@ -8176,7 +8298,7 @@ p, li { white-space: pre-wrap; } - + Play @@ -8238,18 +8360,18 @@ p, li { white-space: pre-wrap; } Сакриј - + New - + 0 0 - - + + Comment Коментар @@ -8264,17 +8386,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + Comments - + Post @@ -8302,13 +8424,13 @@ p, li { white-space: pre-wrap; } GxsChannelPostsWidgetWithModel - + Post to Channel - + Add new post @@ -8378,7 +8500,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -8414,7 +8536,7 @@ p, li { white-space: pre-wrap; } - + Comments @@ -8429,13 +8551,13 @@ p, li { white-space: pre-wrap; } - - + + Click to switch to list view - + Show unread posts only @@ -8450,7 +8572,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -8465,7 +8587,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -8525,12 +8647,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -8605,12 +8737,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed @@ -8661,17 +8794,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -8786,7 +8919,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container @@ -8799,7 +8932,7 @@ p, li { white-space: pre-wrap; } Образац - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -8829,7 +8962,7 @@ p, li { white-space: pre-wrap; } - + Comment Коментар @@ -8868,7 +9001,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment @@ -8892,6 +9025,21 @@ p, li { white-space: pre-wrap; } Vote Down + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -8901,7 +9049,7 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -8930,7 +9078,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -8961,7 +9109,7 @@ before you can comment - + It remains %1 characters after HTML conversion. @@ -9012,7 +9160,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum @@ -9028,7 +9176,7 @@ before you can comment - + Expand Прошири @@ -9047,6 +9195,11 @@ before you can comment Moderator list + + + TextLabel + + Loading... @@ -9076,13 +9229,13 @@ before you can comment GxsForumMsgItem - - + + Subject: - + Unsubscribe To Forum @@ -9093,7 +9246,7 @@ before you can comment - + Expand Прошири @@ -9113,17 +9266,17 @@ before you can comment - + Loading... - + Forum Feed - + Hide Сакриј @@ -9136,63 +9289,66 @@ before you can comment Образац - + Start new Thread for Selected Forum - + + Threaded + + + + + + + ... + + + + + Flat + + + + + Latest post in thread + + + + Search forums - Last Post - Последња порука - - - + New Thread - - - Threaded View - - - - - Flat View - - - + Title - - + + Date - + Author - - Save image - - - - + Loading - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9202,12 +9358,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message @@ -9247,23 +9398,23 @@ before you can comment - + No name - - + + Reply - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -9306,16 +9457,12 @@ before you can comment - + Hide Сакриј - Expand - Прошири - - - + [unknown] @@ -9345,8 +9492,8 @@ before you can comment - - + + Distribution @@ -9429,12 +9576,12 @@ before you can comment - + New thread - + Edit @@ -9495,7 +9642,7 @@ before you can comment - + Show column @@ -9515,7 +9662,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive @@ -9567,7 +9714,7 @@ This message is missing. You should receive it later. - + No result. @@ -9577,7 +9724,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -9592,7 +9739,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -9658,12 +9805,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums @@ -9698,12 +9845,12 @@ This message is missing. You should receive it later. GxsGroupDialog - + Name Назив - + Key recipients can publish to restricted-type group and can view and publish for private-type channels @@ -9714,12 +9861,12 @@ This message is missing. You should receive it later. - + Description - + Message Distribution @@ -9727,7 +9874,7 @@ This message is missing. You should receive it later. - + Public Јавно @@ -9787,7 +9934,7 @@ This message is missing. You should receive it later. - + Comments: @@ -9810,7 +9957,7 @@ This message is missing. You should receive it later. - + All People @@ -9826,12 +9973,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -9848,23 +9995,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -9880,22 +10027,28 @@ This message is missing. You should receive it later. - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo - + Submit Group Changes - + Owner: @@ -9905,12 +10058,12 @@ This message is missing. You should receive it later. - + Info - + ID ИД @@ -9920,7 +10073,7 @@ This message is missing. You should receive it later. Последња порука - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -9995,7 +10148,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity Популарност @@ -10011,27 +10169,22 @@ This message is missing. You should receive it later. - + Created - + Cancel - + Create - - Author - - - - + GxsIdLabel @@ -10039,7 +10192,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading @@ -10099,7 +10252,7 @@ This message is missing. You should receive it later. - + Synchronise posts of last... @@ -10156,12 +10309,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link @@ -10184,7 +10337,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature @@ -10197,14 +10350,14 @@ This message is missing. You should receive it later. GxsIdDetails - + Not found - - + + [Banned] @@ -10214,7 +10367,7 @@ This message is missing. You should receive it later. - + Loading... @@ -10224,7 +10377,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -10244,6 +10402,14 @@ This message is missing. You should receive it later. + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -10255,7 +10421,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -10303,7 +10469,7 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] @@ -10690,7 +10856,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -10706,7 +10872,7 @@ p, li { white-space: pre-wrap; } - + Authors @@ -10725,7 +10891,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -10799,7 +10965,7 @@ p, li { white-space: pre-wrap; } Образац - + Add friend @@ -10809,7 +10975,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -10837,7 +11003,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -10847,7 +11013,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard @@ -10857,7 +11023,7 @@ private and secure decentralized communication platform. - + Send via Email @@ -10877,13 +11043,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -10895,12 +11085,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -10915,12 +11105,7 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... @@ -11185,14 +11370,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All - + Reputation @@ -11202,12 +11387,12 @@ p, li { white-space: pre-wrap; } Претражи - + Anonymous Id - + Create new Identity @@ -11217,7 +11402,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -11232,27 +11417,27 @@ p, li { white-space: pre-wrap; } - + Close Затвори - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -11268,29 +11453,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles - + Circle name @@ -11310,18 +11505,20 @@ p, li { white-space: pre-wrap; } - + + Edit identity - + + Delete identity - + Chat with this peer @@ -11331,78 +11528,78 @@ p, li { white-space: pre-wrap; } - + Owner node ID : - + Identity name : - + () - + Identity ID - + Send message - + Identity info - + Identity ID : - + Owner node name : - + Create new... - + Type: - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: - + Negative - + Neutral @@ -11413,17 +11610,17 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous @@ -11438,24 +11635,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you - - + + My own identities - - + + My contacts - + Show Items @@ -11470,7 +11667,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -11480,7 +11682,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -11555,7 +11757,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -11585,7 +11787,7 @@ p, li { white-space: pre-wrap; } - + Invited @@ -11600,7 +11802,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle @@ -11648,7 +11850,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -11656,7 +11858,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -11699,7 +11901,7 @@ These identities will soon be not supported anymore. - + Boards @@ -11779,7 +11981,7 @@ These identities will soon be not supported anymore. - + information @@ -11795,17 +11997,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -11910,7 +12107,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -11960,21 +12157,21 @@ These identities will soon be not supported anymore. - - - + + + People - + Your Avatar Click here to change your avatar - + Linked to neighbor nodes @@ -11984,7 +12181,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -11999,7 +12196,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -12014,12 +12211,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -12039,12 +12236,12 @@ These identities will soon be not supported anymore. - + Owned by - + Node name: @@ -12054,7 +12251,7 @@ These identities will soon be not supported anymore. - + Really delete? @@ -12062,7 +12259,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname @@ -12092,7 +12289,13 @@ These identities will soon be not supported anymore. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity @@ -12106,7 +12309,7 @@ These identities will soon be not supported anymore. - + @@ -12116,7 +12319,12 @@ These identities will soon be not supported anymore. - + + No avatar chosen + + + + Edit identity @@ -12127,27 +12335,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -12167,7 +12375,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -12177,12 +12385,18 @@ These identities will soon be not supported anymore. - + Error KeyID invalid - + + + No Avatar chosen. A default image will be automatically displayed from your new identity. + + + + Import image @@ -12192,12 +12406,7 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. - - - - + Unknown GpgId @@ -12207,7 +12416,7 @@ These identities will soon be not supported anymore. - + Create New Identity @@ -12217,10 +12426,15 @@ These identities will soon be not supported anymore. - + Choose image... + + + Remove + Уклони + @@ -12246,7 +12460,7 @@ These identities will soon be not supported anymore. Додај - + Create @@ -12256,13 +12470,13 @@ These identities will soon be not supported anymore. - + Your Avatar Click here to change your avatar - + Linked to your profile @@ -12272,7 +12486,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -12346,7 +12560,7 @@ These identities will soon be not supported anymore. - + Copy Умножи @@ -12356,12 +12570,12 @@ These identities will soon be not supported anymore. Уклони - + %1 's Message History - + Mark all @@ -12384,18 +12598,34 @@ These identities will soon be not supported anymore. ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -12413,27 +12643,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: - + Listen Address: - + + Status: + Статус: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -12454,7 +12689,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -12463,26 +12703,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File - + Open Folder - + Checking... @@ -12492,7 +12737,7 @@ These identities will soon be not supported anymore. - + Recommend in a message to... @@ -12520,7 +12765,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend @@ -12536,7 +12781,8 @@ These identities will soon be not supported anymore. - + + Options Опције @@ -12557,7 +12803,7 @@ These identities will soon be not supported anymore. - + Quit @@ -12568,12 +12814,12 @@ These identities will soon be not supported anymore. - + RetroShare %1 a secure decentralized communication platform - + Unfinished @@ -12598,11 +12844,12 @@ These identities will soon be not supported anymore. + Status - + Notify @@ -12613,31 +12860,35 @@ These identities will soon be not supported anymore. + Open Messages - + + Bandwidth Graph - + Applications + Help Помоћ - + + Minimize - + Maximize @@ -12652,7 +12903,12 @@ These identities will soon be not supported anymore. Ретрошер - + + Close window + + + + %1 new message @@ -12682,7 +12938,7 @@ These identities will soon be not supported anymore. - + Do you really want to exit RetroShare ? @@ -12702,7 +12958,7 @@ These identities will soon be not supported anymore. Прикажи - + Make sure this link has not been forged to drag you to a malicious website. @@ -12747,12 +13003,13 @@ These identities will soon be not supported anymore. - + + Statistics - + Show web interface @@ -12767,7 +13024,7 @@ These identities will soon be not supported anymore. - + Really quit ? @@ -12776,17 +13033,17 @@ These identities will soon be not supported anymore. MessageComposer - + Compose - + Contacts - + Paragraph @@ -12822,12 +13079,12 @@ These identities will soon be not supported anymore. - + Font size - + Increase font size @@ -12842,32 +13099,32 @@ These identities will soon be not supported anymore. - + Italic - + Alignment - + Add an Image - + Sets text font to code style - + Underline - + Subject: @@ -12878,32 +13135,32 @@ These identities will soon be not supported anymore. - + Tags - + Address list: - + Recommend this friend - + Set Text color - + Set Text background color - + Recommended Files @@ -12973,7 +13230,7 @@ These identities will soon be not supported anymore. - + Send To: @@ -13013,7 +13270,7 @@ These identities will soon be not supported anymore. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> @@ -13033,18 +13290,18 @@ These identities will soon be not supported anymore. - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team - - + + Save Message - + Message has not been Sent. Do you want to save message to draft box? @@ -13055,7 +13312,17 @@ Do you want to save message to draft box? - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" @@ -13075,7 +13342,7 @@ Do you want to save message to draft box? - + Original Message @@ -13085,21 +13352,21 @@ Do you want to save message to draft box? - + - + To - - + + Cc - + Sent @@ -13114,7 +13381,7 @@ Do you want to save message to draft box? - + Re: @@ -13124,30 +13391,30 @@ Do you want to save message to draft box? - - - + + + RetroShare Ретрошер - + Do you want to send the message without a subject ? - + Please insert at least one recipient. - + Bcc - + Unknown @@ -13262,13 +13529,13 @@ Do you want to save message to draft box? - + Open File... - + HTML-Files (*.htm *.html);;All Files (*) @@ -13288,7 +13555,7 @@ Do you want to save message to draft box? - + Message has not been Sent. Do you want to save message ? @@ -13309,7 +13576,7 @@ Do you want to save message ? - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -13339,18 +13606,18 @@ Do you want to save message ? - - + + Close Затвори - + From: - + Bullet list (disc) @@ -13390,13 +13657,13 @@ Do you want to save message ? - - + + Thanks, <br> - + Distant identity: @@ -13406,12 +13673,12 @@ Do you want to save message ? - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -13489,7 +13756,7 @@ Do you want to save message ? Подразумевано - + A new tab @@ -13499,7 +13766,7 @@ Do you want to save message ? - + Edit Tag @@ -13522,7 +13789,7 @@ Do you want to save message ? MessageToaster - + Sub: @@ -13530,7 +13797,7 @@ Do you want to save message ? MessageUserNotify - + Message @@ -13558,7 +13825,7 @@ Do you want to save message ? MessageWidget - + Recommended Files @@ -13568,37 +13835,37 @@ Do you want to save message ? - + Subject: - + From: - + To: - + Cc: - + Bcc: - + Tags: - + Reply @@ -13638,7 +13905,7 @@ Do you want to save message ? - + Send Invite @@ -13690,7 +13957,7 @@ Do you want to save message ? - + Confirm %1 as friend @@ -13700,12 +13967,12 @@ Do you want to save message ? - + View source - + No subject @@ -13715,17 +13982,22 @@ Do you want to save message ? - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -13734,14 +14006,24 @@ Do you want to save message ? %1 (%2) + + + Show less + + + + + Show more + + - + Download all - + Print Document @@ -13756,12 +14038,12 @@ Do you want to save message ? - + Load images always for this message - + Hide the attachment pane @@ -13783,10 +14065,6 @@ Do you want to save message ? Compose - - Delete - Обриши - Print @@ -13865,7 +14143,7 @@ Do you want to save message ? MessagesDialog - + New Message @@ -13875,20 +14153,16 @@ Do you want to save message ? - Delete - Обриши - - - + - - + + Tags - - + + Inbox @@ -13918,17 +14192,17 @@ Do you want to save message ? - + Total Inbox: - + Quick View - + Print... @@ -13959,7 +14233,7 @@ Do you want to save message ? - + Subject Наслов @@ -13969,7 +14243,7 @@ Do you want to save message ? - + Date @@ -13979,7 +14253,7 @@ Do you want to save message ? - + Search Subject @@ -13988,6 +14262,16 @@ Do you want to save message ? Search From + + + To + + + + + Search To + + Search Date @@ -14014,12 +14298,12 @@ Do you want to save message ? - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred @@ -14095,7 +14379,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -14109,7 +14393,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -14124,18 +14408,28 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts - + No Box selected. - + @@ -14170,7 +14464,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -14224,7 +14528,7 @@ Do you want to save message ? - + Expand Прошири @@ -14234,7 +14538,7 @@ Do you want to save message ? Уклони ставку - + from @@ -14269,7 +14573,7 @@ Do you want to save message ? - + Hide Сакриј @@ -14410,7 +14714,7 @@ Do you want to save message ? - + Remove unused keys... @@ -14420,7 +14724,7 @@ Do you want to save message ? - + Clean keyring @@ -14434,7 +14738,13 @@ Notes: Your old keyring will be backed up. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info @@ -14467,18 +14777,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. - - - Export/create a new node - - Trusted keys only - + Search name @@ -14488,12 +14793,12 @@ For security, your keyring was previously backed-up to file - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -14526,7 +14831,7 @@ Reported error: NewFriendList - + Offline Friends @@ -14547,7 +14852,7 @@ Reported error: - + Groups @@ -14577,19 +14882,19 @@ Reported error: - - + + Search Претражи - + ID ИД - + Search ID @@ -14599,12 +14904,12 @@ Reported error: - + Show Items - + Last contact @@ -14614,7 +14919,7 @@ Reported error: - + Group @@ -14729,7 +15034,7 @@ Reported error: - + Do you want to remove this node? @@ -14739,7 +15044,7 @@ Reported error: - + Done! @@ -14846,7 +15151,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -14861,7 +15166,7 @@ at least one peer was not added to a group - + Newest on top @@ -14871,12 +15176,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15114,7 +15419,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -15134,12 +15439,12 @@ at least one peer was not added to a group - + Please enter your Retroshare passphrase - + Unregistered plugin/executable @@ -15154,7 +15459,7 @@ at least one peer was not added to a group - + Test @@ -15165,17 +15470,19 @@ at least one peer was not added to a group + Unknown title - + + Encrypted message - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -15183,7 +15490,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online @@ -15322,7 +15629,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -15367,12 +15679,7 @@ p, li { white-space: pre-wrap; } - - Options - Опције - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -15418,21 +15725,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare Ретрошер - - + + Error : cannot get peer details. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) @@ -15450,7 +15757,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -15526,12 +15833,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -15557,7 +15864,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat @@ -15578,7 +15885,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Уклони ставку - + Name: Назив: @@ -15618,7 +15925,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message @@ -15676,7 +15983,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Сакриј - + Send Message @@ -15843,13 +16150,6 @@ Warning: In your File-Transfer option, you select allow direct download to No. - - PhotoCommentItem - - Form - Образац - - PhotoDialog @@ -15862,10 +16162,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.TextLabel - - Comment - Коментар - Album / Photo Name @@ -16005,17 +16301,17 @@ p, li { white-space: pre-wrap; } - + My Albums - + Subscribed Albums - + Shared Albums @@ -16044,7 +16340,7 @@ requesting to edit it! PhotoSlideShow - + Album Name @@ -16103,19 +16399,19 @@ requesting to edit it! - - + + TextLabel - + Posted by - + ago @@ -16151,12 +16447,12 @@ requesting to edit it! PluginItem - + TextLabel - + Show more details about this plugin @@ -16367,12 +16663,27 @@ p, li { white-space: pre-wrap; } - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -16425,7 +16736,7 @@ p, li { white-space: pre-wrap; } - + Vote up @@ -16445,8 +16756,8 @@ p, li { white-space: pre-wrap; } - - + + Comments @@ -16471,13 +16782,13 @@ p, li { white-space: pre-wrap; } - - + + Comment Коментар - + Comments @@ -16505,12 +16816,12 @@ p, li { white-space: pre-wrap; } PostedCreatePostDialog - + Create a new Post - + RetroShare Ретрошер @@ -16525,12 +16836,22 @@ p, li { white-space: pre-wrap; } - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File - + Post image @@ -16546,7 +16867,17 @@ p, li { white-space: pre-wrap; } - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -16556,7 +16887,7 @@ p, li { white-space: pre-wrap; } - + Please add a Title @@ -16576,12 +16907,22 @@ p, li { white-space: pre-wrap; } - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -16596,7 +16937,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -16607,7 +16948,7 @@ p, li { white-space: pre-wrap; } - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -16617,7 +16958,7 @@ p, li { white-space: pre-wrap; } - + Link @@ -16625,12 +16966,12 @@ p, li { white-space: pre-wrap; } PostedDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -16664,7 +17005,7 @@ p, li { white-space: pre-wrap; } PostedGroupDialog - + Create New Board @@ -16702,7 +17043,17 @@ p, li { white-space: pre-wrap; } PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted @@ -16718,7 +17069,7 @@ p, li { white-space: pre-wrap; } - + Expand Прошири @@ -16733,12 +17084,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + + Never + + + + New Board @@ -16751,18 +17107,18 @@ p, li { white-space: pre-wrap; } PostedItem - + 0 0 - - + + Comments - + Copy RetroShare Link @@ -16773,12 +17129,12 @@ p, li { white-space: pre-wrap; } - + Comment Коментар - + Comments @@ -16788,7 +17144,7 @@ p, li { white-space: pre-wrap; } - + Click to view Picture @@ -16798,17 +17154,17 @@ p, li { white-space: pre-wrap; } Сакриј - + Vote up - + Vote down - + Set as read and remove item @@ -16818,7 +17174,7 @@ p, li { white-space: pre-wrap; } - + New Comment: @@ -16828,7 +17184,7 @@ p, li { white-space: pre-wrap; } - + Name Назив @@ -16869,22 +17225,11 @@ p, li { white-space: pre-wrap; } - + Loading - - PostedListWidget - - Form - Образац - - - RetroShare - Ретрошер - - PostedListWidgetWithModel @@ -16903,7 +17248,17 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -16913,15 +17268,15 @@ p, li { white-space: pre-wrap; } - + - + unknown - + Distribution: @@ -16931,42 +17286,42 @@ p, li { white-space: pre-wrap; } - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -16986,7 +17341,7 @@ p, li { white-space: pre-wrap; } - + Search Претражи @@ -17016,17 +17371,17 @@ p, li { white-space: pre-wrap; } - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -17041,12 +17396,17 @@ p, li { white-space: pre-wrap; } - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -17056,27 +17416,31 @@ p, li { white-space: pre-wrap; } - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -17091,7 +17455,7 @@ p, li { white-space: pre-wrap; } Пријави ме - + Never @@ -17165,6 +17529,16 @@ p, li { white-space: pre-wrap; } No Channel Selected + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -17254,16 +17628,16 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -17371,7 +17745,7 @@ and use the import button to load it ProfileWidget - + Edit status message @@ -17387,7 +17761,7 @@ and use the import button to load it - + Public Information @@ -17422,12 +17796,12 @@ and use the import button to load it - + Other Information - + My Address @@ -17471,27 +17845,27 @@ and use the import button to load it PulseAddDialog - + Add to Pulse - + Display As - + URL - + GroupLabel - + IDLabel @@ -17501,12 +17875,12 @@ and use the import button to load it - + Head - + Head Shot @@ -17536,13 +17910,13 @@ and use the import button to load it - - + + Whats happening? - + @@ -17554,12 +17928,22 @@ and use the import button to load it - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -17574,7 +17958,7 @@ and use the import button to load it - + Reply to Pulse @@ -17589,26 +17973,24 @@ and use the import button to load it - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - ... - + + Load Picture File + @@ -17619,7 +18001,7 @@ and use the import button to load it Образац - + @@ -17638,7 +18020,7 @@ and use the import button to load it PulseReply - + icn @@ -17648,7 +18030,7 @@ and use the import button to load it - + REPLY @@ -17675,7 +18057,7 @@ and use the import button to load it - + FOLLOW @@ -17685,7 +18067,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -17705,7 +18087,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -17821,7 +18203,7 @@ and use the import button to load it - + FOLLOW @@ -17829,37 +18211,42 @@ and use the import button to load it PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -17891,7 +18278,7 @@ and use the import button to load it - + FOLLOW @@ -17899,8 +18286,8 @@ and use the import button to load it QObject - - + + Confirmation @@ -18168,12 +18555,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + File Request canceled - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. @@ -18204,7 +18591,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + Cannot start Tor Manager! @@ -18238,7 +18625,7 @@ The error reported is:" - + Multiple instances @@ -18257,6 +18644,26 @@ The error reported is:" + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -18336,7 +18743,7 @@ Reported error is: - + You appear to have nodes associated to DSA keys: @@ -18346,7 +18753,7 @@ Reported error is: - + enabled @@ -18356,7 +18763,7 @@ Reported error is: - + Move IP %1 to whitelist @@ -18372,7 +18779,7 @@ Reported error is: - + %1 seconds ago @@ -18439,7 +18846,7 @@ Security: no anonymous IDs - + Join chat room @@ -18467,7 +18874,7 @@ Security: no anonymous IDs - + Indefinitely @@ -18647,13 +19054,29 @@ Security: no anonymous IDs Ban list + + + Name + Назив + - Status + Node + Address + + + + + + Status + + + + NXS @@ -18896,6 +19319,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -19035,7 +19470,7 @@ p, li { white-space: pre-wrap; } - + Network Wide @@ -19202,7 +19637,7 @@ p, li { white-space: pre-wrap; } Образац - + The loading of embedded images is blocked. @@ -19215,7 +19650,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default @@ -19388,12 +19823,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -19401,12 +19846,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -20094,7 +20539,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name Назив @@ -20215,7 +20660,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name Назив @@ -20235,7 +20680,7 @@ If you believe it is correct, remove the corresponding line from the file and re - + Profile ID @@ -20291,7 +20736,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -20305,11 +20750,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - - RsMessageModel @@ -20323,6 +20763,11 @@ prevents the message to be forwarded to your friends. From + + + To + + Subject @@ -20345,12 +20790,17 @@ prevents the message to be forwarded to your friends. - Click to sort by read + Click to sort by read status - Click to sort by from + Click to sort by author + + + + + Click to sort by destination @@ -20374,7 +20824,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -20395,7 +20847,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. @@ -20456,7 +20908,7 @@ prevents the message to be forwarded to your friends. - + Unable to open log file '%1': %2 @@ -20477,7 +20929,7 @@ prevents the message to be forwarded to your friends. - + opmode @@ -20507,7 +20959,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -20525,7 +20977,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -20542,12 +20994,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) - + Start Search @@ -20608,7 +21060,7 @@ prevents the message to be forwarded to your friends. - + KeyWords @@ -20623,7 +21075,7 @@ prevents the message to be forwarded to your friends. - + Filename @@ -20723,23 +21175,23 @@ prevents the message to be forwarded to your friends. - + File Name - + Download - + Copy RetroShare Link - + Send RetroShare Link @@ -20749,7 +21201,7 @@ prevents the message to be forwarded to your friends. - + Download Notice @@ -20786,7 +21238,7 @@ prevents the message to be forwarded to your friends. - + Folder @@ -20797,17 +21249,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) - + Open Folder - + Create Collection... @@ -20827,7 +21279,7 @@ prevents the message to be forwarded to your friends. - + Collection @@ -20835,7 +21287,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details @@ -20851,22 +21303,22 @@ prevents the message to be forwarded to your friends. Уклони ставку - + IP address: - + Peer ID: - + Location: Место: - + Peer Name: @@ -20883,7 +21335,7 @@ prevents the message to be forwarded to your friends. Сакриј - + but reported: @@ -20908,8 +21360,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -20917,7 +21369,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare @@ -20948,7 +21400,7 @@ prevents the message to be forwarded to your friends. - + Expand Прошири @@ -20993,12 +21445,12 @@ prevents the message to be forwarded to your friends. Статус: - + Write Message - + Connect Attempt @@ -21018,17 +21470,12 @@ prevents the message to be forwarded to your friends. - + Unknown Security Issue - - A unknown peer - - - - + Unknown @@ -21038,7 +21485,17 @@ prevents the message to be forwarded to your friends. - + + SSL request + + + + + An unknown peer + + + + Hide Сакриј @@ -21048,7 +21505,7 @@ prevents the message to be forwarded to your friends. - + Certificate has wrong signature!! This peer is not who he claims to be. @@ -21058,12 +21515,12 @@ prevents the message to be forwarded to your friends. - + Certificate caused an internal error. - + Peer/node not in friendlist (PGP id= @@ -21122,12 +21579,12 @@ prevents the message to be forwarded to your friends. - + Local Address - + NAT @@ -21148,22 +21605,22 @@ prevents the message to be forwarded to your friends. - + Local network - + External ip address finder - + UPnP - + Known / Previous IPs: @@ -21176,21 +21633,16 @@ behind a firewall or a VPN. - - Allow RetroShare to ask my ip to these websites: - - - - - - + + + kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -21200,23 +21652,46 @@ behind a firewall or a VPN. - + Onion Address - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -21226,7 +21701,7 @@ behind a firewall or a VPN. - + I2P Address @@ -21251,37 +21726,95 @@ behind a firewall or a VPN. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -21296,71 +21829,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -21370,22 +21839,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -21397,12 +21851,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -21412,7 +21866,7 @@ Also check your ports! - + Download limit (KB/s) @@ -21427,23 +21881,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -21454,17 +21908,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -21474,12 +21918,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -21489,17 +21928,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 127.0.0.1 - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -21539,7 +21968,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start @@ -21554,12 +21983,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - BOB status - - - - + Incoming @@ -21595,7 +22019,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -21650,7 +22099,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Warning: This bandwidth adds up to the max bandwidth. @@ -21675,7 +22124,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -21687,7 +22136,7 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Filters @@ -21710,7 +22159,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status @@ -21770,17 +22219,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -21796,18 +22256,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -21842,12 +22302,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -21870,22 +22330,22 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -21920,7 +22380,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -21930,12 +22390,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -22015,7 +22475,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with @@ -22025,12 +22485,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Share - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -22049,7 +22509,7 @@ Select the Friends with which you want to Share your Channel. - + Shared directory @@ -22069,17 +22529,17 @@ Select the Friends with which you want to Share your Channel. - + Add new - + Cancel - + Add a Share Directory @@ -22089,7 +22549,7 @@ Select the Friends with which you want to Share your Channel. Уклони - + Apply and close @@ -22180,7 +22640,7 @@ Select the Friends with which you want to Share your Channel. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. @@ -22188,7 +22648,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files @@ -22239,11 +22699,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files - + Download selected @@ -22253,7 +22718,7 @@ Select the Friends with which you want to Share your Channel. - + Copy retroshare Links to Clipboard @@ -22268,7 +22733,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted @@ -22284,7 +22749,7 @@ Select the Friends with which you want to Share your Channel. - + Create Collection... @@ -22309,7 +22774,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted because they have not been indexed yet. @@ -22452,12 +22917,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration - + Create interface @@ -22481,7 +22946,7 @@ Select the Friends with which you want to Share your Channel. - + Log In @@ -22820,7 +23285,7 @@ This choice can be reverted in settings. - + Message: @@ -23057,7 +23522,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags @@ -23093,12 +23558,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown @@ -23108,18 +23576,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -23129,12 +23592,57 @@ p, li { white-space: pre-wrap; } - + + Error + + + + + Not connected + + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -23142,7 +23650,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -23152,7 +23660,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -23163,11 +23671,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -23195,7 +23704,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options @@ -23206,7 +23715,7 @@ p, li { white-space: pre-wrap; } - + Shared Directories @@ -23216,22 +23725,27 @@ p, li { white-space: pre-wrap; } - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -23316,7 +23830,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -23325,7 +23839,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -23350,7 +23869,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming @@ -23415,12 +23939,7 @@ p, li { white-space: pre-wrap; } - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -23430,7 +23949,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -23458,7 +23987,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed @@ -23486,19 +24015,19 @@ p, li { white-space: pre-wrap; } TransfersDialog - - + + Downloads - + Uploads - + Name i.e: file name Назив @@ -23705,7 +24234,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... @@ -23730,7 +24264,7 @@ p, li { white-space: pre-wrap; } - + Anonymous end-to-end encrypted tunnel 0x @@ -23751,7 +24285,7 @@ p, li { white-space: pre-wrap; } Ретрошер - + @@ -23784,7 +24318,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name @@ -23799,7 +24343,7 @@ p, li { white-space: pre-wrap; } - + Expand all @@ -23926,23 +24470,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns - + File Transfers - + Path Путања @@ -23952,7 +24491,7 @@ p, li { white-space: pre-wrap; } - + Could not delete preview file @@ -23962,7 +24501,7 @@ p, li { white-space: pre-wrap; } - + Create Collection... @@ -23977,7 +24516,7 @@ p, li { white-space: pre-wrap; } - + Collection @@ -23987,7 +24526,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x @@ -24401,12 +24940,17 @@ p, li { white-space: pre-wrap; } Образац - + Enable Retroshare WEB Interface - + + Status: + Статус: + + + Web parameters @@ -24446,17 +24990,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -24466,12 +25020,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface @@ -24608,7 +25162,7 @@ p, li { white-space: pre-wrap; } - + Page Name @@ -24623,7 +25177,7 @@ p, li { white-space: pre-wrap; } - + << @@ -24711,7 +25265,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History @@ -24746,7 +25300,7 @@ p, li { white-space: pre-wrap; } - + \/ @@ -24776,14 +25330,18 @@ p, li { white-space: pre-wrap; } - - + + History + + + + Show Edit History - + Status @@ -24804,7 +25362,7 @@ p, li { white-space: pre-wrap; } - + Submit @@ -24887,16 +25445,7 @@ p, li { white-space: pre-wrap; } - ... - - - - - Refresh - - - - + Settings @@ -24911,7 +25460,7 @@ p, li { white-space: pre-wrap; } - + Who to Follow @@ -24931,7 +25480,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -24961,7 +25510,7 @@ p, li { white-space: pre-wrap; } - + Yourself @@ -24971,7 +25520,7 @@ p, li { white-space: pre-wrap; } - + RetroShare Ретрошер @@ -25034,35 +25583,42 @@ p, li { white-space: pre-wrap; } Образац - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + Уклони + + + Location: Место: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -25107,11 +25663,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + + + + + Following + + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) @@ -25189,7 +25775,7 @@ p, li { white-space: pre-wrap; } - + k e.g: 3.1 k @@ -25226,7 +25812,7 @@ p, li { white-space: pre-wrap; } pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_sv.ts b/retroshare-gui/src/lang/retroshare_sv.ts index 3bdd3ebc7..754e79479 100644 --- a/retroshare-gui/src/lang/retroshare_sv.ts +++ b/retroshare-gui/src/lang/retroshare_sv.ts @@ -84,13 +84,6 @@ - - AddCommentDialog - - Add Comment - Lägg till kommentar - - AddFileAssociationDialog @@ -128,12 +121,12 @@ RetroShare: Avancerad sökning - + Search Criteria Sökkriterium - + Add a further search criterion. Lägg till ytterligare sökkriterium. @@ -143,7 +136,7 @@ Återställ sökkriterium. - + Cancels the search. Avbryter sökningen. @@ -163,177 +156,6 @@ Sök - - AlbumCreateDialog - - Create Album - Skapa album - - - Album Name: - Albumnamn: - - - Category: - Kategori: - - - Animals - Djur - - - Family - Familj - - - Friends - Kontakter - - - Flowers - Blommor - - - Holiday - Semester - - - Landscapes - Landskap - - - Pets - Husdjur - - - Portraits - Porträtt - - - Travel - Resor - - - Work - Arbete - - - Random - Blandat - - - Caption: - Taget: - - - Where: - Plats: - - - Photographer: - Fotograf: - - - Description: - Beskrivning: - - - Share Options - Fildelningsalternativ - - - Policy: - Policy: - - - Quality: - Kvallitet: - - - Comments: - Kommentarer: - - - Identity: - Identitet: - - - Public - Publik - - - Restricted - Begränsad - - - Resize Images (< 1Mb) - Storleksändra bilder (< 1Mb) - - - Resize Images (< 10Mb) - Storleksändra bilder (< 10Mb) - - - Send Original Images - Skicka originalbilder - - - No Comments Allowed - Inga kommentarer tillåtna - - - Authenticated Comments - Autentiserade kommentarer - - - Any Comments Allowed - Alla kommentarer tillåtna - - - Publish with Identity - Publicera med identitet - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Dra &amp; släpp för att infoga bilder. Klicka på en bild för att redigera.</span></p></body></html> - - - Back - Tillbaka - - - Add Photos - Lägg till bilder - - - Publish Album - Publicera album - - - Untitle Album - Namnlöst album - - - Say something about this album... - Säg något om detta album... - - - Where were these taken? - Var togs dessa bilder? - - - Load Album Thumbnail - Läs in albumminiatyr - - AlbumDialog @@ -342,19 +164,11 @@ p, li { white-space: pre-wrap; } Album Album - - Album Thumbnail - Albumminiatyr - TextLabel Textetikett - - Summary - Sammanfattning - Album Title: @@ -370,34 +184,6 @@ p, li { white-space: pre-wrap; } Caption Taget - - Where: - Plats: - - - When - Tidpunkt - - - Description: - Beskrivning: - - - Share Options - Fildelningsalternativ - - - Comments - Kommentarer - - - Publish Identity - Publicera identitet - - - Visibility - Synlighet - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -766,7 +552,7 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. Varning! De här tjänsterna är experimentella. Hjälp oss gärna att testa dem. @@ -782,14 +568,6 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot Circles Cirklar - - GxsForums - GxsForum - - - GxsChannels - Gxs-kanaler - The Wire @@ -801,10 +579,23 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot Bilder + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb %p Kb @@ -841,17 +632,13 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot Browse... - - Add Avatar - Lägg till profilbild - Remove Ta bort - + Set your Avatar picture Lägg till din probild @@ -870,10 +657,6 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - Läs in profilbild - AvatarWidget @@ -942,22 +725,10 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot Återställ - Receive Rate - Mottagningshastighet - - - Send Rate - Sändningshastighet - - - + Always on Top Alltid överst - - Style - Stil - Changes the transparency of the Bandwidth Graph @@ -973,23 +744,11 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot % Opaque % Opak - - Save - Spara - - - Cancel - Avbryt - Since: Sedan: - - Hide Settings - Dölj inställningar - BandwidthStatsWidget @@ -1062,7 +821,7 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot BoardPostDisplayWidgetBase - + Comment Kommentar @@ -1092,12 +851,12 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot Kopiera RetroShare-länk - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -1105,7 +864,7 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot BoardPostDisplayWidget_card - + Vote up @@ -1125,7 +884,7 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot \/ - + Posted by @@ -1163,7 +922,7 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot BoardPostDisplayWidget_compact - + Vote up @@ -1183,7 +942,7 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot \/ - + Click to view picture @@ -1213,7 +972,7 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot Dela - + Toggle Message Read Status Växla meddelandestatus @@ -1223,7 +982,7 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot Nytt - + TextLabel @@ -1231,12 +990,12 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot BoardsCommentsItem - + I like this Jag gillar detta - + 0 0 @@ -1256,18 +1015,18 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot Profilbild - + New Comment - + Copy RetroShare Link Kopiera RetroShare-länk - + Expand @@ -1282,12 +1041,12 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot Ta bort objektet - + Name Namn - + Comm value @@ -1456,17 +1215,17 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot ChannelPage - + Channels Kanaler - + Tabs Flikar - + General Allmänt @@ -1476,11 +1235,17 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot - Load posts in background (Thread) - Ladda inlägg i bakgrunden (Tråd) + + Downloads + Nerladdningar - + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab Öppna varje kanal i en ny flik @@ -1488,7 +1253,7 @@ Kom bara ihåg... all data här, *KOMMER* att förloras när vi uppgraderar prot ChannelPostDelegate - + files @@ -1511,7 +1276,7 @@ into the image, so as to ChannelsCommentsItem - + I like this Jag gillar detta @@ -1536,18 +1301,18 @@ into the image, so as to Profilbild - + New Comment - + Copy RetroShare Link Kopiera RetroShare-länk - + Expand @@ -1562,7 +1327,7 @@ into the image, so as to Ta bort objektet - + Name Namn @@ -1572,17 +1337,7 @@ into the image, so as to - - Comment - Kommentar - - - - Comments - - - - + Hide Dölj @@ -1590,7 +1345,7 @@ into the image, so as to ChatLobbyDialog - + Name Namn @@ -1781,7 +1536,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby Visa chattlobby @@ -1793,22 +1548,6 @@ into the image, so as to Chats - - You have %1 new messages - Du har %1 nya meddelanden - - - You have %1 new message - Du har %1 nytt meddelande - - - %1 new messages - %1 nya meddelanden - - - %1 new message - %1 nytt meddelande - You have %1 mentions @@ -1830,13 +1569,14 @@ into the image, so as to - + + Unknown Lobby Okänd lobby - - + + Remove All Ta bort alla @@ -1844,13 +1584,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Namn - + Count Antal @@ -1860,29 +1600,7 @@ into the image, so as to Ämne - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - - - - - - Public chat rooms - - - - + Create chat room @@ -1892,7 +1610,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1949,12 +1667,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1964,31 +1682,31 @@ Double click a chat room to enter and chat. - Create chat lobby - Skapa ny chattlobby - - - + [No topic provided] [Ämne saknas] - Selected lobby info - Vald lobbyinformation - - - + + Private Privat - + + + Public Publik - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted @@ -1998,42 +1716,25 @@ Double click a chat room to enter and chat. Avsluta Prenumeration - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe Prenumerera - + Search Chat lobbies Sök Chat Lobbyn - + Search Name Sök namn - Subscribed - Prenumererat - - - + Columns Kolumner - - Yes - Ja - - - No - Nej - Chat rooms @@ -2045,47 +1746,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: Ämne: - + Type: Typ: - + Security: Säkerhet: - + Peers: Användare: - - - - - - + + + + + + TextLabel Textetikett @@ -2100,13 +1801,24 @@ Double click a chat room to enter and chat. Inga anonyma ID - + Show Visa - + + Private Subscribed + + + + + + Public Subscribed + + + + column kolumn @@ -2120,7 +1832,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item Ta bort objektet @@ -2165,7 +1877,7 @@ Double click a chat room to enter and chat. ChatPage - + General Allmänt @@ -2180,19 +1892,7 @@ Double click a chat room to enter and chat. - Chat Settings - Chattinställningar - - - Enable Emoticons Private Chat - Aktivera uttryckssymboler i privat chatt - - - Enable Emoticons Group Chat - Aktivera uttryckssymboler i gruppchatt - - - + Enable custom fonts Aktivera anpassat teckensnitt @@ -2212,7 +1912,7 @@ Double click a chat room to enter and chat. Aktivera kursiv stil - + General settings @@ -2237,11 +1937,7 @@ Double click a chat room to enter and chat. Ladda inbäddade bilder - Chat Lobby - Chattlobby - - - + Blink tab icon Blinka med flikikon @@ -2250,10 +1946,6 @@ Double click a chat room to enter and chat. Do not send typing notifications - - Private Chat - Privatchatt - Open Window for new chat @@ -2275,11 +1967,7 @@ Double click a chat room to enter and chat. Blinka med fönster-/flikikon - Chat Font - Chatteckensnitt - - - + Change Chat Font Ändra teckensnitt @@ -2289,14 +1977,10 @@ Double click a chat room to enter and chat. Teckensnitt: - + History Historik - - Style - Stil - @@ -2311,17 +1995,13 @@ Double click a chat room to enter and chat. Variant: - - Group chat - Gruppchatt - Private chat Privatchatt - + Choose your default font for Chat. @@ -2385,22 +2065,28 @@ Double click a chat room to enter and chat. <html><head/><body><p align="justify">In this tab you can setup how many chat messages Retroshare will keep saved on the disc and how much of the previous conversation it will display, for the different chat systems. The max storage period allows to discard old messages and prevents the chat history from filling up with volatile chat (e.g. chat lobbies and distant chat).</p></body></html> - - Chatlobbies - Chatlobbyn - Enabled: Aktiverad: - + Search Sök - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2410,7 +2096,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2507,11 +2203,7 @@ Double click a chat room to enter and chat. Maximalt antal dagar att spara (0 = behåll allt): - Search by default - Sök som standard - - - + Case sensitive Skiftlägeskänslig @@ -2617,7 +2309,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat Visa chatt @@ -2653,7 +2345,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close Stäng @@ -2688,12 +2380,12 @@ Double click a chat room to enter and chat. Kursiv - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2773,11 +2465,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2815,7 +2502,7 @@ Double click a chat room to enter and chat. - + is typing... skriver... @@ -2837,7 +2524,7 @@ after HTML conversion. - + Do you really want to physically delete the history? Vill du verkligen ta bort historiken? @@ -2887,7 +2574,7 @@ after HTML conversion. är upptagen och kanske inte svarar. - + Find Case Sensitively @@ -2909,7 +2596,7 @@ after HTML conversion. Sluta inte att färga efter X hittade (använder mer CPU) - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> @@ -2924,16 +2611,12 @@ after HTML conversion. - + (Status) (Status) - Set text font & color - Ange teckensnitt & färg - - - + Attach a File Bifoga en fil @@ -2949,12 +2632,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> - + Person id: @@ -2965,12 +2648,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. @@ -2990,7 +2673,7 @@ Double click on it to add his name on text writer. Skriv ett meddelande här - + Don't stop to color after @@ -3016,7 +2699,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: Visningsdetaljer: @@ -3038,7 +2721,7 @@ Double click on it to add his name on text writer. - + Personal Circles Privata cirklar @@ -3064,7 +2747,7 @@ Double click on it to add his name on text writer. - + Friends Kontakter @@ -3124,7 +2807,7 @@ Double click on it to add his name on text writer. Vänners vänner - + External Circles (Admin) Externa Cirklar (Administratör) @@ -3140,7 +2823,7 @@ Double click on it to add his name on text writer. - + Circles Cirklar @@ -3192,45 +2875,45 @@ Double click on it to add his name on text writer. - + RetroShare RetroShare - + - + Error : cannot get peer details. Fel: Kan inte hämta användaruppgifter. - + Retroshare ID - + <p>This Retroshare ID contains: - + <p>This certificate contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: @@ -3240,7 +2923,7 @@ Double click on it to add his name on text writer. Kryptering - + Not connected Inte ansluten @@ -3322,12 +3005,17 @@ Double click on it to add his name on text writer. ingen - + <li>a <b>node ID</b> and <b>name</b> - + + <b>DNS:</b> : + + + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3347,7 +3035,7 @@ Double click on it to add his name on text writer. - + with med @@ -3364,104 +3052,16 @@ Double click on it to add his name on text writer. Connect Friend Wizard Anslut kontakt ((Steg för steg-guide)) - - Add a new Friend - Lägg till en ny kontakt - - - &You get a certificate file from your friend - &Du får en certifikatfil från en kontakt - - - &Make friend with selected friends of my friends - &Skapa kontakt med en utvald kontakt till en befintlig kontakt - - - Include signatures - Inkludera signaturer - - - Copy your Cert to Clipboard - Kopiera certifikatet till Urklipp - - - Save your Cert into a File - Spara certifikatet till fil - - - Run Email program - Starta e-postprogrammet - Open Cert of your friend from File - - Certificate files - Certifikatfiler - - - Use PGP certificates saved in files. - Använd PGP-certifikat som sparats i filer. - - - Import friend's certificate... - Importera en kontakts certifikat... - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - Du behöver generera en certifikatfil och ge den till din kontakt. Du kan också använda en befintlig certifikatfil. - - - Export my certificate... - Exportera mitt certifikat... - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - Dra och släpp din kontakts certifikat i det här fönstret, eller ange sökväg i nedanstående textfält - - - Browse - Bläddra - - - Friends of friends - Kontakter till kontakter - - - Select now who you want to make friends with. - Välj vem du vill skapa kontakt med - - - Show me: - Visa mig: - - - Make friend with these peers - Skapa kontakt med dessa användare - RetroShare ID RetroShare-ID - - Use RetroShare ID for adding a Friend which is available in your network. - Använd RetroShare-ID för att lägga till en kontakt som är tillgänglig i ditt nätverk. - - - Add Friends RetroShare ID... - Lägg till kontaktens RetroShare-ID... - - - Paste Friends RetroShare ID in the box below - Klistra in kontaktens RetroShare-ID i nedanstående indataruta - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - Ange kontaktens RetroShare-ID. Ex. Användare@BDE8D16A46D938CF - RetroShare is better with Friends @@ -3503,27 +3103,7 @@ Double click on it to add his name on text writer. E-post - Invite Friends by Email - Bjud in kontakter via e-post - - - Enter your friends' email addresses (separate each one with a semicolon) - Ange kontaktens e-postadresser (separera med semikolon) - - - Your friends' email addresses: - Kontaktens e-postadresser: - - - Enter Friends Email addresses - Ange kontaktens e-postadresser - - - Subject: - Ämne: - - - + @@ -3539,40 +3119,32 @@ Double click on it to add his name on text writer. Fakta om begäran - + Peer details Användarinformation - + Name: Namn: - - Email: - E-post: - - - Node: - Nod: - Location: Plats: - + Options Alternativ - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: Lägg till kontakt till grupp: @@ -3582,7 +3154,7 @@ Double click on it to add his name on text writer. Autentisera kontakt (Signera PGP-nyckel) - + Please paste below your friend's Retroshare ID @@ -3607,16 +3179,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with Lägg till en kontakt att ansluta till - To accept the Friend Request, click the Finish button. - Klicka på 'Slutför' för att acceptera denna kontaktförfrågan - - - + Sorry, some error appeared Något fel uppstod @@ -3636,32 +3214,27 @@ Double click on it to add his name on text writer. Fakta om din kontakt: - + Key validity: Nyckelvaliditet: - + Profile ID: - - Signers - Signerad av: - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. Denna användare finns redan på din kontaktlista. Att lägga till den kanske bara anger IP-adress. - + To accept the Friend Request, click the Accept button. @@ -3707,45 +3280,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed Certifikatinläsning misslyckades - Cannot get peer details of PGP key %1 - Kan inte hämta användarinformation för PGP-nyckel %1 - - - Any peer I've not signed - Vilken användare som helst, som jag inte signerat - - - Friends of my friends who already trust me - Kontakter till mina kontakter som redan litar på mig - - - Signed peers showing as denied - Signerade användare som visas som avvisade - - - Peer name - Användarnamn - - - Also signed by - Också signerad av - - - Peer id - Användar-ID - - - + Not a valid Retroshare certificate! - + RetroShare Invitation RetroShare-inbjudan @@ -3765,12 +3310,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3778,7 +3323,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3818,7 +3363,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Du har en kontaktförfrågan från - + Profile password needed. @@ -3843,7 +3388,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3853,47 +3398,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - Certificate Load Failed:file %1 not found - Certifikatinläsning misslyckades! %1 kan inte hittas - - - This Peer %1 is not available in your Network - %1 finns inte tillgänglig i ditt nätverk - - - Use new certificate format (safer, more robust) - Använd nytt certifikatformat (säkrare, mer robust) - - - Use old (backward compatible) certificate format - Använd gammalt (bakåtkompatibelt) certifikatformat - - - Remove signatures - Ta bort signaturer - - - RetroShare Invite - RetroShare-inbjudan - - - Connect Friend Help - Anslut kontakt Hjälp - - - You can copy this text and send it to your friend via email or some other way - Du kan kopiera denna text och skicka den till din kontakt via e-post eller på något annat sätt. - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Ditt certifikat är kopierat till Urklipp, klistra in och skicka det till din kontakt via e-post eller på något annat sätt. - - - Save as... - Spara som... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3932,11 +3437,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.*** Ingen *** - Use as direct source, when available - Använd som direkt källa, om tillgänglig - - - + IP-Addr: @@ -3946,7 +3447,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.IP-adress - + Show Advanced options @@ -3965,41 +3466,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> - - Recommend many friends to each others - Rekommendera många användare åt varandra - - - Friend Recommendations - Kontaktrekommendationer - - - Message: - Meddelande: - - - Recommend friends - Rekommendera kontakter - - - To - Till - - - Please select at least one friend for recommendation. - Välj minst en kontakt för rekommendation. - - - Please select at least one friend as recipient. - Välj minst en kontakt som mottagare. - Add key to keyring Lägg till nyckel till nyckelring - + This key is already in your keyring Den här nyckeln finns redan i din nyckelring @@ -4012,7 +3485,7 @@ even if you don't make friends. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. Certifikatet har fel versionsnummer. Kom ihåg att v0.6 och v0.5-nätverk inte är kompatibla med varandra. @@ -4047,7 +3520,7 @@ even if you don't make friends. - + No IP in this certificate! @@ -4057,12 +3530,7 @@ even if you don't make friends. - - [Unknown] - - - - + Added with certificate from %1 @@ -4127,7 +3595,7 @@ even if you don't make friends. - + UDP Setup UDP Inställning @@ -4155,7 +3623,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant Anslutningsassistent @@ -4165,17 +3633,20 @@ p, li { white-space: pre-wrap; } Ogiltigt Användar-ID - + + Unknown State Okänt tillstånd - + + Offline Frånkopplad - + + Behind Symmetric NAT Bakom symmetrisk NAT @@ -4185,12 +3656,14 @@ p, li { white-space: pre-wrap; } Bakom NAT & Ingen DHT - + + NET Restart NET Återstart - + + Behind NAT Bakom NAT @@ -4200,7 +3673,8 @@ p, li { white-space: pre-wrap; } Ingen DHT - + + NET STATE GOOD! NET TILLSTÅND BRA! @@ -4225,7 +3699,7 @@ p, li { white-space: pre-wrap; } Söker RS-användare - + Lookup requires DHT Sökning kräver DHT @@ -4517,7 +3991,7 @@ p, li { white-space: pre-wrap; } Försök igen genom att importera en fullständig Nyckel - + @@ -4525,7 +3999,8 @@ p, li { white-space: pre-wrap; } N/A - + + UNVERIFIABLE FORWARD! OVERIFIERBAR VIDAREBEFORDRING! @@ -4535,7 +4010,7 @@ p, li { white-space: pre-wrap; } OVERIFIERBAR VIDAREBEFORDRING & INGEN DHT - + Searching Söker @@ -4571,12 +4046,12 @@ p, li { white-space: pre-wrap; } Cirkeldetaljer - + Name Namn - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4596,7 +4071,7 @@ p, li { white-space: pre-wrap; } - + IDs ID @@ -4616,18 +4091,18 @@ p, li { white-space: pre-wrap; } Filter - + Cancel Avbryt - + Nickname Användarnamn - + Invited Members @@ -4642,15 +4117,7 @@ p, li { white-space: pre-wrap; } - ID - ID - - - Type - Typ - - - + Name: Namn: @@ -4690,19 +4157,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - + Please set a name for your Circle Ange ett namn för din cirkel - + No Restriction Circle Selected Ingen begränsad cirkel vald @@ -4712,12 +4179,24 @@ p, li { white-space: pre-wrap; } Inga cirkel begränsningar valda - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add Lägg till @@ -4727,7 +4206,7 @@ p, li { white-space: pre-wrap; } Ta bort - + Search Sök @@ -4742,10 +4221,6 @@ p, li { white-space: pre-wrap; } Signed Signerad - - Signed by known nodes - Signerad av kända noder - Edit Circle @@ -4762,10 +4237,6 @@ p, li { white-space: pre-wrap; } PGP Identity PGP-identitet - - Anon Id - Anonymt Id - Circle name @@ -4788,17 +4259,13 @@ p, li { white-space: pre-wrap; } - + Create Skapa - PGP Linked Id - PGP-länkat ID - - - + Add Member @@ -4817,7 +4284,7 @@ p, li { white-space: pre-wrap; } Skapa en ny grupp - + Group Name: Gruppnamn: @@ -4852,7 +4319,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post Nytt kanalinlägg @@ -4862,7 +4329,7 @@ p, li { white-space: pre-wrap; } Kanalinlägg - + Post @@ -4923,23 +4390,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Använd Dra och släpp / Lägg till fil, för att hash-beräkna nya filer.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Kopiera/Klistra in RetroShare-länkar från dina utdelade mappar</span></p></body></html> - - Add File to Attach - Bifofoga fil - Add Channel Thumbnail Lägg till kanalminiatyr - - Message - Meddelande - - - Subject : - Ämne: - @@ -5025,17 +4480,17 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -5054,17 +4509,18 @@ p, li { white-space: pre-wrap; } The following files will only be shared for 30 days. Think about adding them to a shared directory. - - File already Added and Hashed - Filen är redan tillagd och hash-beräknad - Please add a Subject Ange ett ämne - + + Cannot publish post + + + + Load thumbnail picture Läs in miniatyrbild @@ -5079,18 +4535,12 @@ p, li { white-space: pre-wrap; } Dölj - - + Generate mass data Generera massdata - - Do you really want to generate %1 messages ? - Vill du verkligen generera %1 meddelanden? - - - + You are about to add files you're not actually sharing. Do you still want this to happen? Du är på väg att lägga till filer som du inte delar. Vill du verkligen fortsätta? @@ -5124,7 +4574,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message Posta foruminlägg @@ -5133,10 +4583,6 @@ p, li { white-space: pre-wrap; } Forum Forum - - Subject - Ämne - Attach File @@ -5157,8 +4603,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -5177,7 +4623,7 @@ p, li { white-space: pre-wrap; } Du kan bifoga filer via Dra & släpp i det här fönstret - + Post @@ -5207,17 +4653,17 @@ p, li { white-space: pre-wrap; } - + No Forum Inga forum - + In Reply to Som svar på - + Title @@ -5270,7 +4716,7 @@ Do you want to discard this message? Läs in en bildfil - + No compatible ID for this forum @@ -5280,8 +4726,8 @@ Do you want to discard this message? - - + + Generate mass data Generera massdata @@ -5290,10 +4736,6 @@ Do you want to discard this message? Do you really want to generate %1 messages ? Vill du verkligen generera %1 meddelanden? - - Send - Skicka - Post as @@ -5308,23 +4750,7 @@ Do you want to discard this message? CreateLobbyDialog - Create Chat Lobby - Skapa ny chattlobby - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - En chattlobby är en decentraliserad och anonym chattgrupp. Samtliga deltagare tar emot alla meddelanden. När lobbyn är skapad kan du bjuda in andra kontakter via kontakt-fliken - - - Lobby name: - Lobbynamn: - - - Lobby topic: - Lobbyämne: - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5359,7 +4785,7 @@ Do you want to discard this message? - + Create Skapa @@ -5369,7 +4795,7 @@ Do you want to discard this message? Avbryt - + require PGP-signed identities @@ -5384,11 +4810,7 @@ Do you want to discard this message? Välj de kontakter du vill gruppchatta med. - Invited friends - Inbjudna kontakter - - - + Create Chat Room @@ -5409,7 +4831,7 @@ Do you want to discard this message? Kontakter: - + Identity to use: Identitet att använda: @@ -5417,17 +4839,17 @@ Do you want to discard this message? CryptoPage - + Public Information Öppen information - + Name: Namn: - + Location: Plats: @@ -5437,12 +4859,12 @@ Do you want to discard this message? Plats-ID: - + Software Version: Programversion: - + Online since: Uppkopplad sedan: @@ -5462,12 +4884,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5477,7 +4894,7 @@ Do you want to discard this message? - + Other Information Annan information @@ -5487,17 +4904,12 @@ Do you want to discard this message? - + Profile - - Certificate - Certifikat - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5507,11 +4919,7 @@ Do you want to discard this message? Inkludera signaturer - Save Key into a file - Spara nyckel som fil - - - + Export Identity Exportera identitet @@ -5585,33 +4993,33 @@ och där läsa in den med importfunktionen. - + TextLabel Textetikett - + PGP fingerprint: PGP fingeravtryck: - - Node information - Nodinformation - - - + PGP Id : PGP Id : - + Friend nodes: Vännoder: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5650,14 +5058,6 @@ och där läsa in den med importfunktionen. Node Nod - - Create new node... - Skapa ny node... - - - show statistics window - visa statistikfönster - DHTGraphSource @@ -5709,7 +5109,7 @@ och där läsa in den med importfunktionen. DLListDelegate - + B B @@ -6377,7 +5777,7 @@ och där läsa in den med importfunktionen. DownloadToaster - + Start file Starta @@ -6385,38 +5785,38 @@ och där läsa in den med importfunktionen. ExprParamElement - + - + to till - + ignore case Ignorera skiftläge - - - dd.MM.yyyy - dd.MM.yyyy + + + yyyy-MM-dd + - - + + KB KB - - + + MB MB - - + + GB GB @@ -6424,12 +5824,12 @@ och där läsa in den med importfunktionen. ExpressionWidget - + Expression Widget Uttrycks-widget - + Delete this expression Ta bort det här uttrycket @@ -6591,7 +5991,7 @@ och där läsa in den med importfunktionen. FilesDefs - + Picture Bild @@ -6601,7 +6001,7 @@ och där läsa in den med importfunktionen. Video - + Audio Audio @@ -6661,11 +6061,21 @@ och där läsa in den med importfunktionen. C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Kontakters mappar @@ -6787,7 +6197,7 @@ och där läsa in den med importfunktionen. - + ID ID @@ -6829,7 +6239,7 @@ och där läsa in den med importfunktionen. Visa grupper - + Group Grupp @@ -6865,7 +6275,7 @@ och där läsa in den med importfunktionen. Lägg till i grupp - + Search Sök @@ -6881,7 +6291,7 @@ och där läsa in den med importfunktionen. Sortera efter stadie - + Profile details @@ -7118,7 +6528,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request Bekräfta kontaktförfrågan @@ -7135,10 +6545,6 @@ at least one peer was not added to a group FriendSelectionWidget - - Search : - Sök: - Sort by state @@ -7160,7 +6566,7 @@ at least one peer was not added to a group Sök kontakter - + Mark all Markera alla @@ -7171,16 +6577,132 @@ at least one peer was not added to a group Markera ingen + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Namn + + + + Node ID + + + + + Address + + + + + Status + Status + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + Skapa kontakt + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message Redigera statusmeddelande - - + + Broadcast Sändning @@ -7263,33 +6785,38 @@ at least one peer was not added to a group Återställ standardteckensnitt - + Keyring Nyckelring - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. Retroshare utsändningschat: meddelanden skickas till alla anslutna vänner. - - + + Network Nätverk - + + Friend Server + + + + Network graph Nätverksgraf - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. Ange ditt statusmeddelande här. @@ -7307,7 +6834,17 @@ at least one peer was not added to a group Lösenord - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters Samtliga indatafält kräver minst 3 tecken @@ -7317,17 +6854,12 @@ at least one peer was not added to a group Lösenorden stämmer inte överens - + Port Port - - Use BOB - - - - + This password is for PGP Detta lösenord är för PGP @@ -7348,38 +6880,38 @@ at least one peer was not added to a group - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -7399,12 +6931,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -7414,42 +6946,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel - Advanced options - Avancerade alternativ - - - + hidden address gömd adress - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -7493,13 +7026,13 @@ and use the import button to load it - + Import profile Importera profil - + Create new profile and new Retroshare node @@ -7509,7 +7042,7 @@ and use the import button to load it - + Tor/I2P address @@ -7544,7 +7077,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7554,12 +7087,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -7569,12 +7097,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7800,36 +7323,13 @@ and use the import button to load it Kom igång - + Invite Friends Bjud in kontakter - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:12pt;">RetroShare är ingentig utan dina kontakter. Klicka på knappen för att starta processen.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:12pt;">Skicka en inbjudan med ditt certifikat, via e-post, till dina vänner.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:12pt;">Tillse att du får en inbjudan i retur... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:12pt;">Du kan endast ansluta till kontakter om ni båda har lagt till varandra.</span></p></body></html> - - - + Add Your Friends to RetroShare Lägg till dina kontakter i RetroShare @@ -7839,89 +7339,103 @@ p, li { white-space: pre-wrap; } Lägg till kontakter - + + Connect To Friends + Anslut till kontakter + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Avancerat: Öppna brandväggsport + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - Anslut till kontakter - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - Avancerat: Öppna brandväggsport - - - + Further Help and Support Mer hjälp och support - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website RetroShare Hemsida @@ -7946,7 +7460,7 @@ p, li { white-space: pre-wrap; } Återkoppling (e-post) - + RetroShare Invitation RetroShare Inbjudan @@ -7996,12 +7510,12 @@ p, li { white-space: pre-wrap; } RetroShare återkoppling - + RetroShare Support RetroShare support - + It has many features, including built-in chat, messaging, @@ -8125,7 +7639,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat Visa gruppchatt @@ -8133,7 +7647,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] @@ -8303,7 +7817,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title Titel @@ -8316,12 +7830,12 @@ p, li { white-space: pre-wrap; } - + Description Beskrivning - + Number of Unread message @@ -8346,19 +7860,7 @@ p, li { white-space: pre-wrap; } - Sort by Name - Sortera efter namn - - - Sort by Popularity - Sortera efter popularitet - - - Sort by Last Post - Sortera efter senaste inlägg - - - + You are admin (modify names and description using Edit menu) @@ -8373,14 +7875,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post Senaste inlägget - + Name Namn @@ -8391,17 +7893,13 @@ p, li { white-space: pre-wrap; } Popularitet - + Never - Display - Visa - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8414,7 +7912,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and och @@ -8550,7 +8048,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels Kanaler @@ -8561,22 +8059,22 @@ p, li { white-space: pre-wrap; } Skapa kanal - + Enable Auto-Download Aktivera automatisk nedladdning - + My Channels Mina kanaler - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Kanalabonnemang @@ -8596,12 +8094,12 @@ p, li { white-space: pre-wrap; } - + Disable Auto-Download Inaktivera automatisk nedladdning - + Set download directory @@ -8636,22 +8134,22 @@ p, li { white-space: pre-wrap; } - + Play Spela upp - + Open folder Öppna mapp - + Open file - + Error Fel @@ -8671,17 +8169,17 @@ p, li { white-space: pre-wrap; } - + Are you sure that you want to cancel and delete the file? Vill du verkligen avbryta och radera filen? - + Can't open folder Kan inte öppna mapp - + Play File Spela upp fil @@ -8691,33 +8189,10 @@ p, li { white-space: pre-wrap; } %1 finns inte i den mappen. - - GxsChannelFilesWidget - - Form - Formulär - - - Filename - Filname - - - Size - Storlek - - - Title - Rubrik - - - Status - Status - - GxsChannelGroupDialog - + Create New Channel Skapa ny kanal @@ -8755,9 +8230,19 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - Abonnera på kanal + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel + @@ -8771,7 +8256,7 @@ p, li { white-space: pre-wrap; } - + Expand Visa @@ -8786,7 +8271,7 @@ p, li { white-space: pre-wrap; } Kanalbeskrivning - + Loading Läser in @@ -8801,8 +8286,9 @@ p, li { white-space: pre-wrap; } - New Channel - Ny kanal + + Never + @@ -8813,7 +8299,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: @@ -8834,7 +8320,7 @@ p, li { white-space: pre-wrap; } - + Play Spela upp @@ -8890,28 +8376,24 @@ p, li { white-space: pre-wrap; } Files Filer - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - Varning! Det är mindre än %1 timmar och %2 minuter kvar tills den här filen raderas. Överväg att spara den. - Hide Dölj - + New Nytt - + 0 0 - - + + Comment Kommentar @@ -8926,21 +8408,17 @@ p, li { white-space: pre-wrap; } Jag gillar inte detta - Loading - Läser in - - - + Loading... - + Comments - + Post @@ -8965,83 +8443,16 @@ p, li { white-space: pre-wrap; } Spela upp media - - GxsChannelPostsWidget - - Post to Channel - Posta i kanal - - - Loading - Läser in - - - Search channels - Sök kanaler - - - Title - Rubrik - - - Search Title - Sök titel - - - Message - Meddelande - - - Search Message - Sök meddelanden - - - Filename - Filname - - - Search Filename - Sök filnamn - - - No Channel Selected - Inga kanaler markerade - - - Disable Auto-Download - Inaktivera automatisk nedladdning - - - Enable Auto-Download - Aktivera automatisk nedladdning - - - Show files - Visa filer - - - Feeds - Flöden - - - Files - Filer - - - Description: - Beskrivning: - - GxsChannelPostsWidgetWithModel - + Post to Channel Posta i kanal - + Add new post @@ -9111,7 +8522,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -9147,7 +8558,7 @@ p, li { white-space: pre-wrap; } - + Comments Kommentarer @@ -9162,13 +8573,13 @@ p, li { white-space: pre-wrap; } Flöden - - + + Click to switch to list view - + Show unread posts only @@ -9183,7 +8594,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -9198,7 +8609,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -9258,12 +8669,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -9338,12 +8759,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed Prenumererat @@ -9394,17 +8816,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -9519,7 +8941,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container Kommentarsbehållare @@ -9532,7 +8954,7 @@ p, li { white-space: pre-wrap; } Formulär - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9562,7 +8984,7 @@ p, li { white-space: pre-wrap; } Uppdatera - + Comment Kommentar @@ -9601,7 +9023,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment Besvara kommentar @@ -9625,6 +9047,21 @@ p, li { white-space: pre-wrap; } Vote Down Rösta ned + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9634,7 +9071,7 @@ p, li { white-space: pre-wrap; } Kommentera - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9663,26 +9100,10 @@ p, li { white-space: pre-wrap; } - + Post - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Kommentera</span></p></body></html> - - - Signed by - Signerad av - Reply to Comment @@ -9711,7 +9132,7 @@ before you can comment innan du kan kommentera - + It remains %1 characters after HTML conversion. @@ -9753,14 +9174,6 @@ innan du kan kommentera Forum moderators can edit/delete/pinup others posts - - Add Forum Admins - Lägg till forumadministratörer - - - Select Forum Admins - Välj forumadministratörer - Create @@ -9770,7 +9183,7 @@ innan du kan kommentera GxsForumGroupItem - + Subscribe to Forum Prenumerera på forum @@ -9786,7 +9199,7 @@ innan du kan kommentera - + Expand Visa @@ -9806,8 +9219,9 @@ innan du kan kommentera - Loading - Läser in + + TextLabel + @@ -9838,13 +9252,13 @@ innan du kan kommentera GxsForumMsgItem - - + + Subject: Ämne: - + Unsubscribe To Forum Avsluta prenumeration på forum @@ -9855,7 +9269,7 @@ innan du kan kommentera - + Expand Visa @@ -9875,21 +9289,17 @@ innan du kan kommentera Svar svar på: - Loading - Läser in - - - + Loading... - + Forum Feed - + Hide Dölj @@ -9902,63 +9312,66 @@ innan du kan kommentera Formulär - + Start new Thread for Selected Forum Starta ny tråd i aktuellt forum - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Sök i forum - Last Post - Senaste inlägget - - - + New Thread Ny tråd - - - Threaded View - Trådvy - - - - Flat View - Platt vy - - + Title Rubrik - - + + Date Datum - + Author Författare - - Save image - - - - + Loading Läser in - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9968,12 +9381,7 @@ innan du kan kommentera - - Lastest post in thread - - - - + Reply Message Svarsmeddelande @@ -9997,10 +9405,6 @@ innan du kan kommentera Download all files Ladda ner alla filer - - Next unread - Nästa olästa - Search Title @@ -10017,31 +9421,23 @@ innan du kan kommentera Sök författare - Content - Innehåll - - - Search Content - Sökinnehåll - - - + No name Inget namn - - + + Reply Svara - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -10084,16 +9480,12 @@ innan du kan kommentera Kopiera RetroShare-länk - + Hide Dölj - Expand - Expandera - - - + [unknown] @@ -10123,8 +9515,8 @@ innan du kan kommentera - - + + Distribution @@ -10138,22 +9530,6 @@ innan du kan kommentera Anti-spam - - Anonymous - Anonym - - - signed - signerad - - - none - ingen - - - [ ... Missing Message ... ] - [ ... Meddelande saknas ... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10223,12 +9599,12 @@ innan du kan kommentera Originalmeddelande - + New thread - + Edit Redigera @@ -10289,7 +9665,7 @@ innan du kan kommentera - + Show column @@ -10309,7 +9685,7 @@ innan du kan kommentera - + Anonymous/unknown posts forwarded if reputation is positive @@ -10361,7 +9737,7 @@ This message is missing. You should receive it later. - + No result. @@ -10371,7 +9747,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -10386,7 +9762,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -10452,12 +9828,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums Forum @@ -10488,35 +9864,16 @@ This message is missing. You should receive it later. Andra forum - - GxsForumsFillThread - - Waiting - Väntar - - - Retrieving - Tar emot - - - Loading - Läser in - - GxsGroupDialog - + Name Namn - Add Icon - Lägg till ikon - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels Nyckelmottagare kan publicera på begränsad Wiki-grupp, och kan visa och publicera på privata kanaler @@ -10525,22 +9882,14 @@ This message is missing. You should receive it later. Share Publish Key Dela publiceringsnyckel - - check peers you would like to share private publish key with - Markera de användare du vill dela privat publiceringsnyckel med. - - - Share Key With - Dela nyckel med - - + Description Beskrivning - + Message Distribution Meddelandedistribution @@ -10548,7 +9897,7 @@ This message is missing. You should receive it later. - + Public Publik @@ -10567,14 +9916,6 @@ This message is missing. You should receive it later. New Thread Ny tråd - - Required - Obligatorisk - - - Encrypted Msgs - Krypterade meddelanden - Personal Signatures @@ -10616,7 +9957,7 @@ This message is missing. You should receive it later. - + Comments: Kommentarer: @@ -10639,7 +9980,7 @@ This message is missing. You should receive it later. - + All People @@ -10655,12 +9996,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -10677,23 +10018,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -10709,26 +10050,28 @@ This message is missing. You should receive it later. Lägg till ett namn - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo Läs in grupplogotyp - + Submit Group Changes - Will be used to send feedback - Kommer att användas för att skicka feedback - - - + Owner: Ägare: @@ -10738,12 +10081,12 @@ This message is missing. You should receive it later. - + Info Information - + ID ID @@ -10753,7 +10096,7 @@ This message is missing. You should receive it later. Senaste inlägget - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -10828,7 +10171,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity Popularitet @@ -10844,27 +10192,22 @@ This message is missing. You should receive it later. - + Created - + Cancel Avbryt - + Create Skapa - - Author - Upphovsman - - - + GxsIdLabel @@ -10872,7 +10215,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading Läser in @@ -10932,7 +10275,7 @@ This message is missing. You should receive it later. Redigera detaljer - + Synchronise posts of last... @@ -10989,12 +10332,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link Kopiera RetroShare-länk @@ -11017,7 +10360,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature Ingen signatur @@ -11030,22 +10373,14 @@ This message is missing. You should receive it later. GxsIdDetails - Loading - Läser in - - - + Not found Hittades inte - - No Signature - Ingen signatur - - - + + [Banned] @@ -11055,7 +10390,7 @@ This message is missing. You should receive it later. okänd nyckel - + Loading... @@ -11065,7 +10400,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -11085,6 +10425,14 @@ This message is missing. You should receive it later. + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -11096,7 +10444,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -11144,17 +10492,13 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] GxsMessageFramePostWidget - - Loading - Läser in - Loading... @@ -11535,7 +10879,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -11551,7 +10895,7 @@ p, li { white-space: pre-wrap; } - + Authors Upphovsmän @@ -11570,7 +10914,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -11648,7 +10992,7 @@ p, li { white-space: pre-wrap; } Formulär - + Add friend @@ -11658,7 +11002,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -11686,7 +11030,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -11696,7 +11040,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard Kopiera certifikatet till Urklipp @@ -11706,7 +11050,7 @@ private and secure decentralized communication platform. Spara certifikatet till fil - + Send via Email @@ -11726,13 +11070,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -11744,12 +11112,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -11764,12 +11132,7 @@ new short format RetroShare-inbjudan - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... Spara som... @@ -12034,14 +11397,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Alla - + Reputation Rykte @@ -12051,12 +11414,12 @@ p, li { white-space: pre-wrap; } Sök - + Anonymous Id Anonymt Id - + Create new Identity Skapa ny identitet @@ -12066,7 +11429,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -12081,27 +11444,27 @@ p, li { white-space: pre-wrap; } - + Close Stäng - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -12117,29 +11480,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles Cirklar - + Circle name @@ -12159,18 +11532,20 @@ p, li { white-space: pre-wrap; } Privata cirklar - + + Edit identity Redigera identitet - + + Delete identity Ta bort identitet - + Chat with this peer @@ -12180,78 +11555,78 @@ p, li { white-space: pre-wrap; } - + Owner node ID : - + Identity name : - + () - + Identity ID Identitets-ID - + Send message Skicka meddelande - + Identity info Identitetsinfo - + Identity ID : Identitets-ID : - + Owner node name : - + Create new... - + Type: Typ: - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: - + Negative Negativ - + Neutral Neutral @@ -12262,17 +11637,17 @@ p, li { white-space: pre-wrap; } Positiv - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous Anonym @@ -12287,24 +11662,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you - - + + My own identities - - + + My contacts - + Show Items @@ -12319,7 +11694,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -12329,7 +11709,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -12404,7 +11784,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -12434,7 +11814,7 @@ p, li { white-space: pre-wrap; } okänd - + Invited @@ -12449,7 +11829,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle Editera cirkeln @@ -12497,7 +11877,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -12505,7 +11885,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -12548,7 +11928,7 @@ These identities will soon be not supported anymore. - + Boards @@ -12628,7 +12008,7 @@ These identities will soon be not supported anymore. - + information @@ -12644,17 +12024,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -12759,7 +12134,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -12809,21 +12184,21 @@ These identities will soon be not supported anymore. - - - + + + People - + Your Avatar Click here to change your avatar Din avatar - + Linked to neighbor nodes @@ -12833,7 +12208,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -12848,7 +12223,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -12863,12 +12238,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -12888,12 +12263,12 @@ These identities will soon be not supported anymore. - + Owned by Ägd av - + Node name: Nodnamn: @@ -12903,7 +12278,7 @@ These identities will soon be not supported anymore. Nod-ID : - + Really delete? @@ -12911,7 +12286,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname Användarnamn @@ -12941,7 +12316,7 @@ These identities will soon be not supported anymore. Pseudonym - + Import image @@ -12951,12 +12326,19 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. + + + No Avatar chosen. A default image will be automatically displayed from your new identity. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity Ny identitet @@ -12970,7 +12352,7 @@ These identities will soon be not supported anymore. - + @@ -12980,7 +12362,12 @@ These identities will soon be not supported anymore. N/A - + + No avatar chosen + + + + Edit identity Editera identitet @@ -12991,27 +12378,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -13031,7 +12418,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -13041,11 +12428,7 @@ These identities will soon be not supported anymore. - Error getting key! - Ett fel uppstod vid hämtning av nyckeln! - - - + Error KeyID invalid Fel NyckelID felaktigt @@ -13060,7 +12443,7 @@ These identities will soon be not supported anymore. Okänt riktigt namn - + Create New Identity Skapa ny Identitet @@ -13070,10 +12453,15 @@ These identities will soon be not supported anymore. Typ - + Choose image... + + + Remove + Ta bort + @@ -13099,7 +12487,7 @@ These identities will soon be not supported anymore. Lägg till - + Create Skapa @@ -13109,13 +12497,13 @@ These identities will soon be not supported anymore. Avbryt - + Your Avatar Click here to change your avatar Din avatar - + Linked to your profile @@ -13125,7 +12513,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -13184,10 +12572,6 @@ These identities will soon be not supported anymore. PGP name: PGP-namn: - - GXS id: - GXS-id: - PGP id: @@ -13203,7 +12587,7 @@ These identities will soon be not supported anymore. - + Copy Kopiera @@ -13213,12 +12597,12 @@ These identities will soon be not supported anymore. Ta bort - + %1 's Message History - + Mark all Markera alla @@ -13237,26 +12621,38 @@ These identities will soon be not supported anymore. Quote Citera - - Send - Skicka - ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -13274,27 +12670,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: Port: - + Listen Address: - + + Status: + Status: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -13315,7 +12716,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -13324,26 +12730,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File Öppna fil - + Open Folder Öppna mapp - + Checking... Kontrollerar... @@ -13353,7 +12764,7 @@ These identities will soon be not supported anymore. Kontrollera filer - + Recommend in a message to... @@ -13381,7 +12792,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend Lägg till kontakt @@ -13397,7 +12808,8 @@ These identities will soon be not supported anymore. - + + Options Alternativ @@ -13418,7 +12830,7 @@ These identities will soon be not supported anymore. - + Quit Avsluta @@ -13429,12 +12841,12 @@ These identities will soon be not supported anymore. Snabbstartsguide - + RetroShare %1 a secure decentralized communication platform RetroShare %1 en säker, decentraliserad kommunikationsplattform - + Unfinished Pågående @@ -13463,11 +12875,12 @@ Frigör mer diskutrymme och klicka OK. + Status Status - + Notify Meddela @@ -13478,31 +12891,35 @@ Frigör mer diskutrymme och klicka OK. + Open Messages Öppna meddelanden - + + Bandwidth Graph Bandbreddsgraf - + Applications Program + Help Hjälp - + + Minimize Minimera - + Maximize Maximera @@ -13517,7 +12934,12 @@ Frigör mer diskutrymme och klicka OK. RetroShare - + + Close window + + + + %1 new message %1 nytt meddelande @@ -13547,7 +12969,7 @@ Frigör mer diskutrymme och klicka OK. %1 kontakter anslutna - + Do you really want to exit RetroShare ? Vill du verkligen avsluta RetroShare? @@ -13567,7 +12989,7 @@ Frigör mer diskutrymme och klicka OK. Visa - + Make sure this link has not been forged to drag you to a malicious website. Tillse att den här länken inte leder till en webbsida med skadlig kod. @@ -13612,12 +13034,13 @@ Frigör mer diskutrymme och klicka OK. Tjänståtkomstmatrix - + + Statistics Statistik - + Show web interface @@ -13632,7 +13055,7 @@ Frigör mer diskutrymme och klicka OK. - + Really quit ? @@ -13641,17 +13064,17 @@ Frigör mer diskutrymme och klicka OK. MessageComposer - + Compose Skriv - + Contacts Kontakter - + Paragraph Rubrik @@ -13687,12 +13110,12 @@ Frigör mer diskutrymme och klicka OK. Rubrik 6 - + Font size Teckenstorlek - + Increase font size Öka teckenstorlek @@ -13707,32 +13130,32 @@ Frigör mer diskutrymme och klicka OK. Fet - + Italic Kursiv - + Alignment Justering - + Add an Image Lägg till en bild - + Sets text font to code style Anger teckensnitt - + Underline Understruken - + Subject: Ämne: @@ -13743,32 +13166,32 @@ Frigör mer diskutrymme och klicka OK. - + Tags Taggar - + Address list: - + Recommend this friend - + Set Text color - + Set Text background color - + Recommended Files Rekommenderade filer @@ -13838,7 +13261,7 @@ Frigör mer diskutrymme och klicka OK. Lägg till blockcitat - + Send To: Skicka till: @@ -13878,7 +13301,7 @@ Frigör mer diskutrymme och klicka OK. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> Hej! Jag rekommenderar mina kontakter. Du kan autentisera dem också, när du autentiserar mig. @@ -13898,18 +13321,18 @@ Frigör mer diskutrymme och klicka OK. vill bli en av dina kontakter på RetroShare - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team Hej %1!<br><br>%2 vill bli en av dina kontakter på RetroShare.<br><br>Svara nu:<br>%3<br><br>Tack!<br>RetroShare Team - - + + Save Message Spara meddelande - + Message has not been Sent. Do you want to save message to draft box? Meddelandet har inte skickats. @@ -13921,7 +13344,17 @@ Vill du spara meddelandet i Utkast? Klistra in RetroShare-länk - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" Lägg till i "Till" @@ -13941,7 +13374,7 @@ Vill du spara meddelandet i Utkast? Lägg till som rekommendation - + Original Message Ursprungligt meddelande @@ -13951,21 +13384,21 @@ Vill du spara meddelandet i Utkast? Från - + - + To Till - - + + Cc Kopia - + Sent Skickat @@ -13980,7 +13413,7 @@ Vill du spara meddelandet i Utkast? På %1, skrev %2: - + Re: Svar: @@ -13990,30 +13423,30 @@ Vill du spara meddelandet i Utkast? Vidarebefordran: - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? Vill du skicka meddelandet utan angivet ämne? - + Please insert at least one recipient. Ange minst en mottagare. - + Bcc Dold kopia - + Unknown Okänd @@ -14128,13 +13561,13 @@ Vill du spara meddelandet i Utkast? Detaljer - + Open File... Öppna fil... - + HTML-Files (*.htm *.html);;All Files (*) HTML-filer (*.htm *.html);;Alla Filer (*) @@ -14154,7 +13587,7 @@ Vill du spara meddelandet i Utkast? Exportera PDF - + Message has not been Sent. Do you want to save message ? Meddelandet har inte skickats. @@ -14176,7 +13609,7 @@ Vill du spara meddelandet? Lägg till fil - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -14206,18 +13639,18 @@ Vill du spara meddelandet? - - + + Close Stäng - + From: Från: - + Bullet list (disc) @@ -14257,13 +13690,13 @@ Vill du spara meddelandet? - - + + Thanks, <br> - + Distant identity: @@ -14273,12 +13706,12 @@ Vill du spara meddelandet? - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -14356,7 +13789,7 @@ Vill du spara meddelandet? Standard - + A new tab Ny flik @@ -14366,7 +13799,7 @@ Vill du spara meddelandet? Nytt fönster - + Edit Tag Redigera tagg @@ -14389,7 +13822,7 @@ Vill du spara meddelandet? MessageToaster - + Sub: Ämne: @@ -14397,7 +13830,7 @@ Vill du spara meddelandet? MessageUserNotify - + Message Meddelande @@ -14425,7 +13858,7 @@ Vill du spara meddelandet? MessageWidget - + Recommended Files Rekommenderade filer @@ -14435,37 +13868,37 @@ Vill du spara meddelandet? Ladda ner alla rekommenderade filer - + Subject: Ämne: - + From: Från: - + To: Till: - + Cc: Kopia: - + Bcc: Dold kopia: - + Tags: Taggar: - + Reply Svara @@ -14487,7 +13920,7 @@ Vill du spara meddelandet? Forward - + Framåt @@ -14505,7 +13938,7 @@ Vill du spara meddelandet? - + Send Invite @@ -14557,7 +13990,7 @@ Vill du spara meddelandet? - + Confirm %1 as friend Bekräfta %1 som kontakt @@ -14567,12 +14000,12 @@ Vill du spara meddelandet? Lägg till %1 som kontakt - + View source - + No subject Inget ämne @@ -14582,17 +14015,22 @@ Vill du spara meddelandet? Ladda ner - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -14601,14 +14039,24 @@ Vill du spara meddelandet? %1 (%2) + + + Show less + + + + + Show more + + - + Download all Ladda ner alla - + Print Document Skriv ut dokument @@ -14623,12 +14071,12 @@ Vill du spara meddelandet? HTML-filer (*.htm *.html);;Alla Filer (*) - + Load images always for this message Ladda alltid bilder för detta meddelande - + Hide the attachment pane @@ -14650,42 +14098,6 @@ Vill du spara meddelandet? Compose Skriv - - Reply to selected message - Svara på markerat meddelande - - - Reply - Svara - - - Reply all to selected message - Svara alla på markerat meddelande - - - Reply all - Svara alla - - - Forward selected message - Vidarebefordra markerat meddelande - - - Forward - Vidarebefordra - - - Remove selected message - Ta bort markerat meddelande - - - Delete - Ta bort - - - Print selected message - Skriv ut markerat meddelande - Print @@ -14764,7 +14176,7 @@ Vill du spara meddelandet? MessagesDialog - + New Message Nytt meddelande @@ -14774,60 +14186,16 @@ Vill du spara meddelandet? Skriv - Reply to selected message - Svara på markerat meddelande - - - Reply - Svara - - - Reply all to selected message - Svara alla på markerat meddelande - - - Reply all - Svara alla - - - Forward selected message - Vidarebefordra markerat meddelande - - - Foward - Vidarebefordra - - - Remove selected message - Ta bort markerat meddelande - - - Delete - Ta bort - - - Print selected message - Skriv ut markerat meddelande - - - Print - Skriv ut - - - Display - Visa - - - + - - + + Tags Taggar - - + + Inbox Inkorg @@ -14857,21 +14225,17 @@ Vill du spara meddelandet? Papperskorg - + Total Inbox: Totalt inkorg: - Folders - Mappar - - - + Quick View Snabbvy - + Print... Skriv ut... @@ -14881,26 +14245,6 @@ Vill du spara meddelandet? Print Preview Förhandsgranskning - - Buttons Icon Only - Endast ikoner - - - Buttons Text Beside Icon - Text intill ikon - - - Buttons with Text - Endast text - - - Buttons Text Under Icon - Text under ikon - - - Set Text Under Icon - Ange text under ikon - Save As... @@ -14922,7 +14266,7 @@ Vill du spara meddelandet? Vidarebefordra meddelande - + Subject Ämne @@ -14932,7 +14276,7 @@ Vill du spara meddelandet? Från - + Date Datum @@ -14942,39 +14286,7 @@ Vill du spara meddelandet? Innehåll - Click to sort by attachments - Klicka för att sortera efter bilagor - - - Click to sort by subject - Klicka för att sortera efter ämne - - - Click to sort by read - Klicka för att sortera efter 'Lästa' - - - Click to sort by from - Klicka för att sortera efter 'Från' - - - Click to sort by date - Klicka för att sortera efter datum - - - Click to sort by tags - Klicka för att sortera efter taggar - - - Click to sort by star - Klicka för att sortera efter 'Stjärnmärkt' - - - Forward selected Message - Vidarebefordra markerat meddelande - - - + Search Subject Sök på ämne @@ -14983,6 +14295,11 @@ Vill du spara meddelandet? Search From Sök på avsändare + + + Search To + + Search Date @@ -15009,14 +14326,14 @@ Vill du spara meddelandet? Sök på bilagor - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred - Stjärnmärkt + @@ -15090,7 +14407,7 @@ Vill du spara meddelandet? - Show author in People + Show in People @@ -15104,7 +14421,7 @@ Vill du spara meddelandet? - + No message using %1 tag available. @@ -15119,34 +14436,33 @@ Vill du spara meddelandet? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts Utkast - + No Box selected. - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - Det finns inga stjärnmärkta meddelanden. Stjärnorna ger meddelanden en särskild status, för att dom skall bli lättare att hitta. För att stjärnmärka ett meddelande, klickar du på den grå stjärnan vid sidan av önskat meddelande. - - - No system messages available. - Det finns inga systemmeddelanden. - - + To - Till + Till - Click to sort by to - Klicka för att sortera efter - - - + @@ -15154,22 +14470,6 @@ Vill du spara meddelandet? Total: Totalt: - - Messages - Meddelanden - - - Click to sort by signature - Klicka för att sortera enligt signatur - - - This message was signed and the signature checks - Det här meddelandet har blivit signerat och signaturen kollar - - - This message was signed but the signature doesn't check - Det här meddelandet har blivit signerat men signaturen stämmer inte - Mail @@ -15197,7 +14497,17 @@ Vill du spara meddelandet? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -15251,7 +14561,7 @@ Vill du spara meddelandet? - + Expand Expandera @@ -15261,7 +14571,7 @@ Vill du spara meddelandet? Ta bort objektet - + from Från @@ -15296,7 +14606,7 @@ Vill du spara meddelandet? Väntande - + Hide Dölj @@ -15437,7 +14747,7 @@ Vill du spara meddelandet? Användar-ID - + Remove unused keys... Ta bort oanvända nycklar... @@ -15447,7 +14757,7 @@ Vill du spara meddelandet? - + Clean keyring Rensa nyckelringen @@ -15465,7 +14775,13 @@ Notera: Din gamla nyckelring kommer att säkerhetskopieras. Borttagningen kan misslyckas om du kör flera Retroshare-instanser på samma maskin. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info Nyckelringsinformation @@ -15501,18 +14817,13 @@ För din säkerhet har din nyckelring säkerhetskopierats till filen Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. Inkonsistent data i nyckelringen. Detta är troligtvis en bug. Var god och kontakta utvecklarna. - - - Export/create a new node - - Trusted keys only - + Search name @@ -15522,25 +14833,18 @@ För din säkerhet har din nyckelring säkerhetskopierats till filen - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: - - NetworkPage - - Network - Nätverk - - NetworkView @@ -15567,7 +14871,7 @@ Reported error: NewFriendList - + Offline Friends @@ -15588,7 +14892,7 @@ Reported error: - + Groups Grupper @@ -15618,19 +14922,19 @@ Reported error: importera din vänlista inklusive grupper - - + + Search Sök - + ID ID - + Search ID @@ -15640,12 +14944,12 @@ Reported error: - + Show Items - + Last contact @@ -15655,7 +14959,7 @@ Reported error: IP - + Group Grupp @@ -15770,7 +15074,7 @@ Reported error: Fäll ihop alla - + Do you want to remove this node? Vill du ta bort denna nod? @@ -15780,7 +15084,7 @@ Reported error: - + Done! Färdig! @@ -15887,7 +15191,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -15902,11 +15206,7 @@ at least one peer was not added to a group Ta bort alla - This is a test. - Detta är ett test. - - - + Newest on top @@ -15916,12 +15216,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15976,10 +15276,6 @@ at least one peer was not added to a group Blogs Bloggar - - Security - Säkerhet - @@ -16001,10 +15297,6 @@ at least one peer was not added to a group Message Meddelande - - Connect attempt - Anslutningsförsök - @@ -16158,10 +15450,6 @@ at least one peer was not added to a group Disable All Toaster temporarily - - Feed - Flöde - Systray @@ -16171,7 +15459,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -16191,12 +15479,12 @@ at least one peer was not added to a group Fel lösenord! - + Please enter your Retroshare passphrase - + Unregistered plugin/executable Oregisterad insticks-/programfil @@ -16211,19 +15499,7 @@ at least one peer was not added to a group Kontrollera din systemklocka. - Examining shared files... - Undersöker delade filer... - - - Hashing file - Hash-beräknar fil - - - Saving file index... - Sparar filindex... - - - + Test Testa @@ -16234,17 +15510,19 @@ at least one peer was not added to a group + Unknown title Okänd titel - + + Encrypted message Krypterat meddelande - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -16252,7 +15530,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online Kontakten ansluten @@ -16394,7 +15672,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -16403,10 +15686,6 @@ p, li { white-space: pre-wrap; } Keysigning: - - Sign PGP key - Signera GPG-nyckel - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -16443,12 +15722,7 @@ p, li { white-space: pre-wrap; } Inkludera signaturer - - Options - Alternativ - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -16494,21 +15768,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare RetroShare - - + + Error : cannot get peer details. Fel: Kan inte hämta användaruppgifter. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) Angiven nyckelalgoritm stöds inte av RetroShare. (För tillfället stöds endast RSA-nycklar) @@ -16526,7 +15800,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -16595,10 +15869,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Check the password! - - Maybe password is wrong - Lösenordet kanske är fel - You haven't set a trust level for this key. @@ -16606,12 +15876,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -16637,7 +15907,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat Chatta @@ -16658,7 +15928,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.Ta bort objektet - + Name: Namn: @@ -16698,7 +15968,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message Skriv meddelande @@ -16712,10 +15982,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Friend Connected Kontakten anslöt - - Connect Attempt - Anslutningsförsök - Connection refused by peer @@ -16754,17 +16020,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.Unknown - - Unknown Peer - Okänd användare - Hide Dölj - + Send Message Sänd Meddelande @@ -16931,13 +16193,6 @@ Warning: In your File-Transfer option, you select allow direct download to No. - - PhotoCommentItem - - Form - Formulär - - PhotoDialog @@ -16945,23 +16200,11 @@ Warning: In your File-Transfer option, you select allow direct download to No.PhotoShare Fotodelning - - Photo - Bild - TextLabel Bildtext - - Comment - Kommentar - - - Summary - Sammanfattning - Album / Photo Name @@ -17022,14 +16265,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.... ... - - Add Comment - Lägg till kommentar - - - Write a comment... - Skriv en kommentar... - Album @@ -17100,10 +16335,6 @@ p, li { white-space: pre-wrap; } Create Album Skapa album - - View Album - Visa album - Edit Album Details @@ -17125,17 +16356,17 @@ p, li { white-space: pre-wrap; } Bildspel - + My Albums Mina album - + Subscribed Albums Albumprenumerationer - + Shared Albums Delade album @@ -17165,7 +16396,7 @@ före redigering! PhotoSlideShow - + Album Name Albumnamn @@ -17224,19 +16455,19 @@ före redigering! - - + + TextLabel - + Posted by - + ago @@ -17272,12 +16503,12 @@ före redigering! PluginItem - + TextLabel Textetikett - + Show more details about this plugin Visa mer information om det här insticksprogrammet @@ -17423,44 +16654,6 @@ p, li { white-space: pre-wrap; } Plugin look-up directories Mappar med insticksprogram - - No API number supplied. Please read plugin development manual. - Inget API-nummer. Läs manualen för insticksutveckling. - - - No SVN number supplied. Please read plugin development manual. - Inget SVN-nummer. Läs manualen för insticksutveckling. - - - Loading error. - Inläsningsfel. - - - Missing symbol. Wrong version? - Saknat tecken, fel version? - - - No plugin object - Det finns inga insticksprogram - - - Plugins is loaded. - Insticksprogram inläst. - - - Unknown status. - Okänd status. - - - Check this for developing plugins. They will not -be checked for the hash. However, in normal -times, checking the hash protects you from -malicious behavior of crafted plugins. - Markera detta för instick under utveckling. -De kommer inte att hash-beräknas, vilket i normala -fall görs som skydd mot skadligt beteende från -felaktigt utformade insticksprogram. - Plugins @@ -17530,12 +16723,27 @@ felaktigt utformade insticksprogram. Alltid överst - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -17569,14 +16777,6 @@ felaktigt utformade insticksprogram. Close conversation? - - Closing this window will end the conversation, notify the peer and remove the encrypted tunnel. - Om du stänger fönstret kommer konversationen att avslutas, den andra parten meddelas och den krypterade tunneln tas bort. - - - Kill the tunnel? - Ta bort tunneln? - PostedCardView @@ -17596,7 +16796,7 @@ felaktigt utformade insticksprogram. Nytt - + Vote up @@ -17616,8 +16816,8 @@ felaktigt utformade insticksprogram. \/ - - + + Comments Kommentarer @@ -17642,13 +16842,13 @@ felaktigt utformade insticksprogram. - - + + Comment Kommentar - + Comments @@ -17676,20 +16876,12 @@ felaktigt utformade insticksprogram. PostedCreatePostDialog - Signed by: - Signerad av: - - - Notes - Anteckningar - - - + Create a new Post - + RetroShare RetroShare @@ -17704,12 +16896,22 @@ felaktigt utformade insticksprogram. - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File Läs in en bildfil - + Post image @@ -17725,7 +16927,17 @@ felaktigt utformade insticksprogram. - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -17735,15 +16947,7 @@ felaktigt utformade insticksprogram. - Submit Post - Skicka - - - Submit - Skicka - - - + Please add a Title @@ -17763,12 +16967,22 @@ felaktigt utformade insticksprogram. - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -17783,7 +16997,7 @@ felaktigt utformade insticksprogram. Posta som - + Post @@ -17794,7 +17008,7 @@ felaktigt utformade insticksprogram. Bild - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -17804,7 +17018,7 @@ felaktigt utformade insticksprogram. Rubrik - + Link Länk @@ -17812,32 +17026,12 @@ felaktigt utformade insticksprogram. PostedDialog - Posted Links - Postade länkar - - - My Topics - Mina rubriker - - - Subscribed Topics - Rubrikprenumerationer - - - Popular Topics - Populära rubriker - - - Other Topics - Andra rubriker - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -17871,27 +17065,7 @@ felaktigt utformade insticksprogram. PostedGroupDialog - Posted Topic - Postad rubrik - - - Add Topic Admins - Lägg till rubrikadministratörer - - - Select Topic Admins - Välj rubrikadministratörer - - - Create New Topic - Skapa nytt ämne - - - Edit Topic - Redigera Ämne - - - + Create New Board @@ -17929,7 +17103,17 @@ felaktigt utformade insticksprogram. PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted @@ -17945,7 +17129,7 @@ felaktigt utformade insticksprogram. - + Expand Visa @@ -17960,16 +17144,17 @@ felaktigt utformade insticksprogram. - Loading - Läser in - - - + Loading... - + + Never + + + + New Board @@ -17982,22 +17167,18 @@ felaktigt utformade insticksprogram. PostedItem - + 0 0 - Site - Webbplats - - - - + + Comments Kommentarer - + Copy RetroShare Link Kopiera RetroShare-länk @@ -18008,12 +17189,12 @@ felaktigt utformade insticksprogram. - + Comment Kommentar - + Comments @@ -18023,7 +17204,7 @@ felaktigt utformade insticksprogram. - + Click to view Picture @@ -18033,21 +17214,17 @@ felaktigt utformade insticksprogram. Dölj - + Vote up - + Vote down - \/ - \/ - - - + Set as read and remove item Markera som läst och ta bort objektet @@ -18057,7 +17234,7 @@ felaktigt utformade insticksprogram. Nytt - + New Comment: @@ -18067,7 +17244,7 @@ felaktigt utformade insticksprogram. - + Name Namn @@ -18108,69 +17285,10 @@ felaktigt utformade insticksprogram. - + Loading Läser in - - By - Av - - - - PostedListWidget - - Form - Formulär - - - Hot - Het - - - New - Nytt - - - Top - Topp - - - Today - I dag - - - Yesterday - I går - - - This Week - Den här veckan - - - This Month - Den här månaden - - - This Year - Detta år - - - Next - Nästa - - - RetroShare - RetroShare - - - Please create or choose a Signing Id before Voting - Skapa nytt eller välj ett befintligt signatur-ID först - - - Previous - Föregående - PostedListWidgetWithModel @@ -18190,7 +17308,17 @@ felaktigt utformade insticksprogram. - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -18200,15 +17328,15 @@ felaktigt utformade insticksprogram. - + - + unknown okänd - + Distribution: @@ -18218,42 +17346,42 @@ felaktigt utformade insticksprogram. - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -18273,7 +17401,7 @@ felaktigt utformade insticksprogram. Het - + Search Sök @@ -18303,17 +17431,17 @@ felaktigt utformade insticksprogram. - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -18328,12 +17456,17 @@ felaktigt utformade insticksprogram. - + Copy RetroShare Link Kopiera RetroShare-länk - + + Copy http Link + + + + Show author in People tab @@ -18343,27 +17476,31 @@ felaktigt utformade insticksprogram. Redigera - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -18378,7 +17515,7 @@ felaktigt utformade insticksprogram. Prenumerera - + Never @@ -18452,6 +17589,16 @@ felaktigt utformade insticksprogram. No Channel Selected Inga kanaler markerade + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -18460,10 +17607,6 @@ felaktigt utformade insticksprogram. Tabs Flikar - - Open each topic in a new tab - Öppna varje ämne i en ny flik - Open each board in a new tab @@ -18477,10 +17620,6 @@ felaktigt utformade insticksprogram. PostedUserNotify - - Posted - Postat - Board Post @@ -18549,16 +17688,16 @@ felaktigt utformade insticksprogram. Profilhanterare - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -18670,7 +17809,7 @@ och där läsa in den med importfunktionen. ProfileWidget - + Edit status message Redigera statusmeddelande @@ -18686,7 +17825,7 @@ och där läsa in den med importfunktionen. Profilhanterare - + Public Information Publik information @@ -18721,12 +17860,12 @@ och där läsa in den med importfunktionen. Ansluten sedan: - + Other Information Annan information - + My Address Min adress @@ -18770,51 +17909,27 @@ och där läsa in den med importfunktionen. PulseAddDialog - Post From: - Inlägg från: - - - Account 1 - Konto 1 - - - Account 2 - Konto 2 - - - Account 3 - Konto 3 - - - + Add to Pulse Lägg till i Pulse - filter - filter - - - URL Adder - URL-Adder - - - + Display As Visa som - + URL URL - + GroupLabel - + IDLabel @@ -18824,12 +17939,12 @@ och där läsa in den med importfunktionen. Från: - + Head - + Head Shot @@ -18859,13 +17974,13 @@ och där läsa in den med importfunktionen. Negativ - - + + Whats happening? - + @@ -18877,12 +17992,22 @@ och där läsa in den med importfunktionen. - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -18891,17 +18016,13 @@ och där läsa in den med importfunktionen. Cancel Avbryt - - Post Pulse to Wire - Posta Pulse till Wire - Post - + Reply to Pulse @@ -18916,34 +18037,24 @@ och där läsa in den med importfunktionen. - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - Från - - - Date - Datum - - - ... - ... + + Load Picture File + Läs in en bildfil @@ -18954,7 +18065,7 @@ och där läsa in den med importfunktionen. Formulär - + @@ -18973,7 +18084,7 @@ och där läsa in den med importfunktionen. PulseReply - + icn @@ -18983,7 +18094,7 @@ och där läsa in den med importfunktionen. - + REPLY @@ -19010,7 +18121,7 @@ och där läsa in den med importfunktionen. - + FOLLOW @@ -19020,7 +18131,7 @@ och där läsa in den med importfunktionen. - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -19040,7 +18151,7 @@ och där läsa in den med importfunktionen. - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -19156,7 +18267,7 @@ och där läsa in den med importfunktionen. - + FOLLOW @@ -19164,37 +18275,42 @@ och där läsa in den med importfunktionen. PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -19226,7 +18342,7 @@ och där läsa in den med importfunktionen. - + FOLLOW @@ -19234,8 +18350,8 @@ och där läsa in den med importfunktionen. QObject - - + + Confirmation Bekräftelse @@ -19506,12 +18622,12 @@ Tecknen <b>",|,/,\,&lt;,&gt;,*,?</b> kommer att ersätt Användarinformation - + File Request canceled Filbegäran avbruten - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. Denna version av RetroShare använder OpenPGP-SDK. Som sidoeffekt använder den inte systemets delade PGP-nyckelring, utan har sin egen nyckelring som delas av alla RetroShare-instanser. <br><br>Du verkar inte ha någon sådan nyckelring, även om GPG-nycklar associeras med befintliga RetroShare-konton, troligen för att du just uppgraderat till denna nya version av programmet. @@ -19542,7 +18658,7 @@ Tecknen <b>",|,/,\,&lt;,&gt;,*,?</b> kommer att ersätt Ett oväntat fel uppstod. Rapportera 'RsInit::InitRetroShare unexpected return code %1'. - + Cannot start Tor Manager! @@ -19576,7 +18692,7 @@ The error reported is:" - + Multiple instances Flera instanser @@ -19597,6 +18713,26 @@ The error reported is:" Låsfil: + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -19677,7 +18813,7 @@ Rapporterat fel är: %2 - + You appear to have nodes associated to DSA keys: @@ -19687,7 +18823,7 @@ Rapporterat fel är: %2 - + enabled @@ -19697,7 +18833,7 @@ Rapporterat fel är: %2 - + Move IP %1 to whitelist @@ -19713,7 +18849,7 @@ Rapporterat fel är: %2 - + %1 seconds ago @@ -19780,7 +18916,7 @@ Security: no anonymous IDs - + Join chat room @@ -19808,7 +18944,7 @@ Security: no anonymous IDs - + Indefinitely @@ -19988,13 +19124,29 @@ Security: no anonymous IDs Ban list + + + Name + Namn + + Node + Nod + + + + Address + + + + + Status Status - + NXS @@ -20237,6 +19389,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -20399,7 +19563,7 @@ p, li { white-space: pre-wrap; } - + Network Wide Nätverksövergripande @@ -20579,7 +19743,7 @@ p, li { white-space: pre-wrap; } Formulär - + The loading of embedded images is blocked. Laddning av inbäddade bilder är blockerad. @@ -20592,7 +19756,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default @@ -20765,12 +19929,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -20778,12 +19952,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -21475,7 +20649,7 @@ Om du tror att den är giltig, ta bort strängen från filen och öppna den på RsDownloadListModel - + Name i.e: file name Namn @@ -21596,7 +20770,7 @@ Om du tror att den är giltig, ta bort strängen från filen och öppna den på RsFriendListModel - + Name Namn @@ -21616,7 +20790,7 @@ Om du tror att den är giltig, ta bort strängen från filen och öppna den på IP - + Profile ID @@ -21672,7 +20846,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -21686,11 +20860,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - [ ... Meddelande saknas ... ] - RsMessageModel @@ -21704,6 +20873,11 @@ prevents the message to be forwarded to your friends. From Från + + + To + Till + Subject @@ -21726,13 +20900,18 @@ prevents the message to be forwarded to your friends. - Click to sort by read - Klicka för att sortera efter 'Lästa' + Click to sort by read status + - Click to sort by from - Klicka för att sortera efter 'Från' + Click to sort by author + + + + + Click to sort by destination + @@ -21755,7 +20934,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -21776,7 +20957,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. Återställer ALLA sparade RetroShare-inställningar. @@ -21837,7 +21018,7 @@ prevents the message to be forwarded to your friends. Anger RetroShares språk. - + Unable to open log file '%1': %2 Kan inte öppna loggfil '%1': %2 @@ -21858,11 +21039,7 @@ prevents the message to be forwarded to your friends. Kunde inte skapa datamapp: %1 - Revision - Revision - - - + opmode @@ -21892,7 +21069,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -21910,7 +21087,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -21927,12 +21104,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) Ange nyckelord här (minst 3 tecken) - + Start Search Starta sökning @@ -21994,7 +21171,7 @@ prevents the message to be forwarded to your friends. Rensa - + KeyWords Nyckelord @@ -22009,7 +21186,7 @@ prevents the message to be forwarded to your friends. Sök ID - + Filename Filnamn @@ -22109,23 +21286,23 @@ prevents the message to be forwarded to your friends. Nedladdning vald - + File Name Filnamn - + Download Ladda ner - + Copy RetroShare Link Kopiera RetroShare-länk - + Send RetroShare Link Skicka RetroShare-länk @@ -22135,7 +21312,7 @@ prevents the message to be forwarded to your friends. - + Download Notice Nedladdningsunderrättelse @@ -22172,7 +21349,7 @@ prevents the message to be forwarded to your friends. Ta bort alla - + Folder Mapp @@ -22183,17 +21360,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) Ny RetroShare-länk - + Open Folder Öppna mapp - + Create Collection... Skapa samling... @@ -22213,7 +21390,7 @@ prevents the message to be forwarded to your friends. Ladda ner från samlingsfil... - + Collection Samling @@ -22221,7 +21398,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details Användarinformation @@ -22237,22 +21414,22 @@ prevents the message to be forwarded to your friends. Ta bort objektet - + IP address: IP-adress: - + Peer ID: Användar-ID - + Location: Plats: - + Peer Name: @@ -22269,7 +21446,7 @@ prevents the message to be forwarded to your friends. Dölj - + but reported: @@ -22294,8 +21471,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -22303,7 +21480,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare vill bli en av dina kontakter på RetroShare @@ -22334,7 +21511,7 @@ prevents the message to be forwarded to your friends. - + Expand Expandera @@ -22379,12 +21556,12 @@ prevents the message to be forwarded to your friends. Status: - + Write Message Skriv meddelande - + Connect Attempt Anslutningsförsök @@ -22404,17 +21581,22 @@ prevents the message to be forwarded to your friends. Okänt (utgående) anslutningsförsök - + Unknown Security Issue Okänt säkerhetsproblem - - A unknown peer + + SSL request - + + An unknown peer + + + + Unknown @@ -22424,11 +21606,7 @@ prevents the message to be forwarded to your friends. - Unknown Peer - Okänd användare - - - + Hide Dölj @@ -22438,7 +21616,7 @@ prevents the message to be forwarded to your friends. Vill du verkligen ta bort den här kontakten? - + Certificate has wrong signature!! This peer is not who he claims to be. Certifikatet har fel signatur!! Den här klienten är inte vem den utger sig för att vara. @@ -22448,12 +21626,12 @@ prevents the message to be forwarded to your friends. - + Certificate caused an internal error. Certifikatet orsakade ett internt fel. - + Peer/node not in friendlist (PGP id= @@ -22512,12 +21690,12 @@ prevents the message to be forwarded to your friends. - + Local Address Lokal adress - + NAT @@ -22538,22 +21716,22 @@ prevents the message to be forwarded to your friends. Port: - + Local network Lokalt nätverk - + External ip address finder Sökverktyg för externt IP - + UPnP UPnP - + Known / Previous IPs: Kända / Tidigare IP: @@ -22569,21 +21747,16 @@ när du ansluter till någon. Att låta det här vara markerat bra om du sitter bakom en brandvägg eller en VPN-tunnel. - - Allow RetroShare to ask my ip to these websites: - Låt RetroShare fråga om min externa IP-adress på dessa sidor: - - - - - + + + kB/s kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -22593,23 +21766,46 @@ bra om du sitter bakom en brandvägg eller en VPN-tunnel. - + Onion Address - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -22619,7 +21815,7 @@ bra om du sitter bakom en brandvägg eller en VPN-tunnel. - + I2P Address I2P-adress @@ -22644,37 +21840,95 @@ bra om du sitter bakom en brandvägg eller en VPN-tunnel. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -22689,71 +21943,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. okänd - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -22763,22 +21953,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -22790,12 +21965,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -22805,7 +21980,7 @@ Also check your ports! Rensa - + Download limit (KB/s) @@ -22820,23 +21995,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -22847,17 +22022,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -22867,12 +22032,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -22882,17 +22042,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 127.0.0.1 - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -22932,7 +22082,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start Starta @@ -22947,12 +22097,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why Stopp - - BOB status - - - - + Incoming Inkommande @@ -22988,7 +22133,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -23043,7 +22213,7 @@ If you have issues connecting over Tor check the Tor logs too. Totalt: - + Warning: This bandwidth adds up to the max bandwidth. @@ -23068,7 +22238,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -23080,7 +22250,7 @@ If you have issues connecting over Tor check the Tor logs too. Nätverk - + IP Filters IP-filter @@ -23103,7 +22273,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status Status @@ -23163,17 +22333,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -23189,18 +22370,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -23235,12 +22416,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -23263,22 +22444,22 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -23313,7 +22494,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -23323,12 +22504,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -23408,7 +22589,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with Markera de användare du vill dela privat publiceringsnyckel med. @@ -23418,12 +22599,12 @@ If you have issues connecting over Tor check the Tor logs too. Dela med kontakt - + Share Dela - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. Du kan meddela dina vänner om din kanal genom att dela den med dem. @@ -23443,7 +22624,7 @@ Välj de kontakter du vill dela kanalen med. Delade mappar - + Shared directory @@ -23463,17 +22644,17 @@ Välj de kontakter du vill dela kanalen med. Synlighet - + Add new - + Cancel Avbryt - + Add a Share Directory Lägg till en delad katalog @@ -23483,7 +22664,7 @@ Välj de kontakter du vill dela kanalen med. Ta bort - + Apply and close Verkställ och stäng @@ -23574,7 +22755,7 @@ Välj de kontakter du vill dela kanalen med. Mappen kan inte hittas, eller ogiltigt mappnamn. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. Det här är en lista på delade mappar. Du kan lägga till eller ta bort mappar med knapparna nedantill. När du lägger till en ny katalog så delas alla filer i denna katalog ut. Du kan ange olika rättigheter för varje enskild katalog. @@ -23582,7 +22763,7 @@ Välj de kontakter du vill dela kanalen med. SharedFilesDialog - + Files Filer @@ -23633,11 +22814,16 @@ Välj de kontakter du vill dela kanalen med. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files Kontrollera filer - + Download selected Ladda ner markerat @@ -23647,7 +22833,7 @@ Välj de kontakter du vill dela kanalen med. Ladda ner - + Copy retroshare Links to Clipboard Kopiera RetroShare-länk till Urklipp @@ -23662,7 +22848,7 @@ Välj de kontakter du vill dela kanalen med. Skicka RetroShare-länk - + Some files have been omitted @@ -23678,7 +22864,7 @@ Välj de kontakter du vill dela kanalen med. Rekommendation(er) - + Create Collection... Skapa samling... @@ -23703,7 +22889,7 @@ Välj de kontakter du vill dela kanalen med. Ladda ner från samlingsfil... - + Some files have been omitted because they have not been indexed yet. @@ -23846,12 +23032,12 @@ Välj de kontakter du vill dela kanalen med. SplashScreen - + Load configuration Läser in konfiguration - + Create interface Skapar gränssnitt @@ -23875,7 +23061,7 @@ Välj de kontakter du vill dela kanalen med. Kom ihåg lösenordet - + Log In Logga in @@ -24216,7 +23402,7 @@ This choice can be reverted in settings. Statusmeddelande - + Message: Meddelande: @@ -24461,7 +23647,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags Ta bort alla taggar @@ -24497,12 +23683,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown @@ -24512,18 +23701,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -24533,12 +23717,57 @@ p, li { white-space: pre-wrap; } - + + Error + Fel + + + + Not connected + Inte ansluten + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -24546,7 +23775,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -24556,7 +23785,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -24567,11 +23796,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -24599,7 +23829,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options Överföringsalternativ @@ -24610,7 +23840,7 @@ p, li { white-space: pre-wrap; } Max antal samtidiga nedladdningar: - + Shared Directories @@ -24620,22 +23850,27 @@ p, li { white-space: pre-wrap; } Dela inkommande automatiskt (Rekommenderas) - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -24720,7 +23955,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -24729,7 +23964,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -24754,7 +23994,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming Strömmande @@ -24819,12 +24064,7 @@ p, li { white-space: pre-wrap; } Max antal tunnelförfrågningar per sekund: - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -24834,7 +24074,17 @@ p, li { white-space: pre-wrap; } - + + Warning + Varning + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -24862,7 +24112,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed Nedladdning slutförd @@ -24886,39 +24136,23 @@ p, li { white-space: pre-wrap; } %1 completed transfer - - You have %1 completed downloads - Du har %1 slutförda nedladdningar - - - You have %1 completed download - Du har %1 slutförd nedladdning - - - %1 completed downloads - %1 slutförda nedladdningar - - - %1 completed download - %1 slutförd nedladdning - TransfersDialog - - + + Downloads Nerladdningar - + Uploads Uppladdningar - + Name i.e: file name Namn @@ -25125,7 +24359,12 @@ p, li { white-space: pre-wrap; } Specificera - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... Flytta i kön... @@ -25150,7 +24389,7 @@ p, li { white-space: pre-wrap; } Välj mapp - + Anonymous end-to-end encrypted tunnel 0x @@ -25171,7 +24410,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -25204,7 +24443,17 @@ p, li { white-space: pre-wrap; } %1 är inte slutförd. Är det en mediafil kan du försöka förhandsgranska den. - + + Warning + Varning + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name Byt filnamn @@ -25219,7 +24468,7 @@ p, li { white-space: pre-wrap; } Ange nytt giltigt filnamn - + Expand all Expandera alla @@ -25346,23 +24595,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Kolumner - + File Transfers Filöverföringar - + Path Sökväg @@ -25372,7 +24616,7 @@ p, li { white-space: pre-wrap; } Visa Väg-kolumn - + Could not delete preview file @@ -25382,7 +24626,7 @@ p, li { white-space: pre-wrap; } - + Create Collection... Skapa samling... @@ -25397,7 +24641,7 @@ p, li { white-space: pre-wrap; } Visa samling... - + Collection Samling @@ -25407,7 +24651,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x @@ -25821,12 +25065,17 @@ p, li { white-space: pre-wrap; } Formulär - + Enable Retroshare WEB Interface - + + Status: + Status: + + + Web parameters @@ -25866,17 +25115,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -25886,12 +25145,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface Webbgränssnitt @@ -26028,11 +25287,7 @@ p, li { white-space: pre-wrap; } Wiki-sidor - New Group - Ny grupp - - - + Page Name Sidnamn @@ -26047,7 +25302,7 @@ p, li { white-space: pre-wrap; } Original-ID - + << << @@ -26135,7 +25390,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History Sidredigeringshistorik @@ -26170,7 +25425,7 @@ p, li { white-space: pre-wrap; } Sid-ID - + \/ \/ @@ -26200,14 +25455,18 @@ p, li { white-space: pre-wrap; } Taggar - - + + History + Historik + + + Show Edit History Visa redigeringshistorik - + Status Status @@ -26228,7 +25487,7 @@ p, li { white-space: pre-wrap; } Återställ - + Submit Skicka @@ -26300,10 +25559,6 @@ p, li { white-space: pre-wrap; } WireDialog - - TimeRange - Tidsintervall - Create Account @@ -26315,16 +25570,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - Uppdatera - - - + Settings @@ -26339,7 +25585,7 @@ p, li { white-space: pre-wrap; } Andra - + Who to Follow @@ -26359,7 +25605,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -26389,85 +25635,17 @@ p, li { white-space: pre-wrap; } - Last Month - Förra månaden - - - Last Week - Förra veckan - - - Today - I dag - - - New - Nytt - - - from - Från - - - until - tills - - - Search/Filter - Sök/Filter - - - Network Wide - Nätverksövergripande - - - Manage Accounts - Hantera konton - - - Showing: - Visar: - - - + Yourself Du själv - - Friends - Kontakter - Following Följande - Custom - Anpassad - - - Account 1 - Konto 1 - - - Account 2 - Konto 2 - - - Account 3 - Konto 3 - - - CheckBox - Kryssruta - - - Post Pulse to Wire - Posta Pulse till Wire - - - + RetroShare RetroShare @@ -26530,35 +25708,42 @@ p, li { white-space: pre-wrap; } Formulär - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + Ta bort + + + Location: Plats: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -26603,11 +25788,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + N/A + + + + Following + Följande + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Okänd @@ -26685,7 +25900,7 @@ p, li { white-space: pre-wrap; } %1å %2d - + k e.g: 3.1 k k @@ -26722,7 +25937,7 @@ p, li { white-space: pre-wrap; } pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_tr.ts b/retroshare-gui/src/lang/retroshare_tr.ts index b0d731573..1163f7149 100644 --- a/retroshare-gui/src/lang/retroshare_tr.ts +++ b/retroshare-gui/src/lang/retroshare_tr.ts @@ -84,13 +84,6 @@ Yalnızca Gizli Düğüm - - AddCommentDialog - - Add Comment - Yorum Ekle - - AddFileAssociationDialog @@ -129,12 +122,12 @@ RetroShare: Gelişmiş Arama - + Search Criteria Arama Ölçütü - + Add a further search criterion. Başka bir arama ölçütü ekler. @@ -144,7 +137,7 @@ Arama ölçütlerini sıfırlar. - + Cancels the search. Aramayı iptal eder. @@ -164,177 +157,6 @@ Arama - - AlbumCreateDialog - - Create Album - Albüm Oluştur - - - Album Name: - Albüm Adı: - - - Category: - Kategori: - - - Animals - Hayvanlar - - - Family - Aile - - - Friends - Arkadaşlar - - - Flowers - Çiçekler - - - Holiday - Tatil - - - Landscapes - Manzaralar - - - Pets - Evcil hayvanlar - - - Portraits - Portreler - - - Travel - Seyahat - - - Work - İş - - - Random - Rastgele - - - Caption: - Başlık: - - - Where: - Nerede: - - - Photographer: - Fotoğrafçı: - - - Description: - Açıklama: - - - Share Options - Paylaşım Ayarları - - - Policy: - İlke: - - - Quality: - Kalite: - - - Comments: - Yorum: - - - Identity: - Kimlik: - - - Public - Genel - - - Restricted - Kısıtlanmış - - - Resize Images (< 1Mb) - Görselleri Yeniden Boyutlandır (< 1Mb) - - - Resize Images (< 10Mb) - Görselleri Yeniden Boyutlandır (< 10Mb) - - - Send Original Images - Orijinal Görselleri Gönder - - - No Comments Allowed - Yorum İzni Yok - - - Authenticated Comments - Kimliği Doğrulanmış Yorumlar - - - Any Comments Allowed - Herkes Yorum Yapabilir - - - Publish with Identity - Kimlikle Yayınla - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Görsel eklemek için Sürükleyip Bırakın. Ayrıntılarını düzenlemek istediğiniz görsele tıklayın.</span></p></body></html> - - - Back - Geri - - - Add Photos - Fotoğraf Ekle - - - Publish Album - Albümü Yayınla - - - Untitle Album - Başlıksız Albüm - - - Say something about this album... - Bu albüm hakkında birşeyler yazın... - - - Where were these taken? - Bu fotoğraflar nerede çekildi ? - - - Load Album Thumbnail - Albüm Küçük Görseli Yükle - - AlbumDialog @@ -343,19 +165,11 @@ p, li { white-space: pre-wrap; } Album Albüm - - Album Thumbnail - Albüm Küçük Görseli - TextLabel Metin Etiketi - - Summary - Özet - Album Title: @@ -371,34 +185,6 @@ p, li { white-space: pre-wrap; } Caption Başlık - - Where: - Nerede: - - - When - Ne Zaman - - - Description: - Açıklama: - - - Share Options - Paylaşım Ayarları - - - Comments - Yorumlar - - - Publish Identity - Kimliği Yayınla - - - Visibility - Görünürlük - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -767,7 +553,7 @@ p, li { white-space: pre-wrap; } RetroShare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. Uyarı: Buradaki hizmetler henüz deneme aşamasındadır. Bu hizmetleri geliştirmemize yardımcı olun. @@ -783,14 +569,6 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim Circles Çevreler - - GxsForums - GxsForumları - - - GxsChannels - GxsKanalları - The Wire @@ -802,10 +580,23 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim Fotoğraflar + + AspectRatioPixmapLabel + + + Save image + Görseli kaydet + + + + Copy image + + + AttachFileItem - + %p Kb %p Kb @@ -842,17 +633,13 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim Browse... - - Add Avatar - Avatar Ekle - Remove Sil - + Set your Avatar picture Avatar görselinizi ayarlayın @@ -871,10 +658,6 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - Avatar Yükle - AvatarWidget @@ -943,22 +726,10 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim Sıfırlayın - Receive Rate - Alma Hızı - - - Send Rate - Gönderme Hızı - - - + Always on Top Her zaman üstte - - Style - Biçem - Changes the transparency of the Bandwidth Graph @@ -974,23 +745,11 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim % Opaque % Mat - - Save - Kaydedin - - - Cancel - İptal - Since: Başlangıç: - - Hide Settings - Ayarlar Gizlensin - BandwidthStatsWidget @@ -1063,7 +822,7 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim BoardPostDisplayWidgetBase - + Comment @@ -1093,12 +852,12 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> <p><font color="#ff0000"><b>Bu iletinin yazarı (%1 kodlu) engellendi.</b> - + ago @@ -1106,7 +865,7 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim BoardPostDisplayWidget_card - + Vote up Beğendim @@ -1126,7 +885,7 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim \/ - + Posted by @@ -1164,7 +923,7 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim BoardPostDisplayWidget_compact - + Vote up Beğendim @@ -1184,7 +943,7 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim \/ - + Click to view picture @@ -1214,7 +973,7 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim Paylaş - + Toggle Message Read Status İleti Okundu Durumunu Değiştir @@ -1224,7 +983,7 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim Yeni - + TextLabel Metin Etiketi @@ -1232,12 +991,12 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim BoardsCommentsItem - + I like this Beğendim - + 0 0 @@ -1257,18 +1016,18 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim Avatar - + New Comment - + Copy RetroShare Link - + Expand Genişlet @@ -1283,12 +1042,12 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim - + Name Ad - + Comm value @@ -1457,17 +1216,17 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim ChannelPage - + Channels Kanallar - + Tabs Sekmeler - + General Genel @@ -1477,11 +1236,17 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim - Load posts in background (Thread) - İletiler artalanda yüklensin (İş Parçacığı) + + Downloads + İndirmeler - + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab Her kanal yeni bir sekmede açılsın @@ -1489,7 +1254,7 @@ Unutmayın: Buradaki herhangi bir bilgi, iletişim kurallarını güncellediğim ChannelPostDelegate - + files @@ -1512,7 +1277,7 @@ into the image, so as to ChannelsCommentsItem - + I like this Beğendim @@ -1537,18 +1302,18 @@ into the image, so as to Avatar - + New Comment - + Copy RetroShare Link - + Expand Genişlet @@ -1563,7 +1328,7 @@ into the image, so as to - + Name Ad @@ -1573,17 +1338,7 @@ into the image, so as to - - Comment - - - - - Comments - Yorumlar - - - + Hide Gizle @@ -1591,7 +1346,7 @@ into the image, so as to ChatLobbyDialog - + Name Ad @@ -1782,7 +1537,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby Sohbet Odasını Görüntüle @@ -1794,22 +1549,6 @@ into the image, so as to Chats Sohbetler - - You have %1 new messages - %1 yeni iletiniz var - - - You have %1 new message - %1 yeni iletiniz var - - - %1 new messages - %1 yeni ileti - - - %1 new message - %1 yeni ileti - You have %1 mentions @@ -1831,13 +1570,14 @@ into the image, so as to - + + Unknown Lobby Bilinmeyen Oda - - + + Remove All Tümünü Kaldır @@ -1845,13 +1585,13 @@ into the image, so as to ChatLobbyWidget - - + + Name Ad - + Count Kullanıcı Sayısı @@ -1861,33 +1601,7 @@ into the image, so as to Konu - - Private Subscribed chat rooms - Abone Olduğunuz Özel Sohbet Odaları - - - - - Public Subscribed chat rooms - Abone Olduğunuz Herkese Açık Sohbet Odaları - - - - Private chat rooms - Özel Sohbet Odaları - - - - - Public chat rooms - Herkese Açık Sohbet Odaları - - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/images/add_24x24.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Sohbet Odaları</h1> <p>Sohbet odaları merkezi olmayan sohbet yerleridir ve IRC gibi çalışır. İsimsiz kimlikle ve arkadaş olmanız gerekmeden tonlarca insanla konuşmanızı sağlar.</p> <p>Bir sohbet odası herkese açık (arkadaşlarınız görebilir) ya da özel (siz çağırmadıkça arkadaşlarınız göremez <img src=":/images/add_24x24.png" width=%2/>). Özel bir odaya çağrıldığınızda içinde arkadaşlarınızın olup olmadığını görebilirsiniz.</p> <p>Soldaki listede arkadaşlarınızın bulunduğu sohbet odalarını görebilirsiniz. Ayrıca <ul> <li>Sağ tıklayarak yeni bir sohbet odası oluşturabilirsiniz.</li> <li>Bir sohbet odasına girmek ve arkadaşlarınıza göstermek için çift tıklayın</li> </ul> Not: Sohbet odalarının bilgisayarınızda doğru şekilde çalışması için bilgisayarınızın tarih ve saati doğru olmalıdır. Bu nedenle sistem ayarlarınızı denetleyin! </p> - - - + Create chat room Sohbet odası oluştur @@ -1897,7 +1611,7 @@ into the image, so as to Bu odadan ayrılın - + Create a non anonymous identity and enter this room İsimsiz olmayan bir kimlik oluşturup bu odaya katılın @@ -1956,12 +1670,12 @@ Ayrıntıları görmek için soldan bir sohbet odası seçin. Odaya katılıp sohbet etmek için çift tıklayın. - + %1 invites you to chat room named %2 %1 sizi %2 adlı sohbet odasına çağırıyor - + Choose a non anonymous identity for this chat room: Bu sohbet odası için isimsiz olmayan bir kimlik seçin: @@ -1971,31 +1685,31 @@ Odaya katılıp sohbet etmek için çift tıklayın. Bu sohbet odası için bir kimlik seçin: - Create chat lobby - Sohbet odası oluşturun - - - + [No topic provided] [Konu belirtilmemiş] - Selected lobby info - Seçilmiş oda bilgileri - - - + + Private Özel - + + + Public Herkese Açık - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted İsimsiz kodlar kullanılabilir @@ -2005,42 +1719,25 @@ Odaya katılıp sohbet etmek için çift tıklayın. Otomatik Aboneliği Kaldır - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe Otomatik Aboneliği Ekle - + Search Chat lobbies Sohbet Odası Arama - + Search Name Ad Arama - Subscribed - Abone Olundu - - - + Columns Sütunlar - - Yes - Evet - - - No - Hayır - Chat rooms @@ -2052,47 +1749,47 @@ Odaya katılıp sohbet etmek için çift tıklayın. - + Chat Room info - + Chat room Name: Sohbet Odası Adı: - + Chat room Id: Sohbet Odası Kodu: - + Topic: Konu: - + Type: Tür: - + Security: Güvenlik: - + Peers: Eşler: - - - - - - + + + + + + TextLabel Metin Etiketi @@ -2107,13 +1804,24 @@ Odaya katılıp sohbet etmek için çift tıklayın. İsimsiz kodlar kullanılamaz - + Show Görüntüle - + + Private Subscribed + + + + + + Public Subscribed + + + + column sütun @@ -2127,7 +1835,7 @@ Odaya katılıp sohbet etmek için çift tıklayın. ChatMsgItem - + Remove Item Ögeyi Kaldır @@ -2172,46 +1880,22 @@ Odaya katılıp sohbet etmek için çift tıklayın. ChatPage - + General Genel - - Distant Chat - Uzak Sohbet - Everyone Herkes - - Contacts - Kişiler - Nobody Hiçkimse - Accept encrypted distant chat from - Şuradan şifreli uzak sohbeti kabul et - - - Chat Settings - Sohbet Ayarları - - - Enable Emoticons Private Chat - Özel Sohbette İfadeler Kullanılabilsin - - - Enable Emoticons Group Chat - Grup Sohbetinde İfadeler Kullanılabilsin - - - + Enable custom fonts Özel yazı türleri kullanılsın @@ -2220,10 +1904,6 @@ Odaya katılıp sohbet etmek için çift tıklayın. Enable custom font size Özel yazı boyutu kullanılsın - - Minimum font size - En küçük yazı boyutu - Enable bold @@ -2235,7 +1915,7 @@ Odaya katılıp sohbet etmek için çift tıklayın. Eğik yazım kullanılsın - + General settings @@ -2260,11 +1940,7 @@ Odaya katılıp sohbet etmek için çift tıklayın. Gömülü görselleri yükle - Chat Lobby - Sohbet Odası - - - + Blink tab icon Yanıp sönen sekme simgesi @@ -2273,10 +1949,6 @@ Odaya katılıp sohbet etmek için çift tıklayın. Do not send typing notifications Yazıyor bildirimleri gönderilmesin - - Private Chat - Özel Sohbet - Open Window for new chat @@ -2298,11 +1970,7 @@ Odaya katılıp sohbet etmek için çift tıklayın. Yanıp sönen pencere/sekme simgesi - Chat Font - Sohbet Yazı Türü - - - + Change Chat Font Sohbet Yazı Türünü Değiştir @@ -2312,14 +1980,10 @@ Odaya katılıp sohbet etmek için çift tıklayın. Sohbet Yazı Türü: - + History Geçmiş - - Style - Biçem - @@ -2334,17 +1998,13 @@ Odaya katılıp sohbet etmek için çift tıklayın. Variant: Çeşit: - - Group chat - Grup Sohbeti - Private chat Özel sohbet - + Choose your default font for Chat. Sohbet için varsayılan yazı türünü seçin. @@ -2408,22 +2068,28 @@ Odaya katılıp sohbet etmek için çift tıklayın. <html><head/><body><p align="justify">In this tab you can setup how many chat messages Retroshare will keep saved on the disc and how much of the previous conversation it will display, for the different chat systems. The max storage period allows to discard old messages and prevents the chat history from filling up with volatile chat (e.g. chat lobbies and distant chat).</p></body></html> <html><head/><body><p align="justify">Farklı sohbet sistemleri için RetroShare tarafından diskinizde saklanacak sohbet iletisi sayısı ve görüşme geçmişinin ne kadarını görüntüleneceği buradan ayarlanabilir. En fazla saklama süresi, eski iletilerin silinmesini ve sohbet geçmişinin geçici sohbetlerle dolmasını engeller (sohbet odaları ve uzak sohbet gibi).</p></body></html> - - Chatlobbies - Sohbet Odaları - Enabled: Etkin: - + Search Arama - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2433,7 +2099,17 @@ Odaya katılıp sohbet etmek için çift tıklayın. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms Sohbet odaları @@ -2480,7 +2156,7 @@ Odaya katılıp sohbet etmek için çift tıklayın. Description: - + Açiklama: @@ -2530,11 +2206,7 @@ Odaya katılıp sohbet etmek için çift tıklayın. En fazla saklama süresi, gün olarak (0=sınırsız): - Search by default - Varsayılan arama - - - + Case sensitive Büyük küçük harfe duyarlı @@ -2573,10 +2245,6 @@ Odaya katılıp sohbet etmek için çift tıklayın. Threshold for automatic search Otomatik arama eşiği - - Default identity for chat lobbies: - Sohbet odaları için varsayılan kimlik: - Show Bar by default @@ -2644,7 +2312,7 @@ Odaya katılıp sohbet etmek için çift tıklayın. ChatToaster - + Show Chat Sohbeti Görüntüle @@ -2680,7 +2348,7 @@ Odaya katılıp sohbet etmek için çift tıklayın. ChatWidget - + Close Kapat @@ -2715,12 +2383,12 @@ Odaya katılıp sohbet etmek için çift tıklayın. Yatık - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon Emoticon ekle @@ -2729,10 +2397,6 @@ Odaya katılıp sohbet etmek için çift tıklayın. Attach a Picture Görsel Ekle - - <html><head/><body><p>QToolButton:disabled {</p><p> image: url(:/icons/png/send-message-blocked.png) ;</p><p>}</p><p><br/></p></body></html> - <html><head/><body><p>QToolButton:disabled {</p><p> image: url(:/icons/png/send-message-blocked.png) ;</p><p>}</p><p><br/></p></body></html> - Strike @@ -2804,11 +2468,6 @@ Odaya katılıp sohbet etmek için çift tıklayın. Insert horizontal rule Yatay çizgi ekle - - - Save image - Görseli kaydet - Import sticker @@ -2846,7 +2505,7 @@ Odaya katılıp sohbet etmek için çift tıklayın. - + is typing... yazıyor... @@ -2870,7 +2529,7 @@ karakter fazla olacak. Yazı türünüzü seçin. - + Do you really want to physically delete the history? Geçmişi tamamen silmek istediğinize emin misiniz? @@ -2920,7 +2579,7 @@ karakter fazla olacak. Meşgul ve yanıtlamayabilir - + Find Case Sensitively B/K Harfe Duyarlı Arama @@ -2942,7 +2601,7 @@ karakter fazla olacak. X nesne bulunduktan sonra renklendirmeye devam edilsin (daha fazla işlemci gücü gerekir) - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> <b>Önceki </b><br/><i>Ctrl+Shift+G</i> @@ -2957,16 +2616,12 @@ karakter fazla olacak. <b>Bul </b><br/><i>Ctrl+F</i> - + (Status) (Durum) - Set text font & color - Metin yazı türü ve rengini ayarlayın - - - + Attach a File Dosya Ekle @@ -2982,12 +2637,12 @@ karakter fazla olacak. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> <b>Seçili metni işaretleyin</b><br><i>Ctrl+M</i> - + Person id: Kişi kodu: @@ -2999,12 +2654,12 @@ Double click on it to add his name on text writer. Adını yazı alanına eklemek için üstüne çift tıklayın. - + Unsigned İmzalanmamış - + items found. öge bulundu. @@ -3024,7 +2679,7 @@ Adını yazı alanına eklemek için üstüne çift tıklayın. Buraya iletinizi yazın - + Don't stop to color after Şuradan sonra renklendirme durdurulmasın @@ -3050,7 +2705,7 @@ Adını yazı alanına eklemek için üstüne çift tıklayın. CirclesDialog - + Showing details: Ayrıntılar görüntüleniyor: @@ -3072,7 +2727,7 @@ Adını yazı alanına eklemek için üstüne çift tıklayın. - + Personal Circles Kişisel Çevreler @@ -3098,7 +2753,7 @@ Adını yazı alanına eklemek için üstüne çift tıklayın. - + Friends Arkadaşlar @@ -3158,7 +2813,7 @@ Adını yazı alanına eklemek için üstüne çift tıklayın. Arkadaşların Arkadaşları - + External Circles (Admin) Dış Çevreler (Yönetici) @@ -3174,7 +2829,7 @@ Adını yazı alanına eklemek için üstüne çift tıklayın. - + Circles Çevreler @@ -3226,43 +2881,48 @@ Adını yazı alanına eklemek için üstüne çift tıklayın. - + RetroShare RetroShare - + - + Error : cannot get peer details. Hata: eş ayrıntıları alınamıyor. - + Retroshare ID - + <p>This Retroshare ID contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: + + + <b>DNS:</b> : + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3274,7 +2934,7 @@ Adını yazı alanına eklemek için üstüne çift tıklayın. Şifreleme - + Not connected Bağlı değil @@ -3356,25 +3016,17 @@ Adını yazı alanına eklemek için üstüne çift tıklayın. yok - + <p>This certificate contains: <p>Bu sertifikanın içeriği: - + <li>a <b>node ID</b> and <b>name</b> <li>bir <b>düğüm kodu</b> ve <b>ad</b> - an <b>onion address</b> and <b>port</b> - bir <b>onion adresi</b> ve <b>kapı</b> - - - an <b>IP address</b> and <b>port</b> - bir <b>IP adresi</b> ve <b>kapı</b> - - - + <p>You can use this certificate to make new friends. Send it by email, or give it hand to hand.</p> <p>Yeni arkadaşlar eklemek için bu sertifikayı kullanabilirsiniz. Sertifikayı e-posta ile gönderebilir ya da elden ele verebilirsiniz.</p> @@ -3389,7 +3041,7 @@ Adını yazı alanına eklemek için üstüne çift tıklayın. <html><head/><body><p><span style=" font-weight:600;">OpenSSL</span> tarafından kullanılan şifreleme yöntemi. Arkadaş düğümlerle kurulan bağlantı</p><p> her zaman yoğun bir şekilde şifrelenir ve DHE varsa bağlantı </p><p>&quot;mükemmel bir yönlendirme gizliliğine&quot;.</p> sahiptir</body></html> - + with ile @@ -3406,118 +3058,16 @@ Adını yazı alanına eklemek için üstüne çift tıklayın. Connect Friend Wizard Arkadaş Bağlantı Yardımcısı - - Add a new Friend - Yeni Arkadaş Ekle - - - &You get a certificate file from your friend - &Arkadaşınızdan bir sertifika dosyası aldıysanız - - - &Make friend with selected friends of my friends - &Arkadaşlarınızın seçtiği kişilerle arkadaş olun - - - &Send an Invitation by Email - (Your friend will receive an email with instructions how to download RetroShare) - &Eposta yoluyla Davetiye gönderin -(Arkadaşınıza RetroShare indirme bilgilerini içeren bir e-posta gönderilir) - - - Include signatures - İmzalar katılsın - - - Copy your Cert to Clipboard - Sertifikanızı panoya kopyalayın - - - Save your Cert into a File - Sertifikanızı bir dosyaya kaydedin - - - Run Email program - E-posta programını çalıştırın - Open Cert of your friend from File Dosyadan arkadaşınızın Sertifikasını yükleyin - - Open certificate - Sertifika yükleyin - - - Please, paste your friend's Retroshare certificate into the box below - Lütfen, arkadaşınızın RetroShare sertifikasını alttaki kutuya yapıştırın - - - Certificate files - Sertifika dosyaları - - - Use PGP certificates saved in files. - Dosyalarda kayıtlı PGP sertifikaları kullanılır. - - - Import friend's certificate... - Arkadaşınız sertifikasını içe aktarın... - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - Sertifikanızın olduğu bir dosya üretip bunu arkadaşınıza ulaştırmalısınız. İsterseniz önceden oluşturulmuş bir dosyayı da kullanabilirsiniz. - - - Export my certificate... - Sertifikamı dışa aktar... - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - Arkadaşınızın sertifikasını sürükleyip bu pencereye bırakın ya da alttaki kutudan dosya yolunu seçin - - - Browse - Gözat - - - Friends of friends - Arkadaşların arkadaşları - - - Select now who you want to make friends with. - Şimdi kiminle arkadaş olmak istediğinizi seçin. - - - Show me: - Göster: - - - Make friend with these peers - Bu eşlerle arkadaş olun - RetroShare ID RetroShare Kodu - - Use RetroShare ID for adding a Friend which is available in your network. - İletişim ağınızdaki bir arkadaşınızı eklemek için, RetroShare Kodunu kullanın. - - - Add Friends RetroShare ID... - Arkadaşınızın RetroShare Kodunu Ekleyin... - - - Paste Friends RetroShare ID in the box below - Arkadaşınızın RetroShare Kodunu alttaki kutuya yapıştırın - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - Arkadaşınızın RetroShare Kodunu yazın, Eş@BDE8D16A46D938CF gibi - RetroShare is better with Friends @@ -3559,27 +3109,7 @@ Adını yazı alanına eklemek için üstüne çift tıklayın. E-posta - Invite Friends by Email - Arkadaşlarınızı e-posta ile çağırın - - - Enter your friends' email addresses (separate each one with a semicolon) - Arkadaşlarınızın e-posta adreslerini yazın (adresleri noktalı virgül ile ayırın) - - - Your friends' email addresses: - Arkadaşlarınızın e-posta adresleri: - - - Enter Friends Email addresses - Arkadaşlarınızın E-posta adreslerini yazın - - - Subject: - Konu: - - - + @@ -3595,77 +3125,32 @@ Adını yazı alanına eklemek için üstüne çift tıklayın. İstek hakkında ayrıntılar - + Peer details Eş bilgileri - + Name: Ad: - - Email: - E-posta: - - - Node: - Düğüm: - - - Please note that RetroShare will require excessive amounts of bandwidth, memory and CPU if you add too many friends. You can add as many friends as you like, but more than 40 will probably require too much -resources. - Lütfen unutmayın, çok fazla arkadaş eklerseniz, RetroShare aşırı miktarda bant genişliğine, belleğe ve işlemci gücüne gerek duyar. İstediğiniz kadar ekleyebilirsiniz, ama 40 arkadaştan fazlası çok fazla kaynağa gerek duyabilir. - Location: Konum: - + Options Ayarlar - This wizard will help you to connect to your friend(s) to RetroShare network.<br>Select how you would like to add a friend: - Bu yardımcı RetroShare ağındaki arkadaşlarınızla bağlantı kurmanızı sağlar. <br>Arkadaşlarınızı nasıl eklemek istediğinizi seçin: - - - Enter the certificate manually - Sertifikayı el ile yazın - - - Enter RetroShare ID manually - RetroShare kodunu el ile yazın - - - &Send an Invitation by Web Mail Providers - Web Posta Hizmeti &Sunucuları Üzerinden bir Çağrı Gönderin - - - Recommend many friends to each other - Arkadaşlarınızı diğerlerine önerin - - - RetroShare certificate - RetroShare sertifikası - - - Please paste below your friend's Retroshare certificate - Lütfen, arkadaşınızın RetroShare sertifikasını aşağıya yapıştırın - - - Paste certificate - Sertifikayı yapıştırın - - - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> <html><head/><body><p>Arkadaşınızın RetroShare sertifikasını bu kutuya yapıştırın. UYARI: bu sertifika arkadaşınızın profil anahtarından farklıdır. Arkadaşınızın profil anahtarını (bir bölümünü bile) buraya yapıştırmayın, çalışmaz.</p></body></html> - + Add friend to group: Gruba arkadaş ekleyin: @@ -3675,7 +3160,7 @@ resources. Arkadaşı doğrulayın (PGP anahtarını imzalayın) - + Please paste below your friend's Retroshare ID @@ -3700,16 +3185,22 @@ resources. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with Bağlantı kurulacak arkadaş olarak ekleyin - To accept the Friend Request, click the Finish button. - Arkadaşlık isteğini kabul etmek için Tamam üzerine tıklayın. - - - + Sorry, some error appeared Maalesef, bir sorun çıktı @@ -3729,32 +3220,27 @@ resources. Arkadaşınızın bilgileri: - + Key validity: Anahtar geçerliliği: - + Profile ID: - - Signers - İmzalayanlar - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Bir arkadaşınızın anahtarını imzaladığınızda, diğer arkadaşlarınıza bu arkadaşınıza güvendiğinizi gösterirsiniz. Aşağıdaki imzalar, listelenmiş anahtar sahiplerinin geçerli PGP anahtarını özgün olarak tanındığını şifreli olarak ispatlar.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. Bu eş zaten arkadaş listenizde. Eklerseniz yalnız IP adresi değişebilir. - + To accept the Friend Request, click the Accept button. @@ -3800,49 +3286,17 @@ resources. - + Certificate Load Failed Sertifika Yüklenemedi - Cannot get peer details of PGP key %1 - PGP anahtarı %1 olan eş bilgileri alınamıyor - - - Any peer I've not signed - İmzalamadığım eşler - - - Friends of my friends who already trust me - Bana güvenmiş olan arkadaşlarımın arkadaşları - - - Signed peers showing as denied - Reddedilmiş görünen imzalanmış eşler - - - Peer name - Eş adı - - - Also signed by - Ayrıca imzalayan - - - Peer id - Eş Kodu - - - Certificate appears to be valid - Sertifika geçerli görünüyor - - - + Not a valid Retroshare certificate! Geçerli bir Retroshare sertifikası değil! - + RetroShare Invitation RetroShare Çağrısı @@ -3864,12 +3318,12 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? Bu sizin kendi sertifikanız! Kendi kendinizle arakadaş olmak istemezsiniz. Değil mi? - + @@ -3877,7 +3331,7 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. - + This key is already on your trusted list Bu anahtar zaten güvenilir listenizde @@ -3917,7 +3371,7 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. Şu kişi arkadaşlık isteğinde bulundu - + Profile password needed. @@ -3942,7 +3396,7 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. - + Valid Retroshare ID @@ -3952,47 +3406,7 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. - Certificate Load Failed:file %1 not found - Sertifika yüklenemedi: %1 dosyası bulunamadı - - - This Peer %1 is not available in your Network - %1 eşi ağınızda bulunamadı - - - Use new certificate format (safer, more robust) - Yeni sertifika biçimi kullanılsın (güvenli, daha sağlam) - - - Use old (backward compatible) certificate format - Eski sertifika biçimi kullanılsın (geriye dönük uyumlu) - - - Remove signatures - İmzaları kaldır - - - RetroShare Invite - RetroShare Çağrı - - - Connect Friend Help - Arkadaş Bağlantısı Yardımı - - - You can copy this text and send it to your friend via email or some other way - Bu metni kopyalayarak e-posta ya da başka bir şekilde arkadaşınıza yollayabilirsiniz - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Sertifikanız Panoya kopyalandı, e-postanıza yapıştırarak ya da başka bir şekilde arkadaşınıza iletebilirsiniz - - - Save as... - Farklı Kaydet... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -4031,11 +3445,7 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. *** Yok *** - Use as direct source, when available - Olabildiğinde doğrudan kaynak olarak kullanılsın - - - + IP-Addr: IP Adresi: @@ -4045,7 +3455,7 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. IP Adresi - + Show Advanced options Gelişmiş ayarları görüntüle @@ -4054,10 +3464,6 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">Bir arkadaşınızın anahtarını imzaladığınızda, diğer arkadaşlarınıza bu arkadaşınıza güvendiğinizi gösterirsiniz. Böylece arkadaşlarınız bu anahtara güvenme durumunuza göre bağlantıları onaylamaya karar verebilir. Anahtar imzalama işlemi isteğe bağlıdır ancak geri alınamaz. Bu nedenle ne yaptığınızdan emin olun.</span></p></body></html> - - <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> - <html><head/><body><p align="justify">RetroShare , doğrudan aktarım yapabilmeniz için düzenli aralıklarla, aktarımlarınızla eşleşen görülebilir dosyalar için arkadaş listenizi kontrol eder. Bu durumda, arkadaşınız dosyayı indirdiğinizi bilebilir.</p><p align="justify">Bu işlemi yalnızca bu arkadaşınız için engellemek istiyorsanız, kutudaki işareti kaldırın. İsterseniz hala açıkca sorarak doğrudan aktarım yapabilirsiniz, Örneğin arkadaşınızın dosya listesinden indirebilirsiniz. Bu ayar aynı düğümdeki tüm konumlara uygulanır.</p></body></html> - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> @@ -4068,45 +3474,13 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. <html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> <html><head/><body><p>Bu seçeneği kullanan eşlerin bağlantı adresleri beyaz listede değilse bağlanamazlar. Böylece trafik yönlendirme saldırılarından korunursunuz. Bu seçenek kullanıldığında, reddedilen eşler, Haber Kaynağı &quot;güvenlik akışı ögeleri&quot; bölümünde bildirilir. O bölümden IP adreslerini kara ya da beyaz listeye ekleyebilirsiniz. Aynı düğümdeki tüm konumlara uygulanır.</p></body></html> - - Recommend many friends to each others - Arkadaşlarınızı birbirine önerin - - - Friend Recommendations - Arkadaş Önerileri - - - The text below is your Retroshare certificate. You have to provide it to your friend - Aşağıda RetroShare sertifikanızı görebilirsiniz. Bu metni arkadaşınıza iletmelisiniz - - - Message: - İleti: - - - Recommend friends - Arkadaş önerin - - - To - Kime - - - Please select at least one friend for recommendation. - Önerilecek en az bir arkadaşınızı seçin. - - - Please select at least one friend as recipient. - Lütfen arkadaşlarınızdan en az birini alıcı olarak seçin. - Add key to keyring Anahtarı, anahtarlığa ekle - + This key is already in your keyring Bu anahtar zaten anahtarlığınızda bulunuyor @@ -4122,7 +3496,7 @@ uzak iletiler göndermek için kullanılabilir. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. Sertifikanın sürüm numarası hatalı. v0.6 ve v0.5 ağlarının birbiriyle uyumlu olmadığını unutmayın. @@ -4157,7 +3531,7 @@ kullanılabilir. IP adresini beyaz listeye ekle - + No IP in this certificate! Bu sertifikada bir IP adresi yok! @@ -4167,27 +3541,10 @@ kullanılabilir. <p>Bu sertifikada bir IP adresi yok. IP adresini bulmak için keşif ve DHT özelliğine güvenmelisiniz. Beyaz listeye eklenme zorunlu olsun seçeneğini etkinleştirdiğiniz için Haber Akışı sekmesinde eşle ilgili bir güvenlik uyarısı görüntülenecek. Oraya bakarak eşin IP adresini beyaz listeye alabilirsiniz.</p> - - [Unknown] - [Bilinmiyor] - - - + Added with certificate from %1 Sertifikasıyla birlikte %1 üzerinden eklendi - - Paste Cert of your friend from Clipboard - Panodan arkadaşınızın Sertifikasını yapıştırın - - - Certificate Load Failed:can't read from file %1 - Sertifika Yüklenemedi: %1 dosyası okunamıyor - - - Certificate Load Failed:something is wrong with %1 - Sertifika Yüklenemedi: %1 dosyasında bir şeyler yanlış - ConnectProgressDialog @@ -4249,7 +3606,7 @@ kullanılabilir. - + UDP Setup UDP Kurulumu @@ -4285,7 +3642,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:13pt;">kapatabilirsiniz.</span></p></body></html> - + Connection Assistant Bağlantı Yardımcısı @@ -4295,17 +3652,20 @@ p, li { white-space: pre-wrap; } Eş Kodu Geçersiz - + + Unknown State Durum Bilinmiyor - + + Offline Çevrimdisi - + + Behind Symmetric NAT Simetrik NAT Arkasında @@ -4315,12 +3675,14 @@ p, li { white-space: pre-wrap; } NAT Arkasında ve DHT Yok - + + NET Restart Ağı Yeniden Başlat - + + Behind NAT NAT Arkasında @@ -4330,7 +3692,8 @@ p, li { white-space: pre-wrap; } DHT Yok - + + NET STATE GOOD! AĞ DURUMU İYİ! @@ -4355,7 +3718,7 @@ p, li { white-space: pre-wrap; } RetroShare Eşleri Bulunuyor - + Lookup requires DHT Arama için DHT gerekli @@ -4647,7 +4010,7 @@ p, li { white-space: pre-wrap; } Lütfen yeniden tam Sertifikayı içe aktarmayı deneyin - + @@ -4655,7 +4018,8 @@ p, li { white-space: pre-wrap; } Kullanılamıyor - + + UNVERIFIABLE FORWARD! YÖNLENDİRME DOĞRULANAMIYOR! @@ -4665,7 +4029,7 @@ p, li { white-space: pre-wrap; } YÖNLENDİRME DOĞRULANAMIYOR ve DHT YOK - + Searching Aranıyor @@ -4701,12 +4065,12 @@ p, li { white-space: pre-wrap; } Çevre Ayrıntıları - + Name Ad - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> <html><head/><body><p>Tüm çağrılan üyeler, çevre adını, ilgili yöneticiyi ve çağrılan üye listesini görebilir. Çevre özel değil ise bu bilgiler çağrılan üyelerin düğümlerine komşu düğümler tarafından da görülebilir.</p></body></html> @@ -4726,7 +4090,7 @@ p, li { white-space: pre-wrap; } - + IDs Kodlar @@ -4746,18 +4110,18 @@ p, li { white-space: pre-wrap; } Süzgeç - + Cancel - + Nickname Takma Ad - + Invited Members Çağrılmış Üyeler @@ -4772,15 +4136,7 @@ p, li { white-space: pre-wrap; } Bilinen Kişiler - ID - Kod - - - Type - Tür - - - + Name: Ad: @@ -4820,23 +4176,19 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Çevreler başka bir çevrenin üyeleriyle kısıtlanabilir. Yalnız bu ikinci çevredeki kişiler yeni çevreyi ve içeriğini (üye listesi, vb) görebilir.</p></body></html> - Only visible to members of: - Yalnız şu çevrenin üyelerine görüntülensin: - - - - + + RetroShare RetroShare - + Please set a name for your Circle Lütfen Çevrenize bir ad verin - + No Restriction Circle Selected Herhangi Bir Sınırlama Çevresi Seçilmemiş @@ -4846,12 +4198,24 @@ p, li { white-space: pre-wrap; } Herhangi Bir Çevre Sınırlaması Seçilmemiş - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] [Bilinmiyor] - + Add Ekle @@ -4861,7 +4225,7 @@ p, li { white-space: pre-wrap; } Sil - + Search Arama @@ -4876,10 +4240,6 @@ p, li { white-space: pre-wrap; } Signed İmzalanmış - - Signed by known nodes - Bilinen düğümler tarafından imzalanmış - Edit Circle @@ -4896,10 +4256,6 @@ p, li { white-space: pre-wrap; } PGP Identity PGP Kodu - - Anon Id - İsimsiz Kod - Circle name @@ -4922,17 +4278,13 @@ p, li { white-space: pre-wrap; } Yeni Çevre Ekle - + Create Ekle - PGP Linked Id - PGP Bağlantılı Kod - - - + Add Member Üye Ekle @@ -4951,7 +4303,7 @@ p, li { white-space: pre-wrap; } Grup Ekle - + Group Name: Grup Adı: @@ -4986,7 +4338,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post Yeni Kanal İletisi @@ -4996,7 +4348,7 @@ p, li { white-space: pre-wrap; } Kanal İletisi - + Post @@ -5057,23 +4409,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Yeni dosyaları karmak için, Sürükle Bırak ya da Dosya Ekleme düğmelerini kullanın.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Paylaştığınız bölümlerden RetroShare bağlantılarını Kopyalayıp Yapıştırın</span></p></body></html> - - Add File to Attach - Dosya Ekle - Add Channel Thumbnail Kanal Küçük Görseli Ekle - - Message - İleti - - - Subject : - Konu: - @@ -5159,17 +4499,17 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -5188,17 +4528,18 @@ p, li { white-space: pre-wrap; } The following files will only be shared for 30 days. Think about adding them to a shared directory. - - File already Added and Hashed - Dosya Zaten Eklenmiş ve Karılmış - Please add a Subject Lütfen bir konu ekleyin - + + Cannot publish post + + + + Load thumbnail picture Küçük Görsel Yükle @@ -5213,18 +4554,12 @@ p, li { white-space: pre-wrap; } Gizle - - + Generate mass data Toplu veri üret - - Do you really want to generate %1 messages ? - Gerçekten %1 ileti oluşturmak istiyor musunuz? - - - + You are about to add files you're not actually sharing. Do you still want this to happen? Gerçekte paylaşmadığınız dosyaları eklemek istediğinize emin misiniz? @@ -5258,7 +4593,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message Forum İletisi Gönder @@ -5267,10 +4602,6 @@ p, li { white-space: pre-wrap; } Forum Forum - - Subject - Konu - Attach File @@ -5291,8 +4622,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -5311,7 +4642,7 @@ p, li { white-space: pre-wrap; } Eklemek istediğiniz dosyaları sürükleyip bu pencereye bırakabilirsiniz - + Post @@ -5341,17 +4672,17 @@ p, li { white-space: pre-wrap; } - + No Forum Forum Yok - + In Reply to Şuna Yanıt - + Title Başlık @@ -5405,7 +4736,7 @@ Bu iletiyi silmek istiyor musunuz? Görsel Dosyası Yükle - + No compatible ID for this forum Bu forum için uyumlu bir kod bulunamadı @@ -5415,8 +4746,8 @@ Bu iletiyi silmek istiyor musunuz? Kimliklerinizin hiç biri bu foruma ileti göndermenize izin vermiyor. Bu durum forum kimliklerinizin hiç birini içermeyen bir çevre ile kısıtlanmış olduğundan ya da forum özellikleri PGP imzalı bir kimlik zorunlu olacak şekilde ayarlanmış olduğundan olabilir. - - + + Generate mass data Toplu veri üret @@ -5425,10 +4756,6 @@ Bu iletiyi silmek istiyor musunuz? Do you really want to generate %1 messages ? Gerçekten %1 ileti üretmek istiyor musunuz? - - Send - Gönder - Post as @@ -5443,23 +4770,7 @@ Bu iletiyi silmek istiyor musunuz? CreateLobbyDialog - Create Chat Lobby - Sohbet Odası Oluştur - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - Sohbet odası merkezi olmayan, isimsiz bir sohbet grubudur. Tüm katılımcılar tüm iletileri alabilir. Odayı oluşturduktan sonra Arkadaşlar sekmesinden diğer arkadaşlarınızı çağırabilirsiniz. - - - Lobby name: - Oda Adı: - - - Lobby topic: - Oda Konusu: - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5494,7 +4805,7 @@ Bu iletiyi silmek istiyor musunuz? - + Create Ekle @@ -5504,11 +4815,7 @@ Bu iletiyi silmek istiyor musunuz? - <html><head/><body><p>If you check this, only PGP-signed ids can be used to join and talk in this lobby. This limitation prevents anonymous spamming as it becomes possible for at least some people in the lobby to locate the spammer's node.</p></body></html> - <html><head/><body><p>Bu seçenek işaretlendiğinde bu odaya yalnız PGP imzalı kodlar katılıp konuşabilir. Bu sınırlama sonucunda en azından odadaki bazı kişiler spam gönderenin düğümünü tespit edebileceğinden isimsiz spam gönderenler engellenir.</p></body></html> - - - + require PGP-signed identities PGP imzalı kimlikler zorunlu olsun @@ -5523,11 +4830,7 @@ Bu iletiyi silmek istiyor musunuz? Grup sohbeti yapmak istediğiniz Arkadaşlarınızı seçin. - Invited friends - Çağrılan Arkadaşlar - - - + Create Chat Room Sohbet Odası Ekle @@ -5548,7 +4851,7 @@ Bu iletiyi silmek istiyor musunuz? İlgililer: - + Identity to use: Kullanılacak kimlik: @@ -5556,17 +4859,17 @@ Bu iletiyi silmek istiyor musunuz? CryptoPage - + Public Information Herkese Açık Bilgiler - + Name: Ad: - + Location: Konum: @@ -5576,12 +4879,12 @@ Bu iletiyi silmek istiyor musunuz? Konum Kodu: - + Software Version: Yazılım Sürümü: - + Online since: Çevrimiçi süresi: @@ -5601,12 +4904,7 @@ Bu iletiyi silmek istiyor musunuz? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5616,7 +4914,7 @@ Bu iletiyi silmek istiyor musunuz? - + Other Information Diğer Bilgiler @@ -5626,17 +4924,12 @@ Bu iletiyi silmek istiyor musunuz? - + Profile - - Certificate - Sertifika - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5646,11 +4939,7 @@ Bu iletiyi silmek istiyor musunuz? İmzalar katılsın - Save Key into a file - Anahtarı dosyaya kaydet - - - + Export Identity Kimliği Dışa Aktar @@ -5724,33 +5013,33 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz - + TextLabel Metin Etiketi - + PGP fingerprint: PGP Parmak İzi: - - Node information - Düğüm Bilgileri - - - + PGP Id : PGP Kodu : - + Friend nodes: Arkadaş Düğümleriniz: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5789,14 +5078,6 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz Node Düğüm - - Create new node... - Yeni düğüm ekle... - - - show statistics window - istatistik penceresini görüntüle - DHTGraphSource @@ -5813,10 +5094,6 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz DHT DHT - - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your friends to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your friends.</p> - <p>RetroShare bağlantılarda vekil sunucu olarak Bittorrent DHT özelliğini kullanır. IP adresiniz DHT üzerinde "kaydedilmez". Bunun yerine DHT, standart DHT istekleri işlenirken arkadaşlarınızın size ulaşması için kullanılır. RetroShare arkadaşlarınızın birinden bir DHT yanıtı aldığında durum simgesi yeşile döner.</p> - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your trusted nodes to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your trusted nodes.</p> @@ -5852,7 +5129,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz DLListDelegate - + B B @@ -6520,7 +5797,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz DownloadToaster - + Start file Dosyayı başlat @@ -6528,38 +5805,38 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz ExprParamElement - + - + to hedef - + ignore case büyük küçük harf önemsiz - - - dd.MM.yyyy - gg.AA.yyyy + + + yyyy-MM-dd + - - + + KB KB - - + + MB MB - - + + GB GB @@ -6567,12 +5844,12 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz ExpressionWidget - + Expression Widget İfade Gereci - + Delete this expression Bu ifadeyi sil @@ -6734,7 +6011,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz FilesDefs - + Picture Görsel @@ -6744,7 +6021,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz Görüntü - + Audio Ses @@ -6804,11 +6081,21 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories Arkadaş Klasörleri @@ -6930,7 +6217,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz - + ID Kod @@ -6965,10 +6252,6 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz Show State Durum Görüntülensin - - Trusted nodes - Güvenilen düğümler - @@ -6976,7 +6259,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz Gruplar Görüntülensin - + Group Grup @@ -7012,7 +6295,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz Gruba ekle - + Search Arama @@ -7028,7 +6311,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz Duruma göre sırala - + Profile details Profil bilgileri @@ -7272,7 +6555,7 @@ en az bir eş bir gruba eklenemedi FriendRequestToaster - + Confirm Friend Request Arkadaşlık İsteğini Onayla @@ -7289,10 +6572,6 @@ en az bir eş bir gruba eklenemedi FriendSelectionWidget - - Search : - Arama : - Sort by state @@ -7314,7 +6593,7 @@ en az bir eş bir gruba eklenemedi Arkadaş Arama - + Mark all Tümünü işaretle @@ -7325,16 +6604,134 @@ en az bir eş bir gruba eklenemedi Tümünün işaretini kaldır + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + Ad + + + + Node ID + + + + + Address + + + + + Status + Durum + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + Arkadaş ol + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + Vekil sunucu etkinleştirilmemiş ya da bozuk. +Tüm hizmetler düzgün çalışıyor mu?? +Ayrıca kapı ayarlarınızı da denetleyin! + + FriendsDialog - + Edit status message Durum iletisini düzenle - - + + Broadcast Yayınla @@ -7417,33 +6814,38 @@ en az bir eş bir gruba eklenemedi Yazı türünü varsayılana çevir - + Keyring Anahtarlık - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Ağ</h1> <p>Ağ sekmesi arkadaşınız olan RetroShare düğümlerini: yani size bağlı olan komşu RetroShare düğümlerini görüntüler.</p> <p>Bilgiye daha iyi erişim sağlamak için düğümleri gruplandırabilirsiniz. Örneğin yalnızca bazı düğümlerin belirli dosyalarınıza erişmesine izin verebilirsiniz.</p> <p>Sağ tarafta, 3 adet kullanışlı sekme bulacaksınız:<ul> <li>Yayın; bağlı olduğunuz tüm düğümlere aynı anda ileti gönderir</li> <li>Yerel ağ çizelgesi; keşif bilgilerine bağlı olarak, etrafınızdaki ağı görüntüler</li> <li>Anahtarlık; genellikle arkadaşlarınız tarafından size yönlendirilmiş, biriktirdiğiniz düğüm anahtarlarını bulundurur.</li> </ul> </p> - - - + Retroshare broadcast chat: messages are sent to all connected friends. RetroShare sohbeti yayını: iletiler bağlı olan tüm arkadaşlara gönderilir. - - + + Network - + + Friend Server + + + + Network graph Ağ çizelgesi - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. Durum iletinizi buraya yazın. @@ -7461,7 +6863,17 @@ en az bir eş bir gruba eklenemedi Parola - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters Tüm alanlara en az 3 karakter yazılmalıdır @@ -7471,17 +6883,12 @@ en az bir eş bir gruba eklenemedi Parola ve onayı aynı değil - + Port Kapı - - Use BOB - BOB kullan - - - + This password is for PGP Bu parola PGP için @@ -7502,50 +6909,38 @@ en az bir eş bir gruba eklenemedi Yeni sertifikanız üretilemedi. PGP parolası yanlış olabilir! - Options - Ayarlar - - - + PGP Key Length PGP Anahtar Uzunluğu - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> <html><head/><body><p>Buraya güçlü bir parola yazın. Bu parola kişisel düğüm anahtarınızı korumak için kullanılacak!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> <html><head/><body><p>Lütfen olabildiğince fazla rastlantısallık oluşturmak için, farenizi ekranda gezdirin. Düğüm anahtarlarını oluşturmak için yüzde değeri en az %20 olmalıdır.</p></body></html> - + Standard node Standart düğüm - TOR/I2P Hidden node - TOR/I2P Gizli Düğüm - - - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> <html><head/><body><p>Düğüm adınız bu bilgisayarda çalışacak olan RetroShare kopyasını</p><p>belirlemek için kullanılır.</p></body></html> - Use existing profile - Varolan profili kullan - - - + Node name Düğüm adı - + Node type: @@ -7565,12 +6960,12 @@ en az bir eş bir gruba eklenemedi - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> <html><head/><body><p>Profil adı sizi ağda tanımlamak için kullanılır.</p><p>Arkadaşlarınızın sizden gelen bağlantıları onaylamasını sağlar.</p><p>Aynı profili kullanarak farklı bilgisayarlar üzerinde </p><p>birden çok RetroShare düğümü oluşturabilirsiniz.</p><p><br/></p></body></html> - + Export this profle Bu profili dışa aktar @@ -7580,42 +6975,43 @@ en az bir eş bir gruba eklenemedi - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> <html><head/><body><p>Bu değer şu formda bir Tor Onion adresi olmalıdır: xa76giaf6ifda7ri63i263.onion <br/>ya da şu formda bir I2P adresi olmalıdır: [52 karakter].b32.i2p </p><p>Bir adres edinmek için Tor ya da I2P uygulamasını yeni bir gizli hizmet / sunucu tüneli oluşturacak şekilde yapılandırmalısınız. </p><p>Bu değeri şu anda boş bırakabilirsiniz ancak düğümünüz yalnız Ayarlar-&gt;Ağ-&gt;Gizli Hizmet yapılandırma bölümünden Tor/I2P hizmet adresini doğru olarak ayarlamışsanız çalışır.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> <html><head/><body><p>Kimlikler, sohbet odalarında, forumlarda ve kanal yorumlarında yazışırken kullanılır. </p><p>Kimlikler ayrıca RetroShare ağı üzerinden e-posta alıp gönderebilir. İmzalanmış bir kimliği</p><p>şimdi oluşturabileceğiniz gibi daha sonra gerek duyduğunuz zaman da oluşturabilirsiniz.</p></body></html> - + Go! Git! - - + + TextLabel Metin Etiketi - Advanced options - Gelişmiş Ayarlar - - - + hidden address gizli adres - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. Profiliniz bir PGP anahtar çiftiyle ilişkilendirildi. RetroShare şu anda DSA anahtarlarını yok sayıyor. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> <html><head/><body><p>Bağlantı kapınız.</p><p>1024 ile 65535 arasındaki herhangi bir değer</p><p>kullanılabilir. Bu değer daha sonra değiştirilebilir.</p></body></html> @@ -7663,13 +7059,13 @@ ve İçe Aktar düğmesini kullanarak yükleyebilirsiniz Profiliniz kaydedilemedi. Bir sorun çıktı. - + Import profile Profili içe aktar - + Create new profile and new Retroshare node Yeni profil ve yeni bir RetroShare düğümü oluştur @@ -7679,7 +7075,7 @@ ve İçe Aktar düğmesini kullanarak yükleyebilirsiniz Yeni bir RetroShare düğümü oluştur - + Tor/I2P address Tor/I2P adresi @@ -7714,7 +7110,7 @@ ve İçe Aktar düğmesini kullanarak yükleyebilirsiniz - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7724,12 +7120,7 @@ ve İçe Aktar düğmesini kullanarak yükleyebilirsiniz - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> <p>Tüm alanlar geçerli olana kadar düğüm oluşturamazsınız.</p> @@ -7739,12 +7130,7 @@ ve İçe Aktar düğmesini kullanarak yükleyebilirsiniz <p>Yeteri kadar rasgelelik elde edilene kadar düğüm oluşturamazsınız. En az %20'ye ulaşana kadar, lütfen farenizi oynatmaya devam edin.</p> - - I2P instance address with BOB enabled - BOB özelliği aktif I2P adres örneği - - - + I2P instance address I2P adres örneği @@ -7970,36 +7356,13 @@ ve İçe Aktar düğmesini kullanarak yükleyebilirsiniz Buradan Başlayın - + Invite Friends Arkadaşlarınızı Çağırın - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Arkadaşlarınız olmadan RetroShare bir hiçtir. Çağırma işlemini başlatmak için düğmeye tıklayın.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Arkadaşlarınızı &quot;Kimlik sertifikanız&quot; ile çağırın.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Arkadaşlarınızın çağrınızı aldıklarından emin olun... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Arkadaşlarınızı ekleyebilmeniz için hem siz hem de arkadaşınız birbirinizi eklemelisiniz.</span></p></body></html> - - - + Add Your Friends to RetroShare Arkadaşlarınızı RetroShare Üzerine Ekleyin @@ -8009,124 +7372,103 @@ p, li { white-space: pre-wrap; } Arkadaşlarınızı Ekleyin - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Arkadaşlarınızla aynı anda çevrimiçi olduğunuzda RetroShare sizi otomatik olarak bağlar!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">İstemcinizin bağlantılar kurabilmesi için önce RetroShare ağını bulması gerekir.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Bu işlem RetroShare ilk kez başlatıldığında 5-30 dakika arasında sürer.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Bağlantılar kurulduğunda DHT göstergesi (Durum Çubuğunda) yeşile döner.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Bir kaç dakika sonra NAT göstergesi (gene Durum Çubuğunda) sarı ya da yeşile döner.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Gösterge kırmızı kalırsa RetroShare bağlantısının kurulmasında zorluk çıkaran bir Güvenlik Duvarı var demektir.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Bu durumda bağlantı kurmakla ilgili ayrıntılı bilgi almak için ilgili yardım bölümüne bakın.</span></p></body></html> + + Connect To Friends + Arkadaşlarınıza Bağlanın - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare başarımını arttırmak için bir Dış Kapı açabilirsiniz. </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Böylece bağlantı kurmayı hızlandırarak daha çok kişinin sizinle bağlantı kurmasını sağlayabilirsiniz. </span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Bunu yapmanın en kolay yolu İnternet bağlantısı için kullandığınız modem üzerinde UPnP özelliğini etkinleştirmektir.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Ayarlar her modem için farklı olduğundan, İnternet üzerinde modem modelinize göre arama yaparak ayarları nasıl yapacağınızı öğrenebilirsiniz.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Bu bilgilerin sizin için bir anlamı yoksa dert etmeyin. RetroShare gene de çalışacaktır.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + Gelişmiş: Güvenlik Duvarında Kapı Açın <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare uygulamasını başlatmakta sorun mu yaşıyorsunuz?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) SSS Wiki sayfasına bakın. Buradaki bilgiler biraz eskidi, ancak güncel tutmaya çalışıyoruz..</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Çevrimiçi Forumlara bakın. Soru sorun ve özellikleri tartışın.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) RetroShare İçi Forumları deneyin </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - Bunlar arkadaşlarınıza bağlandığınızda çevrimiçi olur.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) Hala sorun yaşıyorsanız bize e-posta gönderin.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare kullanmanın tadını çıkarın.</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> + - - Connect To Friends - Arkadaşlarınıza Bağlanın - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Arkadaşlarınız size çağrı gönderdiğinde, Arkadaş Ekleme penceresini açmak için tıklayın.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Eklemek istediğiniz arkadaşınızın Kod Sertifikasını pencereye yapıştırın.</span></p></body></html> - - - - Advanced: Open Firewall Port - Gelişmiş: Güvenlik Duvarında Kapı Açın - - - + Further Help and Support Ayrıntılı Yardım ve Destek Alın - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website RetroShare Web Sitesini Açın @@ -8151,7 +7493,7 @@ p, li { white-space: pre-wrap; } E-posta Geri Bildirimi - + RetroShare Invitation RetroShare Çağrısı @@ -8201,12 +7543,12 @@ p, li { white-space: pre-wrap; } RestroShare Geri Bildirimi - + RetroShare Support RetroShare Desteği - + It has many features, including built-in chat, messaging, Canlı sohbet, ileti gönderme gibi pek çok özellik vardır, @@ -8330,7 +7672,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat Grup Sohbetini Görüntüle @@ -8338,7 +7680,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] [Bilinmiyor] @@ -8504,19 +7846,11 @@ p, li { white-space: pre-wrap; } You can let your friends know about your forum by sharing it with them. Select the friends with which you want to share your forum. Paylaşarak arkadaşlarınıza forumunuzu duyurabilirsiniz. Forumunuzu paylaşmak istediğiniz arkadaşlarınızı seçin. - - Share topic admin permissions - Konu yönetici izinlerini paylaş - - - You can allow your friends to edit the topic. Select them in the list below. Note: it is not possible to revoke Posted admin permissions. - Arkadaşlarınıza konuyu düzenleme izni verebilirsiniz. Aşağıdaki listeden arkadaşlarınızı seçin. Not: verilen yönetici izinlerinin geri alınamayacağını unutmayın. - GroupTreeWidget - + Title Başlık @@ -8529,12 +7863,12 @@ p, li { white-space: pre-wrap; } - + Description Açıklama - + Number of Unread message @@ -8559,35 +7893,7 @@ p, li { white-space: pre-wrap; } - Sort Descending Order - Azalan Düzende Sırala - - - Sort Ascending Order - Artan Düzende Sırala - - - Sort by Name - Ada Göre Sırala - - - Sort by Popularity - Beğeniye Göre Sırala - - - Sort by Last Post - Son İletiye Göre Sırala - - - Sort by Number of Posts - İleti Sayısına Göre Sırala - - - Sort by Unread - Okunmamışlara Göre Sırala - - - + You are admin (modify names and description using Edit menu) Yöneticisiniz (Düzenle menüsünden ad ve açıklamaları değiştirebilirsiniz) @@ -8602,14 +7908,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post Son İleti - + Name Ad @@ -8620,17 +7926,13 @@ p, li { white-space: pre-wrap; } - + Never Hiç - Display - Görünüm - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8643,7 +7945,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and ve @@ -8779,7 +8081,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels Kanallar @@ -8790,26 +8092,22 @@ p, li { white-space: pre-wrap; } Kanal Ekle - + Enable Auto-Download Otomatik İndirme Kullanılsın - + My Channels Kanallarım - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Kanallar</h1> <p>Kanallar ağa yaymak istediğiniz verileri (film, müzik gibi) göndermenizi sağlar.</p> <p>Arkadaşlarınızın abone olduğu kanalları görebilirsiniz. Abone olduğunuz kanallar da otomatik olarak arkadaşlarınıza iletilir. Böylece ağdaki iyi kanallar öne çıkar.</p> <p>Bir kanala yalnız kanalı oluşturan kişi veri gönderebilir. Kanal özel bir kanal değilse ağdaki diğer eşler bu verileri yalnızca okuyabilir. Bununla birlikte veri gönderme ya da okuma izinlerini arkadaşınız oluan RetroShare düğümleri ile paylaşabilirsiniz.</p> <p>Kanallar isimsiz olabileceği gibi bir RetroShare kimliğiyle ilişkilendirilebilir. Böylece okuyucular gerek duyduğunda sizinle iletişim kurabilir. Gönderdiğiniz verilere kullanıcıların yorum yapmasını istiyorsanız "Yorumlar Kullanılsın" seçeneğini etkinleştirin.</p> <p>Bu değeri değiştirmediyseniz, kanala gönderilen veriler %1 gün tutulur ve son %2 gündeki veriler eşitlenir.</p> - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels Abone Olunan Kanallar @@ -8829,12 +8127,12 @@ p, li { white-space: pre-wrap; } Kanal indirme klasörünü seçin - + Disable Auto-Download Otomatik İndirmeyi Devre Dışı Bırak - + Set download directory İndirme klasörünü ayarla @@ -8869,22 +8167,22 @@ p, li { white-space: pre-wrap; } - + Play Oynat - + Open folder Klasörü aç - + Open file - + Error Hata @@ -8904,17 +8202,17 @@ p, li { white-space: pre-wrap; } Denetleniyor - + Are you sure that you want to cancel and delete the file? İşlemi iptal edip dosyayı silmek istediğinize emin misiniz? - + Can't open folder Klasör açılamadı - + Play File Dosyayı Oynat @@ -8924,37 +8222,10 @@ p, li { white-space: pre-wrap; } %1 dosyası konumda bulunamadı. - - GxsChannelFilesWidget - - Form - Form - - - Filename - Dosya Adı - - - Size - Boyut - - - Title - Başlık - - - Published - Yayınlanmış - - - Status - Durum - - GxsChannelGroupDialog - + Create New Channel Yeni Kanal Ekle @@ -8992,9 +8263,19 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - Kanala Abone Ol + + Last activity + + + + + TextLabel + Metin Etiketi + + + + Subscribe this Channel + @@ -9008,7 +8289,7 @@ p, li { white-space: pre-wrap; } - + Expand Genişlet @@ -9023,7 +8304,7 @@ p, li { white-space: pre-wrap; } Kanal Açıklaması - + Loading Yükleniyor @@ -9038,8 +8319,9 @@ p, li { white-space: pre-wrap; } - New Channel - Kanal Ekle + + Never + Hiç @@ -9050,7 +8332,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: Yeni Yorum: @@ -9071,7 +8353,7 @@ p, li { white-space: pre-wrap; } - + Play Oynat @@ -9127,28 +8409,24 @@ p, li { white-space: pre-wrap; } Files Dosya - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - Uyarı! Bu dosyanın silinmesine %1 saat %2 dakikadan az kaldı. Dosyayı kaydetmeyi düşünün. - Hide Gizle - + New Yeni - + 0 0 - - + + Comment Yorum @@ -9163,21 +8441,17 @@ p, li { white-space: pre-wrap; } Beğenmedim - Loading - Yükleniyor - - - + Loading... - + Comments Yorumlar - + Post @@ -9202,139 +8476,16 @@ p, li { white-space: pre-wrap; } Ortamı Oynat - - GxsChannelPostsWidget - - Post to Channel - Kanala Gönder - - - Add new post - Yeni ileti oluştur - - - Loading - Yükleniyor - - - Search channels - Kanal Arama - - - Title - Başlık - - - Search Title - Başlık Arama - - - Message - İleti - - - Search Message - İleti Arama - - - Filename - Dosya Adı - - - Search Filename - Dosya Adı Arama - - - No Channel Selected - Bir Kanal Seçilmemiş - - - Never - Hiç - - - Public - Herkese Açık - - - Restricted to members of circle " - Çevre üyeleri ile kısıtlı " - - - Restricted to members of circle - Çevre üyeleri ile kısıtlı - - - Your eyes only - Yalnız sizin gözlerinize - - - You and your friend nodes - Siz ve arkadaş düğümlerinize - - - Disable Auto-Download - Otomatik İndirmeyi Devre Dışı Bırak - - - Enable Auto-Download - Otomatik İndirmeyi Etkinleştir - - - Show feeds - Akışları görüntüle - - - Show files - Dosyaları görüntüle - - - Administrator: - Yönetici: - - - Last Post: - Son İleti: - - - unknown - bilinmiyorr - - - Distribution: - Dağıtım: - - - Feeds - Akış - - - Files - Dosya - - - Subscribers - Abone - - - Description: - Açıklama: - - - Posts (at neighbor nodes): - Gönderiler (komşu düğümlerden): - - GxsChannelPostsWidgetWithModel - + Post to Channel Kanala Gönder - + Add new post Yeni ileti oluştur @@ -9404,7 +8555,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -9440,7 +8591,7 @@ p, li { white-space: pre-wrap; } - + Comments Yorumlar @@ -9455,13 +8606,13 @@ p, li { white-space: pre-wrap; } Akış - - + + Click to switch to list view - + Show unread posts only @@ -9476,7 +8627,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -9491,7 +8642,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -9551,12 +8702,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -9608,7 +8769,7 @@ p, li { white-space: pre-wrap; } Public - + Herkese Açık @@ -9631,14 +8792,15 @@ p, li { white-space: pre-wrap; } Siz ve arkadaş düğümlerinize - + + Copy Retroshare link - + Subscribed - + Abone @@ -9673,7 +8835,7 @@ p, li { white-space: pre-wrap; } Enable Auto-Download - + Otomatik İndirme Kullanılsın @@ -9687,17 +8849,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel Metin Etiketi - + Circle name: - + Accept @@ -9717,27 +8879,11 @@ p, li { white-space: pre-wrap; } Remove Item Ögeyi Sil - - for identity - şu kimlik için - - - You received a membership request for circle: - Şu çevreye üyelik talebi aldınız: - Grant membership request Üyelik onayı talebi - - Revoke membership request - Üyelik iptali talebi - - - You received an invitation for circle: - Şu çevreye davet edildiniz: - @@ -9828,7 +8974,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container Yorum Taşıyıcı @@ -9841,7 +8987,7 @@ p, li { white-space: pre-wrap; } Form - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9871,7 +9017,7 @@ p, li { white-space: pre-wrap; } Yenile - + Comment Yorum @@ -9910,7 +9056,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment Yorumu Yanıtla @@ -9934,6 +9080,21 @@ p, li { white-space: pre-wrap; } Vote Down Beğenmedim + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9943,7 +9104,7 @@ p, li { white-space: pre-wrap; } Yorum Yap - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9972,26 +9133,10 @@ p, li { white-space: pre-wrap; } - + Post - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Yorum</span></p></body></html> - - - Signed by - İmzalayan - Reply to Comment @@ -10020,7 +9165,7 @@ before you can comment bir kimlik oluşturmalısınız - + It remains %1 characters after HTML conversion. @@ -10062,14 +9207,6 @@ bir kimlik oluşturmalısınız Forum moderators can edit/delete/pinup others posts - - Add Forum Admins - Forum Yöneticileri Ekle - - - Select Forum Admins - Forum Yöneticilerini Seçin - Create @@ -10079,7 +9216,7 @@ bir kimlik oluşturmalısınız GxsForumGroupItem - + Subscribe to Forum Foruma Abone Ol @@ -10095,7 +9232,7 @@ bir kimlik oluşturmalısınız - + Expand Genişlet @@ -10115,8 +9252,9 @@ bir kimlik oluşturmalısınız - Loading - Yükleniyor + + TextLabel + Metin Etiketi @@ -10147,13 +9285,13 @@ bir kimlik oluşturmalısınız GxsForumMsgItem - - + + Subject: Konu: - + Unsubscribe To Forum Forum Aboneliğinden Ayrıl @@ -10164,7 +9302,7 @@ bir kimlik oluşturmalısınız - + Expand Genişlet @@ -10184,21 +9322,17 @@ bir kimlik oluşturmalısınız Şuna Yanıt Olarak: - Loading - Yükleniyor - - - + Loading... - + Forum Feed Forum Akışı - + Hide Gizle @@ -10211,63 +9345,66 @@ bir kimlik oluşturmalısınız Form - + Start new Thread for Selected Forum Seçilmiş Foruma Yeni Konu Ekle - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums Forum Arama - Last Post - Son İleti - - - + New Thread Yeni Konu - - - Threaded View - İç İçe Görünüm - - - - Flat View - Düz Görünüm - - + Title Başlık - - + + Date Tarih - + Author Yazar - - Save image - Görseli Kaydet - - - + Loading Yükleniyor - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -10277,12 +9414,7 @@ bir kimlik oluşturmalısınız - - Lastest post in thread - - - - + Reply Message İletiyi Yanıtla @@ -10306,10 +9438,6 @@ bir kimlik oluşturmalısınız Download all files Tüm dosyaları indir - - Next unread - Sonraki Okunmamış - Search Title @@ -10326,35 +9454,23 @@ bir kimlik oluşturmalısınız Yazar Arama - Content - İçerik - - - Search Content - İçerik Arama - - - <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - <p>Foruma abone olduğunuzda diğer abone olan arkadaşlarınızın gönderilerini alabilir ve forumu tüm diğer arkadaşlarınıza görünür kılabilirsiniz..</p><p>İstediğinizde soldaki forum listesine sağ tıklayarak abonelikten ayrılabilirsiniz.</p> - - - + No name Adsız - - + + Reply Yanıtla - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -10397,20 +9513,12 @@ bir kimlik oluşturmalısınız RetroShare Bağlantısını Kopyala - + Hide Gizle - Expand - Genişlet - - - [Banned] - [Engellenmiş] - - - + [unknown] [bilinmiyor] @@ -10440,8 +9548,8 @@ bir kimlik oluşturmalısınız Yalnız sizin gözlerinize - - + + Distribution Dağıtım @@ -10455,26 +9563,6 @@ bir kimlik oluşturmalısınız Anti-spam Önemsiz İleti Ayıklama - - [ ... Redacted message ... ] - [ ... Düzeltilmiş İleti ... ] - - - Anonymous - İsimsiz - - - signed - imzalanmış - - - none - yok - - - [ ... Missing Message ... ] - [... İleti Eksik ... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10544,16 +9632,12 @@ bir kimlik oluşturmalısınız Özgün İleti - + New thread Yeni konu - Read status - Okunma durumu - - - + Edit Düzenle @@ -10614,7 +9698,7 @@ bir kimlik oluşturmalısınız Yazarın değerlendirmesi - + Show column @@ -10634,7 +9718,7 @@ bir kimlik oluşturmalısınız - + Anonymous/unknown posts forwarded if reputation is positive Değerlendirme olumlu ise İsimsiz/bilinmeyen iletiler iletilir @@ -10686,7 +9770,7 @@ This message is missing. You should receive it later. - + No result. @@ -10696,7 +9780,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -10711,29 +9795,7 @@ This message is missing. You should receive it later. - Information for this identity is currently missing. - Bu kimlikle ilgili bilgiler şu anda eksik. - - - You have banned this ID. The message will not be -displayed nor forwarded to your friends. - Bu kodu engellediniz. Bu leti arkadaşlarınıza -görüntülenmeyecek ve iletilmeyecek. - - - You have not set an opinion for this person, - and your friends do not vote positively: Spam regulation -prevents the message to be forwarded to your friends. - Bu kişiyle ilgili bir değerlendirme yapmamışsınız ve -arkadaşlarınız da olumlu olarak değerlendirmemiş: -İstenmeyen ileti kuralı bu iletinin arkadaşlarınıza iletilmesini engeller. - - - Message will be forwarded to your friends. - İleti arkadaşlarınıza iletilecek. - - - + (Latest) (En yeni) @@ -10742,10 +9804,6 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: (Old) (Eski) - - You cant act on the author to a non-existant Message - Var olmayan bir iletinin yazarına işlem yapamazsınız - From @@ -10803,12 +9861,12 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forumlar</h1> <p>RetroShare Forumları İnternet forumları gibi görünür, ancak merkezi olmayan bir şekilde çalışır.</p> <p>Arkadaşlarınızın abone olduğu forumları görebilir ve abone olduğunuz forumları arkadaşlarınıza iletebilirsiniz. Böylece ilgi gören forumlar ağ üzerinde kendiliğinden üst sıralara çıkar.</p> <p>Başka şekilde yapılandırmadıysanız, forum iletileri %1 gün saklanır ve son %2 gündeki iletiler eşitlenir.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> + - + Forums Forumlar @@ -10839,35 +9897,16 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Diğer Forumlar - - GxsForumsFillThread - - Waiting - Bekliyor - - - Retrieving - Alınıyor - - - Loading - Yükleniyor - - GxsGroupDialog - + Name Ad - Add Icon - Simge Ekle - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels Temel alıcılar kısıtlanmış türde gruplar üzerinde yayınlama işlemi yapabilir ve özel türde kanallar üzerinde okuma yayınlama işlemi yapabilir. @@ -10876,22 +9915,14 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Share Publish Key Yayınlama Anahtarını Paylaş - - check peers you would like to share private publish key with - özel yayın anahtarınızı paylaşacağınız eşleri seçin - - - Share Key With - Anahtarı Şunlarla Paylaş - - + Description Açıklama - + Message Distribution İleti Dağıtımı @@ -10899,7 +9930,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - + Public Herkese Açık @@ -10918,14 +9949,6 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: New Thread Konu Ekle - - Required - Zorunlu - - - Encrypted Msgs - Şifreli İletiler - Personal Signatures @@ -10967,7 +9990,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Önemsiz ileti koruması - + Comments: Yorumlar: @@ -10990,7 +10013,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Önemsiz İleti Ayıklama: - + All People @@ -11006,12 +10029,12 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - + Restricted to circle: Çevre ile sınırlı: - + Limited to your friends Arkadaşlarınız ile sınırlı @@ -11028,23 +10051,23 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - + Message tracking İleti izleme - - + + PGP signature required PGP imzası zorunlu - + Never Hiç - + Only friends nodes in group Yalnız gruptaki arkadaş düğümleri @@ -11060,30 +10083,28 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Lütfen bir ad ekleyin - + PGP signature from known ID required Bilinen bir kodun PGP imzası zorunludur - + + + [None] + + + + Load Group Logo Grup Logosunu Yükle - + Submit Group Changes Grup Değişikliklerini Gönder - Failed to Prepare Group MetaData - please Review - Grup Üst Verisi Hazırlanamadı - Lütfen Gözden Geçirin - - - Will be used to send feedback - Geri bildirim göndermek için kullanılır - - - + Owner: Sahip: @@ -11093,12 +10114,12 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Buraya açıklayıcı bilgiler yazın - + Info Bilgiler - + ID Kod @@ -11108,7 +10129,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Son İleti - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> <html><head/><body><p>İletiler, oluşturduğunuz kanal, forum ya da gönderiye abone olundukça, arkadaş düğümleriniz aracılığı ile yayılır.</p></body></html> @@ -11183,7 +10204,12 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: İmzasız ve bilinmeyen düğüm kodlarını gözden düşür - + + Author: + + + + Popularity Beğenilme @@ -11199,27 +10225,22 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - + Created - + Cancel - + Create Ekle - - Author - Yazar - - - + GxsIdLabel GxsKodEtiketi @@ -11227,7 +10248,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: GxsGroupFrameDialog - + Loading Yükleniyor @@ -11287,7 +10308,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Ayrıntıları Düzenle - + Synchronise posts of last... İletilerin eşitleneceği süre... @@ -11344,16 +10365,12 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - + Search for - Share publish permissions - Yayınlama izinlerini paylaş - - - + Copy RetroShare Link RetroShare Bağlantısını Kopyala @@ -11376,7 +10393,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: GxsIdChooser - + No Signature İmza Yok @@ -11389,40 +10406,24 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: GxsIdDetails - Loading - Yükleniyor - - - + Not found Bulunamadı - - No Signature - İmza Yok - - - + + [Banned] [Engellenmiş] - - Authentication - Doğrulama - unknown Key Anahtar Bilinmiyor - anonymous - isimsiz - - - + Loading... @@ -11432,7 +10433,12 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - + + [Nobody] + + + + Identity&nbsp;name Kimlik&nbsp;Adı @@ -11446,16 +10452,20 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Node Düğüm - - Signed&nbsp;by - İmzalayan - [Unknown] [Bilinmiyor] + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -11467,7 +10477,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: GxsIdStatisticsWidget - + Total identities: @@ -11515,17 +10525,13 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: GxsIdTreeItemDelegate - + [Unknown] [Bilinmiyor] GxsMessageFramePostWidget - - Loading - Yükleniyor - Loading... @@ -11642,10 +10648,6 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Group ID / Author Grup Kodu / Yazar - - Number of messages / Publish TS - İleti sayısı / Yayım Zamanı - Local size of data @@ -11661,10 +10663,6 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Popularity Beğenilme - - Details - Ayrıntılar - @@ -11697,41 +10695,6 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Hayır - - GxsTunnelsDialog - - Authenticated tunnels: - Doğrulanmış tüneller: - - - Tunnel ID: %1 - Tünel Kodu: %1 - - - from: %1 - şuradan: %1 - - - to: %1 - şuraya: %1 - - - status: %1 - durum: %1 - - - total sent: %1 bytes - toplam gönderilen: %1 bayt - - - total recv: %1 bytes - toplam alınan: %1 bayt - - - Unknown Peer - Eş Bilinmiyor - - HashBox @@ -11944,48 +10907,12 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: About Hakkında - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare provides file sharing, chat, messages and channels</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Useful external links to more information:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Wiki</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare's Forum</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Project Page</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Team Blog</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Dev Twitter</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare Açık Kaynaklı platformlar arası, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">kişisel ve güvenli, merkezi olmayan bir iletişim platformudur. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Kimliği doğrulanmış eşler ağı ve OpenSSL ile şifrelenmiş ilerişim üzerinden </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">arkadaşlarınız ile güvenli sayısal içerik paylaşımı sağlar.</span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare dosya paylaşımı, sohbet, iletiler ve kanallar gibi özellikler sunar</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Ayrıntılı bilgi alınabilecek bağlantılar:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Retroshare Web Sayfası</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Wiki Sayfası</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Forumu</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Proje Sayfası</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Takım Bloğu</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Geliştirici Twitter Hesabı</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -12001,7 +10928,7 @@ p, li { white-space: pre-wrap; } - + Authors Geliştiriciler @@ -12020,7 +10947,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -12033,36 +10960,6 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Daniel Wester</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">wester@speedmail.se</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">German: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Jan</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Keller</span><span style=" font-family:'MS Shell Dlg 2';"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">trilarion@users.sourceforge.net</span><span style=" font-family:'MS Shell Dlg 2';">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - <span style=" font-size:8pt; font-weight:600;"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Çevirileri:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Web Sitesi Çevirmenleri:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">İsveçce: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Daniel Wester</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">wester@speedmail.se</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Almanca: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Jan</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Keller</span><span style=" font-family:'MS Shell Dlg 2';"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">trilarion@users.sourceforge.net</span><span style=" font-family:'MS Shell Dlg 2';">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Lehçe: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - License Agreement @@ -12128,12 +11025,12 @@ p, li { white-space: pre-wrap; } Form - + <html><head/><body><p>Copy your RetroShare ID to clipboard</p></body></html> - + Add friend @@ -12148,7 +11045,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -12157,32 +11054,12 @@ p, li { white-space: pre-wrap; } This is your Retroshare ID. Copy and share with your friends! - - Did you receive a certificate from a friend? - Bir arkadaşınızdan bir sertifika dosyası aldınız mı? - - - Add friends certificate - Arkadaş sertifikasını ekle - - - Add certificate file - Sertifika dosyası ekle - - - Share your RetroShare Key - RetroShare Anahtarınızı Paylaşın - ... ... - - The text below is your own Retroshare certificate. Send it to your friends - Aşağıdaki metin sizin RetroShare sertifikanızdır. Bu metni arkadaşlarınıza gönderin - Open Source cross-platform, @@ -12192,20 +11069,12 @@ private and secure decentralized communication platform. merkezi olmayan kişisel ve güvenli bir iletişim platformu. - Launch startup wizard - Başlangıç yardımcısını çalıştır - - - Do you need help with RetroShare? - RetroShare hakkında yardıma ihtiyacınız var mı? - - - + Open Web Help Web Yardımını Aç - + Copy your Cert to Clipboard Sertifikanızı Panoya Kopyalayın @@ -12215,7 +11084,7 @@ merkezi olmayan kişisel ve güvenli bir iletişim platformu. Sertifikanızı Bir Dosyaya Kaydedin - + Send via Email E-posta ile Gönder @@ -12235,13 +11104,37 @@ merkezi olmayan kişisel ve güvenli bir iletişim platformu. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -12253,17 +11146,12 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -12272,19 +11160,11 @@ new short format Your Retroshare ID is copied to Clipboard, paste and send it to your friend via email or some other way - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your certificate on this page and send it to friends, and add your friends' certificate.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange certificates with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;RetroShare uygulamasına hoş geldiniz!</h1> <p><b>Arkadaş</b> edinmeniz gerek! Bir arkadaş ağı oluşturduğunuzda ya da var olan bir ağa katıldığınızda, dosya gönderip almak, sohbet etmek ve forumlarda yazışmak gibi işlemler yapabilirsiniz. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>Bunun için, bu sayfadaki sertifikanızı kopyalayıp arkadaşlarınıza gönderin ve arkadaşınızın sertifikasını ekleyin.</p> <p>Diğer bir seçenek İnternet üzerinde "Retroshare chat servers" (bağımsız olarak yönetilirler) ifadesini aramaktır. Bu sunucular adanmış bir RetroShare düğümü ile sertifika değiş tokuşu yapabilmenizi sağlar. Böylece başka kişilerle isimsiz olarak tanışabilirsiniz.</p> - RetroShare Invite RetroShare Çağrı - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - Sertifikanız Panoya kopyalandı, e-postanıza yapıştırarak ya da başka bir şekilde arkadaşınıza iletebilirsiniz - Save as... @@ -12556,14 +11436,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All Tümü - + Reputation Değerlendirme @@ -12573,12 +11453,12 @@ p, li { white-space: pre-wrap; } Arama - + Anonymous Id İsimsiz Kod - + Create new Identity Yeni kimlik ekle @@ -12588,7 +11468,7 @@ p, li { white-space: pre-wrap; } Yeni çevre ekle - + Persons Kişiler @@ -12603,27 +11483,27 @@ p, li { white-space: pre-wrap; } Kişi - + Close Kapat - + Ban-option: Engelleme seçeneği: - + Auto-Ban all identities signed by the same node Aynı düğüm tarafından imzalanmış tüm kimlikler otomatik engellensin - + Friend votes: Arkadaş değerlendirmeleri: - + Positive votes Olumlu değerlendirme @@ -12639,29 +11519,39 @@ p, li { white-space: pre-wrap; } Olumsuz değerlendirme - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics Kullanım istatistikleri - + Circles Çevreler - + Circle name Çevre adı @@ -12681,18 +11571,20 @@ p, li { white-space: pre-wrap; } Kişisel Çevreler - + + Edit identity Kimliği Düzenle - + + Delete identity Kimliği Sil - + Chat with this peer Bu eş ile sohbet et @@ -12702,97 +11594,78 @@ p, li { white-space: pre-wrap; } Bu eş ile bir sohbet başlatır - + Owner node ID : Sahip düğüm kodu : - + Identity name : Kimlik adı : - + () () - + Identity ID Kimlik Kodu - + Send message İleti Gönder - + Identity info Kimlik Bilgileri - + Identity ID : Kimlik Kodu : - + Owner node name : Sahip düğüm adı : - + Create new... Yeni ekle... - + Type: Tür: - + Send Invite Çağrı Gönder - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> <html><head/><body><p>Komşu düğümlerin bu kimlik hakkında ortalama değerlendirmesi. Olumsuz kötü,</p><p>olumlu iyi, sıfır kararsızdır</p></body></html> - + Your opinion: Değerlendirmeniz: - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </p> -<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Bir kimlik hakkındaki değerlendirmeniz, bu kimliğin siz ve arkadaşlarınıza görüntülenmesini belirler. Değerlendirmeniz arkadaşlarınızla paylaşılır ve değerlendirme notunun hesaplanmasında kullanılır: Bir kimlik hakkındaki değerlendirmeniz kararsız ise, değerlendirme notu, arkadaşlarınızın olumlu ve olumsuz değerlendirmeleri arasındaki fark olur. Kararsız değil ise sizin değerlendirmeniz notu belirler.</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Genel not her bir kimliğin sohbet odaları, forumlar ve kanallarda yapabileceği işlemleri belirler. Genel not -1 değerinden düşükse, bu kimlikten gelen ve ona gönderilen tüm forum/kanal iletiler engellenir. Ayrıca kötü değerlendirmelere karşı daha duyarlı bazı forumlarda daha yüksek değerlendirme notu gerektiren özel anti-spam işaretleri bulunur. Engellenen kimliklerin etkinliği yavaşça azalır ve bir süre sonra kaybolur (5 gün sonra). </p> -<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - + Negative Olumsuz - + Neutral Kararsız @@ -12803,17 +11676,17 @@ p, li { white-space: pre-wrap; } Olumlu - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> <html><head/><body><p>Siz ve arkadaşlarınız için hesaplanmış genel değerlendirme notu.</p><p>Olumsuz kötü, olumlu iyi, sıfır kararsızdır. Not çok düşükse,</p><p>kimlik kötü olarak işaretlenir ve forumlar, sohbet odaları,</p><p>kanallar gibi ögelerin dışında bırakılır.</p></body></html> - + Overall: Genel Değerlendirme: - + Anonymous İsimsiz @@ -12828,24 +11701,24 @@ p, li { white-space: pre-wrap; } Kod Arama - + This identity is owned by you Bu kimlik size ait - - + + My own identities Kendi kimliklerim - - + + My contacts Kişilerim - + Show Items Ögeleri Görüntüle @@ -12860,7 +11733,12 @@ p, li { white-space: pre-wrap; } Düğümümle bağlantılı - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles Diğer çevreler @@ -12870,7 +11748,7 @@ p, li { white-space: pre-wrap; } Üyesi olduğum çevreler - + Circle ID: Çevre Kodu: @@ -12945,7 +11823,7 @@ p, li { white-space: pre-wrap; } Üye değil (bu çevrenin verilerine erişemezsiniz) - + Identity ID: Kimlik Kodu: @@ -12975,7 +11853,7 @@ p, li { white-space: pre-wrap; } bilinmiyor - + Invited Çağrılmış @@ -12990,7 +11868,7 @@ p, li { white-space: pre-wrap; } Üye - + Edit Circle Çevreyi Düzenle @@ -13038,7 +11916,7 @@ p, li { white-space: pre-wrap; } Üyeliği onayla - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -13049,7 +11927,7 @@ Bu izden kurtulup yeni bir tane kullanmalısınız. Bu kimliklere yakın zamanda destek verilmeyecek. - + [Unknown node] [Düğüm bilinmiyor] @@ -13092,7 +11970,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. İsimsiz kimlik - + Boards @@ -13172,7 +12050,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. - + information bilgiler @@ -13188,29 +12066,12 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Kimliği panoya kopyala - Send invite? - Çağrı gönderilsin mi? - - - Do you really want send a invite with your Certificate? - Sertifikanız ile bir çağrı göndermek istediğinize emin misiniz? - - - + Banned Engellenmiş - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Kimlikler</h1> <p>Bu sekmeden <b>sahte isimsiz kimlikler</b> ve <b>çevreler</b> oluşturup düzenleyebilirsiniz. </p> <p><b>Kimlikler</b> verilerinizin güvenli olarak tanınmasını sağlamak için forum ve kanal iletilerini imzalamakta ve RetroShare iç e-posta sistemini kullanarak geri bildirimleri almak, kanal iletilerinden sonra yorum yapmak gibi işlemler için kullanılır</p> <p> Kimlikler isteğe bağlı olarak RetroShare düğümünüzün sertifikası ile <b>imzalanabilir</b>. İmzalanmış kimliklere güvenilmesi daha kolaydır ancak bunlar düğümünüzün IP adresinin kolayca belirlenmesini sağlar.</p> <p><b>İsimsiz kimlikler</b> diğer kullanıcılar ile kimliğinizi gizli tutarak etkileşimde bulunmanızı sağlar. Kandırılamazlar ancak hiç kimse verilen bir kimliğin gerçek sahibini ispatlayamaz.</p> <p><b>Çevreler</b> ağ üzerinde bir alanı paylaşan bir kimlik grubudur (isimsiz ya da imzalanmış). Çevreler forum ve kanal gibi ögelerin görüntülenmesini kısıtlamak için kullanılır. </p> <p>Bir <b>çevre</b> başka bir çevre tarafından ya da yalnız kendi üyeleri tarafından görülebilecek şekilde kendi içinde kısıtlanabilir.</p> - - - Unknown ID: - Kod Bilinmiyor : - - - + positive olumlu @@ -13254,19 +12115,11 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Forums Forumlar - - Posted - Gönderilme - Chat Sohbet - - Unknown - Bilinmiyor - [Unknown] @@ -13287,14 +12140,6 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Creation of author signature in service %1 %1 hizmetinin yönetici imzasının oluşturma - - Message/vote/comment - İleti/oy/yorum - - - %1 in %2 tab - %1 %2 sekmesinde - Distant message signature validation. @@ -13315,19 +12160,11 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Signature in distant tunnel system. Uzak tünel sistemi imzası. - - Update of identity data. - Kimlik verisinin güncellenmesi. - Generic signature validation. Genel imza doğrulama. - - Generic signature. - Genel imza. - Generic encryption. @@ -13339,11 +12176,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Genel şifre çözme. - Membership verification in circle %1. - %1 çevresinde üyelik doğrulama. - - - + Add to Contacts Kişilere Ekle @@ -13393,21 +12226,21 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Merhaba,<br>RetroShare üzerinde sizinle arkadaş olmak istiyorum.<br> - - - + + + People Kişiler - + Your Avatar Click here to change your avatar Avatarınız - + Linked to neighbor nodes Komşu düğümlerle bağlantılı @@ -13417,7 +12250,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Uzak düğümlerle bağlantılı - + Linked to a friend Retroshare node Bir arkadaşın RetroShare düğümüyle bağlantılı @@ -13432,7 +12265,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Bilinmeyen bir RetroShare düğümüyle bağlantılı - + Chat with this person Bu kişiyle sohbet edin @@ -13447,12 +12280,12 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Bu kişi ile uzak sohbet reddedildi. - + Last used: Son kullanılma: - + +50 Known PGP +50 Bilinen PGP @@ -13472,12 +12305,12 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Bu kimliği silmek istediğinize emin misiniz? - + Owned by Sahibi - + Node name: Düğüm adı: @@ -13487,7 +12320,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Düğüm Kodu: - + Really delete? Gerçekten silinsin mi? @@ -13495,7 +12328,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. IdEditDialog - + Nickname Takma ad @@ -13525,7 +12358,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Takma Ad - + Import image @@ -13535,12 +12368,19 @@ Bu kimliklere yakın zamanda destek verilmeyecek. - - Use the mouse to zoom and adjust the image for your avatar. + + + No Avatar chosen. A default image will be automatically displayed from your new identity. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity Yeni kimlik @@ -13554,7 +12394,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. - + @@ -13564,7 +12404,12 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Kullanılamıyor - + + No avatar chosen + + + + Edit identity Kimliği düzenle @@ -13575,27 +12420,27 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Güncelle - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -13615,7 +12460,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. - + Identity update failed @@ -13625,11 +12470,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. - Error getting key! - Anahtar alınamadı! - - - + Error KeyID invalid Anahtar kodu geçersiz @@ -13644,7 +12485,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Gerçek ad bilinmiyor - + Create New Identity Yeni Kimlik Oluştur @@ -13654,10 +12495,15 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Tür - + Choose image... + + + Remove + + @@ -13683,7 +12529,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Ekle - + Create Ekle @@ -13693,17 +12539,13 @@ Bu kimliklere yakın zamanda destek verilmeyecek. - + Your Avatar Click here to change your avatar Avatarınız - Set Avatar - Avatarı Ayarla - - - + Linked to your profile Profilinizle bağlantılı @@ -13713,7 +12555,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Bir ya da bir kaç kimliğiniz olabilir. Kimlikler sohbet odalarında, forumlarda ve kanal yorumlarında yazışırken kullanılır. Uzak sohbet ve RetroShare uzak posta sistemi için hedef olarak kullanılırlar. - + The nickname is too short. Please input at least %1 characters. Takma ad çok kısa. Lütfen en az %1 karakter yazın. @@ -13772,10 +12614,6 @@ Bu kimliklere yakın zamanda destek verilmeyecek. PGP name: PGP adı: - - GXS id: - GXS kodu: - PGP id: @@ -13791,7 +12629,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. - + Copy Kopyala @@ -13801,12 +12639,12 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Sil - + %1 's Message History - + Mark all Tümünü işaretle @@ -13825,26 +12663,38 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Quote - - Send - Gönder - ImageUtil - - + + Save image Görseli kaydet + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + + + + Cannot save the image, invalid filename Dosya adı geçersiz olduğundan görsel kaydedilemiyor - + + Copy image + + + + + Not an image Bu bir görsel değil @@ -13862,27 +12712,32 @@ Bu kimliklere yakın zamanda destek verilmeyecek. - + Enable RetroShare JSON API Server - + Port: Kapı: - + Listen Address: - + + Status: + Durum: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -13903,7 +12758,12 @@ Bu kimliklere yakın zamanda destek verilmeyecek. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -13912,26 +12772,31 @@ Bu kimliklere yakın zamanda destek verilmeyecek. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File Dosya Aç - + Open Folder Klasör Aç - + Checking... Denetleniyor... @@ -13941,7 +12806,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Dosyaları denetle - + Recommend in a message to... Şu kişiye iletiyle öner... @@ -13969,7 +12834,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. MainWindow - + Add Friend Arkadaş Ekle @@ -13985,7 +12850,8 @@ Bu kimliklere yakın zamanda destek verilmeyecek. - + + Options Ayarlar @@ -14006,7 +12872,7 @@ Bu kimliklere yakın zamanda destek verilmeyecek. - + Quit Çık @@ -14017,12 +12883,12 @@ Bu kimliklere yakın zamanda destek verilmeyecek. Hızlı Başlangıç Yardımcısı - + RetroShare %1 a secure decentralized communication platform RetroShare %1 merkezi olmayan güvenli bir iletişim platformudur - + Unfinished Tamamlanmamış @@ -14051,11 +12917,12 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın. + Status Durum - + Notify Bildir @@ -14066,31 +12933,35 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın. + Open Messages İletileri Aç - + + Bandwidth Graph Bant Genişliği Çizelgesi - + Applications Uygulamalar + Help Yardım - + + Minimize Küçült - + Maximize Büyüt @@ -14105,7 +12976,12 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın.RetroShare - + + Close window + + + + %1 new message %1 yeni ileti @@ -14135,7 +13011,7 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın.%1 arkadaş bağlı - + Do you really want to exit RetroShare ? RetroShare uygulamasından çıkmak istiyor musunuz? @@ -14155,7 +13031,7 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın.Görüntüle - + Make sure this link has not been forged to drag you to a malicious website. Bu bağlantının sizi zararlı yazılım bulunduran bir web sitesine yönlendirmediğinden emin olun. @@ -14200,12 +13076,13 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın.Hizmet izinleri matrisi - + + Statistics İstatistikler - + Show web interface Web arayüzünü görüntüle @@ -14220,7 +13097,7 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın.klasöründe yer azaldı (geçerli sınır - + Really quit ? Gerçekten çıkmak istiyor musunuz? @@ -14229,17 +13106,17 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın.MessageComposer - + Compose Yeni İleti - + Contacts Kişiler - + Paragraph Paragraf @@ -14275,12 +13152,12 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın.6. Başlık - + Font size Yazı Boyutu - + Increase font size Yazı boyutunu büyüt @@ -14295,32 +13172,32 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın.Koyu - + Italic Yatık - + Alignment Hizalama - + Add an Image Bir görsel ekle - + Sets text font to code style Metin yazı türünü kod biçeminde ayarla - + Underline Altı çizili - + Subject: Konu: @@ -14331,32 +13208,32 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın. - + Tags Etiketler - + Address list: Adres listesi: - + Recommend this friend Bu arkadaşı öner - + Set Text color Metin rengini ayarla - + Set Text background color Metin art alan rengini ayarla - + Recommended Files Önerilen Dosyalar @@ -14426,7 +13303,7 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın.Blok Alıntısı Ekle - + Send To: Kime: @@ -14450,10 +13327,6 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın.&Justify &Yanlara - - All addresses (mixed) - Tüm adresler (karışık) - All people @@ -14465,7 +13338,7 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın.Kişilerim - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> Merhaba, <br>İyi bir arkadaşımı öneriyorum; bana güveniyorsan ona da güvenebilirsin. <br> @@ -14485,18 +13358,18 @@ Lütfen biraz boş disk alanı açıp Tamam düğmesine tıklayın.RetroShare üzerinde sizinle arkadaş olmak istiyor - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team Merhaba %1, %2 <br><br>RetroShare üzerinde seninle arkadaş olmak istiyor. <br><br>İsteği şimdi yanıtlayabilirsin: <br>%3<br><br>Teşekkürler,<br>RetroShare Takımı - - + + Save Message İletiyi Kaydet - + Message has not been Sent. Do you want to save message to draft box? İleti gönderilemedi @@ -14508,7 +13381,17 @@ Do you want to save message to draft box? RetroShare Bağlantısını Yapıştır - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" "Kime" alanına ekle @@ -14528,7 +13411,7 @@ Do you want to save message to draft box? Öneri Olarak Ekle - + Original Message Özgün İleti @@ -14538,21 +13421,21 @@ Do you want to save message to draft box? Kimden - + - + To Kime - - + + Cc Kopya - + Sent Gönderildi @@ -14567,7 +13450,7 @@ Do you want to save message to draft box? %1 zamanında, %2 yazdı: - + Re: Ynt: @@ -14577,30 +13460,30 @@ Do you want to save message to draft box? İlet: - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? Bu iletiyi konusu olmadan mı göndermek istiyorsunuz? - + Please insert at least one recipient. Lütfen en az bir alıcı ekleyin. - + Bcc Gizli Kopya - + Unknown Bilinmiyor @@ -14715,13 +13598,13 @@ Do you want to save message to draft box? Ayrıntılar - + Open File... Dosya Aç... - + HTML-Files (*.htm *.html);;All Files (*) HTML Dosyaları (*.htm *.html);;Tüm Dosyalar (*) @@ -14741,7 +13624,7 @@ Do you want to save message to draft box? PDF Olarak Dışa Aktar - + Message has not been Sent. Do you want to save message ? İleti gönderilemedi @@ -14763,7 +13646,7 @@ Do you want to save message ? Başka Dosya Ekleyin - + Hi,<br>I want to be friends with you on RetroShare.<br> Merhaba,<br>RetroShare üzerinde sizinle arkadaş olmak istiyorum.<br> @@ -14787,28 +13670,24 @@ Do you want to save message ? Warning: This message is too big of %1 characters after HTML conversion. - - You have a friend invite - Bir arkadaşlık isteğiniz var - Respond now: Şimdi yanıtlayın: - - + + Close Kapat - + From: Kimden: - + Friend Nodes Arkadaş Düğümleri @@ -14853,13 +13732,13 @@ Do you want to save message ? Sıralı liste (büyük romen) - - + + Thanks, <br> Teşekkürler, <br> - + Distant identity: Uzak kimlik: @@ -14869,12 +13748,12 @@ Do you want to save message ? [Eksik] - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. Lütfen uzak iletileri imzalamak için bir kimlik oluşturun ya da hedef listesinden uzak eşleri kaldırın. - + Node name & id: Düğüm adı ve kodu: @@ -14952,7 +13831,7 @@ Do you want to save message ? Varsayilan - + A new tab Yeni sekmede @@ -14962,7 +13841,7 @@ Do you want to save message ? Yeni pencerede - + Edit Tag Etiketi Düzenle @@ -14985,7 +13864,7 @@ Do you want to save message ? MessageToaster - + Sub: Konu: @@ -14993,7 +13872,7 @@ Do you want to save message ? MessageUserNotify - + Message İleti @@ -15021,7 +13900,7 @@ Do you want to save message ? MessageWidget - + Recommended Files Önerilen Dosyalar @@ -15031,37 +13910,37 @@ Do you want to save message ? Önerilen Tüm Dosyaları İndir - + Subject: Konu: - + From: Kimden: - + To: Kime: - + Cc: Kopya: - + Bcc: Gizli Kopya: - + Tags: Etiketler: - + Reply Yanıtla @@ -15083,7 +13962,7 @@ Do you want to save message ? Forward - + İleri @@ -15101,7 +13980,7 @@ Do you want to save message ? - + Send Invite Çağrı Gönder @@ -15145,7 +14024,7 @@ Do you want to save message ? Buttons Text Beside Icon - + Düğme Simgelerinin Yanında Metin @@ -15153,7 +14032,7 @@ Do you want to save message ? - + Confirm %1 as friend %1 kullanıcısını arkadaş olarak onayla @@ -15163,12 +14042,12 @@ Do you want to save message ? %1 kullanıcısını arkadaş olarak ekle - + View source - + No subject Konu yok @@ -15178,17 +14057,22 @@ Do you want to save message ? Indir - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -15198,21 +14082,23 @@ Do you want to save message ? - Send invite? - Çağrı Gönder + + Show less + - Do you really want send a invite with your Certificate? - Sertifikanız ile bir çağrı göndermek istediğinize emin misiniz? + + Show more + - + Download all Tümünü indir - + Print Document Belgeyi Yazdır @@ -15227,12 +14113,12 @@ Do you want to save message ? HTML Dosyaları (*.htm *.html);;Tüm Dosyalar (*) - + Load images always for this message Bu iletideki görseller her zaman yüklensin - + Hide the attachment pane Dosya ekleme panosu gizlensin @@ -15254,42 +14140,6 @@ Do you want to save message ? Compose Yeni İleti - - Reply to selected message - Seçilmiş iletiyi yanıtla - - - Reply - Yanıtla - - - Reply all to selected message - Seçilmiş iletinin tüm alıcılarını yanıtla - - - Reply all - Tümünü yanıtla - - - Forward selected message - Seçilmiş iletiyi ilet - - - Forward - İlet - - - Remove selected message - Seçilmiş iletiyi sil - - - Delete - Sil - - - Print selected message - Seçilmiş iletiyi yazdır - Print @@ -15368,7 +14218,7 @@ Do you want to save message ? MessagesDialog - + New Message Yeni İleti @@ -15378,60 +14228,16 @@ Do you want to save message ? Yeni İleti - Reply to selected message - Seçilmiş iletiyi yanıtla - - - Reply - Yanıtla - - - Reply all to selected message - Seçilmiş iletinin tüm alıcılarını yanıtla - - - Reply all - Tümünü yanıtla - - - Forward selected message - Seçilmiş iletiyi ilet - - - Foward - İlet - - - Remove selected message - Seçilmiş iletiyi sil - - - Delete - Sil - - - Print selected message - Seçilmiş iletiyi yazdır - - - Print - Yazdır - - - Display - Görünüm - - - + - - + + Tags Etiketler - - + + Inbox Gelen @@ -15461,21 +14267,17 @@ Do you want to save message ? Çöp - + Total Inbox: Toplam Gelen: - Folders - Klasörler - - - + Quick View Hızlı Görünüm - + Print... Yazdır... @@ -15485,26 +14287,6 @@ Do you want to save message ? Print Preview Baskı Önizleme - - Buttons Icon Only - Yalnız Düğme Simgeleri - - - Buttons Text Beside Icon - Düğme Simgelerinin Yanındaki Metin - - - Buttons with Text - Düğme Üzerindeki Metin - - - Buttons Text Under Icon - Simgenin Altındaki Düğme Metni - - - Set Text Under Icon - Simge Altındaki Metni Ayarlayın - Save As... @@ -15526,7 +14308,7 @@ Do you want to save message ? İletiyi İlet - + Subject Konu @@ -15536,7 +14318,7 @@ Do you want to save message ? Kimden - + Date Tarih @@ -15546,39 +14328,7 @@ Do you want to save message ? İçindekiler - Click to sort by attachments - Dosya eklerine göre sıralamak için tıklayın - - - Click to sort by subject - Konuya göre sıralamak için tıklayın - - - Click to sort by read - Okunmuş durumuna göre sıralamak için tıklayın - - - Click to sort by from - Gönderene göre sıralamak için tıklayın - - - Click to sort by date - Tarihe göre sıralamak için tıklayın - - - Click to sort by tags - Etiketlere göre sıralamak için tıklayın - - - Click to sort by star - Yıldızlara göre sıralamak için tıklayın - - - Forward selected Message - Seçilmiş iletiyi ilet - - - + Search Subject Konu Arama @@ -15587,6 +14337,11 @@ Do you want to save message ? Search From Gönderen Arama + + + Search To + + Search Date @@ -15613,14 +14368,14 @@ Do you want to save message ? Dosya Eki Arama - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;İletiler</h1> <p>RetroShare kendi iç posta sistemine sahiptir. Bağlantılı arkadaş düğümleri ile e-posta alışverişi yapılabilir.</p> <p>Genel yöneltme sistemini kullanarak diğer kişilerin kimliklerine de ileti gönderilebilir. Bu iletiler her zaman şifrelenip imzalanır ve hedefe ulaşmadan önce ara düğümlerden geçirilir. </p> <p>Onay alındısı gelene kadar uzak iletiler Giden kutusunda kalır.</p> <p>Genel olarak iletiler arkadaşlarınızla dosya bağlantılarını paylaşmak, ağınızı güçlendirmek için arkadaş düğümlerini başka arkadaş düğümlerine önermek ya da bir kanal sahibine geri bildirim göndermek için kullanılabilir.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + - + Starred - Yıldızlı + @@ -15694,7 +14449,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -15708,7 +14463,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -15723,38 +14478,33 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts Taslaklar - + No Box selected. - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - Henüz yıldızlı bir ileti yok. Kolayca ayırt etmek istediğiniz iletilere yıldız ekleyebilirsiniz. Yıldız eklemek için bir iletinin yanındaki açık gri yıldıza tıklayın. - - - No system messages available. - Henüz bir sistem iletisi yok. - - + To - Kime + Kime - Click to sort by to - Alıcıya göre sıralamak için tıklayın - - - This message goes to a distant person. - Bu ileti uzaktaki bir kişiye gönderiliyor. - - - + @@ -15762,26 +14512,6 @@ Do you want to save message ? Total: Toplam: - - Messages - İletiler - - - Click to sort by signature - İmzaya göre sıralamak için tıklayın - - - This message was signed and the signature checks - Bu ileti imzalanmış ve imza denetlenmiş - - - This message was signed but the signature doesn't check - Bu ileti imzalanmış ancak imza denetlenmemiş - - - This message comes from a distant person. - Bu ileti uzak bir kişiden geliyor. - Mail @@ -15809,7 +14539,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + Görseli kaydet + + + + Copy image + + + + Paste as plain text Düz metin olarak yapıştır @@ -15863,7 +14603,7 @@ Do you want to save message ? - + Expand Genişlet @@ -15873,7 +14613,7 @@ Do you want to save message ? Ögeyi Sil - + from kimden @@ -15908,18 +14648,10 @@ Do you want to save message ? Bekleyen İleti - + Hide Gizle - - Send invite? - Çağrı gönderilsin mi? - - - Do you really want send a invite with your Certificate? - Sertifikanız ile bir çağrı göndermek istediğinize emin misiniz? - NATStatus @@ -16057,7 +14789,7 @@ Do you want to save message ? Eş Kodu - + Remove unused keys... Kullanılmayan anahtarları sil... @@ -16067,7 +14799,7 @@ Do you want to save message ? - + Clean keyring Anahtarlığı temizle @@ -16086,7 +14818,13 @@ Notlar: Eski anahtarlığınız yedeklenecek. Aynı bilgisayarda birden çok RetroShare kopyası çalışıyorsa silme işlemi tamamlanamayabilir. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info Anahtarlık bilgileri @@ -16122,18 +14860,13 @@ Güvenlik için anahtarlığınız dosyaya yedeklendi Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. Anahtarlık verileri tutarlı değil. Bu sorun bir hatadan kaynaklanıyor olabilir. Lütfen yazılımı geliştirenler ile görüşün. - - - Export/create a new node - Yeni bir düğüm dışa aktar/oluştur - Trusted keys only Yalnız güvenilen anahtarlar - + Search name Ad Arama @@ -16143,12 +14876,12 @@ Güvenlik için anahtarlığınız dosyaya yedeklendi Eş Kodu Arama - + Profile details... Profil ayrıntıları... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -16157,13 +14890,6 @@ Reported error: Bildirilen hata: - - NetworkPage - - Network - - - NetworkView @@ -16190,7 +14916,7 @@ Bildirilen hata: NewFriendList - + Offline Friends @@ -16211,7 +14937,7 @@ Bildirilen hata: - + Groups Gruplar @@ -16241,19 +14967,19 @@ Bildirilen hata: arkadaş listenizi gruplarla birlikte içe aktarın - - + + Search Arama - + ID Kod - + Search ID @@ -16263,12 +14989,12 @@ Bildirilen hata: - + Show Items Ögeleri Görüntüle - + Last contact @@ -16278,7 +15004,7 @@ Bildirilen hata: IP Adresi - + Group Grup @@ -16393,7 +15119,7 @@ Bildirilen hata: - + Do you want to remove this node? Bu düğümü silmek istiyor musunuz? @@ -16403,7 +15129,7 @@ Bildirilen hata: Bu Arkadaşı silmek istiyor musunuz? - + Done! Tamam! @@ -16517,11 +15243,7 @@ en az bir eş bir gruba eklenemedi NewsFeed - Log entries - Günlük kayıtları - - - + Activity Stream @@ -16536,11 +15258,7 @@ en az bir eş bir gruba eklenemedi Tümünü Kaldır - This is a test. - Bu bir denemedir. - - - + Newest on top Yeniden eskiye @@ -16550,20 +15268,12 @@ en az bir eş bir gruba eklenemedi Eskiden yeniye - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;News Feed</h1> <p>The Log Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel and Forum posts</li> <li>New Channels and Forums you can subscribe to</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Haber Akışı</h1> <p>Haber Akışı ağınızdaki son gelişmeleri aldığınız tarihe göre sıralayarak görüntüler. Bu özellik arkadaşlarınızın yaptığı işlemlerin bir özetini verir. Hangi işlemlerin görüntüleneceğini seçmek için <b>Ayarlar</b> üzerine tıklayabilirsiniz. </p> <p>Seçenekler şunlardır: <ul> <li>Bağlanma girişimleri (yeni kişiler ile arkadaş olmak ve size ulaşmaya çalışanları görmek için)</li> <li>Kanal ve Forum iletileri</li> <li>Abone olabileceğiniz yeni kanal ve forumlar</li> <li>Arkadaşlarınızdan gelen özel iletiler</li> </ul> </p> - - - Log - Haber - - - + Activity @@ -16618,10 +15328,6 @@ en az bir eş bir gruba eklenemedi Blogs Bloglar - - Security - Güvenlik - @@ -16643,10 +15349,6 @@ en az bir eş bir gruba eklenemedi Message İleti - - Connect attempt - Bağlanma girişimi - @@ -16663,10 +15365,6 @@ en az bir eş bir gruba eklenemedi Ip security IP güvenliği - - Log - Haber - Friend Connected @@ -16677,10 +15375,6 @@ en az bir eş bir gruba eklenemedi Circles Çevreler - - Links - Bağlantılar - Activity @@ -16733,26 +15427,6 @@ en az bir eş bir gruba eklenemedi Chat rooms Sohbet odaları - - Chat Rooms - Sohbet Odaları - - - Count occurrences of my current identity - Geçerli kimliğimi içerenler sayılsın - - - Count occurrences of any of the following texts (separate by newlines): - Şu metinlerden herhangi birini içerenler sayılsın (her metni ayrı bir satıra yazın): - - - Checked, if the identity and the text above occurrences must be in the same case to trigger count. - Denetlendi, sayının arttırılması için kimlik ve yukarıdaki metin aynı olmalıdır. - - - Case sensitive - Büyük küçük harfe duyarlı - Position @@ -16828,24 +15502,16 @@ en az bir eş bir gruba eklenemedi Disable All Toaster temporarily Tüm Bildirimleri geçici olarak devre dışı bırak - - Feed - Akış - Systray Sistem Tepsisi - - Count all unread messages - Tüm okunmamış iletiler sayılsın - NotifyQt - + Passphrase required Parola zorunludur @@ -16865,12 +15531,12 @@ en az bir eş bir gruba eklenemedi Parola Yanlış ! - + Please enter your Retroshare passphrase Lütfen RetroShare parolanızı yazın - + Unregistered plugin/executable Kaydedilmemiş eklenti ya da çalıştırılabilir dosya @@ -16885,19 +15551,7 @@ en az bir eş bir gruba eklenemedi Lütfen sistem saatini denetleyin - Examining shared files... - Paylaşılan dosyalar inceleniyor... - - - Hashing file - Dosya karılıyor - - - Saving file index... - Dosya dizini kaydediliyor... - - - + Test Deneme @@ -16908,17 +15562,19 @@ en az bir eş bir gruba eklenemedi + Unknown title Başlık bilinmiyor - + + Encrypted message Şifreli ileti - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). Sohbet odalarının düzgün çalışması için bilgisayarınızın saatinin doğru olması gerekir. Lütfen sorunun bu olup olmadığını denetleyin (arkadaşlarınızla bir kaç dakikalık saat farkınız olabileceği algılandı). @@ -16926,7 +15582,7 @@ en az bir eş bir gruba eklenemedi OnlineToaster - + Friend Online Arkadaş Çevrimiçi @@ -16978,10 +15634,6 @@ Düşük Trafik: %10 standart trafik ve YAPILACAK: tüm dosya aktarımları dura PGPKeyDialog - - Dialog - Pencere - Profile info @@ -17047,10 +15699,6 @@ Düşük Trafik: %10 standart trafik ve YAPILACAK: tüm dosya aktarımları dura This profile has signed your own profile key Bu profil kendi profil anahtarınız ile imzalanmış - - Key signatures : - Anahtar imzaları : - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> @@ -17080,23 +15728,20 @@ p, li { white-space: pre-wrap; } PGP anahtarı - - These options apply to all nodes of the profile: - Bu seçenekler profildeki tüm düğümlere uygulanır: + + Friend options + - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> - <html><head/><body><p><span style=" font-size:10pt;">Bir arkadaşınızın anahtarını imzaladığınızda, diğer arkadaşlarınıza bu arkadaşınıza güvendiğinizi gösterirsiniz. Böylece arkadaşlarınız bu anahtara güvenme durumunuza göre bağlantıları onaylamaya karar verebilir. Anahtar imzalama işlemi isteğe bağlıdır ancak geri alınamaz. Bu nedenle ne yaptığınızdan emin olun.</span></p></body></html> + + These options apply to all nodes of the profile: + Bu seçenekler profildeki tüm düğümlere uygulanır: Keysigning: - - Sign PGP key - PGP anahtarını imzala - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -17133,12 +15778,7 @@ p, li { white-space: pre-wrap; } Imzalar katılsın - - Options - Seçenekler - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> <html><head/><body><p align="justify">RetroShare , doğrudan aktarım yapabilmeniz için düzenli aralıklarla, aktarımlarınızla eşleşen görülebilir dosyalar için arkadaş listenizi kontrol eder. Bu durumda, arkadaşınız dosyayı indirdiğinizi bilebilir.</p><p align="justify">Bu işlemi yalnızca bu arkadaşınız için engellemek istiyorsanız, kutudaki işareti kaldırın. İsterseniz hala açıkca sorarak doğrudan aktarım yapabilirsiniz, Örneğin arkadaşınızın dosya listesinden indirebilirsiniz. Bu ayar aynı düğümdeki tüm konumlara uygulanır.</p></body></html> @@ -17152,10 +15792,6 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this profile (e.g. when the message author is a signed identity that belongs to this profile). This can be used for instance to send files between your own nodes.</p></body></html> - - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> - <html><head/><body><p>Bu seçenek, bu düğümden gelen bir iletide önerilen bir dosyanın otomatik olarak indirilmesini sağlar. Bu işlem örneğin kendi düğümleriniz arasında dosya göndermek gibi amaçlarla kullanılabilir. Aynı düğümdeki tüm konumlara uygulanır.</p></body></html> - Auto-download recommended files from this node @@ -17188,21 +15824,21 @@ p, li { white-space: pre-wrap; } kB/s - - + + RetroShare RetroShare - - + + Error : cannot get peer details. Hata: eş ayrıntıları alınamadı. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) Verilen anahtar algoritmasi RetroShare tarafından desteklenmiyor @@ -17223,7 +15859,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. Güvenilirlik düzeyi bu anahtara güveninizi göstermenin bir yoludur. Yazılım tarafından kullanılmaz ya da paylaşılmaz ancak iyi ve kötü anahtarları anımsamanıza yardımcı olur. @@ -17292,10 +15928,6 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. Check the password! - - Maybe password is wrong - Parola yanlış olabilir - You haven't set a trust level for this key. @@ -17303,12 +15935,12 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. - + Retroshare profile RetroShare profili - + This is your own PGP key, and it is signed by : Bu sizin kendi PGP anahtarınız ve imzalayan : @@ -17334,7 +15966,7 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. PeerItem - + Chat Sohbet @@ -17355,7 +15987,7 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. Ögeyi Sil - + Name: Ad: @@ -17395,7 +16027,7 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. - + Write Message İleti Yaz @@ -17409,10 +16041,6 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. Friend Connected Arkadaş Bağlandı - - Connect Attempt - Bağlantı Girişimi - Connection refused by peer @@ -17451,17 +16079,13 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. Unknown - - Unknown Peer - Bilinmeyen Eş - Hide Gizle - + Send Message İleti Gönder @@ -17513,10 +16137,6 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. Chat with this person as... Bu kişiyle şu kimlikle sohbet et... - - Send message to this person - Bu kişiye ileti gönder - Invite to Circle @@ -17575,10 +16195,6 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. <html><head/><body><p>Anyone in your contact list will automatically have a positive opinion if not set. This allows to automatically raise reputations of used nodes. </p></body></html> <html><head/><body><p>Ayarlanmadığında, kişi listenizdeki herkes olumlu olarak değerlendirilir. Böylece kullanılan düğümlerin değerlendirmesi otomatik olarak yükseltilir. </p></body></html> - - automatically give "Positive" opinion to my contacts - kişilerim otomatik olarak "Olumlu" değerlendirilsin - use "positive" as the default opinion for contacts (instead of neutral) @@ -17636,13 +16252,6 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. <html><head/><body><p>Forum ya da kanal gibi ortamlarda kullanıldıklarından engellenip silinmiş kimliklerin geri gelmesini önlemek için engellenmiş kimlikler bir süre için bir listede tutulur. Bu sürenin sonunda engelleme listesinden &quot;temizlenerek&quot; forum, sohbet odası gibi yerlerde kullanılıyorlarsa yeniden indilrilirler.</p></body></html> - - PhotoCommentItem - - Form - Form - - PhotoDialog @@ -17650,23 +16259,11 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. PhotoShare PhotoShare - - Photo - Fotoğraf - TextLabel Metin Etiketi - - Comment - Yorum - - - Summary - Özet - Album / Photo Name @@ -17727,14 +16324,6 @@ Uyarı: Dosya-Aktarımı ayarlarınızda, doğrudan indirmeye İzin verilmemiş. ... ... - - Add Comment - Yorum Ekle - - - Write a comment... - Yorum yaz... - Album @@ -17805,10 +16394,6 @@ p, li { white-space: pre-wrap; } Create Album Albüm Ekle - - View Album - Albümü Görüntüle - Edit Album Details @@ -17830,17 +16415,17 @@ p, li { white-space: pre-wrap; } Saydam Sunumu - + My Albums Albümlerim - + Subscribed Albums Abone Olunan Albümler - + Shared Albums Paylaşılan Albümler @@ -17870,7 +16455,7 @@ lütfen bir albüm seçin! PhotoSlideShow - + Album Name Albüm Adı @@ -17929,19 +16514,19 @@ lütfen bir albüm seçin! - - + + TextLabel Metin Etiketi - + Posted by - + ago @@ -17977,12 +16562,12 @@ lütfen bir albüm seçin! PluginItem - + TextLabel Metin Etiketi - + Show more details about this plugin Bu uygulama eki ile ilgili ayrıntılı bilgilere bakın @@ -18128,60 +16713,6 @@ p, li { white-space: pre-wrap; } Plugin look-up directories Uygulama eklerinin aranacağı klasörler - - Plugin disabled. Click the enable button and restart Retroshare - Uygulama eki devre dışı. Etkinleştir düğmesine tıklayıp RetroShare yazılımını yeniden başlatın - - - [disabled] - [Devre Dışı] - - - No API number supplied. Please read plugin development manual. - Herhangi bir API numarası belirtilmemiş. Lütfen uygulama eki geliştirme kılavuzunu okuyun. - - - [loading problem] - [yükleme sorunu] - - - No SVN number supplied. Please read plugin development manual. - Herhangi bir SVN numarası belirtilmemiş. Lütfen uygulama eki geliştirme kılavuzunu okuyun. - - - Loading error. - Yükleme hatası. - - - Missing symbol. Wrong version? - Simge eksik. Sürüm yanlış olabilir mi? - - - No plugin object - Herhangi bir uygulama eki nesnesi yok - - - Plugins is loaded. - Uygulama ekleri yüklendi. - - - Unknown status. - Durum bilinmiyor. - - - Check this for developing plugins. They will not -be checked for the hash. However, in normal -times, checking the hash protects you from -malicious behavior of crafted plugins. - Uygulama eki geliştirirken bu seçeneği işaretleyin. -Böylece karma denetimi yapılmaz. Ancak -normal zamanlarda karma denetimi sizi -uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. - - - <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Plugins</h1> <p>Plugins are loaded from the directories listed in the bottom list.</p> <p>For security reasons, accepted plugins load automatically until the main Retroshare executable or the plugin library changes. In such a case, the user needs to confirm them again. After the program is started, you can enable a plugin manually by clicking on the "Enable" button and then restart Retroshare.</p> <p>If you want to develop your own plugins, contact the developpers team they will be happy to help you out!</p> - <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Uygulama&nbsp;Ekleri</h1> <p>Uygulama ekleri aşağıdaki listedeki klasörlerden yüklenir.</p> <p>Güvenlik nedeniyle onaylanmış uygulama ekleri temel RetroShare çalıştırılabilir dosyası ya da uygulama eki kitaplıkları değişene kadar otomatik olarak yüklenir. Bu durumda kullanıcı uygulama eklerini yeniden onaylamalıdır. Bir uygulama ekini el ile etkinleştirmek için "Etkinleştir" düğmesine tıklayıp RetroShare yazılımını yeniden başlatın.</p><p>Kendi uygulama eklerinizi geliştirmek isterseniz, geliştirici ekibiyle görüşebilirsiniz. Size seve seve yardımcı olurlar!</p> - Plugins @@ -18251,12 +16782,27 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Pencere en üstte kalsın - + + Ban this person (Sets negative opinion) + Bu kişiyi engelle (Olumsuz olarak değerlendirir) + + + + Give neutral opinion + Kararsız olarak değerlendir + + + + Give positive opinion + Olumlu olarak değerlendir + + + Choose window color... - + Dock window @@ -18290,22 +16836,6 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Close conversation? - - The person you are talking to has deleted the secured chat tunnel. - Konuştuğunuz kişi güvenli sohbet tünelini silmiş. - - - The chat partner deleted the secure tunnel, messages will be delivered as soon as possible - Sohbet eşiniz güvenli tüneli kaldırmış, iletileriniz en kısa zamanda gönderilecektir - - - Closing this window will end the conversation, notify the peer and remove the encrypted tunnel. - Bu pencereyi kapatmak görüşmenizi sona erdirerek, eşinizi bilgilendirir ve şifrelenmiş tüneli kaldırır. - - - Kill the tunnel? - Tünel kapatılsın mı? - PostedCardView @@ -18325,7 +16855,7 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Yeni - + Vote up Beğendim @@ -18345,8 +16875,8 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. \/ - - + + Comments Yorumlar @@ -18371,13 +16901,13 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. - - + + Comment - + Comments Yorumlar @@ -18405,20 +16935,12 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. PostedCreatePostDialog - Signed by: - İmzalayan: - - - Notes - Notlar - - - + Create a new Post - + RetroShare RetroShare @@ -18433,12 +16955,22 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File Görsel Dosyası Yükle - + Post image @@ -18454,7 +16986,17 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -18464,23 +17006,7 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. - Submit Post - İleti Gönder - - - You are submitting a link. The key to a successful submission is interesting content and a descriptive title. - Bir bağlantı gönderiyorsunuz. Başarılı bir gönderinin sırrı ilginç bir içerik ve açıklayıcı bir başlıktır. - - - Submit - Gönder - - - Submit a new Post - Yeni bir ileti gönder - - - + Please add a Title Lütfen bir başlık ekleyin @@ -18500,12 +17026,22 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -18520,7 +17056,7 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Şu olarak gönder - + Post @@ -18531,7 +17067,7 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Görsel - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -18541,7 +17077,7 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Başlık - + Link Bağlantı @@ -18549,44 +17085,12 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. PostedDialog - Posted Links - Gönderilen Bağlantılar - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Posted</h1> <p>The posted service allows you to share internet links, that spread among Retroshare nodes like forums and channels</p> <p>Links can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Posted links are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Gönderilen</h1> <p>Gönderilen hizmeti İnternet bağlantılarının forum ve kanalllar gibi RetroShare düğümleri üzerinden paylaşılmasını sağlar</p> <p>Bağlantılara abone olan kullanıcılar tarafından yorum yapılabilir. Bir değerlendirme sistemi sayesinde önemli bağlantılar vurgulanabilir.</p> <p>Paylaşılacak bağlantılarla ilgili bir kısıtlama yoktur. Bu nedenle bağlantıları açarken dikkatli olun.</p> <p>Başka şekilde ayarlamadıysanız, gönderilen bağlantılar %1 gün saklanır ve son %2 gündeki iletiler eşitlenir.</p> - - - Create Topic - Başlık Ekle - - - My Topics - Başlıklarım - - - Subscribed Topics - Abone Olunmuş Başlıklar - - - Popular Topics - Beğenilen Başlıklar - - - Other Topics - Diğer Başlıklar - - - Links - Bağlantılar - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -18620,31 +17124,7 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. PostedGroupDialog - Posted Topic - Gönderilen Konu - - - Add Topic Admins - Konu Yöneticisi Ekle - - - Select Topic Admins - Konu Yöneticilerini Seçin - - - Create New Topic - Yeni Konu Ekle - - - Edit Topic - Konuyu Düzenle - - - Update Topic - Konuyu Güncelle - - - + Create New Board @@ -18682,7 +17162,17 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. PostedGroupItem - + + Last activity + + + + + TextLabel + Metin Etiketi + + + Subscribe to Posted Gönderilenlere Abone Ol @@ -18698,7 +17188,7 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. - + Expand Genişlet @@ -18713,24 +17203,17 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. - Posted Description - Gönderilen Açıklaması - - - Loading - Yükleniyor - - - New Posted - Gönderilen Ekle - - - + Loading... - + + Never + Hiç + + + New Board @@ -18743,22 +17226,18 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. PostedItem - + 0 0 - Site - Site - - - - + + Comments Yorumlar - + Copy RetroShare Link @@ -18769,12 +17248,12 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. - + Comment Yorum yapın - + Comments Yorumlar @@ -18784,7 +17263,7 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. <p><font color="#ff0000"><b>Bu iletinin yazarı (%1 kodlu) engellendi.</b> - + Click to view Picture @@ -18794,21 +17273,17 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Gizle - + Vote up Beğendim - + Vote down Beğenmedim - \/ - \/ - - - + Set as read and remove item Okunmuş olarak işaretle ve ögeyi sil @@ -18818,7 +17293,7 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Yeni - + New Comment: Yeni Yorum: @@ -18828,7 +17303,7 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Yorum Değeri - + Name Ad @@ -18869,77 +17344,10 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Metin Etiketi - + Loading Yükleniyor - - By - Gönderen - - - - PostedListWidget - - Form - Form - - - Hot - Sıcak - - - New - Yeni - - - Top - Beğenilen - - - Today - Bügün - - - Yesterday - Dün - - - This Week - Bu Hafta - - - This Month - Bu Ay - - - This Year - Bu Yil - - - Submit a new Post - Yeni bir ileti gönder - - - Next - Sonraki - - - RetroShare - RetroShare - - - Please create or choose a Signing Id before Voting - Lütfen oylamadan önce bir imzalayan kimliği oluşturun ya da seçin - - - Previous - Önceki - - - 1-10 - 1-10 - PostedListWidgetWithModel @@ -18959,7 +17367,17 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -18969,15 +17387,15 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Yönetici: - + - + unknown - + Distribution: Dağıtım: @@ -18987,42 +17405,42 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. - + Created - + TextLabel Metin Etiketi - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts İletiler - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -19042,7 +17460,7 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Sıcak - + Search Arama @@ -19072,17 +17490,17 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -19097,12 +17515,17 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -19112,34 +17535,38 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Düzenle - + + information bilgiler - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] Subscribed - + Abone @@ -19147,7 +17574,7 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Abone Ol - + Never Hiç @@ -19194,7 +17621,7 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Public - + Herkese Açık @@ -19221,6 +17648,16 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. No Channel Selected Bir Kanal Seçilmemiş + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -19229,14 +17666,6 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Tabs Sekmeler - - Open each topic in a new tab - Her konu yeni bir sekmede açılsın - - - Links - Bağlantılar - Open each board in a new tab @@ -19250,10 +17679,6 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. PostedUserNotify - - Posted - Gönderilme - Board Post @@ -19322,16 +17747,16 @@ uygulama eklerinde bulunabilecek zararlı yazılımlardan korur. Profil Yönetimi - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -19443,7 +17868,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz ProfileWidget - + Edit status message Durum iletisini düzenle @@ -19459,7 +17884,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz Profil Yönetimi - + Public Information Genel Bilgiler @@ -19494,12 +17919,12 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz Çevrimiçi süresi: - + Other Information Diğer Bilgiler - + My Address Adresim @@ -19543,51 +17968,27 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz PulseAddDialog - Post From: - Şu Hesapla Gönderilsin: - - - Account 1 - 1. Hesap - - - Account 2 - 2. Hesap - - - Account 3 - 3. Hesap - - - + Add to Pulse Pulse üzerine ekle - filter - süzgeç - - - URL Adder - Adres Ekleyici - - - + Display As Şu Şekilde Görüntüle - + URL Adres - + GroupLabel - + IDLabel @@ -19597,12 +17998,12 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz Kimden: - + Head - + Head Shot @@ -19632,13 +18033,13 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz Olumsuz - - + + Whats happening? - + @@ -19650,12 +18051,22 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -19664,17 +18075,13 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz Cancel İptal - - Post Pulse to Wire - Pulse Wire Üzerine Gönder - Post - + Reply to Pulse @@ -19689,34 +18096,24 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - Kimden - - - Date - Tarih - - - ... - ... + + Load Picture File + Görsel Dosyası Yükle @@ -19727,7 +18124,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz Form - + @@ -19746,7 +18143,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz PulseReply - + icn @@ -19756,7 +18153,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz - + REPLY @@ -19783,7 +18180,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz - + FOLLOW @@ -19793,7 +18190,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -19813,7 +18210,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -19929,7 +18326,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz - + FOLLOW @@ -19937,37 +18334,42 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -19999,7 +18401,7 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz - + FOLLOW @@ -20007,8 +18409,8 @@ Kimliği İçe Aktar düğmesine tıklayarak yükleyebilirsiniz QObject - - + + Confirmation Onaylama @@ -20279,12 +18681,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace Eş ayrıntıları - + File Request canceled Dosya isteği iptal edildi - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. Bu RetroShare sürümü OpenPGP-SDK kullanır. Bu nedenle sistem paylaşımlı PGP anahtarlığını kullanamaz, ama çalışan tüm RetroShare kopyaları ile paylaşılan kendi anahtarlığı bulunur.<br><br>Büyük olasılıkla uygulamanın yeni sürümüne henüz geçtiğiniz için, var olan RetroShare hesaplarında PGP anahtarlarının olduğu anılmasına rağmen, böyle bir anahtarlığınız yok gibi görünüyor. @@ -20315,7 +18717,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace Beklenmeyen bir sorun çıktı. Lütfen 'RsInit::InitRetroShare beklenmeyen dönüş kodu %1' hatasını bildirin. - + Cannot start Tor Manager! @@ -20349,7 +18751,7 @@ The error reported is:" - + Multiple instances Birden çok kopya @@ -20371,6 +18773,26 @@ Kilit dosyası: Kilit dosyası: + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -20453,7 +18875,7 @@ Bildirilen hata: Veri iletilen - + You appear to have nodes associated to DSA keys: DSA anahtarlarıyla ilişkili düğümleriniz var gibi görünüyor: @@ -20463,7 +18885,7 @@ Bildirilen hata: Bu RetroShare sürümü henüz DSA anahtarlarını desteklenmiyor. Tüm bu düğümler kullanılamayacak. Bunun için çok üzgünüz. - + enabled etkin @@ -20473,7 +18895,7 @@ Bildirilen hata: devre dışı - + Move IP %1 to whitelist %1 IP adresini beyaz listeye taşı @@ -20489,7 +18911,7 @@ Bildirilen hata: - + %1 seconds ago %1 saniye önce @@ -20557,7 +18979,7 @@ Security: no anonymous IDs Güvenlik: İsimsiz kodlar kullanılamaz - + Join chat room Sohbet odasına katıl @@ -20585,7 +19007,7 @@ Güvenlik: İsimsiz kodlar kullanılamaz XML dosyası işlenemedi! - + Indefinitely Süresiz @@ -20765,13 +19187,29 @@ Güvenlik: İsimsiz kodlar kullanılamaz Ban list + + + Name + Ad + + Node + Düğüm + + + + Address + + + + + Status Durum - + NXS @@ -20964,10 +19402,6 @@ Güvenlik: İsimsiz kodlar kullanılamaz Click to resume the hashing process - - <p>This certificate contains: - <p>Bu sertifikanın içeriği: - Idle @@ -21018,6 +19452,18 @@ Güvenlik: İsimsiz kodlar kullanılamaz Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -21180,7 +19626,7 @@ p, li { white-space: pre-wrap; } - + Network Wide Tüm Ağda @@ -21363,7 +19809,7 @@ p, li { white-space: pre-wrap; } Form - + The loading of embedded images is blocked. Gömülü görsellerin yüklenmesi engellenmiş. @@ -21376,7 +19822,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default Varsayılan olarak onaylandı @@ -21549,12 +19995,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + Görseli kaydet + + + + Copy image + + + + Document source @@ -21562,12 +20018,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options Ağaç Görünümü Ayarları - + Show Header @@ -21597,14 +20053,6 @@ p, li { white-space: pre-wrap; } Show column … - - Show column... - Görüntülenecek sütun... - - - [no title] - [başlık yok] - RatesStatus @@ -22267,7 +20715,7 @@ Dosyanın doğru olduğunu düşünüyorsanız bu satırı silerek dosyayı Retr RsDownloadListModel - + Name i.e: file name Ad @@ -22388,7 +20836,7 @@ Dosyanın doğru olduğunu düşünüyorsanız bu satırı silerek dosyayı Retr RsFriendListModel - + Name Ad @@ -22408,7 +20856,7 @@ Dosyanın doğru olduğunu düşünüyorsanız bu satırı silerek dosyayı Retr IP Adresi - + Profile ID @@ -22467,7 +20915,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: İleti arkadaşlarınıza iletilecek. - + [ ... Redacted message ... ] [ ... Düzeltilmiş İleti ... ] @@ -22481,11 +20929,6 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: [Unknown] [Bilinmiyor] - - - [ ... Missing Message ... ] - [... İleti Eksik ... ] - RsMessageModel @@ -22499,6 +20942,11 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: From Kimden + + + To + + Subject @@ -22521,13 +20969,18 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - Click to sort by read - Okunmuş durumuna göre sıralamak için tıklayın + Click to sort by read status + - Click to sort by from - Gönderene göre sıralamak için tıklayın + Click to sort by author + + + + + Click to sort by destination + @@ -22550,7 +21003,9 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - + + + [Notification] @@ -22571,7 +21026,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Rshare - + Resets ALL stored RetroShare settings. TÜM RetroShare ayarlarını sıfırlar. @@ -22632,7 +21087,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: RetroShare arayüz dilini ayarlar. - + Unable to open log file '%1': %2 '%1':%2 günlük dosyası açılamadı @@ -22653,11 +21108,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Veri klasörü oluşturulamadı: %1 - Revision - Değişiklik - - - + opmode @@ -22687,7 +21138,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - + Invalid language code specified: Belirtilen dil kodu geçersiz: @@ -22705,7 +21156,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: RshareSettings - + Registry Access Error. Maybe you need Administrator right. Kayıt Defterine Erişim Hatası. Yönetici izinleri gerekiyor olabilir. @@ -22722,12 +21173,12 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: SearchDialog - + Enter a keyword here (at least 3 char long) Buraya bir anahtar sözcük yazın (en az 3 karakter uzunluğunda) - + Start Search Aramayı Başlat @@ -22789,7 +21240,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Temizle - + KeyWords Anahtar Sözcükler @@ -22804,7 +21255,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Kod Arama - + Filename Dosya Adı @@ -22904,23 +21355,23 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Seçilmişleri indir - + File Name Dosya Adı - + Download Indir - + Copy RetroShare Link RetroShare Bağlantısını Kopyala - + Send RetroShare Link RetroShare Bağlantısını Gönder @@ -22930,7 +21381,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - + Download Notice İndirme Bildirimi @@ -22967,7 +21418,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Tümünü Kaldır - + Folder Klasör @@ -22978,17 +21429,17 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - + New RetroShare Link(s) Yeni RetroShare Bağlantıları - + Open Folder Klasör Aç - + Create Collection... Derleme Oluştur... @@ -23008,7 +21459,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Derleme dosyasından indir... - + Collection Derleme @@ -23016,7 +21467,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: SecurityIpItem - + Peer details Eş ayrıntıları @@ -23032,22 +21483,22 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Ögeyi Sil - + IP address: IP Adresi: - + Peer ID: Eş Kodu: - + Location: Konum: - + Peer Name: Eş Adı: @@ -23064,7 +21515,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Gizle - + but reported: ancak bildirilen: @@ -23089,8 +21540,8 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: <p>Arkadaşınız bu IP adresine bağlanmak istiyor. IP adresini yeni değiştirdiyseniz bu uyarıyı dikkate almayın. IP adresini değiştirmediyseniz aradaki bir eş tarafından bu arkadaşınıza şüpheli bir IP adresi gönderiliyor olabilir.</p> - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> <html><head/> <body><p>Bu uyarı sizi trafik iletme saldırılarına karşı korumayı amaçlıyor. Böyle bir durumda, bağlı olduğunuz arkadaşınız dış IP adresiniz yerine saldırganın IP adresini görür. </p> <p><br/></p> <p>Bununla birlikte, bir nedenle IP adreslerini değiştirdiyseniz (Bazı hizmet sağlayıcılar düzenli olarak IP adreslerini değiştirir), bu uyarı size yalnızca RetroShare farketmeden önce bir arkadaşınıza yeni bir IP adresi ile bağlandığınızı belirtir. Bu durumda bir sorun yoktur.</p> <p><br/></p> <p>Kendi IP adreslerinizi beyaz listeye ekleyerek (örneğin, hizmet sağlayıcınızın IP adresi aralığını) hatalı uyarıları gizleyebilir ya da Ayarlar-&gt;Bildirim-&gt;Haber Akışı bölümünden tamamen devre dışı bırakabilirsiniz.</p></body></html> @@ -23098,7 +21549,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: SecurityItem - + wants to be friend with you on RetroShare RetroShare üzerinde arkadaşınız olmak istiyor @@ -23129,7 +21580,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - + Expand Genişlet @@ -23174,12 +21625,12 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Durum: - + Write Message İleti Yaz - + Connect Attempt Bağlantı Girişimi @@ -23199,17 +21650,22 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Bilinmeyen (Giden) Bağlantı İsteği - + Unknown Security Issue Bilinmeyen Güvenlik Sorunu - - A unknown peer + + SSL request - + + An unknown peer + + + + Unknown @@ -23219,11 +21675,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - Unknown Peer - Bilinmeyen Eş - - - + Hide Gizle @@ -23233,7 +21685,7 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Bu Arkadaşı silmek istiyor musunuz? - + Certificate has wrong signature!! This peer is not who he claims to be. Sertifika imzası yanlış!! Bu eş, olduğunu iddia ettiği kişi değil. @@ -23243,12 +21695,12 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Eksik/Bozuk sertifika. Kullanıcı gerçek bir RetroShare kullanıcısı değil. - + Certificate caused an internal error. Sertifika içeride bir soruna yol açtı. - + Peer/node not in friendlist (PGP id= Eş/Düğüm arkadaş listesinde değil (PGP kodu= @@ -23307,12 +21759,12 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: - + Local Address Yerel Adres - + NAT @@ -23333,22 +21785,22 @@ arkadaşlarınız da olumlu olarak değerlendirmemiş: Kapı: - + Local network Yerel ağ - + External ip address finder Dış IP adres bulucu - + UPnP UPnP - + Known / Previous IPs: Bilinen / Önceki IP Adresleri: @@ -23365,21 +21817,16 @@ Ayrıca güvenlik duvarı ya da VPN bağlantısı kullanıyorsanız da yardımcı olur. - - Allow RetroShare to ask my ip to these websites: - RetroShare IP adresinizi şu sitelere sorabilsin: - - - - - + + + kB/s kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. Kullanılabilecek kapı numaraları 10 ile 65535 arasındadır. Normal olarak 1024 altındaki kapı numaraları sistem kullanımına ayrılmıştır. @@ -23389,23 +21836,46 @@ yardımcı olur. Kullanılabilecek kapı numaraları 10 ile 65535 arasındadır. Normal olarak 1024 altındaki kapı numaraları sistem kullanımına ayrılmıştır. - + Onion Address Onion Adresi - + Discovery On (recommended) Keşif Açık (Önerilir) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off Keşif Kapalı @@ -23415,7 +21885,7 @@ yardımcı olur. Gizli - Yapılandırmaya Bakın - + I2P Address I2P Adresi @@ -23440,37 +21910,95 @@ yardımcı olur. geliş tamam - - + + + Proxy seems to work. Vekil sunucu çalışıyor görünüyor. - + + I2P proxy is not enabled I2P vekil sunucusu etkinleştirilmemiş - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -23485,71 +22013,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -23559,22 +22023,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. Gizli bir hizmet üzerinden ulaşılabiliyorsunuz. @@ -23588,12 +22037,12 @@ Tüm hizmetler düzgün çalışıyor mu?? Ayrıca kapı ayarlarınızı da denetleyin! - + [Hidden mode] [Gizli Kip] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> <html><head/><body><p>Bu işlem bilinen adresler listesini temizler. Böylece adres listenizde olabilecek herhangi bir nedenle geçersiz/ilgisiz/süresi geçmiş adreslerin kişi adresi olarak arkadaşlarınıza bildirilmesi engellenir.</p></body></html> @@ -23603,7 +22052,7 @@ Ayrıca kapı ayarlarınızı da denetleyin! Temizle - + Download limit (KB/s) İndirme sınırı (KB/s) @@ -23618,23 +22067,23 @@ Ayrıca kapı ayarlarınızı da denetleyin! Yükleme sınırı (KB/s) - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> <html><head/><body><p>Yükleme sınırı tüm uygulamayı kapsar. Yükleme sınırı çok küçük olursa düşük öncelikli hizmetler engellenebilir (forumlar, kanallar). Önerilen en küçük değer: 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -23645,17 +22094,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -23665,12 +22104,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -23680,17 +22114,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 127.0.0.1 - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -23730,7 +22154,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start Başlat @@ -23745,12 +22169,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why Durdur - - BOB status - - - - + Incoming Gelen @@ -23786,7 +22205,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay Aktarıcı @@ -23841,7 +22285,7 @@ If you have issues connecting over Tor check the Tor logs too. Toplam: - + Warning: This bandwidth adds up to the max bandwidth. @@ -23866,7 +22310,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -23878,7 +22322,7 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Filters IP Süzgeçleri @@ -23901,7 +22345,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status Durum @@ -23961,17 +22405,28 @@ If you have issues connecting over Tor check the Tor logs too. Beyaz listeye ekle - + Hidden Service Configuration Gizli Hizmet Yapılandırması - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>Tor Socks vekil sunucusunun kapı numarası. RetroShare düğümünüz bu kapıyı kullanarak</p><p>Gizli düğümlere bağlanabilir. Bilgisayarınızda bu kapı etkinleştiğinde sağdaki LED yeşile döner. </p><p>Bununla birlikte bu durum RetroShare trafiğinizin Tor üzerinden aktığı anlamına gelmez. Tor üzerinden veri akışı yalnız </p><p>Gizli düğümlere bağlandığınızda ya da Gizli bir düğüm çalıştırıyorsanız gerçekleşir.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>Bilgisayarınızda soldaki kapı dinlemesi etkinleştiğinde bu LED yeşile döner. </p><p>Bununla birlikte bu durum RetroShare trafiğinizin Tor üzerinden aktığı anlamına gelmez. Tor üzerinden veri akışı yalnız </p><p>Gizli düğümlere bağlandığınızda ya da Gizli bir düğüm çalıştırıyorsanız gerçekleşir.</p></body></html> @@ -23987,18 +22442,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>Bilgisayarınızda soldaki kapı dinlemesi etkinleştiğinde bu LED yeşile döner. </p><p>Bununla birlikte bu durum RetroShare trafiğinizin I2P üzerinden aktığı anlamına gelmez. I2P üzerinden veri akışı yalnız </p><p>Gizli düğümlere bağlandığınızda ya da Gizli bir düğüm çalıştırıyorsanız gerçekleşir.</p></body></html> - + I2P outgoing Okay I2P gidiş tamam - + Service Address Hizmet Adresi @@ -24033,12 +22488,12 @@ If you have issues connecting over Tor check the Tor logs too. Lütfen bir hizmet adresi yazın - + IP Range IP Aralığı - + Reported by DHT for IP masquerading DHT tarafından IP maskelemesi için bildirildi @@ -24061,22 +22516,22 @@ If you have issues connecting over Tor check the Tor logs too. Sizin eklediğiniz - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> <html><head/><body><p>Beyaz listeye IP adresleri şu kaynaklardan toplanır: El ile değiş tokuş edilmiş bir sertifika ile gelen IP adresleri, bu bölümden el ile yazılan ya da güvenlik akışı ögelerinden alınan IP adresi aralıkları.</p><p>RetroShare varsayılan olarak (1) IP adresi beyaz listede bulunan eşlerle bağlantıya kara listede bulunsalar bile her zaman izin verir; (2) isteğe bağlı olarak IP adreslerinin beyaz listede bulunması gerekir. Bu davranış her bir eş için RetroShare düğümlerinin &quot;Ayrıntılar&quot; penceresinden değiştirilebilir. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> <html><head/><body><p>DHT, Bittorrent DHT özelliğini kullanan arkadaşlarınızdan gelen bağlantı isteklerini yanıtlamanızı sağlayarak bağlanabilirliği büyük ölçüde arttırır. DHT üzerinde herhangi bir veri saklanmaz. Yalnızca diğer RetroShrare düğümleri ile iletişim kurmak için bir vekil sistem olarak kullanılır.</p><p>Keşif hizmeti, güvendiğiniz kişilerin düğüm adı ve kodunu bağlı olduğunuz eşlere ileterek yeni arkadaşlar edinmelerine yardımcı olur. Asla otomatik olarak arkadaşlık kurulmaz. İki eşin bağlanabilmesi için birbirlerine karşılıklı olarak güvenmeleri gerekir. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> <html><head/><body><p>Bu işlem etkinleştirildiğinde, aşağıdaki web sitelerinden kendi IP adresinizi aldığınızda RetroShare bu imi yeşile döndürür. RetroShare kendi IP adresinizi bulmak için başka yöntemler de kullanır.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> <html><head/><body><p>Bu liste çeşitli kaynaklardan toplanan bilgiler ile otomatik olarak doldurulur: DHT tarafından bildirilen maskelenmiş eşler, sizin yazdığınız IP aralıkları ve arkadaşlarınız tarafından bildirilen IP aralıkları. Varsayılan ayarlar sizi büyük ölçekli trafik aktarımlarına karşı korur.</p><p>Maskelenmiş IP adreslerinin otomatik olarak öngörülmesi yüzünden arkadaşlarınızın IP adresleri kara listeye eklenebilir. Bu durumda bu IP adreslerini beyaz listeye eklemek için sağ tıklayın.</p></body></html> @@ -24111,7 +22566,7 @@ If you have issues connecting over Tor check the Tor logs too. Şuradan başlayan DHT maskeleme IP adresleri otomatik engellensin - + Outgoing Manual Tor/I2P @@ -24121,12 +22576,12 @@ If you have issues connecting over Tor check the Tor logs too. Tor Socks Vekil Sunucusu - + Tor outgoing Okay Tor gidiş tamam - + Tor proxy is not enabled Tor vekil sunucusu etkinleştirilmemiş @@ -24206,7 +22661,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with özel yayın anahtarınızı paylaşacağınız eşleri seçin @@ -24216,12 +22671,12 @@ If you have issues connecting over Tor check the Tor logs too. Arkadaşla Paylaş - + Share Paylaş - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. Kanalınızı paylaşarak arkadaşlarınıza bildirebilirsiniz. @@ -24241,7 +22696,7 @@ Kanalınızı paylaşmak istediğiniz Arkadaşlarınızı seçin. Paylaşılan Klasör Yönetimi - + Shared directory Paylaşılan klasör @@ -24261,17 +22716,17 @@ Kanalınızı paylaşmak istediğiniz Arkadaşlarınızı seçin. Görünürlük - + Add new Yeni ekle - + Cancel İptal - + Add a Share Directory Paylaşım Klasörü Ekle @@ -24281,7 +22736,7 @@ Kanalınızı paylaşmak istediğiniz Arkadaşlarınızı seçin. Sil - + Apply and close Uygula ve kapat @@ -24372,7 +22827,7 @@ Kanalınızı paylaşmak istediğiniz Arkadaşlarınızı seçin. Klasör bulunamadı ya da klasör adı kabul edilmiyor. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. Paylaşılan klasörlerin listesi. Alttaki düğmeleri kullanarak klasörler ekleyip çıkarabilirsiniz. Yeni bir klasörü ilk kez eklediğinizde, bu klasördeki tüm dosyalar paylaşılır. Ardından paylaşılan her klasör için ayrı ayrı paylaşım işaretlerini ayarlayabilirsiniz. @@ -24380,7 +22835,7 @@ Kanalınızı paylaşmak istediğiniz Arkadaşlarınızı seçin. SharedFilesDialog - + Files Dosyalar @@ -24431,11 +22886,16 @@ Kanalınızı paylaşmak istediğiniz Arkadaşlarınızı seçin. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files dosyaları seçin - + Download selected Seçilmişleri indir @@ -24445,7 +22905,7 @@ Kanalınızı paylaşmak istediğiniz Arkadaşlarınızı seçin. İndir - + Copy retroshare Links to Clipboard RetroShare Bağlantılarını Panoya Kopyala @@ -24460,7 +22920,7 @@ Kanalınızı paylaşmak istediğiniz Arkadaşlarınızı seçin. RetroShare Bağlantılarını Gönder - + Some files have been omitted Bazı dosyalar yok sayıldı @@ -24476,7 +22936,7 @@ Kanalınızı paylaşmak istediğiniz Arkadaşlarınızı seçin. Öneriler - + Create Collection... Derleme Ekle... @@ -24501,7 +22961,7 @@ Kanalınızı paylaşmak istediğiniz Arkadaşlarınızı seçin. Derleme dosyasından indir... - + Some files have been omitted because they have not been indexed yet. @@ -24644,12 +23104,12 @@ Kanalınızı paylaşmak istediğiniz Arkadaşlarınızı seçin. SplashScreen - + Load configuration Yapılandırmayı yükle - + Create interface Arayüz ekle @@ -24673,7 +23133,7 @@ Kanalınızı paylaşmak istediğiniz Arkadaşlarınızı seçin. Parolam Hatırlansın - + Log In Oturum Aç @@ -25026,7 +23486,7 @@ Bu seçim ayarlardan değiştirilebilir. Durum iletisi - + Message: İleti: @@ -25271,7 +23731,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags Tüm Etiketleri Kaldır @@ -25307,12 +23767,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown Bilinmiyor @@ -25322,18 +23785,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -25343,12 +23801,57 @@ p, li { white-space: pre-wrap; } - + + Error + Hata + + + + Not connected + Bağlı değil + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -25356,7 +23859,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -25366,7 +23869,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -25377,11 +23880,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -25409,7 +23913,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options Aktarım Ayarları @@ -25420,7 +23924,7 @@ p, li { white-space: pre-wrap; } Aynı anda en çok indirme sayısı: - + Shared Directories Paylaşılan Klasörler @@ -25430,22 +23934,27 @@ p, li { white-space: pre-wrap; } Gelen klasörü otomatik olarak paylaşılsın (Önerilir) - - Edit Share - Paylaşımı Düzenle - - - + Directories - + + Configure shared directories + Paylaşılan klasörleri yapılandır + + + Auto-check shared directories every Paylaşılan klasörler şu aralıkla denetlensin + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) dakika @@ -25530,7 +24039,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -25539,7 +24048,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -25564,7 +24078,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming Akış @@ -25623,38 +24142,13 @@ p, li { white-space: pre-wrap; } Trust friend nodes with banned files - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> arkadaşlar arasında yapılmasına gerek olmayan veri ve arama isteklerini aktarımlarını eşler arasında yapabilir. Bu trafikte yalnız bağlantılı arkadaş listesi bulunur ve isimsizdir.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Paylaşılan her bir klasör için paylaşım işaretleri paylaşılan dosyalar penceresinden ayarlanabilir :</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Arkadaşlar gözatabilir</span>: Bu dosyaları yalnız arkadaşlarınız görebilir.</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">İsimsiz olarak paylaşılan</span>: Bu dosyalara uzak F2F tünelleri üzerinden isimsiz olarak erişilebilir.</li></ul></body></html> - Max. tunnel req. forwarded per second: Saniyede iletilecek en fazla tünel isteği sayısı: - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - <html><head/><body><p><span style=" font-weight:600;">Akış </span>artan sırada, önizlemeye izin verecek şekilde 1MB boyutlu dosya parçaları aktarımının istenmesine neden olur. <span style=" font-weight:600;">Rastgele</span> Tümüyle rastgeledir ve kaynaşmaya yönelik davranır. <span style=" font-weight:600;">Gelişen</span> Ortalama çözüm. dosya parçasının sonundaki 50MB bölümden rastgele seçilir. Böylece büyük boş dosya hazırlama süresini beklemeden biraz rastlantısallık sağlanır.</p></body></html> - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> <html><head/><body><p>Boş disk alanı bu sınırın altına inerse RetroShare tüm aktarımları ve yapılandırma dosyası kayıtlarını durdurur. Böylece bazı sistemlerde oluşabilecek veri kayıpları engellenir. Gerçekleşirse bu durum açılan bir pencere ile bildirilir.</p></body></html> @@ -25664,7 +24158,17 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Bu değer saniyede iletilebilecek tünel isteği sayısını belirler. </p><p>İnternet bağlantı hızınız yüksek ise, durağan olarak daha uzun tünellerin geçişine izin vermek için bu değeri 30-40 yapabilirsiniz. Bu işlem çok sayıda küçük paket oluşturarak kendi dosya aktarımınızı yavaşlatabileceğinden çok dikkatli olun. </p><p>Varsayılan değer: 20. Emin değilseniz böyle bırakın.</p></body></html> - + + Warning + Uyarı + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory Gelen Klasörünü Ayarla @@ -25692,7 +24196,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed İndirme tamamlandı @@ -25716,39 +24220,23 @@ p, li { white-space: pre-wrap; } %1 completed transfer - - You have %1 completed downloads - %1 dosya indirildi - - - You have %1 completed download - %1 dosya indirildi - - - %1 completed downloads - %1 dosya indirildi - - - %1 completed download - %1 dosya indirildi - TransfersDialog - - + + Downloads İndirmeler - + Uploads Yüklemeler - + Name i.e: file name Ad @@ -25955,11 +24443,7 @@ p, li { white-space: pre-wrap; } Belirtin... - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1> <p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p> <p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p> <p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Dosya Aktarımı</h1> <p>RetroShare iki şekilde dosya aktarımı sunar: Arkadaşlarınızdan doğrudan aktarım ve uzak isimsiz tünel aktarımı. Ek olarak, dosya aktarımı birden çok kaynak kullanabilir ve karşılıklıdır (indirme yapılırken yükleme de yapılır)</p> <p>Sol yan çubuktaki <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> simgesini kullanarak dosyaları paylaşabilirsiniz. Paylaşılan dosyalar Dosyalarım sekmesi altında görüntülenir. Her bir arkadaş grubunuzun bu dosyaları kendi Arkadaşların Dosyaları sekmelerinde görüp görümeyeceğini seçebilirsiniz.</p> <p>Arama sekmesi arkadaşlarınızın dosya listelerinde arama yapar ve birden çok sıçramalı tünel sistemi üzerinden uzak dosyalara isimsiz olarak erişebilir.</p> - - - + Move in Queue... Kuyrukta Taşı... @@ -25984,7 +24468,7 @@ p, li { white-space: pre-wrap; } Klasör seçin - + Anonymous end-to-end encrypted tunnel 0x İsimsiz uçtan uca şifrelenmiş tünel 0x @@ -26005,7 +24489,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -26038,7 +24522,17 @@ p, li { white-space: pre-wrap; } %1 dosyası tamamlanmamış. Bu bir ortam dosyası ise önizlemeyi deneyin. - + + Warning + Uyarı + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name Dosya adını değiştir @@ -26053,7 +24547,7 @@ p, li { white-space: pre-wrap; } Lütfen yeni -ve geçerli- bir dosya adı yazın - + Expand all Tümünü genişlet @@ -26180,23 +24674,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns Sütunlar - + File Transfers Dosya Aktarımları - + Path Yol @@ -26206,7 +24695,7 @@ p, li { white-space: pre-wrap; } Yol Sütunu Görüntülensin - + Could not delete preview file Önizleme dosyası silinemedi @@ -26216,7 +24705,7 @@ p, li { white-space: pre-wrap; } Yeniden denensin mi? - + Create Collection... Derleme Ekle... @@ -26231,7 +24720,12 @@ p, li { white-space: pre-wrap; } Derlemeyi Görüntüle... - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Collection Derleme @@ -26241,7 +24735,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x İsimsiz tünel 0x @@ -26462,10 +24956,6 @@ p, li { white-space: pre-wrap; } File transfer tunnels - - Anonymous tunnels - İsimsiz tüneller - Authenticated tunnels @@ -26659,12 +25149,17 @@ p, li { white-space: pre-wrap; } Form - + Enable Retroshare WEB Interface RetroShare Web arayüzü kullanılsın - + + Status: + Durum: + + + Web parameters Web parametreleri @@ -26704,17 +25199,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Web Arayüzü</h1> <p>Web arayüzü ile RetroShare web tarayıcı üzerinden kullanılabilir. Birden çok aygıt bir RetroShare kopyası üzerinden denetlenebilir. Böylece bir tablet üzerinden başlattığınız sohbeti masaüstü bilgisayar üzerinden sürdürebilirsiniz.</p> <p>Uyarı: Erişim denetimi ve şifreleme olmadığından, web arayüzünü İnternet üzerine açmayın. Web arayüzünü İnternet üzerinden kullanmak istiyorsanız bağlantı güvenliğini sağlamak için bir SSH tüneli ya da vekil sunucusu kullanın.</p> - + Webinterface not enabled Web arayüzü etkinleştirilmemiş @@ -26724,12 +25229,12 @@ p, li { white-space: pre-wrap; } Web arayüzü etkinleştirilmemiş. Ayarlar > Web arayüzü bölümünden etkinleştirebilirsiniz. - + failed to start Webinterface Web arayüzü başlatılamadı - + Webinterface Web arayüzü @@ -26866,11 +25371,7 @@ p, li { white-space: pre-wrap; } Wiki Sayfaları - New Group - Yeni Grup - - - + Page Name Sayfa Adı @@ -26885,7 +25386,7 @@ p, li { white-space: pre-wrap; } Kaynak Kodu - + << << @@ -26973,7 +25474,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History Sayfa Düzenleme Geçmişi @@ -27008,7 +25509,7 @@ p, li { white-space: pre-wrap; } SayfaKodu - + \/ \/ @@ -27038,14 +25539,18 @@ p, li { white-space: pre-wrap; } Etiketler - - + + History + Geçmiş + + + Show Edit History Düzenleme Geçmişi Görüntülensin - + Status Durum @@ -27066,7 +25571,7 @@ p, li { white-space: pre-wrap; } Geri Al - + Submit Gönder @@ -27138,10 +25643,6 @@ p, li { white-space: pre-wrap; } WireDialog - - TimeRange - ZamanAralığı - Create Account @@ -27153,16 +25654,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - Yenile - - - + Settings @@ -27177,7 +25669,7 @@ p, li { white-space: pre-wrap; } Diğerleri - + Who to Follow @@ -27197,7 +25689,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -27227,85 +25719,17 @@ p, li { white-space: pre-wrap; } - Last Month - Geçen Ay - - - Last Week - Geçen Hafta - - - Today - Bugün - - - New - Yeni - - - from - başlangıç - - - until - bitiş - - - Search/Filter - Arama/Süzgeç - - - Network Wide - Tüm Ağda - - - Manage Accounts - Hesap Yönetimi - - - Showing: - Görüntülenen: - - - + Yourself Benimkiler - - Friends - Arkadaşlar - Following İzlenen - Custom - Özel - - - Account 1 - 1. Hesap - - - Account 2 - 2. Hesap - - - Account 3 - 3. Hesap - - - CheckBox - İşaret Kutusu - - - Post Pulse to Wire - Wire Üzerine Pulse Gönderin - - - + RetroShare @@ -27368,35 +25792,42 @@ p, li { white-space: pre-wrap; } Form - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + + + + Location: Konum: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -27441,11 +25872,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + Kullanılamıyor + + + + Following + İzlenen + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) Bilinmeyen @@ -27523,7 +25984,7 @@ p, li { white-space: pre-wrap; } %1y %2g - + k e.g: 3.1 k k @@ -27556,15 +26017,11 @@ p, li { white-space: pre-wrap; } Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif *.webp) - - Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - Görseller (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_zh_CN.ts b/retroshare-gui/src/lang/retroshare_zh_CN.ts index a07132cf4..82bafc9e1 100644 --- a/retroshare-gui/src/lang/retroshare_zh_CN.ts +++ b/retroshare-gui/src/lang/retroshare_zh_CN.ts @@ -84,13 +84,6 @@ 仅隐藏节点 - - AddCommentDialog - - Add Comment - 添加评论 - - AddFileAssociationDialog @@ -129,12 +122,12 @@ RetroShare: 高级搜索 - + Search Criteria 搜索条件 - + Add a further search criterion. 追加搜索条件。 @@ -144,7 +137,7 @@ 重置搜索条件。 - + Cancels the search. 取消搜索。 @@ -164,177 +157,6 @@ 搜索 - - AlbumCreateDialog - - Create Album - 创建相册 - - - Album Name: - 相册名称: - - - Category: - 类别: - - - Animals - 动物 - - - Family - 家人 - - - Friends - 好友 - - - Flowers - - - - Holiday - 假日 - - - Landscapes - 风景 - - - Pets - 宠物 - - - Portraits - 人像 - - - Travel - 旅行 - - - Work - 工作 - - - Random - 随机 - - - Caption: - 标题: - - - Where: - 地点: - - - Photographer: - 拍照人: - - - Description: - 描述: - - - Share Options - 共享设置 - - - Policy: - 策略: - - - Quality: - 质量: - - - Comments: - 评论: - - - Identity: - 标识: - - - Public - 公开 - - - Restricted - 受限 - - - Resize Images (< 1Mb) - 调整大小 图像 (< 1Mb) - - - Resize Images (< 10Mb) - 调整大小 图像 (< 10Mb) - - - Send Original Images - 发送原图 - - - No Comments Allowed - 禁止评论 - - - Authenticated Comments - 署名评论 - - - Any Comments Allowed - 允许任何评论 - - - Publish with Identity - 使用身份发布 - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> 拖 &amp;放插入图片。 点击一张图片,在下面编辑详情。</span></p></body></html> - - - Back - 返回 - - - Add Photos - 添加照片 - - - Publish Album - 发布相册 - - - Untitle Album - 未命名相册 - - - Say something about this album... - 写点什么吧… - - - Where were these taken? - 这些是在哪里拍摄的? - - - Load Album Thumbnail - 加载相册缩略图 - - AlbumDialog @@ -343,19 +165,11 @@ p, li { white-space: pre-wrap; } Album 相册 - - Album Thumbnail - 相册缩略图 - TextLabel 文字标签 - - Summary - 概述 - Album Title: @@ -371,34 +185,6 @@ p, li { white-space: pre-wrap; } Caption 标题 - - Where: - 地点: - - - When - 何时 - - - Description: - 描述: - - - Share Options - 分享选项 - - - Comments - 评论 - - - Publish Identity - 发布身份 - - - Visibility - 可见性 - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -767,7 +553,7 @@ p, li { white-space: pre-wrap; } Retroshare - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. 注意: 这里提供的服务都处于试验阶段。欢迎测试。 @@ -783,14 +569,6 @@ p, li { white-space: pre-wrap; } Circles 圈子 - - GxsForums - Gxs论坛 - - - GxsChannels - Gxs频道 - The Wire @@ -802,10 +580,23 @@ p, li { white-space: pre-wrap; } 照片 + + AspectRatioPixmapLabel + + + Save image + 保存图像 + + + + Copy image + + + AttachFileItem - + %p Kb %p Kb @@ -842,17 +633,13 @@ p, li { white-space: pre-wrap; } Browse... - - Add Avatar - 添加头像 - Remove 删除 - + Set your Avatar picture 设置头像 @@ -871,10 +658,6 @@ p, li { white-space: pre-wrap; } Use the mouse to zoom and adjust the image for your avatar. - - Load Avatar - 载入头像 - AvatarWidget @@ -943,22 +726,10 @@ p, li { white-space: pre-wrap; } 重置 - Receive Rate - 接收速度 - - - Send Rate - 发送速度 - - - + Always on Top 置顶 - - Style - 样式 - Changes the transparency of the Bandwidth Graph @@ -974,23 +745,11 @@ p, li { white-space: pre-wrap; } % Opaque % 不透明 - - Save - 保存 - - - Cancel - 取消 - Since: 自从: - - Hide Settings - 隐藏设置 - BandwidthStatsWidget @@ -1063,7 +822,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment @@ -1093,12 +852,12 @@ p, li { white-space: pre-wrap; } - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> <p><font color="#ff0000"><b>此消息的作者(ID为%1)被禁止。</b> - + ago @@ -1106,7 +865,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up @@ -1126,7 +885,7 @@ p, li { white-space: pre-wrap; } \/ - + Posted by @@ -1164,7 +923,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up @@ -1184,7 +943,7 @@ p, li { white-space: pre-wrap; } \/ - + Click to view picture @@ -1214,7 +973,7 @@ p, li { white-space: pre-wrap; } 分享 - + Toggle Message Read Status 切换消息阅读状态 @@ -1224,7 +983,7 @@ p, li { white-space: pre-wrap; } - + TextLabel @@ -1232,12 +991,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this - + 0 0 @@ -1257,18 +1016,18 @@ p, li { white-space: pre-wrap; } 头像 - + New Comment - + Copy RetroShare Link - + Expand 展开 @@ -1283,12 +1042,12 @@ p, li { white-space: pre-wrap; } - + Name - + Comm value @@ -1457,17 +1216,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels 频道 - + Tabs 标签 - + General 常规 @@ -1477,11 +1236,17 @@ p, li { white-space: pre-wrap; } - Load posts in background (Thread) - 在新标签页打开 (Thread) + + Downloads + 下载 - + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab 在新标签中打开所有频道 @@ -1489,7 +1254,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1512,7 +1277,7 @@ into the image, so as to ChannelsCommentsItem - + I like this @@ -1537,18 +1302,18 @@ into the image, so as to 头像 - + New Comment - + Copy RetroShare Link - + Expand 展开 @@ -1563,7 +1328,7 @@ into the image, so as to - + Name @@ -1573,17 +1338,7 @@ into the image, so as to - - Comment - - - - - Comments - - - - + Hide 隐藏 @@ -1591,7 +1346,7 @@ into the image, so as to ChatLobbyDialog - + Name 名字 @@ -1782,7 +1537,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby 显示聊天室 @@ -1794,22 +1549,6 @@ into the image, so as to Chats 聊天室 - - You have %1 new messages - 您有 %1 个新消息 - - - You have %1 new message - 您有 %1 个新消息 - - - %1 new messages - %1 个新消息 - - - %1 new message - %1 个新消息 - You have %1 mentions @@ -1831,13 +1570,14 @@ into the image, so as to - + + Unknown Lobby 未知聊天室 - - + + Remove All 删除全部 @@ -1845,13 +1585,13 @@ into the image, so as to ChatLobbyWidget - - + + Name 名称 - + Count 数量 @@ -1861,33 +1601,7 @@ into the image, so as to 主题 - - Private Subscribed chat rooms - 订阅的私有聊天室 - - - - - Public Subscribed chat rooms - 订阅的公共聊天室 - - - - Private chat rooms - 私密聊天室 - - - - - Public chat rooms - 公共聊天室 - - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/images/add_24x24.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;聊天室</h1> <p>聊天室差不多与IRC用法相同, 方便你与为数众多的人聊天而不需要互加好友,</p> <p>聊天室可以公开(你的好友看到)或私人(你的好友看不到它,除非你邀请他们 <img src=":/images/add_24x24.png" width=%2/>). 一旦你被邀请到私人房间,你将能够在您的好友使用时 看到它.</p> <p>左侧列表显示 你好友正参与的聊天大厅 <ul> <li>你也可以右键创建新的房间</li> <li>双击进入,聊天,并介绍给你的好友</li> </ul> 聊天室基于时钟的, 为了聊天室更好的工作,请检查你的系统时间! </p> - - - + Create chat room 创建聊天室 @@ -1897,7 +1611,7 @@ into the image, so as to 离开此房间 - + Create a non anonymous identity and enter this room 创建一个匿名身份并进入此房间 @@ -1956,12 +1670,12 @@ Double click a chat room to enter and chat. 双击房间可以进入聊天 - + %1 invites you to chat room named %2 %1 邀请你进入房间%2 - + Choose a non anonymous identity for this chat room: 为此聊天室选择一个非匿名身份: @@ -1971,31 +1685,31 @@ Double click a chat room to enter and chat. 对这个聊天室选择一个身份: - Create chat lobby - 新建聊天室 - - - + [No topic provided] [主题未设置] - Selected lobby info - 所选聊天室信息 - - - + + Private 私人 - + + + Public 公开 - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted 匿名 ID已接受 @@ -2005,42 +1719,25 @@ Double click a chat room to enter and chat. 取消自动订阅 - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe 启用自动订阅 - + Search Chat lobbies 搜索聊天室 - + Search Name 搜索名称 - Subscribed - 已订阅 - - - + Columns - - Yes - - - - No - - Chat rooms @@ -2052,47 +1749,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: 聊天室名称: - + Chat room Id: 聊天室 ID : - + Topic: 话题: - + Type: 类型: - + Security: 安全 - + Peers: 节点: - - - - - - + + + + + + TextLabel 文本标签 @@ -2107,13 +1804,24 @@ Double click a chat room to enter and chat. 没有匿名 ID - + Show 显示 - + + Private Subscribed + + + + + + Public Subscribed + + + + column @@ -2127,7 +1835,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item 删除项目 @@ -2172,46 +1880,22 @@ Double click a chat room to enter and chat. ChatPage - + General 常规 - - Distant Chat - 私聊 - Everyone 所有人 - - Contacts - 联系人 - Nobody 无人 - Accept encrypted distant chat from - 接受加密的远程聊天从 - - - Chat Settings - 聊天设置 - - - Enable Emoticons Private Chat - 私聊中启用表情图标 - - - Enable Emoticons Group Chat - 群聊中启用表情图标 - - - + Enable custom fonts 启用自定义字体 @@ -2220,10 +1904,6 @@ Double click a chat room to enter and chat. Enable custom font size 启用自定义字号 - - Minimum font size - 最小字体 - Enable bold @@ -2235,7 +1915,7 @@ Double click a chat room to enter and chat. 启用斜体 - + General settings @@ -2260,11 +1940,7 @@ Double click a chat room to enter and chat. 加载内嵌图像 - Chat Lobby - 聊天室 - - - + Blink tab icon 闪烁标签图标 @@ -2273,10 +1949,6 @@ Double click a chat room to enter and chat. Do not send typing notifications 不要显示输入提示 - - Private Chat - 私聊 - Open Window for new chat @@ -2298,11 +1970,7 @@ Double click a chat room to enter and chat. 闪烁窗口/标签图标 - Chat Font - 聊天字体 - - - + Change Chat Font 更改聊天字体 @@ -2312,14 +1980,10 @@ Double click a chat room to enter and chat. 聊天字体: - + History 历史 - - Style - 样式 - @@ -2334,17 +1998,13 @@ Double click a chat room to enter and chat. Variant: 变量: - - Group chat - 群聊 - Private chat 私聊 - + Choose your default font for Chat. 选择你的默认聊天字体 @@ -2408,22 +2068,28 @@ Double click a chat room to enter and chat. <html><head/><body><p align="justify">In this tab you can setup how many chat messages Retroshare will keep saved on the disc and how much of the previous conversation it will display, for the different chat systems. The max storage period allows to discard old messages and prevents the chat history from filling up with volatile chat (e.g. chat lobbies and distant chat).</p></body></html> <html><head/><body><p align="justify">对于不同的聊天系统,这个选项卡是用来设置允许RetroShare可以保存多少聊天消息,以及显示多少条过去的对话。最大存储周期允许丢弃旧消息以防滞留过多不重要的消息(比如,聊天室和年代久远的聊天记录).</p></body></html> - - Chatlobbies - 聊天室 - Enabled: 已启用: - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2433,7 +2099,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms 聊天室 @@ -2480,7 +2156,7 @@ Double click a chat room to enter and chat. Description: - + 描述: @@ -2530,11 +2206,7 @@ Double click a chat room to enter and chat. 最长存储时间,天数 (0 = 保持全部): - Search by default - 默认搜索 - - - + Case sensitive 区分大小写 @@ -2573,10 +2245,6 @@ Double click a chat room to enter and chat. Threshold for automatic search 自动搜索的最大值 - - Default identity for chat lobbies: - 聊天室的默认身份 - Show Bar by default @@ -2644,7 +2312,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat 显示聊天 @@ -2680,7 +2348,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close 关闭 @@ -2715,12 +2383,12 @@ Double click a chat room to enter and chat. 斜体 - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon 插入表情 @@ -2729,10 +2397,6 @@ Double click a chat room to enter and chat. Attach a Picture 附加图片 - - <html><head/><body><p>QToolButton:disabled {</p><p> image: url(:/icons/png/send-message-blocked.png) ;</p><p>}</p><p><br/></p></body></html> - <html><head/><body><p>QT工具按钮:禁用 {</p><p>⇥image: url(:/icons/png/send-message-blocked.png) ;</p><p>}</p><p><br/></p></body></html> - Strike @@ -2804,11 +2468,6 @@ Double click a chat room to enter and chat. Insert horizontal rule 插入水平线 - - - Save image - 保存图像 - Import sticker @@ -2846,7 +2505,7 @@ Double click a chat room to enter and chat. - + is typing... 正在输入... @@ -2868,7 +2527,7 @@ after HTML conversion. 选择字体 - + Do you really want to physically delete the history? 您确认要删除聊天记录? @@ -2918,7 +2577,7 @@ after HTML conversion. 处于忙碌状态可能无法回复您的消息。 - + Find Case Sensitively 区分大小写查找 @@ -2940,7 +2599,7 @@ after HTML conversion. X物品发现后,请勿停止着色(需要更多CPU占用) - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> <b>查找以前的</b><br/><i>Ctrl+Shift+G</i> @@ -2955,16 +2614,12 @@ after HTML conversion. <b>查找 </b><br/><i>Ctrl+F</i> - + (Status) (状态) - Set text font & color - 设置文字大小及颜色 - - - + Attach a File 附加文件 @@ -2980,12 +2635,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> <b>标记选择文本</b><br><i>Ctrl+M</i> - + Person id: 个人ID @@ -2996,12 +2651,12 @@ Double click on it to add his name on text writer. - + Unsigned 未签名 - + items found. 已找到 @@ -3021,7 +2676,7 @@ Double click on it to add his name on text writer. 在此输入消息 - + Don't stop to color after 请勿停止着色 @@ -3047,7 +2702,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: 显示详情: @@ -3069,7 +2724,7 @@ Double click on it to add his name on text writer. - + Personal Circles 私人圈 @@ -3095,7 +2750,7 @@ Double click on it to add his name on text writer. - + Friends 好友 @@ -3155,7 +2810,7 @@ Double click on it to add his name on text writer. 好友的好友 - + External Circles (Admin) 公共圈子(管理) @@ -3171,7 +2826,7 @@ Double click on it to add his name on text writer. - + Circles 圈子 @@ -3223,43 +2878,48 @@ Double click on it to add his name on text writer. - + RetroShare RetroShare - + - + Error : cannot get peer details. 错误:无法获取节点详情。 - + Retroshare ID - + <p>This Retroshare ID contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: + + + <b>DNS:</b> : + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3271,7 +2931,7 @@ Double click on it to add his name on text writer. 加密 - + Not connected 未连接 @@ -3353,25 +3013,17 @@ Double click on it to add his name on text writer. - + <p>This certificate contains: <p>此证书包含: - + <li>a <b>node ID</b> and <b>name</b> <li>a <b>节点 ID</b> 和 <b>名字</b> - an <b>onion address</b> and <b>port</b> - an <b>洋葱地址</b> 和<b>端口</b> - - - an <b>IP address</b> and <b>port</b> - an <b>IP地址</b> 和<b>端口</b> - - - + <p>You can use this certificate to make new friends. Send it by email, or give it hand to hand.</p> <p>您可以使用此证书结交新朋友。通过电子邮件发送,或手动发送。</ p> @@ -3386,7 +3038,7 @@ Double click on it to add his name on text writer. <html><head/><body><p>这个加密方式是 <span style=" font-weight:600;">OpenSSL</span>. 到好友的连接</p><p>是强加密的,如果有DHE</p><p>&quot;安全效果会更加完美&quot;.</p></body></html> - + with @@ -3403,118 +3055,16 @@ Double click on it to add his name on text writer. Connect Friend Wizard 好友连接向导 - - Add a new Friend - 添加新好友 - - - &You get a certificate file from your friend - &通过好友的证书文件 - - - &Make friend with selected friends of my friends - &将好友的好友加为好友 - - - &Send an Invitation by Email - (Your friend will receive an email with instructions how to download RetroShare) - &发送邀请邮件 -(你的好友将会受到一封RetroShare下载教程邮件) - - - Include signatures - 包含签名 - - - Copy your Cert to Clipboard - 复制您的证书到剪贴板 - - - Save your Cert into a File - 保存您的证书至文件 - - - Run Email program - 运行 Email 程序 - Open Cert of your friend from File 从文件打开你好友的证书 - - Open certificate - 打开证书 - - - Please, paste your friend's Retroshare certificate into the box below - 请粘贴你朋友的证书链接到下面的输入框 - - - Certificate files - 证书文件 - - - Use PGP certificates saved in files. - 使用文件中的 PGP 证书。 - - - Import friend's certificate... - 导入好友证书... - - - You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. - 您需要生成您的证书文件,将其发送给您的好友。您也可以使用之前生成过的文件。 - - - Export my certificate... - 导出我的证书... - - - Drag and Drop your friends's certificate in this Window or specify path in the box below - 拖拽您的好友证书到此窗口或在下框中指定证书文件的位置 - - - Browse - 浏览 - - - Friends of friends - 好友的好友 - - - Select now who you want to make friends with. - 选择您要加为好友的节点。 - - - Show me: - 显示: - - - Make friend with these peers - 将这些节点加为好友 - RetroShare ID RetroShare ID - - Use RetroShare ID for adding a Friend which is available in your network. - 使用 RetroShare ID 添加您网络中的节点为好友。 - - - Add Friends RetroShare ID... - 添加好友的 RetroShare ID... - - - Paste Friends RetroShare ID in the box below - 粘贴好友的 RetroShare ID 至下框中 - - - Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF - 输入好友的 RetroShare ID,例如:Peer@BDE8D16A46D938CF - RetroShare is better with Friends @@ -3556,27 +3106,7 @@ Double click on it to add his name on text writer. 邮箱 - Invite Friends by Email - 通过邮件邀请好友 - - - Enter your friends' email addresses (separate each one with a semicolon) - 输入您好友的 Email 地址(多个地址用分号分隔) - - - Your friends' email addresses: - 您好友的邮件地址: - - - Enter Friends Email addresses - 输入好友的电子邮件地址 - - - Subject: - 主题: - - - + @@ -3592,77 +3122,32 @@ Double click on it to add his name on text writer. 请求详情 - + Peer details 节点详情 - + Name: 名称: - - Email: - Email: - - - Node: - 节点: - - - Please note that RetroShare will require excessive amounts of bandwidth, memory and CPU if you add too many friends. You can add as many friends as you like, but more than 40 will probably require too much -resources. - 请注意,如果你添加太多的好友,RetroShare 将会需要大量带宽,内存和CPU占用,你可以尽可能多的加好友,但是超过40个好友可能就会占用大量资源 - Location: 位置: - + Options 选项 - This wizard will help you to connect to your friend(s) to RetroShare network.<br>Select how you would like to add a friend: - 这个向导将帮助你连接到你的朋友(们)进入RetroShare网络,<br>请选择你想怎么添加你的好友 - - - Enter the certificate manually - 手动输入证书 - - - Enter RetroShare ID manually - 手动输入 RetroShare ID - - - &Send an Invitation by Web Mail Providers - 通过网页邮箱发送邀请 - - - Recommend many friends to each other - 批量推荐好友 - - - RetroShare certificate - RetroShare 证书 - - - Please paste below your friend's Retroshare certificate - 请在下面粘贴你的好友的 RetroShare 证书 - - - Paste certificate - 粘贴证书 - - - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> <html><head/><body><p>这里只能输入你的好友的RetroShare证书。 注意,这跟你好友账户的密钥是不一样的。不要再这里粘贴好友的密钥,没用的 (就算是密钥的一部分也不行)。</p></body></html> - + Add friend to group: 添加至好友分组: @@ -3672,7 +3157,7 @@ resources. 为好友的 PGP 密钥签名 - + Please paste below your friend's Retroshare ID @@ -3697,16 +3182,22 @@ resources. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with 添加为可以建立连接的好友 - To accept the Friend Request, click the Finish button. - 点击完成可接受好友请求。 - - - + Sorry, some error appeared 抱歉,出现错误 @@ -3726,32 +3217,27 @@ resources. 您的好友详情: - + Key validity: 密钥有效性: - + Profile ID: - - Signers - 签名者 - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">签署好友的钥匙是表达你对这个好友,给你的其他好友的信任的一种方式。 下面的签名加密地证明所列出的密钥的所有者将当前的PGP密钥识别为真实的</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. 此节点已经存在于您的好友列表中。重复添加仅设置其IP地址。 - + To accept the Friend Request, click the Accept button. @@ -3797,49 +3283,17 @@ resources. - + Certificate Load Failed 证书载入失败 - Cannot get peer details of PGP key %1 - 无法获取PGP密钥 %1 的节点详情 - - - Any peer I've not signed - 任意未签名节点 - - - Friends of my friends who already trust me - 我好友的好友中信任我的节点 - - - Signed peers showing as denied - 显示为拒绝的已签名节点 - - - Peer name - 节点名称 - - - Also signed by - 其他签名者 - - - Peer id - 节点 ID - - - Certificate appears to be valid - 证书似乎有效 - - - + Not a valid Retroshare certificate! 不是一个有效的 RetroShare 证书! - + RetroShare Invitation RetroShare 邀请 @@ -3861,12 +3315,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? 这是你自己的证书!你该不会是想和自己交朋友吧? - + @@ -3874,7 +3328,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list 此密钥已经在你的信任列表中 @@ -3914,7 +3368,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.您有一个好友请求来自 - + Profile password needed. @@ -3939,7 +3393,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3949,47 +3403,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - Certificate Load Failed:file %1 not found - 证书载入失败: 未找到文件 %1 - - - This Peer %1 is not available in your Network - 节点 %1 在您的网络中不可用 - - - Use new certificate format (safer, more robust) - 使用新证书格式(更安全,更强大) - - - Use old (backward compatible) certificate format - 使用旧证书格式(向后兼容) - - - Remove signatures - 删除签名 - - - RetroShare Invite - RetroShare 邀请 - - - Connect Friend Help - “连接好友”的帮助信息 - - - You can copy this text and send it to your friend via email or some other way - 您可以复制此文本并将其通过邮件或其他方式发送给您的好友 - - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - 您的证书已复到剪切板,请将其通过邮件或其他方式发送给您的好友 - - - Save as... - 另存为... - - - + RetroShare Certificate (*.rsc );;All Files (*) @@ -4028,11 +3442,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.*** 无 *** - Use as direct source, when available - 可用时,作为直连数据源。 - - - + IP-Addr: IP 地址: @@ -4042,7 +3452,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.IP 地址: - + Show Advanced options 显示高级选项 @@ -4051,10 +3461,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> <html><head/><body><p><span style=" font-size:10pt;">签署好友的钥匙是表达你对这个好友,给你的其他好友的信任的一种方式。 它可以帮助他们决定是否允许基于您自己的信任的密钥进行连接。 签署密钥是绝对可选的,不能撤销,所以请做出明智的选择.</span></p></body></html> - - <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> - <html><head/><body><p align="justify">RetroShare会定期检查您的好友列表中的可浏览文件与您的传输匹配,以建立直接传输。 在这种情况下,您的好友知道您正在下载文件.</p><p align="justify">要防止此行为(仅适用于此好友),请取消选中此框。 如果您明确要求,您仍然可以执行直接传输。 从你好友的文件列表下载。 此设置应用于同一节点的所有位置.</p></body></html> - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> @@ -4065,45 +3471,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p>Peers that have this option cannot connect if their connection address is not in the whitelist. This protects you from traffic forwarding attacks. When used, rejected peers will be reported by &quot;security feed items&quot; in the News Feed section. From there, you can whitelist/blacklist their IP. Applies to all locations of the same node.</p></body></html> <html> <head /> <body> <p>如果连接地址不在白名单中,则具有此选项的对等人无法连接。 这样可以防止流量转发攻击。 当被使用时,被拒绝的对方将被“安全馈送项目”报告。 在新闻Feed部分。 从那里,您可以对其IP进行白名单/黑名单。 适用于同一节点的所有位置。</ p> </ body> </ html> - - Recommend many friends to each others - 批量互荐好友 - - - Friend Recommendations - 好友推荐 - - - The text below is your Retroshare certificate. You have to provide it to your friend - 下面的文本是你的 RetroShare 证书。你必须提供给你的好友 - - - Message: - 消息: - - - Recommend friends - 推荐好友 - - - To - 收件人 - - - Please select at least one friend for recommendation. - 请选择至少一个好友以推荐。 - - - Please select at least one friend as recipient. - 请选择至少一个好友以接收。 - Add key to keyring 将密钥添加到钥匙环中 - + This key is already in your keyring 密钥已存在于您的钥匙环中 @@ -4119,7 +3493,7 @@ even if you don't make friends. 发送远程信息有用。 - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. 证书包含错误的版本号,记住0.6版本跟0.5版本不能相互添加 @@ -4154,7 +3528,7 @@ even if you don't make friends. 添加至白名单 - + No IP in this certificate! 证书里没有IP @@ -4164,27 +3538,10 @@ even if you don't make friends. <p>此证书没有IP。 你会依靠节点发现和DHT找到它。 由于您需要清除白名单,节点将在NewsFeed选项卡中引发安全警告。 从那里,你可以将他的IP列入白名单。</ p> - - [Unknown] - [未知] - - - + Added with certificate from %1 添加来自1%的证书 - - Paste Cert of your friend from Clipboard - 复制对方的证书到剪贴板 - - - Certificate Load Failed:can't read from file %1 - 签名载入失败:无法读取文件 %1 - - - Certificate Load Failed:something is wrong with %1 - 证书载入失败: %1 出错 - ConnectProgressDialog @@ -4246,7 +3603,7 @@ even if you don't make friends. - + UDP Setup UDP 设置 @@ -4274,7 +3631,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant 连接助手 @@ -4284,17 +3641,20 @@ p, li { white-space: pre-wrap; } 无效节点 ID - + + Unknown State 未知状态 - + + Offline 离线 - + + Behind Symmetric NAT 受限于对称 NAT @@ -4304,12 +3664,14 @@ p, li { white-space: pre-wrap; } 受限于 NAT 且无 DHT - + + NET Restart NET 重启 - + + Behind NAT 受限于 NAT @@ -4319,7 +3681,8 @@ p, li { white-space: pre-wrap; } 无 DHT - + + NET STATE GOOD! 网络状况很好! @@ -4344,7 +3707,7 @@ p, li { white-space: pre-wrap; } 正在探索 RS 节点 - + Lookup requires DHT 查询需要 DHT @@ -4636,7 +3999,7 @@ p, li { white-space: pre-wrap; } 请重试导入完整的证书 - + @@ -4644,7 +4007,8 @@ p, li { white-space: pre-wrap; } 不适用 - + + UNVERIFIABLE FORWARD! 端口转发状态无法确认! @@ -4654,7 +4018,7 @@ p, li { white-space: pre-wrap; } 端口转发状态无法确定,无 DHT! - + Searching 正在搜索 @@ -4690,12 +4054,12 @@ p, li { white-space: pre-wrap; } 圈子详情 - + Name 名称 - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4715,7 +4079,7 @@ p, li { white-space: pre-wrap; } - + IDs ID @@ -4735,18 +4099,18 @@ p, li { white-space: pre-wrap; } 过滤 - + Cancel - + Nickname 昵称 - + Invited Members 已邀请成员 @@ -4761,15 +4125,7 @@ p, li { white-space: pre-wrap; } 认识的人 - ID - ID - - - Type - 类型 - - - + Name: 名称: @@ -4809,23 +4165,19 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>圈子可以限制在另一个圈子的成员身上。 只有该第二圈的成员才能看到新圈子及其内容(成员列表等)。</p></body></html> - Only visible to members of: - 仅对下列成员可见: - - - - + + RetroShare RetroShare - + Please set a name for your Circle 请为您的圈子命名 - + No Restriction Circle Selected 未选择受限圈子 @@ -4835,12 +4187,24 @@ p, li { white-space: pre-wrap; } 未选择圈子限制 - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] [未知] - + Add 添加 @@ -4850,7 +4214,7 @@ p, li { white-space: pre-wrap; } 删除 - + Search 搜索 @@ -4865,10 +4229,6 @@ p, li { white-space: pre-wrap; } Signed 已签名 - - Signed by known nodes - 签名者:已知节点 - Edit Circle @@ -4885,10 +4245,6 @@ p, li { white-space: pre-wrap; } PGP Identity PGP ID - - Anon Id - 匿名 ID - Circle name @@ -4911,17 +4267,13 @@ p, li { white-space: pre-wrap; } 新建圈子 - + Create 创建 - PGP Linked Id - PGP 关联 ID - - - + Add Member 添加成员 @@ -4940,7 +4292,7 @@ p, li { white-space: pre-wrap; } 创建分组 - + Group Name: 组名称: @@ -4975,7 +4327,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post 新频道贴文 @@ -4985,7 +4337,7 @@ p, li { white-space: pre-wrap; } 邮件 - + Post @@ -5046,23 +4398,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">使用拖放 / 添加文件按钮, Hash 新文件。</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> 从你的分享复制/粘贴 RetroShare 链接</span></p></body></html> - - Add File to Attach - 附加文件 - Add Channel Thumbnail 添加频道缩略图 - - Message - 消息 - - - Subject : - 主题: - @@ -5148,17 +4488,17 @@ p, li { white-space: pre-wrap; } - + RetroShare RetroShare - + This file already in this post: - + Post refers to non shared files @@ -5177,17 +4517,18 @@ p, li { white-space: pre-wrap; } The following files will only be shared for 30 days. Think about adding them to a shared directory. - - File already Added and Hashed - 文件已添加并生成散列校验值 - Please add a Subject 请添加主题 - + + Cannot publish post + + + + Load thumbnail picture 载入图片缩略图 @@ -5202,18 +4543,12 @@ p, li { white-space: pre-wrap; } 隐藏 - - + Generate mass data 生成大量数据 - - Do you really want to generate %1 messages ? - 你真的想生成 %1 消息吗? - - - + You are about to add files you're not actually sharing. Do you still want this to happen? 你正在添加未分享的文件,仍想继续? @@ -5247,7 +4582,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message 论坛发帖 @@ -5256,10 +4591,6 @@ p, li { white-space: pre-wrap; } Forum 论坛 - - Subject - 主题 - Attach File @@ -5280,8 +4611,8 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -5300,7 +4631,7 @@ p, li { white-space: pre-wrap; } 您可以通过拖拽在此窗口中添加文件 - + Post @@ -5330,17 +4661,17 @@ p, li { white-space: pre-wrap; } - + No Forum 无论坛 - + In Reply to 回复 - + Title 标题 @@ -5393,7 +4724,7 @@ Do you want to discard this message? 载入图片文件 - + No compatible ID for this forum 没有兼容此论坛的 ID @@ -5403,8 +4734,8 @@ Do you want to discard this message? 您的身份不允许在此论坛中发布。 这可能是由于论坛限于一个不包含您的身份的圈子,或者论坛需要PGP签名的身份。 - - + + Generate mass data 生成大量数据 @@ -5413,10 +4744,6 @@ Do you want to discard this message? Do you really want to generate %1 messages ? 你真的想生成 %1 消息吗? - - Send - 发送 - Post as @@ -5431,23 +4758,7 @@ Do you want to discard this message? CreateLobbyDialog - Create Chat Lobby - 新建聊天室 - - - A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab. - 聊天室是分布式的匿名群组聊天。每个参加者都可以收到全部消息。一旦聊天室创建成功,您可以从好友标签页中邀请其他好友。 - - - Lobby name: - 聊天室名称: - - - Lobby topic: - 聊天室主题: - - - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -5482,7 +4793,7 @@ Do you want to discard this message? - + Create 创建 @@ -5492,11 +4803,7 @@ Do you want to discard this message? - <html><head/><body><p>If you check this, only PGP-signed ids can be used to join and talk in this lobby. This limitation prevents anonymous spamming as it becomes possible for at least some people in the lobby to locate the spammer's node.</p></body></html> - <html><head/><body><p>如果您检查这个,只有PGP签名的ID可以在这个大厅加入和谈话。 这个限制防止匿名垃圾邮件发送,因为大厅中的至少一些人可能找到垃圾邮件发送者的节点</p></body></html> - - - + require PGP-signed identities 需要 PGP 签名的身份 @@ -5511,11 +4818,7 @@ Do you want to discard this message? 选择群聊好友 - Invited friends - 已邀请好友 - - - + Create Chat Room 创建聊天室 @@ -5536,7 +4839,7 @@ Do you want to discard this message? 联系人: - + Identity to use: 使用身份 @@ -5544,17 +4847,17 @@ Do you want to discard this message? CryptoPage - + Public Information 公开信息 - + Name: 名称: - + Location: 位置: @@ -5564,12 +4867,12 @@ Do you want to discard this message? 地点 ID: - + Software Version: 软件版本: - + Online since: 在线始于: @@ -5589,12 +4892,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -5604,7 +4902,7 @@ Do you want to discard this message? - + Other Information 其它信息 @@ -5614,17 +4912,12 @@ Do you want to discard this message? - + Profile - - Certificate - 证书 - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -5634,11 +4927,7 @@ Do you want to discard this message? 包含签名 - Save Key into a file - 保存密钥到文件 - - - + Export Identity 导出身份 @@ -5712,33 +5001,33 @@ and use the import button to load it - + TextLabel 文本标签 - + PGP fingerprint: PGP 指纹: - - Node information - 节点信息 - - - + PGP Id : PGP Id : - + Friend nodes: 好友节点: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5777,14 +5066,6 @@ and use the import button to load it Node 节点 - - Create new node... - 新建节点 - - - show statistics window - 显示统计窗口 - DHTGraphSource @@ -5801,10 +5082,6 @@ and use the import button to load it DHT DHT - - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your friends to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your friends.</p> - <p>RetroShare使用Bittorrent的DHT作为连接的代理。 它不会将您的IP存储在DHT中.。 相反,您的好友可以使用DHT来处理标准的DHT请求。 一旦RetroShare从您的一个好友获得DHT响应,状态栏符号将变为绿色。</p> - <p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not "store" your IP in the DHT. Instead the DHT is used by your trusted nodes to reach you while processing standard DHT requests. The status bullet will turn green as soon as Retroshare gets a DHT response from one of your trusted nodes.</p> @@ -5840,7 +5117,7 @@ and use the import button to load it DLListDelegate - + B B @@ -6508,7 +5785,7 @@ and use the import button to load it DownloadToaster - + Start file 启动文件任务 @@ -6516,38 +5793,38 @@ and use the import button to load it ExprParamElement - + - + to - + ignore case 忽略大小写 - - - dd.MM.yyyy - dd.MM.yyyy + + + yyyy-MM-dd + - - + + KB KB - - + + MB MB - - + + GB GB @@ -6555,12 +5832,12 @@ and use the import button to load it ExpressionWidget - + Expression Widget 表情部件 - + Delete this expression 删掉这个表达式 @@ -6722,7 +5999,7 @@ and use the import button to load it FilesDefs - + Picture 图片 @@ -6732,7 +6009,7 @@ and use the import button to load it 视频 - + Audio 音频 @@ -6792,11 +6069,21 @@ and use the import button to load it C C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories 好友目录 @@ -6918,7 +6205,7 @@ and use the import button to load it - + ID ID @@ -6953,10 +6240,6 @@ and use the import button to load it Show State 显示状态 - - Trusted nodes - 信任的节点 - @@ -6964,7 +6247,7 @@ and use the import button to load it 显示分组 - + Group 分组 @@ -7000,7 +6283,7 @@ and use the import button to load it 添加至分组 - + Search 搜索 @@ -7016,7 +6299,7 @@ and use the import button to load it 以状态分类 - + Profile details 用户信息 @@ -7258,7 +6541,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request 确认好友请求 @@ -7275,10 +6558,6 @@ at least one peer was not added to a group FriendSelectionWidget - - Search : - 搜索 : - Sort by state @@ -7300,7 +6579,7 @@ at least one peer was not added to a group 搜索好友 - + Mark all 标记全部 @@ -7311,16 +6590,134 @@ at least one peer was not added to a group 取消标记 + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + + + + + Node ID + + + + + Address + 地址 + + + + Status + 状态 + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + 接受好友 + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + 代理未启用或中断。 +所有服务都开启并正常运行吗? +另外请检查您的端口! + + FriendsDialog - + Edit status message 编辑状态消息 - - + + Broadcast 广播 @@ -7403,33 +6800,38 @@ at least one peer was not added to a group 重置为默认字体 - + Keyring 钥匙环 - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;网络</h1> <p>“网络”选项卡显示您的好友RetroShare节点:与您连接的相邻RetroShare节点。 </p> <p>您可以将节点分组在一起,以允许设置更精细的信息访问级别,例如仅允许某些节点查看某些文件。</p> <p>在右边,你会发现3个有用的选项卡: <ul> <li>广播一次向所有连接的节点发送消息</li> <li>本地网络图根据节点发现信息显示您周围的网络</li> <li>密钥环包含您收集的节点密钥,主要由您的好友节点转发给您</li> </ul> </p> - - - + Retroshare broadcast chat: messages are sent to all connected friends. RetroShare 广而告之:此处的消息会发给当前连接的所有好友。 - - + + Network 网络 - + + Friend Server + + + + Network graph 网络图表 - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. 在这里设置你的状态消息。 @@ -7447,7 +6849,17 @@ at least one peer was not added to a group 密码 - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters 所有字段都需要最少3个字符 @@ -7457,17 +6869,12 @@ at least one peer was not added to a group 密码不符 - + Port 端口 - - Use BOB - - - - + This password is for PGP 这是保护PGP密钥的密码。 @@ -7488,42 +6895,38 @@ at least one peer was not added to a group 新证书生成失败,可能您的 PGP 密码有误! - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> <html><head/><body><p>请输入一个强壮的密码。您需要靠它保护您的 PGP 密钥。</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> <html><head/><body><p>请移动鼠标以尽可能多地收集随机性。至少需要达到20%来创建你的节点密钥。</p></body></html> - + Standard node 标准节点 - TOR/I2P Hidden node - TOR/I2P 隐藏节点 - - - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> <html><head/><body><p>您的节点名称指定将在此计算机上运行的RetroShare实例。</p></body></html> - + Node name 节点名称 - + Node type: @@ -7543,12 +6946,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> <html><head/><body><p>用户档案文件名称通过网络识别您。</p><p>您的好友使用它来接受您的连接。</p><p>您可以在不同的计算机上创建具有</p><p>同一个用户档案的多个RetroShare节点。</p><p><br/></p></body></html> - + Export this profle 导出账户文件 @@ -7558,42 +6961,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> <html><head/><body><p> 这里应该是洋葱的隐藏地址格式: xa76giaf6ifda7ri63i263.onion <br/>或者是I2P的格式 : [52 个字符].b32.i2p </p><p> 你必须通过建立Tor/I2P隐藏服务才能获得一个地址。</p><p> 当然你现在也可以留空,但是只有你正确配置了Tor/I2p地址过后才能正常工作。配置在选项-&gt;网络-&gt;隐藏服务配置。</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> <html><head/><body><p>I在你聊天室,论坛,频道评论中发东西时需要使用身份。</p><p>他们也使用RetroShare的网络来收发邮件。你可以立即创建</p><p>签名身份,或在你需要的时候再创建。</p></body></html> - + Go! 开始! - - + + TextLabel - Advanced options - 高级选项 - - - + hidden address 隐藏地址 - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. 您的用户档案与PGP密钥相关联。RetroShare目前忽略DSA密钥。 - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> <html><head/><body><p>这是你的连接端口。</p><p>1024到65535之间的任何值</p><p>都可以。你可以在以后更改</p></body></html> @@ -7641,13 +7045,13 @@ and use the import button to load it 您的用户档案未保存。有错误发生。 - + Import profile 导入用户档案 - + Create new profile and new Retroshare node 创建新的用户档案和RetroShare节点 @@ -7657,7 +7061,7 @@ and use the import button to load it 新建 RetroShare 节点 - + Tor/I2P address @@ -7692,7 +7096,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -7702,12 +7106,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -7717,12 +7116,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7948,36 +7342,13 @@ and use the import button to load it 入门指南 - + Invite Friends 邀请好友 - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space:pre-wrap;} -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">离开好友,RetroShare 就失去了意义。点击按钮开始添加好友。</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">将您的 "ID 证书" 通过电邮邀请发送给您的好友。</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">请记得获得回请...</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">只有均已加对方为好友的节点之间才能相互连接。</span></p></body></html> - - - + Add Your Friends to RetroShare 添加您的好友至 RetroShare @@ -7987,131 +7358,103 @@ p, li { white-space:pre-wrap;} 添加好友 - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">和你的好友同时在线,RetroShare将会自动连接你</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">在你创建连接之前,你的客户端必须能找到RetroShare网络。</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> 你第一次开启RetroShare时将会花费5-30分钟在</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> 当能创建连接的时候DHT指示器会(状态栏) 变成绿色。</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> 几分钟之后,NAT指示器 (也是状态栏) 变成黄色或绿色</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">如果它仍然是红色,那么你有一个讨厌的防火墙,RetroShare会努力连接。</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">有关连接的更多建议,请参阅更多帮助部分。</span></p></body></html> + + Connect To Friends + 连接到好友 - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">您可以通过打开外部端口改善 RetroShare 的网络性能。</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">这可以加快程序的连接速度,让更多的节点与您相连。</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">最简单的方式是启用您路由中的 UPnP 自动映射功能。</span></p> - -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">由于各路由器的设置不尽相同,您需要知道您的路由器型号,在网上搜索具体的设置说明。</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">如果这些都不管用,不必担心,RetroShare 仍能正常工作。</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port + 高级:打开防火端口 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">是否在初次使用 RetroShare 时遇到问题? </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) 请查看 FAQ Wiki。虽然其中内容略显陈旧,但我们正在努力更新。</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) 查看在线论坛。提出问题并讨论程序功能。</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) 尝试 RetroShare 内的论坛功能</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - 这些论坛将在您与好友建立连接后上线。</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) 如果您仍有困难,请电邮联系我们。</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> - - - - Connect To Friends - 连接到好友 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Advanced: Open Firewall Port - 高级:打开防火端口 - - - + Further Help and Support 更多帮助与支持 - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website 访问 RS 网站 @@ -8136,7 +7479,7 @@ p, li { white-space: pre-wrap; } 反馈电邮 - + RetroShare Invitation RetroShare 邀请 @@ -8186,12 +7529,12 @@ p, li { white-space: pre-wrap; } RetroShare 反馈 - + RetroShare Support RetroShare 支持 - + It has many features, including built-in chat, messaging, 他拥有多种功能,包括内置的聊天,传信等。 @@ -8315,7 +7658,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat 显示群组聊天 @@ -8323,7 +7666,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] [未知] @@ -8489,19 +7832,11 @@ p, li { white-space: pre-wrap; } You can let your friends know about your forum by sharing it with them. Select the friends with which you want to share your forum. 您可以通过与他们分享让您的好友知道您的论坛。 选择您要与之共享论坛的好友。 - - Share topic admin permissions - 共享话题的管理权限 - - - You can allow your friends to edit the topic. Select them in the list below. Note: it is not possible to revoke Posted admin permissions. - 您可以允许您的好友编辑主题。 在下面的列表中选择它们。 注意:无法撤销发布的管理员权限。 - GroupTreeWidget - + Title 标题 @@ -8514,12 +7849,12 @@ p, li { white-space: pre-wrap; } - + Description 描述 - + Number of Unread message @@ -8544,31 +7879,7 @@ p, li { white-space: pre-wrap; } - Sort Descending Order - 按降序排列 - - - Sort Ascending Order - 按升序排列 - - - Sort by Name - 按名称排序 - - - Sort by Popularity - 按活跃度排序 - - - Sort by Last Post - 按新贴文排序 - - - Sort by Unread - 按未读信息分类 - - - + You are admin (modify names and description using Edit menu) 你是管理员(修改名字和描述请用编辑菜单) @@ -8583,14 +7894,14 @@ p, li { white-space: pre-wrap; } ID - - + + Last Post 最新贴文 - + Name @@ -8601,17 +7912,13 @@ p, li { white-space: pre-wrap; } 活跃度 - + Never 从不 - Display - 显示 - - - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -8624,7 +7931,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and @@ -8760,7 +8067,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels 频道 @@ -8771,26 +8078,22 @@ p, li { white-space: pre-wrap; } 创建频道 - + Enable Auto-Download 启用自动下载 - + My Channels 我的频道 - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;频道</h1> <p> 频道里你可以推送 (比如电影, 音乐) ,这些会传输到网络的各处</p> <p>您可以看到您的好友订阅的频道,并自动将订阅频道转发给您的好友。这促进了网络中的良好沟通。</p> <p>只有频道的创建者可以在该频道上发布。 网络中的其他对等体只能从其中读取,除非该信道是私有的。然而,您可以 与好友的RetroShare节点共享发布权限或阅读权限。</p> <p> 频道也能设置为匿名的,或附加到RetroShare身份, 以便读者可以在需要时联系您。</p> <p> 频道推送能保存 %1 days, 能同步%2天以内的消息,除非你修改了这个。</p> - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels 订阅的频道 @@ -8810,12 +8113,12 @@ p, li { white-space: pre-wrap; } 选择频道下载目录 - + Disable Auto-Download 禁用自动下载 - + Set download directory 设置下载目录 @@ -8850,22 +8153,22 @@ p, li { white-space: pre-wrap; } - + Play 播放 - + Open folder 打开文件夹 - + Open file - + Error 错误 @@ -8885,17 +8188,17 @@ p, li { white-space: pre-wrap; } 检查中 - + Are you sure that you want to cancel and delete the file? 您确定要取消和删除这些文件吗? - + Can't open folder 无法打开文件夹 - + Play File 播放文件 @@ -8905,37 +8208,10 @@ p, li { white-space: pre-wrap; } 文件位置 %1 不存在。 - - GxsChannelFilesWidget - - Form - 表单 - - - Filename - 文件名 - - - Size - 大小 - - - Title - 标题 - - - Published - 已发布 - - - Status - 状态 - - GxsChannelGroupDialog - + Create New Channel 新建频道 @@ -8973,9 +8249,19 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel - 订阅频道 + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel + @@ -8989,7 +8275,7 @@ p, li { white-space: pre-wrap; } - + Expand 展开 @@ -9004,7 +8290,7 @@ p, li { white-space: pre-wrap; } 频道描述 - + Loading 正在载入 @@ -9019,8 +8305,9 @@ p, li { white-space: pre-wrap; } - New Channel - 新频道 + + Never + 从不 @@ -9031,7 +8318,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: 新评论: @@ -9052,7 +8339,7 @@ p, li { white-space: pre-wrap; } - + Play 播放 @@ -9108,28 +8395,24 @@ p, li { white-space: pre-wrap; } Files 文件 - - Warning! You have less than %1 hours and %2 minute before this file is deleted Consider saving it. - 警告! 距离文件删除,您还有 %1 小时 %2 分,请考虑保存。 - Hide 隐藏 - + New - + 0 0 - - + + Comment 评论*** @@ -9144,21 +8427,17 @@ p, li { white-space: pre-wrap; } - Loading - 正在载入 - - - + Loading... - + Comments - + Post @@ -9183,135 +8462,16 @@ p, li { white-space: pre-wrap; } 播放影音 - - GxsChannelPostsWidget - - Post to Channel - 发布至频道 - - - Loading - 正在载入 - - - Search channels - 搜索频道 - - - Title - 标题 - - - Search Title - 搜索标题 - - - Message - 信息 - - - Search Message - 搜索消息 - - - Filename - 文件名 - - - Search Filename - 搜索文件名 - - - No Channel Selected - 未选择频道! - - - Never - 从不 - - - Public - 公共 - - - Restricted to members of circle " - 仅限于圈子的成员 - - - Restricted to members of circle - 仅限于圈子的成员 - - - Your eyes only - 只有你能看见 - - - You and your friend nodes - 你和你好友的节点 - - - Disable Auto-Download - 禁用自动下载 - - - Enable Auto-Download - 启用自动下载 - - - Show feeds - 显示feeds - - - Show files - 显示文件 - - - Administrator: - 管理员: - - - Last Post: - 最新贴文 - - - unknown - 未知 - - - Distribution: - 传播范围 - - - Feeds - 订阅 - - - Files - 文件 - - - Subscribers - 订阅 - - - Description: - 描述: - - - Posts (at neighbor nodes): - 贴文(相邻节点) - - GxsChannelPostsWidgetWithModel - + Post to Channel 发布至频道 - + Add new post @@ -9381,7 +8541,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -9417,7 +8577,7 @@ p, li { white-space: pre-wrap; } - + Comments @@ -9432,13 +8592,13 @@ p, li { white-space: pre-wrap; } 订阅 - - + + Click to switch to list view - + Show unread posts only @@ -9453,7 +8613,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -9468,7 +8628,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -9528,12 +8688,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -9590,17 +8760,17 @@ p, li { white-space: pre-wrap; } Restricted to members of circle " - + 仅限于圈子的成员" Restricted to members of circle - + 仅限于圈子的成员 Your eyes only - + 只有你能看见 @@ -9608,12 +8778,13 @@ p, li { white-space: pre-wrap; } 你和你好友的节点 - + + Copy Retroshare link - + Subscribed 已订阅 @@ -9664,17 +8835,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -9789,7 +8960,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container 评论容器 @@ -9802,7 +8973,7 @@ p, li { white-space: pre-wrap; } 表格 - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -9832,7 +9003,7 @@ p, li { white-space: pre-wrap; } 刷新 - + Comment 评论 @@ -9871,7 +9042,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment 回复评论 @@ -9895,6 +9066,21 @@ p, li { white-space: pre-wrap; } Vote Down + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -9904,7 +9090,7 @@ p, li { white-space: pre-wrap; } 发表评论 - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -9933,26 +9119,10 @@ p, li { white-space: pre-wrap; } - + Post - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">评论</span></p></body></html> - - - Signed by - 签名者 - Reply to Comment @@ -9980,7 +9150,7 @@ before you can comment 评论前您需要先创建身份 - + It remains %1 characters after HTML conversion. @@ -10022,14 +9192,6 @@ before you can comment Forum moderators can edit/delete/pinup others posts - - Add Forum Admins - 添加论坛管理员 - - - Select Forum Admins - 选择论坛管理员 - Create @@ -10039,7 +9201,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum 订阅论坛 @@ -10055,7 +9217,7 @@ before you can comment - + Expand 展开 @@ -10075,8 +9237,9 @@ before you can comment - Loading - 正在载入 + + TextLabel + @@ -10107,13 +9270,13 @@ before you can comment GxsForumMsgItem - - + + Subject: 主题: - + Unsubscribe To Forum 退订论坛 @@ -10124,7 +9287,7 @@ before you can comment - + Expand 展开 @@ -10144,21 +9307,17 @@ before you can comment 回复 - Loading - 正在载入 - - - + Loading... - + Forum Feed 论坛feed - + Hide 隐藏 @@ -10171,63 +9330,66 @@ before you can comment 表格 - + Start new Thread for Selected Forum 新建主题帖 - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums 搜索论坛 - Last Post - 最新贴文 - - - + New Thread 新帖子 - - - Threaded View - 话题视图 - - - - Flat View - 普通视图 - - + Title 标题 - - + + Date 日期 - + Author 作者 - - Save image - 保存图像 - - - + Loading 正在载入 - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -10237,12 +9399,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message 回复贴文 @@ -10266,10 +9423,6 @@ before you can comment Download all files 下载全部文件 - - Next unread - 下一条未读 - Search Title @@ -10286,35 +9439,23 @@ before you can comment 搜索作者 - Content - 内容 - - - Search Content - 搜索内容 - - - <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - <p>订阅论坛将收集 您订阅的好友的 可用帖子。</p><p>之后,您可以从左侧的论坛列表的上下文菜单中取消订阅。</p> - - - + No name 未命名 - - + + Reply 回复 - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -10357,20 +9498,12 @@ before you can comment 复制 RetroShare 链接 - + Hide 隐藏 - Expand - 展开 - - - [Banned] - [被屏蔽的] - - - + [unknown] [未知] @@ -10400,8 +9533,8 @@ before you can comment 只有你能看见 - - + + Distribution 传播范围 @@ -10415,26 +9548,6 @@ before you can comment Anti-spam 反垃圾 - - [ ... Redacted message ... ] - [ ... 丢失消息 ... ] - - - Anonymous - 匿名 - - - signed - 已签名 - - - none - - - - [ ... Missing Message ... ] - [ ... 丢失消息 ... ] - <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> @@ -10504,16 +9617,12 @@ before you can comment 原始贴文 - + New thread - Read status - 读取状态 - - - + Edit 编辑 @@ -10574,7 +9683,7 @@ before you can comment 作者的信誉 - + Show column @@ -10594,7 +9703,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive 如果匿名账户/未知节点评分是正的,允许发帖 @@ -10646,7 +9755,7 @@ This message is missing. You should receive it later. - + No result. @@ -10656,7 +9765,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -10671,28 +9780,7 @@ This message is missing. You should receive it later. - Information for this identity is currently missing. - 这个身份的信息现在丢失了 - - - You have banned this ID. The message will not be -displayed nor forwarded to your friends. - 您已屏蔽此ID。 该消息将不会显示,也不会转发给您的好友。 - - - You have not set an opinion for this person, - and your friends do not vote positively: Spam regulation -prevents the message to be forwarded to your friends. - 您未曾设置过对此人的评价, -您的好友们也没有对此人有正面评判。 -防垃圾邮件规则阻止了向您的好友转发此消息。 - - - Message will be forwarded to your friends. - 信息将被转发给你的好友 - - - + (Latest) @@ -10701,10 +9789,6 @@ prevents the message to be forwarded to your friends. (Old) - - You cant act on the author to a non-existant Message - 你不能对不存在的消息指定作者 - From @@ -10762,12 +9846,12 @@ prevents the message to be forwarded to your friends. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;论坛</h1> <p>RetroShare 论坛看起来像互联网论坛,但他们以分散的方式工作</p> <p>您会看到您的好友订阅的论坛,并将订阅的论坛转发给 你的好友。这将自动促进网络中有趣的论坛的发展。</p> <p>论坛信息会保存%1 天并且会同步最后%2天的内容,除非你有另外的配置</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> + - + Forums 论坛 @@ -10798,35 +9882,16 @@ prevents the message to be forwarded to your friends. 其他论坛 - - GxsForumsFillThread - - Waiting - 等待中 - - - Retrieving - 正在获取 - - - Loading - 正在载入 - - GxsGroupDialog - + Name 名称 - Add Icon - 添加图标 - - - + Key recipients can publish to restricted-type group and can view and publish for private-type channels 密钥接收者可以在受限小组中发帖,可以在个人频道中发帖和浏览。 @@ -10835,22 +9900,14 @@ prevents the message to be forwarded to your friends. Share Publish Key 分享发帖密钥 - - check peers you would like to share private publish key with - 选择您希望与之共享个人发帖密钥的节点 - - - Share Key With - 密钥共享给 - - + Description 描述 - + Message Distribution 传播范围 @@ -10858,7 +9915,7 @@ prevents the message to be forwarded to your friends. - + Public 公开 @@ -10877,14 +9934,6 @@ prevents the message to be forwarded to your friends. New Thread 新帖子 - - Required - 必需 - - - Encrypted Msgs - 加密消息 - Personal Signatures @@ -10926,7 +9975,7 @@ prevents the message to be forwarded to your friends. 垃圾信息保护 - + Comments: 评论: @@ -10949,7 +9998,7 @@ prevents the message to be forwarded to your friends. 反垃圾 - + All People @@ -10965,12 +10014,12 @@ prevents the message to be forwarded to your friends. - + Restricted to circle: 仅限于圈子 - + Limited to your friends 限于你的好友 @@ -10987,23 +10036,23 @@ prevents the message to be forwarded to your friends. - + Message tracking 消息追踪 - - + + PGP signature required 需要 PGP 签名 - + Never 从不 - + Only friends nodes in group 仅分组中的好友节点 @@ -11019,30 +10068,28 @@ prevents the message to be forwarded to your friends. 请添加名称 - + PGP signature from known ID required 需要已知ID的 PGP 签名 - + + + [None] + + + + Load Group Logo 加载小组Logo - + Submit Group Changes 提交群组更改 - Failed to Prepare Group MetaData - please Review - 群组元数据准备失败-请查阅 - - - Will be used to send feedback - 将用于发送反馈 - - - + Owner: 拥有着: @@ -11052,12 +10099,12 @@ prevents the message to be forwarded to your friends. 在此设置描述性介绍 - + Info 信息 - + ID ID @@ -11067,7 +10114,7 @@ prevents the message to be forwarded to your friends. 最新贴文 - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -11142,7 +10189,12 @@ prevents the message to be forwarded to your friends. 取消收藏来自未知节点的未签名ID - + + Author: + + + + Popularity 活跃度 @@ -11158,27 +10210,22 @@ prevents the message to be forwarded to your friends. - + Created - + Cancel - + Create 创建 - - Author - 作者 - - - + GxsIdLabel GXS ID 标签 @@ -11186,7 +10233,7 @@ prevents the message to be forwarded to your friends. GxsGroupFrameDialog - + Loading 正在载入 @@ -11246,7 +10293,7 @@ prevents the message to be forwarded to your friends. 编辑详情 - + Synchronise posts of last... 同步最后的贴文... @@ -11303,16 +10350,12 @@ prevents the message to be forwarded to your friends. - + Search for - Share publish permissions - 共享发布权限 - - - + Copy RetroShare Link 复制 RetroShare 链接 @@ -11335,7 +10378,7 @@ prevents the message to be forwarded to your friends. GxsIdChooser - + No Signature 无签名 @@ -11348,40 +10391,24 @@ prevents the message to be forwarded to your friends. GxsIdDetails - Loading - 正在载入 - - - + Not found 未找到 - - No Signature - 无签名 - - - + + [Banned] [被屏蔽的] - - Authentication - 验证 - unknown Key 未知密钥 - anonymous - 匿名 - - - + Loading... @@ -11391,7 +10418,12 @@ prevents the message to be forwarded to your friends. - + + [Nobody] + + + + Identity&nbsp;name 身份 名称 @@ -11405,16 +10437,20 @@ prevents the message to be forwarded to your friends. Node 节点 - - Signed&nbsp;by - 签名者 - [Unknown] [未知] + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -11426,7 +10462,7 @@ prevents the message to be forwarded to your friends. GxsIdStatisticsWidget - + Total identities: @@ -11474,17 +10510,13 @@ prevents the message to be forwarded to your friends. GxsIdTreeItemDelegate - + [Unknown] [未知] GxsMessageFramePostWidget - - Loading - 正在载入 - Loading... @@ -11648,41 +10680,6 @@ prevents the message to be forwarded to your friends. - - GxsTunnelsDialog - - Authenticated tunnels: - 已验证的路由 - - - Tunnel ID: %1 - 路由 ID:%1 - - - from: %1 - 来自: %1 - - - to: %1 - 到: %1 - - - status: %1 - 状态:%1 - - - total sent: %1 bytes - 总共发送: 1% bytes - - - total recv: %1 bytes - 总共收到: 1% bytes - - - Unknown Peer - 未知节点 - - HashBox @@ -11895,48 +10892,12 @@ prevents the message to be forwarded to your friends. About 关于 - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare provides file sharing, chat, messages and channels</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Useful external links to more information:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Wiki</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare's Forum</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">Retroshare Project Page</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Team Blog</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Dev Twitter</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare是一个开源跨平台,</span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">私有安全的去中心化交流平台。 </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;"> 通过他能安全地跟好友分享 , </span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;"> 使用WOT认证节点和OpenSSL进行加密所有的通信。</span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare提供文件分享, 聊天, 邮箱和频道</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> 更多信息请看外链:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'MS Shell Dlg 2'; font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">RetroShare 主页</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare Wiki</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare 论坛</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare 项目主页</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare 团队博客</span></a></li> -<li style=" font-family:'MS Shell Dlg 2'; font-size:12pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" color:#007af4;">RetroShare 开发组Twitter</span></a></li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -11952,7 +10913,7 @@ p, li { white-space: pre-wrap; } - + Authors 作者 @@ -11971,7 +10932,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -11984,36 +10945,6 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Daniel Wester</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">wester@speedmail.se</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">German: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Jan</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Keller</span><span style=" font-family:'MS Shell Dlg 2';"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">trilarion@users.sourceforge.net</span><span style=" font-family:'MS Shell Dlg 2';">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare 翻译:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;"><br /></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare 网页翻译:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Daniel Wester</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">wester@speedmail.se</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">German: </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Jan</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;"> </span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Keller</span><span style=" font-family:'MS Shell Dlg 2';"> &lt;</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">trilarion@users.sourceforge.net</span><span style=" font-family:'MS Shell Dlg 2';">&gt;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Polish: </span><span style=" font-family:'MS Shell Dlg 2';">Maciej Mrug</span></p></body></html> - License Agreement @@ -12079,12 +11010,12 @@ p, li { white-space: pre-wrap; } 表单 - + <html><head/><body><p>Copy your RetroShare ID to clipboard</p></body></html> - + Add friend @@ -12099,7 +11030,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -12108,32 +11039,12 @@ p, li { white-space: pre-wrap; } This is your Retroshare ID. Copy and share with your friends! - - Did you receive a certificate from a friend? - 你收到好友的证书了吗? - - - Add friends certificate - 添加好友证书 - - - Add certificate file - 添加证书文件 - - - Share your RetroShare Key - 分享你的RetroShare密钥 - ... ... - - The text below is your own Retroshare certificate. Send it to your friends - 下面的文本是你的 RetroShare 证书。把它发送给你的好友 - Open Source cross-platform, @@ -12144,16 +11055,12 @@ private and secure decentralized communication platform. - Launch startup wizard - 初次使用向导 - - - + Open Web Help 打开网络帮助 - + Copy your Cert to Clipboard 复制您的证书到剪贴板 @@ -12163,7 +11070,7 @@ private and secure decentralized communication platform. 保存您的证书至文件 - + Send via Email 通过邮件发送 @@ -12183,13 +11090,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -12201,17 +11132,12 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -12225,10 +11151,6 @@ new short format RetroShare Invite RetroShare邀请 - - Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way - 您的证书已复到剪切板,请将其通过邮件或其他方式粘贴发送给您的好友 - Save as... @@ -12500,14 +11422,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All 全部 - + Reputation 信誉 @@ -12517,12 +11439,12 @@ p, li { white-space: pre-wrap; } 搜索 - + Anonymous Id 匿名 ID - + Create new Identity 新建身份 @@ -12532,7 +11454,7 @@ p, li { white-space: pre-wrap; } 新建圈子 - + Persons 个人 @@ -12547,27 +11469,27 @@ p, li { white-space: pre-wrap; } 人物 - + Close 关闭 - + Ban-option: 屏蔽选项 - + Auto-Ban all identities signed by the same node 自动屏蔽掉这个节点签名过的身份 - + Friend votes: 好友点赞 - + Positive votes 正面的投票 @@ -12583,29 +11505,39 @@ p, li { white-space: pre-wrap; } 负面的投票 - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics 使用统计 - + Circles 圈子 - + Circle name 圈子名称 @@ -12625,18 +11557,20 @@ p, li { white-space: pre-wrap; } 私人圈子 - + + Edit identity 编辑身份 - + + Delete identity 删除身份 - + Chat with this peer 与此节点聊天 @@ -12646,78 +11580,78 @@ p, li { white-space: pre-wrap; } 跟这个节点开启一个远程聊天 - + Owner node ID : 所有者节点名称: - + Identity name : 身份名称 - + () () - + Identity ID 身份ID - + Send message 发送消息 - + Identity info 身份信息 - + Identity ID : 身份 ID: - + Owner node name : 所有者节点名称: - + Create new... 创建新的... - + Type: 类型: - + Send Invite 发送邀请 - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> <html><head/><body><p>关于这个身份,相邻节点的综合评价。 负的是差的,</p><p> 正的是好的,零是中立的</p></body></html> - + Your opinion: 你的评价 - + Negative 负面的 - + Neutral 中立的 @@ -12728,17 +11662,17 @@ p, li { white-space: pre-wrap; } 正面的 - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> <html><head/><body><p>总体信誉得分,源于你和你的好友</p><p> 负的是差的,正的是好的,零是中立的,如果分数太低</p><p>这个身份就被标记为差的 , 会被论坛,聊天室频道等</p><p>过滤。</p></body></html> - + Overall: 总体: - + Anonymous 匿名 @@ -12753,24 +11687,24 @@ p, li { white-space: pre-wrap; } 搜索 ID - + This identity is owned by you 这个身份被你是拥有者 - - + + My own identities 我所拥有的身份 - - + + My contacts 我的通讯录 - + Show Items 显示项目 @@ -12785,7 +11719,12 @@ p, li { white-space: pre-wrap; } 链接到我的节点 - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles 其他圈子 @@ -12795,7 +11734,7 @@ p, li { white-space: pre-wrap; } 我加入的圈子 - + Circle ID: 圈子ID @@ -12870,7 +11809,7 @@ p, li { white-space: pre-wrap; } 不是会员(无权访问此圈子的数据) - + Identity ID: 身份 ID : @@ -12900,7 +11839,7 @@ p, li { white-space: pre-wrap; } 未知 - + Invited 被邀请 @@ -12915,7 +11854,7 @@ p, li { white-space: pre-wrap; } 成员 - + Edit Circle 编辑圈子 @@ -12963,7 +11902,7 @@ p, li { white-space: pre-wrap; } 授予会员资格 - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -12974,7 +11913,7 @@ These identities will soon be not supported anymore. 此种身份将很快不再被支持。 - + [Unknown node] [未知节点] @@ -13017,7 +11956,7 @@ These identities will soon be not supported anymore. 匿名身份 - + Boards @@ -13097,7 +12036,7 @@ These identities will soon be not supported anymore. - + information @@ -13113,25 +12052,12 @@ These identities will soon be not supported anymore. - Send invite? - 发送邀请? - - - Do you really want send a invite with your Certificate? - 你真的要以你的证书发送邀请吗 - - - + Banned 已屏蔽 - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;身份</h1> <p>身份在此选项卡中,你可以创建/编辑伪匿名身份<b>, 和<b>圈子</b>。</b> <p>身份<b> 身份用于安全地识别你的数据:为聊天室,论坛和频道文章中的消息签名, 使用 RetroShare 内置电子邮件系统接收反馈,在频道发布文章后 发表评论,使用安全隧道聊天等。</p> <p>身份可任意由<b>你 RetroShare 节点的证书</b>签名。 签名的身份更容易信任,但很容易链接到你节点的 IP 地址。</b> <p><b>匿名身份</b>允许您与其他用户匿名交互。 他们不能 被欺骗,但是没有人可以证明谁真正拥有一个特定的身份。</p> <p><b>圈子</b>是通过网络远程共享的身份(匿名或签名)组,它们可 用于限制论坛,频道等的可见性等<p>。</p> 一个<b>圈子</b>可以受限于另一个圈子,从而限制它对该圈子成员的可见性,甚至限制圈子本身的可见性,这意味着只有被邀请的成员可以看到。 - - - + positive 正面的 @@ -13175,19 +12101,11 @@ These identities will soon be not supported anymore. Forums 论坛 - - Posted - 已发表 - Chat 聊天 - - Unknown - 未知 - [Unknown] @@ -13208,14 +12126,6 @@ These identities will soon be not supported anymore. Creation of author signature in service %1 使用中的作者签名%1 - - Message/vote/comment - 信息/点赞/评论 - - - %1 in %2 tab - %1 在 %2 标签页 - Distant message signature validation. @@ -13236,19 +12146,11 @@ These identities will soon be not supported anymore. Signature in distant tunnel system. 在远程隧道系统中的签名 - - Update of identity data. - 更新身份数据。 - Generic signature validation. 通用签名验证。 - - Generic signature. - 通用签名。 - Generic encryption. @@ -13260,11 +12162,7 @@ These identities will soon be not supported anymore. 通用解密。 - Membership verification in circle %1. - 圈子%1中的成员验证。 - - - + Add to Contacts 添加到通讯录 @@ -13314,21 +12212,21 @@ These identities will soon be not supported anymore. 你好,<br>我想与你成为 RetroShare 上的好友。<br> - - - + + + People 人物 - + Your Avatar Click here to change your avatar 你的头像 - + Linked to neighbor nodes 链接到相邻节点 @@ -13338,7 +12236,7 @@ These identities will soon be not supported anymore. 链接到远程节点 - + Linked to a friend Retroshare node 链接到好友的RetroShare节点 @@ -13353,7 +12251,7 @@ These identities will soon be not supported anymore. 链接到未知RetroShare节点 - + Chat with this person 与此人聊天 @@ -13368,12 +12266,12 @@ These identities will soon be not supported anymore. 远程聊天拒绝此人 - + Last used: 上次使用 - + +50 Known PGP +50 已知 PGP @@ -13393,12 +12291,12 @@ These identities will soon be not supported anymore. 你真的要删除这个身份吗? - + Owned by 拥有者 - + Node name: 节点名称: @@ -13408,7 +12306,7 @@ These identities will soon be not supported anymore. 节点Id: - + Really delete? 真的要删除? @@ -13416,7 +12314,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname 昵称 @@ -13446,7 +12344,7 @@ These identities will soon be not supported anymore. 笔名 - + Import image @@ -13456,12 +12354,19 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. + + + No Avatar chosen. A default image will be automatically displayed from your new identity. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity 新建身份 @@ -13475,7 +12380,7 @@ These identities will soon be not supported anymore. - + @@ -13485,7 +12390,12 @@ These identities will soon be not supported anymore. 不适用 - + + No avatar chosen + + + + Edit identity 编辑身份 @@ -13496,27 +12406,27 @@ These identities will soon be not supported anymore. 更新 - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -13536,7 +12446,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -13546,11 +12456,7 @@ These identities will soon be not supported anymore. - Error getting key! - 错误:密钥获取出错! - - - + Error KeyID invalid 错误:密钥ID无效 @@ -13565,7 +12471,7 @@ These identities will soon be not supported anymore. 未知真实姓名*** - + Create New Identity 创建新身份 @@ -13575,10 +12481,15 @@ These identities will soon be not supported anymore. 类型 - + Choose image... + + + Remove + 删除 + @@ -13604,7 +12515,7 @@ These identities will soon be not supported anymore. 添加 - + Create 创建 @@ -13614,17 +12525,13 @@ These identities will soon be not supported anymore. - + Your Avatar Click here to change your avatar 你的头像 - Set Avatar - 设置头像 - - - + Linked to your profile 链接到你的用户档案 @@ -13634,7 +12541,7 @@ These identities will soon be not supported anymore. 您可以拥有一个或多个身份。 当您在聊天大厅,论坛和频道中撰写评论时,会使用它们。 它们作为远程聊天和RetroShare远程邮件系统的接收地址。 - + The nickname is too short. Please input at least %1 characters. 63/5000 昵称太短。 请输入至少%1个字符。 @@ -13694,10 +12601,6 @@ These identities will soon be not supported anymore. PGP name: PGP 用户名 - - GXS id: - GXS ID: - PGP id: @@ -13713,7 +12616,7 @@ These identities will soon be not supported anymore. - + Copy 复制 @@ -13723,12 +12626,12 @@ These identities will soon be not supported anymore. 删除 - + %1 's Message History - + Mark all 标记全部 @@ -13747,26 +12650,38 @@ These identities will soon be not supported anymore. Quote 引用 - - Send - 发送 - ImageUtil - - + + Save image 保存图像 + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + + + + Cannot save the image, invalid filename 无法保存图片,无效的文件名 - + + Copy image + + + + + Not an image 不是一张图片 @@ -13784,27 +12699,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: 端口: - + Listen Address: - + + Status: + 状态: + + + 127.0.0.1 127.0.0.1 - + Token: @@ -13825,7 +12745,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -13834,26 +12759,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File 打开文件 - + Open Folder 打开文件夹 - + Checking... 正在校验... @@ -13863,7 +12793,7 @@ These identities will soon be not supported anymore. 校验文件 - + Recommend in a message to... @@ -13891,7 +12821,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend 添加好友 @@ -13907,7 +12837,8 @@ These identities will soon be not supported anymore. - + + Options 选项 @@ -13928,7 +12859,7 @@ These identities will soon be not supported anymore. - + Quit 退出 @@ -13939,12 +12870,12 @@ These identities will soon be not supported anymore. 快速入门向导 - + RetroShare %1 a secure decentralized communication platform RetroShare %1 ― 一个分布式安全通信平台 - + Unfinished 未完成 @@ -13973,11 +12904,12 @@ RetroShare 将暂停对此目录的访问。 + Status 状态 - + Notify 提示 @@ -13988,31 +12920,35 @@ RetroShare 将暂停对此目录的访问。 + Open Messages 打开邮件箱 - + + Bandwidth Graph 带宽图 - + Applications 应用 + Help 帮助 - + + Minimize 最小化 - + Maximize 最大化 @@ -14027,7 +12963,12 @@ RetroShare 将暂停对此目录的访问。 RetroShare - + + Close window + + + + %1 new message %1 条新消息 @@ -14057,7 +12998,7 @@ RetroShare 将暂停对此目录的访问。 %1 个好友已连接 - + Do you really want to exit RetroShare ? 您确定要退出 RetroShare 吗? @@ -14077,7 +13018,7 @@ RetroShare 将暂停对此目录的访问。 显示 - + Make sure this link has not been forged to drag you to a malicious website. 请确认此连接不是伪造,不是指向恶意网站。 @@ -14122,12 +13063,13 @@ RetroShare 将暂停对此目录的访问。 服务权限列表 - + + Statistics 统计 - + Show web interface 显示 Web 界面 @@ -14142,7 +13084,7 @@ RetroShare 将暂停对此目录的访问。 目录运行很慢(现在的限制是 - + Really quit ? 真的要退出吗? @@ -14151,17 +13093,17 @@ RetroShare 将暂停对此目录的访问。 MessageComposer - + Compose 写信 - + Contacts 联系人 - + Paragraph 段落 @@ -14197,12 +13139,12 @@ RetroShare 将暂停对此目录的访问。 六级标题 - + Font size 字体大小 - + Increase font size 增大字号 @@ -14217,32 +13159,32 @@ RetroShare 将暂停对此目录的访问。 粗体 - + Italic 斜体 - + Alignment 对齐方式 - + Add an Image 添加图片 - + Sets text font to code style 设置文本为代码样式 - + Underline 下划线 - + Subject: 主题: @@ -14253,32 +13195,32 @@ RetroShare 将暂停对此目录的访问。 - + Tags 标签 - + Address list: 地址列表: - + Recommend this friend 推荐这个好友 - + Set Text color 设置文本颜色 - + Set Text background color 设置文本背景颜色 - + Recommended Files 推荐文件 @@ -14348,7 +13290,7 @@ RetroShare 将暂停对此目录的访问。 添加大段引用 - + Send To: 发送至: @@ -14372,10 +13314,6 @@ RetroShare 将暂停对此目录的访问。 &Justify &两端对齐 - - All addresses (mixed) - 所有地址(混合) - All people @@ -14387,7 +13325,7 @@ RetroShare 将暂停对此目录的访问。 我的通讯录 - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> 你好,<br>我向你推荐我的一个好友;如果你信任我,也可以信任他们。<br> @@ -14407,18 +13345,18 @@ RetroShare 将暂停对此目录的访问。 希望与您在 RetroShare 上成为好友 - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team 你好 %1,<br><br>%2 希望加你为 RetroShare 好友。<br><br>立即回应:<br>%3<br><br>谢谢,<br> RetroShare 软件小组 - - + + Save Message 保存邮件 - + Message has not been Sent. Do you want to save message to draft box? 邮件未发送。 @@ -14430,7 +13368,17 @@ Do you want to save message to draft box? 粘贴 RetroShare 链接 - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" 添加至"收件人" @@ -14450,7 +13398,7 @@ Do you want to save message to draft box? 添加为推荐 - + Original Message 原始消息 @@ -14460,21 +13408,21 @@ Do you want to save message to draft box? 发件人 - + - + To 收件人 - - + + Cc 抄送 - + Sent 已发送 @@ -14489,7 +13437,7 @@ Do you want to save message to draft box? %1, %2 写道: - + Re: 回复: @@ -14499,30 +13447,30 @@ Do you want to save message to draft box? 转发: - - - + + + RetroShare RetroShare - + Do you want to send the message without a subject ? 您确定要发送无主题的邮件吗? - + Please insert at least one recipient. 请输入至少一个收件人。 - + Bcc 密送 - + Unknown 未知 @@ -14637,13 +13585,13 @@ Do you want to save message to draft box? 详情 - + Open File... 打开文件... - + HTML-Files (*.htm *.html);;All Files (*) HTML 文件 (*.htm *.html);;所有文件 (*) @@ -14663,7 +13611,7 @@ Do you want to save message to draft box? 导出 PDF - + Message has not been Sent. Do you want to save message ? 邮件未发送。 @@ -14685,7 +13633,7 @@ Do you want to save message ? 添加额外文件 - + Hi,<br>I want to be friends with you on RetroShare.<br> 你好,<br>我想与你成为 RetroShare 上的好友。<br> @@ -14709,28 +13657,24 @@ Do you want to save message ? Warning: This message is too big of %1 characters after HTML conversion. - - You have a friend invite - 您有一条好友推荐 - Respond now: 现在回应: - - + + Close 关闭 - + From: 发件人: - + Friend Nodes 好友节点 @@ -14775,13 +13719,13 @@ Do you want to save message ? 排序(拉丁字母倒序) - - + + Thanks, <br> 感谢, <br> - + Distant identity: 远程身份 @@ -14791,12 +13735,12 @@ Do you want to save message ? [丢失] - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. 请创建一个身份以签署远程信息,或从目标列表中删除远处的节点。 - + Node name & id: 节点名和id: @@ -14874,7 +13818,7 @@ Do you want to save message ? 默认 - + A new tab 新标签 @@ -14884,7 +13828,7 @@ Do you want to save message ? 新窗口 - + Edit Tag 标记标签 @@ -14907,7 +13851,7 @@ Do you want to save message ? MessageToaster - + Sub: 主题: @@ -14915,7 +13859,7 @@ Do you want to save message ? MessageUserNotify - + Message 邮件 @@ -14943,7 +13887,7 @@ Do you want to save message ? MessageWidget - + Recommended Files 推荐的文件 @@ -14953,37 +13897,37 @@ Do you want to save message ? 下载所有推荐文件 - + Subject: 主题: - + From: 发件人: - + To: 收件人: - + Cc: 抄送: - + Bcc: 密送: - + Tags: 标签: - + Reply 回复 @@ -15005,7 +13949,7 @@ Do you want to save message ? Forward - + 前进 @@ -15023,7 +13967,7 @@ Do you want to save message ? - + Send Invite 发送邀请 @@ -15075,7 +14019,7 @@ Do you want to save message ? - + Confirm %1 as friend 确认 %1 为好友 @@ -15085,12 +14029,12 @@ Do you want to save message ? 添加 %1 为好友 - + View source - + No subject 无主题 @@ -15100,17 +14044,22 @@ Do you want to save message ? 下载 - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -15120,21 +14069,23 @@ Do you want to save message ? - Send invite? - 发送邀请? + + Show less + - Do you really want send a invite with your Certificate? - 你真的要以你的证书发送邀请吗 + + Show more + - + Download all 下载全部 - + Print Document 打印文档 @@ -15149,12 +14100,12 @@ Do you want to save message ? HTML 文件 (*.htm *.html);;所有文件 (*) - + Load images always for this message 此消息总是载入图像 - + Hide the attachment pane 隐藏附件窗格 @@ -15176,42 +14127,6 @@ Do you want to save message ? Compose 写信 - - Reply to selected message - 回复选中的邮件 - - - Reply - 回复 - - - Reply all to selected message - 回复所选邮件给其中的所有人 - - - Reply all - 回复全部 - - - Forward selected message - 转发所选邮件 - - - Forward - 转发 - - - Remove selected message - 删除所选邮件 - - - Delete - 删除 - - - Print selected message - 打印所选邮件 - Print @@ -15290,7 +14205,7 @@ Do you want to save message ? MessagesDialog - + New Message 新信息 @@ -15300,60 +14215,16 @@ Do you want to save message ? 写信 - Reply to selected message - 回复所选邮件 - - - Reply - 回复 - - - Reply all to selected message - 向选中邮件中的所有人回复邮件 - - - Reply all - 回复全部 - - - Forward selected message - 转发所选信息 - - - Foward - 转发 - - - Remove selected message - 删除所选消息 - - - Delete - 删除 - - - Print selected message - 打印所选邮件 - - - Print - 打印 - - - Display - 显示 - - - + - - + + Tags 标签 - - + + Inbox 收件箱 @@ -15383,21 +14254,17 @@ Do you want to save message ? 回收站 - + Total Inbox: 收件箱总数: - Folders - 文件夹 - - - + Quick View 快捷视图 - + Print... 打印... @@ -15407,26 +14274,6 @@ Do you want to save message ? Print Preview 打印预览 - - Buttons Icon Only - 按钮显示图标 - - - Buttons Text Beside Icon - 按钮显示文本和图标 - - - Buttons with Text - 按钮显示文本 - - - Buttons Text Under Icon - 按钮文本位于图标下方 - - - Set Text Under Icon - 文本放置于图标下方 - Save As... @@ -15448,7 +14295,7 @@ Do you want to save message ? 转发信件 - + Subject 主题 @@ -15458,7 +14305,7 @@ Do you want to save message ? 发件人 - + Date 日期 @@ -15468,39 +14315,7 @@ Do you want to save message ? 内容 - Click to sort by attachments - 点击按附件排序 - - - Click to sort by subject - 点击按主题排序 - - - Click to sort by read - 点击按已读排序 - - - Click to sort by from - 点击按发件人排序 - - - Click to sort by date - 点击按日期排序 - - - Click to sort by tags - 点击按标签排序 - - - Click to sort by star - 点击按星标排序 - - - Forward selected Message - 转发所选邮件 - - - + Search Subject 搜索主题 @@ -15509,6 +14324,11 @@ Do you want to save message ? Search From 搜索发件人 + + + Search To + + Search Date @@ -15535,14 +14355,14 @@ Do you want to save message ? 搜索附件 - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;邮件</h1> <p> RetroShare 有自己的内部邮件系统。你可以通过连接的好友节点发送/接收电子邮件。</p> <p>也可以使用全球路由系统向其他人的身份发送消息。 这些消息始终被加密和签名,并由中间节点中继,直到它们到达其最终目的地。 </p> <p>远程消息保留在发件箱中,直到收到确认。</p> <p>通常,你可以使用邮件通过粘贴文件链接向好友推荐文件,或者将好友节点推荐给其他的好友节点,来加强你的网络,或向频道所有者发送反馈。</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + - + Starred - 加星 + @@ -15616,7 +14436,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -15630,7 +14450,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -15645,38 +14465,33 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts 草稿箱 - + No Box selected. - No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light gray star beside any message. - 暂无加星邮件。加星令邮件更容易。为邮件加星标,请点击邮件旁的灰色星标。 - - - No system messages available. - 无系统消息。 - - + To - 收件人 + 收件人 - Click to sort by to - 点击按收件人排序 - - - This message goes to a distant person. - 这条消息发送到了远程用户 - - - + @@ -15684,26 +14499,6 @@ Do you want to save message ? Total: 总计: - - Messages - 邮件 - - - Click to sort by signature - 点击按签名排序 - - - This message was signed and the signature checks - 此信息已签名,且签名已检查 - - - This message was signed but the signature doesn't check - 此信息已签名,但签名未检查 - - - This message comes from a distant person. - 这条消息来自于远程用户 - Mail @@ -15731,7 +14526,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + 保存图像 + + + + Copy image + + + + Paste as plain text 粘贴纯文本 @@ -15785,7 +14590,7 @@ Do you want to save message ? - + Expand 展开 @@ -15795,7 +14600,7 @@ Do you want to save message ? 删除项目 - + from 来自 @@ -15830,18 +14635,10 @@ Do you want to save message ? 待发送消息 - + Hide 隐藏 - - Send invite? - 发送邀请? - - - Do you really want send a invite with your Certificate? - 你真的要以你的证书发送邀请吗 - NATStatus @@ -15979,7 +14776,7 @@ Do you want to save message ? 节点 ID - + Remove unused keys... 移除未使用的密钥... @@ -15989,7 +14786,7 @@ Do you want to save message ? - + Clean keyring 清理钥匙环 @@ -16007,7 +14804,13 @@ Notes: Your old keyring will be backed up. 如果您在同一台电脑上同时运行多个RS实例,清理操作会失败。 - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info 钥匙环信息 @@ -16042,18 +14845,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. 钥匙环中的数据不一致。可能是程序错误。请联系开发人员。 - - - Export/create a new node - 导出或者新建节点 - Trusted keys only 仅信任的节点 - + Search name 搜索名称 @@ -16063,12 +14861,12 @@ For security, your keyring was previously backed-up to file 搜索节点 ID - + Profile details... 用户详情 - + Key removal has failed. Your keyring remains intact. Reported error: @@ -16077,13 +14875,6 @@ Reported error: 报告错误: - - NetworkPage - - Network - 网络 - - NetworkView @@ -16110,7 +14901,7 @@ Reported error: NewFriendList - + Offline Friends @@ -16131,7 +14922,7 @@ Reported error: - + Groups 分组 @@ -16161,19 +14952,19 @@ Reported error: 导出你的好友列表包括分组 - - + + Search - + ID ID - + Search ID 搜索 ID @@ -16183,12 +14974,12 @@ Reported error: - + Show Items 显示项目 - + Last contact @@ -16198,7 +14989,7 @@ Reported error: IP - + Group 分组 @@ -16313,7 +15104,7 @@ Reported error: 全部折叠 - + Do you want to remove this node? 你想移除这个节点吗 @@ -16323,7 +15114,7 @@ Reported error: 您是否要删除此好友? - + Done! 完成! @@ -16435,11 +15226,7 @@ at least one peer was not added to a group NewsFeed - Log entries - 日志条目 - - - + Activity Stream @@ -16454,11 +15241,7 @@ at least one peer was not added to a group 删除全部 - This is a test. - 这是一个测试。 - - - + Newest on top 新的在上面 @@ -16468,27 +15251,12 @@ at least one peer was not added to a group 旧的在上面 - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;News Feed</h1> <p>The Log Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel and Forum posts</li> <li>New Channels and Forums you can subscribe to</li> <li>Private messages from your friends</li> </ul> </p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;事件中心</h1> -<p>事件中心显示网络上最近的事件,按您收到的时间排序。 -它为您提供了一份好友活动摘要。您可以点击<b>选项</b>设置要显示的事件。</p> -<p>可显示的各种事件包括: -<ul><li>连接尝试(有助于结识新朋友,控制与您的连接)</li> -<li>频道/论坛消息</li> -<li>可订阅的新频道/论坛</li> -<li>好友发送的私人消息</li></ul> </p> - - - Log - 日志 - - - + Activity @@ -16543,10 +15311,6 @@ at least one peer was not added to a group Blogs 博客 - - Security - 安全 - @@ -16568,10 +15332,6 @@ at least one peer was not added to a group Message 邮件 - - Connect attempt - 连接尝试 - @@ -16588,10 +15348,6 @@ at least one peer was not added to a group Ip security IP安全 - - Log - 日志 - Friend Connected @@ -16602,10 +15358,6 @@ at least one peer was not added to a group Circles 圈子 - - Links - 链接 - Activity @@ -16658,14 +15410,6 @@ at least one peer was not added to a group Chat rooms 聊天室 - - Chat Rooms - 聊天室 - - - Case sensitive - 区分大小写 - Position @@ -16741,24 +15485,16 @@ at least one peer was not added to a group Disable All Toaster temporarily 临时禁用所有弹出消息 - - Feed - 日志订阅 - Systray 系统托盘 - - Count all unread messages - 计数所有未读信息 - NotifyQt - + Passphrase required 需要密码 @@ -16778,12 +15514,12 @@ at least one peer was not added to a group 密码错误! - + Please enter your Retroshare passphrase 请输入您的RetroShare密码 - + Unregistered plugin/executable 未注册插件/可执行程序 @@ -16798,19 +15534,7 @@ at least one peer was not added to a group 请检查您的系统时钟。 - Examining shared files... - 正在检查共享文件... - - - Hashing file - 正在计算文件的校验散列值 - - - Saving file index... - 正在保存文件索引... - - - + Test 测试 @@ -16821,17 +15545,19 @@ at least one peer was not added to a group + Unknown title 未知标题 - + + Encrypted message 加密消息 - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). 为了正常使用聊天大厅,您的电脑时间一定要正确。如果出现下面状况请检查时间(侦测到您与好友之间可能存在几分钟的时间偏差)。 @@ -16839,7 +15565,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online 好友在线 @@ -16891,10 +15617,6 @@ at least one peer was not added to a group PGPKeyDialog - - Dialog - 对话 - Profile info @@ -16960,10 +15682,6 @@ at least one peer was not added to a group This profile has signed your own profile key 节点是否对我的PGP密钥签名 - - Key signatures : - 密钥签名。 - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> @@ -16993,23 +15711,20 @@ p, li { white-space: pre-wrap; } PGP 密钥 - - These options apply to all nodes of the profile: - 这些选项将应用到这个用户的所有节点 + + Friend options + - <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. It helps them to decide whether to allow connections from that key based on your own trust. Signing a key is absolutely optional and cannot be undone, so do it wisely.</span></p></body></html> - <html><head/><body><p><span style=" font-size:10pt;">签署好友的钥匙是表达你对这个好友,给你的其他好友的信任的一种方式。 它可以帮助他们决定是否允许基于您自己的信任的密钥进行连接。 签署密钥是绝对可选的,不能撤销,所以请做出明智的选择.</span></p></body></html> + + These options apply to all nodes of the profile: + 这些选项将应用到这个用户的所有节点 Keysigning: - - Sign PGP key - 签署PGP密钥 - <html><head/><body><p>Click here if you want to refuse connections to nodes authenticated by this key.</p></body></html> @@ -17046,12 +15761,7 @@ p, li { white-space: pre-wrap; } 包含签名 - - Options - 选项 - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> <html><head/><body><p align="justify">RetroShare会定期检查您的好友列表中的可浏览文件与您的传输匹配,以建立直接传输。 在这种情况下,您的好友知道您正在下载文件.</p><p align="justify">要防止此行为(仅适用于此好友),请取消选中此框。 如果您明确要求,您仍然可以执行直接传输。 从你好友的文件列表下载。 此设置应用于同一节点的所有位置.</p></body></html> @@ -17065,10 +15775,6 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this profile (e.g. when the message author is a signed identity that belongs to this profile). This can be used for instance to send files between your own nodes.</p></body></html> - - <html><head/><body><p>This option allows you to automatically download a file that is recommended in an message coming from this node. This can be used for instance to send files between your own nodes. Applied to all locations of the same node.</p></body></html> - <html> <head /> <body> <p>此选项允许您自动下载来自此节点的消息中推荐的文件。 这可以用于例如在您自己的节点之间发送文件。 应用于同一节点的所有位置。</ p> </ body> </ html> - Auto-download recommended files from this node @@ -17101,21 +15807,21 @@ p, li { white-space: pre-wrap; } kB/s - - + + RetroShare RetroShare - - + + Error : cannot get peer details. 错误:无法获取节点详情。 - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) RetroShare 不支持此密钥算法 @@ -17136,7 +15842,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. 信任级别是表达您对此密钥的信任的一种方式。 它不被软件使用,也不是共享的,仅用于方便记住好/坏的密钥。 @@ -17205,10 +15911,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Check the password! - - Maybe password is wrong - 密码可能不对 - You haven't set a trust level for this key. @@ -17216,12 +15918,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile RetroShare用户档案 - + This is your own PGP key, and it is signed by : 这是你的密钥,签名人是: @@ -17247,7 +15949,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat 聊天 @@ -17268,7 +15970,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.删除项目 - + Name: 名称: @@ -17308,7 +16010,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message 撰写消息 @@ -17322,10 +16024,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Friend Connected 好友已连接 - - Connect Attempt - 连接尝试 - Connection refused by peer @@ -17364,17 +16062,13 @@ Warning: In your File-Transfer option, you select allow direct download to No.Unknown 未知 - - Unknown Peer - 未知节点 - Hide 隐藏 - + Send Message 发送消息 @@ -17426,10 +16120,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.Chat with this person as... 跟这个人聊天以 - - Send message to this person - 给这个人发送信息 - Invite to Circle @@ -17488,10 +16178,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p>Anyone in your contact list will automatically have a positive opinion if not set. This allows to automatically raise reputations of used nodes. </p></body></html> <html><head/><body><p> 如果没有设置你通讯录里的所有人都会自动获的正面的评价,这将自动增长使用过的节点的信誉点 </p></body></html> - - automatically give "Positive" opinion to my contacts - 给我的联系人自动给出正面的评价 - use "positive" as the default opinion for contacts (instead of neutral) @@ -17549,13 +16235,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.<html><head/><body><p>为防止已删除的被屏蔽 ID 因为在论坛或频道中使用而被拒绝,被禁止的身份将被保留在列表中,一段时间后,它们会被从禁止列表中"清除" ,如果在论坛、聊天室等中使用,将会重新作为未被屏蔽的 ID 被下载。</p></body></html> - - PhotoCommentItem - - Form - 表格 - - PhotoDialog @@ -17563,23 +16242,11 @@ Warning: In your File-Transfer option, you select allow direct download to No.PhotoShare 照片共享 - - Photo - 照片 - TextLabel 文字标签 - - Comment - 评论 - - - Summary - 概述 - Album / Photo Name @@ -17640,14 +16307,6 @@ Warning: In your File-Transfer option, you select allow direct download to No.... ... - - Add Comment - 添加评论 - - - Write a comment... - 写评论... - Album @@ -17718,10 +16377,6 @@ p, li { white-space: pre-wrap; } Create Album 创建相册 - - View Album - 浏览相册 - Edit Album Details @@ -17743,17 +16398,17 @@ p, li { white-space: pre-wrap; } 幻灯片放映 - + My Albums 我的相册 - + Subscribed Albums 已订阅相册 - + Shared Albums 已分享相册 @@ -17782,7 +16437,7 @@ requesting to edit it! PhotoSlideShow - + Album Name 相册名称 @@ -17841,19 +16496,19 @@ requesting to edit it! - - + + TextLabel - + Posted by - + ago @@ -17889,12 +16544,12 @@ requesting to edit it! PluginItem - + TextLabel 文本标签 - + Show more details about this plugin 显示此插件的更多详情 @@ -18040,60 +16695,6 @@ p, li { white-space:pre-wrap;} Plugin look-up directories 插件查找目录 - - Plugin disabled. Click the enable button and restart Retroshare - 插件已禁用,点击启用按钮重启 RetroShare 后启用。 - - - [disabled] - [禁用] - - - No API number supplied. Please read plugin development manual. - 未提供 API 版本,请阅读插件开发手册。 - - - [loading problem] - [加载问题] - - - No SVN number supplied. Please read plugin development manual. - 未提供 SVN 版本。请阅读插件开发手册。 - - - Loading error. - 载入错误。 - - - Missing symbol. Wrong version? - 缺少符号,版本错误? - - - No plugin object - 无插件对象 - - - Plugins is loaded. - 插件已载入。 - - - Unknown status. - 未知状态。 - - - Check this for developing plugins. They will not -be checked for the hash. However, in normal -times, checking the hash protects you from -malicious behavior of crafted plugins. - 开发插件可选此项。不再校验插件的散列值。 -然而,通常情况下校验插件散列值可以保护您 -远离被修改的有害插件。 - - - - <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Plugins</h1> <p>Plugins are loaded from the directories listed in the bottom list.</p> <p>For security reasons, accepted plugins load automatically until the main Retroshare executable or the plugin library changes. In such a case, the user needs to confirm them again. After the program is started, you can enable a plugin manually by clicking on the "Enable" button and then restart Retroshare.</p> <p>If you want to develop your own plugins, contact the developpers team they will be happy to help you out!</p> - <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;插件</h1> <p>插件从下列列表中目录中加载。</p> <p> 由于安全原因,接受的插件自动加载 直到主RetroShare可执行文件或插件库更改。 在 这种情况下,用户需要再次确认。 程序启动后,您可以通过单击“启用”按钮手动启用插件, 然后重新启动RetroShare。</p> <p>如果要开发自己的插件,请联系开发人员团队, 他们将乐意帮助您!</p> - Plugins @@ -18163,12 +16764,27 @@ malicious behavior of crafted plugins. 设置装口置顶 - + + Ban this person (Sets negative opinion) + 屏蔽这个人 (给出负面评价) + + + + Give neutral opinion + 给出中立评价 + + + + Give positive opinion + 给出正面评价 + + + Choose window color... - + Dock window @@ -18202,14 +16818,6 @@ malicious behavior of crafted plugins. Close conversation? - - Closing this window will end the conversation, notify the peer and remove the encrypted tunnel. - 关闭此窗口将结束会话,同时通知对方节点终止加密聊天通道。 - - - Kill the tunnel? - 终止隧道? - PostedCardView @@ -18229,7 +16837,7 @@ malicious behavior of crafted plugins. - + Vote up @@ -18249,8 +16857,8 @@ malicious behavior of crafted plugins. \/ - - + + Comments @@ -18275,13 +16883,13 @@ malicious behavior of crafted plugins. - - + + Comment - + Comments @@ -18309,20 +16917,12 @@ malicious behavior of crafted plugins. PostedCreatePostDialog - Signed by: - 签名者: - - - Notes - 备注 - - - + Create a new Post - + RetroShare RetroShare @@ -18337,12 +16937,22 @@ malicious behavior of crafted plugins. - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File 载入图片文件 - + Post image @@ -18358,7 +16968,17 @@ malicious behavior of crafted plugins. - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -18368,23 +16988,7 @@ malicious behavior of crafted plugins. - Submit Post - 提交贴文 - - - You are submitting a link. The key to a successful submission is interesting content and a descriptive title. - 您正在提交一个链接。 成功提交的关键是有趣的内容和描述性标题。 - - - Submit - 提交 - - - Submit a new Post - 提交新贴文 - - - + Please add a Title 请添加标题 @@ -18404,12 +17008,22 @@ malicious behavior of crafted plugins. - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -18424,7 +17038,7 @@ malicious behavior of crafted plugins. 发表 - + Post @@ -18435,7 +17049,7 @@ malicious behavior of crafted plugins. 图像 - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -18445,7 +17059,7 @@ malicious behavior of crafted plugins. 标题 - + Link 链接: @@ -18453,44 +17067,12 @@ malicious behavior of crafted plugins. PostedDialog - Posted Links - 发布链接 - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Posted</h1> <p>The posted service allows you to share internet links, that spread among Retroshare nodes like forums and channels</p> <p>Links can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Posted links are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;已发表</h1> <p>已发表服务允许你共享互联网链接,这些链接在 RetroShare 节点,如论坛和 频道中传播</p> <p>链接可以被订阅的用户评论。 推广系统也给机会 推荐重要的链接。</p> <p>链接被共享时没有限制。 点击它们时要小心。</p> <p>发布的链接保留%1天,并且会同步最近%2天的内容,除非你更改此设置。</p> - - - Create Topic - 创建话题 - - - My Topics - 我的主题 - - - Subscribed Topics - 订阅的主题 - - - Popular Topics - 活跃主题 - - - Other Topics - 其它主题 - - - Links - 链接: - - - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -18524,31 +17106,7 @@ malicious behavior of crafted plugins. PostedGroupDialog - Posted Topic - 已发表主题 - - - Add Topic Admins - 添加主题管理员 - - - Select Topic Admins - 选择主题管理员 - - - Create New Topic - 创建新话题 - - - Edit Topic - 编辑话题 - - - Update Topic - 更新主题 - - - + Create New Board @@ -18586,7 +17144,17 @@ malicious behavior of crafted plugins. PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted 订阅已发布的 @@ -18602,7 +17170,7 @@ malicious behavior of crafted plugins. - + Expand 展开 @@ -18617,24 +17185,17 @@ malicious behavior of crafted plugins. - Posted Description - 贴文描述 - - - Loading - 正在载入 - - - New Posted - 新建贴文 - - - + Loading... - + + Never + 从不 + + + New Board @@ -18647,22 +17208,18 @@ malicious behavior of crafted plugins. PostedItem - + 0 0 - Site - 站点 - - - - + + Comments 注释 - + Copy RetroShare Link @@ -18673,12 +17230,12 @@ malicious behavior of crafted plugins. - + Comment 评论 - + Comments @@ -18688,7 +17245,7 @@ malicious behavior of crafted plugins. <p><font color="#ff0000"><b>此消息的作者(ID为%1)被禁止。</b> - + Click to view Picture @@ -18698,21 +17255,17 @@ malicious behavior of crafted plugins. 隐藏 - + Vote up - + Vote down - \/ - \/ - - - + Set as read and remove item 设置为已读并删除条目 @@ -18722,7 +17275,7 @@ malicious behavior of crafted plugins. - + New Comment: 新评论: @@ -18732,7 +17285,7 @@ malicious behavior of crafted plugins. 评论值 - + Name @@ -18773,77 +17326,10 @@ malicious behavior of crafted plugins. - + Loading 正在载入 - - By - 作者 - - - - PostedListWidget - - Form - 表单 - - - Hot - 人气 - - - New - - - - Top - 排名 - - - Today - 今天 - - - Yesterday - 昨天 - - - This Week - 本周 - - - This Month - 本月 - - - This Year - 今年 - - - Submit a new Post - 提交新贴文 - - - Next - 下一条 - - - RetroShare - RetroShare - - - Please create or choose a Signing Id before Voting - 投票前请选择您的签名ID - - - Previous - 上一条 - - - 1-10 - 1-10 - PostedListWidgetWithModel @@ -18863,7 +17349,17 @@ malicious behavior of crafted plugins. - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 0 @@ -18873,15 +17369,15 @@ malicious behavior of crafted plugins. 管理员: - + - + unknown 未知 - + Distribution: 传播范围 @@ -18891,42 +17387,42 @@ malicious behavior of crafted plugins. - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts 贴文 - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -18943,10 +17439,10 @@ malicious behavior of crafted plugins. Hot - + 热门 - + Search @@ -18976,17 +17472,17 @@ malicious behavior of crafted plugins. - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -19001,12 +17497,17 @@ malicious behavior of crafted plugins. - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -19016,27 +17517,31 @@ malicious behavior of crafted plugins. 编辑 - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -19051,7 +17556,7 @@ malicious behavior of crafted plugins. 订阅 - + Never 从不 @@ -19103,17 +17608,17 @@ malicious behavior of crafted plugins. Restricted to members of circle " - + 仅限于圈子的成员" Restricted to members of circle - + 仅限于圈子的成员 Your eyes only - + 只有你能看见 @@ -19125,6 +17630,16 @@ malicious behavior of crafted plugins. No Channel Selected 未选择频道! + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -19133,10 +17648,6 @@ malicious behavior of crafted plugins. Tabs 标签 - - Open each topic in a new tab - 在新标签页打开每个话题 - Open each board in a new tab @@ -19150,10 +17661,6 @@ malicious behavior of crafted plugins. PostedUserNotify - - Posted - 已发表 - Board Post @@ -19222,16 +17729,16 @@ malicious behavior of crafted plugins. 用户档案管理器 - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -19343,7 +17850,7 @@ and use the import button to load it ProfileWidget - + Edit status message 编辑状态消息 @@ -19359,7 +17866,7 @@ and use the import button to load it 用户档案管理器 - + Public Information 公开信息 @@ -19394,12 +17901,12 @@ and use the import button to load it 在线始于: - + Other Information 其它信息 - + My Address 我的地址 @@ -19443,51 +17950,27 @@ and use the import button to load it PulseAddDialog - Post From: - 贴文来自: - - - Account 1 - 账户1 - - - Account 2 - 账户2 - - - Account 3 - 账户3 - - - + Add to Pulse 添加至 Pulse - filter - 过滤 - - - URL Adder - URL 添加 - - - + Display As 显示为 - + URL URL - + GroupLabel - + IDLabel @@ -19497,12 +17980,12 @@ and use the import button to load it 发件人: - + Head - + Head Shot @@ -19532,13 +18015,13 @@ and use the import button to load it 负面的 - - + + Whats happening? - + @@ -19550,12 +18033,22 @@ and use the import button to load it - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -19564,17 +18057,13 @@ and use the import button to load it Cancel 取消 - - Post Pulse to Wire - 向wire发刺探包 - Post - + Reply to Pulse @@ -19589,34 +18078,24 @@ and use the import button to load it - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - 发信人 - - - Date - 日期 - - - ... - ... + + Load Picture File + 载入图片文件 @@ -19627,7 +18106,7 @@ and use the import button to load it - + @@ -19646,7 +18125,7 @@ and use the import button to load it PulseReply - + icn @@ -19656,7 +18135,7 @@ and use the import button to load it - + REPLY @@ -19683,7 +18162,7 @@ and use the import button to load it - + FOLLOW @@ -19693,7 +18172,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -19713,7 +18192,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -19829,7 +18308,7 @@ and use the import button to load it - + FOLLOW @@ -19837,37 +18316,42 @@ and use the import button to load it PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -19899,7 +18383,7 @@ and use the import button to load it - + FOLLOW @@ -19907,8 +18391,8 @@ and use the import button to load it QObject - - + + Confirmation 确认 @@ -20177,12 +18661,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace 节点详情 - + File Request canceled 文件请求已取消 - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. 此版本的 RetroShare 正在使用 OpenPGP-SDK。因此没有使用系统中的共享PGP钥匙环,而是自有钥匙环,在所有RetroShare实例间共享。<br><br> 您似乎没有这种钥匙环,尽管现有 RetroShare 账户中引用了PGP密钥,也许您刚刚才升级至此新版本。 @@ -20217,7 +18701,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace 发生意外错误。请报告错误'RsInit::InitRetroShare unexpected return code %1'。 - + Cannot start Tor Manager! @@ -20251,7 +18735,7 @@ The error reported is:" - + Multiple instances 多实例运行 @@ -20274,6 +18758,26 @@ The error reported is:" Lock 文件: + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -20356,7 +18860,7 @@ Reported error is: 数据转发 - + You appear to have nodes associated to DSA keys: 您似乎有与DSA密钥关联的节点: @@ -20366,7 +18870,7 @@ Reported error is: 当前 RetroShare 的版本不支持 DSA 密钥。所有这些地点都将无法使用。我们很抱歉会这样。 - + enabled 启用 @@ -20376,7 +18880,7 @@ Reported error is: 禁用 - + Move IP %1 to whitelist 添加%1至白名单 @@ -20392,7 +18896,7 @@ Reported error is: - + %1 seconds ago %1 秒前 @@ -20460,7 +18964,7 @@ Security: no anonymous IDs 安全:没有匿名ID - + Join chat room 加入聊天室 @@ -20489,7 +18993,7 @@ Security: no anonymous IDs 无法解析XML文件! - + Indefinitely 无限期 @@ -20669,13 +19173,29 @@ Security: no anonymous IDs Ban list + + + Name + + + Node + 节点 + + + + Address + 地址 + + + + Status 状态 - + NXS @@ -20868,10 +19388,6 @@ Security: no anonymous IDs Click to resume the hashing process - - <p>This certificate contains: - <p>此证书包含: - Idle @@ -20922,6 +19438,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -21084,7 +19612,7 @@ p, li { white-space:pre-wrap;} - + Network Wide 全网匿名可见 @@ -21267,7 +19795,7 @@ p, li { white-space:pre-wrap;} 表单 - + The loading of embedded images is blocked. 已阻止内置图像加载 @@ -21280,7 +19808,7 @@ p, li { white-space:pre-wrap;} RSPermissionMatrixWidget - + Allowed by default 默认允许 @@ -21453,12 +19981,22 @@ p, li { white-space:pre-wrap;} RSTextBrowser - + View &Source - + + Save image + 保存图像 + + + + Copy image + + + + Document source @@ -21466,12 +20004,12 @@ p, li { white-space:pre-wrap;} RSTreeWidget - + Tree View Options 树状视图选项 - + Show Header @@ -21501,14 +20039,6 @@ p, li { white-space:pre-wrap;} Show column … - - Show column... - 显示列 - - - [no title] - [无标题] - RatesStatus @@ -22171,7 +20701,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name @@ -22292,7 +20822,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name @@ -22312,7 +20842,7 @@ If you believe it is correct, remove the corresponding line from the file and re IP - + Profile ID @@ -22370,7 +20900,7 @@ prevents the message to be forwarded to your friends. 信息将被转发给你的好友 - + [ ... Redacted message ... ] [ ... 丢失消息 ... ] @@ -22384,11 +20914,6 @@ prevents the message to be forwarded to your friends. [Unknown] [未知] - - - [ ... Missing Message ... ] - [ ... 丢失消息 ... ] - RsMessageModel @@ -22402,6 +20927,11 @@ prevents the message to be forwarded to your friends. From + + + To + + Subject @@ -22424,13 +20954,18 @@ prevents the message to be forwarded to your friends. - Click to sort by read - 点击按已读排序 + Click to sort by read status + - Click to sort by from - 点击按发件人排序 + Click to sort by author + + + + + Click to sort by destination + @@ -22453,7 +20988,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -22474,7 +21011,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. 重设所有保存的RetroShare设置。 @@ -22535,7 +21072,7 @@ prevents the message to be forwarded to your friends. 设置RetroShare语言 - + Unable to open log file '%1': %2 无法打开日志文件 "%1':%2 @@ -22556,11 +21093,7 @@ prevents the message to be forwarded to your friends. 无法创建目录:%1 - Revision - Revision - - - + opmode @@ -22590,7 +21123,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: 指定的语言代码无效: @@ -22608,7 +21141,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. 注册表访问错误。也许你需要管理员权限。 @@ -22625,12 +21158,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) 在此输入关键词(至少3个字符长) - + Start Search 开始搜索 @@ -22692,7 +21225,7 @@ prevents the message to be forwarded to your friends. 清除 - + KeyWords 关键词 @@ -22707,7 +21240,7 @@ prevents the message to be forwarded to your friends. 搜索 ID - + Filename 文件名 @@ -22807,23 +21340,23 @@ prevents the message to be forwarded to your friends. 下载所选项目 - + File Name 文件名称 - + Download 下载 - + Copy RetroShare Link 复制 RetroShare 链接 - + Send RetroShare Link 发送 RetroShare 链接 @@ -22833,7 +21366,7 @@ prevents the message to be forwarded to your friends. - + Download Notice 下载提示 @@ -22870,7 +21403,7 @@ prevents the message to be forwarded to your friends. 删除全部 - + Folder 文件夹 @@ -22881,17 +21414,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) 新建 RetroShare 链接 - + Open Folder 打开文件夹 - + Create Collection... 创建资源集合 @@ -22911,7 +21444,7 @@ prevents the message to be forwarded to your friends. 从集合文件中下载... - + Collection 资源集合 @@ -22919,7 +21452,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details 节点详情 @@ -22935,22 +21468,22 @@ prevents the message to be forwarded to your friends. 删除条目 - + IP address: IP 地址: - + Peer ID: 节点 ID - + Location: 位置: - + Peer Name: 节点名称 @@ -22967,7 +21500,7 @@ prevents the message to be forwarded to your friends. 隐藏 - + but reported: 已报告 @@ -22992,8 +21525,8 @@ prevents the message to be forwarded to your friends. <p>这是你的好友声称他连接到的IP。 如果你刚改变IP,这是只是一个错误警告。 如果没有,那意味着你与这个好友的连接是由一个中间的节点转发的,这是可疑的。</p> - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> <html><head/><body><p>这个警告是为了保护你免受流量转发攻击。在这种情况下,你连接的好友不会看到你的外部 IP,而会看到攻击者的 IP。</p><p><br/></p><p>但是,如果你只是因为某些原因(某些ISP经常强制更改IP)而更改了 IP,则此警告只会告诉你在 RetroShare 得知 IP 更改之前连接到新 IP 的好友。这种情况是正常的。</p><p><br/></p><p>可以通过将你自己的 IP (例如你的 ISP 的范围)列入白名单,或通过在“选项” -> “通知” ->“事件中心”中完全禁用这些警告来简单地禁止虚假警告。</p></body></html> @@ -23001,7 +21534,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare 希望成为您的 RetroShare 好友 @@ -23032,7 +21565,7 @@ prevents the message to be forwarded to your friends. - + Expand 展开 @@ -23077,12 +21610,12 @@ prevents the message to be forwarded to your friends. 状态: - + Write Message 写邮件 - + Connect Attempt 连接尝试 @@ -23102,17 +21635,22 @@ prevents the message to be forwarded to your friends. 未知(出站)连接企图 - + Unknown Security Issue 未知安全问题 - - A unknown peer + + SSL request - + + An unknown peer + + + + Unknown 未知 @@ -23122,11 +21660,7 @@ prevents the message to be forwarded to your friends. - Unknown Peer - 未知节点 - - - + Hide 隐藏 @@ -23136,7 +21670,7 @@ prevents the message to be forwarded to your friends. 您是否要删除此好友? - + Certificate has wrong signature!! This peer is not who he claims to be. 证书有错误的签名! 这个节点不是他自称的那样。 @@ -23146,12 +21680,12 @@ prevents the message to be forwarded to your friends. 丢失/损坏的证书 。不是一个真是RetroShare用户 - + Certificate caused an internal error. 证书导致了一个内部错误。 - + Peer/node not in friendlist (PGP id= 节点不在好友列表里(PGP ID= @@ -23210,12 +21744,12 @@ prevents the message to be forwarded to your friends. - + Local Address 本地地址 - + NAT @@ -23236,22 +21770,22 @@ prevents the message to be forwarded to your friends. 端口: - + Local network 本地网络 - + External ip address finder 公网 IP 探测服务 - + UPnP UPnP - + Known / Previous IPs: 已知/先前的 IP @@ -23267,21 +21801,16 @@ behind a firewall or a VPN. 下连接的情况。 - - Allow RetroShare to ask my ip to these websites: - 允许 RetroShare 通过如下网站确定外网IP: - - - - - + + + kB/s kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. 可接受的端口范围从 10 到 65535 。正常情况下低于 1024 的端口被你的系统保留。 @@ -23291,23 +21820,46 @@ behind a firewall or a VPN. 可接受的端口范围从 10 到 65535 。正常情况下低于 1024 的端口被你的系统保留。 - + Onion Address 隐藏地址 - + Discovery On (recommended) 节点探索开启(推荐) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off 节点探索关闭 @@ -23317,7 +21869,7 @@ behind a firewall or a VPN. 隐藏 - 查看配置 - + I2P Address I2P 地址 @@ -23342,37 +21894,95 @@ behind a firewall or a VPN. 传入正常 - - + + + Proxy seems to work. 代理看起来正常工作 - + + I2P proxy is not enabled I2P 代理没有启用 - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client 客户端 @@ -23387,71 +21997,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. 未知 - - - - BOB is processing a request - - - - - connectivity check - 检查连接 - - - - generating key - 正在生成密钥 - - - - starting up - 启动中 - - - - shuting down - 关闭中 - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -23461,22 +22007,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. 通过隐藏服务对你可达 @@ -23490,12 +22021,12 @@ Also check your ports! 另外请检查您的端口! - + [Hidden mode] [隐身模式] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> <html><head/><body><p>这将清除已知地址列表。 如果由于某些原因您的地址列表包含无效/不相关/过期的地址,您希望避免传递给您的好友作为联系地址,此操作是有用的。</p></body></html> @@ -23505,7 +22036,7 @@ Also check your ports! 清除 - + Download limit (KB/s) 下载速率 (KB/s) @@ -23520,23 +22051,23 @@ Also check your ports! 上传速率 (KB/s) - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> <html><head/><body><p>上传限制涉及整个软件。上传限制太小可能最终会阻止低优先级服务(论坛,频道)。 最小的建议值为50KB/s。</p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -23547,17 +22078,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings 启用高级设置 @@ -23567,12 +22088,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 高级模式 - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -23582,17 +22098,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 127.0.0.1 - - I2P proxy port - I2P代理端口 - - - - BOB accessible - - - - + Address 地址 @@ -23632,7 +22138,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start 开始 @@ -23647,12 +22153,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why 停止 - - BOB status - - - - + Incoming 接收 @@ -23688,7 +22189,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay 中继 @@ -23743,7 +22269,7 @@ If you have issues connecting over Tor check the Tor logs too. 总计: - + Warning: This bandwidth adds up to the max bandwidth. @@ -23768,7 +22294,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -23780,7 +22306,7 @@ If you have issues connecting over Tor check the Tor logs too. 网络 - + IP Filters IP过滤 @@ -23803,7 +22329,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status 状态 @@ -23863,17 +22389,28 @@ If you have issues connecting over Tor check the Tor logs too. 添加到白名单 - + Hidden Service Configuration 隐藏服务配置 - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>这是Tor代理的端口。你的RetroShare节点可以用这个端口连接到</p><p>隐藏节点。当你电脑上的端口激活后右边这个指示灯会变绿。</p><p>这并不意味着您的RetroShare流量通过Tor转发。只有你 </p><p>连接到隐藏节点 , 或者你自己运行一个隐藏节点才会正常工作。</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>如果左边所示的监听端口在你的电脑上被成功激活,此LED灯会变绿,</p><p>这不意味着你的RetroShare流量通过Tor通信。只有连接到隐藏节点</p><p>或者您自己运行一个隐藏节点时才会通过Tor通信。</p></body></html> @@ -23889,18 +22426,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay I2P 传出代理正常 - + Service Address 服务地址 @@ -23935,12 +22472,12 @@ If you have issues connecting over Tor check the Tor logs too. 请填写服务地址 - + IP Range IP 范围 - + Reported by DHT for IP masquerading DHT报告IP伪装 @@ -23963,22 +22500,22 @@ If you have issues connecting over Tor check the Tor logs too. 被你添加 - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> <html><head/><body><p>从以下来源收集白名单的IP:来自手动交换的证书中的IP,您在此窗口中输入的IP范围或安全订阅项。</p><p>RetroShare的默认行为是(1)始终允许连接到 IP 的节点在白名单中,即使该 IP 也被列入黑名单; (2)可选地要求 IP 在白名单中。您可以在每个 RetroShare 节点的窗口“详情”中更改每个节点的这种行为。 </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> <html><head/><body><p>DHT允许您使用BitTorrent的DHT网络回应好友的连接请求。它可以极大地改善连通性。没有信息被实际存储在DHT中。它仅用作代理系统与其他RetroShare节点联系。</p><p>节点探索服务将您信任好友的节点名称和ID发送给已连接的节点,来帮助他们选择新朋友。 但节点永远不会自动建立好友关系,并且节点仍然需要相互添加信任才会允许连接。</p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> <html><head/><body><p>如果您启用了该操作,一旦RetroShare设法从下面列出的网站获取你的IP,则符号将变绿。RetroShare也会使用其他方法来查找你的IP。</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> <html><head/><body><p>该列表将自动填充在多个来源收集的信息:DHT报告的伪装节点,您输入的IP范围以及您好友报告的IP范围。 默认设置应保护您免受大规模流量中继。</p><p>自动猜测伪装IP可以将您的好友的IP置于黑名单中,这时请使用上下文菜单将其列入白名单。</p></body></html> @@ -24013,7 +22550,7 @@ If you have issues connecting over Tor check the Tor logs too. 自动屏蔽DHT伪装IP的范围 - + Outgoing Manual Tor/I2P @@ -24023,12 +22560,12 @@ If you have issues connecting over Tor check the Tor logs too. Tor Socks 代理 - + Tor outgoing Okay Tor 传出代理正常 - + Tor proxy is not enabled Tor 代理没有启用 @@ -24108,7 +22645,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with 选择您希望与之共享个人发帖密钥的节点 @@ -24118,12 +22655,12 @@ If you have issues connecting over Tor check the Tor logs too. 共享给好友 - + Share 分享 - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. 您可以通过分享让你的好友了解您的频道。 选择您的好友来分享频道。 @@ -24142,7 +22679,7 @@ Select the Friends with which you want to Share your Channel. 共享文件夹管理器 - + Shared directory 共享文件目录 @@ -24162,17 +22699,17 @@ Select the Friends with which you want to Share your Channel. 可见性 - + Add new 添加新的共享文件夹 - + Cancel 取消 - + Add a Share Directory 添加共享目录 @@ -24182,7 +22719,7 @@ Select the Friends with which you want to Share your Channel. 删除 - + Apply and close 应用并关闭 @@ -24273,7 +22810,7 @@ Select the Friends with which you want to Share your Channel. 目录未找到或目录名称不可接受。 - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. 这是一个共享文件夹的列表。您可以使用底部的按钮添加和删除文件夹。当您添加新文件夹时,该文件夹中所有文件都会被共享。您可以单独设置每个共享文件夹的共享标志。 @@ -24281,7 +22818,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files 共享 @@ -24332,11 +22869,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files 校验文件 - + Download selected 下载所选项目 @@ -24346,7 +22888,7 @@ Select the Friends with which you want to Share your Channel. 下载 - + Copy retroshare Links to Clipboard 复制 RetroShare 链接至剪切板 @@ -24361,7 +22903,7 @@ Select the Friends with which you want to Share your Channel. 发送 RetroShare 链接 - + Some files have been omitted 某些文件已被忽略 @@ -24377,7 +22919,7 @@ Select the Friends with which you want to Share your Channel. 推荐内容 - + Create Collection... 创建资源集合 @@ -24402,7 +22944,7 @@ Select the Friends with which you want to Share your Channel. 从集合文件中下载... - + Some files have been omitted because they have not been indexed yet. @@ -24545,12 +23087,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration 载入设置 - + Create interface 创建界面 @@ -24574,7 +23116,7 @@ Select the Friends with which you want to Share your Channel. 记住密码 - + Log In 登录 @@ -24929,7 +23471,7 @@ This choice can be reverted in settings. 个人状态消息 - + Message: 消息: @@ -25176,7 +23718,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags 删除所有标签 @@ -25212,12 +23754,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: Tor状态: - + + + Unknown 未知 @@ -25227,18 +23772,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: - 隐藏服务地址: - - - - Tor bootstrap status: + + Hidden address: - - + + Not set @@ -25248,12 +23788,57 @@ p, li { white-space: pre-wrap; } Onion地址: - + + Error + 错误 + + + + Not connected + 未连接 + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] [等待Tor就绪] @@ -25261,7 +23846,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor Tor @@ -25271,7 +23856,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline Tor现在离线 @@ -25282,11 +23867,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -25314,7 +23900,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options 传输选项 @@ -25325,7 +23911,7 @@ p, li { white-space: pre-wrap; } 最多同时下载任务: - + Shared Directories 共享文件目录 @@ -25335,22 +23921,27 @@ p, li { white-space: pre-wrap; } 自动共享接收文件目录(推荐) - - Edit Share - 编辑分享 - - - + Directories - + + Configure shared directories + 设置共享文件目录 + + + Auto-check shared directories every 自动检查共享目录,每隔 + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) (分钟) @@ -25435,7 +24026,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -25444,7 +24035,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -25469,7 +24065,12 @@ p, li { white-space: pre-wrap; } 允许直接下载: - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming 顺序 @@ -25528,37 +24129,13 @@ p, li { white-space: pre-wrap; } Trust friend nodes with banned files - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;">可以在非好友间传输数据和搜索请求。这些数据只会通过已连接的好友进行匿名传输。</span></p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">你可以在共享文件对话框中对每个共享文件夹分别设置以下共享标记:</span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">好友可见:</span>文件对好友可见。</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">匿名共享:</span> 文件可以通过 F2F 隧道匿名访问。</li></ul></body></html> - Max. tunnel req. forwarded per second: 每秒最多转发隧道请求数量 - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - <html><head/><body><p><span style=" font-weight:600;">顺序</span> 让传输以递增的顺序请求 1MB 的文件块,便于下载时预览。<span style=" font-weight:600;">  随机</span> 是完全随机的,有利于swarm集群下载。 Progressivexis purely random and favors swarming behavior. <span style=" font-weight:600;">渐进</span> 是一个折中方法,在部分文件末尾不到50MB内随机选择下一个块。 这允许一些随机性,同时防止大量空文件的初始化时间。</p></body></html> - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> <html><head/><body><p>如果磁盘空间低于此限制,RetroShare将暂停所有传输并且保存配置文件。 这可以防止某些系统丢失信息。 当这种情况发生时,弹出窗口会提醒你。</p></body></html> @@ -25568,7 +24145,17 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>这个值控制您的节点每秒可以转发多少个隧道请求。</p><p>如果你网络带宽充裕,可以将其提高到 30-40,以允许更长的隧道通过。 要慎重,因为这会产生许多小数据包,可能会显著减慢你自己的文件传输速度。</p><p>默认值为20。如果你不确定,保持默认值。</p></body></html> - + + Warning + 警告 + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory 设置文件接收目录 @@ -25596,7 +24183,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed 下载完成 @@ -25620,39 +24207,23 @@ p, li { white-space: pre-wrap; } %1 completed transfer - - You have %1 completed downloads - 您有 %1 个下载任务已完成 - - - You have %1 completed download - 您有 %1 个下载任务已完成 - - - %1 completed downloads - %1 个下载任务已完成 - - - %1 completed download - %1 个下载任务已完成 - TransfersDialog - - + + Downloads 下载 - + Uploads 上传 - + Name i.e: file name 名称 @@ -25859,16 +24430,7 @@ p, li { white-space: pre-wrap; } 指定... - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1> <p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p> <p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p> <p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - <h1><img width="32" src=":/images/64px_help.png">&nbsp;&nbsp;文件传输</h1> -<p>RetroShare 支持两种文件传输方式:来自好友的直接传输,及匿名远程隧道传输。 -此外文件传输支持多文件源及swarm集群(下载时可以作为文件源)。</p> -<p>你可以通过左侧的 <img src=":/images/directoryadd_24x24_shadow.png" width=16 /> 图标共享文件。 -这些文件将在我的文件标签中列出。<p></p>你可以在好友的文件标签中决定每个好友分组是否可以看到你的文件。</p> -<p>搜索标签列出来自好友文件列表中的文件,及通过多跳隧道系统匿名可见的远程文件。</p> - - - + Move in Queue... 队列位置... @@ -25893,7 +24455,7 @@ p, li { white-space: pre-wrap; } 选择目录 - + Anonymous end-to-end encrypted tunnel 0x 匿名和端对端加密路由 0x @@ -25914,7 +24476,7 @@ p, li { white-space: pre-wrap; } RetroShare - + @@ -25947,7 +24509,17 @@ p, li { white-space: pre-wrap; } 文件 %1 未完成。但如果是媒体文件,仍可尝试预览。 - + + Warning + 警告 + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name 修改文件名 @@ -25962,7 +24534,7 @@ p, li { white-space: pre-wrap; } 输入新的有效文件名 - + Expand all 全部展开 @@ -26089,23 +24661,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns - + File Transfers 文件传输 - + Path 路径 @@ -26115,7 +24682,7 @@ p, li { white-space: pre-wrap; } 显示路径栏 - + Could not delete preview file 不能删除之前文件 @@ -26125,7 +24692,7 @@ p, li { white-space: pre-wrap; } 再试一次? - + Create Collection... 创建资源集合 @@ -26140,7 +24707,12 @@ p, li { white-space: pre-wrap; } 打开资源集合 - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Collection 资源集合 @@ -26150,7 +24722,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x 匿名Turtle路由 @@ -26371,10 +24943,6 @@ p, li { white-space: pre-wrap; } File transfer tunnels - - Anonymous tunnels - 匿名Turtle路由 - Authenticated tunnels @@ -26568,12 +25136,17 @@ p, li { white-space: pre-wrap; } 表单 - + Enable Retroshare WEB Interface 启用RetroShare网页界面。 - + + Status: + 状态: + + + Web parameters 网页参数 @@ -26607,31 +25180,33 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Note: these settings do not affect retroshare-service, which has a command line switch to activate the web interface and select the listening port.</p></body></html> - - Port: - 端口: - Allow access from all IP addresses (Default: localhost only) - Apply setting and start browser - 应用设置并打开浏览器 - - - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;网页界面</h1> <p>网页界面允许您从浏览器控制 RetroShare 。多个设备可以通过一个 RetroShare 实例共享控制。 所以,您可以在平板电脑上开始对话,然后使用台式电脑继续操作。</p> <p>警告:不要将网络接口暴露在互联网上,因为没有访问控制和加密。 如果要通过互联网使用网络接口,请使用SSH隧道或代理来保护连接。</p> - + Webinterface not enabled 不打开网页界面 @@ -26641,12 +25216,12 @@ p, li { white-space: pre-wrap; } 无法打开网页界面,请到设置 -> 网络界面里进行设置 - + failed to start Webinterface 无法打开网页界面 - + Webinterface 网页界面 @@ -26783,11 +25358,7 @@ p, li { white-space: pre-wrap; } Wiki页面 - New Group - 新建分组 - - - + Page Name 页面名称 @@ -26802,7 +25373,7 @@ p, li { white-space: pre-wrap; } 原始 ID - + << << @@ -26890,7 +25461,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History 页面历史版本 @@ -26925,7 +25496,7 @@ p, li { white-space: pre-wrap; } 页面Id - + \/ \/ @@ -26955,14 +25526,18 @@ p, li { white-space: pre-wrap; } 标签 - - + + History + 历史 + + + Show Edit History 显示编辑历史 - + Status 状态 @@ -26983,7 +25558,7 @@ p, li { white-space: pre-wrap; } 撤销 - + Submit 提交 @@ -27055,10 +25630,6 @@ p, li { white-space: pre-wrap; } WireDialog - - TimeRange - 时间范围 - Create Account @@ -27070,16 +25641,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - 刷新 - - - + Settings @@ -27094,7 +25656,7 @@ p, li { white-space: pre-wrap; } 其他 - + Who to Follow @@ -27114,7 +25676,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -27144,85 +25706,17 @@ p, li { white-space: pre-wrap; } - Last Month - 上月 - - - Last Week - 上周 - - - Today - 今天 - - - New - 新建 - - - from - 自从 - - - until - 直到 - - - Search/Filter - 搜索/过滤 - - - Network Wide - 全网匿名可见 - - - Manage Accounts - 管理账户 - - - Showing: - 当前显示: - - - + Yourself 我自己 - - Friends - 好友 - Following 以下 - Custom - 自定义 - - - Account 1 - 账户1 - - - Account 2 - 账户2 - - - Account 3 - 账户3 - - - CheckBox - 复选框 - - - Post Pulse to Wire - 向wire发刺探包 - - - + RetroShare @@ -27285,35 +25779,42 @@ p, li { white-space: pre-wrap; } - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + 删除 + + + Location: 位置: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -27358,11 +25859,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + 不适用 + + + + Following + 以下 + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) 未知 @@ -27440,7 +25971,7 @@ p, li { white-space: pre-wrap; } %1 年 %2 天 - + k e.g: 3.1 k k @@ -27473,15 +26004,11 @@ p, li { white-space: pre-wrap; } Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif *.webp) - - Pictures (*.png *.jpeg *.xpm *.jpg *.tiff *.gif) - 图片 (*.png *.xpm *.jpg *.tiff *.gif *.jpeg) - pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/lang/retroshare_zh_TW.ts b/retroshare-gui/src/lang/retroshare_zh_TW.ts index 92a16dae4..2acc19ab2 100644 --- a/retroshare-gui/src/lang/retroshare_zh_TW.ts +++ b/retroshare-gui/src/lang/retroshare_zh_TW.ts @@ -121,12 +121,12 @@ - + Search Criteria - + Add a further search criterion. @@ -136,7 +136,7 @@ - + Cancels the search. @@ -156,13 +156,6 @@ - - AlbumCreateDialog - - Description: - 描述: - - AlbumDialog @@ -191,10 +184,6 @@ Caption - - Description: - 描述: - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -551,7 +540,7 @@ p, li { white-space: pre-wrap; } - + Warning: The services here are experimental. Please help us test them. But Remember: Any data here *WILL* be lost when we upgrade the protocols. @@ -577,10 +566,23 @@ p, li { white-space: pre-wrap; } + + AspectRatioPixmapLabel + + + Save image + + + + + Copy image + + + AttachFileItem - + %p Kb @@ -623,7 +625,7 @@ p, li { white-space: pre-wrap; } 刪除 - + Set your Avatar picture @@ -710,7 +712,7 @@ p, li { white-space: pre-wrap; } - + Always on Top @@ -729,10 +731,6 @@ p, li { white-space: pre-wrap; } % Opaque - - Cancel - 取消 - Since: @@ -810,7 +808,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidgetBase - + Comment @@ -840,12 +838,12 @@ p, li { white-space: pre-wrap; } - + <p><font color="#ff0000"><b>The author of this message (with ID %1) is banned.</b> - + ago @@ -853,7 +851,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_card - + Vote up @@ -873,7 +871,7 @@ p, li { white-space: pre-wrap; } - + Posted by @@ -911,7 +909,7 @@ p, li { white-space: pre-wrap; } BoardPostDisplayWidget_compact - + Vote up @@ -931,7 +929,7 @@ p, li { white-space: pre-wrap; } - + Click to view picture @@ -961,7 +959,7 @@ p, li { white-space: pre-wrap; } - + Toggle Message Read Status @@ -971,7 +969,7 @@ p, li { white-space: pre-wrap; } 新建 - + TextLabel @@ -979,12 +977,12 @@ p, li { white-space: pre-wrap; } BoardsCommentsItem - + I like this - + 0 @@ -1004,18 +1002,18 @@ p, li { white-space: pre-wrap; } - + New Comment - + Copy RetroShare Link - + Expand 展開 @@ -1030,12 +1028,12 @@ p, li { white-space: pre-wrap; } 刪除項目 - + Name - + Comm value @@ -1204,17 +1202,17 @@ p, li { white-space: pre-wrap; } ChannelPage - + Channels - + Tabs - + General @@ -1224,7 +1222,17 @@ p, li { white-space: pre-wrap; } - + + Downloads + + + + + Maximum Auto Download Size (in GBs) + + + + Open each channel in a new tab @@ -1232,7 +1240,7 @@ p, li { white-space: pre-wrap; } ChannelPostDelegate - + files @@ -1255,7 +1263,7 @@ into the image, so as to ChannelsCommentsItem - + I like this @@ -1280,18 +1288,18 @@ into the image, so as to - + New Comment - + Copy RetroShare Link - + Expand 展開 @@ -1306,7 +1314,7 @@ into the image, so as to 刪除項目 - + Name @@ -1316,17 +1324,7 @@ into the image, so as to - - Comment - - - - - Comments - - - - + Hide 隱藏 @@ -1334,7 +1332,7 @@ into the image, so as to ChatLobbyDialog - + Name @@ -1525,7 +1523,7 @@ into the image, so as to ChatLobbyToaster - + Show Chat Lobby @@ -1558,13 +1556,14 @@ into the image, so as to - + + Unknown Lobby - - + + Remove All @@ -1572,13 +1571,13 @@ into the image, so as to ChatLobbyWidget - - + + Name - + Count @@ -1588,29 +1587,7 @@ into the image, so as to - - Private Subscribed chat rooms - - - - - - Public Subscribed chat rooms - - - - - Private chat rooms - - - - - - Public chat rooms - - - - + Create chat room @@ -1620,7 +1597,7 @@ into the image, so as to - + Create a non anonymous identity and enter this room @@ -1677,12 +1654,12 @@ Double click a chat room to enter and chat. - + %1 invites you to chat room named %2 - + Choose a non anonymous identity for this chat room: @@ -1692,23 +1669,42 @@ Double click a chat room to enter and chat. - + [No topic provided] - + + Private Subscribed + + + + + + Public Subscribed + + + + + Private - + + + Public - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1><p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p><p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p><p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!</p> + + + + Anonymous IDs accepted @@ -1718,27 +1714,22 @@ Double click a chat room to enter and chat. - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Chat Rooms</h1> <p>Chat rooms work pretty much like IRC. They allow you to talk anonymously with tons of people without the need to make friends.</p> <p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you invite them with <img src=":/icons/png/add.png" width=%2/>). Once you have been invited to a private room, you will be able to see it when your friends are using it.</p> <p>The list at left shows chat lobbies your friends are participating in. You can either <ul> <li>Right click to create a new chat room</li> <li>Double click a chat room to enter, chat, and show it to your friends</li> </ul> Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock! </p> - - - - + Add Auto Subscribe - + Search Chat lobbies - + Search Name - + Columns @@ -1753,47 +1744,47 @@ Double click a chat room to enter and chat. - + Chat Room info - + Chat room Name: - + Chat room Id: - + Topic: - + Type: 類型 - + Security: - + Peers: - - - - - - + + + + + + TextLabel @@ -1808,7 +1799,7 @@ Double click a chat room to enter and chat. - + Show 顯示 @@ -1828,7 +1819,7 @@ Double click a chat room to enter and chat. ChatMsgItem - + Remove Item 刪除項目 @@ -1873,7 +1864,7 @@ Double click a chat room to enter and chat. ChatPage - + General @@ -1888,7 +1879,7 @@ Double click a chat room to enter and chat. - + Enable custom fonts @@ -1908,7 +1899,7 @@ Double click a chat room to enter and chat. - + General settings @@ -1933,7 +1924,7 @@ Double click a chat room to enter and chat. - + Blink tab icon @@ -1963,7 +1954,7 @@ Double click a chat room to enter and chat. - + Change Chat Font @@ -1973,7 +1964,7 @@ Double click a chat room to enter and chat. - + History @@ -1997,7 +1988,7 @@ Double click a chat room to enter and chat. - + Choose your default font for Chat. @@ -2067,12 +2058,22 @@ Double click a chat room to enter and chat. - + Search - + + When focus on text browser after showing chat room + + + + + Shrink text edit field when not needed + + + + Fonts @@ -2082,7 +2083,17 @@ Double click a chat room to enter and chat. - + + If your system is set up correctly, this next square should measure 1 cm. + + + + + This next square is scaled accordingly to your system font size. + + + + Chat rooms @@ -2179,7 +2190,7 @@ Double click a chat room to enter and chat. - + Case sensitive 區分大小寫 @@ -2285,7 +2296,7 @@ Double click a chat room to enter and chat. ChatToaster - + Show Chat @@ -2321,7 +2332,7 @@ Double click a chat room to enter and chat. ChatWidget - + Close @@ -2356,12 +2367,12 @@ Double click a chat room to enter and chat. - + <html><head/><body><p>Chat menu</p></body></html> - + Insert emoticon @@ -2441,11 +2452,6 @@ Double click a chat room to enter and chat. Insert horizontal rule - - - Save image - - Import sticker @@ -2483,7 +2489,7 @@ Double click a chat room to enter and chat. - + is typing... @@ -2505,7 +2511,7 @@ after HTML conversion. - + Do you really want to physically delete the history? @@ -2555,7 +2561,7 @@ after HTML conversion. - + Find Case Sensitively @@ -2577,7 +2583,7 @@ after HTML conversion. - + <b>Find Previous </b><br/><i>Ctrl+Shift+G</i> @@ -2592,12 +2598,12 @@ after HTML conversion. - + (Status) - + Attach a File @@ -2613,12 +2619,12 @@ after HTML conversion. - + <b>Mark this selected text</b><br><i>Ctrl+M</i> - + Person id: @@ -2629,12 +2635,12 @@ Double click on it to add his name on text writer. - + Unsigned - + items found. @@ -2654,7 +2660,7 @@ Double click on it to add his name on text writer. - + Don't stop to color after @@ -2680,7 +2686,7 @@ Double click on it to add his name on text writer. CirclesDialog - + Showing details: @@ -2702,7 +2708,7 @@ Double click on it to add his name on text writer. - + Personal Circles @@ -2728,7 +2734,7 @@ Double click on it to add his name on text writer. - + Friends @@ -2788,7 +2794,7 @@ Double click on it to add his name on text writer. - + External Circles (Admin) @@ -2804,7 +2810,7 @@ Double click on it to add his name on text writer. - + Circles @@ -2856,45 +2862,45 @@ Double click on it to add his name on text writer. - + RetroShare - + - + Error : cannot get peer details. - + Retroshare ID - + <p>This Retroshare ID contains: - + <p>This certificate contains: - + <li> <b>onion address</b> and <b>port</b> + - <li><b>IP address</b> and <b>port</b>: - + <b>IP address</b> and <b>port</b>: @@ -2904,7 +2910,7 @@ Double click on it to add his name on text writer. - + Not connected @@ -2986,12 +2992,17 @@ Double click on it to add his name on text writer. - + <li>a <b>node ID</b> and <b>name</b> - + + <b>DNS:</b> : + + + + <p>You can use this Retroshare ID to make new friends. Send it by email, or give it hand to hand.</p> @@ -3011,7 +3022,7 @@ Double click on it to add his name on text writer. - + with @@ -3079,7 +3090,7 @@ Double click on it to add his name on text writer. - + @@ -3095,12 +3106,12 @@ Double click on it to add his name on text writer. - + Peer details - + Name: 名稱: @@ -3110,17 +3121,17 @@ Double click on it to add his name on text writer. - + Options 選項 - + <html><head/><body><p>This box expects your friend's Retroshare certificate. WARNING: this is different from your friend's profile key. Do not paste your friend's profile key here (not even a part of it). It's not going to work.</p></body></html> - + Add friend to group: @@ -3130,7 +3141,7 @@ Double click on it to add his name on text writer. - + Please paste below your friend's Retroshare ID @@ -3155,12 +3166,22 @@ Double click on it to add his name on text writer. - + + Signers: + + + + + Known IP: + + + + Add as friend to connect with - + Sorry, some error appeared @@ -3180,32 +3201,27 @@ Double click on it to add his name on text writer. - + Key validity: - + Profile ID: - - Signers - - - - + <html><head/><body><p><span style=" font-size:10pt;">Signing a friend's key is a way to express your trust into this friend, to your other friends. The signatures below cryptographically attest that owners of the listed keys recognise the current PGP key as authentic.</span></p></body></html> - + This peer is already on your friend list. Adding it might just set it's ip address. - + To accept the Friend Request, click the Accept button. @@ -3251,17 +3267,17 @@ Double click on it to add his name on text writer. - + Certificate Load Failed - + Not a valid Retroshare certificate! - + RetroShare Invitation @@ -3281,12 +3297,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This is your own certificate! You would not want to make friend with yourself. Wouldn't you? - + @@ -3294,7 +3310,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already on your trusted list @@ -3334,7 +3350,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Profile password needed. @@ -3359,7 +3375,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Valid Retroshare ID @@ -3369,7 +3385,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + RetroShare Certificate (*.rsc );;All Files (*) @@ -3408,7 +3424,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + IP-Addr: @@ -3418,7 +3434,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Show Advanced options @@ -3443,7 +3459,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + This key is already in your keyring @@ -3456,7 +3472,7 @@ even if you don't make friends. - + Certificate has wrong version number. Remember that v0.6 and v0.5 networks are incompatible. @@ -3491,7 +3507,7 @@ even if you don't make friends. - + No IP in this certificate! @@ -3501,12 +3517,7 @@ even if you don't make friends. - - [Unknown] - - - - + Added with certificate from %1 @@ -3571,7 +3582,7 @@ even if you don't make friends. - + UDP Setup @@ -3599,7 +3610,7 @@ p, li { white-space: pre-wrap; } - + Connection Assistant @@ -3609,17 +3620,20 @@ p, li { white-space: pre-wrap; } - + + Unknown State - + + Offline - + + Behind Symmetric NAT @@ -3629,12 +3643,14 @@ p, li { white-space: pre-wrap; } - + + NET Restart - + + Behind NAT @@ -3644,7 +3660,8 @@ p, li { white-space: pre-wrap; } - + + NET STATE GOOD! @@ -3669,7 +3686,7 @@ p, li { white-space: pre-wrap; } - + Lookup requires DHT @@ -3961,7 +3978,7 @@ p, li { white-space: pre-wrap; } - + @@ -3969,7 +3986,8 @@ p, li { white-space: pre-wrap; } - + + UNVERIFIABLE FORWARD! @@ -3979,7 +3997,7 @@ p, li { white-space: pre-wrap; } - + Searching @@ -4015,12 +4033,12 @@ p, li { white-space: pre-wrap; } - + Name - + <html><head/><body><p>The circle name, contact author and invited member list will be visible to all invited members. If the circle is not private, it will also be visible to neighbor nodes of the nodes who host the invited members.</p></body></html> @@ -4040,7 +4058,7 @@ p, li { white-space: pre-wrap; } - + IDs @@ -4060,18 +4078,18 @@ p, li { white-space: pre-wrap; } - + Cancel 取消 - + Nickname - + Invited Members @@ -4086,11 +4104,7 @@ p, li { white-space: pre-wrap; } - Type - 類型 - - - + Name: 名稱: @@ -4130,19 +4144,19 @@ p, li { white-space: pre-wrap; } - - + + RetroShare - + Please set a name for your Circle - + No Restriction Circle Selected @@ -4152,12 +4166,24 @@ p, li { white-space: pre-wrap; } - + + Circle created + + + + + Your new circle has been created: + Name: %1 + Id: %2. + + + + [Unknown] - + Add 添加 @@ -4167,7 +4193,7 @@ p, li { white-space: pre-wrap; } - + Search @@ -4220,13 +4246,13 @@ p, li { white-space: pre-wrap; } - + Create - + Add Member @@ -4245,7 +4271,7 @@ p, li { white-space: pre-wrap; } - + Group Name: @@ -4280,7 +4306,7 @@ p, li { white-space: pre-wrap; } CreateGxsChannelMsg - + New Channel Post @@ -4290,7 +4316,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4435,17 +4461,17 @@ p, li { white-space: pre-wrap; } - + RetroShare - + This file already in this post: - + Post refers to non shared files @@ -4470,7 +4496,12 @@ p, li { white-space: pre-wrap; } - + + Cannot publish post + + + + Load thumbnail picture @@ -4485,18 +4516,12 @@ p, li { white-space: pre-wrap; } 隱藏 - - + Generate mass data - - Do you really want to generate %1 messages ? - - - - + You are about to add files you're not actually sharing. Do you still want this to happen? @@ -4530,7 +4555,7 @@ p, li { white-space: pre-wrap; } CreateGxsForumMsg - + Post Forum Message @@ -4540,7 +4565,16 @@ p, li { white-space: pre-wrap; } 論壇 - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> + + + + Attach File @@ -4555,16 +4589,7 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Sans Serif';"><br /></p></body></html> - - - - + Attach a Picture @@ -4579,7 +4604,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -4609,17 +4634,17 @@ p, li { white-space: pre-wrap; } - + No Forum - + In Reply to - + Title 標題 @@ -4672,7 +4697,7 @@ Do you want to discard this message? - + No compatible ID for this forum @@ -4682,8 +4707,8 @@ Do you want to discard this message? - - + + Generate mass data @@ -4706,7 +4731,7 @@ Do you want to discard this message? CreateLobbyDialog - + A chat room is a decentralized and anonymous chat group. All participants receive all messages. Once the room is created you can invite other friend nodes with invite button on top right. @@ -4741,7 +4766,7 @@ Do you want to discard this message? - + Create @@ -4751,7 +4776,7 @@ Do you want to discard this message? 取消 - + require PGP-signed identities @@ -4766,7 +4791,7 @@ Do you want to discard this message? - + Create Chat Room @@ -4787,7 +4812,7 @@ Do you want to discard this message? - + Identity to use: @@ -4795,17 +4820,17 @@ Do you want to discard this message? CryptoPage - + Public Information - + Name: 名稱: - + Location: @@ -4815,12 +4840,12 @@ Do you want to discard this message? - + Software Version: - + Online since: @@ -4840,12 +4865,7 @@ Do you want to discard this message? - - <html><head/><body><p>Use this to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> - - - - + Export @@ -4855,7 +4875,7 @@ Do you want to discard this message? - + Other Information @@ -4865,17 +4885,12 @@ Do you want to discard this message? - + Profile - - Certificate - - - - + <html><head/><body><p>This option includes all signatures of your profile key. Signatures are not mandatory, but only a way to express your trust in some particular profile.</p></body></html> @@ -4885,7 +4900,7 @@ Do you want to discard this message? - + Export Identity @@ -4955,33 +4970,33 @@ and use the import button to load it - + TextLabel - + PGP fingerprint: - - Node information - - - - + PGP Id : - + Friend nodes: - + + <html><head/><body><p>Use this button to export your profile key. You can then import it in a different computer and make a new node with the same profile. Doing so, existing friends that you also add to the new node will automatically recognise that new node as friend.</p></body></html> + + + + <html><head/><body><p>The short format only contains the profile fingerprint, and authentication is based on the node ID (ID of the SSL key). If you choose the old (long) format, the certificate includes the full profile public key. There is no fundamental difference between making friends with either method, because the public profile keys will be exchanged and checked w.r.t. the fingerprint after connection.</p></body></html> @@ -5071,7 +5086,7 @@ and use the import button to load it DLListDelegate - + B @@ -5739,7 +5754,7 @@ and use the import button to load it DownloadToaster - + Start file @@ -5747,38 +5762,38 @@ and use the import button to load it ExprParamElement - + - + to - + ignore case - - - dd.MM.yyyy + + + yyyy-MM-dd - - + + KB - - + + MB - - + + GB @@ -5786,12 +5801,12 @@ and use the import button to load it ExpressionWidget - + Expression Widget - + Delete this expression @@ -5953,7 +5968,7 @@ and use the import button to load it FilesDefs - + Picture @@ -5963,7 +5978,7 @@ and use the import button to load it - + Audio @@ -6023,11 +6038,21 @@ and use the import button to load it C + + + APK + + + + + DLL + + FlatStyle_RDM - + Friends Directories @@ -6149,7 +6174,7 @@ and use the import button to load it - + ID @@ -6191,7 +6216,7 @@ and use the import button to load it - + Group @@ -6227,7 +6252,7 @@ and use the import button to load it - + Search @@ -6243,7 +6268,7 @@ and use the import button to load it - + Profile details @@ -6480,7 +6505,7 @@ at least one peer was not added to a group FriendRequestToaster - + Confirm Friend Request @@ -6518,7 +6543,7 @@ at least one peer was not added to a group - + Mark all @@ -6529,16 +6554,132 @@ at least one peer was not added to a group + + FriendServerControl + + + Server onion address: + + + + + <html><head/><body><p>Enter here the onion address of the Friend Server that was given to you. The address will be automatically checked after you enter it and a green bullet will appear if the server is online.</p></body></html> + + + + + Onion address of the friend server + + + + + <html><head/><body><p>Communication port of the server. You usually get a server address as somestring.onion:port. The port is the number right after &quot;:&quot;</p></body></html> + + + + + Retroshare passphrase: + + + + + <html><head/><body><p>Your Retroshare login passphrase is needed to ensure the security of data exchange with the friend server.</p></body></html> + + + + + Your retroshare passphrase + + + + + On/Off + + + + + Friends to request: + + + + + Auto accept received certificates as friends + + + + + Auto-accept + + + + + Name + + + + + Node ID + + + + + Address + + + + + Status + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Friend Server</h1> <p>This configuration panel allows you to specify the onion address of a friend server. Retroshare will talk to that server anonymously through Tor and use it to acquire a fixed number of friends.</p> <p>The friend server will continue supplying new friends until that number is reached in particular if you add your own friends manually, the friend server may become useless and you will save bandwidth disabling it. When disabling it, you will keep existing friends.</p> <p>The friend server only knows your peer ID and profile public key. It doesn't know your IP address.</p> + + + + + Make friend + + + + + Missing profile passphrase. + + + + + Your profile passphrase is missing. Please enter is in the field below before enabling the friend server. + + + + + Trying to contact friend server +This may take up to 1 min. + + + + + Friend server is currently reachable. + + + + + The proxy is not enabled or broken. +Are all services up and running fine?? +Also check your ports! + + + FriendsDialog - + Edit status message - - + + Broadcast @@ -6621,33 +6762,38 @@ at least one peer was not added to a group - + Keyring - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1> <p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you. </p> <p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p> <p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> - - - - + Retroshare broadcast chat: messages are sent to all connected friends. - - + + Network - + + Friend Server + + + + Network graph - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Network</h1><p>The Network tab shows your friend Retroshare nodes: the neighbor Retroshare nodes that are connected to you.</p><p>You can group nodes together to allow a finer level of information access, for instance to only allow some nodes to see some of your files.</p><p>On the right, you will find 3 useful tabs: <ul> <li>Broadcast sends messages to all connected nodes at once</li> <li>Local network graph shows the network around you, based on discovery information</li> <li>Keyring contains node keys you collected, mostly forwarded to you by your friend nodes</li> </ul> </p> + + + + Set your status message here. @@ -6665,7 +6811,17 @@ at least one peer was not added to a group 密碼 - + + SAMv3 support is not available + + + + + I2P instance address with SAMv3 enabled + + + + All fields are required with a minimum of 3 characters @@ -6675,17 +6831,12 @@ at least one peer was not added to a group - + Port - - Use BOB - - - - + This password is for PGP @@ -6706,38 +6857,38 @@ at least one peer was not added to a group - + PGP Key Length - - + + <html><head/><body><p>Put a strong password here. This password protects your private node key!</p></body></html> - + <html><head/><body><p>Please move your mouse around in order to collect as much randomness as possible. A minimum of 20% is needed to create your node keys.</p></body></html> - + Standard node - + <html><head/><body><p>Your node name designates the Retroshare instance that</p><p>will run on this computer.</p></body></html> - + Node name - + Node type: @@ -6757,12 +6908,12 @@ at least one peer was not added to a group - + <html><head/><body><p>The profile name identifies you over the network.</p><p>It is used by your friends to accept connections from you.</p><p>You can create multiple Retroshare nodes with the</p><p>same profile on different computers.</p><p><br/></p></body></html> - + Export this profle @@ -6772,38 +6923,43 @@ at least one peer was not added to a group - + <html><head/><body><p>This should be a Tor Onion address of the form: xa76giaf6ifda7ri63i263.onion <br/>or an I2P address in the form: [52 characters].b32.i2p </p><p>In order to get one, you must configure either Tor or I2P to create a new hidden service / server tunnel. </p><p>You can also leave this blank now, but your node will only work if you correctly set the Tor/I2P service address in Options-&gt;Network-&gt;Hidden Service configuration panel.</p></body></html> - + + Use I2P + + + + <html><head/><body><p>Identities are used when you write in chat rooms, forums and channel comments. </p><p>They also receive/send email over the Retroshare network. You can create</p><p>a signed identity now, or do it later on when you get to need it.</p></body></html> - + Go! - - + + TextLabel - + hidden address - + Your profile is associated with a PGP key pair. RetroShare currently ignores DSA keys. - + <html><head/><body><p>This is your connection port.</p><p>Any value between 1024 and 65535 </p><p>should be ok. You can change it later.</p></body></html> @@ -6847,13 +7003,13 @@ and use the import button to load it - + Import profile - + Create new profile and new Retroshare node @@ -6863,7 +7019,7 @@ and use the import button to load it - + Tor/I2P address @@ -6898,7 +7054,7 @@ and use the import button to load it - + <html><p>Put a strong password here. This password will be required to start your Retroshare node and protects all your data.</p></html> @@ -6908,12 +7064,7 @@ and use the import button to load it - - BOB support is not available - - - - + <p>Node creation is disabled until all fields correctly set.</p> @@ -6923,12 +7074,7 @@ and use the import button to load it - - I2P instance address with BOB enabled - - - - + I2P instance address @@ -7154,27 +7300,13 @@ and use the import button to load it - + Invite Friends - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be sure to get their invitation back as well... </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> - - - - + Add Your Friends to RetroShare @@ -7184,39 +7316,57 @@ p, li { white-space: pre-wrap; } - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + Connect To Friends - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">RetroShare is nothing without your Friends. Click on the Button to start the process.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Email an Invitation with your &quot;ID Certificate&quot; to your friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be sure to get their invitation back as well... </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can only connect with friends if you have both added each other.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Be Online at the same time as your friends, and RetroShare will automatically connect you!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Your client needs to find the RetroShare Network before it can make connections.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This takes 5-30 minutes the first time you start up RetroShare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The DHT indicator (in the Status Bar) turns Green when it can make connections.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">After a couple of minutes, the NAT indicator (also in the Status Bar) switch to Yellow or Green.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If it remains Red, then you have a Nasty Firewall, that RetroShare struggles to connect through.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Look in the Further Help section for more advice about connecting.</span></p></body></html> + + + + + Advanced: Open Firewall Port @@ -7224,49 +7374,45 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Having trouble getting started with RetroShare?</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;"> - These come online once you are connected to friends.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">4) If you are still stuck. Email us.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Enjoy Retrosharing</span></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">You can improve your Retroshare performance by opening an External Port. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This will speed up connections and allow more people to connect with you. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">The easiest way to do this is by enabling UPnP on your Wireless Box or Router.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">As each router is different, you will need to find out your Router Model and search the Internet for instructions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">If none of this makes sense to you, don't worry about it Retroshare will still work.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html> - - Connect To Friends - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">When your friends send you their invitations, click to open the Add Friends window.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Paste your Friends' &quot;ID Certificates&quot; into the window and add them as friends.</span></p></body></html> - - - - - Advanced: Open Firewall Port - - - - + Further Help and Support - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Having trouble getting started with RetroShare?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">1) Look at the FAQ Wiki. This is a bit old, we are trying to bring it up to date.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">2) Check out the Online Forums. Ask questions and discuss features.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">3) Try the Internal RetroShare Forums </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;"> - These come online once you are connected to friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">4) If you are still stuck. Email us.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Enjoy Retrosharing</span></p></body></html> + + + + Open RS Website @@ -7291,7 +7437,7 @@ p, li { white-space: pre-wrap; } - + RetroShare Invitation @@ -7341,12 +7487,12 @@ p, li { white-space: pre-wrap; } - + RetroShare Support - + It has many features, including built-in chat, messaging, @@ -7470,7 +7616,7 @@ p, li { white-space: pre-wrap; } GroupChatToaster - + Show Group Chat @@ -7478,7 +7624,7 @@ p, li { white-space: pre-wrap; } GroupChooser - + [Unknown] @@ -7648,7 +7794,7 @@ p, li { white-space: pre-wrap; } GroupTreeWidget - + Title 標題 @@ -7661,12 +7807,12 @@ p, li { white-space: pre-wrap; } - + Description - + Number of Unread message @@ -7691,7 +7837,7 @@ p, li { white-space: pre-wrap; } - + You are admin (modify names and description using Edit menu) @@ -7706,14 +7852,14 @@ p, li { white-space: pre-wrap; } - - + + Last Post - + Name @@ -7724,13 +7870,13 @@ p, li { white-space: pre-wrap; } - + Never - + <html><head/><body><p>Searches a single keyword into the reachable network.</p><p>Objects already provided by friend nodes are not reported.</p></body></html> @@ -7743,7 +7889,7 @@ p, li { white-space: pre-wrap; } GuiExprElement - + and @@ -7879,7 +8025,7 @@ p, li { white-space: pre-wrap; } GxsChannelDialog - + Channels @@ -7890,22 +8036,22 @@ p, li { white-space: pre-wrap; } - + Enable Auto-Download - + My Channels - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1> <p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p> <p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p> <p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p> <p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p> <p>Channel posts are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> <p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Channels</h1><p>Channels allow you to post data (e.g. movies, music) that will spread in the network</p><p>You can see the channels your friends are subscribed to, and you automatically forward subscribed channels to your friends. This promotes good channels in the network.</p><p>Only the channel's creator can post on that channel. Other peers in the network can only read from it, unless the channel is private. You can however share the posting rights or the reading rights with friend Retroshare nodes.</p><p>Channels can be made anonymous, or attached to a Retroshare identity so that readers can contact you if needed. Enable "Allow Comments" if you want to let users comment on your posts.</p><p>Channel posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p><p>UI Tip: use Control + mouse wheel to control image size in the thumbnail view.</p> - + Subscribed Channels @@ -7925,12 +8071,12 @@ p, li { white-space: pre-wrap; } - + Disable Auto-Download - + Set download directory @@ -7965,22 +8111,22 @@ p, li { white-space: pre-wrap; } - + Play - + Open folder - + Open file - + Error @@ -8000,17 +8146,17 @@ p, li { white-space: pre-wrap; } - + Are you sure that you want to cancel and delete the file? - + Can't open folder - + Play File @@ -8020,21 +8166,10 @@ p, li { white-space: pre-wrap; } - - GxsChannelFilesWidget - - Form - 表單 - - - Title - 標題 - - GxsChannelGroupDialog - + Create New Channel @@ -8072,8 +8207,18 @@ p, li { white-space: pre-wrap; } GxsChannelGroupItem - - Subscribe to Channel + + Last activity + + + + + TextLabel + + + + + Subscribe this Channel @@ -8088,7 +8233,7 @@ p, li { white-space: pre-wrap; } - + Expand 展開 @@ -8103,7 +8248,7 @@ p, li { white-space: pre-wrap; } - + Loading @@ -8117,6 +8262,11 @@ p, li { white-space: pre-wrap; } New Channel: + + + Never + + Hide @@ -8126,7 +8276,7 @@ p, li { white-space: pre-wrap; } GxsChannelPostItem - + New Comment: @@ -8147,7 +8297,7 @@ p, li { white-space: pre-wrap; } - + Play @@ -8209,18 +8359,18 @@ p, li { white-space: pre-wrap; } 隱藏 - + New 新建 - + 0 - - + + Comment @@ -8235,17 +8385,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + Comments - + Post @@ -8270,35 +8420,16 @@ p, li { white-space: pre-wrap; } - - GxsChannelPostsWidget - - Title - 標題 - - - Search Title - 搜索標題 - - - Feeds - 訂閱 - - - Description: - 描述: - - GxsChannelPostsWidgetWithModel - + Post to Channel - + Add new post @@ -8368,7 +8499,7 @@ p, li { white-space: pre-wrap; } - Posts (locally / at friends): + Items (locally / at friends): @@ -8404,7 +8535,7 @@ p, li { white-space: pre-wrap; } - + Comments @@ -8419,13 +8550,13 @@ p, li { white-space: pre-wrap; } 訂閱 - - + + Click to switch to list view - + Show unread posts only @@ -8440,7 +8571,7 @@ p, li { white-space: pre-wrap; } - + No text to display @@ -8455,7 +8586,7 @@ p, li { white-space: pre-wrap; } - + Switch to list view @@ -8515,12 +8646,22 @@ p, li { white-space: pre-wrap; } - + Comments (%1) - + + Loading... + + + + + No posts available in this channel. + + + + [No name] @@ -8595,12 +8736,13 @@ p, li { white-space: pre-wrap; } - + + Copy Retroshare link - + Subscribed @@ -8651,17 +8793,17 @@ p, li { white-space: pre-wrap; } GxsCircleItem - + TextLabel - + Circle name: - + Accept @@ -8776,7 +8918,7 @@ p, li { white-space: pre-wrap; } GxsCommentContainer - + Comment Container @@ -8789,7 +8931,7 @@ p, li { white-space: pre-wrap; } 表單 - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html> @@ -8819,7 +8961,7 @@ p, li { white-space: pre-wrap; } - + Comment @@ -8858,7 +9000,7 @@ p, li { white-space: pre-wrap; } GxsCommentTreeWidget - + Reply to Comment @@ -8882,6 +9024,21 @@ p, li { white-space: pre-wrap; } Vote Down + + + Show Author + + + + + Cannot vote + + + + + Error while voting: + + GxsCreateCommentDialog @@ -8891,7 +9048,7 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -8920,7 +9077,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -8951,7 +9108,7 @@ before you can comment - + It remains %1 characters after HTML conversion. @@ -9002,7 +9159,7 @@ before you can comment GxsForumGroupItem - + Subscribe to Forum @@ -9018,7 +9175,7 @@ before you can comment - + Expand 展開 @@ -9037,6 +9194,11 @@ before you can comment Moderator list + + + TextLabel + + Loading... @@ -9066,13 +9228,13 @@ before you can comment GxsForumMsgItem - - + + Subject: - + Unsubscribe To Forum @@ -9083,7 +9245,7 @@ before you can comment - + Expand 展開 @@ -9103,17 +9265,17 @@ before you can comment - + Loading... - + Forum Feed - + Hide 隱藏 @@ -9126,59 +9288,66 @@ before you can comment 表單 - + Start new Thread for Selected Forum - + + Threaded + + + + + + + ... + ... + + + + Flat + + + + + Latest post in thread + + + + Search forums 搜索論壇 - + New Thread - - - Threaded View - - - - - Flat View - - - + Title 標題 - - + + Date 日期 - + Author 作者 - - Save image - - - - + Loading - + <html><head/><body><p>Click here to clear current selected thread and display more information about this forum.</p></body></html> @@ -9188,12 +9357,7 @@ before you can comment - - Lastest post in thread - - - - + Reply Message @@ -9233,23 +9397,23 @@ before you can comment 搜索作者 - + No name 未命名 - - + + Reply - + <p>Subscribing to the forum will gather available posts from your subscribed friends, and make the forum visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the forum list at left.</p> - + Loading... @@ -9292,16 +9456,12 @@ before you can comment - + Hide 隱藏 - Expand - 展開 - - - + [unknown] @@ -9331,8 +9491,8 @@ before you can comment - - + + Distribution @@ -9415,12 +9575,12 @@ before you can comment - + New thread - + Edit 編輯 @@ -9481,7 +9641,7 @@ before you can comment - + Show column @@ -9501,7 +9661,7 @@ before you can comment - + Anonymous/unknown posts forwarded if reputation is positive @@ -9553,7 +9713,7 @@ This message is missing. You should receive it later. - + No result. @@ -9563,7 +9723,7 @@ This message is missing. You should receive it later. - + Failed to retrieve this message. Is the database currently overloaded? @@ -9578,7 +9738,7 @@ This message is missing. You should receive it later. - + (Latest) @@ -9644,12 +9804,12 @@ This message is missing. You should receive it later. GxsForumsDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1> <p>Retroshare Forums look like internet forums, but they work in a decentralized way</p> <p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p> <p>Forum messages are kept for %1 days and sync-ed over the last %2 days, unless you configure it otherwise.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Forums</h1><p>Retroshare Forums look like internet forums, but they work in a decentralized way</p><p>You see forums your friends are subscribed to, and you forward subscribed forums to your friends. This automatically promotes interesting forums in the network.</p><p>Forum messages are kept for %2 days and sync-ed over the last %3 days, unless you configure it otherwise.</p> - + Forums 論壇 @@ -9684,12 +9844,12 @@ This message is missing. You should receive it later. GxsGroupDialog - + Name - + Key recipients can publish to restricted-type group and can view and publish for private-type channels @@ -9700,12 +9860,12 @@ This message is missing. You should receive it later. - + Description - + Message Distribution @@ -9713,7 +9873,7 @@ This message is missing. You should receive it later. - + Public @@ -9773,7 +9933,7 @@ This message is missing. You should receive it later. - + Comments: @@ -9796,7 +9956,7 @@ This message is missing. You should receive it later. - + All People @@ -9812,12 +9972,12 @@ This message is missing. You should receive it later. - + Restricted to circle: - + Limited to your friends @@ -9834,23 +9994,23 @@ This message is missing. You should receive it later. - + Message tracking - - + + PGP signature required - + Never - + Only friends nodes in group @@ -9866,22 +10026,28 @@ This message is missing. You should receive it later. - + PGP signature from known ID required - + + + [None] + + + + Load Group Logo - + Submit Group Changes - + Owner: @@ -9891,12 +10057,12 @@ This message is missing. You should receive it later. - + Info - + ID @@ -9906,7 +10072,7 @@ This message is missing. You should receive it later. - + <html><head/><body><p>Messages will spread way beyond your friend nodes, as long as people subscribe to the channel/forum/posted you're creating.</p></body></html> @@ -9981,7 +10147,12 @@ This message is missing. You should receive it later. - + + Author: + + + + Popularity @@ -9997,27 +10168,22 @@ This message is missing. You should receive it later. - + Created - + Cancel 取消 - + Create - - Author - 作者 - - - + GxsIdLabel @@ -10025,7 +10191,7 @@ This message is missing. You should receive it later. GxsGroupFrameDialog - + Loading @@ -10085,7 +10251,7 @@ This message is missing. You should receive it later. - + Synchronise posts of last... @@ -10142,12 +10308,12 @@ This message is missing. You should receive it later. - + Search for - + Copy RetroShare Link @@ -10170,7 +10336,7 @@ This message is missing. You should receive it later. GxsIdChooser - + No Signature @@ -10183,14 +10349,14 @@ This message is missing. You should receive it later. GxsIdDetails - + Not found - - + + [Banned] @@ -10200,7 +10366,7 @@ This message is missing. You should receive it later. - + Loading... @@ -10210,7 +10376,12 @@ This message is missing. You should receive it later. - + + [Nobody] + + + + Identity&nbsp;name @@ -10230,6 +10401,14 @@ This message is missing. You should receive it later. + + GxsIdLabel + + + [Nobody] + + + GxsIdStatistics @@ -10241,7 +10420,7 @@ This message is missing. You should receive it later. GxsIdStatisticsWidget - + Total identities: @@ -10289,7 +10468,7 @@ This message is missing. You should receive it later. GxsIdTreeItemDelegate - + [Unknown] @@ -10676,7 +10855,7 @@ This message is missing. You should receive it later. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">RetroShare is an Open Source cross-platform, </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">private and secure decentralized communication platform. </span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">It lets you share securely your friends, </span></p> @@ -10692,7 +10871,7 @@ p, li { white-space: pre-wrap; } - + Authors @@ -10711,7 +10890,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">RetroShare Translations:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Translation"><span style=" font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;">http://retroshare.sourceforge.net/wiki/index.php/Translation</span></a></p> @@ -10785,7 +10964,7 @@ p, li { white-space: pre-wrap; } 表單 - + Add friend @@ -10795,7 +10974,7 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Share your RetroShare ID</p></body></html> @@ -10823,7 +11002,7 @@ private and secure decentralized communication platform. - + Did you receive a Retroshare ID from a friend? @@ -10833,7 +11012,7 @@ private and secure decentralized communication platform. - + Copy your Cert to Clipboard @@ -10843,7 +11022,7 @@ private and secure decentralized communication platform. - + Send via Email @@ -10863,13 +11042,37 @@ private and secure decentralized communication platform. - - + + Include current local IP + + + + + Include current external IP + + + + + Include my DNS + + + + + Include all IPs history + + + + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1><p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p><div align="center"><IMG width="%2" height="%3" src=":/images/network_map.png" style="display: block; margin-left: auto; margin-right: auto; "/></div><p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p><p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> + + + + Include all your known IPs - + Use old certificate format @@ -10881,12 +11084,12 @@ new short format - + Use new (short) certificate format - + Your Retroshare certificate is copied to Clipboard, paste and send it to your friend via email or some other way @@ -10901,12 +11104,7 @@ new short format - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Welcome to Retroshare!</h1> <p>You need to <b>make friends</b>! After you create a network of friends or join an existing network, you'll be able to exchange files, chat, talk in forums, etc. </p> <div align=center> <IMG align="center" width="%2" src=":/images/network_map.png"/> </div> <p>To do so, copy your Retroshare ID on this page and send it to friends, and add your friends' Retroshare ID.</p> <p>Another option is to search the internet for "Retroshare chat servers" (independently administrated). These servers allow you to exchange Retroshare ID with a dedicated Retroshare node, through which you will be able to anonymously meet other people.</p> - - - - + Save as... @@ -11171,14 +11369,14 @@ p, li { white-space: pre-wrap; } IdDialog - - - + + + All - + Reputation @@ -11188,12 +11386,12 @@ p, li { white-space: pre-wrap; } - + Anonymous Id - + Create new Identity @@ -11203,7 +11401,7 @@ p, li { white-space: pre-wrap; } - + Persons @@ -11218,27 +11416,27 @@ p, li { white-space: pre-wrap; } - + Close - + Ban-option: - + Auto-Ban all identities signed by the same node - + Friend votes: - + Positive votes @@ -11254,29 +11452,39 @@ p, li { white-space: pre-wrap; } - + Created on : - + + Auto-Ban profile + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - + + Edit Identity + + + + Usage statistics - + Circles - + Circle name @@ -11296,18 +11504,20 @@ p, li { white-space: pre-wrap; } - + + Edit identity - + + Delete identity - + Chat with this peer @@ -11317,78 +11527,78 @@ p, li { white-space: pre-wrap; } - + Owner node ID : - + Identity name : - + () - + Identity ID - + Send message - + Identity info - + Identity ID : - + Owner node name : - + Create new... - + Type: 類型 - + Send Invite - + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - + Your opinion: - + Negative - + Neutral @@ -11399,17 +11609,17 @@ p, li { white-space: pre-wrap; } - + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - + Overall: - + Anonymous @@ -11424,24 +11634,24 @@ p, li { white-space: pre-wrap; } - + This identity is owned by you - - + + My own identities - - + + My contacts - + Show Items @@ -11456,7 +11666,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1><p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p><p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p><p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p><p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p><p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p><p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> + + + + Other circles @@ -11466,7 +11681,7 @@ p, li { white-space: pre-wrap; } - + Circle ID: @@ -11541,7 +11756,7 @@ p, li { white-space: pre-wrap; } - + Identity ID: @@ -11571,7 +11786,7 @@ p, li { white-space: pre-wrap; } - + Invited @@ -11586,7 +11801,7 @@ p, li { white-space: pre-wrap; } - + Edit Circle @@ -11634,7 +11849,7 @@ p, li { white-space: pre-wrap; } - + This identity has a unsecure fingerprint (It's probably quite old). You should get rid of it now and use a new one. @@ -11642,7 +11857,7 @@ These identities will soon be not supported anymore. - + [Unknown node] @@ -11685,7 +11900,7 @@ These identities will soon be not supported anymore. - + Boards @@ -11765,7 +11980,7 @@ These identities will soon be not supported anymore. - + information @@ -11781,17 +11996,12 @@ These identities will soon be not supported anymore. - + Banned - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Identities</h1> <p>In this tab you can create/edit <b>pseudo-anonymous identities</b>, and <b>circles</b>.</p> <p><b>Identities</b> are used to securely identify your data: sign messages in chat lobbies, forum and channel posts, receive feedback using the Retroshare built-in email system, post comments after channel posts, chat using secured tunnels, etc.</p> <p>Identities can optionally be <b>signed</b> by your Retroshare node's certificate. Signed identities are easier to trust but are easily linked to your node's IP address.</p> <p><b>Anonymous identities</b> allow you to anonymously interact with other users. They cannot be spoofed, but noone can prove who really owns a given identity.</p> <p><b>Circles</b> are groups of identities (anonymous or signed), that are shared at a distance over the network. They can be used to restrict the visibility to forums, channels, etc. </p> <p>An <b>circle</b> can be restricted to another circle, thereby limiting its visibility to members of that circle or even self-restricted, meaning that it is only visible to invited members.</p> - - - - + positive @@ -11896,7 +12106,7 @@ These identities will soon be not supported anymore. - + Add to Contacts @@ -11946,21 +12156,21 @@ These identities will soon be not supported anymore. - - - + + + People - + Your Avatar Click here to change your avatar - + Linked to neighbor nodes @@ -11970,7 +12180,7 @@ These identities will soon be not supported anymore. - + Linked to a friend Retroshare node @@ -11985,7 +12195,7 @@ These identities will soon be not supported anymore. - + Chat with this person @@ -12000,12 +12210,12 @@ These identities will soon be not supported anymore. - + Last used: - + +50 Known PGP @@ -12025,12 +12235,12 @@ These identities will soon be not supported anymore. - + Owned by - + Node name: @@ -12040,7 +12250,7 @@ These identities will soon be not supported anymore. - + Really delete? @@ -12048,7 +12258,7 @@ These identities will soon be not supported anymore. IdEditDialog - + Nickname @@ -12078,7 +12288,13 @@ These identities will soon be not supported anymore. - + + + Use the mouse to zoom and adjust the image for your avatar. Hit Del to remove it. + + + + New identity @@ -12092,7 +12308,7 @@ These identities will soon be not supported anymore. - + @@ -12102,7 +12318,12 @@ These identities will soon be not supported anymore. - + + No avatar chosen + + + + Edit identity @@ -12113,27 +12334,27 @@ These identities will soon be not supported anymore. - - + + Profile password needed. - + - + Identity creation failed - - + + Cannot create an identity linked to your profile without your profile password. - + Identity creation success @@ -12153,7 +12374,7 @@ These identities will soon be not supported anymore. - + Identity update failed @@ -12163,12 +12384,18 @@ These identities will soon be not supported anymore. - + Error KeyID invalid - + + + No Avatar chosen. A default image will be automatically displayed from your new identity. + + + + Import image @@ -12178,12 +12405,7 @@ These identities will soon be not supported anymore. - - Use the mouse to zoom and adjust the image for your avatar. - - - - + Unknown GpgId @@ -12193,7 +12415,7 @@ These identities will soon be not supported anymore. - + Create New Identity @@ -12203,10 +12425,15 @@ These identities will soon be not supported anymore. 類型 - + Choose image... + + + Remove + 刪除 + @@ -12232,7 +12459,7 @@ These identities will soon be not supported anymore. 添加 - + Create @@ -12242,13 +12469,13 @@ These identities will soon be not supported anymore. 取消 - + Your Avatar Click here to change your avatar - + Linked to your profile @@ -12258,7 +12485,7 @@ These identities will soon be not supported anymore. - + The nickname is too short. Please input at least %1 characters. @@ -12332,7 +12559,7 @@ These identities will soon be not supported anymore. - + Copy 複製 @@ -12342,12 +12569,12 @@ These identities will soon be not supported anymore. 刪除 - + %1 's Message History - + Mark all @@ -12370,18 +12597,34 @@ These identities will soon be not supported anymore. ImageUtil - - + + Save image - Cannot save the image, invalid filename + Save Picture File + + + + + Pictures (*.png *.xpm *.jpg) + Cannot save the image, invalid filename + + + + + Copy image + + + + + Not an image @@ -12399,27 +12642,32 @@ These identities will soon be not supported anymore. - + Enable RetroShare JSON API Server - + Port: - + Listen Address: - + + Status: + + + + 127.0.0.1 - + Token: @@ -12440,7 +12688,12 @@ These identities will soon be not supported anymore. - Authenticated Tokens + Authenticated Tokens: + + + + + Registered services: @@ -12449,26 +12702,31 @@ These identities will soon be not supported anymore. - + JSON API + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. Please refer to the Retroshare documentation for how to use this feature. </p> <p>Unless you know what you're doing, you shouldn't need to change anything in this page. The web interface for instance will automatically register its own token to the JSON API which will be visible in the list of authenticated tokens after you enable it.</p> + + LocalSharedFilesDialog - - + + Open File - + Open Folder - + Checking... @@ -12478,7 +12736,7 @@ These identities will soon be not supported anymore. - + Recommend in a message to... @@ -12506,7 +12764,7 @@ These identities will soon be not supported anymore. MainWindow - + Add Friend @@ -12522,7 +12780,8 @@ These identities will soon be not supported anymore. - + + Options 選項 @@ -12543,7 +12802,7 @@ These identities will soon be not supported anymore. - + Quit @@ -12554,12 +12813,12 @@ These identities will soon be not supported anymore. - + RetroShare %1 a secure decentralized communication platform - + Unfinished @@ -12584,11 +12843,12 @@ These identities will soon be not supported anymore. + Status - + Notify @@ -12599,31 +12859,35 @@ These identities will soon be not supported anymore. + Open Messages - + + Bandwidth Graph - + Applications + Help - + + Minimize - + Maximize @@ -12638,7 +12902,12 @@ These identities will soon be not supported anymore. - + + Close window + + + + %1 new message @@ -12668,7 +12937,7 @@ These identities will soon be not supported anymore. - + Do you really want to exit RetroShare ? @@ -12688,7 +12957,7 @@ These identities will soon be not supported anymore. 顯示 - + Make sure this link has not been forged to drag you to a malicious website. @@ -12733,12 +13002,13 @@ These identities will soon be not supported anymore. - + + Statistics - + Show web interface @@ -12753,7 +13023,7 @@ These identities will soon be not supported anymore. - + Really quit ? @@ -12762,17 +13032,17 @@ These identities will soon be not supported anymore. MessageComposer - + Compose - + Contacts - + Paragraph @@ -12808,12 +13078,12 @@ These identities will soon be not supported anymore. - + Font size - + Increase font size @@ -12828,32 +13098,32 @@ These identities will soon be not supported anymore. - + Italic - + Alignment - + Add an Image - + Sets text font to code style - + Underline - + Subject: @@ -12864,32 +13134,32 @@ These identities will soon be not supported anymore. - + Tags - + Address list: - + Recommend this friend - + Set Text color - + Set Text background color - + Recommended Files @@ -12959,7 +13229,7 @@ These identities will soon be not supported anymore. - + Send To: @@ -12999,7 +13269,7 @@ These identities will soon be not supported anymore. - + Hello,<br>I recommend a good friend of mine; you can trust them too when you trust me. <br> @@ -13019,18 +13289,18 @@ These identities will soon be not supported anymore. - + Hi %1,<br><br>%2 wants to be friends with you on RetroShare.<br><br>Respond now:<br>%3<br><br>Thanks,<br>The RetroShare Team - - + + Save Message - + Message has not been Sent. Do you want to save message to draft box? @@ -13041,7 +13311,17 @@ Do you want to save message to draft box? - + + Will not reply + + + + + There is no point in replying to a notification message! + + + + Add to "To" @@ -13061,7 +13341,7 @@ Do you want to save message to draft box? - + Original Message @@ -13071,21 +13351,21 @@ Do you want to save message to draft box? 來自 - + - + To - - + + Cc - + Sent @@ -13100,7 +13380,7 @@ Do you want to save message to draft box? - + Re: @@ -13110,30 +13390,30 @@ Do you want to save message to draft box? - - - + + + RetroShare - + Do you want to send the message without a subject ? - + Please insert at least one recipient. - + Bcc - + Unknown 未知 @@ -13248,13 +13528,13 @@ Do you want to save message to draft box? - + Open File... - + HTML-Files (*.htm *.html);;All Files (*) @@ -13274,7 +13554,7 @@ Do you want to save message to draft box? - + Message has not been Sent. Do you want to save message ? @@ -13295,7 +13575,7 @@ Do you want to save message ? - + Hi,<br>I want to be friends with you on RetroShare.<br> @@ -13325,18 +13605,18 @@ Do you want to save message ? - - + + Close - + From: 從: - + Bullet list (disc) @@ -13376,13 +13656,13 @@ Do you want to save message ? - - + + Thanks, <br> - + Distant identity: @@ -13392,12 +13672,12 @@ Do you want to save message ? - + Please create an identity to sign distant messages, or remove the distant peers from the destination list. - + Node name & id: @@ -13475,7 +13755,7 @@ Do you want to save message ? - + A new tab @@ -13485,7 +13765,7 @@ Do you want to save message ? - + Edit Tag @@ -13508,7 +13788,7 @@ Do you want to save message ? MessageToaster - + Sub: @@ -13516,7 +13796,7 @@ Do you want to save message ? MessageUserNotify - + Message @@ -13544,7 +13824,7 @@ Do you want to save message ? MessageWidget - + Recommended Files @@ -13554,37 +13834,37 @@ Do you want to save message ? - + Subject: - + From: 從: - + To: 到: - + Cc: - + Bcc: - + Tags: - + Reply @@ -13624,7 +13904,7 @@ Do you want to save message ? - + Send Invite @@ -13676,7 +13956,7 @@ Do you want to save message ? - + Confirm %1 as friend @@ -13686,12 +13966,12 @@ Do you want to save message ? - + View source - + No subject @@ -13701,17 +13981,22 @@ Do you want to save message ? 下載 - + You got an invite to make friend! You may accept this request. - + You got an invite to make friend! You may accept this request and send your own Certificate back - + + more + + + + Document source @@ -13720,14 +14005,24 @@ Do you want to save message ? %1 (%2) + + + Show less + + + + + Show more + + - + Download all - + Print Document @@ -13742,12 +14037,12 @@ Do you want to save message ? - + Load images always for this message - + Hide the attachment pane @@ -13769,10 +14064,6 @@ Do you want to save message ? Compose - - Delete - 刪除 - Print @@ -13851,7 +14142,7 @@ Do you want to save message ? MessagesDialog - + New Message @@ -13861,20 +14152,16 @@ Do you want to save message ? - Delete - 刪除 - - - + - - + + Tags - - + + Inbox @@ -13904,17 +14191,17 @@ Do you want to save message ? - + Total Inbox: - + Quick View - + Print... @@ -13945,7 +14232,7 @@ Do you want to save message ? - + Subject @@ -13955,7 +14242,7 @@ Do you want to save message ? 來自 - + Date 日期 @@ -13965,7 +14252,7 @@ Do you want to save message ? - + Search Subject @@ -13974,6 +14261,16 @@ Do you want to save message ? Search From + + + To + + + + + Search To + + Search Date @@ -14000,12 +14297,12 @@ Do you want to save message ? - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1> <p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p> <p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p> <p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p> <p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Messages</h1><p>Retroshare has its own internal email system. You can send/receive emails to/from connected friend nodes.</p><p>It is also possible to send messages to other people's Identities using the global routing system. These messages are always encrypted and signed, and are relayed by intermediate nodes until they reach their final destination. </p><p>Distant messages stay into your Outbox until an acknowledgement of receipt has been received.</p><p>Generally, you may use messages to recommend files to your friends by pasting file links, or recommend friend nodes to other friend nodes, in order to strengthen your network, or send feedback to a channel's owner.</p> - + Starred @@ -14081,7 +14378,7 @@ Do you want to save message ? - Show author in People + Show in People @@ -14095,7 +14392,7 @@ Do you want to save message ? - + No message using %1 tag available. @@ -14110,18 +14407,28 @@ Do you want to save message ? - + + Deletion is not recommended + + + + + Messages in this box are automatically deleted when received. Manually deleting a message does not guaranty that the message will not be delivered. Messages that cannot be delivered will however stay here indefinitly. Do you want to proceed and delete? + + + + Drafts - + No Box selected. - + @@ -14156,7 +14463,17 @@ Do you want to save message ? MimeTextEdit - + + Save image + + + + + Copy image + + + + Paste as plain text @@ -14210,7 +14527,7 @@ Do you want to save message ? - + Expand 展開 @@ -14220,7 +14537,7 @@ Do you want to save message ? 刪除項目 - + from @@ -14255,7 +14572,7 @@ Do you want to save message ? - + Hide 隱藏 @@ -14396,7 +14713,7 @@ Do you want to save message ? - + Remove unused keys... @@ -14406,7 +14723,7 @@ Do you want to save message ? - + Clean keyring @@ -14420,7 +14737,13 @@ Notes: Your old keyring will be backed up. - + + You have selected %1 accepted peers among others, + Are you sure you want to un-friend them? + + + + Keyring info @@ -14453,18 +14776,13 @@ For security, your keyring was previously backed-up to file Data inconsistency in the keyring. This is most probably a bug. Please contact the developers. - - - Export/create a new node - - Trusted keys only - + Search name @@ -14474,12 +14792,12 @@ For security, your keyring was previously backed-up to file - + Profile details... - + Key removal has failed. Your keyring remains intact. Reported error: @@ -14512,7 +14830,7 @@ Reported error: NewFriendList - + Offline Friends @@ -14533,7 +14851,7 @@ Reported error: - + Groups @@ -14563,19 +14881,19 @@ Reported error: - - + + Search - + ID - + Search ID @@ -14585,12 +14903,12 @@ Reported error: - + Show Items - + Last contact @@ -14600,7 +14918,7 @@ Reported error: - + Group @@ -14715,7 +15033,7 @@ Reported error: - + Do you want to remove this node? @@ -14725,7 +15043,7 @@ Reported error: - + Done! @@ -14832,7 +15150,7 @@ at least one peer was not added to a group NewsFeed - + Activity Stream @@ -14847,7 +15165,7 @@ at least one peer was not added to a group - + Newest on top @@ -14857,12 +15175,12 @@ at least one peer was not added to a group - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1> <p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p> <p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Activity Feed</h1><p>The Activity Feed displays the last events on your network, sorted by the time you received them. This gives you a summary of the activity of your friends. You can configure which events to show by pressing on <b>Options</b>. </p><p>The various events shown are: <ul> <li>Connection attempts (useful to make friends with new people and control who's trying to reach you)</li> <li>Channel, Forum and Board posts</li> <li>Circle membership requests and invites</li> <li>New Channels, Forums and Boards you can subscribe to</li> <li>Channel and Board comments</li> <li>New Mail messages</li> <li>Private messages from your friends</li> </ul> </p> - + Activity @@ -15091,10 +15409,6 @@ at least one peer was not added to a group Disable All Toaster temporarily - - Feed - 訂閱 - Systray @@ -15104,7 +15418,7 @@ at least one peer was not added to a group NotifyQt - + Passphrase required @@ -15124,12 +15438,12 @@ at least one peer was not added to a group - + Please enter your Retroshare passphrase - + Unregistered plugin/executable @@ -15144,7 +15458,7 @@ at least one peer was not added to a group - + Test 測試 @@ -15155,17 +15469,19 @@ at least one peer was not added to a group + Unknown title - + + Encrypted message - + For the chat lobbies to work properly, the time of your computer needs to be correct. Please check that this is the case (A possible time shift of several minutes was detected with your friends). @@ -15173,7 +15489,7 @@ at least one peer was not added to a group OnlineToaster - + Friend Online @@ -15312,7 +15628,12 @@ p, li { white-space: pre-wrap; } - + + Friend options + + + + These options apply to all nodes of the profile: @@ -15357,12 +15678,7 @@ p, li { white-space: pre-wrap; } - - Options - 選項 - - - + <html><head/><body><p align="justify">Retroshare periodically checks your friend lists for browsable files matching your transfers, to establish a direct transfer. In this case, your friend knows you're downloading the file.</p><p align="justify">To prevent this behavior for this friend only, uncheck this box. You can still perform a direct transfer if you explicitly ask for it, by e.g. downloading from your friend's file list. This setting is applied to all locations of the same node.</p></body></html> @@ -15408,21 +15724,21 @@ p, li { white-space: pre-wrap; } - - + + RetroShare - - + + Error : cannot get peer details. - + The supplied key algorithm is not supported by RetroShare (Only RSA keys are supported at the moment) @@ -15440,7 +15756,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + The trust level is a way to express your own trust in this key. It is not used by the software nor shared, but can be useful to you in order to remember good/bad keys. @@ -15516,12 +15832,12 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Retroshare profile - + This is your own PGP key, and it is signed by : @@ -15547,7 +15863,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. PeerItem - + Chat @@ -15568,7 +15884,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.刪除項目 - + Name: 名稱: @@ -15608,7 +15924,7 @@ Warning: In your File-Transfer option, you select allow direct download to No. - + Write Message @@ -15666,7 +15982,7 @@ Warning: In your File-Transfer option, you select allow direct download to No.隱藏 - + Send Message @@ -15833,13 +16149,6 @@ Warning: In your File-Transfer option, you select allow direct download to No. - - PhotoCommentItem - - Form - 表單 - - PhotoDialog @@ -15991,17 +16300,17 @@ p, li { white-space: pre-wrap; } - + My Albums - + Subscribed Albums - + Shared Albums @@ -16030,7 +16339,7 @@ requesting to edit it! PhotoSlideShow - + Album Name @@ -16089,19 +16398,19 @@ requesting to edit it! - - + + TextLabel - + Posted by - + ago @@ -16137,12 +16446,12 @@ requesting to edit it! PluginItem - + TextLabel - + Show more details about this plugin @@ -16353,12 +16662,27 @@ p, li { white-space: pre-wrap; } - + + Ban this person (Sets negative opinion) + + + + + Give neutral opinion + + + + + Give positive opinion + + + + Choose window color... - + Dock window @@ -16411,7 +16735,7 @@ p, li { white-space: pre-wrap; } 新建 - + Vote up @@ -16431,8 +16755,8 @@ p, li { white-space: pre-wrap; } - - + + Comments @@ -16457,13 +16781,13 @@ p, li { white-space: pre-wrap; } - - + + Comment - + Comments @@ -16491,12 +16815,12 @@ p, li { white-space: pre-wrap; } PostedCreatePostDialog - + Create a new Post - + RetroShare @@ -16511,12 +16835,22 @@ p, li { white-space: pre-wrap; } - + + Error while creating post + + + + + An error occurred while creating the post. + + + + Load Picture File - + Post image @@ -16532,7 +16866,17 @@ p, li { white-space: pre-wrap; } - + + No clipboard image found. + + + + + There is no image data in the clipboard to paste + + + + Close this window? @@ -16542,7 +16886,7 @@ p, li { white-space: pre-wrap; } - + Please add a Title @@ -16562,12 +16906,22 @@ p, li { white-space: pre-wrap; } - + Post size is limited to 32 KB, pictures will be downscaled. - + + Paste image from clipboard + + + + + Paste Picture + + + + Remove image @@ -16582,7 +16936,7 @@ p, li { white-space: pre-wrap; } - + Post @@ -16593,7 +16947,7 @@ p, li { white-space: pre-wrap; } - + You are submitting a post. The key to a successful submission is interesting content and a descriptive title. @@ -16603,7 +16957,7 @@ p, li { white-space: pre-wrap; } 標題 - + Link @@ -16611,12 +16965,12 @@ p, li { white-space: pre-wrap; } PostedDialog - - <h1><img width="32" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1> <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p> <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p> <p>There is no restriction on which links are shared. Be careful when clicking on them.</p> <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p> + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;Boards</h1><p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and channels</p><p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to enlight important links.</p><p>There is no restriction on which links are shared. Be careful when clicking on them.</p><p>Boards are kept for %2 days, and sync-ed over the last %3 days, unless you change this.</p> - + Boards @@ -16650,7 +17004,7 @@ p, li { white-space: pre-wrap; } PostedGroupDialog - + Create New Board @@ -16688,7 +17042,17 @@ p, li { white-space: pre-wrap; } PostedGroupItem - + + Last activity + + + + + TextLabel + + + + Subscribe to Posted @@ -16704,7 +17068,7 @@ p, li { white-space: pre-wrap; } - + Expand 展開 @@ -16719,12 +17083,17 @@ p, li { white-space: pre-wrap; } - + Loading... - + + Never + + + + New Board @@ -16737,18 +17106,18 @@ p, li { white-space: pre-wrap; } PostedItem - + 0 - - + + Comments - + Copy RetroShare Link @@ -16759,12 +17128,12 @@ p, li { white-space: pre-wrap; } - + Comment - + Comments @@ -16774,7 +17143,7 @@ p, li { white-space: pre-wrap; } - + Click to view Picture @@ -16784,17 +17153,17 @@ p, li { white-space: pre-wrap; } 隱藏 - + Vote up - + Vote down - + Set as read and remove item 設置為已讀并刪除項目 @@ -16804,7 +17173,7 @@ p, li { white-space: pre-wrap; } 新建 - + New Comment: @@ -16814,7 +17183,7 @@ p, li { white-space: pre-wrap; } - + Name @@ -16855,30 +17224,11 @@ p, li { white-space: pre-wrap; } - + Loading - - PostedListWidget - - Form - 表單 - - - New - 新建 - - - Next - 下一個 - - - Previous - 前一個 - - PostedListWidgetWithModel @@ -16897,7 +17247,17 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + + + + + Items (at friends): + + + + 0 @@ -16907,15 +17267,15 @@ p, li { white-space: pre-wrap; } - + - + unknown - + Distribution: @@ -16925,42 +17285,42 @@ p, li { white-space: pre-wrap; } - + Created - + TextLabel - + Popularity: - - Contributions: - - - - + Sync period: - + + Number of subscribed friend nodes + + + + Posts - + Create Post - + <html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14pt; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html> @@ -16980,7 +17340,7 @@ p, li { white-space: pre-wrap; } - + Search @@ -17010,17 +17370,17 @@ p, li { white-space: pre-wrap; } - + No files in this post, or no post selected - + No posts available in this board - + Click to switch to card view @@ -17035,12 +17395,17 @@ p, li { white-space: pre-wrap; } - + Copy RetroShare Link - + + Copy http Link + + + + Show author in People tab @@ -17050,27 +17415,31 @@ p, li { white-space: pre-wrap; } 編輯 - + + information - + + The Retrohare link was copied to your clipboard. - + + Link creation error - + + Link could not be created: - + [No name] @@ -17085,7 +17454,7 @@ p, li { white-space: pre-wrap; } - + Never @@ -17159,6 +17528,16 @@ p, li { white-space: pre-wrap; } No Channel Selected + + + Could not vote + + + + + Error occured while voting: + + PostedPage @@ -17248,16 +17627,16 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Creating a new node with the same key allows your friend nodes to accept you automatically.</p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Select a Retroshare node key from the list below to be used on another computer, and press &quot;Export selected key.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To create a new location on a different computer, select the identity manager in the login window. From there you can import the key file and create a new location for that key. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Creating a new node with the same key allows your friend nodes to accept you automatically.</span></p></body></html> @@ -17365,7 +17744,7 @@ and use the import button to load it ProfileWidget - + Edit status message @@ -17381,7 +17760,7 @@ and use the import button to load it - + Public Information @@ -17416,12 +17795,12 @@ and use the import button to load it - + Other Information - + My Address @@ -17465,27 +17844,27 @@ and use the import button to load it PulseAddDialog - + Add to Pulse - + Display As - + URL - + GroupLabel - + IDLabel @@ -17495,12 +17874,12 @@ and use the import button to load it 從: - + Head - + Head Shot @@ -17530,13 +17909,13 @@ and use the import button to load it - - + + Whats happening? - + @@ -17548,12 +17927,22 @@ and use the import button to load it - + + Remove all images + + + + Clear Display As - + + Add Picture + + + + Post @@ -17568,7 +17957,7 @@ and use the import button to load it - + Reply to Pulse @@ -17583,34 +17972,24 @@ and use the import button to load it - + Like Pulse - + Hide Pictures - + Add Pictures - - - PulseItem - From - 來自 - - - Date - 日期 - - - ... - ... + + Load Picture File + @@ -17621,7 +18000,7 @@ and use the import button to load it 表單 - + @@ -17640,7 +18019,7 @@ and use the import button to load it PulseReply - + icn @@ -17650,7 +18029,7 @@ and use the import button to load it - + REPLY @@ -17677,7 +18056,7 @@ and use the import button to load it - + FOLLOW @@ -17687,7 +18066,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> @@ -17707,7 +18086,7 @@ and use the import button to load it - + <html><head/><body><p><span style=" color:#555753;">Replying to @sidler</span></p></body></html> @@ -17823,7 +18202,7 @@ and use the import button to load it - + FOLLOW @@ -17831,37 +18210,42 @@ and use the import button to load it PulseViewGroup - + headshot - + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - + <html><head/><body><p><span style=" font-weight:600;">Sidler</span></p></body></html> - + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - + Location - + + Edit profile + + + + Tag Line - + <html><head/><body><p><span style=" font-weight:600;">1.2K</span></p></body></html> @@ -17893,7 +18277,7 @@ and use the import button to load it - + FOLLOW @@ -17901,8 +18285,8 @@ and use the import button to load it QObject - - + + Confirmation @@ -18170,12 +18554,12 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + File Request canceled - + This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software. @@ -18206,7 +18590,7 @@ Characters <b>",|,/,\,&lt;,&gt;,*,?</b> will be replace - + Cannot start Tor Manager! @@ -18240,7 +18624,7 @@ The error reported is:" - + Multiple instances @@ -18259,6 +18643,26 @@ The error reported is:" + + + Old certificate + + + + + This node uses old certificate settings that are considered too weak by your current OpenSSL library version. You need to create a new node possibly using the same profile. + + + + + Tor error + + + + + Cannot run/configure Tor. Make sure it is installed on your system. + + Distant peer has closed the chat @@ -18338,7 +18742,7 @@ Reported error is: - + You appear to have nodes associated to DSA keys: @@ -18348,7 +18752,7 @@ Reported error is: - + enabled @@ -18358,7 +18762,7 @@ Reported error is: - + Move IP %1 to whitelist @@ -18374,7 +18778,7 @@ Reported error is: - + %1 seconds ago @@ -18441,7 +18845,7 @@ Security: no anonymous IDs - + Join chat room @@ -18469,7 +18873,7 @@ Security: no anonymous IDs - + Indefinitely @@ -18650,12 +19054,28 @@ Security: no anonymous IDs - - Status + + Name + Node + + + + + Address + + + + + + Status + + + + NXS @@ -18898,6 +19318,18 @@ Security: no anonymous IDs Server + + + + Missing channel post + + + + + + [System] + + QuickStartWizard @@ -19037,7 +19469,7 @@ p, li { white-space: pre-wrap; } - + Network Wide @@ -19204,7 +19636,7 @@ p, li { white-space: pre-wrap; } 表單 - + The loading of embedded images is blocked. @@ -19217,7 +19649,7 @@ p, li { white-space: pre-wrap; } RSPermissionMatrixWidget - + Allowed by default @@ -19390,12 +19822,22 @@ p, li { white-space: pre-wrap; } RSTextBrowser - + View &Source - + + Save image + + + + + Copy image + + + + Document source @@ -19403,12 +19845,12 @@ p, li { white-space: pre-wrap; } RSTreeWidget - + Tree View Options - + Show Header @@ -20096,7 +20538,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsDownloadListModel - + Name i.e: file name @@ -20217,7 +20659,7 @@ If you believe it is correct, remove the corresponding line from the file and re RsFriendListModel - + Name @@ -20237,7 +20679,7 @@ If you believe it is correct, remove the corresponding line from the file and re - + Profile ID @@ -20293,7 +20735,7 @@ prevents the message to be forwarded to your friends. - + [ ... Redacted message ... ] @@ -20307,11 +20749,6 @@ prevents the message to be forwarded to your friends. [Unknown] - - - [ ... Missing Message ... ] - - RsMessageModel @@ -20325,6 +20762,11 @@ prevents the message to be forwarded to your friends. From 來自 + + + To + + Subject @@ -20347,12 +20789,17 @@ prevents the message to be forwarded to your friends. - Click to sort by read + Click to sort by read status - Click to sort by from + Click to sort by author + + + + + Click to sort by destination @@ -20376,7 +20823,9 @@ prevents the message to be forwarded to your friends. - + + + [Notification] @@ -20397,7 +20846,7 @@ prevents the message to be forwarded to your friends. Rshare - + Resets ALL stored RetroShare settings. @@ -20458,7 +20907,7 @@ prevents the message to be forwarded to your friends. - + Unable to open log file '%1': %2 @@ -20479,7 +20928,7 @@ prevents the message to be forwarded to your friends. - + opmode @@ -20509,7 +20958,7 @@ prevents the message to be forwarded to your friends. - + Invalid language code specified: @@ -20527,7 +20976,7 @@ prevents the message to be forwarded to your friends. RshareSettings - + Registry Access Error. Maybe you need Administrator right. @@ -20544,12 +20993,12 @@ prevents the message to be forwarded to your friends. SearchDialog - + Enter a keyword here (at least 3 char long) - + Start Search @@ -20610,7 +21059,7 @@ prevents the message to be forwarded to your friends. - + KeyWords @@ -20625,7 +21074,7 @@ prevents the message to be forwarded to your friends. - + Filename @@ -20725,23 +21174,23 @@ prevents the message to be forwarded to your friends. - + File Name - + Download 下載 - + Copy RetroShare Link - + Send RetroShare Link @@ -20751,7 +21200,7 @@ prevents the message to be forwarded to your friends. - + Download Notice 下載 @@ -20788,7 +21237,7 @@ prevents the message to be forwarded to your friends. - + Folder 文件夾 @@ -20799,17 +21248,17 @@ prevents the message to be forwarded to your friends. - + New RetroShare Link(s) - + Open Folder - + Create Collection... @@ -20829,7 +21278,7 @@ prevents the message to be forwarded to your friends. - + Collection @@ -20837,7 +21286,7 @@ prevents the message to be forwarded to your friends. SecurityIpItem - + Peer details @@ -20853,22 +21302,22 @@ prevents the message to be forwarded to your friends. 刪除項目 - + IP address: - + Peer ID: - + Location: - + Peer Name: @@ -20885,7 +21334,7 @@ prevents the message to be forwarded to your friends. 隱藏 - + but reported: @@ -20910,8 +21359,8 @@ prevents the message to be forwarded to your friends. - - + + <html><head/><body><p>This warning is here to protect you against traffic forwarding attacks. In such a case, the friend you're connected to will not see your external IP, but the attacker's IP. </p><p><br/></p><p>However, if you just changed IPs for some reason (some ISPs regularly force change IPs) this warning just tells you that a friend connected to the new IP before Retroshare figured out the IP changed. Nothing's wrong in this case.</p><p><br/></p><p>You can easily suppress false warnings by white-listing your own IPs (e.g. the range of your ISP), or by completely disabling these warnings in Options-&gt;Notify-&gt;News Feed.</p></body></html> @@ -20919,7 +21368,7 @@ prevents the message to be forwarded to your friends. SecurityItem - + wants to be friend with you on RetroShare @@ -20950,7 +21399,7 @@ prevents the message to be forwarded to your friends. - + Expand 展開 @@ -20995,12 +21444,12 @@ prevents the message to be forwarded to your friends. - + Write Message - + Connect Attempt @@ -21020,17 +21469,12 @@ prevents the message to be forwarded to your friends. - + Unknown Security Issue - - A unknown peer - - - - + Unknown 未知 @@ -21040,7 +21484,17 @@ prevents the message to be forwarded to your friends. - + + SSL request + + + + + An unknown peer + + + + Hide 隱藏 @@ -21050,7 +21504,7 @@ prevents the message to be forwarded to your friends. - + Certificate has wrong signature!! This peer is not who he claims to be. @@ -21060,12 +21514,12 @@ prevents the message to be forwarded to your friends. - + Certificate caused an internal error. - + Peer/node not in friendlist (PGP id= @@ -21124,12 +21578,12 @@ prevents the message to be forwarded to your friends. - + Local Address - + NAT @@ -21150,22 +21604,22 @@ prevents the message to be forwarded to your friends. - + Local network - + External ip address finder - + UPnP - + Known / Previous IPs: @@ -21178,21 +21632,16 @@ behind a firewall or a VPN. - - Allow RetroShare to ask my ip to these websites: - - - - - - + + + kB/s - + Acceptable ports range from 10 to 65535. Normally Ports below 1024 are reserved by your system. @@ -21202,23 +21651,46 @@ behind a firewall or a VPN. - + Onion Address - + Discovery On (recommended) - + Tor has been automatically configured by Retroshare. You shouldn't need to change anything here. - + + sec + + + + + local + + + + + external + + + + + + +List of found external IP: + + + + + Discovery Off @@ -21228,7 +21700,7 @@ behind a firewall or a VPN. - + I2P Address @@ -21253,37 +21725,95 @@ behind a firewall or a VPN. - - + + + Proxy seems to work. - + + I2P proxy is not enabled - - BOB is running and accessible + + SAMv3 is running and accessible - BOB is not accessible! Is it running? + SAMv3 is not accessible! Is i2p running and SAM enabled? - - RetroShare uses BOB to set up a %1 tunnel at %2:%3 (named %4) + + Your key uses the following algorithms: %1 and %2 + + + + + + unkown key type + + + + + RetroShare uses SAMv3 to set up a %1 tunnel at %2:%3 +(id: %4) -When changing options (e.g. port) use the buttons at the bottom to restart BOB. +When changing options use the buttons at the bottom to restart SAMv3. - + + Offline, no SAM session is established yet. + + + + + + SAM is trying to establish a session ... this can take some time. + + + + + + SAM session established! Now setting up a forward session ... + + + + + + Online, SAM is working as exptected + + + + + + You key uses %1 for signing and %2 for crypto + + + + + stop SAM tunnel first to generate a new key + + + + + stop SAM tunnel first to load a key + + + + + stop SAM tunnel first to disable SAM + + + + client @@ -21298,71 +21828,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - - - BOB is processing a request - - - - - connectivity check - - - - - generating key - - - - - starting up - - - - - shuting down - - - - - BOB is processing a request: %1 - - - - - BOB is broken - - - - - - BOB encountered an error: - - - - - - BOB tunnel is running - - - - - BOB is working fine: tunnel established - - - - - BOB tunnel is not running - - - - - BOB is inactive: tunnel closed - - - - + request a new server key @@ -21372,22 +21838,7 @@ When changing options (e.g. port) use the buttons at the bottom to restart BOB. - - stop BOB tunnel first to generate a new key - - - - - stop BOB tunnel first to load a key - - - - - stop BOB tunnel first to disable BOB - - - - + You are reachable through the hidden service. @@ -21399,12 +21850,12 @@ Also check your ports! - + [Hidden mode] - + <html><head/><body><p>This clears the list of known addresses. This action is useful if for some reason your address list contains an invalid/irrelevant/expired address that you want to avoid passing to your friends as a contact address.</p></body></html> @@ -21414,7 +21865,7 @@ Also check your ports! - + Download limit (KB/s) @@ -21429,23 +21880,23 @@ Also check your ports! - + <html><head/><body><p>The upload limit covers the entire software. Too small an upload limit might eventually block low priority services (forums, channels). A minimum recommended value is 50KB/s. </p></body></html> - + WARNING: These values don't take into account the Relays. - + <html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. It will allow you to also connect </p><p>to hidden nodes.</p></body></html> - + Tor Socks Proxy default: 127.0.0.1:9050. Set in torrc config and update here. I2P Socks Proxy: see http://127.0.0.1:7657/i2ptunnelmgr for setting up a client tunnel: @@ -21456,17 +21907,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - Automatic I2P/BOB - - - - - Enable I2P BOB - changing this requires a restart to fully take effect - - - - + enableds advanced settings @@ -21476,12 +21917,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P Basic Open Bridge - - - - + I2P Instance address @@ -21491,17 +21927,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - I2P proxy port - - - - - BOB accessible - - - - + Address @@ -21541,7 +21967,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - + Start @@ -21556,12 +21982,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why - - BOB status - - - - + Incoming @@ -21597,7 +22018,32 @@ If you have issues connecting over Tor check the Tor logs too. - + + Automatic I2P + + + + + Enable I2P SAMv3 - changing this requires a restart to fully take effect + + + + + I2P Simple Anonymous Messaging + + + + + SAM accessible + + + + + SAM status + + + + Relay @@ -21652,7 +22098,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Warning: This bandwidth adds up to the max bandwidth. @@ -21677,7 +22123,7 @@ If you have issues connecting over Tor check the Tor logs too. - + <p>By activating relays, you allow your Retroshare node to act as a bridge between Retroshare users who cannot connect directly, e.g. because they're firewalled.</p> <p>You may choose to act as a relay by checking <i>enable relay connections</i>, or simply benefit from other peers acting as relay, by checking <i>use relay servers</i>. For the former, you may specify the bandwidth allocated when acting as a relay for friends of you, for friends of your friends, or anyone in the Retroshare network.</p> <p>In any case, a Retroshare node acting as a relay cannot see the relayed traffic, since it is encrypted and authenticated by the two relayed nodes.</p> @@ -21689,7 +22135,7 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Filters @@ -21712,7 +22158,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Status @@ -21772,17 +22218,28 @@ If you have issues connecting over Tor check the Tor logs too. - + Hidden Service Configuration - + + Allow RetroShare to ask my ip to these DNS servers: + + + + + + List of OpenDns servers used. + + + + <html><head/><body><p>This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to</p><p>Hidden nodes. The led at right turns green when this port is active on your computer. </p><p>This does not mean however that your Retroshare traffic transits though Tor. It does only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though Tor. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> @@ -21798,18 +22255,18 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html> - + I2P outgoing Okay - + Service Address @@ -21844,12 +22301,12 @@ If you have issues connecting over Tor check the Tor logs too. - + IP Range - + Reported by DHT for IP masquerading @@ -21872,22 +22329,22 @@ If you have issues connecting over Tor check the Tor logs too. - + <html><head/><body><p>White listed IPs are gathered from the following sources: IPs coming inside a manually exchanged certificate, IP ranges entered by you in this window, or in the security feed items.</p><p>The default behavior for Retroshare is to (1) always allow connection to peers with IP in the whitelist, even if that IP is also blacklisted; (2) optionally require IPs to be in the whitelist. You can change this behavior for each peer in the &quot;Details&quot; window of each Retroshare node. </p></body></html> - + <html><head/><body><p>The DHT allows you to answer connection requests from your friends using BitTorrent's DHT. It greatly improves the connectivity. No information is actually stored in the DHT. It is only used as a proxy system to get in touch with other Retroshare nodes.</p><p>The Discovery service sends node name and ids of your trusted contacts to connected peers, to help them choose new friends. The friendship is never automatic however, and both peers still need to trust each other to allow connection. </p></body></html> - + <html><head/><body><p>The bullet turns green as soon as Retroshare manages to get your own IP from the websites listed below, if you enabled that action. Retroshare will also use other means to find out your own IP.</p></body></html> - + <html><head/><body><p>This list gets automatically filled with information gathered at multiple sources: masquerading peers reported by the DHT, IP ranges entered by you, and IP ranges reported by your friends. Default settings should protect you against large scale traffic relaying.</p><p>Automatically guessing masquerading IPs can put your friends IPs in the blacklist. In this case, use the context menu to whitelist them.</p></body></html> @@ -21922,7 +22379,7 @@ If you have issues connecting over Tor check the Tor logs too. - + Outgoing Manual Tor/I2P @@ -21932,12 +22389,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Tor outgoing Okay - + Tor proxy is not enabled @@ -22017,7 +22474,7 @@ If you have issues connecting over Tor check the Tor logs too. ShareKey - + check peers you would like to share private publish key with @@ -22027,12 +22484,12 @@ If you have issues connecting over Tor check the Tor logs too. - + Share - + You can let your friends know about your Channel by sharing it with them. Select the Friends with which you want to Share your Channel. @@ -22051,7 +22508,7 @@ Select the Friends with which you want to Share your Channel. - + Shared directory @@ -22071,17 +22528,17 @@ Select the Friends with which you want to Share your Channel. - + Add new - + Cancel 取消 - + Add a Share Directory @@ -22091,7 +22548,7 @@ Select the Friends with which you want to Share your Channel. 刪除 - + Apply and close @@ -22182,7 +22639,7 @@ Select the Friends with which you want to Share your Channel. - + This is a list of shared folders. You can add and remove folders using the buttons at the bottom. When you add a new folder, intially all files in that folder are shared. You can separately setup share flags for each shared directory. @@ -22190,7 +22647,7 @@ Select the Friends with which you want to Share your Channel. SharedFilesDialog - + Files @@ -22241,11 +22698,16 @@ Select the Friends with which you want to Share your Channel. + <html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html> + + + + check files - + Download selected @@ -22255,7 +22717,7 @@ Select the Friends with which you want to Share your Channel. 下載 - + Copy retroshare Links to Clipboard @@ -22270,7 +22732,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted @@ -22286,7 +22748,7 @@ Select the Friends with which you want to Share your Channel. - + Create Collection... @@ -22311,7 +22773,7 @@ Select the Friends with which you want to Share your Channel. - + Some files have been omitted because they have not been indexed yet. @@ -22454,12 +22916,12 @@ Select the Friends with which you want to Share your Channel. SplashScreen - + Load configuration - + Create interface @@ -22483,7 +22945,7 @@ Select the Friends with which you want to Share your Channel. - + Log In @@ -22822,7 +23284,7 @@ This choice can be reverted in settings. - + Message: @@ -23059,7 +23521,7 @@ p, li { white-space: pre-wrap; } TagsMenu - + Remove All Tags @@ -23095,12 +23557,15 @@ p, li { white-space: pre-wrap; } - + + Tor status: - + + + Unknown 未知 @@ -23110,18 +23575,13 @@ p, li { white-space: pre-wrap; } - - Hidden service address: + + Hidden address: - - Tor bootstrap status: - - - - - + + Not set @@ -23131,12 +23591,57 @@ p, li { white-space: pre-wrap; } - + + Error + + + + + Not connected + + + + + Connecting + + + + + Socket connected + + + + + Authenticating + + + + + Authenticated + + + + + Hidden service ready + + + + + Tor offline + + + + + Tor ready + + + + Check that Tor is accessible in your executable path - + [Waiting for Tor...] @@ -23144,7 +23649,7 @@ p, li { white-space: pre-wrap; } TorStatus - + Tor @@ -23154,7 +23659,7 @@ p, li { white-space: pre-wrap; } - + Tor is currently offline @@ -23165,11 +23670,12 @@ p, li { white-space: pre-wrap; } + No tor configuration - + Tor proxy is OK @@ -23197,7 +23703,7 @@ p, li { white-space: pre-wrap; } TransferPage - + Transfer options @@ -23208,7 +23714,7 @@ p, li { white-space: pre-wrap; } - + Shared Directories @@ -23218,22 +23724,27 @@ p, li { white-space: pre-wrap; } - - Edit Share - - - - + Directories - + + Configure shared directories + + + + Auto-check shared directories every + <html><head/><body><p>Retroshare will quickly scan shared directories for new/removed files. It will not detect changes in existing files for efficiency reasons. It is however possible to force a full re-scan of the entire hierarchy including possibly modified files using the &quot;check files&quot; button in shared files tab.</p></body></html> + + + + minute(s) @@ -23318,7 +23829,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> @@ -23327,7 +23838,12 @@ p, li { white-space: pre-wrap; } - + + Minimum font size for Shared Files + + + + Maximum uploads per friend (0 = no limit) @@ -23352,7 +23868,12 @@ p, li { white-space: pre-wrap; } - + + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + + + + Streaming @@ -23417,12 +23938,7 @@ p, li { white-space: pre-wrap; } - - <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> - - - - + <html><head/><body><p>Retroshare will suspend all transfers and config file saving if the disk space goes below this limit. That prevents loss of information on some systems. A popup window will warn you when that happens.</p></body></html> @@ -23432,7 +23948,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use "progressive")? + + + + Set Incoming Directory @@ -23460,7 +23986,7 @@ p, li { white-space: pre-wrap; } TransferUserNotify - + Download completed @@ -23488,19 +24014,19 @@ p, li { white-space: pre-wrap; } TransfersDialog - - + + Downloads - + Uploads - + Name i.e: file name @@ -23707,7 +24233,12 @@ p, li { white-space: pre-wrap; } - + + <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp; File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> + + + + Move in Queue... @@ -23732,7 +24263,7 @@ p, li { white-space: pre-wrap; } - + Anonymous end-to-end encrypted tunnel 0x @@ -23753,7 +24284,7 @@ p, li { white-space: pre-wrap; } - + @@ -23786,7 +24317,17 @@ p, li { white-space: pre-wrap; } - + + Warning + + + + + On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway? + + + + Change file name @@ -23801,7 +24342,7 @@ p, li { white-space: pre-wrap; } - + Expand all @@ -23928,23 +24469,18 @@ p, li { white-space: pre-wrap; } - - <h1><img width="%1" src=":/icons/help_64.png">&nbsp;&nbsp;File Transfer</h1><p>Retroshare brings two ways of transferring files: direct transfers from your friends, and distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming (you can be a source while downloading)</p><p>You can share files using the <img src=":/images/directoryadd_24x24_shadow.png" width=%2 /> icon from the left side bar. These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files in their Friends Files tab</p><p>The search tab reports files from your friends' file lists, and distant files that can be reached anonymously using the multi-hop tunnelling system.</p> - - - - + Columns - + File Transfers - + Path @@ -23954,7 +24490,7 @@ p, li { white-space: pre-wrap; } - + Could not delete preview file @@ -23964,7 +24500,7 @@ p, li { white-space: pre-wrap; } - + Create Collection... @@ -23979,7 +24515,7 @@ p, li { white-space: pre-wrap; } - + Collection @@ -23989,7 +24525,7 @@ p, li { white-space: pre-wrap; } - + Anonymous tunnel 0x @@ -24403,12 +24939,17 @@ p, li { white-space: pre-wrap; } 表單 - + Enable Retroshare WEB Interface - + + Status: + + + + Web parameters @@ -24448,17 +24989,27 @@ p, li { white-space: pre-wrap; } - + Please select the directory were to find retroshare webinterface files - + + Missing passphrase + + + + + Please set a passphrase to proect the access to the WEB interface. + + + + <h1><img width="24" src=":/icons/help_64.png">&nbsp;&nbsp;Webinterface</h1> <p>The webinterface allows you to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet computer and later use a desktop computer to continue it.</p> <p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p> - + Webinterface not enabled @@ -24468,12 +25019,12 @@ p, li { white-space: pre-wrap; } - + failed to start Webinterface - + Webinterface @@ -24610,7 +25161,7 @@ p, li { white-space: pre-wrap; } - + Page Name @@ -24625,7 +25176,7 @@ p, li { white-space: pre-wrap; } - + << @@ -24713,7 +25264,7 @@ p, li { white-space: pre-wrap; } WikiEditDialog - + Page Edit History @@ -24748,7 +25299,7 @@ p, li { white-space: pre-wrap; } - + \/ @@ -24778,14 +25329,18 @@ p, li { white-space: pre-wrap; } - - + + History + + + + Show Edit History - + Status @@ -24806,7 +25361,7 @@ p, li { white-space: pre-wrap; } - + Submit @@ -24889,16 +25444,7 @@ p, li { white-space: pre-wrap; } - ... - ... - - - - Refresh - - - - + Settings @@ -24913,7 +25459,7 @@ p, li { white-space: pre-wrap; } - + Who to Follow @@ -24933,7 +25479,7 @@ p, li { white-space: pre-wrap; } - + Most Recent @@ -24963,11 +25509,7 @@ p, li { white-space: pre-wrap; } - New - 新建 - - - + Yourself @@ -24977,7 +25519,7 @@ p, li { white-space: pre-wrap; } - + RetroShare @@ -25040,35 +25582,42 @@ p, li { white-space: pre-wrap; } 表單 - - Masthead - - - + + MastHead background Image - + Select Image - + Tagline: + Remove + 刪除 + + + Location: - + Load Masthead + + + Use the mouse to zoom and adjust the image for your background. + + WireGroupItem @@ -25113,11 +25662,41 @@ p, li { white-space: pre-wrap; } Edit Profile + + + Own + + + + + N/A + + + + + Following + + + + + Unfollow + + + + + Other + + + + + Follow + + misc - + Unknown Unknown (size) 未知 @@ -25195,7 +25774,7 @@ p, li { white-space: pre-wrap; } - + k e.g: 3.1 k @@ -25232,7 +25811,7 @@ p, li { white-space: pre-wrap; } pgpid_item_model - + Do you accept connections signed by this profile? diff --git a/retroshare-gui/src/main.cpp b/retroshare-gui/src/main.cpp index cfb9932ca..228f24067 100644 --- a/retroshare-gui/src/main.cpp +++ b/retroshare-gui/src/main.cpp @@ -22,12 +22,17 @@ #include "util/stacktrace.h" #include "util/argstream.h" +#include "retroshare/rswebui.h" CrashStackTrace gCrashStackTrace; #include #include #include +#include +#include +#include +#include #include #include "gui/common/FilesDefs.h" @@ -66,7 +71,7 @@ CrashStackTrace gCrashStackTrace; # include "gui/settings/JsonApiPage.h" #endif // RS_JSONAPI -#include "TorControl/TorManager.h" +#include "retroshare/rstor.h" #include "TorControl/TorControlWindow.h" #include "retroshare/rsidentity.h" @@ -90,304 +95,483 @@ CrashStackTrace gCrashStackTrace; extern "C" { __declspec(dllexport) __cdecl BOOL _OPENSSL_isservice(void) { - DWORD sess; - if (ProcessIdToSessionId(GetCurrentProcessId(),&sess)) - return sess==0; - return FALSE; + DWORD sess; + if (ProcessIdToSessionId(GetCurrentProcessId(),&sess)) + return sess==0; + return FALSE; } } #endif #endif -/*** WINDOWS DON'T LIKE THIS - REDEFINES VER numbers. -#include -****/ - #include #include #include #include "gui/notifyqt.h" #include +static void showHelp(const argstream& as) +{ + RsInfo() << "\n" << + "+================================================================+\n" + "| o---o o |\n" + "| \\ / - Retroshare GUI - / \\ |\n" + "| o o---o |\n" + "+================================================================+" + << std::endl ; + + std::cerr << as.usage(false) << std::endl; + + char *argv[1]; + int argc=0; + QApplication dummyApp (argc, argv); // needed for QMessageBox + QMessageBox box; + QString text = QString::fromUtf8(as.usage(false,false).c_str()); + QFont font("Courier New",10,50,false); + font.setStyleHint(QFont::TypeWriter,QFont::PreferMatch); + font.setStyle(QFont::StyleNormal); + font.setBold(true); + box.setFont(font); + box.setInformativeText(text); + box.setWindowTitle(QObject::tr("Retroshare commandline arguments")); + + // now compute the size of text and set the size of the box. For the record, this doesn't work... + box.setBaseSize( QSize(QFontMetricsF(font).width(text),QFontMetricsF(font).height()*text.count('\n')) ); + box.exec(); +} + +static bool notifyRunningInstance() +{ + // Connect to the Local Server of the main process to notify it + // that a new process had been started + + RsInfo() << "Trying to contact running instance through socket \"" << TARGET << "\""; + QLocalSocket localSocket; + localSocket.connectToServer(QString(TARGET)); +#ifdef DEBUG + std::cerr << "RsApplication::RsApplication waitForConnected to other instance." << std::endl; +#endif + if( localSocket.waitForConnected(100) ) + { +#ifdef DEBUG + std::cerr << "RsApplication::RsApplication Connection etablished. Waiting for disconnection." << std::endl; +#endif + localSocket.waitForDisconnected(1000); + return true; + } + else + { +#ifdef DEBUG + std::cerr << "RsApplication::RsApplication failed to connect to other instance." << std::endl; +#endif + return false; + } +} + +static void sendArgsToRunningInstance(const QStringList& args) +{ + QString serverName = QString(TARGET); + + // load into shared memory + QBuffer buffer; + buffer.open(QBuffer::ReadWrite); + QDataStream out(&buffer); + out << args; + int size = buffer.size(); + + QSharedMemory newArgs; + newArgs.setKey(serverName + "_newArgs"); + if (newArgs.isAttached()) newArgs.detach(); + + if (!newArgs.create(size)) { + std::cerr << "(EE) RsApplication::RsApplication Unable to create shared memory segment of size:" + << size << " error:" << newArgs.errorString().toStdString() << "." << std::endl; +#ifdef Q_OS_UNIX + std::cerr << "Look with `ipcs -m` for nattch==0 segment. And remove it with `ipcrm -m 'shmid'`." << std::endl; + //No need for windows, as it removes shared segment directly even when crash. +#endif + newArgs.detach(); + ::exit(EXIT_FAILURE); + } + newArgs.lock(); + char *to = (char*)newArgs.data(); + const char *from = buffer.data().data(); + memcpy(to, from, qMin(newArgs.size(), size)); + newArgs.unlock(); + + std::cerr << "RsApplication::RsApplication waitForConnected to other instance." << std::endl; + if(notifyRunningInstance()) + { + newArgs.detach(); + std::cerr << "RsApplication::RsApplication Arguments was sended." << std::endl + << " To disable it, in Options - General - Misc," << std::endl + << " uncheck \"Use Local Server to get new Arguments\"." << std::endl; + ::exit(EXIT_SUCCESS); // Terminate the program using STDLib's exit function + } + else + std::cerr << "RsApplication::RsApplication failed to connect to other instance." << std::endl; + newArgs.detach(); +} + +static bool setLanguage(const std::string& language) +{ + if(!language.empty()) + { + if(!LanguageSupport::translate(QString::fromStdString(language))) + { + RsErr() << "Language \"" << language << "\" is not supported." ; + + QString s; + for(QString ss:LanguageSupport::languageCodes()) + s += ss + ", " ; + + RsErr() << "Possible choices are: " << s.toStdString(); + return false; + } + return true; + } + else + { + LanguageSupport::translate(LanguageSupport::defaultLanguageCode()); + return true; + } +} + + static void displayWarningAboutDSAKeys() { - std::map > unsupported_keys; - RsAccounts::GetUnsupportedKeys(unsupported_keys); - - if(unsupported_keys.empty()) - return ; + std::map > unsupported_keys; + RsAccounts::GetUnsupportedKeys(unsupported_keys); - QMessageBox msgBox; + if(unsupported_keys.empty()) + return ; - QString txt = QObject::tr("You appear to have nodes associated to DSA keys:"); - txt += "
      " ; - for(std::map >::const_iterator it(unsupported_keys.begin());it!=unsupported_keys.end();++it) - { - txt += "
    • " + QString::fromStdString(it->first) ; - txt += "
        " ; + QMessageBox msgBox; - for(uint32_t i=0;isecond.size();++i) - txt += "
      • " + QString::fromStdString(it->second[i]) + "
      • " ; + QString txt = QObject::tr("You appear to have nodes associated to DSA keys:"); + txt += "
          " ; + for(std::map >::const_iterator it(unsupported_keys.begin());it!=unsupported_keys.end();++it) + { + txt += "
        • " + QString::fromStdString(it->first) ; + txt += "
            " ; - txt += "
          " ; - txt += "
        • " ; - } - txt += "
        " ; + for(uint32_t i=0;isecond.size();++i) + txt += "
      • " + QString::fromStdString(it->second[i]) + "
      • " ; - msgBox.setText(txt) ; - msgBox.setInformativeText(QObject::tr("DSA keys are not yet supported by this version of RetroShare. All these nodes will be unusable. We're very sorry for that.")); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); + txt += "
      " ; + txt += "
    • " ; + } + txt += "
    " ; + + msgBox.setText(txt) ; + msgBox.setInformativeText(QObject::tr("DSA keys are not yet supported by this version of RetroShare. All these nodes will be unusable. We're very sorry for that.")); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); msgBox.setWindowIcon(FilesDefs::getIconFromQtResourcePath(":/icons/logo_128.png")); - msgBox.exec(); + msgBox.exec(); } #ifdef WINDOWS_SYS #if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) && QT_VERSION < QT_VERSION_CHECK (5, 3, 0) QStringList filedialog_open_filenames_hook(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) { - return QFileDialog::getOpenFileNames(parent, caption, dir, filter, selectedFilter, options | QFileDialog::DontUseNativeDialog); + return QFileDialog::getOpenFileNames(parent, caption, dir, filter, selectedFilter, options | QFileDialog::DontUseNativeDialog); } QString filedialog_open_filename_hook(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) { - return QFileDialog::getOpenFileName(parent, caption, dir, filter, selectedFilter, options | QFileDialog::DontUseNativeDialog); + return QFileDialog::getOpenFileName(parent, caption, dir, filter, selectedFilter, options | QFileDialog::DontUseNativeDialog); } QString filedialog_save_filename_hook(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) { - return QFileDialog::getSaveFileName(parent, caption, dir, filter, selectedFilter, options | QFileDialog::DontUseNativeDialog); + return QFileDialog::getSaveFileName(parent, caption, dir, filter, selectedFilter, options | QFileDialog::DontUseNativeDialog); } QString filedialog_existing_directory_hook(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options) { - return QFileDialog::getExistingDirectory(parent, caption, dir, options | QFileDialog::DontUseNativeDialog); + return QFileDialog::getExistingDirectory(parent, caption, dir, options | QFileDialog::DontUseNativeDialog); } #endif #endif int main(int argc, char *argv[]) -{ +{ #ifdef WINDOWS_SYS - // The current directory of the application is changed when using the native dialog on Windows - // This is a quick fix until libretroshare is using a absolute path in the portable Version + // The current directory of the application is changed when using the native dialog on Windows + // This is a quick fix until libretroshare is using a absolute path in the portable Version #if QT_VERSION >= QT_VERSION_CHECK (5, 3, 0) - // Do we need a solution in v0.6? + // Do we need a solution in v0.6? #endif #if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) && QT_VERSION < QT_VERSION_CHECK (5, 3, 0) - typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options); - typedef QString (*_qt_filedialog_open_filename_hook) (QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options); - typedef QString (*_qt_filedialog_save_filename_hook) (QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options); - typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options); + typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options); + typedef QString (*_qt_filedialog_open_filename_hook) (QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options); + typedef QString (*_qt_filedialog_save_filename_hook) (QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options); + typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options); - extern Q_GUI_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook; - extern Q_GUI_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook; - extern Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook; - extern Q_GUI_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook; + extern Q_GUI_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook; + extern Q_GUI_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook; + extern Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook; + extern Q_GUI_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook; - qt_filedialog_open_filename_hook = filedialog_open_filename_hook; - qt_filedialog_open_filenames_hook = filedialog_open_filenames_hook; - qt_filedialog_save_filename_hook = filedialog_save_filename_hook; - qt_filedialog_existing_directory_hook = filedialog_existing_directory_hook; + qt_filedialog_open_filename_hook = filedialog_open_filename_hook; + qt_filedialog_open_filenames_hook = filedialog_open_filenames_hook; + qt_filedialog_save_filename_hook = filedialog_save_filename_hook; + qt_filedialog_existing_directory_hook = filedialog_existing_directory_hook; #endif #if QT_VERSION < QT_VERSION_CHECK (5, 0, 0) - extern bool Q_GUI_EXPORT qt_use_native_dialogs; - qt_use_native_dialogs = false; + extern bool Q_GUI_EXPORT qt_use_native_dialogs; + qt_use_native_dialogs = false; #endif - { - /* Set the current directory to the application dir, - because the start dir with autostart from the registry run key is not the exe dir */ - QApplication app(argc, argv); - QDir::setCurrent(QCoreApplication::applicationDirPath()); - } + { + /* Set the current directory to the application dir, + because the start dir with autostart from the registry run key is not the exe dir */ + QApplication app(argc, argv); + QDir::setCurrent(QCoreApplication::applicationDirPath()); + } #endif #ifdef SIGFPE_DEBUG feenableexcept(FE_INVALID | FE_DIVBYZERO); #endif - QStringList args = char_array_to_stringlist(argv+1, argc-1); + QStringList args = char_array_to_stringlist(argv+1, argc-1); Q_INIT_RESOURCE(images); Q_INIT_RESOURCE(icons); - // Loop through all command-line args/values to get help wanted before RsInit exit. - for (int i = 0; i < args.size(); ++i) { - QString arg; - /* Get the argument name and set a blank value */ - arg = args.at(i); - if ((arg.toLower() == "-h") || (arg.toLower() == "--help")) { - QApplication dummyApp (argc, argv); // needed for QMessageBox - Rshare::showUsageMessageBox(); - } - } + // This is needed to allocate rsNotify, so that it can be used to ask for PGP passphrase + // + RsControl::earlyInitNotificationSystem() ; - // This is needed to allocate rsNotify, so that it can be used to ask for PGP passphrase - // - RsControl::earlyInitNotificationSystem() ; + NotifyQt *notify = NotifyQt::Create(); + rsNotify->registerNotifyClient(notify); - NotifyQt *notify = NotifyQt::Create(); - rsNotify->registerNotifyClient(notify); + /* RetroShare Core Objects */ + RsInit::InitRsConfig(); - /* RetroShare Core Objects */ - RsInit::InitRsConfig(); + RsGUIConfigOptions conf; - RsConfigOptions conf; + std::string rslink,rsfile; + std::list links_and_files; + std::string loglevel="off"; + std::string logfilename,language,guistyle,guistylesheetfile; - argstream as(argc,argv); - as >> option('s',"stderr" ,conf.outStderr ,"output to stderr instead of log file." ) - >> option('u',"udp" ,conf.udpListenerOnly,"Only listen to UDP." ) - >> parameter('c',"base-dir" ,conf.optBaseDir ,"directory", "Set base directory." ,false) - >> parameter('l',"log-file" ,conf.logfname ,"logfile" ,"Set Log filename." ,false) - >> parameter('d',"debug-level" ,conf.debugLevel ,"level" ,"Set debug level." ,false) - >> parameter('i',"ip-address" ,conf.forcedInetAddress,"nnn.nnn.nnn.nnn", "Force IP address to use (if cannot be detected)." ,false) - >> parameter('p',"port" ,conf.forcedPort ,"port" ,"Set listenning port to use." ,false) - >> parameter('o',"opmode" ,conf.opModeStr ,"opmode" ,"Set Operating mode (Full, NoTurtle, Gaming, Minimal)." ,false); + argstream as(argc,argv); + as >> option( 's',"stderr" ,conf.outStderr ,"output to stderr instead of log file " ) + >> option( 'u',"udp" ,conf.udpListenerOnly ,"Only listen to UDP " ) + >> option( 'R',"reset" ,conf.optResetParams ,"reset retroshare parameters " ) + >> parameter('c',"base-dir" ,conf.optBaseDir ,"directory" ,"Set base directory " ,false) + >> parameter('l',"log-file" ,logfilename ,"logfile" ,"Set Log filename " ,false) + >> parameter('d',"debug-level" ,loglevel ,"level (debug,info,notice,warn,error,off)","Set debug level " ,false) + >> parameter('i',"ip-address" ,conf.forcedInetAddress ,"nnn.nnn.nnn.nnn" ,"Force IP address " ,false) + >> parameter('p',"port" ,conf.forcedPort ,"port" ,"Set listenning port " ,false) + >> parameter('o',"opmode" ,conf.opModeStr ,"opmode (Full, NoTurtle, Gaming, Minimal)","Set mode" ,false) + >> parameter('t',"tor" ,conf.userSuppliedTorExecutable,"path" ,"supply full tor executable path " ,false) + >> parameter('g',"style" ,guistyle ,"style (fusion,windows,gtk2,breeze)" ,"set GUI style" ,false) + >> parameter('k',"style" ,guistylesheetfile ,"file" ,"gui stylesheet file" ,false) + >> parameter('L',"lang" ,language ,"langage (fr,cn,...)" ,"set language" ,false) + >> parameter('r',"link" ,rslink ,"retroshare link" ,"retroshare link to open (passed to running server)" ,false) + >> parameter('f',"rsfile" ,rsfile ,"rsfile" ,"rscollection file to open (passed to running server)" ,false); #ifdef RS_JSONAPI - as >> parameter('J', "jsonApiPort", conf.jsonApiPort, "jsonApiPort", "Enable JSON API on the specified port", false ) - >> parameter('P', "jsonApiBindAddress", conf.jsonApiBindAddress, "jsonApiBindAddress", "JSON API Bind Address.", false); + as >> parameter('J', "jsonApiPort" ,conf.jsonApiPort ,"jsonApiPort" ,"Enable JSON API on the specified port" ,false) + >> parameter('P', "jsonApiBindAddress",conf.jsonApiBindAddress ,"jsonApiBindAddress" ,"JSON API Bind Address " ,false); #endif // ifdef RS_JSONAPI #ifdef LOCALNET_TESTING - as >> parameter('R',"restrict-port" ,portRestrictions ,"port1-port2","Apply port restriction" ,false); + as >> parameter('R',"restrict-port" ,portRestrictions ,"port1-port2","Apply port restriction " ,false); #endif // ifdef LOCALNET_TESTING #ifdef RS_AUTOLOGIN - as >> option('a',"auto-login" ,conf.autoLogin ,"AutoLogin (Windows Only) + StartMinimised"); + as >> option('a',"auto-login" ,conf.autoLogin ,"AutoLogin (Windows Only) + StartMinimised"); #endif // ifdef RS_AUTOLOGIN + as >> values(std::back_inserter(links_and_files),"links and rscollection files") + >> help('h',"help",QObject::tr("Display this help").toStdString().c_str()); + + if(!as.isOk()) + { + std::cerr << "Incorrect arguments." << std::endl; + std::cerr << as.usage() << std::endl; + return 0; + } + conf.logFileName = QString::fromStdString(logfilename); + conf.logLevel = QString::fromStdString(loglevel); // these will be checked when used in RsApplication + conf.guiStyle = QString::fromStdString(guistyle); // these will be checked when used in RsApplication + conf.guiStyleSheetFile = QString::fromUtf8(guistylesheetfile.c_str());// these will be checked when used in RsApplication + + if(as.helpRequested()) + { + showHelp(as); + return 0; + } + // Look for parameters to be transmitted to running server + + if((!rslink.empty() || !rsfile.empty() || !links_and_files.empty() || !conf.opModeStr.empty()) && notifyRunningInstance()) + { + QStringList args; + RsErr() << "Sending rscollection files, retroshare links and opmode parameters to the runnning retroshare server." ; + + if(!rslink.empty()) { args.push_back("-l"); args.push_back(QString::fromUtf8(rslink.c_str())); } + if(!rsfile.empty()) { args.push_back("-f"); args.push_back(QString::fromUtf8(rsfile.c_str())); } + + for(auto s:links_and_files) + args.push_back(QString::fromUtf8(s.c_str())); + + if(!conf.opModeStr.empty()) { args.push_back("-o"); args.push_back(QString::fromStdString(conf.opModeStr)); } + + sendArgsToRunningInstance(args); + return 0; + } + + // Now start RS login system conf.main_executable_path = argv[0]; - int initResult = RsInit::InitRetroShare(conf); + int initResult = RsInit::InitRetroShare(conf); - if(initResult == RS_INIT_NO_KEYRING) // happens when we already have accounts, but no pgp key. This is when switching to the openpgp-sdk version. - { - QApplication dummyApp (argc, argv); // needed for QMessageBox - /* Translate into the desired language */ - LanguageSupport::translate(LanguageSupport::defaultLanguageCode()); + if(initResult == RS_INIT_NO_KEYRING) // happens when we already have accounts, but no pgp key. This is when switching to the openpgp-sdk version. + { + QApplication dummyApp (argc, argv); // needed for QMessageBox + /* Translate into the desired language */ - QMessageBox msgBox; - msgBox.setText(QObject::tr("This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances.

    You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software.")); - msgBox.setInformativeText(QObject::tr("Choose between:
    • Ok to copy the existing keyring from gnupg (safest bet), or
    • Close without saving to start fresh with an empty keyring (you will be asked to create a new PGP key to work with RetroShare, or import a previously saved pgp keypair).
    • Cancel to quit and forge a keyring by yourself (needs some PGP skills)
    ")); - msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Discard | QMessageBox::Cancel); - msgBox.setDefaultButton(QMessageBox::Ok); + if(!setLanguage(language)) + return 1; + + QMessageBox msgBox; + msgBox.setText(QObject::tr("This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances.

    You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software.")); + msgBox.setInformativeText(QObject::tr("Choose between:
    • Ok to copy the existing keyring from gnupg (safest bet), or
    • Close without saving to start fresh with an empty keyring (you will be asked to create a new PGP key to work with RetroShare, or import a previously saved pgp keypair).
    • Cancel to quit and forge a keyring by yourself (needs some PGP skills)
    ")); + msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Discard | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Ok); msgBox.setWindowIcon(FilesDefs::getIconFromQtResourcePath(":/icons/logo_128.png")); - int ret = msgBox.exec(); + int ret = msgBox.exec(); - if(ret == QMessageBox::Cancel) - return 0 ; - if(ret == QMessageBox::Ok) - { - if(!RsAccounts::CopyGnuPGKeyrings()) - return 0 ; + if(ret == QMessageBox::Cancel) + return 0 ; + if(ret == QMessageBox::Ok) + { + if(!RsAccounts::CopyGnuPGKeyrings()) + return 0 ; - initResult = RsInit::InitRetroShare(conf); + initResult = RsInit::InitRetroShare(conf); - displayWarningAboutDSAKeys() ; + displayWarningAboutDSAKeys() ; - } - else - initResult = RS_INIT_OK ; - } + } + else + initResult = RS_INIT_OK ; + } - if (initResult < 0) { - /* Error occured */ - QApplication dummyApp (argc, argv); // needed for QMessageBox - /* Translate into the desired language */ - LanguageSupport::translate(LanguageSupport::defaultLanguageCode()); + if (initResult < 0) { + /* Error occured */ + QApplication dummyApp (argc, argv); // needed for QMessageBox + /* Translate into the desired language */ - displayWarningAboutDSAKeys(); + if(!setLanguage(language)) + return 1; - QMessageBox mb(QMessageBox::Critical, QObject::tr("RetroShare"), "", QMessageBox::Ok); + displayWarningAboutDSAKeys(); + + QMessageBox mb(QMessageBox::Critical, QObject::tr("RetroShare"), "", QMessageBox::Ok); mb.setWindowIcon(FilesDefs::getIconFromQtResourcePath(":/icons/logo_128.png")); - switch (initResult) - { - case RS_INIT_AUTH_FAILED: - std::cerr << "RsInit::InitRetroShare AuthGPG::InitAuth failed" << std::endl; - mb.setText(QObject::tr("Initialization failed. Wrong or missing installation of PGP.")); - break; - default: - /* Unexpected return code */ - std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl; - mb.setText(QObject::tr("An unexpected error occurred. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult)); - break; - } - mb.exec(); - return 1; - } + switch (initResult) + { + case RS_INIT_AUTH_FAILED: + std::cerr << "RsInit::InitRetroShare AuthGPG::InitAuth failed" << std::endl; + mb.setText(QObject::tr("Initialization failed. Wrong or missing installation of PGP.")); + break; + default: + /* Unexpected return code */ + std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl; + mb.setText(QObject::tr("An unexpected error occurred. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult)); + break; + } + mb.exec(); + return 1; + } - /* create global settings object - path maybe wrong, when no profile exist - in this case it can be use only for default values */ - RshareSettings::Create (); + /* create global settings object + path maybe wrong, when no profile exist + in this case it can be use only for default values */ + RshareSettings::Create (); - /* Setup The GUI Stuff */ - Rshare rshare(args, argc, argv, QString::fromUtf8(RsAccounts::ConfigDirectory().c_str())); + if(LanguageSupport::isValidLanguageCode(QString::fromStdString(language))) + conf.language = QString::fromStdString(language); - /* Start RetroShare */ - QString sDefaultGXSIdToCreate = ""; - switch (initResult) { - case RS_INIT_OK: - { - /* Login Dialog */ - /* check for existing Certificate */ - bool genCert = false; - std::list accountIds; - if (RsAccounts::GetAccountIds(accountIds) && (accountIds.size() > 0)) - { - StartDialog sd; - if (sd.exec() == QDialog::Rejected) { - return 1; - } + /* Setup The GUI Stuff */ + //Rshare rshare(args, argc, argv, QString::fromUtf8(RsAccounts::ConfigDirectory().c_str())); + RsApplication rshare(conf); - /* if we're logged in */ - genCert = sd.requestedNewCert(); - } - else - { - genCert = true; - } + if(!setLanguage(language)) + return 1; - if (genCert) - { - GenCertDialog gd(false); + /* Start RetroShare */ + QString sDefaultGXSIdToCreate = ""; + switch (initResult) { + case RS_INIT_OK: + { + /* Login Dialog */ + /* check for existing Certificate */ + bool genCert = false; + std::list accountIds; + if (RsAccounts::GetAccountIds(accountIds) && (accountIds.size() > 0)) + { + StartDialog sd; + if (sd.exec() == QDialog::Rejected) { + return 1; + } - if (gd.exec () == QDialog::Rejected) - return 1; + /* if we're logged in */ + genCert = sd.requestedNewCert(); + } + else + { + genCert = true; + } - sDefaultGXSIdToCreate = gd.getGXSNickname(); - } + if (genCert) + { + GenCertDialog gd(false); - //splashScreen.show(); - } - break; - case RS_INIT_HAVE_ACCOUNT: - { - //splashScreen.show(); - //splashScreen.showMessage(rshare.translate("SplashScreen", "Load profile"), Qt::AlignHCenter | Qt::AlignBottom); + if (gd.exec () == QDialog::Rejected) + return 1; - RsPeerId preferredId; - RsAccounts::GetPreferredAccountId(preferredId); + sDefaultGXSIdToCreate = gd.getGXSNickname(); + } - // true: note auto-login is active - Rshare::loadCertificate(preferredId, true); - } - break; - default: - /* Unexpected return code */ - std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl; - QMessageBox::warning(0, QObject::tr("RetroShare"), QObject::tr("An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult)); - return 1; - } + //splashScreen.show(); + } + break; + case RS_INIT_HAVE_ACCOUNT: + { + //splashScreen.show(); + //splashScreen.showMessage(rshare.translate("SplashScreen", "Load profile"), Qt::AlignHCenter | Qt::AlignBottom); - /* recreate global settings object, now with correct path */ - RshareSettings::Create(true); - Rshare::resetLanguageAndStyle(); + RsPeerId preferredId; + RsAccounts::GetPreferredAccountId(preferredId); - SoundManager::create(); + // true: note auto-login is active + if(!RsApplication::loadCertificate(preferredId, true)) + { + RsErr() << "Retroshare auto-login startup failed." ; + return 1; + } + } + break; + default: + /* Unexpected return code */ + std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl; + QMessageBox::warning(0, QObject::tr("RetroShare"), QObject::tr("An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult)); + return 1; + } + + /* recreate global settings object, now with correct path, specific to the selected node */ + RshareSettings::Create(true); + RsApplication::resetLanguageAndStyle(); + + SoundManager::create(); bool is_hidden_node = false; bool is_auto_tor = false ; @@ -396,214 +580,221 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO); RsAccounts::getCurrentAccountOptions(is_hidden_node,is_auto_tor,is_first_time); if(is_auto_tor) - { - // Now that we know the Tor service running, and we know the SSL id, we can make sure it provides a viable hidden service + { + if(!conf.userSuppliedTorExecutable.empty()) + RsTor::setTorExecutablePath(conf.userSuppliedTorExecutable); - QString tor_hidden_service_dir = QString::fromStdString(RsAccounts::AccountDirectory()) + QString("/hidden_service/") ; + // Now that we know the Tor service running, and we know the SSL id, we can make sure it provides a viable hidden service - Tor::TorManager *torManager = Tor::TorManager::instance(); - torManager->setTorDataDirectory(Rshare::dataDirectory() + QString("/tor/")); - torManager->setHiddenServiceDirectory(tor_hidden_service_dir); // re-set it, because now it's changed to the specific location that is run + std::string tor_hidden_service_dir = RsAccounts::AccountDirectory() + "/hidden_service/" ; - RsDirUtil::checkCreateDirectory(std::string(tor_hidden_service_dir.toUtf8())) ; + RsTor::setTorDataDirectory(RsApplication::dataDirectory().toStdString() + "/tor/"); + RsTor::setHiddenServiceDirectory(tor_hidden_service_dir); // re-set it, because now it's changed to the specific location that is run - torManager->setupHiddenService(); + RsDirUtil::checkCreateDirectory(std::string(tor_hidden_service_dir)) ; - if(! torManager->start() || torManager->hasError()) - { - QMessageBox::critical(NULL,QObject::tr("Cannot start Tor Manager!"),QObject::tr("Tor cannot be started on your system: \n\n")+torManager->errorMessage()) ; - return 1 ; - } + //RsTor::setupHiddenService(); - { - TorControlDialog tcd(torManager) ; - QString error_msg ; - tcd.show(); + if(! RsTor::start() || RsTor::hasError()) + { + QMessageBox::critical(NULL,QObject::tr("Cannot start Tor Manager!"),QObject::tr("Tor cannot be started on your system: \n\n")+QString::fromStdString(RsTor::errorMessage())) ; + return 1 ; + } - while(tcd.checkForTor(error_msg) != TorControlDialog::TOR_STATUS_OK || tcd.checkForHiddenService() != TorControlDialog::HIDDEN_SERVICE_STATUS_OK) // runs until some status is reached: either tor works, or it fails. - { - QCoreApplication::processEvents(); - rstime::rs_usleep(0.2*1000*1000) ; + { + TorControlDialog tcd; + QString error_msg ; + tcd.show(); - if(!error_msg.isNull()) - { - QMessageBox::critical(NULL,QObject::tr("Cannot start Tor"),QObject::tr("Sorry but Tor cannot be started on your system!\n\nThe error reported is:\"")+error_msg+"\"") ; - return 1; - } - } + while(tcd.checkForTor(error_msg) != TorControlDialog::TOR_STATUS_OK || tcd.checkForHiddenService() != TorControlDialog::HIDDEN_SERVICE_STATUS_OK) // runs until some status is reached: either tor works, or it fails. + { + QCoreApplication::processEvents(); + rstime::rs_usleep(0.2*1000*1000) ; - tcd.hide(); + if(!error_msg.isNull()) + { + QMessageBox::critical(NULL,QObject::tr("Cannot start Tor"),QObject::tr("Sorry but Tor cannot be started on your system!\n\nThe error reported is:\"")+error_msg+"\"") ; + return 1; + } + } - if(tcd.checkForHiddenService() != TorControlDialog::HIDDEN_SERVICE_STATUS_OK) - { - QMessageBox::critical(NULL,QObject::tr("Cannot start a hidden tor service!"),QObject::tr("It was not possible to start a hidden service.")) ; - return 1 ; - } - } - } + tcd.hide(); + + if(tcd.checkForHiddenService() != TorControlDialog::HIDDEN_SERVICE_STATUS_OK) + { + QMessageBox::critical(NULL,QObject::tr("Cannot start a hidden tor service!"),QObject::tr("It was not possible to start a hidden service.")) ; + return 1 ; + } + } + } QSplashScreen splashScreen(FilesDefs::getPixmapFromQtResourcePath(":/images/logo/logo_splash.png")/* , Qt::WindowStaysOnTopHint*/); - splashScreen.show(); - splashScreen.showMessage(rshare.translate("SplashScreen", "Load configuration"), Qt::AlignHCenter | Qt::AlignBottom); + splashScreen.show(); + splashScreen.showMessage(rshare.translate("SplashScreen", "Load configuration"), Qt::AlignHCenter | Qt::AlignBottom); - QCoreApplication::processEvents(); + QCoreApplication::processEvents(); - /* stop Retroshare if startup fails */ - if (!RsControl::instance()->StartupRetroShare()) - { - std::cerr << "libretroshare failed to startup!" << std::endl; - return 1; - } + /* stop Retroshare if startup fails */ + if (!RsControl::instance()->StartupRetroShare()) + { + std::cerr << "libretroshare failed to startup!" << std::endl; + return 1; + } if(is_auto_tor) - { - // Tor works with viable hidden service. Let's use it! + { + // Tor works with viable hidden service. Let's use it! - QString service_id ; - QString onion_address ; - uint16_t service_port ; - uint16_t service_target_port ; - uint16_t proxy_server_port ; - QHostAddress service_target_address ; - QHostAddress proxy_server_address ; + std::string service_id ; + std::string onion_address ; + uint16_t service_port ; + uint16_t service_target_port ; + uint16_t proxy_server_port ; + std::string service_target_address ; + std::string proxy_server_address ; - Tor::TorManager *torManager = Tor::TorManager::instance(); - torManager->getHiddenServiceInfo(service_id,onion_address,service_port,service_target_address,service_target_port); - torManager->getProxyServerInfo(proxy_server_address,proxy_server_port) ; + RsTor::getHiddenServiceInfo(service_id,onion_address,service_port,service_target_address,service_target_port); + RsTor::getProxyServerInfo(proxy_server_address,proxy_server_port) ; - std::cerr << "Got hidden service info: " << std::endl; - std::cerr << " onion address : " << onion_address.toStdString() << std::endl; - std::cerr << " service_id : " << service_id.toStdString() << std::endl; - std::cerr << " service port : " << service_port << std::endl; - std::cerr << " target port : " << service_target_port << std::endl; - std::cerr << " target address : " << service_target_address.toString().toStdString() << std::endl; + std::cerr << "Got hidden service info: " << std::endl; + std::cerr << " onion address : " << onion_address << std::endl; + std::cerr << " service_id : " << service_id << std::endl; + std::cerr << " service port : " << service_port << std::endl; + std::cerr << " target port : " << service_target_port << std::endl; + std::cerr << " target address : " << service_target_address << std::endl; - std::cerr << "Setting proxy server to " << service_target_address.toString().toStdString() << ":" << service_target_port << std::endl; + std::cerr << "Setting proxy server to " << service_target_address << ":" << service_target_port << std::endl; - rsPeers->setLocalAddress(rsPeers->getOwnId(), service_target_address.toString().toStdString(), service_target_port); - rsPeers->setHiddenNode(rsPeers->getOwnId(), onion_address.toStdString(), service_port); - rsPeers->setProxyServer(RS_HIDDEN_TYPE_TOR, proxy_server_address.toString().toStdString(),proxy_server_port) ; - } + rsPeers->setLocalAddress(rsPeers->getOwnId(), service_target_address, service_target_port); + rsPeers->setHiddenNode(rsPeers->getOwnId(), onion_address, service_port); + rsPeers->setProxyServer(RS_HIDDEN_TYPE_TOR, proxy_server_address,proxy_server_port) ; + } - Rshare::initPlugins(); + RsApplication::initPlugins(); - splashScreen.showMessage(rshare.translate("SplashScreen", "Create interface"), Qt::AlignHCenter | Qt::AlignBottom); - QCoreApplication::processEvents(); // forces splashscreen to show up + splashScreen.showMessage(rshare.translate("SplashScreen", "Create interface"), Qt::AlignHCenter | Qt::AlignBottom); + QCoreApplication::processEvents(); // forces splashscreen to show up - RsharePeerSettings::Create(); + RsharePeerSettings::Create(); - Emoticons::load(); - AvatarDialog::load(); + Emoticons::load(); + AvatarDialog::load(); - if (Settings->value(QString::fromUtf8("FirstRun"), true).toBool()) { - splashScreen.hide(); + if (Settings->value(QString::fromUtf8("FirstRun"), true).toBool()) { + splashScreen.hide(); - Settings->setValue(QString::fromUtf8("FirstRun"), false); + Settings->setValue(QString::fromUtf8("FirstRun"), false); - SoundManager::initDefault(); + SoundManager::initDefault(); #ifdef __APPLE__ - /* For OSX, we set the default to "cleanlooks", as the AQUA style hides some input boxes - * only on the first run - as the user might want to change it ;) - */ - QString osx_style("cleanlooks"); - Rshare::setStyle(osx_style); - Settings->setInterfaceStyle(osx_style); + /* For OSX, we set the default to "cleanlooks", as the AQUA style hides some input boxes + * only on the first run - as the user might want to change it ;) + */ + QString osx_style("cleanlooks"); + RsApplication::setStyle(osx_style); + Settings->setInterfaceStyle(osx_style); #endif // This is now disabled - as it doesn't add very much. // Need to make sure that defaults are sensible! #ifdef ENABLE_QUICKSTART_WIZARD - QuickStartWizard qstartWizard; - qstartWizard.exec(); + QuickStartWizard qstartWizard; + qstartWizard.exec(); #endif - } + } - MainWindow *w = MainWindow::Create (); - splashScreen.finish(w); + MainWindow *w = MainWindow::Create (); + splashScreen.finish(w); - w->processLastArgs(); + if (!sDefaultGXSIdToCreate.isEmpty()) { + RsIdentityParameters params; + params.nickname = sDefaultGXSIdToCreate.toUtf8().constData(); + params.isPgpLinked = true; + params.mImage.clear(); + uint32_t token = 0; + rsIdentity->createIdentity(token, params); + } + // I'm using a signal to transfer the hashing info to the mainwindow, because Qt schedules signals properly to + // avoid clashes between infos from threads. + // - if (!sDefaultGXSIdToCreate.isEmpty()) { - RsIdentityParameters params; - params.nickname = sDefaultGXSIdToCreate.toUtf8().constData(); - params.isPgpLinked = true; - params.mImage.clear(); - uint32_t token = 0; - rsIdentity->createIdentity(token, params); - } - // I'm using a signal to transfer the hashing info to the mainwindow, because Qt schedules signals properly to - // avoid clashes between infos from threads. - // - - qRegisterMetaType("FileDetail") ; - qRegisterMetaType("RsPeerId") ; - - std::cerr << "connecting signals and slots" << std::endl ; - QObject::connect(notify,SIGNAL(gotTurtleSearchResult(qulonglong,FileDetail)),w->transfersDialog->searchDialog ,SLOT(updateFiles(qulonglong,FileDetail))) ; - QObject::connect(notify,SIGNAL(deferredSignatureHandlingRequested()),notify,SLOT(handleSignatureEvent()),Qt::QueuedConnection) ; - QObject::connect(notify,SIGNAL(chatLobbyTimeShift(int)),notify,SLOT(handleChatLobbyTimeShift(int)),Qt::QueuedConnection) ; - QObject::connect(notify,SIGNAL(diskFull(int,int)) ,w ,SLOT(displayDiskSpaceWarning(int,int))) ; + qRegisterMetaType("RsPeerId") ; +#ifdef DEBUG + std::cerr << "connecting signals and slots" << std::endl ; +#endif + QObject::connect(notify,SIGNAL(deferredSignatureHandlingRequested()),notify,SLOT(handleSignatureEvent()),Qt::QueuedConnection) ; + QObject::connect(notify,SIGNAL(chatLobbyTimeShift(int)),notify,SLOT(handleChatLobbyTimeShift(int)),Qt::QueuedConnection) ; + QObject::connect(notify,SIGNAL(diskFull(int,int)) ,w ,SLOT(displayDiskSpaceWarning(int,int))) ; QObject::connect(notify,SIGNAL(filesPostModChanged(bool)) ,w ,SLOT(postModDirectories(bool)) ,Qt::QueuedConnection ) ; - QObject::connect(notify,SIGNAL(transfersChanged()) ,w->transfersDialog ,SLOT(insertTransfers() )) ; - QObject::connect(notify,SIGNAL(publicChatChanged(int)) ,w->friendsDialog ,SLOT(publicChatChanged(int) )); - QObject::connect(notify,SIGNAL(neighboursChanged()) ,w->friendsDialog->networkDialog ,SLOT(securedUpdateDisplay())) ; + QObject::connect(notify,SIGNAL(transfersChanged()) ,w->transfersDialog ,SLOT(insertTransfers() )) ; + QObject::connect(notify,SIGNAL(publicChatChanged(int)) ,w->friendsDialog ,SLOT(publicChatChanged(int) )); + QObject::connect(notify,SIGNAL(neighboursChanged()) ,w->friendsDialog->networkDialog ,SLOT(securedUpdateDisplay())) ; - QObject::connect(notify,SIGNAL(chatStatusChanged(const QString&,const QString&,bool)),w->friendsDialog,SLOT(updatePeerStatusString(const QString&,const QString&,bool))); - QObject::connect(notify,SIGNAL(ownStatusMessageChanged()),w->friendsDialog,SLOT(loadmypersonalstatus())); + QObject::connect(notify,SIGNAL(chatStatusChanged(const QString&,const QString&,bool)),w->friendsDialog,SLOT(updatePeerStatusString(const QString&,const QString&,bool))); + QObject::connect(notify,SIGNAL(ownStatusMessageChanged()),w->friendsDialog,SLOT(loadmypersonalstatus())); // QObject::connect(notify,SIGNAL(logInfoChanged(const QString&)) ,w->friendsDialog->networkDialog,SLOT(setLogInfo(QString))) ; - QObject::connect(notify,SIGNAL(discInfoChanged()) ,w->friendsDialog->networkView,SLOT(update()),Qt::QueuedConnection) ; - QObject::connect(notify,SIGNAL(errorOccurred(int,int,const QString&)),w,SLOT(displayErrorMessage(int,int,const QString&))) ; + QObject::connect(notify,SIGNAL(discInfoChanged()) ,w->friendsDialog->networkView,SLOT(update()),Qt::QueuedConnection) ; + QObject::connect(notify,SIGNAL(errorOccurred(int,int,const QString&)),w,SLOT(displayErrorMessage(int,int,const QString&))) ; - w->installGroupChatNotifier(); + w->installGroupChatNotifier(); - /* only show window, if not startMinimized */ - if (RsInit::getStartMinimised() || Settings->getStartMinimized()) - { - splashScreen.close(); - } else { - w->show(); - } + /* only show window, if not startMinimized */ + if (RsInit::getStartMinimised() || Settings->getStartMinimized()) + { + splashScreen.close(); + } else { + w->show(); + } - /* Startup a Timer to keep the gui's updated */ - QTimer *timer = new QTimer(w); - timer -> connect(timer, SIGNAL(timeout()), notify, SLOT(UpdateGUI())); - timer->start(1000); + /* Startup a Timer to keep the gui's updated */ + QTimer *timer = new QTimer(w); + timer -> connect(timer, SIGNAL(timeout()), notify, SLOT(UpdateGUI())); + timer->start(1000); - notify->enable() ; // enable notification system after GUI creation, to avoid data races in Qt. + notify->enable() ; // enable notification system after GUI creation, to avoid data races in Qt. + + // Read webui params in settings. We cannot save them to some webui.cfg because cfg needs the node id and + // jsonapi is started before node ID selection in retroshare-service. #ifdef RS_JSONAPI - JsonApiPage::checkStartJsonApi(); - #ifdef RS_WEBUI - WebuiPage::checkStartWebui(); // normally we should rather save the UI flags internally to p3webui -#endif -#endif // RS_JSONAPI + conf.enableWebUI = Settings->getWebinterfaceEnabled(); - /* dive into the endless loop */ - int ti = rshare.exec(); - delete w ; + if(!Settings->getWebinterfaceFilesDirectory().isNull()) + rsWebUi->setHtmlFilesDirectory(Settings->getWebinterfaceFilesDirectory().toStdString()); +#endif + RsInit::startupWebServices(conf,false); +#endif + + /* dive into the endless loop */ + int ti = rshare.exec(); + delete w ; #ifdef RS_JSONAPI - JsonApiPage::checkShutdownJsonApi(); + JsonApiPage::checkShutdownJsonApi(); #endif // RS_JSONAPI - /* cleanup */ - ChatDialog::cleanupChat(); + /* cleanup */ + ChatDialog::cleanupChat(); #ifdef RS_ENABLE_GXS - RsGxsUpdateBroadcast::cleanup(); + RsGxsUpdateBroadcast::cleanup(); #endif - RsControl::instance()->rsGlobalShutDown(); + if (is_auto_tor) { + RsTor::stop(); + } - delete(soundManager); - soundManager = NULL; + RsControl::instance()->rsGlobalShutDown(); - Settings->sync(); - delete(Settings); + delete(soundManager); + soundManager = NULL; - return ti ; + Settings->sync(); + delete(Settings); + + return ti ; } diff --git a/retroshare-gui/src/qss/blacknight/check_sel.png b/retroshare-gui/src/qss/blacknight/check_sel.png deleted file mode 100644 index 300de11ee..000000000 Binary files a/retroshare-gui/src/qss/blacknight/check_sel.png and /dev/null differ diff --git a/retroshare-gui/src/qss/blacknight/check_unsel.png b/retroshare-gui/src/qss/blacknight/check_unsel.png deleted file mode 100644 index 50ca1d0a5..000000000 Binary files a/retroshare-gui/src/qss/blacknight/check_unsel.png and /dev/null differ diff --git a/retroshare-gui/src/qss/blacknight/clbg.png b/retroshare-gui/src/qss/blacknight/clbg.png deleted file mode 100644 index 45ce37337..000000000 Binary files a/retroshare-gui/src/qss/blacknight/clbg.png and /dev/null differ diff --git a/retroshare-gui/src/qss/blacknight/down.png b/retroshare-gui/src/qss/blacknight/down.png deleted file mode 100644 index ce161569b..000000000 Binary files a/retroshare-gui/src/qss/blacknight/down.png and /dev/null differ diff --git a/retroshare-gui/src/qss/blacknight/radio_sel.png b/retroshare-gui/src/qss/blacknight/radio_sel.png deleted file mode 100644 index 1239b6dc8..000000000 Binary files a/retroshare-gui/src/qss/blacknight/radio_sel.png and /dev/null differ diff --git a/retroshare-gui/src/qss/blacknight/radio_unsel.png b/retroshare-gui/src/qss/blacknight/radio_unsel.png deleted file mode 100644 index 4c895c9da..000000000 Binary files a/retroshare-gui/src/qss/blacknight/radio_unsel.png and /dev/null differ diff --git a/retroshare-gui/src/qss/blacknight/up.png b/retroshare-gui/src/qss/blacknight/up.png deleted file mode 100644 index 38d747789..000000000 Binary files a/retroshare-gui/src/qss/blacknight/up.png and /dev/null differ diff --git a/retroshare-gui/src/qss/blue.qss b/retroshare-gui/src/qss/blue.qss deleted file mode 100644 index 894196f68..000000000 --- a/retroshare-gui/src/qss/blue.qss +++ /dev/null @@ -1,199 +0,0 @@ -.QWidget { - background-color: #c4dafa; - border-color: transparent; -} - -QFrame#titleBarFrame, QFrame#toolBarFrame { - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #E3EFFF, stop: 1 #87ADE4); - border: 1px solid #87ADE4; -} - -FriendsDialog QFrame#headFrame { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #E3EFFF, stop: 1 #87ADE4); - border: 1px solid #87ADE4; - border: 1px; - border-radius: 4px; -} - -HeaderFrame { - background-image: url(:/images/headerFrame.png); - border: 0px; -} - -QDialog{ - background-color: #c4dafa; - -} - -QWidget#chatcentralwidget{ - background-color: #c4dafa; - -} - -QToolBar#chattoolBar{ - border-image: url(%THISPATH%/blue/blue.png); - - -} - - -/* Customize the toolbar. */ -QToolBar#toolBarPage { - border-image: url(%THISPATH%/blue/blue.png); - -} - -QToolBar#toolBarAction { - border-image: url(%THISPATH%/blue/blue.png); - -} - -QTabBar::tab { - border-image: url(%THISPATH%/blue/tab1.png); - min-width: 8ex; - padding: 4px; - - -} - -QTabBar::tab:!selected { - margin-top: 2px; /* make non-selected tabs look smaller */ - -} - -QTabBar::tab:selected, QTabBar::tab:hover { - - border-image: url(%THISPATH%/blue/tab_hover.png); - - -} - -QTabBar::tab:selected { - border-image: url(%THISPATH%/blue/tabselected.png); -} - -QPushButton#okButton { - min-height: 27px; - min-width: 77px; -} - -QPushButton#cancelprefButton { - min-height: 27px; - min-width: 77px; -} - -QPushButton#cancelButton { - min-height: 25px; - max-height: 25px; - min-width: 75px; -} - - -QPushButton#applyButton { - - min-height: 25px; - max-height: 25px; - min-width: 75px; -} - - - -QMenu::item:selected { /* when user selects item using mouse or keyboard */ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #E3EFFF, stop: 1 #87ADE4); -} - -QListWidget::item:selected { /* when user selects item using mouse or keyboard */ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #E3EFFF, stop: 1 #87ADE4); -} - -QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #E3EFFF, stop: 1 #87ADE4); -} - -QStatusBar{ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #E3EFFF, stop: 1 #87ADE4); -} - - -QFrame#messengerframetop{ - - border-image: url(%THISPATH%/blue/blue.png); - -} - -QFrame#Chatbuttonframe{ - - border-image: url(%THISPATH%/blue/blue.png); - -} - -QLabel#subjectText{ - font: bold 12px; - -} - -QLabel#subjectlabel{ - font: bold 12px; - -} - -QLabel#fromlabel{ - font: bold 12px; - -} - -QLabel#datelabel{ - font: bold 12px; - -} - -QLabel#tolabel{ - font: bold 12px; - -} - -QLabel#fromText{ - font: bold ; - color: blue; - -} -QSplitter#splitter{ - border-image: url(%THISPATH%/blue/blue.png); - -} - -HomePage QToolButton#addButton { - font: bold; - font-size: 15pt; - color: white; - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E3EFFF, stop: 1 #87ADE4); - border: 1px solid #87ADE4; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -HomePage QToolButton#addButton:hover { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e3e5ff, stop: 1 #879ae4); - border: 1px solid #879ae4; - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - -MainWindow QListWidget { - font-size: 12pt; -} - diff --git a/retroshare-gui/src/qss/blue/blue.png b/retroshare-gui/src/qss/blue/blue.png deleted file mode 100644 index 28a723edd..000000000 Binary files a/retroshare-gui/src/qss/blue/blue.png and /dev/null differ diff --git a/retroshare-gui/src/qss/blue/blue2.png b/retroshare-gui/src/qss/blue/blue2.png deleted file mode 100644 index 7671a1649..000000000 Binary files a/retroshare-gui/src/qss/blue/blue2.png and /dev/null differ diff --git a/retroshare-gui/src/qss/blue/tab1.png b/retroshare-gui/src/qss/blue/tab1.png deleted file mode 100644 index 68d6960b4..000000000 Binary files a/retroshare-gui/src/qss/blue/tab1.png and /dev/null differ diff --git a/retroshare-gui/src/qss/blue/tab_hover.png b/retroshare-gui/src/qss/blue/tab_hover.png deleted file mode 100644 index 1a5fc3ef4..000000000 Binary files a/retroshare-gui/src/qss/blue/tab_hover.png and /dev/null differ diff --git a/retroshare-gui/src/qss/blue/tabselected.png b/retroshare-gui/src/qss/blue/tabselected.png deleted file mode 100644 index 78a819cb8..000000000 Binary files a/retroshare-gui/src/qss/blue/tabselected.png and /dev/null differ diff --git a/retroshare-gui/src/qss/groove.qss b/retroshare-gui/src/qss/groove.qss deleted file mode 100644 index 51f8d8c4b..000000000 --- a/retroshare-gui/src/qss/groove.qss +++ /dev/null @@ -1,94 +0,0 @@ -.QWidget{ - - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #6799B3, stop: 1 #377a90); -} - -QFrame#titleBarFrame, QFrame#toolBarFrame { - - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #6799B3, stop: 0.3 #377a90, - stop: 0.31 #0e5e73, stop: 1 #4b8598); - - border: 1px solid #4b8598; -} - -HeaderFrame { - -} - -QDialog{ - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #6799B3, stop: 1 #377a90); - -} - -QWidget#chatcentralwidget{ - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #6799B3, stop: 1 #377a90); - - -} - -QToolBar#chattoolBar{ - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #6799B3, stop: 0.3 #377a90, - stop: 0.31 #0e5e73, stop: 1 #4b8598); - - border: 1px solid #4b8598; -} - -QFrame#Chatbuttonframe{ - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #6799B3, stop: 0.3 #377a90, - stop: 0.31 #0e5e73, stop: 1 #4b8598); - - border: 1px solid #4b8598; -} - -QStatusBar{ - - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #6799B3, stop: 1 #377a90); - -} - -/* Customize the toolbar. */ -QToolBar { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #6799B3, stop: 0.3 #377a90, - stop: 0.31 #0e5e73, stop: 1 #4b8598); - - border: 1px solid #4b8598; -} - -QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #6799B3, stop: 0.3 #377a90, - stop: 0.31 #0e5e73, stop: 1 #4b8598); - -} - -HomePage QToolButton#addButton { - font: bold; - font-size: 15pt; - color: white; - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #6799B3, stop: 0.3 #377a90, - stop: 0.31 #0e5e73, stop: 1 #4b8598); - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -HomePage QToolButton#addButton:hover { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #719cb2, stop: 0.3 #5e9bab, - stop: 0.31 #0e5e69, stop: 1 #4b9897); - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - -MainWindow QListWidget { - font-size: 12pt; -} - - diff --git a/retroshare-gui/src/qss/orangesurfer.qss b/retroshare-gui/src/qss/orangesurfer.qss deleted file mode 100644 index a3c7c6174..000000000 --- a/retroshare-gui/src/qss/orangesurfer.qss +++ /dev/null @@ -1,231 +0,0 @@ -.QWidget { - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07); - -} - -QFrame#titleBarFrame, QFrame#toolBarFrame { - - border-image: url(%THISPATH%/orangesurfer/main.png); -} - -HeaderFrame { - background-image: url(:/images/headerFrame.png); - border: 0px; -} - -QDialog, QMainWindow{ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07); -} - -QWidget#chatcentralwidget{ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07); - -} - -QToolBar#chattoolBar{ - border-image: url(%THISPATH%/orangesurfer/main.png); - - -} - -/* Customize the toolbar. */ -QToolBar#toolBarPage { - border-image: url(%THISPATH%/orangesurfer/main.png); - -} - -QToolBar#toolBarAction { - border-image: url(%THISPATH%/orangesurfer/main.png); - -} - - -QTabBar::tab { - border-image: url(%THISPATH%/orangesurfer/tab_normal.png); - border-top-left-radius: 4px; - border-top-right-radius: 4px; - min-width: 8ex; - padding: 4px; - - -} - -QTabBar::tab:!selected { - margin-top: 2px; /* make non-selected tabs look smaller */ - -} - -QTabBar::tab:selected, QTabBar::tab:hover { - - border-image: url(%THISPATH%/orangesurfer/tab_hover.png); - - -} - -QTabBar::tab:selected { - border-image: url(%THISPATH%/orangesurfer/tab_pressed.png); -} - - -QPushButton#okButton { - min-height: 27px; - min-width: 77px; -} - -QPushButton#cancelprefButton { - min-height: 27px; - min-width: 77px; -} - -QPushButton#cancelButton { - min-height: 25px; - max-height: 25px; - min-width: 75px; -} - - -QPushButton#applyButton { - - min-height: 25px; - max-height: 25px; - min-width: 75px; -} - - - -QStatusBar{ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #67768D, stop: 0.4 #EDEEFD); - -} - -QSizeGrip { - image: url(%THISPATH%/orangesurfer/sizegrip.png); - width: 16px; - height: 16px; -} - -QMenu { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #67768D, stop: 0.4 #EDEEFD); - border: 1px solid black; -} - -QMenu::item:selected { /* when user selects item using mouse or keyboard */ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07); -} - -QListWidget::item:selected { /* when user selects item using mouse or keyboard */ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07); -} - - -QTreeWidget { /* when user selects item using mouse or keyboard */ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07); - - -} -QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ - - - - border-image: url(%THISPATH%/orangesurfer/border.png); - -} - -QTreeView { /* when user selects item using mouse or keyboard */ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07); - - -} - -QTreeView::item:selected { /* when user selects item using mouse or keyboard */ - - /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07);*/ - - border-image: url(%THISPATH%/orangesurfer/border.png); - -} - -QFrame#messengerframetop{ - - border-image: url(%THISPATH%/orangesurfer/main.png); - - /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07);*/ -} - -QFrame#Chatbuttonframe{ - - border-image: url(%THISPATH%/orangesurfer/main.png); - -} - -QLabel#subjectText{ - font: bold 12px; - -} - -QLabel#subjectlabel{ - font: bold 12px; - -} - -QLabel#fromlabel{ - font: bold 12px; - -} - -QLabel#datelabel{ - font: bold 12px; - -} - -QLabel#tolabel{ - font: bold 12px; - -} - -QLabel#fromText{ - font: bold ; - color: blue; - -} - -HomePage QToolButton#addButton { - font: bold; - font-size: 15pt; - color: white; - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #F7B552, stop: 1 #FF5E07); - border: 1px solid #FF5E07; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -HomePage QToolButton#addButton:hover { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #fac26e, stop: 1 #f87d3b); - border: 1px solid #f87d3b; - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - -MainWindow QListWidget { - font-size: 12pt; -} diff --git a/retroshare-gui/src/qss/orangesurfer/border.png b/retroshare-gui/src/qss/orangesurfer/border.png deleted file mode 100644 index e8bd39f07..000000000 Binary files a/retroshare-gui/src/qss/orangesurfer/border.png and /dev/null differ diff --git a/retroshare-gui/src/qss/orangesurfer/main.png b/retroshare-gui/src/qss/orangesurfer/main.png deleted file mode 100644 index 2605e0d4d..000000000 Binary files a/retroshare-gui/src/qss/orangesurfer/main.png and /dev/null differ diff --git a/retroshare-gui/src/qss/orangesurfer/main2.png b/retroshare-gui/src/qss/orangesurfer/main2.png deleted file mode 100644 index e977b4812..000000000 Binary files a/retroshare-gui/src/qss/orangesurfer/main2.png and /dev/null differ diff --git a/retroshare-gui/src/qss/orangesurfer/sizegrip.png b/retroshare-gui/src/qss/orangesurfer/sizegrip.png deleted file mode 100644 index be6cd102c..000000000 Binary files a/retroshare-gui/src/qss/orangesurfer/sizegrip.png and /dev/null differ diff --git a/retroshare-gui/src/qss/orangesurfer/tab_hover.png b/retroshare-gui/src/qss/orangesurfer/tab_hover.png deleted file mode 100644 index 1a5fc3ef4..000000000 Binary files a/retroshare-gui/src/qss/orangesurfer/tab_hover.png and /dev/null differ diff --git a/retroshare-gui/src/qss/orangesurfer/tab_normal.png b/retroshare-gui/src/qss/orangesurfer/tab_normal.png deleted file mode 100644 index f3a4b4694..000000000 Binary files a/retroshare-gui/src/qss/orangesurfer/tab_normal.png and /dev/null differ diff --git a/retroshare-gui/src/qss/orangesurfer/tab_pressed.png b/retroshare-gui/src/qss/orangesurfer/tab_pressed.png deleted file mode 100644 index eeae9b138..000000000 Binary files a/retroshare-gui/src/qss/orangesurfer/tab_pressed.png and /dev/null differ diff --git a/retroshare-gui/src/qss/orangesurfer/toolbar.png b/retroshare-gui/src/qss/orangesurfer/toolbar.png deleted file mode 100644 index 2aae1f8ff..000000000 Binary files a/retroshare-gui/src/qss/orangesurfer/toolbar.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle-v2.qss b/retroshare-gui/src/qss/qdarkstyle-v2.qss deleted file mode 100644 index a98b1e08f..000000000 --- a/retroshare-gui/src/qss/qdarkstyle-v2.qss +++ /dev/null @@ -1,2329 +0,0 @@ -/* QDarkStyleSheet -------------------------------------------------------- - -This is the main style sheet, the palette has nine main colors. -It is based on three selecting colors, three greyish (background) colors -plus three whitish (foreground) colors. Each set of widgets of the same -type have a header like this: - - ------------------ - GroupName -------- - ------------------ - -And each widget is separated with a header like this: - - QWidgetName ------ - -This makes more easy to find and change some css field. The basic -configuration is described bellow. - - SELECTION ------------ - - sel_light #179AE0 #148CD2 (selection/hover/active) - sel_normal #3375A3 #1464A0 (selected) - sel_dark #18465D #14506E (selected disabled) - - FOREGROUND ----------- - - for_light #EFF0F1 #F0F0F0 (texts/labels) - for_normal #AAAAAA (not used yet) - for_dark #505F69 #787878 (disabled texts) - - BACKGROUND ----------- - - bac_light #4D545B #505F69 (unpressed) - bac_normal #31363B #32414B (border, disabled, pressed, checked, toolbars, menus) - bac_dark #232629 #19232D (background) - -If a stranger configuration is required because of a bugfix or anything -else, keep the comment on that line to nobodys changed it, including the -issue number. ---------------------------------------------------------------------------- */ - - - -/* QWidget ---------------------------------------------------------------- */ - -QWidget { - background-color: #19232D; - border: 0px solid #32414B; - padding: 0px; - color: #F0F0F0; - selection-background-color: #1464A0; - selection-color: #F0F0F0; -} -QTreeView::item, QTreeWidget::item, QListWidget::item{ - color: #F0F0F0; -} - -QWidget:disabled { - background-color: #19232D; - color: #787878; - selection-background-color: #14506E; - selection-color: #787878; -} - -QWidget:item:selected { - background-color: #1464A0; -} - -QWidget:item:hover { - background-color: #148CD2; - color: #32414B; -} - -/* QMainWindow ------------------------------------------------------------ */ -/* This adjusts the splitter in the dock widget, not qsplitter */ - - -QMainWindow::separator { - background-color: #32414B; - border: 0 solid #19232D; - spacing: 0; - padding: 2px; -} - -QMainWindow::separator:hover { - background-color: #505F69; - border: 0px solid #148CD2; -} - -QMainWindow::separator:horizontal { - width: 5px; - margin-top: 2px; - margin-bottom: 2px; - image: url(%THISPATH%/qdarkstyle/rc/Vsepartoolbar.png); -} - -QMainWindow::separator:vertical { - height: 5px; - margin-left: 2px; - margin-right: 2px; - image: url(%THISPATH%/qdarkstyle/rc/Hsepartoolbar.png); -} - -/* QToolTip --------------------------------------------------------------- */ - -QToolTip { - background-color: #148CD2; - border: 1px solid #19232D; - color: #19232D; - padding: 0; /*remove padding, for fix combo box tooltip*/ - opacity: 230; /*reducing transparency to read better*/ -} - -/* QStatusBar ------------------------------------------------------------- */ - -QStatusBar { - border: 1px solid #32414B; - background: #32414B; /*fixes spyder #9120,#9121*/ -} - -QStatusBar QToolTip { - background-color: #148CD2; - border: 1px solid #19232D; - color: #19232D; - padding: 0; /*remove padding, for fix combo box tooltip*/ - opacity: 230; /*reducing transparency to read better*/ -} - -QStatusBar QLabel { - background-color: transparent; /*fixes spyder #9120,#9121*/ -} - -/* QCheckBox -------------------------------------------------------------- */ - -QCheckBox { - background-color: #19232D; - color: #F0F0F0; - spacing: 4px; - outline: none; - padding-top: 4px; - padding-bottom: 4px; -} - -QCheckBox:focus { - border: none; -} - -QCheckBox QWidget:disabled { - background-color: #19232D; - color: #787878; -} - -QCheckBox::indicator { - margin-left: 4px; - width: 16px; - height: 16px; -} - -QCheckBox::indicator:unchecked { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_unchecked.png); -} - -QCheckBox::indicator:unchecked:hover, -QCheckBox::indicator:unchecked:focus, -QCheckBox::indicator:unchecked:pressed { - border: none; - image: url(%THISPATH%/qdarkstyle/rc/checkbox_unchecked_focus.png); -} - -QCheckBox::indicator:unchecked:disabled { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_unchecked_disabled.png); -} - -QCheckBox::indicator:checked { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_checked.png); -} - -QCheckBox::indicator:checked:hover, -QCheckBox::indicator:checked:focus, -QCheckBox::indicator:checked:pressed { - border: none; - image: url(%THISPATH%/qdarkstyle/rc/checkbox_checked_focus.png); -} - -QCheckBox::indicator:checked:disabled{ - image: url(%THISPATH%/qdarkstyle/rc/checkbox_checked_disabled.png); -} - -QCheckBox::indicator:indeterminate { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_indeterminate.png); -} - -QCheckBox::indicator:indeterminate:disabled { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_indeterminate_disabled.png); -} - -QCheckBox::indicator:indeterminate:focus, -QCheckBox::indicator:indeterminate:hover, -QCheckBox::indicator:indeterminate:pressed { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_indeterminate_focus.png); -} - -/* QGroupBox -------------------------------------------------------------- */ - -QGroupBox { - font-weight: bold; - border: 1px solid #32414B; - border-radius: 4px; - padding: 4px; - margin-top: 16px; -} - - - -QGroupBox::title { - subcontrol-origin: margin; - subcontrol-position: top left; - left: 3px; - padding-left: 3px; - padding-right: 5px; - padding-top: 8px; - padding-bottom: 16px; -} - -QGroupBox::indicator { - margin-left: 4px; - width: 16px; - height: 16px; -} - -QGroupBox::indicator { - margin-left: 2px; -} - -QGroupBox::indicator:unchecked:hover, -QGroupBox::indicator:unchecked:focus, -QGroupBox::indicator:unchecked:pressed { - border: none; - image: url(%THISPATH%/qdarkstyle/rc/checkbox_unchecked_focus.png); -} - -QGroupBox::indicator:checked:hover, -QGroupBox::indicator:checked:focus, -QGroupBox::indicator:checked:pressed { - border: none; - image: url(%THISPATH%/qdarkstyle/rc/checkbox_checked_focus.png); -} - -QGroupBox::indicator:checked:disabled { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_checked_disabled.png); -} - -QGroupBox::indicator:unchecked:disabled { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_unchecked_disabled.png); -} - -/* QRadioButton ----------------------------------------------------------- */ - -QRadioButton { - background-color: #19232D; - color: #F0F0F0; - spacing: 0; - padding: 0; - border: none; - outline: none; -} - -QRadioButton:focus { - border: none; -} - -QRadioButton:disabled { - background-color: #19232D; - color: #787878; - border: none; - outline: none; -} - -QRadioButton QWidget { - background-color: #19232D; - color: #F0F0F0; - spacing: 0px; - padding: 0px; - outline: none; - border: none; -} - -QRadioButton::indicator { - border: none; - outline: none; - margin-bottom: 2px; - width: 25px; - height: 25px; -} - -QRadioButton::indicator:unchecked { - image: url(%THISPATH%/qdarkstyle/rc/radio_unchecked.png); -} - -QRadioButton::indicator:unchecked:hover, -QRadioButton::indicator:unchecked:focus, -QRadioButton::indicator:unchecked:pressed { - border: none; - outline: none; - image: url(%THISPATH%/qdarkstyle/rc/radio_unchecked_focus.png); -} - -QRadioButton::indicator:checked { - border: none; - outline: none; - image: url(%THISPATH%/qdarkstyle/rc/radio_checked.png); -} - -QRadioButton::indicator:checked:hover, -QRadioButton::indicator:checked:focus, -QRadioButton::indicator:checked:pressed { - border: none; - outline: none; - image: url(%THISPATH%/qdarkstyle/rc/radio_checked_focus.png); -} - -QRadioButton::indicator:checked:disabled { - outline: none; - image: url(%THISPATH%/qdarkstyle/rc/radio_checked_disabled.png); -} - -QRadioButton::indicator:unchecked:disabled { - image: url(%THISPATH%/qdarkstyle/rc/radio_unchecked_disabled.png); -} - -/* QMenuBar --------------------------------------------------------------- */ - -QMenuBar { - background-color: #32414B; - padding: 2px; - border: 1px solid #19232D; - color: #F0F0F0; -} - -QMenuBar:focus { - border: 1px solid #148CD2; -} - -QMenuBar::item { - background: transparent; - padding: 4px; -} - -QMenuBar::item:selected { - padding: 4px; - background: transparent; - border: 0px solid #32414B; -} - -QMenuBar::item:pressed { - padding: 4px; - border: 0px solid #32414B; - background-color: #148CD2; - color: #F0F0F0; - margin-bottom: 0px; - padding-bottom: 0px; -} - -/* QMenu ------------------------------------------------------------------ */ - -QMenu { - border: 0px solid #32414B; - color: #F0F0F0; - margin: 0px; -} - -QMenu::separator { - height: 2px; - background-color: #505F69; - color: #F0F0F0; - padding-left: 4px; - margin-left: 2px; - margin-right: 2px; -} - -QMenu::icon { - margin: 0px; - padding-left:4px; -} - -QMenu::item { - padding: 4px 24px 4px 24px; - border: 1px transparent #32414B; /* reserve space for selection border */ -} - -QMenu::item:selected { - color: #F0F0F0; -} - - - -QMenu::indicator { - width: 12px; - height: 12px; - padding-left:6px; -} - -/* non-exclusive indicator = check box style indicator (see QActionGroup::setExclusive) */ - -QMenu::indicator:non-exclusive:unchecked { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_unchecked.png); -} - -QMenu::indicator:non-exclusive:unchecked:selected { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_unchecked_disabled.png); -} - -QMenu::indicator:non-exclusive:checked { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_checked.png); -} - -QMenu::indicator:non-exclusive:checked:selected { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_checked_disabled.png); -} - -/* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */ - -QMenu::indicator:exclusive:unchecked { - image: url(%THISPATH%/qdarkstyle/rc/radio_unchecked.png); -} - -QMenu::indicator:exclusive:unchecked:selected { - image: url(%THISPATH%/qdarkstyle/rc/radio_unchecked_disabled.png); -} - -QMenu::indicator:exclusive:checked { - image: url(%THISPATH%/qdarkstyle/rc/radio_checked.png); -} - -QMenu::indicator:exclusive:checked:selected { - image: url(%THISPATH%/qdarkstyle/rc/radio_checked_disabled.png); -} - -QMenu::right-arrow { - margin: 5px; - image: url(%THISPATH%/qdarkstyle/rc/right_arrow.png) -} - -/* QAbstractItemView ------------------------------------------------------ */ - -QAbstractItemView { - alternate-background-color: #19232D; - color: #F0F0F0; - border: 1px solid #32414B; - border-radius: 4px; -} - -QAbstractItemView QLineEdit { - padding: 2px; -} - -/* QAbstractScrollArea ---------------------------------------------------- */ - -QAbstractScrollArea { - background-color: #19232D; - border: 1px solid #32414B; - border-radius: 4px; - padding: 4px; - color: #F0F0F0; -} - -QAbstractScrollArea:disabled { - color: #787878; -} - -/* QScrollArea ------------------------------------------------------------ */ - -QScrollArea QWidget QWidget:disabled { - background-color: #19232D; -} - -/* QScrollBar ------------------------------------------------------------- */ - -QScrollBar:horizontal { - height: 16px; - margin: 2px 16px 2px 16px; - border: 1px solid #32414B; - border-radius: 4px; - background-color: #19232D; -} - -QScrollBar::handle:horizontal { - background-color: #787878; - border: 1px solid #32414B; - border-radius: 4px; - min-width: 8px; - -} - -QScrollBar::handle:horizontal:hover { - background-color: #148CD2; - border: 1px solid #148CD2; - border-radius: 4px; - min-width: 8px; -} - -QScrollBar::add-line:horizontal { - margin: 0px 0px 0px 0px; - border-image: url(%THISPATH%/qdarkstyle/rc/right_arrow_disabled.png); - width: 10px; - height: 10px; - subcontrol-position: right; - subcontrol-origin: margin; -} - -QScrollBar::sub-line:horizontal { - margin: 0px 3px 0px 3px; - border-image: url(%THISPATH%/qdarkstyle/rc/left_arrow_disabled.png); - height: 10px; - width: 10px; - subcontrol-position: left; - subcontrol-origin: margin; -} - -QScrollBar::add-line:horizontal:hover, -QScrollBar::add-line:horizontal:on { - border-image: url(%THISPATH%/qdarkstyle/rc/right_arrow.png); - height: 10px; - width: 10px; - subcontrol-position: right; - subcontrol-origin: margin; -} - -QScrollBar::sub-line:horizontal:hover, -QScrollBar::sub-line:horizontal:on { - border-image: url(%THISPATH%/qdarkstyle/rc/left_arrow.png); - height: 10px; - width: 10px; - subcontrol-position: left; - subcontrol-origin: margin; -} - -QScrollBar::up-arrow:horizontal, -QScrollBar::down-arrow:horizontal { - background: none; -} - -QScrollBar::add-page:horizontal, -QScrollBar::sub-page:horizontal { - background: none; -} - -QScrollBar:vertical { - background-color: #19232D; - width: 16px; - margin: 16px 2px 16px 2px; - border: 1px solid #32414B; - border-radius: 4px; -} - -QScrollBar::handle:vertical { - background-color: #787878; - border: 1px solid #32414B; - min-height: 8px; - border-radius: 4px; -} - -QScrollBar::handle:vertical:hover { - background-color: #148CD2; - border: 1px solid #148CD2; - border-radius: 4px; - min-height: 8px; - -} - -QScrollBar::sub-line:vertical { - margin: 3px 0px 3px 0px; - border-image: url(%THISPATH%/qdarkstyle/rc/up_arrow_disabled.png); - height: 10px; - width: 10px; - subcontrol-position: top; - subcontrol-origin: margin; -} - -QScrollBar::add-line:vertical { - margin: 3px 0px 3px 0px; - border-image: url(%THISPATH%/qdarkstyle/rc/down_arrow_disabled.png); - height: 10px; - width: 10px; - subcontrol-position: bottom; - subcontrol-origin: margin; -} - -QScrollBar::sub-line:vertical:hover, -QScrollBar::sub-line:vertical:on { - border-image: url(%THISPATH%/qdarkstyle/rc/up_arrow.png); - height: 10px; - width: 10px; - subcontrol-position: top; - subcontrol-origin: margin; -} - -QScrollBar::add-line:vertical:hover, -QScrollBar::add-line:vertical:on { - border-image: url(%THISPATH%/qdarkstyle/rc/down_arrow.png); - height: 10px; - width: 10px; - subcontrol-position: bottom; - subcontrol-origin: margin; -} - -QScrollBar::up-arrow:vertical, -QScrollBar::down-arrow:vertical { - background: none; -} - -QScrollBar::add-page:vertical, -QScrollBar::sub-page:vertical { - background: none; -} - -/* QTextEdit--------------------------------------------------------------- */ - -QTextEdit { - background-color: #19232D; - color: #F0F0F0; - border: 1px solid #32414B; -} - -QTextEdit:hover { - border: 1px solid #148CD2; - color: #F0F0F0; -} - -QTextEdit:selected { - background: #1464A0; - color: #32414B; -} - -/* QPlainTextEdit --------------------------------------------------------- */ - -QPlainTextEdit { - background-color: #19232D; - color: #F0F0F0; - border-radius: 4px; - border: 1px solid #32414B; -} - -QPlainTextEdit:hover { - border: 1px solid #148CD2; - color: #F0F0F0; -} - -QPlainTextEdit:selected { - background: #1464A0; - color: #32414B; -} - -/* QSizeGrip --------------------------------------------------------------- */ - -QSizeGrip { - image: url(%THISPATH%/qdarkstyle/rc/sizegrip.png); - width: 12px; - height: 12px; -} - -/* QStackedWidget --------------------------------------------------------- */ - -QStackedWidget { - padding: 4px; - border: 1px solid #32414B; - border: 1px solid #19232D; -} - -/* QToolBar --------------------------------------------------------------- */ - -QToolBar { - background-color: #32414B; - border-bottom: 1px solid #19232D; - padding: 2px; - font-weight: bold; -} - -QToolBar QToolButton{ - background-color: #32414B; -} - -QToolBar::handle:horizontal { - width: 6px; - image: url(%THISPATH%/qdarkstyle/rc/Hmovetoolbar.png); -} - -QToolBar::handle:vertical { - height: 6px; - image: url(%THISPATH%/qdarkstyle/rc/Vmovetoolbar.png); -} - -QToolBar::separator:horizontal { - width: 3px; - image: url(%THISPATH%/qdarkstyle/rc/Hsepartoolbar.png); -} - -QToolBar::separator:vertical { - height: 3px; - image: url(%THISPATH%/qdarkstyle/rc/Vsepartoolbar.png); -} - -QToolButton#qt_toolbar_ext_button { - background: #32414B; - border: 0px; - color: #F0F0F0; - image: url(%THISPATH%/qdarkstyle/rc/right_arrow.png); -} - -/* QAbstractSpinBox ------------------------------------------------------- */ - -QAbstractSpinBox { - background-color: #19232D; - border: 1px solid #32414B; - color: #F0F0F0; - padding-top: 2px; /* This fix 103, 111*/ - padding-bottom: 2px; /* This fix 103, 111*/ - padding-left: 4px; - padding-right: 4px; - border-radius: 4px; - /* min-width: 5px; removed to fix 109 */ -} - -QAbstractSpinBox:up-button { - background-color: transparent #19232D; - subcontrol-origin: border; - subcontrol-position: top right; - border-left: 1px solid #32414B; - margin: 1px; -} - -QAbstractSpinBox::up-arrow, -QAbstractSpinBox::up-arrow:disabled, -QAbstractSpinBox::up-arrow:off { - image: url(%THISPATH%/qdarkstyle/rc/up_arrow_disabled.png); - width: 9px; - height: 9px; -} - -QAbstractSpinBox::up-arrow:hover { - image: url(%THISPATH%/qdarkstyle/rc/up_arrow.png); -} - -QAbstractSpinBox:down-button { - background-color: transparent #19232D; - subcontrol-origin: border; - subcontrol-position: bottom right; - border-left: 1px solid #32414B; - margin: 1px; -} - -QAbstractSpinBox::down-arrow, -QAbstractSpinBox::down-arrow:disabled, -QAbstractSpinBox::down-arrow:off { - image: url(%THISPATH%/qdarkstyle/rc/down_arrow_disabled.png); - width: 9px; - height: 9px; -} - -QAbstractSpinBox::down-arrow:hover { - image: url(%THISPATH%/qdarkstyle/rc/down_arrow.png); -} - -QAbstractSpinBox:hover{ - border: 1px solid #148CD2; - color: #F0F0F0; -} - -QAbstractSpinBox:selected { - background: #1464A0; - color: #32414B; -} - -/* ------------------------------------------------------------------------ */ -/* DISPLAYS --------------------------------------------------------------- */ -/* ------------------------------------------------------------------------ */ - -/* QLabel ----------------------------------------------------------------- */ - -QLabel { - background-color: #19232D; - border: 0px solid #32414B; - padding: 2px; - margin: 0px; - color: #F0F0F0 -} - -QLabel::disabled { - background-color: #19232D; - border: 0px solid #32414B; - color: #787878; -} - -/* QTextBrowser ----------------------------------------------------------- */ - -QTextBrowser { - background-color: #19232D; - border: 1px solid #32414B; - color: #F0F0F0; - border-radius: 4px; -} - -QTextBrowser:disabled { - background-color: #19232D; - border: 1px solid #32414B; - color: #787878; - border-radius: 4px; -} - -QTextBrowser:hover, -QTextBrowser:!hover, -QTextBrowser::selected, -QTextBrowser::pressed { - border: 1px solid #32414B; -} - -/* QGraphicsView --------------------------------------------------------- */ - -QGraphicsView { - background-color: #19232D; - border: 1px solid #32414B; - color: #F0F0F0; - border-radius: 4px; -} - -QGraphicsView:disabled { - background-color: #19232D; - border: 1px solid #32414B; - color: #787878; - border-radius: 4px; -} - -QGraphicsView:hover, -QGraphicsView:!hover, -QGraphicsView::selected, -QGraphicsView::pressed { - border: 1px solid #32414B; -} - -/* QCalendarWidget -------------------------------------------------------- */ - -QCalendarWidget { - border: 1px solid #32414B; - border-radius: 4px; -} - -QCalendarWidget:disabled { - background-color: #19232D; - color: #787878; -} - -/* QLCDNumber ------------------------------------------------------------- */ - -QLCDNumber { - background-color: #19232D; - color: #F0F0F0; -} - -QLCDNumber:disabled { - background-color: #19232D; - color: #787878; -} - -/* QProgressBar ----------------------------------------------------------- */ - -QProgressBar { - background-color: #19232D; - border: 1px solid #32414B; - color: #F0F0F0; - border-radius: 4px; - text-align: center; -} - -QProgressBar:disabled { - background-color: #19232D; - border: 1px solid #32414B; - color: #787878; - border-radius: 4px; - text-align: center; -} - -QProgressBar::chunk { - background-color: #1464A0; - color: #19232D; - border-radius: 4px; -} - -QProgressBar::chunk:disabled { - background-color: #14506E; - color: #787878; - border-radius: 4px; -} - - -/* ------------------------------------------------------------------------ */ -/* BUTTONS ---------------------------------------------------------------- */ -/* ------------------------------------------------------------------------ */ - -/* QPushButton ------------------------------------------------------------ */ - -QPushButton { - background-color: #505F69 ; - border: 1px solid #32414B; - color: #F0F0F0; - border-radius: 4px; - padding: 3px; - outline: none; -} - -QPushButton:disabled { - background-color: #32414B; - border: 1px solid #32414B; - color: #787878; - border-radius: 4px; - padding: 3px; -} - - -QPushButton:checked { - background-color: #32414B; - border: 1px solid #32414B; - border-radius: 4px; - padding: 3px; - outline: none; -} - -QPushButton:checked:disabled { - background-color: #19232D; - border: 1px solid #32414B; - color: #787878; - border-radius: 4px; - padding: 3px; - outline: none; -} - -QPushButton::menu-indicator { - subcontrol-origin: padding; - subcontrol-position: bottom right; - bottom: 4px; - -} - -QPushButton:pressed { - background-color: #19232D; - border: 1px solid #19232D; -} - -QPushButton:hover, -QPushButton:checked:hover{ - border: 1px solid #148CD2; - color: #F0F0F0; -} - -QPushButton:pressed:hover{ - border: 1px solid #1464A0; -} - -QPushButton:selected, -QPushButton:checked:selected{ - background: #1464A0; - color: #32414B; -} - -/* QToolButton ------------------------------------------------------------ */ - -QToolButton { - background-color: transparent; - border: 1px solid #32414B; - border-radius: 4px; - margin: 0px; - padding: 2px; -} - -QToolButton:checked { - background-color: #19232D; - border: 1px solid #19232D; -} - -QToolButton:pressed { - background-color: #19232D; - border: 1px solid #19232D; - -} - -QToolButton:disabled { - border: 1px solid #32414B; -} - -QToolButton:hover, -QToolButton:checked:hover{ - border: 1px solid #148CD2; -} -QToolButton:pressed:hover{ - border: 1px solid #1464A0; -} - -/* the subcontrols below are used only in the MenuButtonPopup mode */ - -QToolButton[popupMode="1"] { - padding: 2px; - padding-right: 12px; /* only for MenuButtonPopup */ - border: 1px solid #32414B; /* make way for the popup button */ - border-radius: 4px; -} - -/* The subcontrol below is used only in the InstantPopup or DelayedPopup mode */ - -QToolButton[popupMode="2"] { - padding: 2px; - padding-right: 12px; /* only for InstantPopup */ - border: 1px solid #32414B; /* make way for the popup button */ -} - -QToolButton::menu-button { - padding: 2px; - border-radius: 4px; - border: 1px solid #32414B; - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; - /* 16px width + 4px for border = 20px allocated above */ - width: 16px; - outline: none; -} - -QToolButton::menu-button:hover, -QToolButton::menu-button:checked:hover { - border: 1px solid #148CD2; -} - -QToolButton::menu-indicator { - image: url(%THISPATH%/qdarkstyle/rc/down_arrow.png); - top: -8px; /* shift it a bit */ - left: -4px; /* shift it a bit */ -} - -QToolButton::menu-arrow { - image: url(%THISPATH%/qdarkstyle/rc/down_arrow.png); -} - -QToolButton::menu-arrow:open { - border: 1px solid #32414B; -} - -/* QCommandLinkButton ----------------------------------------------------- */ - -QCommandLinkButton { - background-color: transparent; - border: 1px solid #32414B; - color: #F0F0F0; - border-radius: 4px; - padding: 0px; - margin: 0px; -} - -QCommandLinkButton:disabled { - background-color: transparent; - color: #787878; -} - -/* ------------------------------------------------------------------------ */ -/* INPUTS - NO FIELDS ----------------------------------------------------- */ -/* ------------------------------------------------------------------------ */ - -/* QCombobox -------------------------------------------------------------- */ -QComboBox { - border: 1px solid #32414B; - border-radius: 4px; - selection-background-color: #1464A0; - padding-left: 4px; - padding-right: 4px; - min-height: 1.5em; /* fix #103, #111 */ - /* padding-top: 2px; removed to fix #132 */ - /* padding-bottom: 2px; removed to fix #132 */ - /* min-width: 75px; removed to fix #109 */ -} - -QComboBox QAbstractItemView { - background-color: #19232d; - border-radius: 4px; - border: 1px solid #32414B; - selection-color: #148CD2; - selection-background-color: #32414B; -} - -QComboBox:disabled { - background-color: #19232D; - color: #787878; -} - -QComboBox:hover{ - border: 1px solid #148CD2; -} - -QComboBox:on { - selection-background-color: #19232D; -} - -/* Needed to remove indicator - fix #132 */ -QComboBox::indicator { - background-color:transparent; - selection-background-color:transparent; - color:transparent; - selection-color:transparent; -} - -/* Needed to remove indicator - fix #132 */ -QComboBox::item:alternate { - background: #19232D; -} - -QComboBox::item:checked { - /*font-weight: bold;*/ - background-color: #148CD2; -} - -QComboBox::item:selected { - border: 0px solid transparent; -} - -QComboBox::drop-down { - subcontrol-origin: padding; - subcontrol-position: top right; - width: 20px; - border-left-width: 0px; - border-left-color: #32414B; - border-left-style: solid; - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} - -QComboBox::down-arrow { - image: url(%THISPATH%/qdarkstyle/rc/down_arrow_disabled.png); -} - -QComboBox::down-arrow:on, -QComboBox::down-arrow:hover, -QComboBox::down-arrow:focus { - image: url(%THISPATH%/qdarkstyle/rc/down_arrow.png); -} - -/* QSlider ---------------------------------------------------------------- */ - -QSlider:disabled { - background: #19232D; -} - -QSlider:focus { - border: none; -} - -QSlider::groove:horizontal { - background: #32414B; - border: 1px solid #32414B; - height: 4px; - margin: 0px; - border-radius: 4px; -} - -QSlider::sub-page:horizontal { - background: #1464A0; - border: 1px solid #32414B; - height: 4px; - margin: 0px; - border-radius: 4px; -} - -QSlider::sub-page:horizontal:disabled { - background: #14506E; -} - -QSlider::handle:horizontal { - background: #787878; - border: 1px solid #32414B; - width: 8px; - height: 8px; - margin: -8px 0; - border-radius: 4px; -} - -QSlider::handle:horizontal:hover { - background: #148CD2; - border: 1px solid #148CD2; -} - -QSlider::groove:vertical { - background: #32414B; - border: 1px solid #32414B; - width: 4px; - margin: 0px; - border-radius: 4px; -} - -QSlider::sub-page:vertical { - background: #1464A0; - border: 1px solid #32414B; - width: 4px; - margin: 0px; - border-radius: 4px; -} - -QSlider::sub-page:vertical:disabled { - background: #14506E; -} - -QSlider::handle:vertical { - background: #787878; - border: 1px solid #32414B; - width: 8px; - height: 8px; - margin: 0 -8px; - border-radius: 4px; -} - -QSlider::handle:vertical:hover { - background: #148CD2; - border: 1px solid #148CD2; -} - -/* QLine ------------------------------------------------------------------ */ - -QLineEdit { - background-color: #19232D; - padding-top: 2px; /* This QLineEdit fix 103, 111 */ - padding-bottom: 2px; /* This QLineEdit fix 103, 111 */ - padding-left: 4px; - padding-right: 4px; - border-style: solid; - border: 1px solid #32414B; - border-radius: 4px; - color: #F0F0F0; -} - -QLineEdit:disabled { - background-color: #19232D; - color: #787878; -} - -QLineEdit:hover{ - border: 1px solid #148CD2; - color: #F0F0F0; -} - -QLineEdit:selected{ - background: #1464A0; - color: #32414B; -} - -/* QTabWiget -------------------------------------------------------------- */ - -QTabWidget { - padding: 2px; - selection-background-color: #32414B; -} - - -QTabWidget QWidget QWidget /* add wanted borders fix #141, #126, #123 */ -QTabWidget QFrame { - border: 1px solid #32414B; -} - -QTabWidget QLabel { - border: 0px solid #32414B; /* label derived from frame, remove border #141 */ -} - -QTabWidget::pane { - border: 1px solid #32414B; - border-radius: 4px; - padding: 0px; /* fixes double border inside pane wit pyqt5 */ - margin: 0px; -} - -QTabWidget::pane:selected { - background-color: #32414B; - border: 1px solid #1464A0; -} - -/* QTabBar ---------------------------------------------------------------- */ - -QTabBar { - qproperty-drawBase: 0; - border-radius: 4px; - margin: 0px; - padding: 2px; - border: 0; - - /* left: 5px; move to the right by 5px - removed for fix */ - } - -QTabBar::close-button { - border: 0; - margin: 2px; - padding: 0; - image: url(%THISPATH%/qdarkstyle/rc/close.png); -} - -QTabBar::close-button:hover { - image: url(%THISPATH%/qdarkstyle/rc/close-hover.png); -} - -QTabBar::close-button:pressed { - image: url(%THISPATH%/qdarkstyle/rc/close-pressed.png); -} - -/* QTabBar::tab - selected ----------------------------------------------- */ - -QTabBar::tab:top:selected:disabled { - border-bottom: 3px solid #14506E; - color: #787878; - background-color: #32414B; -} - -QTabBar::tab:bottom:selected:disabled { - border-top: 3px solid #14506E; - color: #787878; - background-color: #32414B; -} - -QTabBar::tab:left:selected:disabled { - border-left: 3px solid #14506E; - color: #787878; - background-color: #32414B; -} - -QTabBar::tab:right:selected:disabled { - border-right: 3px solid #14506E; - color: #787878; - background-color: #32414B; -} - -/* QTabBar::tab - !selected and disabled ---------------------------------- */ - -QTabBar::tab:top:!selected:disabled { - border-bottom: 3px solid #19232D; - color: #787878; - background-color: #19232D; -} - -QTabBar::tab:bottom:!selected:disabled { - border-top: 3px solid #19232D; - color: #787878; - background-color: #19232D; -} - -QTabBar::tab:left:!selected:disabled { - border-right: 3px solid #19232D; - color: #787878; - background-color: #19232D; -} - -QTabBar::tab:right:!selected:disabled { - border-left: 3px solid #19232D; - color: #787878; - background-color: #19232D; -} - -/* QTabBar::tab - selected ----------------------------------------------- */ - -QTabBar::tab:top:!selected { - border-bottom: 2px solid #19232D; - margin-top: 2px; -} - -QTabBar::tab:bottom:!selected { - border-top: 2px solid #19232D; - margin-bottom: 3px; -} - -QTabBar::tab:left:!selected { - border-left: 2px solid #19232D; - margin-right: 2px; -} - -QTabBar::tab:right:!selected { - border-right: 2px solid #19232D; - margin-left: 2px; -} - - -QTabBar::tab:top { - background-color: #32414B; - color: #F0F0F0; - margin-left: 2px; - padding-left: 4px; - padding-right: 4px; - padding-top: 2px; - padding-bottom: 2px; - min-width: 5px; - border-bottom: 3px solid #32414B; - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} - -QTabBar::tab:top:selected { - background-color: #505F69; - color: #F0F0F0; - border-bottom: 3px solid #1464A0; - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} - -QTabBar::tab:top:!selected:hover { - border: 1px solid #148CD2; - border-bottom: 3px solid #148CD2; - padding: 0px; -} - -QTabBar::tab:bottom { - color: #F0F0F0; - border-top: 3px solid #32414B; - background-color: #32414B; - margin-left: 2px; - padding-left: 4px; - padding-right: 4px; - padding-top: 2px; - padding-bottom: 2px; - border-bottom-left-radius: 3px; - border-bottom-right-radius: 3px; - min-width: 5px; -} - -QTabBar::tab:bottom:selected { - color: #F0F0F0; - background-color: #505F69; - border-top: 3px solid #1464A0; - border-bottom-left-radius: 3px; - border-bottom-right-radius: 3px; -} - -QTabBar::tab:bottom:!selected:hover { - border: 1px solid #148CD2; - border-top: 3px solid #148CD2; - padding: 0px; -} - -QTabBar::tab:left { - color: #F0F0F0; - background-color: #32414B; - margin-top: 2px; - padding-left: 2px; - padding-right: 2px; - padding-top: 4px; - padding-bottom: 4px; - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; - min-height: 5px; -} - -QTabBar::tab:left:selected { - color: #F0F0F0; - background-color: #505F69; - border-left: 3px solid #1464A0; - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} - -QTabBar::tab:left:!selected:hover { - border: 1px solid #148CD2; - border-left: 3px solid #148CD2; - padding: 0px; -} - -QTabBar::tab:right { - color: #F0F0F0; - background-color: #32414B; - margin-top: 2px; - padding-left: 2px; - padding-right: 2px; - padding-top: 4px; - padding-bottom: 4px; - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; - min-height: 5px; -} - -QTabBar::tab:right:selected { - color: #F0F0F0; - background-color: #505F69; - border-right: 3px solid #1464A0; - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; -} - -QTabBar::tab:right:!selected:hover { - border: 1px solid #148CD2; - border-right: 3px solid #148CD2; - padding: 0px; -} - -QTabBar QToolButton::right-arrow:enabled { - image: url(%THISPATH%/qdarkstyle/rc/right_arrow.png); -} - -QTabBar QToolButton::left-arrow:enabled { - image: url(%THISPATH%/qdarkstyle/rc/left_arrow.png); -} - -QTabBar QToolButton::right-arrow:disabled { - image: url(%THISPATH%/qdarkstyle/rc/right_arrow_disabled.png); -} - -QTabBar QToolButton::left-arrow:disabled { - image: url(%THISPATH%/qdarkstyle/rc/left_arrow_disabled.png); -} - -QTabBar QToolButton{ - background-color: #32414B; /* fixes #136 */ - width: 16px; - height: 16px; -} - -/* QDockWiget ------------------------------------------------------------- */ - -QDockWidget { - outline: 1px solid #32414B; - background-color: #19232D; - border: 1px solid #32414B; - border-radius: 4px; - titlebar-close-icon: url(%THISPATH%/qdarkstyle/rc/close.png); - titlebar-normal-icon: url(%THISPATH%/qdarkstyle/rc/undock.png); -} - -QDockWidget::title { - padding: 6px; /* better size for title bar */ - border: none; - background-color: #32414B; -} - -QDockWidget::close-button { - background-color: #32414B; - border-radius: 4px; - border: none; -} - -QDockWidget::close-button:hover { - border: 1px solid #32414B; -} - -QDockWidget::close-button:pressed { - border: 1px solid #32414B; -} - -QDockWidget::float-button { - background-color: #32414B; - border-radius: 4px; - border: none; -} - -QDockWidget::float-button:hover { - border: 1px solid #32414B; -} - -QDockWidget::float-button:pressed { - border: 1px solid #32414B; -} - - -/* QTreeView QTableView QListView ----------------------------------------- */ - -QTreeView:branch:selected, -QTreeView:branch:hover { - background: url(%THISPATH%/qdarkstyle/rc/transparent.png); -} - -QTreeView::branch:has-siblings:!adjoins-item { - border-image: url(%THISPATH%/qdarkstyle/rc/transparent.png); -} - -QTreeView::branch:has-siblings:adjoins-item { - border-image: url(%THISPATH%/qdarkstyle/rc/transparent.png); -} - -QTreeView::branch:!has-children:!has-siblings:adjoins-item { - border-image: url(%THISPATH%/qdarkstyle/rc/transparent.png); -} - -QTreeView::branch:has-children:!has-siblings:closed, -QTreeView::branch:closed:has-children:has-siblings { - image: url(%THISPATH%/qdarkstyle/rc/branch_closed.png); -} - -QTreeView::branch:open:has-children:!has-siblings, -QTreeView::branch:open:has-children:has-siblings { - image: url(%THISPATH%/qdarkstyle/rc/branch_open.png); -} - -QTreeView::branch:has-children:!has-siblings:closed:hover, -QTreeView::branch:closed:has-children:has-siblings:hover { - image: url(%THISPATH%/qdarkstyle/rc/branch_closed-on.png); -} - -QTreeView::branch:open:has-children:!has-siblings:hover, -QTreeView::branch:open:has-children:has-siblings:hover { - image: url(%THISPATH%/qdarkstyle/rc/branch_open-on.png); -} - -QListView::item:!selected:hover, -QTreeView::item:!selected:hover, -QTableView::item:!selected:hover, -QColumnView::item:!selected:hover { - outline: 0; - color: #148CD2; - background-color: #32414B; -} - -QListView::item:selected:hover, -QTreeView::item:selected:hover, -QTableView::item:selected:hover, -QColumnView::item:selected:hover { - background: #1464A0; - color: #19232D; -} - -QTreeView::indicator:checked, -QListView::indicator:checked { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_checked.png); -} - -QTreeView::indicator:unchecked, -QListView::indicator:unchecked { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_unchecked.png); -} - -QTreeView::indicator:checked:hover, -QTreeView::indicator:checked:focus, -QTreeView::indicator:checked:pressed, -QListView::indicator:checked:hover, -QListView::indicator:checked:focus, -QListView::indicator:checked:pressed { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_checked_focus.png); -} - -QTreeView::indicator:unchecked:hover, -QTreeView::indicator:unchecked:focus, -QTreeView::indicator:unchecked:pressed, -QListView::indicator:unchecked:hover, -QListView::indicator:unchecked:focus, -QListView::indicator:unchecked:pressed { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_unchecked_focus.png); -} - -QTreeView::indicator:indeterminate:hover, -QTreeView::indicator:indeterminate:focus, -QTreeView::indicator:indeterminate:pressed, -QListView::indicator:indeterminate:hover, -QListView::indicator:indeterminate:focus, -QListView::indicator:indeterminate:pressed { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_indeterminate_focus.png); -} - -QTreeView::indicator:indeterminate, -QListView::indicator:indeterminate { - image: url(%THISPATH%/qdarkstyle/rc/checkbox_indeterminate.png); -} - -QListView, -QTreeView, -QTableView, -QColumnView { - background-color: #19232D; - border: 1px solid #32414B; - color: #F0F0F0; - gridline-color: #32414B; - border-radius: 4px; -} - -QListView:disabled, -QTreeView:disabled, -QTableView:disabled, -QColumnView:disabled { - background-color: #19232D; - color: #787878; -} - -QListView:selected, -QTreeView:selected, -QTableView:selected, -QColumnView:selected { - background: #1464A0; - color: #32414B; -} - -QListView:hover, -QTreeView::hover, -QTableView::hover, -QColumnView::hover { - background-color: #19232D; - border: 1px solid #148CD2; -} - -QListView::item:pressed, -QTreeView::item:pressed, -QTableView::item:pressed, -QColumnView::item:pressed { - background-color: #1464A0; -} - -QListView::item:selected:active, -QTreeView::item:selected:active, -QTableView::item:selected:active, -QColumnView::item:selected:active { - background-color: #1464A0; -} - -QTableCornerButton::section { - background-color: #19232D; - border: 1px transparent #32414B; - border-radius: 0px; -} - -/* QHeaderView ------------------------------------------------------------ */ - -QHeaderView { - background-color: #32414B; - border: 0px transparent #32414B; - padding: 0px; - margin: 0px; - border-radius: 0px; -} - -QHeaderView:disabled { - background-color: #32414B; - border: 1px transparent #32414B; - padding: 2px; -} - -QHeaderView::section { - background-color: #32414B; - color: #F0F0F0; - padding: 2px; - border-radius: 0px; - text-align: left; -} - -QHeaderView::section:checked { - color: #F0F0F0; - background-color: #1464A0; -} - -QHeaderView::section:checked:disabled { - color: #787878; - background-color: #14506E; -} - -QHeaderView::section::horizontal:disabled, -QHeaderView::section::vertical:disabled { - color: #787878; -} - -QHeaderView::section::vertical::first, -QHeaderView::section::vertical::only-one { - border-top: 1px solid #32414B; -} - -QHeaderView::section::vertical { - border-top: 1px solid #19232D; -} - -QHeaderView::section::horizontal::first, -QHeaderView::section::horizontal::only-one { - border-left: 1px solid #32414B; -} - -QHeaderView::section::horizontal { - border-left: 1px solid #19232D; -} - -/* Those settings (border/width/height/background-color) solve bug */ -/* transparent arrow background and size */ - -QHeaderView::down-arrow { - background-color: #32414B; - width: 16px; - height: 16px; - border-right: 1px solid #19232D; - image: url(%THISPATH%/qdarkstyle/rc/down_arrow.png); -} - -QHeaderView::up-arrow { - background-color: #32414B; - width: 16px; - height: 16px; - border-right: 1px solid #19232D; - image: url(%THISPATH%/qdarkstyle/rc/up_arrow.png); -} - -/* QToolBox -------------------------------------------------------------- */ - -QToolBox { - padding: 0px; - border: 1px solid #32414B; -} - -QToolBox::selected { - padding: 0px; - border: 2px solid #1464A0; -} - -QToolBox::tab { - background-color: #19232D; - border: 1px solid #32414B; - color: #F0F0F0; - border-top-left-radius: 4px; - border-top-right-radius: 4px; -} - -QToolBox::tab:disabled { - color: #787878; -} - -QToolBox::tab:selected { - background-color: #505F69; - border-bottom: 2px solid #1464A0; -} - -QToolBox::tab:!selected { - background-color: #32414B; - border-bottom: 2px solid #32414B; -} - -QToolBox::tab:selected:disabled { - background-color: #32414B; - border-bottom: 2px solid #14506E; -} - -QToolBox::tab:!selected:disabled { - background-color: #19232D; -} - -QToolBox::tab:hover { - border-color: #148CD2; - border-bottom: 2px solid #148CD2; -} - -QToolBox QScrollArea QWidget QWidget { - padding: 0px; - background-color: #19232D; -} - -/* QFrame ----------------------------------------------------------------- */ - -QFrame { - border-radius: 4px; - border: 1px solid #32414B; - -} - -QFrame[frameShape="0"] { - border-radius: 4px; - border: 1px transparent #32414B; -} - -QFrame[height="3"], -QFrame[width="3"] { - background-color: #19232D; -} - -/* QSplitter -------------------------------------------------------------- */ - -QSplitter { - background-color: #32414B; - spacing: 0; - padding: 0; - margin: 0; -} - -QSplitter::separator { - background-color: #32414B; - border: 0 solid #19232D; - spacing: 0; - padding: 1px; - margin: 0; -} - -QSplitter::separator:hover { - background-color: #787878; -} - -QSplitter::separator:horizontal { - width: 5px; - image: url(%THISPATH%/qdarkstyle/rc/Vsepartoolbar.png); -} - -QSplitter::separator:vertical { - height: 5px; - image: url(%THISPATH%/qdarkstyle/rc/Hsepartoolbar.png); -} - - -/* QDateEdit-------------------------------------------------------------- */ - -QDateEdit { - selection-background-color: #1464A0; - border-style: solid; - border: 1px solid #32414B; - border-radius: 4px; - padding-top: 2px; /* This fix #103, #111*/ - padding-bottom: 2px; /* This fix #103, #111*/ - padding-left: 4px; - padding-right: 4px; - min-width: 10px; -} - -QDateEdit:on { - selection-background-color: #1464A0; -} - -QDateEdit::drop-down { - subcontrol-origin: padding; - subcontrol-position: top right; - width: 20px; - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} - -QDateEdit::down-arrow { - image: url(%THISPATH%/qdarkstyle/rc/down_arrow_disabled.png); -} - -QDateEdit::down-arrow:on, -QDateEdit::down-arrow:hover, -QDateEdit::down-arrow:focus { - image: url(%THISPATH%/qdarkstyle/rc/down_arrow.png); -} - -QDateEdit QAbstractItemView { - background-color: #19232D; - border-radius: 4px; - border: 1px solid #32414B; - selection-background-color: #1464A0; -} - -QAbstractView:hover{ - border: 1px solid #148CD2; - color: #F0F0F0; -} - -QAbstractView:selected { - background: #1464A0; - color: #32414B; -} - - -PlotWidget { - padding: 0px; /* to fix cut labels in plots #134 */ -} - -NewFriendList { - qproperty-textColorStatusAway: #4040A0; - qproperty-textColorStatusBusy: #A04040; - qproperty-textColorStatusOnline: #40A040; - qproperty-textColorStatusInactive: #A0A040; - qproperty-textColorStatusOffline: gray; - qproperty-textColorGroup: rgb(123, 123, 123); -} - -NetworkDialog { - qproperty-backgroundColorSelf: darkred; - qproperty-backgroundColorOwnSign: darkred; - qproperty-backgroundColorAcceptConnection: black; - qproperty-backgroundColorHasSignedMe: darkred; - qproperty-backgroundColorDenied: #201F1F; -} - -RSTreeWidget#idTreeWidget::item:!selected { - color: #C0C0C0; -} - -GxsChannelPostItem > QFrame#mainFrame[new=true] { - border: 3px solid #82B9F4; - border-radius: 10px; -} - -GxsForumThreadWidget QPushButton#forumName -{ - qproperty-fontSizeFactor: 140; - color: #0099cc; - font-size: 14pt; - font: bold; -} - -ForumsDialog, GxsForumThreadWidget -{ - qproperty-textColorRead: darkgray; - qproperty-textColorUnread: white; - qproperty-textColorUnreadChildren: red; - qproperty-textColorNotSubscribed: white; - qproperty-textColorMissing: darkred; - qproperty-textColorPinned: #D07000; - - qproperty-backgroundColorPinned: #19232D; - qproperty-backgroundColorFiltered: darkGreen; -} - -GxsForumThreadWidget QWidget#threadTreeWidget { - selection-background-color: #005599; - show-decoration-selected: 1; -} - -GxsForumThreadWidget QWidget#threadTreeWidget::item { - padding: 2px; -} - -GxsForumThreadWidget QWidget#threadTreeWidget::item:selected:active , -GxsForumThreadWidget QWidget#threadTreeWidget::item:selected:!active { - background-color: #005599; -} - -QTreeView [new=true]{ - color: #0099cc; - -} - -/* changes for the subscribe Button */ - -PostedListWidgetWithModel QToolButton#subscribeToolButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; -} - -PostedListWidgetWithModel QToolButton#subscribeToolButton:hover { - background: #03b1f3; - border-radius: 4px; -} - -GxsForumThreadWidget QToolButton#subscribeToolButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; -} - -GxsForumThreadWidget QToolButton#subscribeToolButton:hover { - background: #03b1f3; - border-radius: 4px; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton:hover { - background: #03b1f3; - border-radius: 4px; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton:pressed { - background: #03b1f3; - border-radius: 4px; - border: 1px solid gray; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton:disabled { - background: gray; - border-radius: 4px; - border: 1px solid gray; - color: lightgray; -} - -/* only for MenuButtonPopup */ -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton[popupMode="1"] { - padding-right: 0px; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton::menu-arrow { - image: none; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton::menu-button { - image: none; - -} - -CreateGxsChannelMsg QPushButton#postButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -CreateGxsChannelMsg QPushButton#postButton:hover { - background: #03b1f3; - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - -CreateCircleDialog QPushButton#createButton, CreateLobbyDialog QPushButton#createButton, -IdEditDialog QPushButton#createButton, CreateGxsForumMsg QPushButton#postButton, -GxsCreateCommentDialog QPushButton#postButton, GxsGroupDialog QPushButton#createButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -CreateCircleDialog QPushButton#createButton:hover, CreateLobbyDialog QPushButton#createButton:hover, -IdEditDialog QPushButton#createButton:hover, CreateGxsForumMsg QPushButton#postButton:hover, -GxsCreateCommentDialog QPushButton#postButton:hover, GxsGroupDialog QPushButton#createButton:hover { - background: #03b1f3; - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - -CreateGxsForumMsg QPushButton#postButton:disabled, PostedCreatePostDialog QPushButton#submitButton:disabled, -CreateGxsChannelMsg QPushButton#postButton:disabled, GxsCreateCommentDialog QPushButton#postButton:disabled { - font: bold; - font-size: 12pt; - color: white; - background: #d40000; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -QTabBar#smTab::tab{ - height: 32px; - width: 32px; -} - -QLabel#avatarLabel{ - border: 2px solid #CCCCCC; - border-radius: 4px; -} - -PostedCreatePostDialog QPushButton#submitButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - min-width: 2em; - -} - -PostedCreatePostDialog QPushButton#submitButton:hover { - background: #03b1f3; - border-radius: 4px; - min-width: 2em; - -} - -BoardPostDisplayWidget_compact QFrame#mainFrame { - border-radius: 4px; - border: 1px solid #32414B; - background-color: #19232D; -} - -BoardPostDisplayWidget_compact QFrame#mainFrame [new=false]{ - background: #19232D; -} - -BoardPostDisplayWidget_compact QFrame#mainFrame[new=true] { - background-color: #1464a0; -} - -GxsChannelPostItem QFrame#mainFrame { - border-radius: 4px; - border: 1px solid #32414B; - background-color: #19232D; -} - -GxsChannelPostItem QLabel#subjectLabel, GxsChannelPostItem QLabel#titleLabel { - font: 12pt; - font: bold italic; -} - -BoardPostDisplayWidget_compact QPushButton#shareButton { - background-color: transparent; - min-width: 80px; - max-height: 22px; -} - -BoardPostDisplayWidget_compact QFrame#voteFrame { - background: #141415; -} - -BoardPostDisplayWidget_compact QToolButton#voteDownButton, QToolButton#voteUpButton, -BoardPostDisplayWidget_card QToolButton#voteDownButton, QToolButton#voteUpButton -{ - border: none; -} - -BoardPostDisplayWidget_compact QLabel#pictureLabel{ - border: 2px solid #CCCCCC; - border-radius: 3px; -} - -BoardPostDisplayWidget_compact QLabel#scoreLabel, QLabel#titleLabel, QLabel#fromBoldLabel , QLabel#fromLabel, QLabel#dateLabel, -BoardPostDisplayWidget_card QLabel#scoreLabel, QLabel#titleLabel{ - background-color: transparent; -} - -BoardPostDisplayWidget_compact QLabel#newLabel, -BoardPostDisplayWidget_card QLabel#newLabel { - border: 1px solid #00B712; - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5AFF15, stop: 1 #00B712); - border-radius: 3px; - color: black; -} - -BoardPostDisplayWidget_card QPushButton#shareButton{ - background-color: transparent; - min-width: 80px; - max-height: 22px; -} - -BoardPostDisplayWidget_card QFrame#voteFrame { - background: #141415; -} - -BoardPostDisplayWidget_card QFrame#mainFrame { - background-color: #19232D; -} - -BoardPostDisplayWidget_card QFrame#mainFrame [new=false]{ - background: #19232D; -} - -BoardPostDisplayWidget_card QFrame#mainFrame[new=true] { - background-color: #1464a0; -} - -BoardPostDisplayWidget_compact QLabel#titleLabel, -BoardPostDisplayWidget_card QLabel#titleLabel{ - font-size: 12pt; - font: bold; -} - -GxsForumMsgItem QFrame#frame{ - background-color: #19232D; -} - -PostedItem QFrame#mainFrame{ - background: #19232D; -} - -WireGroupItem QFrame#wire_frame{ - background: transparent; -} - -GxsChannelDialog GroupTreeWidget QTreeWidget#treeWidget::item{ - /*background-color: #F00000;*/ - /*padding: 2px;*/ -} - -RSTextBrowser, MimeTextEdit -{ - /*qproperty-textColorQuote: rgb(125, 125, 255);*/ - qproperty-textColorQuotes: ColorList(#789922 #039bd5 #800000 #800080 #008080 #b10dc9 #85144b #3d9970); -} - -PulseTopLevel QFrame#frame, PulseViewGroup QFrame#frame, PulseReply QFrame#frame { - border: 2px solid #38444d; - border-radius: 6px; -} - -MainWindow QListWidget { - font-size: 12pt; -} - -ChatLobbyWidget QTreeWidget#lobbyTreeWidget{ - font-size: 10pt; -} - -NewFriendList QTreeView#peerTreeWidget { - font-size: 12pt; -} - -ChannelsCommentsItem QFrame#mainFrame, BoardsCommentsItem QFrame#mainFrame { - background: #19232D; -} - -ChannelsCommentsItem QLabel#newCommentLabel, BoardsCommentsItem QLabel#newCommentLabel { - font: 12pt; - font: bold; -} - -ChannelsCommentsItem QLabel#subjectLabel, ChannelsCommentsItem QLabel#titleLabel , QLabel#nameLabel { - font: 12pt; - font: bold; -} - -BoardsCommentsItem QLabel#subjectLabel, QLabel#titleLabel , QLabel#nameLabel { - font: 12pt; - font: bold; -} - -HomePage QToolButton#addButton { - font: bold; - font-size: 15pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -HomePage QToolButton#addButton:hover { - background: #03b1f3; - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - -NewFriendList QTreeView#peerTreeWidget { - font-size: 12pt; -} diff --git a/retroshare-gui/src/qss/qdarkstyle.qss b/retroshare-gui/src/qss/qdarkstyle.qss deleted file mode 100644 index bac32c219..000000000 --- a/retroshare-gui/src/qss/qdarkstyle.qss +++ /dev/null @@ -1,1558 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) <2013-2014> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -QProgressBar:horizontal { - border: 1px solid #3A3939; - text-align: center; - padding: 1px; - background: #201F1F; - width: 15px; -} -QProgressBar::chunk:horizontal { - background-color: qlineargradient(spread:reflect, x1:1, y1:0.545, x2:1, y2:0, stop:0 rgba(28, 66, 111, 255), stop:1 rgba(37, 87, 146, 255)); - width: 15px; -} - -QFrame#titleBarFrame, QFrame#toolBarFrame -{ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #616161, stop: 0.5 #505050, - stop: 0.6 #434343, stop:1 #656565); -} - -QToolTip -{ - border: 1px solid #3A3939; - background-color: rgb(90, 102, 117); - color: white; - padding: 1px; - opacity: 200; -} - -QWidget -{ - color: silver; - background-color: #302F2F; - selection-background-color:#78879b; - selection-color: black; - background-clip: border; - border-image: none; - outline: 0; -} -QTreeView::item, QTreeWidget::item, QListWidget::item{ - color: silver; -} - -QWidget:item:hover -{ - background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #78879b, stop: 1 #78879b); - color: black; -} - -QWidget:item:selected -{ - background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #78879b, stop: 1 #78879b); -} - -QTableWidget::item { - color: #C0C0C0; - background-color: #201F1F; -} - -QTableWidget::item:selected { - color: black; -} - -ForumsDialog, GxsForumThreadWidget -{ - qproperty-textColorRead: darkgray; - qproperty-textColorUnread: white; - qproperty-textColorUnreadChildren: red; - qproperty-textColorNotSubscribed: white; - qproperty-textColorMissing: darkred; - qproperty-textColorPinned: #D07000; - - qproperty-backgroundColorPinned: #202020; - qproperty-backgroundColorFiltered: darkGreen; -} - -QMenuBar -{ - background-color: #302F2F; - color: silver; -} - -QMenuBar::item -{ - background: transparent; -} - -QMenuBar::item:selected -{ - background: transparent; - border: 1px solid #3A3939; -} - -QMenuBar::item:pressed -{ - border: 1px solid #3A3939; - background-color: #78879b; - color: black; - margin-bottom:-1px; - padding-bottom:1px; -} - -QMenu -{ - border: 1px solid #3A3939; - color: silver; - margin: 2px; -} - -QMenu::icon -{ - margin: 5px; -} - -QMenu::item -{ - padding: 5px 30px 5px 30px; - margin-left: 5px; - border: 1px solid transparent; /* reserve space for selection border */ -} - -QMenu::item:selected -{ - color: black; -} - -QWidget:disabled -{ - color: #404040; - background-color: #302F2F; -} - -QAbstractItemView -{ - alternate-background-color: #3A3939; - color: silver; - border: 1px solid 3A3939; - border-radius: 3px; - padding: 1px; -} - -QWidget:focus, QMenuBar:focus -{ - border: 1px solid rgba(48, 86, 111); -} - -QTabWidget:focus, QCheckBox:focus, QRadioButton:focus -{ - border: none; -} - -QLineEdit -{ - background-color: #201F1F; - padding: 2px; - border-style: solid; - border: 1px solid #3A3939; - border-radius: 3px; - color: silver; -} - -QGroupBox { - border:1px solid #3A3939; - border-radius: 7px; - margin-top: 2ex; -} - -QGroupBox::title { - subcontrol-origin: margin; - subcontrol-position: top center; - padding-left: 10px; - padding-right: 10px; -} - -QAbstractScrollArea -{ - border-radius: 3px; - border: 1px solid #3A3939; -} - -QScrollBar:horizontal -{ - height: 15px; - margin: 0px 11px 0px 11px; - border: 1px solid #3A3939; - border-radius: 6px; - background-color: QLinearGradient( x1: 0, y1: 1, x2: 0, y2: 0, - stop: 0 #302F2F, stop: 1 #484846); -} - -QScrollBar::handle:horizontal -{ - background-color: QLinearGradient( x1: 0, y1: 1, x2: 0, y2: 0, - stop: 0 #605F5F, stop: 1 #787876); - min-width: 5px; - border-radius: 5px; -} - -QScrollBar::sub-line:horizontal -{ - border-image: url(%THISPATH%/qdarkstyle/right_arrow_disabled.png); - width: 10px; - height: 10px; - subcontrol-position: right; - subcontrol-origin: margin; -} - -QScrollBar::add-line:horizontal -{ - border-image: url(%THISPATH%/qdarkstyle/left_arrow_disabled.png); - height: 10px; - width: 10px; - subcontrol-position: left; - subcontrol-origin: margin; -} - -QScrollBar::sub-line:horizontal:hover,QScrollBar::sub-line:horizontal:on -{ - border-image: url(%THISPATH%/qdarkstyle/right_arrow.png); - height: 10px; - width: 10px; - subcontrol-position: right; - subcontrol-origin: margin; -} - - -QScrollBar::add-line:horizontal:hover, QScrollBar::add-line:horizontal:on -{ - border-image: url(%THISPATH%/qdarkstyle/left_arrow.png); - height: 10px; - width: 10px; - subcontrol-position: left; - subcontrol-origin: margin; -} - -QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal -{ - background: none; -} - - -QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal -{ - background: none; -} - -QScrollBar:vertical -{ - background-color: QLinearGradient( x1: 1, y1: 0, x2: 0, y2: 0, - stop: 0 #302F2F, stop: 1 #484846); - width: 15px; - margin: 11px 0 11px 0; - border: 1px solid #3A3939; - border-radius: 6px; -} - -QScrollBar::handle:vertical -{ - background-color: QLinearGradient( x1: 1, y1: 0, x2: 0, y2: 0, - stop: 0 #605F5F, stop: 1 #787876); - min-height: 5px; - border-radius: 5px; -} - -QScrollBar::sub-line:vertical -{ - border-image: url(%THISPATH%/qdarkstyle/up_arrow_disabled.png); - height: 10px; - width: 10px; - subcontrol-position: top; - subcontrol-origin: margin; -} - -QScrollBar::add-line:vertical -{ - - border-image: url(%THISPATH%/qdarkstyle/down_arrow_disabled.png); - height: 10px; - width: 10px; - subcontrol-position: bottom; - subcontrol-origin: margin; -} - -QScrollBar::sub-line:vertical:hover,QScrollBar::sub-line:vertical:on -{ - - border-image: url(%THISPATH%/qdarkstyle/up_arrow.png); - height: 10px; - width: 10px; - subcontrol-position: top; - subcontrol-origin: margin; -} - - -QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on -{ - border-image: url(%THISPATH%/qdarkstyle/down_arrow.png); - height: 10px; - width: 10px; - subcontrol-position: bottom; - subcontrol-origin: margin; -} - -QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical -{ - background: none; -} - - -QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical -{ - background: none; -} - -QTextEdit -{ - background-color: #201F1F; - color: silver; - border: 1px solid #3A3939; -} - -QPlainTextEdit -{ - background-color: #201F1F; - color: silver; - border-radius: 3px; - border: 1px solid #3A3939; -} - -QHeaderView::section -{ - background-color: #3A3939; - color: silver; - padding-left: 4px; - border: 1px solid #6c6c6c; -} - -QCheckBox:disabled -{ - color: #404040; -} - -QSizeGrip { - image: url(%THISPATH%/qdarkstyle/sizegrip.png); - width: 12px; - height: 12px; -} - - -QMainWindow::separator -{ - background-color: #302F2F; - color: white; - padding-left: 4px; - spacing: 2px; - border: 1px dashed #3A3939; -} - -QMainWindow::separator:hover -{ - - background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #58677b, - stop:0.5 #78879b stop:1 #58677b); - color: white; - padding-left: 4px; - border: 1px solid #3A3939; - spacing: 2px; -} - - -QMenu::separator -{ - height: 1px; - background-color: #3A3939; - color: white; - padding-left: 4px; - margin-left: 10px; - margin-right: 5px; -} - - - -QRadioButton::indicator:checked, QRadioButton::indicator:unchecked{ - color: #b1b1b1; - background-color: #302F2F; - border: 1px solid silver; - border-radius: 5px; -} - - - -QRadioButton::indicator:checked -{ - background-color: qradialgradient( - cx: 0.5, cy: 0.5, - fx: 0.5, fy: 0.5, - radius: 1.0, - stop: 0.25 #78879b, - stop: 0.3 #302F2F - ); -} - -QCheckBox, QRadioButton -{ - padding: 3px; - outline: none; -} - -QCheckBox::indicator{ - color: #b1b1b1; - background-color: #302F2F; - border: 1px solid silver; - width: 9px; - height: 9px; -} - -QRadioButton::indicator -{ - border-radius: 7px; - width: 9px; - height: 9px; -} - -QCheckBox::indicator:pressed -{ - border: 1px solid #78879b; -} - -QRadioButton::indicator:hover, QCheckBox::indicator:hover -{ - border: 1px solid #78879b; -} - -QCheckBox::indicator:checked -{ - background-color: qradialgradient( - cx: 0.5, cy: 0.5, - fx: 0.5, fy: 0.5, - radius: 1.0, - stop: 0.25 #78879b, - stop: 0.3 #302F2F - ); - -} - -QCheckBox::indicator:disabled, QRadioButton::indicator:disabled -{ - border: 1px solid #444; -} - -QFrame -{ - border-radius: 3px; -} - -QStackedWidget -{ - border: none; -} - -QToolBar { - border: 1px solid #393838; - background: 1px solid #302F2F; - font-weight: bold; -} - -QToolBar::handle:horizontal { - image: url(%THISPATH%/qdarkstyle/Hmovetoolbar.png); -} -QToolBar::handle:vertical { - image: url(%THISPATH%/qdarkstyle/Vmovetoolbar.png); -} -QToolBar::separator:horizontal { - image: url(%THISPATH%/qdarkstyle/Hsepartoolbar.png); -} -QToolBar::separator:vertical { - image: url(%THISPATH%/qdarkstyle/Vsepartoolbars.png); -} - -QPushButton -{ - color: silver; - background-color: QLinearGradient( x1: 0, y1: 1, x2: 0, y2: 0, - stop: 0 #302F2F, stop: 1 #484846); - border-width: 1px; - border-color: #4A4949; - border-style: solid; - padding-top: 5px; - padding-bottom: 5px; - padding-left: 5px; - padding-right: 5px; - border-radius: 5px; - outline: none; -} - -QPushButton:disabled -{ - background-color: #302F2F; - border-width: 1px; - border-color: #3A3939; - border-style: solid; - padding-top: 5px; - padding-bottom: 5px; - padding-left: 10px; - padding-right: 10px; - /*border-radius: 3px;*/ - color: #454545; -} - -QComboBox -{ - selection-background-color: #78879b; - background-color: #201F1F; - border-style: solid; - border: 1px solid #3A3939; - border-radius: 3px; - padding: 2px; - min-width: 75px; -} - -QComboBox:hover,QPushButton:hover,QAbstractSpinBox:hover,QLineEdit:hover,QTextEdit:hover,QPlainTextEdit:hover,QAbstractView:hover,QTreeView:hover -{ - border: 1px solid #78879b; - color: silver; -} - -QComboBox:on -{ - background-color: #626873; - padding-top: 3px; - padding-left: 4px; - selection-background-color: #4a4a4a; -} - -/* Needed to remove indicator - fix #132 */ -QComboBox::indicator { - background-color:transparent; - selection-background-color:transparent; - color:transparent; - selection-color:transparent; -} - -QComboBox QAbstractItemView -{ - background-color: #201F1F; - border-radius: 3px; - border: 1px solid #3A3939; - selection-background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #78879b, stop: 1 #78879b); -} - -QComboBox::drop-down -{ - subcontrol-origin: padding; - subcontrol-position: top right; - width: 15px; - - border-left-width: 0px; - border-left-color: darkgray; - border-left-style: solid; - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} - -QComboBox::down-arrow -{ - image: url(%THISPATH%/qdarkstyle/down_arrow_disabled.png); -} - -QComboBox::down-arrow:on, QComboBox::down-arrow:hover, -QComboBox::down-arrow:focus -{ - image: url(%THISPATH%/qdarkstyle/down_arrow.png); -} - -QPushButton:pressed -{ - background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #302F2F, stop: 1 #484846); -} - -QAbstractSpinBox { - padding-top: 2px; - padding-bottom: 2px; - border: 1px solid #3A3939; - background-color: #201F1F; - color: silver; - border-radius: 3px; - min-width: 75px; -} - -QAbstractSpinBox:up-button -{ - background-color: transparent; - subcontrol-origin: border; - subcontrol-position: center right; -} - -QAbstractSpinBox:down-button -{ - background-color: transparent; - subcontrol-origin: border; - subcontrol-position: center left; -} - -QAbstractSpinBox::up-arrow,QAbstractSpinBox::up-arrow:disabled,QAbstractSpinBox::up-arrow:off { - image: url(%THISPATH%/qdarkstyle/up_arrow_disabled.png); - width: 10px; - height: 10px; -} -QAbstractSpinBox::up-arrow:hover -{ - image: url(%THISPATH%/qdarkstyle/up_arrow.png); -} - - -QAbstractSpinBox::down-arrow,QAbstractSpinBox::down-arrow:disabled,QAbstractSpinBox::down-arrow:off -{ - image: url(%THISPATH%/qdarkstyle/down_arrow_disabled.png); - width: 10px; - height: 10px; -} -QAbstractSpinBox::down-arrow:hover -{ - image: url(%THISPATH%/qdarkstyle/down_arrow.png); -} - - -QLabel -{ - background-color: transparent; /*fixes spyder #9120,#9121*/ -} - - -QTabWidget::pane { - border: 1px solid #3A3939; -} - -QTabBar -{ - qproperty-drawBase: 0; - padding-right: 15px; -} - -QTabBar:focus -{ - border: 0px transparent black; -} - -QTabBar::close-button { - image: url(%THISPATH%/qdarkstyle/close.png); - background: transparent; - icon-size: 10px; - padding: 5px; -} - -QTabBar::close-button:hover -{ - background: rgba(255, 255, 255, 20); - border-radius: 3px; -} - -QTabBar::close-button:pressed { - padding: 5px 4px 4px 5px; -} - -/* TOP - BOTTOM TABS */ -QTabBar::tab:top { - color: #b1b1b1; - border: 1px solid #3A3939; - background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, - stop:1 #302F2F, stop:0 #5A5959); - padding-left: 5px; - padding-right: 5px; - padding-top: 3px; - padding-bottom: 2px; - margin-right: -1px; - - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} - -QTabBar::tab:bottom { - color: #b1b1b1; - border: 1px solid #3A3939; - background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, - stop:1 #302F2F, stop:0 #5A5959); - padding-left: 5px; - padding-right: 5px; - padding-top: 3px; - padding-bottom: 2px; - margin-right: -1px; - - border-bottom-left-radius: 3px; - border-bottom-right-radius: 3px; -} - -QTabBar::tab:top:last, QTabBar::tab:bottom:last -{ - margin-right: 0; -} - -QTabBar::tab:top:first:!selected, QTabBar::tab:bottom:first:!selected -{ - margin-left: 0px; -} - -QTabBar::tab:top:!selected -{ - color: #b1b1b1; - margin-top: 3px; - background-color: #302F2F; -} - -QTabBar::tab:top:selected -{ - margin-bottom: 0px; -} - -QTabBar::tab:bottom:!selected -{ - color: #b1b1b1; - margin-bottom: 3px; - background-color: #302F2F; -} - -QTabBar::tab:bottom:selected -{ - margin-top: 0px; -} - -/* LEFT - RIGHT TABS */ -QTabBar::tab:left { - color: #b1b1b1; - border: 1px solid #3A3939; - background-color: QLinearGradient(x1:1, y1:0, x2:0, y2:0, - stop:1 #302F2F, stop:0 #5A5959); - padding-left: 3px; - padding-right: 2px; - padding-top: 5px; - padding-bottom: 5px; - margin-bottom: -1px; - - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} - -QTabBar::tab:right { - color: #b1b1b1; - border: 1px solid #3A3939; - background-color: QLinearGradient(x1:0, y1:0, x2:1, y2:0, - stop:1 #302F2F, stop:0 #5A5959); - padding-left: 3px; - padding-right: 2px; - padding-top: 5px; - padding-bottom: 5px; - margin-bottom: -1px; - - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; -} - -QTabBar::tab:left:!selected -{ - color: #b1b1b1; - margin-right: 3px; - background-color: #302F2F; -} - -QTabBar::tab:left:selected -{ - margin-left: 0px; -} - -QTabBar::tab:right:!selected -{ - color: #b1b1b1; - margin-left: 3px; - background-color: #302F2F; -} - -QTabBar::tab:right:selected -{ - margin-right: 0px; -} - -QTabBar QToolButton::right-arrow:enabled { - image: url(%THISPATH%/qdarkstyle/right_arrow.png); - } - - QTabBar QToolButton::left-arrow:enabled { - image: url(%THISPATH%/qdarkstyle/left_arrow.png); - } - -QTabBar QToolButton::right-arrow:disabled { - image: url(%THISPATH%/qdarkstyle/right_arrow_disabled.png); - } - - QTabBar QToolButton::left-arrow:disabled { - image: url(%THISPATH%/qdarkstyle/left_arrow_disabled.png); - } - - -QDockWidget { - border: 1px solid #403F3F; - titlebar-close-icon: url(%THISPATH%/qdarkstyle/close.png); - titlebar-normal-icon: url(%THISPATH%/qdarkstyle/undock.png); -} - -QDockWidget::close-button, QDockWidget::float-button { - border: 1px solid transparent; - border-radius: 3px; - background: transparent; - icon-size: 10px; -} - -QDockWidget::close-button:hover, QDockWidget::float-button:hover { - background: rgba(255, 255, 255, 10); -} - -QDockWidget::close-button:pressed, QDockWidget::float-button:pressed { - padding: 1px -1px -1px 1px; - background: rgba(255, 255, 255, 10); -} - -NewFriendList { - qproperty-textColorStatusAway: #4040A0; - qproperty-textColorStatusBusy: #A04040; - qproperty-textColorStatusOnline: #40A040; - qproperty-textColorStatusInactive: #A0A040; - qproperty-textColorStatusOffline: gray; - qproperty-textColorGroup: rgb(123, 123, 123); -} - -QTreeView, QListView -{ - border: 1px solid #78879b; - background-color: #201F1F; -} - -QTreeView::item { - background-color: #201F1F; -} - -QTreeView::item:selected { - color: black; -} - -RSTreeWidget#idTreeWidget::item:!selected { - color: #C0C0C0; -} - -NetworkDialog { - qproperty-backgroundColorSelf: darkred; - qproperty-backgroundColorOwnSign: darkred; - qproperty-backgroundColorAcceptConnection: black; - qproperty-backgroundColorHasSignedMe: darkred; - qproperty-backgroundColorDenied: #201F1F; -} - -QTreeView:branch:selected, QTreeView:branch:hover -{ - background: url(%THISPATH%/qdarkstyle/transparent.png); -} - -QTreeView::branch:has-siblings:!adjoins-item { - border-image: url(%THISPATH%/qdarkstyle/transparent.png); -} - -QTreeView::branch:has-siblings:adjoins-item { - border-image: url(%THISPATH%/qdarkstyle/transparent.png); -} - -QTreeView::branch:!has-children:!has-siblings:adjoins-item { - border-image: url(%THISPATH%/qdarkstyle/transparent.png); -} - -QTreeView::branch:has-children:!has-siblings:closed, -QTreeView::branch:closed:has-children:has-siblings { - image: url(%THISPATH%/qdarkstyle/branch_closed.png); -} - -QTreeView::branch:open:has-children:!has-siblings, -QTreeView::branch:open:has-children:has-siblings { - image: url(%THISPATH%/qdarkstyle/branch_open.png); -} - -QTreeView::branch:has-children:!has-siblings:closed:hover, -QTreeView::branch:closed:has-children:has-siblings:hover { - image: url(%THISPATH%/qdarkstyle/branch_closed-on.png); - } - -QTreeView::branch:open:has-children:!has-siblings:hover, -QTreeView::branch:open:has-children:has-siblings:hover { - image: url(%THISPATH%/qdarkstyle/branch_open-on.png); - } - -QListView::item:!selected:hover, QTableView::item:!selected:hover, QTreeView::item:!selected:hover { - background: rgba(0, 0, 0, 0); - outline: 0; - color: #FFFFFF; -} - -QListView::item:selected:hover, QTableView::item:selected:hover, QTreeView::item:selected:hover { - background: #78879b; - color: #FFFFFF; -} - -QSlider::groove:horizontal { - border: 1px solid #3A3939; - height: 8px; - background: #201F1F; - margin: 2px 0; - border-radius: 4px; -} - -QSlider::handle:horizontal { - background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0.0 silver, stop: 0.2 #a8a8a8, stop: 1 #727272); - border: 1px solid #3A3939; - width: 14px; - height: 14px; - margin: -4px 0; - border-radius: 7px; -} - -QSlider::groove:vertical { - border: 1px solid #3A3939; - width: 8px; - background: #201F1F; - margin: 0 0px; - border-radius: 4px; -} - -QSlider::handle:vertical { - background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0.0 silver, - stop: 0.2 #a8a8a8, stop: 1 #727272); - border: 1px solid #3A3939; - width: 14px; - height: 14px; - margin: 0 -4px; - border-radius: 7px; -} - -QToolButton { - background-color: transparent; - border: 1px solid #3A3939; - border-radius: 3px; - margin: 3px; -} - -QToolButton:pressed, QToolButton::menu-button:pressed { - background-color: #4A4949; - border: 1px solid silver; -} - -QToolButton:hover, QToolButton::menu-button:hover { - background-color: #4A4949; - border: 1px solid gray; -} - -QToolButton[popupMode="1"] { /* only for MenuButtonPopup */ - padding-right: 20px; /* make way for the popup button */ -} - -QToolButton[popupMode="2"] { /* only for MenuButtonPopup */ - padding-right: 10px; /* make way for the popup button */ -} - -/* the subcontrols below are used only in the MenuButtonPopup mode */ -QToolButton::menu-button { - border: 1px solid #3A3939; - border-top-right-radius: 6px; - border-bottom-right-radius: 6px; - /* 16px width + 4px for border = 20px allocated above */ - width: 16px; -} - -QToolButton::menu-arrow { - image: url(%THISPATH%/qdarkstyle/down_arrow.png); -} - -QToolButton::menu-arrow:open { - top: 1px; left: 1px; /* shift it a bit */ -} - -QPushButton::menu-indicator { - subcontrol-origin: padding; - subcontrol-position: bottom right; - -} - -QTableView -{ - border: transparent; - gridline-color: #6c6c6c; - background-color: #201F1F; -} - - -QTableView, QHeaderView -{ - border-radius: 0px; -} - -QTableView::item:pressed, QListView::item:pressed, QTreeView::item:pressed { - background: #78879b; - color: #FFFFFF; -} - -QTableView::item:selected:active, QTreeView::item:selected:active, QListView::item:selected:active { - background: #78879b; - color: #FFFFFF; -} - - -QHeaderView -{ - border: 1px transparent; - margin: 0px; - padding: 0px; -} - -QHeaderView::section { - background-color: #3A3939; - color: silver; - padding: 4px; - border: 1px solid #6c6c6c; - border-radius: 0px; - text-align: center; -} - -QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one -{ - border-top: 1px solid #6c6c6c; -} - -QHeaderView::section::vertical -{ - border-top: transparent; -} - -QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one -{ - border-left: 1px solid #6c6c6c; -} - -QHeaderView::section::horizontal -{ - border-left: transparent; -} - - -QHeaderView::section:checked - { - color: white; - background-color: #5A5959; - } - - /* style the sort indicator */ -QHeaderView::down-arrow { - image: url(%THISPATH%/qdarkstyle/down_arrow.png); -} - -QHeaderView::up-arrow { - image: url(%THISPATH%/qdarkstyle/up_arrow.png); -} - - -QTableCornerButton::section { - background-color: #3A3939; - border: 1px solid #3A3939; - border-radius: 0px; -} - -QToolBox::tab { - background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, - stop:1 #302F2F, stop:0 #5A5959); - padding-left: 3px; - padding-right: 2px; - padding-top: 5px; - padding-bottom: 5px; - margin-bottom: -1px; - - border-top-left-radius: 3px; - border-top-right-radius: 3px; - color: darkgray; - } - - QToolBox::tab:selected { /* italicize selected tabs */ - font: italic bold; - color: white; - } - -QStatusBar::item { - border: 1px solid #3A3939; - border-radius: 3px; - } - -/* OpModeStatus need to be at end to overload other values*/ -OpModeStatus { - qproperty-opMode_Full_Color: #007000; - qproperty-opMode_NoTurtle_Color: #000070; - qproperty-opMode_Gaming_Color: #707000; - qproperty-opMode_Minimal_Color: #700000; -} -OpModeStatus[opMode="Full"] { - background: #007000; -} -OpModeStatus[opMode="NoTurtle"] { - background: #000070; -} -OpModeStatus[opMode="Gaming"] { - background: #707000; -} -OpModeStatus[opMode="Minimal"] { - background: #700000; -} - -/*Property Values at end to overwrite other settings*/ - -[new=false] { - background: #202020; -} -[new=true] { - background: #005000; -} - -[WrongValue="true"] { - background-color: #702020; -} - -/* changes for the subscribe Button */ - -PostedListWidgetWithModel QToolButton#subscribeToolButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; -} - -PostedListWidgetWithModel QToolButton#subscribeToolButton:hover { - background: #03b1f3; - border-radius: 4px; -} - -GxsForumThreadWidget QToolButton#subscribeToolButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; -} - -GxsForumThreadWidget QToolButton#subscribeToolButton:hover { - background: #03b1f3; - border-radius: 4px; -} - -GxsForumThreadWidget QWidget#threadTreeWidget { - selection-background-color: #445566; - show-decoration-selected: 1; -} - -GxsForumThreadWidget QWidget#threadTreeWidget::item { - padding: 2px; -} - -GxsForumThreadWidget QWidget#threadTreeWidget::item:selected:active , -GxsForumThreadWidget QWidget#threadTreeWidget::item:selected:!active { - background-color: #445566; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton:hover { - background: #03b1f3; - border-radius: 4px; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton:pressed { - background: #03b1f3; - border-radius: 4px; - border: 1px solid gray; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton:disabled { - background: gray; - border-radius: 4px; - border: 1px solid gray; - color: lightgray; -} - -/* only for MenuButtonPopup */ -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton[popupMode="1"] { - padding-right: 0px; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton::menu-arrow { - image: none; -} - -GxsChannelPostsWidgetWithModel QToolButton#subscribeToolButton::menu-button { - image: none; - -} - -GxsChannelPostItem QFrame#mainFrame { - background: #302F2F; -} - -GxsChannelPostItem > QFrame#mainFrame [new=false]{ - background: #302F2F; -} - -GxsChannelPostItem > QFrame#mainFrame[new=true] { - background-color: #005000; -} - -GxsChannelPostItem QLabel#subjectLabel, GxsChannelPostItem QLabel#titleLabel { - font: 12pt; - font: bold italic; -} - -CreateGxsChannelMsg QPushButton#postButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -CreateGxsChannelMsg QPushButton#postButton:hover { - background: #03b1f3; - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - -CreateCircleDialog QPushButton#createButton, CreateLobbyDialog QPushButton#createButton, -IdEditDialog QPushButton#createButton, CreateGxsForumMsg QPushButton#postButton, -GxsCreateCommentDialog QPushButton#postButton, GxsGroupDialog QPushButton#createButton, -PulseAddDialog QPushButton#pushButton_Post, PulseTopLevel QToolButton#toolButton_follow, -PulseViewGroup QToolButton#toolButton_follow { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 20px; - min-width: 4em; - padding: 2px; - padding-left: 6px; - padding-right: 6px; -} - -CreateCircleDialog QPushButton#createButton:hover, CreateLobbyDialog QPushButton#createButton:hover, -IdEditDialog QPushButton#createButton:hover, CreateGxsForumMsg QPushButton#postButton:hover, -GxsCreateCommentDialog QPushButton#postButton:hover, GxsGroupDialog QPushButton#createButton:hover, -ShareManager QPushButton#closeButton:hover, PulseAddDialog QPushButton#pushButton_Post:hover, -PulseTopLevel QToolButton#toolButton_follow:hover, PulseViewGroup QToolButton#toolButton_follow:hover{ - background: #03b1f3; - border-radius: 4px; - min-width: 4em; - padding-left: 6px; - padding-right: 6px; -} - -CreateGxsForumMsg QPushButton#postButton:disabled, PostedCreatePostDialog QPushButton#submitButton:disabled, -CreateGxsChannelMsg QPushButton#postButton:disabled, GxsCreateCommentDialog QPushButton#postButton:disabled, -PulseAddDialog QPushButton#pushButton_Post:disabled { - font: bold; - font-size: 12pt; - color: white; - background: #d40000; - border-radius: 4px; - max-height: 20px; - min-width: 4em; - padding: 2px; - padding-left: 6px; - padding-right: 6px; -} - -ShareManager QPushButton#closeButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; - padding-left: 6px; - padding-right: 6px; -} - -ShareManager QPushButton#addButton { - font: bold; - font-size: 12pt; - color: white; - background: #32CD32; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 4px; -} - -ShareManager QPushButton#addButton:hover { - background: #5AD75A; - border-radius: 4px; - min-width: 4em; - padding: 4px; -} - -QTabBar#smTab::tab{ - height: 32px; - width: 32px; -} - -QLabel#avatarLabel{ - border: 2px solid #CCCCCC; - border-radius: 4px; -} - -PostedCreatePostDialog QPushButton#submitButton { - font: bold; - font-size: 12pt; - color: white; - background: #0099cc; - border-radius: 4px; - min-width: 2em; - -} - -PostedCreatePostDialog QPushButton#submitButton:hover { - background: #03b1f3; - border-radius: 4px; - min-width: 2em; - -} - -GxsForumThreadWidget QPushButton#forumName -{ - qproperty-fontSizeFactor: 140; - color: #0099cc; - font-size: 14pt; - font: bold; -} - -GxsForumMsgItem QFrame#frame{ - background: #302F2F; -} - -PostedItem QFrame#mainFrame{ - background: #302F2F; -} - -BoardPostDisplayWidget_compact QPushButton#shareButton -{ - background-color: transparent; - border: none; - min-width: 75px; - max-height: 22px; -} - -BoardPostDisplayWidget_card QPushButton#shareButton -{ - background-color: transparent; - border: none; - min-width: 75px; -} - -BoardPostDisplayWidget_compact QFrame#voteFrame { - background: #141415; -} - -BoardPostDisplayWidget_card QFrame#voteFrame { - background: #141415; -} - -QPushButton#shareButton:hover, QPushButton#shareButton::menu-button:hover { - background-color: #4A4949; - border: 1px solid gray; -} - -BoardPostDisplayWidget_compact QToolButton#voteDownButton, QToolButton#voteUpButton, QToolButton#expandButton, QToolButton#readButton, -QToolButton#commentButton, QToolButton#notesButton -{ - border: none; -} - -BoardPostDisplayWidget_compact QLabel#pictureLabel{ - border: 2px solid #CCCCCC; - border-radius: 3px; -} - -BoardPostDisplayWidget_compact > QFrame#frame [new=false]{ - background: #302F2F; -} - -BoardPostDisplayWidget_compact > QFrame#frame[new=true] { - background-color: #005000; -} - -BoardPostDisplayWidget_card QToolButton#voteDownButton, QToolButton#voteUpButton -{ - border: none; -} - -BoardPostDisplayWidget_card QFrame#frame{ - background: #302F2F; -} - -BoardPostDisplayWidget_card > QFrame#frame [new=false]{ - background: #302F2F; -} - -BoardPostDisplayWidget_card > QFrame#frame[new=true] { - background-color: #005000; -} - -BoardPostDisplayWidget_compact QLabel#newLabel { - border: 1px solid #00B712; - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5AFF15, stop: 1 #00B712); - border-radius: 3px; - color: black; -} - -BoardPostDisplayWidget_card QLabel#newLabel { - border: 1px solid #00B712; - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5AFF15, stop: 1 #00B712); - border-radius: 3px; - color: black; -} - -BoardPostDisplayWidget_compact QLabel#titleLabel, -BoardPostDisplayWidget_card QLabel#titleLabel{ - font-size: 12pt; - font: bold; -} - -WireGroupItem QFrame#wire_frame -{ - border: 1px solid #38444d; - background: transparent; -} - -PulseReply #line_replyLine , PulseMessage #line{ - color: #38444d; -} - -RSTextBrowser, MimeTextEdit -{ - /*qproperty-textColorQuote: rgb(125, 125, 255);*/ - qproperty-textColorQuotes: ColorList(#789922 #039bd5 #800000 #800080 #008080 #b10dc9 #85144b #3d9970); -} - -PulseTopLevel QFrame#frame, PulseViewGroup QFrame#frame, PulseReply QFrame#frame { - border: 2px solid #38444d; - border-radius: 6px; -} - -MainWindow QListWidget { - font-size: 12pt; -} - -PhotoShare QPushButton#pushButton_YourAlbums, QPushButton#pushButton_SubscribedAlbums, -QPushButton#pushButton_SharedAlbums { - font-size: 12pt; -} - -PhotoItem QFrame#photoFrame{ - border: 2px solid #3A3939; -} - -AlbumItem QFrame#albumFrame { - border: 2px solid #3A3939; - border-radius: 10px -} - -ChannelsCommentsItem QFrame#mainFrame, BoardsCommentsItem QFrame#mainFrame { - background: #302F2F; -} - -ChannelsCommentsItem QLabel#newCommentLabel, BoardsCommentsItem QLabel#newCommentLabel { - font: 12pt; - font: bold; -} - -ChannelsCommentsItem QLabel#subjectLabel, ChannelsCommentsItem QLabel#titleLabel , QLabel#nameLabel { - font: 12pt; - font: bold; -} - -BoardsCommentsItem QLabel#subjectLabel, QLabel#titleLabel , QLabel#nameLabel { - font: 12pt; - font: bold; -} - -HomePage QToolButton#addButton { - font: bold; - font-size: 15pt; - color: white; - background: #0099cc; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -HomePage QToolButton#addButton:hover { - background: #03b1f3; - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - -NewFriendList QTreeView#peerTreeWidget { - font-size: 12pt; -} diff --git a/retroshare-gui/src/qss/qdarkstyle/Hmovetoolbar.png b/retroshare-gui/src/qss/qdarkstyle/Hmovetoolbar.png deleted file mode 100644 index 520c3aac3..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/Hmovetoolbar.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/Hsepartoolbar.png b/retroshare-gui/src/qss/qdarkstyle/Hsepartoolbar.png deleted file mode 100644 index 401bfb40a..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/Hsepartoolbar.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/Vmovetoolbar.png b/retroshare-gui/src/qss/qdarkstyle/Vmovetoolbar.png deleted file mode 100644 index 512edcecd..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/Vmovetoolbar.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/Vsepartoolbar.png b/retroshare-gui/src/qss/qdarkstyle/Vsepartoolbar.png deleted file mode 100644 index d9dc1561b..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/Vsepartoolbar.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/branch_closed-on.png b/retroshare-gui/src/qss/qdarkstyle/branch_closed-on.png deleted file mode 100644 index d081e9b3b..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/branch_closed-on.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/branch_closed.png b/retroshare-gui/src/qss/qdarkstyle/branch_closed.png deleted file mode 100644 index d652159a3..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/branch_closed.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/branch_open-on.png b/retroshare-gui/src/qss/qdarkstyle/branch_open-on.png deleted file mode 100644 index ec372b27d..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/branch_open-on.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/branch_open.png b/retroshare-gui/src/qss/qdarkstyle/branch_open.png deleted file mode 100644 index 66f8e1ac6..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/branch_open.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/checkbox.png b/retroshare-gui/src/qss/qdarkstyle/checkbox.png deleted file mode 100644 index b4a9aa3b5..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/checkbox.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/close.png b/retroshare-gui/src/qss/qdarkstyle/close.png deleted file mode 100644 index ffdec9a14..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/close.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/down_arrow.png b/retroshare-gui/src/qss/qdarkstyle/down_arrow.png deleted file mode 100644 index e271f7f90..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/down_arrow.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/down_arrow_disabled.png b/retroshare-gui/src/qss/qdarkstyle/down_arrow_disabled.png deleted file mode 100644 index 5805d9842..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/down_arrow_disabled.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/left_arrow.png b/retroshare-gui/src/qss/qdarkstyle/left_arrow.png deleted file mode 100644 index f808d2d72..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/left_arrow.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/left_arrow_disabled.png b/retroshare-gui/src/qss/qdarkstyle/left_arrow_disabled.png deleted file mode 100644 index f5b9af8a3..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/left_arrow_disabled.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/Hmovetoolbar.png b/retroshare-gui/src/qss/qdarkstyle/rc/Hmovetoolbar.png deleted file mode 100644 index cead99ed1..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/Hmovetoolbar.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/Hsepartoolbar.png b/retroshare-gui/src/qss/qdarkstyle/rc/Hsepartoolbar.png deleted file mode 100644 index 7f183c8b3..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/Hsepartoolbar.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/Vmovetoolbar.png b/retroshare-gui/src/qss/qdarkstyle/rc/Vmovetoolbar.png deleted file mode 100644 index ac6a655e2..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/Vmovetoolbar.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/Vsepartoolbar.png b/retroshare-gui/src/qss/qdarkstyle/rc/Vsepartoolbar.png deleted file mode 100644 index 7bf62f168..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/Vsepartoolbar.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/branch_closed-on.png b/retroshare-gui/src/qss/qdarkstyle/rc/branch_closed-on.png deleted file mode 100644 index d081e9b3b..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/branch_closed-on.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/branch_closed.png b/retroshare-gui/src/qss/qdarkstyle/rc/branch_closed.png deleted file mode 100644 index d652159a3..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/branch_closed.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/branch_open-on.png b/retroshare-gui/src/qss/qdarkstyle/rc/branch_open-on.png deleted file mode 100644 index ec372b27d..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/branch_open-on.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/branch_open.png b/retroshare-gui/src/qss/qdarkstyle/rc/branch_open.png deleted file mode 100644 index 66f8e1ac6..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/branch_open.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked.png deleted file mode 100644 index 4007c2ed3..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked@2x.png deleted file mode 100644 index b9c3204f1..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked_disabled.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked_disabled.png deleted file mode 100644 index 4762561b3..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked_disabled.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked_disabled@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked_disabled@2x.png deleted file mode 100644 index 98bf5470c..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked_disabled@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked_focus.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked_focus.png deleted file mode 100644 index 91cb16c9f..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked_focus.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked_focus@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked_focus@2x.png deleted file mode 100644 index 04b3bb514..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_checked_focus@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate.png deleted file mode 100644 index 6b846365c..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate@2x.png deleted file mode 100644 index baa502017..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate_disabled.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate_disabled.png deleted file mode 100644 index 435048a08..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate_disabled.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate_disabled@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate_disabled@2x.png deleted file mode 100644 index 3e7f76c7c..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate_disabled@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate_focus.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate_focus.png deleted file mode 100644 index 4bf4d53c1..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate_focus.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate_focus@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate_focus@2x.png deleted file mode 100644 index 1f5cb3e88..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_indeterminate_focus@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked.png deleted file mode 100644 index 54044babf..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked@2x.png deleted file mode 100644 index 1259a9841..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked_disabled.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked_disabled.png deleted file mode 100644 index 75f049024..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked_disabled.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked_disabled@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked_disabled@2x.png deleted file mode 100644 index e4ecef9d5..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked_disabled@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked_focus.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked_focus.png deleted file mode 100644 index 5b0a18f01..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked_focus.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked_focus@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked_focus@2x.png deleted file mode 100644 index 14bec86c2..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/checkbox_unchecked_focus@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/close-hover.png b/retroshare-gui/src/qss/qdarkstyle/rc/close-hover.png deleted file mode 100644 index fdbaf9bf0..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/close-hover.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/close-pressed.png b/retroshare-gui/src/qss/qdarkstyle/rc/close-pressed.png deleted file mode 100644 index 9b243bfe8..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/close-pressed.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/close.png b/retroshare-gui/src/qss/qdarkstyle/rc/close.png deleted file mode 100644 index 89407de72..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/close.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/down_arrow.png b/retroshare-gui/src/qss/qdarkstyle/rc/down_arrow.png deleted file mode 100644 index e271f7f90..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/down_arrow.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/down_arrow_disabled.png b/retroshare-gui/src/qss/qdarkstyle/rc/down_arrow_disabled.png deleted file mode 100644 index 5805d9842..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/down_arrow_disabled.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/left_arrow.png b/retroshare-gui/src/qss/qdarkstyle/rc/left_arrow.png deleted file mode 100644 index f808d2d72..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/left_arrow.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/left_arrow_disabled.png b/retroshare-gui/src/qss/qdarkstyle/rc/left_arrow_disabled.png deleted file mode 100644 index f5b9af8a3..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/left_arrow_disabled.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked.png b/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked.png deleted file mode 100644 index 368acce58..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked@2x.png deleted file mode 100644 index b5f5eed9b..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked_disabled.png b/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked_disabled.png deleted file mode 100644 index 73ff735f2..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked_disabled.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked_disabled@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked_disabled@2x.png deleted file mode 100644 index 827e5928b..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked_disabled@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked_focus.png b/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked_focus.png deleted file mode 100644 index ad6d2cf82..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked_focus.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked_focus@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked_focus@2x.png deleted file mode 100644 index 7e5930563..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/radio_checked_focus@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked.png b/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked.png deleted file mode 100644 index 82f2abb8c..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked@2x.png deleted file mode 100644 index 793719b3b..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked_disabled.png b/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked_disabled.png deleted file mode 100644 index 5c54ee9df..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked_disabled.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked_disabled@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked_disabled@2x.png deleted file mode 100644 index d50153d1d..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked_disabled@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked_focus.png b/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked_focus.png deleted file mode 100644 index f42d85c7f..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked_focus.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked_focus@2x.png b/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked_focus@2x.png deleted file mode 100644 index 0927b4959..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/radio_unchecked_focus@2x.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/right_arrow.png b/retroshare-gui/src/qss/qdarkstyle/rc/right_arrow.png deleted file mode 100644 index 9b0a4e6a7..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/right_arrow.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/right_arrow_disabled.png b/retroshare-gui/src/qss/qdarkstyle/rc/right_arrow_disabled.png deleted file mode 100644 index 5c0bee402..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/right_arrow_disabled.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/sizegrip.png b/retroshare-gui/src/qss/qdarkstyle/rc/sizegrip.png deleted file mode 100644 index 350583aaa..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/sizegrip.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/stylesheet-branch-end.png b/retroshare-gui/src/qss/qdarkstyle/rc/stylesheet-branch-end.png deleted file mode 100644 index cb5d3b51f..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/stylesheet-branch-end.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/stylesheet-branch-more.png b/retroshare-gui/src/qss/qdarkstyle/rc/stylesheet-branch-more.png deleted file mode 100644 index 62711409d..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/stylesheet-branch-more.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/stylesheet-vline.png b/retroshare-gui/src/qss/qdarkstyle/rc/stylesheet-vline.png deleted file mode 100644 index 87536cce1..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/stylesheet-vline.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/transparent.png b/retroshare-gui/src/qss/qdarkstyle/rc/transparent.png deleted file mode 100644 index 483df2513..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/transparent.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/undock.png b/retroshare-gui/src/qss/qdarkstyle/rc/undock.png deleted file mode 100644 index 58cde37b8..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/undock.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/up_arrow.png b/retroshare-gui/src/qss/qdarkstyle/rc/up_arrow.png deleted file mode 100644 index abcc72452..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/up_arrow.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/rc/up_arrow_disabled.png b/retroshare-gui/src/qss/qdarkstyle/rc/up_arrow_disabled.png deleted file mode 100644 index b9c8e3b53..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/rc/up_arrow_disabled.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/right_arrow.png b/retroshare-gui/src/qss/qdarkstyle/right_arrow.png deleted file mode 100644 index 9b0a4e6a7..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/right_arrow.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/right_arrow_disabled.png b/retroshare-gui/src/qss/qdarkstyle/right_arrow_disabled.png deleted file mode 100644 index 5c0bee402..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/right_arrow_disabled.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/sizegrip.png b/retroshare-gui/src/qss/qdarkstyle/sizegrip.png deleted file mode 100644 index 350583aaa..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/sizegrip.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/stylesheet-branch-end.png b/retroshare-gui/src/qss/qdarkstyle/stylesheet-branch-end.png deleted file mode 100644 index cb5d3b51f..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/stylesheet-branch-end.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/stylesheet-branch-more.png b/retroshare-gui/src/qss/qdarkstyle/stylesheet-branch-more.png deleted file mode 100644 index 62711409d..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/stylesheet-branch-more.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/stylesheet-vline.png b/retroshare-gui/src/qss/qdarkstyle/stylesheet-vline.png deleted file mode 100644 index 87536cce1..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/stylesheet-vline.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/transparent.png b/retroshare-gui/src/qss/qdarkstyle/transparent.png deleted file mode 100644 index 483df2513..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/transparent.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/undock.png b/retroshare-gui/src/qss/qdarkstyle/undock.png deleted file mode 100644 index 804547aed..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/undock.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/up_arrow.png b/retroshare-gui/src/qss/qdarkstyle/up_arrow.png deleted file mode 100644 index abcc72452..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/up_arrow.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qdarkstyle/up_arrow_disabled.png b/retroshare-gui/src/qss/qdarkstyle/up_arrow_disabled.png deleted file mode 100644 index b9c8e3b53..000000000 Binary files a/retroshare-gui/src/qss/qdarkstyle/up_arrow_disabled.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qlive.qss b/retroshare-gui/src/qss/qlive.qss deleted file mode 100644 index d7df00f76..000000000 --- a/retroshare-gui/src/qss/qlive.qss +++ /dev/null @@ -1,141 +0,0 @@ -.QWidget{ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #77AEF1, stop: 0.4 #86BBF7); -} - -QDialog{ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #77AEF1, stop: 0.4 #86BBF7); -} - -QFrame#titleBarFrame, QFrame#toolBarFrame { - - border-image: url(%THISPATH%/qlive/qb.png); -} - -HeaderFrame { - background-image: url(:/images/headerFrame.png); - border: 0px; -} - -/* Customize the toolbar. */ -QToolBar#toolBarAction { - border-image: url(%THISPATH%/qlive/qb.png); - -} - -QToolBar#toolBarPage { - border-image: url(%THISPATH%/qlive/qb.png); - -} - -QToolBar#chattoolBar{ - border-image: url(%THISPATH%/qlive/qb.png); - -} - -QMenu { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #77AEF1, stop: 0.4 #86BBF7); - - border: 1px solid black; - } - -QMenu::item:selected { /* when user selects item using mouse or keyboard */ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F6F9FA, stop: 1 #C6D3E5); -} - -QListWidget::item:selected { /* when user selects item using mouse or keyboard */ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F6F9FA, stop: 1 #C6D3E5); -} -QTreeWidget { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #77AEF1, stop: 0.4 #86BBF7); - - } - - -QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F6F9FA, stop: 1 #C6D3E5); - -} - -QTreeView::item:selected { /* when user selects item using mouse or keyboard */ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F6F9FA, stop: 1 #C6D3E5); - -} - -QFrame#messengerframetop{ - - border-image: url(%THISPATH%/qlive/qb.png); - -} - -QFrame#Chatbuttonframe{ - - border-image: url(%THISPATH%/qlive/qb.png); - -} - -QLabel#subjectText{ - font: bold 12px; - -} - -QLabel#subjectlabel{ - font: bold 12px; - -} - -QLabel#fromlabel{ - font: bold 12px; - -} - -QLabel#datelabel{ - font: bold 12px; - -} - -QLabel#tolabel{ - font: bold 12px; - -} - -QLabel#fromText{ - font: bold ; - color: blue; - -} -QStatusBar{ - border-image: url(%THISPATH%/qlive/qb.png); -} - -HomePage QToolButton#addButton { - font: bold; - font-size: 15pt; - color: white; - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #77AEF1, stop: 0.4 #86BBF7); - border: 1px solid #86BBF7; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -HomePage QToolButton#addButton:hover { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #7fb0ec, stop: 1 #90a1e2); - border: 1px solid #90a1e2; - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - -MainWindow QListWidget { - font-size: 12pt; -} \ No newline at end of file diff --git a/retroshare-gui/src/qss/qlive/qb.png b/retroshare-gui/src/qss/qlive/qb.png deleted file mode 100644 index cde1a8588..000000000 Binary files a/retroshare-gui/src/qss/qlive/qb.png and /dev/null differ diff --git a/retroshare-gui/src/qss/qlive/qb2.png b/retroshare-gui/src/qss/qlive/qb2.png deleted file mode 100644 index abd2f0b74..000000000 Binary files a/retroshare-gui/src/qss/qlive/qb2.png and /dev/null differ diff --git a/retroshare-gui/src/qss/redscorpion.qss b/retroshare-gui/src/qss/redscorpion.qss deleted file mode 100644 index d0fb8d0ed..000000000 --- a/retroshare-gui/src/qss/redscorpion.qss +++ /dev/null @@ -1,321 +0,0 @@ -.QWidget { - background-color: #3E1716; -} - -QFrame#titleBarFrame, QFrame#toolBarFrame { - - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F55332, stop: 0.5 #C82B18, - stop: 0.51 #B71502, stop: 1 #900907); - border: 1px solid #7A3C37; -} - - -QDialog{ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 red, stop: 1 darkred); -} - -HeaderFrame { - background-image: url(:/images/headerFrame.png); - border: 0px; -} - -/* Customize the toolbar. */ -QToolBar#toolBarPage { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F55332, stop: 0.5 #C82B18, - stop: 0.51 #B71502, stop: 1 #900907); - border: 1px solid #7A3C37; - -} - -QToolBar#toolBarAction { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F55332, stop: 0.5 #C82B18, - stop: 0.51 #B71502, stop: 1 #900907); - border: 1px solid #7A3C37; - - -} - -QToolBar#chattoolBar{ - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F55332, stop: 0.5 #C82B18, - stop: 0.51 #B71502, stop: 1 #900907); - border: 1px solid #7A3C37; - -} - - -/* it works only at the moment with vista Thema on XP*/ -QToolButton::hover { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #FFD200, stop: 1 #FF6400); - - -} - -QToolButton::pressed { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #FFD200, stop: 1 #FF6400); - - -} - -QPushButton { - /* background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 red, stop: 1 darkred);*/ -} - -QPushButton#okButton { - min-height: 27px; - min-width: 77px; -} - -QPushButton#cancelprefButton { - min-height: 27px; - min-width: 77px; -} - -QPushButton#cancelButton { - min-height: 25px; - max-height: 25px; - min-width: 75px; -} - - -QPushButton#applyButton { - - min-height: 25px; - max-height: 25px; - min-width: 75px; -} - -QToolButton { - color: black; -} - - QTabWidget::tab-bar { - left: 0px; /* move to the right by 5px */ - } - - /* Style the tab using the tab sub-control. Note that - it reads QTabBar _not_ QTabWidget */ - QTabBar::tab { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 red, stop: 1 darkred); - border: 2px solid #C4C4C3; - border-bottom-color: #C2C7CB; /* same as the pane color */ - border-top-left-radius: 4px; - border-top-right-radius: 4px; - min-width: 8ex; - padding: 2px; - } - - QTabBar::tab:selected, QTabBar::tab:hover { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 darkred, stop: 1 red); - } - - QTabBar::tab:selected { - border-color: #9B9B9B; - border-bottom-color: #C2C7CB; /* same as pane color */ - } - - QTabBar::tab:!selected { - margin-top: 2px; /* make non-selected tabs look smaller */ - } - -QStatusBar{ - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F55332, stop: 0.5 #C82B18, - stop: 0.51 #B71502, stop: 1 #900907); - border: 1px solid #7A3C37; - -} - -QToolTip{ - background-color: darkred; -} - -QMenu { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 red, stop: 1 darkred); - border: 1px solid black; - } - -QMenu::item { - /* sets background of menu item. set this to something non-transparent - if you want menu color and menu item color to be different */ - background-color: transparent; - } - -QMenu::item:selected { /* when user selects item using mouse or keyboard */ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #FFD200, stop: 1 #FF6400); - } - -QListWidget::item:selected { /* when user selects item using mouse or keyboard */ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 red, stop: 1 darkred); -} - -QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 red, stop: 1 darkred); -} - -QTreeView::item:selected { /* when user selects item using mouse or keyboard */ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 red, stop: 1 darkred); - -} - -QFrame#messengerframetop{ - - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F55332, stop: 0.5 #C82B18, - stop: 0.51 #B71502, stop: 1 #900907); - border: 1px solid #7A3C37; -} - -QFrame#Chatbuttonframe{ - - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F55332, stop: 0.5 #C82B18, - stop: 0.51 #B71502, stop: 1 #900907); - border: 1px solid #7A3C37; - -} - -QFrame#frame_2{ - border-image: url(%THISPATH%/redscorpion/red.png); - - -border: 1px solid #CCCCCC; -} - -QFrame#buttonframe{ - border-image: url(%THISPATH%/redscorpion/red.png); - - -border: 1px solid #CCCCCC; -} - -QFrame#frame{ - border-image: url(%THISPATH%/redscorpion/red.png); - - border: 1px solid #CCCCCC; -} - -QFrame#chheaderframe{ - border-image: url(%THISPATH%/redscorpion/red.png); - - -border: 1px solid #CCCCCC; -} - - -QLabel#subjectText{ - font: bold 12px; - -} - -QLabel#subjectlabel{ - font: bold 12px; - -} - -QLabel#fromlabel{ - font: bold 12px; - -} - -QLabel#datelabel{ - font: bold 12px; - -} - -QLabel#tolabel{ - font: bold 12px; - -} - -QLabel#fromText{ - font: bold ; - color: blue; - -} - -QLabel#infolabel{ - color: darkred; -} - -QLabel#friendstitlellabel{ - color: black; -} - -QLabel#networklabel{ - color: black; -} - -QLabel#labeltext{ - color: black; -} - -QRadioButton{ - color: white; -} - -QLabel{ - - color: white; -} - -QLabel#forumName{ - border: 2px solid red; - border-radius: 10px; - background: white; - color: black; -} - -QLabel#threadTitle{ - border: 2px solid red; - border-radius: 10px; - background: white; - color: black; -} - -HomePage QToolButton#addButton { - font: bold; - font-size: 15pt; - color: white; - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F55332, stop: 0.5 #C82B18, - stop: 0.51 #B71502, stop: 1 #900907); - border: 1px solid #7A3C37; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -HomePage QToolButton#addButton:hover { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F55332, stop: 0.5 #C82B18, - stop: 0.51 #ca1b06, stop: 1 #ac0c0a); - border: 1px solid #7A3C37; - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - -MainWindow QListWidget { - font-size: 12pt; -} - -MainWindow QToolButton { - color: white; -} diff --git a/retroshare-gui/src/qss/redscorpion/red.png b/retroshare-gui/src/qss/redscorpion/red.png deleted file mode 100644 index 8c2246cdb..000000000 Binary files a/retroshare-gui/src/qss/redscorpion/red.png and /dev/null differ diff --git a/retroshare-gui/src/qss/redscorpion/red2.png b/retroshare-gui/src/qss/redscorpion/red2.png deleted file mode 100644 index 0b2a36121..000000000 Binary files a/retroshare-gui/src/qss/redscorpion/red2.png and /dev/null differ diff --git a/retroshare-gui/src/qss/retroclassic.qss b/retroshare-gui/src/qss/retroclassic.qss new file mode 100644 index 000000000..eea7fdf25 --- /dev/null +++ b/retroshare-gui/src/qss/retroclassic.qss @@ -0,0 +1,192 @@ +/* QTreeView QListView QTableView ----------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtreeview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview + +--------------------------------------------------------------------------- */ +QTreeView:branch:selected, QTreeView:branch:hover { + background: url(":/standard_light/rc/transparent.png"); +} + +QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings { + border-image: none; + image: url(":/standard_light/rc/branch_closed.png"); +} + +QTreeView:branch:open:has-children:!has-siblings, QTreeView:branch:open:has-children:has-siblings { + border-image: none; + image: url(":/standard_light/rc/branch_open.png"); +} + +QTreeView:branch:has-children:!has-siblings:closed:hover, QTreeView:branch:closed:has-children:has-siblings:hover { + image: url(":/standard_light/rc/branch_closed_focus.png"); +} + +QTreeView:branch:open:has-children:!has-siblings:hover, QTreeView:branch:open:has-children:has-siblings:hover { + image: url(":/standard_light/rc/branch_open_focus.png"); +} + +QTreeView::indicator:checked { + image: url(":/standard_light/rc/checkbox_checked.png"); +} + +QTreeView::indicator:checked:hover, +QTreeView::indicator:checked:focus, +QTreeView::indicator:checked:pressed { + image: url(":/standard_light/rc/checkbox_checked_focus.png"); +} + +QTreeView::indicator:unchecked { + image: url(":/standard_light/rc/checkbox_unchecked.png"); +} + +QTreeView::indicator:unchecked:hover, +QTreeView::indicator:unchecked:focus, +QTreeView::indicator:unchecked:pressed { + image: url(":/standard_light/rc/checkbox_unchecked_focus.png"); +} + +QTreeView, +QListView, +QTableView, +QColumnView { + background-color: #FAFAFA; + border: 1px solid #C9CDD0; + color: #19232D; + gridline-color: #C9CDD0; + border-radius: 4px; +} + +QTreeView:disabled, +QListView:disabled, +QTableView:disabled, +QColumnView:disabled { + background-color: #FAFAFA; + color: #788D9C; +} + +QTreeView:selected, +QListView:selected, +QTableView:selected, +QColumnView:selected { + background-color: #9FCBFF; + color: #C9CDD0; +} + +QTreeView:focus, +QListView:focus, +QTableView:focus, +QColumnView:focus { + border: 1px solid #73C7FF; +} + +QTreeView::item:pressed, +QListView::item:pressed, +QTableView::item:pressed, +QColumnView::item:pressed { + background-color: #9FCBFF; +} + +QTreeView::item:selected:active, +QListView::item:selected:active, +QTableView::item:selected:active, +QColumnView::item:selected:active { + background-color: #9FCBFF; +} + +QTreeView::item:selected:!active, +QListView::item:selected:!active, +QTableView::item:selected:!active, +QColumnView::item:selected:!active { + color: #19232D; + background-color: #CED1D4; +} + +QTreeView::item:!selected:hover, +QListView::item:!selected:hover, +QTableView::item:!selected:hover, +QColumnView::item:!selected:hover { + outline: 0; + color: #19232D; + background-color: #CED1D4; +} + +QTableCornerButton::section { + background-color: #FAFAFA; + border: 1px transparent #C9CDD0; + border-radius: 0px; +} + +/**** Fix QTreeView Items ****/ + +QTreeView::item, +QListView::item, +QTableView::item, +QColumnView::item { + color: #101010; + background: transparent; +} + +QTreeView:branch:selected{ + background-color: #9FCBFF; +} + +QTreeView:branch:!selected:hover, +QTreeView:branch:selected:!active { + color: #19232D; + background-color: #CED1D4; +} + +/* HeaderFrame & TitleBarFrame */ + +QFrame[objectName^="headerFrame"] { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #9BDBF9, stop:1 #1592CD); +} +QFrame[objectName^="headerBFrame"] { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #9BDBF9, stop:1 #1592CD); + border: 1px; + border-radius: 4px; +} +QFrame[objectName^="headerFrame"] > *:!hover, +QFrame[objectName^="headerBFrame"] > *:!hover{ + background: transparent; + color: white; +} + +QFrame[objectName^="toolBarFrame"], +QFrame[objectName^="toolBarFrameTop"] { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FEFEFE, stop:1 #E8E8E8); + border: 1px solid #CCCCCC; +} + +/* Forums */ + +GxsForumThreadWidget QWidget#threadTreeWidget { + selection-background-color: #9FCBFF; + show-decoration-selected: 1; +} + +GxsForumThreadWidget QWidget#threadTreeWidget::item:selected:active , +GxsForumThreadWidget QWidget#threadTreeWidget::item:selected:!active { + background-color: #9FCBFF; +} + +/* People */ + +IdDialog QWidget#idTreeWidget { + selection-background-color: #9FCBFF; + show-decoration-selected: 1; +} + +/* Wire */ +QLabel#label_masthead{ + border: 2px solid #CCCCCC; + border-radius: 4px; +} + +PulseReplySeperator QFrame#frame { + border: 2px solid #CCCCCC; + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #EEEEEE, stop: 1 #CCCCCC); + border-radius: 10px} +} diff --git a/retroshare-gui/src/qss/silver.qss b/retroshare-gui/src/qss/silver.qss deleted file mode 100644 index 32025e8fa..000000000 --- a/retroshare-gui/src/qss/silver.qss +++ /dev/null @@ -1,164 +0,0 @@ -.QWidget{ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F9F9FF, stop: 1 #9F9DB9); -} - -QFrame#titleBarFrame, QFrame#toolBarFrame { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F9F9FF, stop: 1 #9F9DB9); -} - -FriendsDialog QFrame#headFrame { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F9F9FF, stop: 1 #9F9DB9); - border: 1px; - border-radius: 4px; -} - -HeaderFrame { - background-image: url(:/images/headerFrame.png); - border: 0px; -} - -/* Customize the toolbar. */ -QToolBar#toolBarAction { - border-image: url(%THISPATH%/silver/silver.png); - -} - -/* Customize the toolbar. */ -QToolBar#toolBarPage { - border-image: url(%THISPATH%/silver/silver.png); - -} - -QToolBar#chattoolBar{ - border-image: url(%THISPATH%/silver/silver.png); - -} - -QDialog{ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F9F9FF, stop: 1 #9F9DB9); -} - -QPushButton#okButton { - min-height: 27px; - min-width: 77px; -} - -QPushButton#cancelprefButton { - min-height: 27px; - min-width: 77px; -} - -QPushButton#cancelButton { - min-height: 25px; - max-height: 25px; - min-width: 75px; -} - - -QPushButton#applyButton { - - min-height: 25px; - max-height: 25px; - min-width: 75px; -} - -QMenu::item:selected { /* when user selects item using mouse or keyboard */ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F9F9FF, stop: 1 #9F9DB9); -} - -QListWidget::item:selected { /* when user selects item using mouse or keyboard */ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F9F9FF, stop: 1 #9F9DB9); -} - -QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F9F9FF, stop: 1 #9F9DB9); -} - -QStatusBar{ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F9F9FF, stop: 1 #9F9DB9); -} - -QFrame#messengerframetop{ - - border-image: url(%THISPATH%/silver/silver.png); - - - /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07);*/ -} - -QFrame#Chatbuttonframe{ - - border-image: url(%THISPATH%/silver/silver.png); - -} - -QLabel#subjectText{ - font: bold 12px; - -} - -QLabel#subjectlabel{ - font: bold 12px; - -} - -QLabel#fromlabel{ - font: bold 12px; - -} - -QLabel#datelabel{ - font: bold 12px; - -} - -QLabel#tolabel{ - font: bold 12px; - -} - -QLabel#fromText{ - font: bold ; - color: blue; - -} - -HomePage QToolButton#addButton { - font: bold; - font-size: 15pt; - color: white; - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F9F9FF, stop: 1 #9F9DB9); - border: 1px solid #9F9DB9; - border-radius: 4px; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -HomePage QToolButton#addButton:hover { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #eaeaff, stop: 1 #9f9dbc); - border: 1px solid #9F9DB9; - border-radius: 4px; - min-width: 4em; - padding: 2px; -} - -MainWindow QListWidget { - font-size: 12pt; -} - diff --git a/retroshare-gui/src/qss/silver/silver.png b/retroshare-gui/src/qss/silver/silver.png deleted file mode 100644 index 2559aa8d8..000000000 Binary files a/retroshare-gui/src/qss/silver/silver.png and /dev/null differ diff --git a/retroshare-gui/src/qss/silver/silver2.png b/retroshare-gui/src/qss/silver/silver2.png deleted file mode 100644 index fe875f925..000000000 Binary files a/retroshare-gui/src/qss/silver/silver2.png and /dev/null differ diff --git a/retroshare-gui/src/qss/uus.qss b/retroshare-gui/src/qss/uus.qss deleted file mode 100644 index ee1e7b82a..000000000 --- a/retroshare-gui/src/qss/uus.qss +++ /dev/null @@ -1,317 +0,0 @@ -.QWidget { - /*background-color: black;*/ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #376D85, stop: 0.4 #185772); - -} - -QFrame#titleBarFrame, QFrame#toolBarFrame { - - border-image: url(%THISPATH%/uus/uus.png); -} - -FriendsDialog QFrame#headFrame { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #BDDF7D, stop: 1 #49881F); - border: 1px; - border-radius: 4px; -} - -HeaderFrame { - background-image: url(:/images/headerFrame.png); - border: 0px; -} - -QDialog{ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #376D85, stop: 0.4 #185772); -} - - -/* Customize the toolbar. */ -QToolBar#toolBarAction { - border-image: url(%THISPATH%/uus/uus.png); - -} -QToolBar#toolBarPage { - border-image: url(%THISPATH%/uus/uus.png); - -} - -QToolBar#chattoolBar{ - border-image: url(%THISPATH%/uus/uus.png); - - -} - -QFrame#frame_2{ -background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #376D85, stop: 0.4 #185772); - border: 1px solid #CCCCCC; - -} - -QFrame#buttonframe{ -background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FEFEFE, stop:1 #E8E8E8); -} - -/* it works only at the moment with vista Thema on XP*/ -QToolButton::hover { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #BDDF7D, stop: 1 #49881F); - - -} - -QToolButton::pressed { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #BDDF7D, stop: 1 #49881F); - - -} - -/* Style the tab using the tab sub-control. Note that - it reads QTabBar _not_ QTabWidget */ -QTabBar::tab { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #BDDF7D, stop: 1 #49881F); - border: 2px solid #BDDF7D; - border-bottom-color: #49881F; /* same as the pane color */ - border-top-left-radius: 4px; - border-top-right-radius: 4px; - min-width: 8ex; - padding: 2px; - -} - -QTabBar::tab:!selected { - margin-top: 2px; /* make non-selected tabs look smaller */ - -} - -QTabBar::tab:selected, QTabBar::tab:hover { - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F0F8CB, stop: 1 #F0F8CD); - -} - -QTabBar::tab:selected { - border-color: #9B9B9B; - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F5FFBC, stop: 1 #609C08); -} - -QHeaderView::section { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #BDDF7D, stop: 1 #49881F); - color: white; - padding-left: 4px; - border: 1px solid #6c6c6c; - } - -QPushButton#okButton { - min-height: 27px; - min-width: 77px; -} - -QPushButton#cancelprefButton { - min-height: 27px; - min-width: 77px; -} - -QPushButton#cancelButton { - min-height: 25px; - max-height: 25px; - min-width: 75px; -} - - -QPushButton#applyButton { - - min-height: 25px; - max-height: 25px; - min-width: 75px; -} - -QPushButton { - /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #BDDF7D, stop: 1 #49881F); - border: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #BDDF7D, stop: 1 #49881F);*/ -} - - -QPushButton::hover { - /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F0F8CB, stop: 1 #F0F8CD);*/ -} - -QPushButton::pressed { - /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F5FFBC, stop: 1 #609C08);*/ -} - - -QLabel -{ -color: white; -} - -QStatusBar{ - border-image: url(%THISPATH%/uus/uus.png); - -} - -QMenu { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #376D85, stop: 1 #185772); - border: 1px solid black; - } - -QMenu::item:selected { /* when user selects item using mouse or keyboard */ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #BDDF7D, stop: 1 #49881F); -} - -QListWidget::item:selected { /* when user selects item using mouse or keyboard */ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #BDDF7D, stop: 1 #49881F); -} - -QTreeWidget { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #376D85, stop: 1 #185772); - - } - - -QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #BDDF7D, stop: 1 #49881F); - -} - -QTreeView { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #376D85, stop: 1 #185772); - - } - -QTreeView::item:selected { /* when user selects item using mouse or keyboard */ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #BDDF7D, stop: 1 #49881F); - -} - -QToolTip{ - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07); -} - -QFrame#messengerframetop{ - - border-image: url(%THISPATH%/uus/uus.png); - - /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07);*/ -} - -QFrame#Chatbuttonframe{ - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #BDDF7D, stop: 1 #49881F); - -} - -QLabel#subjectText{ - font: bold 12px; - -} - -QLabel#subjectlabel{ - font: bold 12px; - -} - -QLabel#fromlabel{ - font: bold 12px; - -} - -QLabel#datelabel{ - font: bold 12px; - -} - -QLabel#tolabel{ - font: bold 12px; - -} - -QLabel#fromText{ - font: bold ; - color: blue; - -} - -QLabel#friendstitlellabel{ - color: black; -} - -QLabel#friendslabel{ - color: black; -} - -QLabel#networklabel{ - color: black; -} - -QLabel#channellabel{ - color: black; -} - -QLabel#forumslabel{ - color: black; -} - -QLabel#downloadslabel{ - color: black; -} - -QLabel#forumName{ - color: black; -} - -QLabel#threadTitle{ - color: black; -} - - -QLabel#labeltext{ - color: black; -} - -QStatusBar { - - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #BDDF7D, stop: 1 #49881F); - -} - -HomePage QToolButton#addButton { - font: bold; - font-size: 15pt; - color: #49881F; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -MainWindow QListWidget { - font-size: 12pt; -} - diff --git a/retroshare-gui/src/qss/uus/uus.png b/retroshare-gui/src/qss/uus/uus.png deleted file mode 100644 index 1e4f98f98..000000000 Binary files a/retroshare-gui/src/qss/uus/uus.png and /dev/null differ diff --git a/retroshare-gui/src/qss/uus/uus2.png b/retroshare-gui/src/qss/uus/uus2.png deleted file mode 100644 index 6036684b0..000000000 Binary files a/retroshare-gui/src/qss/uus/uus2.png and /dev/null differ diff --git a/retroshare-gui/src/qss/yaba.qss b/retroshare-gui/src/qss/yaba.qss deleted file mode 100644 index 06d35b9ad..000000000 --- a/retroshare-gui/src/qss/yaba.qss +++ /dev/null @@ -1,228 +0,0 @@ -.QWidget { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #6F6F6F, stop:1 #979797); - } - - -QFrame#titleBarFrame, QFrame#toolBarFrame { - - border-image: url(%THISPATH%/yaba/yaba.png); -} - -HeaderFrame { - background-image: url(:/images/headerFrame.png); - border: 0px; -} - -FriendsDialog QFrame#headFrame { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FBC957, stop:1 #D79704); - border: 1px; - border-radius: 4px; -} - -QFrame#titleBarFrame, QFrame#toolBarFrame { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FBC957, stop:1 #D79704); - -} - -QDialog, QMainWindow, QStatusBar{ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #6F6F6F, stop:1 #979797); -} - -QWidget#chatcentralwidget{ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #6F6F6F, stop:1 #979797); -} - - -/* Channels */ - -ChannelFeed QFrame#headerFrame { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FBC957, stop:1 #D79704); - border: 1px solid #CCCCCC; -} - -/* Customize the toolbar. */ -QToolBar#toolBarAction { - border-image: url(%THISPATH%/yaba/yaba.png); - -} - -QToolBar#toolBarPage { - border-image: url(%THISPATH%/yaba/yaba.png); - -} - -QFrame#frame_2{ - border-image: url(%THISPATH%/yaba/yaba3.png); - -} - -QFrame#buttonframe{ - border-image: url(%THISPATH%/yaba/yaba3.png); - -} - -QFrame#chheaderframe{ - border-image: url(%THISPATH%/yaba/yaba3.png); - -} -QFrame#frame{ - border-image: url(%THISPATH%/yaba/yaba3.png); - -} - -QHeaderView::section { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #616161, stop: 0.5 #505050, - stop: 0.6 #434343, stop:1 #656565); - color: white; - padding-left: 4px; - border: 1px solid #6c6c6c; - } - - - QMenuBar { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #626262, stop:1 #989898); - } - - QTabWidget::pane { /* The tab widget frame */ - border-top: 2px solid #C2C7CB; - } - - QTabWidget::tab-bar { - left: 0px; /* move to the right by 5px */ - } - - /* Style the tab using the tab sub-control. Note that - it reads QTabBar _not_ QTabWidget */ - QTabBar::tab { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #E1E1E1, stop: 0.4 #DDDDDD, - stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3); - border: 2px solid #C4C4C3; - border-bottom-color: #C2C7CB; /* same as the pane color */ - border-top-left-radius: 4px; - border-top-right-radius: 4px; - min-width: 8ex; - padding: 2px; - } - - QTabBar::tab:selected, QTabBar::tab:hover { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #fafafa, stop: 0.4 #f4f4f4, - stop: 0.5 #e7e7e7, stop: 1.0 #fafafa); - } - - QTabBar::tab:selected { - border-color: #9B9B9B; - border-bottom-color: #C2C7CB; /* same as pane color */ - } - - QTabBar::tab:!selected { - margin-top: 2px; /* make non-selected tabs look smaller */ - } - -QMenu { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #6F6F6F, stop:1 #979797); - border: 1px solid black; - } - - -QMenu::item { - /* sets background of menu item. set this to something non-transparent - if you want menu color and menu item color to be different */ - background-color: transparent; - } - -QMenu::item:selected { /* when user selects item using mouse or keyboard */ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FBC957, stop:1 #D79704); - } - -QListWidget::item:selected { /* when user selects item using mouse or keyboard */ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FBC957, stop:1 #D79704); -} - -QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FBC957, stop:1 #D79704); -} - -QTreeView::item:selected { /* when user selects item using mouse or keyboard */ - - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #FBC957, stop: 1 #D79704); - -} - -QFrame#messengerframetop{ - - border-image: url(%THISPATH%/yaba/yaba.png); - - /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07);*/ -} - -QFrame#Chatbuttonframe{ - - border-image: url(%THISPATH%/yaba/yaba.png); - -} - -QLabel#subjectText{ - font: bold 12px; - -} - -QLabel#subjectlabel{ - font: bold 12px; - -} - -QLabel#fromlabel{ - font: bold 12px; - -} - -QLabel#datelabel{ - font: bold 12px; - -} - -QLabel#tolabel{ - font: bold 12px; - -} - -QLabel#fromText{ - font: bold ; - color: blue; - -} - -QToolBar#chattoolBar{ - border-image: url(%THISPATH%/yaba/yaba.png); - -} - -HomePage QToolButton#addButton { - font: bold; - font-size: 15pt; - color: #979797; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -MainWindow QListWidget { - font-size: 12pt; -} - diff --git a/retroshare-gui/src/qss/yaba/yaba.png b/retroshare-gui/src/qss/yaba/yaba.png deleted file mode 100644 index e8659f66d..000000000 Binary files a/retroshare-gui/src/qss/yaba/yaba.png and /dev/null differ diff --git a/retroshare-gui/src/qss/yaba/yaba2.png b/retroshare-gui/src/qss/yaba/yaba2.png deleted file mode 100644 index af6be6117..000000000 Binary files a/retroshare-gui/src/qss/yaba/yaba2.png and /dev/null differ diff --git a/retroshare-gui/src/qss/yaba/yaba3.png b/retroshare-gui/src/qss/yaba/yaba3.png deleted file mode 100644 index 5dd5a2a32..000000000 Binary files a/retroshare-gui/src/qss/yaba/yaba3.png and /dev/null differ diff --git a/retroshare-gui/src/qss/yeah.qss b/retroshare-gui/src/qss/yeah.qss deleted file mode 100644 index b154b7f53..000000000 --- a/retroshare-gui/src/qss/yeah.qss +++ /dev/null @@ -1,183 +0,0 @@ -.QWidget { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 lightgray, stop:1 darkgray); -} - -FriendsDialog QFrame#headFrame { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FBC957, stop:1 #D79704); - border: 1px; - border-radius: 4px; -} - -QFrame#titleBarFrame, QFrame#toolBarFrame { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FBC957, stop:1 #D79704); - border: 1px solid #CCCCCC; -} - -HeaderFrame { - background-image: url(:/images/headerFrame.png); - border: 0px; -} - -QDialog{ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 lightgray, stop:1 darkgray); -} - - -/* Customize the toolbar. */ -QToolBar { - border-image: url(%THISPATH%/yeah/yeah.png); - -} - -QStatusBar{ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 lightgray, stop:1 darkgray); -} - - -QHeaderView::section { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #616161, stop: 0.5 #505050, - stop: 0.6 #434343, stop:1 #656565); - color: white; - padding-left: 4px; - border: 1px solid #6c6c6c; -} - - -QMenuBar { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 lightgray, stop:1 darkgray); -} - - QTabWidget::pane { /* The tab widget frame */ - border-top: 2px solid #C2C7CB; - } - - QTabWidget::tab-bar { - left: 0px; /* move to the right by 5px */ - } - - /* Style the tab using the tab sub-control. Note that - it reads QTabBar _not_ QTabWidget */ - QTabBar::tab { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #E1E1E1, stop: 0.4 #DDDDDD, - stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3); - border: 2px solid #C4C4C3; - border-bottom-color: #C2C7CB; /* same as the pane color */ - border-top-left-radius: 4px; - border-top-right-radius: 4px; - min-width: 8ex; - padding: 2px; - } - - QTabBar::tab:selected, QTabBar::tab:hover { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #fafafa, stop: 0.4 #f4f4f4, - stop: 0.5 #e7e7e7, stop: 1.0 #fafafa); - } - - QTabBar::tab:selected { - border-color: #9B9B9B; - border-bottom-color: #C2C7CB; /* same as pane color */ - } - - QTabBar::tab:!selected { - margin-top: 2px; /* make non-selected tabs look smaller */ - } - - QMenu { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 lightgray, stop:1 darkgray); - border: 1px solid black; - } - -QMenu::item { - /* sets background of menu item. set this to something non-transparent - if you want menu color and menu item color to be different */ - background-color: transparent; - } - -QMenu::item:selected { /* when user selects item using mouse or keyboard */ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FBC957, stop:1 #D79704); - } - -QListWidget::item:selected { /* when user selects item using mouse or keyboard */ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FBC957, stop:1 #D79704); -} - -QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 #FBC957, stop:1 #D79704); -} - -QTreeView::item:selected { /* when user selects item using mouse or keyboard */ - - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #FBC957, stop: 1 #D79704); - -} - -QFrame#messengerframetop{ - - border-image: url(%THISPATH%/yeah/yeah.png); - - /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #F7B552, stop: 1 #FF5E07);*/ -} - -QFrame#Chatbuttonframe{ - - border-image: url(%THISPATH%/yeah/yeah.png); - -} - -QLabel#subjectText{ - font: bold 12px; - -} - -QLabel#subjectlabel{ - font: bold 12px; - -} - -QLabel#fromlabel{ - font: bold 12px; - -} - -QLabel#datelabel{ - font: bold 12px; - -} - -QLabel#tolabel{ - font: bold 12px; - -} -QLabel#fromText{ - font: bold ; - color: blue; - -} - -HomePage QToolButton#addButton { - font: bold; - font-size: 15pt; - color: #979797; - max-height: 27px; - min-width: 4em; - padding: 2px; -} - -MainWindow QListWidget { - font-size: 12pt; -} diff --git a/retroshare-gui/src/qss/yeah/yeah.png b/retroshare-gui/src/qss/yeah/yeah.png deleted file mode 100644 index bd31010f7..000000000 Binary files a/retroshare-gui/src/qss/yeah/yeah.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Bliss/maxButton.png b/retroshare-gui/src/release/skin/Bliss/maxButton.png deleted file mode 100644 index 4d83bcd35..000000000 Binary files a/retroshare-gui/src/release/skin/Bliss/maxButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Bliss/maxButton1.png b/retroshare-gui/src/release/skin/Bliss/maxButton1.png deleted file mode 100644 index a916ba483..000000000 Binary files a/retroshare-gui/src/release/skin/Bliss/maxButton1.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Bliss/maxButton2.png b/retroshare-gui/src/release/skin/Bliss/maxButton2.png deleted file mode 100644 index aaba43674..000000000 Binary files a/retroshare-gui/src/release/skin/Bliss/maxButton2.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Bliss/minButton.png b/retroshare-gui/src/release/skin/Bliss/minButton.png deleted file mode 100644 index 7f1553a6e..000000000 Binary files a/retroshare-gui/src/release/skin/Bliss/minButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Bliss/minButton1.png b/retroshare-gui/src/release/skin/Bliss/minButton1.png deleted file mode 100644 index a3c564cdd..000000000 Binary files a/retroshare-gui/src/release/skin/Bliss/minButton1.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Bliss/minButton2.png b/retroshare-gui/src/release/skin/Bliss/minButton2.png deleted file mode 100644 index 01af810b0..000000000 Binary files a/retroshare-gui/src/release/skin/Bliss/minButton2.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Bliss/quiButton.png b/retroshare-gui/src/release/skin/Bliss/quiButton.png deleted file mode 100644 index 6a657ae1a..000000000 Binary files a/retroshare-gui/src/release/skin/Bliss/quiButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Bliss/quiButton1.png b/retroshare-gui/src/release/skin/Bliss/quiButton1.png deleted file mode 100644 index 174c7b2ee..000000000 Binary files a/retroshare-gui/src/release/skin/Bliss/quiButton1.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Bliss/quiButton2.png b/retroshare-gui/src/release/skin/Bliss/quiButton2.png deleted file mode 100644 index f379e9431..000000000 Binary files a/retroshare-gui/src/release/skin/Bliss/quiButton2.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Bliss/sl.png b/retroshare-gui/src/release/skin/Bliss/sl.png deleted file mode 100644 index 851821b6a..000000000 Binary files a/retroshare-gui/src/release/skin/Bliss/sl.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Bliss/so.png b/retroshare-gui/src/release/skin/Bliss/so.png deleted file mode 100644 index 6497639b3..000000000 Binary files a/retroshare-gui/src/release/skin/Bliss/so.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Bliss/sr.png b/retroshare-gui/src/release/skin/Bliss/sr.png deleted file mode 100644 index 6689549b3..000000000 Binary files a/retroshare-gui/src/release/skin/Bliss/sr.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Bliss/su.png b/retroshare-gui/src/release/skin/Bliss/su.png deleted file mode 100644 index 9862742f0..000000000 Binary files a/retroshare-gui/src/release/skin/Bliss/su.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Glassy/maxButton.png b/retroshare-gui/src/release/skin/Glassy/maxButton.png deleted file mode 100644 index 469d21e40..000000000 Binary files a/retroshare-gui/src/release/skin/Glassy/maxButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Glassy/minButton.png b/retroshare-gui/src/release/skin/Glassy/minButton.png deleted file mode 100644 index 40c6ba78c..000000000 Binary files a/retroshare-gui/src/release/skin/Glassy/minButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Glassy/quiButton.png b/retroshare-gui/src/release/skin/Glassy/quiButton.png deleted file mode 100644 index da6390211..000000000 Binary files a/retroshare-gui/src/release/skin/Glassy/quiButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Glassy/sl.png b/retroshare-gui/src/release/skin/Glassy/sl.png deleted file mode 100644 index f259a74c7..000000000 Binary files a/retroshare-gui/src/release/skin/Glassy/sl.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Glassy/so.png b/retroshare-gui/src/release/skin/Glassy/so.png deleted file mode 100644 index 9b554663d..000000000 Binary files a/retroshare-gui/src/release/skin/Glassy/so.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Glassy/sr.png b/retroshare-gui/src/release/skin/Glassy/sr.png deleted file mode 100644 index f259a74c7..000000000 Binary files a/retroshare-gui/src/release/skin/Glassy/sr.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Glassy/su.png b/retroshare-gui/src/release/skin/Glassy/su.png deleted file mode 100644 index 0e96fdbed..000000000 Binary files a/retroshare-gui/src/release/skin/Glassy/su.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Green/maxButton.png b/retroshare-gui/src/release/skin/Green/maxButton.png deleted file mode 100644 index 73f1fc27d..000000000 Binary files a/retroshare-gui/src/release/skin/Green/maxButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Green/minButton.png b/retroshare-gui/src/release/skin/Green/minButton.png deleted file mode 100644 index 1c9adaa6c..000000000 Binary files a/retroshare-gui/src/release/skin/Green/minButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Green/quiButton.png b/retroshare-gui/src/release/skin/Green/quiButton.png deleted file mode 100644 index 6134015ef..000000000 Binary files a/retroshare-gui/src/release/skin/Green/quiButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Green/sl.png b/retroshare-gui/src/release/skin/Green/sl.png deleted file mode 100644 index 06af00e82..000000000 Binary files a/retroshare-gui/src/release/skin/Green/sl.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Green/so.png b/retroshare-gui/src/release/skin/Green/so.png deleted file mode 100644 index 661ffd761..000000000 Binary files a/retroshare-gui/src/release/skin/Green/so.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Green/sr.png b/retroshare-gui/src/release/skin/Green/sr.png deleted file mode 100644 index 7f62f1c0b..000000000 Binary files a/retroshare-gui/src/release/skin/Green/sr.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Green/su.png b/retroshare-gui/src/release/skin/Green/su.png deleted file mode 100644 index 8e04d5077..000000000 Binary files a/retroshare-gui/src/release/skin/Green/su.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Night Vision/maxButton.png b/retroshare-gui/src/release/skin/Night Vision/maxButton.png deleted file mode 100644 index cbb27c3cb..000000000 Binary files a/retroshare-gui/src/release/skin/Night Vision/maxButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Night Vision/minButton.png b/retroshare-gui/src/release/skin/Night Vision/minButton.png deleted file mode 100644 index 5892a982c..000000000 Binary files a/retroshare-gui/src/release/skin/Night Vision/minButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Night Vision/quiButton.png b/retroshare-gui/src/release/skin/Night Vision/quiButton.png deleted file mode 100644 index 1443caa9d..000000000 Binary files a/retroshare-gui/src/release/skin/Night Vision/quiButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Night Vision/sl.png b/retroshare-gui/src/release/skin/Night Vision/sl.png deleted file mode 100644 index acc9db3d1..000000000 Binary files a/retroshare-gui/src/release/skin/Night Vision/sl.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Night Vision/so.png b/retroshare-gui/src/release/skin/Night Vision/so.png deleted file mode 100644 index 900e051a9..000000000 Binary files a/retroshare-gui/src/release/skin/Night Vision/so.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Night Vision/sr.png b/retroshare-gui/src/release/skin/Night Vision/sr.png deleted file mode 100644 index 0d0f296ec..000000000 Binary files a/retroshare-gui/src/release/skin/Night Vision/sr.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Night Vision/su.png b/retroshare-gui/src/release/skin/Night Vision/su.png deleted file mode 100644 index 32b195e0d..000000000 Binary files a/retroshare-gui/src/release/skin/Night Vision/su.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Vista/maxButton.png b/retroshare-gui/src/release/skin/Vista/maxButton.png deleted file mode 100644 index cbb27c3cb..000000000 Binary files a/retroshare-gui/src/release/skin/Vista/maxButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Vista/maxButton1.png b/retroshare-gui/src/release/skin/Vista/maxButton1.png deleted file mode 100644 index 1bed27a49..000000000 Binary files a/retroshare-gui/src/release/skin/Vista/maxButton1.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Vista/maxButton2.png b/retroshare-gui/src/release/skin/Vista/maxButton2.png deleted file mode 100644 index a9ece6da2..000000000 Binary files a/retroshare-gui/src/release/skin/Vista/maxButton2.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Vista/minButton.png b/retroshare-gui/src/release/skin/Vista/minButton.png deleted file mode 100644 index 5892a982c..000000000 Binary files a/retroshare-gui/src/release/skin/Vista/minButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Vista/minButton1.png b/retroshare-gui/src/release/skin/Vista/minButton1.png deleted file mode 100644 index 79207e5df..000000000 Binary files a/retroshare-gui/src/release/skin/Vista/minButton1.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Vista/minButton2.png b/retroshare-gui/src/release/skin/Vista/minButton2.png deleted file mode 100644 index b52bdb299..000000000 Binary files a/retroshare-gui/src/release/skin/Vista/minButton2.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Vista/quiButton.png b/retroshare-gui/src/release/skin/Vista/quiButton.png deleted file mode 100644 index 1443caa9d..000000000 Binary files a/retroshare-gui/src/release/skin/Vista/quiButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Vista/quiButton1.png b/retroshare-gui/src/release/skin/Vista/quiButton1.png deleted file mode 100644 index 008b25e2e..000000000 Binary files a/retroshare-gui/src/release/skin/Vista/quiButton1.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Vista/quiButton2.png b/retroshare-gui/src/release/skin/Vista/quiButton2.png deleted file mode 100644 index 3e79d9f08..000000000 Binary files a/retroshare-gui/src/release/skin/Vista/quiButton2.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Vista/sl.png b/retroshare-gui/src/release/skin/Vista/sl.png deleted file mode 100644 index 05628496b..000000000 Binary files a/retroshare-gui/src/release/skin/Vista/sl.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Vista/so.png b/retroshare-gui/src/release/skin/Vista/so.png deleted file mode 100644 index d9472686c..000000000 Binary files a/retroshare-gui/src/release/skin/Vista/so.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Vista/sr.png b/retroshare-gui/src/release/skin/Vista/sr.png deleted file mode 100644 index 60e8e091f..000000000 Binary files a/retroshare-gui/src/release/skin/Vista/sr.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/Vista/su.png b/retroshare-gui/src/release/skin/Vista/su.png deleted file mode 100644 index c62254cfb..000000000 Binary files a/retroshare-gui/src/release/skin/Vista/su.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/bg.png b/retroshare-gui/src/release/skin/VistaAlpha/bg.png deleted file mode 100644 index f7ead614a..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/bg.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/maxButton.png b/retroshare-gui/src/release/skin/VistaAlpha/maxButton.png deleted file mode 100644 index bb1c53ee4..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/maxButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/maxButton1.png b/retroshare-gui/src/release/skin/VistaAlpha/maxButton1.png deleted file mode 100644 index 1bed27a49..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/maxButton1.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/maxButton2.png b/retroshare-gui/src/release/skin/VistaAlpha/maxButton2.png deleted file mode 100644 index a9ece6da2..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/maxButton2.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/minButton.png b/retroshare-gui/src/release/skin/VistaAlpha/minButton.png deleted file mode 100644 index 379bfa4cb..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/minButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/minButton1.png b/retroshare-gui/src/release/skin/VistaAlpha/minButton1.png deleted file mode 100644 index 79207e5df..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/minButton1.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/minButton2.png b/retroshare-gui/src/release/skin/VistaAlpha/minButton2.png deleted file mode 100644 index b52bdb299..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/minButton2.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/quiButton.png b/retroshare-gui/src/release/skin/VistaAlpha/quiButton.png deleted file mode 100644 index e3882e9ff..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/quiButton.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/quiButton1.png b/retroshare-gui/src/release/skin/VistaAlpha/quiButton1.png deleted file mode 100644 index 008b25e2e..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/quiButton1.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/quiButton2.png b/retroshare-gui/src/release/skin/VistaAlpha/quiButton2.png deleted file mode 100644 index 3e79d9f08..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/quiButton2.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/sl.png b/retroshare-gui/src/release/skin/VistaAlpha/sl.png deleted file mode 100644 index 82deb022e..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/sl.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/so.png b/retroshare-gui/src/release/skin/VistaAlpha/so.png deleted file mode 100644 index 677255b01..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/so.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/sr.png b/retroshare-gui/src/release/skin/VistaAlpha/sr.png deleted file mode 100644 index 22f2e74fe..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/sr.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/su.png b/retroshare-gui/src/release/skin/VistaAlpha/su.png deleted file mode 100644 index 6f19cdc00..000000000 Binary files a/retroshare-gui/src/release/skin/VistaAlpha/su.png and /dev/null differ diff --git a/retroshare-gui/src/release/skin/skin.dat b/retroshare-gui/src/release/skin/skin.dat deleted file mode 100644 index 7a501621c..000000000 --- a/retroshare-gui/src/release/skin/skin.dat +++ /dev/null @@ -1,7 +0,0 @@ -[Skin] -Blur=false -Hintergrundfarbe=@Variant(\0\0\0\x43\x1\xff\xff\xd5\xd5\xd5\xd5\xd5\xd5\0\0) -SkinOn=true -Skinpfad=skin/Vista/ -Titelfarbe=@Variant(\0\0\0\x43\x1\xff\xff\0\0\0\0\0\0\0\0) -Titelschrift=@Variant(\0\0\0@\0\0\0\x1a\0\x43\0o\0m\0i\0\x63\0 \0S\0\x61\0n\0s\0 \0M\0S@$\0\0\0\0\0\0\xff\xff\xff\xff\x5\x1\0K\x10) diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index 11bb33dca..6f217db9c 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -113,7 +113,6 @@ CONFIG += gxscircles # Other Disabled Bits. #CONFIG += framecatcher -#CONFIG += blogs ## To enable unfinished services #CONFIG += wikipoos @@ -147,11 +146,11 @@ unix { target.path = "$${BIN_DIR}" INSTALLS += target - data_files.path="$${DATA_DIR}/" + data_files.path="$${RS_DATA_DIR}/" data_files.files=sounds qss INSTALLS += data_files - style_files.path="$${DATA_DIR}/stylesheets" + style_files.path="$${RS_DATA_DIR}/stylesheets" style_files.files=gui/qss/chat/Bubble gui/qss/chat/Bubble_Compact INSTALLS += style_files @@ -218,10 +217,6 @@ win32-g++|win32-clang-g++ { CONFIG -= console } - # Switch on extra warnings - QMAKE_CFLAGS += -Wextra - QMAKE_CXXFLAGS += -Wextra - CONFIG(debug, debug|release) { } else { # Tell linker to use ASLR protection @@ -280,13 +275,22 @@ macx { mac_icon.files = $$files($$PWD/rsMacIcon.icns) mac_icon.path = Contents/Resources QMAKE_BUNDLE_DATA += mac_icon + dplQSS.files = $$PWD/qss + dplQSS.path = Contents/Resources + QMAKE_BUNDLE_DATA += dplQSS + dplChatStyles.files = \ + $$PWD/gui/qss/chat/Bubble \ + $$PWD/gui/qss/chat/Bubble_Compact + dplChatStyles.path = Contents/Resources/stylesheets + QMAKE_BUNDLE_DATA += dplChatStyles # mac_webui.files = $$files($$PWD/../../libresapi/src/webui) # mac_webui.path = Contents/Resources # QMAKE_BUNDLE_DATA += mac_webui + OBJECTS_DIR = temp/obj + CONFIG += version_detail_bash_script - LIBS += -lssl -lcrypto -lz - #LIBS += -lssl -lcrypto -lz -lgpgme -lgpg-error -lassuan + LIBS += -lssl -lcrypto -lz for(lib, LIB_DIR):exists($$lib/libminiupnpc.a){ LIBS += $$lib/libminiupnpc.a} LIBS += -framework CoreFoundation LIBS += -framework Security @@ -300,6 +304,9 @@ macx { #DEFINES *= MAC_IDLE # for idle feature CONFIG -= uitools + + OBJECTIVE_SOURCES += gui/common/MacDockIconHandler.mm + OBJECTIVE_HEADERS += gui/common/MacDockIconHandler.h } ##################################### FreeBSD ###################################### @@ -355,46 +362,6 @@ wikipoos { ################################### HEADERS & SOURCES ############################# -# Tor controller - -HEADERS += TorControl/AddOnionCommand.h \ - TorControl/AuthenticateCommand.h \ - TorControl/CryptoKey.h \ - TorControl/GetConfCommand.h \ - TorControl/HiddenService.h \ - TorControl/PendingOperation.h \ - TorControl/ProtocolInfoCommand.h \ - TorControl/SecureRNG.h \ - TorControl/SetConfCommand.h \ - TorControl/Settings.h \ - TorControl/StrUtil.h \ - TorControl/TorControl.h \ - TorControl/TorControlCommand.h \ - TorControl/TorControlSocket.h \ - TorControl/TorManager.h \ - TorControl/TorProcess.h \ - TorControl/TorProcess_p.h \ - TorControl/TorSocket.h \ - TorControl/Useful.h - -SOURCES += TorControl/AddOnionCommand.cpp \ - TorControl/AuthenticateCommand.cpp \ - TorControl/GetConfCommand.cpp \ - TorControl/HiddenService.cpp \ - TorControl/ProtocolInfoCommand.cpp \ - TorControl/SetConfCommand.cpp \ - TorControl/TorControlCommand.cpp \ - TorControl/TorControl.cpp \ - TorControl/TorControlSocket.cpp \ - TorControl/TorManager.cpp \ - TorControl/TorProcess.cpp \ - TorControl/TorSocket.cpp \ - TorControl/CryptoKey.cpp \ - TorControl/PendingOperation.cpp \ - TorControl/SecureRNG.cpp \ - TorControl/Settings.cpp \ - TorControl/StrUtil.cpp - # Input HEADERS += rshare.h \ retroshare-gui/configpage.h \ @@ -484,6 +451,7 @@ HEADERS += rshare.h \ util/qtthreadsutils.h \ util/ClickableLabel.h \ util/AspectRatioPixmapLabel.h \ + util/FontSizeHandler.h \ gui/profile/ProfileWidget.h \ gui/profile/ProfileManager.h \ gui/profile/StatusMessage.h \ @@ -552,6 +520,7 @@ HEADERS += rshare.h \ gui/common/vmessagebox.h \ gui/common/RsUrlHandler.h \ gui/common/RsCollectionDialog.h \ + gui/common/RsCollectionModel.h \ gui/common/rwindow.h \ gui/common/rshtml.h \ gui/common/AvatarDefs.h \ @@ -562,6 +531,7 @@ HEADERS += rshare.h \ gui/common/TagDefs.h \ gui/common/GroupDefs.h \ gui/common/Emoticons.h \ + gui/common/RSComboBox.h \ gui/common/RSListWidgetItem.h \ gui/common/RSTextEdit.h \ gui/common/RSPlainTextEdit.h \ @@ -597,8 +567,6 @@ HEADERS += rshare.h \ gui/common/RsBanListToolButton.h \ gui/common/FlowLayout.h \ gui/common/PictureFlow.h \ - gui/common/StyledLabel.h \ - gui/common/StyledElidedLabel.h \ gui/common/ToasterNotify.h \ gui/style/RSStyle.h \ gui/style/StyleDialog.h \ @@ -850,6 +818,7 @@ SOURCES += main.cpp \ util/RichTextEdit.cpp \ util/ClickableLabel.cpp \ util/AspectRatioPixmapLabel.cpp \ + util/FontSizeHandler.cpp \ gui/profile/ProfileWidget.cpp \ gui/profile/StatusMessage.cpp \ gui/profile/ProfileManager.cpp \ @@ -879,6 +848,7 @@ SOURCES += main.cpp \ gui/common/ElidedLabel.cpp \ gui/common/vmessagebox.cpp \ gui/common/RsCollectionDialog.cpp \ + gui/common/RsCollectionModel.cpp \ gui/common/RsUrlHandler.cpp \ gui/common/rwindow.cpp \ gui/common/rshtml.cpp \ @@ -891,6 +861,7 @@ SOURCES += main.cpp \ gui/common/TagDefs.cpp \ gui/common/GroupDefs.cpp \ gui/common/Emoticons.cpp \ + gui/common/RSComboBox.cpp \ gui/common/RSListWidgetItem.cpp \ gui/common/RSTextEdit.cpp \ gui/common/RSPlainTextEdit.cpp \ @@ -926,8 +897,6 @@ SOURCES += main.cpp \ gui/common/RsBanListToolButton.cpp \ gui/common/FlowLayout.cpp \ gui/common/PictureFlow.cpp \ - gui/common/StyledLabel.cpp \ - gui/common/StyledElidedLabel.cpp \ gui/common/ToasterNotify.cpp \ gui/style/RSStyle.cpp \ gui/style/StyleDialog.cpp \ @@ -1038,7 +1007,9 @@ SOURCES += main.cpp \ # gui/feeds/ChanNewItem.cpp \ # gui/feeds/ChanMsgItem.cpp \ -RESOURCES += gui/images.qrc gui/icons.qrc lang/lang.qrc gui/help/content/content.qrc gui/emojione.qrc +RESOURCES += gui/images.qrc gui/icons.qrc lang/lang.qrc gui/help/content/content.qrc gui/emojione.qrc \ + gui/qss/stylesheet/qdarkstyle/dark/Standard_Dark.qrc \ + gui/qss/stylesheet/qdarkstyle/light/Standard_Light.qrc TRANSLATIONS += \ lang/retroshare_ca_ES.ts \ @@ -1121,6 +1092,14 @@ DEFINES *= CHANNELS_FRAME_CATCHER } +# Embedded Friend Server + +rs_efs { + DEFINES *= RS_EMBEDED_FRIEND_SERVER + SOURCES += gui/FriendServerControl.cpp + HEADERS += gui/FriendServerControl.h + FORMS += gui/FriendServerControl.ui +} # BELOW IS GXS Unfinished Services. @@ -1248,6 +1227,7 @@ gxsthewire { gui/TheWire/PulseReply.h \ gui/TheWire/PulseReplySeperator.h \ gui/TheWire/PulseMessage.h \ + gui/TheWire/CustomFrame.h \ FORMS += gui/TheWire/WireDialog.ui \ gui/TheWire/WireGroupItem.ui \ @@ -1270,6 +1250,7 @@ gxsthewire { gui/TheWire/PulseReply.cpp \ gui/TheWire/PulseReplySeperator.cpp \ gui/TheWire/PulseMessage.cpp \ + gui/TheWire/CustomFrame.cpp \ RESOURCES += gui/TheWire/TheWire_images.qrc } @@ -1278,6 +1259,7 @@ identities { HEADERS += \ gui/Identity/IdDialog.h \ + gui/Identity/IdentityListModel.h \ gui/Identity/IdEditDialog.h \ gui/Identity/IdDetailsDialog.h \ @@ -1287,6 +1269,7 @@ identities { SOURCES += \ gui/Identity/IdDialog.cpp \ + gui/Identity/IdentityListModel.cpp \ gui/Identity/IdEditDialog.cpp \ gui/Identity/IdDetailsDialog.cpp \ diff --git a/retroshare-gui/src/retroshare-process.nsi b/retroshare-gui/src/retroshare-process.nsi deleted file mode 100644 index 685f90214..000000000 --- a/retroshare-gui/src/retroshare-process.nsi +++ /dev/null @@ -1,502 +0,0 @@ -; Script generated with the Venis Install Wizard & modified by defnax -; This script need the http://nsis.sourceforge.net/Processes_plug-in -; This script need the http://nsis.sourceforge.net/KillProcDLL_plug-in - -; Define your application name -!define APPNAME "RetroShare" -!define VERSION "0.4.13d" -!define APPNAMEANDVERSION "${APPNAME} ${VERSION}" - - -; Main Install settings -Name "${APPNAMEANDVERSION}" -InstallDir "$PROGRAMFILES\RetroShare" -InstallDirRegKey HKLM "Software\${APPNAME}" "" -OutFile "RetroShare_${VERSION}_setup.exe" -BrandingText "${APPNAMEANDVERSION}" -; Use compression -SetCompressor LZMA - -VAR KILLEXENAME - - -; Modern interface settings -!include Sections.nsh -!include "MUI.nsh" - -;Interface Settings -!define MUI_ABORTWARNING -;!define MUI_HEADERIMAGE -;!define MUI_HEADERIMAGE_BITMAP "retroshare.bmp" ; optional - -# MUI defines -!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\orange-install.ico" -!define MUI_FINISHPAGE_NOAUTOCLOSE -!define MUI_LICENSEPAGE_RADIOBUTTONS -!define MUI_COMPONENTSPAGE_SMALLDESC -!define MUI_FINISHPAGE_LINK "Visit the RetroShare forum for the latest news and support" -!define MUI_FINISHPAGE_LINK_LOCATION "http://retroshare.sourceforge.net/forum/" -!define MUI_FINISHPAGE_RUN "$INSTDIR\RetroShare.exe" -!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\changelog.txt -!define MUI_FINISHPAGE_SHOWREADME_TEXT changelog.txt -!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED -!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\orange-uninstall.ico" -!define MUI_UNFINISHPAGE_NOAUTOCLOSE -!define MUI_LANGDLL_REGISTRY_ROOT HKLM -!define MUI_LANGDLL_REGISTRY_KEY ${REGKEY} -!define MUI_LANGDLL_REGISTRY_VALUENAME InstallerLanguage - -; !define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIt is recommended that you close all other applications before starting Setup. This will make it possible to update relevant system files without havinf to reboot your computer. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " - -;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " - - -; Defines the un-/installer logo of RetroShare -!insertmacro MUI_DEFAULT MUI_WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange.bmp" -!insertmacro MUI_DEFAULT MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange-uninstall.bmp" - -; Set languages (first is default language) -!insertmacro MUI_RESERVEFILE_LANGDLL -ReserveFile "${NSISDIR}\Plugins\AdvSplash.dll" - -;-------------------------------- -;Configuration - - - ;!insertmacro MUI_RESERVEFILE_SPECIALBITMAP - - LicenseLangString myLicenseData 1033 "license\license.txt" - LicenseLangString myLicenseData 1031 "license\license-GER.txt" - LicenseLangString myLicenseData 1036 "license\license-FR.txt" - LicenseLangString myLicenseData 1055 "license\license-TR.txt" - LicenseLangString myLicenseData 2052 "license\license.txt" - LicenseLangString myLicenseData 1045 "license\license.txt" - - LicenseData $(myLicenseData) - -# Installer pages -!insertmacro MUI_PAGE_WELCOME -!insertmacro MUI_PAGE_LICENSE "$(myLicenseData)" -!insertmacro MUI_PAGE_COMPONENTS -!insertmacro MUI_PAGE_DIRECTORY -!insertmacro MUI_PAGE_INSTFILES -!insertmacro MUI_PAGE_FINISH -!insertmacro MUI_UNPAGE_CONFIRM -!insertmacro MUI_UNPAGE_INSTFILES - -# Installer languages -!define MUI_LANGDLL_ALLLANGUAGES - -!insertmacro MUI_LANGUAGE English -!insertmacro MUI_LANGUAGE German -!insertmacro MUI_LANGUAGE French -!insertmacro MUI_LANGUAGE Turkish -!insertmacro MUI_LANGUAGE SimpChinese -!insertmacro MUI_LANGUAGE Polish - - ;Component-selection page - ;Titles - - LangString sec_main ${LANG_ENGLISH} "Program Files" - LangString sec_data ${LANG_ENGLISH} "Program Skins" - LangString sec_shortcuts ${LANG_ENGLISH} "Shortcuts" - LangString sec_link ${LANG_ENGLISH} "File Association" - LangString sec_autostart ${LANG_ENGLISH} "Auto Startup" - LangString DESC_sec_main ${LANG_ENGLISH} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_ENGLISH} "Installs RetroShare Skins" - LangString DESC_sec_shortcuts ${LANG_ENGLISH} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_ENGLISH} "Associate RetroShare with .pqi file extension" - LangString DESC_sec_autostart ${LANG_ENGLISH} "Auto-Run and Login at Startup" - LangString LANGUAGEID ${LANG_ENGLISH} "1033" - - LangString sec_main ${LANG_FRENCH} "RetroShare" - LangString sec_data ${LANG_FRENCH} "Programme de Skins" - LangString sec_shortcuts ${LANG_FRENCH} "Raccourcis" - LangString sec_link ${LANG_FRENCH} "RetroShare fichiers Association" - LangString sec_startmenu ${LANG_FRENCH} "Raccourcis du menu Démarrer" - LangString sec_autostart ${LANG_FRENCH} "Démarrage automatique" - LangString DESC_sec_main ${LANG_FRENCH} "Installe les fichiers du programme." - LangString DESC_sec_data ${LANG_FRENCH} "Installe RetroShare Skins" - LangString DESC_sec_startmenu ${LANG_FRENCH} "Crée les raccourcis du menu Démarrer" - LangString DESC_sec_shortcuts ${LANG_FRENCH} "Crée une icône sur le bureau." - LangString DESC_sec_link ${LANG_FRENCH} "Associate RetroShare with .pqi file extension" - LangString DESC_sec_autostart ${LANG_FRENCH} "Run and Auto-connexion au démarrage" - LangString LANGUAGEID ${LANG_FRENCH} "1036" - - LangString sec_main ${LANG_GERMAN} "Programmdateien" - LangString sec_data ${LANG_GERMAN} "Skins f�r das Programm" - LangString sec_shortcuts ${LANG_GERMAN} "Shortcuts" - LangString sec_link ${LANG_GERMAN} "Dateiverkn�pfungen" - LangString sec_autostart ${LANG_GERMAN} "Auto Startup" - LangString DESC_sec_main ${LANG_GERMAN} "Installiert die erforderlichen Programmdateien." - LangString DESC_sec_data ${LANG_GERMAN} "Installiert RetroShare Skins" - LangString DESC_sec_shortcuts ${LANG_GERMAN} "Erstellt eine RetroShare Verkn�pfung im Startmen�, Desktop oder im Schnellstarter." - LangString DESC_sec_link ${LANG_GERMAN} "RetroShare mit .pqi Dateien verkn�pfen" - LangString DESC_sec_autostart ${LANG_GERMAN} "Beim Neustart automatisch RetroShare starten und sich anmelden" - LangString LANGUAGEID ${LANG_GERMAN} "1031" - - LangString sec_main ${LANG_TURKISH} "Program Dosyalar�" - LangString sec_data ${LANG_TURKISH} "Program Skinleri" - LangString sec_shortcuts ${LANG_TURKISH} "Shortcut'lar" - LangString sec_link ${LANG_TURKISH} ".pqi Dosya Kaydet" - LangString sec_autostart ${LANG_TURKISH} "Otomatik calistir ve baglan" - LangString DESC_sec_main ${LANG_TURKISH} "Program dosyalar�n� kurar." - LangString DESC_sec_data ${LANG_TURKISH} "RetroShare Skin'leri kurar" - LangString DESC_sec_shortcuts ${TURKISH} "Shortcut yap Start menu , Desktop veya Quicklaunchbar icin." - LangString DESC_sec_link ${LANG_TURKISH} "RetroShare .pqi almas� i�in kaydettirir" - LangString DESC_sec_autostart ${LANG_TURKISH} "Isletim sistemi acildiginda Otomatik olarak calistir ve baglan" - LangString LANGUAGEID ${LANG_TURKISH} "1055" - - LangString sec_main ${LANG_SIMPCHINESE} "程序文件" - LangString sec_data ${LANG_SIMPCHINESE} "程序皮肤" - LangString sec_shortcuts ${LANG_SIMPCHINESE} "快捷方式" - LangString sec_link ${LANG_SIMPCHINESE} "RetroShare文件关联" - LangString sec_autostart ${LANG_SIMPCHINESE} "自动启动" - LangString DESC_sec_main ${LANG_SIMPCHINESE} "安装RetroShare程序" - LangString DESC_sec_data ${LANG_SIMPCHINESE} "安装RetroShare皮肤" - LangString DESC_sec_shortcuts ${LANG_SIMPCHINESE} "建RetroShare快捷方式" - LangString DESC_sec_link ${LANG_SIMPCHINESE} "关联.pqi扩展名" - LangString DESC_sec_autostart ${LANG_SIMPCHINESE} "启动时自动运行和登录" - LangString LANGUAGEID ${LANG_SIMPCHINESE} "2052" - - LangString sec_main ${LANG_POLISH} "Pliki programu" - LangString sec_data ${LANG_POLISH} "Skórki" - LangString sec_shortcuts ${LANG_POLISH} "Skróty" - LangString sec_link ${LANG_POLISH} "Skojarz pliki" - LangString sec_autostart ${LANG_POLISH} "Automatyczne uruchamianie" - LangString DESC_sec_main ${LANG_POLISH} "Instaluje pliki programu RetroShare" - LangString DESC_sec_data ${LANG_POLISH} "Instaluje skórki programu RetroShare" - LangString DESC_sec_shortcuts ${LANG_POLISH} "Utwórz ikony skrótów na pulpicie, w menu start oraz na pasku szybkiego uruchamiania." - LangString DESC_sec_link ${LANG_POLISH} "Skojarz pliki o rozszerzeniu .pqi z RetroShare" - LangString DESC_sec_autostart ${LANG_POLISH} "Uruchom i zaloguj podczas startu systemu" - LangString LANGUAGEID ${LANG_POLISH} "1045" - - -!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS - -; CloseRetroShare: this will in a loop send the RetroShare window the WM_CLOSE -; message until it does not find a valid RetroShare window -; - -!macro CloseRetroShare UN -Function ${UN}CloseRetroShare - Push $0 - - IntFmt $R4 "%u" 0 - - goto skip - killloop: - DetailPrint "Killing RetroShare" - KillProcDLL::KillProc "RetroShare.exe" - loop: - Sleep 1000 - IntOp $R4 $R4 + 1 - IntCmp $R4 5 done - skip: - DetailPrint "Looking for running copies of RetroShare" - - ;Push "wxWindowClassNR" # the wcn - ;Push "RetroShare" # the known part of the wt - ;Call ${UN}EnhancedFindWindow - ;Pop $0 # will contain the window's handle - ;Pop $1 # will containg the full wcn - # both will containg "failed", if no matching wcn was found - - ;StrCmp $0 "failed" done - ;StrCmp $0 "0" done - ;DetailPrint "Stopping RetroShare" - ;SendMessage $0 16 0 0 # WM_CLOSE == 16 - Goto loop - done: - - IntFmt $R4 "%u" 0 - Processes::FindProcess "RetroShare.exe" - StrCmp $R0 "1" killloop reallydone - - reallydone: - Pop $0 -FunctionEnd -!macroend - - -!macro CheckForIt UN -Function ${UN}CheckForIt - - Processes::FindProcess $KILLEXENAME - StrCmp $R0 "1" foundit didntfindit - - foundit: - MessageBox MB_OKCANCEL "You must quit ${APPNAME} ($KILLEXENAME) \ - before installing this version.$\r$\nPlease quit it and press \ - OK to continue." IDOK tryagain - Abort - - tryagain: - - Sleep 2000 - Processes::FindProcess $KILLEXENAME - StrCmp $R0 "1" stillthere didntfindit - - stillthere: - MessageBox MB_OKCANCEL "There is still a copy of ${APPNAME} \ - ($KILLEXENAME) running.$\r$\nPress OK to force-quit the application, \ - or Cancel to exit." IDOK killit - Abort - - killit: - KillProcDLL::KillProc $KILLEXENAME - Sleep 1000 - - didntfindit: - -FunctionEnd -!macroend - -!macro QuitIt UN -Function ${UN}QuitIt - - # try nicely first - Call ${UN}CloseRetroShare - - # kill all the old ones - StrCpy $KILLEXENAME "RetroShare.exe" - Call ${UN}CheckForIt - StrCpy $KILLEXENAME "" -FunctionEnd -!macroend - - -; This function automatically uninstalls older versions. -; It is largely copied from: -; http://nsis.sourceforge.net/archive/viewpage.php?pageid=326 - - -Section $(sec_main) sec_main - - ;Set Section required - SectionIn RO - - ; Set Section properties - SetOverwrite on - - ; Clears previous error logs - Delete "$INSTDIR\*.log" - - ; Set Section Files and Shortcuts - SetOutPath "$INSTDIR\" - File /r "release\RetroShare.exe" - File /r "D:\Qt\2009.02\mingw\bin\mingwm10.dll" - File /r "D:\Qt\2009.02\qt\bin\QtCore4.dll" - File /r "D:\Qt\2009.02\qt\bin\QtGui4.dll" - File /r "D:\Qt\2009.02\qt\bin\QtNetwork4.dll" - File /r "D:\Qt\2009.02\qt\bin\QtXml4.dll" - File /r "D:\Qt\2009.02\qt\bin\QtScript4.dll" - File /r "pthreadGCE2.dll" - File /r "pthreadGC2d.dll" - File /r "changelog.txt" - - -SectionEnd - -Section $(sec_data) sec_data - - ; Set Section properties - SetOverwrite on - - ; Set Section Files and Shortcuts - SetOutPath "$APPDATA\RetroShare\" - ;File /r "data\*" - - ; We're not ready for external skins... - ; Set Section qss need to remove svn path - SetOutPath "$INSTDIR\qss\" - File /r qss\*.* - - ; Set Section skin - ; SetOutPath "$INSTDIR\skin\" - ; File /r release\skin\*.* - - ; Add emoticons - SetOutPath "$INSTDIR\emoticons\" - File /r emoticons\*.* - - ; Add Chat Style - SetOutPath "$INSTDIR\style\" - File /r style\*.* - -SectionEnd - -Section $(sec_link) sec_link - ; Delete any existing keys - - - ; Write the file association - WriteRegStr HKCR .pqi "" retroshare - WriteRegStr HKCR retroshare "" "PQI File" - WriteRegBin HKCR retroshare EditFlags 00000100 - WriteRegStr HKCR "retroshare\shell" "" open - WriteRegStr HKCR "retroshare\shell\open\command" "" `"$INSTDIR\RetroShare.exe" "%1"` - -SectionEnd - -SectionGroup $(sec_shortcuts) sec_shortcuts -Section StartMenu SEC0001 - - SetOutPath "$INSTDIR" - CreateDirectory "$SMPROGRAMS\${APPNAME}" - CreateShortCut "$SMPROGRAMS\${APPNAME}\$(^UninstallLink).lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 - CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 - -SectionEnd - -Section Desktop SEC0002 - - - CreateShortCut "$DESKTOP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 - -SectionEnd - -Section Quicklaunchbar SEC0003 - - - CreateShortCut "$QUICKLAUNCH\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 - -SectionEnd -SectionGroupEnd - -;Section $(sec_autostart) sec_autostart - -; WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" "$INSTDIR\${APPNAME}.exe -a" - -;SectionEnd - -Section $(sec_autostart) sec_autostart - - CreateShortCut "$SMSTARTUP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 -SectionEnd - - -Section -FinishSection - - WriteRegStr HKLM "Software\${APPNAME}" "" "$INSTDIR" - WriteRegStr HKLM "Software\${APPNAME}" "Version" "${VERSION}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$INSTDIR\uninstall.exe" - WriteUninstaller "$INSTDIR\uninstall.exe" - -SectionEnd - - - -;-------------------------------- -;Descriptions - -!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN - !insertmacro MUI_DESCRIPTION_TEXT ${sec_main} $(DESC_sec_main) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_data} $(DESC_sec_data) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_shortcuts} $(DESC_sec_shortcuts) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_link} $(DESC_sec_link) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_autostart} $(DESC_sec_autostart) -!insertmacro MUI_FUNCTION_DESCRIPTION_END - - -;!insertmacro EnhancedFindWindow "" -;!insertmacro EnhancedFindWindow "un." - -!insertmacro CloseRetroShare "" -!insertmacro CloseRetroShare "un." - -!insertmacro CheckForIt "" -!insertmacro CheckForIt "un." - -!insertmacro QuitIt "" -!insertmacro QuitIt "un." - -;Uninstall section -Section "Uninstall" - - Call un.QuitIt - - ; Remove file association registry keys - DeleteRegKey HKCR .pqi - DeleteRegKey HKCR retroshare - - ; Remove program/uninstall regsitry keys - DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" - DeleteRegKey HKLM SOFTWARE\${APPNAME} - - DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" - - ; Remove files and uninstaller - Delete $INSTDIR\RetroShare.exe - Delete $INSTDIR\*.dll - Delete $INSTDIR\*.dat - Delete $INSTDIR\*.txt - Delete $INSTDIR\*.ini - Delete $INSTDIR\*.log - - Delete $INSTDIR\uninstall.exe - - ; Remove the kadc.ini file. - ; Don't remove the directory, otherwise - ; we lose the XPGP keys. - ; Should make this an option though... - Delete "$APPDATA\${APPNAME}\kadc.ini" - Delete "$APPDATA\${APPNAME}\*.cfg" - Delete "$APPDATA\${APPNAME}\*.conf" - Delete "$APPDATA\${APPNAME}\*.log-save" - Delete "$APPDATA\${APPNAME}\*.log" - Delete "$APPDATA\${APPNAME}\*.failed" - - RMDir /r "$APPDATA\${APPNAME}\cache" - RMDir /r "$APPDATA\${APPNAME}\Partials" - - ; Remove shortcuts, if any - Delete "$SMPROGRAMS\${APPNAME}\*.*" - - ; Remove desktop shortcut - Delete "$DESKTOP\${APPNAME}.lnk" - - ; Remove Quicklaunch shortcut - Delete "$QUICKLAUNCH\${APPNAME}.lnk" - - ; Remove Autstart - Delete "$SMSTARTUP\${APPNAME}.lnk" - - ; Remove directories used - RMDir "$SMPROGRAMS\${APPNAME}" - RMDir /r "$INSTDIR" - RMDir /r "$INSTDIR\qss" - RMDir /r "$INSTDIR\emoticons" - RMDir /r "$INSTDIR\style" - -SectionEnd - -Function .onInit - - InitPluginsDir - Push $R1 - File /oname=$PLUGINSDIR\spltmp.bmp "gui\images\splash.bmp" - advsplash::show 1200 1000 1000 -1 $PLUGINSDIR\spltmp - Pop $R1 - Pop $R1 - !insertmacro MUI_LANGDLL_DISPLAY - -FunctionEnd - - -# Installer Language Strings -# TODO Update the Language Strings with the appropriate translations. - -LangString ^UninstallLink ${LANG_ENGLISH} "Uninstall" -LangString ^UninstallLink ${LANG_GERMAN} "Deinstallieren" -LangString ^UninstallLink ${LANG_TURKISH} "Kald�r" -LangString ^UninstallLink ${LANG_FRENCH} "Désinstaller" -LangString ^UninstallLink ${LANG_SIMPCHINESE} "卸载" -LangString ^UninstallLink ${LANG_POLISH} "Odinstaluj" - - - - - -; eof diff --git a/retroshare-gui/src/retroshare-ultramodern.nsi b/retroshare-gui/src/retroshare-ultramodern.nsi deleted file mode 100644 index d224cc8f1..000000000 --- a/retroshare-gui/src/retroshare-ultramodern.nsi +++ /dev/null @@ -1,501 +0,0 @@ -; Script generated with the Venis Install Wizard & modified by defnax - -; Define your application name -!define APPNAME "RetroShare" -!define VERSION "0.5.1 4049" -!define APPNAMEANDVERSION "${APPNAME} ${VERSION}" -!define QTBASE "D:\qt\2010.01" - -; Main Install settings -Name "${APPNAMEANDVERSION}" -InstallDir "$PROGRAMFILES\RetroShare" -InstallDirRegKey HKLM "Software\${APPNAME}" "" -OutFile "RetroShare_${VERSION}_setup_ultramodern.exe" -BrandingText "${APPNAMEANDVERSION}" -; Use compression -SetCompressor /SOLID LZMA - -; Modern interface settings -!include Sections.nsh -!include "UMUI.nsh" - -;Interface Settings -!define MUI_ABORTWARNING -;!define MUI_HEADERIMAGE -;!define MUI_HEADERIMAGE_BITMAP "retroshare.bmp" ; optional - -# MUI defines -!define MUI_ICON "${NSISDIR}\Contrib\Graphics\UltraModernUI\Icon.ico" -!define MUI_FINISHPAGE_NOAUTOCLOSE -!define MUI_LICENSEPAGE_RADIOBUTTONS -!define MUI_COMPONENTSPAGE_SMALLDESC -!define MUI_FINISHPAGE_LINK "Visit the RetroShare forum for the latest news and support" -!define MUI_FINISHPAGE_LINK_LOCATION "http://retroshare.sourceforge.net/forum/" -!define MUI_FINISHPAGE_RUN "$INSTDIR\RetroShare.exe" -!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\changelog.txt -!define MUI_FINISHPAGE_SHOWREADME_TEXT changelog.txt -!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED -!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\UltraModernUI\UnIcon.ico" -!define MUI_UNFINISHPAGE_NOAUTOCLOSE -!define MUI_LANGDLL_REGISTRY_ROOT HKLM -!define MUI_LANGDLL_REGISTRY_KEY ${REGKEY} -!define UMUI_LANGDLL_REGISTRY_VALUENAME InstallerLanguage - -;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIt is recommended that you close all other applications before starting Setup. This will make it possible to update relevant system files without havinf to reboot your computer. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " - -;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " - - -; Defines the un-/installer logo of RetroShare -!insertmacro MUI_DEFAULT MUI_WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange.bmp" -!insertmacro MUI_DEFAULT MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange-uninstall.bmp" - -; Set languages (first is default language) -!insertmacro MUI_RESERVEFILE_LANGDLL -ReserveFile "${NSISDIR}\Plugins\AdvSplash.dll" - -;-------------------------------- -;Configuration - - - ;!insertmacro MUI_RESERVEFILE_SPECIALBITMAP - - LicenseLangString myLicenseData 1030 "license\license.txt" - LicenseLangString myLicenseData 1033 "license\license.txt" - LicenseLangString myLicenseData 1031 "license\license-GER.txt" - LicenseLangString myLicenseData 1036 "license\license-FR.txt" - LicenseLangString myLicenseData 1055 "license\license-TR.txt" - LicenseLangString myLicenseData 2052 "license\license.txt" - LicenseLangString myLicenseData 1045 "license\license.txt" - LicenseLangString myLicenseData 1041 "license\license.txt" - LicenseLangString myLicenseData 1042 "license\license.txt" - LicenseLangString myLicenseData 1049 "license\license.txt" - LicenseLangString myLicenseData 1053 "license\license.txt" - - LicenseData $(myLicenseData) - -# Installer pages -!insertmacro MUI_PAGE_WELCOME -!insertmacro MUI_PAGE_LICENSE "$(myLicenseData)" -!insertmacro MUI_PAGE_COMPONENTS -!insertmacro MUI_PAGE_DIRECTORY -!insertmacro MUI_PAGE_INSTFILES -!insertmacro MUI_PAGE_FINISH -!insertmacro MUI_UNPAGE_CONFIRM -!insertmacro MUI_UNPAGE_INSTFILES - -# Installer languages -!define MUI_LANGDLL_ALLLANGUAGES - -!insertmacro MUI_LANGUAGE Danish -!insertmacro MUI_LANGUAGE English -!insertmacro MUI_LANGUAGE French -!insertmacro MUI_LANGUAGE German -!insertmacro MUI_LANGUAGE Japanese -!insertmacro MUI_LANGUAGE Korean -!insertmacro MUI_LANGUAGE Polish -!insertmacro MUI_LANGUAGE Russian -!insertmacro MUI_LANGUAGE Swedish -!insertmacro MUI_LANGUAGE SimpChinese -!insertmacro MUI_LANGUAGE Turkish - - - - ;Component-selection page - ;Titles - - LangString sec_main ${LANG_ENGLISH} "Program Files" - LangString sec_data ${LANG_ENGLISH} "Program Skins" - LangString sec_shortcuts ${LANG_ENGLISH} "Shortcuts" - LangString sec_link ${LANG_ENGLISH} "File Association" - LangString sec_autostart ${LANG_ENGLISH} "Auto Startup" - LangString DESC_sec_main ${LANG_ENGLISH} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_ENGLISH} "Installs RetroShare Skins" - LangString DESC_sec_shortcuts ${LANG_ENGLISH} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_ENGLISH} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_ENGLISH} "1033" - - - LangString sec_main ${LANG_FRENCH} "RetroShare" - LangString sec_data ${LANG_FRENCH} "Programme de Skins" - LangString sec_shortcuts ${LANG_FRENCH} "Raccourcis" - LangString sec_link ${LANG_FRENCH} "RetroShare fichiers Association" - LangString sec_startmenu ${LANG_FRENCH} "Raccourcis du menu Démarrer" - LangString sec_autostart ${LANG_FRENCH} "Démarrage automatique" - LangString DESC_sec_main ${LANG_FRENCH} "Installe les fichiers du programme." - LangString DESC_sec_data ${LANG_FRENCH} "Installe RetroShare Skins" - LangString DESC_sec_startmenu ${LANG_FRENCH} "Crée les raccourcis du menu Démarrer" - LangString DESC_sec_shortcuts ${LANG_FRENCH} "Crée une icône sur le bureau." - LangString DESC_sec_link ${LANG_FRENCH} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_FRENCH} "1036" - - - LangString sec_main ${LANG_GERMAN} "Programmdateien" - LangString sec_data ${LANG_GERMAN} "Skins fuer das Programm" - LangString sec_shortcuts ${LANG_GERMAN} "Shortcuts" - LangString sec_link ${LANG_GERMAN} "Dateiverknuepfungen" - LangString sec_autostart ${LANG_GERMAN} "Auto Startup" - LangString DESC_sec_main ${LANG_GERMAN} "Installiert die erforderlichen Programmdateien." - LangString DESC_sec_data ${LANG_GERMAN} "Installiert RetroShare Skins" - LangString DESC_sec_shortcuts ${LANG_GERMAN} "Erstellt eine RetroShare Verkn�pfung im Startmen�, Desktop oder im Schnellstarter." - LangString DESC_sec_link ${LANG_GERMAN} "RetroShare mit .rsc Dateien verkn�pfen" - LangString LANGUAGEID ${LANG_GERMAN} "1031" - - LangString sec_main ${LANG_TURKISH} "Program Dosyalar�" - LangString sec_data ${LANG_TURKISH} "Program Skinleri" - LangString sec_shortcuts ${LANG_TURKISH} "Shortcut'lar" - LangString sec_link ${LANG_TURKISH} ".rsc Dosya Kaydet" - LangString sec_autostart ${LANG_TURKISH} "Otomatik calistir ve baglan" - LangString DESC_sec_main ${LANG_TURKISH} "Program dosyalar�n� kurar." - LangString DESC_sec_data ${LANG_TURKISH} "RetroShare Skin'leri kurar" - LangString DESC_sec_shortcuts ${TURKISH} "Shortcut yap Start menu , Desktop veya Quicklaunchbar icin." - LangString DESC_sec_link ${LANG_TURKISH} "RetroShare .rsc almas� i�in kaydettirir" - LangString LANGUAGEID ${LANG_TURKISH} "1055" - - LangString sec_main ${LANG_SIMPCHINESE} "程序文件" - LangString sec_data ${LANG_SIMPCHINESE} "程序皮肤" - LangString sec_shortcuts ${LANG_SIMPCHINESE} "快捷方式" - LangString sec_link ${LANG_SIMPCHINESE} "RetroShare文件关联" - LangString sec_autostart ${LANG_SIMPCHINESE} "自动启动" - LangString DESC_sec_main ${LANG_SIMPCHINESE} "安装RetroShare程序" - LangString DESC_sec_data ${LANG_SIMPCHINESE} "安装RetroShare皮肤" - LangString DESC_sec_shortcuts ${LANG_SIMPCHINESE} "建RetroShare快捷方式" - LangString DESC_sec_link ${LANG_SIMPCHINESE} "关联.rsc扩" - LangString LANGUAGEID ${LANG_SIMPCHINESE} "2052" - - LangString sec_main ${LANG_POLISH} "Pliki programu" - LangString sec_data ${LANG_POLISH} "Skórki" - LangString sec_shortcuts ${LANG_POLISH} "Skróty" - LangString sec_link ${LANG_POLISH} "Skojarz pliki" - LangString sec_autostart ${LANG_POLISH} "Automatyczne uruchamianie" - LangString DESC_sec_main ${LANG_POLISH} "Instaluje pliki programu RetroShare" - LangString DESC_sec_data ${LANG_POLISH} "Instaluje skórki programu RetroShare" - LangString DESC_sec_shortcuts ${LANG_POLISH} "Utwórz ikony skrótów na pulpicie, w menu start oraz na pasku szybkiego uruchamiania." - LangString DESC_sec_link ${LANG_POLISH} "Skojarz pliki o rozszerzeniu .rsc z RetroShare" - LangString LANGUAGEID ${LANG_POLISH} "1045" - - LangString sec_main ${LANG_DANISH} "Program Files" - LangString sec_data ${LANG_DANISH} "Program Skins" - LangString sec_shortcuts ${LANG_DANISH} "Shortcuts" - LangString sec_link ${LANG_DANISH} "File Association" - LangString sec_autostart ${LANG_DANISH} "Auto Startup" - LangString DESC_sec_main ${LANG_DANISH} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_DANISH} "Installs RetroShare Skins" - LangString DESC_sec_shortcuts ${LANG_DANISH} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_DANISH} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_DANISH} "1030" - - LangString sec_main ${LANG_RUSSIAN} "Program Files" - LangString sec_data ${LANG_RUSSIAN} "Program Skins" - LangString sec_shortcuts ${LANG_RUSSIAN} "Shortcuts" - LangString sec_link ${LANG_RUSSIAN} "File Association" - LangString sec_autostart ${LANG_RUSSIAN} "Auto Startup" - LangString DESC_sec_main ${LANG_RUSSIAN} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_RUSSIAN} "Installs RetroShare Skins" - LangString DESC_sec_shortcuts ${LANG_RUSSIAN} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_RUSSIAN} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_RUSSIAN} "1049" - - LangString sec_main ${LANG_SWEDISH} "Program Files" - LangString sec_data ${LANG_SWEDISH} "Program Skins" - LangString sec_shortcuts ${LANG_SWEDISH} "Shortcuts" - LangString sec_link ${LANG_SWEDISH} "File Association" - LangString sec_autostart ${LANG_SWEDISH} "Auto Startup" - LangString DESC_sec_main ${LANG_SWEDISH} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_SWEDISH} "Installs RetroShare Skins" - LangString DESC_sec_shortcuts ${LANG_SWEDISH} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_SWEDISH} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_SWEDISH} "1053" - - LangString sec_main ${LANG_JAPANESE} "Program Files" - LangString sec_data ${LANG_JAPANESE} "Program Skins" - LangString sec_shortcuts ${LANG_JAPANESE} "Shortcuts" - LangString sec_link ${LANG_JAPANESE} "File Association" - LangString sec_autostart ${LANG_JAPANESE} "Auto Startup" - LangString DESC_sec_main ${LANG_JAPANESE} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_JAPANESE} "Installs RetroShare Skins" - LangString DESC_sec_shortcuts ${LANG_JAPANESE} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_JAPANESE} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_JAPANESE} "1041" - - LangString sec_main ${LANG_KOREAN} "Program Files" - LangString sec_data ${LANG_KOREAN} "Program Skins" - LangString sec_shortcuts ${LANG_KOREAN} "Shortcuts" - LangString sec_link ${LANG_KOREAN} "File Association" - LangString sec_autostart ${LANG_KOREAN} "Auto Startup" - LangString DESC_sec_main ${LANG_KOREAN} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_KOREAN} "Installs RetroShare Skins" - LangString DESC_sec_shortcuts ${LANG_KOREAN} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_KOREAN} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_KOREAN} "1042" - - -!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS - -Section $(sec_main) sec_main - - ;Set Section required - SectionIn RO - - ; Set Section properties - SetOverwrite on - - ; Clears previous error logs - Delete "$INSTDIR\*.log" - - ; Set Section Files and Shortcuts - SetOutPath "$INSTDIR\" - File /r "release\RetroShare.exe" - File /r "..\..\retroshare-nogui\src\release\retroshare-nogui.exe" - File /r "D:\Qt\2010.01\mingw\bin\mingwm10.dll" - File /r "D:\Qt\2010.01\qt\bin\QtCore4.dll" - File /r "D:\Qt\2010.01\qt\bin\QtGui4.dll" - File /r "D:\Qt\2010.01\qt\bin\QtNetwork4.dll" - File /r "D:\Qt\2010.01\qt\bin\QtXml4.dll" - File /r "D:\Qt\2010.01\qt\bin\QtScript4.dll" - File /r "D:\Qt\2010.01\qt\bin\libgcc_s_dw2-1.dll" - File /r "D:\Qt\2010.01\qt\plugins\imageformats" - File /r "D:\Development\miniupnpc-1.3\miniupnpc.dll" - File /r ${QTBASE}\qt\qt_*.qm - File /r "release\pthreadGC2d.dll" - File /r "release\libgpg-error-0.dll" - File /r "release\libgpgme-11.dll" - File /r "changelog.txt" - File /r /x Data "release\bdboot.txt" - - -SectionEnd - -Section $(sec_data) sec_data - - ; Set Section properties - SetOverwrite on - - ; Set Section Files and Shortcuts - SetOutPath "$APPDATA\RetroShare\" - ;File /r "data\*" - - ; Set Section Plugins - SetOutPath "$APPDATA\RetroShare\plugins\" - ;File /r "plugins\" - - ; Set Section qss and exclude svn - SetOutPath "$INSTDIR\qss\" - File /r /x .svn qss\*.* - - ; Set Section sounds and exclude svn - SetOutPath "$INSTDIR\sounds\" - File /r /x .svn sounds\*.* - - ; Set Section skin - ; SetOutPath "$INSTDIR\skin\" - ; File /r release\skin\*.* - - ; Add emoticons - ;SetOutPath "$INSTDIR\emoticons\" - ;File /r emoticons\*.* - - ; Add Chat Style - ;SetOutPath "$INSTDIR\style\" - ;File /r style\*.* - -SectionEnd - -; These are the programs that are needed by RetroShare. -Section -Prerequisites - SetOutPath $INSTDIR\Prerequisites - MessageBox MB_YESNO "$(InstallGPG4WIN)" /SD IDYES IDNO leave - File "Prerequisites\gpg4win-1.1.4.exe" - ExecWait "$INSTDIR\Prerequisites\gpg4win-1.1.4.exe" - - leave: -SectionEnd - -Section $(sec_link) sec_link - ; Delete any existing keys - - - ; Write the file association - WriteRegStr HKCR .rsc "" retroshare - WriteRegStr HKCR retroshare "" "RSC File" - WriteRegBin HKCR retroshare EditFlags 00000100 - WriteRegStr HKCR "retroshare\shell" "" open - WriteRegStr HKCR "retroshare\shell\open\command" "" `"$INSTDIR\RetroShare.exe" "%1"` - -SectionEnd - -SectionGroup $(sec_shortcuts) sec_shortcuts -Section StartMenu SEC0001 - - SetOutPath "$INSTDIR" - CreateDirectory "$SMPROGRAMS\${APPNAME}" - CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 - CreateShortCut "$SMPROGRAMS\${APPNAME}\$(^UninstallLink).lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 - -SectionEnd - -Section Desktop SEC0002 - - - CreateShortCut "$DESKTOP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 - -SectionEnd - -Section Quicklaunchbar SEC0003 - - - CreateShortCut "$QUICKLAUNCH\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 - -SectionEnd -SectionGroupEnd - -;Section $(sec_autostart) sec_autostart - -; WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" "$INSTDIR\${APPNAME}.exe -a" - -;SectionEnd - -;Section $(sec_autostart) sec_autostart - -; CreateShortCut "$SMSTARTUP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 -;SectionEnd - - -Section -FinishSection - - WriteRegStr HKLM "Software\${APPNAME}" "" "$INSTDIR" - WriteRegStr HKLM "Software\${APPNAME}" "Version" "${VERSION}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$INSTDIR\uninstall.exe" - WriteUninstaller "$INSTDIR\uninstall.exe" - -SectionEnd - - - -;-------------------------------- -;Descriptions - -!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN - !insertmacro MUI_DESCRIPTION_TEXT ${sec_main} $(DESC_sec_main) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_data} $(DESC_sec_data) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_shortcuts} $(DESC_sec_shortcuts) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_link} $(DESC_sec_link) - ;!insertmacro MUI_DESCRIPTION_TEXT ${sec_autostart} $(DESC_sec_autostart) -!insertmacro MUI_FUNCTION_DESCRIPTION_END - -;Uninstall section -Section "Uninstall" - - ; Remove file association registry keys - DeleteRegKey HKCR .rsc - DeleteRegKey HKCR retroshare - - ; Remove program/uninstall regsitry keys - DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" - DeleteRegKey HKLM SOFTWARE\${APPNAME} - - DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" - - ; Remove files and uninstaller - Delete $INSTDIR\RetroShare.exe - Delete $INSTDIR\*.dll - Delete $INSTDIR\*.dat - Delete $INSTDIR\*.txt - Delete $INSTDIR\*.ini - Delete $INSTDIR\*.log - - Delete $INSTDIR\uninstall.exe - - ; Remove the kadc.ini file. - ; Don't remove the directory, otherwise - ; we lose the XPGP keys. - ; Should make this an option though... - Delete "$APPDATA\${APPNAME}\kadc.ini" - Delete "$APPDATA\${APPNAME}\*.cfg" - Delete "$APPDATA\${APPNAME}\*.conf" - Delete "$APPDATA\${APPNAME}\*.log-save" - Delete "$APPDATA\${APPNAME}\*.log" - Delete "$APPDATA\${APPNAME}\*.failed" - - RMDir /r "$APPDATA\${APPNAME}\cache" - RMDir /r "$APPDATA\${APPNAME}\Partials" - - ; Remove shortcuts, if any - Delete "$SMPROGRAMS\${APPNAME}\*.*" - - ; Remove desktop shortcut - Delete "$DESKTOP\${APPNAME}.lnk" - - ; Remove Quicklaunch shortcut - Delete "$QUICKLAUNCH\${APPNAME}.lnk" - - ; Remove Autostart - ;Delete "$SMSTARTUP\${APPNAME}.lnk" - - ; Remove directories used - RMDir "$SMPROGRAMS\${APPNAME}" - RMDir /r "$INSTDIR" - RMDir /r "$INSTDIR\qss" - RMDir /r "$INSTDIR\emoticons" - RMDir /r "$INSTDIR\style" - RMDir /r "$INSTDIR\translations" - -SectionEnd - -Function .onInit - - InitPluginsDir - Push $R1 - File /oname=$PLUGINSDIR\spltmp.bmp "gui\images\splash.bmp" - advsplash::show 1200 1000 1000 -1 $PLUGINSDIR\spltmp - Pop $R1 - Pop $R1 - !insertmacro MUI_LANGDLL_DISPLAY - - - -FunctionEnd - - -# Installer Language Strings -# TODO Update the Language Strings with the appropriate translations. - -LangString InstallGPG4WIN ${LANG_ENGLISH} "Install Gpg4win ? Gpg4win is required for RetroShare!" -LangString InstallGPG4WIN ${LANG_GERMAN} "Installiere Gpg4win ? Gpg4win ist erforderlich fuer RetroShare!" -LangString InstallGPG4WIN ${LANG_TURKISH} "Gpg4win Yükle? Gpg4win RetroShare için gerekli!" -LangString InstallGPG4WIN ${LANG_FRENCH} "RetroShare a besoin de GPG4win pour fonctionner. Lancer l'installation de GPG4win?" -LangString InstallGPG4WIN ${LANG_SIMPCHINESE} "Install Gpg4win ? Gpg4win是需要Retroshare!" -LangString InstallGPG4WIN ${LANG_POLISH} "Install Gpg4win ? Gpg4win wymagane jest Retroshare!" -LangString InstallGPG4WIN ${LANG_DANISH} "Installer Gpg4win? Gpg4win er nødvendig for RetroShare!" -LangString InstallGPG4WIN ${LANG_JAPANESE} "Install Gpg4win ? Gpg4win is required for RetroShare!" -LangString InstallGPG4WIN ${LANG_KOREAN} "Install Gpg4win ? Gpg4win is required for RetroShare!" -LangString InstallGPG4WIN ${LANG_RUSSIAN} "Install Gpg4win ? Gpg4win is required for RetroShare!" -LangString InstallGPG4WIN ${LANG_SWEDISH} "Installera Gpg4win? Gpg4win krävs för RetroShare!" - -LangString FINISHPAGELINK ${LANG_ENGLISH} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_GERMAN} "Besuche RetroShare Support Forum " -LangString FINISHPAGELINK ${LANG_TURKISH} "Destek için Retroshare foruma ziyaret" -LangString FINISHPAGELINK ${LANG_FRENCH} "Consultez le forum RetroShare pour vous tenir au courant des dernieres modifications, et obtenir de l'aide." -LangString FINISHPAGELINK ${LANG_SIMPCHINESE} "帮助论坛" -LangString FINISHPAGELINK ${LANG_POLISH} "Odwiedź forum RetroShare do najświeższych informacji i wsparcia" -LangString FINISHPAGELINK ${LANG_DANISH} "Besøg RetroShare fora for de seneste nyheder og støtte" -LangString FINISHPAGELINK ${LANG_JAPANESE} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_KOREAN} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_RUSSIAN} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_SWEDISH} "Besök RetroShare forum för de senaste nyheterna och stöd" - -LangString ^UninstallLink ${LANG_ENGLISH} "Uninstall" -LangString ^UninstallLink ${LANG_GERMAN} "Deinstallieren" -LangString ^UninstallLink ${LANG_TURKISH} "Kald�r" -LangString ^UninstallLink ${LANG_FRENCH} "Désinstaller" -LangString ^UninstallLink ${LANG_SIMPCHINESE} "卸载" -LangString ^UninstallLink ${LANG_POLISH} "Odinstaluj" -LangString ^UninstallLink ${LANG_DANISH} "Afinstaller" -LangString ^UninstallLink ${LANG_JAPANESE} "Uninstall" -LangString ^UninstallLink ${LANG_KOREAN} "Uninstall" -LangString ^UninstallLink ${LANG_RUSSIAN} "Uninstall" -LangString ^UninstallLink ${LANG_SWEDISH} "Avinstallera" - - -; eof diff --git a/retroshare-gui/src/retroshare.in b/retroshare-gui/src/retroshare.in deleted file mode 100644 index 994d26d7c..000000000 --- a/retroshare-gui/src/retroshare.in +++ /dev/null @@ -1,594 +0,0 @@ -; Script generated with the Venis Install Wizard & modified by defnax - -; Define your application name -!define APPNAME "RetroShare" -!define VERSION "0.5.4e" -!define REVISION "$WCREV$" -!define APPNAMEANDVERSION "${APPNAME} ${VERSION} ${REVISION}" -!define QTBASE "d:\qt\2010.05" -!define RSBASE "d:\Development\retroshare\retroshare-gui\" - -; Main Install settings -Name "${APPNAMEANDVERSION}" -InstallDir "$PROGRAMFILES\RetroShare" -InstallDirRegKey HKLM "Software\${APPNAME}" "" -OutFile "RetroShare_${VERSION}_${REVISION}_setup.exe" -BrandingText "${APPNAMEANDVERSION}" -; Use compression -SetCompressor /SOLID LZMA - -; Modern interface settings -!include Sections.nsh -!include "MUI.nsh" - -;Interface Settings -!define MUI_ABORTWARNING -;!define MUI_HEADERIMAGE -;!define MUI_HEADERIMAGE_BITMAP "retroshare.bmp" ; optional - -# MUI defines -!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\orange-install.ico" -!define MUI_FINISHPAGE_NOAUTOCLOSE -!define MUI_LICENSEPAGE_RADIOBUTTONS -!define MUI_COMPONENTSPAGE_SMALLDESC -!define MUI_FINISHPAGE_LINK "$(FINISHPAGELINK)" -!define MUI_FINISHPAGE_LINK_LOCATION "http://retroshare.sourceforge.net/forum/" -!define MUI_FINISHPAGE_RUN "$INSTDIR\RetroShare.exe" -!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\changelog.txt -!define MUI_FINISHPAGE_SHOWREADME_TEXT changelog.txt -!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED -!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\orange-uninstall.ico" -!define MUI_UNFINISHPAGE_NOAUTOCLOSE -!define MUI_LANGDLL_REGISTRY_ROOT HKLM -!define MUI_LANGDLL_REGISTRY_KEY ${REGKEY} -!define MUI_LANGDLL_REGISTRY_VALUENAME InstallerLanguage - -;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIt is recommended that you close all other applications before starting Setup. This will make it possible to update relevant system files without havinf to reboot your computer. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " - -;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " - - -; Defines the un-/installer logo of RetroShare -!insertmacro MUI_DEFAULT MUI_WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange.bmp" -!insertmacro MUI_DEFAULT MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange-uninstall.bmp" - -; Set languages (first is default language) -!insertmacro MUI_RESERVEFILE_LANGDLL -ReserveFile "${NSISDIR}\Plugins\AdvSplash.dll" - -;-------------------------------- -;Configuration - - - ;!insertmacro MUI_RESERVEFILE_SPECIALBITMAP - - LicenseLangString myLicenseData 1030 "license\license.txt" - LicenseLangString myLicenseData 1031 "license\license-GER.txt" - LicenseLangString myLicenseData 1032 "license\license-GR.txt" - LicenseLangString myLicenseData 1033 "license\license.txt" - LicenseLangString myLicenseData 1034 "license\license-SP.txt" - LicenseLangString myLicenseData 1036 "license\license-FR.txt" - LicenseLangString myLicenseData 1040 "license\license-IT.txt" - LicenseLangString myLicenseData 1041 "license\license.txt" - LicenseLangString myLicenseData 1042 "license\license.txt" - LicenseLangString myLicenseData 1045 "license\license.txt" - LicenseLangString myLicenseData 1046 "license\license-PT_BR.txt" - LicenseLangString myLicenseData 1049 "license\license.txt" - LicenseLangString myLicenseData 1053 "license\license.txt" - LicenseLangString myLicenseData 1055 "license\license-TR.txt" - LicenseLangString myLicenseData 2052 "license\license.txt" - - LicenseData $(myLicenseData) - -# Installer pages -!insertmacro MUI_PAGE_WELCOME -!insertmacro MUI_PAGE_LICENSE "$(myLicenseData)" -!insertmacro MUI_PAGE_COMPONENTS -!insertmacro MUI_PAGE_DIRECTORY -!insertmacro MUI_PAGE_INSTFILES -!insertmacro MUI_PAGE_FINISH -!insertmacro MUI_UNPAGE_CONFIRM -!insertmacro MUI_UNPAGE_INSTFILES - -# Installer languages -!define MUI_LANGDLL_ALLLANGUAGES - -!insertmacro MUI_LANGUAGE English -!insertmacro MUI_LANGUAGE Danish -!insertmacro MUI_LANGUAGE French -!insertmacro MUI_LANGUAGE German -!insertmacro MUI_LANGUAGE Greek -!insertmacro MUI_LANGUAGE Italian -!insertmacro MUI_LANGUAGE Japanese -!insertmacro MUI_LANGUAGE Korean -!insertmacro MUI_LANGUAGE Polish -!insertmacro MUI_LANGUAGE PortugueseBR -!insertmacro MUI_LANGUAGE Russian -!insertmacro MUI_LANGUAGE Swedish -!insertmacro MUI_LANGUAGE SimpChinese -!insertmacro MUI_LANGUAGE Spanish -!insertmacro MUI_LANGUAGE Turkish - - - ;Component-selection page - ;Titles - - LangString sec_main ${LANG_ENGLISH} "Program Files" - LangString sec_data ${LANG_ENGLISH} "Program Skins" - LangString sec_shortcuts ${LANG_ENGLISH} "Shortcuts" - LangString sec_plugins ${LANG_ENGLISH} "Plugins" - LangString sec_link ${LANG_ENGLISH} "File Association" - LangString sec_autostart ${LANG_ENGLISH} "Auto Startup" - LangString DESC_sec_main ${LANG_ENGLISH} "Installs the RetroShare program files." - LangString DESC_sec_plugins ${LANG_ENGLISH} "Installs the RetroShare plugins." - LangString DESC_sec_data ${LANG_ENGLISH} "Installs RetroShare Skins" - LangString DESC_sec_shortcuts ${LANG_ENGLISH} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_ENGLISH} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_ENGLISH} "1033" - - LangString sec_main ${LANG_FRENCH} "RetroShare" - LangString sec_data ${LANG_FRENCH} "Programme de Skins" - LangString sec_plugins ${LANG_FRENCH} "Plugins" - LangString sec_shortcuts ${LANG_FRENCH} "Raccourcis" - LangString sec_link ${LANG_FRENCH} "Association de fichiers" - LangString sec_startmenu ${LANG_FRENCH} "Raccourcis du menu Démarrer" - LangString sec_autostart ${LANG_FRENCH} "Démarrage automatique" - LangString DESC_sec_main ${LANG_FRENCH} "Installation des fichiers du programme." - LangString DESC_sec_data ${LANG_FRENCH} "Installation des Skins de RetroShare" - LangString DESC_sec_plugins ${LANG_FRENCH} "Installation des extensions de RetroShare " - LangString DESC_sec_startmenu ${LANG_FRENCH} "Création des raccourcis du menu Démarrer" - LangString DESC_sec_shortcuts ${LANG_FRENCH} "Création de l'icône sur le bureau." - LangString DESC_sec_link ${LANG_FRENCH} "Associer RetroShare avec l'extension de fichier .rsc" - LangString LANGUAGEID ${LANG_FRENCH} "1036" - - LangString sec_main ${LANG_GERMAN} "Programme" - LangString sec_data ${LANG_GERMAN} "Programm Skins" - LangString sec_plugins ${LANG_GERMAN} "Plug-ins" - LangString sec_shortcuts ${LANG_GERMAN} "Verknüpfungen" - LangString sec_link ${LANG_GERMAN} "Dateiverknüpfungen" - LangString sec_autostart ${LANG_GERMAN} "Autostart" - LangString DESC_sec_main ${LANG_GERMAN} "Installiert die RetroShare Programmdateien." - LangString DESC_sec_data ${LANG_GERMAN} "Installiert RetroShare Skins" - LangString DESC_sec_plugins ${LANG_GERMAN} "Installiert die RetroShare Erweiterungen." - LangString DESC_sec_shortcuts ${LANG_GERMAN} "RetroShare Verknüpfung im Startmenüe, Desktop oder im Schnellstarter erstellen." - LangString DESC_sec_link ${LANG_GERMAN} "RetroShare mit .rsc Dateiendung verknüpfen" - LangString LANGUAGEID ${LANG_GERMAN} "1031" - - LangString sec_main ${LANG_TURKISH} "Program Dosyalar?" - LangString sec_data ${LANG_TURKISH} "Program Skinleri" - LangString sec_shortcuts ${LANG_TURKISH} "Shortcut'lar" - LangString sec_plugins ${LANG_TURKISH} "Eklentiler" - LangString sec_link ${LANG_TURKISH} ".rsc Dosya Kaydet" - LangString sec_autostart ${LANG_TURKISH} "Otomatik calistir ve baglan" - LangString DESC_sec_main ${LANG_TURKISH} "Program dosyalar?n? kurar." - LangString DESC_sec_data ${LANG_TURKISH} "RetroShare Skin'leri kurar" - LangString DESC_sec_plugins ${LANG_TURKISH} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${TURKISH} "Shortcut yap Start menu , Desktop veya Quicklaunchbar icin." - LangString DESC_sec_link ${LANG_TURKISH} "RetroShare .rsc almas? i?in kaydettirir" - LangString LANGUAGEID ${LANG_TURKISH} "1055" - - LangString sec_main ${LANG_SIMPCHINESE} "程序文件" - LangString sec_data ${LANG_SIMPCHINESE} "程序皮肤" - LangString sec_plugins ${LANG_SIMPCHINESE} "Plugins" - LangString sec_shortcuts ${LANG_SIMPCHINESE} "快捷方式" - LangString sec_link ${LANG_SIMPCHINESE} "RetroShare文件关联" - LangString sec_autostart ${LANG_SIMPCHINESE} "自动启动" - LangString DESC_sec_main ${LANG_SIMPCHINESE} "安装RetroShare程序" - LangString DESC_sec_data ${LANG_SIMPCHINESE} "安装RetroShare皮肤" - LangString DESC_sec_plugins ${LANG_SIMPCHINESE} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_SIMPCHINESE} "建RetroShare快捷方式" - LangString DESC_sec_link ${LANG_SIMPCHINESE} "关联.rsc扩展名" - LangString LANGUAGEID ${LANG_SIMPCHINESE} "2052" - - LangString sec_main ${LANG_POLISH} "Pliki programu" - LangString sec_data ${LANG_POLISH} "Skórki" - LangString sec_plugins ${LANG_POLISH} "Plugins" - LangString sec_shortcuts ${LANG_POLISH} "Skróty" - LangString sec_link ${LANG_POLISH} "Skojarz pliki" - LangString sec_autostart ${LANG_POLISH} "Automatyczne uruchamianie" - LangString DESC_sec_main ${LANG_POLISH} "Instaluje pliki programu RetroShare" - LangString DESC_sec_data ${LANG_POLISH} "Instaluje skórki programu RetroShare" - LangString DESC_sec_plugins ${LANG_POLISH} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_POLISH} "Utwórz ikony skrótów na pulpicie, w menu start oraz na pasku szybkiego uruchamiania." - LangString DESC_sec_link ${LANG_POLISH} "Skojarz pliki o rozszerzeniu .rsc z RetroShare" - LangString LANGUAGEID ${LANG_POLISH} "1045" - - LangString sec_main ${LANG_DANISH} "Program Files" - LangString sec_data ${LANG_DANISH} "Program Skins" - LangString sec_plugins ${LANG_DANISH} "Plugins" - LangString sec_shortcuts ${LANG_DANISH} "Shortcuts" - LangString sec_link ${LANG_DANISH} "File Association" - LangString sec_autostart ${LANG_DANISH} "Auto Startup" - LangString DESC_sec_main ${LANG_DANISH} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_DANISH} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_DANISH} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_DANISH} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_DANISH} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_DANISH} "1030" - - LangString sec_main ${LANG_RUSSIAN} "Program Files" - LangString sec_data ${LANG_RUSSIAN} "Program Skins" - LangString sec_plugins ${LANG_RUSSIAN} "Plugins" - LangString sec_shortcuts ${LANG_RUSSIAN} "Shortcuts" - LangString sec_link ${LANG_RUSSIAN} "File Association" - LangString sec_autostart ${LANG_RUSSIAN} "Auto Startup" - LangString DESC_sec_main ${LANG_RUSSIAN} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_RUSSIAN} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_RUSSIAN} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_RUSSIAN} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_RUSSIAN} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_RUSSIAN} "1049" - - LangString sec_main ${LANG_SWEDISH} "Program Files" - LangString sec_data ${LANG_SWEDISH} "Program Skins" - LangString sec_plugins ${LANG_SWEDISH} "Plugins" - LangString sec_shortcuts ${LANG_SWEDISH} "Shortcuts" - LangString sec_link ${LANG_SWEDISH} "File Association" - LangString sec_autostart ${LANG_SWEDISH} "Auto Startup" - LangString DESC_sec_main ${LANG_SWEDISH} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_SWEDISH} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_SWEDISH} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_SWEDISH} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_SWEDISH} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_SWEDISH} "1053" - - LangString sec_main ${LANG_SPANISH} "Archivos de programa" - LangString sec_data ${LANG_SPANISH} "Estilos del programa" - LangString sec_plugins ${LANG_SPANISH} "Plugins" - LangString sec_shortcuts ${LANG_SPANISH} "Accesos directos" - LangString sec_link ${LANG_SPANISH} "Asociación de archivos" - LangString sec_autostart ${LANG_SPANISH} "Inicio automático" - LangString DESC_sec_main ${LANG_SPANISH} "Instala los archivos del programa RetroShare." - LangString DESC_sec_data ${LANG_SPANISH} "Instala los estilos para RetroShare" - LangString DESC_sec_plugins ${LANG_SPANISH} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_SPANISH} "Crear iconos de acceso directo de RetroShare." - LangString DESC_sec_link ${LANG_SPANISH} "Asociar RetroShare con la extensión de archivo .rsc" - LangString LANGUAGEID ${LANG_SPANISH} "1034" - - LangString sec_main ${LANG_ITALIAN} "Programmi" - LangString sec_data ${LANG_ITALIAN} "Temi del Programma" - LangString sec_plugins ${LANG_ITALIAN} "Plugins" - LangString sec_shortcuts ${LANG_ITALIAN} "Icone" - LangString sec_link ${LANG_ITALIAN} "Associazione dei File" - LangString sec_autostart ${LANG_ITALIAN} "Esecuzione Automatica" - LangString DESC_sec_main ${LANG_ITALIAN} "Installare i file programma di RetroShare." - LangString DESC_sec_data ${LANG_ITALIAN} "Installare i temi di RetroShare" - LangString DESC_sec_plugins ${LANG_ITALIAN} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_ITALIAN} "Creare le icone per avviare RetroShare." - LangString DESC_sec_link ${LANG_ITALIAN} "Associa a RetroShare i file con estensione .rsc" - LangString LANGUAGEID ${LANG_ITALIAN} "1040" - - LangString sec_main ${LANG_GREEK} "Program Files" - LangString sec_data ${LANG_GREEK} "Program Skins" - LangString sec_plugins ${LANG_GREEK} "Plugins" - LangString sec_shortcuts ${LANG_GREEK} "Shortcuts" - LangString sec_link ${LANG_GREEK} "File Association" - LangString sec_autostart ${LANG_GREEK} "Auto Startup" - LangString DESC_sec_main ${LANG_GREEK} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_GREEK} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_GREEK} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_GREEK} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_GREEK} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_GREEK} "1032" - - LangString sec_main ${LANG_PORTUGUESEBR} "Program Files" - LangString sec_data ${LANG_PORTUGUESEBR} "Program Skins" - LangString sec_plugins ${LANG_PORTUGUESEBR} "Plugins" - LangString sec_shortcuts ${LANG_PORTUGUESEBR} "Shortcuts" - LangString sec_link ${LANG_PORTUGUESEBR} "File Association" - LangString sec_autostart ${LANG_PORTUGUESEBR} "Auto Startup" - LangString DESC_sec_main ${LANG_PORTUGUESEBR} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_PORTUGUESEBR} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_PORTUGUESEBR} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_PORTUGUESEBR} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_PORTUGUESEBR} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_PORTUGUESEBR} "1046" - - LangString sec_main ${LANG_JAPANESE} "Program Files" - LangString sec_data ${LANG_JAPANESE} "Program Skins" - LangString sec_plugins ${LANG_JAPANESE} "Plugins" - LangString sec_shortcuts ${LANG_JAPANESE} "Shortcuts" - LangString sec_link ${LANG_JAPANESE} "File Association" - LangString sec_autostart ${LANG_JAPANESE} "Auto Startup" - LangString DESC_sec_main ${LANG_JAPANESE} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_JAPANESE} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_JAPANESE} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_JAPANESE} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_JAPANESE} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_JAPANESE} "1041" - - LangString sec_main ${LANG_KOREAN} "Program Files" - LangString sec_data ${LANG_KOREAN} "Program Skins" - LangString sec_plugins ${LANG_KOREAN} "Plugins" - LangString sec_shortcuts ${LANG_KOREAN} "Shortcuts" - LangString sec_link ${LANG_KOREAN} "File Association" - LangString sec_autostart ${LANG_KOREAN} "Auto Startup" - LangString DESC_sec_main ${LANG_KOREAN} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_KOREAN} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_KOREAN} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_KOREAN} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_KOREAN} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_KOREAN} "1042" - - -!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS - -Section $(sec_main) sec_main - - ;Set Section required - SectionIn RO - - ; Set Section properties - SetOverwrite on - - ; Clears previous error logs - Delete "$INSTDIR\*.log" - - ; Set Section Files and Shortcuts - SetOutPath "$INSTDIR\" - File /r "release\RetroShare.exe" - File /r "..\..\retroshare-nogui\src\release\retroshare-nogui.exe" - File /r "${QTBASE}\mingw\bin\mingwm10.dll" - File /r "${QTBASE}\qt\bin\QtCore4.dll" - File /r "${QTBASE}\qt\bin\QtGui4.dll" - File /r "${QTBASE}\qt\bin\QtNetwork4.dll" - File /r "${QTBASE}\qt\bin\QtMultimedia4.dll" - File /r "${QTBASE}\qt\bin\QtXml4.dll" - File /r "${QTBASE}\qt\bin\QtScript4.dll" - File /r "${QTBASE}\qt\bin\QtSvg4.dll" - File /r "${QTBASE}\qt\bin\libgcc_s_dw2-1.dll" - File /r "${QTBASE}\qt\plugins\imageformats" - File /r ${QTBASE}\qt\qt_*.qm - File /r ${RSBASE}\src\qt_*.qm - File /r "release\pthreadGC2d.dll" - File /r "d:\Development\lib\libminiupnpc-1.3\miniupnpc.dll" - File /r "changelog.txt" - File /r /x Data "release\bdboot.txt" - - -SectionEnd - -Section $(sec_data) sec_data - - ; Set Section properties - SetOverwrite on - - ; Set Section Files and Shortcuts - SetOutPath "$APPDATA\RetroShare\" - ;File /r "data\*" - - ; Set Section qss and exclude svn - SetOutPath "$INSTDIR\qss\" - File /r /x .svn qss\*.* - - ; Set Section sounds and exclude svn - SetOutPath "$INSTDIR\sounds\" - File /r /x .svn sounds\*.* - - ; Set Section skin - ; SetOutPath "$INSTDIR\skin\" - ; File /r release\skin\*.* - - ; Add emoticons - ;SetOutPath "$INSTDIR\emoticons\" - ;File /r emoticons\*.* - - ; Add Chat Style - SetOutPath "$APPDATA\RetroShare\stylesheets\" - File /r gui\qss\chat\Bubble - File /r gui\qss\chat\Bubble_Compact - - -SectionEnd - -SectionGroup $(sec_plugins) sec_plugins -Section Voip SEC001 - - ; Set Section properties - SetOverwrite on - - ; Set Section Plugins - SetOutPath "$APPDATA\RetroShare\extensions\" - - File /r "..\..\plugins\VOIP\release\VOIP.dll" - -SectionEnd - -Section FeedReader SEC002 - - ; Set Section properties - SetOverwrite on - - ; Set Section Plugins - SetOutPath "$APPDATA\RetroShare\extensions\" - - File /r "..\..\plugins\FeedReader\release\FeedReader.dll" - -SectionEnd -SectionGroupEnd - -Section $(sec_link) sec_link - ; Delete any existing keys - - - ; Write the file association - WriteRegStr HKCR .rsc "" retroshare - WriteRegStr HKCR retroshare "" "RSC File" - WriteRegBin HKCR retroshare EditFlags 00000100 - WriteRegStr HKCR "retroshare\shell" "" open - WriteRegStr HKCR "retroshare\shell\open\command" "" `"$INSTDIR\RetroShare.exe" "%1"` - -SectionEnd - -SectionGroup $(sec_shortcuts) sec_shortcuts -Section StartMenu SEC0001 - - SetOutPath "$INSTDIR" - CreateDirectory "$SMPROGRAMS\${APPNAME}" - CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 - CreateShortCut "$SMPROGRAMS\${APPNAME}\$(^UninstallLink).lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 - -SectionEnd - -Section Desktop SEC0002 - - - CreateShortCut "$DESKTOP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 - -SectionEnd - -Section Quicklaunchbar SEC0003 - - - CreateShortCut "$QUICKLAUNCH\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 - -SectionEnd -SectionGroupEnd - -;Section $(sec_autostart) sec_autostart - -; WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" "$INSTDIR\${APPNAME}.exe -a" - -;SectionEnd - -;Section $(sec_autostart) sec_autostart - -; CreateShortCut "$SMSTARTUP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 -;SectionEnd - - -Section -FinishSection - - WriteRegStr HKLM "Software\${APPNAME}" "" "$INSTDIR" - WriteRegStr HKLM "Software\${APPNAME}" "Version" "${VERSION}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$INSTDIR\uninstall.exe" - WriteUninstaller "$INSTDIR\uninstall.exe" - -SectionEnd - - - -;-------------------------------- -;Descriptions - -!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN - !insertmacro MUI_DESCRIPTION_TEXT ${sec_main} $(DESC_sec_main) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_data} $(DESC_sec_data) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_plugins} $(DESC_sec_plugins) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_shortcuts} $(DESC_sec_shortcuts) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_link} $(DESC_sec_link) - ;!insertmacro MUI_DESCRIPTION_TEXT ${sec_autostart} $(DESC_sec_autostart) -!insertmacro MUI_FUNCTION_DESCRIPTION_END - -;Uninstall section -Section "Uninstall" - - ; Remove file association registry keys - DeleteRegKey HKCR .rsc - DeleteRegKey HKCR retroshare - - ; Remove program/uninstall regsitry keys - DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" - DeleteRegKey HKLM SOFTWARE\${APPNAME} - - DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" - - ; Remove files and uninstaller - Delete $INSTDIR\RetroShare.exe - Delete $INSTDIR\*.dll - Delete $INSTDIR\*.dat - Delete $INSTDIR\*.txt - Delete $INSTDIR\*.ini - Delete $INSTDIR\*.log - - Delete $INSTDIR\uninstall.exe - - ; Remove the kadc.ini file. - ; Don't remove the directory, otherwise - ; we lose the XPGP keys. - ; Should make this an option though... - Delete "$APPDATA\${APPNAME}\kadc.ini" - Delete "$APPDATA\${APPNAME}\*.cfg" - Delete "$APPDATA\${APPNAME}\*.conf" - Delete "$APPDATA\${APPNAME}\*.log-save" - Delete "$APPDATA\${APPNAME}\*.log" - Delete "$APPDATA\${APPNAME}\*.failed" - - RMDir /r "$APPDATA\${APPNAME}\cache" - RMDir /r "$APPDATA\${APPNAME}\Partials" - - ; Remove shortcuts, if any - Delete "$SMPROGRAMS\${APPNAME}\*.*" - - ; Remove desktop shortcut - Delete "$DESKTOP\${APPNAME}.lnk" - - ; Remove Quicklaunch shortcut - Delete "$QUICKLAUNCH\${APPNAME}.lnk" - - ; Remove Autostart - ;Delete "$SMSTARTUP\${APPNAME}.lnk" - - ; Remove directories used - RMDir "$SMPROGRAMS\${APPNAME}" - RMDir /r "$INSTDIR" - RMDir /r "$INSTDIR\qss" - RMDir /r "$INSTDIR\emoticons" - RMDir /r "$INSTDIR\style" - RMDir /r "$INSTDIR\translations" - -SectionEnd - -Function .onInit - - InitPluginsDir - Push $R1 - File /oname=$PLUGINSDIR\spltmp.bmp "gui\images\splash.bmp" - advsplash::show 1200 1000 1000 -1 $PLUGINSDIR\spltmp - Pop $R1 - Pop $R1 - !insertmacro MUI_LANGDLL_DISPLAY - - - -FunctionEnd - - -# Installer Language Strings -# TODO Update the Language Strings with the appropriate translations. - - -LangString FINISHPAGELINK ${LANG_ENGLISH} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_GERMAN} "Das RetroShare Support-Forum besuchen, um Neuigkeiten und Unterstützung zu erfahren" -LangString FINISHPAGELINK ${LANG_TURKISH} "Destek için Retroshare foruma ziyaret et" -LangString FINISHPAGELINK ${LANG_FRENCH} "Consultez le forum RetroShare pour vous tenir au courant des dernieres modifications, et obtenir de l'aide." -LangString FINISHPAGELINK ${LANG_SIMPCHINESE} "帮助论坛" -LangString FINISHPAGELINK ${LANG_POLISH} "Odwiedź forum RetroShare do najświeższych informacji i wsparcia" -LangString FINISHPAGELINK ${LANG_DANISH} "Besøg RetroShare fora for de seneste nyheder og støtte" -LangString FINISHPAGELINK ${LANG_JAPANESE} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_KOREAN} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_RUSSIAN} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_SWEDISH} "Besök RetroShare forum för de senaste nyheterna och stöd" -LangString FINISHPAGELINK ${LANG_SPANISH} "Visite los foros de RetroShare para las últimas noticias y soporte" -LangString FINISHPAGELINK ${LANG_ITALIAN} "Visita i forum di RetroShare per le ultime novità ed il supporto" -LangString FINISHPAGELINK ${LANG_GREEK} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_PORTUGUESEBR} "Visit the RetroShare forums for the latest news and support" - -LangString ^UninstallLink ${LANG_ENGLISH} "Uninstall" -LangString ^UninstallLink ${LANG_GERMAN} "Deinstallieren" -LangString ^UninstallLink ${LANG_TURKISH} "Kald�r" -LangString ^UninstallLink ${LANG_FRENCH} "Désinstaller" -LangString ^UninstallLink ${LANG_SIMPCHINESE} "卸载" -LangString ^UninstallLink ${LANG_POLISH} "Odinstaluj" -LangString ^UninstallLink ${LANG_DANISH} "Afinstaller" -LangString ^UninstallLink ${LANG_JAPANESE} "Uninstall" -LangString ^UninstallLink ${LANG_KOREAN} "Uninstall" -LangString ^UninstallLink ${LANG_RUSSIAN} "Uninstall" -LangString ^UninstallLink ${LANG_SWEDISH} "Avinstallera" -LangString ^UninstallLink ${LANG_SPANISH} "Desinstalar" -LangString ^UninstallLink ${LANG_ITALIAN} "Disinstallare" -LangString ^UninstallLink ${LANG_GREEK} "Απεγκατάσταση" -LangString ^UninstallLink ${LANG_PORTUGUESEBR} "Desinstalar" - -; eof diff --git a/retroshare-gui/src/retroshare.nsi b/retroshare-gui/src/retroshare.nsi deleted file mode 100644 index 9a604b44a..000000000 --- a/retroshare-gui/src/retroshare.nsi +++ /dev/null @@ -1,595 +0,0 @@ -; Script generated with the Venis Install Wizard & modified by defnax - -; Define your application name -!define APPNAME "RetroShare" -!define VERSION "0.5.5a" -!define REVISION "6725" -!define APPNAMEANDVERSION "${APPNAME} ${VERSION} ${REVISION}" -!define QTBASE "h:\qt\2010.05" -!define RSBASE "h:\Development\retroshare\retroshare-gui\" - -; Main Install settings -Name "${APPNAMEANDVERSION}" -InstallDir "$PROGRAMFILES\RetroShare" -InstallDirRegKey HKLM "Software\${APPNAME}" "" -OutFile "RetroShare_${VERSION}_${REVISION}_setup.exe" -BrandingText "${APPNAMEANDVERSION}" -; Use compression -SetCompressor /SOLID LZMA - -; Modern interface settings -!include Sections.nsh -!include "MUI.nsh" - -;Interface Settings -!define MUI_ABORTWARNING -;!define MUI_HEADERIMAGE -;!define MUI_HEADERIMAGE_BITMAP "retroshare.bmp" ; optional - -# MUI defines -!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\orange-install.ico" -!define MUI_FINISHPAGE_NOAUTOCLOSE -!define MUI_LICENSEPAGE_RADIOBUTTONS -!define MUI_COMPONENTSPAGE_SMALLDESC -!define MUI_FINISHPAGE_LINK "$(FINISHPAGELINK)" -!define MUI_FINISHPAGE_LINK_LOCATION "http://retroshare.sourceforge.net/forum/" -!define MUI_FINISHPAGE_RUN "$INSTDIR\RetroShare.exe" -!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\changelog.txt -!define MUI_FINISHPAGE_SHOWREADME_TEXT changelog.txt -!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED -!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\orange-uninstall.ico" -!define MUI_UNFINISHPAGE_NOAUTOCLOSE -!define MUI_LANGDLL_REGISTRY_ROOT HKLM -!define MUI_LANGDLL_REGISTRY_KEY ${REGKEY} -!define MUI_LANGDLL_REGISTRY_VALUENAME InstallerLanguage - -;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIt is recommended that you close all other applications before starting Setup. This will make it possible to update relevant system files without havinf to reboot your computer. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " - -;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " - - -; Defines the un-/installer logo of RetroShare -!insertmacro MUI_DEFAULT MUI_WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange.bmp" -!insertmacro MUI_DEFAULT MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange-uninstall.bmp" - -; Set languages (first is default language) -!insertmacro MUI_RESERVEFILE_LANGDLL -ReserveFile "${NSISDIR}\Plugins\AdvSplash.dll" - -;-------------------------------- -;Configuration - - - ;!insertmacro MUI_RESERVEFILE_SPECIALBITMAP - - LicenseLangString myLicenseData 1030 "license\license.txt" - LicenseLangString myLicenseData 1031 "license\license-GER.txt" - LicenseLangString myLicenseData 1032 "license\license-GR.txt" - LicenseLangString myLicenseData 1033 "license\license.txt" - LicenseLangString myLicenseData 1034 "license\license-SP.txt" - LicenseLangString myLicenseData 1036 "license\license-FR.txt" - LicenseLangString myLicenseData 1040 "license\license-IT.txt" - LicenseLangString myLicenseData 1041 "license\license.txt" - LicenseLangString myLicenseData 1042 "license\license.txt" - LicenseLangString myLicenseData 1045 "license\license.txt" - LicenseLangString myLicenseData 1046 "license\license-PT_BR.txt" - LicenseLangString myLicenseData 1049 "license\license.txt" - LicenseLangString myLicenseData 1053 "license\license.txt" - LicenseLangString myLicenseData 1055 "license\license-TR.txt" - LicenseLangString myLicenseData 2052 "license\license.txt" - - LicenseData $(myLicenseData) - -# Installer pages -!insertmacro MUI_PAGE_WELCOME -!insertmacro MUI_PAGE_LICENSE "$(myLicenseData)" -!insertmacro MUI_PAGE_COMPONENTS -!insertmacro MUI_PAGE_DIRECTORY -!insertmacro MUI_PAGE_INSTFILES -!insertmacro MUI_PAGE_FINISH -!insertmacro MUI_UNPAGE_CONFIRM -!insertmacro MUI_UNPAGE_INSTFILES - -# Installer languages -!define MUI_LANGDLL_ALLLANGUAGES - -!insertmacro MUI_LANGUAGE English -!insertmacro MUI_LANGUAGE Danish -!insertmacro MUI_LANGUAGE French -!insertmacro MUI_LANGUAGE German -!insertmacro MUI_LANGUAGE Greek -!insertmacro MUI_LANGUAGE Italian -!insertmacro MUI_LANGUAGE Japanese -!insertmacro MUI_LANGUAGE Korean -!insertmacro MUI_LANGUAGE Polish -!insertmacro MUI_LANGUAGE PortugueseBR -!insertmacro MUI_LANGUAGE Russian -!insertmacro MUI_LANGUAGE Swedish -!insertmacro MUI_LANGUAGE SimpChinese -!insertmacro MUI_LANGUAGE Spanish -!insertmacro MUI_LANGUAGE Turkish - - - ;Component-selection page - ;Titles - - LangString sec_main ${LANG_ENGLISH} "Program Files" - LangString sec_data ${LANG_ENGLISH} "Program Skins" - LangString sec_shortcuts ${LANG_ENGLISH} "Shortcuts" - LangString sec_plugins ${LANG_ENGLISH} "Plugins" - LangString sec_link ${LANG_ENGLISH} "File Association" - LangString sec_autostart ${LANG_ENGLISH} "Auto Startup" - LangString DESC_sec_main ${LANG_ENGLISH} "Installs the RetroShare program files." - LangString DESC_sec_plugins ${LANG_ENGLISH} "Installs the RetroShare plugins." - LangString DESC_sec_data ${LANG_ENGLISH} "Installs RetroShare Skins" - LangString DESC_sec_shortcuts ${LANG_ENGLISH} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_ENGLISH} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_ENGLISH} "1033" - - LangString sec_main ${LANG_FRENCH} "RetroShare" - LangString sec_data ${LANG_FRENCH} "Programme de Skins" - LangString sec_plugins ${LANG_FRENCH} "Plugins" - LangString sec_shortcuts ${LANG_FRENCH} "Raccourcis" - LangString sec_link ${LANG_FRENCH} "Association de fichiers" - LangString sec_startmenu ${LANG_FRENCH} "Raccourcis du menu Démarrer" - LangString sec_autostart ${LANG_FRENCH} "Démarrage automatique" - LangString DESC_sec_main ${LANG_FRENCH} "Installation des fichiers du programme." - LangString DESC_sec_data ${LANG_FRENCH} "Installation des Skins de RetroShare" - LangString DESC_sec_plugins ${LANG_FRENCH} "Installation des extensions de RetroShare " - LangString DESC_sec_startmenu ${LANG_FRENCH} "Création des raccourcis du menu Démarrer" - LangString DESC_sec_shortcuts ${LANG_FRENCH} "Création de l'icône sur le bureau." - LangString DESC_sec_link ${LANG_FRENCH} "Associer RetroShare avec l'extension de fichier .rsc" - LangString LANGUAGEID ${LANG_FRENCH} "1036" - - LangString sec_main ${LANG_GERMAN} "Programme" - LangString sec_data ${LANG_GERMAN} "Programm Skins" - LangString sec_plugins ${LANG_GERMAN} "Plug-ins" - LangString sec_shortcuts ${LANG_GERMAN} "Verknüpfungen" - LangString sec_link ${LANG_GERMAN} "Dateiverknüpfungen" - LangString sec_autostart ${LANG_GERMAN} "Autostart" - LangString DESC_sec_main ${LANG_GERMAN} "Installiert die RetroShare Programmdateien." - LangString DESC_sec_data ${LANG_GERMAN} "Installiert RetroShare Skins" - LangString DESC_sec_plugins ${LANG_GERMAN} "Installiert die RetroShare Erweiterungen." - LangString DESC_sec_shortcuts ${LANG_GERMAN} "RetroShare Verknüpfung im Startmenüe, Desktop oder im Schnellstarter erstellen." - LangString DESC_sec_link ${LANG_GERMAN} "RetroShare mit .rsc Dateiendung verknüpfen" - LangString LANGUAGEID ${LANG_GERMAN} "1031" - - LangString sec_main ${LANG_TURKISH} "Program Dosyalar?" - LangString sec_data ${LANG_TURKISH} "Program Skinleri" - LangString sec_shortcuts ${LANG_TURKISH} "Shortcut'lar" - LangString sec_plugins ${LANG_TURKISH} "Eklentiler" - LangString sec_link ${LANG_TURKISH} ".rsc Dosya Kaydet" - LangString sec_autostart ${LANG_TURKISH} "Otomatik calistir ve baglan" - LangString DESC_sec_main ${LANG_TURKISH} "Program dosyalar?n? kurar." - LangString DESC_sec_data ${LANG_TURKISH} "RetroShare Skin'leri kurar" - LangString DESC_sec_plugins ${LANG_TURKISH} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${TURKISH} "Shortcut yap Start menu , Desktop veya Quicklaunchbar icin." - LangString DESC_sec_link ${LANG_TURKISH} "RetroShare .rsc almas? i?in kaydettirir" - LangString LANGUAGEID ${LANG_TURKISH} "1055" - - LangString sec_main ${LANG_SIMPCHINESE} "程序文件" - LangString sec_data ${LANG_SIMPCHINESE} "程序皮肤" - LangString sec_plugins ${LANG_SIMPCHINESE} "Plugins" - LangString sec_shortcuts ${LANG_SIMPCHINESE} "快捷方式" - LangString sec_link ${LANG_SIMPCHINESE} "RetroShare文件关联" - LangString sec_autostart ${LANG_SIMPCHINESE} "自动启动" - LangString DESC_sec_main ${LANG_SIMPCHINESE} "安装RetroShare程序" - LangString DESC_sec_data ${LANG_SIMPCHINESE} "安装RetroShare皮肤" - LangString DESC_sec_plugins ${LANG_SIMPCHINESE} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_SIMPCHINESE} "建RetroShare快捷方式" - LangString DESC_sec_link ${LANG_SIMPCHINESE} "关联.rsc扩展名" - LangString LANGUAGEID ${LANG_SIMPCHINESE} "2052" - - LangString sec_main ${LANG_POLISH} "Pliki programu" - LangString sec_data ${LANG_POLISH} "Skórki" - LangString sec_plugins ${LANG_POLISH} "Plugins" - LangString sec_shortcuts ${LANG_POLISH} "Skróty" - LangString sec_link ${LANG_POLISH} "Skojarz pliki" - LangString sec_autostart ${LANG_POLISH} "Automatyczne uruchamianie" - LangString DESC_sec_main ${LANG_POLISH} "Instaluje pliki programu RetroShare" - LangString DESC_sec_data ${LANG_POLISH} "Instaluje skórki programu RetroShare" - LangString DESC_sec_plugins ${LANG_POLISH} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_POLISH} "Utwórz ikony skrótów na pulpicie, w menu start oraz na pasku szybkiego uruchamiania." - LangString DESC_sec_link ${LANG_POLISH} "Skojarz pliki o rozszerzeniu .rsc z RetroShare" - LangString LANGUAGEID ${LANG_POLISH} "1045" - - LangString sec_main ${LANG_DANISH} "Program Files" - LangString sec_data ${LANG_DANISH} "Program Skins" - LangString sec_plugins ${LANG_DANISH} "Plugins" - LangString sec_shortcuts ${LANG_DANISH} "Shortcuts" - LangString sec_link ${LANG_DANISH} "File Association" - LangString sec_autostart ${LANG_DANISH} "Auto Startup" - LangString DESC_sec_main ${LANG_DANISH} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_DANISH} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_DANISH} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_DANISH} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_DANISH} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_DANISH} "1030" - - LangString sec_main ${LANG_RUSSIAN} "Program Files" - LangString sec_data ${LANG_RUSSIAN} "Program Skins" - LangString sec_plugins ${LANG_RUSSIAN} "Plugins" - LangString sec_shortcuts ${LANG_RUSSIAN} "Shortcuts" - LangString sec_link ${LANG_RUSSIAN} "File Association" - LangString sec_autostart ${LANG_RUSSIAN} "Auto Startup" - LangString DESC_sec_main ${LANG_RUSSIAN} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_RUSSIAN} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_RUSSIAN} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_RUSSIAN} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_RUSSIAN} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_RUSSIAN} "1049" - - LangString sec_main ${LANG_SWEDISH} "Program Files" - LangString sec_data ${LANG_SWEDISH} "Program Skins" - LangString sec_plugins ${LANG_SWEDISH} "Plugins" - LangString sec_shortcuts ${LANG_SWEDISH} "Shortcuts" - LangString sec_link ${LANG_SWEDISH} "File Association" - LangString sec_autostart ${LANG_SWEDISH} "Auto Startup" - LangString DESC_sec_main ${LANG_SWEDISH} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_SWEDISH} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_SWEDISH} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_SWEDISH} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_SWEDISH} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_SWEDISH} "1053" - - LangString sec_main ${LANG_SPANISH} "Archivos de programa" - LangString sec_data ${LANG_SPANISH} "Estilos del programa" - LangString sec_plugins ${LANG_SPANISH} "Plugins" - LangString sec_shortcuts ${LANG_SPANISH} "Accesos directos" - LangString sec_link ${LANG_SPANISH} "Asociación de archivos" - LangString sec_autostart ${LANG_SPANISH} "Inicio automático" - LangString DESC_sec_main ${LANG_SPANISH} "Instala los archivos del programa RetroShare." - LangString DESC_sec_data ${LANG_SPANISH} "Instala los estilos para RetroShare" - LangString DESC_sec_plugins ${LANG_SPANISH} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_SPANISH} "Crear iconos de acceso directo de RetroShare." - LangString DESC_sec_link ${LANG_SPANISH} "Asociar RetroShare con la extensión de archivo .rsc" - LangString LANGUAGEID ${LANG_SPANISH} "1034" - - LangString sec_main ${LANG_ITALIAN} "Programmi" - LangString sec_data ${LANG_ITALIAN} "Temi del Programma" - LangString sec_plugins ${LANG_ITALIAN} "Plugins" - LangString sec_shortcuts ${LANG_ITALIAN} "Icone" - LangString sec_link ${LANG_ITALIAN} "Associazione dei File" - LangString sec_autostart ${LANG_ITALIAN} "Esecuzione Automatica" - LangString DESC_sec_main ${LANG_ITALIAN} "Installare i file programma di RetroShare." - LangString DESC_sec_data ${LANG_ITALIAN} "Installare i temi di RetroShare" - LangString DESC_sec_plugins ${LANG_ITALIAN} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_ITALIAN} "Creare le icone per avviare RetroShare." - LangString DESC_sec_link ${LANG_ITALIAN} "Associa a RetroShare i file con estensione .rsc" - LangString LANGUAGEID ${LANG_ITALIAN} "1040" - - LangString sec_main ${LANG_GREEK} "Program Files" - LangString sec_data ${LANG_GREEK} "Program Skins" - LangString sec_plugins ${LANG_GREEK} "Plugins" - LangString sec_shortcuts ${LANG_GREEK} "Shortcuts" - LangString sec_link ${LANG_GREEK} "File Association" - LangString sec_autostart ${LANG_GREEK} "Auto Startup" - LangString DESC_sec_main ${LANG_GREEK} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_GREEK} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_GREEK} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_GREEK} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_GREEK} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_GREEK} "1032" - - LangString sec_main ${LANG_PORTUGUESEBR} "Program Files" - LangString sec_data ${LANG_PORTUGUESEBR} "Program Skins" - LangString sec_plugins ${LANG_PORTUGUESEBR} "Plugins" - LangString sec_shortcuts ${LANG_PORTUGUESEBR} "Shortcuts" - LangString sec_link ${LANG_PORTUGUESEBR} "File Association" - LangString sec_autostart ${LANG_PORTUGUESEBR} "Auto Startup" - LangString DESC_sec_main ${LANG_PORTUGUESEBR} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_PORTUGUESEBR} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_PORTUGUESEBR} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_PORTUGUESEBR} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_PORTUGUESEBR} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_PORTUGUESEBR} "1046" - - LangString sec_main ${LANG_JAPANESE} "Program Files" - LangString sec_data ${LANG_JAPANESE} "Program Skins" - LangString sec_plugins ${LANG_JAPANESE} "Plugins" - LangString sec_shortcuts ${LANG_JAPANESE} "Shortcuts" - LangString sec_link ${LANG_JAPANESE} "File Association" - LangString sec_autostart ${LANG_JAPANESE} "Auto Startup" - LangString DESC_sec_main ${LANG_JAPANESE} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_JAPANESE} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_JAPANESE} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_JAPANESE} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_JAPANESE} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_JAPANESE} "1041" - - LangString sec_main ${LANG_KOREAN} "Program Files" - LangString sec_data ${LANG_KOREAN} "Program Skins" - LangString sec_plugins ${LANG_KOREAN} "Plugins" - LangString sec_shortcuts ${LANG_KOREAN} "Shortcuts" - LangString sec_link ${LANG_KOREAN} "File Association" - LangString sec_autostart ${LANG_KOREAN} "Auto Startup" - LangString DESC_sec_main ${LANG_KOREAN} "Installs the RetroShare program files." - LangString DESC_sec_data ${LANG_KOREAN} "Installs RetroShare Skins" - LangString DESC_sec_plugins ${LANG_KOREAN} "Installs the RetroShare plugins." - LangString DESC_sec_shortcuts ${LANG_KOREAN} "Create RetroShare shortcut icons." - LangString DESC_sec_link ${LANG_KOREAN} "Associate RetroShare with .rsc file extension" - LangString LANGUAGEID ${LANG_KOREAN} "1042" - - -!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS - -Section $(sec_main) sec_main - - ;Set Section required - SectionIn RO - - ; Set Section properties - SetOverwrite on - - ; Clears previous error logs - Delete "$INSTDIR\*.log" - - ; Set Section Files and Shortcuts - SetOutPath "$INSTDIR\" - File /r "release\RetroShare.exe" - File /r "..\..\retroshare-nogui\src\release\retroshare-nogui.exe" - File /r "${QTBASE}\mingw\bin\mingwm10.dll" - File /r "${QTBASE}\qt\bin\QtCore4.dll" - File /r "${QTBASE}\qt\bin\QtGui4.dll" - File /r "${QTBASE}\qt\bin\QtNetwork4.dll" - File /r "${QTBASE}\qt\bin\QtMultimedia4.dll" - File /r "${QTBASE}\qt\bin\QtXml4.dll" - File /r "${QTBASE}\qt\bin\QtScript4.dll" - File /r "${QTBASE}\qt\bin\QtSvg4.dll" - File /r "${QTBASE}\qt\bin\libgcc_s_dw2-1.dll" - File /r "${QTBASE}\qt\plugins\imageformats" - File /r ${QTBASE}\qt\qt_*.qm - File /r ${RSBASE}\src\qt_*.qm - File /r "release\pthreadGC2d.dll" - File /r "h:\Development\lib\libminiupnpc-1.3\miniupnpc.dll" - File /r "changelog.txt" - File /r /x Data "release\bdboot.txt" - - -SectionEnd - -Section $(sec_data) sec_data - - ; Set Section properties - SetOverwrite on - - ; Set Section Files and Shortcuts - SetOutPath "$APPDATA\RetroShare\" - ;File /r "data\*" - - ; Set Section qss and exclude svn - SetOutPath "$INSTDIR\qss\" - File /r /x .svn qss\*.* - - ; Set Section sounds and exclude svn - SetOutPath "$INSTDIR\sounds\" - File /r /x .svn sounds\*.* - - ; Set Section skin - ; SetOutPath "$INSTDIR\skin\" - ; File /r release\skin\*.* - - ; Add emoticons - ;SetOutPath "$INSTDIR\emoticons\" - ;File /r emoticons\*.* - - ; Add Chat Style - SetOutPath "$APPDATA\RetroShare\stylesheets\" - File /r gui\qss\chat\Bubble - File /r gui\qss\chat\Bubble_Compact - - -SectionEnd - -SectionGroup $(sec_plugins) sec_plugins -Section Voip SEC001 - - ; Set Section properties - SetOverwrite on - - ; Set Section Plugins - SetOutPath "$APPDATA\RetroShare\extensions\" - - File /r "..\..\plugins\VOIP\release\VOIP.dll" - -SectionEnd - -Section FeedReader SEC002 - - ; Set Section properties - SetOverwrite on - - ; Set Section Plugins - SetOutPath "$APPDATA\RetroShare\extensions\" - - File /r "..\..\plugins\FeedReader\release\FeedReader.dll" - -SectionEnd - -SectionGroupEnd - -Section $(sec_link) sec_link - ; Delete any existing keys - - - ; Write the file association - WriteRegStr HKCR .rsc "" retroshare - WriteRegStr HKCR retroshare "" "RSC File" - WriteRegBin HKCR retroshare EditFlags 00000100 - WriteRegStr HKCR "retroshare\shell" "" open - WriteRegStr HKCR "retroshare\shell\open\command" "" `"$INSTDIR\RetroShare.exe" "%1"` - -SectionEnd - -SectionGroup $(sec_shortcuts) sec_shortcuts -Section StartMenu SEC0001 - - SetOutPath "$INSTDIR" - CreateDirectory "$SMPROGRAMS\${APPNAME}" - CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 - CreateShortCut "$SMPROGRAMS\${APPNAME}\$(^UninstallLink).lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 - -SectionEnd - -Section Desktop SEC0002 - - - CreateShortCut "$DESKTOP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 - -SectionEnd - -Section Quicklaunchbar SEC0003 - - - CreateShortCut "$QUICKLAUNCH\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 - -SectionEnd -SectionGroupEnd - -;Section $(sec_autostart) sec_autostart - -; WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" "$INSTDIR\${APPNAME}.exe -a" - -;SectionEnd - -;Section $(sec_autostart) sec_autostart - -; CreateShortCut "$SMSTARTUP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 -;SectionEnd - - -Section -FinishSection - - WriteRegStr HKLM "Software\${APPNAME}" "" "$INSTDIR" - WriteRegStr HKLM "Software\${APPNAME}" "Version" "${VERSION}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$INSTDIR\uninstall.exe" - WriteUninstaller "$INSTDIR\uninstall.exe" - -SectionEnd - - - -;-------------------------------- -;Descriptions - -!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN - !insertmacro MUI_DESCRIPTION_TEXT ${sec_main} $(DESC_sec_main) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_data} $(DESC_sec_data) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_plugins} $(DESC_sec_plugins) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_shortcuts} $(DESC_sec_shortcuts) - !insertmacro MUI_DESCRIPTION_TEXT ${sec_link} $(DESC_sec_link) - ;!insertmacro MUI_DESCRIPTION_TEXT ${sec_autostart} $(DESC_sec_autostart) -!insertmacro MUI_FUNCTION_DESCRIPTION_END - -;Uninstall section -Section "Uninstall" - - ; Remove file association registry keys - DeleteRegKey HKCR .rsc - DeleteRegKey HKCR retroshare - - ; Remove program/uninstall regsitry keys - DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" - DeleteRegKey HKLM SOFTWARE\${APPNAME} - - DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" - - ; Remove files and uninstaller - Delete $INSTDIR\RetroShare.exe - Delete $INSTDIR\*.dll - Delete $INSTDIR\*.dat - Delete $INSTDIR\*.txt - Delete $INSTDIR\*.ini - Delete $INSTDIR\*.log - - Delete $INSTDIR\uninstall.exe - - ; Remove the kadc.ini file. - ; Don't remove the directory, otherwise - ; we lose the XPGP keys. - ; Should make this an option though... - Delete "$APPDATA\${APPNAME}\kadc.ini" - Delete "$APPDATA\${APPNAME}\*.cfg" - Delete "$APPDATA\${APPNAME}\*.conf" - Delete "$APPDATA\${APPNAME}\*.log-save" - Delete "$APPDATA\${APPNAME}\*.log" - Delete "$APPDATA\${APPNAME}\*.failed" - - RMDir /r "$APPDATA\${APPNAME}\cache" - RMDir /r "$APPDATA\${APPNAME}\Partials" - - ; Remove shortcuts, if any - Delete "$SMPROGRAMS\${APPNAME}\*.*" - - ; Remove desktop shortcut - Delete "$DESKTOP\${APPNAME}.lnk" - - ; Remove Quicklaunch shortcut - Delete "$QUICKLAUNCH\${APPNAME}.lnk" - - ; Remove Autostart - ;Delete "$SMSTARTUP\${APPNAME}.lnk" - - ; Remove directories used - RMDir "$SMPROGRAMS\${APPNAME}" - RMDir /r "$INSTDIR" - RMDir /r "$INSTDIR\qss" - RMDir /r "$INSTDIR\emoticons" - RMDir /r "$INSTDIR\style" - RMDir /r "$INSTDIR\translations" - -SectionEnd - -Function .onInit - - InitPluginsDir - Push $R1 - File /oname=$PLUGINSDIR\spltmp.bmp "gui\images\splash.bmp" - advsplash::show 1200 1000 1000 -1 $PLUGINSDIR\spltmp - Pop $R1 - Pop $R1 - !insertmacro MUI_LANGDLL_DISPLAY - - - -FunctionEnd - - -# Installer Language Strings -# TODO Update the Language Strings with the appropriate translations. - - -LangString FINISHPAGELINK ${LANG_ENGLISH} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_GERMAN} "Das RetroShare Support-Forum besuchen, um Neuigkeiten und Unterstützung zu erfahren" -LangString FINISHPAGELINK ${LANG_TURKISH} "Destek için Retroshare foruma ziyaret et" -LangString FINISHPAGELINK ${LANG_FRENCH} "Consultez le forum RetroShare pour vous tenir au courant des dernieres modifications, et obtenir de l'aide." -LangString FINISHPAGELINK ${LANG_SIMPCHINESE} "帮助论坛" -LangString FINISHPAGELINK ${LANG_POLISH} "Odwiedź forum RetroShare do najświeższych informacji i wsparcia" -LangString FINISHPAGELINK ${LANG_DANISH} "Besøg RetroShare fora for de seneste nyheder og støtte" -LangString FINISHPAGELINK ${LANG_JAPANESE} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_KOREAN} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_RUSSIAN} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_SWEDISH} "Besök RetroShare forum för de senaste nyheterna och stöd" -LangString FINISHPAGELINK ${LANG_SPANISH} "Visite los foros de RetroShare para las últimas noticias y soporte" -LangString FINISHPAGELINK ${LANG_ITALIAN} "Visita i forum di RetroShare per le ultime novità ed il supporto" -LangString FINISHPAGELINK ${LANG_GREEK} "Visit the RetroShare forums for the latest news and support" -LangString FINISHPAGELINK ${LANG_PORTUGUESEBR} "Visit the RetroShare forums for the latest news and support" - -LangString ^UninstallLink ${LANG_ENGLISH} "Uninstall" -LangString ^UninstallLink ${LANG_GERMAN} "Deinstallieren" -LangString ^UninstallLink ${LANG_TURKISH} "Kald�r" -LangString ^UninstallLink ${LANG_FRENCH} "Désinstaller" -LangString ^UninstallLink ${LANG_SIMPCHINESE} "卸载" -LangString ^UninstallLink ${LANG_POLISH} "Odinstaluj" -LangString ^UninstallLink ${LANG_DANISH} "Afinstaller" -LangString ^UninstallLink ${LANG_JAPANESE} "Uninstall" -LangString ^UninstallLink ${LANG_KOREAN} "Uninstall" -LangString ^UninstallLink ${LANG_RUSSIAN} "Uninstall" -LangString ^UninstallLink ${LANG_SWEDISH} "Avinstallera" -LangString ^UninstallLink ${LANG_SPANISH} "Desinstalar" -LangString ^UninstallLink ${LANG_ITALIAN} "Disinstallare" -LangString ^UninstallLink ${LANG_GREEK} "Απεγκατάσταση" -LangString ^UninstallLink ${LANG_PORTUGUESEBR} "Desinstalar" - -; eof diff --git a/retroshare-gui/src/rshare.cpp b/retroshare-gui/src/rshare.cpp index cbed6698a..d867f1545 100644 --- a/retroshare-gui/src/rshare.cpp +++ b/retroshare-gui/src/rshare.cpp @@ -50,55 +50,22 @@ #include #include +#include #include #include #include #include "rshare.h" -/* Available command-line arguments. */ -#define ARG_RESET "reset" /**< Reset Rshare's saved settings. */ -#define ARG_DATADIR "datadir" /**< Directory to use for data files. */ -#define ARG_LOGFILE "logfile" /**< Location of our logfile. */ -#define ARG_LOGLEVEL "loglevel" /**< Log verbosity. */ -#define ARG_GUISTYLE "style" /**< Argument specfying GUI style. */ -#define ARG_GUISTYLESHEET "stylesheet" /**< Argument specfying GUI style. */ -#define ARG_LANGUAGE "lang" /**< Argument specifying language. */ -#define ARG_OPMODE_S "o" /**< OpMode (Full, NoTurtle, Gaming, Minimal) */ -#define ARG_OPMODE_L "opmode" /**< OpMode (Full, NoTurtle, Gaming, Minimal) */ -#define ARG_RSLINK_S "r" /**< Open RsLink with protocol retroshare:// */ -#define ARG_RSLINK_L "link" /**< Open RsLink with protocol retroshare:// */ -#define ARG_RSFILE_S "f" /**< Open RsFile with or without arg. */ -#define ARG_RSFILE_L "rsfile" /**< Open RsFile with or without arg. */ -//Other defined for server in /libretroshare/src/rsserver/rsinit.cc:351 +#ifdef __APPLE__ +QStringList RsApplication::_links; /**< List of links passed by arguments. */ +QStringList RsApplication::_files; /**< List of files passed by arguments. */ +#endif -// The arguments here can be send to a running instance. -// If the command line contains arguments not listed here, we have to start a new instance. -// For example, the user wants to start a second instance using --base-dir arg of libretroshare. -static const char* const forwardableArgs[] = { - ARG_OPMODE_S, - ARG_OPMODE_L, - ARG_RSLINK_S, - ARG_RSLINK_L, - ARG_RSFILE_S, - ARG_RSFILE_L, - NULL, -}; - -/* Static member variables */ -QMap Rshare::_args; /**< List of command-line arguments. */ -Log Rshare::_log; /**< Logs debugging messages to file or stdout. */ -QString Rshare::_style; /**< The current GUI style. */ -QString Rshare::_stylesheet; /**< The current GUI stylesheet. */ -QString Rshare::_language; /**< The current language. */ -QString Rshare::_dateformat; /**< The format of dates in feed items etc. */ -QString Rshare::_opmode; /**< The operating mode passed by args. */ -QStringList Rshare::_links; /**< List of links passed by arguments. */ -QStringList Rshare::_files; /**< List of files passed by arguments. */ -QDateTime Rshare::mStartupTime; -bool Rshare::useConfigDir; -QString Rshare::configDir; -QLocalServer* Rshare::localServer; +Log RsApplication::log_output; /**< Logs debugging messages to file or stdout. */ +RsGUIConfigOptions RsApplication::options; +QDateTime RsApplication::mStartupTime; +QLocalServer* RsApplication::localServer; /** Catches debugging messages from Qt and sends them to RetroShare's logs. If Qt * emits a QtFatalMsg, we will write the message to the log and then abort(). @@ -133,189 +100,87 @@ void qt_msg_handler(QtMsgType type, const char *msg) } } -static bool notifyRunningInstance() -{ - // Connect to the Local Server of the main process to notify it - // that a new process had been started - QLocalSocket localSocket; - localSocket.connectToServer(QString(TARGET)); - - std::cerr << "Rshare::Rshare waitForConnected to other instance." << std::endl; - if( localSocket.waitForConnected(100) ) - { - std::cerr << "Rshare::Rshare Connection etablished. Waiting for disconnection." << std::endl; - localSocket.waitForDisconnected(1000); - return true; - } - else - { - std::cerr << "Rshare::Rshare failed to connect to other instance." << std::endl; - return false; - } -} - -/** Constructor. Parses the command-line arguments, resets Rshare's +/** Constructor. Parses the command-line arguments, resets RsApplication's * configuration (if requested), and sets up the GUI style and language - * translation. */ -Rshare::Rshare(QStringList args, int &argc, char **argv, const QString &dir) -: QApplication(argc, argv) + * translation. + * the const_cast below is truely horrible, but it allows to hide these unused argc/argv + * when initing RsApplication + */ + +RsApplication::RsApplication(const RsGUIConfigOptions& conf) +: QApplication(const_cast(&conf)->argc,const_cast(&conf)->argv) { - mStartupTime = QDateTime::currentDateTime(); - localServer = NULL; + mStartupTime = QDateTime::currentDateTime(); + localServer = NULL; + options = conf; - //Initialize connection to LocalServer to know if other process runs. - { - QString serverName = QString(TARGET); + // So we start a Local Server to listen for connections from new process + localServer= new QLocalServer(); + QObject::connect(localServer, SIGNAL(newConnection()), this, SLOT(slotConnectionEstablished())); + updateLocalServer(); - // check if another instance is running - bool haveRunningInstance = notifyRunningInstance(); - - bool sendArgsToRunningInstance = haveRunningInstance; - if(args.empty()) - sendArgsToRunningInstance = false; - // if we find non-forwardable args, start a new instance - for(int i = 0; i < args.size(); ++i) - { - const char* const* argit = forwardableArgs; - bool found = false; - while(*argit && i < args.size()) - { - if(args.value(i) == "-"+QString(*argit) || args.value(i) == "--"+QString(*argit)) - { - found = true; - if(argNeedsValue(*argit)) - i++; - } - argit++; - } - if(!found) - sendArgsToRunningInstance = false; - } - - if (sendArgsToRunningInstance) { - // load into shared memory - QBuffer buffer; - buffer.open(QBuffer::ReadWrite); - QDataStream out(&buffer); - out << args; - int size = buffer.size(); - - QSharedMemory newArgs; - newArgs.setKey(serverName + "_newArgs"); - if (newArgs.isAttached()) newArgs.detach(); - - if (!newArgs.create(size)) { - std::cerr << "(EE) Rshare::Rshare Unable to create shared memory segment of size:" - << size << " error:" << newArgs.errorString().toStdString() << "." << std::endl; -#ifdef Q_OS_UNIX - std::cerr << "Look with `ipcs -m` for nattch==0 segment. And remove it with `ipcrm -m 'shmid'`." << std::endl; - //No need for windows, as it removes shared segment directly even when crash. -#endif + // clear out any old arguments (race condition?) + QSharedMemory newArgs; + newArgs.setKey(QString(TARGET) + "_newArgs"); + if(newArgs.attach(QSharedMemory::ReadWrite)) newArgs.detach(); - ::exit(EXIT_FAILURE); - } - newArgs.lock(); - char *to = (char*)newArgs.data(); - const char *from = buffer.data().data(); - memcpy(to, from, qMin(newArgs.size(), size)); - newArgs.unlock(); - - std::cerr << "Rshare::Rshare waitForConnected to other instance." << std::endl; - if(notifyRunningInstance()) - { - newArgs.detach(); - std::cerr << "Rshare::Rshare Arguments was sended." << std::endl - << " To disable it, in Options - General - Misc," << std::endl - << " uncheck \"Use Local Server to get new Arguments\"." << std::endl; - ::exit(EXIT_SUCCESS); // Terminate the program using STDLib's exit function - } - else - std::cerr << "Rshare::Rshare failed to connect to other instance." << std::endl; - newArgs.detach(); - } - - if(!haveRunningInstance) - { - // No main process exists - // Or started without arguments - // So we start a Local Server to listen for connections from new process - localServer= new QLocalServer(); - QObject::connect(localServer, SIGNAL(newConnection()), this, SLOT(slotConnectionEstablished())); - updateLocalServer(); - // clear out any old arguments (race condition?) - QSharedMemory newArgs; - newArgs.setKey(QString(TARGET) + "_newArgs"); - if(newArgs.attach(QSharedMemory::ReadWrite)) - newArgs.detach(); - } - } #if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) - qInstallMessageHandler(qt_msg_handler); + qInstallMessageHandler(qt_msg_handler); #else - qInstallMsgHandler(qt_msg_handler); + qInstallMsgHandler(qt_msg_handler); #endif #ifndef __APPLE__ - /* set default window icon */ - setWindowIcon(FilesDefs::getIconFromQtResourcePath(":/icons/logo_128.png")); + /* set default window icon */ + setWindowIcon(FilesDefs::getIconFromQtResourcePath(":/icons/logo_128.png")); #endif - mBlink = true; - QTimer *timer = new QTimer(this); - timer->setInterval(500); - connect(timer, SIGNAL(timeout()), this, SLOT(blinkTimer())); - timer->start(); + mBlink = true; + QTimer *timer = new QTimer(this); + timer->setInterval(500); + connect(timer, SIGNAL(timeout()), this, SLOT(blinkTimer())); + timer->start(); - timer = new QTimer(this); - timer->setInterval(60000); - connect(timer, SIGNAL(timeout()), this, SIGNAL(minuteTick())); - timer->start(); + timer = new QTimer(this); + timer->setInterval(60000); + connect(timer, SIGNAL(timeout()), this, SIGNAL(minuteTick())); + timer->start(); - /* Read in all our command-line arguments. */ - parseArguments(args); + /* Check if we're supposed to reset our config before proceeding. */ + if (options.optResetParams) + { + RsInfo() << "Resetting Retroshare config parameters, as requested (option -R)"; + Settings->reset(); + } - /* Check if we're supposed to reset our config before proceeding. */ - if (_args.contains(ARG_RESET)) { - Settings->reset(); - } - - /* Handle the -loglevel and -logfile options. */ - if (_args.contains(ARG_LOGFILE)) - _log.open(_args.value(ARG_LOGFILE)); - if (_args.contains(ARG_LOGLEVEL)) { - _log.setLogLevel(Log::stringToLogLevel( - _args.value(ARG_LOGLEVEL))); - if (!_args.contains(ARG_LOGFILE)) - _log.open(stdout); - } - if (!_args.contains(ARG_LOGLEVEL) && - !_args.contains(ARG_LOGFILE)) - _log.setLogLevel(Log::Off); + /* Handle the -loglevel and -logfile options. */ + if (options.logLevel != "Off") + { + if (!options.logFileName.isNull()) + log_output.open(options.logFileName); + else + log_output.open(stdout); - /* config directory */ - useConfigDir = false; - if (dir != "") - { - setConfigDirectory(dir); - } + log_output.setLogLevel(Log::stringToLogLevel(options.logLevel)); + } - /** Initialize support for language translations. */ - //LanguageSupport::initialize(); + /** Initialize support for language translations. */ + //LanguageSupport::initialize(); - resetLanguageAndStyle(); + resetLanguageAndStyle(); - /* Switch off auto shutdown */ - setQuitOnLastWindowClosed ( false ); + /* Switch off auto shutdown */ + setQuitOnLastWindowClosed ( false ); - /* Initialize GxsIdDetails */ - GxsIdDetails::initialize(); + /* Initialize GxsIdDetails */ + GxsIdDetails::initialize(); } /** Destructor */ -Rshare::~Rshare() +RsApplication::~RsApplication() { /* Cleanup GxsIdDetails */ GxsIdDetails::cleanup(); @@ -329,7 +194,7 @@ Rshare::~Rshare() /** * @brief Executed when new instance connect command is sent to LocalServer */ -void Rshare::slotConnectionEstablished() +void RsApplication::slotConnectionEstablished() { QSharedMemory newArgs; newArgs.setKey(QString(TARGET) + "_newArgs"); @@ -341,7 +206,7 @@ void Rshare::slotConnectionEstablished() /* this is not an error. It just means we were notified to check newArgs, but none had been set yet. TODO: implement separate ping/take messages - std::cerr << "(EE) Rshare::slotConnectionEstablished() Unable to attach to shared memory segment." + std::cerr << "(EE) RsApplication::slotConnectionEstablished() Unable to attach to shared memory segment." << newArgs.errorString().toStdString() << std::endl; */ socket->close(); @@ -352,36 +217,41 @@ void Rshare::slotConnectionEstablished() socket->close(); delete socket; - QBuffer buffer; - QDataStream in(&buffer); - QStringList args; + if(newArgs.error()) + { + RsErr() << "Something when wrong in receiving arguments from operating system: " << newArgs.errorString().toStdString() ; + return ; + } + QBuffer buffer; + QDataStream in(&buffer); + QStringList args; - newArgs.lock(); - buffer.setData((char*)newArgs.constData(), newArgs.size()); - buffer.open(QBuffer::ReadOnly); - in >> args; - newArgs.unlock(); - newArgs.detach(); + newArgs.lock(); + buffer.setData((char*)newArgs.constData(), newArgs.size()); + buffer.open(QBuffer::ReadOnly); + in >> args; + newArgs.unlock(); + newArgs.detach(); - emit newArgsReceived(args); - while (!args.empty()) - { - std::cerr << "Rshare::slotConnectionEstablished args:" << QString(args.takeFirst()).toStdString() << std::endl; - } + emit newArgsReceived(args); + while (!args.empty()) + { + std::cerr << "RsApplication::slotConnectionEstablished args:" << QString(args.takeFirst()).toStdString() << std::endl; + } } -QString Rshare::retroshareVersion(bool) { return RS_HUMAN_READABLE_VERSION; } +QString RsApplication::retroshareVersion(bool) { return RS_HUMAN_READABLE_VERSION; } /** Enters the main event loop and waits until exit() is called. The signal * running() will be emitted when the event loop has started. */ int -Rshare::run() +RsApplication::run() { QTimer::singleShot(0, rApp, SLOT(onEventLoopStarted())); return rApp->exec(); } -QDateTime Rshare::startupTime() +QDateTime RsApplication::startupTime() { return mStartupTime; } @@ -390,202 +260,17 @@ QDateTime Rshare::startupTime() * will emit the running() signal to indicate that the application's event * loop is running. */ void -Rshare::onEventLoopStarted() +RsApplication::onEventLoopStarted() { emit running(); } -/** Display usage information regarding command-line arguments. */ -/*void -Rshare::printUsage(QString errmsg) -{ - QTextStream out(stdout);*/ - - /* If there was an error message, print it out. */ - /*if (!errmsg.isEmpty()) { - out << "** " << errmsg << " **" << endl << endl; - }*/ - - /* Now print the application usage */ - //out << "Usage: " << endl; - //out << "\t" << qApp->arguments().at(0) << " [options]" << endl; - - /* And available options */ - //out << endl << "Available Options:" << endl; - //out << "\t-"ARG_RESET"\t\tResets ALL stored Rshare settings." << endl; - //out << "\t-"ARG_DATADIR"\tSets the directory Rshare uses for data files"<< endl; - //out << "\t-"ARG_GUISTYLE"\t\tSets Rshare's interface style." << endl; - //out << "\t-"ARG_GUISTYLESHEET"\t\tSets Rshare's stylesheet." << endl; - //out << "\t\t\t[" << QStyleFactory::keys().join("|") << "]" << endl; - //out << "\t-"ARG_LANGUAGE"\t\tSets Rshare's language." << endl; - //out << "\t\t\t[" << LanguageSupport::languageCodes().join("|") << "]" << endl; -//} - -/** Displays usage information for command-line args. */ -void -Rshare::showUsageMessageBox() -{ - QString usage; - QTextStream out(&usage); - - out << "Available Options:" << endl; - out << ""; - //out << trow(tcol("-"ARG_HELP) + - // tcol(tr("Displays this usage message and exits."))); - out << trow(tcol("-" ARG_RESET) + - tcol(tr("Resets ALL stored RetroShare settings."))); - out << trow(tcol("-" ARG_DATADIR" <dir>") + - tcol(tr("Sets the directory RetroShare uses for data files."))); - out << trow(tcol("-" ARG_LOGFILE" <" + tr("filename") + ">") + - tcol(tr("Sets the name and location of RetroShare's logfile."))); - out << trow(tcol("-" ARG_LOGLEVEL" <" + tr("level") + ">") + - tcol(tr("Sets the verbosity of RetroShare's logging.") + - "
    [" + Log::logLevels().join("|") +"]")); - out << trow(tcol("-" ARG_GUISTYLE" <" + tr("style") +">") + - tcol(tr("Sets RetroShare's interface style.") + - "
    [" + QStyleFactory::keys().join("|") + "]")); - out << trow(tcol("-" ARG_GUISTYLESHEET" <" + tr("stylesheet") + ">") + - tcol(tr("Sets RetroShare's interface stylesheets."))); - out << trow(tcol("-" ARG_LANGUAGE" <" + tr("language") + ">") + - tcol(tr("Sets RetroShare's language.") + - "
    [" + LanguageSupport::languageCodes().join("|") + "]")); - out << trow(tcol("--" ARG_OPMODE_L" <" + tr("opmode") + ">") + - tcol(tr("Sets RetroShare's operating mode.") + - "
    [full|noturtle|gaming|minimal]")); - out << trow(tcol("-" ARG_RSLINK_L" <" + tr("RsLinkURL") + ">") + - tcol(tr("Open RsLink with protocol retroshare://"))); - out << trow(tcol("-" ARG_RSFILE_L" <" + tr("filename") + ">") + - tcol(tr("Open RsFile with or without arg."))); - out << "
    "; - - VMessageBox::information(0, - tr("RetroShare GUI Usage Information"), usage, VMessageBox::Ok); -} - -/** Returns true if the specified argument expects a value. */ -bool -Rshare::argNeedsValue(QString argName) -{ - return ( - argName == ARG_DATADIR || - argName == ARG_LOGFILE || - argName == ARG_LOGLEVEL || - argName == ARG_GUISTYLE || - argName == ARG_GUISTYLESHEET || - argName == ARG_LANGUAGE || - argName == ARG_OPMODE_S || - argName == ARG_OPMODE_L || - argName == ARG_RSLINK_S || - argName == ARG_RSLINK_L || - argName == ARG_RSFILE_S || - argName == ARG_RSFILE_L ); -} - -/** Parses the list of command-line arguments for their argument names and - * values. */ -void -Rshare::parseArguments(QStringList args, bool firstRun) -{ - QString arg, value; - - /* Loop through all command-line args/values and put them in a map */ - for (int i = 0; i < args.size(); ++i) { - /* Get the argument name and set a blank value */ - arg = args.at(i);//.toLower(); Need Upper case for file name. - if (arg.toLower() == "empty") continue; - value = ""; - - /* Check if it starts with a - or -- */ - if (arg.startsWith("-")) { - arg = arg.mid((arg.startsWith("--") ? 2 : 1)); - /* Check if it takes a value and there is one on the command-line */ - if (i < args.size()-1 && argNeedsValue(arg.toLower())) { - value = args.at(++i); - } - } else { - /* Check if links or files without arg */ - if (arg.toLower().startsWith("retroshare://")) { - value = arg; - arg = ARG_RSLINK_L; - } else { - if (QFile(arg).exists()) { - value = arg; - arg = ARG_RSFILE_L; - } - } - } - - /* handle opmode that could be change while running.*/ - QString omValue = QString(value).prepend(";").append(";").toLower(); - QString omValues = QString(";full;noturtle;gaming;minimal;"); - if ((arg == ARG_OPMODE_S || arg == ARG_OPMODE_L ) && - omValues.contains(omValue)) { - _opmode = value; - } - - /* Don't send theses argument to _args map to allow multiple. */ - if (arg == ARG_RSLINK_S || arg == ARG_RSLINK_L) { - _links.append(value); - } else if (arg == ARG_RSFILE_S || arg == ARG_RSFILE_L) { - _files.append(value); - } else if (firstRun) { - /* Place this arg/value in the map only first time*/ - _args.insert(arg, value); - } - } -} - -/** Verifies that all specified arguments were valid. */ -bool -Rshare::validateArguments(QString &errmsg) -{ - /* Check for a writable log file */ - if (_args.contains(ARG_LOGFILE) && !_log.isOpen()) { - errmsg = tr("Unable to open log file '%1': %2") - .arg(_args.value(ARG_LOGFILE)) - .arg(_log.errorString()); - return false; - } - /* Check for a valid log level */ - if (_args.contains(ARG_LOGLEVEL) && - !Log::logLevels().contains(_args.value(ARG_LOGLEVEL))) { - errmsg = tr("Invalid log level specified:")+" " + _args.value(ARG_LOGLEVEL); - return false; - } - /* Check for a valid GUI style */ - if (_args.contains(ARG_GUISTYLE) && - !QStyleFactory::keys().contains(_args.value(ARG_GUISTYLE), - Qt::CaseInsensitive)) { - errmsg = tr("Invalid GUI style specified:")+" " + _args.value(ARG_GUISTYLE); - return false; - } - /* Check for a language that Retroshare recognizes. */ - if (_args.contains(ARG_LANGUAGE) && - !LanguageSupport::isValidLanguageCode(_args.value(ARG_LANGUAGE))) { - errmsg = tr("Invalid language code specified:")+" " + _args.value(ARG_LANGUAGE); - return false; - } - /* Check for an opmode that Retroshare recognizes. */ - if (_args.contains(ARG_OPMODE_S) && - !QString(";full;noturtle;gaming;minimal;").contains(QString(_args.value(ARG_OPMODE_S)).prepend(";").append(";").toLower())) { - errmsg = tr("Invalid operating mode specified:")+" " + _args.value(ARG_OPMODE_S); - return false; - } - /* Check for an opmode that Retroshare recognizes. */ - if (_args.contains(ARG_OPMODE_L) && - !QString(";full;noturtle;gaming;minimal;").contains(QString(_args.value(ARG_OPMODE_L)).prepend(";").append(";").toLower())) { - errmsg = tr("Invalid operating mode specified:")+" " + _args.value(ARG_OPMODE_L); - return false; - } - return true; -} - /** Sets the translation RetroShare will use. If one was specified on the * command-line, we will use that. Otherwise, we'll check to see if one was * saved previously. If not, we'll default to one appropriate for the system * locale. */ bool -Rshare::setLanguage(QString languageCode) +RsApplication::setLanguage(QString languageCode) { /* If the language code is empty, use the previously-saved setting */ if (languageCode.isEmpty()) { @@ -593,7 +278,7 @@ Rshare::setLanguage(QString languageCode) } /* Translate into the desired language */ if (LanguageSupport::translate(languageCode)) { - _language = languageCode; + options.language = languageCode; return true; } return false; @@ -604,7 +289,7 @@ Rshare::setLanguage(QString languageCode) * saved previously. If not, we'll default to the system * locale. */ bool -Rshare::setLocale(QString languageCode) +RsApplication::setLocale(QString languageCode) { bool retVal = false; /* If the language code is empty, use the previously-saved setting */ @@ -620,20 +305,20 @@ Rshare::setLocale(QString languageCode) } /** customize date format for feeds etc. */ -void Rshare::customizeDateFormat() +void RsApplication::customizeDateFormat() { QLocale locale = QLocale(); // set to default locale /* get long date format without weekday */ - _dateformat = locale.dateFormat(QLocale::LongFormat); - _dateformat.replace(QRegExp("^dddd,*[^ ]* *('[^']+' )*"), ""); - _dateformat.replace(QRegExp(",* *dddd"), ""); - _dateformat = _dateformat.trimmed(); + options.dateformat = locale.dateFormat(QLocale::LongFormat); + options.dateformat.replace(QRegExp("^dddd,*[^ ]* *('[^']+' )*"), ""); + options.dateformat.replace(QRegExp(",* *dddd"), ""); + options.dateformat = options.dateformat.trimmed(); } /** Get custom date format (defaultlongformat) */ -QString Rshare::customDateFormat() +QString RsApplication::customDateFormat() { - return _dateformat; + return options.dateformat; } /** Sets the GUI style RetroShare will use. If one was specified on the @@ -641,55 +326,56 @@ QString Rshare::customDateFormat() * saved previously. If not, we'll default to one appropriate for the * operating system. */ bool -Rshare::setStyle(QString styleKey) +RsApplication::setStyle(QString styleKey) { /* If no style was specified, use the previously-saved setting */ if (styleKey.isEmpty()) { styleKey = Settings->getInterfaceStyle(); } /* Apply the specified GUI style */ - if (QApplication::setStyle(styleKey)) { - _style = styleKey; + if (QApplication::setStyle(styleKey)) + { + options.guiStyle = styleKey; return true; } return false; } bool -Rshare::setSheet(QString sheet) +RsApplication::setSheet(QString sheet) { /* If no stylesheet was specified, use the previously-saved setting */ if (sheet.isEmpty()) { sheet = Settings->getSheetName(); } /* Apply the specified GUI stylesheet */ - _stylesheet = sheet; + options.guiStyleSheetFile = sheet; /* load the StyleSheet*/ - loadStyleSheet(_stylesheet); + loadStyleSheet(options.guiStyleSheetFile); return true; } -void Rshare::resetLanguageAndStyle() +void RsApplication::resetLanguageAndStyle() { /** Translate the GUI to the appropriate language. */ - setLanguage(_args.value(ARG_LANGUAGE)); + setLanguage(options.language); /** Set the locale appropriately. */ - setLocale(_args.value(ARG_LANGUAGE)); + setLocale(options.language); /** Set the GUI style appropriately. */ - setStyle(_args.value(ARG_GUISTYLE)); + setStyle(options.guiStyle); /** Set the GUI stylesheet appropriately. */ - setSheet(_args.value(ARG_GUISTYLESHEET)); + setSheet(options.guiStyleSheetFile); } // RetroShare: // Default: -// :/qss/stylesheet/qss.default -// :/qss/stylesheet/qss. +// :/qss/stylesheet/default.qss +// :/qss/stylesheet/.qss // Internal: // :/qss/stylesheet/.qss // External: @@ -699,8 +385,8 @@ void Rshare::resetLanguageAndStyle() // // Plugin: // Default: -// :/qss/stylesheet//_qss.default -// :/qss/stylesheet//_qss. +// :/qss/stylesheet//_default.qss +// :/qss/stylesheet//_.qss // Internal: // :/qss/stylesheet//_.qss // External: @@ -708,7 +394,7 @@ void Rshare::resetLanguageAndStyle() // Language depended stylesheet // _.lqss -void Rshare::loadStyleSheet(const QString &sheetName) +void RsApplication::loadStyleSheet(const QString &sheetName) { QString locale = QLocale().name(); QString styleSheet; @@ -719,8 +405,8 @@ void Rshare::loadStyleSheet(const QString &sheetName) /* Get stylesheet from plugins */ if (rsPlugins) { int count = rsPlugins->nbPlugins(); - for (int i = 0; i < count; ++i) { - RsPlugin* plugin = rsPlugins->plugin(i); + for (int iCurs = 0; iCurs < count; ++iCurs) { + RsPlugin* plugin = rsPlugins->plugin(iCurs); if (plugin) { QString pluginStyleSheetName = QString::fromUtf8(plugin->qt_stylesheet().c_str()); if (!pluginStyleSheetName.isEmpty()) { @@ -732,22 +418,22 @@ void Rshare::loadStyleSheet(const QString &sheetName) foreach (QString name, names) { /* load the default stylesheet */ - QFile file(QString(":/qss/stylesheet/%1qss.default").arg(name)); + QFile file(QString(":/qss/stylesheet/%1default.qss").arg(name)); if (file.open(QFile::ReadOnly)) { styleSheet += QLatin1String(file.readAll()) + "\n"; file.close(); } /* load locale depended default stylesheet */ - file.setFileName(QString(":/qss/stylesheet/%1qss.%2").arg(name, locale)); + file.setFileName(QString(":/qss/stylesheet/%1%2.qss").arg(name, locale)); if (file.open(QFile::ReadOnly)) { styleSheet += QLatin1String(file.readAll()) + "\n"; file.close(); } - if (!sheetName.isEmpty()) { + if (!sheetName.isEmpty() && (sheetName != ":default")) { /* load stylesheet */ - if (sheetName.left(1) == ":") { + if (sheetName.at(0) == ':') { /* internal stylesheet */ file.setFileName(QString(":/qss/stylesheet/%1%2.qss").arg(name, sheetName.mid(1))); } else { @@ -779,14 +465,14 @@ void Rshare::loadStyleSheet(const QString &sheetName) } /** get list of available stylesheets **/ -void Rshare::getAvailableStyleSheets(QMap &styleSheets) +void RsApplication::getAvailableStyleSheets(QMap &styleSheets) { QFileInfoList fileInfoList = QDir(":/qss/stylesheet/").entryInfoList(QStringList("*.qss")); QFileInfo fileInfo; foreach (fileInfo, fileInfoList) { if (fileInfo.isFile()) { QString name = fileInfo.baseName(); - styleSheets.insert(QString("%1 (%2)").arg(name, tr("built-in")), ":" + name); + styleSheets.insert(QString(" %1 (%2)").arg(name, tr("built-in")), ":" + name);//Add space to name to get them up because QMap sort by Key. } } fileInfoList = QDir(QString::fromUtf8(RsAccounts::ConfigDirectory().c_str()) + "/qss/").entryInfoList(QStringList("*.qss")); @@ -807,7 +493,7 @@ void Rshare::getAvailableStyleSheets(QMap &styleSheets) } } -void Rshare::refreshStyleSheet(QWidget *widget, bool processChildren) +void RsApplication::refreshStyleSheet(QWidget *widget, bool processChildren) { if (widget != NULL) { // force widget to recalculate valid style @@ -833,40 +519,35 @@ void Rshare::refreshStyleSheet(QWidget *widget, bool processChildren) } /** Initialize plugins. */ -void Rshare::initPlugins() +void RsApplication::initPlugins() { - loadStyleSheet(_stylesheet); - LanguageSupport::translatePlugins(_language); + loadStyleSheet(options.guiStyleSheetFile); + LanguageSupport::translatePlugins(options.language); } /** Returns the directory RetroShare uses for its data files. */ -QString -Rshare::dataDirectory() +QString RsApplication::dataDirectory() { - if (useConfigDir) - { - return configDir; - } - else if (_args.contains(ARG_DATADIR)) { - return _args.value(ARG_DATADIR); - } - return defaultDataDirectory(); + if(!options.optBaseDir.empty()) + return QString::fromUtf8(options.optBaseDir.c_str()); + else + return defaultDataDirectory(); } /** Returns the default location of RetroShare's data directory. */ QString -Rshare::defaultDataDirectory() +RsApplication::defaultDataDirectory() { #if defined(Q_OS_WIN) return (win32_app_data_folder() + "\\RetroShare"); #else - return (QDir::homePath() + "/.RetroShare"); + return (QDir::homePath() + "/.retroshare"); #endif } -/** Creates Rshare's data directory, if it doesn't already exist. */ +/** Creates RsApplication's data directory, if it doesn't already exist. */ bool -Rshare::createDataDirectory(QString *errmsg) +RsApplication::createDataDirectory(QString *errmsg) { QDir datadir(dataDirectory()); if (!datadir.exists()) { @@ -879,33 +560,29 @@ Rshare::createDataDirectory(QString *errmsg) return true; } -/** Set Rshare's data directory - externally */ -bool Rshare::setConfigDirectory(QString dir) +/** Set RsApplication's data directory - externally */ +bool RsApplication::setConfigDirectory(const QString& dir) { - useConfigDir = true; - configDir = dir; + options.optBaseDir = std::string(dir.toUtf8()); return true; } /** Writes msg with severity level to RetroShare's log. */ -Log::LogMessage -Rshare::log(Log::LogLevel level, QString msg) +Log::LogMessage RsApplication::log(Log::LogLevel level, QString msg) { - return _log.log(level, msg); + return log_output.log(level, msg); } /** Creates and binds a shortcut such that when key is pressed in * sender's context, receiver's slot will be called. */ -void -Rshare::createShortcut(const QKeySequence &key, QWidget *sender, - QWidget *receiver, const char *slot) +void RsApplication::createShortcut(const QKeySequence &key, QWidget *sender, QWidget *receiver, const char *slot) { QShortcut *s = new QShortcut(key, sender); connect(s, SIGNAL(activated()), receiver, slot); } #ifdef __APPLE__ -bool Rshare::event(QEvent *event) +bool RsApplication::event(QEvent *event) { switch (event->type()) { case QEvent::FileOpen:{ @@ -927,7 +604,7 @@ bool Rshare::event(QEvent *event) } #endif -void Rshare::blinkTimer() +void RsApplication::blinkTimer() { mBlink = !mBlink; emit blink(mBlink); @@ -938,7 +615,7 @@ void Rshare::blinkTimer() } } -bool Rshare::loadCertificate(const RsPeerId &accountId, bool autoLogin) +bool RsApplication::loadCertificate(const RsPeerId &accountId, bool autoLogin) { if (!RsAccounts::SelectAccount(accountId)) { @@ -946,35 +623,47 @@ bool Rshare::loadCertificate(const RsPeerId &accountId, bool autoLogin) } std::string lockFile; - int retVal = RsInit::LockAndLoadCertificates(autoLogin, lockFile); - switch (retVal) { - case 0: break; - case 1: QMessageBox::warning( 0, - QObject::tr("Multiple instances"), - QObject::tr("Another RetroShare using the same profile is " - "already running on your system. Please close " - "that instance first\n Lock file:\n") + - QString::fromUtf8(lockFile.c_str())); - return false; - case 2: QMessageBox::critical( 0, - QObject::tr("Multiple instances"), - QObject::tr("An unexpected error occurred when Retroshare " - "tried to acquire the single instance lock\n Lock file:\n") + - QString::fromUtf8(lockFile.c_str())); - return false; - case 3: -// case 3: QMessageBox::critical( 0, -// QObject::tr("Login Failure"), -// QObject::tr("Maybe password is wrong") ); - return false; - default: std::cerr << "Rshare::loadCertificate() unexpected switch value " << retVal << std::endl; - return false; - } + RsInit::LoadCertificateStatus retVal = RsInit::LockAndLoadCertificates(autoLogin, lockFile); + + switch (retVal) + { + case RsInit::OK: + break; + case RsInit::ERR_ALREADY_RUNNING: QMessageBox::warning( nullptr, + QObject::tr("Multiple instances"), + QObject::tr("Another RetroShare using the same profile is " + "already running on your system. Please close " + "that instance first\n Lock file:\n") + + QString::fromUtf8(lockFile.c_str())); + return false; + case RsInit::ERR_CANT_ACQUIRE_LOCK: QMessageBox::critical( nullptr, + QObject::tr("Multiple instances"), + QObject::tr("An unexpected error occurred when Retroshare " + "tried to acquire the single instance lock\n Lock file:\n") + + QString::fromUtf8(lockFile.c_str())); + return false; + case RsInit::ERR_CERT_CRYPTO_IS_TOO_WEAK: QMessageBox::critical( nullptr, + QObject::tr("Old certificate"), + QObject::tr("This node uses old certificate settings that are considered too " + "weak by your current OpenSSL library version. You need to create a new node " + "possibly using the same profile.")); + return false; + case RsInit::ERR_CANNOT_CONFIGURE_TOR: QMessageBox::critical( nullptr, + QObject::tr("Tor error"), + QObject::tr("Cannot run/configure Tor. Make sure it is installed on your system.")); + return false; + // case 3: QMessageBox::critical( 0, + // QObject::tr("Login Failure"), + // QObject::tr("Maybe password is wrong") ); + return false; + default: std::cerr << "RsApplication::loadCertificate() unexpected switch value " << retVal << std::endl; + return false; + } return true; } -bool Rshare::updateLocalServer() +bool RsApplication::updateLocalServer() { if (localServer) { QString serverName = QString(TARGET); diff --git a/retroshare-gui/src/rshare.h b/retroshare-gui/src/rshare.h index e1b68f6b6..be6af336c 100644 --- a/retroshare-gui/src/rshare.h +++ b/retroshare-gui/src/rshare.h @@ -36,9 +36,10 @@ #include "util/log.h" #include "retroshare/rstypes.h" +#include "retroshare/rsinit.h" /** Pointer to this RetroShare application instance. */ -#define rApp ((Rshare *)qApp) +#define rApp (static_cast(qApp)) #define rDebug(fmt) (rApp->log(Log::Debug, (fmt))) #define rInfo(fmt) (rApp->log(Log::Info, (fmt))) @@ -46,33 +47,40 @@ #define rWarn(fmt) (rApp->log(Log::Warn, (fmt))) #define rError(fmt) (rApp->log(Log::Error, (fmt))) +struct RsGUIConfigOptions: public RsConfigOptions +{ + RsGUIConfigOptions() + : optResetParams(false), logLevel("Off"), argc(0) + {} -class Rshare : public QApplication + bool optResetParams; // reset all GUI parameters + + QString dateformat; // The format for dates in feed items etc. + QString language; // The current language. + + QString logFileName; // output filename for log + QString logLevel; // severity threshold for log output + + QString guiStyle; // CSS Style for the GUI + QString guiStyleSheetFile; // CSS Style for the GUI + + int argc ; // stores argc parameter. Only used by the creator of QApplication + char *argv[1] ; // stores argv parameter. Only used by the creator of QApplication +}; + +class RsApplication : public QApplication { Q_OBJECT public: /** Constructor. */ - Rshare(QStringList args, int &argc, char **argv, const QString &dir); + RsApplication(const RsGUIConfigOptions& conf); /** Destructor. */ - ~Rshare(); + ~RsApplication(); /** Return the version info */ static QString retroshareVersion(bool=true); - /** Return the map of command-line arguments and values. */ - static QMap arguments() { return _args; } - /** Parse the list of command-line arguments. */ - static void parseArguments(QStringList args, bool firstRun = true); - /** Validates that all arguments were well-formed. */ - bool validateArguments(QString &errmsg); - /** Prints usage information to the given text stream. */ - //void printUsage(QString errmsg = QString()); - /** Displays usage information for command-line args. */ - static void showUsageMessageBox(); - /** Returns true if the user wants to see usage information. */ - static bool showUsage(); - /** Sets the current language. */ static bool setLanguage(QString languageCode = QString()); /** Sets the current locale. */ @@ -105,17 +113,22 @@ public: static void initPlugins(); /** Returns the current GUI style. */ - static QString style() { return _style; } + static QString style() { return options.guiStyle; } /** Returns the current GUI stylesheet. */ - static QString stylesheet() { return _stylesheet; } + static QString stylesheet() { return options.guiStyleSheetFile; } /** Returns the current language. */ - static QString language() { return _language; } - /** Returns the operating mode. */ - static QString opmode() { return _opmode; } + static QString language() { return options.language; } + + /** Sets/Returns the operating mode. */ + static void setOpMode(const QString& op ) { options.opModeStr = op.toStdString(); } + static QString opmode() { return QString::fromStdString(options.opModeStr); } + +#ifdef __APPLE__ /** Returns links passed by arguments. */ static QStringList* links() { return &_links; } /** Returns files passed by arguments. */ static QStringList* files() {return &_files; } +#endif /** Returns Rshare's application startup time. */ static QDateTime startupTime(); @@ -130,7 +143,7 @@ public: static Log::LogMessage log(Log::LogLevel level, QString msg); /** Creates Rshare's data directory, if it doesn't already exist. */ - static bool setConfigDirectory(QString dir); + static bool setConfigDirectory(const QString &dir); /** Enters the main event loop and waits until exit() is called. The signal * running() will be emitted when the event loop has started. */ @@ -176,24 +189,20 @@ private: /** customize the date format (defaultlongformat) */ static void customizeDateFormat(); +#ifdef TO_REMOVE /** Returns true if the specified arguments wants a value. */ - static bool argNeedsValue(QString argName); + static bool argNeedsValue(const QString &argName); +#endif - static QMap _args; /**< List of command-line arguments. */ - static Log _log; /**< Logs debugging messages to file or stdout. */ - static QString _style; /**< The current GUI style. */ - static QString _stylesheet; /**< The current GUI stylesheet. */ - static QString _language; /**< The current language. */ - static QString _dateformat; /**< The format for dates in feed items etc. */ - static QString _opmode; /**< The operating mode passed by args. */ +#ifdef __APPLE__ static QStringList _links; /**< List of links passed by arguments. */ static QStringList _files; /**< List of files passed by arguments. */ +#endif static QDateTime mStartupTime; // startup time - - static bool useConfigDir; - static QString configDir; bool mBlink; static QLocalServer* localServer; + static RsGUIConfigOptions options; + static Log log_output; }; #endif diff --git a/retroshare-gui/src/util/AspectRatioPixmapLabel.cpp b/retroshare-gui/src/util/AspectRatioPixmapLabel.cpp index 08ecf18c6..0ff9d851b 100644 --- a/retroshare-gui/src/util/AspectRatioPixmapLabel.cpp +++ b/retroshare-gui/src/util/AspectRatioPixmapLabel.cpp @@ -18,8 +18,14 @@ * * *******************************************************************************/ +#include +#include +#include + #include "AspectRatioPixmapLabel.h" #include +#include "util/imageutil.h" +#include "gui/common/FilesDefs.h" AspectRatioPixmapLabel::AspectRatioPixmapLabel(QWidget *parent) : QLabel(parent) @@ -31,7 +37,7 @@ AspectRatioPixmapLabel::AspectRatioPixmapLabel(QWidget *parent) : void AspectRatioPixmapLabel::setPixmap ( const QPixmap & p) { pix = p; - QLabel::setPixmap(pix); + QLabel::setPixmap(scaledPixmap()); //std::cout << "Information size: " << pix.width() << 'x' << pix.height() << std::endl; } @@ -57,3 +63,53 @@ void AspectRatioPixmapLabel::resizeEvent(QResizeEvent * e) QLabel::resizeEvent(e); //std::cout << "Information resized: " << e->oldSize().width() << 'x' << e->oldSize().height() << " to " << e->size().width() << 'x' << e->size().height() << std::endl; } + +void AspectRatioPixmapLabel::addContextMenuAction(QAction *action) +{ + mContextMenuActions.push_back(action); +} + +void AspectRatioPixmapLabel::contextMenuEvent(QContextMenuEvent *event) +{ + emit calculateContextMenuActions(); + + QMenu *contextMenu = new QMenu(); + + QAction *actionSaveImage = contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/images/document_save.png"), tr("Save image"), this, SLOT(saveImage())); + QAction *actionCopyImage = contextMenu->addAction(tr("Copy image"), this, SLOT(copyImage())); + + if (pix.isNull()) { + actionSaveImage->setEnabled(false); + actionCopyImage->setEnabled(false); + } else { + actionSaveImage->setEnabled(true); + actionCopyImage->setEnabled(true); + } + + QList::iterator it; + for (it = mContextMenuActions.begin(); it != mContextMenuActions.end(); ++it) { + contextMenu->addAction(*it); + } + + contextMenu->exec(event->globalPos()); + + delete(contextMenu); +} + +void AspectRatioPixmapLabel::copyImage() +{ + if (pix.isNull()) { + return; + } + + QApplication::clipboard()->setPixmap(pix, QClipboard::Clipboard); +} + +void AspectRatioPixmapLabel::saveImage() +{ + if (pix.isNull()) { + return; + } + + ImageUtil::saveImage(window(), pix.toImage()); +} diff --git a/retroshare-gui/src/util/AspectRatioPixmapLabel.h b/retroshare-gui/src/util/AspectRatioPixmapLabel.h index ad7c40e4c..be6e79077 100644 --- a/retroshare-gui/src/util/AspectRatioPixmapLabel.h +++ b/retroshare-gui/src/util/AspectRatioPixmapLabel.h @@ -28,17 +28,33 @@ class AspectRatioPixmapLabel : public QLabel { Q_OBJECT + public: explicit AspectRatioPixmapLabel(QWidget *parent = nullptr); virtual int heightForWidth( int width ) const override; virtual QSize sizeHint() const override; QPixmap scaledPixmap() const; + + // Add QAction to context menu (action won't be deleted) + void addContextMenuAction(QAction *action); + +Q_SIGNALS: + void calculateContextMenuActions(); + public slots: void setPixmap ( const QPixmap & ); + protected: void resizeEvent(QResizeEvent *event) override; + virtual void contextMenuEvent(QContextMenuEvent *event); + +private slots: + void copyImage(); + void saveImage(); + private: QPixmap pix; + QList mContextMenuActions; }; #endif // ASPECTRATIOPIXMAPLABEL_H diff --git a/retroshare-gui/src/util/ClickableLabel.cpp b/retroshare-gui/src/util/ClickableLabel.cpp index e12e01c8d..ee16abdc8 100644 --- a/retroshare-gui/src/util/ClickableLabel.cpp +++ b/retroshare-gui/src/util/ClickableLabel.cpp @@ -22,7 +22,7 @@ /** Constructor */ ClickableLabel::ClickableLabel(QWidget* parent, Qt::WindowFlags f) - : QLabel(parent) { + : QLabel(parent, f) { } @@ -30,6 +30,24 @@ ClickableLabel::~ClickableLabel() { } -void ClickableLabel::mousePressEvent(QMouseEvent* event) { +void ClickableLabel::mousePressEvent(QMouseEvent* /*event*/) { emit clicked(); } + +#if QT_VERSION >= QT_VERSION_CHECK (6, 0, 0) +void ClickableLabel::enterEvent(QEnterEvent* /*event*/) +#else +void ClickableLabel::enterEvent(QEvent* /*event*/) +#endif +{ + if (mUseStyleSheet) { + setStyleSheet("QLabel { border: 2px solid #039bd5; }"); + } +} + +void ClickableLabel::leaveEvent(QEvent* /*event*/) +{ + if (mUseStyleSheet) { + setStyleSheet(""); + } +} diff --git a/retroshare-gui/src/util/ClickableLabel.h b/retroshare-gui/src/util/ClickableLabel.h index 54b3499d8..610a1eabd 100644 --- a/retroshare-gui/src/util/ClickableLabel.h +++ b/retroshare-gui/src/util/ClickableLabel.h @@ -39,8 +39,12 @@ signals: protected: void mousePressEvent(QMouseEvent* event) override; - void enterEvent(QEvent * /* ev */ ) override { if(mUseStyleSheet) setStyleSheet("QLabel { border: 2px solid #039bd5; }");} - void leaveEvent(QEvent * /* ev */ ) override { if(mUseStyleSheet) setStyleSheet("");} +#if QT_VERSION >= QT_VERSION_CHECK (6, 0, 0) + void enterEvent(QEnterEvent* event) override; +#else + void enterEvent(QEvent* event) override; +#endif + void leaveEvent(QEvent* event) override; bool mUseStyleSheet; }; diff --git a/retroshare-gui/src/util/DateTime.cpp b/retroshare-gui/src/util/DateTime.cpp index b93a4dfe1..658772c5a 100644 --- a/retroshare-gui/src/util/DateTime.cpp +++ b/retroshare-gui/src/util/DateTime.cpp @@ -30,7 +30,7 @@ QString DateTime::formatLongDate(time_t dateValue) QString DateTime::formatLongDate(const QDate &dateValue) { - QString customDateFormat = Rshare::customDateFormat(); + QString customDateFormat = RsApplication::customDateFormat(); if (customDateFormat.isEmpty()) { return dateValue.toString(Qt::ISODate); diff --git a/retroshare-gui/src/util/FontSizeHandler.cpp b/retroshare-gui/src/util/FontSizeHandler.cpp new file mode 100644 index 000000000..c184da0de --- /dev/null +++ b/retroshare-gui/src/util/FontSizeHandler.cpp @@ -0,0 +1,210 @@ +/******************************************************************************* + * util/FontSizeHandler.cpp * + * * + * Copyright (C) 2025, Retroshare Team * + * * + * 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 . * + * * + *******************************************************************************/ + +#include +#include +#include + +#include "rshare.h" +#include "FontSizeHandler.h" +#include "gui/settings/rsharesettings.h" +#include "gui/notifyqt.h" + +// Data for QAbstractItemView +struct FontSizeHandlerWidgetData +{ + std::function callback; +}; + +// Data for QWidget +struct FontSizeHandlerViewData +{ + float iconHeightFactor; + std::function callback; +}; + +class FontSizeHandlerObject : public QObject +{ +public: + FontSizeHandlerObject(FontSizeHandlerBase *fontSizeHandler): QObject() + { + mFontSizeHandlerBase = fontSizeHandler; + } + + bool eventFilter(QObject* object, QEvent* event) + { + if (event->type() == QEvent::StyleChange) { + QMap::iterator itView = mView.find((QAbstractItemView*) object); + if (itView != mView.end()) { + mFontSizeHandlerBase->updateFontSize(itView.key(), itView.value().iconHeightFactor, itView.value().callback); + } + + QMap::iterator itWidget = mWidget.find((QWidget*) object); + if (itWidget != mWidget.end()) { + mFontSizeHandlerBase->updateFontSize(itWidget.key(), itWidget.value().callback); + } + } + + return false; + } + + void registerFontSize(QWidget *widget, std::function callback) + { + FontSizeHandlerWidgetData data; + data.callback = callback; + mWidget.insert(widget, data); + + QObject::connect(NotifyQt::getInstance(), &NotifyQt::settingsChanged, widget, [this, widget, callback]() { + mFontSizeHandlerBase->updateFontSize(widget, callback); + }); + + widget->installEventFilter(this); + QObject::connect(widget, &QObject::destroyed, this, [this, widget](QObject *object) { + if (widget == object) { + mWidget.remove(widget); + widget->removeEventFilter(this); + } + }); + + mFontSizeHandlerBase->updateFontSize(widget, callback, true); + } + + void registerFontSize(QAbstractItemView *view, float iconHeightFactor, std::function callback) + { + FontSizeHandlerViewData data; + data.iconHeightFactor = iconHeightFactor; + data.callback = callback; + mView.insert(view, data); + + QObject::connect(NotifyQt::getInstance(), &NotifyQt::settingsChanged, view, [this, view, iconHeightFactor, callback]() { + mFontSizeHandlerBase->updateFontSize(view, iconHeightFactor, callback); + }); + + view->installEventFilter(this); + QObject::connect(view, &QObject::destroyed, this, [this, view](QObject *object) { + if (view == object) { + mView.remove(view); + view->removeEventFilter(this); + } + }); + + mFontSizeHandlerBase->updateFontSize(view, iconHeightFactor, callback, true); + } + +private: + FontSizeHandlerBase *mFontSizeHandlerBase; + QMap mView; + QMap mWidget; +}; + +FontSizeHandlerBase::FontSizeHandlerBase(Type type) +{ + mType = type; + mObject = nullptr; +} + +FontSizeHandlerBase::~FontSizeHandlerBase() +{ + if (mObject) { + mObject->deleteLater(); + mObject = nullptr; + } +} + +int FontSizeHandlerBase::getFontSize() +{ + switch (mType) { + case FONT_SIZE: + return Settings->getFontSize(); + + case MESSAGE_FONT_SIZE: + return Settings->getMessageFontSize(); + } + + return 0; +} + +void FontSizeHandlerBase::registerFontSize(QWidget *widget, std::function callback) +{ + if (!widget) { + return; + } + + if (!mObject) { + mObject = new FontSizeHandlerObject(this); + } + + mObject->registerFontSize(widget, callback); +} + +void FontSizeHandlerBase::registerFontSize(QAbstractItemView *view, float iconHeightFactor, std::function callback) +{ + if (!view) { + return; + } + + if (!mObject) { + mObject = new FontSizeHandlerObject(this); + } + + mObject->registerFontSize(view, iconHeightFactor, callback); +} + +void FontSizeHandlerBase::updateFontSize(QWidget *widget, std::function callback, bool force) +{ + if (!widget) { + return; + } + + int fontSize = getFontSize(); + QFont font = widget->font(); + if (force || font.pointSize() != fontSize) { + font.setPointSize(fontSize); + widget->setFont(font); + + if (callback) { + callback(widget, fontSize); + } + } +} + +void FontSizeHandlerBase::updateFontSize(QAbstractItemView *view, float iconHeightFactor, std::function callback, bool force) +{ + if (!view) { + return; + } + + int fontSize = getFontSize(); + QFont font = view->font(); + if (force || font.pointSize() != fontSize) { + font.setPointSize(fontSize); + view->setFont(font); + + if (iconHeightFactor) { + QFontMetricsF fontMetrics(font); + int iconHeight = fontMetrics.height() * iconHeightFactor; + view->setIconSize(QSize(iconHeight, iconHeight)); + } + + if (callback) { + callback(view, fontSize); + } + } +} diff --git a/retroshare-gui/src/util/FontSizeHandler.h b/retroshare-gui/src/util/FontSizeHandler.h new file mode 100644 index 000000000..bf9c8058b --- /dev/null +++ b/retroshare-gui/src/util/FontSizeHandler.h @@ -0,0 +1,73 @@ +/******************************************************************************* + * util/FontSizeHandler.h * + * * + * Copyright (C) 2025, Retroshare Team * + * * + * 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 . * + * * + *******************************************************************************/ + +#ifndef _FONTSIZEHANDLER_H +#define _FONTSIZEHANDLER_H + +#include + +class QWidget; +class QAbstractItemView; +class FontSizeHandlerObject; + +// Class to handle font size and message font size setting +class FontSizeHandlerBase +{ + friend class FontSizeHandlerObject; + +public: + virtual ~FontSizeHandlerBase(); + + int getFontSize(); + + void registerFontSize(QWidget *widget, std::function callback = nullptr); + void registerFontSize(QAbstractItemView *view, float iconHeightFactor = 0.0f, std::function callback = nullptr); + + void updateFontSize(QWidget *widget, std::function callback = nullptr, bool force = false); + void updateFontSize(QAbstractItemView *view, float iconHeightFactor, std::function callback, bool force = false); + +protected: + enum Type { + FONT_SIZE, + MESSAGE_FONT_SIZE + }; + + FontSizeHandlerBase(Type type); + +private: + Type mType; + FontSizeHandlerObject *mObject; +}; + +// Class to handle font size setting +class FontSizeHandler : public FontSizeHandlerBase +{ +public: + FontSizeHandler() : FontSizeHandlerBase(FONT_SIZE) {} +}; + +// Class to handle message font size setting +class MessageFontSizeHandler : public FontSizeHandlerBase +{ +public: + MessageFontSizeHandler() : FontSizeHandlerBase(MESSAGE_FONT_SIZE) {} +}; + +#endif // FONTSIZEHANDLER diff --git a/retroshare-gui/src/util/HandleRichText.cpp b/retroshare-gui/src/util/HandleRichText.cpp index 409d37aa6..7ad0c15e8 100644 --- a/retroshare-gui/src/util/HandleRichText.cpp +++ b/retroshare-gui/src/util/HandleRichText.cpp @@ -31,6 +31,7 @@ #include "gui/RetroShareLink.h" #include "util/ObjectPainter.h" #include "util/imageutil.h" +#include "util/QtVersion.h" #include "util/rsdebug.h" #include "util/rstime.h" @@ -334,6 +335,29 @@ void RsHtml::replaceAnchorWithImg(QDomDocument &doc, QDomElement &element, QText element.appendChild(img); } +void RsHtml::filterEmbeddedImages(QDomDocument &doc, QDomElement ¤tElement) +{ + QDomNodeList children = currentElement.childNodes(); + for(uint index = 0; index < (uint)children.length(); index++) { + QDomNode node = children.item(index); + if(node.isElement()) { + QDomElement element = node.toElement(); + if(element.tagName().toLower() == "img") { + if(element.hasAttribute("src")) { + QString src = element.attribute("src"); + // Do not allow things in the image source, except these: + // :/ internal resource needed for emotes + // data:image base64 embedded image needed for stickers + if(!src.startsWith(":/") && !src.startsWith("data:image", Qt::CaseInsensitive)) { + element.setAttribute("src", ":/images/imageblocked_24.png"); + } + } + } + filterEmbeddedImages(doc, element); + } + } +} + int RsHtml::indexInWithValidation(QRegExp &rx, const QString &text, EmbedInHtml &embedInfos, int pos) { int index = rx.indexIn(text, pos); @@ -636,6 +660,7 @@ QString RsHtml::formatText(QTextDocument *textDocument, const QString &text, ulo } QDomElement body = doc.documentElement(); + filterEmbeddedImages(doc, body); // This should be first, becuse it should not overwrite embedded custom smileys if (flag & RSHTML_FORMATTEXT_EMBED_SMILEYS) { embedHtml(textDocument, doc, body, defEmbedImg, flag); } @@ -1192,7 +1217,7 @@ bool RsHtml::makeEmbeddedImage(const QString &fileName, QString &embeddedImage, fprintf (stderr, "RsHtml::makeEmbeddedImage() - image \"%s\" can't be load\n", fileName.toLatin1().constData()); return false; } - return RsHtml::makeEmbeddedImage(image, embeddedImage, maxPixels, maxBytes); + return RsHtml::makeEmbeddedImage(image, embeddedImage, maxPixels, maxBytes); } /** Converts image to embedded image HTML fragment **/ @@ -1200,7 +1225,7 @@ bool RsHtml::makeEmbeddedImage(const QImage &originalImage, QString &embeddedIma { rstime::RsScopeTimer s("Embed image"); QImage opt; - return ImageUtil::optimizeSizeHtml(embeddedImage, originalImage, opt, maxPixels, maxBytes); + return ImageUtil::optimizeSizeHtml(embeddedImage, originalImage, opt, maxPixels, maxBytes); } QString RsHtml::plainText(const QString &text) @@ -1228,7 +1253,7 @@ QString RsHtml::makeQuotedText(RSTextBrowser *browser) { text = browser->toPlainText(); } - QStringList sl = text.split(QRegExp("[\r\n]"),QString::SkipEmptyParts); + QStringList sl = text.split(QRegExp("[\r\n]"),QtSkipEmptyParts); text = sl.join("\n> "); text.replace("\n> >","\n>>"); // Don't add space for already quotted lines. text.replace(QChar(-4)," ");//Char used when image on text. diff --git a/retroshare-gui/src/util/HandleRichText.h b/retroshare-gui/src/util/HandleRichText.h index 8189e4ce1..3e98ea21c 100644 --- a/retroshare-gui/src/util/HandleRichText.h +++ b/retroshare-gui/src/util/HandleRichText.h @@ -70,7 +70,7 @@ public: static QString toHtml(QString text, bool realHtml = true); static bool makeEmbeddedImage(const QString &fileName, QString &embeddedImage, const int maxPixels, const int maxBytes = -1); - static bool makeEmbeddedImage(const QImage &originalImage, QString &embeddedImage, const int maxPixels, const int maxBytes = -1); + static bool makeEmbeddedImage(const QImage &originalImage, QString &embeddedImage, const int maxPixels, const int maxBytes = -1); static QString plainText(const QString &text); static QString plainText(const std::string &text); @@ -82,6 +82,7 @@ public: protected: void embedHtml(QTextDocument *textDocument, QDomDocument &doc, QDomElement ¤tElement, EmbedInHtml& embedInfos, ulong flag); void replaceAnchorWithImg(QDomDocument& doc, QDomElement &element, QTextDocument *textDocument, const RetroShareLink &link); + void filterEmbeddedImages(QDomDocument &doc, QDomElement ¤tElement); virtual bool canReplaceAnchor(QDomDocument &doc, QDomElement &element, const RetroShareLink &link); virtual void anchorTextForImg(QDomDocument &doc, QDomElement &element, const RetroShareLink &link, QString &text); diff --git a/retroshare-gui/src/util/QtVersion.h b/retroshare-gui/src/util/QtVersion.h index d04d226ae..f5e8e9784 100644 --- a/retroshare-gui/src/util/QtVersion.h +++ b/retroshare-gui/src/util/QtVersion.h @@ -21,7 +21,7 @@ #ifndef QTVERSION_H #define QTVERSION_H -// Macros to compile with Qt 4 and Qt 5 +// Macros to compile with Qt 4, Qt 5 and Qt 6 // Renamed QHeaderView::setResizeMode to QHeaderView::setSectionResizeMode #if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) @@ -43,4 +43,10 @@ #define QHeaderView_setSectionsMovable(header, movable) header->setMovable(movable); #endif +#if QT_VERSION >= QT_VERSION_CHECK (6, 0, 0) +#define QtSkipEmptyParts Qt::SkipEmptyParts +#else +#define QtSkipEmptyParts QString::SkipEmptyParts +#endif + #endif diff --git a/retroshare-gui/src/util/RichTextEdit.cpp b/retroshare-gui/src/util/RichTextEdit.cpp index 9d4596a82..020b13db9 100644 --- a/retroshare-gui/src/util/RichTextEdit.cpp +++ b/retroshare-gui/src/util/RichTextEdit.cpp @@ -167,7 +167,7 @@ RichTextEdit::RichTextEdit(QWidget *parent) : QWidget(parent) { QFontDatabase db; foreach(int size, db.standardSizes()) - f_fontsize->addItem(QString::number(size)); + f_fontsize->addItem(QString::number(size), size); connect(f_fontsize, SIGNAL(activated(QString)), this, SLOT(textSize(QString))); @@ -195,6 +195,9 @@ RichTextEdit::RichTextEdit(QWidget *parent) : QWidget(parent) { // check message length connect(f_textedit, SIGNAL(textChanged()), this, SLOT(checkLength())); + mMessageFontSizeHandler.registerFontSize(f_textedit, [this] (QWidget*, int fontSize) { + f_fontsize->setCurrentIndex(f_fontsize->findData(fontSize)); + }); } diff --git a/retroshare-gui/src/util/RichTextEdit.h b/retroshare-gui/src/util/RichTextEdit.h index aae9d20ab..6e4869838 100644 --- a/retroshare-gui/src/util/RichTextEdit.h +++ b/retroshare-gui/src/util/RichTextEdit.h @@ -23,6 +23,7 @@ #include #include "ui_RichTextEdit.h" +#include "util/FontSizeHandler.h" /** * @Brief A simple rich-text editor @@ -93,6 +94,9 @@ signals: ParagraphMonospace }; QPointer m_lastBlockList; + +private: + MessageFontSizeHandler mMessageFontSizeHandler; }; #endif diff --git a/retroshare-gui/src/util/RichTextEdit.ui b/retroshare-gui/src/util/RichTextEdit.ui index 7b5ffc6ae..5bb57a792 100644 --- a/retroshare-gui/src/util/RichTextEdit.ui +++ b/retroshare-gui/src/util/RichTextEdit.ui @@ -6,7 +6,7 @@ 0 0 - 703 + 784 312
    @@ -48,7 +48,7 @@ 0
    - + Qt::ClickFocus @@ -61,7 +61,7 @@ - + MS Sans Serif @@ -566,7 +566,6 @@ MS Sans Serif - 9 @@ -590,10 +589,15 @@ + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    MimeTextEdit QTextEdit -
    gui/common/MimeTextEdit.h
    +
    gui/common/MimeTextEdit.h
    @@ -603,7 +607,6 @@ f_menu - diff --git a/retroshare-gui/src/util/RsAction.cpp b/retroshare-gui/src/util/RsAction.cpp index f80fd0293..a0c38d492 100644 --- a/retroshare-gui/src/util/RsAction.cpp +++ b/retroshare-gui/src/util/RsAction.cpp @@ -20,7 +20,7 @@ #include "util/RsAction.h" -RsAction::RsAction(QWidget * parent, std::string rsid) +RsAction::RsAction(QObject * parent, std::string rsid) : QAction(parent), RsId(rsid) { connect(this, SIGNAL( triggered( bool ) ), this, SLOT( triggerEvent( bool ) ) ); diff --git a/retroshare-gui/src/util/RsAction.h b/retroshare-gui/src/util/RsAction.h index d61efc08b..b2110428a 100644 --- a/retroshare-gui/src/util/RsAction.h +++ b/retroshare-gui/src/util/RsAction.h @@ -28,7 +28,7 @@ class RsAction : public QAction { Q_OBJECT public: - RsAction(QWidget * parent, std::string rsid); + RsAction(QObject *parent, std::string rsid); RsAction(const QString & text, QObject * parent, std::string rsid); RsAction(const QIcon & icon, const QString & text, QObject * parent , std::string rsid); diff --git a/retroshare-gui/src/util/imageutil.cpp b/retroshare-gui/src/util/imageutil.cpp index 47029505e..690872bdb 100644 --- a/retroshare-gui/src/util/imageutil.cpp +++ b/retroshare-gui/src/util/imageutil.cpp @@ -23,8 +23,12 @@ #include "util/rstime.h" #include +#include +#include #include #include +#include +#include #include #include #include @@ -37,6 +41,64 @@ ImageUtil::ImageUtil() {} +bool ImageUtil::checkImage(const QTextEdit *edit, const QPoint &pos, QRect *cursorRectStartOut, QRect *cursorRectLeftOut, QRect *cursorRectRightOut, QRect *cursorRectEndOut) +{ + QString imageStr; + return checkImage(edit, pos, imageStr, cursorRectStartOut, cursorRectLeftOut, cursorRectRightOut, cursorRectEndOut); +} + +bool ImageUtil::checkImage(const QTextEdit *edit, const QPoint &pos, QString &imageStr, QRect *cursorRectStartOut, QRect *cursorRectLeftOut, QRect *cursorRectRightOut, QRect *cursorRectEndOut) +{ + //Get text cursor under pos. But if pos is under text browser end line this return last cursor. + QTextCursor cursor = edit->cursorForPosition(pos); + //First get rect of cursor (could be at left or right of image) + QRect cursorRectStart = edit->cursorRect(cursor); + //Second get text + cursor.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, 1);//To get character just before + QRect cursorRectLeft = edit->cursorRect(cursor); + cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 2); + QRect cursorRectRight = edit->cursorRect(cursor); + imageStr = cursor.selection().toHtml(); + + if (cursorRectStartOut) { + *cursorRectStartOut = cursorRectStart; + } + if (cursorRectLeftOut) { + *cursorRectLeftOut = cursorRectLeft; + } + if (cursorRectRightOut) { + *cursorRectRightOut = cursorRectRight; + } + + QRect cursorRectEnd = cursorRectStart; + //Finally set left with right of precedent character. + if (cursorRectEnd.top() < cursorRectLeft.bottom()) + { + cursorRectEnd.setLeft(cursorRectLeft.right()); + } else { + //Image on new line + cursorRectEnd.setLeft(0); + } + //And set Right with left of next character. + if (cursorRectEnd.bottom() > cursorRectRight.top()) + { + cursorRectEnd.setRight(cursorRectRight.left()); + } else { + //New line after Image. + } + + if (cursorRectEndOut) { + *cursorRectEndOut = cursorRectEnd; + } + + //If pos is on text rect + if (cursorRectEnd.contains(pos)) + { + return imageStr.indexOf("base64,") != -1; + } + return false; +} + void ImageUtil::extractImage(QWidget *window, QTextCursor cursor, QString file) { cursor.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, 1); @@ -53,13 +115,7 @@ void ImageUtil::extractImage(QWidget *window, QTextCursor cursor, QString file) if(!image.isNull()) { success = true; - if(!file.isEmpty() || misc::getSaveFileName(window, RshareSettings::LASTDIR_IMAGES, "Save Picture File", "Pictures (*.png *.xpm *.jpg)", file)) - { - if(!image.save(file, nullptr, 100)) - if(!image.save(file + ".png", nullptr, 100)) - QMessageBox::warning(window, QApplication::translate("ImageUtil", "Save image"), QApplication::translate("ImageUtil", "Cannot save the image, invalid filename") - + "\n" + file); - } + saveImage(window, image, file); } } if(!success) @@ -68,12 +124,60 @@ void ImageUtil::extractImage(QWidget *window, QTextCursor cursor, QString file) } } -bool ImageUtil::optimizeSizeBytes(QByteArray &bytearray, const QImage &original, QImage &optimized, int maxPixels, int maxBytes) +bool ImageUtil::saveImage(QWidget *window, const QImage &image, QString file) +{ + bool result = false; + + if (!file.isEmpty() || misc::getSaveFileName(window, RshareSettings::LASTDIR_IMAGES, QApplication::translate("ImageUtil", "Save Picture File"), QApplication::translate("ImageUtil", "Pictures (*.png *.xpm *.jpg)"), file)) { + if (image.save(file, nullptr, 100)) { + result = true; + } else { + if (image.save(file + ".png", nullptr, 100)) { + result = true; + } else { + QMessageBox::warning(window, QApplication::translate("ImageUtil", "Save image"), QApplication::translate("ImageUtil", "Cannot save the image, invalid filename") + + "\n" + file); + } + } + } + + return result; +} + +void ImageUtil::copyImage(QWidget *window, QTextCursor cursor) +{ + cursor.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, 1); + cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 2); + QString imagestr = cursor.selection().toHtml(); + bool success = false; + int start = imagestr.indexOf("base64,") + 7; + int stop = imagestr.indexOf("\"", start); + int length = stop - start; + if((start >= 0) && (length > 0)) + { + QByteArray ba = QByteArray::fromBase64(imagestr.mid(start, length).toLatin1()); + QImage image = QImage::fromData(ba); + if(!image.isNull()) + { + success = true; + QClipboard *clipboard = QApplication::clipboard(); + QMimeData *data = new QMimeData; + data->setImageData(image); + clipboard->setMimeData(data, QClipboard::Clipboard); + } + } + if(!success) + { + QMessageBox::warning(window, QApplication::translate("ImageUtil", "Copy image"), QApplication::translate("ImageUtil", "Not an image")); + } +} + +bool ImageUtil::optimizeSizeBytes(QByteArray &bytearray, const QImage &original, QImage &optimized, const char *format, int maxPixels, int maxBytes) { //nothing to do if it fits into the limits optimized = original; if ((maxPixels <= 0) || (optimized.width()*optimized.height() <= maxPixels)) { - int s = checkSize(bytearray, optimized); + int s = checkSize(bytearray, optimized,format); if((maxBytes <= 0) || (s <= maxBytes)) { return true; } @@ -92,7 +196,7 @@ bool ImageUtil::optimizeSizeBytes(QByteArray &bytearray, const QImage &original, //if maxBytes not defined, do not reduce color space, just downscale if(maxBytes <= 0) { - checkSize(bytearray, optimized = original.scaledToWidth(maxwidth, Qt::SmoothTransformation)); + checkSize(bytearray, optimized = original.scaledToWidth(maxwidth, Qt::SmoothTransformation),format); return true; } @@ -100,9 +204,9 @@ bool ImageUtil::optimizeSizeBytes(QByteArray &bytearray, const QImage &original, quantization(original, ct); //Use binary search to find a suitable image size + linear regression to guess the file size - double maxsize = (double)checkSize(bytearray, optimized = original.scaledToWidth(maxwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct, Qt::ThresholdDither)); + double maxsize = (double)checkSize(bytearray, optimized = original.scaledToWidth(maxwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct, Qt::ThresholdDither),format); if(maxsize <= maxBytes) return true; //success - double minsize = (double)checkSize(bytearray, optimized = original.scaledToWidth(minwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct, Qt::ThresholdDither)); + double minsize = (double)checkSize(bytearray, optimized = original.scaledToWidth(minwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct, Qt::ThresholdDither),format); if(minsize > maxBytes) return false; //impossible // std::cout << "maxS: " << maxsize << " minS: " << minsize << std::endl; @@ -115,7 +219,7 @@ bool ImageUtil::optimizeSizeBytes(QByteArray &bytearray, const QImage &original, double b = maxsize - m * ((double)maxwidth * (double)maxwidth / whratio); double a = ((double)(maxBytes - region/2) - b) / m; //maxBytes - region/2 target the center of the accepted region int nextwidth = (int)sqrt(a * whratio); - int nextsize = checkSize(bytearray, optimized = original.scaledToWidth(nextwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct, Qt::ThresholdDither)); + int nextsize = checkSize(bytearray, optimized = original.scaledToWidth(nextwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct, Qt::ThresholdDither),format); if(nextsize <= maxBytes) { minsize = nextsize; minwidth = nextwidth; @@ -137,6 +241,25 @@ bool ImageUtil::optimizeSizeBytes(QByteArray &bytearray, const QImage &original, //std::cout << html.toStdString() << std::endl; } +bool ImageUtil::hasAlphaContent(const QImage& image) +{ + if(!image.hasAlphaChannel()) + { + std::cerr << "Image of size " << image.width() << " x " << image.height() << ": No transparency content detected." << std::endl; + return false; + } + + for(int i=0;i"); return true; @@ -156,7 +284,7 @@ bool ImageUtil::optimizeSizeHtml(QString &html, const QImage& original, QImage & return false; } -int ImageUtil::checkSize(QByteArray &bytearray, const QImage &img) +int ImageUtil::checkSize(QByteArray &bytearray, const QImage &img,const char *format) { rstime::RsScopeTimer st("Check size"); @@ -166,7 +294,7 @@ int ImageUtil::checkSize(QByteArray &bytearray, const QImage &img) //std::cout << QString("Trying image: format PNG, size %1x%2, colors %3\n").arg(img.width()).arg(img.height()).arg(img.colorCount()).toStdString(); if (buffer.open(QIODevice::WriteOnly)) { - if (img.save(&buffer, "PNG", 0)) { + if (img.save(&buffer, format, 85)) { size = bytearray.length(); } else { std::cerr << "ImageUtil: image can't be saved to buffer" << std::endl; diff --git a/retroshare-gui/src/util/imageutil.h b/retroshare-gui/src/util/imageutil.h index 1a9658e13..46e83e728 100644 --- a/retroshare-gui/src/util/imageutil.h +++ b/retroshare-gui/src/util/imageutil.h @@ -22,21 +22,28 @@ #define IMAGEUTIL_H #include -#include -#include #include +class QWidget; +class QTextEdit; +class QByteArray; + class ImageUtil { public: ImageUtil(); + static bool checkImage(const QTextEdit *edit, const QPoint &pos, QRect *cursorRectStartOut = NULL, QRect *cursorRectLeftOut = NULL, QRect *cursorRectRightOut = NULL, QRect *cursorRectEndOut = NULL); + static bool checkImage(const QTextEdit *edit, const QPoint &pos, QString &imageStr, QRect *cursorRectStartOut = NULL, QRect *cursorRectLeftOut = NULL, QRect *cursorRectRightOut = NULL, QRect *cursorRectEndOut = NULL); static void extractImage(QWidget *window, QTextCursor cursor, QString file = ""); - static bool optimizeSizeHtml(QString &html, const QImage& original, QImage &optimized, int maxPixels = -1, int maxBytes = -1); - static bool optimizeSizeBytes(QByteArray &bytearray, const QImage& original, QImage &optimized, int maxPixels = -1, int maxBytes = -1); + static void copyImage(QWidget *window, QTextCursor cursor); + static bool saveImage(QWidget *window, const QImage &image, QString file = ""); + static bool optimizeSizeHtml(QString &html, const QImage& original, QImage &optimized, int maxPixels = -1, int maxBytes = -1); + static bool optimizeSizeBytes(QByteArray &bytearray, const QImage &original, QImage &optimized, const char *format, int maxPixels, int maxBytes); + static bool hasAlphaContent(const QImage& image); private: - static int checkSize(QByteArray& embeddedImage, const QImage& img); + static int checkSize(QByteArray& embeddedImage, const QImage& img, const char *format); static void quantization(const QImage& img, QVector& palette); static void quantization(QList::iterator begin, QList::iterator end, int depth, QVector& palette); static void avgbucket(QList::iterator begin, QList::iterator end, QVector& palette); diff --git a/retroshare-gui/src/util/misc.cpp b/retroshare-gui/src/util/misc.cpp index e63ad2fd6..84c408de3 100644 --- a/retroshare-gui/src/util/misc.cpp +++ b/retroshare-gui/src/util/misc.cpp @@ -19,17 +19,20 @@ * * *******************************************************************************/ -#include +#include "misc.h" + +#include "gui/common/FilesDefs.h" +#include "util/rsdebug.h" + +#include +#include +#include #include #include -#include -#include -#include #include +#include -#include "misc.h" -#include "util/rsdebug.h" -#include "gui/common/FilesDefs.h" +#include // return best userfriendly storage unit (B, KiB, MiB, GiB, TiB) // use Binary prefix standards from IEC 60027-2 @@ -67,46 +70,46 @@ QString misc::fingerPrintStyleSplit(const QString& in) bool misc::isPreviewable(QString extension) { extension = extension.toUpper(); - if(extension == "AVI") return true; - if(extension == "MP3") return true; - if(extension == "OGG") return true; - if(extension == "OGM") return true; - if(extension == "WMV") return true; - if(extension == "WMA") return true; - if(extension == "MPEG") return true; - if(extension == "MPG") return true; - if(extension == "ASF") return true; - if(extension == "QT") return true; - if(extension == "RM") return true; - if(extension == "RMVB") return true; - if(extension == "RMV") return true; - if(extension == "SWF") return true; - if(extension == "FLV") return true; - if(extension == "WAV") return true; - if(extension == "MOV") return true; - if(extension == "VOB") return true; - if(extension == "MID") return true; - if(extension == "AC3") return true; - if(extension == "MP4") return true; - if(extension == "MP2") return true; - if(extension == "AVI") return true; - if(extension == "FLAC") return true; - if(extension == "AU") return true; - if(extension == "MPE") return true; - if(extension == "MOV") return true; - if(extension == "MKV") return true; - if(extension == "AIF") return true; - if(extension == "AIFF") return true; - if(extension == "AIFC") return true; - if(extension == "RA") return true; - if(extension == "RAM") return true; - if(extension == "M4P") return true; - if(extension == "M4A") return true; if(extension == "3GP") return true; if(extension == "AAC") return true; - if(extension == "SWA") return true; + if(extension == "AC3") return true; + if(extension == "AIF") return true; + if(extension == "AIFC") return true; + if(extension == "AIFF") return true; + if(extension == "ASF") return true; + if(extension == "AU") return true; + if(extension == "AVI") return true; + if(extension == "FLAC") return true; + if(extension == "FLV") return true; + if(extension == "M4P") return true; + if(extension == "M4A") return true; + if(extension == "MOV") return true; + if(extension == "MID") return true; + if(extension == "MKV") return true; + if(extension == "MP2") return true; + if(extension == "MP3") return true; + if(extension == "MP4") return true; if(extension == "MPC") return true; + if(extension == "MPE") return true; + if(extension == "MPEG") return true; + if(extension == "MPG") return true; if(extension == "MPP") return true; + if(extension == "OGG") return true; + if(extension == "OGM") return true; + if(extension == "QT") return true; + if(extension == "RA") return true; + if(extension == "RAM") return true; + if(extension == "RM") return true; + if(extension == "RMV") return true; + if(extension == "RMVB") return true; + if(extension == "SWA") return true; + if(extension == "SWF") return true; + if(extension == "VOB") return true; + if(extension == "WAV") return true; + if(extension == "WMA") return true; + if(extension == "WMV") return true; + if(extension == "WEBM") return true; + if(extension == "WEBA") return true; return false; } @@ -227,8 +230,6 @@ QString misc::userFriendlyUnit(double count, unsigned int decimal, double factor return "0"; } - QString output; - int i; for (i = 0; i < 5; ++i) { if (count < factor) { @@ -290,7 +291,7 @@ bool misc::getOpenAvatarPicture(QWidget *parent, QByteArray &image_data) // save image in QByteArray QBuffer buffer(&image_data); buffer.open(QIODevice::WriteOnly); - picture.save(&buffer, "PNG"); // writes image into ba in PNG format + picture.save(&buffer, "PNG"); // writes image into ba in PNG format return true; } @@ -434,3 +435,12 @@ void misc::clearLayout(QLayout * layout) { //delete item;//Auto deleted by Qt. } } + +QSizeF misc::getFontSizeFactor(const QString &group, const qreal defaultFactor /*= 1.0*/) +{ + static qreal appFontWidth = QFontMetrics(QApplication::font()).maxWidth(); + static qreal appFontHeight = QFontMetrics(QApplication::font()).height(); + qreal factor = Settings->valueFromGroup("FontHeighFactor",group,defaultFactor).toReal(); + return QSizeF(appFontWidth*factor,appFontHeight*factor); +} + diff --git a/retroshare-gui/src/util/misc.h b/retroshare-gui/src/util/misc.h index f09280ecf..2863a867c 100644 --- a/retroshare-gui/src/util/misc.h +++ b/retroshare-gui/src/util/misc.h @@ -22,14 +22,15 @@ #ifndef MISC_H #define MISC_H -#include +#include "gui/settings/rsharesettings.h" + +#include +#include #include #include #include -#include -#include -#include "gui/settings/rsharesettings.h" +#include /* Miscellaneaous functions that can be useful */ class misc : public QObject @@ -165,15 +166,15 @@ class misc : public QObject static QPixmap getOpenThumbnailedPicture(QWidget *parent, const QString &caption, int width, int height); static bool getOpenFileName(QWidget *parent, RshareSettings::enumLastDir type , const QString &caption, const QString &filter - , QString &file, QFileDialog::Options options = 0); + , QString &file, QFileDialog::Options options = QFileDialog::Options()); static bool getOpenFileNames(QWidget *parent, RshareSettings::enumLastDir type , const QString &caption, const QString &filter - , QStringList &files, QFileDialog::Options options = 0); + , QStringList &files, QFileDialog::Options options = QFileDialog::Options()); static bool getSaveFileName(QWidget *parent, RshareSettings::enumLastDir type , const QString &caption , const QString &filter - , QString &file, QString *selectedFilter = NULL - , QFileDialog::Options options = 0); + , QString &file, QString *selectedFilter = NULL + , QFileDialog::Options options = QFileDialog::Options()); static QFont getFont(bool *ok , const QFont &initial @@ -187,6 +188,9 @@ class misc : public QObject //Clear QLayout static void clearLayout(QLayout *layout); + static QSizeF getFontSizeFactor(const QString &group, const qreal defaultFactor = 1.0); + static QSizeF getFontSizeFactor() {return getFontSizeFactor("Main");} + }; // Trick to get a portable sleep() function @@ -201,7 +205,7 @@ class SleeperThread : public QThread{ template class SignalsBlocker { public: - SignalsBlocker(T *blocked) : blocked(blocked), previous(blocked->blockSignals(true)) {} + explicit SignalsBlocker(T *blocked) : blocked(blocked), previous(blocked->blockSignals(true)) {} ~SignalsBlocker() { blocked->blockSignals(previous); } T *operator->() { return blocked; } diff --git a/retroshare-gui/src/util/retroshareWin32.cpp b/retroshare-gui/src/util/retroshareWin32.cpp index 2e025a354..5693ef514 100644 --- a/retroshare-gui/src/util/retroshareWin32.cpp +++ b/retroshare-gui/src/util/retroshareWin32.cpp @@ -21,7 +21,6 @@ #ifdef WIN32 -#define WIN32_LEAN_AND_MEAN #include #endif diff --git a/retroshare-service/CMakeLists.txt b/retroshare-service/CMakeLists.txt new file mode 100644 index 000000000..97562c91e --- /dev/null +++ b/retroshare-service/CMakeLists.txt @@ -0,0 +1,177 @@ +# RetroShare decentralized communication platform +# +# Copyright (C) 2021-2022 Gioacchino Mazzurco +# Copyright (C) 2021-2022 Asociación Civil Altermundi +# +# SPDX-License-Identifier: CC0-1.0 + +cmake_minimum_required (VERSION 3.18.0) +project(retroshare-service) + +include(CMakeDependentOption) + +if(APPLE) + include_directories("/usr/local/include") + LINK_DIRECTORIES("/usr/local/lib") +endif() + +set( + RS_BIN_INSTALL_DIR + "${CMAKE_INSTALL_PREFIX}/bin" + CACHE PATH + "Path where to install retroshare-service compiled binary" ) + +option( + RS_DEVELOPMENT_BUILD + "Disable optimization to speed up build, enable verbose build log. \ + just for development purposes, not suitable for library usage" + OFF ) + +option( + RS_JSON_API + "Use restbed to expose libretroshare as JSON API via HTTP" + ON ) + +option( + RS_SERVICE_DESKTOP + "Install icons and shortcuts for desktop environements" + OFF ) + +option( + RS_SERVICE_TERMINAL_LOGIN + "Enable RetroShare login via terminal" + ON ) + +cmake_dependent_option( + RS_SERVICE_TERMINAL_WEBUI_PASSWORD + "Enable settin Web UI password via terminal in retroshare-service" + OFF + "RS_WEBUI" + ON ) + +cmake_dependent_option( + RS_WEBUI + "Install RetroShare Web UI" + OFF + "RS_JSON_API" + ON ) + +################################################################################ + +set(FETCHCONTENT_QUIET OFF) +include(FetchContent) + +find_package(Git REQUIRED) + +################################################################################ + +if(RS_DEVELOPMENT_BUILD) + set(CMAKE_VERBOSE_MAKEFILE ON) + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +endif(RS_DEVELOPMENT_BUILD) + +################################################################################ + +list( + APPEND RS_SERVICE_SOURCES + src/retroshare-service.cc ) + +add_executable(${PROJECT_NAME} ${RS_SERVICE_SOURCES}) + +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 17) + +install(TARGETS ${PROJECT_NAME} DESTINATION ${RS_BIN_INSTALL_DIR}) + +################################################################################ + +if(RS_DEVELOPMENT_BUILD) + target_compile_options(${PROJECT_NAME} PRIVATE "-O0") +endif(RS_DEVELOPMENT_BUILD) + +################################################################################ + +set(LIBRETROSHARE_DEVEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../libretroshare/") +if(EXISTS "${LIBRETROSHARE_DEVEL_DIR}/CMakeLists.txt" ) + message( + STATUS + "libretroshare source found at ${LIBRETROSHARE_DEVEL_DIR} using it" ) + add_subdirectory( + "${LIBRETROSHARE_DEVEL_DIR}" "${CMAKE_BINARY_DIR}/libretroshare" ) +else() + FetchContent_Declare( + libretroshare + GIT_REPOSITORY "https://github.com/RetroShare/libretroshare.git" + GIT_TAG "origin/master" + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE + TIMEOUT 10 + ) + FetchContent_MakeAvailable(libretroshare) +endif() + +target_link_libraries(${PROJECT_NAME} PRIVATE retroshare) + +################################################################################ + +if(RS_SERVICE_DESKTOP) + if(UNIX AND NOT APPLE) + install( + FILES data/retroshare-service.svg + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/ ) + + install( + FILES data/retroshare-service_48x48.png + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps/ + RENAME retroshare-service.png) + + install( + FILES data/retroshare-service_128x128.png + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/128x128/apps/ + RENAME retroshare-service.png ) + + install( + FILES data/retroshare-service.desktop + DESTINATION ${CMAKE_INSTALL_PREFIX}/data/ ) + endif(UNIX AND NOT APPLE) +endif(RS_SERVICE_DESKTOP) + +################################################################################ + +if(RS_JSON_API) + target_compile_definitions(${PROJECT_NAME} PUBLIC RS_JSONAPI) +endif(RS_JSON_API) + +if(RS_SERVICE_TERMINAL_LOGIN) + target_compile_definitions(${PROJECT_NAME} PUBLIC RS_SERVICE_TERMINAL_LOGIN) +endif(RS_SERVICE_TERMINAL_LOGIN) + +if(RS_WEBUI) + set(RS_WEBUI_DEVEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../webui/") + if(EXISTS "${RS_WEBUI_DEVEL_DIR}/CMakeLists.txt" ) + message( + STATUS + "RetroShare WebUI source found at ${RS_WEBUI_DEVEL_DIR} using it" ) + add_subdirectory( + "${RS_WEBUI_DEVEL_DIR}" "${CMAKE_BINARY_DIR}/webui" ) + else() + FetchContent_Declare( + webui + GIT_REPOSITORY "https://github.com/RetroShare/RSNewWebUI.git" + GIT_TAG "origin/master" + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE + TIMEOUT 10 + ) + FetchContent_MakeAvailable(webui) + endif() + + add_dependencies(${PROJECT_NAME} retroshare-webui) + target_compile_definitions(${PROJECT_NAME} PUBLIC RS_WEBUI) +endif(RS_WEBUI) + +if(RS_SERVICE_TERMINAL_WEBUI_PASSWORD) + target_compile_definitions( + ${PROJECT_NAME} PUBLIC RS_SERVICE_TERMINAL_WEBUI_PASSWORD ) +endif(RS_SERVICE_TERMINAL_WEBUI_PASSWORD) + +################################################################################ diff --git a/retroshare-service/data/retroshare-service.desktop b/retroshare-service/data/retroshare-service.desktop index 5d077597b..fc8135e05 100644 --- a/retroshare-service/data/retroshare-service.desktop +++ b/retroshare-service/data/retroshare-service.desktop @@ -7,4 +7,4 @@ Exec=retroshare-service %U Icon=retroshare-service Terminal=false Type=Application -Categories=Application;Network; +Categories=Network; diff --git a/retroshare-service/src/android/AndroidManifest.xml b/retroshare-service/src/android/AndroidManifest.xml index d41a72995..ecf8ba78a 100644 --- a/retroshare-service/src/android/AndroidManifest.xml +++ b/retroshare-service/src/android/AndroidManifest.xml @@ -2,9 +2,9 @@ - + @@ -14,59 +14,81 @@ - - - - - - - - - - - - - + + + + + - + + + + - - - - +]]> + + + + + + + + + + + + + + + +]]> + + + + + + + + + + + + + @@ -76,17 +98,11 @@ ++ features based on the dependencies of the application. ++ Remove the comment if you do not require these default features. --> +]]> - + - - - - - - - - - + --> +]]> diff --git a/retroshare-service/src/android/src/org/retroshare/service/AppUpdatedReceiver.java b/retroshare-service/src/android/src/org/retroshare/service/AppUpdatedReceiver.java index 283fd10cc..3f2e3f375 100644 --- a/retroshare-service/src/android/src/org/retroshare/service/AppUpdatedReceiver.java +++ b/retroshare-service/src/android/src/org/retroshare/service/AppUpdatedReceiver.java @@ -19,6 +19,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +/* package org.retroshare.service; import android.content.BroadcastReceiver; @@ -36,3 +37,4 @@ public class AppUpdatedReceiver extends BroadcastReceiver RetroShareServiceAndroid.start(context); } } +*/ \ No newline at end of file diff --git a/retroshare-service/src/android/src/org/retroshare/service/AssetHelper.java b/retroshare-service/src/android/src/org/retroshare/service/AssetHelper.java new file mode 120000 index 000000000..60da18398 --- /dev/null +++ b/retroshare-service/src/android/src/org/retroshare/service/AssetHelper.java @@ -0,0 +1 @@ +../../../../../../../libretroshare/src/rs_android/org/retroshare/service/AssetHelper.java \ No newline at end of file diff --git a/retroshare-service/src/android/src/org/retroshare/service/BootCompletedReceiver.java b/retroshare-service/src/android/src/org/retroshare/service/BootCompletedReceiver.java index 89c09c241..75bfbc063 100644 --- a/retroshare-service/src/android/src/org/retroshare/service/BootCompletedReceiver.java +++ b/retroshare-service/src/android/src/org/retroshare/service/BootCompletedReceiver.java @@ -19,6 +19,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +/* package org.retroshare.service; import android.content.BroadcastReceiver; @@ -35,3 +36,4 @@ public class BootCompletedReceiver extends BroadcastReceiver RetroShareServiceAndroid.start(context); } } +*/ \ No newline at end of file diff --git a/retroshare-service/src/android/src/org/retroshare/service/ErrorConditionWrap.java b/retroshare-service/src/android/src/org/retroshare/service/ErrorConditionWrap.java new file mode 120000 index 000000000..1f90a62c6 --- /dev/null +++ b/retroshare-service/src/android/src/org/retroshare/service/ErrorConditionWrap.java @@ -0,0 +1 @@ +../../../../../../../libretroshare/src/rs_android/org/retroshare/service/ErrorConditionWrap.java \ No newline at end of file diff --git a/retroshare-service/src/android/src/org/retroshare/service/RetroShareServiceAndroid.java b/retroshare-service/src/android/src/org/retroshare/service/RetroShareServiceAndroid.java deleted file mode 100644 index 3cea999bf..000000000 --- a/retroshare-service/src/android/src/org/retroshare/service/RetroShareServiceAndroid.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * RetroShare - * Copyright (C) 2016-2018 Gioacchino Mazzurco - * - * 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 . - * - * SPDX-FileCopyrightText: Retroshare Team - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -package org.retroshare.service; - -import android.app.ActivityManager; -import android.content.Context; -import android.content.Intent; - -import org.qtproject.qt5.android.bindings.QtService; - -public class RetroShareServiceAndroid extends QtService -{ - public static void start(Context ctx) - { - ctx.startService(new Intent(ctx, RetroShareServiceAndroid.class)); - } - - public static void stop(Context ctx) - { - ctx.stopService(new Intent(ctx, RetroShareServiceAndroid.class)); - } - - public static boolean isRunning(Context ctx) - { - ActivityManager manager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE); - for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) - if (RetroShareServiceAndroid.class.getName().equals(service.service.getClassName())) - return true; - return false; - } -} diff --git a/retroshare-service/src/android/src/org/retroshare/service/RetroShareServiceAndroid.java b/retroshare-service/src/android/src/org/retroshare/service/RetroShareServiceAndroid.java new file mode 120000 index 000000000..480e21ac4 --- /dev/null +++ b/retroshare-service/src/android/src/org/retroshare/service/RetroShareServiceAndroid.java @@ -0,0 +1 @@ +../../../../../../../libretroshare/src/rs_android/org/retroshare/service/RetroShareServiceAndroid.java \ No newline at end of file diff --git a/retroshare-service/src/android/src/org/retroshare/service/RetroShareServiceControlActivity.java b/retroshare-service/src/android/src/org/retroshare/service/RetroShareServiceControlActivity.java index d1e1f78b7..dafe10301 100644 --- a/retroshare-service/src/android/src/org/retroshare/service/RetroShareServiceControlActivity.java +++ b/retroshare-service/src/android/src/org/retroshare/service/RetroShareServiceControlActivity.java @@ -1,6 +1,6 @@ /* * RetroShare - * Copyright (C) 2016-2018 Gioacchino Mazzurco + * Copyright (C) 2016-2021 Gioacchino Mazzurco * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -50,7 +50,11 @@ public class RetroShareServiceControlActivity extends Activity else { button.setText("Starting..."); - RetroShareServiceAndroid.start(RetroShareServiceControlActivity.this); + RetroShareServiceAndroid.start( + RetroShareServiceControlActivity.this, + RetroShareServiceAndroid.DEFAULT_JSON_API_PORT, + RetroShareServiceAndroid.DEFAULT_JSON_API_BINDING_ADDRESS + ); serviceStarting = true; serviceStopping = false; } diff --git a/retroshare-service/src/logo.icns b/retroshare-service/src/logo.icns new file mode 100644 index 000000000..cb105009d Binary files /dev/null and b/retroshare-service/src/logo.icns differ diff --git a/retroshare-service/src/retroshare-service-android.cc b/retroshare-service/src/retroshare-service-android.cc new file mode 100644 index 000000000..30204c8fd --- /dev/null +++ b/retroshare-service/src/retroshare-service-android.cc @@ -0,0 +1,29 @@ +/* + * RetroShare Service Android + * Copyright (C) 2021 Gioacchino Mazzurco + * Copyright (C) 2021 Asociación Civil Altermundi + * + * 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 . + * + * SPDX-FileCopyrightText: Retroshare Team + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include "rs_android/rsjni.hpp" + +extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* _reserved) +{ + RS_DBG(vm); + return JNI_OnLoad_retroshare(vm, _reserved); +} diff --git a/retroshare-service/src/retroshare-service.cc b/retroshare-service/src/retroshare-service.cc index e80d468e1..ac82593da 100644 --- a/retroshare-service/src/retroshare-service.cc +++ b/retroshare-service/src/retroshare-service.cc @@ -1,6 +1,7 @@ /* * RetroShare Service - * Copyright (C) 2016-2019 Gioacchino Mazzurco + * Copyright (C) 2016-2022 Gioacchino Mazzurco + * Copyright (C) 2021-2022 Asociación Civil Altermundi * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -19,39 +20,57 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -#include "util/stacktrace.h" -#include "util/argstream.h" -#include "util/rskbdinput.h" -#include "retroshare/rsinit.h" - -#ifdef RS_JSONAPI -#include "retroshare/rsjsonapi.h" - -#ifdef RS_WEBUI -#include "retroshare/rswebui.h" -#endif -#endif - -static CrashStackTrace gCrashStackTrace; #include #include #include #include -#ifdef __ANDROID__ -# include -# include -# include -# include - -# include "util/androiddebug.h" -#endif // def __ANDROID__ - +#include "retroshare/rsinit.h" +#include "retroshare/rstor.h" +#include "retroshare/rspeers.h" #include "retroshare/rsinit.h" #include "retroshare/rsiface.h" + +#include "util/stacktrace.h" +#include "util/rsprint.h" +#include "util/argstream.h" +#include "util/rskbdinput.h" +#include "util/rsdir.h" #include "util/rsdebug.h" +#ifdef RS_JSONAPI +# include "retroshare/rsjsonapi.h" + +# ifdef RS_WEBUI +# include "retroshare/rswebui.h" +# endif // def RS_WEBUI +#endif // def RS_JSONAPI + +static CrashStackTrace gCrashStackTrace; + +// We should move these functions to rsprint in libretroshare + +#define COLOR_GREEN 0 +#define COLOR_YELLOW 1 +#define COLOR_BLUE 2 +#define COLOR_PURPLE 3 +#define COLOR_RED 4 + +std::string colored(int color,const std::string& s) +{ + switch(color) + { + case COLOR_GREEN : return "\033[0;32m"+s+"\033[0m"; + case COLOR_YELLOW: return "\033[0;33m"+s+"\033[0m"; + case COLOR_BLUE : return "\033[0;36m"+s+"\033[0m"; + case COLOR_PURPLE: return "\033[0;35m"+s+"\033[0m"; + case COLOR_RED : return "\033[0;31m"+s+"\033[0m"; + default: + return s; + } +} + #ifdef RS_SERVICE_TERMINAL_LOGIN class RsServiceNotify: public NotifyClient { @@ -63,9 +82,7 @@ public: const std::string& title, const std::string& question, bool /*prev_is_bad*/, std::string& password, bool& cancel ) { - std::string question1 = title + - "\nPlease enter your PGP password for key:\n " + - question + " :"; + std::string question1 = title + colored(COLOR_GREEN,"Please enter your PGP password for key:\n ") + question + " :"; password = RsUtil::rs_getpass(question1.c_str()) ; cancel = false ; @@ -74,9 +91,6 @@ public: }; #endif // def RS_SERVICE_TERMINAL_LOGIN -#ifdef __ANDROID__ -void signalHandler(int /*signal*/) { QCoreApplication::exit(0); } -#else static std::atomic keepRunning(true); static int receivedSignal = 0; @@ -87,22 +101,43 @@ void signalHandler(int signal) receivedSignal = signal; keepRunning = false; } -#endif // def __ANDROID__ int main(int argc, char* argv[]) { -#ifdef __ANDROID__ - AndroidStdIOCatcher dbg; (void) dbg; - QAndroidService app(argc, argv); -#endif // def __ANDROID__ - signal(SIGINT, signalHandler); signal(SIGTERM, signalHandler); #ifdef SIGBREAK signal(SIGBREAK, signalHandler); #endif // ifdef SIGBREAK +#ifdef WINDOWS_SYS + // Enable ANSI color support in Windows console + { +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4 +#endif + + HANDLE hStdin = GetStdHandle(STD_OUTPUT_HANDLE); + if (hStdin) { + DWORD consoleMode; + if (GetConsoleMode(hStdin, &consoleMode)) { + if ((consoleMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == 0) { + if (SetConsoleMode(hStdin, consoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) { + std::cout << "Enabled ANSI color support in console" << std::endl; + } else { + RsErr() << "Error getting console mode" << std::endl; + } + } + } else { + RsErr() << "Error getting console mode" << std::endl; + } + } else { + RsErr() << "Error getting stdin handle" << std::endl; + } + } +#endif + RsInfo() << "\n" << "+================================================================+\n" "| o---o o |\n" @@ -128,7 +163,7 @@ int main(int argc, char* argv[]) RsConfigOptions conf; #ifdef RS_JSONAPI - conf.jsonApiPort = RsJsonApi::DEFAULT_PORT; // enable JSonAPI by default + conf.jsonApiPort = RsJsonApi::DEFAULT_PORT; // enable JSON API by default #ifdef RS_WEBUI std::string webui_base_directory = RsWebUi::DEFAULT_BASE_DIRECTORY; #endif @@ -139,19 +174,13 @@ int main(int argc, char* argv[]) "output to stderr instead of log file." ) >> option( 'u',"udp", conf.udpListenerOnly, "Only listen to UDP." ) - >> parameter( 'c',"base-dir", conf.optBaseDir, "directory", - "Set base directory.", false ) - >> parameter( 'l', "log-file", conf.logfname, "logfile", - "Set Log filename.", false ) - >> parameter( 'd', "debug-level", conf.debugLevel, "level", - "Set debug level.", false ) - >> parameter( 'i', "ip-address", conf.forcedInetAddress, "IP", - "Force IP address to use (if cannot be detected).", false ) - >> parameter( 'o', "opmode", conf.opModeStr, "opmode", - "Set Operating mode (Full, NoTurtle, Gaming, Minimal).", - false ) - >> parameter( 'p', "port", conf.forcedPort, "port", - "Set listenning port to use.", false ); + >> parameter( 'c',"base-dir", conf.optBaseDir, "directory", "Set base directory.", false ) + >> parameter( 'l', "log-file", conf.logfname, "logfile", "Set Log filename.", false ) + >> parameter( 'd', "debug-level", conf.debugLevel, "level", "Set debug level.", false ) + >> parameter( 'i', "ip-address", conf.forcedInetAddress, "IP", "Force IP address to use (if cannot be detected).", false ) + >> parameter( 'o', "opmode", conf.opModeStr, "opmode", "Set Operating mode (Full, NoTurtle, Gaming, Minimal).", false ) + >> parameter( 'p', "port", conf.forcedPort, "port", "Set listenning port to use.", false ) + >> parameter( 't', "tor", conf.userSuppliedTorExecutable, "tor", "Set Tor executable full path.", false ); #ifdef RS_SERVICE_TERMINAL_LOGIN as >> parameter( 'U', "user-id", prefUserString, "ID", @@ -189,43 +218,60 @@ int main(int argc, char* argv[]) as >> help( 'h', "help", "Display this Help" ); as.defaultErrorHandling(true, true); + if(!conf.userSuppliedTorExecutable.empty()) + RsTor::setTorExecutablePath(conf.userSuppliedTorExecutable); + #if (defined(RS_JSONAPI) && defined(RS_WEBUI)) && defined(RS_SERVICE_TERMINAL_WEBUI_PASSWORD) - std::string webui_pass1 = "Y"; + std::string webui_pass1; if(askWebUiPassword) { std::string webui_pass2 = "N"; while(keepRunning) { - webui_pass1 = RsUtil::rs_getpass( - "Please register a password for the web interface: " ); - webui_pass2 = RsUtil::rs_getpass( - "Please enter the same password again : " ); + webui_pass1 = RsUtil::rs_getpass( colored(COLOR_GREEN,"Please register a password for the web interface: ")); + webui_pass2 = RsUtil::rs_getpass( colored(COLOR_GREEN,"Please enter the same password again : ")); if(webui_pass1 != webui_pass2) { - std::cout << "Passwords do not match!" << std::endl; + std::cout << colored(COLOR_RED,"Passwords do not match!") << std::endl; continue; } if(webui_pass1.empty()) { - std::cout << "Password cannot be empty!" << std::endl; + std::cout << colored(COLOR_RED,"Password cannot be empty!") << std::endl; continue; } break; } } +#ifdef RS_SERVICE_TERMINAL_WEBUI_PASSWORD + if(askWebUiPassword && !webui_pass1.empty()) + { + rsWebUi->setHtmlFilesDirectory(webui_base_directory); + conf.webUIPasswd = webui_pass1; // cannot be set using rsWebUI methods because it calls the still non-existent rsJsonApi + conf.enableWebUI = true; + + // JsonApi is started below in InitRetroShare(). Not calling restart here avoids multiple restart. + } +#endif #endif /* defined(RS_JSONAPI) && defined(RS_WEBUI) && defined(RS_SERVICE_TERMINAL_WEBUI_PASSWORD) */ conf.main_executable_path = argv[0]; int initResult = RsInit::InitRetroShare(conf); + +#ifdef RS_JSONAPI + RsInit::startupWebServices(conf,true); + rstime::rs_usleep(1000000); // waits for jas->restart to print stuff +#endif + if(initResult != RS_INIT_OK) { - RsErr() << "Retroshare core initalization failed with: " << initResult - << std::endl; + RsFatal() << "Retroshare core initalization failed with: " << initResult + << std::endl; return -initResult; } @@ -239,28 +285,27 @@ int main(int argc, char* argv[]) if(locations.size() == 0) { - RsErr() << "No available accounts. You cannot use option -U list" << std::endl; + RsErr() << colored(COLOR_RED,"No available accounts. You cannot use option -U list") << std::endl; return -RsInit::ERR_NO_AVAILABLE_ACCOUNT; } std::cout << std::endl << std::endl - << "Available accounts:" << std::endl; + << colored(COLOR_GREEN,"Available accounts:") << std::endl<( ceil(log(locations.size())/log(10.0)) ); for( uint32_t i=0; i= locations.size())) { - std::cout << "Please enter account number: "; + std::cout << colored(COLOR_GREEN,"Please enter account number: "); std::cout.flush(); std::string inputStr; @@ -280,7 +325,7 @@ int main(int argc, char* argv[]) RsPeerId ssl_id(prefUserString); if(ssl_id.isNull()) { - RsErr() << "Invalid User location id: a hexadecimal ID is expected." + RsErr() << colored(COLOR_RED,"Invalid User location id: a hexadecimal ID is expected.") << std::endl; return -EINVAL; } @@ -311,34 +356,42 @@ int main(int argc, char* argv[]) << std::endl; return -result; } + + if(RsAccounts::isTorAuto()) + { + + std::cerr << colored(COLOR_GREEN,"(II) Hidden service is ready:") << std::endl; + + std::string service_id ; + std::string onion_address ; + uint16_t service_port ; + uint16_t service_target_port ; + uint16_t proxy_server_port ; + std::string service_target_address ; + std::string proxy_server_address ; + + RsTor::getHiddenServiceInfo(service_id,onion_address,service_port,service_target_address,service_target_port); + RsTor::getProxyServerInfo(proxy_server_address,proxy_server_port) ; + + std::cerr << colored(COLOR_GREEN," onion address : ") << onion_address << std::endl; + std::cerr << colored(COLOR_GREEN," service_id : ") << service_id << std::endl; + std::cerr << colored(COLOR_GREEN," service port : ") << service_port << std::endl; + std::cerr << colored(COLOR_GREEN," target port : ") << service_target_port << std::endl; + std::cerr << colored(COLOR_GREEN," target address : ") << service_target_address << std::endl; + + std::cerr << colored(COLOR_GREEN,"Setting proxy server to ") << service_target_address << ":" << service_target_port << std::endl; + + rsPeers->setLocalAddress(rsPeers->getOwnId(), service_target_address, service_target_port); + rsPeers->setHiddenNode(rsPeers->getOwnId(), onion_address, service_port); + rsPeers->setProxyServer(RS_HIDDEN_TYPE_TOR, proxy_server_address,proxy_server_port) ; + } } #endif // def RS_SERVICE_TERMINAL_LOGIN -#if (defined(RS_JSONAPI) && defined(RS_WEBUI)) && defined(RS_SERVICE_TERMINAL_WEBUI_PASSWORD) - if(rsJsonApi && !webui_pass1.empty()) - { - rsWebUi->setHtmlFilesDirectory(webui_base_directory); - rsWebUi->setUserPassword(webui_pass1); - rsWebUi->restart(); - } -#endif - -#ifdef __ANDROID__ - rsControl->setShutdownCallback(QCoreApplication::exit); - - QObject::connect( - &app, &QCoreApplication::aboutToQuit, - [](){ - if(RsControl::instance()->isReady()) - RsControl::instance()->rsGlobalShutDown(); } ); - - return app.exec(); -#else // def __ANDROID__ rsControl->setShutdownCallback([&](int){keepRunning = false;}); while(keepRunning) std::this_thread::sleep_for(std::chrono::milliseconds(500)); return 0; -#endif } diff --git a/retroshare-service/src/retroshare-service.pro b/retroshare-service/src/retroshare-service.pro index cbd1b9d13..275f868cc 100644 --- a/retroshare-service/src/retroshare-service.pro +++ b/retroshare-service/src/retroshare-service.pro @@ -1,6 +1,6 @@ # RetroShare service qmake build script # -# Copyright (C) 2018-2019, Gioacchino Mazzurco +# Copyright (C) 2018-2021, Gioacchino Mazzurco # # 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 @@ -22,9 +22,6 @@ TARGET = retroshare-service -QT += core -QT -= gui - !include("../../libretroshare/src/use_libretroshare.pri"):error("Including") SOURCES += retroshare-service.cc @@ -32,8 +29,6 @@ SOURCES += retroshare-service.cc ################################# Linux ########################################## android-* { - QT += androidextras - ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android DISTFILES += android/AndroidManifest.xml \ @@ -45,6 +40,9 @@ android-* { android/build.gradle \ android/gradle/wrapper/gradle-wrapper.properties \ android/gradlew.bat + + SOURCES -= retroshare-service.cc + SOURCES += retroshare-service-android.cc } @@ -72,6 +70,10 @@ macx { #QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 LIBS += -lz #LIBS += -lssl -lcrypto -lz -lgpgme -lgpg-error -lassuan + RC_FILE = $$files($$PWD/logo.icns) + mac_icon.files = $$files($$PWD/logo.icns) + mac_icon.path = Contents/Resources + QMAKE_BUNDLE_DATA += mac_icon for(lib, LIB_DIR):exists($$lib/libminiupnpc.a){ LIBS += $$lib/libminiupnpc.a} @@ -89,16 +91,7 @@ macx { ################################# Windows ########################################## win32-g++|win32-clang-g++ { - CONFIG(debug, debug|release) { - # show console output - CONFIG += console - } else { - CONFIG -= console - } - - # Switch on extra warnings - QMAKE_CFLAGS += -Wextra - QMAKE_CXXFLAGS += -Wextra + CONFIG += console CONFIG(debug, debug|release) { } else { diff --git a/retroshare-webui b/retroshare-webui new file mode 160000 index 000000000..edfc638a6 --- /dev/null +++ b/retroshare-webui @@ -0,0 +1 @@ +Subproject commit edfc638a6af87d0f60489632416105e1fa13fc4e diff --git a/retroshare.pri b/retroshare.pri index 2c2201ef3..98226c686 100644 --- a/retroshare.pri +++ b/retroshare.pri @@ -1,7 +1,8 @@ # RetroShare common qmake build script # -# Copyright (C) 2004-2019, Retroshare Team -# Copyright (C) 2016-2019, Gioacchino Mazzurco +# Copyright (C) 2004-2021 Retroshare Team +# Copyright (C) 2016-2021 Gioacchino Mazzurco +# Copyright (C) 2021 Asociación Civil Altermundi # # 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 @@ -50,6 +51,11 @@ retroshare_plugins:CONFIG -= no_retroshare_plugins CONFIG *= retroshare_service no_retroshare_service:CONFIG -= retroshare_service +# To disable RetroShare FriendServer append the following assignation to +# qmake command line "CONFIG+=no_retroshare_friendserver" +CONFIG *= retroshare_friendserver +no_retroshare_friendserver:CONFIG -= retroshare_friendserver + # To disable SQLCipher support append the following assignation to qmake # command line "CONFIG+=no_sqlcipher" CONFIG *= sqlcipher @@ -126,7 +132,7 @@ use_dht_stunner_ext_ip:CONFIG -= no_use_dht_stunner_ext_ip # To select your MacOsX version append the following assignation to qmake # command line "CONFIG+=rs_macos10.11" where 10.11 depends your version -macx:CONFIG *= rs_macos10.11 +macx:CONFIG *= rs_macos11.1 rs_macos10.8:CONFIG -= rs_macos10.11 rs_macos10.9:CONFIG -= rs_macos10.11 rs_macos10.10:CONFIG -= rs_macos10.11 @@ -134,16 +140,17 @@ rs_macos10.12:CONFIG -= rs_macos10.11 rs_macos10.13:CONFIG -= rs_macos10.11 rs_macos10.14:CONFIG -= rs_macos10.11 rs_macos10.15:CONFIG -= rs_macos10.11 +rs_macos11.1:CONFIG -= rs_macos10.11 # To enable JSON API append the following assignation to qmake command line # "CONFIG+=rs_jsonapi" CONFIG *= no_rs_jsonapi rs_jsonapi:CONFIG -= no_rs_jsonapi -# Disable i2p BOB support for automatically setting up an i2p tunnel for RS -# "CONFIG+=no_rs_bob" -CONFIG *= rs_bob -no_rs_bob:CONFIG -= rs_bob +# To enable forums indexing append the following assignation to qmake command +# line "CONFIG+=rs_deep_forums_index" +CONFIG *= no_rs_deep_forums_index +rs_deep_forums_index:CONFIG -= no_rs_deep_forums_index # To enable channel indexing append the following assignation to qmake command # line "CONFIG+=rs_deep_channels_index" @@ -175,6 +182,12 @@ rs_deep_files_index_taglib:CONFIG -= no_rs_deep_files_index_taglib CONFIG *= no_rs_use_native_dialogs rs_use_native_dialogs:CONFIG -= no_rs_use_native_dialogs +# By default, use RNP lib for RFC4880 PGP management. If not, compilation will +# default to openpgp-sdk, which is old and unmaintained, so probably not very secure. +CONFIG *= rs_rnplib +rs_no_rnplib:CONFIG -= rs_rnplib +rs_no_rnplib:CONFIG += rs_openpgpsdk + # To disable broadcast discovery append the following assignation to qmake # command line "CONFIG+=no_rs_broadcast_discovery" CONFIG *= rs_broadcast_discovery @@ -204,10 +217,16 @@ no_rs_service_terminal_login:CONFIG -= rs_service_terminal_login CONFIG+=rs_dh_init_check no_rs_dh_init_check:CONFIG -= rs_dh_init_check -# To export all symbols for the plugins on Windows build we need to build libretroshare as -# shared library. Fix linking error (ld.exe: Error: export ordinal too large) due to too -# many exported symbols. -retroshare_plugins:win32:CONFIG *= libretroshare_shared +# To disable I2P sam3 support append the following assignation to qmake command +# line "CONFIG+=no_rs_sam3" +CONFIG *= rs_sam3 +no_rs_sam3:CONFIG -= rs_sam3 + +# To disable I2P sam3 library submodule build append the following assignation +# to qmake command line "CONFIG+=no_rs_sam3_libsam3" +CONFIG *= rs_sam3_libsam3 +no_rs_sam3_libsam3:CONFIG -= rs_sam3_libsam3 + # Specify host precompiled jsonapi-generator path, appending the following # assignation to qmake command line @@ -267,7 +286,7 @@ isEmpty(RS_THREAD_LIB):RS_THREAD_LIB = pthread # # V07_NON_BACKWARD_COMPATIBLE_CHANGE_002: # -# What: Use RSA+SHA256 instead of RSA+SHA1 for PGP certificate signatures +# What: Use RSA+SHA256 instead of RSA+SHA1 for SSL certificates # # Why: Sha1 is likely to be prone to primary collisions anytime soon, so it is urgent to turn to a more secure solution. # @@ -277,16 +296,38 @@ isEmpty(RS_THREAD_LIB):RS_THREAD_LIB = pthread # # What: Do not hash PGP certificate twice when signing # -# Why: hasing twice is not per se a security issue, but it makes it harder to change the settings for hashing. +# Why: hasing twice is not per se a security issue, but it makes it harder to change the settings for hashing. # -# Backward compat: patched peers cannot connect to non patched peers older than Nov 2017. +# Backward compat: patched peers cannot connect to non patched peers older than Nov 2017. # # V07_NON_BACKWARD_COMPATIBLE_CHANGE_004: # # What: Do not probe that GXS tunnels accept fast items. Just assume they do. +# # Why: Avoids sending probe packets +# # BackwardCompat: old RS before Mai 2019 will not be able to distant chat. # +# V07_NON_BACKWARD_COMPATIBLE_CHANGE_005: +# +# What: Stop accepting certificates signed with sha1 algorithm +# +# Why: Sha1 has been declared insecure and shouldn't be used anymore. +# +# BackwardCompat: Retroshare profiles generated before Nov.2024 with openpgp-sdk may still use sha1 +# +########################################################################################################################################################### + +########################################################################################################################################################### +# +# V06_EXPERIMENTAL_CHANGE_001: +# +# What: removes issuer fingerprint from signature subpackets +# Why: This type of subpacket is not part of RFC4880 and not recognised by OpenPGP-SDK +# BackwardCompat: old RS before Sept.2024 will not be able to exchange keys +# Note: Since signature subpacket 33 is part of the hashed section of the signature, this also invalidates the signature. +# Depending on the implementation, certificates with self-signature that miss this subpacket may not be accepted. +# ########################################################################################################################################################### @@ -300,6 +341,7 @@ rs_v07_changes { DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_002 DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 + DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_005 DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_UNNAMED } @@ -443,13 +485,26 @@ defined in command line") RS_MINOR_VERSION = $$member(RS_GIT_DESCRIBE_SPLIT, 1) RS_GIT_DESCRIBE_SPLIT = $$member(RS_GIT_DESCRIBE_SPLIT, 2) - RS_GIT_DESCRIBE_SPLIT = $$split(RS_GIT_DESCRIBE_SPLIT, -) + RS_GIT_DESCRIBE_SPLIT = $$split(RS_GIT_DESCRIBE_SPLIT, ) - RS_MINI_VERSION = $$member(RS_GIT_DESCRIBE_SPLIT, 0) - - RS_GIT_DESCRIBE_SPLIT = $$member(RS_GIT_DESCRIBE_SPLIT, 1, -1) - - RS_EXTRA_VERSION = $$join(RS_GIT_DESCRIBE_SPLIT,-,-) + # Split string into mini version (leading numbers) and extra version (string after the numbers) + RS_MINI_VERSION = + RS_EXTRA_VERSION = + for(CHAR, RS_GIT_DESCRIBE_SPLIT) { + isEqual(CHAR, 0) | greaterThan(CHAR, 0):lessThan(CHAR, 9) | isEqual(CHAR, 9) { + # Number + isEmpty(RS_EXTRA_VERSION) { + # Add leading numbers to mini version + RS_MINI_VERSION = $${RS_MINI_VERSION}$${CHAR} + } else { + # Add to extra version + RS_EXTRA_VERSION = $${RS_EXTRA_VERSION}$${CHAR} + } + } else { + # Add to extra version + RS_EXTRA_VERSION = $${RS_EXTRA_VERSION}$${CHAR} + } + } message("RetroShare version\ $${RS_MAJOR_VERSION}.$${RS_MINOR_VERSION}.$${RS_MINI_VERSION}$${RS_EXTRA_VERSION}\ @@ -465,6 +520,18 @@ trough qmake command line arguments!") } } +# Some supportlibs compilation won't start if the intstalled CMAKE verison is >=3.5. +# Force compilation in that case +CMAKE_FORCE_MINVERSION="" +CMAKE_VERSION_SPLIT = $$system(cmake --version) +CMAKE_VERSION_SPLIT = $$split(CMAKE_VERSION_SPLIT, \\s+) +CMAKE_VERSION = $$member(CMAKE_VERSION_SPLIT, 2) +message("Cmake version detected: $${CMAKE_VERSION}") +versionAtLeast(CMAKE_VERSION, 3.5) { + warning("Forcing compilation with CMAKE_POLICY_VERSION_MINIMUM=3.5") + CMAKE_FORCE_MINVERSION="-DCMAKE_POLICY_VERSION_MINIMUM=3.5" +} + gxsdistsync:DEFINES *= RS_USE_GXS_DISTANT_SYNC wikipoos:DEFINES *= RS_USE_WIKI rs_gxs:DEFINES *= RS_ENABLE_GXS @@ -559,10 +626,7 @@ rs_webui { DEFINES *= RS_WEBUI } -rs_bob { - DEFINES *= RS_USE_I2P_BOB -} - +rs_deep_forums_index:DEFINES *= RS_DEEP_FORUMS_INDEX rs_deep_channels_index:DEFINES *= RS_DEEP_CHANNEL_INDEX rs_deep_files_index:DEFINES *= RS_DEEP_FILES_INDEX @@ -576,6 +640,13 @@ rs_broadcast_discovery:DEFINES *= RS_BROADCAST_DISCOVERY no_rs_dh_init_check:DEFINES *= RS_DISABLE_DIFFIE_HELLMAN_INIT_CHECK +rs_sam3: { + DEFINES *= RS_USE_I2P_SAM3 + # this allows a downgrade from a SAMv3 build to a BOB build, can be removed in the future + DEFINES *= RS_I2P_SAM3_BOB_COMPAT +} +rs_sam3_libsam3: DEFINES *= RS_USE_I2P_SAM3_LIBSAM3 + debug { rs_mutex_debug:DEFINES *= RS_MUTEX_DEBUG @@ -596,6 +667,18 @@ profiling { QMAKE_LFLAGS *= -pg } +# Enable all warnings +QMAKE_CFLAGS *= -Wall -Wextra +QMAKE_CXXFLAGS *= -Wall -Wextra + +# Disable unwanted warnings +QMAKE_CFLAGS *= -Wno-misleading-indentation -Wno-dangling-else +QMAKE_CXXFLAGS *= -Wno-misleading-indentation -Wno-dangling-else + +# Treat warnings as error for better removing +#QMAKE_CFLAGS += -Werror +#QMAKE_CXXFLAGS += -Werror + ################################################################################ ## Last goes platform specific statements common to all RetroShare subprojects # ################################################################################ @@ -609,6 +692,8 @@ linux-* { isEmpty(RS_PLUGIN_DIR) : RS_PLUGIN_DIR = "$${PREFIX}/lib/retroshare/extensions6" QMAKE_LIBDIR *= "$$RS_LIB_DIR" + QMAKE_LIBDIR += "$${PREFIX}/lib64" + QMAKE_LIBDIR += "$${PREFIX}/lib/x86_64-linux-gnu" rs_autologin { # try libsecret first since it is not limited to gnome keyring and libgnome-keyring is deprecated @@ -646,6 +731,14 @@ android-* { RS_THREAD_LIB = } +# To export all symbols for the plugins on Windows build we need to build +# libretroshare as shared library. Fix linking error (ld.exe: Error: export +# ordinal too large) due to too many exported symbols. +#retroshare_plugins:win32:CONFIG *= libretroshare_shared + +# Always build libretroshare on Windows as shared library to be compatible when building with and without plugins +win32:CONFIG *= libretroshare_shared + win32-g++|win32-clang-g++ { !isEmpty(EXTERNAL_LIB_DIR) { message(Use pre-compiled libraries in $${EXTERNAL_LIB_DIR}.) @@ -755,6 +848,13 @@ macx-* { QMAKE_CXXFLAGS += -Wno-nullability-completeness QMAKE_CFLAGS += -Wno-nullability-completeness } + rs_macos11.1 { + message(***retroshare.pri: Set Target and SDK to MacOS 11.1 ) + QMAKE_MACOSX_DEPLOYMENT_TARGET=11.1 + QMAKE_MAC_SDK = macosx11.1 + QMAKE_CXXFLAGS += -Wno-nullability-completeness + QMAKE_CFLAGS += -Wno-nullability-completeness + } @@ -763,6 +863,13 @@ macx-* { INCLUDEPATH += "/usr/local/include" RS_UPNP_LIB = miniupnpc QT += macextras + INCLUDEPATH += "/usr/local/opt/openssl/include" + QMAKE_LIBDIR += "/usr/local/opt/openssl/lib" + QMAKE_LIBDIR += "/usr/local/opt/sqlcipher/lib" + QMAKE_LIBDIR += "/usr/local/opt/miniupnpc/lib" + INCLUDEPATH += "/usr/local/opt/libxml2/include/libxml2" + INCLUDEPATH += "/usr/local/opt/libxslt/include" + QMAKE_LIBDIR += "/usr/local/opt/libxslt/lib" } # If not yet defined attempt UPnP library autodetection should works at least @@ -789,6 +896,19 @@ isEmpty(RS_UPNP_LIB) { } } +rs_openpgpsdk { + SUBDIRS += openpgpsdk + openpgpsdk.file = openpgpsdk/src/openpgpsdk.pro + libretroshare.depends += openpgpsdk + message("Using OpenPGP-SDK for PGP") +} + +rs_rnplib { + DEFINES += USE_RNP_LIB + message("Using RNP lib for PGP") +} + + equals(RS_UPNP_LIB, none):RS_UPNP_LIB= equals(RS_UPNP_LIB, miniupnpc):DEFINES*=RS_USE_LIBMINIUPNPC contains(RS_UPNP_LIB, upnp):DEFINES*=RS_USE_LIBUPNP @@ -798,5 +918,4 @@ contains(RS_UPNP_LIB, upnp):DEFINES*=RS_USE_LIBUPNP isEmpty(BIN_DIR) : BIN_DIR = $${RS_BIN_DIR} isEmpty(INC_DIR) : INC_DIR = $${RS_INCLUDE_DIR} isEmpty(LIBDIR) : LIBDIR = $${QMAKE_LIBDIR} -isEmpty(DATA_DIR) : DATA_DIR = $${RS_DATA_DIR} isEmpty(PLUGIN_DIR): PLUGIN_DIR= $${RS_PLUGIN_DIR} diff --git a/supportlibs/cmark b/supportlibs/cmark index b9c7a496b..3460cd809 160000 --- a/supportlibs/cmark +++ b/supportlibs/cmark @@ -1 +1 @@ -Subproject commit b9c7a496ba7dd9c3495bae2ff2855899e47b245d +Subproject commit 3460cd809b6dd311b58e92733ece2fc956224fd2 diff --git a/supportlibs/jni.hpp b/supportlibs/jni.hpp new file mode 160000 index 000000000..66f73a6aa --- /dev/null +++ b/supportlibs/jni.hpp @@ -0,0 +1 @@ +Subproject commit 66f73a6aa82367d6ba23e7e842f95dfb33c451d6 diff --git a/supportlibs/librnp b/supportlibs/librnp new file mode 160000 index 000000000..ec7811726 --- /dev/null +++ b/supportlibs/librnp @@ -0,0 +1 @@ +Subproject commit ec78117269461b2cdce15a085033a8c6bff6d7e3 diff --git a/supportlibs/libsam3 b/supportlibs/libsam3 new file mode 160000 index 000000000..f90555ba4 --- /dev/null +++ b/supportlibs/libsam3 @@ -0,0 +1 @@ +Subproject commit f90555ba4d6f9fadb6f0fbb1e2253e13557aad34 diff --git a/supportlibs/rapidjson b/supportlibs/rapidjson index f54b0e47a..24b5e7a8b 160000 --- a/supportlibs/rapidjson +++ b/supportlibs/rapidjson @@ -1 +1 @@ -Subproject commit f54b0e47a08782a6131cc3d60f94d038fa6e0a51 +Subproject commit 24b5e7a8b27f42fa16b96fc70aade9106cf7102f diff --git a/supportlibs/restbed b/supportlibs/restbed index c27c6726d..6001a3228 160000 --- a/supportlibs/restbed +++ b/supportlibs/restbed @@ -1 +1 @@ -Subproject commit c27c6726d28c42e2e1b7537ba63eeb23e944789d +Subproject commit 6001a322809b5005b8bcccdf593fdda6f0173691 diff --git a/tests/librssimulator/librssimulator.pro b/tests/librssimulator/librssimulator.pro index 1f6ded77d..75a73fdd3 100644 --- a/tests/librssimulator/librssimulator.pro +++ b/tests/librssimulator/librssimulator.pro @@ -89,7 +89,7 @@ linux-* { INCLUDEPATH *= $${OPENPGPSDK_DIR} ../openpgpsdk DESTDIR = lib - QMAKE_CXXFLAGS *= -Wall -D_FILE_OFFSET_BITS=64 + QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 QMAKE_CC = $${QMAKE_CXX} SSL_DIR = /usr/include/openssl @@ -172,10 +172,6 @@ win32 { DEFINES *= WINVER=0x0501 DESTDIR = lib - # Switch on extra warnings - QMAKE_CFLAGS += -Wextra - QMAKE_CXXFLAGS += -Wextra - # Switch off optimization for release version QMAKE_CXXFLAGS_RELEASE -= -O2 QMAKE_CXXFLAGS_RELEASE += -O0 diff --git a/tests/test_JSON_API_DirDetails_handle_correct_64bit_integer_type.sh b/tests/test_JSON_API_DirDetails_handle_correct_64bit_integer_type.sh new file mode 100755 index 000000000..03b99a94e --- /dev/null +++ b/tests/test_JSON_API_DirDetails_handle_correct_64bit_integer_type.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# Copyright (C) 2021 Gioacchino Mazzurco +# Copyright (C) 2021 Asociación Civil Altermundi +# +# 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, version 3. +# +# 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 +# +# SPDX-FileCopyrightText: Retroshare Team +# SPDX-License-Identifier: AGPL-3.0-only + + +## Define default value for variable, take two arguments, $1 variable name, +## $2 default variable value, if the variable is not already define define it +## with default value. +function define_default_value() +{ + VAR_NAME="${1}" + DEFAULT_VALUE="${2}" + + [ -z "${!VAR_NAME}" ] && export ${VAR_NAME}="${DEFAULT_VALUE}" || true +} + +define_default_value API_BASE_URL "http://127.0.0.1:9092" +define_default_value API_TOKEN "0000:0000" + +function tLog() +{ + local mCategory="$1" ; shift + echo "$mCategory $(date) $@" >&2 +} + +mCmd="curl -u $API_TOKEN $API_BASE_URL/rsFiles/requestDirDetails" + +mReply="$($mCmd)" +mCurlRet="$?" + +if [ "$mCurlRet" != 0 ]; then + tLog E "$mCmd failed: $mCurlRet '$mReply'" + exit -3 +fi + +[ "$(echo "$mReply" | jq '.retval')" == "true" ] || +{ + tLog E "/rsFiles/requestDirDetails failed: '$mReply'" + exit -1 +} + +[ "$(echo "$mReply" | jq '.details.handle')" != "0" ] || +{ + tLog E ".details.handle has wrong type int: '$mReply'" + exit -1 +} + +[ "$(echo "$mReply" | jq '.details.handle.xstr64')" == "\"0\"" ] && + [ "$(echo "$mReply" | jq '.details.handle.xint64')" == "0" ] && +{ + tLog I '.details.handle has correct type' + exit 0 +} + +tLog E "Unkown error in test $0: '$mReply'" +exit -2 diff --git a/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.cc b/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.cc index 925e90be2..442a25cc1 100644 --- a/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.cc +++ b/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.cc @@ -134,11 +134,11 @@ const RsPgpId& rs_nxs_test::RsDummyPgpUtils::getPGPOwnId() { return mOwnId; } -RsPgpId rs_nxs_test::RsDummyPgpUtils::getPGPId(const RsPeerId& /*sslid*/) { +RsPgpId rs_nxs_test::RsDummyPgpUtils::getPgpId(const RsPeerId& /*sslid*/) { return RsPgpId().random(); } -bool rs_nxs_test::RsDummyPgpUtils::getGPGAllList(std::list& /*ids*/) { +bool rs_nxs_test::RsDummyPgpUtils::getPgpAllList(std::list& /*ids*/) { return true; } diff --git a/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.h b/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.h index aee8f989e..6e993a658 100644 --- a/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.h +++ b/tests/unittests/libretroshare/gxs/nxs_test/nxsdummyservices.h @@ -164,8 +164,8 @@ namespace rs_nxs_test virtual ~RsDummyPgpUtils(){} const RsPgpId &getPGPOwnId() ; - RsPgpId getPGPId(const RsPeerId& sslid) ; - bool getGPGAllList(std::list &ids) ; + RsPgpId getPgpId(const RsPeerId& sslid) ; + bool getPgpAllList(std::list &ids) ; bool getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) const; bool parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const; diff --git a/tests/unittests/libretroshare/services/gxs/FakePgpAuxUtils.cc b/tests/unittests/libretroshare/services/gxs/FakePgpAuxUtils.cc index 2d274897a..49e440e5e 100644 --- a/tests/unittests/libretroshare/services/gxs/FakePgpAuxUtils.cc +++ b/tests/unittests/libretroshare/services/gxs/FakePgpAuxUtils.cc @@ -24,7 +24,7 @@ FakePgpAuxUtils::FakePgpAuxUtils(const RsPeerId& ownId) { - mOwnId = getPGPId(ownId); + mOwnId = getPgpId(ownId); addPeerIdToPgpList(ownId); } @@ -39,7 +39,7 @@ void FakePgpAuxUtils::addPeerListToPgpList(const std::list &ids) void FakePgpAuxUtils::addPeerIdToPgpList(const RsPeerId &id) { - RsPgpId pgpId = getPGPId(id); + RsPgpId pgpId = getPgpId(id); if (mPgpList.end() == std::find(mPgpList.begin(), mPgpList.end(), pgpId)) { mPgpList.push_back(pgpId); @@ -51,7 +51,7 @@ const RsPgpId & FakePgpAuxUtils::getPGPOwnId() return mOwnId; } -RsPgpId FakePgpAuxUtils::getPGPId(const RsPeerId& sslid) +RsPgpId FakePgpAuxUtils::getPgpId(const RsPeerId& sslid) { /* convert an sslId */ std::string idstring = sslid.toStdString(); @@ -95,7 +95,7 @@ bool FakePgpAuxUtils::VerifySignBin(const void* /*data*/, uint32_t /*len*/, unsi return true; } -bool FakePgpAuxUtils::getGPGAllList(std::list &ids) +bool FakePgpAuxUtils::getPgpAllList(std::list &ids) { ids = mPgpList; return true; diff --git a/tests/unittests/libretroshare/services/gxs/FakePgpAuxUtils.h b/tests/unittests/libretroshare/services/gxs/FakePgpAuxUtils.h index 63b20b85d..f866164a6 100644 --- a/tests/unittests/libretroshare/services/gxs/FakePgpAuxUtils.h +++ b/tests/unittests/libretroshare/services/gxs/FakePgpAuxUtils.h @@ -28,7 +28,7 @@ public: FakePgpAuxUtils(const RsPeerId& ownId); virtual const RsPgpId &getPGPOwnId(); - virtual RsPgpId getPGPId(const RsPeerId& sslid); + virtual RsPgpId getPgpId(const RsPeerId& sslid); virtual bool getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) const; virtual bool parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const; @@ -36,7 +36,7 @@ public: virtual void addPeerListToPgpList(const std::list &ids); virtual void addPeerIdToPgpList(const RsPeerId &id); - virtual bool getGPGAllList(std::list &ids); + virtual bool getPgpAllList(std::list &ids); private: RsPgpId mOwnId; std::list mPgpList;